OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [mwin/] [winlib/] [listbox.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
/*
2
 * Copyright (C) 1999, 2000, Wei Yongming.
3
 * Portions Copyright (c) 2000 Greg Haerr <greg@censoft.com>
4
 *
5
 * Listbox for Microwindows win32 api.
6
 */
7
 
8
/*
9
**  This library is free software; you can redistribute it and/or
10
**  modify it under the terms of the GNU Library General Public
11
**  License as published by the Free Software Foundation; either
12
**  version 2 of the License, or (at your option) any later version.
13
**
14
**  This library is distributed in the hope that it will be useful,
15
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
**  Library General Public License for more details.
18
**
19
**  You should have received a copy of the GNU Library General Public
20
**  License along with this library; if not, write to the Free
21
**  Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22
**  MA 02111-1307, USA
23
*/
24
 
25
/*
26
**  Alternatively, the contents of this file may be used under the terms
27
**  of the Mozilla Public License (the "MPL License") in which case the
28
**  provisions of the MPL License are applicable instead of those above.
29
*/
30
 
31
/* Note:
32
**  Although there was a version by Zhao Jianghua, this version of
33
**  LISTBOX control is written by Wei Yongming from scratch.
34
**
35
** Modify records:
36
**
37
**  Who             When        Where       For What                Status
38
**-----------------------------------------------------------------------------
39
**  Wei Yongming    1999/10/18  Tsinghua    Item Additional Data    Finished
40
**  Wei Yongming    1999/10/31  Tsinghua    Space bar for checkmark Finished
41
**  Wei Yongming    1999/10/31  Tsinghua    Character match item    Finished
42
**  Wei Yongming    1999/11/07  Tsinghua    Character match item    Bug fixing
43
**  WEI Yongming    2000/01/20  Tsinghua    Thumb dragging          Finished
44
**  WEI Yongming    2000/02/24  Tsinghua    Add MPL License         Finished
45
**  Kevin Tseng     2000/05/26  gv          port to microwin        ported
46
**  Greg Haerr      2000/06/15  Utah        3d look, bug fixes      Finished
47
**  Kevin Tseng     2000/06/22  gv          port to mw-nanox        ported
48
**  Kevin Tseng     2000/06/22  gv          fixed bug if no item    Finished
49
**  Kevin Tseng     2000/08/08  gv          enable scrollbar(V)     porting
50
**  Kevin Tseng     2000/08/10  gv          enable scrollbar(V)     ported
51
**  Kevin Tseng     2000/08/10  gv          WM_CHAR, WM_KEYDOWN     ported
52
**
53
** TODO:
54
** 1. Multiple columns support.
55
*/
56
 
57
#include <stdio.h>
58
#include <stdlib.h>
59
#include <string.h>
60
#define MWINCLUDECOLORS
61
#include "windows.h"
62
#include "wintools.h"   /* Draw3dBox */
63
#include "device.h"     /* GdGetTextSize */
64
 
65
#define FixStrAlloc(n)  malloc((n)+1)
66
#define FreeFixStr(p)   free(p)
67
 
68
#define LBIF_NORMAL         0x0000L
69
#define LBIF_SELECTED       0x0001L
70
#define LBIF_CHECKED        0x0010L
71
#define LBIF_PARTCHECKED    0x0020L
72
#define LBIF_CHECKMARKMASK  0x00F0L
73
 
74
#define CMFLAG_BLANK        0
75
#define CMFLAG_CHECKED      1
76
#define CMFLAG_PARTCHECKED  2
77
typedef struct _LISTBOXITEMINFO {
78
    int     insPos;         /* insert position */
79
    char*   string;         /* item string */
80
    int     cmFlag;         /* check mark flag */
81
    HICON   hIcon;          /* handle of icon */
82
} LISTBOXITEMINFO, *PLISTBOXITEMINFO;
83
 
84
typedef struct _LISTBOXITEM {
85
    char*   key;                /* item sort key */
86
    DWORD   dwFlags;            /* item flags */
87
    DWORD   dwData;             /* item data */
88
    DWORD   dwAddData;          /* item additional data */
89
    struct  _LISTBOXITEM* next;  /* next item */
90
} LISTBOXITEM, *PLISTBOXITEM;
91
 
92
#define DEF_LB_BUFFER_LEN       5
93
 
94
#define LBF_FOCUS               0x0001
95
#define LBF_NOTHINGSELECTED     0x0002
96
 
97
typedef struct _LISTBOXDATA {
98
    DWORD dwFlags;          /* listbox flags */
99
 
100
    int itemCount;          /* items count */
101
    int itemTop;            /* start display item */
102
    int itemVisibles;       /* number of visible items */
103
 
104
    int itemHilighted;      /* current hilighted item */
105
    int itemHeight;         /* item height */
106
 
107
    LISTBOXITEM* head;      /* items linked list head */
108
 
109
    int buffLen;            /* buffer length */
110
    LISTBOXITEM* buffStart; /* buffer start */
111
    LISTBOXITEM* buffEnd;   /* buffer end */
112
    LISTBOXITEM* freeList;  /* free list in buffer */
113
} LISTBOXDATA, *PLISTBOXDATA;
114
 
115
void ListboxControlCleanup ();
116
static LRESULT CALLBACK
117
ListboxCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
118
 
119
#define ITEM_BOTTOM(x)  (x->itemTop + x->itemVisibles - 1)
120
 
121
#define LST_WIDTH_CHECKMARK     11
122
#define LST_HEIGHT_CHECKMARK    11
123
#define LST_INTER_BMPTEXT       2
124
 
125
int WINAPI MwRegisterListboxControl(HINSTANCE hInstance)
126
{
127
        WNDCLASS        wc;
128
#if 0
129
    static BITMAP sg_bmpCheckMark;
130
    if (!LoadSystemBitmap (&sg_bmpCheckMark, "checkmark")) {
131
        fprintf (stderr, "Load ListBox Check Mark Bitmap failure!\n");
132
        return FALSE;
133
    }
134
#endif
135
        wc.style        = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
136
        wc.lpfnWndProc  = (WNDPROC)ListboxCtrlProc;
137
        wc.cbClsExtra   = 0;
138
        wc.cbWndExtra   = 0;
139
        wc.hInstance    = hInstance;
140
        wc.hIcon        = NULL;
141
        wc.hCursor      = 0; /*LoadCursor(NULL, IDC_ARROW);*/
142
        wc.hbrBackground= GetStockObject(WHITE_BRUSH);
143
        wc.lpszMenuName = NULL;
144
        wc.lpszClassName= "LISTBOX";
145
 
146
        return RegisterClass(&wc);
147
}
148
 
149
void ListboxControlCleanup ()
150
{
151
#if 0
152
    UnloadBitmap (&sg_bmpCheckMark);
153
#endif
154
}
155
 
156
static LRESULT NotifyParent (HWND hwnd, int id, int code)
157
{
158
    return SendMessage (GetParent (hwnd), WM_COMMAND,
159
                 (WPARAM) MAKELONG (id, code), (LPARAM)hwnd);
160
}
161
 
162
static BOOL lstInitListBoxData (HWND hwnd,LISTBOXDATA* pData, int len)
163
{
164
    int i, xw, xh, xb;
165
    PLISTBOXITEM plbi;
166
    HDC hdc;
167
 
168
    memset (pData, 0, sizeof (LISTBOXDATA));
169
#if 0
170
    pData->itemHeight = GetSysCharHeight ();
171
#else
172
    hdc=GetDC(hwnd);
173
#if MWCLIENT    /* nanox client */
174
    GrSetGCFont(hdc->gc,hdc->font->fontid);
175
    GrGetGCTextSize(hdc->gc,"X",1,
176
                MWTF_ASCII,&xw,&xh,&xb);
177
#else
178
    GdSetFont(hdc->font->pfont);
179
    GdGetTextSize(hdc->font->pfont,"X",1,
180
                &xw,&xh,&xb,MWTF_ASCII);
181
#endif
182
    ReleaseDC(hwnd,hdc);
183
    pData->itemHeight=xh + 1;
184
#endif
185
    pData->itemHilighted = 0;
186
    pData->dwFlags = LBF_NOTHINGSELECTED;
187
 
188
    /* init item buffer. */
189
    if (!(pData->buffStart = malloc (len * sizeof (LISTBOXITEM))))
190
        return FALSE;
191
 
192
    pData->buffLen = len;
193
    pData->buffEnd = pData->buffStart + len;
194
    pData->freeList = pData->buffStart;
195
 
196
    plbi = pData->freeList;
197
    for (i = 0; i < len - 1; i++) {
198
        plbi->next = plbi + 1;
199
        plbi ++;
200
    }
201
    plbi->next = NULL;
202
 
203
    return TRUE;
204
}
205
 
206
static void lstListBoxCleanUp (LISTBOXDATA* pData)
207
{
208
    PLISTBOXITEM plbi;
209
    PLISTBOXITEM next;
210
 
211
    plbi = pData->head;
212
    while (plbi) {
213
        FreeFixStr (plbi->key);
214
        next = plbi->next;
215
        if (plbi < pData->buffStart || plbi > pData->buffEnd)
216
            free (plbi);
217
 
218
        plbi = next;
219
    }
220
 
221
    free (pData->buffStart);
222
}
223
 
224
static void lstResetListBoxContent (PLISTBOXDATA pData)
225
{
226
    int i;
227
    PLISTBOXITEM plbi, next;
228
 
229
    pData->itemCount = 0;
230
    pData->itemTop = 0;
231
    pData->itemHilighted = 0;
232
#if 0
233
    pData->itemVisibles = 0;
234
#endif
235
 
236
    plbi = pData->head;
237
    while (plbi) {
238
        FreeFixStr (plbi->key);
239
        next = plbi->next;
240
        if (plbi < pData->buffStart || plbi > pData->buffEnd)
241
            free (plbi);
242
 
243
        plbi = next;
244
    }
245
 
246
    pData->head = NULL;
247
    pData->freeList = pData->buffStart;
248
 
249
    plbi = pData->freeList;
250
    for (i = 0; i < pData->buffLen - 1; i++) {
251
        plbi->next = plbi + 1;
252
        plbi ++;
253
    }
254
    plbi->next = NULL;
255
}
256
 
257
static PLISTBOXITEM lstAllocItem (PLISTBOXDATA pData)
258
{
259
    PLISTBOXITEM plbi;
260
 
261
    if (pData->freeList) {
262
        plbi = pData->freeList;
263
        pData->freeList = plbi->next;
264
    }
265
    else
266
        plbi = (PLISTBOXITEM) malloc (sizeof (LISTBOXITEM));
267
 
268
    return plbi;
269
}
270
 
271
static void lstFreeItem (PLISTBOXDATA pData, PLISTBOXITEM plbi)
272
{
273
    if (plbi < pData->buffStart || plbi > pData->buffEnd)
274
        free (plbi);
275
    else {
276
        plbi->next = pData->freeList;
277
        pData->freeList = plbi;
278
    }
279
}
280
 
281
static int lstAddNewItem (DWORD dwStyle,
282
        PLISTBOXDATA pData, PLISTBOXITEM newItem, int pos)
283
{
284
    PLISTBOXITEM plbi;
285
    PLISTBOXITEM insPosItem = NULL;
286
    int insPos = 0;
287
 
288
    newItem->next = NULL;
289
    if (!pData->head)
290
        insPosItem = NULL;
291
    else if (dwStyle & LBS_SORT) {
292
        plbi = pData->head;
293
 
294
        if (strcmp (newItem->key, plbi->key) < 0) {
295
            insPosItem = NULL;
296
            insPos = 0;
297
        }
298
        else {
299
            while (plbi->next) {
300
                if (strcmp (newItem->key, plbi->next->key) <= 0)
301
                    break;
302
 
303
                plbi = plbi->next;
304
                insPos ++;
305
            }
306
            insPosItem = plbi;
307
        }
308
    }
309
    else {
310
        plbi = pData->head;
311
 
312
        if (pos < 0) {
313
            while (plbi->next) {
314
                plbi = plbi->next;
315
                insPos ++;
316
            }
317
            insPosItem = plbi;
318
        }
319
        else if (pos > 0) {
320
            int index = 0;
321
 
322
            while (plbi->next) {
323
                if (pos == index)
324
                    break;
325
                plbi = plbi->next;
326
                index ++;
327
                insPos ++;
328
            }
329
            insPosItem = plbi;
330
        }
331
    }
332
 
333
    if (insPosItem) {
334
        plbi = insPosItem->next;
335
        insPosItem->next = newItem;
336
        newItem->next = plbi;
337
 
338
        insPos ++;
339
    }
340
    else {
341
        plbi = pData->head;
342
        pData->head = newItem;
343
        newItem->next = plbi;
344
    }
345
 
346
    pData->itemCount ++;
347
    return insPos;
348
}
349
 
350
static PLISTBOXITEM lstRemoveItem (PLISTBOXDATA pData, int* pos)
351
{
352
    int index = 0;
353
    PLISTBOXITEM plbi, prev;
354
 
355
    if (!pData->head)
356
        return NULL;
357
 
358
    if (*pos < 0) {
359
        prev = pData->head;
360
        plbi = pData->head;
361
        while (plbi->next) {
362
            prev = plbi;
363
            plbi = plbi->next;
364
            index ++;
365
        }
366
 
367
        if (plbi == pData->head) {
368
            pData->head = pData->head->next;
369
            *pos = 0;
370
            return plbi;
371
        }
372
        else {
373
            prev->next = plbi->next;
374
            *pos = index;
375
            return plbi;
376
        }
377
    }
378
    else if (*pos == 0) {
379
        plbi = pData->head;
380
        pData->head = plbi->next;
381
        return plbi;
382
    }
383
    else {
384
        index = 0;
385
        prev = pData->head;
386
        plbi = pData->head;
387
        while (plbi->next) {
388
            if (*pos == index)
389
                break;
390
 
391
            prev = plbi;
392
            plbi = plbi->next;
393
            index ++;
394
        }
395
 
396
        if (plbi == pData->head) {
397
            pData->head = pData->head->next;
398
            *pos = 0;
399
            return plbi;
400
        }
401
        else {
402
            prev->next = plbi->next;
403
            *pos = index;
404
            return plbi;
405
        }
406
    }
407
 
408
    return NULL;
409
}
410
 
411
static void lstGetItemsRect (PLISTBOXDATA pData, int start, int end, RECT* prc)
412
{
413
    if (start < 0)
414
        start = 0;
415
 
416
    prc->top = (start - pData->itemTop)*pData->itemHeight;
417
 
418
    if (end >= 0)
419
        prc->bottom = (end - pData->itemTop + 1)*pData->itemHeight;
420
 
421
}
422
 
423
static void lstInvalidateItem (HWND hwnd, PLISTBOXDATA pData, int pos,BOOL fEBk)
424
{
425
    RECT rcInv;
426
 
427
    if (pos < pData->itemTop || pos > (pData->itemTop + pData->itemVisibles))
428
        return;
429
 
430
    GetClientRect (hwnd, &rcInv);
431
    rcInv.top = (pos - pData->itemTop)*pData->itemHeight;
432
    rcInv.bottom = rcInv.top + pData->itemHeight;
433
 
434
    InvalidateRect (hwnd, &rcInv, fEBk);
435
}
436
 
437
static BOOL lstInvalidateUnderItem (HWND hwnd, PLISTBOXDATA pData, int pos)
438
{
439
    RECT rcInv;
440
 
441
    if (pos > (pData->itemTop + pData->itemVisibles))
442
        return FALSE;
443
 
444
    if (pos <= pData->itemTop) {
445
        InvalidateRect (hwnd, NULL, TRUE);
446
        return TRUE;
447
    }
448
 
449
    GetClientRect (hwnd, &rcInv);
450
 
451
    lstGetItemsRect (pData, pos, -1, &rcInv);
452
 
453
    if (rcInv.top < rcInv.bottom)
454
        InvalidateRect (hwnd, &rcInv, TRUE);
455
 
456
    return TRUE;
457
}
458
 
459
static PLISTBOXITEM lstGetItem (PLISTBOXDATA pData, int pos)
460
{
461
    int i;
462
    PLISTBOXITEM plbi;
463
 
464
    plbi = pData->head;
465
    for (i=0; i < pos && plbi; i++)
466
        plbi = plbi->next;
467
 
468
    return plbi;
469
}
470
 
471
static int lstFindItem (PLISTBOXDATA pData, int start, char* key, BOOL bExact)
472
{
473
    PLISTBOXITEM plbi;
474
    int keylen = strlen (key);
475
 
476
    if (start >= (pData->itemCount - 1))
477
        start = 0;
478
 
479
    plbi = lstGetItem (pData, start);
480
 
481
    while (plbi)
482
    {
483
        if (bExact && (keylen != strlen (plbi->key))) {
484
            plbi = plbi->next;
485
            start ++;
486
            continue;
487
        }
488
 
489
        if (strncasecmp (key, plbi->key, keylen) == 0)
490
            return start;
491
 
492
        plbi = plbi->next;
493
        start ++;
494
    }
495
 
496
    return LB_ERR;
497
}
498
 
499
static void lstOnDrawSListBoxItems (HDC hdc, DWORD dwStyle,
500
                PLISTBOXDATA pData, int width)
501
{
502
    PLISTBOXITEM plbi;
503
    int i;
504
    int x = 0, y = 0;
505
    int offset;
506
    RECT rc;
507
    COLORREF bk;
508
 
509
    plbi = lstGetItem (pData, pData->itemTop);
510
 
511
    for (i = 0; plbi && i < (pData->itemVisibles + 1); i++) {
512
 
513
        if (plbi->dwFlags & LBIF_SELECTED) {
514
            SetBkColor (hdc, bk = BLUE);
515
            SetTextColor (hdc, WHITE);
516
        }
517
        else {
518
            SetBkColor (hdc, bk = WHITE);
519
            SetTextColor (hdc, BLACK);
520
        }
521
        rc.left = 0;
522
        rc.top = y;
523
        rc.right = width;
524
        rc.bottom = y + pData->itemHeight;
525
        FastFillRect(hdc, &rc, bk);
526
 
527
        if (dwStyle & LBS_CHECKBOX) {
528
            x = LST_INTER_BMPTEXT;
529
            if (plbi->dwFlags & LBIF_CHECKED)
530
                offset = 0;
531
            else if (plbi->dwFlags & LBIF_PARTCHECKED)
532
                offset = LST_WIDTH_CHECKMARK << 1;
533
            else
534
                offset = LST_WIDTH_CHECKMARK;
535
#if 0   /* fix: no bitmap */
536
            FillBoxWithBitmapPart (hdc,
537
                x, y + ((pData->itemHeight - LST_HEIGHT_CHECKMARK)>>1),
538
                LST_WIDTH_CHECKMARK, LST_HEIGHT_CHECKMARK,
539
                0, 0,
540
                &sg_bmpCheckMark,
541
                offset, 0);
542
#endif
543
            x += LST_WIDTH_CHECKMARK + LST_INTER_BMPTEXT;
544
        }
545
#if 0   /* fix: no icon */
546
        if (dwStyle & LBS_USEICON && plbi->dwData) {
547
            DrawIcon (hdc,
548
                x, y, pData->itemHeight, pData->itemHeight,
549
                (HICON) plbi->dwData);
550
            x += pData->itemHeight + LST_INTER_BMPTEXT;
551
        }
552
#endif
553
 
554
/* jmt: should be SYSTEM_FIXED_FONT because of minigui's GetSysCharXXX() */
555
#if 0
556
        SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
557
#endif
558
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
559
        TextOut (hdc, x+2, y, plbi->key,-1);
560
 
561
        y += pData->itemHeight;
562
        plbi = plbi->next;
563
    }
564
}
565
 
566
static int lstSelectItem (DWORD dwStyle, PLISTBOXDATA pData, int newSel)
567
{
568
    PLISTBOXITEM plbi, newItem;
569
    int index;
570
 
571
    newItem = lstGetItem (pData, newSel);
572
#if 1   /* jmt: fixed if no item added */
573
    if (!newItem) return -1;
574
#endif 
575
#ifdef _DEBUG
576
    if (!newItem)
577
        fprintf (stderr, "ASSERT failed: return value of lstGetItem"
578
                         " in lstSelectItem.\n");
579
#endif
580
 
581
    if (dwStyle & LBS_MULTIPLESEL) {
582
        newItem->dwFlags ^= LBIF_SELECTED;
583
        return newSel;
584
    }
585
 
586
    index = 0;
587
    plbi = pData->head;
588
    while (plbi) {
589
        if (plbi->dwFlags & LBIF_SELECTED) {
590
            if (index != newSel) {
591
                plbi->dwFlags &= ~LBIF_SELECTED;
592
                newItem->dwFlags |= LBIF_SELECTED;
593
                return index;
594
            }
595
            break;
596
        }
597
 
598
        plbi = plbi->next;
599
        index ++;
600
    }
601
 
602
    newItem->dwFlags |= LBIF_SELECTED;
603
    return -1;
604
}
605
 
606
static void lstDrawFocusRect (HDC hdc, PLISTBOXDATA pData, RECT* rc)
607
{
608
    HGDIOBJ oldbrush,oldpen;
609
 
610
    if (pData->itemHilighted < pData->itemTop
611
            || pData->itemHilighted > (pData->itemTop + pData->itemVisibles))
612
        return;
613
 
614
    if (pData->dwFlags & LBF_FOCUS) {
615
        lstGetItemsRect (pData, pData->itemHilighted, pData->itemHilighted, rc);
616
#if 0
617
        InflateRect (rc, -1, -1);
618
 
619
        FocusRect (hdc, rc->left - 1, rc->top, rc->right, rc->bottom);
620
#else
621
        oldbrush=SelectObject(hdc, GetStockObject(NULL_BRUSH));
622
        oldpen=SelectObject(hdc, CreatePen(PS_SOLID, 1,
623
                                GetSysColor(COLOR_BTNHIGHLIGHT)));
624
#if 0
625
        GdSetMode(MWMODE_XOR);
626
#endif
627
        Rectangle (hdc, rc->left, rc->top, rc->right, rc->bottom);
628
#if 0
629
        GdSetMode(MWMODE_SET);
630
#endif
631
        SelectObject(hdc,oldbrush);
632
        DeleteObject(SelectObject(hdc,oldpen));
633
#endif
634
    }
635
}
636
 
637
static void lstCalcParams (const RECT* rcClient, PLISTBOXDATA pData)
638
{
639
#define RECTHP(prc)  (prc->bottom - prc->top)
640
    pData->itemVisibles = (RECTHP (rcClient)) / pData->itemHeight;
641
 
642
#if 1   /* test calculation of itemVisibles */
643
    if( ((RECTHP (rcClient)) % pData->itemHeight) )
644
        pData->itemVisibles++;
645
#endif
646
}
647
 
648
extern BOOL SetScrollPos (HWND hWnd, int iSBar, int iNewPos);
649
extern BOOL EnableScrollBar (HWND hWnd, int iSBar, BOOL bEnable);
650
 
651
static void lstSetVScrollInfo (HWND hwnd, PLISTBOXDATA pData, BOOL fRedraw)
652
{
653
    SCROLLINFO si;
654
 
655
    if (pData->itemVisibles >= pData->itemCount)
656
    {
657
        SetScrollPos (hwnd, SB_VERT, 0);
658
        EnableScrollBar (hwnd, SB_VERT, FALSE);
659
        return;
660
    }
661
 
662
    si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
663
    si.nMax = pData->itemCount - 1;
664
    si.nMin = 0;
665
    si.nPage = min (pData->itemVisibles, (pData->itemCount - pData->itemTop));
666
    si.nPos = pData->itemTop;
667
 
668
    SetScrollInfo (hwnd, SB_VERT, &si, fRedraw);
669
    EnableScrollBar (hwnd, SB_VERT, TRUE);
670
}
671
 
672
LRESULT CALLBACK
673
ListboxCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
674
{
675
    HDC             hdc;
676
    HWND            pCtrl;
677
    PLISTBOXDATA    pData;
678
    DWORD           dwStyle;
679
 
680
    pCtrl   = hwnd;
681
    dwStyle = pCtrl->style;
682
 
683
    switch (message)
684
    {
685
        case WM_CREATE:
686
            pData = (LISTBOXDATA*) malloc (sizeof(LISTBOXDATA));
687
            if (pData == NULL)
688
                return -1;
689
 
690
            pCtrl->userdata = (DWORD)pData;
691
            if (!lstInitListBoxData (hwnd, pData, DEF_LB_BUFFER_LEN)) {
692
                free (pData);
693
                return -1;
694
            }
695
        break;
696
 
697
        case WM_SIZE:
698
        {
699
            RECT rc;
700
 
701
            pData = (PLISTBOXDATA)pCtrl->userdata;
702
            GetClientRect(hwnd, &rc);
703
            lstCalcParams (&rc, pData);
704
        }
705
        break;
706
 
707
        case WM_DESTROY:
708
            pData = (PLISTBOXDATA)pCtrl->userdata;
709
            lstListBoxCleanUp (pData);
710
            free (pData);
711
        break;
712
 
713
        case LB_RESETCONTENT:
714
            pData = (PLISTBOXDATA)pCtrl->userdata;
715
            lstResetListBoxContent (pData);
716
            InvalidateRect (hwnd, NULL, TRUE);
717
        break;
718
 
719
        case LB_ADDSTRING:
720
        case LB_INSERTSTRING:
721
        {
722
            char* string = NULL;
723
            PLISTBOXITEMINFO plbii = NULL;
724
            PLISTBOXITEM newItem;
725
            int pos;
726
 
727
            if (dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON) {
728
                plbii = (PLISTBOXITEMINFO)lParam;
729
                if (!plbii)
730
                    return LB_ERR;
731
 
732
                string = plbii->string;
733
            }
734
            else {
735
                string = (char*)lParam;
736
                if (string == NULL || string [0] == '\0')
737
                    return LB_ERR;
738
            }
739
 
740
            pData = (PLISTBOXDATA)pCtrl->userdata;
741
            newItem = lstAllocItem (pData);
742
            if (!newItem) {
743
                NotifyParent (hwnd, pCtrl->id, LBN_ERRSPACE);
744
                return LB_ERRSPACE;
745
            }
746
 
747
            newItem->key = FixStrAlloc (strlen (string));
748
            strcpy (newItem->key, string);
749
            newItem->dwFlags = LBIF_NORMAL;
750
            if (plbii) {
751
                switch (plbii->cmFlag) {
752
                    case CMFLAG_CHECKED:
753
                        newItem->dwFlags |= LBIF_CHECKED;
754
                    break;
755
                    case CMFLAG_PARTCHECKED:
756
                        newItem->dwFlags |= LBIF_PARTCHECKED;
757
                    break;
758
                }
759
 
760
                if (dwStyle & LBS_USEICON)
761
                    newItem->dwData = (DWORD)plbii->hIcon;
762
                else
763
                    newItem->dwData = 0L;
764
            }
765
            newItem->dwAddData = 0L;
766
 
767
            if (message == LB_ADDSTRING)
768
                pos = lstAddNewItem (dwStyle, pData, newItem, -1);
769
            else
770
                pos = lstAddNewItem (dwStyle, pData, newItem, (int)wParam);
771
 
772
            lstInvalidateUnderItem (hwnd, pData, pos);
773
 
774
            lstSetVScrollInfo (hwnd, pData, TRUE);
775
 
776
            return pos;
777
        }
778
        break;
779
 
780
        case LB_DELETESTRING:
781
        {
782
            PLISTBOXITEM removed;
783
            int delete;
784
 
785
            delete = (int)wParam;
786
 
787
            pData = (PLISTBOXDATA)pCtrl->userdata;
788
            removed = lstRemoveItem (pData, &delete);
789
            if (removed) {
790
                FreeFixStr (removed->key);
791
                lstFreeItem (pData, removed);
792
 
793
                pData->itemCount --;
794
 
795
                if (pData->itemTop != 0
796
                        && pData->itemCount <= pData->itemVisibles) {
797
                    pData->itemTop = 0;
798
                    InvalidateRect (hwnd, NULL, TRUE);
799
                }
800
                else {
801
                    lstInvalidateUnderItem (hwnd, pData, delete);
802
                    if (delete <= pData->itemTop) {
803
                        pData->itemTop --;
804
                        if (pData->itemTop < 0)
805
                            pData->itemTop = 0;
806
                    }
807
                }
808
 
809
                if (pData->itemHilighted >= pData->itemCount) {
810
                    pData->itemHilighted = pData->itemCount - 1;
811
                    if (pData->itemHilighted < 0)
812
                        pData->itemHilighted = 0;
813
                }
814
 
815
                if (pData->itemHilighted < pData->itemTop)
816
                    pData->itemHilighted = pData->itemTop;
817
                if (pData->itemHilighted > ITEM_BOTTOM (pData))
818
                    pData->itemHilighted = ITEM_BOTTOM (pData);
819
 
820
                lstSetVScrollInfo (hwnd, pData, TRUE);
821
            }
822
        }
823
        break;
824
 
825
        case LB_FINDSTRING:
826
            if( *(char*)lParam == '\0' )
827
                return LB_ERR;
828
 
829
            pData = (PLISTBOXDATA)pCtrl->userdata;
830
            return lstFindItem(pData, (int)wParam, (char*)lParam, FALSE);
831
 
832
        case LB_FINDSTRINGEXACT:
833
            if( *(char*)lParam == '\0' )
834
                return LB_ERR;
835
 
836
            pData = (PLISTBOXDATA)pCtrl->userdata;
837
            return lstFindItem(pData, (int)wParam, (char*)lParam, TRUE);
838
 
839
        case LB_SETTOPINDEX:
840
        {
841
            int newTop = (int) wParam;
842
 
843
            pData = (PLISTBOXDATA)pCtrl->userdata;
844
 
845
            if (newTop <0)
846
                newTop = 0;
847
            else if (newTop > pData->itemCount - pData->itemVisibles)
848
                newTop = pData->itemCount - pData->itemVisibles;
849
 
850
            if (pData->itemTop != newTop) {
851
                pData->itemTop = newTop;
852
 
853
                if (pData->itemHilighted < pData->itemTop)
854
                    pData->itemHilighted = pData->itemTop;
855
                if (pData->itemHilighted > ITEM_BOTTOM (pData))
856
                    pData->itemHilighted = ITEM_BOTTOM (pData);
857
 
858
                lstSetVScrollInfo (hwnd, pData, TRUE);
859
 
860
                InvalidateRect (hwnd, NULL, TRUE);
861
            }
862
        }
863
        break;
864
 
865
        case LB_SETCURSEL:
866
        case LB_SETCARETINDEX:
867
        {
868
            int new = (int)wParam;
869
            int old, newTop;
870
 
871
            pData = (PLISTBOXDATA)pCtrl->userdata;
872
            if (new < 0 || new > pData->itemCount - 1)
873
                return LB_ERR;
874
 
875
            old = pData->itemHilighted;
876
            if (new >= 0 && new != old) {
877
                if (pData->itemCount - new >= pData->itemVisibles)
878
                    newTop = new;
879
                else
880
                    newTop = max (pData->itemCount - pData->itemVisibles, 0);
881
 
882
                pData->itemTop = newTop;
883
                pData->itemHilighted = new;
884
                lstSetVScrollInfo (hwnd, pData, TRUE);
885
            }
886
 
887
            if (!(dwStyle & LBS_MULTIPLESEL))
888
                lstSelectItem (dwStyle, pData, new);
889
            InvalidateRect (hwnd, NULL, TRUE);
890
 
891
            return old;
892
        }
893
        break;
894
 
895
        case LB_GETCOUNT:
896
            pData = (PLISTBOXDATA)pCtrl->userdata;
897
            return pData->itemCount;
898
        break;
899
 
900
        case LB_GETCURSEL:
901
        {
902
            PLISTBOXITEM plbi;
903
            int index = 0;
904
 
905
            pData = (PLISTBOXDATA)pCtrl->userdata;
906
            if (dwStyle & LBS_MULTIPLESEL)
907
                return pData->itemHilighted;
908
 
909
            plbi = pData->head;
910
            while (plbi) {
911
                if (plbi->dwFlags & LBIF_SELECTED)
912
                    return index;
913
 
914
                index ++;
915
                plbi = plbi->next;
916
           }
917
 
918
           return LB_ERR;
919
        }
920
        break;
921
 
922
        case LB_GETSELCOUNT:
923
        {
924
            int nSel;
925
            PLISTBOXITEM plbi;
926
 
927
            pData = (PLISTBOXDATA)pCtrl->userdata;
928
 
929
            nSel = 0;
930
            plbi = pData->head;
931
            while (plbi) {
932
                if (plbi->dwFlags & LBIF_SELECTED)
933
                    nSel ++;
934
                plbi = plbi->next;
935
            }
936
 
937
            return nSel;
938
        }
939
        break;
940
 
941
        case LB_GETTOPINDEX:
942
            pData = (PLISTBOXDATA)pCtrl->userdata;
943
            return pData->itemTop;
944
        break;
945
 
946
        case LB_GETCARETINDEX:
947
            pData = (PLISTBOXDATA)pCtrl->userdata;
948
            return pData->itemHilighted;
949
        break;
950
 
951
        case LB_GETTEXTLEN:
952
        {
953
            PLISTBOXITEM plbi;
954
 
955
            pData = (PLISTBOXDATA)pCtrl->userdata;
956
            plbi = lstGetItem (pData, (int)wParam);
957
            if (plbi)
958
                return strlen (plbi->key);
959
            else
960
                return LB_ERR;
961
        }
962
        break;
963
 
964
        case LB_GETTEXT:
965
        {
966
            PLISTBOXITEM plbi;
967
 
968
            pData = (PLISTBOXDATA)pCtrl->userdata;
969
            plbi = lstGetItem (pData, (int)wParam);
970
            if (plbi)
971
                strcpy ((char*)lParam, plbi->key);
972
            else
973
                return LB_ERR;
974
        }
975
        break;
976
 
977
        case LB_SETTEXT:
978
        {
979
            PLISTBOXITEM plbi;
980
            char* newStr;
981
 
982
            pData = (PLISTBOXDATA)pCtrl->userdata;
983
            plbi = lstGetItem (pData, (int)wParam);
984
            if (plbi) {
985
                newStr = FixStrAlloc (strlen ((char*)lParam));
986
                if (newStr) {
987
                    FreeFixStr (plbi->key);
988
                    plbi->key = newStr;
989
                    strcpy (plbi->key, (char*)lParam);
990
                    lstInvalidateItem (hwnd, pData, (int)wParam, TRUE);
991
                }
992
                else
993
                    return LB_ERR;
994
            }
995
            else
996
                return LB_ERR;
997
        }
998
        break;
999
 
1000
        case LB_GETITEMDATA:
1001
        {
1002
            PLISTBOXITEM plbi;
1003
            PLISTBOXITEMINFO plbii;
1004
 
1005
            pData = (PLISTBOXDATA)pCtrl->userdata;
1006
            if (!(plbi = lstGetItem (pData, (int)wParam)))
1007
                return LB_ERR;
1008
 
1009
            if (!(dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON)) {
1010
                return plbi->dwData;
1011
            }
1012
 
1013
            plbii = (PLISTBOXITEMINFO)lParam;
1014
            if (!plbii)
1015
                return LB_ERR;
1016
 
1017
            if (plbi->dwFlags & LBIF_CHECKED)
1018
                plbii->cmFlag = CMFLAG_CHECKED;
1019
            else if (plbi->dwFlags & LBIF_PARTCHECKED)
1020
                plbii->cmFlag = CMFLAG_PARTCHECKED;
1021
            else
1022
                plbii->cmFlag = CMFLAG_BLANK;
1023
            plbii->hIcon = (HICON)plbi->dwData;
1024
 
1025
            return LB_OKAY;
1026
        }
1027
        break;
1028
 
1029
        case LB_SETITEMDATA:
1030
        {
1031
            PLISTBOXITEM plbi;
1032
            PLISTBOXITEMINFO plbii;
1033
 
1034
            pData = (PLISTBOXDATA)pCtrl->userdata;
1035
            if (!(plbi = lstGetItem (pData, (int)wParam)))
1036
                return LB_ERR;
1037
 
1038
            if (!(dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON)) {
1039
                plbi->dwData = (DWORD)lParam;
1040
                return LB_OKAY;
1041
            }
1042
 
1043
            plbii = (PLISTBOXITEMINFO)lParam;
1044
            if (!plbii)
1045
                return LB_ERR;
1046
 
1047
            plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
1048
            switch (plbii->cmFlag) {
1049
                case CMFLAG_CHECKED:
1050
                    plbi->dwFlags |= LBIF_CHECKED;
1051
                break;
1052
                case CMFLAG_PARTCHECKED:
1053
                    plbi->dwFlags |= LBIF_PARTCHECKED;
1054
                break;
1055
            }
1056
 
1057
            if (dwStyle & LBS_USEICON)
1058
                plbi->dwData = (DWORD)plbii->hIcon;
1059
            else
1060
                plbi->dwData = 0;
1061
 
1062
            lstInvalidateItem (hwnd, pData, (int)wParam, TRUE);
1063
 
1064
            return LB_OKAY;
1065
        }
1066
        break;
1067
 
1068
        case LB_GETITEMADDDATA:
1069
        {
1070
            PLISTBOXITEM plbi;
1071
 
1072
            pData = (PLISTBOXDATA)pCtrl->userdata;
1073
            if (!(plbi = lstGetItem (pData, (int)wParam)))
1074
                return LB_ERR;
1075
 
1076
            return plbi->dwAddData;
1077
        }
1078
        break;
1079
 
1080
        case LB_SETITEMADDDATA:
1081
        {
1082
            PLISTBOXITEM plbi;
1083
 
1084
            pData = (PLISTBOXDATA)pCtrl->userdata;
1085
            if (!(plbi = lstGetItem (pData, (int)wParam)))
1086
                return LB_ERR;
1087
 
1088
            plbi->dwAddData = (DWORD)lParam;
1089
 
1090
            return LB_OKAY;
1091
        }
1092
        break;
1093
 
1094
        case LB_GETCHECKMARK:
1095
        {
1096
            PLISTBOXITEM plbi;
1097
 
1098
            if (!(dwStyle & LBS_CHECKBOX))
1099
                return LB_ERR;
1100
 
1101
            pData = (PLISTBOXDATA)pCtrl->userdata;
1102
            if (!(plbi = lstGetItem (pData, (int)wParam)))
1103
                return LB_ERR;
1104
 
1105
            if (plbi->dwFlags & LBIF_CHECKED)
1106
                return CMFLAG_CHECKED;
1107
 
1108
            if (plbi->dwFlags & LBIF_PARTCHECKED)
1109
                return CMFLAG_PARTCHECKED;
1110
 
1111
            return CMFLAG_BLANK;
1112
        }
1113
        break;
1114
 
1115
        case LB_SETCHECKMARK:
1116
        {
1117
            PLISTBOXITEM plbi;
1118
 
1119
            if (!(dwStyle & LBS_CHECKBOX))
1120
                return LB_ERR;
1121
 
1122
            pData = (PLISTBOXDATA)pCtrl->userdata;
1123
            if (!(plbi = lstGetItem (pData, (int)wParam)))
1124
                return LB_ERR;
1125
 
1126
            plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
1127
            switch (lParam) {
1128
                case CMFLAG_CHECKED:
1129
                    plbi->dwFlags |= LBIF_CHECKED;
1130
                break;
1131
                case CMFLAG_PARTCHECKED:
1132
                    plbi->dwFlags |= LBIF_PARTCHECKED;
1133
                break;
1134
            }
1135
 
1136
            lstInvalidateItem (hwnd, pData, (int)wParam, TRUE);
1137
 
1138
            return LB_OKAY;
1139
        }
1140
        break;
1141
 
1142
        case LB_GETSELITEMS:
1143
        {
1144
            int  nItem;
1145
            int  nSel = 0;
1146
            int  index = 0;
1147
            int* pInt;
1148
            PLISTBOXITEM plbi;
1149
 
1150
            nItem = (int)wParam;
1151
            pInt  = (int*)lParam;
1152
 
1153
            pData = (PLISTBOXDATA)pCtrl->userdata;
1154
            plbi = pData->head;
1155
            while (plbi) {
1156
 
1157
                if (plbi->dwFlags & LBIF_SELECTED) {
1158
                    if (pInt) {
1159
                        if (nSel < nItem)
1160
                            *(pInt + nSel) = index;
1161
                        else
1162
                            return nItem;
1163
                    }
1164
                    nSel ++;
1165
                }
1166
 
1167
                plbi = plbi->next;
1168
                index ++;
1169
            }
1170
 
1171
            return nSel;
1172
        }
1173
        break;
1174
 
1175
        case LB_GETSEL:
1176
        {
1177
            PLISTBOXITEM plbi;
1178
 
1179
            pData = (PLISTBOXDATA)pCtrl->userdata;
1180
            plbi = lstGetItem (pData, (int)wParam);
1181
            if (plbi)
1182
                return plbi->dwFlags & LBIF_SELECTED;
1183
            else
1184
                return LB_ERR;
1185
        }
1186
        break;
1187
 
1188
        case LB_SETSEL:
1189
        {
1190
            PLISTBOXITEM plbi;
1191
 
1192
            pData = (PLISTBOXDATA)pCtrl->userdata;
1193
            plbi = lstGetItem (pData, (int)lParam);
1194
            if (plbi) {
1195
                pData->dwFlags &= ~LBF_NOTHINGSELECTED;
1196
                if (wParam == -1)
1197
                    plbi->dwFlags ^= LBIF_SELECTED;
1198
                else if (wParam == 0)
1199
                    plbi->dwFlags &= ~LBIF_SELECTED;
1200
                else
1201
                    plbi->dwFlags |= LBIF_SELECTED;
1202
 
1203
                lstInvalidateItem (hwnd, pData, (int)lParam, FALSE);
1204
            }
1205
            else
1206
                return LB_ERR;
1207
        }
1208
        break;
1209
 
1210
        case LB_GETITEMHEIGHT:
1211
            pData = (PLISTBOXDATA)pCtrl->userdata;
1212
            return pData->itemHeight;
1213
        break;
1214
 
1215
        case LB_SETITEMHEIGHT:
1216
            pData = (PLISTBOXDATA)pCtrl->userdata;
1217
            if (pData->itemHeight != LOWORD (lParam)) {
1218
                RECT rcClient;
1219
 
1220
                pData->itemHeight = LOWORD (lParam);
1221
                GetClientRect (hwnd, &rcClient);
1222
                lstCalcParams (&rcClient, pData);
1223
 
1224
                lstSetVScrollInfo (hwnd, pData, TRUE);
1225
                InvalidateRect (hwnd, NULL, TRUE);
1226
            }
1227
        break;
1228
 
1229
        case WM_SETFOCUS:
1230
        {
1231
            pData = (PLISTBOXDATA)pCtrl->userdata;
1232
 
1233
            if (pData->dwFlags & LBF_FOCUS)
1234
                break;
1235
 
1236
            pData->dwFlags |= LBF_FOCUS;
1237
            InvalidateRect(hwnd, NULL, TRUE);
1238
 
1239
            NotifyParent (hwnd, pCtrl->id, LBN_SETFOCUS);
1240
        }
1241
        break;
1242
 
1243
        case WM_KILLFOCUS:
1244
        {
1245
            pData = (PLISTBOXDATA)pCtrl->userdata;
1246
 
1247
            pData->dwFlags &= ~LBF_FOCUS;
1248
            InvalidateRect(hwnd, NULL, TRUE);
1249
 
1250
            NotifyParent (hwnd, pCtrl->id, LBN_KILLFOCUS);
1251
        }
1252
        break;
1253
 
1254
        case WM_GETDLGCODE:
1255
            return DLGC_WANTARROWS | DLGC_WANTCHARS;
1256
 
1257
        case WM_GETTEXTLENGTH:
1258
        case WM_GETTEXT:
1259
        case WM_SETTEXT:
1260
            return -1;
1261
#if 0            
1262
        case WM_SETFONT:
1263
        break;
1264
 
1265
        case WM_GETFONT:
1266
        break;
1267
#endif        
1268
        case WM_NCCALCSIZE:
1269
        {
1270
                LPNCCALCSIZE_PARAMS lpnc;
1271
 
1272
                /* calculate client rect from passed window rect in rgrc[0]*/
1273
                lpnc = (LPNCCALCSIZE_PARAMS)lParam;
1274
                if(GetWindowLong(hwnd, GWL_STYLE) & WS_BORDER)
1275
                        InflateRect(&lpnc->rgrc[0], -2, -2);
1276
        }
1277
                break;
1278
 
1279
        case WM_NCPAINT:
1280
        {
1281
            RECT rc;
1282
 
1283
            hdc = wParam? (HDC)wParam: GetWindowDC (hwnd);
1284
            GetWindowRect(hwnd, &rc);
1285
 
1286
            if (dwStyle & WS_BORDER)
1287
                Draw3dInset(hdc, rc.left, rc.top,
1288
                        rc.right-rc.left, rc.bottom-rc.top);
1289
 
1290
            if (!wParam)
1291
                ReleaseDC (hwnd, hdc);
1292
        }
1293
            break;
1294
 
1295
        case WM_PAINT:
1296
        {
1297
            RECT rc;
1298
            PAINTSTRUCT ps;
1299
 
1300
            hdc = BeginPaint (hwnd,&ps);
1301
            pData = (PLISTBOXDATA)pCtrl->userdata;
1302
 
1303
            /*
1304
             * If this is the first paint and there's nothing
1305
             * selected, then auto select the topmost displayed item.
1306
             */
1307
            if (pData->dwFlags & LBF_NOTHINGSELECTED) {
1308
                    lstSelectItem (hwnd->style, pData, pData->itemTop);
1309
                    pData->dwFlags &= ~LBF_NOTHINGSELECTED;
1310
            }
1311
            GetClientRect (hwnd, &rc);
1312
            lstOnDrawSListBoxItems (hdc, dwStyle, pData, rc.right-rc.left);
1313
            lstDrawFocusRect (hdc, pData, &rc);
1314
 
1315
            EndPaint (hwnd, &ps);
1316
        }
1317
        break;
1318
 
1319
        case WM_LBUTTONDBLCLK:
1320
            if (dwStyle & LBS_NOTIFY)
1321
                NotifyParent (hwnd, pCtrl->id, LBN_DBLCLK);
1322
        break;
1323
 
1324
        case WM_LBUTTONDOWN:
1325
        {
1326
            int oldSel, mouseX, mouseY, hit;
1327
            RECT rcInv;
1328
 
1329
            pData = (PLISTBOXDATA)pCtrl->userdata;
1330
            if (pData->itemCount == 0)
1331
                break;
1332
 
1333
            mouseX = LOWORD (lParam);
1334
            mouseY = HIWORD (lParam);
1335
            hit = mouseY / pData->itemHeight;
1336
            hit += pData->itemTop;
1337
 
1338
            if (hit >= pData->itemCount)
1339
                break;
1340
 
1341
            GetClientRect (hwnd, &rcInv);
1342
            oldSel = lstSelectItem (dwStyle, pData, hit);
1343
            if ((dwStyle & LBS_NOTIFY) && (oldSel != hit))
1344
                NotifyParent (hwnd, pCtrl->id, LBN_SELCHANGE);
1345
            if (oldSel >= 0) {
1346
                if (oldSel >= pData->itemTop
1347
                        && (oldSel <= pData->itemTop + pData->itemVisibles)) {
1348
                    lstGetItemsRect (pData, oldSel, oldSel, &rcInv);
1349
                    InvalidateRect (hwnd, &rcInv, TRUE);
1350
                }
1351
            }
1352
 
1353
            lstGetItemsRect (pData, hit, hit, &rcInv);
1354
            InvalidateRect (hwnd, &rcInv, TRUE);
1355
 
1356
            if (pData->itemHilighted != hit)
1357
            {
1358
                hdc = GetDC(hwnd); /* hdc = GetClientDC (hwnd); */
1359
 
1360
                lstDrawFocusRect (hdc, pData, &rcInv);
1361
                ReleaseDC (hwnd,hdc);
1362
            }
1363
            pData->itemHilighted = hit;
1364
 
1365
            if (dwStyle & LBS_CHECKBOX) {
1366
                if (mouseX > 0 && mouseX < LST_WIDTH_CHECKMARK) {
1367
                    NotifyParent (hwnd, pCtrl->id, LBN_CLICKCHECKMARK);
1368
 
1369
                    if (dwStyle & LBS_AUTOCHECK) {
1370
                        PLISTBOXITEM plbi;
1371
 
1372
                        plbi = lstGetItem (pData, hit);
1373
 
1374
                        switch (plbi->dwFlags & LBIF_CHECKMARKMASK) {
1375
                        case LBIF_CHECKED:
1376
                            plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
1377
                            break;
1378
                        default:
1379
                            plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
1380
                            plbi->dwFlags |= LBIF_CHECKED;
1381
                            break;
1382
                        }
1383
 
1384
                        lstInvalidateItem (hwnd, pData, hit, TRUE);
1385
                    }
1386
                }
1387
            }
1388
 
1389
            lstSetVScrollInfo (hwnd, pData, TRUE);
1390
        }
1391
        break;
1392
 
1393
        case WM_LBUTTONUP:
1394
        break;
1395
 
1396
        case WM_MOUSEMOVE:
1397
        break;
1398
 
1399
        case WM_KEYDOWN:
1400
        {
1401
            int oldSel, newSel, newTop;
1402
            RECT rcInv;
1403
 
1404
            pData = (PLISTBOXDATA)pCtrl->userdata;
1405
            newTop = pData->itemTop;
1406
            newSel = pData->itemHilighted;
1407
            switch (LOWORD (wParam))
1408
            {
1409
                case VK_HOME:   /* SCANCODE_HOME: */
1410
                    newSel = 0;
1411
                    newTop = 0;
1412
                break;
1413
 
1414
                case VK_END:    /* SCANCODE_END: */
1415
                    newSel = pData->itemCount - 1;
1416
                    if (pData->itemCount > pData->itemVisibles)
1417
                        newTop = pData->itemCount - pData->itemVisibles;
1418
                    else
1419
                        newTop = 0;
1420
                break;
1421
 
1422
                case VK_DOWN:   /* SCANCODE_CURSORBLOCKDOWN: */
1423
                    newSel ++;
1424
                    if (newSel >= pData->itemCount)
1425
                        return 0;
1426
                    if (newSel > ITEM_BOTTOM (pData))
1427
                        newTop ++;
1428
                break;
1429
 
1430
                case VK_UP:     /* SCANCODE_CURSORBLOCKUP: */
1431
                    newSel --;
1432
                    if (newSel < 0)
1433
                        return 0;
1434
                    if (newSel < pData->itemTop)
1435
                        newTop --;
1436
                break;
1437
 
1438
                case VK_NEXT:   /* SCANCODE_PAGEDOWN: */
1439
                    newSel += pData->itemVisibles;
1440
                    if (newSel >= pData->itemCount)
1441
                        newSel = pData->itemCount - 1;
1442
 
1443
                    if (pData->itemCount - newSel >= pData->itemVisibles)
1444
                        newTop = newSel;
1445
                    else
1446
                        newTop = max (pData->itemCount-pData->itemVisibles, 0);
1447
                break;
1448
 
1449
                case VK_PRIOR:  /* SCANCODE_PAGEUP: */
1450
                    newSel -= pData->itemVisibles;
1451
                    if (newSel < 0)
1452
                        newSel = 0;
1453
 
1454
                    newTop -= pData->itemVisibles;
1455
                    if (newTop < 0)
1456
                        newTop = 0;
1457
                break;
1458
 
1459
                default:
1460
                return 0;
1461
            }
1462
 
1463
            GetClientRect (hwnd, &rcInv);
1464
            if (pData->itemHilighted != newSel) {
1465
                if (pData->itemTop != newTop) {
1466
                    pData->itemTop = newTop;
1467
                    pData->itemHilighted = newSel;
1468
                    if (!(dwStyle & LBS_MULTIPLESEL)) {
1469
                        oldSel = lstSelectItem (dwStyle, pData, newSel);
1470
                        if ((dwStyle & LBS_NOTIFY) && (oldSel != newSel))
1471
                            NotifyParent (hwnd, pCtrl->id, LBN_SELCHANGE);
1472
                    }
1473
                    InvalidateRect (hwnd, NULL, TRUE);
1474
                }
1475
                else {
1476
                    if (!(dwStyle & LBS_MULTIPLESEL)) {
1477
                        oldSel = lstSelectItem (dwStyle, pData, newSel);
1478
                        if ((dwStyle & LBS_NOTIFY) && (oldSel != newSel))
1479
                            NotifyParent (hwnd, pCtrl->id, LBN_SELCHANGE);
1480
                        if (oldSel >= 0) {
1481
                            if (oldSel >= pData->itemTop
1482
                                    && oldSel <= (ITEM_BOTTOM (pData) + 1)) {
1483
                                lstGetItemsRect (pData, oldSel, oldSel, &rcInv);
1484
                                InvalidateRect (hwnd, &rcInv, TRUE);
1485
                            }
1486
                        }
1487
 
1488
                        if (newSel < newTop) {
1489
                            pData->itemHilighted = newSel;
1490
                            break;
1491
                        }
1492
 
1493
                        lstGetItemsRect (pData, pData->itemHilighted,
1494
                                                pData->itemHilighted, &rcInv);
1495
 
1496
                        hdc = GetDC(hwnd); /* hdc = GetClientDC (hwnd); */
1497
 
1498
                        lstDrawFocusRect (hdc, pData, &rcInv);
1499
                        ReleaseDC (hwnd,hdc);
1500
 
1501
                        pData->itemHilighted = newSel;
1502
                        lstGetItemsRect (pData, newSel, newSel, &rcInv);
1503
                        InvalidateRect (hwnd, &rcInv, TRUE);
1504
                    }
1505
                    else
1506
                    {
1507
                        hdc = GetDC(hwnd); /* hdc = GetClientDC (hwnd); */
1508
 
1509
                        lstDrawFocusRect (hdc, pData, &rcInv);
1510
                        pData->itemHilighted = newSel;
1511
                        GetClientRect (hwnd, &rcInv);
1512
                        lstDrawFocusRect (hdc, pData, &rcInv);
1513
                        ReleaseDC (hwnd,hdc);
1514
                    }
1515
                }
1516
                lstSetVScrollInfo (hwnd, pData, TRUE);
1517
            }
1518
        }
1519
        break;
1520
 
1521
        case WM_CHAR:
1522
        {
1523
            char head [2];
1524
            int index;
1525
            int newTop;
1526
 
1527
            head [0] = (char) (wParam);
1528
            head [1] = '\0';
1529
 
1530
            pData = (PLISTBOXDATA)pCtrl->userdata;
1531
 
1532
            if (head[0] == ' ') {
1533
                if (dwStyle & LBS_MULTIPLESEL) {
1534
                    RECT rcInv;
1535
 
1536
                    GetClientRect (hwnd, &rcInv);
1537
                    lstSelectItem (dwStyle, pData, pData->itemHilighted);
1538
                    lstGetItemsRect (pData,
1539
                            pData->itemHilighted,
1540
                            pData->itemHilighted,
1541
                            &rcInv);
1542
                    InvalidateRect (hwnd, &rcInv, TRUE);
1543
                }
1544
                else if (dwStyle & LBS_CHECKBOX) {
1545
                    NotifyParent (hwnd, pCtrl->id, LBN_CLICKCHECKMARK);
1546
 
1547
                    if (dwStyle & LBS_AUTOCHECK) {
1548
                        PLISTBOXITEM plbi;
1549
 
1550
                        plbi = lstGetItem (pData, pData->itemHilighted);
1551
 
1552
                        switch (plbi->dwFlags & LBIF_CHECKMARKMASK) {
1553
                        case LBIF_CHECKED:
1554
                            plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
1555
                            break;
1556
                        default:
1557
                            plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
1558
                            plbi->dwFlags |= LBIF_CHECKED;
1559
                            break;
1560
                        }
1561
 
1562
                        lstInvalidateItem (hwnd, pData,
1563
                                pData->itemHilighted, TRUE);
1564
                    }
1565
                }
1566
                break;
1567
            }
1568
 
1569
            index = lstFindItem (pData, pData->itemHilighted + 1, head, FALSE);
1570
            if (index < 0) {
1571
                index = lstFindItem (pData, 0, head, FALSE);
1572
            }
1573
 
1574
            if (index >= 0) {
1575
                if (pData->itemCount - index >= pData->itemVisibles)
1576
                    newTop = index;
1577
                else
1578
                    newTop = max (pData->itemCount - pData->itemVisibles, 0);
1579
 
1580
                pData->itemTop = newTop;
1581
                pData->itemHilighted = index;
1582
                if (!(dwStyle & LBS_MULTIPLESEL))
1583
                    lstSelectItem (dwStyle, pData, index);
1584
                InvalidateRect (hwnd, NULL, TRUE);
1585
 
1586
                lstSetVScrollInfo (hwnd, pData, TRUE);
1587
            }
1588
        }
1589
        break;
1590
 
1591
        case WM_VSCROLL:
1592
        {
1593
            int newTop;
1594
            int scrollHeight = 0;
1595
 
1596
            pData = (PLISTBOXDATA)pCtrl->userdata;
1597
            newTop = pData->itemTop;
1598
            switch(wParam)
1599
            {
1600
                case SB_LINEDOWN:
1601
 
1602
#if 0   /* test itemVisibles */
1603
                    printf("itemVisibles:%d\n",pData->itemVisibles);
1604
                    printf("SB_LINEDOWN:(%d:%d)\n",
1605
                        ITEM_BOTTOM (pData),(pData->itemCount - 1 ));
1606
#endif
1607
                    if (ITEM_BOTTOM (pData) < (pData->itemCount - 1 ))
1608
                    {
1609
                        newTop ++;
1610
                        scrollHeight = -pData->itemHeight;      /* for ScrollWindow() */
1611
                    }
1612
                break;
1613
 
1614
                case SB_LINEUP:
1615
                    if (pData->itemTop > 0)
1616
                    {
1617
                        newTop --;
1618
                        scrollHeight = pData->itemHeight;
1619
                    }
1620
                break;
1621
 
1622
                case SB_PAGEDOWN:
1623
                    if ((pData->itemTop + (pData->itemVisibles << 1)) <=
1624
                            pData->itemCount)
1625
                        newTop += pData->itemVisibles;
1626
                    else
1627
                        newTop = pData->itemCount - pData->itemVisibles;
1628
 
1629
                    if (newTop < 0)
1630
                        return 0;
1631
 
1632
                    scrollHeight = -(newTop - pData->itemTop)
1633
                                    *pData->itemHeight;
1634
                break;
1635
 
1636
                case SB_PAGEUP:
1637
                    if (pData->itemTop >= pData->itemVisibles)
1638
                        newTop -= pData->itemVisibles;
1639
                    else
1640
                        newTop = 0;
1641
 
1642
                    scrollHeight = (pData->itemTop - newTop)*pData->itemHeight;
1643
                break;
1644
 
1645
                case SB_THUMBTRACK:
1646
                    newTop = (int)lParam;
1647
                    scrollHeight = (pData->itemTop - newTop)*pData->itemHeight;
1648
                break;
1649
            }
1650
 
1651
            if (scrollHeight)
1652
            {
1653
                pData->itemTop = newTop;
1654
#if 0   /* !!: fix: no scroll */
1655
                ScrollWindow (hwnd, 0, scrollHeight, NULL, NULL);
1656
#endif
1657
                SendMessage (hwnd, WM_PAINT, 0, 0);
1658
 
1659
                lstSetVScrollInfo (hwnd, pData, TRUE);
1660
 
1661
                return 0;
1662
            }
1663
        }
1664
        break;
1665
 
1666
        case WM_HSCROLL:
1667
            pData = (PLISTBOXDATA)pCtrl->userdata;
1668
            switch (wParam)
1669
            {
1670
                case SB_LINERIGHT:
1671
                break;
1672
 
1673
                case SB_LINELEFT:
1674
                break;
1675
 
1676
                case SB_PAGELEFT:
1677
                break;
1678
 
1679
                case SB_PAGERIGHT:
1680
                break;
1681
            }
1682
        break;
1683
 
1684
        default:
1685
                return DefWindowProc (hwnd, message, wParam, lParam);
1686
    }
1687
    return 0;
1688
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.