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