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