#include <cdk_int.h>
/*
* $Author: tom $
* $Date: 2004/08/30 00:12:09 $
* $Revision: 1.59 $
*/
DeclareCDKObjects(BUTTONBOX, Buttonbox, setCdk, Int);
/*
* This returns a CDK buttonbox widget pointer.
*/
CDKBUTTONBOX *newCDKButtonbox (CDKSCREEN *cdkscreen, int xPos, int yPos, int height, int width, char *title, int rows, int cols, char **buttons, int buttonCount, chtype highlight, boolean Box, boolean shadow)
{
CDKBUTTONBOX *buttonbox = 0;
int parentWidth = getmaxx(cdkscreen->window);
int parentHeight = getmaxy(cdkscreen->window);
int boxWidth = 0;
int boxHeight = 0;
int maxColWidth = INT_MIN;
int colWidth = 0;
int xpos = xPos;
int ypos = yPos;
int currentButton = 0;
int x, y, junk;
if (buttonCount <= 0
|| (buttonbox = newCDKObject(CDKBUTTONBOX, &my_funcs)) == 0
|| (buttonbox->button = typeCallocN(chtype *, buttonCount + 1)) == 0
|| (buttonbox->buttonLen = typeCallocN(int, buttonCount + 1)) == 0
|| (buttonbox->buttonPos = typeCallocN(int, buttonCount + 1)) == 0
|| (buttonbox->columnWidths = typeCallocN(int, buttonCount + 1)) == 0)
{
destroyCDKObject (buttonbox);
return (0);
}
setCDKButtonboxBox (buttonbox, Box);
/* Set some default values for the widget. */
buttonbox->rowAdjust = 0;
buttonbox->colAdjust = 0;
/*
* 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, rows + 1);
/*
* 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);
boxWidth = setCdkTitle(ObjOf(buttonbox), title, boxWidth);
/* Translate the buttons char * to a chtype * */
for (x = 0; x < buttonCount; x++)
{
buttonbox->button[x] = char2Chtype (buttons[x], &buttonbox->buttonLen[x], &junk);
}
/* Set the button positions. */
for (x=0; x < cols; x++)
{
maxColWidth = INT_MIN;
/* Look for the widest item in this column. */
for (y=0; y < rows; y++)
{
if (currentButton < buttonCount)
{
maxColWidth = MAXIMUM (buttonbox->buttonLen[currentButton], maxColWidth);
currentButton++;
}
}
/* Keep the maximum column width for this column. */
buttonbox->columnWidths[x] = maxColWidth;
colWidth += maxColWidth;
}
boxWidth++;
/*
* Make sure we didn't extend beyond the dimensions of the window.
*/
boxWidth = (boxWidth > parentWidth ? parentWidth : boxWidth);
boxHeight = (boxHeight > parentHeight ? parentHeight : boxHeight);
/* Now we have to readjust the x and y positions. */
alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
/* Set up the buttonbox box attributes. */
ScreenOf(buttonbox) = cdkscreen;
buttonbox->parent = cdkscreen->window;
buttonbox->win = newwin (boxHeight, boxWidth, ypos, xpos);
buttonbox->shadowWin = 0;
buttonbox->buttonCount = buttonCount;
buttonbox->currentButton = 0;
buttonbox->rows = rows;
buttonbox->cols = (buttonCount < cols ? buttonCount : cols);
buttonbox->boxHeight = boxHeight;
buttonbox->boxWidth = boxWidth;
buttonbox->highlight = highlight;
initExitType(buttonbox);
ObjOf(buttonbox)->acceptsFocus = TRUE;
ObjOf(buttonbox)->inputWindow = buttonbox->win;
buttonbox->shadow = shadow;
buttonbox->ButtonAttrib = A_NORMAL;
/* Set up the row adjustment. */
if (boxHeight - rows - TitleLinesOf(buttonbox) > 0)
{
buttonbox->rowAdjust = (int)((boxHeight - rows - TitleLinesOf(buttonbox)) / buttonbox->rows);
}
/* Set the col adjustment. */
if (boxWidth - colWidth > 0)
{
buttonbox->colAdjust = (int)((boxWidth-colWidth) / buttonbox->cols)-1;
}
/* If we couldn't create the window, we should return a null value. */
if (buttonbox->win == 0)
{
destroyCDKObject (buttonbox);
return (0);
}
keypad (buttonbox->win, TRUE);
/* Was there a shadow? */
if (shadow)
{
buttonbox->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1);
}
/* Empty the key bindings. */
cleanCDKObjectBindings (vBUTTONBOX, buttonbox);
/* Register this baby. */
registerCDKObject (cdkscreen, vBUTTONBOX, buttonbox);
/* Return the buttonbox box pointer. */
return (buttonbox);
}
/*
* This activates the widget.
*/
int activateCDKButtonbox (CDKBUTTONBOX *buttonbox, chtype *actions)
{
chtype input = 0;
int ret;
/* Draw the buttonbox box. */
drawCDKButtonbox (buttonbox, ObjOf(buttonbox)->box);
/* Check if actions is null. */
if (actions == 0)
{
for (;;)
{
/* Get the input. */
input = getcCDKObject (ObjOf(buttonbox));
/* Inject the character into the widget. */
ret = injectCDKButtonbox (buttonbox, input);
if (buttonbox->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 = injectCDKButtonbox (buttonbox, actions[x]);
if (buttonbox->exitType != vEARLY_EXIT)
{
return ret;
}
}
}
/* Set the exit type and exit. */
setExitType(buttonbox, 0);
return -1;
}
/*
* This injects a single character into the widget.
*/
static int _injectCDKButtonbox (CDKOBJS *object, chtype input)
{
CDKBUTTONBOX *buttonbox = (CDKBUTTONBOX *)object;
int firstButton = 0;
int lastButton = buttonbox->buttonCount - 1;
int ppReturn = 1;
int ret = unknownInt;
bool complete = FALSE;
/* Set the exit type. */
setExitType(buttonbox, 0);
/* Check if there is a pre-process function to be called. */
if (PreProcessFuncOf(buttonbox) != 0)
{
ppReturn = PreProcessFuncOf(buttonbox) (vBUTTONBOX, buttonbox, PreProcessDataOf(buttonbox), input);
}
/* Should we continue? */
if (ppReturn != 0)
{
/* Check for a key binding. */
if (checkCDKObjectBind (vBUTTONBOX, buttonbox, input) != 0)
{
checkEarlyExit(buttonbox);
complete = TRUE;
}
else
{
switch (input)
{
case KEY_LEFT : case KEY_BTAB : case KEY_BACKSPACE :
if ((buttonbox->currentButton-buttonbox->rows) < firstButton)
{
buttonbox->currentButton = lastButton;
}
else
{
buttonbox->currentButton -= buttonbox->rows;
}
break;
case KEY_RIGHT : case KEY_TAB : case SPACE :
if ((buttonbox->currentButton + buttonbox->rows) > lastButton)
{
buttonbox->currentButton = firstButton;
}
else
{
buttonbox->currentButton += buttonbox->rows;
}
break;
case KEY_UP :
if ((buttonbox->currentButton-1) < firstButton)
{
buttonbox->currentButton = lastButton;
}
else
{
buttonbox->currentButton--;
}
break;
case KEY_DOWN :
if ((buttonbox->currentButton + 1) > lastButton)
{
buttonbox->currentButton = firstButton;
}
else
{
buttonbox->currentButton++;
}
break;
case CDK_REFRESH :
eraseCDKScreen (ScreenOf(buttonbox));
refreshCDKScreen (ScreenOf(buttonbox));
break;
case KEY_ESC :
setExitType(buttonbox, input);
complete = TRUE;
break;
case KEY_ENTER :
setExitType(buttonbox, input);
ret = buttonbox->currentButton;
complete = TRUE;
break;
default :
break;
}
}
/* Should we call a post-process? */
if (!complete && (PostProcessFuncOf(buttonbox) != 0))
{
PostProcessFuncOf(buttonbox) (vBUTTONBOX, buttonbox, PostProcessDataOf(buttonbox), input);
}
}
if (!complete) {
drawCDKButtonboxButtons (buttonbox);
setExitType(buttonbox, 0);
}
ResultOf(buttonbox).valueInt = ret;
return (ret != unknownInt);
}
/*
* This sets multiple attributes of the widget.
*/
void setCDKButtonbox (CDKBUTTONBOX *buttonbox, chtype highlight, boolean Box)
{
setCDKButtonboxHighlight (buttonbox, highlight);
setCDKButtonboxBox (buttonbox, Box);
}
/*
* This sets the highlight attribute for the buttonboxs.
*/
void setCDKButtonboxHighlight (CDKBUTTONBOX *buttonbox, chtype highlight)
{
buttonbox->highlight = highlight;
}
chtype getCDKButtonboxHighlight (CDKBUTTONBOX *buttonbox)
{
return (chtype)buttonbox->highlight;
}
/*
* This sets the box attribute of the widget.
*/
void setCDKButtonboxBox (CDKBUTTONBOX *buttonbox, boolean Box)
{
ObjOf(buttonbox)->box = Box;
ObjOf(buttonbox)->borderSize = Box ? 1 : 0;
}
boolean getCDKButtonboxBox (CDKBUTTONBOX *buttonbox)
{
return ObjOf(buttonbox)->box;
}
/*
* This sets the background attribute of the widget.
*/
static void _setBKattrButtonbox (CDKOBJS *object, chtype attrib)
{
if (object != 0)
{
CDKBUTTONBOX *widget = (CDKBUTTONBOX *) object;
wbkgd (widget->win, attrib);
}
}
/*
* This draws the buttonbox box widget.
*/
static void _drawCDKButtonbox (CDKOBJS *object, boolean Box)
{
CDKBUTTONBOX *buttonbox = (CDKBUTTONBOX *)object;
/* Is there a shadow? */
if (buttonbox->shadowWin != 0)
{
drawShadow (buttonbox->shadowWin);
}
/* Box the widget if they asked. */
if (Box)
{
drawObjBox (buttonbox->win, ObjOf(buttonbox));
}
/* Draw in the title if there is one. */
drawCdkTitle (buttonbox->win, object);
/* Draw in the buttons. */
drawCDKButtonboxButtons (buttonbox);
}
/*
* This draws the buttons on the button box widget.
*/
void drawCDKButtonboxButtons (CDKBUTTONBOX *buttonbox)
{
int row = TitleLinesOf(buttonbox) + 1;
int col = (int)(buttonbox->colAdjust / 2);
int currentButton = 0;
int x, y;
int cur_row = -1;
int cur_col = -1;
/* Draw the buttons. */
while (currentButton < buttonbox->buttonCount)
{
for (x=0; x < buttonbox->cols; x++)
{
row = TitleLinesOf(buttonbox) + BorderOf(buttonbox);
for (y=0; y < buttonbox->rows; y++)
{
chtype attr = buttonbox->ButtonAttrib;
if (currentButton == buttonbox->currentButton)
{
attr = buttonbox->highlight,
cur_row = row;
cur_col = col;
}
writeChtypeAttrib (buttonbox->win,
col, row,
buttonbox->button[currentButton],
attr,
HORIZONTAL, 0,
buttonbox->buttonLen[currentButton]);
row += (1 + buttonbox->rowAdjust);
currentButton++;
}
col += buttonbox->columnWidths[x] + buttonbox->colAdjust + BorderOf(buttonbox);
}
}
if (cur_row >= 0 && cur_col >= 0)
wmove(buttonbox->win, cur_row, cur_col);
refreshCDKWindow (buttonbox->win);
}
/*
* This erases the buttonbox box from the screen.
*/
static void _eraseCDKButtonbox (CDKOBJS *object)
{
if (validCDKObject (object))
{
CDKBUTTONBOX *buttonbox = (CDKBUTTONBOX *)object;
eraseCursesWindow (buttonbox->win);
eraseCursesWindow (buttonbox->shadowWin);
}
}
/*
* This moves the buttonbox box to a new screen location.
*/
static void _moveCDKButtonbox (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag)
{
CDKBUTTONBOX *buttonbox = (CDKBUTTONBOX *)object;
int currentX = getbegx(buttonbox->win);
int currentY = getbegy(buttonbox->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(buttonbox->win) + xplace;
ypos = getbegy(buttonbox->win) + yplace;
}
/* Adjust the window if we need to. */
alignxy (WindowOf(buttonbox), &xpos, &ypos, buttonbox->boxWidth, buttonbox->boxHeight);
/* Get the difference. */
xdiff = currentX - xpos;
ydiff = currentY - ypos;
/* Move the window to the new location. */
moveCursesWindow(buttonbox->win, -xdiff, -ydiff);
moveCursesWindow(buttonbox->shadowWin, -xdiff, -ydiff);
/* Touch the windows so they 'move'. */
refreshCDKWindow (WindowOf(buttonbox));
/* Redraw the window, if they asked for it. */
if (refresh_flag)
{
drawCDKButtonbox (buttonbox, ObjOf(buttonbox)->box);
}
}
/*
* This destroys the widget and all the memory associated with it.
*/
static void _destroyCDKButtonbox (CDKOBJS *object)
{
if (object != 0)
{
CDKBUTTONBOX *buttonbox = (CDKBUTTONBOX *)object;
cleanCdkTitle (object);
CDKfreeChtypes (buttonbox->button);
freeChecked (buttonbox->buttonLen);
freeChecked (buttonbox->buttonPos);
freeChecked (buttonbox->columnWidths);
/* Delete the windows. */
deleteCursesWindow (buttonbox->shadowWin);
deleteCursesWindow (buttonbox->win);
/* Unregister this object. */
unregisterCDKObject (vBUTTONBOX, buttonbox);
}
}
/*
*
*/
void setCDKButtonboxCurrentButton (CDKBUTTONBOX * buttonbox, int button)
{
if ((button >= 0) && (button < buttonbox->buttonCount))
{
buttonbox->currentButton = button;
}
}
int getCDKButtonboxCurrentButton (CDKBUTTONBOX * buttonbox)
{
return buttonbox->currentButton;
}
int getCDKButtonboxButtonCount (CDKBUTTONBOX * buttonbox)
{
return buttonbox->buttonCount;
}
static void _focusCDKButtonbox (CDKOBJS * object)
{
CDKBUTTONBOX *widget = (CDKBUTTONBOX *)object;
drawCDKButtonbox (widget, ObjOf(widget)->box);
}
static void _unfocusCDKButtonbox (CDKOBJS * object)
{
CDKBUTTONBOX *widget = (CDKBUTTONBOX *)object;
drawCDKButtonbox (widget, ObjOf(widget)->box);
}
dummyRefreshData(Buttonbox)
dummySaveData(Buttonbox)
syntax highlighted by Code2HTML, v. 0.9.1