Release 961201
Sat Nov 30 19:21:17 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [configure]
Re-generated with autoconf 2.11. Let me know if you have
problems.
* [controls/listbox.c] [controls/oldlbox.c]
Listboxes rewritten from scratch. Moved old code still used by
comboboxes to oldlbox.c
* [misc/registry.c]
Use temporary file when saving registry.
* [windows/dialog.c]
Implemented Win32 version of DlgDirList() and DlgDirListComboBox().
* [windows/winproc.c]
Added translation for listbox Win32 messages.
Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [controls/widgets.c] [controls/button.c]
Fixed some incompatibilities with CTL3D DLL.
* [windows/dialog.c]
Made dialog windows fit into the desktop.
* [misc/winsock.c] [misc/winsock_async.c]
New Winsock engine.
* [windows/message.c]
GetMessage() fixes.
* [windows/queue.c] [windows/hook.c] [windows/win.c]
SetMessageQueue() fixes.
Fri Nov 29 10:25:12 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [objects/text.c]
DrawText16(): Fixed return value.
Tue Nov 26 14:47:09 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [files/profile.c] [*/*]
Added Win32 profile functions, updated to new naming standard.
* [objects/font.c] [if1632/thunk.c] [include/windows.h]
Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
structures.
* [misc/ole2nls.c] [if1632/thunk.c]
Added EnumSystemLocales() (winhelp.exe).
* [misc/registry.c]
Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no
* [win32/file.c]
Partially fixed CreateFileMapping(), added UnmapViewOfFile().
Sat Nov 23 23:36:05 1996 Ronan Waide <waider@waider.ie>
* [misc/shell.c]
Fixed some FIXMEs relating to ShellExec() and FindExecutable().
* [misc/main.c]
Implemented a few more of the SystemParametersInfo() cases.
Tue Nov 19 01:24:34 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
* [include/keyboard.h]
New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).
* [include/windows.h]
New [VK_A, VK_Z] and [VK_0, VK9] macros.
* [misc/keyboard.c]
Fixes in KeyTable and ToAscii.
* [objects/font.c]
FONT_init : Give default value for MSWIN "system" font.
FONT_MatchFont : Do not try every size of a font family if the
family does not exist.
* [windows/event.c]
lastEventChar hack removed.
KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
and QueueKeyStateTable (maintained in message.c).
EVENT_key : Corrections to the extended bit setting.
* [windows/message.c] [windows/keyboard.c]
Implementation of a new QueueKeyStateTable : table of key states
valid when messages are retrieved by GetMessage or PeekMessage,
and valid for TranslateMessage.
TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
and ToAscii.
Mon Nov 18 16:59:01 1996 Robert Pouliot <krynos@clic.net>
* [graphics/Makefile.in] [graphics/wing.c]
[if1632/wing.spec]
Some functions for WinG support, mostly empty stubs.
* [misc/crtdll.c] [if1632/crtdll.spec]
Many functions added to CRTDLL, mostly calls to Unix C library.
diff --git a/controls/listbox.c b/controls/listbox.c
index a07645d..bad86a7 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -1,2269 +1,2393 @@
/*
* Listbox controls
- *
- * Copyright Martin Ayotte, 1993
- * Constantine Sapuntzakis, 1995
- * Alex Korobka, 1995, 1996
- *
+ *
+ * Copyright 1996 Alexandre Julliard
*/
- /*
- * FIXME:
- * - proper scrolling for multicolumn style
- * - anchor and caret for LBS_EXTENDEDSEL
- * - proper selection with keyboard
- * - how to handle (LBS_EXTENDEDSEL | LBS_MULTIPLESEL) style
- * - support for LBS_NOINTEGRALHEIGHT and LBS_OWNERDRAWVARIABLE styles
- */
-
-#include <stdio.h>
-#include <stdlib.h>
+#define NO_TRANSITION_TYPES /* This file is Win32-clean */
#include <string.h>
-#include <ctype.h>
+#include <stdio.h>
#include "windows.h"
-#include "win.h"
-#include "gdi.h"
-#include "msdos.h"
-#include "listbox.h"
-#include "dos_fs.h"
#include "drive.h"
-#include "file.h"
+#include "dos_fs.h"
+#include "msdos.h"
#include "heap.h"
+#include "spy.h"
+#include "win.h"
#include "stddebug.h"
#include "debug.h"
-#include "xmalloc.h"
-#define LIST_HEAP_ALLOC(lphl,f,size) \
- LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
-#define LIST_HEAP_FREE(lphl,handle) \
- LOCAL_Free( lphl->HeapSel, (handle) )
-#define LIST_HEAP_ADDR(lphl,handle) \
- ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
+/* Unimplemented yet:
+ * - LBS_NOSEL
+ * - LBS_USETABSTOPS
+ * - Unicode
+ * - Locale handling
+ * - COMBOLBOX
+ */
-#define LIST_HEAP_SIZE 0x10000
+/* Items array granularity */
+#define LB_ARRAY_GRANULARITY 16
-#define LBMM_EDGE 4 /* distance inside box which is same as moving mouse
- outside box, to trigger scrolling of LB */
+/* Scrolling timeout in ms */
+#define LB_SCROLL_TIMEOUT 50
-#define MATCH_SUBSTR 2
-#define MATCH_EXACT 1
-#define MATCH_NEAREST 0
+/* Listbox system timer id */
+#define LB_TIMER_ID 2
-static void ListBoxInitialize(LPHEADLIST lphl)
+/* Item structure */
+typedef struct
{
- lphl->lpFirst = NULL;
- lphl->ItemsCount = 0;
- lphl->ItemsVisible = 0;
- lphl->FirstVisible = 0;
- lphl->ColumnsVisible = 1;
- lphl->ItemsPerColumn = 0;
- lphl->ItemFocused = -1;
- lphl->PrevFocused = -1;
-}
+ LPSTR str; /* Item text */
+ BOOL32 selected; /* Is item selected? */
+ UINT32 height; /* Item height (only for OWNERDRAWVARIABLE) */
+ DWORD data; /* User data */
+} LB_ITEMDATA;
-void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
+/* Listbox structure */
+typedef struct
{
- LPHEADLIST lphl;
- HDC32 hdc;
+ HANDLE32 heap; /* Heap for this listbox */
+ HWND32 owner; /* Owner window */
+ UINT32 style; /* Window style */
+ INT32 width; /* Window width */
+ INT32 height; /* Window height */
+ LB_ITEMDATA *items; /* Array of items */
+ INT32 nb_items; /* Number of items */
+ INT32 top_item; /* Top visible item */
+ INT32 selected_item; /* Selected item */
+ INT32 focus_item; /* Item that has the focus */
+ INT32 anchor_item; /* Anchor item for extended selection */
+ INT32 item_height; /* Default item height */
+ INT32 page_size; /* Items per listbox page */
+ INT32 column_width; /* Column width for multi-column listboxes */
+ INT32 horz_extent; /* Horizontal extent (0 if no hscroll) */
+ INT32 horz_pos; /* Horizontal position */
+ INT32 nb_tabs; /* Number of tabs in array */
+ INT32 *tabs; /* Array of tabs */
+ BOOL32 caret_on; /* Is caret on? */
+ HFONT32 font; /* Current font */
+ LCID locale; /* Current locale for string comparisons */
+} LB_DESCR;
- lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
- SetWindowLong32A(hwnd, 0, (LONG)lphl);
- ListBoxInitialize(lphl);
- lphl->DrawCtlType = CtlType;
- lphl->CtlID = GetWindowWord(hwnd,GWW_ID);
- lphl->bRedrawFlag = TRUE;
- lphl->iNumStops = 0;
- lphl->TabStops = NULL;
- lphl->hFont = GetStockObject32(SYSTEM_FONT);
- lphl->hSelf = hwnd;
- if (CtlType==ODT_COMBOBOX) /* use the "faked" style for COMBOLBOX */
- /* LBS_SORT instead CBS_SORT e.g. */
- lphl->dwStyle = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong32A(hwnd,GWL_STYLE)));
- else
- lphl->dwStyle = GetWindowLong32A(hwnd,GWL_STYLE); /* use original style dword */
- lphl->hParent = parent;
- lphl->StdItemHeight = 15; /* FIXME: should get the font height */
- lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
- lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
- /* create dummy hdc to set text height */
- if ((hdc = GetDC32(0)))
- {
- TEXTMETRIC16 tm;
- GetTextMetrics16( hdc, &tm );
- lphl->StdItemHeight = tm.tmHeight;
- dprintf_listbox(stddeb,"CreateListBoxStruct: font height %d\n",
- lphl->StdItemHeight);
- ReleaseDC32( 0, hdc );
- }
+#define IS_OWNERDRAW(descr) \
+ ((descr)->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))
- if (lphl->OwnerDrawn)
- {
- LISTSTRUCT dummyls;
-
- lphl->needMeasure = TRUE;
- dummyls.mis.CtlType = lphl->DrawCtlType;
- dummyls.mis.CtlID = lphl->CtlID;
- dummyls.mis.itemID = -1;
- dummyls.mis.itemWidth = 0; /* ignored */
- dummyls.mis.itemData = 0;
+#define HAS_STRINGS(descr) \
+ (!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
- ListBoxAskMeasure(lphl,&dummyls);
- }
+#define SEND_NOTIFICATION(wnd,descr,code) \
+ (SendMessage32A( (descr)->owner, WM_COMMAND, \
+ MAKEWPARAM( (wnd)->wIDmenu, (code) ), (wnd)->hwndSelf ))
- lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE);
- LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
-}
-
-void DestroyListBoxStruct(LPHEADLIST lphl)
+/* Current timer status */
+typedef enum
{
- /* XXX need to free lphl->Heap */
- GlobalFree16(lphl->HeapSel);
- free(lphl);
-}
+ LB_TIMER_NONE,
+ LB_TIMER_UP,
+ LB_TIMER_LEFT,
+ LB_TIMER_DOWN,
+ LB_TIMER_RIGHT
+} TIMER_DIRECTION;
-static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
+static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
+
+
+/***********************************************************************
+ * LISTBOX_Dump
+ */
+void LISTBOX_Dump( WND *wnd )
{
- return (LPHEADLIST)GetWindowLong32A(hwnd,0);
-}
+ INT32 i;
+ LB_ITEMDATA *item;
+ LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
-/* Send notification "code" as part of a WM_COMMAND-message if hwnd
- has the LBS_NOTIFY style */
-void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
-{
- if (lphl->dwStyle & LBS_NOTIFY)
- SendMessage32A( lphl->hParent, WM_COMMAND,
- MAKEWPARAM( lphl->CtlID, code), (LPARAM)lphl->hSelf );
-}
-
-
-/* get the maximum value of lphl->FirstVisible */
-int ListMaxFirstVisible(LPHEADLIST lphl)
-{
- int m = lphl->ItemsCount-lphl->ItemsVisible;
- return (m < 0) ? 0 : m;
-}
-
-
-void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
-{
- if (lphl->dwStyle & WS_VSCROLL)
- SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
- if ((lphl->dwStyle & WS_HSCROLL) && (lphl->ItemsPerColumn != 0))
- SetScrollRange32(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
- lphl->ItemsPerColumn + 1, TRUE);
-
- if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
-}
-
-/* Returns: 0 if nothing needs to be changed */
-/* 1 if FirstVisible changed */
-
-int ListBoxScrollToFocus(LPHEADLIST lphl)
-{
- short end;
-
- if (lphl->ItemsCount == 0) return 0;
- if (lphl->ItemFocused == -1) return 0;
-
- end = lphl->FirstVisible + lphl->ItemsVisible - 1;
-
- if (lphl->ItemFocused < lphl->FirstVisible ) {
- lphl->FirstVisible = lphl->ItemFocused;
- return 1;
- } else {
- if (lphl->ItemFocused > end) {
- WORD maxFirstVisible = ListMaxFirstVisible(lphl);
-
- lphl->FirstVisible = lphl->ItemFocused;
-
- if (lphl->FirstVisible > maxFirstVisible) {
- lphl->FirstVisible = maxFirstVisible;
- }
- return 1;
+ printf( "Listbox:\n" );
+ printf( "hwnd=%04x descr=%08x heap=%08x items=%d top=%d\n",
+ wnd->hwndSelf, (UINT32)descr, descr->heap, descr->nb_items,
+ descr->top_item );
+ for (i = 0, item = descr->items; i < descr->nb_items; i++, item++)
+ {
+ printf( "%4d: %-40s %d %08lx %3d\n",
+ i, item->str, item->selected, item->data, item->height );
}
- }
- return 0;
}
-LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
+/***********************************************************************
+ * LISTBOX_GetCurrentPageSize
+ *
+ * Return the current page size
+ */
+static INT32 LISTBOX_GetCurrentPageSize( WND *wnd, LB_DESCR *descr )
{
- LPLISTSTRUCT lpls;
- UINT Count = 0;
-
- if (uIndex >= lphl->ItemsCount) return NULL;
-
- lpls = lphl->lpFirst;
- while (Count++ < uIndex) lpls = lpls->lpNext;
- return lpls;
+ INT32 i, height;
+ if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size;
+ for (i = descr->top_item, height = 0; i < descr->nb_items; i++)
+ {
+ if ((height += descr->items[i].height) > descr->height) break;
+ }
+ if (i == descr->top_item) return 1;
+ else return i - descr->top_item;
}
-void ListBoxDrawItem(HWND hwnd, LPHEADLIST lphl, HDC16 hdc, LPLISTSTRUCT lpls,
- RECT16 *rect, WORD itemAction, WORD itemState)
+/***********************************************************************
+ * LISTBOX_GetMaxTopIndex
+ *
+ * Return the maximum possible index for the top of the listbox.
+ */
+static INT32 LISTBOX_GetMaxTopIndex( WND *wnd, LB_DESCR *descr )
{
- if (lphl->OwnerDrawn)
+ INT32 max, page;
+
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ page = descr->height;
+ for (max = descr->nb_items - 1; max >= 0; max--)
+ if ((page -= descr->items[max].height) < 0) break;
+ if (max < descr->nb_items - 1) max++;
+ }
+ else if (descr->style & LBS_MULTICOLUMN)
+ {
+ if ((page = descr->width / descr->column_width) < 1) page = 1;
+ max = (descr->nb_items + descr->page_size - 1) / descr->page_size;
+ max = (max - page) * descr->page_size;
+ }
+ else
+ {
+ max = descr->nb_items - descr->page_size;
+ }
+ if (max < 0) max = 0;
+ return max;
+}
+
+
+/***********************************************************************
+ * LISTBOX_UpdateScroll
+ *
+ * Update the scrollbars. Should be called whenever the content
+ * of the listbox changes.
+ */
+static void LISTBOX_UpdateScroll( WND *wnd, LB_DESCR *descr )
+{
+ SCROLLINFO info;
+
+ if (descr->style & LBS_NOREDRAW) return;
+ info.cbSize = sizeof(info);
+
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ info.nMin = 0;
+ info.nMax = (descr->nb_items - 1) / descr->page_size;
+ info.nPos = descr->top_item / descr->page_size;
+ info.nPage = descr->width / descr->column_width;
+ if (info.nPage < 1) info.nPage = 1;
+ info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ if (descr->style & LBS_DISABLENOSCROLL)
+ info.fMask |= SIF_DISABLENOSCROLL;
+ SetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info, TRUE );
+ info.nMax = 0;
+ info.fMask = SIF_RANGE;
+ SetScrollInfo32( wnd->hwndSelf, SB_VERT, &info, TRUE );
+ }
+ else
+ {
+ info.nMin = 0;
+ info.nMax = descr->nb_items - 1;
+ info.nPos = descr->top_item;
+ info.nPage = LISTBOX_GetCurrentPageSize( wnd, descr );
+ info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ if (descr->style & LBS_DISABLENOSCROLL)
+ info.fMask |= SIF_DISABLENOSCROLL;
+ SetScrollInfo32( wnd->hwndSelf, SB_VERT, &info, TRUE );
+
+ if (descr->horz_extent)
+ {
+ info.nMin = 0;
+ info.nMax = descr->horz_extent - 1;
+ info.nPos = descr->horz_pos;
+ info.nPage = descr->width;
+ info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ if (descr->style & LBS_DISABLENOSCROLL)
+ info.fMask |= SIF_DISABLENOSCROLL;
+ SetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info, TRUE );
+ }
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetTopItem
+ *
+ * Set the top item of the listbox, scrolling up or down if necessary.
+ */
+static LRESULT LISTBOX_SetTopItem( WND *wnd, LB_DESCR *descr, INT32 index,
+ BOOL32 scroll )
+{
+ INT32 max = LISTBOX_GetMaxTopIndex( wnd, descr );
+ if (index > max) index = max;
+ if (index < 0) index = 0;
+ if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
+ if (descr->top_item == index) return LB_OKAY;
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT32 diff = (descr->top_item - index) / descr->page_size * descr->column_width;
+ if (scroll && (abs(diff) < descr->width))
+ ScrollWindow32( wnd->hwndSelf, diff, 0, NULL, NULL );
+ else
+ scroll = FALSE;
+ }
+ else if (scroll)
+ {
+ INT32 diff;
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ INT32 i;
+ diff = 0;
+ if (index > descr->top_item)
+ {
+ for (i = index - 1; i >= descr->top_item; i--)
+ diff -= descr->items[i].height;
+ }
+ else
+ {
+ for (i = index; i < descr->top_item; i++)
+ diff += descr->items[i].height;
+ }
+ }
+ else
+ diff = (descr->top_item - index) * descr->item_height;
+
+ if (abs(diff) < descr->height)
+ ScrollWindow32( wnd->hwndSelf, 0, diff, NULL, NULL );
+ else
+ scroll = FALSE;
+ }
+ if (!scroll) InvalidateRect32( wnd->hwndSelf, NULL, TRUE );
+ descr->top_item = index;
+ LISTBOX_UpdateScroll( wnd, descr );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_UpdatePage
+ *
+ * Update the page size. Should be called when the size of
+ * the client area or the item height changes.
+ */
+static void LISTBOX_UpdatePage( WND *wnd, LB_DESCR *descr )
+{
+ INT32 page_size;
+
+ if ((page_size = descr->height / descr->item_height) < 1) page_size = 1;
+ if (page_size == descr->page_size) return;
+ descr->page_size = page_size;
+ if (descr->style & LBS_MULTICOLUMN)
+ InvalidateRect32( wnd->hwndSelf, NULL, TRUE );
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item, FALSE );
+}
+
+
+/***********************************************************************
+ * LISTBOX_UpdateSize
+ *
+ * Update the size of the listbox. Should be called when the size of
+ * the client area changes.
+ */
+static void LISTBOX_UpdateSize( WND *wnd, LB_DESCR *descr )
+{
+ RECT32 rect;
+
+ GetClientRect32( wnd->hwndSelf, &rect );
+ descr->width = rect.right - rect.left;
+ descr->height = rect.bottom - rect.top;
+ if (!(descr->style & LBS_NOINTEGRALHEIGHT))
+ {
+ if ((descr->height > descr->item_height) &&
+ (descr->height % descr->item_height))
+ {
+ dprintf_listbox(stddeb, "Listbox %04x: changing height %d -> %d\n",
+ wnd->hwndSelf, descr->height,
+ descr->height - descr->height%descr->item_height );
+ SetWindowPos( wnd->hwndSelf, 0, 0, 0,
+ wnd->rectWindow.right - wnd->rectWindow.left,
+ wnd->rectWindow.bottom - wnd->rectWindow.top -
+ (descr->height % descr->item_height),
+ SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
+ return;
+ }
+ }
+ dprintf_listbox( stddeb, "Listbox %04x: new size = %d,%d\n",
+ wnd->hwndSelf, descr->width, descr->height );
+ LISTBOX_UpdatePage( wnd, descr );
+ LISTBOX_UpdateScroll( wnd, descr );
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetItemRect
+ *
+ * Get the rectangle enclosing an item, in listbox client coordinates.
+ * Return 1 if the rectangle is (partially) visible, 0 if hidden, -1 on error.
+ */
+static LRESULT LISTBOX_GetItemRect( WND *wnd, LB_DESCR *descr, INT32 index,
+ RECT32 *rect )
+{
+ /* Index <= 0 is legal even on empty listboxes */
+ if (index && (index >= descr->nb_items)) return -1;
+ SetRect32( rect, 0, 0, descr->width, descr->height );
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT32 col = (index / descr->page_size) -
+ (descr->top_item / descr->page_size);
+ rect->left += col * descr->column_width;
+ rect->right = rect->left + descr->column_width;
+ rect->top += (index % descr->page_size) * descr->item_height;
+ rect->bottom = rect->top + descr->item_height;
+ }
+ else if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ INT32 i;
+ if (index < descr->top_item)
+ {
+ for (i = descr->top_item-1; i >= index; i--)
+ rect->top -= descr->items[i].height;
+ }
+ else
+ {
+ for (i = descr->top_item; i < index; i++)
+ rect->top += descr->items[i].height;
+ }
+ rect->bottom = rect->top + descr->items[index].height;
+ rect->right += descr->horz_pos;
+ }
+ else
+ {
+ rect->top += (index - descr->top_item) * descr->item_height;
+ rect->bottom = rect->top + descr->item_height;
+ rect->right += descr->horz_pos;
+ }
+
+ return ((rect->left < descr->width) && (rect->right > 0) &&
+ (rect->top < descr->height) && (rect->bottom > 0));
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetItemFromPoint
+ *
+ * Return the item nearest from point (x,y) (in client coordinates).
+ */
+static INT32 LISTBOX_GetItemFromPoint( WND *wnd, LB_DESCR *descr,
+ INT32 x, INT32 y )
+{
+ INT32 index = descr->top_item;
+
+ if (!descr->nb_items) return -1; /* No items */
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ INT32 pos = 0;
+ if (y >= 0)
+ {
+ while (index < descr->nb_items)
+ {
+ if ((pos += descr->items[index].height) > y) break;
+ index++;
+ }
+ }
+ else
+ {
+ while (index > 0)
+ {
+ index--;
+ if ((pos -= descr->items[index].height) <= y) break;
+ }
+ }
+ }
+ else if (descr->style & LBS_MULTICOLUMN)
+ {
+ if (y >= descr->item_height * descr->page_size) return -1;
+ if (y >= 0) index += y / descr->item_height;
+ if (x >= 0) index += (x / descr->column_width) * descr->page_size;
+ else index -= (((x + 1) / descr->column_width) - 1) * descr->page_size;
+ }
+ else
+ {
+ index += (y / descr->item_height);
+ }
+ if (index < 0) return 0;
+ if (index >= descr->nb_items) return -1;
+ return index;
+}
+
+
+/***********************************************************************
+ * LISTBOX_PaintItem
+ *
+ * Paint an item.
+ */
+static void LISTBOX_PaintItem( WND *wnd, LB_DESCR *descr, HDC32 hdc,
+ const RECT32 *rect, INT32 index, UINT32 action )
+{
+ LB_ITEMDATA *item = NULL;
+ if (index < descr->nb_items) item = &descr->items[index];
+
+ if (IS_OWNERDRAW(descr))
{
DRAWITEMSTRUCT32 dis;
-
- dis.CtlID = lpls->mis.CtlID;
- dis.CtlType = lpls->mis.CtlType;
- dis.itemID = lpls->mis.itemID;
- dis.hDC = hdc;
- dis.hwndItem = hwnd;
- dis.itemData = lpls->mis.itemData;
- dis.itemAction = itemAction;
- dis.itemState = itemState;
- CONV_RECT16TO32( rect, &dis.rcItem );
- SendMessage32A( lphl->hParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis );
- return;
- }
- if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
- int OldBkMode;
- DWORD dwOldTextColor = 0;
-
- OldBkMode = SetBkMode(hdc, TRANSPARENT);
-
- if (itemState != 0) {
- dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
- FillRect16(hdc, rect, GetStockObject32(BLACK_BRUSH));
- }
-
- if (lphl->dwStyle & LBS_USETABSTOPS) {
- TabbedTextOut(hdc, rect->left + 5, rect->top + 2,
- (char *)lpls->itemText, strlen((char *)lpls->itemText),
- lphl->iNumStops, lphl->TabStops, 0);
- } else {
- TextOut16(hdc, rect->left + 5, rect->top + 2,
- (char *)lpls->itemText, strlen((char *)lpls->itemText));
- }
-
- if (itemState != 0) {
- SetTextColor(hdc, dwOldTextColor);
- }
-
- SetBkMode(hdc, OldBkMode);
- }
- else DrawFocusRect16(hdc, rect);
-}
-
-
-int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
-{
- LPLISTSTRUCT lpls = lphl->lpFirst;
- int i, j;
- POINT16 point;
-
- point.x = X; point.y = Y;
- if (lphl->ItemsCount == 0) return LB_ERR;
-
- for(i = 0; i < lphl->FirstVisible; i++) {
- if (lpls == NULL) return LB_ERR;
- lpls = lpls->lpNext;
- }
- for(j = 0; j < lphl->ItemsVisible; i++, j++) {
- if (lpls == NULL) return LB_ERR;
- if (PtInRect16(&lpls->itemRect,point)) {
- return i;
- }
- lpls = lpls->lpNext;
- }
- dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
- return LB_ERR;
-}
-
-BOOL32 lbDeleteItemNotify(LPHEADLIST lphl, LPLISTSTRUCT lpls)
-{
- /* called only for owner drawn listboxes */
- BOOL32 ret;
- DELETEITEMSTRUCT16 *delItem = SEGPTR_NEW(DELETEITEMSTRUCT16);
- if (!delItem) return FALSE;
-
- delItem->CtlType = lphl->DrawCtlType;
- delItem->CtlID = lphl->CtlID;
- delItem->itemID = lpls->mis.itemID;
- delItem->hwndItem = lphl->hSelf;
- delItem->itemData = lpls->mis.itemData;
-
- ret = SendMessage16( lphl->hParent, WM_DELETEITEM, (WPARAM16)lphl->CtlID,
- (LPARAM)SEGPTR_GET(delItem) );
- SEGPTR_FREE(delItem);
- return ret;
-}
-
-void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)
-{
- MEASUREITEMSTRUCT16 *lpmeasure = SEGPTR_NEW(MEASUREITEMSTRUCT16);
- if (!lpmeasure) return;
- *lpmeasure = lpls->mis;
- lpmeasure->itemHeight = lphl->StdItemHeight;
- SendMessage16( lphl->hParent, WM_MEASUREITEM, lphl->CtlID,
- (LPARAM)SEGPTR_GET(lpmeasure) );
-
- if (lphl->dwStyle & LBS_OWNERDRAWFIXED)
- {
- if (lpmeasure->itemHeight > lphl->StdItemHeight)
- lphl->StdItemHeight = lpmeasure->itemHeight;
- lpls->mis.itemHeight = lpmeasure->itemHeight;
- }
- SEGPTR_FREE(lpmeasure);
-}
-
-/* -------------------- strings and item data ---------------------- */
-
-LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
-{
- LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
-
- if (lplsnew == NULL) return NULL;
-
- lplsnew->itemState = 0;
- lplsnew->mis.CtlType = lphl->DrawCtlType;
- lplsnew->mis.CtlID = lphl->CtlID;
- lplsnew->mis.itemID = id;
- lplsnew->mis.itemHeight = lphl->StdItemHeight;
- lplsnew->mis.itemWidth = 0; /* ignored */
- lplsnew->mis.itemData = 0;
- SetRectEmpty16( &lplsnew->itemRect );
-
- return lplsnew;
-}
-
-int ListBoxAskCompare(LPHEADLIST lphl, int startItem, SEGPTR matchData, BOOL exactMatch )
-{
- /* Do binary search for sorted listboxes. Linked list item storage sort of
- * defeats the purpose ( forces to traverse item list all the time ) but M$ does it this way...
- *
- * MATCH_NEAREST (0) - return position for insertion - for all styles
- * MATCH_EXACT (1) - search for an item, return index or LB_ERR
- * MATCH_SUBSTR (2) - same as exact match but with strncmp for string comparision
- */
-
- COMPAREITEMSTRUCT16 *itemCmp;
- LPLISTSTRUCT currentItem = NULL;
- LPCSTR matchStr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(matchData):NULL;
- int head, pos = -1, tail, loop = 1;
- short b = 0, s_length = 0;
-
- /* check if empty */
-
- if( !lphl->ItemsCount )
- return (exactMatch)? LB_ERR: 0;
-
- /* set up variables */
-
- if( exactMatch == MATCH_NEAREST )
- startItem = 0;
- else if( ++startItem )
- {
- loop = 2;
- if( startItem >= lphl->ItemsCount ) startItem = lphl->ItemsCount - 1;
- }
-
- if( exactMatch == MATCH_SUBSTR && lphl->HasStrings )
- {
- s_length = strlen( matchStr );
- if( !s_length ) return 0; /* head of the list - empty string */
- }
-
- head = startItem; tail = lphl->ItemsCount - 1;
-
- dprintf_listbox(stddeb,"AskCompare: head = %i, tail = %i, data = %08x\n", head, tail, (unsigned)matchData );
-
- if (!(itemCmp = SEGPTR_NEW(COMPAREITEMSTRUCT16))) return 0;
- itemCmp->CtlType = lphl->DrawCtlType;
- itemCmp->CtlID = lphl->CtlID;
- itemCmp->hwndItem = lphl->hSelf;
-
- /* search from startItem */
-
- while ( loop-- )
- {
- while( head <= tail )
- {
- pos = (tail + head)/2;
- currentItem = ListBoxGetItem( lphl, pos );
-
- if( lphl->HasStrings )
- {
- b = ( s_length )? lstrncmpi32A( currentItem->itemText, matchStr, s_length)
- : lstrcmpi32A( currentItem->itemText, matchStr);
- }
- else
- {
- itemCmp->itemID1 = pos;
- itemCmp->itemData1 = currentItem->mis.itemData;
- itemCmp->itemID2 = -1;
- itemCmp->itemData2 = matchData;
-
- b = SendMessage16( lphl->hParent, WM_COMPAREITEM,
- (WPARAM16)lphl->CtlID,
- (LPARAM)SEGPTR_GET(itemCmp) );
- }
-
- if( b == 0 )
- {
- SEGPTR_FREE(itemCmp);
- return pos; /* found exact match */
- }
- else
- if( b < 0 ) head = ++pos;
- else
- if( b > 0 ) tail = pos - 1;
- }
-
- /* reset to search from the first item */
- head = 0; tail = startItem - 1;
- }
-
- dprintf_listbox(stddeb,"\t-> pos = %i\n", pos );
- SEGPTR_FREE(itemCmp);
-
- /* if we got here match is not exact */
-
- if( pos < 0 ) pos = 0;
- else if( pos > lphl->ItemsCount ) pos = lphl->ItemsCount;
-
- return (exactMatch)? LB_ERR: pos;
-}
-
-int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
-{
- LPLISTSTRUCT *lppls, lplsnew, lpls;
- HANDLE16 hStr;
- LPSTR str;
- UINT Count;
-
- dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
-
- if (!newstr) return -1;
-
- if (uIndex == (UINT)-1)
- uIndex = lphl->ItemsCount;
-
- lppls = &lphl->lpFirst;
- for(Count = 0; Count < uIndex; Count++) {
- if (*lppls == NULL) return LB_ERR;
- lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
- }
-
- lplsnew = ListBoxCreateItem(lphl, Count);
-
- if (lplsnew == NULL) {
- fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
- return LB_ERRSPACE;
- }
-
- lplsnew->lpNext = *lppls;
- *lppls = lplsnew;
- lphl->ItemsCount++;
-
- hStr = 0;
- if (lphl->HasStrings) {
- dprintf_listbox(stddeb," string: %s\n", newstr);
- hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
- str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
- if (str == NULL) return LB_ERRSPACE;
- strcpy(str, newstr);
- lplsnew->itemText = str;
- /* I'm not so sure about the next one */
- lplsnew->mis.itemData = 0;
- } else {
- lplsnew->itemText = NULL;
- lplsnew->mis.itemData = (DWORD)newstr;
- }
-
- lplsnew->mis.itemID = uIndex;
- lplsnew->hData = hStr;
-
- /* adjust the itemID field of the following entries */
- for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
- lpls->mis.itemID++;
- }
-
- if (lphl->needMeasure) {
- ListBoxAskMeasure(lphl, lplsnew);
- }
-
- dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
- return uIndex;
-}
-
-
-int ListBoxAddString(LPHEADLIST lphl, SEGPTR itemData)
-{
- UINT pos = (UINT) -1;
- LPCSTR newstr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(itemData):(LPCSTR)itemData;
-
- if ( lphl->dwStyle & LBS_SORT )
- pos = ListBoxAskCompare( lphl, -1, itemData, MATCH_NEAREST );
-
- return ListBoxInsertString(lphl, pos, newstr);
-}
-
-
-int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
-{
- LPLISTSTRUCT lpls;
-
- if (!OutStr) {
- dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
- return 0;
- }
- *OutStr = '\0';
- lpls = ListBoxGetItem (lphl, uIndex);
- if (lpls == NULL) return LB_ERR;
-
- if (!lphl->HasStrings) {
- *((long *)OutStr) = lpls->mis.itemData;
- return 4;
- }
-
- strcpy(OutStr, lpls->itemText);
- return strlen(OutStr);
-}
-
-
-DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
-{
- LPLISTSTRUCT lpls;
-
- lpls = ListBoxGetItem (lphl, uIndex);
- if (lpls == NULL) return LB_ERR;
- return lpls->mis.itemData;
-}
-
-
-int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
-{
- LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
-
- if (lpls == NULL) return LB_ERR;
- lpls->mis.itemData = ItemData;
- return 1;
-}
-
-
-int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
-{
- LPLISTSTRUCT lpls, lpls2;
- UINT Count;
-
- if (uIndex >= lphl->ItemsCount) return LB_ERR;
-
- lpls = lphl->lpFirst;
- if (lpls == NULL) return LB_ERR;
-
- if (uIndex == 0)
- {
- if( lphl->OwnerDrawn )
- lbDeleteItemNotify( lphl, lpls);
- lphl->lpFirst = lpls->lpNext;
- }
- else
- {
- LPLISTSTRUCT lpls2 = NULL;
- for(Count = 0; Count < uIndex; Count++) {
- if (lpls->lpNext == NULL) return LB_ERR;
-
- lpls2 = lpls;
- lpls = (LPLISTSTRUCT)lpls->lpNext;
- }
- if( lphl->OwnerDrawn )
- lbDeleteItemNotify( lphl, lpls);
- lpls2->lpNext = lpls->lpNext;
- }
-
- /* adjust the itemID field of the following entries */
- for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
- lpls2->mis.itemID--;
- }
-
- lphl->ItemsCount--;
-
- if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
- free(lpls);
-
- return lphl->ItemsCount;
-}
-
-int lbFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr, BOOL match)
-{
- /* match is either MATCH_SUBSTR or MATCH_EXACT */
-
- LPLISTSTRUCT lpls;
- UINT Count;
- UINT First = nFirst + 1;
- int s_length = 0;
- LPSTR lpMatchStr = (LPSTR)MatchStr;
-
- if (First > lphl->ItemsCount) return LB_ERR;
-
- if (lphl->dwStyle & LBS_SORT )
- return ListBoxAskCompare( lphl, nFirst, MatchStr, match );
-
- if (lphl->HasStrings )
- {
- lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
-
- if( match == MATCH_SUBSTR )
- {
- s_length = strlen(lpMatchStr);
- if( !s_length ) return (lphl->ItemsCount)?0:LB_ERR;
- }
- }
-
- lpls = ListBoxGetItem(lphl, First);
- Count = 0;
- while(lpls != NULL)
- {
- if (lphl->HasStrings)
- {
- if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length)
- : !lstrcmpi32A(lpls->itemText, lpMatchStr) ) return Count;
+ dis.CtlType = ODT_LISTBOX;
+ dis.CtlID = wnd->wIDmenu;
+ dis.hwndItem = wnd->hwndSelf;
+ dis.itemAction = action;
+ dis.hDC = hdc;
+ dis.itemID = index;
+ dis.itemState = 0;
+ if (item && item->selected) dis.itemState |= ODS_SELECTED;
+ if ((descr->focus_item == index) &&
+ (descr->caret_on) &&
+ (GetFocus32() == wnd->hwndSelf)) dis.itemState |= ODS_FOCUS;
+ if (wnd->dwStyle & WS_DISABLED) dis.itemState |= ODS_DISABLED;
+ dis.itemData = item ? item->data : 0;
+ dis.rcItem = *rect;
+ dprintf_listbox( stddeb, "Listbox %04x: drawitem %d (%s) action=%02x "
+ "state=%02x rect=%d,%d-%d,%d\n",
+ wnd->hwndSelf, index, item ? item->str : "", action,
+ dis.itemState, rect->left, rect->top,
+ rect->right, rect->bottom );
+ SendMessage32A(descr->owner, WM_DRAWITEM, wnd->wIDmenu, (LPARAM)&dis);
}
else
- if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count;
-
- lpls = lpls->lpNext;
- Count++;
- }
-
- /* Start over at top */
- Count = 0;
- lpls = lphl->lpFirst;
-
- while (Count < First)
- {
- if (lphl->HasStrings)
{
- if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length)
- : !lstrcmpi32A(lpls->itemText, lpMatchStr) ) return Count;
+ if (action == ODA_FOCUS)
+ {
+ DrawFocusRect32( hdc, rect );
+ return;
+ }
+ if (item && item->selected)
+ {
+ SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
+ SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
+ }
+ else
+ {
+ SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
+ if (wnd->dwStyle & WS_DISABLED)
+ SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+ else
+ SetTextColor( hdc, GetSysColor( COLOR_WINDOWTEXT ) );
+ }
+ dprintf_listbox( stddeb, "Listbox %04x: painting %d (%s) action=%02x"
+ "rect=%d,%d-%d,%d\n",
+ wnd->hwndSelf, index, item ? item->str : "", action,
+ rect->left, rect->top, rect->right, rect->bottom );
+ /* FIXME: check LBS_USETABSTOPS style */
+ if (item)
+ ExtTextOut32A( hdc, rect->left + 1, rect->top + 1,
+ ETO_OPAQUE | ETO_CLIPPED, rect, item->str,
+ strlen(item->str), NULL );
+ else
+ ExtTextOut32A( hdc, rect->left + 1, rect->top + 1,
+ ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
+ if ((descr->focus_item == index) &&
+ (descr->caret_on) &&
+ (GetFocus32() == wnd->hwndSelf)) DrawFocusRect32( hdc, rect );
}
- else
- if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count;
-
- lpls = lpls->lpNext;
- Count++;
- }
-
- return LB_ERR;
}
-int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
+
+/***********************************************************************
+ * LISTBOX_SetRedraw
+ *
+ * Change the redraw flag.
+ */
+static void LISTBOX_SetRedraw( WND *wnd, LB_DESCR *descr, BOOL32 on )
{
- return lbFindString(lphl, nFirst, MatchStr, MATCH_SUBSTR );
-}
-
-int ListBoxFindStringExact(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
-{
- return lbFindString(lphl, nFirst, MatchStr, MATCH_EXACT );
-}
-
-int ListBoxResetContent(LPHEADLIST lphl)
-{
- LPLISTSTRUCT lpls;
- int i;
-
- if (lphl->ItemsCount == 0) return 0;
-
- dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
- lphl->ItemsCount);
-
- for(i = 0; i < lphl->ItemsCount; i++) {
- lpls = lphl->lpFirst;
- if (lpls == NULL) return LB_ERR;
-
- if (lphl->OwnerDrawn) lbDeleteItemNotify(lphl, lpls);
-
- lphl->lpFirst = lpls->lpNext;
- if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
- free(lpls);
+ if (on)
+ {
+ if (!(descr->style & LBS_NOREDRAW)) return;
+ descr->style &= ~LBS_NOREDRAW;
+ LISTBOX_UpdateScroll( wnd, descr );
}
- ListBoxInitialize(lphl);
+ else descr->style |= LBS_NOREDRAW;
+}
+
+/***********************************************************************
+ * LISTBOX_RepaintItem
+ *
+ * Repaint a single item synchronously.
+ */
+static void LISTBOX_RepaintItem( WND *wnd, LB_DESCR *descr, INT32 index,
+ UINT32 action )
+{
+ HDC32 hdc;
+ RECT32 rect;
+
+ if (descr->style & LBS_NOREDRAW) return;
+ if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) != 1) return;
+ if ((hdc = GetDCEx32( wnd->hwndSelf, 0, DCX_CACHE )))
+ {
+ HFONT32 oldFont = 0;
+ if (descr->font) oldFont = SelectObject32( hdc, descr->font );
+ SetWindowOrgEx32( hdc, descr->horz_pos, 0, NULL );
+ LISTBOX_PaintItem( wnd, descr, hdc, &rect, index, action );
+ if (oldFont) SelectObject32( hdc, oldFont );
+ ReleaseDC32( wnd->hwndSelf, hdc );
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_InitStorage
+ */
+static LRESULT LISTBOX_InitStorage( WND *wnd, LB_DESCR *descr, INT32 nb_items,
+ DWORD bytes )
+{
+ LB_ITEMDATA *item;
+
+ nb_items += LB_ARRAY_GRANULARITY - 1;
+ nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
+ if (descr->items)
+ nb_items += HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
+ if (!(item = HeapReAlloc( descr->heap, 0, descr->items,
+ nb_items * sizeof(LB_ITEMDATA) )))
+ {
+ SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+ return LB_ERRSPACE;
+ }
+ descr->items = item;
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetTabStops
+ */
+static BOOL32 LISTBOX_SetTabStops( WND *wnd, LB_DESCR *descr, INT32 count,
+ LPINT32 tabs, BOOL32 short_ints )
+{
+ if (!(descr->style & LBS_USETABSTOPS)) return TRUE;
+ if (descr->tabs) HeapFree( descr->heap, 0, descr->tabs );
+ if (!(descr->nb_tabs = count))
+ {
+ descr->tabs = NULL;
+ return TRUE;
+ }
+ /* FIXME: count = 1 */
+ if (!(descr->tabs = (INT32 *)HeapAlloc( descr->heap, 0,
+ descr->nb_tabs * sizeof(INT32) )))
+ return FALSE;
+ if (short_ints)
+ {
+ INT32 i;
+ LPINT16 p = (LPINT16)tabs;
+ for (i = 0; i < descr->nb_tabs; i++) descr->tabs[i] = *p++;
+ }
+ else memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT32) );
+ /* FIXME: repaint the window? */
return TRUE;
}
-/* --------------------- selection ------------------------- */
-int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
+/***********************************************************************
+ * LISTBOX_GetText
+ */
+static LRESULT LISTBOX_GetText( WND *wnd, LB_DESCR *descr, INT32 index,
+ LPSTR buffer )
{
- LPLISTSTRUCT lpls;
-
- /* use ListBoxSetSel instead */
- if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0;
-
- /* unselect previous item */
- if (lphl->ItemFocused != -1) {
- lphl->PrevFocused = lphl->ItemFocused;
- lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
- if (lpls == 0) return LB_ERR;
- lpls->itemState = 0;
- }
-
- if ((wIndex != (UINT)-1) && (wIndex < lphl->ItemsCount))
- {
- lphl->ItemFocused = wIndex;
- lpls = ListBoxGetItem(lphl, wIndex);
- if (lpls == 0) return LB_ERR;
- lpls->itemState = ODS_SELECTED | ODS_FOCUS;
-
- return 0;
- }
-
- return LB_ERR;
-}
-
-
-int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state)
-{
- LPLISTSTRUCT lpls;
- int n = 0;
-
- if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
- return LB_ERR;
-
- if (wIndex == (UINT)-1) {
- for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
- if( lpls->itemState & ODS_SELECTED) n++;
- lpls->itemState = state? lpls->itemState | ODS_SELECTED
- : lpls->itemState & ~ODS_SELECTED;
+ if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ if (HAS_STRINGS(descr))
+ {
+ lstrcpy32A( buffer, descr->items[index].str );
+ return strlen(buffer);
}
- return n;
- }
-
- if (wIndex >= lphl->ItemsCount) return LB_ERR;
-
- lpls = ListBoxGetItem(lphl, wIndex);
- lpls->itemState = state? lpls->itemState | ODS_SELECTED
- : lpls->itemState & ~ODS_SELECTED;
-
- return 0;
+ else
+ {
+ memcpy( buffer, &descr->items[index].data, sizeof(DWORD) );
+ return sizeof(DWORD);
+ }
}
-int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
+/***********************************************************************
+ * LISTBOX_FindStringPos
+ *
+ * Find the nearest string located before a given string in sort order.
+ * If 'exact' is TRUE, return an error if we don't get an exact match.
+ */
+static INT32 LISTBOX_FindStringPos( WND *wnd, LB_DESCR *descr, LPCSTR str,
+ BOOL32 exact )
{
- LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex);
+ INT32 index, min, max, res = -1;
- if (lpls == NULL) return LB_ERR;
- return lpls->itemState & ODS_SELECTED;
+ if (!(descr->style & LBS_SORT)) return -1; /* Add it at the end */
+ min = 0;
+ max = descr->nb_items;
+ while (min != max)
+ {
+ index = (min + max) / 2;
+ if (HAS_STRINGS(descr))
+ res = lstrcmpi32A( descr->items[index].str, str );
+ else
+ {
+ COMPAREITEMSTRUCT32 cis;
+ cis.CtlType = ODT_LISTBOX;
+ cis.CtlID = wnd->wIDmenu;
+ cis.hwndItem = wnd->hwndSelf;
+ cis.itemID1 = index;
+ cis.itemData1 = descr->items[index].data;
+ cis.itemID2 = -1;
+ cis.itemData2 = (DWORD)str;
+ cis.dwLocaleId = descr->locale;
+ res = SendMessage32A( descr->owner, WM_COMPAREITEM,
+ wnd->wIDmenu, (LPARAM)&cis );
+ }
+ if (!res) return index;
+ if (res > 0) max = index;
+ else min = index + 1;
+ }
+ return exact ? -1 : max;
}
-/* ------------------------- dir listing ------------------------ */
-LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
+/***********************************************************************
+ * LISTBOX_FindFileStrPos
+ *
+ * Find the nearest string located before a given string in directory
+ * sort order (i.e. first files, then directories, then drives).
+ */
+static INT32 LISTBOX_FindFileStrPos( WND *wnd, LB_DESCR *descr, LPCSTR str )
{
- char mask[13];
- char* temp = NULL;
- const char* ptr;
- int skip, count;
- LONG ret;
- DOS_DIRENT entry;
+ INT32 min, max, res = -1;
+
+ if (!HAS_STRINGS(descr))
+ return LISTBOX_FindStringPos( wnd, descr, str, FALSE );
+ min = 0;
+ max = descr->nb_items;
+ while (min != max)
+ {
+ INT32 index = (min + max) / 2;
+ const char *p = descr->items[index].str;
+ if (*p == '[') /* drive or directory */
+ {
+ if (*str != '[') res = -1;
+ else if (p[1] == '-') /* drive */
+ {
+ if (str[1] == '-') res = str[2] - p[2];
+ else res = -1;
+ }
+ else /* directory */
+ {
+ if (str[1] == '-') res = 1;
+ else res = lstrcmpi32A( str, p );
+ }
+ }
+ else /* filename */
+ {
+ if (*str == '[') res = 1;
+ else res = lstrcmpi32A( str, p );
+ }
+ if (!res) return index;
+ if (res < 0) max = index;
+ else min = index + 1;
+ }
+ return max;
+}
+
+
+/***********************************************************************
+ * LISTBOX_FindString
+ *
+ * Find the item beginning with a given string.
+ */
+static INT32 LISTBOX_FindString( WND *wnd, LB_DESCR *descr, INT32 start,
+ LPCSTR str, BOOL32 exact )
+{
+ INT32 i;
+ LB_ITEMDATA *item;
+
+ if (start >= descr->nb_items) start = -1;
+ item = descr->items + start + 1;
+ if (HAS_STRINGS(descr))
+ {
+ if (exact)
+ {
+ for (i = start + 1; i < descr->nb_items; i++, item++)
+ if (!lstrcmpi32A( str, item->str )) return i;
+ for (i = 0, item = descr->items; i <= start; i++, item++)
+ if (!lstrcmpi32A( str, item->str )) return i;
+ }
+ else
+ {
+ /* Special case for drives and directories: ignore prefix */
+#define CHECK_DRIVE(item) \
+ if ((item)->str[0] == '[') \
+ { \
+ if (!lstrncmpi32A( str, (item)->str+1, len )) return i; \
+ if (((item)->str[1] == '-') && !lstrncmpi32A(str,(item)->str+2,len)) \
+ return i; \
+ }
+
+ INT32 len = strlen(str);
+ for (i = start + 1; i < descr->nb_items; i++, item++)
+ {
+ if (!lstrncmpi32A( str, item->str, len )) return i;
+ CHECK_DRIVE(item);
+ }
+ for (i = 0, item = descr->items; i <= start; i++, item++)
+ {
+ if (!lstrncmpi32A( str, item->str, len )) return i;
+ CHECK_DRIVE(item);
+ }
+#undef CHECK_DRIVE
+ }
+ }
+ else
+ {
+ if (exact && (descr->style & LBS_SORT))
+ /* If sorted, use a WM_COMPAREITEM binary search */
+ return LISTBOX_FindStringPos( wnd, descr, str, TRUE );
+
+ /* Otherwise use a linear search */
+ for (i = start + 1; i < descr->nb_items; i++, item++)
+ if (item->data == (DWORD)str) return i;
+ for (i = 0, item = descr->items; i <= start; i++, item++)
+ if (item->data == (DWORD)str) return i;
+ }
+ return LB_ERR;
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetSelCount
+ */
+static LRESULT LISTBOX_GetSelCount( WND *wnd, LB_DESCR *descr )
+{
+ INT32 i, count;
+ LB_ITEMDATA *item = descr->items;
+
+ if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+ for (i = count = 0; i < descr->nb_items; i++, item++)
+ if (item->selected) count++;
+ return count;
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetSelItems16
+ */
+static LRESULT LISTBOX_GetSelItems16( WND *wnd, LB_DESCR *descr, INT16 max,
+ LPINT16 array )
+{
+ INT32 i, count;
+ LB_ITEMDATA *item = descr->items;
+
+ if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+ for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
+ if (item->selected) array[count++] = (INT16)i;
+ return count;
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetSelItems32
+ */
+static LRESULT LISTBOX_GetSelItems32( WND *wnd, LB_DESCR *descr, INT32 max,
+ LPINT32 array )
+{
+ INT32 i, count;
+ LB_ITEMDATA *item = descr->items;
+
+ if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+ for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
+ if (item->selected) array[count++] = i;
+ return count;
+}
+
+
+/***********************************************************************
+ * LISTBOX_Paint
+ */
+static LRESULT LISTBOX_Paint( WND *wnd, LB_DESCR *descr, HDC32 hdc )
+{
+ INT32 i, col_pos = descr->page_size - 1;
+ RECT32 rect;
+ HFONT32 oldFont = 0;
+
+ SetRect32( &rect, 0, 0, descr->width, descr->height );
+ if (descr->style & LBS_NOREDRAW) return 0;
+ if (descr->style & LBS_MULTICOLUMN)
+ rect.right = rect.left + descr->column_width;
+ else if (descr->horz_pos)
+ {
+ SetWindowOrgEx32( hdc, descr->horz_pos, 0, NULL );
+ rect.right += descr->horz_pos;
+ }
+
+ if (descr->font) oldFont = SelectObject32( hdc, descr->font );
+
+ if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
+ (GetFocus32() == wnd->hwndSelf))
+ {
+ /* Special case for empty listbox: paint focus rect */
+ rect.bottom = rect.top + descr->item_height;
+ LISTBOX_PaintItem( wnd, descr, hdc, &rect, descr->focus_item,
+ ODA_DRAWENTIRE );
+ rect.top = rect.bottom;
+ }
+
+ for (i = descr->top_item; i < descr->nb_items; i++)
+ {
+ if (!(descr->style & LBS_OWNERDRAWVARIABLE))
+ rect.bottom = rect.top + descr->item_height;
+ else
+ rect.bottom = rect.top + descr->items[i].height;
+
+ LISTBOX_PaintItem( wnd, descr, hdc, &rect, i, ODA_DRAWENTIRE );
+ rect.top = rect.bottom;
+
+ if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
+ {
+ if (!IS_OWNERDRAW(descr))
+ {
+ /* Clear the bottom of the column */
+ SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
+ if (rect.top < descr->height)
+ {
+ rect.bottom = descr->height;
+ ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+ &rect, NULL, 0, NULL );
+ }
+ }
+
+ /* Go to the next column */
+ rect.left += descr->column_width;
+ rect.right += descr->column_width;
+ rect.top = 0;
+ col_pos = descr->page_size - 1;
+ }
+ else
+ {
+ col_pos--;
+ if (rect.top >= descr->height) break;
+ }
+ }
+
+ if (!IS_OWNERDRAW(descr))
+ {
+ /* Clear the remainder of the client area */
+ SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
+ if (rect.top < descr->height)
+ {
+ rect.bottom = descr->height;
+ ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+ &rect, NULL, 0, NULL );
+ }
+ if (rect.right < descr->width)
+ {
+ rect.left = rect.right;
+ rect.right = descr->width;
+ rect.top = 0;
+ rect.bottom = descr->height;
+ ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+ &rect, NULL, 0, NULL );
+ }
+ }
+ if (oldFont) SelectObject32( hdc, oldFont );
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_InvalidateItems
+ *
+ * Invalidate all items from a given item. If the specified item is not
+ * visible, nothing happens.
+ */
+static void LISTBOX_InvalidateItems( WND *wnd, LB_DESCR *descr, INT32 index )
+{
+ RECT32 rect;
+
+ if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) == 1)
+ {
+ rect.bottom = descr->height;
+ InvalidateRect32( wnd->hwndSelf, &rect, TRUE );
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ /* Repaint the other columns */
+ rect.left = rect.right;
+ rect.right = descr->width;
+ rect.top = 0;
+ InvalidateRect32( wnd->hwndSelf, &rect, TRUE );
+ }
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetItemHeight
+ */
+static LRESULT LISTBOX_GetItemHeight( WND *wnd, LB_DESCR *descr, INT32 index )
+{
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ return descr->items[index].height;
+ }
+ else return descr->item_height;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetItemHeight
+ */
+static LRESULT LISTBOX_SetItemHeight( WND *wnd, LB_DESCR *descr, INT32 index,
+ UINT32 height )
+{
+ if (!height) height = 1;
+
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ dprintf_listbox( stddeb, "Listbox %04x: item %d height = %d\n",
+ wnd->hwndSelf, index, height );
+ descr->items[index].height = height;
+ LISTBOX_UpdateScroll( wnd, descr );
+ LISTBOX_InvalidateItems( wnd, descr, index );
+ }
+ else if (height != descr->item_height)
+ {
+ dprintf_listbox( stddeb, "Listbox %04x: new height = %d\n",
+ wnd->hwndSelf, height );
+ descr->item_height = height;
+ LISTBOX_UpdatePage( wnd, descr );
+ LISTBOX_UpdateScroll( wnd, descr );
+ InvalidateRect32( wnd->hwndSelf, 0, TRUE );
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetHorizontalPos
+ */
+static void LISTBOX_SetHorizontalPos( WND *wnd, LB_DESCR *descr, INT32 pos )
+{
+ INT32 diff;
+
+ if (pos > descr->horz_extent - descr->width)
+ pos = descr->horz_extent - descr->width;
+ if (pos < 0) pos = 0;
+ if (!(diff = descr->horz_pos - pos)) return;
+ dprintf_listbox( stddeb, "Listbox %04x: new horz pos = %d\n",
+ wnd->hwndSelf, pos );
+ descr->horz_pos = pos;
+ LISTBOX_UpdateScroll( wnd, descr );
+ if (abs(diff) < descr->width)
+ ScrollWindow32( wnd->hwndSelf, diff, 0, NULL, NULL );
+ else
+ InvalidateRect32( wnd->hwndSelf, NULL, TRUE );
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetHorizontalExtent
+ */
+static LRESULT LISTBOX_SetHorizontalExtent( WND *wnd, LB_DESCR *descr,
+ UINT32 extent )
+{
+ if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
+ return LB_OKAY;
+ if (extent <= 0) extent = 1;
+ if (extent == descr->horz_extent) return LB_OKAY;
+ dprintf_listbox( stddeb, "Listbox %04x: new horz extent = %d\n",
+ wnd->hwndSelf, extent );
+ descr->horz_extent = extent;
+ if (descr->horz_pos > extent - descr->width)
+ LISTBOX_SetHorizontalPos( wnd, descr, extent - descr->width );
+ else
+ LISTBOX_UpdateScroll( wnd, descr );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetColumnWidth
+ */
+static LRESULT LISTBOX_SetColumnWidth( WND *wnd, LB_DESCR *descr, UINT32 width)
+{
+ width += 2; /* For left and right margin */
+ if (width == descr->column_width) return LB_OKAY;
+ dprintf_listbox( stddeb, "Listbox %04x: new column width = %d\n",
+ wnd->hwndSelf, width );
+ descr->column_width = width;
+ LISTBOX_UpdatePage( wnd, descr );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetFont
+ *
+ * Returns the item height.
+ */
+static INT32 LISTBOX_SetFont( WND *wnd, LB_DESCR *descr, HFONT32 font )
+{
+ HDC32 hdc;
+ HFONT32 oldFont = 0;
+ TEXTMETRIC32A tm;
+
+ descr->font = font;
+
+ if (!(hdc = GetDCEx32( wnd->hwndSelf, 0, DCX_CACHE )))
+ {
+ fprintf( stderr, "LISTBOX_SetFont: unable to get DC\n" );
+ return 16;
+ }
+ if (font) oldFont = SelectObject32( hdc, font );
+ GetTextMetrics32A( hdc, &tm );
+ if (oldFont) SelectObject32( hdc, oldFont );
+ ReleaseDC32( wnd->hwndSelf, hdc );
+ if (!IS_OWNERDRAW(descr))
+ LISTBOX_SetItemHeight( wnd, descr, 0, tm.tmHeight + 2 );
+ return tm.tmHeight + 2;
+}
+
+
+/***********************************************************************
+ * LISTBOX_MakeItemVisible
+ *
+ * Make sure that a given item is partially or fully visible.
+ */
+static void LISTBOX_MakeItemVisible( WND *wnd, LB_DESCR *descr, INT32 index,
+ BOOL32 fully )
+{
+ INT32 top;
+
+ if (index <= descr->top_item) top = index;
+ else if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT32 cols = descr->width;
+ if (!fully) cols += descr->column_width - 1;
+ if (cols >= descr->column_width) cols /= descr->column_width;
+ else cols = 1;
+ if (index < descr->top_item + (descr->page_size * cols)) return;
+ top = index - descr->page_size * (cols - 1);
+ }
+ else if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ INT32 height = fully ? descr->items[index].height : 1;
+ for (top = index; top > descr->top_item; top--)
+ if ((height += descr->items[top-1].height) > descr->height) break;
+ }
+ else
+ {
+ if (index < descr->top_item + descr->page_size) return;
+ if (!fully && (index == descr->top_item + descr->page_size) &&
+ (descr->height > (descr->page_size * descr->item_height))) return;
+ top = index - descr->page_size + 1;
+ }
+ LISTBOX_SetTopItem( wnd, descr, top, TRUE );
+}
+
+
+/***********************************************************************
+ * LISTBOX_SelectItemRange
+ *
+ * Select a range of items. Should only be used on a MULTIPLESEL listbox.
+ */
+static LRESULT LISTBOX_SelectItemRange( WND *wnd, LB_DESCR *descr, INT32 first,
+ INT32 last, BOOL32 on )
+{
+ INT32 i;
+
+ /* A few sanity checks */
+
+ if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+ if (last == -1) last = descr->nb_items - 1;
+ if ((first < 0) || (first >= descr->nb_items)) return LB_ERR;
+ if ((last < 0) || (last >= descr->nb_items)) return LB_ERR;
+ /* selected_item reflects last selected/unselected item on multiple sel */
+ descr->selected_item = last;
+
+ if (on) /* Turn selection on */
+ {
+ for (i = first; i <= last; i++)
+ {
+ if (descr->items[i].selected) continue;
+ descr->items[i].selected = TRUE;
+ LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT );
+ }
+ }
+ else /* Turn selection off */
+ {
+ for (i = first; i <= last; i++)
+ {
+ if (!descr->items[i].selected) continue;
+ descr->items[i].selected = FALSE;
+ LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT );
+ }
+ }
+ if (descr->style & LBS_NOTIFY)
+ SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetCaretIndex
+ */
+static LRESULT LISTBOX_SetCaretIndex( WND *wnd, LB_DESCR *descr, INT32 index,
+ BOOL32 fully_visible )
+{
+ INT32 oldfocus = descr->focus_item;
+
+ if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
+ if (index == oldfocus) return LB_OKAY;
+ descr->focus_item = index;
+ if ((oldfocus != -1) && descr->caret_on && (GetFocus32() == wnd->hwndSelf))
+ LISTBOX_RepaintItem( wnd, descr, oldfocus, ODA_FOCUS );
+ if (index != -1)
+ {
+ LISTBOX_MakeItemVisible( wnd, descr, index, fully_visible );
+ if (descr->caret_on && (GetFocus32() == wnd->hwndSelf))
+ LISTBOX_RepaintItem( wnd, descr, index, ODA_FOCUS );
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetSelection
+ */
+static LRESULT LISTBOX_SetSelection( WND *wnd, LB_DESCR *descr, INT32 index,
+ BOOL32 on, BOOL32 send_notify )
+{
+ if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
+ if (descr->style & LBS_MULTIPLESEL)
+ {
+ if (index == -1) /* Select all items */
+ return LISTBOX_SelectItemRange( wnd, descr, 0, -1, on );
+ else /* Only one item */
+ return LISTBOX_SelectItemRange( wnd, descr, index, index, on );
+ }
+ else
+ {
+ INT32 oldsel = descr->selected_item;
+ if (index == oldsel) return LB_OKAY;
+ if (oldsel != -1) descr->items[oldsel].selected = FALSE;
+ if (index != -1) descr->items[index].selected = TRUE;
+ descr->selected_item = index;
+/* FIXME if (index != -1) LISTBOX_MakeItemVisible( wnd, descr, index );*/
+ if (oldsel != -1) LISTBOX_RepaintItem( wnd, descr, oldsel, ODA_SELECT);
+ if (index != -1) LISTBOX_RepaintItem( wnd, descr, index, ODA_SELECT );
+ if (send_notify) SEND_NOTIFICATION( wnd, descr,
+ (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_MoveCaret
+ *
+ * Change the caret position and extend the selection to the new caret.
+ */
+static void LISTBOX_MoveCaret( WND *wnd, LB_DESCR *descr, INT32 index,
+ BOOL32 fully_visible )
+{
+ LISTBOX_SetCaretIndex( wnd, descr, index, fully_visible );
+ if (descr->style & LBS_EXTENDEDSEL)
+ {
+ if (descr->anchor_item != -1)
+ {
+ INT32 first = MIN( descr->focus_item, descr->anchor_item );
+ INT32 last = MAX( descr->focus_item, descr->anchor_item );
+ if (first > 0)
+ LISTBOX_SelectItemRange( wnd, descr, 0, first - 1, FALSE );
+ LISTBOX_SelectItemRange( wnd, descr, first, last, TRUE );
+ LISTBOX_SelectItemRange( wnd, descr, last + 1, -1, FALSE );
+ }
+ }
+ else if (!(descr->style & LBS_MULTIPLESEL) && (descr->selected_item != -1))
+ {
+ /* Set selection to new caret item */
+ LISTBOX_SetSelection( wnd, descr, index, TRUE,
+ (descr->style & LBS_NOTIFY) != 0 );
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_InsertItem
+ */
+static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT32 index,
+ LPSTR str, DWORD data )
+{
+ LB_ITEMDATA *item;
+ INT32 max_items;
+
+ if (index == -1) index = descr->nb_items;
+ else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
+ if (!descr->items) max_items = 0;
+ else max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
+ if (descr->nb_items == max_items)
+ {
+ /* We need to grow the array */
+ max_items += LB_ARRAY_GRANULARITY;
+ if (!(item = HeapReAlloc( descr->heap, 0, descr->items,
+ max_items * sizeof(LB_ITEMDATA) )))
+ {
+ SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+ return LB_ERRSPACE;
+ }
+ descr->items = item;
+ }
+
+ /* Insert the item structure */
+
+ item = &descr->items[index];
+ if (index < descr->nb_items)
+ RtlMoveMemory( item + 1, item,
+ (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
+ item->str = str;
+ item->data = data;
+ item->height = 0;
+ item->selected = FALSE;
+ descr->nb_items++;
+
+ /* Get item height */
+
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ MEASUREITEMSTRUCT32 mis;
+ mis.CtlType = ODT_LISTBOX;
+ mis.CtlID = wnd->wIDmenu;
+ mis.itemID = index;
+ mis.itemData = descr->items[index].data;
+ mis.itemHeight = descr->item_height;
+ SendMessage32A( descr->owner, WM_MEASUREITEM, wnd->wIDmenu,
+ (LPARAM)&mis );
+ item->height = mis.itemHeight ? mis.itemHeight : 1;
+ dprintf_listbox( stddeb, "Listbox %04x: measure item %d (%s) = %d\n",
+ wnd->hwndSelf, index, str ? str : "", item->height );
+ }
+
+ /* Repaint the items */
+
+ LISTBOX_UpdateScroll( wnd, descr );
+ LISTBOX_InvalidateItems( wnd, descr, index );
+
+ /* Move selection and focused item */
+
+ if (index <= descr->selected_item) descr->selected_item++;
+ if (index <= descr->focus_item)
+ {
+ descr->focus_item++;
+ LISTBOX_MoveCaret( wnd, descr, descr->focus_item - 1, FALSE );
+ }
+
+ /* If listbox was empty, set focus to the first item */
+
+ if (descr->nb_items == 1) LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_InsertString
+ */
+static LRESULT LISTBOX_InsertString( WND *wnd, LB_DESCR *descr, INT32 index,
+ LPCSTR str )
+{
+ LPSTR new_str = NULL;
+ DWORD data = 0;
+ LRESULT ret;
+
+ if (HAS_STRINGS(descr))
+ {
+ if (!(new_str = HEAP_strdupA( descr->heap, 0, str )))
+ {
+ SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+ return LB_ERRSPACE;
+ }
+ }
+ else data = (DWORD)str;
+
+ if (index == -1) index = descr->nb_items;
+ if ((ret = LISTBOX_InsertItem( wnd, descr, index, new_str, data )) != 0)
+ {
+ if (new_str) HeapFree( descr->heap, 0, new_str );
+ return ret;
+ }
+
+ dprintf_listbox( stddeb, "Listbox %04x: added item %d '%s'\n",
+ wnd->hwndSelf, index, HAS_STRINGS(descr) ? new_str : "" );
+ return index;
+}
+
+
+/***********************************************************************
+ * LISTBOX_DeleteItem
+ *
+ * Delete the content of an item. 'index' must be a valid index.
+ */
+static void LISTBOX_DeleteItem( WND *wnd, LB_DESCR *descr, INT32 index )
+{
+ /* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
+ * while Win95 sends it for all items with user data.
+ * It's probably better to send it too often than not
+ * often enough, so this is what we do here.
+ */
+ if (IS_OWNERDRAW(descr) || descr->items[index].data)
+ {
+ DELETEITEMSTRUCT32 dis;
+ dis.CtlType = ODT_LISTBOX;
+ dis.CtlID = wnd->wIDmenu;
+ dis.itemID = index;
+ dis.hwndItem = wnd->hwndSelf;
+ dis.itemData = descr->items[index].data;
+ SendMessage32A( wnd->hwndSelf, WM_DELETEITEM, wnd->wIDmenu,
+ (LPARAM)&dis );
+ }
+ if (HAS_STRINGS(descr) && descr->items[index].str)
+ HeapFree( descr->heap, 0, descr->items[index].str );
+}
+
+
+/***********************************************************************
+ * LISTBOX_RemoveItem
+ *
+ * Remove an item from the listbox and delete its content.
+ */
+static LRESULT LISTBOX_RemoveItem( WND *wnd, LB_DESCR *descr, INT32 index )
+{
+ LB_ITEMDATA *item;
+ INT32 max_items;
+
+ if (index == -1) index = descr->nb_items - 1;
+ else if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ LISTBOX_DeleteItem( wnd, descr, index );
+
+ /* Remove the item */
+
+ item = &descr->items[index];
+ if (index < descr->nb_items-1)
+ RtlMoveMemory( item, item + 1,
+ (descr->nb_items - index - 1) * sizeof(LB_ITEMDATA) );
+ descr->nb_items--;
+ if (descr->anchor_item == descr->nb_items) descr->anchor_item--;
+
+ /* Shrink the item array if possible */
+
+ max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(LB_ITEMDATA);
+ if (descr->nb_items < max_items - 2*LB_ARRAY_GRANULARITY)
+ {
+ max_items -= LB_ARRAY_GRANULARITY;
+ item = HeapReAlloc( descr->heap, 0, descr->items,
+ max_items * sizeof(LB_ITEMDATA) );
+ if (item) descr->items = item;
+ }
+
+ /* Repaint the items */
+
+ LISTBOX_UpdateScroll( wnd, descr );
+ LISTBOX_InvalidateItems( wnd, descr, index );
+
+ /* Move selection and focused item */
+
+ if (index <= descr->selected_item) descr->selected_item--;
+ if (index <= descr->focus_item)
+ {
+ descr->focus_item--;
+ LISTBOX_MoveCaret( wnd, descr, descr->focus_item + 1, FALSE );
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_ResetContent
+ */
+static void LISTBOX_ResetContent( WND *wnd, LB_DESCR *descr )
+{
+ INT32 i;
+
+ for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( wnd, descr, i );
+ if (descr->items) HeapFree( descr->heap, 0, descr->items );
+ descr->nb_items = 0;
+ descr->top_item = 0;
+ descr->selected_item = -1;
+ descr->focus_item = 0;
+ descr->anchor_item = -1;
+ descr->items = NULL;
+ LISTBOX_UpdateScroll( wnd, descr );
+ InvalidateRect32( wnd->hwndSelf, NULL, TRUE );
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetCount
+ */
+static LRESULT LISTBOX_SetCount( WND *wnd, LB_DESCR *descr, INT32 count )
+{
+ LRESULT ret;
+
+ if (HAS_STRINGS(descr)) return LB_ERR;
+ /* FIXME: this is far from optimal... */
+ if (count > descr->nb_items)
+ {
+ while (count > descr->nb_items)
+ if ((ret = LISTBOX_InsertString( wnd, descr, -1, 0 )) < 0)
+ return ret;
+ }
+ else if (count < descr->nb_items)
+ {
+ while (count < descr->nb_items)
+ if ((ret = LISTBOX_RemoveItem( wnd, descr, -1 )) < 0)
+ return ret;
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_Directory
+ */
+LRESULT LISTBOX_Directory( WND *wnd, LB_DESCR *descr, UINT32 attrib,
+ LPCSTR filespec, BOOL32 long_names )
+{
+ char mask[13];
+ const char *ptr;
char *path, *p;
+ int count, skip, pos;
+ LRESULT ret;
+ DOS_DIRENT entry;
- dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
+ /* FIXME: should use FindFirstFile/FindNextFile */
+
if (!filespec) return LB_ERR;
if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
- path = xstrdup(ptr);
+ path = HEAP_strdupA( SystemHeap, 0, ptr );
p = strrchr( path, '/' );
*p++ = '\0';
- if (!(ptr = DOSFS_ToDosFCBFormat( p )) ||
- !(temp = SEGPTR_ALLOC( sizeof(char) * 16 )) )
+ if (!(ptr = DOSFS_ToDosFCBFormat( p )))
{
- free( path );
+ HeapFree( SystemHeap, 0, path );
return LB_ERR;
}
-
strcpy( mask, ptr );
- dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
-
- skip = ret = 0;
+ skip = 0;
+ ret = LB_OKAY;
attrib &= ~FA_LABEL;
while ((count = DOSFS_FindNext( path, mask, NULL, 0,
attrib, skip, &entry )) > 0)
{
+ char buffer[260];
skip += count;
if (entry.attr & FA_DIRECTORY)
{
- if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". "))
- {
- sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
- AnsiLower( temp );
- if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
- }
+ if (!(attrib & DDL_DIRECTORY) || !strcmp(entry.name,". "))
+ continue;
+ if (long_names) sprintf( buffer, "[%s]", entry.unixname );
+ else sprintf( buffer, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
}
else /* not a directory */
{
- if (!(attrib & DDL_EXCLUSIVE) ||
- ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
+ if ((attrib & DDL_EXCLUSIVE) &&
+ ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) !=
(entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
- {
- strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
- AnsiLower( temp );
- if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
- }
+ continue;
+ if (long_names) strcpy( buffer, entry.unixname );
+ else strcpy( buffer, DOSFS_ToDosDTAFormat( entry.name ) );
}
-
- dprintf_listbox(stddeb,"\tn - %i, file '%s'\n", count, temp);
+ if (!long_names) AnsiLower( buffer );
+ pos = LISTBOX_FindFileStrPos( wnd, descr, buffer );
+ if ((ret = LISTBOX_InsertString( wnd, descr, pos, buffer )) < 0)
+ break;
}
- if (attrib & DDL_DRIVES)
+
+ if ((ret == LB_OKAY) && (attrib & DDL_DRIVES))
{
- int x;
- DWORD oldstyle = lphl->dwStyle;
-
- lphl->dwStyle &= ~LBS_SORT;
- strcpy( temp, "[-a-]" );
- for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
+ char buffer[] = "[-a-]";
+ int drive;
+ for (drive = 0; drive < MAX_DOS_DRIVES; drive++, buffer[2]++)
{
- if (DRIVE_IsValid(x))
- if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
+ if (!DRIVE_IsValid(drive)) continue;
+ if ((ret = LISTBOX_InsertString( wnd, descr, -1, buffer )) < 0)
+ break;
}
- lphl->dwStyle = oldstyle;
}
- free( path );
- SEGPTR_FREE( temp );
-
+ HeapFree( SystemHeap, 0, path );
return ret;
}
-/* ------------------------- dimensions ------------------------- */
-int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT16 lprect)
+/***********************************************************************
+ * LISTBOX_HandleVScroll
+ */
+static LRESULT LISTBOX_HandleVScroll( WND *wnd, LB_DESCR *descr,
+ WPARAM32 wParam, LPARAM lParam )
{
- LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
+ SCROLLINFO info;
- dprintf_listbox(stddeb,"ListBox LB_GETITEMRECT %i %p", wIndex,lpls);
- if (lpls == NULL)
- {
- if (lphl->dwStyle & LBS_OWNERDRAWVARIABLE)
- return LB_ERR;
- else
+ if (descr->style & LBS_MULTICOLUMN) return 0;
+ switch(LOWORD(wParam))
{
- GetClientRect16(lphl->hSelf,lprect);
- lprect->bottom=lphl->StdItemHeight;
- if (lprect->right<0) lprect->right=0;
+ case SB_LINEUP:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item - 1, TRUE );
+ break;
+ case SB_LINEDOWN:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item + 1, TRUE );
+ break;
+ case SB_PAGEUP:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item -
+ LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE );
+ break;
+ case SB_PAGEDOWN:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item +
+ LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE );
+ break;
+ case SB_THUMBPOSITION:
+ LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam), TRUE );
+ break;
+ case SB_THUMBTRACK:
+ info.cbSize = sizeof(info);
+ info.fMask = SIF_TRACKPOS;
+ GetScrollInfo32( wnd->hwndSelf, SB_VERT, &info );
+ LISTBOX_SetTopItem( wnd, descr, info.nTrackPos, TRUE );
+ break;
+ case SB_TOP:
+ LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
+ break;
+ case SB_BOTTOM:
+ LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE );
+ break;
}
- }
- else
- *lprect = lpls->itemRect;
- dprintf_listbox(stddeb," = %d,%d %d,%d\n", lprect->left,lprect->top,
- lprect->right,lprect->bottom);
- return 0;
-}
-
-
-int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
-{
- LPLISTSTRUCT lpls;
-
- if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
- lphl->StdItemHeight = (short)height;
return 0;
- }
-
- lpls = ListBoxGetItem(lphl, wIndex);
- if (lpls == NULL) return LB_ERR;
-
- lpls->mis.itemHeight = height;
- return 0;
-}
-
-/* -------------------------- string search ------------------------ */
-
-int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
-{
- LPLISTSTRUCT lpls;
- UINT count,first;
-
- if ((char)wChar < ' ') return LB_ERR;
- if (!lphl->HasStrings) return LB_ERR;
-
- lpls = lphl->lpFirst;
-
- for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
- if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
- }
- if (lpls == NULL) return LB_ERR;
- first = count;
- for(; lpls != NULL; lpls = lpls->lpNext, count++) {
- if (*lpls->itemText != (char)wChar)
- break;
- if ((short) count > lphl->ItemFocused)
- return count;
- }
- return first;
-}
-
-/***********************************************************************
- * LBCreate
- */
-static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl;
- LONG dwStyle = GetWindowLong32A(hwnd,GWL_STYLE);
- RECT16 rect;
-
- CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent16(hwnd));
- lphl = ListBoxGetStorageHeader(hwnd);
- dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n",
- lphl, HIWORD(dwStyle), LOWORD(dwStyle));
-
- GetClientRect16(hwnd,&rect);
- lphl->ColumnsWidth = rect.right - rect.left;
-
- if (dwStyle & WS_VSCROLL)
- SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
- if (dwStyle & WS_HSCROLL)
- SetScrollRange32(hwnd, SB_HORZ, 1, 1, TRUE);
-
- return 0;
}
/***********************************************************************
- * LBDestroy
+ * LISTBOX_HandleHScroll
*/
-static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleHScroll( WND *wnd, LB_DESCR *descr,
+ WPARAM32 wParam, LPARAM lParam )
{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
+ SCROLLINFO info;
+ INT32 page;
- ListBoxResetContent(lphl);
-
- DestroyListBoxStruct(lphl);
- dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
- return 0;
-}
-
-
-/***********************************************************************
- * LBNCCalcSize
- */
-static LONG LBNCCalcSize(HWND hwnd, WORD wParam, LONG lParam)
-{
- LONG ret = DefWindowProc16(hwnd, WM_NCCALCSIZE, wParam, lParam);
-
- return (GetWindowLong32A(hwnd,GWL_STYLE) & LBS_MULTICOLUMN)? WVR_VREDRAW : ret;
-}
-
-
-/***********************************************************************
- * LBVScroll
- */
-static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- int y;
-
- dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
- wParam, lParam);
- y = lphl->FirstVisible;
-
- switch(wParam) {
- case SB_LINEUP:
- if (lphl->FirstVisible > 0)
- lphl->FirstVisible--;
- break;
-
- case SB_LINEDOWN:
- lphl->FirstVisible++;
- break;
-
- case SB_PAGEUP:
- if (lphl->FirstVisible > lphl->ItemsVisible) {
- lphl->FirstVisible -= lphl->ItemsVisible;
- } else {
- lphl->FirstVisible = 0;
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ switch(LOWORD(wParam))
+ {
+ case SB_LINELEFT:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item-descr->page_size,
+ TRUE );
+ break;
+ case SB_LINERIGHT:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item+descr->page_size,
+ TRUE );
+ break;
+ case SB_PAGELEFT:
+ page = descr->width / descr->column_width;
+ if (page < 1) page = 1;
+ LISTBOX_SetTopItem( wnd, descr,
+ descr->top_item - page * descr->page_size, TRUE );
+ break;
+ case SB_PAGERIGHT:
+ page = descr->width / descr->column_width;
+ if (page < 1) page = 1;
+ LISTBOX_SetTopItem( wnd, descr,
+ descr->top_item + page * descr->page_size, TRUE );
+ break;
+ case SB_THUMBPOSITION:
+ LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam)*descr->page_size,
+ TRUE );
+ break;
+ case SB_THUMBTRACK:
+ info.cbSize = sizeof(info);
+ info.fMask = SIF_TRACKPOS;
+ GetScrollInfo32( wnd->hwndSelf, SB_VERT, &info );
+ LISTBOX_SetTopItem( wnd, descr, info.nTrackPos*descr->page_size,
+ TRUE );
+ break;
+ case SB_LEFT:
+ LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
+ break;
+ case SB_RIGHT:
+ LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE );
+ break;
+ }
}
- break;
-
- case SB_PAGEDOWN:
- lphl->FirstVisible += lphl->ItemsVisible;
- break;
-
- case SB_THUMBTRACK:
- lphl->FirstVisible = LOWORD(lParam);
- break;
- }
-
- if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
- lphl->FirstVisible = ListMaxFirstVisible(lphl);
-
- if (y != lphl->FirstVisible) {
- SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
- InvalidateRect32( hwnd, NULL, TRUE );
- }
- return 0;
+ else if (descr->horz_extent)
+ {
+ switch(LOWORD(wParam))
+ {
+ case SB_LINELEFT:
+ LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos - 1 );
+ break;
+ case SB_LINERIGHT:
+ LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos + 1 );
+ break;
+ case SB_PAGELEFT:
+ LISTBOX_SetHorizontalPos( wnd, descr,
+ descr->horz_pos - descr->width );
+ break;
+ case SB_PAGERIGHT:
+ LISTBOX_SetHorizontalPos( wnd, descr,
+ descr->horz_pos + descr->width );
+ break;
+ case SB_THUMBPOSITION:
+ LISTBOX_SetHorizontalPos( wnd, descr, HIWORD(wParam) );
+ break;
+ case SB_THUMBTRACK:
+ info.cbSize = sizeof(info);
+ info.fMask = SIF_TRACKPOS;
+ GetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info );
+ LISTBOX_SetHorizontalPos( wnd, descr, info.nTrackPos );
+ break;
+ case SB_LEFT:
+ LISTBOX_SetHorizontalPos( wnd, descr, 0 );
+ break;
+ case SB_RIGHT:
+ LISTBOX_SetHorizontalPos( wnd, descr,
+ descr->horz_extent - descr->width );
+ break;
+ }
+ }
+ return 0;
}
+
/***********************************************************************
- * LBHScroll
+ * LISTBOX_HandleLButtonDown
*/
-static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleLButtonDown( WND *wnd, LB_DESCR *descr,
+ WPARAM32 wParam, INT32 x, INT32 y )
{
- LPHEADLIST lphl;
- int y;
-
- dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
- wParam, lParam);
- lphl = ListBoxGetStorageHeader(hwnd);
- y = lphl->FirstVisible;
- switch(wParam) {
- case SB_LINEUP:
- if (lphl->FirstVisible > lphl->ItemsPerColumn) {
- lphl->FirstVisible -= lphl->ItemsPerColumn;
- } else {
- lphl->FirstVisible = 0;
+ INT32 index = LISTBOX_GetItemFromPoint( wnd, descr, x, y );
+ dprintf_listbox( stddeb, "Listbox %04x: lbuttondown %d,%d item %d\n",
+ wnd->hwndSelf, x, y, index );
+ if (!descr->caret_on && (GetFocus32() == wnd->hwndSelf)) return 0;
+ if (index != -1)
+ {
+ if (descr->style & LBS_EXTENDEDSEL)
+ {
+ if (!(wParam & MK_SHIFT)) descr->anchor_item = index;
+ if (wParam & MK_CONTROL)
+ {
+ LISTBOX_SetCaretIndex( wnd, descr, index, FALSE );
+ LISTBOX_SetSelection( wnd, descr, index,
+ !descr->items[index].selected,
+ (descr->style & LBS_NOTIFY) != 0 );
+ }
+ else LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+ }
+ else
+ {
+ LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+ LISTBOX_SetSelection( wnd, descr, index,
+ (!(descr->style & LBS_MULTIPLESEL) ||
+ !descr->items[index].selected),
+ (descr->style & LBS_NOTIFY) != 0 );
+ }
}
- break;
- case SB_LINEDOWN:
- lphl->FirstVisible += lphl->ItemsPerColumn;
- break;
- case SB_PAGEUP:
- if (lphl->ItemsPerColumn != 0) {
- int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
- if (lphl->FirstVisible > lbsub) {
- lphl->FirstVisible -= lbsub;
- } else {
- lphl->FirstVisible = 0;
- }
+ SetFocus32( wnd->hwndSelf );
+ SetCapture32( wnd->hwndSelf );
+ if (index != -1)
+ {
+ if (descr->style & LBS_NOTIFY)
+ SendMessage32A( descr->owner, WM_LBTRACKPOINT, index,
+ MAKELPARAM( x, y ) );
+ if (wnd->dwExStyle & WS_EX_DRAGDETECT)
+ {
+ POINT16 pt = { x, y };
+ if (DragDetect( wnd->hwndSelf, pt ))
+ SendMessage32A( descr->owner, WM_BEGINDRAG, 0, 0 );
+ }
}
- break;
- case SB_PAGEDOWN:
- if (lphl->ItemsPerColumn != 0)
- lphl->FirstVisible += lphl->ItemsVisible /
- lphl->ItemsPerColumn * lphl->ItemsPerColumn;
- break;
- case SB_THUMBTRACK:
- lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
- break;
- }
- if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
- lphl->FirstVisible = ListMaxFirstVisible(lphl);
-
- if (lphl->ItemsPerColumn != 0) {
- lphl->FirstVisible = lphl->FirstVisible /
- lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
- if (y != lphl->FirstVisible) {
- SetScrollPos32(hwnd, SB_HORZ, lphl->FirstVisible /
- lphl->ItemsPerColumn + 1, TRUE);
- InvalidateRect32( hwnd, NULL, TRUE );
- }
- }
- return 0;
+ return 0;
}
-/***********************************************************************
- * LBLButtonDown
- */
-static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- WORD wRet;
- int y,n;
- RECT16 rectsel;
-
- SetFocus32(hwnd);
- SetCapture32(hwnd);
-
- lphl->PrevFocused = lphl->ItemFocused;
-
- y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
-
- if (y == -1) return 0;
-
- if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR )
- if( SendMessage16(lphl->hParent, WM_LBTRACKPOINT, y, lParam) )
- return 0;
-
-
- switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
- {
- case LBS_MULTIPLESEL:
- lphl->ItemFocused = y;
- wRet = ListBoxGetSel(lphl, y);
- ListBoxSetSel(lphl, y, !wRet);
- break;
- case LBS_EXTENDEDSEL:
- /* should handle extended mode here and in kbd handler
- */
-
- if ( lphl->PrevFocused != y && y!= LB_ERR)
- {
- LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y );
- n = ListBoxSetSel(lphl,-1,FALSE);
-
- lpls->itemState = ODS_FOCUS | ODS_SELECTED;
-
- if( n > 1 && n != LB_ERR )
- InvalidateRect32( hwnd,NULL,TRUE );
- }
- else
- return 0;
-
- break;
- case 0:
- if( y!=lphl->ItemFocused )
- ListBoxSetCurSel(lphl, y);
- else
- return 0;
- break;
- default:
- fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
- return 0;
- }
-
- /* invalidate changed items */
- if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused )
- {
- ListBoxGetItemRect(lphl, y, &rectsel);
- InvalidateRect16( hwnd, &rectsel, TRUE );
- }
- if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused )
- {
- ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
- InvalidateRect16( hwnd, &rectsel, TRUE );
- }
-
- if (GetWindowLong32A(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
- if( DragDetect(lphl->hSelf,MAKEPOINT16(lParam)) )
- SendMessage16(lphl->hParent, WM_BEGINDRAG,0,0L);
- return 0;
-}
/***********************************************************************
- * LBLButtonUp
- */
-static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- if (GetCapture32() == hwnd) ReleaseCapture();
-
- if (lphl->PrevFocused != lphl->ItemFocused)
- ListBoxSendNotification(lphl, LBN_SELCHANGE);
-
- return 0;
-}
-
-/***********************************************************************
- * LBRButtonUp
- */
-static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- SendMessage16(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
- MAKELONG(hwnd, LBN_DBLCLK));
- return 0;
-}
-
-/***********************************************************************
- * LBMouseMove
- */
-static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- int y,redraw_prev = 0;
- int iRet;
- RECT16 rect, rectsel; /* XXX Broken */
-
- dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
- if ((wParam & MK_LBUTTON) != 0) {
- y = SHIWORD(lParam);
- if (y < LBMM_EDGE) {
- if (lphl->FirstVisible > 0) {
- lphl->FirstVisible--;
- SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
- InvalidateRect32( hwnd, NULL, TRUE );
- return 0;
- }
- }
- GetClientRect16(hwnd, &rect);
- if (y >= (rect.bottom-LBMM_EDGE)) {
- if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
- lphl->FirstVisible++;
- SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
- InvalidateRect32( hwnd, NULL, TRUE );
- return 0;
- }
- }
- if ((y > 0) && (y < (rect.bottom - LBMM_EDGE))) {
- if ((y < rectsel.top) || (y > rectsel.bottom)) {
- iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
- if (iRet == lphl->ItemFocused || iRet == -1) {
- return 0;
- }
- if (lphl->dwStyle & LBS_MULTIPLESEL) {
- lphl->ItemFocused = iRet;
- ListBoxSendNotification(lphl, LBN_SELCHANGE);
- } else if ( lphl->dwStyle & LBS_EXTENDEDSEL )
- {
- /* Fixme: extended selection mode */
- ListBoxSetSel( lphl, lphl->ItemFocused, 0);
- lphl->PrevFocused = lphl->ItemFocused;
- lphl->ItemFocused = iRet;
- ListBoxSetSel( lphl, iRet, TRUE);
- redraw_prev = 1;
- }
- else
- {
- ListBoxSetCurSel(lphl, (WORD)iRet);
- redraw_prev = 1;
- }
- if( lphl->PrevFocused!=-1 && redraw_prev )
- {
- ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
- InvalidateRect16( hwnd, &rectsel, TRUE );
- }
- ListBoxGetItemRect(lphl, iRet, &rectsel);
- InvalidateRect16( hwnd, &rectsel, TRUE );
- }
- }
- }
-
- return 0;
- }
-
-/***********************************************************************
- * LBKeyDown
+ * LISTBOX_HandleTimer
*
- * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
+ * Handle scrolling upon a timer event.
+ * Return TRUE if scrolling should continue.
*/
-static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleTimer( WND *wnd, LB_DESCR *descr,
+ INT32 index, TIMER_DIRECTION dir )
{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- WORD newFocused = 0xFFFF;
- RECT16 rect;
-
- ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
- switch(wParam)
+ switch(dir)
{
- case VK_HOME:
- case VK_END:
- case VK_LEFT:
- case VK_RIGHT:
- case VK_UP:
- case VK_DOWN:
- case VK_PRIOR:
- case VK_NEXT:
- if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT )
- {
- newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_VKEYTOITEM,
- wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
- if ( newFocused == 0xFFFE ) return 0L;
- }
- if ( newFocused == 0xFFFF )
- {
- newFocused = lphl->ItemFocused;
-
- /* nested switch */
- switch(wParam)
- {
- case VK_HOME:
- newFocused = 0;
- break;
- case VK_END:
- newFocused = lphl->ItemsCount - 1;
- break;
- case VK_LEFT:
- if (lphl->dwStyle & LBS_MULTICOLUMN) {
- if (newFocused >= lphl->ItemsPerColumn) {
- newFocused -= lphl->ItemsPerColumn;
- } else {
- newFocused = 0;
- }
- }
- break;
- case VK_UP:
- if (newFocused > 0) newFocused--;
- break;
- case VK_RIGHT:
- if (lphl->dwStyle & LBS_MULTICOLUMN)
- newFocused += lphl->ItemsPerColumn;
- break;
- case VK_DOWN:
- newFocused++;
- break;
- case VK_PRIOR:
- if (newFocused > lphl->ItemsVisible)
- newFocused -= lphl->ItemsVisible;
- else newFocused = 0;
- break;
- case VK_NEXT:
- newFocused += lphl->ItemsVisible;
- break;
- default:
- return 0;
- }
- /* end of nested switch */
- }
- break;
- case VK_SPACE:
- if (lphl->dwStyle & LBS_MULTIPLESEL)
- {
- WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
- ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
- }
- return 0;
-
- /* chars are handled in LBChar */
- default:
- return 0;
+ case LB_TIMER_UP:
+ if (descr->top_item) index = descr->top_item - 1;
+ else index = 0;
+ break;
+ case LB_TIMER_LEFT:
+ if (descr->top_item) index -= descr->page_size;
+ break;
+ case LB_TIMER_DOWN:
+ index = descr->top_item + LISTBOX_GetCurrentPageSize( wnd, descr );
+ if (index >= descr->nb_items) index = descr->nb_items - 1;
+ break;
+ case LB_TIMER_RIGHT:
+ if (index + descr->page_size < descr->nb_items)
+ index += descr->page_size;
+ break;
+ case LB_TIMER_NONE:
+ break;
}
+ if (index == descr->focus_item) return FALSE;
+ LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+ return TRUE;
+}
- /* at this point newFocused is set up */
- if (newFocused >= lphl->ItemsCount)
- newFocused = lphl->ItemsCount - 1;
-
- if (!(lphl->dwStyle & LBS_MULTIPLESEL))
- {
- ListBoxSetCurSel(lphl, newFocused);
- ListBoxSendNotification(lphl, LBN_SELCHANGE);
- }
-
- lphl->ItemFocused = newFocused;
-
- if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle &
- (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
- InvalidateRect32( hwnd, NULL, TRUE );
- else
+/***********************************************************************
+ * LISTBOX_HandleSystemTimer
+ *
+ * WM_SYSTIMER handler.
+ */
+static LRESULT LISTBOX_HandleSystemTimer( WND *wnd, LB_DESCR *descr )
+{
+ if (!LISTBOX_HandleTimer( wnd, descr, descr->focus_item, LISTBOX_Timer ))
{
- InvalidateRect16( hwnd, &rect, TRUE );
- if( newFocused < 0x8000 )
- {
- ListBoxGetItemRect(lphl, newFocused, &rect);
- InvalidateRect16( hwnd, &rect, TRUE );
- }
+ KillSystemTimer32( wnd->hwndSelf, LB_TIMER_ID );
+ LISTBOX_Timer = LB_TIMER_NONE;
}
-
- SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-
- return 0;
-}
-
-/***********************************************************************
- * LBChar
- */
-static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- WORD newFocused = 0xFFFF;
-
- if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
- {
- newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_CHARTOITEM,
- wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
- if ( newFocused == 0xFFFE ) return 0L;
- }
-
- if (newFocused == 0xFFFF )
- newFocused = ListBoxFindNextMatch(lphl, wParam);
-
- if (newFocused == (WORD)LB_ERR) return 0;
-
- if (newFocused >= lphl->ItemsCount)
- newFocused = lphl->ItemsCount - 1;
-
- if (!(lphl->dwStyle & LBS_MULTIPLESEL))
- {
- ListBoxSetCurSel(lphl, newFocused);
- ListBoxSendNotification(lphl, LBN_SELCHANGE);
- }
-
- lphl->ItemFocused = newFocused;
- ListBoxScrollToFocus(lphl);
- SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-
- InvalidateRect32( hwnd, NULL, TRUE );
-
- return 0;
-}
-
-/***********************************************************************
- * LBSetRedraw
- */
-static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
- hwnd, wParam);
- lphl->bRedrawFlag = wParam;
-
- return 0;
-}
-
-/***********************************************************************
- * LBSetFont
- */
-static LONG LBSetFont(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- HDC32 hdc;
-
- if (wParam == 0)
- lphl->hFont = GetStockObject32(SYSTEM_FONT);
- else
- lphl->hFont = (HFONT16)wParam;
-
- /* a new font means possible new text height */
- /* does this mean the height of each entry must be separately changed? */
- /* or are we guaranteed to get a LBSetFont before the first insert/add? */
- if ((hdc = GetDC32(0)))
- {
- TEXTMETRIC16 tm;
- GetTextMetrics16( hdc, &tm );
- lphl->StdItemHeight = tm.tmHeight;
- dprintf_listbox(stddeb,"LBSetFont: new font %d with height %d\n",
- lphl->hFont, lphl->StdItemHeight);
- ReleaseDC32( 0, hdc );
- }
-
- return 0;
-}
-
-/***********************************************************************
- * LBPaint
- */
-static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- LPLISTSTRUCT lpls;
- PAINTSTRUCT16 ps;
- HBRUSH16 hBrush;
- HFONT32 hOldFont;
- HDC16 hdc = BeginPaint16( hwnd, &ps );
- DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
- RECT16 rect, paintRect, scratchRect;
- int i, top, height, maxwidth, ipc;
-
- top = 0;
-
- if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
- EndPaint16(hwnd, &ps);
return 0;
- }
-
- GetRgnBox16(dc->w.hGCClipRgn,&paintRect);
- GetClientRect16(hwnd, &rect);
- IntersectRect16(&paintRect,&rect,&paintRect);
-
- hOldFont = SelectObject32(hdc, lphl->hFont);
-
- hBrush = (HBRUSH16)SendMessage32A( lphl->hParent, WM_CTLCOLORLISTBOX,
- (WPARAM32)hdc, (LPARAM)hwnd);
- if (hBrush == 0) hBrush = GetStockObject32(WHITE_BRUSH);
-
- FillRect16(hdc, &rect, hBrush);
-
- maxwidth = rect.right;
- if (lphl->dwStyle & LBS_MULTICOLUMN) {
- rect.right = lphl->ColumnsWidth;
- }
- lpls = lphl->lpFirst;
-
- lphl->ItemsVisible = 0;
- lphl->ItemsPerColumn = ipc = 0;
-
- for(i = 0; i < lphl->ItemsCount; i++) {
- if (lpls == NULL) break;
-
- if (i >= lphl->FirstVisible) {
- height = lpls->mis.itemHeight;
-
- if (top > (rect.bottom-height+1)) {
- if (lphl->dwStyle & LBS_MULTICOLUMN) {
- lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
- ipc = 0;
- top = 0;
- rect.left += lphl->ColumnsWidth;
- rect.right += lphl->ColumnsWidth;
- if (rect.left > maxwidth) break;
- } else {
- break;
- }
- }
-
- lpls->itemRect.top = top;
- lpls->itemRect.bottom = top + height;
- lpls->itemRect.left = rect.left;
- lpls->itemRect.right = rect.right;
-
- if( IntersectRect16(&scratchRect,&paintRect,&lpls->itemRect) )
- {
- dprintf_listbox(stddeb,"LBPaint: drawing item: %d %d %d %d %d\n",
- rect.left,top,rect.right,top+height,lpls->itemState);
-
- if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus32() == hwnd)
- {
- ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS,
- lpls->itemState & ~ODS_FOCUS);
- ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
- lpls->itemState & ~ODS_FOCUS);
- ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState);
- }
- else
- ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
- lpls->itemState);
- }
-
- top += height;
- lphl->ItemsVisible++;
- ipc++;
- }
-
- lpls = lpls->lpNext;
- }
- ListBoxUpdateWindow(hwnd,lphl,FALSE);
- SelectObject32(hdc,hOldFont);
- EndPaint16( hwnd, &ps );
- return 0;
}
+
/***********************************************************************
- * LBSetFocus
+ * LISTBOX_HandleMouseMove
+ *
+ * WM_MOUSEMOVE handler.
*/
-static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
+static void LISTBOX_HandleMouseMove( WND *wnd, LB_DESCR *descr,
+ INT32 x, INT32 y )
{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
+ INT32 index;
+ TIMER_DIRECTION dir;
- dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for %04x\n",hwnd);
- if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
- if( lphl->ItemsCount && lphl->ItemFocused != -1)
- {
- HDC32 hDC = GetDC32(hwnd);
- HFONT32 hOldFont = SelectObject32(hDC, lphl->hFont);
- LPLISTSTRUCT lpls;
-
- lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
- lpls->itemState |= ODS_FOCUS;
-
- ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
- SelectObject32(hDC, hOldFont);
- ReleaseDC32(hwnd,hDC);
- }
-
- ListBoxSendNotification(lphl, LBN_SETFOCUS);
-
- return 0;
-}
-
-/***********************************************************************
- * LBKillFocus
- */
-static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for %04x\n",hwnd);
- if (!(lphl->dwStyle & LBS_MULTIPLESEL))
- {
- if( lphl->ItemsCount )
- if( lphl->ItemFocused != -1 )
- {
- HDC32 hDC = GetDC32(hwnd);
- HFONT32 hOldFont = SelectObject32(hDC, lphl->hFont);
- LPLISTSTRUCT lpls;
-
- lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
- lpls->itemState &= ~ODS_FOCUS;
-
- ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
- SelectObject32(hDC, hOldFont);
- ReleaseDC32(hwnd,hDC);
- }
- else
- dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
- }
- else
- InvalidateRect32( hwnd, NULL, TRUE );
-
- ListBoxSendNotification(lphl, LBN_KILLFOCUS);
-
- return 0;
-}
-
-/***********************************************************************
- * LBResetContent
- */
-static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
- ListBoxResetContent(lphl);
- ListBoxUpdateWindow(hwnd, lphl, TRUE);
- return 0;
-}
-
-/***********************************************************************
- * LBDir
- */
-static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
-{
- LONG ret;
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
-
- ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
- ListBoxUpdateWindow(hwnd, lphl, TRUE);
- return ret;
-}
-
-/***********************************************************************
- * LBAddString
- */
-static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
-{
- WORD wRet;
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- wRet = ListBoxAddString(lphl, (SEGPTR)lParam);
-
- ListBoxUpdateWindow(hwnd,lphl,TRUE);
- return wRet;
-}
-
-/***********************************************************************
- * LBGetText
- */
-static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
-{
- LONG wRet;
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam);
- wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
-
- return wRet;
-}
-
-/***********************************************************************
- * LBInsertString
- */
-static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
-{
- WORD wRet;
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- if (lphl->HasStrings)
- wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
- else
- wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
-
- ListBoxUpdateWindow(hwnd,lphl,TRUE);
- return wRet;
-}
-
-/***********************************************************************
- * LBDeleteString
- */
-static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- LONG lRet = ListBoxDeleteString(lphl,wParam);
-
- ListBoxUpdateWindow(hwnd,lphl,TRUE);
- return lRet;
-}
-
-/***********************************************************************
- * LBFindString
- */
-static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- return lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_SUBSTR);
-}
-
-/***********************************************************************
- * LBFindStringExact
- */
-static LONG LBFindStringExact(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- return lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_EXACT);
-}
-
-/***********************************************************************
- * LBGetCaretIndex
- */
-static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- return lphl->ItemFocused;
-}
-
-/***********************************************************************
- * LBGetCount
- */
-static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl;
-
- lphl = ListBoxGetStorageHeader(hwnd);
- return lphl->ItemsCount;
-}
-
-/***********************************************************************
- * LBGetCurSel
- */
-static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl;
-
- lphl = ListBoxGetStorageHeader(hwnd);
- dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n",
- lphl->ItemFocused);
- return lphl->ItemFocused;
-}
-
-/***********************************************************************
- * LBGetHorizontalExtent
- */
-static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
-{
- return 0;
-}
-
-/***********************************************************************
- * LBGetItemHeight
- */
-static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
-
- if (lpls == NULL) return LB_ERR;
- return lpls->mis.itemHeight;
-}
-
-/***********************************************************************
- * LBGetItemRect
- */
-static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
-}
-
-/***********************************************************************
- * LBGetSel
- */
-static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- int iSel = ListBoxGetSel(lphl, wParam);
-
- dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel);
-
- return (iSel)? 1 : 0;
-}
-
-/***********************************************************************
- * LBGetSelCount
- */
-static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- LPLISTSTRUCT lpls;
- int cnt = 0;
- int items = 0;
-
- if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
- return LB_ERR;
-
- for( lpls = lphl->lpFirst;
- lpls;
- lpls = lpls->lpNext )
- {
- items++;
- if (lpls->itemState )
- cnt++;
- }
-
- return cnt;
-}
-
-/***********************************************************************
- * LBGetSelItems
- */
-static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- LPLISTSTRUCT lpls;
- int cnt, idx;
- int *lpItems = PTR_SEG_TO_LIN(lParam);
-
- if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
- return LB_ERR;
-
- if (wParam == 0) return 0;
-
- lpls = lphl->lpFirst;
- cnt = 0; idx = 0;
-
- while (lpls != NULL) {
- if (lpls->itemState > 0) lpItems[cnt++] = idx;
-
- if (cnt == wParam) break;
- idx++;
- lpls = lpls->lpNext;
- }
-
- return cnt;
-}
-
-/***********************************************************************
- * LBGetTextLen
- */
-static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
-
- if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
- return strlen(lpls->itemText);
-}
-
-/***********************************************************************
- * LBGetDlgCode
- */
-static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
-{
- return DLGC_WANTARROWS | DLGC_WANTCHARS;
-}
-
-/***********************************************************************
- * LBGetTopIndex
- */
-static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- return lphl->FirstVisible;
-}
-
-
-/***********************************************************************
- * LBSelectString
- */
-static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- INT iRet;
-
- iRet = lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_SUBSTR);
-
- if( iRet != LB_ERR)
+ if (descr->style & LBS_MULTICOLUMN)
{
- if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
- ListBoxSetSel(lphl,iRet,TRUE);
- else
- ListBoxSetCurSel(lphl,iRet);
+ if (y < 0) y = 0;
+ else if (y >= descr->item_height * descr->page_size)
+ y = descr->item_height * descr->page_size - 1;
- lphl->ItemFocused = iRet;
- InvalidateRect32( hwnd, 0, TRUE );
+ if (x < 0)
+ {
+ dir = LB_TIMER_LEFT;
+ x = 0;
+ }
+ else if (x >= descr->width)
+ {
+ dir = LB_TIMER_RIGHT;
+ x = descr->width - 1;
+ }
+ else dir = LB_TIMER_NONE; /* inside */
}
- return iRet;
+ else
+ {
+ if (y < 0) dir = LB_TIMER_UP; /* above */
+ else if (y >= descr->height) dir = LB_TIMER_DOWN; /* below */
+ else dir = LB_TIMER_NONE; /* inside */
+ }
+
+ index = LISTBOX_GetItemFromPoint( wnd, descr, x, y );
+ if (index == -1) index = descr->focus_item;
+ if (!LISTBOX_HandleTimer( wnd, descr, index, dir )) dir = LB_TIMER_NONE;
+
+ /* Start/stop the system timer */
+
+ if (dir != LB_TIMER_NONE)
+ SetSystemTimer32( wnd->hwndSelf, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
+ else if (LISTBOX_Timer != LB_TIMER_NONE)
+ KillSystemTimer32( wnd->hwndSelf, LB_TIMER_ID );
+ LISTBOX_Timer = dir;
}
+
/***********************************************************************
- * LBSelItemRange
+ * LISTBOX_HandleKeyDown
*/
-static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr,
+ WPARAM32 wParam )
{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- LPLISTSTRUCT lpls;
- WORD cnt;
- WORD first = LOWORD(lParam);
- WORD last = HIWORD(lParam);
- BOOL select = wParam;
-
- if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ))
- return LB_ERR;
-
- if (first >= lphl->ItemsCount ||
- last >= lphl->ItemsCount) return LB_ERR;
-
- lpls = lphl->lpFirst;
- cnt = 0;
-
- while (lpls != NULL) {
- if (cnt++ >= first)
- lpls->itemState = select ? lpls->itemState | ODS_SELECTED : 0;
-
- if (cnt > last)
- break;
-
- lpls = lpls->lpNext;
- }
-
- return 0;
+ INT32 caret = -1;
+ if (descr->style & LBS_WANTKEYBOARDINPUT)
+ {
+ caret = SendMessage32A( descr->owner, WM_VKEYTOITEM,
+ MAKEWPARAM(LOWORD(wParam), descr->focus_item),
+ wnd->hwndSelf );
+ if (caret == -2) return 0;
+ }
+ if (caret == -1) switch(wParam)
+ {
+ case VK_LEFT:
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ if (descr->focus_item >= descr->page_size)
+ caret = descr->focus_item - descr->page_size;
+ break;
+ }
+ /* fall through */
+ case VK_UP:
+ caret = descr->focus_item - 1;
+ if (caret < 0) caret = 0;
+ break;
+ case VK_RIGHT:
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ if (descr->focus_item + descr->page_size < descr->nb_items)
+ caret = descr->focus_item + descr->page_size;
+ break;
+ }
+ /* fall through */
+ case VK_DOWN:
+ caret = descr->focus_item + 1;
+ if (caret >= descr->nb_items) caret = descr->nb_items - 1;
+ break;
+ case VK_PRIOR:
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT32 page = descr->width / descr->column_width;
+ if (page < 1) page = 1;
+ caret = descr->focus_item - (page * descr->page_size) + 1;
+ }
+ else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(wnd,descr)+1;
+ if (caret < 0) caret = 0;
+ break;
+ case VK_NEXT:
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT32 page = descr->width / descr->column_width;
+ if (page < 1) page = 1;
+ caret = descr->focus_item + (page * descr->page_size) - 1;
+ }
+ else caret = descr->focus_item+LISTBOX_GetCurrentPageSize(wnd,descr)-1;
+ if (caret >= descr->nb_items) caret = descr->nb_items - 1;
+ break;
+ case VK_HOME:
+ caret = 0;
+ break;
+ case VK_END:
+ caret = descr->nb_items - 1;
+ break;
+ case VK_SPACE:
+ if (descr->style & LBS_EXTENDEDSEL)
+ {
+ if (!(GetKeyState(VK_SHIFT) & 0x8000))
+ descr->anchor_item = descr->focus_item;
+ LISTBOX_MoveCaret( wnd, descr, descr->focus_item, TRUE );
+ }
+ else if (descr->style & LBS_MULTIPLESEL)
+ LISTBOX_SetSelection( wnd, descr, descr->focus_item,
+ !descr->items[descr->focus_item].selected,
+ (descr->style & LBS_NOTIFY) != 0 );
+ break;
+ }
+ if (caret >= 0)
+ {
+ if ((descr->style & LBS_EXTENDEDSEL) &&
+ !(GetKeyState( VK_SHIFT ) & 0x8000))
+ descr->anchor_item = caret;
+ LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
+ }
+ return 0;
}
+
/***********************************************************************
- * LBSetCaretIndex
+ * LISTBOX_HandleChar
*/
-static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleChar( WND *wnd, LB_DESCR *descr,
+ WPARAM32 wParam )
{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- int i;
+ INT32 index;
+ char str[2] = { wParam & 0xff, '\0' };
- if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0;
-
- dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd,wParam);
-
- if (wParam >= lphl->ItemsCount) return LB_ERR;
-
- lphl->ItemFocused = wParam;
- i = ListBoxScrollToFocus (lphl);
-
- SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
- if(i)
- InvalidateRect32( hwnd, NULL, TRUE );
-
- return 1;
+ index = LISTBOX_FindString( wnd, descr, descr->focus_item, str, FALSE );
+ if (index != LB_ERR) LISTBOX_MoveCaret( wnd, descr, index, TRUE );
+ return 0;
}
-/***********************************************************************
- * LBSetColumnWidth
- */
-static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- lphl->ColumnsWidth = wParam;
- InvalidateRect32( hwnd, NULL, TRUE );
- return 0;
-}
/***********************************************************************
- * LBSetHorizontalExtent
+ * LISTBOX_Create
*/
-static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
+static BOOL32 LISTBOX_Create( WND *wnd )
{
- return 0;
-}
+ LB_DESCR *descr;
+ MEASUREITEMSTRUCT32 mis;
+ RECT32 rect;
-/***********************************************************************
- * LBGetItemData
- */
-static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
- return ListBoxGetItemData(lphl, wParam);
-}
+ if (!(descr = HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) )))
+ return FALSE;
+ if (!(descr->heap = HeapCreate( 0, 0x10000, 0 )))
+ {
+ HeapFree( GetProcessHeap(), 0, descr );
+ return FALSE;
+ }
+ GetClientRect32( wnd->hwndSelf, &rect );
+ descr->owner = GetParent32( wnd->hwndSelf );
+ descr->style = wnd->dwStyle;
+ descr->width = rect.right - rect.left;
+ descr->height = rect.bottom - rect.top;
+ descr->items = NULL;
+ descr->nb_items = 0;
+ descr->top_item = 0;
+ descr->selected_item = -1;
+ descr->focus_item = 0;
+ descr->anchor_item = -1;
+ descr->item_height = 1;
+ descr->page_size = 1;
+ descr->column_width = 150;
+ descr->horz_extent = (wnd->dwStyle & WS_HSCROLL) ? 1 : 0;
+ descr->horz_pos = 0;
+ descr->nb_tabs = 0;
+ descr->tabs = NULL;
+ descr->caret_on = TRUE;
+ descr->font = 0;
+ descr->locale = 0; /* FIXME */
-/***********************************************************************
- * LBSetItemData
- */
-static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam);
- return ListBoxSetItemData(lphl, wParam, lParam);
-}
+ *(LB_DESCR **)wnd->wExtra = descr;
-/***********************************************************************
- * LBSetTabStops
- */
-static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl;
+ if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
+ if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
+ if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
+ descr->item_height = LISTBOX_SetFont( wnd, descr, 0 );
- lphl = ListBoxGetStorageHeader(hwnd);
+ if (descr->style & LBS_OWNERDRAWFIXED)
+ {
+ mis.CtlType = ODT_LISTBOX;
+ mis.CtlID = wnd->wIDmenu;
+ mis.itemID = 0;
+ mis.itemWidth = 0;
+ mis.itemData = 0;
+ mis.itemHeight = descr->item_height;
+ SendMessage32A( descr->owner, WM_MEASUREITEM, wnd->wIDmenu,
+ (LPARAM)&mis );
+ descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
+ }
- if (lphl->TabStops != NULL) {
- lphl->iNumStops = 0;
- free (lphl->TabStops);
- }
-
- lphl->TabStops = malloc (wParam * sizeof (short));
- if (lphl->TabStops) {
- lphl->iNumStops = wParam;
- memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
return TRUE;
- }
-
- return FALSE;
}
+
/***********************************************************************
- * LBSetCurSel
+ * LISTBOX_Destroy
*/
-static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
+static BOOL32 LISTBOX_Destroy( WND *wnd, LB_DESCR *descr )
{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- WORD wRet;
-
- dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n",
- wParam);
-
- wRet = ListBoxSetCurSel(lphl, wParam);
-
- SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
- InvalidateRect32( hwnd, NULL, TRUE );
-
- return wRet;
-}
-
-/***********************************************************************
- * LBSetSel
- */
-static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- RECT16 rect;
- int iRet;
-
- dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
-
- iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
-
- if( iRet > 1 ) InvalidateRect32( hwnd, NULL, TRUE );
- else if( iRet != LB_ERR )
- {
- if( lphl->dwStyle & LBS_EXTENDEDSEL &&
- lphl->ItemFocused != LOWORD(lParam) )
- {
- ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect);
- InvalidateRect16( hwnd, &rect, TRUE );
- lphl->ItemFocused = LOWORD(lParam);
- }
- ListBoxGetItemRect(lphl,LOWORD(lParam),&rect);
- InvalidateRect16( hwnd, &rect, TRUE );
- }
-
- return (iRet == (WORD)LB_ERR)? LB_ERR: 0;
-}
-
-/***********************************************************************
- * LBSetTopIndex
- */
-static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
- wParam);
- lphl->FirstVisible = wParam;
- SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-
- InvalidateRect32( hwnd, NULL, TRUE );
-
- return 0;
-}
-
-/***********************************************************************
- * LBSetItemHeight
- */
-static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
-{
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
- WORD wRet;
-
- dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
- wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
- InvalidateRect32( hwnd, NULL, TRUE );
- return wRet;
-}
-
-/***********************************************************************
- * LBPassToParent
- */
-static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam)
-{
- WND* ptrWnd = WIN_FindWndPtr(hwnd);
-
- if( ptrWnd )
- if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */
- ptrWnd->parent )
- return SendMessage16(ptrWnd->parent->hwndSelf,message,wParam,lParam);
- return 0;
-}
-
-/***********************************************************************
- * ListBoxWndProc
- */
-LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam)
-{
- switch (message) {
- case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
- case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
- case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
- case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
- case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
- case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
- case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
- case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
- case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
- case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
- case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
- case WM_CHAR: return LBChar(hwnd, wParam, lParam);
- case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
- case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
- case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
- case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
- case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
- case WM_NCCALCSIZE: return LBNCCalcSize(hwnd, wParam, lParam);
- case LB_RESETCONTENT16: return LBResetContent(hwnd, wParam, lParam);
- case LB_DIR16: return LBDir(hwnd, wParam, lParam);
- case LB_ADDSTRING16: return LBAddString(hwnd, wParam, lParam);
- case LB_INSERTSTRING16: return LBInsertString(hwnd, wParam, lParam);
- case LB_DELETESTRING16: return LBDeleteString(hwnd, wParam, lParam);
- case LB_FINDSTRING16: return LBFindString(hwnd, wParam, lParam);
- case LB_FINDSTRINGEXACT16: return LBFindStringExact(hwnd, wParam, lParam);
- case LB_GETCARETINDEX16: return LBGetCaretIndex(hwnd, wParam, lParam);
- case LB_GETCOUNT16: return LBGetCount(hwnd, wParam, lParam);
- case LB_GETCURSEL16: return LBGetCurSel(hwnd, wParam, lParam);
- case LB_GETHORIZONTALEXTENT16: return LBGetHorizontalExtent(hwnd, wParam, lParam);
- case LB_GETITEMDATA16: return LBGetItemData(hwnd, wParam, lParam);
- case LB_GETITEMHEIGHT16: return LBGetItemHeight(hwnd, wParam, lParam);
- case LB_GETITEMRECT16: return LBGetItemRect(hwnd, wParam, lParam);
- case LB_GETSEL16: return LBGetSel(hwnd, wParam, lParam);
- case LB_GETSELCOUNT16: return LBGetSelCount(hwnd, wParam, lParam);
- case LB_GETSELITEMS16: return LBGetSelItems(hwnd, wParam, lParam);
- case LB_GETTEXT16: return LBGetText(hwnd, wParam, lParam);
- case LB_GETTEXTLEN16: return LBGetTextLen(hwnd, wParam, lParam);
- case LB_GETTOPINDEX16: return LBGetTopIndex(hwnd, wParam, lParam);
- case LB_SELECTSTRING16: return LBSelectString(hwnd, wParam, lParam);
- case LB_SELITEMRANGE16: return LBSelItemRange(hwnd, wParam, lParam);
- case LB_SETCARETINDEX16: return LBSetCaretIndex(hwnd, wParam, lParam);
- case LB_SETCOLUMNWIDTH16: return LBSetColumnWidth(hwnd, wParam, lParam);
- case LB_SETHORIZONTALEXTENT16: return LBSetHorizontalExtent(hwnd, wParam, lParam);
- case LB_SETITEMDATA16: return LBSetItemData(hwnd, wParam, lParam);
- case LB_SETTABSTOPS16: return LBSetTabStops(hwnd, wParam, lParam);
- case LB_SETCURSEL16: return LBSetCurSel(hwnd, wParam, lParam);
- case LB_SETSEL16: return LBSetSel(hwnd, wParam, lParam);
- case LB_SETTOPINDEX16: return LBSetTopIndex(hwnd, wParam, lParam);
- case LB_SETITEMHEIGHT16: return LBSetItemHeight(hwnd, wParam, lParam);
-
- case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
-
- /* these will have to be implemented for proper LBS_EXTENDEDSEL -
- *
- * anchor item is an item that with caret (focused) item defines a
- * range of currently selected items when listbox is in the extended
- * selection mode.
- */
- case LB_SETANCHORINDEX16: return LB_SETANCHORINDEX16; /* that's what Windows returns */
- case LB_GETANCHORINDEX16: return 0;
-
- case WM_DROPOBJECT:
- case WM_QUERYDROPOBJECT:
- case WM_DRAGSELECT:
- case WM_DRAGMOVE:
- {
- LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
- LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
- lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
- lpDragInfo->pt.y);
-
- return LBPassToParent(hwnd, message, wParam, lParam);
- }
- }
-
- return DefWindowProc16(hwnd, message, wParam, lParam);
-}
-
-
-/**********************************************************************
- * DlgDirList (USER.100)
- */
-INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
-{
- char *filespec = (char *)PTR_SEG_TO_LIN( spec );
- int drive;
- HWND hwnd;
-
-#define SENDMSG(msg,wparam,lparam) \
- ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
- : SendMessage16( hwnd, msg, wparam, lparam ))
-
- dprintf_listbox( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n",
- hDlg, filespec ? filespec : "NULL",
- idLBox, idStatic, attrib );
-
- if (filespec && filespec[0] && (filespec[1] == ':'))
- {
- drive = toupper( filespec[0] ) - 'A';
- filespec += 2;
- if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
- }
- else drive = DRIVE_GetCurrentDrive();
-
- if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
- {
- char mask[20];
-
- if (!filespec || !filespec[0]) strcpy( mask, "*.*" );
- else
- {
- /* If the path exists and is a directory, chdir to it */
- if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" );
- else
- {
- char *p, *p2;
- p = filespec;
- if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
- if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
- lstrcpyn32A( mask, p, sizeof(mask) );
- if (p != filespec)
- {
- p[-1] = '\0';
- if (!DRIVE_Chdir( drive, filespec )) return FALSE;
- }
- }
- }
-
- strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
-
- dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
- 'A' + drive, DRIVE_GetDosCwd(drive), mask);
-
- SENDMSG( LB_RESETCONTENT16, 0, 0 );
- if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
- {
- char *temp;
- if (SENDMSG( LB_DIR16, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
- (LPARAM)spec ) == LB_ERR) return FALSE;
- if (!(temp = SEGPTR_ALLOC( 4*sizeof(char) ))) return FALSE;
- strcpy( temp, "*.*" );
- /* FIXME: this won't work with PostMessage(), as temp will */
- /* have been freed by the time we do a DispatchMessage(). */
- if (SENDMSG( LB_DIR16, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
- (LPARAM)SEGPTR_GET(temp) ) == LB_ERR)
- {
- SEGPTR_FREE(temp);
- return FALSE;
- }
- SEGPTR_FREE(temp);
- }
- else
- {
- if (SENDMSG( LB_DIR16, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
- }
- }
-
- if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
- {
- char temp[512];
- int drive = DRIVE_GetCurrentDrive();
- strcpy( temp, "A:\\" );
- temp[0] += drive;
- lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
- AnsiLower( temp );
- /* Can't use PostMessage() here, because the string is on the stack */
- SetDlgItemText32A( hDlg, idStatic, temp );
- }
+ LISTBOX_ResetContent( wnd, descr );
+ HeapDestroy( descr->heap );
+ HeapFree( GetProcessHeap(), 0, descr );
+ *(LB_DESCR **)wnd->wExtra = NULL;
return TRUE;
-#undef SENDMSG
+}
+
+
+/***********************************************************************
+ * ListBoxWndProc
+ */
+LRESULT ListBoxWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
+{
+ LRESULT ret;
+ LB_DESCR *descr;
+ WND *wnd = WIN_FindWndPtr( hwnd );
+
+ if (!wnd) return 0;
+ if (!(descr = *(LB_DESCR **)wnd->wExtra))
+ {
+ if (msg == WM_CREATE)
+ {
+ if (!LISTBOX_Create( wnd )) return -1;
+ dprintf_listbox( stddeb, "Listbox: creating wnd=%04x descr=%p\n",
+ hwnd, *(LB_DESCR **)wnd->wExtra );
+ return 0;
+ }
+ /* Ignore all other messages before we get a WM_CREATE */
+ return DefWindowProc32A( hwnd, msg, wParam, lParam );
+ }
+
+ dprintf_listbox( stddeb, "Listbox %04x: msg %s wp %08x lp %08lx\n",
+ wnd->hwndSelf, SPY_GetMsgName(msg), wParam, lParam );
+ switch(msg)
+ {
+ case LB_RESETCONTENT16:
+ case LB_RESETCONTENT32:
+ LISTBOX_ResetContent( wnd, descr );
+ return 0;
+
+ case LB_ADDSTRING16:
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+ /* fall through */
+ case LB_ADDSTRING32:
+ wParam = LISTBOX_FindStringPos( wnd, descr, (LPCSTR)lParam, FALSE );
+ return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+ case LB_INSERTSTRING16:
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+ wParam = (INT32)(INT16)wParam;
+ /* fall through */
+ case LB_INSERTSTRING32:
+ return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+ case LB_ADDFILE16:
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+ /* fall through */
+ case LB_ADDFILE32:
+ wParam = LISTBOX_FindFileStrPos( wnd, descr, (LPCSTR)lParam );
+ return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+ case LB_DELETESTRING16:
+ case LB_DELETESTRING32:
+ return LISTBOX_RemoveItem( wnd, descr, wParam );
+
+ case LB_GETITEMDATA16:
+ case LB_GETITEMDATA32:
+ if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items))
+ return LB_ERR;
+ return descr->items[wParam].data;
+
+ case LB_SETITEMDATA16:
+ case LB_SETITEMDATA32:
+ if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items))
+ return LB_ERR;
+ descr->items[wParam].data = (DWORD)lParam;
+ return LB_OKAY;
+
+ case LB_GETCOUNT16:
+ case LB_GETCOUNT32:
+ return descr->nb_items;
+
+ case LB_GETTEXT16:
+ lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+ /* fall through */
+ case LB_GETTEXT32:
+ return LISTBOX_GetText( wnd, descr, wParam, (LPSTR)lParam );
+
+ case LB_GETTEXTLEN16:
+ /* fall through */
+ case LB_GETTEXTLEN32:
+ if (wParam >= descr->nb_items) return LB_ERR;
+ return (HAS_STRINGS(descr) ? strlen(descr->items[wParam].str)
+ : sizeof(DWORD));
+
+ case LB_GETCURSEL16:
+ case LB_GETCURSEL32:
+ return descr->selected_item;
+
+ case LB_GETTOPINDEX16:
+ case LB_GETTOPINDEX32:
+ return descr->top_item;
+
+ case LB_GETITEMHEIGHT16:
+ case LB_GETITEMHEIGHT32:
+ return LISTBOX_GetItemHeight( wnd, descr, wParam );
+
+ case LB_SETITEMHEIGHT16:
+ lParam = LOWORD(lParam);
+ /* fall through */
+ case LB_SETITEMHEIGHT32:
+ return LISTBOX_SetItemHeight( wnd, descr, wParam, lParam );
+
+ case LB_ITEMFROMPOINT32:
+ {
+ POINT32 pt = { LOWORD(lParam), HIWORD(lParam) };
+ RECT32 rect = { 0, 0, descr->width, descr->height };
+ return MAKELONG( LISTBOX_GetItemFromPoint(wnd, descr, pt.x, pt.y),
+ PtInRect32( &rect, pt ) );
+ }
+
+ case LB_SETCARETINDEX16:
+ case LB_SETCARETINDEX32:
+ return LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam );
+
+ case LB_GETCARETINDEX16:
+ case LB_GETCARETINDEX32:
+ return descr->focus_item;
+
+ case LB_SETTOPINDEX16:
+ case LB_SETTOPINDEX32:
+ return LISTBOX_SetTopItem( wnd, descr, wParam, TRUE );
+
+ case LB_SETCOLUMNWIDTH16:
+ case LB_SETCOLUMNWIDTH32:
+ return LISTBOX_SetColumnWidth( wnd, descr, wParam );
+
+ case LB_GETITEMRECT16:
+ {
+ RECT32 rect;
+ ret = LISTBOX_GetItemRect( wnd, descr, (INT16)wParam, &rect );
+ CONV_RECT32TO16( &rect, (RECT16 *)PTR_SEG_TO_LIN(lParam) );
+ }
+ return ret;
+
+ case LB_GETITEMRECT32:
+ return LISTBOX_GetItemRect( wnd, descr, wParam, (RECT32 *)lParam );
+
+ case LB_FINDSTRING16:
+ wParam = (INT32)(INT16)wParam;
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+ /* fall through */
+ case LB_FINDSTRING32:
+ return LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, FALSE );
+
+ case LB_FINDSTRINGEXACT16:
+ wParam = (INT32)(INT16)wParam;
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+ /* fall through */
+ case LB_FINDSTRINGEXACT32:
+ return LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, TRUE );
+
+ case LB_SELECTSTRING16:
+ wParam = (INT32)(INT16)wParam;
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+ /* fall through */
+ case LB_SELECTSTRING32:
+ {
+ INT32 index = LISTBOX_FindString( wnd, descr, wParam,
+ (LPCSTR)lParam, FALSE );
+ if (index == LB_ERR) return LB_ERR;
+ LISTBOX_SetSelection( wnd, descr, index, TRUE,
+ (descr->style & LBS_NOTIFY) != 0 );
+ return index;
+ }
+
+ case LB_GETSEL16:
+ wParam = (INT32)(INT16)wParam;
+ /* fall through */
+ case LB_GETSEL32:
+ if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items))
+ return LB_ERR;
+ return descr->items[wParam].selected;
+
+ case LB_SETSEL16:
+ lParam = (INT32)(INT16)lParam;
+ /* fall through */
+ case LB_SETSEL32:
+ return LISTBOX_SetSelection( wnd, descr, lParam, wParam,
+ (descr->style & LBS_NOTIFY) != 0 );
+
+ case LB_SETCURSEL16:
+ wParam = (INT32)(INT16)wParam;
+ /* fall through */
+ case LB_SETCURSEL32:
+ return LISTBOX_SetSelection( wnd, descr, wParam, TRUE, FALSE );
+
+ case LB_GETSELCOUNT16:
+ case LB_GETSELCOUNT32:
+ return LISTBOX_GetSelCount( wnd, descr );
+
+ case LB_GETSELITEMS16:
+ return LISTBOX_GetSelItems16( wnd, descr, wParam,
+ (LPINT16)PTR_SEG_TO_LIN(lParam) );
+
+ case LB_GETSELITEMS32:
+ return LISTBOX_GetSelItems32( wnd, descr, wParam, (LPINT32)lParam );
+
+ case LB_SELITEMRANGE16:
+ case LB_SELITEMRANGE32:
+ return LISTBOX_SelectItemRange( wnd, descr, LOWORD(lParam),
+ HIWORD(lParam), wParam );
+
+ case LB_SELITEMRANGEEX16:
+ case LB_SELITEMRANGEEX32:
+ if ((INT32)lParam >= (INT32)wParam)
+ return LISTBOX_SelectItemRange( wnd, descr, wParam, lParam, TRUE );
+ else
+ return LISTBOX_SelectItemRange( wnd, descr, lParam, wParam, FALSE);
+
+ case LB_GETHORIZONTALEXTENT16:
+ case LB_GETHORIZONTALEXTENT32:
+ return descr->horz_extent;
+
+ case LB_SETHORIZONTALEXTENT16:
+ case LB_SETHORIZONTALEXTENT32:
+ return LISTBOX_SetHorizontalExtent( wnd, descr, wParam );
+
+ case LB_GETANCHORINDEX16:
+ case LB_GETANCHORINDEX32:
+ return descr->anchor_item;
+
+ case LB_SETANCHORINDEX16:
+ wParam = (INT32)(INT16)wParam;
+ /* fall through */
+ case LB_SETANCHORINDEX32:
+ if (((INT32)wParam < -1) || ((INT32)wParam >= descr->nb_items))
+ return LB_ERR;
+ descr->anchor_item = (INT32)wParam;
+ return LB_OKAY;
+
+ case LB_DIR16:
+ return LISTBOX_Directory( wnd, descr, wParam,
+ (LPCSTR)PTR_SEG_TO_LIN(lParam), FALSE );
+
+ case LB_DIR32:
+ return LISTBOX_Directory( wnd, descr, wParam, (LPCSTR)lParam, TRUE );
+
+ case LB_GETLOCALE32:
+ return descr->locale;
+
+ case LB_SETLOCALE32:
+ descr->locale = (LCID)wParam; /* FIXME: should check for valid lcid */
+ return LB_OKAY;
+
+ case LB_INITSTORAGE32:
+ return LISTBOX_InitStorage( wnd, descr, wParam, (DWORD)lParam );
+
+ case LB_SETCOUNT32:
+ return LISTBOX_SetCount( wnd, descr, (INT32)wParam );
+
+ case LB_SETTABSTOPS16:
+ return LISTBOX_SetTabStops( wnd, descr, (INT32)(INT16)wParam,
+ (LPINT32)PTR_SEG_TO_LIN(lParam), TRUE );
+
+ case LB_SETTABSTOPS32:
+ return LISTBOX_SetTabStops( wnd, descr, wParam,
+ (LPINT32)lParam, FALSE );
+
+ case LB_CARETON16:
+ case LB_CARETON32:
+ if (descr->caret_on) return LB_OKAY;
+ descr->caret_on = TRUE;
+ if ((descr->focus_item != -1) && (GetFocus32() == wnd->hwndSelf))
+ LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+ return LB_OKAY;
+
+ case LB_CARETOFF16:
+ case LB_CARETOFF32:
+ if (!descr->caret_on) return LB_OKAY;
+ descr->caret_on = FALSE;
+ if ((descr->focus_item != -1) && (GetFocus32() == wnd->hwndSelf))
+ LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+ return LB_OKAY;
+
+ case WM_DESTROY:
+ return LISTBOX_Destroy( wnd, descr );
+
+ case WM_ENABLE:
+ InvalidateRect32( hwnd, NULL, TRUE );
+ return 0;
+
+ case WM_SETREDRAW:
+ LISTBOX_SetRedraw( wnd, descr, wParam != 0 );
+ return 0;
+
+ case WM_GETDLGCODE:
+ return DLGC_WANTARROWS | DLGC_WANTCHARS;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT32 ps;
+ HDC32 hdc = BeginPaint32( hwnd, &ps );
+ ret = LISTBOX_Paint( wnd, descr, hdc );
+ EndPaint32( hwnd, &ps );
+ }
+ return ret;
+
+ case WM_SIZE:
+ LISTBOX_UpdateSize( wnd, descr );
+ return 0;
+
+ case WM_GETFONT:
+ return descr->font;
+
+ case WM_SETFONT:
+ LISTBOX_SetFont( wnd, descr, (HFONT32)wParam );
+ if (lParam) InvalidateRect32( wnd->hwndSelf, 0, TRUE );
+ return 0;
+
+ case WM_SETFOCUS:
+ descr->caret_on = TRUE;
+ if (descr->focus_item != -1)
+ LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+ SEND_NOTIFICATION( wnd, descr, LBN_SETFOCUS );
+ return 0;
+
+ case WM_KILLFOCUS:
+ if ((descr->focus_item != -1) && descr->caret_on)
+ LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+ SEND_NOTIFICATION( wnd, descr, LBN_KILLFOCUS );
+ return 0;
+
+ case WM_HSCROLL:
+ return LISTBOX_HandleHScroll( wnd, descr, wParam, lParam );
+
+ case WM_VSCROLL:
+ return LISTBOX_HandleVScroll( wnd, descr, wParam, lParam );
+
+ case WM_LBUTTONDOWN:
+ return LISTBOX_HandleLButtonDown( wnd, descr, wParam,
+ (INT16)LOWORD(lParam),
+ (INT16)HIWORD(lParam) );
+
+ case WM_LBUTTONDBLCLK:
+ if (descr->style & LBS_NOTIFY)
+ SEND_NOTIFICATION( wnd, descr, LBN_DBLCLK );
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture32() == hwnd)
+ LISTBOX_HandleMouseMove( wnd, descr, (INT16)LOWORD(lParam),
+ (INT16)HIWORD(lParam) );
+ return 0;
+
+ case WM_LBUTTONUP:
+ if (LISTBOX_Timer != LB_TIMER_NONE)
+ KillSystemTimer32( hwnd, LB_TIMER_ID );
+ LISTBOX_Timer = LB_TIMER_NONE;
+ if (GetCapture32() == hwnd) ReleaseCapture();
+ return 0;
+
+ case WM_KEYDOWN:
+ return LISTBOX_HandleKeyDown( wnd, descr, wParam );
+
+ case WM_CHAR:
+ return LISTBOX_HandleChar( wnd, descr, wParam );
+
+ case WM_SYSTIMER:
+ return LISTBOX_HandleSystemTimer( wnd, descr );
+
+ case WM_ERASEBKGND:
+ if (IS_OWNERDRAW(descr))
+ {
+ RECT32 rect = { 0, 0, descr->width, descr->height };
+ HBRUSH32 hbrush = SendMessage32A( descr->owner, WM_CTLCOLORLISTBOX,
+ wParam, (LPARAM)wnd->hwndSelf );
+ if (hbrush) FillRect32( (HDC32)wParam, &rect, hbrush );
+ }
+ return 1;
+
+ case WM_DROPFILES:
+ return SendMessage32A( descr->owner, msg, wParam, lParam );
+
+ case WM_DROPOBJECT:
+ case WM_QUERYDROPOBJECT:
+ case WM_DRAGSELECT:
+ case WM_DRAGMOVE:
+ {
+ LPDRAGINFO dragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN( (SEGPTR)lParam );
+ dragInfo->l = LISTBOX_GetItemFromPoint( wnd, descr, dragInfo->pt.x,
+ dragInfo->pt.y );
+ return SendMessage32A( descr->owner, msg, wParam, lParam );
+ }
+
+ default:
+ if ((msg >= WM_USER) && (msg < 0xc000))
+ fprintf(stderr,"Listbox %04x: unknown msg %04x wp %08x lp %08lx\n",
+ hwnd, msg, wParam, lParam );
+ return DefWindowProc32A( hwnd, msg, wParam, lParam );
+ }
+ return 0;
}