comparison win/dw.c @ 3:67a643a734d9

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