NetBSD/dist/cdk/dialog.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;
}