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 *
gs_init(char * name)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 *
gs_new_win(GS * gp)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
win_end(WIN * wp)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
gs_end(GS * gp)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
perr(char * name,char * msg)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