comparison os2/dw.c @ 236:5592cdeb29cf

Make sure all platforms have the same typedefs.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 14 Feb 2003 07:57:30 +0000
parents 69f2a59ec7d0
children 00d2b1bcf036
comparison
equal deleted inserted replaced
235:69f2a59ec7d0 236:5592cdeb29cf
1 (binary file text/plain, hash: 98db7a2deb7a050b8ef7c392b200688b3ee06687) 1 /*
2 * Dynamic Windows:
3 * A GTK like implementation of the PM GUI
4 *
5 * (C) 2000-2002 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 <time.h>
25 #ifndef __EMX__
26 #include <direct.h>
27 #endif
28 #include "dw.h"
29
30 #define QWP_USER 0
31
32 MRESULT EXPENTRY _run_event(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
33 void _do_resize(Box *thisbox, int x, int y);
34 void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y);
35
36 char ClassName[] = "dynamicwindows";
37 char SplitbarClassName[] = "dwsplitbar";
38 char DefaultFont[] = "9.WarpSans";
39
40 HAB dwhab = 0;
41 HMQ dwhmq = 0;
42 DWTID _dwtid = 0;
43 LONG _foreground = 0xAAAAAA, _background = 0;
44
45 HWND hwndBubble = NULLHANDLE, hwndBubbleLast = NULLHANDLE, hwndEmph = NULLHANDLE;
46 PRECORDCORE pCore = NULL, pCoreEmph = NULL;
47 ULONG aulBuffer[4];
48 HWND lasthcnr = 0, lastitem = 0, popup = 0, desktop;
49
50 unsigned long _colors[] = {
51 CLR_BLACK,
52 CLR_DARKRED,
53 CLR_DARKGREEN,
54 CLR_BROWN,
55 CLR_DARKBLUE,
56 CLR_DARKPINK,
57 CLR_DARKCYAN,
58 CLR_PALEGRAY,
59 CLR_DARKGRAY,
60 CLR_RED,
61 CLR_GREEN,
62 CLR_YELLOW,
63 CLR_BLUE,
64 CLR_PINK,
65 CLR_CYAN,
66 CLR_WHITE
67 };
68
69 #define IS_WARP4() (aulBuffer[0] == 20 && aulBuffer[1] >= 40)
70
71 #ifndef min
72 #define min(a, b) (((a < b) ? a : b))
73 #endif
74
75 typedef struct _sighandler
76 {
77 struct _sighandler *next;
78 ULONG message;
79 HWND window;
80 int id;
81 void *signalfunction;
82 void *data;
83
84 } SignalHandler;
85
86 SignalHandler *Root = NULL;
87
88 typedef struct
89 {
90 ULONG message;
91 char name[30];
92
93 } SignalList;
94
95 /* List of signals and their equivilent OS/2 message */
96 #define SIGNALMAX 15
97
98 SignalList SignalTranslate[SIGNALMAX] = {
99 { WM_SIZE, "configure_event" },
100 { WM_CHAR, "key_press_event" },
101 { WM_BUTTON1DOWN, "button_press_event" },
102 { WM_BUTTON1UP, "button_release_event"},
103 { WM_MOUSEMOVE, "motion_notify_event" },
104 { WM_CLOSE, "delete_event" },
105 { WM_PAINT, "expose_event" },
106 { WM_COMMAND, "clicked" },
107 { CN_ENTER, "container-select" },
108 { CN_CONTEXTMENU, "container-context" },
109 { LN_SELECT, "item-select" },
110 { CN_EMPHASIS, "tree-select" },
111 { WM_SETFOCUS, "set-focus" },
112 { WM_USER+1, "lose-focus" },
113 { SLN_SLIDERTRACK, "value_changed" }
114 };
115
116 /* This function adds a signal handler callback into the linked list.
117 */
118 void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data)
119 {
120 SignalHandler *new = malloc(sizeof(SignalHandler));
121
122 if(message == WM_COMMAND)
123 dw_signal_disconnect_by_window(window);
124
125 new->message = message;
126 new->window = window;
127 new->id = id;
128 new->signalfunction = signalfunction;
129 new->data = data;
130 new->next = NULL;
131
132 if (!Root)
133 Root = new;
134 else
135 {
136 SignalHandler *prev = NULL, *tmp = Root;
137 while(tmp)
138 {
139 if(tmp->message == message &&
140 tmp->window == window &&
141 tmp->signalfunction == signalfunction)
142 {
143 tmp->data = data;
144 free(new);
145 return;
146 }
147 prev = tmp;
148 tmp = tmp->next;
149 }
150 if(prev)
151 prev->next = new;
152 else
153 Root = new;
154 }
155 }
156
157 /* Finds the message number for a given signal name */
158 ULONG _findsigmessage(char *signame)
159 {
160 int z;
161
162 for(z=0;z<SIGNALMAX;z++)
163 {
164 if(stricmp(signame, SignalTranslate[z].name) == 0)
165 return SignalTranslate[z].message;
166 }
167 return 0L;
168 }
169
170 typedef struct _CNRITEM
171 {
172 MINIRECORDCORE rc;
173 HPOINTER hptrIcon;
174 PVOID user;
175
176 } CNRITEM, *PCNRITEM;
177
178
179 int _null_key(HWND window, int key, void *data)
180 {
181 return TRUE;
182 }
183
184 /* Find the desktop window handle */
185 HWND _toplevel_window(HWND handle)
186 {
187 HWND box, lastbox = WinQueryWindow(handle, QW_PARENT);
188
189 /* Find the toplevel window */
190 while((box = WinQueryWindow(lastbox, QW_PARENT)) != desktop && box > 0)
191 {
192 lastbox = box;
193 }
194 if(box > 0)
195 return lastbox;
196 return handle;
197 }
198
199 /* Return the entryfield child of a window */
200 HWND _find_entryfield(HWND handle)
201 {
202 HENUM henum;
203 HWND child, entry = 0;
204
205 henum = WinBeginEnumWindows(handle);
206 while((child = WinGetNextWindow(henum)) != NULLHANDLE)
207 {
208 char tmpbuf[100];
209
210 WinQueryClassName(child, 99, tmpbuf);
211
212 if(strncmp(tmpbuf, "#6", 3)==0) /* Entryfield */
213 {
214 entry = child;
215 break;
216 }
217 }
218 WinEndEnumWindows(henum);
219 return entry;
220 }
221
222 /* This function changes the owner of buttons in to the
223 * dynamicwindows handle to fix a problem in notebooks.
224 */
225 void _fix_button_owner(HWND handle, HWND dw)
226 {
227 HENUM henum;
228 HWND child;
229
230 henum = WinBeginEnumWindows(handle);
231 while((child = WinGetNextWindow(henum)) != NULLHANDLE)
232 {
233 char tmpbuf[100];
234
235 WinQueryClassName(child, 99, tmpbuf);
236
237 if(strncmp(tmpbuf, "#3", 3)==0 && dw) /* Button */
238 WinSetOwner(child, dw);
239 else if(strncmp(tmpbuf, "dynamicwindows", 14) == 0)
240 dw = child;
241
242 _fix_button_owner(child, dw);
243 }
244 WinEndEnumWindows(henum);
245 return;
246 }
247
248 /* This function removes and handlers on windows and frees
249 * the user memory allocated to it.
250 */
251 void _free_window_memory(HWND handle)
252 {
253 HENUM henum;
254 HWND child;
255 void *ptr = (void *)WinQueryWindowPtr(handle, QWP_USER);
256
257 dw_signal_disconnect_by_window(handle);
258
259 if((child = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE)
260 {
261 Box *box = (Box *)WinQueryWindowPtr(child, QWP_USER);
262
263 if(box)
264 {
265 if(box->count && box->items)
266 free(box->items);
267
268 WinSetWindowPtr(child, QWP_USER, 0);
269 free(box);
270 }
271 }
272
273 if(ptr)
274 {
275 WindowData *wd = (WindowData *)ptr;
276 char tmpbuf[100];
277 HBITMAP hbm = (HBITMAP)dw_window_get_data(handle, "_dw_bitmap");
278
279 /* If this window has an associate bitmap destroy it. */
280 if(hbm)
281 GpiDeleteBitmap(hbm);
282
283 WinQueryClassName(handle, 99, tmpbuf);
284
285 if(strncmp(tmpbuf, "#1", 3)==0)
286 {
287 Box *box = (Box *)ptr;
288
289 if(box->count && box->items)
290 free(box->items);
291 }
292 else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
293 {
294 void *data = dw_window_get_data(handle, "_dw_percent");
295
296 if(data)
297 free(data);
298 }
299
300 if(wd->oldproc)
301 WinSubclassWindow(handle, wd->oldproc);
302
303 dw_window_set_data(handle, NULL, NULL);
304 WinSetWindowPtr(handle, QWP_USER, 0);
305 free(ptr);
306 }
307
308 henum = WinBeginEnumWindows(handle);
309 while((child = WinGetNextWindow(henum)) != NULLHANDLE)
310 _free_window_memory(child);
311
312 WinEndEnumWindows(henum);
313 return;
314 }
315
316 /* This function returns 1 if the window (widget) handle
317 * passed to it is a valid window that can gain input focus.
318 */
319 int _validate_focus(HWND handle)
320 {
321 char tmpbuf[100];
322
323 if(!handle)
324 return 0;
325
326 if(!WinIsWindowEnabled(handle) || dw_window_get_data(handle, "_dw_disabled"))
327 return 0;
328
329 WinQueryClassName(handle, 99, tmpbuf);
330
331 /* These are the window classes which can
332 * obtain input focus.
333 */
334 if(strncmp(tmpbuf, "#2", 3)==0 || /* Combobox */
335 strncmp(tmpbuf, "#3", 3)==0 || /* Button */
336 strncmp(tmpbuf, "#6", 3)==0 || /* Entryfield */
337 strncmp(tmpbuf, "#7", 3)==0 || /* List box */
338 strncmp(tmpbuf, "#10", 4)==0 || /* MLE */
339 strncmp(tmpbuf, "#32", 4)==0 || /* Spinbutton */
340 strncmp(tmpbuf, "#37", 4)==0 || /* Container */
341 strncmp(tmpbuf, "#38", 4)== 0) /* Slider */
342 return 1;
343 return 0;
344 }
345
346 int _focus_check_box(Box *box, HWND handle, int start, HWND defaultitem)
347 {
348 int z;
349 static HWND lasthwnd, firsthwnd;
350 static int finish_searching;
351
352 /* Start is 2 when we have cycled completely and
353 * need to set the focus to the last widget we found
354 * that was valid.
355 */
356 if(start == 2)
357 {
358 if(lasthwnd)
359 WinSetFocus(HWND_DESKTOP, lasthwnd);
360 return 0;
361 }
362
363 /* Start is 1 when we are entering the function
364 * for the first time, it is zero when entering
365 * the function recursively.
366 */
367 if(start == 1)
368 {
369 lasthwnd = handle;
370 finish_searching = 0;
371 firsthwnd = 0;
372 }
373
374 /* Vertical boxes are inverted on OS/2 */
375 if(box->type == BOXVERT)
376 {
377 for(z=0;z<box->count;z++)
378 {
379 if(box->items[z].type == TYPEBOX)
380 {
381 Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER);
382
383 if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0, defaultitem))
384 return 1;
385 }
386 else
387 {
388 if(box->items[z].hwnd == handle)
389 {
390 if(lasthwnd == handle && firsthwnd)
391 WinSetFocus(HWND_DESKTOP, firsthwnd);
392 else if(lasthwnd == handle && !firsthwnd)
393 finish_searching = 1;
394 else
395 WinSetFocus(HWND_DESKTOP, lasthwnd);
396
397 /* If we aren't looking for the last handle,
398 * return immediately.
399 */
400 if(!finish_searching)
401 return 1;
402 }
403 if(_validate_focus(box->items[z].hwnd))
404 {
405 /* Start is 3 when we are looking for the
406 * first valid item in the layout.
407 */
408 if(start == 3)
409 {
410 if(!defaultitem || (defaultitem && defaultitem == box->items[z].hwnd))
411 {
412 WinSetFocus(HWND_DESKTOP, box->items[z].hwnd);
413 return 1;
414 }
415 }
416
417 if(!firsthwnd)
418 firsthwnd = box->items[z].hwnd;
419
420 lasthwnd = box->items[z].hwnd;
421 }
422 else
423 {
424 char tmpbuf[100] = "";
425
426 WinQueryClassName(box->items[z].hwnd, 99, tmpbuf);
427 if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
428 {
429 /* Then try the bottom or right box */
430 HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright");
431
432 if(mybox)
433 {
434 Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER);
435
436 if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
437 return 1;
438 }
439
440 /* Try the top or left box */
441 mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft");
442
443 if(mybox)
444 {
445 Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER);
446
447 if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
448 return 1;
449 }
450 }
451 else if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */
452 {
453 Box *notebox;
454 HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND,
455 (MPARAM)dw_notebook_page_query(box->items[z].hwnd), 0);
456
457 if(page)
458 {
459 notebox = (Box *)WinQueryWindowPtr(page, QWP_USER);
460
461 if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, defaultitem))
462 return 1;
463 }
464 }
465 }
466 }
467 }
468 }
469 else
470 {
471 for(z=box->count-1;z>-1;z--)
472 {
473 if(box->items[z].type == TYPEBOX)
474 {
475 Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER);
476
477 if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0, defaultitem))
478 return 1;
479 }
480 else
481 {
482 if(box->items[z].hwnd == handle)
483 {
484 if(lasthwnd == handle && firsthwnd)
485 WinSetFocus(HWND_DESKTOP, firsthwnd);
486 else if(lasthwnd == handle && !firsthwnd)
487 finish_searching = 1;
488 else
489 WinSetFocus(HWND_DESKTOP, lasthwnd);
490
491 /* If we aren't looking for the last handle,
492 * return immediately.
493 */
494 if(!finish_searching)
495 return 1;
496 }
497 if(_validate_focus(box->items[z].hwnd))
498 {
499 /* Start is 3 when we are looking for the
500 * first valid item in the layout.
501 */
502 if(start == 3)
503 {
504 if(!defaultitem || (defaultitem && defaultitem == box->items[z].hwnd))
505 {
506 WinSetFocus(HWND_DESKTOP, box->items[z].hwnd);
507 return 1;
508 }
509 }
510
511 if(!firsthwnd)
512 firsthwnd = box->items[z].hwnd;
513
514 lasthwnd = box->items[z].hwnd;
515 }
516 else
517 {
518 char tmpbuf[100] = "";
519
520 WinQueryClassName(box->items[z].hwnd, 99, tmpbuf);
521 if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */
522 {
523 Box *notebox;
524 HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND,
525 (MPARAM)dw_notebook_page_query(box->items[z].hwnd), 0);
526
527 if(page)
528 {
529 notebox = (Box *)WinQueryWindowPtr(page, QWP_USER);
530
531 if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, defaultitem))
532 return 1;
533 }
534 }
535 }
536 }
537 }
538 }
539 return 0;
540 }
541
542 int _focus_check_box_back(Box *box, HWND handle, int start, HWND defaultitem)
543 {
544 int z;
545 static HWND lasthwnd, firsthwnd;
546 static int finish_searching;
547
548 /* Start is 2 when we have cycled completely and
549 * need to set the focus to the last widget we found
550 * that was valid.
551 */
552 if(start == 2)
553 {
554 if(lasthwnd)
555 WinSetFocus(HWND_DESKTOP, lasthwnd);
556 return 0;
557 }
558
559 /* Start is 1 when we are entering the function
560 * for the first time, it is zero when entering
561 * the function recursively.
562 */
563 if(start == 1)
564 {
565 lasthwnd = handle;
566 finish_searching = 0;
567 firsthwnd = 0;
568 }
569
570 /* Vertical boxes are inverted on OS/2 */
571 if(box->type == BOXVERT)
572 {
573 for(z=box->count-1;z>-1;z--)
574 {
575 if(box->items[z].type == TYPEBOX)
576 {
577 Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER);
578
579 if(thisbox && _focus_check_box_back(thisbox, handle, start == 3 ? 3 : 0, defaultitem))
580 return 1;
581 }
582 else
583 {
584 if(box->items[z].hwnd == handle)
585 {
586 if(lasthwnd == handle && firsthwnd)
587 WinSetFocus(HWND_DESKTOP, firsthwnd);
588 else if(lasthwnd == handle && !firsthwnd)
589 finish_searching = 1;
590 else
591 WinSetFocus(HWND_DESKTOP, lasthwnd);
592
593 /* If we aren't looking for the last handle,
594 * return immediately.
595 */
596 if(!finish_searching)
597 return 1;
598 }
599 if(_validate_focus(box->items[z].hwnd))
600 {
601 /* Start is 3 when we are looking for the
602 * first valid item in the layout.
603 */
604 if(start == 3)
605 {
606 if(!defaultitem || (defaultitem && defaultitem == box->items[z].hwnd))
607 {
608 WinSetFocus(HWND_DESKTOP, box->items[z].hwnd);
609 return 1;
610 }
611 }
612
613 if(!firsthwnd)
614 firsthwnd = box->items[z].hwnd;
615
616 lasthwnd = box->items[z].hwnd;
617 }
618 else
619 {
620 char tmpbuf[100] = "";
621
622 WinQueryClassName(box->items[z].hwnd, 99, tmpbuf);
623 if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */
624 {
625 Box *notebox;
626 HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND,
627 (MPARAM)dw_notebook_page_query(box->items[z].hwnd), 0);
628
629 if(page)
630 {
631 notebox = (Box *)WinQueryWindowPtr(page, QWP_USER);
632
633 if(notebox && _focus_check_box_back(notebox, handle, start == 3 ? 3 : 0, defaultitem))
634 return 1;
635 }
636 }
637 }
638 }
639 }
640 }
641 else
642 {
643 for(z=0;z<box->count;z++)
644 {
645 if(box->items[z].type == TYPEBOX)
646 {
647 Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER);
648
649 if(thisbox && _focus_check_box_back(thisbox, handle, start == 3 ? 3 : 0, defaultitem))
650 return 1;
651 }
652 else
653 {
654 if(box->items[z].hwnd == handle)
655 {
656 if(lasthwnd == handle && firsthwnd)
657 WinSetFocus(HWND_DESKTOP, firsthwnd);
658 else if(lasthwnd == handle && !firsthwnd)
659 finish_searching = 1;
660 else
661 WinSetFocus(HWND_DESKTOP, lasthwnd);
662
663 /* If we aren't looking for the last handle,
664 * return immediately.
665 */
666 if(!finish_searching)
667 return 1;
668 }
669 if(_validate_focus(box->items[z].hwnd))
670 {
671 /* Start is 3 when we are looking for the
672 * first valid item in the layout.
673 */
674 if(start == 3)
675 {
676 if(!defaultitem || (defaultitem && defaultitem == box->items[z].hwnd))
677 {
678 WinSetFocus(HWND_DESKTOP, box->items[z].hwnd);
679 return 1;
680 }
681 }
682
683 if(!firsthwnd)
684 firsthwnd = box->items[z].hwnd;
685
686 lasthwnd = box->items[z].hwnd;
687 }
688 else
689 {
690 char tmpbuf[100] = "";
691
692 WinQueryClassName(box->items[z].hwnd, 99, tmpbuf);
693 if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */
694 {
695 Box *notebox;
696 HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND,
697 (MPARAM)dw_notebook_page_query(box->items[z].hwnd), 0);
698
699 if(page)
700 {
701 notebox = (Box *)WinQueryWindowPtr(page, QWP_USER);
702
703 if(notebox && _focus_check_box_back(notebox, handle, start == 3 ? 3 : 0, defaultitem))
704 return 1;
705 }
706 }
707 }
708 }
709 }
710 }
711 return 0;
712 }
713
714 /* This function finds the first widget in the
715 * layout and moves the current focus to it.
716 */
717 int _initial_focus(HWND handle)
718 {
719 Box *thisbox = NULL;
720 HWND box;
721
722 box = WinWindowFromID(handle, FID_CLIENT);
723 if(box)
724 thisbox = WinQueryWindowPtr(box, QWP_USER);
725 else
726 return 1;
727
728 if(thisbox)
729 _focus_check_box(thisbox, handle, 3, thisbox->defaultitem);
730 return 0;
731 }
732
733 /* This function finds the current widget in the
734 * layout and moves the current focus to the next item.
735 */
736 void _shift_focus(HWND handle)
737 {
738 Box *thisbox;
739 HWND box, lastbox = _toplevel_window(handle);
740
741 box = WinWindowFromID(lastbox, FID_CLIENT);
742 if(box)
743 thisbox = WinQueryWindowPtr(box, QWP_USER);
744 else
745 thisbox = WinQueryWindowPtr(lastbox, QWP_USER);
746
747 if(thisbox)
748 {
749 if(_focus_check_box(thisbox, handle, 1, 0) == 0)
750 _focus_check_box(thisbox, handle, 2, 0);
751 }
752 }
753
754 /* This function finds the current widget in the
755 * layout and moves the current focus to the next item.
756 */
757 void _shift_focus_back(HWND handle)
758 {
759 Box *thisbox;
760 HWND box, lastbox = _toplevel_window(handle);
761
762 box = WinWindowFromID(lastbox, FID_CLIENT);
763 if(box)
764 thisbox = WinQueryWindowPtr(box, QWP_USER);
765 else
766 thisbox = WinQueryWindowPtr(lastbox, QWP_USER);
767
768 if(thisbox)
769 {
770 if(_focus_check_box_back(thisbox, handle, 1, 0) == 0)
771 _focus_check_box_back(thisbox, handle, 2, 0);
772 }
773 }
774
775 /* This function will recursively search a box and add up the total height of it */
776 void _count_size(HWND box, int type, int *xsize, int *xorigsize)
777 {
778 int size = 0, origsize = 0, z;
779 Box *tmp = WinQueryWindowPtr(box, QWP_USER);
780
781 if(!tmp)
782 {
783 *xsize = *xorigsize = 0;
784 return;
785 }
786
787 if(type == tmp->type)
788 {
789 /* If the box is going in the direction we want, then we
790 * return the entire sum of the items.
791 */
792 for(z=0;z<tmp->count;z++)
793 {
794 if(tmp->items[z].type == TYPEBOX)
795 {
796 int s, os;
797
798 _count_size(tmp->items[z].hwnd, type, &s, &os);
799 size += s;
800 origsize += os;
801 }
802 else
803 {
804 size += (type == BOXHORZ ? tmp->items[z].width : tmp->items[z].height);
805 origsize += (type == BOXHORZ ? tmp->items[z].origwidth : tmp->items[z].origheight);
806 }
807 }
808 }
809 else
810 {
811 /* If the box is not going in the direction we want, then we only
812 * want to return the maximum value.
813 */
814 int tmpsize = 0, tmporigsize = 0;
815
816 for(z=0;z<tmp->count;z++)
817 {
818 if(tmp->items[z].type == TYPEBOX)
819 _count_size(tmp->items[z].hwnd, type, &tmpsize, &tmporigsize);
820 else
821 {
822 tmpsize = (type == BOXHORZ ? tmp->items[z].width : tmp->items[z].height);
823 tmporigsize = (type == BOXHORZ ? tmp->items[z].origwidth : tmp->items[z].origheight);
824 }
825
826 if(tmpsize > size)
827 size = tmpsize;
828 }
829 }
830
831 *xsize = size;
832 *xorigsize = origsize;
833 }
834
835
836 /* Function: TrackRectangle
837 * Abstract: Tracks given rectangle.
838 *
839 * If rclBounds is NULL, then track rectangle on entire desktop.
840 * rclTrack is in window coorditates and will be mapped to
841 * desktop.
842 */
843
844 BOOL _TrackRectangle(HWND hwndBase, RECTL* rclTrack, RECTL* rclBounds)
845 {
846 TRACKINFO track;
847 APIRET rc;
848
849 track.cxBorder = 1;
850 track.cyBorder = 1;
851 track.cxGrid = 1;
852 track.cyGrid = 1;
853 track.cxKeyboard = 8;
854 track.cyKeyboard = 8;
855
856 if(!rclTrack)
857 return FALSE;
858
859 if(rclBounds)
860 {
861 track.rclBoundary = *rclBounds;
862 }
863 else
864 {
865 track.rclBoundary.yTop =
866 track.rclBoundary.xRight = 3000;
867 track.rclBoundary.yBottom =
868 track.rclBoundary.xLeft = -3000;
869 }
870
871 track.rclTrack = *rclTrack;
872
873 WinMapWindowPoints(hwndBase,
874 HWND_DESKTOP,
875 (PPOINTL)&track.rclTrack,
876 2);
877
878 track.ptlMinTrackSize.x = track.rclTrack.xRight
879 - track.rclTrack.xLeft;
880 track.ptlMinTrackSize.y = track.rclTrack.yTop
881 - track.rclTrack.yBottom;
882 track.ptlMaxTrackSize.x = track.rclTrack.xRight
883 - track.rclTrack.xLeft;
884 track.ptlMaxTrackSize.y = track.rclTrack.yTop
885 - track.rclTrack.yBottom;
886
887 track.fs = TF_MOVE | TF_ALLINBOUNDARY;
888
889 rc = WinTrackRect(HWND_DESKTOP, 0, &track);
890
891 if(rc)
892 *rclTrack = track.rclTrack;
893
894 return rc;
895 }
896
897 void _check_resize_notebook(HWND hwnd)
898 {
899 char tmpbuf[100];
900
901 WinQueryClassName(hwnd, 99, tmpbuf);
902
903 /* If we have a notebook we resize the page again. */
904 if(strncmp(tmpbuf, "#40", 4)==0)
905 {
906 unsigned long x, y, width, height;
907 ULONG page = (ULONG)WinSendMsg(hwnd, BKM_QUERYPAGEID, 0, MPFROM2SHORT(BKA_FIRST, BKA_MAJOR));
908
909 while(page)
910 {
911 HWND pagehwnd = (HWND)WinSendMsg(hwnd, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(page), 0);
912 RECTL rc;
913
914 Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER);
915 if(pagebox)
916 {
917 dw_window_get_pos_size(hwnd, &x, &y, &width, &height);
918
919 rc.xLeft = x;
920 rc.yBottom = y;
921 rc.xRight = x + width;
922 rc.yTop = y + height;
923
924 WinSendMsg(hwnd, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE);
925
926 _do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom);
927 }
928 page = (ULONG)WinSendMsg(hwnd, BKM_QUERYPAGEID, (MPARAM)page, MPFROM2SHORT(BKA_NEXT, BKA_MAJOR));
929 }
930
931 }
932 }
933
934 /* Return the OS/2 color from the DW color */
935 unsigned long _internal_color(unsigned long color)
936 {
937 if(color < 16)
938 return _colors[color];
939 return color;
940 }
941
942 /* This function calculates how much space the widgets and boxes require
943 * and does expansion as necessary.
944 */
945 int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy,
946 int pass, int *usedpadx, int *usedpady)
947 {
948 int z, currentx = 0, currenty = 0;
949 int uymax = 0, uxmax = 0;
950 int upymax = 0, upxmax = 0;
951 /* Used for the SIZEEXPAND */
952 int nux = *usedx, nuy = *usedy;
953 int nupx = *usedpadx, nupy = *usedpady;
954
955 (*usedx) += (thisbox->pad * 2);
956 (*usedy) += (thisbox->pad * 2);
957
958 for(z=0;z<thisbox->count;z++)
959 {
960 if(thisbox->items[z].type == TYPEBOX)
961 {
962 int initialx, initialy;
963 Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
964
965 initialx = x - (*usedx);
966 initialy = y - (*usedy);
967
968 if(tmp)
969 {
970 int newx, newy;
971 int nux = *usedx, nuy = *usedy;
972 int upx = *usedpadx + (tmp->pad*2), upy = *usedpady + (tmp->pad*2);
973
974 /* On the second pass we know how big the box needs to be and how
975 * much space we have, so we can calculate a ratio for the new box.
976 */
977 if(pass == 2)
978 {
979 int deep = *depth + 1;
980
981 _resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy);
982
983 tmp->upx = upx - *usedpadx;
984 tmp->upy = upy - *usedpady;
985
986 newx = x - nux;
987 newy = y - nuy;
988
989 tmp->width = thisbox->items[z].width = initialx - newx;
990 tmp->height = thisbox->items[z].height = initialy - newy;
991
992 tmp->parentxratio = thisbox->xratio;
993 tmp->parentyratio = thisbox->yratio;
994
995 tmp->parentpad = tmp->pad;
996
997 /* Just in case */
998 tmp->xratio = thisbox->xratio;
999 tmp->yratio = thisbox->yratio;
1000
1001 if(thisbox->type == BOXVERT)
1002 {
1003 if((thisbox->items[z].width-((thisbox->items[z].pad*2)+(tmp->pad*2)))!=0)
1004 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))));
1005 }
1006 else
1007 {
1008 if((thisbox->items[z].width-tmp->upx)!=0)
1009 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx));
1010 }
1011 if(thisbox->type == BOXHORZ)
1012 {
1013 if((thisbox->items[z].height-((thisbox->items[z].pad*2)+(tmp->pad*2)))!=0)
1014 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))));
1015 }
1016 else
1017 {
1018 if((thisbox->items[z].height-tmp->upy)!=0)
1019 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy));
1020 }
1021
1022 nux = *usedx; nuy = *usedy;
1023 upx = *usedpadx + (tmp->pad*2); upy = *usedpady + (tmp->pad*2);
1024 }
1025
1026 (*depth)++;
1027
1028 _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy);
1029
1030 (*depth)--;
1031
1032 newx = x - nux;
1033 newy = y - nuy;
1034
1035 tmp->minwidth = thisbox->items[z].width = initialx - newx;
1036 tmp->minheight = thisbox->items[z].height = initialy - newy;
1037 }
1038 }
1039
1040 if(pass > 1 && *depth > 0)
1041 {
1042 if(thisbox->type == BOXVERT)
1043 {
1044 if((thisbox->minwidth-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))) == 0)
1045 thisbox->items[z].xratio = 1.0;
1046 else
1047 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))));
1048 }
1049 else
1050 {
1051 if(thisbox->minwidth-thisbox->upx == 0)
1052 thisbox->items[z].xratio = 1.0;
1053 else
1054 thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
1055 }
1056
1057 if(thisbox->type == BOXHORZ)
1058 {
1059 if((thisbox->minheight-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))) == 0)
1060 thisbox->items[z].yratio = 1.0;
1061 else
1062 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))));
1063 }
1064 else
1065 {
1066 if(thisbox->minheight-thisbox->upy == 0)
1067 thisbox->items[z].yratio = 1.0;
1068 else
1069 thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
1070 }
1071
1072 if(thisbox->items[z].type == TYPEBOX)
1073 {
1074 Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
1075
1076 if(tmp)
1077 {
1078 tmp->parentxratio = thisbox->items[z].xratio;
1079 tmp->parentyratio = thisbox->items[z].yratio;
1080 }
1081 }
1082 }
1083 else
1084 {
1085 thisbox->items[z].xratio = thisbox->xratio;
1086 thisbox->items[z].yratio = thisbox->yratio;
1087 }
1088
1089 if(thisbox->type == BOXVERT)
1090 {
1091 if((thisbox->items[z].width + (thisbox->items[z].pad*2)) > uxmax)
1092 uxmax = (thisbox->items[z].width + (thisbox->items[z].pad*2));
1093 if(thisbox->items[z].hsize != SIZEEXPAND)
1094 {
1095 if(((thisbox->items[z].pad*2) + thisbox->items[z].width) > upxmax)
1096 upxmax = (thisbox->items[z].pad*2) + thisbox->items[z].width;
1097 }
1098 else
1099 {
1100 if(thisbox->items[z].pad*2 > upxmax)
1101 upxmax = thisbox->items[z].pad*2;
1102 }
1103 }
1104 else
1105 {
1106 if(thisbox->items[z].width == -1)
1107 {
1108 /* figure out how much space this item requires */
1109 /* thisbox->items[z].width = */
1110 }
1111 else
1112 {
1113 (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2);
1114 if(thisbox->items[z].hsize != SIZEEXPAND)
1115 (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width;
1116 else
1117 (*usedpadx) += thisbox->items[z].pad*2;
1118 }
1119 }
1120 if(thisbox->type == BOXHORZ)
1121 {
1122 if((thisbox->items[z].height + (thisbox->items[z].pad*2)) > uymax)
1123 uymax = (thisbox->items[z].height + (thisbox->items[z].pad*2));
1124 if(thisbox->items[z].vsize != SIZEEXPAND)
1125 {
1126 if(((thisbox->items[z].pad*2) + thisbox->items[z].height) > upymax)
1127 upymax = (thisbox->items[z].pad*2) + thisbox->items[z].height;
1128 }
1129 else
1130 {
1131 if(thisbox->items[z].pad*2 > upymax)
1132 upymax = thisbox->items[z].pad*2;
1133 }
1134 }
1135 else
1136 {
1137 if(thisbox->items[z].height == -1)
1138 {
1139 /* figure out how much space this item requires */
1140 /* thisbox->items[z].height = */
1141 }
1142 else
1143 {
1144 (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2);
1145 if(thisbox->items[z].vsize != SIZEEXPAND)
1146 (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height;
1147 else
1148 (*usedpady) += thisbox->items[z].pad*2;
1149 }
1150 }
1151 }
1152
1153 (*usedx) += uxmax;
1154 (*usedy) += uymax;
1155 (*usedpadx) += upxmax;
1156 (*usedpady) += upymax;
1157
1158 currentx += thisbox->pad;
1159 currenty += thisbox->pad;
1160
1161 /* The second pass is for expansion and actual placement. */
1162 if(pass > 1)
1163 {
1164 /* Any SIZEEXPAND items should be set to uxmax/uymax */
1165 for(z=0;z<thisbox->count;z++)
1166 {
1167 if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == BOXVERT)
1168 thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2);
1169 if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == BOXHORZ)
1170 thisbox->items[z].height = uymax-(thisbox->items[z].pad*2);
1171 /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */
1172 if(thisbox->items[z].type == TYPEBOX)
1173 {
1174 Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
1175
1176 if(tmp)
1177 {
1178 if(*depth > 0)
1179 {
1180 if(thisbox->type == BOXVERT)
1181 {
1182 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))));
1183 tmp->width = thisbox->items[z].width;
1184 }
1185 if(thisbox->type == BOXHORZ)
1186 {
1187 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))));
1188 tmp->height = thisbox->items[z].height;
1189 }
1190 }
1191
1192 (*depth)++;
1193
1194 _resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy);
1195
1196 (*depth)--;
1197
1198 }
1199 }
1200 }
1201
1202 for(z=0;z<(thisbox->count);z++)
1203 {
1204 int height = thisbox->items[z].height;
1205 int width = thisbox->items[z].width;
1206 int pad = thisbox->items[z].pad;
1207 HWND handle = thisbox->items[z].hwnd;
1208 int vectorx, vectory;
1209
1210 /* When upxmax != pad*2 then ratios are incorrect. */
1211 vectorx = (int)((width*thisbox->items[z].xratio)-width);
1212 vectory = (int)((height*thisbox->items[z].yratio)-height);
1213
1214 if(width > 0 && height > 0)
1215 {
1216 char tmpbuf[100];
1217 /* This is a hack to fix rounding of the sizing */
1218 if(*depth == 0)
1219 {
1220 vectorx++;
1221 vectory++;
1222 }
1223
1224 /* If this item isn't going to expand... reset the vectors to 0 */
1225 if(thisbox->items[z].vsize != SIZEEXPAND)
1226 vectory = 0;
1227 if(thisbox->items[z].hsize != SIZEEXPAND)
1228 vectorx = 0;
1229
1230 WinQueryClassName(handle, 99, tmpbuf);
1231
1232 if(strncmp(tmpbuf, "#2", 3)==0)
1233 {
1234 /* Make the combobox big enough to drop down. :) */
1235 WinSetWindowPos(handle, HWND_TOP, currentx + pad, (currenty + pad) - 100,
1236 width + vectorx, (height + vectory) + 100, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
1237 }
1238 else if(strncmp(tmpbuf, "#6", 3)==0)
1239 {
1240 /* Entryfields on OS/2 have a thick border that isn't on Windows and GTK */
1241 WinSetWindowPos(handle, HWND_TOP, (currentx + pad) + 3, (currenty + pad) + 3,
1242 (width + vectorx) - 6, (height + vectory) - 6, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
1243 }
1244 else if(strncmp(tmpbuf, "#40", 5)==0)
1245 {
1246 WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad,
1247 width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
1248 _check_resize_notebook(handle);
1249 }
1250 else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
1251 {
1252 /* Then try the bottom or right box */
1253 float *percent = (float *)dw_window_get_data(handle, "_dw_percent");
1254 int type = (int)dw_window_get_data(handle, "_dw_type");
1255 int cx = width + vectorx;
1256 int cy = height + vectory;
1257
1258 WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad,
1259 cx, cy, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
1260
1261 if(cx > 0 && cy > 0 && percent)
1262 _handle_splitbar_resize(handle, *percent, type, cx, cy);
1263 }
1264 else
1265 {
1266 WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad,
1267 width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
1268 if(thisbox->items[z].type == TYPEBOX)
1269 {
1270 Box *boxinfo = WinQueryWindowPtr(handle, QWP_USER);
1271
1272 if(boxinfo && boxinfo->grouphwnd)
1273 WinSetWindowPos(boxinfo->grouphwnd, HWND_TOP, 0, 0,
1274 width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE);
1275
1276 }
1277
1278 }
1279
1280 if(thisbox->type == BOXHORZ)
1281 currentx += width + vectorx + (pad * 2);
1282 if(thisbox->type == BOXVERT)
1283 currenty += height + vectory + (pad * 2);
1284 }
1285 }
1286 }
1287 return 0;
1288 }
1289
1290 void _do_resize(Box *thisbox, int x, int y)
1291 {
1292 if(x != 0 && y != 0)
1293 {
1294 if(thisbox)
1295 {
1296 int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0;
1297
1298 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady);
1299
1300 if(usedx-usedpadx == 0 || usedy-usedpady == 0)
1301 return;
1302
1303 thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx));
1304 thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady));
1305
1306 usedx = usedy = usedpadx = usedpady = depth = 0;
1307
1308 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady);
1309 }
1310 }
1311 }
1312
1313 /* This procedure handles WM_QUERYTRACKINFO requests from the frame */
1314 MRESULT EXPENTRY _sizeproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1315 {
1316 PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER);
1317 Box *thisbox = NULL;
1318 HWND box;
1319
1320 box = WinWindowFromID(hWnd, FID_CLIENT);
1321 if(box)
1322 thisbox = WinQueryWindowPtr(box, QWP_USER);
1323
1324 if(thisbox && !thisbox->titlebar)
1325 {
1326 switch(msg)
1327 {
1328 case WM_QUERYTRACKINFO:
1329 {
1330 if(blah && *blah)
1331 {
1332 PTRACKINFO ptInfo;
1333 int res;
1334 PFNWP myfunc = *blah;
1335 res = (int)myfunc(hWnd, msg, mp1, mp2);
1336
1337 ptInfo = (PTRACKINFO)(mp2);
1338
1339 ptInfo->ptlMinTrackSize.y = 8;
1340 ptInfo->ptlMinTrackSize.x = 8;
1341
1342 return (MRESULT)res;
1343 }
1344 }
1345 }
1346 }
1347
1348 if(blah && *blah)
1349 {
1350 PFNWP myfunc = *blah;
1351 return myfunc(hWnd, msg, mp1, mp2);
1352 }
1353
1354 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1355 }
1356
1357 void _Top(HPS hpsPaint, RECTL rclPaint)
1358 {
1359 POINTL ptl1, ptl2;
1360
1361 ptl1.x = rclPaint.xLeft;
1362 ptl2.y = ptl1.y = rclPaint.yTop - 1;
1363 ptl2.x = rclPaint.xRight - 1;
1364 GpiMove(hpsPaint, &ptl1);
1365 GpiLine(hpsPaint, &ptl2);
1366 }
1367
1368 /* Left hits the bottom */
1369 void _Left(HPS hpsPaint, RECTL rclPaint)
1370 {
1371 POINTL ptl1, ptl2;
1372
1373 ptl2.x = ptl1.x = rclPaint.xLeft;
1374 ptl1.y = rclPaint.yTop - 1;
1375 ptl2.y = rclPaint.yBottom;
1376 GpiMove(hpsPaint, &ptl1);
1377 GpiLine(hpsPaint, &ptl2);
1378 }
1379
1380 void _Bottom(HPS hpsPaint, RECTL rclPaint)
1381 {
1382 POINTL ptl1, ptl2;
1383
1384 ptl1.x = rclPaint.xRight - 1;
1385 ptl1.y = ptl2.y = rclPaint.yBottom;
1386 ptl2.x = rclPaint.xLeft;
1387 GpiMove(hpsPaint, &ptl1);
1388 GpiLine(hpsPaint, &ptl2);
1389 }
1390
1391 /* Right hits the top */
1392 void _Right(HPS hpsPaint, RECTL rclPaint)
1393 {
1394 POINTL ptl1, ptl2;
1395
1396 ptl2.x = ptl1.x = rclPaint.xRight - 1;
1397 ptl1.y = rclPaint.yBottom + 1;
1398 ptl2.y = rclPaint.yTop - 1;
1399 GpiMove(hpsPaint, &ptl1);
1400 GpiLine(hpsPaint, &ptl2);
1401 }
1402
1403 /* This procedure handles drawing of a status border */
1404 MRESULT EXPENTRY _statusproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1405 {
1406 PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER);
1407
1408 if(blah && *blah)
1409 {
1410 PFNWP myfunc = *blah;
1411
1412 switch(msg)
1413 {
1414 case WM_PAINT:
1415 {
1416 HPS hpsPaint;
1417 RECTL rclPaint;
1418 char buf[1024];
1419
1420 hpsPaint = WinBeginPaint(hWnd, 0, 0);
1421 WinQueryWindowRect(hWnd, &rclPaint);
1422 WinFillRect(hpsPaint, &rclPaint, CLR_PALEGRAY);
1423
1424 GpiSetColor(hpsPaint, CLR_DARKGRAY);
1425 _Top(hpsPaint, rclPaint);
1426 _Left(hpsPaint, rclPaint);
1427
1428 GpiSetColor(hpsPaint, CLR_WHITE);
1429 _Right(hpsPaint, rclPaint);
1430 _Bottom(hpsPaint, rclPaint);
1431
1432 WinQueryWindowText(hWnd, 1024, buf);
1433 rclPaint.xLeft += 3;
1434 rclPaint.xRight--;
1435 rclPaint.yTop--;
1436 rclPaint.yBottom++;
1437
1438 GpiSetColor(hpsPaint, CLR_BLACK);
1439 WinDrawText(hpsPaint, -1, buf, &rclPaint, DT_TEXTATTRS, DT_TEXTATTRS, DT_VCENTER | DT_LEFT | DT_TEXTATTRS);
1440 WinEndPaint(hpsPaint);
1441
1442 return (MRESULT)TRUE;
1443 }
1444 }
1445 return myfunc(hWnd, msg, mp1, mp2);
1446 }
1447
1448 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1449 }
1450
1451 void _click_default(HWND handle)
1452 {
1453 char tmpbuf[100];
1454
1455 WinQueryClassName(handle, 99, tmpbuf);
1456
1457 /* These are the window classes which can
1458 * obtain input focus.
1459 */
1460 if(strncmp(tmpbuf, "#3", 3)==0)
1461 {
1462 /* Generate click on default item */
1463 SignalHandler *tmp = Root;
1464
1465 /* Find any callbacks for this function */
1466 while(tmp)
1467 {
1468 if(tmp->message == WM_COMMAND)
1469 {
1470 int (*clickfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction;
1471
1472 /* Make sure it's the right window, and the right ID */
1473 if(tmp->window == handle)
1474 {
1475 clickfunc(tmp->window, tmp->data);
1476 tmp = NULL;
1477 }
1478 }
1479 if(tmp)
1480 tmp= tmp->next;
1481 }
1482 }
1483 else
1484 WinSetFocus(HWND_DESKTOP, handle);
1485 }
1486
1487 #define ENTRY_CUT 1001
1488 #define ENTRY_COPY 1002
1489 #define ENTRY_PASTE 1003
1490 #define ENTRY_UNDO 1004
1491 #define ENTRY_SALL 1005
1492
1493 /* Originally just intended for entryfields, it now serves as a generic
1494 * procedure for handling TAB presses to change input focus on controls.
1495 */
1496 MRESULT EXPENTRY _entryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1497 {
1498 WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER);
1499 PFNWP oldproc = 0;
1500 char tmpbuf[100];
1501
1502 if(blah)
1503 oldproc = blah->oldproc;
1504
1505 WinQueryClassName(hWnd, 99, tmpbuf);
1506
1507 /* These are the window classes which should get a menu */
1508 if(strncmp(tmpbuf, "#2", 3)==0 || /* Combobox */
1509 strncmp(tmpbuf, "#6", 3)==0 || /* Entryfield */
1510 strncmp(tmpbuf, "#10", 4)==0 || /* MLE */
1511 strncmp(tmpbuf, "#32", 4)==0) /* Spinbutton */
1512 {
1513 switch(msg)
1514 {
1515 case WM_CONTEXTMENU:
1516 {
1517 HMENUI hwndMenu = dw_menu_new(0L);
1518 long x, y;
1519
1520 if(strncmp(tmpbuf, "#10", 4)==0 && !WinSendMsg(hWnd, MLM_QUERYREADONLY, 0, 0))
1521 {
1522 dw_menu_append_item(hwndMenu, "Undo", ENTRY_UNDO, 0L, TRUE, FALSE, 0L);
1523 dw_menu_append_item(hwndMenu, "", 0L, 0L, TRUE, FALSE, 0L);
1524 }
1525 dw_menu_append_item(hwndMenu, "Copy", ENTRY_COPY, 0L, TRUE, FALSE, 0L);
1526 if((strncmp(tmpbuf, "#10", 4)!=0 && !dw_window_get_data(hWnd, "_dw_disabled")) || (strncmp(tmpbuf, "#10", 4)==0 && !WinSendMsg(hWnd, MLM_QUERYREADONLY, 0, 0)))
1527 {
1528 dw_menu_append_item(hwndMenu, "Cut", ENTRY_CUT, 0L, TRUE, FALSE, 0L);
1529 dw_menu_append_item(hwndMenu, "Paste", ENTRY_PASTE, 0L, TRUE, FALSE, 0L);
1530 }
1531 dw_menu_append_item(hwndMenu, "", 0L, 0L, TRUE, FALSE, 0L);
1532 dw_menu_append_item(hwndMenu, "Select All", ENTRY_SALL, 0L, TRUE, FALSE, 0L);
1533
1534 WinSetFocus(HWND_DESKTOP, hWnd);
1535 dw_pointer_query_pos(&x, &y);
1536 dw_menu_popup(&hwndMenu, hWnd, x, y);
1537 }
1538 break;
1539 case WM_COMMAND:
1540 {
1541 ULONG command = COMMANDMSG(&msg)->cmd;
1542
1543 /* MLE */
1544 if(strncmp(tmpbuf, "#10", 4)==0)
1545 {
1546 switch(command)
1547 {
1548 case ENTRY_CUT:
1549 return WinSendMsg(hWnd, MLM_CUT, 0, 0);
1550 case ENTRY_COPY:
1551 return WinSendMsg(hWnd, MLM_COPY, 0, 0);
1552 case ENTRY_PASTE:
1553 return WinSendMsg(hWnd, MLM_PASTE, 0, 0);
1554 case ENTRY_UNDO:
1555 return WinSendMsg(hWnd, MLM_UNDO, 0, 0);
1556 case ENTRY_SALL:
1557 {
1558 ULONG len = (ULONG)WinSendMsg(hWnd, MLM_QUERYTEXTLENGTH, 0, 0);
1559 return WinSendMsg(hWnd, MLM_SETSEL, 0, (MPARAM)len);
1560 }
1561 }
1562 }
1563 else /* Other */
1564 {
1565 HWND handle = hWnd;
1566
1567 /* Get the entryfield handle from multi window controls */
1568 if(strncmp(tmpbuf, "#2", 3)==0)
1569 handle = WinWindowFromID(hWnd, 667);
1570
1571 if(handle)
1572 {
1573 switch(command)
1574 {
1575 case ENTRY_CUT:
1576 return WinSendMsg(handle, EM_CUT, 0, 0);
1577 case ENTRY_COPY:
1578 return WinSendMsg(handle, EM_COPY, 0, 0);
1579 case ENTRY_PASTE:
1580 return WinSendMsg(handle, EM_PASTE, 0, 0);
1581 case ENTRY_SALL:
1582 {
1583 LONG len = WinQueryWindowTextLength(hWnd);
1584 return WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT(0, (SHORT)len), 0);
1585 }
1586 }
1587 }
1588 }
1589 }
1590 break;
1591 }
1592 }
1593
1594 switch(msg)
1595 {
1596 case WM_BUTTON1DOWN:
1597 case WM_BUTTON2DOWN:
1598 case WM_BUTTON3DOWN:
1599 {
1600 if(strncmp(tmpbuf, "#32", 4)==0)
1601 _run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE);
1602 }
1603 break;
1604 case WM_CONTROL:
1605 {
1606 if(strncmp(tmpbuf, "#38", 4)==0)
1607 _run_event(hWnd, msg, mp1, mp2);
1608 }
1609 break;
1610 case WM_SETFOCUS:
1611 _run_event(hWnd, msg, mp1, mp2);
1612 break;
1613 case WM_CHAR:
1614 if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE)
1615 return (MRESULT)TRUE;
1616 if(SHORT1FROMMP(mp2) == '\t')
1617 {
1618 if(CHARMSG(&msg)->fs & KC_SHIFT)
1619 _shift_focus_back(hWnd);
1620 else
1621 _shift_focus(hWnd);
1622 return FALSE;
1623 }
1624 else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault)
1625 _click_default(blah->clickdefault);
1626 /* When you hit escape we get this value and the
1627 * window hangs for reasons unknown. (in an MLE)
1628 */
1629 else if(SHORT1FROMMP(mp2) == 283)
1630 return (MRESULT)TRUE;
1631
1632 break;
1633 case WM_SIZE:
1634 {
1635 /* If it's a slider... make sure it shows the correct value */
1636 if(strncmp(tmpbuf, "#38", 4)==0)
1637 WinPostMsg(hWnd, WM_USER+7, 0, 0);
1638 }
1639 break;
1640 case WM_USER+7:
1641 {
1642 int pos = (int)dw_window_get_data(hWnd, "_dw_slider_value");
1643 WinSendMsg(hWnd, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)pos);
1644 }
1645 break;
1646 }
1647
1648 if(oldproc)
1649 return oldproc(hWnd, msg, mp1, mp2);
1650
1651 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1652 }
1653
1654 /* Deal with combobox specifics and enhancements */
1655 MRESULT EXPENTRY _comboentryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1656 {
1657 WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER);
1658
1659 switch(msg)
1660 {
1661 case WM_CONTEXTMENU:
1662 case WM_COMMAND:
1663 return _entryproc(hWnd, msg, mp1, mp2);
1664 case WM_SETFOCUS:
1665 _run_event(hWnd, msg, mp1, mp2);
1666 break;
1667 case WM_CHAR:
1668 if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE)
1669 return (MRESULT)TRUE;
1670 /* A Similar problem to the MLE, if ESC just return */
1671 if(SHORT1FROMMP(mp2) == 283)
1672 return (MRESULT)TRUE;
1673 break;
1674 }
1675
1676 if(blah && blah->oldproc)
1677 return blah->oldproc(hWnd, msg, mp1, mp2);
1678
1679 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1680 }
1681
1682 /* Enhance the standard OS/2 MLE control */
1683 MRESULT EXPENTRY _mleproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1684 {
1685 switch(msg)
1686 {
1687 case WM_VSCROLL:
1688 if(SHORT2FROMMP(mp2) == SB_SLIDERTRACK)
1689 {
1690 USHORT pos = SHORT1FROMMP(mp2);
1691
1692 WinSendMsg(hWnd, msg, mp1, MPFROM2SHORT(pos, SB_SLIDERPOSITION));
1693 }
1694 break;
1695 }
1696 return _entryproc(hWnd, msg, mp1, mp2);
1697 }
1698
1699 /* Handle special messages for the spinbutton's entryfield */
1700 MRESULT EXPENTRY _spinentryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1701 {
1702 WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER);
1703 PFNWP oldproc = 0;
1704
1705 if(blah)
1706 oldproc = blah->oldproc;
1707
1708 switch(msg)
1709 {
1710 case WM_CONTEXTMENU:
1711 case WM_COMMAND:
1712 return _entryproc(hWnd, msg, mp1, mp2);
1713 }
1714
1715 if(oldproc)
1716 return oldproc(hWnd, msg, mp1, mp2);
1717
1718 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1719 }
1720
1721 int _dw_int_pos(HWND hwnd)
1722 {
1723 int pos = (int)dw_window_get_data(hwnd, "_dw_percent_value");
1724 int range = dw_percent_query_range(hwnd);
1725 float fpos = (float)pos;
1726 float frange = (float)range;
1727 float fnew = (fpos/1000.0)*frange;
1728 return (int)fnew;
1729 }
1730
1731 void _dw_int_set(HWND hwnd, int pos)
1732 {
1733 int inew, range = dw_percent_query_range(hwnd);
1734 if(range)
1735 {
1736 float fpos = (float)pos;
1737 float frange = (float)range;
1738 float fnew = (fpos/frange)*1000.0;
1739 inew = (int)fnew;
1740 dw_window_set_data(hwnd, "_dw_percent_value", (void *)inew);
1741 }
1742 }
1743
1744 /* Handle size changes in the percent class */
1745 MRESULT EXPENTRY _percentproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1746 {
1747 WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER);
1748 PFNWP oldproc = 0;
1749
1750 if(blah)
1751 oldproc = blah->oldproc;
1752
1753 switch(msg)
1754 {
1755 case WM_SIZE:
1756 WinPostMsg(hWnd, WM_USER+7, 0, 0);
1757 break;
1758 case WM_USER+7:
1759 WinSendMsg(hWnd, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)_dw_int_pos(hWnd));
1760 break;
1761 }
1762
1763 if(oldproc)
1764 return oldproc(hWnd, msg, mp1, mp2);
1765
1766 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1767 }
1768
1769 /* Handle correct painting of a combobox with the WS_CLIPCHILDREN
1770 * flag enabled, and also handle TABs to switch input focus.
1771 */
1772 MRESULT EXPENTRY _comboproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1773 {
1774 WindowData *blah = WinQueryWindowPtr(hWnd, QWP_USER);
1775 PFNWP oldproc = 0;
1776
1777 if(blah)
1778 oldproc = blah->oldproc;
1779
1780 switch(msg)
1781 {
1782 case WM_CHAR:
1783 if(SHORT1FROMMP(mp2) == '\t')
1784 {
1785 if(CHARMSG(&msg)->fs & KC_SHIFT)
1786 _shift_focus_back(hWnd);
1787 else
1788 _shift_focus(hWnd);
1789 return FALSE;
1790 }
1791 else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault)
1792 _click_default(blah->clickdefault);
1793 break;
1794 case WM_BUTTON1DBLCLK:
1795 case WM_BUTTON2DBLCLK:
1796 case WM_BUTTON3DBLCLK:
1797 if(dw_window_get_data(hWnd, "_dw_disabled"))
1798 return (MRESULT)TRUE;
1799 break;
1800 case WM_BUTTON1DOWN:
1801 case WM_BUTTON2DOWN:
1802 case WM_BUTTON3DOWN:
1803 if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE)
1804 return (MRESULT)TRUE;
1805 _run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE);
1806 break;
1807 case WM_SETFOCUS:
1808 _run_event(hWnd, msg, mp1, mp2);
1809 break;
1810 case WM_PAINT:
1811 {
1812 HWND parent = WinQueryWindow(hWnd, QW_PARENT);
1813 ULONG bcol, av[32];
1814 HPS hpsPaint;
1815 POINTL ptl; /* Add 6 because it has a thick border like the entryfield */
1816 unsigned long width, height, thumbheight = WinQuerySysValue(HWND_DESKTOP, SV_CYVSCROLLARROW) + 6;
1817
1818 WinQueryPresParam(parent, PP_BACKGROUNDCOLORINDEX, 0, &bcol, sizeof(ULONG), &av, QPF_ID1COLORINDEX | QPF_NOINHERIT);
1819 dw_window_get_pos_size(hWnd, 0, 0, &width, &height);
1820
1821 hpsPaint = WinGetPS(hWnd);
1822 GpiSetColor(hpsPaint, CLR_PALEGRAY);
1823
1824 ptl.x = 0;
1825 ptl.y = 0;
1826 GpiMove(hpsPaint, &ptl);
1827
1828 ptl.x = width;
1829 ptl.y = height - thumbheight;
1830 GpiBox(hpsPaint, DRO_FILL, &ptl, 0, 0);
1831
1832 WinReleasePS(hpsPaint);
1833 }
1834 break;
1835 }
1836 if(oldproc)
1837 return oldproc(hWnd, msg, mp1, mp2);
1838
1839 return WinDefWindowProc(hWnd, msg, mp1, mp2);
1840 }
1841
1842 void _GetPPFont(HWND hwnd, char *buff)
1843 {
1844 ULONG AttrFound;
1845 BYTE AttrValue[128];
1846 ULONG cbRetLen;
1847
1848 cbRetLen = WinQueryPresParam(hwnd,
1849 PP_FONTNAMESIZE,
1850 0,
1851 &AttrFound,
1852 sizeof(AttrValue),
1853 &AttrValue,
1854 QPF_NOINHERIT);
1855
1856 if(PP_FONTNAMESIZE == AttrFound && cbRetLen)
1857 {
1858 memcpy(buff, AttrValue, cbRetLen);
1859 }
1860 }
1861
1862 /* Returns height of specified window. */
1863 int _get_height(HWND handle)
1864 {
1865 unsigned long height;
1866 dw_window_get_pos_size(handle, NULL, NULL, NULL, &height);
1867 return (int)height;
1868 }
1869
1870 /* Find the height of the frame a desktop style window is sitting on */
1871 int _get_frame_height(HWND handle)
1872 {
1873 while(handle)
1874 {
1875 HWND client;
1876 if((client = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE)
1877 {
1878 return _get_height(WinQueryWindow(handle, QW_PARENT));
1879 }
1880 handle = WinQueryWindow(handle, QW_PARENT);
1881 }
1882 return dw_screen_height();
1883 }
1884
1885 int _HandleScroller(HWND handle, int pos, int which)
1886 {
1887 MPARAM res;
1888 int min, max, page;
1889
1890 if(which == SB_SLIDERTRACK)
1891 return pos;
1892
1893 pos = dw_scrollbar_query_pos(handle);
1894 res = WinSendMsg(handle, SBM_QUERYRANGE, 0, 0);
1895
1896 min = SHORT1FROMMP(res);
1897 max = SHORT2FROMMP(res);
1898 page = (int)dw_window_get_data(handle, "_dw_scrollbar_visible");
1899
1900 switch(which)
1901 {
1902 case SB_LINEUP:
1903 pos = pos - 1;
1904 if(pos < min)
1905 pos = min;
1906 dw_scrollbar_set_pos(handle, pos);
1907 return pos;
1908 case SB_LINEDOWN:
1909 pos = pos + 1;
1910 if(pos > max)
1911 pos = max;
1912 dw_scrollbar_set_pos(handle, pos);
1913 return pos;
1914 case SB_PAGEUP:
1915 pos = pos - page;
1916 if(pos < min)
1917 pos = min;
1918 dw_scrollbar_set_pos(handle, pos);
1919 return pos;
1920 case SB_PAGEDOWN:
1921 pos = pos + page;
1922 if(pos > max)
1923 pos = max;
1924 dw_scrollbar_set_pos(handle, pos);
1925 return pos;
1926 }
1927 return -1;
1928 }
1929
1930 MRESULT EXPENTRY _run_event(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1931 {
1932 int result = -1;
1933 SignalHandler *tmp = Root;
1934 ULONG origmsg = msg;
1935
1936 if(msg == WM_BUTTON2DOWN || msg == WM_BUTTON3DOWN)
1937 msg = WM_BUTTON1DOWN;
1938 if(msg == WM_BUTTON2UP || msg == WM_BUTTON3UP)
1939 msg = WM_BUTTON1UP;
1940 if(msg == WM_VSCROLL || msg == WM_HSCROLL)
1941 msg = WM_CONTROL;
1942
1943 /* Find any callbacks for this function */
1944 while(tmp)
1945 {
1946 if(tmp->message == msg || msg == WM_CONTROL || tmp->message == WM_USER+1)
1947 {
1948 switch(msg)
1949 {
1950 case WM_SETFOCUS:
1951 {
1952 if((mp2 && tmp->message == WM_SETFOCUS) || (!mp2 && tmp->message == WM_USER+1))
1953 {
1954 int (* API setfocusfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction;
1955
1956 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd)
1957 {
1958 result = setfocusfunc(tmp->window, tmp->data);
1959 tmp = NULL;
1960 }
1961 }
1962 }
1963 break;
1964 case WM_TIMER:
1965 {
1966 int (* API timerfunc)(void *) = (int (* API)(void *))tmp->signalfunction;
1967 if(tmp->id == (int)mp1)
1968 {
1969 if(!timerfunc(tmp->data))
1970 dw_timer_disconnect(tmp->id);
1971 tmp = NULL;
1972 }
1973 result = 0;
1974 }
1975 break;
1976 case WM_SIZE:
1977 {
1978 int (* API sizefunc)(HWND, int, int, void *) = (int (* API)(HWND, int, int, void *))tmp->signalfunction;
1979
1980 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd)
1981 {
1982 result = sizefunc(tmp->window, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), tmp->data);
1983 tmp = NULL;
1984 }
1985 }
1986 break;
1987 case WM_BUTTON1DOWN:
1988 {
1989 POINTS pts = (*((POINTS*)&mp1));
1990 int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction;
1991
1992 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
1993 {
1994 int button = 0;
1995
1996 switch(origmsg)
1997 {
1998 case WM_BUTTON1DOWN:
1999 button = 1;
2000 break;
2001 case WM_BUTTON2DOWN:
2002 button = 2;
2003 break;
2004 case WM_BUTTON3DOWN:
2005 button = 3;
2006 break;
2007 }
2008
2009 result = buttonfunc(tmp->window, pts.x, _get_frame_height(tmp->window) - pts.y, button, tmp->data);
2010 tmp = NULL;
2011 }
2012 }
2013 break;
2014 case WM_BUTTON1UP:
2015 {
2016 POINTS pts = (*((POINTS*)&mp1));
2017 int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction;
2018
2019 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
2020 {
2021 int button = 0;
2022
2023 switch(origmsg)
2024 {
2025 case WM_BUTTON1UP:
2026 button = 1;
2027 break;
2028 case WM_BUTTON2UP:
2029 button = 2;
2030 break;
2031 case WM_BUTTON3UP:
2032 button = 3;
2033 break;
2034 }
2035
2036 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);
2037 tmp = NULL;
2038 }
2039 }
2040 break;
2041 case WM_MOUSEMOVE:
2042 {
2043 int (* API motionfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction;
2044
2045 if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
2046 {
2047 int keys = 0;
2048 SHORT x = SHORT1FROMMP(mp1), y = SHORT2FROMMP(mp1);
2049
2050 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000)
2051 keys = DW_BUTTON1_MASK;
2052 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000)
2053 keys |= DW_BUTTON2_MASK;
2054 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000)
2055 keys |= DW_BUTTON3_MASK;
2056
2057 result = motionfunc(tmp->window, x, _get_frame_height(tmp->window) - y, keys, tmp->data);
2058 tmp = NULL;
2059 }
2060 }
2061 break;
2062 case WM_CHAR:
2063 {
2064 int (* API keypressfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction;
2065
2066 if(hWnd == tmp->window)
2067 {
2068 result = keypressfunc(tmp->window, SHORT1FROMMP(mp2), tmp->data);
2069 tmp = NULL;
2070 }
2071 }
2072 break;
2073 case WM_CLOSE:
2074 {
2075 int (* API closefunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction;
2076
2077 if(hWnd == tmp->window || hWnd == WinWindowFromID(tmp->window, FID_CLIENT))
2078 {
2079 result = closefunc(tmp->window, tmp->data);
2080 if(result)
2081 result = FALSE;
2082 tmp = NULL;
2083 }
2084 }
2085 break;
2086 case WM_PAINT:
2087 {
2088 HPS hps;
2089 DWExpose exp;
2090 int (* API exposefunc)(HWND, DWExpose *, void *) = (int (* API)(HWND, DWExpose *, void *))tmp->signalfunction;
2091 RECTL rc;
2092
2093 if(hWnd == tmp->window)
2094 {
2095 int height = _get_height(hWnd);
2096
2097 hps = WinBeginPaint(hWnd, 0L, &rc);
2098 exp.x = rc.xLeft;
2099 exp.y = height - rc.yTop - 1;
2100 exp.width = rc.xRight - rc. xLeft;
2101 exp.height = rc.yTop - rc.yBottom;
2102 result = exposefunc(hWnd, &exp, tmp->data);
2103 WinEndPaint(hps);
2104 }
2105 }
2106 break;
2107 case WM_COMMAND:
2108 {
2109 int (* API clickfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction;
2110 ULONG command = COMMANDMSG(&msg)->cmd;
2111
2112 if(tmp->window < 65536 && command == tmp->window)
2113 {
2114 result = clickfunc(popup ? popup : tmp->window, tmp->data);
2115 tmp = NULL;
2116 }
2117 }
2118 break;
2119 case WM_CONTROL:
2120 if(origmsg == WM_VSCROLL || origmsg == WM_HSCROLL || tmp->message == SHORT2FROMMP(mp1) ||
2121 (tmp->message == SLN_SLIDERTRACK && SHORT2FROMMP(mp1) == SLN_CHANGE))
2122 {
2123 int svar = SLN_SLIDERTRACK;
2124 if(origmsg == WM_CONTROL)
2125 svar = SHORT2FROMMP(mp1);
2126
2127 switch(svar)
2128 {
2129 case CN_ENTER:
2130 {
2131 int (* API containerselectfunc)(HWND, char *, void *) = (int (* API)(HWND, char *, void *))tmp->signalfunction;
2132 int id = SHORT1FROMMP(mp1);
2133 HWND conthwnd = dw_window_from_id(hWnd, id);
2134 char *text = NULL;
2135
2136 if(mp2)
2137 {
2138 PRECORDCORE pre;
2139
2140 pre = ((PNOTIFYRECORDENTER)mp2)->pRecord;
2141 if(pre)
2142 text = pre->pszIcon;
2143 }
2144
2145 if(tmp->window == conthwnd)
2146 {
2147 result = containerselectfunc(tmp->window, text, tmp->data);
2148 tmp = NULL;
2149 }
2150 }
2151 break;
2152 case CN_CONTEXTMENU:
2153 {
2154 int (* API containercontextfunc)(HWND, char *, int, int, void *, void *) = (int (* API)(HWND, char *, int, int, void *, void *))tmp->signalfunction;
2155 int id = SHORT1FROMMP(mp1);
2156 HWND conthwnd = dw_window_from_id(hWnd, id);
2157 char *text = NULL;
2158 void *user = NULL;
2159 LONG x,y;
2160
2161 if(mp2)
2162 {
2163 PCNRITEM pci;
2164
2165 pci = (PCNRITEM)mp2;
2166
2167 text = pci->rc.pszIcon;
2168 user = pci->user;
2169 }
2170
2171 dw_pointer_query_pos(&x, &y);
2172
2173 if(tmp->window == conthwnd)
2174 {
2175 int container = (int)dw_window_get_data(tmp->window, "_dw_container");
2176
2177 if(mp2)
2178 {
2179 if(!container)
2180 {
2181 NOTIFYRECORDEMPHASIS pre;
2182
2183 dw_tree_item_select(tmp->window, (HWND)mp2);
2184 pre.pRecord = mp2;
2185 pre.fEmphasisMask = CRA_CURSORED;
2186 pre.hwndCnr = tmp->window;
2187 _run_event(hWnd, WM_CONTROL, MPFROM2SHORT(0, CN_EMPHASIS), (MPARAM)&pre);
2188 pre.pRecord->flRecordAttr |= CRA_CURSORED;
2189 }
2190 else
2191 {
2192 hwndEmph = tmp->window;
2193 pCoreEmph = mp2;
2194 WinSendMsg(tmp->window, CM_SETRECORDEMPHASIS, mp2, MPFROM2SHORT(TRUE, CRA_SOURCE));
2195 }
2196 }
2197 result = containercontextfunc(tmp->window, text, x, y, tmp->data, user);
2198 tmp = NULL;
2199 }
2200 }
2201 break;
2202 case CN_EMPHASIS:
2203 {
2204 PNOTIFYRECORDEMPHASIS pre = (PNOTIFYRECORDEMPHASIS)mp2;
2205 static int emph_recurse = 0;
2206
2207 if(!emph_recurse)
2208 {
2209 emph_recurse = 1;
2210
2211 if(mp2)
2212 {
2213 if(tmp->window == pre->hwndCnr)
2214 {
2215 PCNRITEM pci = (PCNRITEM)pre->pRecord;
2216
2217 if(pci && pre->fEmphasisMask & CRA_CURSORED && (pci->rc.flRecordAttr & CRA_CURSORED))
2218 {
2219 if(dw_window_get_data(tmp->window, "_dw_container"))
2220 {
2221 int (* API containerselectfunc)(HWND, char *, void *) = (int (* API)(HWND, char *, void *))tmp->signalfunction;
2222
2223 result = containerselectfunc(tmp->window, pci->rc.pszIcon, tmp->data);
2224 }
2225 else
2226 {
2227 int (* API treeselectfunc)(HWND, HWND, char *, void *, void *) = (int (* API)(HWND, HWND, char *, void *, void *))tmp->signalfunction;
2228
2229 if(lasthcnr == tmp->window && lastitem == (HWND)pci)
2230 {
2231 lasthcnr = 0;
2232 lastitem = 0;
2233 }
2234 else
2235 {
2236 lasthcnr = tmp->window;
2237 lastitem = (HWND)pci;
2238 result = treeselectfunc(tmp->window, (HWND)pci, pci->rc.pszIcon, pci->user, tmp->data);
2239 }
2240 }
2241 tmp = NULL;
2242 }
2243 }
2244 }
2245 emph_recurse = 0;
2246 }
2247 }
2248 break;
2249 case LN_SELECT:
2250 {
2251 char classbuf[100];
2252
2253 WinQueryClassName(tmp->window, 99, classbuf);
2254
2255 if(strncmp(classbuf, "#38", 4) == 0)
2256 {
2257 int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction;
2258
2259 if(tmp->window == hWnd || WinQueryWindow(tmp->window, QW_PARENT) == hWnd)
2260 {
2261 static int lastvalue = -1;
2262 static HWND lasthwnd = NULLHANDLE;
2263 int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0);
2264 if(lastvalue != ulValue || lasthwnd != tmp->window)
2265 {
2266 result = valuechangedfunc(tmp->window, ulValue, tmp->data);
2267 lastvalue = ulValue;
2268 lasthwnd = tmp->window;
2269 }
2270 tmp = NULL;
2271 }
2272 }
2273 else
2274 {
2275 int (* API listboxselectfunc)(HWND, int, void *) = (int (* API )(HWND, int, void *))tmp->signalfunction;
2276 int id = SHORT1FROMMP(mp1);
2277 HWND conthwnd = dw_window_from_id(hWnd, id);
2278 static int _recursing = 0;
2279
2280 if(_recursing == 0 && (tmp->window == conthwnd || (!id && tmp->window == (HWND)mp2)))
2281 {
2282 char buf1[500];
2283 unsigned int index = dw_listbox_selected(tmp->window);
2284
2285 dw_listbox_query_text(tmp->window, index, buf1, 500);
2286
2287 _recursing = 1;
2288
2289 if(id && strncmp(classbuf, "#2", 3)==0)
2290 {
2291 char *buf2;
2292
2293 buf2 = dw_window_get_text(tmp->window);
2294
2295 /* This is to make sure the listboxselect function doesn't
2296 * get called if the user is modifying the entry text.
2297 */
2298 if(buf2 && *buf2 && *buf1 && strncmp(buf1, buf2, 500) == 0)
2299 result = listboxselectfunc(tmp->window, index, tmp->data);
2300
2301 if(buf2)
2302 free(buf2);
2303 }
2304 else
2305 result = listboxselectfunc(tmp->window, index, tmp->data);
2306
2307 _recursing = 0;
2308 tmp = NULL;
2309 }
2310 }
2311 }
2312 break;
2313 case SLN_SLIDERTRACK:
2314 {
2315 int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction;
2316
2317 if(origmsg == WM_CONTROL)
2318 {
2319 /* Handle Slider control */
2320 if(tmp->window == hWnd || WinQueryWindow(tmp->window, QW_PARENT) == hWnd)
2321 {
2322 static int lastvalue = -1;
2323 static HWND lasthwnd = NULLHANDLE;
2324 int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0);
2325 if(lastvalue != ulValue || lasthwnd != tmp->window)
2326 {
2327 dw_window_set_data(tmp->window, "_dw_slider_value", (void *)ulValue);
2328 result = valuechangedfunc(tmp->window, ulValue, tmp->data);
2329 lastvalue = ulValue;
2330 lasthwnd = tmp->window;
2331 }
2332 tmp = NULL;
2333 }
2334 }
2335 else
2336 {
2337 /* Handle scrollbar control */
2338 if(tmp->window > 65535 && tmp->window == WinWindowFromID(hWnd, (ULONG)mp1))
2339 {
2340 int pos = _HandleScroller(tmp->window, (int)SHORT1FROMMP(mp2), (int)SHORT2FROMMP(mp2));;
2341
2342 if(pos > -1)
2343 {
2344 dw_window_set_data(tmp->window, "_dw_scrollbar_value", (void *)pos);
2345 result = valuechangedfunc(tmp->window, pos, tmp->data);
2346 }
2347 result = 0;
2348 tmp = NULL;
2349 }
2350 }
2351 }
2352
2353 break;
2354 }
2355 }
2356 break;
2357 }
2358 }
2359
2360 if(tmp)
2361 tmp = tmp->next;
2362
2363 }
2364 return (MRESULT)result;
2365 }
2366
2367 /* Handles control messages sent to the box (owner). */
2368 MRESULT EXPENTRY _controlproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2369 {
2370 Box *blah = WinQueryWindowPtr(hWnd, QWP_USER);
2371
2372 switch(msg)
2373 {
2374 case WM_VSCROLL:
2375 case WM_HSCROLL:
2376 if(_run_event(hWnd, msg, mp1, mp2))
2377 {
2378 HWND window = WinWindowFromID(hWnd, (ULONG)mp1);
2379 _HandleScroller(window, (int)SHORT1FROMMP(mp2), (int)SHORT2FROMMP(mp2));
2380 }
2381 break;
2382 case WM_CONTROL:
2383 _run_event(hWnd, msg, mp1, mp2);
2384 break;
2385 }
2386
2387 if(blah && blah->oldproc)
2388 return blah->oldproc(hWnd, msg, mp1, mp2);
2389
2390 return WinDefWindowProc(hWnd, msg, mp1, mp2);
2391 }
2392
2393 /* The main window procedure for Dynamic Windows, all the resizing code is done here. */
2394 MRESULT EXPENTRY _wndproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2395 {
2396 int result = -1;
2397 static int command_active = 0;
2398 void (* API windowfunc)(PVOID) = 0L;
2399
2400 if(!command_active)
2401 {
2402 /* Make sure we don't end up in infinite recursion */
2403 command_active = 1;
2404
2405 result = (int)_run_event(hWnd, msg, mp1, mp2);
2406
2407 command_active = 0;
2408 }
2409
2410 /* Now that any handlers are done... do normal processing */
2411 switch( msg )
2412 {
2413 case WM_ERASEBACKGROUND:
2414 return 0;
2415
2416 case WM_PAINT:
2417 {
2418 HPS hps;
2419 RECTL rc;
2420
2421 hps = WinBeginPaint( hWnd, 0L, &rc );
2422 WinEndPaint( hps );
2423 break;
2424 }
2425
2426 case WM_SIZE:
2427 {
2428 Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER);
2429
2430 if(!SHORT1FROMMP(mp2) && !SHORT2FROMMP(mp2))
2431 return (MPARAM)TRUE;
2432
2433 if(mybox && mybox->flags != DW_MINIMIZED)
2434 {
2435 /* Hide the window when recalculating to reduce
2436 * CPU load.
2437 */
2438 WinShowWindow(hWnd, FALSE);
2439
2440 _do_resize(mybox, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2));
2441
2442 WinShowWindow(hWnd, TRUE);
2443 }
2444 }
2445 break;
2446 case WM_MINMAXFRAME:
2447 {
2448 Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER);
2449 SWP *swp = (SWP *)mp1;
2450
2451 if(mybox && (swp->fl & SWP_MINIMIZE))
2452 mybox->flags = DW_MINIMIZED;
2453
2454 if(mybox && (swp->fl & SWP_RESTORE))
2455 {
2456 if(!mybox->titlebar && mybox->hwndtitle)
2457 WinSetParent(mybox->hwndtitle, HWND_OBJECT, FALSE);
2458 mybox->flags = 0;
2459 }
2460
2461 if(mybox && (swp->fl & SWP_MAXIMIZE))
2462 {
2463 int z;
2464 SWP swp2;
2465
2466 WinQueryWindowPos(swp->hwnd, &swp2);
2467
2468 if(swp2.cx == swp->cx && swp2.cy == swp->cy)
2469 return FALSE;
2470
2471 mybox->flags = 0;
2472
2473 /* Hide the window when recalculating to reduce
2474 * CPU load.
2475 */
2476 WinShowWindow(hWnd, FALSE);
2477
2478 _do_resize(mybox, swp->cx, swp->cy);
2479
2480 if(mybox->count == 1 && mybox->items[0].type == TYPEBOX)
2481 {
2482 mybox = (Box *)WinQueryWindowPtr(mybox->items[0].hwnd, QWP_USER);
2483
2484 for(z=0;z<mybox->count;z++)
2485 _check_resize_notebook(mybox->items[z].hwnd);
2486
2487 }
2488
2489 WinShowWindow(hWnd, TRUE);
2490 }
2491 }
2492 break;
2493 case WM_CONTROL:
2494 switch(SHORT2FROMMP(mp1))
2495 {
2496 case BKN_PAGESELECTEDPENDING:
2497 {
2498 PAGESELECTNOTIFY *psn = (PAGESELECTNOTIFY *)mp2;
2499 HWND pagehwnd = (HWND)WinSendMsg(psn->hwndBook, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(psn->ulPageIdNew), 0);
2500 Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER);
2501 unsigned long x, y, width, height;
2502 RECTL rc;
2503
2504 if(pagebox && psn->ulPageIdNew != psn->ulPageIdCur)
2505 {
2506 dw_window_get_pos_size(psn->hwndBook, &x, &y, &width, &height);
2507
2508 rc.xLeft = x;
2509 rc.yBottom = y;
2510 rc.xRight = x + width;
2511 rc.yTop = y + height;
2512
2513 WinSendMsg(psn->hwndBook, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE);
2514
2515 _do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom);
2516 }
2517 }
2518 break;
2519 }
2520 break;
2521 case WM_CLOSE:
2522 if(result == -1)
2523 {
2524 dw_window_destroy(WinQueryWindow(hWnd, QW_PARENT));
2525 return (MRESULT)TRUE;
2526 }
2527 break;
2528 case WM_USER:
2529 windowfunc = (void (* API)(void *))mp1;
2530
2531 if(windowfunc)
2532 windowfunc((void *)mp2);
2533 break;
2534 case WM_CHAR:
2535 if(SHORT1FROMMP(mp2) == '\t')
2536 {
2537 if(CHARMSG(&msg)->fs & KC_SHIFT)
2538 _shift_focus_back(hWnd);
2539 else
2540 _shift_focus(hWnd);
2541 return FALSE;
2542 }
2543 break;
2544 case WM_DESTROY:
2545 /* Free memory before destroying */
2546 _free_window_memory(hWnd);
2547 break;
2548 case WM_MENUEND:
2549 if(hwndEmph && pCoreEmph)
2550 WinSendMsg(hwndEmph, CM_SETRECORDEMPHASIS, pCoreEmph, MPFROM2SHORT(FALSE, CRA_SOURCE));
2551 hwndEmph = NULLHANDLE;
2552 pCoreEmph = NULL;
2553 break;
2554 }
2555
2556 if(result != -1)
2557 return (MRESULT)result;
2558 else
2559 return WinDefWindowProc(hWnd, msg, mp1, mp2);
2560 }
2561
2562 void _changebox(Box *thisbox, int percent, int type)
2563 {
2564 int z;
2565
2566 for(z=0;z<thisbox->count;z++)
2567 {
2568 if(thisbox->items[z].type == TYPEBOX)
2569 {
2570 Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
2571 _changebox(tmp, percent, type);
2572 }
2573 else
2574 {
2575 if(type == BOXHORZ)
2576 {
2577 if(thisbox->items[z].hsize == SIZEEXPAND)
2578 thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0)));
2579 }
2580 else
2581 {
2582 if(thisbox->items[z].vsize == SIZEEXPAND)
2583 thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0)));
2584 }
2585 }
2586 }
2587 }
2588
2589 void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y)
2590 {
2591 if(type == BOXHORZ)
2592 {
2593 int newx = x;
2594 float ratio = (float)percent/(float)100.0;
2595 HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft");
2596 HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright");
2597 Box *tmp = WinQueryWindowPtr(handle1, QWP_USER);
2598
2599 WinShowWindow(handle1, FALSE);
2600 WinShowWindow(handle2, FALSE);
2601
2602 newx = (int)((float)newx * ratio) - (SPLITBAR_WIDTH/2);
2603
2604 WinSetWindowPos(handle1, NULLHANDLE, 0, 0, newx, y, SWP_MOVE | SWP_SIZE);
2605 _do_resize(tmp, newx - 1, y - 1);
2606
2607 dw_window_set_data(hwnd, "_dw_start", (void *)newx);
2608
2609 tmp = WinQueryWindowPtr(handle2, QWP_USER);
2610
2611 newx = x - newx - SPLITBAR_WIDTH;
2612
2613 WinSetWindowPos(handle2, NULLHANDLE, x - newx, 0, newx, y, SWP_MOVE | SWP_SIZE);
2614 _do_resize(tmp, newx - 1, y - 1);
2615
2616 WinShowWindow(handle1, TRUE);
2617 WinShowWindow(handle2, TRUE);
2618 }
2619 else
2620 {
2621 int newy = y;
2622 float ratio = (float)percent/(float)100.0;
2623 HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft");
2624 HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright");
2625 Box *tmp = WinQueryWindowPtr(handle1, QWP_USER);
2626
2627 WinShowWindow(handle1, FALSE);
2628 WinShowWindow(handle2, FALSE);
2629
2630 newy = (int)((float)newy * ratio) - (SPLITBAR_WIDTH/2);
2631
2632 WinSetWindowPos(handle1, NULLHANDLE, 0, y - newy, x, newy, SWP_MOVE | SWP_SIZE);
2633 _do_resize(tmp, x - 1, newy - 1);
2634
2635 tmp = WinQueryWindowPtr(handle2, QWP_USER);
2636
2637 newy = y - newy - SPLITBAR_WIDTH;
2638
2639 WinSetWindowPos(handle2, NULLHANDLE, 0, 0, x, newy, SWP_MOVE | SWP_SIZE);
2640 _do_resize(tmp, x - 1, newy - 1);
2641
2642 WinShowWindow(handle1, TRUE);
2643 WinShowWindow(handle2, TRUE);
2644
2645 dw_window_set_data(hwnd, "_dw_start", (void *)newy);
2646 }
2647 }
2648
2649
2650 /* This handles any activity on the splitbars (sizers) */
2651 MRESULT EXPENTRY _splitwndproc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2652 {
2653 float *percent = (float *)dw_window_get_data(hwnd, "_dw_percent");
2654 int type = (int)dw_window_get_data(hwnd, "_dw_type");
2655 int start = (int)dw_window_get_data(hwnd, "_dw_start");
2656
2657 switch (msg)
2658 {
2659 case WM_ACTIVATE:
2660 case WM_SETFOCUS:
2661 return (MRESULT)(FALSE);
2662
2663 case WM_PAINT:
2664 {
2665 HPS hps;
2666 POINTL ptl[2];
2667 RECTL rcl;
2668
2669 hps = WinBeginPaint(hwnd, 0, 0);
2670
2671 WinQueryWindowRect(hwnd, &rcl);
2672
2673 if(type == BOXHORZ)
2674 {
2675 ptl[0].x = rcl.xLeft + start;
2676 ptl[0].y = rcl.yBottom;
2677 ptl[1].x = rcl.xRight + start + 3;
2678 ptl[1].y = rcl.yTop;
2679 }
2680 else
2681 {
2682 ptl[0].x = rcl.xLeft;
2683 ptl[0].y = rcl.yBottom + start;
2684 ptl[1].x = rcl.xRight;
2685 ptl[1].y = rcl.yTop + start + 3;
2686 }
2687
2688
2689 GpiSetColor(hps, CLR_PALEGRAY);
2690 GpiMove(hps, &ptl[0]);
2691 GpiBox(hps, DRO_OUTLINEFILL, &ptl[1], 0, 0);
2692 WinEndPaint(hps);
2693 }
2694 return MRFROMSHORT(FALSE);
2695
2696 case WM_MOUSEMOVE:
2697 {
2698 if(type == BOXHORZ)
2699 WinSetPointer(HWND_DESKTOP,
2700 WinQuerySysPointer(HWND_DESKTOP,
2701 SPTR_SIZEWE,
2702 FALSE));
2703 else
2704 WinSetPointer(HWND_DESKTOP,
2705 WinQuerySysPointer(HWND_DESKTOP,
2706 SPTR_SIZENS,
2707 FALSE));
2708 }
2709 return MRFROMSHORT(FALSE);
2710 case WM_BUTTON1DOWN:
2711 {
2712 APIRET rc;
2713 RECTL rclFrame;
2714 RECTL rclBounds;
2715
2716 WinQueryWindowRect(hwnd, &rclFrame);
2717 WinQueryWindowRect(hwnd, &rclBounds);
2718
2719 WinMapWindowPoints(hwnd, HWND_DESKTOP,
2720 (PPOINTL)&rclBounds, 2);
2721
2722
2723 if(type == BOXHORZ)
2724 {
2725 rclFrame.xLeft = start;
2726 rclFrame.xRight = start + SPLITBAR_WIDTH;
2727 }
2728 else
2729 {
2730 rclFrame.yBottom = start;
2731 rclFrame.yTop = start + SPLITBAR_WIDTH;
2732 }
2733
2734 if(percent)
2735 {
2736 rc = _TrackRectangle(hwnd, &rclFrame, &rclBounds);
2737
2738 if(rc == TRUE)
2739 {
2740 int width = (rclBounds.xRight - rclBounds.xLeft);
2741 int height = (rclBounds.yTop - rclBounds.yBottom);
2742
2743 if(type == BOXHORZ)
2744 {
2745 start = rclFrame.xLeft - rclBounds.xLeft;
2746 if(width - SPLITBAR_WIDTH > 1 && start < width - SPLITBAR_WIDTH)
2747 *percent = ((float)start / (float)(width - SPLITBAR_WIDTH)) * 100.0;
2748 }
2749 else
2750 {
2751 start = rclFrame.yBottom - rclBounds.yBottom;
2752 if(height - SPLITBAR_WIDTH > 1 && start < height - SPLITBAR_WIDTH)
2753 *percent = 100.0 - (((float)start / (float)(height - SPLITBAR_WIDTH)) * 100.0);
2754 }
2755 _handle_splitbar_resize(hwnd, *percent, type, width, height);
2756 }
2757 }
2758 }
2759 return MRFROMSHORT(FALSE);
2760 }
2761 return WinDefWindowProc(hwnd, msg, mp1, mp2);
2762 }
2763
2764 /* Function: BubbleProc
2765 * Abstract: Subclass procedure for bubble help
2766 */
2767 MRESULT EXPENTRY _BubbleProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2768 {
2769 MRESULT res;
2770 PFNWP proc = (PFNWP)WinQueryWindowPtr(hwnd, QWL_USER);
2771
2772 if(proc)
2773 res = proc(hwnd, msg, mp1, mp2);
2774 else
2775 res = WinDefWindowProc(hwnd, msg, mp1, mp2);
2776
2777 if(msg == WM_PAINT)
2778 {
2779 POINTL ptl;
2780 HPS hpsTemp;
2781 RECTL rcl;
2782 int height, width;
2783
2784 WinQueryWindowRect(hwnd, &rcl);
2785 height = rcl.yTop - rcl.yBottom - 1;
2786 width = rcl.xRight - rcl.xLeft - 1;
2787
2788 /* Draw a border around the bubble help */
2789 hpsTemp = WinGetPS(hwnd);
2790 GpiSetColor(hpsTemp, CLR_BLACK);
2791 ptl.x = ptl.y = 0;
2792 GpiMove(hpsTemp, &ptl);
2793 ptl.x = 0;
2794 ptl.y = height;
2795 GpiLine(hpsTemp, &ptl);
2796 ptl.x = ptl.y = 0;
2797 GpiMove(hpsTemp, &ptl);
2798 ptl.y = 0;
2799 ptl.x = width;
2800 GpiLine(hpsTemp, &ptl);
2801 ptl.x = width;
2802 ptl.y = height;
2803 GpiMove(hpsTemp, &ptl);
2804 ptl.x = 0;
2805 ptl.y = height;
2806 GpiLine(hpsTemp, &ptl);
2807 ptl.x = width;
2808 ptl.y = height;
2809 GpiMove(hpsTemp, &ptl);
2810 ptl.y = 0;
2811 ptl.x = width;
2812 GpiLine(hpsTemp, &ptl);
2813 WinReleasePS(hpsTemp);
2814 }
2815 return res;
2816 }
2817
2818 /* Function: BtProc
2819 * Abstract: Subclass procedure for buttons
2820 */
2821
2822 MRESULT EXPENTRY _BtProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2823 {
2824 BubbleButton *bubble;
2825 PFNWP oldproc;
2826
2827 bubble = (BubbleButton *)WinQueryWindowPtr(hwnd, QWL_USER);
2828
2829 if(!bubble)
2830 return WinDefWindowProc(hwnd, msg, mp1, mp2);
2831
2832 oldproc = bubble->pOldProc;
2833
2834 switch(msg)
2835 {
2836 case WM_SETFOCUS:
2837 if(mp2)
2838 _run_event(hwnd, msg, mp1, mp2);
2839 else
2840 WinSendMsg(hwnd, BM_SETDEFAULT, 0, 0);
2841 break;
2842 case WM_BUTTON1DOWN:
2843 case WM_BUTTON2DOWN:
2844 case WM_BUTTON3DOWN:
2845 case WM_BUTTON1DBLCLK:
2846 case WM_BUTTON2DBLCLK:
2847 case WM_BUTTON3DBLCLK:
2848 if(dw_window_get_data(hwnd, "_dw_disabled"))
2849 return (MRESULT)FALSE;
2850 break;
2851 case WM_BUTTON1UP:
2852 {
2853 SignalHandler *tmp = Root;
2854
2855 if(WinIsWindowEnabled(hwnd) && !dw_window_get_data(hwnd, "_dw_disabled"))
2856 {
2857 /* Find any callbacks for this function */
2858 while(tmp)
2859 {
2860 if(tmp->message == WM_COMMAND)
2861 {
2862 /* Make sure it's the right window, and the right ID */
2863 if(tmp->window == hwnd)
2864 {
2865 /* Due to the fact that if we run the function
2866 * here, finishing actions on the button will occur
2867 * after we run the signal handler. So we post the
2868 * message so the button can finish what it needs to
2869 * do before we run our handler.
2870 */
2871 WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0);
2872 tmp = NULL;
2873 }
2874 }
2875 if(tmp)
2876 tmp= tmp->next;
2877 }
2878 }
2879 }
2880 break;
2881 case WM_USER:
2882 {
2883 SignalHandler *tmp = (SignalHandler *)mp1;
2884 int (* API clickfunc)(HWND, void *) = NULL;
2885
2886 if(tmp)
2887 {
2888 clickfunc = (int (* API)(HWND, void *))tmp->signalfunction;
2889
2890 clickfunc(tmp->window, tmp->data);
2891 }
2892 }
2893 break;
2894 case WM_CHAR:
2895 {
2896 /* A button press should also occur for an ENTER or SPACE press
2897 * while the button has the active input focus.
2898 */
2899 if(SHORT1FROMMP(mp2) == '\r' || SHORT1FROMMP(mp2) == ' ')
2900 {
2901 SignalHandler *tmp = Root;
2902
2903 /* Find any callbacks for this function */
2904 while(tmp)
2905 {
2906 if(tmp->message == WM_COMMAND)
2907 {
2908 /* Make sure it's the right window, and the right ID */
2909 if(tmp->window == hwnd)
2910 {
2911 WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0);
2912 tmp = NULL;
2913 }
2914 }
2915 if(tmp)
2916 tmp= tmp->next;
2917 }
2918 }
2919 if(SHORT1FROMMP(mp2) == '\t')
2920 {
2921 if(CHARMSG(&msg)->fs & KC_SHIFT)
2922 _shift_focus_back(hwnd);
2923 else
2924 _shift_focus(hwnd);
2925 WinSendMsg(hwnd, BM_SETDEFAULT, 0, 0);
2926 return FALSE;
2927 }
2928 else if(!(CHARMSG(&msg)->fs & KC_KEYUP) && (CHARMSG(&msg)->vkey == VK_LEFT || CHARMSG(&msg)->vkey == VK_UP))
2929 {
2930 _shift_focus_back(hwnd);
2931 return FALSE;
2932 }
2933 else if(!(CHARMSG(&msg)->fs & KC_KEYUP) && (CHARMSG(&msg)->vkey == VK_RIGHT || CHARMSG(&msg)->vkey == VK_DOWN))
2934 {
2935 _shift_focus(hwnd);
2936 return FALSE;
2937 }
2938 }
2939 break;
2940 case 0x041f:
2941 if (hwndBubble)
2942 {
2943 WinDestroyWindow(hwndBubble);
2944 hwndBubble = 0;
2945 }
2946 break;
2947
2948 case 0x041e:
2949
2950 if(!*bubble->bubbletext)
2951 break;
2952
2953 if(hwndBubble)
2954 {
2955 WinDestroyWindow(hwndBubble);
2956 hwndBubble = 0;
2957 }
2958
2959 if(!hwndBubble)
2960 {
2961 HPS hpsTemp = 0;
2962 LONG lHight;
2963 LONG lWidth;
2964 POINTL txtPointl[TXTBOX_COUNT];
2965 POINTL ptlWork = {0,0};
2966 ULONG ulColor = CLR_YELLOW;
2967 void *blah;
2968
2969 hwndBubbleLast = hwnd;
2970 hwndBubble = WinCreateWindow(HWND_DESKTOP,
2971 WC_STATIC,
2972 "",
2973 SS_TEXT |
2974 DT_CENTER |
2975 DT_VCENTER,
2976 0,0,0,0,
2977 HWND_DESKTOP,
2978 HWND_TOP,
2979 0,
2980 NULL,
2981 NULL);
2982
2983 WinSetPresParam(hwndBubble,
2984 PP_FONTNAMESIZE,
2985 sizeof(DefaultFont),
2986 DefaultFont);
2987
2988
2989 WinSetPresParam(hwndBubble,
2990 PP_BACKGROUNDCOLORINDEX,
2991 sizeof(ulColor),
2992 &ulColor);
2993
2994 WinSetWindowText(hwndBubble,
2995 bubble->bubbletext);
2996
2997 WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptlWork, 1);
2998
2999 hpsTemp = WinGetPS(hwndBubble);
3000 GpiQueryTextBox(hpsTemp,
3001 strlen(bubble->bubbletext),
3002 bubble->bubbletext,
3003 TXTBOX_COUNT,
3004 txtPointl);
3005 WinReleasePS(hpsTemp);
3006
3007 lWidth = txtPointl[TXTBOX_TOPRIGHT].x -
3008 txtPointl[TXTBOX_TOPLEFT ].x + 8;
3009
3010 lHight = txtPointl[TXTBOX_TOPLEFT].y -
3011 txtPointl[TXTBOX_BOTTOMLEFT].y + 8;
3012
3013 ptlWork.y -= lHight;
3014
3015 blah = (void *)WinSubclassWindow(hwndBubble, _BubbleProc);
3016
3017 if(blah)
3018 WinSetWindowPtr(hwndBubble, QWP_USER, blah);
3019
3020 WinSetWindowPos(hwndBubble,
3021 HWND_TOP,
3022 ptlWork.x,
3023 ptlWork.y,
3024 lWidth,
3025 lHight,
3026 SWP_SIZE | SWP_MOVE | SWP_SHOW);
3027 }
3028 break;
3029 }
3030
3031 if(!oldproc)
3032 return WinDefWindowProc(hwnd, msg, mp1, mp2);
3033 return oldproc(hwnd, msg, mp1, mp2);
3034 }
3035
3036 MRESULT EXPENTRY _RendProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
3037 {
3038 int res = 0;
3039 res = (int)_run_event(hwnd, msg, mp1, mp2);
3040 switch(msg)
3041 {
3042 case WM_BUTTON1DOWN:
3043 case WM_BUTTON2DOWN:
3044 case WM_BUTTON3DOWN:
3045 if(res)
3046 return (MPARAM)TRUE;
3047 }
3048 return WinDefWindowProc(hwnd, msg, mp1, mp2);
3049 }
3050
3051 MRESULT EXPENTRY _TreeProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
3052 {
3053 WindowData *blah = (WindowData *)WinQueryWindowPtr(hwnd, QWP_USER);
3054 PFNWP oldproc = 0;
3055
3056 if(blah)
3057 oldproc = blah->oldproc;
3058
3059 switch(msg)
3060 {
3061 case WM_PAINT:
3062 {
3063 HPS hps;
3064 RECTL rcl;
3065 POINTL ptl[2];
3066
3067 if(oldproc)
3068 oldproc(hwnd, msg, mp1, mp2);
3069
3070 hps = WinBeginPaint(hwnd, 0, 0);
3071 WinQueryWindowRect(hwnd, &rcl);
3072 ptl[0].x = rcl.xLeft + 1;
3073 ptl[0].y = rcl.yBottom + 1;
3074 ptl[1].x = rcl.xRight - 1;
3075 ptl[1].y = rcl.yTop - 1;
3076
3077 GpiSetColor(hps, CLR_BLACK);
3078 GpiMove(hps, &ptl[0]);
3079 GpiBox(hps, DRO_OUTLINE, &ptl[1], 0, 0);
3080 WinEndPaint(hps);
3081 }
3082 return MRFROMSHORT(FALSE);
3083 case WM_SETFOCUS:
3084 _run_event(hwnd, msg, mp1, mp2);
3085 break;
3086 case WM_CHAR:
3087 if(SHORT1FROMMP(mp2) == '\t')
3088 {
3089 if(CHARMSG(&msg)->fs & KC_SHIFT)
3090 _shift_focus_back(hwnd);
3091 else
3092 _shift_focus(hwnd);
3093 return FALSE;
3094 }
3095 break;
3096 }
3097
3098 _run_event(hwnd, msg, mp1, mp2);
3099
3100 if(oldproc)
3101 return oldproc(hwnd, msg, mp1, mp2);
3102
3103 return WinDefWindowProc(hwnd, msg, mp1, mp2);
3104 }
3105
3106 /*
3107 * Initializes the Dynamic Windows engine.
3108 * Parameters:
3109 * newthread: True if this is the only thread.
3110 * False if there is already a message loop running.
3111 */
3112 int API dw_init(int newthread, int argc, char *argv[])
3113 {
3114 APIRET rc;
3115
3116 if(newthread)
3117 {
3118 dwhab = WinInitialize(0);
3119 dwhmq = WinCreateMsgQueue(dwhab, 0);
3120 }
3121
3122 rc = WinRegisterClass(dwhab, ClassName, _wndproc, CS_SIZEREDRAW | CS_CLIPCHILDREN, 32);
3123 rc = WinRegisterClass(dwhab, SplitbarClassName, _splitwndproc, 0L, 32);
3124
3125 /* Get the OS/2 version. */
3126 DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_MS_COUNT,(void *)aulBuffer, 4*sizeof(ULONG));
3127
3128 desktop = WinQueryDesktopWindow(dwhab, NULLHANDLE);
3129
3130 return rc;
3131 }
3132
3133 /*
3134 * Runs a message loop for Dynamic Windows.
3135 */
3136 void API dw_main(void)
3137 {
3138 QMSG qmsg;
3139
3140 _dwtid = dw_thread_id();
3141
3142 while(WinGetMsg(dwhab, &qmsg, 0, 0, 0))
3143 {
3144 if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
3145 _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
3146 WinDispatchMsg(dwhab, &qmsg);
3147 }
3148
3149 WinDestroyMsgQueue(dwhmq);
3150 WinTerminate(dwhab);
3151 }
3152
3153 /*
3154 * Runs a message loop for Dynamic Windows, for a period of milliseconds.
3155 * Parameters:
3156 * milliseconds: Number of milliseconds to run the loop for.
3157 */
3158 void API dw_main_sleep(int milliseconds)
3159 {
3160 QMSG qmsg;
3161 double start = (double)clock();
3162
3163 while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds)
3164 {
3165 if(WinPeekMsg(dwhab, &qmsg, 0, 0, 0, PM_NOREMOVE))
3166 {
3167 WinGetMsg(dwhab, &qmsg, 0, 0, 0);
3168 if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
3169 _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
3170 WinDispatchMsg(dwhab, &qmsg);
3171 }
3172 else
3173 DosSleep(1);
3174 }
3175 }
3176
3177 /*
3178 * Processes a single message iteration and returns.
3179 */
3180 void API dw_main_iteration(void)
3181 {
3182 QMSG qmsg;
3183
3184 _dwtid = dw_thread_id();
3185
3186 if(WinGetMsg(dwhab, &qmsg, 0, 0, 0))
3187 {
3188 if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
3189 _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
3190 WinDispatchMsg(dwhab, &qmsg);
3191 }
3192 }
3193
3194 /*
3195 * Free's memory allocated by dynamic windows.
3196 * Parameters:
3197 * ptr: Pointer to dynamic windows allocated
3198 * memory to be free()'d.
3199 */
3200 void API dw_free(void *ptr)
3201 {
3202 free(ptr);
3203 }
3204
3205 /*
3206 * Allocates and initializes a dialog struct.
3207 * Parameters:
3208 * data: User defined data to be passed to functions.
3209 */
3210 DWDialog * API dw_dialog_new(void *data)
3211 {
3212 DWDialog *tmp = malloc(sizeof(DWDialog));
3213
3214 tmp->eve = dw_event_new();
3215 dw_event_reset(tmp->eve);
3216 tmp->data = data;
3217 tmp->done = FALSE;
3218 tmp->result = NULL;
3219
3220 return tmp;
3221 }
3222
3223 /*
3224 * Accepts a dialog struct and returns the given data to the
3225 * initial called of dw_dialog_wait().
3226 * Parameters:
3227 * dialog: Pointer to a dialog struct aquired by dw_dialog_new).
3228 * result: Data to be returned by dw_dialog_wait().
3229 */
3230 int API dw_dialog_dismiss(DWDialog *dialog, void *result)
3231 {
3232 dialog->result = result;
3233 dw_event_post(dialog->eve);
3234 dialog->done = TRUE;
3235 return 0;
3236 }
3237
3238 /*
3239 * Accepts a dialog struct waits for dw_dialog_dismiss() to be
3240 * called by a signal handler with the given dialog struct.
3241 * Parameters:
3242 * dialog: Pointer to a dialog struct aquired by dw_dialog_new).
3243 */
3244 void * API dw_dialog_wait(DWDialog *dialog)
3245 {
3246 QMSG qmsg;
3247 void *tmp;
3248
3249 while (WinGetMsg(dwhab, &qmsg, 0, 0, 0))
3250 {
3251 if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
3252 _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
3253 WinDispatchMsg(dwhab, &qmsg);
3254 if(dialog->done)
3255 break;
3256 }
3257 dw_event_close(&dialog->eve);
3258 tmp = dialog->result;
3259 free(dialog);
3260 return tmp;
3261 }
3262
3263
3264 /*
3265 * Displays a Message Box with given text and title..
3266 * Parameters:
3267 * title: The title of the message box.
3268 * format: printf style format string.
3269 * ...: Additional variables for use in the format.
3270 */
3271 int API dw_messagebox(char *title, char *format, ...)
3272 {
3273 va_list args;
3274 char outbuf[1024];
3275
3276 va_start(args, format);
3277 vsprintf(outbuf, format, args);
3278 va_end(args);
3279
3280 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, outbuf, title, 0, MB_OK | MB_INFORMATION | MB_MOVEABLE);
3281
3282 return strlen(outbuf);
3283 }
3284
3285 /*
3286 * Displays a Message Box with given text and title..
3287 * Parameters:
3288 * title: The title of the message box.
3289 * text: The text to display in the box.
3290 * Returns:
3291 * True if YES False of NO.
3292 */
3293 int API dw_yesno(char *title, char *text)
3294 {
3295 if(WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, text, title, 0, MB_YESNO | MB_INFORMATION | MB_MOVEABLE | MB_SYSTEMMODAL)==MBID_YES)
3296 return TRUE;
3297 return FALSE;
3298 }
3299
3300 /*
3301 * Makes the window topmost.
3302 * Parameters:
3303 * handle: The window handle to make topmost.
3304 */
3305 int API dw_window_raise(HWND handle)
3306 {
3307 return WinSetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
3308 }
3309
3310 /*
3311 * Makes the window bottommost.
3312 * Parameters:
3313 * handle: The window handle to make bottommost.
3314 */
3315 int API dw_window_lower(HWND handle)
3316 {
3317 return WinSetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER);
3318 }
3319
3320 /*
3321 * Makes the window visible.
3322 * Parameters:
3323 * handle: The window handle to make visible.
3324 */
3325 int API dw_window_show(HWND handle)
3326 {
3327 int rc = WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_SHOW);
3328 HSWITCH hswitch;
3329 SWCNTRL swcntrl;
3330
3331 _fix_button_owner(_toplevel_window(handle), 0);
3332 WinSetFocus(HWND_DESKTOP, handle);
3333 _initial_focus(handle);
3334
3335 /* If this window has a switch list entry make sure it is visible */
3336 hswitch = WinQuerySwitchHandle(handle, 0);
3337 if(hswitch)
3338 {
3339 WinQuerySwitchEntry(hswitch, &swcntrl);
3340 swcntrl.uchVisibility = SWL_VISIBLE;
3341 WinChangeSwitchEntry(hswitch, &swcntrl);
3342 }
3343 if(WinWindowFromID(handle, FID_CLIENT))
3344 {
3345 WindowData *blah = WinQueryWindowPtr(handle, QWP_USER);
3346
3347 if(blah && !(blah->flags & DW_OS2_NEW_WINDOW))
3348 {
3349 ULONG cx = dw_screen_width(), cy = dw_screen_height();
3350 int newx, newy, changed = 0;
3351 SWP swp;
3352
3353 blah->flags |= DW_OS2_NEW_WINDOW;
3354
3355 WinQueryWindowPos(handle, &swp);
3356
3357 newx = swp.x;
3358 newy = swp.y;
3359
3360 if((swp.x+swp.cx) > cx)
3361 {
3362 newx = (cx - swp.cx)/2;
3363 changed = 1;
3364 }
3365 if((swp.y+swp.cy) > cy)
3366 {
3367 newy = (cy - swp.cy)/2;
3368 changed = 1;
3369 }
3370 if(changed)
3371 WinSetWindowPos(handle, NULLHANDLE, newx, newy, 0, 0, SWP_MOVE);
3372 }
3373 }
3374 return rc;
3375 }
3376
3377 /*
3378 * Minimizes or Iconifies a top-level window.
3379 * Parameters:
3380 * handle: The window handle to minimize.
3381 */
3382 int API dw_window_minimize(HWND handle)
3383 {
3384 HWND hwndclient = WinWindowFromID(handle, FID_CLIENT);
3385
3386 if(hwndclient)
3387 {
3388 Box *box = (Box *)WinQueryWindowPtr(hwndclient, QWP_USER);
3389
3390 if(box)
3391 {
3392 if(!box->titlebar && box->hwndtitle)
3393 WinSetParent(box->hwndtitle, handle, FALSE);
3394 }
3395 }
3396
3397 return WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_MINIMIZE);
3398 }
3399
3400 /*
3401 * Makes the window invisible.
3402 * Parameters:
3403 * handle: The window handle to make visible.
3404 */
3405 int API dw_window_hide(HWND handle)
3406 {
3407 HSWITCH hswitch;
3408 SWCNTRL swcntrl;
3409
3410 /* If this window has a switch list entry make sure it is invisible */
3411 hswitch = WinQuerySwitchHandle(handle, 0);
3412 if(hswitch)
3413 {
3414 WinQuerySwitchEntry(hswitch, &swcntrl);
3415 swcntrl.uchVisibility = SWL_INVISIBLE;
3416 WinChangeSwitchEntry(hswitch, &swcntrl);
3417 }
3418 return WinShowWindow(handle, FALSE);
3419 }
3420
3421 /*
3422 * Destroys a window and all of it's children.
3423 * Parameters:
3424 * handle: The window handle to destroy.
3425 */
3426 int API dw_window_destroy(HWND handle)
3427 {
3428 HWND parent = WinQueryWindow(handle, QW_PARENT);
3429 Box *thisbox = WinQueryWindowPtr(parent, QWP_USER);
3430
3431 if(!handle)
3432 return -1;
3433
3434 if(parent != desktop && thisbox && thisbox->count)
3435 {
3436 int z, index = -1;
3437 Item *tmpitem, *thisitem = thisbox->items;
3438
3439 for(z=0;z<thisbox->count;z++)
3440 {
3441 if(thisitem[z].hwnd == handle)
3442 index = z;
3443 }
3444
3445 if(index == -1)
3446 return 0;
3447
3448 tmpitem = malloc(sizeof(Item)*(thisbox->count-1));
3449
3450 /* Copy all but the current entry to the new list */
3451 for(z=0;z<index;z++)
3452 {
3453 tmpitem[z] = thisitem[z];
3454 }
3455 for(z=index+1;z<thisbox->count;z++)
3456 {
3457 tmpitem[z-1] = thisitem[z];
3458 }
3459
3460 thisbox->items = tmpitem;
3461 free(thisitem);
3462 thisbox->count--;
3463 _free_window_memory(handle);
3464 }
3465 return WinDestroyWindow(handle);
3466 }
3467
3468 /* Causes entire window to be invalidated and redrawn.
3469 * Parameters:
3470 * handle: Toplevel window handle to be redrawn.
3471 */
3472 void API dw_window_redraw(HWND handle)
3473 {
3474 HWND client = WinWindowFromID(handle, FID_CLIENT);
3475 HWND window = client ? client : handle;
3476 Box *mybox = (Box *)WinQueryWindowPtr(window, QWP_USER);
3477
3478 if(window && mybox)
3479 {
3480 unsigned long width, height;
3481
3482 dw_window_get_pos_size(window, NULL, NULL, &width, &height);
3483
3484 WinShowWindow(client ? mybox->items[0].hwnd : handle, FALSE);
3485 _do_resize(mybox, width, height);
3486 WinShowWindow(client ? mybox->items[0].hwnd : handle, TRUE);
3487 }
3488 }
3489
3490 /*
3491 * Changes a window's parent to newparent.
3492 * Parameters:
3493 * handle: The window handle to destroy.
3494 * newparent: The window's new parent window.
3495 */
3496 void API dw_window_reparent(HWND handle, HWND newparent)
3497 {
3498 HWND blah = WinWindowFromID(newparent, FID_CLIENT);
3499 WinSetParent(handle, blah ? blah : newparent, TRUE);
3500 }
3501
3502 /*
3503 * Sets the font used by a specified window (widget) handle.
3504 * Parameters:
3505 * handle: The window (widget) handle.
3506 * fontname: Name and size of the font in the form "size.fontname"
3507 */
3508 int API dw_window_set_font(HWND handle, char *fontname)
3509 {
3510 return WinSetPresParam(handle, PP_FONTNAMESIZE, strlen(fontname)+1, fontname);
3511 }
3512
3513 /* Internal version */
3514 int _dw_window_set_color(HWND handle, ULONG fore, ULONG back)
3515 {
3516 if((fore & DW_RGB_COLOR) == DW_RGB_COLOR)
3517 {
3518 RGB2 rgb2;
3519
3520 rgb2.bBlue = DW_BLUE_VALUE(fore);
3521 rgb2.bGreen = DW_GREEN_VALUE(fore);
3522 rgb2.bRed = DW_RED_VALUE(fore);
3523 rgb2.fcOptions = 0;
3524
3525 WinSetPresParam(handle, PP_FOREGROUNDCOLOR, sizeof(RGB2), &rgb2);
3526
3527 }
3528 else if(fore != DW_CLR_DEFAULT)
3529 {
3530 fore = _internal_color(fore);
3531
3532 WinSetPresParam(handle, PP_FOREGROUNDCOLORINDEX, sizeof(ULONG), &fore);
3533 }
3534 if((back & DW_RGB_COLOR) == DW_RGB_COLOR)
3535 {
3536 RGB2 rgb2;
3537
3538 rgb2.bBlue = DW_BLUE_VALUE(back);
3539 rgb2.bGreen = DW_GREEN_VALUE(back);
3540 rgb2.bRed = DW_RED_VALUE(back);
3541 rgb2.fcOptions = 0;
3542
3543 WinSetPresParam(handle, PP_BACKGROUNDCOLOR, sizeof(RGB2), &rgb2);
3544 return 0;
3545 }
3546 else if(back != DW_CLR_DEFAULT)
3547 {
3548 back = _internal_color(back);
3549
3550 WinSetPresParam(handle, PP_BACKGROUNDCOLORINDEX, sizeof(ULONG), &back);
3551 }
3552 return 0;
3553 }
3554 /*
3555 * Sets the colors used by a specified window (widget) handle.
3556 * Parameters:
3557 * handle: The window (widget) handle.
3558 * fore: Foreground color in DW_RGB format or a default color index.
3559 * back: Background color in DW_RGB format or a default color index.
3560 */
3561 int API dw_window_set_color(HWND handle, ULONG fore, ULONG back)
3562 {
3563 dw_window_set_data(handle, "_dw_fore", (void *)(fore+1));
3564 dw_window_set_data(handle, "_dw_back", (void *)(back+1));
3565
3566 return _dw_window_set_color(handle, fore, back);
3567 }
3568
3569 /*
3570 * Sets the font used by a specified window (widget) handle.
3571 * Parameters:
3572 * handle: The window (widget) handle.
3573 * border: Size of the window border in pixels.
3574 */
3575 int API dw_window_set_border(HWND handle, int border)
3576 {
3577 WinSendMsg(handle, WM_SETBORDERSIZE, MPFROMSHORT(border), MPFROMSHORT(border));
3578 return 0;
3579 }
3580
3581 /*
3582 * Captures the mouse input to this window.
3583 * Parameters:
3584 * handle: Handle to receive mouse input.
3585 */
3586 void API dw_window_capture(HWND handle)
3587 {
3588 WinSetCapture(HWND_DESKTOP, handle);
3589 }
3590
3591 /*
3592 * Releases previous mouse capture.
3593 */
3594 void API dw_window_release(void)
3595 {
3596 WinSetCapture(HWND_DESKTOP, NULLHANDLE);
3597 }
3598
3599 /*
3600 * Tracks this window movement.
3601 * Parameters:
3602 * handle: Handle to frame to be tracked.
3603 */
3604 void API dw_window_track(HWND handle)
3605 {
3606 WinSendMsg(handle, WM_TRACKFRAME, MPFROMSHORT(TF_MOVE), 0);
3607 }
3608
3609 /*
3610 * Changes the appearance of the mouse pointer.
3611 * Parameters:
3612 * handle: Handle to widget for which to change.
3613 * cursortype: ID of the pointer you want.
3614 */
3615 void API dw_window_pointer(HWND handle, int pointertype)
3616 {
3617 WinSetPointer(handle,
3618 WinQuerySysPointer(HWND_DESKTOP,
3619 pointertype,
3620 FALSE));
3621 }
3622
3623 /*
3624 * Create a new Window Frame.
3625 * Parameters:
3626 * owner: The Owner's window handle or HWND_DESKTOP.
3627 * title: The Window title.
3628 * flStyle: Style flags, see the PM reference.
3629 */
3630 HWND API dw_window_new(HWND hwndOwner, char *title, ULONG flStyle)
3631 {
3632 HWND hwndclient = 0, hwndframe;
3633 Box *newbox = calloc(1, sizeof(Box));
3634 WindowData *blah = calloc(1, sizeof(WindowData));
3635
3636 newbox->pad = 0;
3637 newbox->type = BOXVERT;
3638 newbox->count = 0;
3639
3640 flStyle |= FCF_NOBYTEALIGN;
3641
3642 if(flStyle & DW_FCF_TITLEBAR)
3643 newbox->titlebar = 1;
3644 else
3645 flStyle |= FCF_TITLEBAR;
3646
3647 if(!(flStyle & FCF_SHELLPOSITION))
3648 blah->flags |= DW_OS2_NEW_WINDOW;
3649
3650 hwndframe = WinCreateStdWindow(hwndOwner, 0L, &flStyle, ClassName, title, 0L, NULLHANDLE, 0L, &hwndclient);
3651 newbox->hwndtitle = WinWindowFromID(hwndframe, FID_TITLEBAR);
3652 if(!newbox->titlebar && newbox->hwndtitle)
3653 WinSetParent(newbox->hwndtitle, HWND_OBJECT, FALSE);
3654 blah->oldproc = WinSubclassWindow(hwndframe, _sizeproc);
3655 WinSetWindowPtr(hwndframe, QWP_USER, blah);
3656 WinSetWindowPtr(hwndclient, QWP_USER, newbox);
3657
3658 return hwndframe;
3659 }
3660
3661 /*
3662 * Create a new Box to be packed.
3663 * Parameters:
3664 * type: Either BOXVERT (vertical) or BOXHORZ (horizontal).
3665 * pad: Number of pixels to pad around the box.
3666 */
3667 HWND API dw_box_new(int type, int pad)
3668 {
3669 Box *newbox = calloc(1, sizeof(Box));
3670 HWND hwndframe;
3671
3672 newbox->pad = pad;
3673 newbox->type = type;
3674 newbox->count = 0;
3675 newbox->grouphwnd = NULLHANDLE;
3676
3677 hwndframe = WinCreateWindow(HWND_OBJECT,
3678 WC_FRAME,
3679 NULL,
3680 WS_VISIBLE | WS_CLIPCHILDREN |
3681 FS_NOBYTEALIGN,
3682 0,0,2000,1000,
3683 NULLHANDLE,
3684 HWND_TOP,
3685 0L,
3686 NULL,
3687 NULL);
3688
3689 newbox->oldproc = WinSubclassWindow(hwndframe, _controlproc);
3690 WinSetWindowPtr(hwndframe, QWP_USER, newbox);
3691 dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
3692 return hwndframe;
3693 }
3694
3695 /*
3696 * Create a new Group Box to be packed.
3697 * Parameters:
3698 * type: Either BOXVERT (vertical) or BOXHORZ (horizontal).
3699 * pad: Number of pixels to pad around the box.
3700 * title: Text to be displayined in the group outline.
3701 */
3702 HWND API dw_groupbox_new(int type, int pad, char *title)
3703 {
3704 Box *newbox = calloc(1, sizeof(Box));
3705 HWND hwndframe;
3706
3707 newbox->pad = pad;
3708 newbox->type = type;
3709 newbox->count = 0;
3710
3711 hwndframe = WinCreateWindow(HWND_OBJECT,
3712 WC_FRAME,
3713 NULL,
3714 WS_VISIBLE |
3715 FS_NOBYTEALIGN,
3716 0,0,2000,1000,
3717 NULLHANDLE,
3718 HWND_TOP,
3719 0L,
3720 NULL,
3721 NULL);
3722
3723 newbox->grouphwnd = WinCreateWindow(hwndframe,
3724 WC_STATIC,
3725 title,
3726 WS_VISIBLE | SS_GROUPBOX |
3727 WS_GROUP,
3728 0,0,2000,1000,
3729 NULLHANDLE,
3730 HWND_TOP,
3731 0L,
3732 NULL,
3733 NULL);
3734
3735 WinSetWindowPtr(hwndframe, QWP_USER, newbox);
3736 dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
3737 dw_window_set_color(newbox->grouphwnd, DW_CLR_BLACK, DW_CLR_PALEGRAY);
3738 dw_window_set_font(newbox->grouphwnd, DefaultFont);
3739 return hwndframe;
3740 }
3741
3742 /*
3743 * Create a new MDI Frame to be packed.
3744 * Parameters:
3745 * id: An ID to be used with dw_window_from_id or 0L.
3746 */
3747 HWND API dw_mdi_new(unsigned long id)
3748 {
3749 HWND hwndframe;
3750
3751 hwndframe = WinCreateWindow(HWND_OBJECT,
3752 WC_FRAME,
3753 NULL,
3754 WS_VISIBLE | WS_CLIPCHILDREN |
3755 FS_NOBYTEALIGN,
3756 0,0,2000,1000,
3757 NULLHANDLE,
3758 HWND_TOP,
3759 0L,
3760 NULL,
3761 NULL);
3762 return hwndframe;
3763 }
3764
3765 /*
3766 * Create a bitmap object to be packed.
3767 * Parameters:
3768 * id: An ID to be used with WinWindowFromID() or 0L.
3769 */
3770 HWND API dw_bitmap_new(ULONG id)
3771 {
3772 return WinCreateWindow(HWND_OBJECT,
3773 WC_STATIC,
3774 NULL,
3775 WS_VISIBLE | SS_TEXT,
3776 0,0,2000,1000,
3777 NULLHANDLE,
3778 HWND_TOP,
3779 id,
3780 NULL,
3781 NULL);
3782 }
3783
3784 /*
3785 * Create a notebook object to be packed.
3786 * Parameters:
3787 * id: An ID to be used for getting the resource from the
3788 * resource file.
3789 */
3790 HWND API dw_notebook_new(ULONG id, int top)
3791 {
3792 ULONG flags;
3793 HWND tmp;
3794
3795 if(top)
3796 flags = BKS_MAJORTABTOP;
3797 else
3798 flags = BKS_MAJORTABBOTTOM;
3799
3800 tmp = WinCreateWindow(HWND_OBJECT,
3801 WC_NOTEBOOK,
3802 NULL,
3803 WS_VISIBLE |
3804 BKS_TABBEDDIALOG |
3805 flags,
3806 0,0,2000,1000,
3807 NULLHANDLE,
3808 HWND_TOP,
3809 id,
3810 NULL,
3811 NULL);
3812
3813 /* Fix tab sizes on Warp 3 */
3814 if(!IS_WARP4())
3815 {
3816 /* best sizes to be determined by trial and error */
3817 WinSendMsg(tmp, BKM_SETDIMENSIONS,MPFROM2SHORT(102, 28), MPFROMSHORT( BKA_MAJORTAB));
3818 }
3819
3820 dw_window_set_font(tmp, DefaultFont);
3821 return tmp;
3822 }
3823
3824 /*
3825 * Create a menu object to be popped up.
3826 * Parameters:
3827 * id: An ID to be used for getting the resource from the
3828 * resource file.
3829 */
3830 HMENUI API dw_menu_new(ULONG id)
3831 {
3832 HMENUI tmp = WinCreateWindow(HWND_OBJECT,
3833 WC_MENU,
3834 NULL,
3835 WS_VISIBLE,
3836 0,0,2000,1000,
3837 NULLHANDLE,
3838 HWND_TOP,
3839 id,
3840 NULL,
3841 NULL);
3842 return tmp;
3843 }
3844
3845 /*
3846 * Create a menubar on a window.
3847 * Parameters:
3848 * location: Handle of a window frame to be attached to.
3849 */
3850 HMENUI API dw_menubar_new(HWND location)
3851 {
3852 HMENUI tmp = WinCreateWindow(location,
3853 WC_MENU,
3854 NULL,
3855 WS_VISIBLE | MS_ACTIONBAR,
3856 0,0,2000,1000,
3857 location,
3858 HWND_TOP,
3859 FID_MENU,
3860 NULL,
3861 NULL);
3862 return tmp;
3863 }
3864
3865 /*
3866 * Destroys a menu created with dw_menubar_new or dw_menu_new.
3867 * Parameters:
3868 * menu: Handle of a menu.
3869 */
3870 void API dw_menu_destroy(HMENUI *menu)
3871 {
3872 if(menu)
3873 WinDestroyWindow(*menu);
3874 }
3875
3876 /*
3877 * Adds a menuitem or submenu to an existing menu.
3878 * Parameters:
3879 * menu: The handle the the existing menu.
3880 * title: The title text on the menu item to be added.
3881 * id: An ID to be used for message passing.
3882 * flags: Extended attributes to set on the menu.
3883 * end: If TRUE memu is positioned at the end of the menu.
3884 * check: If TRUE menu is "check"able.
3885 * submenu: Handle to an existing menu to be a submenu or NULL.
3886 */
3887 HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu)
3888 {
3889 MENUITEM miSubMenu;
3890
3891 if(!menux)
3892 return NULLHANDLE;
3893
3894 if(end)
3895 miSubMenu.iPosition=MIT_END;
3896 else
3897 miSubMenu.iPosition=0;
3898
3899 if(strlen(title) == 0)
3900 miSubMenu.afStyle=MIS_SEPARATOR | flags;
3901 else
3902 miSubMenu.afStyle=MIS_TEXT | flags;
3903 miSubMenu.afAttribute=0;
3904 miSubMenu.id=id;
3905 miSubMenu.hwndSubMenu = submenu;
3906 miSubMenu.hItem=NULLHANDLE;
3907
3908 WinSendMsg(menux,
3909 MM_INSERTITEM,
3910 MPFROMP(&miSubMenu),
3911 MPFROMP(title));
3912 return (HWND)id;
3913 }
3914
3915 /*
3916 * Sets the state of a menu item check.
3917 * Parameters:
3918 * menu: The handle the the existing menu.
3919 * id: Menuitem id.
3920 * check: TRUE for checked FALSE for not checked.
3921 */
3922 void API dw_menu_item_set_check(HMENUI menux, unsigned long id, int check)
3923 {
3924 if(check)
3925 WinSendMsg(menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE),
3926 MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED));
3927 else
3928 WinSendMsg(menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE),
3929 MPFROM2SHORT(MIA_CHECKED, 0));
3930 }
3931
3932 /*
3933 * Pops up a context menu at given x and y coordinates.
3934 * Parameters:
3935 * menu: The handle the the existing menu.
3936 * parent: Handle to the window initiating the popup.
3937 * x: X coordinate.
3938 * y: Y coordinate.
3939 */
3940 void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y)
3941 {
3942 if(menu)
3943 {
3944 popup = parent;
3945 WinPopupMenu(HWND_DESKTOP, parent, *menu, x, dw_screen_height() - y, 0, PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_VCONSTRAIN | PU_HCONSTRAIN);
3946 }
3947 }
3948
3949 /*
3950 * Returns the current X and Y coordinates of the mouse pointer.
3951 * Parameters:
3952 * x: Pointer to variable to store X coordinate.
3953 * y: Pointer to variable to store Y coordinate.
3954 */
3955 void API dw_pointer_query_pos(long *x, long *y)
3956 {
3957 POINTL ptl;
3958
3959 WinQueryPointerPos(HWND_DESKTOP, &ptl);
3960 if(x && y)
3961 {
3962 *x = ptl.x;
3963 *y = dw_screen_height() - ptl.y;
3964 }
3965 }
3966
3967 /*
3968 * Sets the X and Y coordinates of the mouse pointer.
3969 * Parameters:
3970 * x: X coordinate.
3971 * y: Y coordinate.
3972 */
3973 void API dw_pointer_set_pos(long x, long y)
3974 {
3975 WinSetPointerPos(HWND_DESKTOP, x, dw_screen_height() - y);
3976 }
3977
3978 /*
3979 * Create a container object to be packed.
3980 * Parameters:
3981 * id: An ID to be used for getting the resource from the
3982 * resource file.
3983 */
3984 HWND API dw_container_new(ULONG id)
3985 {
3986 WindowData *blah = calloc(1, sizeof(WindowData));
3987 HWND tmp = WinCreateWindow(HWND_OBJECT,
3988 WC_CONTAINER,
3989 NULL,
3990 WS_VISIBLE | CCS_READONLY |
3991 CCS_SINGLESEL | CCS_AUTOPOSITION,
3992 0,0,2000,1000,
3993 NULLHANDLE,
3994 HWND_TOP,
3995 id,
3996 NULL,
3997 NULL);
3998 blah->oldproc = WinSubclassWindow(tmp, _TreeProc);
3999 WinSetWindowPtr(tmp, QWP_USER, blah);
4000 dw_window_set_font(tmp, DefaultFont);
4001 dw_window_set_data(tmp, "_dw_container", (void *)1);
4002 return tmp;
4003 }
4004
4005 /*
4006 * Create a tree object to be packed.
4007 * Parameters:
4008 * id: An ID to be used for getting the resource from the
4009 * resource file.
4010 */
4011 HWND API dw_tree_new(ULONG id)
4012 {
4013 CNRINFO cnrinfo;
4014 WindowData *blah = calloc(1, sizeof(WindowData));
4015 HWND tmp = WinCreateWindow(HWND_OBJECT,
4016 WC_CONTAINER,
4017 NULL,
4018 WS_VISIBLE | CCS_READONLY |
4019 CCS_SINGLESEL | CCS_AUTOPOSITION,
4020 0,0,2000,1000,
4021 NULLHANDLE,
4022 HWND_TOP,
4023 id,
4024 NULL,
4025 NULL);
4026
4027 cnrinfo.flWindowAttr = CV_TREE | CA_TREELINE;
4028 cnrinfo.slBitmapOrIcon.cx = 16;
4029 cnrinfo.slBitmapOrIcon.cy = 16;
4030 cnrinfo.cyLineSpacing = 0;
4031 cnrinfo.cxTreeIndent = 16;
4032 cnrinfo.cxTreeLine = 1;
4033
4034 WinSendMsg(tmp, CM_SETCNRINFO, &cnrinfo, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON |
4035 CMA_LINESPACING | CMA_CXTREEINDENT | CMA_CXTREELINE));
4036 blah->oldproc = WinSubclassWindow(tmp, _TreeProc);
4037 WinSetWindowPtr(tmp, QWP_USER, blah);
4038 dw_window_set_font(tmp, DefaultFont);
4039 return tmp;
4040 }
4041
4042 /*
4043 * Create a new static text window (widget) to be packed.
4044 * Parameters:
4045 * text: The text to be display by the static text widget.
4046 * id: An ID to be used with WinWindowFromID() or 0L.
4047 */
4048 HWND API dw_text_new(char *text, ULONG id)
4049 {
4050 HWND tmp = WinCreateWindow(HWND_OBJECT,
4051 WC_STATIC,
4052 text,
4053 WS_VISIBLE | SS_TEXT,
4054 0,0,2000,1000,
4055 NULLHANDLE,
4056 HWND_TOP,
4057 id,
4058 NULL,
4059 NULL);
4060 dw_window_set_font(tmp, DefaultFont);
4061 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
4062 return tmp;
4063 }
4064
4065 /*
4066 * Create a new status text window (widget) to be packed.
4067 * Parameters:
4068 * text: The text to be display by the static text widget.
4069 * id: An ID to be used with WinWindowFromID() or 0L.
4070 */
4071 HWND API dw_status_text_new(char *text, ULONG id)
4072 {
4073 WindowData *blah = calloc(sizeof(WindowData), 1);
4074 HWND tmp = WinCreateWindow(HWND_OBJECT,
4075 WC_STATIC,
4076 text,
4077 WS_VISIBLE | SS_TEXT,
4078 0,0,2000,1000,
4079 NULLHANDLE,
4080 HWND_TOP,
4081 id,
4082 NULL,
4083 NULL);
4084 blah->oldproc = WinSubclassWindow(tmp, _statusproc);
4085 WinSetWindowPtr(tmp, QWP_USER, blah);
4086 dw_window_set_font(tmp, DefaultFont);
4087 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
4088 return tmp;
4089 }
4090
4091 #ifndef MLS_LIMITVSCROLL
4092 #define MLS_LIMITVSCROLL 0x00000080L
4093 #endif
4094
4095 /*
4096 * Create a new Multiline Editbox window (widget) to be packed.
4097 * Parameters:
4098 * id: An ID to be used with WinWindowFromID() or 0L.
4099 */
4100 HWND API dw_mle_new(ULONG id)
4101 {
4102 WindowData *blah = calloc(1, sizeof(WindowData));
4103 HWND tmp = WinCreateWindow(HWND_OBJECT,
4104 WC_MLE,
4105 "",
4106 WS_VISIBLE |
4107 MLS_BORDER | MLS_IGNORETAB |
4108 MLS_READONLY | MLS_VSCROLL |
4109 MLS_LIMITVSCROLL,
4110 0,0,2000,1000,
4111 NULLHANDLE,
4112 HWND_TOP,
4113 id,
4114 NULL,
4115 NULL);
4116 blah->oldproc = WinSubclassWindow(tmp, _mleproc);
4117 WinSetWindowPtr(tmp, QWP_USER, blah);
4118 dw_window_set_font(tmp, DefaultFont);
4119 return tmp;
4120 }
4121
4122 /*
4123 * Create a new Entryfield window (widget) to be packed.
4124 * Parameters:
4125 * text: The default text to be in the entryfield widget.
4126 * id: An ID to be used with WinWindowFromID() or 0L.
4127 */
4128 HWND API dw_entryfield_new(char *text, ULONG id)
4129 {
4130
4131 WindowData *blah = calloc(1, sizeof(WindowData));
4132 HWND tmp = WinCreateWindow(HWND_OBJECT,
4133 WC_ENTRYFIELD,
4134 text,
4135 WS_VISIBLE | ES_MARGIN |
4136 ES_AUTOSCROLL | WS_TABSTOP,
4137 0,0,2000,1000,
4138 NULLHANDLE,
4139 HWND_TOP,
4140 id,
4141 NULL,
4142 NULL);
4143 blah->oldproc = WinSubclassWindow(tmp, _entryproc);
4144 WinSetWindowPtr(tmp, QWP_USER, blah);
4145 dw_window_set_font(tmp, DefaultFont);
4146 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
4147 return tmp;
4148 }
4149
4150 /*
4151 * Create a new Entryfield (password) window (widget) to be packed.
4152 * Parameters:
4153 * text: The default text to be in the entryfield widget.
4154 * id: An ID to be used with WinWindowFromID() or 0L.
4155 */
4156 HWND API dw_entryfield_password_new(char *text, ULONG id)
4157 {
4158 WindowData *blah = calloc(1, sizeof(WindowData));
4159 HWND tmp = WinCreateWindow(HWND_OBJECT,
4160 WC_ENTRYFIELD,
4161 text,
4162 WS_VISIBLE | ES_MARGIN | ES_UNREADABLE |
4163 ES_AUTOSCROLL | WS_TABSTOP,
4164 0,0,2000,1000,
4165 NULLHANDLE,
4166 HWND_TOP,
4167 id,
4168 NULL,
4169 NULL);
4170 blah->oldproc = WinSubclassWindow(tmp, _entryproc);
4171 WinSetWindowPtr(tmp, QWP_USER, blah);
4172 dw_window_set_font(tmp, DefaultFont);
4173 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
4174 return tmp;
4175 }
4176
4177 /*
4178 * Create a new Combobox window (widget) to be packed.
4179 * Parameters:
4180 * text: The default text to be in the combpbox widget.
4181 * id: An ID to be used with WinWindowFromID() or 0L.
4182 */
4183 HWND API dw_combobox_new(char *text, ULONG id)
4184 {
4185 WindowData *blah = calloc(1, sizeof(WindowData));
4186 HWND tmp = WinCreateWindow(HWND_OBJECT,
4187 WC_COMBOBOX,
4188 text,
4189 WS_VISIBLE | CBS_DROPDOWN | WS_GROUP,
4190 0,0,2000,1000,
4191 NULLHANDLE,
4192 HWND_TOP,
4193 id,
4194 NULL,
4195 NULL);
4196 HENUM henum = WinBeginEnumWindows(tmp);
4197 HWND child;
4198
4199 while((child = WinGetNextWindow(henum)) != NULLHANDLE)
4200 {
4201 WindowData *moreblah = calloc(1, sizeof(WindowData));
4202 moreblah->oldproc = WinSubclassWindow(child, _comboentryproc);
4203 WinSetWindowPtr(child, QWP_USER, moreblah);
4204 dw_window_set_color(child, DW_CLR_BLACK, DW_CLR_WHITE);
4205 }
4206 WinEndEnumWindows(henum);
4207 blah->oldproc = WinSubclassWindow(tmp, _comboproc);
4208 WinSetWindowPtr(tmp, QWP_USER, blah);
4209 dw_window_set_font(tmp, DefaultFont);
4210 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
4211 return tmp;
4212 }
4213
4214 /*
4215 * Create a new button window (widget) to be packed.
4216 * Parameters:
4217 * text: The text to be display by the static text widget.
4218 * id: An ID to be used with WinWindowFromID() or 0L.
4219 */
4220 HWND API dw_button_new(char *text, ULONG id)
4221 {
4222 BubbleButton *bubble = calloc(sizeof(BubbleButton), 1);
4223
4224 HWND tmp = WinCreateWindow(HWND_OBJECT,
4225 WC_BUTTON,
4226 text,
4227 WS_VISIBLE,
4228 0,0,2000,1000,
4229 NULLHANDLE,
4230 HWND_TOP,
4231 id,
4232 NULL,
4233 NULL);
4234
4235 bubble->id = id;
4236 bubble->bubbletext[0] = '\0';
4237 bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
4238
4239 WinSetWindowPtr(tmp, QWP_USER, bubble);
4240 dw_window_set_font(tmp, DefaultFont);
4241 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
4242 return tmp;
4243 }
4244
4245 /* Function: GenResIDStr
4246 ** Abstract: Generate string '#nnnn' for a given ID for using with Button
4247 ** controls
4248 */
4249
4250 void _GenResIDStr(CHAR *buff, ULONG ulID)
4251 {
4252 char *str;
4253 int slen = 0;
4254
4255 *buff++ = '#';
4256
4257 str = buff;
4258
4259 do
4260 {
4261 *str++ = (ulID % 10) + '0';
4262 ulID /= 10;
4263 slen++;
4264 }
4265 while(ulID);
4266
4267 *str-- = 0;
4268
4269 for(; str > buff; str--, buff++)
4270 {
4271 *buff ^= *str;
4272 *str ^= *buff;
4273 *buff ^= *str;
4274 }
4275 }
4276
4277
4278 /*
4279 * Create a new bitmap button window (widget) to be packed.
4280 * Parameters:
4281 * text: Bubble help text to be displayed.
4282 * id: An ID of a bitmap in the resource file.
4283 */
4284 HWND API dw_bitmapbutton_new(char *text, ULONG id)
4285 {
4286 char idbuf[256];
4287 HWND tmp;
4288 BubbleButton *bubble = calloc(sizeof(BubbleButton), 1);
4289
4290 _GenResIDStr(idbuf, id);
4291
4292 tmp = WinCreateWindow(HWND_OBJECT,
4293 WC_BUTTON,
4294 idbuf,
4295 WS_VISIBLE | BS_PUSHBUTTON |
4296 BS_BITMAP | BS_AUTOSIZE |
4297 BS_NOPOINTERFOCUS,
4298 0,0,2000,1000,
4299 NULLHANDLE,
4300 HWND_TOP,
4301 id,
4302 NULL,
4303 NULL);
4304
4305 bubble->id = id;
4306 strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1);
4307 bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0';
4308 bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
4309
4310 WinSetWindowPtr(tmp, QWP_USER, bubble);
4311 return tmp;
4312 }
4313
4314 /*
4315 * Create a new spinbutton window (widget) to be packed.
4316 * Parameters:
4317 * text: The text to be display by the static text widget.
4318 * id: An ID to be used with WinWindowFromID() or 0L.
4319 */
4320 HWND API dw_spinbutton_new(char *text, ULONG id)
4321 {
4322 WindowData *blah = calloc(sizeof(WindowData), 1);
4323 HWND tmp = WinCreateWindow(HWND_OBJECT,
4324 WC_SPINBUTTON,
4325 text,
4326 WS_VISIBLE | SPBS_MASTER,
4327 0,0,2000,1000,
4328 NULLHANDLE,
4329 HWND_TOP,
4330 id,
4331 NULL,
4332 NULL);
4333 HWND entry = _find_entryfield(tmp);
4334 blah->oldproc = WinSubclassWindow(tmp, _entryproc);
4335 WinSetWindowPtr(tmp, QWP_USER, blah);
4336 blah = calloc(sizeof(WindowData), 1);
4337 blah->oldproc = WinSubclassWindow(entry, _spinentryproc);
4338 WinSetWindowPtr(entry, QWP_USER, blah);
4339 dw_window_set_font(tmp, DefaultFont);
4340 dw_window_set_color(entry, DW_CLR_BLACK, DW_CLR_WHITE);
4341 return tmp;
4342 }
4343
4344 /*
4345 * Create a new radiobutton window (widget) to be packed.
4346 * Parameters:
4347 * text: The text to be display by the static text widget.
4348 * id: An ID to be used with WinWindowFromID() or 0L.
4349 */
4350 HWND API dw_radiobutton_new(char *text, ULONG id)
4351 {
4352 WindowData *blah = calloc(sizeof(WindowData), 1);
4353 HWND tmp = WinCreateWindow(HWND_OBJECT,
4354 WC_BUTTON,
4355 text,
4356 WS_VISIBLE |
4357 BS_AUTORADIOBUTTON,
4358 0,0,2000,1000,
4359 NULLHANDLE,
4360 HWND_TOP,
4361 id,
4362 NULL,
4363 NULL);
4364 blah->oldproc = WinSubclassWindow(tmp, _entryproc);
4365 WinSetWindowPtr(tmp, QWP_USER, blah);
4366 dw_window_set_font(tmp, DefaultFont);
4367 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
4368 return tmp;
4369 }
4370
4371
4372 /*
4373 * Create a new slider window (widget) to be packed.
4374 * Parameters:
4375 * vertical: TRUE or FALSE if slider is vertical.
4376 * increments: Number of increments available.
4377 * id: An ID to be used with WinWindowFromID() or 0L.
4378 */
4379 HWND API dw_slider_new(int vertical, int increments, ULONG id)
4380 {
4381 WindowData *blah = calloc(1, sizeof(WindowData));
4382 SLDCDATA sldcData = { 0, 0, 0, 0, 0 };
4383 HWND tmp;
4384
4385 sldcData.cbSize = sizeof(SLDCDATA);
4386 sldcData.usScale1Increments = increments;
4387
4388 tmp = WinCreateWindow(HWND_OBJECT,
4389 WC_SLIDER,
4390 "",
4391 WS_VISIBLE | SLS_SNAPTOINCREMENT |
4392 (vertical ? SLS_VERTICAL : SLS_HORIZONTAL),
4393 0,0,2000,1000,
4394 NULLHANDLE,
4395 HWND_TOP,
4396 id,
4397 &sldcData,
4398 NULL);
4399
4400 blah->oldproc = WinSubclassWindow(tmp, _entryproc);
4401 WinSetWindowPtr(tmp, QWP_USER, blah);
4402 return tmp;
4403 }
4404
4405 /*
4406 * Create a new scrollbar window (widget) to be packed.
4407 * Parameters:
4408 * vertical: TRUE or FALSE if scrollbar is vertical.
4409 * increments: Number of increments available.
4410 * id: An ID to be used with WinWindowFromID() or 0L.
4411 */
4412 HWND API dw_scrollbar_new(int vertical, int increments, ULONG id)
4413 {
4414 return WinCreateWindow(HWND_OBJECT,
4415 WC_SCROLLBAR,
4416 "",
4417 WS_VISIBLE | SBS_AUTOTRACK |
4418 (vertical ? SBS_VERT : SBS_HORZ),
4419 0,0,2000,1000,
4420 NULLHANDLE,
4421 HWND_TOP,
4422 id,
4423 NULL,
4424 NULL);
4425 }
4426
4427 /*
4428 * Create a new percent bar window (widget) to be packed.
4429 * Parameters:
4430 * id: An ID to be used with WinWindowFromID() or 0L.
4431 */
4432 HWND API dw_percent_new(ULONG id)
4433 {
4434 WindowData *blah = calloc(1, sizeof(WindowData));
4435 HWND tmp = WinCreateWindow(HWND_OBJECT,
4436 WC_SLIDER,
4437 "",
4438 WS_VISIBLE | SLS_READONLY
4439 | SLS_RIBBONSTRIP,
4440 0,0,2000,1000,
4441 NULLHANDLE,
4442 HWND_TOP,
4443 id,
4444 NULL,
4445 NULL);
4446 blah->oldproc = WinSubclassWindow(tmp, _percentproc);
4447 WinSetWindowPtr(tmp, QWP_USER, blah);
4448 dw_window_disable(tmp);
4449 return tmp;
4450 }
4451
4452 /*
4453 * Create a new checkbox window (widget) to be packed.
4454 * Parameters:
4455 * text: The text to be display by the static text widget.
4456 * id: An ID to be used with WinWindowFromID() or 0L.
4457 */
4458 HWND API dw_checkbox_new(char *text, ULONG id)
4459 {
4460 BubbleButton *bubble = calloc(sizeof(BubbleButton), 1);
4461 HWND tmp = WinCreateWindow(HWND_OBJECT,
4462 WC_BUTTON,
4463 text,
4464 WS_VISIBLE | BS_AUTOCHECKBOX,
4465 0,0,2000,1000,
4466 NULLHANDLE,
4467 HWND_TOP,
4468 id,
4469 NULL,
4470 NULL);
4471 bubble->id = id;
4472 bubble->bubbletext[0] = '\0';
4473 bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
4474 WinSetWindowPtr(tmp, QWP_USER, bubble);
4475 dw_window_set_font(tmp, DefaultFont);
4476 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
4477 return tmp;
4478 }
4479
4480 /*
4481 * Create a new listbox window (widget) to be packed.
4482 * Parameters:
4483 * id: An ID to be used with WinWindowFromID() or 0L.
4484 * multi: Multiple select TRUE or FALSE.
4485 */
4486 HWND API dw_listbox_new(ULONG id, int multi)
4487 {
4488 WindowData *blah = calloc(sizeof(WindowData), 1);
4489 HWND tmp = WinCreateWindow(HWND_OBJECT,
4490 WC_LISTBOX,
4491 NULL,
4492 WS_VISIBLE | LS_NOADJUSTPOS |
4493 (multi ? LS_MULTIPLESEL : 0),
4494 0,0,2000,1000,
4495 NULLHANDLE,
4496 HWND_TOP,
4497 id,
4498 NULL,
4499 NULL);
4500 blah->oldproc = WinSubclassWindow(tmp, _entryproc);
4501 WinSetWindowPtr(tmp, QWP_USER, blah);
4502 dw_window_set_font(tmp, DefaultFont);
4503 dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
4504 return tmp;
4505 }
4506
4507 /*
4508 * Sets the icon used for a given window.
4509 * Parameters:
4510 * handle: Handle to the window.
4511 * id: An ID to be used to specify the icon.
4512 */
4513 void API dw_window_set_icon(HWND handle, ULONG id)
4514 {
4515 HPOINTER icon;
4516
4517 icon = WinLoadPointer(HWND_DESKTOP,NULLHANDLE,id);
4518 WinSendMsg(handle, WM_SETICON, (MPARAM)icon, 0);
4519 }
4520
4521 /*
4522 * Sets the bitmap used for a given static window.
4523 * Parameters:
4524 * handle: Handle to the window.
4525 * id: An ID to be used to specify the icon.
4526 */
4527 void API dw_window_set_bitmap(HWND handle, ULONG id)
4528 {
4529 HBITMAP hbm;
4530 HPS hps = WinGetPS(handle);
4531
4532 hbm = GpiLoadBitmap(hps, NULLHANDLE, id, 0, 0);
4533 WinSetWindowBits(handle,QWL_STYLE,SS_BITMAP,SS_BITMAP | 0x7f);
4534 WinSendMsg( handle, SM_SETHANDLE, MPFROMP(hbm), NULL );
4535 WinReleasePS(hps);
4536 dw_window_set_data(handle, "_dw_bitmap", (void *)hbm);
4537 }
4538
4539 /*
4540 * Sets the text used for a given window.
4541 * Parameters:
4542 * handle: Handle to the window.
4543 * text: The text associsated with a given window.
4544 */
4545 void API dw_window_set_text(HWND handle, char *text)
4546 {
4547 WinSetWindowText(handle, text);
4548 }
4549
4550 /*
4551 * Gets the text used for a given window.
4552 * Parameters:
4553 * handle: Handle to the window.
4554 * Returns:
4555 * text: The text associsated with a given window.
4556 */
4557 char * API dw_window_get_text(HWND handle)
4558 {
4559 int len = WinQueryWindowTextLength(handle);
4560 char *tempbuf = calloc(1, len + 2);
4561
4562 WinQueryWindowText(handle, len + 1, tempbuf);
4563
4564 return tempbuf;
4565 }
4566
4567 /*
4568 * Disables given window (widget).
4569 * Parameters:
4570 * handle: Handle to the window.
4571 */
4572 void API dw_window_disable(HWND handle)
4573 {
4574 char tmpbuf[100];
4575
4576 if(dw_window_get_data(handle, "_dw_disabled"))
4577 return;
4578
4579 WinQueryClassName(handle, 99, tmpbuf);
4580 dw_window_set_data(handle, "_dw_disabled", (void *)1);
4581
4582 if(tmpbuf[0] == '#')
4583 {
4584 int val = atoi(&tmpbuf[1]);
4585 HWND hwnd;
4586
4587 switch(val)
4588 {
4589 case 2:
4590 case 6:
4591 case 10:
4592 case 32:
4593 case 7:
4594 hwnd = _find_entryfield(handle);
4595 _dw_window_set_color(hwnd ? hwnd : handle, DW_CLR_BLACK, DW_CLR_PALEGRAY);
4596 dw_signal_connect(hwnd ? hwnd : handle, "key_press_event", DW_SIGNAL_FUNC(_null_key), (void *)100);
4597 if(val == 2)
4598 dw_signal_connect(handle, "button_press_event", DW_SIGNAL_FUNC(_null_key), (void *)100);
4599 if(hwnd)
4600 dw_window_set_data(hwnd, "_dw_disabled", (void *)1);
4601 return;
4602 case 3:
4603 _dw_window_set_color(handle, DW_CLR_DARKGRAY, DW_CLR_PALEGRAY);
4604 dw_signal_connect(handle, "key_press_event", DW_SIGNAL_FUNC(_null_key), (void *)100);
4605 dw_signal_connect(handle, "button_press_event", DW_SIGNAL_FUNC(_null_key), (void *)100);
4606 return;
4607 }
4608 }
4609 WinEnableWindow(handle, FALSE);
4610 }
4611
4612 /*
4613 * Enables given window (widget).
4614 * Parameters:
4615 * handle: Handle to the window.
4616 */
4617 void API dw_window_enable(HWND handle)
4618 {
4619 ULONG fore = (ULONG)dw_window_get_data(handle, "_dw_fore");
4620 ULONG back = (ULONG)dw_window_get_data(handle, "_dw_back");
4621 HWND hwnd = _find_entryfield(handle);
4622
4623 dw_window_set_data(handle, "_dw_disabled", 0);
4624 if(hwnd)
4625 dw_window_set_data(hwnd, "_dw_disabled", 0);
4626 if(fore && back)
4627 _dw_window_set_color(hwnd ? hwnd : handle, fore-1, back-1);
4628 dw_signal_disconnect_by_data(handle, (void *)100);
4629 WinEnableWindow(handle, TRUE);
4630 }
4631
4632 /*
4633 * Gets the child window handle with specified ID.
4634 * Parameters:
4635 * handle: Handle to the parent window.
4636 * id: Integer ID of the child.
4637 */
4638 HWND API dw_window_from_id(HWND handle, int id)
4639 {
4640 HENUM henum;
4641 HWND child;
4642 char tmpbuf[100];
4643
4644 henum = WinBeginEnumWindows(handle);
4645 while((child = WinGetNextWindow(henum)) != NULLHANDLE)
4646 {
4647 int windowid = WinQueryWindowUShort(child, QWS_ID);
4648 HWND found;
4649
4650 WinQueryClassName(child, 99, tmpbuf);
4651
4652 /* If the child is a box (frame) then recurse into it */
4653 if(strncmp(tmpbuf, "#1", 3)==0)
4654 if((found = dw_window_from_id(child, id)) != NULLHANDLE)
4655 return found;
4656
4657 if(windowid && windowid == id)
4658 {
4659 WinEndEnumWindows(henum);
4660 return child;
4661 }
4662 }
4663 WinEndEnumWindows(henum);
4664 return NULLHANDLE;
4665 }
4666
4667 /*
4668 * Pack windows (widgets) into a box from the end (or bottom).
4669 * Parameters:
4670 * box: Window handle of the box to be packed into.
4671 * item: Window handle of the item to be back.
4672 * width: Width in pixels of the item or -1 to be self determined.
4673 * height: Height in pixels of the item or -1 to be self determined.
4674 * hsize: TRUE if the window (widget) should expand horizontally to fill space given.
4675 * vsize: TRUE if the window (widget) should expand vertically to fill space given.
4676 * pad: Number of pixels of padding around the item.
4677 */
4678 void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
4679 {
4680 Box *thisbox;
4681
4682 if(WinWindowFromID(box, FID_CLIENT))
4683 {
4684 box = WinWindowFromID(box, FID_CLIENT);
4685 thisbox = WinQueryWindowPtr(box, QWP_USER);
4686 }
4687 else
4688 thisbox = WinQueryWindowPtr(box, QWP_USER);
4689 if(thisbox)
4690 {
4691 if(thisbox->type == BOXHORZ)
4692 dw_box_pack_start_stub(box, item, width, height, hsize, vsize, pad);
4693 else
4694 dw_box_pack_end_stub(box, item, width, height, hsize, vsize, pad);
4695 }
4696 }
4697
4698 void dw_box_pack_end_stub(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
4699 {
4700 Box *thisbox;
4701
4702 if(WinWindowFromID(box, FID_CLIENT))
4703 {
4704 box = WinWindowFromID(box, FID_CLIENT);
4705 thisbox = WinQueryWindowPtr(box, QWP_USER);
4706 hsize = TRUE;
4707 vsize = TRUE;
4708 }
4709 else
4710 thisbox = WinQueryWindowPtr(box, QWP_USER);
4711 if(!thisbox)
4712 {
4713 box = WinWindowFromID(box, FID_CLIENT);
4714 if(box)
4715 {
4716 thisbox = WinQueryWindowPtr(box, QWP_USER);
4717 hsize = TRUE;
4718 vsize = TRUE;
4719 }
4720 }
4721 if(thisbox)
4722 {
4723 int z;
4724 Item *tmpitem, *thisitem = thisbox->items;
4725 char tmpbuf[100];
4726
4727 tmpitem = malloc(sizeof(Item)*(thisbox->count+1));
4728
4729 for(z=0;z<thisbox->count;z++)
4730 {
4731 tmpitem[z] = thisitem[z];
4732 }
4733
4734 WinQueryClassName(item, 99, tmpbuf);
4735
4736 if(strncmp(tmpbuf, "#1", 3)==0)
4737 tmpitem[thisbox->count].type = TYPEBOX;
4738 else
4739 tmpitem[thisbox->count].type = TYPEITEM;
4740
4741 tmpitem[thisbox->count].hwnd = item;
4742 tmpitem[thisbox->count].origwidth = tmpitem[thisbox->count].width = width;
4743 tmpitem[thisbox->count].origheight = tmpitem[thisbox->count].height = height;
4744 tmpitem[thisbox->count].pad = pad;
4745 if(hsize)
4746 tmpitem[thisbox->count].hsize = SIZEEXPAND;
4747 else
4748 tmpitem[thisbox->count].hsize = SIZESTATIC;
4749
4750 if(vsize)
4751 tmpitem[thisbox->count].vsize = SIZEEXPAND;
4752 else
4753 tmpitem[thisbox->count].vsize = SIZESTATIC;
4754
4755 thisbox->items = tmpitem;
4756
4757 if(thisbox->count)
4758 free(thisitem);
4759
4760 thisbox->count++;
4761
4762 /* Don't set the ownership if it's an entryfield or spinbutton */
4763 WinQueryClassName(item, 99, tmpbuf);
4764 if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0)
4765 WinSetOwner(item, box);
4766 WinSetParent(item, box, FALSE);
4767 }
4768 }
4769
4770 /*
4771 * Sets the size of a given window (widget).
4772 * Parameters:
4773 * handle: Window (widget) handle.
4774 * width: New width in pixels.
4775 * height: New height in pixels.
4776 */
4777 void API dw_window_set_usize(HWND handle, ULONG width, ULONG height)
4778 {
4779 WinSetWindowPos(handle, NULLHANDLE, 0, 0, width, height, SWP_SHOW | SWP_SIZE);
4780 }
4781
4782 /*
4783 * Returns the width of the screen.
4784 */
4785 int API dw_screen_width(void)
4786 {
4787 return WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN);
4788 }
4789
4790 /*
4791 * Returns the height of the screen.
4792 */
4793 int API dw_screen_height(void)
4794 {
4795 return WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN);
4796 }
4797
4798 /* This should return the current color depth */
4799 unsigned long API dw_color_depth(void)
4800 {
4801 HDC hdc = WinOpenWindowDC(HWND_DESKTOP);
4802 long colors;
4803
4804 DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, &colors);
4805 DevCloseDC(hdc);
4806 return colors;
4807 }
4808
4809
4810 /*
4811 * Sets the position of a given window (widget).
4812 * Parameters:
4813 * handle: Window (widget) handle.
4814 * x: X location from the bottom left.
4815 * y: Y location from the bottom left.
4816 */
4817 void API dw_window_set_pos(HWND handle, ULONG x, ULONG y)
4818 {
4819 int myy = _get_frame_height(handle) - (y + _get_height(handle));
4820
4821 WinSetWindowPos(handle, NULLHANDLE, x, myy, 0, 0, SWP_MOVE);
4822 }
4823
4824 /*
4825 * Sets the position and size of a given window (widget).
4826 * Parameters:
4827 * handle: Window (widget) handle.
4828 * x: X location from the bottom left.
4829 * y: Y location from the bottom left.
4830 * width: Width of the widget.
4831 * height: Height of the widget.
4832 */
4833 void API dw_window_set_pos_size(HWND handle, ULONG x, ULONG y, ULONG width, ULONG height)
4834 {
4835 int myy = _get_frame_height(handle) - (y + height);
4836
4837 WinSetWindowPos(handle, NULLHANDLE, x, myy, width, height, SWP_MOVE | SWP_SIZE | SWP_SHOW);
4838 }
4839
4840 /*
4841 * Gets the position and size of a given window (widget).
4842 * Parameters:
4843 * handle: Window (widget) handle.
4844 * x: X location from the bottom left.
4845 * y: Y location from the bottom left.
4846 * width: Width of the widget.
4847 * height: Height of the widget.
4848 */
4849 void API dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height)
4850 {
4851 SWP swp;
4852 WinQueryWindowPos(handle, &swp);
4853 if(x)
4854 *x = swp.x;
4855 if(y)
4856 *y = _get_frame_height(handle) - (swp.y + swp.cy);
4857 if(width)
4858 *width = swp.cx;
4859 if(height)
4860 *height = swp.cy;
4861 }
4862
4863 /*
4864 * Sets the style of a given window (widget).
4865 * Parameters:
4866 * handle: Window (widget) handle.
4867 * width: New width in pixels.
4868 * height: New height in pixels.
4869 */
4870 void API dw_window_set_style(HWND handle, ULONG style, ULONG mask)
4871 {
4872 WinSetWindowBits(handle, QWL_STYLE, style, mask);
4873 }
4874
4875 /*
4876 * Adds a new page to specified notebook.
4877 * Parameters:
4878 * handle: Window (widget) handle.
4879 * flags: Any additional page creation flags.
4880 * front: If TRUE page is added at the beginning.
4881 */
4882 unsigned long API dw_notebook_page_new(HWND handle, ULONG flags, int front)
4883 {
4884 if(front)
4885 return (ULONG)WinSendMsg(handle, BKM_INSERTPAGE, 0L,
4886 MPFROM2SHORT((BKA_STATUSTEXTON | BKA_AUTOPAGESIZE | BKA_MAJOR | flags), BKA_FIRST));
4887 return (ULONG)WinSendMsg(handle, BKM_INSERTPAGE, 0L,
4888 MPFROM2SHORT((BKA_STATUSTEXTON | BKA_AUTOPAGESIZE | BKA_MAJOR | flags), BKA_LAST));
4889 }
4890
4891 /*
4892 * Remove a page from a notebook.
4893 * Parameters:
4894 * handle: Handle to the notebook widget.
4895 * pageid: ID of the page to be destroyed.
4896 */
4897 void API dw_notebook_page_destroy(HWND handle, unsigned int pageid)
4898 {
4899 WinSendMsg(handle, BKM_DELETEPAGE,
4900 MPFROMLONG(pageid), (MPARAM)BKA_SINGLE);
4901 }
4902
4903 /*
4904 * Queries the currently visible page ID.
4905 * Parameters:
4906 * handle: Handle to the notebook widget.
4907 */
4908 unsigned int API dw_notebook_page_query(HWND handle)
4909 {
4910 return (int)WinSendMsg(handle, BKM_QUERYPAGEID,0L, MPFROM2SHORT(BKA_TOP, BKA_MAJOR));
4911 }
4912
4913 /*
4914 * Sets the currently visibale page ID.
4915 * Parameters:
4916 * handle: Handle to the notebook widget.
4917 * pageid: ID of the page to be made visible.
4918 */
4919 void API dw_notebook_page_set(HWND handle, unsigned int pageid)
4920 {
4921 WinSendMsg(handle, BKM_TURNTOPAGE, MPFROMLONG(pageid), 0L);
4922 }
4923
4924 /*
4925 * Sets the text on the specified notebook tab.
4926 * Parameters:
4927 * handle: Notebook handle.
4928 * pageid: Page ID of the tab to set.
4929 * text: Pointer to the text to set.
4930 */
4931 void API dw_notebook_page_set_text(HWND handle, ULONG pageid, char *text)
4932 {
4933 WinSendMsg(handle, BKM_SETTABTEXT,
4934 MPFROMLONG(pageid), MPFROMP(text));
4935 }
4936
4937 /*
4938 * Sets the text on the specified notebook tab status area.
4939 * Parameters:
4940 * handle: Notebook handle.
4941 * pageid: Page ID of the tab to set.
4942 * text: Pointer to the text to set.
4943 */
4944 void API dw_notebook_page_set_status_text(HWND handle, ULONG pageid, char *text)
4945 {
4946 WinSendMsg(handle, BKM_SETSTATUSLINETEXT,
4947 MPFROMLONG(pageid), MPFROMP(text));
4948 }
4949
4950 /*
4951 * Packs the specified box into the notebook page.
4952 * Parameters:
4953 * handle: Handle to the notebook to be packed.
4954 * pageid: Page ID in the notebook which is being packed.
4955 * page: Box handle to be packed.
4956 */
4957 void API dw_notebook_pack(HWND handle, ULONG pageid, HWND page)
4958 {
4959 HWND tmpbox = dw_box_new(BOXVERT, 0);
4960
4961 dw_box_pack_start(tmpbox, page, 0, 0, TRUE, TRUE, 0);
4962 WinSubclassWindow(tmpbox, _wndproc);
4963 WinSendMsg(handle, BKM_SETPAGEWINDOWHWND,
4964 MPFROMLONG(pageid), MPFROMHWND(tmpbox));
4965 }
4966
4967 /*
4968 * Appends the specified text to the listbox's (or combobox) entry list.
4969 * Parameters:
4970 * handle: Handle to the listbox to be appended to.
4971 * text: Text to append into listbox.
4972 */
4973 void API dw_listbox_append(HWND handle, char *text)
4974 {
4975 WinSendMsg(handle,
4976 LM_INSERTITEM,
4977 MPFROMSHORT(LIT_END),
4978 MPFROMP(text));
4979 }
4980
4981 /*
4982 * Clears the listbox's (or combobox) list of all entries.
4983 * Parameters:
4984 * handle: Handle to the listbox to be cleared.
4985 */
4986 void API dw_listbox_clear(HWND handle)
4987 {
4988 WinSendMsg(handle,
4989 LM_DELETEALL, 0L, 0L);
4990 }
4991
4992 /*
4993 * Returns the listbox's item count.
4994 * Parameters:
4995 * handle: Handle to the listbox to be cleared.
4996 */
4997 int API dw_listbox_count(HWND handle)
4998 {
4999 return (int)WinSendMsg(handle,
5000 LM_QUERYITEMCOUNT,0L, 0L);
5001 }
5002
5003 /*
5004 * Sets the topmost item in the viewport.
5005 * Parameters:
5006 * handle: Handle to the listbox to be cleared.
5007 * top: Index to the top item.
5008 */
5009 void API dw_listbox_set_top(HWND handle, int top)
5010 {
5011 WinSendMsg(handle,
5012 LM_SETTOPINDEX,
5013 MPFROMSHORT(top),
5014 0L);
5015 }
5016
5017 /*
5018 * Copies the given index item's text into buffer.
5019 * Parameters:
5020 * handle: Handle to the listbox to be queried.
5021 * index: Index into the list to be queried.
5022 * buffer: Buffer where text will be copied.
5023 * length: Length of the buffer (including NULL).
5024 */
5025 void API dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length)
5026 {
5027 WinSendMsg(handle, LM_QUERYITEMTEXT, MPFROM2SHORT(index, length), (MPARAM)buffer);
5028 }
5029
5030 /*
5031 * Sets the text of a given listbox entry.
5032 * Parameters:
5033 * handle: Handle to the listbox to be queried.
5034 * index: Index into the list to be queried.
5035 * buffer: Buffer where text will be copied.
5036 */
5037 void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer)
5038 {
5039 WinSendMsg(handle, LM_SETITEMTEXT, MPFROMSHORT(index), (MPARAM)buffer);
5040 }
5041
5042 /*
5043 * Returns the index to the item in the list currently selected.
5044 * Parameters:
5045 * handle: Handle to the listbox to be queried.
5046 */
5047 unsigned int API dw_listbox_selected(HWND handle)
5048 {
5049 return (unsigned int)WinSendMsg(handle,
5050 LM_QUERYSELECTION,
5051 MPFROMSHORT(LIT_CURSOR),
5052 0);
5053 }
5054
5055 /*
5056 * Returns the index to the current selected item or -1 when done.
5057 * Parameters:
5058 * handle: Handle to the listbox to be queried.
5059 * where: Either the previous return or -1 to restart.
5060 */
5061 int API dw_listbox_selected_multi(HWND handle, int where)
5062 {
5063 int place = where;
5064
5065 if(where == -1)
5066 place = LIT_FIRST;
5067
5068 place = (int)WinSendMsg(handle,
5069 LM_QUERYSELECTION,
5070 MPFROMSHORT(place),0L);
5071 if(place == LIT_NONE)
5072 return -1;
5073 return place;
5074 }
5075
5076 /*
5077 * Sets the selection state of a given index.
5078 * Parameters:
5079 * handle: Handle to the listbox to be set.
5080 * index: Item index.
5081 * state: TRUE if selected FALSE if unselected.
5082 */
5083 void API dw_listbox_select(HWND handle, int index, int state)
5084 {
5085 char tmpbuf[100];
5086
5087 WinSendMsg(handle, LM_SELECTITEM, MPFROMSHORT(index), (MPARAM)state);
5088
5089 WinQueryClassName(handle, 99, tmpbuf);
5090
5091 /* If we are setting a combobox call the event handler manually */
5092 if(strncmp(tmpbuf, "#6", 3)==0)
5093 _run_event(handle, WM_CONTROL, MPFROM2SHORT(0, LN_SELECT), (MPARAM)handle);
5094 }
5095
5096 /*
5097 * Deletes the item with given index from the list.
5098 * Parameters:
5099 * handle: Handle to the listbox to be set.
5100 * index: Item index.
5101 */
5102 void API dw_listbox_delete(HWND handle, int index)
5103 {
5104 WinSendMsg(handle, LM_DELETEITEM, MPFROMSHORT(index), 0);
5105 }
5106
5107 /*
5108 * Adds text to an MLE box and returns the current point.
5109 * Parameters:
5110 * handle: Handle to the MLE to be queried.
5111 * buffer: Text buffer to be imported.
5112 * startpoint: Point to start entering text.
5113 */
5114 unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint)
5115 {
5116 unsigned long point = startpoint;
5117 PBYTE mlebuf;
5118
5119 /* Work around 64K limit */
5120 if(!DosAllocMem((PPVOID) &mlebuf, 65536, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE))
5121 {
5122 int amount, len = strlen(buffer), written = 0;
5123
5124 while(written < len)
5125 {
5126 if((len - written) > 65535)
5127 amount = 65535;
5128 else
5129 amount = len - written;
5130
5131 memcpy(mlebuf, &buffer[written], amount);
5132 mlebuf[amount] = '\0';
5133
5134 WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount+1));
5135 WinSendMsg(handle, MLM_IMPORT, MPFROMP(&point), MPFROMLONG(amount + 1));
5136 dw_mle_delete(handle, point, 1);
5137
5138 written += amount;
5139 }
5140 DosFreeMem(mlebuf);
5141 }
5142 return point - 1;
5143 }
5144
5145 /*
5146 * Grabs text from an MLE box.
5147 * Parameters:
5148 * handle: Handle to the MLE to be queried.
5149 * buffer: Text buffer to be exported.
5150 * startpoint: Point to start grabbing text.
5151 * length: Amount of text to be grabbed.
5152 */
5153 void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length)
5154 {
5155 PBYTE mlebuf;
5156
5157 /* Work around 64K limit */
5158 if(!DosAllocMem((PPVOID) &mlebuf, 65535, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE))
5159 {
5160 int amount, copied, written = 0;
5161
5162 while(written < length)
5163 {
5164 if((length - written) > 65535)
5165 amount = 65535;
5166 else
5167 amount = length - written;
5168
5169 WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount));
5170 copied = (int)WinSendMsg(handle, MLM_EXPORT, MPFROMP(&startpoint), MPFROMLONG(&amount));
5171
5172 if(copied)
5173 {
5174 memcpy(&buffer[written], mlebuf, copied);
5175
5176 written += copied;
5177 }
5178 else
5179 break;
5180 }
5181 DosFreeMem(mlebuf);
5182 }
5183 }
5184
5185 /*
5186 * Obtains information about an MLE box.
5187 * Parameters:
5188 * handle: Handle to the MLE to be queried.
5189 * bytes: A pointer to a variable to return the total bytes.
5190 * lines: A pointer to a variable to return the number of lines.
5191 */
5192 void API dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines)
5193 {
5194 if(bytes)
5195 *bytes = (unsigned long)WinSendMsg(handle, MLM_QUERYTEXTLENGTH, 0, 0);
5196 if(lines)
5197 *lines = (unsigned long)WinSendMsg(handle, MLM_QUERYLINECOUNT, 0, 0);
5198 }
5199
5200 /*
5201 * Deletes text from an MLE box.
5202 * Parameters:
5203 * handle: Handle to the MLE to be deleted from.
5204 * startpoint: Point to start deleting text.
5205 * length: Amount of text to be deleted.
5206 */
5207 void API dw_mle_delete(HWND handle, int startpoint, int length)
5208 {
5209 char *buf = malloc(length+1);
5210 int z, dellen = length;
5211
5212 dw_mle_export(handle, buf, startpoint, length);
5213
5214 for(z=0;z<length-1;z++)
5215 {
5216 if(strncmp(&buf[z], "\r\n", 2) == 0)
5217 dellen--;
5218 }
5219 WinSendMsg(handle, MLM_DELETE, MPFROMLONG(startpoint), MPFROMLONG(dellen));
5220 free(buf);
5221 }
5222
5223 /*
5224 * Clears all text from an MLE box.
5225 * Parameters:
5226 * handle: Handle to the MLE to be cleared.
5227 */
5228 void API dw_mle_clear(HWND handle)
5229 {
5230 unsigned long bytes;
5231
5232 dw_mle_query(handle, &bytes, NULL);
5233
5234 WinSendMsg(handle, MLM_DELETE, MPFROMLONG(0), MPFROMLONG(bytes));
5235 }
5236
5237 /*
5238 * Sets the visible line of an MLE box.
5239 * Parameters:
5240 * handle: Handle to the MLE to be positioned.
5241 * line: Line to be visible.
5242 */
5243 void API dw_mle_set_visible(HWND handle, int line)
5244 {
5245 int tmppnt = (int)WinSendMsg(handle, MLM_CHARFROMLINE, MPFROMLONG(line), 0);
5246 WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(tmppnt), MPFROMLONG(tmppnt));
5247 }
5248
5249 /*
5250 * Sets the editablity of an MLE box.
5251 * Parameters:
5252 * handle: Handle to the MLE.
5253 * state: TRUE if it can be edited, FALSE for readonly.
5254 */
5255 void API dw_mle_set_editable(HWND handle, int state)
5256 {
5257 WinSendMsg(handle, MLM_SETREADONLY, MPFROMLONG(state ? FALSE : TRUE), 0);
5258 }
5259
5260 /*
5261 * Sets the word wrap state of an MLE box.
5262 * Parameters:
5263 * handle: Handle to the MLE.
5264 * state: TRUE if it wraps, FALSE if it doesn't.
5265 */
5266 void API dw_mle_set_word_wrap(HWND handle, int state)
5267 {
5268 WinSendMsg(handle, MLM_SETWRAP, MPFROMLONG(state), 0);
5269 }
5270
5271 /*
5272 * Sets the current cursor position of an MLE box.
5273 * Parameters:
5274 * handle: Handle to the MLE to be positioned.
5275 * point: Point to position cursor.
5276 */
5277 void API dw_mle_set(HWND handle, int point)
5278 {
5279 WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(point), MPFROMLONG(point));
5280 }
5281
5282 /*
5283 * Finds text in an MLE box.
5284 * Parameters:
5285 * handle: Handle to the MLE to be cleared.
5286 * text: Text to search for.
5287 * point: Start point of search.
5288 * flags: Search specific flags.
5289 */
5290 int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags)
5291 {
5292 MLE_SEARCHDATA msd;
5293
5294 /* This code breaks with structure packing set to 1 (/Sp1 in VAC)
5295 * if this is needed we need to add a pragma here.
5296 */
5297 msd.cb = sizeof(msd);
5298 msd.pchFind = text;
5299 msd.pchReplace = NULL;
5300 msd.cchFind = strlen(text);
5301 msd.cchReplace = 0;
5302 msd.iptStart = point;
5303 msd.iptStop = -1;
5304
5305 if(WinSendMsg(handle, MLM_SEARCH, MPFROMLONG(MLFSEARCH_SELECTMATCH | flags), (MPARAM)&msd))
5306 return (int)WinSendMsg(handle, MLM_QUERYSEL,(MPARAM)MLFQS_MAXSEL, 0);
5307 return 0;
5308 }
5309
5310 /*
5311 * Stops redrawing of an MLE box.
5312 * Parameters:
5313 * handle: Handle to the MLE to freeze.
5314 */
5315 void API dw_mle_freeze(HWND handle)
5316 {
5317 WinSendMsg(handle, MLM_DISABLEREFRESH, 0, 0);
5318 }
5319
5320 /*
5321 * Resumes redrawing of an MLE box.
5322 * Parameters:
5323 * handle: Handle to the MLE to thaw.
5324 */
5325 void API dw_mle_thaw(HWND handle)
5326 {
5327 WinSendMsg(handle, MLM_ENABLEREFRESH, 0, 0);
5328 }
5329
5330 /*
5331 * Returns the range of the percent bar.
5332 * Parameters:
5333 * handle: Handle to the percent bar to be queried.
5334 */
5335 unsigned int API dw_percent_query_range(HWND handle)
5336 {
5337 return SHORT2FROMMP(WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), 0));
5338 }
5339
5340 /*
5341 * Sets the percent bar position.
5342 * Parameters:
5343 * handle: Handle to the percent bar to be set.
5344 * position: Position of the percent bar withing the range.
5345 */
5346 void API dw_percent_set_pos(HWND handle, unsigned int position)
5347 {
5348 _dw_int_set(handle, position);
5349 WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)position);
5350 }
5351
5352 /*
5353 * Returns the position of the slider.
5354 * Parameters:
5355 * handle: Handle to the slider to be queried.
5356 */
5357 unsigned int API dw_slider_query_pos(HWND handle)
5358 {
5359 return (unsigned int)WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0);
5360 }
5361
5362 /*
5363 * Sets the slider position.
5364 * Parameters:
5365 * handle: Handle to the slider to be set.
5366 * position: Position of the slider withing the range.
5367 */
5368 void API dw_slider_set_pos(HWND handle, unsigned int position)
5369 {
5370 dw_window_set_data(handle, "_dw_slider_value", (void *)position);
5371 WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)position);
5372 }
5373
5374 /*
5375 * Returns the position of the scrollbar.
5376 * Parameters:
5377 * handle: Handle to the scrollbar to be queried.
5378 */
5379 unsigned int API dw_scrollbar_query_pos(HWND handle)
5380 {
5381 return (unsigned int)WinSendMsg(handle, SBM_QUERYPOS, 0, 0);
5382 }
5383
5384 /*
5385 * Sets the scrollbar position.
5386 * Parameters:
5387 * handle: Handle to the scrollbar to be set.
5388 * position: Position of the scrollbar withing the range.
5389 */
5390 void API dw_scrollbar_set_pos(HWND handle, unsigned int position)
5391 {
5392 dw_window_set_data(handle, "_dw_scrollbar_value", (void *)position);
5393 WinSendMsg(handle, SBM_SETPOS, (MPARAM)position, 0);
5394 }
5395
5396 /*
5397 * Sets the scrollbar range.
5398 * Parameters:
5399 * handle: Handle to the scrollbar to be set.
5400 * range: Maximum range value.
5401 * visible: Visible area relative to the range.
5402 */
5403 void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible)
5404 {
5405 unsigned int pos = (unsigned int)dw_window_get_data(handle, "_dw_scrollbar_value");
5406 WinSendMsg(handle, SBM_SETSCROLLBAR, (MPARAM)pos, MPFROM2SHORT(0, (unsigned short)range - visible));
5407 WinSendMsg(handle, SBM_SETTHUMBSIZE, MPFROM2SHORT((unsigned short)visible, range), 0);
5408 dw_window_set_data(handle, "_dw_scrollbar_visible", (void *)visible);
5409 }
5410
5411 /*
5412 * Sets the spinbutton value.
5413 * Parameters:
5414 * handle: Handle to the spinbutton to be set.
5415 * position: Current value of the spinbutton.
5416 */
5417 void API dw_spinbutton_set_pos(HWND handle, long position)
5418 {
5419 WinSendMsg(handle, SPBM_SETCURRENTVALUE, MPFROMLONG((long)position), 0L);
5420 }
5421
5422 /*
5423 * Sets the spinbutton limits.
5424 * Parameters:
5425 * handle: Handle to the spinbutton to be set.
5426 * upper: Upper limit.
5427 * lower: Lower limit.
5428 */
5429 void API dw_spinbutton_set_limits(HWND handle, long upper, long lower)
5430 {
5431 WinSendMsg(handle, SPBM_SETLIMITS, MPFROMLONG(upper), MPFROMLONG(lower));
5432 }
5433
5434 /*
5435 * Sets the entryfield character limit.
5436 * Parameters:
5437 * handle: Handle to the spinbutton to be set.
5438 * limit: Number of characters the entryfield will take.
5439 */
5440 void API dw_entryfield_set_limit(HWND handle, ULONG limit)
5441 {
5442 WinSendMsg(handle, EM_SETTEXTLIMIT, (MPARAM)limit, (MPARAM)0);
5443 }
5444
5445
5446 /*
5447 * Returns the current value of the spinbutton.
5448 * Parameters:
5449 * handle: Handle to the spinbutton to be queried.
5450 */
5451 long API dw_spinbutton_query(HWND handle)
5452 {
5453 long tmpval = 0L;
5454
5455 WinSendMsg(handle, SPBM_QUERYVALUE, (MPARAM)&tmpval,0L);
5456 return tmpval;
5457 }
5458
5459 /*
5460 * Returns the state of the checkbox.
5461 * Parameters:
5462 * handle: Handle to the checkbox to be queried.
5463 */
5464 int API dw_checkbox_query(HWND handle)
5465 {
5466 return (int)WinSendMsg(handle,BM_QUERYCHECK,0,0);
5467 }
5468
5469 /*
5470 * Sets the state of the checkbox.
5471 * Parameters:
5472 * handle: Handle to the checkbox to be queried.
5473 * value: TRUE for checked, FALSE for unchecked.
5474 */
5475 void API dw_checkbox_set(HWND handle, int value)
5476 {
5477 WinSendMsg(handle,BM_SETCHECK,MPFROMSHORT(value),0);
5478 }
5479
5480 /*
5481 * Inserts an item into a tree window (widget) after another item.
5482 * Parameters:
5483 * handle: Handle to the tree to be inserted.
5484 * item: Handle to the item to be positioned after.
5485 * title: The text title of the entry.
5486 * icon: Handle to coresponding icon.
5487 * parent: Parent handle or 0 if root.
5488 * itemdata: Item specific data.
5489 */
5490 HWND API dw_tree_insert_after(HWND handle, HWND item, char *title, unsigned long icon, HWND parent, void *itemdata)
5491 {
5492 ULONG cbExtra;
5493 PCNRITEM pci;
5494 RECORDINSERT ri;
5495
5496 if(!item)
5497 item = CMA_FIRST;
5498
5499 /* Calculate extra bytes needed for each record besides that needed for the
5500 * MINIRECORDCORE structure
5501 */
5502
5503 cbExtra = sizeof(CNRITEM) - sizeof(MINIRECORDCORE);
5504
5505 /* Allocate memory for the parent record */
5506
5507 pci = WinSendMsg(handle, CM_ALLOCRECORD, MPFROMLONG(cbExtra), MPFROMSHORT(1));
5508
5509 /* Fill in the parent record data */
5510
5511 pci->rc.cb = sizeof(MINIRECORDCORE);
5512 pci->rc.pszIcon = strdup(title);
5513 pci->rc.hptrIcon = icon;
5514
5515 pci->hptrIcon = icon;
5516 pci->user = itemdata;
5517
5518 memset(&ri, 0, sizeof(RECORDINSERT));
5519
5520 ri.cb = sizeof(RECORDINSERT);
5521 ri.pRecordOrder = (PRECORDCORE)item;
5522 ri.pRecordParent = (PRECORDCORE)NULL;
5523 ri.zOrder = (USHORT)CMA_TOP;
5524 ri.cRecordsInsert = 1;
5525 ri.fInvalidateRecord = TRUE;
5526
5527 /* We are about to insert the child records. Set the parent record to be
5528 * the one we just inserted.
5529 */
5530 ri.pRecordParent = (PRECORDCORE)parent;
5531
5532 /* Insert the record */
5533 WinSendMsg(handle, CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri));
5534
5535 return (HWND)pci;
5536 }
5537
5538 /*
5539 * Inserts an item into a tree window (widget).
5540 * Parameters:
5541 * handle: Handle to the tree to be inserted.
5542 * title: The text title of the entry.
5543 * icon: Handle to coresponding icon.
5544 * parent: Parent handle or 0 if root.
5545 * itemdata: Item specific data.
5546 */
5547 HWND API dw_tree_insert(HWND handle, char *title, unsigned long icon, HWND parent, void *itemdata)
5548 {
5549 return dw_tree_insert_after(handle, (HWND)CMA_END, title, icon, parent, itemdata);
5550 }
5551
5552 /*
5553 * Sets the text and icon of an item in a tree window (widget).
5554 * Parameters:
5555 * handle: Handle to the tree containing the item.
5556 * item: Handle of the item to be modified.
5557 * title: The text title of the entry.
5558 * icon: Handle to coresponding icon.
5559 */
5560 void API dw_tree_set(HWND handle, HWND item, char *title, unsigned long icon)
5561 {
5562 PCNRITEM pci = (PCNRITEM)item;
5563
5564 if(!pci)
5565 return;
5566
5567 if(pci->rc.pszIcon)
5568 free(pci->rc.pszIcon);
5569
5570 pci->rc.pszIcon = strdup(title);
5571 pci->rc.hptrIcon = icon;
5572
5573 pci->hptrIcon = icon;
5574
5575 WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_TEXTCHANGED));
5576 }
5577
5578 /*
5579 * Sets the item data of a tree item.
5580 * Parameters:
5581 * handle: Handle to the tree containing the item.
5582 * item: Handle of the item to be modified.
5583 * itemdata: User defined data to be associated with item.
5584 */
5585 void API dw_tree_set_data(HWND handle, HWND item, void *itemdata)
5586 {
5587 PCNRITEM pci = (PCNRITEM)item;
5588
5589 if(!pci)
5590 return;
5591
5592 pci->user = itemdata;
5593 }
5594
5595 /*
5596 * Sets this item as the active selection.
5597 * Parameters:
5598 * handle: Handle to the tree window (widget) to be selected.
5599 * item: Handle to the item to be selected.
5600 */
5601 void API dw_tree_item_select(HWND handle, HWND item)
5602 {
5603 PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
5604
5605 while(pCore)
5606 {
5607 if(pCore->flRecordAttr & CRA_SELECTED)
5608 WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)pCore, MPFROM2SHORT(FALSE, CRA_SELECTED | CRA_CURSORED));
5609 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
5610 }
5611 WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)item, MPFROM2SHORT(TRUE, CRA_SELECTED | CRA_CURSORED));
5612 lastitem = 0;
5613 lasthcnr = 0;
5614 }
5615
5616 /*
5617 * Removes all nodes from a tree.
5618 * Parameters:
5619 * handle: Handle to the window (widget) to be cleared.
5620 */
5621 void API dw_tree_clear(HWND handle)
5622 {
5623 WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)0L, MPFROM2SHORT(0, CMA_INVALIDATE | CMA_FREE));
5624 }
5625
5626 /*
5627 * Expands a node on a tree.
5628 * Parameters:
5629 * handle: Handle to the tree window (widget).
5630 * item: Handle to node to be expanded.
5631 */
5632 void API dw_tree_expand(HWND handle, HWND item)
5633 {
5634 WinSendMsg(handle, CM_EXPANDTREE, MPFROMP(item), 0);
5635 }
5636
5637 /*
5638 * Collapses a node on a tree.
5639 * Parameters:
5640 * handle: Handle to the tree window (widget).
5641 * item: Handle to node to be collapsed.
5642 */
5643 void API dw_tree_collapse(HWND handle, HWND item)
5644 {
5645 WinSendMsg(handle, CM_COLLAPSETREE, MPFROMP(item), 0);
5646 }
5647
5648 /*
5649 * Removes a node from a tree.
5650 * Parameters:
5651 * handle: Handle to the window (widget) to be cleared.
5652 * item: Handle to node to be deleted.
5653 */
5654 void API dw_tree_delete(HWND handle, HWND item)
5655 {
5656 PCNRITEM pci = (PCNRITEM)item;
5657
5658 if(!item)
5659 return;
5660
5661 if(pci->rc.pszIcon)
5662 {
5663 free(pci->rc.pszIcon);
5664 pci->rc.pszIcon = 0;
5665 }
5666
5667 WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_INVALIDATE | CMA_FREE));
5668 }
5669
5670 /* Some OS/2 specific container structs */
5671 typedef struct _containerinfo {
5672 int count;
5673 void *data;
5674 HWND handle;
5675 } ContainerInfo;
5676
5677 /*
5678 * Sets up the container columns.
5679 * Parameters:
5680 * handle: Handle to the container to be configured.
5681 * flags: An array of unsigned longs with column flags.
5682 * titles: An array of strings with column text titles.
5683 * count: The number of columns (this should match the arrays).
5684 * separator: The column number that contains the main separator.
5685 * (this item may only be used in OS/2)
5686 */
5687 int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator)
5688 {
5689 PFIELDINFO details, first, left = NULL;
5690 FIELDINFOINSERT detin;
5691 CNRINFO cnri;
5692 int z;
5693 ULONG size = sizeof(RECORDCORE);
5694 ULONG *offStruct = malloc(count * sizeof(ULONG));
5695 ULONG *tempflags = malloc((count+1) * sizeof(ULONG));
5696 WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
5697 ULONG *oldflags = blah ? blah->data : 0;
5698
5699 if(!offStruct || !tempflags)
5700 return FALSE;
5701
5702 memcpy(tempflags, flags, count * sizeof(ULONG));
5703 tempflags[count] = 0;
5704
5705 blah->data = tempflags;
5706 blah->flags = separator;
5707
5708 if(oldflags)
5709 free(oldflags);
5710
5711 while((first = (PFIELDINFO)WinSendMsg(handle, CM_QUERYDETAILFIELDINFO, 0, MPFROMSHORT(CMA_FIRST))) != NULL)
5712 {
5713 WinSendMsg(handle, CM_REMOVEDETAILFIELDINFO, (MPARAM)&first, MPFROM2SHORT(1, CMA_FREE));
5714 }
5715
5716 /* Figure out the offsets to the items in the struct */
5717 for(z=0;z<count;z++)
5718 {
5719 offStruct[z] = size;
5720 if(flags[z] & DW_CFA_BITMAPORICON)
5721 size += sizeof(HPOINTER);
5722 else if(flags[z] & DW_CFA_STRING)
5723 size += sizeof(char *);
5724 else if(flags[z] & DW_CFA_ULONG)
5725 size += sizeof(ULONG);
5726 else if(flags[z] & DW_CFA_DATE)
5727 size += sizeof(CDATE);
5728 else if(flags[z] & DW_CFA_TIME)
5729 size += sizeof(CTIME);
5730 }
5731
5732 first = details = (PFIELDINFO)WinSendMsg(handle, CM_ALLOCDETAILFIELDINFO, MPFROMLONG(count), 0L);
5733
5734 if(!first)
5735 {
5736 free(offStruct);
5737 return FALSE;
5738 }
5739
5740 for(z=0;z<count;z++)
5741 {
5742 if(z==separator-1)
5743 left=details;
5744 details->cb = sizeof(FIELDINFO);
5745 details->flData = flags[z];
5746 details->flTitle = CFA_FITITLEREADONLY;
5747 details->pTitleData = titles[z];
5748 details->offStruct = offStruct[z];
5749 details = details->pNextFieldInfo;
5750 }
5751
5752 detin.cb = sizeof(FIELDINFOINSERT);
5753 detin.fInvalidateFieldInfo = FALSE;
5754 detin.pFieldInfoOrder = (PFIELDINFO) CMA_FIRST;
5755 detin.cFieldInfoInsert = (ULONG)count;
5756
5757 WinSendMsg(handle, CM_INSERTDETAILFIELDINFO, MPFROMP(first), MPFROMP(&detin));
5758
5759 if(count > separator && separator > 0)
5760 {
5761 cnri.cb = sizeof(CNRINFO);
5762 cnri.pFieldInfoLast = left;
5763 cnri.xVertSplitbar = 150;
5764
5765 WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri), MPFROMLONG(CMA_PFIELDINFOLAST | CMA_XVERTSPLITBAR));
5766 }
5767
5768 free(offStruct);
5769 return TRUE;
5770 }
5771
5772 /*
5773 * Sets up the filesystem columns, note: filesystem always has an icon/filename field.
5774 * Parameters:
5775 * handle: Handle to the container to be configured.
5776 * flags: An array of unsigned longs with column flags.
5777 * titles: An array of strings with column text titles.
5778 * count: The number of columns (this should match the arrays).
5779 */
5780 int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count)
5781 {
5782 char **newtitles = malloc(sizeof(char *) * (count + 2));
5783 unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 2));
5784
5785 newtitles[0] = "Icon";
5786 newtitles[1] = "Filename";
5787
5788 newflags[0] = DW_CFA_BITMAPORICON | DW_CFA_CENTER | DW_CFA_HORZSEPARATOR | DW_CFA_SEPARATOR;
5789 newflags[1] = DW_CFA_STRING | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR;
5790
5791 memcpy(&newtitles[2], titles, sizeof(char *) * count);
5792 memcpy(&newflags[2], flags, sizeof(unsigned long) * count);
5793
5794 dw_container_setup(handle, newflags, newtitles, count + 2, count ? 2 : 0);
5795
5796 free(newtitles);
5797 free(newflags);
5798 return TRUE;
5799 }
5800
5801 /*
5802 * Obtains an icon from a module (or header in GTK).
5803 * Parameters:
5804 * module: Handle to module (DLL) in OS/2 and Windows.
5805 * id: A unsigned long id int the resources on OS/2 and
5806 * Windows, on GTK this is converted to a pointer
5807 * to an embedded XPM.
5808 */
5809 unsigned long API dw_icon_load(unsigned long module, unsigned long id)
5810 {
5811 return WinLoadPointer(HWND_DESKTOP,module,id);
5812 }
5813
5814 /*
5815 * Frees a loaded resource in OS/2 and Windows.
5816 * Parameters:
5817 * handle: Handle to icon returned by dw_icon_load().
5818 */
5819 void API dw_icon_free(unsigned long handle)
5820 {
5821 WinDestroyPointer(handle);
5822 }
5823
5824 /*
5825 * Allocates memory used to populate a container.
5826 * Parameters:
5827 * handle: Handle to the container window (widget).
5828 * rowcount: The number of items to be populated.
5829 */
5830 void * API dw_container_alloc(HWND handle, int rowcount)
5831 {
5832 WindowData *wd = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
5833 ULONG *flags = wd ? wd->data : 0;
5834 int z, size = 0, totalsize, count = 0;
5835 PRECORDCORE temp;
5836 ContainerInfo *ci;
5837 void *blah = NULL;
5838
5839 if(!flags || rowcount < 1)
5840 return NULL;
5841
5842 while(flags[count])
5843 count++;
5844
5845 /* Figure out the offsets to the items in the struct */
5846 for(z=0;z<count;z++)
5847 {
5848 if(flags[z] & DW_CFA_BITMAPORICON)
5849 size += sizeof(HPOINTER);
5850 else if(flags[z] & DW_CFA_STRING)
5851 size += sizeof(char *);
5852 else if(flags[z] & DW_CFA_ULONG)
5853 size += sizeof(ULONG);
5854 else if(flags[z] & DW_CFA_DATE)
5855 size += sizeof(CDATE);
5856 else if(flags[z] & DW_CFA_TIME)
5857 size += sizeof(CTIME);
5858 }
5859
5860 totalsize = size + sizeof(RECORDCORE);
5861
5862 z = 0;
5863
5864 while((blah = (void *)WinSendMsg(handle, CM_ALLOCRECORD, MPFROMLONG(size), MPFROMLONG(rowcount))) == NULL)
5865 {
5866 z++;
5867 if(z > 5000000)
5868 break;
5869 dw_main_sleep(1);
5870 }
5871
5872 if(!blah)
5873 return NULL;
5874
5875 temp = (PRECORDCORE)blah;
5876
5877 for(z=0;z<rowcount;z++)
5878 {
5879 temp->cb = totalsize;
5880 temp = temp->preccNextRecord;
5881 }
5882
5883 ci = malloc(sizeof(struct _containerinfo));
5884
5885 ci->count = rowcount;
5886 ci->data = blah;
5887 ci->handle = handle;
5888
5889 return (void *)ci;
5890 }
5891
5892 /* Internal function that does the work for set_item and change_item */
5893 void _dw_container_set_item(HWND handle, PRECORDCORE temp, int column, int row, void *data)
5894 {
5895 WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
5896 ULONG totalsize, size = 0, *flags = blah ? blah->data : 0;
5897 int z, currentcount;
5898 CNRINFO cnr;
5899 void *dest;
5900
5901 if(!flags)
5902 return;
5903
5904 z = 0;
5905
5906 while(WinSendMsg(handle, CM_QUERYCNRINFO, (MPARAM)&cnr, MPFROMSHORT(sizeof(CNRINFO))) == 0)
5907 {
5908 z++;
5909 if(z > 5000000)
5910 return;
5911 dw_main_sleep(1);
5912 }
5913 currentcount = cnr.cRecords;
5914
5915 /* Figure out the offsets to the items in the struct */
5916 for(z=0;z<column;z++)
5917 {
5918 if(flags[z] & DW_CFA_BITMAPORICON)
5919 size += sizeof(HPOINTER);
5920 else if(flags[z] & DW_CFA_STRING)
5921 size += sizeof(char *);
5922 else if(flags[z] & DW_CFA_ULONG)
5923 size += sizeof(ULONG);
5924 else if(flags[z] & DW_CFA_DATE)
5925 size += sizeof(CDATE);
5926 else if(flags[z] & DW_CFA_TIME)
5927 size += sizeof(CTIME);
5928 }
5929
5930 totalsize = size + sizeof(RECORDCORE);
5931
5932 for(z=0;z<(row-currentcount);z++)
5933 temp = temp->preccNextRecord;
5934
5935 dest = (void *)(((ULONG)temp)+((ULONG)totalsize));
5936
5937 if(flags[column] & DW_CFA_BITMAPORICON)
5938 memcpy(dest, data, sizeof(HPOINTER));
5939 else if(flags[column] & DW_CFA_STRING)
5940 memcpy(dest, data, sizeof(char *));
5941 else if(flags[column] & DW_CFA_ULONG)
5942 memcpy(dest, data, sizeof(ULONG));
5943 else if(flags[column] & DW_CFA_DATE)
5944 memcpy(dest, data, sizeof(CDATE));
5945 else if(flags[column] & DW_CFA_TIME)
5946 memcpy(dest, data, sizeof(CTIME));
5947 }
5948
5949 /*
5950 * Sets an item in specified row and column to the given data.
5951 * Parameters:
5952 * handle: Handle to the container window (widget).
5953 * pointer: Pointer to the allocated memory in dw_container_alloc().
5954 * column: Zero based column of data being set.
5955 * row: Zero based row of data being set.
5956 * data: Pointer to the data to be added.
5957 */
5958 void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data)
5959 {
5960 ContainerInfo *ci = (ContainerInfo *)pointer;
5961
5962 if(!ci)
5963 return;
5964
5965 _dw_container_set_item(handle, (PRECORDCORE)ci->data, column, row, data);
5966 }
5967
5968 /*
5969 * Changes an existing item in specified row and column to the given data.
5970 * Parameters:
5971 * handle: Handle to the container window (widget).
5972 * column: Zero based column of data being set.
5973 * row: Zero based row of data being set.
5974 * data: Pointer to the data to be added.
5975 */
5976 void API dw_container_change_item(HWND handle, int column, int row, void *data)
5977 {
5978 PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
5979 int count = 0;
5980
5981 while(pCore)
5982 {
5983 if(count == row)
5984 {
5985 _dw_container_set_item(handle, pCore, column, row, data);
5986 WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_NOREPOSITION | CMA_TEXTCHANGED));
5987 return;
5988 }
5989 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
5990 count++;
5991 }
5992 }
5993
5994 /*
5995 * Sets an item in specified row and column to the given data.
5996 * Parameters:
5997 * handle: Handle to the container window (widget).
5998 * pointer: Pointer to the allocated memory in dw_container_alloc().
5999 * column: Zero based column of data being set.
6000 * row: Zero based row of data being set.
6001 * data: Pointer to the data to be added.
6002 */
6003 void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon)
6004 {
6005 dw_container_set_item(handle, pointer, 0, row, (void *)&icon);
6006 dw_container_set_item(handle, pointer, 1, row, (void *)&filename);
6007 }
6008
6009 /*
6010 * Sets an item in specified row and column to the given data.
6011 * Parameters:
6012 * handle: Handle to the container window (widget).
6013 * pointer: Pointer to the allocated memory in dw_container_alloc().
6014 * column: Zero based column of data being set.
6015 * row: Zero based row of data being set.
6016 * data: Pointer to the data to be added.
6017 */
6018 void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data)
6019 {
6020 dw_container_set_item(handle, pointer, column + 2, row, data);
6021 }
6022
6023 /*
6024 * Sets the width of a column in the container.
6025 * Parameters:
6026 * handle: Handle to window (widget) of container.
6027 * column: Zero based column of width being set.
6028 * width: Width of column in pixels.
6029 */
6030 void API dw_container_set_column_width(HWND handle, int column, int width)
6031 {
6032 }
6033
6034 /*
6035 * Sets the title of a row in the container.
6036 * Parameters:
6037 * pointer: Pointer to the allocated memory in dw_container_alloc().
6038 * row: Zero based row of data being set.
6039 * title: String title of the item.
6040 */
6041 void API dw_container_set_row_title(void *pointer, int row, char *title)
6042 {
6043 ContainerInfo *ci = (ContainerInfo *)pointer;
6044 PRECORDCORE temp;
6045 int z, currentcount;
6046 CNRINFO cnr;
6047
6048 if(!ci)
6049 return;
6050
6051 temp = (PRECORDCORE)ci->data;
6052
6053 z = 0;
6054
6055 while(WinSendMsg(ci->handle, CM_QUERYCNRINFO, (MPARAM)&cnr, MPFROMSHORT(sizeof(CNRINFO))) == 0)
6056 {
6057 z++;
6058 if(z > 5000000)
6059 return;
6060 dw_main_sleep(1);
6061 }
6062 currentcount = cnr.cRecords;
6063
6064 for(z=0;z<(row-currentcount);z++)
6065 temp = temp->preccNextRecord;
6066
6067 temp->pszIcon = title;
6068 temp->pszName = title;
6069 temp->pszText = title;
6070 }
6071
6072 /*
6073 * Sets the title of a row in the container.
6074 * Parameters:
6075 * handle: Handle to the container window (widget).
6076 * pointer: Pointer to the allocated memory in dw_container_alloc().
6077 * rowcount: The number of rows to be inserted.
6078 */
6079 void API dw_container_insert(HWND handle, void *pointer, int rowcount)
6080 {
6081 RECORDINSERT recin;
6082 ContainerInfo *ci = (ContainerInfo *)pointer;
6083 int z;
6084
6085 if(!ci)
6086 return;
6087
6088 recin.cb = sizeof(RECORDINSERT);
6089 recin.pRecordOrder = (PRECORDCORE)CMA_END;
6090 recin.pRecordParent = NULL;
6091 recin.zOrder = CMA_TOP;
6092 recin.fInvalidateRecord = TRUE;
6093 recin.cRecordsInsert = rowcount;
6094
6095 z = 0;
6096
6097 while(WinSendMsg(handle, CM_INSERTRECORD, MPFROMP(ci->data), MPFROMP(&recin)) == 0)
6098 {
6099 z++;
6100 if(z > 5000000)
6101 break;
6102 dw_main_sleep(1);
6103 }
6104
6105 free(ci);
6106 }
6107
6108 /*
6109 * Removes all rows from a container.
6110 * Parameters:
6111 * handle: Handle to the window (widget) to be cleared.
6112 * redraw: TRUE to cause the container to redraw immediately.
6113 */
6114 void API dw_container_clear(HWND handle, int redraw)
6115 {
6116 int z = 0;
6117
6118 while((int)WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)0L, MPFROM2SHORT(0, (redraw ? CMA_INVALIDATE : 0) | CMA_FREE)) == -1)
6119 {
6120 z++;
6121 if(z > 5000000)
6122 break;
6123 dw_main_sleep(1);
6124 }
6125 }
6126
6127 /*
6128 * Removes the first x rows from a container.
6129 * Parameters:
6130 * handle: Handle to the window (widget) to be deleted from.
6131 * rowcount: The number of rows to be deleted.
6132 */
6133 void API dw_container_delete(HWND handle, int rowcount)
6134 {
6135 RECORDCORE *last, **prc = malloc(sizeof(RECORDCORE *) * rowcount);
6136 int current = 1, z;
6137
6138 prc[0] = last = (RECORDCORE *)WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
6139
6140 while(last && current < rowcount)
6141 {
6142 prc[current] = last = (RECORDCORE *)WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)last, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
6143 current++;
6144 }
6145
6146 z = 0;
6147
6148 while((int)WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)prc, MPFROM2SHORT(current, CMA_INVALIDATE | CMA_FREE)) == -1)
6149 {
6150 z++;
6151 if(z > 5000000)
6152 break;
6153 dw_main_sleep(1);
6154 }
6155
6156 free(prc);
6157 }
6158
6159 /*
6160 * Scrolls container up or down.
6161 * Parameters:
6162 * handle: Handle to the window (widget) to be scrolled.
6163 * direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or
6164 * DW_SCROLL_BOTTOM. (rows is ignored for last two)
6165 * rows: The number of rows to be scrolled.
6166 */
6167 void API dw_container_scroll(HWND handle, int direction, long rows)
6168 {
6169 switch(direction)
6170 {
6171 case DW_SCROLL_TOP:
6172 WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(-10000000));
6173 break;
6174 case DW_SCROLL_BOTTOM:
6175 WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(10000000));
6176 break;
6177 }
6178 }
6179
6180 /*
6181 * Removes all rows from a container.
6182 * Parameters:
6183 * handle: Handle to the window (widget) to be cleared.
6184 */
6185 void API dw_container_set_view(HWND handle, unsigned long flags, int iconwidth, int iconheight)
6186 {
6187 CNRINFO cnrinfo;
6188
6189 cnrinfo.flWindowAttr = flags;
6190 cnrinfo.slBitmapOrIcon.cx = iconwidth;
6191 cnrinfo.slBitmapOrIcon.cy = iconheight;
6192
6193 WinSendMsg(handle, CM_SETCNRINFO, &cnrinfo, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON));
6194 }
6195
6196 /*
6197 * Starts a new query of a container.
6198 * Parameters:
6199 * handle: Handle to the window (widget) to be queried.
6200 * flags: If this parameter is DW_CRA_SELECTED it will only
6201 * return items that are currently selected. Otherwise
6202 * it will return all records in the container.
6203 */
6204 char * API dw_container_query_start(HWND handle, unsigned long flags)
6205 {
6206 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
6207 if(pCore)
6208 {
6209 if(flags)
6210 {
6211 while(pCore)
6212 {
6213 if(pCore->flRecordAttr & flags)
6214 return pCore->pszIcon;
6215 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
6216 }
6217 }
6218 else
6219 return pCore->pszIcon;
6220 }
6221 return NULL;
6222 }
6223
6224 /*
6225 * Continues an existing query of a container.
6226 * Parameters:
6227 * handle: Handle to the window (widget) to be queried.
6228 * flags: If this parameter is DW_CRA_SELECTED it will only
6229 * return items that are currently selected. Otherwise
6230 * it will return all records in the container.
6231 */
6232 char * API dw_container_query_next(HWND handle, unsigned long flags)
6233 {
6234 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
6235 if(pCore)
6236 {
6237 if(flags)
6238 {
6239 while(pCore)
6240 {
6241 if(pCore->flRecordAttr & flags)
6242 return pCore->pszIcon;
6243
6244 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
6245 }
6246 }
6247 else
6248 return pCore->pszIcon;
6249 }
6250 return NULL;
6251 }
6252
6253 /*
6254 * Cursors the item with the text speficied, and scrolls to that item.
6255 * Parameters:
6256 * handle: Handle to the window (widget) to be queried.
6257 * text: Text usually returned by dw_container_query().
6258 */
6259 void API dw_container_cursor(HWND handle, char *text)
6260 {
6261 RECTL viewport, item;
6262
6263 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
6264 while(pCore)
6265 {
6266 if((char *)pCore->pszIcon == text)
6267 {
6268 QUERYRECORDRECT qrr;
6269 int scrollpixels = 0, midway;
6270
6271 qrr.cb = sizeof(QUERYRECORDRECT);
6272 qrr.pRecord = pCore;
6273 qrr.fRightSplitWindow = 0;
6274 qrr.fsExtent = CMA_TEXT;
6275
6276 WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)pCore, MPFROM2SHORT(TRUE, CRA_CURSORED));
6277 WinSendMsg(handle, CM_QUERYVIEWPORTRECT, (MPARAM)&viewport, MPFROM2SHORT(CMA_WORKSPACE, FALSE));
6278 WinSendMsg(handle, CM_QUERYRECORDRECT, (MPARAM)&item, (MPARAM)&qrr);
6279
6280 midway = (viewport.yTop - viewport.yBottom)/2;
6281 scrollpixels = viewport.yTop - (item.yTop + midway);
6282
6283 WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(scrollpixels));
6284 return;
6285 }
6286
6287 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
6288 }
6289 }
6290
6291 /*
6292 * Deletes the item with the text speficied.
6293 * Parameters:
6294 * handle: Handle to the window (widget).
6295 * text: Text usually returned by dw_container_query().
6296 */
6297 void API dw_container_delete_row(HWND handle, char *text)
6298 {
6299 PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
6300
6301 while(pCore)
6302 {
6303 if((char *)pCore->pszIcon == text)
6304 {
6305 WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_FREE | CMA_INVALIDATE));
6306 return;
6307 }
6308 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
6309 }
6310 }
6311
6312 /*
6313 * Optimizes the column widths so that all data is visible.
6314 * Parameters:
6315 * handle: Handle to the window (widget) to be optimized.
6316 */
6317 void API dw_container_optimize(HWND handle)
6318 {
6319 WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
6320 RECTL item;
6321 PRECORDCORE pCore = NULL;
6322 int max = 0;
6323
6324 if(blah && !blah->flags)
6325 return;
6326
6327 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
6328 while(pCore)
6329 {
6330 QUERYRECORDRECT qrr;
6331 int vector;
6332
6333 qrr.cb = sizeof(QUERYRECORDRECT);
6334 qrr.pRecord = pCore;
6335 qrr.fRightSplitWindow = 0;
6336 qrr.fsExtent = CMA_TEXT;
6337
6338 WinSendMsg(handle, CM_QUERYRECORDRECT, (MPARAM)&item, (MPARAM)&qrr);
6339
6340 vector = item.xRight - item.xLeft;
6341
6342 if(vector > max)
6343 max = vector;
6344
6345 pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
6346 }
6347
6348 if(max)
6349 {
6350 CNRINFO cnri;
6351
6352 cnri.cb = sizeof(CNRINFO);
6353 cnri.xVertSplitbar = max;
6354
6355 WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri), MPFROMLONG(CMA_XVERTSPLITBAR));
6356 }
6357 }
6358
6359 /*
6360 * Creates a rendering context widget (window) to be packed.
6361 * Parameters:
6362 * id: An id to be used with dw_window_from_id.
6363 * Returns:
6364 * A handle to the widget or NULL on failure.
6365 */
6366 HWND API dw_render_new(unsigned long id)
6367 {
6368 HWND hwndframe = WinCreateWindow(HWND_OBJECT,
6369 WC_FRAME,
6370 NULL,
6371 WS_VISIBLE |
6372 FS_NOBYTEALIGN,
6373 0,0,2000,1000,
6374 NULLHANDLE,
6375 HWND_TOP,
6376 id,
6377 NULL,
6378 NULL);
6379 WinSubclassWindow(hwndframe, _RendProc);
6380 return hwndframe;
6381 }
6382
6383 /* Sets the current foreground drawing color.
6384 * Parameters:
6385 * red: red value.
6386 * green: green value.
6387 * blue: blue value.
6388 */
6389 void API dw_color_foreground_set(unsigned long value)
6390 {
6391 _foreground = value;
6392 }
6393
6394 /* Sets the current background drawing color.
6395 * Parameters:
6396 * red: red value.
6397 * green: green value.
6398 * blue: blue value.
6399 */
6400 void API dw_color_background_set(unsigned long value)
6401 {
6402 _background = value;
6403 }
6404
6405 HPS _set_hps(HPS hps)
6406 {
6407 LONG alTable[2];
6408
6409 alTable[0] = DW_RED_VALUE(_foreground) << 16 | DW_GREEN_VALUE(_foreground) << 8 | DW_BLUE_VALUE(_foreground);
6410 alTable[1] = DW_RED_VALUE(_background) << 16 | DW_GREEN_VALUE(_background) << 8 | DW_BLUE_VALUE(_background);
6411
6412 GpiCreateLogColorTable(hps,
6413 LCOL_RESET,
6414 LCOLF_CONSECRGB,
6415 16,
6416 2,
6417 alTable);
6418 if(_foreground & DW_RGB_COLOR)
6419 GpiSetColor(hps, 16);
6420 else
6421 GpiSetColor(hps, _internal_color(_foreground));
6422 if(_background & DW_RGB_COLOR)
6423 GpiSetBackColor(hps, 17);
6424 else
6425 GpiSetBackColor(hps, _internal_color(_background));
6426 return hps;
6427 }
6428
6429 HPS _set_colors(HWND handle)
6430 {
6431 HPS hps = WinGetPS(handle);
6432
6433 _set_hps(hps);
6434 return hps;
6435 }
6436
6437 /* Draw a point on a window (preferably a render window).
6438 * Parameters:
6439 * handle: Handle to the window.
6440 * pixmap: Handle to the pixmap. (choose only one of these)
6441 * x: X coordinate.
6442 * y: Y coordinate.
6443 */
6444 void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y)
6445 {
6446 HPS hps;
6447 int height;
6448 POINTL ptl;
6449
6450 if(handle)
6451 {
6452 hps = _set_colors(handle);
6453 height = _get_height(handle);
6454 }
6455 else if(pixmap)
6456 {
6457 hps = _set_hps(pixmap->hps);
6458 height = pixmap->height;
6459 }
6460 else
6461 return;
6462
6463 ptl.x = x;
6464 ptl.y = height - y - 1;
6465
6466 GpiSetPel(hps, &ptl);
6467 if(!pixmap)
6468 WinReleasePS(hps);
6469 }
6470
6471 /* Draw a line on a window (preferably a render window).
6472 * Parameters:
6473 * handle: Handle to the window.
6474 * pixmap: Handle to the pixmap. (choose only one of these)
6475 * x1: First X coordinate.
6476 * y1: First Y coordinate.
6477 * x2: Second X coordinate.
6478 * y2: Second Y coordinate.
6479 */
6480 void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2)
6481 {
6482 HPS hps;
6483 int height;
6484 POINTL ptl[2];
6485
6486 if(handle)
6487 {
6488 hps = _set_colors(handle);
6489 height = _get_height(handle);
6490 }
6491 else if(pixmap)
6492 {
6493 hps = _set_hps(pixmap->hps);
6494 height = pixmap->height;
6495 }
6496 else
6497 return;
6498
6499 ptl[0].x = x1;
6500 ptl[0].y = height - y1 - 1;
6501 ptl[1].x = x2;
6502 ptl[1].y = height - y2 - 1;
6503
6504 GpiMove(hps, &ptl[0]);
6505 GpiLine(hps, &ptl[1]);
6506
6507 if(!pixmap)
6508 WinReleasePS(hps);
6509 }
6510
6511
6512 void _CopyFontSettings(HPS hpsSrc, HPS hpsDst)
6513 {
6514 FONTMETRICS fm;
6515 FATTRS fat;
6516 SIZEF sizf;
6517
6518 GpiQueryFontMetrics(hpsSrc, sizeof(FONTMETRICS), &fm);
6519
6520 memset(&fat, 0, sizeof(fat));
6521
6522 fat.usRecordLength = sizeof(FATTRS);
6523 fat.lMatch = fm.lMatch;
6524 strcpy(fat.szFacename, fm.szFacename);
6525
6526 GpiCreateLogFont(hpsDst, 0, 1L, &fat);
6527 GpiSetCharSet(hpsDst, 1L);
6528
6529 sizf.cx = MAKEFIXED(fm.lEmInc,0);
6530 sizf.cy = MAKEFIXED(fm.lMaxBaselineExt,0);
6531 GpiSetCharBox(hpsDst, &sizf );
6532 }
6533
6534 /* Draw text on a window (preferably a render window).
6535 * Parameters:
6536 * handle: Handle to the window.
6537 * pixmap: Handle to the pixmap. (choose only one of these)
6538 * x: X coordinate.
6539 * y: Y coordinate.
6540 * text: Text to be displayed.
6541 */
6542 void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text)
6543 {
6544 HPS hps;
6545 int z, height;
6546 RECTL rcl;
6547 char fontname[128];
6548 POINTL aptl[TXTBOX_COUNT];
6549
6550 if(handle)
6551 {
6552 hps = _set_colors(handle);
6553 height = _get_height(handle);
6554 _GetPPFont(handle, fontname);
6555 }
6556 else if(pixmap)
6557 {
6558 HPS pixmaphps = WinGetPS(pixmap->handle);
6559
6560 hps = _set_hps(pixmap->hps);
6561 height = pixmap->height;
6562 _GetPPFont(pixmap->handle, fontname);
6563 _CopyFontSettings(pixmaphps, hps);
6564 WinReleasePS(pixmaphps);
6565 }
6566 else
6567 return;
6568
6569 for(z=0;z<strlen(fontname);z++)
6570 {
6571 if(fontname[z]=='.')
6572 break;
6573 }
6574
6575 GpiQueryTextBox(hps, strlen(text), text, TXTBOX_COUNT, aptl);
6576
6577 rcl.xLeft = x;
6578 rcl.yTop = height - y;
6579 rcl.yBottom = rcl.yTop - (aptl[TXTBOX_TOPLEFT].y - aptl[TXTBOX_BOTTOMLEFT].y);
6580 rcl.xRight = rcl.xLeft + (aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_TOPLEFT].x);
6581
6582 WinDrawText(hps, -1, text, &rcl, DT_TEXTATTRS, DT_TEXTATTRS, DT_VCENTER | DT_LEFT | DT_TEXTATTRS);
6583
6584 if(!pixmap)
6585 WinReleasePS(hps);
6586 }
6587
6588 /* Query the width and height of a text string.
6589 * Parameters:
6590 * handle: Handle to the window.
6591 * pixmap: Handle to the pixmap. (choose only one of these)
6592 * text: Text to be queried.
6593 * width: Pointer to a variable to be filled in with the width.
6594 * height Pointer to a variable to be filled in with the height.
6595 */
6596 void API dw_font_text_extents(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height)
6597 {
6598 HPS hps;
6599 POINTL aptl[TXTBOX_COUNT];
6600
6601 if(handle)
6602 {
6603 hps = _set_colors(handle);
6604 }
6605 else if(pixmap)
6606 {
6607 HPS pixmaphps = WinGetPS(pixmap->handle);
6608
6609 hps = _set_hps(pixmap->hps);
6610 _CopyFontSettings(pixmaphps, hps);
6611 WinReleasePS(pixmaphps);
6612 }
6613 else
6614 return;
6615
6616 GpiQueryTextBox(hps, strlen(text), text, TXTBOX_COUNT, aptl);
6617
6618 if(width)
6619 *width = aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_TOPLEFT].x;
6620
6621 if(height)
6622 *height = aptl[TXTBOX_TOPLEFT].y - aptl[TXTBOX_BOTTOMLEFT].y;
6623
6624 if(!pixmap)
6625 WinReleasePS(hps);
6626 }
6627
6628 /* Draw a rectangle on a window (preferably a render window).
6629 * Parameters:
6630 * handle: Handle to the window.
6631 * pixmap: Handle to the pixmap. (choose only one of these)
6632 * fill: Fill box TRUE or FALSE.
6633 * x: X coordinate.
6634 * y: Y coordinate.
6635 * width: Width of rectangle.
6636 * height: Height of rectangle.
6637 */
6638 void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height)
6639 {
6640 HPS hps;
6641 int thisheight;
6642 POINTL ptl[2];
6643
6644 if(handle)
6645 {
6646 hps = _set_colors(handle);
6647 thisheight = _get_height(handle);
6648 }
6649 else if(pixmap)
6650 {
6651 hps = _set_hps(pixmap->hps);
6652 thisheight = pixmap->height;
6653 }
6654 else
6655 return;
6656
6657 ptl[0].x = x;
6658 ptl[0].y = thisheight - y - 1;
6659 ptl[1].x = x + width - 1;
6660 ptl[1].y = thisheight - y - height;
6661
6662 GpiMove(hps, &ptl[0]);
6663 GpiBox(hps, fill ? DRO_OUTLINEFILL : DRO_OUTLINE, &ptl[1], 0, 0);
6664
6665 if(!pixmap)
6666 WinReleasePS(hps);
6667 }
6668
6669 /* Call this after drawing to the screen to make sure
6670 * anything you have drawn is visible.
6671 */
6672 void API dw_flush(void)
6673 {
6674 }
6675
6676 /*
6677 * Creates a pixmap with given parameters.
6678 * Parameters:
6679 * handle: Window handle the pixmap is associated with.
6680 * width: Width of the pixmap in pixels.
6681 * height: Height of the pixmap in pixels.
6682 * depth: Color depth of the pixmap.
6683 * Returns:
6684 * A handle to a pixmap or NULL on failure.
6685 */
6686 HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth)
6687 {
6688 BITMAPINFOHEADER bmih;
6689 SIZEL sizl = { 0, 0 };
6690 HPIXMAP pixmap;
6691 HDC hdc;
6692 HPS hps;
6693 ULONG ulFlags;
6694 LONG cPlanes, cBitCount;
6695
6696 if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
6697 return NULL;
6698
6699 hps = WinGetPS(handle);
6700
6701 hdc = GpiQueryDevice(hps);
6702 ulFlags = GpiQueryPS(hps, &sizl);
6703
6704 pixmap->handle = handle;
6705 pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc);
6706 pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC);
6707
6708 DevQueryCaps(hdc, CAPS_COLOR_PLANES , 1L, &cPlanes);
6709 if (!depth)
6710 {
6711 DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1L, &cBitCount);
6712 depth = cBitCount;
6713 }
6714
6715 memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
6716 bmih.cbFix = sizeof(BITMAPINFOHEADER);
6717 bmih.cx = (SHORT)width;
6718 bmih.cy = (SHORT)height;
6719 bmih.cPlanes = (SHORT)cPlanes;
6720 bmih.cBitCount = (SHORT)depth;
6721
6722 pixmap->width = width; pixmap->height = height;
6723
6724 pixmap->hbm = GpiCreateBitmap(pixmap->hps, (PBITMAPINFOHEADER2)&bmih, 0L, NULL, NULL);
6725
6726 GpiSetBitmap(pixmap->hps, pixmap->hbm);
6727
6728 if (depth>8)
6729 GpiCreateLogColorTable(pixmap->hps, LCOL_PURECOLOR, LCOLF_RGB, 0, 0, NULL );
6730
6731 WinReleasePS(hps);
6732
6733 return pixmap;
6734 }
6735
6736 /*
6737 * Creates a pixmap from internal resource graphic specified by id.
6738 * Parameters:
6739 * handle: Window handle the pixmap is associated with.
6740 * id: Resource ID associated with requested pixmap.
6741 * Returns:
6742 * A handle to a pixmap or NULL on failure.
6743 */
6744 HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id)
6745 {
6746 BITMAPINFOHEADER bmih;
6747 SIZEL sizl = { 0, 0 };
6748 HPIXMAP pixmap;
6749 HDC hdc;
6750 HPS hps;
6751 ULONG ulFlags;
6752
6753 if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
6754 return NULL;
6755
6756 hps = WinGetPS(handle);
6757
6758 hdc = GpiQueryDevice(hps);
6759 ulFlags = GpiQueryPS(hps, &sizl);
6760
6761 pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc);
6762 pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC);
6763
6764 pixmap->hbm = GpiLoadBitmap(pixmap->hps, NULLHANDLE, id, 0, 0);
6765
6766 GpiQueryBitmapParameters(pixmap->hbm, &bmih);
6767
6768 GpiSetBitmap(pixmap->hps, pixmap->hbm);
6769
6770 pixmap->width = bmih.cx; pixmap->height = bmih.cy;
6771
6772 WinReleasePS(hps);
6773
6774 return pixmap;
6775 }
6776
6777 /*
6778 * Destroys an allocated pixmap.
6779 * Parameters:
6780 * pixmap: Handle to a pixmap returned by
6781 * dw_pixmap_new..
6782 */
6783 void API dw_pixmap_destroy(HPIXMAP pixmap)
6784 {
6785 GpiSetBitmap(pixmap->hps, NULLHANDLE);
6786 GpiDeleteBitmap(pixmap->hbm);
6787 GpiAssociate(pixmap->hps, NULLHANDLE);
6788 GpiDestroyPS(pixmap->hps);
6789 DevCloseDC(pixmap->hdc);
6790 free(pixmap);
6791 }
6792
6793 /*
6794 * Copies from one item to another.
6795 * Parameters:
6796 * dest: Destination window handle.
6797 * destp: Destination pixmap. (choose only one).
6798 * xdest: X coordinate of destination.
6799 * ydest: Y coordinate of destination.
6800 * width: Width of area to copy.
6801 * height: Height of area to copy.
6802 * src: Source window handle.
6803 * srcp: Source pixmap. (choose only one).
6804 * xsrc: X coordinate of source.
6805 * ysrc: Y coordinate of source.
6806 */
6807 void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc)
6808 {
6809 HPS hpsdest;
6810 HPS hpssrc;
6811 POINTL ptl[4];
6812 int destheight, srcheight;
6813
6814 if(dest)
6815 {
6816 hpsdest = WinGetPS(dest);
6817 destheight = _get_height(dest);
6818 }
6819 else if(destp)
6820 {
6821 hpsdest = destp->hps;
6822 destheight = destp->height;
6823 }
6824 else
6825 return;
6826
6827 if(src)
6828 {
6829 hpssrc = WinGetPS(src);
6830 srcheight = _get_height(src);
6831 }
6832 else if(srcp)
6833 {
6834 hpssrc = srcp->hps;
6835 srcheight = srcp->height;
6836 }
6837 else
6838 {
6839 if(!destp)
6840 WinReleasePS(hpsdest);
6841 return;
6842 }
6843
6844 ptl[0].x = xdest;
6845 ptl[0].y = (destheight - ydest) - height;
6846 ptl[1].x = ptl[0].x + width;
6847 ptl[1].y = destheight - ydest;
6848 ptl[2].x = xsrc;
6849 ptl[2].y = srcheight - (ysrc + height);
6850 ptl[3].x = ptl[2].x + width;
6851 ptl[3].y = ptl[2].y + height;
6852
6853 GpiBitBlt(hpsdest, hpssrc, 4, ptl, ROP_SRCCOPY, BBO_IGNORE);
6854
6855 if(!destp)
6856 WinReleasePS(hpsdest);
6857 if(!srcp)
6858 WinReleasePS(hpssrc);
6859 }
6860
6861 /*
6862 * Emits a beep.
6863 * Parameters:
6864 * freq: Frequency.
6865 * dur: Duration.
6866 */
6867 void API dw_beep(int freq, int dur)
6868 {
6869 DosBeep(freq, dur);
6870 }
6871
6872 /* Open a shared library and return a handle.
6873 * Parameters:
6874 * name: Base name of the shared library.
6875 * handle: Pointer to a module handle,
6876 * will be filled in with the handle.
6877 */
6878 int API dw_module_load(char *name, HMOD *handle)
6879 {
6880 char objnamebuf[300] = "";
6881
6882 return DosLoadModule(objnamebuf, sizeof(objnamebuf), name, handle);
6883 }
6884
6885 /* Queries the address of a symbol within open handle.
6886 * Parameters:
6887 * handle: Module handle returned by dw_module_load()
6888 * name: Name of the symbol you want the address of.
6889 * func: A pointer to a function pointer, to obtain
6890 * the address.
6891 */
6892 int API dw_module_symbol(HMOD handle, char *name, void**func)
6893 {
6894 return DosQueryProcAddr(handle, 0, name, (PFN*)func);
6895 }
6896
6897 /* Frees the shared library previously opened.
6898 * Parameters:
6899 * handle: Module handle returned by dw_module_load()
6900 */
6901 int API dw_module_close(HMOD handle)
6902 {
6903 DosFreeModule(handle);
6904 return 0;
6905 }
6906
6907 /*
6908 * Returns the handle to an unnamed mutex semaphore.
6909 */
6910 HMTX API dw_mutex_new(void)
6911 {
6912 HMTX mutex;
6913
6914 DosCreateMutexSem(NULL, &mutex, 0, FALSE);
6915 return mutex;
6916 }
6917
6918 /*
6919 * Closes a semaphore created by dw_mutex_new().
6920 * Parameters:
6921 * mutex: The handle to the mutex returned by dw_mutex_new().
6922 */
6923 void API dw_mutex_close(HMTX mutex)
6924 {
6925 DosCloseMutexSem(mutex);
6926 }
6927
6928 /*
6929 * Tries to gain access to the semaphore, if it can't it blocks.
6930 * If we are in a callback we must keep the message loop running
6931 * while blocking.
6932 * Parameters:
6933 * mutex: The handle to the mutex returned by dw_mutex_new().
6934 */
6935 void API dw_mutex_lock(HMTX mutex)
6936 {
6937 if(_dwtid == dw_thread_id())
6938 {
6939 int rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN);
6940
6941 while(rc == ERROR_TIMEOUT)
6942 {
6943 dw_main_sleep(10);
6944 rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN);
6945 }
6946 }
6947 else
6948 DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT);
6949 }
6950
6951 /*
6952 * Reliquishes the access to the semaphore.
6953 * Parameters:
6954 * mutex: The handle to the mutex returned by dw_mutex_new().
6955 */
6956 void API dw_mutex_unlock(HMTX mutex)
6957 {
6958 DosReleaseMutexSem(mutex);
6959 }
6960
6961 /*
6962 * Returns the handle to an unnamed event semaphore.
6963 */
6964 HEV API dw_event_new(void)
6965 {
6966 HEV blah;
6967
6968 if(DosCreateEventSem (NULL, &blah, 0L, FALSE))
6969 return 0;
6970
6971 return blah;
6972 }
6973
6974 /*
6975 * Resets a semaphore created by dw_event_new().
6976 * Parameters:
6977 * eve: The handle to the event returned by dw_event_new().
6978 */
6979 int API dw_event_reset(HEV eve)
6980 {
6981 ULONG count;
6982
6983 if(DosResetEventSem(eve, &count))
6984 return FALSE;
6985 return TRUE;
6986 }
6987
6988 /*
6989 * Posts a semaphore created by dw_event_new(). Causing all threads
6990 * waiting on this event in dw_event_wait to continue.
6991 * Parameters:
6992 * eve: The handle to the event returned by dw_event_new().
6993 */
6994 int API dw_event_post(HEV eve)
6995 {
6996 if(DosPostEventSem(eve))
6997 return FALSE;
6998 return TRUE;
6999 }
7000
7001
7002 /*
7003 * Waits on a semaphore created by dw_event_new(), until the
7004 * event gets posted or until the timeout expires.
7005 * Parameters:
7006 * eve: The handle to the event returned by dw_event_new().
7007 */
7008 int API dw_event_wait(HEV eve, unsigned long timeout)
7009 {
7010 int rc = DosWaitEventSem(eve, timeout);
7011 if(!rc)
7012 return 1;
7013 if(rc == ERROR_TIMEOUT)
7014 return -1;
7015 return 0;
7016 }
7017
7018 /*
7019 * Closes a semaphore created by dw_event_new().
7020 * Parameters:
7021 * eve: The handle to the event returned by dw_event_new().
7022 */
7023 int API dw_event_close(HEV *eve)
7024 {
7025 if(!eve || ~DosCloseEventSem(*eve))
7026 return FALSE;
7027 return TRUE;
7028 }
7029
7030 /*
7031 * Encapsulate the message queues on OS/2.
7032 */
7033 void _dwthreadstart(void *data)
7034 {
7035 HAB thishab = WinInitialize(0);
7036 HMQ thishmq = WinCreateMsgQueue(dwhab, 0);
7037 void (*threadfunc)(void *) = NULL;
7038 void **tmp = (void **)data;
7039
7040 threadfunc = (void (*)(void *))tmp[0];
7041 threadfunc(tmp[1]);
7042
7043 free(tmp);
7044
7045 WinDestroyMsgQueue(thishmq);
7046 WinTerminate(thishab);
7047 }
7048
7049 /*
7050 * Creates a new thread with a starting point of func.
7051 * Parameters:
7052 * func: Function which will be run in the new thread.
7053 * data: Parameter(s) passed to the function.
7054 * stack: Stack size of new thread (OS/2 and Windows only).
7055 */
7056 DWTID API dw_thread_new(void *func, void *data, int stack)
7057 {
7058 void **tmp = malloc(sizeof(void *) * 2);
7059
7060 tmp[0] = func;
7061 tmp[1] = data;
7062
7063 return (DWTID)_beginthread((void (*)(void *))_dwthreadstart, NULL, stack, (void *)tmp);
7064 }
7065
7066 /*
7067 * Ends execution of current thread immediately.
7068 */
7069 void API dw_thread_end(void)
7070 {
7071 _endthread();
7072 }
7073
7074 /*
7075 * Returns the current thread's ID.
7076 */
7077 DWTID API dw_thread_id(void)
7078 {
7079 return (DWTID)_threadid;
7080 }
7081
7082 /*
7083 * Cleanly terminates a DW session, should be signal handler safe.
7084 * Parameters:
7085 * exitcode: Exit code reported to the operating system.
7086 */
7087 void API dw_exit(int exitcode)
7088 {
7089 /* In case we are in a signal handler, don't
7090 * try to free memory that could possibly be
7091 * free()'d by the runtime already.
7092 */
7093 Root = NULL;
7094
7095 exit(exitcode);
7096 }
7097
7098 /*
7099 * Creates a splitbar window (widget) with given parameters.
7100 * Parameters:
7101 * type: Value can be BOXVERT or BOXHORZ.
7102 * topleft: Handle to the window to be top or left.
7103 * bottomright: Handle to the window to be bottom or right.
7104 * Returns:
7105 * A handle to a splitbar window or NULL on failure.
7106 */
7107 HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id)
7108 {
7109 HWND tmp = WinCreateWindow(HWND_OBJECT,
7110 SplitbarClassName,
7111 NULL,
7112 WS_VISIBLE | WS_CLIPCHILDREN,
7113 0,0,2000,1000,
7114 NULLHANDLE,
7115 HWND_TOP,
7116 id,
7117 NULL,
7118 NULL);
7119 if(tmp)
7120 {
7121 HWND tmpbox = dw_box_new(BOXVERT, 0);
7122 float *percent = malloc(sizeof(float));
7123
7124 dw_box_pack_start(tmpbox, topleft, 1, 1, TRUE, TRUE, 0);
7125 WinSetParent(tmpbox, tmp, FALSE);
7126 dw_window_set_data(tmp, "_dw_topleft", (void *)tmpbox);
7127
7128 tmpbox = dw_box_new(BOXVERT, 0);
7129 dw_box_pack_start(tmpbox, bottomright, 1, 1, TRUE, TRUE, 0);
7130 WinSetParent(tmpbox, tmp, FALSE);
7131 *percent = 50.0;
7132 dw_window_set_data(tmp, "_dw_bottomright", (void *)tmpbox);
7133 dw_window_set_data(tmp, "_dw_percent", (void *)percent);
7134 dw_window_set_data(tmp, "_dw_type", (void *)type);
7135 }
7136 return tmp;
7137 }
7138
7139 /*
7140 * Sets the position of a splitbar (pecentage).
7141 * Parameters:
7142 * handle: The handle to the splitbar returned by dw_splitbar_new().
7143 */
7144 void API dw_splitbar_set(HWND handle, float percent)
7145 {
7146 float *mypercent = (float *)dw_window_get_data(handle, "_dw_percent");
7147 int type = (int)dw_window_get_data(handle, "_dw_type");
7148 unsigned long width, height;
7149
7150 if(mypercent)
7151 *mypercent = percent;
7152
7153 dw_window_get_pos_size(handle, NULL, NULL, &width, &height);
7154
7155 _handle_splitbar_resize(handle, percent, type, width, height);
7156 }
7157
7158 /*
7159 * Gets the position of a splitbar (pecentage).
7160 * Parameters:
7161 * handle: The handle to the splitbar returned by dw_splitbar_new().
7162 */
7163 float API dw_splitbar_get(HWND handle)
7164 {
7165 float *percent = (float *)dw_window_get_data(handle, "_dw_percent");
7166
7167 if(percent)
7168 return *percent;
7169 return 0.0;
7170 }
7171
7172 /*
7173 * Pack windows (widgets) into a box from the start (or top).
7174 * Parameters:
7175 * box: Window handle of the box to be packed into.
7176 * item: Window handle of the item to be back.
7177 * width: Width in pixels of the item or -1 to be self determined.
7178 * height: Height in pixels of the item or -1 to be self determined.
7179 * hsize: TRUE if the window (widget) should expand horizontally to fill space given.
7180 * vsize: TRUE if the window (widget) should expand vertically to fill space given.
7181 * pad: Number of pixels of padding around the item.
7182 */
7183 void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
7184 {
7185 Box *thisbox;
7186
7187 if(WinWindowFromID(box, FID_CLIENT))
7188 {
7189 box = WinWindowFromID(box, FID_CLIENT);
7190 thisbox = WinQueryWindowPtr(box, QWP_USER);
7191 }
7192 else
7193 thisbox = WinQueryWindowPtr(box, QWP_USER);
7194 if(thisbox)
7195 {
7196 if(thisbox->type == BOXHORZ)
7197 dw_box_pack_end_stub(box, item, width, height, hsize, vsize, pad);
7198 else
7199 dw_box_pack_start_stub(box, item, width, height, hsize, vsize, pad);
7200 }
7201 }
7202
7203 void dw_box_pack_start_stub(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
7204 {
7205 Box *thisbox;
7206
7207 if(WinWindowFromID(box, FID_CLIENT))
7208 {
7209 box = WinWindowFromID(box, FID_CLIENT);
7210 thisbox = WinQueryWindowPtr(box, QWP_USER);
7211 hsize = TRUE;
7212 vsize = TRUE;
7213 }
7214 else
7215 thisbox = WinQueryWindowPtr(box, QWP_USER);
7216 if(thisbox)
7217 {
7218 int z;
7219 Item *tmpitem, *thisitem = thisbox->items;
7220 char tmpbuf[100];
7221
7222 tmpitem = malloc(sizeof(Item)*(thisbox->count+1));
7223
7224 for(z=0;z<thisbox->count;z++)
7225 {
7226 tmpitem[z+1] = thisitem[z];
7227 }
7228
7229 WinQueryClassName(item, 99, tmpbuf);
7230
7231 if(strncmp(tmpbuf, "#1", 3)==0)
7232 tmpitem[0].type = TYPEBOX;
7233 else
7234 tmpitem[0].type = TYPEITEM;
7235
7236 tmpitem[0].hwnd = item;
7237 tmpitem[0].origwidth = tmpitem[0].width = width;
7238 tmpitem[0].origheight = tmpitem[0].height = height;
7239 tmpitem[0].pad = pad;
7240 if(hsize)
7241 tmpitem[0].hsize = SIZEEXPAND;
7242 else
7243 tmpitem[0].hsize = SIZESTATIC;
7244
7245 if(vsize)
7246 tmpitem[0].vsize = SIZEEXPAND;
7247 else
7248 tmpitem[0].vsize = SIZESTATIC;
7249
7250 thisbox->items = tmpitem;
7251
7252 if(thisbox->count)
7253 free(thisitem);
7254
7255 thisbox->count++;
7256
7257 WinQueryClassName(item, 99, tmpbuf);
7258 /* Don't set the ownership if it's an entryfield or spinbutton */
7259 if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0)
7260 WinSetOwner(item, box);
7261 WinSetParent(item, box, FALSE);
7262 }
7263 }
7264
7265 /* The following two functions graciously contributed by Peter Nielsen. */
7266 static ULONG _ParseBuildLevel (char* pchBuffer, ULONG ulSize) {
7267 char* pchStart = pchBuffer;
7268 char* pchEnd = pchStart + ulSize - 2;
7269
7270 while (pchEnd >= pchStart)
7271 {
7272 if ((pchEnd[0] == '#') && (pchEnd[1] == '@'))
7273 {
7274 *pchEnd-- = '\0';
7275 while (pchEnd >= pchStart)
7276 {
7277 if ((pchEnd[0] == '@') && (pchEnd[1] == '#'))
7278 {
7279 ULONG ulMajor = 0;
7280 ULONG ulMinor = 0;
7281
7282 char* pch = pchEnd + 2;
7283 while (!isdigit ((int)*pch) && *pch)
7284 pch++;
7285
7286 while (isdigit ((int)*pch))
7287 ulMajor = ulMajor * 10 + *pch++ - '0';
7288
7289 if (*pch == '.')
7290 {
7291 while (isdigit ((int)*++pch))
7292 ulMinor = ulMinor * 10 + *pch - '0';
7293 }
7294 return ((ulMajor << 16) | ulMinor);
7295 }
7296 pchEnd--;
7297 }
7298 }
7299 pchEnd--;
7300 }
7301 return (0);
7302 }
7303
7304 ULONG _GetSystemBuildLevel(void) {
7305 /* 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.
7306 * 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.
7307 */
7308 ULONG ulBootDrive = 0;
7309 ULONG ulBuild = 0;
7310 if (DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive, sizeof (ulBootDrive)) == NO_ERROR)
7311 {
7312 char achFileName[11] = "C:\\OS2KRNL";
7313 HFILE hfile;
7314 ULONG ulResult;
7315
7316 achFileName[0] = (char)('A'+ulBootDrive-1);
7317
7318 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)
7319 {
7320 ULONG ulFileSize = 0;
7321 if (DosSetFilePtr (hfile, 0, FILE_END, &ulFileSize) == NO_ERROR)
7322 {
7323 const ULONG ulFirstTry = min (256, ulFileSize);
7324 if (DosSetFilePtr (hfile, -(LONG)ulFirstTry, FILE_END, &ulResult) == NO_ERROR)
7325 {
7326 char *pchBuffer = malloc(ulFirstTry);
7327 if (DosRead (hfile, pchBuffer, ulFirstTry, &ulResult) == NO_ERROR)
7328 {
7329 ulBuild = _ParseBuildLevel (pchBuffer, ulFirstTry);
7330 if (ulBuild == 0)
7331 {
7332 if (DosSetFilePtr (hfile, 0, FILE_BEGIN, &ulResult) == NO_ERROR)
7333 {
7334 free(pchBuffer);
7335 pchBuffer = malloc(ulFileSize);
7336
7337 if (DosRead (hfile, pchBuffer, ulFileSize, &ulResult) == NO_ERROR)
7338 ulBuild = _ParseBuildLevel (pchBuffer, ulFileSize);
7339 }
7340 }
7341 }
7342 free(pchBuffer);
7343 }
7344 }
7345 DosClose (hfile);
7346 }
7347 }
7348 return (ulBuild);
7349 }
7350
7351 /*
7352 * Sets the default focus item for a window/dialog.
7353 * Parameters:
7354 * window: Toplevel window or dialog.
7355 * defaultitem: Handle to the dialog item to be default.
7356 */
7357 void API dw_window_default(HWND window, HWND defaultitem)
7358 {
7359 Box *thisbox = NULL;
7360 HWND box;
7361
7362 box = WinWindowFromID(window, FID_CLIENT);
7363 if(box)
7364 thisbox = WinQueryWindowPtr(box, QWP_USER);
7365
7366 if(thisbox)
7367 thisbox->defaultitem = defaultitem;
7368 }
7369
7370 /*
7371 * Sets window to click the default dialog item when an ENTER is pressed.
7372 * Parameters:
7373 * window: Window (widget) to look for the ENTER press.
7374 * next: Window (widget) to move to next (or click)
7375 */
7376 void API dw_window_click_default(HWND window, HWND next)
7377 {
7378 WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER);
7379
7380 if(blah)
7381 blah->clickdefault = next;
7382 }
7383
7384 /*
7385 * Returns some information about the current operating environment.
7386 * Parameters:
7387 * env: Pointer to a DWEnv struct.
7388 */
7389 void API dw_environment_query(DWEnv *env)
7390 {
7391 ULONG Build;
7392
7393 if(!env)
7394 return;
7395
7396 /* The default is OS/2 2.0 */
7397 strcpy(env->osName,"OS/2");
7398 env->MajorVersion = 2;
7399 env->MinorVersion = 0;
7400
7401 Build = _GetSystemBuildLevel();
7402 env->MinorBuild = Build & 0xFFFF;
7403 env->MajorBuild = Build >> 16;
7404
7405 if (aulBuffer[0] == 20)
7406 {
7407 int i = (unsigned int)aulBuffer[1];
7408 if (i > 20)
7409 {
7410 strcpy(env->osName,"Warp");
7411 env->MajorVersion = (int)i/10;
7412 env->MinorVersion = i-(((int)i/10)*10);
7413 }
7414 else if (i == 10)
7415 env->MinorVersion = 1;
7416 }
7417 strcpy(env->buildDate, __DATE__);
7418 strcpy(env->buildTime, __TIME__);
7419 env->DWMajorVersion = DW_MAJOR_VERSION;
7420 env->DWMinorVersion = DW_MINOR_VERSION;
7421 env->DWSubVersion = DW_SUB_VERSION;
7422 }
7423
7424 /*
7425 * Opens a file dialog and queries user selection.
7426 * Parameters:
7427 * title: Title bar text for dialog.
7428 * defpath: The default path of the open dialog.
7429 * ext: Default file extention.
7430 * flags: DW_FILE_OPEN or DW_FILE_SAVE.
7431 * Returns:
7432 * NULL on error. A malloced buffer containing
7433 * the file path on success.
7434 *
7435 */
7436 char * API dw_file_browse(char *title, char *defpath, char *ext, int flags)
7437 {
7438 FILEDLG fild;
7439 HWND hwndFile;
7440 int len;
7441
7442 if(defpath)
7443 strcpy(fild.szFullFile, defpath);
7444 else
7445 strcpy(fild.szFullFile, "");
7446
7447 len = strlen(fild.szFullFile);
7448
7449 if(len)
7450 {
7451 if(fild.szFullFile[len-1] != '\\')
7452 strcat(fild.szFullFile, "\\");
7453 }
7454 strcat(fild.szFullFile, "*");
7455
7456 if(ext)
7457 {
7458 strcat(fild.szFullFile, ".");
7459 strcat(fild.szFullFile, ext);
7460 }
7461
7462 fild.cbSize = sizeof(FILEDLG);
7463 fild.fl = /*FDS_HELPBUTTON |*/ FDS_CENTER | FDS_OPEN_DIALOG;
7464 fild.pszTitle = title;
7465 fild.pszOKButton = ((flags & DW_FILE_SAVE) ? "Save" : "Open");
7466 fild.ulUser = 0L;
7467 fild.pfnDlgProc = (PFNWP)WinDefFileDlgProc;
7468 fild.lReturn = 0L;
7469 fild.lSRC = 0L;
7470 fild.hMod = 0;
7471 fild.x = 0;
7472 fild.y = 0;
7473 fild.pszIType = (PSZ)NULL;
7474 fild.papszITypeList = (PAPSZ)NULL;
7475 fild.pszIDrive = (PSZ)NULL;
7476 fild.papszIDriveList= (PAPSZ)NULL;
7477 fild.sEAType = (SHORT)0;
7478 fild.papszFQFilename= (PAPSZ)NULL;
7479 fild.ulFQFCount = 0L;
7480
7481 hwndFile = WinFileDlg(HWND_DESKTOP, HWND_DESKTOP, &fild);
7482 if(hwndFile)
7483 {
7484 switch(fild.lReturn)
7485 {
7486 case DID_OK:
7487 return strdup(fild.szFullFile);
7488 case DID_CANCEL:
7489 return NULL;
7490 }
7491 }
7492 return NULL;
7493 }
7494
7495 /* Internal function to set drive and directory */
7496 int _SetPath(char *path)
7497 {
7498 #ifndef __WATCOMC__
7499 if(strlen(path) > 2)
7500 {
7501 if(path[1] == ':')
7502 {
7503 char drive = toupper(path[0]);
7504 _chdrive((drive - 'A')+1);
7505 }
7506 }
7507 #endif
7508 return chdir(path);
7509 }
7510
7511 /*
7512 * Execute and external program in a seperate session.
7513 * Parameters:
7514 * program: Program name with optional path.
7515 * type: Either DW_EXEC_CON or DW_EXEC_GUI.
7516 * params: An array of pointers to string arguements.
7517 * Returns:
7518 * -1 on error.
7519 */
7520 int API dw_exec(char *program, int type, char **params)
7521 {
7522 return spawnvp(P_NOWAIT, program, (const char **)params);
7523 }
7524
7525 /*
7526 * Loads a web browser pointed at the given URL.
7527 * Parameters:
7528 * url: Uniform resource locator.
7529 */
7530 int API dw_browse(char *url)
7531 {
7532 /* Is there a way to find the webbrowser in Unix? */
7533 char *execargs[3], browser[1024], *olddir, *newurl = NULL;
7534 int len, ret;
7535
7536 olddir = _getcwd(NULL, 1024);
7537
7538 PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS",
7539 "DefaultWorkingDir", NULL, browser, 1024);
7540
7541 if(browser[0])
7542 _SetPath(browser);
7543
7544 PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS",
7545 "DefaultBrowserExe", NULL, browser, 1024);
7546
7547 len = strlen(browser) - strlen("explore.exe");
7548
7549 execargs[0] = browser;
7550 execargs[1] = url;
7551 execargs[2] = NULL;
7552
7553 /* Special case for Web Explorer, it requires file:/// instead
7554 * of file:// so I am handling it here.
7555 */
7556 if(len > 0)
7557 {
7558 if(stricmp(&browser[len], "explore.exe") == 0)
7559 {
7560 int newlen, z;
7561 newurl = malloc(strlen(url) + 2);
7562 sprintf(newurl, "file:///%s", &url[7]);
7563 newlen = strlen(newurl);
7564 for(z=8;z<(newlen-8);z++)
7565 {
7566 if(newurl[z] == '|')
7567 newurl[z] = ':';
7568 if(newurl[z] == '/')
7569 newurl[z] = '\\';
7570 }
7571 execargs[1] = newurl;
7572 }
7573 }
7574
7575 ret = dw_exec(browser, DW_EXEC_GUI, execargs);
7576
7577 if(olddir)
7578 {
7579 _SetPath(olddir);
7580 free(olddir);
7581 }
7582 if(newurl)
7583 free(newurl);
7584 return ret;
7585 }
7586
7587 /*
7588 * Returns a pointer to a static buffer which containes the
7589 * current user directory. Or the root directory (C:\ on
7590 * OS/2 and Windows).
7591 */
7592 char * API dw_user_dir(void)
7593 {
7594 static char _user_dir[1024] = "";
7595
7596 if(!_user_dir[0])
7597 {
7598 char *home = getenv("HOME");
7599
7600 if(home)
7601 strcpy(_user_dir, home);
7602 else
7603 strcpy(_user_dir, "C:\\");
7604 }
7605 return _user_dir;
7606 }
7607
7608 /*
7609 * Call a function from the window (widget)'s context.
7610 * Parameters:
7611 * handle: Window handle of the widget.
7612 * function: Function pointer to be called.
7613 * data: Pointer to the data to be passed to the function.
7614 */
7615 void API dw_window_function(HWND handle, void *function, void *data)
7616 {
7617 WinSendMsg(handle, WM_USER, (MPARAM)function, (MPARAM)data);
7618 }
7619
7620 /* Functions for managing the user data lists that are associated with
7621 * a given window handle. Used in dw_window_set_data() and
7622 * dw_window_get_data().
7623 */
7624 UserData *_find_userdata(UserData **root, char *varname)
7625 {
7626 UserData *tmp = *root;
7627
7628 while(tmp)
7629 {
7630 if(stricmp(tmp->varname, varname) == 0)
7631 return tmp;
7632 tmp = tmp->next;
7633 }
7634 return NULL;
7635 }
7636
7637 int _new_userdata(UserData **root, char *varname, void *data)
7638 {
7639 UserData *new = _find_userdata(root, varname);
7640
7641 if(new)
7642 {
7643 new->data = data;
7644 return TRUE;
7645 }
7646 else
7647 {
7648 new = malloc(sizeof(UserData));
7649 if(new)
7650 {
7651 new->varname = strdup(varname);
7652 new->data = data;
7653
7654 new->next = NULL;
7655
7656 if (!*root)
7657 *root = new;
7658 else
7659 {
7660 UserData *prev = NULL, *tmp = *root;
7661 while(tmp)
7662 {
7663 prev = tmp;
7664 tmp = tmp->next;
7665 }
7666 if(prev)
7667 prev->next = new;
7668 else
7669 *root = new;
7670 }
7671 return TRUE;
7672 }
7673 }
7674 return FALSE;
7675 }
7676
7677 int _remove_userdata(UserData **root, char *varname, int all)
7678 {
7679 UserData *prev = NULL, *tmp = *root;
7680
7681 while(tmp)
7682 {
7683 if(all || stricmp(tmp->varname, varname) == 0)
7684 {
7685 if(!prev)
7686 {
7687 *root = tmp->next;
7688 free(tmp->varname);
7689 free(tmp);
7690 if(!all)
7691 return 0;
7692 tmp = *root;
7693 }
7694 else
7695 {
7696 /* If all is true we should
7697 * never get here.
7698 */
7699 prev->next = tmp->next;
7700 free(tmp->varname);
7701 free(tmp);
7702 return 0;
7703 }
7704 }
7705 else
7706 {
7707 prev = tmp;
7708 tmp = tmp->next;
7709 }
7710 }
7711 return 0;
7712 }
7713
7714 /*
7715 * Add a named user data item to a window handle.
7716 * Parameters:
7717 * window: Window handle of signal to be called back.
7718 * dataname: A string pointer identifying which signal to be hooked.
7719 * data: User data to be passed to the handler function.
7720 */
7721 void API dw_window_set_data(HWND window, char *dataname, void *data)
7722 {
7723 WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER);
7724
7725 if(!blah)
7726 {
7727 if(!dataname)
7728 return;
7729
7730 blah = calloc(1, sizeof(WindowData));
7731 WinSetWindowPtr(window, QWP_USER, blah);
7732 }
7733
7734 if(data)
7735 _new_userdata(&(blah->root), dataname, data);
7736 else
7737 {
7738 if(dataname)
7739 _remove_userdata(&(blah->root), dataname, FALSE);
7740 else
7741 _remove_userdata(&(blah->root), NULL, TRUE);
7742 }
7743 }
7744
7745 /*
7746 * Gets a named user data item to a window handle.
7747 * Parameters:
7748 * window: Window handle of signal to be called back.
7749 * dataname: A string pointer identifying which signal to be hooked.
7750 * data: User data to be passed to the handler function.
7751 */
7752 void *dw_window_get_data(HWND window, char *dataname)
7753 {
7754 WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER);
7755
7756 if(blah && blah->root && dataname)
7757 {
7758 UserData *ud = _find_userdata(&(blah->root), dataname);
7759 if(ud)
7760 return ud->data;
7761 }
7762 return NULL;
7763 }
7764
7765 /*
7766 * Add a callback to a timer event.
7767 * Parameters:
7768 * interval: Milliseconds to delay between calls.
7769 * sigfunc: The pointer to the function to be used as the callback.
7770 * data: User data to be passed to the handler function.
7771 * Returns:
7772 * Timer ID for use with dw_timer_disconnect(), 0 on error.
7773 */
7774 int API dw_timer_connect(int interval, void *sigfunc, void *data)
7775 {
7776 if(sigfunc)
7777 {
7778 int timerid = WinStartTimer(dwhab, NULLHANDLE, timerid, interval);
7779
7780 if(timerid)
7781 {
7782 _new_signal(WM_TIMER, NULLHANDLE, timerid, sigfunc, data);
7783 return timerid;
7784 }
7785 }
7786 return 0;
7787 }
7788
7789 /*
7790 * Removes timer callback.
7791 * Parameters:
7792 * id: Timer ID returned by dw_timer_connect().
7793 */
7794 void API dw_timer_disconnect(int id)
7795 {
7796 SignalHandler *prev = NULL, *tmp = Root;
7797
7798 /* 0 is an invalid timer ID */
7799 if(!id)
7800 return;
7801
7802 WinStopTimer(dwhab, NULLHANDLE, id);
7803
7804 while(tmp)
7805 {
7806 if(tmp->id == id)
7807 {
7808 if(prev)
7809 {
7810 prev->next = tmp->next;
7811 free(tmp);
7812 tmp = prev->next;
7813 }
7814 else
7815 {
7816 Root = tmp->next;
7817 free(tmp);
7818 tmp = Root;
7819 }
7820 }
7821 else
7822 {
7823 prev = tmp;
7824 tmp = tmp->next;
7825 }
7826 }
7827 }
7828
7829 /*
7830 * Add a callback to a window event.
7831 * Parameters:
7832 * window: Window handle of signal to be called back.
7833 * signame: A string pointer identifying which signal to be hooked.
7834 * sigfunc: The pointer to the function to be used as the callback.
7835 * data: User data to be passed to the handler function.
7836 */
7837 void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
7838 {
7839 ULONG message = 0L;
7840
7841 if(strcmp(signame, "lose-focus") == 0)
7842 {
7843 char tmpbuf[100];
7844
7845 WinQueryClassName(window, 99, tmpbuf);
7846
7847 if(strncmp(tmpbuf, "#2", 3) == 0)
7848 {
7849 HENUM henum = WinBeginEnumWindows(window);
7850 HWND child = WinGetNextWindow(henum);
7851 WinEndEnumWindows(henum);
7852 if(child)
7853 window = child;
7854 }
7855 }
7856 if(window && signame && sigfunc)
7857 {
7858 if((message = _findsigmessage(signame)) != 0)
7859 _new_signal(message, window, 0, sigfunc, data);
7860 }
7861 }
7862
7863 /*
7864 * Removes callbacks for a given window with given name.
7865 * Parameters:
7866 * window: Window handle of callback to be removed.
7867 */
7868 void API dw_signal_disconnect_by_name(HWND window, char *signame)
7869 {
7870 SignalHandler *prev = NULL, *tmp = Root;
7871 ULONG message;
7872
7873 if(!window || !signame || (message = _findsigmessage(signame)) == 0)
7874 return;
7875
7876 while(tmp)
7877 {
7878 if(tmp->window == window && tmp->message == message)
7879 {
7880 if(prev)
7881 {
7882 prev->next = tmp->next;
7883 free(tmp);
7884 tmp = prev->next;
7885 }
7886 else
7887 {
7888 Root = tmp->next;
7889 free(tmp);
7890 tmp = Root;
7891 }
7892 }
7893 else
7894 {
7895 prev = tmp;
7896 tmp = tmp->next;
7897 }
7898 }
7899 }
7900
7901 /*
7902 * Removes all callbacks for a given window.
7903 * Parameters:
7904 * window: Window handle of callback to be removed.
7905 */
7906 void API dw_signal_disconnect_by_window(HWND window)
7907 {
7908 SignalHandler *prev = NULL, *tmp = Root;
7909
7910 while(tmp)
7911 {
7912 if(tmp->window == window)
7913 {
7914 if(prev)
7915 {
7916 prev->next = tmp->next;
7917 free(tmp);
7918 tmp = prev->next;
7919 }
7920 else
7921 {
7922 Root = tmp->next;
7923 free(tmp);
7924 tmp = Root;
7925 }
7926 }
7927 else
7928 {
7929 prev = tmp;
7930 tmp = tmp->next;
7931 }
7932 }
7933 }
7934
7935 /*
7936 * Removes all callbacks for a given window with specified data.
7937 * Parameters:
7938 * window: Window handle of callback to be removed.
7939 * data: Pointer to the data to be compared against.
7940 */
7941 void API dw_signal_disconnect_by_data(HWND window, void *data)
7942 {
7943 SignalHandler *prev = NULL, *tmp = Root;
7944
7945 while(tmp)
7946 {
7947 if(tmp->window == window && tmp->data == data)
7948 {
7949 if(prev)
7950 {
7951 prev->next = tmp->next;
7952 free(tmp);
7953 tmp = prev->next;
7954 }
7955 else
7956 {
7957 Root = tmp->next;
7958 free(tmp);
7959 tmp = Root;
7960 }
7961 }
7962 else
7963 {
7964 prev = tmp;
7965 tmp = tmp->next;
7966 }
7967 }
7968 }
7969
7970