00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <string.h>
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <os2win.h>
00019 #include "controls.h"
00020 #include "winerror.h"
00021 #include "combo.h"
00022 #include <misc.h>
00023 #include "heapstring.h"
00024
00025 #define DBG_LOCALLOG DBG_listbox
00026 #include "dbglocal.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #define MAX_DOS_DRIVES 26 //a..z
00051
00052 BOOL DRIVE_IsValid( int drive )
00053 {
00054 if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0;
00055
00056 return (GetLogicalDrives() & (1 << drive));
00057 }
00058
00059
00060 #define LB_ARRAY_GRANULARITY 16
00061
00062
00063 #define LB_SCROLL_TIMEOUT 50
00064
00065
00066 #define LB_TIMER_ID 2
00067
00068
00069 typedef struct
00070 {
00071 LPSTR str;
00072 BOOL selected;
00073 UINT height;
00074 DWORD data;
00075 } LB_ITEMDATA;
00076
00077
00078 typedef struct
00079 {
00080 HANDLE heap;
00081 HWND owner;
00082 UINT style;
00083 INT width;
00084 INT height;
00085 LB_ITEMDATA *items;
00086 INT nb_items;
00087 INT top_item;
00088 INT selected_item;
00089 INT focus_item;
00090 INT anchor_item;
00091 INT item_height;
00092 INT page_size;
00093 INT column_width;
00094 INT horz_extent;
00095 INT horz_pos;
00096 INT nb_tabs;
00097 INT *tabs;
00098 BOOL caret_on;
00099 BOOL captured;
00100 BOOL in_focus;
00101 HFONT font;
00102 LCID locale;
00103 LPHEADCOMBO lphc;
00104 } LB_DESCR;
00105
00106
00107 #define IS_OWNERDRAW(descr) \
00108 ((descr)->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))
00109
00110 #define HAS_STRINGS(descr) \
00111 (!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
00112
00113 #define HAS_NODATA(descr) \
00114 ((descr)->style & LBS_NODATA)
00115
00116 #define IS_MULTISELECT(descr) \
00117 ((descr)->style & LBS_MULTIPLESEL || ((descr)->style & LBS_EXTENDEDSEL))
00118
00119 #define SEND_NOTIFICATION(hwnd,descr,code) \
00120 (SendMessageA( (descr)->owner, WM_COMMAND, \
00121 MAKEWPARAM(GetWindowLongA(hwnd,GWL_ID), (code)), hwnd ))
00122
00123
00124 typedef enum
00125 {
00126 LB_TIMER_NONE,
00127 LB_TIMER_UP,
00128 LB_TIMER_LEFT,
00129 LB_TIMER_DOWN,
00130 LB_TIMER_RIGHT
00131 } TIMER_DIRECTION;
00132
00133 static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
00134
00135
00136
00137
00138
00139
00140
00141 static INT LISTBOX_GetCurrentPageSize( HWND hwnd, LB_DESCR *descr )
00142 {
00143 INT i, height;
00144 if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size;
00145 for (i = descr->top_item, height = 0; i < descr->nb_items; i++)
00146 {
00147 if ((height += descr->items[i].height) > descr->height) break;
00148 }
00149 if (i == descr->top_item) return 1;
00150 else return i - descr->top_item;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 static INT LISTBOX_GetMaxTopIndex( HWND hwnd, LB_DESCR *descr )
00160 {
00161 INT max, page;
00162
00163 if (descr->style & LBS_OWNERDRAWVARIABLE)
00164 {
00165 page = descr->height;
00166 for (max = descr->nb_items - 1; max >= 0; max--)
00167 if ((page -= descr->items[max].height) < 0) break;
00168 if (max < descr->nb_items - 1) max++;
00169 }
00170 else if (descr->style & LBS_MULTICOLUMN)
00171 {
00172 if ((page = descr->width / descr->column_width) < 1) page = 1;
00173 max = (descr->nb_items + descr->page_size - 1) / descr->page_size;
00174 max = (max - page) * descr->page_size;
00175 }
00176 else
00177 {
00178 max = descr->nb_items - descr->page_size;
00179 }
00180 if (max < 0) max = 0;
00181 return max;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191 static void LISTBOX_UpdateScroll( HWND hwnd, LB_DESCR *descr )
00192 {
00193 SCROLLINFO info;
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 if (descr->style & LBS_NOREDRAW) return;
00211 info.cbSize = sizeof(info);
00212
00213 if (descr->style & LBS_MULTICOLUMN)
00214 {
00215 info.nMin = 0;
00216 info.nMax = (descr->nb_items - 1) / descr->page_size;
00217 info.nPos = descr->top_item / descr->page_size;
00218 info.nPage = descr->width / descr->column_width;
00219 if (info.nPage < 1) info.nPage = 1;
00220 info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
00221 if (descr->style & LBS_DISABLENOSCROLL)
00222 info.fMask |= SIF_DISABLENOSCROLL;
00223 if (descr->style & WS_HSCROLL)
00224 SetScrollInfo( hwnd, SB_HORZ, &info, TRUE );
00225 info.nMax = 0;
00226 info.fMask = SIF_RANGE;
00227 if (descr->style & WS_VSCROLL)
00228 SetScrollInfo( hwnd, SB_VERT, &info, TRUE );
00229 }
00230 else
00231 {
00232 info.nMin = 0;
00233 info.nMax = descr->nb_items - 1;
00234 info.nPos = descr->top_item;
00235 info.nPage = LISTBOX_GetCurrentPageSize( hwnd, descr );
00236 info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
00237 if (descr->style & LBS_DISABLENOSCROLL)
00238 info.fMask |= SIF_DISABLENOSCROLL;
00239 if (descr->style & WS_VSCROLL)
00240 SetScrollInfo( hwnd, SB_VERT, &info, TRUE );
00241
00242 if (descr->horz_extent)
00243 {
00244 info.nMin = 0;
00245 info.nMax = descr->horz_extent - 1;
00246 info.nPos = descr->horz_pos;
00247 info.nPage = descr->width;
00248 info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
00249 if (descr->style & LBS_DISABLENOSCROLL)
00250 info.fMask |= SIF_DISABLENOSCROLL;
00251 if (descr->style & WS_HSCROLL)
00252 SetScrollInfo( hwnd, SB_HORZ, &info, TRUE );
00253 }
00254 }
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 static LRESULT LISTBOX_SetTopItem( HWND hwnd, LB_DESCR *descr, INT index,
00264 BOOL scroll )
00265 {
00266 INT max = LISTBOX_GetMaxTopIndex( hwnd, descr );
00267 if (index > max) index = max;
00268 if (index < 0) index = 0;
00269 if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
00270 if (descr->top_item == index) return LB_OKAY;
00271 if (descr->style & LBS_MULTICOLUMN)
00272 {
00273 INT diff = (descr->top_item - index) / descr->page_size * descr->column_width;
00274 if (scroll && (abs(diff) < descr->width))
00275 ScrollWindowEx( hwnd, diff, 0, NULL, NULL, 0, NULL,
00276 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
00277
00278 else
00279 scroll = FALSE;
00280 }
00281 else if (scroll)
00282 {
00283 INT diff;
00284 if (descr->style & LBS_OWNERDRAWVARIABLE)
00285 {
00286 INT i;
00287 diff = 0;
00288 if (index > descr->top_item)
00289 {
00290 for (i = index - 1; i >= descr->top_item; i--)
00291 diff -= descr->items[i].height;
00292 }
00293 else
00294 {
00295 for (i = index; i < descr->top_item; i++)
00296 diff += descr->items[i].height;
00297 }
00298 }
00299 else
00300 diff = (descr->top_item - index) * descr->item_height;
00301
00302 if (abs(diff) < descr->height)
00303 ScrollWindowEx( hwnd, 0, diff, NULL, NULL, 0, NULL,
00304 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
00305 else
00306 scroll = FALSE;
00307 }
00308 if (!scroll) InvalidateRect( hwnd, NULL, TRUE );
00309 descr->top_item = index;
00310 LISTBOX_UpdateScroll( hwnd, descr );
00311 return LB_OKAY;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321 static void LISTBOX_UpdatePage( HWND hwnd, LB_DESCR *descr )
00322 {
00323 INT page_size;
00324
00325 if ((descr->item_height == 0) || (page_size = descr->height / descr->item_height) < 1)
00326 page_size = 1;
00327 if (page_size == descr->page_size) return;
00328 descr->page_size = page_size;
00329 if (descr->style & LBS_MULTICOLUMN)
00330 InvalidateRect( hwnd, NULL, TRUE );
00331 LISTBOX_SetTopItem( hwnd, descr, descr->top_item, FALSE );
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341 static void LISTBOX_UpdateSize( HWND hwnd, LB_DESCR *descr )
00342 {
00343 RECT rect, rectWindow;
00344
00345 GetWindowRect( hwnd, &rectWindow );
00346 GetClientRect( hwnd, &rect );
00347
00348
00349 descr->width = rect.right - rect.left;
00350 descr->height = rect.bottom - rect.top;
00351 if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !(descr->style & LBS_OWNERDRAWVARIABLE))
00352 {
00353 if ((descr->height > descr->item_height) &&
00354 (descr->height % descr->item_height))
00355 {
00356 dprintf(("LISTBOX: [%04x]: changing height %d -> %d\n",
00357 hwnd, descr->height,
00358 descr->height - descr->height%descr->item_height));
00359 SetWindowPos( hwnd, 0, 0, 0,
00360 rectWindow.right - rectWindow.left,
00361 rectWindow.bottom - rectWindow.top -
00362 (descr->height % descr->item_height),
00363 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
00364 return;
00365 }
00366 }
00367
00368
00369 LISTBOX_UpdatePage( hwnd, descr );
00370 LISTBOX_UpdateScroll( hwnd, descr );
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380 static LRESULT LISTBOX_GetItemRect( HWND hwnd, LB_DESCR *descr, INT index,
00381 RECT *rect )
00382 {
00383
00384 if (index && (index >= descr->nb_items)) return -1;
00385 SetRect( rect, 0, 0, descr->width, descr->height );
00386 if (descr->style & LBS_MULTICOLUMN)
00387 {
00388 INT col = (index / descr->page_size) -
00389 (descr->top_item / descr->page_size);
00390 rect->left += col * descr->column_width;
00391 rect->right = rect->left + descr->column_width;
00392 rect->top += (index % descr->page_size) * descr->item_height;
00393 rect->bottom = rect->top + descr->item_height;
00394 }
00395 else if (descr->style & LBS_OWNERDRAWVARIABLE)
00396 {
00397 INT i;
00398 rect->right += descr->horz_pos;
00399 if ((index >= 0) && (index < descr->nb_items))
00400 {
00401 if (index < descr->top_item)
00402 {
00403 for (i = descr->top_item-1; i >= index; i--)
00404 rect->top -= descr->items[i].height;
00405 }
00406 else
00407 {
00408 for (i = descr->top_item; i < index; i++)
00409 rect->top += descr->items[i].height;
00410 }
00411 rect->bottom = rect->top + descr->items[index].height;
00412
00413 }
00414 }
00415 else
00416 {
00417 rect->top += (index - descr->top_item) * descr->item_height;
00418 rect->bottom = rect->top + descr->item_height;
00419 rect->right += descr->horz_pos;
00420 }
00421
00422 return ((rect->left < descr->width) && (rect->right > 0) &&
00423 (rect->top < descr->height) && (rect->bottom > 0));
00424 }
00425
00426
00427
00428
00429
00430
00431
00432 static INT LISTBOX_GetItemFromPoint( HWND hwnd, LB_DESCR *descr,
00433 INT x, INT y )
00434 {
00435 INT index = descr->top_item;
00436
00437 if (!descr->nb_items) return -1;
00438 if (descr->style & LBS_OWNERDRAWVARIABLE)
00439 {
00440 INT pos = 0;
00441 if (y >= 0)
00442 {
00443 while (index < descr->nb_items)
00444 {
00445 if ((pos += descr->items[index].height) > y) break;
00446 index++;
00447 }
00448 }
00449 else
00450 {
00451 while (index > 0)
00452 {
00453 index--;
00454 if ((pos -= descr->items[index].height) <= y) break;
00455 }
00456 }
00457 }
00458 else if (descr->style & LBS_MULTICOLUMN)
00459 {
00460 if (y >= descr->item_height * descr->page_size) return -1;
00461 if (y >= 0) index += y / descr->item_height;
00462 if (x >= 0) index += (x / descr->column_width) * descr->page_size;
00463 else index -= (((x + 1) / descr->column_width) - 1) * descr->page_size;
00464 }
00465 else
00466 {
00467 index += (y / descr->item_height);
00468 }
00469 if (index < 0) return 0;
00470 if (index >= descr->nb_items) return -1;
00471 return index;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480 static void LISTBOX_DrawItem( HWND hwnd, LB_DESCR *descr, HDC hdc,
00481 const RECT *rect, INT index, UINT action )
00482 {
00483 LB_ITEMDATA *item = NULL;
00484 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
00485
00486 if (index < descr->nb_items) item = &descr->items[index];
00487
00488 if (IS_OWNERDRAW(descr))
00489 {
00490 DRAWITEMSTRUCT dis;
00491 UINT id = GetWindowLongA(hwnd,GWL_ID);
00492
00493 if (!item)
00494 {
00495 if (action == ODA_FOCUS)
00496 DrawFocusRect( hdc, rect );
00497
00498
00499 return;
00500 }
00501 dis.CtlType = ODT_LISTBOX;
00502 dis.CtlID = id;
00503 dis.hwndItem = hwnd;
00504 dis.itemAction = action;
00505 dis.hDC = hdc;
00506 dis.itemID = index;
00507 dis.itemState = 0;
00508 if (item && item->selected) dis.itemState |= ODS_SELECTED;
00509 if ((descr->focus_item == index) &&
00510 (descr->caret_on) &&
00511 (descr->in_focus)) dis.itemState |= ODS_FOCUS;
00512 if (dwStyle & WS_DISABLED) dis.itemState |= ODS_DISABLED;
00513 dis.itemData = item ? item->data : 0;
00514 dis.rcItem = *rect;
00515 dprintf2(("[%04x]: drawitem %d (%s) action=%02x "
00516 "state=%02x rect=%d,%d-%d,%d\n",
00517 hwnd, index, item ? item->str : "", action,
00518 dis.itemState, rect->left, rect->top,
00519 rect->right, rect->bottom ));
00520 SendMessageA(descr->owner, WM_DRAWITEM, id, (LPARAM)&dis);
00521 }
00522 else
00523 {
00524 COLORREF oldText = 0, oldBk = 0;
00525
00526 if (action == ODA_FOCUS)
00527 {
00528 DrawFocusRect( hdc, rect );
00529 return;
00530 }
00531 if (item && item->selected)
00532 {
00533 oldBk = SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
00534 oldText = SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
00535 }
00536
00537
00538
00539
00540
00541 if (!item)
00542 ExtTextOutA( hdc, rect->left + 1, rect->top,
00543 ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
00544 else if (!(descr->style & LBS_USETABSTOPS))
00545 ExtTextOutA( hdc, rect->left + 1, rect->top,
00546 ETO_OPAQUE | ETO_CLIPPED, rect, item->str,
00547 strlen(item->str), NULL );
00548 else
00549 {
00550
00551 ExtTextOutA( hdc, rect->left + 1, rect->top,
00552 ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
00553 TabbedTextOutA( hdc, rect->left + 1 , rect->top,
00554 item->str, strlen(item->str),
00555 descr->nb_tabs, descr->tabs, 0);
00556 }
00557 if (item && item->selected)
00558 {
00559 SetBkColor( hdc, oldBk );
00560 SetTextColor( hdc, oldText );
00561 }
00562 if ((descr->focus_item == index) &&
00563 (descr->caret_on) &&
00564 (descr->in_focus)) DrawFocusRect( hdc, rect );
00565 }
00566 }
00567
00568
00569
00570
00571
00572
00573
00574 static LRESULT LISTBOX_SetRedraw( HWND hwnd, LB_DESCR *descr, BOOL on )
00575 {
00576 if (on)
00577 {
00578 if (!(descr->style & LBS_NOREDRAW)) return 0;
00579 descr->style &= ~LBS_NOREDRAW;
00580 LISTBOX_UpdateScroll( hwnd, descr );
00581 }
00582 else descr->style |= LBS_NOREDRAW;
00583
00584 return 0;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593 static void LISTBOX_RepaintItem( HWND hwnd, LB_DESCR *descr, INT index,
00594 UINT action )
00595 {
00596 HDC hdc;
00597 RECT rect;
00598 HFONT oldFont = 0;
00599 HBRUSH hbrush, oldBrush = 0;
00600 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
00601
00602
00603 if ((descr->style & LBS_NOREDRAW) || !IsWindowVisible(hwnd)) return;
00604
00605 if (LISTBOX_GetItemRect( hwnd, descr, index, &rect ) != 1) return;
00606 if (!(hdc = GetDCEx( hwnd, 0, DCX_CACHE ))) return;
00607 if (descr->font) oldFont = SelectObject( hdc, descr->font );
00608 hbrush = SendMessageA( descr->owner, WM_CTLCOLORLISTBOX,
00609 hdc, (LPARAM)hwnd );
00610 if (hbrush) oldBrush = SelectObject( hdc, hbrush );
00611 if (dwStyle & WS_DISABLED)
00612 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
00613 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
00614 LISTBOX_DrawItem( hwnd, descr, hdc, &rect, index, action );
00615 if (oldFont) SelectObject( hdc, oldFont );
00616 if (oldBrush) SelectObject( hdc, oldBrush );
00617 ReleaseDC( hwnd, hdc );
00618 }
00619
00620
00621
00622
00623
00624 static LRESULT LISTBOX_InitStorage( HWND hwnd, LB_DESCR *descr, INT nb_items,
00625 DWORD bytes )
00626 {
00627 LB_ITEMDATA *item;
00628
00629 nb_items += LB_ARRAY_GRANULARITY - 1;
00630 nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
00631 if (descr->items)
00632 nb_items += HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
00633 if (!(item = (LB_ITEMDATA*)HeapReAlloc( descr->heap, 0, descr->items,
00634 nb_items * sizeof(LB_ITEMDATA) )))
00635 {
00636 SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
00637 return LB_ERRSPACE;
00638 }
00639 descr->items = item;
00640 return LB_OKAY;
00641 }
00642
00643
00644
00645
00646
00647 static BOOL LISTBOX_SetTabStops( HWND hwnd, LB_DESCR *descr, INT count,
00648 LPINT tabs, BOOL short_ints )
00649 {
00650 if (!(descr->style & LBS_USETABSTOPS)) return TRUE;
00651 if (descr->tabs) HeapFree( descr->heap, 0, descr->tabs );
00652 if (!(descr->nb_tabs = count))
00653 {
00654 descr->tabs = NULL;
00655 return TRUE;
00656 }
00657
00658 if (!(descr->tabs = (INT *)HeapAlloc( descr->heap, 0,
00659 descr->nb_tabs * sizeof(INT) )))
00660 return FALSE;
00661 if (short_ints)
00662 {
00663 INT i;
00664 LPINT16 p = (LPINT16)tabs;
00665
00666 for (i = 0; i < descr->nb_tabs; i++) {
00667 descr->tabs[i] = *p++<<1;
00668
00669
00670 }
00671
00672
00673 }
00674 else memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
00675
00676 return TRUE;
00677 }
00678
00679
00680
00681
00682
00683 static LRESULT LISTBOX_GetText( HWND hwnd, LB_DESCR *descr, INT index,
00684 LPSTR buffer )
00685 {
00686 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
00687 if (HAS_STRINGS(descr))
00688 {
00689 if (!buffer)
00690 return strlen(descr->items[index].str);
00691 lstrcpyA( buffer, descr->items[index].str );
00692 return strlen(buffer);
00693 } else {
00694 if (buffer)
00695 *((LPDWORD)buffer)=*(LPDWORD)(&descr->items[index].data);
00696 return sizeof(DWORD);
00697 }
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707 static INT LISTBOX_FindStringPos( HWND hwnd, LB_DESCR *descr, LPCSTR str,
00708 BOOL exact )
00709 {
00710 INT index, min, max, res = -1;
00711
00712 if (!(descr->style & LBS_SORT)) return -1;
00713 min = 0;
00714 max = descr->nb_items;
00715 while (min != max)
00716 {
00717 index = (min + max) / 2;
00718 if (HAS_STRINGS(descr))
00719 res = lstrcmpiA( descr->items[index].str, str );
00720 else
00721 {
00722 COMPAREITEMSTRUCT cis;
00723 UINT id = GetWindowLongA(hwnd,GWL_ID);
00724
00725 cis.CtlType = ODT_LISTBOX;
00726 cis.CtlID = id;
00727 cis.hwndItem = hwnd;
00728 cis.itemID1 = index;
00729 cis.itemData1 = descr->items[index].data;
00730 cis.itemID2 = -1;
00731 cis.itemData2 = (DWORD)str;
00732 cis.dwLocaleId = descr->locale;
00733 res = SendMessageA( descr->owner, WM_COMPAREITEM,
00734 id, (LPARAM)&cis );
00735 }
00736 if (!res) return index;
00737 if (res > 0) max = index;
00738 else min = index + 1;
00739 }
00740 return exact ? -1 : max;
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750 static INT LISTBOX_FindFileStrPos( HWND hwnd, LB_DESCR *descr, LPCSTR str )
00751 {
00752 INT min, max, res = -1;
00753
00754 if (!HAS_STRINGS(descr))
00755 return LISTBOX_FindStringPos( hwnd, descr, str, FALSE );
00756 min = 0;
00757 max = descr->nb_items;
00758 while (min != max)
00759 {
00760 INT index = (min + max) / 2;
00761 const char *p = descr->items[index].str;
00762 if (*p == '[')
00763 {
00764 if (*str != '[') res = -1;
00765 else if (p[1] == '-')
00766 {
00767 if (str[1] == '-') res = str[2] - p[2];
00768 else res = -1;
00769 }
00770 else
00771 {
00772 if (str[1] == '-') res = 1;
00773 else res = lstrcmpiA( str, p );
00774 }
00775 }
00776 else
00777 {
00778 if (*str == '[') res = 1;
00779 else res = lstrcmpiA( str, p );
00780 }
00781 if (!res) return index;
00782 if (res < 0) max = index;
00783 else min = index + 1;
00784 }
00785 return max;
00786 }
00787
00788
00789
00790
00791
00792
00793
00794 static INT LISTBOX_FindString( HWND hwnd, LB_DESCR *descr, INT start,
00795 LPCSTR str, BOOL exact )
00796 {
00797 INT i;
00798 LB_ITEMDATA *item;
00799
00800 if (start >= descr->nb_items) start = -1;
00801 item = descr->items + start + 1;
00802 if (HAS_STRINGS(descr))
00803 {
00804 if (!str || !str[0]) return LB_ERR;
00805 if (exact)
00806 {
00807 for (i = start + 1; i < descr->nb_items; i++, item++)
00808 if (!lstrcmpiA( str, item->str )) return i;
00809 for (i = 0, item = descr->items; i <= start; i++, item++)
00810 if (!lstrcmpiA( str, item->str )) return i;
00811 }
00812 else
00813 {
00814
00815 #define CHECK_DRIVE(item) \
00816 if ((item)->str[0] == '[') \
00817 { \
00818 if (!lstrcmpiA( str, (item)->str+1)) return i; \
00819 if (((item)->str[1] == '-') && !lstrcmpiA(str,(item)->str+2)) \
00820 return i; \
00821 }
00822
00823 for (i = start + 1; i < descr->nb_items; i++, item++)
00824 {
00825 if (!lstrcmpiA( str, item->str)) return i;
00826 CHECK_DRIVE(item);
00827 }
00828 for (i = 0, item = descr->items; i <= start; i++, item++)
00829 {
00830 if (!lstrcmpiA( str, item->str)) return i;
00831 CHECK_DRIVE(item);
00832 }
00833 #undef CHECK_DRIVE
00834 }
00835 }
00836 else
00837 {
00838 if (exact && (descr->style & LBS_SORT))
00839
00840 return LISTBOX_FindStringPos( hwnd, descr, str, TRUE );
00841
00842
00843 for (i = start + 1; i < descr->nb_items; i++, item++)
00844 if (item->data == (DWORD)str) return i;
00845 for (i = 0, item = descr->items; i <= start; i++, item++)
00846 if (item->data == (DWORD)str) return i;
00847 }
00848 return LB_ERR;
00849 }
00850
00851
00852
00853
00854
00855 static LRESULT LISTBOX_GetSelCount( HWND hwnd, LB_DESCR *descr )
00856 {
00857 INT i, count;
00858 LB_ITEMDATA *item = descr->items;
00859
00860 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
00861 for (i = count = 0; i < descr->nb_items; i++, item++)
00862 if (item->selected) count++;
00863 return count;
00864 }
00865
00866
00867
00868
00869
00870 static LRESULT LISTBOX_GetSelItems( HWND hwnd, LB_DESCR *descr, INT max,
00871 LPINT array )
00872 {
00873 INT i, count;
00874 LB_ITEMDATA *item = descr->items;
00875
00876 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
00877 for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
00878 if (item->selected) array[count++] = i;
00879 return count;
00880 }
00881
00882
00883
00884
00885
00886 static LRESULT LISTBOX_Draw( HWND hwnd, LB_DESCR *descr, HDC hdc )
00887 {
00888 INT i, col_pos = descr->page_size - 1;
00889 RECT rect;
00890 RECT focusRect = {-1, -1, -1, -1};
00891 HFONT oldFont = 0;
00892 HBRUSH hbrush, oldBrush = 0;
00893 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
00894 INT focusItem;
00895
00896 if (descr->style & LBS_NOREDRAW) return 0;
00897
00898 SetRect( &rect, 0, 0, descr->width, descr->height );
00899 if (descr->style & LBS_MULTICOLUMN)
00900 rect.right = rect.left + descr->column_width;
00901 else if (descr->horz_pos)
00902 {
00903 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
00904 rect.right += descr->horz_pos;
00905 }
00906
00907 if (descr->font) oldFont = SelectObject( hdc, descr->font );
00908 hbrush = SendMessageA( descr->owner, WM_CTLCOLORLISTBOX,
00909 hdc, (LPARAM)hwnd );
00910 if (hbrush) oldBrush = SelectObject( hdc, hbrush );
00911 if (dwStyle & WS_DISABLED)
00912 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
00913
00914 if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
00915 (descr->in_focus))
00916 {
00917
00918 rect.bottom = rect.top + descr->item_height;
00919 LISTBOX_DrawItem( hwnd, descr, hdc, &rect, descr->focus_item,
00920 ODA_FOCUS );
00921 rect.top = rect.bottom;
00922 }
00923
00924
00925
00926 focusItem = descr->focus_item;
00927 descr->focus_item = -1;
00928
00929 for (i = descr->top_item; i < descr->nb_items; i++)
00930 {
00931 if (!(descr->style & LBS_OWNERDRAWVARIABLE))
00932 rect.bottom = rect.top + descr->item_height;
00933 else
00934 rect.bottom = rect.top + descr->items[i].height;
00935
00936 if (i == focusItem)
00937 {
00938
00939 focusRect.left = rect.left;
00940 focusRect.right = rect.right;
00941 focusRect.top = rect.top;
00942 focusRect.bottom = rect.bottom;
00943 }
00944 LISTBOX_DrawItem( hwnd, descr, hdc, &rect, i, ODA_DRAWENTIRE );
00945 rect.top = rect.bottom;
00946
00947 if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
00948 {
00949 if (!IS_OWNERDRAW(descr))
00950 {
00951
00952 SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
00953 if (rect.top < descr->height)
00954 {
00955 rect.bottom = descr->height;
00956 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
00957 &rect, NULL, 0, NULL );
00958 }
00959 }
00960
00961
00962 rect.left += descr->column_width;
00963 rect.right += descr->column_width;
00964 rect.top = 0;
00965 col_pos = descr->page_size - 1;
00966 }
00967 else
00968 {
00969 col_pos--;
00970 if (rect.top >= descr->height) break;
00971 }
00972 }
00973
00974
00975 descr->focus_item = focusItem;
00976 if (focusRect.top != focusRect.bottom && descr->caret_on)
00977 LISTBOX_DrawItem( hwnd, descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS );
00978
00979 if (!IS_OWNERDRAW(descr))
00980 {
00981
00982 SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
00983 if (rect.top < descr->height)
00984 {
00985 rect.bottom = descr->height;
00986 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
00987 &rect, NULL, 0, NULL );
00988 }
00989 if (rect.right < descr->width)
00990 {
00991 rect.left = rect.right;
00992 rect.right = descr->width;
00993 rect.top = 0;
00994 rect.bottom = descr->height;
00995 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
00996 &rect, NULL, 0, NULL );
00997 }
00998 }
00999 if (oldFont) SelectObject( hdc, oldFont );
01000 if (oldBrush) SelectObject( hdc, oldBrush );
01001 return 0;
01002 }
01003
01004
01005
01006
01007
01008
01009
01010
01011 static void LISTBOX_InvalidateItems( HWND hwnd, LB_DESCR *descr, INT index )
01012 {
01013 RECT rect;
01014
01015 if (descr->style & LBS_NOREDRAW) return;
01016
01017 if (LISTBOX_GetItemRect( hwnd, descr, index, &rect ) == 1)
01018 {
01019 rect.bottom = descr->height;
01020 InvalidateRect( hwnd, &rect, TRUE );
01021 if (descr->style & LBS_MULTICOLUMN)
01022 {
01023
01024 rect.left = rect.right;
01025 rect.right = descr->width;
01026 rect.top = 0;
01027 InvalidateRect( hwnd, &rect, TRUE );
01028 }
01029 }
01030 }
01031
01032
01033
01034
01035
01036 static LRESULT LISTBOX_GetItemHeight( HWND hwnd, LB_DESCR *descr, INT index )
01037 {
01038 if (descr->style & LBS_OWNERDRAWVARIABLE)
01039 {
01040 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
01041 return descr->items[index].height;
01042 }
01043 else return descr->item_height;
01044 }
01045
01046
01047
01048
01049
01050 static LRESULT LISTBOX_SetItemHeight( HWND hwnd, LB_DESCR *descr, INT index,
01051 UINT height )
01052 {
01053 if (!height) height = 1;
01054
01055 if (descr->style & LBS_OWNERDRAWVARIABLE)
01056 {
01057 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
01058
01059
01060 descr->items[index].height = height;
01061 LISTBOX_UpdateScroll( hwnd, descr );
01062 LISTBOX_InvalidateItems( hwnd, descr, index );
01063 }
01064 else if (height != descr->item_height)
01065 {
01066
01067
01068 descr->item_height = height;
01069 LISTBOX_UpdatePage( hwnd, descr );
01070 LISTBOX_UpdateScroll( hwnd, descr );
01071 InvalidateRect( hwnd, 0, TRUE );
01072 }
01073 return LB_OKAY;
01074 }
01075
01076
01077
01078
01079
01080 static void LISTBOX_SetHorizontalPos( HWND hwnd, LB_DESCR *descr, INT pos )
01081 {
01082 INT diff;
01083
01084 if (pos > descr->horz_extent - descr->width)
01085 pos = descr->horz_extent - descr->width;
01086 if (pos < 0) pos = 0;
01087 if (!(diff = descr->horz_pos - pos)) return;
01088
01089
01090 descr->horz_pos = pos;
01091 LISTBOX_UpdateScroll( hwnd, descr );
01092 if (abs(diff) < descr->width)
01093 ScrollWindowEx( hwnd, diff, 0, NULL, NULL, 0, NULL,
01094 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
01095 else
01096 InvalidateRect( hwnd, NULL, TRUE );
01097 }
01098
01099
01100
01101
01102
01103 static LRESULT LISTBOX_SetHorizontalExtent( HWND hwnd, LB_DESCR *descr,
01104 UINT extent )
01105 {
01106 if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
01107 return LB_OKAY;
01108 if (extent <= 0) extent = 1;
01109 if (extent == descr->horz_extent) return LB_OKAY;
01110
01111
01112 descr->horz_extent = extent;
01113 if (descr->horz_pos > extent - descr->width)
01114 LISTBOX_SetHorizontalPos( hwnd, descr, extent - descr->width );
01115 else
01116 LISTBOX_UpdateScroll( hwnd, descr );
01117 return LB_OKAY;
01118 }
01119
01120
01121
01122
01123
01124 static LRESULT LISTBOX_SetColumnWidth( HWND hwnd, LB_DESCR *descr, UINT width)
01125 {
01126 if (width == descr->column_width) return LB_OKAY;
01127
01128
01129 descr->column_width = width;
01130 LISTBOX_UpdatePage( hwnd, descr );
01131 return LB_OKAY;
01132 }
01133
01134
01135
01136
01137
01138
01139
01140 static LRESULT LISTBOX_SetFont(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
01141 {
01142 HDC hdc;
01143 HFONT oldFont = 0;
01144 TEXTMETRICA tm;
01145
01146 descr->font = (HFONT)wParam;
01147
01148 if (!(hdc = GetDCEx( hwnd, 0, DCX_CACHE )))
01149 {
01150
01151 descr->item_height = 16;
01152 return 0;
01153 }
01154 if (descr->font) oldFont = SelectObject(hdc,descr->font);
01155 GetTextMetricsA( hdc, &tm );
01156 if (oldFont) SelectObject( hdc, oldFont );
01157 ReleaseDC( hwnd, hdc );
01158 if (!IS_OWNERDRAW(descr))
01159 LISTBOX_SetItemHeight( hwnd, descr, 0, tm.tmHeight );
01160
01161 descr->item_height = tm.tmHeight;
01162
01163 if (lParam) InvalidateRect( hwnd, 0, TRUE );
01164
01165 return 0;
01166 }
01167
01168
01169
01170
01171
01172
01173
01174 static void LISTBOX_MakeItemVisible( HWND hwnd, LB_DESCR *descr, INT index,
01175 BOOL fully )
01176 {
01177 INT top;
01178
01179 if (index <= descr->top_item) top = index;
01180 else if (descr->style & LBS_MULTICOLUMN)
01181 {
01182 INT cols = descr->width;
01183 if (!fully) cols += descr->column_width - 1;
01184 if (cols >= descr->column_width) cols /= descr->column_width;
01185 else cols = 1;
01186 if (index < descr->top_item + (descr->page_size * cols)) return;
01187 top = index - descr->page_size * (cols - 1);
01188 }
01189 else if (descr->style & LBS_OWNERDRAWVARIABLE)
01190 {
01191 INT height = fully ? descr->items[index].height : 1;
01192 for (top = index; top > descr->top_item; top--)
01193 if ((height += descr->items[top-1].height) > descr->height) break;
01194 }
01195 else
01196 {
01197 if (index < descr->top_item + descr->page_size) return;
01198 if (!fully && (index == descr->top_item + descr->page_size) &&
01199 (descr->height > (descr->page_size * descr->item_height))) return;
01200 top = index - descr->page_size + 1;
01201 }
01202 LISTBOX_SetTopItem( hwnd, descr, top, TRUE );
01203 }
01204
01205
01206
01207
01208
01209
01210
01211 static LRESULT LISTBOX_SelectItemRange( HWND hwnd, LB_DESCR *descr, INT first,
01212 INT last, BOOL on )
01213 {
01214 INT i;
01215
01216
01217
01218 if ((last == -1) && (descr->nb_items == 0)) return LB_OKAY;
01219 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
01220 if (last == -1) last = descr->nb_items - 1;
01221 if ((first < 0) || (first >= descr->nb_items)) return LB_ERR;
01222 if ((last < 0) || (last >= descr->nb_items)) return LB_ERR;
01223
01224 descr->selected_item = last;
01225
01226 if (on)
01227 {
01228 for (i = first; i <= last; i++)
01229 {
01230 if (descr->items[i].selected) continue;
01231 descr->items[i].selected = TRUE;
01232 LISTBOX_RepaintItem( hwnd, descr, i, ODA_SELECT );
01233 }
01234 }
01235 else
01236 {
01237 for (i = first; i <= last; i++)
01238 {
01239 if (!descr->items[i].selected) continue;
01240 descr->items[i].selected = FALSE;
01241 LISTBOX_RepaintItem( hwnd, descr, i, ODA_SELECT );
01242 }
01243 }
01244 return LB_OKAY;
01245 }
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 static LRESULT LISTBOX_SetCaretIndex( HWND hwnd, LB_DESCR *descr, INT index,
01256 BOOL fully_visible )
01257 {
01258 INT oldfocus = descr->focus_item;
01259
01260 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
01261 if (index == oldfocus) return LB_OKAY;
01262 descr->focus_item = index;
01263 if ((oldfocus != -1) && descr->caret_on && (descr->in_focus))
01264 LISTBOX_RepaintItem( hwnd, descr, oldfocus, ODA_FOCUS );
01265
01266 LISTBOX_MakeItemVisible( hwnd, descr, index, fully_visible );
01267 if (descr->caret_on && (descr->in_focus))
01268 LISTBOX_RepaintItem( hwnd, descr, index, ODA_FOCUS );
01269
01270 return LB_OKAY;
01271 }
01272
01273
01274
01275
01276
01277 static LRESULT LISTBOX_SetSelection( HWND hwnd, LB_DESCR *descr, INT index,
01278 BOOL on, BOOL send_notify )
01279 {
01280 if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
01281 if (descr->style & LBS_MULTIPLESEL)
01282 {
01283 if (index == -1)
01284 return LISTBOX_SelectItemRange( hwnd, descr, 0, -1, on );
01285 else
01286 return LISTBOX_SelectItemRange( hwnd, descr, index, index, on );
01287 }
01288 else
01289 {
01290 INT oldsel = descr->selected_item;
01291
01292 if (index != oldsel)
01293 {
01294 if (oldsel != -1) descr->items[oldsel].selected = FALSE;
01295 if (index != -1) descr->items[index].selected = TRUE;
01296
01297 descr->selected_item = index;
01298
01299 if (oldsel != -1)
01300 LISTBOX_RepaintItem( hwnd, descr, oldsel, ODA_SELECT);
01301 if (index != -1)
01302 LISTBOX_RepaintItem( hwnd, descr, index, ODA_SELECT );
01303
01304 if (send_notify && descr->nb_items)
01305 SEND_NOTIFICATION( hwnd, descr, (index != -1)
01306 ? LBN_SELCHANGE : LBN_SELCANCEL );
01307 else
01308 if( descr->lphc )
01309
01310 descr->lphc->wState |= CBF_SELCHANGE;
01311 }
01312 }
01313
01314
01315
01316 return (index == -1) ? LB_ERR : LB_OKAY;
01317 }
01318
01319
01320
01321
01322
01323
01324
01325 static void LISTBOX_MoveCaret( HWND hwnd, LB_DESCR *descr, INT index,
01326 BOOL fully_visible )
01327 {
01328 INT oldfocus = descr->focus_item;
01329
01330 if ((index < 0) || (index >= descr->nb_items) || (oldfocus == index))
01331 return;
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341 descr->focus_item = -1;
01342 if ((oldfocus != -1) && descr->caret_on && (descr->in_focus))
01343 LISTBOX_RepaintItem( hwnd, descr, oldfocus, ODA_FOCUS );
01344
01345
01346
01347 if (descr->style & LBS_EXTENDEDSEL)
01348 {
01349 if (descr->anchor_item != -1)
01350 {
01351 INT first = MIN( index, descr->anchor_item );
01352 INT last = MAX( index, descr->anchor_item );
01353 if (first > 0)
01354 LISTBOX_SelectItemRange( hwnd, descr, 0, first - 1, FALSE );
01355 LISTBOX_SelectItemRange( hwnd, descr, last + 1, -1, FALSE );
01356 LISTBOX_SelectItemRange( hwnd, descr, first, last, TRUE );
01357 }
01358 }
01359 else if (!(descr->style & LBS_MULTIPLESEL))
01360 {
01361
01362 LISTBOX_SetSelection( hwnd, descr, index, TRUE, FALSE );
01363 }
01364
01365
01366 descr->focus_item = index;
01367 LISTBOX_MakeItemVisible( hwnd, descr, index, fully_visible );
01368 if (descr->caret_on && (descr->in_focus))
01369 LISTBOX_RepaintItem( hwnd, descr, index, ODA_FOCUS );
01370 }
01371
01372
01373
01374
01375
01376 static LRESULT LISTBOX_InsertItem( HWND hwnd, LB_DESCR *descr, INT index,
01377 LPSTR str, DWORD data )
01378 {
01379 LB_ITEMDATA *item;
01380 INT max_items;
01381 INT oldfocus = descr->focus_item;
01382
01383 if (index == -1) index = descr->nb_items;
01384 else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
01385 if (!descr->items) max_items = 0;
01386 else max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
01387 if (descr->nb_items == max_items)
01388 {
01389
01390 max_items += LB_ARRAY_GRANULARITY;
01391 if (!(item = (LB_ITEMDATA*)HeapReAlloc( descr->heap, 0, descr->items,
01392 max_items * sizeof(LB_ITEMDATA) )))
01393 {
01394 SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
01395 return LB_ERRSPACE;
01396 }
01397 descr->items = item;
01398 }
01399
01400
01401
01402 item = &descr->items[index];
01403 if (index < descr->nb_items)
01404 RtlMoveMemory( item + 1, item,
01405 (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
01406 item->str = str;
01407 item->data = data;
01408 item->height = 0;
01409 item->selected = FALSE;
01410 descr->nb_items++;
01411
01412
01413
01414 if (descr->style & LBS_OWNERDRAWVARIABLE)
01415 {
01416 MEASUREITEMSTRUCT mis;
01417 UINT id = GetWindowLongA(hwnd,GWL_ID);
01418
01419 mis.CtlType = ODT_LISTBOX;
01420 mis.CtlID = id;
01421 mis.itemID = index;
01422 mis.itemData = descr->items[index].data;
01423 mis.itemHeight = descr->item_height;
01424 SendMessageA( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
01425 item->height = mis.itemHeight ? mis.itemHeight : 1;
01426
01427
01428 }
01429
01430
01431
01432 LISTBOX_UpdateScroll( hwnd, descr );
01433 LISTBOX_InvalidateItems( hwnd, descr, index );
01434
01435
01436
01437 if (descr->nb_items == 1)
01438 LISTBOX_SetCaretIndex( hwnd, descr, 0, FALSE );
01439
01440 else
01441 {
01442 if (index <= descr->selected_item)
01443 {
01444 descr->selected_item++;
01445 descr->focus_item = oldfocus;
01446 }
01447 }
01448 return LB_OKAY;
01449 }
01450
01451
01452
01453
01454 static LRESULT LISTBOX_InsertString( HWND hwnd, LB_DESCR *descr, INT index,
01455 LPCSTR str )
01456 {
01457 LPSTR new_str = NULL;
01458 DWORD data = 0;
01459 LRESULT ret;
01460
01461 if (HAS_STRINGS(descr))
01462 {
01463 if (!str) str="";
01464 if (!(new_str = HEAP_strdupA( descr->heap, 0, str )))
01465 {
01466 SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
01467 return LB_ERRSPACE;
01468 }
01469 }
01470 else data = (DWORD)str;
01471
01472 if (index == -1) index = descr->nb_items;
01473 if ((ret = LISTBOX_InsertItem( hwnd, descr, index, new_str, data )) != 0)
01474 {
01475 if (new_str) HeapFree( descr->heap, 0, new_str );
01476 return ret;
01477 }
01478
01479
01480
01481 return index;
01482 }
01483
01484 static LRESULT LISTBOX_AddString(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
01485 {
01486 wParam = LISTBOX_FindStringPos( hwnd, descr, (LPCSTR)lParam, FALSE );
01487 return LISTBOX_InsertString( hwnd, descr, wParam, (LPCSTR)lParam );
01488 }
01489
01490 static LRESULT LISTBOX_AddFile(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
01491 {
01492 wParam = LISTBOX_FindFileStrPos( hwnd, descr, (LPCSTR)lParam );
01493 return LISTBOX_InsertString( hwnd, descr, wParam, (LPCSTR)lParam );
01494 }
01495
01496
01497
01498
01499
01500
01501 static void LISTBOX_DeleteItem( HWND hwnd, LB_DESCR *descr, INT index )
01502 {
01503
01504
01505
01506
01507
01508 if (IS_OWNERDRAW(descr) || descr->items[index].data)
01509 {
01510 DELETEITEMSTRUCT dis;
01511 UINT id = GetWindowLongA(hwnd,GWL_ID);
01512
01513 dis.CtlType = ODT_LISTBOX;
01514 dis.CtlID = id;
01515 dis.itemID = index;
01516 dis.hwndItem = hwnd;
01517 dis.itemData = descr->items[index].data;
01518 SendMessageA( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
01519 }
01520 if (HAS_STRINGS(descr) && descr->items[index].str)
01521 HeapFree( descr->heap, 0, descr->items[index].str );
01522 }
01523
01524
01525
01526
01527
01528
01529
01530 static LRESULT LISTBOX_RemoveItem( HWND hwnd, LB_DESCR *descr, INT index )
01531 {
01532 LB_ITEMDATA *item;
01533 INT max_items;
01534
01535 if (index == -1) index = descr->nb_items - 1;
01536 else if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
01537
01538
01539 LISTBOX_InvalidateItems( hwnd, descr, index );
01540
01541 LISTBOX_DeleteItem( hwnd, descr, index );
01542
01543
01544
01545 item = &descr->items[index];
01546 if (index < descr->nb_items-1)
01547 RtlMoveMemory( item, item + 1,
01548 (descr->nb_items - index - 1) * sizeof(LB_ITEMDATA) );
01549 descr->nb_items--;
01550 if (descr->anchor_item == descr->nb_items) descr->anchor_item--;
01551
01552
01553
01554 max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(LB_ITEMDATA);
01555 if (descr->nb_items < max_items - 2*LB_ARRAY_GRANULARITY)
01556 {
01557 max_items -= LB_ARRAY_GRANULARITY;
01558 item = (LB_ITEMDATA*)HeapReAlloc( descr->heap, 0, descr->items,
01559 max_items * sizeof(LB_ITEMDATA) );
01560 if (item) descr->items = item;
01561 }
01562
01563
01564
01565 LISTBOX_UpdateScroll( hwnd, descr );
01566
01567
01568 if (descr->nb_items == descr->page_size)
01569 LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
01570
01571
01572 if (!IS_MULTISELECT(descr))
01573 {
01574 if (index == descr->selected_item)
01575 descr->selected_item = -1;
01576 else if (index < descr->selected_item)
01577 {
01578 descr->selected_item--;
01579 }
01580 }
01581
01582 if (descr->focus_item >= descr->nb_items)
01583 {
01584 descr->focus_item = descr->nb_items - 1;
01585 if (descr->focus_item < 0) descr->focus_item = 0;
01586 }
01587 return LB_OKAY;
01588 }
01589
01590 static LRESULT LISTBOX_DeleteString(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
01591 {
01592 if (LISTBOX_RemoveItem( hwnd, descr, wParam) != LB_ERR)
01593 return descr->nb_items;
01594 else
01595 return LB_ERR;
01596 }
01597
01598
01599
01600
01601 static LRESULT LISTBOX_ResetContent( HWND hwnd, LB_DESCR *descr,BOOL refresh)
01602 {
01603 INT i;
01604
01605 for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( hwnd, descr, i );
01606 if (descr->items) HeapFree( descr->heap, 0, descr->items );
01607 descr->nb_items = 0;
01608 descr->top_item = 0;
01609 descr->selected_item = -1;
01610 descr->focus_item = 0;
01611 descr->anchor_item = -1;
01612 descr->items = NULL;
01613 if (refresh)
01614 {
01615 LISTBOX_UpdateScroll( hwnd, descr );
01616 InvalidateRect( hwnd, NULL, TRUE );
01617 }
01618
01619 return 0;
01620 }
01621
01622
01623
01624
01625
01626 static LRESULT LISTBOX_SetCount( HWND hwnd, LB_DESCR *descr, INT count )
01627 {
01628 LRESULT ret;
01629 INT oldcount = descr->nb_items;
01630
01631 if (HAS_STRINGS(descr) || !HAS_NODATA(descr)) return LB_ERR;
01632
01633 if (count > descr->nb_items)
01634 {
01635 LB_ITEMDATA *item;
01636 INT max_items,index;
01637 UINT id = (descr->lphc) ? ID_CB_LISTBOX:GetWindowLongA(hwnd,GWL_ID);
01638
01639 max_items = count+LB_ARRAY_GRANULARITY-(count % LB_ARRAY_GRANULARITY);
01640 if (!(item = (LB_ITEMDATA*)HeapReAlloc(descr->heap,0,descr->items,max_items*sizeof(LB_ITEMDATA))))
01641 {
01642 SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
01643 return LB_ERRSPACE;
01644 }
01645 descr->items = item;
01646
01647
01648
01649 index = descr->nb_items-1;
01650 while (count > descr->nb_items)
01651 {
01652 index++;
01653 item = &descr->items[index];
01654
01655 item->str = "";
01656 item->data = 0;
01657 item->height = 0;
01658 item->selected = FALSE;
01659 descr->nb_items++;
01660
01661
01662
01663 if (descr->style & LBS_OWNERDRAWVARIABLE)
01664 {
01665 MEASUREITEMSTRUCT mis;
01666
01667 mis.CtlType = ODT_LISTBOX;
01668 mis.CtlID = id;
01669 mis.itemID = index;
01670 mis.itemData = descr->items[index].data;
01671 mis.itemHeight = descr->item_height;
01672 SendMessageA( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
01673 item->height = mis.itemHeight ? mis.itemHeight : 1;
01674 }
01675 }
01676 } else if (count < descr->nb_items)
01677 {
01678 descr->nb_items = count;
01679 if (descr->selected_item >= count) descr->selected_item = count-1;
01680 if (descr->focus_item >= count) descr-> focus_item = count-1;
01681 }
01682
01683
01684 LISTBOX_UpdateScroll( hwnd, descr );
01685 InvalidateRect(hwnd,NULL,TRUE);
01686
01687
01688
01689 if (oldcount == 0)
01690 LISTBOX_SetCaretIndex( hwnd, descr, 0, FALSE );
01691
01692 return LB_OKAY;
01693 }
01694
01695
01696
01697
01698
01699 static LRESULT LISTBOX_Directory( HWND hwnd, LB_DESCR *descr, UINT attrib,
01700 LPCSTR filespec, BOOL long_names )
01701 {
01702 HANDLE handle;
01703 LRESULT ret = LB_OKAY;
01704 WIN32_FIND_DATAA entry;
01705 int pos;
01706
01707 if ((handle = FindFirstFileA(filespec,&entry)) == INVALID_HANDLE_VALUE)
01708 {
01709 if (GetLastError() != ERROR_NO_MORE_FILES) return LB_ERR;
01710 }
01711 else
01712 {
01713 do
01714 {
01715 char buffer[270];
01716 if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
01717 {
01718 if (!(attrib & DDL_DIRECTORY) ||
01719 !strcmp( entry.cAlternateFileName, "." )) continue;
01720 if (long_names) sprintf( buffer, "[%s]", entry.cFileName );
01721 else sprintf( buffer, "[%s]", entry.cAlternateFileName );
01722 }
01723 else
01724 {
01725 #ifdef __WIN32OS2__
01726 #define ATTRIBS (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
01727 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NORMAL)
01728 #else
01729 #define ATTRIBS (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
01730 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE )
01731 #endif
01732
01733 if ((attrib & DDL_EXCLUSIVE) &&
01734 ((attrib & ATTRIBS) != (entry.dwFileAttributes & ATTRIBS)))
01735 continue;
01736 #undef ATTRIBS
01737 if (long_names) strcpy( buffer, entry.cFileName );
01738 else strcpy( buffer, entry.cAlternateFileName );
01739 }
01740 if (!long_names) CharLowerA( buffer );
01741 pos = LISTBOX_FindFileStrPos( hwnd, descr, buffer );
01742 if ((ret = LISTBOX_InsertString( hwnd, descr, pos, buffer )) < 0)
01743 break;
01744 } while (FindNextFileA( handle, &entry ));
01745 FindClose( handle );
01746 }
01747
01748 if ((ret >= 0) && (attrib & DDL_DRIVES))
01749 {
01750 char buffer[] = "[-a-]";
01751 int drive;
01752 for (drive = 0; drive < MAX_DOS_DRIVES; drive++, buffer[2]++)
01753 {
01754 if (!DRIVE_IsValid(drive)) continue;
01755 if ((ret = LISTBOX_InsertString( hwnd, descr, -1, buffer )) < 0)
01756 break;
01757 }
01758 }
01759 return ret;
01760 }
01761
01762
01763
01764
01765
01766 static LRESULT LISTBOX_HandleVScroll( HWND hwnd, LB_DESCR *descr,
01767 WPARAM wParam, LPARAM lParam )
01768 {
01769 SCROLLINFO info;
01770
01771 if (descr->style & LBS_MULTICOLUMN) return 0;
01772 switch(LOWORD(wParam))
01773 {
01774 case SB_LINEUP:
01775 LISTBOX_SetTopItem( hwnd, descr, descr->top_item - 1, TRUE );
01776 break;
01777 case SB_LINEDOWN:
01778 LISTBOX_SetTopItem( hwnd, descr, descr->top_item + 1, TRUE );
01779 break;
01780 case SB_PAGEUP:
01781 LISTBOX_SetTopItem( hwnd, descr, descr->top_item -
01782 LISTBOX_GetCurrentPageSize( hwnd, descr ), TRUE );
01783 break;
01784 case SB_PAGEDOWN:
01785 LISTBOX_SetTopItem( hwnd, descr, descr->top_item +
01786 LISTBOX_GetCurrentPageSize( hwnd, descr ), TRUE );
01787 break;
01788 case SB_THUMBPOSITION:
01789 LISTBOX_SetTopItem( hwnd, descr, HIWORD(wParam), TRUE );
01790 break;
01791 case SB_THUMBTRACK:
01792 info.cbSize = sizeof(info);
01793 info.fMask = SIF_TRACKPOS;
01794 GetScrollInfo( hwnd, SB_VERT, &info );
01795 LISTBOX_SetTopItem( hwnd, descr, info.nTrackPos, TRUE );
01796 break;
01797 case SB_TOP:
01798 LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
01799 break;
01800 case SB_BOTTOM:
01801 LISTBOX_SetTopItem( hwnd, descr, descr->nb_items, TRUE );
01802 break;
01803 }
01804 return 0;
01805 }
01806
01807
01808
01809
01810
01811 static LRESULT LISTBOX_HandleHScroll( HWND hwnd, LB_DESCR *descr,
01812 WPARAM wParam, LPARAM lParam )
01813 {
01814 SCROLLINFO info;
01815 INT page;
01816
01817 if (descr->style & LBS_MULTICOLUMN)
01818 {
01819 switch(LOWORD(wParam))
01820 {
01821 case SB_LINELEFT:
01822 LISTBOX_SetTopItem( hwnd, descr, descr->top_item-descr->page_size,
01823 TRUE );
01824 break;
01825 case SB_LINERIGHT:
01826 LISTBOX_SetTopItem( hwnd, descr, descr->top_item+descr->page_size,
01827 TRUE );
01828 break;
01829 case SB_PAGELEFT:
01830 page = descr->width / descr->column_width;
01831 if (page < 1) page = 1;
01832 LISTBOX_SetTopItem( hwnd, descr,
01833 descr->top_item - page * descr->page_size, TRUE );
01834 break;
01835 case SB_PAGERIGHT:
01836 page = descr->width / descr->column_width;
01837 if (page < 1) page = 1;
01838 LISTBOX_SetTopItem( hwnd, descr,
01839 descr->top_item + page * descr->page_size, TRUE );
01840 break;
01841 case SB_THUMBPOSITION:
01842 LISTBOX_SetTopItem( hwnd, descr, HIWORD(wParam)*descr->page_size,
01843 TRUE );
01844 break;
01845 case SB_THUMBTRACK:
01846 info.cbSize = sizeof(info);
01847 info.fMask = SIF_TRACKPOS;
01848 GetScrollInfo( hwnd, SB_VERT, &info );
01849 LISTBOX_SetTopItem( hwnd, descr, info.nTrackPos*descr->page_size,
01850 TRUE );
01851 break;
01852 case SB_LEFT:
01853 LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
01854 break;
01855 case SB_RIGHT:
01856 LISTBOX_SetTopItem( hwnd, descr, descr->nb_items, TRUE );
01857 break;
01858 }
01859 }
01860 else if (descr->horz_extent)
01861 {
01862 switch(LOWORD(wParam))
01863 {
01864 case SB_LINELEFT:
01865 LISTBOX_SetHorizontalPos( hwnd, descr, descr->horz_pos - 1 );
01866 break;
01867 case SB_LINERIGHT:
01868 LISTBOX_SetHorizontalPos( hwnd, descr, descr->horz_pos + 1 );
01869 break;
01870 case SB_PAGELEFT:
01871 LISTBOX_SetHorizontalPos( hwnd, descr,
01872 descr->horz_pos - descr->width );
01873 break;
01874 case SB_PAGERIGHT:
01875 LISTBOX_SetHorizontalPos( hwnd, descr,
01876 descr->horz_pos + descr->width );
01877 break;
01878 case SB_THUMBPOSITION:
01879 LISTBOX_SetHorizontalPos( hwnd, descr, HIWORD(wParam) );
01880 break;
01881 case SB_THUMBTRACK:
01882 info.cbSize = sizeof(info);
01883 info.fMask = SIF_TRACKPOS;
01884 GetScrollInfo( hwnd, SB_HORZ, &info );
01885 LISTBOX_SetHorizontalPos( hwnd, descr, info.nTrackPos );
01886 break;
01887 case SB_LEFT:
01888 LISTBOX_SetHorizontalPos( hwnd, descr, 0 );
01889 break;
01890 case SB_RIGHT:
01891 LISTBOX_SetHorizontalPos( hwnd, descr,
01892 descr->horz_extent - descr->width );
01893 break;
01894 }
01895 }
01896 return 0;
01897 }
01898
01899 static LRESULT LISTBOX_HandleMouseWheel(HWND hwnd, LB_DESCR *descr,WPARAM wParam, LPARAM lParam )
01900 {
01901 short gcWheelDelta = 0;
01902 UINT pulScrollLines = 3;
01903
01904 if (wParam & (MK_SHIFT | MK_CONTROL))
01905 return DefWindowProcA(hwnd,WM_MOUSEWHEEL,wParam,lParam);
01906
01907 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
01908
01909 gcWheelDelta -= (short) HIWORD(wParam);
01910
01911 if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
01912 {
01913 int cLineScroll = (int) min((UINT) descr->page_size, pulScrollLines);
01914 cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
01915 LISTBOX_SetTopItem( hwnd, descr, descr->top_item + cLineScroll, TRUE );
01916 }
01917 return 0;
01918 }
01919
01920
01921
01922
01923 static LRESULT LISTBOX_HandleLButtonDown( HWND hwnd, LB_DESCR *descr,
01924 WPARAM wParam, INT x, INT y )
01925 {
01926 INT index = LISTBOX_GetItemFromPoint( hwnd, descr, x, y );
01927
01928
01929 if (!descr->caret_on && (descr->in_focus)) return 0;
01930 if (index != -1)
01931 {
01932 if (descr->style & LBS_EXTENDEDSEL)
01933 {
01934 if (!(wParam & MK_SHIFT)) descr->anchor_item = index;
01935 if (wParam & MK_CONTROL)
01936 {
01937 LISTBOX_SetCaretIndex( hwnd, descr, index, FALSE );
01938 LISTBOX_SetSelection( hwnd, descr, index,
01939 !descr->items[index].selected,
01940 (descr->style & LBS_NOTIFY) != 0 );
01941 }
01942 else LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
01943 }
01944 else
01945 {
01946 LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
01947 LISTBOX_SetSelection( hwnd, descr, index,
01948 (!(descr->style & LBS_MULTIPLESEL) ||
01949 !descr->items[index].selected),
01950 (descr->style & LBS_NOTIFY) != 0 );
01951 }
01952 }
01953
01954 if (!descr->in_focus)
01955 {
01956 if( !descr->lphc ) SetFocus( hwnd );
01957 else SetFocus( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit
01958 : descr->lphc->hwndself ) ;
01959 }
01960
01961 descr->captured = TRUE;
01962 SetCapture( hwnd );
01963 if (index != -1 && !descr->lphc)
01964 {
01965 if (descr->style & LBS_NOTIFY )
01966 SendMessageA( descr->owner, WM_LBTRACKPOINT, index,
01967 MAKELPARAM( x, y ) );
01968 if (GetWindowLongA(hwnd,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
01969 {
01970 POINT pt;
01971
01972 pt.x = x;
01973 pt.y = y;
01974
01975 if (DragDetect( hwnd, pt ))
01976 SendMessageA( descr->owner, WM_BEGINDRAG, 0, 0 );
01977 }
01978 }
01979 return 0;
01980 }
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002 static LRESULT LISTBOX_HandleLButtonDownCombo( HWND hwnd, LB_DESCR *pDescr,
02003 UINT msg,WPARAM wParam, INT x, INT y)
02004 {
02005 RECT clientRect, screenRect;
02006 POINT mousePos;
02007
02008 mousePos.x = x;
02009 mousePos.y = y;
02010
02011 GetClientRect(hwnd, &clientRect);
02012
02013 if(PtInRect(&clientRect, mousePos))
02014 {
02015
02016 if (msg == WM_LBUTTONDOWN)
02017 {
02018 pDescr->lphc->droppedIndex = pDescr->nb_items ? pDescr->selected_item : -1;
02019 return LISTBOX_HandleLButtonDown( hwnd, pDescr, wParam, x, y);
02020 }
02021 else if (pDescr->style & LBS_NOTIFY)
02022 SEND_NOTIFICATION( hwnd, pDescr, LBN_DBLCLK );
02023 return 0;
02024 }
02025 else
02026 {
02027 POINT screenMousePos;
02028 RECT screenRect;
02029 HWND hWndOldCapture;
02030
02031
02032 screenMousePos = mousePos;
02033 hWndOldCapture = GetCapture();
02034 GetWindowRect(hwnd,&screenRect);
02035 ClientToScreen(hwnd,&screenMousePos);
02036
02037 if (!PtInRect(&screenRect,screenMousePos))
02038 {
02039 ReleaseCapture();
02040 LISTBOX_SetSelection( hwnd, pDescr, pDescr->lphc->droppedIndex, FALSE, FALSE );
02041 COMBO_FlipListbox( pDescr->lphc, FALSE, FALSE );
02042
02043 return 0;
02044 } else
02045 {
02046
02047 INT nHitTestType = SendMessageA(hwnd,WM_NCHITTEST,0,MAKELONG(screenMousePos.x,screenMousePos.y));
02048
02049
02050
02051 if (nHitTestType != HTCLIENT)
02052 {
02053 SendMessageA(hwnd,(msg == WM_LBUTTONDOWN) ? WM_NCLBUTTONDOWN:WM_NCLBUTTONDBLCLK,nHitTestType,MAKELONG(screenMousePos.x,screenMousePos.y));
02054 }
02055
02056
02057
02058 if (hWndOldCapture)
02059 {
02060 SetCapture(hWndOldCapture);
02061 }
02062 }
02063 }
02064 return 0;
02065 }
02066
02067
02068
02069
02070
02071 static LRESULT LISTBOX_HandleLButtonUp( HWND hwnd, LB_DESCR *descr )
02072 {
02073 if (LISTBOX_Timer != LB_TIMER_NONE)
02074 KillSystemTimer( hwnd, LB_TIMER_ID );
02075
02076 LISTBOX_Timer = LB_TIMER_NONE;
02077 if (descr->captured)
02078 {
02079 descr->captured = FALSE;
02080 if (GetCapture() == hwnd) ReleaseCapture();
02081 if ((descr->style & LBS_NOTIFY) && descr->nb_items)
02082 SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
02083 }
02084 return 0;
02085 }
02086
02087
02088
02089
02090
02091
02092
02093
02094 static LRESULT LISTBOX_HandleTimer( HWND hwnd, LB_DESCR *descr,
02095 INT index, TIMER_DIRECTION dir )
02096 {
02097 switch(dir)
02098 {
02099 case LB_TIMER_UP:
02100 if (descr->top_item) index = descr->top_item - 1;
02101 else index = 0;
02102 break;
02103 case LB_TIMER_LEFT:
02104 if (descr->top_item) index -= descr->page_size;
02105 break;
02106 case LB_TIMER_DOWN:
02107 index = descr->top_item + LISTBOX_GetCurrentPageSize( hwnd, descr );
02108 if (index == descr->focus_item) index++;
02109 if (index >= descr->nb_items) index = descr->nb_items - 1;
02110 break;
02111 case LB_TIMER_RIGHT:
02112 if (index + descr->page_size < descr->nb_items)
02113 index += descr->page_size;
02114 break;
02115 case LB_TIMER_NONE:
02116 break;
02117 }
02118 if (index == descr->focus_item) return FALSE;
02119 LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
02120 return TRUE;
02121 }
02122
02123
02124
02125
02126
02127
02128
02129 static LRESULT LISTBOX_HandleSystemTimer( HWND hwnd, LB_DESCR *descr )
02130 {
02131 if (!LISTBOX_HandleTimer( hwnd, descr, descr->focus_item, LISTBOX_Timer ))
02132 {
02133 KillSystemTimer( hwnd, LB_TIMER_ID );
02134
02135 LISTBOX_Timer = LB_TIMER_NONE;
02136 }
02137 return 0;
02138 }
02139
02140
02141
02142
02143
02144
02145
02146 static LRESULT LISTBOX_HandleMouseMove( HWND hwnd, LB_DESCR *descr,
02147 INT x, INT y )
02148 {
02149 INT index;
02150 TIMER_DIRECTION dir = LB_TIMER_NONE;
02151
02152 if (GetCapture() != hwnd) return 0;
02153 if (!descr->captured) return 0;
02154
02155 if (descr->style & LBS_MULTICOLUMN)
02156 {
02157 if (y < 0) y = 0;
02158 else if (y >= descr->item_height * descr->page_size)
02159 y = descr->item_height * descr->page_size - 1;
02160
02161 if (x < 0)
02162 {
02163 dir = LB_TIMER_LEFT;
02164 x = 0;
02165 }
02166 else if (x >= descr->width)
02167 {
02168 dir = LB_TIMER_RIGHT;
02169 x = descr->width - 1;
02170 }
02171 }
02172 else
02173 {
02174 if (y < 0) dir = LB_TIMER_UP;
02175 else if (y >= descr->height) dir = LB_TIMER_DOWN;
02176 }
02177
02178 index = LISTBOX_GetItemFromPoint( hwnd, descr, x, y );
02179 if (index == -1) index = descr->focus_item;
02180 if (!LISTBOX_HandleTimer( hwnd, descr, index, dir )) dir = LB_TIMER_NONE;
02181
02182
02183
02184 if (dir != LB_TIMER_NONE)
02185 SetSystemTimer( hwnd, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
02186 else if (LISTBOX_Timer != LB_TIMER_NONE)
02187 KillSystemTimer( hwnd, LB_TIMER_ID );
02188
02189 LISTBOX_Timer = dir;
02190
02191 return 0;
02192 }
02193
02194
02195
02196
02197
02198 static LRESULT LISTBOX_HandleKeyDown( HWND hwnd, LB_DESCR *descr, WPARAM wParam )
02199 {
02200 INT caret = -1;
02201 BOOL bForceSelection = TRUE;
02202
02203 if ((IS_MULTISELECT(descr)) || (descr->selected_item == descr->focus_item))
02204 bForceSelection = FALSE;
02205
02206 if (descr->style & LBS_WANTKEYBOARDINPUT)
02207 {
02208 caret = SendMessageA( descr->owner, WM_VKEYTOITEM,
02209 MAKEWPARAM(LOWORD(wParam), descr->focus_item),
02210 hwnd );
02211 if (caret == -2) return 0;
02212 }
02213 if (caret == -1) switch(wParam)
02214 {
02215 case VK_LEFT:
02216 if (descr->style & LBS_MULTICOLUMN)
02217 {
02218 bForceSelection = FALSE;
02219 if (descr->focus_item >= descr->page_size)
02220 caret = descr->focus_item - descr->page_size;
02221 break;
02222 }
02223
02224 case VK_UP:
02225 caret = descr->focus_item - 1;
02226 if (caret < 0) caret = 0;
02227 break;
02228 case VK_RIGHT:
02229 if (descr->style & LBS_MULTICOLUMN)
02230 {
02231 bForceSelection = FALSE;
02232 if (descr->focus_item + descr->page_size < descr->nb_items)
02233 caret = descr->focus_item + descr->page_size;
02234 break;
02235 }
02236
02237 case VK_DOWN:
02238 caret = descr->focus_item + 1;
02239 if (caret >= descr->nb_items) caret = descr->nb_items - 1;
02240 break;
02241 case VK_PRIOR:
02242 if (descr->style & LBS_MULTICOLUMN)
02243 {
02244 INT page = descr->width / descr->column_width;
02245 if (page < 1) page = 1;
02246 caret = descr->focus_item - (page * descr->page_size) + 1;
02247 }
02248 else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(hwnd,descr)+1;
02249 if (caret < 0) caret = 0;
02250 break;
02251 case VK_NEXT:
02252 if (descr->style & LBS_MULTICOLUMN)
02253 {
02254 INT page = descr->width / descr->column_width;
02255 if (page < 1) page = 1;
02256 caret = descr->focus_item + (page * descr->page_size) - 1;
02257 }
02258 else caret = descr->focus_item+LISTBOX_GetCurrentPageSize(hwnd,descr)-1;
02259 if (caret >= descr->nb_items) caret = descr->nb_items - 1;
02260 break;
02261 case VK_HOME:
02262 caret = 0;
02263 break;
02264 case VK_END:
02265 caret = descr->nb_items - 1;
02266 break;
02267 case VK_SPACE:
02268 if (descr->style & LBS_EXTENDEDSEL) caret = descr->focus_item;
02269 else if (descr->style & LBS_MULTIPLESEL)
02270 {
02271 LISTBOX_SetSelection( hwnd, descr, descr->focus_item,
02272 !descr->items[descr->focus_item].selected,
02273 (descr->style & LBS_NOTIFY) != 0 );
02274 }
02275 break;
02276 default:
02277 bForceSelection = FALSE;
02278 }
02279 if (bForceSelection)
02280 caret = descr->focus_item;
02281 if (caret >= 0)
02282 {
02283 if ((descr->style & LBS_EXTENDEDSEL) &&
02284 !(GetKeyState( VK_SHIFT ) & 0x8000))
02285 descr->anchor_item = caret;
02286 LISTBOX_MoveCaret( hwnd, descr, caret, TRUE );
02287 LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
02288 if (descr->style & LBS_NOTIFY)
02289 {
02290 if( descr->lphc && CB_GETTYPE(descr->lphc) != CBS_SIMPLE )
02291 {
02292
02293 descr->lphc->wState |= CBF_NOROLLUP;
02294 }
02295 if (descr->nb_items) SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
02296 }
02297 }
02298 return 0;
02299 }
02300
02301
02302
02303
02304
02305 static LRESULT LISTBOX_HandleChar( HWND hwnd, LB_DESCR *descr,
02306 WPARAM wParam )
02307 {
02308 INT caret = -1;
02309 char str[2];
02310
02311 str[0] = wParam & 0xff;
02312 str[1] = '\0';
02313
02314 if (descr->style & LBS_WANTKEYBOARDINPUT)
02315 {
02316 caret = SendMessageA( descr->owner, WM_CHARTOITEM,
02317 MAKEWPARAM(LOWORD(wParam), descr->focus_item),
02318 hwnd );
02319 if (caret == -2) return 0;
02320 }
02321 if (caret == -1)
02322 caret = LISTBOX_FindString( hwnd, descr, descr->focus_item, str, FALSE);
02323 if (caret != -1)
02324 {
02325 if ((!IS_MULTISELECT(descr)) && descr->selected_item == -1)
02326 LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
02327 LISTBOX_MoveCaret( hwnd, descr, caret, TRUE );
02328 if ((descr->style & LBS_NOTIFY) && descr->nb_items)
02329 SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
02330 }
02331 return 0;
02332 }
02333
02334
02335
02336
02337
02338 static LRESULT LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
02339 {
02340 LB_DESCR *descr;
02341 MEASUREITEMSTRUCT mis;
02342 RECT rect;
02343
02344 if (!(descr = (LB_DESCR*)HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) )))
02345 return -1;
02346 if (!(descr->heap = HeapCreate( 0, 0x10000, 0 )))
02347 {
02348 HeapFree( GetProcessHeap(), 0, descr );
02349 return -1;
02350 }
02351 GetClientRect( hwnd, &rect );
02352 descr->owner = GetParent( hwnd );
02353 descr->style = GetWindowLongA(hwnd,GWL_STYLE);
02354 descr->width = rect.right - rect.left;
02355 descr->height = rect.bottom - rect.top;
02356 descr->items = NULL;
02357 descr->nb_items = 0;
02358 descr->top_item = 0;
02359 descr->selected_item = -1;
02360 descr->focus_item = 0;
02361 descr->anchor_item = -1;
02362 descr->item_height = 1;
02363 descr->page_size = 1;
02364 descr->column_width = 150;
02365 descr->horz_extent = (descr->style & WS_HSCROLL) ? 1 : 0;
02366 descr->horz_pos = 0;
02367 descr->nb_tabs = 0;
02368 descr->tabs = NULL;
02369 descr->caret_on = lphc ? FALSE:TRUE;
02370 descr->in_focus = FALSE;
02371 descr->captured = FALSE;
02372 descr->font = 0;
02373 descr->locale = 0;
02374 descr->lphc = lphc;
02375
02376 if( lphc )
02377 {
02378
02379
02380 descr->owner = lphc->hwndself;
02381 }
02382
02383 SetInfoPtr(hwnd,(DWORD)descr);
02384
02385
02386
02387 if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
02388 if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
02389 if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
02390 LISTBOX_SetFont(hwnd,descr,0,(LPARAM)FALSE);
02391
02392 if (descr->style & LBS_OWNERDRAWFIXED)
02393 {
02394 if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
02395 {
02396
02397 descr->item_height = lphc->fixedOwnerDrawHeight;
02398 }
02399 else
02400 {
02401 UINT id = GetWindowLongA(hwnd,GWL_ID);
02402
02403 mis.CtlType = ODT_LISTBOX;
02404 mis.CtlID = id;
02405 mis.itemID = -1;
02406 mis.itemWidth = 0;
02407 mis.itemData = 0;
02408 mis.itemHeight = descr->item_height;
02409 SendMessageA( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
02410 descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
02411 }
02412 }
02413
02414 return 0;
02415 }
02416
02417 static LRESULT LISTBOX_NCCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
02418 {
02419 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
02420
02421
02422
02423
02424
02425
02426 if (dwStyle & WS_BORDER)
02427 {
02428 SetWindowLongA(hwnd,GWL_EXSTYLE,GetWindowLongA(hwnd,GWL_EXSTYLE) | WS_EX_CLIENTEDGE);
02429 SetWindowLongA(hwnd,GWL_STYLE,GetWindowLongA(hwnd,GWL_STYLE) & ~ WS_BORDER);
02430 }
02431
02432 return DefWindowProcA(hwnd,WM_NCCREATE,wParam,lParam);
02433 }
02434
02435
02436
02437
02438 static BOOL LISTBOX_Destroy( HWND hwnd, LB_DESCR *descr )
02439 {
02440 LISTBOX_ResetContent(hwnd,descr,FALSE);
02441 HeapDestroy( descr->heap );
02442 HeapFree( GetProcessHeap(), 0, descr );
02443 SetInfoPtr(hwnd,0);
02444 return TRUE;
02445 }
02446
02447 static LRESULT LISTBOX_GetItemData(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02448 {
02449 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
02450 return LB_ERR;
02451 return descr->items[wParam].data;
02452 }
02453
02454 static LRESULT LISTBOX_SetItemData(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02455 {
02456 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
02457 return LB_ERR;
02458 descr->items[wParam].data = (DWORD)lParam;
02459 return LB_OKAY;
02460 }
02461
02462 static LRESULT LISTBOX_GetCount(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02463 {
02464 return descr->nb_items;
02465 }
02466
02467 static LRESULT LISTBOX_GetTextLen(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02468 {
02469 if (wParam >= descr->nb_items)
02470 return LB_ERR;
02471 return (HAS_STRINGS(descr) ? strlen(descr->items[wParam].str)
02472 : sizeof(DWORD));
02473 }
02474
02475 static LRESULT LISTBOX_GetCurSel(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02476 {
02477 if (descr->nb_items==0)
02478 return LB_ERR;
02479 if (!IS_MULTISELECT(descr))
02480 return descr->selected_item;
02481
02482 if (descr->selected_item!=-1)
02483 return descr->selected_item;
02484
02485 return descr->focus_item;
02486
02487
02488 }
02489
02490 static LRESULT LISTBOX_GetTopIndex(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02491 {
02492 return descr->top_item;
02493 }
02494
02495 static LRESULT LISTBOX_ItemFromPoint(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02496 {
02497 POINT pt;
02498 RECT rect;
02499
02500 pt.x = LOWORD(lParam);
02501 pt.y = HIWORD(lParam);
02502 rect.left = 0;
02503 rect.top = 0;
02504 rect.right = descr->width;
02505 rect.bottom = descr->height;
02506
02507 return MAKELONG( LISTBOX_GetItemFromPoint(hwnd, descr, pt.x, pt.y),
02508 !PtInRect( &rect, pt ) );
02509 }
02510
02511 static LRESULT LISTBOX_HandleSetCaretIndex(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02512 {
02513 if ((!IS_MULTISELECT(descr)) && (descr->selected_item != -1)) return LB_ERR;
02514 if (LISTBOX_SetCaretIndex( hwnd, descr, wParam, !lParam ) == LB_ERR)
02515 return LB_ERR;
02516 else
02517 return LB_OKAY;
02518 }
02519
02520 static LRESULT LISTBOX_GetCaretIndex(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02521 {
02522 return descr->focus_item;
02523 }
02524
02525 static LRESULT LISTBOX_SelectString(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02526 {
02527 INT index = LISTBOX_FindString( hwnd, descr, wParam,
02528 (LPCSTR)lParam, FALSE );
02529 if (index == LB_ERR)
02530 return LB_ERR;
02531 LISTBOX_SetSelection( hwnd, descr, index, TRUE, FALSE );
02532 return index;
02533 }
02534
02535 static LRESULT LISTBOX_GetSel(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02536 {
02537 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
02538 return LB_ERR;
02539 return descr->items[wParam].selected;
02540 }
02541
02542 static LRESULT LISTBOX_SetCurSel(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02543 {
02544 if (IS_MULTISELECT(descr)) return LB_ERR;
02545 LISTBOX_SetCaretIndex( hwnd, descr, wParam, TRUE );
02546 return LISTBOX_SetSelection( hwnd, descr, wParam, TRUE, FALSE );
02547 }
02548
02549 static LRESULT LISTBOX_SelItemRange(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02550 {
02551 if (LOWORD(lParam) <= HIWORD(lParam))
02552 return LISTBOX_SelectItemRange( hwnd, descr, LOWORD(lParam),
02553 HIWORD(lParam), wParam );
02554 else
02555 return LISTBOX_SelectItemRange( hwnd, descr, HIWORD(lParam),
02556 LOWORD(lParam), wParam );
02557 }
02558
02559 static LRESULT LISTBOX_SelItemRangeEx(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02560 {
02561 if ((INT)lParam >= (INT)wParam)
02562 return LISTBOX_SelectItemRange( hwnd, descr, wParam, lParam, TRUE );
02563 else
02564 return LISTBOX_SelectItemRange( hwnd, descr, lParam, wParam, FALSE);
02565 }
02566
02567 static LRESULT LISTBOX_GetHorizontalExtent(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02568 {
02569 return descr->horz_extent;
02570 }
02571
02572 static LRESULT LISTBOX_GetAnchorIndex(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02573 {
02574 return descr->anchor_item;
02575 }
02576
02577 static LRESULT LISTBOX_SetAnchorIndex(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02578 {
02579 if (((INT)wParam < -1) || ((INT)wParam >= descr->nb_items))
02580 return LB_ERR;
02581 descr->anchor_item = (INT)wParam;
02582 return LB_OKAY;
02583 }
02584
02585 static LRESULT LISTBOX_GetLocale(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02586 {
02587 return descr->locale;
02588 }
02589
02590 static LRESULT LISTBOX_SetLocale(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02591 {
02592 descr->locale = (LCID)wParam;
02593 return LB_OKAY;
02594 }
02595
02596 static LRESULT LISTBOX_CaretOn(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02597 {
02598 if (descr->caret_on)
02599 return LB_OKAY;
02600 descr->caret_on = TRUE;
02601 if ((descr->focus_item != -1) && (descr->in_focus))
02602 LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
02603 return LB_OKAY;
02604 }
02605
02606 static LRESULT LISTBOX_CaretOff(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02607 {
02608 if (!descr->caret_on)
02609 return LB_OKAY;
02610 descr->caret_on = FALSE;
02611 if ((descr->focus_item != -1) && (descr->in_focus))
02612 LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
02613 return LB_OKAY;
02614 }
02615
02616 static LRESULT LISTBOX_Enable(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02617 {
02618 InvalidateRect( hwnd, NULL, TRUE );
02619 return 0;
02620 }
02621
02622 static LRESULT LISTBOX_GetDlgCode(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02623 {
02624 return DLGC_WANTARROWS | DLGC_WANTCHARS;
02625 }
02626
02627 static LRESULT LISTBOX_Paint(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02628 {
02629 PAINTSTRUCT ps;
02630 HDC hdc = ( wParam ) ? ((HDC)wParam) : BeginPaint( hwnd, &ps );
02631 LRESULT ret;
02632
02633 ret = LISTBOX_Draw( hwnd, descr, hdc );
02634 if( !wParam ) EndPaint( hwnd, &ps );
02635
02636 return ret;
02637 }
02638
02639 static LRESULT LISTBOX_Size(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02640 {
02641 LISTBOX_UpdateSize( hwnd, descr );
02642 return 0;
02643 }
02644
02645 static LRESULT LISTBOX_GetFont(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02646 {
02647 return descr->font;
02648 }
02649
02650 static LRESULT LISTBOX_SetFocus(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02651 {
02652 descr->in_focus = TRUE;
02653 descr->caret_on = TRUE;
02654 if (descr->focus_item != -1)
02655 LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
02656 SEND_NOTIFICATION( hwnd, descr, LBN_SETFOCUS );
02657 return 0;
02658 }
02659
02660 static LRESULT LISTBOX_KillFocus(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02661 {
02662 descr->in_focus = FALSE;
02663 if ((descr->focus_item != -1) && descr->caret_on)
02664 LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
02665 SEND_NOTIFICATION( hwnd, descr, LBN_KILLFOCUS );
02666 return 0;
02667 }
02668
02669 static LRESULT LISTBOX_MouseActivate(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02670 {
02671 return MA_NOACTIVATE;
02672 }
02673
02674 static LRESULT LISTBOX_LButtonDblClk(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02675 {
02676 if (descr->style & LBS_NOTIFY)
02677 SEND_NOTIFICATION( hwnd, descr, LBN_DBLCLK );
02678 return 0;
02679 }
02680
02681 static LRESULT LISTBOX_EraseBackground(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02682 {
02683 if (IS_OWNERDRAW(descr))
02684 {
02685 RECT rect;
02686 HBRUSH hbrush = SendMessageA( descr->owner, WM_CTLCOLORLISTBOX, wParam, (LPARAM)hwnd );
02687
02688 GetClientRect(hwnd, &rect);
02689 if (hbrush) FillRect( (HDC)wParam, &rect, hbrush );
02690 }
02691
02692 return 1;
02693 }
02694
02695 static LRESULT LISTBOX_DropFiles(HWND hwnd,LB_DESCR *descr,WPARAM wParam,LPARAM lParam)
02696 {
02697 if ( !descr->lphc )
02698 return SendMessageA( descr->owner, WM_DROPFILES, wParam, lParam );
02699
02700 return 0;
02701 }
02702
02703 static LRESULT LISTBOX_HandleDragDrop(HWND hwnd,LB_DESCR *descr,UINT msg,WPARAM wParam,LPARAM lParam)
02704 {
02705 if( !descr->lphc )
02706 {
02707 LPDRAGINFO dragInfo = (LPDRAGINFO)lParam;
02708
02709 dragInfo->l = LISTBOX_GetItemFromPoint( hwnd, descr, dragInfo->pt.x,
02710 dragInfo->pt.y );
02711 return SendMessageA( descr->owner, msg, wParam, lParam );
02712 }
02713
02714 return 0;
02715 }
02716
02717
02718
02719
02720 LRESULT WINAPI ListBoxWndProc( HWND hwnd, UINT msg,
02721 WPARAM wParam, LPARAM lParam )
02722 {
02723 LB_DESCR *descr;
02724
02725 if (!(descr = (LB_DESCR*)GetInfoPtr(hwnd)))
02726 {
02727 switch (msg)
02728 {
02729 case WM_CREATE:
02730 return LISTBOX_Create(hwnd,NULL);
02731
02732 case WM_NCCREATE:
02733 return LISTBOX_NCCreate(hwnd,wParam,lParam);
02734 }
02735
02736 return DefWindowProcA( hwnd, msg, wParam, lParam );
02737 }
02738
02739 switch(msg)
02740 {
02741 case LB_RESETCONTENT:
02742 return LISTBOX_ResetContent(hwnd,descr,TRUE);
02743
02744 case LB_ADDSTRING:
02745 return LISTBOX_AddString(hwnd,descr,wParam,lParam);
02746
02747 case LB_INSERTSTRING:
02748 return LISTBOX_InsertString( hwnd, descr, wParam, (LPCSTR)lParam );
02749
02750 case LB_ADDFILE:
02751 return LISTBOX_AddFile(hwnd,descr,wParam,lParam);
02752
02753 case LB_DELETESTRING:
02754 return LISTBOX_DeleteString(hwnd,descr,wParam,lParam);
02755
02756 case LB_GETITEMDATA:
02757 return LISTBOX_GetItemData(hwnd,descr,wParam,lParam);
02758
02759 case LB_SETITEMDATA:
02760 return LISTBOX_SetItemData(hwnd,descr,wParam,lParam);
02761
02762 case LB_GETCOUNT:
02763 return LISTBOX_GetCount(hwnd,descr,wParam,lParam);
02764
02765 case LB_GETTEXT:
02766 return LISTBOX_GetText( hwnd, descr, wParam, (LPSTR)lParam );
02767
02768 case LB_GETTEXTLEN:
02769 return LISTBOX_GetTextLen(hwnd,descr,wParam,lParam);
02770
02771 case LB_GETCURSEL:
02772 return LISTBOX_GetCurSel(hwnd,descr,wParam,lParam);
02773
02774 case LB_GETTOPINDEX:
02775 return LISTBOX_GetTopIndex(hwnd,descr,wParam,lParam);
02776
02777 case LB_GETITEMHEIGHT:
02778 return LISTBOX_GetItemHeight( hwnd, descr, wParam );
02779
02780 case LB_SETITEMHEIGHT:
02781 return LISTBOX_SetItemHeight( hwnd, descr, wParam, lParam );
02782
02783 case LB_ITEMFROMPOINT:
02784 return LISTBOX_ItemFromPoint(hwnd,descr,wParam,lParam);
02785
02786 case LB_SETCARETINDEX:
02787 return LISTBOX_HandleSetCaretIndex(hwnd,descr,wParam,lParam);
02788
02789 case LB_GETCARETINDEX:
02790 return LISTBOX_GetCaretIndex(hwnd,descr,wParam,lParam);
02791
02792 case LB_SETTOPINDEX:
02793 return LISTBOX_SetTopItem( hwnd, descr, wParam, TRUE );
02794
02795 case LB_SETCOLUMNWIDTH:
02796 return LISTBOX_SetColumnWidth( hwnd, descr, wParam );
02797
02798 case LB_GETITEMRECT:
02799 return LISTBOX_GetItemRect( hwnd, descr, wParam, (RECT *)lParam );
02800
02801 case LB_FINDSTRING:
02802 return LISTBOX_FindString( hwnd, descr, wParam, (LPCSTR)lParam, FALSE );
02803
02804 case LB_FINDSTRINGEXACT:
02805 return LISTBOX_FindString( hwnd, descr, wParam, (LPCSTR)lParam, TRUE );
02806
02807 case LB_SELECTSTRING:
02808 return LISTBOX_SelectString(hwnd,descr,wParam,lParam);
02809
02810 case LB_GETSEL:
02811 return LISTBOX_GetSel(hwnd,descr,wParam,lParam);
02812
02813 case LB_SETSEL:
02814 return LISTBOX_SetSelection( hwnd, descr, lParam, wParam, FALSE );
02815
02816 case LB_SETCURSEL:
02817 return LISTBOX_SetCurSel(hwnd,descr,wParam,lParam);
02818
02819 case LB_GETSELCOUNT:
02820 return LISTBOX_GetSelCount( hwnd, descr );
02821
02822 case LB_GETSELITEMS:
02823 return LISTBOX_GetSelItems( hwnd, descr, wParam, (LPINT)lParam );
02824
02825 case LB_SELITEMRANGE:
02826 return LISTBOX_SelItemRange(hwnd,descr,wParam,lParam);
02827
02828 case LB_SELITEMRANGEEX:
02829 return LISTBOX_SelItemRangeEx(hwnd,descr,wParam,lParam);
02830
02831 case LB_GETHORIZONTALEXTENT:
02832 return LISTBOX_GetHorizontalExtent(hwnd,descr,wParam,lParam);
02833
02834 case LB_SETHORIZONTALEXTENT:
02835 return LISTBOX_SetHorizontalExtent( hwnd, descr, wParam );
02836
02837 case LB_GETANCHORINDEX:
02838 return LISTBOX_GetAnchorIndex(hwnd,descr,wParam,lParam);
02839
02840 case LB_SETANCHORINDEX:
02841 return LISTBOX_SetAnchorIndex(hwnd,descr,wParam,lParam);
02842
02843 case LB_DIR:
02844 return LISTBOX_Directory( hwnd, descr, wParam, (LPCSTR)lParam, TRUE );
02845
02846 case LB_GETLOCALE:
02847 return LISTBOX_GetLocale(hwnd,descr,wParam,lParam);
02848
02849 case LB_SETLOCALE:
02850 return LISTBOX_SetLocale(hwnd,descr,wParam,lParam);
02851
02852 case LB_INITSTORAGE:
02853 return LISTBOX_InitStorage( hwnd, descr, wParam, (DWORD)lParam );
02854
02855 case LB_SETCOUNT:
02856 return LISTBOX_SetCount( hwnd, descr, (INT)wParam );
02857
02858 case LB_SETTABSTOPS:
02859 return LISTBOX_SetTabStops( hwnd, descr, wParam, (LPINT)lParam, FALSE );
02860
02861 case LB_CARETON:
02862 return LISTBOX_CaretOn(hwnd,descr,wParam,lParam);
02863
02864 case LB_CARETOFF:
02865 return LISTBOX_CaretOff(hwnd,descr,wParam,lParam);
02866
02867 case WM_DESTROY:
02868 return LISTBOX_Destroy( hwnd, descr );
02869
02870 case WM_ENABLE:
02871 return LISTBOX_Enable(hwnd,descr,wParam,lParam);
02872
02873 case WM_SETREDRAW:
02874 return LISTBOX_SetRedraw( hwnd, descr, wParam != 0 );
02875
02876 case WM_GETDLGCODE:
02877 return LISTBOX_GetDlgCode(hwnd,descr,wParam,lParam);
02878
02879 case WM_PAINT:
02880 return LISTBOX_Paint(hwnd,descr,wParam,lParam);
02881
02882 case WM_SIZE:
02883 return LISTBOX_Size(hwnd,descr,wParam,lParam);
02884
02885 case WM_GETFONT:
02886 return LISTBOX_GetFont(hwnd,descr,wParam,lParam);
02887
02888 case WM_SETFONT:
02889 return LISTBOX_SetFont(hwnd,descr,wParam,lParam);
02890
02891 case WM_SETFOCUS:
02892 return LISTBOX_SetFocus(hwnd,descr,wParam,lParam);
02893
02894 case WM_KILLFOCUS:
02895 return LISTBOX_KillFocus(hwnd,descr,wParam,lParam);
02896
02897 case WM_HSCROLL:
02898 return LISTBOX_HandleHScroll( hwnd, descr, wParam, lParam );
02899
02900 case WM_VSCROLL:
02901 return LISTBOX_HandleVScroll( hwnd, descr, wParam, lParam );
02902
02903 case WM_MOUSEACTIVATE:
02904 return LISTBOX_MouseActivate(hwnd,descr,wParam,lParam);
02905
02906 case WM_MOUSEWHEEL:
02907 return LISTBOX_HandleMouseWheel( hwnd, descr, wParam, lParam );
02908
02909 case WM_LBUTTONDOWN:
02910 return LISTBOX_HandleLButtonDown( hwnd, descr, wParam,
02911 (INT16)LOWORD(lParam),
02912 (INT16)HIWORD(lParam) );
02913 case WM_LBUTTONDBLCLK:
02914 return LISTBOX_LButtonDblClk(hwnd,descr,wParam,lParam);
02915
02916 case WM_MOUSEMOVE:
02917 return LISTBOX_HandleMouseMove( hwnd, descr, (INT16)LOWORD(lParam),
02918 (INT16)HIWORD(lParam) );
02919
02920 case WM_LBUTTONUP:
02921 return LISTBOX_HandleLButtonUp( hwnd, descr );
02922
02923 case WM_KEYDOWN:
02924 return LISTBOX_HandleKeyDown( hwnd, descr, wParam );
02925
02926 case WM_CHAR:
02927 return LISTBOX_HandleChar( hwnd, descr, wParam );
02928
02929 case WM_SYSTIMER:
02930 return LISTBOX_HandleSystemTimer( hwnd, descr );
02931
02932 case WM_ERASEBKGND:
02933 return LISTBOX_EraseBackground(hwnd,descr,wParam,lParam);
02934
02935 case WM_DROPFILES:
02936 return LISTBOX_DropFiles(hwnd,descr,wParam,lParam);
02937
02938 case WM_DROPOBJECT:
02939 case WM_QUERYDROPOBJECT:
02940 case WM_DRAGSELECT:
02941 case WM_DRAGMOVE:
02942 return LISTBOX_HandleDragDrop(hwnd,descr,msg,wParam,lParam);
02943
02944 default:
02945
02946
02947
02948 return DefWindowProcA( hwnd, msg, wParam, lParam );
02949 }
02950 return 0;
02951 }
02952
02953
02954
02955
02956 LRESULT COMBO_Directory( LPHEADCOMBO lphc, UINT attrib, LPSTR dir, BOOL bLong)
02957 {
02958 LB_DESCR *descr = (LB_DESCR*)GetInfoPtr(lphc->hWndLBox);
02959
02960 if( descr )
02961 {
02962 #ifdef __WIN32OS2__
02963
02964 LRESULT lRet = LISTBOX_Directory( lphc->hWndLBox, descr, attrib, dir, bLong );
02965 #else
02966 LRESULT lRet = LISTBOX_Directory( lphc->hwndself, descr, attrib, dir, bLong );
02967 #endif
02968
02969 RedrawWindow( lphc->hwndself, NULL, 0,
02970 RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
02971 return lRet;
02972 }
02973 return CB_ERR;
02974 }
02975
02976
02977
02978
02979
02980
02981 LRESULT WINAPI ComboLBWndProc( HWND hwnd, UINT msg,
02982 WPARAM wParam, LPARAM lParam )
02983 {
02984 LRESULT lRet = 0;
02985
02986
02987 LB_DESCR *descr = (LB_DESCR*)GetInfoPtr(hwnd);
02988
02989
02990
02991
02992 if( descr || msg == WM_CREATE )
02993 {
02994 LPHEADCOMBO lphc = (descr) ? descr->lphc : NULL;
02995
02996 switch( msg )
02997 {
02998 case WM_CREATE:
02999 #define lpcs ((LPCREATESTRUCTA)lParam)
03000
03001
03002
03003 lphc = (LPHEADCOMBO)(lpcs->lpCreateParams);
03004 #undef lpcs
03005 return LISTBOX_Create( hwnd, lphc );
03006 case WM_MOUSEMOVE:
03007 if (lphc && (CB_GETTYPE(lphc) != CBS_SIMPLE))
03008 {
03009 POINT mousePos;
03010 BOOL captured;
03011 RECT clientRect;
03012
03013 mousePos.x = (INT16)LOWORD(lParam);
03014 mousePos.y = (INT16)HIWORD(lParam);
03015
03016
03017
03018
03019
03020
03021 GetClientRect(hwnd, &clientRect);
03022 if (PtInRect( &clientRect, mousePos ))
03023 {
03024 captured = descr->captured;
03025 descr->captured = TRUE;
03026
03027 LISTBOX_HandleMouseMove( hwnd, descr,
03028 mousePos.x, mousePos.y);
03029 descr->captured = captured;
03030 }
03031 else
03032 {
03033 LISTBOX_HandleMouseMove( hwnd, descr,
03034 mousePos.x, mousePos.y);
03035 }
03036
03037
03038 return 0;
03039 }
03040 else
03041 {
03042
03043
03044
03045 return ListBoxWndProc( hwnd, msg, wParam, lParam );
03046 }
03047 case WM_LBUTTONUP:
03048 if (lphc)
03049 {
03050 POINT mousePos;
03051 RECT clientRect;
03052
03053
03054
03055
03056
03057
03058 mousePos.x = (INT16)LOWORD(lParam);
03059 mousePos.y = (INT16)HIWORD(lParam);
03060
03061 GetClientRect(hwnd, &clientRect);
03062
03063
03064
03065
03066
03067
03068
03069 if ( (lParam == 0xFFFFFFFF) ||
03070 (!PtInRect( &clientRect, mousePos )) )
03071 {
03072 LISTBOX_MoveCaret( hwnd,
03073 descr,
03074 lphc->droppedIndex,
03075 FALSE );
03076 }
03077 return LISTBOX_HandleLButtonUp( hwnd, descr );
03078 }
03079 case WM_LBUTTONDOWN:
03080 case WM_LBUTTONDBLCLK:
03081 return LISTBOX_HandleLButtonDownCombo( hwnd, descr,msg, wParam,
03082 (INT16)LOWORD(lParam), (INT16)HIWORD(lParam));
03083 case WM_MOUSEACTIVATE:
03084 return MA_NOACTIVATE;
03085 case WM_NCACTIVATE:
03086 return FALSE;
03087 case WM_KEYDOWN:
03088 if(lphc && (CB_GETTYPE(lphc) != CBS_SIMPLE))
03089 {
03090
03091
03092 if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
03093 ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
03094 && (wParam == VK_DOWN || wParam == VK_UP)) )
03095 {
03096 COMBO_FlipListbox( lphc, FALSE, FALSE );
03097 return 0;
03098 }
03099 }
03100 return LISTBOX_HandleKeyDown( hwnd, descr, wParam );
03101
03102 case LB_SETCURSEL:
03103 lRet = ListBoxWndProc( hwnd, msg, wParam, lParam );
03104 lRet =(lRet == LB_ERR) ? lRet : descr->selected_item;
03105 return lRet;
03106 case WM_NCDESTROY:
03107 if(lphc && (CB_GETTYPE(lphc) != CBS_SIMPLE))
03108 lphc->hWndLBox = 0;
03109
03110
03111 default:
03112 return ListBoxWndProc( hwnd, msg, wParam, lParam );
03113 }
03114 }
03115 lRet = DefWindowProcA( hwnd, msg, wParam, lParam );
03116
03117
03118
03119 return lRet;
03120 }
03121
03122 BOOL LISTBOX_Register()
03123 {
03124 WNDCLASSA wndClass;
03125
03126
03127
03128
03129 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
03130 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
03131 wndClass.lpfnWndProc = (WNDPROC)ListBoxWndProc;
03132 wndClass.cbClsExtra = 0;
03133 wndClass.cbWndExtra = sizeof(VOID*);
03134 wndClass.hCursor = LoadCursorA(0,IDC_ARROWA);
03135 wndClass.hbrBackground = (HBRUSH)0;
03136 wndClass.lpszClassName = LISTBOXCLASSNAME;
03137
03138 return RegisterClassA(&wndClass);
03139 }
03140
03141
03142 BOOL LISTBOX_Unregister()
03143 {
03144 if (GlobalFindAtomA(LISTBOXCLASSNAME))
03145 return UnregisterClassA(LISTBOXCLASSNAME,(HINSTANCE)NULL);
03146 else return FALSE;
03147 }
03148
03149 BOOL COMBOLBOX_Register()
03150 {
03151 WNDCLASSA wndClass;
03152
03153
03154
03155
03156 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
03157 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
03158 wndClass.lpfnWndProc = (WNDPROC)ComboLBWndProc;
03159 wndClass.cbClsExtra = 0;
03160 wndClass.cbWndExtra = sizeof(VOID*);
03161 wndClass.hCursor = LoadCursorA(0,IDC_ARROWA);
03162 wndClass.hbrBackground = (HBRUSH)0;
03163 wndClass.lpszClassName = COMBOLBOXCLASSNAME;
03164
03165 return RegisterClassA(&wndClass);
03166 }
03167
03168 BOOL COMBOLBOX_Unregister()
03169 {
03170 if (GlobalFindAtomA(COMBOLBOXCLASSNAME))
03171 return UnregisterClassA(COMBOLBOXCLASSNAME,(HINSTANCE)NULL);
03172 else return FALSE;
03173 }