±Þÿt6æÿt6H, P,, æÿt6è4 ¤ Hè0p„˜¬ÀÔ\H,Dx” ”( Dl ´ ô|”Ðd.„è>ð]tdtdÈy´|{¸4}ÈüXZTÜXd4x8ðehž€¡ / ÐE0|¬-\6ÄS̉ä°¥ø¨Å8 àÐôÔÔ;Èh¼0Í€¿°Œ¨ÊXW” ìdœ ˆoÇ6¤–4Íü0æt¤ö Äù|@ `¼ÚôØ4ô(xlFäP\d^lÐ_è¸`Ôb@hÔèmx`nìLotÀop0pÄôq ô~ø¤¸È‚h0ƒÔ‡HL¤ì8¹ô,Á@l¬ь¤Ó<àÕ@ Öd„Ö,°Öd×xŒ×@Ì×<Ø08Ø,dØ,Ø8ÈØ$ìØ<(Ù,TÙ,€Ù8¸Ùˆ@ÚˆÈÚˆPÛ$tÛ˜ Ü\hÜ,”Ü0ÄÜ<Ý00Ý”ÄÝ,ðݘˆÞDÌÞÔ àHèã€Þÿt6€Þÿt6œ€åÿt6€Þÿt6€åÿt6€åÿt6€åÿt6€åÿt6€åÿt6€æÿt6€æÿt6 5 UCMDS €Þÿt6€Þÿt6€Þÿt6Ô€Þÿt6Ü ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€æÿt6€°¯®€åÿt6˜BBUser-defined commands file, version 3.1, created 2008 12 13 12 9 2€Þÿt6UddAlign Comments via the Clipboard Align Comments via the Clipboard Invoked as an APL+Win Tool by a special key in an )EDIT session Use OptionsþTools to assign ]ACCLIP to a key such as F7 Then select some function lines in the editor and press F7 Position of lamp in first line with a comment establishes the alignment position Use ]ACCLIP /UP (assigned to perhaps Shift+F7) to work from the bottom up 08 Feb 2006 Rex Swain, Independent Consultant, www.rexswain.com 13 May 2007 Drop trailing NULs from ClipGet Another way to assign this to a function key is with: '#' •WI 'PF' 118 ']ACCLIP' ¦ F7 '#' •WI 'PF' 100118 ']ACCLIP /UP' ¦ Shift+F7 See APL+Win Windows Interface help for "Keyboard Events" for Virtual Key Codes. Function keys F1-F24 are 112-135; add Shift=100000, Ctrl=200000, Alt=400000. But these are not saved in your APLW.INI file.€Þÿt6œ}} ì RP ANDSCAN B;A [1] ¦ Partitioned ^\ [2] RBóP  A~R/B  R~†\R\A†ý10,A [3] (•FIRST P)û0  R[âý1+Pâ1]0 ì €Þÿt6¤..Read a native file and assign the variable in it Read a native file and assign the variable in it Use after ]DIFF and save from Araxis Merge to read file and assign changed variable See also: ]DEF Syntax: ]ASSIGN filename We assume that the variable was originally either a simple character matrix or a simple character vector with •TCNL-delimited lines. If the variable exists in the active ws, we check its rank and re-assign it accordingly; otherwise we ask. 01 May 2003 Rex Swain, Independent Consultant, www.rexswain.com 05 May 2003 Correct modulo translation 27 Jul 2003 Correct •SI/•IDLOC alignment 07 May 2005 Remove trailing •tcnl, to avoid trailing blank line 14 May 2005 Remove trailing '.apl' from file/variable name, for ]kedit 11 Mar 2006 Also handle tn#cn or tn,cn -- replace file component€Þÿt6,Automatically )SAVE a copy of the active workspace every so often Automatically )SAVE a copy of the active workspace every so often ]AutoSave ¦ turn it on ]AutoSave /on ¦ turn it on ]AutoSave /off ¦ turn it off ]AutoSave /i ¦ query save interval ]AutoSave /i=5 ¦ set save interval (in minutes; default is 5) ]AutoSave /q ¦ query if AutoSave is running ]AutoSave /log ¦ view log file Every interval, the active ws is saved with .BAK appended to the wsid. I don't want to actually save the active ws (like Ctrl+Shift+S). Sometimes I )SAVE manually, do 15 minutes worth of editing, and then decide to abandon the whole thing. I want to be able to re-)LOAD and get back to my check point. I could save the active ws into a single backup ws, such as AUTOSAVE.W3. But I remember that I once lost a bunch of work by typing Alt,F,2 while thinking that another application had the focus, when in fact APL had the focus! If I did that while AutoSave was running, and the interval happened to tick right afterward, I could be left with not very useful backup. So I like using more than one name, even though it clutters up )WSLIB and the File MRU menu. A log file 'AutoSave.log' holds a record of all saves.  Do we really need this? Provides a way to confirm that it's running. If you execute '#' •wi 'Reset' that will kill the AutoSave timer. (The AutoSave timer will notify you that it is being deleted, but it will be gone nevertheless.) If you use a ]reset utility, you should consider turning AutoSave back on.  No, now this version detects attempts to delete it and restarts itself! A big problem with this Timer approach: if there is a suspension in your SI stack, it stops working because all callbacks are ignored while suspended! Periodic cleanup: ERASE *.BAK.W3 ERASE AutoSave.log 01 Dec 2006 Rex Swain, Independent Consultant, www.rexswain.com 28 Mar 2007 Don't save backup of backup€Þÿt6àà ì ZAV V;•IO [1] ¦ìindorcharAV charorind -- Convert chars to 0-origin •AV indices and vice versa [2] [3] :if 82=•DR V [4] Z•FIRST 82 323 •DR V [5] :else [6] •IO0 [7] Z•AV[V] [8] :end ì €Þÿt6Tff ì Assert a [1] ¦ Assert the truth [2] (^/1=•ENLIST a)û0 [3] •ERROR 'ASSERTION ERROR' ì RE€ßÿt6îîShow formats currently available from the Windows clipboard Show formats currently available from the Windows clipboard Use /F= option to return contents of specified format number Use /* option to display entire contents of all formats Use /M option to ]DISPLAY the CF_TEXT as a matrix 06 Apr 2003 Rex Swain, Independent Consultant, www.rexswain.com 21 Nov 2003 Use FFATC 26 Mar 2005 Evlevel-neutral 05 Jul 2005 Added /F= option 16 Jul 2005 Added /* option 23 Mar 2006 Added /M option+À€ßÿt6@»» ì CMDACCLIP A;B;C;D;E;F;G;H;I;J;K;KEY;L;M;N;Q;T;U;W;X [1] ¦ Align Comments via the Clipboard [2] ¦ Invoked as an APL+Win Tool by a special key in an )EDIT session [3] ¦ Use OptionsþTools to assign ]ACCLIP to a key such as F7 [4] ¦ Then select some function lines in the editor and press F7 [5] ¦ Position of lamp in first line with a comment establishes the alignment position [6] ¦ Use ]ACCLIP /UP (assigned to perhaps Shift+F7) to work from the bottom up [7] ¦ 08 Feb 2006 Rex Swain, Independent Consultant, www.rexswain.com [8] ¦ 13 May 2007 Drop trailing NULs from ClipGet [9] [10] ¦ Another way to assign this to a function key is with: [11] ¦ '#' •WI 'PF' 118 ']ACCLIP' ¦ F7 [12] ¦ '#' •WI 'PF' 100118 ']ACCLIP /UP' ¦ Shift+F7 [13] ¦ See APL+Win Windows Interface help for "Keyboard Events" for Virtual Key Codes. [14] ¦ Function keys F1-F24 are 112-135; add Shift=100000, Ctrl=200000, Alt=400000. [15] ¦ But these are not saved in your APLW.INI file. [16] [17] U1=ûûA ñGETOPT '/U' ¦ up mode? [18] [19] ¦ Search MSDN for "Virtual-Key Codes": [20] ¦ 16 = x10 = VK_SHIFT, SHIFT key [21] ¦ 17 = x11 = VK_CONTROL, CTRL key [22] ¦ 67 = x43 = C key [23] ¦ 86 = x56 = V key [24] ¦ We use negative to mean keyup (2 = x02 = KEYEVENTF_KEYUP) [25] [26] ¦ Not sure why we release the Shift key first [27] ¦ Oh, perhaps that's in case the tool key is a shift key? [28] [29] K•DEF [2] "KEY Y;K" "K•WCALL 'keybd_event' (þY) 0 (2’Y<0) 0" ¦õ KEY K [30] KEY  ý16 17 67 ý67 ý17 ¦ copy with Ctrl+C [31] •WGIVE 0 [32] [33] ¦ Get clipboard text [34] [35] MClipGet 1 ¦ 1=CF_TEXT [36] M•AV[ñAV2ANSIâM] [37] ('¦'îM)0 ¦ quit if no comments [38] [39] MM~•TCLF,•TCNUL ¦ change CR,LF to CR; drop trailing NULs [40] T•TCNL†ý1M ¦ remember if there was not a trailing CR [41] MM,Tû•TCNL ¦ add trailing CR if necessary [42] Mý1 (ý1èM=•TCNL) •PENCLOSE M [43] [44] F'‘ñabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ¦ begin label name [45] GF,'_0123456789' ¦ continue [46] [47] C0 ¦ indent [48] H0 ¦ any changes? [49] LâûM ¦ line indices [50] :if U ¦ up mode? [51] LèL ¦ just do them backwards [52] :end [53] [54] :for N :in L [55] [56] XNM [57] [58] :if ~'¦'îX [59] :continue [60] :end [61] [62] ¦ Don't align if comment is only thing on line [63] [64] EDLB X ¦ temp [65] :if '¦'=1E ¦ lamp is first non-blank char? [66] :continue [67] :end [68] [69] ¦ Don't align if comment follows a line label [70] [71] IXâ'¦' ¦ first lamp [72] [73] :if I>Xâ':' ¦ 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] ì ì €ßÿt6 òò ì CMDAUTOSAVE A;ft;g;i;k;tm;w;x;•wself;•wsid;•ELX [1] ¦ Automatically )SAVE a copy of the active workspace every so often [2] [3] ¦ ]AutoSave ¦ turn it on [4] ¦ ]AutoSave /on ¦ turn it on [5] ¦ ]AutoSave /off ¦ turn it off [6] ¦ ]AutoSave /i ¦ query save interval [7] ¦ ]AutoSave /i=5 ¦ set save interval (in minutes; default is 5) [8] ¦ ]AutoSave /q ¦ query if AutoSave is running [9] ¦ ]AutoSave /log ¦ view log file [10] [11] ¦ Every interval, the active ws is saved with .BAK appended to the wsid. [12] [13] ¦ I don't want to actually save the active ws (like Ctrl+Shift+S). Sometimes I [14] ¦ )SAVE manually, do 15 minutes worth of editing, and then decide to abandon the [15] ¦ whole thing. I want to be able to re-)LOAD and get back to my check point. [16] [17] ¦ I could save the active ws into a single backup ws, such as AUTOSAVE.W3. But [18] ¦ I remember that I once lost a bunch of work by typing Alt,F,2 while thinking [19] ¦ that another application had the focus, when in fact APL had the focus! If I [20] ¦ did that while AutoSave was running, and the interval happened to tick right [21] ¦ afterward, I could be left with not very useful backup. So I like using more [22] ¦ than one name, even though it clutters up )WSLIB and the File MRU menu. [23] [24] ¦ A log file 'AutoSave.log' holds a record of all saves. [25] [26] ¦  Do we really need this? Provides a way to confirm that it's running. [27] [28] ¦ If you execute '#' •wi 'Reset' that will kill the AutoSave timer. [29] ¦ (The AutoSave timer will notify you that it is being deleted, but it will [30] ¦ be gone nevertheless.) If you use a ]reset utility, you should consider [31] ¦ turning AutoSave back on. [32] [33] ¦  No, now this version detects attempts to delete it and restarts itself! [34] [35] ¦ A big problem with this Timer approach: if there is a suspension in your SI [36] ¦ stack, it stops working because all callbacks are ignored while suspended! [37] [38] ¦ Periodic cleanup: ERASE *.BAK.W3 [39] ¦ ERASE AutoSave.log [40] [41] ¦ 01 Dec 2006 Rex Swain, Independent Consultant, www.rexswain.com [42] ¦ 28 Mar 2007 Don't save backup of backup [43] [44] tm'tmAutoSave' ¦ timer name [45] ftý925195289 ¦ log file tie number [46] [47] :if A^.=' ' [48] :orif 1=ûûA ñGETOPT '/ON' [49] :orif 1=ûûA ñGETOPT '/DELETED' [50] [51] :if ’ûtm •wi 'self' [52] :if tm •wi 'opened' [53] •'AutoSave is already running' [54] :else [55] tm •wi 'Open' [56] •'AutoSave opened' [57] :end [58] L1 [59] :end [60] [61] '#' •wi 'onDestroy' "•ucmd ']SystemDestroy'" [62] [63] •wselftm •wi 'Create' 'Timer' [64] •wi 'onTimer' "•UCMD ']AutoSave /SAVE'" ¦õ •UCMD CMDAUTOSAVE [65] •wi 'onClose' "•wres0  •'AutoSave's Timer refusing Close; to really stop it, ]AutoSave /off'" ¦ Close would stop the timer [66] •wi 'onDelete' "'#' •wi 'Defer' '•ucmd '']AutoSave /DELETED'''" [67] [68] i•wcall 'W_Ini' '[UCMDSREX] AutoSave' [69] :if (,1)ð•VI i [70] i1•FI i [71] :else [72] i5 [73] :end [74] •wi 'interval' (i’60’1000) ¦ minutes to milliseconds [75] [76] ¦ Log file [77] g•first /•wcall 'GetModuleFileName' '' (255û•tcnul) 255 ¦ d:\path\aplw.exe [78] g(èú\èg='\')/g ¦ d:\path\ [79] gg,'AutoSave.log' [80] •wi '‘logfile' g [81] [82] :try [83] g •xncreate ft ¦ it's okay for this to fail (already exists) [84] ('APL+Win ]AutoSave log file',•tcnl,•tclf) •nappend ft [85] :catchall ¦ :try requires at least one :catch [86] ¦ noop [87] :end [88] [89] :try [90] g •xntie ft ¦ this must work [91] :catchall [92] •'*** Could not tie log file ',g,' : ',(^\•TCNL†•DM)/•DM [93] 0 [94] :end [95] [96] ¦ Note that the user command processor will untie the log file [97] [98] :if 1=ûûA ñGETOPT '/DELETED' [99] •'AutoSave restarted after being deleted; to really stop it, ]AutoSave /off' [100] :else [101] •'OK, AutoSave is now running' [102] :end [103] [104] :elseif 1=ûûA ñGETOPT '/SAVE' [105] [106] wñDEB •WSID [107] [108] :if '.BAK'ðý4w [109] •'* FYI, ]AutoSave not saving backup of backup' [110] 0 [111] :end [112] [113] ww,(wð'')/'CLEARWS' [114] ww,'.BAK' [115] [116] x(4 0 3 0 3 0 3 0 3 0 3 0 4 0ô•TS),' saving ',w,•tcnl,•tclf [117] [118] g•wi '‘logfile' [119] :try [120] g •xntie ft ¦ file has probably been untied by ucmd processor [121] x •nappend ft [122] :catchall ¦ file might be erased [123] :try [124] g •xncreate ft [125] ('APL+Win ]AutoSave log file',•tcnl,•tclf) •nappend ft [126] x •nappend ft [127] :catchall [128] •'*** ]AutoSave unable to write to log file ',g [129] :end [130] :end [131] [132] •ELX'',ôL9 ¦ in case •SAVE fails (eg read-only drive) [133] [134] 'RESET' •SAVE w ¦õ •wsid ¦ this changes wsid, but •wsid is localized! [135] [136] ¦ Note that •SAVE acts like )SAVEOVER [137] [138] •wi '‘lastsave' •TS [139] [140] :elseif 1=ûûA ñGETOPT '/OFF' [141] [142] :if ’ûtm •wi 'self' [143] tm •wi 'onDelete' '' ¦ avoid warning [144] tm •wi 'Delete' [145] •'OK, AutoSave turned off' [146] :else [147] •'AutoSave was not running' [148] :end [149] [150] :elseif 1=ûûiA ñGETOPT '/I' ¦ note embedded i [151] [152] :if i^.=' ' [153] i•wcall 'W_Ini' '[UCMDSREX] AutoSave' [154] :if ~(,1)ð•VI i [155] iô5 [156] :end [157] •'AutoSave interval is ',(ôi),' minutes' [158] 0 [159] :end [160] [161] :if ~(,1)ð•VI i [162] •'*** Invalid AutoSave interval: ',i [163] 0 [164] :end [165] [166] i1•FI i [167] k•wcall 'W_Ini' ('[UCMDSREX] AutoSave=',ôi) [168] [169] :if ’ûtm •wi 'self' [170] tm •wi 'interval' (i’60’1000) [171] •'OK, AutoSave interval changed to ',(ôi),' minutes' [172] :else [173] •'OK, AutoSave interval set to ',(ôi),' minutes (although AutoSave is not running now)' [174] :end [175] [176] :elseif 1=ûûA ñGETOPT '/Q' [177] [178] :if ’ûtm •wi 'self' [179] :andif tm •wi 'opened' [180] itm •wi 'interval' [181] •'AutoSave is running; interval is ',(ôiö60’1000),' minutes' [182] L1 [183] :else [184] •'AutoSave is not running' [185] :end [186] [187] :elseif 1=ûûA ñGETOPT '/LOG' [188] [189] :if ’ûtm •wi 'self' [190] :andif tm •wi 'opened' [191] itm •wi 'interval' [192] •'AutoSave is running; interval is ',(ôiö60’1000),' minutes' [193] g•wi '‘logfile' [194] :else [195] •'Note: AutoSave is not running' [196] g•first /•wcall 'GetModuleFileName' '' (255û•tcnul) 255 ¦ d:\path\aplw.exe [197] g(èú\èg='\')/g ¦ d:\path\ [198] gg,'AutoSave.log' [199] :end [200] [201] k•wcall 'ShellExecute' 0 'open' g 0 0 'SW_SHOWNORMAL' ¦ probably NotePad [202] [203] :else [204] [205] •'*** Unanticipated CMDAUTOSAVE argument:' A [206] [207] :end [208] [209] 0 [210] [211] L1: [212] [213] xtm •wi '‘lastsave' [214] (xð0)û0 ¦ might be running but nothing saved yet [215] i0 12 30 24 60 ¦ approximate MINBASE ! [216] i(iæý2•TS)-(iæý2x) [217] •'Last save: ',(4 0 3 0 3 0 3 0 3 0 3 0 ôý1x),' (apx. ',(ôi),' minutes ago)' [218] 0 [219] [220] L9: [221] [222] •'*** •SAVE failed: ',(^\•DM†•TCNL)/•DM [223] tm •wi 'onDelete' '' ¦ avoid warning [224] tm •wi 'Delete' [225] •'*** AutoSave turned off' [226] ì €ßÿt6__ ì 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] ì €ßÿt6‘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€ßÿt6ŸŸ ì 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] ì €ßÿt6 ¢¢ ì 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 ì €ßÿt6±± ì 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€ßÿt6CZCZ ì CMDDIFF A;B;C;D;E;F;G;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 APLFONT as the Araxis Merge file comparison font. [53] ¦ Use something like ]DIFF /AMFONT=10.Courier New to return to a non-APL font. [54] [55] ¦ Requires: Araxis Merge 2001, Standard Edition, version 6.0 [56] ¦ or: Araxis Merge Standard Edition, version 6.5 [57] ¦ or: Araxis Merge Standard Edition, version 7.0 (aka 2007) [58] ¦ See [59] [60] ¦ See also ]DEF and ]ASSIGN which will define changed objects in the active ws [61] [62] ¦ To do: [63] ¦ Use XSetPanelTitles with Merge to simplify file names? [64] ¦ Make it work with free WinMerge (www.winmerge.org)? [65] [66] ¦ After similar by JVM and Patrick Parks [67] ¦ 06 Apr 2003 Rex Swain, Independent Consultant, www.rexswain.com [68] ¦ 16 Apr 2003 Added /F support; EVLEVEL-neutral [69] ¦ 25 Apr 2003 Allow ]COMP syntax [70] ¦ 29 Apr 2003 Added /ERASE (such as it is) [71] ¦ 30 Apr 2003 Added /ULIST and /U [72] ¦ 01 May 2003 Maximize AM if "Maximize application on start-up" [73] ¦ 27 Jul 2003 Correct •SI/•IDLOC alignment [74] ¦ 07 Jun 2005 Added one-name compare, active ws vs. saved ws [75] ¦ 06 Oct 2005 Don't allow -options (because filespecs may contain hyphens) [76] ¦ 13 Mar 2006 Prompt to save changes made via Merge (suggested by Patrick Parks) [77] ¦ Use APL font specified in APLW.INI [UCMDSREX] [78] ¦ Added /AMFONT= to reset Araxis Merge font [79] ¦ 10 May 2007 Query MergeXX.Application and remember in APLW.INI [DIFF] [80] [81] ‘elx•ELX [82] [83] ADEB,ôA [84] [85] (Að'::')ûLT ¦ kludge for internal timer callback [86] (Að'')ûL9 ¦ empty arg? [87] [88] ¦E'ActiveObject Merge2000.Application' ¦ Araxis Merge 2001 (version 6.0) [89] ¦E'ActiveObject Merge65.Application' ¦ Araxis Merge version 6.5 [90] ¦E'ActiveObject Merge70.Application' ¦ Araxis Merge version 7.0 (aka 2007) [91] [92] E•wcall 'W_Ini' '[DIFF] ActiveObject' [93] :if E^.=' ' [94] :for V :in '70' '65' '2000' [95] e'Merge',V,'.Application' [96] •'Searching for ActiveObject ',e,' ...' [97] •wgive 0 [98] ¦  Each query takes 0.3 seconds on my system, so remember answer in INI file [99] M'#' •wi 'XInfo' e [100] :if ’1ûM [101] •'Got it, and remembering it in INI file' [102] Ee [103] k•wcall 'W_Ini' ('[DIFF] ActiveObject=',E) [104] :leave [105] :end [106] :end [107] :if E^.=' ' [108] •'*** ]DIFF cannot find MergeXX.Application' [109] 0 [110] :end [111] :end [112] [113] X•FIRST /•wcall 'GetModuleFileName' '' (255û•tcnul) 255 ¦ C:\APLWin50\aplw.exe [114] D(èú\èX='\')/X ¦ C:\APLWin50\ [115] D(D,'Diff1\') (D,'Diff2\') ¦ C:\APLWin50\Diff1\ C:\APLWin50\Diff2\ [116] F2û '' ¦ APL file names [117] S2û '' ¦ ANSI file names [118] [119] CñUCASE A [120] ('/ERASE' ð C)ûL8 ¦ cleanup? [121] ('/ULIST=' ð7C)ûL7 ¦ set ucmd file list [122] ('/ULIST' ð6C)ûL6 ¦ query ucmd file list [123] ('/AMFONT='ð8C)ûL5 ¦ reset Merge font [124] [125] :if ';'îA ¦ semicolon makes it easy [126] ¦ V(A†';') A ¦ EV2 [127] V1(1,A=';')•PENCLOSE ';',A ¦ EV neutral [128] (2=ûV)L9,L2 [129] :end [130] V1(1,A=' ')•PENCLOSE ' ',A [131] (3ûV)L1 L2 L3 ¦ how many words [132] [133] L1: ¦ One word [134] VV, DEB •WSID,' =' [135] L2 [136] [137] L3: ¦ Do it the hard way [138] ¦  begin code from CMDCOMP [139] AñMATRIFY A  MûûA  V0 2û''  T  Y1 0 0 0  I1 [140] ñ1: ¦ next word [141] JY[I]  (J>M)ûñ10 ¦ no more words? [142] Y[I+1]J+1  XA[J;]  VVžX ''  TT,0 [143] ñ2: [144] T[I]•NC X  (T[I]î0 2 3)ûñ4 [145] (0=X ñMATIOTA '=')ûñ3 [146] (I=1)ûñ9 [147] X•FIRST V[I-1;1]  A[J;]X  V[I;1] X  ñ2 [148] ñ3: [149] ¦ B'õ_#,:\.'îX  (1îB)ñ9  T[I]1B/2 2 3/10 12 17 [150] ñ8 [151] ñ4: [152] CA[MJ+1;]  (('/'=1C)^'F='ðñUCASE 21C)ñ5 [153] C3C  Y[I+1]J+2  ((,1)ð•VI C)ñ6 [154] Y[I+1]J+3  CC,' ',A[MJ+2;] [155] V[I;2] ' /F=',C ¦ RHS [156] ñ6 [157] ñ5: [158] ¦(((1C)î'/-')^'F'=ñUCASE 11C)ñ7 [159] cñUCASE 2C  (( c)î'/F' '/U')ñ7 ¦ RHS [160] Y[I+1]J+2 [161] ¦ CñUFILES[1;] [162] V[I;2] ' ',c ¦ RHS [163] ñ8 ¦ RHS [164] ñ6: [165] ¦ õ'ñF',(ôI),'ñC'  T[I]13 [166] V[I;2] ' /F=',C ¦ RHS [167] ñ8 [168] ñ7: [169] (T[I]î2 3)ûñ8  •'Undefined object: ',X  0 [170] ñ8: [171] II+1  (Ió3)ûñ1 [172] N1ûûV  (M3)ûñ9 [177] N1ûûV  (N>1)ûñ11 [178] (T[1]†13)ûñ9 [179] AAžA[1;]  N2  TT,•NC A[1;] [180] (~(ý1T)î0 2 3)ûñ9 [181] VVž(A[1;]) '' [182] ñ11: [183] ¦  end code from CMDCOMP [184] [185] VDEB,/V ¦ this is the only thing we take away from all that [186] (2†ûV)ûñ9 [187] [188] L2: [189] [190] v•SI[;1] ¦ first column of SI [191] v(~vî'õ•><')/v ¦ ditch •SI levels that don't have matching •IDLOC columns [192] Uvâ']' ¦ how much UCMD crap is there [193] UU*Uóûv ¦ or 1 if no ] (non-UCMD) [194] [195] C' ' ¦ name classes [196] K0 0 ¦ variable ranks [197] [198] :for I :in â2 ¦õ I [199] [200] vIV [201] ((vî'ì')/v)' ' ¦ might be from ]SYMFIND [202] vDEB v ¦ possibly problem here with LFNs...? [203] e'Problem with argument ',(ôI),' ... ',v,' ... ' [204] •ELX'•e,(^\•DM†•TCNL)/•DM  0' [205] u'' ¦ /F= and ucmd fileid [206] :if '/'îv [207] iý1+vâ'/' [208] uDLB iv ¦ all options [209] vDTB iv [210] :if ~(11u)î'fFuU' [211] •e,'Invalid option: ',u [212] 0 [213] :end [214] :end [215] iý1+(èv)â' ' ¦ length of last word (object name) [216] j(-i)v ¦ object name [217] w(-i+1)v ¦ wsid [218] [219] :if I=1 [220] (W J)w j [221] :elseif wð,'=' [222] wW [223] :elseif jð,'=' [224] jJ [225] :end [226] [227] :if ’ûu ¦ ----- get from ucmd file ----- [228] [229] :if (11u)î'fF' ¦ '/F'ð2u [230] [231] :if wú.†' ' [232] •e,'Cannot specify a WSID and /F= too' [233] 0 [234] :end [235] [236] c•UCMD ']UNAMES ',j,' ',u ¦ possible FILE NOT FOUND here [237] c(,c)~' ' [238] :if ú/c •SS '' [239] •e,'Object not found in UCMD file' [240] 0 [241] :end [242] cý1c [243] :if ~cî'ì' [244] •e,'Unanticipated name class: ',c [245] 0 [246] :end [247] [248] :elseif (11u)î'uU' ¦ '/U'ð2u [249] [250] :if wú.†' ' [251] •e,'Cannot specify a WSID and /U too' [252] 0 [253] :end [254] [255] m•wcall 'W_Ini' '[DIFF] ULIST' [256] :if m^.=' ' [257] •'ULIST not set; use ]DIFF /ULIST=...' [258] 0 [259] :end [260] ¦ m(m†';') m ¦ EV2 [261] m1(1,m=';')•PENCLOSE ';',m ¦ EV neutral [262] v1 ¦ not found [263] :for i :in m [264] c•UCMD ']UNAMES ',j,' /F=',i ¦ possible FILE NOT FOUND here [265] c(,c)~' ' [266] :if ú/c •SS '' [267] :continue [268] :end [269] cý1c [270] :if ~cî'ì' [271] •e,'Unanticipated name class: ',c [272] 0 [273] :end [274] v0 ¦ found [275] :leave [276] :end [277] :if v [278] •e,'Object not found in ULIST files' [279] 0 [280] :end [281] u'/F=',i [282] [283] :else [284] [285] •'Unanticipated u: ',u [286] 0 [287] [288] :end [289] [290] v•UCMD ']UREAD ',j,' ',u [291] [292] :if c='ì' ¦ function [293] k•DEF[2]('rpeek v;',j) 'r•CR •DEF v' ¦õ peek ¦ convert •VR to •CR [294] rpeek v [295] :else ¦ variable [296] K[I](82=•DR v)’ûûv [297] rôv [298] :end [299] [300] C[I]c ¦ remember class [301] [302] :elseif ú/',#'îj ¦ ----- get from APL file ----- [303] [304] c~jî',#' [305] c•FI c\c/j [306] v•FREAD c [307] K[I](82=•DR v)’ûûv [308] rôv [309] C[I]'' ¦ note that we don't know the name or class of this object [310] [311] :elseif w^.=' ' ¦ ----- get from active ws ----- [312] [313] :if Uò(ý1†,•IDLOC j)â1 [314] •e,'Shadowed: ',j [315] 0 [316] :end [317] [318] :select •FIRST •NC j [319] :case 2 ¦ var [320] C[I]'' ¦ remember class [321] võj [322] K[I](82=•DR v)’ûûv [323] rôv [324] :case 3 ¦ fn [325] C[I]'ì' ¦ remember class [326] r•CR j [327] :else [328] •e,'Not found in active ws: ',j [329] 0 [330] :end [331] [332] w'Active Ws' ¦ for file name (don't use •wsid -- saved ws could be different) [333] [334] :else ¦ ----- copy from another ws ----- [335] [336] X 'rw peek j;v;•ELX;',j [337] XX, 'rý99' [338] XX, '•ELX"0"' [339] XX, 'r•first j •copy w' [340] XX, ':select r' [341] XX, ':case 1' [342] XX, ' C[I]"ì"' [343] XX, ' r•CR j' [344] XX, ':case 2' [345] XX, ' v',j [346] XX, ' C[I]""' [347] XX, ' K[I](82=•DR v)’ûûv' ¦õ C[I] K[I] [348] XX, ' rôv' [349] XX, ':else' [350] XX, ' ö0' [351] XX, ':end' [352] k•DEF[2]X [353] rw peek j [354] :if 0=ðr [355] ke,"Error from '",j,"' •COPY '",w,"' : " [356] :select r ¦ 1=fn copied 2=var copied [357] :case 0  •k,'Object not found' [358] :case 127  •k,'Duplicate name in objlist ¦ should not get here!' [359] :case ý2  •k,'Object too large for available space' [360] :case ý3  •k,'Name defined as a label; cannot be changed' [361] :case ý4  •k,'Insufficient space in symbol table and workspace too full to expand symbol table' [362] :case ý6  •k,'Insufficient free space to carry out command' [363] :case ý99  •k,(^\•DM†•TCNL)/•DM [364] :else  •e,'Unanticipated •COPY return code: ',ôr [365] :end [366] 0 [367] :end [368] [369] :end [370] [371] ¦ Cook up a good file name [372] m(’ûw)/'[',w,'] ' ¦ prefix with wsid [373] mm,j ¦ add object name [374] mm,(’ûu)/' [',(u~'/'),']' ¦ add /F= or /U= (but a "/" will create a subdirectory) [375] m[(mî'\:/')/âûm]' ' [376] mDEB m [377] mm,(C[I]î'')/'.',ôK[I] ¦ record rank if simple character vector or matrix, 0 otherwise [378] mm,('ì'âC[I])'.var' '.fn' '.fc' [379] [380] (IF)(ID),m ¦ file name (for ]DEF or ]ASSIGN) before fixing deltas [381] ¦•(IF) ¦ display for ]DEF [382] ¦•WGIVE 0 ¦ let that output appear [383] [384] ((m='•')/m)'#' ¦ might be a system variable [385] ((m='‘')/m)'+' ¦ fyi, WSIDs can contain ‘ and ñ symbols! [386] ((m='ñ')/m)•AV[178] ¦ that's the plus-or-minus symbol [387] (IS)(ID),m ¦ save the ANSI version of the file name [388] [389] rñAV2ANSI[•AVâr] ¦ translate [390] [391] r ñNFILE IS ¦ write the file [392] [393] :end [394] [395] •ELX‘elx [396] [397] f'aoDIFF_AM' [398] [399] :if ’ûf •wi 'self' [400] :andif f •wi 'visible' [401] [402] ¦ Merge is already running [403] [404] •wselff [405] •wi 'xActive' 0 [406] •wi 'xActive' 1 ¦ make it the active app (thanks, Patrick!) [407] [408] :else [409] [410] ¦ Create new Merge object [411] [412] •wselff •wi 'Create' ('ActiveObject ',E) ¦ 'ActiveObject Merge65.Application' [413] [414] ¦ Araxis Merge never starts maximized when invoked via ActiveX, even if you [415] ¦ have the "Maximize application on start-up" option checked. We can look at [416] ¦ the AM preferences, but only after AM starts -- and if we maximize it then, [417] ¦ you'll see the maximization happening. Oh well. [418] [419] •wi 'Preferences > .prefs' [420] '.prefs' •wi 'Longs > .longs' [421] e'.prefs.longs' •wi 'xItem' 'clAppMax' [422] :if e [423] •wi 'xMaximized' e ¦ maximize the app (if belatedly) [424] :end [425] [426] ¦ Set APL fonts [427] [428] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [429] k•ex 'G' [430] k•fx [2] 'vk G d' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ G [431] [432] tñUCASE 'FontName' G 'APLFONT' [433] z1•fi 'FontSize' G '11' [434] [435] :if tð'APLFONT' [436] :orif tð'APLCODE' [437] ¦ Symbol font (so something like "11.APLFONT" won't work) [438] h•wcall 'GetDC' 0 ¦ handle of device context of display [439] i•wcall 'GetDeviceCaps' h 'LOGPIXELSY' ¦ pixels per vertical logical inch [440] z0.5+(z’i)ö72 ¦ height [441] z'-',ôz ¦ negative means character height (as opposed to cell height) [442] tz,',0,0,0,400,0,0,0,255,1,2,1,49,',t [443] ¦ or, use WChooseFont '' in the TOOLS\WINDOWS workspace to get a logfont spec [444] :else [445] ¦ TrueType font [446] t(ôz),'.',t ¦ e.g., '12.APLHELP' [447] :end [448] ¦•'font  ',t ¦ debug [449] [450] '.prefs' •wi 'Strings > .strings' [451] I 'csUnchangedFont' 'csChangedFont' 'csInsertedFont' 'csRemovedFont' ¦ left window [452] II,'csUnchangedFont2' 'csChangedFont2' 'csInsertedFont2' 'csRemovedFont2' ¦ right panel [453] :for i :in I [454] '.prefs.strings' •wi 'xItem' i t [455] :end [456] [457] ¦ Save method: Saves preferences to the Registry, and propogates them to [458] ¦ other running instances of Merge. Without this method, preferences are [459] ¦ only saved to the Registry when Merge exits. [460] [461] '.prefs' •wi 'XSave' [462] [463] :end [464] [465] ¦ Initiate the file comparison [466] [467] :if '7'îE [468] ¦ Grrr... in version 7.0 they changed the name... [469] •wi 'xTextComparison > .filecomp' [470] :else [471] •wi 'xFileComparison > .filecomp' [472] :end [473] [474] '.filecomp' •wi 'xCompare' (1S) (2S) ¦ Compare! [475] ¦ GiveUserControl: Gives control over the lifetime of the comparison window to [476] ¦ the user. Merge will not automatically close the window when outstanding [477] ¦ automation references are released. [478] '.filecomp' •wi 'xGiveUserControl' ¦ enables tabs for multiple comparisons [479] '.filecomp' •wi 'xVisible' 1 [480] •wi 'xVisible' 1 [481] [482] ¦ Maybe I should creating more than one FileComparison object. [483] ¦ Then could I tell when user does ]diff on the same object? [484] [485] f'fmDIFF_AM' [486] :if ''ðf •wi 'self' [487] •wselff •wi 'Create' 'Form' 'Hide' [488] •wi '‘f' (0û '' '' ' ' (0 0)) ¦ ANSI file, APL file, class, timestamp [489] m0 4û'' '' ' ' (0 0) ¦ ANSI file, APL file, class, timestamp [490] •wi '‘h' ('#' •wi 'hwndmain') [491] ¦t"õ(('#' •wi 'hwndmain')=(•wcall 'GetActiveWindow'))/'CMDDIFF ''::'''" ¦ debug [492] t"õ(('#' •wi 'hwndmain')=(•wcall 'GetActiveWindow'))/'•UCMD '']DIFF ::'''" [493] k'.tm' •wi 'New' 'Timer' ('interval' 500) ('onTimer' t) [494] :else [495] •wselff [496] m•wi '‘f' [497] :end [498] [499] :for I :in â2 [500] fIS [501] h•wcall 'CreateFile' f 'GENERIC_READ' 'FILE_SHARE_READ' 0 'OPEN_EXISTING' 0 0 [502] Assert h†•wcall 'W_Const' 'INVALID_HANDLE_VALUE' [503] t•wcall 'GetFileTime' h    ¦ get create, access, write times [504] Assert 0†•first t [505] k•wcall 'CloseHandle' h [506] t4t ¦ write time [507] u~( f)îm[;1] [508] muëm ¦ if file is already being compared, remove it [509] mmžf (IF) (IC) t [510] :end [511] •wi '‘f' m [512] ¦ •m ¦ debug [513] [514] 0 [515] [516] L5: ¦ /AMFONT [517] [518] t8A ¦ what's after /AMFONT= e.g. '10.Courier New' [519] f'aoDIFF_AM' [520] :if ~''ðf •wi 'self' [521] :andif f •wi 'visible' [522] ¦ Merge is already running [523] •wselff [524] :else [525] ¦ Create new Merge object [526] •wselff •wi 'Create' ('ActiveObject ',E) ¦ 'ActiveObject Merge65.Application' [527] :end [528] •wi 'Preferences > .prefs' [529] •wi '.prefs.Strings > .strings' [530] I 'csUnchangedFont' 'csChangedFont' 'csInsertedFont' 'csRemovedFont' ¦ left window [531] II,'csUnchangedFont2' 'csChangedFont2' 'csInsertedFont2' 'csRemovedFont2' ¦ right panel [532] :for i :in I [533] '.prefs.strings' •wi 'xItem' i t [534] :end [535] '.prefs' •wi 'XSave' [536] f •wi 'Delete' [537] •'Okay, Merge font set to: ',t [538] 0 [539] [540] L6: ¦ /ULIST [541] [542] u•wcall 'W_Ini' '[DIFF] ULIST' [543] :if uð2û•TCNL [544] •'ULIST is undefined; to define it, run',•TCNL,' ]DIFF /ULIST=file1;file2;...' [545] :else [546] •'/ULIST=',u [547] :end [548] 0 [549] [550] L7: ¦ /ULIST= [551] [552] u7A ¦ what's after /ULIST= [553] k•wcall 'W_Ini' ('[DIFF] ULIST=',u) [554] •'Okay, /ULIST=',u [555] 0 [556] [557] L8: ¦ /ERASE [558] [559] •"¦ Note this doesn't work with Win98; you''ll have to erase the directories yourself" [560] 3 •CMD •'RMDIR ',(1D),' /S /Q' [561] 3 •CMD •'RMDIR ',(2D),' /S /Q' [562] 0 [563] [564] L9: ¦ Say syntax [565] [566] r'DIFF syntax is:',•TCNL,' ]DIFF object1 ; object2' [567] rr,•TCNL,'For details, see:',•TCNL,' ]DIFF ?' [568] •r [569] 0 [570] [571] LT: ¦ Internal timer callback [572] [573] ¦ •wself is the Timer object [574] ¦ Bail unless we have returned to the APL session [575] [576] ¦  We now do this test in the onTimer expression to avoid •ucmd overhead [577] ¦(('#' •wi 'hwndmain') = (•wcall 'GetActiveWindow'))0 [578] [579] ¦ Check for changed file timestamps [580] [581] F':' •wi '‘f' [582] :for I :in â1ûF [583] (f a c w)F[I;] [584] h•wcall 'CreateFile' f 'GENERIC_READ' 'FILE_SHARE_READ' 0 'OPEN_EXISTING' 0 0 [585] Assert h†•wcall 'W_Const' 'INVALID_HANDLE_VALUE' [586] t•wcall 'GetFileTime' h    ¦ get create, access, write times [587] Assert 0†•first t [588] k•wcall 'CloseHandle' h [589] t4t ¦ write time [590] :if ~tðw [591] [592] ¦ We're not going to ask again, regardless of answer [593] F[I;4] t [594] ':' •wi '‘f' F [595] [596] V(~èú\èf='\')/f ¦ delete leading path [597] BVî'[]' [598] VDLTB(Bå†\B)/V ¦ delete leading [wsid] and trailing [f=] [599] V(^\V†'.')/V ¦ delete trailing extension [600] [601] X'The timestamp on the file' [602] XX,•TCNL,' ',f [603] XX,•TCNL,'which contains ',(('ì'âc)'variable' 'function' 'file component') [604] XX,•TCNL,' ',V [605] XX,•TCNL,'has changed' [606] XX,•TCNL [607] :if cî'ì' [608] XX,•TCNL,'Define changed object in active ws?' [609] :else [610] XX,•TCNL,'Replace changed array in file component?' [611] :end [612] [613] h'#' •wi 'hwndmain' [614] k•wcall 'MessageBox' h X 'DIFF' 'MB_ICONQUESTION MB_YESNOCANCEL' ¦ MB_DEFBUTTON2 [615] :if k=6 ¦ 6=IDYES [616] :if c='ì' [617] •UCMD •']DEF ',a ¦ use APL file name -- DEF will translate [618] :else ¦ cî'' [619] •UCMD ']ASSIGN ',a [620] :end [621] :elseif k=7 ¦ 7=IDNO [622] ¦ noop [623] :else ¦ 2=IDCANCEL [624] :leave [625] :end [626] :end [627] :end [628] [629] ¦ If Merge has been closed, shut down monitoring [630] [631] f'aoDIFF_AM' [632] :if ''ðf •wi 'self' ¦ somebody else deleted it [633] :orif 0=f •wi 'visible' ¦ user closed it ¦ thanks, Patrick! [634] ¦ Use of Defer solves localization problems with •wself [635] '#' •wi 'Defer' "'fmDIFF_AM' •wi 'Delete'" [636] '#' •wi 'Defer' "'aoDIFF_AM' •wi 'Delete'" [637] :end [638] ì €ßÿt6eûWûW ì b CMDFILEDOC f;B;C;c;cv;cw;D;d;done;e;elx;h;I;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] [38] ¦ To do: [39] ¦ Print [40] ¦ Better error handler for components (WS FULL, FILE DATA ERROR, etc.) [41] ¦ Need to flag the error, then don't wrap quotes around message, say ? for shape, etc. [42] ¦ File/Open [43] ¦ /C=9999 9999 forces just the last comp ; should we report error instead? [44] ¦ Improve peeking at values that )EDIT won't allow [45] ¦ ]PKGDOC needs to handle multiple instances too [46] ¦ Support for colossal files [47] [48] (’•NC 'b')ûL6 ¦ dummy left arg means callback [49] [50] ¦ 28 Jul 2003 [51] ¦ I gave up trying to allow multiple instances. [52] ¦ First I added a kludge to handle the callbacks: [53] ¦ h•VR 'CMDFILEDOC' [54] ¦ h[(hâ'C')+0 1 2]'‘' ¦ change function name 'CMD' to '‘‘‘' [55] ¦ •wi '‘vr' h [56] ¦ h"õ(0=•NC '‘‘‘FILEDOC')/'0 0û•DEF •WI '':‘vr'''   ‘‘‘FILEDOC •wevent" ¦õ CMDFILEDOC [57] ¦ •wi 'onClose' h [58] ¦ •wi 'onDestroy' "•ERASE '‘‘‘FILEDOC'" [59] ¦ This is yucky, and isn't even sufficient because all of FILEDOC's subroutines [60] ¦ may be needed too. [61] ¦ Another complication is that the user command processor unties any ties made [62] ¦ during the execution of a user command. So I had to introduce code to [63] ¦ detect and recover from that. [64] ¦ Conclusion: User commands need to Wait, not Show. [65] ¦ If you run APL+Win with the "Multiple Execution" option, you can still have [66] ¦ several instances, but only the top one will be enabled. [67] [68] fô•ENLIST f ¦ arg might be numeric in development mode [69] [70] :if f^.=' ' ¦ no argument? [71] ñOUT 'For help, execute',•tcnl,' ]FILEDOC ?' [72] 0 [73] :end [74] [75] max256 ¦ max width of FFA display [76] [77] elx•ELX [78] [79] B•first 1=ûûf ñGETOPT '/B' ¦ bytes [80] T•first 1=ûûf ñGETOPT '/T' ¦ timestamp [81] C f ñGETOPT '/C' ¦ component range [82] fDLTB (^\f†'/')/f ¦ delete all options [83] [84] D1 ¦ depth [85] S1 ¦ shape [86] [87] :if (,1)ð•VI f ¦ just a tie number? [88] tn•first •FI f [89] :if tnî•FNUMS [90] n•FNAMES[•FNUMSâtn;] [91] L4 [92] :elseif tnî•XFNUMS [93] n•XFNAMES[•XFNUMSâtn;] [94] L4 [95] :else [96] ñOUT 'No component file tied to ',ôtn [97] 0 [98] :end [99] :end [100] [101] ¦ '9 FOO' could be an •F file in library 9, or a •XF file named '9 FOO' [102] ¦ in the current directory, so we pretty much just have to experiment. [103] ¦ Since this utility was born in the era of •F files, try that first. [104] [105] ¦ •F file names cannot contain '.' (although their path can) [106] ¦ An •F file may have long names in its path, but not the name itself [107] ¦ •XF and •CF file names may or may not have an extension [108] ¦ An •F file may be tied by •XFTIE [109] ¦ •F files are exclusive-tied on create; others are share-tied [110] ¦ '9 FOO' could be an •F file in lib 9, or a •XF file named '9 FOO' in current dir! [111] ¦ You can 'FOO.SF' •XFCREATE and then later 'FOO' •FTIE, but only if .SF is in upper case! [112] ¦ You can 'FOO.SF' •XFCREATE 1 and then 'FOO' •FSTIE 2 and have the same file tied twice! [113] ¦ If a file is tied already, you can tell whether it's a share or exclusive tie by trying [114] ¦ to rename it to itself; if that fails, it's a share tie. [ELE] [115] [116] e'' ¦ error message(s) [117] [118] m(~è<\èfî'\:')/f ¦ filename[.ext] [119] ('.'îm)ûL2 ¦ skip the •FSTIE attempt if the file has an extension [120] [121] ¦ Try •FSTIE [122] [123] d•FNUMS [124] tn•first (â999)~d,•XFNUMS ¦ remember, •F and •XF share pool of tie numbers [125] •ELX'',ôL1 [126] f •FSTIE tn [127] •ELXelx [128] ¦ Okay, it worked; 2 possibilities: new tie, or re-tied to a different tie number [129] ¦ Assert ~•FNUMSðd [130] ¦ Assert (û•FNUMS)òûd [131] :if (û•FNUMS)>ûd ¦ easy case: new tie has been created [132] ¦ It's possible that we have now •ftied a file that was already •xftied, [133] ¦ but I see how we can detect this situation. [134] :else ¦ file was already tied; be polite and restore original tie number [135] tn•first d~•FNUMS [136] f •FSTIE tn ¦ if first tie worked, will this always work too? [137] :end [138] n•FNAMES[•FNUMSâtn;] [139] L4 [140] [141] L1: ¦ •FSTIE failed [142] [143] ee,•tcnl,'Error from •FSTIE: ',(^\•DM†•TCNL)/•DM [144] [145] L2: ¦ Try •XFSTIE (same logic as •FSTIE) [146] [147] d•XFNUMS [148] tn•first (â999)~•FNUMS,d [149] •ELX'',ôL3 [150] f •XFSTIE tn [151] •ELXelx [152] :if (û•XFNUMS)=ûd [153] tn•first d~•XFNUMS [154] f •XFSTIE tn [155] :end [156] n•XFNAMES[•XFNUMSâtn;] [157] L4 [158] [159] L3: ¦ •XFSTIE failed [160] [161] ee,•tcnl,'Error from •XFSTIE: ',(^\•DM†•TCNL)/•DM [162] •1e [163] 0 [164] [165] L4: ¦ Okay, we have tied the file! [166] [167] nDLTB n [168] [169] z•FSIZE tn [170] (i e)2z ¦ first, 1+last [171] zDEB,'CI15' •FMT z [172] [173] :if i=e ¦ no components? [174] :andif ~•sys[21] ¦ not runtime? [175] ñOUT 'No components in file ',n,' - Tie ',(ôtn),' - Size ',z [176] 0 [177] :end [178] [179] uw0 [180] oldu'' [181] [182] ¦ See if it's a user command file [183] [184] U0 ¦ pessimist [185] m((e-1),0)û'' [186] •ELX'',ôL5 [187] [188] q•FREAD tn,2 ¦ pointers to directories [189] k•FREAD tn,q[2] ¦ char directory of objects (names) [190] v•FREAD tn,q[3] ¦ num directory of objects (nc, comp, date mod, arch date) [191] k(èú\è' 'ú.†k)/k ¦ DTBC ¦ no subroutine because of •ELX [192] kk,' ì?'[v[;1]] [193] cv[;2] ¦ component numbers [194] uw10•first ý1ûk [195] m((e-1),uw)û' ' ¦ user command files always start with comp 1 [196] m[c;]uw[2]k [197] m[1 ;]uw'[fileid]' [198] m[2 ;]uw'[head]' [199] m[q[1];]uw'[usage]' [200] m[q[2];]uw'[names]' [201] m[q[3];]uw'[numinfo]' [202] m[3 ;]uw'[bootfn]' [203] m[4 ;]uw'[upath]' [204] m[5 ;]uw'[bootpkg]' [205] m[5+â5;](5,uw)ûuw'[reserved]' [206] U1 [207] [208] L5: [209] [210] •ELXelx [211] [212] :if 1=ûûC [213] Cý2•FI C [214] qC=0 [215] C[q/â2]q/i,e-1 [216] CC[C] [217] CiCe-1 [218] (i e)C+0 1 [219] :end [220] [221] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [222] k•fx [2]'vk I d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ I [223] [224] w•FI 'FileDoc-Place' I '2 5 20 70' [225] v•FI 'FileDoc-Visible' I '1' [226] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [227] [228] ¦ If there are other instances of Filedoc running, cascade windows a little bit [229] :for •wself :in '#' •wi 'children' [230] :if 'Form'ð•wi 'class' [231] :andif 'fmFiledoc'ð9•wi 'name' [232] w[1 2]w[1 2]1.5 3+2•wi 'place' [233] :end [234] :end [235] [236] •wself('fmFiledoc',ôtn) •wi 'Create' 'Form' 'Hide' [237] •wi '‘inifile' f [238] •wi 'caption' ('FileDoc ',(ôtn),' - ',n,' - Size ',z) [239] •wi 'place' w [240] •wi 'visible' v [241] h' CMDFILEDOC •wevent' [242] •wi 'onClose' h [243] [244] •wself':mFile' •wi 'New' 'Menu' [245] •wi 'caption' '&File' [246] [247] •wself':mFile.mPeek' •wi 'New' 'Menu' [248] •wi 'caption' '&Peek...' [249] •wi 'shortcut' 'P' 2 [250] •wi 'onClick' " CMDFILEDOC 'Peek'" [251] [252] •wself':mFile.mExit' •wi 'New' 'Menu' [253] •wi 'caption' 'E&xit' [254] •wi 'shortcut' 'X' 2 [255] •wi 'onClick' "0 0û':' •wi 'Close'" [256] [257] •wself':mView' •wi 'New' 'Menu' [258] •wi 'caption' '&View' [259] [260] •wself':mView.mUcmd' •wi 'New' 'Menu' [261] •wi 'caption' '&UCMD Info' [262] •wi 'shortcut' 'U' 2 [263] •wi 'style' 1 [264] •wi 'value' U [265] •wi 'data' 3 [266] •wi 'onClick' h [267] •wi 'visible' U [268] •wi 'enabled' U [269] [270] •wself':mView.mTime' •wi 'New' 'Menu' [271] •wi 'caption' '&Timestamp' [272] •wi 'shortcut' 'T' 2 [273] •wi 'style' 1 [274] •wi 'value' T [275] •wi 'data' 4 [276] •wi 'onClick' h [277] [278] •wself':mView.mBytes' •wi 'New' 'Menu' [279] •wi 'caption' '&Bytes' [280] •wi 'shortcut' 'B' 2 [281] •wi 'style' 1 [282] •wi 'value' B [283] •wi 'data' 5 [284] •wi 'onClick' h [285] [286] •wself':mView.mDepth' •wi 'New' 'Menu' [287] •wi 'caption' '&Depth' [288] •wi 'shortcut' 'D' 2 [289] •wi 'style' 1 [290] •wi 'value' D [291] •wi 'data' 6 [292] •wi 'onClick' h [293] [294] •wself':mView.mShape' •wi 'New' 'Menu' [295] •wi 'caption' '&Shape' [296] •wi 'shortcut' 'S' 2 [297] •wi 'style' 1 [298] •wi 'value' S [299] •wi 'data' 7 [300] •wi 'onClick' h [301] [302] •wself':bn' •wi 'New' 'Button' [303] •wi 'caption' 'Stop' [304] •wi 'size' 1.25 8 [305] •wi 'style' 2 ¦ 2=cancel [306] •wi 'onClick' 'done1' ¦õ done [307] [308] •wself':l' •wi 'New' 'Label' [309] •wi 'caption' '' [310] •wi 'size' 1 9 [311] •wi 'style' 2 [312] [313] •wself':pb' •wi 'New' 'Progress' [314] •wi 'style' 1 ¦ 1=smooth [315] •wi 'value' 0 (1e-i) 1 0 ¦ 1 in case empty file [316] [317] cw1+2’•first ûôe-1 ¦ component number display width [318] cw4cw ¦ at least 'Comp' [319] [320] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [321] c0 3û0 [322] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [323] ccž((4+5’cwò9)'Component') (1.5+4+5’cwò9 ) 'right' ¦ 2 [324] ccž'UCMD' uw 'left' ¦ 3 [325] ccž'Timestamp' 20 'left' ¦ 4 [326] ccž'Bytes' 8 'right' ¦ 5 [327] ccž'ð' (1.5+1) 'right' ¦ 6 [328] ccž'Shape' 8 'right' ¦ 7 [329] ccž'Value' 80 'left' ¦ 8 [330] [331] •wself':' [332] [333] cv0 1 U T B D S 1 [334] c[(~cv)/âûcv;2]0 [335] •wi '‘cv' cv [336] [337] •wi '‘tn' tn [338] [339] ¦ Get value of key k; if undefined, write default to the ini file [340] k•fx [2]( [2] •cr 'I'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ I [341] [342] •wself':lv' •wi 'New' 'Listview' [343] [344] •wi 'columndisplay' c [345] [346] ¦ •wi 'font' 'APLFONT' 11 0 'default' [347] f 'FontName' I 'APLFONT' [348] ff,•FI 'FontSize' I '11' [349] ff,•FI 'FontStyle' I '0' [350] ff, 'FontCharset' I 'default' [351] •wi 'scale' 3 ¦ font size will be specified in points [352] •wi 'font' f [353] [354] •wi 'where' 0.5 1 [355] •wi 'style' 1 2 4 1024 4096 ¦ 1024=reorder cols 4096=gridlines [356] •wi 'onColClick' h [357] •wi 'onDblClick' h [358] •wi 'onKeyPress' h [359] [360] •wself':' [361] •wi 'onResize' h [362]  CMDFILEDOC 'Resize' [363] [364] •wself':lv' [365] •wi 'Focus' [366] [367] (i=e)ûL7 ¦ no components? [368] [369] v0 ¦ in case just one component [370] r0 [371] u'' [372] t0 [373] b0 [374] [375] T~T ¦ if /T option, force all components to be different [376] [377] oldii [378] oldv•FREAD tn,i ¦ read first component, save for flush [379] oldr•FRDCI tn,i [380] oldum[i;] [381] [382] W0 ¦ wasted bytes in ucmd file [383] [384] done0 ¦ repeat until done [385] [386] :repeat [387] [388] ':l' •wi 'caption' (,'CI9' •FMT i) [389] ':pb' •wi 'Stepit' [390] ii+1 [391] :if i1 [422] cc,'',ôi-1 [423] :end [424] [425] ¦¦¦ Timestamp [426] t,'I4,,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6û3oldr [427] [428] ¦¦¦ Bytes [429] bDLB,'CI15' •FMT oldr[1] [430] [431] ¦¦¦ Depth [432] dðoldv [433] dôd [434] [435] ¦¦¦ Shape [436] pûoldv ¦ shape [437] kûp ¦ rank [438] p(ôp),(k=0)/'' ¦ format shape [439] [440] ¦¦¦ Value [441] ¦fFFA oldv [442] fmax FFAW oldv [443] f(maxûf)ûf [444] qfâ'û' [445] :if qóûf [446] :andif q0 [466] q'FYI: ',(DLB,'CI15' •FMT W),' wasted bytes in ucmd file' [467] •wi 'size' 1 40 [468] •wi 'style' 0 [469] :else [470] q'' [471] :end [472] •wi 'caption' q [473] [474] •wself':pb' [475] •wi 'visible' 0 [476] [477] •wself':bn' [478] •wi 'onClick' '' [479] •wi 'caption' 'E&xit' [480] [481] •wself':lv' [482] •wi 'AutoFit' 'header' (cv/âûcv) ¦ skip dummy column 1 [483] [484] •wself':' [485] [486] k•wi 'Wait' [487] [488] 0 [489] [490] L6: ¦ ----- Callbacks ----- [491] [492] :SELECT f [493] [494] :CASE 'Resize' [495] [496] •wself':' [497] z•wi 'size' [498] (0îz)û0 ¦ noop if minimize [499] •wself':bn' [500] b0.5 1+•wi 'size' ¦ button size plus gaps [501] wz-b [502] •wi 'where' w [503] [504] ':l' •wi 'where' (w[1]+0.1) 1 [505] ':pb' •wi 'where' (w[1]) 11 1.25 (w[2]-12) [506] [507] •wself':lv' [508] w•wi 'where' [509] w[3 4]z-(1 0’b)+(2’w[1 2]) [510] •wi 'where' w [511] [512] :CASE 'RT_Resize' [513] [514] z•wi 'size' [515] •wself':bn' [516] b0.5 1+•wi 'size' [517] wz-b [518] •wi 'where' w [519] [520] •wself':ed' [521] w•wi 'where' [522] w[3 4]z-(1 0’b)+(2’w[1 2]) [523] •wi 'where' w [524] [525] :CASE 'Click' [526] [527] b•wi 'data' ¦ column number [528] v•wi 'value' ¦ on or off [529] cv':' •wi '‘cv' [530] cv[b]v [531] ':' •wi '‘cv' cv [532] •wself':lv' [533] :if v ¦ if turning on, we just need to autofit it [534] •wi 'AutoFit' 'header' b [535] :else ¦ if turning off, we need to change width to 0 [536] c•wi 'columndisplay' [537] c[b;2]0 [538] •wi 'columndisplay' c [539] :end [540] [541] :CASE 'ColClick' [542] [543] ¦ ••wself •wevent •warg [544] c1•warg ¦ column clicked [545] ¦ 1=dummy 2=comp 3=ucmd 4=time 5=bytes 6=depth 7=shape 8=value [546] i•wi 'sortorder' ¦ all rowids [547] m•wi 'GetCells' i c ¦ data [548] m[2],m ¦ simple char matrix [549] :if c=2 [550] pûm [551] b,èú\èm='' [552] m,m  m[b/âûb]' '  mpûm ¦ blank out '5' in '510' [553] :end [554] :if c î 2 5 6 7 [555] m(-+/^\èm=' ')èm ¦ right justify [556] :end [557] :if c=•wi '‘sort' ¦ same col as previous click? [558] d•avm ¦ descending [559] •wi '‘sort' 0 [560] :else [561] d•avm [562] •wi '‘sort' c ¦ remember for possible twice [563] :end [564] •wi 'sortorder' (i[d]) [565] [566] :CASE 'Close' [567] [568] ¦ Set value of key k in APLW.INI section [UCMDSREX] [569] k•fx [2]'k I v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ I [570] [571] 'FileDoc-Place' I •wi 'place' [572] 'FileDoc-Visible' I •wi 'visible' [573] [574] :if ~•sys[21] ¦ not runtime? [575] f':' •wi 'self' [576] '#' •wi 'Defer' ("'",f,"' •wi 'Delete'") [577] :end [578] [579] :CASE 'RT_Close' [580] [581] ¦ Set value of key k in APLW.INI section [UCMDSREX] [582] k•fx [2]'k I v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ I [583] [584] 'FileDocPeek-Place' I •wi 'place' [585] [586] :CASE 'KeyPress' [587] [588] :if •warg=13 ¦ Enter key? [589]  CMDFILEDOC 'Peek' [590] :end [591] [592] :CASE 'Peek' [593] [594] •wself':lv' [595] i1•wi 'value' ¦ selected row [596] :if i=0 [597] i1•wi 'sortorder' ¦ first in list [598] (i=0)û0 [599] :end [600] i CMDFILEDOC 'W_Edit' [601] [602] :CASE 'DblClick' [603] [604] r1•warg ¦ rowid [605] r CMDFILEDOC 'W_Edit' [606] [607] :CASE 'W_Edit' [608] [609] rb ¦ left arg: rowid [610] c•enlist •wi 'GetCells' r 2 ¦ get Comp cell [611] i(^\c†'')/c ¦ '1235' to '12' [612] i•first •FI i ¦ component number [613] tn':' •wi '‘tn' ¦ tie number [614] [615] ¦ W_Edit is not supported by the runtime engine [616] :if •sys[21] ¦ runtime? [617] (tn,i) CMDFILEDOC 'RT_Edit' [618] 0 [619] :end [620] [621] v•FREAD tn,i ¦ the value [622] u•enlist •wi 'GetCells' r 3 ¦ get Ucmd cell [623] [624] :if 1=ûûv [625] :andif 5óûv [626] :andif 'PACKAGE'ð1v [627] •UCMD 'PKGDOC ',ôtn,i ¦õ CMDPKGDOC [628] :elseif 'ì'îu ¦ function from ucmd file [629] nu~' ì' [630] k•DEF "ìn p v;",n,•tcnl,"[1] k•def v  (kðn)0  k•WCALL 'W_Edit' n ì" [631] n p v [632] :else [633] :if ''îu ¦ variable from ucmd file [634] nu~' ' [635] :else [636] n'File',(ôtn),'Comp',ôi ¦ local name [637] :end [638] :if (ðv)>1 [639] :orif (ûûv)>2 [640] :orif ^/0 ' 'î•TYPE •enlist v [641] ¦vFFA v ¦ but can get "Line too long" error from W_Edit [642] v•UCMD 'DISPLAY v' ¦ well, it's better than nothing! [643] :end [644] k•DEF "ìn p ",n,•tcnl,"[1] k•WCALL 'W_Edit' n ì" [645] n p v [646] :end [647] [648] :CASE 'RT_Edit' [649] [650] (tn i)b [651] v•FREAD tn,i ¦ the value [652] vCVR v ¦ simple character (thanks, Roy!) [653] [654] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [655] k•fx [2]'vk I d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ I [656] [657] f 'FontName' I 'APLFONT' [658] ff,•FI 'FontSize' I '11' [659] ff,•FI 'FontStyle' I '0' [660] ff, 'FontCharset' I 'default' [661] [662] w•FI 'FileDocPeek-Place' I '2 5 20 70' [663] [664] •wself('fmPeek',ôi) •wi 'Create' 'Form' 'Hide' [665] •wi 'caption' ('FileDoc ',(ôtn),' - Component ',ôi) [666] •wi 'border' 2 16 64 ¦ 2=sizeable 3=modal 16=sys menu 64=max [667] •wi 'limitwhere' 10 30 ¦ minimum size [668] •wi 'onClose' " CMDFILEDOC 'RT_Close'" [669] •wi 'onResize' " CMDFILEDOC 'RT_Resize'" [670] [671] •wself':ed' •wi 'New' 'Edit' [672] •wi 'where' 0.75 1 10 30 [673] •wi 'scale' 3 ¦ font size will be specified in points [674] •wi 'font' f [675] •wi 'color' (256æ255 255 255) [676] •wi 'style' 4 16 64 2048 4096 ¦ 4=multi-line 16=vscroll 64=hscroll 2048=APL 4096=read-only [677] •wi 'text' v [678] [679] •wi 'Defer' "•wi 'selection' 0" ¦ who knows why Defer is necessary... [680] [681] •wself':bn' •wi 'New' 'Button' [682] •wi 'size' 1.25 9 [683] •wi 'caption' 'Close' [684] •wi 'style' 2 ¦ 1=default (enter key); 2=cancel (escape key)  onClose [685] [686] •wself':' [687] •wi 'where' w ¦ triggers onResize handler [688] k•wi 'Show' ¦ don't Wait; Show permits several peeks [689] [690] :ELSE [691] [692] •'*** Unanticipated CMDFILEDOC callback! ',ôf •wself •wevent •warg [693] [694] :ENDSELECT [695] ì €ßÿt6ýý ì 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] ì $@€ßÿt6 Ü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] [79] Aô•ENLIST A ¦ arg might be numeric in development mode [80] [81] ADLTB A ¦ user command may pass in leading/trailing blanks [82] [83] :if Að'' [84] •'For help, see' [85] •' ]fnrepl ?' [86] 0 [87] :end [88] [89] ¦ Allow simple word search without delimiters [90] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [91] E1A ¦ first delimiter [92] :if Eî'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [93] E'/' [94] AE,A [95] :end [96] ¦ Allow no trailing delimiter for search with no options [97] ¦ If arg is '/foo', make it '/foo/' [98] :if 1=+/A=E [99] AA,E [100] :end [101] [102] ¦ Parse argument [103] [104] G0û '' ¦ targets [105] S0û '' ¦ functions [106] [107] :repeat [108] D1A ¦ delimiter [109] A1A [110] IAâD ¦ find second delimiter (might not be one) [111] :if I=1 [112] •'Empty target string is not a good idea' [113] 0 [114] :end [115] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [116] ADLB IA [117] P1A ¦ function or option [118] :if ~Pî'<ó=ò>†ú^åê&þ' [119] :leave [120] :end [121] P('^ú',P)['&þ'âP] [122] ADLB 1A [123] :if '~'=1A [124] PP,'~' [125] ADLB 1A [126] :end [127] S( P),S ¦ function and possible ~ [128] :if Að'' [129] •'Multiple target syntax error' [130] 0 [131] :end [132] :end [133] [134] D•FIRST ûG ¦ number of targets [135] [136] :if D>1 ¦ multiple targets? [137] FA ¦ options (old left argument) [138] p0 ¦ not replace mode [139] S'ø',S ¦ to save repeated (J-1)S below [140] :else ¦ one target [141] P1(1,E=A) •PENCLOSE E,A ¦ note we look for original first delimiter [142] N•FIRST ûP [143] :if N>2 [144] •'Argument should have 2 or 3 delimiters' [145] 0 [146] :end [147] pN=2 ¦ replace mode? [148] :if p [149] (r F)P ¦ replacement string, options [150] h•FIRST ûr ¦ need this repeatedly [151] d(•FIRST û1G)-h ¦ length difference (scalar for :select :case) [152] :else ¦ find mode [153] F1P ¦ options [154] :end [155] :end [156] [157] ¦ Define ìFILT for APL/quoted strings/comments [158] [159] Z'à''¦'îF [160] Z[2]Z[2]ú'"'îF [161] Z2æZ [162] E~Zî0 8 ¦ not all or none: we need to filter [163] [164] :if E ¦ unless all or none [165] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [166] LL, "¦ Quotes and Comments" [167] LL, "¦ Right arg is a •VR" [168] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [169] LL, "¦ Extracted from Zark's ìParseVR" [170] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [171] LL, "¦ 26 Oct 2004 Include ¦õ" [172] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [173] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [174] LL, "•IO0 ¦ origin 0 is convenient" [175] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [176] LL, "xcx\n" [217] LL, "¦ Flag newline after each comment; then convert pairs to maps" [218] LL, "tnúc" [219] LL, "ut/c" [220] LL, "c†\x\t\uúý10,u" [221] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [222] ¦ 0=None and 7=All cases are excluded before we get here [223] P 'rc' ¦ 1 = ¦ [224] PP, 'rq>c' ¦ 2 = ' ¦ Quoted strings: not in comments [225] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [226] PP, 'rqåc' ¦ 4 = à = 'å¦ [227] PP, 'r~q' ¦ 5 = ঠ= ~' [228] PP, 'r~c' ¦ 6 = à' = ~¦ [229] LL,P[Z] [230] K•FX[2]L ¦õ QC [231] :end [232] [233] L 'RFILT' [234] LL, '¦ Raw hit filter' [235] LL, '¦ V=•VR, P=partition flags' [236] LL, 'R~P ANDSCAN Vî''[1234567890]''' ¦ not line numbers [237] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [238] [239] K•FX[2]L ¦õ FILT ANDSCAN QC [240] [241] ¦ Define ìSYN for syntactic search [242] [243] Z''îF ¦ non-syntactic search? [244] [245] ¦ Token alphabet: chars that can be anywhere in a token [246] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [247] a'_' [248] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [249] aa,'abcdefghijklmnopqrstuvwxyzñ' [250] aa,'0123456789' [251] ¦ Token alphabet, including chars that can only begin a token [252] qa,'•ý' [253] [254] Q 'HA SYN H;B;I' [255] QQ, '¦ Syntactic hit filter' [256] QQ, '¦ Requires: V=•VR, a,q=alphabet' [257] QQ, 'IH/âûH' [258] ¦  Note that if target starts with • then we don't care what's to the [259] ¦ left of it, so ((1A)îa) is correct. [260] QQ, ':if (1A)îa' [261] QQ, ' H[(('' '',V)[I]îq)/I]0' [262] QQ, ':end' [263] QQ, ':if (ý1A)îq' [264] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [265] QQ, ':end' [266] :if Z=1 ¦ Neither? [267] Q1ûQ ¦ noop [268] :end [269] K•FX[2]Q ¦õ SYN a q [270] [271] ¦ Define ìUP for case-insensitive filter [272] [273] Z'ï'îF ¦ ignore case when finding target? [274] [275] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [276] ¦ Noop if no letters in targets [277] K•FX[2]'VUP V' '¦ noop' [278] :elseif Z [279] Q'ñabcdefghijklmnopqrstuvwxyz' [280] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [281] u•AV [282] u[uâQ]L [283] K•FX[2]'VUP V' 'Vu[•AVâV]' ¦õ UP u [284] :else [285] m'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [286] u'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [287] Q 'VUP V;B;I;L;S' [288] QQ, '¦ Force APL+Win keyword names to upper case' [289] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [290] QQ, '¦ RHS 11/18/99' [291] QQ, '' [292] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [293] QQ, 'BVî''•'' ¦ find key symbols' [294] QQ, '(1îB)0 ¦ quit if none' [295] QQ, '' [296] QQ, 'LVîm ¦ flag all letters (any case)' [297] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [298] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [299] QQ, '(1îB)0 ¦ quit if none' [300] QQ, '' [301] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [302] QQ, 'IS/B ¦ flag those which are candidates' [303] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [304] QQ, 'I†\I ¦ name mask' [305] QQ, 'II/âûI ¦ indices' [306] QQ, '' [307] QQ, 'V[I]u[mâV[I]] ¦ translate' [308] K•FX[2]Q [309] ¦ RHS 3/19/01 [310] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [311] ¦ when searching for 'fMain'. [312] ¦ List of keywords? No, could have ':end' •wi 'New' ... [313] ¦ I think we need to upper-case just the à part of the •vr [314] ¦ RHS 2/06/06 [315] ¦ I often search for •fappend or •io. [316] ¦ I cannot recall EVER having searched for :repeat. [317] ¦ So let's not worry about control structure keywords. [318] :end [319] [320] GUPG ¦ targets to uppercase, if appropriate [321] A1G ¦ last (and typically only) target [322] [323] ¦ Options setup [324] [325] R''îF ¦ suppress display, just return result? [326] X0û '' ¦ initialize result [327] [328] T'~'îF ¦ all but named fns? [329] y'û'îF ¦ auto reply Yes to replacement confirmation prompt? [330] [331] i'?'îF ¦ interactive prompt mode? [332] :if i^~p [333] •'Prompt mode "?" is only useful in replace mode' [334] 0 [335] :end [336] [337] g'ì'îF ¦ global fn matching? [338] :if g^D=1 [339] •'FYI, the ì option has no effect with just one target string' [340] g0 [341] :end [342] [343] ¦ Strip flags from function list [344] [345] Eú/'*.'îF ¦ any function name wildcards or groups? [346] F(~Fî'à''¦ï~?ú^ì')/F ¦ note we do not remove asterisk and period [347] FWords F [348] [349] ¦ Default to all fns [350] [351] :if T^0=ûF [352] •'Tilde with no names means "not all functions"' [353] 0 [354] :end [355] [356] :if EúTú0=ûF [357] [358] ¦ You could have a global function that is localized but undefined [359] ¦ •IDLIST 1+2+8 will not pick up that name, so... [360] [361] N•SINL [362] N(~N[;1]î'õ•><')ëN ¦ no local names at these levels [363] N(,ú\N=' ')/,N ¦ discard FOO[3], keep names to the right [364] NWords N ¦ all localized names [365] NN~ ,'*' ¦ the asterisk next to suspended fn is not a name [366] N('•'†•FIRSTN)/N ¦ avoid picking up system vars (ñUCMD2 localizes •PW and •CT) [367] [368] M•IDLIST 1+2+8 ¦ all visible names [369] MWords M [370] MM,N ¦ add all localized names [371] M((MâM)=âûM)/M ¦ there might be dups [372] [373] N,•SI [374] N(ý1+Nâ'[')ûN ¦ name of self ¦ RHS 8/31/99 [375] MM~ N ¦ remove self [376] [377] P•IDLOC [2]M ¦ what are they [378] PP[;0æûP] ¦ global definition [379] M(P=1)/M ¦ functions only [380] [381] ¦ Now we have all global functions (though some could be shadowed) [382] [383] :if 0=ûF [384] FM [385] :elseif E ¦ which implies 0†ûF [386] :while '*'î•ENLIST F ¦ wildcard? [387] P('*'îF)â1 [388] UPF [389] [390] VâûM ¦ indices of matches [391] C' ',M,' ' ¦ candidates [392] U('*'=1U)' ',U,('*'=ý1U)' ' [393] :for L :in '*' Words U [394] BC •SS L [395] Hú/B [396] C((H/B)â1)H/C [397] VH/V [398] :if Vð  :leave  :end [399] :end [400] CM[V] [401] [402] F((P-1)ûF),C,PF [403] :end [404] :while '.'î•ENLIST F ¦ group? [405] P('.'îF)â1 [406] UPF [407] [408] H(U='.')/âûU [409] :if Hð,1 ¦ one leading period [410] :andif 2=•NC 1U [411] Cõ1U [412] :if 2=ûûC [413] C [2] C [414] CC~' ' [415] :end [416] CC[•AV[2]C] ¦ is this a good idea? [417] :else [418] U[H] '(period)' [419] C •ENLIST U ¦ this will fail valid name test [420] :end [421] [422] F((P-1)ûF),C,PF [423] :end [424] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [425] :end [426] :if T [427] FM~F [428] :end [429] :end [430] [431] ¦ Discard invalid names [432] [433] C•NC [2]F [434] :if 4îC [435] N(C=4)/F [436] •'*** Not searched, invalid name',(1=ûN)'s:',ôN [437] F(C†4)/F [438] :end [439] [440] ¦ Discard shadowed names [441] [442] L•IDLOC [2]F ¦ what are names [443] L0 ý1L ¦ disregard global level [444] CL^.=ý1 [445] :if 0îC [446] N(~C)/F [447] •'*** Shadowed:',ôN [448] FC/F [449] :end [450] [451] ¦ Discard non-functions [452] [453] C3=•NC [2]F [454] :if 0îC [455] N(~C)/F [456] •'*** Not function',(1=ûN)'s:',ôN [457] FC/F [458] :end [459] [460] ¦ Discard locked functions [461] [462] K•EX 'L' [463] K•FX [2] 'RL F' "R0†•first û•CRL F,'[0]'" ¦õ L [464] CLF ¦ yuck, but I wanted to get this check out of the function loop [465] K•EX 'L' [466] :if 0îC [467] N(~C)/F [468] •'*** Locked function',(1=ûN)'s:',ôN [469] FC/F [470] :end [471] [472] NûF ¦ how many fns [473] :if 0=ûF [474] •'*** No functions to search!' [475] 0 [476] :end [477] [478] :if p [479] :andif ~y [480] —'Sure you want to search ',(ôN),' function',(N=1)'s and replace "',A,'" with "',r,'" ? ' [481] •ARBOUT '' ¦ an oldie but a goodie [482] (ú/'Yy'î—)0 ¦ default is No [483] :end [484] [485] VDLTB •WSID [486] :if Vð'' [487] V'CLEAR WS' [488] :end [489] [490] •'Searching ',(ôN),' function',(N=1)'s in ',V,' ...' [491] [492] •WGIVE 0 ¦ let that message display [493] [494] T0 ¦ accumulate hits [495] E0 ¦ accumulate lines [496] U0 ¦ accumulate functions [497] [498] :for N :in F ¦ inspect next function [499] [500] V•VR N [501] LUP V [502] [503] ¦ Search •VR [504] [505] HL •SS A ¦ the heart of the matter [506] [507] :if D=1 ¦ single target? [508] :andif ~1îH ¦ no raw hits? [509] :continue ¦ next function [510] :end [511] [512] ¦ Syntactic filter [513] [514] HA SYN H ¦õ V a q [515] [516] :if D=1 ¦ single target? [517] :andif ~1îH ¦ no more hits? [518] :continue ¦ next function [519] :end [520] [521] ¦ Filter for APL / quoted strings / comments [522] [523] P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [524] P[ý5+ûV]1 ¦ force end of last line [525] [526] IFILT ¦õ P V ANDSCAN [527] HH^I [528] [529] :if D=1 ¦ single target? [530] :andif ~1îH ¦ no more hits? [531] :continue ¦ next function [532] :end [533] [534] :if D>1 ¦ multiple targets [535] HP ORRED H ¦ shift hits to leading "[" [536] ¦ We have already done the last target; now step through the others [537] ¦ Note that they are in reverse order so functions work like APL [538] :if g [539] tú/H [540] :for J :in 1âD [541] WL •SS JG ¦ raw search [542] W(JG) SYN W ¦ SYN [543] WW^I ¦ FILT [544] WP ORRED W ¦ shift hits to leading "[" [545] HWúH ¦ lines to show [546] tõ'(ú/W)',(JS),'t' ¦ apply function [547] :end [548] :if ~t ¦ no hits? [549] :continue ¦ next function [550] :end [551] :else [552] :for J :in 1âD [553] WL •SS JG ¦ raw search [554] W(JG) SYN W ¦ SYN [555] WW^I ¦ FILT [556] WP ORRED W ¦ shift hits to leading "[" [557] Hõ'W',(JS),'H' ¦ apply function [558] :end [559] :if ~1îH ¦ no hits remaining? [560] :continue ¦ next function [561] :end [562] :end [563] ¦ Note that when D>1, H flags lines not hits [564] :end [565] [566] ¦ Got some hits; if interactive mode, confirm them [567] [568] :if i ¦ interactive replace mode? [569] •'==> ',N,' (',(ô+/H),')' ¦ name of function, total hits [570] Mý1+P/âûP ¦ partition starts [571] Lý1+(1M,1+ûV)-M ¦ partition lengths [572] :for C :in H/âûH ¦ hit starting positions [573] B+/C>M [574] •N,V[M[B]+âL[B]] [575] —(((ûN)+ý1+C-M[B])û' ') , ((ûA)û'') , ' replace? [Ynq] ' [576] •ARBOUT '' ¦ an oldie but a goodie [577] W— [578] (ú/'Qq'îW)û0 ¦ bail out entirely [579] H[C]~ú/'Nn'îW ¦ default is Yes [580] :end [581] :if ~1îH ¦ no hits remaining? [582] :continue ¦ next function [583] :end [584] :end [585] [586] ¦ Got some hits; now display, or replace and then display [587] [588] :if p ¦ replace mode? [589] [590] LH/âûH ¦ hit starting positions [591] CûL ¦ how many hits [592] M(C,h)ûr ¦ replacements [593] [594] ¦ Replace, depending on length difference [595] [596] :select ’d [597] :case 0 ¦ replacement is same length as target [598] V[Lø.+ý1+âh]M [599] :case ý1 ¦ replacement is longer than target [600] LL+(þd)’ý1+âC [601] B((ûV)+C’þd)û1 [602] B[Lø.+âþd]0 [603] VB\V [604] V[Lø.+ý1+âh]M [605] HB\H [606] PB\P [607] :case 1 ¦ replacement is shorter than target [608] H1èH ¦ move hits left so not deleted [609] V[Lø.+ý1+âh]M [610] B(ûV)û1 [611] B[Lø.+h+ý1+âd]0 [612] VB/V [613] HB/H [614] PB/P [615] :end [616] [617] ¦ Redefine function [618] [619] Q•DEF V [620] :if ~QðN ¦ function name changed? [621] :if 0=10ûQ [622] ¦ APL+Win: Q is error code, line number [line 1 = header!] [623] •'*** DEFN ERROR on ',N,': ',ôQ [624] •ý1((+\P)=Q[2])/V [625] :continue [626] :end [627] K•EX N ¦ erase old version [628] •'* Warning: name of ',N,' has been changed to ',Q [629] NQ [630] :end [631] [632] :end [633] [634] ¦ Ready to display hits [635] [636] :if D=1 [637] TT++/H ¦ accumulate total hits [638] EE++/P ORRED H ¦ accumulate lines with hits [639] :else [640] EE++/H ¦ accumulate lines with hits [641] :end [642] [643] UU+1 ¦ accumulate functions with hits [644] XX, N ¦ add function name to result [645] [646] :if R ¦ if result-only mode [647] :continue ¦ next function [648] :end [649] [650] ¦ Display hits [651] [652] •'==> ',N,' (',(ô+/H),')' ¦ name of function, total hits [653] [654] :if i ¦ interactive replace mode? [655] :continue ¦ next function [656] :end [657] [658] :if D=1 [659] HP ORRED H ¦ any hits per line? [660] :end [661] [662] HH/âûH ¦ line numbers to display (origin 1) [663] PP/âûP ¦ partition starts [664] L(1P,1+ûV)-P ¦ partition lengths [665] PP[H]-1 ¦ compensate for +â with •IO1 [666] LL[H]-1 ¦ not incl trailing CR [667] WûH ¦ number of lines with hits [668] :for B :in âW [669] ¦ APL+Win: Show fn name too so can double-click to edit at that line [670] •N,V[P[B]+âL[B]] ¦ faster than take/drop approach [671] :end [672] •WGIVE 0 ¦ allow display [673] [674] :end ¦ next function [675] [676] :if D=1 [677] •'==> Totals: ',(ôT),' hit',(T=1)'s on ',(ôE),' line',(E=1)'s in ',(ôU),(-U=1)' functions' [678] :else [679] •'==> Total: ',(ôE),' line',(E=1)'s in ',(ôU),(-U=1)' functions' [680] :end [681] [682] Rû0 ¦ quit if result-only mode [683] [684] K•EX 'X' [685] ì €ßÿt6ñ ì 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 ì €ßÿt6f / / ì 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] ¦ 12 Feb 2007 Most recent minor change [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] ¦ Get value of key K from APLW.INI section [UCMDSREX]; default to d [178] •erase 'I' [179] k•fx [2] 'vk I d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ I [180] [181] w•FI 'Keys-Where' I '4 10 20 78' [182] [183] •wself'fmKeys' •wi 'Create' 'Form' 'Close' [184] •wi 'caption' 'Keys' [185] •wi 'where' w [186] •wi 'limitwhere' 8 20 [187] •wi 'onResize' '0 CMDKEYS •wevent' [188] •wi 'onClose' '0 CMDKEYS •wevent' [189] [190] •wself':mFile' •wi 'New' 'Menu' ('caption' '&File') [191] k'.mExit' •wi 'New' 'Menu' ('caption' 'E&xit') ('onClick' 'k":" •wi "Close"') ('shortcut' 27 0) [192] [193] •wself':mEdit' •wi 'New' 'Menu' ('caption' '&Edit') [194] k'.mCW' •wi 'New' 'Menu' ('caption' 'Remove code &walker keys') ('onClick' '0 CMDKEYS "CW"') ('shortcut' 'W' 2) [195] k'.mCopy' •wi 'New' 'Menu' ('caption' '&Copy list to clipboard') ('onClick' '0 CMDKEYS "Copy"') ('shortcut' 'C' 2) [196] [197] ¦ Get value of key k; if undefined, write default to the ini file [198] k•fx [2] ( [2] •cr 'I'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ I [199] [200] •wself':lv' •wi 'New' 'Listview' ('style' 1 2 4 4096) ¦ 4096=gridlines [201] [202] ¦ This allows user to type a letter to jump in the Key column [203] d0 5û ¦ 4=col id (ptr into list), 5=col order [204] ddž'Key' 2 'left' 5 5 [205] ddž'A' 2 'left' 1 1 [206] ddž'C' 2 'left' 2 2 [207] ddž'S' 2 'left' 3 3 [208] ddž'Shifts' 20 'right' 4 4 [209] ddž'Default' 30 'left' 6 6 [210] ddž'Tool' 30 'left' 7 7 [211] [212] •wi 'columndisplay' d [213] [214] ¦ •wi 'font' 'APLFONT' 11 0 'default' [215] F 'FontName' I 'APLFONT' [216] FF,•FI 'FontSize' I '11' [217] FF,•FI 'FontStyle' I '0' [218] FF, 'FontCharset' I 'default' [219] •wi 'scale' 3 ¦ font size will be specified in points [220] •wi 'font' F [221] [222] MK[;1 1 1 1 4 5 6] [223] M[;1]K[;1]û'A' [224] M[;2]K[;2]û'C' [225] M[;3]K[;3]û'S' [226] M[;4]((4’K[;1])û 'Alt+') , ((5’K[;2])û 'Ctrl+') , ((6’K[;3])û 'Shift+') [227] [228] •wi 'list' (0,1,M) [229] [230] •wi 'onColClick' '0 CMDKEYS "Sort"' [231] •wi 'onDblClick' '0 CMDKEYS "Detail"' [232] •wi 'onOpen' "•wi 'AutoFit' 'header' 'all'" [233] •wi 'onKeyPress' '0 CMDKEYS •wevent' [234] [235] •wself':' [236] k•wi 'Wait' [237] •wi 'Delete' [238] 0 [239] [240] L1: [241] [242] :SELECT A [243] [244] :CASE 'Resize' [245] [246] (1=3•warg)û0 ¦ noop if minimize [247] [248] ':lv' •wi 'where' (0 0,2•warg) [249] [250] :CASE 'Sort' [251] [252] D•wi 'sortorder' ¦ current order [253] I•first •warg ¦ column number [254] M[2] ,•wi 'GetCells' D I ¦ the data [255] F( I,3)•wi 'columndisplay' ¦ justification [256] :if I=5 ¦ Key [257] I•AVM ¦ ascending order [258] Lý1’1=+/M[I;]†' ' ¦ first, one-letter keys [259] LL+(M[I;1]='F')’•FI ,'0',0 1M[I;],' ' ¦ second, function keys, in numeric order [260] LL+99’L=0 ¦ then the rest [261] II[L] [262] :elseif Fð'right' ¦ numeric column? [263] M(-+/^\èM=' ')èM ¦ RJUST [264] I•AVM ¦ descending [265] :else ¦ text column [266] I•AVM ¦ ascending order [267] :end [268] [269] :if IðâûI  IèI  :end ¦ reverse sort [270] [271] •wi 'sortorder' (D[I]) ¦ reset the sortorder [272] [273] :CASE 'KeyPress' [274] [275] :if •warg=13 ¦ Enter key? [276] 0 CMDKEYS 'Detail' [277] :end [278] [279] :CASE 'Close' [280] [281] ¦ Set value of key k in APLW.INI section [UCMDSREX] [282] K•fx [2] 'k I v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ I [283] [284] 'Keys-Where' I •wi 'where' [285] [286] :CASE 'CW' [287] [288] •wi 'enabled' 0 [289] [290] •wself':lv' [291] D•wi 'sortorder' ¦ row order [292] M•wi 'GetCells' D (â7) [293] Pú/M[;6] •SS '[CW]' [294] •wi 'SetCells' (P/D) 6 ((+/P)û '') [295] ¦ Don't delete if a Tool is defined [296] PP^M[;7]ð '' [297] ¦ Or if it's an unshifted F key [298] PP>('F'=•enlist 1M[;5])^((•enlist 11M[;5])î'123456789')^M[;4]ð '' [299] •wi 'DeleteRows' (P/D) [300] [301] :CASE 'Copy' [302] [303] •wself':lv' [304] D•wi 'sortorder' ¦ row order [305] L•wi 'columndisplay' [306] M•wi 'GetCells' D (â1ûL) ¦ the data [307] ML[L[;5];1]žM ¦ add column headings, in column order [308] M•TCHT,M [309] MM, •TCNL,•TCLF [310] V•enlist 1•enlist•split M [311] VñAV2ANSI[•AVâV] [312] H•wcall 'GlobalAlloc' 'GMEM_MOVEABLE' (1+•first ûV) [313] •error (H=0)/'Unable to allocate memory for copy' [314] P•wcall 'GlobalLock' H [315] •error (P=0)/'Unable to lock memory for copy' [316] K•wcall 'W_Mem' (P,0,1, V,•tcnul) [317] K•wcall 'GlobalUnlock' H [318] w'#' •wi 'hwndmain' [319] •error (0=•wcall 'OpenClipboard' w)/'Clipboard busy' [320] K•wcall 'EmptyClipboard' [321] K•wcall 'SetClipboardData' 'CF_TEXT' H [322] K•wcall 'CloseClipboard' [323] [324] :ELSE [325] [326] •'*** Unanticipated CMDKEYS case: ',ôA [327] [328] :END ì €ßÿt6Œ{E{E ì RL CMDMF A;D;F;I;K;M;N;O;T;h;p;v;w;•WSELF [1] ¦ Displays •MF timing information [2] ¦ ]MF ¦ show summary for entire ws [3] ¦ ]MF foo ¦ go directly to details on ìfoo [4] ¦ ]MF /ON ¦ turn on monitoring for all fns (reset if already on) [5] ¦ ]MF /OFF ¦ turn off monitoring for all fns [6] ¦ Click on report column headings to sort; click again to reverse [7] ¦ Double-click (or Enter) summary report row to see function detail [8] [9] ¦ Inspired by CMDWSTIME from APL2000 [10] [11] ¦ 23 Jun 2003 Rex Swain, Independent Consultant, www.rexswain.com [12] ¦ 19 Jul 2003 ColClick sorts numeric columns in descending order first [13] ¦ 27 Jul 2003 Correct •SI/•IDLOC alignment [14] ¦ 25 Sep 2004 Use font settings in APLW.INI [UCMDSREX] [15] ¦ 17 Jan 2005 EVLEVEL neutral [16] ¦ 18 Jan 2005 Added Edit/Copy [17] ¦ 16 May 2005 Commented out Print -- ]wprint doesn't work with 'scale' 3 [18] ¦ 12 Feb 2007 Most recent minor change [19] [20] (’•NC 'L')ûL1 ¦õ L ¦ any left arg means callback [21] [22] Aô•enlist A ¦ arg could be numeric in development mode ? [23] [24] :if 1=ûûA ñGETOPT '/ON' [25] O1 [26] :elseif 1=ûûA ñGETOPT '/OFF' [27] O0 [28] :else [29] Oý1 [30] :end [31] [32] AñDEB (^\A†'/')/A ¦ delete all options [33] [34] ¦ Roy says: •MF 3 seems to introduce more noise than repeatability. [35] ¦ It also makes •MF ý1 return slightly inconsistent results from execution to [36] ¦ execution. Using •MF 2 saves me from capturing it just once and saving it. [37] [38] ¦•MF 3 ¦ use CPU clock rate timer, based on the Pentium Read Time Stamp Counter [39] •MF 2 ¦ use high resolution timer, based on the Win32 QueryPerformanceCounter() API [40] [41] ¦ Harder than it should be: Find names of all non-localized functions [42] [43] F•SI[;1] ¦ first column of SI [44] F(~Fî'õ•><')/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] F,' ',F [115] F(F†' ') Partition F [116] [117] NûF [118] M(N,9)û0 ¦ two extra columns for raw time data [119] M[;1]F ¦ function names [120] M[;8 9]ý1 ¦ to flag rows with no •MF data [121] :for I :in âN [122] D•MF IF [123] :if 0<•first ûD [124] M[I;8]D[1;1] ¦ total time used by function (will be M[;2]) [125] M[I;9]+/D[;2] ¦ total time used directly by function (will be M[;3]) [126] M[I;5]/D[;3] ¦ max iteration count [127] M[I;6]D[1;3] ¦ number of times called [128] :end [129] T•CRL (IF),'[0]' ¦ header line [130] :if Tð'' [131] M[I;7] '(locked)' [132] :else [133] M[I;7] (ú\T†' ')/T ¦ some headers have leading blank [134] :end [135] :end [136] MM[M[;9];] ¦ sort by time here (and because of ý1's, no data falls below 0) [137] TM[;9]<0 ¦ remember which have no data [138] D0M[;9] ¦ ditch ý1's [139] M[;4]100’Dö+/D ¦ percent of time here [140] [141] M[;2 3] '' ¦ times [142] M[;5 6]ôM[;5 6] ¦ iter calls [143] M[;4]12ôM[;4] ¦ percent (2ô returns one leading blank) [144] ¦ Save raw data in case resolution is changed [145] ¦ Using •FMT avoids loss of precision from ô and •PP [146] M[;8]•split 'I17' •FMT M[;8] [147] M[;9]•split 'I17' •FMT M[;9] [148] [149] M[T/âN;4 5 6] '' ¦ no monitoring data [150] [151] :if ^/T [152] ñOUT 'No functions in this ws have any monitoring data' [153] 0 [154] :end [155] [156] ¦ Create the form [157] [158] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [159] •erase 'I' [160] K•fx [2] 'vk I d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ I [161] [162] w•FI 'MF-Place' I '4 10 20 78' [163] v•FI 'MF-Visible' I '1' [164] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [165] [166] •wself'fmMF' •wi 'Create' 'Form' 'Close' [167] •wi 'caption' ('MF summary for wsid: ',ñDEB •WSID) [168] •wi 'place' w [169] •wi 'visible' v [170] •wi 'limitwhere' 8 20 [171] •wi 'onResize' '0 CMDMF •wevent' [172] •wi 'onClose' '0 CMDMF •wevent' [173] [174] •wself':mFile' •wi 'New' 'Menu' ('caption' '&File') [175] K'.mDetail' •wi 'New' 'Menu' ('caption' 'Function &Detail...') ('onClick' '0 CMDMF "Detail"') ('shortcut' 'D' 2) [176] ¦K'.mPrint' •wi 'New' 'Menu' ('caption' '&Print...') ('onClick' '0 CMDMF "Print"') ('shortcut' 'P' 2) [177] K'.mSep1' •wi 'New' 'Menu' ('separator' 1) [178] K'.mExit' •wi 'New' 'Menu' ('caption' 'E&xit') ('onClick' 'K":" •wi "Close"') ('shortcut' 27 0) [179] [180] •wself':mEdit' •wi 'New' 'Menu' ('caption' '&Edit') [181] K'.mCopy' •wi 'New' 'Menu' ('caption' '&Copy entire list to clipboard') ('onClick' '0 CMDMF "Copy"') ('shortcut' 'C' 2) [182] [183] •wself':mView' •wi 'New' 'Menu' ('caption' '&View') [184] K'.mHide' •wi 'New' 'Menu' ('caption' '&Hide fns with no time') ('onClick' '0 CMDMF "Hide"') ('style' 1) ('shortcut' 'H' 2) [185] ¦ K'.mRefresh' •wi 'New' 'Menu' ('caption' '&Refresh') ('onClick' '0 CMDMF "Refresh"') ('shortcut' 116 0) ¦ 116=F5 [186] [187] •wself':mRes' •wi 'New' 'Menu' ('caption' '&Resolution') [188] K'.mRaw' •wi 'New' 'Menu' ('caption' '&Raw Ticks') ('onClick' '1 CMDMF "Res"') ('suppress' 1) ('shortcut' 'R' 2) [189] K'.mMsec' •wi 'New' 'Menu' ('caption' '&Millisecs') ('onClick' '2 CMDMF "Res"') ('suppress' 1) ('shortcut' 'M' 2) [190] K'.mSec' •wi 'New' 'Menu' ('caption' 'MM:&SS.mmm') ('onClick' '3 CMDMF "Res"') ('suppress' 1) ('shortcut' 'S' 2) [191] [192] •wself':bnExit' •wi 'New' 'Button' 'Hide' ('style' 2) ¦ 2=cancel [193] [194] ¦ Get value of key k; if undefined, write default to the ini file [195] K•fx [2] ( [2] •cr 'I'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ I [196] [197] •wself':lv' •wi 'New' 'Listview' ('style' 1 2 4 4096) ¦ 4096=gridlines [198] [199] •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') [200] [201] ¦ •wi 'font' 'APLFONT' 11 0 'default' [202] F 'FontName' I 'APLFONT' [203] FF,•FI 'FontSize' I '11' [204] FF,•FI 'FontStyle' I '0' [205] FF, 'FontCharset' I 'default' [206] •wi 'scale' 3 ¦ font size will be specified in points [207] •wi 'font' F [208] [209] •wi 'list' (0,1,M) [210] •wi 'onColClick' '0 CMDMF "Sort"' [211] •wi 'onDblClick' '0 CMDMF "Detail"' [212] •wi 'onOpen' "•wi 'AutoFit' 'header' 'all'" [213] •wi 'onKeyPress' '0 CMDMF •wevent' [214] [215] •wself':' [216] •wi 'Show' [217] ':mRes.mMsec' •wi 'Click' ¦ milliseconds [218] K•wi 'Wait' [219] •wi 'Delete' [220] 0 [221] [222] L1: ¦ •'MF case: ',ôA [223] [224] :SELECT A [225] [226] :CASE 'Print' ¦ print the listview [227] [228] ¦ This works for both Listviews [229] A']WPRINT :lv /QUIET /H=',•TCHT,•wi ':caption' [230] K•UCMD A [231] [232] :CASE 'Hide' [233] [234] ¦ This works for both Forms (and Listviews) [235] T1=•wi 'value' ¦ hide zero lines? [236] •wself':lv' [237] :if T [238] M•wi 'list' [239] •wi '‘list' M ¦ save for later [240] D•FI •enlist M[;2+8] ¦ raw ticks [241] M(D>0)ëM [242] :else ¦ unhide lines [243] M•wi '‘list' ¦ get old list [244] :end [245] •wi 'list' M [246] [247] :CASE 'Res' [248] [249] ¦ This works for both Forms (and Listviews) [250] (1=•wi 'value')û0 ¦ already checked? [251] (•wi 'siblings')•wi 'value' 0 ¦ turn off all checks [252] •wi 'value' 1 ¦ turn my check on [253] [254] D•wi 'caption' [255] D(^\D†•TCHT)/D ¦ ditch possible shortcut [256] DD~'&' ¦ ditch possible key [257] [258] ':mRes' •wi 'caption' ('&Resolution (',D,')') [259] [260] T1=':mView.mHide' •wi 'value' ¦ hide zero lines? [261] [262] •wself':lv' [263] [264] :if T [265] M•wi '‘list' [266] :else [267] M•wi 'list' [268] :end [269] [270] D•FI •enlist M[;2+8]  M[;2+2](D L) CMDMF 'FmtTicks' [271] D•FI •enlist M[;2+9]  M[;2+3](D L) CMDMF 'FmtTicks' [272] [273] :if T ¦ hide zero lines [274] •wi '‘list' M [275] M(D>0)ëM [276] :end [277] [278] •wi 'list' M [279] •wi 'AutoFit' 'header' 2 3 [280] [281] :CASE 'FmtTicks' [282] [283] (T F)L ¦ raw ticks, format [284] :select F [285] :case 1 ¦ raw ticks [286] R•SPLIT 'CI19' •FMT T [287] :case 2 ¦ milliseconds [288] R3ôT’•MF ý1 [289] :case 3 ¦ seconds [290] R•SPLIT 'G' •FMT 0 100 100 1000æ0 60 60 1000 ç 0.5+T’•MF ý1 [291] :else ¦ tilt [292] ö0 [293] :end [294] ((T<0)/R) '' ¦ missing data [295] RR~' ' ¦ DLB [296] [297] :CASE 'Resize' [298] [299] ¦ This works for both Forms (and Listviews) [300] [301] (1=3•warg)û0 ¦ noop if minimize [302] [303] ':lv' •wi 'where' (0 0,2•warg) [304] [305] :CASE 'Sort' [306] [307] ¦ This works for both Listviews [308] D•wi 'sortorder' ¦ current order [309] I•first •warg ¦ column number [310] M[2] ,•wi 'GetCells' D I ¦ the data [311] F( I,3)•wi 'columndisplay' ¦ justification [312] :if Fð'right' ¦ numeric column? [313] M(-+/^\èM=' ')èM ¦ RJUST [314] I•AVM ¦ descending [315] :else ¦ text column [316] I•AVM ¦ ascending order [317] :end [318] [319] :if IðâûI  IèI  :end ¦ reverse sort [320] •wi 'sortorder' (D[I]) ¦ reset the sortorder [321] [322] :CASE 'KeyPress' [323] [324] :if •warg=13 ¦ Enter key? [325] 0 CMDMF 'Detail' [326] :end [327] [328] :CASE 'Detail' [329] [330] •wself':lv' [331] I•first •wi 'value' ¦ selected row [332] :if I=0 [333] I•first •wi 'sortorder' ¦ first in list [334] (I=0)û0 [335] :end [336] F•first •wi 'GetCells' I 1 ¦ function name [337] D•MF F [338] :if 0îûD [339] K•wcall 'MessageBeep' 0 ¦ ding [340] 0 [341] :end [342] F D CMDMF 'FnDetail' [343] [344] :CASE 'FnDetail' [345] [346] (F D)L ¦ function name, •MF data [347] N•first ûD [348] M(N,9)û '' ¦ 9 cols, like summary form [349] ¦ We want these to sort correctly, so we don't left-justify them like •VR does [350] T'<',F,'[>,Q<]>I',ô1+ûôN-1 ¦ here's a technique from the old days [351] M[;1]•split T •FMT ý1+âN [352] M[1;1] F ¦ I prefer no [0] since these are totals [353] ¦ Time spent "here" on header line is negligible [354] ¦ Much more interesting is sum of time spent here on all lines [355] D[1;2]+/D[;2] [356] M[;4]ôD[;3] ¦ iterations [357] T•VR F [358] M[;5]ý1(T†•TCNL) Partition T ¦ drop trailing ì line [359] M[;8]•split 'I17' •FMT D[;1] [360] M[;9]•split 'I17' •FMT D[;2] [361] [362] TF ¦ for caption [363] ((T='‘')/T)'+' [364] ((T='ñ')/T)•AV[249+•IO] ¦ for a Form caption, that yields the plus-or-minus symbol [365] [366] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [367] •erase 'I' [368] K•fx [2] 'vk I d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ I [369] [370] w•FI 'MFDetail-Place' I '3 15 24 70' [371] v•FI 'MFDetail-Visible' I '1' [372] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [373] [374] •wself'fmMFDetail' •wi 'Create' 'Form' 'Close' [375] •wi 'caption' ('MF detail for function: ',T) [376] •wi 'place' w [377] •wi 'visible' v [378] •wi 'limitwhere' 8 20 [379] •wi 'border' 2 16 64 [380] •wi 'onResize' '0 CMDMF •wevent' [381] •wi 'onClose' '0 CMDMF •wevent' [382] •wself':mFile' •wi 'New' 'Menu' ('caption' '&File') [383] ¦K'.mPrint' •wi 'New' 'Menu' ('caption' '&Print...') ('onClick' '0 CMDMF "Print"') ('shortcut' 'P' 2) [384] ¦K'.mSep1' •wi 'New' 'Menu' ('separator' 1) [385] K'.mExit' •wi 'New' 'Menu' ('caption' 'E&xit') ('onClick' 'K":" •wi "Close"') ('shortcut' 27 0) [386] •wself':mEdit' •wi 'New' 'Menu' ('caption' '&Edit') [387] K'.mCopy' •wi 'New' 'Menu' ('caption' '&Copy entire list to clipboard') ('onClick' '0 CMDMF "Copy"') ('shortcut' 'C' 2) [388] •wself':mView' •wi 'New' 'Menu' ('caption' '&View') [389] K'.mHide' •wi 'New' 'Menu' ('caption' '&Hide lines with no time') ('onClick' '0 CMDMF "Hide"') ('style' 1) ('shortcut' 'H' 2) [390] •wself':mRes' •wi 'New' 'Menu' ('caption' '&Resolution') [391] K'.mRaw' •wi 'New' 'Menu' ('caption' '&Raw Ticks') ('onClick' '1 CMDMF "Res"') ('suppress' 1) ('shortcut' 'R' 2) [392] K'.mMsec' •wi 'New' 'Menu' ('caption' '&Millisecs') ('onClick' '2 CMDMF "Res"') ('suppress' 1) ('shortcut' 'M' 2) [393] K'.mSec' •wi 'New' 'Menu' ('caption' 'MM:&SS.mmm') ('onClick' '3 CMDMF "Res"') ('suppress' 1) ('shortcut' 'S' 2) [394] [395] ¦ Get value of key k; if undefined, write default to the ini file [396] K•fx [2] ( [2] •cr 'I'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ I [397] [398] •wself':lv' •wi 'New' 'Listview' ('style' 1 2 4 4096) ¦ 4096=gridlines [399] [400] ¦ •wi 'font' 'APLFONT' 11 0 'default' [401] F 'FontName' I 'APLFONT' [402] FF,•FI 'FontSize' I '11' [403] FF,•FI 'FontStyle' I '0' [404] FF, 'FontCharset' I 'default' [405] •wi 'scale' 3 ¦ font size will be specified in points [406] •wi 'font' F [407] [408] •wi 'columndisplay' (5 3û'Line' 20 'left' 'Total' 10 'right' 'Here' 10 'right' 'Iter' 10 'right' 'Instruction' 40 'left') [409] •wi 'list' (0,1,M) [410] [411] •wi 'onOpen' "•wi 'AutoFit' 'header' 'all'" [412] •wi 'onColClick' '0 CMDMF "Sort"' [413] [414] •wself':bnExit' •wi 'New' 'Button' 'Hide' ('style' 2) ¦ 2=cancel [415] •wself':' [416] •wi 'Show' [417] ':mRes.mMsec' •wi 'Click' [418] K•wi 'Wait' [419] •wi 'Delete' [420] [421] :CASE 'Close' [422] [423] ¦ Set value of key k in APLW.INI section [UCMDSREX] [424] K•fx [2] 'k I v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ I [425] [426] :select •wself [427] :case 'fmMF' [428] 'MF-Place' I •wi 'place' [429] 'MF-Visible' I •wi 'visible' [430] :case 'fmMFDetail' [431] 'MFDetail-Place' I •wi 'place' [432] 'MFDetail-Visible' I •wi 'visible' [433] :else [434] ö'tilt' [435] :end [436] [437] :CASE 'Copy' [438] [439] ¦ Copy to clipboard (works for both Listviews) [440] [441] •wself':lv' [442] D•wi 'sortorder' ¦ current order [443] L•wi 'columndisplay' [444] M•wi 'GetCells' D (â1ûL) ¦ the data [445] ML[;1]žM ¦ column headings [446] M•TCHT,M [447] MM, •TCNL,•TCLF [448] v•enlist 1•enlist•split M [449] vñAV2ANSI[•AVâv] [450] h•wcall 'GlobalAlloc' 'GMEM_MOVEABLE' (1+•first ûv) [451] •error (h=0)/'Unable to allocate memory for copy' [452] p•wcall 'GlobalLock' h [453] •error (p=0)/'Unable to lock memory for copy' [454] K•wcall 'W_Mem' (p,0,1, v,•tcnul) [455] K•wcall 'GlobalUnlock' h [456] w'#' •wi 'hwndmain' [457] •error (0=•wcall 'OpenClipboard' w)/'Clipboard busy' [458] K•wcall 'EmptyClipboard' [459] K•wcall 'SetClipboardData' 'CF_TEXT' h [460] K•wcall 'CloseClipboard' [461] [462] :ELSE [463] [464] •'*** Unanticipated case: ',ôA [465] [466] :END ì €ßÿt6Igg ì CMDNOTLOCAL N;A;F;I;R;S;V;c;d;f;g;h;i;n;p;s;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] ¦ 01 Sep 2005 Most recent minor update [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] s•SI[;1] ¦ first column of SI [41] s(~sî'õ•><')/s ¦ ditch •SI levels that don't have matching •IDLOC columns [42] Isâ']' ¦ how much UCMD crap is there [43] II*Ióûs ¦ or 1 if no ] (non-UCMD) [44] [45] :if ’ûF ¦ specified functions? [46] F[2](F†' ') Partition F [47] i•IDLOC F ¦ what are they [48] d(0,I)i ¦ drop our local classification [49] d(,<\ý1†d)/,d ¦ next-most-local classification [50] dd=1 ¦ which are fns [51] t~d ¦ which are not fns [52] n+/t [53] :if n>0 [54] ñOUT 'NOT FUNCTION',(n=1)'S: ',DEB,' ',tëF [55] FdëF [56] idëi [57] :end [58] :else ¦ all fns [59] ¦ all our locals should have values now, so they'll show up in •NL [60] f•SI[1;] [61] f(^\f†'[')/f [62] f•CRL f,'[0]' [63] f(fâ';')f [64] f[2](f†';') Partition f [65] f(0=•NC f)ëf [66] õ(,f,''),'0' ¦ something like abc0 assumes at least one name [67] [68] F•NL 1 2 3 ¦ all names [69] i•IDLOC F ¦ what are they [70] d(0,I)i ¦ drop our local classification [71] d(,<\ý1†d)/,d ¦ next-most-local classification [72] dd=1 ¦ which are fns [73] FdëF ¦ just fns [74] idëi ¦ just fns [75] :end [76] [77] d(I[2]i)^.=ý1 ¦ which are not shadowed [78] t~d [79] n+/t [80] :if n>0 [81] ñOUT 'SHADOWED: ',DEB,' ',tëF [82] FdëF [83] :end [84] [85] F,' ',F [86] F(F†' ') Partition F [87] u•FIRST ûF ¦ how many fns [88] [89] ñOUT 'Searching ',(ôu),' function',(u=1)'s ...' [90] [91] •WGIVE 0 ¦ let that message display [92] [93] :if R ¦ result only-mode? [94] ñRESULT0û '' [95] :end [96] [97] :if S [98] NñUCASE N [99] :end [100] [101] :for f :in F ¦ next function [102] [103] V•VR f ¦ V •VR [104] [105] :if 0=ûV [106] ñOUT '* LOCKED: ',f [107] :continue [108] :end [109] [110] :if S ¦ system name? [111] (n x d g t)5ParseVR V ¦ names context disp length system [112] (t/n)ñUCASEt/n [113] :else ¦ regular name [114] ¦ try to avoid ParseVR -- see if any raw hits [115] :if ~ú/V •SS N ¦ bail if no raw hits [116] :continue [117] :end [118] (n x d g t)5ParseVR V ¦ names context disp length system [119] :end [120] ¦ thanks a million, Zark! [121] ¦ •n,x,d,g,[1.5]t [122] hnî N ¦ hits on name ¦ î is twice as fast as ð [123] [124] ¦ bail if localized [125] :if ú/(h/x)î'ûà;' ¦ result leftarg rightarg local label [126] :continue [127] :end [128] [129] :if A ¦ assignments only? [130] hh^xî')]' ¦ direct strand indexed selective [131] :else [132] hh^x†':' ¦ ignore control structure names [133] :end [134] [135] :if ~ú/h ¦ might not have any hits left now [136] :continue [137] :end [138] [139] ¦ we have some hits! [140] [141] :if R ¦ result only-mode? [142] ñRESULTñRESULT, N [143] :continue [144] :end [145] [146] ñOUT '==> ',f,' (',(ô+/h),')' [147] [148] ¦ squeeze •VR to just lines containing hits [149] [150] ¦ p1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs) [151] ¦ but, since we never show the header line, we can get away with: [152] pV •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs) [153] p[1,ý6+ûV]1 ¦ force start of header and end of last line [154] t(ûV)û0  t[h/d]1 ¦ convert name hit flags to •VR flags [155] cú/p •PENCLOSE t ¦ flag lines with any hits [156] pp/âûp ¦ partition starts [157] g(1p)-ý1p ¦ line lengths [158] gg-1 ¦ not including trailing CR [159] :for i :in c/âûc [160] ¦ APL+Win: Show fn name too so can double-click to edit at that line [161] ñOUT f,V[p[i]+âg[i]] ¦ faster than take/drop approach [162] :end [163] •WGIVE 0 ¦ allow display [164] [165] :end ì €ßÿt6OEE ì CMDPEEK a;peek;j;k;r [1] ¦ Peek at a function or variable in another workspace [2] ¦ Designed to be used after ]SymFind, which may have displayed something like [3] ¦ 0 EVLEVEL ì foo [4] ¦ \aplwin40\EVLEVEL ì foo [5] ¦ 0 FFA  foo [6] ¦ 0 RTF2HTML * RUNTIME WS [7] ¦ The idea is that you type ]Peek in front of one of those lines [8] ¦ So, argument is wsid symbol objectname [9] ¦ Or, just wsid objectname so can be used like )COPY command syntax [10] ¦ 02 Dec 2002 Rex Swain, Independent Consultant, www.rexswain.com [11] ¦ 16 Jun 2005 Evlevel-neutral [12] [13] :if '*'îa [14] ñOUT 'PEEK ERROR: NO CAN DO (ASTERISK)' [15] 0 [16] :end [17] [18] aDLTB a [19] [20] j(è^\èa†' ')/a ¦ last word: object name [21] aDTB (-ûj)a [22] [23] :if (ý1a)î'ì:' ¦ last char symbol? [24] aDTB ý1a ¦ throw it away [25] :end [26] [27] :if 0=ûa [28] ñOUT 'PEEK ERROR: SPECIFY WSID AND OBJECT NAME' [29] 0 [30] :end [31] [32] k•DEF[2]('rj peek a;k;',j) 'rj •copy a' '(rî1 2)0' "k•WCALL 'W_Edit' j" [33] rj peek a [34] ¦ ñRESULTr [35] (rî1 2)û0 [36] k'•COPY RC ',(ôr),' : ' [37] :select •first r [38] :case 0  ñOUT k,'Object not found' [39] :case 127  ñOUT k,'Duplicate name in objlist ¦ should not get here!' [40] :case ý2  ñOUT k,'Object too large for available space' [41] :case ý3  ñOUT k,'Name defined as a label; cannot be changed' [42] :case ý4  ñOUT k,'Insufficient space in symbol table and workspace too full to expand symbol table' [43] :case ý6  ñOUT k,'Insufficient free space to carry out command' [44] :end [45] [46] ¦ •COPY result codes: [47] ¦ 2 = variable successfully copied [48] ¦ 1 = function successfully copied [49] ¦ 0 = object not found [50] ¦ 127 = duplicate name in objlist [51] ¦ ý2 = object too large for available space [52] ¦ ý3 = name defined as a label; cannot be changed [53] ¦ ý4 = insufficient space in symbol table and workspace too full to expand symbol table [54] ¦ ý6 = insufficient free space to carry out command [55] ì üíU€ßÿt64­S­S ì G CMDPEEKWS N;B;F;I;P;T;V;a;b;c;d;e;f;h;i;j;k;m;nf;n;p;q;rc;r;st;s;t;v;w;x;z;•wself [1] ¦ Browse functions/variables in workspace N [2] [3] ¦ Syntax: [4] ¦ ]PEEKWS wsid [5] ¦ Options for names: [6] ¦ /ì ¦ functions only [7] ¦ / ¦ variables only [8] ¦ View options (see also View menu): [9] ¦ /B ¦ Bytes [10] ¦ /T ¦ Timestamp (YYYY/MM/DD HH:MM:SS) [11] [12] ¦ Double-click on a line to peek at the object [13] ¦ Then Ctrl+Q to quit, or Ctrl+E to define the object in the active ws [14] ¦ Click on a column heading to sort by that column; click again to reverse sort [15] [16] ¦ Weaknesses: [17] ¦ - RDST will untie any .W3 files that were already •XNTIEd [18] ¦ - I make no attempt to detect name conflicts when peeking [19] [20] ¦ To do: [21] ¦ - Add command to "Copy" or "Define" selected object(s) in active ws [22] ¦ &Actions \ Define in active &ws ; could be multiple rows [23] ¦ Just like GetInfo but don't localize, 0=Get 1=Peek 2=Define [24] [25] ¦ Requires: DLB DLTB FFAW RDST [26] ¦ 26 Oct 2003 Rex Swain, Independent Consultant, www.rexswain.com [27] ¦ 25 Sep 2004 Use font settings in APLW.INI [UCMDSREX] [28] ¦ 26 Mar 2005 Evlevel-neutral [29] ¦ 06 Oct 2005 Don't allow -options (because filespecs may contain hyphens) [30] ¦ 26 Mar 2006 Most recent bug fix [31] [32] (’•NC 'G')ûL9 ¦ left arg means callback [33] [34] Nô•ENLIST N ¦ arg could be numeric in development mode [35] [36] :if N^.=' ' ¦ no argument? [37] ñOUT 'For help, execute',•tcnl,' ]PEEKWS ?' [38] 0 [39] :end [40] [41] B1=ûûN ñGETOPT '/B' ¦ bytes [42] T1=ûûN ñGETOPT '/T' ¦ timestamp [43] F1=ûûN ñGETOPT '/ì' ¦ functions only? [44] V1=ûûN ñGETOPT '/' ¦ variables only? [45] [46] NDLTB (^\N†'/')/N ¦ delete all /options [47] [48] :if FåV [49] FV1 ¦ default: functions and variables [50] :end [51] [52] F(F/'ì'),V/'' ¦ fns/vars filter [53] [54] ¦ Compose native file name [55] [56] :if •FIRST •VI N ¦ leading number means a library number (probably!) [57] p•FIRST •FI N [58] p•LIBD p ¦ library path [59] pp,((ý1p)î'\:')'\' ¦ force trailing backslash, unless 'D:' [60] w(ú\~Nî'1234567890 ')/N ¦ ws name [61] nfp,w,'.w3' ¦ native file [62] :else ¦ directory\wsid [63] nfN,'.w3' ¦ native file [64] :end [65] [66] ¦ Read symbol table [67] [68] stRDST nf ¦ here's the magic: read symbol table [69] :if 1=ûûst ¦ error message? [70] ñOUT st,': ',nf [71] 0 [72] :end [73] :if 0îûst [74] ñOUT 'No names in ws : ',N [75] 0 [76] :end [77] [78] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [79] k•fx [2]'vk I d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ I [80] [81] w•FI 'PeekWS-Place' I '4 10 16 60' [82] v•FI 'PeekWS-Visible' I '1' [83] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [84] [85] •wself'fmPeekWS' •wi 'Create' 'Form' 'Hide' [86] •wi 'caption' ('PeekWS ',N) [87] •wi 'place' w [88] •wi 'visible' v [89] e' CMDPEEKWS •wevent' [90] •wi 'onClose' e [91] •wi 'onDropDown' e [92] •wi 'pointer' 11 ¦ 11=hourglass (wait) [93] [94] •wself':mFile' •wi 'New' 'Menu' [95] •wi 'caption' '&File' [96] [97] •wself'.mExit' •wi 'New' 'Menu' [98] •wi 'caption' 'E&xit' [99] •wi 'shortcut' 'X' 2 [100] •wi 'onClick' "0 0û':' •wi 'Close'" [101] [102] •wself':mEdit' •wi 'New' 'Menu' [103] •wi 'caption' '&Edit' [104] [105] •wself'.mAll' •wi 'New' 'Menu' [106] •wi 'caption' 'Select &All' [107] •wi 'shortcut' 'A' 2 [108] •wi 'onClick' " CMDPEEKWS 'All'" [109] [110] •wself'..mNone' •wi 'New' 'Menu' [111] •wi 'caption' 'Select &None' [112] •wi 'shortcut' 'N' 2 [113] •wi 'onClick' " CMDPEEKWS 'None'" [114] [115] •wself'..mInvert' •wi 'New' 'Menu' [116] •wi 'caption' '&Invert Selection' [117] •wi 'shortcut' 'I' 2 [118] •wi 'onClick' " CMDPEEKWS 'Invert'" [119] [120] •wself':mView' •wi 'New' 'Menu' [121] •wi 'caption' '&View' [122] [123] c" CMDPEEKWS 'View'" [124] [125] •wself'.mTime' •wi 'New' 'Menu' [126] •wi 'caption' '&Timestamp' [127] •wi 'shortcut' 'T' 2 [128] •wi 'style' 1 [129] •wi 'value' T [130] •wi 'data' 3 [131] •wi 'onClick' c [132] [133] •wself'..mBytes' •wi 'New' 'Menu' [134] •wi 'caption' '&Bytes' [135] •wi 'shortcut' 'B' 2 [136] •wi 'style' 1 [137] •wi 'value' B [138] •wi 'data' 4 [139] •wi 'onClick' c [140] [141] •wself'..mDepth' •wi 'New' 'Menu' [142] •wi 'caption' 'D&epth' [143] •wi 'shortcut' 'E' 2 [144] •wi 'style' 1 [145] •wi 'value' 1 [146] •wi 'data' 5 [147] •wi 'onClick' c [148] [149] •wself'..mShape' •wi 'New' 'Menu' [150] •wi 'caption' '&Shape' [151] •wi 'shortcut' 'S' 2 [152] •wi 'style' 1 [153] •wi 'value' 1 [154] •wi 'data' 6 [155] •wi 'onClick' c [156] [157] •wself'..mValue' •wi 'New' 'Menu' [158] •wi 'caption' 'Va&lue' [159] •wi 'shortcut' 'L' 2 [160] •wi 'style' 1 [161] •wi 'value' 1 [162] •wi 'data' 7 [163] •wi 'onClick' c [164] [165] •wself':mActions' •wi 'New' 'Menu' [166] •wi 'caption' '&Actions' [167] [168] •wself'.mPeek' •wi 'New' 'Menu' [169] •wi 'caption' '&Peek' [170] •wi 'shortcut' 'P' 2 [171] •wi 'onClick' "1 CMDPEEKWS 'Peek'" ¦ 1=peek [172] [173] •wself'..mGet' •wi 'New' 'Menu' [174] •wi 'caption' '&Get Info' [175] •wi 'shortcut' 'G' 2 [176] •wi 'onClick' "0 CMDPEEKWS 'Peek'" ¦ 0=get info [177] [178] •wself'..mGetAll' •wi 'New' 'Menu' [179] •wi 'caption' 'Get Info for &All' [180] •wi 'shortcut' 'G' 4 [181] •wi 'onClick' " CMDPEEKWS 'GetAll'" [182] [183] •wself'..mDiff' •wi 'New' 'Menu' [184] •wi 'caption' '&Diff' [185] •wi 'shortcut' 'D' 2 [186] •wi 'onClick' " CMDPEEKWS 'Diff'" [187] [188] •wself'..mRemove' •wi 'New' 'Menu' [189] •wi 'caption' '&Remove from list' [190] •wi 'shortcut' (46 0) ¦ 46=Del [191] •wi 'onClick' " CMDPEEKWS 'Remove'" [192] [193] •wself'..mFns' •wi 'New' 'Menu' [194] •wi 'caption' '&Functions only' [195] •wi 'shortcut' 'F' 2 [196] •wi 'onClick' "'ì' CMDPEEKWS 'Only'" [197] [198] •wself'..mVars' •wi 'New' 'Menu' [199] •wi 'caption' '&Variables only' [200] •wi 'shortcut' 'V' 2 [201] •wi 'onClick' "'' CMDPEEKWS 'Only'" [202] [203] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [204] c0 3û0 [205] ccž'Name' 16 'left' ¦ 2 [206] ccž'C' 2.5 'center' ¦ 1 ¦ first col must be left justified [207] [208] ccž'Timestamp' (T’20) 'right' ¦ 3 ¦ rjust in case of '-' [209] ccž'Bytes' (B’8) 'right' ¦ 4 [210] ccž'ð' 2.5 'right' ¦ 5 [211] ccž'Shape' 8 'right' ¦ 6 [212] ccž'Value' 32 'left' ¦ 7 [213] [214] ¦ Get value of key k; if undefined, write default to the ini file [215] k•fx [2]( [2] •cr 'I'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ I [216] [217] •wself':lv' •wi 'New' 'Listview' [218] •wi 'where' 0.5 1 ¦ this establishes gaps [219] •wi 'style' 1 2 4 1024 4096 ¦ 1024=reorder cols 4096=gridlines [220] •wi 'columndisplay' c [221] [222] ¦ •wi 'font' 'APLFONT' 11 0 'default' [223] f 'FontName' I 'APLFONT' [224] ff,•FI 'FontSize' I '11' [225] ff,•FI 'FontStyle' I '0' [226] ff, 'FontCharset' I 'default' [227] •wi 'scale' 3 ¦ font size will be specified in points [228] •wi 'font' f [229] [230] •wi 'onColClick' e ¦ sort [231] •wi 'onDblClick' e ¦ peek [232] •wi 'onKeyPress' e ¦ Enterpeek [233] •wi 'onClick' e ¦ select [234] [235] •wi 'AutoFit' 'header' ((T/3),(B/4),5 6) [236] [237] •wself':l1' •wi 'New' 'Label' [238] •wi 'caption' '' [239] h1 1•wi 'Draw' ('?Text' 'AB') ¦ perhaps 0.8 [240] •wi 'size' h 10 [241] [242] hö•first '#' •wi 'units' ¦ pixel height, in chars [243] h1.2524’h ¦ button height [244] [245] •wself':bnExit' •wi 'New' 'Button' [246] •wi 'caption' 'Stop' [247] •wi 'size' h 8 [248] •wi 'style' 2 ¦ 2=cancel [249] •wi 'onClick' "':' •wi '‘stop' 1" [250] [251] •wself':bnAll' •wi 'New' 'Button' [252] •wi 'caption' '&Get All Info' [253] •wi 'size' h 8 [254] •wi 'onClick' " CMDPEEKWS 'GetAll'" [255] [256] •wself':' [257] [258] •wi 'onResize' e [259] 0 CMDPEEKWS 'Resize' [260] k•wi 'Show' [261] [262] ':bnExit' •wi 'Focus' ¦ so you can hit Enter or Esc to interrupt [263] [264] •wself':lv' [265] [266] •wi '‘N' N ¦ save wsid [267] [268] m0 2st ¦ names [269] i•AVm ¦ to sort by name [270] mm[i;] [271] m( [2]m)~' ' ¦ object names cannot contain blanks [272] tst[i;1] [273] [274] btîF ¦ fns/vars filter [275] :for j :in b/âûb [276] k•wi 'AddRows' 0 1 (jm) (jt) [277] :end [278] [279] •wi 'AutoFit' 'header' (1 2,(T/3),(B/4),5 6 7) [280] [281] n+/tî'ì' [282] q'Found ',(n†0)/(ôn),' function' [283] v+/t='' [284] qq,((’v’n)/' and '),(v†0)/(ôv),' variable' [285] qq,(-1=v+n)' names' [286] [287] ':l1' •wi 'caption' q [288] [289] •wself':bnExit' [290] •wi 'onClick' '' ¦ this enables the style 2=cancel behavior [291] •wi 'caption' 'E&xit' [292] [293] •wself':' [294] [295] •wi 'pointer' 0 [296] [297] :if ']'î•SI[;1] ¦ user command? [298] k•wi 'Wait' [299] :else [300] k•wi 'Show' [301] :end [302] [303] 0 [304] [305] L9: ¦ ========== Callbacks ========== [306] [307] :SELECT N [308] [309] :CASE 'Remove' [310] [311] •wself':lv' [312] v•wi 'value' ¦ selected row(s) [313] •wi 'DeleteRows' v [314] [315] :CASE 'Only' [316] [317] •wself':lv' [318] a•wi 'sortorder' ¦ all row ids [319] c•first,•wi 'GetCells' a 2 ¦ class [320] v(~cî G)/a [321] •wi 'DeleteRows' v [322] [323] :CASE 'KeyPress' [324] [325] :if •warg=13 ¦ Enter key? [326] 1 CMDPEEKWS 'Peek' [327] :end [328] [329] :CASE 'Peek' [330] [331] ¦ G is 1 for peek, 0 for get info [332] •wself':lv' [333] v•wi 'value' ¦ selected row(s) [334] (0=ûv)û0 ¦ nothing selected [335] :if G [336] i1v ¦ if many selected, just peek at first [337] i G CMDPEEKWS 'PeekRow' [338] :else [339] :if 1=ûv [340] v G CMDPEEKWS 'PeekRow' ¦ one row [341] :else [342] v CMDPEEKWS 'GetRows' ¦ hourglass, etc. [343] :end [344] :end [345] [346] :CASE 'DblClick' [347] [348] r1•warg ¦ rowid [349] r 1 CMDPEEKWS 'PeekRow' [350] [351] :CASE 'All' [352] [353] •wself':lv' [354] a•wi 'sortorder' ¦ all row ids [355] •wi 'value' a [356] [357] :CASE 'None' [358] [359] ':lv' •wi 'value'  [360] [361] :CASE 'Invert' [362] [363] •wself':lv' [364] a•wi 'sortorder' ¦ all row ids [365] v•wi 'value' ¦ selected rowids [366] •wi 'value' (a~v) [367] [368] :CASE 'Resize' [369] [370] ¦ ••wself •wevent (FFA •warg) [371] z•wi 'size' ¦ form size [372] (0îz)û0 ¦ minimized? don't bother doing anything [373] a':l1' •wi 'size' ¦ label size [374] b':bnExit' •wi 'size' ¦ button size [375] hb[1]2’a[1] ¦ height needed [376] [377] •wself':lv' [378] w•wi 'where' [379] w[3 4]z-2’w[1 2] ¦ form size, less top/bottom/left/right gaps [380] w[3]w[3]-h+w[1] ¦ less buttons and another vertical gap [381] •wi 'where' w ¦ move and resize [382] [383] •wself':bnExit' [384] tw[1 2]+w[3 4] ¦ botton right of :lv [385] t[2]t[2]-b[2] ¦ move left [386] vt[1]+w[1] ¦ top gap [387] t[1]v+0.5’h-b[1] ¦ plus half of label height differential [388] •wi 'where' t ¦ just move [389] [390] •wself':bnAll' [391] t[2]t[2]-b[2]+w[2] [392] •wi 'where' t ¦ just move [393] [394] •wself':l1' [395] w[1]v+a[1]ö2 [396] w[3]a[1] [397] w[4]t[2]-2’w[2] [398] •wi 'where' w [399] [400] :CASE 'ColClick' [401] [402] c1•warg ¦ column clicked [403] i•wi 'sortorder' ¦ all rowids [404] d,•wi 'GetCells' i c ¦ data [405] :if cò3 ¦ info columns [406] dôd ¦  is in unset cells [407] :end [408] m[2]d ¦ simple char matrix [409] :if cî4 5 6 ¦ bytes depth shape? [410] m(-+/^\èm=' ')èm ¦ right justify [411] :end [412] d•AVm [413] :if dðâûd ¦ already sorted? [414] dèd ¦ descending [415] :end [416] •wi 'sortorder' (i[d]) [417] [418] :CASE 'PeekRow' [419] [420] (r G)G ¦ rowid  1 for peek, 0 for get info [421] (j c),•wi 'GetCells' r (1 2) ¦ name class [422] [423] (r c j G) CMDPEEKWS 'PeekWsid' [424] [425] :CASE 'PeekWsid' [426] [427] (r c j G)G ¦ row class name peek [428] N•wi '‘N' ¦ saved wsid [429] [430] z~G [431] k " rj P a;k;•ELX;*" [432] kk,"@ •ELX'r9  0'" ¦ handle possible INCOMPATIBLE WS error from •COPY [433] kk,"@ rj •COPY a" [434] kk,"@ (rî1 2)0" [435] kk,"@ rr,•SIZE j" [436] kk,"@ :select •first r" [437] kk,"@ :case 1" ¦ function [438] kk,"@ rr,(2 •AT j)(•VR j)" [439] kk,z/"@ 0" ¦ get info only [440] kk,"@ (û4r)0" ¦ don't try to edit if locked [441] kk,"@ k•WCALL 'W_Edit' j" [442] kk,"@ :case 2" ¦ variable [443] kk,"@ v*" [444] kk,"@ rr,'' v" [445] kk,z/"@ 0" ¦ get info only [446] kk,"@ :if 1=ûûv" [447] kk,"@ :andif 5óûv" [448] kk,"@ :andif 'PACKAGE'ð1v" [449] kk,"@ •UCMD 'PKGDOC ',j" [450] kk,"@ 0" [451] kk,"@ :elseif (ðv)>1" [452] kk,"@ :orif (ûûv)>2" [453] kk,"@ :orif ^/0 ' 'î•TYPE •enlist v" [454] kk,"@ v•UCMD 'DISPLAY v'" [455] kk,"@ *v" [456] kk,"@ :end" [457] kk,"@ k•WCALL 'W_Edit' j" [458] kk,"@ :end" [459] [460] ((k='*')/k) j [461] k•enlist k [462] k(k†'@') Partition k [463] k•DEF[2]k ¦õ P [464] ¦ ••vr k [465] (rc z t x)4j P N ¦ peek [466] :if rcî1 2 [467] a256 ¦ max width of FFA display [468] zDLB,'CI15' •FMT z ¦ format bytes [469] :if rc=2 ¦ variable [470] t'-' [471] sûx ¦ shape [472] s(ôs),(0=ûs)/'' ¦ format shape [473] dôðx ¦ depth [474] xa FFAW x [475] x(aûx)ûx [476] qxâ'û' [477] :if qóûx [478] :andif q,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6ût [483] d'-' ¦ depth [484] ¦s(ô+/x •SS •TCNL,'['),' lines' [485] :if c='' [486] s'?' [487] x'(locked function)' [488] :else [489] sôûx [490] x(aûx)ûx [491] ((x=•TCNL)/x)' ' [492] :end [493] :end [494] c3 4 5 6 7 ¦ timestamp bytes depth shape value [495] •wi 'SetCells' r c (t z d s x) [496] ¦ display •wi 'GetCells' r c [497] m•wi 'columndisplay' [498] c(0†m[c;2])/c ¦ only visible columns [499] •wi 'AutoFit' 'header' c [500] 0 [501] :end [502] [503] môrc [504] ((m='ý')/m)'-' [505] m'Return code ',m,' from []COPY:',•tcnl [506] [507] :select rc [508] :case 0  mm,'Object not found' [509] :case 127  mm,'Duplicate name in objlist ¦ should not get here!' [510] :case ý2  mm,'Object too large for available space' [511] :case ý3  mm,'Name defined as a label; cannot be changed' [512] :case ý4  mm,'Insufficient space in symbol table and workspace too full to expand symbol table' [513] :case ý6  mm,'Insufficient free space to carry out command' [514] :case 9  m 'Error from []COPY:',•TCNL,(^\•DM†•TCNL)/•DM [515] :else  mm,'Unanticipated return code!' [516] :end [517] [518] k•wcall 'MessageBox' (•wi ':hwnd') m 'COPY ERROR' 'MB_ICONSTOP' [519] [520] :CASE 'Close' [521] [522] ¦ Set value of key k in APLW.INI section [UCMDSREX] [523] k•fx [2]'k I v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ I [524] [525] 'PeekWS-Place' I •wi 'place' [526] 'PeekWS-Visible' I •wi 'visible' [527] [528] :CASE 'DropDown' [529] [530] ¦ •wself is the form; can't tell which menu item was clicked [531] [532] •wself':lv' [533] [534] i•wi 'sortorder' ¦ all rowids [535] v•wi 'value' ¦ selected rowids [536] nûv [537] [538] •wself':mActions' [539] [540] '.mPeek' •wi 'enabled' (n>0) [541] '.mGet' •wi 'enabled' (n>0) [542] '.mGetAll' •wi 'enabled' ((ûi)>0) [543] '.mDiff' •wi 'enabled' (n=2) [544] '.mRemove' •wi 'enabled' (n>0) [545] [546] :CASE 'Click' [547] [548] ¦ If there are 0 rows selected, act on the pointed-to row [549] ¦ Else always act on selected row(s) [550] [551] a•warg ¦ pointed-to rowid; save to perhaps pass along to DblClick [552] b7a ¦ mouse button (1=left 2=right) [553] (b†2)û0 ¦ quit unless right (row selection has already been toggled) [554] v•wi 'value' ¦ selected rowids [555] r1a ¦ pointed-to rowid; save to perhaps pass along to DblClick [556] r0 ¦ quit if empty row [557] z•first •wi 'GetCells' r 4 ¦ bytes (tells us if we have done Get Info already) [558] [559] f•wself [560] [561] m'mPeekWSPopup' [562] •wselfm •wi 'Create' 'Menu' [563] k'.m1' •wi 'New' 'Menu' ('caption' 'Peek') ('onClick' "':' •wi 'data' 1") [564] k'.m2' •wi 'New' 'Menu' ('caption' 'Get Info') ('onClick' "':' •wi 'data' 2") ('enabled' (0îûz)) [565] k'.m3' •wi 'New' 'Menu' ('caption' 'Diff') ('onClick' "':' •wi 'data' 3") ('enabled' (2=ûv)) [566] k'.m4' •wi 'New' 'Menu' ('caption' 'Remove from list') ('onClick' "':' •wi 'data' 4") [567] [568] •wselff [569] [570] ':' •wi 'Popup' m 2 ¦ 2=make the menu respond to the right mouse button [571] dm •wi 'data' [572] m •wi 'Delete' [573] [574] :select d [575] :case 0 ¦ escape [576] ¦ noop [577] :case 1 ¦ peek [578] r 1 CMDPEEKWS 'PeekRow' [579] :case 2 ¦ get info [580] :for i :in v [581] i 0 CMDPEEKWS 'PeekRow' [582] :end [583] :case 3 ¦ diff [584]  CMDPEEKWS 'Diff' [585] :case 4 ¦ remove [586] •wi 'DeleteRows' v [587] :else ¦ tilt [588] ö0 [589] :end [590] [591] :CASE 'View' [592] [593] ¦ •wself is a menu item [594] v•wi 'value' ¦ value has already changed [595] c•wi 'data' ¦ display column number [596] •wself':lv' [597] :if v ¦ if turning on, we just need to autofit it [598] •wi 'AutoFit' 'header' c [599] :else ¦ if turning off, we need to change width to 0 [600] m•wi 'columndisplay' [601] m[c;2]0 [602] •wi 'columndisplay' m [603] :end [604] [605] :CASE 'FontSize' [606] [607] •'FontSize' •wself [608] c•wi 'caption' [609] •wself':lv' [610] •f•wi 'font' ¦ 'APL+WIN' 11 0 'default' [611] (2f)õc [612] •wi •'font' f [613] [614] :CASE 'GetAll' [615] [616] •wself':lv' [617] w•wi 'sortorder' ¦ all rowids [618] w CMDPEEKWS 'GetRows' [619] [620] :CASE 'GetRows' [621] [622] wG ¦ rowids [623] [624] ':' •wi 'pointer' 11 [625] [626] •wself':bnExit' [627] •wi 'caption' 'Stop' [628] •wi 'onClick' "':' •wi '‘stop' 1" [629] [630] •wself':lv' [631] [632] d,•wi 'GetCells' w 4 ¦ bytes [633] w(0îûd)/w ¦ not got yet [634] [635] :for i :in w [636] •wgive 0 [637] :if ':' •wi '‘stop' [638] ':' •wi '‘stop' 0 [639] :leave [640] :end [641] i 0 CMDPEEKWS 'PeekRow' [642] :end [643] [644] ':' •wi 'pointer' 0 [645] [646] •wself':bnExit' [647] •wi 'onClick' '' [648] •wi 'caption' 'E&xit' [649] [650] :CASE 'Diff' [651] [652] •wself':lv' [653] v•wi 'value' ¦ selected rowids [654] j,•wi 'GetCells' v 1 ¦ names [655] N•wi '‘N' ¦ saved wsid [656] •UCMD •' ]DIFF ',(N,' ',1j),' ; ',N,' ',2j ¦ show ucmd being invoked [657] [658] :ELSE [659] [660] •'Unanticipated callback!' N •wself •wevent •warg [661] [662] :ENDSELECT [663] ì €ßÿt6 ÏÏ ì 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] [37] Jô,J [38] [39] P1=•first ûûJ ñGETOPT '/P' ¦ properties? [40] E1=•first ûûJ ñGETOPT '/E' ¦ events? [41] M1=•first ûûJ ñGETOPT '/M' ¦ methods? [42] X1=•first ûûJ ñGETOPT '/X' ¦ activex only? [43] S ,J ñGETOPT '/î' ¦ substring [44] [45] SñUCASE S~' ' [46] p•FX [2] (-Sð'')  'aF a' 'a(ú/(ñUCASEa) •SS S)/a' ¦õ F S [47] [48] :if ~PúEúM [49] PEM1 ¦ default to all [50] :end [51] [52] p•FX [2] (X-1)  "rx r" "r((•firstr)î 'xX+')/r" ¦õ x ¦ /X filter [53] [54] G0 ¦ generic object flag [55] [56] J(^\~Jî'/-')/J ¦ delete all options [57] JDLTB J [58] [59] iý1+Jâ'?' [60] QiJ ¦ possible '?prop' or '??prop' [61] JDTB iJ [62] [63] i/P E M’•enlist û'Properties: ' 'Events: ' 'Methods: ' [64] h-i [65] [66] :if Jð'' ¦ ]pem [67] J•wself [68] :elseif '•WI'ðñUCASE 3J [69] L1 [70] :elseif ú/'''"'îJ ¦ ]pem 'fm.bn' [71] JõJ [72] :else [73] :if '.'îJ ¦ ]pem fm.bn [74] :orif 0†ûJ •wi 'self' ¦ ]pem fm [75] ¦ noop [76] :elseif ( J)î'ActiveControl' 'ActiveObject' [77] •'No can do: ',J [78] 0 [79] :elseif ( J)î'Form' 'MDIForm' [80] •wself'fmCMDPEM' •wi 'Create' J 'Hide' [81] G1 [82] :elseif Jð'Page' [83] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [84] •wself'.sel' •wi 'New' 'Selector' [85] •wself'.pg' •wi 'New' J [86] G1 [87] :elseif Jð'CommandButton' [88] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [89] •wself'.bar' •wi 'New' 'CommandBar' [90] •wself'.b' •wi 'New' J [91] G1 [92] :elseif ( J)îc'#' •wi 'classes' ¦ note c [93] :orif ( J)î'UEdit' 'ULabel' 'UButton' ¦ sigh -- when will these become visible? [94] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [95] •wself('.',J) •wi 'New' J [96] G1 [97] :elseif Jð'Grid' [98] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [99] •wself('.',J) •wi 'New' 'APL.Grid' [100] G1 [101] :elseif Jð'Chart' [102] •wself'fmCMDPEM' •wi 'Create' 'Form' 'Hide' [103] •wself('.',J) •wi 'New' 'ChartFX.Chart' [104] G1 [105] :elseif Jð'WSEngine' [106] •wself'wseCMDPEM' •wi 'Create' 'APLW.WSEngine' ¦ default is hidden [107] G1 [108] :elseif (,2)ð•NC J ¦ variable name? (•nc returns 4 for invalid name) [109] JõJ [110] :else [111] •'Argument is not an object or class: ',J [112] 0 [113] :end [114] :end [115] [116] :if ~G [117] a•ELX [118] •ELX'•(^\•DM†•TCNL)/•DM  0' [119] •wselfJ ¦ OBJECT ERROR if no such [120] •ELXa [121] J•wself ¦ fully qualified name [122] •(h'Object: '),J [123] :end [124] [125] :if ’ûQ [126] ••wi Q [127] 0 [128] :end [129] [130] a•wi 'class' [131] •(h'Class: '),a [132] aað'System' ¦ flag for system object [133] [134] hh+1 ¦ because ô will add a leading blank [135] [136] mx •wi 'methods' [137] f( 'Info')îm ¦ is Info method available (APL+Win version 5) [138] [139] :if P [140] pF x •wi 'properties' [141] :if f [142] tF x •wi 'Info' 'ph' [143] pp,(0=ût)( '++'),t [144] :end [145] •i WW (h'Properties:'),ôp [146] :end [147] [148] :if E [149] eF x •wi 'events' [150] :if f [151] tF x •wi 'Info' 'eh' [152] ee,(0=ût)( '++'),t [153] :end [154] •i WW (h'Events:'),ôe [155] :end [156] [157] :if M [158] ¦mF x •wi 'methods' [159] mF m [160] :if f [161] tF x •wi 'Info' 'mh' [162] mm,(0=ût)( '++'),t [163] :end [164] •i WW (h'Methods:'),ôm [165] :end [166] [167] :if G [168] p':' •wi 'self' ¦ Form or WSEngine [169] p •wi 'Delete' [170] 0 [171] :end [172] [173] (P^E^M)0 ¦ quit unless all [174] (Xú’ûS)û0 ¦ quit if /X or /î [175] [176] c•wi 'children' [177] :if ~a ¦ unless system [178] c(1+•first ûJ)c ¦ drop self-prefix from children [179] :end [180] •i WW (h'Children:'),ôc [181] [182] :if ~a ¦ system object does not have siblings property [183] s•wi 'siblings' [184] ss~ J ¦ don't include self [185] s(+/ú\èJ='.')s [186] •i WW (h'Siblings:'),ôs [187] :end [188] [189] 0 [190] [191] L1: ¦ ----- Active Object ----- [192] [193] ¦ RHS 8/10/08 [194] ¦ 'word.doc' •wi 'xFields(4)' is nice and returns a scalar pointer. [195] ¦ 'word.doc' •wi 'xFormFields(4)' returns a pointer and the item number! [196] ¦ So just use the first number... [197] J'•FIRST ',J [198] [199] :if ’ûQ [200] •(õJ) •wi Q [201] 0 [202] :end [203] [204] a(õJ) •wi 'class' [205] •(h'Class: '),a [206] [207] hh+1 ¦ because ô will add a leading blank [208] [209] :if P [210] pF x (õJ) •wi 'properties' [211] tF x (õJ) •wi 'Info' 'ph' [212] pp,(0=ût)( '++'),t [213] •i WW (h'Properties:'),ôp [214] :end [215] [216] :if E [217] eF x (õJ) •wi 'events' [218] tF x (õJ) •wi 'Info' 'eh' [219] ee,(0=ût)( '++'),t [220] •i WW (h'Events:'),ôe [221] :end [222] [223] :if M [224] mF x (õJ) •wi 'methods' [225] tF x (õJ) •wi 'Info' 'mh' [226] mm,(0=ût)( '++'),t [227] •i WW (h'Methods:'),ôm [228] :end [229] ì €ßÿt6Iââ ì b CMDPKGDOC f;C;I;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] [17] (’•NC 'b')ûL8 ¦ dummy left arg means callback [18] [19] fô•ENLIST f ¦ arg might be numeric in development mode [20] [21] max256 ¦ max width of FFA display [22] [23] fDEB f [24] :if (1f)î'1234567890' [25] ((fî',#')/f)' ' [26] (1 1ð•VI f)L9 [27] pô•FI f ¦ also for caption [28] x'•FREAD ',p ¦ how to get package [29] :else [30] c•NC f ¦ •NC does not fail on invalid names [31] (4îc)ûL9 ¦ 4=invalid [32] (1†ûc)ûL9 ¦ too many/few names [33] s•SI[;1] ¦ first column of SI [34] s(~sî'õ•><')/s ¦ ditch •SI levels that don't have matching •IDLOC columns [35] usâ']' ¦ how much UCMD crap is there [36] uu*uóûs ¦ or 1 if no ] (non-UCMD) [37] :if uò(ý1†,•IDLOC f)â1 [38] ñOUT 'Shadowed: ',f [39] 0 [40] :end [41] :if c†2 [42] ñOUT 'Not a variable: ',f [43] 0 [44] :end [45] xf ¦ how to get package [46] pf ¦ caption [47] ((p='‘')/p)'+' [48] ((p='ñ')/p)•AV[249+•IO] ¦ for a Form caption, that yields the plus-or-minus symbol [49] [50] :end [51] [52] Kõx [53] [54] :if 1†ûûK [55] :orif 5>ûK [56] :orif ~'PACKAGE'ð1K [57] ñOUT 'Not a package: ',f [58] 0 [59] :end [60] [61] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [62] k•fx [2] 'vk I d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ I [63] [64] w•FI 'PkgDoc-Place' I '2 5 20 70' [65] v•FI 'PkgDoc-Visible' I '1' [66] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [67] [68] •wself'fmPkgdoc' •wi 'Create' 'Form' [69] •wi 'caption' ('PkgDoc ',p) [70] •wi 'place' w [71] •wi 'visible' v [72] •wi 'onClose' ' CMDPKGDOC •wevent' [73] •wi '‘x' x [74] [75] •wself':mFile' •wi 'New' 'Menu' [76] •wi 'caption' '&File' [77] [78] •wself'.mExit' •wi 'New' 'Menu' [79] •wi 'caption' 'E&xit' [80] •wi 'shortcut' 'X' 2 [81] •wi 'onClick' "0 0û':' •wi 'Close'" [82] [83] •wself':bn' •wi 'New' 'Button' [84] •wi 'size' 1.25 8 [85] •wi 'style' 2 ¦ 2=cancel [86] •wi 'caption' 'E&xit' [87] [88] (M C P)K[3 4 5] ¦ object names, classes, pointers [89] nûûM [90] [91] cwûôn ¦ component number display width [92] uwý1ûM [93] [94] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [95] c0 3û0 [96] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [97] ccž'#' 5 'right' ¦ 2 [98] ccž'Name' (1.5+uw) 'left' ¦ 3 [99] ccž'C' 2.5 'center' ¦ 4 [100] ccž'Bytes' 8 'right' ¦ 5 [101] ccž'ð' 2.5 'right' ¦ 6 [102] ccž'Shape' 8 'right' ¦ 7 [103] ccž'Value' 80 'left' ¦ 8 [104] [105] ¦ Get value of key k; if undefined, write default to the ini file [106] k•fx [2] ( [2] •cr 'I'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ I [107] [108] •wself':lv' •wi 'New' 'Listview' [109] •wi 'where' 0.5 1 [110] •wi 'style' 1024 4096 ¦ 1024=reorder cols 4096=gridlines [111] •wi 'columndisplay' c [112] [113] ¦ •wi 'font' 'APLFONT' 11 0 'default' [114] f 'FontName' I 'APLFONT' [115] ff,•FI 'FontSize' I '11' [116] ff,•FI 'FontStyle' I '0' [117] ff, 'FontCharset' I 'default' [118] •wi 'scale' 3 ¦ font size will be specified in points [119] •wi 'font' f [120] [121] •wi 'onColClick' ' CMDPKGDOC •wevent' [122] •wi 'onDblClick' ' CMDPKGDOC •wevent' [123] [124] •wself':' [125] •wi 'onResize' ' CMDPKGDOC •wevent' [126] •wi 'Event' ' CMDPKGDOC •wevent' 'Resize' [127] [128] •wself':lv' [129] •wi 'Focus' [130] [131] :for i :in ân [132] [133] ¦ (M C P)K[3 4 5] ¦ object names, classes, pointers [134] ¦ # [135] côi [136] ¦ Name [137] uM[i;] [138] ¦ Class [139] tiC [140] t'?ì?'[14t] [141] ¦ Value [142] v(iP)K [143] ¦ Bytes [144] bDLB,'CI15' •FMT •SIZE 'v' ¦õ v [145] ¦ Depth [146] dôðv [147] ¦ Shape [148] pûv ¦ shape [149] kûp ¦ rank [150] p(ôp),(k=0)/'' ¦ format shape [151] ¦ Value [152] fmax FFAW v [153] f(maxûf)ûf [154] qfâ'û' [155] :if qóûf [156] :andif q/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] ¦ /~f1 f2 ¦ Look in all but named functions [25] ¦ To limit search scope (using all three is equivalent to using none): [26] ¦ /¦ ¦ Find only in comments [27] ¦ /' ¦ Find only in character constants (or /") [28] ¦ /à ¦ Find only in APL (not comments/quotes) [29] ¦ To expand search scope: [30] ¦ /ì ¦ Find strings anywhere in a function -- not necessarily on the same line. [31] ¦ Only useful with multiple targets. Doesn't change behavior of /t1/ú/t2/. [32] ¦ Display from /t1/^/t2/ì is similar to /t1/ú/t2/ but only shows functions [33] ¦ that contain at least one hit on both strings. [34] ¦ Other: [35] ¦ / ¦ Suppress display; return fn names [36] [37] ¦ 21 Jul 2005 Created ìCMDSCAN from ìCMDFNREPL [38] ¦ 07 Oct 2005 Fixed FILT bug -- H>QC sb H^QC ! [39] ¦ 06 Feb 2006 Added multiple target feature [40] ¦ 04 Mar 2006 Added ì option [41] ¦ 08 Jul 2007 Updated ìQC [42] [43] Aô•ENLIST A ¦ arg might be numeric in development mode [44] [45] ADLTB A ¦ user command may pass in leading/trailing blanks [46] [47] :if Að'' [48] •'For help, see' [49] •' ]scan ?' [50] 0 [51] :end [52] [53] ¦ Allow simple word search without delimiters [54] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [55] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [56] A'/',A [57] :end [58] [59] ¦ Parse targets and functions [60] [61] G0û '' ¦ targets [62] S0û '' ¦ functions [63] [64] :repeat [65] D1A ¦ delimiter [66] A1A [67] IAâD ¦ find second delimiter (might not be one) [68] :if I=1 [69] •'Empty target string is not a good idea' [70] 0 [71] :end [72] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [73] ADLB IA [74] P1A ¦ function or option [75] :if ~Pî'<ó=ò>†ú^åê&þ' [76] :leave [77] :end [78] P('^ú',P)['&þ'âP] [79] ADLB 1A [80] :if '~'=1A [81] PP,'~' [82] ADLB 1A [83] :end [84] S( P),S ¦ function [85] :if Að'' [86] •'Multiple target syntax error' [87] 0 [88] :end [89] :end [90] [91] FA ¦ options (old left argument) [92] [93] D•FIRST ûG ¦ number of targets [94] [95] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [96] [97] ¦ Define ìFILT for APL/quoted strings/comments: [98] [99] Z'à''¦'îF [100] Z[2]Z[2]ú'"'îF [101] Z2æZ [102] E~Zî0 8 ¦ not all or none: we need to filter [103] [104] :if E ¦ unless all or none [105] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [106] LL, "¦ Quotes and Comments" [107] LL, "¦ Right arg is a •VR" [108] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [109] LL, "¦ Extracted from Zark's ìParseVR" [110] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [111] LL, "¦ 26 Oct 2004 Include ¦õ" [112] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [113] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [114] LL, "•IO0 ¦ origin 0 is convenient" [115] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [116] LL, "xcx\n" [157] LL, "¦ Flag newline after each comment; then convert pairs to maps" [158] LL, "tnúc" [159] LL, "ut/c" [160] LL, "c†\x\t\uúý10,u" [161] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [162] ¦ 0=None and 7=All cases are excluded before we get here [163] P 'rc' ¦ 1 = ¦ [164] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [165] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [166] PP, 'rqåc' ¦ 4 = à = 'å¦ [167] PP, 'r~q' ¦ 5 = ঠ= ~' [168] PP, 'r~c' ¦ 6 = à' = ~¦ [169] LL,P[Z] [170] K•FX[2]L ¦õ QC [171] :end [172] [173] L 'RFILT' [174] LL, '¦ Raw hit filter' [175] LL, '¦ V=•VR, P=partition flags' [176] LL, 'R~P ANDSCAN Vî''[1234567890]''' ¦ not line numbers [177] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [178] [179] K•FX[2]L ¦õ FILT ANDSCAN QC [180] [181] ¦ Define ìUP for case-insensitive filter (this is faster than ñUCASE!) [182] [183] Q'ñabcdefghijklmnopqrstuvwxyz' [184] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [185] Y•AV [186] Y[YâQ]L [187] K•FX[2]'VUP V' 'VY[•AVâV]' ¦õ UP Y [188] [189] GUPG ¦ targets to uppercase [190] A1G ¦ last target string [191] [192] ¦ Options setup [193] [194] R''îF ¦ suppress display, just return result? [195] X0û '' ¦ initialize result [196] [197] T'~'îF ¦ all but named fns? [198] [199] g'ì'îF ¦ global fn matching? [200] :if g^D=1 [201] •'FYI, the ì option has no effect with just one target string' [202] g0 [203] :end [204] [205] ¦ Strip flags from function list [206] [207] E'*'îF ¦ any function name wildcards? [208] F(~Fî'à''¦ï~?ì')/F ¦ note we do not remove asterisk [209] FWords F [210] [211] ¦ Default to all fns [212] [213] :if T^0=ûF [214] •'Tilde with no names means "not all functions"' [215] 0 [216] :end [217] [218] :if EúTú0=ûF [219] [220] ¦ You could have a global function that is localized but undefined [221] ¦ •IDLIST 1+2+8 will not pick up that name, so... [222] [223] N•SINL [224] N(~N[;1]î'õ•><')ëN ¦ no local names at these levels [225] N(,ú\N=' ')/,N ¦ discard FOO[3], keep names to the right [226] NWords N ¦ all localized names [227] NN~ ,'*' ¦ the asterisk next to suspended fn is not a name [228] N('•'†•FIRSTN)/N ¦ avoid picking up system vars (ñUCMD2 localizes •PW and •CT) [229] [230] M•IDLIST 1+2+8 ¦ all visible names [231] MWords M [232] MM,N ¦ add all localized names [233] M((MâM)=âûM)/M ¦ there might be dups [234] [235] N,•SI [236] N(ý1+Nâ'[')ûN ¦ name of self ¦ RHS 8/31/99 [237] MM~ N ¦ remove self [238] [239] P•IDLOC [2]M ¦ what are they [240] PP[;0æûP] ¦ global definition [241] M(P=1)/M ¦ functions only [242] [243] ¦ Now we have all global functions (though some could be shadowed) [244] [245] :if 0=ûF [246] FM [247] :elseif E ¦ which implies 0†ûF [248] :while '*'î•ENLIST F [249] P('*'îF)â1 [250] UPF [251] [252] VâûM ¦ indices of matches [253] C' ',M,' ' ¦ candidates [254] U('*'=1U)' ',U,('*'=ý1U)' ' [255] :for L :in '*' Words U [256] BC •SS L [257] Hú/B [258] C((H/B)â1)H/C [259] VH/V [260] :if Vð  :leave  :end [261] :end [262] CM[V] [263] [264] F((P-1)ûF),C,PF [265] :end [266] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [267] :end [268] :if T [269] FM~F [270] :end [271] :end [272] [273] ¦ Discard invalid names [274] [275] C•NC [2]F [276] :if 4îC [277] N(C=4)/F [278] •'*** Not searched, invalid name',(1=ûN)'s:',ôN [279] F(C†4)/F [280] :end [281] [282] ¦ Discard shadowed names [283] [284] L•IDLOC [2]F ¦ what are names [285] L0 ý1L ¦ disregard global level [286] CL^.=ý1 [287] :if 0îC [288] N(~C)/F [289] •'*** Shadowed:',ôN [290] FC/F [291] :end [292] [293] ¦ Discard non-functions [294] [295] C3=•NC [2]F [296] :if 0îC [297] N(~C)/F [298] •'*** Not function',(1=ûN)'s:',ôN [299] FC/F [300] :end [301] [302] ¦ Discard locked functions [303] [304] K•EX 'L' [305] K•FX [2] 'RL F' "R0†•FIRST û•CRL F,'[0]'" ¦õ L [306] CLF ¦ yuck, but I wanted to get this check out of the function loop [307] K•EX 'L' [308] :if 0îC [309] N(~C)/F [310] •'*** Locked function',(1=ûN)'s:',ôN [311] FC/F [312] :end [313] [314] NûF ¦ how many fns [315] :if N=0 [316] •'No functions to search!' [317] 0 [318] :end [319] [320] VDLTB •WSID [321] :if Vð'' [322] V'CLEAR WS' [323] :end [324] [325] •'Searching ',(ôN),' function',(N=1)'s in ',V,' ...' [326] [327] •WGIVE 0 ¦ let that message display [328] [329] E0 ¦ accumulate lines [330] U0 ¦ accumulate functions [331] [332] :for N :in F ¦ inspect next function [333] [334] V•VR N [335] LUP V [336] [337] ¦ Search •VR [338] [339] HL •SS A ¦ the heart of the matter [340] [341] :if D=1 ¦ single target? [342] :andif ~1îH ¦ no raw hits? [343] :continue ¦ next function [344] :end [345] [346] ¦ Filter for APL / quoted strings / comments [347] [348] P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [349] P[ý5+ûV]1 ¦ force end of last line [350] [351] IFILT ¦õ P V ANDSCAN [352] HH^I [353] [354] :if D=1 ¦ single target? [355] :andif ~1îH ¦ no more hits? [356] :continue ¦ next function [357] :end [358] [359] HP ORRED H ¦ shift hits to leading "[" [360] [361] :if D>1 ¦ multiple targets [362] ¦ We have already done the last target; now step through the others [363] ¦ Note that they are in reverse order so functions work like APL [364] :if g ¦ "ì" global option? [365] tú/H [366] :for J :in 1âD [367] WL •SS JG ¦ raw search [368] WW^I ¦ FILT [369] WP ORRED W ¦ shift hits to leading "[" [370] HWúH ¦ lines to show [371] tõ'(ú/W)',(JS),'t' ¦ apply function [372] :end [373] :if ~t ¦ no hits? [374] :continue ¦ next function [375] :end [376] :else [377] :for J :in 1âD [378] WL •SS JG ¦ raw search [379] WW^I ¦ FILT [380] WP ORRED W ¦ shift hits to leading "[" [381] Hõ'W',(JS),'H' ¦ apply function [382] :end [383] :if ~1îH ¦ no more hits? [384] :continue ¦ next function [385] :end [386] :end [387] ¦ Note that when D>1, H flags lines not hits [388] :end [389] [390] ¦ Got some hits [391] [392] EE++/H ¦ accumulate lines with hits [393] UU+1 ¦ accumulate functions with hits [394] XX, N ¦ add function name to result [395] [396] :if R ¦ if result-only mode [397] :continue ¦ next function [398] :end [399] [400] ¦ Display hits [401] [402] HH/âûH ¦ line numbers to display (origin 1) [403] PP/âûP ¦ partition starts [404] L(1P,1+ûV)-P ¦ partition lengths [405] PP[H]-1 ¦ compensate for +â with •IO1 [406] LL[H]-1 ¦ not incl trailing CR [407] WûH ¦ number of lines with hits [408] •'==> ',N,' (',(ôW),')' [409] :for B :in âW [410] ¦ APL+Win: Show fn name too so can double-click to edit at that line [411] •N,V[P[B]+âL[B]] ¦ faster than take/drop approach [412] :end [413] •WGIVE 0 ¦ allow display [414] [415] :end ¦ next function [416] [417] •'==> Total: ',(ôE),' line',(E=1)'s in ',(ôU),(-U=1)' functions' [418] [419] Rû0 ¦ quit if result-only mode [420] [421] K•EX 'X' [422] ì €ßÿt6R¼R¼ ì CMDSEEK A;AU;A1;A2;B;C;CF;D;E;F;FILT;G;H;HW;I;II;J;K;L;M;N;P;Q;QC;R;S;ST;SYN;T;U;UP;V;W;X;Z;a;b;c;d;e;f;g;h;i;j;k;m;n;p;q;r;s;t;u;v;w;x;y;z;•wself [1] ¦ Find strings in functions and variables, by default syntactic and case-sensitive [2] ¦ ( GUI version of ]FNREPL , without the replacement feature ) [3] ¦ Requires a Unicode APL font (default is APLNext 11) [4] [5] ¦ Syntax: [6] ¦ ]seek target ¦ Search (if target begins with a letter) [7] ¦ ]seek target/options ¦ Ditto, with options [8] ¦ Any non-alpha delimiter character may be used in place of the slashes shown below [9] ¦ ]seek /target ¦ Search (closing delimiter assumed) [10] ¦ ]seek /target/ ¦ Search (exactly 2 delimiters) [11] ¦ ]seek /target/options ¦ Ditto, with options [12] ¦ Multiple targets: [13] ¦ ]seek /t1/^/t2/options ¦ Find only lines with both matches [14] ¦ ]seek /t1/ú\t2\ ¦ Find lines with either match; delimiters may be different [15] ¦ ]seek /t1/&~/t2/ ¦ Logical not; & and þ are also permitted [16] ¦ ]seek /t1/>/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 character items in variables [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] ¦ ~f1 f2 ¦ Look in all but named fns/vars [33] ¦ To limit search scope (using all three is equivalent to using none): [34] ¦ ¦ ¦ Find only in comments [35] ¦ ' ¦ Find only in character constants (or /") [36] ¦ à ¦ Find only in APL (not comments/quotes) [37] ¦ To expand search scope: [38] ¦ @ ¦ Find strings anywhere in a fn/var -- not necessarily on the same line. [39] ¦ Only useful with multiple targets. Doesn't change behavior of /t1/ú/t2/. [40] ¦ Display from /t1/^/t2/@ is similar to /t1/ú/t2/ but only shows fns/vars [41] ¦ that contain at least one hit on both strings. [42] ¦ To expand display: [43] ¦ + ¦ Show lines immediately before and after hits, for better context [44] [45] ¦ To do: [46] ¦ Add an input edit box to show (and revise?) target [47] ¦ /t1/ú/t2/ Use a different color for each term? What if they overlap? [48] ¦ Resize of Form could cause Listview vertical scrollbar to come and go [49] ¦ Make default be shallow variable search like ]WSLOC ; use  option for deep search? [50] ¦ Double-click in RichEdit is not reliable [51] [52] ¦ 15 Dec 1987 Rex Swain, Independent Consultant, www.rexswain.com [53] ¦ 19 May 1988 Detect and display changed function names [54] ¦ 16 May 1991 Erase old version when fn name changed [55] ¦ 27 Aug 1993 Added ï (ignore case) option [56] ¦ 26 Nov 1994 Adapted for Dyalog APL/W, added # and ## and  options [57] ¦ 29 Dec 1998 Adapted for APL+Win 3.0, removed # and ## and  options [58] ¦ 10 Nov 1999 Added colon as leading identifier char for APL+Win [59] ¦ 18 Nov 1999 Added case-insensitive treatment for APL+Win key names [60] ¦ 03 Dec 2001 Removed colon -- it can OPTIONALLY begin an identifier [61] ¦ 04 Apr 2003 Report total number of hits [62] ¦ 18 May 2003 Added ~ feature [63] ¦ 14 May 2004 Added ? feature [64] ¦ 29 Aug 2004 Added * feature [65] ¦ 26 Mar 2005 Evlevel-neutral (sigh) [66] ¦ 11 Jul 2005 Use QC (derived from Zark's ParseVR) to handle ' and " quotes [67] ¦ 21 Jul 2005 Created ìCMDFNREPL from ìfnrepl [68] ¦ 07 Oct 2005 Fixed FILT bug -- H>QC should be H^QC ! [69] ¦ 06 Feb 2006 Added multiple target feature [70] ¦ 04 Mar 2006 Added @ option [71] ¦ 15 Feb 2007 GUI version, based on ]FNREPL but without replace feature [72] ¦ 16 Feb 2007 Include simple character arrays in search, like ]WSLOC does [73] ¦ 17 Feb 2007 Added + feature [74] ¦ 18 Feb 2007 Deep search on all variables [75] ¦ 19 Feb 2007 Added ì and  features [76] ¦ 12 May 2007 Added Ctrl+C from RichEdit [77] ¦ 29 May 2007 Fixed bug which caused hits in function header lines to not match [78] ¦ 08 Jul 2007 Updated ìQC [79] [80] (Aðý1)ûL9 ¦ callbacks [81] [82] v•AI[2] ¦ elapsed time [83] [84] Aô•ENLIST A ¦ arg might be numeric in development mode [85] [86] ADLTB A ¦ user command may pass in leading/trailing blanks [87] [88] :if Að'' [89] •'For help, see' [90] •' ]seek ?' [91] 0 [92] :end [93] [94] XA ¦ save original arg [95] [96] ¦ Allow simple word search without delimiters [97] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [98] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [99] ¦ If the argument is 'foo /xx' then the blank should not be significant since [100] ¦ there was no leading delimiter. Is this a good idea? Technically the [101] ¦ blank should be significant. But this way is user-friendly. [102] :if 1=+/A='/' [103] Iý1+Aâ'/' [104] A(DTB IA),IA [105] :end [106] A'/',A [107] :end [108] [109] ¦ Parse targets and functions [110] [111] G0û '' ¦ targets [112] S0û '' ¦ functions [113] [114] :repeat [115] D1A ¦ delimiter [116] A1A [117] IAâD ¦ find second delimiter (might not be one) [118] :if I=1 [119] •'Empty target string is not a good idea' [120] 0 [121] :end [122] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [123] ADLB IA [124] P1A ¦ function or option [125] :if ~Pî'<ó=ò>†ú^åê&þ' [126] :leave [127] :end [128] P('^ú',P)['&þ'âP] [129] ADLB 1A [130] :if '~'=1A [131] PP,'~' [132] ADLB 1A [133] :end [134] S( P),S ¦ function [135] :if Að'' [136] •'Multiple target syntax error' [137] 0 [138] :end [139] :end [140] [141] FA ¦ options (old left argument) [142] [143] D•FIRST ûG ¦ number of targets [144] [145] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [146] [147] ¦ Define ìFILT for APL/quoted strings/comments: [148] [149] Z'à''¦'îF [150] Z[2]Z[2]ú'"'îF [151] Z2æZ [152] E~Zî0 8 ¦ not all or none: we need to filter [153] [154] :if E ¦ unless all or none [155] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [156] LL, "¦ Quotes and Comments" [157] LL, "¦ Right arg is a •VR" [158] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [159] LL, "¦ Extracted from Zark's ìParseVR" [160] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [161] LL, "¦ 26 Oct 2004 Include ¦õ" [162] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [163] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [164] LL, "•IO0 ¦ origin 0 is convenient" [165] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [166] LL, "xcx\n" [207] LL, "¦ Flag newline after each comment; then convert pairs to maps" [208] LL, "tnúc" [209] LL, "ut/c" [210] LL, "c†\x\t\uúý10,u" [211] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [212] ¦ 0=None and 7=All cases are excluded before we get here [213] P 'rc' ¦ 1 = ¦ [214] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [215] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [216] PP, 'rqåc' ¦ 4 = à = 'å¦ [217] PP, 'r~q' ¦ 5 = ঠ= ~' [218] PP, 'r~c' ¦ 6 = à' = ~¦ [219] LL,P[Z] [220] K•FX[2]L ¦õ QC [221] :end [222] [223] L 'RFILT' [224] LL, '¦ Raw hit filter' [225] LL, '¦ V=•VR, P=partition flags' [226] ¦LL, 'R~P ANDSCAN Vî"[1234567890]"' ¦ not line numbers [227] LL, 'RP ANDSCAN V†"]"' ¦ line numbers; allow for (2)[23;] too [228] ¦LL, 'RRåý1è1 0R' ¦ flag the ] too (we assume there is one!) [229] LL, 'RRåR<ý1èR' ¦ < is way faster than  [230] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [231] [232] K•FX[2]L ¦õ FILT ANDSCAN QC [233] [234] ¦ Define ìSYN for syntactic search [235] [236] Z''îF ¦ non-syntactic search? [237] [238] ¦ Token alphabet: chars that can be anywhere in a token [239] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [240] a'_' [241] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [242] aa,'abcdefghijklmnopqrstuvwxyzñ' [243] aa,'0123456789' [244] ¦ Token alphabet, including chars that can only begin a token [245] qa,'•ý' [246] [247] Q 'HA SYN H;B;I' [248] QQ, '¦ Syntactic hit filter' [249] QQ, '¦ Requires: V=•VR, a,q=alphabet' [250] QQ, 'IH/âûH' [251] ¦  Note that if target starts with • then we don't care what's to the [252] ¦ left of it, so ((1A)îa) is correct. [253] QQ, ':if (1A)îa' [254] QQ, ' H[(('' '',V)[I]îq)/I]0' [255] QQ, ':end' [256] QQ, ':if (ý1A)îq' [257] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [258] QQ, ':end' [259] :if Z=1 ¦ Neither? [260] Q1ûQ ¦ noop [261] :end [262] K•FX[2]Q ¦õ SYN a q [263] [264] ¦ Define ìUP for case-insensitive filter [265] [266] Z'ï'îF ¦ ignore case when finding target? [267] [268] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [269] ¦ Noop if no letters in targets [270] K•FX[2]'VUP V' '¦ noop' [271] :elseif Z [272] Q'ñabcdefghijklmnopqrstuvwxyz' [273] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [274] u•AV [275] u[uâQ]L [276] K•FX[2]'VUP V' 'Vu[•AVâV]' ¦õ UP u ¦ this is faster than ñUCASE! [277] :else [278] m'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [279] u'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [280] Q 'VUP V;B;I;L;S' [281] QQ, '¦ Force APL+Win keyword names to upper case' [282] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [283] QQ, '¦ RHS 11/18/99' [284] QQ, '' [285] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [286] QQ, 'BVî''•'' ¦ find key symbols' [287] QQ, '(1îB)0 ¦ quit if none' [288] QQ, '' [289] QQ, 'LVîm ¦ flag all letters (any case)' [290] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [291] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [292] QQ, '(1îB)0 ¦ quit if none' [293] QQ, '' [294] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [295] QQ, 'IS/B ¦ flag those which are candidates' [296] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [297] QQ, 'I†\I ¦ name mask' [298] QQ, 'II/âûI ¦ indices' [299] QQ, '' [300] QQ, 'V[I]u[mâV[I]] ¦ translate' [301] K•FX[2]Q [302] ¦ RHS 3/19/01 [303] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [304] ¦ when searching for 'fMain'. [305] ¦ List of keywords? No, could have ':end' •wi 'New' ... [306] ¦ I think we need to upper-case just the à part of the •vr [307] ¦ RHS 2/06/06 [308] ¦ I often search for •fappend or •io. [309] ¦ I cannot recall EVER having searched for :repeat. [310] ¦ So let's not worry about control structure keywords. [311] :end [312] [313] GUPG ¦ targets to uppercase [314] A1G ¦ last (and typically only) target string [315] [316] ¦ Options setup [317] [318] T'~'îF ¦ all but named fns? [319] b'+'îF ¦ expanded context? [320] f'ì'îF ¦ just fns/vars? [321] ffúå/f ¦ neither means both [322] [323] g'@'îF ¦ global fn matching? [324] :if g^D=1 [325] •'FYI, the @ option has no effect with just one target string' [326] g0 [327] :end [328] [329] ¦ Strip flags from function list [330] [331] E'*'îF ¦ any function name wildcards? [332] F(~Fî'à''¦ï~?@+ì')/F ¦ note we do not remove asterisk [333] FWords F [334] [335] ¦ Default to all fns [336] [337] :if T^0=ûF [338] •'Tilde with no names means "not all fns/vars"' [339] 0 [340] :end [341] [342] :if EúTú0=ûF [343] [344] ¦ You could have a global function that is localized but undefined [345] ¦ •IDLIST 1+2+8 will not pick up that name, so... [346] [347] N•SINL [348] N(~N[;1]î'õ•><')ëN ¦ no local names at these levels [349] N(,ú\N=' ')/,N ¦ discard FOO[3], keep names to the right [350] NWords N ¦ all localized names [351] NN~ ,'*' ¦ the asterisk next to suspended fn is not a name [352] N('•'†•FIRSTN)/N ¦ avoid picking up system vars (ñUCMD2 localizes •PW and •CT) [353] [354] M•IDLIST 1+2+8 ¦ all visible names [355] MWords M [356] MM,N ¦ add all localized names [357] ¦MM,'•ALX' '•ELX' '•LX' ¦ ]WSLOC searches these ¦ oh forget it, ]ucmd shadows •ALX and •ELX [358] M((MâM)=âûM)/M ¦ there might be dups [359] MM[•AV[2]M] ¦ re-sort [360] [361] N,•SI [362] N(ý1+Nâ'[')ûN ¦ name of self ¦ RHS 8/31/99 [363] MM~ N ¦ remove self [364] [365] P•IDLOC [2]M ¦ what are they [366] PP[;0æûP] ¦ global definition [367] M(Pîf/1 2)/M ¦ fns and vars, depending on ì options [368] [369] ¦ Now we have all global fns/vars (though some could be shadowed) [370] [371] :if 0=ûF [372] FM [373] :elseif E ¦ which implies 0†ûF [374] :while '*'î•ENLIST F [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] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [393] :end [394] :if T [395] FM~F [396] :end [397] :end [398] [399] ¦ If we are filtering for APL/quotes/comments, ditch all variables [400] ¦ FIXME is this a good idea? what if •vr's stored in vars? [401] [402] ¦ :if 3=•NC 'QC' [403] ¦ F(2†•NC [2]F)/F [404] ¦ •'ditching vars' [405] ¦ :end [406] [407] E'' ¦ accumulate warning messages [408] [409] ¦ Discard invalid names [410] [411] C•NC [2]F ¦ 0=undef 1=label 2=var 3=fn 4=other/invalid [412] ¦ ¦ Aw jeez. •NC says system names are invalid. •IDLOC classifies them correctly, [413] ¦ ¦ but gives DOMAIN ERROR on truly invalid names. Sigh. Kludge ahead... [414] ¦ C[(Fî'•ALX' '•ELX' '•LX')/âûF]2 [415] :if 4îC [416] N(C=4)/F [417] ¦•'*** Not searched, invalid name',(1=ûN)'s:',ôN [418] EE,•TCNL,'Not searched, invalid name',(1=ûN)'s:',ôN [419] F(C†4)/F [420] :end [421] [422] ¦ Discard shadowed names [423] [424] L•IDLOC [2]F ¦ what are names fn=1 var=2 [425] L0 ý1L ¦ disregard global level [426] CL^.=ý1 [427] :if 0îC [428] N(~C)/F [429] ¦•'*** Shadowed:',ôN [430] EE,•TCNL,'Shadowed:',ôN [431] FC/F [432] :end [433] [434] ¦ Discard non-functions [435] [436] ¦C3=•NC [2]F [437] ¦C(•NC [2]F)î2 3 4 ¦ VARS! ¦ 4 allows •LX; we already checked for invalid [438] C(•NC [2]F)î2 3 ¦ VARS! [439] :if 0îC [440] N(~C)/F [441] ¦•'*** Not function',(1=ûN)'s:',ôN [442] ¦EE,•TCNL,'Not function',(1=ûN)'s:',ôN [443] EE,•TCNL,'Not functions or variables:',ôN ¦ VARS! [444] FC/F [445] :end [446] [447] ¦ Discard locked functions [448] [449] K•EX 'L' [450] ¦K•FX [2] 'RL F' "R0†•FIRST û•CRL F,'[0]'" ¦õ L [451] K•FX [2] 'RL F' ":if 3=•NC F  R0†•FIRST û•CRL F,'[0]'  :else  R1  :end" ¦õ L ¦ VARS! [452] CLF ¦ yuck, but I wanted to get this check out of the function loop [453] K•EX 'L' [454] :if 0îC [455] N(~C)/F [456] ¦•'*** Locked function',(1=ûN)'s:',ôN [457] EE,•TCNL,'Locked function',(1=ûN)'s:',ôN [458] FC/F [459] :end [460] [461] N•first ûF ¦ how many fns [462] :if N=0 [463] ¦•'No functions to search!' [464] ¦EE,•TCNL,'No functions to search!' [465] EE,•TCNL,'Nothing to search!' ¦ VARS! [466] ¦0 [467] :end [468] [469] VDLTB •WSID [470] :if Vð'' [471] V'CLEAR WS' [472] :end [473] [474] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [475] k•fx [2] 'vk II d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ II [476] [477] w•FI 'Seek-Place' II '2 5 25 75' [478] z•FI 'Seek-Visible' II '1' [479] zz-z=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [480] [481] •wself'fmSeek' •wi 'Create' 'Form' 'Hide' [482] •wi 'caption' 'Seek' [483] •wi 'place' w [484] •wi 'visible' z [485] e'CMDSEEK ý1' [486] •wi 'onClose' e [487] •wi 'limitwhere' 10 40 [488] [489] •wself':mFile' •wi 'Create' 'Menu' [490] •wi 'caption' '&File' [491] [492] •wself'.mExit' •wi 'Create' 'Menu' [493] •wi 'caption' 'E&xit' [494] •wi 'shortcut' 'X' 2 [495] •wi 'onClick' "0 0û':' •wi 'Close'" [496] [497] •wself':mEdit' •wi 'Create' 'Menu' [498] •wi 'caption' '&Edit' [499] [500] •wself'.mCopy' •wi 'Create' 'Menu' [501] ¦•wi 'caption' '&Copy list of names to clipboard' [502] •wi 'caption' '&Copy' [503] •wi 'shortcut' 'C' 2 [504] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'Copy'" [505] [506] •wself'..mNext' •wi 'Create' 'Menu' [507] •wi 'caption' 'Find &next hit' [508] •wi 'shortcut' 114 0 ¦ 114=F3 [509] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'redFind' 1" [510] [511] •wself'..mPrev' •wi 'Create' 'Menu' [512] •wi 'caption' 'Find &previous hit' [513] •wi 'shortcut' 114 1 [514] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'redFind' ý1" [515] [516] •wself':mView' •wi 'Create' 'Menu' [517] •wi 'caption' '&Sort' [518] [519] •wself'.mClass' •wi 'Create' 'Menu' [520] •wi 'caption' 'Sort list by Clas&s' [521] •wi 'shortcut' 'S' 2 [522] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'Sort' 1" [523] [524] •wself'..mName' •wi 'Create' 'Menu' [525] •wi 'caption' 'Sort list by &Name' [526] •wi 'shortcut' 'N' 2 [527] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'Sort' 2" [528] [529] •wself'..mHits' •wi 'Create' 'Menu' [530] •wi 'caption' 'Sort list by &Hits' [531] •wi 'shortcut' 'H' 2 [532] •wi 'onClick' "•wi 'Event' 'CMDSEEK ý1' 'Sort' 3" [533] [534] C•NC [2]F [535] [536] •wself':st' •wi 'Create' 'Status' [537] •wi 'status' (1 4û1 '' 0 8) [538] [539] ¦ 4-col matrix [540] ¦ col 1: pane number, negative if an overlay pane [541] ¦ cols 2,3: 1 text show that text [542] ¦ 0 text don't show, but use width of text [543] ¦ text 33 show text; 33 is mimimum width (more if reqd) [544] ¦ text text2 ditto; use width of text2 as minimum [545] ¦ col 4: border: 0=no 1=inset 2=outset 8=expand 16=caps 32=num 64=scr [546] t0 4û [547] ttž 1 1 (' ',V,' ') 1 ¦ wsid [548] ¦ttž 2 1 (' ',(ôN),' functions ') 1 [549] ttž 2 1 (' ',(ô+/C=3),' functions, ',(ô+/C=2),' variables ') 1 [550] ttž 3 '' 25 1 [551] ttž 4 '' 25 1 [552] •wi 'status' t [553] [554] z,•wi 'PaneWhere' 3 [555] [556] •wself'.pb' •wi 'Create' 'Progress' ¦ note child of Status [557] •wi 'style' 1 ¦ 1=smooth [558] •wi 'value' 0 (1N) 1 0 ¦ 1 to avoid •WI DOMAIN ERROR when N=0 [559] •wi 'where' z [560] [561] •wself':bn' •wi 'Create' 'Button' 'Hide' [562] •wi 'style' 2 ¦ 2=cancel [563] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [564] [565] z':' •wi 'size' [566] [567] •wself':lv' •wi 'Create' 'Listview' [568] •wi 'style' 1 2 4 8 128 4096 ¦ 128=no header 4096=grid [569] •wi 'where' (0,0,z[1],200) ¦ wide enough so no horiz scroll bar, else 'size' misleading [570] [571] ¦•wi 'font' 'APL Santa Fe' 0.8 ¦ no, then ñ doesn't display correctly [572] [573] •wi 'scale' 3 ¦ font size will be specified in points [574] [575] ¦•wi 'font' 'APLFONT' 11 0 'default' ¦ 11 13 [576] [577] ¦ Get value of key k; if undefined, write default to the ini file [578] k•fx [2]( [2] •cr 'II'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ II [579] [580] t 'FontName' II 'APLFONT' [581] tt,•FI 'FontSize' II '11' [582] tt,•FI 'FontStyle' II '0' [583] tt, 'FontCharset' II 'default' [584] •wi 'font' t [585] [586] •wi 'scale' 1 [587] [588] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [589] ¦ first col must be left justified [590] c0 3û0 [591] ccž'C' 2 'left' [592] ccž'Name' (5/•enlist ûF) 'left' ¦ 5 to avoid •WI DOMAIN ERROR when N=0 [593] ccž'Hits' 5 'right' [594] ccž'Fake' 0 'right' ¦ because of behavior of 'AutoFit' 'header' 'all' [595] [596] •wi 'list' (0,1,100 1û'x') ¦ force vertical scrollbar [597] [598] •wi 'columndisplay' c [599] w+/c[;2] [600] d•wi 'size' [601] d[2]w ¦ + 5 ¦ allow for vert scrollbar [602] •wi 'size' d [603] w4•wi 'where' [604] [605] •wi 'list' (0 3û0 1 '') ¦ remove fake rows that forced vertical scrollbar [606] [607] •wself':red' •wi 'Create' 'RichEdit' [608] •wi 'style' 4 16 64 4096 16384 32768 ¦ 4=multi-line 16=V SB 64=H SB 2048=APL 4096=read-only [609] ¦ 16384 else entire text selected when you select the Form [610] ¦ 32768 disable automatic word selection when highlighting with mouse [611] [612] •wi 'where' (0,w,z[1],z[2]-w) [613] [614] HW•wi 'hwnd' [615] [616] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [617] •wi 'selection' 0 ý1 ¦ select all [618] •wi 'scale' 3 ¦ points [619] [620] ¦•wi 'selfont' 'APL Santa Fe' 10 0 'default' ¦ all black [621] ¦•wi 'selfont' 'APL Santa Fe' 11 0 'default' ¦ shaded but readable [622] ¦•wi 'selfont' 'APL Santa Fe' 12 0 'default' ¦ shaded but readable [623] ¦•wi 'selfont' 'APL385 Unicode' 11 0 'default' ¦ Dyalog style; kinda ugly [624] ¦•wi 'selfont' 'APLNext' 11 0 'default' ¦ a little crisper [625] [626] t 'UFontName' II 'APLNext' [627] tt,•FI 'UFontSize' II '11' [628] tt,•FI 'UFontStyle' II '0' [629] tt, 'UFontCharset' II 'default' [630] •wi 'selfont' t [631] [632] ¦  Necessary because default is bold (huh?) [633] •wi 'selstyle' (0 0 0 0 0) ¦ bold, italic, underline, strikeout, protected [634] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection [635] [636] 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 [637] 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 [638] ¦ 183=U00B7 : Middle dot, for untranslatable chars [639] [640] ¦ Streamlined version of ìAV2U [641] t 'UAU A;N' [642] tt, 'UA2[A1âA]' [643] tt, ':if 82†•DR A' [644] tt, ' N,0=•TYPE A' [645] tt, ' (N/,U)N/,A' [646] tt, ':end' [647] tt, 'U•FIRST 323 163 82 •DR U' [648] k•fx [2] t ¦õ AU A1 A2 [649] [650] ¦ Streamlined version of ìSetSelTextU [651] k•fx [2] 'ST A;K;U' 'UAU A' "K•wcall 'EM_SetTextEx' HW ('ST_SELECTION' 1200) (U,2û•tcnul)" ¦õ ST AU HW [652] [653] t' ]SEEK ',X [654] [655] ¦ tt,•tcnl,50û9472 ¦ U2500 : Unicode horizontal line [656] ¦ tt,•tcnl,'Test difficult characters:' [657] ¦ tt,•tcnl,'Execute õ' [658] ¦ tt,•tcnl,' Match ð' [659] ¦ tt,•tcnl,' Zilde ' [660] ¦ tt,•tcnl,' Domino ˜' [661] [662] tt,•tcnl [663] ST t [664] [665] •wi 'selection' (0,ý1+ût) ¦ offset, length [666] •wi 'selcolor' (0 196 0) [667] •wi 'selstyle' (1 0 0 0 0) ¦ bold [668] •wi 'selection' ý1 ¦ select none; cursor to end [669] [670] :if ’ûE ¦ any warnings? [671] s1•wi 'selection' [672] ST 1èE [673] •wi 'selection' (s,ý1+ûE) ¦ offset, length [674] •wi 'selcolor' (255 0 0) [675] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [676] •wi 'selection' ý1 ¦ select none; cursor to end [677] :end [678] [679] ¦ Pre-build a CHARFORMAT2 structure that sets background color [680] CF8484 ¦ cbSize [681] CF[8]4 ¦ dwMask CFM_BACKCOLOR [682] CF[65 66 67]255 255 0 ¦ yellow [683] CFAV CF [684] [685] VDLTB •WSID [686] :if Vð'' [687] V'CLEAR WS' [688] :end [689] [690] •wself':' [691] [692] •wi 'Show' [693] e'CMDSEEK ý1' [694] •wi 'onResize' e [695] •wi 'onClose' e [696] [697] ':lv' •wi 'Focus' ¦ necessary to make Esc work during search (why?) [698] [699] X0 ¦ count hits [700] E0 ¦ count lines with hits [701] U0 ¦ count functions with hits [702] p0 5û' ' '' 0 0  ¦ class, name, # hits, pointer to fn in RichEdit, line numbers with hits [703] m0 2û ¦ all hits (start, length) in RichEdit [704] [705] •wself':red' [706] [707] :for N :in F ¦ inspect next function [708] [709] ¦k•dl 0.1 [710] [711] :if ':' •wi '‘stop' [712] s1•wi 'selection' [713] t'Interrupt',•tcnl [714] ST t [715] •wi 'selection' (s,ût) ¦ offset, length [716] •wi 'selcolor' (255 0 0) [717] •wi 'selstyle' (1 0 0 0 0) ¦ bold [718] •wi 'selection' ý1 ¦ select none; cursor to end [719] :leave [720] :end [721] [722] ':st.pb' •wi 'Stepit' [723] [724] ¦•wgive 0 ¦ yikes, this makes it take twice as long! [725] [726] ¦t100’iöN [727] ¦':st' •wi 'SetStatus' ('Searching function ',(ôi),' of ',(ôN),' (',(ôt),'%)','...') [728] ¦':st' •wi 'SetStatus' 3 (' Searching function ',(ôi),'... ') [729] ¦':st' •wi 'SetStatus' 3 (' Searching ',(ô100’iöN),'%... ') [730] [731] ¦  This was nice in the event that a huge variable took forever to search. [732] ¦ But it makes the other status panes shiver [733] ¦':st' •wi 'SetStatus' 4 (' ',N) [734] [735] y3=•NC N ¦ is it a function? ¦ note •NC says 4 for •LX, but we ony test 3= [736] :if y [737] V•VR N [738] V[1 2]'[]' ¦ kludge for FILT [739] :else [740] VõN [741] [742] ¦ RHS 3/03/07 Let's try this, for speed [743] :if 82†•DR V [744] :continue [745] :end [746] [747] ¦ :if 82†•DR V [748] ¦ :orif 2<ûûV [749] ¦ :continue [750] ¦ :else [751] ¦ :if 2=ûûV [752] ¦ t1ûV [753] ¦ w4+2ûôt ¦ we want a blank between ']' and data, so FILT will work [754] ¦ V(('P—[—Q—;]—LI',ôw) •FMT ât),V [755] ¦ ¦ Keep trailing blanks, since they are arguably part of the data [756] ¦ V,V,•TCNL [757] ¦ :elseif •TCNLîV [758] ¦ ¦ Don't use ìPartition because we want to keep empty partitions [759] ¦ V1(V=•TCNL) •PENCLOSE V [760] ¦ tûV [761] ¦ w3+3ûôt ¦ we want a blank between ']' and data, so FILT will work [762] ¦ V( [2] ('P—[—Q—]—LI',ôw) •FMT ât),V [763] ¦ V•ENLIST V,•TCNL [764] ¦ :else ¦ simple vector, no CRs [765] ¦ V(6'[]'),V,•TCNL [766] ¦ :end [767] ¦ :end [768] ¦L•ai[2] [769] VSEEKFMT V [770] ¦L•ai[2]-L [771] ¦:if Lò1 [772] ¦ •'FYI, it took ',(ôL),' seconds for ]SEEK to search: ',N [773] ¦ ¦ FIXME so what? erase it? actually time was used formatting it. [774] ¦:end [775] :if 0=ûV [776] :continue [777] :end [778] ¦VV,6û' ' ¦ make it like a •VR; see ý5+ûV kludge below [779] ¦  not necessary now that we match •TCNL rather than •TCNL,'[' [780] :end [781] [782] LUP V [783] [784] ¦ Search •VR [785] [786] HL •SS A ¦ the heart of the matter [787] [788] :if D=1 ¦ single target? [789] :andif ~1îH ¦ no raw hits? [790] :continue ¦ next function [791] :end [792] [793] ¦ Syntactic filter [794] [795] HA SYN H ¦õ V a q [796] [797] :if D=1 ¦ single target? [798] :andif ~1îH ¦ no more hits? [799] :continue ¦ next function [800] :end [801] [802] ¦ Filter for APL / quoted strings / comments [803] [804] ¦P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [805] ¦  This doesn't work with my variable formatting stuff, like '(2)[13;] ...' [806] ¦ And besides, you're not allowed to have CRs embedded in functions any more [807] P1,ý1V •SS •TCNL ¦ partition on "[" (with trailing CRs); force header line [808] ¦ •SS is still faster than plain = ! [809] ¦P[ý5+ûV]1 ¦ force end of last line [810] ¦ The last 7 characters of a •VR are: •TCNL,' ì',•TCNL [811] ¦ P[ý5+ûV]1 above flags ....................  this blank [812] ¦ No, now that's not necessary at all, now that we match •TCNL rather than •TCNL,'[' [813] [814] IFILT ¦õ P V ANDSCAN [815] HH^I [816] [817] :if D=1 ¦ single target? [818] :andif ~1îH ¦ no more hits? [819] :continue ¦ next function [820] :end [821] [822] R(ûV)û0 [823] R[(H/âûH)ø.+ý1+âûA]1 ¦ flag chars to highlight [824] [825] hP ORRED H ¦ shift hits to leading "[" [826] [827] :if D>1 ¦ multiple targets [828] [829] ¦ We have already done the last target; now step through the others [830] ¦ Note that they are in reverse order so functions work like APL [831] [832] ¦ /t1/ú/t2/ don't stop and display after first hit -- we want to show them all [833] ¦ /t1/&~/t2/ it is okay to show "all" hits since we will exclude lines with t2 [834] [835] :if g ¦ "@" global option? [836] tú/h [837] :for J :in 1âD [838] WL •SS JG ¦ raw search [839] W(JG) SYN W ¦ SYN [840] WW^I ¦ FILT [841] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [842] HHúW ¦ all hits [843] WP ORRED W ¦ shift hits to leading "[" [844] hWúh ¦ lines to show [845] tõ'(ú/W)',(JS),'t' ¦ apply function [846] :end [847] :if ~t ¦ no hits? [848] :continue ¦ next function [849] :end [850] :else [851] :for J :in 1âD [852] WL •SS JG ¦ raw search [853] W(JG) SYN W ¦ SYN [854] WW^I ¦ FILT [855] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [856] HHúW ¦ all hits [857] WP ORRED W ¦ shift hits to leading "[" [858] hõ'W',(JS),'h' ¦ apply function [859] :end [860] :if ~1îh ¦ no more hits? [861] :continue ¦ next function [862] :end [863] :end [864] [865] ¦ Only count hits on lines that will be displayed [866] ¦ (When searching for /1/^/2/ don't count 2s on lines without 1) [867] [868] Hh/P PLUSRED H [869] [870] :end [871] [872] ¦ Got some hits [873] [874] x+/H ¦ total hits in this fn [875] t':lv' •wi 'AddRows' 0 1 (,'ì'[1+y]) N (ôx) [876] k':lv' •wi 'EnsureVisible' t [877] [878] XX+x ¦ accumulate total hits [879] Hh ¦ lines with hits [880] EE++/H ¦ accumulate lines with hits [881] UU+1 ¦ accumulate functions with hits [882] [883] ¦ Display hits [884] [885] HH/âûH ¦ line numbers to display (origin 1) [886] WûH ¦ number of lines with hits [887] PP/âûP ¦ partition starts [888] L(1P,1+ûV)-P ¦ partition lengths [889] :if b ¦ expanded context? [890] :if y [891] eâûP ¦ all line numbers (including the trailing ì line) [892] :else [893] eâý1+ûP ¦ all line numbers (the last line of variables is bogus) [894] :end [895] H(eîHø.+ý1 0 1)/e ¦ this takes care of dups and edges [896] IH>1+ý1èH ¦ flag beginnings of groups of lines [897] :else [898] I(ûH)û0 [899] :end [900] PP[H]-1 ¦ compensate for +â with •IO1 [901] LL[H] ¦ lengths, incl trailing CRs [902] [903] ppž ('ì'[1+y]) N x (1•wi 'selection') H [904] [905] e5û9472 ¦ 9472=U2500 : Horizontal line [906] ¦  5 positions the fn name where it is in the header line (of a niladic fn) [907] te,' ',N,' (',(ôx),' hit',(x=1)'s',((x†W)/' on ',(ôW),(-W=1)' lines'),') ' [908] tt,((70-ût)ûe),•tcnl [909] ST t [910] n•first ût ¦ length of line [911] s1•wi 'selection' [912] ss-n ¦ back up to beginning of line [913] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [914] •wi 'selection' s (n-1) ¦ offset, length [915] :if y [916] V[1 2]' ' ¦ undo kludge for FILT [917] •wi 'selcolor' (0 0 255) ¦ blue fns [918] :else [919] •wi 'selcolor' (255 0 255) ¦ purple vars [920] :end [921] •wi 'selection' (6+s) (•first ûN) ¦ just the function name [922] •wi 'selstyle' (1 0 0 0 0) ¦ bold [923] •wi 'selection' ý1 ¦ select none; cursor to end [924] •wi 'Paint' ¦ show bolded fn name while hits display [925] [926] :for B :in âûH [927] :if I[B] [928] ST (3û183),•TCNL ¦ 183=U00B7 : Middle dot [929] :end [930] nL[B] [931] jP[B]+ân ¦ indices of line in •VR [932] ST V[j] [933] s(1•wi 'selection')-n+1 [934] C(R[j]) Partition ân ¦ groups of chars to highlight [935] :for j :in C [936] e(s+1j),ûj ¦ offset, length [937] mmže ¦ all hits [938] •wi 'selection' e ¦ offset, length [939] ¦•wi 'selcolor' (255 0 255) ¦ purple [940] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [941] k•wcall 'EM_SETCHARFORMAT' HW 1 CF ¦ SCF_SELECTION=1 ¦ yellow background [942] :end [943] •wi 'selection' ý1 ¦ select none; cursor to end [944] :end [945] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection ¦ else :red does not scroll down [946] •WGIVE 0 ¦ listview does not display without this [947] ¦k•dl 0.1 [948] [949] :end ¦ next function [950] [951] ':bn' •wi 'onClick' '' ¦ let style 2 take over [952] [953] ¦ •wi 'selection' 0 ý1 ¦ select all [954] ¦ •wcall 'EM_SETPARAFORMAT' HW PARAFORMAT2 [955] ¦ •wi 'selection' ý1 ¦ select none; cursor to end [956] [957] :if U=0 [958] [959] s1•wi 'selection' [960] [961] t'Not found',•tcnl [962] ST t [963] [964] •wi 'selection' (s,ý1+ût) ¦ offset, length [965] •wi 'selcolor' (255 0 0) [966] •wi 'selstyle' (1 0 0 0 0) ¦ bold [967] •wi 'selection' 0 0 ¦ cursor to top [968] [969] L1 [970] [971] :end [972] [973] ppž ' ' '' 0 (1•wi 'selection')  ¦ fake row so we know position of end of text [974] [975] •wi 'selection' 0 0 ¦ cursor to top [976] [977] •wself':lv' [978] [979] •wi 'noredraw' 1 [980] •wi 'AutoFit' 'all' [981] c•wi 'columndisplay' [982] cý1 0c ¦ delete Fake column [983] •wi 'columndisplay' c [984] [985] •wi 'highlightfocus' 1 [986] •wi 'value' 1 [987] k•wi 'EnsureVisible' 1 [988] [989] •wi 'noredraw' 0 [990] [991] d+/c[;2] [992] z•wi 'size' [993] z[2]d [994] •wi 'size' z [995] w•wi 'where' [996] [997] z':' •wi 'size' [998] d':red' •wi 'where' [999] d[2]w[4] [1000] d[4]z[2]-w[4] [1001] ':red' •wi 'where' d [1002] [1003] •wi 'Focus' [1004] [1005] •wi '‘p' p [1006] [1007] e'CMDSEEK ý1' [1008] [1009] ¦  Sadly, when you click a different row in the list, both these events fire [1010] •wi 'onClick' e [1011] •wi 'onSelect' e [1012] [1013] •wi 'keys' 13 ¦ 13=Enter [1014] •wi 'onKeyPress' e [1015] •wi 'onDblClick' e [1016] [1017] •wself':red' [1018] [1019] •wi '‘m' m [1020] [1021] •wi 'keys' 13 ¦ 13=Enter [1022] •wi 'onKeyPress' e [1023] •wi 'onMouseDouble' e ¦ sadly, there is no onDblClick [1024] [1025] L1: [1026] [1027] •wself':st' [1028] [1029] '.pb' •wi 'Delete' [1030] [1031] t(2æf)'variables' 'functions' 'fns/vars' [1032] t' ',(ôX),' hits on ',(ôE),' lines in ',(ôU),' ',t,' ' [1033] •wi 'SetStatus' 3 t [1034] [1035] v•ai[2]-v [1036] t(0 1ôv),' seconds elapsed' ¦ note free leading blank [1037] •wi 'SetStatus' 4 t [1038] [1039] •wself':' [1040] [1041] k•wi 'Wait' [1042] [1043] 0 [1044] [1045] ¦ ============================================================================= [1046] [1047] L9: [1048] [1049] ¦ ••wself •wevent •warg '(' ('#' •wi 'focus') ')' ¦ debug [1050] [1051] :SELECT •wevent [1052] [1053] :CASE 'Resize' [1054] [1055] (1=3•warg)û0 ¦ noop if minimize [1056] [1057] z•wi 'size' [1058] •wself':lv' [1059] w•wi 'where' [1060] w[3]z[1] [1061] •wi 'where' w [1062] •wself':red' [1063] w•wi 'where' [1064] w[3 4]z[1],z[2]-w[2] [1065] •wi 'where' w [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] p•wi '‘p' [1110] N2p[i;] ¦ name [1111] [1112] k•WCALL 'W_Edit' N [1113] [1114] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1115] [1116] :CASE 'MouseDouble' [1117] [1118] ¦ Second mouseup has not occurred yet, so we have to wait [1119] [1120] ¦ Pass mouse position before Windows does "word" select, which could change selection offset [1121] [1122] •wi 'Defer' 'CMDSEEK ý1' 'KeyPress' (•wi 'selection') [1123] [1124] :CASE 'KeyPress' [1125] [1126] :if 'Listview'ð•wi 'class' [1127] [1128] i•first •wi 'value' [1129] (i=0)û0 ¦ click in blank row? [1130] p•wi '‘p' [1131] N2p[i;] ¦ name [1132] [1133] :else [1134] [1135] Assert 'RichEdit'ð•wi 'class' [1136] [1137] ¦ This could be from Enter key or from MouseDouble [1138] :if •wargð13 [1139] s•first •wi 'selection' [1140] :else [1141] Assert 2=û,•warg [1142] s•first •warg [1143] :end [1144] •wi 'selection' s 0 ¦ cancel word-selection [1145] ¦  Sadly, Windows may have changed the offset to the beginning of a "word" [1146] p':lv' •wi '‘p' ¦ name, hits, beginning of line, line numbers [1147] n1ûp [1148] (s=p[n;4])û0 ¦ beyond end? [1149] i+/sòp[;4] [1150] (c N k g n)p[i;] [1151] e1+•wi 'CharToLine' g ¦ divider line [1152] d1+•wi 'CharToLine' s ¦ clicked line [1153] :if e=d [1154] n0 [1155] :else [1156] id-e [1157] (i>ûn)û0 ¦ on Interrupt message [1158] ný1+n[i] ¦ ý1+ because we recorded line numbers in origin 1 [1159] :end [1160] NN,'[',(ôn),']' [1161] [1162] :end [1163] [1164] k•WCALL 'W_Edit' N [1165] [1166] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1167] [1168] :CASE 'Sort' [1169] [1170] i•warg [1171] •wself':lv' [1172] d•wi 'sortorder' [1173] pý1 0•wi '‘p' [1174] [1175] :if iî1 2 ¦ Class, Name [1176] wd[•AV[2]p[d;i]] ¦ new order [1177] :if dðw ¦ already sorted? [1178] wd[•AV[2]p[d;i]] [1179] :end [1180] :elseif i=3 ¦ Hits [1181] wd[p[d;i]] [1182] :if dðw [1183] wd[p[d;i]] [1184] :end [1185] :else [1186] ö'Tilt' [1187] :end [1188] [1189] •wi 'sortorder' w ¦ this triggers a Select [1190] [1191] i•first •wi 'value' [1192] •wi '‘skipnextselect' i [1193] [1194] :CASE 'Close' [1195] [1196] ¦ Set value of key k in APLW.INI section [UCMDSREX] [1197] k•fx [2] 'k II v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ II [1198] [1199] 'Seek-Place' II •wi 'place' [1200] 'Seek-Visible' II •wi 'visible' [1201] [1202] ¦•wi 'Delete' ¦ requires APL+Win version ò 6.2 [1203] [1204] '#' •wi 'Defer' "'fmSeek' •wi 'Delete'" ¦ works with APL+Win version < 6.2 [1205] [1206] :CASE 'redFind' [1207] [1208] •wself':red' [1209] s•first •wi 'selection' [1210] m•wi '‘m' ¦ offsets, lengths [1211] :if •warg=1 ¦ 1=next ý1=prev [1212] i(m[;1]>s)â1 [1213] :if i>1ûm  i1  :end [1214] :else [1215] 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] [93] (Aðý1)ûL9 ¦ callbacks [94] [95] v•AI[2] ¦ elapsed time [96] [97] Aô•ENLIST A ¦ arg might be numeric in development mode [98] [99] ADLTB A ¦ user command may pass in leading/trailing blanks [100] [101] :if Að'' [102] •'For help, see' [103] •' ]seek ?' [104] 0 [105] :end [106] [107] XA ¦ save original arg [108] [109] ¦ Allow simple word search without delimiters [110] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [111] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [112] A'/',A [113] :end [114] [115] ¦ Parse targets and functions [116] [117] G0û '' ¦ targets [118] S0û '' ¦ functions [119] [120] :repeat [121] D1A ¦ delimiter [122] A1A [123] IAâD ¦ find second delimiter (might not be one) [124] :if I=1 [125] •'Empty target string is not a good idea' [126] 0 [127] :end [128] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [129] ADLB IA [130] P1A ¦ function or option [131] :if ~Pî'<ó=ò>†ú^åê&þ' [132] :leave [133] :end [134] P('^ú',P)['&þ'âP] [135] ADLB 1A [136] :if '~'=1A [137] PP,'~' [138] ADLB 1A [139] :end [140] S( P),S ¦ function [141] :if Að'' [142] •'Multiple target syntax error' [143] 0 [144] :end [145] :end [146] [147] FA ¦ options (old left argument) [148] [149] D•FIRST ûG ¦ number of targets [150] [151] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [152] [153] ¦ Define ìFILT for APL/quoted strings/comments: [154] [155] Z'à''¦'îF [156] Z[2]Z[2]ú'"'îF [157] Z2æZ [158] E~Zî0 8 ¦ not all or none: we need to filter [159] [160] :if E ¦ unless all or none [161] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [162] LL, "¦ Quotes and Comments" [163] LL, "¦ Right arg is a •VR" [164] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [165] LL, "¦ Extracted from Zark's ìParseVR" [166] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [167] LL, "¦ 26 Oct 2004 Include ¦õ" [168] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [169] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [170] LL, "•IO0 ¦ origin 0 is convenient" [171] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [172] LL, "xcx\n" [213] LL, "¦ Flag newline after each comment; then convert pairs to maps" [214] LL, "tnúc" [215] LL, "ut/c" [216] LL, "c†\x\t\uúý10,u" [217] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [218] ¦ 0=None and 7=All cases are excluded before we get here [219] P 'rc' ¦ 1 = ¦ [220] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [221] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [222] PP, 'rqåc' ¦ 4 = à = 'å¦ [223] PP, 'r~q' ¦ 5 = ঠ= ~' [224] PP, 'r~c' ¦ 6 = à' = ~¦ [225] LL,P[Z] [226] K•FX[2]L ¦õ QC [227] :end [228] [229] L 'RFILT' [230] LL, '¦ Raw hit filter' [231] LL, '¦ V=•VR, P=partition flags' [232] ¦LL, 'R~P ANDSCAN Vî"[1234567890]"' ¦ not line numbers [233] LL, 'RP ANDSCAN V†"]"' ¦ not line numbers; allow for (2)[23;] too [234] ¦LL, 'RRåý1è1 0R' ¦ flag the ] too (we assume there is one!) [235] LL, 'RRåR<ý1èR' ¦ < is way faster than  [236] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [237] [238] K•FX[2]L ¦õ FILT ANDSCAN QC [239] [240] ¦ Define ìSYN for syntactic search [241] [242] Z''îF ¦ non-syntactic search? [243] [244] ¦ Token alphabet: chars that can be anywhere in a token [245] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [246] a'_' [247] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [248] aa,'abcdefghijklmnopqrstuvwxyzñ' [249] aa,'0123456789' [250] ¦ Token alphabet, including chars that can only begin a token [251] qa,'•ý' [252] [253] Q 'HA SYN H;B;I' [254] QQ, '¦ Syntactic hit filter' [255] QQ, '¦ Requires: V=•VR, a,q=alphabet' [256] QQ, 'IH/âûH' [257] ¦  Note that if target starts with • then we don't care what's to the [258] ¦ left of it, so ((1A)îa) is correct. [259] QQ, ':if (1A)îa' [260] QQ, ' H[(('' '',V)[I]îq)/I]0' [261] QQ, ':end' [262] QQ, ':if (ý1A)îq' [263] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [264] QQ, ':end' [265] :if Z=1 ¦ Neither? [266] Q1ûQ ¦ noop [267] :end [268] K•FX[2]Q ¦õ SYN a q [269] [270] ¦ Define ìUP for case-insensitive filter [271] [272] Z'ï'îF ¦ ignore case when finding target? [273] [274] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [275] ¦ Noop if no letters in targets [276] K•FX[2]'VUP V' '¦ noop' [277] :elseif Z [278] Q'ñabcdefghijklmnopqrstuvwxyz' [279] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [280] u•AV [281] u[uâQ]L [282] K•FX[2]'VUP V' 'Vu[•AVâV]' ¦õ UP u ¦ this is faster than ñUCASE! [283] :else [284] m'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [285] u'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [286] Q 'VUP V;B;I;L;S' [287] QQ, '¦ Force APL+Win keyword names to upper case' [288] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [289] QQ, '¦ RHS 11/18/99' [290] QQ, '' [291] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [292] QQ, 'BVî''•'' ¦ find key symbols' [293] QQ, '(1îB)0 ¦ quit if none' [294] QQ, '' [295] QQ, 'LVîm ¦ flag all letters (any case)' [296] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [297] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [298] QQ, '(1îB)0 ¦ quit if none' [299] QQ, '' [300] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [301] QQ, 'IS/B ¦ flag those which are candidates' [302] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [303] QQ, 'I†\I ¦ name mask' [304] QQ, 'II/âûI ¦ indices' [305] QQ, '' [306] QQ, 'V[I]u[mâV[I]] ¦ translate' [307] K•FX[2]Q [308] ¦ RHS 3/19/01 [309] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [310] ¦ when searching for 'fMain'. [311] ¦ List of keywords? No, could have ':end' •wi 'New' ... [312] ¦ I think we need to upper-case just the à part of the •vr [313] ¦ RHS 2/06/06 [314] ¦ I often search for •fappend or •io. [315] ¦ I cannot recall EVER having searched for :repeat. [316] ¦ So let's not worry about control structure keywords. [317] :end [318] [319] GUPG ¦ targets to uppercase [320] A1G ¦ last (and typically only) target string [321] [322] ¦ Options setup [323] [324] T'~'îF ¦ all but named fns? [325] b'+'îF ¦ expanded context? [326] f'ì'îF ¦ just fns/vars? [327] ffúå/f ¦ neither means both [328] UL1 ¦ search user command files? [329] [330] g'@'îF ¦ global fn matching? [331] :if g^D=1 [332] •'FYI, the @ option has no effect with just one target string' [333] g0 [334] :end [335] [336] ¦ Strip flags from function list [337] [338] E'*'îF ¦ any function name wildcards? [339] F(~Fî'à''¦ï~?@+ì')/F ¦ note we do not remove asterisk [340] FWords F [341] [342] ¦ Default to all fns [343] [344] :if T^0=ûF [345] •'Tilde with no names means "not all fns/vars"' [346] 0 [347] :end [348] [349] E'' ¦ accumulate warning messages [350] [351] ULûL2 ¦ FIXME specific fn names, wildcards not supported? [352] [353] :if EúTú0=ûF [354] [355] ¦ You could have a global function that is localized but undefined [356] ¦ •IDLIST 1+2+8 will not pick up that name, so... [357] [358] N•SINL [359] N(~N[;1]î'õ•><')ëN ¦ no local names at these levels [360] N(,ú\N=' ')/,N ¦ discard FOO[3], keep names to the right [361] NWords N ¦ all localized names [362] NN~ ,'*' ¦ the asterisk next to suspended fn is not a name [363] N('•'†•FIRSTN)/N ¦ avoid picking up system vars (ñUCMD2 localizes •PW and •CT) [364] [365] M•IDLIST 1+2+8 ¦ all visible names [366] MWords M [367] MM,N ¦ add all localized names [368] ¦MM,'•ALX' '•ELX' '•LX' ¦ ]WSLOC searches these ¦ oh forget it, ]ucmd shadows •ALX and •ELX [369] M((MâM)=âûM)/M ¦ there might be dups [370] MM[•AV[2]M] ¦ re-sort [371] [372] N,•SI [373] N(ý1+Nâ'[')ûN ¦ name of self ¦ RHS 8/31/99 [374] MM~ N ¦ remove self [375] [376] P•IDLOC [2]M ¦ what are they [377] PP[;0æûP] ¦ global definition [378] M(Pîf/1 2)/M ¦ fns and vars, depending on ì options [379] [380] ¦ Now we have all global fns/vars (though some could be shadowed) [381] [382] :if 0=ûF [383] FM [384] :elseif E ¦ which implies 0†ûF [385] :while '*'î•ENLIST F [386] P('*'îF)â1 [387] UPF [388] [389] VâûM ¦ indices of matches [390] C' ',M,' ' ¦ candidates [391] U('*'=1U)' ',U,('*'=ý1U)' ' [392] :for L :in '*' Words U [393] BC •SS L [394] Hú/B [395] C((H/B)â1)H/C [396] VH/V [397] :if Vð  :leave  :end [398] :end [399] CM[V] [400] [401] F((P-1)ûF),C,PF [402] :end [403] F((FâF)=âûF)/F ¦ in case wildcards picked up dup fns [404] :end [405] :if T [406] FM~F [407] :end [408] :end [409] [410] ¦ If we are filtering for APL/quotes/comments, ditch all variables [411] ¦ FIXME is this a good idea? what if •vr's stored in vars? [412] [413] ¦ :if 3=•NC 'QC' [414] ¦ F(2†•NC [2]F)/F [415] ¦ •'ditching vars' [416] ¦ :end [417] [418] ¦ Discard invalid names [419] [420] C•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] [433] L•IDLOC [2]F ¦ what are names fn=1 var=2 [434] L0 ý1L ¦ disregard global level [435] CL^.=ý1 [436] :if 0îC [437] N(~C)/F [438] ¦•'*** Shadowed:',ôN [439] EE,•TCNL,'Shadowed:',ôN [440] FC/F [441] :end [442] [443] ¦ Discard non-functions [444] [445] ¦C3=•NC [2]F [446] ¦C(•NC [2]F)î2 3 4 ¦ VARS! ¦ 4 allows •LX; we already checked for invalid [447] C(•NC [2]F)î2 3 ¦ VARS! [448] :if 0îC [449] N(~C)/F [450] ¦•'*** Not function',(1=ûN)'s:',ôN [451] ¦EE,•TCNL,'Not function',(1=ûN)'s:',ôN [452] EE,•TCNL,'Not functions or variables:',ôN ¦ VARS! [453] FC/F [454] :end [455] [456] ¦ Discard locked functions [457] [458] K•EX 'L' [459] ¦K•FX [2] 'RL F' "R0†•FIRST û•CRL F,'[0]'" ¦õ L [460] K•FX [2] 'RL F' ":if 3=•NC F  R0†•FIRST û•CRL F,'[0]'  :else  R1  :end" ¦õ L ¦ VARS! [461] CLF ¦ yuck, but I wanted to get this check out of the function loop [462] K•EX 'L' [463] :if 0îC [464] N(~C)/F [465] ¦•'*** Locked function',(1=ûN)'s:',ôN [466] EE,•TCNL,'Locked function',(1=ûN)'s:',ôN [467] FC/F [468] :end [469] [470] L2: [471] [472] :if UL [473] ul•wcall 'W_Ini' '[DIFF] ULIST' [474] :if ul^.=' ' [475] •'ULIST not set; use ]DIFF /ULIST=...' [476] 0 [477] :end [478] ul';' Words ul [479] [480] Nûul [481] V(ôN),(-N=1)' files' [482] ¦ Gather C and TN [483] TN [484] C [485] :for i :in âûul [486] ¦ Don't use ñTIEUF because it disturbs ucmd globals [487] tnñFTNUM iul [488] :if tn=0 [489] tn•FNUMS,•XFNUMS [490] tn((âûtn)îtn)â0 [491] (iul) •FSTIE tn [492] :end [493] TNTN,tn [494] j•FREAD tn,2 ¦ pointers to directories [495] un•FREAD tn,j[3] ¦ num directory of objects (nc, comp) [496] cun[;1] [497] c(cîf/3 2)/c ¦ 3=fn 2=var, depending on ì options [498] CC,c ¦ big vec of •nc [499] :end [500] N•first ûC [501] F, 20û' ' ¦ kludge for listview initial column width [502] :else [503] ul1û '' ¦ kludge to get one iteration in uloop [504] uf0 ¦ never show file name heading [505] VDLTB •WSID [506] :if Vð'' [507] V'CLEAR WS' [508] :end [509] N•first ûF [510] C•NC [2]F [511] :end [512] [513] :if N=0 [514] ¦•'No functions to search!' [515] ¦EE,•TCNL,'No functions to search!' [516] EE,•TCNL,'Nothing to search!' ¦ VARS! [517] ¦0 [518] :end [519] [520] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [521] k•fx [2] 'vk II d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ II [522] [523] w•FI 'Seek-Place' II '2 5 25 75' [524] z•FI 'Seek-Visible' II '1' [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] •wi 'where' z [603] [604] •wself':bn' •wi 'Create' 'Button' 'Hide' [605] •wi 'style' 2 ¦ 2=cancel [606] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [607] [608] z':' •wi 'size' [609] [610] •wself':lv' •wi 'Create' 'Listview' [611] •wi 'style' 1 2 4 8 128 4096 ¦ 128=no header 4096=grid [612] •wi 'where' (0,0,z[1],200) ¦ wide enough so no horiz scroll bar, else 'size' misleading [613] [614] ¦•wi 'font' 'APL Santa Fe' 0.8 ¦ no, then ñ doesn't display correctly [615] [616] •wi 'scale' 3 ¦ font size will be specified in points [617] [618] ¦•wi 'font' 'APLFONT' 11 0 'default' ¦ 11 13 [619] [620] ¦ Get value of key k; if undefined, write default to the ini file [621] k•fx [2]( [2] •cr 'II'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ II [622] [623] t 'FontName' II 'APLFONT' [624] tt,•FI 'FontSize' II '11' [625] tt,•FI 'FontStyle' II '0' [626] tt, 'FontCharset' II 'default' [627] •wi 'font' t [628] [629] •wi 'scale' 1 [630] [631] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [632] ¦ first col must be left justified [633] c0 3û0 [634] ccž'C' 2 'left' [635] ccž'Name' (5/•enlist ûF) 'left' ¦ 5 to avoid •WI DOMAIN ERROR when N=0 [636] ccž'Hits' 5 'right' [637] ccž'Fake' 0 'right' ¦ because of behavior of 'AutoFit' 'header' 'all' [638] [639] •wi 'list' (0,1,100 1û'x') ¦ force vertical scrollbar [640] [641] •wi 'columndisplay' c [642] w+/c[;2] [643] d•wi 'size' [644] d[2]w ¦ + 5 ¦ allow for vert scrollbar [645] •wi 'size' d [646] w4•wi 'where' [647] [648] •wi 'list' (0 3û0 1 '') ¦ remove fake row that forced vertical scrollbar [649] [650] •wself':red' •wi 'Create' 'RichEdit' [651] •wi 'style' 4 16 64 4096 16384 32768 ¦ 4=multi-line 16=V SB 64=H SB 2048=APL 4096=read-only [652] ¦ 16384 else entire text selected when you select the Form [653] ¦ 32768 disable automatic word selection when highlighting with mouse [654] [655] •wi 'where' (0,w,z[1],z[2]-w) [656] [657] HW•wi 'hwnd' [658] [659] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [660] •wi 'selection' 0 ý1 ¦ select all [661] •wi 'scale' 3 ¦ points [662] [663] ¦•wi 'selfont' 'APL Santa Fe' 10 0 'default' ¦ all black [664] ¦•wi 'selfont' 'APL Santa Fe' 11 0 'default' ¦ shaded but readable [665] ¦•wi 'selfont' 'APL Santa Fe' 12 0 'default' ¦ shaded but readable [666] ¦•wi 'selfont' 'APL385 Unicode' 11 0 'default' ¦ Dyalog style; kinda ugly [667] ¦•wi 'selfont' 'APLNext' 11 0 'default' ¦ a little crisper [668] [669] t 'UFontName' II 'APLNext' [670] tt,•FI 'UFontSize' II '11' [671] tt,•FI 'UFontStyle' II '0' [672] tt, 'UFontCharset' II 'default' [673] •wi 'selfont' t [674] [675] ¦  Necessary because default is bold (huh?) [676] •wi 'selstyle' (0 0 0 0 0) ¦ bold, italic, underline, strikeout, protected [677] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection [678] [679] 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 [680] 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 [681] ¦ 183=U00B7 : Middle dot, for untranslatable chars [682] [683] ¦ Streamlined version of ìAV2U [684] t 'UAU A;N' [685] tt, 'UA2[A1âA]' [686] tt, ':if 82†•DR A' [687] tt, ' N,0=•TYPE A' [688] tt, ' (N/,U)N/,A' [689] tt, ':end' [690] tt, 'U•FIRST 323 163 82 •DR U' [691] k•fx [2] t ¦õ AU A1 A2 [692] [693] ¦ Streamlined version of ìSetSelTextU [694] k•fx [2] 'ST A;K;U' 'UAU A' "K•wcall 'EM_SetTextEx' HW ('ST_SELECTION' 1200) (U,2û•tcnul)" ¦õ ST AU HW [695] [696] t' ]SEEKU ',X [697] [698] ¦ tt,•tcnl,50û9472 ¦ U2500 : Unicode horizontal line [699] ¦ tt,•tcnl,'Test difficult characters:' [700] ¦ tt,•tcnl,'Execute õ' [701] ¦ tt,•tcnl,' Match ð' [702] ¦ tt,•tcnl,' Zilde ' [703] ¦ tt,•tcnl,' Domino ˜' [704] [705] tt,•tcnl [706] ST t [707] [708] •wi 'selection' (0,ý1+ût) ¦ offset, length [709] •wi 'selcolor' (0 196 0) [710] •wi 'selstyle' (1 0 0 0 0) ¦ bold [711] •wi 'selection' ý1 ¦ select none; cursor to end [712] [713] :if ’ûE ¦ any warnings? [714] s1•wi 'selection' [715] ST 1èE [716] •wi 'selection' (s,ý1+ûE) ¦ offset, length [717] •wi 'selcolor' (255 0 0) [718] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [719] •wi 'selection' ý1 ¦ select none; cursor to end [720] :end [721] [722] ¦ Pre-build a CHARFORMAT2 structure that sets background color [723] CF8484 ¦ cbSize [724] CF[8]4 ¦ dwMask CFM_BACKCOLOR [725] CF[65 66 67]255 255 128 ¦ pale yellow [726] CFAV CF [727] [728] •wself':' [729] [730] •wi 'Show' [731] e'CMDSEEKU ý1' [732] •wi 'onResize' e [733] •wi 'onClose' e [734] [735] ':lv' •wi 'Focus' ¦ necessary to make Esc work during search (why?) [736] [737] X0 ¦ count hits [738] E0 ¦ count lines with hits [739] U0 ¦ count functions with hits [740] p0 5û' ' '' 0 0  ¦ class, name, # hits, pointer to fn in RichEdit, line numbers with hits [741] m0 2û ¦ all hits (start, length) in RichEdit [742] [743] •wself':red' [744] [745] :FOR ui :in âûul [746] [747] :if UL [748] tnuiTN [749] j•FREAD tn,2 ¦ pointers to directories [750] uc•FREAD tn,j[2] ¦ char directory of objects (names) [751] un•FREAD tn,j[3] ¦ num directory of objects (nc, comp) [752] [753] cun[;1]îf/3 2 ¦ 3=fn 2=var, depending on ì options [754] uccëuc [755] uncëun [756] [757] j•AVuc [758] unun[j;] [759] ucuc[j;] [760] ucWords uc [761] Fâûj ¦ kludge for name loop [762] uf1 ¦ show file name heading on first hit [763] :end [764] [765] :for N :in F ¦ inspect next function [766] [767] ¦k•dl 0.1 [768] [769] :if ':' •wi '‘stop' [770] s1•wi 'selection' [771] t'Interrupt',•tcnl [772] ST t [773] •wi 'selection' (s,ût) ¦ offset, length [774] •wi 'selcolor' (255 0 0) [775] •wi 'selstyle' (1 0 0 0 0) ¦ bold [776] •wi 'selection' ý1 ¦ select none; cursor to end [777] :leave [778] :end [779] [780] ':st.pb' •wi 'Stepit' [781] [782] ¦•wgive 0 ¦ yikes, this makes it take twice as long! [783] [784] ¦t100’iöN [785] ¦':st' •wi 'SetStatus' ('Searching function ',(ôi),' of ',(ôN),' (',(ôt),'%)','...') [786] ¦':st' •wi 'SetStatus' 3 (' Searching function ',(ôi),'... ') [787] ¦':st' •wi 'SetStatus' 3 (' Searching ',(ô100’iöN),'%... ') [788] [789] ¦  This was nice in the event that a huge variable took forever to search. [790] ¦ But it makes the other status panes shiver [791] ¦':st' •wi 'SetStatus' 4 (' ',N) [792] [793] :IF UL [794] [795] y,3=un[N;1] ¦ is it a function? ¦ RHS 1/25/08 ravel so like •NC which returns a one-element vector [796] V•FREAD tn,un[N;2] [797] NNuc ¦ name of object [798] :if y [799] ¦ V is •VR already [800] V[1 2]'[]' ¦ kludge for FILT [801] :else [802] :if Nð'xmMap' ¦ Winklevoss kludge [803] :continue [804] :end [805] VSEEKFMT V [806] :if 0=ûV [807] :continue [808] :end [809] :end [810] [811] :ELSE ¦ if not UL [812] [813] y3=•NC N ¦ is it a function? ¦ VARS! ¦ note •NC says 4 for •LX, but we ony test 3= [814] :if y [815] V•VR N [816] V[1 2]'[]' ¦ kludge for FILT [817] :else [818] VõN [819] ¦ :if 82†•DR V [820] ¦ :orif 2<ûûV [821] ¦ :continue [822] ¦ :else [823] ¦ :if 2=ûûV [824] ¦ t1ûV [825] ¦ w4+2ûôt ¦ we want a blank between ']' and data, so FILT will work [826] ¦ V(('P—[—Q—;]—LI',ôw) •FMT ât),V [827] ¦ ¦ Keep trailing blanks, since they are arguably part of the data [828] ¦ V,V,•TCNL [829] ¦ :elseif •TCNLîV [830] ¦ ¦ Don't use ìPartition because we want to keep empty partitions [831] ¦ V1(V=•TCNL) •PENCLOSE V [832] ¦ tûV [833] ¦ w3+3ûôt ¦ we want a blank between ']' and data, so FILT will work [834] ¦ V( [2] ('P—[—Q—]—LI',ôw) •FMT ât),V [835] ¦ V•ENLIST V,•TCNL [836] ¦ :else ¦ simple vector, no CRs [837] ¦ V(6'[]'),V,•TCNL [838] ¦ :end [839] ¦ :end [840] ¦L•ai[2] [841] VSEEKFMT V [842] ¦L•ai[2]-L [843] ¦:if Lò1 [844] ¦ •'FYI, it took ',(ôL),' seconds for ]SEEK to search: ',N [845] ¦ ¦ FIXME so what? erase it? actually time was used formatting it. [846] ¦:end [847] :if 0=ûV [848] :continue [849] :end [850] ¦VV,6û' ' ¦ make it like a •VR; see ý5+ûV kludge below [851] ¦  not necessary now that we match •TCNL rather than •TCNL,'[' [852] :end [853] [854] :END [855] [856] LUP V [857] [858] ¦ Search •VR [859] [860] HL •SS A ¦ the heart of the matter [861] [862] :if D=1 ¦ single target? [863] :andif ~1îH ¦ no raw hits? [864] :continue ¦ next function [865] :end [866] [867] ¦ Syntactic filter [868] [869] HA SYN H ¦õ V a q [870] [871] :if D=1 ¦ single target? [872] :andif ~1îH ¦ no more hits? [873] :continue ¦ next function [874] :end [875] [876] ¦ Filter for APL / quoted strings / comments [877] [878] ¦P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [879] ¦  This doesn't work with my variable formatting stuff, like '(2)[13;] ...' [880] ¦ And besides, you're not allowed to have CRs embedded in functions any more [881] P1,ý1V •SS •TCNL ¦ partition on "[" (with trailing CRs); force header line [882] ¦ •SS is still faster than plain = ! [883] ¦P[ý5+ûV]1 ¦ force end of last line [884] ¦ The last 7 characters of a •VR are: •TCNL,' ì',•TCNL [885] ¦ P[ý5+ûV]1 above flags ....................  this blank [886] ¦ No, now that's not necessary at all, now that we match •TCNL rather than •TCNL,'[' [887] [888] IFILT ¦õ P V ANDSCAN [889] HH^I [890] [891] :if D=1 ¦ single target? [892] :andif ~1îH ¦ no more hits? [893] :continue ¦ next function [894] :end [895] [896] R(ûV)û0 [897] R[(H/âûH)ø.+ý1+âûA]1 ¦ flag chars to highlight [898] [899] hP ORRED H ¦ shift hits to leading "[" [900] [901] :if D>1 ¦ multiple targets [902] [903] ¦ We have already done the last target; now step through the others [904] ¦ Note that they are in reverse order so functions work like APL [905] [906] ¦ /t1/ú/t2/ don't stop and display after first hit -- we want to show them all [907] ¦ /t1/&~/t2/ it is okay to show "all" hits since we will exclude lines with t2 [908] [909] :if g ¦ "@" global option? [910] tú/h [911] :for J :in 1âD [912] WL •SS JG ¦ raw search [913] W(JG) SYN W ¦ SYN [914] WW^I ¦ FILT [915] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [916] HHúW ¦ all hits [917] WP ORRED W ¦ shift hits to leading "[" [918] hWúh ¦ lines to show [919] tõ'(ú/W)',(JS),'t' ¦ apply function [920] :end [921] :if ~t ¦ no hits? [922] :continue ¦ next function [923] :end [924] :else [925] :for J :in 1âD [926] WL •SS JG ¦ raw search [927] W(JG) SYN W ¦ SYN [928] WW^I ¦ FILT [929] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [930] HHúW ¦ all hits [931] WP ORRED W ¦ shift hits to leading "[" [932] hõ'W',(JS),'h' ¦ apply function [933] :end [934] :if ~1îh ¦ no more hits? [935] :continue ¦ next function [936] :end [937] :end [938] [939] ¦ Only count hits on lines that will be displayed [940] ¦ (When searching for /1/^/2/ don't count 2s on lines without 1) [941] [942] Hh/P PLUSRED H [943] [944] :end [945] [946] ¦ Got some hits [947] [948] :if uf [949] uf0 [950] e9552 ¦ 9552=U2550 : Double horizontal line [951] t(5ûe),' File: ',(uiul),' ' [952] tt,((70-ût)ûe),•tcnl [953] ST t [954] [955] n•first ût ¦ length of line [956] s1•wi 'selection' [957] ss-n ¦ back up to beginning of line [958] •wi 'selection' s (n-1) ¦ offset, length [959] [960] ¦ Mark thinks this is too colorful [961] ¦ jCF [962] ¦ j[65 66 67]AV 196 255 255 ¦ pale cyan [963] ¦ k•wcall 'EM_SETCHARFORMAT' HW 1 j ¦ SCF_SELECTION=1 ¦ background [964] [965] •wi 'selection' ((s+12),ûuiul) ¦ just the file name [966] •wi 'selstyle' (1 0 0 0 0) ¦ bold [967] [968] •wi 'selection' ý1 ¦ select none; cursor to end [969] :end [970] [971] x+/H ¦ total hits in this fn [972] t':lv' •wi 'AddRows' 0 1 (,'ì'[1+y]) N (ôx) [973] k':lv' •wi 'EnsureVisible' t [974] [975] XX+x ¦ accumulate total hits [976] Hh ¦ lines with hits [977] EE++/H ¦ accumulate lines with hits [978] UU+1 ¦ accumulate functions with hits [979] [980] ¦ Display hits [981] [982] HH/âûH ¦ line numbers to display (origin 1) [983] WûH ¦ number of lines with hits [984] PP/âûP ¦ partition starts [985] L(1P,1+ûV)-P ¦ partition lengths [986] :if b ¦ expanded context? [987] :if y [988] eâûP ¦ all line numbers (including the trailing ì line) [989] :else [990] eâý1+ûP ¦ all line numbers (the last line of variables is bogus) [991] :end [992] H(eîHø.+ý1 0 1)/e ¦ this takes care of dups and edges [993] IH>1+ý1èH ¦ flag beginnings of groups of lines [994] :else [995] I(ûH)û0 [996] :end [997] PP[H]-1 ¦ compensate for +â with •IO1 [998] LL[H] ¦ lengths, incl trailing CRs [999] [1000] ppž ('ì'[1+y]) N x (1•wi 'selection') H [1001] [1002] e5û9472 ¦ 9472=U2500 : Horizontal line [1003] ¦  5 positions the fn name where it is in the header line (of a niladic fn) [1004] te,' ',N,' (',(ôx),' hit',(x=1)'s',((x†W)/' on ',(ôW),(-W=1)' lines'),') ' [1005] tt,((70-ût)ûe),•tcnl [1006] ST t [1007] n•first ût ¦ length of line [1008] s1•wi 'selection' [1009] ss-n ¦ back up to beginning of line [1010] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [1011] •wi 'selection' s (n-1) ¦ offset, length [1012] :if y [1013] V[1 2]' ' ¦ undo kludge for FILT [1014] •wi 'selcolor' (0 0 255) ¦ blue fns [1015] :else [1016] •wi 'selcolor' (255 0 255) ¦ purple vars [1017] :end [1018] •wi 'selection' (6+s) (•first ûN) ¦ just the function name [1019] •wi 'selstyle' (1 0 0 0 0) ¦ bold [1020] •wi 'selection' ý1 ¦ select none; cursor to end [1021] •wi 'Paint' ¦ show bolded fn name while hits display [1022] [1023] :for B :in âûH [1024] :if I[B] [1025] ST (3û183),•TCNL ¦ 183=U00B7 : Middle dot [1026] :end [1027] nL[B] [1028] jP[B]+ân ¦ indices of line in •VR [1029] ST V[j] [1030] s(1•wi 'selection')-n+1 [1031] C(R[j]) Partition ân ¦ groups of chars to highlight [1032] :for j :in C [1033] e(s+1j),ûj ¦ offset, length [1034] mmže ¦ all hits [1035] •wi 'selection' e ¦ offset, length [1036] ¦•wi 'selcolor' (255 0 255) ¦ purple [1037] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [1038] k•wcall 'EM_SETCHARFORMAT' HW 1 CF ¦ SCF_SELECTION=1 ¦ yellow background [1039] :end [1040] •wi 'selection' ý1 ¦ select none; cursor to end [1041] :end [1042] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection ¦ else :red does not scroll down [1043] •WGIVE 0 ¦ listview does not display without this [1044] ¦k•dl 0.1 [1045] [1046] :end ¦ next function [1047] :END ¦ next ufile [1048] [1049] ':bn' •wi 'onClick' '' ¦ let style 2 take over [1050] [1051] ¦ •wi 'selection' 0 ý1 ¦ select all [1052] ¦ •wcall 'EM_SETPARAFORMAT' HW PARAFORMAT2 [1053] ¦ •wi 'selection' ý1 ¦ select none; cursor to end [1054] [1055] :if U=0 [1056] [1057] s1•wi 'selection' [1058] [1059] t'Not found',•tcnl [1060] ST t [1061] [1062] •wi 'selection' (s,ý1+ût) ¦ offset, length [1063] •wi 'selcolor' (255 0 0) [1064] •wi 'selstyle' (1 0 0 0 0) ¦ bold [1065] •wi 'selection' 0 0 ¦ cursor to top [1066] [1067] L1 [1068] [1069] :end [1070] [1071] ppž ' ' '' 0 (1•wi 'selection')  ¦ fake row so we know position of end of text [1072] [1073] •wi 'selection' 0 0 ¦ cursor to top [1074] [1075] •wself':lv' [1076] [1077] •wi 'noredraw' 1 [1078] •wi 'AutoFit' 'all' [1079] c•wi 'columndisplay' [1080] cý1 0c ¦ delete Fake column [1081] •wi 'columndisplay' c [1082] [1083] •wi 'highlightfocus' 1 [1084] •wi 'value' 1 [1085] k•wi 'EnsureVisible' 1 [1086] [1087] •wi 'noredraw' 0 [1088] [1089] d+/c[;2] [1090] z•wi 'size' [1091] z[2]d [1092] •wi 'size' z [1093] w•wi 'where' [1094] [1095] z':' •wi 'size' [1096] d':red' •wi 'where' [1097] d[2]w[4] [1098] d[4]z[2]-w[4] [1099] ':red' •wi 'where' d [1100] [1101] •wi 'Focus' [1102] [1103] •wi '‘p' p [1104] [1105] e'CMDSEEKU ý1' [1106] [1107] ¦  Sadly, when you click a different row in the list, both these events fire [1108] •wi 'onClick' e [1109] •wi 'onSelect' e [1110] [1111] •wi 'keys' 13 ¦ 13=Enter [1112] •wi 'onKeyPress' e [1113] •wi 'onDblClick' e [1114] [1115] •wself':red' [1116] [1117] •wi '‘m' m [1118] [1119] •wi 'keys' 13 ¦ 13=Enter [1120] •wi 'onKeyPress' e [1121] •wi 'onMouseDouble' e ¦ sadly, there is no onDblClick [1122] [1123] L1: [1124] [1125] •wself':st' [1126] [1127] '.pb' •wi 'Delete' [1128] [1129] t(2æf)'variables' 'functions' 'fns/vars' [1130] t' ',(ôX),' hits on ',(ôE),' lines in ',(ôU),' ',t,' ' [1131] •wi 'SetStatus' 3 t [1132] [1133] v•ai[2]-v [1134] t(0 1ôv),' seconds elapsed' ¦ note free leading blank [1135] •wi 'SetStatus' 4 t [1136] [1137] •wself':' [1138] [1139] k•wi 'Wait' [1140] [1141] 0 [1142] [1143] ¦ ============================================================================= [1144] [1145] L9: [1146] [1147] :SELECT •wevent [1148] [1149] :CASE 'Resize' [1150] [1151] (1=3•warg)û0 ¦ noop if minimize [1152] [1153] z•wi 'size' [1154] •wself':lv' [1155] w•wi 'where' [1156] w[3]z[1] [1157] •wi 'where' w [1158] •wself':red' [1159] w•wi 'where' [1160] w[3 4]z[1],z[2]-w[2] [1161] •wi 'where' w [1162] [1163] :CASELIST 'Click' 'Select' [1164] [1165] ¦ If you click on a new row, you get Click,Select [1166] ¦ If you click on the same row, you get just Click [1167] ¦ If you use keyboard, you get just Select [1168] [1169] i•first •wi 'value' [1170] (i=0)û0 ¦ click in blank row? [1171] [1172] :if •weventð'Click' [1173] •wi '‘skipnextselect' i [1174] :else [1175] Assert •weventð'Select' [1176] :if i=•wi '‘skipnextselect' [1177] •wi '‘skipnextselect' 0 [1178] 0 [1179] :end [1180] :end [1181] [1182] p•wi '‘p' [1183] (c N k s k)p[i;] ¦ class, name, hits, beginning of line, line numbers [1184] ss+6 ¦ advance past '----- ' [1185] n•first ûN [1186] [1187] •wself':red' [1188] [1189] •wi 'selection' s n [1190] [1191] ¦ Scroll into view on RichEdit control [1192] [1193] e1+•wi 'CharToLine' s ¦ line number of first line [1194] t1+•wi 'CharToLine' (p[i+1;4]-1) ¦ line number of last line [1195] g•wi 'range' [1196] g(g[1]-1)+âg[2] ¦ lines now visible [1197] :if 0î(e,t)îg ¦ if the whole fn is already visible, don't change range [1198] •wi 'range' e [1199] :end [1200] [1201] :CASE 'DblClick' [1202] [1203] i1•warg [1204] (i=0)û0 ¦ click in blank row? [1205] p•wi '‘p' [1206] N2p[i;] ¦ name [1207] [1208] k•WCALL 'W_Edit' N [1209] [1210] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1211] [1212] :CASE 'MouseDouble' [1213] [1214] ¦ Second mouseup has not occurred yet, so we have to wait [1215] [1216] ¦ Pass mouse position before Windows does "word" select, which could change selection offset [1217] [1218] •wi 'Defer' 'CMDSEEKU ý1' 'KeyPress' (•wi 'selection') [1219] [1220] :CASE 'KeyPress' [1221] [1222] :if 'Listview'ð•wi 'class' [1223] [1224] i•first •wi 'value' [1225] (i=0)û0 ¦ click in blank row? [1226] p•wi '‘p' [1227] N2p[i;] ¦ name [1228] [1229] :else [1230] [1231] Assert 'RichEdit'ð•wi 'class' [1232] [1233] ¦ This could be from Enter key or from MouseDouble [1234] :if •wargð13 [1235] s•first •wi 'selection' [1236] :else [1237] Assert 2=û,•warg [1238] s•first •warg [1239] :end [1240] •wi 'selection' s 0 ¦ cancel word-selection [1241] ¦  Sadly, Windows may have changed the offset to the beginning of a "word" [1242] p':lv' •wi '‘p' ¦ name, hits, beginning of line, line numbers [1243] n1ûp [1244] (s=p[n;4])û0 ¦ beyond end? [1245] i+/sòp[;4] [1246] (c N k g n)p[i;] [1247] e1+•wi 'CharToLine' g ¦ divider line [1248] d1+•wi 'CharToLine' s ¦ clicked line [1249] :if e=d [1250] n0 [1251] :else [1252] id-e [1253] (i>ûn)û0 ¦ on Interrupt message [1254] ný1+n[i] ¦ ý1+ because we recorded line numbers in origin 1 [1255] :end [1256] NN,'[',(ôn),']' [1257] [1258] :end [1259] [1260] k•WCALL 'W_Edit' N [1261] [1262] ':st' •wi 'SetStatus' 4 (' ',k) ¦ in case of 'Unable to edit object' [1263] [1264] :CASE 'Sort' [1265] [1266] i•warg [1267] •wself':lv' [1268] d•wi 'sortorder' [1269] pý1 0•wi '‘p' [1270] [1271] :if iî1 2 ¦ Class, Name [1272] wd[•AV[2]p[d;i]] ¦ new order [1273] :if dðw ¦ already sorted? [1274] wd[•AV[2]p[d;i]] [1275] :end [1276] :elseif i=3 ¦ Hits [1277] wd[p[d;i]] [1278] :if dðw [1279] wd[p[d;i]] [1280] :end [1281] :else [1282] ö'Tilt' [1283] :end [1284] [1285] •wi 'sortorder' w ¦ this triggers a Select [1286] [1287] i•first •wi 'value' [1288] •wi '‘skipnextselect' i [1289] [1290] :CASE 'Close' [1291] [1292] ¦ Set value of key k in APLW.INI section [UCMDSREX] [1293] k•fx [2] 'k II v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ II [1294] [1295] 'Seek-Place' II •wi 'place' [1296] 'Seek-Visible' II •wi 'visible' [1297] [1298] ¦•wi 'Delete' ¦ requires APL+Win version ò 6.2 [1299] [1300] '#' •wi 'Defer' "'fmSeek' •wi 'Delete'" ¦ works with APL+Win version < 6.2 [1301] [1302] :CASE 'redFind' [1303] [1304] •wself':red' [1305] s•first •wi 'selection' [1306] m•wi '‘m' ¦ offsets, lengths [1307] :if •warg=1 ¦ 1=next ý1=prev [1308] i(m[;1]>s)â1 [1309] :if i>1ûm  i1  :end [1310] :else [1311] 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] [68] (Aðý1)ûL9 ¦ callbacks [69] [70] v•AI[2] ¦ elapsed time [71] [72] Aô•ENLIST A ¦ arg might be numeric in development mode [73] [74] ADLTB A ¦ user command may pass in leading/trailing blanks [75] [76] :if Að'' [77] •'For help, see' [78] •' ]superseek ?' [79] 0 [80] :end [81] [82] XA ¦ save original arg [83] [84] ¦ Allow simple word search without delimiters [85] ¦ If arg is 'foo', make it '/foo'; if arg is 'foo/xx' make it '/foo/xx' [86] :if A[1]î'•ý1234567890abcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZñ' [87] ¦ If the argument is 'foo /xx' then the blank should not be significant since [88] ¦ there was no leading delimiter. Is this a good idea? Technically the [89] ¦ blank should be significant. But this way is user-friendly. [90] :if 1=+/A='/' [91] Iý1+Aâ'/' [92] A(DTB IA),IA [93] :end [94] A'/',A [95] :end [96] [97] ¦ Parse targets and functions [98] [99] G0û '' ¦ targets [100] S0û '' ¦ functions [101] [102] :repeat [103] D1A ¦ delimiter [104] A1A [105] IAâD ¦ find second delimiter (might not be one) [106] :if I=1 [107] •'Empty target string is not a good idea' [108] 0 [109] :end [110] G( (I-1)ûA),G ¦ target (note we accumulate them right to left) [111] ADLB IA [112] P1A ¦ function or option [113] :if ~Pî'<ó=ò>†ú^åê&þ' [114] :leave [115] :end [116] P('^ú',P)['&þ'âP] [117] ADLB 1A [118] :if '~'=1A [119] PP,'~' [120] ADLB 1A [121] :end [122] S( P),S ¦ function [123] :if Að'' [124] •'Multiple target syntax error' [125] 0 [126] :end [127] :end [128] [129] FA ¦ options (old left argument) [130] [131] D•FIRST ûG ¦ number of targets [132] [133] S'ø',S ¦ to save repeated (J-1)S below, if multiple targets [134] [135] ¦ Define ìFILT for APL/quoted strings/comments: [136] [137] Z'à''¦'îF [138] Z[2]Z[2]ú'"'îF [139] Z2æZ [140] E~Zî0 8 ¦ not all or none: we need to filter [141] [142] :if E ¦ unless all or none [143] L "rQC v;c;i;n;p;q;s;t;u;x;z;•IO" [144] LL, "¦ Quotes and Comments" [145] LL, "¦ Right arg is a •VR" [146] LL, "¦ Result is a boolean vector with 0's marking all quoted strings and comments" [147] LL, "¦ Extracted from Zark's ìParseVR" [148] LL, "¦ 21 Mar 2002 Rex Swain, Independent Consultant, www.rexswain.com" [149] LL, "¦ 26 Oct 2004 Include ¦õ" [150] LL, "¦ 02 Nov 2006 Handle unclosed quotes correctly" [151] LL, "¦ 20 Nov 2006 Use GAB's technique for unclosed quotes" [152] LL, "•IO0 ¦ origin 0 is convenient" [153] LL, "cv •SS '¦õ' ¦ flag lamps followed by õ" [154] LL, "xcx\n" [195] LL, "¦ Flag newline after each comment; then convert pairs to maps" [196] LL, "tnúc" [197] LL, "ut/c" [198] LL, "c†\x\t\uúý10,u" [199] ¦LL, "rqåc ¦ flag where neither quotes nor comments" [200] ¦ 0=None and 7=All cases are excluded before we get here [201] P 'rc' ¦ 1 = ¦ [202] PP, 'rq>c' ¦ 2 = ' ¦ quoted strings: not in comments [203] PP, 'rqúc' ¦ 3 = ¦' = 'ú¦ [204] PP, 'rqåc' ¦ 4 = à = 'å¦ [205] PP, 'r~q' ¦ 5 = ঠ= ~' [206] PP, 'r~c' ¦ 6 = à' = ~¦ [207] LL,P[Z] [208] K•FX[2]L ¦õ QC [209] :end [210] [211] L 'RFILT' [212] LL, '¦ Raw hit filter' [213] LL, '¦ V=•VR, P=partition flags' [214] ¦LL, 'R~P ANDSCAN Vî"[1234567890]"' ¦ not line numbers [215] LL, 'RP ANDSCAN V†"]"' ¦ line numbers; allow for (2)[23;] too [216] ¦LL, 'RRåý1è1 0R' ¦ flag the ] too (we assume there is one!) [217] LL, 'RRåR<ý1èR' ¦ < is way faster than  [218] LL,E/ 'RR^QC V' ¦õ QC ¦ filter for à'¦ [219] [220] K•FX[2]L ¦õ FILT ANDSCAN QC [221] [222] ¦ Define ìSYN for syntactic search [223] [224] Z''îF ¦ non-syntactic search? [225] [226] ¦ Token alphabet: chars that can be anywhere in a token [227] ¦ a'._' ¦ Dilemma: period helps for numbers, but not PLUS.TIMES [228] a'_' [229] aa,'ABCDEFGHIJKLMNOPQRSTUVWXYZ‘' [230] aa,'abcdefghijklmnopqrstuvwxyzñ' [231] aa,'0123456789' [232] ¦ Token alphabet, including chars that can only begin a token [233] qa,'•ý' [234] [235] Q 'HA SYN H;B;I' [236] QQ, '¦ Syntactic hit filter' [237] QQ, '¦ Requires: V=•VR, a,q=alphabet' [238] QQ, 'IH/âûH' [239] ¦  Note that if target starts with • then we don't care what's to the [240] ¦ left of it, so ((1A)îa) is correct. [241] QQ, ':if (1A)îa' [242] QQ, ' H[(('' '',V)[I]îq)/I]0' [243] QQ, ':end' [244] QQ, ':if (ý1A)îq' [245] QQ, ' H[((V,'' '')[I+ûA]îa)/I]0' [246] QQ, ':end' [247] :if Z=1 ¦ Neither? [248] Q1ûQ ¦ noop [249] :end [250] K•FX[2]Q ¦õ SYN a q [251] [252] ¦ Define ìUP for case-insensitive filter [253] [254] Z'ï'îF ¦ ignore case when finding target? [255] [256] :if ~ú/(•ENLIST G)î'ñabcdefghijklmnopqrstuvwxyz‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [257] ¦ Noop if no letters in targets [258] K•FX[2]'VUP V' '¦ noop' [259] :elseif Z [260] Q'ñabcdefghijklmnopqrstuvwxyz' [261] L'‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' [262] u•AV [263] u[uâQ]L [264] K•FX[2]'VUP V' 'Vu[•AVâV]' ¦õ UP u ¦ this is faster than ñUCASE! [265] :else [266] m'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_‘ñ' ¦ mixed [267] u'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_‘ñ' ¦ upper [268] Q 'VUP V;B;I;L;S' [269] QQ, '¦ Force APL+Win keyword names to upper case' [270] QQ, '¦ In APL+Win, quad and control-structure names are case insensitive!' [271] QQ, '¦ RHS 11/18/99' [272] QQ, '' [273] ¦QQ, 'BVî''•:'' ¦ find key symbols' ¦ no! -- see comments below [274] QQ, 'BVî''•'' ¦ find key symbols' [275] QQ, '(1îB)0 ¦ quit if none' [276] QQ, '' [277] QQ, 'LVîm ¦ flag all letters (any case)' [278] QQ, 'BB>ý10,L ¦ flag symbols preceded by a non-letter' [279] QQ, 'BL^ý10,B ¦ flag letters preceded by a symbol preceded by a non-letter' [280] QQ, '(1îB)0 ¦ quit if none' [281] QQ, '' [282] QQ, 'SL†ý10,L ¦ letter state changes (S † next L)' [283] QQ, 'IS/B ¦ flag those which are candidates' [284] QQ, 'IS\I†ý10,I ¦ name start-stop flags for †\ (S S\ † next I)' [285] QQ, 'I†\I ¦ name mask' [286] QQ, 'II/âûI ¦ indices' [287] QQ, '' [288] QQ, 'V[I]u[mâV[I]] ¦ translate' [289] K•FX[2]Q [290] ¦ RHS 3/19/01 [291] ¦ Vî'•:' causes trouble for things like ':fMain' •wi ... [292] ¦ when searching for 'fMain'. [293] ¦ List of keywords? No, could have ':end' •wi 'New' ... [294] ¦ I think we need to upper-case just the à part of the •vr [295] ¦ RHS 2/06/06 [296] ¦ I often search for •fappend or •io. [297] ¦ I cannot recall EVER having searched for :repeat. [298] ¦ So let's not worry about control structure keywords. [299] :end [300] [301] GUPG ¦ targets to uppercase [302] A1G ¦ last (and typically only) target string [303] [304] ¦ Options setup [305] [306] oE'*'îF ¦ entire drive? [307] oX'+'îF ¦ expanded context? [308] T'ì'îF ¦ just fns/vars? [309] oFTúå/T ¦ neither means both [310] [311] oG'@'îF ¦ global fn matching? [312] :if oG^D=1 [313] •'FYI, the @ option has no effect with just one target string' [314] oG0 [315] :end [316] [317] ¦ Strip symbol flags from options list [318] [319] ((Fî'à''¦ï~?@+ì*')/F)' ' ¦ note we do remove asterisk [320] FWords F [321] [322] ¦ Parse other options [323] [324] T( ,1)ð•VIF [325] :if oE ¦ entire drive [326] oL, ,'\' [327] :elseif 1îT ¦ explicitly specified [328] oL•ENLIST T/•FIF ¦ library numbers [329] :else [330] oL•FI,11[2]•LIBS ¦ RHS 1/27/04 if no libs are defined, 0 0ðû•LIBS [331] :end [332] [333] ¦ ----- Start user interface ----- [334] [335] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [336] k•fx [2] 'vk II d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ II [337] [338] w•FI 'Seek-Place' II '2 5 25 90' [339] w[4]w[4]90 ¦ make sure wide enough for Status pane 4 [340] z•FI 'Seek-Visible' II '1' [341] zz-z=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [342] [343] •wself'fmSuperSeek' •wi 'Create' 'Form' 'Hide' [344] •wi 'caption' 'SuperSeek' [345] •wi 'place' w [346] •wi 'visible' z [347] e'CMDSUPERSEEK ý1' [348] •wi 'onClose' e [349] •wi 'limitwhere' 10 40 [350] [351] •wself':bn' •wi 'Create' 'Button' 'Hide' [352] •wi 'style' 2 ¦ 2=cancel [353] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [354] [355] •wself':mFile' •wi 'Create' 'Menu' [356] •wi 'caption' '&File' [357] [358] •wself'.mExit' •wi 'Create' 'Menu' [359] •wi 'caption' 'E&xit' [360] •wi 'shortcut' 'X' 2 [361] •wi 'onClick' "0 0û':' •wi 'Close'" [362] [363] •wself':mEdit' •wi 'Create' 'Menu' [364] •wi 'caption' '&Edit' [365] [366] •wself'.mCopy' •wi 'Create' 'Menu' [367] •wi 'caption' '&Copy' [368] •wi 'shortcut' 'C' 2 [369] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Copy'" [370] [371] •wself'..mNext' •wi 'Create' 'Menu' [372] •wi 'caption' 'Find &next hit' [373] •wi 'shortcut' 114 0 ¦ 114=F3 [374] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'redFind' 1" [375] [376] •wself'..mPrev' •wi 'Create' 'Menu' [377] •wi 'caption' 'Find &previous hit' [378] •wi 'shortcut' 114 1 [379] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'redFind' ý1" [380] [381] •wself':mView' •wi 'Create' 'Menu' [382] •wi 'caption' '&View' [383] [384] •wself'.mLib' •wi 'Create' 'Menu' [385] •wi 'caption' 'Sort list by &Library Number' [386] •wi 'shortcut' 'L' 2 [387] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 2" [388] [389] •wself'..mWsid' •wi 'Create' 'Menu' [390] •wi 'caption' 'Sort list by &Workspace Name' [391] •wi 'shortcut' 'W' 2 [392] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 3" [393] [394] •wself'..mClass' •wi 'Create' 'Menu' [395] •wi 'caption' 'Sort list by Clas&s' [396] •wi 'shortcut' 'S' 2 [397] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 4" [398] [399] •wself'..mName' •wi 'Create' 'Menu' [400] •wi 'caption' 'Sort list by &Name' [401] •wi 'shortcut' 'N' 2 [402] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 5" [403] [404] •wself'..mHits' •wi 'Create' 'Menu' [405] •wi 'caption' 'Sort list by &Hits' [406] •wi 'shortcut' 'H' 2 [407] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' 6" [408] [409] •wself'..mSep' •wi 'Create' 'Menu' [410] •wi 'separator' 1 [411] [412] •wself'..mVisible' •wi 'Create' 'Menu' [413] •wi 'caption' '&Visible list' [414] •wi 'style' 1 [415] •wi 'value' 1 [416] •wi 'shortcut' 'V' 2 [417] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'Resize'" [418] [419] •wself':mActions' •wi 'Create' 'Menu' [420] •wi 'caption' '&Actions' [421] [422] •wself'.mCopy' •wi 'Create' 'Menu' [423] •wi 'caption' ')COPY selected Listview items into active ws' [424] ¦•wi 'shortcut' 'L' 2 [425] •wi 'onClick' "•wi 'Event' 'CMDSUPERSEEK ý1' 'QuadCOPY'" [426] [427] •wself':st' •wi 'Create' 'Status' [428] •wi 'status' (1 4û1 '' 0 8) [429] [430] ¦ 4-col matrix [431] ¦ col 1: pane number, negative if an overlay pane [432] ¦ cols 2,3: 1 text show that text [433] ¦ 0 text don't show, but use width of text [434] ¦ text 33 show text; 33 is mimimum width (more if reqd) [435] ¦ text text2 ditto; use width of text2 as minimum [436] ¦ col 4: border: 0=no 1=inset 2=outset 8=expand 16=caps 32=num 64=scr [437] t0 4û [438] ttž 1 0 ' Searching 99999 workspaces... ' 1 [439] ttž 2 0 ' 999999999 XXXXXXXX ' 1 [440] ¦ttž 3 0 ' 99999 functions, 99999 variables ' 1 [441] ttž 3 0 ' 9999 hits on 9999 lines in 9999 fns/vars ' 1 [442] ttž 4 '' 25 1 ¦ progress bar [443] •wi 'status' t [444] [445] z,•wi 'PaneWhere' 4 [446] [447] Assert ~ý1îz ¦ else Form width is not wide enough to show pane 4 [448] [449] •wself'.pb' •wi 'Create' 'Progress' ¦ note child of Status [450] •wi 'style' 1 ¦ 1=smooth [451] •wi 'where' z [452] [453] •wself':bn' •wi 'Create' 'Button' 'Hide' [454] •wi 'style' 2 ¦ 2=cancel [455] •wi 'onClick' "':' •wi '‘stop' 1" ¦ handle Esc during search [456] [457] z':' •wi 'size' [458] [459] •wself':lv' •wi 'Create' 'Listview' [460] •wi 'style' 1 2 4 4096 ¦ 8=no multiple selections 128=no header 4096=grid [461] •wi 'where' (0,0,z[1],50) ¦ wide enough so no horiz scroll bar, else 'size' misleading [462] [463] •wi 'scale' 3 ¦ font size will be specified in points [464] [465] ¦ Get value of key k; if undefined, write default to the ini file [466] k•fx [2]( [2] •cr 'II'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ II [467] [468] t 'FontName' II 'APLFONT' [469] tt,•FI 'FontSize' II '11' [470] tt,•FI 'FontStyle' II '0' [471] tt, 'FontCharset' II 'default' [472] •wi 'font' t [473] [474] •wi 'scale' 1 [475] [476] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [477] [478] c0 3û0 [479] ccž'Fake' 0 'left' ¦ first col must be left justified [480] :if oE [481] ccž'Dir' 14 'left' [482] :else [483] ccž'Lib' 4 'right' [484] :end [485] ccž'Wsid' 10 'left' [486] ccž'C' 2 'left' [487] ccž'Name' 12 'left' [488] ccž'H' 3 'right' ¦ Hits [489] ccž'Fake' 0 'right' ¦ because of behavior of 'AutoFit' 'header' 'all' [490] [491] •wi 'list' (0,1,100 1û'x') ¦ force vertical scrollbar [492] [493] •wi 'columndisplay' c [494] [495] d•wi 'size' [496] d[2]+/c[;2] ¦ inner width [497] •wi 'size' d [498] [499] w4•wi 'where' ¦ outer width [500] [501] •wi 'list' (0 3û0 1 '') ¦ remove fake rows that forced vertical scrollbar [502] [503] •wself':red' •wi 'Create' 'RichEdit' [504] •wi 'style' 4 16 64 4096 16384 32768 ¦ 4=multi-line 16=V SB 64=H SB 2048=APL 4096=read-only [505] ¦ 16384 else entire text selected when you select the Form [506] ¦ 32768 disable automatic word selection when highlighting with mouse [507] [508] •wi 'where' (0,w,z[1],z[2]-w) [509] [510] HW•wi 'hwnd' [511] [512] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [513] •wi 'selection' 0 ý1 ¦ select all [514] •wi 'scale' 3 ¦ points [515] [516] t 'UFontName' II 'APLNext' [517] tt,•FI 'UFontSize' II '11' [518] tt,•FI 'UFontStyle' II '0' [519] tt, 'UFontCharset' II 'default' [520] •wi 'selfont' t [521] [522] ¦  Necessary because default is bold (huh?) [523] •wi 'selstyle' (0 0 0 0 0) ¦ bold, italic, underline, strikeout, protected [524] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection [525] [526] 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 [527] 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 [528] ¦ 183=U00B7 : Middle dot, for untranslatable chars [529] [530] ¦ Streamlined version of ìAV2U [531] t 'UAU A;N' [532] tt, 'UA2[A1âA]' [533] tt, ':if 82†•DR A' [534] tt, ' N,0=•TYPE A' [535] tt, ' (N/,U)N/,A' [536] tt, ':end' [537] tt, 'U•FIRST 323 163 82 •DR U' [538] k•fx [2] t ¦õ AU A1 A2 [539] [540] ¦ Streamlined version of ìSetSelTextU [541] k•fx [2] 'ST A;K;U' 'UAU A' "K•wcall 'EM_SetTextEx' HW ('ST_SELECTION' 1200) (U,2û•tcnul)" ¦õ ST AU HW [542] [543] t' ]SuperSeek ',X [544] [545] ¦ tt,•tcnl,50û9472 ¦ U2500 : Unicode horizontal line [546] ¦ tt,•tcnl,'Test difficult characters:' [547] ¦ tt,•tcnl,'Execute õ' [548] ¦ tt,•tcnl,' Match ð' [549] ¦ tt,•tcnl,' Zilde ' [550] ¦ tt,•tcnl,' Domino ˜' [551] [552] tt,•tcnl [553] ST t [554] [555] •wi 'selection' (0,ý1+ût) ¦ offset, length [556] •wi 'selcolor' (0 196 0) [557] •wi 'selstyle' (1 0 0 0 0) ¦ bold [558] •wi 'selection' ý1 ¦ select none; cursor to end [559] [560] ¦ Pre-build a CHARFORMAT2 structure that sets background color [561] CF8484 ¦ cbSize [562] CF[8]4 ¦ dwMask CFM_BACKCOLOR [563] CF[65 66 67]255 255 0 ¦ yellow [564] CFAV CF [565] [566] •wself':' [567] [568] •wi 'Show' [569] e'CMDSUPERSEEK ý1' [570] •wi 'onResize' e [571] •wi 'onClose' e [572] [573] ':lv' •wi 'Focus' ¦ necessary to make Esc work during search (why?) [574] [575] X0 ¦ count hits [576] E0 ¦ count lines with hits [577] U0 ¦ count functions with hits [578] p0 5û' ' '' 0 0  ¦ class, name, # hits, pointer to fn in RichEdit, line numbers with hits [579] m0 2û ¦ all hits (start, length) in RichEdit [580] [581] •wself':red' [582] [583] ¦ ----- Loop through libraries to find wss ----- [584] [585] Q0û '' ¦ queue of wss to search [586] [587] :if oE ¦ entire drive? [588] [589] ':st' •wi 'SetStatus' 1 (' Scanning for workspaces ... ') [590] [591] W•LIB 1oL [592] W(Wú.='\')ëW ¦ only subdirectories [593] n•first ûW ¦ how many top level dirs [594] [595] ':st.pb' •wi 'value' 0 n 1 0 ¦ wraps around [596] [597] :while ’ûoL [598] [599] L1oL ¦ next directory [600] oL1oL [601] [602] :if 2=+/L='\' ¦ top level dirs [603] ':st' •wi 'SetStatus' 2 (' ',ý1L) [604] ':st.pb' •wi 'Stepit' [605] :end [606] [607] •wgive 0 [608] [609] :if ':' •wi '‘stop' [610] :leave [611] :end [612] [613] WDMIFERR '•WSLIB L' ¦õ •WSLIB L ¦ try to get workspace names [614] :if 1=ûûW ¦ error if no such lib [615] •'*** ',W,': •WSLIB ',L [616] :continue [617] :end [618] [619] W(~ú/'.BAK 'W,' ')ëW ¦ don't search backup wss [620] [621] QQ,( L),DTB [2]W [622] [623] WDMIFERR '•LIB L' [624] :if 1=ûûW ¦ error? [625] •'*** ',W,': •LIB ',L [626] :continue [627] :end [628] W(Wú.='\')ëW ¦ only subdirectories [629] W( L),DTB [2]W ¦ append to directory [630] oLW,oL ¦ add to front of queue [631] [632] :end [633] [634] :else ¦ normal library scan [635] [636] :for L :in oL ¦ next library [637] [638] •wgive 0 [639] [640] :if ':' •wi '‘stop' [641] :leave [642] :end [643] [644] WDMIFERR '•WSLIB L' ¦õ •WSLIB L ¦ try to get workspace names [645] :if 1=ûûW ¦ error if no such lib [646] •'*** ',W,': ',ôL [647] :continue [648] :end [649] [650] W(~ú/'.BAK 'W,' ')ëW ¦ don't search backup wss [651] [652] QQ,DLTB [2]W [653] [654] :end [655] [656] :end [657] [658] n•first ûQ [659] ':st' •wi 'SetStatus' 1 (' Searching ',(ôn),' workspaces... ') [660] [661] ':st.pb' •wi 'value' 0 (1n) 1 0 ¦ 1 to avoid •WI DOMAIN ERROR when N=0 [662] [663] ¦ ----- Start server ----- [664] [665] wse'wseSuperSeek' •wi 'Create' 'APLW.WSEngine' ('xVisible' 0) [666] kwse •wi 'XExec' ("•CHDIR '",(•chdir ''),"'") [667] [668] ¦ ----- Loop through wss ----- [669] [670] nW0 ¦ wss searched [671] fW0 ¦ found in wss [672] [673] :FOR WS :in Q [674] [675] ¦ In case of INTERNAL WS REPRESENTATION IS NEWER THAN THIS INTERP warning, show this now [676] ':st' •wi 'SetStatus' 2 WS [677] ':st' •wi 'SetStatus' 3 '' [678] [679] •wgive 0 [680] [681] :if ':' •wi '‘stop' ¦ FIXME check this at every fn/var? [682] s1•wi 'selection' [683] t'Interrupt',•tcnl [684] ST t [685] •wi 'selection' (s,ût) ¦ offset, length [686] •wi 'selcolor' (255 0 0) [687] •wi 'selstyle' (1 0 0 0 0) ¦ bold [688] •wi 'selection' ý1 ¦ select none; cursor to end [689] :leave [690] :end [691] [692] uf1 ¦ show file name heading on first hit [693] [694] :if oE [695] i(è<\èWS='\')â1 [696] :else [697] iWSâ' ' [698] :end [699] ln(i-1)ûWS ¦ library number [700] wsiWS ¦ wsid [701] [702] kwse •wi 'XExec' ')CLEAR' [703] kwse •wi 'XExec' (')XLOAD ',WS) [704] kwse •wi 'XExec' ')RESET' [705] rwse •wi 'XExec' '•WSID' [706] :if rð'' ¦ in a clear ws, •WSIDð'' [707] ¦ RUNTIME WS SERIALIZATION MISMATCH ? [708] •'*** Failed: )XLOAD ',WS [709] :continue [710] :end [711] wDEB r ¦ APL's way of saying wsid [712] [713] Mwse •wi 'XExec' '•NL 2 3' ¦! a character matrix comes back as a nested vector!!! [714] Assert 1=ûûM [715] MM~' ' ¦ DTB [716] Cwse •wi 'XExec' '•NC •NL 2 3' ¦ 2=var 3=fn [717] Assert 1=ûûC [718] Assert ^/Cî2 3 ¦ since we cleared stack, cannot be labels [719] [720] MM,'•ALX' '•ELX' '•LX' ¦ interesting system vars [721] CC, 2 2 2 [722] [723] C':ì'[C] [724] [725] bCîoF/'ì' ¦ fns/vars filter [726] Cb/C [727] Mb/M [728] [729] ':st' •wi 'SetStatus' 3 (' ',(ô+/C='ì'),' functions, ',(ô+/C=''),' variables ') [730] [731] ¦ ----- Loop through fns/vars ----- [732] [733] :for i :in âûM [734] [735] NiM ¦ object name [736] [737] y'ì'=iC ¦ is it a function? ¦ note •NC says 4 for •LX, but we ony test 3= [738] :if y [739] Vwse •wi 'XExec' ("•VR '",N,"'") [740] :if 0=ûV ¦ locked or •NA ? [741] :continue [742] :end [743] V[1 2]'[]' ¦ kludge for FILT [744] :else [745] :try [746] V'unwrapl' •DR wse •wi 'XExec' ("'wrapl' •DR ",N) [747] :catchall [748] ¦ FANFILE ws has screwed up variable A with 0=ûûA but ðûA which makes unwrapl fail [749] •'*** ',((^\•DM†•TCNL)/•DM),' retrieving variable <',N,'> from ws ',WS [750] :continue [751] :end [752] ¦ RHS 3/03/07 Let's try this, for speed [753] :if 82†•DR V [754] :continue [755] :end [756] VSEEKFMT V [757] :if 0=ûV [758] :continue [759] :end [760] :end [761] [762] LUP V [763] [764] ¦ Search •VR [765] [766] HL •SS A ¦ the heart of the matter [767] [768] :if D=1 ¦ single target? [769] :andif ~1îH ¦ no raw hits? [770] :continue ¦ next function [771] :end [772] [773] ¦ Syntactic filter [774] [775] HA SYN H ¦õ V a q [776] [777] :if D=1 ¦ single target? [778] :andif ~1îH ¦ no more hits? [779] :continue ¦ next function [780] :end [781] [782] ¦ Filter for APL / quoted strings / comments [783] [784] ¦P1,ý1V •SS •TCNL,'[' ¦ partition on "[" (with trailing CRs); force header line [785] ¦  This doesn't work with my variable formatting stuff, like '(2)[13;] ...' [786] ¦ And besides, you're not allowed to have CRs embedded in functions any more [787] P1,ý1V •SS •TCNL ¦ partition on "[" (with trailing CRs); force header line [788] ¦ •SS is still faster than plain = ! [789] ¦P[ý5+ûV]1 ¦ force end of last line [790] ¦ The last 7 characters of a •VR are: •TCNL,' ì',•TCNL [791] ¦ P[ý5+ûV]1 above flags ....................  this blank [792] ¦ No, now that's not necessary at all, now that we match •TCNL rather than •TCNL,'[' [793] [794] IFILT ¦õ P V ANDSCAN [795] HH^I [796] [797] :if D=1 ¦ single target? [798] :andif ~1îH ¦ no more hits? [799] :continue ¦ next function [800] :end [801] [802] R(ûV)û0 [803] R[(H/âûH)ø.+ý1+âûA]1 ¦ flag chars to highlight [804] [805] hP ORRED H ¦ shift hits to leading "[" [806] [807] :if D>1 ¦ multiple targets [808] [809] ¦ We have already done the last target; now step through the others [810] ¦ Note that they are in reverse order so functions work like APL [811] [812] ¦ /t1/ú/t2/ don't stop and display after first hit -- we want to show them all [813] ¦ /t1/&~/t2/ it is okay to show "all" hits since we will exclude lines with t2 [814] [815] :if oG ¦ "@" global option? [816] tú/h [817] :for J :in 1âD [818] WL •SS JG ¦ raw search [819] W(JG) SYN W ¦ SYN [820] WW^I ¦ FILT [821] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [822] HHúW ¦ all hits [823] WP ORRED W ¦ shift hits to leading "[" [824] hWúh ¦ lines to show [825] tõ'(ú/W)',(JS),'t' ¦ apply function [826] :end [827] :if ~t ¦ no hits? [828] :continue ¦ next function [829] :end [830] :else [831] :for J :in 1âD [832] WL •SS JG ¦ raw search [833] W(JG) SYN W ¦ SYN [834] WW^I ¦ FILT [835] R[(W/âûW)ø.+ý1+âûJG]1 ¦ flag chars to highlight [836] HHúW ¦ all hits [837] WP ORRED W ¦ shift hits to leading "[" [838] hõ'W',(JS),'h' ¦ apply function [839] :end [840] :if ~1îh ¦ no more hits? [841] :continue ¦ next function [842] :end [843] :end [844] [845] ¦ Only count hits on lines that will be displayed [846] ¦ (When searching for /1/^/2/ don't count 2s on lines without 1) [847] [848] Hh/P PLUSRED H [849] [850] :end [851] [852] ¦ Got some hits [853] [854] :if uf [855] fWfW+1 ¦ found in wss [856] uf0 [857] e9552 ¦ 9552=U2550 : Double horizontal line [858] t(5ûe),' WSID: ',WS,' ' [859] tt,((570-ût)ûe),•tcnl [860] ST t [861] [862] n•first ût ¦ length of line [863] s1•wi 'selection' [864] ss-n ¦ back up to beginning of line [865] •wi 'selection' s (n-1) ¦ offset, length [866] [867] ¦ Mark thinks this is too colorful [868] jCF [869] j[65 66 67]AV 196 255 255 ¦ pale cyan [870] k•wcall 'EM_SETCHARFORMAT' HW 1 j ¦ SCF_SELECTION=1 ¦ background [871] [872] •wi 'selection' ((s+12),ûWS) ¦ just the file name [873] •wi 'selstyle' (1 0 0 0 0) ¦ bold [874] [875] •wi 'selection' ý1 ¦ select none; cursor to end [876] :end [877] [878] [879] x+/H ¦ total hits in this fn [880] t':lv' •wi 'AddRows' 0 1 '' ln ws (,'ì'[1+y]) N (ôx) WS [881] k':lv' •wi 'EnsureVisible' t [882] [883] XX+x ¦ accumulate total hits [884] Hh ¦ lines with hits [885] EE++/H ¦ accumulate lines with hits [886] UU+1 ¦ accumulate functions with hits [887] [888] ¦ Display hits [889] [890] HH/âûH ¦ line numbers to display (origin 1) [891] WûH ¦ number of lines with hits [892] PP/âûP ¦ partition starts [893] L(1P,1+ûV)-P ¦ partition lengths [894] :if oX ¦ expanded context? [895] :if y [896] eâûP ¦ all line numbers (including the trailing ì line) [897] :else [898] eâý1+ûP ¦ all line numbers (the last line of variables is bogus) [899] :end [900] H(eîHø.+ý1 0 1)/e ¦ this takes care of dups and edges [901] IH>1+ý1èH ¦ flag beginnings of groups of lines [902] :else [903] I(ûH)û0 [904] :end [905] PP[H]-1 ¦ compensate for +â with •IO1 [906] LL[H] ¦ lengths, incl trailing CRs [907] [908] ppž ('ì'[1+y]) N x (1•wi 'selection') H ¦ class name #hits position lines [909] [910] e5û9472 ¦ 9472=U2500 : Horizontal line [911] ¦  5 positions the fn name where it is in the header line (of a niladic fn) [912] te,' ',N,' (',(ôx),' hit',(x=1)'s',((x†W)/' on ',(ôW),(-W=1)' lines'),') ' [913] tt,((70-ût)ûe),•tcnl [914] ST t [915] n•first ût ¦ length of line [916] s1•wi 'selection' [917] ss-n ¦ back up to beginning of line [918] k•wcall 'EM_HideSelection' HW 1 0 ¦ hide selection [919] •wi 'selection' s (n-1) ¦ offset, length [920] :if y [921] V[1 2]' ' ¦ undo kludge for FILT [922] •wi 'selcolor' (0 0 255) ¦ blue fns [923] :else [924] •wi 'selcolor' (255 0 255) ¦ purple vars [925] :end [926] •wi 'selection' (6+s) (•first ûN) ¦ just the function name [927] •wi 'selstyle' (1 0 0 0 0) ¦ bold [928] •wi 'selection' ý1 ¦ select none; cursor to end [929] •wi 'Paint' ¦ show bolded fn name while hits display [930] [931] :for B :in âûH [932] :if I[B] [933] ST (3û183),•TCNL ¦ 183=U00B7 : Middle dot [934] :end [935] nL[B] [936] jP[B]+ân ¦ indices of line in •VR [937] ST V[j] [938] s(1•wi 'selection')-n+1 [939] c(R[j]) Partition ân ¦ groups of chars to highlight [940] :for j :in c [941] e(s+1j),ûj ¦ offset, length [942] mmže ¦ all hits [943] •wi 'selection' e ¦ offset, length [944] ¦•wi 'selcolor' (255 0 255) ¦ purple [945] ¦•wi 'selstyle' (1 0 0 0 0) ¦ bold [946] k•wcall 'EM_SETCHARFORMAT' HW 1 CF ¦ SCF_SELECTION=1 ¦ yellow background [947] :end [948] •wi 'selection' ý1 ¦ select none; cursor to end [949] :end [950] k•wcall 'EM_HideSelection' HW 0 0 ¦ show selection ¦ else :red does not scroll down [951] •WGIVE 0 ¦ listview does not display without this [952] ¦k•dl 0.1 [953] [954] :end ¦ next function [955] [956] ':st.pb' •wi 'Stepit' [957] [958] nWnW+1 ¦ wss searched [959] [960] :END ¦ next ws [961] [962] ':st' •wi 'SetStatus' 1 (' Searched ',(ônW),' workspaces ') [963] ':st' •wi 'SetStatus' 2 (' Found in ',(ôfW),' wss ') [964] [965] ':bn' •wi 'onClick' '' ¦ let style 2 take over [966] [967] :if U=0 [968] [969] s1•wi 'selection' [970] [971] t'Not found',•tcnl [972] ST t [973] [974] •wi 'selection' (s,ý1+ût) ¦ offset, length [975] •wi 'selcolor' (255 0 0) [976] •wi 'selstyle' (1 0 0 0 0) ¦ bold [977] •wi 'selection' 0 0 ¦ cursor to top [978] [979] L1 [980] [981] :end [982] [983] ppž ' ' '' 0 (1•wi 'selection')  ¦ fake row so we know position of end of text [984] [985] •wi 'selection' 0 0 ¦ cursor to top [986] [987] •wself':lv' [988] [989] •wi 'noredraw' 1 [990] [991] •wi 'AutoFit' 'header' (2 3 4 5 6) [992] [993] c•wi 'columndisplay' [994] cý1 0c ¦ delete Fake column [995] •wi 'columndisplay' c [996] [997] •wi 'highlightfocus' 1 [998] •wi 'value' 1 [999] k•wi 'EnsureVisible' 1 [1000] [1001] s•wi 'size' [1002] s[2]+/c[;2] ¦ inner width [1003] •wi 'size' s [1004] [1005] w•wi 'where' [1006] z':' •wi 'size' [1007] w[3]z[1] ¦ outer height [1008] •wi 'where' w [1009] [1010] •wi 'noredraw' 0 [1011] [1012] d':red' •wi 'where' [1013] d[2]w[4] [1014] d[4]z[2]-w[4] [1015] ':red' •wi 'where' d [1016] [1017] •wi 'Focus' [1018] [1019] •wi '‘p' p [1020] [1021] e'CMDSUPERSEEK ý1' [1022] [1023] ¦  Sadly, when you click a different row in the list, both these events fire [1024] •wi 'onClick' e [1025] •wi 'onSelect' e [1026] [1027] •wi 'onColClick' e [1028] [1029] •wi 'keys' 13 ¦ 13=Enter [1030] •wi 'onKeyPress' e [1031] •wi 'onDblClick' e [1032] [1033] •wself':red' [1034] [1035] •wi '‘m' m [1036] [1037] •wi 'keys' 13 ¦ 13=Enter [1038] •wi 'onKeyPress' e [1039] •wi 'onMouseDouble' e ¦ sadly, there is no onDblClick [1040] [1041] L1: [1042] [1043] •wself':st' [1044] [1045] '.pb' •wi 'Delete' [1046] [1047] t(2æoF)'variables' 'functions' 'fns/vars' [1048] t' ',(ôX),' hits on ',(ôE),' lines in ',(ôU),' ',t,' ' [1049] •wi 'SetStatus' 3 t [1050] [1051] v•ai[2]-v [1052] t(0 1ôv),' seconds elapsed' ¦ note free leading blank [1053] •wi 'SetStatus' 4 t [1054] [1055] •wself':' [1056] [1057] k•wi 'Wait' [1058] [1059] 0 [1060] [1061] ¦ ============================================================================= [1062] [1063] L9: [1064] [1065] ¦ ••wself •wevent •warg '(' ('#' •wi 'focus') ')' ¦ debug [1066] [1067] :SELECT •wevent [1068] [1069] :CASELIST 'Click' 'Select' [1070] [1071] ¦ If you click on a new row, you get Click,Select [1072] ¦ If you click on the same row, you get just Click [1073] ¦ If you use keyboard, you get just Select [1074] [1075] i•first •wi 'value' [1076] (i=0)û0 ¦ click in blank row? [1077] [1078] :if •weventð'Click' [1079] •wi '‘skipnextselect' i [1080] :else [1081] Assert •weventð'Select' [1082] :if i=•wi '‘skipnextselect' [1083] •wi '‘skipnextselect' 0 [1084] 0 [1085] :end [1086] :end [1087] [1088] p•wi '‘p' [1089] (c N k s k)p[i;] ¦ class, name, hits, beginning of line, line numbers [1090] ss+6 ¦ advance past '----- ' [1091] n•first ûN [1092] [1093] •wself':red' [1094] [1095] •wi 'selection' s n [1096] [1097] ¦ Scroll into view on RichEdit control [1098] [1099] e1+•wi 'CharToLine' s ¦ line number of first line [1100] t1+•wi 'CharToLine' (p[i+1;4]-1) ¦ line number of last line [1101] g•wi 'range' [1102] g(g[1]-1)+âg[2] ¦ lines now visible [1103] :if 0î(e,t)îg ¦ if the whole fn is already visible, don't change range [1104] •wi 'range' e [1105] :end [1106] [1107] :CASE 'DblClick' [1108] [1109] i1•warg [1110] (i=0)û0 ¦ click in blank row? [1111] •wi 'Event' 'CMDSUPERSEEK ý1' 'Peek' i [1112] [1113] :CASE 'MouseDouble' [1114] [1115] ¦ Second mouseup has not occurred yet, so we have to wait [1116] [1117] ¦ Pass mouse position before Windows does "word" select, which could change selection offset [1118] [1119] •wi 'Defer' 'CMDSUPERSEEK ý1' 'KeyPress' (•wi 'selection') [1120] [1121] :CASE 'KeyPress' [1122] [1123] ¦ note, for both classes: •wi 'keys' 13 ¦ 13=Enter [1124] [1125] :if 'Listview'ð•wi 'class' [1126] [1127] i•first •wi 'value' [1128] (i=0)û0 ¦ click in blank row? [1129] •wi 'Event' 'CMDSUPERSEEK ý1' 'Peek' i [1130] [1131] :else [1132] [1133] Assert 'RichEdit'ð•wi 'class' [1134] [1135] ¦ This could be from Enter key or from MouseDouble [1136] :if •wargð13 [1137] s•first •wi 'selection' [1138] :else [1139] Assert 2=û,•warg [1140] s•first •warg [1141] :end [1142] •wi 'selection' s 0 ¦ cancel word-selection [1143] ¦  Sadly, Windows may have changed the offset to the beginning of a "word" [1144] p':lv' •wi '‘p' ¦ name, hits, beginning of line, line numbers [1145] n1ûp [1146] (s=p[n;4])û0 ¦ beyond end? [1147] i+/sòp[;4] [1148] (c N k g n)p[i;] [1149] e1+•wi 'CharToLine' g ¦ divider line [1150] d1+•wi 'CharToLine' s ¦ clicked line [1151] :if e=d [1152] j0 [1153] :else [1154] jd-e [1155] (j>ûn)û0 ¦ on Interrupt message [1156] jý1+n[j] ¦ ý1+ because we recorded line numbers in origin 1 [1157] :end [1158] [1159] •wi 'Event' 'CMDSUPERSEEK ý1' 'Peek' (i j) [1160] [1161] :end [1162] [1163] :CASE 'Peek' [1164] [1165] ¦ caller does: •wi 'Event' 'CMDSUPERSEEK ý1' 'Peek' (i j) [1166] [1167] (i j)2•warg ¦ listview rowid, function line number [1168] [1169] (C N WS),':lv' •wi 'GetCells' i (4 5 7) ¦ class, name, full wsid [1170] [1171] •wself'wseSuperSeek' [1172] [1173] k•wi 'XExec' (')XLOAD ',WS) [1174] k•wi 'XExec' ')RESET' [1175] r•wi 'XExec' '•WSID' [1176] Assert ~rð'' ¦ in a clear ws, •WSIDð'' ¦ this )XLOAD worked once before, so it should work again... [1177] [1178] :if C='ì' ¦ function? [1179] x•wi 'XExec' ("•VR '",N,"'") [1180] Assert 0†ûx ¦ should not be locked or •NA else how did it get in list? [1181] :else [1182] x'unwrapl' •DR •wi 'XExec' ("'wrapl' •DR ",N) [1183] :end [1184] [1185] EN,(j†0)/'[',(ôj),']' [1186] [1187] :if C='' ¦ variable [1188] :if (ðx)>1 [1189] :orif (ûûx)>2 [1190] :orif ^/0 ' 'î•TYPE •enlist x [1191] x•UCMD 'DISPLAY x' ¦ I guess this is better than an error from )edit [1192] :end [1193] k "p ",N ¦! we cannot peek at anything named p [1194] kk, "k•WCALL 'W_Edit' (,'",E,"')" ¦õ k ¦ W_Edit fails if arg is scalar [1195] k•DEF [2] k ¦õ p [1196] p x [1197] :else [1198] k "p x;",N ¦! we cannot peek at anything named p or x or k [1199] kk, "k•DEF x" ¦õ k x [1200] kk, "k•WCALL 'W_Edit' (,'",E,"')" ¦õ k ¦ W_Edit fails if arg is scalar [1201] k•DEF [2] k ¦õ p [1202] p x [1203] :end [1204] [1205] :CASE 'QuadCOPY' [1206] [1207] •wself':lv' [1208] v•wi 'value' ¦ selected rowids [1209] Assert ’ûv [1210] Assert ~0îv [1211] M•wi 'GetCells' v (5 7) ¦ name, full wsid [1212] mM[;1] [1213] dý1ú.†ý1[2] •idloc [2] m ¦ shadowed? [1214] :if ú/d [1215] •'*** Shadowed:',ôd/m [1216] M(~d)ëM [1217] :end [1218] ¦ Should group by wsid, but it's easier to just do one at at time... [1219] :for i :in â1ûM [1220] (m w)M[i;] [1221] •' )COPY ',w,' ',m [1222] rm •COPY w [1223] Assert (,1)ðûr [1224] :select •first r [1225] :case 1  •'Function copied' [1226] :case 2  •'Variable copied' [1227] :case 0  •'*** •COPY failed: Object not found' [1228] :case 127  •'*** •COPY failed: Duplicate name in objlist ¦ should not get here!' [1229] :case ý2  •'*** •COPY failed: Object too large for available space' [1230] :case ý3  •'*** •COPY failed: Name defined as a label; cannot be changed' [1231] :case ý4  •'*** •COPY failed: Insufficient space in symbol table and workspace too full to expand symbol table' [1232] :case ý6  •'*** •COPY failed: Insufficient free space to carry out command' [1233] :else  ö0 [1234] :end [1235] :end [1236] [1237] :CASE 'ColClick' [1238] [1239] c1•warg [1240] •wi 'Event' 'CMDSUPERSEEK ý1' 'Sort' c [1241] [1242] :CASE 'Sort' [1243] [1244] c•warg [1245] •wself':lv' [1246] d•wi 'sortorder' [1247] p,•wi 'GetCells' d c [1248] [1249] :if cî3 4 5 ¦ Wsid, Class, Name [1250] p[2]p [1251] wd[•AVp] ¦ new order [1252] :if dðw ¦ already sorted? [1253] wd[•AVp] [1254] :end [1255] :elseif cî2 6 ¦ Lib, Hits [1256] p•FIôp [1257] wd[p] [1258] :if dðw [1259] wd[p] [1260] :end [1261] :else [1262] ö'Tilt' [1263] :end [1264] [1265] •wi 'sortorder' w ¦ this triggers a Select [1266] [1267] i•first •wi 'value' [1268] •wi '‘skipnextselect' i [1269] [1270] :CASE 'redFind' [1271] [1272] •wself':red' [1273] s•first •wi 'selection' [1274] m•wi '‘m' ¦ offsets, lengths [1275] :if •warg=1 ¦ 1=next ý1=prev [1276] i(m[;1]>s)â1 [1277] :if i>1ûm  i1  :end [1278] :else [1279] iý1+(m[;1]0)^(nd=0) ¦ all library numbers? [313] ccž'Lib' 8 'right' ¦ 2 [314] :elseif (nl=0)^(nd>0) ¦ all directories? [315] ccž'Dir' 16 'left' ¦ 2 [316] :else [317] ccž'Lib/Dir' 16 'left' ¦ 2 [318] :end [319] ccž'WSID' (W’16) 'left' ¦ 3 [320] ccž'UFile' (U’16) 'left' ¦ 4 [321] ccž'C' 2.5 'center' ¦ 5 [322] ccž'Name' 16 'left' ¦ 6 [323] [324] ccž'Timestamp' (T’20) 'right' ¦ 7 ¦ rjust in case of '-' [325] ccž'Bytes' (B’8) 'right' ¦ 8 [326] ccž'ð' 2.5 'right' ¦ 9 [327] ccž'Shape' 8 'right' ¦ 10 [328] ccž'Value' 32 'left' ¦ 11 [329] [330] ¦ Get value of key k; if undefined, write default to the ini file [331] k•fx [2]( [2] •cr 'I'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ I [332] [333] •wself':lv' •wi 'New' 'Listview' [334] •wi 'where' 0.5 1 ¦ this establishes gaps [335] •wi 'style' 1 2 4 1024 4096 ¦ 1024=reorder cols 4096=gridlines [336] •wi 'columndisplay' c [337] [338] ¦ •wi 'font' 'APLFONT' 11 0 'default' [339] f 'FontName' I 'APLFONT' [340] ff,•FI 'FontSize' I '11' [341] ff,•FI 'FontStyle' I '0' [342] ff, 'FontCharset' I 'default' [343] •wi 'scale' 3 ¦ font size will be specified in points [344] •wi 'font' f [345] [346] •wi 'onColClick' e ¦ sort [347] •wi 'onDblClick' e ¦ peek [348] •wi 'onKeyPress' e ¦ Enterpeek [349] •wi 'onClick' e ¦ select [350] [351] •wi 'AutoFit' 'header' ((T/7),(B/8),9 10) [352] [353] •wself':l1' •wi 'New' 'Label' [354] •wi 'caption' '' [355] h1 1•wi 'Draw' ('?Text' 'AB') ¦ perhaps 0.8 [356] •wi 'size' h 10 [357] [358] •wself':l2' •wi 'New' 'Label' [359] •wi 'caption' '' [360] [361] hö•first '#' •wi 'units' ¦ pixel height, in chars [362] h1.2524’h ¦ button height [363] [364] •wself':bnExit' •wi 'New' 'Button' [365] •wi 'caption' 'Stop' [366] •wi 'size' h 8 [367] •wi 'style' 2 ¦ 2=cancel [368] •wi 'onClick' "':' •wi '‘stop' 1" [369] [370] •wself':bnAll' •wi 'New' 'Button' [371] •wi 'caption' '&Get All Info' [372] •wi 'size' h 8 [373] •wi 'onClick' " CMDSYMFIND 'GetAll'" [374] [375] •wself':' [376] [377] •wi 'onResize' e [378] 0 CMDSYMFIND 'Resize' [379] k•wi 'Show' [380] [381] ':bnExit' •wi 'Focus' ¦ so you can hit Enter or Esc to interrupt [382] [383] •wself':lv' [384] [385] ¦ ----- Workspaces ----- [386] [387] hw4û0 ¦ count hits [388] LLLL,DD ¦ combine libs and dirs [389] ULLL ¦ save for ufiles [390] LLW/LL ¦ if /W ... [391] [392] :while ’ûLL ¦ next library or directory [393] [394] •wgive 0 [395] [396] :if ':' •wi '‘stop' [397] :leave [398] :end [399] [400] L1LL ¦ pop next ... [401] LL1LL ¦ ... lib or dir [402] wsDMIFERR '•WSLIB L' ¦ try to get workspace names [403] :if 1=ûûws ¦ error if no such lib/dir [404] ñOUT ws,': ',ôL [405] :continue [406] :end [407] :if 82†•DR L ¦ library number? [408] ws0 11ws ¦ drop library numbers [409] lp•LIBD L ¦ library path [410] ¦lplp,('\'†ý1lp)û'\' ¦ force trailing backslash [411] ¦lplp,'\'~ý1lp ¦ force trailing backslash ¦ thanks, Roy [412] lplp,((ý1lp)î'\:')'\' ¦ force trailing backslash, unless 'D:' [413] pvôL ¦ lib/dir for display [414] pxpv,' ' ¦ wsid prefix [415] :else ¦ directory [416] pv(-'\'=ý1L)L ¦ lib/dir for display (last might be î'\:.') [417] lpL ¦ library path [418] pxL ¦ wsid prefix [419] :if S ¦ subdirectories? [420] ¦b•LIB L ¦ all files [421] ¦ Have gotten several unrepeatable errors from •LIB: [422] ¦ XFHOST ERROR FindFirstFile 1 0 123 The filename, directory name, or volume label syntax is incorrect. [423] bDMIFERR '•LIB L' [424] :if 1=ûûb ¦ error? [425] ñOUT L,' * ',b [426] :continue [427] :end [428] b(bú.='\')ëb ¦ only subdirectories [429] b( L),DTB [2]b ¦ append to directory [430] LLb,LL ¦ add to front of queue [431] :end [432] :end [433] ws(~ú/'.BAK 'ws,' ')ëws ¦ 7/14/07 don't search backup wss [434] nw•first ûws ¦ number of wss [435] hw[1]hw[1]+nw ¦ wss attempted [436] :for i :in ânw ¦ next workspace [437] •wgive 0 [438] :if ':' •wi '‘stop' [439] :leave [440] :end [441] wDTB ws[i;] ¦ workspace [442] lwpx,w ¦ wsid [443] ':l1' •wi 'caption' ('Searching workspace ',(ôhw[2]+1),' ... ',lw) [444] sRDST lp,w,'.w3' ¦ here's the magic: read symbol table [445] :if 1=ûûs ¦ error message? [446] :if ( s)î'RUNTIME WS' 'EMPTY FILE' [447] ¦ don't mention those errors [448] :else [449] ñOUT s,': ',lw [450] :end [451] :continue [452] :end [453] hw[2]hw[2]+1 ¦ wss searched [454] bú/•first ú/N (Up s),' ' [455] bb^ú/sîF ¦ fns/vars filter [456] n+/b [457] :if n>0 [458] hw[3]hw[3]+1 ¦ wss w/ hits [459] hw[4]hw[4]+n ¦ total hits [460] :for j :in b/âûb [461] k•wi 'AddRows' 0 1 '' pv w '' (s[j;1]) (DTB 2s[j;]) [462] :end [463] :end [464] :end ¦ next workspace [465] :end ¦ next library or directory [466] [467] :if W [468] (u w h)hw[2 3 4] [469] q'Found ',(ôh),((-h=1)' matching names'),' in ',(ôw),' of ',(ôu),(-u=1)' workspaces' [470] ':l1' •wi 'caption' q [471] :end [472] [473] ¦ ----- User command files ----- [474] [475] hu4û0 ¦ count hits [476] ¦ LL is now empty [477] ¦ UU may have list of ucmd files [478] :if U ¦ if /U ... [479] :andif 0=ûUU [480] LLUL [481] :end [482] [483] :repeat ¦ while ’ûLL,UU [484] [485] •wgive 0 [486] [487] :if ':' •wi '‘stop' [488] :leave [489] :end [490] [491] :if ’ûUU ¦ first priority: file in queue [492] L1UU ¦ pop next ... [493] UU1UU ¦ ... file [494] ':l2' •wi 'caption' ('Searching file ',(ôhu[2]+1),' ... ',L) [495] sL CMDSYMFIND 'Udir' ¦ read ufile symbol table [496] :if 0=ûûs ¦ not a ufile? [497] :continue [498] :end [499] hu[1]hu[1]+1 ¦ files attempted [500] L(' '=•first L)L ¦ un-kludge [501] :if 1=ûûs ¦ error message? [502] ñOUT L,' * ',s [503] :continue [504] :end [505] hu[2]hu[2]+1 ¦ files searched [506] bú/•first ú/N (Up s),' ' [507] bb^ú/sîF ¦ fns/vars filter [508] n+/b [509] :if n>0 [510] hu[3]hu[3]+1 ¦ files w/ hits [511] hu[4]hu[4]+n ¦ total hits [512] i(è<\èLî' \:')â1 [513] uiL ¦ ufile [514] pv(i-L[i]î'\ ')L ¦ lib/dir for display (last might be î' \:.') [515] :for j :in b/âûb [516] k•wi 'AddRows' 0 1 '' pv '' u (s[j;1]) (DTB 2s[j;]) [517] :end [518] :end [519] [520] :elseif ’ûLL ¦ second priority: lib or dir [521] L1LL ¦ pop next ... [522] LL1LL ¦ ... lib [523] wsDMIFERR '•FLIB L' ¦ try to get file names [524] :if 1=ûûws ¦ error if no such lib/dir [525] ñOUT (ôL),' * ',ws [526] :continue [527] :end [528] B82†•DR L ¦ is this a library number? [529] :if B ¦ lib? [530] UUUU,DLTB [2]ws ¦ add files to queue [531] :else [532] UUUU,( L),DTB [2]ws ¦ add files to queue [533] :end [534] :if S ¦ subdirs? [535] :if B [536] L•LIBD L ¦ library path [537] LL,((ý1L)î'\:')'\' ¦ force trailing backslash, unless 'D:' [538] :end [539] b•LIB L ¦ all files [540] b(bú.='\')ëb ¦ only subdirectories [541] b( L),DTB [2]b ¦ append to directory [542] LLb,LL ¦ add to front of queue [543] :end [544] [545] :else [546] :leave ¦ we're done [547] [548] :end [549] [550] :end [551] [552] :if U [553] (u w h)hu[2 3 4] [554] q'Found ',(ôh),((-h=1)' matching names'),' in ',(ôw),' of ',(ôu),(-u=1)' files' [555] ':l2' •wi 'caption' q [556] :end [557] [558] •wi 'AutoFit' 'header' (2,(W/3),(U/4),5 6 11) [559] [560] •wself':bnExit' [561] •wi 'onClick' '' ¦ this enables the style 2=cancel behavior [562] •wi 'caption' 'E&xit' [563] [564] •wself':' [565] [566] •wi '‘stop' 0 [567] •wi 'pointer' 0 [568] [569] :if ']'î•SI[;1] ¦ user command? [570] k•wi 'Wait' [571] :else [572] k•wi 'Show' [573] :end [574] [575] 0 [576] [577] L9: ¦ ========== Callbacks ========== [578] [579] :SELECT N [580] [581] :CASE 'Remove' [582] [583] •wself':lv' [584] v•wi 'value' ¦ selected row(s) [585] •wi 'DeleteRows' v [586] [587] :CASE 'Only' [588] [589] •wself':lv' [590] a•wi 'sortorder' ¦ all row ids [591] c•first,•wi 'GetCells' a 5 ¦ class [592] v(~cî G)/a [593] •wi 'DeleteRows' v [594] [595] :CASE 'KeyPress' [596] [597] :if •warg=13 ¦ Enter key? [598] 1 CMDSYMFIND 'Peek' [599] :end [600] [601] :CASE 'Peek' [602] [603] ¦ G is 1 for peek, 0 for get info [604] •wself':lv' [605] v•wi 'value' ¦ selected row(s) [606] (0=ûv)û0 ¦ nothing selected [607] :if G [608] i1v ¦ if many selected, just peek at first [609] i G CMDSYMFIND 'PeekRow' [610] :else [611] :if 1=ûv [612] v G CMDSYMFIND 'PeekRow' ¦ one row [613] :else [614] v CMDSYMFIND 'GetRows' ¦ hourglass, etc. [615] :end [616] :end [617] [618] :CASE 'DblClick' [619] [620] r1•warg ¦ rowid [621] r 1 CMDSYMFIND 'PeekRow' [622] [623] :CASE 'All' [624] [625] •wself':lv' [626] a•wi 'sortorder' ¦ all row ids [627] •wi 'value' a [628] [629] :CASE 'None' [630] [631] ':lv' •wi 'value'  [632] [633] :CASE 'Invert' [634] [635] •wself':lv' [636] a•wi 'sortorder' ¦ all row ids [637] v•wi 'value' ¦ selected rowids [638] •wi 'value' (a~v) [639] [640] :CASE 'Resize' [641] [642] ¦ ••wself •wevent (FFA •warg) [643] z•wi 'size' ¦ form size [644] (0îz)û0 ¦ minimized? don't bother doing anything [645] a':l1' •wi 'size' ¦ label size [646] b':bnExit' •wi 'size' ¦ button size [647] hb[1]2’a[1] ¦ height needed [648] [649] •wself':lv' [650] w•wi 'where' [651] w[3 4]z-2’w[1 2] ¦ form size, less top/bottom/left/right gaps [652] w[3]w[3]-h+w[1] ¦ less buttons and another vertical gap [653] •wi 'where' w ¦ move and resize [654] [655] •wself':bnExit' [656] tw[1 2]+w[3 4] ¦ botton right of :lv [657] t[2]t[2]-b[2] ¦ move left [658] vt[1]+w[1] ¦ top gap [659] t[1]v+0.5’h-b[1] ¦ plus half of label height differential [660] •wi 'where' t ¦ just move [661] [662] •wself':bnAll' [663] t[2]t[2]-b[2]+w[2] [664] •wi 'where' t ¦ just move [665] [666] •wself':l1' [667] w[1]v+0.5’h-2’a[1] [668] w[3]a[1] [669] w[4]t[2]-2’w[2] [670] •wi 'where' w [671] [672] •wself':l2' [673] w[1]w[1]+a[1] [674] •wi 'where' w [675] [676] :CASE 'ColClick' [677] [678] c1•warg ¦ column clicked [679] i•wi 'sortorder' ¦ all rowids [680] d,•wi 'GetCells' i c ¦ data [681] :if cò7 ¦ info columns [682] dôd ¦  is in unset cells [683] :end [684] m[2]d ¦ simple char matrix [685] :if c=2 ¦ lib/dir? [686] b1=•first•VId ¦ plain library numbers [687] bb/âûb [688] rm[b;] [689] m[b;](-+/^\èr=' ')èr ¦ right justify [690] :end [691] :if cî8 9 10 ¦ bytes depth shape? [692] m(-+/^\èm=' ')èm ¦ right justify [693] :end [694] d•AVm [695] :if dðâûd ¦ already sorted? [696] dèd ¦ descending [697] :end [698] •wi 'sortorder' (i[d]) [699] [700] :CASE 'PeekRow' [701] [702] ¦ ••wself •wevent •warg [703] (r G)G ¦ rowid  1 for peek, 0 for get info [704] (b w u c j),•wi 'GetCells' r (2 3 4 5 6) ¦ lib wsid ufile class name [705] [706] :if (,1)ð•VI b ¦ library number [707] bb,' ' [708] :else ¦ path [709] bb,(':'=ý1b)'\' ¦ force trailing backslash, unless 'D:' [710] :end [711] [712] :if wú.†' ' [713] (r (b,w) c j G) CMDSYMFIND 'PeekWsid' [714] :else [715] (r (b,u) c j G) CMDSYMFIND 'PeekUfile' [716] :end [717] [718] :CASE 'PeekWsid' [719] [720] (r w c j G)G ¦ row ws class name peek [721] [722] z~G [723] k " rj P a;k;•ELX;*" [724] kk,"@ •ELX'r9  0'" ¦ handle possible INCOMPATIBLE WS error from •COPY [725] kk,"@ rj •COPY a" [726] kk,"@ (rî1 2)0" [727] kk,"@ rr,•SIZE j" [728] kk,"@ :select •first r" [729] kk,"@ :case 1" ¦ function [730] kk,"@ rr,(2 •AT j)(•VR j)" [731] kk,z/"@ 0" ¦ get info only [732] kk,"@ (û4r)0" ¦ don't try to edit if locked [733] kk,"@ k•WCALL 'W_Edit' j" [734] kk,"@ :case 2" ¦ variable [735] kk,"@ v*" [736] kk,"@ rr,'' v" [737] kk,z/"@ 0" ¦ get info only [738] kk,"@ :if 1=ûûv" [739] kk,"@ :andif 5óûv" [740] kk,"@ :andif 'PACKAGE'ð1v" [741] kk,"@ •UCMD 'PKGDOC ',j" [742] kk,"@ 0" [743] kk,"@ :elseif (ðv)>1" [744] kk,"@ :orif (ûûv)>2" [745] kk,"@ :orif ^/0 ' 'î•TYPE •enlist v" [746] kk,"@ v•UCMD 'DISPLAY v'" [747] kk,"@ *v" [748] kk,"@ :end" [749] kk,"@ k•WCALL 'W_Edit' j" [750] kk,"@ :end" [751] [752] ((k='*')/k) j [753] k•enlist k [754] k(k†'@') Partition k [755] k•DEF[2]k ¦õ P [756] ¦ ••vr k [757] (rc z t x)4j P w [758] :if rcî1 2 [759] max256 ¦ max width of FFA display [760] zDLB,'CI15' •FMT z ¦ format bytes [761] :if rc=2 ¦ variable [762] t'-' [763] sûx ¦ shape [764] s(ôs),(0=ûs)/'' ¦ format shape [765] dôðx ¦ depth [766] xmax FFAW x [767] x(maxûx)ûx [768] qxâ'û' [769] :if qóûx [770] :andif q,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6ût [775] d'-' ¦ depth [776] ¦s(ô+/x •SS •TCNL,'['),' lines' [777] :if c='' [778] s'?' [779] x'(locked function)' [780] :else [781] sôûx [782] x(maxûx)ûx [783] ((x=•TCNL)/x)' ' [784] :end [785] :end [786] c7 8 9 10 11 ¦ timestamp bytes depth shape value [787] •wi 'SetCells' r c (t z d s x) [788] ¦ display •wi 'GetCells' r c [789] m•wi 'columndisplay' [790] c(0†m[c;2])/c ¦ only visible columns [791] •wi 'AutoFit' 'header' c [792] 0 [793] :end [794] [795] môrc [796] ((m='ý')/m)'-' [797] m'Return code ',m,' from []COPY:',•tcnl [798] [799] :select rc [800] :case 0  mm,'Object not found' [801] :case 127  mm,'Duplicate name in objlist ¦ should not get here!' [802] :case ý2  mm,'Object too large for available space' [803] :case ý3  mm,'Name defined as a label; cannot be changed' [804] :case ý4  mm,'Insufficient space in symbol table and workspace too full to expand symbol table' [805] :case ý6  mm,'Insufficient free space to carry out command' [806] :case 9  m 'Error from []COPY:',•TCNL,(^\•DM†•TCNL)/•DM [807] :else  mm,'Unanticipated return code!' [808] :end [809] [810] k•wcall 'MessageBox' (•wi ':hwnd') m 'COPY ERROR' 'MB_ICONSTOP' [811] [812] :CASE 'PeekUfile' [813] [814] (r u c j G)G ¦ row file class name peek [815] [816] (v t)(u j) CMDSYMFIND 'Uget' ¦ the value, timestamp [817] t,'I4,,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6ûFTIMEREP t [818] nj [819] [820] :if 1=ûûv [821] :andif 5óûv [822] :andif 'PACKAGE'ð1v [823] rc2 ¦ variable [824] z•SIZE 'v' ¦ bytes [825] :if G ¦ if peek [826] k•DEF[2]("n P ",n) "•UCMD 'PKGDOC ',n" ¦õ P [827] ¦ ••vr 'P' [828] n P v [829] :end [830] :elseif c='ì' ¦ function [831] rc1 ¦ function [832] ¦ Note we update z here -- [833] ¦ need to measure bytes while function is defined; it's not just •size •vr ! [834] k•DEF[2]("n P v;",n) "k•def v  (kðn)0  z•SIZE n" (G/"k•WCALL 'W_Edit' n") [835] n P v [836] :else ¦ variable [837] rc2 [838] z•SIZE 'v' ¦ bytes [839] :if G ¦ if peek [840] :if (ðv)>1 [841] :orif (ûûv)>2 [842] :orif ^/0 ' 'î•TYPE •enlist v [843] v•UCMD 'DISPLAY v' ¦ well, it's better than nothing! [844] :end [845] k•DEF[2]("n P ",n) "k•WCALL 'W_Edit' n" [846] n P v [847] :end [848] :end [849] [850] max256 ¦ max width of FFA display [851] zDLB,'CI15' •FMT z ¦ format bytes [852] :if rc=2 ¦ variable [853] sûv ¦ shape [854] s(ôs),(0=ûs)/'' ¦ format shape [855] dôðv ¦ depth [856] xmax FFAW v [857] x(maxûx)ûx [858] qxâ'û' [859] :if qóûx [860] :andif q0) [896] '.mGet' •wi 'enabled' (n>0) [897] '.mGetAll' •wi 'enabled' ((ûi)>0) [898] '.mDiff' •wi 'enabled' (n=2) [899] '.mRemove' •wi 'enabled' (n>0) [900] [901] :CASE 'Click' [902] [903] ¦ If there are 0 rows selected, act on the pointed-to row [904] ¦ Else always act on selected row(s) [905] [906] a•warg ¦ pointed-to rowid; save to perhaps pass along to DblClick [907] b7a ¦ mouse button (1=left 2=right) [908] (b†2)û0 ¦ quit unless right (row selection has already been toggled) [909] v•wi 'value' ¦ selected rowids [910] r1a ¦ pointed-to rowid; save to perhaps pass along to DblClick [911] r0 ¦ quit if empty row [912] z•first •wi 'GetCells' r 8 ¦ bytes (tells us if we have done Get Info already) [913] [914] f•wself [915] [916] m'mSymFindPopup' [917] •wselfm •wi 'Create' 'Menu' [918] k'.m1' •wi 'New' 'Menu' ('caption' 'Peek') ('onClick' "':' •wi 'data' 1") [919] k'.m2' •wi 'New' 'Menu' ('caption' 'Get Info') ('onClick' "':' •wi 'data' 2") ('enabled' (0îûz)) [920] k'.m3' •wi 'New' 'Menu' ('caption' 'Diff') ('onClick' "':' •wi 'data' 3") ('enabled' (2=ûv)) [921] k'.m4' •wi 'New' 'Menu' ('caption' 'Remove from list') ('onClick' "':' •wi 'data' 4") [922] [923] •wselff [924] [925] ':' •wi 'Popup' m 2 ¦ 2=make the menu respond to the right mouse button [926] dm •wi 'data' [927] m •wi 'Delete' [928] [929] :select d [930] :case 0 ¦ escape [931] ¦ noop [932] :case 1 ¦ peek [933] r 1 CMDSYMFIND 'PeekRow' [934] :case 2 ¦ get info [935] :for i :in v [936] i 0 CMDSYMFIND 'PeekRow' [937] :end [938] :case 3 ¦ diff [939]  CMDSYMFIND 'Diff' [940] :case 4 ¦ remove [941] •wi 'DeleteRows' v [942] :else ¦ tilt [943] ö0 [944] :end [945] [946] :CASE 'View' [947] [948] ¦ •wself is a menu item [949] v•wi 'value' ¦ value has already changed [950] c•wi 'data' ¦ display column number [951] •wself':lv' [952] :if v ¦ if turning on, we just need to autofit it [953] •wi 'AutoFit' 'header' c [954] :else ¦ if turning off, we need to change width to 0 [955] m•wi 'columndisplay' [956] m[c;2]0 [957] •wi 'columndisplay' m [958] :end [959] [960] :CASE 'GetAll' [961] [962] ':mView.mTime' •wi 'value' 1 ¦ RHS 9/18/04 automatically reveal the Timestamp column [963] [964] •wself':lv' [965] w•wi 'sortorder' ¦ all rowids [966] w CMDSYMFIND 'GetRows' [967] [968] :CASE 'GetRows' [969] [970] wG ¦ rowids [971] [972] ':' •wi 'pointer' 11 [973] [974] •wself':bnExit' [975] •wi 'caption' 'Stop' [976] •wi 'onClick' "':' •wi '‘stop' 1" [977] [978] •wself':lv' [979] [980] d,•wi 'GetCells' w 8 ¦ bytes [981] w(0îûd)/w ¦ not got yet [982] [983] :for i :in w [984] •wgive 0 [985] :if ':' •wi '‘stop' [986] ':' •wi '‘stop' 0 [987] :leave [988] :end [989] i 0 CMDSYMFIND 'PeekRow' [990] :end [991] [992] ':' •wi 'pointer' 0 [993] [994] •wself':bnExit' [995] •wi 'onClick' '' [996] •wi 'caption' 'E&xit' [997] [998] :CASE 'Udir' [999] [1000] ¦ Callback to read ucmd file directory [1001] [1002] n' '=•first G ¦ file name from ]UFILE ? [1003] :if n ¦ no tolerence for error [1004] •ELX'R"NOT A USER COMMAND FILE"  b' ¦ vector result: error [1005] :else ¦ file name from lib or dir: ignore any error [1006] •ELX"R0  b" [1007] :end [1008] [1009] b0 ¦ branch target after error [1010] T•FNUMS,•XFNUMS ¦ save current ties [1011] t1+0/T ¦ next available tie number [1012] G •FSTIE t ¦ tie it [1013] bL2 ¦ now we need to untie [1014] :if n [1015] :orif 1î'User-defined commands file'•enlist •FREAD t,1 ¦ first comp should have signature [1016] i•FREAD t,2 ¦ pointers to directories [1017] s•FREAD t,i[2] ¦ char directory of objects (names) [1018] n•FREAD t,i[3] ¦ num directory of objects (nc, comp) [1019] n' ì?'[n[;1]] [1020] Rn,' ',DTBC s ¦ matrix result: like RDST [1021] :else [1022] R0 ¦ scalar result: not a ucmd file, ignore it [1023] :end [1024] L2: [1025] b0 [1026] •FUNTIE t [1027] tT~•FNUMS,•XFNUMS [1028] :if ’ût ¦ we lost a tie number [1029] G •FSTIE t ¦ but what if it was originally •FTIE ...? [1030] :end [1031] [1032] :CASE 'Uget' [1033] [1034] (G j)G ¦ file, object name [1035] T•FNUMS,•XFNUMS ¦ before [1036] t1+0/T ¦ next available tie number [1037] G •FSTIE t ¦ tie it [1038] w•FNUMS,•XFNUMS ¦ after [1039] :if (ûT)=ûw ¦ was it already tied? [1040] tT~w ¦ original tie number [1041] G •FSTIE t ¦ but what if it was originally •FTIE ...? [1042] u ¦ nothing to untie when done [1043] :else [1044] ut ¦ to untie when done [1045] :end [1046] i•FREAD t,2 ¦ pointers to directories [1047] s•FREAD t,i[2] ¦ char directory of objects (names) [1048] n•FREAD t,i[3] ¦ num directory of objects (nc, comp) [1049] i(s^.=(ý1ûs)j)â1 ¦ find name [1050] (c m)n[i;2 3] ¦ component, timestamp [1051] v•FREAD t,c ¦ read value [1052] •FUNTIE u [1053] Rv m ¦ value, timestamp [1054] [1055] :CASE 'Diff' [1056] [1057] •wself':lv' [1058] v•wi 'value' ¦ selected rowids [1059] m•wi 'GetCells' v (2 3 4 6) ¦ lib wsid ufile name [1060] d2û '' [1061] :for i :in â2 [1062] (b w u j)m[i;] ¦ lib wsid ufile name [1063] :if (,1)ð•VI b ¦ library number [1064] bb,' ' [1065] :else ¦ path [1066] bb,(':'=ý1b)'\' ¦ add trailing backslash, unless 'D:' [1067] :end [1068] :if wú.†' ' [1069] (id)b,w,' ',j [1070] :else [1071] (id)j, '/F=',b,u [1072] :end [1073] :end [1074] •UCMD •' ]DIFF ',(1d),' ; ',2d ¦ show ucmd being invoked [1075] [1076] :ELSE [1077] [1078] •'Unanticipated callback!' N •wself •wevent •warg [1079] [1080] :ENDSELECT [1081] ì €àÿt6Xèè ì CMDTRACEOBJ A;C;E;F;I;J;T;X;a;d;e;h;n;s;v;•wself [1] ¦ Trace activity on an APL GUI object [2] ¦ Syntax: ]TraceObj [obj] [/A] [/E] [/OFF] [/X=...] [/I=...] [3] ¦ If object not specified, •wself is used [4] ¦ Use /A to trace just actions or /E to trace just events; default is to trace both [5] ¦ /X excludes (all but) actions and events matching substring -- e.g., /X=mouse key [6] ¦ /I includes (only) actions and events matching substring [7] ¦ Any trace on an object replaces any previous trace [8] ¦ Trace display is: øøø TraceObj: •wself •wevent (•warg) •si [9] [10] ¦ ----- Actions ----- [11] ¦ [12] ¦ For example, after: 'fm' •wi 'Create' 'Form' ('onResize' 'foo') [13] ¦ /A traces property changes such as: 'fm' •wi 'size' 10 20 [14] ¦ and methods such as: 'fm' •wi 'Show' [15] ¦ but it does NOT trace event handlers (Resize is not traced if user resizes fm) [16] ¦ [17] ¦ I.e., we trace actions initiated by programs, but not actions [18] ¦ initiated by the system in response to the user having done something [19] [20] ¦ ----- Events ----- [21] ¦ [22] ¦ /E traces events such as Resize triggered by onResize handler if user resizes form [23] [24] ¦ 18 Sep 2005 Rex Swain, Independent Consultant, www.rexswain.com [25] ¦ 07 Dec 2005 Most recent minor update [26] [27] ('@ 'ð2A~' ')ûL9 ¦ special arg indicates callback to trace an event or action [28] [29] JñDEB (^\A†'/')/A ¦ delete all options, leaving object [30] :if Jð'' [31] :if ''ð•wself [32] •"Current object undefined (•wself'')" [33] 0 [34] :end [35] :else [36] :if ''ðJ •wi '*self' [37] •'No such object: ',J [38] 0 [39] :end [40] •wselfJ [41] :end [42] [43] ¦ ----- First do /OFF ----- [44] [45] C•wi '*‘traceobj_actions' ¦ love that default 0! [46] E•wi '*‘traceobj_events' [47] [48] v0û '' ¦ events to reset [49] [50] :if C [51] •wi '*‘traceobj_actions' 0 [52] vv, 'Action' [53] :end [54] [55] :if E [56] •wi '*‘traceobj_events' 0 [57] vv,•wi '*‘traceobj_eventlist' [58] :end [59] [60] :for e :in v [61] :if eð'Modify'  e'onModified' ¦ event is 'Modify' but handler is 'onModified'! [62] :else  e'on',e [63] :end [64] a•wi '*‘traceobj_old_',e ¦ original [65] d•wi '*‘traceobj_new_',e ¦ what we changed the original to [66] h•wi '*',e ¦ current; normally same as _new above [67] :if hðd [68] •wi ('*',e) a ¦ restore original [69] :else [70] •'** ',e,' has changed since ]TraceObj ; leaving current value: ',h [71] :end [72] :end [73] [74] F1=ûûA ñGETOPT '/OFF' ¦ off option [75] [76] :if F ¦ if /OFF, we're done [77] :if ’ûv [78] •'TraceObj removed from ',•wself [79] :else [80] •'No TraceObj to remove from ',•wself ¦ but no harm done [81] :end [82] 0 [83] :end [84] [85] ¦ ----- /ON ----- [86] [87] C1=ûûA ñGETOPT '/A' ¦ actions only [88] E1=ûûA ñGETOPT '/E' ¦ events only [89] (C E)(C E) ú CåE ¦ default to both [90] XWords,A ñGETOPT '/X' ¦ exclude [91] IWords,A ñGETOPT '/I' ¦ include [92] :if (’ûX)^(’ûI) [93] •'/X and /I not permitted at the same time' [94] 0 [95] :end [96] T"•ucmd 'TraceObj @'" [97] [98] ¦ Do events before actions, else all changes we make here are traced! [99] [100] :if E ¦ Events [101] [102] v•wi '*events' [103] vv~ 'Action' ¦ because we treat this separately [104] [105] :if ’ûX [106] h ú/ ú/ (ñUCASEv) ø.•SS (ñUCASEX) [107] •'TraceObj excluding events:',ôh/v [108] v(~h)/v [109] :end [110] [111] :if ’ûI [112] h ú/ ú/ (ñUCASEv) ø.•SS (ñUCASEI) [113] •'TraceObj including events:',ôh/v [114] vh/v [115] :end [116] [117] •wi '*‘traceobj_eventlist' v ¦ remember which ones we are changing [118] [119] :for e :in v [120] :if eð'Modify'  e'onModified' ¦ event is 'Modify' but handler is 'onModified'! [121] :else  e'on',e [122] :end [123] h•wi e [124] •wi ('*‘traceobj_old_',e) h ¦ original [125] hT,(’ûh)/'  ',h [126] •wi ('*‘traceobj_new_',e) h ¦ what we changed the original to [127] •wi ('*',e) h [128] :end [129] [130] •wi '*‘traceobj_events' 1 [131] [132] •'TraceObj now tracing ',(ôûv),' events on ',•wself [133] [134] :end [135] [136] :if C ¦ Actions [137] [138] h•wi '*onAction' [139] [140] •wi '*‘traceobj_old_onAction' h ¦ save original onAction handler [141] [142] :if ’ûX [143] •'TraceObj excluding actions matching:',ôX [144] XñUCASEX [145] •wi '*‘traceobj_XI' ('X' X) ¦ because we cannot rule them out right now [146] :end [147] [148] :if ’ûI [149] •'TraceObj including actions matching:',ôI [150] IñUCASEI [151] •wi '*‘traceobj_XI' ('I' I) [152] :end [153] [154] :if hð'' [155] h"•wres•wi '*'" [156] •'TraceObj now tracing actions on ',•wself [157] :else [158] •'Object ',•wself,' already has an onAction handler: ',h [159] •'TraceObj tracing added to ',•wself [160] :end [161] [162] hT,(’ûh)/'  ',h [163] •wi '*‘traceobj_new_onAction' h ¦ what we changed the original to [164] •wi '*onAction' h [165] [166] •wi '*‘traceobj_actions' 1 [167] [168] :end [169] [170] 0 [171] [172] L9: ¦ ----- callback ----- [173] [174] ¦ Unwanted events never even get here; unwanted actions need to be filtered out now [175] [176] :if •weventð'Action' [177] (C X)•wi '*‘traceobj_XI' [178] :if ~Cð0 [179] ¦Assert Cî'XI' [180] aú/ú/( ñUCASE 1•warg) •SSX [181] (a=C='X')û0 [182] :end [183] :end [184] [185] ¦ 1st row in •SI is ourself [186] ¦ 2nd row is : >[•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] ì €àÿt6ˆ]] ì CMDTRACEVAR A;D;K;S;V;W;X [1] ¦ Trace changes to variable(s) [2] ¦ ]TraceVar dat ... ¦ trace changes to the named variable(s) [3] ¦ ]TraceVar dat:2dat ¦ display 2dat when dat changes; just one var [4] ¦ ]TraceVar dat[2] ¦ trace only when dat[2] changes; just one var [5] ¦ ]TraceVar ... /STOP ¦ sets stop on first change; suspends before next change [6] ¦ ]TraceVar ... /ALERT ¦ display MessageBox after change report [7] [8] ¦ ]TraceVar dat ... /OFF ¦ turn off tracing of the named variable(s) [9] ¦ ]TraceVar /OFF ¦ turn off all tracing [10] [11] ¦ ]TraceVar dat /REPORT ¦ used internally to report a change [12] [13] ¦ Requires: FFAW [14] ¦ EVLEVEL neutral [15] ¦ 21 Oct 2004 Rex Swain, Independent Consultant, www.rexswain.com [16] ¦ 19 Apr 2005 Added varname:expression feature [17] ¦ 03 Jun 2005 Added /STOP and /ALERT features [18] ¦ 29 Mar 2007 Added dat[2] feature [19] ¦ 22 Feb 2008 Allow dat[2;5] ¦ duh [20] [21] VñDEB (^\A†'/')/A ¦ argument without options [22] :if 1=ûûA ñGETOPT '/REPORT' [23] ¦ 1st row in •SI is ourself; 2nd row is •WATCHPOINT[1] [24] S•SI[;1] ¦ first column of SI [25] WSâ']' ¦ how much UCMD crap is there [26] WW*WóûS ¦ or 1 if no ] (non-UCMD) [27] WW+1 ¦ •WATCHPOINT[1] [28] SW[1]•SI ¦ •SI to report [29] :if '['îV [30] Dý1V ¦ drop ] [31] ¦D[Dâ'[']'_' [32] ((Dî'[;')/D)'_' ¦ RHS 2/22/08 in case 'DAT[2;5]' [33] :if 0='#' •wi '‘TraceVar_Flag_',D [34] ¦ first time [35] '#' •wi ('‘TraceVar_Flag_',D) 1 [36] ¦ and fall through to let it display [37] :else [38] X'#' •wi '‘TraceVar_Value_',D [39] (XðõV)û0 ¦ no change, no display [40] :end [41] '#' •wi ('‘TraceVar_Value_',D) (õV) [42] :end [43] W' TraceVar: ',ñDEB,' ',S  •(•pwûW)W [44] W' TraceVar: ',V,'',(•pw FFAW õV)  •(•pwûW)W [45] :if 1=ûûA ñGETOPT '/STOP' [46] ¦ S[1;] might be 'õ' now [47] X(S[;1]î'õ•><')â0 [48] :if X>ûûS [49] •' Cannot set Stop -- no function in SI stack' [50] :else [51] WS[X;] [52] X1(†\Wî'[]')/W ¦ line number [53] W(^\W†'[')/W ¦ function name [54] K((•STOP W),•FI X) •STOP W [55] X•STOP W [56] •' Stop',(1=ûX)'s now set on ',W,'[',(ôX),']' [57] :end [58] :end [59] :if 1=ûûA ñGETOPT '/ALERT' [60] XV,•TCNL,,•TCNL,S [61] XX,•TCNL,•TCNL,'Continue? (Y=Continue, N=Suspend, C=Cancel trace)' [62] K•wcall 'MessageBox' 0 X 'TraceVar' 'MB_ICONINFORMATION MB_YESNOCANCEL' [63] :if K=6 ¦ 6=IDYES [64] :elseif K=7 ¦ 7=IDNO [65] ñRESULT1 ¦ non-zero result suspends on •WATCHPOINT[1] [66] :else ¦ 2=IDCANCEL [67] V(^\V†'[')/V [68] •UCMD ']TraceVar ',V,' /OFF' [69] :end [70] :end [71] :elseif 1=ûûA ñGETOPT '/OFF' [72] :if Vð'' [73] •watchpoints0 2û '' [74] •']TraceVar * /OFF' [75] :else [76] V(V†' ') Partition V [77] W•watchpoints [78] W(~W[;1]îV)ëW [79] •watchpointsW [80] •']TraceVar',(ôV),'/OFF ¦ ',(ô1ûW),' vars remain traced' [81] :end [82] :else ¦ /ON [83] W•watchpoints [84] :if ~Vð'' [85] S(1=ûûA ñGETOPT '/STOP' )/' /STOP' [86] X(1=ûûA ñGETOPT '/ALERT')/' /ALERT' [87] :if ':'îV [88] (V D)(~<\V=':') Partition V [89] W(~W[;1]î V)ëW [90] WWžV ("•UCMD ']TraceVar ",D," /REPORT",S,X,"'") [91] :elseif '['îV [92] (V D)(1+<\V='[') Partition V [93] W(~W[;1]î V)ëW [94] WWžV ("•UCMD ']TraceVar ",V,D," /REPORT",S,X,"'") [95] :else [96] V(V†' ') Partition V [97] W(~W[;1]îV)ëW [98] WWžV,[1.5] ( "•UCMD ']TraceVar "),V, " /REPORT",S,X,"'" [99] :end [100] •watchpointsW [101] :end [102] •']TraceVar',ôW[;1] [103] :end [104] ì €àÿt6²   ì 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) ì €àÿt6 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 ¦ all names [91] ¦ Since we used •NL, we can skip check for invalid names [92] ¦ Only possible problems are global vars shadowed by our and UCMD local names [93] ¦ Don't warn if shadowed object is not a var -- we wouldn't have searched it anyway! [94] n•IDLOC V ¦ state of each name [95] b0 Xn ¦ look outside us and UCMD stuff [96] c(,<\ý1†b)/,b ¦ next-most-local classification [97] vc=2 ¦ flag those that are global vars [98] VvëV ¦ squeeze names [99] nvën ¦ squeeze idloc [100] ¦ Okay, we have all the global variables names; are any shadowed? [101] bn[;âX] ¦ look inside us and UCMD stuff [102] nbú.†ý1 ¦ flag if any definition [103] [104] :if 1în [105] •'*** Shadowed variable',(1=+/n)'s:',ôWords nëV [106] V(~n)ëV ¦ squeeze names [107] :end [108] [109] :else ¦ user supplied list of names [110] [111] V[2] Words V ¦ matrix [112] c4=•NC V ¦ 4=invalid [113] :if 1îc [114] •'*** Invalid name',(1=+/c)'s:',ôWords cëV [115] V(~c)ëV [116] :end [117] n•IDLOC V ¦ state of each name [118] cn[;âX]ú.†ý1 ¦ flag our locals [119] n0 Xn ¦ drop local classification [120] n(,<\ý1†n)/,n ¦ next-most-local classification [121] nn=2 ¦ flag those that are global vars [122] :if 0în [123] •'*** Not variable',(1=+/~n)'s:',ôWords (~n)ëV [124] :end [125] bc^n ¦ local var and global var [126] :if 1îb [127] •'*** Shadowed variable',(1=+/b)'s:',ôWords bëV [128] :end [129] V(n>c)ëV [130] [131] :end [132] [133] VWords V ¦ items [134] nûV ¦ how many vars [135] Xnû0 ¦ X/V will be result [136] [137] DðT ¦ depth of target [138] S(1òD)^(1òûûT)^(~•TCNLîT) ¦ simple vector with no cr's? [139] [140] ••PW'Searching ',(ôn),' variable',(n=1)'s for ',FFAW T [141] [142] •WGIVE 0 ¦ let that message display [143] [144] ¦ Climb SI stack until •ELX is localized [145] •ELX"•ERROR(ý1=1û•IDLOC'•ELX')/•DM  •N,' : ',(^\•DM†•TCNL)/•DM  1+•LC" [146] [147] :for b :in ân [148] H0 ¦ count hits in this var [149] NbV ¦ name [150] ¦ Note that ìVARFIND2 uses semi-globals: D H N R S T [151]  VARFIND2 õN ¦ search and recurse [152] X[b]H>0 ¦ add to result? [153] •WGIVE 0 [154] :end [155] [156] :if Rð0 ¦ / option [157] ñRESULTX/V [158] :end [159] ì €àÿt6·   ì CMDVARSS N [1] ¦ )VARS string search [2] ¦ Syntax: [3] ¦ ]VARSS foo ¦ find variable names containing substring foo [4] ¦ Use semicolons to delimit multiple names and to retain leading/trailing blanks [5] ¦ ]VARSS ; foo ¦ names beginning with foo [6] ¦ ]VARSS foo ; ¦ names ending with foo [7] ¦ ]VARSS ; foo ; ¦ names matching foo [8] ¦ ]VARSS foo;goo ¦ names containing foo or goo [9] ¦ Options: [10] ¦ /C ¦ case-sensitive [11] ¦ /N ¦ name matching -- shorthand for ]VARSS ; 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] 2 NLSS N ì €àÿt6¥Ú¥Ú ì RG CMDWSCOMP W;B;C;D;E;F;I;S;V;X;a;b;c;c1;c2;d;e;f;g;g1;g2;h;i;j;k;m;n;n1;n2;p;r;s;s1;s2;t;t1;t2;u;v;w;w1;w2;x;x1;x2;z;•elx;•wself [1] ¦ Compare two workspaces (or user command files) [2] [3] ¦ Syntax: [4] ¦ ]WSCOMP wsorufile ; wsorufile ¦ compare two specified wss/ucmd files [5] ¦ ]WSCOMP ; wsid ¦ compare active ws with specified ws [6] ¦ ]WSCOMP ; ufile /F ¦ compare active ws with ucmd file [7] ¦ ]WSCOMP = ¦ special case: compare active ws with saved ws [8] ¦ [9] ¦ You may omit the semicolon if there are just one or two words in the argument [10] ¦ (so if you're using library numbers or /F, you must supply the semicolon) [11] ¦ [12] ¦ You may use "=" in the second wsorufile: [13] ¦ For example, ]WSCOMP \aplwin52\foo ; \aplwin64\= [14] ¦ Is treated as ]WSCOMP \aplwin52\foo ; \aplwin64\foo [15] ¦ [16] ¦ A wsid may be anything suitable for )XLOAD [17] ¦ A ufile may be anything suitable for •XFSTIE, followed by /F [18] ¦ [19] ¦ For example: [20] ¦ ]WSCOMP 9 foo /F ; d:\path\myws [21] ¦ [22] ¦ Options: [23] ¦ /ì ¦ functions only [24] ¦ / ¦ variables only [25] [26] ¦ Three panes are shown. In each, the "C" column shows the class of each object: [27] ¦ "ì" for function or "" for variable. You may click on a column heading to [28] ¦ sort by that column; click again to reverse the sort. [29] ¦ [30] ¦ The left and right panes show objects that exist in only one workspace/ufile. [31] ¦ The name lists are alphabetized. With double-click (or right-click and choose [32] ¦ "Peek") you can peek at objects with the editor. Normally you will want to end [33] ¦ the peek with Ctrl+Q -- if you end the edit with Ctrl+E, the object will be [34] ¦ saved in your active ws. Another way to get an object into your active ws is [35] ¦ to right-click and choose "Copy selected object into Active Ws". [36] ¦ [37] ¦ The center pane shows the names of objects that occur in both wss/ufiles. [38] ¦ Names whose values do not match are moved to the top of this list. The "ð" [39] ¦ column indicates whether the values of the objects match ("ð") or not ("~"). [40] ¦ For functions, the "New" column uses "®" or "¯" to point to the side with the [41] ¦ newest timestamp, or shows "=" if they are the same. If you have Araxis Merge, [42] ¦ double-click will show a detailed comparison of an object in this list. [43] [44] ¦ If you need to register this aplw.exe, execute [45] ¦ ]WSCOMP /RegServer [46] [47] ¦ Note that timestamps on functions in user command files are the time they [48] ¦ were saved into the file, not the 2 •AT time. [49] [50] ¦ To do: [51] ¦ - When peeking in active ws, we don't really need to localize and etc. [52] ¦ - Should "functions only" be the default? [53] ¦ - Resolve problems with •vars [54] ¦ - Argument parsing [55] ¦ - Show timestamp column on left and right, so can sort by it [56] [57] ¦ 16 Oct 2004 Rex Swain, Independent Consultant, www.rexswain.com [58] ¦ 04 Dec 2004 Added support for user command files [59] ¦ 14 Dec 2004 Added )COPY features [60] ¦ 10 Mar 2005 Added /RegServer option [61] ¦ 26 Mar 2005 Evlevel-neutral [62] ¦ 01 Aug 2005 Added = special case [63] ¦ 06 Oct 2005 Don't allow -options (because filespecs may contain hyphens) [64] ¦ 12 Oct 2005 Remove /options before checking for '=' special case [65] ¦ 31 Oct 2005 Fixed problem with )RESET in saved ws [66] ¦ 13 Mar 2006 Prompt to save changes made via Merge (suggested by Patrick Parks) [67] ¦ Use APL font specified in APLW.INI [UCMDSREX] [68] ¦ Added /AMFONT= to reset Araxis Merge font [69] ¦ 08 May 2006 Ensure one last Timer tick before exiting [70] ¦ 14 Oct 2006 Support "=" in the second wsorufile [71] ¦ 04 Feb 2008 Show 'ð' if •VRs match; '=' if match except for trailing blanks [72] [73] E'ActiveObject Merge65.Application' ¦ Araxis Merge version 6.5 [74] ¦E'ActiveObject Merge2000.Application' ¦ Araxis Merge 2001 (version 6.0) [75] [76] (’•NC 'G')ûL9 ¦ left arg means callback [77] [78] Wô,W ¦ arg could be numeric in development mode [79] [80] :if W^.=' ' ¦ no argument? [81] •'For help, execute',•tcnl,' ]WSCOMP ?' [82] 0 [83] :end [84] [85] :if 1=ûûW ñGETOPT '/REGSERVER' [86] x•first /•wcall 'GetModuleFileName' '' (255û•tcnul) 255 [87] d(èú\èx='\')/x ¦ directory [88] x'"',x,'" CLEARWS /regserver' [89] •'Executing: ',x [90] 3 •cmd x ¦ 3=no DOS window; APL waits until done [91] x'REGSVR32 "',d,'aplwCo.dll"' [92] •'Executing: ',x [93] 3 •cmd x [94] 0 [95] :end [96] [97] tW ñGETOPT '/AMFONT' [98] :if 1=ûût [99] f'aoDIFF_AM' [100] :if ~''ðf •wi 'self' [101] :andif f •wi 'visible' [102] ¦ Merge is already running [103] •wselff [104] :else [105] ¦ Create new Merge object [106] •wselff •wi 'Create' E ¦ 'ActiveObject Merge65.Application' [107] :end [108] •wi 'Preferences > .prefs' [109] •wi '.prefs.Strings > .strings' [110] I 'csUnchangedFont' 'csChangedFont' 'csInsertedFont' 'csRemovedFont' ¦ left window [111] II,'csUnchangedFont2' 'csChangedFont2' 'csInsertedFont2' 'csRemovedFont2' ¦ right panel [112] :for i :in I [113] '.prefs.strings' •wi 'xItem' i t [114] :end [115] '.prefs' •wi 'XSave' [116] f •wi 'Delete' [117] •'Okay, Merge font set to: ',t [118] 0 [119] :end [120] [121] f1=ûûW ñGETOPT '/ì' ¦ functions only? [122] v1=ûûW ñGETOPT '/' ¦ variables only? [123] [124] :if fåv [125] fv1 ¦ default: functions and variables [126] :end [127] [128] F(f,v)/'ì' ¦ fns/vars filter [129] [130] :if (W~' /ì')ð,'=' ¦ special case for active vs. saved ws [131] :if •WSID^.=' ' [132] •'Cannot use = feature in a clear ws' [133] 0 [134] :end [135] W •WSID [136] :elseif ';'îW [137] W';' Words W ¦ 'foo;goo'  'foo' 'goo' [138] :else [139] WWords W ¦ 'foo goo'  'foo' 'goo' [140] :end [141] [142] WDEBý2W ¦ default first item to active ws [143] [144] :if '='î2W ¦ '\aplwin52\foo' 'aplwin64\=' [145] (w1 w2)W [146] :if ( ý2w1)î'/f' '/F' [147] w1DEB ý2w1 [148] :end [149] tý1+(èw1î'\ ')â1 [150] w2[w2â'='] (-t)w1 [151] (2W)•enlist w2 [152] :end [153] [154] ¦ ----- Fetch Symbol Tables ----- [155] [156] ¦ server: 0 means active ws, >0 means saved ws, <0 means ucmd file [157] (x1 s1 w1 c1 n1)(1 W F) CMDWSCOMP 'GetWs' ¦ OK, server number, •wsid, classes, names [158] (x2 s2 w2 c2 n2)(2 W F) CMDWSCOMP 'GetWs' ¦ OK, server number, •wsid, classes, names [159] ss1,s2 [160] [161] :if x1êx2 ¦ any trouble? [162] s CMDWSCOMP 'Shutdown' ¦ shut down servers, untie files [163] 0 ¦ and bail out [164] :end [165] [166] ¦ ----- Create Form ----- [167] [168] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [169] k•fx [2] 'vk i d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ i [170] [171] w•FI 'WsComp-Place' i '2 5 20 70' [172] v•FI 'WsComp-Visible' i '1' [173] vv-v=2 ¦ 1=normal 2=minimized 3=maximized; don't start minimized [174] [175] •wself'mdiWsComp' •wi 'Create' 'MDIForm' 'Hide' [176] •wi 'caption' 'WsComp' [177] •wi 'place' w [178] •wi 'visible' v [179] •wi 'limitwhere' 12 45 [180] •wi 'pointer' 11 ¦ 11=hourglass (wait) [181] •wi '‘W' (w1 w2) ¦ wsids in captions [182] •wi '‘servers' s [183] e' CMDWSCOMP •wevent' [184] •wi 'onClose' e [185] •wi 'onDropDown' e ¦! this has no effect -- is this an APL bug? [186] [187] •wself':mFile' •wi 'New' 'Menu' [188] •wi 'caption' '&File' [189] [190] •wself'.mExit' •wi 'New' 'Menu' [191] •wi 'caption' 'E&xit' [192] •wi 'shortcut' 'X' 2 [193] •wi 'onClick' "0 0û':' •wi 'Close'" [194] [195] •wself':mEdit' •wi 'New' 'Menu' [196] •wi 'caption' '&Edit' [197] [198] •wself'.mCopy' •wi 'New' 'Menu' [199] •wi 'caption' '&Copy Entire Name List to Clipboard' [200] •wi 'shortcut' 'C' 2 [201] •wi 'onClick' " CMDWSCOMP 'Copy'" [202] [203] •wself':mView' •wi 'New' 'Menu' [204] •wi 'caption' '&View' [205] [206] fFð'ì' [207] [208] •wself'.mFns' •wi 'New' 'Menu' [209] •wi 'caption' '&Functions only' [210] •wi 'shortcut' 'F' 2 [211] •wi 'suppress' 1 [212] •wi 'onClick' "'ì' CMDWSCOMP 'Only'" [213] •wi 'enabled' f [214] [215] •wself'..mVars' •wi 'New' 'Menu' [216] •wi 'caption' '&Variables only' [217] •wi 'shortcut' 'V' 2 [218] •wi 'suppress' 1 [219] •wi 'onClick' "'' CMDWSCOMP 'Only'" [220] •wi 'enabled' f [221] [222] •wself':mActions' •wi 'New' 'Menu' [223] •wi 'caption' '&Actions' [224] [225] •wself'.mDiff' •wi 'New' 'Menu' [226] •wi 'caption' '&Diff' [227] •wi 'shortcut' 'D' 2 [228] •wi 'onClick' "1 CMDWSCOMP 'mActions'" [229] [230] •wself'..mPeekL' •wi 'New' 'Menu' [231] •wi 'caption' 'Peek &Left' [232] •wi 'shortcut' 'L' 2 [233] •wi 'onClick' "2 CMDWSCOMP 'mActions'" ¦  2 3 4: same values as popup menu [234] [235] •wself'..mPeekR' •wi 'New' 'Menu' [236] •wi 'caption' 'Peek &Right' [237] •wi 'shortcut' 'R' 2 [238] •wi 'onClick' "3 CMDWSCOMP 'mActions'" [239] [240] •wself'..mPeek' •wi 'New' 'Menu' [241] •wi 'caption' '&Peek' [242] •wi 'shortcut' 'P' 2 [243] •wi 'onClick' "4 CMDWSCOMP 'mActions'" [244] [245] ¦ Escape handler (this means Stop, then Exit) [246] •wself':mEsc' •WI 'New' 'Menu' ('visible' 0) [247] •wi 'shortcut' 27 0 [248] •wi 'onClick' "':f.bnExit' •wi 'Click'" [249] [250] ¦ ----- 3 Forms ----- [251] [252] t1 4û1 '' 0 8 ¦ status [253] [254] •wself':fm1' •wi 'New' 'Form' [255] •wi 'caption' ('Only in ',w1) [256] •wi '‘pane' 1 [257] •wi 'onDropDown' e ¦! now DropDown events fire; go figure [258] [259] •wself'.lv' •wi 'New' 'Listview' [260] •wi '‘server' (1s) [261] •wi '‘pane' 1 [262] [263] •wself'..st'•wi 'New' 'Status' [264] •wi 'status' t [265] [266] •wself':fm0' •wi 'New' 'Form' [267] •wi 'caption' 'In Both' [268] •wi '‘pane' 0 [269] •wi 'onDropDown' e [270] [271] •wself'.lv' •wi 'New' 'Listview' [272] •wi '‘pane' 0 [273] [274] •wself'..st'•wi 'New' 'Status' [275] •wi 'status' t [276] [277] •wself':fm2' •wi 'New' 'Form' [278] •wi 'caption' ('Only in ',w2) [279] •wi '‘pane' 2 [280] •wi 'onDropDown' e [281] [282] •wself'.lv' •wi 'New' 'Listview' [283] •wi '‘server' (2s) [284] •wi '‘pane' 2 [285] [286] •wself'..st'•wi 'New' 'Status' [287] •wi 'status' t [288] [289] ':' •wi 'activeform' '.fm0' [290] [291] ¦ ----- Font ----- [292] [293] ¦ Get value of key k; if undefined, write default to the ini file [294] k•fx [2] ( [2] •cr 'i'), "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôd)" ¦õ i [295] [296] t 'FontName' i 'APLFONT' [297] tt,•FI 'FontSize' i '11' [298] tt,•FI 'FontStyle' i '0' [299] tt, 'FontCharset' i 'default' [300] [301] ¦ ----- Bottom Frame ----- [302] [303] ¦ We need frame here because Buttons cannot be children of MDIForm! [304] [305] •wself':f' •wi 'New' 'Frame' [306] •wi 'style' 7 [307] [308] •wself'.l' •wi 'New' 'Label' [309] •wi 'style' 4 8 [310] •wi 'caption' '' [311] •wi 'scale' 3 [312] •wi 'font' t [313] •wi 'scale' 1 [314] x2’1 1•wi 'Draw' ('?Text' 'AB') ¦ height for two lines [315] [316] •wself'..pb' •wi 'New' 'Progress' [317] •wi 'style' 1 ¦ 1=smooth [318] •wi 'value' 0 100 1 0 [319] [320] •wself'..bnExit' •wi 'New' 'Button' [321] ¦•wi 'style' 2 ¦ 2=cancel ¦ this doesn't work on an MDIForm [322] ¦ Stop feature: [323] •wi 'caption' '&Stop' [324] •wi 'onClick' "':' •wi '‘stop' 1" [325] [326] ¦ ----- Fix Sizes ----- [327] [328] h0.5+x ¦ height of bottom frame [329] b1.2524ö•first '#' •wi 'units' ¦ button height [330] w8 ¦ button width [331] [332] •wself':' [333] z•wi 'size' [334] cz-h 0 ¦ client size [335] •wi '‘h' h [336] •wi 'clientwhere' (0,0,c) [337] [338] •wself':f' [339] •wi 'where' (c[1],0,h,z[2]) [340] [341] •wself'.l' [342] •wi 'where' (0.25,0.5,x,z[2]-w+2) [343] [344] •wself'..pb' [345] •wi 'where' ((h-b+0.25),0.5,b,z[2]-w+2) [346] [347] •wself'..bnExit' [348] •wi 'where' ((h-b+0.25),(z[2]-w+0.5),b,w) [349] [350] ¦ ----- Flesh Out 3 Forms ----- [351] [352] p3 4 3 ¦ relative widths [353] dc[2]’pö+/p [354] p+\0,d [355] [356] ':fm1' •wi 'where' (0,p[1],c[1],d[1]) [357] ':fm0' •wi 'where' (0,p[2],c[1],d[2]) [358] ':fm2' •wi 'where' (0,p[3],c[1],d[3]) [359] [360] :for •wself :in ':fm1' ':fm0' ':fm2' [361] •wi 'onResize' " CMDWSCOMP 'fmResize'" [362] z•wi 'size' [363] •wself'.lv' [364] •wi 'where' (0 0,z) [365] •wi 'style' 1 2 4 1024 4096 ¦ 1024=reorder cols 4096=gridlines [366] •wi 'scale' 3 ¦ font size will be specified in points [367] •wi 'font' t [368] •wi 'scale' 1 [369] •wi 'onColClick' e ¦ sort [370] •wi 'onDblClick' e ¦ peek [371] •wi 'keys' 13 ¦ Enter [372] •wi 'onKeyPress' e ¦ Enterpeek [373] •wi 'onClick' e ¦ select [374] •wi 'onSelect' e ¦ select [375] :end [376] [377] ¦ 1=label 2=width 3=just 4=col id 5=col order 6=header image 7=header style [378] [379] c0 3û0 [380] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [381] ccž'C' 3.5 'center' ¦ 2 [382] ccž'New' 4.5 'center' ¦ 3 ¦ newer [383] ccž' ð ' 4.5 'center' ¦ 4 ¦ match [384] ccž'Name' 16 'left' ¦ 5 [385] [386] ':fm0.lv' •wi 'columndisplay' c [387] [388] c0 3û0 [389] ccž' ' 0 'left' ¦ 1 ¦ first col must be left justified [390] ccž'C' 2.5 'center' ¦ 2 [391] ccž'Name' 16 'left' ¦ 3 [392] [393] ':fm1.lv' •wi 'columndisplay' c [394] ':fm2.lv' •wi 'columndisplay' c [395] [396] ¦ ----- Load name lists ----- [397] [398] •wself':fm1.lv' [399] b~n1în2 [400] cb/c1 [401] dc,[1.5] b/n1 [402] d,' ',d ¦ add hidden column; Listview wants all vectors [403] k•wi 'AddRows' (0,1,d) [404] •wi 'AutoFit' 'header' (2 3) [405] [406] '..st' •wi 'SetStatus' ((ô+/c='ì'),' Fns, ',(ô+/c=''),' Vars') [407] [408] •wself':fm2.lv' [409] b~n2în1 [410] cb/c2 [411] dc,[1.5] b/n2 [412] d,' ',d ¦ add hidden column; Listview wants all vectors [413] k•wi 'AddRows' (0,1,d) [414] •wi 'AutoFit' 'header' (2 3) [415] [416] '..st' •wi 'SetStatus' ((ô+/c='ì'),' Fns, ',(ô+/c=''),' Vars') [417] [418] •wself':fm0.lv' [419] [420] bn1în2 [421] x1b/c1 [422] ¦x2(n2în1)/c2 ¦ no, n1 and n2 might not be sorted in the same order [423] x2c2[n2âb/n1] ¦ we want same order as n1 [424] tx1†x2 [425] cx1,(ý2’t)x2 [426] dc,' ',' ',[1.5](b/n1) [427] d,' ',d ¦ add hidden column; Listview wants all vectors [428] k•wi 'AddRows' (0,1,d) [429] [430] •wi 'AutoFit' 'header' (2 3 4 5) [431] [432] f+/t0)/', ',(ôn),' Conflict') [436] '..st' •wi 'SetStatus' s [437] '..st' •wi '‘text' s ¦ because there is no GetStatus method [438] [439] ¦ ----- Ready to Show ----- [440] [441] •wself':' [442] [443] ¦k•wi 'Show' [444] [445] ¦ There is something squirrelly about this whole thing [446] ¦ I suspect because we are using an MDIForm rather than a normal Form [447] ¦ '#' •wi 'focus' ':fm0' ¦ this cannot be an MDIForm ! [448] ¦  And that doesn't even work! [449] [450] ¦  So do it the hard way [451] h•wi 'hwnd' [452] k•WCALL 'SetForegroundWindow' h [453] [454]  CMDWSCOMP 'GetAll' [455] [456] ':f.bnExit' •wi 'caption' 'E&xit' [457] ':f.bnExit' •wi 'onClick' "k':' •wi 'Close'" [458] [459] •wi 'pointer' 0 [460] [461] •wi 'onResize' e ¦ note after Show [462] [463] k•wi 'Wait' [464] 0 [465] [466] L9: ¦ ========== Callbacks ========== [467] [468] :SELECT W [469] [470] :CASE 'KeyPress' [471] [472] ¦ :if •warg=13 ¦ we don't need that because of 'keys' 13 [473] ¦ •wself is .lv [474] r•first •wi 'value' ¦ selected rowids [475] r0 ¦ might not be any row selected yet [476] •wi 'Event' ' CMDWSCOMP •wevent' 'DblClick' (,r) [477] [478] :CASE 'DblClick' [479] [480] r1•warg ¦ rowid [481] r0 ¦ might be a blank row [482] p•wi '‘pane' ¦ 1=left 0=center 2=right [483] :if p=0 [484] (c m),•wi 'GetCells' r (2 5) ¦ class name [485] (c m) CMDWSCOMP 'Diff' [486] :else [487] s•wi '‘server' [488] (c m),•wi 'GetCells' r (2 3) ¦ class name [489] (s c m) CMDWSCOMP 'Peek' [490] :end [491] [492] :CASE 'ColClick' [493] [494] c1•warg ¦ column clicked [495] i•wi 'sortorder' ¦ all rowids [496] d,•wi 'GetCells' i c ¦ data [497] ¦ dô•enlistd ¦! bug workaround ¦ just make sure all cells are vectors [498] m[2]d ¦ simple char matrix [499] a'ì',•AV ¦ make ì sort before  [500] ¦! and • before A? But that's not the way ]ordloc does it [501] dam [502] :if dðâûd ¦ already sorted? [503] ¦dèd ¦ no! this reverses other cols too [504] dam ¦ descending [505] :end [506] •wi 'sortorder' (i[d]) [507] [508] :CASE 'Peek' [509] [510] ¦ •wself is a Listview [511] [512] (s c m)G ¦ server class name [513] [514] (g x t)(s c m) CMDWSCOMP 'Fetch' ¦ global value timestamp [515] [516] :if ~g [517] :if c='' [518] a'Shadowed variable' [519] :else [520] a'Shadowed function' [521] :end [522] ':f.l' •wi 'caption' a [523] k•wcall 'MessageBeep' 0 ¦ ding [524] 0 [525] :end [526] [527] :if c†'' ¦ function [528] :andif 0=ûx [529] ':f.l' •wi 'caption' 'Locked function' [530] k•wcall 'MessageBeep' 0 ¦ ding [531] 0 [532] :end [533] [534] :if c='' ¦ variable [535] :if (ðx)>1 [536] :orif (ûûx)>2 [537] :orif ^/0 ' 'î•TYPE •enlist x [538] x•UCMD 'DISPLAY x' ¦ I guess this is better than an error from )edit [539] :end [540] k "p ",m ¦! we cannot peek at anything named p [541] kk, "k•WCALL 'W_Edit' (,'",m,"')" ¦õ k ¦ W_Edit fails if arg is scalar [542] k•DEF [2] k ¦õ p [543] p x [544] :else [545] k "p x;",m ¦! we cannot peek at anything named p or x or k [546] kk, "k•DEF x" ¦õ k x [547] kk, "k•WCALL 'W_Edit' (,'",m,"')" ¦õ k ¦ W_Edit fails if arg is scalar [548] k•DEF [2] k ¦õ p [549] p x [550] :end [551] [552] :CASE 'Shutdown' [553] [554] sG [555] ¦ server: 0 means active ws, >0 means saved ws, <0 means ucmd file [556] •funtie (s<0)/þs ¦ untie ucmd files [557] :for i :in (s>0)/s [558] w'wseWsComp',ôi ¦ server name [559] :if ’ûw •wi 'self' [560] w •wi 'xVisible' 0 ¦ so we don't get warning [561] w •wi 'Delete' [562] :end [563] :end [564] [565] :CASE 'Close' [566] [567] s•wi '‘servers' [568] s CMDWSCOMP 'Shutdown' ¦ shut down servers [569] [570] ¦ Set value of key k in APLW.INI section [UCMDSREX] [571] k•fx [2] 'k i v;z' "z•wcall 'W_Ini' ('[UCMDSREX] ',k,'=',ôv)" ¦õ i [572] [573] 'WsComp-Place' i •wi 'place' [574] 'WsComp-Visible' i •wi 'visible' [575] [576] :if ~''ð'fmDIFF_AM' •wi 'self' ¦ if the Timer form exists [577] k'fmDIFF_AM.tm' •wi 'Delete' ¦ stop ticking [578]  CMDWSCOMP '::' ¦ simulate one final tick [579] :end [580] [581] '#' •wi 'Defer' "'mdiWsComp' •wi 'Delete'" [582] [583] :CASE 'DropDown' [584] [585] ¦ •wself is a Form (not the MDIForm); can't tell which menu item was clicked [586] p•wi '‘pane' ¦ 1 0 2 [587] •wself':mActions' [588] [589] '.mDiff' •wi 'enabled' (pî 0 ) [590] '.mPeekL' •wi 'enabled' (pî1 0 ) [591] '.mPeekR' •wi 'enabled' (pî 0 2) [592] '.mPeek' •wi 'enabled' (pî1 2) [593] [594] :CASE 'Click' [595] [596] a•warg [597] (2†7a)û0 ¦ quit unless right button (row selection has already been toggled) [598] r1a ¦ pointed-to rowid [599] r0 ¦ quit if empty row [600] [601] Assert 'Listview'ð•wi 'class' [602] v•wi 'value' ¦ selected row(s) [603] p•wi '‘pane' ¦ 1=left 0=center 2=right [604] s':' •wi '‘servers' ¦ 0 active ws >0 saved ws <0 ucmd file [605] [606] f•wself [607] m'mWsCompPopup' [608] •wselfm •wi 'Create' 'Menu' [609] :if p=0 [610] k'.m1' •wi 'New' 'Menu' ('caption' 'Diff') ('onClick' "•wi ':data' 1") [611] k'.m2' •wi 'New' 'Menu' ('caption' 'Peek Left') ('onClick' "•wi ':data' 2") [612] k'.m3' •wi 'New' 'Menu' ('caption' 'Peek Right') ('onClick' "•wi ':data' 3") [613] :else [614] k'.m4' •wi 'New' 'Menu' ('caption' 'Peek') ('onClick' "•wi ':data' 4") [615] :end [616] [617] k'.s1' •wi 'New' 'Menu' ('separator' 1) [618] [619] k'.m5' •wi 'New' 'Menu' ('caption' 'Select All') ('onClick' "•wi ':data' 5") [620] [621] e'Copy Name',(1=ûv)'s to Clipboard' [622] k'.m6' •wi 'New' 'Menu' ('caption' e) ('onClick' ("•wi ':data' ",ô6+p>0)) ¦ 6 or 7 [623] [624] e' selected object',(1=ûv)'s into Active Ws' [625] :if p=0 [626] k'.s2' •wi 'New' 'Menu' ('separator' 1) [627] :if s[1]†0 [628] k'.m8' •wi 'New' 'Menu' ('caption' (')COPY Left version of',e)) ('onClick' "•wi ':data' 8") [629] :end [630] :if s[2]†0 [631] k'.m9' •wi 'New' 'Menu' ('caption' (')COPY Right version of',e)) ('onClick' "•wi ':data' 9") [632] :end [633] :else ¦ left or right pane [634] :if s[p]†0 ¦ unless this IS the active ws... [635] k'.s2' •wi 'New' 'Menu' ('separator' 1) [636] k'.m7' •wi 'New' 'Menu' ('caption' (')COPY',e)) ('onClick' ("•wi ':data' ",ô7+p)) ¦ 8 or 9 [637] :end [638] :end [639] [640] •wselff [641] [642] ':' •wi 'Popup' m 2 ¦ 2=make the menu respond to the right mouse button [643] dm •wi 'data' [644] m •wi 'Delete' [645] d0 ¦ 0=escape [646] d CMDWSCOMP 'Actions' [647] [648] :CASE 'mActions' [649] [650] •wself':' •wi 'activeform' [651] •wself'.lv' [652] G CMDWSCOMP 'Actions' [653] [654] :CASE 'Actions' [655] [656] ¦ •wself is a Listview [657] s':' •wi '‘servers' [658] v•wi 'value' ¦ selected row(s) [659] r•first v ¦ selected row [660] r0 [661] [662] :select G [663] :case 1 ¦ diff [664] (c m),•wi 'GetCells' r (2 5) ¦ class name [665] (c m) CMDWSCOMP 'Diff' [666] :case 2 ¦ peek left [667] (c m),•wi 'GetCells' r (2 5) ¦ class name [668] c1c [669] (s[1] c m) CMDWSCOMP 'Peek' [670] :case 3 ¦ peek right [671] (c m),•wi 'GetCells' r (2 5) ¦ class name [672] cý1c [673] (s[2] c m) CMDWSCOMP 'Peek' [674] :case 4 ¦ peek [675] s•wi '‘server' [676] (c m),•wi 'GetCells' r (2 3) ¦ class name [677] (s c m) CMDWSCOMP 'Peek' [678] :case 5 ¦ select all [679] i•wi 'sortorder' [680] •wi 'value' i [681] :case 6 ¦ copy center [682] m,•wi 'GetCells' v 5 ¦ names [683] m1•enlist ' ',m [684] m CMDWSCOMP 'SetClip' [685] :case 7 ¦ copy left/right [686] m,•wi 'GetCells' v 3 ¦ names [687] m1•enlist ' ',m [688] m CMDWSCOMP 'SetClip' [689] :case 8 ¦ )copy left [690] (s[1] v) CMDWSCOMP ')COPY' [691] :case 9 ¦ )copy right [692] (s[2] v) CMDWSCOMP ')COPY' [693] :else ¦ tilt [694] ö0 [695] :end [696] [697] :CASE ')COPY' [698] [699] (s v)G [700] p•wi '‘pane' ¦ 1=left 0=center 2=right [701] :if p=0 ¦ center pane [702] c5 [703] :else [704] c3 [705] :end [706] m,•wi 'GetCells' v c ¦ names [707] dý1ú.†ý1[2] •idloc [2] m ¦ shadowed? [708] :if ú/d [709] •'*** Shadowed:',ôd/m [710] m(~d)/m [711] (ûm)0 [712] :end [713] [714] Assert s†0 [715] [716] :if s>0 ¦ saved ws [717] ws•wi ':‘W' ¦ wsid [718] r([2]m) •COPY w [719] :for i :in âûm [720] k'*** •COPY of <',(im),'> failed, ' [721] :select r[i] [722] :case 1  •'Function <',(im),'> copied' [723] :case 2  •'Variable <',(im),'> copied' [724] :case 0  •k,'Object not found' [725] :case 127  •k,'Duplicate name in objlist ¦ should not get here!' [726] :case ý2  •k,'Object too large for available space' [727] :case ý3  •k,'Name defined as a label; cannot be changed' [728] :case ý4  •k,'Insufficient space in symbol table and workspace too full to expand symbol table' [729] :case ý6  •k,'Insufficient free space to carry out command' [730] :else  ö0 [731] :end [732] :end [733] :else ¦ s<0 means ucmd file [734] tþs ¦ tie number [735] i•FREAD t,2 ¦ pointers to directories [736] s•FREAD t,i[2] ¦ char directory of objects (names) [737] n•FREAD t,i[3] ¦ num directory of objects (nc, comp) [738] :for j :in âûm [739] bjm ¦ object name [740] i(s^.=(ý1ûs)b)â1 ¦ find name [741] x•FREAD t,n[i;2] ¦ read value [742] •erase b ¦ in case of class change [743] :if 2=n[i;1] ¦ •NC [744] õb,'x' [745] •'Variable <',b,'> defined' [746] :else [747] k•DEF x [748] :if kðb [749] •'Function <',b,'> defined' [750] :else [751] •'*** Problem defining function <',b,'>: ',ôk [752] :end [753] :end [754] :end [755] :end [756] [757] :CASE 'Copy' [758] [759] •wself':' •wi 'activeform' [760] •wself'.lv' [761] p•wi '‘pane' ¦ 1=left 0=center 2=right [762] :if p=0 ¦ center pane [763] c5 [764] :else [765] c3 [766] :end [767] i•wi 'sortorder' ¦ all rowids [768] m,•wi 'GetCells' i c [769] [770] mý2•enlist m, •tcnl,•tclf [771] [772] m CMDWSCOMP 'SetClip' [773] [774] :CASE 'SetClip' [775] [776] GñAV2ANSI[•AVâG] [777] h•wcall 'GlobalAlloc' 'GMEM_MOVEABLE' (1+•first ûG) [778] •error (h=0)/'Unable to allocate memory for copy' [779] p•wcall 'GlobalLock' h [780] •error (p=0)/'Unable to lock memory for copy' [781] k•wcall 'W_Mem' (p,0,1, G,•tcnul) [782] k•wcall 'GlobalUnlock' h [783] w'#' •wi 'hwndmain' [784] •error (0=•wcall 'OpenClipboard' w)/'Clipboard busy' [785] k•wcall 'EmptyClipboard' [786] k•wcall 'SetClipboardData' 'CF_TEXT' h [787] k•wcall 'CloseClipboard' [788] [789] :CASE 'GetWs' [790] [791] (n W F)G ¦ arg number, args, filter [792] wnW [793] c1=ûûw ñGETOPT '/F' ¦ ucmd file? [794] wDEB (^\w†'/')/w ¦ delete all options [795] [796] :if wð'' [797] R(n w F) CMDWSCOMP 'GetAws' ¦ active ws [798] 0 [799] :elseif c ¦ ucmd file [800] R(n w F) CMDWSCOMP 'GetUfile' [801] 0 [802] :end [803] [804] ¦ It's a wsid [805] e'wseWsComp',ôn ¦ server name [806] :if ''ðe •wi 'self' [807] •wselfe •wi 'New' 'APLW.WSEngine' ('xVisible' 0) [808] :else [809] •wselfe [810] :end [811] r("•CHDIR '",(•chdir''),"'") CMDWSCOMP 'XExec' [812] r('••WSID' ) CMDWSCOMP 'XExec' [813] r(')XLOAD ',w ) CMDWSCOMP 'XExec' [814] ¦ RHS 10/31/05 the )RESET attempt hangs if done with CMDWSCOMP 'XExec' and the [815] ¦ state indicator is not empty! )RESET must be the very first thing done. [816] r•wi 'XExec' ')RESET' [817] k•wi 'XExec' '•" )RESET"' [818] r('••WSID' ) CMDWSCOMP 'XExec' [819] :if rð'' ¦ in a clear ws, •WSIDð'' [820] •'*** Failed: )XLOAD ',w [821] •" '",e,"' •wi 'xVisible' 1 ¦ to see why" [822] R5û0 [823] 0 [824] :end [825] wDEB r ¦ APL's way of saying wsid [826] •'Loaded ',w [827] ¦r')RESET' CMDWSCOMP 'XExec' ¦ clear SI stack ¦ RHS 10/31/05 commented out; see above [828] [829] m'•NL 2 3' CMDWSCOMP 'XExec' ¦! a character matrix comes back as a nested vector!!! [830] Assert 1=ûûm [831] mm~' ' ¦ DTB [832] c'•NC •NL 2 3' CMDWSCOMP 'XExec' [833] Assert 1=ûûc [834] Assert ^/cî2 3 ¦ since we cleared stack, cannot be labels [835] [836] ¦ ¦s'•ALX' '•CT' '•ELX' '•IO' '•LX' '•PP' '•RL' '•SA' '•WATCHPOINTS' ¦ interesting system vars [837] ¦ ¦  •WATCHPOINTS made XExec fail on laptop 11/04; others are boring [838] s'•ALX' '•ELX' '•IO' '•LX' '•PP' ¦ interesting system vars [839] ¦ i•IDLOC [2] s [840] ¦ ii[;•first ý1ûi] [841] ¦ cc,i [842] mm,s [843] cc,(ûs)û2 [844] [845] c':ì'[c] [846] [847] bcîF ¦ fns/vars filter [848] cb/c [849] mb/m [850] [851] R1 n w c m ¦ OK, server number, •wsid, classes, names [852] [853] :CASE 'XExec' [854] [855] xG ¦ expression to execute [856] k•wi 'XExec' ('•" ',x,'"') [857] R•wi 'XExec' x [858] [859] :CASE 'GetAws' [860] [861] ¦ Get list of globals in active ws [862] ¦ Some may be shadowed, but at least we know they exist [863] [864] (n w F)G ¦ arg number, arg, filter [865] [866] ¦m1(•IT 'SymbolTable')[;1] ¦ requires APL+Win version 5 [867] [868] s•SINL [869] s(~s[;1]î'õ•><')ës ¦ no local names at these levels [870] s(,ú\s=' ')/,s ¦ discard FOO[3], keep names to the right [871] sWords s ¦ all localized names [872] ss~ ,'*' ¦ the asterisk next to suspended fn is not a name [873] ¦ Avoid picking up system vars (ñUCMD2 localizes •PW and •CT) [874] s('•'†•firsts)/s [875] [876] ¦v'•ALX' '•CT' '•ELX' '•IO' '•LX' '•PP' '•RL' '•SA' '•WATCHPOINTS' ¦ interesting system vars [877] ¦  •WATCHPOINTS made XExec fail on laptop 11/04; others are boring [878] v'•ALX' '•ELX' '•IO' '•LX' '•PP' ¦ interesting system vars [879] [880] m•IDLIST 1+2+8 ¦ all visible names [881] mWords m [882] [883] mm,s,v [884] m((mâm)=âûm)/m [885] [886] m[2] m [887] c•IDLOC m ¦ what are they [888] cc[;•first ý1ûc] ¦ global definition [889] bc†0 ¦ flag those with any global definition [890] mbëm [891] cb/c [892] Assert ^/cî1 2 ¦ since we are looking at global definitions, cannot be labels [893] c'ì34567:'[c] [894] i•AVm [895] mm[i;] [896] cc[i] [897] mWords m [898] [899] bcîF ¦ fns/vars filter [900] cb/c [901] mb/m [902] [903] R1 0 'Active WS' c m ¦ OK, server number, •wsid, classes, names [904] [905] :CASE 'GetUfile' [906] [907] (n w F)G ¦ arg number, args, filter [908] Ww ¦ save an unmolested copy for result [909] R5û0 ¦ pessimist [910] [911] ¦ Tie the freakin' file (what a pain this is in APL+Win!) [912] t•FNUMS,•XFNUMS [913] t((âût)ît)â0 [914] ¦ Try for a vanilla •fstie [915] e•elx [916] •elx'',ôL1 [917] w •fstie t [918] L5 [919] L1: [920] •elxe [921] ('.'îw)ûL4 ¦ already in extended format? [922] wWords w [923] (2=ûw)ûL2 ¦ two words? [924] b•CHDIR '' ¦ use current directory as library [925] w1w [926] L3 [927] L2: [928] b•LIBD •FI 1w ¦ first word is library number [929] :if bð'' [930] •'Library ',(1w),' definition not found' [931] 0 [932] :end [933] w2w [934] L3: [935] bb,((ý1b)î'\:')'\' ¦ force trailing backslash, unless 'D:' [936] wb,w,'.sf' [937] L4: [938] •elx'•(^\•DM†•TCNL)/•DM  0' [939] w •XFSTIE t [940] L5: [941] •elxe [942] ¦ Right, then -- that was easy! [943] [944] :if ~1î'User-defined commands file'•enlist •FREAD t,1 ¦ first comp should have signature [945] •'Not a user command file: ',W [946] 0 [947] :end [948] [949] i•FREAD t,2 ¦ pointers to directories [950] s•FREAD t,i[2] ¦ char directory of objects (names) [951] n•FREAD t,i[3] ¦ num directory of objects (nc, comp) [952] ¦ •wi ('#.‘WsComp',ôt) (s n) ¦ could save dirs for future reference [953] c' ì?'[n[;1]] [954] bcîF ¦ fns/vars filter [955] cb/c [956] sbës [957] i•AVs [958] ss[i;] [959] cc[i] [960] sWords s [961] R1 (-t) W c s ¦ OK, server number, filename, classes, names [962] [963] :CASE 'Only' [964] [965] •wi 'value' 1 ¦ check the one we're doing [966] (•wi 'siblings') •wi 'enabled' 0 ¦ but can't do this again [967] [968] :for •wself :in ':fm1.lv' ':fm0.lv' ':fm2.lv' [969] a•wi 'sortorder' ¦ all row ids [970] c,•wi 'GetCells' a 2 ¦ class [971] a(~1îcî G)/a [972] •wi 'DeleteRows' a [973] :end [974] [975] :CASE 'fmResize' [976] [977] t3•warg ¦ height width state [978] (tî1 2)û0 ¦ minimized or maximized? don't bother doing anything [979] p•wi '‘pane' [980] w•wi 'where' [981] z•wi 'size' [982] '.lv' •wi 'where' (0 0,z) [983] :select p [984] [985] :case 1 ¦ left [986] [987] e+/w[2 4] ¦ right side [988] •wself'..fm0' [989] h•wi 'where' [990] d+/h[2 4] ¦ right side [991] h[2 4]e,0d-e [992] •wi 'where' h [993] '.lv' •wi 'where' (0 0,•wi 'size') [994] [995] :case 2 ¦ right [996] [997] ew[2] ¦ left side [998] •wself'..fm0' [999] h•wi 'where' [1000] dh[2] ¦ left side [1001] h[4]0e-d [1002] •wi 'where' h [1003] '.lv' •wi 'where' (0 0,•wi 'size') [1004] [1005] :case 0 ¦ center [1006] [1007] ew[2] ¦ left side [1008] •wself'..fm1' [1009] h•wi 'where' [1010] dh[2] ¦ left side [1011] h[4]0e-d [1012] •wi 'where' h [1013] '.lv' •wi 'where' (0 0,•wi 'size') [1014] [1015] e+/w[2 4] ¦ right side [1016] •wself'..fm2' [1017] h•wi 'where' [1018] d+/h[2 4] ¦ right side [1019] h[2 4]e,0d-e [1020] •wi 'where' h [1021] '.lv' •wi 'where' (0 0,•wi 'size') [1022] [1023] :end [1024] [1025] :CASE 'Resize' [1026] [1027] z•wi 'size' [1028] h•wi '‘h' [1029] [1030] cz-h 0 ¦ client size [1031] •wi 'clientwhere' (0,0,c) [1032] [1033] •wself':f' [1034] w•wi 'where' [1035] w[1]c[1] ¦ move [1036] w[4]z[2] ¦ fix width [1037] •wi 'where' w [1038] [1039] •wself'.bnExit' [1040] w•wi 'where' [1041] dw[4] ¦ button width [1042] w[2]z[2]-d+0.5 ¦ move [1043] •wi 'where' w [1044] [1045] •wself'..l' [1046] w•wi 'where' [1047] w[4]z[2]-d+2 ¦ fix width [1048] •wi 'where' w [1049] [1050] f':fm1' ':fm0' ':fm2' [1051] d4f •wi 'where' ¦ widths [1052] dz[2]’dö+/d ¦ allocate [1053] p+\0,d [1054] :for i :in â3 [1055] •wselfif [1056] •wi 'suppress' 1 [1057] w0,p[i],c[1],d[i] [1058] •wi 'where' w ¦ this would trigger fmResize, which is a bit of overkill [1059] '.lv' •wi 'where' (0 0,•wi 'size') [1060] •wi 'suppress' ý1 [1061] :end [1062] [1063] :CASE 'GetAll' [1064] [1065] •wself':fm0.lv' [1066] [1067] d•wi 'sortorder' ¦ all rowids [1068] n•first ûd [1069] :if n>0 ¦ they might not have ANYthing in common [1070] [1071] m•wi 'GetCells' d (2 5) ¦ class, name [1072] [1073] ':f.pb' •wi 'value' 0 n 1 0 ¦ fails if n=0 [1074] [1075] x(n,2)û' ' [1076] s':' •wi '‘servers' [1077] [1078] :for i :in ân [1079] •wgive 0 [1080] [1081] :if ':' •wi '‘stop' [1082] :leave [1083] :end [1084] [1085] 'mdiWsComp.f.pb' •wi 'Stepit' [1086] [1087] (c j)m[i;] ¦ class, object name [1088] [1089] :if (ûc)>1 ¦ different classes [1090] [1091] w'' [1092] e'*' [1093] [1094] :else ¦ same class [1095] [1096] (g1 x1 t1)((s[1]) c j) CMDWSCOMP 'Fetch' [1097] (g2 x2 t2)((s[2]) c j) CMDWSCOMP 'Fetch' [1098] [1099] ¦ Do they match? [1100] [1101] :if g1êg2 ¦ shadowed? [1102] e'?' [1103] :elseif c='' [1104] e'~ð'[1+x1ðx2] [1105] :else ¦ ì [1106] a’(ûx1),ûx2 [1107] :if ^/a [1108] ¦e'~ð'[1+x1ðx2] ¦ RHS 2/03/08 distinguish between ð and = [1109] :if x1ðx2 [1110] e'ð' [1111] :elseif (DTBVR x1)ð(DTBVR x2) [1112] e'=' [1113] :else [1114] e'~' [1115] :end [1116] :else ¦ one or both fns locked [1117] e'?' [1118] c(1+2æa)  '' 'ì ' ' ì' 'ì' [1119] •wi 'SetCells' (id) 2 (,c) [1120] :end [1121] :end [1122] [1123] ¦ Compare timestamps [1124] ¦ Note that timestamps could be same even when one is locked and the other isn't [1125] [1126] :if ''îc [1127] w'' [1128] :else [1129] :if g1êg2 ¦ shadowed? [1130] w'?' [1131] :else [1132] a0 13 32 24 60 60 1000æt2,[1.5]t1 [1133] w(2+’-/a)  '® ' ' = ' ' ¯' [1134] :end [1135] :end [1136] [1137] :end [1138] [1139] ¦  This caused some screen chatter [1140] ¦'mdiWsComp.fm0.lv' •wi 'SetCells' (d[i]) (3 4) (w e) [1141] [1142] x[i;]w e [1143] [1144] :end [1145] [1146] •wi 'SetCells' d (3 4) (,x) [1147] [1148] xx[;2] [1149] :if '?'îx [1150] •'Note: Shadowing can be avoided by using a saved version of the active ws' [1151] :end [1152] ¦ex='ð' [1153] exî'=ð' [1154] m+/e ¦ match [1155] dn-m ¦ don't match [1156] s'..st' •wi '‘text' ¦ because there is no GetStatus method [1157] ss,'; ',((d=0)/'All '),(ôm),' Match',(d>0)/', ',(ôd),' Don''t' [1158] '..st' •wi 'SetStatus' s [1159] [1160] ¦ Move non-matching names to top of list [1161] :if d>0 [1162] ¦•wi 'sortorder' (e) [1163] •wi 'sortorder' (4þ'~=ð'âx) [1164] :end [1165] [1166] :end [1167] [1168] ':f.pb' •wi 'Delete' [1169] [1170] :CASE 'Select' [1171] [1172] v•wi 'value' ¦ selected rowids [1173] v•first v [1174] v0 [1175] p•wi '‘pane' ¦ 1=left 0=center 2=right [1176] s•wi '‘server' ¦ 0=activews 1 2 [1177] d•TCBS,•TCNL,•TCLF,•TCBEL,•TCDEL,•TCESC,•TCFF,•TCHT,•TCNUL [1178] [1179] :if p=0 ¦ center pane [1180] [1181] (c m),•wi 'GetCells' v (2 5) [1182] s':' •wi '‘servers' [1183] :if (ûc)>1 ¦ different classes! [1184] cc~' ' [1185] Assert 2=ûc [1186] a'' [1187] :for i :in â2 [1188] aa,•tcnl [1189] (g x t)((s[i])(c[i])m) CMDWSCOMP 'Fetch' [1190] :if c[i]='' [1191] :if g [1192] aa,m,'',200 FFAW x [1193] :else [1194] aa,'Shadowed variable' [1195] :end [1196] :else ¦ ì [1197] :if g [1198] :if ’ûx [1199] xDLB (200ûx)ûx [1200] x[(xîd)/âûx]'©' [1201] aa,x [1202] :else [1203] aa,'Locked function' [1204] c[i]'' [1205] •wi 'SetCells' v 2 (1 0 1\c) [1206] :end [1207] :else [1208] aa,'Shadowed function' [1209] :end [1210] :end [1211] :end [1212] a1a [1213] :else ¦ same class [1214] a'' [1215] :for i :in â2 [1216] aa,•tcnl [1217] (g x t)((s[i]) c m) CMDWSCOMP 'Fetch' [1218] :if c='' [1219] :if g [1220] aa,m,'',200 FFAW x [1221] :else [1222] aa,'Shadowed variable' [1223] :end [1224] :else ¦ ì [1225] :if g [1226] aa,,'I4,,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6ût [1227] :if ’ûx [1228] x(200ûx)ûx ¦ DLB? [1229] x[(xîd)/âûx]'©' [1230] aa,x [1231] :else [1232] aa,'Locked function' [1233] c[i]'' [1234] •wi 'SetCells' v 2 (1 0 1\c) [1235] :end [1236] :else [1237] aa,'Shadowed function' [1238] :end [1239] :end [1240] :end [1241] a1a [1242] :end [1243] [1244] :else ¦ left or right pane [1245] [1246] (c m),•wi 'GetCells' v (2 3) [1247] (g x t)(s c m) CMDWSCOMP 'Fetch' ¦ global value timestamp [1248] :if c='' [1249] :if g [1250] a'Depth ',ôðx [1251] aa,'  Shape ',(ôûx),(0=ûûx)/'' [1252] aa,'  Size ',ô•size 'x' [1253] aa,•tcnl [1254] aa,m,'',200 FFAW x [1255] :else [1256] a'Depth ?  Shape ?  Size ?' [1257] aa,•tcnl [1258] aa,'Shadowed variable' [1259] :end [1260] :else ¦ ì [1261] :if g [1262] :if ’ûx [1263] a'Lines ',ôý2++/x=•tcnl [1264] :else [1265] a'Lines ?' [1266] :end [1267] aa,'  Timestamp ',,'I4,,ZI2,,ZI2,< >,ZI2,<:>,ZI2,<:>,ZI2' •fmt 1 6ût [1268] aa,•tcnl [1269] ¦  Don't use FFA -- we don't want quote treatment [1270] :if ’ûx [1271] xDLB (200ûx)ûx [1272] x[(xîd)/âûx]'©' [1273] aa,x [1274] :else [1275] aa,'Locked function' [1276] •wi 'SetCells' v 2 (,'') [1277] :end [1278] :else [1279] a'Lines ?  Timestamp ?' [1280] aa,•tcnl [1281] aa,'Shadowed function' [1282] :end [1283] :end [1284] [1285] :end [1286] [1287] ':f.l' •wi 'caption' a [1288] [1289] :CASE 'Fetch' [1290] [1291] (s c m)G ¦ server class name [1292] [1293] ¦ shadowed: R  0   [1294] ¦ function: R  1 vr timestamp [1295] ¦ variable: R  1 value  [1296] [1297] :if s=0 ¦ active ws [1298] :if ý1ú.†ý1,•idloc m ¦ shadowed [1299] R0   [1300] :elseif c='' [1301] xõm [1302] R1 x  [1303] :else ¦ ì [1304] x•VR m [1305] t2 •AT m [1306] R1 x t [1307] :end [1308] :elseif s>0 ¦ saved ws [1309] s'wseWsComp',ôs [1310] :if c='' [1311] x'unwrapl' •DR s •wi 'XExec' ("'wrapl' •DR ",m) [1312] R1 x  [1313] :else ¦ ì [1314] xs •wi 'XExec' ( "•VR '",m,"'") [1315] ts •wi 'XExec' ("2 •AT '",m,"'") [1316] R1 x t [1317] :end [1318] :else ¦ s<0 means ucmd file [1319] tþs ¦ tie number [1320] i•FREAD t,2 ¦ pointers to directories [1321] s•FREAD t,i[2] ¦ char directory of objects (names) [1322] n•FREAD t,i[3] ¦ num directory of objects (nc, comp) [1323] i(s^.=(ý1ûs)m)â1 ¦ find name [1324] (c m)n[i;2 3] ¦ component, timestamp [1325] x•FREAD t,c ¦ read value [1326] mFTIMEREP m ¦ convert timestamp to •AT style [1327] R1 x m [1328] :end [1329] [1330] :CASE 'Fetch4Diff' [1331] [1332] ¦ Fetch just the raw value [1333] [1334] (s c m)G ¦ server class name [1335] [1336] :if s=0 ¦ active ws [1337] i,•idloc m [1338] :if ý1ú.†ý1i [1339] R'Shadowed ',(1 2 8â0æi)'function' 'variable' 'label' [1340] :elseif c='' [1341] Rõm [1342] :else ¦ ì [1343] R•CR m [1344] :if 0îûR [1345] R'Locked function' [1346] :end [1347] :end [1348] :elseif s>0 ¦ saved ws [1349] s'wseWsComp',ôs [1350] :if c='' [1351] R'unwrapl' •DR s •wi 'XExec' ("'wrapl' •DR ",m) [1352] :else ¦ ì [1353] R'unwrapl' •DR s •wi 'XExec' ("'wrapl' •DR •CR '",m,"'") ¦ need wrapl because •CR returns a matrix [1354] :end [1355] :else ¦ s<0 means ucmd file [1356] tþs ¦ tie number [1357] i•FREAD t,2 ¦ pointers to directories [1358] s•FREAD t,i[2] ¦ char directory of objects (names) [1359] n•FREAD t,i[3] ¦ num directory of objects (nc, comp) [1360] i(s^.=(ý1ûs)m)â1 ¦ find name [1361] R•FREAD t,n[i;2] ¦ read value [1362] :if c='ì' [1363] k•DEF [2] ('rp v;',m) 'r•CR •DEF v' ¦õ p ¦ convert •VR to •CR [1364] Rp R [1365] :end [1366] :end [1367] [1368] :CASE 'CaseSuffix' [1369] [1370] ¦ Encode capitalization of name G [1371] ¦ Assumes ‘ and ñ have already been converted to + and +- [1372] [1373] ¦ If we want two files 'FOO' and 'Foo' in the same directory, then we need [1374] ¦ to make them different somehow. We will append a suffix so they become [1375] ¦ 'FOO.0' and 'Foo.c'. We don't need to be able to reverse this process [1376] ¦ since Windows preserves the casing of file names. [1377] [1378] c'0123456789abcdefghijklmnopqrstuv' ¦ suffix alphabet [1379] w2ûc ¦ bits per alpha (5) [1380] n(ûG)öw ¦ how many suffix chars do we need? [1381] bG†ñUCASE G ¦ flag lower case letters [1382] Rc[1+2æí(n,w)û(n’w)b] [1383] [1384] :CASE 'Diff' [1385] [1386] ¦ (c m)G ¦ classes name [1387] ¦ w':' •wi '‘W' ¦ wsids [1388] ¦ dDEB (1w),' ',m,' ; ',(2w),' =' [1389] ¦ •UCMD •' ]DIFF ',d [1390] [1391] (c m)G ¦ classes name [1392] c(1c),ý1c [1393] w':' •wi '‘W' ¦ wsids [1394] s':' •wi '‘servers' [1395] [1396] D•first /•wcall 'GetModuleFileName' '' (255û•tcnul) 255 ¦ C:\APLWin50\aplw.exe [1397] D(èú\èD='\')/D ¦ C:\APLWin50\ [1398] D(D,'Diff1\') (D,'Diff2\') ¦ C:\APLWin50\Diff1\ C:\APLWin50\Diff2\ [1399] F2û '' ¦ APL file names [1400] S2û '' ¦ ANSI file names [1401] Cc ¦ classes [1402] [1403] :for i :in â2 [1404] [1405] x((is) (ic) m) CMDWSCOMP 'Fetch4Diff' [1406] [1407] k(82=•DR x)’ûûx ¦ rank if simple char [1408] xôx ¦ force simple char [1409] [1410] fm,' [',(iw),']' ¦ append wsid [1411] f[(fî'\:/')/âûf]' ' ¦ in case of path [1412] fDEB f [1413] ff,(c[i]='')/'.',ôk ¦ rank if simple character vector or matrix, 0 otherwise [1414] ff,('ì'âc[i])'.var' '.fn' [1415] [1416] ¦ •(iF),f ¦ display the file name (for ]DEF) before fixing deltas [1417] (iF)(iD),f ¦ file name (for ]DEF or ]ASSIGN) before fixing deltas [1418] [1419] ((f='•')/f)'#' ¦ might be a system variable [1420] ((f='‘')/f)'+' ¦ fyi, WSIDs can contain ‘ and ñ symbols! [1421] ((f='ñ')/f)•AV[178] ¦ that's the plus-or-minus symbol [1422] (iS)(iD),f ¦ save the ANSI version of the file name [1423] [1424] xñAV2ANSI[•AVâx] ¦ translate [1425] x ñNFILE iS ¦ write the file [1426] [1427] :end [1428] [1429] ¦ ----- Below lifted directly from ìCMDDIFF (except for the onTimer expression) ----- [1430] [1431] f'aoDIFF_AM' [1432] [1433] :if ’ûf •wi 'self' [1434] :andif f •wi 'visible' [1435] [1436] ¦ Merge is already running [1437] [1438] •wselff [1439] •wi 'xActive' 0 [1440] •wi 'xActive' 1 ¦ make it the active app (thanks, Patrick!) [1441] [1442] :else [1443] [1444] ¦ Create new Merge object [1445] [1446] •wselff •wi 'Create' E ¦ 'ActiveObject Merge65.Application' [1447] [1448] ¦ Araxis Merge never starts maximized when invoked via ActiveX, even if you [1449] ¦ have the "Maximize application on start-up" option checked. We can look at [1450] ¦ the AM preferences, but only after AM starts -- and if we maximize it then, [1451] ¦ you'll see the maximization happening. Oh well. [1452] [1453] •wi 'Preferences > .prefs' [1454] '.prefs' •wi 'Longs > .longs' [1455] e'.prefs.longs' •wi 'xItem' 'clAppMax' [1456] :if e [1457] •wi 'xMaximized' e ¦ maximize the app (if belatedly) [1458] :end [1459] [1460] ¦ Set APL fonts [1461] [1462] ¦ Get value of key k from APLW.INI section [UCMDSREX]; default to d [1463] k•ex 'G' [1464] k•fx [2] 'vk G d;z' "v•wcall 'W_Ini' ('[UCMDSREX] ',k)  (vð'')0  vd" ¦õ G [1465] [1466] tñUCASE 'FontName' G 'APLFONT' [1467] z1•fi 'FontSize' G '11' [1468] [1469] :if tð'APLFONT' [1470] :orif tð'APLCODE' [1471] ¦ Symbol font (so something like "11.APLFONT" won't work) [1472] h•wcall 'GetDC' 0 ¦ handle of device context of display [1473] i•wcall 'GetDeviceCaps' h 'LOGPIXELSY' ¦ pixels per vertical logical inch [1474] z0.5+(z’i)ö72 ¦ height [1475] z'-',ôz ¦ negative means character height (as opposed to cell height) [1476] tz,',0,0,0,400,0,0,0,255,1,2,1,49,',t [1477] ¦ or, use WChooseFont '' in the TOOLS\WINDOWS workspace to get a logfont spec [1478] :else [1479] ¦ TrueType font [1480] t(ôz),'.',t ¦ e.g., '12.APLHELP' [1481] :end [1482] [1483] '.prefs' •wi 'Strings > .strings' [1484] I 'csUnchangedFont' 'csChangedFont' 'csInsertedFont' 'csRemovedFont' ¦ left window [1485] II,'csUnchangedFont2' 'csChangedFont2' 'csInsertedFont2' 'csRemovedFont2' ¦ right panel [1486] :for i :in I [1487] '.prefs.strings' •wi 'xItem' i t [1488] :end [1489] [1490] ¦ Save method: Saves preferences to the Registry, and propogates them to [1491] ¦ other running instances of Merge. Without this method, preferences are [1492] ¦ only saved to the Registry when Merge exits. [1493] [1494] '.prefs' •wi 'XSave' [1495] [1496] :end [1497] [1498] ¦ Initiate the file comparison [1499] [1500] •wi 'xFileComparison > .filecomp' [1501] '.filecomp' •wi 'xCompare' (1S) (2S) ¦ Compare! [1502] ¦ GiveUserControl: Gives control over the lifetime of the comparison window to [1503] ¦ the user. Merge will not automatically close the window when outstanding [1504] ¦ automation references are released. [1505] '.filecomp' •wi 'xGiveUserControl' ¦ enables tabs for multiple comparisons [1506] '.filecomp' •wi 'xVisible' 1 [1507] •wi 'xVisible' 1 [1508] [1509] ¦ Maybe I should create more than one FileComparison object. [1510] ¦ Then could I tell when user does ]diff on the same object? [1511] [1512] f'fmDIFF_AM' [1513] :if ''ðf •wi 'self' [1514] •wselff •wi 'Create' 'Form' 'Hide' [1515] •wi '‘f' (0û '' '' ' ' (0 0)) ¦ ANSI file, APL file, class, timestamp [1516] m0 4û'' '' ' ' (0 0) ¦ ANSI file, APL file, class, timestamp [1517] •wi '‘h' ('#' •wi 'hwndmain') [1518] t"õ(('#' •wi 'hwndmain')=(•wcall 'GetActiveWindow'))/' CMDWSCOMP ''::'''" [1519] k'.tm' •wi 'New' 'Timer' ('interval' 500) ('onTimer' t) [1520] :else [1521] •wselff [1522] •wi 'Open' ¦ 5/08/06 make sure it's running [1523] m•wi '‘f' [1524] :end [1525] [1526] :for I :in â2 [1527] fIS [1528] h•wcall 'CreateFile' f 'GENERIC_READ' 'FILE_SHARE_READ' 0 'OPEN_EXISTING' 0 0 [1529] Assert h†•wcall 'W_Const' 'INVALID_HANDLE_VALUE' [1530] t•wcall 'GetFileTime' h    ¦ get create, access, write times [1531] Assert 0†•first t [1532] k•wcall 'CloseHandle' h [1533] t4t ¦ write time [1534] u~( f)îm[;1] [1535] muëm ¦ if file is already being compared, remove it [1536] mmžf (IF) (IC) t [1537] :end [1538] •wi '‘f' m [1539] [1540] [1541] [1542] :CASE '::' ¦ internal timer callback [1543] [1544] ¦ Bail unless we have returned to the APL session [1545] [1546] ¦  We now do this test in the onTimer expression to avoid •ucmd overhead [1547] ¦(('#' •wi 'hwndmain') = (•wcall 'GetActiveWindow'))0 [1548] [1549] ¦ Check for changed file timestamps [1550] [1551] F'fmDIFF_AM' •wi '‘f' [1552] :for I :in â1ûF [1553] (f a c w)F[I;] [1554] h•wcall 'CreateFile' f 'GENERIC_READ' 'FILE_SHARE_READ' 0 'OPEN_EXISTING' 0 0 [1555] Assert h†•wcall 'W_Const' 'INVALID_HANDLE_VALUE' [1556] t•wcall 'GetFileTime' h    ¦ get create, access, write times [1557] Assert 0†•first t [1558] k•wcall 'CloseHandle' h [1559] t4t ¦ write time [1560] :if ~tðw [1561] [1562] ¦ We're not going to ask again, regardless of answer [1563] F[I;4] t [1564] 'fmDIFF_AM' •wi '‘f' F [1565] [1566] V(~èú\èf='\')/f ¦ delete leading path [1567] BVî'[]' [1568] VDLTB(Bå†\B)/V ¦ delete leading [wsid] and trailing [f=] [1569] V(^\V†'.')/V ¦ delete trailing extension [1570] [1571] X'The timestamp on the file' [1572] XX,•TCNL,' ',f [1573] XX,•TCNL,'which contains ',(('ì'âc)'variable' 'function' 'file component') [1574] XX,•TCNL,' ',V [1575] XX,•TCNL,'has changed' [1576] XX,•TCNL [1577] :if cî'ì' [1578] XX,•TCNL,'Define changed object in active ws?' [1579] :else [1580] XX,•TCNL,'Replace changed array in file component?' [1581] :end [1582] [1583] h'#' •wi 'hwndmain' [1584] k•wcall 'MessageBox' h X 'DIFF' 'MB_ICONQUESTION MB_YESNOCANCEL' ¦ MB_DEFBUTTON2 [1585] :if k=6 ¦ 6=IDYES [1586] :if c='ì' [1587] •UCMD •']DEF ',a ¦ use APL file name -- DEF will translate [1588] :else ¦ cî'' [1589] •UCMD ']ASSIGN ',a [1590] :end [1591] :elseif k=7 ¦ 7=IDNO [1592] ¦ noop [1593] :else ¦ 2=IDCANCEL [1594] :leave [1595] :end [1596] :end [1597] :end [1598] [1599] ¦ If Merge has been closed, shut down monitoring [1600] [1601] f'aoDIFF_AM' [1602] :if ''ðf •wi 'self' ¦ somebody else deleted it [1603] :orif 0=f •wi 'visible' ¦ user closed it ¦ thanks, Patrick! [1604] ¦ Use of Defer solves localization problems with •wself [1605] '#' •wi 'Defer' "'fmDIFF_AM' •wi 'Delete'" [1606] '#' •wi 'Defer' "'aoDIFF_AM' •wi 'Delete'" [1607] :end [1608] [1609] [1610] [1611] :ELSE [1612] [1613] •'*** Unanticipated WSCOMP callback!' W •wself •wevent •warg [1614] [1615] :ENDSELECT [1616] ì SCO€àÿt6CÄ4Ä4 ì G CMDWSLI N;D;F;H;I;L;M;OB;OT;R;T;W;Z;a;b;c;d;e;f;h;i;k;m;n;r;t;v;w;x;z;•wself [1] ¦ ]WSLIB (but no trailing B) [2] [3] ¦ Syntax: [4] ¦ ]WSLI ¦ current drive/path (like •chdir '') [5] ¦ ]WSLI 5 ¦ only library number [6] ¦ ]WSLI 6 8 ¦ several library numbers [7] ¦ ]WSLI * ¦ all library numbers (from •LIBS) [8] [9] ¦ Options: [10] ¦ /B or /Z ¦ sort by Bytes / Size [11] ¦ /T ¦ sort by Timestamp [12] [13] ¦ 28 Nov 2007 Rex Swain, Independent Consultant, www.rexswain.com [14] ¦ 23 Dec 2007 Added "Load" action [15] [16] (’•NC 'G')ûL9 ¦ any left arg means callback [17] [18] Nô•enlist N ¦ arg could be numeric in development mode [19] [20] OT1=ûûN ñGETOPT '/T' ¦ sort by timestamp [21] OB 1=ûûN ñGETOPT '/B' ¦ sort by bytes [22] OBOBú1=ûûN ñGETOPT '/Z' ¦ or sort by size [23] [24] N(^\N†'/')/N ¦ delete all options [25] [26] :if '*'îN [27] N•FI,11[2]•LIBS ¦ RHS 1/27/04 if no libs are defined, 0 0ðû•LIBS [28] :else [29] N(•VI N)/•FI N [30] :end [31] [32] ¦ ----- Find workspaces ----- [33] [34] :if 0=ûN [35] D•CHDIR '' [36] DD,((ý1D)î'\:')'\' ¦ force trailing backslash, unless 'D:' [37] L [2] •WSLIB '' ¦ uses •chdir '' , sorts by wsid, and does not return library number [38] W( ''),( D),[1.5] L ¦ no library number [39] :else [40] W0 3û '' ¦ 1=lib 2=path 3=wsid [41] :for T :in N [42] :try [43] D•LIBD T [44] DD,((ý1D)î'\:')'\' ¦ force trailing backslash, unless 'D:' [45] L [2] 11[2] •WSLIB T [46] WWž ( ôT),( D),[1.5] L [47] :catchall [48] •((^\•DM†•TCNL)/•DM),' from library ',ôT [49] :end [50] :end [51] :end [52] [53] n1ûW [54] [55] :if n=0 [56] •'No workspaces found' [57] 0 [58] :end [59] [60] ¦ ----- Get size and timestamp for each ws ----- [61] [62] k•wcall 'W_Def' '[Call] GetFileSizeEx=B(H hFile,>ULARGE_INTEGER lpFileSize) LIB Kernel32' [63] [64] d•wcall 'W_Const' 'INVALID_HANDLE_VALUE' [65] [66] W5[2] W ¦ 4=size 5=modified [67] [68] :for I :in ân [69] [70] F,/W[I;2 3] [71] F(DTB F),'.W3' [72] [73] H•wcall 'CreateFile' F 'GENERIC_READ' 'FILE_SHARE_READ' 0 'OPEN_EXISTING' 0 0 [74] Assert H†d [75] [76] (R Z)•wcall 'GetFileSizeEx' H  ¦ return code and size [77] Assert R†0 [78] Z(2*32)æèZ [79] W[I;4]Z [80] [81] T•wcall 'GetFileTime' H    ¦ get create, access, write/modified times [82] Assert 0†•first T [83] T4T [84] [85] (R T)•wcall 'FileTimeToLocalFileTime' T  ¦ convert from UTC (GMT) to local time [