]> granicus.if.org Git - nethack/commitdiff
FIXES:
authornethack.allison <nethack.allison>
Fri, 25 Jan 2002 07:19:21 +0000 (07:19 +0000)
committernethack.allison <nethack.allison>
Fri, 25 Jan 2002 07:19:21 +0000 (07:19 +0000)
- added counting to the menu window. I changed the way it works in the TTY
port though  ("you hear the rumble of distant thunder..." :)  The count
applies to the currently selected item instead of being aplied to the item
to be selected  (in other words a12 instead of 12a). It works better this
way in the graphical port since there is a notion of current menu item.
 I also notes that the count is ignored for PICK_ONE menu - is this by
design?

- somebode mention that text is not scrollable by default - this is fixed.

- fixed player selection dialog to use initXXXX options

-----------------------
B1028 [reported] win32: popup window is too short
The text in the popup window's top line "What do you want to
call the ..." is cut off. Could the window be bigger, so you
can read the entire line?

Fixed.

---------------------
B1027 [reported] win32: select via traditional class char
In a shop (and perhaps elsewhere), I can autoselect a class of
items to drop: a for all types, b for coins, c for weapons, ...,
A for every item, B for blessed items, ... I like the new
possibilities, but I would like to be able to use the old way of
using ! for potions, ) for weapons, etc., as well.

Fixed.

---------------------
B1026 [reported] win32: setting multiple options

I want to set packorder and pickup_types. The first comes up
first, and I type in the order. Then comes the second, without
any hint what is asked of me. A little explanation here would
be appropriate, like "pick up what things automatically?" or
somesuch. When more than one option is set where extra input
is required, some explanation is useful.

Looking into. Apparently something  end_menu() call is ignored by nethackw.

---------------------
B1025 [reported] win32: menu navigation
I press O. Now, when I press "a" to turn on "autodig", not only
is the mark set at "a", but there also appears a dotted
rectangle around option "A" (capitalized). Shouldn't this
rectangle also appear at "a"? Pressing "a" repeatedly toggles
the checkmark, but the rectangle switches between "A" and "a".
My CAPS LOCK is not set. The same goes for B, C, D, ... N,
by the way. Pressing "A" works the other way around: the first
press checks "A" and "rectangles" "a", the next unchecks "A"
and rectangles "A" as well.

Fixed.

---------------------
B1024 [reported] win32: no text in final window
After I clicked away the last screen with information
(challenges, I believe it was), I got an empty text screen, as
big as my screen, without any content. It looked like the text
screens that appear on the right, only it was larger and had
only a large OK button over the full width of the window, and
no cancel button. Why this window?

Fixed. The program did not set window text for RIP window.

---------------------
B1010 [known issue] win32: cosmetic
When I get my list of spells, the columns aren't properly
aligned: if the spell name is longer, the rest of the line
shifts right.

Fixed. Fixed-pitch font is used for menu window.

---------------------
B1004 [reported] win32: numeric keyboard Del/.-key
The Del/.-key on my numeric keyboard doesn't make me rest a turn

Fixed. Added rest on Del.

---------------------
B1003 [reported] win32: focus
When the window has the focus, the window bar isn't highlighted.

This is by design. Menu and text widnows are popup and the main
window is disabled when they are up.

14 files changed:
Files
sys/winnt/nhsetup.bat
win/win32/mhdlg.c
win/win32/mhfont.c
win/win32/mhmain.c
win/win32/mhmenu.c
win/win32/mhrip.c
win/win32/mhtext.c
win/win32/mnselcnt.uu [new file with mode: 0644]
win/win32/mswproc.c
win/win32/resource.h
win/win32/winMS.h
win/win32/winhack.c
win/win32/winhack.rc

diff --git a/Files b/Files
index a71696d712afb5936d29d9ed9e87d3a02beb0e77..af9663ce07513702e46e052e353012f86313b9bc 100644 (file)
--- a/Files
+++ b/Files
@@ -251,10 +251,11 @@ mhcmd.c         mhcmd.h         mhdlg.c         mhdlg.h         mhfont.c
 mhfont.h        mhinput.c       mhinput.h       mhmain.c        mhmain.h
 mhmap.c         mhmap.h         mhmenu.c        mhmenu.h        mhmsg.h
 mhmsgwnd.c      mhmsgwnd.h      mhrip.c         mhrip.h         mhstatus.c
-mhstatus.h      mhtext.c        mhtext.h        mnsel.uu        mnunsel.uu
-mswproc.c       nethack.dsw     nethackw.dsp    petmark.uu      recover.dsp
-resource.h      tile2bmp.c      tile2bmp.dsp    tilemap.dsp     tiles.dsp
-tiles.mak       winhack.c       winhack.h       winhack.rc      winMS.h
+mhstatus.h      mhtext.c        mhtext.h        mnsel.uu        mnselcnt.uu
+mnunsel.uu      mswproc.c       nethack.dsw     nethackw.dsp    petmark.uu
+recover.dsp     resource.h      tile2bmp.c      tile2bmp.dsp    tilemap.dsp
+tiles.dsp       tiles.mak       winhack.c       winhack.h       winhack.rc
+winMS.h
 
 
 
index 20d5a2d22300376c7a916211cd060bff4221edbc..e4cfb7a738deb3af60363f115c20a363d4293505 100755 (executable)
@@ -1,4 +1,4 @@
-@REM  SCCS Id: @(#)nhsetup.bat      2002/01/21
+@REM  SCCS Id: @(#)nhsetup.bat      2002/01/25
 @REM  Copyright (c) NetHack PC Development Team 1993, 1996, 2002
 @REM  NetHack may be freely redistributed.  See license for details. 
 @REM  Win32 setup batch file, see Install.nt for details
@@ -96,6 +96,18 @@ copy .\mnunsel.bmp ..\..\win\win32
 :hasmnuns2
 if NOT exist ..\..\win\win32\mnunsel.bmp set err_nouu=Y
 
+if exist ..\..\win\win32\mnselcnt.bmp goto hasmnselcnt2
+if exist .\mnselcnt.bmp goto hasmnselcnt1
+if exist ..\..\win\win32\mnselcnt.uu uudecode ..\..\win\win32\mnselcnt.uu >nul
+if exist .\mnselcnt.bmp goto hasmnselcnt1
+echo Error - No UUDECODE utility to decode ..\..\win\win32\mnselcnt.uu
+goto hasmnselcnt2
+:hasmnselcnt1
+echo copy .\mnselcnt.bmp ..\..\win\win32
+copy .\mnselcnt.bmp ..\..\win\win32
+:hasmnselcnt2
+if NOT exist ..\..\win\win32\mnselcnt.bmp set err_nouu=Y
+
 if exist ..\..\win\win32\petmark.bmp goto haspm2
 if exist .\petmark.bmp goto haspm1
 if exist ..\..\win\win32\petmark.uu uudecode ..\..\win\win32\petmark.uu >nul
index f6a5aaa86c8bcfc1cf0a0395f400c826f9efa8c5..07022570d16f98de4813a402a4c7e87ac525e3a0 100644 (file)
@@ -50,9 +50,11 @@ int mswin_getlin_window (
 BOOL CALLBACK GetlinDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
        struct getlin_data* data;
-       RECT   main_rt, dlg_rt;
+       RECT   main_rt, text_rt, dlg_rt, edit_rt;
        SIZE   dlg_sz;
        TCHAR  wbuf[BUFSZ];
+       HDC hdc;
+       HWND   control;
 
        switch (message) 
        {
@@ -61,12 +63,18 @@ BOOL CALLBACK GetlinDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara
                SetWindowText(hWnd, NH_A2W(data->question, wbuf, sizeof(wbuf)));
                SetWindowLong(hWnd, GWL_USERDATA, lParam);
 
+               /* get title text width */
+               SetRect(&text_rt, 0, 0, 100, 50);
+               hdc = GetWindowDC(hWnd);
+               DrawText(hdc, wbuf, _tcslen(wbuf), &text_rt, 
+                            DT_CALCRECT | DT_SINGLELINE | DT_NOPREFIX | DT_LEFT | DT_VCENTER );
+               ReleaseDC(hWnd, hdc);
+
                /* center dialog in the main window */
-               GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
                GetWindowRect(hWnd, &dlg_rt);
-               dlg_sz.cx = dlg_rt.right - dlg_rt.left;
+               GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
+               dlg_sz.cx = max(dlg_rt.right-dlg_rt.left, text_rt.right-text_rt.left );
                dlg_sz.cy = dlg_rt.bottom - dlg_rt.top;
-
                dlg_rt.left = (main_rt.left+main_rt.right-dlg_sz.cx)/2;
                dlg_rt.right = dlg_rt.left + dlg_sz.cx;
                dlg_rt.top = (main_rt.top+main_rt.bottom-dlg_sz.cy)/2;
@@ -78,6 +86,36 @@ BOOL CALLBACK GetlinDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara
                                        dlg_sz.cy,
                                        TRUE );
 
+               /* change layout of controls */
+               GetClientRect(hWnd, &dlg_rt);
+
+               control = GetDlgItem(hWnd, IDC_GETLIN_EDIT);
+               GetWindowRect(control, &edit_rt);
+               MoveWindow( control,
+                                       0,
+                                       0,
+                                       dlg_rt.right - dlg_rt.left,
+                                       edit_rt.bottom - edit_rt.top,
+                                       TRUE );
+
+               control = GetDlgItem(hWnd, IDOK);
+               GetWindowRect(control, &text_rt);
+               MoveWindow( control,
+                                       0,
+                                       edit_rt.bottom - edit_rt.top,
+                                       (dlg_rt.right-dlg_rt.left)/2,
+                                       text_rt.bottom - text_rt.top,
+                                       TRUE );
+
+               control = GetDlgItem(hWnd, IDCANCEL);
+               GetWindowRect(control, &text_rt);
+               MoveWindow( control,
+                                       (dlg_rt.right-dlg_rt.left)/2,
+                                       edit_rt.bottom - edit_rt.top,
+                                       (dlg_rt.right-dlg_rt.left)/2,
+                                       text_rt.bottom - text_rt.top,
+                                       TRUE );
+
                /* set focus to the edit control */
                SetFocus(GetDlgItem(hWnd, IDC_GETLIN_EDIT));
 
@@ -401,20 +439,44 @@ void plselInitDialog(HWND hWnd)
        plselAdjustLists(hWnd, -1);
 
        /* intialize roles list */
-       CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_CHECKED);
-       EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), FALSE);
+       if( flags.initrole<0 ) {
+               CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_CHECKED);
+               EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), FALSE);
+       } else {
+               CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_UNCHECKED);
+               EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), TRUE);
+               SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_LIST, CB_SETCURSEL, (WPARAM)flags.initrole, 0);
+       }
 
        /* intialize races list */
-       CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_CHECKED);
-       EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), FALSE);
+       if( flags.initrace<0 || !validrace(flags.initrole, flags.initrace) ) {
+               CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_CHECKED);
+               EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), FALSE);
+       } else {
+               CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_UNCHECKED);
+               EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), TRUE);
+               SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_LIST, CB_SETCURSEL, (WPARAM)flags.initrace, 0);
+       }
 
        /* intialize genders list */
-       CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_CHECKED);
-       EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), FALSE);
+       if( flags.initgend<0 || !validgend(flags.initrole, flags.initrace, flags.initgend)) {
+               CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_CHECKED);
+               EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), FALSE);
+       } else {
+               CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_UNCHECKED);
+               EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), TRUE);
+               SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_LIST, CB_SETCURSEL, (WPARAM)flags.initgend, 0);
+       }
 
        /* intialize alignments list */
-       CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_CHECKED);
-       EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), FALSE);
+       if( flags.initalign<0 || !validalign(flags.initrole, flags.initrace, flags.initalign) ) {
+               CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_CHECKED);
+               EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), FALSE);
+       } else {
+               CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_UNCHECKED);
+               EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), TRUE);
+               SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_LIST, CB_SETCURSEL, (WPARAM)flags.initalign, 0);
+       }
 }
 
 /* adjust role/race/alignment/gender list - filter out
@@ -424,10 +486,8 @@ void plselInitDialog(HWND hWnd)
 */
 void  plselAdjustLists(HWND hWnd, int changed_sel)
 {
-       HWND control_role;
-       HWND control_race;
-       HWND control_gender;
-       HWND control_align;
+       HWND control_role, control_race, control_gender, control_align;
+       int  initrole, initrace, initgend, initalign;
        int i;
        int ind;
        int valid_opt;
@@ -441,16 +501,16 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
 
        /* get current selections */    
        ind = SendMessage(control_role, CB_GETCURSEL, 0, 0);
-       flags.initrole = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_role, CB_GETITEMDATA, ind, 0);
+       initrole = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_role, CB_GETITEMDATA, ind, 0);
 
        ind = SendMessage(control_race, CB_GETCURSEL, 0, 0);
-       flags.initrace = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_race, CB_GETITEMDATA, ind, 0);
+       initrace = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_race, CB_GETITEMDATA, ind, 0);
 
        ind = SendMessage(control_gender, CB_GETCURSEL, 0, 0);
-       flags.initgend = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_gender, CB_GETITEMDATA, ind, 0);
+       initgend = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_gender, CB_GETITEMDATA, ind, 0);
 
        ind = SendMessage(control_align, CB_GETCURSEL, 0, 0);
-       flags.initalign = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_align, CB_GETITEMDATA, ind, 0);
+       initalign = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_align, CB_GETITEMDATA, ind, 0);
 
        /* intialize roles list */
        if( changed_sel==-1 ) {
@@ -459,11 +519,14 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
                /* reset content and populate the list */
                SendMessage(control_role, CB_RESETCONTENT, 0, 0); 
                for (i = 0; roles[i].name.m; i++) {
-                       if (ok_role(i, flags.initrace, flags.initgend,
-                                                       flags.initalign)) {
-                               ind = SendMessage(control_role, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(roles[i].name.m, wbuf, sizeof(wbuf)) ); 
+                       if (ok_role(i, initrace, initgend, initalign)) {
+                           if (initgend>=0 && flags.female && roles[i].name.f)
+                                       ind = SendMessage(control_role, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(roles[i].name.f, wbuf, sizeof(wbuf)) );
+                               else 
+                                       ind = SendMessage(control_role, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(roles[i].name.m, wbuf, sizeof(wbuf)) );
+
                                SendMessage(control_role, CB_SETITEMDATA, (WPARAM)ind, (LPARAM)i );
-                               if( i==flags.initrole ) { 
+                               if( i==initrole ) { 
                                        SendMessage(control_role, CB_SETCURSEL, (WPARAM)ind, (LPARAM)0 );
                                        valid_opt = 1;
                                }
@@ -473,10 +536,10 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
                /* set selection to the previously selected role
                   if it is still valid */
                if( !valid_opt ) {
-                       flags.initrole = ROLE_NONE;
-                       flags.initrace = ROLE_NONE;
-                       flags.initgend = ROLE_NONE;
-                       flags.initalign = ROLE_NONE;
+                       initrole = ROLE_NONE;
+                       initrace = ROLE_NONE;
+                       initgend = ROLE_NONE;
+                       initalign = ROLE_NONE;
                        SendMessage(control_role, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0 );
                }
 
@@ -491,10 +554,10 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
                /* reset content and populate the list */
                SendMessage(control_race, CB_RESETCONTENT, 0, 0); 
                for (i = 0; races[i].noun; i++)
-                       if (ok_race(flags.initrole, i, ROLE_NONE, ROLE_NONE)) {
+                       if (ok_race(initrole, i, ROLE_NONE, ROLE_NONE)) {
                                ind = SendMessage(control_race, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(races[i].noun, wbuf, sizeof(wbuf)) ); 
                                SendMessage(control_race, CB_SETITEMDATA, (WPARAM)ind, (LPARAM)i ); 
-                               if( i==flags.initrace ) { 
+                               if( i==initrace ) { 
                                        SendMessage(control_race, CB_SETCURSEL, (WPARAM)ind, (LPARAM)0 );
                                        valid_opt = 1;
                                }
@@ -503,9 +566,9 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
                /* set selection to the previously selected race
                   if it is still valid */
                if( !valid_opt ) {
-                       flags.initrace = ROLE_NONE;
-                       flags.initgend = ROLE_NONE;
-                       flags.initalign = ROLE_NONE;
+                       initrace = ROLE_NONE;
+                       initgend = ROLE_NONE;
+                       initalign = ROLE_NONE;
                        SendMessage(control_race, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0 );
                }
 
@@ -520,11 +583,10 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
                /* reset content and populate the list */
                SendMessage(control_gender, CB_RESETCONTENT, 0, 0); 
                for (i = 0; i < ROLE_GENDERS; i++)
-                       if (ok_gend(flags.initrole, flags.initrace, i,
-                                               ROLE_NONE)) {
+                       if (ok_gend(initrole, initrace, i, ROLE_NONE)) {
                                ind = SendMessage(control_gender, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(genders[i].adj, wbuf, sizeof(wbuf)) ); 
                                SendMessage(control_gender, CB_SETITEMDATA, (WPARAM)ind, (LPARAM)i ); 
-                               if( i==flags.initgend ) { 
+                               if( i==initgend ) { 
                                        SendMessage(control_gender, CB_SETCURSEL, (WPARAM)ind, (LPARAM)0 );
                                }
                        }
@@ -532,8 +594,8 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
                /* set selection to the previously selected gender
                   if it is still valid */
                if( !valid_opt ) {
-                       flags.initgend = ROLE_NONE;
-                       flags.initalign = ROLE_NONE;
+                       initgend = ROLE_NONE;
+                       initalign = ROLE_NONE;
                        SendMessage(control_gender, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0 );
                }
 
@@ -548,11 +610,10 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
                /* reset content and populate the list */
                SendMessage(control_align, CB_RESETCONTENT, 0, 0); 
                for (i = 0; i < ROLE_ALIGNS; i++)
-                       if (ok_align(flags.initrole, flags.initrace,
-                                                       flags.initgend, i)) {
+                       if (ok_align(initrole, initrace, initgend, i)) {
                                ind = SendMessage(control_align, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(aligns[i].adj, wbuf, sizeof(wbuf)) ); 
                                SendMessage(control_align, CB_SETITEMDATA, (WPARAM)ind, (LPARAM)i ); 
-                               if( i==flags.initalign ) { 
+                               if( i==initalign ) { 
                                        SendMessage(control_align, CB_SETCURSEL, (WPARAM)ind, (LPARAM)0 );
                                        valid_opt = 1;
                                }
@@ -561,7 +622,7 @@ void  plselAdjustLists(HWND hWnd, int changed_sel)
                /* set selection to the previously selected alignment
                   if it is still valid */
                if( !valid_opt ) {
-                       flags.initalign = ROLE_NONE;
+                       initalign = ROLE_NONE;
                        SendMessage(control_align, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0 );
                }
        }
@@ -604,8 +665,7 @@ int plselFinalSelection(HWND hWnd, int* selection)
 
        /* check the role */
        if( flags.initrole==ROLE_RANDOM ) {
-               flags.initrole = pick_role(flags.initrace, flags.initgend,
-                                       flags.initalign, PICK_RANDOM);
+               flags.initrole = pick_role(flags.initrace, flags.initgend, flags.initalign, PICK_RANDOM);
                if (flags.initrole < 0) {
                        MessageBox(hWnd, TEXT("Incompatible role!"), TEXT("STOP"), MB_OK);
                        return FALSE;
@@ -617,8 +677,7 @@ int plselFinalSelection(HWND hWnd, int* selection)
        if (flags.initrace==ROLE_RANDOM || !validrace(flags.initrole, flags.initrace)) {
                /* pre-selected race not valid */
                if (flags.initrace == ROLE_RANDOM) {
-                       flags.initrace = pick_race(flags.initrole, flags.initgend,
-                                                       flags.initalign, PICK_RANDOM);
+                       flags.initrace = pick_race(flags.initrole, flags.initgend, flags.initalign, PICK_RANDOM);
                }
                
                if (flags.initrace < 0) {
@@ -634,8 +693,7 @@ int plselFinalSelection(HWND hWnd, int* selection)
                !validgend(flags.initrole, flags.initrace, flags.initgend)) {
            /* pre-selected gender not valid */
            if (flags.initgend == ROLE_RANDOM) {
-                       flags.initgend = pick_gend(flags.initrole, flags.initrace,
-                                                       flags.initalign, PICK_RANDOM);
+                       flags.initgend = pick_gend(flags.initrole, flags.initrace, flags.initalign, PICK_RANDOM);
                }
                
                if (flags.initgend < 0) {
@@ -650,8 +708,7 @@ int plselFinalSelection(HWND hWnd, int* selection)
                !validalign(flags.initrole, flags.initrace,     flags.initalign)) {
                /* pre-selected alignment not valid */
                if (flags.initalign == ROLE_RANDOM) {
-                       flags.initalign = pick_align(flags.initrole, flags.initrace,
-                                                       flags.initgend, PICK_RANDOM);
+                       flags.initalign = pick_align(flags.initrole, flags.initrace, flags.initgend, PICK_RANDOM);
                } else {
                        MessageBox(hWnd, TEXT("Incompatible alignment!"), TEXT("STOP"), MB_OK);
                        return FALSE;
@@ -659,4 +716,4 @@ int plselFinalSelection(HWND hWnd, int* selection)
        }
 
        return TRUE;
-}
+}
\ No newline at end of file
index 0ca69b36a63dc300e147da8f9beedce6c4fca167..0755e64443d7935406621471fdc4219dca68d781 100644 (file)
@@ -67,7 +67,7 @@ HGDIOBJ mswin_create_font(int win_type, int attr, HDC hdc)
                lgfnt.lfOutPrecision    =       OUT_DEFAULT_PRECIS;  // output precision
                lgfnt.lfClipPrecision   =       CLIP_DEFAULT_PRECIS; // clipping precision
                lgfnt.lfQuality                 =       DEFAULT_QUALITY;     // output quality
-               lgfnt.lfPitchAndFamily  =       VARIABLE_PITCH;          // pitch and family
+               lgfnt.lfPitchAndFamily  =       FIXED_PITCH;             // pitch and family
                /* lgfnt.lfFaceName */
                break;
 
index d76ef74e61b16f40b13c7f36e68eade3c8d6be63..fd8a12726a24315f4f748da38cec4f01ddb8d183 100644 (file)
@@ -142,6 +142,10 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar
             case VK_NEXT: 
                                NHEVENT_KBD('3')
                 return 0; 
+
+            case VK_DELETE: 
+                               NHEVENT_KBD('.')
+                return 0; 
             }
                        return 1;
                } break;
@@ -165,8 +169,8 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar
                case WM_SETFOCUS:
                        /* if there is a menu window out there -
                           transfer input focus to it */
-                       if( IsWindow( GetNHApp()->hMenuWnd ) ) {
-                               SetFocus( GetNHApp()->hMenuWnd );
+                       if( IsWindow( GetNHApp()->hPopupWnd ) ) {
+                               SetFocus( GetNHApp()->hPopupWnd );
                        }
                        break;
 
index f467dbb33a5afc951c4695d130f9bfa9900b700a..0be8a6914d9ab566926a9ae693e8c33004552eeb 100644 (file)
@@ -1,4 +1,3 @@
-/* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "winMS.h"
@@ -10,7 +9,7 @@
 #include "mhfont.h"
 
 #define MENU_MARGIN                    0
-#define NHMENU_STR_SIZE     50
+#define NHMENU_STR_SIZE     BUFSZ
 
 typedef struct mswin_menu_item {
        int                             glyph;
@@ -20,17 +19,21 @@ typedef struct mswin_menu_item {
        int                             attr;
        char                    str[NHMENU_STR_SIZE];
        BOOLEAN_P               presel;
+       int                             count;
+       BOOL                    has_focus;
 } NHMenuItem, *PNHMenuItem;
 
 typedef struct mswin_nethack_menu_window {
-       int type;
-       int how;
+       int type;               /* MENU_TYPE_TEXT or MENU_TYPE_MENU */
+       int how;                /* for menus: PICK_NONE, PICK_ONE, PICK_ANY */
 
        union {
                struct menu_list {
-                       int                              size;
-                       int                              allocated;
-                       PNHMenuItem              items;
+                       int                              size;                  /* number of items in items[] */
+                       int                              allocated;             /* number of allocated slots in items[] */
+                       PNHMenuItem              items;                 /* menu items */
+                       char                     gacc[QBUFSZ];  /* group accelerators */
+                       BOOL                     counting;              /* counting flag */
                } menu;
 
                struct menu_text {
@@ -41,23 +44,31 @@ typedef struct mswin_nethack_menu_window {
        int done;
 
        HBITMAP bmpChecked;
+       HBITMAP bmpCheckedCount;
        HBITMAP bmpNotChecked;
 } NHMenuWindow, *PNHMenuWindow;
 
 extern short glyph2tile[];
 
+static WNDPROC wndProcListViewOrig = NULL;
+static WNDPROC editControlWndProc = NULL;
+
 #define NHMENU_IS_SELECTABLE(item) ((item).identifier.a_obj!=NULL)
+#define NHMENU_IS_SELECTED(item) ((item).count!=0)
 
-BOOL CALLBACK  MenuWndProc(HWND, UINT, WPARAM, LPARAM);
+BOOL   CALLBACK        MenuWndProc(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK       NHMenuListWndProc(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK       NHMenuTextWndProc(HWND, UINT, WPARAM, LPARAM);
 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
 static BOOL onMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam);
 static BOOL onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam);
-static BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch);
 static void LayoutMenu(HWND hwnd);
 static void SetMenuType(HWND hwnd, int type);
 static void SetMenuListType(HWND hwnd, int now);
 static HWND GetMenuControl(HWND hwnd);
-static int GetListPageSize( HWND hwndList );
+static void SelectMenuItem(HWND hwndList, PNHMenuWindow data, int item, int count);
+static void reset_menu_count(HWND hwndList, PNHMenuWindow data);
+static BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch);
 
 HWND mswin_init_menu_window (int type) {
        HWND ret;
@@ -68,7 +79,9 @@ HWND mswin_init_menu_window (int type) {
                        GetNHApp()->hMainWnd,
                        MenuWndProc
        );
-       if( !ret ) panic("Cannot create menu window");
+       if( !ret ) {
+               panic("Cannot create menu window");
+       }
        
        SetMenuType(ret, type);
        return ret;
@@ -82,6 +95,7 @@ int mswin_menu_window_select_menu (HWND hWnd, int how, MENU_ITEM_P ** _selected)
        int ret_val;
     MENU_ITEM_P *selected = NULL;
        int i;
+       char* ap;
 
        assert( _selected!=NULL );
        *_selected = NULL;
@@ -89,10 +103,15 @@ int mswin_menu_window_select_menu (HWND hWnd, int how, MENU_ITEM_P ** _selected)
 
        data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA);
 
+       /* set menu type */
+       SetMenuListType(hWnd, how);
+
        /* Ok, now give items a unique accelerators */
        if( data->type == MENU_TYPE_MENU ) {
                char next_char = 'a';
 
+               data->menu.gacc[0] = '\0';
+               ap = data->menu.gacc;
                for( i=0; i<data->menu.size;  i++) {
                        if( data->menu.items[i].accelerator!=0 ) {
                                next_char = (char)(data->menu.items[i].accelerator+1);
@@ -109,23 +128,34 @@ int mswin_menu_window_select_menu (HWND hWnd, int how, MENU_ITEM_P ** _selected)
 
                                next_char ++;
                        }
+
+                       /* collect group accelerators */
+                       if( data->how != PICK_NONE ) {
+                               if( data->menu.items[i].group_accel && 
+                                       !strchr(data->menu.gacc, data->menu.items[i].group_accel) ) {
+                                       *ap++ = data->menu.items[i].group_accel;
+                                       *ap = '\x0';
+                               }
+                       }
                }
+
+               reset_menu_count(NULL, data);
        }
 
        /* activate the menu window */
-       GetNHApp()->hMenuWnd = hWnd;
-
-       SetMenuListType(hWnd, how);
+       GetNHApp()->hPopupWnd = hWnd;
 
        mswin_layout_main_window(hWnd);
 
+       /* disable game windows */
        EnableWindow(mswin_hwnd_from_winid(WIN_MAP), FALSE);
        EnableWindow(mswin_hwnd_from_winid(WIN_MESSAGE), FALSE);
        EnableWindow(mswin_hwnd_from_winid(WIN_STATUS), FALSE);
-       EnableWindow(GetNHApp()->hMainWnd, FALSE);
 
+       /* bring menu window on top */
        SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
 
+       /* go into message loop */
        while( IsWindow(hWnd) && 
                   !data->done &&
                   GetMessage(&msg, NULL, 0, 0)!=0 ) {
@@ -142,70 +172,49 @@ int mswin_menu_window_select_menu (HWND hWnd, int how, MENU_ITEM_P ** _selected)
                if(how==PICK_NONE) {
                        if(data->result>=0) ret_val=0;
                        else                            ret_val=-1;
-               } else if(how==PICK_ONE) {
-                       HWND menu_list;
-                       int nItem;
-
-                       menu_list = GetMenuControl(hWnd);
-                       nItem = SendMessage(menu_list, LB_GETCURSEL, 0, 0);
-                       if(nItem==LB_ERR) {
-                               ret_val = 0;
-                       } else {
-                               assert(nItem>=0 && nItem<data->menu.size);
-
-                               ret_val = 1;
-                               selected =  malloc( sizeof(MENU_ITEM_P) );
-                               assert (selected != NULL);
-                               selected[0].item = data->menu.items[nItem].identifier;
-                               selected[0].count = -1;
-                               *_selected = selected;
+               } else if(how==PICK_ONE || how==PICK_ANY) {
+                       /* count selected items */
+                       ret_val = 0;
+                       for(i=0; i<data->menu.size; i++ ) {
+                               if( NHMENU_IS_SELECTABLE(data->menu.items[i]) &&
+                                       NHMENU_IS_SELECTED(data->menu.items[i]) ) {
+                                       ret_val++;
+                               }
                        }
-               } else if(how==PICK_ANY) {
-                       HWND menu_list;
-                       int  buffer[255];
-                       int  n_sel_items_in_buffer;
-                       int  i;
-
-                       menu_list = GetMenuControl(hWnd); 
-                       ret_val = SendMessage(menu_list, LB_GETSELCOUNT, 0, 0); 
-                       if( ret_val==LB_ERR ) ret_val = 0;
-
                        if( ret_val > 0 ) {
-                               n_sel_items_in_buffer = SendMessage(menu_list, LB_GETSELITEMS, sizeof(buffer)/sizeof(buffer[0]), (LPARAM) buffer); 
-                               ret_val = n_sel_items_in_buffer;
-
-                               selected =  malloc( n_sel_items_in_buffer*sizeof(MENU_ITEM_P) );
-                               assert (selected != NULL);
-
-                               ret_val = 0;
-                               for(i=0; i<n_sel_items_in_buffer; i++ ) {
-                                       assert(buffer[i]>=0 && buffer[i]<data->menu.size);
-
-                                       if( NHMENU_IS_SELECTABLE(data->menu.items[buffer[i]]) ) {
-                                               selected[ret_val].item = data->menu.items[buffer[i]].identifier;
-                                               selected[ret_val].count = -1;
-                                               ret_val++;
+                               int sel_ind;
+
+                               selected = (MENU_ITEM_P*)malloc(ret_val*sizeof(MENU_ITEM_P));
+                               if( !selected ) panic("out of memory");
+
+                               sel_ind = 0;
+                               for(i=0; i<data->menu.size; i++ ) {
+                                       if( NHMENU_IS_SELECTABLE(data->menu.items[i]) &&
+                                               NHMENU_IS_SELECTED(data->menu.items[i]) ) {
+                                               selected[sel_ind].item = data->menu.items[i].identifier;
+                                               selected[sel_ind].count = data->menu.items[i].count;
+                                               sel_ind++;
                                        }
                                }
+                               ret_val = sel_ind;
                                *_selected = selected;
                        }
                }
        }
 
        /* restore window state */
-       EnableWindow(GetNHApp()->hMainWnd, TRUE);
        EnableWindow(mswin_hwnd_from_winid(WIN_MAP), TRUE);
        EnableWindow(mswin_hwnd_from_winid(WIN_MESSAGE), TRUE);
        EnableWindow(mswin_hwnd_from_winid(WIN_STATUS), TRUE);
 
        SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
-       GetNHApp()->hMenuWnd = NULL;
-
+       GetNHApp()->hPopupWnd = NULL;
        mswin_window_mark_dead( mswin_winid_from_handle(hWnd) );
        DestroyWindow(hWnd);
+
        mswin_layout_main_window(hWnd);
 
-       SetFocus(GetTopWindow(GetNHApp()->hMainWnd));
+       SetFocus(GetNHApp()->hMainWnd );
 
        return ret_val;
 }
@@ -213,8 +222,6 @@ int mswin_menu_window_select_menu (HWND hWnd, int how, MENU_ITEM_P ** _selected)
 BOOL CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
        PNHMenuWindow data;
-       int nItem;
-       HDC hdc;
 
        data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA);
        switch (message) 
@@ -227,20 +234,13 @@ BOOL CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                data->result = 0;
                data->done = 0;
                data->bmpChecked = LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_MENU_SEL));
+               data->bmpCheckedCount = LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_MENU_SEL_COUNT));
                data->bmpNotChecked = LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_MENU_UNSEL));
                SetWindowLong(hWnd, GWL_USERDATA, (LONG)data);
 
-               /* set text control font & the rest*/
-               if( data->type==MENU_TYPE_MENU ) {
-                       hdc = GetDC(GetDlgItem(hWnd, IDC_MENU_TEXT));
-                       SendDlgItemMessage(hWnd, IDC_MENU_TEXT, WM_SETFONT, (WPARAM)mswin_create_font(NHW_MENU, ATR_NONE, hdc), 0);
-                       ReleaseDC(GetDlgItem(hWnd, IDC_MENU_TEXT), hdc);
-
-                       SetFocus(GetMenuControl(hWnd));
-               } else {
-                       SetFocus(GetDlgItem(hWnd, IDOK));
-               }
-               return FALSE;
+               /* subclass edit control */
+               editControlWndProc = (WNDPROC)GetWindowLong(GetDlgItem(hWnd, IDC_MENU_TEXT), GWL_WNDPROC);
+               SetWindowLong(GetDlgItem(hWnd, IDC_MENU_TEXT), GWL_WNDPROC, (LONG)NHMenuTextWndProc);
        break;
 
        case WM_MSNH_COMMAND:
@@ -249,7 +249,6 @@ BOOL CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
        case WM_SIZE:
                LayoutMenu(hWnd);
-       break;
        return FALSE;
 
        case WM_COMMAND: 
@@ -257,73 +256,142 @@ BOOL CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                switch (LOWORD(wParam)) 
         { 
                case IDCANCEL:
-                       data->result = -1;
-                       data->done = 1;
+                       if( data->type == MENU_TYPE_MENU && 
+                           (data->how==PICK_ONE || data->how==PICK_ANY) &&
+                           data->menu.counting) {
+                               HWND list;
+                               int i;
+
+                               /* reset counter if counting is in progress */
+                               list = GetMenuControl(hWnd);
+                               i = ListView_GetNextItem(list, -1,      LVNI_FOCUSED);
+                               if( i>=0 ) {
+                                       SelectMenuItem(list, data, i,  0);
+                               }
+                               return TRUE;
+                       } else {
+                               data->result = -1;
+                               data->done = 1;
+                       }
                return TRUE;
 
                case IDOK:
                        data->done = 1;
                        data->result = 0;
                return TRUE;
+               }
+       } break;
 
+       case WM_NOTIFY:
+       {
+               LPNMHDR lpnmhdr = (LPNMHDR)lParam;
+               switch (LOWORD(wParam)) {
                case IDC_MENU_LIST:
                {
                        if( !data || data->type!=MENU_TYPE_MENU ) break;
 
-                       switch(HIWORD(wParam)) {
-                       case LBN_DBLCLK: 
+                       switch(lpnmhdr->code) {
+                       case LVN_ITEMACTIVATE: 
+                       {
+                               LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam;
                                if(data->how==PICK_ONE) {
-                                       nItem = SendMessage((HWND)lParam, LB_GETCURSEL, (WPARAM)0, (LPARAM)0);
-                                       if( nItem!=LB_ERR &&
-                                               nItem>0 &&
-                                               nItem<data->menu.size &&
-                                               data->menu.items[nItem].accelerator!=0 ) {
+                                       if( lpnmlv->iItem>=0 &&
+                                               lpnmlv->iItem<data->menu.size &&
+                                               NHMENU_IS_SELECTABLE(data->menu.items[lpnmlv->iItem]) ) {
+                                               SelectMenuItem(
+                                                       lpnmlv->hdr.hwndFrom, 
+                                                       data, 
+                                                       lpnmlv->iItem, 
+                                                       -1
+                                               );
                                                data->done = 1;
                                                data->result = 0;
                                                return TRUE;
                                        }
                                }
+                       } break;
+
+                       case NM_CLICK: {
+                               LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) lParam;
+                               if( lpnmitem->iItem==-1 ) return 0;
+                               if( data->how==PICK_ANY ) {
+                                       SelectMenuItem(
+                                               lpnmitem->hdr.hwndFrom, 
+                                               data, 
+                                               lpnmitem->iItem, 
+                                               NHMENU_IS_SELECTED(data->menu.items[lpnmitem->iItem])? 0 : -1
+                                       );
+                               }
+                       } break;
+
+                       case LVN_ITEMCHANGED: 
+                       {
+                               LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam;
+                               if( lpnmlv->iItem==-1 ) return 0;
+                               if( !(lpnmlv->uChanged & LVIF_STATE) ) return 0;
+
+                               if( data->how==PICK_ONE || data->how==PICK_ANY ) {
+                                       data->menu.items[lpnmlv->iItem].has_focus = !!(lpnmlv->uNewState & LVIS_FOCUSED);
+                                       ListView_RedrawItems(lpnmlv->hdr.hwndFrom, lpnmlv->iItem, lpnmlv->iItem);
+                               }
+
+                               /* update count for single-selection menu (follow the listview selection) */
+                               if( data->how==PICK_ONE ) {
+                                       if( lpnmlv->uNewState & LVIS_SELECTED ) {
+                                               SelectMenuItem(
+                                                       lpnmlv->hdr.hwndFrom, 
+                                                       data, 
+                                                       lpnmlv->iItem, 
+                                                       -1
+                                               );
+                                       }
+                               }
+
+                               /* check item focus */
+                               if( data->how==PICK_ONE || data->how==PICK_ANY ) {
+                                       data->menu.items[lpnmlv->iItem].has_focus = !!(lpnmlv->uNewState & LVIS_FOCUSED);
+                                       ListView_RedrawItems(lpnmlv->hdr.hwndFrom, lpnmlv->iItem, lpnmlv->iItem);
+                               }
+                       } break;
+
+                       case NM_KILLFOCUS:
+                               reset_menu_count(lpnmhdr->hwndFrom, data);
                        break;
+
                        }
-               }
-               break;
+               } break;
                }
        } break;
 
        case WM_SETFOCUS:
-               if( hWnd!=GetNHApp()->hMenuWnd ) {
-                       SetFocus(GetNHApp()->hMainWnd );
+               if( hWnd!=GetNHApp()->hPopupWnd ) {
+                       SetFocus(GetNHApp()->hPopupWnd );
                }
        break;
        
     case WM_MEASUREITEM: 
-               return onMeasureItem(hWnd, wParam, lParam);
+               if( wParam==IDC_MENU_LIST )
+                       return onMeasureItem(hWnd, wParam, lParam);
+               else
+                       return FALSE;
 
     case WM_DRAWITEM:
-               return onDrawItem(hWnd, wParam, lParam);
-
-       case WM_VKEYTOITEM:
-       { 
-               WORD c[4];
-               BYTE kbd_state[256];
-               
-               ZeroMemory(kbd_state, sizeof(kbd_state));
-               ZeroMemory(c, sizeof(c));
-               GetKeyboardState(kbd_state);
-               
-               if( ToAscii( LOWORD(wParam), 0, kbd_state, c, 0)==1 ) {
-                       return onListChar(hWnd, (HWND)lParam, c[0]);
-               }
-       } return -1;
+               if( wParam==IDC_MENU_LIST )
+                       return onDrawItem(hWnd, wParam, lParam);
+               else
+                       return FALSE;
 
        case WM_DESTROY:
-               DeleteObject(data->bmpChecked);
-               DeleteObject(data->bmpNotChecked);
-               if( data->type == MENU_TYPE_TEXT ) {
-                       if( data->text.text ) free(data->text.text);
+               if( data ) {
+                       DeleteObject(data->bmpChecked);
+                       DeleteObject(data->bmpCheckedCount);
+                       DeleteObject(data->bmpNotChecked);
+                       if( data->type == MENU_TYPE_TEXT ) {
+                               if( data->text.text ) free(data->text.text);
+                       }
+                       free(data);
+                       SetWindowLong(hWnd, GWL_USERDATA, (LONG)0);
                }
-               free(data);
-               SetWindowLong(hWnd, GWL_USERDATA, (LONG)0);
                return TRUE;
        }
        return FALSE;
@@ -388,6 +456,7 @@ void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
                        data->menu.items = (PNHMenuItem)realloc(data->menu.items, data->menu.allocated*sizeof(NHMenuItem));
                }
 
+               ZeroMemory( &data->menu.items[data->menu.size], sizeof(data->menu.items[data->menu.size]));
                data->menu.items[data->menu.size].glyph = msg_data->glyph;
                data->menu.items[data->menu.size].identifier = *msg_data->identifier;
                data->menu.items[data->menu.size].accelerator = msg_data->accelerator;
@@ -456,11 +525,13 @@ void SetMenuType(HWND hWnd, int type)
                EnableWindow(list, FALSE);
                EnableWindow(text, TRUE);
                ShowWindow(text, SW_SHOW);
+               SetFocus(text);
        } else {
                ShowWindow(text, SW_HIDE);
                EnableWindow(text, FALSE);
                EnableWindow(list, TRUE);
                ShowWindow(list, SW_SHOW);
+               SetFocus(list);
        }
        LayoutMenu(hWnd);
 }
@@ -470,10 +541,12 @@ void SetMenuListType(HWND hWnd, int how)
        PNHMenuWindow data;
        RECT rt;
        DWORD dwStyles;
-       char buf[255];
+       char buf[BUFSZ];
+       TCHAR wbuf[BUFSZ];
        int nItem;
        int i;
        HWND control;
+       LVCOLUMN lvcol;
        LRESULT fnt;
 
        data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA);
@@ -484,52 +557,65 @@ void SetMenuListType(HWND hWnd, int how)
        switch(how) {
        case PICK_NONE: 
                dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD 
-                       | WS_VSCROLL | WS_HSCROLL | LBS_WANTKEYBOARDINPUT
-                       | LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | LBS_NOSEL 
-                       | LBS_OWNERDRAWFIXED; 
+                       | WS_VSCROLL | WS_HSCROLL | LVS_REPORT | LVS_NOCOLUMNHEADER 
+                       | LVS_OWNERDRAWFIXED | LVS_SINGLESEL; 
                break;
        case PICK_ONE: 
                dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD 
-                       | WS_VSCROLL | WS_HSCROLL | LBS_WANTKEYBOARDINPUT
-                       | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT     | LBS_OWNERDRAWFIXED 
-                       | LBS_HASSTRINGS; 
+                       | WS_VSCROLL | WS_HSCROLL | LVS_REPORT | LVS_NOCOLUMNHEADER 
+                       | LVS_OWNERDRAWFIXED | LVS_SINGLESEL; 
                break;
        case PICK_ANY: 
                dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD 
-                       | WS_VSCROLL | WS_HSCROLL | LBS_WANTKEYBOARDINPUT
-                       | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_MULTIPLESEL 
-                       | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS; 
+                       | WS_VSCROLL | WS_HSCROLL | LVS_REPORT | LVS_NOCOLUMNHEADER 
+                       | LVS_OWNERDRAWFIXED | LVS_SINGLESEL; 
                break;
        default: panic("how should be one of PICK_NONE, PICK_ONE or PICK_ANY");
        };
 
        GetWindowRect(GetDlgItem(hWnd, IDC_MENU_LIST), &rt);
        DestroyWindow(GetDlgItem(hWnd, IDC_MENU_LIST));
-       control = CreateWindow(
-               TEXT("LISTBOX"),        /* registered class name */
-               NULL,                           /* window name */
-               dwStyles,                       /* window style */
-               rt.left,                        /* horizontal position of window */
-               rt.top,                         /* vertical position of window */
-               rt.right - rt.left, /* window width */
-               rt.bottom - rt.top, /* window height */
-               hWnd,                           /* handle to parent or owner window */
-               (HMENU)IDC_MENU_LIST, /* menu handle or child identifier */
-               GetNHApp()->hApp,       /* handle to application instance */
-               NULL );                         /* window-creation data */
+       control = CreateWindow(WC_LISTVIEW, NULL, 
+               dwStyles,
+               rt.left,
+               rt.top,
+               rt.right - rt.left,
+               rt.bottom - rt.top,
+               hWnd,
+               (HMENU)IDC_MENU_LIST,
+               GetNHApp()->hApp,
+               NULL );
+       if( !control ) panic( "cannot create menu control" );
+       
+       /* install the hook for the control window procedure */
+       wndProcListViewOrig = (WNDPROC)GetWindowLong(control, GWL_WNDPROC);
+       SetWindowLong(control, GWL_WNDPROC, (LONG)NHMenuListWndProc);
+
+       /* set control font */
        fnt = SendMessage(hWnd, WM_GETFONT, (WPARAM)0, (LPARAM)0);
        SendMessage(control, WM_SETFONT, (WPARAM)fnt, (LPARAM)0);
 
+       /* add column to the list view */
+       ZeroMemory(&lvcol, sizeof(lvcol));
+       lvcol.mask = LVCF_WIDTH;
+       lvcol.cx = 1024;
+       ListView_InsertColumn(control, 0, &lvcol);
+
+       /* add items to the list view */
        for(i=0; i<data->menu.size; i++ ) {
-               TCHAR wbuf[255];
+               LVITEM lvitem;
+               ZeroMemory( &lvitem, sizeof(lvitem) );
                sprintf(buf, "%c - %s", max(data->menu.items[i].accelerator, ' '), data->menu.items[i].str );
-               nItem = SendMessage(control, LB_ADDSTRING, (WPARAM)0, (LPARAM) NH_A2W(buf, wbuf, sizeof(wbuf))); 
-               if( data->menu.items[i].presel ) {
-                       if( data->how==PICK_ONE ) {
-                               nItem = SendMessage(control, LB_SETCURSEL, (WPARAM)nItem, (LPARAM)0); 
-                       } else if( data->how==PICK_ANY ) {
-                               nItem = SendMessage(control, LB_SETSEL, (WPARAM)TRUE, (LPARAM)nItem); 
-                       }
+
+               lvitem.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+               lvitem.iItem = i;
+               lvitem.iSubItem = 0;
+               lvitem.state = data->menu.items[i].presel? LVIS_SELECTED : 0;
+               lvitem.pszText = NH_A2W(buf, wbuf, BUFSZ);
+               lvitem.lParam = (LPARAM)&data->menu.items[i];
+               nItem = SendMessage(control, LB_ADDSTRING, (WPARAM)0, (LPARAM) buf); 
+               if( ListView_InsertItem(control, &lvitem)==-1 ) {
+                       panic("cannot insert menu item");
                }
        }
        SetFocus(control);
@@ -557,10 +643,11 @@ BOOL onMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
        HGDIOBJ saveFont;
        HDC hdc;
        PNHMenuWindow data;
-       RECT client_rect;
+       RECT list_rect;
 
     lpmis = (LPMEASUREITEMSTRUCT) lParam; 
        data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA);
+       GetClientRect(GetMenuControl(hWnd), &list_rect);
 
        hdc = GetDC(GetMenuControl(hWnd));
        saveFont = SelectObject(hdc, mswin_create_font(NHW_MENU, ATR_INVERSE, hdc));
@@ -568,10 +655,7 @@ BOOL onMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
 
     /* Set the height of the list box items. */
     lpmis->itemHeight = max(tm.tmHeight, TILE_Y)+2;
-
-       /* Set windth of list box items */
-       GetClientRect(hWnd, &client_rect);
-       lpmis->itemWidth = client_rect.right - client_rect.left;
+       lpmis->itemWidth = list_rect.right - list_rect.left;
 
        mswin_destroy_font(SelectObject(hdc, saveFont));
        ReleaseDC(GetMenuControl(hWnd), hdc);
@@ -585,106 +669,122 @@ BOOL onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
        PNHMenuWindow data;
     TEXTMETRIC tm;
        HGDIOBJ saveFont;
-       HGDIOBJ savePen;
-       HPEN    pen;
        HDC tileDC;
        short ntile;
        int t_x, t_y;
        int x, y;
-       TCHAR wbuf[255];
+       TCHAR wbuf[BUFSZ];
+       RECT drawRect;
 
        lpdis = (LPDRAWITEMSTRUCT) lParam; 
 
     /* If there are no list box items, skip this message. */
-    if ( (int)(lpdis->itemID) < 0) return FALSE;
+    if (lpdis->itemID == -1) return FALSE;
 
        data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA);
-    switch (lpdis->itemAction) 
-    { 
-        case ODA_SELECT: 
-        case ODA_DRAWENTIRE: 
-            item = &data->menu.items[lpdis->itemID];
-
-                       tileDC = CreateCompatibleDC(lpdis->hDC);
-                       saveFont = SelectObject(lpdis->hDC, mswin_create_font(NHW_MENU, item->attr, lpdis->hDC));
-            GetTextMetrics(lpdis->hDC, &tm);
-
-                       x = lpdis->rcItem.left;
-
-                       /* print check mark */
-                       if( NHMENU_IS_SELECTABLE(*item) ) {
-                               HGDIOBJ saveBmp;
-                               char buf[2];
-
-                               saveBmp = SelectObject(tileDC, 
-                                       (lpdis->itemState & ODS_SELECTED)? data->bmpChecked: data->bmpNotChecked );
-
-                       y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; 
-                               BitBlt(lpdis->hDC, x, y, TILE_X, TILE_Y, tileDC, 0, 0, SRCCOPY );
-                               x += TILE_X + 5;
-
-                               if(item->accelerator!=0) {
-                                       y = (lpdis->rcItem.bottom + lpdis->rcItem.top - 
-                                               tm.tmHeight) / 2; 
-                                       buf[0] = item->accelerator;
-                                       buf[1] = '\x0';
-                                       TextOut(lpdis->hDC, x, y, NH_A2W(buf, wbuf, sizeof(wbuf)), 1); 
-                               }
-                               x += tm.tmAveCharWidth + 5;
-                               SelectObject(tileDC, saveBmp);
-                       }
 
-                       /* print glyph if present */
-                       if( item->glyph != NO_GLYPH ) {
-                               HGDIOBJ saveBmp;
+    item = &data->menu.items[lpdis->itemID];
 
-                               saveBmp = SelectObject(tileDC, GetNHApp()->bmpTiles);                           
-                               ntile = glyph2tile[ item->glyph ];
-                               t_x = (ntile % TILES_PER_LINE)*TILE_X;
-                               t_y = (ntile / TILES_PER_LINE)*TILE_Y;
+       tileDC = CreateCompatibleDC(lpdis->hDC);
+       saveFont = SelectObject(lpdis->hDC, mswin_create_font(NHW_MENU, item->attr, lpdis->hDC));
+    GetTextMetrics(lpdis->hDC, &tm);
 
-                               y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; 
+       x = lpdis->rcItem.left + 1;
 
-                               nhapply_image_transparent(
-                                       lpdis->hDC, x, y, TILE_X, TILE_Y, 
-                                       tileDC, t_x, t_y, TILE_X, TILE_Y, TILE_BK_COLOR );
-                               SelectObject(tileDC, saveBmp);
-                       }
-                       x += TILE_X + 5;
+       /* print check mark */
+       if( NHMENU_IS_SELECTABLE(*item) ) {
+               HGDIOBJ saveBmp;
+               char buf[2];
+
+               switch(item->count) {
+               case -1: saveBmp = SelectObject(tileDC, data->bmpChecked); break;
+               case 0: saveBmp = SelectObject(tileDC, data->bmpNotChecked); break;
+               default: saveBmp = SelectObject(tileDC, data->bmpCheckedCount); break;
+               }
 
-            y = (lpdis->rcItem.bottom + lpdis->rcItem.top - 
-                tm.tmHeight) / 2; 
+               y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; 
+               BitBlt(lpdis->hDC, x, y, TILE_X, TILE_Y, tileDC, 0, 0, SRCCOPY );
 
-            TextOut(lpdis->hDC, 
-                x, 
-                y, 
-                NH_A2W(item->str, wbuf, sizeof(wbuf)), 
-                strlen(item->str)); 
+               x += TILE_X + 5;
 
-                       mswin_destroy_font(SelectObject(lpdis->hDC, saveFont));
-                       DeleteDC(tileDC);
-                       
-            break; 
+               if(item->accelerator!=0) {
+                       buf[0] = item->accelerator;
+                       buf[1] = '\x0';
 
-        case ODA_FOCUS:
-                       if( data->how==PICK_NONE ) break;
+                       SetRect( &drawRect, x, lpdis->rcItem.top, lpdis->rcItem.right, lpdis->rcItem.bottom );
+                       DrawText(lpdis->hDC, NH_A2W(buf, wbuf, 2), 1, &drawRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
+               }
+               x += tm.tmAveCharWidth + 5;
+               SelectObject(tileDC, saveBmp);
+       }
 
-                       if( lpdis->itemState & ODS_FOCUS )
-                               pen = CreatePen(PS_DOT, 0, RGB(0,0,0));
-                       else 
-                               pen = CreatePen(PS_DOT, 0, GetBkColor(lpdis->hDC));
+       /* print glyph if present */
+       if( item->glyph != NO_GLYPH ) {
+               HGDIOBJ saveBmp;
 
-                       savePen = SelectObject(lpdis->hDC, pen);
+               saveBmp = SelectObject(tileDC, GetNHApp()->bmpTiles);                           
+               ntile = glyph2tile[ item->glyph ];
+               t_x = (ntile % TILES_PER_LINE)*TILE_X;
+               t_y = (ntile / TILES_PER_LINE)*TILE_Y;
+
+               y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; 
+
+               nhapply_image_transparent(
+                       lpdis->hDC, x, y, TILE_X, TILE_Y, 
+                       tileDC, t_x, t_y, TILE_X, TILE_Y, TILE_BK_COLOR );
+               SelectObject(tileDC, saveBmp);
+       }
+
+       x += TILE_X + 5;
+
+       SetRect( &drawRect, x, lpdis->rcItem.top, lpdis->rcItem.right, lpdis->rcItem.bottom );
+    DrawText(lpdis->hDC, 
+        NH_A2W(item->str, wbuf, BUFSZ), 
+        strlen(item->str),
+        &drawRect, 
+               DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX
+       ); 
+
+       /* draw focused item */
+       if( item->has_focus ) {
+               RECT client_rt;
+
+               GetClientRect(lpdis->hwndItem, &client_rt);
+               if( NHMENU_IS_SELECTABLE(*item) && 
+                       data->menu.items[lpdis->itemID].count!=0 &&
+                       item->glyph != NO_GLYPH ) {
+                       if( data->menu.items[lpdis->itemID].count==-1 ) {
+                               _stprintf(wbuf, TEXT("Count: All") );
+                       } else {
+                               _stprintf(wbuf, TEXT("Count: %d"), data->menu.items[lpdis->itemID].count );
+                       }
+
+                       SelectObject(lpdis->hDC, mswin_create_font(NHW_MENU, ATR_BLINK, lpdis->hDC));
+
+                       /* calculate text rectangle */
+                       SetRect( &drawRect, client_rt.left, lpdis->rcItem.top, client_rt.right, lpdis->rcItem.bottom );
+                       DrawText(lpdis->hDC, wbuf, _tcslen(wbuf), &drawRect, 
+                                        DT_CALCRECT | DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX );
                        
-                       MoveToEx(lpdis->hDC,lpdis->rcItem.left, lpdis->rcItem.top, NULL);
-                       LineTo(lpdis->hDC, lpdis->rcItem.right-1, lpdis->rcItem.top);
-                       LineTo(lpdis->hDC, lpdis->rcItem.right-1, lpdis->rcItem.bottom-1);
-                       LineTo(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.bottom-1);
-                       LineTo(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top);
-
-                       DeleteObject(SelectObject(lpdis->hDC, savePen));
-           break; 
-    } 
+                       /* erase text rectangle */
+                       drawRect.left = max(client_rt.left+1, client_rt.right - (drawRect.right - drawRect.left) - 10);
+                       drawRect.right = client_rt.right-1;
+                       drawRect.top = lpdis->rcItem.top;
+                       drawRect.bottom = lpdis->rcItem.bottom;
+                       FillRect(lpdis->hDC, &drawRect, (HBRUSH)GetClassLong(lpdis->hwndItem, GCL_HBRBACKGROUND) );
+
+                       /* draw text */
+                       DrawText(lpdis->hDC, wbuf, _tcslen(wbuf), &drawRect, 
+                                        DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX );
+               }
+
+               /* draw focus rect */
+               SetRect( &drawRect, client_rt.left, lpdis->rcItem.top, client_rt.right, lpdis->rcItem.bottom );
+               DrawFocusRect(lpdis->hDC, &drawRect);
+       }
+
+       mswin_destroy_font(SelectObject(lpdis->hDC, saveFont));
+       DeleteDC(tileDC);
        return TRUE;
 }
 
@@ -698,38 +798,38 @@ BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch)
 
        switch( ch ) {
        case MENU_FIRST_PAGE:
-               SendMessage(hwndList, LB_SETTOPINDEX, 0, 0);
+               i = 0;
+               ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED);
+               ListView_EnsureVisible(hwndList, i, FALSE);
        return -2;
 
        case MENU_LAST_PAGE:
-               SendMessage(hwndList, 
-                                       LB_SETTOPINDEX, 
-                                       (WPARAM)max(0, data->menu.size-1),
-                                       (LPARAM)0);
+               i = max(0, data->menu.size-1);
+               ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED);
+               ListView_EnsureVisible(hwndList, i, FALSE);
        return -2;
 
        case MENU_NEXT_PAGE:
-               topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 );
-               pageSize = GetListPageSize( hwndList );
-               SendMessage(hwndList, 
-                                       LB_SETTOPINDEX, 
-                                       (WPARAM)min(topIndex+pageSize, data->menu.size-1),
-                                       (LPARAM)0);
+               topIndex = ListView_GetTopIndex( hwndList );
+               pageSize = ListView_GetCountPerPage( hwndList );
+               i = min(topIndex+pageSize, data->menu.size-1);
+               ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED);
+               ListView_EnsureVisible(hwndList, i, FALSE);
        return -2;
 
        case MENU_PREVIOUS_PAGE:
-               topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 );
-               pageSize = GetListPageSize( hwndList );
-               SendMessage(hwndList, 
-                                       LB_SETTOPINDEX, 
-                                       (WPARAM)max(topIndex-pageSize, 0),
-                                       (LPARAM)0);
+               topIndex = ListView_GetTopIndex( hwndList );
+               pageSize = ListView_GetCountPerPage( hwndList );
+               i = max(topIndex-pageSize, 0);
+               ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED);
+               ListView_EnsureVisible(hwndList, i, FALSE);
        break;
 
        case MENU_SELECT_ALL:
                if( data->how == PICK_ANY ) {
+                       reset_menu_count(hwndList, data);
                        for(i=0; i<data->menu.size; i++ ) {
-                               SendMessage(hwndList, LB_SETSEL, (WPARAM)TRUE, (LPARAM)i);
+                               SelectMenuItem(hwndList, data, i, -1);
                        }
                        return -2;
                }
@@ -737,8 +837,9 @@ BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch)
 
        case MENU_UNSELECT_ALL:
                if( data->how == PICK_ANY ) {
+                       reset_menu_count(hwndList, data);
                        for(i=0; i<data->menu.size; i++ ) {
-                               SendMessage(hwndList, LB_SETSEL, (WPARAM)FALSE, (LPARAM)i);
+                               SelectMenuItem(hwndList, data, i, 0);
                        }
                        return -2;
                }
@@ -746,11 +847,14 @@ BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch)
 
        case MENU_INVERT_ALL:
                if( data->how == PICK_ANY ) {
+                       reset_menu_count(hwndList, data);
                        for(i=0; i<data->menu.size; i++ ) {
-                               SendMessage(hwndList, 
-                                                       LB_SETSEL, 
-                                                       (WPARAM)!SendMessage(hwndList, LB_GETSEL, (WPARAM)i, (LPARAM)0),
-                                                       (LPARAM)i);
+                               SelectMenuItem(
+                                       hwndList, 
+                                       data, 
+                                       i, 
+                                       NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1
+                               );
                        }
                        return -2;
                }
@@ -758,10 +862,11 @@ BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch)
 
        case MENU_SELECT_PAGE:
                if( data->how == PICK_ANY ) {
-                       topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 );
-                       pageSize = GetListPageSize( hwndList );
+                       reset_menu_count(hwndList, data);
+                       topIndex = ListView_GetTopIndex( hwndList );
+                       pageSize = ListView_GetCountPerPage( hwndList );
                        for(i=0; i<pageSize; i++ ) {
-                               SendMessage(hwndList, LB_SETSEL, (WPARAM)TRUE, (LPARAM)topIndex+i);
+                               SelectMenuItem(hwndList, data, topIndex+i, -1);
                        }
                        return -2;
                }
@@ -769,10 +874,11 @@ BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch)
 
        case MENU_UNSELECT_PAGE:
                if( data->how == PICK_ANY ) {
-                       topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 );
-                       pageSize = GetListPageSize( hwndList );
+                       reset_menu_count(hwndList, data);
+                       topIndex = ListView_GetTopIndex( hwndList );
+                       pageSize = ListView_GetCountPerPage( hwndList );
                        for(i=0; i<pageSize; i++ ) {
-                               SendMessage(hwndList, LB_SETSEL, (WPARAM)FALSE, (LPARAM)topIndex+i);
+                               SelectMenuItem(hwndList, data, topIndex+i, 0);
                        }
                        return -2;
                }
@@ -780,13 +886,16 @@ BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch)
 
        case MENU_INVERT_PAGE:
                if( data->how == PICK_ANY ) {
-                       topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 );
-                       pageSize = GetListPageSize( hwndList );
+                       reset_menu_count(hwndList, data);
+                       topIndex = ListView_GetTopIndex( hwndList );
+                       pageSize = ListView_GetCountPerPage( hwndList );
                        for(i=0; i<pageSize; i++ ) {
-                               SendMessage(hwndList, 
-                                                       LB_SETSEL, 
-                                                       (WPARAM)!SendMessage(hwndList, LB_GETSEL, (WPARAM)topIndex+i, (LPARAM)0),
-                                                       (LPARAM)topIndex+i);
+                               SelectMenuItem(
+                                       hwndList, 
+                                       data, 
+                                       topIndex+i, 
+                                       NHMENU_IS_SELECTED(data->menu.items[topIndex+i])? 0 : -1
+                               );
                        }
                        return -2;
                }
@@ -795,18 +904,27 @@ BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch)
        case MENU_SEARCH:
            if( data->how==PICK_ANY || data->how==PICK_ONE ) {
                        char buf[BUFSZ];
+                       
+                       reset_menu_count(hwndList, data);
                        mswin_getlin("Search for:", buf);
                        if (!*buf || *buf == '\033') return -2;
                        for(i=0; i<data->menu.size; i++ ) {
                                if( NHMENU_IS_SELECTABLE(data->menu.items[i])
                                        && strstr(data->menu.items[i].str, buf) ) {
                                        if (data->how == PICK_ANY) {
-                                               SendMessage(hwndList, 
-                                                                       LB_SETSEL, 
-                                                                       (WPARAM)!SendMessage(hwndList, LB_GETSEL, (WPARAM)i, (LPARAM)0),
-                                                                       (LPARAM)i);
+                                               SelectMenuItem(
+                                                       hwndList, 
+                                                       data, 
+                                                       i, 
+                                                       NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1
+                                               );
                                        } else if( data->how == PICK_ONE ) {
-                                               SendMessage(hwndList, LB_SETCURSEL, (WPARAM)i, (LPARAM)0);
+                                               SelectMenuItem(
+                                                       hwndList, 
+                                                       data, 
+                                                       i, 
+                                                       -1
+                                               );
                                                break;
                                        }
                                }
@@ -817,36 +935,111 @@ BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch)
        return -2;
 
        case ' ':
+               /* ends menu for PICK_ONE/PICK_NONE
+                  select item for PICK_ANY */
                if( data->how==PICK_ONE || data->how==PICK_NONE ) {
                        data->done = 1;
                        data->result = 0;
                        return -2;
+               } else if( data->how==PICK_ANY ) {
+                       i = ListView_GetNextItem(hwndList, -1,  LVNI_FOCUSED);
+                       if( i>=0 ) {
+                               SelectMenuItem(
+                                       hwndList, 
+                                       data, 
+                                       i, 
+                                       NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1
+                               );
+                       }
                }
        break;
-       
+
        default:
+               if( strchr(data->menu.gacc, ch) &&
+                       !(ch=='0' && data->menu.counting) ) {
+                       /* matched a group accelerator */
+                       if (data->how == PICK_ANY || data->how == PICK_ONE) {
+                               reset_menu_count(hwndList, data);
+                               for(i=0; i<data->menu.size; i++ ) {
+                                       if( NHMENU_IS_SELECTABLE(data->menu.items[i]) &&
+                                               data->menu.items[i].group_accel == ch ) {
+                                               if( data->how == PICK_ANY ) {
+                                                       SelectMenuItem(
+                                                               hwndList, 
+                                                               data, 
+                                                               i, 
+                                                               NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1
+                                                       );
+                                               } else if( data->how == PICK_ONE ) {
+                                                       SelectMenuItem(
+                                                               hwndList, 
+                                                               data, 
+                                                               i, 
+                                                               -1
+                                                       );
+                                                       data->result = 0;
+                                                       data->done = 1;
+                                                       return -2;
+                                               }
+                                       }
+                               }
+                               return -2;
+                       } else {
+                               mswin_nhbell();
+                               return -2;
+                       }
+               }
+
+               if (isdigit(ch)) {
+                       int count;
+                       i = ListView_GetNextItem(hwndList, -1,  LVNI_FOCUSED);
+                       if( i>=0 ) {
+                               count = data->menu.items[i].count;
+                               if( count==-1 ) count=0;
+                               count *= 10L;
+                               count += (int)(ch - '0');
+                               if (count != 0) /* ignore leading zeros */ {
+                                       data->menu.counting = TRUE;
+                                       data->menu.items[i].count = min(100000, count);
+                                       ListView_RedrawItems( hwndList, i, i ); /* update count mark */
+                               }
+                       }
+                       return -2;
+               }
+
                if( (ch>='a' && ch<='z') ||
                        (ch>='A' && ch<='Z') ) {
-                       for(i=0; i<data->menu.size; i++ ) {
-                               if( data->menu.items[i].accelerator == ch ) {
-                                       if( data->how == PICK_ANY ) {
-                                               SendMessage(hwndList, 
-                                                                       LB_SETSEL, 
-                                                                       (WPARAM)!SendMessage(hwndList, LB_GETSEL, (WPARAM)i, (LPARAM)0),
-                                                                       (LPARAM)i);
-                                               return -2;
-                                       } else if( data->how == PICK_ONE ) {
-                                               SendMessage(hwndList, LB_SETCURSEL, (WPARAM)i, (LPARAM)0);
-                                               data->result = 0;
-                                               data->done = 1;
-                                               return -2;
+                       if (data->how == PICK_ANY || data->how == PICK_ONE) {
+                               for(i=0; i<data->menu.size; i++ ) {
+                                       if( data->menu.items[i].accelerator == ch ) {
+                                               if( data->how == PICK_ANY ) {
+                                                       SelectMenuItem(
+                                                               hwndList, 
+                                                               data, 
+                                                               i, 
+                                                               NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1
+                                                       );
+                                                       ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED);
+                                                       return -2;
+                                               } else if( data->how == PICK_ONE ) {
+                                                       SelectMenuItem(
+                                                               hwndList, 
+                                                               data, 
+                                                               i, 
+                                                               -1
+                                                       );
+                                                       data->result = 0;
+                                                       data->done = 1;
+                                                       return -2;
+                                               }
                                        }
                                }
                        }
                }
        break;
        }
-       
+
+       reset_menu_count(hwndList, data);
        return -1;
 }
 
@@ -872,7 +1065,7 @@ void mswin_menu_window_size (HWND hWnd, LPSIZE sz)
                /* Set the height of the list box items. */
                for(i=0; i<data->menu.size; i++ ) {
                        sz->cx = max(sz->cx, 
-                               (LONG)(2*TILE_X + tm.tmAveCharWidth*(strlen(data->menu.items[i].str)+1)));
+                               (LONG)(2*TILE_X + tm.tmMaxCharWidth*(strlen(data->menu.items[i].str)+10)));
                }
 
                mswin_destroy_font(SelectObject(hdc, saveFont));
@@ -880,16 +1073,100 @@ void mswin_menu_window_size (HWND hWnd, LPSIZE sz)
        }
 }
 
-int GetListPageSize( HWND hwndList ) 
+void SelectMenuItem(HWND hwndList, PNHMenuWindow data, int item, int count)
+{
+       int i;
+       if( data->how==PICK_ONE && count!=0 ) {
+               for(i=0; i<data->menu.size; i++) 
+                       if( item!=i && data->menu.items[i].count!=0 ) {
+                               data->menu.items[i].count = 0;
+                               ListView_RedrawItems( hwndList, i, i );
+                       };
+       }
+
+       data->menu.items[item].count = count;
+       ListView_RedrawItems( hwndList, item, item );
+       reset_menu_count(hwndList, data);
+}
+
+void reset_menu_count(HWND hwndList, PNHMenuWindow data) 
+{
+       int i; 
+       data->menu.counting = FALSE;
+       if( IsWindow(hwndList) ) {
+               i = ListView_GetNextItem((hwndList), -1, LVNI_FOCUSED);
+               if( i>=0 ) ListView_RedrawItems( hwndList, i, i ); 
+       }
+}
+
+/* List window Proc */
+LRESULT CALLBACK NHMenuListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+       BOOL bUpdateFocusItem;
+
+       bUpdateFocusItem = FALSE;
+
+       switch(message) {
+
+       /* filter keyboard input for the control */
+       case WM_KEYDOWN:
+       case WM_KEYUP: {
+               MSG msg;
+               BOOL processed;
+
+               processed = FALSE;
+               if( PeekMessage(&msg, hWnd, WM_CHAR, WM_CHAR, PM_REMOVE) ) {
+                       if( onListChar(GetParent(hWnd), hWnd, (char)msg.wParam)==-2 ) {
+                               processed = TRUE;
+                       }
+               }
+               if( processed ) return 0;
+
+               if( wParam==VK_LEFT || wParam==VK_RIGHT )
+                       bUpdateFocusItem = TRUE;
+       } break;
+
+       case WM_SIZE:
+       case WM_HSCROLL:
+               bUpdateFocusItem = TRUE;
+       break;
+
+       }
+
+       if(     bUpdateFocusItem ) {
+               int i;
+               RECT rt;
+
+               /* invalidate the focus rectangle */
+               i = ListView_GetNextItem(hWnd, -1,      LVNI_FOCUSED);
+               if( i!=-1 ) {
+                       ListView_GetItemRect(hWnd, i, &rt, LVIR_BOUNDS);
+                       InvalidateRect(hWnd, &rt, TRUE);
+               }
+       }
+
+       if( wndProcListViewOrig ) 
+               return CallWindowProc(wndProcListViewOrig, hWnd, message, wParam, lParam);
+       else 
+               return 0;
+}
+
+/* Text control window proc - implements close on space */
+LRESULT CALLBACK NHMenuTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
-   int ntop, nRectheight, nVisibleItems;
-   RECT rc, itemrect;
+       switch(message) {
 
-   ntop = SendMessage(hwndList, LB_GETTOPINDEX, 0, 0); /* Top item index. */
-   GetClientRect(hwndList, &rc);                                               /* Get list box rectangle. */
-   nRectheight = rc.bottom - rc.top;                                   /* Compute list box height. */
+       /* close on space */
+       case WM_KEYDOWN:
+               if( wParam==VK_SPACE ) {
+                       PostMessage(GetParent(hWnd), WM_COMMAND, MAKELONG(IDOK, 0), 0);
+               }
+       break;
+
+       }
 
-   SendMessage(hwndList, LB_GETITEMRECT, ntop, (DWORD)(&itemrect)); /* Get current line's rectangle. */
-   nVisibleItems = nRectheight/(itemrect.bottom - itemrect.top);
-   return max(1, nVisibleItems);
+       if( editControlWndProc ) 
+               return CallWindowProc(editControlWndProc, hWnd, message, wParam, lParam);
+       else 
+               return 0;
 }
index c1025b83bbf47080c3e4e8176750ea0530670b42..0ac68ec6b34d142483a16eee995f4f1c0eb37740 100644 (file)
@@ -13,24 +13,5 @@ HWND mswin_init_RIP_window ()
 
 void mswin_display_RIP_window (HWND hWnd)
 {
-       MSG msg;
-       RECT rt;
-
-       GetNHApp()->hMenuWnd = hWnd;
-       GetWindowRect(GetNHApp()->hMainWnd, &rt);
-       MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, FALSE);
-       ShowWindow(hWnd, SW_SHOW);
-       SetFocus(hWnd);
-
-       while( IsWindow(hWnd) && 
-                  GetMessage(&msg, NULL, 0, 0)!=0 ) {
-               if( !IsDialogMessage(hWnd, &msg) ) {
-                       if (!TranslateAccelerator(msg.hwnd, GetNHApp()->hAccelTable, &msg)) {
-                               TranslateMessage(&msg);
-                               DispatchMessage(&msg);
-                       }
-               }
-       }
-
-       GetNHApp()->hMenuWnd = NULL;
-}
\ No newline at end of file
+       mswin_display_text_window (hWnd);
+}
index a83acf985f9a4fb1d3e424977bd8fb9449c3c4d9..527d117832e0f59e580120de99f57a9b4de012c0 100644 (file)
@@ -13,7 +13,10 @@ typedef struct mswin_nethack_text_window {
        TCHAR*  window_text;
 } NHTextWindow, *PNHTextWindow;
 
-BOOL CALLBACK  TextWndProc(HWND, UINT, WPARAM, LPARAM);
+static WNDPROC  editControlWndProc = 0;
+
+BOOL   CALLBACK        NHTextWndProc(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK       NHEditHookWndProc(HWND, UINT, WPARAM, LPARAM);
 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
 static void LayoutText(HWND hwnd);
 
@@ -25,7 +28,7 @@ HWND mswin_init_text_window () {
                        GetNHApp()->hApp,
                        MAKEINTRESOURCE(IDD_NHTEXT),
                        GetNHApp()->hMainWnd,
-                       TextWndProc
+                       NHTextWndProc
        );
        if( !ret ) panic("Cannot create text window");
 
@@ -52,13 +55,12 @@ void mswin_display_text_window (HWND hWnd)
                SetWindowText(GetDlgItem(hWnd, IDC_TEXT_CONTROL), data->window_text);
        }
 
-       GetNHApp()->hMenuWnd = hWnd;
+       GetNHApp()->hPopupWnd = hWnd;
        mapWnd = mswin_hwnd_from_winid(WIN_MAP);
        if( !IsWindow(mapWnd) ) mapWnd = GetNHApp()->hMainWnd;
        GetWindowRect(mapWnd, &rt);
        MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
        ShowWindow(hWnd, SW_SHOW);
-       SetFocus(hWnd);
 
        while( IsWindow(hWnd) && 
                   GetMessage(&msg, NULL, 0, 0)!=0 ) {
@@ -70,10 +72,10 @@ void mswin_display_text_window (HWND hWnd)
                }
        }
 
-       GetNHApp()->hMenuWnd = NULL;
+       GetNHApp()->hPopupWnd = NULL;
 }
     
-BOOL CALLBACK TextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+BOOL CALLBACK NHTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
        HWND control;
        HDC hdc;
@@ -93,6 +95,10 @@ BOOL CALLBACK TextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                SendMessage(control, WM_SETFONT, (WPARAM)mswin_create_font(NHW_TEXT, ATR_NONE, hdc), 0);
                ReleaseDC(control, hdc);
 
+               /* subclass edit control */
+               editControlWndProc = (WNDPROC)GetWindowLong(control, GWL_WNDPROC);
+               SetWindowLong(control, GWL_WNDPROC, (LONG)NHEditHookWndProc);
+
                SetFocus(control);
        return FALSE;
 
@@ -187,3 +193,23 @@ void LayoutText(HWND hWnd)
        MoveWindow(text, pt_elem.x, pt_elem.y, sz_elem.cx, sz_elem.cy, TRUE );
        MoveWindow(btn_ok, pt_ok.x, pt_ok.y, sz_ok.cx, sz_ok.cy, TRUE );
 }
+
+/* Edit box hook */
+LRESULT CALLBACK NHEditHookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+       switch(message) {
+
+       /* close on space */
+       case WM_KEYDOWN:
+               if( wParam==VK_SPACE ) {
+                       PostMessage(GetParent(hWnd), WM_COMMAND, MAKELONG(IDOK, 0), 0);
+               }
+       break;
+
+       }
+
+       if( editControlWndProc ) 
+               return CallWindowProc(editControlWndProc, hWnd, message, wParam, lParam);
+       else 
+               return 0;
+}
diff --git a/win/win32/mnselcnt.uu b/win/win32/mnselcnt.uu
new file mode 100644 (file)
index 0000000..72273d7
--- /dev/null
@@ -0,0 +1,9 @@
+begin 600 mnselcnt.bmp
+M0DWV`````````'8````H````$````!`````!``0``````(``````````````
+M````````````````````@```@````("``(````"``(``@(```,#`P`"`@(``
+M``#_``#_````__\`_P```/\`_P#__P``____````````````````````````
+M________``#_______\``/_P__\/_P``_P````#_``#_\/__#_\``/_P__\/
+M_P``__#__P__``#_\/__#_\``/\`````_P``__#__P__``#_______\``/__
+5_____P``````````````````````
+`
+end
index 19ec2d73c3b735ada7b2f6b457f1f7c686fda256..fbdbde3d4e1372a0f4266222e9810cc18b08ea3d 100644 (file)
@@ -126,11 +126,6 @@ void mswin_player_selection(void)
        logDebug("mswin_player_selection()\n");
 
        /* select a role */
-       flags.initalign = -1;    /* reset */
-    flags.initgend = -1;
-    flags.initrace = -1;
-       flags.initrole = -1;
-  
        if( mswin_player_selection_window( &nRole ) == IDCANCEL ) {
                clearlocks();
                mswin_exit_nhwindows(0);
index dd5ad49a98a2e8996e72dde492ad5ff3682d76f3..263d6b35429fa9841876bed5acb79eb290ee6b22 100644 (file)
@@ -23,6 +23,7 @@
 #define IDD_EXTCMD                      139
 #define IDD_PLAYER_SELECTOR             141
 #define IDB_PETMARK                     143
+#define IDB_MENU_SEL_COUNT              144
 #define IDC_TEXT_VIEW                   1000
 #define IDC_TEXT_CONTROL                1000
 #define IDC_CMD_MOVE_NW                 1001
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        144
+#define _APS_NEXT_RESOURCE_VALUE        145
 #define _APS_NEXT_COMMAND_VALUE         32793
 #define _APS_NEXT_CONTROL_VALUE         1331
 #define _APS_NEXT_SYMED_VALUE           110
index 805c2f204566001044c6a3fde2b9a7f602e18618..5b47161ed713ecad40fd453a363be20a7a8890be 100644 (file)
@@ -38,7 +38,7 @@ typedef struct mswin_nhwindow_app {
        HINSTANCE   hApp;
        HWND            hMainWnd;
        HACCEL          hAccelTable;
-       HWND            hMenuWnd;       /* menu window in the selection process */
+       HWND            hPopupWnd;      /* current popup window  */
 
        MSNHWinData windowlist[MAXWINDOWS];
 
index a85a383b50d2ea591da9b7887985546530536825..e322fb743e7f2ef19069c8e0b6df119ed3ecf24f 100644 (file)
@@ -51,7 +51,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
        _nethack_app.hApp = hInstance;
        _nethack_app.hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WINHACK);
        _nethack_app.hMainWnd = NULL;
-       _nethack_app.hMenuWnd = NULL;
+       _nethack_app.hPopupWnd = NULL;
        _nethack_app.bmpTiles = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TILES));
        if( _nethack_app.bmpTiles==NULL ) panic("cannot load tiles bitmap");
        _nethack_app.bmpPetMark = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_PETMARK));
@@ -91,7 +91,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
        }
        GetModuleFileName(NULL, wbuf, BUFSZ);
        argv[0] = _strdup(NH_W2A(wbuf, buf, BUFSZ));
-       
+
        pcmain(argc,argv);
 
        moveloop();
index 90dc3828fd8ab487da0fc2f7de392dcf53ce88f5..8c85b6933744c19c1e465fe5f1ce9325ff76d626 100644 (file)
@@ -108,10 +108,8 @@ BEGIN
 END
 
 IDD_NHTEXT DIALOGEX 0, 0, 172, 178
-STYLE DS_SETFOREGROUND | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | 
-    WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+STYLE DS_SETFOREGROUND | WS_POPUP | WS_THICKFRAME
 EXSTYLE WS_EX_STATICEDGE
-CAPTION "Text"
 FONT 8, "MS Sans Serif"
 BEGIN
     DEFPUSHBUTTON   "OK",IDOK,54,163,50,14
@@ -122,7 +120,7 @@ END
 IDD_MENU DIALOGEX 0, 0, 187, 153
 STYLE WS_POPUP | WS_CLIPSIBLINGS | WS_THICKFRAME
 EXSTYLE WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT | WS_EX_STATICEDGE
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
 BEGIN
     DEFPUSHBUTTON   "OK",IDOK,7,132,50,14,BS_FLAT
     PUSHBUTTON      "Cancel",IDCANCEL,130,132,50,14,BS_FLAT
@@ -222,6 +220,7 @@ IDB_TILES               BITMAP  DISCARDABLE     "tiles.bmp"
 IDB_MENU_SEL            BITMAP  DISCARDABLE     "mnsel.bmp"
 IDB_MENU_UNSEL          BITMAP  DISCARDABLE     "mnunsel.bmp"
 IDB_PETMARK             BITMAP  DISCARDABLE     "petmark.bmp"
+IDB_MENU_SEL_COUNT      BITMAP  DISCARDABLE     "mnselcnt.bmp"
 
 /////////////////////////////////////////////////////////////////////////////
 //