1 /* $NetBSD: gs.c,v 1.4 2013/12/01 02:34:54 christos Exp $ */ 2 /*- 3 * Copyright (c) 2000 4 * Sven Verdoolaege. All rights reserved. 5 * 6 * See the LICENSE file for redistribution information. 7 */ 8 9 #include "config.h" 10 11 #include <sys/types.h> 12 #include <sys/queue.h> 13 14 #include <bitstring.h> 15 #include <ctype.h> 16 #include <errno.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 22 #include "../common/common.h" 23 #ifdef USE_PERL_INTERP 24 #include "perl_api_extern.h" 25 #endif 26 27 __dead static void perr __P((char *, char *)); 28 29 /* 30 * gs_init -- 31 * Create and partially initialize the GS structure. 32 * PUBLIC: GS * gs_init __P((char*)); 33 */ 34 GS * 35 gs_init(char *name) 36 { 37 GS *gp; 38 char *p; 39 40 /* Figure out what our name is. */ 41 if ((p = strrchr(name, '/')) != NULL) 42 name = p + 1; 43 44 /* Allocate the global structure. */ 45 CALLOC_NOMSG(NULL, gp, GS *, 1, sizeof(GS)); 46 if (gp == NULL) 47 perr(name, NULL); 48 49 gp->progname = name; 50 51 /* Common global structure initialization. */ 52 /* others will need to be copied from main.c */ 53 TAILQ_INIT(&gp->dq); 54 55 TAILQ_INIT(&gp->hq); 56 gp->noprint = DEFAULT_NOPRINT; 57 58 /* Structures shared by screens so stored in the GS structure. */ 59 TAILQ_INIT(&gp->frefq); 60 TAILQ_INIT(&gp->exfq); 61 LIST_INIT(&gp->seqq); 62 63 thread_init(gp); 64 65 return (gp); 66 } 67 68 /* 69 * gs_new_win 70 * Create new window 71 * PUBLIC: WIN * gs_new_win __P((GS *gp)); 72 */ 73 74 WIN * 75 gs_new_win(GS *gp) 76 { 77 WIN *wp; 78 79 CALLOC_NOMSG(NULL, wp, WIN *, 1, sizeof(*wp)); 80 if (!wp) 81 return NULL; 82 83 /* Common global structure initialization. */ 84 LIST_INIT(&wp->ecq); 85 LIST_INSERT_HEAD(&wp->ecq, &wp->excmd, q); 86 87 TAILQ_INSERT_TAIL(&gp->dq, wp, q); 88 TAILQ_INIT(&wp->scrq); 89 90 TAILQ_INIT(&wp->dcb_store.textq); 91 LIST_INIT(&wp->cutq); 92 93 wp->gp = gp; 94 95 return wp; 96 } 97 98 /* 99 * win_end -- 100 * Remove window. 101 * 102 * PUBLIC: int win_end __P((WIN *wp)); 103 */ 104 int 105 win_end(WIN *wp) 106 { 107 SCR *sp; 108 109 TAILQ_REMOVE(&wp->gp->dq, wp, q); 110 111 if (wp->ccl_sp != NULL) { 112 (void)file_end(wp->ccl_sp, NULL, 1); 113 (void)screen_end(wp->ccl_sp); 114 } 115 while ((sp = TAILQ_FIRST(&wp->scrq)) != NULL) 116 (void)screen_end(sp); 117 118 /* Free key input queue. */ 119 if (wp->i_event != NULL) 120 free(wp->i_event); 121 122 /* Free cut buffers. */ 123 cut_close(wp); 124 125 /* Free default buffer storage. */ 126 (void)text_lfree(&wp->dcb_store.textq); 127 128 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY) 129 /* Free any temporary space. */ 130 if (wp->tmp_bp != NULL) 131 free(wp->tmp_bp); 132 #endif 133 134 return 0; 135 } 136 137 /* 138 * gs_end -- 139 * End the program, discarding screens and most of the global area. 140 * 141 * PUBLIC: void gs_end __P((GS *)); 142 */ 143 void 144 gs_end(GS *gp) 145 { 146 MSGS *mp; 147 SCR *sp; 148 WIN *wp; 149 150 /* If there are any remaining screens, kill them off. */ 151 while ((wp = TAILQ_FIRST(&gp->dq)) != NULL) 152 (void)win_end(wp); 153 while ((sp = TAILQ_FIRST(&gp->hq)) != NULL) 154 (void)screen_end(sp); 155 156 #ifdef HAVE_PERL_INTERP 157 perl_end(gp); 158 #endif 159 160 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY) 161 { FREF *frp; 162 /* Free FREF's. */ 163 while ((frp = TAILQ_FIRST(&gp->frefq)) != NULL) { 164 TAILQ_REMOVE(&gp->frefq, frp, q); 165 if (frp->name != NULL) 166 free(frp->name); 167 if (frp->tname != NULL) 168 free(frp->tname); 169 free(frp); 170 } 171 } 172 173 /* Free map sequences. */ 174 seq_close(gp); 175 176 /* Close message catalogs. */ 177 msg_close(gp); 178 #endif 179 180 /* Ring the bell if scheduled. */ 181 if (F_ISSET(gp, G_BELLSCHED)) 182 (void)fprintf(stderr, "\07"); /* \a */ 183 184 /* 185 * Flush any remaining messages. If a message is here, it's almost 186 * certainly the message about the event that killed us (although 187 * it's possible that the user is sourcing a file that exits from the 188 * editor). 189 */ 190 while ((mp = LIST_FIRST(&gp->msgq)) != NULL) { 191 (void)fprintf(stderr, "%s%.*s", 192 mp->mtype == M_ERR ? "ex/vi: " : "", (int)mp->len, mp->buf); 193 LIST_REMOVE(mp, q); 194 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY) 195 free(mp->buf); 196 free(mp); 197 #endif 198 } 199 200 #if defined(TRACE) 201 /* Close tracing file descriptor. */ 202 vtrace_end(); 203 #endif 204 } 205 206 207 /* 208 * perr -- 209 * Print system error. 210 */ 211 static void 212 perr(char *name, char *msg) 213 { 214 (void)fprintf(stderr, "%s:", name); 215 if (msg != NULL) 216 (void)fprintf(stderr, "%s:", msg); 217 (void)fprintf(stderr, "%s\n", strerror(errno)); 218 exit(1); 219 } 220