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