Merge from vendor branch NTPD:
[dragonfly.git] / contrib / nvi / tk / tk_util.c
1 /*-
2  * Copyright (c) 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1993, 1994, 1995, 1996
5  *      Keith Bostic.  All rights reserved.
6  *
7  * See the LICENSE file for redistribution information.
8  */
9
10 #include "config.h"
11
12 #ifndef lint
13 static const char sccsid[] = "@(#)tk_util.c     8.14 (Berkeley) 7/19/96";
14 #endif /* not lint */
15
16 #include <sys/types.h>
17 #include <sys/queue.h>
18
19 #include <bitstring.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <termios.h>
27 #include <unistd.h>
28
29 #include "../common/common.h"
30 #include "tki.h"
31
32 static int tk_op_push __P((SCR *, TK_PRIVATE *, e_event_t));
33
34 /*
35  * tk_op --
36  *      Events provided directly from Tcl/Tk.
37  *
38  * PUBLIC: int tk_op __P((ClientData, Tcl_Interp *, int, char *[]));
39  */
40 int
41 tk_op(clientData, interp, argc, argv)
42         ClientData clientData;
43         Tcl_Interp *interp;
44         int argc;
45         char *argv[];
46 {
47         SCR *sp;
48         TK_PRIVATE *tkp;
49
50         sp = __global_list->dq.cqh_first;               /* XXX */
51         tkp = (TK_PRIVATE *)clientData;
52
53         switch (argv[1][0]) {
54         case 'q':
55                 if (!strcmp(argv[1], "quit"))
56                         return (tk_op_push(sp, tkp, E_QUIT));
57                 break;
58         case 'w':
59                 if (!strcmp(argv[1], "write"))
60                         return (tk_op_push(sp, tkp, E_WRITE));
61                 if (!strcmp(argv[1], "writequit")) {
62                         if (tk_op_push(sp, tkp, E_WRITE) != TCL_OK)
63                                 return (TCL_ERROR);
64                         if (tk_op_push(sp, tkp, E_QUIT) != TCL_OK)
65                                 return (TCL_ERROR);
66                         return (TCL_OK);
67                 }
68                 break;
69         }
70         (void)Tcl_VarEval(tkp->interp,
71             "tk_err {", argv[1], ": unknown event", "}", NULL);
72         return (TCL_OK);
73 }
74
75 /*
76  * tk_op_push --
77  *      Push an event.
78  */
79 static int
80 tk_op_push(sp, tkp, et)
81         SCR *sp;
82         TK_PRIVATE *tkp;
83         e_event_t et;
84 {
85         EVENT *evp;
86
87         CALLOC(sp, evp, EVENT *, 1, sizeof(EVENT));
88         if (evp == NULL)
89                 return (TCL_ERROR);
90
91         evp->e_event = et;
92         TAILQ_INSERT_TAIL(&tkp->evq, evp, q);
93         return (TCL_OK);
94 }
95
96 /*
97  * tk_opt_init --
98  *      Initialize the values of the current options.
99  *
100  * PUBLIC: int tk_opt_init __P((ClientData, Tcl_Interp *, int, char *[]));
101  */
102 int
103 tk_opt_init(clientData, interp, argc, argv)
104         ClientData clientData;
105         Tcl_Interp *interp;
106         int argc;
107         char *argv[];
108 {
109         OPTLIST const *op;
110         SCR *sp;
111         TK_PRIVATE *tkp;
112         int off;
113         char buf[20];
114
115         sp = __global_list->dq.cqh_first;               /* XXX */
116
117         tkp = (TK_PRIVATE *)clientData;
118         for (op = optlist, off = 0; op->name != NULL; ++op, ++off) {
119                 if (F_ISSET(op, OPT_NDISP))
120                         continue;
121                 switch (op->type) {
122                 case OPT_0BOOL:
123                 case OPT_1BOOL:
124                         (void)Tcl_VarEval(tkp->interp, "set tko_",
125                             op->name, O_ISSET(sp, off) ? " 1" : " 0", NULL);
126                         break;
127                 case OPT_NUM:
128                         (void)snprintf(buf,
129                             sizeof(buf), " %lu", O_VAL(sp, off));
130                         (void)Tcl_VarEval(tkp->interp,
131                             "set tko_", op->name, buf, NULL);
132                         break;
133                 case OPT_STR:
134                         (void)Tcl_VarEval(tkp->interp,
135                             "set tko_", op->name, " {",
136                             O_STR(sp, off) == NULL ? "" : O_STR(sp, off),
137                             "}", NULL);
138                         break;
139                 }
140         }
141         return (TCL_OK);
142 }
143
144 /*
145  * tk_opt_set --
146  *      Set an options button.
147  *
148  * PUBLIC: int tk_opt_set __P((ClientData, Tcl_Interp *, int, char *[]));
149  */
150 int
151 tk_opt_set(clientData, interp, argc, argv)
152         ClientData clientData;
153         Tcl_Interp *interp;
154         int argc;
155         char *argv[];
156 {
157         ARGS *ap[2], a, b;
158         GS *gp;
159         SCR *sp;
160         int rval;
161         void (*msg) __P((SCR *, mtype_t, char *, size_t));
162         char buf[64];
163
164         gp = __global_list;
165         sp = gp->dq.cqh_first;                          /* XXX */
166
167         switch (argc) {
168         case 2:
169                 a.bp = argv[1] + (sizeof("tko_") - 1);
170                 a.len = strlen(a.bp);
171                 break;
172         case 3:
173                 a.bp = buf;
174                 a.len = snprintf(buf, sizeof(buf),
175                     "%s%s", atoi(argv[2]) ? "no" : "", argv[1]);
176                 break;
177         default:
178                 abort();
179         }
180         b.bp = NULL;
181         b.len = 0;
182         ap[0] = &a;
183         ap[1] = &b;
184
185         /* Use Tcl/Tk for error messages. */
186         msg = gp->scr_msg;
187         gp->scr_msg = tk_msg;
188
189         rval = opts_set(sp, ap, NULL);
190
191         gp->scr_msg = msg;
192         return (rval ? TCL_ERROR : TCL_OK);
193 }
194
195 /*
196  * tk_version --
197  *      Display the version in Tcl/Tk.
198  *
199  * PUBLIC: int tk_version __P((ClientData, Tcl_Interp *, int, char *[]));
200  */
201 int
202 tk_version(clientData, interp, argc, argv)
203         ClientData clientData;
204         Tcl_Interp *interp;
205         int argc;
206         char *argv[];
207 {
208         EXCMD cmd;
209         GS *gp;
210         SCR *sp;
211         int rval;
212         void (*msg) __P((SCR *, mtype_t, char *, size_t));
213
214         gp = __global_list;
215         sp = gp->dq.cqh_first;                          /* XXX */
216
217         msg = gp->scr_msg;
218         gp->scr_msg = tk_msg;
219
220         ex_cinit(&cmd, C_VERSION, 0, OOBLNO, OOBLNO, 0, NULL);
221         rval = cmd.cmd->fn(sp, &cmd);
222         (void)ex_fflush(sp);
223
224         gp->scr_msg = msg;
225         return (rval ? TCL_ERROR : TCL_OK);
226 }
227
228 /*
229  * tk_msg --
230  *      Display an error message in Tcl/Tk.
231  *
232  * PUBLIC: void tk_msg __P((SCR *, mtype_t, char *, size_t));
233  */
234 void
235 tk_msg(sp, mtype, line, rlen)
236         SCR *sp;
237         mtype_t mtype;
238         char *line;
239         size_t rlen;
240 {
241         TK_PRIVATE *tkp;
242         char buf[2048];
243
244         if (line == NULL)
245                 return;
246
247         tkp = TKP(sp);
248         (void)snprintf(buf, sizeof(buf), "%.*s", (int)rlen, line);
249         (void)Tcl_VarEval(tkp->interp, "tk_err {", buf, "}", NULL);
250 }