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