comparison os2/dw.c @ 212:f2d1e231922e

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