1 /* ------------- popdown.c ----------- */
5 static int SelectionWidth(struct DfPopDown
*);
8 /* ------------ DFM_CREATE_WINDOW Message ------------- */
9 static int CreateWindowMsg(DFWINDOW wnd
)
13 DfClearAttribute (wnd
,
20 /* ------ adjust to keep popdown on screen ----- */
21 adj
= DfGetScreenHeight()-1-wnd
->rc
.bt
;
27 adj
= DfGetScreenWidth()-1-wnd
->rc
.rt
;
34 rtn
= DfBaseWndProc(DF_POPDOWNMENU
, wnd
, DFM_CREATE_WINDOW
, 0, 0);
35 DfSendMessage(wnd
, DFM_CAPTURE_MOUSE
, 0, 0);
36 DfSendMessage(wnd
, DFM_CAPTURE_KEYBOARD
, 0, 0);
37 DfSendMessage(NULL
, DFM_SAVE_CURSOR
, 0, 0);
38 DfSendMessage(NULL
, DFM_HIDE_CURSOR
, 0, 0);
39 wnd
->oldFocus
= DfInFocus
;
45 /* --------- DFM_LEFT_BUTTON Message --------- */
46 static void LeftButtonMsg(DFWINDOW wnd
, DF_PARAM p1
, DF_PARAM p2
)
48 int my
= (int) p2
- DfGetTop(wnd
);
49 if (DfInsideRect(p1
, p2
, DfClientRect(wnd
))) {
51 DfSendMessage(wnd
, DFM_LB_SELECTION
,
52 (DF_PARAM
) wnd
->wtop
+my
-1, TRUE
);
56 else if ((int)p2
== DfGetTop(DfGetParent(wnd
)))
57 if (DfGetClass(DfGetParent(wnd
)) == DF_MENUBAR
)
58 DfPostMessage(DfGetParent(wnd
), DFM_LEFT_BUTTON
, p1
, p2
);
61 /* -------- BUTTON_RELEASED Message -------- */
62 static BOOL
ButtonReleasedMsg(DFWINDOW wnd
, DF_PARAM p1
, DF_PARAM p2
)
65 if (DfInsideRect((int)p1
, (int)p2
, DfClientRect(wnd
))) {
66 int sel
= (int)p2
- DfGetClientTop(wnd
);
67 if (*DfTextLine(wnd
, sel
) != DF_LINE
)
68 DfSendMessage(wnd
, DFM_LB_CHOOSE
, wnd
->selection
, 0);
71 DFWINDOW pwnd
= DfGetParent(wnd
);
72 if (DfGetClass(pwnd
) == DF_MENUBAR
&& (int)p2
==DfGetTop(pwnd
))
74 if ((int)p1
== DfGetLeft(pwnd
)+2)
76 DfSendMessage(wnd
, DFM_CLOSE_WINDOW
, 0, 0);
82 /* --------- DFM_PAINT Message -------- */
83 static void PaintMsg(DFWINDOW wnd
)
86 char sep
[80], *cp
= sep
;
88 struct DfPopDown
*ActivePopDown
;
89 struct DfPopDown
*pd1
;
91 ActivePopDown
= pd1
= wnd
->mnu
->Selections
;
92 wd
= DfMenuWidth(ActivePopDown
)-2;
96 DfSendMessage(wnd
, DFM_CLEARTEXT
, 0, 0);
97 wnd
->selection
= wnd
->mnu
->Selection
;
98 while (pd1
->SelectionTitle
!= NULL
) {
99 if (*pd1
->SelectionTitle
== DF_LINE
)
100 DfSendMessage(wnd
, DFM_ADDTEXT
, (DF_PARAM
) sep
, 0);
103 memset(sel
, '\0', sizeof sel
);
104 if (pd1
->Attrib
& DF_INACTIVE
)
105 /* ------ inactive menu selection ----- */
106 sprintf(sel
, "%c%c%c",
108 wnd
->WindowColors
[DF_HILITE_COLOR
] [DF_FG
]|0x80,
109 wnd
->WindowColors
[DF_STD_COLOR
] [DF_BG
]|0x80);
111 if (pd1
->Attrib
& DF_CHECKED
)
112 /* ---- paint the toggle checkmark ---- */
113 sel
[strlen(sel
)-1] = DF_CHECKMARK
;
114 len
=DfCopyCommand(sel
+strlen(sel
),pd1
->SelectionTitle
,
115 pd1
->Attrib
& DF_INACTIVE
,
116 wnd
->WindowColors
[DF_STD_COLOR
] [DF_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
& DF_CASCADED
) {
133 /* ---- paint cascaded menu token ---- */
134 if (!pd1
->Accelerator
) {
135 wd
= DfMenuWidth(ActivePopDown
)-len
+1;
139 sel
[strlen(sel
)-1] = DF_CASCADEPOINTER
;
144 sel
[strlen(sel
)-1] = DF_RESETCOLOR
;
145 DfSendMessage(wnd
, DFM_ADDTEXT
, (DF_PARAM
) sel
, 0);
151 /* ---------- DFM_BORDER Message ----------- */
152 static int BorderMsg(DFWINDOW wnd
)
156 if (wnd
->mnu
!= NULL
) {
157 currFocus
= DfInFocus
;
159 rtn
= DfBaseWndProc(DF_POPDOWNMENU
, wnd
, DFM_BORDER
, 0, 0);
160 DfInFocus
= currFocus
;
161 for (i
= 0; i
< DfClientHeight(wnd
); i
++) {
162 if (*DfTextLine(wnd
, i
) == DF_LINE
) {
163 DfWPutch(wnd
, DF_LEDGE
, 0, i
+1);
164 DfWPutch(wnd
, DF_REDGE
, DfWindowWidth(wnd
)-1, i
+1);
171 /* -------------- DFM_LB_CHOOSE Message -------------- */
172 static void LBChooseMsg(DFWINDOW wnd
, DF_PARAM p1
)
174 struct DfPopDown
*ActivePopDown
= wnd
->mnu
->Selections
;
175 if (ActivePopDown
!= NULL
) {
176 int *attr
= &(ActivePopDown
+(int)p1
)->Attrib
;
177 wnd
->mnu
->Selection
= (int)p1
;
178 if (!(*attr
& DF_INACTIVE
)) {
179 if (*attr
& DF_TOGGLE
)
181 DfPostMessage(DfGetParent(wnd
), DFM_COMMAND
,
182 (ActivePopDown
+(int)p1
)->ActionId
, p1
);
189 /* ---------- DFM_KEYBOARD Message --------- */
190 static BOOL
KeyboardMsg(DFWINDOW wnd
, DF_PARAM p1
, DF_PARAM p2
)
192 struct DfPopDown
*ActivePopDown
= wnd
->mnu
->Selections
;
194 if (wnd
->mnu
!= NULL
)
196 if (ActivePopDown
!= NULL
)
201 struct DfPopDown
*pd
= ActivePopDown
;
203 if ((c
& DF_OFFSET
) == 0)
207 while (pd
->SelectionTitle
!= NULL
)
209 char *cp
= strchr(pd
->SelectionTitle
, DF_SHORTCUTCHAR
);
211 /* FIXME: DfAltConvert bug !! */
212 if ((cp
&& tolower(*(cp
+1)) == c
) ||
213 // (a && tolower(*(cp+1)) == a) ||
214 pd
->Accelerator
== c
)
216 DfPostMessage(wnd
, DFM_LB_SELECTION
, sel
, 0);
217 DfPostMessage(wnd
, DFM_LB_CHOOSE
, sel
, TRUE
);
229 if (ActivePopDown
== NULL
)
230 DfSendMessage(DfGetParent(wnd
), DFM_KEYBOARD
, p1
, p2
);
233 (ActivePopDown
+wnd
->selection
)->help
);
236 DfSendMessage(wnd
, DFM_CLOSE_WINDOW
, 0, 0);
240 if (DfGetClass(DfGetParent(wnd
)) == DF_MENUBAR
)
241 DfPostMessage(DfGetParent(wnd
), DFM_KEYBOARD
, p1
, p2
);
244 if (wnd
->selection
== 0) {
245 if (wnd
->wlines
== DfClientHeight(wnd
)) {
246 DfPostMessage(wnd
, DFM_LB_SELECTION
,
247 wnd
->wlines
-1, FALSE
);
253 if (wnd
->selection
== wnd
->wlines
-1) {
254 if (wnd
->wlines
== DfClientHeight(wnd
)) {
255 DfPostMessage(wnd
, DFM_LB_SELECTION
, 0, FALSE
);
270 /* ----------- DFM_CLOSE_WINDOW Message ---------- */
271 static int CloseWindowMsg(DFWINDOW wnd
)
274 DFWINDOW pwnd
= DfGetParent(wnd
);
275 DfSendMessage(wnd
, DFM_RELEASE_MOUSE
, 0, 0);
276 DfSendMessage(wnd
, DFM_RELEASE_KEYBOARD
, 0, 0);
277 DfSendMessage(NULL
, DFM_RESTORE_CURSOR
, 0, 0);
278 DfInFocus
= wnd
->oldFocus
;
279 rtn
= DfBaseWndProc(DF_POPDOWNMENU
, wnd
, DFM_CLOSE_WINDOW
, 0, 0);
280 DfSendMessage(pwnd
, DFM_CLOSE_POPDOWN
, 0, 0);
284 /* - Window processing module for DF_POPDOWNMENU window class - */
285 int DfPopDownProc(DFWINDOW wnd
, DFMESSAGE msg
, DF_PARAM p1
, DF_PARAM p2
)
288 case DFM_CREATE_WINDOW
:
289 return CreateWindowMsg(wnd
);
290 case DFM_LEFT_BUTTON
:
291 LeftButtonMsg(wnd
, p1
, p2
);
295 case DFM_LB_SELECTION
:
296 if (*DfTextLine(wnd
, (int)p1
) == DF_LINE
)
298 wnd
->mnu
->Selection
= (int)p1
;
300 case DFM_BUTTON_RELEASED
:
301 if (ButtonReleasedMsg(wnd
, p1
, p2
))
304 case DFM_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
))
322 case DFM_CLOSE_WINDOW
:
323 return CloseWindowMsg(wnd
);
327 return DfBaseWndProc(DF_POPDOWNMENU
, wnd
, msg
, p1
, p2
);
330 /* --------- compute menu height -------- */
331 int DfMenuHeight(struct DfPopDown
*pd
)
334 while (pd
[ht
].SelectionTitle
!= NULL
)
339 /* --------- compute menu width -------- */
340 int DfMenuWidth(struct DfPopDown
*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
& DF_CASCADED
)
361 /* ---- compute the maximum selection width in a menu ---- */
362 static int SelectionWidth(struct DfPopDown
*pd
)
365 while (pd
->SelectionTitle
!= NULL
) {
366 int len
= strlen(pd
->SelectionTitle
)-1;
373 /* ----- copy a menu command to a display buffer ---- */
374 int DfCopyCommand(char *dest
, char *src
, int skipcolor
, int bg
)
377 while (*src
&& *src
!= '\n') {
378 if (*src
== DF_SHORTCUTCHAR
) {
381 *dest
++ = DF_CHANGECOLOR
;
382 *dest
++ = DfCfg
.clr
[DF_POPDOWNMENU
]
383 [DF_HILITE_COLOR
] [DF_BG
] | 0x80;
386 *dest
++ = DF_RESETCOLOR
;
392 return (int) (dest
- d
);