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