1660 lines
44 KiB
C
1660 lines
44 KiB
C
/*
|
|
This file is part of Warzone 2100.
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
Copyright (C) 2005-2007 Warzone Resurrection Project
|
|
|
|
Warzone 2100 is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Warzone 2100 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Warzone 2100; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
* Form.c
|
|
*
|
|
* Functionality for the form widget.
|
|
*/
|
|
#include <string.h>
|
|
|
|
#include "lib/framework/frame.h"
|
|
#include "widget.h"
|
|
#include "widgint.h"
|
|
#include "form.h"
|
|
#include "tip.h"
|
|
// FIXME Direct iVis implementation include!
|
|
#include "lib/ivis_common/rendmode.h"
|
|
#include "lib/ivis_common/piepalette.h"
|
|
|
|
/* Control whether single tabs are displayed */
|
|
#define NO_DISPLAY_SINGLE_TABS 1
|
|
|
|
static inline void formFreeTips(W_TABFORM *psForm);
|
|
|
|
/* Store the position of a tab */
|
|
typedef struct _tab_pos
|
|
{
|
|
SDWORD index;
|
|
SDWORD x,y;
|
|
UDWORD width,height;
|
|
SDWORD TabMultiplier; //Added to keep track of tab scroll
|
|
} TAB_POS;
|
|
|
|
/* Set default colours for a form */
|
|
static void formSetDefaultColours(W_FORM *psForm)
|
|
{
|
|
static BOOL bDefaultsSet = FALSE;
|
|
static PIELIGHT wcol_bkgrnd;
|
|
static PIELIGHT wcol_text;
|
|
static PIELIGHT wcol_light;
|
|
static PIELIGHT wcol_dark;
|
|
static PIELIGHT wcol_hilite;
|
|
static PIELIGHT wcol_cursor;
|
|
static PIELIGHT wcol_tipbkgrnd;
|
|
static PIELIGHT wcol_disable;
|
|
|
|
if (bDefaultsSet)
|
|
{
|
|
psForm->aColours[WCOL_BKGRND] = wcol_bkgrnd;
|
|
psForm->aColours[WCOL_TEXT] = wcol_text;
|
|
psForm->aColours[WCOL_LIGHT] = wcol_light;
|
|
psForm->aColours[WCOL_DARK] = wcol_dark;
|
|
psForm->aColours[WCOL_HILITE] = wcol_hilite;
|
|
psForm->aColours[WCOL_CURSOR] = wcol_cursor;
|
|
psForm->aColours[WCOL_TIPBKGRND] = wcol_tipbkgrnd;
|
|
psForm->aColours[WCOL_DISABLE] = wcol_disable;
|
|
}
|
|
else
|
|
{
|
|
wcol_bkgrnd = pal_Colour(0x7f, 0x7f, 0x7f);
|
|
wcol_text = WZCOL_WHITE;
|
|
wcol_light = WZCOL_WHITE;
|
|
wcol_dark = WZCOL_BLACK;
|
|
wcol_hilite = pal_Colour(0x40, 0x40, 0x40);
|
|
wcol_cursor = pal_Colour(0xff, 0x00, 0x00);
|
|
wcol_tipbkgrnd = pal_Colour(0x30, 0x30, 0x60);
|
|
wcol_disable = pal_Colour(0xbf, 0xbf, 0xbf);
|
|
|
|
bDefaultsSet = TRUE;
|
|
|
|
psForm->aColours[WCOL_BKGRND] = wcol_bkgrnd;
|
|
psForm->aColours[WCOL_TEXT] = wcol_text;
|
|
psForm->aColours[WCOL_LIGHT] = wcol_light;
|
|
psForm->aColours[WCOL_DARK] = wcol_dark;
|
|
psForm->aColours[WCOL_HILITE] = wcol_hilite;
|
|
psForm->aColours[WCOL_CURSOR] = wcol_cursor;
|
|
psForm->aColours[WCOL_TIPBKGRND] = wcol_tipbkgrnd;
|
|
psForm->aColours[WCOL_DISABLE] = wcol_disable;
|
|
}
|
|
}
|
|
|
|
/* Create a plain form widget */
|
|
static BOOL formCreatePlain(W_FORM **ppsWidget, W_FORMINIT *psInit)
|
|
{
|
|
/* Allocate the required memory */
|
|
*ppsWidget = (W_FORM *)malloc(sizeof(W_FORM));
|
|
if (*ppsWidget == NULL)
|
|
{
|
|
ASSERT( FALSE, "formCreatePlain: Out of memory" );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialise the structure */
|
|
memset(*ppsWidget, 0, sizeof(W_FORM));
|
|
(*ppsWidget)->type = WIDG_FORM;
|
|
(*ppsWidget)->id = psInit->id;
|
|
(*ppsWidget)->formID = psInit->formID;
|
|
(*ppsWidget)->style = psInit->style;
|
|
(*ppsWidget)->disableChildren = psInit->disableChildren;
|
|
(*ppsWidget)->animCount = 0;
|
|
(*ppsWidget)->x = psInit->x;
|
|
(*ppsWidget)->y = psInit->y;
|
|
(*ppsWidget)->width = psInit->width;
|
|
(*ppsWidget)->height = psInit->height;
|
|
|
|
if (psInit->pDisplay)
|
|
{
|
|
(*ppsWidget)->display = psInit->pDisplay;
|
|
}
|
|
else
|
|
{
|
|
(*ppsWidget)->display = formDisplay;
|
|
}
|
|
(*ppsWidget)->callback = psInit->pCallback;
|
|
(*ppsWidget)->pUserData = psInit->pUserData;
|
|
(*ppsWidget)->UserData = psInit->UserData;
|
|
(*ppsWidget)->psWidgets = NULL;
|
|
(*ppsWidget)->psLastHiLite = NULL;
|
|
formSetDefaultColours(*ppsWidget);
|
|
|
|
formInitialise(*ppsWidget);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Free a plain form widget */
|
|
static void formFreePlain(W_FORM *psWidget)
|
|
{
|
|
ASSERT( psWidget != NULL,
|
|
"formFreePlain: Invalid form pointer" );
|
|
|
|
widgReleaseWidgetList(psWidget->psWidgets);
|
|
free(psWidget);
|
|
}
|
|
|
|
|
|
/* Create a plain form widget */
|
|
static BOOL formCreateClickable(W_CLICKFORM **ppsWidget, W_FORMINIT *psInit)
|
|
{
|
|
/* Allocate the required memory */
|
|
*ppsWidget = (W_CLICKFORM *)malloc(sizeof(W_CLICKFORM));
|
|
if (*ppsWidget == NULL)
|
|
{
|
|
ASSERT( FALSE, "formCreateClickable: Out of memory" );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialise the structure */
|
|
memset(*ppsWidget, 0, sizeof(W_CLICKFORM));
|
|
(*ppsWidget)->type = WIDG_FORM;
|
|
(*ppsWidget)->id = psInit->id;
|
|
(*ppsWidget)->formID = psInit->formID;
|
|
(*ppsWidget)->style = psInit->style;
|
|
(*ppsWidget)->disableChildren = psInit->disableChildren;
|
|
(*ppsWidget)->animCount = 0;
|
|
(*ppsWidget)->x = psInit->x;
|
|
(*ppsWidget)->y = psInit->y;
|
|
(*ppsWidget)->width = psInit->width;
|
|
(*ppsWidget)->height = psInit->height;
|
|
(*ppsWidget)->callback = psInit->pCallback;
|
|
(*ppsWidget)->pUserData = psInit->pUserData;
|
|
(*ppsWidget)->UserData = psInit->UserData;
|
|
|
|
(*ppsWidget)->AudioCallback = WidgGetAudioCallback();
|
|
(*ppsWidget)->HilightAudioID = WidgGetHilightAudioID();
|
|
(*ppsWidget)->ClickedAudioID = WidgGetClickedAudioID();
|
|
|
|
if (psInit->pDisplay)
|
|
{
|
|
(*ppsWidget)->display = psInit->pDisplay;
|
|
}
|
|
else
|
|
{
|
|
(*ppsWidget)->display = formDisplayClickable;
|
|
}
|
|
(*ppsWidget)->psWidgets = NULL;
|
|
(*ppsWidget)->psLastHiLite = NULL;
|
|
(*ppsWidget)->pTip = psInit->pTip;
|
|
formSetDefaultColours((W_FORM *)*ppsWidget);
|
|
|
|
formInitialise((W_FORM *)*ppsWidget);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Free a plain form widget */
|
|
static void formFreeClickable(W_CLICKFORM *psWidget)
|
|
{
|
|
ASSERT( psWidget != NULL,
|
|
"formFreePlain: Invalid form pointer" );
|
|
|
|
widgReleaseWidgetList(psWidget->psWidgets);
|
|
|
|
free(psWidget);
|
|
}
|
|
|
|
|
|
/* Create a tabbed form widget */
|
|
static BOOL formCreateTabbed(W_TABFORM **ppsWidget, W_FORMINIT *psInit)
|
|
{
|
|
UDWORD major,minor;
|
|
W_MAJORTAB *psMajor;
|
|
|
|
if (psInit->numMajor == 0)
|
|
{
|
|
ASSERT( FALSE, "formCreateTabbed: Must have at least one major tab on a tabbed form" );
|
|
return FALSE;
|
|
}
|
|
if (psInit->majorPos != 0 && psInit->majorPos == psInit->minorPos)
|
|
{
|
|
ASSERT( FALSE, "formCreateTabbed: Cannot have major and minor tabs on same side" );
|
|
return FALSE;
|
|
}
|
|
if (psInit->numMajor >= WFORM_MAXMAJOR)
|
|
{
|
|
ASSERT( FALSE, "formCreateTabbed: Too many Major tabs" );
|
|
return FALSE;
|
|
}
|
|
for(major=0; major<psInit->numMajor; major++)
|
|
{
|
|
if (psInit->aNumMinors[major] >= WFORM_MAXMINOR)
|
|
{
|
|
ASSERT( FALSE, "formCreateTabbed: Too many Minor tabs for Major %d", major );
|
|
return FALSE;
|
|
}
|
|
if (psInit->aNumMinors[major] == 0)
|
|
{
|
|
ASSERT( FALSE, "formCreateTabbed: Must have at least one Minor tab for each major" );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Allocate the required memory */
|
|
*ppsWidget = (W_TABFORM *)malloc(sizeof(W_TABFORM));
|
|
if (*ppsWidget == NULL)
|
|
{
|
|
ASSERT( FALSE, "formCreateTabbed: Out of memory" );
|
|
return FALSE;
|
|
}
|
|
memset(*ppsWidget, 0, sizeof(W_TABFORM));
|
|
|
|
/* Allocate the memory for tool tips and copy them in */
|
|
psMajor = (*ppsWidget)->asMajor;
|
|
for(major=0; major<psInit->numMajor; major++)
|
|
{
|
|
/* Check for a tip for the major tab */
|
|
psMajor->pTip = psInit->apMajorTips[major];
|
|
|
|
/* Check for tips for the minor tab */
|
|
for(minor=0; minor<psInit->aNumMinors[major]; minor++)
|
|
{
|
|
psMajor->asMinor[minor].pTip = psInit->apMinorTips[major][minor];
|
|
}
|
|
psMajor++;
|
|
}
|
|
|
|
/* Initialise the structure */
|
|
(*ppsWidget)->type = WIDG_FORM;
|
|
(*ppsWidget)->id = psInit->id;
|
|
(*ppsWidget)->formID = psInit->formID;
|
|
(*ppsWidget)->style = psInit->style;
|
|
(*ppsWidget)->disableChildren = psInit->disableChildren;
|
|
(*ppsWidget)->animCount = 0;
|
|
(*ppsWidget)->x = psInit->x;
|
|
(*ppsWidget)->y = psInit->y;
|
|
(*ppsWidget)->width = psInit->width;
|
|
(*ppsWidget)->height = psInit->height;
|
|
if (psInit->pDisplay)
|
|
{
|
|
(*ppsWidget)->display = psInit->pDisplay;
|
|
}
|
|
else
|
|
{
|
|
(*ppsWidget)->display = formDisplayTabbed;
|
|
}
|
|
(*ppsWidget)->callback = psInit->pCallback;
|
|
(*ppsWidget)->pUserData = psInit->pUserData;
|
|
(*ppsWidget)->UserData = psInit->UserData;
|
|
(*ppsWidget)->psLastHiLite = NULL;
|
|
(*ppsWidget)->majorSize = psInit->majorSize;
|
|
(*ppsWidget)->minorSize = psInit->minorSize;
|
|
(*ppsWidget)->tabMajorThickness = psInit->tabMajorThickness;
|
|
(*ppsWidget)->tabMinorThickness = psInit->tabMinorThickness;
|
|
(*ppsWidget)->tabMajorGap = psInit->tabMajorGap;
|
|
(*ppsWidget)->tabMinorGap = psInit->tabMinorGap;
|
|
(*ppsWidget)->tabVertOffset = psInit->tabVertOffset;
|
|
(*ppsWidget)->tabHorzOffset = psInit->tabHorzOffset;
|
|
(*ppsWidget)->majorOffset = psInit->majorOffset;
|
|
(*ppsWidget)->minorOffset = psInit->minorOffset;
|
|
(*ppsWidget)->majorPos = psInit->majorPos;
|
|
(*ppsWidget)->minorPos = psInit->minorPos;
|
|
(*ppsWidget)->pTabDisplay = psInit->pTabDisplay;
|
|
(*ppsWidget)->TabMultiplier = psInit->TabMultiplier;
|
|
(*ppsWidget)->numButtons = psInit->numButtons;
|
|
(*ppsWidget)->numStats = psInit->numStats;
|
|
|
|
formSetDefaultColours((W_FORM *)(*ppsWidget));
|
|
|
|
/* Set up the tab data.
|
|
* All widget pointers have been zeroed by the memset above.
|
|
*/
|
|
(*ppsWidget)->numMajor = psInit->numMajor;
|
|
for (major=0; major<psInit->numMajor; major++)
|
|
{
|
|
(*ppsWidget)->asMajor[major].numMinor = psInit->aNumMinors[major];
|
|
}
|
|
|
|
formInitialise((W_FORM *)*ppsWidget);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Free the tips strings for a tabbed form */
|
|
static inline void formFreeTips(W_TABFORM *psForm)
|
|
{
|
|
psForm = psForm;
|
|
}
|
|
|
|
/* Free a tabbed form widget */
|
|
static void formFreeTabbed(W_TABFORM *psWidget)
|
|
{
|
|
WIDGET *psCurr;
|
|
W_FORMGETALL sGetAll;
|
|
|
|
ASSERT( psWidget != NULL,
|
|
"formFreeTabbed: Invalid form pointer" );
|
|
|
|
formFreeTips(psWidget);
|
|
|
|
formInitGetAllWidgets((W_FORM *)psWidget,&sGetAll);
|
|
psCurr = formGetAllWidgets(&sGetAll);
|
|
while (psCurr)
|
|
{
|
|
widgReleaseWidgetList(psCurr);
|
|
psCurr = formGetAllWidgets(&sGetAll);
|
|
}
|
|
free(psWidget);
|
|
}
|
|
|
|
|
|
/* Create a form widget data structure */
|
|
BOOL formCreate(W_FORM **ppsWidget, W_FORMINIT *psInit)
|
|
{
|
|
/* Check the style bits are OK */
|
|
if (psInit->style & ~(WFORM_TABBED | WFORM_INVISIBLE | WFORM_CLICKABLE |
|
|
WFORM_NOCLICKMOVE | WFORM_NOPRIMARY | WFORM_SECONDARY |
|
|
WIDG_HIDDEN))
|
|
{
|
|
ASSERT( FALSE, "formCreate: Unknown style bit" );
|
|
return FALSE;
|
|
}
|
|
if ((psInit->style & WFORM_TABBED) &&
|
|
(psInit->style & (WFORM_INVISIBLE | WFORM_CLICKABLE)))
|
|
{
|
|
ASSERT( FALSE, "formCreate: Tabbed form cannot be invisible or clickable" );
|
|
return FALSE;
|
|
}
|
|
if ((psInit->style & WFORM_INVISIBLE) &&
|
|
(psInit->style & WFORM_CLICKABLE))
|
|
{
|
|
ASSERT( FALSE, "formCreate: Cannot have an invisible clickable form" );
|
|
return FALSE;
|
|
}
|
|
if (!(psInit->style & WFORM_CLICKABLE) &&
|
|
((psInit->style & WFORM_NOPRIMARY) || (psInit->style & WFORM_SECONDARY)))
|
|
{
|
|
ASSERT( FALSE, "formCreate: Cannot set keys if the form isn't clickable" );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Create the correct type of form */
|
|
if (psInit->style & WFORM_TABBED)
|
|
{
|
|
return formCreateTabbed((W_TABFORM **)ppsWidget, psInit);
|
|
}
|
|
else if (psInit->style & WFORM_CLICKABLE)
|
|
{
|
|
return formCreateClickable((W_CLICKFORM **)ppsWidget, psInit);
|
|
}
|
|
else
|
|
{
|
|
return formCreatePlain(ppsWidget, psInit);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* Free the memory used by a form */
|
|
void formFree(W_FORM *psWidget)
|
|
{
|
|
if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
formFreeTabbed((W_TABFORM *)psWidget);
|
|
}
|
|
else if (psWidget->style & WFORM_CLICKABLE)
|
|
{
|
|
formFreeClickable((W_CLICKFORM *)psWidget);
|
|
}
|
|
else
|
|
{
|
|
formFreePlain(psWidget);
|
|
}
|
|
}
|
|
|
|
|
|
/* Add a widget to a form */
|
|
BOOL formAddWidget(W_FORM *psForm, WIDGET *psWidget, W_INIT *psInit)
|
|
{
|
|
W_TABFORM *psTabForm;
|
|
WIDGET **ppsList;
|
|
W_MAJORTAB *psMajor;
|
|
|
|
ASSERT( psWidget != NULL,
|
|
"formAddWidget: Invalid widget pointer" );
|
|
|
|
if (psForm->style & WFORM_TABBED)
|
|
{
|
|
ASSERT( psForm != NULL,
|
|
"formAddWidget: Invalid tab form pointer" );
|
|
psTabForm = (W_TABFORM *)psForm;
|
|
if (psInit->majorID >= psTabForm->numMajor)
|
|
{
|
|
ASSERT( FALSE, "formAddWidget: Major tab does not exist" );
|
|
return FALSE;
|
|
}
|
|
psMajor = psTabForm->asMajor + psInit->majorID;
|
|
if (psInit->minorID >= psMajor->numMinor)
|
|
{
|
|
ASSERT( FALSE, "formAddWidget: Minor tab does not exist" );
|
|
return FALSE;
|
|
}
|
|
ppsList = &(psMajor->asMinor[psInit->minorID].psWidgets);
|
|
psWidget->psNext = *ppsList;
|
|
*ppsList = psWidget;
|
|
}
|
|
else
|
|
{
|
|
ASSERT( psForm != NULL,
|
|
"formAddWidget: Invalid form pointer" );
|
|
psWidget->psNext = psForm->psWidgets;
|
|
psForm->psWidgets = psWidget;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Get the button state of a click form */
|
|
UDWORD formGetClickState(W_CLICKFORM *psForm)
|
|
{
|
|
UDWORD State = 0;
|
|
|
|
if (psForm->state & WCLICK_GREY)
|
|
{
|
|
State |= WBUT_DISABLE;
|
|
}
|
|
|
|
if (psForm->state & WCLICK_LOCKED)
|
|
{
|
|
State |= WBUT_LOCK;
|
|
}
|
|
|
|
if (psForm->state & WCLICK_CLICKLOCK)
|
|
{
|
|
State |= WBUT_CLICKLOCK;
|
|
}
|
|
|
|
return State;
|
|
}
|
|
|
|
|
|
/* Set the button state of a click form */
|
|
void formSetClickState(W_CLICKFORM *psForm, UDWORD state)
|
|
{
|
|
ASSERT( !((state & WBUT_LOCK) && (state & WBUT_CLICKLOCK)),
|
|
"widgSetButtonState: Cannot have WBUT_LOCK and WBUT_CLICKLOCK" );
|
|
|
|
if (state & WBUT_DISABLE)
|
|
{
|
|
psForm->state |= WCLICK_GREY;
|
|
}
|
|
else
|
|
{
|
|
psForm->state &= ~WCLICK_GREY;
|
|
}
|
|
if (state & WBUT_LOCK)
|
|
{
|
|
psForm->state |= WCLICK_LOCKED;
|
|
}
|
|
else
|
|
{
|
|
psForm->state &= ~WCLICK_LOCKED;
|
|
}
|
|
if (state & WBUT_CLICKLOCK)
|
|
{
|
|
psForm->state |= WCLICK_CLICKLOCK;
|
|
}
|
|
else
|
|
{
|
|
psForm->state &= ~WCLICK_CLICKLOCK;
|
|
}
|
|
}
|
|
|
|
/* Return the widgets currently displayed by a form */
|
|
WIDGET *formGetWidgets(W_FORM *psWidget)
|
|
{
|
|
W_TABFORM *psTabForm;
|
|
W_MAJORTAB *psMajor;
|
|
|
|
if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
psTabForm = (W_TABFORM *)psWidget;
|
|
psMajor = psTabForm->asMajor + psTabForm->majorT;
|
|
return psMajor->asMinor[psTabForm->minorT].psWidgets;
|
|
}
|
|
else
|
|
{
|
|
return psWidget->psWidgets;
|
|
}
|
|
}
|
|
|
|
|
|
/* Initialise the formGetAllWidgets function */
|
|
void formInitGetAllWidgets(W_FORM *psWidget, W_FORMGETALL *psCtrl)
|
|
{
|
|
if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
psCtrl->psGAWList = NULL;
|
|
psCtrl->psGAWForm = (W_TABFORM *)psWidget;
|
|
psCtrl->psGAWMajor = psCtrl->psGAWForm->asMajor;
|
|
psCtrl->GAWMajor = 0;
|
|
psCtrl->GAWMinor = 0;
|
|
}
|
|
else
|
|
{
|
|
psCtrl->psGAWList = psWidget->psWidgets;
|
|
psCtrl->psGAWForm = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/* Repeated calls to this function will return widget lists
|
|
* until all widgets in a form have been returned.
|
|
* When a NULL list is returned, all widgets have been seen.
|
|
*/
|
|
WIDGET *formGetAllWidgets(W_FORMGETALL *psCtrl)
|
|
{
|
|
WIDGET *psRetList;
|
|
|
|
if (psCtrl->psGAWForm == NULL)
|
|
{
|
|
/* Not a tabbed form, return the list */
|
|
psRetList = psCtrl->psGAWList;
|
|
psCtrl->psGAWList = NULL;
|
|
}
|
|
else
|
|
{
|
|
/* Working with a tabbed form - search for the first widget list */
|
|
psRetList = NULL;
|
|
while (psRetList == NULL && psCtrl->GAWMajor < psCtrl->psGAWForm->numMajor)
|
|
{
|
|
psRetList = psCtrl->psGAWMajor->asMinor[psCtrl->GAWMinor++].psWidgets;
|
|
if (psCtrl->GAWMinor >= psCtrl->psGAWMajor->numMinor)
|
|
{
|
|
psCtrl->GAWMinor = 0;
|
|
psCtrl->GAWMajor ++;
|
|
psCtrl->psGAWMajor ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return psRetList;
|
|
}
|
|
|
|
|
|
/* Set the current tabs for a tab form */
|
|
void widgSetTabs(W_SCREEN *psScreen, UDWORD id, UWORD major, UWORD minor)
|
|
{
|
|
W_TABFORM *psForm;
|
|
|
|
psForm = (W_TABFORM *)widgGetFromID(psScreen, id);
|
|
ASSERT(psForm != NULL, "widgSetTabs: Invalid tab form pointer" );
|
|
ASSERT((psForm->style & WFORM_TABBED), "widgSetTabs: couldn't find tabbed form from id");
|
|
if (psForm == NULL || !(psForm->style & WFORM_TABBED))
|
|
{
|
|
return; /* make us work fine in no assert compiles */
|
|
}
|
|
|
|
ASSERT(major < psForm->numMajor, "widgSetTabs id=%u: invalid major id %u >= max %u", id,
|
|
major, psForm->numMajor);
|
|
|
|
ASSERT(minor < psForm->asMajor[major].numMinor, "widgSetTabs id=%u: invalid minor id %u >= max %u", id,
|
|
minor, psForm->asMajor[major].numMinor);
|
|
|
|
// Make sure to bail out when we've been passed out-of-bounds major or minor numbers
|
|
if (major >= psForm->numMajor
|
|
|| minor >= psForm->asMajor[major].numMinor)
|
|
{
|
|
return;
|
|
}
|
|
|
|
psForm->majorT = major;
|
|
psForm->minorT = minor;
|
|
psForm->asMajor[major].lastMinor = minor;
|
|
}
|
|
|
|
|
|
/* Get the current tabs for a tab form */
|
|
void widgGetTabs(W_SCREEN *psScreen, UDWORD id, UWORD *pMajor, UWORD *pMinor)
|
|
{
|
|
W_TABFORM *psForm;
|
|
|
|
psForm = (W_TABFORM *)widgGetFromID(psScreen, id);
|
|
if (psForm == NULL || psForm->type != WIDG_FORM ||
|
|
!(psForm->style & WFORM_TABBED))
|
|
{
|
|
ASSERT( FALSE,"widgGetTabs: couldn't find tabbed form from id" );
|
|
return;
|
|
}
|
|
ASSERT( psForm != NULL,
|
|
"widgGetTabs: Invalid tab form pointer" );
|
|
|
|
*pMajor = psForm->majorT;
|
|
*pMinor = psForm->minorT;
|
|
}
|
|
|
|
|
|
/* Set a colour on a form */
|
|
void widgSetColour(W_SCREEN *psScreen, UDWORD id, UDWORD colour,
|
|
UBYTE red, UBYTE green, UBYTE blue)
|
|
{
|
|
W_TABFORM *psForm;
|
|
|
|
psForm = (W_TABFORM *)widgGetFromID(psScreen, id);
|
|
if (psForm == NULL || psForm->type != WIDG_FORM)
|
|
{
|
|
ASSERT( FALSE,"widgSetColour: couldn't find form from id" );
|
|
return;
|
|
}
|
|
ASSERT( psForm != NULL,
|
|
"widgSetColour: Invalid tab form pointer" );
|
|
|
|
if (colour >= WCOL_MAX)
|
|
{
|
|
ASSERT( FALSE, "widgSetColour: Colour id out of range" );
|
|
return;
|
|
}
|
|
psForm->aColours[colour] = pal_Colour(red,green,blue);
|
|
}
|
|
|
|
|
|
/* Return the origin on the form from which button locations are calculated */
|
|
void formGetOrigin(W_FORM *psWidget, SDWORD *pXOrigin, SDWORD *pYOrigin)
|
|
{
|
|
W_TABFORM *psTabForm;
|
|
|
|
ASSERT( psWidget != NULL,
|
|
"formGetOrigin: Invalid form pointer" );
|
|
|
|
if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
psTabForm = (W_TABFORM *)psWidget;
|
|
if(psTabForm->majorPos == WFORM_TABTOP) {
|
|
*pYOrigin = psTabForm->tabMajorThickness;
|
|
} else if(psTabForm->minorPos == WFORM_TABTOP) {
|
|
*pYOrigin = psTabForm->tabMinorThickness;
|
|
} else {
|
|
*pYOrigin = 0;
|
|
}
|
|
if(psTabForm->majorPos == WFORM_TABLEFT) {
|
|
*pXOrigin = psTabForm->tabMajorThickness;
|
|
} else if(psTabForm->minorPos == WFORM_TABLEFT) {
|
|
*pXOrigin = psTabForm->tabMinorThickness;
|
|
} else {
|
|
*pXOrigin = 0;
|
|
}
|
|
// if ((psTabForm->majorPos == WFORM_TABTOP) ||
|
|
// (psTabForm->minorPos == WFORM_TABTOP))
|
|
// {
|
|
// *pYOrigin = psTabForm->tabThickness;
|
|
// }
|
|
// else
|
|
// {
|
|
// *pYOrigin = 0;
|
|
// }
|
|
// if ((psTabForm->majorPos == WFORM_TABLEFT) ||
|
|
// (psTabForm->minorPos == WFORM_TABLEFT))
|
|
// {
|
|
// *pXOrigin = psTabForm->tabThickness;
|
|
// }
|
|
// else
|
|
// {
|
|
// *pXOrigin = 0;
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
*pXOrigin = 0;
|
|
*pYOrigin = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* Initialise a form widget before running it */
|
|
void formInitialise(W_FORM *psWidget)
|
|
{
|
|
W_TABFORM *psTabForm;
|
|
W_CLICKFORM *psClickForm;
|
|
UDWORD i;
|
|
|
|
if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
ASSERT( psWidget != NULL,
|
|
"formInitialise: invalid tab form pointer" );
|
|
psTabForm = (W_TABFORM *)psWidget;
|
|
psTabForm->majorT = 0;
|
|
psTabForm->minorT = 0;
|
|
psTabForm->tabHiLite = (UWORD)(-1);
|
|
for (i=0; i<psTabForm->numMajor; i++)
|
|
{
|
|
psTabForm->asMajor[i].lastMinor = 0;
|
|
}
|
|
}
|
|
else if (psWidget->style & WFORM_CLICKABLE)
|
|
{
|
|
ASSERT( psWidget != NULL,
|
|
"formInitialise: invalid clickable form pointer" );
|
|
psClickForm = (W_CLICKFORM *)psWidget;
|
|
psClickForm->state = WCLICK_NORMAL;
|
|
}
|
|
else
|
|
{
|
|
ASSERT( psWidget != NULL,
|
|
"formInitialise: invalid form pointer" );
|
|
}
|
|
|
|
psWidget->psLastHiLite = NULL;
|
|
}
|
|
|
|
|
|
// Currently in game, I can only find that warzone uses horizontal tabs.
|
|
// So ONLY this routine was modified. Will have to modify the vert. tab
|
|
// routine if we ever use it.
|
|
// Choose a horizontal tab from a coordinate
|
|
static BOOL formPickHTab(TAB_POS *psTabPos,
|
|
SDWORD x0, SDWORD y0,
|
|
UDWORD width, UDWORD height, UDWORD gap,
|
|
UDWORD number, SDWORD fx, SDWORD fy)
|
|
{
|
|
SDWORD x, y1;
|
|
UDWORD i;
|
|
|
|
#if NO_DISPLAY_SINGLE_TABS
|
|
if (number == 1)
|
|
{
|
|
// Don't have single tabs
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
x = x0;
|
|
y1 = y0 + height;
|
|
|
|
// We need to filter out some tabs, since we can only display 7 at a time, with
|
|
// the scroll tabs in place, and 8 without. MAX_TAB_SMALL_SHOWN (currently 8) is the case
|
|
// when we do NOT want scrolltabs, and are using smallTab icons.
|
|
// Also need to check if the TabMultiplier is set or not, if not then it means
|
|
// we have not yet added the code to display/handle the tab scroll buttons.
|
|
// At this time, I think only the design screen has this limitation of only 8 tabs.
|
|
if (number > MAX_TAB_SMALL_SHOWN && psTabPos->TabMultiplier) // of course only do this if we actually need >8 tabs.
|
|
{
|
|
number -= (psTabPos->TabMultiplier - 1) * TAB_SEVEN;
|
|
if (number > TAB_SEVEN) // is it still > than TAB_SEVEN?
|
|
{
|
|
number = TAB_SEVEN;
|
|
}
|
|
}
|
|
else if (number > MAX_TAB_SMALL_SHOWN)
|
|
{
|
|
// we need to clip the tab count to max amount *without* the scrolltabs visible.
|
|
// The reason for this, is that in design screen & 'feature' debug & others(?),
|
|
// we can get over max # of tabs that the game originally supported.
|
|
// This made it look bad.
|
|
number = MAX_TAB_SMALL_SHOWN;
|
|
}
|
|
|
|
for (i=0; i < number; i++)
|
|
{
|
|
// if (fx >= x && fx <= x + (SDWORD)(width - gap) &&
|
|
if (fx >= x && fx <= x + (SDWORD)(width) &&
|
|
fy >= y0 && fy <= y1)
|
|
{
|
|
// found a tab under the coordinate
|
|
if (psTabPos->TabMultiplier) //Checks to see we need the extra tab scroll buttons
|
|
{ // holds the VIRTUAL tab #, since obviously, we can't display more than 7
|
|
psTabPos->index = (i % TAB_SEVEN)+ ((psTabPos->TabMultiplier -1)*TAB_SEVEN);
|
|
}
|
|
else
|
|
{ // This is a normal request.
|
|
psTabPos->index = i;
|
|
}
|
|
psTabPos->x = x ;
|
|
psTabPos->y = y0;
|
|
psTabPos->width = width;
|
|
psTabPos->height = height;
|
|
return TRUE;
|
|
}
|
|
|
|
x += width + gap;
|
|
}
|
|
|
|
/* Didn't find any */
|
|
return FALSE;
|
|
}
|
|
|
|
// NOTE: This routine is NOT modified to use the tab scroll buttons.
|
|
// Choose a vertical tab from a coordinate
|
|
static BOOL formPickVTab(TAB_POS *psTabPos,
|
|
SDWORD x0, SDWORD y0,
|
|
UDWORD width, UDWORD height, UDWORD gap,
|
|
UDWORD number, SDWORD fx, SDWORD fy)
|
|
{
|
|
SDWORD x1, y;
|
|
UDWORD i;
|
|
|
|
#if NO_DISPLAY_SINGLE_TABS
|
|
if (number == 1)
|
|
{
|
|
/* Don't have single tabs */
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
x1 = x0 + width;
|
|
y = y0;
|
|
for (i=0; i < number; i++)
|
|
{
|
|
if (fx >= x0 && fx <= x1 &&
|
|
fy >= y && fy <= y + (SDWORD)(height))
|
|
// fy >= y && fy <= y + (SDWORD)(height - gap))
|
|
{
|
|
/* found a tab under the coordinate */
|
|
psTabPos->index = i;
|
|
psTabPos->x = x0;
|
|
psTabPos->y = y;
|
|
psTabPos->width = width;
|
|
psTabPos->height = height;
|
|
return TRUE;
|
|
}
|
|
|
|
y += height + gap;
|
|
}
|
|
|
|
/* Didn't find any */
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* Find which tab is under a form coordinate */
|
|
static BOOL formPickTab(W_TABFORM *psForm, UDWORD fx, UDWORD fy,
|
|
TAB_POS *psTabPos)
|
|
{
|
|
SDWORD x0,y0, x1,y1;
|
|
W_MAJORTAB *psMajor;
|
|
SDWORD xOffset,yOffset;
|
|
SDWORD xOffset2,yOffset2;
|
|
|
|
/* Get the basic position of the form */
|
|
x0 = 0;
|
|
y0 = 0;
|
|
x1 = psForm->width;
|
|
y1 = psForm->height;
|
|
|
|
/* Adjust for where the tabs are */
|
|
if(psForm->majorPos == WFORM_TABLEFT) {
|
|
x0 += psForm->tabMajorThickness;
|
|
} else if(psForm->minorPos == WFORM_TABLEFT) {
|
|
x0 += psForm->tabMinorThickness;
|
|
}
|
|
if(psForm->majorPos == WFORM_TABRIGHT) {
|
|
x1 -= psForm->tabMajorThickness;
|
|
} else if (psForm->minorPos == WFORM_TABRIGHT) {
|
|
x1 -= psForm->tabMinorThickness;
|
|
}
|
|
if(psForm->majorPos == WFORM_TABTOP) {
|
|
y0 += psForm->tabMajorThickness;
|
|
} else if(psForm->minorPos == WFORM_TABTOP) {
|
|
y0 += psForm->tabMinorThickness;
|
|
}
|
|
if(psForm->majorPos == WFORM_TABBOTTOM) {
|
|
y1 -= psForm->tabMajorThickness;
|
|
} else if(psForm->minorPos == WFORM_TABBOTTOM) {
|
|
y1 -= psForm->tabMinorThickness;
|
|
}
|
|
|
|
// /* Adjust for where the tabs are */
|
|
// if (psForm->majorPos == WFORM_TABLEFT || psForm->minorPos == WFORM_TABLEFT)
|
|
// {
|
|
// x0 += psForm->tabThickness;
|
|
// }
|
|
// if (psForm->majorPos == WFORM_TABRIGHT || psForm->minorPos == WFORM_TABRIGHT)
|
|
// {
|
|
// x1 -= psForm->tabThickness;
|
|
// }
|
|
// if (psForm->majorPos == WFORM_TABTOP || psForm->minorPos == WFORM_TABTOP)
|
|
// {
|
|
// y0 += psForm->tabThickness;
|
|
// }
|
|
// if (psForm->majorPos == WFORM_TABBOTTOM || psForm->minorPos == WFORM_TABBOTTOM)
|
|
// {
|
|
// y1 -= psForm->tabThickness;
|
|
// }
|
|
|
|
|
|
xOffset = yOffset = 0;
|
|
switch (psForm->minorPos)
|
|
{
|
|
case WFORM_TABTOP:
|
|
yOffset = psForm->tabVertOffset;
|
|
break;
|
|
|
|
case WFORM_TABLEFT:
|
|
xOffset = psForm->tabHorzOffset;
|
|
break;
|
|
|
|
case WFORM_TABBOTTOM:
|
|
yOffset = psForm->tabVertOffset;
|
|
break;
|
|
|
|
case WFORM_TABRIGHT:
|
|
xOffset = psForm->tabHorzOffset;
|
|
break;
|
|
}
|
|
|
|
xOffset2 = yOffset2 = 0;
|
|
psTabPos->TabMultiplier = psForm->TabMultiplier;
|
|
/* Check the major tabs */
|
|
switch (psForm->majorPos)
|
|
{
|
|
case WFORM_TABTOP:
|
|
if (formPickHTab(psTabPos, x0+psForm->majorOffset - xOffset, y0 - psForm->tabMajorThickness,
|
|
psForm->majorSize, psForm->tabMajorThickness, psForm->tabMajorGap,
|
|
psForm->numMajor, fx, fy))
|
|
{
|
|
return TRUE;
|
|
}
|
|
yOffset2 = -psForm->tabVertOffset;
|
|
break;
|
|
case WFORM_TABBOTTOM:
|
|
if (formPickHTab(psTabPos, x0+psForm->majorOffset - xOffset, y1,
|
|
psForm->majorSize, psForm->tabMajorThickness, psForm->tabMajorGap,
|
|
psForm->numMajor, fx, fy))
|
|
{
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case WFORM_TABLEFT:
|
|
if (formPickVTab(psTabPos, x0 - psForm->tabMajorThickness, y0+psForm->majorOffset - yOffset,
|
|
psForm->tabMajorThickness, psForm->majorSize, psForm->tabMajorGap,
|
|
psForm->numMajor, fx, fy))
|
|
{
|
|
return TRUE;
|
|
}
|
|
xOffset2 = psForm->tabHorzOffset;
|
|
break;
|
|
case WFORM_TABRIGHT:
|
|
if (formPickVTab(psTabPos, x1, y0+psForm->majorOffset - yOffset,
|
|
psForm->tabMajorThickness, psForm->majorSize, psForm->tabMajorGap,
|
|
psForm->numMajor, fx, fy))
|
|
{
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case WFORM_TABNONE:
|
|
ASSERT( FALSE, "formDisplayTabbed: Cannot have a tabbed form with no major tabs" );
|
|
break;
|
|
}
|
|
|
|
/* Draw the minor tabs */
|
|
psMajor = psForm->asMajor + psForm->majorT;
|
|
switch (psForm->minorPos)
|
|
{
|
|
case WFORM_TABTOP:
|
|
if (formPickHTab(psTabPos, x0+psForm->minorOffset - xOffset2, y0 - psForm->tabMinorThickness,
|
|
psForm->minorSize, psForm->tabMinorThickness, psForm->tabMinorGap,
|
|
psMajor->numMinor, fx, fy))
|
|
{
|
|
psTabPos->index += psForm->numMajor;
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case WFORM_TABBOTTOM:
|
|
if (formPickHTab(psTabPos, x0+psForm->minorOffset - xOffset2, y1,
|
|
psForm->minorSize, psForm->tabMinorThickness, psForm->tabMinorGap,
|
|
psMajor->numMinor, fx, fy))
|
|
{
|
|
psTabPos->index += psForm->numMajor;
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case WFORM_TABLEFT:
|
|
if (formPickVTab(psTabPos, x0+xOffset - psForm->tabMinorThickness, y0+psForm->minorOffset - yOffset2,
|
|
psForm->tabMinorThickness, psForm->minorSize, psForm->tabMinorGap,
|
|
psMajor->numMinor, fx, fy))
|
|
{
|
|
psTabPos->index += psForm->numMajor;
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case WFORM_TABRIGHT:
|
|
if (formPickVTab(psTabPos, x1+xOffset, y0+psForm->minorOffset - yOffset2,
|
|
psForm->tabMinorThickness, psForm->minorSize, psForm->tabMinorGap,
|
|
psMajor->numMinor, fx, fy))
|
|
{
|
|
psTabPos->index += psForm->numMajor;
|
|
return TRUE;
|
|
}
|
|
break;
|
|
/* case WFORM_TABNONE - no minor tabs so nothing to display */
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern UDWORD gameTime2;
|
|
|
|
/* Run a form widget */
|
|
void formRun(W_FORM *psWidget, W_CONTEXT *psContext)
|
|
{
|
|
SDWORD mx,my;
|
|
TAB_POS sTabPos;
|
|
char *pTip;
|
|
W_TABFORM *psTabForm;
|
|
|
|
memset(&sTabPos, 0x0, sizeof(TAB_POS));
|
|
if(psWidget->style & WFORM_CLICKABLE) {
|
|
if(((W_CLICKFORM *)psWidget)->state & WCLICK_FLASH) {
|
|
if (((gameTime2/250) % 2) == 0) {
|
|
((W_CLICKFORM *)psWidget)->state &= ~WCLICK_FLASHON;
|
|
} else {
|
|
((W_CLICKFORM *)psWidget)->state |= WCLICK_FLASHON;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
mx = psContext->mx;
|
|
my = psContext->my;
|
|
psTabForm = (W_TABFORM *)psWidget;
|
|
|
|
/* If the mouse is over the form, see if any tabs need to be hilited */
|
|
if (mx >= 0 && mx <= psTabForm->width &&
|
|
my >= 0 && my <= psTabForm->height)
|
|
{
|
|
if (formPickTab(psTabForm, mx,my, &sTabPos))
|
|
{
|
|
if (psTabForm->tabHiLite != (UWORD)sTabPos.index)
|
|
{
|
|
/* Got a new tab - start the tool tip if there is one */
|
|
psTabForm->tabHiLite = (UWORD)sTabPos.index;
|
|
if (sTabPos.index >= psTabForm->numMajor)
|
|
{
|
|
pTip = psTabForm->asMajor[psTabForm->majorT].
|
|
asMinor[sTabPos.index - psTabForm->numMajor].pTip;
|
|
}
|
|
else
|
|
{
|
|
pTip = psTabForm->asMajor[sTabPos.index].pTip;
|
|
}
|
|
if (pTip)
|
|
{
|
|
/* Got a tip - start it off */
|
|
tipStart((WIDGET *)psTabForm, pTip,
|
|
psContext->psScreen->TipFontID, psTabForm->aColours,
|
|
sTabPos.x + psContext->xOffset,
|
|
sTabPos.y + psContext->yOffset,
|
|
sTabPos.width,sTabPos.height);
|
|
}
|
|
else
|
|
{
|
|
/* No tip - clear any old tip */
|
|
tipStop((WIDGET *)psWidget);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* No tab - clear the tool tip */
|
|
tipStop((WIDGET *)psWidget);
|
|
/* And clear the hilite */
|
|
psTabForm->tabHiLite = (UWORD)(-1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void formSetFlash(W_FORM *psWidget)
|
|
{
|
|
if(psWidget->style & WFORM_CLICKABLE) {
|
|
((W_CLICKFORM *)psWidget)->state |= WCLICK_FLASH;
|
|
}
|
|
}
|
|
|
|
|
|
void formClearFlash(W_FORM *psWidget)
|
|
{
|
|
if(psWidget->style & WFORM_CLICKABLE) {
|
|
((W_CLICKFORM *)psWidget)->state &= ~WCLICK_FLASH;
|
|
((W_CLICKFORM *)psWidget)->state &= ~WCLICK_FLASHON;
|
|
}
|
|
}
|
|
|
|
|
|
/* Respond to a mouse click */
|
|
void formClicked(W_FORM *psWidget, UDWORD key)
|
|
{
|
|
W_CLICKFORM *psClickForm;
|
|
|
|
/* Stop the tip if there is one */
|
|
tipStop((WIDGET *)psWidget);
|
|
|
|
if (psWidget->style & WFORM_CLICKABLE)
|
|
{
|
|
/* Can't click a button if it is disabled or locked down */
|
|
if (!(((W_CLICKFORM *)psWidget)->state & (WCLICK_GREY | WCLICK_LOCKED)))
|
|
{
|
|
// Check this is the correct key
|
|
if ((!(psWidget->style & WFORM_NOPRIMARY) && key == WKEY_PRIMARY) ||
|
|
((psWidget->style & WFORM_SECONDARY) && key == WKEY_SECONDARY))
|
|
{
|
|
((W_CLICKFORM *)psWidget)->state &= ~WCLICK_FLASH; // Stop it flashing
|
|
((W_CLICKFORM *)psWidget)->state &= ~WCLICK_FLASHON;
|
|
((W_CLICKFORM *)psWidget)->state |= WCLICK_DOWN;
|
|
|
|
psClickForm = (W_CLICKFORM *)psWidget;
|
|
|
|
if(psClickForm->AudioCallback) {
|
|
psClickForm->AudioCallback(psClickForm->ClickedAudioID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Respond to a mouse form up */
|
|
void formReleased(W_FORM *psWidget, UDWORD key, W_CONTEXT *psContext)
|
|
{
|
|
W_TABFORM *psTabForm;
|
|
W_CLICKFORM *psClickForm;
|
|
TAB_POS sTabPos;
|
|
|
|
if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
psTabForm = (W_TABFORM *)psWidget;
|
|
/* See if a tab has been clicked on */
|
|
if (formPickTab(psTabForm, psContext->mx,psContext->my, &sTabPos))
|
|
{
|
|
if (sTabPos.index >= psTabForm->numMajor)
|
|
{
|
|
/* Clicked on a minor tab */
|
|
psTabForm->minorT = (UWORD)(sTabPos.index - psTabForm->numMajor);
|
|
psTabForm->asMajor[psTabForm->majorT].lastMinor = psTabForm->minorT;
|
|
widgSetReturn((WIDGET *)psWidget);
|
|
}
|
|
else
|
|
{
|
|
/* Clicked on a major tab */
|
|
psTabForm->majorT = (UWORD)sTabPos.index;
|
|
psTabForm->minorT = psTabForm->asMajor[sTabPos.index].lastMinor;
|
|
widgSetReturn((WIDGET *)psWidget);
|
|
}
|
|
}
|
|
}
|
|
else if (psWidget->style & WFORM_CLICKABLE)
|
|
{
|
|
psClickForm = (W_CLICKFORM *)psWidget;
|
|
if (psClickForm->state & WCLICK_DOWN)
|
|
{
|
|
// Check this is the correct key
|
|
if ((!(psWidget->style & WFORM_NOPRIMARY) && key == WKEY_PRIMARY) ||
|
|
((psWidget->style & WFORM_SECONDARY) && key == WKEY_SECONDARY))
|
|
{
|
|
widgSetReturn((WIDGET *)psClickForm);
|
|
psClickForm->state &= ~WCLICK_DOWN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Respond to a mouse moving over a form */
|
|
void formHiLite(W_FORM *psWidget, W_CONTEXT *psContext)
|
|
{
|
|
W_CLICKFORM *psClickForm;
|
|
|
|
if (psWidget->style & WFORM_CLICKABLE)
|
|
{
|
|
psClickForm = (W_CLICKFORM *)psWidget;
|
|
|
|
psClickForm->state |= WCLICK_HILITE;
|
|
|
|
/* If there is a tip string start the tool tip */
|
|
if (psClickForm->pTip)
|
|
{
|
|
tipStart((WIDGET *)psClickForm, psClickForm->pTip,
|
|
psContext->psScreen->TipFontID, psContext->psForm->aColours,
|
|
psWidget->x + psContext->xOffset, psWidget->y + psContext->yOffset,
|
|
psWidget->width, psWidget->height);
|
|
}
|
|
|
|
if(psClickForm->AudioCallback) {
|
|
psClickForm->AudioCallback(psClickForm->HilightAudioID);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Respond to the mouse moving off a form */
|
|
void formHiLiteLost(W_FORM *psWidget, W_CONTEXT *psContext)
|
|
{
|
|
/* If one of the widgets were hilited that has to loose it as well */
|
|
if (psWidget->psLastHiLite != NULL)
|
|
{
|
|
widgHiLiteLost(psWidget->psLastHiLite, psContext);
|
|
}
|
|
if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
((W_TABFORM *)psWidget)->tabHiLite = (UWORD)(-1);
|
|
}
|
|
if (psWidget->style & WFORM_CLICKABLE)
|
|
{
|
|
((W_CLICKFORM *)psWidget)->state &= ~(WCLICK_DOWN | WCLICK_HILITE);
|
|
}
|
|
/* Clear the tool tip if there is one */
|
|
tipStop((WIDGET *)psWidget);
|
|
}
|
|
|
|
/* Display a form */
|
|
void formDisplay(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours)
|
|
{
|
|
UDWORD x0,y0,x1,y1;
|
|
|
|
if (!(psWidget->style & WFORM_INVISIBLE))
|
|
{
|
|
x0 = psWidget->x + xOffset;
|
|
y0 = psWidget->y + yOffset;
|
|
x1 = x0 + psWidget->width;
|
|
y1 = y0 + psWidget->height;
|
|
|
|
pie_BoxFill(x0 + 1, y0 + 1, x1 - 1, y1 - 1, pColours[WCOL_BKGRND]);
|
|
iV_Line(x0,y1,x0,y0, pColours[WCOL_LIGHT]);
|
|
iV_Line(x0,y0,x1,y0, pColours[WCOL_LIGHT]);
|
|
iV_Line(x1,y0,x1,y1, pColours[WCOL_DARK]);
|
|
iV_Line(x1,y1,x0,y1, pColours[WCOL_DARK]);
|
|
}
|
|
}
|
|
|
|
|
|
/* Display a clickable form */
|
|
void formDisplayClickable(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours)
|
|
{
|
|
UDWORD x0,y0,x1,y1;
|
|
W_CLICKFORM *psForm;
|
|
|
|
psForm = (W_CLICKFORM *)psWidget;
|
|
x0 = psWidget->x + xOffset;
|
|
y0 = psWidget->y + yOffset;
|
|
x1 = x0 + psWidget->width;
|
|
y1 = y0 + psWidget->height;
|
|
|
|
/* Fill the background */
|
|
pie_BoxFill(x0 + 1, y0 + 1, x1 - 1, y1 - 1, pColours[WCOL_BKGRND]);
|
|
|
|
/* Display the border */
|
|
if (psForm->state & (WCLICK_DOWN | WCLICK_LOCKED | WCLICK_CLICKLOCK))
|
|
{
|
|
/* Form down */
|
|
iV_Line(x0,y1,x0,y0, pColours[WCOL_DARK]);
|
|
iV_Line(x0,y0,x1,y0, pColours[WCOL_DARK]);
|
|
iV_Line(x1,y0,x1,y1, pColours[WCOL_LIGHT]);
|
|
iV_Line(x1,y1,x0,y1, pColours[WCOL_LIGHT]);
|
|
}
|
|
else
|
|
{
|
|
/* Form up */
|
|
iV_Line(x0,y1,x0,y0, pColours[WCOL_LIGHT]);
|
|
iV_Line(x0,y0,x1,y0, pColours[WCOL_LIGHT]);
|
|
iV_Line(x1,y0,x1,y1, pColours[WCOL_DARK]);
|
|
iV_Line(x1,y1,x0,y1, pColours[WCOL_DARK]);
|
|
}
|
|
}
|
|
|
|
|
|
/* Draw top tabs */
|
|
static void formDisplayTTabs(W_TABFORM *psForm,SDWORD x0, SDWORD y0,
|
|
UDWORD width, UDWORD height,
|
|
UDWORD number, UDWORD selected, UDWORD hilite,
|
|
PIELIGHT *pColours,UDWORD TabType,UDWORD TabGap)
|
|
{
|
|
SDWORD x,x1, y1;
|
|
UDWORD i, drawnumber;
|
|
|
|
#if NO_DISPLAY_SINGLE_TABS
|
|
if (number == 1)
|
|
{
|
|
/* Don't display single tabs */
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
x = x0 + 2;
|
|
x1 = x + width - 2;
|
|
y1 = y0 + height;
|
|
if (number > MAX_TAB_SMALL_SHOWN) //we can display 8 tabs fine with no extra voodoo.
|
|
{ // We do NOT want to draw all the tabs once we have drawn 7 tabs
|
|
// Both selected & hilite are converted from virtual tab range, to a range
|
|
// that is seen on the form itself. This would be 0-6 (7 tabs)
|
|
// We also fix drawnumber, so we don't display too many tabs since the pages
|
|
// will be empty.
|
|
drawnumber = (number - (( psForm->TabMultiplier -1) * TAB_SEVEN));
|
|
if (drawnumber > TAB_SEVEN) drawnumber = TAB_SEVEN ;
|
|
selected = (selected % TAB_SEVEN); //Go from Virtual range, to our range
|
|
|
|
if(hilite != 65535) //sigh. Don't blame me for this!It is THEIR 'hack'.
|
|
hilite = hilite % TAB_SEVEN; //we want to hilite tab 0 - 6.
|
|
}
|
|
else
|
|
{ // normal draw
|
|
drawnumber = number;
|
|
}
|
|
for (i=0; i < drawnumber; i++)
|
|
{
|
|
if(psForm->pTabDisplay) {
|
|
psForm->pTabDisplay((WIDGET*)psForm,TabType,WFORM_TABTOP,i,i==selected,i==hilite,x,y0,width,height);
|
|
} else {
|
|
if (i == selected)
|
|
{
|
|
/* Fill in the tab */
|
|
pie_BoxFill(x + 1, y0 + 1, x1 - 1, y1, pColours[WCOL_BKGRND]);
|
|
/* Draw the outline */
|
|
iV_Line(x,y0+2, x,y1-1, pColours[WCOL_LIGHT]);
|
|
iV_Line(x,y0+2, x+2,y0, pColours[WCOL_LIGHT]);
|
|
iV_Line(x+2,y0, x1-1,y0, pColours[WCOL_LIGHT]);
|
|
iV_Line(x1,y0+1, x1,y1, pColours[WCOL_DARK]);
|
|
}
|
|
else
|
|
{
|
|
/* Fill in the tab */
|
|
pie_BoxFill(x + 1, y0 + 2, x1 - 1, y1 - 1, pColours[WCOL_BKGRND]);
|
|
/* Draw the outline */
|
|
iV_Line(x,y0+3, x,y1-1, pColours[WCOL_LIGHT]);
|
|
iV_Line(x,y0+3, x+2,y0+1, pColours[WCOL_LIGHT]);
|
|
iV_Line(x+2,y0+1, x1-1,y0+1, pColours[WCOL_LIGHT]);
|
|
iV_Line(x1,y0+2, x1,y1-1, pColours[WCOL_DARK]);
|
|
}
|
|
if (i == hilite)
|
|
{
|
|
/* Draw the hilite box */
|
|
iV_Box(x+2,y0+4, x1-3, y1-3, pColours[WCOL_HILITE]);
|
|
}
|
|
}
|
|
x += width + TabGap;
|
|
x1 += width + TabGap;
|
|
}
|
|
}
|
|
|
|
|
|
/* Draw bottom tabs */
|
|
static void formDisplayBTabs(W_TABFORM *psForm,SDWORD x0, SDWORD y0,
|
|
UDWORD width, UDWORD height,
|
|
UDWORD number, UDWORD selected, UDWORD hilite,
|
|
PIELIGHT *pColours,UDWORD TabType,UDWORD TabGap)
|
|
{
|
|
SDWORD x,x1, y1;
|
|
UDWORD i;
|
|
|
|
#if NO_DISPLAY_SINGLE_TABS
|
|
if (number == 1)
|
|
{
|
|
/* Don't display single tabs */
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
x = x0 + 2;
|
|
x1 = x + width - 2;
|
|
y1 = y0 + height;
|
|
for (i=0; i < number; i++)
|
|
{
|
|
if(psForm->pTabDisplay) {
|
|
psForm->pTabDisplay((WIDGET*)psForm,TabType,WFORM_TABBOTTOM,i,i==selected,i==hilite,x,y0,width,height);
|
|
} else {
|
|
if (i == selected)
|
|
{
|
|
/* Fill in the tab */
|
|
pie_BoxFill(x + 1, y0, x1 - 1, y1 - 1, pColours[WCOL_BKGRND]);
|
|
/* Draw the outline */
|
|
iV_Line(x,y0, x,y1-1, pColours[WCOL_LIGHT]);
|
|
iV_Line(x,y1, x1-3,y1, pColours[WCOL_DARK]);
|
|
iV_Line(x1-2,y1, x1,y1-2, pColours[WCOL_DARK]);
|
|
iV_Line(x1,y1-3, x1,y0+1, pColours[WCOL_DARK]);
|
|
}
|
|
else
|
|
{
|
|
/* Fill in the tab */
|
|
pie_BoxFill(x + 1, y0 + 1, x1 - 1, y1 - 2, pColours[WCOL_BKGRND]);
|
|
/* Draw the outline */
|
|
iV_Line(x,y0+1, x,y1-1, pColours[WCOL_LIGHT]);
|
|
iV_Line(x+1,y1-1, x1-3,y1-1, pColours[WCOL_DARK]);
|
|
iV_Line(x1-2,y1-1, x1,y1-3, pColours[WCOL_DARK]);
|
|
iV_Line(x1,y1-4, x1,y0+1, pColours[WCOL_DARK]);
|
|
}
|
|
if (i == hilite)
|
|
{
|
|
/* Draw the hilite box */
|
|
iV_Box(x+2,y0+3, x1-3, y1-4, pColours[WCOL_HILITE]);
|
|
}
|
|
}
|
|
x += width + TabGap;
|
|
x1 += width + TabGap;
|
|
}
|
|
}
|
|
|
|
|
|
/* Draw left tabs */
|
|
static void formDisplayLTabs(W_TABFORM *psForm,SDWORD x0, SDWORD y0,
|
|
UDWORD width, UDWORD height,
|
|
UDWORD number, UDWORD selected, UDWORD hilite,
|
|
PIELIGHT *pColours,UDWORD TabType,UDWORD TabGap)
|
|
{
|
|
SDWORD x1, y,y1;
|
|
UDWORD i;
|
|
|
|
#if NO_DISPLAY_SINGLE_TABS
|
|
if (number == 1)
|
|
{
|
|
/* Don't display single tabs */
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
x1 = x0 + width;
|
|
y = y0+2;
|
|
y1 = y + height - 2;
|
|
for (i=0; i < number; i++)
|
|
{
|
|
if(psForm->pTabDisplay) {
|
|
psForm->pTabDisplay((WIDGET*)psForm,TabType,WFORM_TABLEFT,i,i==selected,i==hilite,x0,y,width,height);
|
|
} else {
|
|
if (i == selected)
|
|
{
|
|
/* Fill in the tab */
|
|
pie_BoxFill(x0 + 1, y + 1, x1, y1 - 1, pColours[WCOL_BKGRND]);
|
|
/* Draw the outline */
|
|
iV_Line(x0,y, x1-1,y, pColours[WCOL_LIGHT]);
|
|
iV_Line(x0,y+1, x0,y1-2, pColours[WCOL_LIGHT]);
|
|
iV_Line(x0+1,y1-1, x0+2,y1, pColours[WCOL_DARK]);
|
|
iV_Line(x0+3,y1, x1,y1, pColours[WCOL_DARK]);
|
|
}
|
|
else
|
|
{
|
|
/* Fill in the tab */
|
|
pie_BoxFill(x0 + 2, y + 1, x1 - 1, y1 - 1, pColours[WCOL_BKGRND]);
|
|
/* Draw the outline */
|
|
iV_Line(x0+1,y, x1-1,y, pColours[WCOL_LIGHT]);
|
|
iV_Line(x0+1,y+1, x0+1,y1-2, pColours[WCOL_LIGHT]);
|
|
iV_Line(x0+2,y1-1, x0+3,y1, pColours[WCOL_DARK]);
|
|
iV_Line(x0+4,y1, x1-1,y1, pColours[WCOL_DARK]);
|
|
}
|
|
if (i == hilite)
|
|
{
|
|
iV_Box(x0+4,y+2, x1-2, y1-3, pColours[WCOL_HILITE]);
|
|
}
|
|
}
|
|
y += height + TabGap;
|
|
y1 += height + TabGap;
|
|
}
|
|
}
|
|
|
|
|
|
/* Draw right tabs */
|
|
static void formDisplayRTabs(W_TABFORM *psForm,SDWORD x0, SDWORD y0,
|
|
UDWORD width, UDWORD height,
|
|
UDWORD number, UDWORD selected, UDWORD hilite,
|
|
PIELIGHT *pColours,UDWORD TabType,UDWORD TabGap)
|
|
{
|
|
SDWORD x1, y,y1;
|
|
UDWORD i;
|
|
|
|
#if NO_DISPLAY_SINGLE_TABS
|
|
if (number == 1)
|
|
{
|
|
/* Don't display single tabs */
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
x1 = x0 + width;
|
|
y = y0+2;
|
|
y1 = y + height - 2;
|
|
for (i=0; i < number; i++)
|
|
{
|
|
if(psForm->pTabDisplay) {
|
|
psForm->pTabDisplay((WIDGET*)psForm,TabType,WFORM_TABRIGHT,i,i==selected,i==hilite,x0,y,width,height);
|
|
} else {
|
|
if (i == selected)
|
|
{
|
|
/* Fill in the tab */
|
|
pie_BoxFill(x0,y+1, x1-1,y1-1, pColours[WCOL_BKGRND]);
|
|
/* Draw the outline */
|
|
iV_Line(x0,y, x1-1,y, pColours[WCOL_LIGHT]);
|
|
iV_Line(x1,y, x1,y1-2, pColours[WCOL_DARK]);
|
|
iV_Line(x1-1,y1-1, x1-2,y1, pColours[WCOL_DARK]);
|
|
iV_Line(x1-3,y1, x0,y1, pColours[WCOL_DARK]);
|
|
}
|
|
else
|
|
{
|
|
/* Fill in the tab */
|
|
pie_BoxFill(x0+1,y+1, x1-2,y1-1, pColours[WCOL_BKGRND]);
|
|
/* Draw the outline */
|
|
iV_Line(x0+1,y, x1-1,y, pColours[WCOL_LIGHT]);
|
|
iV_Line(x1-1,y, x1-1,y1-2, pColours[WCOL_DARK]);
|
|
iV_Line(x1-2,y1-1, x1-3,y1, pColours[WCOL_DARK]);
|
|
iV_Line(x1-4,y1, x0+1,y1, pColours[WCOL_DARK]);
|
|
}
|
|
if (i == hilite)
|
|
{
|
|
iV_Box(x0+2,y+2, x1-4, y1-3, pColours[WCOL_HILITE]);
|
|
}
|
|
}
|
|
y += height + TabGap;
|
|
y1 += height + TabGap;
|
|
}
|
|
}
|
|
|
|
|
|
/* Display a tabbed form */
|
|
void formDisplayTabbed(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours)
|
|
{
|
|
UDWORD x0,y0,x1,y1;
|
|
W_TABFORM *psForm;
|
|
W_MAJORTAB *psMajor;
|
|
|
|
psForm = (W_TABFORM *)psWidget;
|
|
|
|
/* Get the basic position of the form */
|
|
x0 = psForm->x + xOffset;
|
|
y0 = psForm->y + yOffset;
|
|
x1 = x0 + psForm->width;
|
|
y1 = y0 + psForm->height;
|
|
|
|
/* Adjust for where the tabs are */
|
|
if(psForm->majorPos == WFORM_TABLEFT) {
|
|
x0 += psForm->tabMajorThickness - psForm->tabHorzOffset;
|
|
} else if(psForm->minorPos == WFORM_TABLEFT) {
|
|
x0 += psForm->tabMinorThickness - psForm->tabHorzOffset;
|
|
}
|
|
if(psForm->majorPos == WFORM_TABRIGHT) {
|
|
x1 -= psForm->tabMajorThickness - psForm->tabHorzOffset;
|
|
} else if(psForm->minorPos == WFORM_TABRIGHT) {
|
|
x1 -= psForm->tabMinorThickness - psForm->tabHorzOffset;
|
|
}
|
|
if(psForm->majorPos == WFORM_TABTOP) {
|
|
y0 += psForm->tabMajorThickness - psForm->tabVertOffset;
|
|
} else if(psForm->minorPos == WFORM_TABTOP) {
|
|
y0 += psForm->tabMinorThickness - psForm->tabVertOffset;
|
|
}
|
|
if(psForm->majorPos == WFORM_TABBOTTOM) {
|
|
y1 -= psForm->tabMajorThickness - psForm->tabVertOffset;
|
|
} else if(psForm->minorPos == WFORM_TABBOTTOM) {
|
|
y1 -= psForm->tabMinorThickness - psForm->tabVertOffset;
|
|
}
|
|
|
|
/* Draw the major tabs */
|
|
switch (psForm->majorPos)
|
|
{
|
|
case WFORM_TABTOP:
|
|
formDisplayTTabs(psForm,x0+psForm->majorOffset, y0 - psForm->tabMajorThickness + psForm->tabVertOffset,
|
|
psForm->majorSize, psForm->tabMajorThickness,
|
|
psForm->numMajor, psForm->majorT, psForm->tabHiLite,
|
|
pColours,TAB_MAJOR,psForm->tabMajorGap);
|
|
break;
|
|
case WFORM_TABBOTTOM:
|
|
formDisplayBTabs(psForm,x0+psForm->majorOffset, y1 + psForm->tabVertOffset,
|
|
psForm->majorSize, psForm->tabMajorThickness,
|
|
psForm->numMajor, psForm->majorT, psForm->tabHiLite,
|
|
pColours,TAB_MAJOR,psForm->tabMajorGap);
|
|
break;
|
|
case WFORM_TABLEFT:
|
|
formDisplayLTabs(psForm,x0 - psForm->tabMajorThickness + psForm->tabHorzOffset, y0+psForm->majorOffset,
|
|
psForm->tabMajorThickness, psForm->majorSize,
|
|
psForm->numMajor, psForm->majorT, psForm->tabHiLite,
|
|
pColours,TAB_MAJOR,psForm->tabMajorGap);
|
|
break;
|
|
case WFORM_TABRIGHT:
|
|
formDisplayRTabs(psForm,x1 - psForm->tabHorzOffset, y0+psForm->majorOffset,
|
|
psForm->tabMajorThickness, psForm->majorSize,
|
|
psForm->numMajor, psForm->majorT, psForm->tabHiLite,
|
|
pColours,TAB_MAJOR,psForm->tabMajorGap);
|
|
break;
|
|
case WFORM_TABNONE:
|
|
ASSERT( FALSE, "formDisplayTabbed: Cannot have a tabbed form with no major tabs" );
|
|
break;
|
|
}
|
|
|
|
/* Draw the minor tabs */
|
|
psMajor = psForm->asMajor + psForm->majorT;
|
|
switch (psForm->minorPos)
|
|
{
|
|
case WFORM_TABTOP:
|
|
formDisplayTTabs(psForm,x0 + psForm->minorOffset, y0 - psForm->tabMinorThickness + psForm->tabVertOffset,
|
|
psForm->minorSize, psForm->tabMinorThickness,
|
|
psMajor->numMinor, psForm->minorT,
|
|
psForm->tabHiLite - psForm->numMajor, pColours,TAB_MINOR,psForm->tabMinorGap);
|
|
break;
|
|
case WFORM_TABBOTTOM:
|
|
formDisplayBTabs(psForm,x0 + psForm->minorOffset, y1 + psForm->tabVertOffset,
|
|
psForm->minorSize, psForm->tabMinorThickness,
|
|
psMajor->numMinor, psForm->minorT,
|
|
psForm->tabHiLite - psForm->numMajor, pColours,TAB_MINOR,psForm->tabMinorGap);
|
|
break;
|
|
case WFORM_TABLEFT:
|
|
formDisplayLTabs(psForm,x0 - psForm->tabMinorThickness + psForm->tabHorzOffset + psForm->minorOffset,
|
|
y0+psForm->minorOffset,
|
|
psForm->tabMinorThickness, psForm->minorSize,
|
|
psMajor->numMinor, psForm->minorT,
|
|
psForm->tabHiLite - psForm->numMajor, pColours,TAB_MINOR,psForm->tabMinorGap);
|
|
break;
|
|
case WFORM_TABRIGHT:
|
|
formDisplayRTabs(psForm,x1 + psForm->tabHorzOffset, y0+psForm->minorOffset,
|
|
psForm->tabMinorThickness, psForm->minorSize,
|
|
psMajor->numMinor, psForm->minorT,
|
|
psForm->tabHiLite - psForm->numMajor, pColours,TAB_MINOR,psForm->tabMinorGap);
|
|
break;
|
|
/* case WFORM_TABNONE - no minor tabs so nothing to display */
|
|
}
|
|
}
|