#include "cdk.h" /* * Declare file local prototypes. */ static void drawCDKScrollList (CDKSCROLL *scrollp, boolean Box); static void createCDKScrollItemList (CDKSCROLL *scrollp, boolean numbers, char **list, int listSize); DeclareCDKObjects(my_funcs,Scroll); /* * This function creates a new scrolling list widget. */ CDKSCROLL *newCDKScroll (CDKSCREEN *cdkscreen, int xplace, int yplace, int splace, int height, int width, char *title, char **list, int listSize, boolean numbers, chtype highlight, boolean Box, boolean shadow) { /* Declare local variables. */ CDKSCROLL *scrollp = newCDKObject(CDKSCROLL, &my_funcs); chtype *holder = 0; int parentWidth = getmaxx(cdkscreen->window) - 1; int parentHeight = getmaxy(cdkscreen->window) - 1; int boxWidth = width; int boxHeight = height; int maxWidth = INT_MIN; int xpos = xplace; int ypos = yplace; int scrollAdjust = 0; char **temp = 0; int x, len, junk2; /* * If the height is a negative value, the height will * be ROWS-height, otherwise, the height will be the * given height. */ boxHeight = setWidgetDimension (parentHeight, height, 0); /* * If the width is a negative value, the width will * be COLS-width, otherwise, the width will be the * given width. */ boxWidth = setWidgetDimension (parentWidth, width, 0); /* Translate the char * items to chtype * */ if (title != 0) { temp = CDKsplitString (title, '\n'); scrollp->titleLines = CDKcountStrings (temp); /* We need to determine the widest title line. */ for (x=0; x < scrollp->titleLines; x++) { holder = char2Chtype (temp[x], &len, &junk2); maxWidth = MAXIMUM (maxWidth, len); freeChtype (holder); } boxWidth = MAXIMUM (boxWidth, maxWidth + 2); /* For each line in the title, convert from char * to chtype * */ for (x=0; x < scrollp->titleLines; x++) { scrollp->title[x] = char2Chtype (temp[x], &scrollp->titleLen[x], &scrollp->titlePos[x]); scrollp->titlePos[x] = justifyString (boxWidth, scrollp->titleLen[x], scrollp->titlePos[x]); } CDKfreeStrings(temp); } else { /* No title? Set the required variables. */ scrollp->titleLines = 0; } /* Set the box height. */ if (scrollp->titleLines > boxHeight) { if (listSize > 8) { boxHeight = scrollp->titleLines + 10; } else { boxHeight = scrollp->titleLines + listSize + 2; } } /* Set the rest of the variables. */ scrollp->titleAdj = scrollp->titleLines + 1; scrollp->listSize = listSize; scrollp->viewSize = boxHeight - (2 + scrollp->titleLines); scrollp->lastItem = listSize - 1; scrollp->maxTopItem = listSize - scrollp->viewSize; /* Is the view size larger than the list? */ if (listSize < scrollp->viewSize) { // scrollp->viewSize = listSize; // rubik // rubik scrollp->listSize = listSize; scrollp->lastItem = listSize; scrollp->maxTopItem = -1; } /* Adjust the box width if there is a scrollp bar. */ if ((splace == LEFT) || (splace == RIGHT)) { scrollp->scrollbar = TRUE; scrollAdjust = 1; boxWidth += 1; } else { scrollp->scrollbar = FALSE; } /* * Make sure we didn't extend beyond the dimensions of the window. */ boxWidth = (boxWidth > parentWidth ? (parentWidth-scrollAdjust) : boxWidth); boxHeight = (boxHeight > parentHeight ? parentHeight : boxHeight); /* Determine the size of the scrollbar toggle and the step. */ scrollp->step = (float)(boxHeight-2) / (float)scrollp->listSize; scrollp->toggleSize = (scrollp->listSize > (boxHeight-2) ? 1 : ceilCDK(scrollp->step)); /* Rejustify the x and y positions if we need to. */ alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight); /* Make the scrolling window */ scrollp->win = newwin (boxHeight, boxWidth, ypos, xpos); /* Is the scrolling window null?? */ if (scrollp->win == 0) { /* Clean up any memory. */ for (x=0; x < scrollp->titleLines; x++) { freeChtype (scrollp->title[x]); } free(scrollp); /* Return a null pointer. */ return (0); } /* Turn the keypad on for the window. */ keypad (scrollp->win, TRUE); /* Create the scrollbar window. */ if (splace == RIGHT) { scrollp->scrollbarWin = subwin (scrollp->win, boxHeight-scrollp->titleAdj-1, 1, ypos + scrollp->titleAdj, xpos + boxWidth-2); } else if (splace == LEFT) { scrollp->scrollbarWin = subwin (scrollp->win, boxHeight, 1, getbegy(scrollp->win) + scrollp->titleAdj, getbegx(scrollp->win) + 1); } else { scrollp->scrollbarWin = 0; } /* Set the rest of the variables */ ScreenOf(scrollp) = cdkscreen; scrollp->parent = cdkscreen->window; scrollp->shadowWin = 0; scrollp->boxHeight = boxHeight; scrollp->boxWidth = boxWidth; scrollp->scrollbarPlacement = splace; scrollp->maxLeftChar = 0; scrollp->currentTop = 0; scrollp->currentItem = 0; scrollp->currentHigh = 0; scrollp->leftChar = 0; scrollp->highlight = highlight; scrollp->exitType = vNEVER_ACTIVATED; ObjOf(scrollp)->box = Box; scrollp->shadow = shadow; scrollp->preProcessFunction = 0; scrollp->preProcessData = 0; scrollp->postProcessFunction = 0; scrollp->postProcessData = 0; scrollp->ULChar = ACS_ULCORNER; scrollp->URChar = ACS_URCORNER; scrollp->LLChar = ACS_LLCORNER; scrollp->LRChar = ACS_LRCORNER; scrollp->HChar = ACS_HLINE; scrollp->VChar = ACS_VLINE; scrollp->BoxAttrib = A_NORMAL; /* Create the scrolling list item list and needed variables. */ createCDKScrollItemList (scrollp, numbers, list, listSize); /* Do we need to create a shadow? */ if (shadow) { scrollp->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1); } /* Clean the key bindings. */ cleanCDKObjectBindings (vSCROLL, scrollp); /* Register this baby. */ registerCDKObject (cdkscreen, vSCROLL, scrollp); /* Return the scrolling list */ return scrollp; } /* * This actually does all the 'real' work of managing the scrolling list. */ int activateCDKScroll (CDKSCROLL *scrollp, chtype *actions) { /* Draw the scrolling list */ drawCDKScroll (scrollp, ObjOf(scrollp)->box); /* Check if actions is null. */ if (actions == 0) { /* Declare some local variables. */ chtype input; int ret; for (;;) { /* Get the input. */ input = wgetch (scrollp->win); /* Inject the character into the widget. */ ret = injectCDKScroll (scrollp, input); if (scrollp->exitType != vEARLY_EXIT) { return ret; } } } else { /* Declare some local variables. */ int length = chlen (actions); int x = 0; int ret; /* Inject each character one at a time. */ for (x=0; x < length; x++) { ret = injectCDKScroll (scrollp, actions[x]); if (scrollp->exitType != vEARLY_EXIT) { return ret; } } } /* Set the exit type for the widget and return. */ scrollp->exitType = vEARLY_EXIT; return -1; } /* * This injects a single character into the widget. */ int injectCDKScroll (CDKSCROLL *scrollp, chtype input) { /* Declare local variables. */ int ppReturn = 1; /* Set the exit type for the widget. */ scrollp->exitType = vEARLY_EXIT; /* Draw the scrolling list */ drawCDKScrollList (scrollp, ObjOf(scrollp)->box); /* Check if there is a pre-process function to be called. */ if (scrollp->preProcessFunction != 0) { /* Call the pre-process function. */ ppReturn = scrollp->preProcessFunction (vSCROLL, scrollp, scrollp->preProcessData, input); } /* Should we continue? */ if (ppReturn != 0) { /* Check for a predefined key binding. */ if (checkCDKObjectBind (vSCROLL, scrollp, input) != 0) { scrollp->exitType = vESCAPE_HIT; return -1; } else { switch (input) { case KEY_UP : if (scrollp->listSize > 0) { if (scrollp->currentItem > 0) { if (scrollp->currentHigh == 0) { if (scrollp->currentTop != 0) { scrollp->currentTop--; scrollp->currentItem--; } else { Beep(); } } else { scrollp->currentItem--; scrollp->currentHigh--; } } else { Beep(); } } else { Beep(); } break; case KEY_DOWN : if (scrollp->listSize > 0) { if (scrollp->currentItem < scrollp->listSize-1) { if (scrollp->currentHigh == scrollp->viewSize - 1) { /* We need to scroll down one line. */ if (scrollp->currentTop < scrollp->maxTopItem) { scrollp->currentTop++; scrollp->currentItem++; } else { Beep(); } } else { scrollp->currentItem++; scrollp->currentHigh++; } } else { Beep(); } } else { Beep(); } break; case KEY_RIGHT : if (scrollp->listSize > 0) { if (scrollp->leftChar >= scrollp->maxLeftChar) { Beep(); } else { scrollp->leftChar ++; } } else { Beep(); } break; case KEY_LEFT : if (scrollp->listSize > 0) { if (scrollp->leftChar == 0) { Beep(); } else { scrollp->leftChar --; } } else { Beep(); } break; case KEY_PPAGE : case CONTROL('B') : if (scrollp->listSize > 0) { if (scrollp->currentTop > 0) { if (scrollp->currentTop >= (scrollp->viewSize -1)) { scrollp->currentTop -= (scrollp->viewSize - 1); scrollp->currentItem -= (scrollp->viewSize - 1); } else { scrollp->currentTop = 0; scrollp->currentItem = 0; scrollp->currentHigh = 0; } } else { Beep(); } } else { Beep(); } break; case KEY_NPAGE : case CONTROL('F') : if (scrollp->listSize > 0) { if (scrollp->currentTop < scrollp->maxTopItem) { if ((scrollp->currentTop + scrollp->viewSize - 1) <= scrollp->maxTopItem) { scrollp->currentTop += (scrollp->viewSize - 1); scrollp->currentItem += (scrollp->viewSize - 1); } else { scrollp->currentTop = scrollp->maxTopItem; scrollp->currentItem = scrollp->lastItem; scrollp->currentHigh = scrollp->viewSize-1; } } else { Beep(); } } else { Beep(); } break; case 'g' : case '1' : case KEY_HOME : scrollp->currentTop = 0; scrollp->currentItem = 0; scrollp->currentHigh = 0; break; case 'G' : case KEY_END : scrollp->currentTop = scrollp->maxTopItem; scrollp->currentItem = scrollp->lastItem; scrollp->currentHigh = scrollp->viewSize-1; break; case '$' : scrollp->leftChar = scrollp->maxLeftChar; break; case '|' : scrollp->leftChar = 0; break; case KEY_ESC : scrollp->exitType = vESCAPE_HIT; return -1; case CDK_REFRESH : eraseCDKScreen (ScreenOf(scrollp)); refreshCDKScreen (ScreenOf(scrollp)); break; case KEY_RETURN : case KEY_TAB : case KEY_ENTER : scrollp->exitType = vNORMAL; return scrollp->currentItem; default : break; } } /* Should we call a post-process? */ if (scrollp->postProcessFunction != 0) { scrollp->postProcessFunction (vSCROLL, scrollp, scrollp->postProcessData, input); } } /* Redraw the list */ drawCDKScrollList (scrollp, ObjOf(scrollp)->box); /* Set the exit type and return. */ scrollp->exitType = vEARLY_EXIT; return -1; } /* rubik add-on * this allows the user to scroll down one line the box, even if the selected item is not the last one */ void scrolldownCDKScroll (CDKSCROLL *scrollp) { if (scrollp->currentTop < scrollp->maxTopItem) { scrollp->currentTop++; scrollp->currentItem++; drawCDKScrollList (scrollp, ObjOf(scrollp)->box); } else { Beep(); } } /* rubik add-on * this allows the user to scroll up one line the box, even if the selected item is not the first one */ void scrollupCDKScroll (CDKSCROLL *scrollp) { if (scrollp->currentTop != 0) { scrollp->currentTop--; scrollp->currentItem--; drawCDKScrollList (scrollp, ObjOf(scrollp)->box); } else { Beep(); } } /* * This allows the user to accelerate to a position in the scrolling list. */ void setCDKScrollPosition (CDKSCROLL *scrollp, int item) { if (item < 0) { scrollp->currentTop = 0; scrollp->currentItem = 0; scrollp->currentHigh = 1; } else if (item > scrollp->listSize-1) { scrollp->currentTop = scrollp->maxTopItem; scrollp->currentItem = scrollp->lastItem; scrollp->currentHigh = scrollp->viewSize-1; } else { scrollp->currentTop = item; scrollp->currentItem = item; scrollp->currentHigh = 0; } } /* * This moves the scroll field to the given location. */ static void _moveCDKScroll (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag) { CDKSCROLL *scrollp = (CDKSCROLL *)object; /* Declare local variables. */ int currentX = getbegx(scrollp->win); int currentY = getbegy(scrollp->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(scrollp->win) + xplace; ypos = getbegy(scrollp->win) + yplace; } /* Adjust the window if we need to. */ alignxy (WindowOf(scrollp), &xpos, &ypos, scrollp->boxWidth, scrollp->boxHeight); /* Get the difference. */ xdiff = currentX - xpos; ydiff = currentY - ypos; /* Move the window to the new location. */ moveCursesWindow(scrollp->win, -xdiff, -ydiff); /* If there is a shadow box we have to move it too. */ if (scrollp->shadowWin != 0) { moveCursesWindow(scrollp->shadowWin, -xdiff, -ydiff); } /* If there is a scrollbar we have to move it too. */ if (scrollp->scrollbar) { moveCursesWindow(scrollp->scrollbarWin, -xdiff, -ydiff); } /* Touch the windows so they 'move'. */ touchwin (WindowOf(scrollp)); wrefresh (WindowOf(scrollp)); /* Redraw the window, if they asked for it. */ if (refresh_flag) { drawCDKScroll (scrollp, ObjOf(scrollp)->box); } } /* * This function draws the scrolling list widget. */ static void _drawCDKScroll (CDKOBJS *object, boolean Box) { CDKSCROLL *scrollp = (CDKSCROLL *)object; int x; /* Draw in the shadow if we need to. */ if (scrollp->shadowWin != 0) { drawShadow (scrollp->shadowWin); } /* Draw in the title if there is one. */ if (scrollp->titleLines != 0) { for (x=0; x < scrollp->titleLines; x++) { writeChtype (scrollp->win, scrollp->titlePos[x], x + 1, scrollp->title[x], HORIZONTAL, 0, scrollp->titleLen[x]); } } /* Draw in the scolling list items. */ drawCDKScrollList (scrollp, Box); } /* * This redraws the scrolling list. */ static void drawCDKScrollList (CDKSCROLL *scrollp, boolean Box) { /* Declare some local vars */ int scrollbarAdj = 0; int screenPos = 0; char emptyString[1000]; int x; /* * If the scroll bar is on the left hand side, then adjust * everything over to the right one character. */ if (scrollp->numbers == FALSE) { scrollbarAdj = (scrollp->scrollbarPlacement == LEFT ? 2 : 0); } else { scrollbarAdj = 1; } /* If the list is empty, don't draw anything. */ if (scrollp->listSize < 1) { /* Box it if needed. */ if (Box) { attrbox (scrollp->win, scrollp->ULChar, scrollp->URChar, scrollp->LLChar, scrollp->LRChar, scrollp->HChar, scrollp->VChar, scrollp->BoxAttrib); } /* Refresh the window. */ touchwin (scrollp->win); wrefresh (scrollp->win); return; } /* Create the empty string. */ cleanChar (emptyString, scrollp->boxWidth-1, ' '); /* Redraw the list */ for (x=0; x < scrollp->viewSize; x++) { /* Draw the elements in the scrolling list. */ if (x < scrollp->listSize) { screenPos = scrollp->itemPos[x + scrollp->currentTop]-scrollp->leftChar + scrollbarAdj; /* Draw in an empty line. */ writeChar (scrollp->win, 1, scrollp->titleAdj + x, emptyString, HORIZONTAL, 0, (int)strlen(emptyString)); /* Write in the correct line. */ if (screenPos >= 0) { writeChtype (scrollp->win, screenPos, x + scrollp->titleAdj, scrollp->item[x + scrollp->currentTop], HORIZONTAL, 0, scrollp->itemLen[x + scrollp->currentTop]); } else { writeChtype (scrollp->win, 1, x + scrollp->titleAdj, scrollp->item[x + scrollp->currentTop], HORIZONTAL, scrollp->leftChar - scrollp->itemPos[scrollp->currentTop] + 1, scrollp->itemLen[x + scrollp->currentTop]); } } else { /* Draw in an empty line. */ writeChar (scrollp->win, 1, scrollp->titleAdj + x, emptyString, HORIZONTAL, 0, (int)strlen(emptyString)); } } screenPos = scrollp->itemPos[scrollp->currentItem]-scrollp->leftChar + scrollbarAdj; /* Rehighlight the current menu item. */ if (screenPos >= 0) { writeChtypeAttrib (scrollp->win, screenPos, scrollp->currentHigh + scrollp->titleAdj, scrollp->item[scrollp->currentItem], scrollp->highlight, HORIZONTAL, 0, scrollp->itemLen[scrollp->currentItem]); } else { writeChtypeAttrib (scrollp->win, 1 + scrollbarAdj, scrollp->currentHigh + scrollp->titleAdj, scrollp->item[scrollp->currentItem], scrollp->highlight, HORIZONTAL, scrollp->leftChar - scrollp->itemPos[scrollp->currentTop] + 1, scrollp->itemLen[scrollp->currentItem]); } /* Determine where the toggle is supposed to be. */ if (scrollp->scrollbarWin != 0) { if (scrollp->listSize > scrollp->boxHeight-2) { scrollp->togglePos = floorCDK((float)scrollp->currentItem * (float)scrollp->step); } else { scrollp->togglePos = ceilCDK((float)scrollp->currentItem * (float)scrollp->step); } /* Make sure the toggle button doesn't go out of bounds. */ scrollbarAdj = (scrollp->togglePos + scrollp->toggleSize)-(scrollp->boxHeight-scrollp->titleAdj-1); if (scrollbarAdj > 0) { scrollp->togglePos -= scrollbarAdj; } /* Draw the scrollbar. */ for (x=0; x < scrollp->boxHeight-1; x++) { mvwaddch (scrollp->scrollbarWin, x, 0, ACS_CKBOARD); } for (x=scrollp->togglePos; x < scrollp->togglePos + scrollp->toggleSize; x++) { mvwaddch (scrollp->scrollbarWin, x, 0, ' ' | A_REVERSE); } touchwin (scrollp->scrollbarWin); wrefresh (scrollp->scrollbarWin); } /* Box it if needed. */ if (Box) { attrbox (scrollp->win, scrollp->ULChar, scrollp->URChar, scrollp->LLChar, scrollp->LRChar, scrollp->HChar, scrollp->VChar, scrollp->BoxAttrib); } /* Refresh the window. */ touchwin (scrollp->win); wrefresh (scrollp->win); } /* * These functions set the drawing characters of the widget. */ void setCDKScrollULChar (CDKSCROLL *scrollp, chtype character) { scrollp->ULChar = character; } void setCDKScrollURChar (CDKSCROLL *scrollp, chtype character) { scrollp->URChar = character; } void setCDKScrollLLChar (CDKSCROLL *scrollp, chtype character) { scrollp->LLChar = character; } void setCDKScrollLRChar (CDKSCROLL *scrollp, chtype character) { scrollp->LRChar = character; } void setCDKScrollVerticalChar (CDKSCROLL *scrollp, chtype character) { scrollp->VChar = character; } void setCDKScrollHorizontalChar (CDKSCROLL *scrollp, chtype character) { scrollp->HChar = character; } void setCDKScrollBoxAttribute (CDKSCROLL *scrollp, chtype character) { scrollp->BoxAttrib = character; } /* * This sets the background color of the widget. */ void setCDKScrollBackgroundColor (CDKSCROLL *scrollp, char *color) { chtype *holder = 0; int junk1, junk2; /* Make sure the color isn't null. */ if (color == 0) { return; } /* Convert the value of the environment variable to a chtype. */ holder = char2Chtype (color, &junk1, &junk2); /* Set the widgets background color. */ wbkgd (scrollp->win, holder[0]); if (scrollp->scrollbarWin != 0) { wbkgd (scrollp->scrollbarWin, holder[0]); } /* Clean up. */ freeChtype (holder); } /* * This function destroys */ void destroyCDKScroll (CDKSCROLL *scrollp) { /* Declare local variables. */ int x; /* Erase the object. */ eraseCDKScroll (scrollp); /* Clean up the char pointers. */ for (x=0; x < scrollp->titleLines; x++) { freeChtype (scrollp->title[x]); } for (x=0; x < scrollp->listSize; x++) { freeChtype (scrollp->item[x]); } /* Clean up the windows. */ deleteCursesWindow (scrollp->scrollbarWin); deleteCursesWindow (scrollp->shadowWin); deleteCursesWindow (scrollp->win); /* Unregister this object. */ unregisterCDKObject (vSCROLL, scrollp); /* Finish cleaning up. */ free (scrollp); } /* * This function erases the scrolling list from the screen. */ static void _eraseCDKScroll (CDKOBJS *object) { CDKSCROLL *scrollp = (CDKSCROLL *)object; eraseCursesWindow (scrollp->win); eraseCursesWindow (scrollp->shadowWin); } /* * This function creates massages the scrolling list information and * sets up the needed variables for the scrolling list to work correctly. */ static void createCDKScrollItemList (CDKSCROLL *scrollp, boolean numbers, char **list, int listSize) { /* Declare local variables. */ int widestItem = 0; int x = 0; char temp[100]; /* Create the items in the scrolling list. */ if (numbers == NUMBERS) { for (x=0 ; x < listSize; x++) { sprintf (temp, "%4d. %s", x + 1, list[x]); scrollp->item[x] = char2Chtype (temp, &scrollp->itemLen[x], &scrollp->itemPos[x]); scrollp->itemPos[x] = justifyString (scrollp->boxWidth, scrollp->itemLen[x], scrollp->itemPos[x]); widestItem = MAXIMUM (scrollp->itemLen[x], widestItem); } } else { for (x=0 ; x < listSize; x++) { scrollp->item[x] = char2Chtype (list[x], &scrollp->itemLen[x], &scrollp->itemPos[x]); scrollp->itemPos[x] = justifyString (scrollp->boxWidth, scrollp->itemLen[x], scrollp->itemPos[x]); widestItem = MAXIMUM (scrollp->itemLen[x], widestItem); } } /* Determine how many characters we can shift to the right */ /* before all the items have been scrolled off the screen. */ if (scrollp->boxWidth > widestItem) { scrollp->maxLeftChar = 0; } else { scrollp->maxLeftChar = widestItem-(scrollp->boxWidth-2); } /* Keep the boolean flag 'numbers' */ scrollp->numbers = numbers; } /* * This sets certain attributes of the scrolling list. */ void setCDKScroll (CDKSCROLL *scrollp, char **list, int listSize, boolean numbers, chtype highlight, boolean Box) { setCDKScrollItems (scrollp, list, listSize, numbers); setCDKScrollHighlight (scrollp, highlight); setCDKScrollBox (scrollp, Box); } /* * This sets the scrolling list items. */ void setCDKScrollItems (CDKSCROLL *scrollp, char **list, int listSize, boolean numbers) { /* Declare some wars. */ char emptyString[2000]; int x = 0; /* Clean out the old list. */ for (x=0; x < scrollp->listSize; x++) { freeChtype (scrollp->item[x]); scrollp->itemLen[x] = 0; scrollp->itemPos[x] = 0; } /* Clean up the display. */ cleanChar (emptyString, scrollp->boxWidth-1, ' '); for (x=0; x < scrollp->viewSize ; x++) { writeChar (scrollp->win, 1, scrollp->titleAdj + x, emptyString, HORIZONTAL, 0, (int)strlen(emptyString)); } /* Readjust all of the variables ... */ scrollp->listSize = listSize; scrollp->viewSize = scrollp->boxHeight - (2 + scrollp->titleLines); scrollp->lastItem = listSize - 1; scrollp->maxTopItem = listSize - scrollp->viewSize; /* Is the view size smaller then the window? */ if (listSize < (scrollp->boxHeight-1-scrollp->titleAdj)) { scrollp->viewSize = listSize; scrollp->listSize = listSize; scrollp->lastItem = listSize; scrollp->maxTopItem = -1; } /* Set some vars. */ scrollp->currentTop = 0; scrollp->currentItem = 0; scrollp->currentHigh = 0; scrollp->leftChar = 0; /* Set the information for the scroll bar. */ scrollp->step = (float)(scrollp->boxHeight-2) / (float)scrollp->listSize; scrollp->toggleSize = (scrollp->listSize > (scrollp->boxHeight-2) ? 1 : ceilCDK(scrollp->step)); /* Set up the new list. */ createCDKScrollItemList (scrollp, numbers, list, listSize); } int getCDKScrollItems (CDKSCROLL *scrollp, char *list[]) { int x; for (x=0; x < scrollp->listSize; x++) { list[x] = chtype2Char (scrollp->item[x]); } return scrollp->listSize; } /* * This sets the highlight of the scrolling list. */ void setCDKScrollHighlight (CDKSCROLL *scrollp, chtype highlight) { scrollp->highlight = highlight; } chtype getCDKScrollHighlight (CDKSCROLL *scrollp, chtype highlight GCC_UNUSED) { return scrollp->highlight; } /* * This sets the box attribute of the scrolling list. */ void setCDKScrollBox (CDKSCROLL *scrollp, boolean Box) { ObjOf(scrollp)->box = Box; } boolean getCDKScrollBox (CDKSCROLL *scrollp) { return ObjOf(scrollp)->box; } /* * This adds a single item to a scrolling list. */ void addCDKScrollItem (CDKSCROLL *scrollp, char *item) { /* Declare some local variables. */ int itemNumber = scrollp->listSize; int widestItem = scrollp->maxLeftChar + (scrollp->boxWidth-2); char temp[256]; /* * If the scrolling list has numbers, then add the new item * with a numeric value attached. */ if (scrollp->numbers == NUMBERS) { sprintf (temp, "%4d. %s", itemNumber + 1, item); scrollp->item[itemNumber] = char2Chtype (temp, &scrollp->itemLen[itemNumber], &scrollp->itemPos[itemNumber]); scrollp->itemPos[itemNumber] = justifyString (scrollp->boxWidth, scrollp->itemLen[itemNumber], scrollp->itemPos[itemNumber]); } else { scrollp->item[itemNumber] = char2Chtype (item, &scrollp->itemLen[itemNumber], &scrollp->itemPos[itemNumber]); scrollp->itemPos[itemNumber] = justifyString (scrollp->boxWidth, scrollp->itemLen[itemNumber], scrollp->itemPos[itemNumber]); } /* Determine the size of the widest item. */ widestItem = MAXIMUM (scrollp->itemLen[itemNumber], widestItem); if (scrollp->boxWidth > widestItem) { scrollp->maxLeftChar = 0; } else { scrollp->maxLeftChar = widestItem - (scrollp->boxWidth-2); } /* Increment the list size. */ scrollp->listSize++; if (scrollp->listSize < scrollp->viewSize) { scrollp->lastItem = scrollp->listSize; scrollp->maxTopItem = -1; } else { scrollp->lastItem = scrollp->listSize - 1; scrollp->maxTopItem = scrollp->listSize - scrollp->viewSize; } /* Reset some variables. */ scrollp->currentHigh = 0; scrollp->currentTop = 0; scrollp->currentItem = 0; scrollp->leftChar = 0; } /* * This adds a single item to a scrolling list. */ void deleteCDKScrollItem (CDKSCROLL *scrollp, int position) { /* Declare some local variables. */ int x; /* Nuke the current item. */ freeChtype (scrollp->item[position]); /* Adjust the list. */ for (x=position; x < scrollp->listSize-1; x++) { scrollp->item[x] = scrollp->item[x + 1]; scrollp->itemLen[x] = scrollp->itemLen[x + 1]; scrollp->itemPos[x] = scrollp->itemPos[x + 1]; } scrollp->listSize--; /* Did we just delete the last element? */ if (scrollp->listSize == 0) { scrollp->lastItem = -1; scrollp->maxTopItem = -1; scrollp->currentHigh = -1; scrollp->currentItem = -1; scrollp->currentTop = -1; } else { scrollp->lastItem--; scrollp->maxTopItem--; scrollp->currentHigh = 0; scrollp->currentItem = 0; scrollp->currentTop = 0; } } /* * This function sets the pre-process function. */ void setCDKScrollPreProcess (CDKSCROLL *scrollp, PROCESSFN callback, void *data) { scrollp->preProcessFunction = callback; scrollp->preProcessData = data; } /* * This function sets the post-process function. */ void setCDKScrollPostProcess (CDKSCROLL *scrollp, PROCESSFN callback, void *data) { scrollp->postProcessFunction = callback; scrollp->postProcessData = data; }