reactos/rosapps/lib/dflat32/dialbox.c
Steven Edwards 81345fd691 Still working on making dflat32 a dll. Alot of this will be cleaned up in the
next few weeks. I'm going through the DFLAT api doc and fixing the export
names and then going to try to build a simple hello dflat application.

svn path=/trunk/; revision=2844
2002-04-14 10:15:06 +00:00

793 lines
21 KiB
C

/* ----------------- dialbox.c -------------- */
#include "dflat32/dflat.h"
static int inFocusCommand(DBOX *);
static void dbShortcutKeys(DBOX *, int);
static int ControlProc(DFWINDOW, DFMESSAGE, PARAM, PARAM);
static void FirstFocus(DBOX *db);
static void NextFocus(DBOX *db);
static void PrevFocus(DBOX *db);
static CTLWINDOW *AssociatedControl(DBOX *, enum commands);
static BOOL SysMenuOpen;
static DBOX **dbs = NULL;
static int dbct = 0;
/* --- clear all heap allocations to control text fields --- */
void ClearDialogBoxes(void)
{
int i;
for (i = 0; i < dbct; i++)
{
CTLWINDOW *ct = (*(dbs+i))->ctl;
while (ct->class)
{
if ((ct->class == EDITBOX ||
ct->class == COMBOBOX) &&
ct->itext != NULL)
{
free(ct->itext);
}
ct++;
}
}
if (dbs != NULL)
{
free(dbs);
dbs = NULL;
}
dbct = 0;
}
/* -------- CREATE_WINDOW Message --------- */
static int CreateWindowMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
DBOX *db = wnd->extension;
CTLWINDOW *ct = db->ctl;
DFWINDOW cwnd;
int rtn, i;
/* ---- build a table of processed dialog boxes ---- */
for (i = 0; i < dbct; i++)
if (db == dbs[i])
break;
if (i == dbct) {
dbs = DFrealloc(dbs, sizeof(DBOX *) * (dbct+1));
*(dbs + dbct++) = db;
}
rtn = BaseWndProc(DIALOG, wnd, CREATE_WINDOW, p1, p2);
ct = db->ctl;
while (ct->class) {
int attrib = 0;
if (TestAttribute(wnd, NOCLIP))
attrib |= NOCLIP;
if (wnd->Modal)
attrib |= SAVESELF;
ct->setting = ct->isetting;
if (ct->class == EDITBOX && ct->dwnd.h > 1)
attrib |= (MULTILINE | HASBORDER);
else if ((ct->class == LISTBOX || ct->class == TEXTBOX) &&
ct->dwnd.h > 2)
attrib |= HASBORDER;
cwnd = DfCreateWindow(ct->class,
ct->dwnd.title,
ct->dwnd.x+GetClientLeft(wnd),
ct->dwnd.y+GetClientTop(wnd),
ct->dwnd.h,
ct->dwnd.w,
ct,
wnd,
ControlProc,
attrib);
if ((ct->class == EDITBOX ||
ct->class == COMBOBOX) &&
ct->itext != NULL)
DfSendMessage(cwnd, SETTEXT, (PARAM) ct->itext, 0);
ct++;
}
return rtn;
}
/* -------- LEFT_BUTTON Message --------- */
static BOOL LeftButtonMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
DBOX *db = wnd->extension;
CTLWINDOW *ct = db->ctl;
if (WindowSizing || WindowMoving)
return TRUE;
if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd))) {
DfPostMessage(wnd, KEYBOARD, ' ', ALTKEY);
return TRUE;
}
while (ct->class) {
DFWINDOW cwnd = ct->wnd;
if (ct->class == COMBOBOX) {
if (p2 == GetTop(cwnd)) {
if (p1 == GetRight(cwnd)+1) {
DfSendMessage(cwnd, LEFT_BUTTON, p1, p2);
return TRUE;
}
}
if (GetClass(inFocus) == LISTBOX)
DfSendMessage(wnd, SETFOCUS, TRUE, 0);
}
else if (ct->class == SPINBUTTON) {
if (p2 == GetTop(cwnd)) {
if (p1 == GetRight(cwnd)+1 ||
p1 == GetRight(cwnd)+2) {
DfSendMessage(cwnd, LEFT_BUTTON, p1, p2);
return TRUE;
}
}
}
ct++;
}
return FALSE;
}
/* -------- KEYBOARD Message --------- */
static BOOL KeyboardMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
DBOX *db = wnd->extension;
CTLWINDOW *ct;
if (WindowMoving || WindowSizing)
return FALSE;
switch ((int)p1) {
case F1:
ct = GetControl(inFocus);
if (ct != NULL)
if (DisplayHelp(wnd, ct->help))
return TRUE;
break;
case SHIFT_HT:
case BS:
case UP:
PrevFocus(db);
break;
case ALT_F6:
case '\t':
case FWD:
case DN:
NextFocus(db);
break;
case ' ':
if (((int)p2 & ALTKEY) &&
TestAttribute(wnd, CONTROLBOX)) {
SysMenuOpen = TRUE;
BuildSystemMenu(wnd);
}
break;
case CTRL_F4:
case ESC:
DfSendMessage(wnd, DFM_COMMAND, ID_CANCEL, 0);
break;
default:
/* ------ search all the shortcut keys ----- */
dbShortcutKeys(db, (int) p1);
break;
}
return wnd->Modal;
}
/* -------- COMMAND Message --------- */
static BOOL CommandMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
DBOX *db = wnd->extension;
switch ((int) p1) {
case ID_OK:
case ID_CANCEL:
if ((int)p2 != 0)
return TRUE;
wnd->ReturnCode = (int) p1;
if (wnd->Modal)
DfPostMessage(wnd, ENDDIALOG, 0, 0);
else
DfSendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
return TRUE;
case ID_HELP:
if ((int)p2 != 0)
return TRUE;
return DisplayHelp(wnd, db->HelpName);
default:
break;
}
return FALSE;
}
/* ----- window-processing module, DIALOG window class ----- */
int DialogProc(DFWINDOW wnd, DFMESSAGE msg, PARAM p1, PARAM p2)
{
int rtn;
DBOX *db = wnd->extension;
switch (msg) {
case CREATE_WINDOW:
return CreateWindowMsg(wnd, p1, p2);
case SHIFT_CHANGED:
if (wnd->Modal)
return TRUE;
break;
case LEFT_BUTTON:
if (LeftButtonMsg(wnd, p1, p2))
return TRUE;
break;
case KEYBOARD:
if (KeyboardMsg(wnd, p1, p2))
return TRUE;
break;
case CLOSE_POPDOWN:
SysMenuOpen = FALSE;
break;
case LB_SELECTION:
case LB_CHOOSE:
if (SysMenuOpen)
return TRUE;
DfSendMessage(wnd, DFM_COMMAND, inFocusCommand(db), msg);
break;
case DFM_COMMAND:
if (CommandMsg(wnd, p1, p2))
return TRUE;
break;
case PAINT:
p2 = TRUE;
break;
case MOVE:
case DFM_SIZE:
rtn = BaseWndProc(DIALOG, wnd, msg, p1, p2);
if (wnd->dfocus != NULL)
DfSendMessage(wnd->dfocus, SETFOCUS, TRUE, 0);
return rtn;
case CLOSE_WINDOW:
if (!p1)
{
DfSendMessage(wnd, DFM_COMMAND, ID_CANCEL, 0);
return TRUE;
}
break;
default:
break;
}
return BaseWndProc(DIALOG, wnd, msg, p1, p2);
}
/* ------- create and execute a dialog box ---------- */
BOOL DfDialogBox(DFWINDOW wnd, DBOX *db, BOOL Modal,
int (*wndproc)(struct window *, enum messages, PARAM, PARAM))
{
BOOL rtn;
int x = db->dwnd.x, y = db->dwnd.y;
DFWINDOW DialogWnd;
if (!Modal && wnd != NULL)
{
x += GetLeft(wnd);
y += GetTop(wnd);
}
DialogWnd = DfCreateWindow(DIALOG,
db->dwnd.title,
x, y,
db->dwnd.h,
db->dwnd.w,
db,
wnd,
wndproc,
Modal ? SAVESELF : 0);
DialogWnd->Modal = Modal;
FirstFocus(db);
DfPostMessage(DialogWnd, INITIATE_DIALOG, 0, 0);
if (Modal)
{
DfSendMessage(DialogWnd, CAPTURE_MOUSE, 0, 0);
DfSendMessage(DialogWnd, CAPTURE_KEYBOARD, 0, 0);
while (DfDispatchMessage ())
;
rtn = DialogWnd->ReturnCode == ID_OK;
DfSendMessage(DialogWnd, RELEASE_MOUSE, 0, 0);
DfSendMessage(DialogWnd, RELEASE_KEYBOARD, 0, 0);
DfSendMessage(DialogWnd, CLOSE_WINDOW, TRUE, 0);
return rtn;
}
return FALSE;
}
/* ----- return command code of in-focus control window ---- */
static int inFocusCommand(DBOX *db)
{
CTLWINDOW *ct = db->ctl;
while (ct->class) {
if (ct->wnd == inFocus)
return ct->command;
ct++;
}
return -1;
}
/* -------- find a specified control structure ------- */
CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class)
{
CTLWINDOW *ct = db->ctl;
while (ct->class)
{
if (ct->class == class)
if (cmd == ct->command)
return ct;
ct++;
}
return NULL;
}
/* ---- return the window handle of a specified command ---- */
DFWINDOW ControlWindow(DBOX *db, enum commands cmd)
{
CTLWINDOW *ct = db->ctl;
while (ct->class)
{
if (ct->class != TEXT && cmd == ct->command)
return ct->wnd;
ct++;
}
return NULL;
}
/* --- return a pointer to the control structure that matches a window --- */
CTLWINDOW *WindowControl(DBOX *db, DFWINDOW wnd)
{
CTLWINDOW *ct = db->ctl;
while (ct->class)
{
if (ct->wnd == wnd)
return ct;
ct++;
}
return NULL;
}
/* ---- set a control ON or OFF ----- */
void ControlSetting(DBOX *db, enum commands cmd,
int class, int setting)
{
CTLWINDOW *ct = FindCommand(db, cmd, class);
if (ct != NULL) {
ct->isetting = setting;
if (ct->wnd != NULL)
ct->setting = setting;
}
}
/* ---- return pointer to the text of a control window ---- */
char *GetDlgTextString(DBOX *db,enum commands cmd,DFCLASS class)
{
CTLWINDOW *ct = FindCommand(db, cmd, class);
if (ct != NULL)
return ct->itext;
else
return NULL;
}
/* ------- set the text of a control specification ------ */
void SetDlgTextString(DBOX *db, enum commands cmd,
char *text, DFCLASS class)
{
CTLWINDOW *ct = FindCommand(db, cmd, class);
if (ct != NULL) {
ct->itext = DFrealloc(ct->itext, strlen(text)+1);
strcpy(ct->itext, text);
}
}
/* ------- set the text of a control window ------ */
void PutItemText(DFWINDOW wnd, enum commands cmd, char *text)
{
CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
if (ct == NULL)
ct = FindCommand(wnd->extension, cmd, TEXTBOX);
if (ct == NULL)
ct = FindCommand(wnd->extension, cmd, COMBOBOX);
if (ct == NULL)
ct = FindCommand(wnd->extension, cmd, LISTBOX);
if (ct == NULL)
ct = FindCommand(wnd->extension, cmd, SPINBUTTON);
if (ct == NULL)
ct = FindCommand(wnd->extension, cmd, TEXT);
if (ct != NULL) {
DFWINDOW cwnd = (DFWINDOW) (ct->wnd);
switch (ct->class) {
case COMBOBOX:
case EDITBOX:
DfSendMessage(cwnd, CLEARTEXT, 0, 0);
DfSendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
if (!isMultiLine(cwnd))
DfSendMessage(cwnd, PAINT, 0, 0);
break;
case LISTBOX:
case TEXTBOX:
case SPINBUTTON:
DfSendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
break;
case TEXT: {
DfSendMessage(cwnd, CLEARTEXT, 0, 0);
DfSendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
DfSendMessage(cwnd, PAINT, 0, 0);
break;
}
default:
break;
}
}
}
/* ------- get the text of a control window ------ */
void GetItemText(DFWINDOW wnd, enum commands cmd,
char *text, int len)
{
CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
unsigned char *cp;
if (ct == NULL)
ct = FindCommand(wnd->extension, cmd, COMBOBOX);
if (ct == NULL)
ct = FindCommand(wnd->extension, cmd, TEXTBOX);
if (ct == NULL)
ct = FindCommand(wnd->extension, cmd, TEXT);
if (ct != NULL) {
DFWINDOW cwnd = (DFWINDOW) (ct->wnd);
if (cwnd != NULL) {
switch (ct->class) {
case TEXT:
if (GetText(cwnd) != NULL) {
cp = strchr(GetText(cwnd), '\n');
if (cp != NULL)
len = (int) (cp - GetText(cwnd));
strncpy(text, GetText(cwnd), len);
*(text+len) = '\0';
}
break;
case TEXTBOX:
if (GetText(cwnd) != NULL)
strncpy(text, GetText(cwnd), len);
break;
case COMBOBOX:
case EDITBOX:
DfSendMessage(cwnd,GETTEXT,(PARAM)text,len);
break;
default:
break;
}
}
}
}
/* ------- set the text of a listbox control window ------ */
void GetDlgListText(DFWINDOW wnd, char *text, enum commands cmd)
{
CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX);
int sel = DfSendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0);
DfSendMessage(ct->wnd, DFM_LB_GETTEXT, (PARAM) text, sel);
}
/* -- find control structure associated with text control -- */
static CTLWINDOW *AssociatedControl(DBOX *db,enum commands Tcmd)
{
CTLWINDOW *ct = db->ctl;
while (ct->class) {
if (ct->class != TEXT)
if (ct->command == Tcmd)
break;
ct++;
}
return ct;
}
/* --- process dialog box shortcut keys --- */
static void dbShortcutKeys(DBOX *db, int ky)
{
CTLWINDOW *ct;
int ch = AltConvert(ky);
if (ch != 0) {
ct = db->ctl;
while (ct->class) {
char *cp = ct->itext;
while (cp && *cp) {
if (*cp == SHORTCUTCHAR &&
tolower(*(cp+1)) == ch) {
if (ct->class == TEXT)
ct = AssociatedControl(db, ct->command);
if (ct->class == RADIOBUTTON)
SetRadioButton(db, ct);
else if (ct->class == CHECKBOX) {
ct->setting ^= ON;
DfSendMessage(ct->wnd, PAINT, 0, 0);
}
else if (ct->class) {
DfSendMessage(ct->wnd, SETFOCUS, TRUE, 0);
if (ct->class == BUTTON)
DfSendMessage(ct->wnd,KEYBOARD,'\r',0);
}
return;
}
cp++;
}
ct++;
}
}
}
/* --- dynamically add or remove scroll bars
from a control window ---- */
void SetScrollBars(DFWINDOW wnd)
{
int oldattr = GetAttribute(wnd);
if (wnd->wlines > ClientHeight(wnd))
AddAttribute(wnd, VSCROLLBAR);
else
ClearAttribute(wnd, VSCROLLBAR);
if (wnd->textwidth > ClientWidth(wnd))
AddAttribute(wnd, HSCROLLBAR);
else
ClearAttribute(wnd, HSCROLLBAR);
if (GetAttribute(wnd) != oldattr)
DfSendMessage(wnd, BORDER, 0, 0);
}
/* ------- CREATE_WINDOW Message (Control) ----- */
static void CtlCreateWindowMsg(DFWINDOW wnd)
{
CTLWINDOW *ct;
ct = wnd->ct = wnd->extension;
wnd->extension = NULL;
if (ct != NULL)
ct->wnd = wnd;
}
/* ------- KEYBOARD Message (Control) ----- */
static BOOL CtlKeyboardMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
CTLWINDOW *ct = GetControl(wnd);
switch ((int) p1) {
case F1:
if (WindowMoving || WindowSizing)
break;
if (!DisplayHelp(wnd, ct->help))
DfSendMessage(GetParent(wnd),DFM_COMMAND,ID_HELP,0);
return TRUE;
case ' ':
if (!((int)p2 & ALTKEY))
break;
case ALT_F6:
case CTRL_F4:
case ALT_F4:
DfPostMessage(GetParent(wnd), KEYBOARD, p1, p2);
return TRUE;
default:
break;
}
if (GetClass(wnd) == EDITBOX)
if (isMultiLine(wnd))
return FALSE;
switch ((int) p1) {
case UP:
if (!isDerivedFrom(wnd, LISTBOX)) {
p1 = CTRL_FIVE;
p2 = LEFTSHIFT;
}
break;
case BS:
if (!isDerivedFrom(wnd, EDITBOX)) {
p1 = CTRL_FIVE;
p2 = LEFTSHIFT;
}
break;
case DN:
if (!isDerivedFrom(wnd, LISTBOX) &&
!isDerivedFrom(wnd, COMBOBOX))
p1 = '\t';
break;
case FWD:
if (!isDerivedFrom(wnd, EDITBOX))
p1 = '\t';
break;
case '\r':
if (isDerivedFrom(wnd, EDITBOX))
if (isMultiLine(wnd))
break;
if (isDerivedFrom(wnd, BUTTON))
break;
DfSendMessage(GetParent(wnd), DFM_COMMAND, ID_OK, 0);
return TRUE;
default:
break;
}
return FALSE;
}
/* ------- CLOSE_WINDOW Message (Control) ----- */
static void CtlCloseWindowMsg(DFWINDOW wnd)
{
CTLWINDOW *ct = GetControl(wnd);
if (ct != NULL) {
ct->wnd = NULL;
if (GetParent(wnd)->ReturnCode == ID_OK) {
if (ct->class == EDITBOX || ct->class == COMBOBOX) {
if (wnd->TextChanged) {
ct->itext=DFrealloc(ct->itext,strlen(wnd->text)+1);
strcpy(ct->itext, wnd->text);
if (!isMultiLine(wnd)) {
char *cp = ct->itext+strlen(ct->itext)-1;
if (*cp == '\n')
*cp = '\0';
}
}
}
else if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
ct->isetting = ct->setting;
}
}
}
static void FixColors(DFWINDOW wnd)
{
CTLWINDOW *ct = wnd->ct;
if (ct->class != BUTTON)
{
if (ct->class != SPINBUTTON && ct->class != COMBOBOX)
{
wnd->WindowColors[FRAME_COLOR][FG] =
GetParent(wnd)->WindowColors[FRAME_COLOR][FG];
wnd->WindowColors[FRAME_COLOR][BG] =
GetParent(wnd)->WindowColors[FRAME_COLOR][BG];
if (ct->class != EDITBOX && ct->class != LISTBOX)
{
wnd->WindowColors[STD_COLOR][FG] =
GetParent(wnd)->WindowColors[STD_COLOR][FG];
wnd->WindowColors[STD_COLOR][BG] =
GetParent(wnd)->WindowColors[STD_COLOR][BG];
}
}
}
}
/* -- generic window processor used by dialog box controls -- */
static int ControlProc(DFWINDOW wnd,DFMESSAGE msg,PARAM p1,PARAM p2)
{
DBOX *db;
if (wnd == NULL)
return FALSE;
db = GetParent(wnd) ? GetParent(wnd)->extension : NULL;
switch (msg) {
case CREATE_WINDOW:
CtlCreateWindowMsg(wnd);
break;
case KEYBOARD:
if (CtlKeyboardMsg(wnd, p1, p2))
return TRUE;
break;
case PAINT:
FixColors(wnd);
if (GetClass(wnd) == EDITBOX ||
GetClass(wnd) == LISTBOX ||
GetClass(wnd) == TEXTBOX)
SetScrollBars(wnd);
break;
case BORDER:
FixColors(wnd);
if (GetClass(wnd) == EDITBOX) {
DFWINDOW oldFocus = inFocus;
inFocus = NULL;
DefaultWndProc(wnd, msg, p1, p2);
inFocus = oldFocus;
return TRUE;
}
break;
case SETFOCUS: {
DFWINDOW pwnd = GetParent(wnd);
if (p1)
{
DefaultWndProc(wnd, msg, p1, p2);
if (pwnd != NULL)
{
pwnd->dfocus = wnd;
DfSendMessage(pwnd, DFM_COMMAND,
inFocusCommand(db), ENTERFOCUS);
}
return TRUE;
}
else
DfSendMessage(pwnd, DFM_COMMAND,
inFocusCommand(db), LEAVEFOCUS);
break;
}
case CLOSE_WINDOW:
CtlCloseWindowMsg(wnd);
break;
default:
break;
}
return DefaultWndProc(wnd, msg, p1, p2);
}
/* ---- change the focus to the first control --- */
static void FirstFocus(DBOX *db)
{
CTLWINDOW *ct = db->ctl;
if (ct != NULL)
{
while (ct->class == TEXT || ct->class == BOX) {
ct++;
if (ct->class == 0)
return;
}
DfSendMessage(ct->wnd, SETFOCUS, TRUE, 0);
}
}
/* ---- change the focus to the next control --- */
static void NextFocus(DBOX *db)
{
CTLWINDOW *ct = WindowControl(db, inFocus);
int looped = 0;
if (ct != NULL)
{
do
{
ct++;
if (ct->class == 0)
{
if (looped)
return;
looped++;
ct = db->ctl;
}
} while (ct->class == TEXT || ct->class == BOX);
DfSendMessage(ct->wnd, SETFOCUS, TRUE, 0);
}
}
/* ---- change the focus to the previous control --- */
static void PrevFocus(DBOX *db)
{
CTLWINDOW *ct = WindowControl(db, inFocus);
int looped = 0;
if (ct != NULL)
{
do
{
if (ct == db->ctl)
{
if (looped)
return;
looped++;
while (ct->class)
ct++;
}
--ct;
} while (ct->class == TEXT || ct->class == BOX);
DfSendMessage(ct->wnd, SETFOCUS, TRUE, 0);
}
}
void SetFocusCursor(DFWINDOW wnd)
{
if (wnd == inFocus)
{
DfSendMessage(NULL, SHOW_CURSOR, 0, 0);
DfSendMessage(wnd, KEYBOARD_CURSOR, 1, 0);
}
}
/* EOF */