ip_funcs.c revision 1.1.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