Release 971101
[wine] / controls / status.c
1 /*
2  * Interface code to StatusWindow widget/control
3  *
4  * Copyright 1996 Bruce Milner
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "windows.h"
10 #include "status.h"
11 #include "commctrl.h"
12 #include "heap.h"
13 #include "win.h"
14
15 /*
16  * Run tests using Waite Group Windows95 API Bible Vol. 1&2
17  * The second cdrom contains executables drawstat.exe,gettext.exe,
18  * simple.exe, getparts.exe, setparts.exe, statwnd.exe
19  */
20
21 /*
22  * Fixme/Todo
23  * 1) Add size grip to status bar - SBARS_SIZEGRIP
24  * 2) Don't hard code bar to bottom of window, allow CCS_TOP also
25  * 3) Fix SBT_OWNERDRAW
26  * 4) Add DrawStatusText32A funtion
27  */
28
29 static STATUSWINDOWINFO *GetStatusInfo(HWND32 hwnd)
30 {
31     WND *wndPtr;
32
33     wndPtr = WIN_FindWndPtr(hwnd);
34     return ((STATUSWINDOWINFO *) &wndPtr->wExtra[0]);
35 }
36
37 static BOOL32 SW_Refresh( HWND32 hwnd, HDC32 hdc, STATUSWINDOWINFO *self )
38 {
39         int     i;
40
41         if (!IsWindowVisible32(hwnd)) {
42             return (TRUE);
43         }
44
45         if (self->simple) {
46             DrawStatusText32A(hdc,
47                               &self->part0.bound,
48                               self->part0.text,
49                               self->part0.style);
50         }
51         else {
52             for (i = 0; i < self->numParts; i++) {
53                 DrawStatusText32A(hdc,
54                                   &self->parts[i].bound,
55                                   self->parts[i].text,
56                                   self->parts[i].style);
57             }
58         }
59
60         return TRUE;
61 }
62
63
64 static LRESULT
65 SW_GetBorders(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
66 {
67     LPINT32     out;
68
69     /* FIXME for sizegrips */
70     out = (LPINT32) lParam;
71     out[0] = 1; /* vertical border width */
72     out[1] = 1; /* horizontal border width */
73     out[2] = 1; /* width of border between rectangles */
74     return TRUE;
75 }
76
77 static void
78 SW_SetPartBounds(HWND32 hwnd, STATUSWINDOWINFO *self)
79 {
80     int i;
81     RECT32      rect, *r;
82     STATUSWINDOWPART *part;
83     int sep = 1;
84
85     /* get our window size */
86     GetClientRect32(hwnd, &rect);
87
88     /* set bounds for simple rectangle */
89     self->part0.bound = rect;
90
91     /* set bounds for non-simple rectangles */
92     for (i = 0; i < self->numParts; i++) {
93         part = &self->parts[i];
94         r = &self->parts[i].bound;
95         r->top = rect.top;
96         r->bottom = rect.bottom;
97         if (i == 0)
98             r->left = 0;
99         else
100             r->left = self->parts[i-1].bound.right+sep;
101         if (part->x == -1)
102             r->right = rect.right;
103         else
104             r->right = part->x;
105     }
106 }
107
108 static LRESULT
109 SW_SetText(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
110 {
111     int part_num;
112     int style;
113     LPSTR       text;
114     int len;
115     STATUSWINDOWPART *part;
116
117     text = (LPSTR) lParam;
118     part_num = ((INT32) wParam) & 0x00ff;
119     style = ((INT32) wParam) & 0xff00;
120
121     if (part_num >= 255)
122         return FALSE;
123
124     if ((self->simple) || (part_num==255))
125         part = &self->part0;
126     else
127         part = &self->parts[part_num];
128     part->style = style;
129     if (style == SBT_OWNERDRAW) {
130         part->text = text;
131     }
132     else {
133         /* duplicate string */
134         if (part->text)
135             HeapFree(SystemHeap, 0, part->text);
136         part->text = 0;
137         if (text && (len = lstrlen32A(text))) {
138             part->text = HeapAlloc(SystemHeap, 0, len+1);
139             lstrcpy32A(part->text, text);
140         }
141     }
142     InvalidateRect32(hwnd, &part->bound, FALSE);
143     return TRUE;
144 }
145
146 static LRESULT
147 SW_SetParts(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
148 {
149     HDC32       hdc;
150     LPINT32 parts;
151     STATUSWINDOWPART *  tmp;
152     int i;
153     int oldNumParts;
154
155     if (self->simple) {
156         self->simple = FALSE;
157     }
158     oldNumParts = self->numParts;
159     self->numParts = (INT32) wParam;
160     parts = (LPINT32) lParam;
161     if (oldNumParts > self->numParts) {
162         for (i = self->numParts ; i < oldNumParts; i++) {
163             if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
164                 HeapFree(SystemHeap, 0, self->parts[i].text);
165         }
166     }
167     else if (oldNumParts < self->numParts) {
168         tmp = HeapAlloc(SystemHeap, HEAP_ZERO_MEMORY,
169                         sizeof(STATUSWINDOWPART) * self->numParts);
170         for (i = 0; i < oldNumParts; i++) {
171             tmp[i] = self->parts[i];
172         }
173         if (self->parts)
174             HeapFree(SystemHeap, 0, self->parts);
175         self->parts = tmp;
176     }
177     
178     for (i = 0; i < self->numParts; i++) {
179         self->parts[i].x = parts[i];
180     }
181     SW_SetPartBounds(hwnd, self);
182
183     hdc = GetDC32(hwnd);
184     SW_Refresh(hwnd, hdc, self);
185     ReleaseDC32(hwnd, hdc);
186     return TRUE;
187 }
188
189 static LRESULT
190 SW_GetParts(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
191 {
192     LPINT32 parts;
193     INT32       num_parts;
194     int i;
195
196     self = GetStatusInfo(hwnd);
197     num_parts = (INT32) wParam;
198     parts = (LPINT32) lParam;
199     if (parts) {
200         return (self->numParts);
201         for (i = 0; i < num_parts; i++) {
202             parts[i] = self->parts[i].x;
203         }
204     }
205     return (self->numParts);
206 }
207
208 static LRESULT
209 SW_Create(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
210 {
211     RECT32      rect;
212     LPCREATESTRUCT32A lpCreate = (LPCREATESTRUCT32A) lParam;
213     int height, width;
214     HDC32       hdc;
215     HWND32      parent;
216
217     self->numParts = 0;
218     self->parts = 0;
219     self->simple = TRUE;
220     GetClientRect32(hwnd, &rect);
221
222     /* initialize simple case */
223     self->part0.bound = rect;
224     self->part0.text = 0;
225     self->part0.x = 0;
226     self->part0.style = 0;
227
228     height = 40;
229     if ((hdc = GetDC32(0))) {
230         TEXTMETRIC32A tm;
231         GetTextMetrics32A(hdc, &tm);
232         self->textHeight = tm.tmHeight;
233         ReleaseDC32(0, hdc);
234     }
235
236     parent = GetParent32(hwnd);
237     GetClientRect32(parent, &rect);
238     width = rect.right - rect.left;
239     height = (self->textHeight * 3)/2;
240     MoveWindow32(hwnd, lpCreate->x, lpCreate->y-1, width, height, FALSE);
241     SW_SetPartBounds(hwnd, self);
242     return 0;
243 }
244
245 static LRESULT
246 SW_GetRect(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
247 {
248     int part_num;
249     LPRECT32  rect;
250
251     part_num = ((INT32) wParam) & 0x00ff;
252     rect = (LPRECT32) lParam;
253     if (self->simple)
254         *rect = self->part0.bound;
255     else
256         *rect = self->parts[part_num].bound;
257     return TRUE;
258 }
259
260 static LRESULT
261 SW_GetText(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
262 {
263     int part_num;
264     LRESULT     result;
265     STATUSWINDOWPART *part;
266     LPSTR       out_text;
267
268     part_num = ((INT32) wParam) & 0x00ff;
269     out_text = (LPSTR) lParam;
270     if (self->simple)
271         part = &self->part0;
272     else
273         part = &self->parts[part_num];
274
275     if (part->style == SBT_OWNERDRAW)
276         result = (LRESULT) part->text;
277     else {
278         result = part->text ? lstrlen32A(part->text) : 0;
279         result |= (part->style << 16);
280         if (out_text) {
281             lstrcpy32A(out_text, part->text);
282         }
283     }
284     return result;
285 }
286
287 static LRESULT
288 SW_GetTextLength(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
289 {
290     int part_num;
291     STATUSWINDOWPART *part;
292     DWORD       result;
293
294     part_num = ((INT32) wParam) & 0x00ff;
295
296     if (self->simple)
297         part = &self->part0;
298     else
299         part = &self->parts[part_num];
300
301     if (part->text)
302         result = lstrlen32A(part->text);
303     else
304         result = 0;
305
306     result |= (part->style << 16);
307     return result;
308 }
309
310 static LRESULT
311 SW_SetMinHeight(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
312 {
313     /* FIXME */
314     /* size is wParam | 2*pixels_of_horz_border */
315     return TRUE;
316 }
317
318 static LRESULT
319 SW_Simple(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
320 {
321     BOOL32 simple;
322     HDC32       hdc;
323
324     simple = (BOOL32) wParam;
325     self->simple = simple;
326     hdc = GetDC32(hwnd);
327     SW_Refresh(hwnd, hdc, self);
328     ReleaseDC32(hwnd, hdc);
329     return TRUE;
330 }
331
332 static LRESULT
333 SW_Size(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
334 {
335     /* Need to resize width to match parent */
336     INT32       width, height, x, y;
337     RECT32      parent_rect;
338     HWND32      parent;
339
340     INT32       flags;
341
342     flags = (INT32) wParam;
343
344     /* FIXME for flags =
345      * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
346      */
347
348     if (flags == SIZE_RESTORED) {
349         /* width and height don't apply */
350         parent = GetParent32(hwnd);
351         GetClientRect32(parent, &parent_rect);
352         height = (self->textHeight * 3)/2;
353         width = parent_rect.right - parent_rect.left;
354         x = parent_rect.left;
355         y = parent_rect.bottom - height;
356         MoveWindow32(hwnd, parent_rect.left, parent_rect.bottom - height - 1,
357                      width, height, TRUE);
358         SW_SetPartBounds(hwnd, self);
359     }
360     return 0;
361 }
362
363 static LRESULT
364 SW_Destroy(STATUSWINDOWINFO *self, HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
365 {
366     int i;
367
368     for (i = 0; i < self->numParts; i++) {
369         if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
370             HeapFree(SystemHeap, 0, self->parts[i].text);
371     }
372     if (self->part0.text && (self->part0.style != SBT_OWNERDRAW))
373         HeapFree(SystemHeap, 0, self->part0.text);
374     HeapFree(SystemHeap, 0, self->parts);
375     return 0;
376 }
377
378
379
380 static LRESULT
381 SW_Paint(STATUSWINDOWINFO *self, HWND32 hwnd)
382 {
383     HDC32 hdc;
384     PAINTSTRUCT32       ps;
385
386     hdc = BeginPaint32(hwnd, &ps);
387     SW_Refresh(hwnd, hdc, self);
388     EndPaint32(hwnd, &ps);
389     return 0;
390 }
391
392 LRESULT WINAPI StatusWindowProc( HWND32 hwnd, UINT32 msg,
393                                  WPARAM32 wParam, LPARAM lParam )
394 {
395     STATUSWINDOWINFO *self;
396
397     self = GetStatusInfo(hwnd);
398
399     switch (msg) {
400     case SB_GETBORDERS:
401         return SW_GetBorders(self, hwnd, wParam, lParam);
402     case SB_GETPARTS:
403         return SW_GetParts(self, hwnd, wParam, lParam);
404     case SB_GETRECT:
405         return SW_GetRect(self, hwnd, wParam, lParam);
406     case SB_GETTEXT32A:
407         return SW_GetText(self, hwnd, wParam, lParam);
408     case SB_GETTEXTLENGTH32A:
409         return SW_GetTextLength(self, hwnd, wParam, lParam);
410     case SB_SETMINHEIGHT:
411         return SW_SetMinHeight(self, hwnd, wParam, lParam);
412     case SB_SETPARTS:   
413         return SW_SetParts(self, hwnd, wParam, lParam);
414     case SB_SETTEXT32A:
415         return SW_SetText(self, hwnd, wParam, lParam);
416     case SB_SIMPLE:
417         return SW_Simple(self, hwnd, wParam, lParam);
418
419     case WM_CREATE:
420         return SW_Create(self, hwnd, wParam, lParam);
421     case WM_DESTROY:
422         return SW_Destroy(self, hwnd, wParam, lParam);
423     case WM_PAINT:
424         return SW_Paint(self, hwnd);
425     case WM_SIZE:
426         return SW_Size(self, hwnd, wParam, lParam);
427     default:
428         return DefWindowProc32A(hwnd, msg, wParam, lParam);
429     }
430     return 0;
431 }
432
433
434