xref: /minix/external/bsd/nvi/dist/ip/ip_funcs.c (revision 0a6a1f1d)
1 /*	$NetBSD: ip_funcs.c,v 1.4 2014/01/26 21:43:45 christos 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.4 2014/01/26 21:43:45 christos 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 /*
320  * ip_insertln --
321  *	Push down the current line, discarding the bottom line.
322  *
323  * PUBLIC: int ip_insertln __P((SCR *));
324  */
325 int
ip_insertln(SCR * sp)326 ip_insertln(SCR *sp)
327 {
328 	IP_BUF ipb;
329 	IP_PRIVATE *ipp = IPP(sp);
330 
331 	memset(&ipb, 0, sizeof(ipb));
332 	ipb.code = SI_INSERTLN;
333 
334 	return (vi_send(ipp->o_fd, NULL, &ipb));
335 }
336 
337 /*
338  * ip_keyval --
339  *	Return the value for a special key.
340  *
341  * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
342  */
343 int
ip_keyval(SCR * sp,scr_keyval_t val,CHAR_T * chp,int * dnep)344 ip_keyval(SCR *sp, scr_keyval_t val, CHAR_T *chp, int *dnep)
345 {
346 	/*
347 	 * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
348 	 * VWERASE is a 4BSD extension.
349 	 */
350 	switch (val) {
351 	case KEY_VEOF:
352 		*dnep = '\004';		/* ^D */
353 		break;
354 	case KEY_VERASE:
355 		*dnep = '\b';		/* ^H */
356 		break;
357 	case KEY_VKILL:
358 		*dnep = '\025';		/* ^U */
359 		break;
360 #ifdef VWERASE
361 	case KEY_VWERASE:
362 		*dnep = '\027';		/* ^W */
363 		break;
364 #endif
365 	default:
366 		*dnep = 1;
367 		break;
368 	}
369 	return (0);
370 }
371 
372 /*
373  * ip_move --
374  *	Move the cursor.
375  *
376  * PUBLIC: int ip_move __P((SCR *, size_t, size_t));
377  */
378 int
ip_move(SCR * sp,size_t lno,size_t cno)379 ip_move(SCR *sp, size_t lno, size_t cno)
380 {
381 	IP_PRIVATE *ipp;
382 	IP_BUF ipb;
383 
384 	ipp = IPP(sp);
385 	ipp->row = lno;
386 	ipp->col = cno;
387 
388 	memset(&ipb, 0, sizeof(ipb));
389 	ipb.code = SI_MOVE;
390 	ipb.val1 = RLNO(sp, lno);
391 	ipb.val2 = RCNO(sp, cno);
392 	return (vi_send(ipp->o_fd, "12", &ipb));
393 }
394 
395 /*
396  * PUBLIC: void ip_msg __P((SCR *, mtype_t, char *, size_t));
397  */
398 void
ip_msg(SCR * sp,mtype_t mtype,char * line,size_t len)399 ip_msg(SCR *sp, mtype_t mtype, char *line, size_t len)
400 {
401 	IP_PRIVATE *ipp = IPP(sp);
402 
403 	if (F_ISSET(ipp, IP_ON_ALTERNATE))
404 		vs_msg(sp, mtype, line, len);
405 	else {
406 		write(ipp->t_fd, line, len);
407 		F_CLR(sp, SC_EX_WAIT_NO);
408 	}
409 }
410 
411 /*
412  * ip_refresh --
413  *	Refresh the screen.
414  *
415  * PUBLIC: int ip_refresh __P((SCR *, int));
416  */
417 int
ip_refresh(SCR * sp,int repaint)418 ip_refresh(SCR *sp, int repaint)
419 {
420 	IP_BUF ipb;
421 	IP_PRIVATE *ipp;
422 	db_recno_t total;
423 
424 	ipp = IPP(sp);
425 
426 	/*
427 	 * If the scroll bar information has changed since we last sent
428 	 * it, resend it.  Currently, we send three values:
429 	 *
430 	 * top		The line number of the first line in the screen.
431 	 * num		The number of lines visible on the screen.
432 	 * total	The number of lines in the file.
433 	 *
434 	 * XXX
435 	 * This is a gross violation of layering... we're looking at data
436 	 * structures at which we have absolutely no business whatsoever
437 	 * looking...
438 	 */
439 	memset(&ipb, 0, sizeof(ipb));
440 	ipb.val1 = HMAP->lno;
441 	ipb.val2 = TMAP->lno - HMAP->lno;
442 	if (sp->ep != NULL && sp->ep->db != NULL)
443 		(void)db_last(sp, &total);
444 	ipb.val3 = total == 0 ? 1 : total;
445 	if (ipb.val1 != ipp->sb_top ||
446 	    ipb.val2 != ipp->sb_num || ipb.val3 != ipp->sb_total) {
447 		ipb.code = SI_SCROLLBAR;
448 		(void)vi_send(ipp->o_fd, "123", &ipb);
449 		ipp->sb_top = ipb.val1;
450 		ipp->sb_num = ipb.val2;
451 		ipp->sb_total = ipb.val3;
452 	}
453 
454 	/* Refresh/repaint the screen. */
455 	ipb.code = repaint ? SI_REDRAW : SI_REFRESH;
456 	return (vi_send(ipp->o_fd, NULL, &ipb));
457 }
458 
459 /*
460  * ip_rename --
461  *	Rename the file.
462  *
463  * PUBLIC: int ip_rename __P((SCR *, char *, int));
464  */
465 int
ip_rename(SCR * sp,char * name,int on)466 ip_rename(SCR *sp, char *name, int on)
467 {
468 	IP_BUF ipb;
469 	IP_PRIVATE *ipp = IPP(sp);
470 
471 	memset(&ipb, 0, sizeof(ipb));
472 	ipb.code = SI_RENAME;
473 	ipb.str1 = name;
474 	ipb.len1 = name ? strlen(name) : 0;
475 	return (vi_send(ipp->o_fd, "a", &ipb));
476 }
477 
478 /*
479  * ip_reply --
480  *	Reply to a message.
481  *
482  * PUBLIC: int ip_reply __P((SCR *, int, char *));
483  */
484 int
ip_reply(SCR * sp,int status,char * msg)485 ip_reply(SCR *sp, int status, char *msg)
486 {
487 	IP_BUF ipb;
488 	IP_PRIVATE *ipp = IPP(sp);
489 
490 	memset(&ipb, 0, sizeof(ipb));
491 	ipb.code = SI_REPLY;
492 	ipb.val1 = status;
493 	ipb.str1 = msg == NULL ? "" : msg;
494 	ipb.len1 = strlen(ipb.str1);
495 	return (vi_send(ipp->o_fd, "1a", &ipb));
496 }
497 
498 /*
499  * ip_split --
500  *	Split a screen.
501  *
502  * PUBLIC: int ip_split __P((SCR *, SCR *));
503  */
504 int
ip_split(SCR * origp,SCR * newp)505 ip_split(SCR *origp, SCR *newp)
506 {
507 	return (0);
508 }
509 
510 /*
511  * ip_suspend --
512  *	Suspend a screen.
513  *
514  * PUBLIC: int ip_suspend __P((SCR *, int *));
515  */
516 int
ip_suspend(SCR * sp,int * allowedp)517 ip_suspend(SCR *sp, int *allowedp)
518 {
519 	*allowedp = 0;
520 	return (0);
521 }
522 
523 /*
524  * ip_usage --
525  *      Print out the ip usage messages.
526  *
527  * PUBLIC: void ip_usage __P((void));
528  */
529 void
ip_usage(void)530 ip_usage(void)
531 {
532 #define USAGE "\
533 usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n"
534         (void)fprintf(stderr, "%s", USAGE);
535 #undef  USAGE
536 }
537