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[] = "@(#)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
25 static 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 */
33 int
ip_addstr(sp,str,len)34 ip_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 */
71 int
ip_attr(sp,attribute,on)72 ip_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 */
92 int
ip_baud(sp,ratep)93 ip_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 */
107 int
ip_bell(sp)108 ip_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 */
124 void
ip_busy(sp,str,bval)125 ip_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 */
151 int
ip_clrtoeol(sp)152 ip_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 */
168 int
ip_cursor(sp,yp,xp)169 ip_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 */
187 int
ip_deleteln(sp)188 ip_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 */
222 int
ip_ex_adjust(sp,action)223 ip_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 */
237 int
ip_insertln(sp)238 ip_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 */
254 int
ip_keyval(sp,val,chp,dnep)255 ip_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 */
293 int
ip_move(sp,lno,cno)294 ip_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 */
317 int
ip_refresh(sp,repaint)318 ip_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 */
335 int
ip_rename(sp)336 ip_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 */
354 int
ip_suspend(sp,allowedp)355 ip_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 */
369 void
ip_usage()370 ip_usage()
371 {
372 #define USAGE "\
373 usage: 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 */
382 static int
ip_send(sp,fmt,ipbp)383 ip_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);
411 value: 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