Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: screen.c,v 1.8 2014/01/26 21:43:45 christos Exp $	*/
      2 /*-
      3  * Copyright (c) 1993, 1994
      4  *	The Regents of the University of California.  All rights reserved.
      5  * Copyright (c) 1993, 1994, 1995, 1996
      6  *	Keith Bostic.  All rights reserved.
      7  *
      8  * See the LICENSE file for redistribution information.
      9  */
     10 
     11 #include "config.h"
     12 
     13 #include <sys/cdefs.h>
     14 #if 0
     15 #ifndef lint
     16 static const char sccsid[] = "Id: screen.c,v 10.22 2001/06/25 15:19:12 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:12 ";
     17 #endif /* not lint */
     18 #else
     19 __RCSID("$NetBSD: screen.c,v 1.8 2014/01/26 21:43:45 christos Exp $");
     20 #endif
     21 
     22 #include <sys/types.h>
     23 #include <sys/queue.h>
     24 #include <sys/time.h>
     25 
     26 #include <bitstring.h>
     27 #include <errno.h>
     28 #include <limits.h>
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <unistd.h>
     33 
     34 #include "common.h"
     35 #include "../vi/vi.h"
     36 
     37 static int screen_end1(SCR *, int);
     38 /*
     39  * screen_init --
     40  *	Do the default initialization of an SCR structure.
     41  *
     42  * PUBLIC: int screen_init __P((GS *, SCR *, SCR **));
     43  */
     44 int
     45 screen_init(GS *gp, SCR *orig, SCR **spp)
     46 {
     47 	SCR *sp;
     48 	size_t len;
     49 
     50 	*spp = NULL;
     51 	CALLOC_RET(orig, sp, SCR *, 1, sizeof(SCR));
     52 	*spp = sp;
     53 
     54 /* INITIALIZED AT SCREEN CREATE. */
     55 	sp->id = ++gp->id;
     56 	sp->refcnt = 1;
     57 
     58 	sp->gp = gp;			/* All ref the GS structure. */
     59 
     60 	sp->ccnt = 2;			/* Anything > 1 */
     61 
     62 	/*
     63 	 * XXX
     64 	 * sp->defscroll is initialized by the opts_init() code because
     65 	 * we don't have the option information yet.
     66 	 */
     67 
     68 	TAILQ_INIT(&sp->tiq);
     69 
     70 /* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
     71 	if (orig == NULL) {
     72 		sp->searchdir = NOTSET;
     73 	} else {
     74 		sp->wp = orig->wp;
     75 
     76 		/* Alternate file name. */
     77 		if (orig->alt_name != NULL &&
     78 		    (sp->alt_name = strdup(orig->alt_name)) == NULL)
     79 			goto mem;
     80 
     81 		/* Last executed at buffer. */
     82 		if (F_ISSET(orig, SC_AT_SET)) {
     83 			F_SET(sp, SC_AT_SET);
     84 			sp->at_lbuf = orig->at_lbuf;
     85 		}
     86 
     87 		/* Retain searching/substitution information. */
     88 		sp->searchdir = orig->searchdir == NOTSET ? NOTSET : FORWARD;
     89 		if (orig->re != NULL && (sp->re =
     90 		    v_wstrdup(sp, orig->re, orig->re_len)) == NULL)
     91 			goto mem;
     92 		sp->re_len = orig->re_len;
     93 		if (orig->subre != NULL && (sp->subre =
     94 		    v_wstrdup(sp, orig->subre, orig->subre_len)) == NULL)
     95 			goto mem;
     96 		sp->subre_len = orig->subre_len;
     97 		if (orig->repl != NULL && (sp->repl =
     98 		    v_wstrdup(sp, orig->repl, orig->repl_len)) == NULL)
     99 			goto mem;
    100 		sp->repl_len = orig->repl_len;
    101 		if (orig->newl_len) {
    102 			len = orig->newl_len * sizeof(size_t);
    103 			MALLOC(sp, sp->newl, size_t *, len);
    104 			if (sp->newl == NULL) {
    105 mem:				msgq(orig, M_SYSERR, NULL);
    106 				goto err;
    107 			}
    108 			sp->newl_len = orig->newl_len;
    109 			sp->newl_cnt = orig->newl_cnt;
    110 			memcpy(sp->newl, orig->newl, len);
    111 		}
    112 
    113 		if (opts_copy(orig, sp))
    114 			goto err;
    115 
    116 		F_SET(sp, F_ISSET(orig, SC_EX | SC_VI));
    117 	}
    118 
    119 	if (ex_screen_copy(orig, sp))		/* Ex. */
    120 		goto err;
    121 	if (v_screen_copy(orig, sp))		/* Vi. */
    122 		goto err;
    123 	sp->cl_private = 0;			/* XXX */
    124 	conv_init(orig, sp);			/* XXX */
    125 
    126 	*spp = sp;
    127 	return (0);
    128 
    129 err:	screen_fini(sp);
    130 	return (1);
    131 }
    132 
    133 static int
    134 screen_end1(SCR *sp, int init)
    135 {
    136 	int rval;
    137 
    138 	/* If multiply referenced, just decrement the count and return. */
    139 	if (--sp->refcnt != 0)
    140 		return (0);
    141 
    142 	/*
    143 	 * Remove the screen from the displayed queue.
    144 	 *
    145 	 * If a created screen failed during initialization, it may not
    146 	 * be linked into the chain.
    147 	 *
    148 	 * XXX screen_end can be called multiple times, abuse the tqe_prev pointer
    149 	 * to signal wether the tailq node is on-list.
    150 	 */
    151 	if (init && sp->q.tqe_prev) {
    152 		TAILQ_REMOVE(&sp->wp->scrq, sp, q);
    153 		sp->q.tqe_prev = NULL;
    154 	}
    155 
    156 	/* The screen is no longer real. */
    157 	F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
    158 
    159 	rval = 0;
    160 #ifdef HAVE_PERL_INTERP
    161 	if (perl_screen_end(sp))		/* End perl. */
    162 		rval = 1;
    163 #endif
    164 	if (v_screen_end(sp))			/* End vi. */
    165 		rval = 1;
    166 	if (ex_screen_end(sp))			/* End ex. */
    167 		rval = 1;
    168 
    169 	/* Free file names. */
    170 	{ char **ap;
    171 		if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
    172 			for (ap = sp->argv; *ap != NULL; ++ap)
    173 				free(*ap);
    174 			free(sp->argv);
    175 		}
    176 	}
    177 
    178 	/* Free any text input. */
    179 	if (!TAILQ_EMPTY(&sp->tiq))
    180 		text_lfree(&sp->tiq);
    181 
    182 	/* Free alternate file name. */
    183 	if (sp->alt_name != NULL)
    184 		free(sp->alt_name);
    185 
    186 	/* Free up search information. */
    187 	if (sp->re != NULL)
    188 		free(sp->re);
    189 	if (F_ISSET(sp, SC_RE_SEARCH))
    190 		regfree(&sp->re_c);
    191 	if (sp->subre != NULL)
    192 		free(sp->subre);
    193 	if (F_ISSET(sp, SC_RE_SUBST))
    194 		regfree(&sp->subre_c);
    195 	if (sp->repl != NULL)
    196 		free(sp->repl);
    197 	if (sp->newl != NULL)
    198 		free(sp->newl);
    199 
    200 	/* Free all the options */
    201 	opts_free(sp);
    202 
    203 	/* Free the screen itself. */
    204 	free(sp);
    205 
    206 	return (rval);
    207 }
    208 
    209 /*
    210  * screen_fini --
    211  *	Release a screen, that has not been chained to the screen queues.
    212  *
    213  * PUBLIC: int screen_fini __P((SCR *));
    214  */
    215 int
    216 screen_fini(SCR *sp)
    217 {
    218 	return screen_end1(sp, 0);
    219 }
    220 
    221 /*
    222  * screen_end --
    223  *	Release a screen, that has been chained to the screen queues.
    224  *
    225  * PUBLIC: int screen_end __P((SCR *));
    226  */
    227 int
    228 screen_end(SCR *sp)
    229 {
    230 	return screen_end1(sp, 1);
    231 }
    232 /*
    233  * screen_next --
    234  *	Return the next screen in the queue.
    235  *
    236  * PUBLIC: SCR *screen_next __P((SCR *));
    237  */
    238 SCR *
    239 screen_next(SCR *sp)
    240 {
    241 	GS *gp;
    242 	WIN *wp;
    243 	SCR *next;
    244 
    245 	/* Try the display queue, without returning the current screen. */
    246 	gp = sp->gp;
    247 	wp = sp->wp;
    248 	TAILQ_FOREACH(next, &wp->scrq, q)
    249 		if (next != sp)
    250 			break;
    251 	if (next != NULL)
    252 		return (next);
    253 
    254 	/* Try the hidden queue; if found, move screen to the display queue. */
    255 	if ((next = TAILQ_FIRST(&gp->hq)) != NULL) {
    256 		TAILQ_REMOVE(&gp->hq, next, q);
    257 		TAILQ_INSERT_HEAD(&wp->scrq, next, q);
    258 		next->wp = sp->wp;
    259 		return (next);
    260 	}
    261 	return (NULL);
    262 }
    263