diff options
Diffstat (limited to 'usr.bin/vi/svi/svi_util.c')
-rw-r--r-- | usr.bin/vi/svi/svi_util.c | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/usr.bin/vi/svi/svi_util.c b/usr.bin/vi/svi/svi_util.c new file mode 100644 index 00000000000..65422ede1a6 --- /dev/null +++ b/usr.bin/vi/svi/svi_util.c @@ -0,0 +1,347 @@ +/*- + * Copyright (c) 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)svi_util.c 8.55 (Berkeley) 8/17/94"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/time.h> + +#include <bitstring.h> +#include <errno.h> +#include <limits.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +#include "compat.h" +#include <curses.h> +#include <db.h> +#include <regex.h> + +#include "vi.h" +#include "../vi/vcmd.h" +#include "excmd.h" +#include "svi_screen.h" +#include "../sex/sex_screen.h" + +/* + * svi_bell -- + * Ring the bell. + */ +void +svi_bell(sp) + SCR *sp; +{ +#ifdef SYSV_CURSES + if (O_ISSET(sp, O_FLASH)) + flash(); + else + beep(); +#else + if (O_ISSET(sp, O_FLASH) && SVP(sp)->VB != NULL) { + (void)tputs(SVP(sp)->VB, 1, vi_putchar); + (void)fflush(stdout); + } else + (void)write(STDOUT_FILENO, "\007", 1); /* '\a' */ +#endif + F_CLR(sp, S_BELLSCHED); +} + +/* + * svi_optchange -- + * Screen specific "option changed" routine. + */ +int +svi_optchange(sp, opt) + SCR *sp; + int opt; +{ + switch (opt) { + case O_TERM: + /* Toss any saved visual bell information. */ + if (SVP(sp)->VB != NULL) { + FREE(SVP(sp)->VB, strlen(SVP(sp)->VB) + 1); + SVP(sp)->VB = NULL; + } + + /* Reset the screen size. */ + if (sp->s_window(sp, 0)) + return (1); + F_SET(sp, S_RESIZE); + break; + case O_WINDOW: + if (svi_crel(sp, O_VAL(sp, O_WINDOW))) + return (1); + break; + } + + (void)v_optchange(sp, opt); + (void)ex_optchange(sp, opt); + + return (0); +} + +/* + * svi_busy -- + * Put the cursor somewhere so the user will think we're busy. + */ +int +svi_busy(sp, msg) + SCR *sp; + char const *msg; +{ + /* + * search.c:f_search() is called from ex/ex_tag.c:ex_tagfirst(), + * which runs before the screen really exists. Make sure we don't + * step on anything. + * + * If the terminal isn't initialized, there's nothing to do. + */ + if (!F_ISSET(SVP(sp), SVI_CURSES_INIT)) + return (0); + + MOVE(sp, INFOLINE(sp), 0); + if (msg) { + ADDSTR(msg); + clrtoeol(); + } + refresh(); + F_SET(SVP(sp), SVI_CUR_INVALID); + return (0); +} + +/* + * svi_keypad -- + * Put the keypad/cursor arrows into or out of application mode. + */ +void +svi_keypad(sp, on) + SCR *sp; + int on; +{ +#ifdef SYSV_CURSES + keypad(stdscr, on ? TRUE : FALSE); +#else + char *sbp, *t, sbuf[128]; + + sbp = sbuf; + if ((t = tgetstr(on ? "ks" : "ke", &sbp)) == NULL) + return; + (void)tputs(t, 0, vi_putchar); + (void)fflush(stdout); +#endif +} + +/* + * svi_clear -- + * Clear from the row down to the end of the screen. + */ +int +svi_clear(sp) + SCR *sp; +{ + size_t oldy, oldx, row; + + getyx(stdscr, oldy, oldx); + for (row = SVP(sp)->srows - 1; row >= oldy; --row) { + MOVEA(sp, row, 0); + clrtoeol(); + } + MOVEA(sp, oldy, oldx); + refresh(); + return (0); +} + +/* + * svi_suspend -- + * Suspend an svi screen. + * + * See signal.c for a long discussion of what's going on here. Let + * me put it this way, it's NOT my fault. + */ +int +svi_suspend(sp) + SCR *sp; +{ + struct termios sv_term; + sigset_t set; + int oldx, oldy, rval; + char *sbp, *t, sbuf[128]; + + rval = 0; + + /* + * Block SIGALRM, because vi uses timers to decide when to paint + * busy messages on the screen. + */ + (void)sigemptyset(&set); + (void)sigaddset(&set, SIGALRM); + if (sigprocmask(SIG_BLOCK, &set, NULL)) { + msgq(sp, M_SYSERR, "suspend: sigblock"); + return (1); + } + + /* Save the current cursor position. */ + getyx(stdscr, oldy, oldx); + + /* + * Move the cursor to the bottom of the screen. + * + * XXX + * Some curses implementations don't turn off inverse video when + * standend() is called, waiting to see what the next character is + * going to be, instead. Write a character to force inverse video + * off, and then clear the line. + */ + MOVE(sp, INFOLINE(sp), 0); + ADDCH('.'); + refresh(); + MOVE(sp, INFOLINE(sp), 0); + clrtoeol(); + refresh(); + + /* Restore the cursor keys to normal mode. */ + svi_keypad(sp, 0); + + /* Send VE/TE. */ +#ifdef SYSV_CURSES + if ((t = tigetstr("cnorm")) != NULL && t != (char *)-1) + (void)tputs(t, 0, vi_putchar); + if ((t = tigetstr("rmcup")) != NULL && t != (char *)-1) + (void)tputs(t, 0, vi_putchar); +#else + sbp = sbuf; + if ((t = tgetstr("ve", &sbp)) != NULL) + (void)tputs(t, 0, vi_putchar); + sbp = sbuf; + if ((t = tgetstr("te", &sbp)) != NULL) + (void)tputs(t, 0, vi_putchar); +#endif + (void)fflush(stdout); + + /* Save current terminal settings, and restore the original ones. */ + if (tcgetattr(STDIN_FILENO, &sv_term)) { + msgq(sp, M_SYSERR, "suspend: tcgetattr"); + return (1); + } + if (tcsetattr(STDIN_FILENO, + TCSASOFT | TCSADRAIN, &sp->gp->original_termios)) { + msgq(sp, M_SYSERR, "suspend: tcsetattr original"); + return (1); + } + + /* Push out any waiting messages. */ + (void)write(STDOUT_FILENO, "\n", 1); + (void)sex_refresh(sp, sp->ep); + + /* Stop the process group. */ + if (kill(0, SIGTSTP)) { + msgq(sp, M_SYSERR, "suspend: kill"); + rval = 1; + } + + /* Time passes ... */ + + /* Restore current terminal settings. */ + if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &sv_term)) { + msgq(sp, M_SYSERR, "suspend: tcsetattr current"); + rval = 1; + } + + /* Send TI/VS. */ +#ifdef SYSV_CURSES + if ((t = tigetstr("smcup")) != NULL && t != (char *)-1) + (void)tputs(t, 0, vi_putchar); + if ((t = tigetstr("cvvis")) != NULL && t != (char *)-1) + (void)tputs(t, 0, vi_putchar); +#else + sbp = sbuf; + if ((t = tgetstr("ti", &sbp)) != NULL) + (void)tputs(t, 0, vi_putchar); + sbp = sbuf; + if ((t = tgetstr("vs", &sbp)) != NULL) + (void)tputs(t, 0, vi_putchar); +#endif + (void)fflush(stdout); + + /* Put the cursor keys into application mode. */ + svi_keypad(sp, 1); + + /* + * If the screen changed size, do a full refresh. Otherwise, + * System V has curses repaint it. 4BSD curses will repaint + * it in the wrefresh() call below. + */ + if (!sp->s_window(sp, 1)) + (void)sp->s_refresh(sp, sp->ep); +#ifdef SYSV_CURSES + else + redrawwin(stdscr); +#endif + + /* + * Restore the cursor. + * + * !!! + * Don't use MOVE/MOVEA, we don't want to return without resetting + * the signals, regardless. + */ + (void)move(oldy, oldx); + (void)wrefresh(curscr); + + /* Reset the signals. */ + if (sigprocmask(SIG_UNBLOCK, &set, NULL)) { + msgq(sp, M_SYSERR, "suspend: sigblock"); + rval = 1; + } + return (rval); +} + +/* + * svi_gdbrefresh -- + * Stub routine so can flush out screen changes using gdb. + */ +#ifdef DEBUG +int +svi_gdbrefresh() +{ + refresh(); + return (0); +} +#endif |