home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 5 / ctrom5b.zip / ctrom5b / PROGRAM / ASM / ALIB30B / PULDOWN1.ASM < prev    next >
Assembly Source File  |  1994-10-15  |  22KB  |  858 lines

  1.     page    66,132
  2. ;******************************** PULDOWN1.ASM *******************************
  3.  
  4. LIBSEG           segment byte public "LIB"
  5.         assume cs:LIBSEG , ds:nothing
  6.  
  7. ;----------------------------------------------------------------------------
  8. .xlist
  9.     include  mac.inc
  10.     include  common.inc
  11. .list
  12. ;----------------------------------------------------------------------------
  13.     extrn    draw_box:far
  14.     extrn    save_window:far
  15.     extrn    display_string_fill:far
  16.     extrn    key_if_ready:far
  17.     extrn    restore_window:far
  18.     extrn    box_shrink:far
  19.  
  20.     extrn    posn_to_adr:near
  21.     extrn    $put_crt_chr:near
  22.     extrn    $put_crt_blk:near
  23.  
  24.     extrn    lib_info:byte
  25.     extrn    breakflag:byte
  26.     extrn    bar_hotkey_color:byte
  27.     extrn    bar_text_color:byte
  28.     extrn    bar_select_color:byte
  29.     extrn    submenu_text_color:byte
  30.     extrn    submenu_select_color:byte
  31. ;----------------------------------------------------------------------------
  32.  
  33. ;
  34. ; m_flag equates
  35. ;
  36. m_saved        equ    80h        ;screen data under menu saved
  37. ;
  38.  
  39. comment 
  40. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MENU   )
  41. MENU_SYSTEM - Menu bar display and decode of user selection
  42. ;
  43. ; inputs:  ds:bx - pointer to info structure see COMMON.INC
  44. ;          ah - control flags (see below)
  45. ;    bar_save        equ    80h    ;save display data under bar
  46. ;    bar_restore    equ    40h    ;restore display data under bar before exit
  47. ;    bar_display    equ    20h    ;display the menu bar
  48. ;    wait_valid_key    equ    10h    ;wait forever till valid key found
  49. ;    return_bad_key    equ    08h    ;wait for key and return unknown keys
  50. ;    no_mouse_sim    equ    04h    ;do not simulate mouse with arrow keys
  51. ;
  52. ; output:  cl=0   ax=don't care (none key process occurred)
  53. ;       cl=1   ax=process ptr
  54. ;       cl=2   ax=key (unknown key press)
  55. ;       cl=3   ax=click row/column (unknown mouse click)
  56. ;       cl=4   ax=key (abort key pressed)
  57. ;* * * * * * * * * * * * * *
  58. 
  59. ;---------------------------
  60. pm_input_flags db      0
  61. ;---------------------------
  62.     PUBLIC    MENU_SYSTEM
  63. MENU_SYSTEM    PROC    FAR
  64.     apush    bx,si,di,bp,ds,es
  65.     mov    pm_input_flags,ah
  66. ;
  67. ; check if initial setup needed
  68. ;
  69. pm_1:    test    [bx.m_flag],m_saved    ;check if screen saved
  70.     jnz    pm_4            ;jmp if screen saved already
  71.     test    ah,bar_save        ;check if screen save requested
  72.     jz    pm_4            ;jmp if screen save not needed
  73.     call    menu_save
  74. pm_4:    test    pm_input_flags,bar_display ;check if menu bar display needed
  75.     jz    pm_12            ;jmp if no display needed
  76. ;
  77. ; display the menu bar
  78. ;
  79. pm_10:    call    display_menu_bar
  80.     test    pm_input_flags,wait_valid_key+return_bad_key
  81.     jnz    pm_12            ;jmp if wait for key wanted
  82. ;
  83. ; no key wait flags are set, so exit now
  84. ;
  85.     mov    cl,0
  86.     clc
  87.     jmp    pm_exit
  88.         
  89. pm_12:    cmp    [bx.m_selected_main],0    ;check if any selections active
  90.     jne    pm_20            ;jmp if selection has been made
  91. ;
  92. ; no selections have been make on the main menu, wait for key
  93. ;
  94.     call    menu_key        ;wait for key
  95.     cmp    cl,0            ;main selection key
  96.     jne    pm_40            ;jmp if not selection type key
  97.     mov    [bx.m_selected_main],si ;save selection
  98.     cmp    [si.e_count],0        ;check if any submenu entries
  99.     je    pm_70            ; jmp if no submenu (do process)
  100.     jmp    pm_10            ;go display selection
  101. ;
  102. ; a main menu selection has occured, check if submenu available
  103. ;
  104. pm_20:    mov    si,[bx.m_selected_main] ;get selected menu item info
  105.     cmp    [si.e_count],0        ;check number of submenu items
  106.     jne    pm_30            ;jmp if submenu display needed
  107. ;
  108. ; a main menu selection has occurred, no submenu exists, wait for key
  109. ;
  110.     call    menu_key
  111.     cmp    cl,1
  112.     ja    pm_40            ;jmp not selection key
  113.     cmp    al,0dh
  114.     je    pm_70            ;jmp if <Enter> key pressed
  115.     cmp    si,[bx.m_selected_main]
  116.     je    pm_70            ;jmp if click or alt-? for selected item
  117. ;
  118. ; this selection must be for a new main menu item, so update & redisplay
  119. ;
  120.     mov    [bx.m_selected_main],si
  121.     jmp    pm_10
  122. ;
  123. ; a submenu is available for selected main entry, display submenu
  124. ;
  125. pm_30:    call    display_submenu
  126.     call    menu_key        ;wait for key
  127.     call    restore_window
  128.     cmp    cl,2            ;was key a submenu selection key
  129.     jne    pm_36            ;jmp if not submenu selection key
  130.     cmp    al,0dh
  131.     je    pm_70            ;jmp if <Enter> key pressed
  132.     cmp    si,[bx.m_selected_sub]
  133.     je    pm_70            ;jmp if click or alt-? for selected item
  134. ;
  135. ; a new submenu item has been selected, update data and redisplay
  136. ;
  137.     mov    [bx.m_selected_sub],si
  138.     jmp    pm_10
  139. ;
  140. ; a non-submenu key was found while submenu displayed, what is it?
  141. ;
  142. pm_36:    cmp    cl,1            ;check if main menu key
  143.     ja    pm_40            ;jmp if not main menu select
  144. ;
  145. ; a main menu select key occured within a submenu
  146. ;
  147. pm_38:    mov    [bx.m_selected_sub],0
  148.     mov    [bx.m_selected_main],si
  149.     jmp    pm_10
  150. ;
  151. ; an unknown or unexpected key was found, is it an abort key?
  152. ;
  153. pm_40:    cmp    cl,3
  154.     jne    pm_60            ;jmp if not abort key
  155.     cmp    al,1bh            ;check for escape
  156.     jne    pm_42            ;  jmp if not escape
  157.     cmp    [bx.m_selected_main],0        
  158.     je    pm_42            ;jmp if <esc> and no selections active
  159.     mov    [bx.m_selected_main],0
  160.     mov    [bx.m_selected_sub],0
  161.     jmp    pm_10            ;go redisplay menu bar
  162. pm_42:    mov    cl,4            ;abort exit code
  163.     mov    [bx.m_selected_main],0
  164.     mov    [bx.m_selected_sub],0
  165.     jmp    pm_exit
  166. ;
  167. ; an unknown key was found and it is not an abort key, does the caller want it?
  168. ;
  169. pm_60:    test    pm_input_flags,return_bad_key
  170.     jz    pm_10            ;jmp if user does not want it
  171.     mov    cl,2            ;setup unknown key return
  172.     cmp    ch,0            ;was it an unknown key
  173.     je    pm_exit            ;jmp if unknown key
  174.     mov    cl,3            ;setup unknown click
  175.     jmp    pm_exit            ;jmp if unknown click
  176. ;
  177. ; a menu item has been selected for execution, return the hit
  178. ;
  179. pm_70:    mov    [bx.m_selected_main],0    ;deselect main
  180.     mov    [bx.m_selected_sub],0    ;deselect sub
  181.     mov    cl,1            ;return hit code
  182.     mov    ax,[si.e_process]    ;return the process info
  183. ;
  184. ; exit states are -  cl=0   ax=don't care
  185. ;             cl=1   ax=process info for key/mouse hit
  186. ;             cl=2   ax=unknown key
  187. ;             cl=3   ax=unknown click location (row/col)
  188. ;             cl=4   ax=abort key if ctrl-c or esc
  189. pm_exit:
  190.     push    cx
  191.     pushf
  192. ;
  193. ; check if area under bar is to be restored
  194. ;    
  195.     test    pm_input_flags,bar_restore    ;check for release memory & cleanup
  196.     jz    pm_exit1              ;jmp if not cleanup time
  197.     call    restore_window
  198. pm_exit1:    
  199.     popf
  200.     pop    cx
  201.     apop    es,ds,bp,di,si,bx
  202.     retf
  203. MENU_SYSTEM    ENDP
  204. ;-----------------------------------------------------------------------------
  205. ; menu_save - save area under menu bar
  206. ;   inputs:  ds:bx - points at menu structure
  207.  
  208. menu_save:
  209.     apush    ax,bx,ds
  210. ;
  211. ; use save_window to save area of screen
  212. ;
  213.     mov    dx,word ptr es:[bx.m_left_column]
  214.     mov    bx,word ptr es:[bx.m_rows]
  215.     xchg    bh,bl
  216.     call    save_window
  217.     apop    ds,bx,ax
  218.     ret
  219.  
  220. ;-----------------------------------------------------------------------------
  221. ; display_menu_bar - display the top menu bar
  222. ;   inputs:  ds:bx - point at menu structure
  223. ;
  224. display_menu_bar:
  225.     apush    ax,bx,ds
  226.     cld
  227. ;
  228. ; compute amount of area for menu bar
  229. ;
  230.     mov    cl,[bx.m_columns]
  231.     sub    ch,ch
  232. ;
  233. ; setup addresses, and clear menu bar area
  234. ;
  235.     mov    dx,word ptr [bx.m_left_column]
  236.     call    posn_to_adr
  237.     mov    ah,byte ptr cs:bar_text_color
  238.         mov     al,' '
  239.     rep    stosw            ;clear the menu bar area
  240. ;
  241. ; setup to display menu
  242. ;
  243.     mov    bp,bx
  244.     add    bp,m_main01        ;point at first menu item
  245. dmb_1:
  246.     mov    dx,word ptr ds:[bp.e_column]
  247.     call    posn_to_adr
  248.     mov    cl,ds:[bp.e_length]
  249.     sub    ch,ch
  250.     mov    si,ds:[bp.e_text_ptr]
  251. ;
  252. ; display first char. as hot key
  253. ;    
  254.     mov    ah,cs:bar_hotkey_color
  255.     lodsb
  256.     call    $put_crt_chr
  257.     dec    cx
  258. ;
  259. ; display remaining char's
  260. ;    
  261.     mov    ah,byte ptr cs:bar_text_color
  262.     cmp    bp,[bx.m_selected_main] ;check if this menu item selected
  263.     jne    dmb_2            ;jmp if not selected
  264.     mov    ah,byte ptr cs:bar_select_color
  265. ;
  266. ; cx=#chars  ds:si=string  es:di=display ah=color
  267. ;    
  268. dmb_2:    call    $put_crt_blk
  269.     add    bp,size menu_entry
  270.     cmp    ds:[bp.e_length],0    ;check if done with display
  271.     jne    dmb_1            ;loop if another entry
  272.     apop    ds,bx,ax
  273.     ret
  274.  
  275. ;-----------------------------------------------------------------------------
  276. ;display_submenu - display a submenu
  277. ;  inputs: ds:bx - point at menu structure
  278. ;
  279. ;------------------------
  280. dsm_bx_sav   dw      0
  281. ;------------------------
  282. display_submenu:
  283.     apush    ax,bx,cx,dx,si,di,bp,ds
  284.     mov    di,[bx.m_selected_main]
  285.     mov    ah,[di.e_sub_length]        ;get length of box
  286.     add    ah,2                ;adjust for box borders
  287.     mov    al,[di.e_count]            ;get number of submenu items
  288.     add    al,2                ;adjust for box border
  289.     mov    cx,ax                ;save    ax
  290.  
  291. ; ch=columns in box  cl=rows in box,
  292. ;
  293.     mov    dx,word ptr [di.e_column]    ;get main selection address
  294.     add    dh,1                ;move down one row
  295.     mov    dsm_bx_sav,bx
  296.     mov    bh,cl                ;rows in box -> bh
  297.     mov    bl,ch                ;columns in box -> bl
  298. ;
  299. ; dx=box address  bh=rows bl=columns
  300. ;
  301.     call    save_window            ;save current window data
  302.     mov    ah,byte ptr cs:submenu_text_color
  303.     mov    al,1                ;select double line box
  304.     call    draw_box
  305.     call    box_shrink
  306.     mov    bp,cs:dsm_bx_sav
  307. ;
  308. ; display the submenu text
  309. ;
  310.     mov    di,[di.e_process]        ;get ptr to first submenu struc
  311. ;
  312. ; check if any selected, and if not select first one
  313. ;
  314.     cmp    ds:[bp.m_selected_sub],0
  315.     jne    dsm_loop            ;jmp if item selected
  316.     mov    ds:[bp.m_selected_sub],di    ;select first item
  317.  
  318. dsm_loop:
  319.     mov    si,[di.e_text_ptr]        ;get text ptr
  320.     mov    ch,0
  321.     mov    cl,bl                ;get window size
  322.     mov    dh,[di.e_row]
  323.     mov    dl,[di.e_column]
  324.     mov    ah,byte ptr cs:submenu_text_color
  325.     cmp    ds:[bp.m_selected_sub],di    ;check if this item selected
  326.     jne    dsm_out                ;jmp if not selected
  327.     mov    ah,byte ptr cs:submenu_select_color
  328. dsm_out:
  329.     call    display_string_fill
  330.     add    di,size menu_entry
  331.     dec    bh                ;decrement item count
  332.     jnz    dsm_loop            ;loop till done
  333.  
  334.     apop    ds,bp,di,si,dx,cx,bx,ax
  335.     ret
  336. ;-----------------------------------------------------------------------------
  337. ;-----------------------------------------------------------------------------
  338. ; key_mouse_wait - wait for key or mouse input
  339. ;   inputs:  ds:bx - points at menu structure
  340. ;   output:  if no carry then dh=row  dl=column of mouse click
  341. ;         if carry    ax=keyboard info.
  342. ;            dx=cursor location
  343. ;         if carry and ax=0 then breakflag is set
  344. ; processing:  1. check the break_flag and exit if set
  345. ;           2. put mouse cursor on screen.
  346. ;           3. track mouse movements
  347. ;           4. return any keypresses or mouse clicks found.
  348. ;           5. remove the mouse cursor at exit
  349. ;-------------------
  350. character_under_cursor    dw    0
  351. cursor_column        db    1
  352. cursor_row        db    1
  353. ;-------------------
  354. key_mouse_wait    proc    far
  355.     apush    bx,ds
  356. kmw_loop:
  357.     shr    byte ptr breakflag,1
  358.     mov    ax,0            ;preload abort code
  359.     jc    kmw_exit        ;jmp if ctrl-break active
  360.     call    KEY_IF_READY        ;get key if pressed
  361.     or    ax,ax
  362.     jnz    kmw_got_key
  363. ;
  364. ; check if mouse click occured
  365. ;
  366. kmw_ck_mouse:
  367.     cmp    cs:lib_info.mouse_present,0
  368.     jne    kmw_mouse_active    ;jmp if mouse is present
  369.     test    cs:pm_input_flags,no_mouse_sim
  370.     jnz    kmw_loop        ;jmp if mouse simulation off
  371. ;
  372. ; there is no mouse present, simulate the mouse cursor
  373. ;
  374.     mov    dx,word ptr cursor_column
  375.     jmp    kmw_cursor_sim
  376.  
  377. kmw_mouse_active:
  378.     push    bx
  379.     mov    ax,0003
  380.     int    33h        ;get mouse status
  381.     or    bx,bx        ;check if any clicks
  382.     pop    bx
  383.     jz    kmw_update    ;jmp if no mouse clicks
  384. kmw_flush_mouse:
  385.     push    bx
  386.     mov    ax,0003
  387.     int    33h
  388.     or    bx,bx
  389.     pop    bx
  390.     jnz    kmw_flush_mouse  ;read mouse till all clicks returned
  391. ;
  392. ; convert pixel row (dx) and pixel column (cx) to character address.
  393. ; Since this is CRT mode 3 or 7 we know their are 8 pixels per char.
  394. ;
  395.     call    pixels_to_adr
  396.     mov    ax,dx        ;move mouse posn -> ax
  397.     clc
  398.     jmp    kmw_exit
  399. ;
  400. ; there isn't any keyboard or mouse activity, update mouse position
  401. ;
  402. kmw_update:
  403.     call    pixels_to_adr        ;get mouse adr dh=row  dl=column
  404. kmw_cursor_sim:
  405.     test    cs:pm_input_flags,no_mouse_show
  406.     jnz    kmw_loop        ;jmp if no mouse cursor needed
  407.     call    posn_to_adr        ;get crt address in es:di
  408.     cmp    character_under_cursor,0
  409.     jne    kmw_update1        ;jmp if mouse on screen
  410. ;
  411. ; this is the first entry, so save char. under cursor and show mouse cursor.
  412. ;
  413.     mov    ax,word ptr es:[di]    ;get screen data
  414.     mov    character_under_cursor,ax ; and save it
  415. ;    or    ah,88h            ;set blink and intensify
  416. ;    xor    ah,33h            ;adjust foreground and background
  417. ;        mov     al,''
  418.     mov    word ptr es:[di],ax
  419.     mov    word ptr cursor_column,dx
  420.     jmp    kmw_loop
  421. ;
  422. ; check if mouse has moved. dx=current mouse adr.  es:di=current display adr
  423. ;
  424. kmw_update1:
  425.     cmp    dx,word ptr cursor_column
  426.     jne    kw_mousing        ;jmp if mouse movement
  427. ;
  428. ; the mouse cursor is on screen, but has not moved, update it's color
  429. ;    
  430.     mov    ax,word ptr es:[di]    ;get present char. under mouse
  431.     apush    es,si,bx
  432.     mov    bx,0
  433.     mov    es,bx
  434.     mov    ah,byte ptr es:46ch    ;get clock setting
  435.     and    ah,06h
  436.     mov    bh,ah
  437.     shl    ah,1
  438.     shl    ah,1
  439.     shl    ah,1
  440.     or    ah,bh
  441.     apop    bx,si,es
  442.     
  443.     mov    word ptr es:[di],ax    
  444.     jmp    kmw_loop        ;jmp if no mouse movement
  445. ;
  446. ; the mouse has moved, update the cursor posn
  447. ;
  448. kw_mousing:
  449.     call    remove_mouse_cursor
  450.     mov    word ptr cursor_column,dx
  451.     jmp    kmw_loop
  452.  
  453. kmw_got_key:
  454.     cmp    [bx.m_selected_main],0
  455.     jne    kmw_got_key1        ;jmp if menu is active
  456.     test    cs:pm_input_flags,no_mouse_sim    ;check if cursor simulation on
  457.     jnz    kmw_got_key1        ;jmp if cursor simulation off
  458.     cmp    al,4dh
  459.     jne    kmw_key1        ;jmp if not right-arrow
  460. ;
  461. ; cursor right
  462. ;
  463.     cmp    dl,79
  464.     jae    kmw_loop        ;jmp if at right edge already
  465.     inc    dl
  466.     jmp    kmw_key_cursor
  467.  
  468. kmw_key1:
  469.     cmp    al,4bh
  470.     jne    kmw_key2        ;jmp if not left-arrow
  471. ;
  472. ; cursor left
  473. ;
  474.     cmp    dl,0
  475.     je    kmw_loop        ;jmp if already at left edge
  476.     dec    dl
  477.     jmp    kmw_key_cursor
  478.  
  479. kmw_key2:
  480.     cmp    al,48h
  481.     jne    kmw_key3        ;jmp if not up-arrow
  482. ;
  483. ; up arrow key
  484. ;
  485.     cmp    dh,0
  486.     je    kmw_loop        ;jmp if already at top
  487.     dec    dh
  488.     jmp    kmw_key_cursor
  489.  
  490. kmw_key3:
  491.     cmp    al,50h
  492.     jne    kmw_got_key1        ;jmp if not down-arrow
  493. ;
  494. ; cursor down
  495. ;
  496.     cmp    dh,cs:lib_info.crt_rows ;check if at bottom already
  497.     jae    kmw_loop        ;jmp if at bottom already
  498.     inc    dh
  499. ;
  500. ; remove cursor & update its position
  501. ;
  502. kmw_key_cursor:
  503.     call    remove_mouse_cursor
  504.     mov    word ptr cursor_column,dx
  505.     cmp    cs:lib_info.mouse_present,0
  506.     je    kmw_loop        ;jmp if no mouse present
  507.     mov    cx,dx
  508.     sub    ch,ch
  509.     shl    cx,1
  510.     shl    cx,1
  511.     shl    cx,1
  512.     sub    dl,dl
  513.     xchg    dl,dh
  514.     shl    dx,1
  515.     shl    dx,1
  516.     shl    dx,1
  517.     mov    ax,4
  518.     int    33h            ;update mouse position
  519.     jmp    kmw_loop
  520.  
  521.  
  522. kmw_got_key1:
  523.     stc
  524. kmw_exit:
  525.     call    remove_mouse_cursor
  526.     apop    ds,bx
  527.     retf
  528. key_mouse_wait    endp
  529. ;-----------------------------
  530. remove_mouse_cursor:
  531.     pushf
  532.     apush    ax,dx,di
  533.     cmp    character_under_cursor,0
  534.     je    rmc_exit        ;jmp if no mouse cursor
  535.     mov    dx,word ptr cursor_column
  536.     call    posn_to_adr
  537.     mov    ax,character_under_cursor
  538.     mov    word ptr es:[di],ax
  539.     mov    character_under_cursor,0
  540. rmc_exit:
  541.     apop    di,dx,ax
  542.     popf
  543.     ret
  544. ;-----------------------------
  545. ; inputs:  dx = pixel row
  546. ;       cx = pixel column
  547. ; output:  dh=crt char row
  548. ;       dl=crt char column
  549. ;
  550. pixels_to_adr:
  551.     shr    dx,1
  552.     shr    dx,1
  553.     shr    dx,1
  554.     shr    cx,1
  555.     shr    cx,1
  556.     shr    cx,1
  557.     mov    dh,cl
  558.     xchg    dh,dl        ;move char. row->dh  move char. column->dl
  559.     ret
  560. ;-----------------------------------------------------------------------------
  561. ; menu_key - processes key press
  562. ;   inputs:  ds:bx - points at menu structure
  563. ;   output:  cl=0 initial main selection key found (click or alt-?)
  564. ;          si=menu structure for selection
  565. ;          if ch=0 then ax=key  dx=loc
  566. ;          if ch=1 then dx=click
  567. ;         cl=1 secondary main selection key. right,left,click,alt-?,enter
  568. ;          si=menu structure for selection
  569. ;          if ch=0 then ax=key    dx=loc
  570. ;          if ch=1 then dx=click
  571. ;         cl=2 submenu selection key. up,down,click,enter
  572. ;          si=menu structure for selection
  573. ;          if ch=0 then ax=key    dx=loc
  574. ;          if ch=1 then dx=click
  575. ;         cl=3 abort key found, ax=key if esc or ctrl-c
  576. ;         cl=4 other key/click
  577. ;          if ch=0 then ax=key    dx=loc
  578. ;          if ch=1 then dx=click
  579. ;
  580. ;
  581. menu_key:
  582.     apush    bx,ds
  583. mk_loop:
  584.     call    key_mouse_wait
  585.     jnc    mk_ck_mouse        ;jmp if mouse activity
  586.     or    ax,ax
  587.     jz    mk_abort        ;jmp if break key
  588. ;
  589. ; the keyboard was used, -ax- has keystroke  001b=esc
  590. ;                         000d=Enter
  591. ;                         014b=left arrow
  592. ;                         014d=right arrow
  593. ;                         0148=up
  594. ;                         0150=down
  595. ;                         0003=control-c
  596. ;
  597.     cmp    ah,0            ;check if normal key
  598.     je    mk_norm_key
  599. ;
  600. ; extended keystroke found, check type
  601. ;
  602.     cmp    al,4dh
  603.     jne    mk_04            ;jmp if not right arrow
  604. ;
  605. ; right arrow key pressed
  606. ;
  607. mk_right:
  608.     cmp    [bx.m_selected_main],0
  609.     je    mk_unknown_key        ;jmp if no main selection yet
  610.     mov    si,[bx.m_selected_main]        ;get current selection
  611.     add    si,size menu_entry
  612.     cmp    [si.e_length],0            ;check if at right end
  613.     je    wrap_right
  614.     jmp    mk_main2_key            ;jmp if new selection (si)
  615. wrap_right:
  616.     lea    si,[bx.m_main01]
  617.     jmp    mk_main2_key            ;jmp with wraped selection (si)
  618. ;
  619. ; extended key decode, not right arrow, check if left arrow
  620. ;
  621. mk_04:    cmp    al,4bh
  622.     jne    mk_06                ;jmp if not left arrow
  623. ;
  624. ; left arrow key was found
  625. ;
  626.     cmp    [bx.m_selected_main],0        ;is right arrow possible
  627.     je    mk_unknown_key            ;jmp if right arrow not expected
  628.     mov    si,[bx.m_selected_main]        ;get current selection
  629.     lea    dx,[bx.m_main01]
  630.     cmp    si,dx
  631.     je    wrap_left            ;jmp if at end
  632.     sub    si,size menu_entry
  633.     jmp    mk_main2_key
  634. wrap_left:
  635.     add    si,size menu_entry
  636.     cmp    [si.e_length],0
  637.     jne    wrap_left
  638.     sub    si,size menu_entry
  639.     jmp    mk_main2_key            ;jmp if new selection (si)
  640. ;
  641. ;extended key decode, not right, not left, check if up arrow
  642. ;
  643. mk_06:    cmp    al,48h
  644.     jne    mk_08                ;jmp if not up arrow
  645. ;
  646. ; up arrow was found. Check if we are expecting up arrow (submenu active)
  647. ;
  648.     cmp    [bx.m_selected_sub],0
  649.     je    mk_unknown_key            ;jmp if up arrow not expected
  650.     mov    si,[bx.m_selected_sub]
  651.     mov    di,[bx.m_selected_main]
  652.     cmp    [di.e_process],si        ;are we at top of selections
  653.     je    wrap_up                ;jmp if at top
  654.     sub    si,size menu_entry
  655.     jmp    mk_sub_key
  656. wrap_up:mov    cl,[di.e_count]            ;get number of submenu items
  657. wrap_up_lp:
  658.     dec    cl
  659.     jz    wrap_up1
  660.     add    si,size menu_entry
  661.     jmp    wrap_up_lp
  662. wrap_up1:
  663.     jmp    mk_sub_key
  664. ;
  665. ;extended key decode, not right, not left, not up, check if down key
  666. ;
  667. mk_08:    cmp    al,50h                ;check if down arrow
  668.     jne    mk_10                ;jmp if not down arrow
  669. ;
  670. ; down arrow key was found
  671. ;
  672.     cmp    [bx.m_selected_sub],0
  673.     je    mk_unknown_key            ;jmp if down arrow not expected
  674. ;
  675. ; check if we are at end of item list by scanning to end
  676. ;
  677.     mov    di,[bx.m_selected_main]
  678.     mov    si,[di.e_process]        ;get ptr to first submenu entry
  679.     mov    cl,[di.e_count]            ;get number of submenu entries
  680. mk_09:    dec    cl
  681.     jz    mk_down1
  682.     add    si,size menu_entry
  683.     jmp    mk_09
  684. mk_down1:
  685.     cmp    si,[bx.m_selected_sub]        ;check if we are at end
  686.     je    mk_down_wrap            ;jmp if at end
  687.     mov    si,[bx.m_selected_sub]
  688.     add    si,size menu_entry
  689.     jmp    mk_sub_key
  690. mk_down_wrap:
  691.     mov    si,[di.e_process]
  692.     jmp    mk_sub_key
  693. ;
  694. ; extended key decode, it is not right,left,up,down, check if main alt-?
  695. ;
  696. mk_10:    lea    si,[bx.m_main01]        ;get ptr to first struc
  697.         mov     cl,[bx.m_options]               ;get number of struc's to scan
  698.     call    hot_key_scan
  699.     cmp    si,0                ;check if key found
  700.     je    mk_12                ;jmp if hot key not main item
  701. ;
  702. ; a main menu hot key was found. check if main is selected
  703. ;
  704.     cmp    [bx.m_selected_main],0
  705.     je    mk_main1_key            ;jmp if this is initial select
  706.     jmp    mk_main2_key
  707. ;
  708. ; extended key decode, it is not right,left,up,down,main alt-?, check if sub alt
  709. ;
  710. mk_12:    cmp    [bx.m_selected_sub],0
  711.     je    mk_unknown_key            ;jmp if sub alt-? not expected
  712.     mov    di,[bx.m_selected_main]
  713.     mov    si,[di.e_process]        ;get top of sub menu list
  714.     mov    cl,[di.e_count]            ;get number of sub menu items
  715.     call    hot_key_scan
  716.     cmp    si,0
  717.     je    mk_unknown_key            ;jmp if key not sub alt-?
  718.     jmp    mk_sub_key            ;jmp if sub hot key found
  719. ;
  720. ; normal key decode start.
  721. ;
  722. mk_norm_key:
  723.     cmp    al,03        ;check for ctrl-c
  724.     je    mk_abort
  725.     cmp    al,1bh
  726.     je    mk_abort    ;jmp if <escape>
  727.     cmp    al,09
  728.     je    mk_right    ;jmp if <tab>
  729.     cmp    al,0dh
  730.     jne    mk_unknown_key    ;jmp if not <enter> key
  731. ;
  732. ; the <enter> key was found, check which mode we are in
  733. ;
  734.     mov    si,[bx.m_selected_sub]
  735.     cmp    si,0        ;check if sub menu selected
  736.     jne    mk_sub_key    ;jmp if this is sub menu selection
  737.     mov    si,[bx.m_selected_main]
  738.     cmp    si,0
  739.     jne    mk_main2_key    ;jmp if this is a main menu selection
  740.     
  741. ;!    jmp    mk_unknown_key
  742. ;
  743. ; Mouse click decode start.
  744. ;
  745. mk_ck_mouse:
  746.     cmp    [bx.m_selected_sub],0
  747.     jne    mk_40            ;jmp if sub menu selected
  748. mk_20:    cmp    dh,[bx.m_top_row]    ;check if correct row for main
  749.     jne    mk_unknown_mouse    ;jmp if not within main range
  750.     mov    si,bx
  751.     add    si,offset m_main01
  752. mk_mouse_lp:
  753.     cmp    [si.e_length],0
  754.     je    mk_unknown_mouse    ;jmp if no click on option
  755.     mov    ah,[si.e_column]
  756.     add    ah,[si.e_length];compute right edge of key
  757.     cmp    dl,ah
  758.     jb    mk_got_mouse    ;jmp if mouse key found
  759.     add    si,size menu_entry
  760.     jmp    mk_mouse_lp    ;loop till mouse decoded
  761. ;
  762. ; a valid mouse click was found.  ds:si points at match structure
  763. ;
  764. mk_got_mouse:
  765.     cmp    [bx.m_selected_main],0
  766.     je    mk_main1_mouse        ;jmp if initial main selection
  767.     jmp    mk_main2_mouse        ;jmp if secondary mouse selection
  768. ;
  769. ; we have a mouse click, and a sub menu is active.
  770. ;
  771. mk_40:    mov    di,[bx.m_selected_main]
  772.     mov    cl,[di.e_count]        ;get number of submenu items
  773.     mov    si,[di.e_process]    ;get ptr to first submenu sturc
  774. mk_submouse_scan:
  775.     cmp    ah,[si.e_row]
  776.     je    mk_subrow_fnd        ;jmp if row found
  777.     dec    cl
  778.     jz    mk_20            ;jmp if row was not found
  779.     add    si,size menu_entry
  780.     jmp    mk_submouse_scan
  781. ;
  782. ; the mouse click was on a possibly correct row, check column
  783. ;
  784. mk_subrow_fnd:
  785.     cmp    al,[si.e_column]
  786.     jb    mk_20            ;jmp if mouse too far left
  787.     mov    cl,[si.e_column]
  788.     add    cl,[si.e_length]
  789.     cmp    al,cl
  790.     ja    mk_20            ;jmp if mouse too far right
  791.     jmp    mk_sub_mouse        ;jmp if submenu mouse hit
  792. ;
  793. ; keyboard exit states
  794. ;
  795. mk_main1_key:
  796.     mov    ch,0
  797.     mov    cl,0
  798.     jmp    mk_exit
  799. mk_main2_key:
  800.     mov    ch,0
  801.     mov    cl,1
  802.     jmp    mk_exit
  803. mk_sub_key:
  804.     mov    ch,0
  805.     mov    cl,2
  806.     jmp    mk_exit
  807. mk_abort:
  808.     mov    ch,0
  809.     mov    cl,3
  810.     jmp    mk_exit
  811. mk_unknown_key:
  812.     mov    ch,0
  813.     mov    cl,4
  814.     jmp    mk_exit
  815.     jmp    mk_exit
  816. ;
  817. ; mouse exit states
  818. ;
  819. mk_main1_mouse:
  820.     mov    ch,1
  821.     mov    cl,0
  822.     jmp    mk_exit
  823. mk_main2_mouse:
  824.     mov    ch,1
  825.     mov    cl,1
  826.     jmp    mk_exit
  827. mk_sub_mouse:
  828.     mov    ch,1
  829.     mov    cl,2
  830.     jmp    mk_exit
  831. mk_unknown_mouse:
  832.     mov    ch,1
  833.     mov    cl,4
  834. mk_exit:
  835.     apop    ds,bx
  836.     ret
  837. ;-------------------------------------
  838. ; scan the menu structure for this key
  839. ;  inputs: ds:si = menu structures (either main or sub)
  840. ;          cl = number of structures to search
  841. ;          ax = key press
  842. ;  output: ds:si = ptr to hit structure, or zero if key not found
  843. ;
  844. hot_key_scan:
  845.     sub    ch,ch
  846. hks_scan_lp:
  847.     cmp    al,[si.e_hot_key]
  848.     je    hks_exit         ;jmp if hot key found
  849.     add    si,size menu_entry
  850.     loop    hks_scan_lp
  851.     mov    si,0
  852. hks_exit:
  853.     ret
  854. ;-----------------------------------------------------------------------------
  855.  
  856. LIBSEG    ENDS
  857.     end
  858.