mirror of
https://github.com/reactos/reactos.git
synced 2024-11-09 16:20:37 +00:00
397 lines
11 KiB
C
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 */
|