ÒUS<US<Œ& Pp& US<( 0 ¤ Hè0p„˜¬ÀÔ\H,Dx” ”( Dl päTôH è|dt"x$ÐH:„ÌJŒ XkL ¤‹>´Ét(àdŒå´@ç¸øèÈÀí]ÀJÔS”ž¨¢D9ìÛ¨e”A¬D`, q¸@ı¼€Ä\ÜÌlQHô<;˜ÔX8 d h À4;ôºì¶àq€¿`1”Æô÷” ˆœ $ðÆ×ð˜pü‰ää™ ˆQŒî|  ( ÞHìðC)/'C, C' [6] [7] ¦ EnumWindows [8] [9] P•wcall 'W_CreateFilter' ('EnumWindows' 'HH,•first •warg') [10] H [11] K•wcall 'EnumWindows' P 0 ¦õ HH,•warg [12] K•wcall 'W_DestroyFilter' P ¦ free the pointer [13] [14] ¦ EnumWindowTexts [15] [16] P(ûH)û '' [17] [18] Z256 [19] VZû•tcnul [20] [21] :for I :in âûH [22] P[I]/•wcall 'GetWindowText' (H[I]) V Z [23] :end [24] [25] ¦B1îP •SS C [26] Bú/ 1î P ø.•SS C [27] HB/H [28] [29] õ(1=ûC)/'C1C' ¦ for FFA [30] [31] :if 0=ûH [32] •'* Could not find handle to window with caption: ',FFA C [33] :else [34] :if 1†ûH [35] •'* Using first handle to window with caption: ',FFA C [36] •(âûH),H,[1.5] FFAB/P [37] :end [38] R•WCALL 'SetForegroundWindow' (H[1]) [39] :if ~R [40] •'* SetForegroundWindow failed (why?)' [41] :end [42] :end [43] ì €USXâ':' ¦ lamp after colon? [74] :if (1E)îF ¦ could be a line label? [75] :andif ':'=1DLB (+/^\EîG)E ¦ this takes advantage of the fact that ^/IîJ [76] :andif '¦'=1DLB (Eâ':')E ¦ lamp immediately follows colon [77] :continue ¦ leave this line alone [78] :end [79] :end [80] [81] ¦ Watch out for lamps in quotes [82] [83] :if ((Xî'''"')â1); will save as a matrix' [32] ¦ :end [33] [34] ¦ v(-4’'.APL'ðñUCASE ý4v)v ¦ for ]kedit [35] ¦ bvî'[]' [36] ¦ vDLTB(bå†\b)/v ¦ delete leading [wsid] and trailing [f=] [37] [38] ((f='‘')/f)'+' [39] ((f='ñ')/f)•AV[178] ¦ that's the plus-or-minus symbol [40] añNFILE f ¦ read the file [41] a•AV[ñAV2ANSIâa] ¦ xlate back to APL [42] a(-•tcnl=ý1a)a ¦ remove trailing •tcnl, to avoid trailing blank line [43] [44] ¦ AV2ANSI cycle changes ß (y umlaut) to ý (high minus) [45] ((a=•AV[224])/a)•AV[254] ¦ ((a='ß')/a)'ý' [46] ¦ AV2ANSI cycle changes •AV[255] (modulo) to •AV[180] (looks like modulo) [47] ((a=•AV[180])/a)•AV[255] [48] [49] ¦ :if ú/',#'îv ¦ file component? [50] ¦ ((vî',#')/v)' ' [51] ¦ v•fi v [52] ¦ v'TN',(ô1v),'CN',(ô2v) [53] ¦ :end [54] [55] :if ú/',#'îv ¦ file component? [56] c5 ¦ fake class [57] :else [58] c•NC v ¦ •NC does not fail on invalid names [59] :if 4îc ¦ 4=invalid [60] :orif 1†ûc ¦ too many/few names [61] •'*** Invalid variable name: ',v [62] 0 [63] :end [64] [65] s•SI[;1] ¦ first column of SI [66] s(~sî'õ•><')/s ¦ ditch •SI levels that don't have matching •IDLOC columns [67] usâ']' ¦ how much UCMD crap is there [68] uu*uóûs ¦ or 1 if no ] (non-UCMD) [69] :if uò(ý1†,•IDLOC v)â1 [70] •'*** Shadowed: ',v [71] 0 [72] :end [73] [74] :if cî1 3 ¦ label or function [75] cc'label' '' 'function' [76] •'*** Cannot define <',v,'> as a variable because already defined as a ',c [77] 0 [78] :end [79] :end [80] [81] :if k=0 [82] [83] uv [84] ((u='‘')/u)'+' [85] ((u='ñ')/u)•AV[178] ¦ that's the plus-or-minus symbol [86] p'Don''t know original rank of' [87] pp,•TCNL,•TCNL,' ',u [88] pp,•TCNL,•TCNL,'OK to save as a Matrix?' [89] pp,•TCNL,•TCNL,'Yes for Matrix, No for Vector with newlines, or Cancel for neither' [90] [91] h'#' •wi 'hwndmain' [92] x•wcall 'MessageBox' h p 'DIFF' 'MB_ICONQUESTION MB_YESNOCANCEL' [93] [94] :if x=6 ¦ 6=IDYES [95] k2 [96] :elseif x=7 ¦ 7=IDNO [97] k1 [98] :else ¦ 2=IDCANCEL [99] •'Nothing done' [100] 0 [101] :end [102] [103] :end [104] [105] :if k=2 [106] a[2]1(1,a=•tcnl)•PENCLOSE ' ',a ¦ EV neutral [107] :end [108] [109] •'Saving <',v,'> as a ',k'vector with •TCNLs' 'matrix' [110] [111] :if c=5 [112] ((vî',#')/v)' ' [113] v•fi v [114] a •freplace v [115] •'û = ',ôûa [116] :else [117] õv,'a' [118] •'û',v,' = ',ôûa [119] :end [120] ì ì €US'ð1 1 0 1/ý4c ¦ session window? as opposed to edit window with or [31] z(s’6)û•TCBS ¦ 6 if session, 0 if edit [32] [33] añDEB a [34] U( ý2a)î'/U' '/u' [35] :if U [36] añDEB ý2a [37] :end [38] [39] ¦(ûa)L9 [40] [41] m0 •NL 2 3 ¦ 0=global [42] c0 •NC m ¦ classes [43] [44] :if U [45] u•wcall 'W_Ini' '[DIFF] ULIST' [46] :if u^.=' ' [47] •'ULIST not set; use ]DIFF /ULIST=...' [48] 0 [49] :end [50] u';' Words u [51] e ¦ untie list [52] mWords m [53] :for f :in u [54] ¦ Don't use ñTIEUF because it disturbs ucmd globals [55] tnñFTNUM f [56] :if tn=0 [57] tn•FNUMS,•XFNUMS [58] tn((âûtn)îtn)â0 [59] f •FSTIE tn [60] ee,tn ¦ untie list [61] :end [62] r•FREAD tn,2 ¦ pointers to directories [63] t•FREAD tn,r[2] ¦ char directory of objects (names) [64] mm,Words t [65] t•FREAD tn,r[3] ¦ num directory of objects (nc, comp) [66] cc,t[;1] [67] :end [68] •FUNTIE e [69] u(mâm)=âûm ¦ fn could be in active ws and ufile [70] mu/m [71] cu/c [72] m[2] m [73] :end [74] [75] (ûa)L1 [76] [77] AñUCASE a [78] MñUCASE m [79] [80] Bú/AM ¦ leading or embedded match [81] [82] ¦ Make 'gsm' match 'GetSystemMetrics' [83] [84] tú\M=1A [85] bú/t [86] :if ú/b [87] :for r :in 1A [88] tú\(0 ý10,t)^M=r [89] bú/t [90] :if ~ú/b [91] :leave [92] :end [93] :end [94] BBúb [95] :end [96] [97] (ú/B)L9 [98] [99] mBëm [100] cB/c [101] m(' 'ú.†m)/m [102] L1: [103] t ' ABCDEFGHIJKLMNOPQRSTUVWXYZ‘0123456789' [104] tt,[0.5] ' abcdefghijklmnopqrstuvwxyzñ0123456789' [105] itm [106] mm[i;] [107] cc[i] [108] [109] :if ’ûa [110] v(1+1ûm)þ(AñUCASE m)[;1]â1 ¦ first leading match [111] :else [112] v1 [113] :end [114] [115] mm,' ' [116] mm,' ì'[c] [117] [118] h•wcall 'GetActiveWindow' [119] [120] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d; if undefined, write default to the ini file [121] k•fx [2]'vk ini d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd  z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ ini [122] [123] •wself'fmAutoComplete' •wi 'Create' 'Form' 'Hide' ('caption' '') ('border' 512) [124] •wi 'scale' 3 [125] •wi '‘ahz' (a h z) [126] [127] •wself':ls' •wi 'Create' 'List' ('where' 0 0) ('edge' 0) ('border' 1) ('style' 16 128) [128] •wi 'list' m [129] •wi '‘m' m [130] •wi 'value' (1v) [131] •wi 'color' (256æè255 255 192) [132] ¦•wi 'color' (256æ 224 224 224) [133] ¦•wi 'color' (256æ 248 248 248) [134] •wi 'scale' 3 ¦ font size will be specified in points [135] •wi 'font' (UcmdFont '') [136] z1•wi 'Draw' ('?Text' 'A') [137] x40 ¦ max rows [138] b10 ¦ min rows [139] (r c)ûm [140] zz’(bxr) (10c) ¦ min/max rows/cols [141] u'#' •wi 'units' [142] eöu[3;] [143] •wi 'size' (z+4’e) [144] :if r>x [145] z[2]z[2]+e[2]’•wcall 'GetSystemMetrics' 'SM_CXVSCROLL' ¦ vertical scroll arrow width [146] :end [147] ':' •wi 'size' (z+2 6’e) [148] •wi 'onDblClick' '1 CMDAUTOCOMPLETE ' [149] [150] k':bn1' •wi 'Create' 'Button' 'Hide' ('style' 1) ('onClick' '1 CMDAUTOCOMPLETE ') ¦ ok [151] k':bn2' •wi 'Create' 'Button' 'Hide' ('style' 2) ('onClick' '0 CMDAUTOCOMPLETE ') ¦ cancel [152] ¦ 1=shift 2=ctrl 4=alt [153] k':bnV' •wi 'Create' 'Menu' ('visible' 0) ('shortcut' 'V' 2) ('onClick' '2 CMDAUTOCOMPLETE ') ¦ vars [154] k':bnF' •wi 'Create' 'Menu' ('visible' 0) ('shortcut' 'F' 2) ('onClick' '3 CMDAUTOCOMPLETE ') ¦ fns [155] k':bnO1' •wi 'Create' 'Menu' ('visible' 0) ('shortcut' 'O' 3) ('onClick' '9 CMDAUTOCOMPLETE ') ¦ open Ctrl+Shift+O (APL+Win default) [156] k':bnO2' •wi 'Create' 'Menu' ('visible' 0) ('shortcut' 116 0) ('onClick' '9 CMDAUTOCOMPLETE ') ¦ open F5 (for Rex) [157] [158] •wself':' [159] [160] ¦ Position window [161] [162] z2•wi 'where' ¦ outer size [163] [164] r•wcall 'GetWindowRect' p  ¦ left, top, right, bottom [165] rr[2 1],r[4 3]-r[2 1] ¦ top, left, height, width [166] rrö4û2ûu ¦ chars [167] [168] :if s ¦ session window? [169] ¦ Center on window [170] w0.5’r[3 4]-z [171] :else ¦ edit window [172] ¦ Place next to cursor [173] ¦ This does not work in the session window! [174] c•wcall 'GetCaretPos'  ¦ from left, top [175] cèc ¦ from top, left [176] c[1]c[1]+•wcall 'GetSystemMetrics' 'SM_CYCAPTION' ¦ caption bar height [177] wcö2ûu ¦ to chars [178] ¦w[1]w[1]-z[1]ö2 ¦ vertical center [179] w[2]w[2]+1.5 ¦ a bit to the right [180] :end [181] [182] ww+r[1 2] ¦ current window, from APL app window [183] [184] ¦ KeepOnScreen [185] [186] eworkarea '#' [187] f(w+z) - (e[1 2]+e[3 4]) [188] ww-0f [189] [190] •wi 'where' w [191] [192] k•wi 'Wait' [193] [194] :ELSEIF optî2 3 [195] [196] •wself':ls' [197] t•wi '‘vf' [198] :if t=0 ¦ we have not previously reduced list [199] m•wi 'list' [200] v•wi 'value' [201] :elseif t=opt ¦ same as last time [202] 0 [203] :else ¦ reset list [204] m•wi '‘m' [205] v1 [206] :end [207] (r c)ûm [208] bm[;c]=' ì'[opt] [209] mbëm [210] vb/vóâr [211] v(1++/b)þvâ1 [212] m•wi 'list' m [213] v•wi 'value' (1v) [214] •wi '‘vf' opt [215] [216] :ELSEIF opt=9 ¦ Ctrl+O [217] [218] •wself':ls' [219] m•wi 'list' [220] v•wi 'value' [221] tm[v;] [222] f(ý1t)~' ' [223] k•wcall 'W_Edit' f [224] [225] :ELSE [226] [227] (a h z)':' •wi '‘ahz' ¦ arg, handle, backspaces [228] [229] :if opt ¦ ok [230] m':ls' •wi 'list' [231] v':ls' •wi 'value' [232] tm[v;] [233] zz,(ûa)û•TCBS [234] zz,(ý1t)~' ' [235] :else ¦ cancel [236] ¦ noop [237] :end [238] [239] k':' •wi 'Delete' [240] ¦•wgive 0 ¦ if another Form was in Wait state, this helps to bury it (!) [241] k•wcall 'SetForegroundWindow' h [242] ý1 •INBUF z ¦ ý1=insert after current contents [243] [244] :END [245] [246] 0 [247] [248] L9: [249] [250] k•wcall 'MessageBeep' 0 [251] ý1 •INBUF z ¦ ý1=insert after current contents [252] ì €USûd ¦ easy case: new tie has been created [83] :else ¦ file was already tied; be polite and restore original tie number [84] tn•first d~•CFNUMS [85] kf •CFSTIE tn ¦ if first tie worked, will this always work too? [86] :end [87] n•CFNAMES[•CFNUMSâtn;] [88] L4 [89] [90] L1: ¦ •CFSTIE failed [91] [92] ee,•tcnl,'Error from •CFSTIE: ',(^\•DM†•TCNL)/•DM [93] •1e [94] 0 [95] [96] L4: ¦ Okay, we have tied the file! [97] [98] nDLTB n [99] [100] z•CFSIZE tn [101] (i e)2z ¦ first, 1+last [102] zDEB,'CI15' •FMT z [103] [104] :if i=e ¦ no components? [105] :andif ~•sys[21] ¦ not runtime? [106] ñOUT 'No components in file ',n,' - Tie ',(ôtn),' - Size ',z [107] 0 [108] :end [109] [110] •ELXelx [111] [112] :if 1=ûûC [113] Cý2•FI C [114] qC=0 [115] C[q/â2]q/i,e-1 [116] CC[C] [117] CiCe-1 [118] (i e)C+0 1 [119] :end [120] [121] w•FI UcmdIni 'CFileDoc-Place' '2 5 20 70' [122] v•FI UcmdIni 'CFileDoc-Visible' '1' [123] [124] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [125] [126] ¦ If there are other instances of CFiledoc running, cascade windows a little bit [127] :for •wself :in '#' •wi 'children' [128] :if 'Form'ð•wi 'class' [129] :andif 'fmCFiledoc'ð9•wi 'name' [130] w[1 2]w[1 2]1.5 3+2•wi 'place' [131] :end [132] :end [133] [134] •wself('fmCFiledoc',ôtn) •wi 'Create' 'Form' 'Hide' [135] •wi '‘inifile' f [136] •wi 'caption' ('CFileDoc ',(ôtn),' - ',n,' - Size ',z) [137] •wi 'place' w [138] •wi 'visible' v [139] h' CMDCFILEDOC •wevent' [140] •wi 'onClose' h [141] [142] •wself':mFile' •wi 'New' 'Menu' [143] •wi 'caption' '&File' [144] [145] •wself':mFile.mPeek' •wi 'New' 'Menu' [146] •wi 'caption' '&Peek...' [147] •wi 'shortcut' 'P' 2 [148] •wi 'onClick' " CMDCFILEDOC 'Peek'" [149] [150] •wself':mFile.mExit' •wi 'New' 'Menu' [151] •wi 'caption' 'E&xit' [152] •wi 'shortcut' 'X' 2 [153] •wi 'onClick' "0 0û':' •wi 'Close'" [154] [155] •wself':mView' •wi 'New' 'Menu' [156] •wi 'caption' '&View' [157] [158] •wself':mView.mTime' •wi 'New' 'Menu' [159] •wi 'caption' '&Timestamp' [160] •wi 'shortcut' 'T' 2 [161] •wi 'style' 1 [162] •wi 'value' T [163] •wi 'data' 3 [164] •wi 'onClick' h [165] [166] •wself':mView.mBytes' •wi 'New' 'Menu' [167] •wi 'caption' '&Bytes' [168] •wi 'shortcut' 'B' 2 [169] •wi 'style' 1 [170] •wi 'value' B [171] •wi 'data' 4 [172] •wi 'onClick' h [173] [174] •wself':mView.mDepth' •wi 'New' 'Menu' [175] •wi 'caption' '&Depth' [176] •wi 'shortcut' 'D' 2 [177] •wi 'style' 1 [178] •wi 'value' D [179] •wi 'data' 5 [180] •wi 'onClick' h [181] [182] •wself':mView.mShape' •wi 'New' 'Menu' [183] •wi 'caption' '&Shape' [184] •wi 'shortcut' 'S' 2 [185] •wi 'style' 1 [186] •wi 'value' S [187] •wi 'data' 6 [188] •wi 'onClick' h [189] [190] •wself':bn' •wi 'New' 'Button' [191] •wi 'caption' 'Stop' [192] •wi 'size' 1.25 8 [193] •wi 'style' 2 ¦ 2=cancel [194] •wi 'onClick' 'done1' ¦õ done [195] [196] •wself':l' •wi 'New' 'Label' [197] •wi 'caption' '' [198] •wi 'size' 1 9 [199] •wi 'style' 2 [200] [201] •wself':pb' •wi 'New' 'Progress' [202] •wi 'style' 1 ¦ 1=smooth [203] •wi 'value' 0 (1e-i) 1 0 ¦ 1 in case empty file [204] [205] cw1+2’•first ûôe-1 ¦ component number display width [206] cw4cw ¦ at least 'Comp' [207] [208] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [209] c0 3û0 [210] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [211] ccž((4+5’cwò9)'Component') (1.5+4+5’cwò9 ) 'right' ¦ 2 [212] ccž'Timestamp' 20 'left' ¦ 4 [213] ccž'Bytes' 8 'right' ¦ 5 [214] ccž'ð' (1.5+1) 'right' ¦ 6 [215] ccž'Shape' 8 'right' ¦ 7 [216] ccž'Value' 80 'left' ¦ 8 [217] [218] •wself':' [219] [220] cv0 1 T B D S 1 [221] c[(~cv)/âûcv;2]0 [222] •wi '‘cv' cv [223] [224] •wi '‘tn' tn [225] [226] •wself':lv' •wi 'New' 'Listview' [227] [228] •wi 'columndisplay' c [229] [230] •wi 'scale' 3 ¦ font size will be specified in points [231] •wi 'font' (UcmdFont '') [232] [233] •wi 'where' 0.5 1 [234] •wi 'style' 1 2 4 1024 4096 ¦ 1024=reorder cols 4096=gridlines [235] •wi 'onColClick' h [236] •wi 'onDblClick' h [237] •wi 'onKeyPress' h [238] [239] •wself':' [240] •wi 'onResize' h [241]  CMDCFILEDOC 'Resize' [242] [243] •wself':lv' [244] •wi 'Focus' [245] [246] (i=e)ûL7 ¦ no components? [247] [248] v0 ¦ in case just one component [249] r0 [250] t0 [251] b0 [252] [253] T~T ¦ if /T option, force all components to be different [254] [255] oldii [256] oldv•CFREAD tn,i ¦ read first component, save for flush [257] oldr•CFRDCI tn,i [258] [259] done0 ¦ repeat until done [260] [261] :repeat [262] [263] ':l' •wi 'caption' (,'CI9' •FMT i) [264] ':pb' •wi 'Stepit' [265] ii+1 [266] :if i1 [283] cc,'',ôi-1 [284] :end [285] [286] ¦¦¦ Timestamp [287] t,'I4,,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6û3oldr [288] [289] ¦¦¦ Bytes [290] bDLB,'CI15' •FMT oldr[1] [291] [292] ¦¦¦ Depth [293] dðoldv [294] dôd [295] [296] ¦¦¦ Shape [297] pûoldv ¦ shape [298] kûp ¦ rank [299] p(ôp),(k=0)/'' ¦ format shape [300] [301] ¦¦¦ Value [302] ¦fFFA oldv [303] fmax FFAW oldv [304] f(maxûf)ûf [305] qfâ'û' [306] :if qóûf [307] :andif q1 [476] :orif (ûûv)>2 [477] :orif ^/0 ' 'î•TYPE •enlist v [478] ¦vFFA v ¦ but can get "Line too long" error from W_Edit [479] v•UCMD 'DISPLAY v' ¦ well, it's better than nothing! [480] :end [481] k•DEF "ìn p ",n,•tcnl,"[1] k•WCALL 'W_Edit' n ì" [482] n p v [483] :end [484] [485] :CASE 'RT_Edit' [486] [487] (tn i)b [488] v•CFREAD tn,i ¦ the value [489] vCVR v ¦ simple character (thanks, Roy!) [490] [491] w•FI 'CFileDocPeek-Place' UcmdIni '2 5 20 70' [492] [493] •wself('fmPeek',ôi) •wi 'Create' 'Form' 'Hide' [494] •wi 'caption' ('CFileDoc ',(ôtn),' - Component ',ôi) [495] •wi 'border' 2 16 64 ¦ 2=sizeable 3=modal 16=sys menu 64=max [496] •wi 'limitwhere' 10 30 ¦ minimum size [497] •wi 'onClose' " CMDCFILEDOC 'RT_Close'" [498] •wi 'onResize' " CMDCFILEDOC 'RT_Resize'" [499] [500] •wself':ed' •wi 'New' 'Edit' [501] •wi 'where' 0.75 1 10 30 [502] •wi 'scale' 3 ¦ font size will be specified in points [503] •wi 'font' (UcmdFont '') [504] •wi 'color' (256æ255 255 255) [505] •wi 'style' 4 16 64 2048 4096 ¦ 4=multi-line 16=vscroll 64=hscroll 2048=APL 4096=read-only [506] •wi 'text' v [507] [508] •wi 'Defer' "•wi 'selection' 0" ¦ who knows why Defer is necessary... [509] [510] •wself':bn' •wi 'New' 'Button' [511] •wi 'size' 1.25 9 [512] •wi 'caption' 'Close' [513] •wi 'style' 2 ¦ 1=default (enter key); 2=cancel (escape key)  onClose [514] [515] •wself':' [516] •wi 'where' w ¦ triggers onResize handler [517] k•wi 'Show' ¦ don't Wait; Show permits several peeks [518] [519] :ELSE [520] [521] •'*** Unanticipated CMDCFILEDOC callback! ',ôf •wself •wevent •warg [522] [523] :ENDSELECT [524] ì €US<__ ì CMDCLIPDOC X;A;C;F;H;I;K;L;M;P;S;T;W;Z [1] ¦ Show formats currently available from the Windows clipboard [2] ¦ Use /F= option to return contents of specified format number [3] ¦ Use /* option to display entire contents of all formats [4] ¦ Use /M option to ]DISPLAY the CF_TEXT as a matrix [5] [6] ¦ 06 Apr 2003 Rex Swain, Independent Consultant, www.rexswain.com [7] ¦ 21 Nov 2003 Use FFATC [8] ¦ 26 Mar 2005 Evlevel-neutral [9] ¦ 05 Jul 2005 Added /F= option [10] ¦ 16 Jul 2005 Added /* option [11] ¦ 23 Mar 2006 Added /M option [12] [13] W'#' •wi 'hwndmain' ¦ get the handle for APL [14] K•wcall 'OpenClipboard' W ¦ open the clipboard [15] :if 0=K [16] •'Cannot open clipboard' [17] 0 [18] :end [19] [20] ¦ Handle /F= case [21] [22] F,X ñGETOPT '/F' [23] :if (,1)ð•VI F [24] F1•FI F [25] Z•wcall 'IsClipboardFormatAvailable' F [26] :if Z=0 [27] •'Format not available in clipboard' [28] L9 [29] :end [30] H•wcall 'GetClipboardData' F ¦ get a handle to the clipboard data [31] :if 0=H [32] •'Could not get handle to clipboard data' [33] L9 [34] :end [35] Z•wcall 'GlobalSize' H ¦ get the size of the data [36] P•wcall 'GlobalLock' H ¦ get a far pointer to the memory [37] :if 0=P [38] •'Could not get GlobalLock' [39] L9 [40] :end [41] T•wcall 'W_Mem' (P 82 Z) [42] K•wcall 'GlobalUnlock' H ¦ unlock the memory [43] ñRESULTT [44] L9 [45] :end [46] [47] ¦ Handle /M case [48] [49] :if 1=ûûX ñGETOPT '/M' [50] F1 ¦ 1=CF_TEXT [51] Z•wcall 'IsClipboardFormatAvailable' F [52] :if Z=0 [53] •'CF_TEXT format not available in clipboard' [54] L9 [55] :end [56] H•wcall 'GetClipboardData' F ¦ get a handle to the clipboard data [57] :if 0=H [58] •'Could not get handle to clipboard data' [59] L9 [60] :end [61] Z•wcall 'GlobalSize' H ¦ get the size of the data [62] P•wcall 'GlobalLock' H ¦ get a far pointer to the memory [63] :if 0=P [64] •'Could not get GlobalLock' [65] L9 [66] :end [67] C•wcall 'W_Mem' (P 82 Z) ¦ clipboard text [68] K•wcall 'GlobalUnlock' H ¦ unlock the memory [69] [70] ¦ Convert to a matrix [71] CC~•TCLF ¦ CR,LF to CR [72] CC~•TCNUL ¦ delete possible trailing NUL [73] CC,(•TCNL†ý1C)/•TCNL ¦ make sure it ends with CR [74] Cý1èC ¦ put CRs at start of each line [75] C1(C=•TCNL) •PENCLOSE C ¦ make each line be an item [76] W+/C=•TCHT ¦ num cells in each line [77] CC,((/W)-W)û•TCHT ¦ make each line have same number of cells [78] C•TCHT,C ¦ start with Tab [79] C1•MIX(C=•TCHT)•PENCLOSEC ¦ matrix of cells [80] •UCMD ']DISPLAY C' [81] L9 [82] :end [83] [84] ¦ Handle normal case [85] [86] ¦ F•wcall 'CountClipboardFormats' [87] ¦ but CountClipboardFormats does not include the registered clipboard formats! [88] [89] L1=ûûX ñGETOPT '/*' ¦ show all? [90] [91] M0 5û '' ¦ Format Hex Name Bytes Value [92] F0 [93] :repeat [94] F•wcall 'EnumClipboardFormats' F [95] :if F=0 [96] :leave [97] :end [98] MMž '' [99] I•first ûM [100] M[I;1] ôF [101] M[I;2] D2X F [102] H•wcall 'GetClipboardFormatName' F (80û' ') 80 [103] A•first /H ¦ name [104] :select F [105] :case 1  C'CF_TEXT' [106] :case 2  C'CF_BITMAP' [107] :case 3  C'CF_METAFILEPICT' [108] :case 4  C'CF_SYLK' [109] :case 5  C'CF_DIF' [110] :case 6  C'CF_TIFF' [111] :case 7  C'CF_OEMTEXT' [112] :case 8  C'CF_DIB' [113] :case 9  C'CF_PALETTE' [114] :case 10  C'CF_PENDATA' [115] :case 11  C'CF_RIFF' [116] :case 12  C'CF_WAVE' [117] :case 13  C'CF_UNICODETEXT' [118] :case 14  C'CF_ENHMETAFILE' [119] :else  C'' [120] :end [121] AA,((’ûC)/((’ûA)/' '),'¦ '),C [122] M[I;3] A [123] [124] H•wcall 'GetClipboardData' F ¦ get a handle to the clipboard data [125] :if 0=H [126] S'(Could not get handle)' [127] T'' [128] :else [129] Z•wcall 'GlobalSize' H ¦ get the size of the data [130] SDLB,'CI12' •FMT Z [131] [132] P•wcall 'GlobalLock' H ¦ get a far pointer to the memory [133] :if 0=P [134] T'(Could not get GlobalLock)' [135] :else [136] T•wcall 'W_Mem' (P 82 Z) [137] K•wcall 'GlobalUnlock' H ¦ unlock the memory [138] :end [139] :end [140] :if L ¦ /* [141] •'' [142] •' Format=',(ôF),' Hex=',(D2X F),' Name=',A,' Bytes=',S [143] •'' [144] •FFATC T [145] :else [146] T(•PWûT)ûT ¦ avoid WS FULL [147] TFFATC T [148] M[I;4 5]S T [149] :end [150] :end [151] [152] :if L ¦ /* [153] L9 [154] :end [155] [156] Wë•firstûM [157] WW6 3 4 5 5 [158] WW’ý1 ý1 1 ý1 1 [159] [160] M[;1]W[1]M[;1] [161] M[;2]W[2]M[;2] [162] M[;3]W[3]M[;3] [163] M[;4]W[4]M[;4] [164] W[5]W[5]•PW-(+/þý1W)+5 ¦ 5=one blank before each column [165] M[;5]W[5]M[;5] [166] [167] M((þW)û'-')žM [168] M(W'Format' 'Hex' 'Name' 'Bytes' 'Value')žM [169] [170] •M [171] [172] L9: [173] [174] K•wcall 'CloseClipboard' ¦ close the clipboard [175] ì €US<‘NN ì CMDCOLORMAP A;C;F;Z;fm;i;j;k;r;x;•IO;•wself [1] ¦ Displays a sampler of the 125 colors [2] ¦ General idea and resize technique stolen from Zark's ìColorMap circa 1996 [3] ¦ 15 Jul 2007 Rex Swain, Independent Consultant, www.rexswain.com [4] [5] •IO0 ¦ NOTE! [6] [7] Z1.25 ¦ font size [8] [9] fm'fmColorMap' [10] •wselffm •wi 'Create' 'Form' 'Close' [11] •wi 'caption' 'Color Map' [12] ¦•wi 'visible' 3 [13] •wi 'size' (0.75’ý2'#' •wi 'workarea') [14] •wi 'scale' 0 0 0 51 112 [15] •wi 'font' 'Arial' Z [16] [17] C0 64 128 192 255 [18] F' ', ý5 ý4 ý3 ý3 ý3  ô C ¦ double leading blanks [19] [20] :for i :in â5 [21] :for j :in â5 [22] :for k :in â5 [23] [24] •wself(':l','01234'[i j k]) •wi 'New' 'Label' ('style' 1) ¦ ('border' 1) [25] r5æj k ¦ row [26] •wi 'color' (C[i j k]) (3û255’r<15) [27] •wi 'caption' (1•enlist F[i j k]) [28] •wi 'where' (0.75+2’r) (4+22’i) Z 15 [29] [30] :end [31] :end [32] :end [33] [34] x((1+ûfm)fm •wi 'children'), '.where' [35] x [1] x,[0.1] fm •wi ( 'Ref'),x [36] fm •wi 'data' ('Set' ('font' 'Arial' Z),x) [37] fm •wi 'onResize' '•wi •wi ''data''' [38] [39] k':mEsc' •wi 'Create' 'Menu' ('visible' 0) ('onClick' "0 0û':' •wi 'Close'") ('shortcut' 27 0) [40] [41] fm •WI 'Show' ì C€US<ŸŸ ì CMDD2B D;B;N;•IO [1] ¦ Decimal to Binary [2] ¦ 29 Mar 2007 Rex Swain, Independent Consultant, www.rexswain.com [3] [4] •IO0 [5] [6] Dô•ENLIST D ¦ arg might be numeric in development mode [7] [8] D•FI D [9] N1+21D ¦ numer of binary digits required [10] N2’0.5’N+1 ¦ round up to next even number [11] B•SPLIT í'01'[((/N)û2)çD] [12] B(-N)B [13] ñRESULTB [14] ì €US< ¢¢ ì CMDD2X D;N;X;•IO [1] ¦ Decimal to Hex [2] ¦ 07 Feb 2006 Rex Swain, Independent Consultant, www.rexswain.com [3] [4] •IO0 [5] [6] Dô•ENLIST D ¦ arg might be numeric in development mode [7] [8] D•FI D [9] N1+161D ¦ numer of hex digits required [10] N2’0.5’N+1 ¦ round up to next even number [11] X•SPLIT í'0123456789ABCDEF'[((/N)û16)çD] [12] X(-N)X [13] ñRESULTX ì €US<±± ì CMDDEF A;a;m;r;v [1] ¦ Read a native file and •DEF the function in it [2] ¦ Use after ]DIFF and save from Araxis Merge to get and define changed function [3] ¦ See also: ]ASSIGN [4] ¦ Syntax: ]DEF filename [5] ¦ 25 Apr 2003 Rex Swain, Independent Consultant, www.rexswain.com [6] ¦ 05 May 2003 Correct modulo translation [7] ¦ 03 May 2005 Remove trailing •tcnl, to avoid trailing blank line [8] ¦ 07 Mar 2006 Display error message if •DEF fails [9] [10] ADLTB,ôA [11] ((A='‘')/A)'+' [12] ((A='ñ')/A)•AV[177+•IO] ¦ that's the plus-or-minus symbol [13] vñNFILE A [14] a•AV[ñAV2ANSIâv] [15] [16] a(-•tcnl=ý1a)a ¦ remove trailing •tcnl, to avoid trailing blank line [17] [18] ¦ AV2ANSI cycle changes ß (y umlaut) to ý (high minus) [19] ((a=•AV[224])/a)•AV[254] ¦ ((a='ß')/a)'ý' [20] ¦ AV2ANSI cycle changes •AV[255] (modulo) to •AV[180] (looks like modulo) [21] ((a=•AV[180])/a)•AV[255] [22] [23] ¦ m1(+\1,a=•tcnl) ' ',a ¦ EV2 [24] m[2]1(1,a=•tcnl)•PENCLOSE ' ',a ¦ EV neutral [25] [26] r•DEF m [27] [28] :if 82=•DR r [29] •r [30] :else [31] •'*** Error ',(ôr),' from •DEF on file ',A [32] :end [33] [34] ì USA€US<ì\ì\ ì CMDDIFF A;B;C;D;E;F;I;J;K;M;N;S;T;U;V;W;X;Y;a;c;e;f;h;i;j;k;m;peek;r;t;u;v;w;z;‘elx;•ELX;•WSELF [1] ¦ Compare (show the DIFFerences between) two functions or variables [2] [3] ¦ Syntax: ]DIFF object1 ; object2 [4] ¦ Where each object may be: [5] ¦ Active ws: [6] ¦ FOO ¦ object name (function or variable) [7] ¦ Saved ws: [8] ¦ UTILS FOO ¦ wsid, object name [9] ¦ 9 STUFF FOO ¦ library number, wsid, object name [10] ¦ \EUDORA\ATTACH\UTIL FOO ¦ path, wsid, object name [11] ¦ User command file: [12] ¦ FOO /F=UCMDS ¦ object name and ucmd file to get it from [13] ¦ FOO /F=19 UCMDS ¦ object name and ucmd file with library number [14] ¦ FOO /F ¦ object name, from first ]UFILE file [15] ¦ APL file component: [16] ¦ tn,cn ¦ tie number, component number [17] ¦ tn#cn ¦ tie number, component number [18] ¦ You may use "=" for the second wsid or object name [19] ¦ Example: ]DIFF FOO;UTILS = [20] [21] ¦ Special case syntax with only one name: [22] ¦ ]DIFF object [23] ¦ Compares object to same name in saved version of active ws [24] [25] ¦ Alternate syntax (borrowed from ]COMP) with no semicolon: [26] ¦ ]DIFF object1 object2 [27] ¦ Each object may be one of the following types: [28] ¦ fnname [/F[=cmdfile]] ¦ function [29] ¦ varname [/F[=cmdfile]] ¦ variable [30] ¦ tn,cn ¦ APL file: tie number, component number [31] ¦ tn#cn ¦ APL file: tie number, component number [32] ¦ Examples: [33] ¦ ]DIFF FUN GUN [34] ¦ ]DIFF FUN FUN /F=5 UCMDS [35] ¦ ]DIFF FUN /F=5 UCMDS GUN [36] ¦ ]DIFF FUN /F=5 UCMDS GUN /F=9 MYUCMDS [37] ¦ You may use "=" for the second object name [38] ¦ Note that you may not specify WSIDs when using this no-semicolon syntax [39] [40] ¦ Execute ]DIFF /ERASE occasionally to clean up temp files [41] ¦ (Sorry, this feature does not work with Win98) [42] [43] ¦ You may establish a list of user command files with [44] ¦ ]DIFF /ULIST=file1;file2;file3 [45] ¦ and query it with [46] ¦ ]DIFF /ULIST [47] ¦ Then use [48] ¦ ]DIFF FOO;= /U [49] ¦ /U triggers a search through the list of files established above [50] ¦ for the first object named FOO [51] [52] ¦ This tool automatically sets the Araxis Merge file comparison font to the APL [53] ¦ font specified in APLW.INI section [UCMDSREX]. [54] ¦ Use something like ]DIFF /AMFONT=10.Courier New to return to a non-APL font. [55] [56] ¦ Requires: Araxis Merge 2001, Standard Edition, version 6.0 [57] ¦ or: Araxis Merge Standard Edition, version 6.5 [58] ¦ or: Araxis Merge Standard Edition, version 7.0 (aka 2007) [59] ¦ See [60] [61] ¦ See also ]DEF and ]ASSIGN which will define changed objects in the active ws [62] [63] ¦ To do: [64] ¦ Use XSetPanelTitles with Merge to simplify file names? [65] ¦ Make it work with free WinMerge (www.winmerge.org)? [66] [67] ¦ After similar by JVM and Patrick Parks [68] ¦ 06 Apr 2003 Rex Swain, Independent Consultant, www.rexswain.com [69] ¦ 16 Apr 2003 Added /F support; EVLEVEL-neutral [70] ¦ 25 Apr 2003 Allow ]COMP syntax [71] ¦ 29 Apr 2003 Added /ERASE (such as it is) [72] ¦ 30 Apr 2003 Added /ULIST and /U [73] ¦ 01 May 2003 Maximize AM if "Maximize application on start-up" [74] ¦ 27 Jul 2003 Correct •SI/•IDLOC alignment [75] ¦ 07 Jun 2005 Added one-name compare, active ws vs. saved ws [76] ¦ 06 Oct 2005 Don't allow -options (because filespecs may contain hyphens) [77] ¦ 13 Mar 2006 Prompt to save changes made via Merge (suggested by Patrick Parks) [78] ¦ Use APL font specified in APLW.INI [UCMDSREX] [79] ¦ Added /AMFONT= to reset Araxis Merge font [80] ¦ 10 May 2007 Query MergeXX.Application and remember in APLW.INI [DIFF] [81] ¦ 20 Jul 2009 Work around '.prefs' •wi 'XSave' which sometimes hangs Merge.exe [82] ¦ 11 Aug 2009 Added /PLIST and /P for Pending (intended for remote network files) [83] ¦ 25 May 2010 Activate the Araxis Merge window after launching (for Windows 7) [84] ¦ 02 Jun 2010 Use UcmdFont subroutine [85] ¦ 24 May 2011 Update for Araxis Merge 7 caption [86] [87] ‘elx•ELX [88] [89] ADEB,ôA [90] [91] (Að'::')ûLT ¦ kludge for internal timer callback [92] (Að'')ûL9 ¦ empty arg? [93] [94] ¦E'ActiveObject Merge2000.Application' ¦ Araxis Merge 2001 (version 6.0) [95] ¦E'ActiveObject Merge65.Application' ¦ Araxis Merge version 6.5 [96] ¦E'ActiveObject Merge70.Application' ¦ Araxis Merge version 7.0 (aka 2007) [97] [98] E•wcall 'W_Ini' '[DIFF] ActiveObject' [99] :if E^.=' ' [100] :for V :in '70' '65' '2000' [101] e'Merge',V,'.Application' [102] •'Searching for ActiveObject ',e,' ...' [103] •wgive 0 [104] ¦  Each query takes 0.3 seconds on my system, so remember answer in INI file [105] M'#' •wi 'XInfo' e [106] :if ’1ûM [107] •'Got it, and remembering it in INI file' [108] Ee [109] k•wcall 'W_Ini' ('[DIFF] ActiveObject=',E) [110] :leave [111] :end [112] :end [113] :if E^.=' ' [114] •'*** ]DIFF cannot find MergeXX.Application' [115] 0 [116] :end [117] :end [118] [119] X•FIRST /•wcall 'GetModuleFileName' '' (255û•tcnul) 255 ¦ C:\APLWin50\aplw.exe [120] D(èú\èX='\')/X ¦ C:\APLWin50\ [121] D(D,'Diff1\') (D,'Diff2\') ¦ C:\APLWin50\Diff1\ C:\APLWin50\Diff2\ [122] F2û '' ¦ APL file names [123] S2û '' ¦ ANSI file names [124] [125] CñUCASE A [126] ('/ERASE' ð C)ûL8 ¦ cleanup? [127] ('/ULIST=' ð7C)ûL7 ¦ set ucmd file list [128] ('/PLIST=' ð7C)ûL7 ¦ set ucmd file list [129] ('/ULIST' ð6C)ûL6 ¦ query ucmd file list [130] ('/PLIST' ð6C)ûL6 ¦ query ucmd file list [131] ('/AMFONT='ð8C)ûL5 ¦ reset Merge font [132] [133] :if ';'îA ¦ semicolon makes it easy [134] ¦ V(A†';') A ¦ EV2 [135] V1(1,A=';')•PENCLOSE ';',A ¦ EV neutral [136] (2=ûV)L9,L2 [137] :end [138] V1(1,A=' ')•PENCLOSE ' ',A [139] (3ûV)L1 L2 L3 ¦ how many words [140] [141] L1: ¦ One word [142] VV, DEB •WSID,' =' [143] L2 [144] [145] L3: ¦ Do it the hard way [146] ¦  begin code from CMDCOMP [147] AñMATRIFY A  MûûA  V0 2û''  T  Y1 0 0 0  I1 [148] ñ1: ¦ next word [149] JY[I]  (J>M)ûñ10 ¦ no more words? [150] Y[I+1]J+1  XA[J;]  VVžX ''  TT,0 [151] ñ2: [152] T[I]•NC X  (T[I]î0 2 3)ûñ4 [153] (0=X ñMATIOTA '=')ûñ3 [154] (I=1)ûñ9 [155] X•FIRST V[I-1;1]  A[J;]X  V[I;1] X  ñ2 [156] ñ3: [157] ¦ B'õ_#,:\.'îX  (1îB)ñ9  T[I]1B/2 2 3/10 12 17 [158] ñ8 [159] ñ4: [160] CA[MJ+1;]  (('/'=1C)^'F='ðñUCASE 21C)ñ5 [161] C3C  Y[I+1]J+2  ((,1)ð•VI C)ñ6 [162] Y[I+1]J+3  CC,' ',A[MJ+2;] [163] V[I;2] ' /F=',C ¦ RHS [164] ñ6 [165] ñ5: [166] ¦(((1C)î'/-')^'F'=ñUCASE 11C)ñ7 [167] cñUCASE 2C  (( c)î'/F' '/U')ñ7 ¦ RHS [168] Y[I+1]J+2 [169] ¦ CñUFILES[1;] [170] V[I;2] ' ',c ¦ RHS [171] ñ8 ¦ RHS [172] ñ6: [173] ¦ õ'ñF',(ôI),'ñC'  T[I]13 [174] V[I;2] ' /F=',C ¦ RHS [175] ñ8 [176] ñ7: [177] (T[I]î2 3)ûñ8  •'Undefined object: ',X  0 [178] ñ8: [179] II+1  (Ió3)ûñ1 [180] N1ûûV  (M3)ûñ9 [185] N1ûûV  (N>1)ûñ11 [186] (T[1]†13)ûñ9 [187] AAžA[1;]  N2  TT,•NC A[1;] [188] (~(ý1T)î0 2 3)ûñ9 [189] VVž(A[1;]) '' [190] ñ11: [191] ¦  end code from CMDCOMP [192] [193] VDEB,/V ¦ this is the only thing we take away from all that [194] (2†ûV)ûñ9 [195] [196] L2: [197] [198] v•SI[;1] ¦ first column of SI [199] v(~vî'õ•><')/v ¦ ditch •SI levels that don't have matching •IDLOC columns [200] Uvâ']' ¦ how much UCMD crap is there [201] UU*Uóûv ¦ or 1 if no ] (non-UCMD) [202] [203] C' ' ¦ name classes [204] K0 0 ¦ variable ranks [205] [206] :for I :in â2 ¦õ I [207] [208] vIV [209] ((vî'ì')/v)' ' ¦ might be from ]SYMFIND [210] vDEB v ¦ possibly problem here with LFNs...? [211] e'Problem with argument ',(ôI),' ... ',v,' ... ' [212] •ELX'•e,(^\•DM†•TCNL)/•DM  0' [213] u'' ¦ /F= and ucmd fileid [214] :if '/'îv [215] iý1+vâ'/' [216] uDLB iv ¦ all options [217] vDTB iv [218] :if ~(11u)î'fFuUpP' [219] •e,'Invalid option: ',u [220] 0 [221] :end [222] :end [223] iý1+(èv)â' ' ¦ length of last word (object name) [224] j(-i)v ¦ object name [225] w(-i+1)v ¦ wsid [226] [227] :if I=1 [228] (W J)w j [229] :elseif wð,'=' [230] wW [231] :elseif jð,'=' [232] jJ [233] :end [234] [235] :if ’ûu ¦ ----- get from ucmd file ----- [236] [237] :if (11u)î'fF' ¦ '/F'ð2u [238] [239] :if wú.†' ' [240] •e,'Cannot specify a WSID and /F= too' [241] 0 [242] :end [243] [244] c•UCMD ']UNAMES ',j,' ',u ¦ possible FILE NOT FOUND here [245] c(,c)~' ' [246] :if ú/c •SS '' [247] •e,'Object not found in UCMD file' [248] 0 [249] :end [250] cý1c [251] :if ~cî'ì' [252] •e,'Unanticipated name class: ',c [253] 0 [254] :end [255] [256] :elseif (11u)î'uUpP' ¦ '/U'ð2u ¦ RHS 8/11/09 or '/P' for Pending [257] [258] tñUCASE 11u [259] [260] :if wú.†' ' [261] •e,'Cannot specify a WSID and /',t,' too' ¦ /U or /P [262] 0 [263] :end [264] [265] tt,'LIST' ¦ ULIST or PLIST [266] [267] m•wcall 'W_Ini' ('[DIFF] ',t) ¦ ULIST or PLIST [268] :if m^.=' ' [269] •t,' not set; use ]DIFF /',t,'=...' [270] 0 [271] :end [272] ¦ m(m†';') m ¦ EV2 [273] m1(1,m=';')•PENCLOSE ';',m ¦ EV neutral [274] v1 ¦ not found [275] :for i :in m [276] c•UCMD ']UNAMES ',j,' /F=',i ¦ possible FILE NOT FOUND here [277] c(,c)~' ' [278] :if ú/c •SS '' [279] :continue [280] :end [281] cý1c [282] :if ~cî'ì' [283] •e,'Unanticipated name class: ',c [284] 0 [285] :end [286] v0 ¦ found [287] :leave [288] :end [289] :if v [290] •e,'Object not found in ',t,' files' [291] 0 [292] :end [293] u'/F=',i [294] [295] :else [296] [297] •'Unanticipated u: ',u [298] 0 [299] [300] :end [301] [302] v•UCMD ']UREAD ',j,' ',u [303] [304] :if c='ì' ¦ function [305] k•DEF[2]('rpeek v;',j) 'r•CR •DEF v' ¦õ peek ¦ convert •VR to •CR [306] rpeek v [307] :else ¦ variable [308] K[I](82=•DR v)’ûûv [309] rôv [310] :end [311] [312] C[I]c ¦ remember class [313] [314] :elseif ú/',#'îj ¦ ----- get from APL file ----- [315] [316] c~jî',#' [317] c•FI c\c/j [318] v•FREAD c [319] K[I](82=•DR v)’ûûv [320] rôv [321] C[I]'' ¦ note that we don't know the name or class of this object [322] [323] :elseif w^.=' ' ¦ ----- get from active ws ----- [324] [325] ¦ :if Uò(ý1†,•IDLOC j)â1 [326] ¦ •e,'Shadowed: ',j [327] ¦ 0 [328] ¦ :end [329] [330] :select •FIRST 0 •NC j [331] :case 2 ¦ var [332] C[I]'' ¦ remember class [333] võj [334] v0 •VGET j [335] K[I](82=•DR v)’ûûv [336] rôv [337] :case 3 ¦ fn [338] C[I]'ì' ¦ remember class [339] r0 •CR j [340] :else [341] •e,'Not found in active ws: ',j [342] 0 [343] :end [344] [345] w'Active Ws' ¦ for file name (don't use •wsid -- saved ws could be different) [346] [347] :else ¦ ----- copy from another ws ----- [348] [349] X 'rw peek j;v;•ELX;',j [350] XX, 'rý99' [351] XX, '•ELX"0"' [352] XX, 'r•first j •copy w' [353] XX, ':select r' [354] XX, ':case 1' [355] XX, ' C[I]"ì"' [356] XX, ' r•CR j' [357] XX, ':case 2' [358] XX, ' v',j [359] XX, ' C[I]""' [360] XX, ' K[I](82=•DR v)’ûûv' ¦õ C[I] K[I] [361] XX, ' rôv' [362] XX, ':else' [363] XX, ' ö0' [364] XX, ':end' [365] k•DEF[2]X [366] rw peek j [367] :if 0=ðr [368] ke,"Error from '",j,"' •COPY '",w,"' : " [369] :select r ¦ 1=fn copied 2=var copied [370] :case 0  •k,'Object not found' [371] :case 127  •k,'Duplicate name in objlist ¦ should not get here!' [372] :case ý2  •k,'Object too large for available space' [373] :case ý3  •k,'Name defined as a label; cannot be changed' [374] :case ý4  •k,'Insufficient space in symbol table and workspace too full to expand symbol table' [375] :case ý6  •k,'Insufficient free space to carry out command' [376] :case ý99  •k,(^\•DM†•TCNL)/•DM [377] :else  •e,'Unanticipated •COPY return code: ',ôr [378] :end [379] 0 [380] :end [381] [382] :end [383] [384] ¦ Cook up a good file name [385] m(’ûw)/'[',w,'] ' ¦ prefix with wsid [386] mm,j ¦ add object name [387] mm,(’ûu)/' [',(u~'/'),']' ¦ add /F= or /U= (but a "/" will create a subdirectory) [388] m[(mî'\:/')/âûm]' ' [389] mDEB m [390] mm,(C[I]î'')/'.',ôK[I] ¦ record rank if simple character vector or matrix, 0 otherwise [391] mm,('ì'âC[I])'.var' '.fn' '.fc' [392] [393] (IF)(ID),m ¦ file name (for ]DEF or ]ASSIGN) before fixing deltas [394] ¦•(IF) ¦ display for ]DEF [395] ¦•WGIVE 0 ¦ let that output appear [396] [397] ((m='•')/m)'#' ¦ might be a system variable [398] ((m='‘')/m)'+' ¦ fyi, WSIDs can contain ‘ and ñ symbols! [399] ((m='ñ')/m)•AV[178] ¦ that's the plus-or-minus symbol [400] (IS)(ID),m ¦ save the ANSI version of the file name [401] [402] rñAV2ANSI[•AVâr] ¦ translate [403] [404] r ñNFILE IS ¦ write the file [405] [406] :end [407] [408] •ELX‘elx [409] [410] f'aoDIFF_AM' [411] [412] :if ’ûf •wi 'self' [413] :andif f •wi 'visible' [414] [415] ¦ Merge is already running [416] [417] •wselff [418] •wi 'xActive' 0 [419] •wi 'xActive' 1 ¦ make it the active app (thanks, Patrick!) [420] [421] :else [422] [423] ¦ Create new Merge object [424] [425] •wselff •wi 'Create' ('ActiveObject ',E) ¦ 'ActiveObject Merge65.Application' [426] [427] ¦ Araxis Merge never starts maximized when invoked via ActiveX, even if you [428] ¦ have the "Maximize application on start-up" option checked. We can look at [429] ¦ the AM preferences, but only after AM starts -- and if we maximize it then, [430] ¦ you'll see the maximization happening. Oh well. [431] [432] •wi 'Preferences > .prefs' [433] '.prefs' •wi 'Longs > .longs' [434] e'.prefs.longs' •wi 'xItem' 'clAppMax' [435] :if e [436] •wi 'xMaximized' e ¦ maximize the app (if belatedly) [437] :end [438] [439] ¦ Set APL fonts [440] [441] tUcmdFont 'V' ¦ 'V' for vector [442] [443] '.prefs' •wi 'Strings > .strings' [444] I 'csUnchangedFont' 'csChangedFont' 'csInsertedFont' 'csRemovedFont' ¦ left window [445] II,'csUnchangedFont2' 'csChangedFont2' 'csInsertedFont2' 'csRemovedFont2' ¦ right panel [446] [447] ¦ :for i :in I [448] ¦ '.prefs.strings' •wi 'xItem' i t [449] ¦ :end [450] ¦ [451] ¦ ¦ Save method: Saves preferences to the Registry, and propogates them to [452] ¦ ¦ other running instances of Merge. Without this method, preferences are [453] ¦ ¦ only saved to the Registry when Merge exits. [454] ¦ [455] ¦ '.prefs' •wi 'XSave' [456] [457] c0 ¦ any change? [458] :for i :in I [459] :if ~tð'.prefs.strings' •wi 'xItem' i [460] '.prefs.strings' •wi 'xItem' i t [461] c1 [462] :end [463] :end [464] [465] :if c ¦ only save if any changes [466] '.prefs' •wi 'XSave' ¦ for some reason, this sometimes hangs Merge.exe [467] :end [468] [469] :end [470] [471] ¦ Initiate the file comparison [472] [473] :if '7'îE [474] ¦ Grrr... in version 7.0 they changed the name... [475] •wi 'xTextComparison > .filecomp' [476] :else [477] •wi 'xFileComparison > .filecomp' [478] :end [479] [480] '.filecomp' •wi 'xCompare' (1S) (2S) ¦ Compare! [481] ¦ GiveUserControl: Gives control over the lifetime of the comparison window to [482] ¦ the user. Merge will not automatically close the window when outstanding [483] ¦ automation references are released. [484] '.filecomp' •wi 'xGiveUserControl' ¦ enables tabs for multiple comparisons [485] '.filecomp' •wi 'xVisible' 1 [486] •wi 'xVisible' 1 [487] [488] ¦ActivateWindow 'Araxis Merge - [' ¦ RHS 5/25/10 activate the Merge window (for Windows 7) [489] ¦ActivateWindow 'Araxis Merge' ¦ RHS 5/24/11 Araxis Merge 7 uses caption "... - Araxis Merge" [490] ¦  Arg -- that picked up "Araxis Merge DDE Server" [491] ActivateWindow 'Araxis Merge -' '- Araxis Merge' ¦ RHS 6/06/11 accept either one [492] [493] ¦ Maybe I should creating more than one FileComparison object. [494] ¦ Then could I tell when user does ]diff on the same object? [495] [496] f'fmDIFF_AM' [497] :if ''ðf •wi 'self' [498] •wselff •wi 'Create' 'Form' 'Hide' [499] •wi '‘f' (0û '' '' ' ' (0 0)) ¦ ANSI file, APL file, class, timestamp [500] m0 4û'' '' ' ' (0 0) ¦ ANSI file, APL file, class, timestamp [501] •wi '‘h' ('#' •wi 'hwndmain') [502] ¦t"õ(('#' •wi 'hwndmain')=(•wcall 'GetActiveWindow'))/'CMDDIFF ''::'''" ¦ debug [503] t"õ(('#' •wi 'hwndmain')=(•wcall 'GetActiveWindow'))/'•UCMD '']DIFF ::'''" [504] k'.tm' •wi 'New' 'Timer' ('interval' 500) ('onTimer' t) [505] :else [506] •wselff [507] m•wi '‘f' [508] :end [509] [510] :for I :in â2 [511] fIS [512] h•wcall 'CreateFile' f 'GENERIC_READ' 'FILE_SHARE_READ' 0 'OPEN_EXISTING' 0 0 [513] Assert h†•wcall 'W_Const' 'INVALID_HANDLE_VALUE' [514] t•wcall 'GetFileTime' h    ¦ get create, access, write times [515] Assert 0†•first t [516] k•wcall 'CloseHandle' h [517] t4t ¦ write time [518] u~( f)îm[;1] [519] muëm ¦ if file is already being compared, remove it [520] mmžf (IF) (IC) t [521] :end [522] •wi '‘f' m [523] ¦ •m ¦ debug [524] [525] 0 [526] [527] L5: ¦ /AMFONT [528] [529] t8A ¦ what's after /AMFONT= e.g. '10.Courier New' [530] f'aoDIFF_AM' [531] :if ~''ðf •wi 'self' [532] :andif f •wi 'visible' [533] ¦ Merge is already running [534] •wselff [535] :else [536] ¦ Create new Merge object [537] •wselff •wi 'Create' ('ActiveObject ',E) ¦ 'ActiveObject Merge65.Application' [538] :end [539] •wi 'Preferences > .prefs' [540] •wi '.prefs.Strings > .strings' [541] I 'csUnchangedFont' 'csChangedFont' 'csInsertedFont' 'csRemovedFont' ¦ left window [542] II,'csUnchangedFont2' 'csChangedFont2' 'csInsertedFont2' 'csRemovedFont2' ¦ right panel [543] :for i :in I [544] '.prefs.strings' •wi 'xItem' i t [545] :end [546] '.prefs' •wi 'XSave' [547] f •wi 'Delete' [548] •'Okay, Merge font set to: ',t [549] 0 [550] [551] L6: ¦ /ULIST [552] [553] ¦ '/ULIST' ð6C [554] t1C ¦ ULIST or PLIST [555] u•wcall 'W_Ini' ('[DIFF] ',t) [556] :if uð2û•TCNL [557] •t,' is undefined; to define it, run',•TCNL,' ]DIFF /',t,'=file1;file2;...' [558] :else [559] •'/',t,'=',u [560] :end [561] 0 [562] [563] L7: ¦ /ULIST= [564] [565] ¦ '/ULIST=' ð7C [566] t16C ¦ ULIST or PLIST (in upper case) [567] u7A ¦ what's after /ULIST= [568] k•wcall 'W_Ini' ('[DIFF] ',t,'=',u) [569] •'Okay, /',t,'=',u [570] 0 [571] [572] L8: ¦ /ERASE [573] [574] •"¦ Note this doesn't work with Win98; you''ll have to erase the directories yourself" [575] 3 •CMD •'RMDIR ',(1D),' /S /Q' [576] 3 •CMD •'RMDIR ',(2D),' /S /Q' [577] 0 [578] [579] L9: ¦ Say syntax [580] [581] r'DIFF syntax is:',•TCNL,' ]DIFF object1 ; object2' [582] rr,•TCNL,'For details, see:',•TCNL,' ]DIFF ?' [583] •r [584] 0 [585] [586] LT: ¦ Internal timer callback [587] [588] ¦ •wself is the Timer object [589] ¦ Bail unless we have returned to the APL session [590] [591] ¦  We now do this test in the onTimer expression to avoid •ucmd overhead [592] ¦(('#' •wi 'hwndmain') = (•wcall 'GetActiveWindow'))0 [593] [594] ¦ Check for changed file timestamps [595] [596] F':' •wi '‘f' [597] :for I :in â1ûF [598] (f a c w)F[I;] [599] h•wcall 'CreateFile' f 'GENERIC_READ' 'FILE_SHARE_READ' 0 'OPEN_EXISTING' 0 0 [600] Assert h†•wcall 'W_Const' 'INVALID_HANDLE_VALUE' [601] t•wcall 'GetFileTime' h    ¦ get create, access, write times [602] Assert 0†•first t [603] k•wcall 'CloseHandle' h [604] t4t ¦ write time [605] :if ~tðw [606] [607] ¦ We're not going to ask again, regardless of answer [608] F[I;4] t [609] ':' •wi '‘f' F [610] [611] V(~èú\èf='\')/f ¦ delete leading path [612] BVî'[]' [613] VDLTB(Bå†\B)/V ¦ delete leading [wsid] and trailing [f=] [614] V(^\V†'.')/V ¦ delete trailing extension [615] [616] X'The timestamp on the file' [617] XX,•TCNL,' ',f [618] XX,•TCNL,'which contains ',(('ì'âc)'variable' 'function' 'file component') [619] XX,•TCNL,' ',V [620] XX,•TCNL,'has changed' [621] XX,•TCNL [622] :if cî'ì' [623] XX,•TCNL,'Define changed object in active ws?' [624] :else [625] XX,•TCNL,'Replace changed array in file component?' [626] :end [627] [628] h'#' •wi 'hwndmain' [629] k•wcall 'MessageBox' h X 'DIFF' 'MB_ICONQUESTION MB_YESNOCANCEL' ¦ MB_DEFBUTTON2 [630] :if k=6 ¦ 6=IDYES [631] :if c='ì' [632] •UCMD •']DEF ',a ¦ use APL file name -- DEF will translate [633] :else ¦ cî'' [634] •UCMD ']ASSIGN ',a [635] :end [636] :elseif k=7 ¦ 7=IDNO [637] ¦ noop [638] :else ¦ 2=IDCANCEL [639] :leave [640] :end [641] :end [642] :end [643] [644] ¦ If Merge has been closed, shut down monitoring [645] [646] f'aoDIFF_AM' [647] :if ''ðf •wi 'self' ¦ somebody else deleted it [648] :orif 0=f •wi 'visible' ¦ user closed it ¦ thanks, Patrick! [649] ¦ Use of Defer solves localization problems with •wself [650] '#' •wi 'Defer' "'fmDIFF_AM' •wi 'Delete'" [651] '#' •wi 'Defer' "'aoDIFF_AM' •wi 'Delete'" [652] :end [653] ì €US<0¿S¿S ì b CMDFILEDOC f;B;C;c;cv;cw;D;d;done;e;elx;h;i;k;m;max;n;oldi;oldr;oldu;oldv;p;q;r;S;T;t;tn;U;u;uw;v;W;w;z;•ELX;•wself [1] ¦ File documentation [2] ¦ Syntax: [3] ¦ ]FileDoc tienumber [4] ¦ ]FileDoc filename [5] ¦ Options: [6] ¦ /C=2 5 Do just components 2 through 5 (inclusive) [7] ¦ /C=6 * Do just components 6 through last component [8] ¦ /C=* 6 Do just first component through component 6 [9] ¦ /C=6 Same as /C=* 6 [10] ¦ View options (see also View menu): [11] ¦ /B Bytes [12] ¦ /T Timestamp (YYYY/MM/DD HH:MM:SS) [13] ¦ You may double-click a row to display the value [14] ¦ This uses )EDIT, so it does not work for nested values [15] ¦ Any changes are NOT replaced [16] ¦ You may click on a column heading to sort by that column [17] ¦ Click twice for descending order [18] [19] ¦ 13 Jan 2003 Rex Swain, Independent Consultant, www.rexswain.com [20] ¦ 20 Jan 2003 Auto-detect UCMD files [21] ¦ 18 Feb 2003 Make UCMD column at least 10 wide [22] ¦ 05 Apr 2003 Handle .sf file names; simple component error handler [23] ¦ 25 Apr 2003 Remember window size and position [24] ¦ 02 May 2003 Added use of ]PKGDOC for peeking at PACKAGEs in ucmd files [25] ¦ 06 May 2003 Improved peeking at fns and vars in ucmd files [26] ¦ 06 Jul 2003 Keep already-tied files tied to their original tie numbers [27] ¦ 28 Mar 2004 Handle long file names: translate '9 LongFName' to 'path\LongFName.sf' [28] ¦ 25 Sep 2004 Use font settings in APLW.INI [UCMDSREX] [29] ¦ 26 Mar 2005 Evlevel-neutral [30] ¦ 20 Jun 2005 Added peek for runtime (see FILEDOC.W3) [31] ¦ 18 Sep 2005 Most recent minor change [32] ¦ 14 Oct 2005 New logic for •FSTIE and •XFSTIE attempts [33] ¦ 27 Oct 2005 Handle no components with runtime FileDoc [34] ¦ 12 Feb 2007 Most recent minor change [35] ¦ 14 Jun 2007 If /T option, force all components to be treated as different [36] ¦ 09 Jan 2008 Report wasted bytes in ucmd files [37] ¦ 02 Jun 2010 Use UcmdIni and UcmdFont subroutines [38] [39] ¦ To do: [40] ¦ Print [41] ¦ Better error handler for components (WS FULL, FILE DATA ERROR, etc.) [42] ¦ Need to flag the error, then don't wrap quotes around message, say ? for shape, etc. [43] ¦ File/Open [44] ¦ /C=9999 9999 forces just the last comp ; should we report error instead? [45] ¦ Improve peeking at values that )EDIT won't allow [46] ¦ ]PKGDOC needs to handle multiple instances too [47] ¦ Support for colossal files [48] [49] (’•NC 'b')ûL6 ¦ dummy left arg means callback [50] [51] ¦ 28 Jul 2003 [52] ¦ I gave up trying to allow multiple instances. [53] ¦ First I added a kludge to handle the callbacks: [54] ¦ h•VR 'CMDFILEDOC' [55] ¦ h[(hâ'C')+0 1 2]'‘' ¦ change function name 'CMD' to '‘‘‘' [56] ¦ •wi '‘vr' h [57] ¦ h"õ(0=•NC '‘‘‘FILEDOC')/'0 0û•DEF •WI '':‘vr'''   ‘‘‘FILEDOC •wevent" ¦õ CMDFILEDOC [58] ¦ •wi 'onClose' h [59] ¦ •wi 'onDestroy' "•ERASE '‘‘‘FILEDOC'" [60] ¦ This is yucky, and isn't even sufficient because all of FILEDOC's subroutines [61] ¦ may be needed too. [62] ¦ Another complication is that the user command processor unties any ties made [63] ¦ during the execution of a user command. So I had to introduce code to [64] ¦ detect and recover from that. [65] ¦ Conclusion: User commands need to Wait, not Show. [66] ¦ If you run APL+Win with the "Multiple Execution" option, you can still have [67] ¦ several instances, but only the top one will be enabled. [68] [69] fô•ENLIST f ¦ arg might be numeric in development mode [70] [71] :if f^.=' ' ¦ no argument? [72] ñOUT 'For help, execute',•tcnl,' ]FILEDOC ?' [73] 0 [74] :end [75] [76] max256 ¦ max width of FFA display [77] [78] elx•ELX [79] [80] B•first 1=ûûf ñGETOPT '/B' ¦ bytes [81] T•first 1=ûûf ñGETOPT '/T' ¦ timestamp [82] C f ñGETOPT '/C' ¦ component range [83] fDLTB (^\f†'/')/f ¦ delete all options [84] [85] D1 ¦ depth [86] S1 ¦ shape [87] [88] :if (,1)ð•VI f ¦ just a tie number? [89] tn•first •FI f [90] :if tnî•FNUMS [91] n•FNAMES[•FNUMSâtn;] [92] L4 [93] :elseif tnî•XFNUMS [94] n•XFNAMES[•XFNUMSâtn;] [95] L4 [96] :else [97] ñOUT 'No component file tied to ',ôtn [98] 0 [99] :end [100] :end [101] [102] ¦ '9 FOO' could be an •F file in library 9, or a •XF file named '9 FOO' [103] ¦ in the current directory, so we pretty much just have to experiment. [104] ¦ Since this utility was born in the era of •F files, try that first. [105] [106] ¦ •F file names cannot contain '.' (although their path can) [107] ¦ An •F file may have long names in its path, but not the name itself [108] ¦ •XF and •CF file names may or may not have an extension [109] ¦ An •F file may be tied by •XFTIE [110] ¦ •F files are exclusive-tied on create; others are share-tied [111] ¦ '9 FOO' could be an •F file in lib 9, or a •XF file named '9 FOO' in current dir! [112] ¦ You can 'FOO.SF' •XFCREATE and then later 'FOO' •FTIE, but only if .SF is in upper case! [113] ¦ You can 'FOO.SF' •XFCREATE 1 and then 'FOO' •FSTIE 2 and have the same file tied twice! [114] ¦ If a file is tied already, you can tell whether it's a share or exclusive tie by trying [115] ¦ to rename it to itself; if that fails, it's a share tie. [ELE] [116] [117] e'' ¦ error message(s) [118] [119] m(~è<\èfî'\:')/f ¦ filename[.ext] [120] ('.'îm)ûL2 ¦ skip the •FSTIE attempt if the file has an extension [121] [122] ¦ Try •FSTIE [123] [124] d•FNUMS [125] tn•first (â999)~d,•XFNUMS ¦ remember, •F and •XF share pool of tie numbers [126] •ELX'',ôL1 [127] f •FSTIE tn [128] •ELXelx [129] ¦ Okay, it worked; 2 possibilities: new tie, or re-tied to a different tie number [130] ¦ Assert ~•FNUMSðd [131] ¦ Assert (û•FNUMS)òûd [132] :if (û•FNUMS)>ûd ¦ easy case: new tie has been created [133] ¦ It's possible that we have now •ftied a file that was already •xftied, [134] ¦ but I see how we can detect this situation. [135] :else ¦ file was already tied; be polite and restore original tie number [136] tn•first d~•FNUMS [137] f •FSTIE tn ¦ if first tie worked, will this always work too? [138] :end [139] n•FNAMES[•FNUMSâtn;] [140] L4 [141] [142] L1: ¦ •FSTIE failed [143] [144] ee,•tcnl,'Error from •FSTIE: ',(^\•DM†•TCNL)/•DM [145] [146] L2: ¦ Try •XFSTIE (same logic as •FSTIE) [147] [148] d•XFNUMS [149] tn•first (â999)~•FNUMS,d [150] •ELX'',ôL3 [151] f •XFSTIE tn [152] •ELXelx [153] :if (û•XFNUMS)=ûd [154] tn•first d~•XFNUMS [155] f •XFSTIE tn [156] :end [157] n•XFNAMES[•XFNUMSâtn;] [158] L4 [159] [160] L3: ¦ •XFSTIE failed [161] [162] ee,•tcnl,'Error from •XFSTIE: ',(^\•DM†•TCNL)/•DM [163] •1e [164] 0 [165] [166] L4: ¦ Okay, we have tied the file! [167] [168] nDLTB n [169] [170] z•FSIZE tn [171] (i e)2z ¦ first, 1+last [172] zDEB,'CI15' •FMT z [173] [174] :if i=e ¦ no components? [175] :andif ~•sys[21] ¦ not runtime? [176] ñOUT 'No components in file ',n,' - Tie ',(ôtn),' - Size ',z [177] 0 [178] :end [179] [180] uw0 [181] oldu'' [182] [183] ¦ See if it's a user command file [184] [185] U0 ¦ pessimist [186] m((e-1),0)û'' [187] •ELX'',ôL5 [188] [189] q•FREAD tn,2 ¦ pointers to directories [190] k•FREAD tn,q[2] ¦ char directory of objects (names) [191] v•FREAD tn,q[3] ¦ num directory of objects (nc, comp, date mod, arch date) [192] k(èú\è' 'ú.†k)/k ¦ DTBC ¦ no subroutine because of •ELX [193] kk,' ì?'[v[;1]] [194] cv[;2] ¦ component numbers [195] uw10•first ý1ûk [196] m((e-1),uw)û' ' ¦ user command files always start with comp 1 [197] m[c;]uw[2]k [198] m[1 ;]uw'[fileid]' [199] m[2 ;]uw'[head]' [200] m[q[1];]uw'[usage]' [201] m[q[2];]uw'[names]' [202] m[q[3];]uw'[numinfo]' [203] m[3 ;]uw'[bootfn]' [204] m[4 ;]uw'[upath]' [205] m[5 ;]uw'[bootpkg]' [206] m[5+â5;](5,uw)ûuw'[reserved]' [207] U1 [208] [209] L5: [210] [211] •ELXelx [212] [213] :if 1=ûûC [214] Cý2•FI C [215] qC=0 [216] C[q/â2]q/i,e-1 [217] CC[C] [218] CiCe-1 [219] (i e)C+0 1 [220] :end [221] [222] w•FI UcmdIni 'FileDoc-Place' '2 5 20 70' [223] v•FI UcmdIni 'FileDoc-Visible' '1' [224] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [225] [226] ¦ If there are other instances of Filedoc running, cascade windows a little bit [227] :for •wself :in '#' •wi 'children' [228] :if 'Form'ð•wi 'class' [229] :andif 'fmFiledoc'ð9•wi 'name' [230] w[1 2]w[1 2]1.5 3+2•wi 'place' [231] :end [232] :end [233] [234] •wself('fmFiledoc',ôtn) •wi 'Create' 'Form' 'Hide' [235] •wi '‘inifile' f [236] •wi 'caption' ('FileDoc ',(ôtn),' - ',n,' - Size ',z) [237] •wi 'place' w [238] •wi 'visible' v [239] h' CMDFILEDOC •wevent' [240] •wi 'onClose' h [241] [242] •wself':mFile' •wi 'New' 'Menu' [243] •wi 'caption' '&File' [244] [245] •wself':mFile.mPeek' •wi 'New' 'Menu' [246] •wi 'caption' '&Peek...' [247] •wi 'shortcut' 'P' 2 [248] •wi 'onClick' " CMDFILEDOC 'Peek'" [249] [250] •wself':mFile.mExit' •wi 'New' 'Menu' [251] •wi 'caption' 'E&xit' [252] •wi 'shortcut' 'X' 2 [253] •wi 'onClick' "0 0û':' •wi 'Close'" [254] [255] •wself':mView' •wi 'New' 'Menu' [256] •wi 'caption' '&View' [257] [258] •wself':mView.mUcmd' •wi 'New' 'Menu' [259] •wi 'caption' '&UCMD Info' [260] •wi 'shortcut' 'U' 2 [261] •wi 'style' 1 [262] •wi 'value' U [263] •wi 'data' 3 [264] •wi 'onClick' h [265] •wi 'visible' U [266] •wi 'enabled' U [267] [268] •wself':mView.mTime' •wi 'New' 'Menu' [269] •wi 'caption' '&Timestamp' [270] •wi 'shortcut' 'T' 2 [271] •wi 'style' 1 [272] •wi 'value' T [273] •wi 'data' 4 [274] •wi 'onClick' h [275] [276] •wself':mView.mBytes' •wi 'New' 'Menu' [277] •wi 'caption' '&Bytes' [278] •wi 'shortcut' 'B' 2 [279] •wi 'style' 1 [280] •wi 'value' B [281] •wi 'data' 5 [282] •wi 'onClick' h [283] [284] •wself':mView.mDepth' •wi 'New' 'Menu' [285] •wi 'caption' '&Depth' [286] •wi 'shortcut' 'D' 2 [287] •wi 'style' 1 [288] •wi 'value' D [289] •wi 'data' 6 [290] •wi 'onClick' h [291] [292] •wself':mView.mShape' •wi 'New' 'Menu' [293] •wi 'caption' '&Shape' [294] •wi 'shortcut' 'S' 2 [295] •wi 'style' 1 [296] •wi 'value' S [297] •wi 'data' 7 [298] •wi 'onClick' h [299] [300] •wself':bn' •wi 'New' 'Button' [301] •wi 'caption' 'Stop' [302] •wi 'size' 1.25 8 [303] •wi 'style' 2 ¦ 2=cancel [304] •wi 'onClick' 'done1' ¦õ done [305] [306] •wself':l' •wi 'New' 'Label' [307] •wi 'caption' '' [308] •wi 'size' 1 9 [309] •wi 'style' 2 [310] [311] •wself':pb' •wi 'New' 'Progress' [312] •wi 'style' 1 ¦ 1=smooth [313] •wi 'value' 0 (1e-i) 1 0 ¦ 1 in case empty file [314] [315] cw1+2’•first ûôe-1 ¦ component number display width [316] cw4cw ¦ at least 'Comp' [317] [318] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [319] c0 3û0 [320] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [321] ccž((4+5’cwò9)'Component') (1.5+4+5’cwò9 ) 'right' ¦ 2 [322] ccž'UCMD' uw 'left' ¦ 3 [323] ccž'Timestamp' 20 'left' ¦ 4 [324] ccž'Bytes' 8 'right' ¦ 5 [325] ccž'ð' (1.5+1) 'right' ¦ 6 [326] ccž'Shape' 8 'right' ¦ 7 [327] ccž'Value' 80 'left' ¦ 8 [328] [329] •wself':' [330] [331] cv0 1 U T B D S 1 [332] c[(~cv)/âûcv;2]0 [333] •wi '‘cv' cv [334] [335] •wi '‘tn' tn [336] [337] •wself':lv' •wi 'New' 'Listview' [338] [339] •wi 'columndisplay' c [340] •wi 'scale' 3 ¦ font size will be specified in points [341] •wi 'font' (UcmdFont '') [342] •wi 'where' 0.5 1 [343] •wi 'style' 1 2 4 1024 4096 ¦ 1024=reorder cols 4096=gridlines [344] •wi 'onColClick' h [345] •wi 'onDblClick' h [346] •wi 'onKeyPress' h [347] [348] •wself':' [349] •wi 'onResize' h [350]  CMDFILEDOC 'Resize' [351] [352] •wself':lv' [353] •wi 'Focus' [354] [355] (i=e)ûL7 ¦ no components? [356] [357] v0 ¦ in case just one component [358] r0 [359] u'' [360] t0 [361] b0 [362] [363] T~T ¦ if /T option, force all components to be different [364] [365] oldii [366] oldv•FREAD tn,i ¦ read first component, save for flush [367] oldr•FRDCI tn,i [368] oldum[i;] [369] [370] W0 ¦ wasted bytes in ucmd file [371] [372] done0 ¦ repeat until done [373] [374] :repeat [375] [376] ':l' •wi 'caption' (,'CI9' •FMT i) [377] ':pb' •wi 'Stepit' [378] ii+1 [379] :if i1 [410] cc,'',ôi-1 [411] :end [412] [413] ¦¦¦ Timestamp [414] t,'I4,,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6û3oldr [415] [416] ¦¦¦ Bytes [417] bDLB,'CI15' •FMT oldr[1] [418] [419] ¦¦¦ Depth [420] dðoldv [421] dôd [422] [423] ¦¦¦ Shape [424] pûoldv ¦ shape [425] kûp ¦ rank [426] p(ôp),(k=0)/'' ¦ format shape [427] [428] ¦¦¦ Value [429] ¦fFFA oldv [430] fmax FFAW oldv [431] f(maxûf)ûf [432] qfâ'û' [433] :if qóûf [434] :andif q0 [454] q'FYI: ',(DLB,'CI15' •FMT W),' wasted bytes in ucmd file' [455] •wi 'size' 1 40 [456] •wi 'style' 0 [457] :else [458] q'' [459] :end [460] •wi 'caption' q [461] [462] •wself':pb' [463] •wi 'visible' 0 [464] [465] •wself':bn' [466] •wi 'onClick' '' [467] •wi 'caption' 'E&xit' [468] [469] •wself':lv' [470] •wi 'AutoFit' 'header' (cv/âûcv) ¦ skip dummy column 1 [471] [472] •wself':' [473] [474] k•wi 'Wait' [475] [476] 0 [477] [478] L6: ¦ ----- Callbacks ----- [479] [480] :SELECT f [481] [482] :CASE 'Resize' [483] [484] •wself':' [485] z•wi 'size' [486] (0îz)û0 ¦ noop if minimize [487] •wself':bn' [488] b0.5 1+•wi 'size' ¦ button size plus gaps [489] wz-b [490] •wi 'where' w [491] [492] ':l' •wi 'where' (w[1]+0.1) 1 [493] ':pb' •wi 'where' (w[1]) 11 1.25 (w[2]-12) [494] [495] •wself':lv' [496] w•wi 'where' [497] w[3 4]z-(1 0’b)+(2’w[1 2]) [498] •wi 'where' w [499] [500] :CASE 'RT_Resize' [501] [502] z•wi 'size' [503] •wself':bn' [504] b0.5 1+•wi 'size' [505] wz-b [506] •wi 'where' w [507] [508] •wself':ed' [509] w•wi 'where' [510] w[3 4]z-(1 0’b)+(2’w[1 2]) [511] •wi 'where' w [512] [513] :CASE 'Click' [514] [515] b•wi 'data' ¦ column number [516] v•wi 'value' ¦ on or off [517] cv':' •wi '‘cv' [518] cv[b]v [519] ':' •wi '‘cv' cv [520] •wself':lv' [521] :if v ¦ if turning on, we just need to autofit it [522] •wi 'AutoFit' 'header' b [523] :else ¦ if turning off, we need to change width to 0 [524] c•wi 'columndisplay' [525] c[b;2]0 [526] •wi 'columndisplay' c [527] :end [528] [529] :CASE 'ColClick' [530] [531] ¦ ••wself •wevent •warg [532] c1•warg ¦ column clicked [533] ¦ 1=dummy 2=comp 3=ucmd 4=time 5=bytes 6=depth 7=shape 8=value [534] i•wi 'sortorder' ¦ all rowids [535] m•wi 'GetCells' i c ¦ data [536] m[2],m ¦ simple char matrix [537] :if c=2 [538] pûm [539] b,èú\èm='' [540] m,m  m[b/âûb]' '  mpûm ¦ blank out '5' in '510' [541] :end [542] :if c î 2 5 6 7 [543] m(-+/^\èm=' ')èm ¦ right justify [544] :end [545] :if c=•wi '‘sort' ¦ same col as previous click? [546] d•avm ¦ descending [547] •wi '‘sort' 0 [548] :else [549] d•avm [550] •wi '‘sort' c ¦ remember for possible twice [551] :end [552] •wi 'sortorder' (i[d]) [553] [554] :CASE 'Close' [555] [556] (•wi 'place') UcmdIni 'FileDoc-Place' [557] (•wi 'visible') UcmdIni 'FileDoc-Visible' [558] [559] :if ~•sys[21] ¦ not runtime? [560] f':' •wi 'self' [561] '#' •wi 'Defer' ("'",f,"' •wi 'Delete'") [562] :end [563] [564] :CASE 'RT_Close' [565] [566] (•wi 'place') UcmdIni 'FileDocPeek-Place' [567] [568] :CASE 'KeyPress' [569] [570] :if •warg=13 ¦ Enter key? [571]  CMDFILEDOC 'Peek' [572] :end [573] [574] :CASE 'Peek' [575] [576] •wself':lv' [577] i1•wi 'value' ¦ selected row [578] :if i=0 [579] i1•wi 'sortorder' ¦ first in list [580] (i=0)û0 [581] :end [582] i CMDFILEDOC 'W_Edit' [583] [584] :CASE 'DblClick' [585] [586] r1•warg ¦ rowid [587] r CMDFILEDOC 'W_Edit' [588] [589] :CASE 'W_Edit' [590] [591] rb ¦ left arg: rowid [592] c•enlist •wi 'GetCells' r 2 ¦ get Comp cell [593] i(^\c†'')/c ¦ '1235' to '12' [594] i•first •FI i ¦ component number [595] tn':' •wi '‘tn' ¦ tie number [596] [597] ¦ W_Edit is not supported by the runtime engine [598] :if •sys[21] ¦ runtime? [599] (tn,i) CMDFILEDOC 'RT_Edit' [600] 0 [601] :end [602] [603] v•FREAD tn,i ¦ the value [604] u•enlist •wi 'GetCells' r 3 ¦ get Ucmd cell [605] [606] :if 1=ûûv [607] :andif 5óûv [608] :andif 'PACKAGE'ð1v [609] •UCMD 'PKGDOC ',ôtn,i ¦õ CMDPKGDOC [610] :elseif 'ì'îu ¦ function from ucmd file [611] nu~' ì' [612] k•DEF "ìn p v;",n,•tcnl,"[1] k•def v  (kðn)0  k•WCALL 'W_Edit' n ì" [613] n p v [614] :else [615] :if ''îu ¦ variable from ucmd file [616] nu~' ' [617] :else [618] n'File',(ôtn),'Comp',ôi ¦ local name [619] :end [620] :if (ðv)>1 [621] :orif (ûûv)>2 [622] :orif ^/0 ' 'î•TYPE •enlist v [623] ¦vFFA v ¦ but can get "Line too long" error from W_Edit [624] v•UCMD 'DISPLAY v' ¦ well, it's better than nothing! [625] :end [626] k•DEF "ìn p ",n,•tcnl,"[1] k•WCALL 'W_Edit' n ì" [627] n p v [628] :end [629] [630] :CASE 'RT_Edit' [631] [632] (tn i)b [633] v•FREAD tn,i ¦ the value [634] vCVR v ¦ simple character (thanks, Roy!) [635] [636] w•FI UcmdIni 'FileDocPeek-Place' '2 5 20 70' [637] [638] •wself('fmPeek',ôi) •wi 'Create' 'Form' 'Hide' [639] •wi 'caption' ('FileDoc ',(ôtn),' - Component ',ôi) [640] •wi 'border' 2 16 64 ¦ 2=sizeable 3=modal 16=sys menu 64=max [641] •wi 'limitwhere' 10 30 ¦ minimum size [642] •wi 'onClose' " CMDFILEDOC 'RT_Close'" [643] •wi 'onResize' " CMDFILEDOC 'RT_Resize'" [644] [645] •wself':ed' •wi 'New' 'Edit' [646] •wi 'where' 0.75 1 10 30 [647] •wi 'scale' 3 ¦ font size will be specified in points [648] •wi 'font' (UcmdFont '') [649] •wi 'color' (256æ255 255 255) [650] •wi 'style' 4 16 64 2048 4096 ¦ 4=multi-line 16=vscroll 64=hscroll 2048=APL 4096=read-only [651] •wi 'text' v [652] [653] •wi 'Defer' "•wi 'selection' 0" ¦ who knows why Defer is necessary... [654] [655] •wself':bn' •wi 'New' 'Button' [656] •wi 'size' 1.25 9 [657] •wi 'caption' 'Close' [658] •wi 'style' 2 ¦ 1=default (enter key); 2=cancel (escape key)  onClose [659] [660] •wself':' [661] •wi 'where' w ¦ triggers onResize handler [662] k•wi 'Show' ¦ don't Wait; Show permits several peeks [663] [664] :ELSE [665] [666] •'*** Unanticipated CMDFILEDOC callback! ',ôf •wself •wevent •warg [667] [668] :ENDSELECT [669] ì €US<ýý ì CMDFIND A;D [1] ¦ Find strings in functions, non-syntactic and case-insensitive [2] ¦ ( GUI version of ]SCAN ) [3] [4] ¦ See ]SEEK ? for documentation [5] ¦ This cover function just adds the and ï options [6] [7] ¦ 30 Mar 2007 Rex Swain, Independent Consultant, www.rexswain.com [8] [9] Aô•ENLIST A ¦ arg might be numeric in development mode [10] [11] AñDEB A ¦ user command may pass in leading/trailing blanks [12] [13] :if Að'' [14] •'For help, see' [15] •' ]seek ?' [16] 0 [17] :end [18] [19] ¦ Allow simple word search without delimiters [20] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [21] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [22] A'/',A [23] :end [24] [25] D1A ¦ delimiter [26] AA,(1=2þ+/A=D)ûD ¦ add a closing delimiter if necessary [27] AA,'ï' ¦ non-syntactic, case-insensitive [28] [29] •UCMD ']SEEK ',A [30] ì $@€US<â0909 ì G CMDFLI A;D;E;F;H;I;L;M;N;OB;OT;P;R;T;W;Z;a;b;c;d;e;h;i;k;m;n;r;t;v;w;x;z;•wself [1] ¦ ]FLIB (but no trailing B) [2] [3] ¦ Syntax: [4] ¦ ]FLI ¦ current drive/path (like •CHDIR '') [5] ¦ ]FLI 5 ¦ only library number [6] ¦ ]FLI 6 8 ¦ several library numbers [7] ¦ ]FLI * ¦ all library numbers (from •LIBS) [8] ¦ ]FLI foo ¦ ws names containing substring (in all libraries) [9] [10] ¦ Options: [11] ¦ /B or /Z ¦ sort by Bytes / Size [12] ¦ /T ¦ sort by Timestamp [13] [14] ¦ 13 Apr 2011 Rex Swain, Independent Consultant, www.rexswain.com [15] ¦ 13 Apr 2011 Cloned from CMDWSLI dated 03 Mar 2011 [16] [17] (’•NC 'G')ûL9 ¦ any left arg means callback [18] [19] Aô•enlist A ¦ arg could be numeric in development mode [20] [21] OT1=ûûA ñGETOPT '/T' ¦ sort by timestamp [22] OB 1=ûûA ñGETOPT '/B' ¦ sort by bytes [23] OBOBú1=ûûA ñGETOPT '/Z' ¦ or sort by size [24] [25] A(^\A†'/')/A ¦ delete all options [26] [27] :if '*'îA [28] :orif 0î•VI A ¦ RHS 3/03/11 substring [29] N•FI,11[2]•LIBS ¦ RHS 1/27/04 if no libs are defined, 0 0ðû•LIBS [30] :else [31] N(•VI A)/•FI A [32] :end [33] [34] ¦ ----- Find files ----- [35] [36] :if 0=ûN [37] D•CHDIR '' [38] DD,((ý1D)î'\:')'\' ¦ force trailing backslash, unless 'D:' [39] L [2] •FLIB '' ¦ uses •chdir '' , sorts by name, and does not return library number [40] W( ''),( D),[1.5] L ¦ no library number [41] :else [42] W0 3û '' ¦ 1=lib 2=path 3=file [43] :for T :in N [44] :try [45] D•LIBD T [46] DD,((ý1D)î'\:')'\' ¦ force trailing backslash, unless 'D:' [47] L [2] 11[2] •FLIB T [48] WWž ( ôT),( D),[1.5] L [49] :catchall [50] •((^\•DM†•TCNL)/•DM),' from library ',ôT [51] :end [52] :end [53] :end [54] [55] :if ~'*'îA [56] :andif 0î•VI A ¦ RHS 3/03/11 substring [57] bú/ (ñUCASE A~' ')  ñUCASE [2] W[;3] [58] WbëW [59] :end [60] [61] n1ûW [62] [63] :if n=0 [64] •'No files found' [65] 0 [66] :end [67] [68] ¦ ----- Get size and timestamp for each file ----- [69] [70] k•wcall 'W_Def' '[Call] GetFileSizeEx=B(H hFile,>ULARGE_INTEGER lpFileSize) LIB Kernel32' [71] [72] d•wcall 'W_Const' 'INVALID_HANDLE_VALUE' [73] [74] W5[2] W ¦ 4=size 5=modified [75] [76] :for I :in ân [77] [78] F,/W[I;2 3] [79] F(DTB F),'.SF' [80] [81] H•wcall 'CreateFile' F 'GENERIC_READ' 'FILE_SHARE_READ' 0 'OPEN_EXISTING' 0 0 [82] ¦Assert H†d [83] [84] :if H=d ¦ root ucmd file is exclusively tied [85] W[I;4]ý1 [86] W[I;5] 7û0 [87] :continue [88] :end [89] [90] (R Z)•wcall 'GetFileSizeEx' H  ¦ return code and size [91] Assert R†0 [92] Z(2*32)æèZ [93] W[I;4]Z [94] [95] T•wcall 'GetFileTime' H    ¦ get create, access, write/modified times [96] Assert 0†•first T [97] T4T [98] [99] (R T)•wcall 'FileTimeToLocalFileTime' T  ¦ convert from UTC (GMT) to local time [100] Assert R†0 [101] [102] (R T)•wcall 'FileTimeToSystemTime' T  ¦ convert from FILETIME to SYSTEMTIME structure [103] Assert R†0 [104] [105] T1 1 0 1 1 1 1 1/T ¦ to be like •TS, ditch day of week [106] [107] W[I;5] T [108] [109] k•wcall 'CloseHandle' H [110] [111] :end [112] [113] ¦ ----- GUI ----- [114] [115] w•FI UcmdIni 'FLib-Place' '2 5 20 50' [116] [117] w[4]0 ¦ force onResize when we right-size later on [118] [119] •wself'fmFLib' •wi 'Create' 'Form' 'Hide' [120] •wi 'caption' ('FLib ',ôN) [121] •wi 'where' w [122] e' CMDFLI •wevent' [123] •wi 'onClose' e [124] •wi 'onDropDown' e [125] [126] •wself':mFile' •wi 'New' 'Menu' [127] •wi 'caption' '&File' [128] [129] •wself'.mExit' •wi 'New' 'Menu' [130] •wi 'caption' 'E&xit' [131] •wi 'shortcut' 'X' 4 [132] •wi 'onClick' "0 0û':' •wi 'Close'" [133] [134] •wself':mActions' •wi 'New' 'Menu' [135] •wi 'caption' '&Actions' [136] [137] •wself'.mFiledoc' •wi 'New' 'Menu' [138] •wi 'caption' '&Filedoc' [139] •wi 'shortcut' 'F' 2 [140] •wi 'onClick' " CMDFLI 'Filedoc'" [141] [142] •wself'..mRename' •wi 'New' 'Menu' [143] •wi 'caption' '&Rename' [144] •wi 'shortcut' 'R' 2 [145] •wi 'onClick' " CMDFLI 'Rename'" [146] [147] •wself'..mErase' •wi 'New' 'Menu' [148] •wi 'caption' '&Erase' [149] •wi 'shortcut' 'E' 2 [150] •wi 'onClick' " CMDFLI 'Erase'" [151] [152] •wself'..mRemove' •wi 'New' 'Menu' [153] •wi 'caption' 'Remove from list' [154] •wi 'shortcut' (46 0) ¦ 46=Del [155] •wi 'onClick' " CMDFLI 'Remove'" [156] [157] c0 3û0 [158] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [159] ccž'Lib' 8 'right' ¦ 2 [160] ccž'File' 16 'left' ¦ 3 [161] ccž'Bytes' 8 'right' ¦ 4 [162] ccž'Timestamp' 20 'left' ¦ 5 [163] [164] •wself':lv' •wi 'New' 'Listview' [165] •wi 'where' 0.25 1 [166] •wi 'style' 1 2 4 1024 4096 ¦ 1024=reorder cols 4096=gridlines [167] •wi 'columndisplay' c [168] [169] •wi 'scale' 3 ¦ font size will be specified in points [170] •wi 'font' (UcmdFont '') [171] •wi 'scale' 1 [172] [173] M(n,5)û '' [174] M[;2]W[;1] [175] M[;3]W[;3] [176] M[;4]DLB [2] 'Oý1CI15' •FMT W[;4] [177] T'I4,,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •FMT ý1[2] [2] W[;5] [178] M[;5] [2] T [179] [180] •wi 'list' (0,1,M) [181] [182] •wi 'AutoFit' 'header' (2 3 4 5) [183] [184] •wi 'onColClick' e ¦ sort [185] •wi 'onDblClick' e ¦ peek [186] •wi 'onKeyPress' e ¦ Enterpeek [187] •wi 'onClick' e ¦ select [188] [189] :if OT ¦ sort by timestamp [190] dè•AVT ¦ descending [191] •wi 'sortorder' d [192] :elseif OB ¦ sort by bytes [193] dèW[;4] ¦ descending [194] •wi 'sortorder' d [195] :end [196] [197] •wself':l1' •wi 'New' 'Label' [198] h1 1•wi 'Draw' ('?Text' 'AB') ¦ perhaps 0.8 [199] •wi 'size' h 10 [200] •wi 'caption' ((ôn),(-n=1)' files') [201] [202] xö2û'#' •wi 'units' [203] h1.2525’x[1] ¦ button height [204] [205] •wself':bnExit' •wi 'New' 'Button' [206] •wi 'caption' 'E&xit' [207] •wi 'size' h 8 [208] •wi 'style' 2 ¦ 2=cancel [209] [210] ¦ Right-size width around Listview [211] [212] •wself':' [213] [214] (h w)•wi 'size' [215] [216] wx[2]’•wcall 'GetSystemMetrics' 'SM_CXVSCROLL' ¦ vertical scroll arrow width [217] c':lv' •wi 'columndisplay' [218] ww++/c[;2] [219] ww+4’x[2] ¦ inner to outer size [220] ww+2 [221] [222] •wi 'onResize' e [223] •wi 'size' (h w) ¦ trigger Resize [224] [225] k•wi 'Wait' [226] [227] 0 [228] [229] L9: ¦ ========== Callbacks ========== [230] [231] :SELECT A [232] [233] :CASE 'DropDown' [234] [235] ¦ •wself is the form; can't tell which menu item was clicked [236] [237] •wself':lv' [238] [239] i•wi 'sortorder' ¦ all rowids [240] v•wi 'value' ¦ selected rowids [241] Nûv [242] [243] d[2],•wi 'GetCells' i 3 ¦ wsids [244] bú/'.BAK '  ñUCASE d,' ' [245] [246] •wself':mActions' [247] [248] '.mFiledoc' •wi 'enabled' (N=1) [249] '.mRename' •wi 'enabled' (N=1) [250] '.mErase' •wi 'enabled' (N>0) [251] '.mRemove' •wi 'enabled' (N>0) [252] [253] :CASE 'Remove' [254] [255] •wself':lv' [256] v•wi 'value' ¦ selected row(s) [257] •wi 'DeleteRows' v [258] [259] :CASE 'KeyPress' [260] [261] :if •warg=13 ¦ Enter key? [262] v•wi 'value' [263] :if 1=ûv [264] (1v) CMDFLI 'DoFiledoc' [265] :else [266] k•wcall 'MessageBeep' 0 [267] :end [268] :end [269] [270] :CASE 'Filedoc' [271] [272] •wself':lv' [273] v•wi 'value' ¦ selected row(s) [274] (0=ûv)û0 ¦ nothing selected [275] r1v [276] r CMDFLI 'DoFiledoc' [277] [278] :CASE 'DblClick' [279] [280] r1•warg ¦ rowid [281] r CMDFLI 'DoFiledoc' [282] [283] :CASE 'DoFiledoc' [284] [285] (L W),':lv' •wi 'GetCells' G (2 3) ¦ lib file [286] •UCMD •' ]FILEDOC ',ñDEB L,' ',W ¦ show ucmd being invoked [287] [288] :CASE 'Erase' [289] [290] •wself':lv' [291] v•wi 'value' ¦ selected row(s) [292] (0=ûv)û0 ¦ nothing selected [293] :for r :in v ¦ rowid [294] (L W),':lv' •wi 'GetCells' r (2 3) ¦ lib file [295] NñDEB L,' ',W [296] [297] :if •FIRST •VI N ¦ leading number means a library number (probably!) [298] P•FIRST •FI N [299] P•LIBD P ¦ library path [300] PP,((ý1P)î'\:')'\' ¦ force trailing backslash, unless 'D:' [301] W(ú\~Nî'1234567890 ')/N ¦ ws name [302] NP,W [303] :end [304] [305] FN,'.sf' ¦ native file [306] •" ¦ DeleteFile '",F,"'" [307] t•wcall 'DeleteFile' F [308] :if t=0 [309] •'*** DeleteFile failed' [310] e•wcall 'GetLastError' [311] •'GetLastError = ',(ôe),' = ','#' •wi 'FormatMessage' e [312] 0 [313] :end [314] :end [315] •wi 'DeleteRows' v [316] [317] :CASE 'Rename' [318] [319] •wself':lv' [320] v•wi 'value' ¦ selected row(s) [321] (0=ûv)û0 ¦ nothing selected [322] r•first v ¦ rowid [323] (L W),':lv' •wi 'GetCells' r (2 3) ¦ lib file [324] WñDEB W [325] [326] •wself'fmFLibAsk' •wi 'Create' 'Form' 'Hide' ('size' 6.75 21) ('caption' 'Rename') [327] k'.l1' •wi 'Create' 'Label' ('caption' 'Old:') ('where' 1.1 1 1.25 4) [328] k'.ed1' •wi 'Create' 'Edit' ('text' W) ('where' 1 5 1.25 15) ('style' 4096) [329] k'.l2' •wi 'Create' 'Label' ('caption' 'New:') ('where' 3.1 1 1.25 4) [330] k'.ed2' •wi 'Create' 'Edit' ('text' W) ('where' 3 5 1.25 15) [331] k'.bn1' •wi 'Create' 'Button' ('caption' 'OK') ('where' 5 2 1.25 8) ('style' 1) ('onClick' "':' •wi 'value' (':ed2' •wi 'text')  k':' •wi 'Close'") [332] k'.bn2' •wi 'Create' 'Button' ('caption' 'Cancel') ('where' 5 11 1.25 8) ('style' 2) [333] [334] e'fmFLib' •wi 'where' [335] z•wi 'where' [336] we[1 2]+0.5’e[3 4]-z[3 4] ¦ proposed where [337] •wi 'where' w ¦ move •wself [338] [339] •wi 'onShow' "'.ed2' •wi 'Focus'" [340] N•wi 'Wait' [341] •wi 'Delete' [342] •wself'fmFLib' [343] [344] :if Nð0 [345] :orif NðW [346] 0 [347] :end [348] [349] :if •FIRST •VI L ¦ numeric means a library number [350] L•FIRST •FI L [351] P•LIBD L ¦ library path [352] LP,((ý1P)î'\:')'\' ¦ force trailing backslash, unless 'D:' [353] :end [354] [355] DL,W,'.sf' ¦ old [356] EL,N,'.sf' ¦ new [357] [358] •" ¦ MoveFile '",D,"' '",E,"'" [359] t•wcall 'MoveFile' D E [360] :if t=0 [361] •'*** MoveFile failed' [362] 0 [363] :end [364] [365] ':lv' •wi 'SetCells' r 3 N ¦ wsid [366] [367] :CASE 'Resize' [368] [369] z•wi 'size' ¦ form size [370] (0îz)û0 ¦ minimized? don't bother doing anything [371] b':bnExit' •wi 'size' ¦ button size [372] tb[1] ¦ button height [373] [374] •wself':lv' [375] w•wi 'where' [376] w[3]z[1]-w[1]+t+1 ¦ less buttons and vertical gaps [377] w[4]z[2]-w[2]’2 ¦ form width less gaps [378] •wi 'where' w ¦ move and resize [379] [380] •wself':bnExit' [381] vz[1]-t+0.5 ¦ v pos [382] hz[2]-b[2]+1 ¦ h pos [383] •wi 'where' (v,h) ¦ just move [384] [385] •wself':l1' [386] a•wi 'size' [387] vv-0.5’a[1]-t [388] •wi 'where' (v,1) [389] [390] :CASE 'ColClick' [391] [392] c1•warg ¦ column clicked [393] i•wi 'sortorder' ¦ all rowids [394] d,•wi 'GetCells' i c ¦ data [395] m[2]d ¦ simple char matrix [396] :if cî2 4 ¦ lib bytes? [397] m(-+/^\èm=' ')èm ¦ right justify [398] :end [399] d•AVm [400] :if dðâûd ¦ already sorted? [401] dèd ¦ descending [402] :end [403] •wi 'sortorder' (i[d]) [404] [405] :CASE 'Close' [406] [407] (•wi 'place') UcmdIni 'FLib-Place' [408] [409] :CASE 'Click' [410] [411] ¦ If there are 0 rows selected, act on the pointed-to row [412] ¦ Else always act on selected row(s) [413] [414] a•warg ¦ pointed-to rowid; save to perhaps pass along to DblClick [415] b7a ¦ mouse button (1=left 2=right) [416] (b†2)û0 ¦ quit unless right (row selection has already been toggled) [417] v•wi 'value' ¦ selected rowids [418] r1a ¦ pointed-to rowid; save to perhaps pass along to DblClick [419] r0 ¦ quit if empty row [420] z•first •wi 'GetCells' r 8 ¦ bytes (tells us if we have done Get Info already) [421] [422] m'mFLibPopup' •wi 'Create' 'Menu' [423] k(m,'.m1') •wi 'New' 'Menu' ('caption' '&Filedoc') ('onClick' "':' •wi 'data' 1") [424] k(m,'.m7') •wi 'New' 'Menu' ('caption' '&Rename') ('onClick' "':' •wi 'data' 7") [425] k(m,'.m6') •wi 'New' 'Menu' ('caption' '&Erase') ('onClick' "':' •wi 'data' 6") [426] k(m,'.m3') •wi 'New' 'Menu' ('caption' '&Remove from list') ('onClick' "':' •wi 'data' 3") [427] [428] ':' •wi 'Popup' m 2 ¦ 2=make the menu respond to the right mouse button [429] dm •wi 'data' [430] m •wi 'Delete' [431] [432] :select d [433] :case 0 ¦ escape [434] ¦ noop [435] :case 1 [436] r CMDFLI 'DoFiledoc' [437] :case 3 ¦ remove [438] •wi 'DeleteRows' v [439] :case 6 [440]  CMDFLI 'Erase' [441] :case 7 [442]  CMDFLI 'Rename' [443] :else ¦ tilt [444] ö0 [445] :end [446] [447] :ELSE [448] [449] •'Unanticipated CMDFLI callback!' A •wself •wevent •warg [450] [451] :ENDSELECT [452] ì €US<ý’e’e ì XCMDFNREPL A;B;C;D;E;F;FILT;G;H;I;J;K;L;M;N;P;Q;QC;R;S;SYN;T;U;UP;V;W;Z;a;d;g;h;i;m;p;q;r;t;u;y [1] ¦ Find (and optionally replace) strings in functions [2] [3] ¦ Syntax: [4] ¦ [5] ¦ ]fnrepl target ¦ Search (if target begins with a letter) [6] ¦ ]fnrepl target/options ¦ Ditto, with options [7] ¦ Any non-alpha delimiter character may be used in place of the slashes shown below [8] ¦ ]fnrepl /target ¦ Search (exactly 1 delimiter) [9] ¦ ]fnrepl /target/ ¦ Search (exactly 2 delimiters) [10] ¦ ]fnrepl /target/options ¦ Ditto, with options [11] ¦ ]fnrepl /target/replacement/ ¦ Replace (exactly 3 delimiters) [12] ¦ ]fnrepl /target/replacement/options ¦ Ditto, with options [13] ¦ Multiple targets (not allowed in replace mode): [14] ¦ ]fnrepl /t1/^/t2/options ¦ Find only lines with both matches [15] ¦ ]fnrepl /t1/ú\t2\ ¦ Find lines with either match; delimiters may be different [16] ¦ ]fnrepl /t1/&~/t2/ ¦ Logical not; & and þ are also permitted [17] ¦ ]fnrepl /t1/>/t2/ ¦ Can use any of <ó=ò>†ú^åê&þ and ~ [18] ¦ ]fnrepl /t1/^~/t2/ú/t3/ ¦ Evaluated as APL would ("right to left") [19] [20] ¦ Default is to perform case-sensitive, syntactic (name) search, on all global functions [21] [22] ¦ Options: [23] ¦ [24] ¦ To loosen match criteria: [25] ¦ / ¦ Non-syntactic search (ANY occurrence) (Alt+S for non-Syntactic) [26] ¦ /ï ¦ Ignore case (upper/lower/underscore) (Alt+C for Case) [27] ¦ To limit functions searched: [28] ¦ /f1 f2 ¦ Only look in named functions [29] ¦ /f* ¦ Fn names with wildcards (foo* *old fm*def etc.) [30] ¦ /.grp ¦ Fn names contained in variable grp [31] ¦ /~f1 f2 ¦ Look in all but named functions [32] ¦ To limit search scope (using all three is equivalent to using none): [33] ¦ /¦ ¦ Find only in comments [34] ¦ /' ¦ Find only in character constants (or /") [35] ¦ /à ¦ Find only in APL (not comments/quotes) [36] ¦ To expand search scope: [37] ¦ /ì ¦ Find strings anywhere in a function -- not necessarily on the same line. [38] ¦ Only useful with multiple targets. Doesn't change behavior of /t1/ú/t2/. [39] ¦ Display from /t1/^/t2/ì is similar to /t1/ú/t2/ but only shows functions [40] ¦ that contain at least one hit on both strings. [41] ¦ Other: [42] ¦ /û ¦ Auto reply Yes to the replacement confirmation prompt [43] ¦ /? ¦ Prompt before each replacement [44] ¦ / ¦ Suppress display; return fn names [45] [46] ¦ Nice features: [47] ¦ Both single- and double-quotes are handled (thanks, Zark!) [48] ¦ Searches for system names (such as •io) are automatically case-insensitive [49] [50] ¦ Outstanding issues: [51] ¦ Search for 'ý2' should not match '1Eý2' [52] ¦ Search for 'if' should match "':if' •wi 'Create' 'Image'" [53] ¦ Search for 'if' should not match ':if a>b' [54] ¦ Search for ':if' should be automatically case-insensitive [55] [56] ¦ 15 Dec 1987 Rex Swain, Independent Consultant [57] ¦ 19 May 1988 Detect and display changed function names [58] ¦ 16 May 1991 Erase old version when fn name changed [59] ¦ 27 Aug 1993 Added ï (ignore case) option [60] ¦ 26 Nov 1994 Adapted for Dyalog APL/W, added # and ## and  options [61] ¦ 29 Dec 1998 Adapted for APL+Win 3.0, removed # and ## and  options [62] ¦ 10 Nov 1999 Added colon as leading identifier char for APL+Win [63] ¦ 18 Nov 1999 Added case-insensitive treatment for APL+Win key names [64] ¦ 03 Dec 2001 Removed colon -- it can OPTIONALLY begin an identifier [65] ¦ 04 Apr 2003 Report total number of hits [66] ¦ 18 May 2003 Added ~ feature [67] ¦ 14 May 2004 Added ? feature [68] ¦ 29 Aug 2004 Added * feature [69] ¦ 26 Mar 2005 Evlevel-neutral (sigh) [70] ¦ 11 Jul 2005 Use QC (derived from Zark's ParseVR) to handle ' and " quotes [71] ¦ 21 Jul 2005 Created ìCMDFNREPL from ìfnrepl [72] ¦ 07 Oct 2005 Fixed FILT bug -- H>QC should be H^QC ! [73] ¦ 06 Feb 2006 Added multiple target feature [74] ¦ 04 Mar 2006 Added ì option [75] ¦ 08 Jul 2007 Updated ìQC [76] ¦ 14 Sep 2007 Allow "Q" for quit in prompted replace mode [77] ¦ 13 Dec 2008 Added .grp feature [78] ¦ 16 Mar 2009 Use •VGET and 0 •VR and etc. to avoid shadowing (req APL ver 7.2) [79] ¦ 13 Oct 2010 Most recent minor update [80] [81] Aô•ENLIST A ¦ arg might be numeric in development mode [82] [83] ADLTB A ¦ user command may pass in leading/trailing blanks [84] [85] :if Að'' [86] •'For help, see' [87] •' ]fnrepl ?' [88] 0 [89] :end [90] [91] ¦ Allow simple word search without delimiters [92] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [93] E1A ¦ first delimiter [94] :if Eî'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [95] E'/' [96] AE,A [97] :end [98] ¦ Allow no trailing delimiter for search with no options [99] ¦ If arg is '/foo', make it '/foo/' [100] :if 1=+/A=E [101] AA,E [102] :end [103] [104] ¦ Parse argument [105] [106] G0û '' ¦ targets [107] S0û '' ¦ functions [108] [109] :repeat [110] D1A ¦ delimiter [111] A1A [112] IAâD ¦ find second delimiter (might not be one) [113] :if I=1 [114] •'Empty target string is not a good idea' [115] 0 [116] :end [117] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [118] ADLB IA [119] P1A ¦ function or option [120] :if ~Pî'<ó=ò>†ú^åê&þ' [121] :leave [122] :end [123] P('^ú',P)['&þ'âP] [124] ADLB 1A [125] :if '~'=1A [126] PP,'~' [127] ADLB 1A [128] :end [129] S( P),S ¦ function and possible ~ [130] :if Að'' [131] •'Multiple target syntax error' [132] 0 [133] :end [134] :end [135] [136] D•FIRST ûG ¦ number of targets [137] [138] :if D>1 ¦ multiple targets? [139] FA ¦ options (old left argument) [140] p0 ¦ not replace mode [141] S'ø',S ¦ to save repeated (J-1)S below [142] :else ¦ one target [143] P1(1,E=A) •PENCLOSE E,A ¦ note we look for original first delimiter [144] N•FIRST ûP [145] :if N>2 [146] •'Argument should have 2 or 3 delimiters' [147] 0 [148] :end [149] pN=2 ¦ replace mode? [150] :if p [151] (r F)P ¦ replacement string, options [152] h•FIRST ûr ¦ need this repeatedly [153] d(•FIRST û1G)-h ¦ length difference (scalar for :select :case) [154] :else ¦ find mode [155] F1P ¦ options [156] :end [157] :end [158] [159] ¦ Define ìFILT for APL/quoted strings/comments [160] [161] Z'à''¦'îF [162] Z[2]Z[2]ú'"'îF [163] Z2æZ [164] E~Zî0 8 ¦ not all or none: we need to filter [165] [166] :if E ¦ unless all or none [167] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [168] LL, "¦ Quotes and Comments" [169] LL, "¦ Right arg is a •VR" [170] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [171] LL, "¦ Extracted from Zark's ìParseVR" [172] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [173] LL, "¦ 26 Oct 2004 Include ¦õ" [174] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [175] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [176] LL, "•IO0 ¦ origin 0 is convenient" [177] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [178] LL, "xcx\n" [219] LL, "¦ Flag newline after each comment; then convert pairs to maps" [220] LL, "tnúc" [221] LL, "ut/c" [222] LL, "c†\x\t\uúý10,u" [223] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [224] ¦ 0=None and 7=All cases are excluded before we get here [225] P 'rc' ¦ 1 = ¦ [226] PP, 'rq>c' ¦ 2 = ' ¦ Quoted strings: not in comments [227] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [228] PP, 'rqåc' ¦ 4 = à = 'å¦ [229] PP, 'r~q' ¦ 5 = ঠ= ~' [230] PP, 'r~c' ¦ 6 = à' = ~¦ [231] LL,P[Z] [232] K•FX[2]L ¦õ QC [233] :end [234] [235] L 'RFILT' [236] LL, '¦ Raw hit filter' [237] LL, '¦ V=•VR, P=partition flags' [238] LL, 'R~P ANDSCAN Vî''[1234567890]''' ¦ not line numbers [239] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [240] [241] K•FX[2]L ¦õ FILT ANDSCAN QC [242] [243] ¦ Define ìSYN for syntactic search [244] [245] Z''îF ¦ non-syntactic search? [246] [247] ¦ Token alphabet: chars that can be anywhere in a token [248] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [249] a'_' [250] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [251] aa,'abcdefghijklmnopqrstuvwxyzñ' [252] aa,'0123456789' [253] ¦ Token alphabet, including chars that can only begin a token [254] qa,'•ý' [255] ¦ Dilemma: search for 'if' should not find ':if' -- but watch out for L1:if1 [256] [257] Q 'HA SYN H;B;I' [258] QQ, '¦ Syntactic hit filter' [259] QQ, '¦ Requires: V=•VR, a,q=alphabet' [260] QQ, 'IH/âûH' [261] ¦  Note that if target starts with • then we don't care what's to the [262] ¦ left of it, so ((1A)îa) is correct. [263] QQ, ':if (1A)îa' [264] QQ, ' H[(('' '',V)[I]îq)/I]0' [265] QQ, ':end' [266] QQ, ':if (ý1A)îq' [267] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [268] QQ, ':end' [269] :if Z=1 ¦ Neither? [270] Q1ûQ ¦ noop [271] :end [272] K•FX[2]Q ¦õ SYN a q [273] [274] ¦ Define ìUP for case-insensitive filter [275] [276] Z'ï'îF ¦ ignore case when finding target? [277] [278] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [279] ¦ Noop if no letters in targets [280] K•FX[2]'VUP V' '¦ noop' [281] :elseif Z [282] Q'ñabcdefghijklmnopqrstuvwxyz' [283] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [284] u•AV [285] u[uâQ]L [286] K•FX[2]'VUP V' 'Vu[•AVâV]' ¦õ UP u [287] :else [288] m'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [289] u'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [290] Q 'VUP V;B;I;L;S' [291] QQ, '¦ Force APL+Win keyword names to upper case' [292] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [293] QQ, '¦ RHS 11/18/99' [294] QQ, '' [295] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [296] QQ, 'BVî''•'' ¦ find key symbols' [297] QQ, '(1îB)0 ¦ quit if none' [298] QQ, '' [299] QQ, 'LVîm ¦ flag all letters (any case)' [300] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [301] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [302] QQ, '(1îB)0 ¦ quit if none' [303] QQ, '' [304] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [305] QQ, 'IS/B ¦ flag those which are candidates' [306] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [307] QQ, 'I†\I ¦ name mask' [308] QQ, 'II/âûI ¦ indices' [309] QQ, '' [310] QQ, 'V[I]u[mâV[I]] ¦ translate' [311] K•FX[2]Q [312] ¦ RHS 3/19/01 [313] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [314] ¦ when searching for 'fMain'. [315] ¦ List of keywords? No, could have ':end' •wi 'New' ... [316] ¦ I think we need to upper-case just the à part of the •vr [317] ¦ RHS 2/06/06 [318] ¦ I often search for •fappend or •io. [319] ¦ I cannot recall EVER having searched for :repeat. [320] ¦ So let's not worry about control structure keywords. [321] :end [322] [323] GUPG ¦ targets to uppercase, if appropriate [324] A1G ¦ last (and typically only) target [325] [326] ¦ Options setup [327] [328] R''îF ¦ suppress display, just return result? [329] X0û '' ¦ initialize result [330] [331] T'~'îF ¦ all but named fns? [332] y'û'îF ¦ auto reply Yes to replacement confirmation prompt? [333] [334] i'?'îF ¦ interactive prompt mode? [335] :if i^~p [336] •'Prompt mode "?" is only useful in replace mode' [337] 0 [338] :end [339] [340] g'ì'îF ¦ global fn matching? [341] :if g^D=1 [342] •'FYI, the ì option has no effect with just one target string' [343] g0 [344] :end [345] [346] ¦ Strip flags from function list [347] [348] Eú/'*.'îF ¦ any function name wildcards or groups? [349] F(~Fî'à''¦ï~?ú^ì')/F ¦ note we do not remove asterisk and period [350] FWords F [351] [352] ¦ Default to all fns [353] [354] :if T^0=ûF [355] •'Tilde with no names means "not all functions"' [356] 0 [357] :end [358] [359] :if EúTú0=ûF [360] [361] M0 •IDLIST 1 ¦ all global fns [362] MWords M [363] [364] ¦ Since this is a user command function, it won't be defined globally, [365] ¦ so we don't have to remove it from the list [366] [367] ¦N,•SI [368] ¦N(ý1+Nâ'[')ûN ¦ name of self ¦ RHS 8/31/99 [369] ¦MM~ N ¦ remove self [370] [371] :if 0=ûF [372] FM [373] :elseif E ¦ which implies 0†ûF [374] :while '*'î•ENLIST F ¦ wildcard? [375] P('*'îF)â1 [376] UPF [377] [378] VâûM ¦ indices of matches [379] C' ',M,' ' ¦ candidates [380] U('*'=1U)' ',U,('*'=ý1U)' ' [381] :for L :in '*' Words U [382] BC •SS L [383] Hú/B [384] C((H/B)â1)H/C [385] VH/V [386] :if Vð  :leave  :end [387] :end [388] CM[V] [389] [390] F((P-1)ûF),C,PF [391] :end [392] :while '.'î•ENLIST F ¦ group? [393] P('.'îF)â1 [394] UPF [395] [396] H(U='.')/âûU [397] :if Hð,1 ¦ one leading period [398] :andif 2=0 •NC 1U [399] Cõ1U [400] :if (ðC)ó1 ¦ simple vector or matrix [401] CWords C [402] :end [403] CC[•AV[2]C] ¦ is this a good idea? [404] :else [405] U[H] '(period)' [406] C •ENLIST U ¦ this will fail valid name test [407] :end [408] [409] F((P-1)ûF),C,PF [410] :end [411] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [412] :end [413] :if T [414] FM~F [415] :end [416] :end [417] [418] ¦ Discard invalid names [419] ¦ (This could still happen, if names are supplied in option list) [420] [421] C0 •NC [2]F [422] :if 4îC [423] N(C=4)/F [424] •'*** Not searched, invalid name',(1=ûN)'s:',ôN [425] F(C†4)/F [426] :end [427] [428] ¦ Discard non-functions [429] ¦ (This could still happen, if names are supplied in option list) [430] [431] C3=0 •NC [2]F [432] :if 0îC [433] N(~C)/F [434] •'*** Not function',(1=ûN)'s:',ôN [435] FC/F [436] :end [437] [438] ¦ Discard locked functions [439] [440] K•EX 'L' [441] K•FX [2] 'RL F' "R0†•first û0 •CRL F,'[0]'" ¦õ L [442] CLF ¦ yuck, but I wanted to get this check out of the function loop [443] K•EX 'L' [444] :if 0îC [445] N(~C)/F [446] •'*** Locked function',(1=ûN)'s:',ôN [447] FC/F [448] :end [449] [450] NûF ¦ how many fns [451] :if 0=ûF [452] •'*** No functions to search!' [453] 0 [454] :end [455] [456] :if p [457] :andif ~y [458] —'Sure you want to search ',(ôN),' function',(N=1)'s and replace "',A,'" with "',r,'" ? ' [459] •ARBOUT '' ¦ an oldie but a goodie [460] (ú/'Yy'î—)0 ¦ default is No [461] :end [462] [463] VDLTB •WSID [464] :if Vð'' [465] V'CLEAR WS' [466] :end [467] [468] •'Searching ',(ôN),' function',(N=1)'s in ',V,' ...' [469] [470] •WGIVE 0 ¦ let that message display [471] [472] T0 ¦ accumulate hits [473] E0 ¦ accumulate lines [474] U0 ¦ accumulate functions [475] [476] :for N :in F ¦ inspect next function [477] [478] V0 •VR N [479] LUP V [480] [481] ¦ Search •VR [482] [483] HL •SS A ¦ the heart of the matter [484] [485] :if D=1 ¦ single target? [486] :andif ~1îH ¦ no raw hits? [487] :continue ¦ next function [488] :end [489] [490] ¦ Syntactic filter [491] [492] HA SYN H ¦õ V a q [493] [494] :if D=1 ¦ single target? [495] :andif ~1îH ¦ no more hits? [496] :continue ¦ next function [497] :end [498] [499] ¦ Filter for APL / quoted strings / comments [500] [501] P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [502] P[ý5+ûV]1 ¦ force end of last line [503] [504] IFILT ¦õ P V ANDSCAN [505] HH^I [506] [507] :if D=1 ¦ single target? [508] :andif ~1îH ¦ no more hits? [509] :continue ¦ next function [510] :end [511] [512] :if D>1 ¦ multiple targets [513] HP ORRED H ¦ shift hits to leading "[" [514] ¦ We have already done the last target; now step through the others [515] ¦ Note that they are in reverse order so functions work like APL [516] :if g [517] tú/H [518] :for J :in 1âD [519] WL •SS JG ¦ raw search [520] W(JG) SYN W ¦ SYN [521] WW^I ¦ FILT [522] WP ORRED W ¦ shift hits to leading "[" [523] HWúH ¦ lines to show [524] tõ'(ú/W)',(JS),'t' ¦ apply function [525] :end [526] :if ~t ¦ no hits? [527] :continue ¦ next function [528] :end [529] :else [530] :for J :in 1âD [531] WL •SS JG ¦ raw search [532] W(JG) SYN W ¦ SYN [533] WW^I ¦ FILT [534] WP ORRED W ¦ shift hits to leading "[" [535] Hõ'W',(JS),'H' ¦ apply function [536] :end [537] :if ~1îH ¦ no hits remaining? [538] :continue ¦ next function [539] :end [540] :end [541] ¦ Note that when D>1, H flags lines not hits [542] :end [543] [544] ¦ Got some hits; if interactive mode, confirm them [545] [546] :if i ¦ interactive replace mode? [547] •'==> ',N,' (',(ô+/H),')' ¦ name of function, total hits [548] Mý1+P/âûP ¦ partition starts [549] Lý1+(1M,1+ûV)-M ¦ partition lengths [550] :for C :in H/âûH ¦ hit starting positions [551] B+/C>M [552] •N,V[M[B]+âL[B]] [553] —(((ûN)+ý1+C-M[B])û' ') , ((ûA)û'') , ' replace? [Ynq] ' [554] •ARBOUT '' ¦ an oldie but a goodie [555] W— [556] (ú/'Qq'îW)û0 ¦ bail out entirely [557] H[C]~ú/'Nn'îW ¦ default is Yes [558] :end [559] :if ~1îH ¦ no hits remaining? [560] :continue ¦ next function [561] :end [562] :end [563] [564] ¦ Got some hits; now display, or replace and then display [565] [566] :if p ¦ replace mode? [567] [568] LH/âûH ¦ hit starting positions [569] CûL ¦ how many hits [570] M(C,h)ûr ¦ replacements [571] [572] ¦ Replace, depending on length difference [573] [574] :select ’d [575] :case 0 ¦ replacement is same length as target [576] V[Lø.+ý1+âh]M [577] :case ý1 ¦ replacement is longer than target [578] LL+(þd)’ý1+âC [579] B((ûV)+C’þd)û1 [580] B[Lø.+âþd]0 [581] VB\V [582] V[Lø.+ý1+âh]M [583] HB\H [584] PB\P [585] :case 1 ¦ replacement is shorter than target [586] H1èH ¦ move hits left so not deleted [587] V[Lø.+ý1+âh]M [588] B(ûV)û1 [589] B[Lø.+h+ý1+âd]0 [590] VB/V [591] HB/H [592] PB/P [593] :end [594] [595] ¦ Redefine function [596] [597] Q•DEF V [598] [599] :if QðN ¦ function name same? [600] :andif ~ý1^.=ý1,•IDLOC N [601] •'*** •DEF ineffective because <',N,'> is shadowed' [602] :end [603] [604] :if 0=10ûQ [605] ¦ APL+Win: Q is error code, line number [line 1 = header!] [606] •'*** DEFN ERROR on <',N,'>: ',ôQ [607] •ý1((+\P)=Q[2])/V [608] :continue [609] :end [610] [611] :if ~QðN ¦ function name changed? [612] :if ~ý1^.=ý1,•IDLOC Q [613] •'*** •DEF ineffective because new name <',Q,'> is shadowed' [614] :else [615] •'* Warning: name of <',N,'> has been changed to <',Q,'>' [616] :if ý1^.=ý1,•IDLOC N [617] K•EX N ¦ erase old version [618] :else [619] •'* Warning: cannot erase old name <',N,'> because it is shadowed' [620] :end [621] :end [622] NQ [623] :end [624] [625] :end [626] [627] ¦ Ready to display hits [628] [629] :if D=1 [630] TT++/H ¦ accumulate total hits [631] EE++/P ORRED H ¦ accumulate lines with hits [632] :else [633] EE++/H ¦ accumulate lines with hits [634] :end [635] [636] UU+1 ¦ accumulate functions with hits [637] XX, N ¦ add function name to result [638] [639] :if R ¦ if result-only mode [640] :continue ¦ next function [641] :end [642] [643] ¦ Display hits [644] [645] •'==> ',N,' (',(ô+/H),')' ¦ name of function, total hits [646] [647] :if i ¦ interactive replace mode? [648] :continue ¦ next function [649] :end [650] [651] :if D=1 [652] HP ORRED H ¦ any hits per line? [653] :end [654] [655] HH/âûH ¦ line numbers to display (origin 1) [656] PP/âûP ¦ partition starts [657] L(1P,1+ûV)-P ¦ partition lengths [658] PP[H]-1 ¦ compensate for +â with •IO1 [659] LL[H]-1 ¦ not incl trailing CR [660] WûH ¦ number of lines with hits [661] :for B :in âW [662] ¦ APL+Win: Show fn name too so can double-click to edit at that line [663] •N,V[P[B]+âL[B]] ¦ faster than take/drop approach [664] :end [665] •WGIVE 0 ¦ allow display [666] [667] :end ¦ next function [668] [669] :if D=1 [670] •'==> Totals: ',(ôT),' hit',(T=1)'s on ',(ôE),' line',(E=1)'s in ',(ôU),(-U=1)' functions' [671] :else [672] •'==> Total: ',(ôE),' line',(E=1)'s in ',(ôU),(-U=1)' functions' [673] :end [674] [675] Rû0 ¦ quit if result-only mode [676] [677] K•EX 'X' [678] ì p€US<ñ ì CMDFNSS N [1] ¦ )FNS string search [2] ¦ Syntax: [3] ¦ ]FNSS foo ¦ find function names containing substring foo [4] ¦ Use semicolons to delimit multiple names and to retain leading/trailing blanks [5] ¦ ]FNSS ; foo ¦ names beginning with foo [6] ¦ ]FNSS foo ; ¦ names ending with foo [7] ¦ ]FNSS ; foo ; ¦ names matching foo [8] ¦ ]FNSS foo;goo ¦ names containing foo or goo [9] ¦ Options: [10] ¦ /C ¦ case-sensitive [11] ¦ /N ¦ name matching -- shorthand for ]FNSS ; Foo ; /c [12] ¦ /M ¦ return a matrix (display in a one-column list) [13] ¦ 23 Nov 2002 Rex Swain, Independent Consultant, www.rexswain.com [14] ¦ 09 Mar 2004 Added /M option [15] [16] 1 NLSS N ì €US<'J,J, ì L CMDKEYS A;D;F;H;I;K;M;P;V;c;d;i;j;k;m;s;w [1] ¦ Displays a list of APL+Win keyboard shortcuts [2] ¦ See ATN401.DOC for info on some of these [3] ¦ Also shows keys that have an APL Tool assigned [4] [5] ¦ You can assign an APL tool to override some standard Windows keys (eg Alt+F4) [6] ¦ But some keys cannot be overridden (eg Alt+Tab) [7] [8] ¦ 20 Jun 2005 Rex Swain, Independent Consultant, www.rexswain.com [9] ¦ 02 Jun 2010 Use UcmdIni and UcmdFont subroutines [10] [11] ¦ To do: Filter by string in Edit box [12] [13] (’•NC 'L')ûL1 ¦õ L ¦ any left arg means callback [14] [15] K0 5û [16] ¦ Alt Ctrl Shift Key Default [17] [18] KKž0 0 0 'F1' 'Help' [19] KKž0 0 0 'F2' 'Jump to next bookmark' [20] KKž0 1 0 'F2' 'Bookmark toggle' [21] KKž0 0 1 'F2' 'Jump to previous bookmark' [22] KKž0 1 1 'F2' 'Remove all bookmarks' [23] KKž0 0 0 'F3' 'Repeat find' [24] KKž0 0 1 'F3' 'Repeat find backward' [25] KKž0 1 0 'F3' 'Find current selection' [26] KKž0 1 1 'F3' 'Find current selection backward' [27] KKž1 0 0 'F3' 'Find dialog (same as Ctrl+F)' [28] KKž0 0 0 'F4' '' [29] KKž1 0 0 'F4' 'End APL session' [30] KKž0 0 0 'F5' 'Run [CW]' [31] KKž0 1 0 'F5' 'Set next statement [CW]' [32] KKž0 0 0 'F6' '' [33] KKž0 1 0 'F6' 'Next window' [34] KKž0 1 1 'F6' 'Previous window' [35] KKž0 0 0 'F7' '' [36] KKž0 1 0 'F7' 'Run to cursor or below [CW]' [37] KKž0 1 1 'F7' 'Run to cursor [CW]' [38] KKž0 0 0 'F8' '' [39] KKž0 0 0 'F9' 'Recall previous line backward' [40] KKž0 0 1 'F9' 'Recall previous line forward' [41] KKž0 1 0 'F9' 'Recall line dialog' [42] KKž1 0 0 'F9' 'Jump to previous executed line' [43] KKž1 0 1 'F9' 'Jump to next executed line' [44] KKž0 0 0 'F10' 'Step to next statement [CW]' [45] KKž0 0 1 'F10' 'Step to next line [CW]' [46] KKž0 1 0 'F10' 'Step over by primitive [CW]' [47] KKž0 0 0 'F11' 'Step into function [CW]' [48] KKž0 0 1 'F11' 'Step out of function [CW]' [49] KKž0 1 0 'F11' 'Step into by primitive [CW]' [50] KKž0 0 0 'F12' 'Copy code to APL session [CW]' [51] KKž0 1 0 'F12' 'Edit pending function' [52] [53] KKž0 1 0 'A' 'Select all' [54] KKž0 1 1 'A' ')SAVE As dialog' [55] ¦KKž0 1 0 'B' 'Breakpoint set' ¦¦¦¦¦¦¦ I think that's an error [56] KKž0 1 0 'C' 'Copy' [57] KKž0 1 1 'C' ')COPY dialog' [58] KKž0 1 1 'D' ')DROP dialog' [59] KKž0 1 0 'E' 'End and save edit' [60] KKž0 1 0 'F' 'Find dialog' [61] KKž0 1 0 'G' 'Get (Fetch dialog)' [62] KKž0 1 1 'G' 'Gather selected executed lines to clipboard' [63] KKž0 1 0 'J' 'Jump dialog' [64] KKž0 1 1 'J' 'Jump to column dialog' [65] KKž0 1 0 'K' 'Show/hide Code Walker' [66] KKž1 1 0 'K' 'Show/hide code window [CW]' [67] KKž0 1 1 'K' 'Show/hide state indicator window [CW]' [68] KKž0 1 0 'L' 'Localize toggle' [69] KKž0 1 1 'L' ')LOAD dialog' [70] KKž0 1 0 'M' 'Match paren/quote/bracket' [71] KKž0 1 1 'M' 'Match paren/quote/bracket and select' [72] KKž0 1 0 'N' 'New edit' [73] KKž0 1 0 'O' 'Open edit dialog' [74] KKž0 1 1 'O' 'Open edit session on object at caret' [75] KKž0 1 0 'P' 'Print dialog' [76] KKž0 1 1 'P' ')PCOPY dialog' [77] KKž0 1 0 'Q' 'Quit edit' [78] KKž0 1 0 'R' 'Replace dialog' [79] KKž0 1 1 'R' ')CLEAR dialog' [80] KKž0 1 0 'S' 'Save edit' [81] KKž0 1 0 'T' 'Toggle edit and session' [82] KKž0 1 0 'V' 'Paste' [83] KKž0 1 0 'W' 'Watchpoints dialog' [84] KKž0 1 0 'X' 'Cut' [85] KKž0 1 0 'Z' 'Undo' [86] [87] KKž0 1 0 '' 'Scroll down without moving caret' [88] KKž0 1 1 '' 'Move the cursor line to the bottom of the page' [89] KKž0 1 0 '' 'Scroll up without moving caret' [90] KKž0 1 1 '' 'Move the cursor line to the top of the page' [91] KKž0 1 1 'End' 'Select from caret to end' [92] KKž1 0 1 'End' 'Erase from caret to end of session log' [93] KKž0 1 1 'Home' 'Select from caret to beginning' [94] KKž0 1 0 'PgDn' 'Scroll left' [95] KKž0 1 0 'PgUp' 'Scroll right' [96] KKž0 0 0 'Tab' 'Insert tab indent' [97] KKž0 0 1 'Tab' 'Remove tab indent' [98] KKž0 1 0 'Tab' 'Next window' [99] KKž0 1 1 'Tab' 'Previous window' [100] KKž1 0 0 'Tab' 'Next application [XX]' [101] KKž0 1 0 'Space' 'Insert space indent' [102] KKž0 1 1 'Space' 'Remove space indent' [103] KKž1 0 0 'Bksp' 'Undo (same as Ctrl+Z)' [104] KKž0 0 1 'Del' 'Cut (same as Ctrl+X)' [105] KKž0 0 1 'Ins' 'Paste (same as Ctrl+V)' [106] KKž0 1 0 'Ins' 'Copy (same as Ctrl+C)' [107] KKž0 1 0 'Enter' 'Insert line in session (without execution)' [108] KKž0 1 1 'Enter' 'Move the cursor line to the middle of the page' [109] KKž0 1 0 '/' 'Insert lamp' [110] KKž0 1 1 '/' 'Remove lamp' [111] KKž0 1 0 '+' 'Increase font size' [112] KKž0 1 1 '+' 'Decrease font size' [113] KKž0 1 0 '.' 'Stop toggle' [114] KKž0 1 0 ',' 'Trace toggle' [115] KKž0 1 1 '.' 'Stop remove' [116] KKž0 1 1 ',' 'Trace remove' [117] [118] KKž0 1 0 'Num *' 'Top of stack [CW]' [119] KKž0 1 0 'Num -' 'Up one stack level [CW]' [120] KKž0 1 0 'Num +' 'Down one stack level [CW]' [121] KKž0 1 0 'Num /' 'Bottom of stack [CW]' [122] [123] K[;4],K[;4] ¦ else Listview has a fit [124] [125] k [2] K[;â4] [126] Assert (kâk)^.=âûk ¦ no dups [127] [128] ¦ [Tools] [129] ¦ Command1=0 •inbuf ')edit ',((,1[•io]•si)~'*'),•tcnl [130] ¦ MenuItem1=&Edit Suspended Function F11 [131] ¦ Command2=)RESET [132] ¦ MenuItem2=Quit &All Suspended Functions F4 [133] ¦ Command3=)edit ì [134] ¦ MenuItem3=Edit &Current Object F5 [135] [136] ¦ For case-insensitive match below [137] dK[;â4] [138] d[;4]ñUCASEd[;4] [139] d [2] d [140] [141] KK, '' [142] [143] s0 0 0 '' [144] :for i :in â32 [145] m•wcall 'W_Ini' ('[Tools] MenuItem',ôi) [146] :if mð'' [147] :leave [148] :end [149] c•wcall 'W_Ini' ('[Tools] Command',ôi) [150] mñDEB m [151] k(è^\èm†' ')/m ¦ last word 'ctrl+f9' [152] w(è^\èk†'+')/k ¦ word after last + 'f9' [153] (1w)ñUCASE 1w ¦ mixed -- this works unless PgUp or TAB [154] kñUCASE k ¦ upper all for matching [155] s[1]ú/k •SS 'ALT+' [156] s[2]ú/k •SS 'CTRL+' [157] s[3]ú/k •SS 'SHIFT+' [158] s[4] ñUCASE w [159] ¦ Is it really a key? [160] :if ú/3ûs [161] :orif ('F'=1w)^(1•FI 1w)îâ12 [162] m(-1+ûk)m [163] m0 WinAmps m [164] jdâ s [165] :if jóûûd [166] K[j;6] m [167] ¦display K[j;] [168] :else [169] KKž(3ûs),w '' m [170] ¦display (3ûs),w '' m [171] :end [172] :end [173] :end [174] [175] ¦ Create the form [176] [177] w•FI UcmdIni 'Keys-Where' '4 10 20 78' [178] [179] •wself'fmKeys' •wi 'Create' 'Form' 'Close' [180] •wi 'caption' 'Keys' [181] •wi 'where' w [182] •wi 'limitwhere' 8 20 [183] •wi 'onResize' '0 CMDKEYS •wevent' [184] •wi 'onClose' '0 CMDKEYS •wevent' [185] [186] •wself':mFile' •wi 'New' 'Menu' ('caption' '&File') [187] k'.mExit' •wi 'New' 'Menu' ('caption' 'E&xit') ('onClick' 'k":" •wi "Close"') ('shortcut' 27 0) [188] [189] •wself':mEdit' •wi 'New' 'Menu' ('caption' '&Edit') [190] k'.mCW' •wi 'New' 'Menu' ('caption' 'Remove code &walker keys') ('onClick' '0 CMDKEYS "CW"') ('shortcut' 'W' 2) [191] k'.mCopy' •wi 'New' 'Menu' ('caption' '&Copy list to clipboard') ('onClick' '0 CMDKEYS "Copy"') ('shortcut' 'C' 2) [192] [193] •wself':lv' •wi 'New' 'Listview' ('style' 1 2 4 4096) ¦ 4096=gridlines [194] [195] ¦ This allows user to type a letter to jump in the Key column [196] d0 5û ¦ 4=col id (ptr into list), 5=col order [197] ddž'Key' 2 'left' 5 5 [198] ddž'A' 2 'left' 1 1 [199] ddž'C' 2 'left' 2 2 [200] ddž'S' 2 'left' 3 3 [201] ddž'Shifts' 20 'right' 4 4 [202] ddž'Default' 30 'left' 6 6 [203] ddž'Tool' 30 'left' 7 7 [204] [205] •wi 'columndisplay' d [206] [207] •wi 'scale' 3 ¦ font size will be specified in points [208] •wi 'font' (UcmdFont '') [209] [210] MK[;1 1 1 1 4 5 6] [211] M[;1]K[;1]û'A' [212] M[;2]K[;2]û'C' [213] M[;3]K[;3]û'S' [214] M[;4]((4’K[;1])û 'Alt+') , ((5’K[;2])û 'Ctrl+') , ((6’K[;3])û 'Shift+') [215] [216] •wi 'list' (0,1,M) [217] [218] •wi 'onColClick' '0 CMDKEYS "Sort"' [219] •wi 'onDblClick' '0 CMDKEYS "Detail"' [220] •wi 'onOpen' "•wi 'AutoFit' 'header' 'all'" [221] •wi 'onKeyPress' '0 CMDKEYS •wevent' [222] [223] •wself':' [224] k•wi 'Wait' [225] •wi 'Delete' [226] 0 [227] [228] L1: [229] [230] :SELECT A [231] [232] :CASE 'Resize' [233] [234] (1=3•warg)û0 ¦ noop if minimize [235] [236] ':lv' •wi 'where' (0 0,2•warg) [237] [238] :CASE 'Sort' [239] [240] D•wi 'sortorder' ¦ current order [241] I•first •warg ¦ column number [242] M[2] ,•wi 'GetCells' D I ¦ the data [243] F( I,3)•wi 'columndisplay' ¦ justification [244] :if I=5 ¦ Key [245] I•AVM ¦ ascending order [246] Lý1’1=+/M[I;]†' ' ¦ first, one-letter keys [247] LL+(M[I;1]='F')’•FI ,'0',0 1M[I;],' ' ¦ second, function keys, in numeric order [248] LL+99’L=0 ¦ then the rest [249] II[L] [250] :elseif Fð'right' ¦ numeric column? [251] M(-+/^\èM=' ')èM ¦ RJUST [252] I•AVM ¦ descending [253] :else ¦ text column [254] I•AVM ¦ ascending order [255] :end [256] [257] :if IðâûI  IèI  :end ¦ reverse sort [258] [259] •wi 'sortorder' (D[I]) ¦ reset the sortorder [260] [261] :CASE 'KeyPress' [262] [263] :if •warg=13 ¦ Enter key? [264] 0 CMDKEYS 'Detail' [265] :end [266] [267] :CASE 'Close' [268] [269] (•wi 'where') UcmdIni 'Keys-Where' [270] [271] :CASE 'CW' [272] [273] •wi 'enabled' 0 [274] [275] •wself':lv' [276] D•wi 'sortorder' ¦ row order [277] M•wi 'GetCells' D (â7) [278] Pú/M[;6] •SS '[CW]' [279] •wi 'SetCells' (P/D) 6 ((+/P)û '') [280] ¦ Don't delete if a Tool is defined [281] PP^M[;7]ð '' [282] ¦ Or if it's an unshifted F key [283] PP>('F'=•enlist 1M[;5])^((•enlist 11M[;5])î'123456789')^M[;4]ð '' [284] •wi 'DeleteRows' (P/D) [285] [286] :CASE 'Copy' [287] [288] •wself':lv' [289] D•wi 'sortorder' ¦ row order [290] L•wi 'columndisplay' [291] M•wi 'GetCells' D (â1ûL) ¦ the data [292] ML[L[;5];1]žM ¦ add column headings, in column order [293] M•TCHT,M [294] MM, •TCNL,•TCLF [295] V•enlist 1•enlist•split M [296] VñAV2ANSI[•AVâV] [297] H•wcall 'GlobalAlloc' 'GMEM_MOVEABLE' (1+•first ûV) [298] •error (H=0)/'Unable to allocate memory for copy' [299] P•wcall 'GlobalLock' H [300] •error (P=0)/'Unable to lock memory for copy' [301] K•wcall 'W_Mem' (P,0,1, V,•tcnul) [302] K•wcall 'GlobalUnlock' H [303] w'#' •wi 'hwndmain' [304] •error (0=•wcall 'OpenClipboard' w)/'Clipboard busy' [305] K•wcall 'EmptyClipboard' [306] K•wcall 'SetClipboardData' 'CF_TEXT' H [307] K•wcall 'CloseClipboard' [308] [309] :ELSE [310] [311] •'*** Unanticipated CMDKEYS case: ',ôA [312] [313] :END ì ì €US<')/F ¦ ditch •SI levels that don't have matching •IDLOC columns [45] TFâ']' ¦ how much UCMD crap is there [46] TT*TóûF ¦ or 1 if no ] (non-UCMD) [47] [48] ¦ Sidebar: If function name given, go straight to the details [49] [50] :if ~Að'' [51] D•NC A ¦ •NC tolerates bad names [52] :if 4îD [53] :orif 1<ûD [54] ñOUT 'Invalid function name: ',A [55] 0 [56] :end [57] I,•IDLOC A [58] :if ý1ú.†TI [59] ñOUT 'Shadowed: ',A [60] 0 [61] :end [62] :if D†3 [63] ñOUT 'Not a function: ',A [64] 0 [65] :end [66] D•MF A [67] :if 0îûD [68] ñOUT 'No monitoring data for: ',A [69] 0 [70] :end [71] A D CMDMF 'FnDetail' [72] 0 [73] :end [74] [75] ¦ Continuing: Find names of all non-localized functions [76] [77] DIKMN0 ¦ give all our locals values, so they'll show up in •NL [78] L0 ¦ arg too [79] R0 ¦ result too [80] [81] F•NL 1 2 3 ¦ all names [82] I•IDLOC F ¦ what are they [83] D(0,T)I ¦ drop our local classification [84] D(,<\ý1†D)/,D ¦ next-most-local classification [85] DD=1 ¦ which are fns [86] FDëF ¦ just fns [87] IDëI ¦ just fns [88] D(T[2]I)^.=ý1 ¦ which are not shadowed [89] :if 0îD [90] ñOUT 'SHADOWED: ',ñDEB,' ',(~D)ëF [91] FDëF [92] :end [93] [94] ¦ Whew -- now we have fn names in F [95] [96] •ERASE 'R' ¦ clear result [97] [98] :if 0îûF [99] ñOUT 'This is a CLEAR WS' [100] 0 [101] :end [102] [103] :if Oî0 1 [104] N(1+O)'off' 'on' [105] DO •MF F [106] ñOUT 'Monitoring turned ',N,' for ',(ô+/D),' functions' [107] D~D [108] :if 1îD [109] ñOUT '* •MF failed for ',(ô+/D),' functions: ',ñDEB,' ',DëF [110] :end [111] 0 [112] :end [113] [114] FWords F [115] [116] NûF [117] M(N,9)û0 ¦ two extra columns for raw time data [118] M[;1]F ¦ function names [119] M[;8 9]ý1 ¦ to flag rows with no •MF data [120] :for I :in âN [121] D•MF IF [122] :if 0<•first ûD [123] M[I;8]D[1;1] ¦ total time used by function (will be M[;2]) [124] M[I;9]+/D[;2] ¦ total time used directly by function (will be M[;3]) [125] M[I;5]/D[;3] ¦ max iteration count [126] M[I;6]D[1;3] ¦ number of times called [127] :end [128] T•CRL (IF),'[0]' ¦ header line [129] :if Tð'' [130] M[I;7] '(locked)' [131] :else [132] M[I;7] (ú\T†' ')/T ¦ some headers have leading blank [133] :end [134] :end [135] MM[M[;9];] ¦ sort by time here (and because of ý1's, no data falls below 0) [136] TM[;9]<0 ¦ remember which have no data [137] D0M[;9] ¦ ditch ý1's [138] M[;4]100’Dö+/D ¦ percent of time here [139] [140] M[;2 3] '' ¦ times [141] M[;5 6]ôM[;5 6] ¦ iter calls [142] M[;4]12ôM[;4] ¦ percent (2ô returns one leading blank) [143] ¦ Save raw data in case resolution is changed [144] ¦ Using •FMT avoids loss of precision from ô and •PP [145] M[;8]•split 'I17' •FMT M[;8] [146] M[;9]•split 'I17' •FMT M[;9] [147] [148] M[T/âN;4 5 6] '' ¦ no monitoring data [149] [150] :if ^/T [151] ñOUT 'No functions in this ws have any monitoring data' [152] 0 [153] :end [154] [155] ¦ Create the form [156] [157] w•FI UcmdIni 'MF-Place' '4 10 20 78' [158] v•FI UcmdIni 'MF-Visible' '1' [159] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [160] [161] •wself'fmMF' •wi 'Create' 'Form' 'Close' [162] •wi 'caption' ('MF summary for wsid: ',ñDEB •WSID) [163] •wi 'place' w [164] •wi 'visible' v [165] •wi 'limitwhere' 8 20 [166] •wi 'onResize' '0 CMDMF •wevent' [167] •wi 'onClose' '0 CMDMF •wevent' [168] [169] •wself':mFile' •wi 'New' 'Menu' ('caption' '&File') [170] K'.mDetail' •wi 'New' 'Menu' ('caption' 'Function &Detail...') ('onClick' '0 CMDMF "Detail"') ('shortcut' 'D' 2) [171] ¦K'.mPrint' •wi 'New' 'Menu' ('caption' '&Print...') ('onClick' '0 CMDMF "Print"') ('shortcut' 'P' 2) [172] K'.mSep1' •wi 'New' 'Menu' ('separator' 1) [173] K'.mExit' •wi 'New' 'Menu' ('caption' 'E&xit') ('onClick' 'K":" •wi "Close"') ('shortcut' 27 0) [174] [175] •wself':mEdit' •wi 'New' 'Menu' ('caption' '&Edit') [176] K'.mCopy' •wi 'New' 'Menu' ('caption' '&Copy entire list to clipboard') ('onClick' '0 CMDMF "Copy"') ('shortcut' 'C' 2) [177] [178] •wself':mView' •wi 'New' 'Menu' ('caption' '&View') [179] K'.mHide' •wi 'New' 'Menu' ('caption' '&Hide fns with no time') ('onClick' '0 CMDMF "Hide"') ('style' 1) ('shortcut' 'H' 2) [180] ¦ K'.mRefresh' •wi 'New' 'Menu' ('caption' '&Refresh') ('onClick' '0 CMDMF "Refresh"') ('shortcut' 116 0) ¦ 116=F5 [181] [182] •wself':mRes' •wi 'New' 'Menu' ('caption' '&Resolution') [183] K'.mRaw' •wi 'New' 'Menu' ('caption' '&Raw Ticks') ('onClick' '1 CMDMF "Res"') ('suppress' 1) ('shortcut' 'R' 2) [184] K'.mMsec' •wi 'New' 'Menu' ('caption' '&Millisecs') ('onClick' '2 CMDMF "Res"') ('suppress' 1) ('shortcut' 'M' 2) [185] K'.mSec' •wi 'New' 'Menu' ('caption' 'MM:&SS.mmm') ('onClick' '3 CMDMF "Res"') ('suppress' 1) ('shortcut' 'S' 2) [186] [187] •wself':bnExit' •wi 'New' 'Button' 'Hide' ('style' 2) ¦ 2=cancel [188] [189] •wself':lv' •wi 'New' 'Listview' ('style' 1 2 4 4096) ¦ 4096=gridlines [190] [191] •wi 'columndisplay' (7 3û'Function' 20 'left' 'Total' 10 'right' 'Here' 10 'right' 'Pct' 10 'right' '/It' 10 'right' 'Calls' 10 'right' 'Header' 10 'left') [192] [193] •wi 'scale' 3 ¦ font size will be specified in points [194] •wi 'font' (UcmdFont '') [195] [196] •wi 'list' (0,1,M) [197] •wi 'onColClick' '0 CMDMF "Sort"' [198] •wi 'onDblClick' '0 CMDMF "Detail"' [199] •wi 'onOpen' "•wi 'AutoFit' 'header' 'all'" [200] •wi 'onKeyPress' '0 CMDMF •wevent' [201] [202] •wself':' [203] •wi 'Show' [204] ':mRes.mMsec' •wi 'Click' ¦ milliseconds [205] K•wi 'Wait' [206] •wi 'Delete' [207] 0 [208] [209] L1: ¦ •'MF case: ',ôA [210] [211] :SELECT A [212] [213] :CASE 'Print' ¦ print the listview [214] [215] ¦ This works for both Listviews [216] A']WPRINT :lv /QUIET /H=',•TCHT,•wi ':caption' [217] K•UCMD A [218] [219] :CASE 'Hide' [220] [221] ¦ This works for both Forms (and Listviews) [222] T1=•wi 'value' ¦ hide zero lines? [223] •wself':lv' [224] :if T [225] M•wi 'list' [226] •wi '‘list' M ¦ save for later [227] D•FI •enlist M[;2+8] ¦ raw ticks [228] M(D>0)ëM [229] :else ¦ unhide lines [230] M•wi '‘list' ¦ get old list [231] :end [232] •wi 'list' M [233] [234] :CASE 'Res' [235] [236] ¦ This works for both Forms (and Listviews) [237] (1=•wi 'value')û0 ¦ already checked? [238] (•wi 'siblings')•wi 'value' 0 ¦ turn off all checks [239] •wi 'value' 1 ¦ turn my check on [240] [241] D•wi 'caption' [242] D(^\D†•TCHT)/D ¦ ditch possible shortcut [243] DD~'&' ¦ ditch possible key [244] [245] ':mRes' •wi 'caption' ('&Resolution (',D,')') [246] [247] T1=':mView.mHide' •wi 'value' ¦ hide zero lines? [248] [249] •wself':lv' [250] [251] :if T [252] M•wi '‘list' [253] :else [254] M•wi 'list' [255] :end [256] [257] D•FI •enlist M[;2+8]  M[;2+2](D L) CMDMF 'FmtTicks' [258] D•FI •enlist M[;2+9]  M[;2+3](D L) CMDMF 'FmtTicks' [259] [260] :if T ¦ hide zero lines [261] •wi '‘list' M [262] M(D>0)ëM [263] :end [264] [265] •wi 'list' M [266] •wi 'AutoFit' 'header' 2 3 [267] [268] :CASE 'FmtTicks' [269] [270] (T F)L ¦ raw ticks, format [271] :select F [272] :case 1 ¦ raw ticks [273] R•SPLIT 'CI19' •FMT T [274] :case 2 ¦ milliseconds [275] R3ôT’•MF ý1 [276] :case 3 ¦ seconds [277] R•SPLIT 'G' •FMT 0 100 100 1000æ0 60 60 1000 ç 0.5+T’•MF ý1 [278] :else ¦ tilt [279] ö0 [280] :end [281] ((T<0)/R) '' ¦ missing data [282] RR~' ' ¦ DLB [283] [284] :CASE 'Resize' [285] [286] ¦ This works for both Forms (and Listviews) [287] [288] (1=3•warg)û0 ¦ noop if minimize [289] [290] ':lv' •wi 'where' (0 0,2•warg) [291] [292] :CASE 'Sort' [293] [294] ¦ This works for both Listviews [295] D•wi 'sortorder' ¦ current order [296] I•first •warg ¦ column number [297] M[2] ,•wi 'GetCells' D I ¦ the data [298] F( I,3)•wi 'columndisplay' ¦ justification [299] :if Fð'right' ¦ numeric column? [300] M(-+/^\èM=' ')èM ¦ RJUST [301] I•AVM ¦ descending [302] :else ¦ text column [303] I•AVM ¦ ascending order [304] :end [305] [306] :if IðâûI  IèI  :end ¦ reverse sort [307] •wi 'sortorder' (D[I]) ¦ reset the sortorder [308] [309] :CASE 'KeyPress' [310] [311] :if •warg=13 ¦ Enter key? [312] 0 CMDMF 'Detail' [313] :end [314] [315] :CASE 'Detail' [316] [317] •wself':lv' [318] I•first •wi 'value' ¦ selected row [319] :if I=0 [320] I•first •wi 'sortorder' ¦ first in list [321] (I=0)û0 [322] :end [323] F•first •wi 'GetCells' I 1 ¦ function name [324] D•MF F [325] :if 0îûD [326] K•wcall 'MessageBeep' 0 ¦ ding [327] 0 [328] :end [329] F D CMDMF 'FnDetail' [330] [331] :CASE 'FnDetail' [332] [333] (F D)L ¦ function name, •MF data [334] N•first ûD [335] M(N,9)û '' ¦ 9 cols, like summary form [336] ¦ We want these to sort correctly, so we don't left-justify them like •VR does [337] T'<',F,'[>,Q<]>I',ô1+ûôN-1 ¦ here's a technique from the old days [338] M[;1]•split T •FMT ý1+âN [339] M[1;1] F ¦ I prefer no [0] since these are totals [340] ¦ Time spent "here" on header line is negligible [341] ¦ Much more interesting is sum of time spent here on all lines [342] D[1;2]+/D[;2] [343] M[;4]ôD[;3] ¦ iterations [344] T•VR F [345] M[;5]ý1(T†•TCNL) Partition T ¦ drop trailing ì line [346] M[;8]•split 'I17' •FMT D[;1] [347] M[;9]•split 'I17' •FMT D[;2] [348] [349] TF ¦ for caption [350] ((T='‘')/T)'+' [351] ((T='ñ')/T)•AV[249+•IO] ¦ for a Form caption, that yields the plus-or-minus symbol [352] [353] w•FI UcmdIni 'MFDetail-Place' '3 15 24 70' [354] v•FI UcmdIni 'MFDetail-Visible' '1' [355] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [356] [357] •wself'fmMFDetail' •wi 'Create' 'Form' 'Close' [358] •wi 'caption' ('MF detail for function: ',T) [359] •wi 'place' w [360] •wi 'visible' v [361] •wi 'limitwhere' 8 20 [362] •wi 'border' 2 16 64 [363] •wi 'onResize' '0 CMDMF •wevent' [364] •wi 'onClose' '0 CMDMF •wevent' [365] •wself':mFile' •wi 'New' 'Menu' ('caption' '&File') [366] ¦K'.mPrint' •wi 'New' 'Menu' ('caption' '&Print...') ('onClick' '0 CMDMF "Print"') ('shortcut' 'P' 2) [367] ¦K'.mSep1' •wi 'New' 'Menu' ('separator' 1) [368] K'.mExit' •wi 'New' 'Menu' ('caption' 'E&xit') ('onClick' 'K":" •wi "Close"') ('shortcut' 27 0) [369] •wself':mEdit' •wi 'New' 'Menu' ('caption' '&Edit') [370] K'.mCopy' •wi 'New' 'Menu' ('caption' '&Copy entire list to clipboard') ('onClick' '0 CMDMF "Copy"') ('shortcut' 'C' 2) [371] •wself':mView' •wi 'New' 'Menu' ('caption' '&View') [372] K'.mHide' •wi 'New' 'Menu' ('caption' '&Hide lines with no time') ('onClick' '0 CMDMF "Hide"') ('style' 1) ('shortcut' 'H' 2) [373] •wself':mRes' •wi 'New' 'Menu' ('caption' '&Resolution') [374] K'.mRaw' •wi 'New' 'Menu' ('caption' '&Raw Ticks') ('onClick' '1 CMDMF "Res"') ('suppress' 1) ('shortcut' 'R' 2) [375] K'.mMsec' •wi 'New' 'Menu' ('caption' '&Millisecs') ('onClick' '2 CMDMF "Res"') ('suppress' 1) ('shortcut' 'M' 2) [376] K'.mSec' •wi 'New' 'Menu' ('caption' 'MM:&SS.mmm') ('onClick' '3 CMDMF "Res"') ('suppress' 1) ('shortcut' 'S' 2) [377] [378] •wself':lv' •wi 'New' 'Listview' ('style' 1 2 4 4096) ¦ 4096=gridlines [379] [380] •wi 'scale' 3 ¦ font size will be specified in points [381] •wi 'font' (UcmdFont '') [382] [383] •wi 'columndisplay' (5 3û'Line' 20 'left' 'Total' 10 'right' 'Here' 10 'right' 'Iter' 10 'right' 'Instruction' 40 'left') [384] •wi 'list' (0,1,M) [385] [386] •wi 'onOpen' "•wi 'AutoFit' 'header' 'all'" [387] •wi 'onColClick' '0 CMDMF "Sort"' [388] [389] •wself':bnExit' •wi 'New' 'Button' 'Hide' ('style' 2) ¦ 2=cancel [390] •wself':' [391] •wi 'Show' [392] ':mRes.mMsec' •wi 'Click' [393] K•wi 'Wait' [394] •wi 'Delete' [395] [396] :CASE 'Close' [397] [398] :select •wself [399] :case 'fmMF' [400] (•wi 'place') UcmdIni 'MF-Place' [401] (•wi 'visible') UcmdIni 'MF-Visible' [402] :case 'fmMFDetail' [403] (•wi 'place') UcmdIni 'MFDetail-Place' [404] (•wi 'visible') UcmdIni 'MFDetail-Visible' [405] :else [406] ö'tilt' [407] :end [408] [409] :CASE 'Copy' [410] [411] ¦ Copy to clipboard (works for both Listviews) [412] [413] •wself':lv' [414] D•wi 'sortorder' ¦ current order [415] L•wi 'columndisplay' [416] M•wi 'GetCells' D (â1ûL) ¦ the data [417] ML[;1]žM ¦ column headings [418] M•TCHT,M [419] MM, •TCNL,•TCLF [420] v•enlist 1•enlist•split M [421] vñAV2ANSI[•AVâv] [422] h•wcall 'GlobalAlloc' 'GMEM_MOVEABLE' (1+•first ûv) [423] •error (h=0)/'Unable to allocate memory for copy' [424] p•wcall 'GlobalLock' h [425] •error (p=0)/'Unable to lock memory for copy' [426] K•wcall 'W_Mem' (p,0,1, v,•tcnul) [427] K•wcall 'GlobalUnlock' h [428] w'#' •wi 'hwndmain' [429] •error (0=•wcall 'OpenClipboard' w)/'Clipboard busy' [430] K•wcall 'EmptyClipboard' [431] K•wcall 'SetClipboardData' 'CF_TEXT' h [432] K•wcall 'CloseClipboard' [433] [434] :ELSE [435] [436] •'*** Unanticipated case: ',ôA [437] [438] :END ì €US<1¦¦ ì CMDNOTLOCAL N;A;F;R;S;V;c;d;f;g;h;i;n;p;t;u;x [1] ¦ Search active workspace for non-localized identifier references or assignments [2] ¦ (Find who uses a global variable; where it came from; who changed it) [3] ¦ Does not look in comments and quoted strings [4] [5] ¦ Syntax: [6] ¦ ]NOTLOCAL foo [7] ¦ ]NOTLOCAL foo ¦ only show assignments (indexed/vector/selective) [8] ¦ ]NOTLOCAL foo / ¦ same as above [9] ¦ ]NOTLOCAL foo /R ¦ don't show hits; just return function names [10] ¦ ]NOTLOCAL foo /F=foo ¦ only look in specified functions [11] [12] ¦ 23 Jun 1992 Rex Swain, Independent Consultant, www.rexswain.com [13] ¦ 29 Nov 1994 Adapted for Dyalog APL/W [14] ¦ 25 Nov 1999 Adapted for APL+Win; removed # and  options [15] ¦ 24 Nov 2002 Adapted for UCMD; use Zark's ParseVR [16] ¦ 27 Jul 2003 Correct •SI/•IDLOC alignment [17] ¦ 26 Mar 2005 Evlevel-neutral [18] ¦ 09 Oct 2010 Use •VGET and 0 •VR and etc. to avoid shadowing (req APL ver 7.2) [19] [20] A''îN ¦ assignment mode? [21] [22] R1=ûûN ñGETOPT '/R' ¦ result only? [23] F,N ñGETOPT '/F' ¦ specific function names [24] [25] N(^\~Nî'/-')/N ¦ delete all options [26] NN~" " ¦ no spaces and flags [27] [28] :if N^.=' ' ¦ no name? [29] ñOUT 'For help, execute',•tcnl,' ]NOTLOCAL ?' [30] 0 [31] :end [32] [33] S'•'=•FIRST N ¦ system name? [34] [35] :if 4=•NC SN [36] ñOUT 'INVALID IDENTIFIER NAME: ',N [37] 0 [38] :end [39] [40] :if ’ûF ¦ specified functions? [41] F[2] Words F [42] t3†0 •NC F ¦ which are not fns [43] n+/t [44] :if n>0 [45] ñOUT 'NOT FUNCTION',(n=1)'S:',ôWords tëF [46] F(~t)ëF [47] :end [48] :else [49] F0 •NL 3 ¦ all global fns [50] :end [51] [52] FWords F [53] u•FIRST ûF ¦ how many fns [54] [55] ñOUT 'Searching ',(ôu),' function',(u=1)'s ...' [56] [57] •WGIVE 0 ¦ let that message display [58] [59] :if R ¦ result only-mode? [60] ñRESULT0û '' [61] :end [62] [63] :if S [64] NñUCASE N [65] :end [66] [67] :for f :in F ¦ next function [68] [69] V0 •VR f [70] [71] :if 0=ûV [72] ñOUT '* LOCKED: ',f [73] •WGIVE 0 ¦ allow display [74] :continue [75] :end [76] [77] :if S ¦ system name? [78] (n x d g t)5ParseVR V ¦ names context disp length system [79] (t/n)ñUCASEt/n [80] :else ¦ regular name [81] ¦ try to avoid ParseVR -- see if any raw hits [82] :if ~ú/V •SS N ¦ bail if no raw hits [83] :continue [84] :end [85] (n x d g t)5ParseVR V ¦ names context disp length system [86] :end [87] ¦ thanks a million, Zark! [88] ¦ •n,x,d,g,[1.5]t [89] hnî N ¦ hits on name ¦ î is twice as fast as ð [90] [91] ¦ bail if localized [92] :if ú/(h/x)î'ûà;' ¦ result leftarg rightarg local label [93] :continue [94] :end [95] [96] :if A ¦ assignments only? [97] hh^xî')]' ¦ direct strand indexed selective [98] :else [99] hh^x†':' ¦ ignore control structure names [100] :end [101] [102] :if ~ú/h ¦ might not have any hits left now [103] :continue [104] :end [105] [106] ¦ we have some hits! [107] [108] :if R ¦ result only-mode? [109] ñRESULTñRESULT, N [110] :continue [111] :end [112] [113] ñOUT '==> ',f,' (',(ô+/h),')' [114] [115] ¦ squeeze •VR to just lines containing hits [116] [117] ¦ p1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs) [118] ¦ but, since we never show the header line, we can get away with: [119] pV •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs) [120] p[1,ý6+ûV]1 ¦ force start of header and end of last line [121] t(ûV)û0  t[h/d]1 ¦ convert name hit flags to •VR flags [122] cú/p •PENCLOSE t ¦ flag lines with any hits [123] pp/âûp ¦ partition starts [124] g(1p)-ý1p ¦ line lengths [125] gg-1 ¦ not including trailing CR [126] :for i :in c/âûc [127] ¦ APL+Win: Show fn name too so can double-click to edit at that line [128] ñOUT f,V[p[i]+âg[i]] ¦ faster than take/drop approach [129] :end [130] •WGIVE 0 ¦ allow display [131] [132] :end ì — €US1" [441] kk,"@ :orif (ûûv)>2" [442] kk,"@ :orif ^/0 ' 'î•TYPE •enlist v" [443] kk,"@ v•UCMD 'DISPLAY v'" [444] kk,"@ *v" [445] kk,"@ :end" [446] kk,"@ k•WCALL 'W_Edit' j" [447] kk,"@ :end" [448] [449] ((k='*')/k) j [450] k•enlist k [451] k(k†'@') Partition k [452] k•DEF[2]k ¦õ P [453] ¦ ••vr k [454] (rc z t x)4j P N ¦ peek [455] :if rcî1 2 [456] a256 ¦ max width of FFA display [457] zDLB,'CI15' •FMT z ¦ format bytes [458] :if rc=2 ¦ variable [459] t'-' [460] sûx ¦ shape [461] s(ôs),(0=ûs)/'' ¦ format shape [462] dôðx ¦ depth [463] xa FFAW x [464] x(aûx)ûx [465] qxâ'û' [466] :if qóûx [467] :andif q,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6ût [472] d'-' ¦ depth [473] ¦s(ô+/x •SS •TCNL,'['),' lines' [474] :if c='' [475] s'?' [476] x'(locked function)' [477] :else [478] sôûx [479] x(aûx)ûx [480] ((x=•TCNL)/x)' ' [481] :end [482] :end [483] c3 4 5 6 7 ¦ timestamp bytes depth shape value [484] •wi 'SetCells' r c (t z d s x) [485] ¦ display •wi 'GetCells' r c [486] m•wi 'columndisplay' [487] c(0†m[c;2])/c ¦ only visible columns [488] •wi 'AutoFit' 'header' c [489] 0 [490] :end [491] [492] môrc [493] ((m='ý')/m)'-' [494] m'Return code ',m,' from []COPY:',•tcnl [495] [496] :select rc [497] :case 0  mm,'Object not found' [498] :case 127  mm,'Duplicate name in objlist ¦ should not get here!' [499] :case ý2  mm,'Object too large for available space' [500] :case ý3  mm,'Name defined as a label; cannot be changed' [501] :case ý4  mm,'Insufficient space in symbol table and workspace too full to expand symbol table' [502] :case ý6  mm,'Insufficient free space to carry out command' [503] :case 9  m 'Error from []COPY:',•TCNL,(^\•DM†•TCNL)/•DM [504] :else  mm,'Unanticipated return code!' [505] :end [506] [507] k•wcall 'MessageBox' (•wi ':hwnd') m 'COPY ERROR' 'MB_ICONSTOP' [508] [509] :CASE 'Close' [510] [511] (•wi 'place') UcmdIni 'PeekWS-Place' [512] (•wi 'visible') UcmdIni 'PeekWS-Visible' [513] [514] :CASE 'DropDown' [515] [516] ¦ •wself is the form; can't tell which menu item was clicked [517] [518] •wself':lv' [519] [520] i•wi 'sortorder' ¦ all rowids [521] v•wi 'value' ¦ selected rowids [522] nûv [523] [524] •wself':mActions' [525] [526] '.mPeek' •wi 'enabled' (n>0) [527] '.mGet' •wi 'enabled' (n>0) [528] '.mGetAll' •wi 'enabled' ((ûi)>0) [529] '.mDiff' •wi 'enabled' (n=2) [530] '.mRemove' •wi 'enabled' (n>0) [531] [532] :CASE 'Click' [533] [534] ¦ If there are 0 rows selected, act on the pointed-to row [535] ¦ Else always act on selected row(s) [536] [537] a•warg ¦ pointed-to rowid; save to perhaps pass along to DblClick [538] b7a ¦ mouse button (1=left 2=right) [539] (b†2)û0 ¦ quit unless right (row selection has already been toggled) [540] v•wi 'value' ¦ selected rowids [541] r1a ¦ pointed-to rowid; save to perhaps pass along to DblClick [542] r0 ¦ quit if empty row [543] z•first •wi 'GetCells' r 4 ¦ bytes (tells us if we have done Get Info already) [544] [545] f•wself [546] [547] m'mPeekWSPopup' [548] •wselfm •wi 'Create' 'Menu' [549] k'.m1' •wi 'New' 'Menu' ('caption' 'Peek') ('onClick' "':' •wi 'data' 1") [550] k'.m2' •wi 'New' 'Menu' ('caption' 'Get Info') ('onClick' "':' •wi 'data' 2") ('enabled' (0îûz)) [551] k'.m3' •wi 'New' 'Menu' ('caption' 'Diff') ('onClick' "':' •wi 'data' 3") ('enabled' (2=ûv)) [552] k'.m4' •wi 'New' 'Menu' ('caption' 'Remove from list') ('onClick' "':' •wi 'data' 4") [553] [554] •wselff [555] [556] ':' •wi 'Popup' m 2 ¦ 2=make the menu respond to the right mouse button [557] dm •wi 'data' [558] m •wi 'Delete' [559] [560] :select d [561] :case 0 ¦ escape [562] ¦ noop [563] :case 1 ¦ peek [564] r 1 CMDPEEKWS 'PeekRow' [565] :case 2 ¦ get info [566] :for i :in v [567] i 0 CMDPEEKWS 'PeekRow' [568] :end [569] :case 3 ¦ diff [570]  CMDPEEKWS 'Diff' [571] :case 4 ¦ remove [572] •wi 'DeleteRows' v [573] :else ¦ tilt [574] ö0 [575] :end [576] [577] :CASE 'View' [578] [579] ¦ •wself is a menu item [580] v•wi 'value' ¦ value has already changed [581] c•wi 'data' ¦ display column number [582] •wself':lv' [583] :if v ¦ if turning on, we just need to autofit it [584] •wi 'AutoFit' 'header' c [585] :else ¦ if turning off, we need to change width to 0 [586] m•wi 'columndisplay' [587] m[c;2]0 [588] •wi 'columndisplay' m [589] :end [590] [591] :CASE 'FontSize' [592] [593] •'FontSize' •wself [594] c•wi 'caption' [595] •wself':lv' [596] •f•wi 'font' ¦ 'APL+WIN' 11 0 'default' [597] (2f)õc [598] •wi •'font' f [599] [600] :CASE 'GetAll' [601] [602] •wself':lv' [603] w•wi 'sortorder' ¦ all rowids [604] w CMDPEEKWS 'GetRows' [605] [606] :CASE 'GetRows' [607] [608] wG ¦ rowids [609] [610] ':' •wi 'pointer' 11 [611] [612] •wself':bnExit' [613] •wi 'caption' 'Stop' [614] •wi 'onClick' "':' •wi '‘stop' 1" [615] [616] •wself':lv' [617] [618] d,•wi 'GetCells' w 4 ¦ bytes [619] w(0îûd)/w ¦ not got yet [620] [621] :for i :in w [622] •wgive 0 [623] :if ':' •wi '‘stop' [624] ':' •wi '‘stop' 0 [625] :leave [626] :end [627] i 0 CMDPEEKWS 'PeekRow' [628] :end [629] [630] ':' •wi 'pointer' 0 [631] [632] •wself':bnExit' [633] •wi 'onClick' '' [634] •wi 'caption' 'E&xit' [635] [636] :CASE 'Diff' [637] [638] •wself':lv' [639] v•wi 'value' ¦ selected rowids [640] j,•wi 'GetCells' v 1 ¦ names [641] N•wi '‘N' ¦ saved wsid [642] •UCMD •' ]DIFF ',(N,' ',1j),' ; ',N,' ',2j ¦ show ucmd being invoked [643] [644] :ELSE [645] [646] •'Unanticipated callback!' N •wself •wevent •warg [647] [648] :ENDSELECT [649] ì €US<ÞÞ ì CMDPEM J;E;F;G;M;P;Q;S;X;a;c;e;f;h;i;m;p;s;t;x;•ELX;•wself [1] ¦ Properties, Events, Methods [2] [3] ¦ Example: [4] ¦ •wself'fm' •wi 'New' 'Form' [5] ¦ b'.bn' •wi 'New' 'Button' [6] ¦ Usage could be: [7] ¦ ]PEM ¦ •wself [8] ¦ ]PEM 'fm.bn' ¦ quoted name of object (no ambiguity) [9] ¦ ]PEM fm.bn ¦ name of object [10] ¦ ]PEM fm ¦ name of object [11] ¦ ]PEM Label ¦ any class [12] ¦ ]PEM b ¦ variable which names object [13] [14] ¦ Active Objects: [15] ¦ ]PEM •wi 'Slides(1).TextFrame' [16] [17] ¦ Options: [18] ¦ /X ¦ just show ActiveX info [19] ¦ /P /E /M ¦ restrict display [20] ¦ /î string ¦ only show those that match substring (case insensitive) [21] ¦ /î=string ¦ note you need a blank or an equal sign between î and string [22] [23] ¦ Help: [24] ¦ ]PEM Button?style ¦ will display help for Button style property [25] ¦ ¦ requires the file HelpStrings.txt [26] [27] ¦ 09 Nov 2003 Rex Swain, Independent Consultant, www.rexswain.com [28] ¦ 25 Nov 2003 Added generic object capability (just supply the class) [29] ¦ 31 Dec 2003 Added Grid and Chart as generic objects [30] ¦ 15 May 2004 Added /î feature [31] ¦ 20 Sep 2004 Workaround no Info method in APL+Win version ó 5 [32] ¦ 22 Sep 2005 Evlevel-neutral [33] ¦ 20 Dec 2005 Support for UEdit ULabel UButton [34] ¦ 23 Mar 2006 Added ? feature [35] ¦ 29 May 2008 Added "•wi" argument to help with ActiveObject objects [36] ¦ 18 Jul 2010 Avoid NONCE ERROR from ú/ [37] [38] Jô,J [39] [40] P1=•first ûûJ ñGETOPT '/P' ¦ properties? [41] E1=•first ûûJ ñGETOPT '/E' ¦ events? [42] M1=•first ûûJ ñGETOPT '/M' ¦ methods? [43] X1=•first ûûJ ñGETOPT '/X' ¦ activex only? [44] S ,J ñGETOPT '/î' ¦ substring [45] [46] SñUCASE S~' ' [47] [48] ¦p•FX [2] (-Sð'')  'aF a' 'a(ú/(ñUCASEa) •SS S)/a' ¦õ F S [49] ¦  Avoid NONCE ERROR from ú/ [50] p•FX [2] (-Sð'')  'aF a' '(ûa)0  a(ú/(ñUCASEa) •SS S)/a' ¦õ F S [51] [52] :if ~PúEúM [53] PEM1 ¦ default to all [54] :end [55] [56] p•FX [2] (X-1)  "rx r" "r((•firstr)î 'xX+')/r" ¦õ x ¦ /X filter [57] [58] G0 ¦ generic object flag [59] [60] J(^\~Jî'/-')/J ¦ delete all options [61] JDLTB J [62] [63] iý1+Jâ'?' [64] QiJ ¦ possible '?prop' or '??prop' [65] JDTB iJ [66] [67] i/P E M’•enlist û'Properties: ' 'Events: ' 'Methods: ' [68] h-i [69] [70] :if Jð'' ¦ ]pem [71] J•wself [72] :elseif '•WI'ðñUCASE 3J [73] L1 [74] :elseif ú/'''"'îJ ¦ ]pem 'fm.bn' [75] JõJ [76] :else [77] :if '.'îJ ¦ ]pem fm.bn [78] :orif 0†ûJ •wi 'self' ¦ ]pem fm [79] ¦ noop [80] :elseif ( J)î'ActiveControl' 'ActiveObject' [81] •'No can do: ',J [82] 0 [83] :elseif ( J)î'Form' 'MDIForm' [84] •wself'fmCMDPEM' •wi 'Create' J 'Hide' [85] G1 [86] :elseif Jð'Page' [87] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [88] •wself'.sel' •wi 'New' 'Selector' [89] •wself'.pg' •wi 'New' J [90] G1 [91] :elseif Jð'CommandButton' [92] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [93] •wself'.bar' •wi 'New' 'CommandBar' [94] •wself'.b' •wi 'New' J [95] G1 [96] :elseif ( J)îc'#' •wi 'classes' ¦ note c [97] :orif Jð'Frame' ¦ APL 9.2 bug: Frame missing from classes! [98] :orif ( J)î'UEdit' 'ULabel' 'UButton' ¦ sigh -- when will these become visible? [99] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [100] •wself('.',J) •wi 'New' J [101] G1 [102] :elseif Jð'Grid' [103] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [104] •wself('.',J) •wi 'New' 'APL.Grid' [105] G1 [106] :elseif Jð'Chart' [107] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [108] •wself('.',J) •wi 'New' 'ChartFX.Chart' [109] G1 [110] :elseif Jð'WSEngine' [111] •wself'wseCMDPEM' •wi 'Create' 'APLW.WSEngine' ¦ default is hidden [112] G1 [113] :elseif (,2)ð•NC J ¦ variable name? (•nc returns 4 for invalid name) [114] JõJ [115] :else [116] •'Argument is not an object or class: ',J [117] 0 [118] :end [119] :end [120] [121] :if ~G [122] a•ELX [123] •ELX'•(^\•DM†•TCNL)/•DM  0' [124] •wselfJ ¦ OBJECT ERROR if no such [125] •ELXa [126] J•wself ¦ fully qualified name [127] •(h'Object: '),J [128] :end [129] [130] :if ’ûQ [131] ••wi Q [132] 0 [133] :end [134] [135] a•wi 'class' [136] •(h'Class: '),a [137] aað'System' ¦ flag for system object [138] [139] hh+1 ¦ because ô will add a leading blank [140] [141] mx •wi 'methods' [142] f( 'Info')îm ¦ is Info method available (APL+Win version 5) [143] [144] :if P [145] pF x •wi 'properties' [146] :if f [147] tF x •wi 'Info' 'ph' [148] pp,(0=ût)( '++'),t [149] :end [150] •i WW (h'Properties:'),ôp [151] :end [152] [153] :if E [154] eF x •wi 'events' [155] :if f [156] tF x •wi 'Info' 'eh' [157] ee,(0=ût)( '++'),t [158] :end [159] •i WW (h'Events:'),ôe [160] :end [161] [162] :if M [163] ¦mF x •wi 'methods' [164] mF m [165] :if f [166] tF x •wi 'Info' 'mh' [167] mm,(0=ût)( '++'),t [168] :end [169] •i WW (h'Methods:'),ôm [170] :end [171] [172] :if G [173] p':' •wi 'self' ¦ Form or WSEngine [174] p •wi 'Delete' [175] 0 [176] :end [177] [178] (P^E^M)0 ¦ quit unless all [179] (Xú’ûS)û0 ¦ quit if /X or /î [180] [181] c•wi 'children' [182] :if ~a ¦ unless system [183] c(1+•first ûJ)c ¦ drop self-prefix from children [184] :end [185] •i WW (h'Children:'),ôc [186] [187] :if ~a ¦ system object does not have siblings property [188] s•wi 'siblings' [189] ss~ J ¦ don't include self [190] s(+/ú\èJ='.')s [191] •i WW (h'Siblings:'),ôs [192] :end [193] [194] 0 [195] [196] L1: ¦ ----- Active Object ----- [197] [198] ¦ RHS 8/10/08 [199] ¦ 'word.doc' •wi 'xFields(4)' is nice and returns a scalar pointer. [200] ¦ 'word.doc' •wi 'xFormFields(4)' returns a pointer and the item number! [201] ¦ So just use the first number... [202] J'•FIRST ',J [203] [204] :if ’ûQ [205] •(õJ) •wi Q [206] 0 [207] :end [208] [209] a(õJ) •wi 'class' [210] •(h'Class: '),a [211] [212] hh+1 ¦ because ô will add a leading blank [213] [214] :if P [215] pF x (õJ) •wi 'properties' [216] tF x (õJ) •wi 'Info' 'ph' [217] pp,(0=ût)( '++'),t [218] •i WW (h'Properties:'),ôp [219] :end [220] [221] :if E [222] eF x (õJ) •wi 'events' [223] tF x (õJ) •wi 'Info' 'eh' [224] ee,(0=ût)( '++'),t [225] •i WW (h'Events:'),ôe [226] :end [227] [228] :if M [229] mF x (õJ) •wi 'methods' [230] tF x (õJ) •wi 'Info' 'mh' [231] mm,(0=ût)( '++'),t [232] •i WW (h'Methods:'),ôm [233] :end [234] ì €US< ì b CMDPKGDOC f;C;K;M;P;cw;c;d;i;k;max;m;n;p;q;r;s;t;uw;u;v;w;x;z;•wself [1] ¦ Package documentation [2] ¦ Syntax: [3] ¦ ]PkgDoc variablename [4] ¦ ]PkgDoc tienumber[,] componentnumber [5] ¦ You may double-click a row to display the value [6] ¦ This uses )EDIT, so it does not work for nested values [7] ¦ Any changes are NOT replaced [8] ¦ You may click on a column heading to sort by that column [9] ¦ Click twice for descending order [10] [11] ¦ 02 May 2003 Rex Swain, Independent Consultant, www.rexswain.com [12] ¦ 06 May 2003 Improved peeking at fns and vars [13] ¦ 27 Jul 2003 Correct •SI/•IDLOC alignment [14] ¦ 25 Sep 2004 Use font settings in APLW.INI [UCMDSREX] [15] ¦ 26 Mar 2005 Evlevel-neutral [16] ¦ 02 Jun 2010 Use UcmdIni and UcmdFont subroutines [17] [18] (’•NC 'b')ûL8 ¦ dummy left arg means callback [19] [20] fô•ENLIST f ¦ arg might be numeric in development mode [21] [22] max256 ¦ max width of FFA display [23] [24] fDEB f [25] :if (1f)î'1234567890' [26] ((fî',#')/f)' ' [27] (1 1ð•VI f)L9 [28] pô•FI f ¦ also for caption [29] x'•FREAD ',p ¦ how to get package [30] :else [31] c•NC f ¦ •NC does not fail on invalid names [32] (4îc)ûL9 ¦ 4=invalid [33] (1†ûc)ûL9 ¦ too many/few names [34] s•SI[;1] ¦ first column of SI [35] s(~sî'õ•><')/s ¦ ditch •SI levels that don't have matching •IDLOC columns [36] usâ']' ¦ how much UCMD crap is there [37] uu*uóûs ¦ or 1 if no ] (non-UCMD) [38] :if uò(ý1†,•IDLOC f)â1 [39] ñOUT 'Shadowed: ',f [40] 0 [41] :end [42] :if c†2 [43] ñOUT 'Not a variable: ',f [44] 0 [45] :end [46] xf ¦ how to get package [47] pf ¦ caption [48] ((p='‘')/p)'+' [49] ((p='ñ')/p)•AV[249+•IO] ¦ for a Form caption, that yields the plus-or-minus symbol [50] [51] :end [52] [53] Kõx [54] [55] :if 1†ûûK [56] :orif 5>ûK [57] :orif ~'PACKAGE'ð1K [58] ñOUT 'Not a package: ',f [59] 0 [60] :end [61] [62] w•FI UcmdIni 'PkgDoc-Place' '2 5 20 70' [63] v•FI UcmdIni 'PkgDoc-Visible' '1' [64] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [65] [66] •wself'fmPkgdoc' •wi 'Create' 'Form' [67] •wi 'caption' ('PkgDoc ',p) [68] •wi 'place' w [69] •wi 'visible' v [70] •wi 'onClose' ' CMDPKGDOC •wevent' [71] •wi '‘x' x [72] [73] •wself':mFile' •wi 'New' 'Menu' [74] •wi 'caption' '&File' [75] [76] •wself'.mExit' •wi 'New' 'Menu' [77] •wi 'caption' 'E&xit' [78] •wi 'shortcut' 'X' 2 [79] •wi 'onClick' "0 0û':' •wi 'Close'" [80] [81] •wself':bn' •wi 'New' 'Button' [82] •wi 'size' 1.25 8 [83] •wi 'style' 2 ¦ 2=cancel [84] •wi 'caption' 'E&xit' [85] [86] (M C P)K[3 4 5] ¦ object names, classes, pointers [87] nûûM [88] [89] cwûôn ¦ component number display width [90] uwý1ûM [91] [92] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [93] c0 3û0 [94] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [95] ccž'#' 5 'right' ¦ 2 [96] ccž'Name' (1.5+uw) 'left' ¦ 3 [97] ccž'C' 2.5 'center' ¦ 4 [98] ccž'Bytes' 8 'right' ¦ 5 [99] ccž'ð' 2.5 'right' ¦ 6 [100] ccž'Shape' 8 'right' ¦ 7 [101] ccž'Value' 80 'left' ¦ 8 [102] [103] •wself':lv' •wi 'New' 'Listview' [104] •wi 'where' 0.5 1 [105] •wi 'style' 1024 4096 ¦ 1024=reorder cols 4096=gridlines [106] •wi 'columndisplay' c [107] •wi 'scale' 3 ¦ font size will be specified in points [108] •wi 'font' (UcmdFont '') [109] [110] •wi 'onColClick' ' CMDPKGDOC •wevent' [111] •wi 'onDblClick' ' CMDPKGDOC •wevent' [112] [113] •wself':' [114] •wi 'onResize' ' CMDPKGDOC •wevent' [115] •wi 'Event' ' CMDPKGDOC •wevent' 'Resize' [116] [117] •wself':lv' [118] •wi 'Focus' [119] [120] :for i :in ân [121] [122] ¦ (M C P)K[3 4 5] ¦ object names, classes, pointers [123] ¦ # [124] côi [125] ¦ Name [126] uM[i;] [127] ¦ Class [128] tiC [129] t'?ì?'[14t] [130] ¦ Value [131] v(iP)K [132] ¦ Bytes [133] bDLB,'CI15' •FMT •SIZE 'v' ¦õ v [134] ¦ Depth [135] dôðv [136] ¦ Shape [137] pûv ¦ shape [138] kûp ¦ rank [139] p(ôp),(k=0)/'' ¦ format shape [140] ¦ Value [141] fmax FFAW v [142] f(maxûf)ûf [143] qfâ'û' [144] :if qóûf [145] :andif q<')/s ¦ ditch •SI levels that don't have matching •IDLOC columns [57] isâ']' ¦ how much UCMD crap is there [58] ii*ióûs ¦ or 1 if no ] (non-UCMD) [59] d•IDLOC J ¦ what are objects [60] bd[;âi]ú.†ý1 ¦ shadowed? [61] :if 1îb [62] •'Shadowed: ',ñDEB ,' ',bëJ [63] 0 [64] :end [65] D(,<\d†ý1)/,d ¦ current definition [66] :if 0îD [67] •'Undefined: ',ñDEB ,' ',(D=0)ëJ [68] 0 [69] :end [70] :if ~^/Dî1 2 [71] •'Not a function or variable: ',ñDEB ,' ',(~Dî1 2)ëJ ¦ label, I guess? [72] 0 [73] :end [74] [75] J(•SPLIT J)~' ' [76] [77] :for j :in (D=1)/J [78] :if 0=û•VR j [79] •'Cannot do locked function: ',j [80] 0 [81] :end [82] :end [83] [84] ¦ ----- Check wss ----- [85] [86] W0û '' ¦ parsed wss [87] :while Sú.†' ' [88] SDLB S [89] :if '"'=1S [90] S1S [91] iSâ'"' [92] w(i-1)ûS [93] :else [94] iSâ' ' [95] w(i-1)ûS [96] :if •VI w ¦ a library number? [97] SDLB iS [98] iSâ' ' [99] ww,' ',(i-1)ûS [100] :end [101] :end [102] SiS [103] WW, w [104] :end [105] [106] j(-1=ûJ)'Saving ',(ôûJ),' objects' [107] w(-1=ûW)'into ',(ôûW),' workspaces' [108] s'ì'[D] [109] xôj (s,[2]J) w ([2]W) [110] x(ý21,ûx)ûx ¦ might be a vector if 1 obj and 1 ws [111] •0 1x [112] —'OK? ' [113] (ú/'Yy'î—)0 [114] [115] ¦ ----- Fire up server ----- [116] [117] s'wseSave' ¦ server name [118] [119] :if ''ðs •wi 'self' [120] •wselfs •wi 'New' 'APLW.WSEngine' ('xVisible' 0) [121] :else [122] •wselfs [123] :end [124] [125] k'XExec' CMDSAVE "••CHDIR '",(•CHDIR ''),"'" ¦ make sure we are all on the same page [126] [127] ¦ ----- Loop through wss ----- [128] [129] :for w :in W [130] [131] •'Starting ws ',w [132] [133] k'XExec' CMDSAVE ')CLEAR' [134] d'XExec' CMDSAVE '••WSID' [135] [136] :if ~dð'' ¦ in a clear ws, •WSIDð'' [137] 'Error' CMDSAVE '*** )CLEAR failed!' [138] :end [139] [140] k'XExec' CMDSAVE ')XLOAD ',w [141] d'XExec' CMDSAVE '••WSID' [142] [143] :if dð'' [144] 'Error' CMDSAVE '*** )XLOAD failed!' [145] :end [146] [147] :for j :in J [148] [149] k'XExec' CMDSAVE "•ERASE '",j,"'" ¦ in case object is currently other type [150] [151] k•wi 'XExec' "•' •HT...'" [152] [153] :if 3=•NC j ¦ 3=fn [154] [155] ¦ We need to pass the function definition, but we don't want to [156] ¦ disturb any existing variables. So we use •HT as a temp var! [157] •wi 'xSysVariable' 'HT' ('wrapl' •DR •VR j) [158] x'XExec' CMDSAVE "•(",(ô2 •AT j),") •DEF 'unwrapl' •DR •HT" [159] :if ~xðj [160] 'Error' CMDSAVE '*** •DEF failed!' [161] :end [162] [163] :else ¦ 2=var [164] [165] ¦ Use wrapl here because of simple character matrix issue [166] võj [167] •wi 'xSysVariable' 'HT' ('wrapl' •DR v) [168] k'XExec' CMDSAVE j,"'unwrapl' •DR •HT" [169] x•wi 'XExec' ("'wrapl' •DR ",j) [170] :if ~vð'unwrapl' •DR x [171] 'Error' CMDSAVE '*** Assignment failed!' [172] :end [173] [174] :end [175] [176] :end ¦ next object [177] [178] k'XExec' CMDSAVE ')SAVE' [179] [180] :end ¦ next ws [181] [182] •wi 'Delete' [183] [184] •'Done' [185] [186] 0 [187] [188] L9: ¦ ========== Callbacks ========== [189] [190] :SELECT X [191] [192] :CASE 'XExec' [193] [194] k•wi 'XExec' ('•" ',A,'"') ¦ so we can see in server's session [195] R•wi 'XExec' A [196] [197] :CASE 'Error' [198] [199] •A [200] •" '",•wself,"' •wi 'xVisible' 1 ¦ to see why" [201] •" '",•wself,"' •wi 'xVisible' 0  '",•wself,"' •wi 'Delete' ¦ to delete server" [202] R0 [203] [204] :ELSE [205] [206] ö0 [207] [208] :END ì ]f€US<  ; ; ì XCMDSCAN A;B;C;D;E;F;FILT;G;H;I;J;K;L;M;N;P;Q;QC;R;S;T;U;UP;V;W;Y;Z;g;t [1] ¦ Find strings in functions, non-syntactic and case-insensitive [2] [3] ¦ Syntax: [4] ¦ ]scan target ¦ Search (if target begins with a letter) [5] ¦ ]scan target/options ¦ Ditto, with options [6] ¦ Any non-alpha delimiter character may be used in place of the slashes shown below [7] ¦ ]scan /target ¦ Search (exactly 1 delimiter) [8] ¦ ]scan /target/ ¦ Search (exactly 2 delimiters) [9] ¦ ]scan /target/options ¦ Ditto, with options [10] ¦ Multiple targets: [11] ¦ ]scan /t1/^/t2/options ¦ Find only lines with both matches [12] ¦ ]scan /t1/ú\t2\ ¦ Find lines with either match; delimiters may be different [13] ¦ ]scan /t1/&~/t2/ ¦ Logical not; & and þ are also permitted [14] ¦ ]scan /t1/>/t2/ ¦ Can use any of <ó=ò>†ú^åê&þ and ~ [15] ¦ ]scan /t1/^~/t2/ú/t3/ ¦ Evaluated as APL would ("right to left") [16] [17] ¦ Searches are case-insensitive and non-syntactic [18] ¦ Default is to search all global functions [19] [20] ¦ Options: [21] ¦ To limit functions searched: [22] ¦ /f1 f2 ¦ Only look in named functions [23] ¦ /f* ¦ Fn names with wildcards (foo* *old fm*def etc.) [24] ¦ /.grp ¦ Fn names contained in variable grp [25] ¦ /~f1 f2 ¦ Look in all but named functions [26] ¦ To limit search scope (using all three is equivalent to using none): [27] ¦ /¦ ¦ Find only in comments [28] ¦ /' ¦ Find only in character constants (or /") [29] ¦ /à ¦ Find only in APL (not comments/quotes) [30] ¦ To expand search scope: [31] ¦ /ì ¦ Find strings anywhere in a function -- not necessarily on the same line. [32] ¦ Only useful with multiple targets. Doesn't change behavior of /t1/ú/t2/. [33] ¦ Display from /t1/^/t2/ì is similar to /t1/ú/t2/ but only shows functions [34] ¦ that contain at least one hit on both strings. [35] ¦ Other: [36] ¦ / ¦ Suppress display; return fn names [37] [38] ¦ 21 Jul 2005 Created ìCMDSCAN from ìCMDFNREPL [39] ¦ 07 Oct 2005 Fixed FILT bug -- H>QC sb H^QC ! [40] ¦ 06 Feb 2006 Added multiple target feature [41] ¦ 04 Mar 2006 Added ì option [42] ¦ 08 Jul 2007 Updated ìQC [43] ¦ 19 Apr 2009 Use •VGET and 0 •VR and etc. to avoid shadowing (req APL ver 7.2) [44] ¦ 13 Oct 2010 Added .grp feature [45] [46] Aô•ENLIST A ¦ arg might be numeric in development mode [47] [48] ADLTB A ¦ user command may pass in leading/trailing blanks [49] [50] :if Að'' [51] •'For help, see' [52] •' ]scan ?' [53] 0 [54] :end [55] [56] ¦ Allow simple word search without delimiters [57] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [58] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [59] A'/',A [60] :end [61] [62] ¦ Parse targets and functions [63] [64] G0û '' ¦ targets [65] S0û '' ¦ functions [66] [67] :repeat [68] D1A ¦ delimiter [69] A1A [70] IAâD ¦ find second delimiter (might not be one) [71] :if I=1 [72] •'Empty target string is not a good idea' [73] 0 [74] :end [75] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [76] ADLB IA [77] P1A ¦ function or option [78] :if ~Pî'<ó=ò>†ú^åê&þ' [79] :leave [80] :end [81] P('^ú',P)['&þ'âP] [82] ADLB 1A [83] :if '~'=1A [84] PP,'~' [85] ADLB 1A [86] :end [87] S( P),S ¦ function [88] :if Að'' [89] •'Multiple target syntax error' [90] 0 [91] :end [92] :end [93] [94] FA ¦ options (old left argument) [95] [96] D•FIRST ûG ¦ number of targets [97] [98] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [99] [100] ¦ Define ìFILT for APL/quoted strings/comments: [101] [102] Z'à''¦'îF [103] Z[2]Z[2]ú'"'îF [104] Z2æZ [105] E~Zî0 8 ¦ not all or none: we need to filter [106] [107] :if E ¦ unless all or none [108] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [109] LL, "¦ Quotes and Comments" [110] LL, "¦ Right arg is a •VR" [111] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [112] LL, "¦ Extracted from Zark's ìParseVR" [113] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [114] LL, "¦ 26 Oct 2004 Include ¦õ" [115] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [116] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [117] LL, "•IO0 ¦ origin 0 is convenient" [118] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [119] LL, "xcx\n" [160] LL, "¦ Flag newline after each comment; then convert pairs to maps" [161] LL, "tnúc" [162] LL, "ut/c" [163] LL, "c†\x\t\uúý10,u" [164] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [165] ¦ 0=None and 7=All cases are excluded before we get here [166] P 'rc' ¦ 1 = ¦ [167] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [168] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [169] PP, 'rqåc' ¦ 4 = à = 'å¦ [170] PP, 'r~q' ¦ 5 = ঠ= ~' [171] PP, 'r~c' ¦ 6 = à' = ~¦ [172] LL,P[Z] [173] K•FX[2]L ¦õ QC [174] :end [175] [176] L 'RFILT' [177] LL, '¦ Raw hit filter' [178] LL, '¦ V=•VR, P=partition flags' [179] LL, 'R~P ANDSCAN Vî''[1234567890]''' ¦ not line numbers [180] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [181] [182] K•FX[2]L ¦õ FILT ANDSCAN QC [183] [184] ¦ Define ìUP for case-insensitive filter (this is faster than ñUCASE!) [185] [186] Q'ñabcdefghijklmnopqrstuvwxyz' [187] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [188] Y•AV [189] Y[YâQ]L [190] K•FX[2]'VUP V' 'VY[•AVâV]' ¦õ UP Y [191] [192] GUPG ¦ targets to uppercase [193] A1G ¦ last target string [194] [195] ¦ Options setup [196] [197] R''îF ¦ suppress display, just return result? [198] X0û '' ¦ initialize result [199] [200] T'~'îF ¦ all but named fns? [201] [202] g'ì'îF ¦ global fn matching? [203] :if g^D=1 [204] •'FYI, the ì option has no effect with just one target string' [205] g0 [206] :end [207] [208] ¦ Strip flags from function list [209] [210] Eú/'*.'îF ¦ any function name wildcards or groups? [211] F(~Fî'à''¦ï~?ú^ì')/F ¦ note we do not remove asterisk and period [212] FWords F [213] [214] ¦ Default to all fns [215] [216] :if T^0=ûF [217] •'Tilde with no names means "not all functions"' [218] 0 [219] :end [220] [221] :if EúTú0=ûF [222] [223] M0 •IDLIST 1 ¦ all global fns [224] MWords M [225] [226] ¦ Since this is a user command function, it won't be defined globally, [227] ¦ so we don't have to remove it from the list [228] [229] :if 0=ûF [230] FM [231] :elseif E ¦ which implies 0†ûF [232] :while '*'î•ENLIST F [233] P('*'îF)â1 [234] UPF [235] [236] VâûM ¦ indices of matches [237] C' ',M,' ' ¦ candidates [238] U('*'=1U)' ',U,('*'=ý1U)' ' [239] :for L :in '*' Words U [240] BC •SS L [241] Hú/B [242] C((H/B)â1)H/C [243] VH/V [244] :if Vð  :leave  :end [245] :end [246] CM[V] [247] [248] F((P-1)ûF),C,PF [249] :end [250] :while '.'î•ENLIST F ¦ group? [251] P('.'îF)â1 [252] UPF [253] [254] H(U='.')/âûU [255] :if Hð,1 ¦ one leading period [256] :andif 2=0 •NC 1U [257] Cõ1U [258] :if (ðC)ó1 ¦ simple vector or matrix [259] CWords C [260] :end [261] CC[•AV[2]C] ¦ is this a good idea? [262] :else [263] U[H] '(period)' [264] C •ENLIST U ¦ this will fail valid name test [265] :end [266] [267] F((P-1)ûF),C,PF [268] :end [269] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [270] :end [271] :if T [272] FM~F [273] :end [274] :end [275] [276] ¦ Discard invalid names [277] ¦ (This could still happen, if names are supplied in option list) [278] [279] C0 •NC [2]F [280] :if 4îC [281] N(C=4)/F [282] •'*** Not searched, invalid name',(1=ûN)'s:',ôN [283] F(C†4)/F [284] :end [285] [286] ¦ Discard non-functions [287] ¦ (This could still happen, if names are supplied in option list) [288] [289] C3=0 •NC [2]F [290] :if 0îC [291] N(~C)/F [292] •'*** Not function',(1=ûN)'s:',ôN [293] FC/F [294] :end [295] [296] ¦ Discard locked functions [297] [298] K•EX 'L' [299] K•FX [2] 'RL F' "R0†•FIRST û0 •CRL F,'[0]'" ¦õ L [300] CLF ¦ yuck, but I wanted to get this check out of the function loop [301] K•EX 'L' [302] :if 0îC [303] N(~C)/F [304] •'*** Locked function',(1=ûN)'s:',ôN [305] FC/F [306] :end [307] [308] NûF ¦ how many fns [309] :if N=0 [310] •'No functions to search!' [311] 0 [312] :end [313] [314] VDLTB •WSID [315] :if Vð'' [316] V'CLEAR WS' [317] :end [318] [319] •'Searching ',(ôN),' function',(N=1)'s in ',V,' ...' [320] [321] •WGIVE 0 ¦ let that message display [322] [323] E0 ¦ accumulate lines [324] U0 ¦ accumulate functions [325] [326] :for N :in F ¦ inspect next function [327] [328] V0 •VR N [329] LUP V [330] [331] ¦ Search •VR [332] [333] HL •SS A ¦ the heart of the matter [334] [335] :if D=1 ¦ single target? [336] :andif ~1îH ¦ no raw hits? [337] :continue ¦ next function [338] :end [339] [340] ¦ Filter for APL / quoted strings / comments [341] [342] P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [343] P[ý5+ûV]1 ¦ force end of last line [344] [345] IFILT ¦õ P V ANDSCAN [346] HH^I [347] [348] :if D=1 ¦ single target? [349] :andif ~1îH ¦ no more hits? [350] :continue ¦ next function [351] :end [352] [353] HP ORRED H ¦ shift hits to leading "[" [354] [355] :if D>1 ¦ multiple targets [356] ¦ We have already done the last target; now step through the others [357] ¦ Note that they are in reverse order so functions work like APL [358] :if g ¦ "ì" global option? [359] tú/H [360] :for J :in 1âD [361] WL •SS JG ¦ raw search [362] WW^I ¦ FILT [363] WP ORRED W ¦ shift hits to leading "[" [364] HWúH ¦ lines to show [365] tõ'(ú/W)',(JS),'t' ¦ apply function [366] :end [367] :if ~t ¦ no hits? [368] :continue ¦ next function [369] :end [370] :else [371] :for J :in 1âD [372] WL •SS JG ¦ raw search [373] WW^I ¦ FILT [374] WP ORRED W ¦ shift hits to leading "[" [375] Hõ'W',(JS),'H' ¦ apply function [376] :end [377] :if ~1îH ¦ no more hits? [378] :continue ¦ next function [379] :end [380] :end [381] ¦ Note that when D>1, H flags lines not hits [382] :end [383] [384] ¦ Got some hits [385] [386] EE++/H ¦ accumulate lines with hits [387] UU+1 ¦ accumulate functions with hits [388] XX, N ¦ add function name to result [389] [390] :if R ¦ if result-only mode [391] :continue ¦ next function [392] :end [393] [394] ¦ Display hits [395] [396] HH/âûH ¦ line numbers to display (origin 1) [397] PP/âûP ¦ partition starts [398] L(1P,1+ûV)-P ¦ partition lengths [399] PP[H]-1 ¦ compensate for +â with •IO1 [400] LL[H]-1 ¦ not incl trailing CR [401] WûH ¦ number of lines with hits [402] •'==> ',N,' (',(ôW),')' [403] :for B :in âW [404] ¦ APL+Win: Show fn name too so can double-click to edit at that line [405] •N,V[P[B]+âL[B]] ¦ faster than take/drop approach [406] :end [407] •WGIVE 0 ¦ allow display [408] [409] :end ¦ next function [410] [411] •'==> Total: ',(ôE),' line',(E=1)'s in ',(ôU),(-U=1)' functions' [412] [413] Rû0 ¦ quit if result-only mode [414] [415] K•EX 'X' [416] ì €US/t2/ ¦ Can use any of <ó=ò>†ú^åê&þ and ~ [17] ¦ ]seek /t1/^~/t2/ú/t3/ ¦ Evaluated as APL would ("right to left") [18] [19] ¦ Default is to perform case-sensitive, syntactic (name) search [20] ¦ Default is to search all global functions and simple character variables with rankó2 [21] [22] ¦ Options: [23] ¦ To loosen match criteria: [24] ¦ ¦ Non-syntactic search (ANY occurrence) (Alt+S for non-Syntactic) [25] ¦ ï ¦ Ignore case (upper/lower/underscore) (Alt+C for Case) [26] ¦ To limit classes searched: [27] ¦ ì ¦ Find only in functions [28] ¦  ¦ Find only in variables [29] ¦ To limit fns/vars searched: [30] ¦ f1 f2 ¦ Only look in named fns/vars [31] ¦ f* ¦ Names with wildcards (foo* *old fm*def etc.) [32] ¦ /.grp ¦ Fn names contained in variable grp [33] ¦ ~f1 f2 ¦ Look in all but named fns/vars [34] ¦ To limit search scope (using all three is equivalent to using none): [35] ¦ ¦ ¦ Find only in comments [36] ¦ ' ¦ Find only in character constants (or /") [37] ¦ à ¦ Find only in APL (not comments/quotes) [38] ¦ If you use these options, variables are not searched ??? FIXME [39] ¦ To expand search scope: [40] ¦ @ ¦ Find strings anywhere in a fn/var -- not necessarily on the same line. [41] ¦ Only useful with multiple targets. Doesn't change behavior of /t1/ú/t2/. [42] ¦ Display from /t1/^/t2/@ is similar to /t1/ú/t2/ but only shows fns/vars [43] ¦ that contain at least one hit on both strings. [44] ¦ To expand display: [45] ¦ + ¦ Show lines immediately before and after hits, for better context [46] [47] ¦ To do: [48] ¦ Add an input edit box to show (and revise?) target [49] ¦ /t1/ú/t2/ Use a different color for each term? What if they overlap? [50] ¦ Resize of Form could cause Listview vertical scrollbar to come and go [51] ¦ Right-click on RichEdit to Copy text to clipboard? [52] ¦ Make default be shallow variable search like ]WSLOC ; use  option for deep search? [53] ¦ Double-click in RichEdit is not reliable [54] ¦ Search a •NA function as if it were a variable? [55] [56] ¦ 15 Dec 1987 Rex Swain, Independent Consultant, www.rexswain.com [57] ¦ 19 May 1988 Detect and display changed function names [58] ¦ 16 May 1991 Erase old version when fn name changed [59] ¦ 27 Aug 1993 Added ï (ignore case) option [60] ¦ 26 Nov 1994 Adapted for Dyalog APL/W, added # and ## and  options [61] ¦ 29 Dec 1998 Adapted for APL+Win 3.0, removed # and ## and  options [62] ¦ 10 Nov 1999 Added colon as leading identifier char for APL+Win [63] ¦ 18 Nov 1999 Added case-insensitive treatment for APL+Win key names [64] ¦ 03 Dec 2001 Removed colon -- it can OPTIONALLY begin an identifier [65] ¦ 04 Apr 2003 Report total number of hits [66] ¦ 18 May 2003 Added ~ feature [67] ¦ 14 May 2004 Added ? feature [68] ¦ 29 Aug 2004 Added * feature [69] ¦ 26 Mar 2005 Evlevel-neutral (sigh) [70] ¦ 11 Jul 2005 Use QC (derived from Zark's ParseVR) to handle ' and " quotes [71] ¦ 21 Jul 2005 Created ìCMDFNREPL from ìfnrepl [72] ¦ 07 Oct 2005 Fixed FILT bug -- H>QC should be H^QC ! [73] ¦ 06 Feb 2006 Added multiple target feature [74] ¦ 04 Mar 2006 Added @ option [75] ¦ 15 Feb 2007 GUI version, based on ]FNREPL but without replace feature [76] ¦ 16 Feb 2007 Include simple character arrays in search, like ]WSLOC does [77] ¦ 17 Feb 2007 Added + feature [78] ¦ 18 Feb 2007 Deep search on all variables [79] ¦ 19 Feb 2007 Added ì and  features [80] ¦ 12 May 2007 Added Ctrl+C from RichEdit [81] ¦ 29 May 2007 Fixed bug which caused hits in function header lines to not match [82] ¦ 08 Jul 2007 Updated ìQC [83] ¦ 26 Nov 2007 Distinguish between locked and •NA functions [84] ¦ 30 Nov 2007 Use •VGET and 0 •VR and etc. to avoid shadowing (req APL ver 7.2) [85] ¦ 21 Apr 2010 Fixed bug (again!) which skipped hits in function header lines [86] ¦ 02 Jun 2010 Use UcmdIni and UcmdFont subroutines [87] ¦ 13 Oct 2010 Added /.grp feature [88] [89] (Aðý1)ûL9 ¦ callbacks [90] [91] v•AI[2] ¦ elapsed time [92] [93] Aô•ENLIST A ¦ arg might be numeric in development mode [94] [95] ADLTB A ¦ user command may pass in leading/trailing blanks [96] [97] :if Að'' [98] •'For help, see' [99] •' ]seek ?' [100] 0 [101] :end [102] [103] XA ¦ save original arg [104] [105] ¦ Allow simple word search without delimiters [106] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [107] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [108] ¦ If the argument is 'foo /xx' then the blank should not be significant since [109] ¦ there was no leading delimiter. Is this a good idea? Technically the [110] ¦ blank should be significant. But this way is user-friendly. [111] :if 1=+/A='/' [112] Iý1+Aâ'/' [113] A(DTB IA),IA [114] :end [115] A'/',A [116] :end [117] [118] ¦ Parse targets and functions [119] [120] G0û '' ¦ targets [121] S0û '' ¦ functions [122] [123] :repeat [124] D1A ¦ delimiter [125] A1A [126] IAâD ¦ find second delimiter (might not be one) [127] :if I=1 [128] •'Empty target string is not a good idea' [129] 0 [130] :end [131] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [132] ADLB IA [133] P1A ¦ function or option [134] :if ~Pî'<ó=ò>†ú^åê&þ' [135] :leave [136] :end [137] P('^ú',P)['&þ'âP] [138] ADLB 1A [139] :if '~'=1A [140] PP,'~' [141] ADLB 1A [142] :end [143] S( P),S ¦ function [144] :if Að'' [145] •'Multiple target syntax error' [146] 0 [147] :end [148] :end [149] [150] FA ¦ options (old left argument) [151] [152] D•FIRST ûG ¦ number of targets [153] [154] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [155] [156] ¦ Define ìFILT for APL/quoted strings/comments: [157] [158] Z'à''¦'îF [159] Z[2]Z[2]ú'"'îF [160] Z2æZ [161] E~Zî0 8 ¦ not all or none: we need to filter [162] [163] :if E ¦ unless all or none [164] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [165] LL, "¦ Quotes and Comments" [166] LL, "¦ Right arg is a •VR" [167] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [168] LL, "¦ Extracted from Zark's ìParseVR" [169] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [170] LL, "¦ 26 Oct 2004 Include ¦õ" [171] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [172] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [173] LL, "•IO0 ¦ origin 0 is convenient" [174] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [175] LL, "xcx\n" [216] LL, "¦ Flag newline after each comment; then convert pairs to maps" [217] LL, "tnúc" [218] LL, "ut/c" [219] LL, "c†\x\t\uúý10,u" [220] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [221] ¦ 0=None and 7=All cases are excluded before we get here [222] P 'rc' ¦ 1 = ¦ [223] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [224] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [225] PP, 'rqåc' ¦ 4 = à = 'å¦ [226] PP, 'r~q' ¦ 5 = ঠ= ~' [227] PP, 'r~c' ¦ 6 = à' = ~¦ [228] LL,P[Z] [229] K•FX[2]L ¦õ QC [230] :end [231] [232] L 'RFILT' [233] LL, '¦ Raw hit filter' [234] LL, '¦ V=•VR, P=partition flags' [235] ¦LL, 'R~P ANDSCAN Vî"[1234567890]"' ¦ not line numbers [236] LL, 'RP ANDSCAN V†"]"' ¦ line numbers; allow for (2)[23;] too [237] ¦LL, 'RRåý1è1 0R' ¦ flag the ] too (we assume there is one!) [238] LL, 'RRåR<ý1èR' ¦ < is way faster than  [239] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [240] [241] K•FX[2]L ¦õ FILT ANDSCAN QC [242] [243] ¦ Define ìSYN for syntactic search [244] [245] Z''îF ¦ non-syntactic search? [246] [247] ¦ Token alphabet: chars that can be anywhere in a token [248] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [249] a'_' [250] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [251] aa,'abcdefghijklmnopqrstuvwxyzñ' [252] aa,'0123456789' [253] ¦ Token alphabet, including chars that can only begin a token [254] qa,'•ý' [255] [256] Q 'HA SYN H;B;I' [257] QQ, '¦ Syntactic hit filter' [258] QQ, '¦ Requires: V=•VR, a,q=alphabet' [259] QQ, 'IH/âûH' [260] ¦  Note that if target starts with • then we don't care what's to the [261] ¦ left of it, so ((1A)îa) is correct. [262] QQ, ':if (1A)îa' [263] QQ, ' H[(('' '',V)[I]îq)/I]0' [264] QQ, ':end' [265] QQ, ':if (ý1A)îq' [266] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [267] QQ, ':end' [268] :if Z=1 ¦ Neither? [269] Q1ûQ ¦ noop [270] :end [271] K•FX[2]Q ¦õ SYN a q [272] [273] ¦ Define ìUP for case-insensitive filter [274] [275] Z'ï'îF ¦ ignore case when finding target? [276] [277] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [278] ¦ Noop if no letters in targets [279] K•FX[2]'VUP V' '¦ noop' [280] :elseif Z [281] Q'ñabcdefghijklmnopqrstuvwxyz' [282] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [283] uc•AV [284] uc[ucâQ]L [285] K•FX[2]'VUP V' 'Vuc[•AVâV]' ¦õ UP uc ¦ this is faster than ñUCASE! [286] :else [287] mc'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [288] uc'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [289] Q 'VUP V;B;I;L;S' [290] QQ, '¦ Force APL+Win keyword names to upper case' [291] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [292] QQ, '¦ RHS 11/18/99' [293] QQ, '' [294] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [295] QQ, 'BVî''•'' ¦ find key symbols' [296] QQ, '(1îB)0 ¦ quit if none' [297] QQ, '' [298] QQ, 'LVîmc ¦ flag all letters (any case)' [299] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [300] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [301] QQ, '(1îB)0 ¦ quit if none' [302] QQ, '' [303] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [304] QQ, 'IS/B ¦ flag those which are candidates' [305] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [306] QQ, 'I†\I ¦ name mask' [307] QQ, 'II/âûI ¦ indices' [308] QQ, '' [309] QQ, 'V[I]uc[mcâV[I]] ¦ translate' [310] K•FX[2]Q [311] ¦ RHS 3/19/01 [312] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [313] ¦ when searching for 'fMain'. [314] ¦ List of keywords? No, could have ':end' •wi 'New' ... [315] ¦ I think we need to upper-case just the à part of the •vr [316] ¦ RHS 2/06/06 [317] ¦ I often search for •fappend or •io. [318] ¦ I cannot recall EVER having searched for :repeat. [319] ¦ So let's not worry about control structure keywords. [320] :end [321] [322] GUPG ¦ targets to uppercase [323] A1G ¦ last (and typically only) target string [324] [325] ¦ Options setup [326] [327] T'~'îF ¦ all but named fns? [328] b'+'îF ¦ expanded context? [329] f'ì'îF ¦ just fns/vars? [330] ffúå/f ¦ neither means both [331] [332] g'@'îF ¦ global fn matching? [333] :if g^D=1 [334] •'FYI, the @ option has no effect with just one target string' [335] g0 [336] :end [337] [338] ¦ Strip flags from function list [339] [340] Eú/'*.'îF ¦ any function name wildcards or groups? [341] F(~Fî'à''¦ï~?@+ì')/F ¦ note we do not remove asterisk and period [342] FWords F [343] [344] ¦ Default to all fns [345] [346] :if T^0=ûF [347] •'Tilde with no names means "not all fns/vars"' [348] 0 [349] :end [350] [351] :if EúTú0=ûF [352] [353] M0 •IDLIST +/f/1 2 ¦ all global fns/vars [354] MWords M [355] [356] :if 0=ûF [357] FM [358] :elseif E ¦ which implies 0†ûF [359] :while '*'î•ENLIST F [360] P('*'îF)â1 [361] UPF [362] [363] VâûM ¦ indices of matches [364] C' ',M,' ' ¦ candidates [365] U('*'=1U)' ',U,('*'=ý1U)' ' [366] :for L :in '*' Words U [367] BC •SS L [368] Hú/B [369] C((H/B)â1)H/C [370] VH/V [371] :if Vð  :leave  :end [372] :end [373] CM[V] [374] [375] F((P-1)ûF),C,PF [376] :end [377] :while '.'î•ENLIST F ¦ group? [378] P('.'îF)â1 [379] UPF [380] [381] H(U='.')/âûU [382] :if Hð,1 ¦ one leading period [383] :andif 2=0 •NC 1U [384] Cõ1U [385] :if (ðC)ó1 ¦ simple vector or matrix [386] CWords C [387] :end [388] CC[•AV[2]C] ¦ is this a good idea? [389] :else [390] U[H] '(period)' [391] C •ENLIST U ¦ this will fail valid name test [392] :end [393] [394] F((P-1)ûF),C,PF [395] :end [396] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [397] :end [398] :if T [399] FM~F [400] :end [401] :end [402] [403] ¦ ¦ If we are filtering for APL/quotes/comments, ditch all variables [404] ¦ ¦ FIXME is this a good idea? what if •vr's stored in vars? [405] ¦ [406] ¦ :if 3=0 •NC 'QC' [407] ¦ F(2†0 •NC [2]F)/F [408] ¦ •'ditching vars' [409] ¦ :end [410] [411] E'' ¦ accumulate warning messages [412] [413] ¦ Discard invalid names [414] ¦ *** This could still happen, if names are supplied in option list [415] [416] C0 •NC [2]F ¦ 0=undef 1=label 2=var 3=fn 4=other/invalid [417] ¦ ¦ Aw jeez. •NC says system names are invalid. •IDLOC classifies them correctly, [418] ¦ ¦ but gives DOMAIN ERROR on truly invalid names. Sigh. Kludge ahead... [419] ¦ C[(Fî'•ALX' '•ELX' '•LX')/âûF]2 [420] :if 4îC [421] N(C=4)/F [422] ¦•'*** Not searched, invalid name',(1=ûN)'s:',ôN [423] EE,•TCNL,'Not searched, invalid name',(1=ûN)'s:',ôN [424] F(C†4)/F [425] :end [426] [427] ¦ Discard non-functions [428] ¦ *** This could still happen, if names are supplied in option list [429] [430] C(0 •NC [2]F)î2 3 [431] :if 0îC [432] N(~C)/F [433] EE,•TCNL,'Not functions or variables:',ôN [434] FC/F [435] :end [436] [437] ¦ Discard locked functions [438] [439] K•EX 'L' [440] K•FX [2] 'RL F' ":if 3=0 •NC F  R0†•FIRST û0 •CRL F,'[0]'  :else  R1  :end" ¦õ L [441] CLF ¦ yuck, but I wanted to get this check out of the function loop [442] K•EX 'L' [443] :if 0îC [444] N(~C)/F ¦ apparently locked fns [445] L0=•ENLIST û 0 •NA N ¦ flag really locked functions [446] :if 1îL [447] EE,•TCNL,'Locked function',(1=+/L)'s:',ôL/N [448] :end [449] L~L [450] :if 1îL [451] EE,•TCNL,'•NA function',(1=+/L)'s:',ôL/N [452] :end [453] FC/F [454] :end [455] [456] N•first ûF ¦ how many fns [457] :if N=0 [458] EE,•TCNL,'Nothing to search!' [459] :end [460] [461] VDLTB •WSID [462] :if Vð'' [463] V'CLEAR WS' [464] :end [465] [466] w•FI UcmdIni 'Seek-Place' '2 5 25 75' [467] z•FI UcmdIni 'Seek-Visible' '1' [468] [469] zz-z=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [470] [471] •wself'fmSeek' •wi 'Create' 'Form' 'Hide' [472] •wi 'caption' 'Seek' [473] •wi 'limitwhere' 10 70 [474] •wi 'place' w [475] •wi 'visible' z [476] e'CMDSEEK ý1' [477] •wi 'onClose' e [478] [479] •wself':mFile' •wi 'Create' 'Menu' [480] •wi 'caption' '&File' [481] [482] •wself'.mExit' •wi 'Create' 'Menu' [483] •wi 'caption' 'E&xit' [484] •wi 'shortcut' 'X' 2 [485] •wi 'onClick' "0 0û':' •wi 'Close'" [486] [487] •wself':mEdit' •wi 'Create' 'Menu' [488] •wi 'caption' '&Edit' [489] [490] •wself'.mNext' •wi 'Create' 'Menu' [491] •wi 'caption' 'Find &next hit' [492] •wi 'shortcut' 114 0 ¦ 114=F3 [493] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'redFind' 1" [494] [495] •wself'..mPrev' •wi 'Create' 'Menu' [496] •wi 'caption' 'Find &previous hit' [497] •wi 'shortcut' 114 1 [498] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'redFind' ý1" [499] [500] •wself'..mCopy' •wi 'Create' 'Menu' [501] •wi 'caption' '&Copy' [502] •wi 'shortcut' 'C' 2 [503] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'Copy'" [504] [505] •wself':mView' •wi 'Create' 'Menu' [506] •wi 'caption' '&Sort' [507] [508] •wself'.mClass' •wi 'Create' 'Menu' [509] •wi 'caption' 'Sort list by Clas&s' [510] •wi 'shortcut' 'S' 2 [511] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'Sort' 1" [512] [513] •wself'..mName' •wi 'Create' 'Menu' [514] •wi 'caption' 'Sort list by &Name' [515] •wi 'shortcut' 'N' 2 [516] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'Sort' 2" [517] [518] •wself'..mHits' •wi 'Create' 'Menu' [519] •wi 'caption' 'Sort list by &Hits' [520] •wi 'shortcut' 'H' 2 [521] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'Sort' 3" [522] [523] C0 •NC [2]F [524] [525] •wself':st' •wi 'Create' 'Status' [526] •wi 'status' (1 4û1 '' 0 8) [527] [528] ¦ 4-col matrix [529] ¦ col 1: pane number, negative if an overlay pane [530] ¦ cols 2,3: 1 text show that text [531] ¦ 0 text don't show, but use width of text [532] ¦ text 33 show text; 33 is mimimum width (more if reqd) [533] ¦ text text2 ditto; use width of text2 as minimum [534] ¦ col 4: border: 0=no 1=inset 2=outset 8=expand 16=caps 32=num 64=scr [535] t0 4û [536] ttž 1 1 (' ',V,' ') 1 ¦ wsid [537] ttž 2 1 (' ',(ô+/C=3),' functions, ',(ô+/C=2),' variables ') 1 [538] ttž 3 '' 25 1 [539] ttž 4 '' 25 1 [540] •wi 'status' t [541] [542] z,•wi 'PaneWhere' 3 [543] [544] •wself'.pb' •wi 'Create' 'Progress' ¦ note child of Status [545] •wi 'style' 1 ¦ 1=smooth [546] •wi 'value' 0 (1N) 1 0 ¦ 1 to avoid •WI DOMAIN ERROR when N=0 [547] :if ~ý1îz ¦ RHS 9/08/10 z is 4ûý1 if no room for pane (long wsid) [548] •wi 'where' z [549] :end [550] [551] •wself':bn' •wi 'Create' 'Button' 'Hide' [552] •wi 'style' 2 ¦ 2=cancel [553] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [554] [555] z':' •wi 'size' [556] [557] •wself':lv' •wi 'Create' 'Listview' [558] •wi 'style' 1 2 4 8 128 4096 ¦ 128=no header 4096=grid [559] •wi 'where' (0,0,z[1],200) ¦ wide enough so no horiz scroll bar, else 'size' misleading [560] [561] •wi 'scale' 3 ¦ font size will be specified in points [562] •wi 'font' (UcmdFont '5') [563] •wi 'scale' 1 [564] [565] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [566] ¦ first col must be left justified [567] c0 3û0 [568] ccž'C' 2 'left' [569] ccž'Name' (5/•enlist ûF) 'left' ¦ 5 to avoid •WI DOMAIN ERROR when N=0 [570] ccž'Hits' 5 'right' [571] ccž'Fake' 0 'right' ¦ because of behavior of 'AutoFit' 'header' 'all' [572] [573] •wi 'list' (0,1,100 1û'x') ¦ force vertical scrollbar [574] [575] •wi 'columndisplay' c [576] w+/c[;2] [577] d•wi 'size' [578] d[2]w ¦ + 5 ¦ allow for vert scrollbar [579] •wi 'size' d [580] w4•wi 'where' [581] [582] •wi 'list' (0 3û0 1 '') ¦ remove fake row that forced vertical scrollbar [583] [584] •wself':red' •wi 'Create' 'RichEdit' [585] •wi 'style' 4 16 64 4096 16384 32768 ¦ 4=multi-line 16=V SB 64=H SB 2048=APL 4096=read-only [586] ¦ 16384 else entire text selected when you select the Form [587] ¦ 32768 disable automatic word selection when highlighting with mouse [588] [589] •wi 'where' (0,w,z[1],z[2]-w) [590] [591] HW•wi 'hwnd' [592] [593] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [594] •wi 'selection' 0 ý1 ¦ select all [595] •wi 'scale' 3 ¦ points [596] [597] •wi 'selfont' (UcmdFont 'U') ¦ 'U' for Unicode [598] [599] ¦  Necessary because default is bold (huh?) [600] •wi 'selstyle' (0 0 0 0 0) ¦ bold, italic, underline, strikeout, protected [601] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection [602] [603] A1•AV[•IO+65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 48 49 50 51 52 53 54 55 56 57 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96 123 125 2 16 17 18 20 21 128 129 130 131 132 133 135 136 137 138 139 140 142 144 147 148 150 153 154 155 156 157 160 161 162 163 164 165 168 170 171 172 173 174 175 192 193 194 195 197 198 200 202 203 204 205 206 207 210 211 212 213 216 217 218 219 221 223 225 228 4 5 6 11 14 24 25 26 28 29 124 126 134 145 146 230 231 233 236 238 239 240 242 243 246 248 249 250 252 253 254 3 15 19 22 23 30 31 141 143 149 151 152 158 159 166 167 169 224 226 227 229 232 234 235 237 241 244 245 251 13 ] ¦ removed 0 7 8 9 10 12 27 127 [604] A2 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 48 49 50 51 52 53 54 55 56 57 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96 123 125 8364 229 230 236 249 242 199 252 233 226 228 224 231 234 235 232 239 238 196 201 244 246 251 214 220 162 163 165 225 237 243 250 241 209 191 245 248 253 161 171 187 192 193 194 195 197 198 200 202 203 204 205 206 207 210 211 212 213 216 217 218 219 221 255 223 227 8900 168 8592 8834 8835 8593 8595 8594 8867 8866 166 8764 8800 8710 215 8869 8868 8854 8711 8714 8745 8801 8805 8804 247 8728 9675 8744 8746 175 8739 9079 9055 9067 9068 9077 9035 9042 8968 8970 9109 9054 9017 9066 9064 9053 9024 9015 9082 9075 9060 9073 9021 9074 9023 9033 9049 9045 9038 9076 13 183 [605] ¦ 183=U00B7 : Middle dot, for untranslatable chars [606] [607] ¦ Streamlined version of ìAV2U [608] t 'UAU A;N' [609] tt, 'UA2[A1âA]' [610] tt, ':if 82†•DR A' [611] tt, ' N,0=•TYPE A' [612] tt, ' (N/,U)N/,A' [613] tt, ':end' [614] tt, 'U•FIRST 323 163 82 •DR U' [615] k•fx [2] t ¦õ AU A1 A2 [616] [617] ¦ Streamlined version of ìSetSelTextU [618] k•fx [2] 'ST A;K;U' 'UAU A' "K•wcall 'EM_SetTextEx' HW ('ST_SELECTION' 1200) (U,2û•tcnul)" ¦õ ST AU HW [619] [620] t' ]SEEK ',X [621] [622] ¦ tt,•tcnl,50û9472 ¦ U2500 : Unicode horizontal line [623] ¦ tt,•tcnl,'Test difficult characters:' [624] ¦ tt,•tcnl,'Execute õ' [625] ¦ tt,•tcnl,' Match ð' [626] ¦ tt,•tcnl,' Zilde ' [627] ¦ tt,•tcnl,' Domino ˜' [628] ¦ tt,•tcnl,' Euro ' [629] ¦ tt,•tcnl,50û'C' [630] ¦ tt,•tcnl,50û8364 ¦ 8364 = U20AC = Euro [631] ¦ tt,•tcnl,50û'E' [632] ¦ tt,•tcnl,50û9472 ¦ U2500 : Unicode horizontal line [633] [634] tt,•tcnl [635] ST t [636] [637] •wi 'selection' (0,ý1+ût) ¦ offset, length [638] •wi 'selcolor' (0 196 0) [639] •wi 'selstyle' (1 0 0 0 0) ¦ bold [640] •wi 'selection' ý1 ¦ select none; cursor to end [641] [642] :if ’ûE ¦ any warnings? [643] s1•wi 'selection' [644] ST 1èE [645] •wi 'selection' (s,ý1+ûE) ¦ offset, length [646] •wi 'selcolor' (255 0 0) [647] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [648] •wi 'selection' ý1 ¦ select none; cursor to end [649] :end [650] [651] ¦ Pre-build a CHARFORMAT2 structure that sets background color [652] CF8484 ¦ cbSize [653] CF[8]4 ¦ dwMask CFM_BACKCOLOR [654] CF[65 66 67]255 255 0 ¦ yellow [655] CFAV CF [656] [657] VDLTB •WSID [658] :if Vð'' [659] V'CLEAR WS' [660] :end [661] [662] •wself':' [663] [664] •wi 'Show' [665] e'CMDSEEK ý1' [666] •wi 'onResize' e [667] •wi 'onClose' e [668] [669] ':lv' •wi 'Focus' ¦ necessary to make Esc work during search (why?) [670] [671] X0 ¦ count hits [672] E0 ¦ count lines with hits [673] U0 ¦ count functions with hits [674] p0 5û' ' '' 0 0  ¦ class, name, # hits, pointer to fn in RichEdit, line numbers with hits [675] m0 2û ¦ all hits (start, length) in RichEdit [676] [677] •wself':red' [678] [679] :for N :in F ¦ inspect next function [680] [681] ¦k•dl 0.1 [682] [683] :if ':' •wi '‘stop' [684] s1•wi 'selection' [685] t'Interrupt',•tcnl [686] ST t [687] •wi 'selection' (s,ût) ¦ offset, length [688] •wi 'selcolor' (255 0 0) [689] •wi 'selstyle' (1 0 0 0 0) ¦ bold [690] •wi 'selection' ý1 ¦ select none; cursor to end [691] :leave [692] :end [693] [694] ':st.pb' •wi 'Stepit' [695] [696] ¦•wgive 0 ¦ yikes, this makes it take twice as long! [697] [698] ¦t100’iöN [699] ¦':st' •wi 'SetStatus' ('Searching function ',(ôi),' of ',(ôN),' (',(ôt),'%)','...') [700] ¦':st' •wi 'SetStatus' 3 (' Searching function ',(ôi),'... ') [701] ¦':st' •wi 'SetStatus' 3 (' Searching ',(ô100’iöN),'%... ') [702] [703] ¦  This was nice in the event that a huge variable took forever to search. [704] ¦ But it makes the other status panes shiver [705] ¦':st' •wi 'SetStatus' 4 (' ',N) [706] [707] y3=0 •NC N ¦ is it a function? ¦ note •NC says 4 for •LX, but we ony test 3= [708] :if y [709] V0 •VR N [710] V[1 2]'[]' ¦ kludge for FILT [711] :else [712] V0 •VGET N ¦ was VõN [713] [714] ¦ RHS 3/03/07 Let's try this, for speed [715] :if 82†•DR V [716] :continue [717] :end [718] [719] ¦ :if 82†•DR V [720] ¦ :orif 2<ûûV [721] ¦ :continue [722] ¦ :else [723] ¦ :if 2=ûûV [724] ¦ t1ûV [725] ¦ w4+2ûôt ¦ we want a blank between ']' and data, so FILT will work [726] ¦ V(('P—[—Q—;]—LI',ôw) •FMT ât),V [727] ¦ ¦ Keep trailing blanks, since they are arguably part of the data [728] ¦ V,V,•TCNL [729] ¦ :elseif •TCNLîV [730] ¦ ¦ Don't use ìPartition because we want to keep empty partitions [731] ¦ V1(V=•TCNL) •PENCLOSE V [732] ¦ tûV [733] ¦ w3+3ûôt ¦ we want a blank between ']' and data, so FILT will work [734] ¦ V( [2] ('P—[—Q—]—LI',ôw) •FMT ât),V [735] ¦ V•ENLIST V,•TCNL [736] ¦ :else ¦ simple vector, no CRs [737] ¦ V(6'[]'),V,•TCNL [738] ¦ :end [739] ¦ :end [740] ¦L•ai[2] [741] VSEEKFMT V [742] ¦L•ai[2]-L [743] ¦:if Lò1 [744] ¦ •'FYI, it took ',(ôL),' seconds for ]SEEK to search: ',N [745] ¦ ¦ FIXME so what? erase it? actually time was used formatting it. [746] ¦:end [747] :if 0=ûV [748] :continue [749] :end [750] ¦VV,6û' ' ¦ make it like a •VR; see ý5+ûV kludge below [751] ¦  not necessary now that we match •TCNL rather than •TCNL,'[' [752] :end [753] [754] LUP V [755] [756] ¦ Search •VR [757] [758] HL •SS A ¦ the heart of the matter [759] [760] :if D=1 ¦ single target? [761] :andif ~1îH ¦ no raw hits? [762] :continue ¦ next function [763] :end [764] [765] ¦ Syntactic filter [766] [767] HA SYN H ¦õ V a q [768] [769] :if D=1 ¦ single target? [770] :andif ~1îH ¦ no more hits? [771] :continue ¦ next function [772] :end [773] [774] ¦ Filter for APL / quoted strings / comments [775] [776] ¦P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [777] ¦  This doesn't work with my variable formatting stuff, like '(2)[13;] ...' [778] ¦ And besides, you're not allowed to have CRs embedded in functions any more [779] P1,ý1V •SS •TCNL ¦ partition on "[" (with trailing CRs); force header line [780] ¦ •SS is still faster than plain = ! [781] ¦P[ý5+ûV]1 ¦ force end of last line [782] ¦ The last 7 characters of a •VR are: •TCNL,' ì',•TCNL [783] ¦ P[ý5+ûV]1 above flags ....................  this blank [784] ¦ No, now that's not necessary at all, now that we match •TCNL rather than •TCNL,'[' [785] [786] IFILT ¦õ P V ANDSCAN [787] HH^I [788] [789] :if D=1 ¦ single target? [790] :andif ~1îH ¦ no more hits? [791] :continue ¦ next function [792] :end [793] [794] R(ûV)û0 [795] R[(H/âûH)ø.+ý1+âûA]1 ¦ flag chars to highlight [796] [797] hP ORRED H ¦ shift hits to leading "[" [798] [799] :if D>1 ¦ multiple targets [800] [801] ¦ We have already done the last target; now step through the others [802] ¦ Note that they are in reverse order so functions work like APL [803] [804] ¦ /t1/ú/t2/ don't stop and display after first hit -- we want to show them all [805] ¦ /t1/&~/t2/ it is okay to show "all" hits since we will exclude lines with t2 [806] [807] :if g ¦ "@" global option? [808] tú/h [809] :for J :in 1âD [810] WL •SS JG ¦ raw search [811] W(JG) SYN W ¦ SYN [812] WW^I ¦ FILT [813] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [814] HHúW ¦ all hits [815] WP ORRED W ¦ shift hits to leading "[" [816] hWúh ¦ lines to show [817] tõ'(ú/W)',(JS),'t' ¦ apply function [818] :end [819] :if ~t ¦ no hits? [820] :continue ¦ next function [821] :end [822] :else [823] :for J :in 1âD [824] WL •SS JG ¦ raw search [825] W(JG) SYN W ¦ SYN [826] WW^I ¦ FILT [827] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [828] HHúW ¦ all hits [829] WP ORRED W ¦ shift hits to leading "[" [830] hõ'W',(JS),'h' ¦ apply function [831] :end [832] :if ~1îh ¦ no more hits? [833] :continue ¦ next function [834] :end [835] :end [836] [837] ¦ Only count hits on lines that will be displayed [838] ¦ (When searching for /1/^/2/ don't count 2s on lines without 1) [839] [840] Hh/P PLUSRED H [841] [842] :end [843] [844] ¦ Got some hits [845] [846] x+/H ¦ total hits in this fn [847] t':lv' •wi 'AddRows' 0 1 (,'ì'[1+y]) N (ôx) [848] k':lv' •wi 'EnsureVisible' t [849] [850] XX+x ¦ accumulate total hits [851] Hh ¦ lines with hits [852] EE++/H ¦ accumulate lines with hits [853] UU+1 ¦ accumulate functions with hits [854] [855] ¦ Display hits [856] [857] HH/âûH ¦ line numbers to display (origin 1) [858] WûH ¦ number of lines with hits [859] PP/âûP ¦ partition starts [860] L(1P,1+ûV)-P ¦ partition lengths [861] :if b ¦ expanded context? [862] :if y [863] eâûP ¦ all line numbers (including the trailing ì line) [864] :else [865] eâý1+ûP ¦ all line numbers (the last line of variables is bogus) [866] :end [867] H(eîHø.+ý1 0 1)/e ¦ this takes care of dups and edges [868] IH>1+ý1èH ¦ flag beginnings of groups of lines [869] :else [870] I(ûH)û0 [871] :end [872] PP[H]-1 ¦ compensate for +â with •IO1 [873] LL[H] ¦ lengths, incl trailing CRs [874] [875] ppž ('ì'[1+y]) N x (1•wi 'selection') H [876] [877] e5û9472 ¦ 9472=U2500 : Horizontal line [878] ¦  5 positions the fn name where it is in the header line (of a niladic fn) [879] te,' ',N,' (',(ôx),' hit',(x=1)'s',((x†W)/' on ',(ôW),(-W=1)' lines'),') ' [880] tt,((70-ût)ûe),•tcnl [881] ST t [882] n•first ût ¦ length of line [883] s1•wi 'selection' [884] ss-n ¦ back up to beginning of line [885] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [886] •wi 'selection' s (n-1) ¦ offset, length [887] :if y [888] V[1 2]' ' ¦ undo kludge for FILT [889] •wi 'selcolor' (0 0 255) ¦ blue fns [890] :else [891] •wi 'selcolor' (255 0 255) ¦ purple vars [892] :end [893] •wi 'selection' (6+s) (•first ûN) ¦ just the function name [894] •wi 'selstyle' (1 0 0 0 0) ¦ bold [895] •wi 'selection' ý1 ¦ select none; cursor to end [896] •wi 'Paint' ¦ show bolded fn name while hits display [897] [898] :for B :in âûH [899] :if I[B] [900] ST (3û183),•TCNL ¦ 183=U00B7 : Middle dot [901] :end [902] nL[B] [903] jP[B]+ân ¦ indices of line in •VR [904] ST V[j] [905] s(1•wi 'selection')-n+1 [906] C(R[j]) Partition ân ¦ groups of chars to highlight [907] :for j :in C [908] e(s+1j),ûj ¦ offset, length [909] mmže ¦ all hits [910] •wi 'selection' e ¦ offset, length [911] ¦•wi 'selcolor' (255 0 255) ¦ purple [912] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [913] k•wcall 'EM_SETCHARFORMAT' HW 1 CF ¦ SCF_SELECTION=1 ¦ yellow background [914] :end [915] •wi 'selection' ý1 ¦ select none; cursor to end [916] :end [917] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection ¦ else :red does not scroll down [918] •WGIVE 0 ¦ listview does not display without this [919] ¦k•dl 0.1 [920] [921] :end ¦ next function [922] [923] ':bn' •wi 'onClick' '' ¦ let style 2 take over [924] [925] ¦ •wi 'selection' 0 ý1 ¦ select all [926] ¦ •wcall 'EM_SETPARAFORMAT' HW PARAFORMAT2 [927] ¦ •wi 'selection' ý1 ¦ select none; cursor to end [928] [929] :if U=0 [930] [931] s1•wi 'selection' [932] [933] t'Not found',•tcnl [934] ST t [935] [936] •wi 'selection' (s,ý1+ût) ¦ offset, length [937] •wi 'selcolor' (255 0 0) [938] •wi 'selstyle' (1 0 0 0 0) ¦ bold [939] •wi 'selection' 0 0 ¦ cursor to top [940] [941] L1 [942] [943] :end [944] [945] ppž ' ' '' 0 (1•wi 'selection')  ¦ fake row so we know position of end of text [946] [947] •wi 'selection' 0 0 ¦ cursor to top [948] [949] •wself':lv' [950] [951] •wi 'noredraw' 1 [952] •wi 'AutoFit' 'all' [953] c•wi 'columndisplay' [954] cý1 0c ¦ delete Fake column [955] •wi 'columndisplay' c [956] [957] •wi 'highlightfocus' 1 [958] •wi 'value' 1 [959] k•wi 'EnsureVisible' 1 [960] [961] •wi 'noredraw' 0 [962] [963] d+/c[;2] [964] z•wi 'size' [965] z[2]d [966] •wi 'size' z [967] w•wi 'where' [968] [969] z':' •wi 'size' [970] d':red' •wi 'where' [971] d[2]w[4] [972] d[4]z[2]-w[4] [973] ':red' •wi 'where' d [974] [975] •wi 'Focus' [976] [977] •wi '‘p' p [978] [979] e'CMDSEEK ý1' [980] [981] ¦  Sadly, when you click a different row in the list, both these events fire [982] •wi 'onClick' e [983] •wi 'onSelect' e [984] [985] •wi 'keys' 13 ¦ 13=Enter [986] •wi 'onKeyPress' e [987] •wi 'onDblClick' e [988] [989] •wself':red' [990] [991] •wi '‘m' m [992] [993] •wi 'keys' 13 ¦ 13=Enter [994] •wi 'onKeyPress' e [995] •wi 'onMouseDouble' e ¦ sadly, there is no onDblClick [996] [997] L1: [998] [999] •wself':st' [1000] [1001] '.pb' •wi 'Delete' [1002] [1003] t(2æf)'variables' 'functions' 'fns/vars' [1004] t' ',(ôX),' hits on ',(ôE),' lines in ',(ôU),' ',t,' ' [1005] •wi 'SetStatus' 3 t [1006] [1007] v•ai[2]-v [1008] t(0 1ôv),' seconds elapsed' ¦ note free leading blank [1009] •wi 'SetStatus' 4 t [1010] [1011] •wself':' [1012] [1013] k•wi 'Wait' [1014] [1015] 0 [1016] [1017] ¦ ============================================================================= [1018] [1019] L9: [1020] [1021] :SELECT •wevent [1022] [1023] :CASE 'Resize' [1024] [1025] (1=3•warg)û0 ¦ noop if minimize [1026] [1027] z•wi 'size' [1028] •wself':lv' [1029] w•wi 'where' [1030] w[3]z[1] [1031] •wi 'where' w [1032] •wself':red' [1033] w•wi 'where' [1034] w[3 4]z[1],z[2]-w[2] [1035] •wi 'where' w [1036] [1037] :CASELIST 'Click' 'Select' [1038] [1039] ¦ If you click on a new row, you get Click,Select [1040] ¦ If you click on the same row, you get just Click [1041] ¦ If you use keyboard, you get just Select [1042] [1043] i•first •wi 'value' [1044] (i=0)û0 ¦ click in blank row? [1045] [1046] :if •weventð'Click' [1047] •wi '‘skipnextselect' i [1048] :else [1049] Assert •weventð'Select' [1050] :if i=•wi '‘skipnextselect' [1051] •wi '‘skipnextselect' 0 [1052] 0 [1053] :end [1054] :end [1055] [1056] p•wi '‘p' [1057] (c N k s k)p[i;] ¦ class, name, hits, beginning of line, line numbers [1058] ss+6 ¦ advance past '----- ' [1059] n•first ûN [1060] [1061] •wself':red' [1062] [1063] •wi 'selection' s n [1064] [1065] ¦ Scroll into view on RichEdit control [1066] [1067] e1+•wi 'CharToLine' s ¦ line number of first line [1068] t1+•wi 'CharToLine' (p[i+1;4]-1) ¦ line number of last line [1069] g•wi 'range' [1070] g(g[1]-1)+âg[2] ¦ lines now visible [1071] :if 0î(e,t)îg ¦ if the whole fn is already visible, don't change range [1072] •wi 'range' e [1073] :end [1074] [1075] :CASE 'DblClick' [1076] [1077] i1•warg [1078] (i=0)û0 ¦ click in blank row? [1079] p•wi '‘p' [1080] N2p[i;] ¦ name [1081] [1082] k•WCALL 'W_Edit' N ¦ *** New global access system functions: FIXME [1083] [1084] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1085] [1086] :CASE 'MouseDouble' [1087] [1088] ¦ Second mouseup has not occurred yet, so we have to wait [1089] [1090] ¦ Pass mouse position before Windows does "word" select, which could change selection offset [1091] [1092] •wi 'Defer' 'CMDSEEK ý1' 'KeyPress' (•wi 'selection') [1093] [1094] :CASE 'KeyPress' [1095] [1096] :if 'Listview'ð•wi 'class' [1097] [1098] i•first •wi 'value' [1099] (i=0)û0 ¦ click in blank row? [1100] p•wi '‘p' [1101] N2p[i;] ¦ name [1102] [1103] :else [1104] [1105] Assert 'RichEdit'ð•wi 'class' [1106] [1107] ¦ This could be from Enter key or from MouseDouble [1108] :if •wargð13 [1109] s•first •wi 'selection' [1110] :else [1111] Assert 2=û,•warg [1112] s•first •warg [1113] :end [1114] •wi 'selection' s 0 ¦ cancel word-selection [1115] ¦  Sadly, Windows may have changed the offset to the beginning of a "word" [1116] p':lv' •wi '‘p' ¦ name, hits, beginning of line, line numbers [1117] n1ûp [1118] (s=p[n;4])û0 ¦ beyond end? [1119] i+/sòp[;4] [1120] (c N k g n)p[i;] [1121] e1+•wi 'CharToLine' g ¦ divider line [1122] d1+•wi 'CharToLine' s ¦ clicked line [1123] :if e=d [1124] n0 [1125] :else [1126] id-e [1127] (i>ûn)û0 ¦ on Interrupt message [1128] ný1+n[i] ¦ ý1+ because we recorded line numbers in origin 1 [1129] :end [1130] NN,'[',(ôn),']' [1131] [1132] :end [1133] [1134] k•WCALL 'W_Edit' N [1135] [1136] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1137] [1138] :CASE 'Sort' [1139] [1140] i•warg [1141] •wself':lv' [1142] d•wi 'sortorder' [1143] pý1 0•wi '‘p' [1144] [1145] :if iî1 2 ¦ Class, Name [1146] wd[•AV[2]p[d;i]] ¦ new order [1147] :if dðw ¦ already sorted? [1148] wd[•AV[2]p[d;i]] [1149] :end [1150] :elseif i=3 ¦ Hits [1151] wd[p[d;i]] [1152] :if dðw [1153] wd[p[d;i]] [1154] :end [1155] :else [1156] ö'Tilt' [1157] :end [1158] [1159] •wi 'sortorder' w ¦ this triggers a Select [1160] [1161] i•first •wi 'value' [1162] •wi '‘skipnextselect' i [1163] [1164] :CASE 'Close' [1165] [1166] (•wi 'place') UcmdIni 'Seek-Place' [1167] (•wi 'visible') UcmdIni 'Seek-Visible' [1168] [1169] ¦•wi 'Delete' ¦ requires APL+Win version ò 6.2 [1170] [1171] '#' •wi 'Defer' "'fmSeek' •wi 'Delete'" ¦ works with APL+Win version < 6.2 [1172] [1173] :CASE 'redFind' [1174] [1175] •wself':red' [1176] s•first •wi 'selection' [1177] m•wi '‘m' ¦ offsets, lengths [1178] :if •warg=1 ¦ 1=next ý1=prev [1179] i(m[;1]>s)â1 [1180] :if i>1ûm  i1  :end [1181] :else [1182] iý1+(m[;1]/t2/ ¦ Can use any of <ó=ò>†ú^åê&þ and ~ [18] ¦ ]seek /t1/^~/t2/ú/t3/ ¦ Evaluated as APL would ("right to left") [19] [20] ¦ Default is to perform case-sensitive, syntactic (name) search [21] ¦ Default is to search all global functions and simple character variables with rankó2 [22] [23] ¦ Options: [24] ¦ To loosen match criteria: [25] ¦ ¦ Non-syntactic search (ANY occurrence) (Alt+S for non-Syntactic) [26] ¦ ï ¦ Ignore case (upper/lower/underscore) (Alt+C for Case) [27] ¦ To limit classes searched: [28] ¦ ì ¦ Find only in functions [29] ¦  ¦ Find only in variables [30] ¦ To limit fns/vars searched: [31] ¦ f1 f2 ¦ Only look in named fns/vars [32] ¦ f* ¦ Names with wildcards (foo* *old fm*def etc.) [33] ¦ ~f1 f2 ¦ Look in all but named fns/vars [34] ¦ To limit search scope (using all three is equivalent to using none): [35] ¦ ¦ ¦ Find only in comments [36] ¦ ' ¦ Find only in character constants (or /") [37] ¦ à ¦ Find only in APL (not comments/quotes) [38] ¦ If you use these options, variables are not searched ??? FIXME [39] ¦ To expand search scope: [40] ¦ @ ¦ Find strings anywhere in a fn/var -- not necessarily on the same line. [41] ¦ Only useful with multiple targets. Doesn't change behavior of /t1/ú/t2/. [42] ¦ Display from /t1/^/t2/@ is similar to /t1/ú/t2/ but only shows fns/vars [43] ¦ that contain at least one hit on both strings. [44] ¦ To expand display: [45] ¦ + ¦ Show lines immediately before and after hits, for better context [46] [47] ¦ To do: [48] ¦ Add an input edit box to show (and revise?) target [49] ¦ /t1/ú/t2/ Use a different color for each term? What if they overlap? [50] ¦ Resize of Form could cause Listview vertical scrollbar to come and go [51] ¦ Right-click on RichEdit to Copy text to clipboard? [52] ¦ Make default be shallow variable search like ]WSLOC ; use  option for deep search? [53] ¦ Double-click in RichEdit is not reliable [54] ¦ Search a •NA function as if it were a variable? [55] [56] ¦ 15 Dec 1987 Rex Swain, Independent Consultant, www.rexswain.com [57] ¦ 19 May 1988 Detect and display changed function names [58] ¦ 16 May 1991 Erase old version when fn name changed [59] ¦ 27 Aug 1993 Added ï (ignore case) option [60] ¦ 26 Nov 1994 Adapted for Dyalog APL/W, added # and ## and  options [61] ¦ 29 Dec 1998 Adapted for APL+Win 3.0, removed # and ## and  options [62] ¦ 10 Nov 1999 Added colon as leading identifier char for APL+Win [63] ¦ 18 Nov 1999 Added case-insensitive treatment for APL+Win key names [64] ¦ 03 Dec 2001 Removed colon -- it can OPTIONALLY begin an identifier [65] ¦ 04 Apr 2003 Report total number of hits [66] ¦ 18 May 2003 Added ~ feature [67] ¦ 14 May 2004 Added ? feature [68] ¦ 29 Aug 2004 Added * feature [69] ¦ 26 Mar 2005 Evlevel-neutral (sigh) [70] ¦ 11 Jul 2005 Use QC (derived from Zark's ParseVR) to handle ' and " quotes [71] ¦ 21 Jul 2005 Created ìCMDFNREPL from ìfnrepl [72] ¦ 07 Oct 2005 Fixed FILT bug -- H>QC should be H^QC ! [73] ¦ 06 Feb 2006 Added multiple target feature [74] ¦ 04 Mar 2006 Added @ option [75] ¦ 15 Feb 2007 GUI version, based on ]FNREPL but without replace feature [76] ¦ 16 Feb 2007 Include simple character arrays in search, like ]WSLOC does [77] ¦ 17 Feb 2007 Added + feature [78] ¦ 18 Feb 2007 Deep search on all variables [79] ¦ 19 Feb 2007 Added ì and  features [80] ¦ 12 May 2007 Added Ctrl+C from RichEdit [81] ¦ 29 May 2007 Fixed bug which caused hits in function header lines to not match [82] ¦ 08 Jul 2007 Updated ìQC [83] ¦ 26 Nov 2007 Distinguish between locked and •NA functions [84] [85] (Aðý1)ûL9 ¦ callbacks [86] [87] v•AI[2] ¦ elapsed time [88] [89] Aô•ENLIST A ¦ arg might be numeric in development mode [90] [91] ADLTB A ¦ user command may pass in leading/trailing blanks [92] [93] :if Að'' [94] •'For help, see' [95] •' ]seek ?' [96] 0 [97] :end [98] [99] XA ¦ save original arg [100] [101] ¦ Allow simple word search without delimiters [102] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [103] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [104] ¦ If the argument is 'foo /xx' then the blank should not be significant since [105] ¦ there was no leading delimiter. Is this a good idea? Technically the [106] ¦ blank should be significant. But this way is user-friendly. [107] :if 1=+/A='/' [108] Iý1+Aâ'/' [109] A(DTB IA),IA [110] :end [111] A'/',A [112] :end [113] [114] ¦ Parse targets and functions [115] [116] G0û '' ¦ targets [117] S0û '' ¦ functions [118] [119] :repeat [120] D1A ¦ delimiter [121] A1A [122] IAâD ¦ find second delimiter (might not be one) [123] :if I=1 [124] •'Empty target string is not a good idea' [125] 0 [126] :end [127] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [128] ADLB IA [129] P1A ¦ function or option [130] :if ~Pî'<ó=ò>†ú^åê&þ' [131] :leave [132] :end [133] P('^ú',P)['&þ'âP] [134] ADLB 1A [135] :if '~'=1A [136] PP,'~' [137] ADLB 1A [138] :end [139] S( P),S ¦ function [140] :if Að'' [141] •'Multiple target syntax error' [142] 0 [143] :end [144] :end [145] [146] FA ¦ options (old left argument) [147] [148] D•FIRST ûG ¦ number of targets [149] [150] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [151] [152] ¦ Define ìFILT for APL/quoted strings/comments: [153] [154] Z'à''¦'îF [155] Z[2]Z[2]ú'"'îF [156] Z2æZ [157] E~Zî0 8 ¦ not all or none: we need to filter [158] [159] :if E ¦ unless all or none [160] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [161] LL, "¦ Quotes and Comments" [162] LL, "¦ Right arg is a •VR" [163] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [164] LL, "¦ Extracted from Zark's ìParseVR" [165] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [166] LL, "¦ 26 Oct 2004 Include ¦õ" [167] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [168] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [169] LL, "•IO0 ¦ origin 0 is convenient" [170] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [171] LL, "xcx\n" [212] LL, "¦ Flag newline after each comment; then convert pairs to maps" [213] LL, "tnúc" [214] LL, "ut/c" [215] LL, "c†\x\t\uúý10,u" [216] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [217] ¦ 0=None and 7=All cases are excluded before we get here [218] P 'rc' ¦ 1 = ¦ [219] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [220] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [221] PP, 'rqåc' ¦ 4 = à = 'å¦ [222] PP, 'r~q' ¦ 5 = ঠ= ~' [223] PP, 'r~c' ¦ 6 = à' = ~¦ [224] LL,P[Z] [225] K•FX[2]L ¦õ QC [226] :end [227] [228] L 'RFILT' [229] LL, '¦ Raw hit filter' [230] LL, '¦ V=•VR, P=partition flags' [231] ¦LL, 'R~P ANDSCAN Vî"[1234567890]"' ¦ not line numbers [232] LL, 'RP ANDSCAN V†"]"' ¦ line numbers; allow for (2)[23;] too [233] ¦LL, 'RRåý1è1 0R' ¦ flag the ] too (we assume there is one!) [234] LL, 'RRåR<ý1èR' ¦ < is way faster than  [235] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [236] [237] K•FX[2]L ¦õ FILT ANDSCAN QC [238] [239] ¦ Define ìSYN for syntactic search [240] [241] Z''îF ¦ non-syntactic search? [242] [243] ¦ Token alphabet: chars that can be anywhere in a token [244] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [245] a'_' [246] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [247] aa,'abcdefghijklmnopqrstuvwxyzñ' [248] aa,'0123456789' [249] ¦ Token alphabet, including chars that can only begin a token [250] qa,'•ý' [251] [252] Q 'HA SYN H;B;I' [253] QQ, '¦ Syntactic hit filter' [254] QQ, '¦ Requires: V=•VR, a,q=alphabet' [255] QQ, 'IH/âûH' [256] ¦  Note that if target starts with • then we don't care what's to the [257] ¦ left of it, so ((1A)îa) is correct. [258] QQ, ':if (1A)îa' [259] QQ, ' H[(('' '',V)[I]îq)/I]0' [260] QQ, ':end' [261] QQ, ':if (ý1A)îq' [262] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [263] QQ, ':end' [264] :if Z=1 ¦ Neither? [265] Q1ûQ ¦ noop [266] :end [267] K•FX[2]Q ¦õ SYN a q [268] [269] ¦ Define ìUP for case-insensitive filter [270] [271] Z'ï'îF ¦ ignore case when finding target? [272] [273] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [274] ¦ Noop if no letters in targets [275] K•FX[2]'VUP V' '¦ noop' [276] :elseif Z [277] Q'ñabcdefghijklmnopqrstuvwxyz' [278] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [279] u•AV [280] u[uâQ]L [281] K•FX[2]'VUP V' 'Vu[•AVâV]' ¦õ UP u ¦ this is faster than ñUCASE! [282] :else [283] m'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [284] u'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [285] Q 'VUP V;B;I;L;S' [286] QQ, '¦ Force APL+Win keyword names to upper case' [287] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [288] QQ, '¦ RHS 11/18/99' [289] QQ, '' [290] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [291] QQ, 'BVî''•'' ¦ find key symbols' [292] QQ, '(1îB)0 ¦ quit if none' [293] QQ, '' [294] QQ, 'LVîm ¦ flag all letters (any case)' [295] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [296] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [297] QQ, '(1îB)0 ¦ quit if none' [298] QQ, '' [299] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [300] QQ, 'IS/B ¦ flag those which are candidates' [301] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [302] QQ, 'I†\I ¦ name mask' [303] QQ, 'II/âûI ¦ indices' [304] QQ, '' [305] QQ, 'V[I]u[mâV[I]] ¦ translate' [306] K•FX[2]Q [307] ¦ RHS 3/19/01 [308] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [309] ¦ when searching for 'fMain'. [310] ¦ List of keywords? No, could have ':end' •wi 'New' ... [311] ¦ I think we need to upper-case just the à part of the •vr [312] ¦ RHS 2/06/06 [313] ¦ I often search for •fappend or •io. [314] ¦ I cannot recall EVER having searched for :repeat. [315] ¦ So let's not worry about control structure keywords. [316] :end [317] [318] GUPG ¦ targets to uppercase [319] A1G ¦ last (and typically only) target string [320] [321] ¦ Options setup [322] [323] T'~'îF ¦ all but named fns? [324] b'+'îF ¦ expanded context? [325] f'ì'îF ¦ just fns/vars? [326] ffúå/f ¦ neither means both [327] [328] g'@'îF ¦ global fn matching? [329] :if g^D=1 [330] •'FYI, the @ option has no effect with just one target string' [331] g0 [332] :end [333] [334] ¦ Strip flags from function list [335] [336] E'*'îF ¦ any function name wildcards? [337] F(~Fî'à''¦ï~?@+ì')/F ¦ note we do not remove asterisk [338] FWords F [339] [340] ¦ Default to all fns [341] [342] :if T^0=ûF [343] •'Tilde with no names means "not all fns/vars"' [344] 0 [345] :end [346] [347] :if EúTú0=ûF [348] [349] ¦ ¦ You could have a global function that is localized but undefined [350] ¦ ¦ •IDLIST 1+2+8 will not pick up that name, so... [351] ¦ [352] ¦ N•SINL [353] ¦ N(~N[;1]î'õ•><')ëN ¦ no local names at these levels [354] ¦ N(,ú\N=' ')/,N ¦ discard FOO[3], keep names to the right [355] ¦ NWords N ¦ all localized names [356] ¦ NN~ ,'*' ¦ the asterisk next to suspended fn is not a name [357] ¦ N('•'†•FIRSTN)/N ¦ avoid picking up system vars (ñUCMD2 localizes •PW and •CT) [358] ¦ [359] ¦ M•IDLIST 1+2+8 ¦ all visible names [360] ¦ MWords M [361] ¦ MM,N ¦ add all localized names [362] ¦ ¦MM,'•ALX' '•ELX' '•LX' ¦ ]WSLOC searches these ¦ oh forget it, ]ucmd shadows •ALX and •ELX [363] ¦ M((MâM)=âûM)/M ¦ there might be dups [364] ¦ MM[•AV[2]M] ¦ re-sort [365] ¦ [366] ¦ N,•SI [367] ¦ N(ý1+Nâ'[')ûN ¦ name of self ¦ RHS 8/31/99 [368] ¦ MM~ N ¦ remove self [369] ¦ [370] ¦ P•IDLOC [2]M ¦ what are they [371] ¦ PP[;0æûP] ¦ global definition [372] ¦ M(Pîf/1 2)/M ¦ fns and vars, depending on ì options [373] [374] ¦ *** New global access system functions [375] [376] M0 •IDLIST +/f/1 2 ¦ all global fns/vars [377] MWords M [378] [379] :if 0=ûF [380] FM [381] :elseif E ¦ which implies 0†ûF [382] :while '*'î•ENLIST F [383] P('*'îF)â1 [384] UPF [385] [386] VâûM ¦ indices of matches [387] C' ',M,' ' ¦ candidates [388] U('*'=1U)' ',U,('*'=ý1U)' ' [389] :for L :in '*' Words U [390] BC •SS L [391] Hú/B [392] C((H/B)â1)H/C [393] VH/V [394] :if Vð  :leave  :end [395] :end [396] CM[V] [397] [398] F((P-1)ûF),C,PF [399] :end [400] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [401] :end [402] :if T [403] FM~F [404] :end [405] :end [406] [407] ¦ ¦ If we are filtering for APL/quotes/comments, ditch all variables [408] ¦ ¦ FIXME is this a good idea? what if •vr's stored in vars? [409] ¦ [410] ¦ :if 3=•NC 'QC' [411] ¦ F(2†•NC [2]F)/F [412] ¦ •'ditching vars' [413] ¦ :end [414] [415] E'' ¦ accumulate warning messages [416] [417] ¦ Discard invalid names [418] ¦ *** This could still happen, if names are supplied in option list [419] [420] C0 •NC [2]F ¦ 0=undef 1=label 2=var 3=fn 4=other/invalid [421] ¦ ¦ Aw jeez. •NC says system names are invalid. •IDLOC classifies them correctly, [422] ¦ ¦ but gives DOMAIN ERROR on truly invalid names. Sigh. Kludge ahead... [423] ¦ C[(Fî'•ALX' '•ELX' '•LX')/âûF]2 [424] :if 4îC [425] N(C=4)/F [426] ¦•'*** Not searched, invalid name',(1=ûN)'s:',ôN [427] EE,•TCNL,'Not searched, invalid name',(1=ûN)'s:',ôN [428] F(C†4)/F [429] :end [430] [431] ¦ Discard shadowed names [432] ¦ *** No longer necessary [433] [434] ¦ L•IDLOC [2]F ¦ what are names fn=1 var=2 [435] ¦ L0 ý1L ¦ disregard global level [436] ¦ CL^.=ý1 [437] ¦ :if 0îC [438] ¦ N(~C)/F [439] ¦ ¦•'*** Shadowed:',ôN [440] ¦ EE,•TCNL,'Shadowed:',ôN [441] ¦ FC/F [442] ¦ :end [443] [444] ¦ Discard non-functions [445] ¦ *** This could still happen, if names are supplied in option list [446] [447] ¦C3=•NC [2]F [448] ¦C(•NC [2]F)î2 3 4 ¦ VARS! ¦ 4 allows •LX; we already checked for invalid [449] C(0 •NC [2]F)î2 3 ¦ VARS! [450] :if 0îC [451] N(~C)/F [452] ¦•'*** Not function',(1=ûN)'s:',ôN [453] ¦EE,•TCNL,'Not function',(1=ûN)'s:',ôN [454] EE,•TCNL,'Not functions or variables:',ôN ¦ VARS! [455] FC/F [456] :end [457] [458] ¦ Discard locked functions [459] [460] K•EX 'L' [461] ¦K•FX [2] 'RL F' "R0†•FIRST û•CRL F,'[0]'" ¦õ L [462] K•FX [2] 'RL F' ":if 3=0 •NC F  R0†•FIRST û0 •CRL F,'[0]'  :else  R1  :end" ¦õ L ¦ VARS! [463] CLF ¦ yuck, but I wanted to get this check out of the function loop [464] K•EX 'L' [465] :if 0îC [466] N(~C)/F ¦ apparently locked fns [467] L0=•ENLIST û 0 •NA N ¦ flag really locked functions [468] :if 1îL [469] EE,•TCNL,'Locked function',(1=+/L)'s:',ôL/N [470] :end [471] L~L [472] :if 1îL [473] EE,•TCNL,'•NA function',(1=+/L)'s:',ôL/N [474] :end [475] FC/F [476] :end [477] [478] N•first ûF ¦ how many fns [479] :if N=0 [480] ¦•'No functions to search!' [481] ¦EE,•TCNL,'No functions to search!' [482] EE,•TCNL,'Nothing to search!' ¦ VARS! [483] ¦0 [484] :end [485] [486] VDLTB •WSID [487] :if Vð'' [488] V'CLEAR WS' [489] :end [490] [491] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [492] k•fx [2] 'vk II d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ II [493] [494] w•FI 'Seek-Place' II '2 5 25 75' [495] z•FI 'Seek-Visible' II '1' [496] zz-z=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [497] [498] •wself'fmSeek' •wi 'Create' 'Form' 'Hide' [499] •wi 'caption' 'Seek' [500] •wi 'place' w [501] •wi 'visible' z [502] e'CMDSEEKG ý1' [503] •wi 'onClose' e [504] •wi 'limitwhere' 10 40 [505] [506] •wself':mFile' •wi 'Create' 'Menu' [507] •wi 'caption' '&File' [508] [509] •wself'.mExit' •wi 'Create' 'Menu' [510] •wi 'caption' 'E&xit' [511] •wi 'shortcut' 'X' 2 [512] •wi 'onClick' "0 0û':' •wi 'Close'" [513] [514] •wself':mEdit' •wi 'Create' 'Menu' [515] •wi 'caption' '&Edit' [516] [517] •wself'.mNext' •wi 'Create' 'Menu' [518] •wi 'caption' 'Find &next hit' [519] •wi 'shortcut' 114 0 ¦ 114=F3 [520] •wi 'onClick' "•wi 'Event' 'CMDSEEKG ý1' 'redFind' 1" [521] [522] •wself'..mPrev' •wi 'Create' 'Menu' [523] •wi 'caption' 'Find &previous hit' [524] •wi 'shortcut' 114 1 [525] •wi 'onClick' "•wi 'Event' 'CMDSEEKG ý1' 'redFind' ý1" [526] [527] •wself'..mCopy' •wi 'Create' 'Menu' [528] •wi 'caption' '&Copy' [529] •wi 'shortcut' 'C' 2 [530] •wi 'onClick' "•wi 'Event' 'CMDSEEKG ý1' 'Copy'" [531] [532] •wself':mView' •wi 'Create' 'Menu' [533] •wi 'caption' '&Sort' [534] [535] •wself'.mClass' •wi 'Create' 'Menu' [536] •wi 'caption' 'Sort list by Clas&s' [537] •wi 'shortcut' 'S' 2 [538] •wi 'onClick' "•wi 'Event' 'CMDSEEKG ý1' 'Sort' 1" [539] [540] •wself'..mName' •wi 'Create' 'Menu' [541] •wi 'caption' 'Sort list by &Name' [542] •wi 'shortcut' 'N' 2 [543] •wi 'onClick' "•wi 'Event' 'CMDSEEKG ý1' 'Sort' 2" [544] [545] •wself'..mHits' •wi 'Create' 'Menu' [546] •wi 'caption' 'Sort list by &Hits' [547] •wi 'shortcut' 'H' 2 [548] •wi 'onClick' "•wi 'Event' 'CMDSEEKG ý1' 'Sort' 3" [549] [550] C0 •NC [2]F [551] [552] •wself':st' •wi 'Create' 'Status' [553] •wi 'status' (1 4û1 '' 0 8) [554] [555] ¦ 4-col matrix [556] ¦ col 1: pane number, negative if an overlay pane [557] ¦ cols 2,3: 1 text show that text [558] ¦ 0 text don't show, but use width of text [559] ¦ text 33 show text; 33 is mimimum width (more if reqd) [560] ¦ text text2 ditto; use width of text2 as minimum [561] ¦ col 4: border: 0=no 1=inset 2=outset 8=expand 16=caps 32=num 64=scr [562] t0 4û [563] ttž 1 1 (' ',V,' ') 1 ¦ wsid [564] ¦ttž 2 1 (' ',(ôN),' functions ') 1 [565] ttž 2 1 (' ',(ô+/C=3),' functions, ',(ô+/C=2),' variables ') 1 [566] ttž 3 '' 25 1 [567] ttž 4 '' 25 1 [568] •wi 'status' t [569] [570] z,•wi 'PaneWhere' 3 [571] [572] •wself'.pb' •wi 'Create' 'Progress' ¦ note child of Status [573] •wi 'style' 1 ¦ 1=smooth [574] •wi 'value' 0 (1N) 1 0 ¦ 1 to avoid •WI DOMAIN ERROR when N=0 [575] •wi 'where' z [576] [577] •wself':bn' •wi 'Create' 'Button' 'Hide' [578] •wi 'style' 2 ¦ 2=cancel [579] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [580] [581] z':' •wi 'size' [582] [583] •wself':lv' •wi 'Create' 'Listview' [584] •wi 'style' 1 2 4 8 128 4096 ¦ 128=no header 4096=grid [585] •wi 'where' (0,0,z[1],200) ¦ wide enough so no horiz scroll bar, else 'size' misleading [586] [587] ¦•wi 'font' 'APL Santa Fe' 0.8 ¦ no, then ñ doesn't display correctly [588] [589] •wi 'scale' 3 ¦ font size will be specified in points [590] [591] ¦•wi 'font' 'APLFONT' 11 0 'default' ¦ 11 13 [592] [593] ¦ Get value of key k; if undefined, write default to the ini file [594] k•fx [2]( [2] •cr 'II'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ II [595] [596] t 'FontName' II 'APLFONT' [597] tt,•FI 'FontSize' II '11' [598] tt,•FI 'FontStyle' II '0' [599] tt, 'FontCharset' II 'default' [600] •wi 'font' t [601] [602] •wi 'scale' 1 [603] [604] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [605] ¦ first col must be left justified [606] c0 3û0 [607] ccž'C' 2 'left' [608] ccž'Name' (5/•enlist ûF) 'left' ¦ 5 to avoid •WI DOMAIN ERROR when N=0 [609] ccž'Hits' 5 'right' [610] ccž'Fake' 0 'right' ¦ because of behavior of 'AutoFit' 'header' 'all' [611] [612] •wi 'list' (0,1,100 1û'x') ¦ force vertical scrollbar [613] [614] •wi 'columndisplay' c [615] w+/c[;2] [616] d•wi 'size' [617] d[2]w ¦ + 5 ¦ allow for vert scrollbar [618] •wi 'size' d [619] w4•wi 'where' [620] [621] •wi 'list' (0 3û0 1 '') ¦ remove fake row that forced vertical scrollbar [622] [623] •wself':red' •wi 'Create' 'RichEdit' [624] •wi 'style' 4 16 64 4096 16384 32768 ¦ 4=multi-line 16=V SB 64=H SB 2048=APL 4096=read-only [625] ¦ 16384 else entire text selected when you select the Form [626] ¦ 32768 disable automatic word selection when highlighting with mouse [627] [628] •wi 'where' (0,w,z[1],z[2]-w) [629] [630] HW•wi 'hwnd' [631] [632] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [633] •wi 'selection' 0 ý1 ¦ select all [634] •wi 'scale' 3 ¦ points [635] [636] ¦•wi 'selfont' 'APL Santa Fe' 10 0 'default' ¦ all black [637] ¦•wi 'selfont' 'APL Santa Fe' 11 0 'default' ¦ shaded but readable [638] ¦•wi 'selfont' 'APL Santa Fe' 12 0 'default' ¦ shaded but readable [639] ¦•wi 'selfont' 'APL385 Unicode' 11 0 'default' ¦ Dyalog style; kinda ugly [640] ¦•wi 'selfont' 'APLNext' 11 0 'default' ¦ a little crisper [641] [642] t 'UFontName' II 'APLNext' [643] tt,•FI 'UFontSize' II '11' [644] tt,•FI 'UFontStyle' II '0' [645] tt, 'UFontCharset' II 'default' [646] •wi 'selfont' t [647] [648] ¦  Necessary because default is bold (huh?) [649] •wi 'selstyle' (0 0 0 0 0) ¦ bold, italic, underline, strikeout, protected [650] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection [651] [652] A1•AV[•IO+65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 48 49 50 51 52 53 54 55 56 57 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96 123 125 2 16 17 18 20 21 128 129 130 131 132 133 135 136 137 138 139 140 142 144 147 148 150 153 154 155 156 157 160 161 162 163 164 165 168 170 171 172 173 174 175 192 193 194 195 197 198 200 202 203 204 205 206 207 210 211 212 213 216 217 218 219 221 223 225 228 4 5 6 11 14 24 25 26 28 29 124 126 134 145 146 230 231 233 236 238 239 240 242 243 246 248 249 250 252 253 254 3 15 19 22 23 30 31 141 143 149 151 152 158 159 166 167 169 224 226 227 229 232 234 235 237 241 244 245 251 13 ] ¦ removed 0 7 8 9 10 12 27 127 [653] A2 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 48 49 50 51 52 53 54 55 56 57 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96 123 125 8364 229 230 236 249 242 199 252 233 226 228 224 231 234 235 232 239 238 196 201 244 246 251 214 220 162 163 165 225 237 243 250 241 209 191 245 248 253 161 171 187 192 193 194 195 197 198 200 202 203 204 205 206 207 210 211 212 213 216 217 218 219 221 255 223 227 8900 168 8592 8834 8835 8593 8595 8594 8867 8866 166 8764 8800 8710 215 8869 8868 8854 8711 8714 8745 8801 8805 8804 247 8728 9675 8744 8746 175 8739 9079 9055 9067 9068 9077 9035 9042 8968 8970 9109 9054 9017 9066 9064 9053 9024 9015 9082 9075 9060 9073 9021 9074 9023 9033 9049 9045 9038 9076 13 183 [654] ¦ 183=U00B7 : Middle dot, for untranslatable chars [655] [656] ¦ Streamlined version of ìAV2U [657] t 'UAU A;N' [658] tt, 'UA2[A1âA]' [659] tt, ':if 82†•DR A' [660] tt, ' N,0=•TYPE A' [661] tt, ' (N/,U)N/,A' [662] tt, ':end' [663] tt, 'U•FIRST 323 163 82 •DR U' [664] k•fx [2] t ¦õ AU A1 A2 [665] [666] ¦ Streamlined version of ìSetSelTextU [667] k•fx [2] 'ST A;K;U' 'UAU A' "K•wcall 'EM_SetTextEx' HW ('ST_SELECTION' 1200) (U,2û•tcnul)" ¦õ ST AU HW [668] [669] t' ]SEEK ',X [670] [671] ¦ tt,•tcnl,50û9472 ¦ U2500 : Unicode horizontal line [672] ¦ tt,•tcnl,'Test difficult characters:' [673] ¦ tt,•tcnl,'Execute õ' [674] ¦ tt,•tcnl,' Match ð' [675] ¦ tt,•tcnl,' Zilde ' [676] ¦ tt,•tcnl,' Domino ˜' [677] [678] tt,•tcnl [679] ST t [680] [681] •wi 'selection' (0,ý1+ût) ¦ offset, length [682] •wi 'selcolor' (0 196 0) [683] •wi 'selstyle' (1 0 0 0 0) ¦ bold [684] •wi 'selection' ý1 ¦ select none; cursor to end [685] [686] :if ’ûE ¦ any warnings? [687] s1•wi 'selection' [688] ST 1èE [689] •wi 'selection' (s,ý1+ûE) ¦ offset, length [690] •wi 'selcolor' (255 0 0) [691] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [692] •wi 'selection' ý1 ¦ select none; cursor to end [693] :end [694] [695] ¦ Pre-build a CHARFORMAT2 structure that sets background color [696] CF8484 ¦ cbSize [697] CF[8]4 ¦ dwMask CFM_BACKCOLOR [698] CF[65 66 67]255 255 0 ¦ yellow [699] CFAV CF [700] [701] VDLTB •WSID [702] :if Vð'' [703] V'CLEAR WS' [704] :end [705] [706] •wself':' [707] [708] •wi 'Show' [709] e'CMDSEEKG ý1' [710] •wi 'onResize' e [711] •wi 'onClose' e [712] [713] ':lv' •wi 'Focus' ¦ necessary to make Esc work during search (why?) [714] [715] X0 ¦ count hits [716] E0 ¦ count lines with hits [717] U0 ¦ count functions with hits [718] p0 5û' ' '' 0 0  ¦ class, name, # hits, pointer to fn in RichEdit, line numbers with hits [719] m0 2û ¦ all hits (start, length) in RichEdit [720] [721] •wself':red' [722] [723] :for N :in F ¦ inspect next function [724] [725] ¦k•dl 0.1 [726] [727] :if ':' •wi '‘stop' [728] s1•wi 'selection' [729] t'Interrupt',•tcnl [730] ST t [731] •wi 'selection' (s,ût) ¦ offset, length [732] •wi 'selcolor' (255 0 0) [733] •wi 'selstyle' (1 0 0 0 0) ¦ bold [734] •wi 'selection' ý1 ¦ select none; cursor to end [735] :leave [736] :end [737] [738] ':st.pb' •wi 'Stepit' [739] [740] ¦•wgive 0 ¦ yikes, this makes it take twice as long! [741] [742] ¦t100’iöN [743] ¦':st' •wi 'SetStatus' ('Searching function ',(ôi),' of ',(ôN),' (',(ôt),'%)','...') [744] ¦':st' •wi 'SetStatus' 3 (' Searching function ',(ôi),'... ') [745] ¦':st' •wi 'SetStatus' 3 (' Searching ',(ô100’iöN),'%... ') [746] [747] ¦  This was nice in the event that a huge variable took forever to search. [748] ¦ But it makes the other status panes shiver [749] ¦':st' •wi 'SetStatus' 4 (' ',N) [750] [751] y3=0 •NC N ¦ is it a function? ¦ VARS! ¦ note •NC says 4 for •LX, but we ony test 3= [752] :if y [753] V0 •VR N [754] :else [755] ¦VõN [756] ¦ *** New global access system functions [757] V0 •VGET N [758] [759] ¦ RHS 3/03/07 Let's try this, for speed [760] :if 82†•DR V [761] :continue [762] :end [763] [764] ¦ :if 82†•DR V [765] ¦ :orif 2<ûûV [766] ¦ :continue [767] ¦ :else [768] ¦ :if 2=ûûV [769] ¦ t1ûV [770] ¦ w4+2ûôt ¦ we want a blank between ']' and data, so FILT will work [771] ¦ V(('P—[—Q—;]—LI',ôw) •FMT ât),V [772] ¦ ¦ Keep trailing blanks, since they are arguably part of the data [773] ¦ V,V,•TCNL [774] ¦ :elseif •TCNLîV [775] ¦ ¦ Don't use ìPartition because we want to keep empty partitions [776] ¦ V1(V=•TCNL) •PENCLOSE V [777] ¦ tûV [778] ¦ w3+3ûôt ¦ we want a blank between ']' and data, so FILT will work [779] ¦ V( [2] ('P—[—Q—]—LI',ôw) •FMT ât),V [780] ¦ V•ENLIST V,•TCNL [781] ¦ :else ¦ simple vector, no CRs [782] ¦ V(6'[]'),V,•TCNL [783] ¦ :end [784] ¦ :end [785] ¦L•ai[2] [786] VSEEKFMT V [787] ¦L•ai[2]-L [788] ¦:if Lò1 [789] ¦ •'FYI, it took ',(ôL),' seconds for ]SEEK to search: ',N [790] ¦ ¦ FIXME so what? erase it? actually time was used formatting it. [791] ¦:end [792] :if 0=ûV [793] :continue [794] :end [795] ¦VV,6û' ' ¦ make it like a •VR; see ý5+ûV kludge below [796] ¦  not necessary now that we match •TCNL rather than •TCNL,'[' [797] :end [798] [799] LUP V [800] [801] ¦ Search •VR [802] [803] HL •SS A ¦ the heart of the matter [804] [805] :if D=1 ¦ single target? [806] :andif ~1îH ¦ no raw hits? [807] :continue ¦ next function [808] :end [809] [810] ¦ Syntactic filter [811] [812] HA SYN H ¦õ V a q [813] [814] :if D=1 ¦ single target? [815] :andif ~1îH ¦ no more hits? [816] :continue ¦ next function [817] :end [818] [819] ¦ Filter for APL / quoted strings / comments [820] [821] ¦P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [822] ¦  This doesn't work with my variable formatting stuff, like '(2)[13;] ...' [823] ¦ And besides, you're not allowed to have CRs embedded in functions any more [824] P1,ý1V •SS •TCNL ¦ partition on "[" (with trailing CRs); force header line [825] ¦ •SS is still faster than plain = ! [826] ¦P[ý5+ûV]1 ¦ force end of last line [827] ¦ The last 7 characters of a •VR are: •TCNL,' ì',•TCNL [828] ¦ P[ý5+ûV]1 above flags ....................  this blank [829] ¦ No, now that's not necessary at all, now that we match •TCNL rather than •TCNL,'[' [830] [831] IFILT ¦õ P V ANDSCAN [832] HH^I [833] [834] :if D=1 ¦ single target? [835] :andif ~1îH ¦ no more hits? [836] :continue ¦ next function [837] :end [838] [839] R(ûV)û0 [840] R[(H/âûH)ø.+ý1+âûA]1 ¦ flag chars to highlight [841] [842] hP ORRED H ¦ shift hits to leading "[" [843] [844] :if D>1 ¦ multiple targets [845] [846] ¦ We have already done the last target; now step through the others [847] ¦ Note that they are in reverse order so functions work like APL [848] [849] ¦ /t1/ú/t2/ don't stop and display after first hit -- we want to show them all [850] ¦ /t1/&~/t2/ it is okay to show "all" hits since we will exclude lines with t2 [851] [852] :if g ¦ "@" global option? [853] tú/h [854] :for J :in 1âD [855] WL •SS JG ¦ raw search [856] W(JG) SYN W ¦ SYN [857] WW^I ¦ FILT [858] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [859] HHúW ¦ all hits [860] WP ORRED W ¦ shift hits to leading "[" [861] hWúh ¦ lines to show [862] tõ'(ú/W)',(JS),'t' ¦ apply function [863] :end [864] :if ~t ¦ no hits? [865] :continue ¦ next function [866] :end [867] :else [868] :for J :in 1âD [869] WL •SS JG ¦ raw search [870] W(JG) SYN W ¦ SYN [871] WW^I ¦ FILT [872] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [873] HHúW ¦ all hits [874] WP ORRED W ¦ shift hits to leading "[" [875] hõ'W',(JS),'h' ¦ apply function [876] :end [877] :if ~1îh ¦ no more hits? [878] :continue ¦ next function [879] :end [880] :end [881] [882] ¦ Only count hits on lines that will be displayed [883] ¦ (When searching for /1/^/2/ don't count 2s on lines without 1) [884] [885] Hh/P PLUSRED H [886] [887] :end [888] [889] ¦ Got some hits [890] [891] x+/H ¦ total hits in this fn [892] t':lv' •wi 'AddRows' 0 1 (,'ì'[1+y]) N (ôx) [893] k':lv' •wi 'EnsureVisible' t [894] [895] XX+x ¦ accumulate total hits [896] Hh ¦ lines with hits [897] EE++/H ¦ accumulate lines with hits [898] UU+1 ¦ accumulate functions with hits [899] [900] ¦ Display hits [901] [902] HH/âûH ¦ line numbers to display (origin 1) [903] WûH ¦ number of lines with hits [904] PP/âûP ¦ partition starts [905] L(1P,1+ûV)-P ¦ partition lengths [906] :if b ¦ expanded context? [907] :if y [908] eâûP ¦ all line numbers (including the trailing ì line) [909] :else [910] eâý1+ûP ¦ all line numbers (the last line of variables is bogus) [911] :end [912] H(eîHø.+ý1 0 1)/e ¦ this takes care of dups and edges [913] IH>1+ý1èH ¦ flag beginnings of groups of lines [914] :else [915] I(ûH)û0 [916] :end [917] PP[H]-1 ¦ compensate for +â with •IO1 [918] LL[H] ¦ lengths, incl trailing CRs [919] [920] ppž ('ì'[1+y]) N x (1•wi 'selection') H [921] [922] e5û9472 ¦ 9472=U2500 : Horizontal line [923] ¦  5 positions the fn name where it is in the header line (of a niladic fn) [924] te,' ',N,' (',(ôx),' hit',(x=1)'s',((x†W)/' on ',(ôW),(-W=1)' lines'),') ' [925] tt,((70-ût)ûe),•tcnl [926] ST t [927] n•first ût ¦ length of line [928] s1•wi 'selection' [929] ss-n ¦ back up to beginning of line [930] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [931] •wi 'selection' s (n-1) ¦ offset, length [932] :if y [933] ¦V[1 2]' ' ¦ undo kludge for FILT ¦ FIXME was this for *var* deep search? [934] •wi 'selcolor' (0 0 255) ¦ blue fns [935] :else [936] •wi 'selcolor' (255 0 255) ¦ purple vars [937] :end [938] •wi 'selection' (6+s) (•first ûN) ¦ just the function name [939] •wi 'selstyle' (1 0 0 0 0) ¦ bold [940] •wi 'selection' ý1 ¦ select none; cursor to end [941] •wi 'Paint' ¦ show bolded fn name while hits display [942] [943] :for B :in âûH [944] :if I[B] [945] ST (3û183),•TCNL ¦ 183=U00B7 : Middle dot [946] :end [947] nL[B] [948] jP[B]+ân ¦ indices of line in •VR [949] ST V[j] [950] s(1•wi 'selection')-n+1 [951] C(R[j]) Partition ân ¦ groups of chars to highlight [952] :for j :in C [953] e(s+1j),ûj ¦ offset, length [954] mmže ¦ all hits [955] •wi 'selection' e ¦ offset, length [956] ¦•wi 'selcolor' (255 0 255) ¦ purple [957] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [958] k•wcall 'EM_SETCHARFORMAT' HW 1 CF ¦ SCF_SELECTION=1 ¦ yellow background [959] :end [960] •wi 'selection' ý1 ¦ select none; cursor to end [961] :end [962] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection ¦ else :red does not scroll down [963] •WGIVE 0 ¦ listview does not display without this [964] ¦k•dl 0.1 [965] [966] :end ¦ next function [967] [968] ':bn' •wi 'onClick' '' ¦ let style 2 take over [969] [970] ¦ •wi 'selection' 0 ý1 ¦ select all [971] ¦ •wcall 'EM_SETPARAFORMAT' HW PARAFORMAT2 [972] ¦ •wi 'selection' ý1 ¦ select none; cursor to end [973] [974] :if U=0 [975] [976] s1•wi 'selection' [977] [978] t'Not found',•tcnl [979] ST t [980] [981] •wi 'selection' (s,ý1+ût) ¦ offset, length [982] •wi 'selcolor' (255 0 0) [983] •wi 'selstyle' (1 0 0 0 0) ¦ bold [984] •wi 'selection' 0 0 ¦ cursor to top [985] [986] L1 [987] [988] :end [989] [990] ppž ' ' '' 0 (1•wi 'selection')  ¦ fake row so we know position of end of text [991] [992] •wi 'selection' 0 0 ¦ cursor to top [993] [994] •wself':lv' [995] [996] •wi 'noredraw' 1 [997] •wi 'AutoFit' 'all' [998] c•wi 'columndisplay' [999] cý1 0c ¦ delete Fake column [1000] •wi 'columndisplay' c [1001] [1002] •wi 'highlightfocus' 1 [1003] •wi 'value' 1 [1004] k•wi 'EnsureVisible' 1 [1005] [1006] •wi 'noredraw' 0 [1007] [1008] d+/c[;2] [1009] z•wi 'size' [1010] z[2]d [1011] •wi 'size' z [1012] w•wi 'where' [1013] [1014] z':' •wi 'size' [1015] d':red' •wi 'where' [1016] d[2]w[4] [1017] d[4]z[2]-w[4] [1018] ':red' •wi 'where' d [1019] [1020] •wi 'Focus' [1021] [1022] •wi '‘p' p [1023] [1024] e'CMDSEEKG ý1' [1025] [1026] ¦  Sadly, when you click a different row in the list, both these events fire [1027] •wi 'onClick' e [1028] •wi 'onSelect' e [1029] [1030] •wi 'keys' 13 ¦ 13=Enter [1031] •wi 'onKeyPress' e [1032] •wi 'onDblClick' e [1033] [1034] •wself':red' [1035] [1036] •wi '‘m' m [1037] [1038] •wi 'keys' 13 ¦ 13=Enter [1039] •wi 'onKeyPress' e [1040] •wi 'onMouseDouble' e ¦ sadly, there is no onDblClick [1041] [1042] L1: [1043] [1044] •wself':st' [1045] [1046] '.pb' •wi 'Delete' [1047] [1048] t(2æf)'variables' 'functions' 'fns/vars' [1049] t' ',(ôX),' hits on ',(ôE),' lines in ',(ôU),' ',t,' ' [1050] •wi 'SetStatus' 3 t [1051] [1052] v•ai[2]-v [1053] t(0 1ôv),' seconds elapsed' ¦ note free leading blank [1054] •wi 'SetStatus' 4 t [1055] [1056] •wself':' [1057] [1058] k•wi 'Wait' [1059] [1060] 0 [1061] [1062] ¦ ============================================================================= [1063] [1064] L9: [1065] [1066] :SELECT •wevent [1067] [1068] :CASE 'Resize' [1069] [1070] (1=3•warg)û0 ¦ noop if minimize [1071] [1072] z•wi 'size' [1073] •wself':lv' [1074] w•wi 'where' [1075] w[3]z[1] [1076] •wi 'where' w [1077] •wself':red' [1078] w•wi 'where' [1079] w[3 4]z[1],z[2]-w[2] [1080] •wi 'where' w [1081] [1082] :CASELIST 'Click' 'Select' [1083] [1084] ¦ If you click on a new row, you get Click,Select [1085] ¦ If you click on the same row, you get just Click [1086] ¦ If you use keyboard, you get just Select [1087] [1088] i•first •wi 'value' [1089] (i=0)û0 ¦ click in blank row? [1090] [1091] :if •weventð'Click' [1092] •wi '‘skipnextselect' i [1093] :else [1094] Assert •weventð'Select' [1095] :if i=•wi '‘skipnextselect' [1096] •wi '‘skipnextselect' 0 [1097] 0 [1098] :end [1099] :end [1100] [1101] p•wi '‘p' [1102] (c N k s k)p[i;] ¦ class, name, hits, beginning of line, line numbers [1103] ss+6 ¦ advance past '----- ' [1104] n•first ûN [1105] [1106] •wself':red' [1107] [1108] •wi 'selection' s n [1109] [1110] ¦ Scroll into view on RichEdit control [1111] [1112] e1+•wi 'CharToLine' s ¦ line number of first line [1113] t1+•wi 'CharToLine' (p[i+1;4]-1) ¦ line number of last line [1114] g•wi 'range' [1115] g(g[1]-1)+âg[2] ¦ lines now visible [1116] :if 0î(e,t)îg ¦ if the whole fn is already visible, don't change range [1117] •wi 'range' e [1118] :end [1119] [1120] :CASE 'DblClick' [1121] [1122] i1•warg [1123] (i=0)û0 ¦ click in blank row? [1124] p•wi '‘p' [1125] N2p[i;] ¦ name [1126] [1127] k•WCALL 'W_Edit' N ¦ *** New global access system functions: FIXME [1128] [1129] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1130] [1131] :CASE 'MouseDouble' [1132] [1133] ¦ Second mouseup has not occurred yet, so we have to wait [1134] [1135] ¦ Pass mouse position before Windows does "word" select, which could change selection offset [1136] [1137] •wi 'Defer' 'CMDSEEKG ý1' 'KeyPress' (•wi 'selection') [1138] [1139] :CASE 'KeyPress' [1140] [1141] :if 'Listview'ð•wi 'class' [1142] [1143] i•first •wi 'value' [1144] (i=0)û0 ¦ click in blank row? [1145] p•wi '‘p' [1146] N2p[i;] ¦ name [1147] [1148] :else [1149] [1150] Assert 'RichEdit'ð•wi 'class' [1151] [1152] ¦ This could be from Enter key or from MouseDouble [1153] :if •wargð13 [1154] s•first •wi 'selection' [1155] :else [1156] Assert 2=û,•warg [1157] s•first •warg [1158] :end [1159] •wi 'selection' s 0 ¦ cancel word-selection [1160] ¦  Sadly, Windows may have changed the offset to the beginning of a "word" [1161] p':lv' •wi '‘p' ¦ name, hits, beginning of line, line numbers [1162] n1ûp [1163] (s=p[n;4])û0 ¦ beyond end? [1164] i+/sòp[;4] [1165] (c N k g n)p[i;] [1166] e1+•wi 'CharToLine' g ¦ divider line [1167] d1+•wi 'CharToLine' s ¦ clicked line [1168] :if e=d [1169] n0 [1170] :else [1171] id-e [1172] (i>ûn)û0 ¦ on Interrupt message [1173] ný1+n[i] ¦ ý1+ because we recorded line numbers in origin 1 [1174] :end [1175] NN,'[',(ôn),']' [1176] [1177] :end [1178] [1179] k•WCALL 'W_Edit' N [1180] [1181] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1182] [1183] :CASE 'Sort' [1184] [1185] i•warg [1186] •wself':lv' [1187] d•wi 'sortorder' [1188] pý1 0•wi '‘p' [1189] [1190] :if iî1 2 ¦ Class, Name [1191] wd[•AV[2]p[d;i]] ¦ new order [1192] :if dðw ¦ already sorted? [1193] wd[•AV[2]p[d;i]] [1194] :end [1195] :elseif i=3 ¦ Hits [1196] wd[p[d;i]] [1197] :if dðw [1198] wd[p[d;i]] [1199] :end [1200] :else [1201] ö'Tilt' [1202] :end [1203] [1204] •wi 'sortorder' w ¦ this triggers a Select [1205] [1206] i•first •wi 'value' [1207] •wi '‘skipnextselect' i [1208] [1209] :CASE 'Close' [1210] [1211] ¦ Set value of key k in APLW.INI section [UCMDSREX] [1212] k•fx [2] 'k II v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ II [1213] [1214] 'Seek-Place' II •wi 'place' [1215] 'Seek-Visible' II •wi 'visible' [1216] [1217] ¦•wi 'Delete' ¦ requires APL+Win version ò 6.2 [1218] [1219] '#' •wi 'Defer' "'fmSeek' •wi 'Delete'" ¦ works with APL+Win version < 6.2 [1220] [1221] :CASE 'redFind' [1222] [1223] •wself':red' [1224] s•first •wi 'selection' [1225] m•wi '‘m' ¦ offsets, lengths [1226] :if •warg=1 ¦ 1=next ý1=prev [1227] i(m[;1]>s)â1 [1228] :if i>1ûm  i1  :end [1229] :else [1230] iý1+(m[;1]/t2/ ¦ Can use any of <ó=ò>†ú^åê&þ and ~ [25] ¦ ]seek /t1/^~/t2/ú/t3/ ¦ Evaluated as APL would ("right to left") [26] [27] ¦ Default is to perform case-sensitive, syntactic (name) search [28] ¦ Default is to search all global functions and simple character variables with rankó2 [29] [30] ¦ Options: [31] ¦ To loosen match criteria: [32] ¦ ¦ Non-syntactic search (ANY occurrence) (Alt+S for non-Syntactic) [33] ¦ ï ¦ Ignore case (upper/lower/underscore) (Alt+C for Case) [34] ¦ To limit classes searched: [35] ¦ ì ¦ Find only in functions [36] ¦  ¦ Find only in variables [37] ¦ To limit fns/vars searched: [38] ¦ *** These options are not (yet) supported in this user-command-file variant *** [39] ¦ f1 f2 ¦ Only look in named fns/vars [40] ¦ f* ¦ Names with wildcards (foo* *old fm*def etc.) [41] ¦ ~f1 f2 ¦ Look in all but named fns/vars [42] ¦ To limit search scope (using all three is equivalent to using none): [43] ¦ ¦ ¦ Find only in comments [44] ¦ ' ¦ Find only in character constants (or /") [45] ¦ à ¦ Find only in APL (not comments/quotes) [46] ¦ If you use these options, variables are not searched ??? FIXME [47] ¦ To expand search scope: [48] ¦ @ ¦ Find strings anywhere in a fn/var -- not necessarily on the same line. [49] ¦ Only useful with multiple targets. Doesn't change behavior of /t1/ú/t2/. [50] ¦ Display from /t1/^/t2/@ is similar to /t1/ú/t2/ but only shows fns/vars [51] ¦ that contain at least one hit on both strings. [52] ¦ To expand display: [53] ¦ + ¦ Show lines immediately before and after hits, for better context [54] [55] ¦ To do: [56] ¦ Add an input edit box to show (and revise?) target [57] ¦ /t1/ú/t2/ Use a different color for each term? What if they overlap? [58] ¦ Resize of Form could cause Listview vertical scrollbar to come and go [59] ¦ Make default be shallow variable search like ]WSLOC ; use  option for deep search? [60] ¦ Double-click in RichEdit is not reliable [61] [62] ¦ 15 Dec 1987 Rex Swain, Independent Consultant, www.rexswain.com [63] ¦ 19 May 1988 Detect and display changed function names [64] ¦ 16 May 1991 Erase old version when fn name changed [65] ¦ 27 Aug 1993 Added ï (ignore case) option [66] ¦ 26 Nov 1994 Adapted for Dyalog APL/W, added # and ## and  options [67] ¦ 29 Dec 1998 Adapted for APL+Win 3.0, removed # and ## and  options [68] ¦ 10 Nov 1999 Added colon as leading identifier char for APL+Win [69] ¦ 18 Nov 1999 Added case-insensitive treatment for APL+Win key names [70] ¦ 03 Dec 2001 Removed colon -- it can OPTIONALLY begin an identifier [71] ¦ 04 Apr 2003 Report total number of hits [72] ¦ 18 May 2003 Added ~ feature [73] ¦ 14 May 2004 Added ? feature [74] ¦ 29 Aug 2004 Added * feature [75] ¦ 26 Mar 2005 Evlevel-neutral (sigh) [76] ¦ 11 Jul 2005 Use QC (derived from Zark's ParseVR) to handle ' and " quotes [77] ¦ 21 Jul 2005 Created ìCMDFNREPL from ìfnrepl [78] ¦ 07 Oct 2005 Fixed FILT bug -- H>QC should be H^QC ! [79] ¦ 06 Feb 2006 Added multiple target feature [80] ¦ 04 Mar 2006 Added @ option [81] ¦ 15 Feb 2007 GUI version, based on ]FNREPL but without replace feature [82] ¦ 16 Feb 2007 Include simple character arrays in search, like ]WSLOC does [83] ¦ 17 Feb 2007 Added + feature [84] ¦ 18 Feb 2007 Deep search on all variables [85] ¦ 19 Feb 2007 Added ì and  features [86] ¦ 24 Feb 2007 Use /ULIST for Winklevoss [87] ¦ 13 Apr 2007 Kludge for Winklevoss: skip over huge array [88] ¦ 12 May 2007 Added Ctrl+C from RichEdit [89] ¦ 29 May 2007 Fixed bug which caused hits in function header lines to not match [90] ¦ 08 Jul 2007 Updated ìQC [91] ¦ 25 Jan 2008 Fixed error when sorting by class [92] ¦ 02 Jun 2010 Use UcmdIni and UcmdFont subroutines [93] ¦ 08 Sep 2010 Most recent minor fix [94] [95] (Aðý1)ûL9 ¦ callbacks [96] [97] v•AI[2] ¦ elapsed time [98] [99] Aô•ENLIST A ¦ arg might be numeric in development mode [100] [101] ADLTB A ¦ user command may pass in leading/trailing blanks [102] [103] :if Að'' [104] •'For help, see' [105] •' ]seek ?' [106] 0 [107] :end [108] [109] XA ¦ save original arg [110] [111] ¦ Allow simple word search without delimiters [112] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [113] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [114] A'/',A [115] :end [116] [117] ¦ Parse targets and functions [118] [119] G0û '' ¦ targets [120] S0û '' ¦ functions [121] [122] :repeat [123] D1A ¦ delimiter [124] A1A [125] IAâD ¦ find second delimiter (might not be one) [126] :if I=1 [127] •'Empty target string is not a good idea' [128] 0 [129] :end [130] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [131] ADLB IA [132] P1A ¦ function or option [133] :if ~Pî'<ó=ò>†ú^åê&þ' [134] :leave [135] :end [136] P('^ú',P)['&þ'âP] [137] ADLB 1A [138] :if '~'=1A [139] PP,'~' [140] ADLB 1A [141] :end [142] S( P),S ¦ function [143] :if Að'' [144] •'Multiple target syntax error' [145] 0 [146] :end [147] :end [148] [149] FA ¦ options (old left argument) [150] [151] D•FIRST ûG ¦ number of targets [152] [153] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [154] [155] ¦ Define ìFILT for APL/quoted strings/comments: [156] [157] Z'à''¦'îF [158] Z[2]Z[2]ú'"'îF [159] Z2æZ [160] E~Zî0 8 ¦ not all or none: we need to filter [161] [162] :if E ¦ unless all or none [163] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [164] LL, "¦ Quotes and Comments" [165] LL, "¦ Right arg is a •VR" [166] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [167] LL, "¦ Extracted from Zark's ìParseVR" [168] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [169] LL, "¦ 26 Oct 2004 Include ¦õ" [170] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [171] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [172] LL, "•IO0 ¦ origin 0 is convenient" [173] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [174] LL, "xcx\n" [215] LL, "¦ Flag newline after each comment; then convert pairs to maps" [216] LL, "tnúc" [217] LL, "ut/c" [218] LL, "c†\x\t\uúý10,u" [219] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [220] ¦ 0=None and 7=All cases are excluded before we get here [221] P 'rc' ¦ 1 = ¦ [222] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [223] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [224] PP, 'rqåc' ¦ 4 = à = 'å¦ [225] PP, 'r~q' ¦ 5 = ঠ= ~' [226] PP, 'r~c' ¦ 6 = à' = ~¦ [227] LL,P[Z] [228] K•FX[2]L ¦õ QC [229] :end [230] [231] L 'RFILT' [232] LL, '¦ Raw hit filter' [233] LL, '¦ V=•VR, P=partition flags' [234] ¦LL, 'R~P ANDSCAN Vî"[1234567890]"' ¦ not line numbers [235] LL, 'RP ANDSCAN V†"]"' ¦ not line numbers; allow for (2)[23;] too [236] ¦LL, 'RRåý1è1 0R' ¦ flag the ] too (we assume there is one!) [237] LL, 'RRåR<ý1èR' ¦ < is way faster than  [238] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [239] [240] K•FX[2]L ¦õ FILT ANDSCAN QC [241] [242] ¦ Define ìSYN for syntactic search [243] [244] Z''îF ¦ non-syntactic search? [245] [246] ¦ Token alphabet: chars that can be anywhere in a token [247] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [248] a'_' [249] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [250] aa,'abcdefghijklmnopqrstuvwxyzñ' [251] aa,'0123456789' [252] ¦ Token alphabet, including chars that can only begin a token [253] qa,'•ý' [254] [255] Q 'HA SYN H;B;I' [256] QQ, '¦ Syntactic hit filter' [257] QQ, '¦ Requires: V=•VR, a,q=alphabet' [258] QQ, 'IH/âûH' [259] ¦  Note that if target starts with • then we don't care what's to the [260] ¦ left of it, so ((1A)îa) is correct. [261] QQ, ':if (1A)îa' [262] QQ, ' H[(('' '',V)[I]îq)/I]0' [263] QQ, ':end' [264] QQ, ':if (ý1A)îq' [265] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [266] QQ, ':end' [267] :if Z=1 ¦ Neither? [268] Q1ûQ ¦ noop [269] :end [270] K•FX[2]Q ¦õ SYN a q [271] [272] ¦ Define ìUP for case-insensitive filter [273] [274] Z'ï'îF ¦ ignore case when finding target? [275] [276] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [277] ¦ Noop if no letters in targets [278] K•FX[2]'VUP V' '¦ noop' [279] :elseif Z [280] Q'ñabcdefghijklmnopqrstuvwxyz' [281] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [282] uc•AV [283] uc[ucâQ]L [284] K•FX[2]'VUP V' 'Vuc[•AVâV]' ¦õ UP uc ¦ this is faster than ñUCASE! [285] :else [286] mc'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [287] uc'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [288] Q 'VUP V;B;I;L;S' [289] QQ, '¦ Force APL+Win keyword names to upper case' [290] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [291] QQ, '¦ RHS 11/18/99' [292] QQ, '' [293] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [294] QQ, 'BVî''•'' ¦ find key symbols' [295] QQ, '(1îB)0 ¦ quit if none' [296] QQ, '' [297] QQ, 'LVîmc ¦ flag all letters (any case)' [298] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [299] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [300] QQ, '(1îB)0 ¦ quit if none' [301] QQ, '' [302] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [303] QQ, 'IS/B ¦ flag those which are candidates' [304] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [305] QQ, 'I†\I ¦ name mask' [306] QQ, 'II/âûI ¦ indices' [307] QQ, '' [308] QQ, 'V[I]uc[mcâV[I]] ¦ translate' [309] K•FX[2]Q [310] ¦ RHS 3/19/01 [311] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [312] ¦ when searching for 'fMain'. [313] ¦ List of keywords? No, could have ':end' •wi 'New' ... [314] ¦ I think we need to upper-case just the à part of the •vr [315] ¦ RHS 2/06/06 [316] ¦ I often search for •fappend or •io. [317] ¦ I cannot recall EVER having searched for :repeat. [318] ¦ So let's not worry about control structure keywords. [319] :end [320] [321] GUPG ¦ targets to uppercase [322] A1G ¦ last (and typically only) target string [323] [324] ¦ Options setup [325] [326] T'~'îF ¦ all but named fns? [327] b'+'îF ¦ expanded context? [328] f'ì'îF ¦ just fns/vars? [329] ffúå/f ¦ neither means both [330] UL1 ¦ search user command files? [331] [332] g'@'îF ¦ global fn matching? [333] :if g^D=1 [334] •'FYI, the @ option has no effect with just one target string' [335] g0 [336] :end [337] [338] ¦ Strip flags from function list [339] [340] E'*'îF ¦ any function name wildcards? [341] F(~Fî'à''¦ï~?@+ì')/F ¦ note we do not remove asterisk [342] FWords F [343] [344] ¦ Default to all fns [345] [346] :if T^0=ûF [347] •'Tilde with no names means "not all fns/vars"' [348] 0 [349] :end [350] [351] E'' ¦ accumulate warning messages [352] [353] ULûL2 ¦ FIXME specific fn names, wildcards not supported? [354] [355] :if EúTú0=ûF [356] [357] ¦ You could have a global function that is localized but undefined [358] ¦ •IDLIST 1+2+8 will not pick up that name, so... [359] [360] N•SINL [361] N(~N[;1]î'õ•><')ëN ¦ no local names at these levels [362] N(,ú\N=' ')/,N ¦ discard FOO[3], keep names to the right [363] NWords N ¦ all localized names [364] NN~ ,'*' ¦ the asterisk next to suspended fn is not a name [365] N('•'†•FIRSTN)/N ¦ avoid picking up system vars (ñUCMD2 localizes •PW and •CT) [366] [367] M•IDLIST 1+2+8 ¦ all visible names [368] MWords M [369] MM,N ¦ add all localized names [370] ¦MM,'•ALX' '•ELX' '•LX' ¦ ]WSLOC searches these ¦ oh forget it, ]ucmd shadows •ALX and •ELX [371] M((MâM)=âûM)/M ¦ there might be dups [372] MM[•AV[2]M] ¦ re-sort [373] [374] N,•SI [375] N(ý1+Nâ'[')ûN ¦ name of self ¦ RHS 8/31/99 [376] MM~ N ¦ remove self [377] [378] P•IDLOC [2]M ¦ what are they [379] PP[;0æûP] ¦ global definition [380] M(Pîf/1 2)/M ¦ fns and vars, depending on ì options [381] [382] ¦ Now we have all global fns/vars (though some could be shadowed) [383] [384] :if 0=ûF [385] FM [386] :elseif E ¦ which implies 0†ûF [387] :while '*'î•ENLIST F [388] P('*'îF)â1 [389] UPF [390] [391] VâûM ¦ indices of matches [392] C' ',M,' ' ¦ candidates [393] U('*'=1U)' ',U,('*'=ý1U)' ' [394] :for L :in '*' Words U [395] BC •SS L [396] Hú/B [397] C((H/B)â1)H/C [398] VH/V [399] :if Vð  :leave  :end [400] :end [401] CM[V] [402] [403] F((P-1)ûF),C,PF [404] :end [405] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [406] :end [407] :if T [408] FM~F [409] :end [410] :end [411] [412] ¦ If we are filtering for APL/quotes/comments, ditch all variables [413] ¦ FIXME is this a good idea? what if •vr's stored in vars? [414] [415] ¦ :if 3=•NC 'QC' [416] ¦ F(2†•NC [2]F)/F [417] ¦ •'ditching vars' [418] ¦ :end [419] [420] ¦ Discard invalid names [421] [422] C•NC [2]F ¦ 0=undef 1=label 2=var 3=fn 4=other/invalid [423] ¦ ¦ Aw jeez. •NC says system names are invalid. •IDLOC classifies them correctly, [424] ¦ ¦ but gives DOMAIN ERROR on truly invalid names. Sigh. Kludge ahead... [425] ¦ C[(Fî'•ALX' '•ELX' '•LX')/âûF]2 [426] :if 4îC [427] N(C=4)/F [428] ¦•'*** Not searched, invalid name',(1=ûN)'s:',ôN [429] EE,•TCNL,'Not searched, invalid name',(1=ûN)'s:',ôN [430] F(C†4)/F [431] :end [432] [433] ¦ Discard shadowed names [434] [435] L•IDLOC [2]F ¦ what are names fn=1 var=2 [436] L0 ý1L ¦ disregard global level [437] CL^.=ý1 [438] :if 0îC [439] N(~C)/F [440] ¦•'*** Shadowed:',ôN [441] EE,•TCNL,'Shadowed:',ôN [442] FC/F [443] :end [444] [445] ¦ Discard non-functions [446] [447] ¦C3=•NC [2]F [448] ¦C(•NC [2]F)î2 3 4 ¦ VARS! ¦ 4 allows •LX; we already checked for invalid [449] C(•NC [2]F)î2 3 ¦ VARS! [450] :if 0îC [451] N(~C)/F [452] ¦•'*** Not function',(1=ûN)'s:',ôN [453] ¦EE,•TCNL,'Not function',(1=ûN)'s:',ôN [454] EE,•TCNL,'Not functions or variables:',ôN ¦ VARS! [455] FC/F [456] :end [457] [458] ¦ Discard locked functions [459] [460] K•EX 'L' [461] ¦K•FX [2] 'RL F' "R0†•FIRST û•CRL F,'[0]'" ¦õ L [462] K•FX [2] 'RL F' ":if 3=•NC F  R0†•FIRST û•CRL F,'[0]'  :else  R1  :end" ¦õ L ¦ VARS! [463] CLF ¦ yuck, but I wanted to get this check out of the function loop [464] K•EX 'L' [465] :if 0îC [466] N(~C)/F [467] ¦•'*** Locked function',(1=ûN)'s:',ôN [468] EE,•TCNL,'Locked function',(1=ûN)'s:',ôN [469] FC/F [470] :end [471] [472] L2: [473] [474] :if UL [475] ul•wcall 'W_Ini' '[DIFF] ULIST' [476] :if ul^.=' ' [477] •'ULIST not set; use ]DIFF /ULIST=...' [478] 0 [479] :end [480] ul';' Words ul [481] [482] Nûul [483] V(ôN),(-N=1)' files' [484] ¦ Gather C and TN [485] TN [486] C [487] :for i :in âûul [488] ¦ Don't use ñTIEUF because it disturbs ucmd globals [489] tnñFTNUM iul [490] :if tn=0 [491] tn•FNUMS,•XFNUMS [492] tn((âûtn)îtn)â0 [493] (iul) •FSTIE tn [494] :end [495] TNTN,tn [496] j•FREAD tn,2 ¦ pointers to directories [497] un•FREAD tn,j[3] ¦ num directory of objects (nc, comp) [498] cun[;1] [499] c(cîf/3 2)/c ¦ 3=fn 2=var, depending on ì options [500] CC,c ¦ big vec of •nc [501] :end [502] N•first ûC [503] F, 20û' ' ¦ kludge for listview initial column width [504] :else [505] ul1û '' ¦ kludge to get one iteration in uloop [506] uf0 ¦ never show file name heading [507] VDLTB •WSID [508] :if Vð'' [509] V'CLEAR WS' [510] :end [511] N•first ûF [512] C•NC [2]F [513] :end [514] [515] :if N=0 [516] ¦•'No functions to search!' [517] ¦EE,•TCNL,'No functions to search!' [518] EE,•TCNL,'Nothing to search!' ¦ VARS! [519] ¦0 [520] :end [521] [522] w•FI UcmdIni 'Seek-Place' '2 5 25 75' [523] z•FI UcmdIni 'Seek-Visible' '1' [524] [525] zz-z=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [526] [527] •wself'fmSeek' •wi 'Create' 'Form' 'Hide' [528] •wi 'caption' 'Seek' [529] •wi 'place' w [530] •wi 'visible' z [531] e'CMDSEEKU ý1' [532] •wi 'onClose' e [533] •wi 'limitwhere' 10 40 [534] [535] •wself':mFile' •wi 'Create' 'Menu' [536] •wi 'caption' '&File' [537] [538] •wself'.mExit' •wi 'Create' 'Menu' [539] •wi 'caption' 'E&xit' [540] •wi 'shortcut' 'X' 2 [541] •wi 'onClick' "0 0û':' •wi 'Close'" [542] [543] •wself':mEdit' •wi 'Create' 'Menu' [544] •wi 'caption' '&Edit' [545] [546] •wself'.mCopy' •wi 'Create' 'Menu' [547] •wi 'caption' '&Copy' [548] •wi 'shortcut' 'C' 2 [549] •wi 'onClick' "•wi 'Event' 'CMDSEEKU ý1' 'Copy'" [550] [551] •wself'..mNext' •wi 'Create' 'Menu' [552] •wi 'caption' 'Find &next hit' [553] •wi 'shortcut' 114 0 ¦ 114=F3 [554] •wi 'onClick' "•wi 'Event' 'CMDSEEKU ý1' 'redFind' 1" [555] [556] •wself'..mPrev' •wi 'Create' 'Menu' [557] •wi 'caption' 'Find &previous hit' [558] •wi 'shortcut' 114 1 [559] •wi 'onClick' "•wi 'Event' 'CMDSEEKU ý1' 'redFind' ý1" [560] [561] •wself':mView' •wi 'Create' 'Menu' [562] •wi 'caption' '&Sort' [563] [564] •wself'.mClass' •wi 'Create' 'Menu' [565] •wi 'caption' 'Sort list by Clas&s' [566] •wi 'shortcut' 'S' 2 [567] •wi 'onClick' "•wi 'Event' 'CMDSEEKU ý1' 'Sort' 1" [568] [569] •wself'..mName' •wi 'Create' 'Menu' [570] •wi 'caption' 'Sort list by &Name' [571] •wi 'shortcut' 'N' 2 [572] •wi 'onClick' "•wi 'Event' 'CMDSEEKU ý1' 'Sort' 2" [573] [574] •wself'..mHits' •wi 'Create' 'Menu' [575] •wi 'caption' 'Sort list by &Hits' [576] •wi 'shortcut' 'H' 2 [577] •wi 'onClick' "•wi 'Event' 'CMDSEEKU ý1' 'Sort' 3" [578] [579] •wself':st' •wi 'Create' 'Status' [580] •wi 'status' (1 4û1 '' 0 8) [581] [582] ¦ 4-col matrix [583] ¦ col 1: pane number, negative if an overlay pane [584] ¦ cols 2,3: 1 text show that text [585] ¦ 0 text don't show, but use width of text [586] ¦ text 33 show text; 33 is mimimum width (more if reqd) [587] ¦ text text2 ditto; use width of text2 as minimum [588] ¦ col 4: border: 0=no 1=inset 2=outset 8=expand 16=caps 32=num 64=scr [589] t0 4û [590] ttž 1 1 (' ',V,' ') 1 ¦ wsid [591] ¦ttž 2 1 (' ',(ôN),' functions ') 1 [592] ttž 2 1 (' ',(ô+/C=3),' functions, ',(ô+/C=2),' variables ') 1 [593] ttž 3 '' 25 1 ¦ progress [594] ttž 4 '' 25 1 ¦ message [595] •wi 'status' t [596] [597] z,•wi 'PaneWhere' 3 [598] [599] •wself'.pb' •wi 'Create' 'Progress' ¦ note child of Status [600] •wi 'style' 1 ¦ 1=smooth [601] •wi 'value' 0 (1N) 1 0 ¦ 1 to avoid •WI DOMAIN ERROR when N=0 [602] :if ~ý1îz ¦ RHS 9/08/10 z is 4ûý1 if no room for pane (long wsid) [603] •wi 'where' z [604] :end [605] [606] •wself':bn' •wi 'Create' 'Button' 'Hide' [607] •wi 'style' 2 ¦ 2=cancel [608] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [609] [610] z':' •wi 'size' [611] [612] •wself':lv' •wi 'Create' 'Listview' [613] •wi 'style' 1 2 4 8 128 4096 ¦ 128=no header 4096=grid [614] •wi 'where' (0,0,z[1],200) ¦ wide enough so no horiz scroll bar, else 'size' misleading [615] [616] •wi 'scale' 3 ¦ font size will be specified in points [617] •wi 'font' (UcmdFont '5') [618] •wi 'scale' 1 [619] [620] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [621] ¦ first col must be left justified [622] c0 3û0 [623] ccž'C' 2 'left' [624] ccž'Name' (5/•enlist ûF) 'left' ¦ 5 to avoid •WI DOMAIN ERROR when N=0 [625] ccž'Hits' 5 'right' [626] ccž'Fake' 0 'right' ¦ because of behavior of 'AutoFit' 'header' 'all' [627] [628] •wi 'list' (0,1,100 1û'x') ¦ force vertical scrollbar [629] [630] •wi 'columndisplay' c [631] w+/c[;2] [632] d•wi 'size' [633] d[2]w ¦ + 5 ¦ allow for vert scrollbar [634] •wi 'size' d [635] w4•wi 'where' [636] [637] •wi 'list' (0 3û0 1 '') ¦ remove fake row that forced vertical scrollbar [638] [639] •wself':red' •wi 'Create' 'RichEdit' [640] •wi 'style' 4 16 64 4096 16384 32768 ¦ 4=multi-line 16=V SB 64=H SB 2048=APL 4096=read-only [641] ¦ 16384 else entire text selected when you select the Form [642] ¦ 32768 disable automatic word selection when highlighting with mouse [643] [644] •wi 'where' (0,w,z[1],z[2]-w) [645] [646] HW•wi 'hwnd' [647] [648] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [649] •wi 'selection' 0 ý1 ¦ select all [650] •wi 'scale' 3 ¦ points [651] [652] •wi 'selfont' (UcmdFont 'U') ¦ 'U' for Unicode [653] [654] ¦  Necessary because default is bold (huh?) [655] •wi 'selstyle' (0 0 0 0 0) ¦ bold, italic, underline, strikeout, protected [656] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection [657] [658] A1•AV[•IO+65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 48 49 50 51 52 53 54 55 56 57 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96 123 125 2 16 17 18 20 21 128 129 130 131 132 133 135 136 137 138 139 140 142 144 147 148 150 153 154 155 156 157 160 161 162 163 164 165 168 170 171 172 173 174 175 192 193 194 195 197 198 200 202 203 204 205 206 207 210 211 212 213 216 217 218 219 221 223 225 228 4 5 6 11 14 24 25 26 28 29 124 126 134 145 146 230 231 233 236 238 239 240 242 243 246 248 249 250 252 253 254 3 15 19 22 23 30 31 141 143 149 151 152 158 159 166 167 169 224 226 227 229 232 234 235 237 241 244 245 251 13 ] ¦ removed 0 7 8 9 10 12 27 127 [659] A2 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 48 49 50 51 52 53 54 55 56 57 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96 123 125 8364 229 230 236 249 242 199 252 233 226 228 224 231 234 235 232 239 238 196 201 244 246 251 214 220 162 163 165 225 237 243 250 241 209 191 245 248 253 161 171 187 192 193 194 195 197 198 200 202 203 204 205 206 207 210 211 212 213 216 217 218 219 221 255 223 227 8900 168 8592 8834 8835 8593 8595 8594 8867 8866 166 8764 8800 8710 215 8869 8868 8854 8711 8714 8745 8801 8805 8804 247 8728 9675 8744 8746 175 8739 9079 9055 9067 9068 9077 9035 9042 8968 8970 9109 9054 9017 9066 9064 9053 9024 9015 9082 9075 9060 9073 9021 9074 9023 9033 9049 9045 9038 9076 13 183 [660] ¦ 183=U00B7 : Middle dot, for untranslatable chars [661] [662] ¦ Streamlined version of ìAV2U [663] t 'UAU A;N' [664] tt, 'UA2[A1âA]' [665] tt, ':if 82†•DR A' [666] tt, ' N,0=•TYPE A' [667] tt, ' (N/,U)N/,A' [668] tt, ':end' [669] tt, 'U•FIRST 323 163 82 •DR U' [670] k•fx [2] t ¦õ AU A1 A2 [671] [672] ¦ Streamlined version of ìSetSelTextU [673] k•fx [2] 'ST A;K;U' 'UAU A' "K•wcall 'EM_SetTextEx' HW ('ST_SELECTION' 1200) (U,2û•tcnul)" ¦õ ST AU HW [674] [675] t' ]SEEKU ',X [676] [677] ¦ tt,•tcnl,50û9472 ¦ U2500 : Unicode horizontal line [678] ¦ tt,•tcnl,'Test difficult characters:' [679] ¦ tt,•tcnl,'Execute õ' [680] ¦ tt,•tcnl,' Match ð' [681] ¦ tt,•tcnl,' Zilde ' [682] ¦ tt,•tcnl,' Domino ˜' [683] [684] tt,•tcnl [685] ST t [686] [687] •wi 'selection' (0,ý1+ût) ¦ offset, length [688] •wi 'selcolor' (0 196 0) [689] •wi 'selstyle' (1 0 0 0 0) ¦ bold [690] •wi 'selection' ý1 ¦ select none; cursor to end [691] [692] :if ’ûE ¦ any warnings? [693] s1•wi 'selection' [694] ST 1èE [695] •wi 'selection' (s,ý1+ûE) ¦ offset, length [696] •wi 'selcolor' (255 0 0) [697] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [698] •wi 'selection' ý1 ¦ select none; cursor to end [699] :end [700] [701] ¦ Pre-build a CHARFORMAT2 structure that sets background color [702] CF8484 ¦ cbSize [703] CF[8]4 ¦ dwMask CFM_BACKCOLOR [704] CF[65 66 67]255 255 128 ¦ pale yellow [705] CFAV CF [706] [707] •wself':' [708] [709] •wi 'Show' [710] e'CMDSEEKU ý1' [711] •wi 'onResize' e [712] •wi 'onClose' e [713] [714] ':lv' •wi 'Focus' ¦ necessary to make Esc work during search (why?) [715] [716] X0 ¦ count hits [717] E0 ¦ count lines with hits [718] U0 ¦ count functions with hits [719] p0 5û' ' '' 0 0  ¦ class, name, # hits, pointer to fn in RichEdit, line numbers with hits [720] m0 2û ¦ all hits (start, length) in RichEdit [721] [722] •wself':red' [723] [724] :FOR ui :in âûul [725] [726] •WGIVE 0 [727] [728] :if UL [729] tnuiTN [730] j•FREAD tn,2 ¦ pointers to directories [731] ud•FREAD tn,j[2] ¦ char directory of objects (names) [732] un•FREAD tn,j[3] ¦ num directory of objects (nc, comp) [733] [734] cun[;1]îf/3 2 ¦ 3=fn 2=var, depending on ì options [735] udcëud [736] uncëun [737] [738] j•AVud [739] unun[j;] [740] udud[j;] [741] udWords ud [742] Fâûj ¦ kludge for name loop [743] uf1 ¦ show file name heading on first hit [744] :end [745] [746] :for N :in F ¦ inspect next function [747] [748] ¦k•dl 0.1 [749] [750] :if ':' •wi '‘stop' [751] s1•wi 'selection' [752] t'Interrupt',•tcnl [753] ST t [754] •wi 'selection' (s,ût) ¦ offset, length [755] •wi 'selcolor' (255 0 0) [756] •wi 'selstyle' (1 0 0 0 0) ¦ bold [757] •wi 'selection' ý1 ¦ select none; cursor to end [758] :leave [759] :end [760] [761] ':st.pb' •wi 'Stepit' [762] [763] ¦•wgive 0 ¦ yikes, this makes it take twice as long! [764] [765] ¦t100’iöN [766] ¦':st' •wi 'SetStatus' ('Searching function ',(ôi),' of ',(ôN),' (',(ôt),'%)','...') [767] ¦':st' •wi 'SetStatus' 3 (' Searching function ',(ôi),'... ') [768] ¦':st' •wi 'SetStatus' 3 (' Searching ',(ô100’iöN),'%... ') [769] [770] ¦  This was nice in the event that a huge variable took forever to search. [771] ¦ But it makes the other status panes shiver [772] ¦':st' •wi 'SetStatus' 4 (' ',N) [773] [774] :IF UL [775] [776] y,3=un[N;1] ¦ is it a function? ¦ RHS 1/25/08 ravel so like •NC which returns a one-element vector [777] V•FREAD tn,un[N;2] [778] NNud ¦ name of object [779] :if y [780] ¦ V is •VR already [781] V[1 2]'[]' ¦ kludge for FILT [782] :else [783] :if Nð'xmMap' ¦ Winklevoss kludge [784] :continue [785] :end [786] VSEEKFMT V [787] :if 0=ûV [788] :continue [789] :end [790] :end [791] [792] :ELSE ¦ if not UL [793] [794] y3=•NC N ¦ is it a function? ¦ VARS! ¦ note •NC says 4 for •LX, but we ony test 3= [795] :if y [796] V•VR N [797] V[1 2]'[]' ¦ kludge for FILT [798] :else [799] VõN [800] ¦ :if 82†•DR V [801] ¦ :orif 2<ûûV [802] ¦ :continue [803] ¦ :else [804] ¦ :if 2=ûûV [805] ¦ t1ûV [806] ¦ w4+2ûôt ¦ we want a blank between ']' and data, so FILT will work [807] ¦ V(('P—[—Q—;]—LI',ôw) •FMT ât),V [808] ¦ ¦ Keep trailing blanks, since they are arguably part of the data [809] ¦ V,V,•TCNL [810] ¦ :elseif •TCNLîV [811] ¦ ¦ Don't use ìPartition because we want to keep empty partitions [812] ¦ V1(V=•TCNL) •PENCLOSE V [813] ¦ tûV [814] ¦ w3+3ûôt ¦ we want a blank between ']' and data, so FILT will work [815] ¦ V( [2] ('P—[—Q—]—LI',ôw) •FMT ât),V [816] ¦ V•ENLIST V,•TCNL [817] ¦ :else ¦ simple vector, no CRs [818] ¦ V(6'[]'),V,•TCNL [819] ¦ :end [820] ¦ :end [821] ¦L•ai[2] [822] VSEEKFMT V [823] ¦L•ai[2]-L [824] ¦:if Lò1 [825] ¦ •'FYI, it took ',(ôL),' seconds for ]SEEK to search: ',N [826] ¦ ¦ FIXME so what? erase it? actually time was used formatting it. [827] ¦:end [828] :if 0=ûV [829] :continue [830] :end [831] ¦VV,6û' ' ¦ make it like a •VR; see ý5+ûV kludge below [832] ¦  not necessary now that we match •TCNL rather than •TCNL,'[' [833] :end [834] [835] :END [836] [837] LUP V [838] [839] ¦ Search •VR [840] [841] HL •SS A ¦ the heart of the matter [842] [843] :if D=1 ¦ single target? [844] :andif ~1îH ¦ no raw hits? [845] :continue ¦ next function [846] :end [847] [848] ¦ Syntactic filter [849] [850] HA SYN H ¦õ V a q [851] [852] :if D=1 ¦ single target? [853] :andif ~1îH ¦ no more hits? [854] :continue ¦ next function [855] :end [856] [857] ¦ Filter for APL / quoted strings / comments [858] [859] ¦P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [860] ¦  This doesn't work with my variable formatting stuff, like '(2)[13;] ...' [861] ¦ And besides, you're not allowed to have CRs embedded in functions any more [862] P1,ý1V •SS •TCNL ¦ partition on "[" (with trailing CRs); force header line [863] ¦ •SS is still faster than plain = ! [864] ¦P[ý5+ûV]1 ¦ force end of last line [865] ¦ The last 7 characters of a •VR are: •TCNL,' ì',•TCNL [866] ¦ P[ý5+ûV]1 above flags ....................  this blank [867] ¦ No, now that's not necessary at all, now that we match •TCNL rather than •TCNL,'[' [868] [869] IFILT ¦õ P V ANDSCAN [870] HH^I [871] [872] :if D=1 ¦ single target? [873] :andif ~1îH ¦ no more hits? [874] :continue ¦ next function [875] :end [876] [877] R(ûV)û0 [878] R[(H/âûH)ø.+ý1+âûA]1 ¦ flag chars to highlight [879] [880] hP ORRED H ¦ shift hits to leading "[" [881] [882] :if D>1 ¦ multiple targets [883] [884] ¦ We have already done the last target; now step through the others [885] ¦ Note that they are in reverse order so functions work like APL [886] [887] ¦ /t1/ú/t2/ don't stop and display after first hit -- we want to show them all [888] ¦ /t1/&~/t2/ it is okay to show "all" hits since we will exclude lines with t2 [889] [890] :if g ¦ "@" global option? [891] tú/h [892] :for J :in 1âD [893] WL •SS JG ¦ raw search [894] W(JG) SYN W ¦ SYN [895] WW^I ¦ FILT [896] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [897] HHúW ¦ all hits [898] WP ORRED W ¦ shift hits to leading "[" [899] hWúh ¦ lines to show [900] tõ'(ú/W)',(JS),'t' ¦ apply function [901] :end [902] :if ~t ¦ no hits? [903] :continue ¦ next function [904] :end [905] :else [906] :for J :in 1âD [907] WL •SS JG ¦ raw search [908] W(JG) SYN W ¦ SYN [909] WW^I ¦ FILT [910] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [911] HHúW ¦ all hits [912] WP ORRED W ¦ shift hits to leading "[" [913] hõ'W',(JS),'h' ¦ apply function [914] :end [915] :if ~1îh ¦ no more hits? [916] :continue ¦ next function [917] :end [918] :end [919] [920] ¦ Only count hits on lines that will be displayed [921] ¦ (When searching for /1/^/2/ don't count 2s on lines without 1) [922] [923] Hh/P PLUSRED H [924] [925] :end [926] [927] ¦ Got some hits [928] [929] :if uf [930] uf0 [931] e9552 ¦ 9552=U2550 : Double horizontal line [932] t(5ûe),' File: ',(uiul),' ' [933] tt,((70-ût)ûe),•tcnl [934] ST t [935] [936] n•first ût ¦ length of line [937] s1•wi 'selection' [938] ss-n ¦ back up to beginning of line [939] •wi 'selection' s (n-1) ¦ offset, length [940] [941] ¦ Mark thinks this is too colorful [942] ¦ jCF [943] ¦ j[65 66 67]AV 196 255 255 ¦ pale cyan [944] ¦ k•wcall 'EM_SETCHARFORMAT' HW 1 j ¦ SCF_SELECTION=1 ¦ background [945] [946] •wi 'selection' ((s+12),ûuiul) ¦ just the file name [947] •wi 'selstyle' (1 0 0 0 0) ¦ bold [948] [949] •wi 'selection' ý1 ¦ select none; cursor to end [950] :end [951] [952] x+/H ¦ total hits in this fn [953] t':lv' •wi 'AddRows' 0 1 (,'ì'[1+y]) N (ôx) [954] k':lv' •wi 'EnsureVisible' t [955] [956] XX+x ¦ accumulate total hits [957] Hh ¦ lines with hits [958] EE++/H ¦ accumulate lines with hits [959] UU+1 ¦ accumulate functions with hits [960] [961] ¦ Display hits [962] [963] HH/âûH ¦ line numbers to display (origin 1) [964] WûH ¦ number of lines with hits [965] PP/âûP ¦ partition starts [966] L(1P,1+ûV)-P ¦ partition lengths [967] :if b ¦ expanded context? [968] :if y [969] eâûP ¦ all line numbers (including the trailing ì line) [970] :else [971] eâý1+ûP ¦ all line numbers (the last line of variables is bogus) [972] :end [973] H(eîHø.+ý1 0 1)/e ¦ this takes care of dups and edges [974] IH>1+ý1èH ¦ flag beginnings of groups of lines [975] :else [976] I(ûH)û0 [977] :end [978] PP[H]-1 ¦ compensate for +â with •IO1 [979] LL[H] ¦ lengths, incl trailing CRs [980] [981] ppž ('ì'[1+y]) N x (1•wi 'selection') H [982] [983] e5û9472 ¦ 9472=U2500 : Horizontal line [984] ¦  5 positions the fn name where it is in the header line (of a niladic fn) [985] te,' ',N,' (',(ôx),' hit',(x=1)'s',((x†W)/' on ',(ôW),(-W=1)' lines'),') ' [986] tt,((70-ût)ûe),•tcnl [987] ST t [988] n•first ût ¦ length of line [989] s1•wi 'selection' [990] ss-n ¦ back up to beginning of line [991] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [992] •wi 'selection' s (n-1) ¦ offset, length [993] :if y [994] V[1 2]' ' ¦ undo kludge for FILT [995] •wi 'selcolor' (0 0 255) ¦ blue fns [996] :else [997] •wi 'selcolor' (255 0 255) ¦ purple vars [998] :end [999] •wi 'selection' (6+s) (•first ûN) ¦ just the function name [1000] •wi 'selstyle' (1 0 0 0 0) ¦ bold [1001] •wi 'selection' ý1 ¦ select none; cursor to end [1002] •wi 'Paint' ¦ show bolded fn name while hits display [1003] [1004] :for B :in âûH [1005] :if I[B] [1006] ST (3û183),•TCNL ¦ 183=U00B7 : Middle dot [1007] :end [1008] nL[B] [1009] jP[B]+ân ¦ indices of line in •VR [1010] ST V[j] [1011] s(1•wi 'selection')-n+1 [1012] C(R[j]) Partition ân ¦ groups of chars to highlight [1013] :for j :in C [1014] e(s+1j),ûj ¦ offset, length [1015] mmže ¦ all hits [1016] •wi 'selection' e ¦ offset, length [1017] ¦•wi 'selcolor' (255 0 255) ¦ purple [1018] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [1019] k•wcall 'EM_SETCHARFORMAT' HW 1 CF ¦ SCF_SELECTION=1 ¦ yellow background [1020] :end [1021] •wi 'selection' ý1 ¦ select none; cursor to end [1022] :end [1023] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection ¦ else :red does not scroll down [1024] •WGIVE 0 ¦ listview does not display without this [1025] ¦k•dl 0.1 [1026] [1027] :end ¦ next function [1028] :END ¦ next ufile [1029] [1030] ':bn' •wi 'onClick' '' ¦ let style 2 take over [1031] [1032] ¦ •wi 'selection' 0 ý1 ¦ select all [1033] ¦ •wcall 'EM_SETPARAFORMAT' HW PARAFORMAT2 [1034] ¦ •wi 'selection' ý1 ¦ select none; cursor to end [1035] [1036] :if U=0 [1037] [1038] s1•wi 'selection' [1039] [1040] t'Not found',•tcnl [1041] ST t [1042] [1043] •wi 'selection' (s,ý1+ût) ¦ offset, length [1044] •wi 'selcolor' (255 0 0) [1045] •wi 'selstyle' (1 0 0 0 0) ¦ bold [1046] •wi 'selection' 0 0 ¦ cursor to top [1047] [1048] L1 [1049] [1050] :end [1051] [1052] ppž ' ' '' 0 (1•wi 'selection')  ¦ fake row so we know position of end of text [1053] [1054] •wi 'selection' 0 0 ¦ cursor to top [1055] [1056] •wself':lv' [1057] [1058] •wi 'noredraw' 1 [1059] •wi 'AutoFit' 'all' [1060] c•wi 'columndisplay' [1061] cý1 0c ¦ delete Fake column [1062] •wi 'columndisplay' c [1063] [1064] •wi 'highlightfocus' 1 [1065] •wi 'value' 1 [1066] k•wi 'EnsureVisible' 1 [1067] [1068] •wi 'noredraw' 0 [1069] [1070] d+/c[;2] [1071] z•wi 'size' [1072] z[2]d [1073] •wi 'size' z [1074] w•wi 'where' [1075] [1076] z':' •wi 'size' [1077] d':red' •wi 'where' [1078] d[2]w[4] [1079] d[4]z[2]-w[4] [1080] ':red' •wi 'where' d [1081] [1082] •wi 'Focus' [1083] [1084] •wi '‘p' p [1085] [1086] e'CMDSEEKU ý1' [1087] [1088] ¦  Sadly, when you click a different row in the list, both these events fire [1089] •wi 'onClick' e [1090] •wi 'onSelect' e [1091] [1092] •wi 'keys' 13 ¦ 13=Enter [1093] •wi 'onKeyPress' e [1094] •wi 'onDblClick' e [1095] [1096] •wself':red' [1097] [1098] •wi '‘m' m [1099] [1100] •wi 'keys' 13 ¦ 13=Enter [1101] •wi 'onKeyPress' e [1102] •wi 'onMouseDouble' e ¦ sadly, there is no onDblClick [1103] [1104] L1: [1105] [1106] •wself':st' [1107] [1108] '.pb' •wi 'Delete' [1109] [1110] t(2æf)'variables' 'functions' 'fns/vars' [1111] t' ',(ôX),' hits on ',(ôE),' lines in ',(ôU),' ',t,' ' [1112] •wi 'SetStatus' 3 t [1113] [1114] v•ai[2]-v [1115] t(0 1ôv),' seconds elapsed' ¦ note free leading blank [1116] •wi 'SetStatus' 4 t [1117] [1118] •wself':' [1119] [1120] k•wi 'Wait' [1121] [1122] 0 [1123] [1124] ¦ ============================================================================= [1125] [1126] L9: [1127] [1128] :SELECT •wevent [1129] [1130] :CASE 'Resize' [1131] [1132] (1=3•warg)û0 ¦ noop if minimize [1133] [1134] z•wi 'size' [1135] •wself':lv' [1136] w•wi 'where' [1137] w[3]z[1] [1138] •wi 'where' w [1139] •wself':red' [1140] w•wi 'where' [1141] w[3 4]z[1],z[2]-w[2] [1142] •wi 'where' w [1143] [1144] :CASELIST 'Click' 'Select' [1145] [1146] ¦ If you click on a new row, you get Click,Select [1147] ¦ If you click on the same row, you get just Click [1148] ¦ If you use keyboard, you get just Select [1149] [1150] i•first •wi 'value' [1151] (i=0)û0 ¦ click in blank row? [1152] [1153] :if •weventð'Click' [1154] •wi '‘skipnextselect' i [1155] :else [1156] Assert •weventð'Select' [1157] :if i=•wi '‘skipnextselect' [1158] •wi '‘skipnextselect' 0 [1159] 0 [1160] :end [1161] :end [1162] [1163] p•wi '‘p' [1164] (c N k s k)p[i;] ¦ class, name, hits, beginning of line, line numbers [1165] ss+6 ¦ advance past '----- ' [1166] n•first ûN [1167] [1168] •wself':red' [1169] [1170] •wi 'selection' s n [1171] [1172] ¦ Scroll into view on RichEdit control [1173] [1174] e1+•wi 'CharToLine' s ¦ line number of first line [1175] t1+•wi 'CharToLine' (p[i+1;4]-1) ¦ line number of last line [1176] g•wi 'range' [1177] g(g[1]-1)+âg[2] ¦ lines now visible [1178] :if 0î(e,t)îg ¦ if the whole fn is already visible, don't change range [1179] •wi 'range' e [1180] :end [1181] [1182] :CASE 'DblClick' [1183] [1184] i1•warg [1185] (i=0)û0 ¦ click in blank row? [1186] p•wi '‘p' [1187] N2p[i;] ¦ name [1188] [1189] k•WCALL 'W_Edit' N [1190] [1191] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1192] [1193] :CASE 'MouseDouble' [1194] [1195] ¦ Second mouseup has not occurred yet, so we have to wait [1196] [1197] ¦ Pass mouse position before Windows does "word" select, which could change selection offset [1198] [1199] •wi 'Defer' 'CMDSEEKU ý1' 'KeyPress' (•wi 'selection') [1200] [1201] :CASE 'KeyPress' [1202] [1203] :if 'Listview'ð•wi 'class' [1204] [1205] i•first •wi 'value' [1206] (i=0)û0 ¦ click in blank row? [1207] p•wi '‘p' [1208] N2p[i;] ¦ name [1209] [1210] :else [1211] [1212] Assert 'RichEdit'ð•wi 'class' [1213] [1214] ¦ This could be from Enter key or from MouseDouble [1215] :if •wargð13 [1216] s•first •wi 'selection' [1217] :else [1218] Assert 2=û,•warg [1219] s•first •warg [1220] :end [1221] •wi 'selection' s 0 ¦ cancel word-selection [1222] ¦  Sadly, Windows may have changed the offset to the beginning of a "word" [1223] p':lv' •wi '‘p' ¦ name, hits, beginning of line, line numbers [1224] n1ûp [1225] (s=p[n;4])û0 ¦ beyond end? [1226] i+/sòp[;4] [1227] (c N k g n)p[i;] [1228] e1+•wi 'CharToLine' g ¦ divider line [1229] d1+•wi 'CharToLine' s ¦ clicked line [1230] :if e=d [1231] n0 [1232] :else [1233] id-e [1234] (i>ûn)û0 ¦ on Interrupt message [1235] ný1+n[i] ¦ ý1+ because we recorded line numbers in origin 1 [1236] :end [1237] NN,'[',(ôn),']' [1238] [1239] :end [1240] [1241] k•WCALL 'W_Edit' N [1242] [1243] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1244] [1245] :CASE 'Sort' [1246] [1247] i•warg [1248] •wself':lv' [1249] d•wi 'sortorder' [1250] pý1 0•wi '‘p' [1251] [1252] :if iî1 2 ¦ Class, Name [1253] wd[•AV[2]p[d;i]] ¦ new order [1254] :if dðw ¦ already sorted? [1255] wd[•AV[2]p[d;i]] [1256] :end [1257] :elseif i=3 ¦ Hits [1258] wd[p[d;i]] [1259] :if dðw [1260] wd[p[d;i]] [1261] :end [1262] :else [1263] ö'Tilt' [1264] :end [1265] [1266] •wi 'sortorder' w ¦ this triggers a Select [1267] [1268] i•first •wi 'value' [1269] •wi '‘skipnextselect' i [1270] [1271] :CASE 'Close' [1272] [1273] (•wi 'place') UcmdIni 'Seek-Place' [1274] (•wi 'visible') UcmdIni 'Seek-Visible' [1275] [1276] ¦•wi 'Delete' ¦ requires APL+Win version ò 6.2 [1277] [1278] '#' •wi 'Defer' "'fmSeek' •wi 'Delete'" ¦ works with APL+Win version < 6.2 [1279] [1280] :CASE 'redFind' [1281] [1282] •wself':red' [1283] s•first •wi 'selection' [1284] m•wi '‘m' ¦ offsets, lengths [1285] :if •warg=1 ¦ 1=next ý1=prev [1286] i(m[;1]>s)â1 [1287] :if i>1ûm  i1  :end [1288] :else [1289] iý1+(m[;1]< in stack [5] ¦ 17 Jul 2003 Fix for function shadowed by itself [6] [7] ¦ •SI entries: [8] ¦ • pending evaluated input request [9] ¦ õ pending execute request [10] ¦ ] pending user command [11] ¦ # debugger suspension [12] ¦ fnname[i] pendent function and line number [13] ¦ fnname[i]* suspended function and line number [14] ¦ <[object;action] object and action name from a callout in a form [15] ¦ >[object;event] object and event name for a callback in a form [16] [17] ¦ In olden time sharing days, you could get a lone '*' in the stack, I think [18] ¦ from erasing a suspended function, but that does not seem possible in APL+Win. [19] [20] ¦ •IDLOC has a column for each •SI level except those starting with 'õ•><' [21] ¦ Note that ']' *does* get a column in •IDLOC [22] ¦ I am not sure about '#' -- can't figure out how to test it [23] [24] s•SI ¦ real SI [25] fs[;1] ¦ first column [26] ufâ']' ¦ how much UCMD crap is there [27] uu*uóûf ¦ or 1 if no ] (non-UCMD) [28] (u=ûf)û0 ¦ quit if nothing in stack? [29] e~fî'õ•><' ¦ •SI rows that have matching •IDLOC columns [30] •ERROR((1++/e)†ý1û•IDLOC 'CMDSI')/'CMDSI ASSERTION ERROR' [31] p+\e ¦ map •SI rows to •IDLOC columns [32] e~fî'õ•><]#' ¦ •SI rows that have a function name [33] ñRESULT'' ¦ initialize result [34] :for i :in uâûf ¦ for each entry [35] rDTB s[i;] ¦ line of SI [36] :if e[i] ¦ else r is okay as is [37] n(^\r†'[')/r ¦ function name [38] d(<\ý1†,•IDLOC n)â1 ¦ find most-local definition [39] ¦:if d/t2/ ¦ Can use any of <ó=ò>†ú^åê&þ and ~ [24] ¦ ]superseek /t1/^~/t2/ú/t3/ ¦ Evaluated as APL would ("right to left") [25] [26] ¦ Defaults: [27] ¦ Perform case-sensitive, syntactic (name) search [28] ¦ Search all global functions and character items in variables FIXME [29] ¦ Search in all workspaces in all •LIBS libraries [30] ¦ Note that the active workspace is not searched -- only saved wss are searched [31] [32] ¦ Options: [33] ¦ To search only certain libraries: [34] ¦ 5 666 ¦ search just specified library numbers [35] ¦ * ¦ search entire current drive for *.W3 files, regardless of library numbers [36] ¦ To loosen match criteria: [37] ¦ ¦ Non-syntactic search (ANY occurrence) (Alt+S for non-Syntactic) [38] ¦ ï ¦ Ignore case (upper/lower/underscore) (Alt+C for Case) [39] ¦ To limit classes searched: [40] ¦ ì ¦ Find only in functions [41] ¦  ¦ Find only in variables [42] ¦ To limit search scope (using all three is equivalent to using none): [43] ¦ ¦ ¦ Find only in comments [44] ¦ ' ¦ Find only in character constants (or /") [45] ¦ à ¦ Find only in APL (not comments/quotes) [46] ¦ If you use these options, variables are not searched ??? FIXME [47] ¦ To expand search scope: [48] ¦ @ ¦ Find strings anywhere in a fn/var -- not necessarily on the same line. [49] ¦ Only useful with multiple targets. Doesn't change behavior of /t1/ú/t2/. [50] ¦ Display from /t1/^/t2/@ is similar to /t1/ú/t2/ but only shows fns/vars [51] ¦ that contain at least one hit on both strings. [52] ¦ To expand display: [53] ¦ + ¦ Show lines immediately before and after hits, for better context [54] [55] ¦ If you need to register this aplw.exe, execute [56] ¦ ]WSCOMP /RegServer [57] [58] ¦ To do: [59] ¦ - Handle Close via system menu during search (•WI OBJECT ERROR: Current object undefined) [60] ¦ - Directory scan should avoid Recyle Bin, System Volume Information, etc. [61] ¦ - Splitter? Especially with * option. [62] ¦ - Allow name filtering? [63] ¦ - What should Ctrl+C do in the Listview? What would be useful? [64] [65] ¦ 10 Dec 2007 Rex Swain, Independent Consultant, www.rexswain.com [66] ¦ 03 Mar 2008 Added )COPY feature [67] ¦ 23 Jul 2009 Preserve the File menu's MRU list [68] ¦ 06 Apr 2010 Fix stupid error that nullified syntactic filtering [69] ¦ 02 Jun 2010 Use UcmdIni and UcmdFont subroutines [70] ¦ 08 Sep 2010 Most recent minor fix [71] [72] (Aðý1)ûL9 ¦ callbacks [73] [74] v•AI[2] ¦ elapsed time [75] [76] Aô•ENLIST A ¦ arg might be numeric in development mode [77] [78] ADLTB A ¦ user command may pass in leading/trailing blanks [79] [80] :if Að'' [81] •'For help, see' [82] •' ]superseek ?' [83] 0 [84] :end [85] [86] XA ¦ save original arg [87] [88] ¦ Allow simple word search without delimiters [89] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [90] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [91] ¦ If the argument is 'foo /xx' then the blank should not be significant since [92] ¦ there was no leading delimiter. Is this a good idea? Technically the [93] ¦ blank should be significant. But this way is user-friendly. [94] :if 1=+/A='/' [95] Iý1+Aâ'/' [96] A(DTB IA),IA [97] :end [98] A'/',A [99] :end [100] [101] ¦ Parse targets and functions [102] [103] G0û '' ¦ targets [104] S0û '' ¦ functions [105] [106] :repeat [107] D1A ¦ delimiter [108] A1A [109] IAâD ¦ find second delimiter (might not be one) [110] :if I=1 [111] •'Empty target string is not a good idea' [112] 0 [113] :end [114] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [115] ADLB IA [116] P1A ¦ function or option [117] :if ~Pî'<ó=ò>†ú^åê&þ' [118] :leave [119] :end [120] P('^ú',P)['&þ'âP] [121] ADLB 1A [122] :if '~'=1A [123] PP,'~' [124] ADLB 1A [125] :end [126] S( P),S ¦ function [127] :if Að'' [128] •'Multiple target syntax error' [129] 0 [130] :end [131] :end [132] [133] FA ¦ options (old left argument) [134] [135] D•FIRST ûG ¦ number of targets [136] [137] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [138] [139] ¦ Define ìFILT for APL/quoted strings/comments: [140] [141] Z'à''¦'îF [142] Z[2]Z[2]ú'"'îF [143] Z2æZ [144] E~Zî0 8 ¦ not all or none: we need to filter [145] [146] :if E ¦ unless all or none [147] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [148] LL, "¦ Quotes and Comments" [149] LL, "¦ Right arg is a •VR" [150] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [151] LL, "¦ Extracted from Zark's ìParseVR" [152] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [153] LL, "¦ 26 Oct 2004 Include ¦õ" [154] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [155] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [156] LL, "•IO0 ¦ origin 0 is convenient" [157] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [158] LL, "xcx\n" [199] LL, "¦ Flag newline after each comment; then convert pairs to maps" [200] LL, "tnúc" [201] LL, "ut/c" [202] LL, "c†\x\t\uúý10,u" [203] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [204] ¦ 0=None and 7=All cases are excluded before we get here [205] P 'rc' ¦ 1 = ¦ [206] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [207] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [208] PP, 'rqåc' ¦ 4 = à = 'å¦ [209] PP, 'r~q' ¦ 5 = ঠ= ~' [210] PP, 'r~c' ¦ 6 = à' = ~¦ [211] LL,P[Z] [212] K•FX[2]L ¦õ QC [213] :end [214] [215] L 'RFILT' [216] LL, '¦ Raw hit filter' [217] LL, '¦ V=•VR, P=partition flags' [218] ¦LL, 'R~P ANDSCAN Vî"[1234567890]"' ¦ not line numbers [219] LL, 'RP ANDSCAN V†"]"' ¦ line numbers; allow for (2)[23;] too [220] ¦LL, 'RRåý1è1 0R' ¦ flag the ] too (we assume there is one!) [221] LL, 'RRåR<ý1èR' ¦ < is way faster than  [222] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [223] [224] K•FX[2]L ¦õ FILT ANDSCAN QC [225] [226] ¦ Define ìSYN for syntactic search [227] [228] Z''îF ¦ non-syntactic search? [229] [230] ¦ Token alphabet: chars that can be anywhere in a token [231] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [232] a'_' [233] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [234] aa,'abcdefghijklmnopqrstuvwxyzñ' [235] aa,'0123456789' [236] ¦ Token alphabet, including chars that can only begin a token [237] qa,'•ý' [238] [239] Q 'HA SYN H;B;I' [240] QQ, '¦ Syntactic hit filter' [241] QQ, '¦ Requires: V=•VR, a,q=alphabet' [242] QQ, 'IH/âûH' [243] ¦  Note that if target starts with • then we don't care what's to the [244] ¦ left of it, so ((1A)îa) is correct. [245] QQ, ':if (1A)îa' [246] QQ, ' H[(('' '',V)[I]îq)/I]0' [247] QQ, ':end' [248] QQ, ':if (ý1A)îq' [249] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [250] QQ, ':end' [251] :if Z=1 ¦ Neither? [252] Q1ûQ ¦ noop [253] :end [254] K•FX[2]Q ¦õ SYN a q [255] [256] ¦ Define ìUP for case-insensitive filter [257] [258] Z'ï'îF ¦ ignore case when finding target? [259] [260] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [261] ¦ Noop if no letters in targets [262] K•FX[2]'VUP V' '¦ noop' [263] :elseif Z [264] Q'ñabcdefghijklmnopqrstuvwxyz' [265] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [266] uc•AV [267] uc[ucâQ]L [268] K•FX[2]'VUP V' 'Vuc[•AVâV]' ¦õ UP uc ¦ this is faster than ñUCASE! [269] :else [270] mc'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [271] uc'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [272] Q 'VUP V;B;I;L;S' [273] QQ, '¦ Force APL+Win keyword names to upper case' [274] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [275] QQ, '¦ RHS 11/18/99' [276] QQ, '' [277] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [278] QQ, 'BVî''•'' ¦ find key symbols' [279] QQ, '(1îB)0 ¦ quit if none' [280] QQ, '' [281] QQ, 'LVîmc ¦ flag all letters (any case)' [282] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [283] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [284] QQ, '(1îB)0 ¦ quit if none' [285] QQ, '' [286] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [287] QQ, 'IS/B ¦ flag those which are candidates' [288] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [289] QQ, 'I†\I ¦ name mask' [290] QQ, 'II/âûI ¦ indices' [291] QQ, '' [292] QQ, 'V[I]uc[mcâV[I]] ¦ translate' [293] K•FX[2]Q [294] ¦ RHS 3/19/01 [295] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [296] ¦ when searching for 'fMain'. [297] ¦ List of keywords? No, could have ':end' •wi 'New' ... [298] ¦ I think we need to upper-case just the à part of the •vr [299] ¦ RHS 2/06/06 [300] ¦ I often search for •fappend or •io. [301] ¦ I cannot recall EVER having searched for :repeat. [302] ¦ So let's not worry about control structure keywords. [303] :end [304] [305] GUPG ¦ targets to uppercase [306] A1G ¦ last (and typically only) target string [307] [308] ¦ Options setup [309] [310] oE'*'îF ¦ entire drive? [311] oX'+'îF ¦ expanded context? [312] T'ì'îF ¦ just fns/vars? [313] oFTúå/T ¦ neither means both [314] [315] oG'@'îF ¦ global fn matching? [316] :if oG^D=1 [317] •'FYI, the @ option has no effect with just one target string' [318] oG0 [319] :end [320] [321] ¦ Strip symbol flags from options list [322] [323] ((Fî'à''¦ï~?@+ì*')/F)' ' ¦ note we do remove asterisk [324] FWords F [325] [326] ¦ Parse other options [327] [328] T( ,1)ð•VIF [329] :if oE ¦ entire drive [330] oL, ,'\' [331] :elseif 1îT ¦ explicitly specified [332] oL•ENLIST T/•FIF ¦ library numbers [333] :else [334] oL•FI,11[2]•LIBS ¦ RHS 1/27/04 if no libs are defined, 0 0ðû•LIBS [335] :end [336] [337] ¦ ----- Start user interface ----- [338] [339] w•FI UcmdIni 'Seek-Place' '2 5 25 90' [340] w[4]w[4]90 ¦ make sure wide enough for Status pane 4 [341] z•FI UcmdIni 'Seek-Visible' '1' [342] zz-z=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [343] [344] •wself'fmSuperSeek' •wi 'Create' 'Form' 'Hide' [345] •wi 'caption' 'SuperSeek' [346] •wi 'place' w [347] •wi 'visible' z [348] e'CMDSUPERSEEK ý1' [349] •wi 'onClose' e [350] •wi 'limitwhere' 10 40 [351] [352] •wself':bn' •wi 'Create' 'Button' 'Hide' [353] •wi 'style' 2 ¦ 2=cancel [354] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [355] [356] •wself':mFile' •wi 'Create' 'Menu' [357] •wi 'caption' '&File' [358] [359] •wself'.mExit' •wi 'Create' 'Menu' [360] •wi 'caption' 'E&xit' [361] •wi 'shortcut' 'X' 2 [362] •wi 'onClick' "0 0û':' •wi 'Close'" [363] [364] •wself':mEdit' •wi 'Create' 'Menu' [365] •wi 'caption' '&Edit' [366] [367] •wself'.mCopy' •wi 'Create' 'Menu' [368] •wi 'caption' '&Copy' [369] •wi 'shortcut' 'C' 2 [370] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Copy'" [371] [372] •wself'..mNext' •wi 'Create' 'Menu' [373] •wi 'caption' 'Find &next hit' [374] •wi 'shortcut' 114 0 ¦ 114=F3 [375] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'redFind' 1" [376] [377] •wself'..mPrev' •wi 'Create' 'Menu' [378] •wi 'caption' 'Find &previous hit' [379] •wi 'shortcut' 114 1 [380] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'redFind' ý1" [381] [382] •wself':mView' •wi 'Create' 'Menu' [383] •wi 'caption' '&View' [384] [385] •wself'.mLib' •wi 'Create' 'Menu' [386] •wi 'caption' 'Sort list by &Library Number' [387] •wi 'shortcut' 'L' 2 [388] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 2" [389] [390] •wself'..mWsid' •wi 'Create' 'Menu' [391] •wi 'caption' 'Sort list by &Workspace Name' [392] •wi 'shortcut' 'W' 2 [393] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 3" [394] [395] •wself'..mClass' •wi 'Create' 'Menu' [396] •wi 'caption' 'Sort list by Clas&s' [397] •wi 'shortcut' 'S' 2 [398] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 4" [399] [400] •wself'..mName' •wi 'Create' 'Menu' [401] •wi 'caption' 'Sort list by &Name' [402] •wi 'shortcut' 'N' 2 [403] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 5" [404] [405] •wself'..mHits' •wi 'Create' 'Menu' [406] •wi 'caption' 'Sort list by &Hits' [407] •wi 'shortcut' 'H' 2 [408] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 6" [409] [410] •wself'..mSep' •wi 'Create' 'Menu' [411] •wi 'separator' 1 [412] [413] •wself'..mVisible' •wi 'Create' 'Menu' [414] •wi 'caption' '&Visible list' [415] •wi 'style' 1 [416] •wi 'value' 1 [417] •wi 'shortcut' 'V' 2 [418] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Resize'" [419] [420] •wself':mActions' •wi 'Create' 'Menu' [421] •wi 'caption' '&Actions' [422] [423] •wself'.mCopy' •wi 'Create' 'Menu' [424] •wi 'caption' ')COPY selected Listview items into active ws' [425] ¦•wi 'shortcut' 'L' 2 [426] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'QuadCOPY'" [427] [428] •wself':st' •wi 'Create' 'Status' [429] •wi 'status' (1 4û1 '' 0 8) [430] [431] ¦ 4-col matrix [432] ¦ col 1: pane number, negative if an overlay pane [433] ¦ cols 2,3: 1 text show that text [434] ¦ 0 text don't show, but use width of text [435] ¦ text 33 show text; 33 is mimimum width (more if reqd) [436] ¦ text text2 ditto; use width of text2 as minimum [437] ¦ col 4: border: 0=no 1=inset 2=outset 8=expand 16=caps 32=num 64=scr [438] t0 4û [439] ttž 1 0 ' Searching 99999 workspaces... ' 1 [440] ttž 2 0 ' 999999999 XXXXXXXX ' 1 [441] ¦ttž 3 0 ' 99999 functions, 99999 variables ' 1 [442] ttž 3 0 ' 9999 hits on 9999 lines in 9999 fns/vars ' 1 [443] ttž 4 '' 25 1 ¦ progress bar [444] •wi 'status' t [445] [446] z,•wi 'PaneWhere' 4 [447] [448] •wself'.pb' •wi 'Create' 'Progress' ¦ note child of Status [449] •wi 'style' 1 ¦ 1=smooth [450] :if ~ý1îz ¦ RHS 9/08/10 z is 4ûý1 if no room for pane (long wsid) [451] •wi 'where' z [452] :end [453] [454] •wself':bn' •wi 'Create' 'Button' 'Hide' [455] •wi 'style' 2 ¦ 2=cancel [456] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [457] [458] z':' •wi 'size' [459] [460] •wself':lv' •wi 'Create' 'Listview' [461] •wi 'style' 1 2 4 4096 ¦ 8=no multiple selections 128=no header 4096=grid [462] •wi 'where' (0,0,z[1],50) ¦ wide enough so no horiz scroll bar, else 'size' misleading [463] [464] •wi 'scale' 3 ¦ font size will be specified in points [465] •wi 'font' (UcmdFont '5') [466] •wi 'scale' 1 [467] [468] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [469] [470] c0 3û0 [471] ccž'Fake' 0 'left' ¦ first col must be left justified [472] :if oE [473] ccž'Dir' 14 'left' [474] :else [475] ccž'Lib' 4 'right' [476] :end [477] ccž'Wsid' 10 'left' [478] ccž'C' 2 'left' [479] ccž'Name' 12 'left' [480] ccž'H' 3 'right' ¦ Hits [481] ccž'Fake' 0 'right' ¦ because of behavior of 'AutoFit' 'header' 'all' [482] [483] •wi 'list' (0,1,100 1û'x') ¦ force vertical scrollbar [484] [485] •wi 'columndisplay' c [486] [487] d•wi 'size' [488] d[2]+/c[;2] ¦ inner width [489] •wi 'size' d [490] [491] w4•wi 'where' ¦ outer width [492] [493] •wi 'list' (0 3û0 1 '') ¦ remove fake rows that forced vertical scrollbar [494] [495] •wself':red' •wi 'Create' 'RichEdit' [496] •wi 'style' 4 16 64 4096 16384 32768 ¦ 4=multi-line 16=V SB 64=H SB 2048=APL 4096=read-only [497] ¦ 16384 else entire text selected when you select the Form [498] ¦ 32768 disable automatic word selection when highlighting with mouse [499] [500] •wi 'where' (0,w,z[1],z[2]-w) [501] [502] HW•wi 'hwnd' [503] [504] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [505] •wi 'selection' 0 ý1 ¦ select all [506] •wi 'scale' 3 ¦ points [507] •wi 'selfont' (UcmdFont 'U') [508] [509] ¦  Necessary because default is bold (huh?) [510] •wi 'selstyle' (0 0 0 0 0) ¦ bold, italic, underline, strikeout, protected [511] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection [512] [513] A1•AV[•IO+65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 48 49 50 51 52 53 54 55 56 57 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96 123 125 2 16 17 18 20 21 128 129 130 131 132 133 135 136 137 138 139 140 142 144 147 148 150 153 154 155 156 157 160 161 162 163 164 165 168 170 171 172 173 174 175 192 193 194 195 197 198 200 202 203 204 205 206 207 210 211 212 213 216 217 218 219 221 223 225 228 4 5 6 11 14 24 25 26 28 29 124 126 134 145 146 230 231 233 236 238 239 240 242 243 246 248 249 250 252 253 254 3 15 19 22 23 30 31 141 143 149 151 152 158 159 166 167 169 224 226 227 229 232 234 235 237 241 244 245 251 13 ] ¦ removed 0 7 8 9 10 12 27 127 [514] A2 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 48 49 50 51 52 53 54 55 56 57 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96 123 125 8364 229 230 236 249 242 199 252 233 226 228 224 231 234 235 232 239 238 196 201 244 246 251 214 220 162 163 165 225 237 243 250 241 209 191 245 248 253 161 171 187 192 193 194 195 197 198 200 202 203 204 205 206 207 210 211 212 213 216 217 218 219 221 255 223 227 8900 168 8592 8834 8835 8593 8595 8594 8867 8866 166 8764 8800 8710 215 8869 8868 8854 8711 8714 8745 8801 8805 8804 247 8728 9675 8744 8746 175 8739 9079 9055 9067 9068 9077 9035 9042 8968 8970 9109 9054 9017 9066 9064 9053 9024 9015 9082 9075 9060 9073 9021 9074 9023 9033 9049 9045 9038 9076 13 183 [515] ¦ 183=U00B7 : Middle dot, for untranslatable chars [516] [517] ¦ Streamlined version of ìAV2U [518] t 'UAU A;N' [519] tt, 'UA2[A1âA]' [520] tt, ':if 82†•DR A' [521] tt, ' N,0=•TYPE A' [522] tt, ' (N/,U)N/,A' [523] tt, ':end' [524] tt, 'U•FIRST 323 163 82 •DR U' [525] k•fx [2] t ¦õ AU A1 A2 [526] [527] ¦ Streamlined version of ìSetSelTextU [528] k•fx [2] 'ST A;K;U' 'UAU A' "K•wcall 'EM_SetTextEx' HW ('ST_SELECTION' 1200) (U,2û•tcnul)" ¦õ ST AU HW [529] [530] t' ]SuperSeek ',X [531] [532] ¦ tt,•tcnl,50û9472 ¦ U2500 : Unicode horizontal line [533] ¦ tt,•tcnl,'Test difficult characters:' [534] ¦ tt,•tcnl,'Execute õ' [535] ¦ tt,•tcnl,' Match ð' [536] ¦ tt,•tcnl,' Zilde ' [537] ¦ tt,•tcnl,' Domino ˜' [538] [539] tt,•tcnl [540] ST t [541] [542] •wi 'selection' (0,ý1+ût) ¦ offset, length [543] •wi 'selcolor' (0 196 0) [544] •wi 'selstyle' (1 0 0 0 0) ¦ bold [545] •wi 'selection' ý1 ¦ select none; cursor to end [546] [547] ¦ Pre-build a CHARFORMAT2 structure that sets background color [548] CF8484 ¦ cbSize [549] CF[8]4 ¦ dwMask CFM_BACKCOLOR [550] CF[65 66 67]255 255 0 ¦ yellow [551] CFAV CF [552] [553] •wself':' [554] [555] •wi 'Show' [556] e'CMDSUPERSEEK ý1' [557] •wi 'onResize' e [558] •wi 'onClose' e [559] [560] ':lv' •wi 'Focus' ¦ necessary to make Esc work during search (why?) [561] [562] ¦ ----- Before starting, remember MRU list ----- [563] [564] n•first •fi •wcall 'W_Ini' '[Session] MRU WSS LIST' [565] tnû '' [566] :for i :in ân [567] t[i] •wcall 'W_Ini' ('[Session] Open',ôi) [568] :end [569] 'fmSuperSeek' •wi '‘mru' t ¦ save for 'Close' [570] [571] ¦ ----- Go ----- [572] [573] X0 ¦ count hits [574] E0 ¦ count lines with hits [575] U0 ¦ count functions with hits [576] p0 5û' ' '' 0 0  ¦ class, name, # hits, pointer to fn in RichEdit, line numbers with hits [577] m0 2û ¦ all hits (start, length) in RichEdit [578] [579] •wself':red' [580] [581] ¦ ----- Loop through libraries to find wss ----- [582] [583] Q0û '' ¦ queue of wss to search [584] [585] :if oE ¦ entire drive? [586] [587] ':st' •wi 'SetStatus' 1 (' Scanning for workspaces ... ') [588] [589] W•LIB 1oL [590] W(Wú.='\')ëW ¦ only subdirectories [591] n•first ûW ¦ how many top level dirs [592] [593] ':st.pb' •wi 'value' 0 n 1 0 ¦ wraps around [594] [595] :while ’ûoL [596] [597] L1oL ¦ next directory [598] oL1oL [599] [600] :if 2=+/L='\' ¦ top level dirs [601] ':st' •wi 'SetStatus' 2 (' ',ý1L) [602] ':st.pb' •wi 'Stepit' [603] :end [604] [605] •wgive 0 [606] [607] :if ':' •wi '‘stop' [608] :leave [609] :end [610] [611] WDMIFERR '•WSLIB L' ¦õ •WSLIB L ¦ try to get workspace names [612] :if 1=ûûW ¦ error if no such lib [613] •'*** ',W,': •WSLIB ',L [614] :continue [615] :end [616] [617] W(~ú/'.BAK 'W,' ')ëW ¦ don't search backup wss [618] [619] QQ,( L),DTB [2]W [620] [621] WDMIFERR '•LIB L' [622] :if 1=ûûW ¦ error? [623] •'*** ',W,': •LIB ',L [624] :continue [625] :end [626] W(Wú.='\')ëW ¦ only subdirectories [627] W( L),DTB [2]W ¦ append to directory [628] oLW,oL ¦ add to front of queue [629] [630] :end [631] [632] :else ¦ normal library scan [633] [634] :for L :in oL ¦ next library [635] [636] •wgive 0 [637] [638] :if ':' •wi '‘stop' [639] :leave [640] :end [641] [642] WDMIFERR '•WSLIB L' ¦õ •WSLIB L ¦ try to get workspace names [643] :if 1=ûûW ¦ error if no such lib [644] •'*** ',W,': ',ôL [645] :continue [646] :end [647] [648] W(~ú/'.BAK 'W,' ')ëW ¦ don't search backup wss [649] [650] QQ,DLTB [2]W [651] [652] :end [653] [654] :end [655] [656] n•first ûQ [657] ':st' •wi 'SetStatus' 1 (' Searching ',(ôn),' workspaces... ') [658] [659] ':st.pb' •wi 'value' 0 (1n) 1 0 ¦ 1 to avoid •WI DOMAIN ERROR when N=0 [660] [661] ¦ ----- Start server ----- [662] [663] wse'wseSuperSeek' •wi 'Create' 'APLW.WSEngine' ('xVisible' 0) [664] kwse •wi 'XExec' ("•CHDIR '",(•chdir ''),"'") [665] [666] ¦ ----- Loop through wss ----- [667] [668] nW0 ¦ wss searched [669] fW0 ¦ found in wss [670] [671] :FOR WS :in Q [672] [673] ¦ In case of INTERNAL WS REPRESENTATION IS NEWER THAN THIS INTERP warning, show this now [674] ':st' •wi 'SetStatus' 2 WS [675] ':st' •wi 'SetStatus' 3 '' [676] [677] •wgive 0 [678] [679] :if ':' •wi '‘stop' ¦ FIXME check this at every fn/var? [680] s1•wi 'selection' [681] t'Interrupt',•tcnl [682] ST t [683] •wi 'selection' (s,ût) ¦ offset, length [684] •wi 'selcolor' (255 0 0) [685] •wi 'selstyle' (1 0 0 0 0) ¦ bold [686] •wi 'selection' ý1 ¦ select none; cursor to end [687] :leave [688] :end [689] [690] uf1 ¦ show file name heading on first hit [691] [692] :if oE [693] i(è<\èWS='\')â1 [694] :else [695] iWSâ' ' [696] :end [697] ln(i-1)ûWS ¦ library number [698] wsiWS ¦ wsid [699] [700] kwse •wi 'XExec' ')CLEAR' [701] kwse •wi 'XExec' (')XLOAD ',WS) [702] kwse •wi 'XExec' ')RESET' [703] rwse •wi 'XExec' '•WSID' [704] :if rð'' ¦ in a clear ws, •WSIDð'' [705] ¦ RUNTIME WS SERIALIZATION MISMATCH ? [706] •'*** Failed: )XLOAD ',WS [707] :continue [708] :end [709] wDEB r ¦ APL's way of saying wsid [710] [711] Mwse •wi 'XExec' '•NL 2 3' ¦! a character matrix comes back as a nested vector!!! [712] Assert 1=ûûM [713] MM~' ' ¦ DTB [714] Cwse •wi 'XExec' '•NC •NL 2 3' ¦ 2=var 3=fn [715] Assert 1=ûûC [716] Assert ^/Cî2 3 ¦ since we cleared stack, cannot be labels [717] [718] MM,'•ALX' '•ELX' '•LX' ¦ interesting system vars [719] CC, 2 2 2 [720] [721] C':ì'[C] [722] [723] bCîoF/'ì' ¦ fns/vars filter [724] Cb/C [725] Mb/M [726] [727] ':st' •wi 'SetStatus' 3 (' ',(ô+/C='ì'),' functions, ',(ô+/C=''),' variables ') [728] [729] ¦ ----- Loop through fns/vars ----- [730] [731] :for i :in âûM [732] [733] NiM ¦ object name [734] [735] y'ì'=iC ¦ is it a function? ¦ note •NC says 4 for •LX, but we ony test 3= [736] :if y [737] Vwse •wi 'XExec' ("•VR '",N,"'") [738] :if 0=ûV ¦ locked or •NA ? [739] :continue [740] :end [741] V[1 2]'[]' ¦ kludge for FILT [742] :else [743] :try [744] V'unwrapl' •DR wse •wi 'XExec' ("'wrapl' •DR ",N) [745] :catchall [746] ¦ FANFILE ws has screwed up variable A with 0=ûûA but ðûA which makes unwrapl fail [747] •'*** ',((^\•DM†•TCNL)/•DM),' retrieving variable <',N,'> from ws ',WS [748] :continue [749] :end [750] ¦ RHS 3/03/07 Let's try this, for speed [751] :if 82†•DR V [752] :continue [753] :end [754] VSEEKFMT V [755] :if 0=ûV [756] :continue [757] :end [758] :end [759] [760] LUP V [761] [762] ¦ Search •VR [763] [764] HL •SS A ¦ the heart of the matter [765] [766] :if D=1 ¦ single target? [767] :andif ~1îH ¦ no raw hits? [768] :continue ¦ next function [769] :end [770] [771] ¦ Syntactic filter [772] [773] HA SYN H ¦õ V a q [774] [775] :if D=1 ¦ single target? [776] :andif ~1îH ¦ no more hits? [777] :continue ¦ next function [778] :end [779] [780] ¦ Filter for APL / quoted strings / comments [781] [782] ¦P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [783] ¦  This doesn't work with my variable formatting stuff, like '(2)[13;] ...' [784] ¦ And besides, you're not allowed to have CRs embedded in functions any more [785] P1,ý1V •SS •TCNL ¦ partition on "[" (with trailing CRs); force header line [786] ¦ •SS is still faster than plain = ! [787] ¦P[ý5+ûV]1 ¦ force end of last line [788] ¦ The last 7 characters of a •VR are: •TCNL,' ì',•TCNL [789] ¦ P[ý5+ûV]1 above flags ....................  this blank [790] ¦ No, now that's not necessary at all, now that we match •TCNL rather than •TCNL,'[' [791] [792] IFILT ¦õ P V ANDSCAN [793] HH^I [794] [795] :if D=1 ¦ single target? [796] :andif ~1îH ¦ no more hits? [797] :continue ¦ next function [798] :end [799] [800] R(ûV)û0 [801] R[(H/âûH)ø.+ý1+âûA]1 ¦ flag chars to highlight [802] [803] hP ORRED H ¦ shift hits to leading "[" [804] [805] :if D>1 ¦ multiple targets [806] [807] ¦ We have already done the last target; now step through the others [808] ¦ Note that they are in reverse order so functions work like APL [809] [810] ¦ /t1/ú/t2/ don't stop and display after first hit -- we want to show them all [811] ¦ /t1/&~/t2/ it is okay to show "all" hits since we will exclude lines with t2 [812] [813] :if oG ¦ "@" global option? [814] tú/h [815] :for J :in 1âD [816] WL •SS JG ¦ raw search [817] W(JG) SYN W ¦ SYN [818] WW^I ¦ FILT [819] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [820] HHúW ¦ all hits [821] WP ORRED W ¦ shift hits to leading "[" [822] hWúh ¦ lines to show [823] tõ'(ú/W)',(JS),'t' ¦ apply function [824] :end [825] :if ~t ¦ no hits? [826] :continue ¦ next function [827] :end [828] :else [829] :for J :in 1âD [830] WL •SS JG ¦ raw search [831] W(JG) SYN W ¦ SYN [832] WW^I ¦ FILT [833] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [834] HHúW ¦ all hits [835] WP ORRED W ¦ shift hits to leading "[" [836] hõ'W',(JS),'h' ¦ apply function [837] :end [838] :if ~1îh ¦ no more hits? [839] :continue ¦ next function [840] :end [841] :end [842] [843] ¦ Only count hits on lines that will be displayed [844] ¦ (When searching for /1/^/2/ don't count 2s on lines without 1) [845] [846] Hh/P PLUSRED H [847] [848] :end [849] [850] ¦ Got some hits [851] [852] :if uf [853] fWfW+1 ¦ found in wss [854] uf0 [855] e9552 ¦ 9552=U2550 : Double horizontal line [856] t(5ûe),' WSID: ',WS,' ' [857] tt,((570-ût)ûe),•tcnl [858] ST t [859] [860] n•first ût ¦ length of line [861] s1•wi 'selection' [862] ss-n ¦ back up to beginning of line [863] •wi 'selection' s (n-1) ¦ offset, length [864] [865] ¦ Mark thinks this is too colorful [866] jCF [867] j[65 66 67]AV 196 255 255 ¦ pale cyan [868] k•wcall 'EM_SETCHARFORMAT' HW 1 j ¦ SCF_SELECTION=1 ¦ background [869] [870] •wi 'selection' ((s+12),ûWS) ¦ just the file name [871] •wi 'selstyle' (1 0 0 0 0) ¦ bold [872] [873] •wi 'selection' ý1 ¦ select none; cursor to end [874] :end [875] [876] [877] x+/H ¦ total hits in this fn [878] t':lv' •wi 'AddRows' 0 1 '' ln ws (,'ì'[1+y]) N (ôx) WS [879] k':lv' •wi 'EnsureVisible' t [880] [881] XX+x ¦ accumulate total hits [882] Hh ¦ lines with hits [883] EE++/H ¦ accumulate lines with hits [884] UU+1 ¦ accumulate functions with hits [885] [886] ¦ Display hits [887] [888] HH/âûH ¦ line numbers to display (origin 1) [889] WûH ¦ number of lines with hits [890] PP/âûP ¦ partition starts [891] L(1P,1+ûV)-P ¦ partition lengths [892] :if oX ¦ expanded context? [893] :if y [894] eâûP ¦ all line numbers (including the trailing ì line) [895] :else [896] eâý1+ûP ¦ all line numbers (the last line of variables is bogus) [897] :end [898] H(eîHø.+ý1 0 1)/e ¦ this takes care of dups and edges [899] IH>1+ý1èH ¦ flag beginnings of groups of lines [900] :else [901] I(ûH)û0 [902] :end [903] PP[H]-1 ¦ compensate for +â with •IO1 [904] LL[H] ¦ lengths, incl trailing CRs [905] [906] ppž ('ì'[1+y]) N x (1•wi 'selection') H ¦ class name #hits position lines [907] [908] e5û9472 ¦ 9472=U2500 : Horizontal line [909] ¦  5 positions the fn name where it is in the header line (of a niladic fn) [910] te,' ',N,' (',(ôx),' hit',(x=1)'s',((x†W)/' on ',(ôW),(-W=1)' lines'),') ' [911] tt,((70-ût)ûe),•tcnl [912] ST t [913] n•first ût ¦ length of line [914] s1•wi 'selection' [915] ss-n ¦ back up to beginning of line [916] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [917] •wi 'selection' s (n-1) ¦ offset, length [918] :if y [919] V[1 2]' ' ¦ undo kludge for FILT [920] •wi 'selcolor' (0 0 255) ¦ blue fns [921] :else [922] •wi 'selcolor' (255 0 255) ¦ purple vars [923] :end [924] •wi 'selection' (6+s) (•first ûN) ¦ just the function name [925] •wi 'selstyle' (1 0 0 0 0) ¦ bold [926] •wi 'selection' ý1 ¦ select none; cursor to end [927] •wi 'Paint' ¦ show bolded fn name while hits display [928] [929] :for B :in âûH [930] :if I[B] [931] ST (3û183),•TCNL ¦ 183=U00B7 : Middle dot [932] :end [933] nL[B] [934] jP[B]+ân ¦ indices of line in •VR [935] ST V[j] [936] s(1•wi 'selection')-n+1 [937] c(R[j]) Partition ân ¦ groups of chars to highlight [938] :for j :in c [939] e(s+1j),ûj ¦ offset, length [940] mmže ¦ all hits [941] •wi 'selection' e ¦ offset, length [942] ¦•wi 'selcolor' (255 0 255) ¦ purple [943] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [944] k•wcall 'EM_SETCHARFORMAT' HW 1 CF ¦ SCF_SELECTION=1 ¦ yellow background [945] :end [946] •wi 'selection' ý1 ¦ select none; cursor to end [947] :end [948] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection ¦ else :red does not scroll down [949] •WGIVE 0 ¦ listview does not display without this [950] ¦k•dl 0.1 [951] [952] :end ¦ next function [953] [954] ':st.pb' •wi 'Stepit' [955] [956] nWnW+1 ¦ wss searched [957] [958] :END ¦ next ws [959] [960] ':st' •wi 'SetStatus' 1 (' Searched ',(ônW),' workspaces ') [961] ':st' •wi 'SetStatus' 2 (' Found in ',(ôfW),' wss ') [962] [963] ':bn' •wi 'onClick' '' ¦ let style 2 take over [964] [965] :if U=0 [966] [967] s1•wi 'selection' [968] [969] t'Not found',•tcnl [970] ST t [971] [972] •wi 'selection' (s,ý1+ût) ¦ offset, length [973] •wi 'selcolor' (255 0 0) [974] •wi 'selstyle' (1 0 0 0 0) ¦ bold [975] •wi 'selection' 0 0 ¦ cursor to top [976] [977] L1 [978] [979] :end [980] [981] ppž ' ' '' 0 (1•wi 'selection')  ¦ fake row so we know position of end of text [982] [983] •wi 'selection' 0 0 ¦ cursor to top [984] [985] •wself':lv' [986] [987] •wi 'noredraw' 1 [988] [989] •wi 'AutoFit' 'header' (2 3 4 5 6) [990] [991] c•wi 'columndisplay' [992] cý1 0c ¦ delete Fake column [993] •wi 'columndisplay' c [994] [995] •wi 'highlightfocus' 1 [996] •wi 'value' 1 [997] k•wi 'EnsureVisible' 1 [998] [999] s•wi 'size' [1000] s[2]+/c[;2] ¦ inner width [1001] •wi 'size' s [1002] [1003] w•wi 'where' [1004] z':' •wi 'size' [1005] w[3]z[1] ¦ outer height [1006] •wi 'where' w [1007] [1008] •wi 'noredraw' 0 [1009] [1010] d':red' •wi 'where' [1011] d[2]w[4] [1012] d[4]z[2]-w[4] [1013] ':red' •wi 'where' d [1014] [1015] •wi 'Focus' [1016] [1017] •wi '‘p' p [1018] [1019] e'CMDSUPERSEEK ý1' [1020] [1021] ¦  Sadly, when you click a different row in the list, both these events fire [1022] •wi 'onClick' e [1023] •wi 'onSelect' e [1024] [1025] •wi 'onColClick' e [1026] [1027] •wi 'keys' 13 ¦ 13=Enter [1028] •wi 'onKeyPress' e [1029] •wi 'onDblClick' e [1030] [1031] •wself':red' [1032] [1033] •wi '‘m' m [1034] [1035] •wi 'keys' 13 ¦ 13=Enter [1036] •wi 'onKeyPress' e [1037] •wi 'onMouseDouble' e ¦ sadly, there is no onDblClick [1038] [1039] L1: [1040] [1041] •wself':st' [1042] [1043] '.pb' •wi 'Delete' [1044] [1045] t(2æoF)'variables' 'functions' 'fns/vars' [1046] t' ',(ôX),' hits on ',(ôE),' lines in ',(ôU),' ',t,' ' [1047] •wi 'SetStatus' 3 t [1048] [1049] v•ai[2]-v [1050] t(0 1ôv),' seconds elapsed' ¦ note free leading blank [1051] •wi 'SetStatus' 4 t [1052] [1053] •wself':' [1054] [1055] k•wi 'Wait' [1056] [1057] 0 [1058] [1059] ¦ ============================================================================= [1060] [1061] L9: [1062] [1063] ¦ ••wself •wevent •warg '(' ('#' •wi 'focus') ')' ¦ debug [1064] [1065] :SELECT •wevent [1066] [1067] :CASELIST 'Click' 'Select' [1068] [1069] ¦ If you click on a new row, you get Click,Select [1070] ¦ If you click on the same row, you get just Click [1071] ¦ If you use keyboard, you get just Select [1072] [1073] i•first •wi 'value' [1074] (i=0)û0 ¦ click in blank row? [1075] [1076] :if •weventð'Click' [1077] •wi '‘skipnextselect' i [1078] :else [1079] Assert •weventð'Select' [1080] :if i=•wi '‘skipnextselect' [1081] •wi '‘skipnextselect' 0 [1082] 0 [1083] :end [1084] :end [1085] [1086] p•wi '‘p' [1087] (c N k s k)p[i;] ¦ class, name, hits, beginning of line, line numbers [1088] ss+6 ¦ advance past '----- ' [1089] n•first ûN [1090] [1091] •wself':red' [1092] [1093] •wi 'selection' s n [1094] [1095] ¦ Scroll into view on RichEdit control [1096] [1097] e1+•wi 'CharToLine' s ¦ line number of first line [1098] t1+•wi 'CharToLine' (p[i+1;4]-1) ¦ line number of last line [1099] g•wi 'range' [1100] g(g[1]-1)+âg[2] ¦ lines now visible [1101] :if 0î(e,t)îg ¦ if the whole fn is already visible, don't change range [1102] •wi 'range' e [1103] :end [1104] [1105] :CASE 'DblClick' [1106] [1107] i1•warg [1108] (i=0)û0 ¦ click in blank row? [1109] •wi 'Event' 'CMDSUPERSEEK ý1' 'Peek' i [1110] [1111] :CASE 'MouseDouble' [1112] [1113] ¦ Second mouseup has not occurred yet, so we have to wait [1114] [1115] ¦ Pass mouse position before Windows does "word" select, which could change selection offset [1116] [1117] •wi 'Defer' 'CMDSUPERSEEK ý1' 'KeyPress' (•wi 'selection') [1118] [1119] :CASE 'KeyPress' [1120] [1121] ¦ note, for both classes: •wi 'keys' 13 ¦ 13=Enter [1122] [1123] :if 'Listview'ð•wi 'class' [1124] [1125] i•first •wi 'value' [1126] (i=0)û0 ¦ click in blank row? [1127] •wi 'Event' 'CMDSUPERSEEK ý1' 'Peek' i [1128] [1129] :else [1130] [1131] Assert 'RichEdit'ð•wi 'class' [1132] [1133] ¦ This could be from Enter key or from MouseDouble [1134] :if •wargð13 [1135] s•first •wi 'selection' [1136] :else [1137] Assert 2=û,•warg [1138] s•first •warg [1139] :end [1140] •wi 'selection' s 0 ¦ cancel word-selection [1141] ¦  Sadly, Windows may have changed the offset to the beginning of a "word" [1142] p':lv' •wi '‘p' ¦ name, hits, beginning of line, line numbers [1143] n1ûp [1144] (s=p[n;4])û0 ¦ beyond end? [1145] i+/sòp[;4] [1146] (c N k g n)p[i;] [1147] e1+•wi 'CharToLine' g ¦ divider line [1148] d1+•wi 'CharToLine' s ¦ clicked line [1149] :if e=d [1150] j0 [1151] :else [1152] jd-e [1153] (j>ûn)û0 ¦ on Interrupt message [1154] jý1+n[j] ¦ ý1+ because we recorded line numbers in origin 1 [1155] :end [1156] [1157] •wi 'Event' 'CMDSUPERSEEK ý1' 'Peek' (i j) [1158] [1159] :end [1160] [1161] :CASE 'Peek' [1162] [1163] ¦ caller does: •wi 'Event' 'CMDSUPERSEEK ý1' 'Peek' (i j) [1164] [1165] (i j)2•warg ¦ listview rowid, function line number [1166] [1167] (C N WS),':lv' •wi 'GetCells' i (4 5 7) ¦ class, name, full wsid [1168] [1169] •wself'wseSuperSeek' [1170] [1171] k•wi 'XExec' (')XLOAD ',WS) [1172] k•wi 'XExec' ')RESET' [1173] r•wi 'XExec' '•WSID' [1174] Assert ~rð'' ¦ in a clear ws, •WSIDð'' ¦ this )XLOAD worked once before, so it should work again... [1175] [1176] :if C='ì' ¦ function? [1177] x•wi 'XExec' ("•VR '",N,"'") [1178] Assert 0†ûx ¦ should not be locked or •NA else how did it get in list? [1179] :else [1180] x'unwrapl' •DR •wi 'XExec' ("'wrapl' •DR ",N) [1181] :end [1182] [1183] EN,(j†0)/'[',(ôj),']' [1184] [1185] :if C='' ¦ variable [1186] :if (ðx)>1 [1187] :orif (ûûx)>2 [1188] :orif ^/0 ' 'î•TYPE •enlist x [1189] x•UCMD 'DISPLAY x' ¦ I guess this is better than an error from )edit [1190] :end [1191] k "p ",N ¦! we cannot peek at anything named p [1192] kk, "k•WCALL 'W_Edit' (,'",E,"')" ¦õ k ¦ W_Edit fails if arg is scalar [1193] k•DEF [2] k ¦õ p [1194] p x [1195] :else [1196] k "p x;",N ¦! we cannot peek at anything named p or x or k [1197] kk, "k•DEF x" ¦õ k x [1198] kk, "k•WCALL 'W_Edit' (,'",E,"')" ¦õ k ¦ W_Edit fails if arg is scalar [1199] k•DEF [2] k ¦õ p [1200] p x [1201] :end [1202] [1203] :CASE 'QuadCOPY' [1204] [1205] •wself':lv' [1206] v•wi 'value' ¦ selected rowids [1207] Assert ’ûv [1208] Assert ~0îv [1209] M•wi 'GetCells' v (5 7) ¦ name, full wsid [1210] mM[;1] [1211] dý1ú.†ý1[2] •idloc [2] m ¦ shadowed? [1212] :if ú/d [1213] •'*** Shadowed:',ôd/m [1214] M(~d)ëM [1215] :end [1216] ¦ Should group by wsid, but it's easier to just do one at at time... [1217] :for i :in â1ûM [1218] (m w)M[i;] [1219] •' )COPY ',w,' ',m [1220] rm •COPY w [1221] Assert (,1)ðûr [1222] :select •first r [1223] :case 1  •'Function copied' [1224] :case 2  •'Variable copied' [1225] :case 0  •'*** •COPY failed: Object not found' [1226] :case 127  •'*** •COPY failed: Duplicate name in objlist ¦ should not get here!' [1227] :case ý2  •'*** •COPY failed: Object too large for available space' [1228] :case ý3  •'*** •COPY failed: Name defined as a label; cannot be changed' [1229] :case ý4  •'*** •COPY failed: Insufficient space in symbol table and workspace too full to expand symbol table' [1230] :case ý6  •'*** •COPY failed: Insufficient free space to carry out command' [1231] :else  ö0 [1232] :end [1233] :end [1234] [1235] :CASE 'ColClick' [1236] [1237] c1•warg [1238] •wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' c [1239] [1240] :CASE 'Sort' [1241] [1242] c•warg [1243] •wself':lv' [1244] d•wi 'sortorder' [1245] p,•wi 'GetCells' d c [1246] [1247] :if cî3 4 5 ¦ Wsid, Class, Name [1248] p[2]p [1249] wd[•AVp] ¦ new order [1250] :if dðw ¦ already sorted? [1251] wd[•AVp] [1252] :end [1253] :elseif cî2 6 ¦ Lib, Hits [1254] p•FIôp [1255] wd[p] [1256] :if dðw [1257] wd[p] [1258] :end [1259] :else [1260] ö'Tilt' [1261] :end [1262] [1263] •wi 'sortorder' w ¦ this triggers a Select [1264] [1265] i•first •wi 'value' [1266] •wi '‘skipnextselect' i [1267] [1268] :CASE 'redFind' [1269] [1270] •wself':red' [1271] s•first •wi 'selection' [1272] m•wi '‘m' ¦ offsets, lengths [1273] :if •warg=1 ¦ 1=next ý1=prev [1274] i(m[;1]>s)â1 [1275] :if i>1ûm  i1  :end [1276] :else [1277] iý1+(m[;1]m[;12 13 14]^.=d [143] :end [144] :end [145] LLb/LL [146] :end [147] :end [148] [149] DD0û '' ¦ default: no directories [150] [151] :if ’ûD [152] DD(D†';') Partition D ¦ \foo;\windows\system [153] LL(’û,L)/LL ¦ keep library numbers only if explicity specified [154] DDDLTBDD ¦ no leading or trailing blanks [155] b(•enlist ý1DD)î'\:' ¦ which paths have trailing backslash or colon [156] DDDD,b'\' ¦ force trailing backslashes [157] :end [158] [159] :if A ¦ /* [160] LL ¦ forget about library numbers [161] DD, ,'\' ¦ from root [162] S1 ¦ recurse [163] :end [164] [165] N(^\N†'/')/N ¦ delete all options [166] [167] cDEB N ¦ for form caption [168] ((c='‘')/c)'+' [169] ((c='ñ')/c)•AV[249+•IO] ¦ that yields the plus-or-minus symbol [170] [171] :if CúX ¦ case sensitive? [172] k•DEF[2]'RUp A' 'RA' ¦õ Up [173] :else [174] LC'abcdefghijklmnopqrstuvwxyzñ',•AV [175] UC'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘',•AV [176] k•DEF[2]'RUp A' 'RUC[LCâA]' [177] NUp N [178] :end [179] [180] :if X ¦ exact name mode? [181] NN~' ' ¦ delete all blanks [182] N(N†';') Partition N ¦ 'foo;goo'  'foo' 'goo' [183] N' ',N,' ' ¦ pad on both sides [184] :else [185] NDEB N ¦ so at most 1 leading/trailing blank in each name [186] N(N†';') Partition N ¦ 'foo;goo'  'foo' 'goo' [187] :end [188] [189] nlûLL ¦ number of libraries [190] ndûDD ¦ number of directories [191] [192] w•FI UcmdIni 'SymFind-Place' '2 5 20 70' [193] v•FI UcmdIni 'SymFind-Visible' '1' [194] [195] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [196] [197] •wself'fmSymFind' •wi 'Create' 'Form' 'Hide' [198] •wi 'caption' ('SymFind ',c) [199] •wi 'place' w [200] •wi 'visible' v [201] e' CMDSYMFIND •wevent' [202] •wi 'onClose' e [203] •wi 'onDropDown' e [204] •wi 'pointer' 11 ¦ 11=hourglass (wait) [205] [206] •wself':mFile' •wi 'New' 'Menu' [207] •wi 'caption' '&File' [208] [209] •wself'.mExit' •wi 'New' 'Menu' [210] •wi 'caption' 'E&xit' [211] •wi 'shortcut' 'X' 2 [212] •wi 'onClick' "0 0û':' •wi 'Close'" [213] [214] •wself':mEdit' •wi 'New' 'Menu' [215] •wi 'caption' '&Edit' [216] [217] •wself'.mAll' •wi 'New' 'Menu' [218] •wi 'caption' 'Select &All' [219] •wi 'shortcut' 'A' 2 [220] •wi 'onClick' " CMDSYMFIND 'All'" [221] [222] •wself'..mNone' •wi 'New' 'Menu' [223] •wi 'caption' 'Select &None' [224] •wi 'shortcut' 'N' 2 [225] •wi 'onClick' " CMDSYMFIND 'None'" [226] [227] •wself'..mInvert' •wi 'New' 'Menu' [228] •wi 'caption' '&Invert Selection' [229] •wi 'shortcut' 'I' 2 [230] •wi 'onClick' " CMDSYMFIND 'Invert'" [231] [232] •wself':mView' •wi 'New' 'Menu' [233] •wi 'caption' '&View' [234] [235] c" CMDSYMFIND 'View'" [236] [237] •wself'.mWsid' •wi 'New' 'Menu' [238] •wi 'caption' '&WSID' [239] •wi 'shortcut' 'W' 2 [240] •wi 'style' 1 [241] •wi 'value' 1 [242] •wi 'data' 3 ¦ column number in :lv [243] •wi 'onClick' c [244] [245] •wself'..mUfile' •wi 'New' 'Menu' [246] •wi 'caption' '&UFile' [247] •wi 'shortcut' 'U' 2 [248] •wi 'style' 1 [249] •wi 'value' 1 [250] •wi 'data' 4 [251] •wi 'onClick' c [252] [253] •wself'..mTime' •wi 'New' 'Menu' [254] •wi 'caption' '&Timestamp' [255] •wi 'shortcut' 'T' 2 [256] •wi 'style' 1 [257] •wi 'value' T [258] •wi 'data' 7 [259] •wi 'onClick' c [260] [261] •wself'..mBytes' •wi 'New' 'Menu' [262] •wi 'caption' '&Bytes' [263] •wi 'shortcut' 'B' 2 [264] •wi 'style' 1 [265] •wi 'value' B [266] •wi 'data' 8 [267] •wi 'onClick' c [268] [269] •wself'..mDepth' •wi 'New' 'Menu' [270] •wi 'caption' 'D&epth' [271] •wi 'shortcut' 'E' 2 [272] •wi 'style' 1 [273] •wi 'value' 1 [274] •wi 'data' 9 [275] •wi 'onClick' c [276] [277] •wself'..mShape' •wi 'New' 'Menu' [278] •wi 'caption' '&Shape' [279] •wi 'shortcut' 'S' 2 [280] •wi 'style' 1 [281] •wi 'value' 1 [282] •wi 'data' 10 [283] •wi 'onClick' c [284] [285] •wself'..mValue' •wi 'New' 'Menu' [286] •wi 'caption' 'Va&lue' [287] •wi 'shortcut' 'L' 2 [288] •wi 'style' 1 [289] •wi 'value' 1 [290] •wi 'data' 11 [291] •wi 'onClick' c [292] [293] •wself':mActions' •wi 'New' 'Menu' [294] •wi 'caption' '&Actions' [295] [296] •wself'.mPeek' •wi 'New' 'Menu' [297] •wi 'caption' '&Peek' [298] •wi 'shortcut' 'P' 2 [299] •wi 'onClick' "1 CMDSYMFIND 'Peek'" ¦ 1=peek [300] [301] •wself'..mGet' •wi 'New' 'Menu' [302] •wi 'caption' '&Get Info' [303] •wi 'shortcut' 'G' 2 [304] •wi 'onClick' "0 CMDSYMFIND 'Peek'" ¦ 0=get info [305] [306] •wself'..mGetAll' •wi 'New' 'Menu' [307] •wi 'caption' 'Get Info for &All' [308] •wi 'shortcut' 'G' 4 [309] •wi 'onClick' " CMDSYMFIND 'GetAll'" [310] [311] •wself'..mDiff' •wi 'New' 'Menu' [312] •wi 'caption' '&Diff' [313] •wi 'shortcut' 'D' 2 [314] •wi 'onClick' " CMDSYMFIND 'Diff'" [315] [316] •wself'..mRemove' •wi 'New' 'Menu' [317] •wi 'caption' '&Remove from list' [318] •wi 'shortcut' (46 0) ¦ 46=Del [319] •wi 'onClick' " CMDSYMFIND 'Remove'" [320] [321] •wself'..mFns' •wi 'New' 'Menu' [322] •wi 'caption' '&Functions only' [323] •wi 'shortcut' 'F' 2 [324] •wi 'onClick' "'ì' CMDSYMFIND 'Only'" [325] [326] •wself'..mVars' •wi 'New' 'Menu' [327] •wi 'caption' '&Variables only' [328] •wi 'shortcut' 'V' 2 [329] •wi 'onClick' "'' CMDSYMFIND 'Only'" [330] [331] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [332] c0 3û0 [333] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [334] :if (nl>0)^(nd=0) ¦ all library numbers? [335] ccž'Lib' 8 'right' ¦ 2 [336] :elseif (nl=0)^(nd>0) ¦ all directories? [337] ccž'Dir' 16 'left' ¦ 2 [338] :else [339] ccž'Lib/Dir' 16 'left' ¦ 2 [340] :end [341] ccž'WSID' (W’16) 'left' ¦ 3 [342] ccž'UFile' (U’16) 'left' ¦ 4 [343] ccž'C' 2.5 'center' ¦ 5 [344] ccž'Name' 16 'left' ¦ 6 [345] [346] ccž'Timestamp' (T’20) 'right' ¦ 7 ¦ rjust in case of '-' [347] ccž'Bytes' (B’8) 'right' ¦ 8 [348] ccž'ð' 2.5 'right' ¦ 9 [349] ccž'Shape' 8 'right' ¦ 10 [350] ccž'Value' 32 'left' ¦ 11 [351] [352] •wself':lv' •wi 'New' 'Listview' [353] •wi 'where' 0.5 1 ¦ this establishes gaps [354] •wi 'style' 1 2 4 1024 4096 ¦ 1024=reorder cols 4096=gridlines [355] •wi 'columndisplay' c [356] [357] •wi 'scale' 3 ¦ font size will be specified in points [358] •wi 'font' (UcmdFont '') [359] [360] •wi 'onColClick' e ¦ sort [361] •wi 'onDblClick' e ¦ peek [362] •wi 'onKeyPress' e ¦ Enterpeek [363] •wi 'onClick' e ¦ select [364] [365] •wi 'AutoFit' 'header' ((T/7),(B/8),9 10) [366] [367] •wself':l1' •wi 'New' 'Label' [368] •wi 'caption' '' [369] h1 1•wi 'Draw' ('?Text' 'AB') ¦ perhaps 0.8 [370] •wi 'size' h 10 [371] [372] •wself':l2' •wi 'New' 'Label' [373] •wi 'caption' '' [374] [375] hö•first '#' •wi 'units' ¦ pixel height, in chars [376] h1.2524’h ¦ button height [377] [378] •wself':bnExit' •wi 'New' 'Button' [379] •wi 'caption' 'Stop' [380] •wi 'size' h 8 [381] •wi 'style' 2 ¦ 2=cancel [382] •wi 'onClick' "':' •wi '‘stop' 1" [383] [384] •wself':bnAll' •wi 'New' 'Button' [385] •wi 'caption' '&Get All Info' [386] •wi 'size' h 8 [387] •wi 'onClick' " CMDSYMFIND 'GetAll'" [388] [389] •wself':' [390] [391] •wi 'onResize' e [392] 0 CMDSYMFIND 'Resize' [393] k•wi 'Show' [394] [395] ':bnExit' •wi 'Focus' ¦ so you can hit Enter or Esc to interrupt [396] [397] •wself':lv' [398] [399] ¦ ----- Workspaces ----- [400] [401] hw4û0 ¦ count hits [402] LLLL,DD ¦ combine libs and dirs [403] ULLL ¦ save for ufiles [404] LLW/LL ¦ if /W ... [405] [406] :while ’ûLL ¦ next library or directory [407] [408] •wgive 0 [409] [410] :if ':' •wi '‘stop' [411] :leave [412] :end [413] [414] L1LL ¦ pop next ... [415] LL1LL ¦ ... lib or dir [416] wsDMIFERR '•WSLIB L' ¦ try to get workspace names [417] :if 1=ûûws ¦ error if no such lib/dir [418] ñOUT ws,': ',ôL [419] :continue [420] :end [421] :if 82†•DR L ¦ library number? [422] ws0 11ws ¦ drop library numbers [423] lp•LIBD L ¦ library path [424] ¦lplp,('\'†ý1lp)û'\' ¦ force trailing backslash [425] ¦lplp,'\'~ý1lp ¦ force trailing backslash ¦ thanks, Roy [426] lplp,((ý1lp)î'\:')'\' ¦ force trailing backslash, unless 'D:' [427] pvôL ¦ lib/dir for display [428] pxpv,' ' ¦ wsid prefix [429] :else ¦ directory [430] pv(-'\'=ý1L)L ¦ lib/dir for display (last might be î'\:.') [431] lpL ¦ library path [432] pxL ¦ wsid prefix [433] :if S ¦ subdirectories? [434] ¦b•LIB L ¦ all files [435] ¦ Have gotten several unrepeatable errors from •LIB: [436] ¦ XFHOST ERROR FindFirstFile 1 0 123 The filename, directory name, or volume label syntax is incorrect. [437] bDMIFERR '•LIB L' [438] :if 1=ûûb ¦ error? [439] ñOUT L,' * ',b [440] :continue [441] :end [442] b(bú.='\')ëb ¦ only subdirectories [443] b( L),DTB [2]b ¦ append to directory [444] LLb,LL ¦ add to front of queue [445] :end [446] :end [447] ws(~ú/'.BAK 'ws,' ')ëws ¦ 7/14/07 don't search backup wss [448] nw•first ûws ¦ number of wss [449] hw[1]hw[1]+nw ¦ wss attempted [450] :for i :in ânw ¦ next workspace [451] •wgive 0 [452] :if ':' •wi '‘stop' [453] :leave [454] :end [455] wDTB ws[i;] ¦ workspace [456] lwpx,w ¦ wsid [457] ':l1' •wi 'caption' ('Searching workspace ',(ôhw[2]+1),' ... ',lw) [458] sRDST lp,w,'.w3' ¦ here's the magic: read symbol table [459] :if 1=ûûs ¦ error message? [460] :if ( s)î'RUNTIME WS' 'EMPTY FILE' [461] ¦ don't mention those errors [462] :else [463] ñOUT s,': ',lw [464] :end [465] :continue [466] :end [467] hw[2]hw[2]+1 ¦ wss searched [468] bú/•first ú/N (Up s),' ' [469] bb^ú/sîF ¦ fns/vars filter [470] n+/b [471] :if n>0 [472] hw[3]hw[3]+1 ¦ wss w/ hits [473] hw[4]hw[4]+n ¦ total hits [474] :for j :in b/âûb [475] k•wi 'AddRows' 0 1 '' pv w '' (s[j;1]) (DTB 2s[j;]) [476] :end [477] :end [478] :end ¦ next workspace [479] :end ¦ next library or directory [480] [481] :if W [482] (u w h)hw[2 3 4] [483] q'Found ',(ôh),((-h=1)' matching names'),' in ',(ôw),' of ',(ôu),(-u=1)' workspaces' [484] ':l1' •wi 'caption' q [485] :end [486] [487] ¦ ----- User command files ----- [488] [489] hu4û0 ¦ count hits [490] ¦ LL is now empty [491] ¦ UU may have list of ucmd files [492] :if U ¦ if /U ... [493] :andif 0=ûUU [494] LLUL [495] :end [496] [497] :repeat ¦ while ’ûLL,UU [498] [499] •wgive 0 [500] [501] :if ':' •wi '‘stop' [502] :leave [503] :end [504] [505] :if ’ûUU ¦ first priority: file in queue [506] L1UU ¦ pop next ... [507] UU1UU ¦ ... file [508] ':l2' •wi 'caption' ('Searching file ',(ôhu[2]+1),' ... ',L) [509] sL CMDSYMFIND 'Udir' ¦ read ufile symbol table [510] :if 0=ûûs ¦ not a ufile? [511] :continue [512] :end [513] hu[1]hu[1]+1 ¦ files attempted [514] L(' '=•first L)L ¦ un-kludge [515] :if 1=ûûs ¦ error message? [516] ñOUT L,' * ',s [517] :continue [518] :end [519] hu[2]hu[2]+1 ¦ files searched [520] bú/•first ú/N (Up s),' ' [521] bb^ú/sîF ¦ fns/vars filter [522] n+/b [523] :if n>0 [524] hu[3]hu[3]+1 ¦ files w/ hits [525] hu[4]hu[4]+n ¦ total hits [526] i(è<\èLî' \:')â1 [527] uiL ¦ ufile [528] pv(i-L[i]î'\ ')L ¦ lib/dir for display (last might be î' \:.') [529] :for j :in b/âûb [530] k•wi 'AddRows' 0 1 '' pv '' u (s[j;1]) (DTB 2s[j;]) [531] :end [532] :end [533] [534] :elseif ’ûLL ¦ second priority: lib or dir [535] L1LL ¦ pop next ... [536] LL1LL ¦ ... lib [537] wsDMIFERR '•FLIB L' ¦ try to get file names [538] :if 1=ûûws ¦ error if no such lib/dir [539] ñOUT (ôL),' * ',ws [540] :continue [541] :end [542] B82†•DR L ¦ is this a library number? [543] :if B ¦ lib? [544] UUUU,DLTB [2]ws ¦ add files to queue [545] :else [546] UUUU,( L),DTB [2]ws ¦ add files to queue [547] :end [548] :if S ¦ subdirs? [549] :if B [550] L•LIBD L ¦ library path [551] LL,((ý1L)î'\:')'\' ¦ force trailing backslash, unless 'D:' [552] :end [553] b•LIB L ¦ all files [554] b(bú.='\')ëb ¦ only subdirectories [555] b( L),DTB [2]b ¦ append to directory [556] LLb,LL ¦ add to front of queue [557] :end [558] [559] :else [560] :leave ¦ we're done [561] [562] :end [563] [564] :end [565] [566] :if U [567] (u w h)hu[2 3 4] [568] q'Found ',(ôh),((-h=1)' matching names'),' in ',(ôw),' of ',(ôu),(-u=1)' files' [569] ':l2' •wi 'caption' q [570] :end [571] [572] •wi 'AutoFit' 'header' (2,(W/3),(U/4),5 6 11) [573] [574] •wself':bnExit' [575] •wi 'onClick' '' ¦ this enables the style 2=cancel behavior [576] •wi 'caption' 'E&xit' [577] [578] •wself':' [579] [580] •wi '‘stop' 0 [581] •wi 'pointer' 0 [582] [583] :if ']'î•SI[;1] ¦ user command? [584] k•wi 'Wait' [585] :else [586] k•wi 'Show' [587] :end [588] [589] 0 [590] [591] L9: ¦ ========== Callbacks ========== [592] [593] :SELECT N [594] [595] :CASE 'Remove' [596] [597] •wself':lv' [598] v•wi 'value' ¦ selected row(s) [599] •wi 'DeleteRows' v [600] [601] :CASE 'Only' [602] [603] •wself':lv' [604] a•wi 'sortorder' ¦ all row ids [605] c•first,•wi 'GetCells' a 5 ¦ class [606] v(~cî G)/a [607] •wi 'DeleteRows' v [608] [609] :CASE 'KeyPress' [610] [611] :if •warg=13 ¦ Enter key? [612] 1 CMDSYMFIND 'Peek' [613] :end [614] [615] :CASE 'Peek' [616] [617] ¦ G is 1 for peek, 0 for get info [618] •wself':lv' [619] v•wi 'value' ¦ selected row(s) [620] (0=ûv)û0 ¦ nothing selected [621] :if G [622] i1v ¦ if many selected, just peek at first [623] i G CMDSYMFIND 'PeekRow' [624] :else [625] :if 1=ûv [626] v G CMDSYMFIND 'PeekRow' ¦ one row [627] :else [628] v CMDSYMFIND 'GetRows' ¦ hourglass, etc. [629] :end [630] :end [631] [632] :CASE 'DblClick' [633] [634] r1•warg ¦ rowid [635] r 1 CMDSYMFIND 'PeekRow' [636] [637] :CASE 'All' [638] [639] •wself':lv' [640] a•wi 'sortorder' ¦ all row ids [641] •wi 'value' a [642] [643] :CASE 'None' [644] [645] ':lv' •wi 'value'  [646] [647] :CASE 'Invert' [648] [649] •wself':lv' [650] a•wi 'sortorder' ¦ all row ids [651] v•wi 'value' ¦ selected rowids [652] •wi 'value' (a~v) [653] [654] :CASE 'Resize' [655] [656] ¦ ••wself •wevent (FFA •warg) [657] z•wi 'size' ¦ form size [658] (0îz)û0 ¦ minimized? don't bother doing anything [659] a':l1' •wi 'size' ¦ label size [660] b':bnExit' •wi 'size' ¦ button size [661] hb[1]2’a[1] ¦ height needed [662] [663] •wself':lv' [664] w•wi 'where' [665] w[3 4]z-2’w[1 2] ¦ form size, less top/bottom/left/right gaps [666] w[3]w[3]-h+w[1] ¦ less buttons and another vertical gap [667] •wi 'where' w ¦ move and resize [668] [669] •wself':bnExit' [670] tw[1 2]+w[3 4] ¦ botton right of :lv [671] t[2]t[2]-b[2] ¦ move left [672] vt[1]+w[1] ¦ top gap [673] t[1]v+0.5’h-b[1] ¦ plus half of label height differential [674] •wi 'where' t ¦ just move [675] [676] •wself':bnAll' [677] t[2]t[2]-b[2]+w[2] [678] •wi 'where' t ¦ just move [679] [680] •wself':l1' [681] w[1]v+0.5’h-2’a[1] [682] w[3]a[1] [683] w[4]t[2]-2’w[2] [684] •wi 'where' w [685] [686] •wself':l2' [687] w[1]w[1]+a[1] [688] •wi 'where' w [689] [690] :CASE 'ColClick' [691] [692] c1•warg ¦ column clicked [693] i•wi 'sortorder' ¦ all rowids [694] d,•wi 'GetCells' i c ¦ data [695] :if cò7 ¦ info columns [696] dôd ¦  is in unset cells [697] :end [698] m[2]d ¦ simple char matrix [699] :if c=2 ¦ lib/dir? [700] b1=•first•VId ¦ plain library numbers [701] bb/âûb [702] rm[b;] [703] m[b;](-+/^\èr=' ')èr ¦ right justify [704] :end [705] :if cî8 9 10 ¦ bytes depth shape? [706] m(-+/^\èm=' ')èm ¦ right justify [707] :end [708] d•AVm [709] :if dðâûd ¦ already sorted? [710] dèd ¦ descending [711] :end [712] •wi 'sortorder' (i[d]) [713] [714] :CASE 'PeekRow' [715] [716] ¦ ••wself •wevent •warg [717] (r G)G ¦ rowid  1 for peek, 0 for get info [718] (b w u c j),•wi 'GetCells' r (2 3 4 5 6) ¦ lib wsid ufile class name [719] [720] :if (,1)ð•VI b ¦ library number [721] bb,' ' [722] :else ¦ path [723] bb,(':'=ý1b)'\' ¦ force trailing backslash, unless 'D:' [724] :end [725] [726] :if wú.†' ' [727] (r (b,w) c j G) CMDSYMFIND 'PeekWsid' [728] :else [729] (r (b,u) c j G) CMDSYMFIND 'PeekUfile' [730] :end [731] [732] :CASE 'PeekWsid' [733] [734] (r w c j G)G ¦ row ws class name peek [735] [736] z~G [737] k " rj P a;k;•ELX;*" [738] kk,"@ •ELX'r9  0'" ¦ handle possible INCOMPATIBLE WS error from •COPY [739] kk,"@ rj •COPY a" [740] kk,"@ (rî1 2)0" [741] kk,"@ rr,•SIZE j" [742] kk,"@ :select •first r" [743] kk,"@ :case 1" ¦ function [744] kk,"@ rr,(2 •AT j)(•VR j)" [745] kk,z/"@ 0" ¦ get info only [746] kk,"@ (û4r)0" ¦ don't try to edit if locked [747] kk,"@ k•WCALL 'W_Edit' j" [748] kk,"@ :case 2" ¦ variable [749] kk,"@ v*" [750] kk,"@ rr,'' v" [751] kk,z/"@ 0" ¦ get info only [752] kk,"@ :if 1=ûûv" [753] kk,"@ :andif 5óûv" [754] kk,"@ :andif 'PACKAGE'ð1v" [755] kk,"@ •UCMD 'PKGDOC ',j" [756] kk,"@ 0" [757] kk,"@ :elseif (ðv)>1" [758] kk,"@ :orif (ûûv)>2" [759] kk,"@ :orif ^/0 ' 'î•TYPE •enlist v" [760] kk,"@ v•UCMD 'DISPLAY v'" [761] kk,"@ *v" [762] kk,"@ :end" [763] kk,"@ k•WCALL 'W_Edit' j" [764] kk,"@ :end" [765] [766] ((k='*')/k) j [767] k•enlist k [768] k(k†'@') Partition k [769] k•DEF[2]k ¦õ P [770] ¦ ••vr k [771] (rc z t x)4j P w [772] :if rcî1 2 [773] max256 ¦ max width of FFA display [774] zDLB,'CI15' •FMT z ¦ format bytes [775] :if rc=2 ¦ variable [776] t'-' [777] sûx ¦ shape [778] s(ôs),(0=ûs)/'' ¦ format shape [779] dôðx ¦ depth [780] xmax FFAW x [781] x(maxûx)ûx [782] qxâ'û' [783] :if qóûx [784] :andif q,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6ût [789] d'-' ¦ depth [790] ¦s(ô+/x •SS •TCNL,'['),' lines' [791] :if c='' [792] s'?' [793] x'(locked function)' [794] :else [795] sôûx [796] x(maxûx)ûx [797] ((x=•TCNL)/x)' ' [798] :end [799] :end [800] c7 8 9 10 11 ¦ timestamp bytes depth shape value [801] •wi 'SetCells' r c (t z d s x) [802] ¦ display •wi 'GetCells' r c [803] m•wi 'columndisplay' [804] c(0†m[c;2])/c ¦ only visible columns [805] •wi 'AutoFit' 'header' c [806] 0 [807] :end [808] [809] môrc [810] ((m='ý')/m)'-' [811] m'Return code ',m,' from []COPY:',•tcnl [812] [813] :select rc [814] :case 0  mm,'Object not found' [815] :case 127  mm,'Duplicate name in objlist ¦ should not get here!' [816] :case ý2  mm,'Object too large for available space' [817] :case ý3  mm,'Name defined as a label; cannot be changed' [818] :case ý4  mm,'Insufficient space in symbol table and workspace too full to expand symbol table' [819] :case ý6  mm,'Insufficient free space to carry out command' [820] :case 9  m 'Error from []COPY:',•TCNL,(^\•DM†•TCNL)/•DM [821] :else  mm,'Unanticipated return code!' [822] :end [823] [824] k•wcall 'MessageBox' (•wi ':hwnd') m 'COPY ERROR' 'MB_ICONSTOP' [825] [826] :CASE 'PeekUfile' [827] [828] (r u c j G)G ¦ row file class name peek [829] [830] (v t)(u j) CMDSYMFIND 'Uget' ¦ the value, timestamp [831] t,'I4,,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6ûFTIMEREP t [832] nj [833] [834] :if 1=ûûv [835] :andif 5óûv [836] :andif 'PACKAGE'ð1v [837] rc2 ¦ variable [838] z•SIZE 'v' ¦ bytes [839] :if G ¦ if peek [840] k•DEF[2]("n P ",n) "•UCMD 'PKGDOC ',n" ¦õ P [841] ¦ ••vr 'P' [842] n P v [843] :end [844] :elseif c='ì' ¦ function [845] rc1 ¦ function [846] ¦ Note we update z here -- [847] ¦ need to measure bytes while function is defined; it's not just •size •vr ! [848] k•DEF[2]("n P v;",n) "k•def v  (kðn)0  z•SIZE n" (G/"k•WCALL 'W_Edit' n") [849] n P v [850] :else ¦ variable [851] rc2 [852] z•SIZE 'v' ¦ bytes [853] :if G ¦ if peek [854] :if (ðv)>1 [855] :orif (ûûv)>2 [856] :orif ^/0 ' 'î•TYPE •enlist v [857] v•UCMD 'DISPLAY v' ¦ well, it's better than nothing! [858] :end [859] k•DEF[2]("n P ",n) "k•WCALL 'W_Edit' n" [860] n P v [861] :end [862] :end [863] [864] max256 ¦ max width of FFA display [865] zDLB,'CI15' •FMT z ¦ format bytes [866] :if rc=2 ¦ variable [867] sûv ¦ shape [868] s(ôs),(0=ûs)/'' ¦ format shape [869] dôðv ¦ depth [870] xmax FFAW v [871] x(maxûx)ûx [872] qxâ'û' [873] :if qóûx [874] :andif q0) [907] '.mGet' •wi 'enabled' (n>0) [908] '.mGetAll' •wi 'enabled' ((ûi)>0) [909] '.mDiff' •wi 'enabled' (n=2) [910] '.mRemove' •wi 'enabled' (n>0) [911] [912] :CASE 'Click' [913] [914] ¦ If there are 0 rows selected, act on the pointed-to row [915] ¦ Else always act on selected row(s) [916] [917] a•warg ¦ pointed-to rowid; save to perhaps pass along to DblClick [918] b7a ¦ mouse button (1=left 2=right) [919] (b†2)û0 ¦ quit unless right (row selection has already been toggled) [920] v•wi 'value' ¦ selected rowids [921] r1a ¦ pointed-to rowid; save to perhaps pass along to DblClick [922] r0 ¦ quit if empty row [923] z•first •wi 'GetCells' r 8 ¦ bytes (tells us if we have done Get Info already) [924] [925] f•wself [926] [927] m'mSymFindPopup' [928] •wselfm •wi 'Create' 'Menu' [929] k'.m1' •wi 'New' 'Menu' ('caption' 'Peek') ('onClick' "':' •wi 'data' 1") [930] k'.m2' •wi 'New' 'Menu' ('caption' 'Get Info') ('onClick' "':' •wi 'data' 2") ('enabled' (0îûz)) [931] k'.m3' •wi 'New' 'Menu' ('caption' 'Diff') ('onClick' "':' •wi 'data' 3") ('enabled' (2=ûv)) [932] k'.m4' •wi 'New' 'Menu' ('caption' 'Remove from list') ('onClick' "':' •wi 'data' 4") [933] [934] •wselff [935] [936] ':' •wi 'Popup' m 2 ¦ 2=make the menu respond to the right mouse button [937] dm •wi 'data' [938] m •wi 'Delete' [939] [940] :select d [941] :case 0 ¦ escape [942] ¦ noop [943] :case 1 ¦ peek [944] r 1 CMDSYMFIND 'PeekRow' [945] :case 2 ¦ get info [946] :for i :in v [947] i 0 CMDSYMFIND 'PeekRow' [948] :end [949] :case 3 ¦ diff [950]  CMDSYMFIND 'Diff' [951] :case 4 ¦ remove [952] •wi 'DeleteRows' v [953] :else ¦ tilt [954] ö0 [955] :end [956] [957] :CASE 'View' [958] [959] ¦ •wself is a menu item [960] v•wi 'value' ¦ value has already changed [961] c•wi 'data' ¦ display column number [962] •wself':lv' [963] :if v ¦ if turning on, we just need to autofit it [964] •wi 'AutoFit' 'header' c [965] :else ¦ if turning off, we need to change width to 0 [966] m•wi 'columndisplay' [967] m[c;2]0 [968] •wi 'columndisplay' m [969] :end [970] [971] :CASE 'GetAll' [972] [973] ':mView.mTime' •wi 'value' 1 ¦ RHS 9/18/04 automatically reveal the Timestamp column [974] [975] •wself':lv' [976] w•wi 'sortorder' ¦ all rowids [977] w CMDSYMFIND 'GetRows' [978] [979] :CASE 'GetRows' [980] [981] wG ¦ rowids [982] [983] ':' •wi 'pointer' 11 [984] [985] •wself':bnExit' [986] •wi 'caption' 'Stop' [987] •wi 'onClick' "':' •wi '‘stop' 1" [988] [989] •wself':lv' [990] [991] d,•wi 'GetCells' w 8 ¦ bytes [992] w(0îûd)/w ¦ not got yet [993] [994] :for i :in w [995] •wgive 0 [996] :if ':' •wi '‘stop' [997] ':' •wi '‘stop' 0 [998] :leave [999] :end [1000] i 0 CMDSYMFIND 'PeekRow' [1001] :end [1002] [1003] ':' •wi 'pointer' 0 [1004] [1005] •wself':bnExit' [1006] •wi 'onClick' '' [1007] •wi 'caption' 'E&xit' [1008] [1009] :CASE 'Udir' [1010] [1011] ¦ Callback to read ucmd file directory [1012] [1013] n' '=•first G ¦ file name from ]UFILE ? [1014] :if n ¦ no tolerence for error [1015] •ELX'R"NOT A USER COMMAND FILE"  b' ¦ vector result: error [1016] :else ¦ file name from lib or dir: ignore any error [1017] •ELX"R0  b" [1018] :end [1019] [1020] b0 ¦ branch target after error [1021] T•FNUMS,•XFNUMS ¦ save current ties [1022] t1+0/T ¦ next available tie number [1023] G •FSTIE t ¦ tie it [1024] bL2 ¦ now we need to untie [1025] :if n [1026] :orif 1î'User-defined commands file'•enlist •FREAD t,1 ¦ first comp should have signature [1027] i•FREAD t,2 ¦ pointers to directories [1028] s•FREAD t,i[2] ¦ char directory of objects (names) [1029] n•FREAD t,i[3] ¦ num directory of objects (nc, comp) [1030] n' ì?'[n[;1]] [1031] Rn,' ',DTBC s ¦ matrix result: like RDST [1032] :else [1033] R0 ¦ scalar result: not a ucmd file, ignore it [1034] :end [1035] L2: [1036] b0 [1037] •FUNTIE t [1038] tT~•FNUMS,•XFNUMS [1039] :if ’ût ¦ we lost a tie number [1040] G •FSTIE t ¦ but what if it was originally •FTIE ...? [1041] :end [1042] [1043] :CASE 'Uget' [1044] [1045] (G j)G ¦ file, object name [1046] T•FNUMS,•XFNUMS ¦ before [1047] t1+0/T ¦ next available tie number [1048] G •FSTIE t ¦ tie it [1049] w•FNUMS,•XFNUMS ¦ after [1050] :if (ûT)=ûw ¦ was it already tied? [1051] tT~w ¦ original tie number [1052] G •FSTIE t ¦ but what if it was originally •FTIE ...? [1053] u ¦ nothing to untie when done [1054] :else [1055] ut ¦ to untie when done [1056] :end [1057] i•FREAD t,2 ¦ pointers to directories [1058] s•FREAD t,i[2] ¦ char directory of objects (names) [1059] n•FREAD t,i[3] ¦ num directory of objects (nc, comp) [1060] i(s^.=(ý1ûs)j)â1 ¦ find name [1061] (c m)n[i;2 3] ¦ component, timestamp [1062] v•FREAD t,c ¦ read value [1063] •FUNTIE u [1064] Rv m ¦ value, timestamp [1065] [1066] :CASE 'Diff' [1067] [1068] •wself':lv' [1069] v•wi 'value' ¦ selected rowids [1070] m•wi 'GetCells' v (2 3 4 6) ¦ lib wsid ufile name [1071] d2û '' [1072] :for i :in â2 [1073] (b w u j)m[i;] ¦ lib wsid ufile name [1074] :if (,1)ð•VI b ¦ library number [1075] bb,' ' [1076] :else ¦ path [1077] bb,(':'=ý1b)'\' ¦ add trailing backslash, unless 'D:' [1078] :end [1079] :if wú.†' ' [1080] (id)b,w,' ',j [1081] :else [1082] (id)j, '/F=',b,u [1083] :end [1084] :end [1085] •UCMD •' ]DIFF ',(1d),' ; ',2d ¦ show ucmd being invoked [1086] [1087] :ELSE [1088] [1089] •'Unanticipated callback!' N •wself •wevent •warg [1090] [1091] :ENDSELECT [1092] ì €US[•wself;•wevent] [187] n1 [188] [189] ¦ Well, in ucmd environment... [190] s•SI[;1] ¦ first column of SI [191] s(~sî'õ•><')/s ¦ ditch •SI levels that don't have matching •IDLOC columns [192] nsâ']' ¦ how much UCMD crap is there [193] nn*nóûs ¦ or 1 if no ] (non-UCMD) [194] [195] e(n+1)[1]•si [196] eñDEB ,' ',e [197] e'øøø TraceObj: ',•wself,' ',•wevent,' (',(FFAW •warg),') ',e [198] ¦e(•PWûe)e [199] •e [200] ì €US<ÍÍ ì CMDTRACEVAR A;D;K;S;V;W;X [1] ¦ Trace changes to variable(s) [2] [3] ¦ ]TraceVar dat ... ¦ trace changes to the named variable(s) [4] ¦ ]TraceVar dat:2dat ¦ display 2dat when dat changes; just one var [5] ¦ ]TraceVar dat[2] ¦ trace only when dat[2] changes; just one var [6] ¦ ]TraceVar ... /STOP ¦ sets stop on first change; suspends before next change [7] ¦ ]TraceVar ... /ALERT ¦ display MessageBox after change report [8] [9] ¦ ]TraceVar dat ... /OFF ¦ turn off tracing of the named variable(s) [10] ¦ ]TraceVar /OFF ¦ turn off all tracing [11] [12] ¦ ]TraceVar dat /REPORT ¦ used internally to report a change [13] [14] ¦ 21 Oct 2004 Rex Swain, Independent Consultant, www.rexswain.com [15] ¦ 19 Apr 2005 Added varname:expression feature [16] ¦ 03 Jun 2005 Added /STOP and /ALERT features [17] ¦ 29 Mar 2007 Added dat[2] feature [18] ¦ 22 Feb 2008 Allow dat[2;5] ¦ duh [19] [20] ¦ To do: [21] ¦ - Exploit built-in •watchpoints feature to suspend execution [22] ¦ - Is there a way to catch the erasure of a variable? [23] [24] VñDEB (^\A†'/')/A ¦ argument without options [25] :if 1=ûûA ñGETOPT '/REPORT' [26] ¦ 1st row in •SI is ourself; 2nd row is •WATCHPOINT[1] [27] S•SI[;1] ¦ first column of SI [28] WSâ']' ¦ how much UCMD crap is there [29] WW*WóûS ¦ or 1 if no ] (non-UCMD) [30] WW+1 ¦ •WATCHPOINT[1] [31] SW[1]•SI ¦ •SI to report [32] :if '['îV [33] Dý1V ¦ drop ] [34] ¦D[Dâ'[']'_' [35] ((Dî'[;')/D)'_' ¦ RHS 2/22/08 in case 'DAT[2;5]' [36] :if 0='#' •wi '‘TraceVar_Flag_',D [37] ¦ first time [38] '#' •wi ('‘TraceVar_Flag_',D) 1 [39] ¦ and fall through to let it display [40] :else [41] X'#' •wi '‘TraceVar_Value_',D [42] (XðõV)û0 ¦ no change, no display [43] :end [44] '#' •wi ('‘TraceVar_Value_',D) (õV) [45] :end [46] W' TraceVar: ',ñDEB,' ',S  •(•pwûW)W [47] W' TraceVar: ',V,'',(•pw FFAW õV)  •(•pwûW)W [48] :if 1=ûûA ñGETOPT '/STOP' [49] ¦ S[1;] might be 'õ' now [50] X(S[;1]î'õ•><')â0 [51] :if X>ûûS [52] •' Cannot set Stop -- no function in SI stack' [53] :else [54] WS[X;] [55] X1(†\Wî'[]')/W ¦ line number [56] W(^\W†'[')/W ¦ function name [57] K((•STOP W),•FI X) •STOP W [58] X•STOP W [59] •' Stop',(1=ûX)'s now set on ',W,'[',(ôX),']' [60] :end [61] :end [62] :if 1=ûûA ñGETOPT '/ALERT' [63] XV,•TCNL,,•TCNL,S [64] XX,•TCNL,•TCNL,'Continue? (Y=Continue, N=Suspend, C=Cancel trace)' [65] K•wcall 'MessageBox' 0 X 'TraceVar' 'MB_ICONINFORMATION MB_YESNOCANCEL' [66] :if K=6 ¦ 6=IDYES [67] :elseif K=7 ¦ 7=IDNO [68] ñRESULT1 ¦ non-zero result suspends on •WATCHPOINT[1] [69] :else ¦ 2=IDCANCEL [70] V(^\V†'[')/V [71] •UCMD ']TraceVar ',V,' /OFF' [72] :end [73] :end [74] :elseif 1=ûûA ñGETOPT '/OFF' [75] :if Vð'' [76] •watchpoints0 2û '' [77] •']TraceVar * /OFF' [78] :else [79] V(V†' ') Partition V [80] W•watchpoints [81] W(~W[;1]îV)ëW [82] •watchpointsW [83] •']TraceVar',(ôV),'/OFF ¦ ',(ô1ûW),' vars remain traced' [84] :end [85] :else ¦ /ON [86] W•watchpoints [87] :if ~Vð'' [88] S(1=ûûA ñGETOPT '/STOP' )/' /STOP' [89] X(1=ûûA ñGETOPT '/ALERT')/' /ALERT' [90] :if ':'îV [91] (V D)(~<\V=':') Partition V [92] W(~W[;1]î V)ëW [93] WWžV ("•UCMD ']TraceVar ",D," /REPORT",S,X,"'") [94] :elseif '['îV [95] (V D)(1+<\V='[') Partition V [96] W(~W[;1]î V)ëW [97] WWžV ("•UCMD ']TraceVar ",V,D," /REPORT",S,X,"'") [98] :else [99] V(V†' ') Partition V [100] W(~W[;1]îV)ëW [101] WWžV,[1.5] ( "•UCMD ']TraceVar "),V, " /REPORT",S,X,"'" [102] :end [103] •watchpointsW [104] :end [105] •']TraceVar',ôW[;1] [106] :end [107] ì €US<²   ì CMDTTALL A;b;c;j [1] ¦ Create tooltips on all controls so they identify themselves [2] ¦ Note that some classes do not offer tooltips, but most do: [3] ¦ Button, Check, Combo, CommandButton, DateTime, Edit, Frame, Label, [4] ¦ List, Listview, Media, Option, Page, Picture, Progress, RichEdit, [5] ¦ Scroll, Spinner, Status, Toolbox, Trackbar, Tree [6] ¦ 07 Dec 2006 Rex Swain, Independent Consultant, www.rexswain.com [7] [8] j0û '' ¦ accumulate all objects [9] c, ,'#' ¦ children [10] :repeat [11] jj,c[1] [12] c1c,(1c) •wi '*children' [13] :until 0=ûc [14] [15] b( 'tooltip') î j •wi 'properties' [16] jb/j ¦ controls that allow tooltip [17] cj •wi 'class' [18] j •wi( 'tooltip'),(c,•tcnl,j) ì €US<]sQsQ ì XCMDVALENCE A;B;C;E;F;FILT;H;I;L;N;P;Q;QC;SINK;SYN;T;U;UP;V;W;WD;Z;a;c;d;e;f;g;j;k;p;q;s;t;u;v;x;•ELX [1] ¦ Find monadic or dyadic references to function named A [2] ¦ Helpful for finding certain uses of a function with an optional left argument [3] ¦ Syntax: [4] ¦ ]VALENCE FOO /1 options ¦ monadic [5] ¦ ]VALENCE FOO /2 options ¦ dyadic [6] ¦ ]VALENCE •DR /... ¦ also works for system functions [7] ¦ ]VALENCE /â/... ¦ and primitive functions (leading delimiter required) [8] [9] ¦ Options: [10] ¦ To limit functions searched: [11] ¦ /f1 f2 ¦ Only look in named functions [12] ¦ /f* ¦ Fn names with wildcards (foo* *old fm*def etc.) [13] ¦ /~f1 f2 ¦ Look in all but named functions [14] ¦ To limit search scope: [15] ¦ /¦ ¦ Find only in comments [16] ¦ /' ¦ Find only in character constants (or /") [17] ¦ /à ¦ Find only in APL (not comments/quotes) [18] ¦ (using all three above is equivalent to using none) [19] ¦ Other: [20] ¦ /? ¦ Prompt before each replacement [21] ¦ / ¦ Suppress display; return fn names [22] [23] ¦ 27 Dec 2005 Rex Swain, Independent Consultant, www.rexswain.com [24] ¦ 08 Jul 2007 Updated ìQC [25] [26] ¦ To do: [27] ¦ ]valence //1 correctly shows [X]A however this is not sensitive to )EVLEVEL [28] [29] Aô•ENLIST A ¦ arg might be numeric in development mode [30] [31] :if A^.=' ' [32] •'For help, ]valence ?' [33] 0 [34] :end [35] [36] A(ú\A†' ')/A ¦ dlb [37] d1A ¦ delimiter [38] [39] ¦ Allow simple word search without delimiters [40] ¦ If arg is 'foo', make it '/foo/'; if arg is 'foo/xx' make it '/foo/xx' [41] :if dî'•abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [42] d'/' [43] A(èú\èA†' ')/A ¦ DTB because user command may pass in trailing blanks [44] Ad,A,(dîA)d [45] ¦ Allow no trailing delimiter for search with no options [46] ¦ If arg is '/foo', make it '/foo/' [47] :elseif 1=+/A=d [48] A(èú\èA†' ')/A ¦ DTB because user command may pass in trailing blanks [49] AA,d [50] :end [51] [52] BA=d ¦ flag all delimiters [53] :if 2†+/B [54] •'Argument must have 2 delimiters' [55] •'For help, ]valence ?' [56] 0 [57] :end [58] [59] (A F)1B •penclose A ¦ target, options [60] [61] ¦ Check function [62] [63] AñDEB A [64] :if Að'' [65] •'Must specify a function to search for' [66] 0 [67] :elseif ' 'îA [68] •'Must specify only one function to search for' [69] 0 [70] :end [71] [72] :if 4†•NC A ¦ 0=undefined 1=variable 2=label 3=function 4=other [73] ¦ It's a valid identifier name -- though it might not be a function with an optional left arg [74] :elseif '•'=1A [75] E•ELX [76] •ELX'L9  1+•LC' [77] Lý1,•IDLOC A ¦ 1=function 2=variable etc.; DOMAIN ERROR if no such fn/var [78] •ELXE [79] :if L†1 [80] •'No such system function: ',A [81] 0 [82] :end [83] ¦ It's a system function -- though it might not have an optional left arg [84] :elseif 1=ûA [85] :andif Aî'~žðèíé*!-’+ö˜þ?îû~âù*ôþ,? ' [86] ¦ primitive fn that may be mondaic or dyadic [87] :elseif 1=ûA [88] :andif Aî'ž<ó=ò>†ú^åê©õæçü' [89] •'Function cannot be monadic or dyadic: ',A [90] 0 [91] :else [92] •'Not a function: ',A [93] 0 [94] :end [95] [96] ¦ Define ìFILT for APL/quoted strings/comments: [97] [98] Z'à''¦'îF [99] Z[2]Z[2]ú'"'îF [100] Z2æZ [101] E~Zî0 8 ¦ not all or none: we need to filter [102] [103] :if E ¦ unless all or none [104] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [105] LL, "¦ Quotes and Comments" [106] LL, "¦ Right arg is a •VR" [107] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [108] LL, "¦ Extracted from Zark's ìParseVR" [109] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [110] LL, "¦ 26 Oct 2004 Include ¦õ" [111] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [112] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [113] LL, "•IO0 ¦ origin 0 is convenient" [114] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [115] LL, "xcx\n" [156] LL, "¦ Flag newline after each comment; then convert pairs to maps" [157] LL, "tnúc" [158] LL, "ut/c" [159] LL, "c†\x\t\uúý10,u" [160] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [161] ¦ 0=None and 7=All cases are excluded before we get here [162] P 'rc' ¦ 1 = ¦ [163] PP, 'rq>c' ¦ 2 = ' ¦ Quoted strings: not in comments [164] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [165] PP, 'rqåc' ¦ 4 = à = 'å¦ [166] PP, 'r~q' ¦ 5 = ঠ= ~' [167] PP, 'r~c' ¦ 6 = à' = ~¦ [168] LL,P[Z] [169] SINK•FX[2]L ¦õ QC [170] :end [171] [172] L 'RFILT' [173] LL, '¦ Raw hit filter for no options' [174] LL, '¦ Requires: V=•VR, H=hits, P=partition flags' [175] ¦  We don't need this here because functions cannot match line numbers [176] ¦LL, 'HH>P ANDSCAN Vî''[1234567890]''' ¦ Not line numbers [177] LL,E/ 'HH^QC V' ¦õ QC ¦ Filter for à'¦ [178] LL, 'R1îH' ¦ Any hits remaining? [179] [180] SINK•FX[2]L ¦õ FILT QC [181] [182] ¦ Right argument: target [183] [184] tA ¦ Target string [185] [186] ¦ Define ìSYN for syntactic search: [187] [188] ¦ Token alphabet: chars that can be anywhere in a token [189] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [190] a'_' [191] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [192] aa,'abcdefghijklmnopqrstuvwxyzñ' [193] aa,'0123456789' [194] ¦ Token alphabet, including chars that can only begin a token [195] qa,'•ý' [196] ¦  Note that if target starts with • then we don't care what's to the [197] ¦ left of it, so ((1t)îa) is correct. [198] Z((1t)îa),(ý1t)îq ¦ First and last chars possibly names? [199] Z1+2æèZ ¦ 1=Neither 2=First 3=Last 4=Both [200] [201] Q 'RSYN;B;I' [202] QQ, '¦ Syntactic hit filter' [203] QQ, '¦ Requires: V=•VR, H=hits, a,q=alphabet, t=target string' [204] QQ, 'IH/âûH' [205] [206] L '' ¦ 1=Neither [207] LL, 'B('' '',V)[I]îq' ¦ 2=Just first [208] LL, 'B(V,'' '')[I+',(ôût),']îa' ¦ 3=Just last [209] LL, 'B(('' '',V)[I]îq)ú(V,'' '')[I+',(ôût),']îa' ¦ 4=Both [210] [211] QQ,L[Z] [212] QQ, 'H[B/I]0' ¦ Not syntactic; ignore hit [213] QQ, 'R1îH' ¦ Any hits remaining? [214] SINK•FX[2]Q ¦õ SYN H a q t [215] õ(Z=1)/'SINK•EX ''SYN''  SYN1' ¦ Constant 1 if none [216] [217] ¦ Define ìUP for case-insensitive filter [218] [219] :if '•'=1t ¦ only matters for system fns [220] Q'abcdefghijklmnopqrstuvwxyz' [221] L'ABCDEFGHIJKLMNOPQRSTUVWXYZ' [222] u•AV [223] u[uâQ]L [224] SINK•FX[2]'VUP V' 'Vu[•AVâV]' ¦õ UP u [225] ¦  This is faster than ñUCASE! [226] :else [227] ¦ Noop if no letters in target [228] SINK•FX[2]'VUP V' '¦ noop' ¦õ UP [229] :end [230] [231] tUP t ¦ Target to uppercase, if appropriate [232] [233] ¦ Initialize result [234] [235] x''îF ¦ Suppress display, just return result? [236] X0û '' [237] [238] Q "ZL WD R;N;P" [239] QQ, ":if 2óûûR" [240] QQ, " R,' ',R" [241] QQ, ":end" [242] QQ, ":if 0=•NC 'L'" [243] QQ, " NR†' '" [244] QQ, ":else" [245] QQ, " N~RîL" [246] QQ, ":end" [247] QQ, "P1,(1N)>ý1N" [248] QQ, "Z(N/P) •PENCLOSE N/R" [249] SINK•FX[2]Q ¦õ WD ¦ Words [250] [251] ¦ Parse desired valence from options [252] [253] FñDEB F [254] :if (1F)î'12' [255] v•fi 1F ¦ valence we want [256] F1F [257] :else [258] •'Must specify desired valence' [259] 0 [260] :end [261] [262] ¦ Strip flags from function list [263] [264] T'~'îF ¦ All but named fns? [265] [266] E'*'îF ¦ Any function name wildcards? [267] F(~Fî'à''¦~')/F ¦ Note we do not remove asterisk [268] FWD F [269] [270] ¦ Default to all fns [271] [272] :if T^0=ûF [273] •'Tilde with no names means "not all functions"' [274] 0 [275] :end [276] [277] :if EúTú0=ûF [278] [279] ¦ You could have a global function that is localized but undefined [280] ¦ •IDLIST 1+2+8 will not pick up that name, so... [281] [282] N•SINL [283] N(~N[;1]î'õ•><')ëN ¦ no local names at these levels [284] N(,ú\N=' ')/,N ¦ discard FOO[3], keep names to the right [285] NWD N ¦ all localized names [286] NN~ ,'*' ¦ the asterisk next to suspended fn is not a name [287] N('•'†•FIRSTN)/N ¦ avoid picking up system vars (ñUCMD2 localizes •PW and •CT) [288] [289] f•IDLIST 1+2+8 ¦ all visible names [290] fWD f [291] ff,N ¦ add all localized names [292] f((fâf)=âûf)/f ¦ there might be dups [293] [294] N,•SI [295] N(ý1+Nâ'[')ûN ¦ name of self ¦ RHS 8/31/99 [296] ff~ N ¦ remove self [297] [298] P•IDLOC [2]f ¦ what are they [299] PP[;0æûP] ¦ global definition [300] f(P=1)/f ¦ functions only [301] [302] ¦ Now we have all global functions (though some could be shadowed) [303] [304] :if 0=ûF [305] Ff [306] :elseif E ¦ which implies 0†ûF [307] :while '*'î•ENLIST F [308] P('*'îF)â1 [309] UPF [310] [311] Vâûf ¦ indices of matches [312] C' ',f,' ' ¦ candidates [313] U('*'=1U)' ',U,('*'=ý1U)' ' [314] :for L :in '*' WD U [315] BC •SS L [316] Hú/B [317] C((H/B)â1)H/C [318] VH/V [319] :if Vð  :leave  :end [320] :end [321] Cf[V] [322] [323] F((P-1)ûF),C,PF [324] :end [325] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [326] ¦•F ¦ debug [327] :end [328] :if T [329] Ff~F [330] :end [331] :end [332] [333] ¦ Discard invalid names [334] [335] C•NC [2]F [336] :if 4îC [337] N(C=4)/F [338] •'*** Invalid name',(1=ûN)'s:',ôN [339] F(C†4)/F [340] :end [341] [342] ¦ Discard shadowed names [343] [344] L•IDLOC [2]F ¦ what are names [345] L0 ý1L ¦ disregard global level [346] CL^.=ý1 [347] :if 0îC [348] N(~C)/F [349] •'*** Shadowed:',ôN [350] FC/F [351] :end [352] [353] ¦ Discard non-functions [354] [355] C3=•NC [2]F [356] :if 0îC [357] N(~C)/F [358] •'*** Not function',(1=ûN)'s:',ôN [359] FC/F [360] :end [361] [362] ¦ Discard locked functions [363] [364] k•EX 'C' [365] k•DEF [2] 'ZC F' "Z0=•first û•CRL F,'[0]'" ¦õ C ¦ locked? [366] BCF ¦ yuck, but I wanted to get this check out of the function loop [367] k•EX 'C' [368] :if 1îB [369] •'* Locked function',(1=+/B)'s:',ôB/F [370] F(~B)/F [371] :end [372] [373] ¦ All underscored variables are used as global constants below [374] [375] T0 ¦ Accumulate hits [376] E0 ¦ Accumulate lines [377] U0 ¦ Accumulate functions [378] [379] NûF ¦ How many fns [380] [381] VñDEB •WSID [382] :if Vð'' [383] V'CLEAR WS' [384] :end [385] [386] •'Searching ',(ôN),' function',(N=1)'s in ',V,' ...' [387] [388] •WGIVE 0 ¦ let that message display [389] [390] L1: ¦¦¦ Inspect next function [391] [392] (0=ûF)ûL9 ¦ Done? [393] [394] N1F  F1F ¦ N function name [395] [396] V•VR N [397] [398] Assert 0†ûV [399] [400] ¦¦¦ Search •VR [401] [402] H(UP V) •SS t ¦ The heart of the matter [403] (1îH)L1 ¦ Bail out if no raw hits [404] [405] ¦¦¦ Syntactic filter [406] [407] SYNL1 ¦õ H H V a q t  (1îH)L1 [408] [409] ¦¦¦ Filter for APL / quoted strings / comments [410] [411] P1,ý1V •SS •TCNL,'[' ¦ Partition on "[" (with trailing CRs); force header line [412] P[ý5+ûV]1 ¦ Force end of last line [413] [414] FILTL1 ¦õ H H P V [415] [416] ¦¦¦ Check valence [417] [418] W'' ¦ warnings [419] L+\P ¦ function line numbers [420] [421] :for I :in H/âûH [422] [423] eL[I] ¦ line number [424] s(e=L)/V ¦ the line [425] sý1s ¦ drop cr [426] j1+I-Lâe ¦ index within line [427] ksâ']' ¦ find end of [999] [428] sks ¦ drop line number [429] jj-k ¦ adjust pointer within line [430] [431] c(j+ý1+ût)s ¦ just after the hit [432] c(ú\c†' ')/c ¦ dlb [433] c•first c ¦ first non-blank char to right of symbol [434] :if cî'/ë\§.' ¦ check following char [435] ¦ operator, so dyadic [436] H[I]v=2 [437] :continue [438] :end [439] [440] p(j-1)s ¦ up to the hit [441] cèp [442] c(ú\c†' ')/c ¦ dlb [443] k•first c ¦ first non-blank char to left of symbol [444] [445] :if kî' ¦:([' ¦ begin line/stmt/comment, label, assignment, open paren/bracket [446] :orif kî' !#$%&*+,-/;<=>?\^{}~†’•—˜ž¦§-©+þâåæçèéêëíîïðòóôõöøùúûüþ' [447] :orif kî'ì§@`|€‚ƒ„…‡ˆ‰Š‹ŒŽ“”–™š›œŸ ¡¢£¤¥¨ª«¬­®¯ÀÁÂÃŽÅÆ€ÈÊËÌÍÎÏ¥ÒÓÔÕ™ØÙÚÛšÝßàáãä' [448] ¦  these could be in quotes/comments [449] ¦ monadic [450] H[I]v=1 [451] :continue [452] :end [453] [454] :if k='.' ¦ inner/outer product (could also be 1.â3 but that works out okay) [455] :orif k='' ¦ numeric constant [456] :orif k=')' ¦ parenthesized expression [457] ¦ dyadic [458] H[I]v=2 [459] :continue [460] :end [461] [462] ¦ If there's a quote to the left, we cannot be sure what to make of it: [463] ¦ õ'foo 9' ¦ monadic [464] ¦ 'abc' foo 9 ¦ dyadic [465] ¦ But this is pretty annoying when searching for monadic epsilon [466] ¦ õ'îB' ¦ monadic [467] ¦ 'A'îB ¦ very common example of dyadic use! [468] [469] :if kî'"''' [470] ¦WW,•tcnl,'* Quote to left of hit below, so not sure about valence' [471] ¦:continue [472] ¦ Can we solve this by looking for opening vs. closing quotes? [473] gQClosing p ¦ flag closing quotes [474] :if g[(pî'"''') IotaLast 1] ¦ if ours is a closing quote [475] H[I]v=2 ¦ dyadic [476] :else [477] H[I]v=1 ¦ monadic [478] :end [479] :continue [480] :end [481] [482] :if k=']' ¦ indexing or axis A[...] M+[2]V ,[]V [483] e+\(cî'[]')’ý1*cî'[' [484] eeâ0 ¦ the matching opening bracket [485] eec [486] e(ú\e†' ')/e ¦ dlb [487] e•first e ¦ char to left of [ [488] :if eî' !#$%&*+,-/;<=>?\^{}~†’•—˜ž¦§-+þâåæçèéêëíîïðòóôõöøùúûüþ' [489] H[I]v=1 ¦ axis from previous function [490] :else [491] H[I]v=2 ¦ indexed expression [492] :end [493] :continue [494] :end [495] [496] ¦ So, token on left ends with a letter or a digit [497] Assert kî'_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ‘ñ1234567890' [498] ¦ We need to know if it's a numeric constant or a name [499] cèc ¦ restore order [500] kTokenize c [501] k(ûk)k ¦ last token [502] :if (,1)ð•VI k ¦ numeric constant [503] H[I]v=2 [504] :continue [505] :end [506] :if ':'=•FIRST k ¦ control structure keyword [507] H[I]v=1 [508] :continue [509] :end [510] [511] ¦ It's an identifier name [512] [513] :if kðN ¦ same as ourself? (AFOO FOO B) [514] H[I]v=1 [515] :continue [516] :end [517] [518] e(ý1+Vâ•TCNL)ûV ¦ header line [519] :if ( k)î' ;' WD e ¦ localized in header? almost certainly a variable [520] H[I]v=2 [521] :continue [522] :end [523] [524] eý1,•IDLOC k ¦ classification at global level: 0=undef 1=fn 2=var 8=lab [525] ¦ 8=lab is not possible at global level [526] :if eî1 2 ¦ fn means monadic, var means dyadic [527] :if e=1 ¦ function [528] :andif '•'†•FIRST k ¦ •AT doesn't work on system fns [529] :andif 1 0ð21 •AT k ¦ explicit niladic [530] e2 ¦ treat like a variable [531] :end [532] H[I]v=e [533] :continue [534] :end [535] [536] ¦ Undefined name [537] ¦ Since we can't tell, call it a hit to be on the safe side [538] ¦ So just leave H alone [539] [540] WW,•tcnl,'* Undefined name below, so not sure about valence: ',k [541] [542] :end [543] [544] (1îH)L1 ¦ Bail if no hits remain [545] [546] ¦¦¦ Got some hits [547] [548] L+/H ¦ Number of hits [549] TT+L ¦ Accumulate total hits [550] HP ORRED H ¦ Flag lines with hits [551] EE++/H ¦ Accumulate lines with hits [552] UU+1 ¦ Accumulate functions with hits [553] [554] ¦ Add function name to result [555] [556] XX, N ¦ Add to result [557] [558] ¦ Next function if result-only mode [559] [560] xûL1 [561] [562] ¦¦¦ Display hits [563] [564] •'==> ',N,' (',(ôL),')',W ¦ Name of function, total hits, warnings [565] [566] HH/âûH ¦ Line numbers to display (origin 1) [567] PP/âûP ¦ Partition starts [568] L(1P,1+ûV)-P ¦ Partition lengths [569] PP[H]-1 ¦ Compensate for +â with •IO1 [570] LL[H]-1 ¦ Not incl trailing CR [571] B1 [572] L8: [573] ¦ APL+Win: Show fn name too so can double-click to edit at that line [574] •N,V[P[B]+âL[B]] ¦ Faster than take/drop approach [575] BB+1 [576] (BóûH)ûL8 [577] •WGIVE 0 ¦ allow display [578] L1 [579] [580] L9: ¦ Finished last function [581] [582] xû0 ¦ Quit if result-only mode [583] SINK•EX 'X' [584] •'==> Totals: ',(ôT),' hit',(T=1)'s on ',(ôE),' line',(E=1)'s',(U>1)/' in ',(ôU),' functions' ì O€US< ee ì CMDVARFIND T;b;c;D;H;N;n;R;S;v;V;X;•ELX [1] ¦ Search variables for target sub-array T [2] ¦ Basically, for every variable V, we execute VT and show matches [3] [4] ¦ ]VARFIND 'FOO' ¦ Search all vars for string 'FOO' [5] ¦ ]VARFIND 2 4ûâ8 ¦ Search all vars for numeric matrix [6] ¦ ]VARFIND 'FOO' /V=V1 V2 ¦ Only look in named vars [7] ¦ ]VARFIND 'FOO' / ¦ Suppress display; return variable names [8] [9] ¦ Note that unlike most user commands, the argument is executed! [10] ¦ Use ]VARFIND 'FOO' [11] ¦ NOT ]VARFIND FOO [12] [13] ¦ Left argument is variable list: [14] ¦ Empty or undefined means search all variables in active ws [15] ¦ List of names means search just those variables [16] ¦ (matrix, items, or vector delimited by spaces) [17] ¦ Special characters may be included to modify display: [18] ¦  means don't display hits; return var names as explicit result [19] ¦ To do some day (for character targets): [20] ¦ ï means case-insensitive matching [21] ¦ means syntactic matches only [22] [23] ¦ Requires: VARFIND2 FFAW [24] [25] ¦ 30 Jun 2002 Rex Swain, Independent Consultant, www.rexswain.com [26] ¦ 14 Jan 2003 Adapted for UCMD [27] ¦ 08 May 2003 Fixed option parsing [28] ¦ 27 Jul 2003 Correct •SI/•IDLOC alignment [29] ¦ 26 Mar 2005 Evlevel-neutral [30] ¦ 29 Aug 2005 Most recent minor update [31] [32] TôT ¦ arg might be numeric in development mode [33] [34] :if '/'îT ¦ any possible options? [35] D•FIRST T~' ' ¦ leading non-blank character [36] :if Dî'''"' ¦ quotes will complicate matters [37] bT=D [38] bbú†\b ¦ flag quotes and contents [39] S(~b)/T ¦ after target [40] Tb/T ¦ target [41] :else ¦ no quotes [42] ST [43] T(^\T†'/')/T ¦ delete all options [44] :end [45] RS ñGETOPT '/' ¦ result-only option [46] VS ñGETOPT '/V' ¦ var names option [47] :else [48] RV0 0û'' [49] :end [50] [51] :if T^.=' ' [52] ñOUT 'For help, execute',•tcnl,' ]VARFIND ?' [53] 0 [54] :end [55] [56] TõT ¦ execute [57] [58] V,' ',ô,V ¦ force to simple char vector [59] [60] :if 1=ûûR ¦ suppress display, just return result? [61] R0 ¦ so R quits [62] :else [63] R ¦ so R does nothing [64] :end [65] [66] S•SI[;1] ¦ first column of )SI [67] S(~Sî'õ•><')/S ¦ ditch •SI levels that don't have matching •IDLOC columns [68] XSâ']' ¦ how much UCMD crap is there [69] XX*Xó•FIRST ûS ¦ or 1 if no ] (non-UCMD) [70] [71] :if V^.=' ' ¦ default to all vars [72] [73] bcDHNnv0 ¦ define all locals so they appear in •NL [74] [75] ¦ V•NL 2 ¦ all vars [76] ¦ ¦ Since we used •NL, we can skip check for invalid names [77] ¦ ¦ Only possible problems are global vars shadowed by our local vars [78] ¦ ¦ Don't warn if shadowed object is not a var -- we wouldn't have searched it anyway! [79] ¦ n•IDLOC V ¦ state of each name [80] ¦ c2=n[;•IO] ¦ flag our local vars [81] ¦ n0 1cën ¦ drop our local classification [82] ¦ n(,<\ý1†n)/,n ¦ next-most-local classification [83] ¦ nn=2 ¦ flag those that are global vars [84] [85] ¦ 14 Jan 2003 [86] ¦ It's possible that the user command facility has created a local function [87] ¦ that is shadowing a global variable. In order to detect and report this, [88] ¦ we need to look at all defined names, not just variable names. [89] [90] V•NL 1 2 3