comparison os2/dw.c @ 3:67a643a734d9

Import
author ktk@81767d24-ef19-dc11-ae90-00e081727c95
date Tue, 03 Jul 2001 07:50:39 +0000
parents
children 005fa766e8c2
comparison
equal deleted inserted replaced
2:36c5f0ce3fbe 3:67a643a734d9
1 /*
2 * Dynamic Windows:
3 * A GTK like implementation of the PM GUI
4 *
5 * (C) 2000,2001 Brian Smith <dbsoft@technologist.com>
6 * (C) 2000 Achim Hasenmueller <achimha@innotek.de>
7 * (C) 2000 Peter Nielsen <peter@pmview.com>
8 * (C) 1998 Sergey I. Yevtushenko (some code borrowed from cell toolkit)
9 *
10 */
11 #define INCL_DOS
12 #define INCL_DOSERRORS
13 #define INCL_WIN
14 #define INCL_GPI
15
16 #include <os2.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <stddef.h>
22 #include <ctype.h>
23 #include <process.h>
24 #include "dw.h"
25
26 #define QWP_USER 0
27
28 char ClassName[] = "dynamicwindows";
29 char SplitbarClassName[] = "dwsplitbar";
30 char DefaultFont[] = "9.WarpSans";
31
32 /* this is the callback handle for the window procedure
33 * make sure you always match the calling convention!
34 */
35 int (* EXPENTRY filterfunc)(HWND, ULONG, MPARAM, MPARAM) = 0L;
36
37 HAB dwhab = 0;
38 HMQ dwhmq = 0;
39 DWTID _dwtid = 0;
40 LONG _foreground = 0xAAAAAA, _background = 0;
41
42 HWND hwndBubble = NULLHANDLE, hwndBubbleLast = NULLHANDLE;
43 PRECORDCORE pCore = NULL;
44
45 #ifndef min
46 #define min(a, b) (((a < b) ? a : b))
47 #endif
48
49 #ifdef DWDEBUG
50 FILE *f;
51
52 void reopen(void)
53 {
54 fclose(f);
55 f = fopen("dw.log", "at");
56 }
57 #endif
58
59 static LONG lColor[SPLITBAR_WIDTH] =
60 {
61 DW_CLR_BLACK,
62 DW_CLR_PALEGRAY,
63 DW_CLR_WHITE
64 };
65
66 #ifdef NO_SIGNALS
67 #define USE_FILTER
68 #else
69 typedef struct _sighandler
70 {
71 struct _sighandler *next;
72 ULONG message;
73 HWND window;
74 void *signalfunction;
75 void *data;
76
77 } SignalHandler;
78
79 SignalHandler *Root = NULL;
80
81 typedef struct
82 {
83 ULONG message;
84 char name[30];
85
86 } SignalList;
87
88 /* List of signals and their equivilent OS/2 message */
89 #define SIGNALMAX 11
90
91 SignalList SignalTranslate[SIGNALMAX] = {
92 { WM_SIZE, "configure_event" },
93 { WM_CHAR, "key_press_event" },
94 { WM_BUTTON1DOWN, "button_press_event" },
95 { WM_BUTTON1UP, "button_release_event"},
96 { WM_MOUSEMOVE, "motion_notify_event" },
97 { WM_CLOSE, "delete_event" },
98 { WM_PAINT, "expose_event" },
99 { WM_COMMAND, "clicked" },
100 { CN_ENTER, "container-select" },
101 { CN_CONTEXTMENU, "container-context" },
102 { LN_SELECT, "item-select" }
103 };
104
105 /* This function adds a signal handler callback into the linked list.
106 */
107 void _new_signal(ULONG message, HWND window, void *signalfunction, void *data)
108 {
109 SignalHandler *new = malloc(sizeof(SignalHandler));
110
111 new->message = message;
112 new->window = window;
113 new->signalfunction = signalfunction;
114 new->data = data;
115 new->next = NULL;
116
117 if (!Root)
118 Root = new;
119 else
120 {
121 SignalHandler *prev = NULL, *tmp = Root;
122 while(tmp)
123 {
124 prev = tmp;
125 tmp = tmp->next;
126 }
127 if(prev)
128 prev->next = new;
129 else
130 Root = new;
131 }
132 }
133
134 /* Finds the message number for a given signal name */
135 ULONG _findsigmessage(char *signame)
136 {
137 int z;
138
139 for(z=0;z<SIGNALMAX;z++)
140 {
141 if(stricmp(signame, SignalTranslate[z].name) == 0)
142 return SignalTranslate[z].message;
143 }
144 return 0L;
145 }
146 #endif
147
148 /* This function removes and handlers on windows and frees
149 * the user memory allocated to it.
150 */
151 void _free_window_memory(HWND handle)
152 {
153 HENUM henum;
154 HWND child;
155
156 #ifndef NO_SIGNALS
157 dw_signal_disconnect_by_window(handle);
158 #endif
159
160 henum = WinBeginEnumWindows(handle);
161 while((child = WinGetNextWindow(henum)) != NULLHANDLE)
162 {
163 void *ptr = (void *)WinQueryWindowPtr(handle, QWP_USER);
164
165 if(ptr)
166 {
167 WinSetWindowPtr(handle, QWP_USER, 0);
168 free(ptr);
169 }
170
171 _free_window_memory(child);
172 }
173 WinEndEnumWindows(henum);
174 return;
175 }
176
177 /* This function returns 1 if the window (widget) handle
178 * passed to it is a valid window that can gain input focus.
179 */
180 int _validate_focus(HWND handle)
181 {
182 char tmpbuf[100];
183
184 if(!handle)
185 return 0;
186
187 WinQueryClassName(handle, 99, tmpbuf);
188
189 /* These are the window classes which can
190 * obtain input focus.
191 */
192 if(strncmp(tmpbuf, "#2", 2)==0 || /* Entryfield */
193 strncmp(tmpbuf, "#3", 2)==0 || /* Button */
194 strncmp(tmpbuf, "#6", 2)==0 || /* Combobox */
195 strncmp(tmpbuf, "#7", 2)==0 || /* List box */
196 strncmp(tmpbuf, "#10", 3)==0 || /* MLE */
197 strncmp(tmpbuf, "#32", 3)==0 || /* Spinbutton */
198 strncmp(tmpbuf, "#37", 3)== 0) /* Container */
199 return 1;
200 return 0;
201 }
202
203 int _focus_check_box(Box *box, HWND handle, int start)
204 {
205 int z;
206 static HWND lasthwnd, firsthwnd;
207 static int finish_searching;
208
209 /* Start is 2 when we have cycled completely and
210 * need to set the focus to the last widget we found
211 * that was valid.
212 */
213 if(start == 2)
214 {
215 if(lasthwnd)
216 WinSetFocus(HWND_DESKTOP, lasthwnd);
217 return 0;
218 }
219
220 /* Start is 1 when we are entering the function
221 * for the first time, it is zero when entering
222 * the function recursively.
223 */
224 if(start == 1)
225 {
226 lasthwnd = handle;
227 finish_searching = 0;
228 firsthwnd = 0;
229 }
230
231 /* Vertical boxes are inverted on OS/2 */
232 if(box->type == BOXVERT)
233 {
234 for(z=0;z<box->count;z++)
235 {
236 if(box->items[z].type == TYPEBOX)
237 {
238 Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER);
239
240 if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0))
241 return 1;
242 }
243 else
244 {
245 if(box->items[z].hwnd == handle)
246 {
247 if(lasthwnd == handle && firsthwnd)
248 WinSetFocus(HWND_DESKTOP, firsthwnd);
249 else if(lasthwnd == handle && !firsthwnd)
250 finish_searching = 1;
251 else
252 WinSetFocus(HWND_DESKTOP, lasthwnd);
253
254 /* If we aren't looking for the last handle,
255 * return immediately.
256 */
257 if(!finish_searching)
258 return 1;
259 }
260 if(_validate_focus(box->items[z].hwnd))
261 {
262 /* Start is 3 when we are looking for the
263 * first valid item in the layout.
264 */
265 if(start == 3)
266 {
267 WinSetFocus(HWND_DESKTOP, box->items[z].hwnd);
268 return 1;
269 }
270
271 if(!firsthwnd)
272 firsthwnd = box->items[z].hwnd;
273
274 lasthwnd = box->items[z].hwnd;
275 }
276 else
277 {
278 char tmpbuf[100] = "";
279
280 WinQueryClassName(box->items[z].hwnd, 99, tmpbuf);
281 if(strncmp(tmpbuf, "#40", 3)==0) /* Notebook */
282 {
283 Box *notebox;
284 HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND,
285 (MPARAM)dw_notebook_page_query(box->items[z].hwnd), 0);
286
287 if(page)
288 {
289 notebox = (Box *)WinQueryWindowPtr(page, QWP_USER);
290
291 if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0))
292 return 1;
293 }
294 }
295 }
296 }
297 }
298 }
299 else
300 {
301 for(z=box->count-1;z>-1;z--)
302 {
303 if(box->items[z].type == TYPEBOX)
304 {
305 Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER);
306
307 if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0))
308 return 1;
309 }
310 else
311 {
312 if(box->items[z].hwnd == handle)
313 {
314 if(lasthwnd == handle && firsthwnd)
315 WinSetFocus(HWND_DESKTOP, firsthwnd);
316 else if(lasthwnd == handle && !firsthwnd)
317 finish_searching = 1;
318 else
319 WinSetFocus(HWND_DESKTOP, lasthwnd);
320
321 /* If we aren't looking for the last handle,
322 * return immediately.
323 */
324 if(!finish_searching)
325 return 1;
326 }
327 if(_validate_focus(box->items[z].hwnd))
328 {
329 /* Start is 3 when we are looking for the
330 * first valid item in the layout.
331 */
332 if(start == 3)
333 {
334 WinSetFocus(HWND_DESKTOP, box->items[z].hwnd);
335 return 1;
336 }
337
338 if(!firsthwnd)
339 firsthwnd = box->items[z].hwnd;
340
341 lasthwnd = box->items[z].hwnd;
342 }
343 else
344 {
345 char tmpbuf[100] = "";
346
347 WinQueryClassName(box->items[z].hwnd, 99, tmpbuf);
348 if(strncmp(tmpbuf, "#40", 3)==0) /* Notebook */
349 {
350 Box *notebox;
351 HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND,
352 (MPARAM)dw_notebook_page_query(box->items[z].hwnd), 0);
353
354 if(page)
355 {
356 notebox = (Box *)WinQueryWindowPtr(page, QWP_USER);
357
358 if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0))
359 return 1;
360 }
361 }
362 }
363 }
364 }
365 }
366 return 0;
367 }
368
369 /* This function finds the first widget in the
370 * layout and moves the current focus to it.
371 */
372 void _initial_focus(HWND handle)
373 {
374 Box *thisbox;
375 HWND box;
376
377 box = WinWindowFromID(handle, FID_CLIENT);
378 if(box)
379 thisbox = WinQueryWindowPtr(box, QWP_USER);
380
381 if(thisbox)
382 {
383 _focus_check_box(thisbox, handle, 3);
384 }
385 }
386
387 /* This function finds the current widget in the
388 * layout and moves the current focus to the next item.
389 */
390 void _shift_focus(HWND handle)
391 {
392 Box *thisbox;
393 HWND box, lastbox = WinQueryWindow(handle, QW_PARENT);
394
395 /* Find the toplevel window */
396 while((box = WinQueryWindow(lastbox, QW_PARENT)) > 0x80000001)
397 {
398 lastbox = box;
399 }
400
401 thisbox = WinQueryWindowPtr(lastbox, QWP_USER);
402 if(!thisbox)
403 {
404 box = WinWindowFromID(lastbox, FID_CLIENT);
405 if(box)
406 thisbox = WinQueryWindowPtr(box, QWP_USER);
407 }
408 if(thisbox)
409 {
410 if(_focus_check_box(thisbox, handle, 1) == 0)
411 _focus_check_box(thisbox, handle, 2);
412 }
413 }
414
415 /* ResetWindow:
416 * Resizes window to the exact same size to trigger
417 * recalculation of frame.
418 */
419 void _ResetWindow(HWND hwndFrame)
420 {
421 SWP swp;
422
423 WinQueryWindowPos(hwndFrame, &swp);
424 WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, swp.cx, swp.cy-1, SWP_SIZE);
425 WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, swp.cx, swp.cy, SWP_SIZE);
426 }
427
428 /* This function will recursively search a box and add up the total height of it */
429 void _count_size(HWND box, int type, int *xsize, int *xorigsize)
430 {
431 int size = 0, origsize = 0, z;
432 Box *tmp = WinQueryWindowPtr(box, QWP_USER);
433
434 if(!tmp)
435 {
436 *xsize = *xorigsize = 0;
437 return;
438 }
439
440 if(type == tmp->type)
441 {
442 /* If the box is going in the direction we want, then we
443 * return the entire sum of the items.
444 */
445 for(z=0;z<tmp->count;z++)
446 {
447 if(tmp->items[z].type == TYPEBOX)
448 {
449 int s, os;
450
451 _count_size(tmp->items[z].hwnd, type, &s, &os);
452 size += s;
453 origsize += os;
454 }
455 else
456 {
457 size += (type == BOXHORZ ? tmp->items[z].width : tmp->items[z].height);
458 origsize += (type == BOXHORZ ? tmp->items[z].origwidth : tmp->items[z].origheight);
459 }
460 }
461 }
462 else
463 {
464 /* If the box is not going in the direction we want, then we only
465 * want to return the maximum value.
466 */
467 int tmpsize = 0, tmporigsize = 0;
468
469 for(z=0;z<tmp->count;z++)
470 {
471 if(tmp->items[z].type == TYPEBOX)
472 _count_size(tmp->items[z].hwnd, type, &tmpsize, &tmporigsize);
473 else
474 {
475 tmpsize = (type == BOXHORZ ? tmp->items[z].width : tmp->items[z].height);
476 tmporigsize = (type == BOXHORZ ? tmp->items[z].origwidth : tmp->items[z].origheight);
477 }
478
479 if(tmpsize > size)
480 size = tmpsize;
481 }
482 }
483
484 *xsize = size;
485 *xorigsize = origsize;
486 }
487
488
489 /* Function: TrackRectangle
490 * Abstract: Tracks given rectangle.
491 *
492 * If rclBounds is NULL, then track rectangle on entire desktop.
493 * rclTrack is in window coorditates and will be mapped to
494 * desktop.
495 */
496
497 BOOL _TrackRectangle(HWND hwndBase, RECTL* rclTrack, RECTL* rclBounds)
498 {
499 TRACKINFO track;
500 APIRET rc;
501
502 track.cxBorder = 1;
503 track.cyBorder = 1;
504 track.cxGrid = 1;
505 track.cyGrid = 1;
506 track.cxKeyboard = 8;
507 track.cyKeyboard = 8;
508
509 if(!rclTrack)
510 return FALSE;
511
512 if(rclBounds)
513 {
514 track.rclBoundary = *rclBounds;
515 }
516 else
517 {
518 track.rclBoundary.yTop =
519 track.rclBoundary.xRight = 3000;
520 track.rclBoundary.yBottom =
521 track.rclBoundary.xLeft = -3000;
522 }
523
524 track.rclTrack = *rclTrack;
525
526 WinMapWindowPoints(hwndBase,
527 HWND_DESKTOP,
528 (PPOINTL)&track.rclTrack,
529 2);
530
531 track.ptlMinTrackSize.x = track.rclTrack.xRight
532 - track.rclTrack.xLeft;
533 track.ptlMinTrackSize.y = track.rclTrack.yTop
534 - track.rclTrack.yBottom;
535 track.ptlMaxTrackSize.x = track.rclTrack.xRight
536 - track.rclTrack.xLeft;
537 track.ptlMaxTrackSize.y = track.rclTrack.yTop
538 - track.rclTrack.yBottom;
539
540 track.fs = TF_MOVE | TF_ALLINBOUNDARY;
541
542 rc = WinTrackRect(HWND_DESKTOP, 0, &track);
543
544 if(rc)
545 *rclTrack = track.rclTrack;
546
547 return rc;
548 }
549
550 /* This function calculates how much space the widgets and boxes require
551 * and does expansion as necessary.
552 */
553 int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy,
554 int pass, int *usedpadx, int *usedpady)
555 {
556 int z, currentx = 0, currenty = 0;
557 int vectorx = 0, vectory = 0;
558 int uymax = 0, uxmax = 0;
559 int upymax = 0, upxmax = 0;
560 /* Used for the SIZEEXPAND */
561 int nux = *usedx, nuy = *usedy;
562 int nupx = *usedpadx, nupy = *usedpady;
563
564 (*usedx) += (thisbox->pad * 2);
565 (*usedy) += (thisbox->pad * 2);
566
567 for(z=0;z<thisbox->count;z++)
568 {
569 if(thisbox->items[z].type == TYPEBOX)
570 {
571 int initialx, initialy;
572 Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
573
574 initialx = x - (*usedx);
575 initialy = y - (*usedy);
576
577 if(tmp)
578 {
579 int newx, newy;
580 int nux = *usedx, nuy = *usedy;
581 int upx = *usedpadx + (tmp->pad*2), upy = *usedpady + (tmp->pad*2);
582
583 /* On the second pass we know how big the box needs to be and how
584 * much space we have, so we can calculate a ratio for the new box.
585 */
586 if(pass == 2)
587 {
588 int deep = *depth + 1;
589
590 _resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy);
591
592 tmp->upx = upx - *usedpadx;
593 tmp->upy = upy - *usedpady;
594
595 newx = x - nux;
596 newy = y - nuy;
597
598 tmp->width = thisbox->items[z].width = initialx - newx;
599 tmp->height = thisbox->items[z].height = initialy - newy;
600
601 tmp->parentxratio = thisbox->xratio;
602 tmp->parentyratio = thisbox->yratio;
603
604 tmp->parentpad = tmp->pad;
605
606 /* Just in case */
607 tmp->xratio = thisbox->xratio;
608 tmp->yratio = thisbox->yratio;
609
610 #ifdef DWDEBUG
611 if(pass > 1)
612 {
613 fprintf(f, "FARK! depth %d\r\nwidth = %d, height = %d, nux = %d, nuy = %d, upx = %d, upy = %d xratio = %f, yratio = %f\r\n\r\n",
614 *depth, thisbox->items[z].width, thisbox->items[z].height, nux, nuy, tmp->upx, tmp->upy, tmp->xratio, tmp->yratio);
615 reopen();
616 }
617 #endif
618 if(thisbox->type == BOXVERT)
619 {
620 if((thisbox->items[z].width-((thisbox->items[z].pad*2)+(tmp->pad*2)))!=0)
621 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+(tmp->pad*2))))/((float)(thisbox->items[z].width-((thisbox->items[z].pad*2)+(tmp->pad*2))));
622 }
623 else
624 {
625 if((thisbox->items[z].width-tmp->upx)!=0)
626 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx));
627 }
628 if(thisbox->type == BOXHORZ)
629 {
630 if((thisbox->items[z].height-((thisbox->items[z].pad*2)+(tmp->pad*2)))!=0)
631 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+(tmp->pad*2))))/((float)(thisbox->items[z].height-((thisbox->items[z].pad*2)+(tmp->pad*2))));
632 }
633 else
634 {
635 if((thisbox->items[z].height-tmp->upy)!=0)
636 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy));
637 }
638
639 nux = *usedx; nuy = *usedy;
640 upx = *usedpadx + (tmp->pad*2); upy = *usedpady + (tmp->pad*2);
641 }
642
643 (*depth)++;
644
645 #ifdef DWDEBUG
646 if(pass > 1)
647 {
648 fprintf(f, "Before Resize Box depth %d\r\nx = %d, y = %d, usedx = %d, usedy = %d, usedpadx = %d, usedpady = %d xratio = %f, yratio = %f\r\n\r\n",
649 *depth, x, y, *usedx, *usedy, *usedpadx, *usedpady, tmp->xratio, tmp->yratio);
650 reopen();
651 }
652 #endif
653
654 _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy);
655
656 (*depth)--;
657
658 newx = x - nux;
659 newy = y - nuy;
660
661 tmp->minwidth = thisbox->items[z].width = initialx - newx;
662 tmp->minheight = thisbox->items[z].height = initialy - newy;
663
664 #ifdef DWDEBUG
665 if(pass > 1)
666 {
667 fprintf(f, "After Resize Box depth %d\r\nx = %d, y = %d, usedx = %d, usedy = %d, usedpadx = %d, usedpady = %d width = %d, height = %d\r\n\r\n",
668 *depth, x, y, *usedx, *usedy, *usedpadx, *usedpady, thisbox->items[z].width, thisbox->items[z].height);
669 reopen();
670 }
671 #endif
672 }
673 }
674
675 if(pass > 1 && *depth > 0)
676 {
677 if(thisbox->type == BOXVERT)
678 thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minwidth-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
679 else
680 thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
681
682 if(thisbox->type == BOXHORZ)
683 thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minheight-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
684 else
685 thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
686 #ifdef DWDEBUG
687 fprintf(f, "RATIO- xratio = %f, yratio = %f, width = %d, height = %d, pad = %d, box xratio = %f, box yratio = %f, parent xratio = %f, parent yratio = %f, minwidth = %d, minheight = %d, width = %d, height = %d, upx = %d, upy = %d\r\n\r\n",
688 thisbox->items[z].xratio, thisbox->items[z].yratio, thisbox->items[z].width, thisbox->items[z].height, thisbox->items[z].pad, thisbox->xratio, thisbox->yratio, thisbox->parentxratio, thisbox->parentyratio, thisbox->minwidth, thisbox->minheight, thisbox->width, thisbox->height, thisbox->upx, thisbox->upy);
689 reopen();
690 #endif
691 }
692 else
693 {
694 thisbox->items[z].xratio = thisbox->xratio;
695 thisbox->items[z].yratio = thisbox->yratio;
696 }
697
698 if(thisbox->type == BOXVERT)
699 {
700 if((thisbox->items[z].width + (thisbox->items[z].pad*2)) > uxmax)
701 uxmax = (thisbox->items[z].width + (thisbox->items[z].pad*2));
702 if(thisbox->items[z].hsize != SIZEEXPAND)
703 {
704 if(((thisbox->items[z].pad*2) + thisbox->items[z].width) > upxmax)
705 upxmax = (thisbox->items[z].pad*2) + thisbox->items[z].width;
706 }
707 else
708 {
709 if(thisbox->items[z].pad*2 > upxmax)
710 upxmax = thisbox->items[z].pad*2;
711 }
712 }
713 else
714 {
715 if(thisbox->items[z].width == -1)
716 {
717 /* figure out how much space this item requires */
718 /* thisbox->items[z].width = */
719 }
720 else
721 {
722 (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2);
723 if(thisbox->items[z].hsize != SIZEEXPAND)
724 (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width;
725 else
726 (*usedpadx) += thisbox->items[z].pad*2;
727 }
728 }
729 if(thisbox->type == BOXHORZ)
730 {
731 if((thisbox->items[z].height + (thisbox->items[z].pad*2)) > uymax)
732 uymax = (thisbox->items[z].height + (thisbox->items[z].pad*2));
733 if(thisbox->items[z].vsize != SIZEEXPAND)
734 {
735 if(((thisbox->items[z].pad*2) + thisbox->items[z].height) > upymax)
736 upymax = (thisbox->items[z].pad*2) + thisbox->items[z].height;
737 }
738 else
739 {
740 if(thisbox->items[z].pad*2 > upymax)
741 upymax = thisbox->items[z].pad*2;
742 }
743 }
744 else
745 {
746 if(thisbox->items[z].height == -1)
747 {
748 /* figure out how much space this item requires */
749 /* thisbox->items[z].height = */
750 }
751 else
752 {
753 (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2);
754 if(thisbox->items[z].vsize != SIZEEXPAND)
755 (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height;
756 else
757 (*usedpady) += thisbox->items[z].pad*2;
758 }
759 }
760 }
761
762 (*usedx) += uxmax;
763 (*usedy) += uymax;
764 (*usedpadx) += upxmax;
765 (*usedpady) += upymax;
766
767 currentx += thisbox->pad;
768 currenty += thisbox->pad;
769
770 #ifdef DWDEBUG
771 fprintf(f, "Done Calc depth %d\r\nusedx = %d, usedy = %d, usedpadx = %d, usedpady = %d, currentx = %d, currenty = %d, uxmax = %d, uymax = %d\r\n\r\n",
772 *depth, *usedx, *usedy, *usedpadx, *usedpady, currentx, currenty, uxmax, uymax);
773 reopen();
774 #endif
775
776 /* The second pass is for expansion and actual placement. */
777 if(pass > 1)
778 {
779 /* Any SIZEEXPAND items should be set to uxmax/uymax */
780 for(z=0;z<thisbox->count;z++)
781 {
782 if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == BOXVERT)
783 thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2);
784 if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == BOXHORZ)
785 thisbox->items[z].height = uymax-(thisbox->items[z].pad*2);
786 /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */
787 if(thisbox->items[z].type == TYPEBOX)
788 {
789 Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
790
791 if(tmp)
792 {
793 if(*depth > 0)
794 {
795 if(thisbox->type == BOXVERT)
796 {
797 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/((float)(tmp->minwidth-((thisbox->items[z].pad*2)+(thisbox->pad*2))));
798 tmp->width = thisbox->items[z].width;
799 }
800 if(thisbox->type == BOXHORZ)
801 {
802 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/((float)(tmp->minheight-((thisbox->items[z].pad*2)+(thisbox->pad*2))));
803 tmp->height = thisbox->items[z].height;
804 }
805 }
806
807 (*depth)++;
808
809 /*tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx) )/((float)(tmp->minwidth-tmp->upx));
810 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(tmp->minheight-tmp->upy));*/
811
812 #ifdef DWDEBUG
813 fprintf(f, "2- Resize Box depth %d\r\nx = %d, y = %d, usedx = %d, usedy = %d, usedpadx = %d, usedpady = %d xratio = %f, yratio = %f,\r\nupx = %d, upy = %d, width = %d, height = %d, minwidth = %d, minheight = %d, box xratio = %f, box yratio = %f\r\n\r\n",
814 *depth, x, y, *usedx, *usedy, *usedpadx, *usedpady, tmp->xratio, tmp->yratio, tmp->upx, tmp->upy, thisbox->items[z].width, thisbox->items[z].height, tmp->minwidth, tmp->minheight, thisbox->xratio, thisbox->yratio);
815 reopen();
816 #endif
817
818 _resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy);
819
820 (*depth)--;
821
822 }
823 }
824 }
825
826 for(z=0;z<(thisbox->count);z++)
827 {
828 int height = thisbox->items[z].height;
829 int width = thisbox->items[z].width;
830 int pad = thisbox->items[z].pad;
831 HWND handle = thisbox->items[z].hwnd;
832
833 /* When upxmax != pad*2 then ratios are incorrect. */
834 vectorx = (int)((width*thisbox->items[z].xratio)-width);
835 vectory = (int)((height*thisbox->items[z].yratio)-height);
836
837 if(width > 0 && height > 0)
838 {
839 char tmpbuf[100];
840 /* This is a hack to fix rounding of the sizing */
841 if(*depth == 0)
842 {
843 vectorx++;
844 vectory++;
845 }
846
847 /* If this item isn't going to expand... reset the vectors to 0 */
848 if(thisbox->items[z].vsize != SIZEEXPAND)
849 vectory = 0;
850 if(thisbox->items[z].hsize != SIZEEXPAND)
851 vectorx = 0;
852
853 WinQueryClassName(handle, 99, tmpbuf);
854
855 if(strncmp(tmpbuf, "#2", 2)==0)
856 {
857 /* Make the combobox big enough to drop down. :) */
858 WinSetWindowPos(handle, HWND_TOP, currentx + pad, (currenty + pad) - 100,
859 width + vectorx, (height + vectory) + 100, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
860 }
861 else if(strncmp(tmpbuf, "#6", 2)==0)
862 {
863 /* Entryfields on OS/2 have a thick border that isn't on Windows and GTK */
864 WinSetWindowPos(handle, HWND_TOP, (currentx + pad) + 3, (currenty + pad) + 3,
865 (width + vectorx) - 6, (height + vectory) - 6, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
866 }
867 else
868 {
869 WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad,
870 width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
871 if(thisbox->items[z].type == TYPEBOX)
872 {
873 Box *boxinfo = WinQueryWindowPtr(handle, QWP_USER);
874
875 if(boxinfo && boxinfo->grouphwnd)
876 WinSetWindowPos(boxinfo->grouphwnd, HWND_TOP, 0, 0,
877 width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
878
879 }
880
881 }
882
883 #ifdef DWDEBUG
884 fprintf(f, "Window Pos depth %d\r\ncurrentx = %d, currenty = %d, pad = %d, width = %d, height = %d, vectorx = %d, vectory = %d, Box type = %s\r\n\r\n",
885 *depth, currentx, currenty, pad, width, height, vectorx, vectory,thisbox->type == BOXHORZ ? "Horizontal" : "Vertical");
886 reopen();
887 #endif
888
889 if(thisbox->type == BOXHORZ)
890 currentx += width + vectorx + (pad * 2);
891 if(thisbox->type == BOXVERT)
892 currenty += height + vectory + (pad * 2);
893 }
894 }
895 }
896 return 0;
897 }
898
899 void _do_resize(Box *thisbox, int x, int y)
900 {
901 if(x != 0 && y != 0) {
902 if(thisbox)
903 {
904 int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0;
905
906 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady);
907
908 if(usedx-usedpadx == 0 || usedy-usedpady == 0)
909 return;
910
911 thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx));
912 thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady));
913
914 #ifdef DWDEBUG
915 fprintf(f, "WM_SIZE Resize Box Pass 1\r\nx = %d, y = %d, usedx = %d, usedy = %d, usedpadx = %d, usedpady = %d xratio = %f, yratio = %f\r\n\r\n",
916 x, y, usedx, usedy, usedpadx, usedpady, thisbox->xratio, thisbox->yratio);
917 reopen();
918 #endif
919
920 usedx = usedy = usedpadx = usedpady = depth = 0;
921
922 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady);
923 #ifdef DWDEBUG
924 fprintf(f, "WM_SIZE Resize Box Pass 2\r\nx = %d, y = %d, usedx = %d, usedy = %d, usedpadx = %d, usedpady = %d\r\n",
925 x, y, usedx, usedy, usedpadx, usedpady);
926 reopen();
927 #endif
928 }
929 }
930 }
931
932 /* This procedure handles WM_QUERYTRACKINFO requests from the frame */
933 MRESULT EXPENTRY _sizeproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
934 {
935 PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER);
936
937 switch(msg)
938 {
939 case WM_QUERYTRACKINFO:
940 {
941 if(blah && *blah)
942 {
943 PTRACKINFO ptInfo;
944 int res;
945 PFNWP myfunc = *blah;
946 res = (int)myfunc(hWnd, msg, mp1, mp2);
947
948 ptInfo = (PTRACKINFO)(mp2);
949
950 ptInfo->ptlMinTrackSize.y = 8;
951 ptInfo->ptlMinTrackSize.x = 8;
952
953 return (MRESULT)res;
954 }
955 }
956 }
957 if(blah && *blah)
958 {
959 PFNWP myfunc = *blah;
960 return myfunc(hWnd, msg, mp1, mp2);
961 }
962
963 return WinDefWindowProc(hWnd, msg, mp1, mp2);
964 }
965 /* Originally just intended for entryfields, it now serves as a generic
966 * procedure for handling TAB presses to change input focus on controls.
967 */
968 MRESULT EXPENTRY _entryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
969 {
970 PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER);
971
972 switch(msg)
973 {
974 case WM_CHAR:
975 if(SHORT1FROMMP(mp2) == '\t')
976 {
977 _shift_focus(hWnd);
978 return FALSE;
979 }
980 break;
981 }
982 if(blah && *blah)
983 {
984 PFNWP myfunc = *blah;
985 return myfunc(hWnd, msg, mp1, mp2);
986 }
987
988 return WinDefWindowProc(hWnd, msg, mp1, mp2);
989 }
990
991 /* Handle correct painting of a combobox with the WS_CLIPCHILDREN
992 * flag enabled, and also handle TABs to switch input focus.
993 */
994 MRESULT EXPENTRY _comboproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
995 {
996 PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER);
997
998 switch(msg)
999 {
1000 case WM_CHAR:
1001 if(SHORT1FROMMP(mp2) == '\t')
1002 {
1003 _shift_focus(hWnd);
1004 return FALSE;
1005 }
1006 break;
1007 case WM_PAINT:
1008 {
1009 HWND parent = WinQueryWindow(hWnd, QW_PARENT);
1010 ULONG bcol, av[32];
1011 HPS hpsPaint;
1012 POINTL ptl; /* Add 6 because it has a thick border like the entryfield */
1013 unsigned long width, height, thumbheight = WinQuerySysValue(HWND_DESKTOP, SV_CYVSCROLLARROW) + 6;
1014
1015 WinQueryPresParam(parent, PP_BACKGROUNDCOLORINDEX, 0, &bcol, sizeof(ULONG), &av, QPF_ID1COLORINDEX | QPF_NOINHERIT);
1016 dw_window_get_pos_size(hWnd, 0, 0, &width, &height);
1017
1018 hpsPaint = WinGetPS(hWnd);
1019 GpiSetColor(hpsPaint, CLR_PALEGRAY);
1020
1021 ptl.x = 0;
1022 ptl.y = 99;
1023 GpiMove(hpsPaint, &ptl);
1024
1025 ptl.x = width;
1026 ptl.y = height - thumbheight;
1027 GpiBox(hpsPaint, DRO_FILL, &ptl, 0, 0);
1028
1029 WinReleasePS(hpsPaint);
1030 }
1031 break;
1032 }
1033 if(blah && *blah)
1034 {
1035 PFNWP myfunc = *blah;
1036 return myfunc(hWnd, msg, mp1, mp2);
1037 }
1038
1039 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1040 }
1041
1042 void _GetPPFont(HWND hwnd, char *buff)
1043 {
1044 ULONG AttrFound;
1045 BYTE AttrValue[128];
1046 ULONG cbRetLen;
1047
1048 cbRetLen = WinQueryPresParam(hwnd,
1049 PP_FONTNAMESIZE,
1050 0,
1051 &AttrFound,
1052 sizeof(AttrValue),
1053 &AttrValue,
1054 QPF_NOINHERIT);
1055
1056 if(PP_FONTNAMESIZE == AttrFound && cbRetLen)
1057 {
1058 memcpy(buff, AttrValue, cbRetLen);
1059 }
1060 }
1061
1062 /* Returns height of specified window. */
1063 int _get_height(HWND handle)
1064 {
1065 unsigned long height;
1066 dw_window_get_pos_size(handle, NULL, NULL, NULL, &height);
1067 return (int)height;
1068 }
1069
1070 /* Find the height of the frame a desktop style window is sitting on */
1071 int _get_frame_height(HWND handle)
1072 {
1073 while(handle)
1074 {
1075 HWND client;
1076 if((client = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE)
1077 {
1078 return _get_height(WinQueryWindow(handle, QW_PARENT));
1079 }
1080 handle = WinQueryWindow(handle, QW_PARENT);
1081 }
1082 return dw_screen_height();
1083 }
1084
1085 #ifndef NO_SIGNALS
1086 MRESULT EXPENTRY _run_event(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1087 {
1088 int result = -1;
1089 SignalHandler *tmp = Root;
1090 ULONG origmsg = msg;
1091
1092 if(msg == WM_BUTTON2DOWN || msg == WM_BUTTON3DOWN)
1093 msg = WM_BUTTON1DOWN;
1094 if(msg == WM_BUTTON2UP || msg == WM_BUTTON3UP)
1095 msg = WM_BUTTON1UP;
1096
1097 /* Find any callbacks for this function */
1098 while(tmp)
1099 {
1100 if(tmp->message == msg || msg == WM_CONTROL)
1101 {
1102 switch(msg)
1103 {
1104 case WM_SIZE:
1105 {
1106 int (*sizefunc)(HWND, int, int, void *) = (int (*)(HWND, int, int, void *))tmp->signalfunction;
1107
1108 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd)
1109 {
1110 result = sizefunc(tmp->window, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), tmp->data);
1111 tmp = NULL;
1112 }
1113 }
1114 break;
1115 case WM_BUTTON1DOWN:
1116 {
1117 POINTS pts = (*((POINTS*)&mp1));
1118 int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction;
1119
1120 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
1121 {
1122 int button;
1123
1124 switch(origmsg)
1125 {
1126 case WM_BUTTON1DOWN:
1127 button = 1;
1128 break;
1129 case WM_BUTTON2DOWN:
1130 button = 2;
1131 break;
1132 case WM_BUTTON3DOWN:
1133 button = 3;
1134 break;
1135 }
1136
1137 result = buttonfunc(tmp->window, pts.x, _get_frame_height(tmp->window) - pts.y, button, tmp->data);
1138 tmp = NULL;
1139 }
1140 }
1141 break;
1142 case WM_BUTTON1UP:
1143 {
1144 POINTS pts = (*((POINTS*)&mp1));
1145 int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction;
1146
1147 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
1148 {
1149 int button;
1150
1151 switch(origmsg)
1152 {
1153 case WM_BUTTON1UP:
1154 button = 1;
1155 break;
1156 case WM_BUTTON2UP:
1157 button = 2;
1158 break;
1159 case WM_BUTTON3UP:
1160 button = 3;
1161 break;
1162 }
1163
1164 result = buttonfunc(tmp->window, pts.x, WinQueryWindow(tmp->window, QW_PARENT) == HWND_DESKTOP ? dw_screen_height() - pts.y : _get_height(tmp->window) - pts.y, button, tmp->data);
1165 tmp = NULL;
1166 }
1167 }
1168 break;
1169 case WM_MOUSEMOVE:
1170 {
1171 int (*motionfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction;
1172
1173 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
1174 {
1175 int keys = 0;
1176 SHORT x = SHORT1FROMMP(mp1), y = SHORT2FROMMP(mp1);
1177
1178 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000)
1179 keys = DW_BUTTON1_MASK;
1180 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000)
1181 keys |= DW_BUTTON2_MASK;
1182 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000)
1183 keys |= DW_BUTTON3_MASK;
1184
1185 result = motionfunc(tmp->window, x, _get_frame_height(tmp->window) - y, keys, tmp->data);
1186 tmp = NULL;
1187 }
1188 }
1189 break;
1190 case WM_CHAR:
1191 {
1192 int (*keypressfunc)(HWND, int, void *) = (int (*)(HWND, int, void *))tmp->signalfunction;
1193
1194 if(hWnd == tmp->window)
1195 {
1196 result = keypressfunc(tmp->window, SHORT1FROMMP(mp2), tmp->data);
1197 tmp = NULL;
1198 }
1199 }
1200 break;
1201 case WM_CLOSE:
1202 {
1203 int (*closefunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction;
1204
1205 if(hWnd == tmp->window || hWnd == WinWindowFromID(tmp->window, FID_CLIENT))
1206 {
1207 result = closefunc(tmp->window, tmp->data);
1208 tmp = NULL;
1209 }
1210 }
1211 break;
1212 case WM_PAINT:
1213 {
1214 HPS hps;
1215 DWExpose exp;
1216 int (*exposefunc)(HWND, DWExpose *, void *) = (int (*)(HWND, DWExpose *, void *))tmp->signalfunction;
1217 RECTL rc;
1218
1219 if(hWnd == tmp->window)
1220 {
1221 int height = _get_height(hWnd);
1222
1223 hps = WinBeginPaint(hWnd, 0L, &rc);
1224 exp.x = rc.xLeft;
1225 exp.y = height - rc.yTop - 1;
1226 exp.width = rc.xRight - rc. xLeft;
1227 exp.height = rc.yTop - rc.yBottom;
1228 result = exposefunc(hWnd, &exp, tmp->data);
1229 WinEndPaint(hps);
1230 }
1231 }
1232 break;
1233 case WM_COMMAND:
1234 {
1235 int (*clickfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction;
1236 ULONG command = COMMANDMSG(&msg)->cmd;
1237
1238 if(tmp->window < 65536 && command == tmp->window)
1239 {
1240 result = clickfunc(tmp->window, tmp->data);
1241 tmp = NULL;
1242 }
1243 }
1244 break;
1245 case WM_CONTROL:
1246 if(tmp->message == SHORT2FROMMP(mp1))
1247 {
1248 switch(SHORT2FROMMP(mp1))
1249 {
1250 case CN_ENTER:
1251 {
1252 int (*containerselectfunc)(HWND, char *, void *) = (int (*)(HWND, char *, void *))tmp->signalfunction;
1253 int id = SHORT1FROMMP(mp1);
1254 HWND conthwnd = dw_window_from_id(hWnd, id);
1255 char *text = NULL;
1256
1257 if(mp2)
1258 {
1259 PRECORDCORE pre;
1260
1261 pre = ((PNOTIFYRECORDENTER)mp2)->pRecord;
1262 if(pre)
1263 text = pre->pszIcon;
1264 }
1265
1266 if(tmp->window == conthwnd)
1267 {
1268 result = containerselectfunc(tmp->window, text, tmp->data);
1269 tmp = NULL;
1270 }
1271 }
1272 break;
1273 case CN_CONTEXTMENU:
1274 {
1275 int (*containercontextfunc)(HWND, char *, int, int, void *) = (int (*)(HWND, char *, int, int, void *))tmp->signalfunction;
1276 int id = SHORT1FROMMP(mp1);
1277 HWND conthwnd = dw_window_from_id(hWnd, id);
1278 char *text = NULL;
1279 LONG x,y;
1280
1281 if(mp2)
1282 {
1283 PRECORDCORE pre;
1284
1285 pre = (PRECORDCORE)mp2;
1286 text = pre->pszIcon;
1287 }
1288
1289
1290 dw_pointer_query_pos(&x, &y);
1291
1292 if(tmp->window == conthwnd)
1293 {
1294 result = containercontextfunc(tmp->window, text, x, y, tmp->data);
1295 tmp = NULL;
1296 }
1297 }
1298 break;
1299 case LN_SELECT:
1300 {
1301 int (*listboxselectfunc)(HWND, int, void *) = (int (*)(HWND, int, void *))tmp->signalfunction;
1302 int id = SHORT1FROMMP(mp1);
1303 HWND conthwnd = dw_window_from_id(hWnd, id);
1304
1305 if(tmp->window == conthwnd || (!id && tmp->window == (HWND)mp2))
1306 {
1307 char buf1[500], classbuf[100];
1308 unsigned int index = dw_listbox_selected(tmp->window);
1309
1310 dw_listbox_query_text(tmp->window, index, buf1, 500);
1311
1312 WinQueryClassName(tmp->window, 99, classbuf);
1313
1314 if(id && strncmp(classbuf, "#6", 2)==0)
1315 {
1316 char *buf2;
1317
1318 buf2 = dw_window_get_text(tmp->window);
1319
1320 /* This is to make sure the listboxselect function doesn't
1321 * get called if the user is modifying the entry text.
1322 */
1323 if(buf2 && *buf2 && *buf1 && strncmp(buf1, buf2, 500) == 0)
1324 result = listboxselectfunc(tmp->window, index, tmp->data);
1325
1326 if(buf2)
1327 free(buf2);
1328 }
1329 else
1330 result = listboxselectfunc(tmp->window, index, tmp->data);
1331
1332 tmp = NULL;
1333 }
1334 }
1335 break;
1336 }
1337 }
1338 break;
1339 }
1340 }
1341 if(tmp)
1342 tmp = tmp->next;
1343
1344 }
1345
1346 return (MRESULT)result;
1347 }
1348 #endif
1349
1350 /* Handles control messages sent to the box (owner). */
1351 MRESULT EXPENTRY _controlproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1352 {
1353 Box *blah = WinQueryWindowPtr(hWnd, QWP_USER);
1354
1355 switch(msg)
1356 {
1357 case WM_CONTROL:
1358 _run_event(hWnd, msg, mp1, mp2);
1359 break;
1360 }
1361 if(blah && blah->oldproc)
1362 {
1363 return blah->oldproc(hWnd, msg, mp1, mp2);
1364 }
1365
1366 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1367 }
1368
1369 /* The main window procedure for Dynamic Windows, all the resizing code is done here. */
1370 MRESULT EXPENTRY _wndproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1371 {
1372 int result = -1;
1373 static int command_active = 0;
1374 void (* windowfunc)(PVOID) = 0L;
1375
1376 if(filterfunc)
1377 result = filterfunc(hWnd, msg, mp1, mp2);
1378
1379 #ifndef NO_SIGNALS
1380 if(result == -1 && !command_active)
1381 {
1382 /* Make sure we don't end up in infinite recursion */
1383 command_active = 1;
1384
1385 result = (int)_run_event(hWnd, msg, mp1, mp2);
1386
1387 command_active = 0;
1388 }
1389 #endif
1390
1391 /* Now that any handlers are done... do normal processing */
1392 switch( msg )
1393 {
1394 case WM_ERASEBACKGROUND:
1395 return 0;
1396
1397 case WM_PAINT:
1398 {
1399 HPS hps;
1400 RECTL rc;
1401
1402 hps = WinBeginPaint( hWnd, 0L, &rc );
1403 WinEndPaint( hps );
1404 break;
1405 }
1406
1407 case WM_SIZE:
1408 {
1409 Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER);
1410
1411 if(!SHORT1FROMMP(mp2) && !SHORT2FROMMP(mp2))
1412 return (MPARAM)TRUE;
1413
1414 if(mybox)
1415 {
1416 /* Hide the window when recalculating to reduce
1417 * CPU load.
1418 */
1419 WinShowWindow(hWnd, FALSE);
1420
1421 _do_resize(mybox, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2));
1422
1423 WinShowWindow(hWnd, TRUE);
1424 }
1425 }
1426 break;
1427 case WM_MINMAXFRAME:
1428 {
1429 Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER);
1430 SWP *swp = (SWP *)mp1;
1431
1432 if(mybox && (swp->fl & SWP_MAXIMIZE))
1433 {
1434 int z;
1435
1436 /* Hide the window when recalculating to reduce
1437 * CPU load.
1438 */
1439 WinShowWindow(hWnd, FALSE);
1440
1441 _do_resize(mybox, swp->cx, swp->cy);
1442
1443 if(mybox->count == 1 && mybox->items[0].type == TYPEBOX)
1444 {
1445 mybox = (Box *)WinQueryWindowPtr(mybox->items[0].hwnd, QWP_USER);
1446
1447 for(z=0;z<mybox->count;z++)
1448 {
1449 char tmpbuf[100];
1450
1451 WinQueryClassName(mybox->items[z].hwnd, 99, tmpbuf);
1452
1453 /* If we have a notebook we resize the page again. */
1454 if(strncmp(tmpbuf, "#40", 3)==0)
1455 {
1456 unsigned long x, y, width, height;
1457 int page = dw_notebook_page_query(mybox->items[z].hwnd);
1458 HWND pagehwnd = (HWND)WinSendMsg(mybox->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(page), 0);
1459 RECTL rc;
1460
1461 Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER);
1462 if(pagebox)
1463 {
1464 dw_window_get_pos_size(mybox->items[z].hwnd, &x, &y, &width, &height);
1465
1466 rc.xLeft = x;
1467 rc.yBottom = y;
1468 rc.xRight = x + width;
1469 rc.yTop = y + height;
1470
1471 WinSendMsg(mybox->items[z].hwnd, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE);
1472
1473 _do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom);
1474 }
1475
1476 }
1477 }
1478
1479 }
1480
1481 WinShowWindow(hWnd, TRUE);
1482 }
1483 }
1484 break;
1485 case WM_CLOSE:
1486 dw_window_destroy(WinQueryWindow(hWnd, QW_PARENT));
1487 return (MRESULT)TRUE;
1488 case WM_USER:
1489 windowfunc = (void (*)(void *))mp1;
1490
1491 if(windowfunc)
1492 windowfunc((void *)mp2);
1493 break;
1494 case WM_CHAR:
1495 if(SHORT1FROMMP(mp2) == '\t')
1496 {
1497 _shift_focus(hWnd);
1498 return FALSE;
1499 }
1500 break;
1501 case WM_DESTROY:
1502 /* Free memory before destroying */
1503 _free_window_memory(hWnd);
1504 break;
1505 }
1506 if(filterfunc && result != -1)
1507 return (MRESULT)result;
1508 else
1509 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1510 }
1511
1512 void _changebox(Box *thisbox, int percent, int type)
1513 {
1514 int z;
1515
1516 for(z=0;z<thisbox->count;z++)
1517 {
1518 if(thisbox->items[z].type == TYPEBOX)
1519 {
1520 Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
1521 _changebox(tmp, percent, type);
1522 }
1523 else
1524 {
1525 if(type == BOXHORZ)
1526 {
1527 if(thisbox->items[z].hsize == SIZEEXPAND)
1528 thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0)));
1529 }
1530 else
1531 {
1532 if(thisbox->items[z].vsize == SIZEEXPAND)
1533 thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0)));
1534 }
1535 }
1536 }
1537 }
1538
1539 /* This handles any activity on the splitbars (sizers) */
1540 MRESULT EXPENTRY _splitwndproc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1541 {
1542 HWND hwndFrame = 0;
1543 Box *thisbox = 0;
1544
1545 hwndFrame = WinQueryWindow(hwnd, QW_PARENT);
1546 if(hwndFrame)
1547 thisbox = WinQueryWindowPtr(hwndFrame, QWL_USER);
1548
1549 switch (msg)
1550 {
1551 case WM_ACTIVATE:
1552 case WM_SETFOCUS:
1553 return (MRESULT)(FALSE);
1554
1555 case WM_PAINT:
1556 {
1557 HPS hpsPaint;
1558 RECTL rclPaint;
1559 POINTL ptlStart[SPLITBAR_WIDTH];
1560 POINTL ptlEnd[SPLITBAR_WIDTH];
1561 USHORT i;
1562
1563 hpsPaint = WinBeginPaint(hwnd, 0, 0);
1564 WinQueryWindowRect(hwnd, &rclPaint);
1565
1566 if(thisbox->type == BOXHORZ)
1567 {
1568 for(i = 0; i < SPLITBAR_WIDTH; i++)
1569 {
1570 ptlStart[i].x = rclPaint.xLeft + i;
1571 ptlStart[i].y = rclPaint.yTop;
1572
1573 ptlEnd[i].x = rclPaint.xLeft + i;
1574 ptlEnd[i].y = rclPaint.yBottom;
1575 }
1576 }
1577 else
1578 {
1579 for(i = 0; i < SPLITBAR_WIDTH; i++)
1580 {
1581 ptlStart[i].x = rclPaint.xLeft;
1582 ptlStart[i].y = rclPaint.yBottom + i;
1583
1584 ptlEnd[i].x = rclPaint.xRight;
1585 ptlEnd[i].y = rclPaint.yBottom + i;
1586 }
1587 }
1588
1589 for(i = 0; i < SPLITBAR_WIDTH; i++)
1590 {
1591 GpiSetColor( hpsPaint, lColor[i]);
1592 GpiMove(hpsPaint, &ptlStart[i]);
1593 GpiLine(hpsPaint, &ptlEnd[i]);
1594 }
1595 WinEndPaint(hpsPaint);
1596 }
1597 return MRFROMSHORT(FALSE);
1598
1599 case WM_MOUSEMOVE:
1600 {
1601 if(thisbox->type == BOXHORZ)
1602 WinSetPointer(HWND_DESKTOP,
1603 WinQuerySysPointer(HWND_DESKTOP,
1604 SPTR_SIZEWE,
1605 FALSE));
1606 else
1607 WinSetPointer(HWND_DESKTOP,
1608 WinQuerySysPointer(HWND_DESKTOP,
1609 SPTR_SIZENS,
1610 FALSE));
1611 }
1612 return MRFROMSHORT(FALSE);
1613 case WM_BUTTON1DOWN:
1614 {
1615 APIRET rc;
1616 RECTL rclFrame;
1617 RECTL rclBounds;
1618 RECTL rclStart;
1619 USHORT startSize, orig, actual;
1620
1621 WinQueryWindowRect(hwnd, &rclFrame);
1622 WinQueryWindowRect(hwnd, &rclStart);
1623
1624 WinQueryWindowRect(hwndFrame, &rclBounds);
1625
1626 WinMapWindowPoints(hwndFrame, HWND_DESKTOP,
1627 (PPOINTL)&rclBounds, 2);
1628 WinMapWindowPoints(hwnd, HWND_DESKTOP,
1629 (PPOINTL)&rclStart, 2);
1630
1631 {
1632 int z, pastsplitbar = FALSE, found = FALSE;
1633 orig = actual = 0;
1634
1635 for(z=0;z<thisbox->count;z++)
1636 {
1637 if(thisbox->items[z].hwnd == hwnd)
1638 pastsplitbar = TRUE;
1639 else
1640 {
1641 if(thisbox->type == BOXHORZ)
1642 {
1643 int tmpwidth, tmporigwidth;
1644
1645 if(thisbox->items[z].type == TYPEBOX)
1646 _count_size(thisbox->items[z].hwnd, BOXHORZ, &tmpwidth, &tmporigwidth);
1647 else
1648 {
1649 tmpwidth = thisbox->items[z].width;
1650 tmporigwidth = thisbox->items[z].origwidth;
1651 }
1652
1653 if(thisbox->items[z].hsize != SIZESTATIC && tmpwidth > actual && tmporigwidth)
1654 {
1655 found = pastsplitbar;
1656 orig = tmporigwidth;
1657 actual = tmpwidth;
1658 }
1659 }
1660 else
1661 {
1662 int tmpheight, tmporigheight;
1663
1664 if(thisbox->items[z].type == TYPEBOX)
1665 _count_size(thisbox->items[z].hwnd, BOXVERT, &tmpheight, &tmporigheight);
1666 else
1667 {
1668 tmpheight = thisbox->items[z].height;
1669 tmporigheight = thisbox->items[z].origheight;
1670 }
1671
1672 if(thisbox->items[z].vsize != SIZESTATIC && tmpheight > actual && tmporigheight)
1673 {
1674 found = pastsplitbar;
1675 orig = tmporigheight;
1676 actual = tmpheight;
1677 }
1678 }
1679 }
1680 }
1681
1682 /* If we couldn't determine a valid scale... then abort */
1683 if(!orig || !actual)
1684 return MRFROMSHORT(FALSE);
1685
1686 if(thisbox->type == BOXHORZ)
1687 {
1688 if(found)
1689 startSize = (rclStart.xLeft - rclBounds.xLeft)
1690 * (((float)actual)/((float)orig));
1691 else
1692 startSize = (rclStart.xLeft - rclBounds.xLeft)
1693 * (((float)orig)/((float)actual));
1694 }
1695 else
1696 {
1697 if(found)
1698 startSize = (rclStart.yBottom - rclBounds.yBottom)
1699 * (((float)actual)/((float)orig));
1700 else
1701 startSize = (rclStart.yBottom - rclBounds.yBottom)
1702 * (((float)orig)/((float)actual));
1703 }
1704 }
1705
1706 rc = _TrackRectangle(hwnd, &rclFrame, &rclBounds);
1707
1708 if(rc == TRUE)
1709 {
1710 USHORT usNewRB;
1711 USHORT percent;
1712 int z;
1713
1714 if(thisbox->type == BOXHORZ)
1715 {
1716 usNewRB = rclFrame.xLeft
1717 - rclBounds.xLeft;
1718 }
1719 else
1720 {
1721 usNewRB = rclFrame.yBottom
1722 - rclBounds.yBottom;
1723 }
1724
1725 /* We don't want the item to disappear completely */
1726 if(!usNewRB)
1727 usNewRB++;
1728
1729 if(!startSize)
1730 startSize++;
1731
1732 percent = (usNewRB*100)/startSize;
1733
1734 for(z=0;z<thisbox->count;z++)
1735 {
1736 if(thisbox->items[z].type == TYPEBOX)
1737 {
1738 Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
1739 _changebox(tmp, percent, thisbox->type);
1740 }
1741 else
1742 {
1743 if(thisbox->items[z].hwnd == hwnd)
1744 percent = (startSize*100)/usNewRB;
1745
1746 if(thisbox->type == BOXHORZ)
1747 {
1748 if(thisbox->items[z].hsize == SIZEEXPAND)
1749 thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0)));
1750 }
1751 else
1752 {
1753 if(thisbox->items[z].vsize == SIZEEXPAND)
1754 thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0)));
1755 }
1756 }
1757 }
1758
1759 _ResetWindow(WinQueryWindow(hwnd, QW_OWNER));
1760 }
1761 }
1762 return MRFROMSHORT(FALSE);
1763 }
1764 return WinDefWindowProc(hwnd, msg, mp1, mp2);
1765 }
1766
1767 /* Function: BubbleProc
1768 * Abstract: Subclass procedure for bubble help
1769 */
1770 MRESULT EXPENTRY _BubbleProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1771 {
1772 MRESULT res;
1773 PFNWP proc = (PFNWP)WinQueryWindowPtr(hwnd, QWL_USER);
1774
1775 if(proc)
1776 res = proc(hwnd, msg, mp1, mp2);
1777 else
1778 res = WinDefWindowProc(hwnd, msg, mp1, mp2);
1779
1780 if(msg == WM_PAINT)
1781 {
1782 POINTL ptl;
1783 HPS hpsTemp;
1784 RECTL rcl;
1785 int height, width;
1786
1787 WinQueryWindowRect(hwnd, &rcl);
1788 height = rcl.yTop - rcl.yBottom - 1;
1789 width = rcl.xRight - rcl.xLeft - 1;
1790
1791 /* Draw a border around the bubble help */
1792 hpsTemp = WinGetPS(hwnd);
1793 GpiSetColor(hpsTemp, DW_CLR_BLACK);
1794 ptl.x = ptl.y = 0;
1795 GpiMove(hpsTemp, &ptl);
1796 ptl.x = 0;
1797 ptl.y = height;
1798 GpiLine(hpsTemp, &ptl);
1799 ptl.x = ptl.y = 0;
1800 GpiMove(hpsTemp, &ptl);
1801 ptl.y = 0;
1802 ptl.x = width;
1803 GpiLine(hpsTemp, &ptl);
1804 ptl.x = width;
1805 ptl.y = height;
1806 GpiMove(hpsTemp, &ptl);
1807 ptl.x = 0;
1808 ptl.y = height;
1809 GpiLine(hpsTemp, &ptl);
1810 ptl.x = width;
1811 ptl.y = height;
1812 GpiMove(hpsTemp, &ptl);
1813 ptl.y = 0;
1814 ptl.x = width;
1815 GpiLine(hpsTemp, &ptl);
1816 WinReleasePS(hpsTemp);
1817 }
1818 return res;
1819 }
1820
1821 /* Function: BtProc
1822 * Abstract: Subclass procedure for buttons
1823 */
1824
1825 MRESULT EXPENTRY _BtProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1826 {
1827 BubbleButton *bubble;
1828
1829 bubble = (BubbleButton *)WinQueryWindowPtr(hwnd, QWL_USER);
1830
1831 if(!bubble)
1832 return WinDefWindowProc(hwnd, msg, mp1, mp2);
1833
1834 switch(msg)
1835 {
1836 #ifndef NO_SIGNALS
1837 case WM_BUTTON1UP:
1838 {
1839 SignalHandler *tmp = Root;
1840
1841 if(WinIsWindowEnabled(hwnd))
1842 {
1843 /* Find any callbacks for this function */
1844 while(tmp)
1845 {
1846 if(tmp->message == WM_COMMAND)
1847 {
1848 /* Make sure it's the right window, and the right ID */
1849 if(tmp->window == hwnd)
1850 {
1851 /* Due to the fact that if we run the function
1852 * here, finishing actions on the button will occur
1853 * after we run the signal handler. So we post the
1854 * message so the button can finish what it needs to
1855 * do before we run our handler.
1856 */
1857 WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0);
1858 tmp = NULL;
1859 }
1860 }
1861 if(tmp)
1862 tmp= tmp->next;
1863 }
1864 }
1865 }
1866 break;
1867 case WM_USER:
1868 {
1869 SignalHandler *tmp = (SignalHandler *)mp1;
1870 int (*clickfunc)(HWND, void *) = NULL;
1871
1872 if(tmp)
1873 {
1874 clickfunc = (int (*)(HWND, void *))tmp->signalfunction;
1875
1876 clickfunc(tmp->window, tmp->data);
1877 }
1878 }
1879 break;
1880 #endif
1881 case WM_CHAR:
1882 {
1883 #ifndef NO_SIGNALS
1884 /* A button press should also occur for an ENTER or SPACE press
1885 * while the button has the active input focus.
1886 */
1887 if(SHORT1FROMMP(mp2) == '\r' || SHORT1FROMMP(mp2) == ' ')
1888 {
1889 SignalHandler *tmp = Root;
1890
1891 /* Find any callbacks for this function */
1892 while(tmp)
1893 {
1894 if(tmp->message == WM_COMMAND)
1895 {
1896 /* Make sure it's the right window, and the right ID */
1897 if(tmp->window == hwnd)
1898 {
1899 WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0);
1900 tmp = NULL;
1901 }
1902 }
1903 if(tmp)
1904 tmp= tmp->next;
1905 }
1906 }
1907 #endif
1908 if(SHORT1FROMMP(mp2) == '\t')
1909 {
1910 _shift_focus(hwnd);
1911 return FALSE;
1912 }
1913 }
1914 break;
1915 case 0x041f:
1916 if (hwndBubble)
1917 {
1918 WinDestroyWindow(hwndBubble);
1919 hwndBubble = 0;
1920 }
1921 break;
1922
1923 case 0x041e:
1924
1925 if(!*bubble->bubbletext)
1926 break;
1927
1928
1929 if(hwndBubble)
1930 {
1931 WinDestroyWindow(hwndBubble);
1932 hwndBubble = 0;
1933 }
1934
1935 if(!hwndBubble)
1936 {
1937 HPS hpsTemp = 0;
1938 LONG lHight;
1939 LONG lWidth;
1940 POINTL txtPointl[TXTBOX_COUNT];
1941 POINTL ptlWork = {0,0};
1942 ULONG ulColor = DW_CLR_YELLOW;
1943 void *blah;
1944
1945 hwndBubbleLast = hwnd;
1946 hwndBubble = WinCreateWindow(HWND_DESKTOP,
1947 WC_STATIC,
1948 "",
1949 SS_TEXT |
1950 DT_CENTER |
1951 DT_VCENTER,
1952 0,0,0,0,
1953 HWND_DESKTOP,
1954 HWND_TOP,
1955 0,
1956 NULL,
1957 NULL);
1958
1959 WinSetPresParam(hwndBubble,
1960 PP_FONTNAMESIZE,
1961 sizeof(DefaultFont),
1962 DefaultFont);
1963
1964
1965 WinSetPresParam(hwndBubble,
1966 PP_BACKGROUNDCOLORINDEX,
1967 sizeof(ulColor),
1968 &ulColor);
1969
1970 WinSetWindowText(hwndBubble,
1971 bubble->bubbletext);
1972
1973 WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptlWork, 1);
1974
1975 hpsTemp = WinGetPS(hwndBubble);
1976 GpiQueryTextBox(hpsTemp,
1977 strlen(bubble->bubbletext),
1978 bubble->bubbletext,
1979 TXTBOX_COUNT,
1980 txtPointl);
1981 WinReleasePS(hpsTemp);
1982
1983 lWidth = txtPointl[TXTBOX_TOPRIGHT].x -
1984 txtPointl[TXTBOX_TOPLEFT ].x + 8;
1985
1986 lHight = txtPointl[TXTBOX_TOPLEFT].y -
1987 txtPointl[TXTBOX_BOTTOMLEFT].y + 8;
1988
1989 ptlWork.y -= lHight;
1990
1991 blah = (void *)WinSubclassWindow(hwndBubble, _BubbleProc);
1992
1993 if(blah)
1994 WinSetWindowPtr(hwndBubble, QWP_USER, blah);
1995
1996 WinSetWindowPos(hwndBubble,
1997 HWND_TOP,
1998 ptlWork.x,
1999 ptlWork.y,
2000 lWidth,
2001 lHight,
2002 SWP_SIZE | SWP_MOVE | SWP_SHOW);
2003 }
2004 break;
2005 }
2006
2007 if(!bubble->pOldProc)
2008 return WinDefWindowProc(hwnd, msg, mp1, mp2);
2009 return bubble->pOldProc(hwnd, msg, mp1, mp2);
2010 }
2011
2012 MRESULT EXPENTRY _RendProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2013 {
2014 int res = 0;
2015 #ifndef NO_SIGNALS
2016 res = (int)_run_event(hwnd, msg, mp1, mp2);
2017 #endif
2018 switch(msg)
2019 {
2020 case WM_BUTTON1DOWN:
2021 case WM_BUTTON2DOWN:
2022 case WM_BUTTON3DOWN:
2023 if(!res)
2024 WinSetFocus(HWND_DESKTOP, hwnd);
2025 return (MPARAM)TRUE;
2026 }
2027 return WinDefWindowProc(hwnd, msg, mp1, mp2);
2028 }
2029
2030 /*
2031 * Initializes the Dynamic Windows engine.
2032 * Parameters:
2033 * newthread: True if this is the only thread.
2034 * False if there is already a message loop running.
2035 */
2036 int dw_init(int newthread)
2037 {
2038 APIRET rc;
2039
2040 if(newthread)
2041 {
2042 dwhab = WinInitialize(0);
2043 dwhmq = WinCreateMsgQueue(dwhab, 0);
2044 }
2045
2046 rc = WinRegisterClass(dwhab, ClassName, _wndproc, CS_SIZEREDRAW | CS_CLIPCHILDREN, 32);
2047 rc = WinRegisterClass(dwhab, SplitbarClassName, _splitwndproc, 0L, 32);
2048
2049 #ifdef DWDEBUG
2050 f = fopen("dw.log", "wt");
2051 #endif
2052 return rc;
2053 }
2054
2055 /*
2056 * Runs a message loop for Dynamic Windows.
2057 * Parameters:
2058 * currenthab: The handle to the current anchor block
2059 * or NULL if this DW is handling the message loop.
2060 * func: Function pointer to the message filter function.
2061 */
2062 void dw_main(HAB currenthab, void *func)
2063 {
2064 QMSG qmsg;
2065 HAB habtouse;
2066
2067 if(!currenthab)
2068 habtouse = dwhab;
2069 else
2070 habtouse = currenthab;
2071
2072 /* Setup the filter function */
2073 filterfunc = (int (* EXPENTRY)(HWND, ULONG, MPARAM, MPARAM))func;
2074
2075 _dwtid = dw_thread_id();
2076
2077 while (WinGetMsg(habtouse, &qmsg, 0, 0, 0))
2078 WinDispatchMsg(habtouse, &qmsg);
2079
2080 #ifdef DWDEBUG
2081 fclose(f);
2082 #endif
2083
2084 if(!currenthab)
2085 {
2086 WinDestroyMsgQueue(dwhmq);
2087 WinTerminate(dwhab);
2088 }
2089 }
2090
2091 /*
2092 * Free's memory allocated by dynamic windows.
2093 * Parameters:
2094 * ptr: Pointer to dynamic windows allocated
2095 * memory to be free()'d.
2096 */
2097 void dw_free(void *ptr)
2098 {
2099 free(ptr);
2100 }
2101
2102 /*
2103 * Allocates and initializes a dialog struct.
2104 * Parameters:
2105 * data: User defined data to be passed to functions.
2106 */
2107 DWDialog *dw_dialog_new(void *data)
2108 {
2109 DWDialog *tmp = malloc(sizeof(DWDialog));
2110
2111 tmp->eve = dw_event_new();
2112 dw_event_reset(tmp->eve);
2113 tmp->data = data;
2114 tmp->done = FALSE;
2115 tmp->result = NULL;
2116
2117 return tmp;
2118 }
2119
2120 /*
2121 * Accepts a dialog struct and returns the given data to the
2122 * initial called of dw_dialog_wait().
2123 * Parameters:
2124 * dialog: Pointer to a dialog struct aquired by dw_dialog_new).
2125 * result: Data to be returned by dw_dialog_wait().
2126 */
2127 int dw_dialog_dismiss(DWDialog *dialog, void *result)
2128 {
2129 dialog->result = result;
2130 dw_event_post(dialog->eve);
2131 dialog->done = TRUE;
2132 return 0;
2133 }
2134
2135 /*
2136 * Accepts a dialog struct waits for dw_dialog_dismiss() to be
2137 * called by a signal handler with the given dialog struct.
2138 * Parameters:
2139 * dialog: Pointer to a dialog struct aquired by dw_dialog_new).
2140 */
2141 void *dw_dialog_wait(DWDialog *dialog)
2142 {
2143 QMSG qmsg;
2144 void *tmp;
2145
2146 while (WinGetMsg(dwhab, &qmsg, 0, 0, 0))
2147 {
2148 WinDispatchMsg(dwhab, &qmsg);
2149 if(dialog->done)
2150 break;
2151 }
2152 dw_event_close(&dialog->eve);
2153 tmp = dialog->result;
2154 free(dialog);
2155 return tmp;
2156 }
2157
2158
2159 /*
2160 * Displays a Message Box with given text and title..
2161 * Parameters:
2162 * title: The title of the message box.
2163 * format: printf style format string.
2164 * ...: Additional variables for use in the format.
2165 */
2166 int dw_messagebox(char *title, char *format, ...)
2167 {
2168 va_list args;
2169 char outbuf[1024];
2170
2171 va_start(args, format);
2172 vsprintf(outbuf, format, args);
2173 va_end(args);
2174
2175 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, outbuf, title, 0, MB_OK | MB_INFORMATION | MB_MOVEABLE);
2176
2177 return strlen(outbuf);
2178 }
2179
2180 /*
2181 * Displays a Message Box with given text and title..
2182 * Parameters:
2183 * title: The title of the message box.
2184 * text: The text to display in the box.
2185 * Returns:
2186 * True if YES False of NO.
2187 */
2188 int dw_yesno(char *title, char *text)
2189 {
2190 if(WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, text, title, 0, MB_YESNO | MB_INFORMATION | MB_MOVEABLE | MB_SYSTEMMODAL)==MBID_YES)
2191 return TRUE;
2192 return FALSE;
2193 }
2194
2195 /*
2196 * Makes the window visible.
2197 * Parameters:
2198 * handle: The window handle to make visible.
2199 */
2200 int dw_window_show(HWND handle)
2201 {
2202 int rc = WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_SHOW);
2203 HSWITCH hswitch;
2204 SWCNTRL swcntrl;
2205
2206 WinSetFocus(HWND_DESKTOP, handle);
2207 _initial_focus(handle);
2208
2209 /* If this window has a switch list entry make sure it is visible */
2210 hswitch = WinQuerySwitchHandle(handle, 0);
2211 if(hswitch)
2212 {
2213 WinQuerySwitchEntry(hswitch, &swcntrl);
2214 swcntrl.uchVisibility = SWL_VISIBLE;
2215 WinChangeSwitchEntry(hswitch, &swcntrl);
2216 }
2217 return rc;
2218
2219 }
2220
2221 /*
2222 * Makes the window invisible.
2223 * Parameters:
2224 * handle: The window handle to make visible.
2225 */
2226 int dw_window_hide(HWND handle)
2227 {
2228 HSWITCH hswitch;
2229 SWCNTRL swcntrl;
2230
2231 /* If this window has a switch list entry make sure it is invisible */
2232 hswitch = WinQuerySwitchHandle(handle, 0);
2233 if(hswitch)
2234 {
2235 WinQuerySwitchEntry(hswitch, &swcntrl);
2236 swcntrl.uchVisibility = SWL_INVISIBLE;
2237 WinChangeSwitchEntry(hswitch, &swcntrl);
2238 }
2239 return WinShowWindow(handle, FALSE);
2240 }
2241
2242 /*
2243 * Destroys a window and all of it's children.
2244 * Parameters:
2245 * handle: The window handle to destroy.
2246 */
2247 int dw_window_destroy(HWND handle)
2248 {
2249 return WinDestroyWindow(handle);
2250 }
2251
2252 /*
2253 * Changes a window's parent to newparent.
2254 * Parameters:
2255 * handle: The window handle to destroy.
2256 * newparent: The window's new parent window.
2257 */
2258 void dw_window_reparent(HWND handle, HWND newparent)
2259 {
2260 HWND blah = WinWindowFromID(newparent, FID_CLIENT);
2261 WinSetParent(handle, blah ? blah : newparent, TRUE);
2262 }
2263
2264 /*
2265 * Sets the font used by a specified window (widget) handle.
2266 * Parameters:
2267 * handle: The window (widget) handle.
2268 * fontname: Name and size of the font in the form "size.fontname"
2269 */
2270 int dw_window_set_font(HWND handle, char *fontname)
2271 {
2272 return WinSetPresParam(handle, PP_FONTNAMESIZE, strlen(fontname)+1, fontname);
2273 }
2274
2275 /*
2276 * Sets the colors used by a specified window (widget) handle.
2277 * Parameters:
2278 * handle: The window (widget) handle.
2279 * fore: Foreground color in DW_RGB format or a default color index.
2280 * back: Background color in DW_RGB format or a default color index.
2281 */
2282 int dw_window_set_color(HWND handle, ULONG fore, ULONG back)
2283 {
2284 if((fore & DW_RGB_COLOR) == DW_RGB_COLOR)
2285 {
2286 RGB2 rgb2;
2287
2288 rgb2.bBlue = DW_BLUE_VALUE(fore);
2289 rgb2.bGreen = DW_GREEN_VALUE(fore);
2290 rgb2.bRed = DW_RED_VALUE(fore);
2291 rgb2.fcOptions = 0;
2292
2293 WinSetPresParam(handle, PP_FOREGROUNDCOLOR, sizeof(RGB2), &rgb2);
2294
2295 }
2296 if((back & DW_RGB_COLOR) == DW_RGB_COLOR)
2297 {
2298 RGB2 rgb2;
2299
2300 rgb2.bBlue = DW_BLUE_VALUE(back);
2301 rgb2.bGreen = DW_GREEN_VALUE(back);
2302 rgb2.bRed = DW_RED_VALUE(back);
2303 rgb2.fcOptions = 0;
2304
2305 WinSetPresParam(handle, PP_BACKGROUNDCOLOR, sizeof(RGB2), &rgb2);
2306 return 0;
2307 }
2308 if((fore & DW_RGB_COLOR) == DW_RGB_COLOR)
2309 return 0;
2310
2311 /* Slight conversion */
2312 if(fore == DW_CLR_BLACK)
2313 fore = CLR_BLACK;
2314 if(fore == DW_CLR_WHITE)
2315 fore = CLR_WHITE;
2316
2317 if(back == DW_CLR_BLACK)
2318 back = CLR_BLACK;
2319 if(back == DW_CLR_WHITE)
2320 back = CLR_WHITE;
2321
2322 return (WinSetPresParam(handle, PP_FOREGROUNDCOLORINDEX, sizeof(ULONG), &fore) |
2323 WinSetPresParam(handle, PP_BACKGROUNDCOLORINDEX, sizeof(ULONG), &back));
2324 }
2325
2326 /*
2327 * Sets the font used by a specified window (widget) handle.
2328 * Parameters:
2329 * handle: The window (widget) handle.
2330 * border: Size of the window border in pixels.
2331 */
2332 int dw_window_set_border(HWND handle, int border)
2333 {
2334 WinSendMsg(handle, WM_SETBORDERSIZE, MPFROMSHORT(border), MPFROMSHORT(border));
2335 return 0;
2336 }
2337
2338 /*
2339 * Captures the mouse input to this window.
2340 * Parameters:
2341 * handle: Handle to receive mouse input.
2342 */
2343 void dw_window_capture(HWND handle)
2344 {
2345 WinSetCapture(HWND_DESKTOP, handle);
2346 }
2347
2348 /*
2349 * Releases previous mouse capture.
2350 */
2351 void dw_window_release(void)
2352 {
2353 WinSetCapture(HWND_DESKTOP, NULLHANDLE);
2354 }
2355
2356 /*
2357 * Tracks this window movement.
2358 * Parameters:
2359 * handle: Handle to frame to be tracked.
2360 */
2361 void dw_window_track(HWND handle)
2362 {
2363 WinSendMsg(handle, WM_TRACKFRAME, MPFROMSHORT(TF_MOVE), 0);
2364 }
2365
2366 /*
2367 * Create a new Window Frame.
2368 * Parameters:
2369 * owner: The Owner's window handle or HWND_DESKTOP.
2370 * title: The Window title.
2371 * flStyle: Style flags, see the PM reference.
2372 */
2373 HWND dw_window_new(HWND hwndOwner, char *title, ULONG flStyle)
2374 {
2375 HWND hwndclient = 0, hwndframe;
2376 Box *newbox = malloc(sizeof(Box));
2377 PFNWP *blah = malloc(sizeof(PFNWP));
2378
2379 newbox->pad = 0;
2380 newbox->type = BOXVERT;
2381 newbox->count = 0;
2382
2383 flStyle |= FCF_NOBYTEALIGN;
2384
2385 hwndframe = WinCreateStdWindow(hwndOwner, 0L, &flStyle, ClassName, title, 0L, NULLHANDLE, 0L, &hwndclient);
2386 *blah = WinSubclassWindow(hwndframe, _sizeproc);
2387 WinSetWindowPtr(hwndframe, QWP_USER, blah);
2388 WinSetWindowPtr(hwndclient, QWP_USER, newbox);
2389
2390 return hwndframe;
2391 }
2392
2393 /*
2394 * Create a new Box to be packed.
2395 * Parameters:
2396 * type: Either BOXVERT (vertical) or BOXHORZ (horizontal).
2397 * pad: Number of pixels to pad around the box.
2398 */
2399 HWND dw_box_new(int type, int pad)
2400 {
2401 Box *newbox = malloc(sizeof(Box));
2402 HWND hwndframe;
2403
2404 newbox->pad = pad;
2405 newbox->type = type;
2406 newbox->count = 0;
2407 newbox->grouphwnd = NULLHANDLE;
2408
2409 hwndframe = WinCreateWindow(HWND_OBJECT,
2410 WC_FRAME,
2411 NULL,
2412 WS_VISIBLE | WS_CLIPCHILDREN,
2413 0,0,2000,1000,
2414 NULLHANDLE,
2415 HWND_TOP,
2416 0L,
2417 NULL,
2418 NULL);
2419
2420 newbox->oldproc = WinSubclassWindow(hwndframe, _controlproc);
2421 WinSetWindowPtr(hwndframe, QWP_USER, newbox);
2422 dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
2423 return hwndframe;
2424 }
2425
2426 /*
2427 * Create a new Group Box to be packed.
2428 * Parameters:
2429 * type: Either BOXVERT (vertical) or BOXHORZ (horizontal).
2430 * pad: Number of pixels to pad around the box.
2431 * title: Text to be displayined in the group outline.
2432 */
2433 HWND dw_groupbox_new(int type, int pad, char *title)
2434 {
2435 Box *newbox = malloc(sizeof(Box));
2436 HWND hwndframe;
2437
2438 newbox->pad = pad;
2439 newbox->type = type;
2440 newbox->count = 0;
2441
2442 hwndframe = WinCreateWindow(HWND_OBJECT,
2443 WC_FRAME,
2444 NULL,
2445 WS_VISIBLE,
2446 0,0,2000,1000,
2447 NULLHANDLE,
2448 HWND_TOP,
2449 0L,
2450 NULL,
2451 NULL);
2452
2453 newbox->grouphwnd = WinCreateWindow(hwndframe,
2454 WC_STATIC,
2455 title,
2456 WS_VISIBLE | SS_GROUPBOX |
2457 WS_GROUP,
2458 0,0,2000,1000,
2459 NULLHANDLE,
2460 HWND_TOP,
2461 0L,
2462 NULL,
2463 NULL);
2464
2465 WinSetWindowPtr(hwndframe, QWP_USER, newbox);
2466 dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
2467 dw_window_set_color(newbox->grouphwnd, DW_CLR_BLACK, DW_CLR_PALEGRAY);
2468 dw_window_set_font(newbox->grouphwnd, DefaultFont);
2469 return hwndframe;
2470 }
2471
2472 /*
2473 * Create a bitmap object to be packed.
2474 * Parameters:
2475 * id: An ID to be used with WinWindowFromID() or 0L.
2476 */
2477 HWND dw_bitmap_new(ULONG id)
2478 {
2479 return WinCreateWindow(HWND_OBJECT,
2480 WC_STATIC,
2481 NULL,
2482 WS_VISIBLE | SS_TEXT,
2483 0,0,2000,1000,
2484 NULLHANDLE,
2485 HWND_TOP,
2486 id,
2487 NULL,
2488 NULL);
2489 }
2490
2491 /*
2492 * Create a notebook object to be packed.
2493 * Parameters:
2494 * id: An ID to be used for getting the resource from the
2495 * resource file.
2496 */
2497 HWND dw_notebook_new(ULONG id, int top)
2498 {
2499 ULONG flags;
2500 HWND tmp;
2501
2502 if(top)
2503 flags = BKS_MAJORTABTOP;
2504 else
2505 flags = BKS_MAJORTABBOTTOM;
2506
2507 tmp = WinCreateWindow(HWND_OBJECT,
2508 WC_NOTEBOOK,
2509 NULL,
2510 WS_VISIBLE |
2511 BKS_TABBEDDIALOG |
2512 flags,
2513 0,0,2000,1000,
2514 NULLHANDLE,
2515 HWND_TOP,
2516 id,
2517 NULL,
2518 NULL);
2519
2520 dw_window_set_font(tmp, DefaultFont);
2521 return tmp;
2522 }
2523
2524 /*
2525 * Create a menu object to be popped up.
2526 * Parameters:
2527 * id: An ID to be used for getting the resource from the
2528 * resource file.
2529 */
2530 HMENUI dw_menu_new(ULONG id)
2531 {
2532 HMENUI tmp = malloc(sizeof(struct _hmenui));
2533
2534 if(!tmp)
2535 return NULL;
2536
2537 tmp->menu = WinCreateWindow(HWND_OBJECT,
2538 WC_MENU,
2539 NULL,
2540 WS_VISIBLE,
2541 0,0,2000,1000,
2542 NULLHANDLE,
2543 HWND_TOP,
2544 id,
2545 NULL,
2546 NULL);
2547 return tmp;
2548 }
2549
2550 /*
2551 * Create a menubar on a window.
2552 * Parameters:
2553 * location: Handle of a window frame to be attached to.
2554 */
2555 HMENUI dw_menubar_new(HWND location)
2556 {
2557 HMENUI tmp = malloc(sizeof(struct _hmenui));
2558
2559 if(!tmp)
2560 return NULL;
2561
2562 tmp->menu = WinCreateWindow(location,
2563 WC_MENU,
2564 NULL,
2565 WS_VISIBLE | MS_ACTIONBAR,
2566 0,0,2000,1000,
2567 location,
2568 HWND_TOP,
2569 FID_MENU,
2570 NULL,
2571 NULL);
2572 return tmp;
2573 }
2574
2575 /*
2576 * Destroys a menu created with dw_menubar_new or dw_menu_new.
2577 * Parameters:
2578 * menu: Handle of a menu.
2579 */
2580 void dw_menu_destroy(HMENUI *menu)
2581 {
2582 if(menu && *menu)
2583 {
2584 WinDestroyWindow((*menu)->menu);
2585 free(*menu);
2586 *menu = NULL;
2587 }
2588 }
2589
2590 /*
2591 * Adds a menuitem or submenu to an existing menu.
2592 * Parameters:
2593 * menu: The handle the the existing menu.
2594 * title: The title text on the menu item to be added.
2595 * id: An ID to be used for message passing.
2596 * flags: Extended attributes to set on the menu.
2597 * end: If TRUE memu is positioned at the end of the menu.
2598 * check: If TRUE menu is "check"able.
2599 * submenu: Handle to an existing menu to be a submenu or NULL.
2600 */
2601 HWND dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu)
2602 {
2603 MENUITEM miSubMenu;
2604 HWND menu;
2605
2606 if(!menux)
2607 return NULLHANDLE;
2608
2609 menu = menux->menu;
2610
2611 if(end)
2612 miSubMenu.iPosition=MIT_END;
2613 else
2614 miSubMenu.iPosition=0;
2615
2616 if(strlen(title) == 0)
2617 miSubMenu.afStyle=MIS_SEPARATOR | flags;
2618 else
2619 miSubMenu.afStyle=MIS_TEXT | flags;
2620 miSubMenu.afAttribute=0;
2621 miSubMenu.id=id;
2622 miSubMenu.hwndSubMenu = submenu ? submenu->menu : 0;
2623 miSubMenu.hItem=NULLHANDLE;
2624
2625 WinSendMsg(menu,
2626 MM_INSERTITEM,
2627 MPFROMP(&miSubMenu),
2628 MPFROMP(title));
2629 return (HWND)id;
2630 }
2631
2632 /*
2633 * Sets the state of a menu item check.
2634 * Parameters:
2635 * menu: The handle the the existing menu.
2636 * id: Menuitem id.
2637 * check: TRUE for checked FALSE for not checked.
2638 */
2639 void dw_menu_item_set_check(HMENUI menux, int id, int check)
2640 {
2641 HWND menu;
2642
2643 if(!menux)
2644 return;
2645
2646 menu = menux->menu;
2647
2648 if(check)
2649 WinSendMsg(menu, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE),
2650 MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED));
2651 else
2652 WinSendMsg(menu, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE),
2653 MPFROM2SHORT(MIA_CHECKED, 0));
2654 }
2655
2656 /*
2657 * Pops up a context menu at given x and y coordinates.
2658 * Parameters:
2659 * menu: The handle the the existing menu.
2660 * parent: Handle to the window initiating the popup.
2661 * x: X coordinate.
2662 * y: Y coordinate.
2663 */
2664 void dw_menu_popup(HMENUI *menu, HWND parent, int x, int y)
2665 {
2666 if(menu && *menu)
2667 {
2668 WinPopupMenu(HWND_DESKTOP, parent, (*menu)->menu, x, dw_screen_height() - y, 0, PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_VCONSTRAIN | PU_HCONSTRAIN);
2669 free(*menu);
2670 *menu = NULL;
2671 }
2672 }
2673
2674 /*
2675 * Returns the current X and Y coordinates of the mouse pointer.
2676 * Parameters:
2677 * x: Pointer to variable to store X coordinate.
2678 * y: Pointer to variable to store Y coordinate.
2679 */
2680 void dw_pointer_query_pos(long *x, long *y)
2681 {
2682 POINTL ptl;
2683
2684 WinQueryPointerPos(HWND_DESKTOP, &ptl);
2685 if(x && y)
2686 {
2687 *x = ptl.x;
2688 *y = dw_screen_height() - ptl.y;
2689 }
2690 }
2691
2692 /*
2693 * Sets the X and Y coordinates of the mouse pointer.
2694 * Parameters:
2695 * x: X coordinate.
2696 * y: Y coordinate.
2697 */
2698 void dw_pointer_set_pos(long x, long y)
2699 {
2700 WinSetPointerPos(HWND_DESKTOP, x, dw_screen_height() - y);
2701 }
2702
2703 /*
2704 * Create a container object to be packed.
2705 * Parameters:
2706 * id: An ID to be used for getting the resource from the
2707 * resource file.
2708 */
2709 HWND dw_container_new(ULONG id)
2710 {
2711 HWND tmp = WinCreateWindow(HWND_OBJECT,
2712 WC_CONTAINER,
2713 NULL,
2714 WS_VISIBLE | CCS_READONLY |
2715 CCS_SINGLESEL | CCS_AUTOPOSITION,
2716 0,0,2000,1000,
2717 NULLHANDLE,
2718 HWND_TOP,
2719 id,
2720 NULL,
2721 NULL);
2722 dw_window_set_font(tmp, DefaultFont);
2723 return tmp;
2724 }
2725
2726 /*
2727 * Create a new static text window (widget) to be packed.
2728 * Parameters:
2729 * text: The text to be display by the static text widget.
2730 * id: An ID to be used with WinWindowFromID() or 0L.
2731 */
2732 HWND dw_text_new(char *text, ULONG id)
2733 {
2734 HWND tmp = WinCreateWindow(HWND_OBJECT,
2735 WC_STATIC,
2736 text,
2737 WS_VISIBLE | SS_TEXT,
2738 0,0,2000,1000,
2739 NULLHANDLE,
2740 HWND_TOP,
2741 id,
2742 NULL,
2743 NULL);
2744 dw_window_set_font(tmp, DefaultFont);
2745 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
2746 return tmp;
2747 }
2748
2749 /*
2750 * Create a new Multiline Editbox window (widget) to be packed.
2751 * Parameters:
2752 * id: An ID to be used with WinWindowFromID() or 0L.
2753 */
2754 HWND dw_mle_new(ULONG id)
2755 {
2756 HWND tmp = WinCreateWindow(HWND_OBJECT,
2757 WC_MLE,
2758 "",
2759 WS_VISIBLE |
2760 MLS_BORDER | MLS_IGNORETAB |
2761 MLS_READONLY | MLS_VSCROLL,
2762 0,0,2000,1000,
2763 NULLHANDLE,
2764 HWND_TOP,
2765 id,
2766 NULL,
2767 NULL);
2768 dw_window_set_font(tmp, DefaultFont);
2769 dw_window_set_font(tmp, DefaultFont);
2770 return tmp;
2771 }
2772
2773 /*
2774 * Create a new Entryfield window (widget) to be packed.
2775 * Parameters:
2776 * text: The default text to be in the entryfield widget.
2777 * id: An ID to be used with WinWindowFromID() or 0L.
2778 */
2779 HWND dw_entryfield_new(char *text, ULONG id)
2780 {
2781 PFNWP *blah = malloc(sizeof(PFNWP));
2782 HWND tmp = WinCreateWindow(HWND_OBJECT,
2783 WC_ENTRYFIELD,
2784 text,
2785 WS_VISIBLE | ES_MARGIN |
2786 ES_AUTOSCROLL | WS_TABSTOP,
2787 0,0,2000,1000,
2788 NULLHANDLE,
2789 HWND_TOP,
2790 id,
2791 NULL,
2792 NULL);
2793 dw_window_set_font(tmp, DefaultFont);
2794 *blah = WinSubclassWindow(tmp, _entryproc);
2795 WinSetWindowPtr(tmp, QWP_USER, blah);
2796 return tmp;
2797 }
2798
2799 /*
2800 * Create a new Entryfield (password) window (widget) to be packed.
2801 * Parameters:
2802 * text: The default text to be in the entryfield widget.
2803 * id: An ID to be used with WinWindowFromID() or 0L.
2804 */
2805 HWND dw_entryfield_password_new(char *text, ULONG id)
2806 {
2807 PFNWP *blah = malloc(sizeof(PFNWP));
2808 HWND tmp = WinCreateWindow(HWND_OBJECT,
2809 WC_ENTRYFIELD,
2810 text,
2811 WS_VISIBLE | ES_MARGIN | ES_UNREADABLE |
2812 ES_AUTOSCROLL | WS_TABSTOP,
2813 0,0,2000,1000,
2814 NULLHANDLE,
2815 HWND_TOP,
2816 id,
2817 NULL,
2818 NULL);
2819 dw_window_set_font(tmp, DefaultFont);
2820 *blah = WinSubclassWindow(tmp, _entryproc);
2821 WinSetWindowPtr(tmp, QWP_USER, blah);
2822 return tmp;
2823 }
2824
2825 /*
2826 * Create a new Combobox window (widget) to be packed.
2827 * Parameters:
2828 * text: The default text to be in the combpbox widget.
2829 * id: An ID to be used with WinWindowFromID() or 0L.
2830 */
2831 HWND dw_combobox_new(char *text, ULONG id)
2832 {
2833 PFNWP *blah = malloc(sizeof(PFNWP));
2834 HWND tmp = WinCreateWindow(HWND_OBJECT,
2835 WC_COMBOBOX,
2836 text,
2837 WS_VISIBLE | CBS_DROPDOWN | WS_GROUP,
2838 0,0,2000,1000,
2839 NULLHANDLE,
2840 HWND_TOP,
2841 id,
2842 NULL,
2843 NULL);
2844 dw_window_set_font(tmp, DefaultFont);
2845 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
2846 *blah = WinSubclassWindow(tmp, _comboproc);
2847 WinSetWindowPtr(tmp, QWP_USER, blah);
2848 return tmp;
2849 }
2850
2851 /*
2852 * Create a new button window (widget) to be packed.
2853 * Parameters:
2854 * text: The text to be display by the static text widget.
2855 * id: An ID to be used with WinWindowFromID() or 0L.
2856 */
2857 HWND dw_button_new(char *text, ULONG id)
2858 {
2859 BubbleButton *bubble = malloc(sizeof(BubbleButton));
2860
2861 HWND tmp = WinCreateWindow(HWND_OBJECT,
2862 WC_BUTTON,
2863 text,
2864 WS_VISIBLE,
2865 0,0,2000,1000,
2866 NULLHANDLE,
2867 HWND_TOP,
2868 id,
2869 NULL,
2870 NULL);
2871
2872 bubble->id = id;
2873 bubble->bubbletext[0] = '\0';
2874 bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
2875
2876 WinSetWindowPtr(tmp, QWP_USER, bubble);
2877 dw_window_set_font(tmp, DefaultFont);
2878 return tmp;
2879 }
2880
2881 /* Function: GenResIDStr
2882 ** Abstract: Generate string '#nnnn' for a given ID for using with Button
2883 ** controls
2884 */
2885
2886 void _GenResIDStr(CHAR *buff, ULONG ulID)
2887 {
2888 char *str;
2889 int slen = 0;
2890
2891 *buff++ = '#';
2892
2893 str = buff;
2894
2895 do
2896 {
2897 *str++ = (ulID % 10) + '0';
2898 ulID /= 10;
2899 slen++;
2900 }
2901 while(ulID);
2902
2903 *str-- = 0;
2904
2905 for(; str > buff; str--, buff++)
2906 {
2907 *buff ^= *str;
2908 *str ^= *buff;
2909 *buff ^= *str;
2910 }
2911 }
2912
2913
2914 /*
2915 * Create a new bitmap button window (widget) to be packed.
2916 * Parameters:
2917 * text: Bubble help text to be displayed.
2918 * id: An ID of a bitmap in the resource file.
2919 */
2920 HWND dw_bitmapbutton_new(char *text, ULONG id)
2921 {
2922 char idbuf[256];
2923 HWND tmp;
2924 BubbleButton *bubble = malloc(sizeof(BubbleButton));
2925
2926 _GenResIDStr(idbuf, id);
2927
2928 tmp = WinCreateWindow(HWND_OBJECT,
2929 WC_BUTTON,
2930 idbuf,
2931 WS_VISIBLE | BS_PUSHBUTTON |
2932 BS_BITMAP | BS_AUTOSIZE |
2933 BS_NOPOINTERFOCUS,
2934 0,0,2000,1000,
2935 NULLHANDLE,
2936 HWND_TOP,
2937 id,
2938 NULL,
2939 NULL);
2940
2941 bubble->id = id;
2942 strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1);
2943 bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0';
2944 bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
2945
2946 WinSetWindowPtr(tmp, QWP_USER, bubble);
2947 return tmp;
2948 }
2949
2950 /*
2951 * Create a new spinbutton window (widget) to be packed.
2952 * Parameters:
2953 * text: The text to be display by the static text widget.
2954 * id: An ID to be used with WinWindowFromID() or 0L.
2955 */
2956 HWND
2957 dw_spinbutton_new(char *text, ULONG id)
2958 {
2959 PFNWP *blah = malloc(sizeof(PFNWP));
2960 HWND tmp = WinCreateWindow(HWND_OBJECT,
2961 WC_SPINBUTTON,
2962 text,
2963 WS_VISIBLE | SPBS_MASTER,
2964 0,0,2000,1000,
2965 NULLHANDLE,
2966 HWND_TOP,
2967 id,
2968 NULL,
2969 NULL);
2970 dw_window_set_font(tmp, DefaultFont);
2971 *blah = WinSubclassWindow(tmp, _entryproc);
2972 WinSetWindowPtr(tmp, QWP_USER, blah);
2973 return tmp;
2974 }
2975
2976 /*
2977 * Create a new radiobutton window (widget) to be packed.
2978 * Parameters:
2979 * text: The text to be display by the static text widget.
2980 * id: An ID to be used with WinWindowFromID() or 0L.
2981 */
2982 HWND dw_radiobutton_new(char *text, ULONG id)
2983 {
2984 PFNWP *blah = malloc(sizeof(PFNWP));
2985 HWND tmp = WinCreateWindow(HWND_OBJECT,
2986 WC_BUTTON,
2987 text,
2988 WS_VISIBLE |
2989 BS_AUTORADIOBUTTON,
2990 0,0,2000,1000,
2991 NULLHANDLE,
2992 HWND_TOP,
2993 id,
2994 NULL,
2995 NULL);
2996 dw_window_set_font(tmp, DefaultFont);
2997 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
2998 *blah = WinSubclassWindow(tmp, _entryproc);
2999 WinSetWindowPtr(tmp, QWP_USER, blah);
3000 return tmp;
3001 }
3002
3003 /*
3004 * Create a new slider window (widget) to be packed.
3005 * Parameters:
3006 * id: An ID to be used with WinWindowFromID() or 0L.
3007 */
3008 HWND dw_slider_new(ULONG id)
3009 {
3010 return WinCreateWindow(HWND_OBJECT,
3011 WC_SLIDER,
3012 NULL,
3013 WS_VISIBLE,
3014 0,0,2000,1000,
3015 NULLHANDLE,
3016 HWND_TOP,
3017 id,
3018 NULL,
3019 NULL);
3020 }
3021
3022 /*
3023 * Create a new checkbox window (widget) to be packed.
3024 * Parameters:
3025 * text: The text to be display by the static text widget.
3026 * id: An ID to be used with WinWindowFromID() or 0L.
3027 */
3028 HWND dw_checkbox_new(char *text, ULONG id)
3029 {
3030 PFNWP *blah = malloc(sizeof(PFNWP));
3031 HWND tmp = WinCreateWindow(HWND_OBJECT,
3032 WC_BUTTON,
3033 text,
3034 WS_VISIBLE | BS_AUTOCHECKBOX,
3035 0,0,2000,1000,
3036 NULLHANDLE,
3037 HWND_TOP,
3038 id,
3039 NULL,
3040 NULL);
3041 dw_window_set_font(tmp, DefaultFont);
3042 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
3043 *blah = WinSubclassWindow(tmp, _entryproc);
3044 WinSetWindowPtr(tmp, QWP_USER, blah);
3045 return tmp;
3046 }
3047
3048 /*
3049 * Create a new listbox window (widget) to be packed.
3050 * Parameters:
3051 * id: An ID to be used with WinWindowFromID() or 0L.
3052 * multi: Multiple select TRUE or FALSE.
3053 */
3054 HWND dw_listbox_new(ULONG id, int multi)
3055 {
3056 PFNWP *blah = malloc(sizeof(PFNWP));
3057 HWND tmp = WinCreateWindow(HWND_OBJECT,
3058 WC_LISTBOX,
3059 NULL,
3060 WS_VISIBLE | LS_NOADJUSTPOS |
3061 (multi ? LS_MULTIPLESEL : 0),
3062 0,0,2000,1000,
3063 NULLHANDLE,
3064 HWND_TOP,
3065 id,
3066 NULL,
3067 NULL);
3068 dw_window_set_font(tmp, DefaultFont);
3069 *blah = WinSubclassWindow(tmp, _entryproc);
3070 WinSetWindowPtr(tmp, QWP_USER, blah);
3071 return tmp;
3072 }
3073
3074 /*
3075 * Sets the icon used for a given window.
3076 * Parameters:
3077 * handle: Handle to the window.
3078 * id: An ID to be used to specify the icon.
3079 */
3080 void dw_window_set_icon(HWND handle, ULONG id)
3081 {
3082 HPOINTER icon;
3083
3084 icon = WinLoadPointer(HWND_DESKTOP,NULLHANDLE,id);
3085 WinSendMsg(handle, WM_SETICON, (MPARAM)icon, 0);
3086 }
3087
3088 /*
3089 * Sets the bitmap used for a given static window.
3090 * Parameters:
3091 * handle: Handle to the window.
3092 * id: An ID to be used to specify the icon.
3093 */
3094 void dw_window_set_bitmap(HWND handle, ULONG id)
3095 {
3096 HBITMAP hbm;
3097 HPS hps = WinGetPS(handle);
3098
3099 hbm = GpiLoadBitmap(hps, NULLHANDLE, id, 0, 0);
3100 WinSetWindowBits(handle,QWL_STYLE,SS_BITMAP,SS_BITMAP | 0x7f);
3101 WinSendMsg( handle, SM_SETHANDLE, MPFROMP(hbm), NULL );
3102 /*WinSetWindowULong( hwndDlg, QWL_USER, (ULONG) hbm );*/
3103 WinReleasePS(hps);
3104 }
3105
3106 /*
3107 * Sets the text used for a given window.
3108 * Parameters:
3109 * handle: Handle to the window.
3110 * text: The text associsated with a given window.
3111 */
3112 void dw_window_set_text(HWND handle, char *text)
3113 {
3114 WinSetWindowText(handle, text);
3115 }
3116
3117 /*
3118 * Gets the text used for a given window.
3119 * Parameters:
3120 * handle: Handle to the window.
3121 * Returns:
3122 * text: The text associsated with a given window.
3123 */
3124 char *dw_window_get_text(HWND handle)
3125 {
3126 char tempbuf[4096] = "";
3127
3128 WinQueryWindowText(handle, 4095, tempbuf);
3129 tempbuf[4095] = 0;
3130
3131 return strdup(tempbuf);
3132 }
3133
3134 /*
3135 * Disables given window (widget).
3136 * Parameters:
3137 * handle: Handle to the window.
3138 */
3139 void dw_window_disable(HWND handle)
3140 {
3141 WinEnableWindow(handle, FALSE);
3142 }
3143
3144 /*
3145 * Enables given window (widget).
3146 * Parameters:
3147 * handle: Handle to the window.
3148 */
3149 void dw_window_enable(HWND handle)
3150 {
3151 WinEnableWindow(handle, TRUE);
3152 }
3153
3154 /*
3155 * Gets the child window handle with specified ID.
3156 * Parameters:
3157 * handle: Handle to the parent window.
3158 * id: Integer ID of the child.
3159 */
3160 HWND dw_window_from_id(HWND handle, int id)
3161 {
3162 HENUM henum;
3163 HWND child;
3164 char tmpbuf[100];
3165
3166 henum = WinBeginEnumWindows(handle);
3167 while((child = WinGetNextWindow(henum)) != NULLHANDLE)
3168 {
3169 int windowid = WinQueryWindowUShort(child, QWS_ID);
3170 HWND found;
3171
3172 WinQueryClassName(child, 99, tmpbuf);
3173
3174 /* If the child is a box (frame) then recurse into it */
3175 if(strncmp(tmpbuf, "#1", 2)==0)
3176 if((found = dw_window_from_id(child, id)) != NULLHANDLE)
3177 return found;
3178
3179 if(windowid && windowid == id)
3180 {
3181 WinEndEnumWindows(henum);
3182 return child;
3183 }
3184 }
3185 WinEndEnumWindows(henum);
3186 return NULLHANDLE;
3187 }
3188
3189 /*
3190 * Pack windows (widgets) into a box from the end (or bottom).
3191 * Parameters:
3192 * box: Window handle of the box to be packed into.
3193 * item: Window handle of the item to be back.
3194 * width: Width in pixels of the item or -1 to be self determined.
3195 * height: Height in pixels of the item or -1 to be self determined.
3196 * hsize: TRUE if the window (widget) should expand horizontally to fill space given.
3197 * vsize: TRUE if the window (widget) should expand vertically to fill space given.
3198 * pad: Number of pixels of padding around the item.
3199 */
3200 void dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
3201 {
3202 Box *thisbox;
3203
3204 if(WinWindowFromID(box, FID_CLIENT))
3205 {
3206 box = WinWindowFromID(box, FID_CLIENT);
3207 thisbox = WinQueryWindowPtr(box, QWP_USER);
3208 }
3209 else
3210 thisbox = WinQueryWindowPtr(box, QWP_USER);
3211 if(thisbox)
3212 {
3213 if(thisbox->type == BOXHORZ)
3214 dw_box_pack_start_stub(box, item, width, height, hsize, vsize, pad);
3215 else
3216 dw_box_pack_end_stub(box, item, width, height, hsize, vsize, pad);
3217 }
3218 }
3219
3220 void dw_box_pack_end_stub(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
3221 {
3222 HWND boxowner = NULLHANDLE;
3223 Box *thisbox;
3224
3225 if(WinWindowFromID(box, FID_CLIENT))
3226 {
3227 box = WinWindowFromID(box, FID_CLIENT);
3228 thisbox = WinQueryWindowPtr(box, QWP_USER);
3229 hsize = TRUE;
3230 vsize = TRUE;
3231 }
3232 else
3233 thisbox = WinQueryWindowPtr(box, QWP_USER);
3234 if(!thisbox)
3235 {
3236 box = WinWindowFromID(box, FID_CLIENT);
3237 if(box)
3238 {
3239 thisbox = WinQueryWindowPtr(box, QWP_USER);
3240 hsize = TRUE;
3241 vsize = TRUE;
3242 }
3243 }
3244 if(thisbox)
3245 {
3246 int z;
3247 Item *tmpitem, *thisitem = thisbox->items;
3248 char tmpbuf[100];
3249
3250 tmpitem = malloc(sizeof(Item)*(thisbox->count+1));
3251
3252 for(z=0;z<thisbox->count;z++)
3253 {
3254 tmpitem[z] = thisitem[z];
3255 }
3256
3257 WinQueryClassName(item, 99, tmpbuf);
3258
3259 if(strncmp(tmpbuf, "#1", 2)==0)
3260 tmpitem[thisbox->count].type = TYPEBOX;
3261 else
3262 tmpitem[thisbox->count].type = TYPEITEM;
3263
3264 tmpitem[thisbox->count].hwnd = item;
3265 tmpitem[thisbox->count].origwidth = tmpitem[thisbox->count].width = width;
3266 tmpitem[thisbox->count].origheight = tmpitem[thisbox->count].height = height;
3267 tmpitem[thisbox->count].pad = pad;
3268 if(hsize)
3269 tmpitem[thisbox->count].hsize = SIZEEXPAND;
3270 else
3271 tmpitem[thisbox->count].hsize = SIZESTATIC;
3272
3273 if(vsize)
3274 tmpitem[thisbox->count].vsize = SIZEEXPAND;
3275 else
3276 tmpitem[thisbox->count].vsize = SIZESTATIC;
3277
3278 thisbox->items = tmpitem;
3279
3280 if(thisbox->count)
3281 free(thisitem);
3282
3283 thisbox->count++;
3284
3285 /* Don't set the ownership if it's an entryfield or combobox */
3286 WinQueryClassName(item, 99, tmpbuf);
3287 if(strncmp(tmpbuf, "#6", 2)!=0 /*&& strncmp(tmpbuf, "#2", 2)!=0*/)
3288 {
3289 if((boxowner = WinQueryWindow(box, QW_OWNER)) != 0)
3290 WinSetOwner(item, boxowner);
3291 else
3292 WinSetOwner(item, box);
3293 }
3294 WinSetParent(item, box, FALSE);
3295 }
3296 }
3297
3298 /*
3299 * Sets the size of a given window (widget).
3300 * Parameters:
3301 * handle: Window (widget) handle.
3302 * width: New width in pixels.
3303 * height: New height in pixels.
3304 */
3305 void dw_window_set_usize(HWND handle, ULONG width, ULONG height)
3306 {
3307 WinSetWindowPos(handle, NULLHANDLE, 0, 0, width, height, SWP_SHOW | SWP_SIZE);
3308 }
3309
3310 /*
3311 * Returns the width of the screen.
3312 */
3313 int dw_screen_width(void)
3314 {
3315 return WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN);
3316 }
3317
3318 /*
3319 * Returns the height of the screen.
3320 */
3321 int dw_screen_height(void)
3322 {
3323 return WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN);
3324 }
3325
3326 /* This should return the current color depth */
3327 unsigned long dw_color_depth(void)
3328 {
3329 HDC hdc = WinOpenWindowDC(HWND_DESKTOP);
3330 long colors;
3331
3332 DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, &colors);
3333 DevCloseDC(hdc);
3334 return colors;
3335 }
3336
3337
3338 /*
3339 * Sets the position of a given window (widget).
3340 * Parameters:
3341 * handle: Window (widget) handle.
3342 * x: X location from the bottom left.
3343 * y: Y location from the bottom left.
3344 */
3345 void dw_window_set_pos(HWND handle, ULONG x, ULONG y)
3346 {
3347 int myy = _get_frame_height(handle) - (y + _get_height(handle));
3348
3349 WinSetWindowPos(handle, NULLHANDLE, x, myy, 0, 0, SWP_MOVE);
3350 }
3351
3352 /*
3353 * Sets the position and size of a given window (widget).
3354 * Parameters:
3355 * handle: Window (widget) handle.
3356 * x: X location from the bottom left.
3357 * y: Y location from the bottom left.
3358 * width: Width of the widget.
3359 * height: Height of the widget.
3360 */
3361 void dw_window_set_pos_size(HWND handle, ULONG x, ULONG y, ULONG width, ULONG height)
3362 {
3363 int myy = _get_frame_height(handle) - (y + height);
3364
3365 WinSetWindowPos(handle, NULLHANDLE, x, myy, width, height, SWP_MOVE | SWP_SIZE | SWP_SHOW);
3366 }
3367
3368 /*
3369 * Gets the position and size of a given window (widget).
3370 * Parameters:
3371 * handle: Window (widget) handle.
3372 * x: X location from the bottom left.
3373 * y: Y location from the bottom left.
3374 * width: Width of the widget.
3375 * height: Height of the widget.
3376 */
3377 void dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height)
3378 {
3379 SWP swp;
3380 WinQueryWindowPos(handle, &swp);
3381 if(x)
3382 *x = swp.x;
3383 if(y)
3384 *y = _get_frame_height(handle) - (swp.y + swp.cy);
3385 if(width)
3386 *width = swp.cx;
3387 if(height)
3388 *height = swp.cy;
3389 }
3390
3391 /*
3392 * Sets the style of a given window (widget).
3393 * Parameters:
3394 * handle: Window (widget) handle.
3395 * width: New width in pixels.
3396 * height: New height in pixels.
3397 */
3398 void dw_window_set_style(HWND handle, ULONG style, ULONG mask)
3399 {
3400 WinSetWindowBits(handle, QWL_STYLE, style, mask);
3401 }
3402
3403 /*
3404 * Adds a new page to specified notebook.
3405 * Parameters:
3406 * handle: Window (widget) handle.
3407 * flags: Any additional page creation flags.
3408 * front: If TRUE page is added at the beginning.
3409 */
3410 ULONG dw_notebook_page_new(HWND handle, ULONG flags, int front)
3411 {
3412 if(front)
3413 return (ULONG)WinSendMsg(handle, BKM_INSERTPAGE, 0L,
3414 MPFROM2SHORT((BKA_STATUSTEXTON | BKA_AUTOPAGESIZE | BKA_MAJOR | flags), BKA_FIRST));
3415 return (ULONG)WinSendMsg(handle, BKM_INSERTPAGE, 0L,
3416 MPFROM2SHORT((BKA_STATUSTEXTON | BKA_AUTOPAGESIZE | BKA_MAJOR | flags), BKA_LAST));
3417 }
3418
3419 /*
3420 * Remove a page from a notebook.
3421 * Parameters:
3422 * handle: Handle to the notebook widget.
3423 * pageid: ID of the page to be destroyed.
3424 */
3425 void dw_notebook_page_destroy(HWND handle, unsigned int pageid)
3426 {
3427 WinSendMsg(handle, BKM_DELETEPAGE,
3428 MPFROMLONG(pageid), (MPARAM)BKA_SINGLE);
3429 }
3430
3431 /*
3432 * Queries the currently visible page ID.
3433 * Parameters:
3434 * handle: Handle to the notebook widget.
3435 */
3436 unsigned int dw_notebook_page_query(HWND handle)
3437 {
3438 return (int)WinSendMsg(handle, BKM_QUERYPAGEID,0L, MPFROM2SHORT(BKA_TOP, BKA_MAJOR));
3439 }
3440
3441 /*
3442 * Sets the currently visibale page ID.
3443 * Parameters:
3444 * handle: Handle to the notebook widget.
3445 * pageid: ID of the page to be made visible.
3446 */
3447 void dw_notebook_page_set(HWND handle, unsigned int pageid)
3448 {
3449 WinSendMsg(handle, BKM_TURNTOPAGE, MPFROMLONG(pageid), 0L);
3450 }
3451
3452 /*
3453 * Sets the text on the specified notebook tab.
3454 * Parameters:
3455 * handle: Notebook handle.
3456 * pageid: Page ID of the tab to set.
3457 * text: Pointer to the text to set.
3458 */
3459 void dw_notebook_page_set_text(HWND handle, ULONG pageid, char *text)
3460 {
3461 WinSendMsg(handle, BKM_SETTABTEXT,
3462 MPFROMLONG(pageid), MPFROMP(text));
3463 }
3464
3465 /*
3466 * Sets the text on the specified notebook tab status area.
3467 * Parameters:
3468 * handle: Notebook handle.
3469 * pageid: Page ID of the tab to set.
3470 * text: Pointer to the text to set.
3471 */
3472 void dw_notebook_page_set_status_text(HWND handle, ULONG pageid, char *text)
3473 {
3474 WinSendMsg(handle, BKM_SETSTATUSLINETEXT,
3475 MPFROMLONG(pageid), MPFROMP(text));
3476 }
3477
3478 /*
3479 * Packs the specified box into the notebook page.
3480 * Parameters:
3481 * handle: Handle to the notebook to be packed.
3482 * pageid: Page ID in the notebook which is being packed.
3483 * page: Box handle to be packed.
3484 */
3485 void dw_notebook_pack(HWND handle, ULONG pageid, HWND page)
3486 {
3487 HWND tmpbox = dw_box_new(BOXVERT, 0);
3488
3489 dw_box_pack_start(tmpbox, page, 0, 0, TRUE, TRUE, 0);
3490 WinSubclassWindow(tmpbox, _wndproc);
3491 WinSendMsg(handle, BKM_SETPAGEWINDOWHWND,
3492 MPFROMLONG(pageid), MPFROMHWND(tmpbox));
3493 }
3494
3495 /*
3496 * Appends the specified text to the listbox's (or combobox) entry list.
3497 * Parameters:
3498 * handle: Handle to the listbox to be appended to.
3499 * text: Text to append into listbox.
3500 */
3501 void dw_listbox_append(HWND handle, char *text)
3502 {
3503 WinSendMsg(handle,
3504 LM_INSERTITEM,
3505 MPFROMSHORT(LIT_END),
3506 MPFROMP(text));
3507 }
3508
3509 /*
3510 * Clears the listbox's (or combobox) list of all entries.
3511 * Parameters:
3512 * handle: Handle to the listbox to be cleared.
3513 */
3514 void dw_listbox_clear(HWND handle)
3515 {
3516 WinSendMsg(handle,
3517 LM_DELETEALL, 0L, 0L);
3518 }
3519
3520 /*
3521 * Returns the listbox's item count.
3522 * Parameters:
3523 * handle: Handle to the listbox to be cleared.
3524 */
3525 int dw_listbox_count(HWND handle)
3526 {
3527 return (int)WinSendMsg(handle,
3528 LM_QUERYITEMCOUNT,0L, 0L);
3529 }
3530
3531 /*
3532 * Sets the topmost item in the viewport.
3533 * Parameters:
3534 * handle: Handle to the listbox to be cleared.
3535 * top: Index to the top item.
3536 */
3537 void dw_listbox_set_top(HWND handle, int top)
3538 {
3539 WinSendMsg(handle,
3540 LM_SETTOPINDEX,
3541 MPFROMSHORT(top),
3542 0L);
3543 }
3544
3545 /*
3546 * Copies the given index item's text into buffer.
3547 * Parameters:
3548 * handle: Handle to the listbox to be queried.
3549 * index: Index into the list to be queried.
3550 * buffer: Buffer where text will be copied.
3551 * length: Length of the buffer (including NULL).
3552 */
3553 void dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length)
3554 {
3555 WinSendMsg(handle, LM_QUERYITEMTEXT, MPFROM2SHORT(index, length), (MPARAM)buffer);
3556 }
3557
3558 /*
3559 * Sets the text of a given listbox entry.
3560 * Parameters:
3561 * handle: Handle to the listbox to be queried.
3562 * index: Index into the list to be queried.
3563 * buffer: Buffer where text will be copied.
3564 */
3565 void dw_listbox_set_text(HWND handle, unsigned int index, char *buffer)
3566 {
3567 WinSendMsg(handle, LM_SETITEMTEXT, MPFROMSHORT(index), (MPARAM)buffer);
3568 }
3569
3570 /*
3571 * Returns the index to the item in the list currently selected.
3572 * Parameters:
3573 * handle: Handle to the listbox to be queried.
3574 */
3575 unsigned int dw_listbox_selected(HWND handle)
3576 {
3577 return (unsigned int)WinSendMsg(handle,
3578 LM_QUERYSELECTION,
3579 MPFROMSHORT(LIT_CURSOR),
3580 0);
3581 }
3582
3583 /*
3584 * Returns the index to the current selected item or -1 when done.
3585 * Parameters:
3586 * handle: Handle to the listbox to be queried.
3587 * where: Either the previous return or -1 to restart.
3588 */
3589 int dw_listbox_selected_multi(HWND handle, int where)
3590 {
3591 int place = where;
3592
3593 if(where == -1)
3594 place = LIT_FIRST;
3595
3596 place = (int)WinSendMsg(handle,
3597 LM_QUERYSELECTION,
3598 MPFROMSHORT(place),0L);
3599 if(place == LIT_NONE)
3600 return -1;
3601 return place;
3602 }
3603
3604 /*
3605 * Sets the selection state of a given index.
3606 * Parameters:
3607 * handle: Handle to the listbox to be set.
3608 * index: Item index.
3609 * state: TRUE if selected FALSE if unselected.
3610 */
3611 void dw_listbox_select(HWND handle, int index, int state)
3612 {
3613 WinSendMsg(handle, LM_SELECTITEM, MPFROMSHORT(index), (MPARAM)state);
3614 _run_event(handle, WM_CONTROL, MPFROM2SHORT(0, LN_SELECT), (MPARAM)handle);
3615 }
3616
3617 /*
3618 * Deletes the item with given index from the list.
3619 * Parameters:
3620 * handle: Handle to the listbox to be set.
3621 * index: Item index.
3622 */
3623 void dw_listbox_delete(HWND handle, int index)
3624 {
3625 WinSendMsg(handle, LM_DELETEITEM, MPFROMSHORT(index), 0);
3626 }
3627
3628 /*
3629 * Adds text to an MLE box and returns the current point.
3630 * Parameters:
3631 * handle: Handle to the MLE to be queried.
3632 * buffer: Text buffer to be imported.
3633 * startpoint: Point to start entering text.
3634 */
3635 unsigned int dw_mle_import(HWND handle, char *buffer, int startpoint)
3636 {
3637 unsigned long point = startpoint;
3638 PBYTE mlebuf;
3639
3640 /* Work around 64K limit */
3641 if(!DosAllocMem((PPVOID) &mlebuf, 65536, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE))
3642 {
3643 int amount, len = strlen(buffer), written = 0;
3644
3645 while(written < len)
3646 {
3647 if((len - written) > 65535)
3648 amount = 65535;
3649 else
3650 amount = len - written;
3651
3652 memcpy(mlebuf, &buffer[written], amount);
3653 mlebuf[amount] = '\0';
3654
3655 WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount+1));
3656 WinSendMsg(handle, MLM_IMPORT, MPFROMP(&point), MPFROMLONG(amount + 1));
3657 dw_mle_delete(handle, point, 1);
3658
3659 written += amount;
3660 }
3661 DosFreeMem(mlebuf);
3662 }
3663 return point - 1;
3664 }
3665
3666 /*
3667 * Grabs text from an MLE box.
3668 * Parameters:
3669 * handle: Handle to the MLE to be queried.
3670 * buffer: Text buffer to be exported.
3671 * startpoint: Point to start grabbing text.
3672 * length: Amount of text to be grabbed.
3673 */
3674 void dw_mle_export(HWND handle, char *buffer, int startpoint, int length)
3675 {
3676 PBYTE mlebuf;
3677
3678 /* Work around 64K limit */
3679 if(!DosAllocMem((PPVOID) &mlebuf, 65535, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE))
3680 {
3681 int amount, copied, written = 0;
3682
3683 while(written < length)
3684 {
3685 if((length - written) > 65535)
3686 amount = 65535;
3687 else
3688 amount = length - written;
3689
3690 WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount));
3691 copied = (int)WinSendMsg(handle, MLM_EXPORT, MPFROMP(&startpoint), MPFROMLONG(&amount));
3692
3693 if(copied)
3694 {
3695 memcpy(&buffer[written], mlebuf, copied);
3696
3697 written += copied;
3698 }
3699 else
3700 break;
3701 }
3702 DosFreeMem(mlebuf);
3703 }
3704 }
3705
3706 /*
3707 * Obtains information about an MLE box.
3708 * Parameters:
3709 * handle: Handle to the MLE to be queried.
3710 * bytes: A pointer to a variable to return the total bytes.
3711 * lines: A pointer to a variable to return the number of lines.
3712 */
3713 void dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines)
3714 {
3715 if(bytes)
3716 *bytes = (unsigned long)WinSendMsg(handle, MLM_QUERYTEXTLENGTH, 0, 0);
3717 if(lines)
3718 *lines = (unsigned long)WinSendMsg(handle, MLM_QUERYLINECOUNT, 0, 0);
3719 }
3720
3721 /*
3722 * Deletes text from an MLE box.
3723 * Parameters:
3724 * handle: Handle to the MLE to be deleted from.
3725 * startpoint: Point to start deleting text.
3726 * length: Amount of text to be deleted.
3727 */
3728 void dw_mle_delete(HWND handle, int startpoint, int length)
3729 {
3730 char *buf = malloc(length+1);
3731 int z, dellen = length;
3732
3733 dw_mle_export(handle, buf, startpoint, length);
3734
3735 for(z=0;z<length-1;z++)
3736 {
3737 if(strncmp(&buf[z], "\r\n", 2) == 0)
3738 dellen--;
3739 }
3740 WinSendMsg(handle, MLM_DELETE, MPFROMLONG(startpoint), MPFROMLONG(dellen));
3741 free(buf);
3742 }
3743
3744 /*
3745 * Clears all text from an MLE box.
3746 * Parameters:
3747 * handle: Handle to the MLE to be cleared.
3748 */
3749 void dw_mle_clear(HWND handle)
3750 {
3751 unsigned long bytes;
3752
3753 dw_mle_query(handle, &bytes, NULL);
3754
3755 WinSendMsg(handle, MLM_DELETE, MPFROMLONG(0), MPFROMLONG(bytes));
3756 }
3757
3758 /*
3759 * Sets the visible line of an MLE box.
3760 * Parameters:
3761 * handle: Handle to the MLE to be positioned.
3762 * line: Line to be visible.
3763 */
3764 void dw_mle_set_visible(HWND handle, int line)
3765 {
3766 int tmppnt;
3767
3768 if(line > 10)
3769 {
3770 tmppnt = (int)WinSendMsg(handle, MLM_CHARFROMLINE, MPFROMLONG(line - 10), 0);
3771 WinSendMsg(handle, MLM_SETFIRSTCHAR, MPFROMLONG(tmppnt), 0);
3772 }
3773 }
3774
3775 /*
3776 * Sets the current cursor position of an MLE box.
3777 * Parameters:
3778 * handle: Handle to the MLE to be positioned.
3779 * point: Point to position cursor.
3780 */
3781 void dw_mle_set(HWND handle, int point)
3782 {
3783 WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(point), MPFROMLONG(point));
3784 }
3785
3786 /*
3787 * Finds text in an MLE box.
3788 * Parameters:
3789 * handle: Handle to the MLE to be cleared.
3790 * text: Text to search for.
3791 * point: Start point of search.
3792 * flags: Search specific flags.
3793 */
3794 int dw_mle_search(HWND handle, char *text, int point, unsigned long flags)
3795 {
3796 MLE_SEARCHDATA msd;
3797
3798 msd.cb = sizeof(msd);
3799 msd.pchFind = text;
3800 msd.pchReplace = NULL;
3801 msd.cchFind = strlen(text);
3802 msd.cchReplace = 0;
3803 msd.iptStart = point;
3804 msd.iptStop = -1;
3805
3806 if(WinSendMsg(handle, MLM_SEARCH, MPFROMLONG(MLFSEARCH_SELECTMATCH | flags), (MPARAM)&msd))
3807 return (int)WinSendMsg(handle, MLM_QUERYSEL,(MPARAM)MLFQS_MAXSEL, 0);
3808 return 0;
3809 }
3810
3811 /*
3812 * Stops redrawing of an MLE box.
3813 * Parameters:
3814 * handle: Handle to the MLE to freeze.
3815 */
3816 void dw_mle_freeze(HWND handle)
3817 {
3818 WinSendMsg(handle, MLM_DISABLEREFRESH, 0, 0);
3819 }
3820
3821 /*
3822 * Resumes redrawing of an MLE box.
3823 * Parameters:
3824 * handle: Handle to the MLE to thaw.
3825 */
3826 void dw_mle_thaw(HWND handle)
3827 {
3828 WinSendMsg(handle, MLM_ENABLEREFRESH, 0, 0);
3829 }
3830
3831 /*
3832 * Returns the range of the slider.
3833 * Parameters:
3834 * handle: Handle to the slider to be queried.
3835 */
3836 unsigned int dw_slider_query_range(HWND handle)
3837 {
3838 return SHORT2FROMMP(WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), 0));
3839 }
3840
3841 /*
3842 * Sets the slider position.
3843 * Parameters:
3844 * handle: Handle to the slider to be set.
3845 * position: Position of the slider withing the range.
3846 */
3847 void dw_slider_set_pos(HWND handle, unsigned int position)
3848 {
3849 WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)position);
3850 }
3851
3852 /*
3853 * Sets the spinbutton value.
3854 * Parameters:
3855 * handle: Handle to the spinbutton to be set.
3856 * position: Current value of the spinbutton.
3857 */
3858 void dw_spinbutton_set_pos(HWND handle, long position)
3859 {
3860 WinSendMsg(handle, SPBM_SETCURRENTVALUE, MPFROMLONG((long)position), 0L);
3861 }
3862
3863 /*
3864 * Sets the spinbutton limits.
3865 * Parameters:
3866 * handle: Handle to the spinbutton to be set.
3867 * upper: Upper limit.
3868 * lower: Lower limit.
3869 */
3870 void dw_spinbutton_set_limits(HWND handle, long upper, long lower)
3871 {
3872 WinSendMsg(handle, SPBM_SETLIMITS, MPFROMLONG(upper), MPFROMLONG(lower));
3873 }
3874
3875 /*
3876 * Sets the entryfield character limit.
3877 * Parameters:
3878 * handle: Handle to the spinbutton to be set.
3879 * limit: Number of characters the entryfield will take.
3880 */
3881 void dw_entryfield_set_limit(HWND handle, ULONG limit)
3882 {
3883 WinSendMsg(handle, EM_SETTEXTLIMIT, (MPARAM)limit, (MPARAM)0);
3884 }
3885
3886
3887 /*
3888 * Returns the current value of the spinbutton.
3889 * Parameters:
3890 * handle: Handle to the spinbutton to be queried.
3891 */
3892 long dw_spinbutton_query(HWND handle)
3893 {
3894 long tmpval = 0L;
3895
3896 WinSendMsg(handle, SPBM_QUERYVALUE, (MPARAM)&tmpval,0L);
3897 return tmpval;
3898 }
3899
3900 /*
3901 * Returns the state of the checkbox.
3902 * Parameters:
3903 * handle: Handle to the checkbox to be queried.
3904 */
3905 int dw_checkbox_query(HWND handle)
3906 {
3907 return (int)WinSendMsg(handle,BM_QUERYCHECK,0,0);
3908 }
3909
3910 /*
3911 * Sets the state of the checkbox.
3912 * Parameters:
3913 * handle: Handle to the checkbox to be queried.
3914 * value: TRUE for checked, FALSE for unchecked.
3915 */
3916 void dw_checkbox_set(HWND handle, int value)
3917 {
3918 WinSendMsg(handle,BM_SETCHECK,MPFROMSHORT(value),0);
3919 }
3920
3921 /*
3922 * Sets up the container columns.
3923 * Parameters:
3924 * handle: Handle to the container to be configured.
3925 * flags: An array of unsigned longs with column flags.
3926 * titles: An array of strings with column text titles.
3927 * count: The number of columns (this should match the arrays).
3928 * separator: The column number that contains the main separator.
3929 * (this item may only be used in OS/2)
3930 */
3931 int dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator)
3932 {
3933 PFIELDINFO details, first, left = NULL;
3934 FIELDINFOINSERT detin;
3935 CNRINFO cnri;
3936 int z;
3937 ULONG size = sizeof(RECORDCORE);
3938 ULONG *offStruct = malloc(count * sizeof(ULONG));
3939 ULONG *tempflags = malloc((count+1) * sizeof(ULONG));
3940 ULONG *oldflags = (ULONG *)WinQueryWindowPtr(handle, 0);
3941
3942 if(!offStruct || !tempflags)
3943 return FALSE;
3944
3945 memcpy(tempflags, flags, count * sizeof(ULONG));
3946 tempflags[count] = 0;
3947
3948 WinSetWindowPtr(handle, 0, tempflags);
3949
3950 if(oldflags)
3951 free(oldflags);
3952
3953 while((first = (PFIELDINFO)WinSendMsg(handle, CM_QUERYDETAILFIELDINFO, 0, MPFROMSHORT(CMA_FIRST))) != NULL)
3954 {
3955 WinSendMsg(handle, CM_REMOVEDETAILFIELDINFO, (MPARAM)&first, MPFROM2SHORT(1, CMA_FREE));
3956 }
3957
3958 /* Figure out the offsets to the items in the struct */
3959 for(z=0;z<count;z++)
3960 {
3961 offStruct[z] = size;
3962 if(flags[z] & DW_CFA_BITMAPORICON)
3963 size += sizeof(HPOINTER);
3964 else if(flags[z] & DW_CFA_STRING)
3965 size += sizeof(char *);
3966 else if(flags[z] & DW_CFA_ULONG)
3967 size += sizeof(ULONG);
3968 else if(flags[z] & DW_CFA_DATE)
3969 size += sizeof(CDATE);
3970 else if(flags[z] & DW_CFA_TIME)
3971 size += sizeof(CTIME);
3972 }
3973
3974 first = details = (PFIELDINFO)WinSendMsg(handle, CM_ALLOCDETAILFIELDINFO, MPFROMLONG(count), 0L);
3975
3976 if(!first)
3977 {
3978 free(offStruct);
3979 return FALSE;
3980 }
3981
3982 for(z=0;z<count;z++)
3983 {
3984 if(z==separator-1)
3985 left=details;
3986 details->cb = sizeof(FIELDINFO);
3987 details->flData = flags[z];
3988 details->flTitle = CFA_FITITLEREADONLY;
3989 details->pTitleData = titles[z];
3990 details->offStruct = offStruct[z];
3991 details = details->pNextFieldInfo;
3992 }
3993
3994 detin.cb = sizeof(FIELDINFOINSERT);
3995 detin.fInvalidateFieldInfo = FALSE;
3996 detin.pFieldInfoOrder = (PFIELDINFO) CMA_FIRST;
3997 detin.cFieldInfoInsert = (ULONG)count;
3998
3999 WinSendMsg(handle, CM_INSERTDETAILFIELDINFO, MPFROMP(first), MPFROMP(&detin));
4000
4001 if(count > separator)
4002 {
4003 cnri.cb = sizeof(CNRINFO);
4004 cnri.pFieldInfoLast = left;
4005 cnri.xVertSplitbar = 150;
4006
4007 WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri), MPFROMLONG(CMA_PFIELDINFOLAST | CMA_XVERTSPLITBAR));
4008 }
4009
4010 free(offStruct);
4011 return TRUE;
4012 }
4013
4014 /*
4015 * Sets up the filesystem columns, note: filesystem always has an icon/filename field.
4016 * Parameters:
4017 * handle: Handle to the container to be configured.
4018 * flags: An array of unsigned longs with column flags.
4019 * titles: An array of strings with column text titles.
4020 * count: The number of columns (this should match the arrays).
4021 */
4022 int dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count)
4023 {
4024 char **newtitles = malloc(sizeof(char *) * (count + 2));
4025 unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 2));
4026
4027 newtitles[0] = "Icon";
4028 newtitles[1] = "Filename";
4029
4030 newflags[0] = DW_CFA_BITMAPORICON | DW_CFA_CENTER | DW_CFA_HORZSEPARATOR | DW_CFA_SEPARATOR;
4031 newflags[1] = DW_CFA_STRING | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR;
4032
4033 memcpy(&newtitles[2], titles, sizeof(char *) * count);
4034 memcpy(&newflags[2], flags, sizeof(unsigned long) * count);
4035
4036 dw_container_setup(handle, newflags, newtitles, count + 2, 2);
4037
4038 free(newtitles);
4039 free(newflags);
4040 return TRUE;
4041 }
4042
4043 /*
4044 * Obtains an icon from a module (or header in GTK).
4045 * Parameters:
4046 * module: Handle to module (DLL) in OS/2 and Windows.
4047 * id: A unsigned long id int the resources on OS/2 and
4048 * Windows, on GTK this is converted to a pointer
4049 * to an embedded XPM.
4050 */
4051 unsigned long dw_icon_load(unsigned long module, unsigned long id)
4052 {
4053 return WinLoadPointer(HWND_DESKTOP,module,id);
4054 }
4055
4056 /*
4057 * Frees a loaded resource in OS/2 and Windows.
4058 * Parameters:
4059 * handle: Handle to icon returned by dw_icon_load().
4060 */
4061 void dw_icon_free(unsigned long handle)
4062 {
4063 WinDestroyPointer(handle);
4064 }
4065
4066 /*
4067 * Allocates memory used to populate a container.
4068 * Parameters:
4069 * handle: Handle to the container window (widget).
4070 * rowcount: The number of items to be populated.
4071 */
4072 void *dw_container_alloc(HWND handle, int rowcount)
4073 {
4074 ULONG *flags = (ULONG *)WinQueryWindowPtr(handle, 0);
4075 int z, size = 0, totalsize, count = 0;
4076 PRECORDCORE temp;
4077 void *blah;
4078
4079 if(!flags)
4080 return NULL;
4081
4082 while(flags[count])
4083 count++;
4084
4085 /* Figure out the offsets to the items in the struct */
4086 for(z=0;z<count;z++)
4087 {
4088 if(flags[z] & DW_CFA_BITMAPORICON)
4089 size += sizeof(HPOINTER);
4090 else if(flags[z] & DW_CFA_STRING)
4091 size += sizeof(char *);
4092 else if(flags[z] & DW_CFA_ULONG)
4093 size += sizeof(ULONG);
4094 else if(flags[z] & DW_CFA_DATE)
4095 size += sizeof(CDATE);
4096 else if(flags[z] & DW_CFA_TIME)
4097 size += sizeof(CTIME);
4098 }
4099
4100 totalsize = size + sizeof(RECORDCORE);
4101
4102 blah = (void *)WinSendMsg(handle, CM_ALLOCRECORD, MPFROMLONG(size), MPFROMLONG(rowcount));
4103
4104 if(!blah)
4105 return NULL;
4106
4107 temp = (PRECORDCORE)blah;
4108
4109 for(z=0;z<rowcount;z++)
4110 {
4111 temp->cb = totalsize;
4112 temp = temp->preccNextRecord;
4113 }
4114
4115 return blah;
4116 }
4117
4118 /*
4119 * Sets an item in specified row and column to the given data.
4120 * Parameters:
4121 * handle: Handle to the container window (widget).
4122 * pointer: Pointer to the allocated memory in dw_container_alloc().
4123 * column: Zero based column of data being set.
4124 * row: Zero based row of data being set.
4125 * data: Pointer to the data to be added.
4126 */
4127 void dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data)
4128 {
4129 ULONG totalsize, size = 0, *flags = (ULONG *)WinQueryWindowPtr(handle, 0);
4130 int z;
4131 PRECORDCORE temp = (PRECORDCORE)pointer;
4132 void *dest;
4133
4134 if(!flags)
4135 return;
4136
4137 /* Figure out the offsets to the items in the struct */
4138 for(z=0;z<column;z++)
4139 {
4140 if(flags[z] & DW_CFA_BITMAPORICON)
4141 size += sizeof(HPOINTER);
4142 else if(flags[z] & DW_CFA_STRING)
4143 size += sizeof(char *);
4144 else if(flags[z] & DW_CFA_ULONG)
4145 size += sizeof(ULONG);
4146 else if(flags[z] & DW_CFA_DATE)
4147 size += sizeof(CDATE);
4148 else if(flags[z] & DW_CFA_TIME)
4149 size += sizeof(CTIME);
4150 }
4151
4152 totalsize = size + sizeof(RECORDCORE);
4153
4154 for(z=0;z<row;z++)
4155 temp = temp->preccNextRecord;
4156
4157 dest = (void *)(((ULONG)temp)+((ULONG)totalsize));
4158
4159 if(flags[column] & DW_CFA_BITMAPORICON)
4160 memcpy(dest, data, sizeof(HPOINTER));
4161 else if(flags[column] & DW_CFA_STRING)
4162 memcpy(dest, data, sizeof(char *));
4163 else if(flags[column] & DW_CFA_ULONG)
4164 memcpy(dest, data, sizeof(ULONG));
4165 else if(flags[column] & DW_CFA_DATE)
4166 memcpy(dest, data, sizeof(CDATE));
4167 else if(flags[column] & DW_CFA_TIME)
4168 memcpy(dest, data, sizeof(CTIME));
4169 }
4170
4171 /*
4172 * Sets an item in specified row and column to the given data.
4173 * Parameters:
4174 * handle: Handle to the container window (widget).
4175 * pointer: Pointer to the allocated memory in dw_container_alloc().
4176 * column: Zero based column of data being set.
4177 * row: Zero based row of data being set.
4178 * data: Pointer to the data to be added.
4179 */
4180 void dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon)
4181 {
4182 dw_container_set_item(handle, pointer, 0, row, (void *)&icon);
4183 dw_container_set_item(handle, pointer, 1, row, (void *)&filename);
4184 }
4185
4186 /*
4187 * Sets an item in specified row and column to the given data.
4188 * Parameters:
4189 * handle: Handle to the container window (widget).
4190 * pointer: Pointer to the allocated memory in dw_container_alloc().
4191 * column: Zero based column of data being set.
4192 * row: Zero based row of data being set.
4193 * data: Pointer to the data to be added.
4194 */
4195 void dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data)
4196 {
4197 dw_container_set_item(handle, pointer, column + 2, row, data);
4198 }
4199
4200 /*
4201 * Sets the title of a row in the container.
4202 * Parameters:
4203 * pointer: Pointer to the allocated memory in dw_container_alloc().
4204 * row: Zero based row of data being set.
4205 * title: String title of the item.
4206 */
4207 void dw_container_set_row_title(void *pointer, int row, char *title)
4208 {
4209 PRECORDCORE temp = (PRECORDCORE)pointer;
4210 int z;
4211
4212 for(z=0;z<row;z++)
4213 temp = temp->preccNextRecord;
4214
4215 temp->pszIcon = title;
4216 temp->pszName = title;
4217 temp->pszText = title;
4218 }
4219
4220 /*
4221 * Sets the title of a row in the container.
4222 * Parameters:
4223 * handle: Handle to the container window (widget).
4224 * pointer: Pointer to the allocated memory in dw_container_alloc().
4225 * rowcount: The number of rows to be inserted.
4226 */
4227 void dw_container_insert(HWND handle, void *pointer, int rowcount)
4228 {
4229 RECORDINSERT recin;
4230
4231 recin.cb = sizeof(RECORDINSERT);
4232 recin.pRecordOrder = (PRECORDCORE)CMA_END;
4233 recin.pRecordParent = NULL;
4234 recin.zOrder = CMA_TOP;
4235 recin.fInvalidateRecord = TRUE;
4236 recin.cRecordsInsert = rowcount;
4237
4238 WinSendMsg(handle, CM_INSERTRECORD, MPFROMP(pointer), MPFROMP(&recin));
4239 }
4240
4241 /*
4242 * Removes all rows from a container.
4243 * Parameters:
4244 * handle: Handle to the window (widget) to be cleared.
4245 */
4246 void dw_container_clear(HWND handle)
4247 {
4248 WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)0L, MPFROM2SHORT(0, CMA_INVALIDATE | CMA_FREE));
4249 }
4250
4251 /*
4252 * Removes all rows from a container.
4253 * Parameters:
4254 * handle: Handle to the window (widget) to be cleared.
4255 */
4256 void dw_container_set_view(HWND handle, unsigned long flags, int iconwidth, int iconheight)
4257 {
4258 CNRINFO cnrinfo;
4259
4260 cnrinfo.flWindowAttr = flags;
4261 cnrinfo.slBitmapOrIcon.cx = iconwidth;
4262 cnrinfo.slBitmapOrIcon.cy = iconheight;
4263
4264 WinSendMsg(handle, CM_SETCNRINFO, &cnrinfo, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON));
4265 }
4266
4267 /*
4268 * Starts a new query of a container.
4269 * Parameters:
4270 * handle: Handle to the window (widget) to be queried.
4271 * flags: If this parameter is DW_CRA_SELECTED it will only
4272 * return items that are currently selected. Otherwise
4273 * it will return all records in the container.
4274 */
4275 char *dw_container_query_start(HWND handle, unsigned long flags)
4276 {
4277 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
4278 if(pCore)
4279 {
4280 if(flags)
4281 {
4282 while(pCore)
4283 {
4284 if(pCore->flRecordAttr & CRA_SELECTED)
4285 return pCore->pszIcon;
4286 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
4287 }
4288 }
4289 else
4290 return pCore->pszIcon;
4291 }
4292 return NULL;
4293 }
4294
4295 /*
4296 * Continues an existing query of a container.
4297 * Parameters:
4298 * handle: Handle to the window (widget) to be queried.
4299 * flags: If this parameter is DW_CRA_SELECTED it will only
4300 * return items that are currently selected. Otherwise
4301 * it will return all records in the container.
4302 */
4303 char *dw_container_query_next(HWND handle, unsigned long flags)
4304 {
4305 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
4306 if(pCore)
4307 {
4308 if(flags)
4309 {
4310 while(pCore)
4311 {
4312 if(pCore->flRecordAttr & CRA_SELECTED)
4313 return pCore->pszIcon;
4314
4315 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
4316 }
4317 }
4318 else
4319 return pCore->pszIcon;
4320 }
4321 return NULL;
4322 }
4323
4324 /*
4325 * Creates a rendering context widget (window) to be packed.
4326 * Parameters:
4327 * id: An id to be used with dw_window_from_id.
4328 * Returns:
4329 * A handle to the widget or NULL on failure.
4330 */
4331 HWND dw_render_new(unsigned long id)
4332 {
4333 HWND hwndframe = WinCreateWindow(HWND_OBJECT,
4334 WC_FRAME,
4335 NULL,
4336 WS_VISIBLE,
4337 0,0,2000,1000,
4338 NULLHANDLE,
4339 HWND_TOP,
4340 id,
4341 NULL,
4342 NULL);
4343 WinSubclassWindow(hwndframe, _RendProc);
4344 return hwndframe;
4345 }
4346
4347 /* Sets the current foreground drawing color.
4348 * Parameters:
4349 * red: red value.
4350 * green: green value.
4351 * blue: blue value.
4352 */
4353 void dw_color_foreground_set(unsigned long value)
4354 {
4355 _foreground = DW_RED_VALUE(value) << 16 | DW_GREEN_VALUE(value) << 8 | DW_BLUE_VALUE(value);
4356 }
4357
4358 /* Sets the current background drawing color.
4359 * Parameters:
4360 * red: red value.
4361 * green: green value.
4362 * blue: blue value.
4363 */
4364 void dw_color_background_set(unsigned long value)
4365 {
4366 _background = DW_RED_VALUE(value) << 16 | DW_GREEN_VALUE(value) << 8 | DW_BLUE_VALUE(value);
4367 }
4368
4369 HPS _set_hps(HPS hps)
4370 {
4371 LONG alTable[18];
4372
4373 GpiQueryLogColorTable(hps, 0L, 0L, 18L, alTable);
4374
4375 alTable[16] = _foreground;
4376 alTable[17] = _background;
4377
4378 GpiCreateLogColorTable(hps,
4379 0L,
4380 LCOLF_CONSECRGB,
4381 0L,
4382 18,
4383 alTable);
4384 GpiSetColor(hps, 16);
4385 GpiSetBackColor(hps, 17);
4386 return hps;
4387 }
4388
4389 HPS _set_colors(HWND handle)
4390 {
4391 HPS hps = WinGetPS(handle);
4392
4393 _set_hps(hps);
4394 return hps;
4395 }
4396
4397 /* Draw a point on a window (preferably a render window).
4398 * Parameters:
4399 * handle: Handle to the window.
4400 * pixmap: Handle to the pixmap. (choose only one of these)
4401 * x: X coordinate.
4402 * y: Y coordinate.
4403 */
4404 void dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y)
4405 {
4406 HPS hps;
4407 int height;
4408 POINTL ptl;
4409
4410 if(handle)
4411 {
4412 hps = _set_colors(handle);
4413 height = _get_height(handle);
4414 }
4415 else if(pixmap)
4416 {
4417 hps = _set_hps(pixmap->hps);
4418 height = pixmap->height;
4419 }
4420 else
4421 return;
4422
4423 ptl.x = x;
4424 ptl.y = height - y - 1;
4425
4426 GpiSetPel(hps, &ptl);
4427 if(!pixmap)
4428 WinReleasePS(hps);
4429 }
4430
4431 /* Draw a line on a window (preferably a render window).
4432 * Parameters:
4433 * handle: Handle to the window.
4434 * pixmap: Handle to the pixmap. (choose only one of these)
4435 * x1: First X coordinate.
4436 * y1: First Y coordinate.
4437 * x2: Second X coordinate.
4438 * y2: Second Y coordinate.
4439 */
4440 void dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2)
4441 {
4442 HPS hps;
4443 int height;
4444 POINTL ptl[2];
4445
4446 if(handle)
4447 {
4448 hps = _set_colors(handle);
4449 height = _get_height(handle);
4450 }
4451 else if(pixmap)
4452 {
4453 hps = _set_hps(pixmap->hps);
4454 height = pixmap->height;
4455 }
4456 else
4457 return;
4458
4459 ptl[0].x = x1;
4460 ptl[0].y = height - y1 - 1;
4461 ptl[1].x = x2;
4462 ptl[1].y = height - y2 - 1;
4463
4464 GpiMove(hps, &ptl[0]);
4465 GpiLine(hps, &ptl[1]);
4466
4467 if(!pixmap)
4468 WinReleasePS(hps);
4469 }
4470
4471
4472 /* Draw text on a window (preferably a render window).
4473 * Parameters:
4474 * handle: Handle to the window.
4475 * pixmap: Handle to the pixmap. (choose only one of these)
4476 * x: X coordinate.
4477 * y: Y coordinate.
4478 * text: Text to be displayed.
4479 */
4480 void dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text)
4481 {
4482 HPS hps;
4483 int size = 9, z, l, height;
4484 POINTL ptl;
4485 FATTRS fat;
4486 SIZEF sizfCharBox;
4487 FONTMETRICS *fm;
4488 LONG lHorzRes, lVertRes, lRequestFonts, lNumberFonts;
4489 HDC hdc;
4490 char fontname[128];
4491
4492 if(handle)
4493 {
4494 hps = _set_colors(handle);
4495 height = _get_height(handle);
4496 _GetPPFont(handle, fontname);
4497 }
4498 else if(pixmap)
4499 {
4500 hps = _set_hps(pixmap->hps);
4501 height = pixmap->height;
4502 _GetPPFont(pixmap->handle, fontname);
4503 }
4504 else
4505 return;
4506
4507 ptl.x = x;
4508 ptl.y = height - y - 2;
4509
4510 for(z=0;z<strlen(fontname);z++)
4511 {
4512 if(fontname[z]=='.')
4513 break;
4514 }
4515 size = atoi(fontname);
4516
4517 ptl.y -= size;
4518
4519 hdc = GpiQueryDevice(hps);
4520
4521 DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1L, &lHorzRes);
4522 DevQueryCaps(hdc, CAPS_VERTICAL_FONT_RES, 1L, &lVertRes);
4523
4524 lNumberFonts = GpiQueryFonts(hps, QF_PUBLIC | QF_PRIVATE, &fontname[z+1], &lRequestFonts, 0, NULL);
4525
4526 fm = malloc(lNumberFonts * sizeof(FONTMETRICS));
4527
4528 GpiQueryFonts(hps, QF_PUBLIC | QF_PRIVATE, &fontname[z+1], &lNumberFonts, sizeof(FONTMETRICS), fm);
4529
4530 fat.lMatch = 0L;
4531
4532 for(l=0;l<lNumberFonts;l++)
4533 {
4534 if(fm[l].sXDeviceRes == (SHORT)lHorzRes &&
4535 fm[l].sYDeviceRes == (SHORT)lVertRes &&
4536 (fm[l].fsDefn & 1) == 0 &&
4537 fm[l].sNominalPointSize == (size*10))
4538 {
4539 fat.lMatch = fm[l].lMatch;
4540 break;
4541 }
4542 }
4543
4544 fat.usRecordLength = sizeof(FATTRS);
4545 fat.fsSelection = 0;
4546 fat.idRegistry = 0;
4547 fat.usCodePage = GpiQueryCp(hps);
4548 fat.lMaxBaselineExt = 0;
4549 fat.lAveCharWidth = 0;
4550 fat.fsType = 0;
4551 fat.fsFontUse = 0;
4552
4553 strcpy(fat.szFacename , &fontname[z+1]);
4554
4555 GpiCreateLogFont(hps, NULL, 1L, &fat);
4556
4557 GpiSetCharSet(hps, 1L);
4558
4559 if(fm)
4560 free(fm);
4561 else
4562 {
4563 sizfCharBox.cx = MAKEFIXED(size,0);
4564 sizfCharBox.cy = MAKEFIXED(size,0);
4565 GpiSetCharBox(hps, &sizfCharBox);
4566 }
4567
4568 GpiCharStringAt(hps, &ptl, strlen(text), text);
4569
4570 if(!pixmap)
4571 WinReleasePS(hps);
4572 }
4573
4574
4575
4576
4577 /* Draw a rectangle on a window (preferably a render window).
4578 * Parameters:
4579 * handle: Handle to the window.
4580 * pixmap: Handle to the pixmap. (choose only one of these)
4581 * fill: Fill box TRUE or FALSE.
4582 * x: X coordinate.
4583 * y: Y coordinate.
4584 * width: Width of rectangle.
4585 * height: Height of rectangle.
4586 */
4587 void dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height)
4588 {
4589 HPS hps;
4590 int thisheight;
4591 POINTL ptl[2];
4592
4593 if(handle)
4594 {
4595 hps = _set_colors(handle);
4596 thisheight = _get_height(handle);
4597 }
4598 else if(pixmap)
4599 {
4600 hps = _set_hps(pixmap->hps);
4601 thisheight = pixmap->height;
4602 }
4603 else
4604 return;
4605
4606 ptl[0].x = x;
4607 ptl[0].y = thisheight - y - 1;
4608 ptl[1].x = x + width - 1;
4609 ptl[1].y = thisheight - y - height;
4610
4611 GpiMove(hps, &ptl[0]);
4612 GpiBox(hps, fill ? DRO_OUTLINEFILL : DRO_OUTLINE, &ptl[1], 0, 0);
4613
4614 if(!pixmap)
4615 WinReleasePS(hps);
4616 }
4617
4618 /* Call this after drawing to the screen to make sure
4619 * anything you have drawn is visible.
4620 */
4621 void dw_flush(void)
4622 {
4623 }
4624
4625 /*
4626 * Creates a pixmap with given parameters.
4627 * Parameters:
4628 * handle: Window handle the pixmap is associated with.
4629 * width: Width of the pixmap in pixels.
4630 * height: Height of the pixmap in pixels.
4631 * depth: Color depth of the pixmap.
4632 * Returns:
4633 * A handle to a pixmap or NULL on failure.
4634 */
4635 HPIXMAP dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth)
4636 {
4637 BITMAPINFOHEADER bmih;
4638 SIZEL sizl = { 0, 0 };
4639 HPIXMAP pixmap;
4640 HDC hdc;
4641 HPS hps;
4642 ULONG ulFlags;
4643 LONG cPlanes, cBitCount;
4644
4645 if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
4646 return NULL;
4647
4648 hps = WinGetPS(handle);
4649
4650 hdc = GpiQueryDevice(hps);
4651 ulFlags = GpiQueryPS(hps, &sizl);
4652
4653 pixmap->handle = handle;
4654 pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc);
4655 pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC);
4656
4657 DevQueryCaps(hdc, CAPS_COLOR_PLANES , 1L, &cPlanes);
4658 if (!depth)
4659 {
4660 DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1L, &cBitCount);
4661 depth = cBitCount;
4662 }
4663
4664 memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
4665 bmih.cbFix = sizeof(BITMAPINFOHEADER);
4666 bmih.cx = (SHORT)width;
4667 bmih.cy = (SHORT)height;
4668 bmih.cPlanes = (SHORT)cPlanes;
4669 bmih.cBitCount = (SHORT)depth;
4670
4671 pixmap->width = width; pixmap->height = height;
4672
4673 pixmap->hbm = GpiCreateBitmap(pixmap->hps, (PBITMAPINFOHEADER2)&bmih, 0L, NULL, NULL);
4674
4675 GpiSetBitmap(pixmap->hps, pixmap->hbm);
4676
4677 if (depth>8)
4678 GpiCreateLogColorTable(pixmap->hps, LCOL_PURECOLOR, LCOLF_RGB, 0, 0, NULL );
4679
4680 WinReleasePS(hps);
4681
4682 return pixmap;
4683 }
4684
4685 /*
4686 * Creates a pixmap from internal resource graphic specified by id.
4687 * Parameters:
4688 * handle: Window handle the pixmap is associated with.
4689 * id: Resource ID associated with requested pixmap.
4690 * Returns:
4691 * A handle to a pixmap or NULL on failure.
4692 */
4693 HPIXMAP dw_pixmap_grab(HWND handle, ULONG id)
4694 {
4695 BITMAPINFOHEADER bmih;
4696 SIZEL sizl = { 0, 0 };
4697 HPIXMAP pixmap;
4698 HDC hdc;
4699 HPS hps;
4700 ULONG ulFlags;
4701
4702 if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
4703 return NULL;
4704
4705 hps = WinGetPS(handle);
4706
4707 hdc = GpiQueryDevice(hps);
4708 ulFlags = GpiQueryPS(hps, &sizl);
4709
4710 pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc);
4711 pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC);
4712
4713 pixmap->hbm = GpiLoadBitmap(pixmap->hps, NULLHANDLE, id, 0, 0);
4714
4715 GpiQueryBitmapParameters(pixmap->hbm, &bmih);
4716
4717 GpiSetBitmap(pixmap->hps, pixmap->hbm);
4718
4719 pixmap->width = bmih.cx; pixmap->height = bmih.cy;
4720
4721 WinReleasePS(hps);
4722
4723 return pixmap;
4724 }
4725
4726 /*
4727 * Destroys an allocated pixmap.
4728 * Parameters:
4729 * pixmap: Handle to a pixmap returned by
4730 * dw_pixmap_new..
4731 */
4732 void dw_pixmap_destroy(HPIXMAP pixmap)
4733 {
4734 GpiSetBitmap(pixmap->hps, NULLHANDLE);
4735 GpiDeleteBitmap(pixmap->hbm);
4736 GpiAssociate(pixmap->hps, NULLHANDLE);
4737 GpiDestroyPS(pixmap->hps);
4738 DevCloseDC(pixmap->hdc);
4739 free(pixmap);
4740 }
4741
4742 /*
4743 * Copies from one item to another.
4744 * Parameters:
4745 * dest: Destination window handle.
4746 * destp: Destination pixmap. (choose only one).
4747 * xdest: X coordinate of destination.
4748 * ydest: Y coordinate of destination.
4749 * width: Width of area to copy.
4750 * height: Height of area to copy.
4751 * src: Source window handle.
4752 * srcp: Source pixmap. (choose only one).
4753 * xsrc: X coordinate of source.
4754 * ysrc: Y coordinate of source.
4755 */
4756 void dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc)
4757 {
4758 HPS hpsdest;
4759 HPS hpssrc;
4760 POINTL ptl[4];
4761 int destheight, srcheight;
4762
4763 if(dest)
4764 {
4765 hpsdest = WinGetPS(dest);
4766 destheight = _get_height(dest);
4767 }
4768 else if(destp)
4769 {
4770 hpsdest = destp->hps;
4771 destheight = destp->height;
4772 }
4773 else
4774 return;
4775
4776 if(src)
4777 {
4778 hpssrc = WinGetPS(src);
4779 srcheight = _get_height(src);
4780 }
4781 else if(srcp)
4782 {
4783 hpssrc = srcp->hps;
4784 srcheight = srcp->height;
4785 }
4786 else
4787 {
4788 if(!destp)
4789 WinReleasePS(hpsdest);
4790 return;
4791 }
4792
4793 ptl[0].x = xdest;
4794 ptl[0].y = (destheight - ydest) - height;
4795 ptl[1].x = ptl[0].x + width;
4796 ptl[1].y = destheight - ydest;
4797 ptl[2].x = xsrc;
4798 ptl[2].y = srcheight - (ysrc + height);
4799 ptl[3].x = ptl[2].x + width;
4800 ptl[3].y = ptl[2].y + height;
4801
4802 GpiBitBlt(hpsdest, hpssrc, 4, ptl, ROP_SRCCOPY, BBO_IGNORE);
4803
4804 if(!destp)
4805 WinReleasePS(hpsdest);
4806 if(!srcp)
4807 WinReleasePS(hpssrc);
4808 }
4809
4810 /*
4811 * Emits a beep.
4812 * Parameters:
4813 * freq: Frequency.
4814 * dur: Duration.
4815 */
4816 void dw_beep(int freq, int dur)
4817 {
4818 DosBeep(freq, dur);
4819 }
4820
4821 /*
4822 * Returns the handle to an unnamed mutex semaphore.
4823 */
4824 HMTX dw_mutex_new(void)
4825 {
4826 HMTX mutex;
4827
4828 DosCreateMutexSem(NULL, &mutex, 0, FALSE);
4829 return mutex;
4830 }
4831
4832 /*
4833 * Closes a semaphore created by dw_mutex_new().
4834 * Parameters:
4835 * mutex: The handle to the mutex returned by dw_mutex_new().
4836 */
4837 void dw_mutex_close(HMTX mutex)
4838 {
4839 DosCloseMutexSem(mutex);
4840 }
4841
4842 /*
4843 * Tries to gain access to the semaphore, if it can't it blocks.
4844 * Parameters:
4845 * mutex: The handle to the mutex returned by dw_mutex_new().
4846 */
4847 void dw_mutex_lock(HMTX mutex)
4848 {
4849 DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT);
4850 }
4851
4852 /*
4853 * Reliquishes the access to the semaphore.
4854 * Parameters:
4855 * mutex: The handle to the mutex returned by dw_mutex_new().
4856 */
4857 void dw_mutex_unlock(HMTX mutex)
4858 {
4859 DosReleaseMutexSem(mutex);
4860 }
4861
4862 /*
4863 * Returns the handle to an unnamed event semaphore.
4864 */
4865 HEV dw_event_new(void)
4866 {
4867 HEV blah;
4868
4869 if(DosCreateEventSem (NULL, &blah, 0L, FALSE))
4870 return 0;
4871
4872 return blah;
4873 }
4874
4875 /*
4876 * Resets a semaphore created by dw_event_new().
4877 * Parameters:
4878 * eve: The handle to the event returned by dw_event_new().
4879 */
4880 int dw_event_reset(HEV eve)
4881 {
4882 ULONG count;
4883
4884 if(DosResetEventSem(eve, &count))
4885 return FALSE;
4886 return TRUE;
4887 }
4888
4889 /*
4890 * Posts a semaphore created by dw_event_new(). Causing all threads
4891 * waiting on this event in dw_event_wait to continue.
4892 * Parameters:
4893 * eve: The handle to the event returned by dw_event_new().
4894 */
4895 int dw_event_post(HEV eve)
4896 {
4897 if(DosPostEventSem(eve))
4898 return FALSE;
4899 return TRUE;
4900 }
4901
4902
4903 /*
4904 * Waits on a semaphore created by dw_event_new(), until the
4905 * event gets posted or until the timeout expires.
4906 * Parameters:
4907 * eve: The handle to the event returned by dw_event_new().
4908 */
4909 int dw_event_wait(HEV eve, unsigned long timeout)
4910 {
4911 int rc = DosWaitEventSem(eve, timeout);
4912 if(!rc)
4913 return 1;
4914 if(rc == ERROR_TIMEOUT)
4915 return -1;
4916 return 0;
4917 }
4918
4919 /*
4920 * Closes a semaphore created by dw_event_new().
4921 * Parameters:
4922 * eve: The handle to the event returned by dw_event_new().
4923 */
4924 int dw_event_close(HEV *eve)
4925 {
4926 if(!eve || ~DosCloseEventSem(*eve))
4927 return FALSE;
4928 return TRUE;
4929 }
4930
4931 /*
4932 * Encapsulate the message queues on OS/2.
4933 */
4934 void _dwthreadstart(void *data)
4935 {
4936 HAB thishab = WinInitialize(0);
4937 HMQ thishmq = WinCreateMsgQueue(dwhab, 0);
4938 void (*threadfunc)(void *) = NULL;
4939 void **tmp = (void **)data;
4940
4941 threadfunc = (void (*)(void *))tmp[0];
4942 threadfunc(tmp[1]);
4943
4944 free(tmp);
4945
4946 WinDestroyMsgQueue(thishmq);
4947 WinTerminate(thishab);
4948 }
4949
4950 /*
4951 * Creates a new thread with a starting point of func.
4952 * Parameters:
4953 * func: Function which will be run in the new thread.
4954 * data: Parameter(s) passed to the function.
4955 * stack: Stack size of new thread (OS/2 and Windows only).
4956 */
4957 DWTID dw_thread_new(void *func, void *data, int stack)
4958 {
4959 void **tmp = malloc(sizeof(void *) * 2);
4960
4961 tmp[0] = func;
4962 tmp[1] = data;
4963
4964 return (DWTID)_beginthread((void (*)(void *))_dwthreadstart, NULL, stack, (void *)tmp);
4965 }
4966
4967 /*
4968 * Ends execution of current thread immediately.
4969 */
4970 void dw_thread_end(void)
4971 {
4972 _endthread();
4973 }
4974
4975 /*
4976 * Returns the current thread's ID.
4977 */
4978 DWTID dw_thread_id(void)
4979 {
4980 return (DWTID)_threadid;
4981 }
4982
4983 /*
4984 * Cleanly terminates a DW session, should be signal handler safe.
4985 * Parameters:
4986 * exitcode: Exit code reported to the operating system.
4987 */
4988 void dw_exit(int exitcode)
4989 {
4990 /* In case we are in a signal handler, don't
4991 * try to free memory that could possibly be
4992 * free()'d by the runtime already.
4993 */
4994 #ifndef NO_SIGNALS
4995 Root = NULL;
4996 #endif
4997 exit(exitcode);
4998 }
4999
5000 /*
5001 * Pack a splitbar (sizer) into the specified box from the start.
5002 * Parameters:
5003 * box: Window handle of the box to be packed into.
5004 */
5005 void dw_box_pack_splitbar_start(HWND box)
5006 {
5007 Box *thisbox;
5008
5009 if(WinWindowFromID(box, FID_CLIENT))
5010 {
5011 box = WinWindowFromID(box, FID_CLIENT);
5012 thisbox = WinQueryWindowPtr(box, QWP_USER);
5013 }
5014 else
5015 thisbox = WinQueryWindowPtr(box, QWP_USER);
5016 if(thisbox)
5017 {
5018 HWND tmp = WinCreateWindow(HWND_OBJECT,
5019 SplitbarClassName,
5020 NULL,
5021 WS_VISIBLE,
5022 0,0,2000,1000,
5023 NULLHANDLE,
5024 HWND_TOP,
5025 0L,
5026 NULL,
5027 NULL);
5028 if(thisbox->type == BOXVERT)
5029 dw_box_pack_start(box, tmp, 1, SPLITBAR_WIDTH, TRUE, FALSE, 0);
5030 else
5031 dw_box_pack_start(box, tmp, SPLITBAR_WIDTH, 1, FALSE, TRUE, 0);
5032
5033 }
5034 }
5035
5036 /*
5037 * Pack a splitbar (sizer) into the specified box from the end.
5038 * Parameters:
5039 * box: Window handle of the box to be packed into.
5040 */
5041 void dw_box_pack_splitbar_end(HWND box)
5042 {
5043 Box *thisbox;
5044
5045 if(WinWindowFromID(box, FID_CLIENT))
5046 {
5047 box = WinWindowFromID(box, FID_CLIENT);
5048 thisbox = WinQueryWindowPtr(box, QWP_USER);
5049 }
5050 else
5051 thisbox = WinQueryWindowPtr(box, QWP_USER);
5052 if(thisbox)
5053 {
5054 HWND tmp = WinCreateWindow(HWND_OBJECT,
5055 SplitbarClassName,
5056 NULL,
5057 WS_VISIBLE,
5058 0,0,2000,1000,
5059 NULLHANDLE,
5060 HWND_TOP,
5061 0L,
5062 NULL,
5063 NULL);
5064 if(thisbox->type == BOXVERT)
5065 dw_box_pack_end(box, tmp, 1, SPLITBAR_WIDTH, TRUE, FALSE, 0);
5066 else
5067 dw_box_pack_end(box, tmp, SPLITBAR_WIDTH, 1, FALSE, TRUE, 0);
5068
5069 }
5070 }
5071
5072 /*
5073 * Pack windows (widgets) into a box from the start (or top).
5074 * Parameters:
5075 * box: Window handle of the box to be packed into.
5076 * item: Window handle of the item to be back.
5077 * width: Width in pixels of the item or -1 to be self determined.
5078 * height: Height in pixels of the item or -1 to be self determined.
5079 * hsize: TRUE if the window (widget) should expand horizontally to fill space given.
5080 * vsize: TRUE if the window (widget) should expand vertically to fill space given.
5081 * pad: Number of pixels of padding around the item.
5082 */
5083 void dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
5084 {
5085 Box *thisbox;
5086
5087 if(WinWindowFromID(box, FID_CLIENT))
5088 {
5089 box = WinWindowFromID(box, FID_CLIENT);
5090 thisbox = WinQueryWindowPtr(box, QWP_USER);
5091 }
5092 else
5093 thisbox = WinQueryWindowPtr(box, QWP_USER);
5094 if(thisbox)
5095 {
5096 if(thisbox->type == BOXHORZ)
5097 dw_box_pack_end_stub(box, item, width, height, hsize, vsize, pad);
5098 else
5099 dw_box_pack_start_stub(box, item, width, height, hsize, vsize, pad);
5100 }
5101 }
5102
5103 void dw_box_pack_start_stub(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
5104 {
5105 HWND boxowner = NULLHANDLE;
5106 Box *thisbox;
5107
5108 if(WinWindowFromID(box, FID_CLIENT))
5109 {
5110 box = WinWindowFromID(box, FID_CLIENT);
5111 thisbox = WinQueryWindowPtr(box, QWP_USER);
5112 hsize = TRUE;
5113 vsize = TRUE;
5114 }
5115 else
5116 thisbox = WinQueryWindowPtr(box, QWP_USER);
5117 if(thisbox)
5118 {
5119 int z;
5120 Item *tmpitem, *thisitem = thisbox->items;
5121 char tmpbuf[100];
5122
5123 tmpitem = malloc(sizeof(Item)*(thisbox->count+1));
5124
5125 for(z=0;z<thisbox->count;z++)
5126 {
5127 tmpitem[z+1] = thisitem[z];
5128 }
5129
5130 WinQueryClassName(item, 99, tmpbuf);
5131
5132 if(strncmp(tmpbuf, "#1", 2)==0)
5133 tmpitem[0].type = TYPEBOX;
5134 else
5135 tmpitem[0].type = TYPEITEM;
5136
5137 tmpitem[0].hwnd = item;
5138 tmpitem[0].origwidth = tmpitem[0].width = width;
5139 tmpitem[0].origheight = tmpitem[0].height = height;
5140 tmpitem[0].pad = pad;
5141 if(hsize)
5142 tmpitem[0].hsize = SIZEEXPAND;
5143 else
5144 tmpitem[0].hsize = SIZESTATIC;
5145
5146 if(vsize)
5147 tmpitem[0].vsize = SIZEEXPAND;
5148 else
5149 tmpitem[0].vsize = SIZESTATIC;
5150
5151 thisbox->items = tmpitem;
5152
5153 if(thisbox->count)
5154 free(thisitem);
5155
5156 thisbox->count++;
5157
5158 WinQueryClassName(item, 99, tmpbuf);
5159 /* Don't set the ownership if it's an entryfield or combobox */
5160 if(strncmp(tmpbuf, "#6", 2)!=0 /*&& strncmp(tmpbuf, "#2", 2)!=0*/)
5161 {
5162 if((boxowner = WinQueryWindow(box, QW_OWNER)) != 0)
5163 WinSetOwner(item, boxowner);
5164 else
5165 WinSetOwner(item, box);
5166 }
5167 WinSetParent(item, box, FALSE);
5168 }
5169 }
5170
5171 /* The following two functions graciously contributed by Peter Nielsen. */
5172 static ULONG _ParseBuildLevel (char* pchBuffer, ULONG ulSize) {
5173 char* pchStart = pchBuffer;
5174 char* pchEnd = pchStart + ulSize - 2;
5175
5176 while (pchEnd >= pchStart)
5177 {
5178 if ((pchEnd[0] == '#') && (pchEnd[1] == '@'))
5179 {
5180 *pchEnd-- = '\0';
5181 while (pchEnd >= pchStart)
5182 {
5183 if ((pchEnd[0] == '@') && (pchEnd[1] == '#'))
5184 {
5185 ULONG ulMajor = 0;
5186 ULONG ulMinor = 0;
5187
5188 char* pch = pchEnd + 2;
5189 while (!isdigit (*pch) && *pch)
5190 pch++;
5191
5192 while (isdigit (*pch))
5193 ulMajor = ulMajor * 10 + *pch++ - '0';
5194
5195 if (*pch == '.')
5196 {
5197 while (isdigit (*++pch))
5198 ulMinor = ulMinor * 10 + *pch - '0';
5199 }
5200 return ((ulMajor << 16) | ulMinor);
5201 }
5202 pchEnd--;
5203 }
5204 }
5205 pchEnd--;
5206 }
5207 return (0);
5208 }
5209
5210 ULONG _GetSystemBuildLevel(void) {
5211 /* The build level info is normally available in the end of the OS2KRNL file. However, this is not the case in some beta versions of OS/2.
5212 * We first try to find the info in the 256 last bytes of the file. If that fails, we load the entire file and search it completely.
5213 */
5214 ULONG ulBootDrive = 0;
5215 ULONG ulBuild = 0;
5216 if (DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive, sizeof (ulBootDrive)) == NO_ERROR)
5217 {
5218 char achFileName[11] = { (char)('A'+ulBootDrive-1),':','\\','O','S','2','K','R','N','L','\0' };
5219 HFILE hfile;
5220 ULONG ulResult;
5221 if (DosOpen (achFileName, &hfile, &ulResult, 0, 0, OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL) == NO_ERROR)
5222 {
5223 ULONG ulFileSize = 0;
5224 if (DosSetFilePtr (hfile, 0, FILE_END, &ulFileSize) == NO_ERROR)
5225 {
5226 const ULONG ulFirstTry = min (256, ulFileSize);
5227 if (DosSetFilePtr (hfile, -(LONG)ulFirstTry, FILE_END, &ulResult) == NO_ERROR)
5228 {
5229 char *pchBuffer = malloc(ulFirstTry);
5230 if (DosRead (hfile, pchBuffer, ulFirstTry, &ulResult) == NO_ERROR)
5231 {
5232 ulBuild = _ParseBuildLevel (pchBuffer, ulFirstTry);
5233 if (ulBuild == 0)
5234 {
5235 if (DosSetFilePtr (hfile, 0, FILE_BEGIN, &ulResult) == NO_ERROR)
5236 {
5237 free(pchBuffer);
5238 pchBuffer = malloc(ulFileSize);
5239
5240 if (DosRead (hfile, pchBuffer, ulFileSize, &ulResult) == NO_ERROR)
5241 ulBuild = _ParseBuildLevel (pchBuffer, ulFileSize);
5242 }
5243 }
5244 }
5245 free(pchBuffer);
5246 }
5247 }
5248 DosClose (hfile);
5249 }
5250 }
5251 return (ulBuild);
5252 }
5253
5254
5255 /*
5256 * Returns some information about the current operating environment.
5257 * Parameters:
5258 * env: Pointer to a DWEnv struct.
5259 */
5260 void dw_environment_query(DWEnv *env)
5261 {
5262 ULONG aulBuffer[4];
5263 ULONG Build;
5264
5265 if(!env)
5266 return;
5267
5268 /* Get the OS/2 version. */
5269
5270 DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_MS_COUNT,(void *)aulBuffer, 4*sizeof(ULONG));
5271
5272 /* The default is OS/2 2.0 */
5273 strcpy(env->osName,"OS/2");
5274 env->MajorVersion = 2;
5275 env->MinorVersion = 0;
5276
5277 Build = _GetSystemBuildLevel();
5278 env->MinorBuild = Build & 0xFFFF;
5279 env->MajorBuild = Build >> 16;
5280
5281 if (aulBuffer[0] == 20)
5282 {
5283 int i = (unsigned int)aulBuffer[1];
5284 if (i > 20)
5285 {
5286 strcpy(env->osName,"Warp");
5287 env->MajorVersion = (int)i/10;
5288 env->MinorVersion = i-(((int)i/10)*10);
5289 }
5290 else if (i == 10)
5291 env->MinorVersion = 1;
5292 }
5293 }
5294
5295 /*
5296 * Opens a file dialog and queries user selection.
5297 * Parameters:
5298 * title: Title bar text for dialog.
5299 * defpath: The default path of the open dialog.
5300 * ext: Default file extention.
5301 * flags: DW_FILE_OPEN or DW_FILE_SAVE.
5302 * Returns:
5303 * NULL on error. A malloced buffer containing
5304 * the file path on success.
5305 *
5306 */
5307 char *dw_file_browse(char *title, char *defpath, char *ext, int flags)
5308 {
5309 FILEDLG fild;
5310 HWND hwndFile;
5311 int len;
5312
5313 if(defpath)
5314 strcpy(fild.szFullFile, defpath);
5315 else
5316 strcpy(fild.szFullFile, "");
5317
5318 len = strlen(fild.szFullFile);
5319
5320 if(len)
5321 {
5322 if(fild.szFullFile[len-1] != '\\')
5323 strcat(fild.szFullFile, "\\");
5324 }
5325 strcat(fild.szFullFile, "*");
5326
5327 if(ext)
5328 {
5329 strcat(fild.szFullFile, ".");
5330 strcat(fild.szFullFile, ext);
5331 }
5332
5333 fild.cbSize = sizeof(FILEDLG);
5334 fild.fl = /*FDS_HELPBUTTON |*/ FDS_CENTER | FDS_OPEN_DIALOG;
5335 fild.pszTitle = title;
5336 fild.pszOKButton = ((flags & DW_FILE_SAVE) ? "Save" : "Open");
5337 fild.ulUser = 0L;
5338 fild.pfnDlgProc = (PFNWP)WinDefFileDlgProc;
5339 fild.lReturn = 0L;
5340 fild.lSRC = 0L;
5341 fild.hMod = 0;
5342 fild.x = 0;
5343 fild.y = 0;
5344 fild.pszIType = (PSZ)NULL;
5345 fild.papszITypeList = (PAPSZ)NULL;
5346 fild.pszIDrive = (PSZ)NULL;
5347 fild.papszIDriveList= (PAPSZ)NULL;
5348 fild.sEAType = (SHORT)0;
5349 fild.papszFQFilename= (PAPSZ)NULL;
5350 fild.ulFQFCount = 0L;
5351
5352 hwndFile = WinFileDlg(HWND_DESKTOP, HWND_DESKTOP, &fild);
5353 if(hwndFile)
5354 {
5355 switch(fild.lReturn)
5356 {
5357 case DID_OK:
5358 return strdup(fild.szFullFile);
5359 case DID_CANCEL:
5360 return NULL;
5361 }
5362 }
5363 return NULL;
5364 }
5365
5366 /*
5367 * Execute and external program in a seperate session.
5368 * Parameters:
5369 * program: Program name with optional path.
5370 * type: Either DW_EXEC_CON or DW_EXEC_GUI.
5371 * params: An array of pointers to string arguements.
5372 * Returns:
5373 * -1 on error.
5374 */
5375 int dw_exec(char *program, int type, char **params)
5376 {
5377 return spawnvp(P_NOWAIT, program, params);
5378 }
5379
5380 /*
5381 * Loads a web browser pointed at the given URL.
5382 * Parameters:
5383 * url: Uniform resource locator.
5384 */
5385 int dw_browse(char *url)
5386 {
5387 /* Is there a way to find the webbrowser in Unix? */
5388 char *execargs[3], browser[1024];
5389
5390 PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS",
5391 "DefaultBrowserExe", NULL, browser, 1024);
5392
5393 execargs[0] = browser;
5394 execargs[1] = url;
5395 execargs[2] = NULL;
5396
5397 return dw_exec(browser, DW_EXEC_GUI, execargs);
5398 }
5399
5400 /*
5401 * Returns a pointer to a static buffer which containes the
5402 * current user directory. Or the root directory (C:\ on
5403 * OS/2 and Windows).
5404 */
5405 char *dw_user_dir(void)
5406 {
5407 static char _user_dir[1024] = "";
5408
5409 if(!_user_dir[0])
5410 {
5411 char *home = getenv("HOME");
5412
5413 if(home)
5414 strcpy(_user_dir, home);
5415 else
5416 strcpy(_user_dir, "C:\\");
5417 }
5418 return _user_dir;
5419 }
5420
5421 /*
5422 * Call a function from the window (widget)'s context.
5423 * Parameters:
5424 * handle: Window handle of the widget.
5425 * function: Function pointer to be called.
5426 * data: Pointer to the data to be passed to the function.
5427 */
5428 void dw_window_function(HWND handle, void *function, void *data)
5429 {
5430 WinSendMsg(handle, WM_USER, (MPARAM)function, (MPARAM)data);
5431 }
5432
5433 #ifndef NO_SIGNALS
5434 /*
5435 * Add a callback to a window event.
5436 * Parameters:
5437 * window: Window handle of signal to be called back.
5438 * signame: A string pointer identifying which signal to be hooked.
5439 * sigfunc: The pointer to the function to be used as the callback.
5440 * data: User data to be passed to the handler function.
5441 */
5442 void dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
5443 {
5444 ULONG message = 0L;
5445
5446 if(window && signame && sigfunc)
5447 {
5448 if((message = _findsigmessage(signame)) != 0)
5449 _new_signal(message, window, sigfunc, data);
5450 }
5451 }
5452
5453 /*
5454 * Removes callbacks for a given window with given name.
5455 * Parameters:
5456 * window: Window handle of callback to be removed.
5457 */
5458 void dw_signal_disconnect_by_name(HWND window, char *signame)
5459 {
5460 SignalHandler *prev = NULL, *tmp = Root;
5461 ULONG message;
5462
5463 if(!window || !signame || (message = _findsigmessage(signame)) == 0)
5464 return;
5465
5466 while(tmp)
5467 {
5468 if(tmp->window == window && tmp->message == message)
5469 {
5470 if(prev)
5471 {
5472 prev->next = tmp->next;
5473 free(tmp);
5474 tmp = prev->next;
5475 }
5476 else
5477 {
5478 Root = tmp->next;
5479 free(tmp);
5480 tmp = Root;
5481 }
5482 }
5483 else
5484 {
5485 prev = tmp;
5486 tmp = tmp->next;
5487 }
5488 }
5489 }
5490
5491 /*
5492 * Removes all callbacks for a given window.
5493 * Parameters:
5494 * window: Window handle of callback to be removed.
5495 */
5496 void dw_signal_disconnect_by_window(HWND window)
5497 {
5498 SignalHandler *prev = NULL, *tmp = Root;
5499
5500 while(tmp)
5501 {
5502 if(tmp->window == window)
5503 {
5504 if(prev)
5505 {
5506 prev->next = tmp->next;
5507 free(tmp);
5508 tmp = prev->next;
5509 }
5510 else
5511 {
5512 Root = tmp->next;
5513 free(tmp);
5514 tmp = Root;
5515 }
5516 }
5517 else
5518 {
5519 prev = tmp;
5520 tmp = tmp->next;
5521 }
5522 }
5523 }
5524
5525 /*
5526 * Removes all callbacks for a given window with specified data.
5527 * Parameters:
5528 * window: Window handle of callback to be removed.
5529 * data: Pointer to the data to be compared against.
5530 */
5531 void dw_signal_disconnect_by_data(HWND window, void *data)
5532 {
5533 SignalHandler *prev = NULL, *tmp = Root;
5534
5535 while(tmp)
5536 {
5537 if(tmp->window == window && tmp->data == data)
5538 {
5539 if(prev)
5540 {
5541 prev->next = tmp->next;
5542 free(tmp);
5543 tmp = prev->next;
5544 }
5545 else
5546 {
5547 Root = tmp->next;
5548 free(tmp);
5549 tmp = Root;
5550 }
5551 }
5552 else
5553 {
5554 prev = tmp;
5555 tmp = tmp->next;
5556 }
5557 }
5558 }
5559 #endif
5560
5561 #ifdef TEST
5562 HWND mainwindow,
5563 listbox,
5564 okbutton,
5565 cancelbutton,
5566 lbbox,
5567 stext,
5568 buttonbox,
5569 testwindow,
5570 testbox,
5571 testok,
5572 testcancel,
5573 testbox2,
5574 testok2,
5575 testcancel2,
5576 notebook;
5577 int count = 2;
5578
5579 #ifdef USE_FILTER
5580 /* Do any handling you need in the filter function */
5581 LONG testfilter(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
5582 {
5583 switch(msg)
5584 {
5585 case WM_COMMAND:
5586 switch (COMMANDMSG(&msg)->cmd)
5587 {
5588 case 1001L:
5589 case 1002L:
5590 dw_window_destroy(mainwindow);;
5591 count--;
5592 break;
5593 case 1003L:
5594 case 1004L:
5595 dw_window_destroy(testwindow);;
5596 count--;
5597 break;
5598 }
5599 if(!count)
5600 exit(0);
5601 break;
5602 }
5603 /* Return -1 to allow the default handlers to return. */
5604 return TRUE;
5605 }
5606 #else
5607 int test_callback(HWND window, void *data)
5608 {
5609 dw_window_destroy((HWND)data);
5610 /* Return -1 to allow the default handlers to return. */
5611 count--;
5612 if(!count)
5613 exit(0);
5614 return -1;
5615 }
5616 #endif
5617
5618 /*
5619 * Let's demonstrate the functionality of this library. :)
5620 */
5621 int main(void)
5622 {
5623 ULONG flStyle = DW_FCF_SYSMENU | DW_FCF_TITLEBAR |
5624 DW_FCF_SHELLPOSITION | DW_FCF_TASKLIST | DW_FCF_DLGBORDER;
5625 int pageid;
5626
5627 dw_init(TRUE);
5628
5629 /* Try a little server dialog. :) */
5630 mainwindow = dw_window_new(HWND_DESKTOP, "Server", flStyle | DW_FCF_SIZEBORDER | DW_FCF_MINMAX);
5631
5632 lbbox = dw_box_new(BOXVERT, 10);
5633
5634 dw_box_pack_start(mainwindow, lbbox, 0, 0, TRUE, TRUE, 0);
5635
5636 stext = dw_text_new("Choose a server:", 0);
5637
5638 dw_window_set_style(stext, DW_DT_VCENTER, DW_DT_VCENTER);
5639
5640 dw_box_pack_start(lbbox, stext, 130, 15, FALSE, FALSE, 10);
5641
5642 listbox = dw_listbox_new(100L, FALSE);
5643
5644 dw_box_pack_start(lbbox, listbox, 130, 200, TRUE, TRUE, 10);
5645
5646 buttonbox = dw_box_new(BOXHORZ, 0);
5647
5648 dw_box_pack_start(lbbox, buttonbox, 0, 0, TRUE, TRUE, 0);
5649
5650 okbutton = dw_button_new("Ok", 1001L);
5651
5652 dw_box_pack_start(buttonbox, okbutton, 50, 30, TRUE, TRUE, 5);
5653
5654 cancelbutton = dw_button_new("Cancel", 1002L);
5655
5656 dw_box_pack_start(buttonbox, cancelbutton, 50, 30, TRUE, TRUE, 5);
5657
5658 /* Set some nice fonts and colors */
5659 dw_window_set_color(lbbox, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
5660 dw_window_set_color(buttonbox, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
5661 dw_window_set_font(stext, "9.WarpSans");
5662 dw_window_set_color(stext, DW_CLR_BLACK, DW_CLR_PALEGRAY);
5663 dw_window_set_font(listbox, "9.WarpSans");
5664 dw_window_set_font(okbutton, "9.WarpSans");
5665 dw_window_set_font(cancelbutton, "9.WarpSans");
5666
5667 dw_window_show(mainwindow);
5668
5669 dw_window_set_usize(mainwindow, 170, 340);
5670
5671 /* Another small example */
5672 flStyle |= FCF_MINMAX | FCF_SIZEBORDER;
5673
5674 testwindow = dw_window_new(HWND_DESKTOP, "Wow a test dialog! :) yay!", flStyle);
5675
5676 testbox = dw_box_new(BOXVERT, 0);
5677
5678 dw_box_pack_start(testwindow, testbox, 0, 0, TRUE, TRUE, 0);
5679
5680 notebook = dw_notebook_new(1010L, TRUE);
5681
5682 dw_box_pack_start(testbox, notebook, 100, 100, TRUE, TRUE, 0);
5683
5684 testbox = dw_box_new(BOXVERT, 10);
5685
5686 pageid = dw_notebook_page_new(notebook, 0L, FALSE);
5687
5688 dw_notebook_page_set_text(notebook, pageid, "Test page");
5689 dw_notebook_page_set_status_text(notebook, pageid, "Test page");
5690
5691 dw_notebook_pack(notebook, pageid, testbox);
5692
5693 testok = dw_button_new("Ok", 1003L);
5694
5695 dw_box_pack_start(testbox, testok, 60, 40, TRUE, TRUE, 10);
5696
5697 testcancel = dw_button_new("Cancel", 1004L);
5698
5699 dw_box_pack_start(testbox, testcancel, 60, 40, TRUE, TRUE, 10);
5700
5701 testbox2 = dw_box_new(BOXHORZ, 0);
5702
5703 dw_box_pack_start(testbox, testbox2, 0, 0, TRUE, TRUE, 0);
5704
5705 testok2 = dw_button_new("Ok", 1003L);
5706
5707 dw_box_pack_start(testbox2, testok2, 60, 40, TRUE, TRUE, 10);
5708
5709 dw_box_pack_splitbar_start(testbox2);
5710
5711 testcancel2 = dw_button_new("Cancel", 1004L);
5712
5713 dw_box_pack_start(testbox2, testcancel2, 60, 40, TRUE, TRUE, 10);
5714
5715 /* Set some nice fonts and colors */
5716 dw_window_set_color(testbox, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
5717 dw_window_set_color(testbox2, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
5718 dw_window_set_font(testok, "9.WarpSans");
5719 dw_window_set_font(testcancel, "9.WarpSans");
5720 dw_window_set_font(testok2, "9.WarpSans");
5721 dw_window_set_font(testcancel2, "9.WarpSans");
5722
5723 dw_window_show(testwindow);
5724
5725 #ifdef USE_FILTER
5726 dw_main(0L, (void *)testfilter);
5727 #else
5728 /* Setup the function callbacks */
5729 dw_signal_connect(okbutton, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)mainwindow);
5730 dw_signal_connect(cancelbutton, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)mainwindow);
5731 dw_signal_connect(testok, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)testwindow);
5732 dw_signal_connect(testcancel, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)testwindow);
5733 dw_signal_connect(testok2, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)testwindow);
5734 dw_signal_connect(testcancel2, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)testwindow);
5735 dw_signal_connect(mainwindow, "delete_event", DW_SIGNAL_FUNC(test_callback), (void *)mainwindow);
5736 dw_signal_connect(testwindow, "delete_event", DW_SIGNAL_FUNC(test_callback), (void *)testwindow);
5737
5738 dw_main(0L, NULL);
5739 #endif
5740
5741 return 0;
5742 }
5743 #endif