NB. Sets up J as a hot-link DDE server.
NB.
NB. The client sends J sentences for execution. The result is returned
NB. in clipboard format.
NB.
NB. The link is a hot-link, though data will only change after
NB. the client sends a J sentence to execute.
NB.
NB. The service name is: jserver
NB.
NB. Any number of topic/items are supported.
NB.
NB. You can invoke J with this file as the initial file specified
NB. in the command line. No other scripts are required.
NB.
NB. The incoming and outgoing messages are displayed.
NB.
NB. Method:
NB.
NB. Load J and run this script
NB.   (you can set up an icon/shortcut to do this)
NB. From the client, issue a ddestart advise, with any topic and item
NB. From the client, issue a ddepoke for this topic and item, with the
NB.   data being an executable J sentence
NB. If the topic/item is not in the advise loop, J makes no response
NB. If data is 'close', J responds 'done' and the topic/item is closed
NB. If data is 'exit', J responds 'done' and closes all topics
NB. If data is 'off', J responds 'done' and terminates
NB. Otherwise, J executes the sentence, and returns result in a ddeadvise
NB.   message. If execution fails, response is: 'unable to execute: ',data

TAB=: 9{a.
LF=: 10{a.
FF=: 12{a.
CR=: 13{a.
CRLF=: 13 10{a.
EAV=: 255{a.

delay=: 6!:3
empty=: (i.0 0)"_
erase=: 4!:55
nameclass=: 4!:0
signoff=: 2!:55

wd=: 11!:0

NB. wdhandler
NB. runs in form locale
NB. sets global event data: wdq
NB. runs first found of: form_handler, form_event, form_default,
NB. with temporary global event variables from wdq
wdhandler=: 3 : 0
wdq=: wd 'q'
val=. {:"1 wdq
ndx=. 1 i.~ 3 = 4!:0 [ 3{.val
if. 3>ndx do.
  nms=. {."1 wdq
  (nms)=: val
  fn=. >ndx{val
  try. fn~0
  catch.
    err=. LF,,LF,.}.;._2 [ 13!:12''
    wdinfo 'wdhandler';'error in: ',fn,err
  end.
  4!:55 nms
end.
empty''
)

NB. clipfmt
clipfmt=: 3 : 0
NB. format array of rank 0 1 or 2 for clipboard.
NB. columns are separated by TAB, rows by CRLF.
t=. 3!:0 y.
if. 2=t do.
  y=. ,y.,"1 CRLF
elseif. 32<:t do.
  y=. ,&TAB @ ": &.>y.
  y=. ;,&CRLF@}: &.><@;"1 y
elseif. 1 do.
  y=. ;,&CRLF @ ": &.><"1 y.
  y=. '-' (I. y='_') } y
  y=. TAB (I. y=' ') } y
end.
y
)

NB. display form:
WPSERVER=: 0 : 0
pc server;pn "J Server";
xywh 4 4 115 11;cc e0 edit ws_border rightmove;
xywh 4 18 160 40;cc e1 editm ws_border rightmove bottommove;
xywh 130 3 34 11;cc cancel button;cn "Close";
pas 4 4;pcenter;
rem form end;
)

NB. functions to write to controls:
write0=: 3 : 0
wd 'set e0 *',y.
)

write1=: 3 : 0
y=. 1 1}. _1 _1}. ": <y.
y=. }.,LF,"1 y
wd 'set e1 *',y
)

NB. dde advise
wdadvise=: 3 : 0
't i d'=. y.
d=. clipfmt d
wd 'ddeadvise ',t,' ',i,' *',d
)

NB. jserver
jserver=: 3 : 0

NB. set service name: jserver
try. wd 'reset;ddename jserver;'
catch. end.

NB. set up topic;item table:
topitem=: i.0 2

NB. display controls:
wd WPSERVER
j=. FIXFONT
font=. j,(0 e. #j)#'Terminal 10 oem'
wd 'setfont e0 ',font
wd 'setfont e1 ',font
wd 'pshow'
)

NB. event handlers:

server_close=: signoff
server_break=: signoff
server_cancel_button=: signoff

sys_ddestart=: 3 : 0
topitem=: ~. topitem,systopic;sysitem
write0 'ddestart ',systopic,' ',sysitem
)

sys_ddepoke=: 3 : 0
write0 sysdata

if. -. (systopic;sysitem) e. topitem do. return. end.

if. sysdata -: 'close' do.
  topitem=: topitem -. systopic;sysitem
  wdadvise systopic;sysitem;'done'
  
elseif. sysdata -: 'exit' do.
  topitem=: i.0 2
  wdadvise systopic;sysitem;'done'
  
elseif. sysdata -: 'off' do.
  wdadvise systopic;sysitem;'done'
  delay 1
  signoff''
  
elseif. 1 do.
  try. val=. (3 : sysdata) ''
  catch. val=. 'unable to execute: ',sysdata end.
  wdadvise systopic;sysitem;<val
  write1 val
  
end.
)

jserver''
