#include /* * $Author: Thorsten.Glaser $ * $Date: 2005/04/24 20:27:19 $ * $Revision: 1.151 $ */ /* * Declare some local definitions. */ #define DOWN 0 #define UP 1 /* * Declare file local prototypes. */ static int createList(CDKVIEWER *swindow, int listSize); static int searchForWord (CDKVIEWER *viewer, char *pattern, int direction); static int jumpToLine (CDKVIEWER *viewer); static void popUpLabel (CDKVIEWER *viewer, char **mesg); static void getAndStorePattern (CDKSCREEN *screen); static void drawCDKViewerButtons (CDKVIEWER *viewer); static void drawCDKViewerInfo (CDKVIEWER *viewer); /* * Declare file local variables. */ static char * SearchPattern = 0; static int SearchDirection = DOWN; DeclareCDKObjects(VIEWER, Viewer, setCdk, Unknown); /* * This function creates a new viewer object. */ CDKVIEWER *newCDKViewer (CDKSCREEN *cdkscreen, int xplace, int yplace, int height, int width, char **buttons, int buttonCount, chtype buttonHighlight, boolean Box, boolean shadow) { CDKVIEWER *viewer = 0; int parentWidth = getmaxx(cdkscreen->window); int parentHeight = getmaxy(cdkscreen->window); int boxWidth = width; int boxHeight = height; int xpos = xplace; int ypos = yplace; int buttonWidth = 0; int buttonAdj = 0; int buttonPos = 1; int x = 0; static const struct { int from; int to; } bindings[] = { { CDK_BACKCHAR, KEY_PPAGE }, { 'b', KEY_PPAGE }, { 'B', KEY_PPAGE }, { CDK_FORCHAR, KEY_NPAGE }, { SPACE, KEY_NPAGE }, { 'f', KEY_NPAGE }, { 'F', KEY_NPAGE }, { '|', KEY_HOME }, { '$', KEY_END }, }; if ((viewer = newCDKObject(CDKVIEWER, &my_funcs)) == 0) return (0); setCDKViewerBox (viewer, Box); /* * 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); /* Rejustify the x and y positions if we need to. */ alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight); /* Make the viewer window. */ viewer->win = newwin (boxHeight, boxWidth, ypos, xpos); if (viewer->win == 0) { destroyCDKObject(viewer); return (0); } /* Turn the keypad on for the viewer. */ keypad (viewer->win, TRUE); /* Create the buttons. */ viewer->buttonCount = buttonCount; if (buttonCount > 0) { if ((viewer->button = typeCallocN(chtype *, buttonCount + 1)) == 0 || (viewer->buttonLen = typeCallocN(int, buttonCount + 1)) == 0 || (viewer->buttonPos = typeCallocN(int, buttonCount + 1)) == 0) { destroyCDKObject(viewer); return (0); } for (x=0; x < buttonCount; x++) { viewer->button[x] = char2Chtype (buttons[x], &viewer->buttonLen[x], &buttonAdj); buttonWidth += viewer->buttonLen[x] + 1; } buttonAdj = (int)((boxWidth-buttonWidth)/ (buttonCount +1)); buttonPos = 1 + buttonAdj; for (x=0; x < buttonCount; x++) { viewer->buttonPos[x] = buttonPos; buttonPos += buttonAdj + viewer->buttonLen[x]; } } /* Set the rest of the variables */ ScreenOf(viewer) = cdkscreen; viewer->parent = cdkscreen->window; viewer->shadowWin = 0; viewer->buttonHighlight = buttonHighlight; viewer->boxHeight = boxHeight; viewer->boxWidth = boxWidth - 2; viewer->viewSize = height - 2; ObjOf(viewer)->inputWindow = viewer->win; initExitType(viewer); viewer->shadow = shadow; viewer->currentButton = 0; viewer->currentTop = 0; viewer->length = 0; viewer->leftChar = 0; viewer->maxLeftChar = 0; viewer->maxTopLine = 0; viewer->characters = 0; viewer->listSize = -1; viewer->showLineInfo = 1; viewer->exitType = vEARLY_EXIT; /* Do we need to create a shadow??? */ if (shadow) { viewer->shadowWin = newwin (boxHeight, boxWidth + 1, ypos + 1, xpos + 1); if (viewer->shadowWin == 0) { destroyCDKObject(viewer); return (0); } } /* Setup the key bindings. */ for (x = 0; x < (int) SIZEOF(bindings); ++x) bindCDKObject (vVIEWER, viewer, bindings[x].from, getcCDKBind, (void *)(long)bindings[x].to); /* Register this baby. */ registerCDKObject (cdkscreen, vVIEWER, viewer); /* Return the viewer object. */ return (viewer); } /* * This function sets various attributes of the widget. */ int setCDKViewer (CDKVIEWER *viewer, char *title, char **list, int listSize, chtype buttonHighlight, boolean attrInterp, boolean showLineInfo, boolean Box) { setCDKViewerTitle (viewer, title); setCDKViewerHighlight (viewer, buttonHighlight); setCDKViewerInfoLine (viewer, showLineInfo); setCDKViewerBox (viewer, Box); return setCDKViewerInfo (viewer, list, listSize, attrInterp); } /* * This sets the title of the viewer. (A null title is allowed. * It just means that the viewer will not have a title when drawn.) */ void setCDKViewerTitle (CDKVIEWER *viewer, char *title) { (void) setCdkTitle(ObjOf(viewer), title, - (viewer->boxWidth + 1)); viewer->titleAdj = TitleLinesOf(viewer); /* Need to set viewer->viewSize. */ viewer->viewSize = viewer->boxHeight - (TitleLinesOf(viewer) + 1) - 2; } chtype **getCDKViewerTitle (CDKVIEWER *viewer) { return TitleOf(viewer); } static void setupLine (CDKVIEWER *viewer, boolean interpret, char *list, int x) { /* Did they ask for attribute interpretation? */ if (interpret) { viewer->list[x] = char2Chtype (list, &viewer->listLen[x], &viewer->listPos[x]); viewer->listPos[x] = justifyString (viewer->boxWidth, viewer->listLen[x], viewer->listPos[x]); } else { int len = (int)strlen (list); int pass; int y; chtype *t = 0; /* * We must convert tabs and other nonprinting characters. The curses * library normally does this, but we are bypassing it by writing * chtype's directly. */ for (pass = 0; pass < 2; ++pass) { len = 0; for (y = 0; list[y] != '\0'; ++y) { if (list[y] == '\t') { do { if (pass) t[len] = ' '; ++len; } while (len & 7); } else if (isprint(CharOf(list[y]))) { if (pass) t[len] = CharOf(list[y]); ++len; } else { const char *s = unctrl(list[y]); while (*s != 0) { if (pass) t[len] = CharOf(*s); ++len; ++s; } } } if (!pass) { viewer->list[x] = t = typeCallocN(chtype, len + 3); if (t == 0) { len = 0; break; } } } viewer->listLen[x] = len; viewer->listPos[x] = 0; } viewer->widestLine = MAXIMUM (viewer->widestLine, viewer->listLen[x]); } static void freeLine (CDKVIEWER *viewer, int x) { if (x < viewer->listSize) { freeChtype (viewer->list[x]); viewer->list[x] = 0; } } /* * This function sets the contents of the viewer. */ int setCDKViewerInfo (CDKVIEWER *viewer, char **list, int listSize, boolean interpret) { char filename[CDK_PATHMAX + 2]; int currentLine = 0; int x = 0; int viewerSize = listSize; /* * If the list-size is negative, count the length of the null-terminated * list of strings. */ if (listSize < 0) { /* * FIXME: this should be a function, like chlen() */ listSize = 0; if (list != 0) { for (x = 0; list[x] != 0; ++x) { ; } listSize = x; } } /* compute the size of the resulting display */ viewerSize = listSize; if (list != 0 && interpret) { for (x = 0; x < listSize; ++x) { if (checkForLink (list[x], filename) == 1) { char **fileContents = 0; int fileLen = CDKreadFile (filename, &fileContents); if (fileLen >= 0) viewerSize += (fileLen - 1); CDKfreeStrings (fileContents); } } } /* Clean out the old viewer info. (if there is any) */ viewer->inProgress = TRUE; cleanCDKViewer(viewer); createList(viewer, viewerSize); /* Keep some semi-permanent info. */ viewer->interpret = interpret; /* Copy the information given. */ for (x = currentLine = 0; x < listSize && currentLine < viewerSize; x++) { if (list[x] == 0) { viewer->list[currentLine] = 0; viewer->listLen[currentLine] = 0; viewer->listPos[currentLine] = 0; currentLine++; } else { /* Check if we have a file link in this line. */ if (checkForLink (list[x], filename) == 1) { /* We have a link, open the file. */ char **fileContents = 0; int fileLen = 0; int fileLine = 0; /* Open the file and put it into the viewer. */ fileLen = CDKreadFile (filename, &fileContents); if (fileLen == -1) { #ifdef HAVE_START_COLOR #define FOPEN_FMT "Link Failed: Could not open the file %s" #else #define FOPEN_FMT "Link Failed: Could not open the file %s" #endif char *temp = (char *)malloc(80 + strlen(filename)); sprintf(temp, FOPEN_FMT, filename); setupLine(viewer, TRUE, temp, currentLine++); free (temp); } else { /* For each line read, copy it into the viewer. */ fileLen = MINIMUM(fileLen, (viewerSize - currentLine)); for (fileLine=0; fileLine < fileLen ; fileLine++) { if (currentLine >= viewerSize) break; setupLine(viewer, FALSE, fileContents[fileLine], currentLine); viewer->characters += viewer->listLen[currentLine]; currentLine++; } CDKfreeStrings (fileContents); } } else if (currentLine < viewerSize) { setupLine(viewer, viewer->interpret, list[x], currentLine); viewer->characters += viewer->listLen[currentLine]; currentLine++; } } } /* * Determine how many characters we can shift to the right * before all the items have been viewer off the screen. */ if (viewer->widestLine > viewer->boxWidth) { viewer->maxLeftChar = (viewer->widestLine - viewer->boxWidth) + 1; } else { viewer->maxLeftChar = 0; } /* Set up the needed vars for the viewer list. */ viewer->inProgress = FALSE; viewer->listSize = viewerSize; if (viewer->listSize <= viewer->viewSize) { viewer->maxTopLine = 0; } else { viewer->maxTopLine = viewer->listSize-1; } return viewer->listSize; } chtype **getCDKViewerInfo (CDKVIEWER *viewer, int *size) { (*size) = viewer->listSize; return viewer->list; } /* * This function sets the highlight type of the buttons. */ void setCDKViewerHighlight (CDKVIEWER *viewer, chtype buttonHighlight) { viewer->buttonHighlight = buttonHighlight; } chtype getCDKViewerHighlight (CDKVIEWER *viewer) { return viewer->buttonHighlight; } /* * This sets whether or not you want to set the viewer info line. */ void setCDKViewerInfoLine (CDKVIEWER *viewer, boolean showLineInfo) { viewer->showLineInfo = showLineInfo; } boolean getCDKViewerInfoLine (CDKVIEWER *viewer) { return viewer->showLineInfo; } /* * This sets the widgets box attribute. */ void setCDKViewerBox (CDKVIEWER *viewer, boolean Box) { ObjOf(viewer)->box = Box; ObjOf(viewer)->borderSize = Box ? 1 : 0; } boolean getCDKViewerBox (CDKVIEWER *viewer) { return ObjOf(viewer)->box; } /* * This removes all the lines inside the scrolling window. */ void cleanCDKViewer (CDKVIEWER *viewer) { int x; /* Clean up the memory used ... */ for (x=0; x < viewer->listSize; x++) { freeLine (viewer, x); } /* Reset some variables. */ viewer->listSize = 0; viewer->maxLeftChar = 0; viewer->widestLine = 0; viewer->currentTop = 0; viewer->maxTopLine = 0; /* Redraw the window. */ drawCDKViewer (viewer, ObjOf(viewer)->box); } static void PatternNotFound(CDKVIEWER *viewer, char *pattern) { char *tempInfo[2]; char *temp = (char *)malloc(80 + strlen(pattern)); tempInfo[0] = temp; tempInfo[1] = 0; sprintf (temp, "Pattern '%s' not found.", pattern); popUpLabel (viewer, tempInfo); free (temp); } /* * This function actually controls the viewer... */ int activateCDKViewer (CDKVIEWER *viewer, chtype *actions GCC_UNUSED) { char *fileInfo[10]; char *tempInfo[2], temp[500]; chtype input; int x, REFRESH; /* Create the information about the file stats. */ sprintf (temp, " File Statistics "); fileInfo[0] = copyChar(temp); sprintf (temp, " "); fileInfo[1] = copyChar(temp); sprintf (temp, "Character Count: %-4ld ", viewer->characters); fileInfo[2] = copyChar(temp); sprintf (temp, "Line Count : %-4d ", viewer->listSize); fileInfo[3] = copyChar(temp); sprintf (temp, " "); fileInfo[4] = copyChar(temp); sprintf (temp, "Press Any Key To Continue."); fileInfo[5] = copyChar(temp); fileInfo[6] = 0; tempInfo[0] = temp; tempInfo[1] = 0; /* Set the current button. */ viewer->currentButton = 0; /* Draw the viewer list. */ drawCDKViewer (viewer, ObjOf(viewer)->box); /* Do this until KEY_ENTER is hit. */ for (;;) { /* Reset the refresh flag. */ REFRESH = FALSE; /* Get the user input. */ input = getcCDKObject (ObjOf(viewer)); if (! checkCDKObjectBind (vVIEWER, viewer, input)) { switch (input) { case KEY_TAB : if (viewer->buttonCount > 1) { if (viewer->currentButton == (viewer->buttonCount - 1)) { viewer->currentButton = 0; } else { viewer->currentButton++; } /* Redraw the buttons. */ drawCDKViewerButtons (viewer); } break; case CDK_PREV : if (viewer->buttonCount > 1) { if (viewer->currentButton == 0) { viewer->currentButton = viewer->buttonCount - 1; } else { viewer->currentButton--; } /* Redraw the buttons. */ drawCDKViewerButtons (viewer); } break; case KEY_UP : if (viewer->currentTop > 0) { viewer->currentTop--; REFRESH = TRUE; } else { Beep(); } break; case KEY_DOWN : if (viewer->currentTop < viewer->maxTopLine) { viewer->currentTop++; REFRESH = TRUE; } else { Beep(); } break; case KEY_RIGHT : if (viewer->leftChar < viewer->maxLeftChar) { viewer->leftChar++; REFRESH = TRUE; } else { Beep(); } break; case KEY_LEFT : if (viewer->leftChar > 0) { viewer->leftChar--; REFRESH = TRUE; } else { Beep(); } break; case KEY_PPAGE : if (viewer->currentTop > 0) { if ((viewer->currentTop - (viewer->viewSize-1)) > 0) { viewer->currentTop = viewer->currentTop - (viewer->viewSize - 1); } else { viewer->currentTop = 0; } REFRESH = TRUE; } else { Beep(); } break; case KEY_NPAGE : if (viewer->currentTop < viewer->maxTopLine) { if ((viewer->currentTop + viewer->viewSize) < viewer->maxTopLine) { viewer->currentTop = viewer->currentTop + (viewer->viewSize - 1); } else { viewer->currentTop = viewer->maxTopLine; } REFRESH = TRUE; } else { Beep(); } break; case KEY_HOME : viewer->leftChar = 0; REFRESH = TRUE; break; case KEY_END : viewer->leftChar = viewer->maxLeftChar; REFRESH = TRUE; break; case 'g' : case '1' : case '<' : viewer->currentTop = 0; REFRESH = TRUE; break; case 'G' : case '>' : viewer->currentTop = viewer->maxTopLine; REFRESH = TRUE; break; case 'L' : x = (int) ((viewer->listSize + viewer->currentTop) / 2); if (x < viewer->maxTopLine) { viewer->currentTop = x; REFRESH = TRUE; } else { Beep(); } break; case 'l' : x = (int) (viewer->currentTop / 2); if (x >= 0) { viewer->currentTop = x; REFRESH = TRUE; } else { Beep(); } break; case '?' : SearchDirection = UP; getAndStorePattern (ScreenOf(viewer)); if (! searchForWord(viewer, SearchPattern, SearchDirection)) { PatternNotFound(viewer, SearchPattern); } REFRESH = TRUE; break; case '/' : SearchDirection = DOWN; getAndStorePattern (ScreenOf(viewer)); if (! searchForWord(viewer, SearchPattern, SearchDirection)) { PatternNotFound(viewer, SearchPattern); } REFRESH = TRUE; break; case 'N' : case 'n' : if (SearchPattern == 0) { sprintf (temp, "There is no pattern in the buffer."); popUpLabel (viewer, tempInfo); } else if (! searchForWord(viewer, SearchPattern, ((input == 'n') ? SearchDirection : !SearchDirection))) { PatternNotFound(viewer, SearchPattern); } REFRESH = TRUE; break; case ':' : viewer->currentTop = jumpToLine (viewer); REFRESH = TRUE; break; case 'i' : case 's' : case 'S' : popUpLabel(viewer, fileInfo); REFRESH = TRUE; break; case KEY_ESC : freeCharList (fileInfo, 6); setExitType(viewer, input); return -1; case KEY_ENTER : freeCharList (fileInfo, 6); setExitType(viewer, input); return viewer->currentButton; case CDK_REFRESH : eraseCDKScreen (ScreenOf(viewer)); refreshCDKScreen (ScreenOf(viewer)); break; default : Beep(); break; } } /* Do we need to redraw the screen??? */ if (REFRESH) { drawCDKViewerInfo (viewer); } } } /* * This searches the document looking for the given word. */ static void getAndStorePattern (CDKSCREEN *screen) { CDKENTRY *getPattern = 0; char *temp = 0; char *list = 0; /* Check the direction. */ if (SearchDirection == UP) { temp = "Search Up : "; } else { temp = "Search Down: "; } /* Pop up the entry field. */ getPattern = newCDKEntry (screen, CENTER, CENTER, 0, temp, COLOR_PAIR(5)|A_BOLD, '.'|COLOR_PAIR(5)|A_BOLD, vMIXED, 10, 0, 256, TRUE, FALSE); /* Is there an old search pattern? */ if (SearchPattern != 0) { setCDKEntry (getPattern, SearchPattern, getPattern->min, getPattern->max, ObjOf(getPattern)->box); } freeChar (SearchPattern); /* Activate this baby. */ list = activateCDKEntry (getPattern, 0); /* Save the list. */ if ((list != 0) || (strlen (list) != 0)) { SearchPattern = copyChar (list); } /* Clean up. */ destroyCDKEntry (getPattern); } /* * This searches for a line containing the word and realigns the value on the * screen. */ static int searchForWord (CDKVIEWER *viewer, char *pattern, int direction) { int x, y, pos, len, plen; int found = 0; /* If the pattern is empty then return. */ if (pattern != 0 && (plen = strlen(pattern)) != 0) { if (direction == DOWN) { /* Start looking from 'here' down. */ for (x = viewer->currentTop + 1; !found && (x < viewer->listSize); x++) { len = chlen (viewer->list[x]); for (y = pos = 0; y < len; y++) { int plainChar = CharOf(viewer->list[x][y]); if (CharOf(pattern[pos]) != plainChar) { y -= pos; pos = 0; } else if (++pos == plen) { viewer->currentTop = (x < viewer->maxTopLine ? x : viewer->maxTopLine); viewer->leftChar = (y < viewer->boxWidth ? 0 : viewer->maxLeftChar); found = 1; break; } } } } else { /* Start looking from 'here' up. */ for (x = viewer->currentTop - 1; !found && (x >= 0); x--) { len = chlen (viewer->list[x]); for (y = pos = 0; y < len; y++) { int plainChar = CharOf(viewer->list[x][y]); if (CharOf(pattern[pos]) != plainChar) { y -= pos; pos = 0; } else if (++pos == plen) { viewer->currentTop = x; viewer->leftChar = (y < viewer->boxWidth ? 0 : viewer->maxLeftChar); found = 1; break; } } } } } return(found); } /* * This allows us to 'jump' to a given line in the file. */ static int jumpToLine (CDKVIEWER *viewer) { int line = 0; CDKSCALE * newline = newCDKScale (ScreenOf(viewer), CENTER, CENTER, "Jump To Line", "Line :", A_BOLD, intlen(viewer->listSize) + 1, viewer->currentTop + 1, 0, viewer->maxTopLine + 1, 1, 10, TRUE, TRUE); line = activateCDKScale (newline, 0); destroyCDKScale (newline); return ((line-1)); } /* * This pops a little message up on the screen. */ static void popUpLabel (CDKVIEWER *viewer, char **mesg) { CDKLABEL *label; /* Set up variables. */ label = newCDKLabel (ScreenOf(viewer), CENTER, CENTER, mesg, CDKcountStrings(mesg), TRUE, FALSE); /* Draw the label and wait. */ drawCDKLabel (label, TRUE); getcCDKObject (ObjOf(label)); /* Clean up. */ destroyCDKLabel (label); } /* * This moves the viewer field to the given location. */ static void _moveCDKViewer (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag) { CDKVIEWER *viewer = (CDKVIEWER *)object; int currentX = getbegx(viewer->win); int currentY = getbegy(viewer->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(viewer->win) + xplace; ypos = getbegy(viewer->win) + yplace; } /* Adjust the window if we need to. */ alignxy (WindowOf(viewer), &xpos, &ypos, viewer->boxWidth, viewer->boxHeight); /* Get the difference. */ xdiff = currentX - xpos; ydiff = currentY - ypos; /* Move the window to the new location. */ moveCursesWindow(viewer->win, -xdiff, -ydiff); moveCursesWindow(viewer->shadowWin, -xdiff, -ydiff); /* Touch the windows so they 'move'. */ refreshCDKWindow (WindowOf(viewer)); /* Redraw the window, if they asked for it. */ if (refresh_flag) { drawCDKViewer (viewer, ObjOf(viewer)->box); } } /* * This function draws the viewer widget. */ static void _drawCDKViewer (CDKOBJS *object, boolean Box) { CDKVIEWER *viewer = (CDKVIEWER *)object; /* Do we need to draw in the shadow??? */ if (viewer->shadowWin != 0) { drawShadow (viewer->shadowWin); } /* Box it if it was asked for. */ if (Box) { drawObjBox (viewer->win, ObjOf(viewer)); wrefresh (viewer->win); } /* Draw the info in the viewer. */ drawCDKViewerInfo (viewer); } /* * This redraws the viewer buttons. */ static void drawCDKViewerButtons (CDKVIEWER *viewer) { chtype character; int x; /* No buttons, no drawing. */ if (viewer->buttonCount == 0) { return; } /* Redraw the buttons. */ for (x=0; x < viewer->buttonCount; x++) { writeChtype (viewer->win, viewer->buttonPos[x], viewer->boxHeight-2, viewer->button[x], HORIZONTAL, 0, viewer->buttonLen[x]); } /* Highlight the current button. */ for (x=0; x < viewer->buttonLen[viewer->currentButton]; x++) { /* Strip the character of any extra attributes. */ character = CharOf(viewer->button[viewer->currentButton][x]); /* Add the character into the window. */ mvwaddch (viewer->win, viewer->boxHeight-2, viewer->buttonPos[viewer->currentButton] + x, character|viewer->buttonHighlight); } /* Refresh the window. */ refreshCDKWindow (viewer->win); } /* * This sets the background attribute of the widget. */ static void _setBKattrViewer (CDKOBJS *object, chtype attrib) { if (object != 0) { CDKVIEWER *widget = (CDKVIEWER *) object; wbkgd (widget->win, attrib); } } /* * Free any storage associated with the info-list. */ static void destroyInfo(CDKVIEWER *viewer) { CDKfreeChtypes (viewer->list); freeChecked (viewer->listPos); freeChecked (viewer->listLen); viewer->list = 0; viewer->listPos = 0; viewer->listLen = 0; } /* * This function destroys the viewer widget. */ static void _destroyCDKViewer (CDKOBJS *object) { if (object != 0) { CDKVIEWER *viewer = (CDKVIEWER *)object; destroyInfo(viewer); cleanCdkTitle (object); CDKfreeChtypes(viewer->button); freeChecked (viewer->buttonLen); freeChecked (viewer->buttonPos); /* Clean up the windows. */ deleteCursesWindow (viewer->shadowWin); deleteCursesWindow (viewer->win); /* Unregister this object. */ unregisterCDKObject (vVIEWER, viewer); } } /* * This function erases the viewer widget from the screen. */ static void _eraseCDKViewer (CDKOBJS *object) { if (validCDKObject (object)) { CDKVIEWER *viewer = (CDKVIEWER *)object; eraseCursesWindow (viewer->win); eraseCursesWindow (viewer->shadowWin); } } /* * This draws the viewer info lines. */ static void drawCDKViewerInfo (CDKVIEWER *viewer) { int listAdjust = 0; int lastLine = 0; char temp[256]; int x; /* Clear the window. */ werase (viewer->win); drawCdkTitle (viewer->win, ObjOf(viewer)); /* Draw in the current line at the top. */ if (viewer->showLineInfo == TRUE) { /* Set up the info line and draw it. */ if (viewer->inProgress) { strcpy (temp, "processing..."); } else if (viewer->listSize != 0) { sprintf (temp, "%d/%d %2.0f%%", (viewer->currentTop + 1), viewer->listSize, ((float)(viewer->currentTop + 1)/(float)viewer->listSize) * 100); } else { sprintf (temp, "%d/%d %2.0f%%", 0, 0, 0.0); } /* * The listAdjust variable tells us if we have to shift down * one line because the person asked for the line X of Y line * at the top of the screen. We only want to set this to 1 if * they asked for the info line and there is no title, or if the * two items overlap. */ if (TitleLinesOf(viewer) == 0 || TitlePosOf(viewer)[0] < ((int)strlen(temp) + 2)) { listAdjust = 1; } writeChar (viewer->win, 1, (listAdjust ? TitleLinesOf(viewer) : 0) + 1, temp, HORIZONTAL, 0, (int)strlen(temp)); } /* Determine the last line to draw. */ lastLine = (viewer->listSize <= viewer->viewSize ? viewer->listSize : viewer->viewSize); lastLine -= listAdjust; /* Redraw the list. */ for (x=0; x < lastLine; x++) { if (viewer->currentTop + x < viewer->listSize) { int screenPos = viewer->listPos[viewer->currentTop + x] + 1 - viewer->leftChar; if (screenPos >= 0) { writeChtype (viewer->win, screenPos, x + TitleLinesOf(viewer) + listAdjust + 1, viewer->list[x + viewer->currentTop], HORIZONTAL, 0, viewer->listLen[x + viewer->currentTop]); } else { writeChtype (viewer->win, 1, x + TitleLinesOf(viewer) + listAdjust + 1, viewer->list[x + viewer->currentTop], HORIZONTAL, viewer->leftChar - viewer->listPos[viewer->currentTop + x], viewer->listLen[x + viewer->currentTop]); } } } /* Box it if we have to. */ if (ObjOf(viewer)->box) { drawObjBox (viewer->win, ObjOf(viewer)); wrefresh (viewer->win); } /* Draw the separation line. */ if (viewer->buttonCount > 0) { chtype boxattr = BXAttrOf(viewer); for (x=1; x <= viewer->boxWidth; x++) { mvwaddch (viewer->win, viewer->boxHeight-3, x, HZCharOf(viewer) | boxattr); } mvwaddch (viewer->win, viewer->boxHeight-3, 0, ACS_LTEE | boxattr); mvwaddch (viewer->win, viewer->boxHeight-3, getmaxx(viewer->win) - 1, ACS_RTEE | boxattr); } /* Draw the buttons. This will call refresh on the viewer win. */ drawCDKViewerButtons (viewer); } dummyInject(Viewer) dummyFocus(Viewer) dummyUnfocus(Viewer) dummyRefreshData(Viewer) dummySaveData(Viewer) /* * The listSize may be negative, to assign no definite limit. */ static int createList(CDKVIEWER *swindow, int listSize) { int status = 0; if (listSize <= 0) { destroyInfo(swindow); } else { chtype **newList = typeCallocN(chtype *, listSize + 1); int *newPos = typeCallocN(int, listSize + 1); int *newLen = typeCallocN(int, listSize + 1); if (newList != 0 && newPos != 0 && newLen != 0) { status = 1; destroyInfo(swindow); swindow->list = newList; swindow->listPos = newPos; swindow->listLen = newLen; } if (!status) { CDKfreeChtypes(newList); freeChecked(newPos); freeChecked(newLen); } } return status; }