666 lines
16 KiB
C
666 lines
16 KiB
C
#include <cdk.h>
|
|
|
|
/*
|
|
* $Author: garbled $
|
|
* $Date: 2001/01/09 18:41:53 $
|
|
* $Revision: 1.3 $
|
|
*/
|
|
|
|
DeclareCDKObjects(my_funcs,Itemlist);
|
|
|
|
/*
|
|
* This creates a pointer to an itemlist widget.
|
|
*/
|
|
CDKITEMLIST *newCDKItemlist (CDKSCREEN *cdkscreen, int xplace, int yplace, char *title, char *label, char **item, int count, int defaultItem, boolean Box, boolean shadow)
|
|
{
|
|
/* Set up some variables. */
|
|
CDKITEMLIST *itemlist = newCDKObject(CDKITEMLIST, &my_funcs);
|
|
chtype *holder = 0;
|
|
int parentWidth = getmaxx(cdkscreen->window);
|
|
int parentHeight = getmaxy(cdkscreen->window);
|
|
int boxWidth = 0;
|
|
int boxHeight = 3;
|
|
int maxWidth = INT_MIN;
|
|
int fieldWidth = 0;
|
|
int xpos = xplace;
|
|
int ypos = yplace;
|
|
int horizontalAdjust = 0;
|
|
char **temp = 0;
|
|
int x, len, junk, junk2;
|
|
|
|
/* Set some basic values of the itemlist. */
|
|
itemlist->label = 0;
|
|
itemlist->titleLines = 0;
|
|
itemlist->labelLen = 0;
|
|
itemlist->labelWin = 0;
|
|
|
|
/* Translate the label char *pointer to a chtype pointer. */
|
|
if (label != 0)
|
|
{
|
|
itemlist->label = char2Chtype (label, &itemlist->labelLen, &junk);
|
|
}
|
|
|
|
/* Go through the list and determine the widest item. */
|
|
for (x=0; x < count; x++)
|
|
{
|
|
/* Copy the item to the list. */
|
|
itemlist->item[x] = char2Chtype (item[x], &itemlist->itemLen[x], &itemlist->itemPos[x]);
|
|
maxWidth = MAXIMUM (maxWidth, itemlist->itemLen[x]);
|
|
}
|
|
|
|
/* Set the field width and the box width. */
|
|
fieldWidth = maxWidth;
|
|
boxWidth = fieldWidth + itemlist->labelLen + 2;
|
|
|
|
/* Now we need to justify the strings. */
|
|
for (x=0; x < count; x++)
|
|
{
|
|
itemlist->itemPos[x] = justifyString (fieldWidth, itemlist->itemLen[x], itemlist->itemPos[x]);
|
|
}
|
|
|
|
/* Translate the char * items to chtype * */
|
|
if (title != 0)
|
|
{
|
|
temp = CDKsplitString (title, '\n');
|
|
itemlist->titleLines = CDKcountStrings (temp);
|
|
|
|
/* We need to determine the widest title line. */
|
|
for (x=0; x < itemlist->titleLines; x++)
|
|
{
|
|
holder = char2Chtype (temp[x], &len, &junk2);
|
|
maxWidth = MAXIMUM (maxWidth, len);
|
|
freeChtype (holder);
|
|
}
|
|
|
|
/*
|
|
* If one of the title lines is wider than the field and the label,
|
|
* the box width will expand to accomodate.
|
|
*/
|
|
if (maxWidth > boxWidth)
|
|
{
|
|
horizontalAdjust = (int)((maxWidth - boxWidth) / 2) + 1;
|
|
boxWidth = maxWidth + 2;
|
|
}
|
|
|
|
/* For each line in the title, convert from char * to chtype * */
|
|
for (x=0; x < itemlist->titleLines; x++)
|
|
{
|
|
itemlist->title[x] = char2Chtype (temp[x], &itemlist->titleLen[x], &itemlist->titlePos[x]);
|
|
itemlist->titlePos[x] = justifyString (boxWidth - 2, itemlist->titleLen[x], itemlist->titlePos[x]);
|
|
}
|
|
CDKfreeStrings(temp);
|
|
}
|
|
else
|
|
{
|
|
/* No title? Set the required variables. */
|
|
itemlist->titleLines = 0;
|
|
}
|
|
boxHeight += itemlist->titleLines;
|
|
|
|
/*
|
|
* Make sure we didn't extend beyond the dimensions of the window.
|
|
*/
|
|
boxWidth = MINIMUM (boxWidth, parentWidth);
|
|
boxHeight = MINIMUM (boxHeight, parentHeight);
|
|
fieldWidth = (fieldWidth > (boxWidth - itemlist->labelLen - 2) ? (boxWidth - itemlist->labelLen - 2) : fieldWidth);
|
|
|
|
/* Rejustify the x and y positions if we need to. */
|
|
alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
|
|
|
|
/* Make the label window. */
|
|
itemlist->win = newwin (boxHeight + !!shadow, boxWidth + !!shadow, ypos, xpos);
|
|
|
|
/* Is the window null ??? */
|
|
if (itemlist->win == 0)
|
|
{
|
|
/* Clean up the pointers. */
|
|
freeChtype (itemlist->label);
|
|
free (itemlist);
|
|
|
|
/* Exit with null. */
|
|
return (0);
|
|
}
|
|
keypad (itemlist->win, TRUE);
|
|
leaveok (itemlist->win, TRUE);
|
|
|
|
if (itemlist->titleLines > 0)
|
|
{
|
|
/* Make the title window. */
|
|
itemlist->titleWin = subwin (itemlist->win,
|
|
itemlist->titleLines, boxWidth - 2,
|
|
ypos + 1, xpos + 1);
|
|
}
|
|
|
|
/* Make the label window if there was a label. */
|
|
if (itemlist->label != 0)
|
|
{
|
|
itemlist->labelWin = subwin (itemlist->win, 1, itemlist->labelLen,
|
|
ypos + itemlist->titleLines + 1,
|
|
xpos + horizontalAdjust + 1);
|
|
}
|
|
|
|
/* Make the field window. */
|
|
itemlist->fieldWin = subwin (itemlist->win, 1, fieldWidth,
|
|
ypos + itemlist->titleLines + 1,
|
|
xpos + itemlist->labelLen + horizontalAdjust + 1);
|
|
|
|
/* Set up the rest of the structure. */
|
|
ScreenOf(itemlist) = cdkscreen;
|
|
itemlist->parent = cdkscreen->window;
|
|
itemlist->boxHeight = boxHeight;
|
|
itemlist->boxWidth = boxWidth;
|
|
itemlist->fieldWidth = fieldWidth;
|
|
itemlist->itemCount = count-1;
|
|
itemlist->exitType = vNEVER_ACTIVATED;
|
|
ObjOf(itemlist)->box = Box;
|
|
itemlist->shadow = shadow;
|
|
itemlist->ULChar = ACS_ULCORNER;
|
|
itemlist->URChar = ACS_URCORNER;
|
|
itemlist->LLChar = ACS_LLCORNER;
|
|
itemlist->LRChar = ACS_LRCORNER;
|
|
itemlist->HChar = ACS_HLINE;
|
|
itemlist->VChar = ACS_VLINE;
|
|
itemlist->BoxAttrib = A_NORMAL;
|
|
itemlist->preProcessFunction = 0;
|
|
itemlist->preProcessData = 0;
|
|
itemlist->postProcessFunction = 0;
|
|
itemlist->postProcessData = 0;
|
|
|
|
/* Set then default item. */
|
|
if (defaultItem >= 0 && defaultItem <= itemlist->itemCount)
|
|
{
|
|
itemlist->currentItem = defaultItem;
|
|
itemlist->defaultItem = defaultItem;
|
|
}
|
|
else
|
|
{
|
|
itemlist->currentItem = 0;
|
|
itemlist->defaultItem = 0;
|
|
}
|
|
|
|
/* Clean the key bindings. */
|
|
cleanCDKObjectBindings (vITEMLIST, itemlist);
|
|
|
|
/* Register this baby. */
|
|
registerCDKObject (cdkscreen, vITEMLIST, itemlist);
|
|
|
|
/* Return the pointer to the structure */
|
|
return (itemlist);
|
|
}
|
|
|
|
/*
|
|
* This allows the user to play with the widget.
|
|
*/
|
|
int activateCDKItemlist (CDKITEMLIST *itemlist, chtype *actions)
|
|
{
|
|
/* Declare local variables. */
|
|
int ret = -1;
|
|
|
|
/* Draw the widget. */
|
|
drawCDKItemlist (itemlist, ObjOf(itemlist)->box);
|
|
|
|
/* Check if actions is null. */
|
|
if (actions == 0)
|
|
{
|
|
chtype input = 0;
|
|
for (;;)
|
|
{
|
|
/* Get the input. */
|
|
wrefresh (itemlist->win);
|
|
input = wgetch (itemlist->win);
|
|
|
|
/* Inject the character into the widget. */
|
|
ret = injectCDKItemlist (itemlist, input);
|
|
if (itemlist->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 = injectCDKItemlist (itemlist, actions[x]);
|
|
if (itemlist->exitType != vEARLY_EXIT)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Set the exit type and exit. */
|
|
itemlist->exitType = vEARLY_EXIT;
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* This injects a single character into the widget.
|
|
*/
|
|
int injectCDKItemlist (CDKITEMLIST *itemlist, chtype input)
|
|
{
|
|
/* Declare local variables. */
|
|
int ppReturn = 1;
|
|
|
|
/* Set the exit type. */
|
|
itemlist->exitType = vEARLY_EXIT;
|
|
|
|
/* Draw the itemlist field. */
|
|
drawCDKItemlistField (itemlist);
|
|
|
|
/* Check if there is a pre-process function to be called. */
|
|
if (itemlist->preProcessFunction != 0)
|
|
{
|
|
/* Call the pre-process function. */
|
|
ppReturn = ((PROCESSFN)(itemlist->preProcessFunction)) (vITEMLIST, itemlist, itemlist->preProcessData, input);
|
|
}
|
|
|
|
/* Should we continue? */
|
|
if (ppReturn != 0)
|
|
{
|
|
/* Check a predefined binding. */
|
|
if (checkCDKObjectBind (vITEMLIST, itemlist, input) != 0)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
switch (input)
|
|
{
|
|
case KEY_UP : case KEY_RIGHT : case ' ' : case '+' : case 'n' :
|
|
if (itemlist->currentItem < itemlist->itemCount)
|
|
{
|
|
itemlist->currentItem++;
|
|
}
|
|
else
|
|
{
|
|
itemlist->currentItem = 0;
|
|
}
|
|
break;
|
|
|
|
case KEY_DOWN : case KEY_LEFT : case '-' : case 'p' :
|
|
if (itemlist->currentItem > 0)
|
|
{
|
|
itemlist->currentItem--;
|
|
}
|
|
else
|
|
{
|
|
itemlist->currentItem = itemlist->itemCount;
|
|
}
|
|
break;
|
|
|
|
case 'd' : case 'D' :
|
|
itemlist->currentItem = itemlist->defaultItem;
|
|
break;
|
|
|
|
case '0' :
|
|
itemlist->currentItem = 0;
|
|
break;
|
|
|
|
case '$' :
|
|
itemlist->currentItem = itemlist->itemCount;
|
|
break;
|
|
|
|
case KEY_ESC :
|
|
itemlist->exitType = vESCAPE_HIT;
|
|
return -1;
|
|
|
|
case KEY_RETURN : case KEY_TAB : case KEY_ENTER : case KEY_CR :
|
|
itemlist->exitType = vNORMAL;
|
|
return itemlist->currentItem;
|
|
|
|
case CDK_REFRESH :
|
|
eraseCDKScreen (ScreenOf(itemlist));
|
|
refreshCDKScreen (ScreenOf(itemlist));
|
|
break;
|
|
|
|
default :
|
|
Beep();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Should we call a post-process? */
|
|
if (itemlist->postProcessFunction != 0)
|
|
{
|
|
((PROCESSFN)(itemlist->postProcessFunction)) (vITEMLIST, itemlist, itemlist->postProcessData, input);
|
|
}
|
|
}
|
|
|
|
/* Redraw the field. */
|
|
drawCDKItemlistField (itemlist);
|
|
|
|
/* Set the exit type and leave. */
|
|
itemlist->exitType = vEARLY_EXIT;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* This moves the itemlist field to the given location.
|
|
*/
|
|
static void _moveCDKItemlist (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag)
|
|
{
|
|
CDKITEMLIST *itemlist = (CDKITEMLIST *)object;
|
|
|
|
/*
|
|
* If this is a relative move, then we will adjust where we want
|
|
* to move to.
|
|
*/
|
|
if (relative)
|
|
{
|
|
xplace += getbegx(itemlist->win);
|
|
yplace += getbegy(itemlist->win);
|
|
}
|
|
|
|
/* Adjust the window if we need to. */
|
|
alignxy (WindowOf(itemlist), &xplace, &yplace, itemlist->boxWidth, itemlist->boxHeight);
|
|
|
|
/* Move the window to the new location. */
|
|
moveCursesWindow(itemlist->win, xplace, yplace);
|
|
|
|
/* Redraw the window, if they asked for it. */
|
|
if (refresh_flag)
|
|
{
|
|
drawCDKItemlist (itemlist, ObjOf(itemlist)->box);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This draws the widget on the screen.
|
|
*/
|
|
static void _drawCDKItemlist (CDKOBJS *object, int Box)
|
|
{
|
|
CDKITEMLIST *itemlist = (CDKITEMLIST *)object;
|
|
int x;
|
|
|
|
/* Erase the widget from the screen. */
|
|
/*eraseCDKItemlist (itemlist); */
|
|
|
|
/* Box the widget if asked. */
|
|
if (Box)
|
|
{
|
|
attrbox (itemlist->win,
|
|
itemlist->ULChar, itemlist->URChar,
|
|
itemlist->LLChar, itemlist->LRChar,
|
|
itemlist->HChar, itemlist->VChar,
|
|
itemlist->BoxAttrib,
|
|
itemlist->shadow);
|
|
}
|
|
|
|
if (itemlist->titleLines > 0)
|
|
{
|
|
/* Draw in the title if there is one. */
|
|
for (x=0; x < itemlist->titleLines; x++)
|
|
{
|
|
writeChtype (itemlist->titleWin,
|
|
itemlist->titlePos[x], x,
|
|
itemlist->title[x],
|
|
HORIZONTAL, 0,
|
|
itemlist->titleLen[x]);
|
|
}
|
|
wnoutrefresh (itemlist->titleWin);
|
|
}
|
|
|
|
/* Draw in the label to the widget. */
|
|
if (itemlist->label != 0)
|
|
{
|
|
writeChtype (itemlist->labelWin, 0, 0,
|
|
itemlist->label,
|
|
HORIZONTAL, 0,
|
|
itemlist->labelLen);
|
|
wnoutrefresh (itemlist->labelWin);
|
|
}
|
|
|
|
/* Draw in the field. */
|
|
drawCDKItemlistField (itemlist);
|
|
}
|
|
|
|
/*
|
|
* These functions set the drawing characters of the widget.
|
|
*/
|
|
void setCDKItemlistULChar (CDKITEMLIST *itemlist, chtype character)
|
|
{
|
|
itemlist->ULChar = character;
|
|
}
|
|
void setCDKItemlistURChar (CDKITEMLIST *itemlist, chtype character)
|
|
{
|
|
itemlist->URChar = character;
|
|
}
|
|
void setCDKItemlistLLChar (CDKITEMLIST *itemlist, chtype character)
|
|
{
|
|
itemlist->LLChar = character;
|
|
}
|
|
void setCDKItemlistLRChar (CDKITEMLIST *itemlist, chtype character)
|
|
{
|
|
itemlist->LRChar = character;
|
|
}
|
|
void setCDKItemlistVerticalChar (CDKITEMLIST *itemlist, chtype character)
|
|
{
|
|
itemlist->VChar = character;
|
|
}
|
|
void setCDKItemlistHorizontalChar (CDKITEMLIST *itemlist, chtype character)
|
|
{
|
|
itemlist->HChar = character;
|
|
}
|
|
void setCDKItemlistBoxAttribute (CDKITEMLIST *itemlist, chtype character)
|
|
{
|
|
itemlist->BoxAttrib = character;
|
|
}
|
|
|
|
/*
|
|
* This sets the background color of the widget.
|
|
*/
|
|
void setCDKItemlistBackgroundColor (CDKITEMLIST *itemlist, 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 (itemlist->win, holder[0]);
|
|
wbkgd (itemlist->fieldWin, holder[0]);
|
|
if (itemlist->label != 0)
|
|
{
|
|
wbkgd (itemlist->labelWin, holder[0]);
|
|
}
|
|
|
|
/* Clean up. */
|
|
freeChtype (holder);
|
|
}
|
|
|
|
/*
|
|
* This function draws the contents of the field.
|
|
*/
|
|
void drawCDKItemlistField (CDKITEMLIST *itemlist)
|
|
{
|
|
/* Declare local vars. */
|
|
int currentItem = itemlist->currentItem;
|
|
|
|
/* Erase the field window. */
|
|
werase (itemlist->fieldWin);
|
|
|
|
/* Draw in the current item in the field. */
|
|
writeChtype (itemlist->fieldWin,
|
|
itemlist->itemPos[currentItem], 0,
|
|
itemlist->item[currentItem],
|
|
HORIZONTAL, 0,
|
|
itemlist->itemLen[currentItem]);
|
|
|
|
/* Redraw the field window. */
|
|
wnoutrefresh (itemlist->fieldWin);
|
|
wnoutrefresh (itemlist->win);
|
|
}
|
|
|
|
/*
|
|
* This function removes the widget from the screen.
|
|
*/
|
|
static void _eraseCDKItemlist (CDKOBJS *object)
|
|
{
|
|
CDKITEMLIST *itemlist = (CDKITEMLIST *)object;
|
|
|
|
eraseCursesWindow (itemlist->win);
|
|
}
|
|
|
|
/*
|
|
* This function destroys the widget and all the memory it used.
|
|
*/
|
|
void destroyCDKItemlist (CDKITEMLIST *itemlist)
|
|
{
|
|
/* Declare local variables. */
|
|
int x;
|
|
|
|
/* Erase the object. */
|
|
eraseCDKItemlist (itemlist);
|
|
|
|
/* Clear out the character pointers. */
|
|
freeChtype (itemlist->label);
|
|
for (x=0; x < itemlist->titleLines; x++)
|
|
{
|
|
freeChtype (itemlist->title[x]);
|
|
}
|
|
for (x=0; x <= itemlist->itemCount; x++)
|
|
{
|
|
freeChtype (itemlist->item[x]);
|
|
}
|
|
|
|
/* Delete the windows. */
|
|
deleteCursesWindow (itemlist->win);
|
|
|
|
/* Unregister this object. */
|
|
unregisterCDKObject (vITEMLIST, itemlist);
|
|
|
|
/* Finish cleaning up. */
|
|
free (itemlist);
|
|
}
|
|
|
|
/*
|
|
* This sets multiple attributes of the widget.
|
|
*/
|
|
void setCDKItemlist (CDKITEMLIST *itemlist, char **list, int count, int current, boolean Box)
|
|
{
|
|
setCDKItemlistValues (itemlist, list, count, current);
|
|
setCDKItemlistBox (itemlist, Box);
|
|
}
|
|
|
|
/*
|
|
* This function sets the contents of the list.
|
|
*/
|
|
void setCDKItemlistValues (CDKITEMLIST *itemlist, char **item, int count, int defaultItem)
|
|
{
|
|
/* Declare local variables. */
|
|
int x;
|
|
|
|
/* Free up the old memory. */
|
|
for (x=0; x <= itemlist->itemCount; x++)
|
|
{
|
|
freeChtype (itemlist->item[x]);
|
|
}
|
|
|
|
/* Copy in the new information. */
|
|
itemlist->itemCount = count-1;
|
|
for (x=0; x <= itemlist->itemCount; x++)
|
|
{
|
|
/* Copy the new stuff in. */
|
|
itemlist->item[x] = char2Chtype (item[x], &itemlist->itemLen[x], &itemlist->itemPos[x]);
|
|
itemlist->itemPos[x] = justifyString (itemlist->fieldWidth, itemlist->itemLen[x], itemlist->itemPos[x]);
|
|
}
|
|
|
|
/* Set the default item. */
|
|
if ((defaultItem >= 0) && (defaultItem <= itemlist->itemCount))
|
|
{
|
|
itemlist->currentItem = defaultItem;
|
|
itemlist->defaultItem = defaultItem;
|
|
}
|
|
|
|
/* Draw the field. */
|
|
eraseCDKItemlist (itemlist);
|
|
drawCDKItemlist (itemlist, ObjOf(itemlist)->box);
|
|
}
|
|
chtype **getCDKItemlistValues (CDKITEMLIST *itemlist, int *size)
|
|
{
|
|
(*size) = itemlist->itemCount;
|
|
return itemlist->item;
|
|
}
|
|
|
|
/*
|
|
* This sets the default/current item of the itemlist.
|
|
*/
|
|
void setCDKItemlistCurrentItem (CDKITEMLIST *itemlist, int currentItem)
|
|
{
|
|
/* Set the default item. */
|
|
if ((currentItem >= 0) && (currentItem <= itemlist->itemCount))
|
|
{
|
|
itemlist->currentItem = currentItem;
|
|
}
|
|
}
|
|
int getCDKItemlistCurrentItem (CDKITEMLIST *itemlist)
|
|
{
|
|
return itemlist->currentItem;
|
|
}
|
|
|
|
/*
|
|
* This sets the default item in the list.
|
|
*/
|
|
void setCDKItemlistDefaultItem (CDKITEMLIST *itemlist, int defaultItem)
|
|
{
|
|
/* Make sure the item is in the correct range. */
|
|
if (defaultItem < 0)
|
|
{
|
|
itemlist->defaultItem = 0;
|
|
}
|
|
else if (defaultItem > itemlist->itemCount)
|
|
{
|
|
itemlist->defaultItem = itemlist->itemCount-1;
|
|
}
|
|
else
|
|
{
|
|
itemlist->defaultItem = defaultItem;
|
|
}
|
|
}
|
|
int getCDKItemlistDefaultItem (CDKITEMLIST *itemlist)
|
|
{
|
|
return itemlist->defaultItem;
|
|
}
|
|
|
|
/*
|
|
* This sets the box attribute of the itemlist widget.
|
|
*/
|
|
void setCDKItemlistBox (CDKITEMLIST *itemlist, boolean Box)
|
|
{
|
|
ObjOf(itemlist)->box = Box;
|
|
}
|
|
boolean getCDKItemlistBox (CDKITEMLIST *itemlist)
|
|
{
|
|
return ObjOf(itemlist)->box;
|
|
}
|
|
|
|
/*
|
|
* This function sets the pre-process function.
|
|
*/
|
|
void setCDKItemlistPreProcess (CDKITEMLIST *itemlist, PROCESSFN callback, void *data)
|
|
{
|
|
itemlist->preProcessFunction = callback;
|
|
itemlist->preProcessData = data;
|
|
}
|
|
|
|
/*
|
|
* This function sets the post-process function.
|
|
*/
|
|
void setCDKItemlistPostProcess (CDKITEMLIST *itemlist, PROCESSFN callback, void *data)
|
|
{
|
|
itemlist->postProcessFunction = callback;
|
|
itemlist->postProcessData = data;
|
|
}
|