blob: dae876df9f7127714e6ac2994902862607d3d148 [file] [log] [blame]
Alexandre Julliard0e607781993-11-03 19:23:37 +00001/*
Alexandre Julliard2787be81995-05-22 18:23:01 +00002 * Listbox controls
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003 *
4 * Copyright 1996 Alexandre Julliard
Alexandre Julliard2787be81995-05-22 18:23:01 +00005 */
6
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00007#include <string.h>
David Luyeree517e81999-02-28 12:27:56 +00008#include <stdlib.h>
Alex Korobka311d3291999-01-01 18:40:02 +00009#include "wine/winuser16.h"
10#include "winuser.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000011#include "winerror.h"
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000012#include "drive.h"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000013#include "heap.h"
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000014#include "spy.h"
15#include "win.h"
Alexandre Julliarddf2673b1997-03-29 17:20:20 +000016#include "combo.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000017#include "debug.h"
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +000018#include "tweak.h"
Alexandre Julliard0e607781993-11-03 19:23:37 +000019
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000020/* Unimplemented yet:
21 * - LBS_NOSEL
22 * - LBS_USETABSTOPS
23 * - Unicode
24 * - Locale handling
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000025 */
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000026
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000027/* Items array granularity */
28#define LB_ARRAY_GRANULARITY 16
Alexandre Julliard0e607781993-11-03 19:23:37 +000029
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000030/* Scrolling timeout in ms */
31#define LB_SCROLL_TIMEOUT 50
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000032
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000033/* Listbox system timer id */
34#define LB_TIMER_ID 2
Alexandre Julliardac9c9b01996-07-28 18:50:11 +000035
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000036/* Item structure */
37typedef struct
Alexandre Julliard2787be81995-05-22 18:23:01 +000038{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000039 LPSTR str; /* Item text */
Alexandre Julliarda3960291999-02-26 11:11:13 +000040 BOOL selected; /* Is item selected? */
41 UINT height; /* Item height (only for OWNERDRAWVARIABLE) */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000042 DWORD data; /* User data */
43} LB_ITEMDATA;
Alexandre Julliard2787be81995-05-22 18:23:01 +000044
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000045/* Listbox structure */
46typedef struct
Alexandre Julliard2787be81995-05-22 18:23:01 +000047{
Alexandre Julliarda3960291999-02-26 11:11:13 +000048 HANDLE heap; /* Heap for this listbox */
49 HWND owner; /* Owner window to send notifications to */
50 UINT style; /* Window style */
51 INT width; /* Window width */
52 INT height; /* Window height */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000053 LB_ITEMDATA *items; /* Array of items */
Alexandre Julliarda3960291999-02-26 11:11:13 +000054 INT nb_items; /* Number of items */
55 INT top_item; /* Top visible item */
56 INT selected_item; /* Selected item */
57 INT focus_item; /* Item that has the focus */
58 INT anchor_item; /* Anchor item for extended selection */
59 INT item_height; /* Default item height */
60 INT page_size; /* Items per listbox page */
61 INT column_width; /* Column width for multi-column listboxes */
62 INT horz_extent; /* Horizontal extent (0 if no hscroll) */
63 INT horz_pos; /* Horizontal position */
64 INT nb_tabs; /* Number of tabs in array */
65 INT *tabs; /* Array of tabs */
66 BOOL caret_on; /* Is caret on? */
Luc Tourangeau5ee117b1999-04-04 12:48:21 +000067 BOOL captured; /* Is mouse captured? */
Alexandre Julliarda3960291999-02-26 11:11:13 +000068 HFONT font; /* Current font */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000069 LCID locale; /* Current locale for string comparisons */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +000070 LPHEADCOMBO lphc; /* ComboLBox */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000071} LB_DESCR;
Alexandre Julliard2787be81995-05-22 18:23:01 +000072
Alexandre Julliardfa68b751995-04-03 16:55:37 +000073
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000074#define IS_OWNERDRAW(descr) \
75 ((descr)->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000076
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000077#define HAS_STRINGS(descr) \
78 (!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
Alexandre Julliard2787be81995-05-22 18:23:01 +000079
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000080#define SEND_NOTIFICATION(wnd,descr,code) \
Alexandre Julliarda3960291999-02-26 11:11:13 +000081 (SendMessageA( (descr)->owner, WM_COMMAND, \
Alexandre Julliarddf2673b1997-03-29 17:20:20 +000082 MAKEWPARAM((((descr)->lphc)?ID_CB_LISTBOX:(wnd)->wIDmenu), (code) ), (wnd)->hwndSelf ))
Alexandre Julliardfa68b751995-04-03 16:55:37 +000083
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000084/* Current timer status */
85typedef enum
Alexandre Julliardfa68b751995-04-03 16:55:37 +000086{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000087 LB_TIMER_NONE,
88 LB_TIMER_UP,
89 LB_TIMER_LEFT,
90 LB_TIMER_DOWN,
91 LB_TIMER_RIGHT
92} TIMER_DIRECTION;
Alexandre Julliardfa68b751995-04-03 16:55:37 +000093
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000094static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
95
96
97/***********************************************************************
98 * LISTBOX_Dump
99 */
100void LISTBOX_Dump( WND *wnd )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000101{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000102 INT i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000103 LB_ITEMDATA *item;
104 LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000105
Alexandre Julliard54c27111998-03-29 19:44:57 +0000106 DUMP( "Listbox:\n" );
107 DUMP( "hwnd=%04x descr=%08x heap=%08x items=%d top=%d\n",
Alexandre Julliarda3960291999-02-26 11:11:13 +0000108 wnd->hwndSelf, (UINT)descr, descr->heap, descr->nb_items,
Alexandre Julliard54c27111998-03-29 19:44:57 +0000109 descr->top_item );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000110 for (i = 0, item = descr->items; i < descr->nb_items; i++, item++)
111 {
Alexandre Julliard54c27111998-03-29 19:44:57 +0000112 DUMP( "%4d: %-40s %d %08lx %3d\n",
113 i, item->str, item->selected, item->data, item->height );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000114 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000115}
116
117
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000118/***********************************************************************
119 * LISTBOX_GetCurrentPageSize
120 *
121 * Return the current page size
122 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000123static INT LISTBOX_GetCurrentPageSize( WND *wnd, LB_DESCR *descr )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000124{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000125 INT i, height;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000126 if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size;
127 for (i = descr->top_item, height = 0; i < descr->nb_items; i++)
128 {
129 if ((height += descr->items[i].height) > descr->height) break;
130 }
131 if (i == descr->top_item) return 1;
132 else return i - descr->top_item;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000133}
134
135
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000136/***********************************************************************
137 * LISTBOX_GetMaxTopIndex
138 *
139 * Return the maximum possible index for the top of the listbox.
140 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000141static INT LISTBOX_GetMaxTopIndex( WND *wnd, LB_DESCR *descr )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000142{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000143 INT max, page;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000144
145 if (descr->style & LBS_OWNERDRAWVARIABLE)
146 {
147 page = descr->height;
148 for (max = descr->nb_items - 1; max >= 0; max--)
149 if ((page -= descr->items[max].height) < 0) break;
150 if (max < descr->nb_items - 1) max++;
151 }
152 else if (descr->style & LBS_MULTICOLUMN)
153 {
154 if ((page = descr->width / descr->column_width) < 1) page = 1;
155 max = (descr->nb_items + descr->page_size - 1) / descr->page_size;
156 max = (max - page) * descr->page_size;
157 }
158 else
159 {
160 max = descr->nb_items - descr->page_size;
161 }
162 if (max < 0) max = 0;
163 return max;
164}
165
166
167/***********************************************************************
168 * LISTBOX_UpdateScroll
169 *
170 * Update the scrollbars. Should be called whenever the content
171 * of the listbox changes.
172 */
173static void LISTBOX_UpdateScroll( WND *wnd, LB_DESCR *descr )
174{
175 SCROLLINFO info;
176
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000177 if (!(descr->style & WS_VSCROLL)) return;
178 /* It is important that we check descr->style, and not wnd->dwStyle,
179 for WS_VSCROLL, as the former is exactly the one passed in
180 argument to CreateWindow.
181 In Windows (and from now on in Wine :) a listbox created
182 with such a style (no WS_SCROLL) does not update
183 the scrollbar with listbox-related data, thus letting
184 the programmer use it for his/her own purposes. */
185
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000186 if (descr->style & LBS_NOREDRAW) return;
187 info.cbSize = sizeof(info);
188
189 if (descr->style & LBS_MULTICOLUMN)
190 {
191 info.nMin = 0;
192 info.nMax = (descr->nb_items - 1) / descr->page_size;
193 info.nPos = descr->top_item / descr->page_size;
194 info.nPage = descr->width / descr->column_width;
195 if (info.nPage < 1) info.nPage = 1;
196 info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
197 if (descr->style & LBS_DISABLENOSCROLL)
198 info.fMask |= SIF_DISABLENOSCROLL;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000199 SetScrollInfo( wnd->hwndSelf, SB_HORZ, &info, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000200 info.nMax = 0;
201 info.fMask = SIF_RANGE;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000202 SetScrollInfo( wnd->hwndSelf, SB_VERT, &info, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000203 }
204 else
205 {
206 info.nMin = 0;
207 info.nMax = descr->nb_items - 1;
208 info.nPos = descr->top_item;
209 info.nPage = LISTBOX_GetCurrentPageSize( wnd, descr );
210 info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
211 if (descr->style & LBS_DISABLENOSCROLL)
212 info.fMask |= SIF_DISABLENOSCROLL;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000213 SetScrollInfo( wnd->hwndSelf, SB_VERT, &info, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000214
215 if (descr->horz_extent)
216 {
217 info.nMin = 0;
218 info.nMax = descr->horz_extent - 1;
219 info.nPos = descr->horz_pos;
220 info.nPage = descr->width;
221 info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
222 if (descr->style & LBS_DISABLENOSCROLL)
223 info.fMask |= SIF_DISABLENOSCROLL;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000224 SetScrollInfo( wnd->hwndSelf, SB_HORZ, &info, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000225 }
226 }
227}
228
229
230/***********************************************************************
231 * LISTBOX_SetTopItem
232 *
233 * Set the top item of the listbox, scrolling up or down if necessary.
234 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000235static LRESULT LISTBOX_SetTopItem( WND *wnd, LB_DESCR *descr, INT index,
236 BOOL scroll )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000237{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000238 INT max = LISTBOX_GetMaxTopIndex( wnd, descr );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000239 if (index > max) index = max;
240 if (index < 0) index = 0;
241 if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
242 if (descr->top_item == index) return LB_OKAY;
243 if (descr->style & LBS_MULTICOLUMN)
244 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000245 INT diff = (descr->top_item - index) / descr->page_size * descr->column_width;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000246 if (scroll && (abs(diff) < descr->width))
Alexandre Julliarda3960291999-02-26 11:11:13 +0000247 ScrollWindowEx( wnd->hwndSelf, diff, 0, NULL, NULL, 0, NULL,
NF Stevens762f18d1999-01-24 19:02:16 +0000248 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
249
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000250 else
251 scroll = FALSE;
252 }
253 else if (scroll)
254 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000255 INT diff;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000256 if (descr->style & LBS_OWNERDRAWVARIABLE)
257 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000258 INT i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000259 diff = 0;
260 if (index > descr->top_item)
261 {
262 for (i = index - 1; i >= descr->top_item; i--)
263 diff -= descr->items[i].height;
264 }
265 else
266 {
267 for (i = index; i < descr->top_item; i++)
268 diff += descr->items[i].height;
269 }
270 }
271 else
272 diff = (descr->top_item - index) * descr->item_height;
273
274 if (abs(diff) < descr->height)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000275 ScrollWindowEx( wnd->hwndSelf, 0, diff, NULL, NULL, 0, NULL,
NF Stevens762f18d1999-01-24 19:02:16 +0000276 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000277 else
278 scroll = FALSE;
279 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000280 if (!scroll) InvalidateRect( wnd->hwndSelf, NULL, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000281 descr->top_item = index;
282 LISTBOX_UpdateScroll( wnd, descr );
283 return LB_OKAY;
284}
285
286
287/***********************************************************************
288 * LISTBOX_UpdatePage
289 *
290 * Update the page size. Should be called when the size of
291 * the client area or the item height changes.
292 */
293static void LISTBOX_UpdatePage( WND *wnd, LB_DESCR *descr )
294{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000295 INT page_size;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000296
297 if ((page_size = descr->height / descr->item_height) < 1) page_size = 1;
298 if (page_size == descr->page_size) return;
299 descr->page_size = page_size;
300 if (descr->style & LBS_MULTICOLUMN)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000301 InvalidateRect( wnd->hwndSelf, NULL, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000302 LISTBOX_SetTopItem( wnd, descr, descr->top_item, FALSE );
303}
304
305
306/***********************************************************************
307 * LISTBOX_UpdateSize
308 *
309 * Update the size of the listbox. Should be called when the size of
310 * the client area changes.
311 */
312static void LISTBOX_UpdateSize( WND *wnd, LB_DESCR *descr )
313{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000314 RECT rect;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000315
Alexandre Julliarda3960291999-02-26 11:11:13 +0000316 GetClientRect( wnd->hwndSelf, &rect );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000317 descr->width = rect.right - rect.left;
318 descr->height = rect.bottom - rect.top;
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000319 if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !IS_OWNERDRAW(descr))
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000320 {
321 if ((descr->height > descr->item_height) &&
322 (descr->height % descr->item_height))
323 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000324 TRACE(listbox, "[%04x]: changing height %d -> %d\n",
325 wnd->hwndSelf, descr->height,
326 descr->height - descr->height%descr->item_height );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000327 SetWindowPos( wnd->hwndSelf, 0, 0, 0,
Alexandre Julliard01d63461997-01-20 19:43:45 +0000328 wnd->rectWindow.right - wnd->rectWindow.left,
329 wnd->rectWindow.bottom - wnd->rectWindow.top -
330 (descr->height % descr->item_height),
331 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000332 return;
333 }
334 }
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000335 TRACE(listbox, "[%04x]: new size = %d,%d\n",
336 wnd->hwndSelf, descr->width, descr->height );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000337 LISTBOX_UpdatePage( wnd, descr );
338 LISTBOX_UpdateScroll( wnd, descr );
339}
340
341
342/***********************************************************************
343 * LISTBOX_GetItemRect
344 *
345 * Get the rectangle enclosing an item, in listbox client coordinates.
346 * Return 1 if the rectangle is (partially) visible, 0 if hidden, -1 on error.
347 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000348static LRESULT LISTBOX_GetItemRect( WND *wnd, LB_DESCR *descr, INT index,
349 RECT *rect )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000350{
351 /* Index <= 0 is legal even on empty listboxes */
352 if (index && (index >= descr->nb_items)) return -1;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000353 SetRect( rect, 0, 0, descr->width, descr->height );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000354 if (descr->style & LBS_MULTICOLUMN)
355 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000356 INT col = (index / descr->page_size) -
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000357 (descr->top_item / descr->page_size);
358 rect->left += col * descr->column_width;
359 rect->right = rect->left + descr->column_width;
360 rect->top += (index % descr->page_size) * descr->item_height;
361 rect->bottom = rect->top + descr->item_height;
362 }
363 else if (descr->style & LBS_OWNERDRAWVARIABLE)
364 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000365 INT i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000366 rect->right += descr->horz_pos;
Alexandre Julliard349a9531997-02-02 19:01:52 +0000367 if ((index >= 0) && (index < descr->nb_items))
368 {
369 if (index < descr->top_item)
370 {
371 for (i = descr->top_item-1; i >= index; i--)
372 rect->top -= descr->items[i].height;
373 }
374 else
375 {
376 for (i = descr->top_item; i < index; i++)
377 rect->top += descr->items[i].height;
378 }
379 rect->bottom = rect->top + descr->items[index].height;
380
381 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000382 }
383 else
384 {
385 rect->top += (index - descr->top_item) * descr->item_height;
386 rect->bottom = rect->top + descr->item_height;
387 rect->right += descr->horz_pos;
388 }
389
390 return ((rect->left < descr->width) && (rect->right > 0) &&
391 (rect->top < descr->height) && (rect->bottom > 0));
392}
393
394
395/***********************************************************************
396 * LISTBOX_GetItemFromPoint
397 *
398 * Return the item nearest from point (x,y) (in client coordinates).
399 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000400static INT LISTBOX_GetItemFromPoint( WND *wnd, LB_DESCR *descr,
401 INT x, INT y )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000402{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000403 INT index = descr->top_item;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000404
405 if (!descr->nb_items) return -1; /* No items */
406 if (descr->style & LBS_OWNERDRAWVARIABLE)
407 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000408 INT pos = 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000409 if (y >= 0)
410 {
411 while (index < descr->nb_items)
412 {
413 if ((pos += descr->items[index].height) > y) break;
414 index++;
415 }
416 }
417 else
418 {
419 while (index > 0)
420 {
421 index--;
422 if ((pos -= descr->items[index].height) <= y) break;
423 }
424 }
425 }
426 else if (descr->style & LBS_MULTICOLUMN)
427 {
428 if (y >= descr->item_height * descr->page_size) return -1;
429 if (y >= 0) index += y / descr->item_height;
430 if (x >= 0) index += (x / descr->column_width) * descr->page_size;
431 else index -= (((x + 1) / descr->column_width) - 1) * descr->page_size;
432 }
433 else
434 {
435 index += (y / descr->item_height);
436 }
437 if (index < 0) return 0;
438 if (index >= descr->nb_items) return -1;
439 return index;
440}
441
442
443/***********************************************************************
444 * LISTBOX_PaintItem
445 *
446 * Paint an item.
447 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000448static void LISTBOX_PaintItem( WND *wnd, LB_DESCR *descr, HDC hdc,
449 const RECT *rect, INT index, UINT action )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000450{
451 LB_ITEMDATA *item = NULL;
452 if (index < descr->nb_items) item = &descr->items[index];
453
454 if (IS_OWNERDRAW(descr))
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000455 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000456 DRAWITEMSTRUCT dis;
457 UINT id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000458
Marcus Meissner9ad90171999-01-20 14:08:00 +0000459 if (!item)
460 {
461 if (action == ODA_FOCUS)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000462 DrawFocusRect( hdc, rect );
Marcus Meissner9ad90171999-01-20 14:08:00 +0000463 else
464 FIXME(listbox,"called with an out of bounds index %d(%d) in owner draw, Not good.\n",index,descr->nb_items);
465 return;
466 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000467 dis.CtlType = ODT_LISTBOX;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000468 dis.CtlID = id;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000469 dis.hwndItem = wnd->hwndSelf;
470 dis.itemAction = action;
471 dis.hDC = hdc;
472 dis.itemID = index;
473 dis.itemState = 0;
474 if (item && item->selected) dis.itemState |= ODS_SELECTED;
475 if ((descr->focus_item == index) &&
476 (descr->caret_on) &&
Alexandre Julliarda3960291999-02-26 11:11:13 +0000477 (GetFocus() == wnd->hwndSelf)) dis.itemState |= ODS_FOCUS;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000478 if (wnd->dwStyle & WS_DISABLED) dis.itemState |= ODS_DISABLED;
479 dis.itemData = item ? item->data : 0;
480 dis.rcItem = *rect;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000481 TRACE(listbox, "[%04x]: drawitem %d (%s) action=%02x "
482 "state=%02x rect=%d,%d-%d,%d\n",
483 wnd->hwndSelf, index, item ? item->str : "", action,
484 dis.itemState, rect->left, rect->top,
485 rect->right, rect->bottom );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000486 SendMessageA(descr->owner, WM_DRAWITEM, id, (LPARAM)&dis);
Alexandre Julliard2787be81995-05-22 18:23:01 +0000487 }
488 else
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000489 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000490 COLORREF oldText = 0, oldBk = 0;
491
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000492 if (action == ODA_FOCUS)
493 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000494 DrawFocusRect( hdc, rect );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000495 return;
496 }
497 if (item && item->selected)
498 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000499 oldBk = SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
500 oldText = SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000501 }
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000502
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000503 TRACE(listbox, "[%04x]: painting %d (%s) action=%02x "
504 "rect=%d,%d-%d,%d\n",
505 wnd->hwndSelf, index, item ? item->str : "", action,
506 rect->left, rect->top, rect->right, rect->bottom );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000507 if (!item)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000508 ExtTextOutA( hdc, rect->left + 1, rect->top + 1,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000509 ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000510 else if (!(descr->style & LBS_USETABSTOPS))
Alexandre Julliarda3960291999-02-26 11:11:13 +0000511 ExtTextOutA( hdc, rect->left + 1, rect->top + 1,
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000512 ETO_OPAQUE | ETO_CLIPPED, rect, item->str,
513 strlen(item->str), NULL );
514 else
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000515 {
516 /* Output empty string to paint background in the full width. */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000517 ExtTextOutA( hdc, rect->left + 1, rect->top + 1,
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000518 ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000519 TabbedTextOutA( hdc, rect->left + 1 , rect->top + 1,
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000520 item->str, strlen(item->str),
521 descr->nb_tabs, descr->tabs, 0);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000522 }
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000523 if (item && item->selected)
524 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000525 SetBkColor( hdc, oldBk );
526 SetTextColor( hdc, oldText );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000527 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000528 if ((descr->focus_item == index) &&
529 (descr->caret_on) &&
Alexandre Julliarda3960291999-02-26 11:11:13 +0000530 (GetFocus() == wnd->hwndSelf)) DrawFocusRect( hdc, rect );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000531 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000532}
533
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000534
535/***********************************************************************
536 * LISTBOX_SetRedraw
537 *
538 * Change the redraw flag.
539 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000540static void LISTBOX_SetRedraw( WND *wnd, LB_DESCR *descr, BOOL on )
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000541{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000542 if (on)
543 {
544 if (!(descr->style & LBS_NOREDRAW)) return;
545 descr->style &= ~LBS_NOREDRAW;
546 LISTBOX_UpdateScroll( wnd, descr );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000547 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000548 else descr->style |= LBS_NOREDRAW;
549}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000550
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000551
552/***********************************************************************
553 * LISTBOX_RepaintItem
554 *
555 * Repaint a single item synchronously.
556 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000557static void LISTBOX_RepaintItem( WND *wnd, LB_DESCR *descr, INT index,
558 UINT action )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000559{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000560 HDC hdc;
561 RECT rect;
562 HFONT oldFont = 0;
563 HBRUSH hbrush, oldBrush = 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000564
565 if (descr->style & LBS_NOREDRAW) return;
566 if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) != 1) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000567 if (!(hdc = GetDCEx( wnd->hwndSelf, 0, DCX_CACHE ))) return;
568 if (descr->font) oldFont = SelectObject( hdc, descr->font );
569 hbrush = SendMessageA( descr->owner, WM_CTLCOLORLISTBOX,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000570 hdc, (LPARAM)wnd->hwndSelf );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000571 if (hbrush) oldBrush = SelectObject( hdc, hbrush );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000572 if (wnd->dwStyle & WS_DISABLED)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000573 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
574 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000575 LISTBOX_PaintItem( wnd, descr, hdc, &rect, index, action );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000576 if (oldFont) SelectObject( hdc, oldFont );
577 if (oldBrush) SelectObject( hdc, oldBrush );
578 ReleaseDC( wnd->hwndSelf, hdc );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000579}
580
581
582/***********************************************************************
583 * LISTBOX_InitStorage
584 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000585static LRESULT LISTBOX_InitStorage( WND *wnd, LB_DESCR *descr, INT nb_items,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000586 DWORD bytes )
587{
588 LB_ITEMDATA *item;
589
590 nb_items += LB_ARRAY_GRANULARITY - 1;
591 nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
592 if (descr->items)
593 nb_items += HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
594 if (!(item = HeapReAlloc( descr->heap, 0, descr->items,
595 nb_items * sizeof(LB_ITEMDATA) )))
596 {
597 SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
598 return LB_ERRSPACE;
599 }
600 descr->items = item;
601 return LB_OKAY;
602}
603
604
605/***********************************************************************
606 * LISTBOX_SetTabStops
607 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000608static BOOL LISTBOX_SetTabStops( WND *wnd, LB_DESCR *descr, INT count,
609 LPINT tabs, BOOL short_ints )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000610{
611 if (!(descr->style & LBS_USETABSTOPS)) return TRUE;
612 if (descr->tabs) HeapFree( descr->heap, 0, descr->tabs );
613 if (!(descr->nb_tabs = count))
614 {
615 descr->tabs = NULL;
616 return TRUE;
617 }
618 /* FIXME: count = 1 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000619 if (!(descr->tabs = (INT *)HeapAlloc( descr->heap, 0,
620 descr->nb_tabs * sizeof(INT) )))
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000621 return FALSE;
622 if (short_ints)
623 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000624 INT i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000625 LPINT16 p = (LPINT16)tabs;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000626 dbg_decl_str(listbox, 256);
627
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000628 for (i = 0; i < descr->nb_tabs; i++) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000629 descr->tabs[i] = *p++<<1; /* FIXME */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000630 if(TRACE_ON(listbox))
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000631 dsprintf(listbox, "%hd ", descr->tabs[i]);
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000632 }
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000633 TRACE(listbox, "[%04x]: settabstops %s\n",
634 wnd->hwndSelf, dbg_str(listbox));
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000635 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000636 else memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000637 /* FIXME: repaint the window? */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000638 return TRUE;
639}
640
641
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000642/***********************************************************************
643 * LISTBOX_GetText
644 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000645static LRESULT LISTBOX_GetText( WND *wnd, LB_DESCR *descr, INT index,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000646 LPSTR buffer )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000647{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000648 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
649 if (HAS_STRINGS(descr))
650 {
Marcus Meissner4f7dc461998-11-22 15:43:34 +0000651 if (!buffer)
652 return strlen(descr->items[index].str);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000653 lstrcpyA( buffer, descr->items[index].str );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000654 return strlen(buffer);
Marcus Meissner4f7dc461998-11-22 15:43:34 +0000655 } else {
656 if (buffer)
657 *((LPDWORD)buffer)=*(LPDWORD)(&descr->items[index].data);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000658 return sizeof(DWORD);
659 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000660}
661
662
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000663/***********************************************************************
664 * LISTBOX_FindStringPos
665 *
666 * Find the nearest string located before a given string in sort order.
667 * If 'exact' is TRUE, return an error if we don't get an exact match.
668 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000669static INT LISTBOX_FindStringPos( WND *wnd, LB_DESCR *descr, LPCSTR str,
670 BOOL exact )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000671{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000672 INT index, min, max, res = -1;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000673
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000674 if (!(descr->style & LBS_SORT)) return -1; /* Add it at the end */
675 min = 0;
676 max = descr->nb_items;
677 while (min != max)
678 {
679 index = (min + max) / 2;
680 if (HAS_STRINGS(descr))
Alexandre Julliarda3960291999-02-26 11:11:13 +0000681 res = lstrcmpiA( descr->items[index].str, str );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000682 else
683 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000684 COMPAREITEMSTRUCT cis;
685 UINT id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000686
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000687 cis.CtlType = ODT_LISTBOX;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000688 cis.CtlID = id;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000689 cis.hwndItem = wnd->hwndSelf;
690 cis.itemID1 = index;
691 cis.itemData1 = descr->items[index].data;
692 cis.itemID2 = -1;
693 cis.itemData2 = (DWORD)str;
694 cis.dwLocaleId = descr->locale;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000695 res = SendMessageA( descr->owner, WM_COMPAREITEM,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000696 id, (LPARAM)&cis );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000697 }
698 if (!res) return index;
699 if (res > 0) max = index;
700 else min = index + 1;
701 }
702 return exact ? -1 : max;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000703}
704
705
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000706/***********************************************************************
707 * LISTBOX_FindFileStrPos
708 *
709 * Find the nearest string located before a given string in directory
710 * sort order (i.e. first files, then directories, then drives).
711 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000712static INT LISTBOX_FindFileStrPos( WND *wnd, LB_DESCR *descr, LPCSTR str )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000713{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000714 INT min, max, res = -1;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000715
716 if (!HAS_STRINGS(descr))
717 return LISTBOX_FindStringPos( wnd, descr, str, FALSE );
718 min = 0;
719 max = descr->nb_items;
720 while (min != max)
721 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000722 INT index = (min + max) / 2;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000723 const char *p = descr->items[index].str;
724 if (*p == '[') /* drive or directory */
725 {
726 if (*str != '[') res = -1;
727 else if (p[1] == '-') /* drive */
728 {
729 if (str[1] == '-') res = str[2] - p[2];
730 else res = -1;
731 }
732 else /* directory */
733 {
734 if (str[1] == '-') res = 1;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000735 else res = lstrcmpiA( str, p );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000736 }
737 }
738 else /* filename */
739 {
740 if (*str == '[') res = 1;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000741 else res = lstrcmpiA( str, p );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000742 }
743 if (!res) return index;
744 if (res < 0) max = index;
745 else min = index + 1;
746 }
747 return max;
748}
749
750
751/***********************************************************************
752 * LISTBOX_FindString
753 *
754 * Find the item beginning with a given string.
755 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000756static INT LISTBOX_FindString( WND *wnd, LB_DESCR *descr, INT start,
757 LPCSTR str, BOOL exact )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000758{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000759 INT i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000760 LB_ITEMDATA *item;
761
762 if (start >= descr->nb_items) start = -1;
763 item = descr->items + start + 1;
764 if (HAS_STRINGS(descr))
765 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000766 if (!str) return LB_ERR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000767 if (exact)
768 {
769 for (i = start + 1; i < descr->nb_items; i++, item++)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000770 if (!lstrcmpiA( str, item->str )) return i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000771 for (i = 0, item = descr->items; i <= start; i++, item++)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000772 if (!lstrcmpiA( str, item->str )) return i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000773 }
774 else
775 {
776 /* Special case for drives and directories: ignore prefix */
777#define CHECK_DRIVE(item) \
778 if ((item)->str[0] == '[') \
779 { \
Alexandre Julliarda3960291999-02-26 11:11:13 +0000780 if (!lstrncmpiA( str, (item)->str+1, len )) return i; \
781 if (((item)->str[1] == '-') && !lstrncmpiA(str,(item)->str+2,len)) \
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000782 return i; \
783 }
784
Alexandre Julliarda3960291999-02-26 11:11:13 +0000785 INT len = strlen(str);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000786 for (i = start + 1; i < descr->nb_items; i++, item++)
787 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000788 if (!lstrncmpiA( str, item->str, len )) return i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000789 CHECK_DRIVE(item);
790 }
791 for (i = 0, item = descr->items; i <= start; i++, item++)
792 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000793 if (!lstrncmpiA( str, item->str, len )) return i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000794 CHECK_DRIVE(item);
795 }
796#undef CHECK_DRIVE
797 }
798 }
799 else
800 {
801 if (exact && (descr->style & LBS_SORT))
802 /* If sorted, use a WM_COMPAREITEM binary search */
803 return LISTBOX_FindStringPos( wnd, descr, str, TRUE );
804
805 /* Otherwise use a linear search */
806 for (i = start + 1; i < descr->nb_items; i++, item++)
807 if (item->data == (DWORD)str) return i;
808 for (i = 0, item = descr->items; i <= start; i++, item++)
809 if (item->data == (DWORD)str) return i;
810 }
811 return LB_ERR;
812}
813
814
815/***********************************************************************
816 * LISTBOX_GetSelCount
817 */
818static LRESULT LISTBOX_GetSelCount( WND *wnd, LB_DESCR *descr )
819{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000820 INT i, count;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000821 LB_ITEMDATA *item = descr->items;
822
823 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
824 for (i = count = 0; i < descr->nb_items; i++, item++)
825 if (item->selected) count++;
826 return count;
827}
828
829
830/***********************************************************************
831 * LISTBOX_GetSelItems16
832 */
833static LRESULT LISTBOX_GetSelItems16( WND *wnd, LB_DESCR *descr, INT16 max,
834 LPINT16 array )
835{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000836 INT i, count;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000837 LB_ITEMDATA *item = descr->items;
838
839 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
840 for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
841 if (item->selected) array[count++] = (INT16)i;
842 return count;
843}
844
845
846/***********************************************************************
847 * LISTBOX_GetSelItems32
848 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000849static LRESULT LISTBOX_GetSelItems( WND *wnd, LB_DESCR *descr, INT max,
850 LPINT array )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000851{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000852 INT i, count;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000853 LB_ITEMDATA *item = descr->items;
854
855 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
856 for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
857 if (item->selected) array[count++] = i;
858 return count;
859}
860
861
862/***********************************************************************
863 * LISTBOX_Paint
864 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000865static LRESULT LISTBOX_Paint( WND *wnd, LB_DESCR *descr, HDC hdc )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000866{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000867 INT i, col_pos = descr->page_size - 1;
868 RECT rect;
869 HFONT oldFont = 0;
870 HBRUSH hbrush, oldBrush = 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000871
Alexandre Julliarda3960291999-02-26 11:11:13 +0000872 SetRect( &rect, 0, 0, descr->width, descr->height );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000873 if (descr->style & LBS_NOREDRAW) return 0;
874 if (descr->style & LBS_MULTICOLUMN)
875 rect.right = rect.left + descr->column_width;
876 else if (descr->horz_pos)
877 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000878 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000879 rect.right += descr->horz_pos;
880 }
881
Alexandre Julliarda3960291999-02-26 11:11:13 +0000882 if (descr->font) oldFont = SelectObject( hdc, descr->font );
883 hbrush = SendMessageA( descr->owner, WM_CTLCOLORLISTBOX,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000884 hdc, (LPARAM)wnd->hwndSelf );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000885 if (hbrush) oldBrush = SelectObject( hdc, hbrush );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000886 if (wnd->dwStyle & WS_DISABLED)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000887 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000888
889 if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
Alexandre Julliarda3960291999-02-26 11:11:13 +0000890 (GetFocus() == wnd->hwndSelf))
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000891 {
892 /* Special case for empty listbox: paint focus rect */
893 rect.bottom = rect.top + descr->item_height;
894 LISTBOX_PaintItem( wnd, descr, hdc, &rect, descr->focus_item,
Gerard Patelc979b7b1998-12-24 16:25:50 +0000895 ODA_FOCUS );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000896 rect.top = rect.bottom;
897 }
898
899 for (i = descr->top_item; i < descr->nb_items; i++)
900 {
901 if (!(descr->style & LBS_OWNERDRAWVARIABLE))
902 rect.bottom = rect.top + descr->item_height;
903 else
904 rect.bottom = rect.top + descr->items[i].height;
905
906 LISTBOX_PaintItem( wnd, descr, hdc, &rect, i, ODA_DRAWENTIRE );
907 rect.top = rect.bottom;
908
909 if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
910 {
911 if (!IS_OWNERDRAW(descr))
912 {
913 /* Clear the bottom of the column */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000914 SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000915 if (rect.top < descr->height)
916 {
917 rect.bottom = descr->height;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000918 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000919 &rect, NULL, 0, NULL );
920 }
921 }
922
923 /* Go to the next column */
924 rect.left += descr->column_width;
925 rect.right += descr->column_width;
926 rect.top = 0;
927 col_pos = descr->page_size - 1;
928 }
929 else
930 {
931 col_pos--;
932 if (rect.top >= descr->height) break;
933 }
934 }
935
936 if (!IS_OWNERDRAW(descr))
937 {
938 /* Clear the remainder of the client area */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000939 SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000940 if (rect.top < descr->height)
941 {
942 rect.bottom = descr->height;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000943 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000944 &rect, NULL, 0, NULL );
945 }
946 if (rect.right < descr->width)
947 {
948 rect.left = rect.right;
949 rect.right = descr->width;
950 rect.top = 0;
951 rect.bottom = descr->height;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000952 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000953 &rect, NULL, 0, NULL );
954 }
955 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000956 if (oldFont) SelectObject( hdc, oldFont );
957 if (oldBrush) SelectObject( hdc, oldBrush );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000958 return 0;
959}
960
961
962/***********************************************************************
963 * LISTBOX_InvalidateItems
964 *
965 * Invalidate all items from a given item. If the specified item is not
966 * visible, nothing happens.
967 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000968static void LISTBOX_InvalidateItems( WND *wnd, LB_DESCR *descr, INT index )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000969{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000970 RECT rect;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000971
972 if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) == 1)
973 {
974 rect.bottom = descr->height;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000975 InvalidateRect( wnd->hwndSelf, &rect, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000976 if (descr->style & LBS_MULTICOLUMN)
977 {
978 /* Repaint the other columns */
979 rect.left = rect.right;
980 rect.right = descr->width;
981 rect.top = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000982 InvalidateRect( wnd->hwndSelf, &rect, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000983 }
984 }
985}
986
987
988/***********************************************************************
989 * LISTBOX_GetItemHeight
990 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000991static LRESULT LISTBOX_GetItemHeight( WND *wnd, LB_DESCR *descr, INT index )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000992{
993 if (descr->style & LBS_OWNERDRAWVARIABLE)
994 {
995 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
996 return descr->items[index].height;
997 }
998 else return descr->item_height;
999}
1000
1001
1002/***********************************************************************
1003 * LISTBOX_SetItemHeight
1004 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001005static LRESULT LISTBOX_SetItemHeight( WND *wnd, LB_DESCR *descr, INT index,
1006 UINT height )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001007{
1008 if (!height) height = 1;
1009
1010 if (descr->style & LBS_OWNERDRAWVARIABLE)
1011 {
1012 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001013 TRACE(listbox, "[%04x]: item %d height = %d\n",
1014 wnd->hwndSelf, index, height );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001015 descr->items[index].height = height;
1016 LISTBOX_UpdateScroll( wnd, descr );
1017 LISTBOX_InvalidateItems( wnd, descr, index );
1018 }
1019 else if (height != descr->item_height)
1020 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001021 TRACE(listbox, "[%04x]: new height = %d\n",
1022 wnd->hwndSelf, height );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001023 descr->item_height = height;
1024 LISTBOX_UpdatePage( wnd, descr );
1025 LISTBOX_UpdateScroll( wnd, descr );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001026 InvalidateRect( wnd->hwndSelf, 0, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001027 }
1028 return LB_OKAY;
1029}
1030
1031
1032/***********************************************************************
1033 * LISTBOX_SetHorizontalPos
1034 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001035static void LISTBOX_SetHorizontalPos( WND *wnd, LB_DESCR *descr, INT pos )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001036{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001037 INT diff;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001038
1039 if (pos > descr->horz_extent - descr->width)
1040 pos = descr->horz_extent - descr->width;
1041 if (pos < 0) pos = 0;
1042 if (!(diff = descr->horz_pos - pos)) return;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001043 TRACE(listbox, "[%04x]: new horz pos = %d\n",
1044 wnd->hwndSelf, pos );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001045 descr->horz_pos = pos;
1046 LISTBOX_UpdateScroll( wnd, descr );
1047 if (abs(diff) < descr->width)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001048 ScrollWindowEx( wnd->hwndSelf, diff, 0, NULL, NULL, 0, NULL,
NF Stevens762f18d1999-01-24 19:02:16 +00001049 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001050 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001051 InvalidateRect( wnd->hwndSelf, NULL, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001052}
1053
1054
1055/***********************************************************************
1056 * LISTBOX_SetHorizontalExtent
1057 */
1058static LRESULT LISTBOX_SetHorizontalExtent( WND *wnd, LB_DESCR *descr,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001059 UINT extent )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001060{
1061 if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
1062 return LB_OKAY;
1063 if (extent <= 0) extent = 1;
1064 if (extent == descr->horz_extent) return LB_OKAY;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001065 TRACE(listbox, "[%04x]: new horz extent = %d\n",
1066 wnd->hwndSelf, extent );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001067 descr->horz_extent = extent;
1068 if (descr->horz_pos > extent - descr->width)
1069 LISTBOX_SetHorizontalPos( wnd, descr, extent - descr->width );
1070 else
1071 LISTBOX_UpdateScroll( wnd, descr );
1072 return LB_OKAY;
1073}
1074
1075
1076/***********************************************************************
1077 * LISTBOX_SetColumnWidth
1078 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001079static LRESULT LISTBOX_SetColumnWidth( WND *wnd, LB_DESCR *descr, UINT width)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001080{
1081 width += 2; /* For left and right margin */
1082 if (width == descr->column_width) return LB_OKAY;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001083 TRACE(listbox, "[%04x]: new column width = %d\n",
1084 wnd->hwndSelf, width );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001085 descr->column_width = width;
1086 LISTBOX_UpdatePage( wnd, descr );
1087 return LB_OKAY;
1088}
1089
1090
1091/***********************************************************************
1092 * LISTBOX_SetFont
1093 *
1094 * Returns the item height.
1095 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001096static INT LISTBOX_SetFont( WND *wnd, LB_DESCR *descr, HFONT font )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001097{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001098 HDC hdc;
1099 HFONT oldFont = 0;
1100 TEXTMETRICA tm;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001101
1102 descr->font = font;
1103
Alexandre Julliarda3960291999-02-26 11:11:13 +00001104 if (!(hdc = GetDCEx( wnd->hwndSelf, 0, DCX_CACHE )))
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001105 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001106 ERR(listbox, "unable to get DC.\n" );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001107 return 16;
1108 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001109 if (font) oldFont = SelectObject( hdc, font );
1110 GetTextMetricsA( hdc, &tm );
1111 if (oldFont) SelectObject( hdc, oldFont );
1112 ReleaseDC( wnd->hwndSelf, hdc );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001113 if (!IS_OWNERDRAW(descr))
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001114 LISTBOX_SetItemHeight( wnd, descr, 0, tm.tmHeight );
1115 return tm.tmHeight ;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001116}
1117
1118
1119/***********************************************************************
1120 * LISTBOX_MakeItemVisible
1121 *
1122 * Make sure that a given item is partially or fully visible.
1123 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001124static void LISTBOX_MakeItemVisible( WND *wnd, LB_DESCR *descr, INT index,
1125 BOOL fully )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001126{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001127 INT top;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001128
1129 if (index <= descr->top_item) top = index;
1130 else if (descr->style & LBS_MULTICOLUMN)
1131 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001132 INT cols = descr->width;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001133 if (!fully) cols += descr->column_width - 1;
1134 if (cols >= descr->column_width) cols /= descr->column_width;
1135 else cols = 1;
1136 if (index < descr->top_item + (descr->page_size * cols)) return;
1137 top = index - descr->page_size * (cols - 1);
1138 }
1139 else if (descr->style & LBS_OWNERDRAWVARIABLE)
1140 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001141 INT height = fully ? descr->items[index].height : 1;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001142 for (top = index; top > descr->top_item; top--)
1143 if ((height += descr->items[top-1].height) > descr->height) break;
1144 }
1145 else
1146 {
1147 if (index < descr->top_item + descr->page_size) return;
1148 if (!fully && (index == descr->top_item + descr->page_size) &&
1149 (descr->height > (descr->page_size * descr->item_height))) return;
1150 top = index - descr->page_size + 1;
1151 }
1152 LISTBOX_SetTopItem( wnd, descr, top, TRUE );
1153}
1154
1155
1156/***********************************************************************
1157 * LISTBOX_SelectItemRange
1158 *
1159 * Select a range of items. Should only be used on a MULTIPLESEL listbox.
1160 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001161static LRESULT LISTBOX_SelectItemRange( WND *wnd, LB_DESCR *descr, INT first,
1162 INT last, BOOL on )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001163{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001164 INT i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001165
1166 /* A few sanity checks */
1167
Alexandre Julliard03468f71998-02-15 19:40:49 +00001168 if ((last == -1) && (descr->nb_items == 0)) return LB_OKAY;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001169 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
1170 if (last == -1) last = descr->nb_items - 1;
1171 if ((first < 0) || (first >= descr->nb_items)) return LB_ERR;
1172 if ((last < 0) || (last >= descr->nb_items)) return LB_ERR;
1173 /* selected_item reflects last selected/unselected item on multiple sel */
1174 descr->selected_item = last;
1175
1176 if (on) /* Turn selection on */
1177 {
1178 for (i = first; i <= last; i++)
1179 {
1180 if (descr->items[i].selected) continue;
1181 descr->items[i].selected = TRUE;
1182 LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT );
1183 }
1184 }
1185 else /* Turn selection off */
1186 {
1187 for (i = first; i <= last; i++)
1188 {
1189 if (!descr->items[i].selected) continue;
1190 descr->items[i].selected = FALSE;
1191 LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT );
1192 }
1193 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001194 return LB_OKAY;
1195}
1196
1197
1198/***********************************************************************
1199 * LISTBOX_SetCaretIndex
Alexandre Julliard638f1691999-01-17 16:32:32 +00001200 *
1201 * NOTES
1202 * index must be between 0 and descr->nb_items-1, or LB_ERR is returned.
1203 *
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001204 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001205static LRESULT LISTBOX_SetCaretIndex( WND *wnd, LB_DESCR *descr, INT index,
1206 BOOL fully_visible )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001207{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001208 INT oldfocus = descr->focus_item;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001209
Alexandre Julliard638f1691999-01-17 16:32:32 +00001210 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001211 if (index == oldfocus) return LB_OKAY;
1212 descr->focus_item = index;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001213 if ((oldfocus != -1) && descr->caret_on && (GetFocus() == wnd->hwndSelf))
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001214 LISTBOX_RepaintItem( wnd, descr, oldfocus, ODA_FOCUS );
Alexandre Julliard638f1691999-01-17 16:32:32 +00001215
1216 LISTBOX_MakeItemVisible( wnd, descr, index, fully_visible );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001217 if (descr->caret_on && (GetFocus() == wnd->hwndSelf))
Alexandre Julliard638f1691999-01-17 16:32:32 +00001218 LISTBOX_RepaintItem( wnd, descr, index, ODA_FOCUS );
1219
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001220 return LB_OKAY;
1221}
1222
1223
1224/***********************************************************************
1225 * LISTBOX_SetSelection
1226 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001227static LRESULT LISTBOX_SetSelection( WND *wnd, LB_DESCR *descr, INT index,
1228 BOOL on, BOOL send_notify )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001229{
1230 if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
1231 if (descr->style & LBS_MULTIPLESEL)
1232 {
1233 if (index == -1) /* Select all items */
1234 return LISTBOX_SelectItemRange( wnd, descr, 0, -1, on );
1235 else /* Only one item */
1236 return LISTBOX_SelectItemRange( wnd, descr, index, index, on );
1237 }
1238 else
1239 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001240 INT oldsel = descr->selected_item;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001241 if (index == oldsel) return LB_OKAY;
1242 if (oldsel != -1) descr->items[oldsel].selected = FALSE;
1243 if (index != -1) descr->items[index].selected = TRUE;
1244 descr->selected_item = index;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001245 if (oldsel != -1) LISTBOX_RepaintItem( wnd, descr, oldsel, ODA_SELECT);
1246 if (index != -1) LISTBOX_RepaintItem( wnd, descr, index, ODA_SELECT );
1247 if (send_notify) SEND_NOTIFICATION( wnd, descr,
1248 (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
Alex Korobka311d3291999-01-01 18:40:02 +00001249 else
1250 if( descr->lphc ) /* set selection change flag for parent combo */
1251 descr->lphc->wState |= CBF_SELCHANGE;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001252 }
1253 return LB_OKAY;
1254}
1255
1256
1257/***********************************************************************
1258 * LISTBOX_MoveCaret
1259 *
1260 * Change the caret position and extend the selection to the new caret.
1261 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001262static void LISTBOX_MoveCaret( WND *wnd, LB_DESCR *descr, INT index,
1263 BOOL fully_visible )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001264{
1265 LISTBOX_SetCaretIndex( wnd, descr, index, fully_visible );
1266 if (descr->style & LBS_EXTENDEDSEL)
1267 {
1268 if (descr->anchor_item != -1)
1269 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001270 INT first = MIN( descr->focus_item, descr->anchor_item );
1271 INT last = MAX( descr->focus_item, descr->anchor_item );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001272 if (first > 0)
1273 LISTBOX_SelectItemRange( wnd, descr, 0, first - 1, FALSE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001274 LISTBOX_SelectItemRange( wnd, descr, last + 1, -1, FALSE );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001275 LISTBOX_SelectItemRange( wnd, descr, first, last, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001276 }
1277 }
1278 else if (!(descr->style & LBS_MULTIPLESEL) && (descr->selected_item != -1))
1279 {
1280 /* Set selection to new caret item */
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001281 LISTBOX_SetSelection( wnd, descr, index, TRUE, FALSE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001282 }
1283}
1284
1285
1286/***********************************************************************
1287 * LISTBOX_InsertItem
1288 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001289static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT index,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001290 LPSTR str, DWORD data )
1291{
1292 LB_ITEMDATA *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001293 INT max_items;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001294
1295 if (index == -1) index = descr->nb_items;
1296 else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
1297 if (!descr->items) max_items = 0;
1298 else max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
1299 if (descr->nb_items == max_items)
1300 {
1301 /* We need to grow the array */
1302 max_items += LB_ARRAY_GRANULARITY;
1303 if (!(item = HeapReAlloc( descr->heap, 0, descr->items,
1304 max_items * sizeof(LB_ITEMDATA) )))
1305 {
1306 SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
1307 return LB_ERRSPACE;
1308 }
1309 descr->items = item;
1310 }
1311
1312 /* Insert the item structure */
1313
1314 item = &descr->items[index];
1315 if (index < descr->nb_items)
1316 RtlMoveMemory( item + 1, item,
1317 (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
1318 item->str = str;
1319 item->data = data;
1320 item->height = 0;
1321 item->selected = FALSE;
1322 descr->nb_items++;
1323
1324 /* Get item height */
1325
1326 if (descr->style & LBS_OWNERDRAWVARIABLE)
1327 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001328 MEASUREITEMSTRUCT mis;
1329 UINT id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001330
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001331 mis.CtlType = ODT_LISTBOX;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001332 mis.CtlID = id;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001333 mis.itemID = index;
1334 mis.itemData = descr->items[index].data;
1335 mis.itemHeight = descr->item_height;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001336 SendMessageA( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001337 item->height = mis.itemHeight ? mis.itemHeight : 1;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001338 TRACE(listbox, "[%04x]: measure item %d (%s) = %d\n",
1339 wnd->hwndSelf, index, str ? str : "", item->height );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001340 }
1341
1342 /* Repaint the items */
1343
1344 LISTBOX_UpdateScroll( wnd, descr );
1345 LISTBOX_InvalidateItems( wnd, descr, index );
1346
1347 /* Move selection and focused item */
1348
1349 if (index <= descr->selected_item) descr->selected_item++;
1350 if (index <= descr->focus_item)
1351 {
1352 descr->focus_item++;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001353 LISTBOX_MoveCaret( wnd, descr, descr->focus_item, FALSE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001354 }
1355
1356 /* If listbox was empty, set focus to the first item */
1357
1358 if (descr->nb_items == 1) LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE );
1359 return LB_OKAY;
1360}
1361
1362
1363/***********************************************************************
1364 * LISTBOX_InsertString
1365 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001366static LRESULT LISTBOX_InsertString( WND *wnd, LB_DESCR *descr, INT index,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001367 LPCSTR str )
1368{
1369 LPSTR new_str = NULL;
1370 DWORD data = 0;
1371 LRESULT ret;
1372
1373 if (HAS_STRINGS(descr))
1374 {
1375 if (!(new_str = HEAP_strdupA( descr->heap, 0, str )))
1376 {
1377 SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
1378 return LB_ERRSPACE;
1379 }
1380 }
1381 else data = (DWORD)str;
1382
1383 if (index == -1) index = descr->nb_items;
1384 if ((ret = LISTBOX_InsertItem( wnd, descr, index, new_str, data )) != 0)
1385 {
1386 if (new_str) HeapFree( descr->heap, 0, new_str );
1387 return ret;
1388 }
1389
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001390 TRACE(listbox, "[%04x]: added item %d '%s'\n",
1391 wnd->hwndSelf, index, HAS_STRINGS(descr) ? new_str : "" );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001392 return index;
1393}
1394
1395
1396/***********************************************************************
1397 * LISTBOX_DeleteItem
1398 *
1399 * Delete the content of an item. 'index' must be a valid index.
1400 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001401static void LISTBOX_DeleteItem( WND *wnd, LB_DESCR *descr, INT index )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001402{
1403 /* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
1404 * while Win95 sends it for all items with user data.
1405 * It's probably better to send it too often than not
1406 * often enough, so this is what we do here.
1407 */
1408 if (IS_OWNERDRAW(descr) || descr->items[index].data)
1409 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001410 DELETEITEMSTRUCT dis;
1411 UINT id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001412
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001413 dis.CtlType = ODT_LISTBOX;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001414 dis.CtlID = id;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001415 dis.itemID = index;
1416 dis.hwndItem = wnd->hwndSelf;
1417 dis.itemData = descr->items[index].data;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001418 SendMessageA( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001419 }
1420 if (HAS_STRINGS(descr) && descr->items[index].str)
1421 HeapFree( descr->heap, 0, descr->items[index].str );
1422}
1423
1424
1425/***********************************************************************
1426 * LISTBOX_RemoveItem
1427 *
1428 * Remove an item from the listbox and delete its content.
1429 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001430static LRESULT LISTBOX_RemoveItem( WND *wnd, LB_DESCR *descr, INT index )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001431{
1432 LB_ITEMDATA *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001433 INT max_items;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001434
1435 if (index == -1) index = descr->nb_items - 1;
1436 else if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
1437 LISTBOX_DeleteItem( wnd, descr, index );
1438
1439 /* Remove the item */
1440
1441 item = &descr->items[index];
1442 if (index < descr->nb_items-1)
1443 RtlMoveMemory( item, item + 1,
1444 (descr->nb_items - index - 1) * sizeof(LB_ITEMDATA) );
1445 descr->nb_items--;
1446 if (descr->anchor_item == descr->nb_items) descr->anchor_item--;
1447
1448 /* Shrink the item array if possible */
1449
1450 max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(LB_ITEMDATA);
1451 if (descr->nb_items < max_items - 2*LB_ARRAY_GRANULARITY)
1452 {
1453 max_items -= LB_ARRAY_GRANULARITY;
1454 item = HeapReAlloc( descr->heap, 0, descr->items,
1455 max_items * sizeof(LB_ITEMDATA) );
1456 if (item) descr->items = item;
1457 }
1458
1459 /* Repaint the items */
1460
1461 LISTBOX_UpdateScroll( wnd, descr );
1462 LISTBOX_InvalidateItems( wnd, descr, index );
1463
1464 /* Move selection and focused item */
1465
1466 if (index <= descr->selected_item) descr->selected_item--;
1467 if (index <= descr->focus_item)
1468 {
1469 descr->focus_item--;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001470 LISTBOX_MoveCaret( wnd, descr, descr->focus_item, FALSE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001471 }
1472 return LB_OKAY;
1473}
1474
1475
1476/***********************************************************************
1477 * LISTBOX_ResetContent
1478 */
1479static void LISTBOX_ResetContent( WND *wnd, LB_DESCR *descr )
1480{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001481 INT i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001482
1483 for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( wnd, descr, i );
1484 if (descr->items) HeapFree( descr->heap, 0, descr->items );
1485 descr->nb_items = 0;
1486 descr->top_item = 0;
1487 descr->selected_item = -1;
1488 descr->focus_item = 0;
1489 descr->anchor_item = -1;
1490 descr->items = NULL;
1491 LISTBOX_UpdateScroll( wnd, descr );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001492 InvalidateRect( wnd->hwndSelf, NULL, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001493}
1494
1495
1496/***********************************************************************
1497 * LISTBOX_SetCount
1498 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001499static LRESULT LISTBOX_SetCount( WND *wnd, LB_DESCR *descr, INT count )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001500{
1501 LRESULT ret;
1502
1503 if (HAS_STRINGS(descr)) return LB_ERR;
1504 /* FIXME: this is far from optimal... */
1505 if (count > descr->nb_items)
1506 {
1507 while (count > descr->nb_items)
1508 if ((ret = LISTBOX_InsertString( wnd, descr, -1, 0 )) < 0)
1509 return ret;
1510 }
1511 else if (count < descr->nb_items)
1512 {
1513 while (count < descr->nb_items)
1514 if ((ret = LISTBOX_RemoveItem( wnd, descr, -1 )) < 0)
1515 return ret;
1516 }
1517 return LB_OKAY;
1518}
1519
1520
1521/***********************************************************************
1522 * LISTBOX_Directory
1523 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001524static LRESULT LISTBOX_Directory( WND *wnd, LB_DESCR *descr, UINT attrib,
1525 LPCSTR filespec, BOOL long_names )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001526{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001527 HANDLE handle;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001528 LRESULT ret = LB_OKAY;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001529 WIN32_FIND_DATAA entry;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001530 int pos;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001531
Alexandre Julliarda3960291999-02-26 11:11:13 +00001532 if ((handle = FindFirstFileA(filespec,&entry)) == INVALID_HANDLE_VALUE)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001533 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001534 if (GetLastError() != ERROR_NO_MORE_FILES) return LB_ERR;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001535 }
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001536 else
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001537 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001538 do
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001539 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001540 char buffer[270];
1541 if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1542 {
1543 if (!(attrib & DDL_DIRECTORY) ||
1544 !strcmp( entry.cAlternateFileName, "." )) continue;
1545 if (long_names) sprintf( buffer, "[%s]", entry.cFileName );
1546 else sprintf( buffer, "[%s]", entry.cAlternateFileName );
1547 }
1548 else /* not a directory */
1549 {
1550#define ATTRIBS (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
1551 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE)
1552
1553 if ((attrib & DDL_EXCLUSIVE) &&
1554 ((attrib & ATTRIBS) != (entry.dwFileAttributes & ATTRIBS)))
1555 continue;
1556#undef ATTRIBS
1557 if (long_names) strcpy( buffer, entry.cFileName );
1558 else strcpy( buffer, entry.cAlternateFileName );
1559 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001560 if (!long_names) CharLowerA( buffer );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001561 pos = LISTBOX_FindFileStrPos( wnd, descr, buffer );
1562 if ((ret = LISTBOX_InsertString( wnd, descr, pos, buffer )) < 0)
1563 break;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001564 } while (FindNextFileA( handle, &entry ));
1565 FindClose( handle );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001566 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001567
Alexandre Julliard889f7421997-04-15 17:19:52 +00001568 if ((ret >= 0) && (attrib & DDL_DRIVES))
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001569 {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001570 char buffer[] = "[-a-]";
1571 int drive;
1572 for (drive = 0; drive < MAX_DOS_DRIVES; drive++, buffer[2]++)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001573 {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001574 if (!DRIVE_IsValid(drive)) continue;
1575 if ((ret = LISTBOX_InsertString( wnd, descr, -1, buffer )) < 0)
1576 break;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001577 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001578 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001579 return ret;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001580}
1581
1582
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001583/***********************************************************************
1584 * LISTBOX_HandleVScroll
1585 */
1586static LRESULT LISTBOX_HandleVScroll( WND *wnd, LB_DESCR *descr,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001587 WPARAM wParam, LPARAM lParam )
Alexandre Julliard2787be81995-05-22 18:23:01 +00001588{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001589 SCROLLINFO info;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001590
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001591 if (descr->style & LBS_MULTICOLUMN) return 0;
1592 switch(LOWORD(wParam))
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001593 {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001594 case SB_LINEUP:
1595 LISTBOX_SetTopItem( wnd, descr, descr->top_item - 1, TRUE );
1596 break;
1597 case SB_LINEDOWN:
1598 LISTBOX_SetTopItem( wnd, descr, descr->top_item + 1, TRUE );
1599 break;
1600 case SB_PAGEUP:
1601 LISTBOX_SetTopItem( wnd, descr, descr->top_item -
1602 LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE );
1603 break;
1604 case SB_PAGEDOWN:
1605 LISTBOX_SetTopItem( wnd, descr, descr->top_item +
1606 LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE );
1607 break;
1608 case SB_THUMBPOSITION:
1609 LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam), TRUE );
1610 break;
1611 case SB_THUMBTRACK:
1612 info.cbSize = sizeof(info);
1613 info.fMask = SIF_TRACKPOS;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001614 GetScrollInfo( wnd->hwndSelf, SB_VERT, &info );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001615 LISTBOX_SetTopItem( wnd, descr, info.nTrackPos, TRUE );
1616 break;
1617 case SB_TOP:
1618 LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
1619 break;
1620 case SB_BOTTOM:
1621 LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE );
1622 break;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001623 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001624 return 0;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001625}
1626
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001627
Alexandre Julliard2787be81995-05-22 18:23:01 +00001628/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001629 * LISTBOX_HandleHScroll
Alexandre Julliard2787be81995-05-22 18:23:01 +00001630 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001631static LRESULT LISTBOX_HandleHScroll( WND *wnd, LB_DESCR *descr,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001632 WPARAM wParam, LPARAM lParam )
Alexandre Julliard2787be81995-05-22 18:23:01 +00001633{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001634 SCROLLINFO info;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001635 INT page;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001636
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001637 if (descr->style & LBS_MULTICOLUMN)
1638 {
1639 switch(LOWORD(wParam))
1640 {
1641 case SB_LINELEFT:
1642 LISTBOX_SetTopItem( wnd, descr, descr->top_item-descr->page_size,
1643 TRUE );
1644 break;
1645 case SB_LINERIGHT:
1646 LISTBOX_SetTopItem( wnd, descr, descr->top_item+descr->page_size,
1647 TRUE );
1648 break;
1649 case SB_PAGELEFT:
1650 page = descr->width / descr->column_width;
1651 if (page < 1) page = 1;
1652 LISTBOX_SetTopItem( wnd, descr,
1653 descr->top_item - page * descr->page_size, TRUE );
1654 break;
1655 case SB_PAGERIGHT:
1656 page = descr->width / descr->column_width;
1657 if (page < 1) page = 1;
1658 LISTBOX_SetTopItem( wnd, descr,
1659 descr->top_item + page * descr->page_size, TRUE );
1660 break;
1661 case SB_THUMBPOSITION:
1662 LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam)*descr->page_size,
1663 TRUE );
1664 break;
1665 case SB_THUMBTRACK:
1666 info.cbSize = sizeof(info);
1667 info.fMask = SIF_TRACKPOS;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001668 GetScrollInfo( wnd->hwndSelf, SB_VERT, &info );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001669 LISTBOX_SetTopItem( wnd, descr, info.nTrackPos*descr->page_size,
1670 TRUE );
1671 break;
1672 case SB_LEFT:
1673 LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
1674 break;
1675 case SB_RIGHT:
1676 LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE );
1677 break;
1678 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001679 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001680 else if (descr->horz_extent)
1681 {
1682 switch(LOWORD(wParam))
1683 {
1684 case SB_LINELEFT:
1685 LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos - 1 );
1686 break;
1687 case SB_LINERIGHT:
1688 LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos + 1 );
1689 break;
1690 case SB_PAGELEFT:
1691 LISTBOX_SetHorizontalPos( wnd, descr,
1692 descr->horz_pos - descr->width );
1693 break;
1694 case SB_PAGERIGHT:
1695 LISTBOX_SetHorizontalPos( wnd, descr,
1696 descr->horz_pos + descr->width );
1697 break;
1698 case SB_THUMBPOSITION:
1699 LISTBOX_SetHorizontalPos( wnd, descr, HIWORD(wParam) );
1700 break;
1701 case SB_THUMBTRACK:
1702 info.cbSize = sizeof(info);
1703 info.fMask = SIF_TRACKPOS;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001704 GetScrollInfo( wnd->hwndSelf, SB_HORZ, &info );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001705 LISTBOX_SetHorizontalPos( wnd, descr, info.nTrackPos );
1706 break;
1707 case SB_LEFT:
1708 LISTBOX_SetHorizontalPos( wnd, descr, 0 );
1709 break;
1710 case SB_RIGHT:
1711 LISTBOX_SetHorizontalPos( wnd, descr,
1712 descr->horz_extent - descr->width );
1713 break;
1714 }
1715 }
1716 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001717}
1718
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001719
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001720/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001721 * LISTBOX_HandleLButtonDown
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001722 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001723static LRESULT LISTBOX_HandleLButtonDown( WND *wnd, LB_DESCR *descr,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001724 WPARAM wParam, INT x, INT y )
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001725{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001726 INT index = LISTBOX_GetItemFromPoint( wnd, descr, x, y );
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001727 TRACE(listbox, "[%04x]: lbuttondown %d,%d item %d\n",
1728 wnd->hwndSelf, x, y, index );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001729 if (!descr->caret_on && (GetFocus() == wnd->hwndSelf)) return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001730 if (index != -1)
1731 {
1732 if (descr->style & LBS_EXTENDEDSEL)
1733 {
1734 if (!(wParam & MK_SHIFT)) descr->anchor_item = index;
1735 if (wParam & MK_CONTROL)
1736 {
1737 LISTBOX_SetCaretIndex( wnd, descr, index, FALSE );
1738 LISTBOX_SetSelection( wnd, descr, index,
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001739 !descr->items[index].selected, FALSE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001740 }
1741 else LISTBOX_MoveCaret( wnd, descr, index, FALSE );
1742 }
1743 else
1744 {
1745 LISTBOX_MoveCaret( wnd, descr, index, FALSE );
1746 LISTBOX_SetSelection( wnd, descr, index,
1747 (!(descr->style & LBS_MULTIPLESEL) ||
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001748 !descr->items[index].selected), FALSE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001749 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001750 }
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001751
Alexandre Julliarda3960291999-02-26 11:11:13 +00001752 if( !descr->lphc ) SetFocus( wnd->hwndSelf );
1753 else SetFocus( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001754 : descr->lphc->self->hwndSelf ) ;
1755
Luc Tourangeau5ee117b1999-04-04 12:48:21 +00001756 descr->captured = TRUE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001757 SetCapture( wnd->hwndSelf );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001758 if (index != -1 && !descr->lphc)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001759 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001760 if (descr->style & LBS_NOTIFY )
Alexandre Julliarda3960291999-02-26 11:11:13 +00001761 SendMessageA( descr->owner, WM_LBTRACKPOINT, index,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001762 MAKELPARAM( x, y ) );
1763 if (wnd->dwExStyle & WS_EX_DRAGDETECT)
1764 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001765 POINT pt = { x, y };
1766 if (DragDetect( wnd->hwndSelf, pt ))
1767 SendMessageA( descr->owner, WM_BEGINDRAG, 0, 0 );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001768 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001769 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001770 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001771}
1772
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001773
1774/***********************************************************************
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001775 * LISTBOX_HandleLButtonUp
1776 */
1777static LRESULT LISTBOX_HandleLButtonUp( WND *wnd, LB_DESCR *descr )
1778{
1779 if (LISTBOX_Timer != LB_TIMER_NONE)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001780 KillSystemTimer( wnd->hwndSelf, LB_TIMER_ID );
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001781 LISTBOX_Timer = LB_TIMER_NONE;
Luc Tourangeau5ee117b1999-04-04 12:48:21 +00001782 if (descr->captured)
Alexandre Julliard33072e11997-06-29 18:08:02 +00001783 {
Luc Tourangeau5ee117b1999-04-04 12:48:21 +00001784 descr->captured = FALSE;
1785 if (GetCapture() == wnd->hwndSelf) ReleaseCapture();
Alexandre Julliard33072e11997-06-29 18:08:02 +00001786 if (descr->style & LBS_NOTIFY)
1787 SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
1788 }
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001789 return 0;
1790}
1791
1792
1793/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001794 * LISTBOX_HandleTimer
Alexandre Julliardade697e1995-11-26 13:59:11 +00001795 *
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001796 * Handle scrolling upon a timer event.
1797 * Return TRUE if scrolling should continue.
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001798 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001799static LRESULT LISTBOX_HandleTimer( WND *wnd, LB_DESCR *descr,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001800 INT index, TIMER_DIRECTION dir )
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001801{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001802 switch(dir)
Alexandre Julliardade697e1995-11-26 13:59:11 +00001803 {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001804 case LB_TIMER_UP:
1805 if (descr->top_item) index = descr->top_item - 1;
1806 else index = 0;
1807 break;
1808 case LB_TIMER_LEFT:
1809 if (descr->top_item) index -= descr->page_size;
1810 break;
1811 case LB_TIMER_DOWN:
1812 index = descr->top_item + LISTBOX_GetCurrentPageSize( wnd, descr );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00001813 if (index == descr->focus_item) index++;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001814 if (index >= descr->nb_items) index = descr->nb_items - 1;
1815 break;
1816 case LB_TIMER_RIGHT:
1817 if (index + descr->page_size < descr->nb_items)
1818 index += descr->page_size;
1819 break;
1820 case LB_TIMER_NONE:
1821 break;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001822 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001823 if (index == descr->focus_item) return FALSE;
1824 LISTBOX_MoveCaret( wnd, descr, index, FALSE );
1825 return TRUE;
1826}
Alexandre Julliardade697e1995-11-26 13:59:11 +00001827
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001828
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001829/***********************************************************************
1830 * LISTBOX_HandleSystemTimer
1831 *
1832 * WM_SYSTIMER handler.
1833 */
1834static LRESULT LISTBOX_HandleSystemTimer( WND *wnd, LB_DESCR *descr )
1835{
1836 if (!LISTBOX_HandleTimer( wnd, descr, descr->focus_item, LISTBOX_Timer ))
Alexandre Julliardade697e1995-11-26 13:59:11 +00001837 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001838 KillSystemTimer( wnd->hwndSelf, LB_TIMER_ID );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001839 LISTBOX_Timer = LB_TIMER_NONE;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001840 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001841 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001842}
1843
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001844
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001845/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001846 * LISTBOX_HandleMouseMove
1847 *
1848 * WM_MOUSEMOVE handler.
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001849 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001850static void LISTBOX_HandleMouseMove( WND *wnd, LB_DESCR *descr,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001851 INT x, INT y )
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001852{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001853 INT index;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001854 TIMER_DIRECTION dir;
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00001855
Luc Tourangeau5ee117b1999-04-04 12:48:21 +00001856 if (!descr->captured) return;
1857
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001858 if (descr->style & LBS_MULTICOLUMN)
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00001859 {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001860 if (y < 0) y = 0;
1861 else if (y >= descr->item_height * descr->page_size)
1862 y = descr->item_height * descr->page_size - 1;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001863
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001864 if (x < 0)
1865 {
1866 dir = LB_TIMER_LEFT;
1867 x = 0;
1868 }
1869 else if (x >= descr->width)
1870 {
1871 dir = LB_TIMER_RIGHT;
1872 x = descr->width - 1;
1873 }
1874 else dir = LB_TIMER_NONE; /* inside */
Alexandre Julliard7d654eb1996-02-25 11:36:22 +00001875 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001876 else
1877 {
1878 if (y < 0) dir = LB_TIMER_UP; /* above */
1879 else if (y >= descr->height) dir = LB_TIMER_DOWN; /* below */
1880 else dir = LB_TIMER_NONE; /* inside */
1881 }
1882
1883 index = LISTBOX_GetItemFromPoint( wnd, descr, x, y );
1884 if (index == -1) index = descr->focus_item;
1885 if (!LISTBOX_HandleTimer( wnd, descr, index, dir )) dir = LB_TIMER_NONE;
1886
1887 /* Start/stop the system timer */
1888
1889 if (dir != LB_TIMER_NONE)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001890 SetSystemTimer( wnd->hwndSelf, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001891 else if (LISTBOX_Timer != LB_TIMER_NONE)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001892 KillSystemTimer( wnd->hwndSelf, LB_TIMER_ID );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001893 LISTBOX_Timer = dir;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001894}
1895
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001896
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001897/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001898 * LISTBOX_HandleKeyDown
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001899 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001900static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001901{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001902 INT caret = -1;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001903 if (descr->style & LBS_WANTKEYBOARDINPUT)
1904 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001905 caret = SendMessageA( descr->owner, WM_VKEYTOITEM,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001906 MAKEWPARAM(LOWORD(wParam), descr->focus_item),
1907 wnd->hwndSelf );
1908 if (caret == -2) return 0;
1909 }
1910 if (caret == -1) switch(wParam)
1911 {
1912 case VK_LEFT:
1913 if (descr->style & LBS_MULTICOLUMN)
1914 {
1915 if (descr->focus_item >= descr->page_size)
1916 caret = descr->focus_item - descr->page_size;
1917 break;
1918 }
1919 /* fall through */
1920 case VK_UP:
1921 caret = descr->focus_item - 1;
1922 if (caret < 0) caret = 0;
1923 break;
1924 case VK_RIGHT:
1925 if (descr->style & LBS_MULTICOLUMN)
1926 {
1927 if (descr->focus_item + descr->page_size < descr->nb_items)
1928 caret = descr->focus_item + descr->page_size;
1929 break;
1930 }
1931 /* fall through */
1932 case VK_DOWN:
1933 caret = descr->focus_item + 1;
1934 if (caret >= descr->nb_items) caret = descr->nb_items - 1;
1935 break;
1936 case VK_PRIOR:
1937 if (descr->style & LBS_MULTICOLUMN)
1938 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001939 INT page = descr->width / descr->column_width;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001940 if (page < 1) page = 1;
1941 caret = descr->focus_item - (page * descr->page_size) + 1;
1942 }
1943 else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(wnd,descr)+1;
1944 if (caret < 0) caret = 0;
1945 break;
1946 case VK_NEXT:
1947 if (descr->style & LBS_MULTICOLUMN)
1948 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001949 INT page = descr->width / descr->column_width;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001950 if (page < 1) page = 1;
1951 caret = descr->focus_item + (page * descr->page_size) - 1;
1952 }
1953 else caret = descr->focus_item+LISTBOX_GetCurrentPageSize(wnd,descr)-1;
1954 if (caret >= descr->nb_items) caret = descr->nb_items - 1;
1955 break;
1956 case VK_HOME:
1957 caret = 0;
1958 break;
1959 case VK_END:
1960 caret = descr->nb_items - 1;
1961 break;
1962 case VK_SPACE:
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001963 if (descr->style & LBS_EXTENDEDSEL) caret = descr->focus_item;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001964 else if (descr->style & LBS_MULTIPLESEL)
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001965 {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001966 LISTBOX_SetSelection( wnd, descr, descr->focus_item,
1967 !descr->items[descr->focus_item].selected,
1968 (descr->style & LBS_NOTIFY) != 0 );
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001969 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001970 else if (descr->selected_item == -1)
1971 {
1972 LISTBOX_SetSelection( wnd, descr, descr->focus_item, TRUE,
1973 (descr->style & LBS_NOTIFY) != 0 );
1974 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001975 break;
1976 }
1977 if (caret >= 0)
1978 {
1979 if ((descr->style & LBS_EXTENDEDSEL) &&
Alexandre Julliarda3960291999-02-26 11:11:13 +00001980 !(GetKeyState( VK_SHIFT ) & 0x8000))
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001981 descr->anchor_item = caret;
1982 LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001983 if (descr->style & LBS_NOTIFY)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001984 {
1985 if( descr->lphc && CB_GETTYPE(descr->lphc) != CBS_SIMPLE )
1986 {
1987 /* make sure that combo parent doesn't hide us */
1988 descr->lphc->wState |= CBF_NOROLLUP;
1989 }
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00001990 SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001991 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001992 }
1993 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001994}
1995
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001996
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001997/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001998 * LISTBOX_HandleChar
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001999 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002000static LRESULT LISTBOX_HandleChar( WND *wnd, LB_DESCR *descr,
Alexandre Julliarda3960291999-02-26 11:11:13 +00002001 WPARAM wParam )
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002002{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002003 INT caret = -1;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002004 char str[2] = { wParam & 0xff, '\0' };
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002005
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00002006 if (descr->style & LBS_WANTKEYBOARDINPUT)
2007 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002008 caret = SendMessageA( descr->owner, WM_CHARTOITEM,
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00002009 MAKEWPARAM(LOWORD(wParam), descr->focus_item),
2010 wnd->hwndSelf );
2011 if (caret == -2) return 0;
2012 }
2013 if (caret == -1)
2014 caret = LISTBOX_FindString( wnd, descr, descr->focus_item, str, FALSE);
2015 if (caret != -1)
2016 {
2017 LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
2018 if (descr->style & LBS_NOTIFY)
2019 SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
2020 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002021 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002022}
2023
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002024
2025/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002026 * LISTBOX_Create
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002027 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002028static BOOL LISTBOX_Create( WND *wnd, LPHEADCOMBO lphc )
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002029{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002030 LB_DESCR *descr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002031 MEASUREITEMSTRUCT mis;
2032 RECT rect;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002033
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002034 if (!(descr = HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) )))
2035 return FALSE;
2036 if (!(descr->heap = HeapCreate( 0, 0x10000, 0 )))
2037 {
2038 HeapFree( GetProcessHeap(), 0, descr );
2039 return FALSE;
2040 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002041 GetClientRect( wnd->hwndSelf, &rect );
2042 descr->owner = GetParent( wnd->hwndSelf );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002043 descr->style = wnd->dwStyle;
2044 descr->width = rect.right - rect.left;
2045 descr->height = rect.bottom - rect.top;
2046 descr->items = NULL;
2047 descr->nb_items = 0;
2048 descr->top_item = 0;
2049 descr->selected_item = -1;
2050 descr->focus_item = 0;
2051 descr->anchor_item = -1;
2052 descr->item_height = 1;
2053 descr->page_size = 1;
2054 descr->column_width = 150;
2055 descr->horz_extent = (wnd->dwStyle & WS_HSCROLL) ? 1 : 0;
2056 descr->horz_pos = 0;
2057 descr->nb_tabs = 0;
2058 descr->tabs = NULL;
2059 descr->caret_on = TRUE;
Luc Tourangeau5ee117b1999-04-04 12:48:21 +00002060 descr->captured = FALSE;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002061 descr->font = 0;
2062 descr->locale = 0; /* FIXME */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002063 descr->lphc = lphc;
2064
2065 if( lphc )
2066 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002067 TRACE(combo,"[%04x]: resetting owner %04x -> %04x\n",
2068 wnd->hwndSelf, descr->owner, lphc->self->hwndSelf );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002069 descr->owner = lphc->self->hwndSelf;
2070 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00002071
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002072 *(LB_DESCR **)wnd->wExtra = descr;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002073
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002074/* if (wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) descr->style &= ~LBS_NOTIFY;
2075 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002076 if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
2077 if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
2078 if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
2079 descr->item_height = LISTBOX_SetFont( wnd, descr, 0 );
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002080
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002081 if (descr->style & LBS_OWNERDRAWFIXED)
2082 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002083 if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
2084 {
2085 /* WinWord gets VERY unhappy if we send WM_MEASUREITEM from here */
Francis Beaudetf585c611999-04-02 10:37:42 +00002086 descr->item_height = lphc->fixedOwnerDrawHeight;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002087 }
2088 else
2089 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002090 UINT id = (descr->lphc ) ? ID_CB_LISTBOX : wnd->wIDmenu;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002091
2092 mis.CtlType = ODT_LISTBOX;
2093 mis.CtlID = id;
2094 mis.itemID = -1;
2095 mis.itemWidth = 0;
2096 mis.itemData = 0;
2097 mis.itemHeight = descr->item_height;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002098 SendMessageA( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002099 descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
2100 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002101 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002102
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002103 return TRUE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002104}
2105
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002106
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002107/***********************************************************************
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002108 * LISTBOX_Destroy
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002109 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002110static BOOL LISTBOX_Destroy( WND *wnd, LB_DESCR *descr )
Alexandre Julliardfa68b751995-04-03 16:55:37 +00002111{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002112 LISTBOX_ResetContent( wnd, descr );
2113 HeapDestroy( descr->heap );
2114 HeapFree( GetProcessHeap(), 0, descr );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002115 wnd->wExtra[0] = 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00002116 return TRUE;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002117}
2118
2119
2120/***********************************************************************
2121 * ListBoxWndProc
2122 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002123LRESULT WINAPI ListBoxWndProc( HWND hwnd, UINT msg,
2124 WPARAM wParam, LPARAM lParam )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002125{
2126 LRESULT ret;
2127 LB_DESCR *descr;
2128 WND *wnd = WIN_FindWndPtr( hwnd );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002129 LRESULT retvalue;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002130
2131 if (!wnd) return 0;
2132 if (!(descr = *(LB_DESCR **)wnd->wExtra))
2133 {
2134 if (msg == WM_CREATE)
2135 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002136 if (!LISTBOX_Create( wnd, NULL ))
2137 {
2138 retvalue = -1;
2139 goto END;
2140 }
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002141 TRACE(listbox, "creating wnd=%04x descr=%p\n",
2142 hwnd, *(LB_DESCR **)wnd->wExtra );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002143 retvalue = 0;
2144 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002145 }
2146 /* Ignore all other messages before we get a WM_CREATE */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002147 retvalue = DefWindowProcA( hwnd, msg, wParam, lParam );
2148 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002149 }
2150
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002151 TRACE(listbox, "[%04x]: msg %s wp %08x lp %08lx\n",
2152 wnd->hwndSelf, SPY_GetMsgName(msg), wParam, lParam );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002153 switch(msg)
2154 {
2155 case LB_RESETCONTENT16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002156 case LB_RESETCONTENT:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002157 LISTBOX_ResetContent( wnd, descr );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002158 retvalue = 0;
2159 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002160
2161 case LB_ADDSTRING16:
2162 if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
2163 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002164 case LB_ADDSTRING:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002165 wParam = LISTBOX_FindStringPos( wnd, descr, (LPCSTR)lParam, FALSE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002166 retvalue = LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
2167 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002168
2169 case LB_INSERTSTRING16:
2170 if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002171 wParam = (INT)(INT16)wParam;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002172 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002173 case LB_INSERTSTRING:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002174 retvalue = LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
2175 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002176
2177 case LB_ADDFILE16:
2178 if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
2179 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002180 case LB_ADDFILE:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002181 wParam = LISTBOX_FindFileStrPos( wnd, descr, (LPCSTR)lParam );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002182 retvalue = LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
2183 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002184
2185 case LB_DELETESTRING16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002186 case LB_DELETESTRING:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002187 retvalue = LISTBOX_RemoveItem( wnd, descr, wParam );
2188 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002189
2190 case LB_GETITEMDATA16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002191 case LB_GETITEMDATA:
2192 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002193 {
2194 retvalue = LB_ERR;
2195 goto END;
2196 }
2197 retvalue = descr->items[wParam].data;
2198 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002199
2200 case LB_SETITEMDATA16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002201 case LB_SETITEMDATA:
2202 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002203 {
2204 retvalue = LB_ERR;
2205 goto END;
2206 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002207 descr->items[wParam].data = (DWORD)lParam;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002208 retvalue = LB_OKAY;
2209 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002210
2211 case LB_GETCOUNT16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002212 case LB_GETCOUNT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002213 retvalue = descr->nb_items;
2214 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002215
2216 case LB_GETTEXT16:
2217 lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
2218 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002219 case LB_GETTEXT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002220 retvalue = LISTBOX_GetText( wnd, descr, wParam, (LPSTR)lParam );
2221 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002222
2223 case LB_GETTEXTLEN16:
2224 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002225 case LB_GETTEXTLEN:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002226 if (wParam >= descr->nb_items)
2227 {
2228 retvalue = LB_ERR;
2229 goto END;
2230 }
2231 retvalue = (HAS_STRINGS(descr) ? strlen(descr->items[wParam].str)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002232 : sizeof(DWORD));
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002233 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002234
2235 case LB_GETCURSEL16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002236 case LB_GETCURSEL:
Francis Beaudet8730e451999-03-25 13:22:02 +00002237 if (descr->nb_items==0)
2238 retvalue = LB_ERR;
2239 else
2240 {
2241 retvalue = descr->selected_item;
2242 if (retvalue == -1) retvalue = descr->focus_item;
2243 }
Lawson Whitney613092a1999-03-22 14:46:43 +00002244 /* otherwise, if the user tries to move the selection with the */
2245 /* arrow keys, we will give the application something to choke on */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002246 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002247
2248 case LB_GETTOPINDEX16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002249 case LB_GETTOPINDEX:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002250 retvalue = descr->top_item;
2251 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002252
2253 case LB_GETITEMHEIGHT16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002254 case LB_GETITEMHEIGHT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002255 retvalue = LISTBOX_GetItemHeight( wnd, descr, wParam );
2256 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002257
2258 case LB_SETITEMHEIGHT16:
2259 lParam = LOWORD(lParam);
2260 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002261 case LB_SETITEMHEIGHT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002262 retvalue = LISTBOX_SetItemHeight( wnd, descr, wParam, lParam );
2263 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002264
Alexandre Julliarda3960291999-02-26 11:11:13 +00002265 case LB_ITEMFROMPOINT:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002266 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002267 POINT pt = { LOWORD(lParam), HIWORD(lParam) };
2268 RECT rect = { 0, 0, descr->width, descr->height };
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002269 retvalue = MAKELONG( LISTBOX_GetItemFromPoint(wnd, descr, pt.x, pt.y),
Alexandre Julliarda3960291999-02-26 11:11:13 +00002270 PtInRect( &rect, pt ) );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002271 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002272 }
2273
2274 case LB_SETCARETINDEX16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002275 case LB_SETCARETINDEX:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002276 retvalue = LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam );
2277 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002278
2279 case LB_GETCARETINDEX16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002280 case LB_GETCARETINDEX:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002281 retvalue = descr->focus_item;
2282 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002283
2284 case LB_SETTOPINDEX16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002285 case LB_SETTOPINDEX:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002286 retvalue = LISTBOX_SetTopItem( wnd, descr, wParam, TRUE );
2287 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002288
2289 case LB_SETCOLUMNWIDTH16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002290 case LB_SETCOLUMNWIDTH:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002291 retvalue = LISTBOX_SetColumnWidth( wnd, descr, wParam );
2292 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002293
2294 case LB_GETITEMRECT16:
2295 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002296 RECT rect;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002297 ret = LISTBOX_GetItemRect( wnd, descr, (INT16)wParam, &rect );
2298 CONV_RECT32TO16( &rect, (RECT16 *)PTR_SEG_TO_LIN(lParam) );
2299 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002300 retvalue = ret;
2301 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002302
Alexandre Julliarda3960291999-02-26 11:11:13 +00002303 case LB_GETITEMRECT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002304 retvalue = LISTBOX_GetItemRect( wnd, descr, wParam, (RECT *)lParam );
2305 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002306
2307 case LB_FINDSTRING16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002308 wParam = (INT)(INT16)wParam;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002309 if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
2310 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002311 case LB_FINDSTRING:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002312 retvalue = LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, FALSE );
2313 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002314
2315 case LB_FINDSTRINGEXACT16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002316 wParam = (INT)(INT16)wParam;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002317 if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
2318 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002319 case LB_FINDSTRINGEXACT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002320 retvalue = LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, TRUE );
2321 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002322
2323 case LB_SELECTSTRING16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002324 wParam = (INT)(INT16)wParam;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002325 if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
2326 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002327 case LB_SELECTSTRING:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002328 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002329 INT index = LISTBOX_FindString( wnd, descr, wParam,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002330 (LPCSTR)lParam, FALSE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002331 if (index == LB_ERR)
2332 {
2333 retvalue = LB_ERR;
2334 goto END;
2335 }
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +00002336 LISTBOX_SetSelection( wnd, descr, index, TRUE, FALSE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002337 retvalue = index;
2338 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002339 }
2340
2341 case LB_GETSEL16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002342 wParam = (INT)(INT16)wParam;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002343 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002344 case LB_GETSEL:
2345 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002346 {
2347 retvalue = LB_ERR;
2348 goto END;
2349 }
2350 retvalue = descr->items[wParam].selected;
2351 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002352
2353 case LB_SETSEL16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002354 lParam = (INT)(INT16)lParam;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002355 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002356 case LB_SETSEL:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002357 retvalue = LISTBOX_SetSelection( wnd, descr, lParam, wParam, FALSE );
2358 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002359
2360 case LB_SETCURSEL16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002361 wParam = (INT)(INT16)wParam;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002362 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002363 case LB_SETCURSEL:
Alexandre Julliard638f1691999-01-17 16:32:32 +00002364 LISTBOX_SetCaretIndex( wnd, descr, wParam, TRUE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002365 retvalue = LISTBOX_SetSelection( wnd, descr, wParam, TRUE, FALSE );
2366 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002367
2368 case LB_GETSELCOUNT16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002369 case LB_GETSELCOUNT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002370 retvalue = LISTBOX_GetSelCount( wnd, descr );
2371 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002372
2373 case LB_GETSELITEMS16:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002374 retvalue = LISTBOX_GetSelItems16( wnd, descr, wParam,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002375 (LPINT16)PTR_SEG_TO_LIN(lParam) );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002376 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002377
Alexandre Julliarda3960291999-02-26 11:11:13 +00002378 case LB_GETSELITEMS:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002379 retvalue = LISTBOX_GetSelItems( wnd, descr, wParam, (LPINT)lParam );
2380 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002381
2382 case LB_SELITEMRANGE16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002383 case LB_SELITEMRANGE:
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002384 if (LOWORD(lParam) <= HIWORD(lParam))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002385 {
2386 retvalue = LISTBOX_SelectItemRange( wnd, descr, LOWORD(lParam),
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002387 HIWORD(lParam), wParam );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002388 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002389 else
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002390 {
2391 retvalue = LISTBOX_SelectItemRange( wnd, descr, HIWORD(lParam),
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002392 LOWORD(lParam), wParam );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002393 }
2394 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002395
2396 case LB_SELITEMRANGEEX16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002397 case LB_SELITEMRANGEEX:
2398 if ((INT)lParam >= (INT)wParam)
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002399 retvalue = LISTBOX_SelectItemRange( wnd, descr, wParam, lParam, TRUE );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002400 else
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002401 retvalue = LISTBOX_SelectItemRange( wnd, descr, lParam, wParam, FALSE);
2402 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002403
2404 case LB_GETHORIZONTALEXTENT16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002405 case LB_GETHORIZONTALEXTENT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002406 retvalue = descr->horz_extent;
2407 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002408
2409 case LB_SETHORIZONTALEXTENT16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002410 case LB_SETHORIZONTALEXTENT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002411 retvalue = LISTBOX_SetHorizontalExtent( wnd, descr, wParam );
2412 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002413
2414 case LB_GETANCHORINDEX16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002415 case LB_GETANCHORINDEX:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002416 retvalue = descr->anchor_item;
2417 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002418
2419 case LB_SETANCHORINDEX16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002420 wParam = (INT)(INT16)wParam;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002421 /* fall through */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002422 case LB_SETANCHORINDEX:
2423 if (((INT)wParam < -1) || ((INT)wParam >= descr->nb_items))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002424 {
2425 retvalue = LB_ERR;
2426 goto END;
2427 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002428 descr->anchor_item = (INT)wParam;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002429 retvalue = LB_OKAY;
2430 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002431
2432 case LB_DIR16:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002433 retvalue = LISTBOX_Directory( wnd, descr, wParam,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002434 (LPCSTR)PTR_SEG_TO_LIN(lParam), FALSE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002435 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002436
Alexandre Julliarda3960291999-02-26 11:11:13 +00002437 case LB_DIR:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002438 retvalue = LISTBOX_Directory( wnd, descr, wParam, (LPCSTR)lParam, TRUE );
2439 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002440
Alexandre Julliarda3960291999-02-26 11:11:13 +00002441 case LB_GETLOCALE:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002442 retvalue = descr->locale;
2443 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002444
Alexandre Julliarda3960291999-02-26 11:11:13 +00002445 case LB_SETLOCALE:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002446 descr->locale = (LCID)wParam; /* FIXME: should check for valid lcid */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002447 retvalue = LB_OKAY;
2448 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002449
Alexandre Julliarda3960291999-02-26 11:11:13 +00002450 case LB_INITSTORAGE:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002451 retvalue = LISTBOX_InitStorage( wnd, descr, wParam, (DWORD)lParam );
2452 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002453
Alexandre Julliarda3960291999-02-26 11:11:13 +00002454 case LB_SETCOUNT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002455 retvalue = LISTBOX_SetCount( wnd, descr, (INT)wParam );
2456 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002457
2458 case LB_SETTABSTOPS16:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002459 retvalue = LISTBOX_SetTabStops( wnd, descr, (INT)(INT16)wParam,
Alexandre Julliarda3960291999-02-26 11:11:13 +00002460 (LPINT)PTR_SEG_TO_LIN(lParam), TRUE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002461 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002462
Alexandre Julliarda3960291999-02-26 11:11:13 +00002463 case LB_SETTABSTOPS:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002464 retvalue = LISTBOX_SetTabStops( wnd, descr, wParam,
Alexandre Julliarda3960291999-02-26 11:11:13 +00002465 (LPINT)lParam, FALSE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002466 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002467
2468 case LB_CARETON16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002469 case LB_CARETON:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002470 if (descr->caret_on)
2471 {
2472 retvalue = LB_OKAY;
2473 goto END;
2474 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002475 descr->caret_on = TRUE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002476 if ((descr->focus_item != -1) && (GetFocus() == wnd->hwndSelf))
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002477 LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002478 retvalue = LB_OKAY;
2479 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002480
2481 case LB_CARETOFF16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002482 case LB_CARETOFF:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002483 if (!descr->caret_on)
2484 {
2485 retvalue = LB_OKAY;
2486 goto END;
2487 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002488 descr->caret_on = FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002489 if ((descr->focus_item != -1) && (GetFocus() == wnd->hwndSelf))
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002490 LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002491 retvalue = LB_OKAY;
2492 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002493
2494 case WM_DESTROY:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002495 retvalue = LISTBOX_Destroy( wnd, descr );
2496 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002497
2498 case WM_ENABLE:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002499 InvalidateRect( hwnd, NULL, TRUE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002500 retvalue = 0;
2501 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002502
2503 case WM_SETREDRAW:
2504 LISTBOX_SetRedraw( wnd, descr, wParam != 0 );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002505 retvalue = 0;
2506 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002507
2508 case WM_GETDLGCODE:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002509 retvalue =DLGC_WANTARROWS | DLGC_WANTCHARS;
2510 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002511 case WM_PAINT:
2512 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002513 PAINTSTRUCT ps;
2514 HDC hdc = ( wParam ) ? ((HDC)wParam)
2515 : BeginPaint( hwnd, &ps );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002516 ret = LISTBOX_Paint( wnd, descr, hdc );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002517 if( !wParam ) EndPaint( hwnd, &ps );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002518 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002519 retvalue =ret;
2520 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002521 case WM_SIZE:
2522 LISTBOX_UpdateSize( wnd, descr );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002523 retvalue =0;
2524 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002525 case WM_GETFONT:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002526 retvalue =descr->font;
2527 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002528 case WM_SETFONT:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002529 LISTBOX_SetFont( wnd, descr, (HFONT)wParam );
2530 if (lParam) InvalidateRect( wnd->hwndSelf, 0, TRUE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002531 retvalue =0;
2532 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002533 case WM_SETFOCUS:
2534 descr->caret_on = TRUE;
2535 if (descr->focus_item != -1)
2536 LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
2537 SEND_NOTIFICATION( wnd, descr, LBN_SETFOCUS );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002538 retvalue =0;
2539 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002540 case WM_KILLFOCUS:
2541 if ((descr->focus_item != -1) && descr->caret_on)
2542 LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
2543 SEND_NOTIFICATION( wnd, descr, LBN_KILLFOCUS );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002544 retvalue =0;
2545 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002546 case WM_HSCROLL:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002547 retvalue =LISTBOX_HandleHScroll( wnd, descr, wParam, lParam );
2548 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002549 case WM_VSCROLL:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002550 retvalue =LISTBOX_HandleVScroll( wnd, descr, wParam, lParam );
2551 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002552 case WM_LBUTTONDOWN:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002553 retvalue =LISTBOX_HandleLButtonDown( wnd, descr, wParam,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002554 (INT16)LOWORD(lParam),
2555 (INT16)HIWORD(lParam) );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002556 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002557 case WM_LBUTTONDBLCLK:
2558 if (descr->style & LBS_NOTIFY)
2559 SEND_NOTIFICATION( wnd, descr, LBN_DBLCLK );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002560 retvalue =0;
2561 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002562 case WM_MOUSEMOVE:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002563 if (GetCapture() == hwnd)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002564 LISTBOX_HandleMouseMove( wnd, descr, (INT16)LOWORD(lParam),
2565 (INT16)HIWORD(lParam) );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002566 retvalue =0;
2567 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002568 case WM_LBUTTONUP:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002569 retvalue =LISTBOX_HandleLButtonUp( wnd, descr );
2570 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002571 case WM_KEYDOWN:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002572 retvalue =LISTBOX_HandleKeyDown( wnd, descr, wParam );
2573 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002574 case WM_CHAR:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002575 retvalue =LISTBOX_HandleChar( wnd, descr, wParam );
2576 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002577 case WM_SYSTIMER:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002578 retvalue =LISTBOX_HandleSystemTimer( wnd, descr );
2579 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002580 case WM_ERASEBKGND:
2581 if (IS_OWNERDRAW(descr))
2582 {
Luc Tourangeau89147991999-04-18 09:23:56 +00002583 RECT rect;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002584 HBRUSH hbrush = SendMessageA( descr->owner, WM_CTLCOLORLISTBOX,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002585 wParam, (LPARAM)wnd->hwndSelf );
Luc Tourangeau89147991999-04-18 09:23:56 +00002586 GetClientRect(hwnd, &rect);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002587 if (hbrush) FillRect( (HDC)wParam, &rect, hbrush );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002588 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002589 retvalue =1;
2590 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002591 case WM_DROPFILES:
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002592 if( !descr->lphc )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002593 {
2594 retvalue =SendMessageA( descr->owner, msg, wParam, lParam );
2595 goto END;
2596 }
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002597 break;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002598
2599 case WM_DROPOBJECT:
2600 case WM_QUERYDROPOBJECT:
2601 case WM_DRAGSELECT:
2602 case WM_DRAGMOVE:
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002603 if( !descr->lphc )
2604 {
2605 LPDRAGINFO dragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN( (SEGPTR)lParam );
2606 dragInfo->l = LISTBOX_GetItemFromPoint( wnd, descr, dragInfo->pt.x,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002607 dragInfo->pt.y );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002608 retvalue =SendMessageA( descr->owner, msg, wParam, lParam );
2609 goto END;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002610 }
2611 break;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002612
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00002613 case WM_NCCREATE:
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002614 if (TWEAK_WineLook > WIN31_LOOK)
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00002615 wnd->dwExStyle |= WS_EX_CLIENTEDGE;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002616 retvalue =DefWindowProcA( hwnd, msg, wParam, lParam );
2617 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002618 default:
2619 if ((msg >= WM_USER) && (msg < 0xc000))
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002620 WARN(listbox, "[%04x]: unknown msg %04x wp %08x lp %08lx\n",
2621 hwnd, msg, wParam, lParam );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002622 retvalue =DefWindowProcA( hwnd, msg, wParam, lParam );
2623 goto END;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002624 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002625 retvalue =0;
2626END:
2627 WIN_ReleaseWndPtr(wnd);
2628 return retvalue;
Alexandre Julliard58199531994-04-21 01:20:00 +00002629}
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002630
2631/***********************************************************************
2632 * COMBO_Directory
2633 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002634LRESULT COMBO_Directory( LPHEADCOMBO lphc, UINT attrib, LPSTR dir, BOOL bLong)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002635{
2636 WND *wnd = WIN_FindWndPtr( lphc->hWndLBox );
2637
2638 if( wnd )
2639 {
2640 LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
2641 if( descr )
2642 {
2643 LRESULT lRet = LISTBOX_Directory( wnd, descr, attrib, dir, bLong );
2644
Alexandre Julliarda3960291999-02-26 11:11:13 +00002645 RedrawWindow( lphc->self->hwndSelf, NULL, 0,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002646 RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002647 WIN_ReleaseWndPtr(wnd);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002648 return lRet;
2649 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002650 WIN_ReleaseWndPtr(wnd);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002651 }
2652 return CB_ERR;
2653}
2654
2655/***********************************************************************
2656 * ComboLBWndProc
2657 *
2658 * NOTE: in Windows, winproc address of the ComboLBox is the same
2659 * as that of the Listbox.
2660 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002661LRESULT WINAPI ComboLBWndProc( HWND hwnd, UINT msg,
2662 WPARAM wParam, LPARAM lParam )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002663{
2664 LRESULT lRet = 0;
2665 WND *wnd = WIN_FindWndPtr( hwnd );
2666
2667 if (wnd)
2668 {
2669 LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
2670
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002671 TRACE(combo, "[%04x]: msg %s wp %08x lp %08lx\n",
2672 wnd->hwndSelf, SPY_GetMsgName(msg), wParam, lParam );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002673
2674 if( descr || msg == WM_CREATE )
2675 {
2676 LPHEADCOMBO lphc = (descr) ? descr->lphc : NULL;
2677
2678 switch( msg )
2679 {
2680 case WM_CREATE:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002681#define lpcs ((LPCREATESTRUCTA)lParam)
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002682 TRACE(combo, "\tpassed parent handle = 0x%08x\n",
Alexandre Julliarda3960291999-02-26 11:11:13 +00002683 (UINT)lpcs->lpCreateParams);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002684
2685 lphc = (LPHEADCOMBO)(lpcs->lpCreateParams);
2686#undef lpcs
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002687 lRet =LISTBOX_Create( wnd, lphc );
2688 goto END;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002689 case WM_LBUTTONDOWN:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002690 lRet =LISTBOX_HandleLButtonDown( wnd, descr, wParam,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002691 (INT16)LOWORD(lParam), (INT16)HIWORD(lParam));
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002692 goto END;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002693 /* avoid activation at all costs */
2694
2695 case WM_MOUSEACTIVATE:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002696 lRet =MA_NOACTIVATE;
2697 goto END;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002698 case WM_NCACTIVATE:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002699 lRet =FALSE;
2700 goto END;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002701 case WM_KEYDOWN:
2702 if( CB_GETTYPE(lphc) != CBS_SIMPLE )
2703 {
2704 /* for some reason(?) Windows makes it possible to
2705 * show/hide ComboLBox by sending it WM_KEYDOWNs */
2706
2707 if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
2708 ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
2709 && (wParam == VK_DOWN || wParam == VK_UP)) )
2710 {
2711 COMBO_FlipListbox( lphc, FALSE );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002712 lRet =0;
2713 goto END;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002714 }
2715 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002716 lRet =LISTBOX_HandleKeyDown( wnd, descr, wParam );
2717 goto END;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002718
Alex Korobka311d3291999-01-01 18:40:02 +00002719 case LB_SETCURSEL16:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002720 case LB_SETCURSEL:
Alex Korobka311d3291999-01-01 18:40:02 +00002721 lRet = ListBoxWndProc( hwnd, msg, wParam, lParam );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002722 lRet =(lRet == LB_ERR) ? lRet : descr->selected_item;
2723 goto END;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002724 case WM_NCDESTROY:
2725 if( CB_GETTYPE(lphc) != CBS_SIMPLE )
2726 lphc->hWndLBox = 0;
2727 /* fall through */
2728
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002729 default:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002730 lRet =ListBoxWndProc( hwnd, msg, wParam, lParam );
2731 goto END;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002732 }
2733 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002734 lRet = DefWindowProcA( hwnd, msg, wParam, lParam );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002735
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002736 TRACE(combo,"\t default on msg [%04x]\n", (UINT16)msg );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002737 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002738END:
2739 WIN_ReleaseWndPtr(wnd);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002740 return lRet;
2741}
2742