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