xref: /original-bsd/usr.bin/more/decode.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1988 Mark Nudleman
3  * Copyright (c) 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)decode.c	8.1 (Berkeley) 06/06/93";
11 #endif /* not lint */
12 
13 /*
14  * Routines to decode user commands.
15  *
16  * This is all table driven.
17  * A command table is a sequence of command descriptors.
18  * Each command descriptor is a sequence of bytes with the following format:
19  *	<c1><c2>...<cN><0><action>
20  * The characters c1,c2,...,cN are the command string; that is,
21  * the characters which the user must type.
22  * It is terminated by a null <0> byte.
23  * The byte after the null byte is the action code associated
24  * with the command string.
25  *
26  * The default commands are described by cmdtable.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/file.h>
31 #include <stdio.h>
32 #include <less.h>
33 
34 /*
35  * Command table is ordered roughly according to expected
36  * frequency of use, so the common commands are near the beginning.
37  */
38 #define	CONTROL(c)		((c)&037)
39 
40 static char cmdtable[] = {
41 	'\r',0,				A_F_LINE,
42 	'\n',0,				A_F_LINE,
43 	'j',0,				A_F_LINE,
44 	'k',0,				A_B_LINE,
45 	'd',0,				A_F_SCROLL,
46 	CONTROL('D'),0,			A_F_SCROLL,
47 	'u',0,				A_B_SCROLL,
48 	CONTROL('U'),0,			A_B_SCROLL,
49 	' ',0,				A_F_SCREEN,
50 	'f',0,				A_F_SCREEN,
51 	CONTROL('F'),0,			A_F_SCREEN,
52 	'b',0,				A_B_SCREEN,
53 	CONTROL('B'),0,			A_B_SCREEN,
54 	'R',0,				A_FREPAINT,
55 	'r',0,				A_REPAINT,
56 	CONTROL('L'),0,			A_REPAINT,
57 	'g',0,				A_GOLINE,
58 	'p',0,				A_PERCENT,
59 	'%',0,				A_PERCENT,
60 	'G',0,				A_GOEND,
61 	'0',0,				A_DIGIT,
62 	'1',0,				A_DIGIT,
63 	'2',0,				A_DIGIT,
64 	'3',0,				A_DIGIT,
65 	'4',0,				A_DIGIT,
66 	'5',0,				A_DIGIT,
67 	'6',0,				A_DIGIT,
68 	'7',0,				A_DIGIT,
69 	'8',0,				A_DIGIT,
70 	'9',0,				A_DIGIT,
71 
72 	'=',0,				A_STAT,
73 	CONTROL('G'),0,			A_STAT,
74 	'/',0,				A_F_SEARCH,
75 	'?',0,				A_B_SEARCH,
76 	'n',0,				A_AGAIN_SEARCH,
77 	'm',0,				A_SETMARK,
78 	'\'',0,				A_GOMARK,
79 	'E',0,				A_EXAMINE,
80 	'N',0,				A_NEXT_FILE,
81 	':','n',0,			A_NEXT_FILE,
82 	'P',0,				A_PREV_FILE,
83 	':','p',0,			A_PREV_FILE,
84 	'v',0,				A_VISUAL,
85 
86 	'h',0,				A_HELP,
87 	'q',0,				A_QUIT,
88 	':','q',0,			A_QUIT,
89 	':','t',0,			A_TAGFILE,
90 	':', 'a', 0,			A_FILE_LIST,
91 	'Z','Z',0,			A_QUIT,
92 };
93 
94 char *cmdendtable = cmdtable + sizeof(cmdtable);
95 
96 #define	MAX_CMDLEN	16
97 
98 static char kbuf[MAX_CMDLEN+1];
99 static char *kp = kbuf;
100 
101 /*
102  * Indicate that we're not in a prefix command
103  * by resetting the command buffer pointer.
104  */
105 noprefix()
106 {
107 	kp = kbuf;
108 }
109 
110 /*
111  * Decode a command character and return the associated action.
112  */
113 cmd_decode(c)
114 	int c;
115 {
116 	register int action = A_INVALID;
117 
118 	/*
119 	 * Append the new command character to the command string in kbuf.
120 	 */
121 	*kp++ = c;
122 	*kp = '\0';
123 
124 	action = cmd_search(cmdtable, cmdendtable);
125 
126 	/* This is not a prefix character. */
127 	if (action != A_PREFIX)
128 		noprefix();
129 	return(action);
130 }
131 
132 /*
133  * Search a command table for the current command string (in kbuf).
134  */
135 cmd_search(table, endtable)
136 	char *table;
137 	char *endtable;
138 {
139 	register char *p, *q;
140 
141 	for (p = table, q = kbuf;  p < endtable;  p++, q++) {
142 		if (*p == *q) {
143 			/*
144 			 * Current characters match.
145 			 * If we're at the end of the string, we've found it.
146 			 * Return the action code, which is the character
147 			 * after the null at the end of the string
148 			 * in the command table.
149 			 */
150 			if (*p == '\0')
151 				return(p[1]);
152 		}
153 		else if (*q == '\0') {
154 			/*
155 			 * Hit the end of the user's command,
156 			 * but not the end of the string in the command table.
157 			 * The user's command is incomplete.
158 			 */
159 			return(A_PREFIX);
160 		} else {
161 			/*
162 			 * Not a match.
163 			 * Skip ahead to the next command in the
164 			 * command table, and reset the pointer
165 			 * to the user's command.
166 			 */
167 			while (*p++ != '\0');
168 			q = kbuf-1;
169 		}
170 	}
171 	/*
172 	 * No match found in the entire command table.
173 	 */
174 	return(A_INVALID);
175 }
176