1b3fb8555SGiannis Adamopoulos /*
2b3fb8555SGiannis Adamopoulos * Listbox controls
3b3fb8555SGiannis Adamopoulos *
4b3fb8555SGiannis Adamopoulos * Copyright 1996 Alexandre Julliard
5b3fb8555SGiannis Adamopoulos * Copyright 2005 Frank Richter
6b3fb8555SGiannis Adamopoulos *
7b3fb8555SGiannis Adamopoulos * This library is free software; you can redistribute it and/or
8b3fb8555SGiannis Adamopoulos * modify it under the terms of the GNU Lesser General Public
9b3fb8555SGiannis Adamopoulos * License as published by the Free Software Foundation; either
10b3fb8555SGiannis Adamopoulos * version 2.1 of the License, or (at your option) any later version.
11b3fb8555SGiannis Adamopoulos *
12b3fb8555SGiannis Adamopoulos * This library is distributed in the hope that it will be useful,
13b3fb8555SGiannis Adamopoulos * but WITHOUT ANY WARRANTY; without even the implied warranty of
14b3fb8555SGiannis Adamopoulos * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15b3fb8555SGiannis Adamopoulos * Lesser General Public License for more details.
16b3fb8555SGiannis Adamopoulos *
17b3fb8555SGiannis Adamopoulos * You should have received a copy of the GNU Lesser General Public
18b3fb8555SGiannis Adamopoulos * License along with this library; if not, write to the Free Software
19b3fb8555SGiannis Adamopoulos * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20b3fb8555SGiannis Adamopoulos *
21b3fb8555SGiannis Adamopoulos */
22b3fb8555SGiannis Adamopoulos
23b3fb8555SGiannis Adamopoulos #include <string.h>
24b3fb8555SGiannis Adamopoulos #include <stdlib.h>
25b3fb8555SGiannis Adamopoulos #include <stdarg.h>
26b3fb8555SGiannis Adamopoulos #include <stdio.h>
27b3fb8555SGiannis Adamopoulos #include "windef.h"
28b3fb8555SGiannis Adamopoulos #include "winbase.h"
29b3fb8555SGiannis Adamopoulos #include "wingdi.h"
30b3fb8555SGiannis Adamopoulos #include "winuser.h"
31b3fb8555SGiannis Adamopoulos #include "commctrl.h"
32b3fb8555SGiannis Adamopoulos #include "uxtheme.h"
33b3fb8555SGiannis Adamopoulos #include "vssym32.h"
34b3fb8555SGiannis Adamopoulos #include "wine/exception.h"
35b3fb8555SGiannis Adamopoulos #include "wine/debug.h"
36*0707475fSJustin Miller #include "wine/heap.h"
37b3fb8555SGiannis Adamopoulos
38b3fb8555SGiannis Adamopoulos #include "comctl32.h"
39b3fb8555SGiannis Adamopoulos
40*0707475fSJustin Miller WINE_DEFAULT_DEBUG_CHANNEL(listbox);
41b3fb8555SGiannis Adamopoulos
42*0707475fSJustin Miller /* Items array granularity (must be power of 2) */
43b3fb8555SGiannis Adamopoulos #define LB_ARRAY_GRANULARITY 16
44b3fb8555SGiannis Adamopoulos
45b3fb8555SGiannis Adamopoulos /* Scrolling timeout in ms */
46b3fb8555SGiannis Adamopoulos #define LB_SCROLL_TIMEOUT 50
47b3fb8555SGiannis Adamopoulos
48b3fb8555SGiannis Adamopoulos /* Listbox system timer id */
49b3fb8555SGiannis Adamopoulos #define LB_TIMER_ID 2
50b3fb8555SGiannis Adamopoulos
51b3fb8555SGiannis Adamopoulos /* flag listbox changed while setredraw false - internal style */
52b3fb8555SGiannis Adamopoulos #define LBS_DISPLAYCHANGED 0x80000000
53b3fb8555SGiannis Adamopoulos
54b3fb8555SGiannis Adamopoulos /* Item structure */
55b3fb8555SGiannis Adamopoulos typedef struct
56b3fb8555SGiannis Adamopoulos {
57b3fb8555SGiannis Adamopoulos LPWSTR str; /* Item text */
58b3fb8555SGiannis Adamopoulos BOOL selected; /* Is item selected? */
59b3fb8555SGiannis Adamopoulos UINT height; /* Item height (only for OWNERDRAWVARIABLE) */
60b3fb8555SGiannis Adamopoulos ULONG_PTR data; /* User data */
61b3fb8555SGiannis Adamopoulos } LB_ITEMDATA;
62b3fb8555SGiannis Adamopoulos
63b3fb8555SGiannis Adamopoulos /* Listbox structure */
64b3fb8555SGiannis Adamopoulos typedef struct
65b3fb8555SGiannis Adamopoulos {
66b3fb8555SGiannis Adamopoulos HWND self; /* Our own window handle */
67b3fb8555SGiannis Adamopoulos HWND owner; /* Owner window to send notifications to */
68b3fb8555SGiannis Adamopoulos UINT style; /* Window style */
69b3fb8555SGiannis Adamopoulos INT width; /* Window width */
70b3fb8555SGiannis Adamopoulos INT height; /* Window height */
71*0707475fSJustin Miller union
72*0707475fSJustin Miller {
73b3fb8555SGiannis Adamopoulos LB_ITEMDATA *items; /* Array of items */
74*0707475fSJustin Miller BYTE *nodata_items; /* For multi-selection LBS_NODATA */
75*0707475fSJustin Miller } u;
76b3fb8555SGiannis Adamopoulos INT nb_items; /* Number of items */
77*0707475fSJustin Miller UINT items_size; /* Total number of allocated items in the array */
78b3fb8555SGiannis Adamopoulos INT top_item; /* Top visible item */
79b3fb8555SGiannis Adamopoulos INT selected_item; /* Selected item */
80b3fb8555SGiannis Adamopoulos INT focus_item; /* Item that has the focus */
81b3fb8555SGiannis Adamopoulos INT anchor_item; /* Anchor item for extended selection */
82b3fb8555SGiannis Adamopoulos INT item_height; /* Default item height */
83b3fb8555SGiannis Adamopoulos INT page_size; /* Items per listbox page */
84b3fb8555SGiannis Adamopoulos INT column_width; /* Column width for multi-column listboxes */
85b3fb8555SGiannis Adamopoulos INT horz_extent; /* Horizontal extent */
86b3fb8555SGiannis Adamopoulos INT horz_pos; /* Horizontal position */
87b3fb8555SGiannis Adamopoulos INT nb_tabs; /* Number of tabs in array */
88b3fb8555SGiannis Adamopoulos INT *tabs; /* Array of tabs */
89b3fb8555SGiannis Adamopoulos INT avg_char_width; /* Average width of characters */
90b3fb8555SGiannis Adamopoulos INT wheel_remain; /* Left over scroll amount */
91b3fb8555SGiannis Adamopoulos BOOL caret_on; /* Is caret on? */
92b3fb8555SGiannis Adamopoulos BOOL captured; /* Is mouse captured? */
93b3fb8555SGiannis Adamopoulos BOOL in_focus;
94b3fb8555SGiannis Adamopoulos HFONT font; /* Current font */
95b3fb8555SGiannis Adamopoulos LCID locale; /* Current locale for string comparisons */
96b3fb8555SGiannis Adamopoulos HEADCOMBO *lphc; /* ComboLBox */
97b3fb8555SGiannis Adamopoulos } LB_DESCR;
98b3fb8555SGiannis Adamopoulos
99b3fb8555SGiannis Adamopoulos
100b3fb8555SGiannis Adamopoulos #define IS_OWNERDRAW(descr) \
101b3fb8555SGiannis Adamopoulos ((descr)->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))
102b3fb8555SGiannis Adamopoulos
103b3fb8555SGiannis Adamopoulos #define HAS_STRINGS(descr) \
104b3fb8555SGiannis Adamopoulos (!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
105b3fb8555SGiannis Adamopoulos
106b3fb8555SGiannis Adamopoulos
107b3fb8555SGiannis Adamopoulos #define IS_MULTISELECT(descr) \
108b3fb8555SGiannis Adamopoulos ((descr)->style & (LBS_MULTIPLESEL|LBS_EXTENDEDSEL) && \
109b3fb8555SGiannis Adamopoulos !((descr)->style & LBS_NOSEL))
110b3fb8555SGiannis Adamopoulos
111b3fb8555SGiannis Adamopoulos #define SEND_NOTIFICATION(descr,code) \
112b3fb8555SGiannis Adamopoulos (SendMessageW( (descr)->owner, WM_COMMAND, \
113b3fb8555SGiannis Adamopoulos MAKEWPARAM( GetWindowLongPtrW((descr->self),GWLP_ID), (code)), (LPARAM)(descr->self) ))
114b3fb8555SGiannis Adamopoulos
115b3fb8555SGiannis Adamopoulos #define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
116b3fb8555SGiannis Adamopoulos
117b3fb8555SGiannis Adamopoulos /* Current timer status */
118b3fb8555SGiannis Adamopoulos typedef enum
119b3fb8555SGiannis Adamopoulos {
120b3fb8555SGiannis Adamopoulos LB_TIMER_NONE,
121b3fb8555SGiannis Adamopoulos LB_TIMER_UP,
122b3fb8555SGiannis Adamopoulos LB_TIMER_LEFT,
123b3fb8555SGiannis Adamopoulos LB_TIMER_DOWN,
124b3fb8555SGiannis Adamopoulos LB_TIMER_RIGHT
125b3fb8555SGiannis Adamopoulos } TIMER_DIRECTION;
126b3fb8555SGiannis Adamopoulos
127b3fb8555SGiannis Adamopoulos static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
128b3fb8555SGiannis Adamopoulos
129b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_GetItemRect( const LB_DESCR *descr, INT index, RECT *rect );
130b3fb8555SGiannis Adamopoulos
131*0707475fSJustin Miller /*
132*0707475fSJustin Miller For listboxes without LBS_NODATA, an array of LB_ITEMDATA is allocated
133*0707475fSJustin Miller to store the states of each item into descr->u.items.
134*0707475fSJustin Miller
135*0707475fSJustin Miller For single-selection LBS_NODATA listboxes, no storage is allocated,
136*0707475fSJustin Miller and thus descr->u.nodata_items will always be NULL.
137*0707475fSJustin Miller
138*0707475fSJustin Miller For multi-selection LBS_NODATA listboxes, one byte per item is stored
139*0707475fSJustin Miller for the item's selection state into descr->u.nodata_items.
140*0707475fSJustin Miller */
get_sizeof_item(const LB_DESCR * descr)141*0707475fSJustin Miller static size_t get_sizeof_item( const LB_DESCR *descr )
142*0707475fSJustin Miller {
143*0707475fSJustin Miller return (descr->style & LBS_NODATA) ? sizeof(BYTE) : sizeof(LB_ITEMDATA);
144*0707475fSJustin Miller }
145*0707475fSJustin Miller
resize_storage(LB_DESCR * descr,UINT items_size)146*0707475fSJustin Miller static BOOL resize_storage(LB_DESCR *descr, UINT items_size)
147*0707475fSJustin Miller {
148*0707475fSJustin Miller LB_ITEMDATA *items;
149*0707475fSJustin Miller
150*0707475fSJustin Miller if (items_size > descr->items_size ||
151*0707475fSJustin Miller items_size + LB_ARRAY_GRANULARITY * 2 < descr->items_size)
152*0707475fSJustin Miller {
153*0707475fSJustin Miller items_size = (items_size + LB_ARRAY_GRANULARITY - 1) & ~(LB_ARRAY_GRANULARITY - 1);
154*0707475fSJustin Miller if ((descr->style & (LBS_NODATA | LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != LBS_NODATA)
155*0707475fSJustin Miller {
156*0707475fSJustin Miller items = heap_realloc(descr->u.items, items_size * get_sizeof_item(descr));
157*0707475fSJustin Miller if (!items)
158*0707475fSJustin Miller {
159*0707475fSJustin Miller SEND_NOTIFICATION(descr, LBN_ERRSPACE);
160*0707475fSJustin Miller return FALSE;
161*0707475fSJustin Miller }
162*0707475fSJustin Miller descr->u.items = items;
163*0707475fSJustin Miller }
164*0707475fSJustin Miller descr->items_size = items_size;
165*0707475fSJustin Miller }
166*0707475fSJustin Miller
167*0707475fSJustin Miller if ((descr->style & LBS_NODATA) && descr->u.nodata_items && items_size > descr->nb_items)
168*0707475fSJustin Miller {
169*0707475fSJustin Miller memset(descr->u.nodata_items + descr->nb_items, 0,
170*0707475fSJustin Miller (items_size - descr->nb_items) * get_sizeof_item(descr));
171*0707475fSJustin Miller }
172*0707475fSJustin Miller return TRUE;
173*0707475fSJustin Miller }
174*0707475fSJustin Miller
get_item_data(const LB_DESCR * descr,UINT index)175*0707475fSJustin Miller static ULONG_PTR get_item_data( const LB_DESCR *descr, UINT index )
176*0707475fSJustin Miller {
177*0707475fSJustin Miller return (descr->style & LBS_NODATA) ? 0 : descr->u.items[index].data;
178*0707475fSJustin Miller }
179*0707475fSJustin Miller
set_item_data(LB_DESCR * descr,UINT index,ULONG_PTR data)180*0707475fSJustin Miller static void set_item_data( LB_DESCR *descr, UINT index, ULONG_PTR data )
181*0707475fSJustin Miller {
182*0707475fSJustin Miller if (!(descr->style & LBS_NODATA)) descr->u.items[index].data = data;
183*0707475fSJustin Miller }
184*0707475fSJustin Miller
get_item_string(const LB_DESCR * descr,UINT index)185*0707475fSJustin Miller static WCHAR *get_item_string( const LB_DESCR *descr, UINT index )
186*0707475fSJustin Miller {
187*0707475fSJustin Miller return HAS_STRINGS(descr) ? descr->u.items[index].str : NULL;
188*0707475fSJustin Miller }
189*0707475fSJustin Miller
set_item_string(const LB_DESCR * descr,UINT index,WCHAR * string)190*0707475fSJustin Miller static void set_item_string( const LB_DESCR *descr, UINT index, WCHAR *string )
191*0707475fSJustin Miller {
192*0707475fSJustin Miller if (!(descr->style & LBS_NODATA)) descr->u.items[index].str = string;
193*0707475fSJustin Miller }
194*0707475fSJustin Miller
get_item_height(const LB_DESCR * descr,UINT index)195*0707475fSJustin Miller static UINT get_item_height( const LB_DESCR *descr, UINT index )
196*0707475fSJustin Miller {
197*0707475fSJustin Miller return (descr->style & LBS_NODATA) ? 0 : descr->u.items[index].height;
198*0707475fSJustin Miller }
199*0707475fSJustin Miller
set_item_height(LB_DESCR * descr,UINT index,UINT height)200*0707475fSJustin Miller static void set_item_height( LB_DESCR *descr, UINT index, UINT height )
201*0707475fSJustin Miller {
202*0707475fSJustin Miller if (!(descr->style & LBS_NODATA)) descr->u.items[index].height = height;
203*0707475fSJustin Miller }
204*0707475fSJustin Miller
is_item_selected(const LB_DESCR * descr,UINT index)205*0707475fSJustin Miller static BOOL is_item_selected( const LB_DESCR *descr, UINT index )
206*0707475fSJustin Miller {
207*0707475fSJustin Miller if (!(descr->style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)))
208*0707475fSJustin Miller return index == descr->selected_item;
209*0707475fSJustin Miller if (descr->style & LBS_NODATA)
210*0707475fSJustin Miller return descr->u.nodata_items[index];
211*0707475fSJustin Miller else
212*0707475fSJustin Miller return descr->u.items[index].selected;
213*0707475fSJustin Miller }
214*0707475fSJustin Miller
set_item_selected_state(LB_DESCR * descr,UINT index,BOOL state)215*0707475fSJustin Miller static void set_item_selected_state(LB_DESCR *descr, UINT index, BOOL state)
216*0707475fSJustin Miller {
217*0707475fSJustin Miller if (descr->style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
218*0707475fSJustin Miller {
219*0707475fSJustin Miller if (descr->style & LBS_NODATA)
220*0707475fSJustin Miller descr->u.nodata_items[index] = state;
221*0707475fSJustin Miller else
222*0707475fSJustin Miller descr->u.items[index].selected = state;
223*0707475fSJustin Miller }
224*0707475fSJustin Miller }
225*0707475fSJustin Miller
insert_item_data(LB_DESCR * descr,UINT index)226*0707475fSJustin Miller static void insert_item_data(LB_DESCR *descr, UINT index)
227*0707475fSJustin Miller {
228*0707475fSJustin Miller size_t size = get_sizeof_item(descr);
229*0707475fSJustin Miller BYTE *p = descr->u.nodata_items + index * size;
230*0707475fSJustin Miller
231*0707475fSJustin Miller if (!descr->u.items) return;
232*0707475fSJustin Miller
233*0707475fSJustin Miller if (index < descr->nb_items)
234*0707475fSJustin Miller memmove(p + size, p, (descr->nb_items - index) * size);
235*0707475fSJustin Miller }
236*0707475fSJustin Miller
remove_item_data(LB_DESCR * descr,UINT index)237*0707475fSJustin Miller static void remove_item_data(LB_DESCR *descr, UINT index)
238*0707475fSJustin Miller {
239*0707475fSJustin Miller size_t size = get_sizeof_item(descr);
240*0707475fSJustin Miller BYTE *p = descr->u.nodata_items + index * size;
241*0707475fSJustin Miller
242*0707475fSJustin Miller if (!descr->u.items) return;
243*0707475fSJustin Miller
244*0707475fSJustin Miller if (index < descr->nb_items)
245*0707475fSJustin Miller memmove(p, p + size, (descr->nb_items - index) * size);
246*0707475fSJustin Miller }
247*0707475fSJustin Miller
248b3fb8555SGiannis Adamopoulos /***********************************************************************
249b3fb8555SGiannis Adamopoulos * LISTBOX_GetCurrentPageSize
250b3fb8555SGiannis Adamopoulos *
251b3fb8555SGiannis Adamopoulos * Return the current page size
252b3fb8555SGiannis Adamopoulos */
LISTBOX_GetCurrentPageSize(const LB_DESCR * descr)253b3fb8555SGiannis Adamopoulos static INT LISTBOX_GetCurrentPageSize( const LB_DESCR *descr )
254b3fb8555SGiannis Adamopoulos {
255b3fb8555SGiannis Adamopoulos INT i, height;
256b3fb8555SGiannis Adamopoulos if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size;
257b3fb8555SGiannis Adamopoulos for (i = descr->top_item, height = 0; i < descr->nb_items; i++)
258b3fb8555SGiannis Adamopoulos {
259*0707475fSJustin Miller if ((height += get_item_height(descr, i)) > descr->height) break;
260b3fb8555SGiannis Adamopoulos }
261b3fb8555SGiannis Adamopoulos if (i == descr->top_item) return 1;
262b3fb8555SGiannis Adamopoulos else return i - descr->top_item;
263b3fb8555SGiannis Adamopoulos }
264b3fb8555SGiannis Adamopoulos
265b3fb8555SGiannis Adamopoulos
266b3fb8555SGiannis Adamopoulos /***********************************************************************
267b3fb8555SGiannis Adamopoulos * LISTBOX_GetMaxTopIndex
268b3fb8555SGiannis Adamopoulos *
269b3fb8555SGiannis Adamopoulos * Return the maximum possible index for the top of the listbox.
270b3fb8555SGiannis Adamopoulos */
LISTBOX_GetMaxTopIndex(const LB_DESCR * descr)271b3fb8555SGiannis Adamopoulos static INT LISTBOX_GetMaxTopIndex( const LB_DESCR *descr )
272b3fb8555SGiannis Adamopoulos {
273b3fb8555SGiannis Adamopoulos INT max, page;
274b3fb8555SGiannis Adamopoulos
275b3fb8555SGiannis Adamopoulos if (descr->style & LBS_OWNERDRAWVARIABLE)
276b3fb8555SGiannis Adamopoulos {
277b3fb8555SGiannis Adamopoulos page = descr->height;
278b3fb8555SGiannis Adamopoulos for (max = descr->nb_items - 1; max >= 0; max--)
279*0707475fSJustin Miller if ((page -= get_item_height(descr, max)) < 0) break;
280b3fb8555SGiannis Adamopoulos if (max < descr->nb_items - 1) max++;
281b3fb8555SGiannis Adamopoulos }
282b3fb8555SGiannis Adamopoulos else if (descr->style & LBS_MULTICOLUMN)
283b3fb8555SGiannis Adamopoulos {
284b3fb8555SGiannis Adamopoulos if ((page = descr->width / descr->column_width) < 1) page = 1;
285b3fb8555SGiannis Adamopoulos max = (descr->nb_items + descr->page_size - 1) / descr->page_size;
286b3fb8555SGiannis Adamopoulos max = (max - page) * descr->page_size;
287b3fb8555SGiannis Adamopoulos }
288b3fb8555SGiannis Adamopoulos else
289b3fb8555SGiannis Adamopoulos {
290b3fb8555SGiannis Adamopoulos max = descr->nb_items - descr->page_size;
291b3fb8555SGiannis Adamopoulos }
292b3fb8555SGiannis Adamopoulos if (max < 0) max = 0;
293b3fb8555SGiannis Adamopoulos return max;
294b3fb8555SGiannis Adamopoulos }
295b3fb8555SGiannis Adamopoulos
296b3fb8555SGiannis Adamopoulos
297b3fb8555SGiannis Adamopoulos /***********************************************************************
298b3fb8555SGiannis Adamopoulos * LISTBOX_UpdateScroll
299b3fb8555SGiannis Adamopoulos *
300b3fb8555SGiannis Adamopoulos * Update the scrollbars. Should be called whenever the content
301b3fb8555SGiannis Adamopoulos * of the listbox changes.
302b3fb8555SGiannis Adamopoulos */
LISTBOX_UpdateScroll(LB_DESCR * descr)303b3fb8555SGiannis Adamopoulos static void LISTBOX_UpdateScroll( LB_DESCR *descr )
304b3fb8555SGiannis Adamopoulos {
305b3fb8555SGiannis Adamopoulos SCROLLINFO info;
306b3fb8555SGiannis Adamopoulos
307b3fb8555SGiannis Adamopoulos /* Check the listbox scroll bar flags individually before we call
308b3fb8555SGiannis Adamopoulos SetScrollInfo otherwise when the listbox style is WS_HSCROLL and
309b3fb8555SGiannis Adamopoulos no WS_VSCROLL, we end up with an uninitialized, visible horizontal
310b3fb8555SGiannis Adamopoulos scroll bar when we do not need one.
311b3fb8555SGiannis Adamopoulos if (!(descr->style & WS_VSCROLL)) return;
312b3fb8555SGiannis Adamopoulos */
313b3fb8555SGiannis Adamopoulos
314b3fb8555SGiannis Adamopoulos /* It is important that we check descr->style, and not wnd->dwStyle,
315b3fb8555SGiannis Adamopoulos for WS_VSCROLL, as the former is exactly the one passed in
316b3fb8555SGiannis Adamopoulos argument to CreateWindow.
317b3fb8555SGiannis Adamopoulos In Windows (and from now on in Wine :) a listbox created
318b3fb8555SGiannis Adamopoulos with such a style (no WS_SCROLL) does not update
319b3fb8555SGiannis Adamopoulos the scrollbar with listbox-related data, thus letting
320b3fb8555SGiannis Adamopoulos the programmer use it for his/her own purposes. */
321b3fb8555SGiannis Adamopoulos
322b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOREDRAW) return;
323b3fb8555SGiannis Adamopoulos info.cbSize = sizeof(info);
324b3fb8555SGiannis Adamopoulos
325b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
326b3fb8555SGiannis Adamopoulos {
327b3fb8555SGiannis Adamopoulos info.nMin = 0;
328b3fb8555SGiannis Adamopoulos info.nMax = (descr->nb_items - 1) / descr->page_size;
329b3fb8555SGiannis Adamopoulos info.nPos = descr->top_item / descr->page_size;
330b3fb8555SGiannis Adamopoulos info.nPage = descr->width / descr->column_width;
331b3fb8555SGiannis Adamopoulos if (info.nPage < 1) info.nPage = 1;
332b3fb8555SGiannis Adamopoulos info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
333b3fb8555SGiannis Adamopoulos if (descr->style & LBS_DISABLENOSCROLL)
334b3fb8555SGiannis Adamopoulos info.fMask |= SIF_DISABLENOSCROLL;
335b3fb8555SGiannis Adamopoulos if (descr->style & WS_HSCROLL)
336b3fb8555SGiannis Adamopoulos SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
337b3fb8555SGiannis Adamopoulos info.nMax = 0;
338b3fb8555SGiannis Adamopoulos info.fMask = SIF_RANGE;
339b3fb8555SGiannis Adamopoulos if (descr->style & WS_VSCROLL)
340b3fb8555SGiannis Adamopoulos SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
341b3fb8555SGiannis Adamopoulos }
342b3fb8555SGiannis Adamopoulos else
343b3fb8555SGiannis Adamopoulos {
344b3fb8555SGiannis Adamopoulos info.nMin = 0;
345b3fb8555SGiannis Adamopoulos info.nMax = descr->nb_items - 1;
346b3fb8555SGiannis Adamopoulos info.nPos = descr->top_item;
347b3fb8555SGiannis Adamopoulos info.nPage = LISTBOX_GetCurrentPageSize( descr );
348b3fb8555SGiannis Adamopoulos info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
349b3fb8555SGiannis Adamopoulos if (descr->style & LBS_DISABLENOSCROLL)
350b3fb8555SGiannis Adamopoulos info.fMask |= SIF_DISABLENOSCROLL;
351b3fb8555SGiannis Adamopoulos if (descr->style & WS_VSCROLL)
352b3fb8555SGiannis Adamopoulos SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
353b3fb8555SGiannis Adamopoulos
354b3fb8555SGiannis Adamopoulos if ((descr->style & WS_HSCROLL) && descr->horz_extent)
355b3fb8555SGiannis Adamopoulos {
356b3fb8555SGiannis Adamopoulos info.nPos = descr->horz_pos;
357b3fb8555SGiannis Adamopoulos info.nPage = descr->width;
358b3fb8555SGiannis Adamopoulos info.fMask = SIF_POS | SIF_PAGE;
359b3fb8555SGiannis Adamopoulos if (descr->style & LBS_DISABLENOSCROLL)
360b3fb8555SGiannis Adamopoulos info.fMask |= SIF_DISABLENOSCROLL;
361b3fb8555SGiannis Adamopoulos SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
362b3fb8555SGiannis Adamopoulos }
363b3fb8555SGiannis Adamopoulos else
364b3fb8555SGiannis Adamopoulos {
365b3fb8555SGiannis Adamopoulos if (descr->style & LBS_DISABLENOSCROLL)
366b3fb8555SGiannis Adamopoulos {
367b3fb8555SGiannis Adamopoulos info.nMin = 0;
368b3fb8555SGiannis Adamopoulos info.nMax = 0;
369b3fb8555SGiannis Adamopoulos info.fMask = SIF_RANGE | SIF_DISABLENOSCROLL;
370b3fb8555SGiannis Adamopoulos SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
371b3fb8555SGiannis Adamopoulos }
372b3fb8555SGiannis Adamopoulos else
373b3fb8555SGiannis Adamopoulos {
374b3fb8555SGiannis Adamopoulos ShowScrollBar( descr->self, SB_HORZ, FALSE );
375b3fb8555SGiannis Adamopoulos }
376b3fb8555SGiannis Adamopoulos }
377b3fb8555SGiannis Adamopoulos }
378b3fb8555SGiannis Adamopoulos }
379b3fb8555SGiannis Adamopoulos
380b3fb8555SGiannis Adamopoulos
381b3fb8555SGiannis Adamopoulos /***********************************************************************
382b3fb8555SGiannis Adamopoulos * LISTBOX_SetTopItem
383b3fb8555SGiannis Adamopoulos *
384b3fb8555SGiannis Adamopoulos * Set the top item of the listbox, scrolling up or down if necessary.
385b3fb8555SGiannis Adamopoulos */
LISTBOX_SetTopItem(LB_DESCR * descr,INT index,BOOL scroll)386b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index, BOOL scroll )
387b3fb8555SGiannis Adamopoulos {
388b3fb8555SGiannis Adamopoulos INT max = LISTBOX_GetMaxTopIndex( descr );
389b3fb8555SGiannis Adamopoulos
390b3fb8555SGiannis Adamopoulos TRACE("setting top item %d, scroll %d\n", index, scroll);
391b3fb8555SGiannis Adamopoulos
392b3fb8555SGiannis Adamopoulos if (index > max) index = max;
393b3fb8555SGiannis Adamopoulos if (index < 0) index = 0;
394b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
395b3fb8555SGiannis Adamopoulos if (descr->top_item == index) return LB_OKAY;
396b3fb8555SGiannis Adamopoulos if (scroll)
397b3fb8555SGiannis Adamopoulos {
398*0707475fSJustin Miller INT dx = 0, dy = 0;
399b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
400*0707475fSJustin Miller dx = (descr->top_item - index) / descr->page_size * descr->column_width;
401b3fb8555SGiannis Adamopoulos else if (descr->style & LBS_OWNERDRAWVARIABLE)
402b3fb8555SGiannis Adamopoulos {
403b3fb8555SGiannis Adamopoulos INT i;
404b3fb8555SGiannis Adamopoulos if (index > descr->top_item)
405b3fb8555SGiannis Adamopoulos {
406b3fb8555SGiannis Adamopoulos for (i = index - 1; i >= descr->top_item; i--)
407*0707475fSJustin Miller dy -= get_item_height(descr, i);
408b3fb8555SGiannis Adamopoulos }
409b3fb8555SGiannis Adamopoulos else
410b3fb8555SGiannis Adamopoulos {
411b3fb8555SGiannis Adamopoulos for (i = index; i < descr->top_item; i++)
412*0707475fSJustin Miller dy += get_item_height(descr, i);
413b3fb8555SGiannis Adamopoulos }
414b3fb8555SGiannis Adamopoulos }
415b3fb8555SGiannis Adamopoulos else
416*0707475fSJustin Miller dy = (descr->top_item - index) * descr->item_height;
417b3fb8555SGiannis Adamopoulos
418*0707475fSJustin Miller ScrollWindowEx( descr->self, dx, dy, NULL, NULL, 0, NULL,
419b3fb8555SGiannis Adamopoulos SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
420b3fb8555SGiannis Adamopoulos }
421b3fb8555SGiannis Adamopoulos else
422b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, NULL, TRUE );
423b3fb8555SGiannis Adamopoulos descr->top_item = index;
424b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
425b3fb8555SGiannis Adamopoulos return LB_OKAY;
426b3fb8555SGiannis Adamopoulos }
427b3fb8555SGiannis Adamopoulos
428b3fb8555SGiannis Adamopoulos
429b3fb8555SGiannis Adamopoulos /***********************************************************************
430b3fb8555SGiannis Adamopoulos * LISTBOX_UpdatePage
431b3fb8555SGiannis Adamopoulos *
432b3fb8555SGiannis Adamopoulos * Update the page size. Should be called when the size of
433b3fb8555SGiannis Adamopoulos * the client area or the item height changes.
434b3fb8555SGiannis Adamopoulos */
LISTBOX_UpdatePage(LB_DESCR * descr)435b3fb8555SGiannis Adamopoulos static void LISTBOX_UpdatePage( LB_DESCR *descr )
436b3fb8555SGiannis Adamopoulos {
437b3fb8555SGiannis Adamopoulos INT page_size;
438b3fb8555SGiannis Adamopoulos
439b3fb8555SGiannis Adamopoulos if ((descr->item_height == 0) || (page_size = descr->height / descr->item_height) < 1)
440b3fb8555SGiannis Adamopoulos page_size = 1;
441b3fb8555SGiannis Adamopoulos if (page_size == descr->page_size) return;
442b3fb8555SGiannis Adamopoulos descr->page_size = page_size;
443b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
444b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, NULL, TRUE );
445b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->top_item, FALSE );
446b3fb8555SGiannis Adamopoulos }
447b3fb8555SGiannis Adamopoulos
448b3fb8555SGiannis Adamopoulos
449b3fb8555SGiannis Adamopoulos /***********************************************************************
450b3fb8555SGiannis Adamopoulos * LISTBOX_UpdateSize
451b3fb8555SGiannis Adamopoulos *
452b3fb8555SGiannis Adamopoulos * Update the size of the listbox. Should be called when the size of
453b3fb8555SGiannis Adamopoulos * the client area changes.
454b3fb8555SGiannis Adamopoulos */
LISTBOX_UpdateSize(LB_DESCR * descr)455b3fb8555SGiannis Adamopoulos static void LISTBOX_UpdateSize( LB_DESCR *descr )
456b3fb8555SGiannis Adamopoulos {
457b3fb8555SGiannis Adamopoulos RECT rect;
458b3fb8555SGiannis Adamopoulos
459b3fb8555SGiannis Adamopoulos GetClientRect( descr->self, &rect );
460b3fb8555SGiannis Adamopoulos descr->width = rect.right - rect.left;
461b3fb8555SGiannis Adamopoulos descr->height = rect.bottom - rect.top;
462b3fb8555SGiannis Adamopoulos if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !(descr->style & LBS_OWNERDRAWVARIABLE))
463b3fb8555SGiannis Adamopoulos {
464b3fb8555SGiannis Adamopoulos INT remaining;
465b3fb8555SGiannis Adamopoulos RECT rect;
466b3fb8555SGiannis Adamopoulos
467b3fb8555SGiannis Adamopoulos GetWindowRect( descr->self, &rect );
468b3fb8555SGiannis Adamopoulos if(descr->item_height != 0)
469b3fb8555SGiannis Adamopoulos remaining = descr->height % descr->item_height;
470b3fb8555SGiannis Adamopoulos else
471b3fb8555SGiannis Adamopoulos remaining = 0;
472b3fb8555SGiannis Adamopoulos if ((descr->height > descr->item_height) && remaining)
473b3fb8555SGiannis Adamopoulos {
474b3fb8555SGiannis Adamopoulos TRACE("[%p]: changing height %d -> %d\n",
475b3fb8555SGiannis Adamopoulos descr->self, descr->height, descr->height - remaining );
476b3fb8555SGiannis Adamopoulos SetWindowPos( descr->self, 0, 0, 0, rect.right - rect.left,
477b3fb8555SGiannis Adamopoulos rect.bottom - rect.top - remaining,
478b3fb8555SGiannis Adamopoulos SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
479b3fb8555SGiannis Adamopoulos return;
480b3fb8555SGiannis Adamopoulos }
481b3fb8555SGiannis Adamopoulos }
482b3fb8555SGiannis Adamopoulos TRACE("[%p]: new size = %d,%d\n", descr->self, descr->width, descr->height );
483b3fb8555SGiannis Adamopoulos LISTBOX_UpdatePage( descr );
484b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
485b3fb8555SGiannis Adamopoulos
486b3fb8555SGiannis Adamopoulos /* Invalidate the focused item so it will be repainted correctly */
487b3fb8555SGiannis Adamopoulos if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
488b3fb8555SGiannis Adamopoulos {
489b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, &rect, FALSE );
490b3fb8555SGiannis Adamopoulos }
491b3fb8555SGiannis Adamopoulos }
492b3fb8555SGiannis Adamopoulos
493b3fb8555SGiannis Adamopoulos
494b3fb8555SGiannis Adamopoulos /***********************************************************************
495b3fb8555SGiannis Adamopoulos * LISTBOX_GetItemRect
496b3fb8555SGiannis Adamopoulos *
497b3fb8555SGiannis Adamopoulos * Get the rectangle enclosing an item, in listbox client coordinates.
498b3fb8555SGiannis Adamopoulos * Return 1 if the rectangle is (partially) visible, 0 if hidden, -1 on error.
499b3fb8555SGiannis Adamopoulos */
LISTBOX_GetItemRect(const LB_DESCR * descr,INT index,RECT * rect)500b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_GetItemRect( const LB_DESCR *descr, INT index, RECT *rect )
501b3fb8555SGiannis Adamopoulos {
502b3fb8555SGiannis Adamopoulos /* Index <= 0 is legal even on empty listboxes */
503b3fb8555SGiannis Adamopoulos if (index && (index >= descr->nb_items))
504b3fb8555SGiannis Adamopoulos {
505b3fb8555SGiannis Adamopoulos SetRectEmpty(rect);
506b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
507b3fb8555SGiannis Adamopoulos return LB_ERR;
508b3fb8555SGiannis Adamopoulos }
509b3fb8555SGiannis Adamopoulos SetRect( rect, 0, 0, descr->width, descr->height );
510b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
511b3fb8555SGiannis Adamopoulos {
512b3fb8555SGiannis Adamopoulos INT col = (index / descr->page_size) -
513b3fb8555SGiannis Adamopoulos (descr->top_item / descr->page_size);
514b3fb8555SGiannis Adamopoulos rect->left += col * descr->column_width;
515b3fb8555SGiannis Adamopoulos rect->right = rect->left + descr->column_width;
516b3fb8555SGiannis Adamopoulos rect->top += (index % descr->page_size) * descr->item_height;
517b3fb8555SGiannis Adamopoulos rect->bottom = rect->top + descr->item_height;
518b3fb8555SGiannis Adamopoulos }
519b3fb8555SGiannis Adamopoulos else if (descr->style & LBS_OWNERDRAWVARIABLE)
520b3fb8555SGiannis Adamopoulos {
521b3fb8555SGiannis Adamopoulos INT i;
522b3fb8555SGiannis Adamopoulos rect->right += descr->horz_pos;
523b3fb8555SGiannis Adamopoulos if ((index >= 0) && (index < descr->nb_items))
524b3fb8555SGiannis Adamopoulos {
525b3fb8555SGiannis Adamopoulos if (index < descr->top_item)
526b3fb8555SGiannis Adamopoulos {
527b3fb8555SGiannis Adamopoulos for (i = descr->top_item-1; i >= index; i--)
528*0707475fSJustin Miller rect->top -= get_item_height(descr, i);
529b3fb8555SGiannis Adamopoulos }
530b3fb8555SGiannis Adamopoulos else
531b3fb8555SGiannis Adamopoulos {
532b3fb8555SGiannis Adamopoulos for (i = descr->top_item; i < index; i++)
533*0707475fSJustin Miller rect->top += get_item_height(descr, i);
534b3fb8555SGiannis Adamopoulos }
535*0707475fSJustin Miller rect->bottom = rect->top + get_item_height(descr, index);
536b3fb8555SGiannis Adamopoulos
537b3fb8555SGiannis Adamopoulos }
538b3fb8555SGiannis Adamopoulos }
539b3fb8555SGiannis Adamopoulos else
540b3fb8555SGiannis Adamopoulos {
541b3fb8555SGiannis Adamopoulos rect->top += (index - descr->top_item) * descr->item_height;
542b3fb8555SGiannis Adamopoulos rect->bottom = rect->top + descr->item_height;
543b3fb8555SGiannis Adamopoulos rect->right += descr->horz_pos;
544b3fb8555SGiannis Adamopoulos }
545b3fb8555SGiannis Adamopoulos
546b3fb8555SGiannis Adamopoulos TRACE("item %d, rect %s\n", index, wine_dbgstr_rect(rect));
547b3fb8555SGiannis Adamopoulos
548b3fb8555SGiannis Adamopoulos return ((rect->left < descr->width) && (rect->right > 0) &&
549b3fb8555SGiannis Adamopoulos (rect->top < descr->height) && (rect->bottom > 0));
550b3fb8555SGiannis Adamopoulos }
551b3fb8555SGiannis Adamopoulos
552b3fb8555SGiannis Adamopoulos
553b3fb8555SGiannis Adamopoulos /***********************************************************************
554b3fb8555SGiannis Adamopoulos * LISTBOX_GetItemFromPoint
555b3fb8555SGiannis Adamopoulos *
556b3fb8555SGiannis Adamopoulos * Return the item nearest from point (x,y) (in client coordinates).
557b3fb8555SGiannis Adamopoulos */
LISTBOX_GetItemFromPoint(const LB_DESCR * descr,INT x,INT y)558b3fb8555SGiannis Adamopoulos static INT LISTBOX_GetItemFromPoint( const LB_DESCR *descr, INT x, INT y )
559b3fb8555SGiannis Adamopoulos {
560b3fb8555SGiannis Adamopoulos INT index = descr->top_item;
561b3fb8555SGiannis Adamopoulos
562b3fb8555SGiannis Adamopoulos if (!descr->nb_items) return -1; /* No items */
563b3fb8555SGiannis Adamopoulos if (descr->style & LBS_OWNERDRAWVARIABLE)
564b3fb8555SGiannis Adamopoulos {
565b3fb8555SGiannis Adamopoulos INT pos = 0;
566b3fb8555SGiannis Adamopoulos if (y >= 0)
567b3fb8555SGiannis Adamopoulos {
568b3fb8555SGiannis Adamopoulos while (index < descr->nb_items)
569b3fb8555SGiannis Adamopoulos {
570*0707475fSJustin Miller if ((pos += get_item_height(descr, index)) > y) break;
571b3fb8555SGiannis Adamopoulos index++;
572b3fb8555SGiannis Adamopoulos }
573b3fb8555SGiannis Adamopoulos }
574b3fb8555SGiannis Adamopoulos else
575b3fb8555SGiannis Adamopoulos {
576b3fb8555SGiannis Adamopoulos while (index > 0)
577b3fb8555SGiannis Adamopoulos {
578b3fb8555SGiannis Adamopoulos index--;
579*0707475fSJustin Miller if ((pos -= get_item_height(descr, index)) <= y) break;
580b3fb8555SGiannis Adamopoulos }
581b3fb8555SGiannis Adamopoulos }
582b3fb8555SGiannis Adamopoulos }
583b3fb8555SGiannis Adamopoulos else if (descr->style & LBS_MULTICOLUMN)
584b3fb8555SGiannis Adamopoulos {
585b3fb8555SGiannis Adamopoulos if (y >= descr->item_height * descr->page_size) return -1;
586b3fb8555SGiannis Adamopoulos if (y >= 0) index += y / descr->item_height;
587b3fb8555SGiannis Adamopoulos if (x >= 0) index += (x / descr->column_width) * descr->page_size;
588b3fb8555SGiannis Adamopoulos else index -= (((x + 1) / descr->column_width) - 1) * descr->page_size;
589b3fb8555SGiannis Adamopoulos }
590b3fb8555SGiannis Adamopoulos else
591b3fb8555SGiannis Adamopoulos {
592b3fb8555SGiannis Adamopoulos index += (y / descr->item_height);
593b3fb8555SGiannis Adamopoulos }
594b3fb8555SGiannis Adamopoulos if (index < 0) return 0;
595b3fb8555SGiannis Adamopoulos if (index >= descr->nb_items) return -1;
596b3fb8555SGiannis Adamopoulos return index;
597b3fb8555SGiannis Adamopoulos }
598b3fb8555SGiannis Adamopoulos
599b3fb8555SGiannis Adamopoulos
600b3fb8555SGiannis Adamopoulos /***********************************************************************
601b3fb8555SGiannis Adamopoulos * LISTBOX_PaintItem
602b3fb8555SGiannis Adamopoulos *
603b3fb8555SGiannis Adamopoulos * Paint an item.
604b3fb8555SGiannis Adamopoulos */
LISTBOX_PaintItem(LB_DESCR * descr,HDC hdc,const RECT * rect,INT index,UINT action,BOOL ignoreFocus)605b3fb8555SGiannis Adamopoulos static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
606b3fb8555SGiannis Adamopoulos INT index, UINT action, BOOL ignoreFocus )
607b3fb8555SGiannis Adamopoulos {
608*0707475fSJustin Miller BOOL selected = FALSE, focused;
609*0707475fSJustin Miller WCHAR *item_str = NULL;
610*0707475fSJustin Miller
611*0707475fSJustin Miller if (index < descr->nb_items)
612*0707475fSJustin Miller {
613*0707475fSJustin Miller item_str = get_item_string(descr, index);
614*0707475fSJustin Miller selected = is_item_selected(descr, index);
615*0707475fSJustin Miller }
616*0707475fSJustin Miller
617*0707475fSJustin Miller focused = !ignoreFocus && descr->focus_item == index && descr->caret_on && descr->in_focus;
618b3fb8555SGiannis Adamopoulos
619b3fb8555SGiannis Adamopoulos if (IS_OWNERDRAW(descr))
620b3fb8555SGiannis Adamopoulos {
621b3fb8555SGiannis Adamopoulos DRAWITEMSTRUCT dis;
622b3fb8555SGiannis Adamopoulos RECT r;
623b3fb8555SGiannis Adamopoulos HRGN hrgn;
624b3fb8555SGiannis Adamopoulos
625*0707475fSJustin Miller if (index >= descr->nb_items)
626b3fb8555SGiannis Adamopoulos {
627b3fb8555SGiannis Adamopoulos if (action == ODA_FOCUS)
628b3fb8555SGiannis Adamopoulos DrawFocusRect( hdc, rect );
629b3fb8555SGiannis Adamopoulos else
630b3fb8555SGiannis Adamopoulos ERR("called with an out of bounds index %d(%d) in owner draw, Not good.\n",index,descr->nb_items);
631b3fb8555SGiannis Adamopoulos return;
632b3fb8555SGiannis Adamopoulos }
633b3fb8555SGiannis Adamopoulos
634b3fb8555SGiannis Adamopoulos /* some programs mess with the clipping region when
635b3fb8555SGiannis Adamopoulos drawing the item, *and* restore the previous region
636b3fb8555SGiannis Adamopoulos after they are done, so a region has better to exist
637b3fb8555SGiannis Adamopoulos else everything ends clipped */
638b3fb8555SGiannis Adamopoulos GetClientRect(descr->self, &r);
639b3fb8555SGiannis Adamopoulos hrgn = set_control_clipping( hdc, &r );
640b3fb8555SGiannis Adamopoulos
641b3fb8555SGiannis Adamopoulos dis.CtlType = ODT_LISTBOX;
642b3fb8555SGiannis Adamopoulos dis.CtlID = GetWindowLongPtrW( descr->self, GWLP_ID );
643b3fb8555SGiannis Adamopoulos dis.hwndItem = descr->self;
644b3fb8555SGiannis Adamopoulos dis.itemAction = action;
645b3fb8555SGiannis Adamopoulos dis.hDC = hdc;
646b3fb8555SGiannis Adamopoulos dis.itemID = index;
647b3fb8555SGiannis Adamopoulos dis.itemState = 0;
648*0707475fSJustin Miller if (selected)
649*0707475fSJustin Miller dis.itemState |= ODS_SELECTED;
650*0707475fSJustin Miller if (focused)
651*0707475fSJustin Miller dis.itemState |= ODS_FOCUS;
652b3fb8555SGiannis Adamopoulos if (!IsWindowEnabled(descr->self)) dis.itemState |= ODS_DISABLED;
653*0707475fSJustin Miller dis.itemData = get_item_data(descr, index);
654b3fb8555SGiannis Adamopoulos dis.rcItem = *rect;
655b3fb8555SGiannis Adamopoulos TRACE("[%p]: drawitem %d (%s) action=%02x state=%02x rect=%s\n",
656*0707475fSJustin Miller descr->self, index, debugstr_w(item_str), action,
657b3fb8555SGiannis Adamopoulos dis.itemState, wine_dbgstr_rect(rect) );
658b3fb8555SGiannis Adamopoulos SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
659b3fb8555SGiannis Adamopoulos SelectClipRgn( hdc, hrgn );
660b3fb8555SGiannis Adamopoulos if (hrgn) DeleteObject( hrgn );
661b3fb8555SGiannis Adamopoulos }
662b3fb8555SGiannis Adamopoulos else
663b3fb8555SGiannis Adamopoulos {
664b3fb8555SGiannis Adamopoulos COLORREF oldText = 0, oldBk = 0;
665b3fb8555SGiannis Adamopoulos
666b3fb8555SGiannis Adamopoulos if (action == ODA_FOCUS)
667b3fb8555SGiannis Adamopoulos {
668b3fb8555SGiannis Adamopoulos DrawFocusRect( hdc, rect );
669b3fb8555SGiannis Adamopoulos return;
670b3fb8555SGiannis Adamopoulos }
671*0707475fSJustin Miller if (selected)
672b3fb8555SGiannis Adamopoulos {
673b3fb8555SGiannis Adamopoulos oldBk = SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
674b3fb8555SGiannis Adamopoulos oldText = SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
675b3fb8555SGiannis Adamopoulos }
676b3fb8555SGiannis Adamopoulos
677b3fb8555SGiannis Adamopoulos TRACE("[%p]: painting %d (%s) action=%02x rect=%s\n",
678*0707475fSJustin Miller descr->self, index, debugstr_w(item_str), action,
679b3fb8555SGiannis Adamopoulos wine_dbgstr_rect(rect) );
680*0707475fSJustin Miller if (!item_str)
681b3fb8555SGiannis Adamopoulos ExtTextOutW( hdc, rect->left + 1, rect->top,
682b3fb8555SGiannis Adamopoulos ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
683b3fb8555SGiannis Adamopoulos else if (!(descr->style & LBS_USETABSTOPS))
684b3fb8555SGiannis Adamopoulos ExtTextOutW( hdc, rect->left + 1, rect->top,
685*0707475fSJustin Miller ETO_OPAQUE | ETO_CLIPPED, rect, item_str,
686*0707475fSJustin Miller lstrlenW(item_str), NULL );
687b3fb8555SGiannis Adamopoulos else
688b3fb8555SGiannis Adamopoulos {
689b3fb8555SGiannis Adamopoulos /* Output empty string to paint background in the full width. */
690b3fb8555SGiannis Adamopoulos ExtTextOutW( hdc, rect->left + 1, rect->top,
691b3fb8555SGiannis Adamopoulos ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
692b3fb8555SGiannis Adamopoulos TabbedTextOutW( hdc, rect->left + 1 , rect->top,
693*0707475fSJustin Miller item_str, lstrlenW(item_str),
694b3fb8555SGiannis Adamopoulos descr->nb_tabs, descr->tabs, 0);
695b3fb8555SGiannis Adamopoulos }
696*0707475fSJustin Miller if (selected)
697b3fb8555SGiannis Adamopoulos {
698b3fb8555SGiannis Adamopoulos SetBkColor( hdc, oldBk );
699b3fb8555SGiannis Adamopoulos SetTextColor( hdc, oldText );
700b3fb8555SGiannis Adamopoulos }
701*0707475fSJustin Miller if (focused)
702*0707475fSJustin Miller DrawFocusRect( hdc, rect );
703b3fb8555SGiannis Adamopoulos }
704b3fb8555SGiannis Adamopoulos }
705b3fb8555SGiannis Adamopoulos
706b3fb8555SGiannis Adamopoulos
707b3fb8555SGiannis Adamopoulos /***********************************************************************
708b3fb8555SGiannis Adamopoulos * LISTBOX_SetRedraw
709b3fb8555SGiannis Adamopoulos *
710b3fb8555SGiannis Adamopoulos * Change the redraw flag.
711b3fb8555SGiannis Adamopoulos */
LISTBOX_SetRedraw(LB_DESCR * descr,BOOL on)712b3fb8555SGiannis Adamopoulos static void LISTBOX_SetRedraw( LB_DESCR *descr, BOOL on )
713b3fb8555SGiannis Adamopoulos {
714b3fb8555SGiannis Adamopoulos if (on)
715b3fb8555SGiannis Adamopoulos {
716b3fb8555SGiannis Adamopoulos if (!(descr->style & LBS_NOREDRAW)) return;
717b3fb8555SGiannis Adamopoulos descr->style &= ~LBS_NOREDRAW;
718b3fb8555SGiannis Adamopoulos if (descr->style & LBS_DISPLAYCHANGED)
719b3fb8555SGiannis Adamopoulos { /* page was changed while setredraw false, refresh automatically */
720b3fb8555SGiannis Adamopoulos InvalidateRect(descr->self, NULL, TRUE);
721b3fb8555SGiannis Adamopoulos if ((descr->top_item + descr->page_size) > descr->nb_items)
722b3fb8555SGiannis Adamopoulos { /* reset top of page if less than number of items/page */
723b3fb8555SGiannis Adamopoulos descr->top_item = descr->nb_items - descr->page_size;
724b3fb8555SGiannis Adamopoulos if (descr->top_item < 0) descr->top_item = 0;
725b3fb8555SGiannis Adamopoulos }
726b3fb8555SGiannis Adamopoulos descr->style &= ~LBS_DISPLAYCHANGED;
727b3fb8555SGiannis Adamopoulos }
728b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
729b3fb8555SGiannis Adamopoulos }
730b3fb8555SGiannis Adamopoulos else descr->style |= LBS_NOREDRAW;
731b3fb8555SGiannis Adamopoulos }
732b3fb8555SGiannis Adamopoulos
733b3fb8555SGiannis Adamopoulos
734b3fb8555SGiannis Adamopoulos /***********************************************************************
735b3fb8555SGiannis Adamopoulos * LISTBOX_RepaintItem
736b3fb8555SGiannis Adamopoulos *
737b3fb8555SGiannis Adamopoulos * Repaint a single item synchronously.
738b3fb8555SGiannis Adamopoulos */
LISTBOX_RepaintItem(LB_DESCR * descr,INT index,UINT action)739b3fb8555SGiannis Adamopoulos static void LISTBOX_RepaintItem( LB_DESCR *descr, INT index, UINT action )
740b3fb8555SGiannis Adamopoulos {
741b3fb8555SGiannis Adamopoulos HDC hdc;
742b3fb8555SGiannis Adamopoulos RECT rect;
743b3fb8555SGiannis Adamopoulos HFONT oldFont = 0;
744b3fb8555SGiannis Adamopoulos HBRUSH hbrush, oldBrush = 0;
745b3fb8555SGiannis Adamopoulos
746b3fb8555SGiannis Adamopoulos /* Do not repaint the item if the item is not visible */
747b3fb8555SGiannis Adamopoulos if (!IsWindowVisible(descr->self)) return;
748b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOREDRAW)
749b3fb8555SGiannis Adamopoulos {
750b3fb8555SGiannis Adamopoulos descr->style |= LBS_DISPLAYCHANGED;
751b3fb8555SGiannis Adamopoulos return;
752b3fb8555SGiannis Adamopoulos }
753b3fb8555SGiannis Adamopoulos if (LISTBOX_GetItemRect( descr, index, &rect ) != 1) return;
754b3fb8555SGiannis Adamopoulos if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
755b3fb8555SGiannis Adamopoulos if (descr->font) oldFont = SelectObject( hdc, descr->font );
756b3fb8555SGiannis Adamopoulos hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
757b3fb8555SGiannis Adamopoulos (WPARAM)hdc, (LPARAM)descr->self );
758b3fb8555SGiannis Adamopoulos if (hbrush) oldBrush = SelectObject( hdc, hbrush );
759b3fb8555SGiannis Adamopoulos if (!IsWindowEnabled(descr->self))
760b3fb8555SGiannis Adamopoulos SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
761b3fb8555SGiannis Adamopoulos SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
762b3fb8555SGiannis Adamopoulos LISTBOX_PaintItem( descr, hdc, &rect, index, action, TRUE );
763b3fb8555SGiannis Adamopoulos if (oldFont) SelectObject( hdc, oldFont );
764b3fb8555SGiannis Adamopoulos if (oldBrush) SelectObject( hdc, oldBrush );
765b3fb8555SGiannis Adamopoulos ReleaseDC( descr->self, hdc );
766b3fb8555SGiannis Adamopoulos }
767b3fb8555SGiannis Adamopoulos
768b3fb8555SGiannis Adamopoulos
769b3fb8555SGiannis Adamopoulos /***********************************************************************
770b3fb8555SGiannis Adamopoulos * LISTBOX_DrawFocusRect
771b3fb8555SGiannis Adamopoulos */
LISTBOX_DrawFocusRect(LB_DESCR * descr,BOOL on)772b3fb8555SGiannis Adamopoulos static void LISTBOX_DrawFocusRect( LB_DESCR *descr, BOOL on )
773b3fb8555SGiannis Adamopoulos {
774b3fb8555SGiannis Adamopoulos HDC hdc;
775b3fb8555SGiannis Adamopoulos RECT rect;
776b3fb8555SGiannis Adamopoulos HFONT oldFont = 0;
777b3fb8555SGiannis Adamopoulos
778b3fb8555SGiannis Adamopoulos /* Do not repaint the item if the item is not visible */
779b3fb8555SGiannis Adamopoulos if (!IsWindowVisible(descr->self)) return;
780b3fb8555SGiannis Adamopoulos
781b3fb8555SGiannis Adamopoulos if (descr->focus_item == -1) return;
782b3fb8555SGiannis Adamopoulos if (!descr->caret_on || !descr->in_focus) return;
783b3fb8555SGiannis Adamopoulos
784b3fb8555SGiannis Adamopoulos if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) != 1) return;
785b3fb8555SGiannis Adamopoulos if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
786b3fb8555SGiannis Adamopoulos if (descr->font) oldFont = SelectObject( hdc, descr->font );
787b3fb8555SGiannis Adamopoulos if (!IsWindowEnabled(descr->self))
788b3fb8555SGiannis Adamopoulos SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
789b3fb8555SGiannis Adamopoulos SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
790b3fb8555SGiannis Adamopoulos LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, !on );
791b3fb8555SGiannis Adamopoulos if (oldFont) SelectObject( hdc, oldFont );
792b3fb8555SGiannis Adamopoulos ReleaseDC( descr->self, hdc );
793b3fb8555SGiannis Adamopoulos }
794b3fb8555SGiannis Adamopoulos
795b3fb8555SGiannis Adamopoulos
796b3fb8555SGiannis Adamopoulos /***********************************************************************
797b3fb8555SGiannis Adamopoulos * LISTBOX_InitStorage
798b3fb8555SGiannis Adamopoulos */
LISTBOX_InitStorage(LB_DESCR * descr,INT nb_items)799b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_InitStorage( LB_DESCR *descr, INT nb_items )
800b3fb8555SGiannis Adamopoulos {
801*0707475fSJustin Miller UINT new_size = descr->nb_items + nb_items;
802b3fb8555SGiannis Adamopoulos
803*0707475fSJustin Miller if (new_size > descr->items_size && !resize_storage(descr, new_size))
804b3fb8555SGiannis Adamopoulos return LB_ERRSPACE;
805*0707475fSJustin Miller return descr->items_size;
806b3fb8555SGiannis Adamopoulos }
807b3fb8555SGiannis Adamopoulos
808b3fb8555SGiannis Adamopoulos
809b3fb8555SGiannis Adamopoulos /***********************************************************************
810b3fb8555SGiannis Adamopoulos * LISTBOX_SetTabStops
811b3fb8555SGiannis Adamopoulos */
LISTBOX_SetTabStops(LB_DESCR * descr,INT count,LPINT tabs)812b3fb8555SGiannis Adamopoulos static BOOL LISTBOX_SetTabStops( LB_DESCR *descr, INT count, LPINT tabs )
813b3fb8555SGiannis Adamopoulos {
814b3fb8555SGiannis Adamopoulos INT i;
815b3fb8555SGiannis Adamopoulos
816b3fb8555SGiannis Adamopoulos if (!(descr->style & LBS_USETABSTOPS))
817b3fb8555SGiannis Adamopoulos {
818b3fb8555SGiannis Adamopoulos SetLastError(ERROR_LB_WITHOUT_TABSTOPS);
819b3fb8555SGiannis Adamopoulos return FALSE;
820b3fb8555SGiannis Adamopoulos }
821b3fb8555SGiannis Adamopoulos
822b3fb8555SGiannis Adamopoulos HeapFree( GetProcessHeap(), 0, descr->tabs );
823b3fb8555SGiannis Adamopoulos if (!(descr->nb_tabs = count))
824b3fb8555SGiannis Adamopoulos {
825b3fb8555SGiannis Adamopoulos descr->tabs = NULL;
826b3fb8555SGiannis Adamopoulos return TRUE;
827b3fb8555SGiannis Adamopoulos }
828b3fb8555SGiannis Adamopoulos if (!(descr->tabs = HeapAlloc( GetProcessHeap(), 0,
829b3fb8555SGiannis Adamopoulos descr->nb_tabs * sizeof(INT) )))
830b3fb8555SGiannis Adamopoulos return FALSE;
831b3fb8555SGiannis Adamopoulos memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
832b3fb8555SGiannis Adamopoulos
833b3fb8555SGiannis Adamopoulos /* convert into "dialog units"*/
834b3fb8555SGiannis Adamopoulos for (i = 0; i < descr->nb_tabs; i++)
835b3fb8555SGiannis Adamopoulos descr->tabs[i] = MulDiv(descr->tabs[i], descr->avg_char_width, 4);
836b3fb8555SGiannis Adamopoulos
837b3fb8555SGiannis Adamopoulos return TRUE;
838b3fb8555SGiannis Adamopoulos }
839b3fb8555SGiannis Adamopoulos
840b3fb8555SGiannis Adamopoulos
841b3fb8555SGiannis Adamopoulos /***********************************************************************
842b3fb8555SGiannis Adamopoulos * LISTBOX_GetText
843b3fb8555SGiannis Adamopoulos */
LISTBOX_GetText(LB_DESCR * descr,INT index,LPWSTR buffer,BOOL unicode)844b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_GetText( LB_DESCR *descr, INT index, LPWSTR buffer, BOOL unicode )
845b3fb8555SGiannis Adamopoulos {
846b3fb8555SGiannis Adamopoulos DWORD len;
847b3fb8555SGiannis Adamopoulos
848b3fb8555SGiannis Adamopoulos if ((index < 0) || (index >= descr->nb_items))
849b3fb8555SGiannis Adamopoulos {
850b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
851b3fb8555SGiannis Adamopoulos return LB_ERR;
852b3fb8555SGiannis Adamopoulos }
853b3fb8555SGiannis Adamopoulos
854b3fb8555SGiannis Adamopoulos if (HAS_STRINGS(descr))
855b3fb8555SGiannis Adamopoulos {
856*0707475fSJustin Miller WCHAR *str = get_item_string(descr, index);
857b3fb8555SGiannis Adamopoulos
858*0707475fSJustin Miller if (!buffer)
859*0707475fSJustin Miller return lstrlenW(str);
860*0707475fSJustin Miller
861*0707475fSJustin Miller TRACE("index %d (0x%04x) %s\n", index, index, debugstr_w(str));
862b3fb8555SGiannis Adamopoulos
863b3fb8555SGiannis Adamopoulos __TRY /* hide a Delphi bug that passes a read-only buffer */
864b3fb8555SGiannis Adamopoulos {
865*0707475fSJustin Miller lstrcpyW(buffer, str);
866*0707475fSJustin Miller len = lstrlenW(buffer);
867b3fb8555SGiannis Adamopoulos }
868b3fb8555SGiannis Adamopoulos __EXCEPT_PAGE_FAULT
869b3fb8555SGiannis Adamopoulos {
870b3fb8555SGiannis Adamopoulos WARN( "got an invalid buffer (Delphi bug?)\n" );
871b3fb8555SGiannis Adamopoulos SetLastError( ERROR_INVALID_PARAMETER );
872b3fb8555SGiannis Adamopoulos return LB_ERR;
873b3fb8555SGiannis Adamopoulos }
874b3fb8555SGiannis Adamopoulos __ENDTRY
875b3fb8555SGiannis Adamopoulos } else
876b3fb8555SGiannis Adamopoulos {
877b3fb8555SGiannis Adamopoulos if (buffer)
878*0707475fSJustin Miller *((ULONG_PTR *)buffer) = get_item_data(descr, index);
879*0707475fSJustin Miller len = sizeof(ULONG_PTR);
880b3fb8555SGiannis Adamopoulos }
881b3fb8555SGiannis Adamopoulos return len;
882b3fb8555SGiannis Adamopoulos }
883b3fb8555SGiannis Adamopoulos
LISTBOX_lstrcmpiW(LCID lcid,LPCWSTR str1,LPCWSTR str2)884b3fb8555SGiannis Adamopoulos static inline INT LISTBOX_lstrcmpiW( LCID lcid, LPCWSTR str1, LPCWSTR str2 )
885b3fb8555SGiannis Adamopoulos {
886b3fb8555SGiannis Adamopoulos INT ret = CompareStringW( lcid, NORM_IGNORECASE, str1, -1, str2, -1 );
887b3fb8555SGiannis Adamopoulos if (ret == CSTR_LESS_THAN)
888b3fb8555SGiannis Adamopoulos return -1;
889b3fb8555SGiannis Adamopoulos if (ret == CSTR_EQUAL)
890b3fb8555SGiannis Adamopoulos return 0;
891b3fb8555SGiannis Adamopoulos if (ret == CSTR_GREATER_THAN)
892b3fb8555SGiannis Adamopoulos return 1;
893b3fb8555SGiannis Adamopoulos return -1;
894b3fb8555SGiannis Adamopoulos }
895b3fb8555SGiannis Adamopoulos
896b3fb8555SGiannis Adamopoulos /***********************************************************************
897b3fb8555SGiannis Adamopoulos * LISTBOX_FindStringPos
898b3fb8555SGiannis Adamopoulos *
899b3fb8555SGiannis Adamopoulos * Find the nearest string located before a given string in sort order.
900b3fb8555SGiannis Adamopoulos * If 'exact' is TRUE, return an error if we don't get an exact match.
901b3fb8555SGiannis Adamopoulos */
LISTBOX_FindStringPos(LB_DESCR * descr,LPCWSTR str,BOOL exact)902b3fb8555SGiannis Adamopoulos static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact )
903b3fb8555SGiannis Adamopoulos {
904b3fb8555SGiannis Adamopoulos INT index, min, max, res;
905b3fb8555SGiannis Adamopoulos
906*0707475fSJustin Miller if (!descr->nb_items || !(descr->style & LBS_SORT)) return -1; /* Add it at the end */
907*0707475fSJustin Miller
908b3fb8555SGiannis Adamopoulos min = 0;
909*0707475fSJustin Miller max = descr->nb_items - 1;
910*0707475fSJustin Miller while (min <= max)
911b3fb8555SGiannis Adamopoulos {
912b3fb8555SGiannis Adamopoulos index = (min + max) / 2;
913b3fb8555SGiannis Adamopoulos if (HAS_STRINGS(descr))
914*0707475fSJustin Miller res = LISTBOX_lstrcmpiW( descr->locale, get_item_string(descr, index), str );
915b3fb8555SGiannis Adamopoulos else
916b3fb8555SGiannis Adamopoulos {
917b3fb8555SGiannis Adamopoulos COMPAREITEMSTRUCT cis;
918b3fb8555SGiannis Adamopoulos UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
919b3fb8555SGiannis Adamopoulos
920b3fb8555SGiannis Adamopoulos cis.CtlType = ODT_LISTBOX;
921b3fb8555SGiannis Adamopoulos cis.CtlID = id;
922b3fb8555SGiannis Adamopoulos cis.hwndItem = descr->self;
923b3fb8555SGiannis Adamopoulos /* note that some application (MetaStock) expects the second item
924b3fb8555SGiannis Adamopoulos * to be in the listbox */
925*0707475fSJustin Miller cis.itemID1 = index;
926*0707475fSJustin Miller cis.itemData1 = get_item_data(descr, index);
927*0707475fSJustin Miller cis.itemID2 = -1;
928*0707475fSJustin Miller cis.itemData2 = (ULONG_PTR)str;
929b3fb8555SGiannis Adamopoulos cis.dwLocaleId = descr->locale;
930b3fb8555SGiannis Adamopoulos res = SendMessageW( descr->owner, WM_COMPAREITEM, id, (LPARAM)&cis );
931b3fb8555SGiannis Adamopoulos }
932b3fb8555SGiannis Adamopoulos if (!res) return index;
933*0707475fSJustin Miller if (res > 0) max = index - 1;
934b3fb8555SGiannis Adamopoulos else min = index + 1;
935b3fb8555SGiannis Adamopoulos }
936*0707475fSJustin Miller return exact ? -1 : min;
937b3fb8555SGiannis Adamopoulos }
938b3fb8555SGiannis Adamopoulos
939b3fb8555SGiannis Adamopoulos
940b3fb8555SGiannis Adamopoulos /***********************************************************************
941b3fb8555SGiannis Adamopoulos * LISTBOX_FindFileStrPos
942b3fb8555SGiannis Adamopoulos *
943b3fb8555SGiannis Adamopoulos * Find the nearest string located before a given string in directory
944b3fb8555SGiannis Adamopoulos * sort order (i.e. first files, then directories, then drives).
945b3fb8555SGiannis Adamopoulos */
LISTBOX_FindFileStrPos(LB_DESCR * descr,LPCWSTR str)946b3fb8555SGiannis Adamopoulos static INT LISTBOX_FindFileStrPos( LB_DESCR *descr, LPCWSTR str )
947b3fb8555SGiannis Adamopoulos {
948b3fb8555SGiannis Adamopoulos INT min, max, res;
949b3fb8555SGiannis Adamopoulos
950b3fb8555SGiannis Adamopoulos if (!HAS_STRINGS(descr))
951b3fb8555SGiannis Adamopoulos return LISTBOX_FindStringPos( descr, str, FALSE );
952b3fb8555SGiannis Adamopoulos min = 0;
953b3fb8555SGiannis Adamopoulos max = descr->nb_items;
954b3fb8555SGiannis Adamopoulos while (min != max)
955b3fb8555SGiannis Adamopoulos {
956b3fb8555SGiannis Adamopoulos INT index = (min + max) / 2;
957*0707475fSJustin Miller LPCWSTR p = get_item_string(descr, index);
958b3fb8555SGiannis Adamopoulos if (*p == '[') /* drive or directory */
959b3fb8555SGiannis Adamopoulos {
960b3fb8555SGiannis Adamopoulos if (*str != '[') res = -1;
961b3fb8555SGiannis Adamopoulos else if (p[1] == '-') /* drive */
962b3fb8555SGiannis Adamopoulos {
963b3fb8555SGiannis Adamopoulos if (str[1] == '-') res = str[2] - p[2];
964b3fb8555SGiannis Adamopoulos else res = -1;
965b3fb8555SGiannis Adamopoulos }
966b3fb8555SGiannis Adamopoulos else /* directory */
967b3fb8555SGiannis Adamopoulos {
968b3fb8555SGiannis Adamopoulos if (str[1] == '-') res = 1;
969b3fb8555SGiannis Adamopoulos else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
970b3fb8555SGiannis Adamopoulos }
971b3fb8555SGiannis Adamopoulos }
972b3fb8555SGiannis Adamopoulos else /* filename */
973b3fb8555SGiannis Adamopoulos {
974b3fb8555SGiannis Adamopoulos if (*str == '[') res = 1;
975b3fb8555SGiannis Adamopoulos else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
976b3fb8555SGiannis Adamopoulos }
977b3fb8555SGiannis Adamopoulos if (!res) return index;
978b3fb8555SGiannis Adamopoulos if (res < 0) max = index;
979b3fb8555SGiannis Adamopoulos else min = index + 1;
980b3fb8555SGiannis Adamopoulos }
981b3fb8555SGiannis Adamopoulos return max;
982b3fb8555SGiannis Adamopoulos }
983b3fb8555SGiannis Adamopoulos
984b3fb8555SGiannis Adamopoulos
985b3fb8555SGiannis Adamopoulos /***********************************************************************
986b3fb8555SGiannis Adamopoulos * LISTBOX_FindString
987b3fb8555SGiannis Adamopoulos *
988b3fb8555SGiannis Adamopoulos * Find the item beginning with a given string.
989b3fb8555SGiannis Adamopoulos */
LISTBOX_FindString(LB_DESCR * descr,INT start,LPCWSTR str,BOOL exact)990b3fb8555SGiannis Adamopoulos static INT LISTBOX_FindString( LB_DESCR *descr, INT start, LPCWSTR str, BOOL exact )
991b3fb8555SGiannis Adamopoulos {
992*0707475fSJustin Miller INT i, index;
993b3fb8555SGiannis Adamopoulos
994*0707475fSJustin Miller if (descr->style & LBS_NODATA) return LB_ERR;
995*0707475fSJustin Miller
996*0707475fSJustin Miller start++;
997*0707475fSJustin Miller if (start >= descr->nb_items) start = 0;
998b3fb8555SGiannis Adamopoulos if (HAS_STRINGS(descr))
999b3fb8555SGiannis Adamopoulos {
1000b3fb8555SGiannis Adamopoulos if (!str || ! str[0] ) return LB_ERR;
1001b3fb8555SGiannis Adamopoulos if (exact)
1002b3fb8555SGiannis Adamopoulos {
1003*0707475fSJustin Miller for (i = 0, index = start; i < descr->nb_items; i++, index++)
1004*0707475fSJustin Miller {
1005*0707475fSJustin Miller if (index == descr->nb_items) index = 0;
1006*0707475fSJustin Miller if (!LISTBOX_lstrcmpiW(descr->locale, str, get_item_string(descr, index)))
1007*0707475fSJustin Miller return index;
1008*0707475fSJustin Miller }
1009b3fb8555SGiannis Adamopoulos }
1010b3fb8555SGiannis Adamopoulos else
1011b3fb8555SGiannis Adamopoulos {
1012b3fb8555SGiannis Adamopoulos /* Special case for drives and directories: ignore prefix */
1013*0707475fSJustin Miller INT len = lstrlenW(str);
1014*0707475fSJustin Miller WCHAR *item_str;
1015b3fb8555SGiannis Adamopoulos
1016*0707475fSJustin Miller for (i = 0, index = start; i < descr->nb_items; i++, index++)
1017b3fb8555SGiannis Adamopoulos {
1018*0707475fSJustin Miller if (index == descr->nb_items) index = 0;
1019*0707475fSJustin Miller item_str = get_item_string(descr, index);
1020*0707475fSJustin Miller
1021*0707475fSJustin Miller if (!wcsnicmp(str, item_str, len)) return index;
1022*0707475fSJustin Miller if (item_str[0] == '[')
1023b3fb8555SGiannis Adamopoulos {
1024*0707475fSJustin Miller if (!wcsnicmp(str, item_str + 1, len)) return index;
1025*0707475fSJustin Miller if (item_str[1] == '-' && !wcsnicmp(str, item_str + 2, len)) return index;
1026b3fb8555SGiannis Adamopoulos }
1027*0707475fSJustin Miller }
1028b3fb8555SGiannis Adamopoulos }
1029b3fb8555SGiannis Adamopoulos }
1030b3fb8555SGiannis Adamopoulos else
1031b3fb8555SGiannis Adamopoulos {
1032b3fb8555SGiannis Adamopoulos if (exact && (descr->style & LBS_SORT))
1033b3fb8555SGiannis Adamopoulos /* If sorted, use a WM_COMPAREITEM binary search */
1034b3fb8555SGiannis Adamopoulos return LISTBOX_FindStringPos( descr, str, TRUE );
1035b3fb8555SGiannis Adamopoulos
1036b3fb8555SGiannis Adamopoulos /* Otherwise use a linear search */
1037*0707475fSJustin Miller for (i = 0, index = start; i < descr->nb_items; i++, index++)
1038*0707475fSJustin Miller {
1039*0707475fSJustin Miller if (index == descr->nb_items) index = 0;
1040*0707475fSJustin Miller if (get_item_data(descr, index) == (ULONG_PTR)str) return index;
1041*0707475fSJustin Miller }
1042b3fb8555SGiannis Adamopoulos }
1043b3fb8555SGiannis Adamopoulos return LB_ERR;
1044b3fb8555SGiannis Adamopoulos }
1045b3fb8555SGiannis Adamopoulos
1046b3fb8555SGiannis Adamopoulos
1047b3fb8555SGiannis Adamopoulos /***********************************************************************
1048b3fb8555SGiannis Adamopoulos * LISTBOX_GetSelCount
1049b3fb8555SGiannis Adamopoulos */
LISTBOX_GetSelCount(const LB_DESCR * descr)1050b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_GetSelCount( const LB_DESCR *descr )
1051b3fb8555SGiannis Adamopoulos {
1052b3fb8555SGiannis Adamopoulos INT i, count;
1053b3fb8555SGiannis Adamopoulos
1054b3fb8555SGiannis Adamopoulos if (!(descr->style & LBS_MULTIPLESEL) ||
1055b3fb8555SGiannis Adamopoulos (descr->style & LBS_NOSEL))
1056b3fb8555SGiannis Adamopoulos return LB_ERR;
1057*0707475fSJustin Miller for (i = count = 0; i < descr->nb_items; i++)
1058*0707475fSJustin Miller if (is_item_selected(descr, i)) count++;
1059b3fb8555SGiannis Adamopoulos return count;
1060b3fb8555SGiannis Adamopoulos }
1061b3fb8555SGiannis Adamopoulos
1062b3fb8555SGiannis Adamopoulos
1063b3fb8555SGiannis Adamopoulos /***********************************************************************
1064b3fb8555SGiannis Adamopoulos * LISTBOX_GetSelItems
1065b3fb8555SGiannis Adamopoulos */
LISTBOX_GetSelItems(const LB_DESCR * descr,INT max,LPINT array)1066b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_GetSelItems( const LB_DESCR *descr, INT max, LPINT array )
1067b3fb8555SGiannis Adamopoulos {
1068b3fb8555SGiannis Adamopoulos INT i, count;
1069b3fb8555SGiannis Adamopoulos
1070b3fb8555SGiannis Adamopoulos if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
1071*0707475fSJustin Miller for (i = count = 0; (i < descr->nb_items) && (count < max); i++)
1072*0707475fSJustin Miller if (is_item_selected(descr, i)) array[count++] = i;
1073b3fb8555SGiannis Adamopoulos return count;
1074b3fb8555SGiannis Adamopoulos }
1075b3fb8555SGiannis Adamopoulos
1076b3fb8555SGiannis Adamopoulos
1077b3fb8555SGiannis Adamopoulos /***********************************************************************
1078b3fb8555SGiannis Adamopoulos * LISTBOX_Paint
1079b3fb8555SGiannis Adamopoulos */
LISTBOX_Paint(LB_DESCR * descr,HDC hdc)1080b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_Paint( LB_DESCR *descr, HDC hdc )
1081b3fb8555SGiannis Adamopoulos {
1082b3fb8555SGiannis Adamopoulos INT i, col_pos = descr->page_size - 1;
1083b3fb8555SGiannis Adamopoulos RECT rect;
1084b3fb8555SGiannis Adamopoulos RECT focusRect = {-1, -1, -1, -1};
1085b3fb8555SGiannis Adamopoulos HFONT oldFont = 0;
1086b3fb8555SGiannis Adamopoulos HBRUSH hbrush, oldBrush = 0;
1087b3fb8555SGiannis Adamopoulos
1088b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOREDRAW) return 0;
1089b3fb8555SGiannis Adamopoulos
1090b3fb8555SGiannis Adamopoulos SetRect( &rect, 0, 0, descr->width, descr->height );
1091b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
1092b3fb8555SGiannis Adamopoulos rect.right = rect.left + descr->column_width;
1093b3fb8555SGiannis Adamopoulos else if (descr->horz_pos)
1094b3fb8555SGiannis Adamopoulos {
1095b3fb8555SGiannis Adamopoulos SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
1096b3fb8555SGiannis Adamopoulos rect.right += descr->horz_pos;
1097b3fb8555SGiannis Adamopoulos }
1098b3fb8555SGiannis Adamopoulos
1099b3fb8555SGiannis Adamopoulos if (descr->font) oldFont = SelectObject( hdc, descr->font );
1100b3fb8555SGiannis Adamopoulos hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
1101b3fb8555SGiannis Adamopoulos (WPARAM)hdc, (LPARAM)descr->self );
1102b3fb8555SGiannis Adamopoulos if (hbrush) oldBrush = SelectObject( hdc, hbrush );
1103b3fb8555SGiannis Adamopoulos if (!IsWindowEnabled(descr->self)) SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
1104b3fb8555SGiannis Adamopoulos
1105b3fb8555SGiannis Adamopoulos if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
1106b3fb8555SGiannis Adamopoulos (descr->in_focus))
1107b3fb8555SGiannis Adamopoulos {
1108b3fb8555SGiannis Adamopoulos /* Special case for empty listbox: paint focus rect */
1109b3fb8555SGiannis Adamopoulos rect.bottom = rect.top + descr->item_height;
1110b3fb8555SGiannis Adamopoulos ExtTextOutW( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
1111b3fb8555SGiannis Adamopoulos &rect, NULL, 0, NULL );
1112b3fb8555SGiannis Adamopoulos LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, FALSE );
1113b3fb8555SGiannis Adamopoulos rect.top = rect.bottom;
1114b3fb8555SGiannis Adamopoulos }
1115b3fb8555SGiannis Adamopoulos
1116b3fb8555SGiannis Adamopoulos /* Paint all the item, regarding the selection
1117b3fb8555SGiannis Adamopoulos Focus state will be painted after */
1118b3fb8555SGiannis Adamopoulos
1119b3fb8555SGiannis Adamopoulos for (i = descr->top_item; i < descr->nb_items; i++)
1120b3fb8555SGiannis Adamopoulos {
1121b3fb8555SGiannis Adamopoulos if (!(descr->style & LBS_OWNERDRAWVARIABLE))
1122b3fb8555SGiannis Adamopoulos rect.bottom = rect.top + descr->item_height;
1123b3fb8555SGiannis Adamopoulos else
1124*0707475fSJustin Miller rect.bottom = rect.top + get_item_height(descr, i);
1125b3fb8555SGiannis Adamopoulos
1126b3fb8555SGiannis Adamopoulos /* keep the focus rect, to paint the focus item after */
1127b3fb8555SGiannis Adamopoulos if (i == descr->focus_item)
1128b3fb8555SGiannis Adamopoulos focusRect = rect;
1129b3fb8555SGiannis Adamopoulos
1130b3fb8555SGiannis Adamopoulos LISTBOX_PaintItem( descr, hdc, &rect, i, ODA_DRAWENTIRE, TRUE );
1131b3fb8555SGiannis Adamopoulos rect.top = rect.bottom;
1132b3fb8555SGiannis Adamopoulos
1133b3fb8555SGiannis Adamopoulos if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
1134b3fb8555SGiannis Adamopoulos {
1135b3fb8555SGiannis Adamopoulos if (!IS_OWNERDRAW(descr))
1136b3fb8555SGiannis Adamopoulos {
1137b3fb8555SGiannis Adamopoulos /* Clear the bottom of the column */
1138b3fb8555SGiannis Adamopoulos if (rect.top < descr->height)
1139b3fb8555SGiannis Adamopoulos {
1140b3fb8555SGiannis Adamopoulos rect.bottom = descr->height;
1141b3fb8555SGiannis Adamopoulos ExtTextOutW( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
1142b3fb8555SGiannis Adamopoulos &rect, NULL, 0, NULL );
1143b3fb8555SGiannis Adamopoulos }
1144b3fb8555SGiannis Adamopoulos }
1145b3fb8555SGiannis Adamopoulos
1146b3fb8555SGiannis Adamopoulos /* Go to the next column */
1147b3fb8555SGiannis Adamopoulos rect.left += descr->column_width;
1148b3fb8555SGiannis Adamopoulos rect.right += descr->column_width;
1149b3fb8555SGiannis Adamopoulos rect.top = 0;
1150b3fb8555SGiannis Adamopoulos col_pos = descr->page_size - 1;
1151*0707475fSJustin Miller if (rect.left >= descr->width) break;
1152b3fb8555SGiannis Adamopoulos }
1153b3fb8555SGiannis Adamopoulos else
1154b3fb8555SGiannis Adamopoulos {
1155b3fb8555SGiannis Adamopoulos col_pos--;
1156b3fb8555SGiannis Adamopoulos if (rect.top >= descr->height) break;
1157b3fb8555SGiannis Adamopoulos }
1158b3fb8555SGiannis Adamopoulos }
1159b3fb8555SGiannis Adamopoulos
1160b3fb8555SGiannis Adamopoulos /* Paint the focus item now */
1161b3fb8555SGiannis Adamopoulos if (focusRect.top != focusRect.bottom &&
1162b3fb8555SGiannis Adamopoulos descr->caret_on && descr->in_focus)
1163b3fb8555SGiannis Adamopoulos LISTBOX_PaintItem( descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE );
1164b3fb8555SGiannis Adamopoulos
1165b3fb8555SGiannis Adamopoulos if (!IS_OWNERDRAW(descr))
1166b3fb8555SGiannis Adamopoulos {
1167b3fb8555SGiannis Adamopoulos /* Clear the remainder of the client area */
1168b3fb8555SGiannis Adamopoulos if (rect.top < descr->height)
1169b3fb8555SGiannis Adamopoulos {
1170b3fb8555SGiannis Adamopoulos rect.bottom = descr->height;
1171b3fb8555SGiannis Adamopoulos ExtTextOutW( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
1172b3fb8555SGiannis Adamopoulos &rect, NULL, 0, NULL );
1173b3fb8555SGiannis Adamopoulos }
1174b3fb8555SGiannis Adamopoulos if (rect.right < descr->width)
1175b3fb8555SGiannis Adamopoulos {
1176b3fb8555SGiannis Adamopoulos rect.left = rect.right;
1177b3fb8555SGiannis Adamopoulos rect.right = descr->width;
1178b3fb8555SGiannis Adamopoulos rect.top = 0;
1179b3fb8555SGiannis Adamopoulos rect.bottom = descr->height;
1180b3fb8555SGiannis Adamopoulos ExtTextOutW( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
1181b3fb8555SGiannis Adamopoulos &rect, NULL, 0, NULL );
1182b3fb8555SGiannis Adamopoulos }
1183b3fb8555SGiannis Adamopoulos }
1184b3fb8555SGiannis Adamopoulos if (oldFont) SelectObject( hdc, oldFont );
1185b3fb8555SGiannis Adamopoulos if (oldBrush) SelectObject( hdc, oldBrush );
1186b3fb8555SGiannis Adamopoulos return 0;
1187b3fb8555SGiannis Adamopoulos }
1188b3fb8555SGiannis Adamopoulos
LISTBOX_NCPaint(LB_DESCR * descr,HRGN region)1189b3fb8555SGiannis Adamopoulos static void LISTBOX_NCPaint( LB_DESCR *descr, HRGN region )
1190b3fb8555SGiannis Adamopoulos {
1191b3fb8555SGiannis Adamopoulos DWORD exstyle = GetWindowLongW( descr->self, GWL_EXSTYLE);
1192b3fb8555SGiannis Adamopoulos HTHEME theme = GetWindowTheme( descr->self );
1193b3fb8555SGiannis Adamopoulos HRGN cliprgn = region;
1194b3fb8555SGiannis Adamopoulos int cxEdge, cyEdge;
1195b3fb8555SGiannis Adamopoulos HDC hdc;
1196b3fb8555SGiannis Adamopoulos RECT r;
1197b3fb8555SGiannis Adamopoulos
1198b3fb8555SGiannis Adamopoulos if (!theme || !(exstyle & WS_EX_CLIENTEDGE))
1199b3fb8555SGiannis Adamopoulos return;
1200b3fb8555SGiannis Adamopoulos
1201*0707475fSJustin Miller cxEdge = GetSystemMetrics(SM_CXEDGE);
1202b3fb8555SGiannis Adamopoulos cyEdge = GetSystemMetrics(SM_CYEDGE);
1203b3fb8555SGiannis Adamopoulos
1204b3fb8555SGiannis Adamopoulos GetWindowRect(descr->self, &r);
1205b3fb8555SGiannis Adamopoulos
1206b3fb8555SGiannis Adamopoulos /* New clipping region passed to default proc to exclude border */
1207b3fb8555SGiannis Adamopoulos cliprgn = CreateRectRgn(r.left + cxEdge, r.top + cyEdge,
1208b3fb8555SGiannis Adamopoulos r.right - cxEdge, r.bottom - cyEdge);
1209b3fb8555SGiannis Adamopoulos if (region != (HRGN)1)
1210b3fb8555SGiannis Adamopoulos CombineRgn(cliprgn, cliprgn, region, RGN_AND);
1211b3fb8555SGiannis Adamopoulos OffsetRect(&r, -r.left, -r.top);
1212b3fb8555SGiannis Adamopoulos
1213b3fb8555SGiannis Adamopoulos #ifdef __REACTOS__ /* r73789 */
1214b3fb8555SGiannis Adamopoulos hdc = GetWindowDC(descr->self);
1215b3fb8555SGiannis Adamopoulos /* Exclude client part */
1216b3fb8555SGiannis Adamopoulos ExcludeClipRect(hdc,
1217b3fb8555SGiannis Adamopoulos r.left + cxEdge,
1218b3fb8555SGiannis Adamopoulos r.top + cyEdge,
1219b3fb8555SGiannis Adamopoulos r.right - cxEdge,
1220b3fb8555SGiannis Adamopoulos r.bottom -cyEdge);
1221b3fb8555SGiannis Adamopoulos #else
1222b3fb8555SGiannis Adamopoulos hdc = GetDCEx(descr->self, region, DCX_WINDOW|DCX_INTERSECTRGN);
1223b3fb8555SGiannis Adamopoulos OffsetRect(&r, -r.left, -r.top);
1224b3fb8555SGiannis Adamopoulos #endif
1225b3fb8555SGiannis Adamopoulos
1226b3fb8555SGiannis Adamopoulos if (IsThemeBackgroundPartiallyTransparent (theme, 0, 0))
1227b3fb8555SGiannis Adamopoulos DrawThemeParentBackground(descr->self, hdc, &r);
1228b3fb8555SGiannis Adamopoulos DrawThemeBackground (theme, hdc, 0, 0, &r, 0);
1229b3fb8555SGiannis Adamopoulos ReleaseDC(descr->self, hdc);
1230b3fb8555SGiannis Adamopoulos }
1231b3fb8555SGiannis Adamopoulos
1232b3fb8555SGiannis Adamopoulos /***********************************************************************
1233b3fb8555SGiannis Adamopoulos * LISTBOX_InvalidateItems
1234b3fb8555SGiannis Adamopoulos *
1235b3fb8555SGiannis Adamopoulos * Invalidate all items from a given item. If the specified item is not
1236b3fb8555SGiannis Adamopoulos * visible, nothing happens.
1237b3fb8555SGiannis Adamopoulos */
LISTBOX_InvalidateItems(LB_DESCR * descr,INT index)1238b3fb8555SGiannis Adamopoulos static void LISTBOX_InvalidateItems( LB_DESCR *descr, INT index )
1239b3fb8555SGiannis Adamopoulos {
1240b3fb8555SGiannis Adamopoulos RECT rect;
1241b3fb8555SGiannis Adamopoulos
1242b3fb8555SGiannis Adamopoulos if (LISTBOX_GetItemRect( descr, index, &rect ) == 1)
1243b3fb8555SGiannis Adamopoulos {
1244b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOREDRAW)
1245b3fb8555SGiannis Adamopoulos {
1246b3fb8555SGiannis Adamopoulos descr->style |= LBS_DISPLAYCHANGED;
1247b3fb8555SGiannis Adamopoulos return;
1248b3fb8555SGiannis Adamopoulos }
1249b3fb8555SGiannis Adamopoulos rect.bottom = descr->height;
1250b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, &rect, TRUE );
1251b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
1252b3fb8555SGiannis Adamopoulos {
1253b3fb8555SGiannis Adamopoulos /* Repaint the other columns */
1254b3fb8555SGiannis Adamopoulos rect.left = rect.right;
1255b3fb8555SGiannis Adamopoulos rect.right = descr->width;
1256b3fb8555SGiannis Adamopoulos rect.top = 0;
1257b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, &rect, TRUE );
1258b3fb8555SGiannis Adamopoulos }
1259b3fb8555SGiannis Adamopoulos }
1260b3fb8555SGiannis Adamopoulos }
1261b3fb8555SGiannis Adamopoulos
LISTBOX_InvalidateItemRect(LB_DESCR * descr,INT index)1262b3fb8555SGiannis Adamopoulos static void LISTBOX_InvalidateItemRect( LB_DESCR *descr, INT index )
1263b3fb8555SGiannis Adamopoulos {
1264b3fb8555SGiannis Adamopoulos RECT rect;
1265b3fb8555SGiannis Adamopoulos
1266b3fb8555SGiannis Adamopoulos if (LISTBOX_GetItemRect( descr, index, &rect ) == 1)
1267b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, &rect, TRUE );
1268b3fb8555SGiannis Adamopoulos }
1269b3fb8555SGiannis Adamopoulos
1270b3fb8555SGiannis Adamopoulos /***********************************************************************
1271b3fb8555SGiannis Adamopoulos * LISTBOX_GetItemHeight
1272b3fb8555SGiannis Adamopoulos */
LISTBOX_GetItemHeight(const LB_DESCR * descr,INT index)1273b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_GetItemHeight( const LB_DESCR *descr, INT index )
1274b3fb8555SGiannis Adamopoulos {
1275b3fb8555SGiannis Adamopoulos if (descr->style & LBS_OWNERDRAWVARIABLE && descr->nb_items > 0)
1276b3fb8555SGiannis Adamopoulos {
1277b3fb8555SGiannis Adamopoulos if ((index < 0) || (index >= descr->nb_items))
1278b3fb8555SGiannis Adamopoulos {
1279b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
1280b3fb8555SGiannis Adamopoulos return LB_ERR;
1281b3fb8555SGiannis Adamopoulos }
1282*0707475fSJustin Miller return get_item_height(descr, index);
1283b3fb8555SGiannis Adamopoulos }
1284b3fb8555SGiannis Adamopoulos else return descr->item_height;
1285b3fb8555SGiannis Adamopoulos }
1286b3fb8555SGiannis Adamopoulos
1287b3fb8555SGiannis Adamopoulos
1288b3fb8555SGiannis Adamopoulos /***********************************************************************
1289b3fb8555SGiannis Adamopoulos * LISTBOX_SetItemHeight
1290b3fb8555SGiannis Adamopoulos */
LISTBOX_SetItemHeight(LB_DESCR * descr,INT index,INT height,BOOL repaint)1291b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_SetItemHeight( LB_DESCR *descr, INT index, INT height, BOOL repaint )
1292b3fb8555SGiannis Adamopoulos {
1293*0707475fSJustin Miller if (height > MAXWORD)
1294b3fb8555SGiannis Adamopoulos return -1;
1295b3fb8555SGiannis Adamopoulos
1296b3fb8555SGiannis Adamopoulos if (!height) height = 1;
1297b3fb8555SGiannis Adamopoulos
1298b3fb8555SGiannis Adamopoulos if (descr->style & LBS_OWNERDRAWVARIABLE)
1299b3fb8555SGiannis Adamopoulos {
1300b3fb8555SGiannis Adamopoulos if ((index < 0) || (index >= descr->nb_items))
1301b3fb8555SGiannis Adamopoulos {
1302b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
1303b3fb8555SGiannis Adamopoulos return LB_ERR;
1304b3fb8555SGiannis Adamopoulos }
1305b3fb8555SGiannis Adamopoulos TRACE("[%p]: item %d height = %d\n", descr->self, index, height );
1306*0707475fSJustin Miller set_item_height(descr, index, height);
1307b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
1308b3fb8555SGiannis Adamopoulos if (repaint)
1309b3fb8555SGiannis Adamopoulos LISTBOX_InvalidateItems( descr, index );
1310b3fb8555SGiannis Adamopoulos }
1311b3fb8555SGiannis Adamopoulos else if (height != descr->item_height)
1312b3fb8555SGiannis Adamopoulos {
1313b3fb8555SGiannis Adamopoulos TRACE("[%p]: new height = %d\n", descr->self, height );
1314b3fb8555SGiannis Adamopoulos descr->item_height = height;
1315b3fb8555SGiannis Adamopoulos LISTBOX_UpdatePage( descr );
1316b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
1317b3fb8555SGiannis Adamopoulos if (repaint)
1318b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, 0, TRUE );
1319b3fb8555SGiannis Adamopoulos }
1320b3fb8555SGiannis Adamopoulos return LB_OKAY;
1321b3fb8555SGiannis Adamopoulos }
1322b3fb8555SGiannis Adamopoulos
1323b3fb8555SGiannis Adamopoulos
1324b3fb8555SGiannis Adamopoulos /***********************************************************************
1325b3fb8555SGiannis Adamopoulos * LISTBOX_SetHorizontalPos
1326b3fb8555SGiannis Adamopoulos */
LISTBOX_SetHorizontalPos(LB_DESCR * descr,INT pos)1327b3fb8555SGiannis Adamopoulos static void LISTBOX_SetHorizontalPos( LB_DESCR *descr, INT pos )
1328b3fb8555SGiannis Adamopoulos {
1329b3fb8555SGiannis Adamopoulos INT diff;
1330b3fb8555SGiannis Adamopoulos
1331b3fb8555SGiannis Adamopoulos if (pos > descr->horz_extent - descr->width)
1332b3fb8555SGiannis Adamopoulos pos = descr->horz_extent - descr->width;
1333b3fb8555SGiannis Adamopoulos if (pos < 0) pos = 0;
1334b3fb8555SGiannis Adamopoulos if (!(diff = descr->horz_pos - pos)) return;
1335b3fb8555SGiannis Adamopoulos TRACE("[%p]: new horz pos = %d\n", descr->self, pos );
1336b3fb8555SGiannis Adamopoulos descr->horz_pos = pos;
1337b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
1338b3fb8555SGiannis Adamopoulos if (abs(diff) < descr->width)
1339b3fb8555SGiannis Adamopoulos {
1340b3fb8555SGiannis Adamopoulos RECT rect;
1341b3fb8555SGiannis Adamopoulos /* Invalidate the focused item so it will be repainted correctly */
1342b3fb8555SGiannis Adamopoulos if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
1343b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, &rect, TRUE );
1344b3fb8555SGiannis Adamopoulos ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
1345b3fb8555SGiannis Adamopoulos SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
1346b3fb8555SGiannis Adamopoulos }
1347b3fb8555SGiannis Adamopoulos else
1348b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, NULL, TRUE );
1349b3fb8555SGiannis Adamopoulos }
1350b3fb8555SGiannis Adamopoulos
1351b3fb8555SGiannis Adamopoulos
1352b3fb8555SGiannis Adamopoulos /***********************************************************************
1353b3fb8555SGiannis Adamopoulos * LISTBOX_SetHorizontalExtent
1354b3fb8555SGiannis Adamopoulos */
LISTBOX_SetHorizontalExtent(LB_DESCR * descr,INT extent)1355b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_SetHorizontalExtent( LB_DESCR *descr, INT extent )
1356b3fb8555SGiannis Adamopoulos {
1357b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
1358b3fb8555SGiannis Adamopoulos return LB_OKAY;
1359b3fb8555SGiannis Adamopoulos if (extent == descr->horz_extent) return LB_OKAY;
1360b3fb8555SGiannis Adamopoulos TRACE("[%p]: new horz extent = %d\n", descr->self, extent );
1361b3fb8555SGiannis Adamopoulos descr->horz_extent = extent;
1362b3fb8555SGiannis Adamopoulos if (descr->style & WS_HSCROLL) {
1363b3fb8555SGiannis Adamopoulos SCROLLINFO info;
1364b3fb8555SGiannis Adamopoulos info.cbSize = sizeof(info);
1365b3fb8555SGiannis Adamopoulos info.nMin = 0;
1366b3fb8555SGiannis Adamopoulos info.nMax = descr->horz_extent ? descr->horz_extent - 1 : 0;
1367b3fb8555SGiannis Adamopoulos info.fMask = SIF_RANGE;
1368b3fb8555SGiannis Adamopoulos if (descr->style & LBS_DISABLENOSCROLL)
1369b3fb8555SGiannis Adamopoulos info.fMask |= SIF_DISABLENOSCROLL;
1370b3fb8555SGiannis Adamopoulos SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
1371b3fb8555SGiannis Adamopoulos }
1372b3fb8555SGiannis Adamopoulos if (descr->horz_pos > extent - descr->width)
1373b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr, extent - descr->width );
1374b3fb8555SGiannis Adamopoulos return LB_OKAY;
1375b3fb8555SGiannis Adamopoulos }
1376b3fb8555SGiannis Adamopoulos
1377b3fb8555SGiannis Adamopoulos
1378b3fb8555SGiannis Adamopoulos /***********************************************************************
1379b3fb8555SGiannis Adamopoulos * LISTBOX_SetColumnWidth
1380b3fb8555SGiannis Adamopoulos */
LISTBOX_SetColumnWidth(LB_DESCR * descr,INT column_width)1381*0707475fSJustin Miller static LRESULT LISTBOX_SetColumnWidth( LB_DESCR *descr, INT column_width)
1382b3fb8555SGiannis Adamopoulos {
1383*0707475fSJustin Miller RECT rect;
1384*0707475fSJustin Miller
1385*0707475fSJustin Miller TRACE("[%p]: new column width = %d\n", descr->self, column_width);
1386*0707475fSJustin Miller
1387*0707475fSJustin Miller GetClientRect(descr->self, &rect);
1388*0707475fSJustin Miller descr->width = rect.right - rect.left;
1389*0707475fSJustin Miller descr->height = rect.bottom - rect.top;
1390*0707475fSJustin Miller descr->column_width = column_width;
1391*0707475fSJustin Miller
1392b3fb8555SGiannis Adamopoulos LISTBOX_UpdatePage(descr);
1393*0707475fSJustin Miller LISTBOX_UpdateScroll(descr);
1394b3fb8555SGiannis Adamopoulos return LB_OKAY;
1395b3fb8555SGiannis Adamopoulos }
1396b3fb8555SGiannis Adamopoulos
1397b3fb8555SGiannis Adamopoulos
1398b3fb8555SGiannis Adamopoulos /***********************************************************************
1399b3fb8555SGiannis Adamopoulos * LISTBOX_SetFont
1400b3fb8555SGiannis Adamopoulos *
1401b3fb8555SGiannis Adamopoulos * Returns the item height.
1402b3fb8555SGiannis Adamopoulos */
LISTBOX_SetFont(LB_DESCR * descr,HFONT font)1403b3fb8555SGiannis Adamopoulos static INT LISTBOX_SetFont( LB_DESCR *descr, HFONT font )
1404b3fb8555SGiannis Adamopoulos {
1405b3fb8555SGiannis Adamopoulos HDC hdc;
1406b3fb8555SGiannis Adamopoulos HFONT oldFont = 0;
1407b3fb8555SGiannis Adamopoulos const char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1408b3fb8555SGiannis Adamopoulos SIZE sz;
1409b3fb8555SGiannis Adamopoulos
1410b3fb8555SGiannis Adamopoulos descr->font = font;
1411b3fb8555SGiannis Adamopoulos
1412b3fb8555SGiannis Adamopoulos if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE )))
1413b3fb8555SGiannis Adamopoulos {
1414b3fb8555SGiannis Adamopoulos ERR("unable to get DC.\n" );
1415b3fb8555SGiannis Adamopoulos return 16;
1416b3fb8555SGiannis Adamopoulos }
1417b3fb8555SGiannis Adamopoulos if (font) oldFont = SelectObject( hdc, font );
1418b3fb8555SGiannis Adamopoulos GetTextExtentPointA( hdc, alphabet, 52, &sz);
1419b3fb8555SGiannis Adamopoulos if (oldFont) SelectObject( hdc, oldFont );
1420b3fb8555SGiannis Adamopoulos ReleaseDC( descr->self, hdc );
1421b3fb8555SGiannis Adamopoulos
1422b3fb8555SGiannis Adamopoulos descr->avg_char_width = (sz.cx / 26 + 1) / 2;
1423b3fb8555SGiannis Adamopoulos if (!IS_OWNERDRAW(descr))
1424b3fb8555SGiannis Adamopoulos LISTBOX_SetItemHeight( descr, 0, sz.cy, FALSE );
1425b3fb8555SGiannis Adamopoulos return sz.cy;
1426b3fb8555SGiannis Adamopoulos }
1427b3fb8555SGiannis Adamopoulos
1428b3fb8555SGiannis Adamopoulos
1429b3fb8555SGiannis Adamopoulos /***********************************************************************
1430b3fb8555SGiannis Adamopoulos * LISTBOX_MakeItemVisible
1431b3fb8555SGiannis Adamopoulos *
1432b3fb8555SGiannis Adamopoulos * Make sure that a given item is partially or fully visible.
1433b3fb8555SGiannis Adamopoulos */
LISTBOX_MakeItemVisible(LB_DESCR * descr,INT index,BOOL fully)1434b3fb8555SGiannis Adamopoulos static void LISTBOX_MakeItemVisible( LB_DESCR *descr, INT index, BOOL fully )
1435b3fb8555SGiannis Adamopoulos {
1436b3fb8555SGiannis Adamopoulos INT top;
1437b3fb8555SGiannis Adamopoulos
1438b3fb8555SGiannis Adamopoulos TRACE("current top item %d, index %d, fully %d\n", descr->top_item, index, fully);
1439b3fb8555SGiannis Adamopoulos
1440b3fb8555SGiannis Adamopoulos if (index <= descr->top_item) top = index;
1441b3fb8555SGiannis Adamopoulos else if (descr->style & LBS_MULTICOLUMN)
1442b3fb8555SGiannis Adamopoulos {
1443b3fb8555SGiannis Adamopoulos INT cols = descr->width;
1444b3fb8555SGiannis Adamopoulos if (!fully) cols += descr->column_width - 1;
1445b3fb8555SGiannis Adamopoulos if (cols >= descr->column_width) cols /= descr->column_width;
1446b3fb8555SGiannis Adamopoulos else cols = 1;
1447b3fb8555SGiannis Adamopoulos if (index < descr->top_item + (descr->page_size * cols)) return;
1448b3fb8555SGiannis Adamopoulos top = index - descr->page_size * (cols - 1);
1449b3fb8555SGiannis Adamopoulos }
1450b3fb8555SGiannis Adamopoulos else if (descr->style & LBS_OWNERDRAWVARIABLE)
1451b3fb8555SGiannis Adamopoulos {
1452*0707475fSJustin Miller INT height = fully ? get_item_height(descr, index) : 1;
1453b3fb8555SGiannis Adamopoulos for (top = index; top > descr->top_item; top--)
1454*0707475fSJustin Miller if ((height += get_item_height(descr, top - 1)) > descr->height) break;
1455b3fb8555SGiannis Adamopoulos }
1456b3fb8555SGiannis Adamopoulos else
1457b3fb8555SGiannis Adamopoulos {
1458b3fb8555SGiannis Adamopoulos if (index < descr->top_item + descr->page_size) return;
1459b3fb8555SGiannis Adamopoulos if (!fully && (index == descr->top_item + descr->page_size) &&
1460b3fb8555SGiannis Adamopoulos (descr->height > (descr->page_size * descr->item_height))) return;
1461b3fb8555SGiannis Adamopoulos top = index - descr->page_size + 1;
1462b3fb8555SGiannis Adamopoulos }
1463b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, top, TRUE );
1464b3fb8555SGiannis Adamopoulos }
1465b3fb8555SGiannis Adamopoulos
1466b3fb8555SGiannis Adamopoulos /***********************************************************************
1467b3fb8555SGiannis Adamopoulos * LISTBOX_SetCaretIndex
1468b3fb8555SGiannis Adamopoulos *
1469b3fb8555SGiannis Adamopoulos * NOTES
1470b3fb8555SGiannis Adamopoulos * index must be between 0 and descr->nb_items-1, or LB_ERR is returned.
1471b3fb8555SGiannis Adamopoulos *
1472b3fb8555SGiannis Adamopoulos */
LISTBOX_SetCaretIndex(LB_DESCR * descr,INT index,BOOL fully_visible)1473b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_SetCaretIndex( LB_DESCR *descr, INT index, BOOL fully_visible )
1474b3fb8555SGiannis Adamopoulos {
1475*0707475fSJustin Miller BOOL focus_changed = descr->focus_item != index;
1476b3fb8555SGiannis Adamopoulos
1477*0707475fSJustin Miller TRACE("old focus %d, index %d\n", descr->focus_item, index);
1478b3fb8555SGiannis Adamopoulos
1479b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOSEL) return LB_ERR;
1480b3fb8555SGiannis Adamopoulos if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
1481b3fb8555SGiannis Adamopoulos
1482*0707475fSJustin Miller if (focus_changed)
1483*0707475fSJustin Miller {
1484b3fb8555SGiannis Adamopoulos LISTBOX_DrawFocusRect( descr, FALSE );
1485b3fb8555SGiannis Adamopoulos descr->focus_item = index;
1486*0707475fSJustin Miller }
1487b3fb8555SGiannis Adamopoulos
1488b3fb8555SGiannis Adamopoulos LISTBOX_MakeItemVisible( descr, index, fully_visible );
1489*0707475fSJustin Miller
1490*0707475fSJustin Miller if (focus_changed)
1491b3fb8555SGiannis Adamopoulos LISTBOX_DrawFocusRect( descr, TRUE );
1492b3fb8555SGiannis Adamopoulos
1493b3fb8555SGiannis Adamopoulos return LB_OKAY;
1494b3fb8555SGiannis Adamopoulos }
1495b3fb8555SGiannis Adamopoulos
1496b3fb8555SGiannis Adamopoulos
1497b3fb8555SGiannis Adamopoulos /***********************************************************************
1498b3fb8555SGiannis Adamopoulos * LISTBOX_SelectItemRange
1499b3fb8555SGiannis Adamopoulos *
1500b3fb8555SGiannis Adamopoulos * Select a range of items. Should only be used on a MULTIPLESEL listbox.
1501b3fb8555SGiannis Adamopoulos */
LISTBOX_SelectItemRange(LB_DESCR * descr,INT first,INT last,BOOL on)1502b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_SelectItemRange( LB_DESCR *descr, INT first,
1503b3fb8555SGiannis Adamopoulos INT last, BOOL on )
1504b3fb8555SGiannis Adamopoulos {
1505b3fb8555SGiannis Adamopoulos INT i;
1506b3fb8555SGiannis Adamopoulos
1507b3fb8555SGiannis Adamopoulos /* A few sanity checks */
1508b3fb8555SGiannis Adamopoulos
1509b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOSEL) return LB_ERR;
1510b3fb8555SGiannis Adamopoulos if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
1511b3fb8555SGiannis Adamopoulos
1512b3fb8555SGiannis Adamopoulos if (!descr->nb_items) return LB_OKAY;
1513b3fb8555SGiannis Adamopoulos
1514b3fb8555SGiannis Adamopoulos if (last == -1 || last >= descr->nb_items) last = descr->nb_items - 1;
1515b3fb8555SGiannis Adamopoulos if (first < 0) first = 0;
1516b3fb8555SGiannis Adamopoulos if (last < first) return LB_OKAY;
1517b3fb8555SGiannis Adamopoulos
1518b3fb8555SGiannis Adamopoulos if (on) /* Turn selection on */
1519b3fb8555SGiannis Adamopoulos {
1520b3fb8555SGiannis Adamopoulos for (i = first; i <= last; i++)
1521b3fb8555SGiannis Adamopoulos {
1522*0707475fSJustin Miller if (is_item_selected(descr, i)) continue;
1523*0707475fSJustin Miller set_item_selected_state(descr, i, TRUE);
1524b3fb8555SGiannis Adamopoulos LISTBOX_InvalidateItemRect(descr, i);
1525b3fb8555SGiannis Adamopoulos }
1526b3fb8555SGiannis Adamopoulos }
1527b3fb8555SGiannis Adamopoulos else /* Turn selection off */
1528b3fb8555SGiannis Adamopoulos {
1529b3fb8555SGiannis Adamopoulos for (i = first; i <= last; i++)
1530b3fb8555SGiannis Adamopoulos {
1531*0707475fSJustin Miller if (!is_item_selected(descr, i)) continue;
1532*0707475fSJustin Miller set_item_selected_state(descr, i, FALSE);
1533b3fb8555SGiannis Adamopoulos LISTBOX_InvalidateItemRect(descr, i);
1534b3fb8555SGiannis Adamopoulos }
1535b3fb8555SGiannis Adamopoulos }
1536b3fb8555SGiannis Adamopoulos return LB_OKAY;
1537b3fb8555SGiannis Adamopoulos }
1538b3fb8555SGiannis Adamopoulos
1539b3fb8555SGiannis Adamopoulos /***********************************************************************
1540b3fb8555SGiannis Adamopoulos * LISTBOX_SetSelection
1541b3fb8555SGiannis Adamopoulos */
LISTBOX_SetSelection(LB_DESCR * descr,INT index,BOOL on,BOOL send_notify)1542b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_SetSelection( LB_DESCR *descr, INT index,
1543b3fb8555SGiannis Adamopoulos BOOL on, BOOL send_notify )
1544b3fb8555SGiannis Adamopoulos {
1545b3fb8555SGiannis Adamopoulos TRACE( "cur_sel=%d index=%d notify=%s\n",
1546b3fb8555SGiannis Adamopoulos descr->selected_item, index, send_notify ? "YES" : "NO" );
1547b3fb8555SGiannis Adamopoulos
1548b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOSEL)
1549b3fb8555SGiannis Adamopoulos {
1550b3fb8555SGiannis Adamopoulos descr->selected_item = index;
1551b3fb8555SGiannis Adamopoulos return LB_ERR;
1552b3fb8555SGiannis Adamopoulos }
1553b3fb8555SGiannis Adamopoulos if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
1554b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTIPLESEL)
1555b3fb8555SGiannis Adamopoulos {
1556b3fb8555SGiannis Adamopoulos if (index == -1) /* Select all items */
1557b3fb8555SGiannis Adamopoulos return LISTBOX_SelectItemRange( descr, 0, descr->nb_items, on );
1558b3fb8555SGiannis Adamopoulos else /* Only one item */
1559b3fb8555SGiannis Adamopoulos return LISTBOX_SelectItemRange( descr, index, index, on );
1560b3fb8555SGiannis Adamopoulos }
1561b3fb8555SGiannis Adamopoulos else
1562b3fb8555SGiannis Adamopoulos {
1563b3fb8555SGiannis Adamopoulos INT oldsel = descr->selected_item;
1564b3fb8555SGiannis Adamopoulos if (index == oldsel) return LB_OKAY;
1565*0707475fSJustin Miller if (oldsel != -1) set_item_selected_state(descr, oldsel, FALSE);
1566*0707475fSJustin Miller if (index != -1) set_item_selected_state(descr, index, TRUE);
1567b3fb8555SGiannis Adamopoulos descr->selected_item = index;
1568*0707475fSJustin Miller if (oldsel != -1) LISTBOX_RepaintItem( descr, oldsel, ODA_SELECT );
1569b3fb8555SGiannis Adamopoulos if (index != -1) LISTBOX_RepaintItem( descr, index, ODA_SELECT );
1570b3fb8555SGiannis Adamopoulos if (send_notify && descr->nb_items) SEND_NOTIFICATION( descr,
1571b3fb8555SGiannis Adamopoulos (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
1572b3fb8555SGiannis Adamopoulos else
1573b3fb8555SGiannis Adamopoulos if( descr->lphc ) /* set selection change flag for parent combo */
1574b3fb8555SGiannis Adamopoulos descr->lphc->wState |= CBF_SELCHANGE;
1575b3fb8555SGiannis Adamopoulos }
1576b3fb8555SGiannis Adamopoulos return LB_OKAY;
1577b3fb8555SGiannis Adamopoulos }
1578b3fb8555SGiannis Adamopoulos
1579b3fb8555SGiannis Adamopoulos
1580b3fb8555SGiannis Adamopoulos /***********************************************************************
1581b3fb8555SGiannis Adamopoulos * LISTBOX_MoveCaret
1582b3fb8555SGiannis Adamopoulos *
1583b3fb8555SGiannis Adamopoulos * Change the caret position and extend the selection to the new caret.
1584b3fb8555SGiannis Adamopoulos */
LISTBOX_MoveCaret(LB_DESCR * descr,INT index,BOOL fully_visible)1585b3fb8555SGiannis Adamopoulos static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index, BOOL fully_visible )
1586b3fb8555SGiannis Adamopoulos {
1587b3fb8555SGiannis Adamopoulos TRACE("old focus %d, index %d\n", descr->focus_item, index);
1588b3fb8555SGiannis Adamopoulos
1589b3fb8555SGiannis Adamopoulos if ((index < 0) || (index >= descr->nb_items))
1590b3fb8555SGiannis Adamopoulos return;
1591b3fb8555SGiannis Adamopoulos
1592b3fb8555SGiannis Adamopoulos /* Important, repaint needs to be done in this order if
1593b3fb8555SGiannis Adamopoulos you want to mimic Windows behavior:
1594b3fb8555SGiannis Adamopoulos 1. Remove the focus and paint the item
1595b3fb8555SGiannis Adamopoulos 2. Remove the selection and paint the item(s)
1596b3fb8555SGiannis Adamopoulos 3. Set the selection and repaint the item(s)
1597b3fb8555SGiannis Adamopoulos 4. Set the focus to 'index' and repaint the item */
1598b3fb8555SGiannis Adamopoulos
1599b3fb8555SGiannis Adamopoulos /* 1. remove the focus and repaint the item */
1600b3fb8555SGiannis Adamopoulos LISTBOX_DrawFocusRect( descr, FALSE );
1601b3fb8555SGiannis Adamopoulos
1602b3fb8555SGiannis Adamopoulos /* 2. then turn off the previous selection */
1603b3fb8555SGiannis Adamopoulos /* 3. repaint the new selected item */
1604b3fb8555SGiannis Adamopoulos if (descr->style & LBS_EXTENDEDSEL)
1605b3fb8555SGiannis Adamopoulos {
1606b3fb8555SGiannis Adamopoulos if (descr->anchor_item != -1)
1607b3fb8555SGiannis Adamopoulos {
1608b3fb8555SGiannis Adamopoulos INT first = min( index, descr->anchor_item );
1609b3fb8555SGiannis Adamopoulos INT last = max( index, descr->anchor_item );
1610b3fb8555SGiannis Adamopoulos if (first > 0)
1611b3fb8555SGiannis Adamopoulos LISTBOX_SelectItemRange( descr, 0, first - 1, FALSE );
1612b3fb8555SGiannis Adamopoulos LISTBOX_SelectItemRange( descr, last + 1, -1, FALSE );
1613b3fb8555SGiannis Adamopoulos LISTBOX_SelectItemRange( descr, first, last, TRUE );
1614b3fb8555SGiannis Adamopoulos }
1615b3fb8555SGiannis Adamopoulos }
1616b3fb8555SGiannis Adamopoulos else if (!(descr->style & LBS_MULTIPLESEL))
1617b3fb8555SGiannis Adamopoulos {
1618b3fb8555SGiannis Adamopoulos /* Set selection to new caret item */
1619b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, index, TRUE, FALSE );
1620b3fb8555SGiannis Adamopoulos }
1621b3fb8555SGiannis Adamopoulos
1622b3fb8555SGiannis Adamopoulos /* 4. repaint the new item with the focus */
1623b3fb8555SGiannis Adamopoulos descr->focus_item = index;
1624b3fb8555SGiannis Adamopoulos LISTBOX_MakeItemVisible( descr, index, fully_visible );
1625b3fb8555SGiannis Adamopoulos LISTBOX_DrawFocusRect( descr, TRUE );
1626b3fb8555SGiannis Adamopoulos }
1627b3fb8555SGiannis Adamopoulos
1628b3fb8555SGiannis Adamopoulos
1629b3fb8555SGiannis Adamopoulos /***********************************************************************
1630b3fb8555SGiannis Adamopoulos * LISTBOX_InsertItem
1631b3fb8555SGiannis Adamopoulos */
LISTBOX_InsertItem(LB_DESCR * descr,INT index,LPWSTR str,ULONG_PTR data)1632b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index,
1633b3fb8555SGiannis Adamopoulos LPWSTR str, ULONG_PTR data )
1634b3fb8555SGiannis Adamopoulos {
1635b3fb8555SGiannis Adamopoulos INT oldfocus = descr->focus_item;
1636b3fb8555SGiannis Adamopoulos
1637b3fb8555SGiannis Adamopoulos if (index == -1) index = descr->nb_items;
1638b3fb8555SGiannis Adamopoulos else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
1639*0707475fSJustin Miller if (!resize_storage(descr, descr->nb_items + 1)) return LB_ERR;
1640b3fb8555SGiannis Adamopoulos
1641*0707475fSJustin Miller insert_item_data(descr, index);
1642b3fb8555SGiannis Adamopoulos descr->nb_items++;
1643*0707475fSJustin Miller set_item_string(descr, index, str);
1644*0707475fSJustin Miller set_item_data(descr, index, HAS_STRINGS(descr) ? 0 : data);
1645*0707475fSJustin Miller set_item_height(descr, index, 0);
1646*0707475fSJustin Miller set_item_selected_state(descr, index, FALSE);
1647b3fb8555SGiannis Adamopoulos
1648b3fb8555SGiannis Adamopoulos /* Get item height */
1649b3fb8555SGiannis Adamopoulos
1650b3fb8555SGiannis Adamopoulos if (descr->style & LBS_OWNERDRAWVARIABLE)
1651b3fb8555SGiannis Adamopoulos {
1652b3fb8555SGiannis Adamopoulos MEASUREITEMSTRUCT mis;
1653b3fb8555SGiannis Adamopoulos UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
1654b3fb8555SGiannis Adamopoulos
1655b3fb8555SGiannis Adamopoulos mis.CtlType = ODT_LISTBOX;
1656b3fb8555SGiannis Adamopoulos mis.CtlID = id;
1657b3fb8555SGiannis Adamopoulos mis.itemID = index;
1658b3fb8555SGiannis Adamopoulos mis.itemData = data;
1659b3fb8555SGiannis Adamopoulos mis.itemHeight = descr->item_height;
1660b3fb8555SGiannis Adamopoulos SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
1661*0707475fSJustin Miller set_item_height(descr, index, mis.itemHeight ? mis.itemHeight : 1);
1662b3fb8555SGiannis Adamopoulos TRACE("[%p]: measure item %d (%s) = %d\n",
1663*0707475fSJustin Miller descr->self, index, str ? debugstr_w(str) : "", get_item_height(descr, index));
1664b3fb8555SGiannis Adamopoulos }
1665b3fb8555SGiannis Adamopoulos
1666b3fb8555SGiannis Adamopoulos /* Repaint the items */
1667b3fb8555SGiannis Adamopoulos
1668b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
1669b3fb8555SGiannis Adamopoulos LISTBOX_InvalidateItems( descr, index );
1670b3fb8555SGiannis Adamopoulos
1671b3fb8555SGiannis Adamopoulos /* Move selection and focused item */
1672b3fb8555SGiannis Adamopoulos /* If listbox was empty, set focus to the first item */
1673b3fb8555SGiannis Adamopoulos if (descr->nb_items == 1)
1674b3fb8555SGiannis Adamopoulos LISTBOX_SetCaretIndex( descr, 0, FALSE );
1675b3fb8555SGiannis Adamopoulos /* single select don't change selection index in win31 */
1676b3fb8555SGiannis Adamopoulos else if ((ISWIN31) && !(IS_MULTISELECT(descr)))
1677b3fb8555SGiannis Adamopoulos {
1678b3fb8555SGiannis Adamopoulos descr->selected_item++;
1679b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, descr->selected_item-1, TRUE, FALSE );
1680b3fb8555SGiannis Adamopoulos }
1681b3fb8555SGiannis Adamopoulos else
1682b3fb8555SGiannis Adamopoulos {
1683b3fb8555SGiannis Adamopoulos if (index <= descr->selected_item)
1684b3fb8555SGiannis Adamopoulos {
1685b3fb8555SGiannis Adamopoulos descr->selected_item++;
1686b3fb8555SGiannis Adamopoulos descr->focus_item = oldfocus; /* focus not changed */
1687b3fb8555SGiannis Adamopoulos }
1688b3fb8555SGiannis Adamopoulos }
1689b3fb8555SGiannis Adamopoulos return LB_OKAY;
1690b3fb8555SGiannis Adamopoulos }
1691b3fb8555SGiannis Adamopoulos
1692b3fb8555SGiannis Adamopoulos
1693b3fb8555SGiannis Adamopoulos /***********************************************************************
1694b3fb8555SGiannis Adamopoulos * LISTBOX_InsertString
1695b3fb8555SGiannis Adamopoulos */
LISTBOX_InsertString(LB_DESCR * descr,INT index,LPCWSTR str)1696b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_InsertString( LB_DESCR *descr, INT index, LPCWSTR str )
1697b3fb8555SGiannis Adamopoulos {
1698b3fb8555SGiannis Adamopoulos LPWSTR new_str = NULL;
1699b3fb8555SGiannis Adamopoulos LRESULT ret;
1700b3fb8555SGiannis Adamopoulos
1701b3fb8555SGiannis Adamopoulos if (HAS_STRINGS(descr))
1702b3fb8555SGiannis Adamopoulos {
1703b3fb8555SGiannis Adamopoulos static const WCHAR empty_stringW[] = { 0 };
1704b3fb8555SGiannis Adamopoulos if (!str) str = empty_stringW;
1705*0707475fSJustin Miller if (!(new_str = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(str) + 1) * sizeof(WCHAR) )))
1706b3fb8555SGiannis Adamopoulos {
1707b3fb8555SGiannis Adamopoulos SEND_NOTIFICATION( descr, LBN_ERRSPACE );
1708b3fb8555SGiannis Adamopoulos return LB_ERRSPACE;
1709b3fb8555SGiannis Adamopoulos }
1710*0707475fSJustin Miller lstrcpyW(new_str, str);
1711b3fb8555SGiannis Adamopoulos }
1712b3fb8555SGiannis Adamopoulos
1713b3fb8555SGiannis Adamopoulos if (index == -1) index = descr->nb_items;
1714b3fb8555SGiannis Adamopoulos if ((ret = LISTBOX_InsertItem( descr, index, new_str, (ULONG_PTR)str )) != 0)
1715b3fb8555SGiannis Adamopoulos {
1716b3fb8555SGiannis Adamopoulos HeapFree( GetProcessHeap(), 0, new_str );
1717b3fb8555SGiannis Adamopoulos return ret;
1718b3fb8555SGiannis Adamopoulos }
1719b3fb8555SGiannis Adamopoulos
1720b3fb8555SGiannis Adamopoulos TRACE("[%p]: added item %d %s\n",
1721b3fb8555SGiannis Adamopoulos descr->self, index, HAS_STRINGS(descr) ? debugstr_w(new_str) : "" );
1722b3fb8555SGiannis Adamopoulos return index;
1723b3fb8555SGiannis Adamopoulos }
1724b3fb8555SGiannis Adamopoulos
1725b3fb8555SGiannis Adamopoulos
1726b3fb8555SGiannis Adamopoulos /***********************************************************************
1727b3fb8555SGiannis Adamopoulos * LISTBOX_DeleteItem
1728b3fb8555SGiannis Adamopoulos *
1729b3fb8555SGiannis Adamopoulos * Delete the content of an item. 'index' must be a valid index.
1730b3fb8555SGiannis Adamopoulos */
LISTBOX_DeleteItem(LB_DESCR * descr,INT index)1731b3fb8555SGiannis Adamopoulos static void LISTBOX_DeleteItem( LB_DESCR *descr, INT index )
1732b3fb8555SGiannis Adamopoulos {
1733b3fb8555SGiannis Adamopoulos /* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
1734b3fb8555SGiannis Adamopoulos * while Win95 sends it for all items with user data.
1735b3fb8555SGiannis Adamopoulos * It's probably better to send it too often than not
1736b3fb8555SGiannis Adamopoulos * often enough, so this is what we do here.
1737b3fb8555SGiannis Adamopoulos */
1738*0707475fSJustin Miller if (IS_OWNERDRAW(descr) || get_item_data(descr, index))
1739b3fb8555SGiannis Adamopoulos {
1740b3fb8555SGiannis Adamopoulos DELETEITEMSTRUCT dis;
1741b3fb8555SGiannis Adamopoulos UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
1742b3fb8555SGiannis Adamopoulos
1743b3fb8555SGiannis Adamopoulos dis.CtlType = ODT_LISTBOX;
1744b3fb8555SGiannis Adamopoulos dis.CtlID = id;
1745b3fb8555SGiannis Adamopoulos dis.itemID = index;
1746b3fb8555SGiannis Adamopoulos dis.hwndItem = descr->self;
1747*0707475fSJustin Miller dis.itemData = get_item_data(descr, index);
1748b3fb8555SGiannis Adamopoulos SendMessageW( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
1749b3fb8555SGiannis Adamopoulos }
1750*0707475fSJustin Miller HeapFree( GetProcessHeap(), 0, get_item_string(descr, index) );
1751b3fb8555SGiannis Adamopoulos }
1752b3fb8555SGiannis Adamopoulos
1753b3fb8555SGiannis Adamopoulos
1754b3fb8555SGiannis Adamopoulos /***********************************************************************
1755b3fb8555SGiannis Adamopoulos * LISTBOX_RemoveItem
1756b3fb8555SGiannis Adamopoulos *
1757b3fb8555SGiannis Adamopoulos * Remove an item from the listbox and delete its content.
1758b3fb8555SGiannis Adamopoulos */
LISTBOX_RemoveItem(LB_DESCR * descr,INT index)1759b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_RemoveItem( LB_DESCR *descr, INT index )
1760b3fb8555SGiannis Adamopoulos {
1761b3fb8555SGiannis Adamopoulos if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
1762b3fb8555SGiannis Adamopoulos
1763b3fb8555SGiannis Adamopoulos /* We need to invalidate the original rect instead of the updated one. */
1764b3fb8555SGiannis Adamopoulos LISTBOX_InvalidateItems( descr, index );
1765b3fb8555SGiannis Adamopoulos
1766*0707475fSJustin Miller if (descr->nb_items == 1)
1767*0707475fSJustin Miller {
1768*0707475fSJustin Miller SendMessageW(descr->self, LB_RESETCONTENT, 0, 0);
1769*0707475fSJustin Miller return LB_OKAY;
1770*0707475fSJustin Miller }
1771b3fb8555SGiannis Adamopoulos descr->nb_items--;
1772b3fb8555SGiannis Adamopoulos LISTBOX_DeleteItem( descr, index );
1773*0707475fSJustin Miller remove_item_data(descr, index);
1774b3fb8555SGiannis Adamopoulos
1775b3fb8555SGiannis Adamopoulos if (descr->anchor_item == descr->nb_items) descr->anchor_item--;
1776*0707475fSJustin Miller resize_storage(descr, descr->nb_items);
1777b3fb8555SGiannis Adamopoulos
1778b3fb8555SGiannis Adamopoulos /* Repaint the items */
1779b3fb8555SGiannis Adamopoulos
1780b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
1781b3fb8555SGiannis Adamopoulos /* if we removed the scrollbar, reset the top of the list
1782b3fb8555SGiannis Adamopoulos (correct for owner-drawn ???) */
1783b3fb8555SGiannis Adamopoulos if (descr->nb_items == descr->page_size)
1784b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, 0, TRUE );
1785b3fb8555SGiannis Adamopoulos
1786b3fb8555SGiannis Adamopoulos /* Move selection and focused item */
1787b3fb8555SGiannis Adamopoulos if (!IS_MULTISELECT(descr))
1788b3fb8555SGiannis Adamopoulos {
1789b3fb8555SGiannis Adamopoulos if (index == descr->selected_item)
1790b3fb8555SGiannis Adamopoulos descr->selected_item = -1;
1791b3fb8555SGiannis Adamopoulos else if (index < descr->selected_item)
1792b3fb8555SGiannis Adamopoulos {
1793b3fb8555SGiannis Adamopoulos descr->selected_item--;
1794b3fb8555SGiannis Adamopoulos if (ISWIN31) /* win 31 do not change the selected item number */
1795b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, descr->selected_item + 1, TRUE, FALSE);
1796b3fb8555SGiannis Adamopoulos }
1797b3fb8555SGiannis Adamopoulos }
1798b3fb8555SGiannis Adamopoulos
1799b3fb8555SGiannis Adamopoulos if (descr->focus_item >= descr->nb_items)
1800b3fb8555SGiannis Adamopoulos {
1801b3fb8555SGiannis Adamopoulos descr->focus_item = descr->nb_items - 1;
1802b3fb8555SGiannis Adamopoulos if (descr->focus_item < 0) descr->focus_item = 0;
1803b3fb8555SGiannis Adamopoulos }
1804b3fb8555SGiannis Adamopoulos return LB_OKAY;
1805b3fb8555SGiannis Adamopoulos }
1806b3fb8555SGiannis Adamopoulos
1807b3fb8555SGiannis Adamopoulos
1808b3fb8555SGiannis Adamopoulos /***********************************************************************
1809b3fb8555SGiannis Adamopoulos * LISTBOX_ResetContent
1810b3fb8555SGiannis Adamopoulos */
LISTBOX_ResetContent(LB_DESCR * descr)1811b3fb8555SGiannis Adamopoulos static void LISTBOX_ResetContent( LB_DESCR *descr )
1812b3fb8555SGiannis Adamopoulos {
1813b3fb8555SGiannis Adamopoulos INT i;
1814b3fb8555SGiannis Adamopoulos
1815*0707475fSJustin Miller if (!(descr->style & LBS_NODATA))
1816b3fb8555SGiannis Adamopoulos for (i = descr->nb_items - 1; i >= 0; i--) LISTBOX_DeleteItem(descr, i);
1817*0707475fSJustin Miller HeapFree( GetProcessHeap(), 0, descr->u.items );
1818b3fb8555SGiannis Adamopoulos descr->nb_items = 0;
1819b3fb8555SGiannis Adamopoulos descr->top_item = 0;
1820b3fb8555SGiannis Adamopoulos descr->selected_item = -1;
1821b3fb8555SGiannis Adamopoulos descr->focus_item = 0;
1822b3fb8555SGiannis Adamopoulos descr->anchor_item = -1;
1823*0707475fSJustin Miller descr->items_size = 0;
1824*0707475fSJustin Miller descr->u.items = NULL;
1825b3fb8555SGiannis Adamopoulos }
1826b3fb8555SGiannis Adamopoulos
1827b3fb8555SGiannis Adamopoulos
1828b3fb8555SGiannis Adamopoulos /***********************************************************************
1829b3fb8555SGiannis Adamopoulos * LISTBOX_SetCount
1830b3fb8555SGiannis Adamopoulos */
LISTBOX_SetCount(LB_DESCR * descr,UINT count)1831*0707475fSJustin Miller static LRESULT LISTBOX_SetCount( LB_DESCR *descr, UINT count )
1832b3fb8555SGiannis Adamopoulos {
1833*0707475fSJustin Miller UINT orig_num = descr->nb_items;
1834b3fb8555SGiannis Adamopoulos
1835*0707475fSJustin Miller if (!(descr->style & LBS_NODATA)) return LB_ERR;
1836*0707475fSJustin Miller
1837*0707475fSJustin Miller if (!resize_storage(descr, count))
1838*0707475fSJustin Miller return LB_ERRSPACE;
1839*0707475fSJustin Miller descr->nb_items = count;
1840*0707475fSJustin Miller
1841*0707475fSJustin Miller if (count)
1842b3fb8555SGiannis Adamopoulos {
1843*0707475fSJustin Miller LISTBOX_UpdateScroll(descr);
1844*0707475fSJustin Miller if (count < orig_num)
1845*0707475fSJustin Miller {
1846*0707475fSJustin Miller descr->anchor_item = min(descr->anchor_item, count - 1);
1847*0707475fSJustin Miller if (descr->selected_item >= count)
1848*0707475fSJustin Miller descr->selected_item = -1;
1849*0707475fSJustin Miller
1850*0707475fSJustin Miller /* If we removed the scrollbar, reset the top of the list */
1851*0707475fSJustin Miller if (count <= descr->page_size && orig_num > descr->page_size)
1852*0707475fSJustin Miller LISTBOX_SetTopItem(descr, 0, TRUE);
1853*0707475fSJustin Miller
1854*0707475fSJustin Miller descr->focus_item = min(descr->focus_item, count - 1);
1855b3fb8555SGiannis Adamopoulos }
1856b3fb8555SGiannis Adamopoulos
1857*0707475fSJustin Miller /* If it was empty before growing, set focus to the first item */
1858*0707475fSJustin Miller else if (orig_num == 0) LISTBOX_SetCaretIndex(descr, 0, FALSE);
1859b3fb8555SGiannis Adamopoulos }
1860*0707475fSJustin Miller else SendMessageW(descr->self, LB_RESETCONTENT, 0, 0);
1861b3fb8555SGiannis Adamopoulos
1862b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, NULL, TRUE );
1863b3fb8555SGiannis Adamopoulos return LB_OKAY;
1864b3fb8555SGiannis Adamopoulos }
1865b3fb8555SGiannis Adamopoulos
1866b3fb8555SGiannis Adamopoulos
1867b3fb8555SGiannis Adamopoulos /***********************************************************************
1868b3fb8555SGiannis Adamopoulos * LISTBOX_Directory
1869b3fb8555SGiannis Adamopoulos */
LISTBOX_Directory(LB_DESCR * descr,UINT attrib,LPCWSTR filespec,BOOL long_names)1870b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_Directory( LB_DESCR *descr, UINT attrib,
1871b3fb8555SGiannis Adamopoulos LPCWSTR filespec, BOOL long_names )
1872b3fb8555SGiannis Adamopoulos {
1873b3fb8555SGiannis Adamopoulos HANDLE handle;
1874b3fb8555SGiannis Adamopoulos LRESULT ret = LB_OKAY;
1875b3fb8555SGiannis Adamopoulos WIN32_FIND_DATAW entry;
1876b3fb8555SGiannis Adamopoulos int pos;
1877b3fb8555SGiannis Adamopoulos LRESULT maxinsert = LB_ERR;
1878b3fb8555SGiannis Adamopoulos
1879b3fb8555SGiannis Adamopoulos /* don't scan directory if we just want drives exclusively */
1880b3fb8555SGiannis Adamopoulos if (attrib != (DDL_DRIVES | DDL_EXCLUSIVE)) {
1881b3fb8555SGiannis Adamopoulos /* scan directory */
1882b3fb8555SGiannis Adamopoulos if ((handle = FindFirstFileW(filespec, &entry)) == INVALID_HANDLE_VALUE)
1883b3fb8555SGiannis Adamopoulos {
1884b3fb8555SGiannis Adamopoulos int le = GetLastError();
1885b3fb8555SGiannis Adamopoulos if ((le != ERROR_NO_MORE_FILES) && (le != ERROR_FILE_NOT_FOUND)) return LB_ERR;
1886b3fb8555SGiannis Adamopoulos }
1887b3fb8555SGiannis Adamopoulos else
1888b3fb8555SGiannis Adamopoulos {
1889b3fb8555SGiannis Adamopoulos do
1890b3fb8555SGiannis Adamopoulos {
1891b3fb8555SGiannis Adamopoulos WCHAR buffer[270];
1892b3fb8555SGiannis Adamopoulos if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1893b3fb8555SGiannis Adamopoulos {
1894b3fb8555SGiannis Adamopoulos static const WCHAR bracketW[] = { ']',0 };
1895b3fb8555SGiannis Adamopoulos static const WCHAR dotW[] = { '.',0 };
1896b3fb8555SGiannis Adamopoulos if (!(attrib & DDL_DIRECTORY) ||
1897*0707475fSJustin Miller !lstrcmpW( entry.cFileName, dotW )) continue;
1898b3fb8555SGiannis Adamopoulos buffer[0] = '[';
1899b3fb8555SGiannis Adamopoulos if (!long_names && entry.cAlternateFileName[0])
1900*0707475fSJustin Miller lstrcpyW( buffer + 1, entry.cAlternateFileName );
1901b3fb8555SGiannis Adamopoulos else
1902*0707475fSJustin Miller lstrcpyW( buffer + 1, entry.cFileName );
1903*0707475fSJustin Miller lstrcatW(buffer, bracketW);
1904b3fb8555SGiannis Adamopoulos }
1905b3fb8555SGiannis Adamopoulos else /* not a directory */
1906b3fb8555SGiannis Adamopoulos {
1907b3fb8555SGiannis Adamopoulos #define ATTRIBS (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
1908b3fb8555SGiannis Adamopoulos FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE)
1909b3fb8555SGiannis Adamopoulos
1910b3fb8555SGiannis Adamopoulos if ((attrib & DDL_EXCLUSIVE) &&
1911b3fb8555SGiannis Adamopoulos ((attrib & ATTRIBS) != (entry.dwFileAttributes & ATTRIBS)))
1912b3fb8555SGiannis Adamopoulos continue;
1913b3fb8555SGiannis Adamopoulos #undef ATTRIBS
1914b3fb8555SGiannis Adamopoulos if (!long_names && entry.cAlternateFileName[0])
1915*0707475fSJustin Miller lstrcpyW( buffer, entry.cAlternateFileName );
1916b3fb8555SGiannis Adamopoulos else
1917*0707475fSJustin Miller lstrcpyW( buffer, entry.cFileName );
1918b3fb8555SGiannis Adamopoulos }
1919b3fb8555SGiannis Adamopoulos if (!long_names) CharLowerW( buffer );
1920b3fb8555SGiannis Adamopoulos pos = LISTBOX_FindFileStrPos( descr, buffer );
1921b3fb8555SGiannis Adamopoulos if ((ret = LISTBOX_InsertString( descr, pos, buffer )) < 0)
1922b3fb8555SGiannis Adamopoulos break;
1923b3fb8555SGiannis Adamopoulos if (ret <= maxinsert) maxinsert++; else maxinsert = ret;
1924b3fb8555SGiannis Adamopoulos } while (FindNextFileW( handle, &entry ));
1925b3fb8555SGiannis Adamopoulos FindClose( handle );
1926b3fb8555SGiannis Adamopoulos }
1927b3fb8555SGiannis Adamopoulos }
1928b3fb8555SGiannis Adamopoulos if (ret >= 0)
1929b3fb8555SGiannis Adamopoulos {
1930b3fb8555SGiannis Adamopoulos ret = maxinsert;
1931b3fb8555SGiannis Adamopoulos
1932b3fb8555SGiannis Adamopoulos /* scan drives */
1933b3fb8555SGiannis Adamopoulos if (attrib & DDL_DRIVES)
1934b3fb8555SGiannis Adamopoulos {
1935b3fb8555SGiannis Adamopoulos WCHAR buffer[] = {'[','-','a','-',']',0};
1936b3fb8555SGiannis Adamopoulos WCHAR root[] = {'A',':','\\',0};
1937b3fb8555SGiannis Adamopoulos int drive;
1938b3fb8555SGiannis Adamopoulos for (drive = 0; drive < 26; drive++, buffer[2]++, root[0]++)
1939b3fb8555SGiannis Adamopoulos {
1940b3fb8555SGiannis Adamopoulos if (GetDriveTypeW(root) <= DRIVE_NO_ROOT_DIR) continue;
1941b3fb8555SGiannis Adamopoulos if ((ret = LISTBOX_InsertString( descr, -1, buffer )) < 0)
1942b3fb8555SGiannis Adamopoulos break;
1943b3fb8555SGiannis Adamopoulos }
1944b3fb8555SGiannis Adamopoulos }
1945b3fb8555SGiannis Adamopoulos }
1946b3fb8555SGiannis Adamopoulos return ret;
1947b3fb8555SGiannis Adamopoulos }
1948b3fb8555SGiannis Adamopoulos
1949b3fb8555SGiannis Adamopoulos
1950b3fb8555SGiannis Adamopoulos /***********************************************************************
1951b3fb8555SGiannis Adamopoulos * LISTBOX_HandleVScroll
1952b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleVScroll(LB_DESCR * descr,WORD scrollReq,WORD pos)1953b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleVScroll( LB_DESCR *descr, WORD scrollReq, WORD pos )
1954b3fb8555SGiannis Adamopoulos {
1955b3fb8555SGiannis Adamopoulos SCROLLINFO info;
1956b3fb8555SGiannis Adamopoulos
1957b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN) return 0;
1958b3fb8555SGiannis Adamopoulos switch(scrollReq)
1959b3fb8555SGiannis Adamopoulos {
1960b3fb8555SGiannis Adamopoulos case SB_LINEUP:
1961b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->top_item - 1, TRUE );
1962b3fb8555SGiannis Adamopoulos break;
1963b3fb8555SGiannis Adamopoulos case SB_LINEDOWN:
1964b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->top_item + 1, TRUE );
1965b3fb8555SGiannis Adamopoulos break;
1966b3fb8555SGiannis Adamopoulos case SB_PAGEUP:
1967b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->top_item -
1968b3fb8555SGiannis Adamopoulos LISTBOX_GetCurrentPageSize( descr ), TRUE );
1969b3fb8555SGiannis Adamopoulos break;
1970b3fb8555SGiannis Adamopoulos case SB_PAGEDOWN:
1971b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->top_item +
1972b3fb8555SGiannis Adamopoulos LISTBOX_GetCurrentPageSize( descr ), TRUE );
1973b3fb8555SGiannis Adamopoulos break;
1974b3fb8555SGiannis Adamopoulos case SB_THUMBPOSITION:
1975b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, pos, TRUE );
1976b3fb8555SGiannis Adamopoulos break;
1977b3fb8555SGiannis Adamopoulos case SB_THUMBTRACK:
1978b3fb8555SGiannis Adamopoulos info.cbSize = sizeof(info);
1979b3fb8555SGiannis Adamopoulos info.fMask = SIF_TRACKPOS;
1980b3fb8555SGiannis Adamopoulos GetScrollInfo( descr->self, SB_VERT, &info );
1981b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, info.nTrackPos, TRUE );
1982b3fb8555SGiannis Adamopoulos break;
1983b3fb8555SGiannis Adamopoulos case SB_TOP:
1984b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, 0, TRUE );
1985b3fb8555SGiannis Adamopoulos break;
1986b3fb8555SGiannis Adamopoulos case SB_BOTTOM:
1987b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
1988b3fb8555SGiannis Adamopoulos break;
1989b3fb8555SGiannis Adamopoulos }
1990b3fb8555SGiannis Adamopoulos return 0;
1991b3fb8555SGiannis Adamopoulos }
1992b3fb8555SGiannis Adamopoulos
1993b3fb8555SGiannis Adamopoulos
1994b3fb8555SGiannis Adamopoulos /***********************************************************************
1995b3fb8555SGiannis Adamopoulos * LISTBOX_HandleHScroll
1996b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleHScroll(LB_DESCR * descr,WORD scrollReq,WORD pos)1997b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleHScroll( LB_DESCR *descr, WORD scrollReq, WORD pos )
1998b3fb8555SGiannis Adamopoulos {
1999b3fb8555SGiannis Adamopoulos SCROLLINFO info;
2000b3fb8555SGiannis Adamopoulos INT page;
2001b3fb8555SGiannis Adamopoulos
2002b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
2003b3fb8555SGiannis Adamopoulos {
2004b3fb8555SGiannis Adamopoulos switch(scrollReq)
2005b3fb8555SGiannis Adamopoulos {
2006b3fb8555SGiannis Adamopoulos case SB_LINELEFT:
2007b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->top_item-descr->page_size,
2008b3fb8555SGiannis Adamopoulos TRUE );
2009b3fb8555SGiannis Adamopoulos break;
2010b3fb8555SGiannis Adamopoulos case SB_LINERIGHT:
2011b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->top_item+descr->page_size,
2012b3fb8555SGiannis Adamopoulos TRUE );
2013b3fb8555SGiannis Adamopoulos break;
2014b3fb8555SGiannis Adamopoulos case SB_PAGELEFT:
2015b3fb8555SGiannis Adamopoulos page = descr->width / descr->column_width;
2016b3fb8555SGiannis Adamopoulos if (page < 1) page = 1;
2017b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr,
2018b3fb8555SGiannis Adamopoulos descr->top_item - page * descr->page_size, TRUE );
2019b3fb8555SGiannis Adamopoulos break;
2020b3fb8555SGiannis Adamopoulos case SB_PAGERIGHT:
2021b3fb8555SGiannis Adamopoulos page = descr->width / descr->column_width;
2022b3fb8555SGiannis Adamopoulos if (page < 1) page = 1;
2023b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr,
2024b3fb8555SGiannis Adamopoulos descr->top_item + page * descr->page_size, TRUE );
2025b3fb8555SGiannis Adamopoulos break;
2026b3fb8555SGiannis Adamopoulos case SB_THUMBPOSITION:
2027b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, pos*descr->page_size, TRUE );
2028b3fb8555SGiannis Adamopoulos break;
2029b3fb8555SGiannis Adamopoulos case SB_THUMBTRACK:
2030b3fb8555SGiannis Adamopoulos info.cbSize = sizeof(info);
2031b3fb8555SGiannis Adamopoulos info.fMask = SIF_TRACKPOS;
2032b3fb8555SGiannis Adamopoulos GetScrollInfo( descr->self, SB_VERT, &info );
2033b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, info.nTrackPos*descr->page_size,
2034b3fb8555SGiannis Adamopoulos TRUE );
2035b3fb8555SGiannis Adamopoulos break;
2036b3fb8555SGiannis Adamopoulos case SB_LEFT:
2037b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, 0, TRUE );
2038b3fb8555SGiannis Adamopoulos break;
2039b3fb8555SGiannis Adamopoulos case SB_RIGHT:
2040b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
2041b3fb8555SGiannis Adamopoulos break;
2042b3fb8555SGiannis Adamopoulos }
2043b3fb8555SGiannis Adamopoulos }
2044b3fb8555SGiannis Adamopoulos else if (descr->horz_extent)
2045b3fb8555SGiannis Adamopoulos {
2046b3fb8555SGiannis Adamopoulos switch(scrollReq)
2047b3fb8555SGiannis Adamopoulos {
2048b3fb8555SGiannis Adamopoulos case SB_LINELEFT:
2049b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr, descr->horz_pos - 1 );
2050b3fb8555SGiannis Adamopoulos break;
2051b3fb8555SGiannis Adamopoulos case SB_LINERIGHT:
2052b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr, descr->horz_pos + 1 );
2053b3fb8555SGiannis Adamopoulos break;
2054b3fb8555SGiannis Adamopoulos case SB_PAGELEFT:
2055b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr,
2056b3fb8555SGiannis Adamopoulos descr->horz_pos - descr->width );
2057b3fb8555SGiannis Adamopoulos break;
2058b3fb8555SGiannis Adamopoulos case SB_PAGERIGHT:
2059b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr,
2060b3fb8555SGiannis Adamopoulos descr->horz_pos + descr->width );
2061b3fb8555SGiannis Adamopoulos break;
2062b3fb8555SGiannis Adamopoulos case SB_THUMBPOSITION:
2063b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr, pos );
2064b3fb8555SGiannis Adamopoulos break;
2065b3fb8555SGiannis Adamopoulos case SB_THUMBTRACK:
2066b3fb8555SGiannis Adamopoulos info.cbSize = sizeof(info);
2067b3fb8555SGiannis Adamopoulos info.fMask = SIF_TRACKPOS;
2068b3fb8555SGiannis Adamopoulos GetScrollInfo( descr->self, SB_HORZ, &info );
2069b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr, info.nTrackPos );
2070b3fb8555SGiannis Adamopoulos break;
2071b3fb8555SGiannis Adamopoulos case SB_LEFT:
2072b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr, 0 );
2073b3fb8555SGiannis Adamopoulos break;
2074b3fb8555SGiannis Adamopoulos case SB_RIGHT:
2075b3fb8555SGiannis Adamopoulos LISTBOX_SetHorizontalPos( descr,
2076b3fb8555SGiannis Adamopoulos descr->horz_extent - descr->width );
2077b3fb8555SGiannis Adamopoulos break;
2078b3fb8555SGiannis Adamopoulos }
2079b3fb8555SGiannis Adamopoulos }
2080b3fb8555SGiannis Adamopoulos return 0;
2081b3fb8555SGiannis Adamopoulos }
2082b3fb8555SGiannis Adamopoulos
LISTBOX_HandleMouseWheel(LB_DESCR * descr,SHORT delta)2083b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta )
2084b3fb8555SGiannis Adamopoulos {
2085*0707475fSJustin Miller INT pulScrollLines = 3;
2086b3fb8555SGiannis Adamopoulos
2087b3fb8555SGiannis Adamopoulos SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
2088b3fb8555SGiannis Adamopoulos
2089b3fb8555SGiannis Adamopoulos /* if scrolling changes direction, ignore left overs */
2090b3fb8555SGiannis Adamopoulos if ((delta < 0 && descr->wheel_remain < 0) ||
2091b3fb8555SGiannis Adamopoulos (delta > 0 && descr->wheel_remain > 0))
2092b3fb8555SGiannis Adamopoulos descr->wheel_remain += delta;
2093b3fb8555SGiannis Adamopoulos else
2094b3fb8555SGiannis Adamopoulos descr->wheel_remain = delta;
2095b3fb8555SGiannis Adamopoulos
2096b3fb8555SGiannis Adamopoulos if (descr->wheel_remain && pulScrollLines)
2097b3fb8555SGiannis Adamopoulos {
2098b3fb8555SGiannis Adamopoulos int cLineScroll;
2099*0707475fSJustin Miller if (descr->style & LBS_MULTICOLUMN)
2100*0707475fSJustin Miller {
2101*0707475fSJustin Miller pulScrollLines = min(descr->width / descr->column_width, pulScrollLines);
2102*0707475fSJustin Miller pulScrollLines = max(1, pulScrollLines);
2103*0707475fSJustin Miller cLineScroll = pulScrollLines * descr->wheel_remain / WHEEL_DELTA;
2104*0707475fSJustin Miller descr->wheel_remain -= WHEEL_DELTA * cLineScroll / pulScrollLines;
2105*0707475fSJustin Miller cLineScroll *= descr->page_size;
2106*0707475fSJustin Miller }
2107*0707475fSJustin Miller else
2108*0707475fSJustin Miller {
2109*0707475fSJustin Miller pulScrollLines = min(descr->page_size, pulScrollLines);
2110*0707475fSJustin Miller cLineScroll = pulScrollLines * descr->wheel_remain / WHEEL_DELTA;
2111*0707475fSJustin Miller descr->wheel_remain -= WHEEL_DELTA * cLineScroll / pulScrollLines;
2112*0707475fSJustin Miller }
2113b3fb8555SGiannis Adamopoulos LISTBOX_SetTopItem( descr, descr->top_item - cLineScroll, TRUE );
2114b3fb8555SGiannis Adamopoulos }
2115b3fb8555SGiannis Adamopoulos return 0;
2116b3fb8555SGiannis Adamopoulos }
2117b3fb8555SGiannis Adamopoulos
2118b3fb8555SGiannis Adamopoulos /***********************************************************************
2119b3fb8555SGiannis Adamopoulos * LISTBOX_HandleLButtonDown
2120b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleLButtonDown(LB_DESCR * descr,DWORD keys,INT x,INT y)2121b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleLButtonDown( LB_DESCR *descr, DWORD keys, INT x, INT y )
2122b3fb8555SGiannis Adamopoulos {
2123b3fb8555SGiannis Adamopoulos INT index = LISTBOX_GetItemFromPoint( descr, x, y );
2124b3fb8555SGiannis Adamopoulos
2125b3fb8555SGiannis Adamopoulos TRACE("[%p]: lbuttondown %d,%d item %d, focus item %d\n",
2126b3fb8555SGiannis Adamopoulos descr->self, x, y, index, descr->focus_item);
2127b3fb8555SGiannis Adamopoulos
2128b3fb8555SGiannis Adamopoulos if (!descr->caret_on && (descr->in_focus)) return 0;
2129b3fb8555SGiannis Adamopoulos
2130b3fb8555SGiannis Adamopoulos if (!descr->in_focus)
2131b3fb8555SGiannis Adamopoulos {
2132b3fb8555SGiannis Adamopoulos if( !descr->lphc ) SetFocus( descr->self );
2133b3fb8555SGiannis Adamopoulos else SetFocus( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit : descr->lphc->self );
2134b3fb8555SGiannis Adamopoulos }
2135b3fb8555SGiannis Adamopoulos
2136b3fb8555SGiannis Adamopoulos if (index == -1) return 0;
2137b3fb8555SGiannis Adamopoulos
2138b3fb8555SGiannis Adamopoulos if (!descr->lphc)
2139b3fb8555SGiannis Adamopoulos {
2140b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOTIFY )
2141b3fb8555SGiannis Adamopoulos SendMessageW( descr->owner, WM_LBTRACKPOINT, index,
2142b3fb8555SGiannis Adamopoulos MAKELPARAM( x, y ) );
2143b3fb8555SGiannis Adamopoulos }
2144b3fb8555SGiannis Adamopoulos
2145b3fb8555SGiannis Adamopoulos descr->captured = TRUE;
2146b3fb8555SGiannis Adamopoulos SetCapture( descr->self );
2147b3fb8555SGiannis Adamopoulos
2148b3fb8555SGiannis Adamopoulos if (descr->style & (LBS_EXTENDEDSEL | LBS_MULTIPLESEL))
2149b3fb8555SGiannis Adamopoulos {
2150b3fb8555SGiannis Adamopoulos /* we should perhaps make sure that all items are deselected
2151b3fb8555SGiannis Adamopoulos FIXME: needed for !LBS_EXTENDEDSEL, too ?
2152b3fb8555SGiannis Adamopoulos if (!(keys & (MK_SHIFT|MK_CONTROL)))
2153b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, -1, FALSE, FALSE);
2154b3fb8555SGiannis Adamopoulos */
2155b3fb8555SGiannis Adamopoulos
2156b3fb8555SGiannis Adamopoulos if (!(keys & MK_SHIFT)) descr->anchor_item = index;
2157b3fb8555SGiannis Adamopoulos if (keys & MK_CONTROL)
2158b3fb8555SGiannis Adamopoulos {
2159b3fb8555SGiannis Adamopoulos LISTBOX_SetCaretIndex( descr, index, FALSE );
2160b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, index,
2161*0707475fSJustin Miller !is_item_selected(descr, index),
2162b3fb8555SGiannis Adamopoulos (descr->style & LBS_NOTIFY) != 0);
2163b3fb8555SGiannis Adamopoulos }
2164b3fb8555SGiannis Adamopoulos else
2165b3fb8555SGiannis Adamopoulos {
2166b3fb8555SGiannis Adamopoulos LISTBOX_MoveCaret( descr, index, FALSE );
2167b3fb8555SGiannis Adamopoulos
2168b3fb8555SGiannis Adamopoulos if (descr->style & LBS_EXTENDEDSEL)
2169b3fb8555SGiannis Adamopoulos {
2170b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, index,
2171*0707475fSJustin Miller is_item_selected(descr, index),
2172b3fb8555SGiannis Adamopoulos (descr->style & LBS_NOTIFY) != 0 );
2173b3fb8555SGiannis Adamopoulos }
2174b3fb8555SGiannis Adamopoulos else
2175b3fb8555SGiannis Adamopoulos {
2176b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, index,
2177*0707475fSJustin Miller !is_item_selected(descr, index),
2178b3fb8555SGiannis Adamopoulos (descr->style & LBS_NOTIFY) != 0 );
2179b3fb8555SGiannis Adamopoulos }
2180b3fb8555SGiannis Adamopoulos }
2181b3fb8555SGiannis Adamopoulos }
2182b3fb8555SGiannis Adamopoulos else
2183b3fb8555SGiannis Adamopoulos {
2184b3fb8555SGiannis Adamopoulos descr->anchor_item = index;
2185b3fb8555SGiannis Adamopoulos LISTBOX_MoveCaret( descr, index, FALSE );
2186b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, index,
2187b3fb8555SGiannis Adamopoulos TRUE, (descr->style & LBS_NOTIFY) != 0 );
2188b3fb8555SGiannis Adamopoulos }
2189b3fb8555SGiannis Adamopoulos
2190b3fb8555SGiannis Adamopoulos if (!descr->lphc)
2191b3fb8555SGiannis Adamopoulos {
2192b3fb8555SGiannis Adamopoulos if (GetWindowLongW( descr->self, GWL_EXSTYLE ) & WS_EX_DRAGDETECT)
2193b3fb8555SGiannis Adamopoulos {
2194b3fb8555SGiannis Adamopoulos POINT pt;
2195b3fb8555SGiannis Adamopoulos
2196b3fb8555SGiannis Adamopoulos pt.x = x;
2197b3fb8555SGiannis Adamopoulos pt.y = y;
2198b3fb8555SGiannis Adamopoulos
2199b3fb8555SGiannis Adamopoulos if (DragDetect( descr->self, pt ))
2200b3fb8555SGiannis Adamopoulos SendMessageW( descr->owner, WM_BEGINDRAG, 0, 0 );
2201b3fb8555SGiannis Adamopoulos }
2202b3fb8555SGiannis Adamopoulos }
2203b3fb8555SGiannis Adamopoulos return 0;
2204b3fb8555SGiannis Adamopoulos }
2205b3fb8555SGiannis Adamopoulos
2206b3fb8555SGiannis Adamopoulos
2207b3fb8555SGiannis Adamopoulos /*************************************************************************
2208b3fb8555SGiannis Adamopoulos * LISTBOX_HandleLButtonDownCombo [Internal]
2209b3fb8555SGiannis Adamopoulos *
2210b3fb8555SGiannis Adamopoulos * Process LButtonDown message for the ComboListBox
2211b3fb8555SGiannis Adamopoulos *
2212b3fb8555SGiannis Adamopoulos * PARAMS
2213b3fb8555SGiannis Adamopoulos * pWnd [I] The windows internal structure
2214b3fb8555SGiannis Adamopoulos * pDescr [I] The ListBox internal structure
2215b3fb8555SGiannis Adamopoulos * keys [I] Key Flag (WM_LBUTTONDOWN doc for more info)
2216b3fb8555SGiannis Adamopoulos * x [I] X Mouse Coordinate
2217b3fb8555SGiannis Adamopoulos * y [I] Y Mouse Coordinate
2218b3fb8555SGiannis Adamopoulos *
2219b3fb8555SGiannis Adamopoulos * RETURNS
2220b3fb8555SGiannis Adamopoulos * 0 since we are processing the WM_LBUTTONDOWN Message
2221b3fb8555SGiannis Adamopoulos *
2222b3fb8555SGiannis Adamopoulos * NOTES
2223b3fb8555SGiannis Adamopoulos * This function is only to be used when a ListBox is a ComboListBox
2224b3fb8555SGiannis Adamopoulos */
2225b3fb8555SGiannis Adamopoulos
LISTBOX_HandleLButtonDownCombo(LB_DESCR * descr,UINT msg,DWORD keys,INT x,INT y)2226b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleLButtonDownCombo( LB_DESCR *descr, UINT msg, DWORD keys, INT x, INT y)
2227b3fb8555SGiannis Adamopoulos {
2228b3fb8555SGiannis Adamopoulos RECT clientRect, screenRect;
2229b3fb8555SGiannis Adamopoulos POINT mousePos;
2230b3fb8555SGiannis Adamopoulos
2231b3fb8555SGiannis Adamopoulos mousePos.x = x;
2232b3fb8555SGiannis Adamopoulos mousePos.y = y;
2233b3fb8555SGiannis Adamopoulos
2234b3fb8555SGiannis Adamopoulos GetClientRect(descr->self, &clientRect);
2235b3fb8555SGiannis Adamopoulos
2236b3fb8555SGiannis Adamopoulos if(PtInRect(&clientRect, mousePos))
2237b3fb8555SGiannis Adamopoulos {
2238b3fb8555SGiannis Adamopoulos /* MousePos is in client, resume normal processing */
2239b3fb8555SGiannis Adamopoulos if (msg == WM_LBUTTONDOWN)
2240b3fb8555SGiannis Adamopoulos {
2241b3fb8555SGiannis Adamopoulos descr->lphc->droppedIndex = descr->nb_items ? descr->selected_item : -1;
2242b3fb8555SGiannis Adamopoulos return LISTBOX_HandleLButtonDown( descr, keys, x, y);
2243b3fb8555SGiannis Adamopoulos }
2244b3fb8555SGiannis Adamopoulos else if (descr->style & LBS_NOTIFY)
2245b3fb8555SGiannis Adamopoulos SEND_NOTIFICATION( descr, LBN_DBLCLK );
2246b3fb8555SGiannis Adamopoulos }
2247b3fb8555SGiannis Adamopoulos else
2248b3fb8555SGiannis Adamopoulos {
2249b3fb8555SGiannis Adamopoulos POINT screenMousePos;
2250b3fb8555SGiannis Adamopoulos HWND hWndOldCapture;
2251b3fb8555SGiannis Adamopoulos
2252b3fb8555SGiannis Adamopoulos /* Check the Non-Client Area */
2253b3fb8555SGiannis Adamopoulos screenMousePos = mousePos;
2254b3fb8555SGiannis Adamopoulos hWndOldCapture = GetCapture();
2255b3fb8555SGiannis Adamopoulos ReleaseCapture();
2256b3fb8555SGiannis Adamopoulos GetWindowRect(descr->self, &screenRect);
2257b3fb8555SGiannis Adamopoulos ClientToScreen(descr->self, &screenMousePos);
2258b3fb8555SGiannis Adamopoulos
2259b3fb8555SGiannis Adamopoulos if(!PtInRect(&screenRect, screenMousePos))
2260b3fb8555SGiannis Adamopoulos {
2261b3fb8555SGiannis Adamopoulos LISTBOX_SetCaretIndex( descr, descr->lphc->droppedIndex, FALSE );
2262b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, descr->lphc->droppedIndex, FALSE, FALSE );
2263b3fb8555SGiannis Adamopoulos COMBO_FlipListbox( descr->lphc, FALSE, FALSE );
2264b3fb8555SGiannis Adamopoulos }
2265b3fb8555SGiannis Adamopoulos else
2266b3fb8555SGiannis Adamopoulos {
2267b3fb8555SGiannis Adamopoulos /* Check to see the NC is a scrollbar */
2268b3fb8555SGiannis Adamopoulos INT nHitTestType=0;
2269b3fb8555SGiannis Adamopoulos LONG style = GetWindowLongW( descr->self, GWL_STYLE );
2270b3fb8555SGiannis Adamopoulos /* Check Vertical scroll bar */
2271b3fb8555SGiannis Adamopoulos if (style & WS_VSCROLL)
2272b3fb8555SGiannis Adamopoulos {
2273b3fb8555SGiannis Adamopoulos clientRect.right += GetSystemMetrics(SM_CXVSCROLL);
2274b3fb8555SGiannis Adamopoulos if (PtInRect( &clientRect, mousePos ))
2275b3fb8555SGiannis Adamopoulos nHitTestType = HTVSCROLL;
2276b3fb8555SGiannis Adamopoulos }
2277b3fb8555SGiannis Adamopoulos /* Check horizontal scroll bar */
2278b3fb8555SGiannis Adamopoulos if (style & WS_HSCROLL)
2279b3fb8555SGiannis Adamopoulos {
2280b3fb8555SGiannis Adamopoulos clientRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
2281b3fb8555SGiannis Adamopoulos if (PtInRect( &clientRect, mousePos ))
2282b3fb8555SGiannis Adamopoulos nHitTestType = HTHSCROLL;
2283b3fb8555SGiannis Adamopoulos }
2284b3fb8555SGiannis Adamopoulos /* Windows sends this message when a scrollbar is clicked
2285b3fb8555SGiannis Adamopoulos */
2286b3fb8555SGiannis Adamopoulos
2287b3fb8555SGiannis Adamopoulos if(nHitTestType != 0)
2288b3fb8555SGiannis Adamopoulos {
2289b3fb8555SGiannis Adamopoulos SendMessageW(descr->self, WM_NCLBUTTONDOWN, nHitTestType,
2290b3fb8555SGiannis Adamopoulos MAKELONG(screenMousePos.x, screenMousePos.y));
2291b3fb8555SGiannis Adamopoulos }
2292b3fb8555SGiannis Adamopoulos /* Resume the Capture after scrolling is complete
2293b3fb8555SGiannis Adamopoulos */
2294b3fb8555SGiannis Adamopoulos if(hWndOldCapture != 0)
2295b3fb8555SGiannis Adamopoulos SetCapture(hWndOldCapture);
2296b3fb8555SGiannis Adamopoulos }
2297b3fb8555SGiannis Adamopoulos }
2298b3fb8555SGiannis Adamopoulos return 0;
2299b3fb8555SGiannis Adamopoulos }
2300b3fb8555SGiannis Adamopoulos
2301b3fb8555SGiannis Adamopoulos /***********************************************************************
2302b3fb8555SGiannis Adamopoulos * LISTBOX_HandleLButtonUp
2303b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleLButtonUp(LB_DESCR * descr)2304b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleLButtonUp( LB_DESCR *descr )
2305b3fb8555SGiannis Adamopoulos {
2306b3fb8555SGiannis Adamopoulos if (LISTBOX_Timer != LB_TIMER_NONE)
2307b3fb8555SGiannis Adamopoulos KillSystemTimer( descr->self, LB_TIMER_ID );
2308b3fb8555SGiannis Adamopoulos LISTBOX_Timer = LB_TIMER_NONE;
2309b3fb8555SGiannis Adamopoulos if (descr->captured)
2310b3fb8555SGiannis Adamopoulos {
2311b3fb8555SGiannis Adamopoulos descr->captured = FALSE;
2312b3fb8555SGiannis Adamopoulos if (GetCapture() == descr->self) ReleaseCapture();
2313b3fb8555SGiannis Adamopoulos if ((descr->style & LBS_NOTIFY) && descr->nb_items)
2314b3fb8555SGiannis Adamopoulos SEND_NOTIFICATION( descr, LBN_SELCHANGE );
2315b3fb8555SGiannis Adamopoulos }
2316b3fb8555SGiannis Adamopoulos return 0;
2317b3fb8555SGiannis Adamopoulos }
2318b3fb8555SGiannis Adamopoulos
2319b3fb8555SGiannis Adamopoulos
2320b3fb8555SGiannis Adamopoulos /***********************************************************************
2321b3fb8555SGiannis Adamopoulos * LISTBOX_HandleTimer
2322b3fb8555SGiannis Adamopoulos *
2323b3fb8555SGiannis Adamopoulos * Handle scrolling upon a timer event.
2324b3fb8555SGiannis Adamopoulos * Return TRUE if scrolling should continue.
2325b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleTimer(LB_DESCR * descr,INT index,TIMER_DIRECTION dir)2326b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleTimer( LB_DESCR *descr, INT index, TIMER_DIRECTION dir )
2327b3fb8555SGiannis Adamopoulos {
2328b3fb8555SGiannis Adamopoulos switch(dir)
2329b3fb8555SGiannis Adamopoulos {
2330b3fb8555SGiannis Adamopoulos case LB_TIMER_UP:
2331b3fb8555SGiannis Adamopoulos if (descr->top_item) index = descr->top_item - 1;
2332b3fb8555SGiannis Adamopoulos else index = 0;
2333b3fb8555SGiannis Adamopoulos break;
2334b3fb8555SGiannis Adamopoulos case LB_TIMER_LEFT:
2335b3fb8555SGiannis Adamopoulos if (descr->top_item) index -= descr->page_size;
2336b3fb8555SGiannis Adamopoulos break;
2337b3fb8555SGiannis Adamopoulos case LB_TIMER_DOWN:
2338b3fb8555SGiannis Adamopoulos index = descr->top_item + LISTBOX_GetCurrentPageSize( descr );
2339b3fb8555SGiannis Adamopoulos if (index == descr->focus_item) index++;
2340b3fb8555SGiannis Adamopoulos if (index >= descr->nb_items) index = descr->nb_items - 1;
2341b3fb8555SGiannis Adamopoulos break;
2342b3fb8555SGiannis Adamopoulos case LB_TIMER_RIGHT:
2343b3fb8555SGiannis Adamopoulos if (index + descr->page_size < descr->nb_items)
2344b3fb8555SGiannis Adamopoulos index += descr->page_size;
2345b3fb8555SGiannis Adamopoulos break;
2346b3fb8555SGiannis Adamopoulos case LB_TIMER_NONE:
2347b3fb8555SGiannis Adamopoulos break;
2348b3fb8555SGiannis Adamopoulos }
2349b3fb8555SGiannis Adamopoulos if (index == descr->focus_item) return FALSE;
2350b3fb8555SGiannis Adamopoulos LISTBOX_MoveCaret( descr, index, FALSE );
2351b3fb8555SGiannis Adamopoulos return TRUE;
2352b3fb8555SGiannis Adamopoulos }
2353b3fb8555SGiannis Adamopoulos
2354b3fb8555SGiannis Adamopoulos
2355b3fb8555SGiannis Adamopoulos /***********************************************************************
2356b3fb8555SGiannis Adamopoulos * LISTBOX_HandleSystemTimer
2357b3fb8555SGiannis Adamopoulos *
2358b3fb8555SGiannis Adamopoulos * WM_SYSTIMER handler.
2359b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleSystemTimer(LB_DESCR * descr)2360b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleSystemTimer( LB_DESCR *descr )
2361b3fb8555SGiannis Adamopoulos {
2362b3fb8555SGiannis Adamopoulos if (!LISTBOX_HandleTimer( descr, descr->focus_item, LISTBOX_Timer ))
2363b3fb8555SGiannis Adamopoulos {
2364b3fb8555SGiannis Adamopoulos KillSystemTimer( descr->self, LB_TIMER_ID );
2365b3fb8555SGiannis Adamopoulos LISTBOX_Timer = LB_TIMER_NONE;
2366b3fb8555SGiannis Adamopoulos }
2367b3fb8555SGiannis Adamopoulos return 0;
2368b3fb8555SGiannis Adamopoulos }
2369b3fb8555SGiannis Adamopoulos
2370b3fb8555SGiannis Adamopoulos
2371b3fb8555SGiannis Adamopoulos /***********************************************************************
2372b3fb8555SGiannis Adamopoulos * LISTBOX_HandleMouseMove
2373b3fb8555SGiannis Adamopoulos *
2374b3fb8555SGiannis Adamopoulos * WM_MOUSEMOVE handler.
2375b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleMouseMove(LB_DESCR * descr,INT x,INT y)2376b3fb8555SGiannis Adamopoulos static void LISTBOX_HandleMouseMove( LB_DESCR *descr,
2377b3fb8555SGiannis Adamopoulos INT x, INT y )
2378b3fb8555SGiannis Adamopoulos {
2379b3fb8555SGiannis Adamopoulos INT index;
2380b3fb8555SGiannis Adamopoulos TIMER_DIRECTION dir = LB_TIMER_NONE;
2381b3fb8555SGiannis Adamopoulos
2382b3fb8555SGiannis Adamopoulos if (!descr->captured) return;
2383b3fb8555SGiannis Adamopoulos
2384b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
2385b3fb8555SGiannis Adamopoulos {
2386b3fb8555SGiannis Adamopoulos if (y < 0) y = 0;
2387b3fb8555SGiannis Adamopoulos else if (y >= descr->item_height * descr->page_size)
2388b3fb8555SGiannis Adamopoulos y = descr->item_height * descr->page_size - 1;
2389b3fb8555SGiannis Adamopoulos
2390b3fb8555SGiannis Adamopoulos if (x < 0)
2391b3fb8555SGiannis Adamopoulos {
2392b3fb8555SGiannis Adamopoulos dir = LB_TIMER_LEFT;
2393b3fb8555SGiannis Adamopoulos x = 0;
2394b3fb8555SGiannis Adamopoulos }
2395b3fb8555SGiannis Adamopoulos else if (x >= descr->width)
2396b3fb8555SGiannis Adamopoulos {
2397b3fb8555SGiannis Adamopoulos dir = LB_TIMER_RIGHT;
2398b3fb8555SGiannis Adamopoulos x = descr->width - 1;
2399b3fb8555SGiannis Adamopoulos }
2400b3fb8555SGiannis Adamopoulos }
2401b3fb8555SGiannis Adamopoulos else
2402b3fb8555SGiannis Adamopoulos {
2403b3fb8555SGiannis Adamopoulos if (y < 0) dir = LB_TIMER_UP; /* above */
2404b3fb8555SGiannis Adamopoulos else if (y >= descr->height) dir = LB_TIMER_DOWN; /* below */
2405b3fb8555SGiannis Adamopoulos }
2406b3fb8555SGiannis Adamopoulos
2407b3fb8555SGiannis Adamopoulos index = LISTBOX_GetItemFromPoint( descr, x, y );
2408b3fb8555SGiannis Adamopoulos if (index == -1) index = descr->focus_item;
2409b3fb8555SGiannis Adamopoulos if (!LISTBOX_HandleTimer( descr, index, dir )) dir = LB_TIMER_NONE;
2410b3fb8555SGiannis Adamopoulos
2411b3fb8555SGiannis Adamopoulos /* Start/stop the system timer */
2412b3fb8555SGiannis Adamopoulos
2413b3fb8555SGiannis Adamopoulos if (dir != LB_TIMER_NONE)
2414b3fb8555SGiannis Adamopoulos SetSystemTimer( descr->self, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
2415b3fb8555SGiannis Adamopoulos else if (LISTBOX_Timer != LB_TIMER_NONE)
2416b3fb8555SGiannis Adamopoulos KillSystemTimer( descr->self, LB_TIMER_ID );
2417b3fb8555SGiannis Adamopoulos LISTBOX_Timer = dir;
2418b3fb8555SGiannis Adamopoulos }
2419b3fb8555SGiannis Adamopoulos
2420b3fb8555SGiannis Adamopoulos
2421b3fb8555SGiannis Adamopoulos /***********************************************************************
2422b3fb8555SGiannis Adamopoulos * LISTBOX_HandleKeyDown
2423b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleKeyDown(LB_DESCR * descr,DWORD key)2424b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleKeyDown( LB_DESCR *descr, DWORD key )
2425b3fb8555SGiannis Adamopoulos {
2426b3fb8555SGiannis Adamopoulos INT caret = -1;
2427b3fb8555SGiannis Adamopoulos BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */
2428b3fb8555SGiannis Adamopoulos if ((IS_MULTISELECT(descr)) || (descr->selected_item == descr->focus_item))
2429b3fb8555SGiannis Adamopoulos bForceSelection = FALSE; /* only for single select list */
2430b3fb8555SGiannis Adamopoulos
2431b3fb8555SGiannis Adamopoulos if (descr->style & LBS_WANTKEYBOARDINPUT)
2432b3fb8555SGiannis Adamopoulos {
2433b3fb8555SGiannis Adamopoulos caret = SendMessageW( descr->owner, WM_VKEYTOITEM,
2434b3fb8555SGiannis Adamopoulos MAKEWPARAM(LOWORD(key), descr->focus_item),
2435b3fb8555SGiannis Adamopoulos (LPARAM)descr->self );
2436b3fb8555SGiannis Adamopoulos if (caret == -2) return 0;
2437b3fb8555SGiannis Adamopoulos }
2438b3fb8555SGiannis Adamopoulos if (caret == -1) switch(key)
2439b3fb8555SGiannis Adamopoulos {
2440b3fb8555SGiannis Adamopoulos case VK_LEFT:
2441b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
2442b3fb8555SGiannis Adamopoulos {
2443b3fb8555SGiannis Adamopoulos bForceSelection = FALSE;
2444b3fb8555SGiannis Adamopoulos if (descr->focus_item >= descr->page_size)
2445b3fb8555SGiannis Adamopoulos caret = descr->focus_item - descr->page_size;
2446b3fb8555SGiannis Adamopoulos break;
2447b3fb8555SGiannis Adamopoulos }
2448b3fb8555SGiannis Adamopoulos /* fall through */
2449b3fb8555SGiannis Adamopoulos case VK_UP:
2450b3fb8555SGiannis Adamopoulos caret = descr->focus_item - 1;
2451b3fb8555SGiannis Adamopoulos if (caret < 0) caret = 0;
2452b3fb8555SGiannis Adamopoulos break;
2453b3fb8555SGiannis Adamopoulos case VK_RIGHT:
2454b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
2455b3fb8555SGiannis Adamopoulos {
2456b3fb8555SGiannis Adamopoulos bForceSelection = FALSE;
2457*0707475fSJustin Miller caret = min(descr->focus_item + descr->page_size, descr->nb_items - 1);
2458b3fb8555SGiannis Adamopoulos break;
2459b3fb8555SGiannis Adamopoulos }
2460b3fb8555SGiannis Adamopoulos /* fall through */
2461b3fb8555SGiannis Adamopoulos case VK_DOWN:
2462b3fb8555SGiannis Adamopoulos caret = descr->focus_item + 1;
2463b3fb8555SGiannis Adamopoulos if (caret >= descr->nb_items) caret = descr->nb_items - 1;
2464b3fb8555SGiannis Adamopoulos break;
2465b3fb8555SGiannis Adamopoulos
2466b3fb8555SGiannis Adamopoulos case VK_PRIOR:
2467b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
2468b3fb8555SGiannis Adamopoulos {
2469b3fb8555SGiannis Adamopoulos INT page = descr->width / descr->column_width;
2470b3fb8555SGiannis Adamopoulos if (page < 1) page = 1;
2471b3fb8555SGiannis Adamopoulos caret = descr->focus_item - (page * descr->page_size) + 1;
2472b3fb8555SGiannis Adamopoulos }
2473b3fb8555SGiannis Adamopoulos else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(descr) + 1;
2474b3fb8555SGiannis Adamopoulos if (caret < 0) caret = 0;
2475b3fb8555SGiannis Adamopoulos break;
2476b3fb8555SGiannis Adamopoulos case VK_NEXT:
2477b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN)
2478b3fb8555SGiannis Adamopoulos {
2479b3fb8555SGiannis Adamopoulos INT page = descr->width / descr->column_width;
2480b3fb8555SGiannis Adamopoulos if (page < 1) page = 1;
2481b3fb8555SGiannis Adamopoulos caret = descr->focus_item + (page * descr->page_size) - 1;
2482b3fb8555SGiannis Adamopoulos }
2483b3fb8555SGiannis Adamopoulos else caret = descr->focus_item + LISTBOX_GetCurrentPageSize(descr) - 1;
2484b3fb8555SGiannis Adamopoulos if (caret >= descr->nb_items) caret = descr->nb_items - 1;
2485b3fb8555SGiannis Adamopoulos break;
2486b3fb8555SGiannis Adamopoulos case VK_HOME:
2487b3fb8555SGiannis Adamopoulos caret = 0;
2488b3fb8555SGiannis Adamopoulos break;
2489b3fb8555SGiannis Adamopoulos case VK_END:
2490b3fb8555SGiannis Adamopoulos caret = descr->nb_items - 1;
2491b3fb8555SGiannis Adamopoulos break;
2492b3fb8555SGiannis Adamopoulos case VK_SPACE:
2493b3fb8555SGiannis Adamopoulos if (descr->style & LBS_EXTENDEDSEL) caret = descr->focus_item;
2494b3fb8555SGiannis Adamopoulos else if (descr->style & LBS_MULTIPLESEL)
2495b3fb8555SGiannis Adamopoulos {
2496b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, descr->focus_item,
2497*0707475fSJustin Miller !is_item_selected(descr, descr->focus_item),
2498b3fb8555SGiannis Adamopoulos (descr->style & LBS_NOTIFY) != 0 );
2499b3fb8555SGiannis Adamopoulos }
2500b3fb8555SGiannis Adamopoulos break;
2501b3fb8555SGiannis Adamopoulos default:
2502b3fb8555SGiannis Adamopoulos bForceSelection = FALSE;
2503b3fb8555SGiannis Adamopoulos }
2504b3fb8555SGiannis Adamopoulos if (bForceSelection) /* focused item is used instead of key */
2505b3fb8555SGiannis Adamopoulos caret = descr->focus_item;
2506b3fb8555SGiannis Adamopoulos if (caret >= 0)
2507b3fb8555SGiannis Adamopoulos {
2508b3fb8555SGiannis Adamopoulos if (((descr->style & LBS_EXTENDEDSEL) &&
2509b3fb8555SGiannis Adamopoulos !(GetKeyState( VK_SHIFT ) & 0x8000)) ||
2510b3fb8555SGiannis Adamopoulos !IS_MULTISELECT(descr))
2511b3fb8555SGiannis Adamopoulos descr->anchor_item = caret;
2512b3fb8555SGiannis Adamopoulos LISTBOX_MoveCaret( descr, caret, TRUE );
2513b3fb8555SGiannis Adamopoulos
2514b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTIPLESEL)
2515b3fb8555SGiannis Adamopoulos descr->selected_item = caret;
2516b3fb8555SGiannis Adamopoulos else
2517b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, caret, TRUE, FALSE);
2518b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOTIFY)
2519b3fb8555SGiannis Adamopoulos {
2520b3fb8555SGiannis Adamopoulos if (descr->lphc && IsWindowVisible( descr->self ))
2521b3fb8555SGiannis Adamopoulos {
2522b3fb8555SGiannis Adamopoulos /* make sure that combo parent doesn't hide us */
2523b3fb8555SGiannis Adamopoulos descr->lphc->wState |= CBF_NOROLLUP;
2524b3fb8555SGiannis Adamopoulos }
2525b3fb8555SGiannis Adamopoulos if (descr->nb_items) SEND_NOTIFICATION( descr, LBN_SELCHANGE );
2526b3fb8555SGiannis Adamopoulos }
2527b3fb8555SGiannis Adamopoulos }
2528b3fb8555SGiannis Adamopoulos return 0;
2529b3fb8555SGiannis Adamopoulos }
2530b3fb8555SGiannis Adamopoulos
2531b3fb8555SGiannis Adamopoulos
2532b3fb8555SGiannis Adamopoulos /***********************************************************************
2533b3fb8555SGiannis Adamopoulos * LISTBOX_HandleChar
2534b3fb8555SGiannis Adamopoulos */
LISTBOX_HandleChar(LB_DESCR * descr,WCHAR charW)2535b3fb8555SGiannis Adamopoulos static LRESULT LISTBOX_HandleChar( LB_DESCR *descr, WCHAR charW )
2536b3fb8555SGiannis Adamopoulos {
2537b3fb8555SGiannis Adamopoulos INT caret = -1;
2538b3fb8555SGiannis Adamopoulos WCHAR str[2];
2539b3fb8555SGiannis Adamopoulos
2540b3fb8555SGiannis Adamopoulos str[0] = charW;
2541b3fb8555SGiannis Adamopoulos str[1] = '\0';
2542b3fb8555SGiannis Adamopoulos
2543b3fb8555SGiannis Adamopoulos if (descr->style & LBS_WANTKEYBOARDINPUT)
2544b3fb8555SGiannis Adamopoulos {
2545b3fb8555SGiannis Adamopoulos caret = SendMessageW( descr->owner, WM_CHARTOITEM,
2546b3fb8555SGiannis Adamopoulos MAKEWPARAM(charW, descr->focus_item),
2547b3fb8555SGiannis Adamopoulos (LPARAM)descr->self );
2548b3fb8555SGiannis Adamopoulos if (caret == -2) return 0;
2549b3fb8555SGiannis Adamopoulos }
2550b3fb8555SGiannis Adamopoulos if (caret == -1)
2551b3fb8555SGiannis Adamopoulos caret = LISTBOX_FindString( descr, descr->focus_item, str, FALSE);
2552b3fb8555SGiannis Adamopoulos if (caret != -1)
2553b3fb8555SGiannis Adamopoulos {
2554b3fb8555SGiannis Adamopoulos if ((!IS_MULTISELECT(descr)) && descr->selected_item == -1)
2555b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, caret, TRUE, FALSE);
2556b3fb8555SGiannis Adamopoulos LISTBOX_MoveCaret( descr, caret, TRUE );
2557b3fb8555SGiannis Adamopoulos if ((descr->style & LBS_NOTIFY) && descr->nb_items)
2558b3fb8555SGiannis Adamopoulos SEND_NOTIFICATION( descr, LBN_SELCHANGE );
2559b3fb8555SGiannis Adamopoulos }
2560b3fb8555SGiannis Adamopoulos return 0;
2561b3fb8555SGiannis Adamopoulos }
2562b3fb8555SGiannis Adamopoulos
2563b3fb8555SGiannis Adamopoulos
2564b3fb8555SGiannis Adamopoulos /***********************************************************************
2565b3fb8555SGiannis Adamopoulos * LISTBOX_Create
2566b3fb8555SGiannis Adamopoulos */
LISTBOX_Create(HWND hwnd,LPHEADCOMBO lphc)2567b3fb8555SGiannis Adamopoulos static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
2568b3fb8555SGiannis Adamopoulos {
2569b3fb8555SGiannis Adamopoulos LB_DESCR *descr;
2570b3fb8555SGiannis Adamopoulos MEASUREITEMSTRUCT mis;
2571b3fb8555SGiannis Adamopoulos RECT rect;
2572b3fb8555SGiannis Adamopoulos
2573b3fb8555SGiannis Adamopoulos if (!(descr = HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) )))
2574b3fb8555SGiannis Adamopoulos return FALSE;
2575b3fb8555SGiannis Adamopoulos
2576b3fb8555SGiannis Adamopoulos GetClientRect( hwnd, &rect );
2577b3fb8555SGiannis Adamopoulos descr->self = hwnd;
2578b3fb8555SGiannis Adamopoulos descr->owner = GetParent( descr->self );
2579b3fb8555SGiannis Adamopoulos descr->style = GetWindowLongW( descr->self, GWL_STYLE );
2580b3fb8555SGiannis Adamopoulos descr->width = rect.right - rect.left;
2581b3fb8555SGiannis Adamopoulos descr->height = rect.bottom - rect.top;
2582*0707475fSJustin Miller descr->u.items = NULL;
2583*0707475fSJustin Miller descr->items_size = 0;
2584b3fb8555SGiannis Adamopoulos descr->nb_items = 0;
2585b3fb8555SGiannis Adamopoulos descr->top_item = 0;
2586b3fb8555SGiannis Adamopoulos descr->selected_item = -1;
2587b3fb8555SGiannis Adamopoulos descr->focus_item = 0;
2588b3fb8555SGiannis Adamopoulos descr->anchor_item = -1;
2589b3fb8555SGiannis Adamopoulos descr->item_height = 1;
2590b3fb8555SGiannis Adamopoulos descr->page_size = 1;
2591b3fb8555SGiannis Adamopoulos descr->column_width = 150;
2592b3fb8555SGiannis Adamopoulos descr->horz_extent = 0;
2593b3fb8555SGiannis Adamopoulos descr->horz_pos = 0;
2594b3fb8555SGiannis Adamopoulos descr->nb_tabs = 0;
2595b3fb8555SGiannis Adamopoulos descr->tabs = NULL;
2596b3fb8555SGiannis Adamopoulos descr->wheel_remain = 0;
2597b3fb8555SGiannis Adamopoulos descr->caret_on = !lphc;
2598b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOSEL) descr->caret_on = FALSE;
2599b3fb8555SGiannis Adamopoulos descr->in_focus = FALSE;
2600b3fb8555SGiannis Adamopoulos descr->captured = FALSE;
2601b3fb8555SGiannis Adamopoulos descr->font = 0;
2602b3fb8555SGiannis Adamopoulos descr->locale = GetUserDefaultLCID();
2603b3fb8555SGiannis Adamopoulos descr->lphc = lphc;
2604b3fb8555SGiannis Adamopoulos
2605b3fb8555SGiannis Adamopoulos if( lphc )
2606b3fb8555SGiannis Adamopoulos {
2607b3fb8555SGiannis Adamopoulos TRACE("[%p]: resetting owner %p -> %p\n", descr->self, descr->owner, lphc->self );
2608b3fb8555SGiannis Adamopoulos descr->owner = lphc->self;
2609b3fb8555SGiannis Adamopoulos }
2610b3fb8555SGiannis Adamopoulos
2611b3fb8555SGiannis Adamopoulos SetWindowLongPtrW( descr->self, 0, (LONG_PTR)descr );
2612b3fb8555SGiannis Adamopoulos
2613b3fb8555SGiannis Adamopoulos /* if (wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) descr->style &= ~LBS_NOTIFY;
2614b3fb8555SGiannis Adamopoulos */
2615b3fb8555SGiannis Adamopoulos if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
2616b3fb8555SGiannis Adamopoulos if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
2617b3fb8555SGiannis Adamopoulos if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
2618*0707475fSJustin Miller if ((descr->style & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_SORT)) != LBS_OWNERDRAWFIXED)
2619*0707475fSJustin Miller descr->style &= ~LBS_NODATA;
2620b3fb8555SGiannis Adamopoulos descr->item_height = LISTBOX_SetFont( descr, 0 );
2621b3fb8555SGiannis Adamopoulos
2622b3fb8555SGiannis Adamopoulos if (descr->style & LBS_OWNERDRAWFIXED)
2623b3fb8555SGiannis Adamopoulos {
2624*0707475fSJustin Miller descr->style &= ~LBS_OWNERDRAWVARIABLE;
2625*0707475fSJustin Miller
2626b3fb8555SGiannis Adamopoulos if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
2627b3fb8555SGiannis Adamopoulos {
2628b3fb8555SGiannis Adamopoulos /* WinWord gets VERY unhappy if we send WM_MEASUREITEM from here */
2629b3fb8555SGiannis Adamopoulos descr->item_height = lphc->fixedOwnerDrawHeight;
2630b3fb8555SGiannis Adamopoulos }
2631b3fb8555SGiannis Adamopoulos else
2632b3fb8555SGiannis Adamopoulos {
2633b3fb8555SGiannis Adamopoulos UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
2634b3fb8555SGiannis Adamopoulos mis.CtlType = ODT_LISTBOX;
2635b3fb8555SGiannis Adamopoulos mis.CtlID = id;
2636b3fb8555SGiannis Adamopoulos mis.itemID = -1;
2637b3fb8555SGiannis Adamopoulos mis.itemWidth = 0;
2638b3fb8555SGiannis Adamopoulos mis.itemData = 0;
2639b3fb8555SGiannis Adamopoulos mis.itemHeight = descr->item_height;
2640b3fb8555SGiannis Adamopoulos SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
2641b3fb8555SGiannis Adamopoulos descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
2642b3fb8555SGiannis Adamopoulos }
2643b3fb8555SGiannis Adamopoulos }
2644b3fb8555SGiannis Adamopoulos
2645b3fb8555SGiannis Adamopoulos OpenThemeData( descr->self, WC_LISTBOXW );
2646b3fb8555SGiannis Adamopoulos
2647b3fb8555SGiannis Adamopoulos TRACE("owner: %p, style: %08x, width: %d, height: %d\n", descr->owner, descr->style, descr->width, descr->height);
2648b3fb8555SGiannis Adamopoulos return TRUE;
2649b3fb8555SGiannis Adamopoulos }
2650b3fb8555SGiannis Adamopoulos
2651b3fb8555SGiannis Adamopoulos
2652b3fb8555SGiannis Adamopoulos /***********************************************************************
2653b3fb8555SGiannis Adamopoulos * LISTBOX_Destroy
2654b3fb8555SGiannis Adamopoulos */
LISTBOX_Destroy(LB_DESCR * descr)2655b3fb8555SGiannis Adamopoulos static BOOL LISTBOX_Destroy( LB_DESCR *descr )
2656b3fb8555SGiannis Adamopoulos {
2657b3fb8555SGiannis Adamopoulos HTHEME theme = GetWindowTheme( descr->self );
2658b3fb8555SGiannis Adamopoulos CloseThemeData( theme );
2659b3fb8555SGiannis Adamopoulos LISTBOX_ResetContent( descr );
2660b3fb8555SGiannis Adamopoulos SetWindowLongPtrW( descr->self, 0, 0 );
2661b3fb8555SGiannis Adamopoulos HeapFree( GetProcessHeap(), 0, descr );
2662b3fb8555SGiannis Adamopoulos return TRUE;
2663b3fb8555SGiannis Adamopoulos }
2664b3fb8555SGiannis Adamopoulos
2665b3fb8555SGiannis Adamopoulos
2666b3fb8555SGiannis Adamopoulos /***********************************************************************
2667b3fb8555SGiannis Adamopoulos * ListBoxWndProc_common
2668b3fb8555SGiannis Adamopoulos */
LISTBOX_WindowProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)2669b3fb8555SGiannis Adamopoulos static LRESULT CALLBACK LISTBOX_WindowProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
2670b3fb8555SGiannis Adamopoulos {
2671b3fb8555SGiannis Adamopoulos LB_DESCR *descr = (LB_DESCR *)GetWindowLongPtrW( hwnd, 0 );
2672b3fb8555SGiannis Adamopoulos HEADCOMBO *lphc = NULL;
2673b3fb8555SGiannis Adamopoulos HTHEME theme;
2674b3fb8555SGiannis Adamopoulos LRESULT ret;
2675b3fb8555SGiannis Adamopoulos
2676b3fb8555SGiannis Adamopoulos if (!descr)
2677b3fb8555SGiannis Adamopoulos {
2678b3fb8555SGiannis Adamopoulos if (!IsWindow(hwnd)) return 0;
2679b3fb8555SGiannis Adamopoulos
2680b3fb8555SGiannis Adamopoulos if (msg == WM_CREATE)
2681b3fb8555SGiannis Adamopoulos {
2682b3fb8555SGiannis Adamopoulos CREATESTRUCTW *lpcs = (CREATESTRUCTW *)lParam;
2683b3fb8555SGiannis Adamopoulos if (lpcs->style & LBS_COMBOBOX) lphc = lpcs->lpCreateParams;
2684b3fb8555SGiannis Adamopoulos if (!LISTBOX_Create( hwnd, lphc )) return -1;
2685b3fb8555SGiannis Adamopoulos TRACE("creating hwnd %p descr %p\n", hwnd, (void *)GetWindowLongPtrW( hwnd, 0 ) );
2686b3fb8555SGiannis Adamopoulos return 0;
2687b3fb8555SGiannis Adamopoulos }
2688b3fb8555SGiannis Adamopoulos /* Ignore all other messages before we get a WM_CREATE */
2689b3fb8555SGiannis Adamopoulos return DefWindowProcW( hwnd, msg, wParam, lParam );
2690b3fb8555SGiannis Adamopoulos }
2691b3fb8555SGiannis Adamopoulos if (descr->style & LBS_COMBOBOX) lphc = descr->lphc;
2692b3fb8555SGiannis Adamopoulos
2693b3fb8555SGiannis Adamopoulos TRACE("[%p]: msg %#x wp %08lx lp %08lx\n", descr->self, msg, wParam, lParam );
2694b3fb8555SGiannis Adamopoulos
2695b3fb8555SGiannis Adamopoulos switch(msg)
2696b3fb8555SGiannis Adamopoulos {
2697b3fb8555SGiannis Adamopoulos case LB_RESETCONTENT:
2698b3fb8555SGiannis Adamopoulos LISTBOX_ResetContent( descr );
2699b3fb8555SGiannis Adamopoulos LISTBOX_UpdateScroll( descr );
2700b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, NULL, TRUE );
2701b3fb8555SGiannis Adamopoulos return 0;
2702b3fb8555SGiannis Adamopoulos
2703b3fb8555SGiannis Adamopoulos case LB_ADDSTRING:
2704b3fb8555SGiannis Adamopoulos {
2705b3fb8555SGiannis Adamopoulos const WCHAR *textW = (const WCHAR *)lParam;
2706b3fb8555SGiannis Adamopoulos INT index = LISTBOX_FindStringPos( descr, textW, FALSE );
2707b3fb8555SGiannis Adamopoulos return LISTBOX_InsertString( descr, index, textW );
2708b3fb8555SGiannis Adamopoulos }
2709b3fb8555SGiannis Adamopoulos
2710b3fb8555SGiannis Adamopoulos case LB_INSERTSTRING:
2711b3fb8555SGiannis Adamopoulos return LISTBOX_InsertString( descr, wParam, (const WCHAR *)lParam );
2712b3fb8555SGiannis Adamopoulos
2713b3fb8555SGiannis Adamopoulos case LB_ADDFILE:
2714b3fb8555SGiannis Adamopoulos {
2715b3fb8555SGiannis Adamopoulos const WCHAR *textW = (const WCHAR *)lParam;
2716b3fb8555SGiannis Adamopoulos INT index = LISTBOX_FindFileStrPos( descr, textW );
2717b3fb8555SGiannis Adamopoulos return LISTBOX_InsertString( descr, index, textW );
2718b3fb8555SGiannis Adamopoulos }
2719b3fb8555SGiannis Adamopoulos
2720b3fb8555SGiannis Adamopoulos case LB_DELETESTRING:
2721b3fb8555SGiannis Adamopoulos if (LISTBOX_RemoveItem( descr, wParam) != LB_ERR)
2722b3fb8555SGiannis Adamopoulos return descr->nb_items;
2723b3fb8555SGiannis Adamopoulos else
2724b3fb8555SGiannis Adamopoulos {
2725b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
2726b3fb8555SGiannis Adamopoulos return LB_ERR;
2727b3fb8555SGiannis Adamopoulos }
2728b3fb8555SGiannis Adamopoulos
2729b3fb8555SGiannis Adamopoulos case LB_GETITEMDATA:
2730b3fb8555SGiannis Adamopoulos if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2731b3fb8555SGiannis Adamopoulos {
2732b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
2733b3fb8555SGiannis Adamopoulos return LB_ERR;
2734b3fb8555SGiannis Adamopoulos }
2735*0707475fSJustin Miller return get_item_data(descr, wParam);
2736b3fb8555SGiannis Adamopoulos
2737b3fb8555SGiannis Adamopoulos case LB_SETITEMDATA:
2738b3fb8555SGiannis Adamopoulos if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2739b3fb8555SGiannis Adamopoulos {
2740b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
2741b3fb8555SGiannis Adamopoulos return LB_ERR;
2742b3fb8555SGiannis Adamopoulos }
2743*0707475fSJustin Miller set_item_data(descr, wParam, lParam);
2744b3fb8555SGiannis Adamopoulos /* undocumented: returns TRUE, not LB_OKAY (0) */
2745b3fb8555SGiannis Adamopoulos return TRUE;
2746b3fb8555SGiannis Adamopoulos
2747b3fb8555SGiannis Adamopoulos case LB_GETCOUNT:
2748b3fb8555SGiannis Adamopoulos return descr->nb_items;
2749b3fb8555SGiannis Adamopoulos
2750b3fb8555SGiannis Adamopoulos case LB_GETTEXT:
2751b3fb8555SGiannis Adamopoulos return LISTBOX_GetText( descr, wParam, (LPWSTR)lParam, TRUE );
2752b3fb8555SGiannis Adamopoulos
2753b3fb8555SGiannis Adamopoulos case LB_GETTEXTLEN:
2754b3fb8555SGiannis Adamopoulos if ((INT)wParam >= descr->nb_items || (INT)wParam < 0)
2755b3fb8555SGiannis Adamopoulos {
2756b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
2757b3fb8555SGiannis Adamopoulos return LB_ERR;
2758b3fb8555SGiannis Adamopoulos }
2759*0707475fSJustin Miller if (!HAS_STRINGS(descr)) return sizeof(ULONG_PTR);
2760*0707475fSJustin Miller return lstrlenW(get_item_string(descr, wParam));
2761b3fb8555SGiannis Adamopoulos
2762b3fb8555SGiannis Adamopoulos case LB_GETCURSEL:
2763b3fb8555SGiannis Adamopoulos if (descr->nb_items == 0)
2764b3fb8555SGiannis Adamopoulos return LB_ERR;
2765b3fb8555SGiannis Adamopoulos if (!IS_MULTISELECT(descr))
2766b3fb8555SGiannis Adamopoulos return descr->selected_item;
2767b3fb8555SGiannis Adamopoulos if (descr->selected_item != -1)
2768b3fb8555SGiannis Adamopoulos return descr->selected_item;
2769b3fb8555SGiannis Adamopoulos return descr->focus_item;
2770b3fb8555SGiannis Adamopoulos /* otherwise, if the user tries to move the selection with the */
2771b3fb8555SGiannis Adamopoulos /* arrow keys, we will give the application something to choke on */
2772b3fb8555SGiannis Adamopoulos case LB_GETTOPINDEX:
2773b3fb8555SGiannis Adamopoulos return descr->top_item;
2774b3fb8555SGiannis Adamopoulos
2775b3fb8555SGiannis Adamopoulos case LB_GETITEMHEIGHT:
2776b3fb8555SGiannis Adamopoulos return LISTBOX_GetItemHeight( descr, wParam );
2777b3fb8555SGiannis Adamopoulos
2778b3fb8555SGiannis Adamopoulos case LB_SETITEMHEIGHT:
2779b3fb8555SGiannis Adamopoulos return LISTBOX_SetItemHeight( descr, wParam, lParam, TRUE );
2780b3fb8555SGiannis Adamopoulos
2781b3fb8555SGiannis Adamopoulos case LB_ITEMFROMPOINT:
2782b3fb8555SGiannis Adamopoulos {
2783b3fb8555SGiannis Adamopoulos POINT pt;
2784b3fb8555SGiannis Adamopoulos RECT rect;
2785b3fb8555SGiannis Adamopoulos int index;
2786b3fb8555SGiannis Adamopoulos BOOL hit = TRUE;
2787b3fb8555SGiannis Adamopoulos
2788b3fb8555SGiannis Adamopoulos /* The hiword of the return value is not a client area
2789b3fb8555SGiannis Adamopoulos hittest as suggested by MSDN, but rather a hittest on
2790b3fb8555SGiannis Adamopoulos the returned listbox item. */
2791b3fb8555SGiannis Adamopoulos
2792b3fb8555SGiannis Adamopoulos if(descr->nb_items == 0)
2793b3fb8555SGiannis Adamopoulos return 0x1ffff; /* win9x returns 0x10000, we copy winnt */
2794b3fb8555SGiannis Adamopoulos
2795b3fb8555SGiannis Adamopoulos pt.x = (short)LOWORD(lParam);
2796b3fb8555SGiannis Adamopoulos pt.y = (short)HIWORD(lParam);
2797b3fb8555SGiannis Adamopoulos
2798b3fb8555SGiannis Adamopoulos SetRect(&rect, 0, 0, descr->width, descr->height);
2799b3fb8555SGiannis Adamopoulos
2800b3fb8555SGiannis Adamopoulos if(!PtInRect(&rect, pt))
2801b3fb8555SGiannis Adamopoulos {
2802b3fb8555SGiannis Adamopoulos pt.x = min(pt.x, rect.right - 1);
2803b3fb8555SGiannis Adamopoulos pt.x = max(pt.x, 0);
2804b3fb8555SGiannis Adamopoulos pt.y = min(pt.y, rect.bottom - 1);
2805b3fb8555SGiannis Adamopoulos pt.y = max(pt.y, 0);
2806b3fb8555SGiannis Adamopoulos hit = FALSE;
2807b3fb8555SGiannis Adamopoulos }
2808b3fb8555SGiannis Adamopoulos
2809b3fb8555SGiannis Adamopoulos index = LISTBOX_GetItemFromPoint(descr, pt.x, pt.y);
2810b3fb8555SGiannis Adamopoulos
2811b3fb8555SGiannis Adamopoulos if(index == -1)
2812b3fb8555SGiannis Adamopoulos {
2813b3fb8555SGiannis Adamopoulos index = descr->nb_items - 1;
2814b3fb8555SGiannis Adamopoulos hit = FALSE;
2815b3fb8555SGiannis Adamopoulos }
2816b3fb8555SGiannis Adamopoulos return MAKELONG(index, hit ? 0 : 1);
2817b3fb8555SGiannis Adamopoulos }
2818b3fb8555SGiannis Adamopoulos
2819b3fb8555SGiannis Adamopoulos case LB_SETCARETINDEX:
2820b3fb8555SGiannis Adamopoulos if ((!IS_MULTISELECT(descr)) && (descr->selected_item != -1)) return LB_ERR;
2821b3fb8555SGiannis Adamopoulos if (LISTBOX_SetCaretIndex( descr, wParam, !lParam ) == LB_ERR)
2822b3fb8555SGiannis Adamopoulos return LB_ERR;
2823b3fb8555SGiannis Adamopoulos else if (ISWIN31)
2824b3fb8555SGiannis Adamopoulos return wParam;
2825b3fb8555SGiannis Adamopoulos else
2826b3fb8555SGiannis Adamopoulos return LB_OKAY;
2827b3fb8555SGiannis Adamopoulos
2828b3fb8555SGiannis Adamopoulos case LB_GETCARETINDEX:
2829b3fb8555SGiannis Adamopoulos return descr->focus_item;
2830b3fb8555SGiannis Adamopoulos
2831b3fb8555SGiannis Adamopoulos case LB_SETTOPINDEX:
2832b3fb8555SGiannis Adamopoulos return LISTBOX_SetTopItem( descr, wParam, TRUE );
2833b3fb8555SGiannis Adamopoulos
2834b3fb8555SGiannis Adamopoulos case LB_SETCOLUMNWIDTH:
2835b3fb8555SGiannis Adamopoulos return LISTBOX_SetColumnWidth( descr, wParam );
2836b3fb8555SGiannis Adamopoulos
2837b3fb8555SGiannis Adamopoulos case LB_GETITEMRECT:
2838b3fb8555SGiannis Adamopoulos return LISTBOX_GetItemRect( descr, wParam, (RECT *)lParam );
2839b3fb8555SGiannis Adamopoulos
2840b3fb8555SGiannis Adamopoulos case LB_FINDSTRING:
2841b3fb8555SGiannis Adamopoulos return LISTBOX_FindString( descr, wParam, (const WCHAR *)lParam, FALSE );
2842b3fb8555SGiannis Adamopoulos
2843b3fb8555SGiannis Adamopoulos case LB_FINDSTRINGEXACT:
2844b3fb8555SGiannis Adamopoulos return LISTBOX_FindString( descr, wParam, (const WCHAR *)lParam, TRUE );
2845b3fb8555SGiannis Adamopoulos
2846b3fb8555SGiannis Adamopoulos case LB_SELECTSTRING:
2847b3fb8555SGiannis Adamopoulos {
2848b3fb8555SGiannis Adamopoulos const WCHAR *textW = (const WCHAR *)lParam;
2849b3fb8555SGiannis Adamopoulos INT index;
2850b3fb8555SGiannis Adamopoulos
2851b3fb8555SGiannis Adamopoulos if (HAS_STRINGS(descr))
2852b3fb8555SGiannis Adamopoulos TRACE("LB_SELECTSTRING: %s\n", debugstr_w(textW));
2853b3fb8555SGiannis Adamopoulos
2854b3fb8555SGiannis Adamopoulos index = LISTBOX_FindString( descr, wParam, textW, FALSE );
2855b3fb8555SGiannis Adamopoulos if (index != LB_ERR)
2856b3fb8555SGiannis Adamopoulos {
2857b3fb8555SGiannis Adamopoulos LISTBOX_MoveCaret( descr, index, TRUE );
2858b3fb8555SGiannis Adamopoulos LISTBOX_SetSelection( descr, index, TRUE, FALSE );
2859b3fb8555SGiannis Adamopoulos }
2860b3fb8555SGiannis Adamopoulos return index;
2861b3fb8555SGiannis Adamopoulos }
2862b3fb8555SGiannis Adamopoulos
2863b3fb8555SGiannis Adamopoulos case LB_GETSEL:
2864b3fb8555SGiannis Adamopoulos if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2865b3fb8555SGiannis Adamopoulos return LB_ERR;
2866*0707475fSJustin Miller return is_item_selected(descr, wParam);
2867b3fb8555SGiannis Adamopoulos
2868b3fb8555SGiannis Adamopoulos case LB_SETSEL:
2869*0707475fSJustin Miller ret = LISTBOX_SetSelection( descr, lParam, wParam, FALSE );
2870*0707475fSJustin Miller if (ret != LB_ERR && wParam)
2871*0707475fSJustin Miller {
2872*0707475fSJustin Miller descr->anchor_item = lParam;
2873*0707475fSJustin Miller if (lParam != -1)
2874*0707475fSJustin Miller LISTBOX_SetCaretIndex( descr, lParam, TRUE );
2875*0707475fSJustin Miller }
2876*0707475fSJustin Miller return ret;
2877b3fb8555SGiannis Adamopoulos
2878b3fb8555SGiannis Adamopoulos case LB_SETCURSEL:
2879b3fb8555SGiannis Adamopoulos if (IS_MULTISELECT(descr)) return LB_ERR;
2880b3fb8555SGiannis Adamopoulos LISTBOX_SetCaretIndex( descr, wParam, TRUE );
2881b3fb8555SGiannis Adamopoulos ret = LISTBOX_SetSelection( descr, wParam, TRUE, FALSE );
2882b3fb8555SGiannis Adamopoulos if (ret != LB_ERR) ret = descr->selected_item;
2883b3fb8555SGiannis Adamopoulos return ret;
2884b3fb8555SGiannis Adamopoulos
2885b3fb8555SGiannis Adamopoulos case LB_GETSELCOUNT:
2886b3fb8555SGiannis Adamopoulos return LISTBOX_GetSelCount( descr );
2887b3fb8555SGiannis Adamopoulos
2888b3fb8555SGiannis Adamopoulos case LB_GETSELITEMS:
2889b3fb8555SGiannis Adamopoulos return LISTBOX_GetSelItems( descr, wParam, (LPINT)lParam );
2890b3fb8555SGiannis Adamopoulos
2891b3fb8555SGiannis Adamopoulos case LB_SELITEMRANGE:
2892b3fb8555SGiannis Adamopoulos if (LOWORD(lParam) <= HIWORD(lParam))
2893b3fb8555SGiannis Adamopoulos return LISTBOX_SelectItemRange( descr, LOWORD(lParam),
2894b3fb8555SGiannis Adamopoulos HIWORD(lParam), wParam );
2895b3fb8555SGiannis Adamopoulos else
2896b3fb8555SGiannis Adamopoulos return LISTBOX_SelectItemRange( descr, HIWORD(lParam),
2897b3fb8555SGiannis Adamopoulos LOWORD(lParam), wParam );
2898b3fb8555SGiannis Adamopoulos
2899b3fb8555SGiannis Adamopoulos case LB_SELITEMRANGEEX:
2900b3fb8555SGiannis Adamopoulos if ((INT)lParam >= (INT)wParam)
2901b3fb8555SGiannis Adamopoulos return LISTBOX_SelectItemRange( descr, wParam, lParam, TRUE );
2902b3fb8555SGiannis Adamopoulos else
2903b3fb8555SGiannis Adamopoulos return LISTBOX_SelectItemRange( descr, lParam, wParam, FALSE);
2904b3fb8555SGiannis Adamopoulos
2905b3fb8555SGiannis Adamopoulos case LB_GETHORIZONTALEXTENT:
2906b3fb8555SGiannis Adamopoulos return descr->horz_extent;
2907b3fb8555SGiannis Adamopoulos
2908b3fb8555SGiannis Adamopoulos case LB_SETHORIZONTALEXTENT:
2909b3fb8555SGiannis Adamopoulos return LISTBOX_SetHorizontalExtent( descr, wParam );
2910b3fb8555SGiannis Adamopoulos
2911b3fb8555SGiannis Adamopoulos case LB_GETANCHORINDEX:
2912b3fb8555SGiannis Adamopoulos return descr->anchor_item;
2913b3fb8555SGiannis Adamopoulos
2914b3fb8555SGiannis Adamopoulos case LB_SETANCHORINDEX:
2915b3fb8555SGiannis Adamopoulos if (((INT)wParam < -1) || ((INT)wParam >= descr->nb_items))
2916b3fb8555SGiannis Adamopoulos {
2917b3fb8555SGiannis Adamopoulos SetLastError(ERROR_INVALID_INDEX);
2918b3fb8555SGiannis Adamopoulos return LB_ERR;
2919b3fb8555SGiannis Adamopoulos }
2920b3fb8555SGiannis Adamopoulos descr->anchor_item = (INT)wParam;
2921b3fb8555SGiannis Adamopoulos return LB_OKAY;
2922b3fb8555SGiannis Adamopoulos
2923b3fb8555SGiannis Adamopoulos case LB_DIR:
2924b3fb8555SGiannis Adamopoulos return LISTBOX_Directory( descr, wParam, (const WCHAR *)lParam, msg == LB_DIR );
2925b3fb8555SGiannis Adamopoulos
2926b3fb8555SGiannis Adamopoulos case LB_GETLOCALE:
2927b3fb8555SGiannis Adamopoulos return descr->locale;
2928b3fb8555SGiannis Adamopoulos
2929b3fb8555SGiannis Adamopoulos case LB_SETLOCALE:
2930b3fb8555SGiannis Adamopoulos {
2931b3fb8555SGiannis Adamopoulos LCID ret;
2932b3fb8555SGiannis Adamopoulos if (!IsValidLocale((LCID)wParam, LCID_INSTALLED))
2933b3fb8555SGiannis Adamopoulos return LB_ERR;
2934b3fb8555SGiannis Adamopoulos ret = descr->locale;
2935b3fb8555SGiannis Adamopoulos descr->locale = (LCID)wParam;
2936b3fb8555SGiannis Adamopoulos return ret;
2937b3fb8555SGiannis Adamopoulos }
2938b3fb8555SGiannis Adamopoulos
2939b3fb8555SGiannis Adamopoulos case LB_INITSTORAGE:
2940b3fb8555SGiannis Adamopoulos return LISTBOX_InitStorage( descr, wParam );
2941b3fb8555SGiannis Adamopoulos
2942b3fb8555SGiannis Adamopoulos case LB_SETCOUNT:
2943b3fb8555SGiannis Adamopoulos return LISTBOX_SetCount( descr, (INT)wParam );
2944b3fb8555SGiannis Adamopoulos
2945b3fb8555SGiannis Adamopoulos case LB_SETTABSTOPS:
2946b3fb8555SGiannis Adamopoulos return LISTBOX_SetTabStops( descr, wParam, (LPINT)lParam );
2947b3fb8555SGiannis Adamopoulos
2948b3fb8555SGiannis Adamopoulos case LB_CARETON:
2949b3fb8555SGiannis Adamopoulos if (descr->caret_on)
2950b3fb8555SGiannis Adamopoulos return LB_OKAY;
2951b3fb8555SGiannis Adamopoulos descr->caret_on = TRUE;
2952b3fb8555SGiannis Adamopoulos if ((descr->focus_item != -1) && (descr->in_focus))
2953b3fb8555SGiannis Adamopoulos LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
2954b3fb8555SGiannis Adamopoulos return LB_OKAY;
2955b3fb8555SGiannis Adamopoulos
2956b3fb8555SGiannis Adamopoulos case LB_CARETOFF:
2957b3fb8555SGiannis Adamopoulos if (!descr->caret_on)
2958b3fb8555SGiannis Adamopoulos return LB_OKAY;
2959b3fb8555SGiannis Adamopoulos descr->caret_on = FALSE;
2960b3fb8555SGiannis Adamopoulos if ((descr->focus_item != -1) && (descr->in_focus))
2961b3fb8555SGiannis Adamopoulos LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
2962b3fb8555SGiannis Adamopoulos return LB_OKAY;
2963b3fb8555SGiannis Adamopoulos
2964b3fb8555SGiannis Adamopoulos case LB_GETLISTBOXINFO:
2965b3fb8555SGiannis Adamopoulos return descr->page_size;
2966b3fb8555SGiannis Adamopoulos
2967b3fb8555SGiannis Adamopoulos case WM_DESTROY:
2968b3fb8555SGiannis Adamopoulos return LISTBOX_Destroy( descr );
2969b3fb8555SGiannis Adamopoulos
2970b3fb8555SGiannis Adamopoulos case WM_ENABLE:
2971b3fb8555SGiannis Adamopoulos InvalidateRect( descr->self, NULL, TRUE );
2972b3fb8555SGiannis Adamopoulos return 0;
2973b3fb8555SGiannis Adamopoulos
2974b3fb8555SGiannis Adamopoulos case WM_SETREDRAW:
2975b3fb8555SGiannis Adamopoulos LISTBOX_SetRedraw( descr, wParam != 0 );
2976b3fb8555SGiannis Adamopoulos return 0;
2977b3fb8555SGiannis Adamopoulos
2978b3fb8555SGiannis Adamopoulos case WM_GETDLGCODE:
2979b3fb8555SGiannis Adamopoulos return DLGC_WANTARROWS | DLGC_WANTCHARS;
2980b3fb8555SGiannis Adamopoulos
2981b3fb8555SGiannis Adamopoulos case WM_PRINTCLIENT:
2982b3fb8555SGiannis Adamopoulos case WM_PAINT:
2983b3fb8555SGiannis Adamopoulos {
2984b3fb8555SGiannis Adamopoulos PAINTSTRUCT ps;
2985b3fb8555SGiannis Adamopoulos HDC hdc = ( wParam ) ? ((HDC)wParam) : BeginPaint( descr->self, &ps );
2986b3fb8555SGiannis Adamopoulos ret = LISTBOX_Paint( descr, hdc );
2987b3fb8555SGiannis Adamopoulos if( !wParam ) EndPaint( descr->self, &ps );
2988b3fb8555SGiannis Adamopoulos }
2989b3fb8555SGiannis Adamopoulos return ret;
2990b3fb8555SGiannis Adamopoulos
2991b3fb8555SGiannis Adamopoulos case WM_NCPAINT:
2992b3fb8555SGiannis Adamopoulos LISTBOX_NCPaint( descr, (HRGN)wParam );
2993b3fb8555SGiannis Adamopoulos break;
2994b3fb8555SGiannis Adamopoulos
2995b3fb8555SGiannis Adamopoulos case WM_SIZE:
2996b3fb8555SGiannis Adamopoulos LISTBOX_UpdateSize( descr );
2997b3fb8555SGiannis Adamopoulos return 0;
2998b3fb8555SGiannis Adamopoulos case WM_GETFONT:
2999b3fb8555SGiannis Adamopoulos return (LRESULT)descr->font;
3000b3fb8555SGiannis Adamopoulos case WM_SETFONT:
3001b3fb8555SGiannis Adamopoulos LISTBOX_SetFont( descr, (HFONT)wParam );
3002b3fb8555SGiannis Adamopoulos if (lParam) InvalidateRect( descr->self, 0, TRUE );
3003b3fb8555SGiannis Adamopoulos return 0;
3004b3fb8555SGiannis Adamopoulos case WM_SETFOCUS:
3005b3fb8555SGiannis Adamopoulos descr->in_focus = TRUE;
3006b3fb8555SGiannis Adamopoulos descr->caret_on = TRUE;
3007b3fb8555SGiannis Adamopoulos if (descr->focus_item != -1)
3008b3fb8555SGiannis Adamopoulos LISTBOX_DrawFocusRect( descr, TRUE );
3009b3fb8555SGiannis Adamopoulos SEND_NOTIFICATION( descr, LBN_SETFOCUS );
3010b3fb8555SGiannis Adamopoulos return 0;
3011b3fb8555SGiannis Adamopoulos case WM_KILLFOCUS:
3012b3fb8555SGiannis Adamopoulos LISTBOX_HandleLButtonUp( descr ); /* Release capture if we have it */
3013b3fb8555SGiannis Adamopoulos descr->in_focus = FALSE;
3014b3fb8555SGiannis Adamopoulos descr->wheel_remain = 0;
3015b3fb8555SGiannis Adamopoulos if ((descr->focus_item != -1) && descr->caret_on)
3016b3fb8555SGiannis Adamopoulos LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
3017b3fb8555SGiannis Adamopoulos SEND_NOTIFICATION( descr, LBN_KILLFOCUS );
3018b3fb8555SGiannis Adamopoulos return 0;
3019b3fb8555SGiannis Adamopoulos case WM_HSCROLL:
3020b3fb8555SGiannis Adamopoulos return LISTBOX_HandleHScroll( descr, LOWORD(wParam), HIWORD(wParam) );
3021b3fb8555SGiannis Adamopoulos case WM_VSCROLL:
3022b3fb8555SGiannis Adamopoulos return LISTBOX_HandleVScroll( descr, LOWORD(wParam), HIWORD(wParam) );
3023b3fb8555SGiannis Adamopoulos case WM_MOUSEWHEEL:
3024b3fb8555SGiannis Adamopoulos if (wParam & (MK_SHIFT | MK_CONTROL))
3025b3fb8555SGiannis Adamopoulos return DefWindowProcW( descr->self, msg, wParam, lParam );
3026b3fb8555SGiannis Adamopoulos return LISTBOX_HandleMouseWheel( descr, (SHORT)HIWORD(wParam) );
3027b3fb8555SGiannis Adamopoulos case WM_LBUTTONDOWN:
3028b3fb8555SGiannis Adamopoulos if (lphc)
3029b3fb8555SGiannis Adamopoulos return LISTBOX_HandleLButtonDownCombo(descr, msg, wParam,
3030b3fb8555SGiannis Adamopoulos (INT16)LOWORD(lParam),
3031b3fb8555SGiannis Adamopoulos (INT16)HIWORD(lParam) );
3032b3fb8555SGiannis Adamopoulos return LISTBOX_HandleLButtonDown( descr, wParam,
3033b3fb8555SGiannis Adamopoulos (INT16)LOWORD(lParam),
3034b3fb8555SGiannis Adamopoulos (INT16)HIWORD(lParam) );
3035b3fb8555SGiannis Adamopoulos case WM_LBUTTONDBLCLK:
3036b3fb8555SGiannis Adamopoulos if (lphc)
3037b3fb8555SGiannis Adamopoulos return LISTBOX_HandleLButtonDownCombo(descr, msg, wParam,
3038b3fb8555SGiannis Adamopoulos (INT16)LOWORD(lParam),
3039b3fb8555SGiannis Adamopoulos (INT16)HIWORD(lParam) );
3040b3fb8555SGiannis Adamopoulos if (descr->style & LBS_NOTIFY)
3041b3fb8555SGiannis Adamopoulos SEND_NOTIFICATION( descr, LBN_DBLCLK );
3042b3fb8555SGiannis Adamopoulos return 0;
3043b3fb8555SGiannis Adamopoulos case WM_MOUSEMOVE:
3044b3fb8555SGiannis Adamopoulos if ( lphc && ((lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE) )
3045b3fb8555SGiannis Adamopoulos {
3046b3fb8555SGiannis Adamopoulos BOOL captured = descr->captured;
3047b3fb8555SGiannis Adamopoulos POINT mousePos;
3048b3fb8555SGiannis Adamopoulos RECT clientRect;
3049b3fb8555SGiannis Adamopoulos
3050b3fb8555SGiannis Adamopoulos mousePos.x = (INT16)LOWORD(lParam);
3051b3fb8555SGiannis Adamopoulos mousePos.y = (INT16)HIWORD(lParam);
3052b3fb8555SGiannis Adamopoulos
3053b3fb8555SGiannis Adamopoulos /*
3054b3fb8555SGiannis Adamopoulos * If we are in a dropdown combobox, we simulate that
3055b3fb8555SGiannis Adamopoulos * the mouse is captured to show the tracking of the item.
3056b3fb8555SGiannis Adamopoulos */
3057b3fb8555SGiannis Adamopoulos if (GetClientRect(descr->self, &clientRect) && PtInRect( &clientRect, mousePos ))
3058b3fb8555SGiannis Adamopoulos descr->captured = TRUE;
3059b3fb8555SGiannis Adamopoulos
3060b3fb8555SGiannis Adamopoulos LISTBOX_HandleMouseMove( descr, mousePos.x, mousePos.y);
3061b3fb8555SGiannis Adamopoulos
3062b3fb8555SGiannis Adamopoulos descr->captured = captured;
3063b3fb8555SGiannis Adamopoulos }
3064b3fb8555SGiannis Adamopoulos else if (GetCapture() == descr->self)
3065b3fb8555SGiannis Adamopoulos {
3066b3fb8555SGiannis Adamopoulos LISTBOX_HandleMouseMove( descr, (INT16)LOWORD(lParam),
3067b3fb8555SGiannis Adamopoulos (INT16)HIWORD(lParam) );
3068b3fb8555SGiannis Adamopoulos }
3069b3fb8555SGiannis Adamopoulos return 0;
3070b3fb8555SGiannis Adamopoulos case WM_LBUTTONUP:
3071b3fb8555SGiannis Adamopoulos if (lphc)
3072b3fb8555SGiannis Adamopoulos {
3073b3fb8555SGiannis Adamopoulos POINT mousePos;
3074b3fb8555SGiannis Adamopoulos RECT clientRect;
3075b3fb8555SGiannis Adamopoulos
3076b3fb8555SGiannis Adamopoulos /*
3077b3fb8555SGiannis Adamopoulos * If the mouse button "up" is not in the listbox,
3078b3fb8555SGiannis Adamopoulos * we make sure there is no selection by re-selecting the
3079b3fb8555SGiannis Adamopoulos * item that was selected when the listbox was made visible.
3080b3fb8555SGiannis Adamopoulos */
3081b3fb8555SGiannis Adamopoulos mousePos.x = (INT16)LOWORD(lParam);
3082b3fb8555SGiannis Adamopoulos mousePos.y = (INT16)HIWORD(lParam);
3083b3fb8555SGiannis Adamopoulos
3084b3fb8555SGiannis Adamopoulos GetClientRect(descr->self, &clientRect);
3085b3fb8555SGiannis Adamopoulos
3086b3fb8555SGiannis Adamopoulos /*
3087b3fb8555SGiannis Adamopoulos * When the user clicks outside the combobox and the focus
3088b3fb8555SGiannis Adamopoulos * is lost, the owning combobox will send a fake buttonup with
3089b3fb8555SGiannis Adamopoulos * 0xFFFFFFF as the mouse location, we must also revert the
3090b3fb8555SGiannis Adamopoulos * selection to the original selection.
3091b3fb8555SGiannis Adamopoulos */
3092b3fb8555SGiannis Adamopoulos if ( (lParam == (LPARAM)-1) || (!PtInRect( &clientRect, mousePos )) )
3093b3fb8555SGiannis Adamopoulos LISTBOX_MoveCaret( descr, lphc->droppedIndex, FALSE );
3094b3fb8555SGiannis Adamopoulos }
3095b3fb8555SGiannis Adamopoulos return LISTBOX_HandleLButtonUp( descr );
3096b3fb8555SGiannis Adamopoulos case WM_KEYDOWN:
3097b3fb8555SGiannis Adamopoulos if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
3098b3fb8555SGiannis Adamopoulos {
3099b3fb8555SGiannis Adamopoulos /* for some reason Windows makes it possible to
3100b3fb8555SGiannis Adamopoulos * show/hide ComboLBox by sending it WM_KEYDOWNs */
3101b3fb8555SGiannis Adamopoulos
3102b3fb8555SGiannis Adamopoulos if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
3103b3fb8555SGiannis Adamopoulos ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
3104b3fb8555SGiannis Adamopoulos && (wParam == VK_DOWN || wParam == VK_UP)) )
3105b3fb8555SGiannis Adamopoulos {
3106b3fb8555SGiannis Adamopoulos COMBO_FlipListbox( lphc, FALSE, FALSE );
3107b3fb8555SGiannis Adamopoulos return 0;
3108b3fb8555SGiannis Adamopoulos }
3109b3fb8555SGiannis Adamopoulos }
3110b3fb8555SGiannis Adamopoulos return LISTBOX_HandleKeyDown( descr, wParam );
3111b3fb8555SGiannis Adamopoulos case WM_CHAR:
3112b3fb8555SGiannis Adamopoulos return LISTBOX_HandleChar( descr, wParam );
3113b3fb8555SGiannis Adamopoulos
3114b3fb8555SGiannis Adamopoulos case WM_SYSTIMER:
3115b3fb8555SGiannis Adamopoulos return LISTBOX_HandleSystemTimer( descr );
3116b3fb8555SGiannis Adamopoulos case WM_ERASEBKGND:
3117b3fb8555SGiannis Adamopoulos if ((IS_OWNERDRAW(descr)) && !(descr->style & LBS_DISPLAYCHANGED))
3118b3fb8555SGiannis Adamopoulos {
3119b3fb8555SGiannis Adamopoulos RECT rect;
3120b3fb8555SGiannis Adamopoulos HBRUSH hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
3121b3fb8555SGiannis Adamopoulos wParam, (LPARAM)descr->self );
3122b3fb8555SGiannis Adamopoulos TRACE("hbrush = %p\n", hbrush);
3123b3fb8555SGiannis Adamopoulos if(!hbrush)
3124b3fb8555SGiannis Adamopoulos hbrush = GetSysColorBrush(COLOR_WINDOW);
3125b3fb8555SGiannis Adamopoulos if(hbrush)
3126b3fb8555SGiannis Adamopoulos {
3127b3fb8555SGiannis Adamopoulos GetClientRect(descr->self, &rect);
3128b3fb8555SGiannis Adamopoulos FillRect((HDC)wParam, &rect, hbrush);
3129b3fb8555SGiannis Adamopoulos }
3130b3fb8555SGiannis Adamopoulos }
3131b3fb8555SGiannis Adamopoulos return 1;
3132b3fb8555SGiannis Adamopoulos case WM_DROPFILES:
3133b3fb8555SGiannis Adamopoulos if( lphc ) return 0;
3134b3fb8555SGiannis Adamopoulos return SendMessageW( descr->owner, msg, wParam, lParam );
3135b3fb8555SGiannis Adamopoulos
3136b3fb8555SGiannis Adamopoulos case WM_NCDESTROY:
3137b3fb8555SGiannis Adamopoulos if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
3138b3fb8555SGiannis Adamopoulos lphc->hWndLBox = 0;
3139b3fb8555SGiannis Adamopoulos break;
3140b3fb8555SGiannis Adamopoulos
3141b3fb8555SGiannis Adamopoulos case WM_NCACTIVATE:
3142b3fb8555SGiannis Adamopoulos if (lphc) return 0;
3143b3fb8555SGiannis Adamopoulos break;
3144b3fb8555SGiannis Adamopoulos
3145b3fb8555SGiannis Adamopoulos case WM_THEMECHANGED:
3146b3fb8555SGiannis Adamopoulos theme = GetWindowTheme( hwnd );
3147b3fb8555SGiannis Adamopoulos CloseThemeData( theme );
3148b3fb8555SGiannis Adamopoulos OpenThemeData( hwnd, WC_LISTBOXW );
3149b3fb8555SGiannis Adamopoulos break;
3150b3fb8555SGiannis Adamopoulos
3151b3fb8555SGiannis Adamopoulos default:
3152b3fb8555SGiannis Adamopoulos if ((msg >= WM_USER) && (msg < 0xc000))
3153b3fb8555SGiannis Adamopoulos WARN("[%p]: unknown msg %04x wp %08lx lp %08lx\n",
3154b3fb8555SGiannis Adamopoulos hwnd, msg, wParam, lParam );
3155b3fb8555SGiannis Adamopoulos }
3156b3fb8555SGiannis Adamopoulos
3157b3fb8555SGiannis Adamopoulos return DefWindowProcW( hwnd, msg, wParam, lParam );
3158b3fb8555SGiannis Adamopoulos }
3159b3fb8555SGiannis Adamopoulos
LISTBOX_Register(void)3160b3fb8555SGiannis Adamopoulos void LISTBOX_Register(void)
3161b3fb8555SGiannis Adamopoulos {
3162b3fb8555SGiannis Adamopoulos WNDCLASSW wndClass;
3163b3fb8555SGiannis Adamopoulos
3164b3fb8555SGiannis Adamopoulos memset(&wndClass, 0, sizeof(wndClass));
3165b3fb8555SGiannis Adamopoulos wndClass.style = CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS;
3166b3fb8555SGiannis Adamopoulos wndClass.lpfnWndProc = LISTBOX_WindowProc;
3167b3fb8555SGiannis Adamopoulos wndClass.cbClsExtra = 0;
3168b3fb8555SGiannis Adamopoulos wndClass.cbWndExtra = sizeof(LB_DESCR *);
3169b3fb8555SGiannis Adamopoulos wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
3170b3fb8555SGiannis Adamopoulos wndClass.hbrBackground = NULL;
3171b3fb8555SGiannis Adamopoulos wndClass.lpszClassName = WC_LISTBOXW;
3172b3fb8555SGiannis Adamopoulos RegisterClassW(&wndClass);
3173b3fb8555SGiannis Adamopoulos }
3174b3fb8555SGiannis Adamopoulos
COMBOLBOX_Register(void)3175b3fb8555SGiannis Adamopoulos void COMBOLBOX_Register(void)
3176b3fb8555SGiannis Adamopoulos {
3177b3fb8555SGiannis Adamopoulos static const WCHAR combolboxW[] = {'C','o','m','b','o','L','B','o','x',0};
3178b3fb8555SGiannis Adamopoulos WNDCLASSW wndClass;
3179b3fb8555SGiannis Adamopoulos
3180b3fb8555SGiannis Adamopoulos memset(&wndClass, 0, sizeof(wndClass));
3181b3fb8555SGiannis Adamopoulos wndClass.style = CS_SAVEBITS | CS_DBLCLKS | CS_DROPSHADOW | CS_GLOBALCLASS;
3182b3fb8555SGiannis Adamopoulos wndClass.lpfnWndProc = LISTBOX_WindowProc;
3183b3fb8555SGiannis Adamopoulos wndClass.cbClsExtra = 0;
3184b3fb8555SGiannis Adamopoulos wndClass.cbWndExtra = sizeof(LB_DESCR *);
3185b3fb8555SGiannis Adamopoulos wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
3186b3fb8555SGiannis Adamopoulos wndClass.hbrBackground = NULL;
3187b3fb8555SGiannis Adamopoulos wndClass.lpszClassName = combolboxW;
3188b3fb8555SGiannis Adamopoulos RegisterClassW(&wndClass);
3189b3fb8555SGiannis Adamopoulos }
3190ffae49deSMark Jansen
3191ffae49deSMark Jansen #ifdef __REACTOS__
LISTBOX_Unregister(void)3192ffae49deSMark Jansen void LISTBOX_Unregister(void)
3193ffae49deSMark Jansen {
3194ffae49deSMark Jansen UnregisterClassW(WC_LISTBOXW, NULL);
3195ffae49deSMark Jansen }
3196ffae49deSMark Jansen
COMBOLBOX_Unregister(void)3197ffae49deSMark Jansen void COMBOLBOX_Unregister(void)
3198ffae49deSMark Jansen {
3199ffae49deSMark Jansen static const WCHAR combolboxW[] = {'C','o','m','b','o','L','B','o','x',0};
3200ffae49deSMark Jansen UnregisterClassW(combolboxW, NULL);
3201ffae49deSMark Jansen }
3202ffae49deSMark Jansen #endif
3203