This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/deps/cdk-5.0-20161210/viewer.c
2017-03-20 21:40:32 +10:00

1300 lines
30 KiB
C

#include <cdk_int.h>
/*
* $Author: tom $
* $Date: 2016/11/20 20:15:53 $
* $Revision: 1.165 $
*/
/*
* 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, CDK_CSTRING2 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,
CDK_CSTRING2 buttons,
int buttonCount,
chtype buttonHighlight,
boolean Box,
boolean shadow)
{
/* *INDENT-EQLS* */
CDKVIEWER *viewer = 0;
int parentWidth = getmaxx (cdkscreen->window);
int parentHeight = getmaxy (cdkscreen->window);
int boxWidth;
int boxHeight;
int xpos = xplace;
int ypos = yplace;
int buttonAdj = 0;
int x = 0;
/* *INDENT-OFF* */
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 },
};
/* *INDENT-ON* */
if ((viewer = newCDKObject (CDKVIEWER, &my_funcs)) == 0)
return (0);
setCDKViewerBox (viewer, Box);
boxHeight = setWidgetDimension (parentHeight, height, 0);
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)
{
int buttonWidth = 0;
int buttonPos = 1;
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];
}
}
/* *INDENT-EQLS* 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,
(chtype)bindings[x].from,
getcCDKBind,
(void *)(long)bindings[x].to);
registerCDKObject (cdkscreen, vVIEWER, viewer);
return (viewer);
}
/*
* This function sets various attributes of the widget.
*/
int setCDKViewer (CDKVIEWER *viewer,
const char *title,
CDK_CSTRING2 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, const 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, const 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 ((chtype)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, CDK_CSTRING2 list, int listSize, boolean interpret)
{
/* *INDENT-EQLS* */
char filename[CDK_PATHMAX + 2];
int currentLine = 0;
int x = 0;
int viewerSize;
/*
* If the list-size is negative, count the length of the null-terminated
* list of strings.
*/
if (listSize < 0)
{
listSize = (int)CDKcountStrings (list);
}
/* compute the size of the resulting display */
viewerSize = listSize;
if (list != 0 && interpret)
{
for (x = 0; x < listSize; ++x)
{
if (list[x] == 0)
{
viewerSize = x; /* oops - caller gave the wrong length */
break;
}
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;
/* Open the file and put it into the viewer. */
fileLen = CDKreadFile (filename, &fileContents);
if (fileLen == -1)
{
#ifdef HAVE_START_COLOR
#define FOPEN_FMT "<C></16>Link Failed: Could not open the file %s"
#else
#define FOPEN_FMT "<C></K>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
{
int fileLine;
/* 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);
}
/* *INDENT-EQLS* 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)
{
CDK_CSTRING tempInfo[2];
char *temp = (char *)malloc (80 + strlen (pattern));
tempInfo[0] = temp;
tempInfo[1] = 0;
sprintf (temp, "</U/5>Pattern '%s' not found.<!U!5>", pattern);
popUpLabel (viewer, tempInfo);
free (temp);
}
/*
* This function actually controls the viewer...
*/
int activateCDKViewer (CDKVIEWER *widget, chtype *actions GCC_UNUSED)
{
char *fileInfo[10];
CDK_CSTRING tempInfo[2];
char temp[500];
chtype input;
boolean functionKey;
int x;
/* Create the information about the file stats. */
sprintf (temp, "</5> </U>File Statistics<!U> <!5>");
fileInfo[0] = copyChar (temp);
sprintf (temp, "</5> <!5>");
fileInfo[1] = copyChar (temp);
sprintf (temp, "</5/R>Character Count:<!R> %-4ld <!5>", widget->characters);
fileInfo[2] = copyChar (temp);
sprintf (temp, "</5/R>Line Count :<!R> %-4d <!5>", widget->listSize);
fileInfo[3] = copyChar (temp);
sprintf (temp, "</5> <!5>");
fileInfo[4] = copyChar (temp);
sprintf (temp, "<C></5>Press Any Key To Continue.<!5>");
fileInfo[5] = copyChar (temp);
fileInfo[6] = 0;
tempInfo[0] = temp;
tempInfo[1] = 0;
/* Set the current button. */
widget->currentButton = 0;
/* Draw the widget list. */
drawCDKViewer (widget, ObjOf (widget)->box);
/* Do this until KEY_ENTER is hit. */
for (;;)
{
/* Reset the refresh flag. */
int REFRESH = FALSE;
input = (chtype)getchCDKObject (ObjOf (widget), &functionKey);
if (!checkCDKObjectBind (vVIEWER, widget, input))
{
switch (input)
{
case KEY_TAB:
if (widget->buttonCount > 1)
{
if (widget->currentButton == (widget->buttonCount - 1))
{
widget->currentButton = 0;
}
else
{
widget->currentButton++;
}
/* Redraw the buttons. */
drawCDKViewerButtons (widget);
}
break;
case CDK_PREV:
if (widget->buttonCount > 1)
{
if (widget->currentButton == 0)
{
widget->currentButton = widget->buttonCount - 1;
}
else
{
widget->currentButton--;
}
/* Redraw the buttons. */
drawCDKViewerButtons (widget);
}
break;
case KEY_UP:
if (widget->currentTop > 0)
{
widget->currentTop--;
REFRESH = TRUE;
}
else
{
Beep ();
}
break;
case KEY_DOWN:
if (widget->currentTop < widget->maxTopLine)
{
widget->currentTop++;
REFRESH = TRUE;
}
else
{
Beep ();
}
break;
case KEY_RIGHT:
if (widget->leftChar < widget->maxLeftChar)
{
widget->leftChar++;
REFRESH = TRUE;
}
else
{
Beep ();
}
break;
case KEY_LEFT:
if (widget->leftChar > 0)
{
widget->leftChar--;
REFRESH = TRUE;
}
else
{
Beep ();
}
break;
case KEY_PPAGE:
if (widget->currentTop > 0)
{
if ((widget->currentTop - (widget->viewSize - 1)) > 0)
{
widget->currentTop = (widget->currentTop
- (widget->viewSize - 1));
}
else
{
widget->currentTop = 0;
}
REFRESH = TRUE;
}
else
{
Beep ();
}
break;
case KEY_NPAGE:
if (widget->currentTop < widget->maxTopLine)
{
if ((widget->currentTop + widget->viewSize) < widget->maxTopLine)
{
widget->currentTop = widget->currentTop +
(widget->viewSize
- 1);
}
else
{
widget->currentTop = widget->maxTopLine;
}
REFRESH = TRUE;
}
else
{
Beep ();
}
break;
case KEY_HOME:
widget->leftChar = 0;
REFRESH = TRUE;
break;
case KEY_END:
widget->leftChar = widget->maxLeftChar;
REFRESH = TRUE;
break;
case 'g':
case '1':
case '<':
widget->currentTop = 0;
REFRESH = TRUE;
break;
case 'G':
case '>':
widget->currentTop = widget->maxTopLine;
REFRESH = TRUE;
break;
case 'L':
x = (int)((widget->listSize + widget->currentTop) / 2);
if (x < widget->maxTopLine)
{
widget->currentTop = x;
REFRESH = TRUE;
}
else
{
Beep ();
}
break;
case 'l':
x = (int)(widget->currentTop / 2);
if (x >= 0)
{
widget->currentTop = x;
REFRESH = TRUE;
}
else
{
Beep ();
}
break;
case '?':
SearchDirection = UP;
getAndStorePattern (ScreenOf (widget));
if (!searchForWord (widget, SearchPattern, SearchDirection))
{
PatternNotFound (widget, SearchPattern);
}
REFRESH = TRUE;
break;
case '/':
SearchDirection = DOWN;
getAndStorePattern (ScreenOf (widget));
if (!searchForWord (widget, SearchPattern, SearchDirection))
{
PatternNotFound (widget, SearchPattern);
}
REFRESH = TRUE;
break;
case 'N':
case 'n':
if (SearchPattern == 0)
{
sprintf (temp, "</5>There is no pattern in the buffer.<!5>");
popUpLabel (widget, tempInfo);
}
else if (!searchForWord (widget,
SearchPattern,
((input == 'n')
? SearchDirection
: !SearchDirection)))
{
PatternNotFound (widget, SearchPattern);
}
REFRESH = TRUE;
break;
case ':':
widget->currentTop = jumpToLine (widget);
REFRESH = TRUE;
break;
case 'i':
case 's':
case 'S':
popUpLabel (widget, (CDK_CSTRING2)fileInfo);
REFRESH = TRUE;
break;
case KEY_ESC:
freeCharList (fileInfo, 6);
setExitType (widget, input);
return -1;
case KEY_ERROR:
freeCharList (fileInfo, 6);
setExitType (widget, input);
return -1;
case KEY_ENTER:
freeCharList (fileInfo, 6);
setExitType (widget, input);
return widget->currentButton;
case CDK_REFRESH:
eraseCDKScreen (ScreenOf (widget));
refreshCDKScreen (ScreenOf (widget));
break;
default:
Beep ();
break;
}
}
/* Do we need to redraw the screen??? */
if (REFRESH)
{
drawCDKViewerInfo (widget);
}
}
}
/*
* This searches the document looking for the given word.
*/
static void getAndStorePattern (CDKSCREEN *screen)
{
/* *INDENT-EQLS* */
CDKENTRY *getPattern = 0;
const char *temp = 0;
char *list = 0;
/* Check the direction. */
if (SearchDirection == UP)
{
temp = "</5>Search Up : <!5>";
}
else
{
temp = "</5>Search Down: <!5>";
}
/* 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 found = 0;
int plen;
/* If the pattern is empty then return. */
if (pattern != 0 && (plen = (int)strlen (pattern)) != 0)
{
int x, y, pos, len;
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)
{
/* *INDENT-EQLS* */
int line = 0;
CDKSCALE *newline = newCDKScale (ScreenOf (viewer), CENTER, CENTER,
"<C>Jump To Line", "</5>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, CDK_CSTRING2 mesg)
{
CDKLABEL *label;
boolean functionKey;
/* Set up variables. */
label = newCDKLabel (ScreenOf (viewer), CENTER, CENTER,
(CDK_CSTRING2)mesg,
(int)CDKcountStrings (mesg),
TRUE, FALSE);
/* Draw the label and wait. */
drawCDKLabel (label, TRUE);
getchCDKObject (ObjOf (label), &functionKey);
/* 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)
{
/* *INDENT-EQLS* */
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. */
(void)mvwaddch (viewer->win,
viewer->boxHeight - 2,
viewer->buttonPos[viewer->currentButton] + x,
character | viewer->buttonHighlight);
}
/* Refresh the window. */
wrefresh (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);
/* Clean the key bindings. */
cleanCDKObjectBindings (vVIEWER, viewer);
/* 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;
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)
{
char temp[256];
/* 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;
writeChtype (viewer->win,
((screenPos >= 0)
? screenPos
: 1),
x + TitleLinesOf (viewer) + listAdjust + 1,
viewer->list[x + viewer->currentTop],
HORIZONTAL,
((screenPos >= 0)
? 0
: (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++)
{
(void)mvwaddch (viewer->win, viewer->boxHeight - 3, x,
HZCharOf (viewer) | boxattr);
}
(void)mvwaddch (viewer->win, viewer->boxHeight - 3, 0,
ACS_LTEE | boxattr);
(void)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);
}
/*
* The listSize may be negative, to assign no definite limit.
*/
static int createList (CDKVIEWER *swindow, int listSize)
{
int status = 0;
if (listSize >= 0)
{
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);
}
}
else
{
destroyInfo (swindow);
}
return status;
}
dummyInject (Viewer)
dummyFocus (Viewer)
dummyUnfocus (Viewer)
dummyRefreshData (Viewer)
dummySaveData (Viewer)