remove mention of lesskey
[unix-history] / usr / src / usr.bin / more / decode.c
CommitLineData
bfe13c81
KB
1/*
2 * Copyright (c) 1988 Mark Nudleman
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
bfe13c81
KB
6 * Redistribution and use in source and binary forms are permitted
7 * provided that the above copyright notice and this paragraph are
8 * duplicated in all such forms and that any documentation,
9 * advertising materials, and other materials related to such
10 * distribution and use acknowledge that the software was developed
a942b40b
KB
11 * by Mark Nudleman and the University of California, Berkeley. The
12 * name of Mark Nudleman or the
bfe13c81
KB
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20#ifndef lint
a942b40b 21static char sccsid[] = "@(#)decode.c 5.4 (Berkeley) %G%";
bfe13c81
KB
22#endif /* not lint */
23
24/*
25 * Routines to decode user commands.
26 *
27 * This is all table driven.
28 * A command table is a sequence of command descriptors.
29 * Each command descriptor is a sequence of bytes with the following format:
30 * <c1><c2>...<cN><0><action>
31 * The characters c1,c2,...,cN are the command string; that is,
32 * the characters which the user must type.
33 * It is terminated by a null <0> byte.
34 * The byte after the null byte is the action code associated
35 * with the command string.
36 *
37 * The default commands are described by cmdtable.
38 * User-defined commands are read into usertable.
39 */
40
41#include "less.h"
42#include "cmd.h"
43
44/*
45 * Command table is ordered roughly according to expected
46 * frequency of use, so the common commands are near the beginning.
47 */
48static char cmdtable[] =
49{
50 '\r',0, A_F_LINE,
51 '\n',0, A_F_LINE,
52 'e',0, A_F_LINE,
53 'j',0, A_F_LINE,
54 CONTROL('E'),0, A_F_LINE,
55 CONTROL('N'),0, A_F_LINE,
56 'k',0, A_B_LINE,
57 'y',0, A_B_LINE,
58 CONTROL('Y'),0, A_B_LINE,
59 CONTROL('K'),0, A_B_LINE,
60 CONTROL('P'),0, A_B_LINE,
61 'd',0, A_F_SCROLL,
62 CONTROL('D'),0, A_F_SCROLL,
63 'u',0, A_B_SCROLL,
64 CONTROL('U'),0, A_B_SCROLL,
65 ' ',0, A_F_SCREEN,
66 'f',0, A_F_SCREEN,
67 CONTROL('F'),0, A_F_SCREEN,
68 CONTROL('V'),0, A_F_SCREEN,
69 'b',0, A_B_SCREEN,
70 CONTROL('B'),0, A_B_SCREEN,
71 CONTROL('['),'v',0, A_B_SCREEN,
72 'R',0, A_FREPAINT,
73 'r',0, A_REPAINT,
74 CONTROL('R'),0, A_REPAINT,
75 CONTROL('L'),0, A_REPAINT,
76 'g',0, A_GOLINE,
77 '<',0, A_GOLINE,
78 CONTROL('['),'<',0, A_GOLINE,
79 'p',0, A_PERCENT,
80 '%',0, A_PERCENT,
81 'G',0, A_GOEND,
82 CONTROL('['),'>',0, A_GOEND,
83 '>',0, A_GOEND,
84
85 '0',0, A_DIGIT,
86 '1',0, A_DIGIT,
87 '2',0, A_DIGIT,
88 '3',0, A_DIGIT,
89 '4',0, A_DIGIT,
90 '5',0, A_DIGIT,
91 '6',0, A_DIGIT,
92 '7',0, A_DIGIT,
93 '8',0, A_DIGIT,
94 '9',0, A_DIGIT,
95
96 '=',0, A_STAT,
97 CONTROL('G'),0, A_STAT,
98 '/',0, A_F_SEARCH,
99 '?',0, A_B_SEARCH,
100 'n',0, A_AGAIN_SEARCH,
101 'm',0, A_SETMARK,
102 '\'',0, A_GOMARK,
103 CONTROL('X'),CONTROL('X'),0, A_GOMARK,
104 'E',0, A_EXAMINE,
105 ':','e',0, A_EXAMINE,
106 CONTROL('X'),CONTROL('V'),0, A_EXAMINE,
107 'N',0, A_NEXT_FILE,
108 'P',0, A_PREV_FILE,
109 ':','n',0, A_NEXT_FILE,
110 ':','p',0, A_PREV_FILE,
111 '-',0, A_TOGGLE_OPTION,
112 '_',0, A_DISP_OPTION,
113 'v',0, A_VISUAL,
114 '!',0, A_SHELL,
115 '+',0, A_FIRSTCMD,
116
117 'H',0, A_HELP,
118 'h',0, A_HELP,
119 'V',0, A_VERSION,
120 'q',0, A_QUIT,
121 ':','q',0, A_QUIT,
122 'Z','Z',0, A_QUIT
123};
124
125char *cmdendtable = cmdtable + sizeof(cmdtable);
126
127static char usertable[MAX_USERCMD];
128char *userendtable = usertable;
129
130static char kbuf[MAX_CMDLEN+1];
131static char *kp = kbuf;
132
133/*
134 * Decode a command character and return the associated action.
135 */
136 public int
137cmd_decode(c)
138 int c;
139{
140 register int action = A_INVALID;
141
142 /*
143 * Append the new command character to the command string in kbuf.
144 */
145 *kp++ = c;
146 *kp = '\0';
147
bfe13c81
KB
148 /*
149 * Look first for any user-defined commands.
150 */
151 action = cmd_search(usertable, userendtable);
bfe13c81
KB
152 /*
153 * If didn't find user-defined command,
154 * try the normal default commands.
155 */
156 if (action == A_INVALID)
157 action = cmd_search(cmdtable, cmdendtable);
158
159 if (action != A_PREFIX)
160 /*
161 * This is not a prefix character.
162 */
163 noprefix();
164
165 return (action);
166}
167
168/*
169 * Indicate that we're not in a prefix command
170 * by resetting the command buffer pointer.
171 */
172 public void
173noprefix()
174{
175 kp = kbuf;
176}
177
178/*
179 * Search a command table for the current command string (in kbuf).
180 */
181 static int
182cmd_search(table, endtable)
183 char *table;
184 char *endtable;
185{
186 register char *p;
187 register char *q;
188
189 for (p = table, q = kbuf; p < endtable; p++, q++)
190 {
191 if (*p == *q)
192 {
193 /*
194 * Current characters match.
195 * If we're at the end of the string, we've found it.
196 * Return the action code, which is the character
197 * after the null at the end of the string
198 * in the command table.
199 */
200 if (*p == '\0')
201 return (p[1]);
202 } else if (*q == '\0')
203 {
204 /*
205 * Hit the end of the user's command,
206 * but not the end of the string in the command table.
207 * The user's command is incomplete.
208 */
209 return (A_PREFIX);
210 } else
211 {
212 /*
213 * Not a match.
214 * Skip ahead to the next command in the
215 * command table, and reset the pointer
216 * to the user's command.
217 */
218 while (*p++ != '\0') ;
219 q = kbuf-1;
220 }
221 }
222 /*
223 * No match found in the entire command table.
224 */
225 return (A_INVALID);
226}
227
228/*
229 * Initialize the user command table.
230 */
231 public void
232init_cmd()
233{
bfe13c81
KB
234 char *homedir;
235 int f;
236 int n;
e60bf546 237 char filename[MAXPATHLEN];
bfe13c81
KB
238 extern char *getenv();
239
240 /*
241 * Try to open "$HOME/.less"
242 * If we can't, return without doing anything.
243 */
244 homedir = getenv("HOME");
245 if (homedir == NULL)
246 return;
e60bf546
KB
247 (void)sprintf(filename, "%s/%s", homedir, ".less");
248 f = open(filename, O_RDONLY);
bfe13c81
KB
249 if (f < 0)
250 return;
251
252 /*
253 * Read the file into the user table.
254 * {{ Minimal error checking is done here.
255 * A garbage .less file will produce strange results.
256 * To avoid a large amount of error checking code here, we
257 * rely on the lesskey program to generate a good .less file. }}
258 */
259 n = read(f, (char *)usertable, MAX_USERCMD);
260 if (n < 3 || usertable[n-2] != '\0')
261 {
262 /*
263 * Several error cases are lumped together here:
264 * - Cannot read user file (n < 0).
265 * - User file is too short (a valid file must
266 * have at least 3 chars: one char command string,
267 * the terminating null byte, and the action byte).
268 * - The final entry in the user file is bad (it
269 * doesn't have a null byte in the proper place).
270 * Many other error cases are not caught, such as
271 * invalid format in any except the last entry,
272 * invalid action codes, command strings too long, etc.
273 */
274 error("invalid user key file");
275 n = 0;
276 }
277 userendtable = usertable + n;
278 close(f);
bfe13c81 279}