#include "cdk.h" #ifdef HAVE_XCURSES char *XCursesProgramName="command"; #endif /* Define some global variables. */ #define MAXHISTORY 5000 char *introductionMessage[] = {"Little Command Interface", "", "Written by Mike Glover", "", "Type help to get help."}; /* This structure is used for keeping command history. */ struct history_st { int count; int current; char *command[MAXHISTORY]; }; /* Define some local prototypes. */ char *uc (char *word); void help (CDKENTRY *entry); int historyUpCB (EObjectType cdktype, void *object, void *clientData, chtype key); int historyDownCB (EObjectType cdktype, void *object, void *clientData, chtype key); int viewHistoryCB (EObjectType cdktype, void *object, void *clientData, chtype key); int listHistoryCB (EObjectType cdktype, void *object, void *clientData, chtype key); int jumpWindowCB (EObjectType cdktype, void *object, void *clientData, chtype key); /* * Written by: Mike Glover * Purpose: * This creates a very simple command interface. */ int main(int argc, char **argv) { /* Declare variables. */ CDKSCREEN *cdkscreen = (CDKSCREEN *)NULL; CDKSWINDOW *commandOutput = (CDKSWINDOW *)NULL; CDKENTRY *commandEntry = (CDKENTRY *)NULL; WINDOW *cursesWin = (WINDOW *)NULL; chtype *convert = (chtype *)NULL; char *command = (char *)NULL; char *upper = (char *)NULL; char *prompt = "Command >"; char *title = "Command Output Window"; int promptLen = 0; int commandFieldWidth = 0; struct history_st history; char temp[600]; int ret, junk; /* Set up the history. */ history.current = 0; history.count = 0; /* Check the command line for options. */ while (1) { /* Are there any more command line options to parse. */ if ((ret = getopt (argc, argv, "t:p:")) == -1) { break; } switch (ret) { case 'p': prompt = copyChar (optarg); break; case 't': title = copyChar (optarg); break; default: break; } } /* Set up CDK. */ cursesWin = initscr(); cdkscreen = initCDKScreen (cursesWin); /* Start color. */ initCDKColor(); /* Create the scrolling window. */ commandOutput = newCDKSwindow (cdkscreen, CENTER, TOP, -8, -2, title, 1000, TRUE, FALSE); /* Convert the prompt to a chtype and determine its length. */ convert = char2Chtype (prompt, &promptLen, &junk); commandFieldWidth = COLS - promptLen - 4; freeChtype (convert); /* Create the entry field. */ commandEntry = newCDKEntry (cdkscreen, CENTER, BOTTOM, NULL, prompt, A_BOLD|COLOR_PAIR(8), COLOR_PAIR(24)|'_', vMIXED, commandFieldWidth, 1, 512, FALSE, FALSE); /* Create the key bindings. */ bindCDKObject (vENTRY, commandEntry, KEY_UP, historyUpCB, &history); bindCDKObject (vENTRY, commandEntry, KEY_DOWN, historyDownCB, &history); bindCDKObject (vENTRY, commandEntry, TAB, viewHistoryCB, commandOutput); bindCDKObject (vENTRY, commandEntry, '', listHistoryCB, &history); bindCDKObject (vENTRY, commandEntry, '', jumpWindowCB, commandOutput); /* Draw the screen. */ refreshCDKScreen (cdkscreen); /* Show them who wrote this and how to get help. */ popupLabel (cdkscreen, introductionMessage, 5); eraseCDKEntry (commandEntry); /* Do this forever. */ for (;;) { /* Get the command. */ drawCDKEntry (commandEntry, commandEntry->box); command = activateCDKEntry (commandEntry, NULL); upper = uc (command); /* Check the output of the command. */ if (strcmp (upper, "QUIT") == 0 || strcmp (upper, "EXIT") == 0 || strcmp (upper, "Q") == 0 || strcmp (upper, "E") == 0 || commandEntry->exitType == vESCAPE_HIT) { /* All done. */ destroyCDKEntry (commandEntry); destroyCDKSwindow (commandOutput); delwin (cursesWin); freeChar (upper); endCDK(); exit (0); } else if (strcmp (command, "clear") == 0) { /* Keep the history. */ history.command[history.count] = copyChar (command); history.count++; history.current = history.count; cleanCDKSwindow (commandOutput); cleanCDKEntry (commandEntry); } else if (strcmp (command, "history") == 0) { /* Display the history list. */ listHistoryCB (vENTRY, commandEntry, &history, (chtype)NULL); /* Keep the history. */ history.command[history.count] = copyChar (command); history.count++; history.current = history.count; } else if (strcmp (command, "help") == 0) { /* Keep the history. */ history.command[history.count] = copyChar (command); history.count++; history.current = history.count; /* Display the help. */ help (commandEntry); /* Clean the entry field. */ cleanCDKEntry (commandEntry); eraseCDKEntry (commandEntry); } else { /* Keep the history. */ history.command[history.count] = copyChar (command); history.count++; history.current = history.count; /* Jump to the bottom of the scrolling window. */ jumpToLineCDKSwindow (commandOutput, BOTTOM); /* Insert a line providing the command. */ sprintf (temp, "Command: %s", command); addCDKSwindow (commandOutput, temp, BOTTOM); /* Run the command. */ execCDKSwindow (commandOutput, command, BOTTOM); /* Clean out the entry field. */ cleanCDKEntry (commandEntry); } /* Clean up a little. */ freeChar (upper); } } /* * This is the callback for the down arrow. */ int historyUpCB (EObjectType cdktype, void *object, void *clientData, chtype key) { CDKENTRY *entry = (CDKENTRY *)object; struct history_st *history = (struct history_st *) clientData; /* Make sure we don't go out of bounds. */ if (history->current == 0) { Beep(); return 0; } /* Decrement the counter. */ history->current--; /* Display the command. */ setCDKEntryValue (entry, history->command[history->current]); drawCDKEntry (entry, entry->box); return 0; } /* * This is the callback for the down arrow. */ int historyDownCB (EObjectType cdktype, void *object, void *clientData, chtype key) { CDKENTRY *entry = (CDKENTRY *)object; struct history_st *history = (struct history_st *) clientData; /* Make sure we don't go out of bounds. */ if (history->current == history->count) { Beep(); return 0; } /* Increment the counter... */ history->current++; /* If we are at the end, clear the entry field. */ if (history->current == history->count) { cleanCDKEntry (entry); drawCDKEntry (entry, entry->box); return 0; } /* Display the command. */ setCDKEntryValue (entry, history->command[history->current]); drawCDKEntry (entry, entry->box); return 0; } /* * This callback allows the user to play with the scrolling window. */ int viewHistoryCB (EObjectType cdktype, void *object, void *clientData, chtype key) { CDKSWINDOW *swindow = (CDKSWINDOW *)clientData; CDKENTRY *entry = (CDKENTRY *)object; /* Let them play... */ activateCDKSwindow (swindow, NULL); /* Redraw the entry field. */ drawCDKEntry (entry, entry->box); return 0; } /* * This callback jumps to a line in the scrolling window. */ int jumpWindowCB (EObjectType cdktype, void *object, void *clientData, chtype key) { CDKENTRY *entry = (CDKENTRY *)object; CDKSWINDOW *swindow = (CDKSWINDOW *)clientData; CDKSCALE *scale = (CDKSCALE *)NULL; int line; /* Ask them which line they want to jump to. */ scale = newCDKScale (entry->screen, CENTER, CENTER, "Jump To Which Line", "Line", A_NORMAL, 5, 0, 0, swindow->itemCount, 1, 2, TRUE, FALSE); /* Get the line. */ line = activateCDKScale (scale, NULL); /* Clean up. */ destroyCDKScale (scale); /* Jump to the line. */ jumpToLineCDKSwindow (swindow, line); /* Redraw the widgets. */ drawCDKEntry (entry, entry->box); return 0; } /* * This callback allows the user to pick from the history list from a * scrolling list. */ int listHistoryCB (EObjectType cdktype, void *object, void *clientData, chtype key) { CDKENTRY *entry = (CDKENTRY *)object; struct history_st *history = (struct history_st *) clientData; CDKSCROLL *scrollList; int height = (history->count < 10 ? history->count+3 : 13); int selection; /* No history, no list. */ if (history->count == 0) { /* Popup a little window telling the user there are no commands. */ char *mesg[] = {"No Commands Entered", "No History"}; popupLabel (entry->screen, mesg, 2); /* Redraw the screen. */ eraseCDKEntry (entry); drawCDKScreen (entry->screen); /* And leave... */ return 0; } /* Create the scrolling list of previous commands. */ scrollList = newCDKScroll (entry->screen, CENTER, CENTER, RIGHT, height, 20, "Command History", history->command, history->count, NUMBERS, A_REVERSE, TRUE, FALSE); /* Get the command to execute. */ selection = activateCDKScroll (scrollList, NULL); destroyCDKScroll (scrollList); /* Check the results of the selection. */ if (selection >= 0) { /* Get the command and stick it back in the entry field. */ setCDKEntryValue (entry, history->command[selection]); } /* Redraw the screen. */ eraseCDKEntry (entry); drawCDKScreen (entry->screen); return 0; } /* * This function displays help. */ void help (CDKENTRY *entry) { char *mesg[25]; /* Create the help message. */ mesg[0] = "Help"; mesg[1] = ""; mesg[2] = "When in the command line."; mesg[3] = " Displays the command history."; mesg[4] = " Displays the command history."; mesg[5] = " Scrolls back one command."; mesg[6] = " Scrolls forward one command."; mesg[7] = " Activates the scrolling window."; mesg[8] = " Displays this help window."; mesg[9] = ""; mesg[10] = "When in the scrolling window."; mesg[11] = " Loads a file into the window."; mesg[12] = " Saves the contents of the window to a file."; mesg[13] = " Scrolls up one line."; mesg[14] = " Scrolls down one line."; mesg[15] = " Scrolls back one page."; mesg[16] = " Scrolls forward one page."; mesg[17] = " Returns to the command line."; mesg[18] = ""; mesg[19] = " (Refer to the scrolling window online manual for more help.)"; popupLabel (entry->screen, mesg, 20); } /* * This converts a word to upper case. */ char *uc (char *word) { char *upper = (char *)NULL; int length = 0; int x; /* Make sure the word is not NULL. */ if (word == (char *)NULL) { return (char *)NULL; } length = strlen (word); /* Get the memory for the new word. */ upper = (char *)malloc (sizeof (char *) * (length+2)); if (upper == (char *)NULL) { return (word); } /* Start converting the case. */ for (x=0; x < length; x++) { if (isalpha ((int)word[x])) { upper[x] = toupper(word[x]); } else { upper[x] = word[x]; } } upper[length] = '\0'; return upper; }