freebsd-skq/contrib/nvi/vi/v_cmd.c
peter 5f2a1d6536 Update nvi-1.79 to 2.1.1-4334a8297f
This is the gsoc-2011 project to clean up and backport multibyte support
from other nvi forks in a form we can use.

USE_WIDECHAR is on unless building for the rescue crunchgen. This should
allow editing in the native locale encoding.

USE_ICONV depends on make.conf having 'WITH_ICONV=YES' for now.  This
adds the ability to do things like edit a KOI8-R file while having $LANG
set to (say) en_US.UTF-8.  iconv is used to transcode the characters for
display.

Other points:
* It uses gencat and catopen/etc instead of homegrown msg catalog stuff.
* A lot of stuff has been trimmed out, eg: the perl and tcl bindings which
  we could never use in base anyway.
* It uses ncursesw when in widechar mode.  This could be interesting.

GSoC info: http://www.google-melange.com/gsoc/proposal/review/google/gsoc2011/zy/1
Repo at: https://github.com/lichray/nvi2

Obtained from:  Zhihao Yuan <lichray@gmail.com>
2013-08-11 20:03:12 +00:00

506 lines
12 KiB
C

/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
* Copyright (c) 1992, 1993, 1994, 1995, 1996
* Keith Bostic. All rights reserved.
*
* See the LICENSE file for redistribution information.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "$Id: v_cmd.c,v 10.9 1996/03/28 15:18:39 bostic Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/time.h>
#include <bitstring.h>
#include <limits.h>
#include <stdio.h>
#include "../common/common.h"
#include "vi.h"
/*
* This array maps keystrokes to vi command functions. It is known
* in ex/ex_usage.c that it takes four columns to name a vi character.
*/
VIKEYS const vikeys [MAXVIKEY + 1] = {
/* 000 NUL -- The code in vi.c expects key 0 to be undefined. */
{NULL},
/* 001 ^A */
{v_searchw, V_ABS|V_CNT|V_MOVE|V_KEYW|VM_CUTREQ|VM_RCM_SET,
"[count]^A",
"^A search forward for cursor word"},
/* 002 ^B */
{v_pageup, V_CNT|VM_RCM_SET,
"[count]^B",
"^B scroll up by screens"},
/* 003 ^C */
{NULL, 0,
"^C",
"^C interrupt an operation (e.g. read, write, search)"},
/* 004 ^D */
{v_hpagedown, V_CNT|VM_RCM_SET,
"[count]^D",
"^D scroll down by half screens (setting count)"},
/* 005 ^E */
{v_linedown, V_CNT,
"[count]^E",
"^E scroll down by lines"},
/* 006 ^F */
{v_pagedown, V_CNT|VM_RCM_SET,
"[count]^F",
"^F scroll down by screens"},
/* 007 ^G */
{v_status, 0,
"^G",
"^G file status"},
/* 010 ^H */
{v_left, V_CNT|V_MOVE|VM_RCM_SET,
"[count]^H",
"^H move left by characters"},
/* 011 ^I */
{NULL},
/* 012 ^J */
{v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM,
"[count]^J",
"^J move down by lines"},
/* 013 ^K */
{NULL},
/* 014 ^L */
{v_redraw, 0,
"^L",
"^L redraw screen"},
/* 015 ^M */
{v_cr, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
"[count]^M",
"^M move down by lines (to first non-blank)"},
/* 016 ^N */
{v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM,
"[count]^N",
"^N move down by lines"},
/* 017 ^O */
{NULL},
/* 020 ^P */
{v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM,
"[count]^P",
"^P move up by lines"},
/* 021 ^Q -- same as ^V if not used for hardware flow control. */
{NULL},
/* 022 ^R */
{v_redraw, 0,
"^R",
"^R redraw screen"},
/* 023 ^S -- not available, used for hardware flow control. */
{NULL},
/* 024 ^T */
{v_tagpop, V_ABS|VM_RCM_SET,
"^T",
"^T tag pop"},
/* 025 ^U */
{v_hpageup, V_CNT|VM_RCM_SET,
"[count]^U",
"^U half page up (set count)"},
/* 026 ^V */
{NULL, 0,
"^V",
"^V input a literal character"},
/* 027 ^W */
{v_screen, 0,
"^W",
"^W move to next screen"},
/* 030 ^X */
{NULL},
/* 031 ^Y */
{v_lineup, V_CNT,
"[count]^Y",
"^Y page up by lines"},
/* 032 ^Z */
{v_suspend, V_SECURE,
"^Z",
"^Z suspend editor"},
/* 033 ^[ */
{NULL, 0,
"^[ <escape>",
"^[ <escape> exit input mode, cancel partial commands"},
/* 034 ^\ */
{v_exmode, 0,
"^\\",
" ^\\ switch to ex mode"},
/* 035 ^] */
{v_tagpush, V_ABS|V_KEYW|VM_RCM_SET,
"^]",
"^] tag push cursor word"},
/* 036 ^^ */
{v_switch, 0,
"^^",
"^^ switch to previous file"},
/* 037 ^_ */
{NULL},
/* 040 ' ' */
{v_right, V_CNT|V_MOVE|VM_RCM_SET,
"[count]' '",
" <space> move right by columns"},
/* 041 ! */
{v_filter, V_CNT|V_DOT|V_MOTION|V_SECURE|VM_RCM_SET,
"[count]![count]motion command(s)",
" ! filter through command(s) to motion"},
/* 042 " */
{NULL},
/* 043 # */
{v_increment, V_CHAR|V_CNT|V_DOT|VM_RCM_SET,
"[count]# +|-|#",
" # number increment/decrement"},
/* 044 $ */
{v_dollar, V_CNT|V_MOVE|VM_RCM_SETLAST,
" [count]$",
" $ move to last column"},
/* 045 % */
{v_match, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"%",
" % move to match"},
/* 046 & */
{v_again, 0,
"&",
" & repeat substitution"},
/* 047 ' */
{v_fmark, V_ABS_L|V_CHAR|V_MOVE|VM_LMODE|VM_RCM_SET,
"'['a-z]",
" ' move to mark (to first non-blank)"},
/* 050 ( */
{v_sentenceb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"[count](",
" ( move back sentence"},
/* 051 ) */
{v_sentencef, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"[count])",
" ) move forward sentence"},
/* 052 * */
{NULL},
/* 053 + */
{v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
"[count]+",
" + move down by lines (to first non-blank)"},
/* 054 , */
{v_chrrepeat, V_CNT|V_MOVE|VM_RCM_SET,
"[count],",
" , reverse last F, f, T or t search"},
/* 055 - */
{v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
"[count]-",
" - move up by lines (to first non-blank)"},
/* 056 . */
{NULL, 0,
".",
" . repeat the last command"},
/* 057 / */
{v_searchf, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"/RE[/ offset]",
" / search forward"},
/* 060 0 */
{v_zero, V_MOVE|VM_RCM_SET,
"0",
" 0 move to first character"},
/* 061 1 */
{NULL},
/* 062 2 */
{NULL},
/* 063 3 */
{NULL},
/* 064 4 */
{NULL},
/* 065 5 */
{NULL},
/* 066 6 */
{NULL},
/* 067 7 */
{NULL},
/* 070 8 */
{NULL},
/* 071 9 */
{NULL},
/* 072 : */
{v_ex, 0,
":command [| command] ...",
" : ex command"},
/* 073 ; */
{v_chrepeat, V_CNT|V_MOVE|VM_RCM_SET,
"[count];",
" ; repeat last F, f, T or t search"},
/* 074 < */
{v_shiftl, V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
"[count]<[count]motion",
" < shift lines left to motion"},
/* 075 = */
{NULL},
/* 076 > */
{v_shiftr, V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
"[count]>[count]motion",
" > shift lines right to motion"},
/* 077 ? */
{v_searchb, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"?RE[? offset]",
" ? search backward"},
/* 100 @ */
{v_at, V_CNT|V_RBUF|VM_RCM_SET,
"@buffer",
" @ execute buffer"},
/* 101 A */
{v_iA, V_CNT|V_DOT|VM_RCM_SET,
"[count]A",
" A append to the line"},
/* 102 B */
{v_wordB, V_CNT|V_MOVE|VM_RCM_SET,
"[count]B",
" B move back bigword"},
/* 103 C */
{NULL, 0,
"[buffer][count]C",
" C change to end-of-line"},
/* 104 D */
{NULL, 0,
"[buffer]D",
" D delete to end-of-line"},
/* 105 E */
{v_wordE, V_CNT|V_MOVE|VM_RCM_SET,
"[count]E",
" E move to end of bigword"},
/* 106 F */
{v_chF, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
"[count]F character",
" F character in line backward search"},
/* 107 G */
{v_lgoto, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
"[count]G",
" G move to line"},
/* 110 H */
{v_home, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
"[count]H",
" H move to count lines from screen top"},
/* 111 I */
{v_iI, V_CNT|V_DOT|VM_RCM_SET,
"[count]I",
" I insert before first nonblank"},
/* 112 J */
{v_join, V_CNT|V_DOT|VM_RCM_SET,
"[count]J",
" J join lines"},
/* 113 K */
{NULL},
/* 114 L */
{v_bottom, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
"[count]L",
" L move to screen bottom"},
/* 115 M */
{v_middle, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
"M",
" M move to screen middle"},
/* 116 N */
{v_searchN, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"n",
" N reverse last search"},
/* 117 O */
{v_iO, V_CNT|V_DOT|VM_RCM_SET,
"[count]O",
" O insert above line"},
/* 120 P */
{v_Put, V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
"[buffer]P",
" P insert before cursor from buffer"},
/* 121 Q */
{v_exmode, 0,
"Q",
" Q switch to ex mode"},
/* 122 R */
{v_Replace, V_CNT|V_DOT|VM_RCM_SET,
"[count]R",
" R replace characters"},
/* 123 S */
{NULL, 0,
"[buffer][count]S",
" S substitute for the line(s)"},
/* 124 T */
{v_chT, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
"[count]T character",
" T before character in line backward search"},
/* 125 U */
{v_Undo, VM_RCM_SET,
"U",
" U Restore the current line"},
/* 126 V */
{NULL},
/* 127 W */
{v_wordW, V_CNT|V_MOVE|VM_RCM_SET,
"[count]W",
" W move to next bigword"},
/* 130 X */
{v_Xchar, V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
"[buffer][count]X",
" X delete character before cursor"},
/* 131 Y */
{NULL, 0,
"[buffer][count]Y",
" Y copy line"},
/* 132 Z */
{v_zexit, 0,
"ZZ",
"ZZ save file and exit"},
/* 133 [ */
{v_sectionb, V_ABS|V_CNT|V_MOVE|VM_RCM_SET,
"[[",
"[[ move back section"},
/* 134 \ */
{NULL},
/* 135 ] */
{v_sectionf, V_ABS|V_CNT|V_MOVE|VM_RCM_SET,
"]]",
"]] move forward section"},
/* 136 ^ */
/*
* DON'T set the VM_RCM_SETFNB flag, the function has to do the work
* anyway, in case it's a motion component. DO set VM_RCM_SET, so
* that any motion that's part of a command is preserved.
*/
{v_first, V_CNT|V_MOVE|VM_RCM_SET,
"^",
" ^ move to first non-blank"},
/* 137 _ */
/*
* Needs both to set the VM_RCM_SETFNB flag, and to do the work
* in the function, in case it's a delete.
*/
{v_cfirst, V_CNT|V_MOVE|VM_RCM_SETFNB,
"_",
" _ move to first non-blank"},
/* 140 ` */
{v_bmark, V_ABS_C|V_CHAR|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"`[`a-z]",
" ` move to mark"},
/* 141 a */
{v_ia, V_CNT|V_DOT|VM_RCM_SET,
"[count]a",
" a append after cursor"},
/* 142 b */
{v_wordb, V_CNT|V_MOVE|VM_RCM_SET,
"[count]b",
" b move back word"},
/* 143 c */
{v_change, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
"[buffer][count]c[count]motion",
" c change to motion"},
/* 144 d */
{v_delete, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
"[buffer][count]d[count]motion",
" d delete to motion"},
/* 145 e */
{v_worde, V_CNT|V_MOVE|VM_RCM_SET,
"[count]e",
" e move to end of word"},
/* 146 f */
{v_chf, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
"[count]f character",
" f character in line forward search"},
/* 147 g */
{NULL},
/* 150 h */
{v_left, V_CNT|V_MOVE|VM_RCM_SET,
"[count]h",
" h move left by columns"},
/* 151 i */
{v_ii, V_CNT|V_DOT|VM_RCM_SET,
"[count]i",
" i insert before cursor"},
/* 152 j */
{v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM,
"[count]j",
" j move down by lines"},
/* 153 k */
{v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM,
"[count]k",
" k move up by lines"},
/* 154 l */
{v_right, V_CNT|V_MOVE|VM_RCM_SET,
"[count]l",
" l move right by columns"},
/* 155 m */
{v_mark, V_CHAR,
"m[a-z]",
" m set mark"},
/* 156 n */
{v_searchn, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"n",
" n repeat last search"},
/* 157 o */
{v_io, V_CNT|V_DOT|VM_RCM_SET,
"[count]o",
" o append after line"},
/* 160 p */
{v_put, V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
"[buffer]p",
" p insert after cursor from buffer"},
/* 161 q */
{NULL},
/* 162 r */
{v_replace, V_CNT|V_DOT|VM_RCM_SET,
"[count]r character",
" r replace character"},
/* 163 s */
{v_subst, V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
"[buffer][count]s",
" s substitute character"},
/* 164 t */
{v_cht, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
"[count]t character",
" t before character in line forward search"},
/* 165 u */
/*
* DON'T set the V_DOT flag, it' more complicated than that.
* See vi/vi.c for details.
*/
{v_undo, VM_RCM_SET,
"u",
" u undo last change"},
/* 166 v */
{NULL},
/* 167 w */
{v_wordw, V_CNT|V_MOVE|VM_RCM_SET,
"[count]w",
" w move to next word"},
/* 170 x */
{v_xchar, V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
"[buffer][count]x",
" x delete character"},
/* 171 y */
{v_yank, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
"[buffer][count]y[count]motion",
" y copy text to motion into a cut buffer"},
/* 172 z */
/*
* DON'T set the V_CHAR flag, the char isn't required,
* so it's handled specially in getcmd().
*/
{v_z, V_ABS_L|V_CNT|VM_RCM_SETFNB,
"[line]z[window_size][-|.|+|^|<CR>]",
" z reposition the screen"},
/* 173 { */
{v_paragraphb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"[count]{",
" { move back paragraph"},
/* 174 | */
{v_ncol, V_CNT|V_MOVE|VM_RCM_SET,
"[count]|",
" | move to column"},
/* 175 } */
{v_paragraphf, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"[count]}",
" } move forward paragraph"},
/* 176 ~ */
{v_ulcase, V_CNT|V_DOT|VM_RCM_SET,
"[count]~",
" ~ reverse case"},
};