adapt KEY_VAL to wchar and fix apparent thinko
[nvi.git] / ip / ip_main.c
blob94cc5d7edc1ef91c1eb774a9aeefbe49fab846c5
1 /*-
2 * Copyright (c) 1996
3 * Keith Bostic. All rights reserved.
5 * See the LICENSE file for redistribution information.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char sccsid[] = "$Id: ip_main.c,v 8.22 2000/07/14 14:29:22 skimo Exp $ (Berkeley) $Date: 2000/07/14 14:29:22 $";
12 #endif /* not lint */
14 #include <sys/types.h>
15 #include <sys/queue.h>
17 #include <bitstring.h>
18 #include <ctype.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
25 #include <sys/uio.h>
27 #include "../common/common.h"
28 #include "../ipc/ip.h"
29 #include "extern.h"
31 GS *__global_list; /* GLOBAL: List of screens. */
33 static void ip_func_std __P((GS *));
34 static IP_PRIVATE *ip_init __P((WIN *wp, int i_fd, int o_fd, int, int argc, char *argv[]));
35 static void perr __P((char *, char *));
36 static int get_fds __P((char *ip_arg, int *i_fd, int *o_fd));
37 static int get_connection __P((WIN *wp, int main_ifd, int main_ofd,
38 int *i_fd, int *o_fd, int *, int can_pass));
39 static void *run_editor __P((void * vp));
42 * ip_main --
43 * This is the main loop for the vi-as-library editor.
45 int
46 main(argc, argv)
47 int argc;
48 char *argv[];
50 IP_PRIVATE *ipp;
51 int rval;
52 char *ip_arg;
53 char **p_av, **t_av;
54 GS *gp;
55 WIN *wp;
56 int i_fd, o_fd, t_fd, main_ifd, main_ofd;
58 /* Create and initialize the global structure. */
59 __global_list = gp = gs_init(argv[0]);
62 * Strip out any arguments that vi isn't going to understand. There's
63 * no way to portably call getopt twice, so arguments parsed here must
64 * be removed from the argument list.
66 ip_arg = NULL;
67 for (p_av = t_av = argv;;) {
68 if (*t_av == NULL) {
69 *p_av = NULL;
70 break;
72 if (!strcmp(*t_av, "--")) {
73 while ((*p_av++ = *t_av++) != NULL);
74 break;
76 if (!memcmp(*t_av, "-I", sizeof("-I") - 1)) {
77 if (t_av[0][2] != '\0') {
78 ip_arg = t_av[0] + 2;
79 ++t_av;
80 --argc;
81 continue;
83 else if (t_av[1] != NULL) {
84 ip_arg = t_av[1];
85 t_av += 2;
86 argc -= 2;
87 continue;
90 *p_av++ = *t_av++;
93 if (get_fds(ip_arg, &main_ifd, &main_ofd))
94 return 1;
96 wp = NULL;
98 while (get_connection(wp, main_ifd, main_ofd, &i_fd, &o_fd, &t_fd, 1) == 0) {
99 /* Create new window */
100 wp = gs_new_win(gp);
102 /* Create and partially initialize the IP structure. */
103 if ((ipp = ip_init(wp, i_fd, o_fd, t_fd, argc, argv)) == NULL)
104 return (1);
106 gp->run(wp, run_editor, (void *)wp);
109 /* Clean out the global structure. */
110 gs_end(gp);
112 /* Free the global and IP private areas. */
113 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
114 free(gp);
115 #endif
116 exit (rval);
119 static void *
120 run_editor(void * vp)
122 GS *gp;
123 IP_PRIVATE *ipp;
124 WIN *wp;
125 EVENT ev;
126 int rval;
127 IP_BUF ipb;
129 wp = (WIN *) vp;
130 gp = wp->gp;
131 ipp = wp->ip_private;
133 /* Add the terminal type to the global structure. */
134 if ((OG_D_STR(gp, GO_TERM) =
135 OG_STR(gp, GO_TERM) = strdup("ip_curses")) == NULL)
136 perr(gp->progname, NULL);
139 * Figure out how big the screen is -- read events until we get
140 * the rows and columns.
142 for (;;) {
143 if (ip_wevent(wp, NULL, &ev, 0, 0))
144 return;
145 if (ev.e_event == E_WRESIZE)
146 break;
147 if (ev.e_event == E_EOF || ev.e_event == E_ERR ||
148 ev.e_event == E_SIGHUP || ev.e_event == E_SIGTERM)
149 return;
150 if (ev.e_event == E_IPCOMMAND && ev.e_ipcom == VI_QUIT)
151 return;
154 /* Run ex/vi. */
155 rval = editor(wp, ipp->argc, ipp->argv);
157 /* Clean up the screen. */
158 (void)ip_quit(wp);
160 /* Send the quit message. */
161 ipb.code = SI_QUIT;
162 (void)vi_send(ipp->o_fd, NULL, &ipb);
164 /* Give the screen a couple of seconds to deal with it. */
165 sleep(2);
167 /* Remove window; correct place ? */
168 win_end(wp);
170 #if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
171 free(ipp);
172 #endif
173 return NULL;
177 * ip_init --
178 * Create and partially initialize the GS structure.
180 static IP_PRIVATE *
181 ip_init(WIN *wp, int i_fd, int o_fd, int t_fd, int argc, char *argv[])
183 IP_PRIVATE *ipp;
185 /* Allocate the IP private structure. */
186 CALLOC_NOMSG(NULL, ipp, IP_PRIVATE *, 1, sizeof(IP_PRIVATE));
187 if (ipp == NULL)
188 perr(wp->gp->progname, NULL);
189 wp->ip_private = ipp;
191 ipp->i_fd = i_fd;
192 ipp->o_fd = o_fd;
193 ipp->t_fd = t_fd;
195 ipp->argc = argc;
196 ipp->argv = argv;
198 /* Initialize the list of ip functions. */
199 ip_func_std(wp->gp);
201 return (ipp);
204 static int
205 get_fds(char *ip_arg, int *i_fd, int *o_fd)
207 char *ep;
210 * Crack ip_arg -- it's of the form #.#, where the first number is the
211 * file descriptor from the screen, the second is the file descriptor
212 * to the screen.
214 if (!ip_arg || !isdigit(ip_arg[0]))
215 goto usage;
216 *i_fd = strtol(ip_arg, &ep, 10);
217 if (ep[0] != '.' || !isdigit(ep[1]))
218 goto usage;
219 *o_fd = strtol(++ep, &ep, 10);
220 if (ep[0] != '\0') {
221 usage: ip_usage();
222 return 1;
225 return 0;
228 static int
229 get_connection(WIN *wp, int main_ifd, int main_ofd,
230 int *i_fd, int *o_fd, int *t_fd, int can_pass)
232 *t_fd = -1;
234 if (!can_pass) {
235 if (wp == NULL) { /* First call */
236 *i_fd = main_ifd;
237 *o_fd = main_ofd;
238 } else {
239 return 1;
241 } else {
242 struct msghdr mh;
243 IPCMSGHDR ch;
244 char dummy;
245 struct iovec iov;
247 mh.msg_namelen = 0;
248 mh.msg_iovlen = 1;
249 mh.msg_iov = &iov;
250 mh.msg_controllen = sizeof(ch);
251 mh.msg_control = (void *)&ch;
253 iov.iov_len = 1;
254 iov.iov_base = &dummy;
256 if (recvmsg(main_ifd, &mh, 0) != 1)
257 return 1;
258 *i_fd = *(int *)CMSG_DATA(&ch.header);
259 if (recvmsg(*i_fd, &mh, 0) != 1)
260 return 1;
261 *o_fd = *(int *)CMSG_DATA(&ch.header);
262 if (dummy == 'F') {
263 if (recvmsg(*i_fd, &mh, 0) != 1)
264 return 1;
265 *t_fd = *(int *)CMSG_DATA(&ch.header);
269 return 0;
273 * ip_func_std --
274 * Initialize the standard ip functions.
276 static void
277 ip_func_std(gp)
278 GS *gp;
280 gp->scr_addstr = ip_addstr;
281 gp->scr_waddstr = ip_waddstr;
282 gp->scr_attr = ip_attr;
283 gp->scr_baud = ip_baud;
284 gp->scr_bell = ip_bell;
285 gp->scr_busy = ip_busy;
286 gp->scr_child = ip_child;
287 gp->scr_clrtoeol = ip_clrtoeol;
288 gp->scr_cursor = ip_cursor;
289 gp->scr_deleteln = ip_deleteln;
290 gp->scr_discard = ip_discard;
291 gp->scr_event = ip_event;
292 gp->scr_ex_adjust = ip_ex_adjust;
293 gp->scr_fmap = ip_fmap;
294 gp->scr_insertln = ip_insertln;
295 gp->scr_keyval = ip_keyval;
296 gp->scr_move = ip_move;
297 gp->scr_msg = ip_msg;
298 gp->scr_optchange = ip_optchange;
299 gp->scr_refresh = ip_refresh;
300 gp->scr_rename = ip_rename;
301 gp->scr_reply = ip_reply;
302 gp->scr_screen = ip_screen;
303 gp->scr_split = ip_split;
304 gp->scr_suspend = ip_suspend;
305 gp->scr_usage = ip_usage;
309 * perr --
310 * Print system error.
312 static void
313 perr(name, msg)
314 char *name, *msg;
316 (void)fprintf(stderr, "%s:", name);
317 if (msg != NULL)
318 (void)fprintf(stderr, "%s:", msg);
319 (void)fprintf(stderr, "%s\n", strerror(errno));
320 exit(1);