Annotation of othersrc/dist/cdk/demos/command.c, revision 1.1.1.1
1.1 garbled 1: #include <cdk.h>
2:
3: #ifdef HAVE_XCURSES
4: char *XCursesProgramName="command";
5: #endif
6:
7: /* Define some global variables. */
8: #define MAXHISTORY 5000
9: char *introductionMessage[] = {"<C></B/16>Little Command Interface", "",
10: "<C>Written by Mike Glover", "",
11: "<C>Type </B>help<!B> to get help."};
12:
13: /* This structure is used for keeping command history. */
14: struct history_st {
15: int count;
16: int current;
17: char *command[MAXHISTORY];
18: };
19:
20: /* Define some local prototypes. */
21: char *uc (char *word);
22: void help (CDKENTRY *entry);
23: static BINDFN_PROTO(historyUpCB);
24: static BINDFN_PROTO(historyDownCB);
25: static BINDFN_PROTO(viewHistoryCB);
26: static BINDFN_PROTO(listHistoryCB);
27: static BINDFN_PROTO(jumpWindowCB);
28:
29: /*
30: * Written by: Mike Glover
31: * Purpose:
32: * This creates a very simple command interface.
33: */
34: int main(int argc, char **argv)
35: {
36: /* Declare variables. */
37: CDKSCREEN *cdkscreen = 0;
38: CDKSWINDOW *commandOutput = 0;
39: CDKENTRY *commandEntry = 0;
40: WINDOW *cursesWin = 0;
41: chtype *convert = 0;
42: char *command = 0;
43: char *upper = 0;
44: char *prompt = "</B/24>Command >";
45: char *title = "<C></B/5>Command Output Window";
46: int promptLen = 0;
47: int commandFieldWidth = 0;
48: struct history_st history;
49: char temp[600];
50: int ret, junk;
51:
52: /* Set up the history. */
53: history.current = 0;
54: history.count = 0;
55:
56: /* Check the command line for options. */
57: while (1)
58: {
59: /* Are there any more command line options to parse. */
60: if ((ret = getopt (argc, argv, "t:p:")) == -1)
61: {
62: break;
63: }
64: switch (ret)
65: {
66: case 'p':
67: prompt = copyChar (optarg);
68: break;
69:
70: case 't':
71: title = copyChar (optarg);
72: break;
73:
74: default:
75: break;
76: }
77: }
78:
79: /* Set up CDK. */
80: cursesWin = initscr();
81: cdkscreen = initCDKScreen (cursesWin);
82:
83: /* Start color. */
84: initCDKColor();
85:
86: /* Create the scrolling window. */
87: commandOutput = newCDKSwindow (cdkscreen, CENTER, TOP, -4, -2,
88: title, 1000, TRUE, TRUE);
89:
90: /* Convert the prompt to a chtype and determine its length. */
91: convert = char2Chtype (prompt, &promptLen, &junk);
92: commandFieldWidth = COLS - promptLen - 4;
93: freeChtype (convert);
94:
95: /* Create the entry field. */
96: commandEntry = newCDKEntry (cdkscreen, CENTER, BOTTOM,
97: 0, prompt, A_BOLD|COLOR_PAIR(8), COLOR_PAIR(24)|'_',
98: vMIXED, commandFieldWidth, 1, 512, FALSE, FALSE);
99:
100: /* Create the key bindings. */
101: bindCDKObject (vENTRY, commandEntry, KEY_UP, historyUpCB, &history);
102: bindCDKObject (vENTRY, commandEntry, KEY_DOWN, historyDownCB, &history);
103: bindCDKObject (vENTRY, commandEntry, TAB, viewHistoryCB, commandOutput);
104: bindCDKObject (vENTRY, commandEntry, CONTROL('^'), listHistoryCB, &history);
105: bindCDKObject (vENTRY, commandEntry, CONTROL('G'), jumpWindowCB, commandOutput);
106: bindCDKObject (vENTRY, commandEntry, KEY_PPAGE, jumpWindowCB, commandOutput);
107: bindCDKObject (vENTRY, commandEntry, KEY_NPAGE, jumpWindowCB, commandOutput);
108:
109: /* Draw the screen. */
110: refreshCDKScreen (cdkscreen);
111:
112: /* Show them who wrote this and how to get help. */
113: popupLabel (cdkscreen, introductionMessage, 5);
114: eraseCDKEntry (commandEntry);
115:
116: /* Do this forever. */
117: for (;;)
118: {
119: /* Get the command. */
120: drawCDKEntry (commandEntry, ObjOf(commandEntry)->box);
121: command = activateCDKEntry (commandEntry, 0);
122:
123: if (commandEntry->exitType == vESCAPE_HIT)
124: {
125: break;
126: }
127:
128: upper = uc (command);
129:
130: /* Check the output of the command. */
131: if (strcmp (upper, "QUIT") == 0 ||
132: strcmp (upper, "EXIT") == 0 ||
133: strcmp (upper, "Q") == 0 ||
134: strcmp (upper, "E") == 0)
135: {
136: break;
137: }
138: else if (strcmp (command, "clear") == 0)
139: {
140: /* Keep the history. */
141: history.command[history.count] = copyChar (command);
142: history.count++;
143: history.current = history.count;
144:
145: cleanCDKSwindow (commandOutput);
146: cleanCDKEntry (commandEntry);
147: }
148: else if (strcmp (command, "history") == 0)
149: {
150: /* Display the history list. */
151: listHistoryCB (vENTRY, commandEntry, &history, 0);
152:
153: /* Keep the history. */
154: history.command[history.count] = copyChar (command);
155: history.count++;
156: history.current = history.count;
157: }
158: else if (strcmp (command, "help") == 0)
159: {
160: /* Keep the history. */
161: history.command[history.count] = copyChar (command);
162: history.count++;
163: history.current = history.count;
164:
165: /* Display the help. */
166: help (commandEntry);
167:
168: /* Clean the entry field. */
169: cleanCDKEntry (commandEntry);
170: eraseCDKEntry (commandEntry);
171: }
172: else
173: {
174: /* Keep the history. */
175: history.command[history.count] = copyChar (command);
176: history.count++;
177: history.current = history.count;
178:
179: /* Jump to the bottom of the scrolling window. */
180: jumpToLineCDKSwindow (commandOutput, BOTTOM);
181:
182: /* Insert a line providing the command. */
183: sprintf (temp, "Command: </R>%s", command);
184: addCDKSwindow (commandOutput, temp, BOTTOM);
185:
186: /* Run the command. */
187: execCDKSwindow (commandOutput, command, BOTTOM);
188:
189: /* Clean out the entry field. */
190: cleanCDKEntry (commandEntry);
191: }
192:
193: /* Clean up a little. */
194: freeChar (upper);
195: }
196:
197: /* All done. */
198: destroyCDKEntry (commandEntry);
199: destroyCDKSwindow (commandOutput);
200: delwin (cursesWin);
201: freeChar (upper);
202: endCDK();
203: exit (0);
204: }
205:
206: /*
207: * This is the callback for the down arrow.
208: */
209: static void historyUpCB (EObjectType cdktype GCC_UNUSED, void *object, void *clientData, chtype key GCC_UNUSED)
210: {
211: CDKENTRY *entry = (CDKENTRY *)object;
212: struct history_st *history = (struct history_st *) clientData;
213:
214: /* Make sure we don't go out of bounds. */
215: if (history->current == 0)
216: {
217: Beep();
218: return;
219: }
220:
221: /* Decrement the counter. */
222: history->current--;
223:
224: /* Display the command. */
225: setCDKEntryValue (entry, history->command[history->current]);
226: drawCDKEntry (entry, ObjOf(entry)->box);
227: }
228:
229: /*
230: * This is the callback for the down arrow.
231: */
232: static void historyDownCB (EObjectType cdktype GCC_UNUSED, void *object, void *clientData, chtype key GCC_UNUSED)
233: {
234: CDKENTRY *entry = (CDKENTRY *)object;
235: struct history_st *history = (struct history_st *) clientData;
236:
237: /* Make sure we don't go out of bounds. */
238: if (history->current == history->count)
239: {
240: Beep();
241: return;
242: }
243:
244: /* Increment the counter... */
245: history->current++;
246:
247: if (history->current == history->count)
248: {
249: /* If we are at the end, clear the entry field. */
250: cleanCDKEntry (entry);
251: }
252: else
253: {
254: /* Display the command. */
255: setCDKEntryValue (entry, history->command[history->current]);
256: }
257: drawCDKEntry (entry, ObjOf(entry)->box);
258: }
259:
260: /*
261: * This callback allows the user to play with the scrolling window.
262: */
263: static void viewHistoryCB (EObjectType cdktype GCC_UNUSED, void *object, void *clientData, chtype key GCC_UNUSED)
264: {
265: CDKSWINDOW *swindow = (CDKSWINDOW *)clientData;
266: CDKENTRY *entry = (CDKENTRY *)object;
267:
268: /* Let them play... */
269: activateCDKSwindow (swindow, 0);
270:
271: /* Redraw the entry field. */
272: drawCDKEntry (entry, ObjOf(entry)->box);
273: }
274:
275: /*
276: * This callback jumps to a line in the scrolling window.
277: */
278: static void jumpWindowCB (EObjectType cdktype GCC_UNUSED, void *object, void *clientData, chtype key)
279: {
280: CDKENTRY *entry = (CDKENTRY *)object;
281: CDKSWINDOW *swindow = (CDKSWINDOW *)clientData;
282: CDKSCALE *scale = 0;
283: int line;
284:
285: if (key == KEY_PPAGE || key == KEY_NPAGE)
286: {
287: injectCDKSwindow (swindow, key);
288: }
289: else
290: {
291: /* Ask them which line they want to jump to. */
292: scale = newCDKScale (ScreenOf(entry), CENTER, CENTER,
293: "<C>Jump To Which Line",
294: "Line",
295: A_NORMAL, 5,
296: 0, 0, swindow->itemCount, 1, 2, TRUE, FALSE);
297:
298: /* Get the line. */
299: line = activateCDKScale (scale, 0);
300:
301: /* Clean up. */
302: destroyCDKScale (scale);
303:
304: /* Jump to the line. */
305: jumpToLineCDKSwindow (swindow, line);
306: }
307:
308: /* Redraw the widgets. */
309: drawCDKEntry (entry, ObjOf(entry)->box);
310: }
311:
312: /*
313: * This callback allows the user to pick from the history list from a
314: * scrolling list.
315: */
316: static void listHistoryCB (EObjectType cdktype GCC_UNUSED, void *object, void *clientData, chtype key GCC_UNUSED)
317: {
318: CDKENTRY *entry = (CDKENTRY *)object;
319: struct history_st *history = (struct history_st *) clientData;
320: CDKSCROLL *scrollList;
321: int height = (history->count < 10 ? history->count+3 : 13);
322: int selection;
323:
324: /* No history, no list. */
325: if (history->count == 0)
326: {
327: /* Popup a little window telling the user there are no commands. */
328: char *mesg[] = {"<C></B/16>No Commands Entered", "<C>No History"};
329: popupLabel (ScreenOf(entry), mesg, 2);
330: }
331: else
332: {
333: /* Create the scrolling list of previous commands. */
334: scrollList = newCDKScroll (ScreenOf(entry), CENTER, CENTER, RIGHT,
335: height, 20, "<C></B/29>Command History",
336: history->command, history->count,
337: NUMBERS, A_REVERSE, TRUE, FALSE);
338:
339: /* Get the command to execute. */
340: selection = activateCDKScroll (scrollList, 0);
341: destroyCDKScroll (scrollList);
342:
343: /* Check the results of the selection. */
344: if (selection >= 0)
345: {
346: /* Get the command and stick it back in the entry field. */
347: setCDKEntryValue (entry, history->command[selection]);
348: }
349: }
350:
351: /* Redraw the screen. */
352: eraseCDKEntry (entry);
353: drawCDKScreen (ScreenOf(entry));
354: }
355:
356: /*
357: * This function displays help.
358: */
359: void help (CDKENTRY *entry)
360: {
361: char *mesg[25];
362:
363: /* Create the help message. */
364: mesg[0] = "<C></B/29>Help";
365: mesg[1] = "";
366: mesg[2] = "</B/24>When in the command line.";
367: mesg[3] = "<B=history > Displays the command history.";
368: mesg[4] = "<B=Ctrl-^ > Displays the command history.";
369: mesg[5] = "<B=Up Arrow > Scrolls back one command.";
370: mesg[6] = "<B=Down Arrow> Scrolls forward one command.";
371: mesg[7] = "<B=Tab > Activates the scrolling window.";
372: mesg[8] = "<B=help > Displays this help window.";
373: mesg[9] = "";
374: mesg[10] = "</B/24>When in the scrolling window.";
375: mesg[11] = "<B=l or L > Loads a file into the window.";
376: mesg[12] = "<B=s or S > Saves the contents of the window to a file.";
377: mesg[13] = "<B=Up Arrow > Scrolls up one line.";
378: mesg[14] = "<B=Down Arrow> Scrolls down one line.";
379: mesg[15] = "<B=Page Up > Scrolls back one page.";
380: mesg[16] = "<B=Page Down > Scrolls forward one page.";
381: mesg[17] = "<B=Tab/Escape> Returns to the command line.";
382: mesg[18] = "";
383: mesg[19] = "<C> (</B/24>Refer to the scrolling window online manual for more help<!B!24>.)";
384: popupLabel (ScreenOf(entry), mesg, 20);
385: }
386:
387: /*
388: * This converts a word to upper case.
389: */
390: char *uc (char *word)
391: {
392: char *upper = 0;
393: int length = 0;
394: int x;
395:
396: /* Make sure the word is not null. */
397: if (word == 0)
398: {
399: return 0;
400: }
401: length = strlen (word);
402:
403: /* Get the memory for the new word. */
404: upper = (char *)malloc (sizeof (char *) * (length+2));
405: if (upper == 0)
406: {
407: return (word);
408: }
409:
410: /* Start converting the case. */
411: for (x=0; x < length; x++)
412: {
413: if (isalpha ((int)word[x]))
414: {
415: upper[x] = toupper(word[x]);
416: }
417: else
418: {
419: upper[x] = word[x];
420: }
421: }
422: upper[length] = '\0';
423: return upper;
424: }
CVSweb <webmaster@jp.NetBSD.org>