reactos/rosapps/lib/dflat32/popdown.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

397 lines
11 KiB
C

/* ------------- popdown.c ----------- */
#include "dflat32/dflat.h"
static int SelectionWidth(struct PopDown *);
static int py = -1;
/* ------------ CREATE_WINDOW Message ------------- */
static int CreateWindowMsg(DFWINDOW wnd)
{
int rtn, adj;
ClearAttribute (wnd,
HASTITLEBAR |
VSCROLLBAR |
MOVEABLE |
SIZEABLE |
HSCROLLBAR);
/* ------ adjust to keep popdown on screen ----- */
adj = DfGetScreenHeight()-1-wnd->rc.bt;
if (adj < 0)
{
wnd->rc.tp += adj;
wnd->rc.bt += adj;
}
adj = DfGetScreenWidth()-1-wnd->rc.rt;
if (adj < 0)
{
wnd->rc.lf += adj;
wnd->rc.rt += adj;
}
rtn = BaseWndProc(POPDOWNMENU, wnd, CREATE_WINDOW, 0, 0);
DfSendMessage(wnd, CAPTURE_MOUSE, 0, 0);
DfSendMessage(wnd, CAPTURE_KEYBOARD, 0, 0);
DfSendMessage(NULL, SAVE_CURSOR, 0, 0);
DfSendMessage(NULL, HIDE_CURSOR, 0, 0);
wnd->oldFocus = inFocus;
inFocus = wnd;
return rtn;
}
/* --------- LEFT_BUTTON Message --------- */
static void LeftButtonMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
int my = (int) p2 - GetTop(wnd);
if (InsideRect(p1, p2, ClientRect(wnd))) {
if (my != py) {
DfSendMessage(wnd, LB_SELECTION,
(PARAM) wnd->wtop+my-1, TRUE);
py = my;
}
}
else if ((int)p2 == GetTop(GetParent(wnd)))
if (GetClass(GetParent(wnd)) == MENUBAR)
DfPostMessage(GetParent(wnd), LEFT_BUTTON, p1, p2);
}
/* -------- BUTTON_RELEASED Message -------- */
static BOOL ButtonReleasedMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
py = -1;
if (InsideRect((int)p1, (int)p2, ClientRect(wnd))) {
int sel = (int)p2 - GetClientTop(wnd);
if (*TextLine(wnd, sel) != LINE)
DfSendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
}
else {
DFWINDOW pwnd = GetParent(wnd);
if (GetClass(pwnd) == MENUBAR && (int)p2==GetTop(pwnd))
return FALSE;
if ((int)p1 == GetLeft(pwnd)+2)
return FALSE;
DfSendMessage(wnd, CLOSE_WINDOW, 0, 0);
return TRUE;
}
return FALSE;
}
/* --------- PAINT Message -------- */
static void PaintMsg(DFWINDOW wnd)
{
int wd;
unsigned char sep[80], *cp = sep;
unsigned char sel[80];
struct PopDown *ActivePopDown;
struct PopDown *pd1;
ActivePopDown = pd1 = wnd->mnu->Selections;
wd = MenuWidth(ActivePopDown)-2;
while (wd--)
*cp++ = LINE;
*cp = '\0';
DfSendMessage(wnd, CLEARTEXT, 0, 0);
wnd->selection = wnd->mnu->Selection;
while (pd1->SelectionTitle != NULL) {
if (*pd1->SelectionTitle == LINE)
DfSendMessage(wnd, ADDTEXT, (PARAM) sep, 0);
else {
int len;
memset(sel, '\0', sizeof sel);
if (pd1->Attrib & INACTIVE)
/* ------ inactive menu selection ----- */
sprintf(sel, "%c%c%c",
CHANGECOLOR,
wnd->WindowColors [HILITE_COLOR] [FG]|0x80,
wnd->WindowColors [STD_COLOR] [BG]|0x80);
strcat(sel, " ");
if (pd1->Attrib & CHECKED)
/* ---- paint the toggle checkmark ---- */
sel[strlen(sel)-1] = CHECKMARK;
len=CopyCommand(sel+strlen(sel),pd1->SelectionTitle,
pd1->Attrib & INACTIVE,
wnd->WindowColors [STD_COLOR] [BG]);
if (pd1->Accelerator) {
/* ---- paint accelerator key ---- */
int i;
int wd1 = 2+SelectionWidth(ActivePopDown) -
strlen(pd1->SelectionTitle);
for (i = 0; keys[i].keylabel; i++) {
if (keys[i].keycode == pd1->Accelerator) {
while (wd1--)
strcat(sel, " ");
sprintf(sel+strlen(sel), "[%s]",
keys[i].keylabel);
break;
}
}
}
if (pd1->Attrib & CASCADED) {
/* ---- paint cascaded menu token ---- */
if (!pd1->Accelerator) {
wd = MenuWidth(ActivePopDown)-len+1;
while (wd--)
strcat(sel, " ");
}
sel[strlen(sel)-1] = CASCADEPOINTER;
}
else
strcat(sel, " ");
strcat(sel, " ");
sel[strlen(sel)-1] = RESETCOLOR;
DfSendMessage(wnd, ADDTEXT, (PARAM) sel, 0);
}
pd1++;
}
}
/* ---------- BORDER Message ----------- */
static int BorderMsg(DFWINDOW wnd)
{
int i, rtn = TRUE;
DFWINDOW currFocus;
if (wnd->mnu != NULL) {
currFocus = inFocus;
inFocus = NULL;
rtn = BaseWndProc(POPDOWNMENU, wnd, BORDER, 0, 0);
inFocus = currFocus;
for (i = 0; i < ClientHeight(wnd); i++) {
if (*TextLine(wnd, i) == LINE) {
wputch(wnd, LEDGE, 0, i+1);
wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1);
}
}
}
return rtn;
}
/* -------------- LB_CHOOSE Message -------------- */
static void LBChooseMsg(DFWINDOW wnd, PARAM p1)
{
struct PopDown *ActivePopDown = wnd->mnu->Selections;
if (ActivePopDown != NULL) {
int *attr = &(ActivePopDown+(int)p1)->Attrib;
wnd->mnu->Selection = (int)p1;
if (!(*attr & INACTIVE)) {
if (*attr & TOGGLE)
*attr ^= CHECKED;
DfPostMessage(GetParent(wnd), DFM_COMMAND,
(ActivePopDown+(int)p1)->ActionId, p1);
}
else
beep();
}
}
/* ---------- KEYBOARD Message --------- */
static BOOL KeyboardMsg(DFWINDOW wnd, PARAM p1, PARAM p2)
{
struct PopDown *ActivePopDown = wnd->mnu->Selections;
if (wnd->mnu != NULL)
{
if (ActivePopDown != NULL)
{
int c = (int)p1;
int sel = 0;
int a;
struct PopDown *pd = ActivePopDown;
if ((c & OFFSET) == 0)
c = tolower(c);
a = AltConvert(c);
while (pd->SelectionTitle != NULL)
{
char *cp = strchr(pd->SelectionTitle, SHORTCUTCHAR);
/* FIXME: AltConvert bug !! */
if ((cp && tolower(*(cp+1)) == c) ||
// (a && tolower(*(cp+1)) == a) ||
pd->Accelerator == c)
{
DfPostMessage(wnd, LB_SELECTION, sel, 0);
DfPostMessage(wnd, LB_CHOOSE, sel, TRUE);
return TRUE;
}
pd++;
sel++;
}
}
}
switch ((int)p1)
{
case F1:
if (ActivePopDown == NULL)
DfSendMessage(GetParent(wnd), KEYBOARD, p1, p2);
else
DisplayHelp(wnd,
(ActivePopDown+wnd->selection)->help);
return TRUE;
case ESC:
DfSendMessage(wnd, CLOSE_WINDOW, 0, 0);
return TRUE;
case FWD:
case BS:
if (GetClass(GetParent(wnd)) == MENUBAR)
DfPostMessage(GetParent(wnd), KEYBOARD, p1, p2);
return TRUE;
case UP:
if (wnd->selection == 0) {
if (wnd->wlines == ClientHeight(wnd)) {
DfPostMessage(wnd, LB_SELECTION,
wnd->wlines-1, FALSE);
return TRUE;
}
}
break;
case DN:
if (wnd->selection == wnd->wlines-1) {
if (wnd->wlines == ClientHeight(wnd)) {
DfPostMessage(wnd, LB_SELECTION, 0, FALSE);
return TRUE;
}
}
break;
case HOME:
case END:
case '\r':
break;
default:
return TRUE;
}
return FALSE;
}
/* ----------- CLOSE_WINDOW Message ---------- */
static int CloseWindowMsg(DFWINDOW wnd)
{
int rtn;
DFWINDOW pwnd = GetParent(wnd);
DfSendMessage(wnd, RELEASE_MOUSE, 0, 0);
DfSendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
DfSendMessage(NULL, RESTORE_CURSOR, 0, 0);
inFocus = wnd->oldFocus;
rtn = BaseWndProc(POPDOWNMENU, wnd, CLOSE_WINDOW, 0, 0);
DfSendMessage(pwnd, CLOSE_POPDOWN, 0, 0);
return rtn;
}
/* - Window processing module for POPDOWNMENU window class - */
int PopDownProc(DFWINDOW wnd, DFMESSAGE msg, PARAM p1, PARAM p2)
{
switch (msg) {
case CREATE_WINDOW:
return CreateWindowMsg(wnd);
case LEFT_BUTTON:
LeftButtonMsg(wnd, p1, p2);
return FALSE;
case DOUBLE_CLICK:
return TRUE;
case LB_SELECTION:
if (*TextLine(wnd, (int)p1) == LINE)
return TRUE;
wnd->mnu->Selection = (int)p1;
break;
case DFM_BUTTON_RELEASED:
if (ButtonReleasedMsg(wnd, p1, p2))
return TRUE;
break;
case BUILD_SELECTIONS:
wnd->mnu = (void *) p1;
wnd->selection = wnd->mnu->Selection;
break;
case PAINT:
if (wnd->mnu == NULL)
return TRUE;
PaintMsg(wnd);
break;
case BORDER:
return BorderMsg(wnd);
case LB_CHOOSE:
LBChooseMsg(wnd, p1);
return TRUE;
case KEYBOARD:
if (KeyboardMsg(wnd, p1, p2))
return TRUE;
break;
case CLOSE_WINDOW:
return CloseWindowMsg(wnd);
default:
break;
}
return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
}
/* --------- compute menu height -------- */
int MenuHeight(struct PopDown *pd)
{
int ht = 0;
while (pd[ht].SelectionTitle != NULL)
ht++;
return ht+2;
}
/* --------- compute menu width -------- */
int MenuWidth(struct PopDown *pd)
{
int wd = 0, i;
int len = 0;
wd = SelectionWidth(pd);
while (pd->SelectionTitle != NULL) {
if (pd->Accelerator) {
for (i = 0; keys[i].keylabel; i++)
if (keys[i].keycode == pd->Accelerator) {
len = max(len, (int)(2+strlen(keys[i].keylabel)));
break;
}
}
if (pd->Attrib & CASCADED)
len = max(len, 2);
pd++;
}
return wd+5+len;
}
/* ---- compute the maximum selection width in a menu ---- */
static int SelectionWidth(struct PopDown *pd)
{
int wd = 0;
while (pd->SelectionTitle != NULL) {
int len = strlen(pd->SelectionTitle)-1;
wd = max(wd, len);
pd++;
}
return wd;
}
/* ----- copy a menu command to a display buffer ---- */
int CopyCommand(unsigned char *dest, unsigned char *src,
int skipcolor, int bg)
{
unsigned char *d = dest;
while (*src && *src != '\n') {
if (*src == SHORTCUTCHAR) {
src++;
if (!skipcolor) {
*dest++ = CHANGECOLOR;
*dest++ = cfg.clr[POPDOWNMENU]
[HILITE_COLOR] [BG] | 0x80;
*dest++ = bg | 0x80;
*dest++ = *src++;
*dest++ = RESETCOLOR;
}
}
else
*dest++ = *src++;
}
return (int) (dest - d);
}
/* EOF */