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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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