NULLify closed db and don't call db_last on a closed db in ip_refresh
[nvi.git] / ip / ip_funcs.c
blob7f5e62638f0c08d69ac634d9e87457a53098cc86
1 /*-
2 * Copyright (c) 1996
3 * Keith Bostic. All rights reserved.
5 * See the LICENSE file for redistribution information.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char sccsid[] = "$Id: ip_funcs.c,v 8.22 2000/07/19 18:31:55 skimo Exp $ (Berkeley) $Date: 2000/07/19 18:31:55 $";
12 #endif /* not lint */
14 #include <sys/types.h>
15 #include <sys/queue.h>
16 #include <sys/time.h>
18 #include <bitstring.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #include "../common/common.h"
24 #include "../vi/vi.h"
25 #include "../ipc/ip.h"
26 #include "extern.h"
29 * ip_addstr --
30 * Add len bytes from the string at the cursor, advancing the cursor.
32 * PUBLIC: int ip_waddstr __P((SCR *, const CHAR_T *, size_t));
34 int
35 ip_waddstr(sp, str, len)
36 SCR *sp;
37 const CHAR_T *str;
38 size_t len;
40 IP_BUF ipb;
41 IP_PRIVATE *ipp;
42 int iv, rval;
44 ipp = IPP(sp);
46 ipb.code = SI_WADDSTR;
47 ipb.len1 = len * sizeof(CHAR_T);
48 ipb.str1 = (char *)str;
49 rval = vi_send(ipp->o_fd, "a", &ipb);
50 /* XXXX */
51 ipp->col += len;
53 return (rval);
57 * ip_addstr --
58 * Add len bytes from the string at the cursor, advancing the cursor.
60 * PUBLIC: int ip_addstr __P((SCR *, const char *, size_t));
62 int
63 ip_addstr(sp, str, len)
64 SCR *sp;
65 const char *str;
66 size_t len;
68 IP_BUF ipb;
69 IP_PRIVATE *ipp;
70 int iv, rval;
72 ipp = IPP(sp);
75 * If ex isn't in control, it's the last line of the screen and
76 * it's a split screen, use inverse video.
78 iv = 0;
79 if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
80 ipp->row == LASTLINE(sp) && IS_SPLIT(sp)) {
81 iv = 1;
82 ip_attr(sp, SA_INVERSE, 1);
84 ipb.code = SI_ADDSTR;
85 ipb.len1 = len;
86 ipb.str1 = str;
87 rval = vi_send(ipp->o_fd, "a", &ipb);
88 /* XXXX */
89 ipp->col += len;
91 if (iv)
92 ip_attr(sp, SA_INVERSE, 0);
93 return (rval);
97 * ip_attr --
98 * Toggle a screen attribute on/off.
100 * PUBLIC: int ip_attr __P((SCR *, scr_attr_t, int));
103 ip_attr(sp, attribute, on)
104 SCR *sp;
105 scr_attr_t attribute;
106 int on;
108 IP_BUF ipb;
109 IP_PRIVATE *ipp = IPP(sp);
111 if (attribute == SA_ALTERNATE) {
112 if (on) F_SET(ipp, IP_ON_ALTERNATE);
113 else F_CLR(ipp, IP_ON_ALTERNATE);
116 ipb.code = SI_ATTRIBUTE;
117 ipb.val1 = attribute;
118 ipb.val2 = on;
120 return (vi_send(ipp->o_fd, "12", &ipb));
124 * ip_baud --
125 * Return the baud rate.
127 * PUBLIC: int ip_baud __P((SCR *, u_long *));
130 ip_baud(sp, ratep)
131 SCR *sp;
132 u_long *ratep;
134 *ratep = 9600; /* XXX: Translation: fast. */
135 return (0);
139 * ip_bell --
140 * Ring the bell/flash the screen.
142 * PUBLIC: int ip_bell __P((SCR *));
145 ip_bell(sp)
146 SCR *sp;
148 IP_BUF ipb;
149 IP_PRIVATE *ipp = IPP(sp);
151 ipb.code = SI_BELL;
153 return (vi_send(ipp->o_fd, NULL, &ipb));
157 * ip_busy --
158 * Display a busy message.
160 * PUBLIC: void ip_busy __P((SCR *, const char *, busy_t));
162 void
163 ip_busy(sp, str, bval)
164 SCR *sp;
165 const char *str;
166 busy_t bval;
168 IP_BUF ipb;
169 IP_PRIVATE *ipp = IPP(sp);
171 switch (bval) {
172 case BUSY_ON:
173 ipb.code = SI_BUSY_ON;
174 ipb.str1 = str;
175 ipb.len1 = strlen(str);
176 (void)vi_send(ipp->o_fd, "a", &ipb);
177 break;
178 case BUSY_OFF:
179 ipb.code = SI_BUSY_OFF;
180 (void)vi_send(ipp->o_fd, NULL, &ipb);
181 break;
182 case BUSY_UPDATE:
183 break;
185 return;
189 * ip_child --
190 * Prepare child.
192 * PUBLIC: int ip_child __P((SCR *));
195 ip_child(sp)
196 SCR *sp;
198 IP_PRIVATE *ipp = IPP(sp);
200 if (ipp->t_fd != -1) {
201 dup2(ipp->t_fd, 0);
202 dup2(ipp->t_fd, 1);
203 dup2(ipp->t_fd, 2);
204 close(ipp->t_fd);
206 return 0;
210 * ip_clrtoeol --
211 * Clear from the current cursor to the end of the line.
213 * PUBLIC: int ip_clrtoeol __P((SCR *));
216 ip_clrtoeol(sp)
217 SCR *sp;
219 IP_BUF ipb;
220 IP_PRIVATE *ipp = IPP(sp);
222 /* Temporary hack until we can pass screen pointers
223 * or name screens
225 if (IS_VSPLIT(sp)) {
226 size_t x, y, spcnt;
227 IP_PRIVATE *ipp;
228 int error;
230 ipp = IPP(sp);
231 y = ipp->row;
232 x = ipp->col;
233 error = 0;
234 for (spcnt = sp->cols - x;
235 spcnt > 0 && ! error; --spcnt)
236 error = ip_addstr(sp, " ", 1);
237 if (sp->coff == 0)
238 error |= ip_addstr(sp, "|", 1);
239 error |= ip_move(sp, y, x);
240 return error;
243 ipb.code = SI_CLRTOEOL;
245 return (vi_send(ipp->o_fd, NULL, &ipb));
249 * ip_cursor --
250 * Return the current cursor position.
252 * PUBLIC: int ip_cursor __P((SCR *, size_t *, size_t *));
255 ip_cursor(sp, yp, xp)
256 SCR *sp;
257 size_t *yp, *xp;
259 IP_PRIVATE *ipp;
261 ipp = IPP(sp);
262 *yp = ipp->row;
263 *xp = ipp->col;
264 return (0);
268 * ip_deleteln --
269 * Delete the current line, scrolling all lines below it.
271 * PUBLIC: int ip_deleteln __P((SCR *));
274 ip_deleteln(sp)
275 SCR *sp;
277 IP_BUF ipb;
278 IP_PRIVATE *ipp = IPP(sp);
281 * This clause is required because the curses screen uses reverse
282 * video to delimit split screens. If the screen does not do this,
283 * this code won't be necessary.
285 * If the bottom line was in reverse video, rewrite it in normal
286 * video before it's scrolled.
288 if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
289 ipb.code = SI_REWRITE;
290 ipb.val1 = RLNO(sp, LASTLINE(sp));
291 if (vi_send(ipp->o_fd, "1", &ipb))
292 return (1);
296 * The bottom line is expected to be blank after this operation,
297 * and other screens must support that semantic.
299 ipb.code = SI_DELETELN;
300 return (vi_send(ipp->o_fd, NULL, &ipb));
304 * ip_discard --
305 * Discard a screen.
307 * PUBLIC: int ip_discard __P((SCR *, SCR **));
310 ip_discard(discardp, acquirep)
311 SCR *discardp, **acquirep;
313 return (0);
317 * ip_ex_adjust --
318 * Adjust the screen for ex.
320 * PUBLIC: int ip_ex_adjust __P((SCR *, exadj_t));
323 ip_ex_adjust(sp, action)
324 SCR *sp;
325 exadj_t action;
327 abort();
328 /* NOTREACHED */
332 * ip_insertln --
333 * Push down the current line, discarding the bottom line.
335 * PUBLIC: int ip_insertln __P((SCR *));
338 ip_insertln(sp)
339 SCR *sp;
341 IP_BUF ipb;
342 IP_PRIVATE *ipp = IPP(sp);
344 ipb.code = SI_INSERTLN;
346 return (vi_send(ipp->o_fd, NULL, &ipb));
350 * ip_keyval --
351 * Return the value for a special key.
353 * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
356 ip_keyval(sp, val, chp, dnep)
357 SCR *sp;
358 scr_keyval_t val;
359 CHAR_T *chp;
360 int *dnep;
363 * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
364 * VWERASE is a 4BSD extension.
366 switch (val) {
367 case KEY_VEOF:
368 *dnep = '\004'; /* ^D */
369 break;
370 case KEY_VERASE:
371 *dnep = '\b'; /* ^H */
372 break;
373 case KEY_VKILL:
374 *dnep = '\025'; /* ^U */
375 break;
376 #ifdef VWERASE
377 case KEY_VWERASE:
378 *dnep = '\027'; /* ^W */
379 break;
380 #endif
381 default:
382 *dnep = 1;
383 break;
385 return (0);
389 * ip_move --
390 * Move the cursor.
392 * PUBLIC: int ip_move __P((SCR *, size_t, size_t));
395 ip_move(sp, lno, cno)
396 SCR *sp;
397 size_t lno, cno;
399 IP_PRIVATE *ipp;
400 IP_BUF ipb;
402 ipp = IPP(sp);
403 ipp->row = lno;
404 ipp->col = cno;
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));
413 * PUBLIC: void ip_msg __P((SCR *, mtype_t, char *, size_t));
415 void
416 ip_msg(sp, mtype, line, len)
417 SCR *sp;
418 mtype_t mtype;
419 char *line;
420 size_t len;
422 IP_PRIVATE *ipp = IPP(sp);
424 if (F_ISSET(ipp, IP_ON_ALTERNATE))
425 vs_msg(sp, mtype, line, len);
426 else {
427 write(ipp->t_fd, line, len);
428 F_CLR(sp, SC_EX_WAIT_NO);
433 * ip_refresh --
434 * Refresh the screen.
436 * PUBLIC: int ip_refresh __P((SCR *, int));
439 ip_refresh(sp, repaint)
440 SCR *sp;
441 int repaint;
443 IP_BUF ipb;
444 IP_PRIVATE *ipp;
445 db_recno_t total;
447 ipp = IPP(sp);
450 * If the scroll bar information has changed since we last sent
451 * it, resend it. Currently, we send three values:
453 * top The line number of the first line in the screen.
454 * num The number of lines visible on the screen.
455 * total The number of lines in the file.
457 * XXX
458 * This is a gross violation of layering... we're looking at data
459 * structures at which we have absolutely no business whatsoever
460 * looking...
462 ipb.val1 = HMAP->lno;
463 ipb.val2 = TMAP->lno - HMAP->lno;
464 if (sp->ep != NULL && sp->ep->db != NULL)
465 (void)db_last(sp, &total);
466 ipb.val3 = total == 0 ? 1 : total;
467 if (ipb.val1 != ipp->sb_top ||
468 ipb.val2 != ipp->sb_num || ipb.val3 != ipp->sb_total) {
469 ipb.code = SI_SCROLLBAR;
470 (void)vi_send(ipp->o_fd, "123", &ipb);
471 ipp->sb_top = ipb.val1;
472 ipp->sb_num = ipb.val2;
473 ipp->sb_total = ipb.val3;
476 /* Refresh/repaint the screen. */
477 ipb.code = repaint ? SI_REDRAW : SI_REFRESH;
478 return (vi_send(ipp->o_fd, NULL, &ipb));
482 * ip_rename --
483 * Rename the file.
485 * PUBLIC: int ip_rename __P((SCR *, char *, int));
488 ip_rename(sp, name, on)
489 SCR *sp;
490 char *name;
491 int on;
493 IP_BUF ipb;
494 IP_PRIVATE *ipp = IPP(sp);
496 ipb.code = SI_RENAME;
497 ipb.str1 = name;
498 ipb.len1 = name ? strlen(name) : 0;
499 return (vi_send(ipp->o_fd, "a", &ipb));
503 * ip_reply --
504 * Reply to a message.
506 * PUBLIC: int ip_reply __P((SCR *, int, char *));
509 ip_reply(sp, status, msg)
510 SCR *sp;
511 int status;
512 char *msg;
514 IP_BUF ipb;
515 IP_PRIVATE *ipp = IPP(sp);
517 ipb.code = SI_REPLY;
518 ipb.val1 = status;
519 ipb.str1 = msg == NULL ? "" : msg;
520 ipb.len1 = strlen(ipb.str1);
521 return (vi_send(ipp->o_fd, "1a", &ipb));
525 * ip_split --
526 * Split a screen.
528 * PUBLIC: int ip_split __P((SCR *, SCR *));
531 ip_split(origp, newp)
532 SCR *origp, *newp;
534 return (0);
538 * ip_suspend --
539 * Suspend a screen.
541 * PUBLIC: int ip_suspend __P((SCR *, int *));
544 ip_suspend(sp, allowedp)
545 SCR *sp;
546 int *allowedp;
548 *allowedp = 0;
549 return (0);
553 * ip_usage --
554 * Print out the ip usage messages.
556 * PUBLIC: void ip_usage __P((void));
558 void
559 ip_usage()
561 #define USAGE "\
562 usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n"
563 (void)fprintf(stderr, "%s", USAGE);
564 #undef USAGE