NB. popup menu
NB. built from project: ~Source\api\menu\menu
NB. menu - Win32api popup menu
NB.
NB. defines wdmenu - create a popup menu
NB.
NB. form:  [xypos] wdmenu selections
NB.
NB. if xypos is not given, the menu is placed on the current form.
NB.
NB. <selections> is a boxed matrix of up to 4 columns,
NB. or a boxed vector or character string:
NB.   - a boxed vector is treated as a 1-column boxed matrix
NB.   - a character string is cut on its first element.
NB.
NB. The columns are:
NB.   0 = selection texts
NB.   1 = options (see below, default 0)
NB.   2 = callback verb (default none)
NB.   3 = callback verb argument (default '')
NB.
NB. options may be either an integer sum of:
NB.   1 = if checked
NB.   2 = if grayed
NB. or may itself be a 2-column boxed matrix, in which case it is
NB. treated as a submenu.
NB.
NB. The result is _1 on cancel, otherwise it is the result of the
NB. callback verb if defined, or one or more integers being the
NB. selection on that menu.
NB.
NB. see examples in system\packages\winapi\menudemo.ijs.
NB.
NB. Written by Oleg Kobchenko <olegyk@spin.vl.net.ua>.
NB. Enhanced by Alex Kornilovski <kornal@idirect.com>.

coclass 'jmenu'



NB. api

MF_CHECKED=: 8
MF_GRAYED=: 1
MF_POPUP=: 16
MF_SEPARATOR=: 2048
TPM_NONOTIFY=: 128
TPM_RETURNCMD=: 256

TPM_CONST=: TPM_NONOTIFY + TPM_RETURNCMD

firstitem=: {. @ > @ {.
cd=: 15!:0

NB. =========================================================
NB. AppendMenu v win32api call
NB. bool=. AppendMenu h;fl;id;str
AppendMenu=: firstitem @ ('user32 AppendMenuA i i i i *c' & cd)

NB. =========================================================
NB. CreatePopupMenu v win32api call
NB. h=. CreatePopupMenu ''
CreatePopupMenu=: firstitem @ ('user32 CreatePopupMenu i' & cd)

NB. =========================================================
NB. TrackPopupMenu v win32api call
NB. id=. TrackPopupMenu h;fl;x;y;0;(".wd'qhwndp');<,0
TrackPopupMenu=: firstitem @ ('user32 TrackPopupMenu i i i i i i i *i' & cd)

NB. =========================================================
NB. DestroyMenu v win32api call
NB. bool=. DestroyMenu h
DestroyMenu=: firstitem @ ('user32 DestroyMenu i i' & cd)


NB. menu

submsk=: (1: < #&>) # ]

NB. =========================================================
NB. createmenu v create menu, returning handles
NB. x. = offset, blocksize
createmenu=: 4 : 0
assert r=. h0=. CreatePopupMenu''
'off blk'=. x.
for_i. i.#y. do.
  n=. off + i + 1
  'str opt'=. 2 {. i { y.
  if. 0 < L. opt do.
    r=. r, h1=. (n * blk) createmenu opt
    assert AppendMenu h0;MF_POPUP;({.h1);str
  else.
    if. ''-:str do.
      fl=. MF_SEPARATOR
    else.
      opt=. 2 2 #: {.opt,0
      fl=. +/ opt * MF_GRAYED, MF_CHECKED
    end.
    assert AppendMenu h0;fl;n;str
  end.
end.
r
)

NB. =========================================================
NB. countmenu
countmenu=: 3 : 0
r=. #y.
y=. submsk {:"1 y.
while. #y do.
  y=. ;y
  r=. r >. #y
  y=. submsk {:"1 y
end.
r
)

NB. =========================================================
NB.*wdmenu v provide a pop-up menu
wdmenu=: 3 : 0
'' wdmenu y.
:
sel=. x.
val=. y.
if. 0 e. #sel do.
  if. #wd 'qp' do.
    p=. wd 'qformx'
  else.
    smselact_jijs_''
    p=. wd 'qformx'
  end.
  sel=. +/ 1 0.25 * _2 [\ 0 ". p
end.
'x y'=. <. sel
if. 0 = L.val do.
  val=. <;._1 val
end.
if. 1=#$val do. val=. val ,. <0 end.
blk=. 1 + countmenu val
h=. (0,blk) createmenu val
ph=. 0 ". wd 'qhwndx'
r=. TrackPopupMenu ({.h);TPM_CONST;x;y;0;ph;<,0
DestroyMenu &> |. h
if. r <: 0 do. _1 return. end.
r=. <: blk #. inverse r
x=. (}: r ,each 1), <{:r
'v w'=. 2 3 { (x {:: val), 3#a:
if. #v do. v~w else. ((1=#r) }. #r) $ r end.
)

NB. =========================================================
wdmenu_z_=: wdmenu_jmenu_
