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