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 11static const char sccsid[] = "@(#)ip_funcs.c 8.4 (Berkeley) 10/13/96"; 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 21#include "../common/common.h" 22#include "../vi/vi.h" 23#include "ip.h" 24 25static int ip_send __P((SCR *, char *, IP_BUF *)); 26 27/* 28 * ip_addstr -- 29 * Add len bytes from the string at the cursor, advancing the cursor. 30 * 31 * PUBLIC: int ip_addstr __P((SCR *, const char *, size_t)); 32 */ 33int 34ip_addstr(sp, str, len) 35 SCR *sp; 36 const char *str; 37 size_t len; 38{ 39 IP_BUF ipb; 40 IP_PRIVATE *ipp; 41 int iv, rval; 42 43 ipp = IPP(sp); 44 45 /* 46 * If ex isn't in control, it's the last line of the screen and 47 * it's a split screen, use inverse video. 48 */ 49 iv = 0; 50 if (!F_ISSET(sp, SC_SCR_EXWROTE) && 51 ipp->row == LASTLINE(sp) && IS_SPLIT(sp)) { 52 iv = 1; 53 ip_attr(sp, SA_INVERSE, 1); 54 } 55 ipb.code = IPO_ADDSTR; 56 ipb.len = len; 57 ipb.str = str; 58 rval = ip_send(sp, "s", &ipb); 59 60 if (iv) 61 ip_attr(sp, SA_INVERSE, 0); 62 return (rval); 63} 64 65/* 66 * ip_attr -- 67 * Toggle a screen attribute on/off. 68 * 69 * PUBLIC: int ip_attr __P((SCR *, scr_attr_t, int)); 70 */ 71int 72ip_attr(sp, attribute, on) 73 SCR *sp; 74 scr_attr_t attribute; 75 int on; 76{ 77 IP_BUF ipb; 78 79 ipb.code = IPO_ATTRIBUTE; 80 ipb.val1 = attribute; 81 ipb.val2 = on; 82 83 return (ip_send(sp, "12", &ipb)); 84} 85 86/* 87 * ip_baud -- 88 * Return the baud rate. 89 * 90 * PUBLIC: int ip_baud __P((SCR *, u_long *)); 91 */ 92int 93ip_baud(sp, ratep) 94 SCR *sp; 95 u_long *ratep; 96{ 97 *ratep = 9600; /* XXX: Translation: fast. */ 98 return (0); 99} 100 101/* 102 * ip_bell -- 103 * Ring the bell/flash the screen. 104 * 105 * PUBLIC: int ip_bell __P((SCR *)); 106 */ 107int 108ip_bell(sp) 109 SCR *sp; 110{ 111 IP_BUF ipb; 112 113 ipb.code = IPO_BELL; 114 115 return (ip_send(sp, NULL, &ipb)); 116} 117 118/* 119 * ip_busy -- 120 * Display a busy message. 121 * 122 * PUBLIC: void ip_busy __P((SCR *, const char *, busy_t)); 123 */ 124void 125ip_busy(sp, str, bval) 126 SCR *sp; 127 const char *str; 128 busy_t bval; 129{ 130 IP_BUF ipb; 131 132 ipb.code = IPO_BUSY; 133 if (str == NULL) { 134 ipb.len = 0; 135 ipb.str = ""; 136 } else { 137 ipb.len = strlen(str); 138 ipb.str = str; 139 } 140 ipb.val1 = bval; 141 142 (void)ip_send(sp, "s1", &ipb); 143} 144 145/* 146 * ip_clrtoeol -- 147 * Clear from the current cursor to the end of the line. 148 * 149 * PUBLIC: int ip_clrtoeol __P((SCR *)); 150 */ 151int 152ip_clrtoeol(sp) 153 SCR *sp; 154{ 155 IP_BUF ipb; 156 157 ipb.code = IPO_CLRTOEOL; 158 159 return (ip_send(sp, NULL, &ipb)); 160} 161 162/* 163 * ip_cursor -- 164 * Return the current cursor position. 165 * 166 * PUBLIC: int ip_cursor __P((SCR *, size_t *, size_t *)); 167 */ 168int 169ip_cursor(sp, yp, xp) 170 SCR *sp; 171 size_t *yp, *xp; 172{ 173 IP_PRIVATE *ipp; 174 175 ipp = IPP(sp); 176 *yp = ipp->row; 177 *xp = ipp->col; 178 return (0); 179} 180 181/* 182 * ip_deleteln -- 183 * Delete the current line, scrolling all lines below it. 184 * 185 * PUBLIC: int ip_deleteln __P((SCR *)); 186 */ 187int 188ip_deleteln(sp) 189 SCR *sp; 190{ 191 IP_BUF ipb; 192 193 /* 194 * This clause is required because the curses screen uses reverse 195 * video to delimit split screens. If the screen does not do this, 196 * this code won't be necessary. 197 * 198 * If the bottom line was in reverse video, rewrite it in normal 199 * video before it's scrolled. 200 */ 201 if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) { 202 ipb.code = IPO_REWRITE; 203 ipb.val1 = RLNO(sp, LASTLINE(sp)); 204 if (ip_send(sp, "1", &ipb)) 205 return (1); 206 } 207 208 /* 209 * The bottom line is expected to be blank after this operation, 210 * and other screens must support that semantic. 211 */ 212 ipb.code = IPO_DELETELN; 213 return (ip_send(sp, NULL, &ipb)); 214} 215 216/* 217 * ip_ex_adjust -- 218 * Adjust the screen for ex. 219 * 220 * PUBLIC: int ip_ex_adjust __P((SCR *, exadj_t)); 221 */ 222int 223ip_ex_adjust(sp, action) 224 SCR *sp; 225 exadj_t action; 226{ 227 abort(); 228 /* NOTREACHED */ 229} 230 231/* 232 * ip_insertln -- 233 * Push down the current line, discarding the bottom line. 234 * 235 * PUBLIC: int ip_insertln __P((SCR *)); 236 */ 237int 238ip_insertln(sp) 239 SCR *sp; 240{ 241 IP_BUF ipb; 242 243 ipb.code = IPO_INSERTLN; 244 245 return (ip_send(sp, NULL, &ipb)); 246} 247 248/* 249 * ip_keyval -- 250 * Return the value for a special key. 251 * 252 * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *)); 253 */ 254int 255ip_keyval(sp, val, chp, dnep) 256 SCR *sp; 257 scr_keyval_t val; 258 CHAR_T *chp; 259 int *dnep; 260{ 261 /* 262 * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990, 263 * VWERASE is a 4BSD extension. 264 */ 265 switch (val) { 266 case KEY_VEOF: 267 *dnep = '\004'; /* ^D */ 268 break; 269 case KEY_VERASE: 270 *dnep = '\b'; /* ^H */ 271 break; 272 case KEY_VKILL: 273 *dnep = '\025'; /* ^U */ 274 break; 275#ifdef VWERASE 276 case KEY_VWERASE: 277 *dnep = '\027'; /* ^W */ 278 break; 279#endif 280 default: 281 *dnep = 1; 282 break; 283 } 284 return (0); 285} 286 287/* 288 * ip_move -- 289 * Move the cursor. 290 * 291 * PUBLIC: int ip_move __P((SCR *, size_t, size_t)); 292 */ 293int 294ip_move(sp, lno, cno) 295 SCR *sp; 296 size_t lno, cno; 297{ 298 IP_PRIVATE *ipp; 299 IP_BUF ipb; 300 301 ipp = IPP(sp); 302 ipp->row = lno; 303 ipp->col = cno; 304 305 ipb.code = IPO_MOVE; 306 ipb.val1 = RLNO(sp, lno); 307 ipb.val2 = cno; 308 return (ip_send(sp, "12", &ipb)); 309} 310 311/* 312 * ip_refresh -- 313 * Refresh the screen. 314 * 315 * PUBLIC: int ip_refresh __P((SCR *, int)); 316 */ 317int 318ip_refresh(sp, repaint) 319 SCR *sp; 320 int repaint; 321{ 322 IP_BUF ipb; 323 324 ipb.code = repaint ? IPO_REDRAW : IPO_REFRESH; 325 326 return (ip_send(sp, NULL, &ipb)); 327} 328 329/* 330 * ip_rename -- 331 * Rename the file. 332 * 333 * PUBLIC: int ip_rename __P((SCR *)); 334 */ 335int 336ip_rename(sp) 337 SCR *sp; 338{ 339 IP_BUF ipb; 340 341 ipb.code = IPO_RENAME; 342 ipb.len = strlen(sp->frp->name); 343 ipb.str = sp->frp->name; 344 345 return (ip_send(sp, "s", &ipb)); 346} 347 348/* 349 * ip_suspend -- 350 * Suspend a screen. 351 * 352 * PUBLIC: int ip_suspend __P((SCR *, int *)); 353 */ 354int 355ip_suspend(sp, allowedp) 356 SCR *sp; 357 int *allowedp; 358{ 359 *allowedp = 0; 360 return (0); 361} 362 363/* 364 * ip_usage -- 365 * Print out the ip usage messages. 366 * 367 * PUBLIC: void ip_usage __P((void)); 368 */ 369void 370ip_usage() 371{ 372#define USAGE "\ 373usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n" 374 (void)fprintf(stderr, "%s", USAGE); 375#undef USAGE 376} 377 378/* 379 * ip_send -- 380 * Construct and send an IP buffer. 381 */ 382static int 383ip_send(sp, fmt, ipbp) 384 SCR *sp; 385 char *fmt; 386 IP_BUF *ipbp; 387{ 388 IP_PRIVATE *ipp; 389 size_t blen, off; 390 u_int32_t ilen; 391 int nlen, n, nw, rval; 392 char *bp, *p; 393 394 ipp = IPP(sp); 395 396 GET_SPACE_RET(sp, bp, blen, 128); 397 398 p = bp; 399 nlen = 0; 400 *p++ = ipbp->code; 401 nlen += IPO_CODE_LEN; 402 403 if (fmt != NULL) 404 for (; *fmt != '\0'; ++fmt) 405 switch (*fmt) { 406 case '1': /* Value 1. */ 407 ilen = htonl(ipbp->val1); 408 goto value; 409 case '2': /* Value 2. */ 410 ilen = htonl(ipbp->val2); 411value: nlen += IPO_INT_LEN; 412 off = p - bp; 413 ADD_SPACE_RET(sp, bp, blen, nlen); 414 p = bp + off; 415 memmove(p, &ilen, IPO_INT_LEN); 416 p += IPO_INT_LEN; 417 break; 418 case 's': /* String. */ 419 ilen = ipbp->len; /* XXX: conversion. */ 420 ilen = htonl(ilen); 421 nlen += IPO_INT_LEN + ipbp->len; 422 off = p - bp; 423 ADD_SPACE_RET(sp, bp, blen, nlen); 424 p = bp + off; 425 memmove(p, &ilen, IPO_INT_LEN); 426 p += IPO_INT_LEN; 427 memmove(p, ipbp->str, ipbp->len); 428 p += ipbp->len; 429 break; 430 } 431 432 433 rval = 0; 434 for (n = p - bp, p = bp; n > 0; n -= nw, p += nw) 435 if ((nw = write(ipp->o_fd, p, n)) < 0) { 436 rval = 1; 437 break; 438 } 439 440 FREE_SPACE(sp, bp, blen); 441 442 return (rval); 443} 444