989 lines
23 KiB
C
989 lines
23 KiB
C
|
#include <cdk_int.h>
|
||
|
|
||
|
/*
|
||
|
* $Author: tom $
|
||
|
* $Date: 2016/11/20 20:55:23 $
|
||
|
* $Revision: 1.169 $
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Declare file local prototypes.
|
||
|
*/
|
||
|
static void CDKMentryCallBack (CDKMENTRY *mentry, chtype character);
|
||
|
|
||
|
DeclareCDKObjects (MENTRY, Mentry, setCdk, String);
|
||
|
|
||
|
/*
|
||
|
* This creates a pointer to a multiple line entry widget.
|
||
|
*/
|
||
|
CDKMENTRY *newCDKMentry (CDKSCREEN *cdkscreen,
|
||
|
int xplace,
|
||
|
int yplace,
|
||
|
const char *title,
|
||
|
const char *label,
|
||
|
chtype fieldAttr,
|
||
|
chtype filler,
|
||
|
EDisplayType dispType,
|
||
|
int fWidth,
|
||
|
int fRows,
|
||
|
int logicalRows,
|
||
|
int min,
|
||
|
boolean Box,
|
||
|
boolean shadow)
|
||
|
{
|
||
|
/* *INDENT-EQLS* */
|
||
|
CDKMENTRY *mentry = 0;
|
||
|
int parentWidth = getmaxx (cdkscreen->window);
|
||
|
int parentHeight = getmaxy (cdkscreen->window);
|
||
|
int fieldWidth = fWidth;
|
||
|
int fieldRows = fRows;
|
||
|
int boxWidth = 0;
|
||
|
int boxHeight = 0;
|
||
|
int horizontalAdjust, oldWidth;
|
||
|
int xpos = xplace;
|
||
|
int ypos = yplace;
|
||
|
int junk;
|
||
|
|
||
|
if ((mentry = newCDKObject (CDKMENTRY, &my_funcs)) == 0)
|
||
|
return (0);
|
||
|
|
||
|
setCDKMentryBox (mentry, Box);
|
||
|
|
||
|
/*
|
||
|
* If the fieldWidth is a negative value, the fieldWidth will
|
||
|
* be COLS-fieldWidth, otherwise, the fieldWidth will be the
|
||
|
* given width.
|
||
|
*/
|
||
|
fieldWidth = setWidgetDimension (parentWidth, fieldWidth, 0);
|
||
|
|
||
|
/*
|
||
|
* If the fieldRows is a negative value, the fieldRows will
|
||
|
* be ROWS-fieldRows, otherwise, the fieldRows will be the
|
||
|
* given height.
|
||
|
*/
|
||
|
fieldRows = setWidgetDimension (parentWidth, fieldRows, 0);
|
||
|
boxHeight = fieldRows + 2;
|
||
|
|
||
|
/* *INDENT-EQLS* Set some basic values of the mentry field. */
|
||
|
mentry->label = 0;
|
||
|
mentry->labelLen = 0;
|
||
|
mentry->labelWin = 0;
|
||
|
|
||
|
/* We need to translate the char * label to a chtype * */
|
||
|
if (label != 0)
|
||
|
{
|
||
|
mentry->label = char2Chtype (label, &mentry->labelLen, &junk);
|
||
|
}
|
||
|
boxWidth = mentry->labelLen + fieldWidth + 2;
|
||
|
|
||
|
oldWidth = boxWidth;
|
||
|
boxWidth = setCdkTitle (ObjOf (mentry), title, boxWidth);
|
||
|
horizontalAdjust = (boxWidth - oldWidth) / 2;
|
||
|
|
||
|
boxHeight += TitleLinesOf (mentry);
|
||
|
|
||
|
/*
|
||
|
* Make sure we didn't extend beyond the parent window.
|
||
|
*/
|
||
|
boxWidth = (boxWidth > parentWidth ? parentWidth : boxWidth);
|
||
|
boxHeight = (boxHeight > parentHeight ? parentHeight : boxHeight);
|
||
|
fieldWidth = (fieldWidth > (boxWidth - mentry->labelLen - 2)
|
||
|
? (boxWidth - mentry->labelLen - 2)
|
||
|
: fieldWidth);
|
||
|
fieldRows = (fieldRows > (boxHeight - TitleLinesOf (mentry) - 2)
|
||
|
? (boxHeight - TitleLinesOf (mentry) - 2)
|
||
|
: fieldRows);
|
||
|
|
||
|
/* Rejustify the x and y positions if we need to. */
|
||
|
alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
|
||
|
|
||
|
/* Make the label window. */
|
||
|
mentry->win = newwin (boxHeight, boxWidth, ypos, xpos);
|
||
|
|
||
|
/* Is the window null??? */
|
||
|
if (mentry->win == 0)
|
||
|
{
|
||
|
destroyCDKObject (mentry);
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
/* Create the label window. */
|
||
|
if (mentry->label != 0)
|
||
|
{
|
||
|
mentry->labelWin = subwin (mentry->win, fieldRows,
|
||
|
mentry->labelLen + 2,
|
||
|
ypos + TitleLinesOf (mentry) + 1,
|
||
|
xpos + horizontalAdjust + 1);
|
||
|
}
|
||
|
|
||
|
/* Make the field window. */
|
||
|
mentry->fieldWin = subwin (mentry->win, fieldRows, fieldWidth,
|
||
|
ypos + TitleLinesOf (mentry) + 1,
|
||
|
xpos + mentry->labelLen + horizontalAdjust + 1);
|
||
|
|
||
|
/* Turn on the keypad. */
|
||
|
keypad (mentry->fieldWin, TRUE);
|
||
|
keypad (mentry->win, TRUE);
|
||
|
|
||
|
/* *INDENT-EQLS* Set up the rest of the structure. */
|
||
|
mentry->parent = cdkscreen->window;
|
||
|
mentry->totalWidth = (fieldWidth * logicalRows) + 1;
|
||
|
|
||
|
/* Create the info char * pointer. */
|
||
|
mentry->info = typeMallocN (char, mentry->totalWidth + 3);
|
||
|
cleanChar (mentry->info, mentry->totalWidth + 3, '\0');
|
||
|
|
||
|
/* *INDENT-EQLS* Set up the rest of the widget information. */
|
||
|
ScreenOf (mentry) = cdkscreen;
|
||
|
mentry->shadowWin = 0;
|
||
|
mentry->fieldAttr = fieldAttr;
|
||
|
mentry->fieldWidth = fieldWidth;
|
||
|
mentry->rows = fieldRows;
|
||
|
mentry->boxHeight = boxHeight;
|
||
|
mentry->boxWidth = boxWidth;
|
||
|
mentry->filler = filler;
|
||
|
mentry->hidden = filler;
|
||
|
ObjOf (mentry)->inputWindow = mentry->win;
|
||
|
ObjOf (mentry)->acceptsFocus = TRUE;
|
||
|
mentry->currentRow = 0;
|
||
|
mentry->currentCol = 0;
|
||
|
mentry->topRow = 0;
|
||
|
mentry->shadow = shadow;
|
||
|
mentry->dispType = dispType;
|
||
|
mentry->min = min;
|
||
|
mentry->logicalRows = logicalRows;
|
||
|
initExitType (mentry);
|
||
|
mentry->callbackfn = CDKMentryCallBack;
|
||
|
|
||
|
/* Do we need to create a shadow. */
|
||
|
if (shadow)
|
||
|
{
|
||
|
mentry->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1);
|
||
|
}
|
||
|
|
||
|
/* Register this baby. */
|
||
|
registerCDKObject (cdkscreen, vMENTRY, mentry);
|
||
|
|
||
|
/* Return the pointer to the structure. */
|
||
|
return (mentry);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This actually manages the mentry widget...
|
||
|
*/
|
||
|
char *activateCDKMentry (CDKMENTRY *mentry, chtype *actions)
|
||
|
{
|
||
|
chtype input = 0;
|
||
|
boolean functionKey;
|
||
|
char *ret = 0;
|
||
|
|
||
|
/* Draw the mentry widget. */
|
||
|
drawCDKMentry (mentry, ObjOf (mentry)->box);
|
||
|
|
||
|
if (actions == 0)
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
input = (chtype)getchCDKObject (ObjOf (mentry), &functionKey);
|
||
|
|
||
|
/* Inject this character into the widget. */
|
||
|
ret = injectCDKMentry (mentry, input);
|
||
|
if (mentry->exitType != vEARLY_EXIT)
|
||
|
{
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int length = chlen (actions);
|
||
|
int x;
|
||
|
|
||
|
/* Inject each character one at a time. */
|
||
|
for (x = 0; x < length; x++)
|
||
|
{
|
||
|
ret = injectCDKMentry (mentry, actions[x]);
|
||
|
if (mentry->exitType != vEARLY_EXIT)
|
||
|
{
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Set the exit type and exit. */
|
||
|
setExitType (mentry, 0);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static bool setTopRow (CDKMENTRY *widget, int row)
|
||
|
{
|
||
|
if (widget->topRow != row)
|
||
|
{
|
||
|
widget->topRow = row;
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool setCurPos (CDKMENTRY *widget, int row, int col)
|
||
|
{
|
||
|
if (widget->currentRow != row ||
|
||
|
widget->currentCol != col)
|
||
|
{
|
||
|
widget->currentRow = row;
|
||
|
widget->currentCol = col;
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static bool handle_KEY_LEFT (CDKMENTRY *mentry, bool *moved, bool *redraw)
|
||
|
{
|
||
|
bool result = TRUE;
|
||
|
|
||
|
if (mentry->currentCol != 0)
|
||
|
{
|
||
|
*moved = setCurPos (mentry,
|
||
|
mentry->currentRow,
|
||
|
mentry->currentCol - 1);
|
||
|
}
|
||
|
else if (mentry->currentRow == 0)
|
||
|
{
|
||
|
if (mentry->topRow != 0)
|
||
|
{
|
||
|
*moved = setCurPos (mentry,
|
||
|
mentry->currentRow,
|
||
|
mentry->fieldWidth - 1);
|
||
|
*redraw = setTopRow (mentry, mentry->topRow - 1);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*moved = setCurPos (mentry,
|
||
|
mentry->currentRow - 1,
|
||
|
mentry->fieldWidth - 1);
|
||
|
}
|
||
|
|
||
|
if (!*moved && !*redraw)
|
||
|
{
|
||
|
Beep ();
|
||
|
result = FALSE;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static int getCursorPos (CDKMENTRY *mentry)
|
||
|
{
|
||
|
return (((mentry->currentRow + mentry->topRow) * mentry->fieldWidth) +
|
||
|
mentry->currentCol);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This injects a character into the widget.
|
||
|
*/
|
||
|
static int _injectCDKMentry (CDKOBJS *object, chtype input)
|
||
|
{
|
||
|
CDKMENTRY *widget = (CDKMENTRY *)object;
|
||
|
/* *INDENT-EQLS */
|
||
|
int cursorPos = getCursorPos (widget);
|
||
|
int ppReturn = 1;
|
||
|
char *ret = unknownString;
|
||
|
bool complete = FALSE;
|
||
|
|
||
|
/* Set the exit type. */
|
||
|
setExitType (widget, 0);
|
||
|
|
||
|
/* Refresh the field. */
|
||
|
drawCDKMentryField (widget);
|
||
|
|
||
|
/* Check if there is a pre-process function to be called. */
|
||
|
if (PreProcessFuncOf (widget) != 0)
|
||
|
{
|
||
|
/* Call the pre-process function. */
|
||
|
ppReturn = PreProcessFuncOf (widget) (vMENTRY,
|
||
|
widget,
|
||
|
PreProcessDataOf (widget),
|
||
|
input);
|
||
|
}
|
||
|
|
||
|
/* Should we continue? */
|
||
|
if (ppReturn != 0)
|
||
|
{
|
||
|
/* Check for a key binding... */
|
||
|
if (checkCDKObjectBind (vMENTRY, widget, input) != 0)
|
||
|
{
|
||
|
checkEarlyExit (widget);
|
||
|
complete = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bool moved = FALSE;
|
||
|
bool redraw = FALSE;
|
||
|
int infoLength = (int)strlen (widget->info);
|
||
|
int fieldCharacters;
|
||
|
|
||
|
switch (input)
|
||
|
{
|
||
|
case KEY_HOME:
|
||
|
moved = setCurPos (widget, 0, 0);
|
||
|
redraw = setTopRow (widget, 0);
|
||
|
break;
|
||
|
|
||
|
case KEY_END:
|
||
|
fieldCharacters = widget->rows * widget->fieldWidth;
|
||
|
if (infoLength < fieldCharacters)
|
||
|
{
|
||
|
redraw = setTopRow (widget, 0);
|
||
|
moved = setCurPos (widget,
|
||
|
infoLength / widget->fieldWidth,
|
||
|
infoLength % widget->fieldWidth);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
redraw = setTopRow (widget,
|
||
|
(infoLength / widget->fieldWidth) -
|
||
|
widget->rows + 1);
|
||
|
moved = setCurPos (widget,
|
||
|
widget->rows - 1,
|
||
|
infoLength % widget->fieldWidth);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case KEY_LEFT:
|
||
|
handle_KEY_LEFT (widget, &moved, &redraw);
|
||
|
break;
|
||
|
|
||
|
case KEY_RIGHT:
|
||
|
if (widget->currentCol < (widget->fieldWidth - 1))
|
||
|
{
|
||
|
if ((getCursorPos (widget) + 1) <= infoLength)
|
||
|
{
|
||
|
moved = setCurPos (widget,
|
||
|
widget->currentRow,
|
||
|
widget->currentCol + 1);
|
||
|
}
|
||
|
}
|
||
|
else if (widget->currentRow == widget->rows - 1)
|
||
|
{
|
||
|
if ((widget->topRow + widget->currentRow + 1) <= widget->logicalRows)
|
||
|
{
|
||
|
moved = setCurPos (widget, widget->currentRow, 0);
|
||
|
redraw = setTopRow (widget, widget->topRow + 1);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
moved = setCurPos (widget, widget->currentRow + 1, 0);
|
||
|
}
|
||
|
if (!moved && !redraw)
|
||
|
Beep ();
|
||
|
break;
|
||
|
|
||
|
case KEY_DOWN:
|
||
|
if (widget->currentRow != (widget->rows - 1))
|
||
|
{
|
||
|
if ((getCursorPos (widget) + widget->fieldWidth + 1)
|
||
|
<= infoLength)
|
||
|
{
|
||
|
moved = setCurPos (widget, widget->currentRow + 1, widget->currentCol);
|
||
|
}
|
||
|
}
|
||
|
else if (widget->topRow < widget->logicalRows - widget->rows)
|
||
|
{
|
||
|
if (((widget->topRow + widget->currentRow + 1) *
|
||
|
widget->fieldWidth) <= infoLength)
|
||
|
{
|
||
|
redraw = setTopRow (widget, widget->topRow + 1);
|
||
|
}
|
||
|
}
|
||
|
if (!moved && !redraw)
|
||
|
Beep ();
|
||
|
break;
|
||
|
|
||
|
case KEY_UP:
|
||
|
if (widget->currentRow != 0)
|
||
|
{
|
||
|
moved = setCurPos (widget, widget->currentRow - 1, widget->currentCol);
|
||
|
}
|
||
|
else if (widget->topRow != 0)
|
||
|
{
|
||
|
redraw = setTopRow (widget, widget->topRow - 1);
|
||
|
}
|
||
|
if (!moved && !redraw)
|
||
|
Beep ();
|
||
|
break;
|
||
|
|
||
|
case KEY_BACKSPACE:
|
||
|
case KEY_DC:
|
||
|
if (widget->dispType == vVIEWONLY)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else if (infoLength == 0)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else if (input == KEY_DC
|
||
|
|| handle_KEY_LEFT (widget, &moved, &redraw))
|
||
|
{
|
||
|
cursorPos = getCursorPos (widget);
|
||
|
if (widget->info[cursorPos] != '\0')
|
||
|
{
|
||
|
int x;
|
||
|
|
||
|
for (x = cursorPos; x < infoLength; x++)
|
||
|
{
|
||
|
widget->info[x] = widget->info[x + 1];
|
||
|
}
|
||
|
widget->info[--infoLength] = '\0';
|
||
|
|
||
|
drawCDKMentryField (widget);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case CDK_TRANSPOSE:
|
||
|
if (cursorPos >= infoLength - 1)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char holder = widget->info[cursorPos];
|
||
|
widget->info[cursorPos] = widget->info[cursorPos + 1];
|
||
|
widget->info[cursorPos + 1] = holder;
|
||
|
drawCDKMentryField (widget);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case CDK_ERASE:
|
||
|
if (infoLength != 0)
|
||
|
{
|
||
|
cleanCDKMentry (widget);
|
||
|
drawCDKMentryField (widget);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case CDK_CUT:
|
||
|
if (infoLength == 0)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
freeChar (GPasteBuffer);
|
||
|
GPasteBuffer = copyChar (widget->info);
|
||
|
cleanCDKMentry (widget);
|
||
|
drawCDKMentryField (widget);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case CDK_COPY:
|
||
|
if (infoLength == 0)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
freeChar (GPasteBuffer);
|
||
|
GPasteBuffer = copyChar (widget->info);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case CDK_PASTE:
|
||
|
if (GPasteBuffer == 0)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
setCDKMentryValue (widget, GPasteBuffer);
|
||
|
drawCDKMentry (widget, ObjOf (widget)->box);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case KEY_TAB:
|
||
|
case KEY_ENTER:
|
||
|
if (infoLength < widget->min + 1)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
setExitType (widget, input);
|
||
|
ret = (widget->info);
|
||
|
complete = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case KEY_ERROR:
|
||
|
setExitType (widget, input);
|
||
|
complete = TRUE;
|
||
|
break;
|
||
|
|
||
|
case KEY_ESC:
|
||
|
setExitType (widget, input);
|
||
|
complete = TRUE;
|
||
|
break;
|
||
|
|
||
|
case CDK_REFRESH:
|
||
|
eraseCDKScreen (ScreenOf (widget));
|
||
|
refreshCDKScreen (ScreenOf (widget));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (widget->dispType == vVIEWONLY
|
||
|
|| infoLength >= widget->totalWidth)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
(widget->callbackfn) (widget, input);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (redraw)
|
||
|
{
|
||
|
drawCDKMentryField (widget);
|
||
|
}
|
||
|
else if (moved)
|
||
|
{
|
||
|
wmove (widget->fieldWin, widget->currentRow, widget->currentCol);
|
||
|
wrefresh (widget->fieldWin);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Should we do a post-process? */
|
||
|
if (!complete && (PostProcessFuncOf (widget) != 0))
|
||
|
{
|
||
|
PostProcessFuncOf (widget) (vMENTRY,
|
||
|
widget,
|
||
|
PostProcessDataOf (widget),
|
||
|
input);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!complete)
|
||
|
{
|
||
|
setExitType (widget, 0);
|
||
|
}
|
||
|
|
||
|
ResultOf (widget).valueString = ret;
|
||
|
return (ret != unknownString);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This moves the mentry field to the given location.
|
||
|
*/
|
||
|
static void _moveCDKMentry (CDKOBJS *object,
|
||
|
int xplace,
|
||
|
int yplace,
|
||
|
boolean relative,
|
||
|
boolean refresh_flag)
|
||
|
{
|
||
|
CDKMENTRY *mentry = (CDKMENTRY *)object;
|
||
|
/* *INDENT-EQLS* */
|
||
|
int currentX = getbegx (mentry->win);
|
||
|
int currentY = getbegy (mentry->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 (mentry->win) + xplace;
|
||
|
ypos = getbegy (mentry->win) + yplace;
|
||
|
}
|
||
|
|
||
|
/* Adjust the window if we need to. */
|
||
|
alignxy (WindowOf (mentry), &xpos, &ypos, mentry->boxWidth, mentry->boxHeight);
|
||
|
|
||
|
/* Get the difference. */
|
||
|
xdiff = currentX - xpos;
|
||
|
ydiff = currentY - ypos;
|
||
|
|
||
|
/* Move the window to the new location. */
|
||
|
moveCursesWindow (mentry->win, -xdiff, -ydiff);
|
||
|
moveCursesWindow (mentry->fieldWin, -xdiff, -ydiff);
|
||
|
moveCursesWindow (mentry->labelWin, -xdiff, -ydiff);
|
||
|
moveCursesWindow (mentry->shadowWin, -xdiff, -ydiff);
|
||
|
|
||
|
/* Touch the windows so they 'move'. */
|
||
|
refreshCDKWindow (WindowOf (mentry));
|
||
|
|
||
|
/* Redraw the window, if they asked for it. */
|
||
|
if (refresh_flag)
|
||
|
{
|
||
|
drawCDKMentry (mentry, ObjOf (mentry)->box);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This function redraws the multiple line entry field.
|
||
|
*/
|
||
|
void drawCDKMentryField (CDKMENTRY *mentry)
|
||
|
{
|
||
|
/* *INDENT-EQLS* */
|
||
|
int currchar = (mentry->fieldWidth * mentry->topRow);
|
||
|
int length = 0;
|
||
|
int lastpos = 0;
|
||
|
int x, y;
|
||
|
|
||
|
/* Check the value of info. */
|
||
|
if (mentry->info == 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
drawCdkTitle (mentry->win, ObjOf (mentry));
|
||
|
|
||
|
wrefresh (mentry->win);
|
||
|
|
||
|
/* The information isn't null, redraw the field. */
|
||
|
length = (int)strlen (mentry->info);
|
||
|
lastpos = ((chtype)mentry->info[length] == (chtype)mentry->filler
|
||
|
? length - 1
|
||
|
: length);
|
||
|
|
||
|
/* Set background color and attributes of the entry field */
|
||
|
wbkgd (mentry->fieldWin, mentry->fieldAttr);
|
||
|
|
||
|
/* Start redrawing the fields. */
|
||
|
for (x = 0; x < mentry->rows; x++)
|
||
|
{
|
||
|
for (y = 0; y < mentry->fieldWidth; y++)
|
||
|
{
|
||
|
if (currchar < lastpos)
|
||
|
{
|
||
|
if (isHiddenDisplayType (mentry->dispType))
|
||
|
{
|
||
|
(void)mvwaddch (mentry->fieldWin, x, y, mentry->hidden | mentry->fieldAttr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
(void)mvwaddch (mentry->fieldWin, x, y,
|
||
|
CharOf (mentry->info[currchar++]) | mentry->fieldAttr);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
(void)mvwhline (mentry->fieldWin, x, y, mentry->filler |
|
||
|
mentry->fieldAttr, mentry->fieldWidth - y);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Refresh the screen. */
|
||
|
wmove (mentry->fieldWin, mentry->currentRow, mentry->currentCol);
|
||
|
wrefresh (mentry->fieldWin);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This is a generic character parser for the mentry field. It is used as a
|
||
|
* callback function, so any personal modifications can be made by creating
|
||
|
* a new function and calling that one the mentry activation.
|
||
|
*/
|
||
|
static void CDKMentryCallBack (CDKMENTRY *mentry, chtype character)
|
||
|
{
|
||
|
/* *INDENT-EQLS* */
|
||
|
int cursorPos = getCursorPos (mentry);
|
||
|
int infoLength = (int)strlen (mentry->info);
|
||
|
char newchar = (char)filterByDisplayType (mentry->dispType, character);
|
||
|
|
||
|
if (newchar == ERR)
|
||
|
{
|
||
|
Beep ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int x;
|
||
|
|
||
|
for (x = infoLength + 1; x > cursorPos; x--)
|
||
|
{
|
||
|
mentry->info[x] = mentry->info[x - 1];
|
||
|
}
|
||
|
mentry->info[cursorPos] = newchar;
|
||
|
mentry->currentCol++;
|
||
|
|
||
|
drawCDKMentryField (mentry);
|
||
|
|
||
|
/* Have we gone out of bounds. */
|
||
|
if (mentry->currentCol >= mentry->fieldWidth)
|
||
|
{
|
||
|
/* Update the row and col values. */
|
||
|
mentry->currentCol = 0;
|
||
|
mentry->currentRow++;
|
||
|
|
||
|
/*
|
||
|
* If we have gone outside of the visual boundaries, we
|
||
|
* need to scroll the window.
|
||
|
*/
|
||
|
if (mentry->currentRow == mentry->rows)
|
||
|
{
|
||
|
/* We have to redraw the screen. */
|
||
|
mentry->currentRow--;
|
||
|
mentry->topRow++;
|
||
|
drawCDKMentryField (mentry);
|
||
|
}
|
||
|
wmove (mentry->fieldWin, mentry->currentRow, mentry->currentCol);
|
||
|
wrefresh (mentry->fieldWin);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This function draws the multiple line entry field.
|
||
|
*/
|
||
|
static void _drawCDKMentry (CDKOBJS *object, boolean Box)
|
||
|
{
|
||
|
CDKMENTRY *mentry = (CDKMENTRY *)object;
|
||
|
|
||
|
/* Box the widget if asked. */
|
||
|
if (Box)
|
||
|
{
|
||
|
drawObjBox (mentry->win, ObjOf (mentry));
|
||
|
wrefresh (mentry->win);
|
||
|
}
|
||
|
|
||
|
/* Do we need to draw in the shadow??? */
|
||
|
if (mentry->shadowWin != 0)
|
||
|
{
|
||
|
drawShadow (mentry->shadowWin);
|
||
|
}
|
||
|
|
||
|
/* Draw in the label to the widget. */
|
||
|
if (mentry->labelWin != 0)
|
||
|
{
|
||
|
writeChtype (mentry->labelWin, 0, 0,
|
||
|
mentry->label,
|
||
|
HORIZONTAL, 0,
|
||
|
mentry->labelLen);
|
||
|
wrefresh (mentry->labelWin);
|
||
|
}
|
||
|
|
||
|
/* Draw the mentry field. */
|
||
|
drawCDKMentryField (mentry);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This sets the background attribute of the widget.
|
||
|
*/
|
||
|
static void _setBKattrMentry (CDKOBJS *object, chtype attrib)
|
||
|
{
|
||
|
if (object != 0)
|
||
|
{
|
||
|
CDKMENTRY *widget = (CDKMENTRY *)object;
|
||
|
|
||
|
wbkgd (widget->win, attrib);
|
||
|
wbkgd (widget->fieldWin, attrib);
|
||
|
if (widget->labelWin != 0)
|
||
|
{
|
||
|
wbkgd (widget->labelWin, attrib);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This function erases the multiple line entry field from the screen.
|
||
|
*/
|
||
|
static void _eraseCDKMentry (CDKOBJS *object)
|
||
|
{
|
||
|
if (validCDKObject (object))
|
||
|
{
|
||
|
CDKMENTRY *mentry = (CDKMENTRY *)object;
|
||
|
|
||
|
eraseCursesWindow (mentry->fieldWin);
|
||
|
eraseCursesWindow (mentry->labelWin);
|
||
|
eraseCursesWindow (mentry->win);
|
||
|
eraseCursesWindow (mentry->shadowWin);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This function destroys a multiple line entry field widget.
|
||
|
*/
|
||
|
static void _destroyCDKMentry (CDKOBJS *object)
|
||
|
{
|
||
|
if (object != 0)
|
||
|
{
|
||
|
CDKMENTRY *mentry = (CDKMENTRY *)object;
|
||
|
|
||
|
cleanCdkTitle (object);
|
||
|
freeChtype (mentry->label);
|
||
|
freeChar (mentry->info);
|
||
|
|
||
|
/* Clean up the windows. */
|
||
|
deleteCursesWindow (mentry->fieldWin);
|
||
|
deleteCursesWindow (mentry->labelWin);
|
||
|
deleteCursesWindow (mentry->shadowWin);
|
||
|
deleteCursesWindow (mentry->win);
|
||
|
|
||
|
/* Clean the key bindings. */
|
||
|
cleanCDKObjectBindings (vMENTRY, mentry);
|
||
|
|
||
|
/* Unregister this object. */
|
||
|
unregisterCDKObject (vMENTRY, mentry);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This sets multiple attributes of the widget.
|
||
|
*/
|
||
|
void setCDKMentry (CDKMENTRY *mentry, const char *value, int min, boolean Box)
|
||
|
{
|
||
|
setCDKMentryValue (mentry, value);
|
||
|
setCDKMentryMin (mentry, min);
|
||
|
setCDKMentryBox (mentry, Box);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This removes the old information in the entry field and keeps the
|
||
|
* new information given.
|
||
|
*/
|
||
|
void setCDKMentryValue (CDKMENTRY *mentry, const char *newValue)
|
||
|
{
|
||
|
/* *INDENT-EQLS* */
|
||
|
int fieldCharacters = mentry->rows * mentry->fieldWidth;
|
||
|
int len = 0;
|
||
|
int copychars = 0;
|
||
|
|
||
|
/* Just to be sure, if lets make sure the new value isn't null. */
|
||
|
if (newValue == 0)
|
||
|
{
|
||
|
/* Then we want to just erase the old value. */
|
||
|
cleanChar (mentry->info, mentry->totalWidth, '\0');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Determine how many characters we need to copy. */
|
||
|
len = (int)strlen (newValue);
|
||
|
copychars = (len < mentry->totalWidth ? len : mentry->totalWidth);
|
||
|
|
||
|
/* OK, erase the old value, and copy in the new value. */
|
||
|
cleanChar (mentry->info, mentry->totalWidth, '\0');
|
||
|
strncpy (mentry->info, newValue, (size_t) copychars);
|
||
|
|
||
|
/* Set the cursor/row info. */
|
||
|
if (len < fieldCharacters)
|
||
|
{
|
||
|
mentry->topRow = 0;
|
||
|
mentry->currentRow = len / mentry->fieldWidth;
|
||
|
mentry->currentCol = len % mentry->fieldWidth;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* *INDENT-EQLS* */
|
||
|
int rowsUsed = len / mentry->fieldWidth;
|
||
|
mentry->topRow = rowsUsed - mentry->rows + 1;
|
||
|
mentry->currentRow = mentry->rows - 1;
|
||
|
mentry->currentCol = len % mentry->fieldWidth;
|
||
|
}
|
||
|
|
||
|
/* Redraw the widget. */
|
||
|
drawCDKMentryField (mentry);
|
||
|
}
|
||
|
char *getCDKMentryValue (CDKMENTRY *mentry)
|
||
|
{
|
||
|
return mentry->info;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This sets the filler character to use when drawing the widget.
|
||
|
*/
|
||
|
void setCDKMentryFillerChar (CDKMENTRY *mentry, chtype filler)
|
||
|
{
|
||
|
mentry->filler = filler;
|
||
|
}
|
||
|
chtype getCDKMentryFillerChar (CDKMENTRY *mentry)
|
||
|
{
|
||
|
return mentry->filler;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This sets the character to use when a hidden character type is used.
|
||
|
*/
|
||
|
void setCDKMentryHiddenChar (CDKMENTRY *mentry, chtype character)
|
||
|
{
|
||
|
mentry->hidden = character;
|
||
|
}
|
||
|
chtype getCDKMentryHiddenChar (CDKMENTRY *mentry)
|
||
|
{
|
||
|
return mentry->hidden;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This sets the minimum length of the widget.
|
||
|
*/
|
||
|
void setCDKMentryMin (CDKMENTRY *mentry, int min)
|
||
|
{
|
||
|
mentry->min = min;
|
||
|
}
|
||
|
int getCDKMentryMin (CDKMENTRY *mentry)
|
||
|
{
|
||
|
return mentry->min;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This sets the widgets box attribute.
|
||
|
*/
|
||
|
void setCDKMentryBox (CDKMENTRY *mentry, boolean Box)
|
||
|
{
|
||
|
ObjOf (mentry)->box = Box;
|
||
|
ObjOf (mentry)->borderSize = Box ? 1 : 0;
|
||
|
}
|
||
|
boolean getCDKMentryBox (CDKMENTRY *mentry)
|
||
|
{
|
||
|
return ObjOf (mentry)->box;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This erases the information in the multiple line entry widget.
|
||
|
*/
|
||
|
void cleanCDKMentry (CDKMENTRY *mentry)
|
||
|
{
|
||
|
cleanChar (mentry->info, mentry->totalWidth, '\0');
|
||
|
/* *INDENT-EQLS* */
|
||
|
mentry->currentRow = 0;
|
||
|
mentry->currentCol = 0;
|
||
|
mentry->topRow = 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This sets the callback function.
|
||
|
*/
|
||
|
void setCDKMentryCB (CDKMENTRY *mentry, MENTRYCB callback)
|
||
|
{
|
||
|
mentry->callbackfn = callback;
|
||
|
}
|
||
|
|
||
|
static void _focusCDKMentry (CDKOBJS *object)
|
||
|
{
|
||
|
CDKMENTRY *mentry = (CDKMENTRY *)object;
|
||
|
|
||
|
wmove (mentry->fieldWin, 0, mentry->currentCol);
|
||
|
wrefresh (mentry->fieldWin);
|
||
|
}
|
||
|
|
||
|
static void _unfocusCDKMentry (CDKOBJS *object)
|
||
|
{
|
||
|
CDKMENTRY *mentry = (CDKMENTRY *)object;
|
||
|
|
||
|
wrefresh (mentry->fieldWin);
|
||
|
}
|
||
|
|
||
|
dummyRefreshData (Mentry)
|
||
|
|
||
|
dummySaveData (Mentry)
|