xref: /minix/external/bsd/nvi/dist/common/gs.c (revision 84d9c625)
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