#include /* * $Author: tom $ * $Date: 2004/08/31 23:26:45 $ * $Revision: 1.73 $ */ static int createList (CDKITEMLIST *itemlist, char **item, int count); DeclareCDKObjects(ITEMLIST, Itemlist, setCdk, Int); /* * This creates a pointer to an itemlist widget. */ CDKITEMLIST *newCDKItemlist (CDKSCREEN *cdkscreen, int xplace, int yplace, char *title, char *label, char **item, int count, int defaultItem, boolean Box, boolean shadow) { /* Set up some variables. */ CDKITEMLIST *itemlist = 0; int parentWidth = getmaxx(cdkscreen->window); int parentHeight = getmaxy(cdkscreen->window); int boxWidth = 0; int boxHeight; int maxWidth = INT_MIN; int fieldWidth = 0; int xpos = xplace; int ypos = yplace; int x, junk; if ((itemlist = newCDKObject(CDKITEMLIST, &my_funcs)) == 0 || !createList(itemlist, item, count)) { destroyCDKObject (itemlist); return (0); } setCDKItemlistBox (itemlist, Box); boxHeight = (BorderOf(itemlist) * 2) + 1; /* Set some basic values of the itemlist. */ itemlist->label = 0; itemlist->labelLen = 0; itemlist->labelWin = 0; /* Translate the label char *pointer to a chtype pointer. */ if (label != 0) { itemlist->label = char2Chtype (label, &itemlist->labelLen, &junk); } /* Go through the list and determine the widest item. */ for (x=0; x < count; x++) { maxWidth = MAXIMUM (maxWidth, itemlist->itemLen[x]); } /* * Set the box width. Allow an extra char in field width for cursor */ fieldWidth = maxWidth + 1; boxWidth = fieldWidth + itemlist->labelLen + 2 * BorderOf(itemlist); boxWidth = setCdkTitle(ObjOf(itemlist), title, boxWidth); boxHeight += TitleLinesOf(itemlist); /* * Make sure we didn't extend beyond the dimensions of the window. */ boxWidth = (boxWidth > parentWidth ? parentWidth : boxWidth); boxHeight = (boxHeight > parentHeight ? parentHeight : boxHeight); fieldWidth = MINIMUM(fieldWidth, boxWidth - itemlist->labelLen - 2 * BorderOf(itemlist)); /* Rejustify the x and y positions if we need to. */ alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight); /* Make the window. */ itemlist->win = newwin(boxHeight, boxWidth, ypos, xpos); if (itemlist->win == 0) { destroyCDKObject (itemlist); return (0); } /* Make the label window if there was a label. */ if (itemlist->label != 0) { itemlist->labelWin = subwin (itemlist->win, 1, itemlist->labelLen, ypos + BorderOf(itemlist) + TitleLinesOf(itemlist), xpos + BorderOf(itemlist)); if (itemlist->labelWin == 0) { destroyCDKObject (itemlist); return (0); } } keypad (itemlist->win, TRUE); /* Make the field window */ itemlist->fieldWin = subwin (itemlist->win, 1, fieldWidth, ypos + BorderOf(itemlist) + TitleLinesOf(itemlist), xpos + itemlist->labelLen + BorderOf(itemlist)); if (itemlist->fieldWin == 0) { destroyCDKObject (itemlist); return (0); } keypad (itemlist->fieldWin, TRUE); /* Set up the rest of the structure. */ ScreenOf(itemlist) = cdkscreen; itemlist->parent = cdkscreen->window; itemlist->shadowWin = 0; itemlist->boxHeight = boxHeight; itemlist->boxWidth = boxWidth; itemlist->fieldWidth = fieldWidth; itemlist->listSize = count; initExitType(itemlist); ObjOf(itemlist)->acceptsFocus = TRUE; ObjOf(itemlist)->inputWindow = itemlist->fieldWin; itemlist->shadow = shadow; setCDKItemlistBox (itemlist, Box); /* Set then default item. */ if (defaultItem >= 0 && defaultItem < itemlist->listSize) { itemlist->currentItem = defaultItem; itemlist->defaultItem = defaultItem; } else { itemlist->currentItem = 0; itemlist->defaultItem = 0; } /* Do we want a shadow??? */ if (shadow) { itemlist->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1); if (itemlist->shadowWin == 0) { destroyCDKObject (itemlist); return (0); } } /* Clean the key bindings. */ cleanCDKObjectBindings (vITEMLIST, itemlist); /* Register this baby. */ registerCDKObject (cdkscreen, vITEMLIST, itemlist); /* Return the pointer to the structure */ return (itemlist); } /* * This allows the user to play with the widget. */ int activateCDKItemlist (CDKITEMLIST *itemlist, chtype *actions) { /* Declare local variables. */ int ret = -1; /* Draw the widget. */ drawCDKItemlist (itemlist, ObjOf(itemlist)->box); drawCDKItemlistField(itemlist, TRUE); /* Check if actions is null. */ if (actions == 0) { chtype input = 0; for (;;) { /* Get the input. */ input = getcCDKObject (ObjOf(itemlist)); /* Inject the character into the widget. */ ret = injectCDKItemlist (itemlist, input); if (itemlist->exitType != vEARLY_EXIT) { return ret; } } } else { int length = chlen (actions); int x = 0; /* Inject each character one at a time. */ for (x=0; x < length; x++) { ret = injectCDKItemlist (itemlist, actions[x]); if (itemlist->exitType != vEARLY_EXIT) { return ret; } } } /* Set the exit type and exit. */ setExitType(itemlist, 0); return ret; } /* * This injects a single character into the widget. */ static int _injectCDKItemlist (CDKOBJS *object, chtype input) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; /* Declare local variables. */ int ppReturn = 1; int ret = unknownInt; bool complete = FALSE; /* Set the exit type. */ setExitType(itemlist, 0); /* Draw the itemlist field. */ drawCDKItemlistField (itemlist,TRUE); /* Check if there is a pre-process function to be called. */ if (PreProcessFuncOf(itemlist) != 0) { /* Call the pre-process function. */ ppReturn = PreProcessFuncOf(itemlist) (vITEMLIST, itemlist, PreProcessDataOf(itemlist), input); } /* Should we continue? */ if (ppReturn != 0) { /* Check a predefined binding. */ if (checkCDKObjectBind (vITEMLIST, itemlist, input) != 0) { checkEarlyExit(itemlist); complete = TRUE; } else { switch (input) { case KEY_UP : case KEY_RIGHT : case SPACE : case '+' : case 'n' : if (itemlist->currentItem < itemlist->listSize - 1) { itemlist->currentItem++; } else { itemlist->currentItem = 0; } break; case KEY_DOWN : case KEY_LEFT : case '-' : case 'p' : if (itemlist->currentItem > 0) { itemlist->currentItem--; } else { itemlist->currentItem = itemlist->listSize - 1; } break; case 'd' : case 'D' : itemlist->currentItem = itemlist->defaultItem; break; case '0' : itemlist->currentItem = 0; break; case '$' : itemlist->currentItem = itemlist->listSize - 1; break; case KEY_ESC : setExitType(itemlist, input); complete = TRUE; break; case KEY_TAB : case KEY_ENTER : setExitType(itemlist, input); ret = itemlist->currentItem; complete = TRUE; break; case CDK_REFRESH : eraseCDKScreen (ScreenOf(itemlist)); refreshCDKScreen (ScreenOf(itemlist)); break; default : Beep(); break; } } /* Should we call a post-process? */ if (!complete && (PostProcessFuncOf(itemlist) != 0)) { PostProcessFuncOf(itemlist) (vITEMLIST, itemlist, PostProcessDataOf(itemlist), input); } } if (!complete) { drawCDKItemlistField (itemlist,TRUE); setExitType(itemlist, 0); } ResultOf(itemlist).valueInt = ret; return (ret != unknownInt); } /* * This moves the itemlist field to the given location. */ static void _moveCDKItemlist (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; /* Declare local variables. */ int currentX = getbegx(itemlist->win); int currentY = getbegy(itemlist->win); int xpos = xplace; int ypos = yplace; int xdiff = 0; int ydiff = 0; /* * If this is a relative move, then we will adjust where we want * to move to. */ if (relative) { xpos = getbegx(itemlist->win) + xplace; ypos = getbegy(itemlist->win) + yplace; } /* Adjust the window if we need to. */ alignxy (WindowOf(itemlist), &xpos, &ypos, itemlist->boxWidth, itemlist->boxHeight); /* Get the difference. */ xdiff = currentX - xpos; ydiff = currentY - ypos; /* Move the window to the new location. */ moveCursesWindow(itemlist->win, -xdiff, -ydiff); moveCursesWindow(itemlist->fieldWin, -xdiff, -ydiff); moveCursesWindow(itemlist->labelWin, -xdiff, -ydiff); moveCursesWindow(itemlist->shadowWin, -xdiff, -ydiff); /* Touch the windows so they 'move'. */ refreshCDKWindow (WindowOf(itemlist)); /* Redraw the window, if they asked for it. */ if (refresh_flag) { drawCDKItemlist (itemlist, ObjOf(itemlist)->box); } } /* * This draws the widget on the screen. */ static void _drawCDKItemlist (CDKOBJS *object, int Box) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; /* Did we ask for a shadow? */ if (itemlist->shadowWin != 0) { drawShadow (itemlist->shadowWin); } /* Box the widget if asked. */ if (Box) { drawObjBox (itemlist->win, ObjOf(itemlist)); } drawCdkTitle (itemlist->win, object); /* Draw in the label to the widget. */ if (itemlist->labelWin != 0) { writeChtype (itemlist->labelWin, 0, 0, itemlist->label, HORIZONTAL, 0, chlen(itemlist->label)); } refreshCDKWindow (itemlist->win); /* Draw in the field. */ drawCDKItemlistField(itemlist, FALSE); } /* * This sets the background attribute of the widget. */ static void _setBKattrItemlist (CDKOBJS *object, chtype attrib) { if (object != 0) { CDKITEMLIST *widget = (CDKITEMLIST *) object; wbkgd (widget->win, attrib); wbkgd (widget->fieldWin, attrib); if (widget->labelWin != 0) { wbkgd (widget->labelWin, attrib); } } } /* * This function draws the contents of the field. */ void drawCDKItemlistField (CDKITEMLIST *itemlist, boolean highlight) { /* Declare local vars. */ int currentItem = itemlist->currentItem; int len; int x; /* Determine how much we have to draw. */ len = MINIMUM (itemlist->itemLen[currentItem], itemlist->fieldWidth); /* Erase the field window. */ werase (itemlist->fieldWin); /* Draw in the current item in the field. */ for (x=0; x < len; x++) { chtype c = itemlist->item[currentItem][x]; if (highlight) { c = CharOf(c) | A_REVERSE; } mvwaddch (itemlist->fieldWin, 0, x + itemlist->itemPos[currentItem], c); } /* Redraw the field window. */ refreshCDKWindow (itemlist->fieldWin); } /* * This function removes the widget from the screen. */ static void _eraseCDKItemlist (CDKOBJS *object) { if (validCDKObject (object)) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; eraseCursesWindow (itemlist->fieldWin); eraseCursesWindow (itemlist->labelWin); eraseCursesWindow (itemlist->win); eraseCursesWindow (itemlist->shadowWin); } } /* * This function destroys the widget and all the memory it used. */ static void _destroyCDKItemlist (CDKOBJS *object) { if (object != 0) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; cleanCdkTitle (object); freeChtype (itemlist->label); CDKfreeChtypes (itemlist->item); /* Delete the windows. */ deleteCursesWindow (itemlist->fieldWin); deleteCursesWindow (itemlist->labelWin); deleteCursesWindow (itemlist->shadowWin); deleteCursesWindow (itemlist->win); /* Unregister this object. */ unregisterCDKObject (vITEMLIST, itemlist); } } /* * This sets multiple attributes of the widget. */ void setCDKItemlist (CDKITEMLIST *itemlist, char **list, int count, int current, boolean Box) { setCDKItemlistValues (itemlist, list, count, current); setCDKItemlistBox (itemlist, Box); } /* * This function sets the contents of the list. */ void setCDKItemlistValues (CDKITEMLIST *itemlist, char **item, int count, int defaultItem) { if (createList(itemlist, item, count)) { /* Set the default item. */ if ((defaultItem >= 0) && (defaultItem < itemlist->listSize)) { itemlist->currentItem = defaultItem; itemlist->defaultItem = defaultItem; } /* Draw the field. */ eraseCDKItemlist (itemlist); drawCDKItemlist (itemlist, ObjOf(itemlist)->box); } } chtype **getCDKItemlistValues (CDKITEMLIST *itemlist, int *size) { (*size) = itemlist->listSize; return itemlist->item; } /* * This sets the default/current item of the itemlist. */ void setCDKItemlistCurrentItem (CDKITEMLIST *itemlist, int currentItem) { /* Set the default item. */ if ((currentItem >= 0) && (currentItem < itemlist->listSize)) { itemlist->currentItem = currentItem; } } int getCDKItemlistCurrentItem (CDKITEMLIST *itemlist) { return itemlist->currentItem; } /* * This sets the default item in the list. */ void setCDKItemlistDefaultItem (CDKITEMLIST *itemlist, int defaultItem) { /* Make sure the item is in the correct range. */ if (defaultItem < 0) { itemlist->defaultItem = 0; } else if (defaultItem >= itemlist->listSize) { itemlist->defaultItem = itemlist->listSize - 1; } else { itemlist->defaultItem = defaultItem; } } int getCDKItemlistDefaultItem (CDKITEMLIST *itemlist) { return itemlist->defaultItem; } /* * This sets the box attribute of the itemlist widget. */ void setCDKItemlistBox (CDKITEMLIST *itemlist, boolean Box) { ObjOf(itemlist)->box = Box; ObjOf(itemlist)->borderSize = Box ? 1 : 0; } boolean getCDKItemlistBox (CDKITEMLIST *itemlist) { return ObjOf(itemlist)->box; } static void _focusCDKItemlist(CDKOBJS *object) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; drawCDKItemlistField (itemlist,TRUE); } static void _unfocusCDKItemlist(CDKOBJS *object) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; drawCDKItemlistField (itemlist,FALSE); } #if 0 static void _refreshDataCDKItemlist(CDKOBJS *object) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; if (ReturnOf(itemlist)) { switch (DataTypeOf(itemlist)) { default: case DataTypeInt: itemlist->currentItem = *((int*)ReturnOf(itemlist)); break; case DataTypeDouble: itemlist->currentItem = *((double*)ReturnOf(itemlist)); break; case DataTypeFloat: itemlist->currentItem = *((float*)ReturnOf(itemlist)); break; case DataTypeString: { int i; for (i=0; i < itemlist->listSize; ++i) if (!cmpStrChstr((char*)ReturnOf(itemlist),itemlist->item[i])) { itemlist->currentItem = i; break; } itemlist->currentItem = itemlist->defaultItem; break; } } drawCDKItemlistField(itemlist, FALSE); } } static void _saveDataCDKItemlist(CDKOBJS *object) { CDKITEMLIST *itemlist = (CDKITEMLIST *)object; if (ReturnOf(itemlist)) { switch (DataTypeOf(itemlist)) { default: case DataTypeInt: *((int*)ReturnOf(itemlist)) = itemlist->currentItem; break; case DataTypeFloat: *((float*)ReturnOf(itemlist)) = itemlist->currentItem; break; case DataTypeDouble: *((double*)ReturnOf(itemlist)) = itemlist->currentItem; break; case DataTypeString: chstrncpy((char*)ReturnOf(itemlist), itemlist->item[itemlist->currentItem], 9999); break; } } } #else dummyRefreshData(Itemlist) dummySaveData(Itemlist) #endif static int createList (CDKITEMLIST *itemlist, char **item, int count) { int status = 0; if (count > 0) { chtype **newItems = typeCallocN(chtype*, count + 1); int *newPos = typeCallocN(int, count + 1); int *newLen = typeCallocN(int, count + 1); int x; int fieldWidth = 0; if (newItems != 0 && newPos != 0 && newLen != 0) { /* Go through the list and determine the widest item. */ status = 1; for (x=0; x < count; x++) { /* Copy the item to the list. */ newItems[x] = char2Chtype (item[x], &newLen[x], &newPos[x]); if (newItems[x] == 0) { status = 0; break; } fieldWidth = MAXIMUM (fieldWidth, newLen[x]); } /* Now we need to justify the strings. */ for (x=0; x < count; x++) { newPos[x] = justifyString (fieldWidth + 1, newLen[x], newPos[x]); } } if (status) { /* Free up the old memory. */ CDKfreeChtypes (itemlist->item); freeChecked (itemlist->itemPos); freeChecked (itemlist->itemLen); /* Copy in the new information. */ itemlist->listSize = count; itemlist->item = newItems; itemlist->itemPos = newPos; itemlist->itemLen = newLen; } else { CDKfreeChtypes (newItems); freeChecked (newPos); freeChecked (newLen); } } return status; }