1 /*        $NetBSD: ip_funcs.c,v 1.5 2018/08/07 08:05:47 rin Exp $     */
2 /*-
3  * Copyright (c) 1996
4  *        Keith Bostic.  All rights reserved.
5  *
6  * See the LICENSE file for redistribution information.
7  */
8 
9 #include "config.h"
10 
11 #include <sys/cdefs.h>
12 #if 0
13 #ifndef lint
14 static const char sccsid[] = "Id: ip_funcs.c,v 8.23 2001/06/25 15:19:23 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:23 ";
15 #endif /* not lint */
16 #else
17 __RCSID("$NetBSD: ip_funcs.c,v 1.5 2018/08/07 08:05:47 rin Exp $");
18 #endif
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/time.h>
23 
24 #include <bitstring.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 
30 #include "../common/common.h"
31 #include "../vi/vi.h"
32 #include "../ipc/ip.h"
33 
34 /*
35  * ip_addstr --
36  *        Add len bytes from the string at the cursor, advancing the cursor.
37  *
38  * PUBLIC: int ip_waddstr __P((SCR *, const CHAR_T *, size_t));
39  */
40 int
ip_waddstr(SCR * sp,const CHAR_T * str,size_t len)41 ip_waddstr(SCR *sp, const CHAR_T *str, size_t len)
42 {
43           IP_BUF ipb;
44           IP_PRIVATE *ipp;
45           int rval;
46 
47           ipp = IPP(sp);
48 
49           memset(&ipb, 0, sizeof(ipb));
50           ipb.code = SI_WADDSTR;
51           ipb.len1 = len * sizeof(CHAR_T);
52           ipb.str1 = __UNCONST(str);
53           rval = vi_send(ipp->o_fd, "a", &ipb);
54           /* XXXX */
55           ipp->col += len;
56 
57           return (rval);
58 }
59 
60 /*
61  * ip_addstr --
62  *        Add len bytes from the string at the cursor, advancing the cursor.
63  *
64  * PUBLIC: int ip_addstr __P((SCR *, const char *, size_t));
65  */
66 int
ip_addstr(SCR * sp,const char * str,size_t len)67 ip_addstr(SCR *sp, const char *str, size_t len)
68 {
69           IP_BUF ipb;
70           IP_PRIVATE *ipp;
71           int iv, rval;
72 
73           ipp = IPP(sp);
74 
75           /*
76            * If ex isn't in control, it's the last line of the screen and
77            * it's a split screen, use inverse video.
78            */
79           memset(&ipb, 0, sizeof(ipb));
80           iv = 0;
81           if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
82               ipp->row == LASTLINE(sp) && IS_SPLIT(sp)) {
83                     iv = 1;
84                     ip_attr(sp, SA_INVERSE, 1);
85           }
86           ipb.code = SI_ADDSTR;
87           ipb.len1 = len;
88           ipb.str1 = str;
89           rval = vi_send(ipp->o_fd, "a", &ipb);
90           /* XXXX */
91           ipp->col += len;
92 
93           if (iv)
94                     ip_attr(sp, SA_INVERSE, 0);
95           return (rval);
96 }
97 
98 /*
99  * ip_attr --
100  *        Toggle a screen attribute on/off.
101  *
102  * PUBLIC: int ip_attr __P((SCR *, scr_attr_t, int));
103  */
104 int
ip_attr(SCR * sp,scr_attr_t attribute,int on)105 ip_attr(SCR *sp, scr_attr_t attribute, int on)
106 {
107           IP_BUF ipb;
108           IP_PRIVATE *ipp = IPP(sp);
109 
110           memset(&ipb, 0, sizeof(ipb));
111           if (attribute == SA_ALTERNATE) {
112                     if (on) F_SET(ipp, IP_ON_ALTERNATE);
113                     else F_CLR(ipp, IP_ON_ALTERNATE);
114           }
115 
116           ipb.code = SI_ATTRIBUTE;
117           ipb.val1 = attribute;
118           ipb.val2 = on;
119 
120           return (vi_send(ipp->o_fd, "12", &ipb));
121 }
122 
123 /*
124  * ip_baud --
125  *        Return the baud rate.
126  *
127  * PUBLIC: int ip_baud __P((SCR *, u_long *));
128  */
129 int
ip_baud(SCR * sp,u_long * ratep)130 ip_baud(SCR *sp, u_long *ratep)
131 {
132           *ratep = 9600;                /* XXX: Translation: fast. */
133           return (0);
134 }
135 
136 /*
137  * ip_bell --
138  *        Ring the bell/flash the screen.
139  *
140  * PUBLIC: int ip_bell __P((SCR *));
141  */
142 int
ip_bell(SCR * sp)143 ip_bell(SCR *sp)
144 {
145           IP_BUF ipb;
146           IP_PRIVATE *ipp = IPP(sp);
147 
148           memset(&ipb, 0, sizeof(ipb));
149           ipb.code = SI_BELL;
150 
151           return (vi_send(ipp->o_fd, NULL, &ipb));
152 }
153 
154 /*
155  * ip_busy --
156  *        Display a busy message.
157  *
158  * PUBLIC: void ip_busy __P((SCR *, const char *, busy_t));
159  */
160 void
ip_busy(SCR * sp,const char * str,busy_t bval)161 ip_busy(SCR *sp, const char *str, busy_t bval)
162 {
163           IP_BUF ipb;
164           IP_PRIVATE *ipp = IPP(sp);
165 
166           memset(&ipb, 0, sizeof(ipb));
167           switch (bval) {
168           case BUSY_ON:
169                     ipb.code = SI_BUSY_ON;
170                     ipb.str1 = str;
171                     ipb.len1 = strlen(str);
172                     (void)vi_send(ipp->o_fd, "a", &ipb);
173                     break;
174           case BUSY_OFF:
175                     ipb.code = SI_BUSY_OFF;
176                     (void)vi_send(ipp->o_fd, NULL, &ipb);
177                     break;
178           case BUSY_UPDATE:
179                     break;
180           }
181           return;
182 }
183 
184 /*
185  * ip_child --
186  *        Prepare child.
187  *
188  * PUBLIC: int ip_child __P((SCR *));
189  */
190 int
ip_child(SCR * sp)191 ip_child(SCR *sp)
192 {
193           IP_PRIVATE *ipp = IPP(sp);
194 
195           if (ipp->t_fd != -1) {
196               dup2(ipp->t_fd, 0);
197               dup2(ipp->t_fd, 1);
198               dup2(ipp->t_fd, 2);
199               close(ipp->t_fd);
200           }
201           return 0;
202 }
203 
204 /*
205  * ip_clrtoeol --
206  *        Clear from the current cursor to the end of the line.
207  *
208  * PUBLIC: int ip_clrtoeol __P((SCR *));
209  */
210 int
ip_clrtoeol(SCR * sp)211 ip_clrtoeol(SCR *sp)
212 {
213           IP_BUF ipb;
214           IP_PRIVATE *ipp = IPP(sp);
215 
216           /* Temporary hack until we can pass screen pointers
217            * or name screens
218            */
219           memset(&ipb, 0, sizeof(ipb));
220           if (IS_VSPLIT(sp)) {
221                     size_t x, y, spcnt;
222                     int error;
223 
224                     y = ipp->row;
225                     x = ipp->col;
226                     error = 0;
227                     for (spcnt = sp->cols - x;
228                          spcnt > 0 && ! error; --spcnt)
229                               error = ip_addstr(sp, " ", 1);
230                     if (sp->coff == 0)
231                               error |= ip_addstr(sp, "|", 1);
232                     error |= ip_move(sp, y, x);
233                     return error;
234           }
235 
236           ipb.code = SI_CLRTOEOL;
237 
238           return (vi_send(ipp->o_fd, NULL, &ipb));
239 }
240 
241 /*
242  * ip_cursor --
243  *        Return the current cursor position.
244  *
245  * PUBLIC: int ip_cursor __P((SCR *, size_t *, size_t *));
246  */
247 int
ip_cursor(SCR * sp,size_t * yp,size_t * xp)248 ip_cursor(SCR *sp, size_t *yp, size_t *xp)
249 {
250           IP_PRIVATE *ipp;
251 
252           ipp = IPP(sp);
253           *yp = ipp->row;
254           *xp = ipp->col;
255           return (0);
256 }
257 
258 /*
259  * ip_deleteln --
260  *        Delete the current line, scrolling all lines below it.
261  *
262  * PUBLIC: int ip_deleteln __P((SCR *));
263  */
264 int
ip_deleteln(SCR * sp)265 ip_deleteln(SCR *sp)
266 {
267           IP_BUF ipb;
268           IP_PRIVATE *ipp = IPP(sp);
269 
270           /*
271            * This clause is required because the curses screen uses reverse
272            * video to delimit split screens.  If the screen does not do this,
273            * this code won't be necessary.
274            *
275            * If the bottom line was in reverse video, rewrite it in normal
276            * video before it's scrolled.
277            */
278           memset(&ipb, 0, sizeof(ipb));
279           if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
280                     ipb.code = SI_REWRITE;
281                     ipb.val1 = RLNO(sp, LASTLINE(sp));
282                     if (vi_send(ipp->o_fd, "1", &ipb))
283                               return (1);
284           }
285 
286           /*
287            * The bottom line is expected to be blank after this operation,
288            * and other screens must support that semantic.
289            */
290           ipb.code = SI_DELETELN;
291           return (vi_send(ipp->o_fd, NULL, &ipb));
292 }
293 
294 /*
295  * ip_discard --
296  *        Discard a screen.
297  *
298  * PUBLIC: int ip_discard __P((SCR *, SCR **));
299  */
300 int
ip_discard(SCR * discardp,SCR ** acquirep)301 ip_discard(SCR *discardp, SCR **acquirep)
302 {
303           return (0);
304 }
305 
306 /*
307  * ip_ex_adjust --
308  *        Adjust the screen for ex.
309  *
310  * PUBLIC: int ip_ex_adjust __P((SCR *, exadj_t));
311  */
312 int
ip_ex_adjust(SCR * sp,exadj_t action)313 ip_ex_adjust(SCR *sp, exadj_t action)
314 {
315           abort();
316           /* NOTREACHED */
317 }
318 
319 #ifdef IMCTRL
320 /*
321  * ip_imctrl --
322  *        XXX not implemented yet.
323  *
324  * PUBLIC: #ifdef IMCTRL
325  * PUBLIC: void ip_imctrl __P((SCR *, imctrl_t));
326  * PUBLIC: #endif
327  */
328 void
ip_imctrl(SCR * sp,imctrl_t action)329 ip_imctrl(SCR *sp, imctrl_t action)
330 {
331 
332           return;
333 }
334 #endif
335 
336 /*
337  * ip_insertln --
338  *        Push down the current line, discarding the bottom line.
339  *
340  * PUBLIC: int ip_insertln __P((SCR *));
341  */
342 int
ip_insertln(SCR * sp)343 ip_insertln(SCR *sp)
344 {
345           IP_BUF ipb;
346           IP_PRIVATE *ipp = IPP(sp);
347 
348           memset(&ipb, 0, sizeof(ipb));
349           ipb.code = SI_INSERTLN;
350 
351           return (vi_send(ipp->o_fd, NULL, &ipb));
352 }
353 
354 /*
355  * ip_keyval --
356  *        Return the value for a special key.
357  *
358  * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
359  */
360 int
ip_keyval(SCR * sp,scr_keyval_t val,CHAR_T * chp,int * dnep)361 ip_keyval(SCR *sp, scr_keyval_t val, CHAR_T *chp, int *dnep)
362 {
363           /*
364            * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
365            * VWERASE is a 4BSD extension.
366            */
367           switch (val) {
368           case KEY_VEOF:
369                     *dnep = '\004';               /* ^D */
370                     break;
371           case KEY_VERASE:
372                     *dnep = '\b';                 /* ^H */
373                     break;
374           case KEY_VKILL:
375                     *dnep = '\025';               /* ^U */
376                     break;
377 #ifdef VWERASE
378           case KEY_VWERASE:
379                     *dnep = '\027';               /* ^W */
380                     break;
381 #endif
382           default:
383                     *dnep = 1;
384                     break;
385           }
386           return (0);
387 }
388 
389 /*
390  * ip_move --
391  *        Move the cursor.
392  *
393  * PUBLIC: int ip_move __P((SCR *, size_t, size_t));
394  */
395 int
ip_move(SCR * sp,size_t lno,size_t cno)396 ip_move(SCR *sp, size_t lno, size_t cno)
397 {
398           IP_PRIVATE *ipp;
399           IP_BUF ipb;
400 
401           ipp = IPP(sp);
402           ipp->row = lno;
403           ipp->col = cno;
404 
405           memset(&ipb, 0, sizeof(ipb));
406           ipb.code = SI_MOVE;
407           ipb.val1 = RLNO(sp, lno);
408           ipb.val2 = RCNO(sp, cno);
409           return (vi_send(ipp->o_fd, "12", &ipb));
410 }
411 
412 /*
413  * PUBLIC: void ip_msg __P((SCR *, mtype_t, char *, size_t));
414  */
415 void
ip_msg(SCR * sp,mtype_t mtype,char * line,size_t len)416 ip_msg(SCR *sp, mtype_t mtype, char *line, size_t len)
417 {
418           IP_PRIVATE *ipp = IPP(sp);
419 
420           if (F_ISSET(ipp, IP_ON_ALTERNATE))
421                     vs_msg(sp, mtype, line, len);
422           else {
423                     write(ipp->t_fd, line, len);
424                     F_CLR(sp, SC_EX_WAIT_NO);
425           }
426 }
427 
428 /*
429  * ip_refresh --
430  *        Refresh the screen.
431  *
432  * PUBLIC: int ip_refresh __P((SCR *, int));
433  */
434 int
ip_refresh(SCR * sp,int repaint)435 ip_refresh(SCR *sp, int repaint)
436 {
437           IP_BUF ipb;
438           IP_PRIVATE *ipp;
439           db_recno_t total;
440 
441           ipp = IPP(sp);
442 
443           /*
444            * If the scroll bar information has changed since we last sent
445            * it, resend it.  Currently, we send three values:
446            *
447            * top              The line number of the first line in the screen.
448            * num              The number of lines visible on the screen.
449            * total  The number of lines in the file.
450            *
451            * XXX
452            * This is a gross violation of layering... we're looking at data
453            * structures at which we have absolutely no business whatsoever
454            * looking...
455            */
456           memset(&ipb, 0, sizeof(ipb));
457           ipb.val1 = HMAP->lno;
458           ipb.val2 = TMAP->lno - HMAP->lno;
459           if (sp->ep != NULL && sp->ep->db != NULL)
460                     (void)db_last(sp, &total);
461           ipb.val3 = total == 0 ? 1 : total;
462           if (ipb.val1 != ipp->sb_top ||
463               ipb.val2 != ipp->sb_num || ipb.val3 != ipp->sb_total) {
464                     ipb.code = SI_SCROLLBAR;
465                     (void)vi_send(ipp->o_fd, "123", &ipb);
466                     ipp->sb_top = ipb.val1;
467                     ipp->sb_num = ipb.val2;
468                     ipp->sb_total = ipb.val3;
469           }
470 
471           /* Refresh/repaint the screen. */
472           ipb.code = repaint ? SI_REDRAW : SI_REFRESH;
473           return (vi_send(ipp->o_fd, NULL, &ipb));
474 }
475 
476 /*
477  * ip_rename --
478  *        Rename the file.
479  *
480  * PUBLIC: int ip_rename __P((SCR *, char *, int));
481  */
482 int
ip_rename(SCR * sp,char * name,int on)483 ip_rename(SCR *sp, char *name, int on)
484 {
485           IP_BUF ipb;
486           IP_PRIVATE *ipp = IPP(sp);
487 
488           memset(&ipb, 0, sizeof(ipb));
489           ipb.code = SI_RENAME;
490           ipb.str1 = name;
491           ipb.len1 = name ? strlen(name) : 0;
492           return (vi_send(ipp->o_fd, "a", &ipb));
493 }
494 
495 /*
496  * ip_reply --
497  *        Reply to a message.
498  *
499  * PUBLIC: int ip_reply __P((SCR *, int, char *));
500  */
501 int
ip_reply(SCR * sp,int status,char * msg)502 ip_reply(SCR *sp, int status, char *msg)
503 {
504           IP_BUF ipb;
505           IP_PRIVATE *ipp = IPP(sp);
506 
507           memset(&ipb, 0, sizeof(ipb));
508           ipb.code = SI_REPLY;
509           ipb.val1 = status;
510           ipb.str1 = msg == NULL ? "" : msg;
511           ipb.len1 = strlen(ipb.str1);
512           return (vi_send(ipp->o_fd, "1a", &ipb));
513 }
514 
515 /*
516  * ip_split --
517  *        Split a screen.
518  *
519  * PUBLIC: int ip_split __P((SCR *, SCR *));
520  */
521 int
ip_split(SCR * origp,SCR * newp)522 ip_split(SCR *origp, SCR *newp)
523 {
524           return (0);
525 }
526 
527 /*
528  * ip_suspend --
529  *        Suspend a screen.
530  *
531  * PUBLIC: int ip_suspend __P((SCR *, int *));
532  */
533 int
ip_suspend(SCR * sp,int * allowedp)534 ip_suspend(SCR *sp, int *allowedp)
535 {
536           *allowedp = 0;
537           return (0);
538 }
539 
540 /*
541  * ip_usage --
542  *      Print out the ip usage messages.
543  *
544  * PUBLIC: void ip_usage __P((void));
545  */
546 void
ip_usage(void)547 ip_usage(void)
548 {
549 #define USAGE "\
550 usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n"
551         (void)fprintf(stderr, "%s", USAGE);
552 #undef  USAGE
553 }
554