Home | History | Annotate | Line # | Download | only in more
decode.c revision 1.4
      1 /*	$NetBSD: decode.c,v 1.4 2003/08/07 09:27:59 agc Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Copyright (c) 1988 Mark Nudleman
     34  *
     35  * Redistribution and use in source and binary forms, with or without
     36  * modification, are permitted provided that the following conditions
     37  * are met:
     38  * 1. Redistributions of source code must retain the above copyright
     39  *    notice, this list of conditions and the following disclaimer.
     40  * 2. Redistributions in binary form must reproduce the above copyright
     41  *    notice, this list of conditions and the following disclaimer in the
     42  *    documentation and/or other materials provided with the distribution.
     43  * 3. All advertising materials mentioning features or use of this software
     44  *    must display the following acknowledgement:
     45  *	This product includes software developed by the University of
     46  *	California, Berkeley and its contributors.
     47  * 4. Neither the name of the University nor the names of its contributors
     48  *    may be used to endorse or promote products derived from this software
     49  *    without specific prior written permission.
     50  *
     51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     61  * SUCH DAMAGE.
     62  */
     63 
     64 #include <sys/cdefs.h>
     65 #ifndef lint
     66 #if 0
     67 static char sccsid[] = "@(#)decode.c	8.1 (Berkeley) 6/6/93";
     68 #else
     69 __RCSID("$NetBSD: decode.c,v 1.4 2003/08/07 09:27:59 agc Exp $");
     70 #endif
     71 #endif /* not lint */
     72 
     73 /*
     74  * Routines to decode user commands.
     75  *
     76  * This is all table driven.
     77  * A command table is a sequence of command descriptors.
     78  * Each command descriptor is a sequence of bytes with the following format:
     79  *	<c1><c2>...<cN><0><action>
     80  * The characters c1,c2,...,cN are the command string; that is,
     81  * the characters which the user must type.
     82  * It is terminated by a null <0> byte.
     83  * The byte after the null byte is the action code associated
     84  * with the command string.
     85  *
     86  * The default commands are described by cmdtable.
     87  */
     88 
     89 #include <sys/param.h>
     90 #include <sys/file.h>
     91 #include <stdio.h>
     92 
     93 #include "less.h"
     94 #include "extern.h"
     95 
     96 /*
     97  * Command table is ordered roughly according to expected
     98  * frequency of use, so the common commands are near the beginning.
     99  */
    100 #define	CONTROL(c)		((c)&037)
    101 
    102 static char cmdtable[] = {
    103 	'\r',0,				A_F_LINE,
    104 	'\n',0,				A_F_LINE,
    105 	'j',0,				A_F_LINE,
    106 	'k',0,				A_B_LINE,
    107 	'd',0,				A_F_SCROLL,
    108 	CONTROL('D'),0,			A_F_SCROLL,
    109 	'u',0,				A_B_SCROLL,
    110 	CONTROL('U'),0,			A_B_SCROLL,
    111 	' ',0,				A_F_SCREEN,
    112 	'f',0,				A_F_SCREEN,
    113 	CONTROL('F'),0,			A_F_SCREEN,
    114 	'b',0,				A_B_SCREEN,
    115 	CONTROL('B'),0,			A_B_SCREEN,
    116 	'R',0,				A_FREPAINT,
    117 	'r',0,				A_REPAINT,
    118 	CONTROL('L'),0,			A_REPAINT,
    119 	'g',0,				A_GOLINE,
    120 	'p',0,				A_PERCENT,
    121 	'%',0,				A_PERCENT,
    122 	'G',0,				A_GOEND,
    123 	'0',0,				A_DIGIT,
    124 	'1',0,				A_DIGIT,
    125 	'2',0,				A_DIGIT,
    126 	'3',0,				A_DIGIT,
    127 	'4',0,				A_DIGIT,
    128 	'5',0,				A_DIGIT,
    129 	'6',0,				A_DIGIT,
    130 	'7',0,				A_DIGIT,
    131 	'8',0,				A_DIGIT,
    132 	'9',0,				A_DIGIT,
    133 
    134 	'=',0,				A_STAT,
    135 	CONTROL('G'),0,			A_STAT,
    136 	'/',0,				A_F_SEARCH,
    137 	'?',0,				A_B_SEARCH,
    138 	'n',0,				A_AGAIN_SEARCH,
    139 	'm',0,				A_SETMARK,
    140 	'\'',0,				A_GOMARK,
    141 	'E',0,				A_EXAMINE,
    142 	'N',0,				A_NEXT_FILE,
    143 	':','n',0,			A_NEXT_FILE,
    144 	'P',0,				A_PREV_FILE,
    145 	':','p',0,			A_PREV_FILE,
    146 	'v',0,				A_VISUAL,
    147 
    148 	'h',0,				A_HELP,
    149 	'q',0,				A_QUIT,
    150 	':','q',0,			A_QUIT,
    151 	':','t',0,			A_TAGFILE,
    152 	':', 'a', 0,			A_FILE_LIST,
    153 	'Z','Z',0,			A_QUIT,
    154 };
    155 
    156 char *cmdendtable = cmdtable + sizeof(cmdtable);
    157 
    158 #define	MAX_CMDLEN	16
    159 
    160 static char kbuf[MAX_CMDLEN+1];
    161 static char *kp = kbuf;
    162 
    163 /*
    164  * Indicate that we're not in a prefix command
    165  * by resetting the command buffer pointer.
    166  */
    167 void
    168 noprefix()
    169 {
    170 	kp = kbuf;
    171 }
    172 
    173 /*
    174  * Decode a command character and return the associated action.
    175  */
    176 int
    177 cmd_decode(c)
    178 	int c;
    179 {
    180 	int action = A_INVALID;
    181 
    182 	/*
    183 	 * Append the new command character to the command string in kbuf.
    184 	 */
    185 	*kp++ = c;
    186 	*kp = '\0';
    187 
    188 	action = cmd_search(cmdtable, cmdendtable);
    189 
    190 	/* This is not a prefix character. */
    191 	if (action != A_PREFIX)
    192 		noprefix();
    193 	return(action);
    194 }
    195 
    196 /*
    197  * Search a command table for the current command string (in kbuf).
    198  */
    199 int
    200 cmd_search(table, endtable)
    201 	char *table;
    202 	char *endtable;
    203 {
    204 	char *p, *q;
    205 
    206 	for (p = table, q = kbuf;  p < endtable;  p++, q++) {
    207 		if (*p == *q) {
    208 			/*
    209 			 * Current characters match.
    210 			 * If we're at the end of the string, we've found it.
    211 			 * Return the action code, which is the character
    212 			 * after the null at the end of the string
    213 			 * in the command table.
    214 			 */
    215 			if (*p == '\0')
    216 				return(p[1]);
    217 		}
    218 		else if (*q == '\0') {
    219 			/*
    220 			 * Hit the end of the user's command,
    221 			 * but not the end of the string in the command table.
    222 			 * The user's command is incomplete.
    223 			 */
    224 			return(A_PREFIX);
    225 		} else {
    226 			/*
    227 			 * Not a match.
    228 			 * Skip ahead to the next command in the
    229 			 * command table, and reset the pointer
    230 			 * to the user's command.
    231 			 */
    232 			while (*p++ != '\0');
    233 			q = kbuf-1;
    234 		}
    235 	}
    236 	/*
    237 	 * No match found in the entire command table.
    238 	 */
    239 	return(A_INVALID);
    240 }
    241