; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

; NOTE You should not run this version on win98se or lower. It was
; developed on win2k and should be used only in win2k/XP/2003

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

      .486                      ; create 32 bit code
      .model flat, stdcall      ; 32 bit memory model
      option casemap :none      ; case sensitive
  
;     include files
;     ~~~~~~~~~~~~~
      include \masm32\include\windows.inc
      include \masm32\include\masm32.inc
      include \masm32\include\gdi32.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\Comctl32.inc
      include \masm32\include\comdlg32.inc
      include \masm32\include\shell32.inc
      include \masm32\include\oleaut32.inc
      include \masm32\include\msvcrt.inc
      include \masm32\macros\macros.asm
      include \masm32\include\dialogs.inc

;     libraries
;     ~~~~~~~~~
      includelib \masm32\lib\masm32.lib
      includelib \masm32\lib\gdi32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\Comctl32.lib
      includelib \masm32\lib\comdlg32.lib
      includelib \masm32\lib\shell32.lib
      includelib \masm32\lib\oleaut32.lib
      includelib \masm32\lib\msvcrt.lib

      DlgProc       PROTO :DWORD,:DWORD,:DWORD,:DWORD 
      togglecheck   PROTO :DWORD,:DWORD
      CtrlProc      PROTO :DWORD,:DWORD,:DWORD,:DWORD
      generate      PROTO :DWORD
      editcontrol   PROTO :DWORD,:DWORD 
      editcontrolProc PROTO :DWORD,:DWORD,:DWORD,:DWORD 

      checkarray MACRO cnt1,cnt2,spc,lft,top:REQ
        LOCAL idnum,hstep,vstep,lspc,stcnt,var
          idnum = 500
          stcnt = 400
          hstep = 0
          vstep = 0
        REPEAT cnt1
          DlgStatic 0,SS_RIGHT,3,top+vstep,15,8,stcnt
          stcnt = stcnt + 1
            REPEAT cnt2
              DlgCheck 0,0,lft + hstep,top + vstep,8,8,idnum
              idnum = idnum + 1
              hstep = hstep + spc
            ENDM
          vstep = vstep + spc
          hstep = 0
        ENDM
      ENDM

    .data?
      hWnd          dd ?
      hInstance     dd ?
      lpCtrlProc    dd ?
      hLabel        dd ?
      hEdit         dd ?
      hNum          dd ?
      hClose        dd ?

    .code

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

start:
  
      mov hInstance, FUNC(GetModuleHandle,NULL)
      call main
      invoke ExitProcess,eax

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

main proc

    Dialog "Create Character Table", \      ; caption
           "MS Sans Serif",10, \            ; font,pointsize
            WS_OVERLAPPED or \              ; styles for
            WS_SYSMENU or DS_CENTER, \      ; dialog window
            256 + 16 + 8, \                 ; number of controls
            50,50,203,240, \                ; x y co-ordinates
            32768                           ; memory buffer size

    DlgButton "Numbers",   WS_TABSTOP, 21,185,50,13,100
    DlgButton "Upper Case",WS_TABSTOP, 75,185,50,13,101
    DlgButton "Lower Case",WS_TABSTOP,129,185,50,13,102

    DlgButton "Clear All", WS_TABSTOP, 21,200,50,13,103
    DlgButton "Create",    WS_TABSTOP, 75,200,50,13,IDOK
    DlgButton "Close",     WS_TABSTOP,129,200,50,13,IDCANCEL

    DlgButton "?",         WS_TABSTOP,184,6,10,10,104
    DlgStatic 0,SS_LEFT or SS_NOPREFIX,12,8,170,12,110

    checkarray 16,16,10,22,20

    CallModalDialog hInstance,0,DlgProc,NULL

    ret

main endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

DlgProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD 

    LOCAL nrange:DWORD
    LOCAL action:DWORD
    LOCAL ccntr :DWORD
    LOCAL str1  :DWORD
    LOCAL hDC   :DWORD
    LOCAL ps    :PAINTSTRUCT
    LOCAL rct   :RECT

    Switch uMsg
      Case WM_INITDIALOG
        invoke SendMessage,hWin,WM_SETICON,1,
                           FUNC(LoadIcon,NULL,IDI_ASTERISK)
        m2m hWnd, hWin

      ; ---------------------------
      ; set the text for the labels
      ; ---------------------------
        mov nrange, 400
        mov ccntr, 0
        .while nrange <= 415
          mov str1, ustr$(ccntr)
          fn SetWindowText,FUNC(GetDlgItem,hWin,nrange),str1
          add nrange, 1
          add ccntr, 16
        .endw

        mov nrange, 500
        .while nrange <= 755
          invoke SetWindowLong,FUNC(GetDlgItem,hWin,nrange),GWL_WNDPROC,CtrlProc
          mov lpCtrlProc, eax
          add nrange, 1
        .endw

        mov hLabel,FUNC(GetDlgItem,hWnd,110)
        invoke SendMessage,hLabel,WM_SETFONT,FUNC(GetStockObject,SYSTEM_FIXED_FONT),TRUE

        mov hNum,  FUNC(GetDlgItem,hWnd,100)
        mov hClose,FUNC(GetDlgItem,hWnd,IDCANCEL)

        return 1

      Case WM_COMMAND
        Switch wParam
          Case 100
            invoke togglecheck,548, 557     ; numbers
          Case 101
            invoke togglecheck,565, 590     ; upper case
          Case 102
            invoke togglecheck,597, 622     ; lower case
          Case 103
            mov nrange, 500
            .while nrange <= 755
              invoke SendMessage,FUNC(GetDlgItem,hWin,nrange),BM_SETCHECK,BST_UNCHECKED,0
              add nrange, 1
            .endw
          Case 104
            ShellAboutBox hWnd,FUNC(LoadIcon,NULL,IDI_ASTERISK),\
                "Character Table Wizard#Windows Assembler Tool",\
                "Created With MASM32",13,10,"Copyright й MASM32 1998-2004"
          Case IDOK
            invoke editcontrol,hInstance,hWnd 
          Case IDCANCEL
            jmp quit_dialog
        EndSw

      Case WM_PAINT
        invoke FrameWindow,hWin,0,1,0
        invoke FrameWindow,hWin,2,1,1

        invoke FrameGrp,hNum,hClose,4,1,0




      Case WM_CLOSE
        quit_dialog:
         invoke EndDialog,hWin,0
    EndSw

    return 0

DlgProc endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

togglecheck proc first:DWORD,last:DWORD

    LOCAL action    :DWORD

    push esi

    mov esi, first
    .if FUNC(SendMessage,FUNC(GetDlgItem,hWnd,esi),BM_GETCHECK,0,0) == BST_CHECKED
      mov action, BST_UNCHECKED
    .else
      mov action, BST_CHECKED
    .endif
    .while esi <= last
      invoke SendMessage,FUNC(GetDlgItem,hWnd,esi),BM_SETCHECK,action,0
      add esi, 1
    .endw

    pop esi

    ret

togglecheck endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

CtrlProc proc hCtl   :DWORD,
              uMsg   :DWORD,
              wParam :DWORD,
              lParam :DWORD

    LOCAL str1  :DWORD
    LOCAL str2  :DWORD
    LOCAL ctrl  :DWORD
    LOCAL buffer[128]:BYTE
    LOCAL char  [4]:BYTE

    .if uMsg == WM_MOUSEMOVE
      invoke SetFocus, hCtl
      invoke GetDlgCtrlID,hCtl      ; get the control ID number
      sub eax, 500                  ; subtract 500 to get the character value
      mov ctrl, eax                 ; copy it to a variable
      mov str1, ptr$(buffer)        ; get pointer to main buffer
      mov str2, ptr$(char)          ; get pointer to character buffer
      mov eax, str2                 ; copy it to EAX
      mov DWORD PTR [eax], 0        ; write 4 x ascii zero to buffer
      mov edx, ctrl                 ; copy character value to EDX
      MOV BYTE PTR [eax], dl        ; write the character as 1st byte in character buffer

    ; ------------------------------
    ; concantenate the entire string
    ; ------------------------------
      mov str1,cat$(str1,"Ascii ",str$(ctrl)," Hex ",right$(hex$(ctrl),2)," Character ",str2)

    ; -----------------------------------------
    ; display it so user knows the ascii and
    ; hex values and can identify the character
    ; -----------------------------------------
      invoke SetWindowText,hLabel,str1

    .endif

    invoke CallWindowProc,lpCtrlProc,hCtl,uMsg,wParam,lParam

    ret

CtrlProc endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

generate proc Edit:DWORD

    LOCAL pMem  :DWORD
    LOCAL ctrl  :DWORD
    LOCAL cntr  :DWORD
    LOCAL lcnt  :DWORD

    push esi
    push edi

    mov pMem, alloc(1024)
    mov edi, pMem
    mov cntr, 0
    mov ctrl, 500
    mov lcnt, 0

    .data
      leadstring db "  align 4",13,10,"  table_name \",13,10
    .code

    mov esi, OFFSET leadstring
    mov ecx, LENGTHOF leadstring
    rep movsb

    .while cntr <= 255
      .if lcnt == 0
        mov WORD PTR [edi], "  "
        add edi, 2
        mov DWORD PTR [edi], "bd  "
        add edi, 4
        mov BYTE PTR [edi], 32
        add edi, 1
      .endif
      .if FUNC(SendMessage,FUNC(GetDlgItem,hWnd,ctrl),BM_GETCHECK,0,0) == BST_CHECKED
        mov BYTE PTR [edi], 49
        add edi, 1
      .else
        mov BYTE PTR [edi], 48
        add edi, 1
      .endif
      .if lcnt == 15
        mov lcnt, 0
        mov WORD PTR [edi], 0A0Dh
        add edi, 2
        jmp jmpin
      .else
        mov BYTE PTR [edi], ","
        add edi, 1
      .endif
      add lcnt, 1
    jmpin:
      add cntr, 1
      add ctrl, 1
    .endw

    mov BYTE PTR [edi], 0
    invoke SetWindowText,Edit,pMem
    free pMem

    pop edi
    pop esi

    ret

generate endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

editcontrol proc Instance:DWORD,Parent:DWORD

    LOCAL hLib

    fn LoadLibrary,"riched32.dll"
    mov hLib, eax

    Dialog "Character Table", \             ; caption
           "MS Sans Serif",8, \             ; font,pointsize
            WS_OVERLAPPED or \              ; styles for
            WS_SYSMENU or DS_CENTER, \      ; dialog window
            3, \                            ; number of controls
            50,50,250,250, \                ; x y co-ordinates
            1024                            ; memory buffer size

    DlgRichEdit ES_MULTILINE or ES_NOHIDESEL or ES_SUNKEN,3,3,239,200,200
    DlgButton "Copy",  WS_TABSTOP,140,210,40,12,IDOK
    DlgButton "Cancel",WS_TABSTOP,190,210,40,12,IDCANCEL

    CallModalDialog Instance,Parent,editcontrolProc,ADDR Instance

    invoke FreeLibrary,hLib

    ret

editcontrol endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

editcontrolProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD 

    LOCAL hDC:DWORD
    LOCAL cr :CHARRANGE

    .if uMsg == WM_INITDIALOG
      invoke SendMessage,hWin,WM_SETICON,1,
                         FUNC(LoadIcon,NULL,IDI_APPLICATION)
      invoke GetDlgItem,hWin,200
      mov hEdit, eax
      invoke SendMessage,hEdit,WM_SETFONT,
                         FUNC(GetStockObject,SYSTEM_FIXED_FONT),TRUE
      invoke generate,hEdit
      mov eax, 1
      ret

    .elseif uMsg == WM_PAINT
      invoke FrameCtrl,hEdit,1,1,1

    .elseif uMsg == WM_COMMAND
      .if wParam == IDOK
        mov cr.cpMin, 0
        mov cr.cpMax, -1
        invoke SendMessage,hEdit,EM_EXSETSEL,0,ADDR cr
        invoke SendMessage,hEdit,WM_COPY,0,0
        jmp quit_dialog

      .elseif wParam == IDCANCEL
        jmp quit_dialog
      .endif

    .elseif uMsg == WM_CLOSE
      quit_dialog:
       invoke EndDialog,hWin,0

    .endif

    xor eax, eax
    ret

editcontrolProc endp

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

end start