- Use the Wine spooler service as the service entry template as I was
[reactos.git] / rosapps / dflat32 / popdown.c
1 /* ------------- popdown.c ----------- */
2
3 #include "dflat.h"
4
5 static int SelectionWidth(struct DfPopDown *);
6 static int py = -1;
7
8 /* ------------ DFM_CREATE_WINDOW Message ------------- */
9 static int CreateWindowMsg(DFWINDOW wnd)
10 {
11 int rtn, adj;
12
13 DfClearAttribute (wnd,
14 DF_HASTITLEBAR |
15 DF_VSCROLLBAR |
16 DF_MOVEABLE |
17 DF_SIZEABLE |
18 DF_HSCROLLBAR);
19
20 /* ------ adjust to keep popdown on screen ----- */
21 adj = DfGetScreenHeight()-1-wnd->rc.bt;
22 if (adj < 0)
23 {
24 wnd->rc.tp += adj;
25 wnd->rc.bt += adj;
26 }
27 adj = DfGetScreenWidth()-1-wnd->rc.rt;
28 if (adj < 0)
29 {
30 wnd->rc.lf += adj;
31 wnd->rc.rt += adj;
32 }
33
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;
40 DfInFocus = wnd;
41
42 return rtn;
43 }
44
45 /* --------- DFM_LEFT_BUTTON Message --------- */
46 static void LeftButtonMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
47 {
48 int my = (int) p2 - DfGetTop(wnd);
49 if (DfInsideRect(p1, p2, DfClientRect(wnd))) {
50 if (my != py) {
51 DfSendMessage(wnd, DFM_LB_SELECTION,
52 (DF_PARAM) wnd->wtop+my-1, TRUE);
53 py = my;
54 }
55 }
56 else if ((int)p2 == DfGetTop(DfGetParent(wnd)))
57 if (DfGetClass(DfGetParent(wnd)) == DF_MENUBAR)
58 DfPostMessage(DfGetParent(wnd), DFM_LEFT_BUTTON, p1, p2);
59 }
60
61 /* -------- BUTTON_RELEASED Message -------- */
62 static BOOL ButtonReleasedMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
63 {
64 py = -1;
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);
69 }
70 else {
71 DFWINDOW pwnd = DfGetParent(wnd);
72 if (DfGetClass(pwnd) == DF_MENUBAR && (int)p2==DfGetTop(pwnd))
73 return FALSE;
74 if ((int)p1 == DfGetLeft(pwnd)+2)
75 return FALSE;
76 DfSendMessage(wnd, DFM_CLOSE_WINDOW, 0, 0);
77 return TRUE;
78 }
79 return FALSE;
80 }
81
82 /* --------- DFM_PAINT Message -------- */
83 static void PaintMsg(DFWINDOW wnd)
84 {
85 int wd;
86 char sep[80], *cp = sep;
87 char sel[80];
88 struct DfPopDown *ActivePopDown;
89 struct DfPopDown *pd1;
90
91 ActivePopDown = pd1 = wnd->mnu->Selections;
92 wd = DfMenuWidth(ActivePopDown)-2;
93 while (wd--)
94 *cp++ = DF_LINE;
95 *cp = '\0';
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);
101 else {
102 int len;
103 memset(sel, '\0', sizeof sel);
104 if (pd1->Attrib & DF_INACTIVE)
105 /* ------ inactive menu selection ----- */
106 sprintf(sel, "%c%c%c",
107 DF_CHANGECOLOR,
108 wnd->WindowColors [DF_HILITE_COLOR] [DF_FG]|0x80,
109 wnd->WindowColors [DF_STD_COLOR] [DF_BG]|0x80);
110 strcat(sel, " ");
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 ---- */
119 int i;
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) {
124 while (wd1--)
125 strcat(sel, " ");
126 sprintf(sel+strlen(sel), "[%s]",
127 keys[i].keylabel);
128 break;
129 }
130 }
131 }
132 if (pd1->Attrib & DF_CASCADED) {
133 /* ---- paint cascaded menu token ---- */
134 if (!pd1->Accelerator) {
135 wd = DfMenuWidth(ActivePopDown)-len+1;
136 while (wd--)
137 strcat(sel, " ");
138 }
139 sel[strlen(sel)-1] = DF_CASCADEPOINTER;
140 }
141 else
142 strcat(sel, " ");
143 strcat(sel, " ");
144 sel[strlen(sel)-1] = DF_RESETCOLOR;
145 DfSendMessage(wnd, DFM_ADDTEXT, (DF_PARAM) sel, 0);
146 }
147 pd1++;
148 }
149 }
150
151 /* ---------- DFM_BORDER Message ----------- */
152 static int BorderMsg(DFWINDOW wnd)
153 {
154 int i, rtn = TRUE;
155 DFWINDOW currFocus;
156 if (wnd->mnu != NULL) {
157 currFocus = DfInFocus;
158 DfInFocus = NULL;
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);
165 }
166 }
167 }
168 return rtn;
169 }
170
171 /* -------------- DFM_LB_CHOOSE Message -------------- */
172 static void LBChooseMsg(DFWINDOW wnd, DF_PARAM p1)
173 {
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)
180 *attr ^= DF_CHECKED;
181 DfPostMessage(DfGetParent(wnd), DFM_COMMAND,
182 (ActivePopDown+(int)p1)->ActionId, p1);
183 }
184 else
185 DfBeep();
186 }
187 }
188
189 /* ---------- DFM_KEYBOARD Message --------- */
190 static BOOL KeyboardMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
191 {
192 struct DfPopDown *ActivePopDown = wnd->mnu->Selections;
193
194 if (wnd->mnu != NULL)
195 {
196 if (ActivePopDown != NULL)
197 {
198 int c = (int)p1;
199 int sel = 0;
200 int a;
201 struct DfPopDown *pd = ActivePopDown;
202
203 if ((c & DF_OFFSET) == 0)
204 c = tolower(c);
205 a = DfAltConvert(c);
206
207 while (pd->SelectionTitle != NULL)
208 {
209 char *cp = strchr(pd->SelectionTitle, DF_SHORTCUTCHAR);
210
211 /* FIXME: DfAltConvert bug !! */
212 if ((cp && tolower(*(cp+1)) == c) ||
213 // (a && tolower(*(cp+1)) == a) ||
214 pd->Accelerator == c)
215 {
216 DfPostMessage(wnd, DFM_LB_SELECTION, sel, 0);
217 DfPostMessage(wnd, DFM_LB_CHOOSE, sel, TRUE);
218 return TRUE;
219 }
220 pd++;
221 sel++;
222 }
223 }
224 }
225
226 switch ((int)p1)
227 {
228 case DF_F1:
229 if (ActivePopDown == NULL)
230 DfSendMessage(DfGetParent(wnd), DFM_KEYBOARD, p1, p2);
231 else
232 DfDisplayHelp(wnd,
233 (ActivePopDown+wnd->selection)->help);
234 return TRUE;
235 case DF_ESC:
236 DfSendMessage(wnd, DFM_CLOSE_WINDOW, 0, 0);
237 return TRUE;
238 case DF_FWD:
239 case DF_BS:
240 if (DfGetClass(DfGetParent(wnd)) == DF_MENUBAR)
241 DfPostMessage(DfGetParent(wnd), DFM_KEYBOARD, p1, p2);
242 return TRUE;
243 case DF_UP:
244 if (wnd->selection == 0) {
245 if (wnd->wlines == DfClientHeight(wnd)) {
246 DfPostMessage(wnd, DFM_LB_SELECTION,
247 wnd->wlines-1, FALSE);
248 return TRUE;
249 }
250 }
251 break;
252 case DF_DN:
253 if (wnd->selection == wnd->wlines-1) {
254 if (wnd->wlines == DfClientHeight(wnd)) {
255 DfPostMessage(wnd, DFM_LB_SELECTION, 0, FALSE);
256 return TRUE;
257 }
258 }
259 break;
260 case DF_HOME:
261 case DF_END:
262 case '\r':
263 break;
264 default:
265 return TRUE;
266 }
267 return FALSE;
268 }
269
270 /* ----------- DFM_CLOSE_WINDOW Message ---------- */
271 static int CloseWindowMsg(DFWINDOW wnd)
272 {
273 int rtn;
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);
281 return rtn;
282 }
283
284 /* - Window processing module for DF_POPDOWNMENU window class - */
285 int DfPopDownProc(DFWINDOW wnd, DFMESSAGE msg, DF_PARAM p1, DF_PARAM p2)
286 {
287 switch (msg) {
288 case DFM_CREATE_WINDOW:
289 return CreateWindowMsg(wnd);
290 case DFM_LEFT_BUTTON:
291 LeftButtonMsg(wnd, p1, p2);
292 return FALSE;
293 case DOUBLE_CLICK:
294 return TRUE;
295 case DFM_LB_SELECTION:
296 if (*DfTextLine(wnd, (int)p1) == DF_LINE)
297 return TRUE;
298 wnd->mnu->Selection = (int)p1;
299 break;
300 case DFM_BUTTON_RELEASED:
301 if (ButtonReleasedMsg(wnd, p1, p2))
302 return TRUE;
303 break;
304 case DFM_BUILD_SELECTIONS:
305 wnd->mnu = (void *) p1;
306 wnd->selection = wnd->mnu->Selection;
307 break;
308 case DFM_PAINT:
309 if (wnd->mnu == NULL)
310 return TRUE;
311 PaintMsg(wnd);
312 break;
313 case DFM_BORDER:
314 return BorderMsg(wnd);
315 case DFM_LB_CHOOSE:
316 LBChooseMsg(wnd, p1);
317 return TRUE;
318 case DFM_KEYBOARD:
319 if (KeyboardMsg(wnd, p1, p2))
320 return TRUE;
321 break;
322 case DFM_CLOSE_WINDOW:
323 return CloseWindowMsg(wnd);
324 default:
325 break;
326 }
327 return DfBaseWndProc(DF_POPDOWNMENU, wnd, msg, p1, p2);
328 }
329
330 /* --------- compute menu height -------- */
331 int DfMenuHeight(struct DfPopDown *pd)
332 {
333 int ht = 0;
334 while (pd[ht].SelectionTitle != NULL)
335 ht++;
336 return ht+2;
337 }
338
339 /* --------- compute menu width -------- */
340 int DfMenuWidth(struct DfPopDown *pd)
341 {
342 int wd = 0, i;
343 int len = 0;
344
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)));
351 break;
352 }
353 }
354 if (pd->Attrib & DF_CASCADED)
355 len = max(len, 2);
356 pd++;
357 }
358 return wd+5+len;
359 }
360
361 /* ---- compute the maximum selection width in a menu ---- */
362 static int SelectionWidth(struct DfPopDown *pd)
363 {
364 int wd = 0;
365 while (pd->SelectionTitle != NULL) {
366 int len = strlen(pd->SelectionTitle)-1;
367 wd = max(wd, len);
368 pd++;
369 }
370 return wd;
371 }
372
373 /* ----- copy a menu command to a display buffer ---- */
374 int DfCopyCommand(char *dest, char *src, int skipcolor, int bg)
375 {
376 char *d = dest;
377 while (*src && *src != '\n') {
378 if (*src == DF_SHORTCUTCHAR) {
379 src++;
380 if (!skipcolor) {
381 *dest++ = DF_CHANGECOLOR;
382 *dest++ = DfCfg.clr[DF_POPDOWNMENU]
383 [DF_HILITE_COLOR] [DF_BG] | 0x80;
384 *dest++ = bg | 0x80;
385 *dest++ = *src++;
386 *dest++ = DF_RESETCOLOR;
387 }
388 }
389 else
390 *dest++ = *src++;
391 }
392 return (int) (dest - d);
393 }
394
395 /* EOF */