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

376 lines
6.8 KiB
C

#include <cdk_int.h>
/*
* $Author: tom $
* $Date: 2016/11/20 18:28:30 $
* $Revision: 1.24 $
*/
#define limitFocusIndex(screen, value) \
(((value) >= (screen)->objectCount || (value) < 0) \
? 0 \
: (value))
static int getFocusIndex (CDKSCREEN *screen)
{
int result = limitFocusIndex (screen, screen->objectFocus);
return result;
}
static void setFocusIndex (CDKSCREEN *screen, int value)
{
screen->objectFocus = limitFocusIndex (screen, value);
}
static void unsetFocus (CDKOBJS *obj)
{
curs_set (0);
if (obj != 0)
{
HasFocusObj (obj) = FALSE;
UnfocusObj (obj);
}
}
static void setFocus (CDKOBJS *obj)
{
if (obj != 0)
{
HasFocusObj (obj) = TRUE;
FocusObj (obj);
}
curs_set (1);
}
static CDKOBJS *switchFocus (CDKOBJS *newobj, CDKOBJS *oldobj)
{
if (oldobj != newobj)
{
unsetFocus (oldobj);
setFocus (newobj);
}
return newobj;
}
static boolean checkMenuKey (int keyCode, int functionKey)
{
int result;
result = (keyCode == KEY_ESC && !functionKey);
return result;
}
static CDKOBJS *handleMenu (CDKSCREEN *screen, CDKOBJS *menu, CDKOBJS *oldobj)
{
bool done = FALSE;
CDKOBJS *newobj;
switchFocus (menu, oldobj);
while (!done)
{
boolean functionKey;
int key = getchCDKObject (menu, &functionKey);
switch (key)
{
case KEY_TAB:
done = TRUE;
break;
case KEY_ESC:
/* cleanup the menu */
(void)injectCDKMenu ((CDKMENU *)menu, (chtype)key);
done = TRUE;
break;
default:
done = (injectCDKMenu ((CDKMENU *)menu, (chtype)key) >= 0);
break;
}
}
if ((newobj = getCDKFocusCurrent (screen)) == 0)
newobj = setCDKFocusNext (screen);
return switchFocus (newobj, menu);
}
/*
* Save data in widgets on a screen
*/
static void saveDataCDKScreen (CDKSCREEN *screen)
{
int i;
for (i = 0; i < screen->objectCount; ++i)
SaveDataObj (screen->object[i]);
}
/*
* Refresh data in widgets on a screen
*/
static void refreshDataCDKScreen (CDKSCREEN *screen)
{
int i;
for (i = 0; i < screen->objectCount; ++i)
RefreshDataObj (screen->object[i]);
}
/*
* ======================================================================
* Public Interface
*/
void resetCDKScreen (CDKSCREEN *screen)
{
refreshDataCDKScreen (screen);
}
void exitOKCDKScreen (CDKSCREEN *screen)
{
screen->exitStatus = CDKSCREEN_EXITOK;
}
void exitCancelCDKScreen (CDKSCREEN *screen)
{
screen->exitStatus = CDKSCREEN_EXITCANCEL;
}
void exitOKCDKScreenOf (CDKOBJS *obj)
{
exitOKCDKScreen (obj->screen);
}
void exitCancelCDKScreenOf (CDKOBJS *obj)
{
exitCancelCDKScreen (obj->screen);
}
void resetCDKScreenOf (CDKOBJS *obj)
{
resetCDKScreen (obj->screen);
}
/*
* Returns the object on which the focus lies.
*/
CDKOBJS *getCDKFocusCurrent (CDKSCREEN *screen)
{
CDKOBJS *result = 0;
int n = screen->objectFocus;
if (n >= 0 && n < screen->objectCount)
result = screen->object[n];
return result;
}
/*
* Set focus to the next object, returning it.
*/
CDKOBJS *setCDKFocusNext (CDKSCREEN *screen)
{
CDKOBJS *result = 0;
CDKOBJS *curobj;
int n = getFocusIndex (screen);
int first = n;
for (;;)
{
if (++n >= screen->objectCount)
n = 0;
curobj = screen->object[n];
if (curobj != 0 && AcceptsFocusObj (curobj))
{
result = curobj;
break;
}
else
{
if (n == first)
{
break;
}
}
}
setFocusIndex (screen, (result != 0) ? n : -1);
return result;
}
/*
* Set focus to the previous object, returning it.
*/
CDKOBJS *setCDKFocusPrevious (CDKSCREEN *screen)
{
CDKOBJS *result = 0;
CDKOBJS *curobj;
int n = getFocusIndex (screen);
int first = n;
for (;;)
{
if (--n < 0)
n = screen->objectCount - 1;
curobj = screen->object[n];
if (curobj != 0 && AcceptsFocusObj (curobj))
{
result = curobj;
break;
}
else if (n == first)
{
break;
}
}
setFocusIndex (screen, (result != 0) ? n : -1);
return result;
}
/*
* Set focus to a specific object, returning it.
* If the object cannot be found, return null.
*/
CDKOBJS *setCDKFocusCurrent (CDKSCREEN *screen, CDKOBJS *newobj)
{
CDKOBJS *result = 0;
CDKOBJS *curobj;
int n = getFocusIndex (screen);
int first = n;
for (;;)
{
if (++n >= screen->objectCount)
n = 0;
curobj = screen->object[n];
if (curobj == newobj)
{
result = curobj;
break;
}
else if (n == first)
{
break;
}
}
setFocusIndex (screen, (result != 0) ? n : -1);
return result;
}
/*
* Set focus to the first object in the screen.
*/
CDKOBJS *setCDKFocusFirst (CDKSCREEN *screen)
{
setFocusIndex (screen, screen->objectCount - 1);
return switchFocus (setCDKFocusNext (screen), 0);
}
/*
* Set focus to the last object in the screen.
*/
CDKOBJS *setCDKFocusLast (CDKSCREEN *screen)
{
setFocusIndex (screen, 0);
return switchFocus (setCDKFocusPrevious (screen), 0);
}
void traverseCDKOnce (CDKSCREEN *screen,
CDKOBJS *curobj,
int keyCode,
boolean functionKey,
CHECK_KEYCODE funcMenuKey)
{
switch (keyCode)
{
case KEY_BTAB:
switchFocus (setCDKFocusPrevious (screen), curobj);
break;
case KEY_TAB:
switchFocus (setCDKFocusNext (screen), curobj);
break;
case KEY_F (10):
/* save data and exit */
exitOKCDKScreen (screen);
break;
case CTRL ('X'):
exitCancelCDKScreen (screen);
break;
case CTRL ('R'):
/* reset data to defaults */
resetCDKScreen (screen);
setFocus (curobj);
break;
case CDK_REFRESH:
/* redraw screen */
refreshCDKScreen (screen);
setFocus (curobj);
break;
default:
/* not everyone wants menus, so we make them optional here */
if (funcMenuKey != 0 && funcMenuKey (keyCode, functionKey))
{
/* find and enable drop down menu */
int j;
for (j = 0; j < screen->objectCount; ++j)
if (ObjTypeOf (screen->object[j]) == vMENU)
{
handleMenu (screen, screen->object[j], curobj);
break;
}
}
else
{
InjectObj (curobj, (chtype)keyCode);
}
break;
}
}
/*
* Traverse the widgets on a screen.
*/
int traverseCDKScreen (CDKSCREEN *screen)
{
int result = 0;
CDKOBJS *curobj = setCDKFocusFirst (screen);
if (curobj != 0)
{
refreshDataCDKScreen (screen);
screen->exitStatus = CDKSCREEN_NOEXIT;
while (((curobj = getCDKFocusCurrent (screen)) != 0)
&& (screen->exitStatus == CDKSCREEN_NOEXIT))
{
int key;
boolean function;
key = getchCDKObject (curobj, &function);
traverseCDKOnce (screen, curobj, key, function, checkMenuKey);
}
if (screen->exitStatus == CDKSCREEN_EXITOK)
{
saveDataCDKScreen (screen);
result = 1;
}
}
return result;
}