Merge from vendor branch CVS:
[dragonfly.git] / contrib / nvi / ip / ip_funcs.c
1 /*-
2  * Copyright (c) 1996
3  *      Keith Bostic.  All rights reserved.
4  *
5  * See the LICENSE file for redistribution information.
6  */
7
8 #include "config.h"
9
10 #ifndef lint
11 static const char sccsid[] = "@(#)ip_funcs.c    8.4 (Berkeley) 10/13/96";
12 #endif /* not lint */
13
14 #include <sys/types.h>
15 #include <sys/queue.h>
16 #include <sys/time.h>
17
18 #include <bitstring.h>
19 #include <stdio.h>
20
21 #include "../common/common.h"
22 #include "../vi/vi.h"
23 #include "ip.h"
24
25 static int ip_send __P((SCR *, char *, IP_BUF *));
26
27 /*
28  * ip_addstr --
29  *      Add len bytes from the string at the cursor, advancing the cursor.
30  *
31  * PUBLIC: int ip_addstr __P((SCR *, const char *, size_t));
32  */
33 int
34 ip_addstr(sp, str, len)
35         SCR *sp;
36         const char *str;
37         size_t len;
38 {
39         IP_BUF ipb;
40         IP_PRIVATE *ipp;
41         int iv, rval;
42
43         ipp = IPP(sp);
44
45         /*
46          * If ex isn't in control, it's the last line of the screen and
47          * it's a split screen, use inverse video.
48          */
49         iv = 0;
50         if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
51             ipp->row == LASTLINE(sp) && IS_SPLIT(sp)) {
52                 iv = 1;
53                 ip_attr(sp, SA_INVERSE, 1);
54         }
55         ipb.code = IPO_ADDSTR;
56         ipb.len = len;
57         ipb.str = str;
58         rval = ip_send(sp, "s", &ipb);
59
60         if (iv)
61                 ip_attr(sp, SA_INVERSE, 0);
62         return (rval);
63 }
64
65 /*
66  * ip_attr --
67  *      Toggle a screen attribute on/off.
68  *
69  * PUBLIC: int ip_attr __P((SCR *, scr_attr_t, int));
70  */
71 int
72 ip_attr(sp, attribute, on)
73         SCR *sp;
74         scr_attr_t attribute;
75         int on;
76 {
77         IP_BUF ipb;
78
79         ipb.code = IPO_ATTRIBUTE;
80         ipb.val1 = attribute;
81         ipb.val2 = on;
82
83         return (ip_send(sp, "12", &ipb));
84 }
85
86 /*
87  * ip_baud --
88  *      Return the baud rate.
89  *
90  * PUBLIC: int ip_baud __P((SCR *, u_long *));
91  */
92 int
93 ip_baud(sp, ratep)
94         SCR *sp;
95         u_long *ratep;
96 {
97         *ratep = 9600;          /* XXX: Translation: fast. */
98         return (0);
99 }
100
101 /*
102  * ip_bell --
103  *      Ring the bell/flash the screen.
104  *
105  * PUBLIC: int ip_bell __P((SCR *));
106  */
107 int
108 ip_bell(sp)
109         SCR *sp;
110 {
111         IP_BUF ipb;
112
113         ipb.code = IPO_BELL;
114
115         return (ip_send(sp, NULL, &ipb));
116 }
117
118 /*
119  * ip_busy --
120  *      Display a busy message.
121  *
122  * PUBLIC: void ip_busy __P((SCR *, const char *, busy_t));
123  */
124 void
125 ip_busy(sp, str, bval)
126         SCR *sp;
127         const char *str;
128         busy_t bval;
129 {
130         IP_BUF ipb;
131
132         ipb.code = IPO_BUSY;
133         if (str == NULL) {
134                 ipb.len = 0;
135                 ipb.str = "";
136         } else {
137                 ipb.len = strlen(str);
138                 ipb.str = str;
139         }
140         ipb.val1 = bval;
141
142         (void)ip_send(sp, "s1", &ipb);
143 }
144
145 /*
146  * ip_clrtoeol --
147  *      Clear from the current cursor to the end of the line.
148  *
149  * PUBLIC: int ip_clrtoeol __P((SCR *));
150  */
151 int
152 ip_clrtoeol(sp)
153         SCR *sp;
154 {
155         IP_BUF ipb;
156
157         ipb.code = IPO_CLRTOEOL;
158
159         return (ip_send(sp, NULL, &ipb));
160 }
161
162 /*
163  * ip_cursor --
164  *      Return the current cursor position.
165  *
166  * PUBLIC: int ip_cursor __P((SCR *, size_t *, size_t *));
167  */
168 int
169 ip_cursor(sp, yp, xp)
170         SCR *sp;
171         size_t *yp, *xp;
172 {
173         IP_PRIVATE *ipp;
174
175         ipp = IPP(sp);
176         *yp = ipp->row;
177         *xp = ipp->col;
178         return (0);
179 }
180
181 /*
182  * ip_deleteln --
183  *      Delete the current line, scrolling all lines below it.
184  *
185  * PUBLIC: int ip_deleteln __P((SCR *));
186  */
187 int
188 ip_deleteln(sp)
189         SCR *sp;
190 {
191         IP_BUF ipb;
192
193         /*
194          * This clause is required because the curses screen uses reverse
195          * video to delimit split screens.  If the screen does not do this,
196          * this code won't be necessary.
197          *
198          * If the bottom line was in reverse video, rewrite it in normal
199          * video before it's scrolled.
200          */
201         if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
202                 ipb.code = IPO_REWRITE;
203                 ipb.val1 = RLNO(sp, LASTLINE(sp));
204                 if (ip_send(sp, "1", &ipb))
205                         return (1);
206         }
207
208         /*
209          * The bottom line is expected to be blank after this operation,
210          * and other screens must support that semantic.
211          */
212         ipb.code = IPO_DELETELN;
213         return (ip_send(sp, NULL, &ipb));
214 }
215
216 /* 
217  * ip_ex_adjust --
218  *      Adjust the screen for ex.
219  *
220  * PUBLIC: int ip_ex_adjust __P((SCR *, exadj_t));
221  */
222 int
223 ip_ex_adjust(sp, action)
224         SCR *sp;
225         exadj_t action;
226 {
227         abort();
228         /* NOTREACHED */
229 }
230
231 /*
232  * ip_insertln --
233  *      Push down the current line, discarding the bottom line.
234  *
235  * PUBLIC: int ip_insertln __P((SCR *));
236  */
237 int
238 ip_insertln(sp)
239         SCR *sp;
240 {
241         IP_BUF ipb;
242
243         ipb.code = IPO_INSERTLN;
244
245         return (ip_send(sp, NULL, &ipb));
246 }
247
248 /*
249  * ip_keyval --
250  *      Return the value for a special key.
251  *
252  * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
253  */
254 int
255 ip_keyval(sp, val, chp, dnep)
256         SCR *sp;
257         scr_keyval_t val;
258         CHAR_T *chp;
259         int *dnep;
260 {
261         /*
262          * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
263          * VWERASE is a 4BSD extension.
264          */
265         switch (val) {
266         case KEY_VEOF:
267                 *dnep = '\004';         /* ^D */
268                 break;
269         case KEY_VERASE:
270                 *dnep = '\b';           /* ^H */
271                 break;
272         case KEY_VKILL:
273                 *dnep = '\025';         /* ^U */
274                 break;
275 #ifdef VWERASE
276         case KEY_VWERASE:
277                 *dnep = '\027';         /* ^W */
278                 break;
279 #endif
280         default:
281                 *dnep = 1;
282                 break;
283         }
284         return (0);
285 }
286
287 /*
288  * ip_move --
289  *      Move the cursor.
290  *
291  * PUBLIC: int ip_move __P((SCR *, size_t, size_t));
292  */
293 int
294 ip_move(sp, lno, cno)
295         SCR *sp;
296         size_t lno, cno;
297 {
298         IP_PRIVATE *ipp;
299         IP_BUF ipb;
300
301         ipp = IPP(sp);
302         ipp->row = lno;
303         ipp->col = cno;
304
305         ipb.code = IPO_MOVE;
306         ipb.val1 = RLNO(sp, lno);
307         ipb.val2 = cno;
308         return (ip_send(sp, "12", &ipb));
309 }
310
311 /*
312  * ip_refresh --
313  *      Refresh the screen.
314  *
315  * PUBLIC: int ip_refresh __P((SCR *, int));
316  */
317 int
318 ip_refresh(sp, repaint)
319         SCR *sp;
320         int repaint;
321 {
322         IP_BUF ipb;
323
324         ipb.code = repaint ? IPO_REDRAW : IPO_REFRESH;
325
326         return (ip_send(sp, NULL, &ipb));
327 }
328
329 /*
330  * ip_rename --
331  *      Rename the file.
332  *
333  * PUBLIC: int ip_rename __P((SCR *));
334  */
335 int
336 ip_rename(sp)
337         SCR *sp;
338 {
339         IP_BUF ipb;
340
341         ipb.code = IPO_RENAME;
342         ipb.len = strlen(sp->frp->name);
343         ipb.str = sp->frp->name;
344
345         return (ip_send(sp, "s", &ipb));
346 }
347
348 /*
349  * ip_suspend --
350  *      Suspend a screen.
351  *
352  * PUBLIC: int ip_suspend __P((SCR *, int *));
353  */
354 int
355 ip_suspend(sp, allowedp)
356         SCR *sp;
357         int *allowedp;
358 {
359         *allowedp = 0;
360         return (0);
361 }
362
363 /*      
364  * ip_usage --
365  *      Print out the ip usage messages.
366  *
367  * PUBLIC: void ip_usage __P((void));
368  */
369 void    
370 ip_usage()
371 {       
372 #define USAGE "\
373 usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n"
374         (void)fprintf(stderr, "%s", USAGE);
375 #undef  USAGE
376 }
377
378 /*
379  * ip_send --
380  *      Construct and send an IP buffer.
381  */
382 static int
383 ip_send(sp, fmt, ipbp)
384         SCR *sp;
385         char *fmt;
386         IP_BUF *ipbp;
387 {
388         IP_PRIVATE *ipp;
389         size_t blen, off;
390         u_int32_t ilen;
391         int nlen, n, nw, rval;
392         char *bp, *p;
393         
394         ipp = IPP(sp);
395
396         GET_SPACE_RET(sp, bp, blen, 128);
397
398         p = bp;
399         nlen = 0;
400         *p++ = ipbp->code;
401         nlen += IPO_CODE_LEN;
402
403         if (fmt != NULL)
404                 for (; *fmt != '\0'; ++fmt)
405                         switch (*fmt) {
406                         case '1':                       /* Value 1. */
407                                 ilen = htonl(ipbp->val1);
408                                 goto value;
409                         case '2':                       /* Value 2. */
410                                 ilen = htonl(ipbp->val2);
411 value:                          nlen += IPO_INT_LEN;
412                                 off = p - bp;
413                                 ADD_SPACE_RET(sp, bp, blen, nlen);
414                                 p = bp + off;
415                                 memmove(p, &ilen, IPO_INT_LEN);
416                                 p += IPO_INT_LEN;
417                                 break;
418                         case 's':                       /* String. */
419                                 ilen = ipbp->len;       /* XXX: conversion. */
420                                 ilen = htonl(ilen);
421                                 nlen += IPO_INT_LEN + ipbp->len;
422                                 off = p - bp;
423                                 ADD_SPACE_RET(sp, bp, blen, nlen);
424                                 p = bp + off;
425                                 memmove(p, &ilen, IPO_INT_LEN);
426                                 p += IPO_INT_LEN;
427                                 memmove(p, ipbp->str, ipbp->len);
428                                 p += ipbp->len;
429                                 break;
430                         }
431
432
433         rval = 0;
434         for (n = p - bp, p = bp; n > 0; n -= nw, p += nw)
435                 if ((nw = write(ipp->o_fd, p, n)) < 0) {
436                         rval = 1;
437                         break;
438                 }
439
440         FREE_SPACE(sp, bp, blen);
441
442         return (rval);
443 }