1/*	$NetBSD: ex_usage.c,v 1.4 2017/12/01 20:01:31 rin Exp $ */
2/*-
3 * Copyright (c) 1992, 1993, 1994
4 *	The Regents of the University of California.  All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 *	Keith Bostic.  All rights reserved.
7 *
8 * See the LICENSE file for redistribution information.
9 */
10
11#include "config.h"
12
13#include <sys/cdefs.h>
14#if 0
15#ifndef lint
16static const char sccsid[] = "Id: ex_usage.c,v 10.15 2001/06/25 15:19:21 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:21 ";
17#endif /* not lint */
18#else
19__RCSID("$NetBSD: ex_usage.c,v 1.4 2017/12/01 20:01:31 rin Exp $");
20#endif
21
22#include <sys/types.h>
23#include <sys/queue.h>
24#include <sys/time.h>
25
26#include <bitstring.h>
27#include <ctype.h>
28#include <limits.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "../common/common.h"
34#include "../vi/vi.h"
35
36/*
37 * ex_help -- :help
38 *	Display help message.
39 *
40 * PUBLIC: int ex_help __P((SCR *, EXCMD *));
41 */
42int
43ex_help(SCR *sp, EXCMD *cmdp)
44{
45	(void)ex_puts(sp,
46	    "To see the list of vi commands, enter \":viusage<CR>\"\n");
47	(void)ex_puts(sp,
48	    "To see the list of ex commands, enter \":exusage<CR>\"\n");
49	(void)ex_puts(sp,
50	    "For an ex command usage statement enter \":exusage [cmd]<CR>\"\n");
51	(void)ex_puts(sp,
52	    "For a vi key usage statement enter \":viusage [key]<CR>\"\n");
53	(void)ex_puts(sp, "To exit, enter \":q!\"\n");
54	return (0);
55}
56
57/*
58 * ex_usage -- :exusage [cmd]
59 *	Display ex usage strings.
60 *
61 * PUBLIC: int ex_usage __P((SCR *, EXCMD *));
62 */
63int
64ex_usage(SCR *sp, EXCMD *cmdp)
65{
66	ARGS *ap;
67	EXCMDLIST const *cp;
68	int newscreen;
69	CHAR_T *p, nb[MAXCMDNAMELEN + 5];
70	const CHAR_T *name;
71
72	switch (cmdp->argc) {
73	case 1:
74		ap = cmdp->argv[0];
75		if (ISUPPER((UCHAR_T)ap->bp[0])) {
76			newscreen = 1;
77			ap->bp[0] = TOLOWER((UCHAR_T)ap->bp[0]);
78		} else
79			newscreen = 0;
80		for (cp = cmds; cp->name != NULL &&
81		    MEMCMP(ap->bp, cp->name, ap->len); ++cp);
82		if (cp->name == NULL ||
83		    (newscreen && !F_ISSET(cp, E_NEWSCREEN))) {
84			const char *nstr;
85			size_t nlen;
86
87			if (newscreen)
88				ap->bp[0] = TOUPPER((UCHAR_T)ap->bp[0]);
89
90			INT2CHAR(sp, ap->bp, ap->len + 1, nstr, nlen);
91			(void)ex_printf(sp, "The %.*s command is unknown\n",
92			    (int)ap->len, nstr);
93		} else {
94			(void)ex_printf(sp,
95			    "Command: %s\n  Usage: %s\n", cp->help, cp->usage);
96			/*
97			 * !!!
98			 * The "visual" command has two modes, one from ex,
99			 * one from the vi colon line.  Don't ask.
100			 */
101			if (cp != &cmds[C_VISUAL_EX] &&
102			    cp != &cmds[C_VISUAL_VI])
103				break;
104			if (cp == &cmds[C_VISUAL_EX])
105				cp = &cmds[C_VISUAL_VI];
106			else
107				cp = &cmds[C_VISUAL_EX];
108			(void)ex_printf(sp,
109			    "Command: %s\n  Usage: %s\n", cp->help, cp->usage);
110		}
111		break;
112	case 0:
113		for (cp = cmds; cp->name != NULL && !INTERRUPTED(sp); ++cp) {
114			/*
115			 * The ^D command has an unprintable name.
116			 *
117			 * XXX
118			 * We display both capital and lower-case versions of
119			 * the appropriate commands -- no need to add in extra
120			 * room, they're all short names.
121			 */
122			if (cp == &cmds[C_SCROLL])
123				name = L("^D");
124			else if (F_ISSET(cp, E_NEWSCREEN)) {
125				nb[0] = L('[');
126				nb[1] = TOUPPER((UCHAR_T)cp->name[0]);
127				nb[2] = cp->name[0];
128				nb[3] = L(']');
129				for (name = cp->name + 1,
130				    p = nb + 4; (*p++ = *name++) != '\0';);
131				name = nb;
132			} else
133				name = cp->name;
134			(void)ex_printf(sp,
135			    WVS": %s\n", MAXCMDNAMELEN, name, cp->help);
136		}
137		break;
138	default:
139		abort();
140	}
141	return (0);
142}
143
144/*
145 * ex_viusage -- :viusage [key]
146 *	Display vi usage strings.
147 *
148 * PUBLIC: int ex_viusage __P((SCR *, EXCMD *));
149 */
150int
151ex_viusage(SCR *sp, EXCMD *cmdp)
152{
153	VIKEYS const *kp;
154	int key;
155
156	switch (cmdp->argc) {
157	case 1:
158		if (cmdp->argv[0]->len != 1) {
159			ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
160			return (1);
161		}
162		key = cmdp->argv[0]->bp[0];
163		if (key > MAXVIKEY)
164			goto nokey;
165
166		/* Special case: '[' and ']' commands. */
167		if ((key == '[' || key == ']') && cmdp->argv[0]->bp[1] != key)
168			goto nokey;
169
170		/* Special case: ~ command. */
171		if (key == '~' && O_ISSET(sp, O_TILDEOP))
172			kp = &tmotion;
173		else
174			kp = &vikeys[key];
175
176		if (kp->usage == NULL)
177nokey:			(void)ex_printf(sp,
178			    "The %s key has no current meaning\n",
179			    KEY_NAME(sp, key));
180		else
181			(void)ex_printf(sp,
182			    "  Key:%s%s\nUsage: %s\n",
183			    isblank((unsigned char)*kp->help) ? "" : " ", kp->help, kp->usage);
184		break;
185	case 0:
186		for (key = 0; key <= MAXVIKEY && !INTERRUPTED(sp); ++key) {
187			/* Special case: ~ command. */
188			if (key == '~' && O_ISSET(sp, O_TILDEOP))
189				kp = &tmotion;
190			else
191				kp = &vikeys[key];
192			if (kp->help != NULL)
193				(void)ex_printf(sp, "%s\n", kp->help);
194		}
195		break;
196	default:
197		abort();
198	}
199	return (0);
200}
201