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/dialog.c
2017-03-20 21:40:32 +10:00

564 lines
13 KiB
C

#include <cdk_int.h>
/*
* $Author: tom $
* $Date: 2016/11/20 19:02:55 $
* $Revision: 1.102 $
*/
DeclareCDKObjects (DIALOG, Dialog, setCdk, Int);
/*
* This function creates a dialog widget.
*/
CDKDIALOG *newCDKDialog (CDKSCREEN *cdkscreen,
int xplace,
int yplace,
CDK_CSTRING2 mesg,
int rows,
CDK_CSTRING2 buttonLabel,
int buttonCount,
chtype highlight,
boolean separator,
boolean Box,
boolean shadow)
{
/* *INDENT-EQLS* */
CDKDIALOG *dialog = 0;
int boxHeight;
int boxWidth = MIN_DIALOG_WIDTH;
int maxmessagewidth = -1;
int buttonwidth = 0;
int xpos = xplace;
int ypos = yplace;
int temp = 0;
int buttonadj = 0;
int x = 0;
if (rows <= 0
|| buttonCount <= 0
|| (dialog = newCDKObject (CDKDIALOG, &my_funcs)) == 0
|| (dialog->info = typeCallocN (chtype *, rows + 1)) == 0
|| (dialog->infoLen = typeCallocN (int, rows + 1)) == 0
|| (dialog->infoPos = typeCallocN (int, rows + 1)) == 0
|| (dialog->buttonLabel = typeCallocN (chtype *, buttonCount + 1)) == 0
|| (dialog->buttonLen = typeCallocN (int, buttonCount + 1)) == 0
|| (dialog->buttonPos = typeCallocN (int, buttonCount + 1)) == 0)
{
destroyCDKObject (dialog);
return (0);
}
setCDKDialogBox (dialog, Box);
boxHeight = rows + 2 * BorderOf (dialog) + separator + 1;
/* 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 * */
for (x = 0; x < buttonCount; x++)
{
/* *INDENT-EQLS* */
dialog->buttonLabel[x] = char2Chtype (buttonLabel[x],
&dialog->buttonLen[x],
&temp);
buttonwidth += dialog->buttonLen[x] + 1;
}
buttonwidth--;
/* Determine the final dimensions of the box. */
boxWidth = MAXIMUM (boxWidth, maxmessagewidth);
boxWidth = MAXIMUM (boxWidth, buttonwidth);
boxWidth = boxWidth + 2 + 2 * BorderOf (dialog);
/* Now we have to readjust the x and y positions. */
alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
/* *INDENT-EQLS* Set up the dialog box attributes. */
ScreenOf (dialog) = cdkscreen;
dialog->parent = cdkscreen->window;
dialog->win = newwin (boxHeight, boxWidth, ypos, xpos);
dialog->shadowWin = 0;
dialog->buttonCount = buttonCount;
dialog->currentButton = 0;
dialog->messageRows = rows;
dialog->boxHeight = boxHeight;
dialog->boxWidth = boxWidth;
dialog->highlight = highlight;
dialog->separator = separator;
initExitType (dialog);
ObjOf (dialog)->acceptsFocus = TRUE;
ObjOf (dialog)->inputWindow = dialog->win;
dialog->shadow = shadow;
/* If we couldn't create the window, we should return a null value. */
if (dialog->win == 0)
{
destroyCDKObject (dialog);
return (0);
}
keypad (dialog->win, TRUE);
/* Find the button positions. */
buttonadj = ((int)((boxWidth - buttonwidth) / 2));
for (x = 0; x < buttonCount; x++)
{
dialog->buttonPos[x] = buttonadj;
buttonadj = buttonadj + dialog->buttonLen[x] + BorderOf (dialog);
}
/* Create the string alignments. */
for (x = 0; x < rows; x++)
{
dialog->infoPos[x] = justifyString (boxWidth - 2 * BorderOf (dialog),
dialog->infoLen[x],
dialog->infoPos[x]);
}
/* Was there a shadow? */
if (shadow)
{
dialog->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1);
}
/* 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)
{
chtype input = 0;
boolean functionKey;
int ret;
/* Draw the dialog box. */
drawCDKDialog (dialog, ObjOf (dialog)->box);
/* Lets move to the first button. */
writeChtypeAttrib (dialog->win,
dialog->buttonPos[dialog->currentButton],
dialog->boxHeight - 1 - BorderOf (dialog),
dialog->buttonLabel[dialog->currentButton],
dialog->highlight,
HORIZONTAL,
0, dialog->buttonLen[dialog->currentButton]);
wrefresh (dialog->win);
if (actions == 0)
{
for (;;)
{
input = (chtype)getchCDKObject (ObjOf (dialog), &functionKey);
/* 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. */
setExitType (dialog, 0);
return -1;
}
/*
* This injects a single character into the dialog widget.
*/
static int _injectCDKDialog (CDKOBJS *object, chtype input)
{
/* *INDENT-EQLS* */
CDKDIALOG *widget = (CDKDIALOG *)object;
int lastButton = widget->buttonCount - 1;
int ppReturn = 1;
int ret = unknownInt;
bool complete = FALSE;
/* Set the exit type. */
setExitType (widget, 0);
/* Check if there is a pre-process function to be called. */
if (PreProcessFuncOf (widget) != 0)
{
ppReturn = PreProcessFuncOf (widget) (vDIALOG,
widget,
PreProcessDataOf (widget),
input);
}
/* Should we continue? */
if (ppReturn != 0)
{
/* Check for a key binding. */
if (checkCDKObjectBind (vDIALOG, widget, input) != 0)
{
checkEarlyExit (widget);
complete = TRUE;
}
else
{
int firstButton = 0;
switch (input)
{
case KEY_LEFT:
case KEY_BTAB:
case KEY_BACKSPACE:
if (widget->currentButton == firstButton)
{
widget->currentButton = lastButton;;
}
else
{
widget->currentButton--;
}
break;
case KEY_RIGHT:
case KEY_TAB:
case SPACE:
if (widget->currentButton == lastButton)
{
widget->currentButton = firstButton;
}
else
{
widget->currentButton++;
}
break;
case KEY_UP:
case KEY_DOWN:
Beep ();
break;
case CDK_REFRESH:
eraseCDKScreen (ScreenOf (widget));
refreshCDKScreen (ScreenOf (widget));
break;
case KEY_ESC:
setExitType (widget, input);
complete = TRUE;
break;
case KEY_ERROR:
setExitType (widget, input);
complete = TRUE;
break;
case KEY_ENTER:
setExitType (widget, input);
ret = widget->currentButton;
complete = TRUE;
break;
default:
break;
}
}
/* Should we call a post-process? */
if (!complete && (PostProcessFuncOf (widget) != 0))
{
PostProcessFuncOf (widget) (vDIALOG,
widget,
PostProcessDataOf (widget),
input);
}
}
if (!complete)
{
drawCDKDialogButtons (widget);
wrefresh (widget->win);
setExitType (widget, 0);
}
ResultOf (widget).valueInt = ret;
return (ret != unknownInt);
}
/*
* 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;
/* *INDENT-EQLS* */
int currentX = getbegx (dialog->win);
int currentY = getbegy (dialog->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 (dialog->win) + xplace;
ypos = getbegy (dialog->win) + yplace;
}
/* Adjust the window if we need to. */
alignxy (WindowOf (dialog), &xpos, &ypos, dialog->boxWidth, dialog->boxHeight);
/* Get the difference. */
xdiff = currentX - xpos;
ydiff = currentY - ypos;
/* Move the window to the new location. */
moveCursesWindow (dialog->win, -xdiff, -ydiff);
moveCursesWindow (dialog->shadowWin, -xdiff, -ydiff);
/* Touch the windows so they 'move'. */
refreshCDKWindow (WindowOf (dialog));
/* 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;
/* Is there a shadow? */
if (dialog->shadowWin != 0)
{
drawShadow (dialog->shadowWin);
}
/* Box the widget if they asked. */
if (Box)
{
drawObjBox (dialog->win, ObjOf (dialog));
}
/* Draw in the message. */
for (x = 0; x < dialog->messageRows; x++)
{
writeChtype (dialog->win,
dialog->infoPos[x] + BorderOf (dialog), x + BorderOf (dialog),
dialog->info[x],
HORIZONTAL, 0,
dialog->infoLen[x]);
}
/* Draw in the buttons. */
drawCDKDialogButtons (dialog);
wrefresh (dialog->win);
}
/*
* This function destroys the dialog widget.
*/
static void _destroyCDKDialog (CDKOBJS *object)
{
if (object != 0)
{
CDKDIALOG *dialog = (CDKDIALOG *)object;
CDKfreeChtypes (dialog->info);
freeChecked (dialog->infoLen);
freeChecked (dialog->infoPos);
CDKfreeChtypes (dialog->buttonLabel);
freeChecked (dialog->buttonLen);
freeChecked (dialog->buttonPos);
/* Clean up the windows. */
deleteCursesWindow (dialog->win);
deleteCursesWindow (dialog->shadowWin);
/* Clean the key bindings. */
cleanCDKObjectBindings (vDIALOG, dialog);
/* Unregister this object. */
unregisterCDKObject (vDIALOG, dialog);
}
}
/*
* This function erases the dialog widget from the screen.
*/
static void _eraseCDKDialog (CDKOBJS *object)
{
if (validCDKObject (object))
{
CDKDIALOG *dialog = (CDKDIALOG *)object;
eraseCursesWindow (dialog->win);
eraseCursesWindow (dialog->shadowWin);
}
}
/*
* This sets attributes of the dialog box.
*/
void setCDKDialog (CDKDIALOG *dialog, chtype highlight, boolean separator, boolean Box)
{
setCDKDialogHighlight (dialog, highlight);
setCDKDialogSeparator (dialog, separator);
setCDKDialogBox (dialog, Box);
}
/*
* This sets the highlight attribute for the buttons.
*/
void setCDKDialogHighlight (CDKDIALOG *dialog, chtype highlight)
{
dialog->highlight = highlight;
}
chtype getCDKDialogHighlight (CDKDIALOG *dialog)
{
return dialog->highlight;
}
/*
* 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;
ObjOf (dialog)->borderSize = Box ? 1 : 0;
}
boolean getCDKDialogBox (CDKDIALOG *dialog)
{
return ObjOf (dialog)->box;
}
/*
* This sets the background attribute of the widget.
*/
static void _setBKattrDialog (CDKOBJS *object, chtype attrib)
{
if (object != 0)
{
CDKDIALOG *widget = (CDKDIALOG *)object;
wbkgd (widget->win, attrib);
}
}
/*
* This draws the dialog buttons and the separation line.
*/
void drawCDKDialogButtons (CDKDIALOG *dialog)
{
int x;
for (x = 0; x < dialog->buttonCount; x++)
{
writeChtype (dialog->win,
dialog->buttonPos[x],
dialog->boxHeight - 1 - BorderOf (dialog),
dialog->buttonLabel[x],
HORIZONTAL, 0,
dialog->buttonLen[x]);
}
/* Draw the separation line. */
if (dialog->separator)
{
chtype boxattr = BXAttrOf (dialog);
for (x = 1; x < dialog->boxWidth - 1; x++)
{
(void)mvwaddch (dialog->win,
dialog->boxHeight - 2 - BorderOf (dialog),
x,
ACS_HLINE | boxattr);
}
(void)mvwaddch (dialog->win,
dialog->boxHeight - 2 - BorderOf (dialog),
0,
ACS_LTEE | boxattr);
(void)mvwaddch (dialog->win,
dialog->boxHeight - 2 - BorderOf (dialog),
getmaxx (dialog->win) - 1,
ACS_RTEE | boxattr);
}
writeChtypeAttrib (dialog->win,
dialog->buttonPos[dialog->currentButton],
dialog->boxHeight - 1 - BorderOf (dialog),
dialog->buttonLabel[dialog->currentButton],
dialog->highlight,
HORIZONTAL, 0,
dialog->buttonLen[dialog->currentButton]);
}
static void _focusCDKDialog (CDKOBJS *object)
{
CDKDIALOG *widget = (CDKDIALOG *)object;
drawCDKDialog (widget, ObjOf (widget)->box);
}
static void _unfocusCDKDialog (CDKOBJS *object)
{
CDKDIALOG *widget = (CDKDIALOG *)object;
drawCDKDialog (widget, ObjOf (widget)->box);
}
dummyRefreshData (Dialog)
dummySaveData (Dialog)