551 lines
13 KiB
C
551 lines
13 KiB
C
#include <cdk.h>
|
|
|
|
/*
|
|
* $Author: garbled $
|
|
* $Date: 2001/01/09 18:41:53 $
|
|
* $Revision: 1.3 $
|
|
*/
|
|
|
|
DeclareCDKObjects(my_funcs,Dialog);
|
|
|
|
/*
|
|
* This function creates a dialog widget.
|
|
*/
|
|
CDKDIALOG *newCDKDialog (CDKSCREEN *cdkscreen, int xplace, int yplace, char **mesg, int rows, char **buttonLabel, int buttonCount, chtype buttonHighlight, boolean separator, boolean Box, boolean shadow)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKDIALOG *dialog = newCDKObject(CDKDIALOG, &my_funcs);
|
|
int boxWidth = MIN_DIALOG_WIDTH;
|
|
int boxHeight = rows + 2;
|
|
int xpos = xplace;
|
|
int ypos = yplace;
|
|
int maxmessagewidth = 0;
|
|
int buttonWidth, buttonPos;
|
|
int x, junk2;
|
|
|
|
/* Translate the char * message to a chtype * */
|
|
for (x=0; x < rows; x++)
|
|
{
|
|
dialog->info[x] = char2Chtype (mesg[x], &dialog->infoLen[x], &dialog->infoPos[x]);
|
|
maxmessagewidth = MAXIMUM (maxmessagewidth, dialog->infoLen[x]);
|
|
}
|
|
|
|
/* Translate the button label char * to a chtype * */
|
|
buttonWidth = 0;
|
|
for (x=0; x < buttonCount; x++)
|
|
{
|
|
dialog->buttonLabel[x] = char2Chtype (buttonLabel[x], &dialog->buttonLen[x], &junk2);
|
|
buttonWidth += dialog->buttonLen[x] + 1;
|
|
}
|
|
buttonWidth--;
|
|
|
|
/* Determine the final dimensions of the box. */
|
|
boxWidth = MAXIMUM (boxWidth, maxmessagewidth + 2);
|
|
boxWidth = MAXIMUM (boxWidth, buttonWidth + 2);
|
|
|
|
if (buttonCount > 0)
|
|
{
|
|
boxHeight += separator + 1;
|
|
}
|
|
|
|
/* Now we have to readjust the x and y positions. */
|
|
alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
|
|
|
|
/* Make the dialog window. */
|
|
dialog->win = newwin (boxHeight + !!shadow, boxWidth + !!shadow, ypos, xpos);
|
|
|
|
/* If we couldn't create the window, we should return a null value. */
|
|
if (dialog->win == 0)
|
|
{
|
|
/* Couldn't create the window. Clean up used memory. */
|
|
for (x=0; x < dialog->messageRows ; x++)
|
|
{
|
|
freeChtype (dialog->info[x]);
|
|
}
|
|
for (x=0; x < dialog->buttonCount; x++)
|
|
{
|
|
freeChtype (dialog->buttonLabel[x]);
|
|
}
|
|
|
|
/* Remove the memory used by the dialog pointer. */
|
|
free (dialog);
|
|
|
|
/* Return a null dialog box. */
|
|
return (0);
|
|
}
|
|
keypad (dialog->win, TRUE);
|
|
leaveok (dialog->win, TRUE);
|
|
|
|
/* Make the info window. */
|
|
dialog->infoWin = subwin (dialog->win,
|
|
rows, boxWidth - 2,
|
|
ypos + 1, xpos + 1);
|
|
|
|
/* Make the button window. */
|
|
if (buttonCount > 0)
|
|
{
|
|
dialog->buttonWin = subwin (dialog->win,
|
|
1, boxWidth - 2,
|
|
ypos + rows + 2, xpos + 1);
|
|
}
|
|
|
|
/* Set up the dialog box attributes. */
|
|
ScreenOf(dialog) = cdkscreen;
|
|
dialog->parent = cdkscreen->window;
|
|
dialog->buttonCount = buttonCount;
|
|
dialog->buttonHighlight = buttonHighlight;
|
|
dialog->currentButton = 0;
|
|
dialog->messageRows = rows;
|
|
dialog->boxHeight = boxHeight;
|
|
dialog->boxWidth = boxWidth;
|
|
dialog->separator = separator;
|
|
dialog->exitType = vNEVER_ACTIVATED;
|
|
ObjOf(dialog)->box = Box;
|
|
dialog->shadow = shadow;
|
|
dialog->ULChar = ACS_ULCORNER;
|
|
dialog->URChar = ACS_URCORNER;
|
|
dialog->LLChar = ACS_LLCORNER;
|
|
dialog->LRChar = ACS_LRCORNER;
|
|
dialog->HChar = ACS_HLINE;
|
|
dialog->VChar = ACS_VLINE;
|
|
dialog->BoxAttrib = A_NORMAL;
|
|
dialog->preProcessFunction = 0;
|
|
dialog->preProcessData = 0;
|
|
dialog->postProcessFunction = 0;
|
|
dialog->postProcessData = 0;
|
|
|
|
/* Find the button positions. */
|
|
buttonPos = (boxWidth - 2 - buttonWidth) / 2;
|
|
for (x=0; x < buttonCount; x++)
|
|
{
|
|
dialog->buttonPos[x] = buttonPos;
|
|
buttonPos += dialog->buttonLen[x] + 1;
|
|
}
|
|
|
|
/* Create the string alignments. */
|
|
for (x=0; x < rows; x++)
|
|
{
|
|
dialog->infoPos[x] = justifyString (boxWidth - 2, dialog->infoLen[x], dialog->infoPos[x]);
|
|
}
|
|
|
|
/* Empty the key bindings. */
|
|
cleanCDKObjectBindings (vDIALOG, dialog);
|
|
|
|
/* Register this baby. */
|
|
registerCDKObject (cdkscreen, vDIALOG, dialog);
|
|
|
|
/* Return the dialog box pointer. */
|
|
return (dialog);
|
|
}
|
|
|
|
/*
|
|
* This lets the user select the button.
|
|
*/
|
|
int activateCDKDialog (CDKDIALOG *dialog, chtype *actions)
|
|
{
|
|
/* Declare local variables. */
|
|
chtype input = 0;
|
|
int ret;
|
|
|
|
/* Draw the dialog box. */
|
|
drawCDKDialog (dialog, ObjOf(dialog)->box);
|
|
|
|
/* Check if actions is null. */
|
|
if (actions == 0)
|
|
{
|
|
for (;;)
|
|
{
|
|
/* Get the input. */
|
|
wrefresh (dialog->win);
|
|
input = wgetch (dialog->win);
|
|
|
|
/* Inject the character into the widget. */
|
|
ret = injectCDKDialog (dialog, input);
|
|
if (dialog->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 = injectCDKDialog (dialog, actions[x]);
|
|
if (dialog->exitType != vEARLY_EXIT)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Set the exit type and exit. */
|
|
dialog->exitType = vEARLY_EXIT;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* This injects a single character into the dialog widget.
|
|
*/
|
|
int injectCDKDialog (CDKDIALOG *dialog, chtype input)
|
|
{
|
|
int firstButton = 0;
|
|
int lastButton = dialog->buttonCount - 1;
|
|
int ppReturn = 1;
|
|
|
|
/* Set the exit type. */
|
|
dialog->exitType = vEARLY_EXIT;
|
|
|
|
/* Check if there is a pre-process function to be called. */
|
|
if (dialog->preProcessFunction != 0)
|
|
{
|
|
ppReturn = ((PROCESSFN)(dialog->preProcessFunction)) (vDIALOG, dialog, dialog->preProcessData, input);
|
|
}
|
|
|
|
/* Should we continue? */
|
|
if (ppReturn != 0)
|
|
{
|
|
/* Check for a key binding. */
|
|
if (checkCDKObjectBind (vDIALOG, dialog, input) != 0)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
switch (input)
|
|
{
|
|
case KEY_LEFT : case CDK_PREV :
|
|
if (dialog->currentButton == firstButton)
|
|
{
|
|
dialog->currentButton = lastButton;;
|
|
}
|
|
else
|
|
{
|
|
dialog->currentButton--;
|
|
}
|
|
break;
|
|
|
|
case KEY_RIGHT : case CDK_NEXT : case KEY_TAB : case ' ' :
|
|
if (dialog->currentButton == lastButton)
|
|
{
|
|
dialog->currentButton = firstButton;
|
|
}
|
|
else
|
|
{
|
|
dialog->currentButton++;
|
|
}
|
|
break;
|
|
|
|
case KEY_UP : case KEY_DOWN :
|
|
Beep();
|
|
break;
|
|
|
|
case KEY_ESC :
|
|
dialog->exitType = vESCAPE_HIT;
|
|
return -1;
|
|
|
|
case KEY_RETURN : case KEY_ENTER : case KEY_CR :
|
|
dialog->exitType = vNORMAL;
|
|
return dialog->currentButton;
|
|
|
|
case CDK_REFRESH :
|
|
eraseCDKScreen (ScreenOf(dialog));
|
|
refreshCDKScreen (ScreenOf(dialog));
|
|
break;
|
|
|
|
default :
|
|
Beep();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Should we call a post-process? */
|
|
if (dialog->postProcessFunction != 0)
|
|
{
|
|
((PROCESSFN)(dialog->postProcessFunction)) (vDIALOG, dialog, dialog->postProcessData, input);
|
|
}
|
|
}
|
|
|
|
/* Redraw the buttons. */
|
|
drawCDKDialogButtons (dialog);
|
|
|
|
/* Exit the dialog box. */
|
|
dialog->exitType = vEARLY_EXIT;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* This moves the dialog field to the given location.
|
|
*/
|
|
static void _moveCDKDialog (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag)
|
|
{
|
|
CDKDIALOG *dialog = (CDKDIALOG *)object;
|
|
|
|
/*
|
|
* If this is a relative move, then we will adjust where we want
|
|
* to move to.
|
|
*/
|
|
if (relative)
|
|
{
|
|
xplace += getbegx(dialog->win);
|
|
yplace += getbegy(dialog->win);
|
|
}
|
|
|
|
/* Adjust the window if we need to. */
|
|
alignxy (WindowOf(dialog), &xplace, &yplace, dialog->boxWidth, dialog->boxHeight);
|
|
|
|
/* Move the window to the new location. */
|
|
moveCursesWindow(dialog->win, xplace, yplace);
|
|
|
|
/* Redraw the window, if they asked for it. */
|
|
if (refresh_flag)
|
|
{
|
|
drawCDKDialog (dialog, ObjOf(dialog)->box);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This function draws the dialog widget.
|
|
*/
|
|
static void _drawCDKDialog (CDKOBJS *object, boolean Box)
|
|
{
|
|
CDKDIALOG *dialog = (CDKDIALOG *)object;
|
|
int x = 0;
|
|
|
|
/* Box the widget if they asked. */
|
|
if (Box)
|
|
{
|
|
attrbox (dialog->win,
|
|
dialog->ULChar, dialog->URChar,
|
|
dialog->LLChar, dialog->LRChar,
|
|
dialog->HChar, dialog->VChar,
|
|
dialog->BoxAttrib,
|
|
dialog->shadow);
|
|
}
|
|
|
|
/* Draw in the message. */
|
|
for (x=0; x < dialog->messageRows; x++)
|
|
{
|
|
writeChtype (dialog->infoWin,
|
|
dialog->infoPos[x], x,
|
|
dialog->info[x],
|
|
HORIZONTAL, 0,
|
|
dialog->infoLen[x]);
|
|
}
|
|
|
|
wnoutrefresh (dialog->infoWin);
|
|
|
|
/* Draw in the buttons. */
|
|
drawCDKDialogButtons (dialog);
|
|
}
|
|
|
|
/*
|
|
* This function destroys the dialog widget.
|
|
*/
|
|
void destroyCDKDialog (CDKDIALOG *dialog)
|
|
{
|
|
/* Declare local variables. */
|
|
int x;
|
|
|
|
/* Erase the object. */
|
|
eraseCDKDialog (dialog);
|
|
|
|
/* Clean up the char pointers. */
|
|
for (x=0; x < dialog->messageRows; x++)
|
|
{
|
|
freeChtype (dialog->info[x]);
|
|
}
|
|
for (x=0; x < dialog->buttonCount; x++)
|
|
{
|
|
freeChtype (dialog->buttonLabel[x]);
|
|
}
|
|
|
|
/* Clean up the windows. */
|
|
deleteCursesWindow (dialog->win);
|
|
|
|
/* Unregister this object. */
|
|
unregisterCDKObject (vDIALOG, dialog);
|
|
|
|
/* Finish cleaning up. */
|
|
free (dialog);
|
|
}
|
|
|
|
/*
|
|
* This function erases the dialog widget from the screen.
|
|
*/
|
|
static void _eraseCDKDialog (CDKOBJS *object)
|
|
{
|
|
CDKDIALOG *dialog = (CDKDIALOG *)object;
|
|
|
|
eraseCursesWindow (dialog->win);
|
|
}
|
|
|
|
/*
|
|
* This sets attributes of the dialog box.
|
|
*/
|
|
void setCDKDialog (CDKDIALOG *dialog, chtype buttonHighlight, boolean separator, boolean Box)
|
|
{
|
|
setCDKDialogHighlight (dialog, buttonHighlight);
|
|
setCDKDialogSeparator (dialog, separator);
|
|
setCDKDialogBox (dialog, Box);
|
|
}
|
|
|
|
/*
|
|
* This sets the highlight attribute for the buttons.
|
|
*/
|
|
void setCDKDialogHighlight (CDKDIALOG *dialog, chtype buttonHighlight)
|
|
{
|
|
dialog->buttonHighlight = buttonHighlight;
|
|
}
|
|
chtype getCDKDialogHighlight (CDKDIALOG *dialog)
|
|
{
|
|
return dialog->buttonHighlight;
|
|
}
|
|
|
|
/*
|
|
* This sets whether or not the dialog box will have a separator line.
|
|
*/
|
|
void setCDKDialogSeparator (CDKDIALOG *dialog, boolean separator)
|
|
{
|
|
dialog->separator = separator;
|
|
}
|
|
boolean getCDKDialogSeparator (CDKDIALOG *dialog)
|
|
{
|
|
return dialog->separator;
|
|
}
|
|
|
|
/*
|
|
* This sets the box attribute of the widget.
|
|
*/
|
|
void setCDKDialogBox (CDKDIALOG *dialog, boolean Box)
|
|
{
|
|
ObjOf(dialog)->box = Box;
|
|
}
|
|
boolean getCDKDialogBox (CDKDIALOG *dialog)
|
|
{
|
|
return ObjOf(dialog)->box;
|
|
}
|
|
|
|
/*
|
|
* These functions set the drawing characters of the widget.
|
|
*/
|
|
void setCDKDialogULChar (CDKDIALOG *dialog, chtype character)
|
|
{
|
|
dialog->ULChar = character;
|
|
}
|
|
void setCDKDialogURChar (CDKDIALOG *dialog, chtype character)
|
|
{
|
|
dialog->URChar = character;
|
|
}
|
|
void setCDKDialogLLChar (CDKDIALOG *dialog, chtype character)
|
|
{
|
|
dialog->LLChar = character;
|
|
}
|
|
void setCDKDialogLRChar (CDKDIALOG *dialog, chtype character)
|
|
{
|
|
dialog->LRChar = character;
|
|
}
|
|
void setCDKDialogVerticalChar (CDKDIALOG *dialog, chtype character)
|
|
{
|
|
dialog->VChar = character;
|
|
}
|
|
void setCDKDialogHorizontalChar (CDKDIALOG *dialog, chtype character)
|
|
{
|
|
dialog->HChar = character;
|
|
}
|
|
void setCDKDialogBoxAttribute (CDKDIALOG *dialog, chtype character)
|
|
{
|
|
dialog->BoxAttrib = character;
|
|
}
|
|
|
|
/*
|
|
* This sets the background color of the widget.
|
|
*/
|
|
void setCDKDialogBackgroundColor (CDKDIALOG *dialog, 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 (dialog->win, holder[0]);
|
|
|
|
/* Clean up. */
|
|
freeChtype (holder);
|
|
}
|
|
|
|
/*
|
|
* This draws the dialog buttons and the separation line.
|
|
*/
|
|
void drawCDKDialogButtons (CDKDIALOG *dialog)
|
|
{
|
|
/* Declare local variables. */
|
|
int x;
|
|
|
|
if (dialog->buttonCount > 0)
|
|
{
|
|
for (x=0; x < dialog->buttonCount; x++)
|
|
{
|
|
if (x == dialog->currentButton)
|
|
{
|
|
writeChtypeAttrib (dialog->buttonWin,
|
|
dialog->buttonPos[x], 0,
|
|
dialog->buttonLabel[x],
|
|
dialog->buttonHighlight,
|
|
HORIZONTAL, 0,
|
|
dialog->buttonLen[x]);
|
|
}
|
|
else
|
|
{
|
|
writeChtype (dialog->buttonWin,
|
|
dialog->buttonPos[x], 0,
|
|
dialog->buttonLabel[x],
|
|
HORIZONTAL, 0,
|
|
dialog->buttonLen[x]);
|
|
}
|
|
}
|
|
|
|
/* Draw the separation line. */
|
|
if (dialog->separator)
|
|
{
|
|
mvwaddch (dialog->win, dialog->boxHeight-3, 0, ACS_LTEE | dialog->BoxAttrib);
|
|
mvwhline (dialog->win, dialog->boxHeight-3, 1, ACS_HLINE | dialog->BoxAttrib, dialog->boxWidth-2);
|
|
mvwaddch (dialog->win, dialog->boxHeight-3, dialog->boxWidth-1, ACS_RTEE | dialog->BoxAttrib);
|
|
}
|
|
|
|
wnoutrefresh (dialog->buttonWin);
|
|
}
|
|
|
|
wnoutrefresh (dialog->win);
|
|
}
|
|
|
|
/*
|
|
* This function sets the pre-process function.
|
|
*/
|
|
void setCDKDialogPreProcess (CDKDIALOG *dialog, PROCESSFN callback, void *data)
|
|
{
|
|
dialog->preProcessFunction = callback;
|
|
dialog->preProcessData = data;
|
|
}
|
|
|
|
/*
|
|
* This function sets the post-process function.
|
|
*/
|
|
void setCDKDialogPostProcess (CDKDIALOG *dialog, PROCESSFN callback, void *data)
|
|
{
|
|
dialog->postProcessFunction = callback;
|
|
dialog->postProcessData = data;
|
|
}
|