1 /* ------------- popdown.c ----------- */
3 #include "dflat32/dflat.h"
5 static int SelectionWidth(struct PopDown
*);
8 /* ------------ CREATE_WINDOW Message ------------- */
9 static int CreateWindowMsg(DFWINDOW wnd
)
20 /* ------ adjust to keep popdown on screen ----- */
21 adj
= DfGetScreenHeight()-1-wnd
->rc
.bt
;
27 adj
= DfGetScreenWidth()-1-wnd
->rc
.rt
;
34 rtn
= BaseWndProc(POPDOWNMENU
, wnd
, CREATE_WINDOW
, 0, 0);
35 DfSendMessage(wnd
, CAPTURE_MOUSE
, 0, 0);
36 DfSendMessage(wnd
, CAPTURE_KEYBOARD
, 0, 0);
37 DfSendMessage(NULL
, SAVE_CURSOR
, 0, 0);
38 DfSendMessage(NULL
, HIDE_CURSOR
, 0, 0);
39 wnd
->oldFocus
= inFocus
;
45 /* --------- LEFT_BUTTON Message --------- */
46 static void LeftButtonMsg(DFWINDOW wnd
, PARAM p1
, PARAM p2
)
48 int my
= (int) p2
- GetTop(wnd
);
49 if (InsideRect(p1
, p2
, ClientRect(wnd
))) {
51 DfSendMessage(wnd
, LB_SELECTION
,
52 (PARAM
) wnd
->wtop
+my
-1, TRUE
);
56 else if ((int)p2
== GetTop(GetParent(wnd
)))
57 if (GetClass(GetParent(wnd
)) == MENUBAR
)
58 DfPostMessage(GetParent(wnd
), LEFT_BUTTON
, p1
, p2
);
61 /* -------- BUTTON_RELEASED Message -------- */
62 static BOOL
ButtonReleasedMsg(DFWINDOW wnd
, PARAM p1
, PARAM p2
)
65 if (InsideRect((int)p1
, (int)p2
, ClientRect(wnd
))) {
66 int sel
= (int)p2
- GetClientTop(wnd
);
67 if (*TextLine(wnd
, sel
) != LINE
)
68 DfSendMessage(wnd
, LB_CHOOSE
, wnd
->selection
, 0);
71 DFWINDOW pwnd
= GetParent(wnd
);
72 if (GetClass(pwnd
) == MENUBAR
&& (int)p2
==GetTop(pwnd
))
74 if ((int)p1
== GetLeft(pwnd
)+2)
76 DfSendMessage(wnd
, CLOSE_WINDOW
, 0, 0);
82 /* --------- PAINT Message -------- */
83 static void PaintMsg(DFWINDOW wnd
)
86 unsigned char sep
[80], *cp
= sep
;
87 unsigned char sel
[80];
88 struct PopDown
*ActivePopDown
;
91 ActivePopDown
= pd1
= wnd
->mnu
->Selections
;
92 wd
= MenuWidth(ActivePopDown
)-2;
96 DfSendMessage(wnd
, CLEARTEXT
, 0, 0);
97 wnd
->selection
= wnd
->mnu
->Selection
;
98 while (pd1
->SelectionTitle
!= NULL
) {
99 if (*pd1
->SelectionTitle
== LINE
)
100 DfSendMessage(wnd
, ADDTEXT
, (PARAM
) sep
, 0);
103 memset(sel
, '\0', sizeof sel
);
104 if (pd1
->Attrib
& INACTIVE
)
105 /* ------ inactive menu selection ----- */
106 sprintf(sel
, "%c%c%c",
108 wnd
->WindowColors
[HILITE_COLOR
] [FG
]|0x80,
109 wnd
->WindowColors
[STD_COLOR
] [BG
]|0x80);
111 if (pd1
->Attrib
& CHECKED
)
112 /* ---- paint the toggle checkmark ---- */
113 sel
[strlen(sel
)-1] = CHECKMARK
;
114 len
=CopyCommand(sel
+strlen(sel
),pd1
->SelectionTitle
,
115 pd1
->Attrib
& INACTIVE
,
116 wnd
->WindowColors
[STD_COLOR
] [BG
]);
117 if (pd1
->Accelerator
) {
118 /* ---- paint accelerator key ---- */
120 int wd1
= 2+SelectionWidth(ActivePopDown
) -
121 strlen(pd1
->SelectionTitle
);
122 for (i
= 0; keys
[i
].keylabel
; i
++) {
123 if (keys
[i
].keycode
== pd1
->Accelerator
) {
126 sprintf(sel
+strlen(sel
), "[%s]",
132 if (pd1
->Attrib
& CASCADED
) {
133 /* ---- paint cascaded menu token ---- */
134 if (!pd1
->Accelerator
) {
135 wd
= MenuWidth(ActivePopDown
)-len
+1;
139 sel
[strlen(sel
)-1] = CASCADEPOINTER
;
144 sel
[strlen(sel
)-1] = RESETCOLOR
;
145 DfSendMessage(wnd
, ADDTEXT
, (PARAM
) sel
, 0);
151 /* ---------- BORDER Message ----------- */
152 static int BorderMsg(DFWINDOW wnd
)
156 if (wnd
->mnu
!= NULL
) {
159 rtn
= BaseWndProc(POPDOWNMENU
, wnd
, BORDER
, 0, 0);
161 for (i
= 0; i
< ClientHeight(wnd
); i
++) {
162 if (*TextLine(wnd
, i
) == LINE
) {
163 wputch(wnd
, LEDGE
, 0, i
+1);
164 wputch(wnd
, REDGE
, WindowWidth(wnd
)-1, i
+1);
171 /* -------------- LB_CHOOSE Message -------------- */
172 static void LBChooseMsg(DFWINDOW wnd
, PARAM p1
)
174 struct PopDown
*ActivePopDown
= wnd
->mnu
->Selections
;
175 if (ActivePopDown
!= NULL
) {
176 int *attr
= &(ActivePopDown
+(int)p1
)->Attrib
;
177 wnd
->mnu
->Selection
= (int)p1
;
178 if (!(*attr
& INACTIVE
)) {
181 DfPostMessage(GetParent(wnd
), DFM_COMMAND
,
182 (ActivePopDown
+(int)p1
)->ActionId
, p1
);
189 /* ---------- KEYBOARD Message --------- */
190 static BOOL
KeyboardMsg(DFWINDOW wnd
, PARAM p1
, PARAM p2
)
192 struct PopDown
*ActivePopDown
= wnd
->mnu
->Selections
;
194 if (wnd
->mnu
!= NULL
)
196 if (ActivePopDown
!= NULL
)
201 struct PopDown
*pd
= ActivePopDown
;
203 if ((c
& OFFSET
) == 0)
207 while (pd
->SelectionTitle
!= NULL
)
209 char *cp
= strchr(pd
->SelectionTitle
, SHORTCUTCHAR
);
211 /* FIXME: AltConvert bug !! */
212 if ((cp
&& tolower(*(cp
+1)) == c
) ||
213 // (a && tolower(*(cp+1)) == a) ||
214 pd
->Accelerator
== c
)
216 DfPostMessage(wnd
, LB_SELECTION
, sel
, 0);
217 DfPostMessage(wnd
, LB_CHOOSE
, sel
, TRUE
);
229 if (ActivePopDown
== NULL
)
230 DfSendMessage(GetParent(wnd
), KEYBOARD
, p1
, p2
);
233 (ActivePopDown
+wnd
->selection
)->help
);
236 DfSendMessage(wnd
, CLOSE_WINDOW
, 0, 0);
240 if (GetClass(GetParent(wnd
)) == MENUBAR
)
241 DfPostMessage(GetParent(wnd
), KEYBOARD
, p1
, p2
);
244 if (wnd
->selection
== 0) {
245 if (wnd
->wlines
== ClientHeight(wnd
)) {
246 DfPostMessage(wnd
, LB_SELECTION
,
247 wnd
->wlines
-1, FALSE
);
253 if (wnd
->selection
== wnd
->wlines
-1) {
254 if (wnd
->wlines
== ClientHeight(wnd
)) {
255 DfPostMessage(wnd
, LB_SELECTION
, 0, FALSE
);
270 /* ----------- CLOSE_WINDOW Message ---------- */
271 static int CloseWindowMsg(DFWINDOW wnd
)
274 DFWINDOW pwnd
= GetParent(wnd
);
275 DfSendMessage(wnd
, RELEASE_MOUSE
, 0, 0);
276 DfSendMessage(wnd
, RELEASE_KEYBOARD
, 0, 0);
277 DfSendMessage(NULL
, RESTORE_CURSOR
, 0, 0);
278 inFocus
= wnd
->oldFocus
;
279 rtn
= BaseWndProc(POPDOWNMENU
, wnd
, CLOSE_WINDOW
, 0, 0);
280 DfSendMessage(pwnd
, CLOSE_POPDOWN
, 0, 0);
284 /* - Window processing module for POPDOWNMENU window class - */
285 int PopDownProc(DFWINDOW wnd
, DFMESSAGE msg
, PARAM p1
, PARAM p2
)
289 return CreateWindowMsg(wnd
);
291 LeftButtonMsg(wnd
, p1
, p2
);
296 if (*TextLine(wnd
, (int)p1
) == LINE
)
298 wnd
->mnu
->Selection
= (int)p1
;
300 case DFM_BUTTON_RELEASED
:
301 if (ButtonReleasedMsg(wnd
, p1
, p2
))
304 case BUILD_SELECTIONS
:
305 wnd
->mnu
= (void *) p1
;
306 wnd
->selection
= wnd
->mnu
->Selection
;
309 if (wnd
->mnu
== NULL
)
314 return BorderMsg(wnd
);
316 LBChooseMsg(wnd
, p1
);
319 if (KeyboardMsg(wnd
, p1
, p2
))
323 return CloseWindowMsg(wnd
);
327 return BaseWndProc(POPDOWNMENU
, wnd
, msg
, p1
, p2
);
330 /* --------- compute menu height -------- */
331 int MenuHeight(struct PopDown
*pd
)
334 while (pd
[ht
].SelectionTitle
!= NULL
)
339 /* --------- compute menu width -------- */
340 int MenuWidth(struct PopDown
*pd
)
345 wd
= SelectionWidth(pd
);
346 while (pd
->SelectionTitle
!= NULL
) {
347 if (pd
->Accelerator
) {
348 for (i
= 0; keys
[i
].keylabel
; i
++)
349 if (keys
[i
].keycode
== pd
->Accelerator
) {
350 len
= max(len
, (int)(2+strlen(keys
[i
].keylabel
)));
354 if (pd
->Attrib
& CASCADED
)
361 /* ---- compute the maximum selection width in a menu ---- */
362 static int SelectionWidth(struct PopDown
*pd
)
365 while (pd
->SelectionTitle
!= NULL
) {
366 int len
= strlen(pd
->SelectionTitle
)-1;
373 /* ----- copy a menu command to a display buffer ---- */
374 int CopyCommand(unsigned char *dest
, unsigned char *src
,
375 int skipcolor
, int bg
)
377 unsigned char *d
= dest
;
378 while (*src
&& *src
!= '\n') {
379 if (*src
== SHORTCUTCHAR
) {
382 *dest
++ = CHANGECOLOR
;
383 *dest
++ = cfg
.clr
[POPDOWNMENU
]
384 [HILITE_COLOR
] [BG
] | 0x80;
387 *dest
++ = RESETCOLOR
;
393 return (int) (dest
- d
);