1996-11-01 06:45:43 +00:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 1991, 1993, 1994
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
* Copyright (c) 1991, 1993, 1994, 1995, 1996
|
|
|
|
* Keith Bostic. All rights reserved.
|
|
|
|
*
|
|
|
|
* See the LICENSE file for redistribution information.
|
|
|
|
*/
|
|
|
|
|
2013-08-11 09:44:58 +00:00
|
|
|
#include "multibyte.h"
|
|
|
|
|
|
|
|
#ifdef USE_WIDECHAR
|
|
|
|
#define FILE2INT5(sp,buf,n,nlen,w,wlen) \
|
|
|
|
sp->conv.file2int(sp, n, nlen, &buf, &wlen, &w)
|
|
|
|
#define INT2FILE(sp,w,wlen,n,nlen) \
|
|
|
|
sp->conv.int2file(sp, w, wlen, &sp->cw, &nlen, &n)
|
|
|
|
#define CHAR2INT5(sp,buf,n,nlen,w,wlen) \
|
|
|
|
sp->conv.sys2int(sp, n, nlen, &buf, &wlen, &w)
|
|
|
|
#define INT2CHAR(sp,w,wlen,n,nlen) \
|
|
|
|
sp->conv.int2sys(sp, w, wlen, &sp->cw, &nlen, &n)
|
|
|
|
#define INPUT2INT5(sp,cw,n,nlen,w,wlen) \
|
|
|
|
sp->conv.input2int(sp, n, nlen, &(cw), &wlen, &w)
|
|
|
|
#define CONST
|
2013-12-08 00:04:25 +00:00
|
|
|
#define INTISWIDE(c) (wctob(c) == EOF)
|
2013-08-11 09:44:58 +00:00
|
|
|
#define CHAR_WIDTH(sp, ch) wcwidth(ch)
|
2013-12-08 00:04:25 +00:00
|
|
|
#define CAN_PRINT(sp, ch) (CHAR_WIDTH(sp, ch) > 0)
|
2013-08-11 09:44:58 +00:00
|
|
|
#else
|
|
|
|
#define FILE2INT5(sp,buf,n,nlen,w,wlen) \
|
|
|
|
(w = n, wlen = nlen, 0)
|
|
|
|
#define INT2FILE(sp,w,wlen,n,nlen) \
|
|
|
|
(n = w, nlen = wlen, 0)
|
|
|
|
#define CHAR2INT5(sp,buf,n,nlen,w,wlen) \
|
|
|
|
(w = n, wlen = nlen, 0)
|
|
|
|
#define INT2CHAR(sp,w,wlen,n,nlen) \
|
|
|
|
(n = w, nlen = wlen, 0)
|
|
|
|
#define INPUT2INT5(sp,buf,n,nlen,w,wlen) \
|
|
|
|
(w = n, wlen = nlen, 0)
|
2013-12-08 00:04:25 +00:00
|
|
|
#define CONST const
|
|
|
|
#define INTISWIDE(c) 0
|
2013-08-11 09:44:58 +00:00
|
|
|
#define CHAR_WIDTH(sp, ch) 1
|
2013-12-08 00:04:25 +00:00
|
|
|
#define CAN_PRINT(sp, ch) isprint(ch)
|
2013-08-11 09:44:58 +00:00
|
|
|
#endif
|
|
|
|
#define FILE2INT(sp,n,nlen,w,wlen) \
|
|
|
|
FILE2INT5(sp,sp->cw,n,nlen,w,wlen)
|
|
|
|
#define CHAR2INT(sp,n,nlen,w,wlen) \
|
|
|
|
CHAR2INT5(sp,sp->cw,n,nlen,w,wlen)
|
1996-11-01 06:45:43 +00:00
|
|
|
|
|
|
|
/* The maximum number of columns any character can take up on a screen. */
|
2013-08-11 09:44:58 +00:00
|
|
|
#define MAX_CHARACTER_COLUMNS 7
|
1996-11-01 06:45:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Event types.
|
|
|
|
*
|
|
|
|
* The program structure depends on the event loop being able to return
|
|
|
|
* E_EOF/E_ERR multiple times -- eventually enough things will end due
|
|
|
|
* to the events that vi will reach the command level for the screen, at
|
|
|
|
* which point the exit flags will be set and vi will exit.
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
E_NOTUSED = 0, /* Not set. */
|
|
|
|
E_CHARACTER, /* Input character: e_c set. */
|
|
|
|
E_EOF, /* End of input (NOT ^D). */
|
|
|
|
E_ERR, /* Input error. */
|
|
|
|
E_INTERRUPT, /* Interrupt. */
|
|
|
|
E_REPAINT, /* Repaint: e_flno, e_tlno set. */
|
|
|
|
E_SIGHUP, /* SIGHUP. */
|
|
|
|
E_SIGTERM, /* SIGTERM. */
|
|
|
|
E_STRING, /* Input string: e_csp, e_len set. */
|
|
|
|
E_TIMEOUT, /* Timeout. */
|
|
|
|
E_WRESIZE, /* Window resize. */
|
|
|
|
} e_event_t;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Character values.
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
K_NOTUSED = 0, /* Not set. */
|
|
|
|
K_BACKSLASH, /* \ */
|
|
|
|
K_CARAT, /* ^ */
|
|
|
|
K_CNTRLD, /* ^D */
|
|
|
|
K_CNTRLR, /* ^R */
|
|
|
|
K_CNTRLT, /* ^T */
|
|
|
|
K_CNTRLZ, /* ^Z */
|
|
|
|
K_COLON, /* : */
|
|
|
|
K_CR, /* \r */
|
|
|
|
K_ESCAPE, /* ^[ */
|
|
|
|
K_FORMFEED, /* \f */
|
|
|
|
K_HEXCHAR, /* ^X */
|
|
|
|
K_NL, /* \n */
|
|
|
|
K_RIGHTBRACE, /* } */
|
|
|
|
K_RIGHTPAREN, /* ) */
|
|
|
|
K_TAB, /* \t */
|
|
|
|
K_VERASE, /* set from tty: default ^H */
|
|
|
|
K_VKILL, /* set from tty: default ^U */
|
|
|
|
K_VLNEXT, /* set from tty: default ^V */
|
|
|
|
K_VWERASE, /* set from tty: default ^W */
|
|
|
|
K_ZERO /* 0 */
|
|
|
|
} e_key_t;
|
|
|
|
|
|
|
|
struct _event {
|
|
|
|
TAILQ_ENTRY(_event) q; /* Linked list of events. */
|
|
|
|
e_event_t e_event; /* Event type. */
|
|
|
|
union {
|
|
|
|
struct { /* Input character. */
|
|
|
|
CHAR_T c; /* Character. */
|
|
|
|
e_key_t value; /* Key type. */
|
|
|
|
|
|
|
|
#define CH_ABBREVIATED 0x01 /* Character is from an abbreviation. */
|
|
|
|
#define CH_MAPPED 0x02 /* Character is from a map. */
|
|
|
|
#define CH_NOMAP 0x04 /* Do not map the character. */
|
|
|
|
#define CH_QUOTED 0x08 /* Character is already quoted. */
|
|
|
|
u_int8_t flags;
|
|
|
|
} _e_ch;
|
|
|
|
#define e_ch _u_event._e_ch /* !!! The structure, not the char. */
|
|
|
|
#define e_c _u_event._e_ch.c
|
|
|
|
#define e_value _u_event._e_ch.value
|
|
|
|
#define e_flags _u_event._e_ch.flags
|
|
|
|
|
|
|
|
struct { /* Screen position, size. */
|
|
|
|
size_t lno1; /* Line number. */
|
|
|
|
size_t cno1; /* Column number. */
|
|
|
|
size_t lno2; /* Line number. */
|
|
|
|
size_t cno2; /* Column number. */
|
|
|
|
} _e_mark;
|
|
|
|
#define e_lno _u_event._e_mark.lno1 /* Single location. */
|
|
|
|
#define e_cno _u_event._e_mark.cno1
|
|
|
|
#define e_flno _u_event._e_mark.lno1 /* Text region. */
|
|
|
|
#define e_fcno _u_event._e_mark.cno1
|
|
|
|
#define e_tlno _u_event._e_mark.lno2
|
|
|
|
#define e_tcno _u_event._e_mark.cno2
|
|
|
|
|
|
|
|
struct { /* Input string. */
|
|
|
|
CHAR_T *asp; /* Allocated string. */
|
|
|
|
CHAR_T *csp; /* String. */
|
|
|
|
size_t len; /* String length. */
|
|
|
|
} _e_str;
|
|
|
|
#define e_asp _u_event._e_str.asp
|
|
|
|
#define e_csp _u_event._e_str.csp
|
|
|
|
#define e_len _u_event._e_str.len
|
|
|
|
} _u_event;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _keylist {
|
|
|
|
e_key_t value; /* Special value. */
|
2013-08-11 09:44:58 +00:00
|
|
|
int ch; /* Key. */
|
1996-11-01 06:45:43 +00:00
|
|
|
} KEYLIST;
|
|
|
|
extern KEYLIST keylist[];
|
|
|
|
|
|
|
|
/* Return if more keys in queue. */
|
|
|
|
#define KEYS_WAITING(sp) ((sp)->gp->i_cnt != 0)
|
|
|
|
#define MAPPED_KEYS_WAITING(sp) \
|
|
|
|
(KEYS_WAITING(sp) && \
|
|
|
|
F_ISSET(&sp->gp->i_event[sp->gp->i_next].e_ch, CH_MAPPED))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ex/vi commands are generally separated by whitespace characters. We
|
|
|
|
* can't use the standard isspace(3) macro because it returns true for
|
2013-08-11 09:44:58 +00:00
|
|
|
* characters like ^K in the ASCII character set. The POSIX isblank(3)
|
|
|
|
* has the same problem for non-ASCII locale, so we need a standalone one.
|
1996-11-01 06:45:43 +00:00
|
|
|
*/
|
2020-09-09 07:57:59 +00:00
|
|
|
|
|
|
|
static __inline int
|
|
|
|
cmdskip(CHAR_T ch)
|
|
|
|
{
|
|
|
|
return ch == ' ' || ch == '\t';
|
|
|
|
}
|
1996-11-01 06:45:43 +00:00
|
|
|
|
|
|
|
/* The "standard" tab width, for displaying things to users. */
|
|
|
|
#define STANDARD_TAB 6
|
|
|
|
|
|
|
|
/* Various special characters, messages. */
|
|
|
|
#define CH_BSEARCH '?' /* Backward search prompt. */
|
|
|
|
#define CH_CURSOR ' ' /* Cursor character. */
|
|
|
|
#define CH_ENDMARK '$' /* End of a range. */
|
|
|
|
#define CH_EXPROMPT ':' /* Ex prompt. */
|
|
|
|
#define CH_FSEARCH '/' /* Forward search prompt. */
|
|
|
|
#define CH_HEX '\030' /* Leading hex character. */
|
|
|
|
#define CH_LITERAL '\026' /* ASCII ^V. */
|
|
|
|
#define CH_NO 'n' /* No. */
|
|
|
|
#define CH_NOT_DIGIT 'a' /* A non-isdigit() character. */
|
|
|
|
#define CH_QUIT 'q' /* Quit. */
|
|
|
|
#define CH_YES 'y' /* Yes. */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Checking for interrupts means that we look at the bit that gets set if the
|
|
|
|
* screen code supports asynchronous events, and call back into the event code
|
|
|
|
* so that non-asynchronous screens get a chance to post the interrupt.
|
|
|
|
*
|
|
|
|
* INTERRUPT_CHECK is the number of lines "operated" on before checking for
|
|
|
|
* interrupts.
|
|
|
|
*/
|
|
|
|
#define INTERRUPT_CHECK 100
|
|
|
|
#define INTERRUPTED(sp) \
|
|
|
|
(F_ISSET((sp)->gp, G_INTERRUPTED) || \
|
|
|
|
(!v_event_get(sp, NULL, 0, EC_INTERRUPT) && \
|
|
|
|
F_ISSET((sp)->gp, G_INTERRUPTED)))
|
|
|
|
#define CLR_INTERRUPT(sp) \
|
|
|
|
F_CLR((sp)->gp, G_INTERRUPTED)
|
|
|
|
|
|
|
|
/* Flags describing types of characters being requested. */
|
|
|
|
#define EC_INTERRUPT 0x001 /* Checking for interrupts. */
|
|
|
|
#define EC_MAPCOMMAND 0x002 /* Apply the command map. */
|
|
|
|
#define EC_MAPINPUT 0x004 /* Apply the input map. */
|
|
|
|
#define EC_MAPNODIGIT 0x008 /* Return to a digit. */
|
|
|
|
#define EC_QUOTED 0x010 /* Try to quote next character */
|
|
|
|
#define EC_RAW 0x020 /* Any next character. XXX: not used. */
|
|
|
|
#define EC_TIMEOUT 0x040 /* Timeout to next character. */
|
|
|
|
|
|
|
|
/* Flags describing text input special cases. */
|
|
|
|
#define TXT_ADDNEWLINE 0x00000001 /* Replay starts on a new line. */
|
|
|
|
#define TXT_AICHARS 0x00000002 /* Leading autoindent chars. */
|
|
|
|
#define TXT_ALTWERASE 0x00000004 /* Option: altwerase. */
|
|
|
|
#define TXT_APPENDEOL 0x00000008 /* Appending after EOL. */
|
|
|
|
#define TXT_AUTOINDENT 0x00000010 /* Autoindent set this line. */
|
|
|
|
#define TXT_BACKSLASH 0x00000020 /* Backslashes escape characters. */
|
|
|
|
#define TXT_BEAUTIFY 0x00000040 /* Only printable characters. */
|
|
|
|
#define TXT_BS 0x00000080 /* Backspace returns the buffer. */
|
|
|
|
#define TXT_CEDIT 0x00000100 /* Can return TERM_CEDIT. */
|
|
|
|
#define TXT_CNTRLD 0x00000200 /* Control-D is a command. */
|
|
|
|
#define TXT_CNTRLT 0x00000400 /* Control-T is an indent special. */
|
|
|
|
#define TXT_CR 0x00000800 /* CR returns the buffer. */
|
|
|
|
#define TXT_DOTTERM 0x00001000 /* Leading '.' terminates the input. */
|
|
|
|
#define TXT_EMARK 0x00002000 /* End of replacement mark. */
|
|
|
|
#define TXT_EOFCHAR 0x00004000 /* ICANON set, return EOF character. */
|
|
|
|
#define TXT_ESCAPE 0x00008000 /* Escape returns the buffer. */
|
|
|
|
#define TXT_FILEC 0x00010000 /* Option: filec. */
|
|
|
|
#define TXT_INFOLINE 0x00020000 /* Editing the info line. */
|
|
|
|
#define TXT_MAPINPUT 0x00040000 /* Apply the input map. */
|
|
|
|
#define TXT_NLECHO 0x00080000 /* Echo the newline. */
|
|
|
|
#define TXT_NUMBER 0x00100000 /* Number the line. */
|
|
|
|
#define TXT_OVERWRITE 0x00200000 /* Overwrite characters. */
|
|
|
|
#define TXT_PROMPT 0x00400000 /* Display a prompt. */
|
|
|
|
#define TXT_RECORD 0x00800000 /* Record for replay. */
|
|
|
|
#define TXT_REPLACE 0x01000000 /* Replace; don't delete overwrite. */
|
|
|
|
#define TXT_REPLAY 0x02000000 /* Replay the last input. */
|
|
|
|
#define TXT_RESOLVE 0x04000000 /* Resolve the text into the file. */
|
|
|
|
#define TXT_SEARCHINCR 0x08000000 /* Incremental search. */
|
|
|
|
#define TXT_SHOWMATCH 0x10000000 /* Option: showmatch. */
|
|
|
|
#define TXT_TTYWERASE 0x20000000 /* Option: ttywerase. */
|
|
|
|
#define TXT_WRAPMARGIN 0x40000000 /* Option: wrapmargin. */
|