ip_funcs.c revision 1.2 1 /* $NetBSD: ip_funcs.c,v 1.2 2013/11/22 15:52:05 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 #ifndef lint
12 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 ";
13 #endif /* not lint */
14
15 #include <sys/types.h>
16 #include <sys/queue.h>
17 #include <sys/time.h>
18
19 #include <bitstring.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24
25 #include "../common/common.h"
26 #include "../vi/vi.h"
27 #include "../ipc/ip.h"
28
29 /*
30 * ip_addstr --
31 * Add len bytes from the string at the cursor, advancing the cursor.
32 *
33 * PUBLIC: int ip_waddstr __P((SCR *, const CHAR_T *, size_t));
34 */
35 int
36 ip_waddstr(SCR *sp, const CHAR_T *str, size_t len)
37 {
38 IP_BUF ipb;
39 IP_PRIVATE *ipp;
40 int rval;
41
42 ipp = IPP(sp);
43
44 ipb.code = SI_WADDSTR;
45 ipb.len1 = len * sizeof(CHAR_T);
46 ipb.str1 = __UNCONST(str);
47 rval = vi_send(ipp->o_fd, "a", &ipb);
48 /* XXXX */
49 ipp->col += len;
50
51 return (rval);
52 }
53
54 /*
55 * ip_addstr --
56 * Add len bytes from the string at the cursor, advancing the cursor.
57 *
58 * PUBLIC: int ip_addstr __P((SCR *, const char *, size_t));
59 */
60 int
61 ip_addstr(SCR *sp, const char *str, size_t len)
62 {
63 IP_BUF ipb;
64 IP_PRIVATE *ipp;
65 int iv, rval;
66
67 ipp = IPP(sp);
68
69 /*
70 * If ex isn't in control, it's the last line of the screen and
71 * it's a split screen, use inverse video.
72 */
73 iv = 0;
74 if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
75 ipp->row == LASTLINE(sp) && IS_SPLIT(sp)) {
76 iv = 1;
77 ip_attr(sp, SA_INVERSE, 1);
78 }
79 ipb.code = SI_ADDSTR;
80 ipb.len1 = len;
81 ipb.str1 = str;
82 rval = vi_send(ipp->o_fd, "a", &ipb);
83 /* XXXX */
84 ipp->col += len;
85
86 if (iv)
87 ip_attr(sp, SA_INVERSE, 0);
88 return (rval);
89 }
90
91 /*
92 * ip_attr --
93 * Toggle a screen attribute on/off.
94 *
95 * PUBLIC: int ip_attr __P((SCR *, scr_attr_t, int));
96 */
97 int
98 ip_attr(SCR *sp, scr_attr_t attribute, int on)
99 {
100 IP_BUF ipb;
101 IP_PRIVATE *ipp = IPP(sp);
102
103 if (attribute == SA_ALTERNATE) {
104 if (on) F_SET(ipp, IP_ON_ALTERNATE);
105 else F_CLR(ipp, IP_ON_ALTERNATE);
106 }
107
108 ipb.code = SI_ATTRIBUTE;
109 ipb.val1 = attribute;
110 ipb.val2 = on;
111
112 return (vi_send(ipp->o_fd, "12", &ipb));
113 }
114
115 /*
116 * ip_baud --
117 * Return the baud rate.
118 *
119 * PUBLIC: int ip_baud __P((SCR *, u_long *));
120 */
121 int
122 ip_baud(SCR *sp, u_long *ratep)
123 {
124 *ratep = 9600; /* XXX: Translation: fast. */
125 return (0);
126 }
127
128 /*
129 * ip_bell --
130 * Ring the bell/flash the screen.
131 *
132 * PUBLIC: int ip_bell __P((SCR *));
133 */
134 int
135 ip_bell(SCR *sp)
136 {
137 IP_BUF ipb;
138 IP_PRIVATE *ipp = IPP(sp);
139
140 ipb.code = SI_BELL;
141
142 return (vi_send(ipp->o_fd, NULL, &ipb));
143 }
144
145 /*
146 * ip_busy --
147 * Display a busy message.
148 *
149 * PUBLIC: void ip_busy __P((SCR *, const char *, busy_t));
150 */
151 void
152 ip_busy(SCR *sp, const char *str, busy_t bval)
153 {
154 IP_BUF ipb;
155 IP_PRIVATE *ipp = IPP(sp);
156
157 switch (bval) {
158 case BUSY_ON:
159 ipb.code = SI_BUSY_ON;
160 ipb.str1 = str;
161 ipb.len1 = strlen(str);
162 (void)vi_send(ipp->o_fd, "a", &ipb);
163 break;
164 case BUSY_OFF:
165 ipb.code = SI_BUSY_OFF;
166 (void)vi_send(ipp->o_fd, NULL, &ipb);
167 break;
168 case BUSY_UPDATE:
169 break;
170 }
171 return;
172 }
173
174 /*
175 * ip_child --
176 * Prepare child.
177 *
178 * PUBLIC: int ip_child __P((SCR *));
179 */
180 int
181 ip_child(SCR *sp)
182 {
183 IP_PRIVATE *ipp = IPP(sp);
184
185 if (ipp->t_fd != -1) {
186 dup2(ipp->t_fd, 0);
187 dup2(ipp->t_fd, 1);
188 dup2(ipp->t_fd, 2);
189 close(ipp->t_fd);
190 }
191 return 0;
192 }
193
194 /*
195 * ip_clrtoeol --
196 * Clear from the current cursor to the end of the line.
197 *
198 * PUBLIC: int ip_clrtoeol __P((SCR *));
199 */
200 int
201 ip_clrtoeol(SCR *sp)
202 {
203 IP_BUF ipb;
204 IP_PRIVATE *ipp = IPP(sp);
205
206 /* Temporary hack until we can pass screen pointers
207 * or name screens
208 */
209 if (IS_VSPLIT(sp)) {
210 size_t x, y, spcnt;
211 int error;
212
213 y = ipp->row;
214 x = ipp->col;
215 error = 0;
216 for (spcnt = sp->cols - x;
217 spcnt > 0 && ! error; --spcnt)
218 error = ip_addstr(sp, " ", 1);
219 if (sp->coff == 0)
220 error |= ip_addstr(sp, "|", 1);
221 error |= ip_move(sp, y, x);
222 return error;
223 }
224
225 ipb.code = SI_CLRTOEOL;
226
227 return (vi_send(ipp->o_fd, NULL, &ipb));
228 }
229
230 /*
231 * ip_cursor --
232 * Return the current cursor position.
233 *
234 * PUBLIC: int ip_cursor __P((SCR *, size_t *, size_t *));
235 */
236 int
237 ip_cursor(SCR *sp, size_t *yp, size_t *xp)
238 {
239 IP_PRIVATE *ipp;
240
241 ipp = IPP(sp);
242 *yp = ipp->row;
243 *xp = ipp->col;
244 return (0);
245 }
246
247 /*
248 * ip_deleteln --
249 * Delete the current line, scrolling all lines below it.
250 *
251 * PUBLIC: int ip_deleteln __P((SCR *));
252 */
253 int
254 ip_deleteln(SCR *sp)
255 {
256 IP_BUF ipb;
257 IP_PRIVATE *ipp = IPP(sp);
258
259 /*
260 * This clause is required because the curses screen uses reverse
261 * video to delimit split screens. If the screen does not do this,
262 * this code won't be necessary.
263 *
264 * If the bottom line was in reverse video, rewrite it in normal
265 * video before it's scrolled.
266 */
267 if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
268 ipb.code = SI_REWRITE;
269 ipb.val1 = RLNO(sp, LASTLINE(sp));
270 if (vi_send(ipp->o_fd, "1", &ipb))
271 return (1);
272 }
273
274 /*
275 * The bottom line is expected to be blank after this operation,
276 * and other screens must support that semantic.
277 */
278 ipb.code = SI_DELETELN;
279 return (vi_send(ipp->o_fd, NULL, &ipb));
280 }
281
282 /*
283 * ip_discard --
284 * Discard a screen.
285 *
286 * PUBLIC: int ip_discard __P((SCR *, SCR **));
287 */
288 int
289 ip_discard(SCR *discardp, SCR **acquirep)
290 {
291 return (0);
292 }
293
294 /*
295 * ip_ex_adjust --
296 * Adjust the screen for ex.
297 *
298 * PUBLIC: int ip_ex_adjust __P((SCR *, exadj_t));
299 */
300 int
301 ip_ex_adjust(SCR *sp, exadj_t action)
302 {
303 abort();
304 /* NOTREACHED */
305 }
306
307 /*
308 * ip_insertln --
309 * Push down the current line, discarding the bottom line.
310 *
311 * PUBLIC: int ip_insertln __P((SCR *));
312 */
313 int
314 ip_insertln(SCR *sp)
315 {
316 IP_BUF ipb;
317 IP_PRIVATE *ipp = IPP(sp);
318
319 ipb.code = SI_INSERTLN;
320
321 return (vi_send(ipp->o_fd, NULL, &ipb));
322 }
323
324 /*
325 * ip_keyval --
326 * Return the value for a special key.
327 *
328 * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
329 */
330 int
331 ip_keyval(SCR *sp, scr_keyval_t val, CHAR_T *chp, int *dnep)
332 {
333 /*
334 * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
335 * VWERASE is a 4BSD extension.
336 */
337 switch (val) {
338 case KEY_VEOF:
339 *dnep = '\004'; /* ^D */
340 break;
341 case KEY_VERASE:
342 *dnep = '\b'; /* ^H */
343 break;
344 case KEY_VKILL:
345 *dnep = '\025'; /* ^U */
346 break;
347 #ifdef VWERASE
348 case KEY_VWERASE:
349 *dnep = '\027'; /* ^W */
350 break;
351 #endif
352 default:
353 *dnep = 1;
354 break;
355 }
356 return (0);
357 }
358
359 /*
360 * ip_move --
361 * Move the cursor.
362 *
363 * PUBLIC: int ip_move __P((SCR *, size_t, size_t));
364 */
365 int
366 ip_move(SCR *sp, size_t lno, size_t cno)
367 {
368 IP_PRIVATE *ipp;
369 IP_BUF ipb;
370
371 ipp = IPP(sp);
372 ipp->row = lno;
373 ipp->col = cno;
374
375 ipb.code = SI_MOVE;
376 ipb.val1 = RLNO(sp, lno);
377 ipb.val2 = RCNO(sp, cno);
378 return (vi_send(ipp->o_fd, "12", &ipb));
379 }
380
381 /*
382 * PUBLIC: void ip_msg __P((SCR *, mtype_t, char *, size_t));
383 */
384 void
385 ip_msg(SCR *sp, mtype_t mtype, char *line, size_t len)
386 {
387 IP_PRIVATE *ipp = IPP(sp);
388
389 if (F_ISSET(ipp, IP_ON_ALTERNATE))
390 vs_msg(sp, mtype, line, len);
391 else {
392 write(ipp->t_fd, line, len);
393 F_CLR(sp, SC_EX_WAIT_NO);
394 }
395 }
396
397 /*
398 * ip_refresh --
399 * Refresh the screen.
400 *
401 * PUBLIC: int ip_refresh __P((SCR *, int));
402 */
403 int
404 ip_refresh(SCR *sp, int repaint)
405 {
406 IP_BUF ipb;
407 IP_PRIVATE *ipp;
408 db_recno_t total;
409
410 ipp = IPP(sp);
411
412 /*
413 * If the scroll bar information has changed since we last sent
414 * it, resend it. Currently, we send three values:
415 *
416 * top The line number of the first line in the screen.
417 * num The number of lines visible on the screen.
418 * total The number of lines in the file.
419 *
420 * XXX
421 * This is a gross violation of layering... we're looking at data
422 * structures at which we have absolutely no business whatsoever
423 * looking...
424 */
425 ipb.val1 = HMAP->lno;
426 ipb.val2 = TMAP->lno - HMAP->lno;
427 if (sp->ep != NULL && sp->ep->db != NULL)
428 (void)db_last(sp, &total);
429 ipb.val3 = total == 0 ? 1 : total;
430 if (ipb.val1 != ipp->sb_top ||
431 ipb.val2 != ipp->sb_num || ipb.val3 != ipp->sb_total) {
432 ipb.code = SI_SCROLLBAR;
433 (void)vi_send(ipp->o_fd, "123", &ipb);
434 ipp->sb_top = ipb.val1;
435 ipp->sb_num = ipb.val2;
436 ipp->sb_total = ipb.val3;
437 }
438
439 /* Refresh/repaint the screen. */
440 ipb.code = repaint ? SI_REDRAW : SI_REFRESH;
441 return (vi_send(ipp->o_fd, NULL, &ipb));
442 }
443
444 /*
445 * ip_rename --
446 * Rename the file.
447 *
448 * PUBLIC: int ip_rename __P((SCR *, char *, int));
449 */
450 int
451 ip_rename(SCR *sp, char *name, int on)
452 {
453 IP_BUF ipb;
454 IP_PRIVATE *ipp = IPP(sp);
455
456 ipb.code = SI_RENAME;
457 ipb.str1 = name;
458 ipb.len1 = name ? strlen(name) : 0;
459 return (vi_send(ipp->o_fd, "a", &ipb));
460 }
461
462 /*
463 * ip_reply --
464 * Reply to a message.
465 *
466 * PUBLIC: int ip_reply __P((SCR *, int, char *));
467 */
468 int
469 ip_reply(SCR *sp, int status, char *msg)
470 {
471 IP_BUF ipb;
472 IP_PRIVATE *ipp = IPP(sp);
473
474 ipb.code = SI_REPLY;
475 ipb.val1 = status;
476 ipb.str1 = msg == NULL ? "" : msg;
477 ipb.len1 = strlen(ipb.str1);
478 return (vi_send(ipp->o_fd, "1a", &ipb));
479 }
480
481 /*
482 * ip_split --
483 * Split a screen.
484 *
485 * PUBLIC: int ip_split __P((SCR *, SCR *));
486 */
487 int
488 ip_split(SCR *origp, SCR *newp)
489 {
490 return (0);
491 }
492
493 /*
494 * ip_suspend --
495 * Suspend a screen.
496 *
497 * PUBLIC: int ip_suspend __P((SCR *, int *));
498 */
499 int
500 ip_suspend(SCR *sp, int *allowedp)
501 {
502 *allowedp = 0;
503 return (0);
504 }
505
506 /*
507 * ip_usage --
508 * Print out the ip usage messages.
509 *
510 * PUBLIC: void ip_usage __P((void));
511 */
512 void
513 ip_usage(void)
514 {
515 #define USAGE "\
516 usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n"
517 (void)fprintf(stderr, "%s", USAGE);
518 #undef USAGE
519 }
520