1dbd550edSchristos /*-
2dbd550edSchristos * Copyright (c) 1992, 1993, 1994
3dbd550edSchristos * The Regents of the University of California. All rights reserved.
4dbd550edSchristos * Copyright (c) 1992, 1993, 1994, 1995
5dbd550edSchristos * Keith Bostic. All rights reserved.
6dbd550edSchristos * Copyright (c) 1995
7dbd550edSchristos * George V. Neville-Neil. All rights reserved.
8dbd550edSchristos *
9dbd550edSchristos * See the LICENSE file for redistribution information.
10dbd550edSchristos */
11dbd550edSchristos
12dbd550edSchristos #include "config.h"
13dbd550edSchristos
14*2f698edbSchristos #include <sys/cdefs.h>
15*2f698edbSchristos #if 0
16dbd550edSchristos #ifndef lint
17dbd550edSchristos static const char sccsid[] = "Id: tcl.c,v 8.19 2001/08/24 12:17:27 skimo Exp (Berkeley) Date: 2001/08/24 12:17:27 ";
18dbd550edSchristos #endif /* not lint */
19*2f698edbSchristos #else
20*2f698edbSchristos __RCSID("$NetBSD: tcl.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
21*2f698edbSchristos #endif
22dbd550edSchristos
23dbd550edSchristos #include <sys/types.h>
24dbd550edSchristos #include <sys/queue.h>
25dbd550edSchristos #include <sys/time.h>
26dbd550edSchristos
27dbd550edSchristos #include <bitstring.h>
28dbd550edSchristos #include <errno.h>
29dbd550edSchristos #include <limits.h>
30dbd550edSchristos #include <signal.h>
31dbd550edSchristos #include <stdio.h>
32dbd550edSchristos #include <stdlib.h>
33dbd550edSchristos #include <string.h>
34dbd550edSchristos #include <tcl.h>
35dbd550edSchristos #include <termios.h>
36dbd550edSchristos #include <unistd.h>
37dbd550edSchristos
38dbd550edSchristos #include "../common/common.h"
398d01a27eSchristos #include "tcl_api_extern.h"
40dbd550edSchristos
41dbd550edSchristos static int getint __P((Tcl_Interp *, char *, char *, int *));
42dbd550edSchristos static int getscreenid __P((Tcl_Interp *, SCR **, char *, char *));
43dbd550edSchristos static void msghandler __P((SCR *, mtype_t, char *, size_t));
44dbd550edSchristos
45dbd550edSchristos extern GS *__global_list; /* XXX */
46dbd550edSchristos
47dbd550edSchristos /*
48dbd550edSchristos * INITMESSAGE --
49dbd550edSchristos * Macros to point messages at the Tcl message handler.
50dbd550edSchristos */
51dbd550edSchristos #define INITMESSAGE(sp) \
52dbd550edSchristos scr_msg = sp->wp->scr_msg; \
53dbd550edSchristos sp->wp->scr_msg = msghandler;
54dbd550edSchristos #define ENDMESSAGE(sp) \
55dbd550edSchristos sp->wp->scr_msg = scr_msg;
56dbd550edSchristos
57dbd550edSchristos /*
58dbd550edSchristos * tcl_fscreen --
59dbd550edSchristos * Return the screen id associated with file name.
60dbd550edSchristos *
61dbd550edSchristos * Tcl Command: viFindScreen
62dbd550edSchristos * Usage: viFindScreen file
63dbd550edSchristos */
64dbd550edSchristos static int
tcl_fscreen(clientData,interp,argc,argv)65dbd550edSchristos tcl_fscreen(clientData, interp, argc, argv)
66dbd550edSchristos ClientData clientData;
67dbd550edSchristos Tcl_Interp *interp;
68dbd550edSchristos int argc;
69dbd550edSchristos char **argv;
70dbd550edSchristos {
71dbd550edSchristos SCR *sp;
72dbd550edSchristos
73dbd550edSchristos if (argc != 2) {
74dbd550edSchristos Tcl_SetResult(interp, "Usage: viFindScreen file", TCL_STATIC);
75dbd550edSchristos return (TCL_ERROR);
76dbd550edSchristos }
77dbd550edSchristos
78dbd550edSchristos if (getscreenid(interp, &sp, NULL, argv[1]))
79dbd550edSchristos return (TCL_ERROR);
80dbd550edSchristos
81dbd550edSchristos (void)sprintf(interp->result, "%d", sp->id);
82dbd550edSchristos return (TCL_OK);
83dbd550edSchristos }
84dbd550edSchristos
85dbd550edSchristos /*
86dbd550edSchristos * tcl_aline --
87dbd550edSchristos * -- Append the string text after the line in lineNumber.
88dbd550edSchristos *
89dbd550edSchristos * Tcl Command: viAppendLine
90dbd550edSchristos * Usage: viAppendLine screenId lineNumber text
91dbd550edSchristos */
92dbd550edSchristos static int
tcl_aline(clientData,interp,argc,argv)93dbd550edSchristos tcl_aline(clientData, interp, argc, argv)
94dbd550edSchristos ClientData clientData;
95dbd550edSchristos Tcl_Interp *interp;
96dbd550edSchristos int argc;
97dbd550edSchristos char **argv;
98dbd550edSchristos {
99dbd550edSchristos SCR *sp;
100dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
101dbd550edSchristos int lno, rval;
102dbd550edSchristos
103dbd550edSchristos if (argc != 4) {
104dbd550edSchristos Tcl_SetResult(interp,
105dbd550edSchristos "Usage: viAppendLine screenId lineNumber text", TCL_STATIC);
106dbd550edSchristos return (TCL_ERROR);
107dbd550edSchristos }
108dbd550edSchristos
109dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL) ||
110dbd550edSchristos getint(interp, "line number", argv[2], &lno))
111dbd550edSchristos return (TCL_ERROR);
112dbd550edSchristos INITMESSAGE(sp);
113dbd550edSchristos rval = api_aline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
114dbd550edSchristos ENDMESSAGE(sp);
115dbd550edSchristos
116dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
117dbd550edSchristos }
118dbd550edSchristos
119dbd550edSchristos /*
120dbd550edSchristos * tcl_dline --
121dbd550edSchristos * Delete lineNum.
122dbd550edSchristos *
123dbd550edSchristos * Tcl Command: viDelLine
124dbd550edSchristos * Usage: viDelLine screenId lineNum
125dbd550edSchristos */
126dbd550edSchristos static int
tcl_dline(clientData,interp,argc,argv)127dbd550edSchristos tcl_dline(clientData, interp, argc, argv)
128dbd550edSchristos ClientData clientData;
129dbd550edSchristos Tcl_Interp *interp;
130dbd550edSchristos int argc;
131dbd550edSchristos char **argv;
132dbd550edSchristos {
133dbd550edSchristos SCR *sp;
134dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
135dbd550edSchristos int lno, rval;
136dbd550edSchristos
137dbd550edSchristos if (argc != 3) {
138dbd550edSchristos Tcl_SetResult(interp,
139dbd550edSchristos "Usage: viDelLine screenId lineNumber", TCL_STATIC);
140dbd550edSchristos return (TCL_ERROR);
141dbd550edSchristos }
142dbd550edSchristos
143dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL) ||
144dbd550edSchristos getint(interp, "line number", argv[2], &lno))
145dbd550edSchristos return (TCL_ERROR);
146dbd550edSchristos INITMESSAGE(sp);
147dbd550edSchristos rval = api_dline(sp, (db_recno_t)lno);
148dbd550edSchristos ENDMESSAGE(sp);
149dbd550edSchristos
150dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
151dbd550edSchristos }
152dbd550edSchristos
153dbd550edSchristos /*
154dbd550edSchristos * tcl_gline --
155dbd550edSchristos * Return lineNumber.
156dbd550edSchristos *
157dbd550edSchristos * Tcl Command: viGetLine
158dbd550edSchristos * Usage: viGetLine screenId lineNumber
159dbd550edSchristos */
160dbd550edSchristos static int
tcl_gline(clientData,interp,argc,argv)161dbd550edSchristos tcl_gline(clientData, interp, argc, argv)
162dbd550edSchristos ClientData clientData;
163dbd550edSchristos Tcl_Interp *interp;
164dbd550edSchristos int argc;
165dbd550edSchristos char **argv;
166dbd550edSchristos {
167dbd550edSchristos SCR *sp;
168dbd550edSchristos size_t len;
169dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
170dbd550edSchristos int lno, rval;
171dbd550edSchristos char *line, *p;
172dbd550edSchristos
173dbd550edSchristos if (argc != 3) {
174dbd550edSchristos Tcl_SetResult(interp,
175dbd550edSchristos "Usage: viGetLine screenId lineNumber", TCL_STATIC);
176dbd550edSchristos return (TCL_ERROR);
177dbd550edSchristos }
178dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL) ||
179dbd550edSchristos getint(interp, "line number", argv[2], &lno))
180dbd550edSchristos return (TCL_ERROR);
181dbd550edSchristos INITMESSAGE(sp);
182dbd550edSchristos rval = api_gline(sp, (db_recno_t)lno, &p, &len);
183dbd550edSchristos ENDMESSAGE(sp);
184dbd550edSchristos
185dbd550edSchristos if (rval)
186dbd550edSchristos return (TCL_ERROR);
187dbd550edSchristos
188dbd550edSchristos if ((line = malloc(len + 1)) == NULL)
189dbd550edSchristos exit(1); /* XXX */
190dbd550edSchristos memmove(line, p, len);
191dbd550edSchristos line[len] = '\0';
192dbd550edSchristos Tcl_SetResult(interp, line, TCL_DYNAMIC);
193dbd550edSchristos return (TCL_OK);
194dbd550edSchristos }
195dbd550edSchristos
196dbd550edSchristos /*
197dbd550edSchristos * tcl_iline --
198dbd550edSchristos * Insert the string text after the line in lineNumber.
199dbd550edSchristos *
200dbd550edSchristos * Tcl Command: viInsertLine
201dbd550edSchristos * Usage: viInsertLine screenId lineNumber text
202dbd550edSchristos */
203dbd550edSchristos static int
tcl_iline(clientData,interp,argc,argv)204dbd550edSchristos tcl_iline(clientData, interp, argc, argv)
205dbd550edSchristos ClientData clientData;
206dbd550edSchristos Tcl_Interp *interp;
207dbd550edSchristos int argc;
208dbd550edSchristos char **argv;
209dbd550edSchristos {
210dbd550edSchristos SCR *sp;
211dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
212dbd550edSchristos int lno, rval;
213dbd550edSchristos
214dbd550edSchristos if (argc != 4) {
215dbd550edSchristos Tcl_SetResult(interp,
216dbd550edSchristos "Usage: viInsertLine screenId lineNumber text", TCL_STATIC);
217dbd550edSchristos return (TCL_ERROR);
218dbd550edSchristos }
219dbd550edSchristos
220dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL) ||
221dbd550edSchristos getint(interp, "line number", argv[2], &lno))
222dbd550edSchristos return (TCL_ERROR);
223dbd550edSchristos INITMESSAGE(sp);
224dbd550edSchristos rval = api_iline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
225dbd550edSchristos ENDMESSAGE(sp);
226dbd550edSchristos
227dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
228dbd550edSchristos }
229dbd550edSchristos
230dbd550edSchristos /*
231dbd550edSchristos * tcl_lline --
232dbd550edSchristos * Return the last line in the screen.
233dbd550edSchristos *
234dbd550edSchristos * Tcl Command: viLastLine
235dbd550edSchristos * Usage: viLastLine screenId
236dbd550edSchristos */
237dbd550edSchristos static int
tcl_lline(clientData,interp,argc,argv)238dbd550edSchristos tcl_lline(clientData, interp, argc, argv)
239dbd550edSchristos ClientData clientData;
240dbd550edSchristos Tcl_Interp *interp;
241dbd550edSchristos int argc;
242dbd550edSchristos char **argv;
243dbd550edSchristos {
244dbd550edSchristos SCR *sp;
245dbd550edSchristos db_recno_t last;
246dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
247dbd550edSchristos int rval;
248dbd550edSchristos
249dbd550edSchristos if (argc != 2) {
250dbd550edSchristos Tcl_SetResult(interp, "Usage: viLastLine screenId", TCL_STATIC);
251dbd550edSchristos return (TCL_ERROR);
252dbd550edSchristos }
253dbd550edSchristos
254dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
255dbd550edSchristos return (TCL_ERROR);
256dbd550edSchristos INITMESSAGE(sp);
257dbd550edSchristos rval = api_lline(sp, &last);
258dbd550edSchristos ENDMESSAGE(sp);
259dbd550edSchristos if (rval)
260dbd550edSchristos return (TCL_ERROR);
261dbd550edSchristos
262dbd550edSchristos (void)sprintf(interp->result, "%lu", (unsigned long)last);
263dbd550edSchristos return (TCL_OK);
264dbd550edSchristos }
265dbd550edSchristos
266dbd550edSchristos /*
267dbd550edSchristos * tcl_sline --
268dbd550edSchristos * Set lineNumber to the text supplied.
269dbd550edSchristos *
270dbd550edSchristos * Tcl Command: viSetLine
271dbd550edSchristos * Usage: viSetLine screenId lineNumber text
272dbd550edSchristos */
273dbd550edSchristos static int
tcl_sline(clientData,interp,argc,argv)274dbd550edSchristos tcl_sline(clientData, interp, argc, argv)
275dbd550edSchristos ClientData clientData;
276dbd550edSchristos Tcl_Interp *interp;
277dbd550edSchristos int argc;
278dbd550edSchristos char **argv;
279dbd550edSchristos {
280dbd550edSchristos SCR *sp;
281dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
282dbd550edSchristos int lno, rval;
283dbd550edSchristos
284dbd550edSchristos if (argc != 4) {
285dbd550edSchristos Tcl_SetResult(interp,
286dbd550edSchristos "Usage: viSetLine screenId lineNumber text", TCL_STATIC);
287dbd550edSchristos return (TCL_ERROR);
288dbd550edSchristos }
289dbd550edSchristos
290dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL) ||
291dbd550edSchristos getint(interp, "line number", argv[2], &lno))
292dbd550edSchristos return (TCL_ERROR);
293dbd550edSchristos INITMESSAGE(sp);
294dbd550edSchristos rval = api_sline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
295dbd550edSchristos ENDMESSAGE(sp);
296dbd550edSchristos
297dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
298dbd550edSchristos }
299dbd550edSchristos
300dbd550edSchristos /*
301dbd550edSchristos * tcl_getmark --
302dbd550edSchristos * Return the mark's cursor position as a list with two elements.
303dbd550edSchristos * {line, column}.
304dbd550edSchristos *
305dbd550edSchristos * Tcl Command: viGetMark
306dbd550edSchristos * Usage: viGetMark screenId mark
307dbd550edSchristos */
308dbd550edSchristos static int
tcl_getmark(clientData,interp,argc,argv)309dbd550edSchristos tcl_getmark(clientData, interp, argc, argv)
310dbd550edSchristos ClientData clientData;
311dbd550edSchristos Tcl_Interp *interp;
312dbd550edSchristos int argc;
313dbd550edSchristos char **argv;
314dbd550edSchristos {
315dbd550edSchristos MARK cursor;
316dbd550edSchristos SCR *sp;
317dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
318dbd550edSchristos int rval;
319dbd550edSchristos char buf[20];
320dbd550edSchristos
321dbd550edSchristos if (argc != 3) {
322dbd550edSchristos Tcl_SetResult(interp,
323dbd550edSchristos "Usage: viGetMark screenId mark", TCL_STATIC);
324dbd550edSchristos return (TCL_ERROR);
325dbd550edSchristos }
326dbd550edSchristos
327dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
328dbd550edSchristos return (TCL_ERROR);
329dbd550edSchristos INITMESSAGE(sp);
330dbd550edSchristos rval = api_getmark(sp, (int)argv[2][0], &cursor);
331dbd550edSchristos ENDMESSAGE(sp);
332dbd550edSchristos
333dbd550edSchristos if (rval)
334dbd550edSchristos return (TCL_ERROR);
335dbd550edSchristos
336dbd550edSchristos (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno);
337dbd550edSchristos Tcl_AppendElement(interp, buf);
338dbd550edSchristos (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno);
339dbd550edSchristos Tcl_AppendElement(interp, buf);
340dbd550edSchristos return (TCL_OK);
341dbd550edSchristos }
342dbd550edSchristos
343dbd550edSchristos /*
344dbd550edSchristos * tcl_setmark --
345dbd550edSchristos * Set the mark to the line and column numbers supplied.
346dbd550edSchristos *
347dbd550edSchristos * Tcl Command: viSetMark
348dbd550edSchristos * Usage: viSetMark screenId mark line column
349dbd550edSchristos */
350dbd550edSchristos static int
tcl_setmark(clientData,interp,argc,argv)351dbd550edSchristos tcl_setmark(clientData, interp, argc, argv)
352dbd550edSchristos ClientData clientData;
353dbd550edSchristos Tcl_Interp *interp;
354dbd550edSchristos int argc;
355dbd550edSchristos char **argv;
356dbd550edSchristos {
357dbd550edSchristos MARK cursor;
358dbd550edSchristos SCR *sp;
359dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
360dbd550edSchristos int i, rval;
361dbd550edSchristos
362dbd550edSchristos if (argc != 5) {
363dbd550edSchristos Tcl_SetResult(interp,
364dbd550edSchristos "Usage: viSetMark screenId mark line column", TCL_STATIC);
365dbd550edSchristos return (TCL_ERROR);
366dbd550edSchristos }
367dbd550edSchristos
368dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
369dbd550edSchristos return (TCL_ERROR);
370dbd550edSchristos if (getint(interp, "line number", argv[3], &i))
371dbd550edSchristos return (TCL_ERROR);
372dbd550edSchristos cursor.lno = i;
373dbd550edSchristos if (getint(interp, "column number", argv[4], &i))
374dbd550edSchristos return (TCL_ERROR);
375dbd550edSchristos cursor.cno = i;
376dbd550edSchristos INITMESSAGE(sp);
377dbd550edSchristos rval = api_setmark(sp, (int)argv[2][0], &cursor);
378dbd550edSchristos ENDMESSAGE(sp);
379dbd550edSchristos
380dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
381dbd550edSchristos }
382dbd550edSchristos
383dbd550edSchristos /*
384dbd550edSchristos * tcl_getcursor --
385dbd550edSchristos * Return the current cursor position as a list with two elements.
386dbd550edSchristos * {line, column}.
387dbd550edSchristos *
388dbd550edSchristos * Tcl Command: viGetCursor
389dbd550edSchristos * Usage: viGetCursor screenId
390dbd550edSchristos */
391dbd550edSchristos static int
tcl_getcursor(clientData,interp,argc,argv)392dbd550edSchristos tcl_getcursor(clientData, interp, argc, argv)
393dbd550edSchristos ClientData clientData;
394dbd550edSchristos Tcl_Interp *interp;
395dbd550edSchristos int argc;
396dbd550edSchristos char **argv;
397dbd550edSchristos {
398dbd550edSchristos MARK cursor;
399dbd550edSchristos SCR *sp;
400dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
401dbd550edSchristos int rval;
402dbd550edSchristos char buf[20];
403dbd550edSchristos
404dbd550edSchristos if (argc != 2) {
405dbd550edSchristos Tcl_SetResult(interp,
406dbd550edSchristos "Usage: viGetCursor screenId", TCL_STATIC);
407dbd550edSchristos return (TCL_ERROR);
408dbd550edSchristos }
409dbd550edSchristos
410dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
411dbd550edSchristos return (TCL_ERROR);
412dbd550edSchristos INITMESSAGE(sp);
413dbd550edSchristos rval = api_getcursor(sp, &cursor);
414dbd550edSchristos ENDMESSAGE(sp);
415dbd550edSchristos
416dbd550edSchristos if (rval)
417dbd550edSchristos return (TCL_ERROR);
418dbd550edSchristos
419dbd550edSchristos (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno);
420dbd550edSchristos Tcl_AppendElement(interp, buf);
421dbd550edSchristos (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno);
422dbd550edSchristos Tcl_AppendElement(interp, buf);
423dbd550edSchristos return (TCL_OK);
424dbd550edSchristos }
425dbd550edSchristos
426dbd550edSchristos /*
427dbd550edSchristos * tcl_setcursor --
428dbd550edSchristos * Set the cursor to the line and column numbers supplied.
429dbd550edSchristos *
430dbd550edSchristos * Tcl Command: viSetCursor
431dbd550edSchristos * Usage: viSetCursor screenId line column
432dbd550edSchristos */
433dbd550edSchristos static int
tcl_setcursor(clientData,interp,argc,argv)434dbd550edSchristos tcl_setcursor(clientData, interp, argc, argv)
435dbd550edSchristos ClientData clientData;
436dbd550edSchristos Tcl_Interp *interp;
437dbd550edSchristos int argc;
438dbd550edSchristos char **argv;
439dbd550edSchristos {
440dbd550edSchristos MARK cursor;
441dbd550edSchristos SCR *sp;
442dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
443dbd550edSchristos int i, rval;
444dbd550edSchristos
445dbd550edSchristos if (argc != 4) {
446dbd550edSchristos Tcl_SetResult(interp,
447dbd550edSchristos "Usage: viSetCursor screenId line column", TCL_STATIC);
448dbd550edSchristos return (TCL_ERROR);
449dbd550edSchristos }
450dbd550edSchristos
451dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
452dbd550edSchristos return (TCL_ERROR);
453dbd550edSchristos if (getint(interp, "screen id", argv[2], &i))
454dbd550edSchristos return (TCL_ERROR);
455dbd550edSchristos cursor.lno = i;
456dbd550edSchristos if (getint(interp, "screen id", argv[3], &i))
457dbd550edSchristos return (TCL_ERROR);
458dbd550edSchristos cursor.cno = i;
459dbd550edSchristos INITMESSAGE(sp);
460dbd550edSchristos rval = api_setcursor(sp, &cursor);
461dbd550edSchristos ENDMESSAGE(sp);
462dbd550edSchristos
463dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
464dbd550edSchristos }
465dbd550edSchristos
466dbd550edSchristos /*
467dbd550edSchristos * tcl_msg --
468dbd550edSchristos * Set the message line to text.
469dbd550edSchristos *
470dbd550edSchristos * Tcl Command: viMsg
471dbd550edSchristos * Usage: viMsg screenId text
472dbd550edSchristos */
473dbd550edSchristos static int
tcl_msg(clientData,interp,argc,argv)474dbd550edSchristos tcl_msg(clientData, interp, argc, argv)
475dbd550edSchristos ClientData clientData;
476dbd550edSchristos Tcl_Interp *interp;
477dbd550edSchristos int argc;
478dbd550edSchristos char **argv;
479dbd550edSchristos {
480dbd550edSchristos SCR *sp;
481dbd550edSchristos
482dbd550edSchristos if (argc != 3) {
483dbd550edSchristos Tcl_SetResult(interp, "Usage: viMsg screenId text", TCL_STATIC);
484dbd550edSchristos return (TCL_ERROR);
485dbd550edSchristos }
486dbd550edSchristos
487dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
488dbd550edSchristos return (TCL_ERROR);
489dbd550edSchristos api_imessage(sp, argv[2]);
490dbd550edSchristos
491dbd550edSchristos return (TCL_OK);
492dbd550edSchristos }
493dbd550edSchristos
494dbd550edSchristos /*
495dbd550edSchristos * tcl_iscreen --
496dbd550edSchristos * Create a new screen. If a filename is specified then the screen
497dbd550edSchristos * is opened with that file.
498dbd550edSchristos *
499dbd550edSchristos * Tcl Command: viNewScreen
500dbd550edSchristos * Usage: viNewScreen screenId [file]
501dbd550edSchristos */
502dbd550edSchristos static int
tcl_iscreen(clientData,interp,argc,argv)503dbd550edSchristos tcl_iscreen(clientData, interp, argc, argv)
504dbd550edSchristos ClientData clientData;
505dbd550edSchristos Tcl_Interp *interp;
506dbd550edSchristos int argc;
507dbd550edSchristos char **argv;
508dbd550edSchristos {
509dbd550edSchristos SCR *sp, *nsp;
510dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
511dbd550edSchristos int rval;
512dbd550edSchristos
513dbd550edSchristos if (argc != 2 && argc != 3) {
514dbd550edSchristos Tcl_SetResult(interp,
515dbd550edSchristos "Usage: viNewScreen screenId [file]", TCL_STATIC);
516dbd550edSchristos return (TCL_ERROR);
517dbd550edSchristos }
518dbd550edSchristos
519dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
520dbd550edSchristos return (TCL_ERROR);
521dbd550edSchristos INITMESSAGE(sp);
522dbd550edSchristos rval = api_edit(sp, argv[2], &nsp, 1);
523dbd550edSchristos ENDMESSAGE(sp);
524dbd550edSchristos
525dbd550edSchristos if (rval)
526dbd550edSchristos return (TCL_ERROR);
527dbd550edSchristos
528dbd550edSchristos (void)sprintf(interp->result, "%d", nsp->id);
529dbd550edSchristos return (TCL_OK);
530dbd550edSchristos }
531dbd550edSchristos
532dbd550edSchristos /*
533dbd550edSchristos * tcl_escreen --
534dbd550edSchristos * End a screen.
535dbd550edSchristos *
536dbd550edSchristos * Tcl Command: viEndScreen
537dbd550edSchristos * Usage: viEndScreen screenId
538dbd550edSchristos */
539dbd550edSchristos static int
tcl_escreen(clientData,interp,argc,argv)540dbd550edSchristos tcl_escreen(clientData, interp, argc, argv)
541dbd550edSchristos ClientData clientData;
542dbd550edSchristos Tcl_Interp *interp;
543dbd550edSchristos int argc;
544dbd550edSchristos char **argv;
545dbd550edSchristos {
546dbd550edSchristos SCR *sp;
547dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
548dbd550edSchristos int rval;
549dbd550edSchristos
550dbd550edSchristos if (argc != 2) {
551dbd550edSchristos Tcl_SetResult(interp,
552dbd550edSchristos "Usage: viEndScreen screenId", TCL_STATIC);
553dbd550edSchristos return (TCL_ERROR);
554dbd550edSchristos }
555dbd550edSchristos
556dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
557dbd550edSchristos return (TCL_ERROR);
558dbd550edSchristos INITMESSAGE(sp);
559dbd550edSchristos rval = api_escreen(sp);
560dbd550edSchristos ENDMESSAGE(sp);
561dbd550edSchristos
562dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
563dbd550edSchristos }
564dbd550edSchristos
565dbd550edSchristos /*
566dbd550edSchristos * tcl_swscreen --
567dbd550edSchristos * Change the current focus to screen.
568dbd550edSchristos *
569dbd550edSchristos * Tcl Command: viSwitchScreen
570dbd550edSchristos * Usage: viSwitchScreen screenId screenId
571dbd550edSchristos */
572dbd550edSchristos static int
tcl_swscreen(clientData,interp,argc,argv)573dbd550edSchristos tcl_swscreen(clientData, interp, argc, argv)
574dbd550edSchristos ClientData clientData;
575dbd550edSchristos Tcl_Interp *interp;
576dbd550edSchristos int argc;
577dbd550edSchristos char **argv;
578dbd550edSchristos {
579dbd550edSchristos SCR *sp, *new;
580dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
581dbd550edSchristos int rval;
582dbd550edSchristos
583dbd550edSchristos if (argc != 3) {
584dbd550edSchristos Tcl_SetResult(interp,
585dbd550edSchristos "Usage: viSwitchScreen cur_screenId new_screenId",
586dbd550edSchristos TCL_STATIC);
587dbd550edSchristos return (TCL_ERROR);
588dbd550edSchristos }
589dbd550edSchristos
590dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
591dbd550edSchristos return (TCL_ERROR);
592dbd550edSchristos if (getscreenid(interp, &new, argv[2], NULL))
593dbd550edSchristos return (TCL_ERROR);
594dbd550edSchristos INITMESSAGE(sp);
595dbd550edSchristos rval = api_swscreen(sp, new);
596dbd550edSchristos ENDMESSAGE(sp);
597dbd550edSchristos
598dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
599dbd550edSchristos }
600dbd550edSchristos
601dbd550edSchristos /*
602dbd550edSchristos * tcl_map --
603dbd550edSchristos * Associate a key with a tcl procedure.
604dbd550edSchristos *
605dbd550edSchristos * Tcl Command: viMapKey
606dbd550edSchristos * Usage: viMapKey screenId key tclproc
607dbd550edSchristos */
608dbd550edSchristos static int
tcl_map(clientData,interp,argc,argv)609dbd550edSchristos tcl_map(clientData, interp, argc, argv)
610dbd550edSchristos ClientData clientData;
611dbd550edSchristos Tcl_Interp *interp;
612dbd550edSchristos int argc;
613dbd550edSchristos char **argv;
614dbd550edSchristos {
615dbd550edSchristos SCR *sp;
616dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
617dbd550edSchristos int rval;
618dbd550edSchristos char command[256];
619dbd550edSchristos
620dbd550edSchristos if (argc != 4) {
621dbd550edSchristos Tcl_SetResult(interp,
622dbd550edSchristos "Usage: viMapKey screenId key tclproc", TCL_STATIC);
623dbd550edSchristos return (TCL_ERROR);
624dbd550edSchristos }
625dbd550edSchristos
626dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
627dbd550edSchristos return (TCL_ERROR);
628dbd550edSchristos INITMESSAGE(sp);
629dbd550edSchristos (void)snprintf(command, sizeof(command), ":tcl %s\n", argv[3]);
630dbd550edSchristos rval = api_map(sp, argv[2], command, strlen(command));
631dbd550edSchristos ENDMESSAGE(sp);
632dbd550edSchristos
633dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
634dbd550edSchristos }
635dbd550edSchristos
636dbd550edSchristos /*
637dbd550edSchristos * tcl_unmap --
638dbd550edSchristos * Unmap a key.
639dbd550edSchristos *
640dbd550edSchristos * Tcl Command: viUnmapKey
641dbd550edSchristos * Usage: viUnmMapKey screenId key
642dbd550edSchristos */
643dbd550edSchristos static int
tcl_unmap(clientData,interp,argc,argv)644dbd550edSchristos tcl_unmap(clientData, interp, argc, argv)
645dbd550edSchristos ClientData clientData;
646dbd550edSchristos Tcl_Interp *interp;
647dbd550edSchristos int argc;
648dbd550edSchristos char **argv;
649dbd550edSchristos {
650dbd550edSchristos SCR *sp;
651dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
652dbd550edSchristos int rval;
653dbd550edSchristos
654dbd550edSchristos if (argc != 3) {
655dbd550edSchristos Tcl_SetResult(interp,
656dbd550edSchristos "Usage: viUnmapKey screenId key", TCL_STATIC);
657dbd550edSchristos return (TCL_ERROR);
658dbd550edSchristos }
659dbd550edSchristos
660dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
661dbd550edSchristos return (TCL_ERROR);
662dbd550edSchristos INITMESSAGE(sp);
663dbd550edSchristos rval = api_unmap(sp, argv[2]);
664dbd550edSchristos ENDMESSAGE(sp);
665dbd550edSchristos
666dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
667dbd550edSchristos }
668dbd550edSchristos
669dbd550edSchristos /*
670dbd550edSchristos * tcl_opts_set --
671dbd550edSchristos * Set an option.
672dbd550edSchristos *
673dbd550edSchristos * Tcl Command: viSetOpt
674dbd550edSchristos * Usage: viSetOpt screenId command
675dbd550edSchristos */
676dbd550edSchristos static int
tcl_opts_set(clientData,interp,argc,argv)677dbd550edSchristos tcl_opts_set(clientData, interp, argc, argv)
678dbd550edSchristos ClientData clientData;
679dbd550edSchristos Tcl_Interp *interp;
680dbd550edSchristos int argc;
681dbd550edSchristos char **argv;
682dbd550edSchristos {
683dbd550edSchristos SCR *sp;
684dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
685dbd550edSchristos int rval;
686dbd550edSchristos char *setting;
687dbd550edSchristos
688dbd550edSchristos if (argc != 3) {
689dbd550edSchristos Tcl_SetResult(interp,
690dbd550edSchristos "Usage: viSetOpt screenId command", TCL_STATIC);
691dbd550edSchristos return (TCL_ERROR);
692dbd550edSchristos }
693dbd550edSchristos
694dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
695dbd550edSchristos return (TCL_ERROR);
696dbd550edSchristos INITMESSAGE(sp);
697dbd550edSchristos /*rval = api_opts_set(sp, argv[2]);*/
698dbd550edSchristos MALLOC(sp, setting, char *, strlen(argv[2])+6);
699dbd550edSchristos strcpy(setting, ":set ");
700dbd550edSchristos strcpy(setting+5, argv[2]);
701dbd550edSchristos rval=api_run_str(sp, setting);
702dbd550edSchristos free(setting);
703dbd550edSchristos ENDMESSAGE(sp);
704dbd550edSchristos
705dbd550edSchristos return (rval ? TCL_ERROR : TCL_OK);
706dbd550edSchristos }
707dbd550edSchristos
708dbd550edSchristos /*
709dbd550edSchristos * tcl_opts_get --
710dbd550edSchristos Return the value of an option.
711dbd550edSchristos *
712dbd550edSchristos * Tcl Command: viGetOpt
713dbd550edSchristos * Usage: viGetOpt screenId option
714dbd550edSchristos */
715dbd550edSchristos static int
tcl_opts_get(clientData,interp,argc,argv)716dbd550edSchristos tcl_opts_get(clientData, interp, argc, argv)
717dbd550edSchristos ClientData clientData;
718dbd550edSchristos Tcl_Interp *interp;
719dbd550edSchristos int argc;
720dbd550edSchristos char **argv;
721dbd550edSchristos {
722dbd550edSchristos SCR *sp;
723dbd550edSchristos void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
724dbd550edSchristos int rval;
725dbd550edSchristos char *value;
726dbd550edSchristos
727dbd550edSchristos if (argc != 3) {
728dbd550edSchristos Tcl_SetResult(interp,
729dbd550edSchristos "Usage: viGetOpt screenId option", TCL_STATIC);
730dbd550edSchristos return (TCL_ERROR);
731dbd550edSchristos }
732dbd550edSchristos
733dbd550edSchristos if (getscreenid(interp, &sp, argv[1], NULL))
734dbd550edSchristos return (TCL_ERROR);
735dbd550edSchristos INITMESSAGE(sp);
736dbd550edSchristos rval = api_opts_get(sp, argv[2], &value, NULL);
737dbd550edSchristos ENDMESSAGE(sp);
738dbd550edSchristos if (rval)
739dbd550edSchristos return (TCL_ERROR);
740dbd550edSchristos
741dbd550edSchristos Tcl_SetResult(interp, value, TCL_DYNAMIC);
742dbd550edSchristos return (TCL_OK);
743dbd550edSchristos }
744dbd550edSchristos
745dbd550edSchristos /*
746dbd550edSchristos * tcl_init --
747dbd550edSchristos * Create the TCL commands used by nvi.
748dbd550edSchristos *
749dbd550edSchristos * PUBLIC: int tcl_init __P((GS *));
750dbd550edSchristos */
751dbd550edSchristos int
tcl_init(gp)752dbd550edSchristos tcl_init(gp)
753dbd550edSchristos GS *gp;
754dbd550edSchristos {
755dbd550edSchristos gp->tcl_interp = Tcl_CreateInterp();
756dbd550edSchristos if (Tcl_Init(gp->tcl_interp) == TCL_ERROR)
757dbd550edSchristos return (1);
758dbd550edSchristos
759dbd550edSchristos #define TCC(name, function) { \
760dbd550edSchristos Tcl_CreateCommand(gp->tcl_interp, name, function, \
761dbd550edSchristos (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); \
762dbd550edSchristos }
763dbd550edSchristos TCC("viAppendLine", tcl_aline);
764dbd550edSchristos TCC("viDelLine", tcl_dline);
765dbd550edSchristos TCC("viEndScreen", tcl_escreen);
766dbd550edSchristos TCC("viFindScreen", tcl_fscreen);
767dbd550edSchristos TCC("viGetCursor", tcl_getcursor);
768dbd550edSchristos TCC("viGetLine", tcl_gline);
769dbd550edSchristos TCC("viGetMark", tcl_getmark);
770dbd550edSchristos TCC("viGetOpt", tcl_opts_get);
771dbd550edSchristos TCC("viInsertLine", tcl_iline);
772dbd550edSchristos TCC("viLastLine", tcl_lline);
773dbd550edSchristos TCC("viMapKey", tcl_map);
774dbd550edSchristos TCC("viMsg", tcl_msg);
775dbd550edSchristos TCC("viNewScreen", tcl_iscreen);
776dbd550edSchristos TCC("viSetCursor", tcl_setcursor);
777dbd550edSchristos TCC("viSetLine", tcl_sline);
778dbd550edSchristos TCC("viSetMark", tcl_setmark);
779dbd550edSchristos TCC("viSetOpt", tcl_opts_set);
780dbd550edSchristos TCC("viSwitchScreen", tcl_swscreen);
781dbd550edSchristos TCC("viUnmapKey", tcl_unmap);
782dbd550edSchristos
783dbd550edSchristos return (0);
784dbd550edSchristos }
785dbd550edSchristos
786dbd550edSchristos /*
787dbd550edSchristos * getscreenid --
788dbd550edSchristos * Get the specified screen pointer.
789dbd550edSchristos *
790dbd550edSchristos * XXX
791dbd550edSchristos * This is fatal. We can't post a message into vi that we're unable to find
792dbd550edSchristos * the screen without first finding the screen... So, this must be the first
793dbd550edSchristos * thing a Tcl routine does, and, if it fails, the last as well.
794dbd550edSchristos */
795dbd550edSchristos static int
getscreenid(interp,spp,id,name)796dbd550edSchristos getscreenid(interp, spp, id, name)
797dbd550edSchristos Tcl_Interp *interp;
798dbd550edSchristos SCR **spp;
799dbd550edSchristos char *id, *name;
800dbd550edSchristos {
801dbd550edSchristos int scr_no;
802dbd550edSchristos char buf[64];
803dbd550edSchristos
804dbd550edSchristos if (id != NULL && getint(interp, "screen id", id, &scr_no))
805dbd550edSchristos return (1);
806dbd550edSchristos if ((*spp = api_fscreen(scr_no, name)) == NULL) {
807dbd550edSchristos (void)snprintf(buf, sizeof(buf),
808dbd550edSchristos "unknown screen id: %s", name == NULL ? id : name);
809dbd550edSchristos Tcl_SetResult(interp, buf, TCL_VOLATILE);
810dbd550edSchristos return (1);
811dbd550edSchristos }
812dbd550edSchristos return (0);
813dbd550edSchristos }
814dbd550edSchristos
815dbd550edSchristos /*
816dbd550edSchristos * getint --
817dbd550edSchristos * Get a Tcl integer.
818dbd550edSchristos *
819dbd550edSchristos * XXX
820dbd550edSchristos * This code assumes that both db_recno_t and size_t are larger than ints.
821dbd550edSchristos */
822dbd550edSchristos static int
getint(interp,msg,s,intp)823dbd550edSchristos getint(interp, msg, s, intp)
824dbd550edSchristos Tcl_Interp *interp;
825dbd550edSchristos char *msg, *s;
826dbd550edSchristos int *intp;
827dbd550edSchristos {
828dbd550edSchristos char buf[64];
829dbd550edSchristos
830dbd550edSchristos if (Tcl_GetInt(interp, s, intp) == TCL_ERROR)
831dbd550edSchristos return (1);
832dbd550edSchristos if (*intp < 0) {
833dbd550edSchristos (void)snprintf(buf, sizeof(buf),
834dbd550edSchristos "illegal %s %s: may not be negative", msg, s);
835dbd550edSchristos Tcl_SetResult(interp, buf, TCL_VOLATILE);
836dbd550edSchristos return (1);
837dbd550edSchristos }
838dbd550edSchristos return (0);
839dbd550edSchristos }
840dbd550edSchristos
841dbd550edSchristos /*
842dbd550edSchristos * msghandler --
843dbd550edSchristos * Tcl message routine so that error messages are processed in
844dbd550edSchristos * Tcl, not in nvi.
845dbd550edSchristos */
846dbd550edSchristos static void
msghandler(sp,mtype,msg,len)847dbd550edSchristos msghandler(sp, mtype, msg, len)
848dbd550edSchristos SCR *sp;
849dbd550edSchristos mtype_t mtype;
850dbd550edSchristos char *msg;
851dbd550edSchristos size_t len;
852dbd550edSchristos {
853dbd550edSchristos /* Replace the trailing <newline> with an EOS. */
854dbd550edSchristos msg[len - 1] = '\0';
855dbd550edSchristos
856dbd550edSchristos Tcl_SetResult(sp->gp->tcl_interp, msg, TCL_VOLATILE);
857dbd550edSchristos }
858