/* COPYRIGHT, LICENSE AND VERSION {{{ */ /* Copyright (C) 2004 by Steve Litt * * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the * Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, * and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, provided that the * above copyright notice(s) and this permission notice appear * in all copies of the Software and that both the above * copyright notice(s) and this permission notice appear in * supporting documentation. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO * EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS * NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR * CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * * Except as contained in this notice, the name of a copyright * holder shall not be used in advertising or otherwise to * promote the sale, use or other dealings in this Software * without prior written authorization of the copyright holder. * * VERSION: 0.0.1, June 2004 */ /*}}}*/ /* INCLUDES {{{ */ #include #include /* Gives you menuing capabilities */ #include /*assert*/ #include /*malloc*/ #include /*strlen*/ #include /*exit*/ #include /*ltoa*/ /*}}}*/ /* #DEFINES AND ENUMS {{{ */ #define WHITEONRED 1 #define WHITEONBLUE 2 #define WHITEONBLACK 3 #define BLACKONWHITE 4 #define REDONWHITE 5 #define GREENONBLACK 6 #define CYANONRED 7 enum KBDKEYS {ENTER, CTRL_A, CTRL_B, CTRL_C, CTRL_D, CTRL_E, CTRL_F, CTRL_G, CTRL_H, CTRL_I, CTRL_J, CTRL_K, CTRL_L, CTRL_M, CTRL_N, CTRL_O, CTRL_P, CTRL_Q, CTRL_R, CTRL_S, CTRL_T, CTRL_U, CTRL_V, CTRL_W, CTRL_X, CTRL_Y, CTRL_Z, ESC, BACKSPACE, TAB, NULLCHAR}; typedef enum KBDKEYS KBDKEYS8[8]; enum ACTIONTYPES {PICK, ADD, CHANGE, DELETE, BAIL, REFRESH, NULLACTIONTYPE}; /* #DEFINES AND ENUMS }}} */ /* STRUCT FORWARD DECLARATIONS {{{ */ struct ROWINFO; struct ROWNODE; struct ROWSINFO; struct KEYSTROKES; struct SUBROUTINES; struct WINDOWS; struct PICKINFO; struct SLLNODE; /* END STRUCT FORWARD DECLARATIONS }}} */ /* FUNCTION PROTOTYPES {{{ */ /* OBSOLETE ROUTINE PROTOTYPES {{{*/ struct PICKINFO * setUpMenu(); /*{{{*/ /*}}}*/ char * buildKeyChars(); /*{{{*/ /*}}}*/ char ** buildKeySymbols(); /*{{{*/ /*}}}*/ enum KBDKEYS * mallocActionKeyList(const enum KBDKEYS *argk); /*{{{*/ /*}}}*/ /* END OBSOLETE ROUTINE PROTOTYPES }}}*/ /* UTILITY ROUTINE PROTOTYPES {{{*/ void showAscii(); /*{{{*/ /*}}}*/ char * mallocString(const char *msg); /*{{{*/ /*}}}*/ const char * ltoa(const long l); /*{{{*/ /*}}}*/ /* END UTILITY ROUTINE PROTOTYPES }}} */ /* KEYSTROKE ROUTINE PROTOTYPES {{{ */ void testKeySymbol(); /*{{{*/ /*}}}*/ void testAllKeySymbols(); /*{{{*/ /*}}}*/ struct KEYSTROKES * newKeystrokes(); /*{{{*/ /*}}}*/ void setKeySymbol( /*{{{*/ struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey, const char *symbol); /*}}}*/ void setKeyChar( /*{{{*/ struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey, const int keychar); /*}}}*/ void freeKeystrokes(struct KEYSTROKES * keystrokes); /*{{{*/ /*}}}*/ void setKeySymbolAndChar( /*{{{*/ struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey, const int keychar, const char * symbol ); /*}}}*/ void setActionKey( /*{{{*/ struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey, enum ACTIONTYPES actiontype, const int ss ); /*END }}}*/ void buildKeyDefaults(struct KEYSTROKES * keystrokes); /*{{{*/ /*}}}*/ void assignDefaultActionKeys(struct KEYSTROKES * keystrokes); /*{{{*/ /*}}}*/ /* END KEYSTROKE ROUTINE PROTOTYPES }}} */ /* ROW ROUTINE PROTOTYPES {{{ */ void freeRowsInfo(struct ROWSINFO *rowsInfo); /*{{{*/ /*}}}*/ void addRow( /*{{{*/ struct ROWSINFO * rowsInfo, const char *displayString, const char *sortString, const bool sortPointsToDisplay, const char *uid ); /*}}}*/ struct ROWSINFO * newRowsInfo(long increase_maxrows_by); /*{{{*/ /*}}}*/ void testRowInfo(); /*{{{*/ /*}}}*/ void freeRowInfo(struct ROWINFO * rowInfo); /*{{{*/ /*}}}*/ struct ROWINFO * newRowInfo( /*{{{*/ const char *displayString, const char *sortString, const bool sortPointsToDisplay, const char *uid ); /*}}}*/ /* END ROW ROUTINE PROTOTYPES }}} */ /* WINDOW ROUTINE PROTOTYPES {{{ */ void setUpWindows(struct PICKINFO *pickInfo); /*{{{*/ /*}}}*/ /* END WINDOW ROUTINE PROTOTYPES }}} */ /* PICKINFO ROUTINE PROTOTYPES {{{ */ void destroyPickInfo(struct PICKINFO * pickInfo); /*{{{*/ /*}}}*/ struct PICKINFO *newPickInfo(); /*{{{*/ /*}}}*/ void testMenuStructure(struct PICKINFO * pickInfo); /*{{{*/ /*}}}*/ /* END PICKINFO ROUTINE PROTOTYPES }}} */ /* MENU FILL ROUTINE PROTOTYPES {{{ */ void readRecords( /*{{{*/ struct PICKINFO * pickInfo, const char * filename ); /*}}}*/ /* END MENU FILL ROUTINE PROTOTYPES }}} */ /* MENU RUNNING ROUTINE PROTOTYPES {{{ */ /* END MENU RUNNING ROUTINE PROTOTYPES }}} */ /* TEST JIG ROUTINE PROTOTYPES NOT DIRECTLY ASSOCIATED WITH SPECIFIC STRUCTS {{{*/ void testRowsInfo(); /*{{{*/ /*}}}*/ /* TEST JIG ROUTINE PROTOTYPES NOT DIRECTLY ASSOCIATED WITH SPECIFIC STRUCTS }}}*/ /* MAIN {{{ */ int main(int argc, char *argv[]); /* {{{ */ /*}}}*/ /* END MAIN }}} */ /* END FUNCTION PROTOTYPES }}} */ /* STRUCTURE DEFINITIONS {{{ */ struct ROWNODE /*{{{*/ { struct ROWNODE *left; struct ROWNODE *right; struct ROWNODE *parent; struct ROWINFO *row; }; /*}}}*/ struct SUBROUTINES /*{{{*/ { /* add_sub; change_sub; delete_sub; */ }; /*}}}*/ struct WINDOWS /*{{{*/ { int uiTopLeftY; int uiTopLeftX; int ui_height; int ui_width; int ui_color_combo_constant; int ui_attrib; int ui_highlight_color_combo_constant; int ui_highlight_attrib; int borderTopLeftY; int borderTopLeftX; int border_height; int border_width; int border_color_combo_constant; int border_attrib; char *title; int firstPromptY; int firstPromptX; int prompt_color_combo_constant; int prompt_attrib; }; /*}}}*/ struct ROWINFO /*{{{*/ { char *displayString; char *sortString; bool sortPointsToDisplay; char *uid; }; /*}}}*/ struct ROWSINFO /*{{{*/ { long numrows; /* number of rows currently consumed */ long maxrows; /* maximum rows in array */ long increase_maxrows_by; /* number of rows to add to array when full */ struct ROWNODE *headNode; struct ROWINFO **rows; }; /*}}}*/ struct KEYINFO /* UNUSED RIGHT NOW */ /*{{{*/ { char * symbol; char ch; char * name; }; /*}}}*/ struct KEYSTROKES /*{{{*/ { char * keySymbols[NULLCHAR + 1]; char keyChars[NULLCHAR + 1]; KBDKEYS8 action_keys[NULLACTIONTYPE]; }; /*}}}*/ struct PICKINFO /*{{{*/ { struct ROWSINFO *rowsInfo; struct KEYSTROKES *keystrokes; struct SUBROUTINES *subroutines; struct WINDOWS *windows; char ** actionNames; }; /*}}}*/ /* END STRUCTURE DEFINITIONS }}} */ /* FUNCTION DEFINITIONS {{{ */ /* OBSOLETE ROUTINES {{{*/ struct PICKINFO * setUpMenu() /*{{{*/ { struct PICKINFO * pickInfo = newPickInfo(); setUpWindows(pickInfo); return pickInfo; } /*}}}*/ char * buildKeyChars() /*{{{*/ { int n; char keys[100]; keys[0] = 'x'; keys[1] = '\0'; return(mallocString(keys)); for(n=1; n <= 26; n++) { keys[n] = n; } keys[ESC] = '\033'; keys[BACKSPACE] = '\010'; keys[TAB] = '\011'; keys[ENTER] = '\015'; keys[NULLCHAR] = '\0'; return(mallocString(keys)); } /*}}}*/ char ** buildKeySymbols() /*{{{*/ { int elementCount; char **ppc; char **ppc2; char **returnArray; char *temp[] = { "ENTER", "CTRL+A", "CTRL+B", "CTRL+C", "CTRL+D", "CTRL+E", "CTRL+F", "CTRL+G", "CTRL+H", "CTRL+I", "CTRL+J", "CTRL+K", "CTRL+L", "CTRL+M", "CTRL+N", "CTRL+O", "CTRL+P", "CTRL+Q", "CTRL+R", "CTRL+S", "CTRL+T", "CTRL+U", "CTRL+V", "CTRL+W", "CTRL+X", "CTRL+Y", "CTRL+Z", "ESC", "BACKSPACE", "TAB", NULL }; elementCount=0; ppc = temp; while(*ppc != NULL) { elementCount++; ppc++; } returnArray = (char **) malloc ((elementCount + 1) * sizeof(char *)); assert(returnArray != NULL); for(ppc = temp, ppc2 = returnArray; *ppc != NULL; ppc++, ppc2++) { *ppc2 = mallocString(*ppc); } *ppc2 = NULL; return returnArray; } /*}}}*/ enum KBDKEYS * mallocActionKeyList(const enum KBDKEYS *argk) { int count = 0; const enum KBDKEYS *pk; enum KBDKEYS *pk2, *returnList; for(pk = argk; *pk != NULLCHAR; pk++) count++; returnList = (enum KBDKEYS *) malloc((count+1) * sizeof(enum KBDKEYS)); pk = argk; pk2 = returnList; while(*pk != NULLCHAR) *pk2++ = *pk++; *pk2 = NULLCHAR; return returnList; } /* END OBSOLETE ROUTINES }}}*/ /* UTILITY ROUTINES {{{*/ void showAscii() /*{{{*/ { int c; int n; for(n=0; n<20; n++) { c = getchar(); if(c == 'q') break; printf("hux>%dkeySymbols[kbdkey] = NULL; keystrokes->keyChars[kbdkey] = '\0'; } /************************************************************** The following loop should go up to n < 8, but it causes the ensuing free to segfault, so it is n < 7. **************************************************************/ for(actiontype=PICK; actiontype < NULLACTIONTYPE; actiontype++) { for(n = 0; n < 7; n++); { setActionKey(keystrokes, NULLCHAR, actiontype, n); } } return(keystrokes); } /*END }}}*/ void freeKeySymbol(struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey) /*{{{*/ { if(keystrokes->keySymbols[kbdkey] != NULL) free(keystrokes->keySymbols[kbdkey]); } /*}}}*/ void setKeySymbol( /*{{{*/ struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey, const char *symbol ) { keystrokes->keySymbols[kbdkey] = mallocString(symbol); } /*END }}}*/ void testKeySymbol() /*{{{*/ { struct KEYSTROKES * keystrokes; long lT; keystrokes = newKeystrokes(); for(lT = 0; lT < 100000000; lT++) { if(lT % 1000000 == 0) printf("%ld\n", lT); setKeySymbol(keystrokes, CTRL_J, "my test"); freeKeySymbol(keystrokes, CTRL_J); } freeKeystrokes(keystrokes); }/*}}}*/ void setKeyChar(struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey, const int keychar) /*{{{*/ { keystrokes->keyChars[kbdkey] = keychar; } /*END }}}*/ void setKeySymbolAndChar( /*{{{*/ struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey, const int keychar, const char * symbol ) { setKeySymbol(keystrokes, kbdkey, symbol); setKeyChar(keystrokes, kbdkey, keychar); } /*END }}}*/ void setActionKey( /*{{{*/ struct KEYSTROKES * keystrokes, enum KBDKEYS kbdkey, enum ACTIONTYPES actiontype, const int ss ) { keystrokes->action_keys[actiontype][ss] = kbdkey; } /*END }}}*/ void buildKeyDefaults(struct KEYSTROKES * keystrokes) /*{{{*/ { setKeySymbolAndChar(keystrokes, ENTER, 13, "ENTER"); setKeySymbolAndChar(keystrokes, CTRL_A, 1, "CTRL+A"); setKeySymbolAndChar(keystrokes, CTRL_B, 2, "CTRL+B"); setKeySymbolAndChar(keystrokes, CTRL_C, 3, "CTRL+C"); setKeySymbolAndChar(keystrokes, CTRL_D, 4, "CTRL+D"); setKeySymbolAndChar(keystrokes, CTRL_E, 5, "CTRL+E"); setKeySymbolAndChar(keystrokes, CTRL_F, 6, "CTRL+F"); setKeySymbolAndChar(keystrokes, CTRL_G, 7, "CTRL+G"); setKeySymbolAndChar(keystrokes, CTRL_H, 8, "CTRL+H"); setKeySymbolAndChar(keystrokes, CTRL_I, 9, "CTRL+I"); setKeySymbolAndChar(keystrokes, CTRL_J, 10, "CTRL+J"); setKeySymbolAndChar(keystrokes, CTRL_K, 11, "CTRL+K"); setKeySymbolAndChar(keystrokes, CTRL_L, 12, "CTRL+L"); setKeySymbolAndChar(keystrokes, CTRL_M, 13, "CTRL+M"); setKeySymbolAndChar(keystrokes, CTRL_N, 14, "CTRL+N"); setKeySymbolAndChar(keystrokes, CTRL_O, 15, "CTRL+O"); setKeySymbolAndChar(keystrokes, CTRL_P, 16, "CTRL+P"); setKeySymbolAndChar(keystrokes, CTRL_Q, 17, "CTRL+Q"); setKeySymbolAndChar(keystrokes, CTRL_R, 18, "CTRL+R"); setKeySymbolAndChar(keystrokes, CTRL_S, 19, "CTRL+S"); setKeySymbolAndChar(keystrokes, CTRL_T, 20, "CTRL+T"); setKeySymbolAndChar(keystrokes, CTRL_U, 21, "CTRL+U"); setKeySymbolAndChar(keystrokes, CTRL_V, 22, "CTRL+V"); setKeySymbolAndChar(keystrokes, CTRL_W, 23, "CTRL+W"); setKeySymbolAndChar(keystrokes, CTRL_X, 24, "CTRL+X"); setKeySymbolAndChar(keystrokes, CTRL_Y, 25, "CTRL+Y"); setKeySymbolAndChar(keystrokes, CTRL_Z, 26, "CTRL+Z"); setKeySymbolAndChar(keystrokes, ESC, 27, "ESC"); setKeySymbolAndChar(keystrokes, BACKSPACE, 8, "BACKSPACE"); setKeySymbolAndChar(keystrokes, TAB, 9, "TAB"); } /*}}}*/ void assignDefaultActionKeys(struct KEYSTROKES * keystrokes) /*{{{*/ { setActionKey(keystrokes, CTRL_P, PICK, 0); setActionKey(keystrokes, NULLCHAR, PICK, 1); setActionKey(keystrokes, CTRL_A, ADD, 0); setActionKey(keystrokes, NULLCHAR, ADD, 1); setActionKey(keystrokes, CTRL_M, CHANGE, 0); setActionKey(keystrokes, NULLCHAR, CHANGE, 1); setActionKey(keystrokes, CTRL_D, DELETE, 0); setActionKey(keystrokes, NULLCHAR, DELETE, 1); setActionKey(keystrokes, CTRL_B, BAIL, 0); setActionKey(keystrokes, ESC, BAIL, 1); setActionKey(keystrokes, NULLCHAR, BAIL, 2); setActionKey(keystrokes, CTRL_L, REFRESH, 0); setActionKey(keystrokes, CTRL_R, REFRESH, 1); setActionKey(keystrokes, NULLCHAR, REFRESH, 2); } /*}}}*/ void freeKeystrokes(struct KEYSTROKES * keystrokes) /*{{{*/ { enum KBDKEYS kbdkey; for(kbdkey = ENTER; kbdkey <= NULLCHAR; kbdkey++) freeKeySymbol(keystrokes, kbdkey); free(keystrokes); keystrokes = NULL; } /*}}}*/ void testKeystrokes() /*{{{*/ { struct KEYSTROKES * keystrokes; long lT; for(lT = 0; lT < 10000000; lT++) { if(lT % 100000 == 0) printf("%ld\n", lT); keystrokes = newKeystrokes(); setKeySymbol(keystrokes, ENTER, "ENTER"); buildKeyDefaults(keystrokes); assignDefaultActionKeys(keystrokes); /* keystrokes = malloc(sizeof(struct KEYSTROKES));*/ freeKeystrokes(keystrokes); } } /*}}}*/ void testAllKeySymbols() /*{{{*/ { struct KEYSTROKES * keystrokes; long lT; for(lT = 0; lT < 10000000; lT++) { if(lT % 1 == 0) printf("%ld\n", lT); keystrokes = newKeystrokes(); /* setKeySymbol(keystrokes, ENTER, "my test"); */ keystrokes->keySymbols[0] = malloc(10); assert(keystrokes->keySymbols[0] != NULL); /* freeKeySymbol(keystrokes, ENTER); */ /* for(kbdkey=ENTER; kbdkey <= NULLCHAR; kbdkey++) { setKeySymbol(keystrokes, kbdkey, "my test"); } for(kbdkey=ENTER; kbdkey <= NULLCHAR; kbdkey++) { freeKeySymbol(keystrokes, kbdkey); } */ freeKeystrokes(keystrokes); } }/*}}}*/ /* END KEYSTROKE ROUTINES }}} */ /* ROW ROUTINES {{{ */ void freeRowsInfo(struct ROWSINFO *rowsInfo) /*{{{*/ { long lT; for(lT = 0; lT < rowsInfo->numrows; lT++) { freeRowInfo(rowsInfo->rows[lT]); } /* PLACE ROWNODE DELETION CODE HERE LATER */ free(rowsInfo->rows); free(rowsInfo); } /*}}}*/ void addRow( /*{{{*/ struct ROWSINFO * rowsInfo, const char *displayString, const char *sortString, const bool sortPointsToDisplay, const char *uid ) { rowsInfo->numrows++; if(rowsInfo->numrows > rowsInfo->maxrows) { rowsInfo->maxrows += rowsInfo->increase_maxrows_by; if(rowsInfo->rows == NULL) { rowsInfo->rows = malloc(rowsInfo->maxrows * sizeof(struct ROWINFO *)); } else { rowsInfo->rows = realloc(rowsInfo->rows, rowsInfo->maxrows * sizeof(struct ROWINFO *)); } assert(rowsInfo->rows != NULL); } rowsInfo->rows[rowsInfo->numrows - 1] = newRowInfo( displayString, sortString, sortPointsToDisplay, uid ); } /*}}}*/ struct ROWSINFO * newRowsInfo(long increase_maxrows_by) /*{{{*/ { struct ROWSINFO * rowsInfo; rowsInfo = malloc(sizeof(struct ROWSINFO)); assert(rowsInfo != NULL); rowsInfo->numrows = 0; rowsInfo->maxrows = 0; rowsInfo->increase_maxrows_by = increase_maxrows_by; rowsInfo->rows = NULL; rowsInfo->headNode = NULL; return rowsInfo; } /*}}}*/ void testRowInfo() /*{{{*/ { struct ROWINFO * rowInfo; long lT; for(lT = 0; lT < 10000000; lT++) { if(lT % 100000 == 0) printf("%ld\n", lT); rowInfo = newRowInfo("display", "sort", false, "1"); freeRowInfo(rowInfo); } } /*}}}*/ void freeRowInfo(struct ROWINFO * rowInfo) /*{{{*/ { if(rowInfo->displayString != NULL) free(rowInfo->displayString); if(rowInfo->sortString != NULL) free(rowInfo->sortString); if(rowInfo->uid != NULL) free(rowInfo->uid); free(rowInfo); } /*}}}*/ struct ROWINFO * newRowInfo( /*{{{*/ const char *displayString, const char *sortString, const bool sortPointsToDisplay, const char *uid ) { struct ROWINFO * rowInfo; rowInfo = malloc(sizeof(struct ROWINFO)); assert(rowInfo != NULL); rowInfo->displayString = mallocString(displayString); rowInfo->sortPointsToDisplay = sortPointsToDisplay; if(sortPointsToDisplay) rowInfo->sortString = NULL; else rowInfo->sortString = mallocString(sortString); rowInfo->uid = mallocString(uid); return(rowInfo); } /*}}}*/ void testRowsInfo() /*{{{*/ { struct ROWSINFO *rowsInfo; long lT; int nT; for(lT = 0; lT < 1000000; lT++) { if(lT % 100000 == 0) printf("%ld\n", lT); rowsInfo = newRowsInfo(10); for(nT = 0; nT < 30; nT++) { addRow( rowsInfo, "display", "sort", false, ltoa(rowsInfo->numrows) ); } freeRowsInfo(rowsInfo); } } /*}}}*/ /* END ROW ROUTINES }}} */ /* WINDOW ROUTINES {{{ */ void setUpWindows(struct PICKINFO *pickInfo) /*{{{*/ { pickInfo->windows->borderTopLeftY = 2; pickInfo->windows->borderTopLeftX = 5; pickInfo->windows->border_height = 20; pickInfo->windows->border_width = 65; pickInfo->windows->border_color_combo_constant = WHITEONRED; pickInfo->windows->border_attrib = WA_BOLD; pickInfo->windows->uiTopLeftY = 1; pickInfo->windows->uiTopLeftX = 1; pickInfo->windows->ui_height = 18; pickInfo->windows->ui_width = 19; pickInfo->windows->ui_color_combo_constant = WHITEONRED; pickInfo->windows->ui_attrib = WA_BOLD; pickInfo->windows->ui_highlight_color_combo_constant = REDONWHITE; pickInfo->windows->ui_highlight_attrib = 0; pickInfo->windows->title = " CHOOSE ONE "; pickInfo->windows->firstPromptY = 10; pickInfo->windows->firstPromptX = 35; pickInfo->windows->prompt_color_combo_constant = CYANONRED; pickInfo->windows->prompt_attrib = WA_BOLD; } /*}}}*/ bool checkDimensions(struct PICKINFO *pickInfo) /*{{{*/ { if(pickInfo->windows->ui_height + pickInfo->windows->uiTopLeftY > pickInfo->windows->border_height) { printf("MENU DIMENSIONING ERROR\n"); printf("ui window bottom goes past border window bottom.\n"); return(false); } if(pickInfo->windows->ui_width + pickInfo->windows->uiTopLeftX > pickInfo->windows->border_width) { printf("MENU DIMENSIONING ERROR\n"); printf("ui window right edge goes past border window right edge.\n"); return(false); } return(true); } /*}}}*/ /* END WINDOW ROUTINES }}} */ /* PICKINFO ROUTINES {{{ */ void destroyPickInfo(struct PICKINFO * pickInfo) /*{{{*/ { char **ppc; /* DESTROY HEADNODE POINTER */ free(pickInfo->rowsInfo->headNode); /* DESTROY ROWSINFO POINTER AND ROWS ARRAY */ freeRowsInfo(pickInfo->rowsInfo); /* DESTROY KEYSTROKES POINTER AND ITS CONTENTS */ freeKeystrokes(pickInfo->keystrokes); /* DESTROY SUBROUTINES POINTER */ free(pickInfo->subroutines); /* DESTROY WINDOWS POINTER */ free(pickInfo->windows); /* DESTROY ACTION NAMES ARRAY */ for(ppc = pickInfo->actionNames; *ppc != NULL; ppc++) free(*ppc++); free(pickInfo->actionNames); /* DESTROY PICKINFO */ free(pickInfo); } /*}}}*/ struct PICKINFO *newPickInfo() /*{{{*/ { struct PICKINFO * pickInfo; /* ALLOCATE PICKINFO */ pickInfo = (struct PICKINFO *) malloc(sizeof(struct PICKINFO)); assert(pickInfo != NULL); /* ****************************** */ /* SET ACTION NAME DEFAULTS */ /* ****************************** */ pickInfo->actionNames = malloc(NULLACTIONTYPE * sizeof(char *)); pickInfo->actionNames[PICK] = mallocString("Pick"); pickInfo->actionNames[ADD] = mallocString("Add"); pickInfo->actionNames[CHANGE] = mallocString("Modify"); pickInfo->actionNames[DELETE] = mallocString("Delete"); pickInfo->actionNames[BAIL] = mallocString("Abort"); pickInfo->actionNames[REFRESH] = mallocString("Refresh"); pickInfo->actionNames[NULLACTIONTYPE] = NULL; /* ALLOCATE ROWSINFO POINTER */ pickInfo->rowsInfo = newRowsInfo(1000); /* ALLOCATE KEYSTROKES POINTER */ pickInfo->keystrokes = newKeystrokes(); buildKeyDefaults(pickInfo->keystrokes); assignDefaultActionKeys(pickInfo->keystrokes); /* ALLOCATE SUBROUTINES POINTER */ pickInfo->subroutines = (struct SUBROUTINES *) malloc(sizeof(struct SUBROUTINES)); assert(pickInfo->subroutines != NULL); /* ALLOCATE WINDOWS POINTER */ pickInfo->windows = (struct WINDOWS *) malloc(sizeof(struct WINDOWS)); assert(pickInfo->windows != NULL); /* ****************************** */ /* ALLOCATE ALL ROWSINFO POINTERS */ /* ****************************** */ /* ALLOCATE HEADNODE POINTER */ /* Nodes are not used in this program */ /* pickInfo->rowsInfo->headNode = (struct ROWNODE *) malloc(sizeof(struct ROWNODE)); assert(pickInfo->rowsInfo->headNode != NULL); */ /* ALLOCATE ROWS ARRAY POINTER */ /* this is done by the readRecords() routine */ /* pickInfo->rowsInfo->rows = (struct ROWINFO **) malloc(sizeof(struct ROWINFO *)); assert(pickInfo->rowsInfo->rows != NULL); */ /* ****************************** */ /* ALLOCATE ALL CONSTANT KEYSTROKES POINTERS */ /* ****************************** */ /* pickInfo->keystrokes->keyChars = buildKeyChars(); */ /* pickInfo->keystrokes->keySymbols = buildKeySymbols(); */ return(pickInfo); } /*}}}*/ void testMenuStructure(struct PICKINFO * pickInfo) /*{{{*/ { enum KBDKEYS *pkbdkey; enum ACTIONTYPES actionType; char **ppc; char *pc; int n; long lT; printf("\n\nDISPLAYING pickInfo->rowsInfo INFORMATION *************\n"); for(lT = 0; lT < pickInfo->rowsInfo->numrows; lT++) { printf("\t%8ld: %s\n", lT, pickInfo->rowsInfo->rows[lT]->sortString); } printf("\n\nDISPLAYING pickInfo->keystrokes INFORMATION *************\n"); printf("\n\tDISPLAYING pickInfo->keystrokes->keySymbols INFORMATION\n"); ppc = pickInfo->keystrokes->keySymbols; n = 0; while(*ppc != NULL) { if(n > 0) printf(", "); if(n % 5 == 0) printf("\n\t\t"); printf("%s", *ppc); ppc++; n++; } printf("\n\nDISPLAYING pickInfo->keystrokes->keyChars INFORMATION\n"); pc = pickInfo->keystrokes->keyChars; n = 0; while(*pc != '\0') { if(n > 0) printf(", "); if(n % 5 == 0) printf("\n\t\t"); printf("%d", *pc); pc++; n++; } printf("\n\nDISPLAYING pickInfo->keystrokes->action_keys INFORMATION\n"); actionType = PICK; while(actionType < NULLACTIONTYPE) { printf("\t"); printf("%s:\t", pickInfo->actionNames[actionType]); pkbdkey = pickInfo->keystrokes->action_keys[actionType]; n=0; while(pkbdkey[n] >= '\0') { if(n > 0) printf(", "); printf("%s", pickInfo->keystrokes->keySymbols[pkbdkey[n]]); n++; if(pkbdkey[n] == NULLCHAR) break; if(n >= 8) { printf ("ERROR: Unterminated by NULLCHAR\n"); break; } } printf("\n"); actionType++; } printf("\n\nDISPLAYING pickInfo->subroutines INFORMATION *************\n"); printf("\n\nDISPLAYING pickInfo->windows INFORMATION *************\n"); printf("\ttitle=%s.\n", pickInfo->windows->title); printf("\tBORDER WINDOW STATS...\n"); printf("\t\tborderTopLeftY=%d.\n", pickInfo->windows->borderTopLeftY); printf("\t\tborderTopLeftX=%d.\n", pickInfo->windows->borderTopLeftX); printf("\t\tborder_color_combo_constant=%d.\n", pickInfo->windows->border_color_combo_constant); printf("\t\tborder_attrib=%d.\n", pickInfo->windows->border_attrib); printf("\t\tborder_height=%d.\n", pickInfo->windows->border_height); printf("\t\tborder_width=%d.\n", pickInfo->windows->border_width); printf("\tUI WINDOW STATS...\n"); printf("\t\tuiTopLeftY=%d.\n", pickInfo->windows->uiTopLeftY); printf("\t\tuiTopLeftX=%d.\n", pickInfo->windows->uiTopLeftX); printf("\t\tui_height=%d.\n", pickInfo->windows->ui_height); printf("\t\tui_width=%d.\n", pickInfo->windows->ui_width); printf("\t\tui_color_combo_constant=%d.\n", pickInfo->windows->ui_color_combo_constant); printf("\t\tui_attrib=%d.\n", pickInfo->windows->ui_attrib); printf("\tPROMPT STATS...\n"); printf("\t\tfirstPromptY=%d.\n", pickInfo->windows->firstPromptY); printf("\t\tfirstPromptX=%d.\n", pickInfo->windows->firstPromptX); printf("\n\nDISPLAYING pickInfo->actionNames INFORMATION *************\n"); actionType = PICK; while((pc = pickInfo->actionNames[actionType]) != NULL) { if(actionType == NULLACTIONTYPE) { printf ("ERROR: Unterminated by NULL\n"); break; } printf("\t%s\n", pc); actionType++; } } /*}}}*/ void testPickInfo() /*{{{*/ { long lT; struct PICKINFO *pickInfo; for(lT=0; lT < 10000000; lT++) { if((lT % 100000) == 0) printf("%7ld\n", lT); pickInfo = newPickInfo(); /* setUpWindows(pickInfo); */ /* printf("dia b4 readRecords() %ld\n", lT);*/ /* readRecords(pickInfo, "presidents.txt"); */ /* printf("dia b4 destroy %ld\n", lT);*/ destroyPickInfo(pickInfo); } } /*}}}*/ /* END PICKINFO ROUTINES }}} */ /* MENU FILL ROUTINES {{{ */ void readRecords(struct PICKINFO * pickInfo, const char * filename) /*{{{*/ { int BUFSIZE = 101; FILE * fp; char buf[BUFSIZE]; char *pc; int maxLength = pickInfo->windows->ui_width - 1; fp = fopen(filename, "r"); if(fp == NULL) { printf("Cannot open %s for read, aborting...\n", filename); } while((pc = fgets(buf, BUFSIZE, fp)) != NULL) { int len; /* PREVENT OVERFLOW AND TOO WIDE STRINGS */ buf[BUFSIZE - 1] = '\0'; len = strlen(buf); buf[len - 1] = '\0'; /* TRIM NEWLINE */ if(len > maxLength ) buf[maxLength - 1] = '\0'; /* CONTINUE */ pickInfo->rowsInfo->numrows++; if(pickInfo->rowsInfo->numrows > pickInfo->rowsInfo->maxrows) { pickInfo->rowsInfo->maxrows += pickInfo->rowsInfo->increase_maxrows_by; pickInfo->rowsInfo->rows = realloc(pickInfo->rowsInfo->rows, pickInfo->rowsInfo->maxrows * sizeof(struct ROWINFO *)); assert(pickInfo->rowsInfo->rows != NULL); } pickInfo->rowsInfo->rows[pickInfo->rowsInfo->numrows - 1] = newRowInfo( mallocString(pc), mallocString(pc), false, mallocString(ltoa((long)pickInfo->rowsInfo->numrows)) ); } fclose(fp); } /*}}}*/ /* END MENU FILL ROUTINES }}} */ /* MENU RUNNING ROUTINES {{{ */ void wCenterTitle(WINDOW *pwin, const char * title) /*{{{*/ { int x, maxy, maxx, stringsize; getmaxyx(pwin, maxy, maxx); stringsize = 4 + strlen(title); x = (maxx - stringsize)/2; mvwaddch(pwin, 0, x, ACS_RTEE); waddch(pwin, ' '); waddstr(pwin, title); waddch(pwin, ' '); waddch(pwin, ACS_LTEE); } /*}}}*/ void wclrscr(WINDOW * pwin) /*{{{*/ { int y, x, maxy, maxx; getmaxyx(pwin, maxy, maxx); for(y=0; y < maxy; y++) for(x=0; x < maxx; x++) mvwaddch(pwin, y, x, ' '); } /*}}}*/ bool initColors() /*{{{*/ { if(has_colors()) { start_color(); init_pair(WHITEONRED, COLOR_WHITE, COLOR_RED); init_pair(WHITEONBLUE, COLOR_WHITE, COLOR_BLUE); init_pair(WHITEONBLACK, COLOR_WHITE, COLOR_BLACK); init_pair(BLACKONWHITE, COLOR_BLACK, COLOR_WHITE); init_pair(REDONWHITE, COLOR_RED, COLOR_WHITE); init_pair(GREENONBLACK, COLOR_GREEN, COLOR_BLACK); init_pair(CYANONRED, COLOR_CYAN, COLOR_RED); return(true); } else return(false); } /*}}}*/ int runMenu( /*{{{*/ struct PICKINFO *pickInfo, WINDOW *wParent ) { int c; /* key pressed */ ITEM **my_items; /* list of items on this menu */ MENU *my_menu; /* the menu structure */ WINDOW *wUI; /* window on which the user interacts with the menu */ WINDOW *wBorder; /* window containing the wUI window and the border and title */ int n_choices; /* number of items on menu */ int ssChoice; /* subscript to run around the choices array */ int my_choice = -1; /* the zero based numeric user choice */ int y; enum ACTIONTYPES actiontype; /* CALCULATE NUMBER OF MENU CHOICES */ n_choices = pickInfo->rowsInfo->numrows; /* ALLOCATE ITEM ARRAY AND INDIVIDUAL ITEMS */ my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); for(ssChoice = 0; ssChoice < n_choices; ++ssChoice) { my_items[ssChoice] = new_item( pickInfo->rowsInfo->rows[ssChoice]->displayString, NULL); } my_items[n_choices] = (ITEM *)NULL; /* CREATE THE MENU STRUCTURE */ my_menu = new_menu((ITEM **)my_items); /* PUT > TO THE LEFT OF HIGHLIGHTED ITEM */ set_menu_mark(my_menu, "> "); /* SET UP WINDOW FOR MENU'S BORDER */ wBorder = newwin( pickInfo->windows->border_height, pickInfo->windows->border_width, pickInfo->windows->borderTopLeftY, pickInfo->windows->borderTopLeftX); wattrset( wBorder, COLOR_PAIR(pickInfo->windows->border_color_combo_constant) | pickInfo->windows->border_attrib); wclrscr(wBorder); box(wBorder, 0, 0); wCenterTitle(wBorder, pickInfo->windows->title); /* SET UP WINDOW FOR THE MENU'S USER INTERFACE */ wUI = derwin( wBorder, pickInfo->windows->ui_height, pickInfo->windows->ui_width, pickInfo->windows->uiTopLeftY, pickInfo->windows->uiTopLeftX ); /* ASSOCIATE THESE WINDOWS WITH THE MENU */ set_menu_win(my_menu, wBorder); set_menu_sub(my_menu, wUI); set_menu_format(my_menu, pickInfo->windows->ui_height, 1); /* MATCH MENU'S COLORS TO THAT OF ITS WINDOWS */ set_menu_fore( my_menu, COLOR_PAIR(pickInfo->windows->ui_highlight_color_combo_constant) | pickInfo->windows->ui_highlight_attrib ); set_menu_back( my_menu, COLOR_PAIR(pickInfo->windows->ui_color_combo_constant) | pickInfo->windows->ui_attrib ); /* SET UP AN ENVIRONMENT CONDUCIVE TO MENUING */ keypad(wUI, TRUE); /* enable detection of function keys */ noecho(); /* user keystrokes don't echo */ curs_set(0); /* make cursor invisible */ menu_opts_on(my_menu, O_SHOWMATCH); menu_opts_on(my_menu, O_IGNORECASE); menu_opts_on(my_menu, O_NONCYCLIC); /* DISPLAY THE MENU */ post_menu(my_menu); /* DISPLAY THE PROMPTS */ wattrset( wBorder, COLOR_PAIR(pickInfo->windows->prompt_color_combo_constant) | pickInfo->windows->prompt_attrib ); y = pickInfo->windows->firstPromptY; for(actiontype=PICK; actiontype < NULLACTIONTYPE; actiontype++) { enum KBDKEYS *kbdkeys = pickInfo->keystrokes->action_keys[actiontype]; if(kbdkeys[0] != NULLCHAR) { int ssKeySymbol; mvwaddstr( wBorder, y, pickInfo->windows->firstPromptX, pickInfo->actionNames[actiontype] ); waddstr(wBorder, ": "); for(ssKeySymbol = 0; ssKeySymbol < 7; ssKeySymbol++) { enum KBDKEYS thisKey = kbdkeys[ssKeySymbol]; if(thisKey == NULLCHAR) break; else { char *pc; if(ssKeySymbol > 0) waddstr(wBorder, ", "); pc = pickInfo->keystrokes->keySymbols[thisKey]; waddstr(wBorder, pc); } } y++; } } wattrset( wBorder, COLOR_PAIR(pickInfo->windows->border_color_combo_constant) | pickInfo->windows->border_attrib ); /* REFRESH THE BORDER WINDOW PRIOR TO ACCEPTING USER INTERACTION */ touchwin(wBorder); wrefresh(wBorder); /* HANDLE USER KEYSTROKES */ while(my_choice == -1) { touchwin(wUI); /* refresh prior to getch() */ wrefresh(wUI); /* refresh prior to getch() */ c = getch(); switch(c) { case KEY_DOWN: menu_driver(my_menu, REQ_DOWN_ITEM); break; case KEY_UP: menu_driver(my_menu, REQ_UP_ITEM); break; case KEY_NPAGE: menu_driver(my_menu, REQ_SCR_DPAGE); break; case KEY_PPAGE: menu_driver(my_menu, REQ_SCR_UPAGE); break; case 10: /* Enter */ my_choice = item_index(current_item(my_menu)); /* RESET CURSOR IN CASE MORE SELECTION IS NECESSARY */ pos_menu_cursor(my_menu); break; } } /* FREE ALL ALLOCATED MENU AND ITEM RESOURCES */ unpost_menu(my_menu); for(ssChoice = 0; ssChoice < n_choices; ++ssChoice) free_item(my_items[ssChoice]); free_menu(my_menu); /* DESTROY MENU WINDOW AND BORDER WINDOWS */ delwin(wUI); delwin(wBorder); /* UNDO MENU SPECIFIC ENVIRONMENT */ curs_set(1); /* make cursor visible again */ /* REPAINT THE CALLING SCREEN IN PREPARATION FOR RETURN */ touchwin(wParent); wrefresh(wParent); /* RETURN THE ZERO BASED NUMERIC USER CHOICE */ return(my_choice); } /*}}}*/ /* END MENU RUNNING ROUTINES }}} */ /* TEST JIG ROUTINES NOT DIRECTLY ASSOCIATED WITH SPECIFIC STRUCTS {{{*/ int testx() /*{{{*/ { long lT; int n; struct KEYSTROKES * keystrokes; for(lT = 0; lT < 100; lT++) { printf("%ld\n", lT); keystrokes = newKeystrokes(); assert(keystrokes != NULL); for(n=0; n < 20; n++) { keystrokes->keySymbols[n] = malloc(120); sprintf(keystrokes->keySymbols[n], ">%ld<>%d<", lT, n); } for(n=0; n < 20; n++) { printf("%s\n", keystrokes->keySymbols[n]); free(keystrokes->keySymbols[n]); } free(keystrokes); } return(0); } /*}}}*/ /* TEST JIG ROUTINES NOT DIRECTLY ASSOCIATED WITH SPECIFIC STRUCTS }}}*/ /* MAIN() {{{ */ int main(int argc, char *argv[]) /* {{{ */ { struct PICKINFO * pickInfo; int choiceno; printf("Begin\n"); pickInfo = newPickInfo(); setUpWindows(pickInfo); readRecords(pickInfo, "presidents.txt"); if(!checkDimensions(pickInfo)) exit(1); initscr(); /* start ncurses */ cbreak(); /* immediately acquire each keystroke */ noecho(); /* do not echo user keystrokes */ keypad(stdscr, TRUE); /* enable detection of function keys */ initColors(); /* enable colors and initialize pairs */ /* SET UP AND PAINT STANDARD SCREEN */ wattrset(stdscr, COLOR_PAIR(WHITEONBLUE) | WA_BOLD); wclrscr(stdscr); mvwaddstr(stdscr, 10, 10, "Simple color menu"); touchwin(stdscr); wrefresh(stdscr); /* ACQUIRE THE USER'S CHOICE */ choiceno = runMenu(pickInfo, stdscr); mvwaddstr(stdscr, 22, 0, "Hit any key to finish==>"); touchwin(stdscr); wrefresh(stdscr); getch(); endwin(); printf("\n\nYou chose item %d\n", choiceno); /* printf("\n\nYou chose item %d, %s\n", choiceno, pickInfo->rowsInfo->rows[choiceno]->displayString); */ destroyPickInfo(pickInfo); return(0); exit(1); testMenuStructure(pickInfo); testPickInfo(); exit(1); printf("sizeof KBDKEYS8 is %d\n", sizeof(KBDKEYS8)); printf("sizeof struct KEYSTROKES is %d\n", sizeof(struct KEYSTROKES)); printf("Int value of NULLCHAR is %d\n", (int) NULLCHAR); printf("Int value of NULLACTIONTYPE is %d\n", (int) NULLACTIONTYPE); testKeystrokes(); testx(); testAllKeySymbols(); testKeySymbol(); /* testRowsInfo(); exit(1); */ exit(2); printf("End\n"); return(0); } /*}}}*/ /* END MAIN() }}} */ /* END FUNCTION DEFINITIONS }}} */