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