home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / mlepm.zip / mltools.e < prev    next >
Text File  |  1995-09-19  |  34KB  |  885 lines

  1. /* mltools.e - this is the E part of the MlTools package     950314 */
  2.  
  3. /* This file was created from scratch, until I realized that        */
  4. /* I was recreating bookmark.e :-/                                  */
  5. /*                                                                  */
  6. /* Parts Copyright (c) 1994, 1995 Martin Lafaix.                    */
  7.  
  8. /* 950918: Martin Lafaix (lafaix@alto.unice.fr)                     */
  9. /*                                                                  */
  10. /*  .EPM 5.60+ and mode-dependant support for popup menus added     */
  11. /*                                                                  */
  12. /* 950314: Martin Lafaix (lafaix@mimosa.unice.fr)                   */
  13. /*                                                                  */
  14. /*  .Adding mmarkarea.  This function marks current token/block     */
  15. /*   (that is, if we're over a balanceable token, the delimited     */
  16. /*   area, or the current token otherwise).                         */
  17. /*                                                                  */
  18. /* 950202: Martin Lafaix (lafaix@mimosa.unice.fr)                   */
  19. /*                                                                  */
  20. /*  .Adding mdebug.  This function dumps all known infos in a       */
  21. /*   buffer.                                                        */
  22. /*                                                                  */
  23. /* 941026: Martin Lafaix (lafaix@mimosa.unice.fr)                   */
  24. /*                                                                  */
  25. /*  .Adding mquicksave.                                             */
  26. /*                                                                  */
  27. /* 940522: Martin Lafaix (lafaix@sophia.inria.fr)                   */
  28. /*                                                                  */
  29. /*  .Adding mfind/mgo/mnext.                                        */
  30. /*  .Removing ML_function_index.                                    */
  31. /*                                                                  */
  32. /* 940515: Martin Lafaix (lafaix@sophia.inria.fr)                   */
  33. /*                                                                  */
  34. /*  .New popupmenu handling.                                        */
  35. /*                                                                  */
  36. /* 940508: Martin Lafaix (lafaix@sophia.inria.fr)                   */
  37. /*                                                                  */
  38. /*  .Adding mode support (and a new statusline flag: %t, file mode) */
  39. /*  .This package now supersedes bookmark.e (except for Workframe). */
  40. /*                                                                  */
  41. /* 940502: Martin Lafaix (lafaix@sophia.inria.fr)                   */
  42. /*                                                                  */
  43. /*  .A new universal, ML_function_index.  Contains the 'Function'   */
  44. /*   style index.                                                   */
  45. /*  .mloadattributes/msaveattributes functions added.               */
  46. /*  .mpopupmenu function added (yeah! :)                            */
  47. /*                                                                  */
  48. /* 940501: Martin Lafaix (lafaix@sophia.inria.fr)                   */
  49. /*                                                                  */
  50. /*  .Writing docs.                                                  */
  51. /*                                                                  */
  52. /* 940428: Martin Lafaix (lafaix@sophia.inria.fr)                   */
  53. /*                                                                  */
  54. /*  .Changing from MyTools to MlTools. (What a change! :)           */
  55. /*                                                                  */
  56. /* 940427: Martin Lafaix (lafaix@sophia.inria.fr)                   */
  57. /*                                                                  */
  58. /*  .Initial work.                                                  */
  59. /*                                                                  */
  60.  
  61.  
  62. ;  Usage:
  63. ;
  64. ;  Preliminary notes
  65. ;
  66. ;     This package is designed to be used as an external module.
  67. ;     Put MLTOOLS.EX somewhere along your EPMPATH, and insert the
  68. ;     following statement in your profile.erx (you can issue the
  69. ;     command, if you just want to try it) :
  70. ;
  71. ;        link MLTOOLS
  72. ;
  73. ;     All functions names are prefixed with an 'm', in order to
  74. ;     prevent name-clash with future (possible) EPM functions.
  75. ;     (We can't expect them to share the same definition, can we? :)
  76. ;
  77. ;     This package mainly works on attributed (aka hilited) files, so
  78. ;     it's recommended that you use it with a hiliting-package (as
  79. ;     MLHILITE).  If you want to use the mode hook, you have to link
  80. ;     MLHOOK, too.
  81. ;
  82. ;     Popup menus require the MPOPUP.EXE program to be running.
  83. ;
  84. ;  mfindfunction
  85. ;
  86. ;     This function pops up a listbox containing all functions
  87. ;     defined in current file, with option to jump to a specific
  88. ;     function.
  89. ;     A function is something which has the 'Function' style.  If a
  90. ;     function spans on more than one line, only the first line is
  91. ;     shown in the listbox.
  92. ;
  93. ;  mfind start_fid dest_fid style
  94. ;
  95. ;     This function copies the first line of items of style 'style',
  96. ;     from start_fid to dest_fid.
  97. ;
  98. ;  mnext style [P]
  99. ;
  100. ;     This function locates the next (or previous, if P is specified)
  101. ;     item of style 'style'.  If such an item is found, the cursor is
  102. ;     moved.  Otherwise, nothing occurs.
  103. ;
  104. ;  mgo style string
  105. ;
  106. ;     This function locates the specified string with the given style
  107. ;     in current file.  If the string is found, the cursor is moved.
  108. ;     Otherwise, nothing occurs.
  109. ;     'string' should be the beginning of the desired style.
  110. ;     mgo finds the first matching string.
  111. ;
  112. ;  mnextfunction [P]
  113. ;
  114. ;     This function locates the next (or previous, if P is specified)
  115. ;     function header.  If such a function is found, the cursor is
  116. ;     moved.  Otherwise, nothing occurs.
  117. ;     This function can be assigned to a key, allowing you quick
  118. ;     movements in your files.  Put the following in your profile.erx
  119. ;     if you want to assign 'mnextfunction P' to 'Alt+up_arrow' and
  120. ;     'mnextfunction' to Alt+down_arrow :
  121. ;
  122. ;        buildaccel '*' 34 24 1234 mnextfunction
  123. ;        buildaccel '*' 34 22 1235 mnextfunction P
  124. ;        activateaccel
  125. ;
  126. ;     [34 stands for AF_VIRTUALKEY+AF_ALT, 24 is the down_arrow
  127. ;      keycode, and 22 is the up_arrow keycode.  1234 and 1235 can be
  128. ;      any numbers, but they have to be unique.]
  129. ;
  130. ;  mloadattributes [Not yet completed]
  131. ;
  132. ;     This function loads current file attributes from its EAs.  It
  133. ;     supports the new (compact) attribute format.  It can read
  134. ;     attributes from an old EPM file, though...
  135. ;
  136. ;  msaveattributes [Not yet completed]
  137. ;
  138. ;     This function save the current file attributes in its EAs.  They
  139. ;     are saved in the new (compact) attribute format.
  140. ;
  141. ;  mpopupmenu menu
  142. ;
  143. ;     This function popups a menu.  The poped up menu depends on the
  144. ;     cursor location.  This popupmenu support is actually a kludge
  145. ;     for EPM v5.51a. If menu is 10, an application-related popupmenu
  146. ;     is shown.  Otherwise, a contextual menu is displayed.
  147. ;
  148. ;     If defined, a mode-dependant function is used:
  149. ;
  150. ;        'mpopup_'language'_menu'
  151. ;
  152. ;  msetstatusline newstatusline
  153. ;
  154. ;     This function replaces the old setstatusline.  Same usage, same
  155. ;     effects (it just remembers the actual statusline value).
  156. ;
  157. ;  msetfilemode filemode
  158. ;
  159. ;     This function sets the current file mode.  It can be any string
  160. ;     (but a short one is recommended, though...).  The filemode will
  161. ;     be shown on the statusline if this statusline contains '%t'.
  162. ;
  163. ;     Example:
  164. ;
  165. ;        msetfilemode 'C++ mode'
  166. ;
  167. ;     The current file mode will now be 'C++ mode'.  This string will
  168. ;     appears in the statusline if it contains '%t'.  (The
  169. ;     show_mode_hook has to be in effect.)
  170. ;
  171. ;  show_mode_hook
  172. ;
  173. ;     This hook is used to display the file mode in the statusline.
  174. ;     If you want to have the current file mode displayed in the
  175. ;     status line, put the following in your profile.erx :
  176. ;
  177. ;        maddhook 'select_hook 'show_mode_hook
  178. ;
  179. ;     and define a new statusline, which contains '%t' :
  180. ;
  181. ;        msetstatusline 'Line %l of %s  Column %c   %f   %i     %m %t'
  182. ;
  183. ;     If no file mode is defined, 'Text mode' will appear.
  184. ;
  185. ;     [Using hooks requires a hook-package, eg MLHOOK, to be linked.]
  186. ;
  187. ;  mautoindent [|on|off]
  188. ;
  189. ;     This command sets the indentation mode (on by default).  If
  190. ;     no parameters are given, it shows the current indentation state.
  191. ;     Autoindentation is mode-dependant.
  192. ;
  193. ;  mindentline
  194. ;
  195. ;     This function indents the current line.  It's mode dependant.
  196. ;     It can be assigned to a key; put the following in your profile
  197. ;     if you want to assign it to the tab key :
  198. ;
  199. ;        buildaccel '*' 0 9 1236 mindentline
  200. ;        activateaccel
  201. ;
  202. ;  newtop
  203. ;
  204. ;     This function makes the current line the top-line.  It's used
  205. ;     by a popupmenu option (Scroll to top).
  206. ;
  207. ;  mquicksave [|on|off]
  208. ;
  209. ;     This command sets the quicksave mode (on by default).  When in
  210. ;     quicksave mode, using the F2 key saves the file, but not its
  211. ;     attributes.
  212. ;
  213. ;     This is much faster than the standard save, so it can be use for
  214. ;     intermediate saves (say, before compiling...).
  215. ;
  216. ;     [It does NOT reset the .modify counter -- this gives you the
  217. ;      opportunity to save the file with its attributes later.]
  218. ;
  219. ;  mdebug
  220. ;
  221. ;     This command dumps all known informations (concerning MLEPM) in
  222. ;     a buffer named .mlepm.
  223. ;
  224. ;  mmarkarea [n]
  225. ;
  226. ;     This command marks current block/token.  If n is specified, we
  227. ;     use the mouse position.  Otherwise, we use the current position.
  228. ;
  229. ;     A block/token is either an area enclosed within balanceable tokens,
  230. ;     or a token as defined by marktoken.
  231.  
  232.  
  233.  
  234. compile if not defined(BLACK)
  235. const
  236.    ml_tools_is_external = 1
  237.    INCLUDING_FILE = 'MLTOOLS.E'
  238.    WANT_APPLICATION_INI_FILE = 1
  239.    EXTRA_EX = 0
  240.    include 'stdconst.e'
  241. compile else
  242.    const ml_tools_is_external = 0
  243. compile endif
  244. compile if not defined(NLS_LANGUAGE)
  245.    const NLS_LANGUAGE = 'ENGLISH'
  246. compile endif
  247. include NLS_LANGUAGE'.e'
  248.  
  249. const
  250.    COLOR_CLASS = 1
  251.    BOOKMARK_CLASS = 13
  252.    STYLE_CLASS =  14
  253.    FONT_CLASS =  16
  254.    EAT_ASCII    = \253\255    -- FFFD
  255.    EAT_MVST     = \222\255    -- FFDE
  256.  
  257. definit
  258.    universal defaultmenu
  259.    universal ML_autoindent, ML_quicksave
  260.    ML_autoindent = 1
  261.    ML_quicksave = 1
  262. compile if EVERSION < 5.60
  263.    -- popupmenu kludge
  264.    buildacceltable 'defaccel', 'markword', AF_VIRTUALKEY+AF_ALT,0,9200
  265.    buildacceltable 'defaccel', 'marktoken', AF_VIRTUALKEY+AF_ALT,0,9201
  266.    buildacceltable 'defaccel', 'findword', AF_VIRTUALKEY+AF_ALT,0,9202
  267.    buildacceltable 'defaccel', 'key 1 c+f1', AF_VIRTUALKEY+AF_ALT,0,9203
  268.    buildacceltable 'defaccel', 'key 1 c+f2', AF_VIRTUALKEY+AF_ALT,0,9204
  269.    buildacceltable 'defaccel', 'key 1 s+f5', AF_VIRTUALKEY+AF_ALT,0,9205
  270.    buildacceltable 'defaccel', 'newtop', AF_VIRTUALKEY+AF_ALT,0,9206
  271.    buildacceltable 'defaccel', 'ml_make', AF_VIRTUALKEY+AF_ALT,0,9208
  272.    buildacceltable 'defaccel', 'ml_build', AF_VIRTUALKEY+AF_ALT,0,9209
  273.    buildacceltable 'defaccel', 'fill', AF_VIRTUALKEY+AF_ALT,0,9210
  274.    buildacceltable 'defaccel', 'key 1 a+P', AF_VIRTUALKEY+AF_ALT,0,9211
  275.    buildacceltable 'defaccel', 'key 1 c+f3', AF_VIRTUALKEY+AF_ALT,0,9212
  276.    buildacceltable 'defaccel', 'key 1 c+f4', AF_VIRTUALKEY+AF_ALT,0,9213
  277.    buildacceltable 'defaccel', 'sort', AF_VIRTUALKEY+AF_ALT,0,9214
  278.    buildacceltable 'defaccel', 'key 1 c+f7', AF_VIRTUALKEY+AF_ALT,0,9220
  279.    buildacceltable 'defaccel', 'key 2 c+f7', AF_VIRTUALKEY+AF_ALT,0,9221
  280.    buildacceltable 'defaccel', 'key 3 c+f7', AF_VIRTUALKEY+AF_ALT,0,9222
  281.    buildacceltable 'defaccel', 'key 1 c+f8', AF_VIRTUALKEY+AF_ALT,0,9224
  282.    buildacceltable 'defaccel', 'key 2 c+f8', AF_VIRTUALKEY+AF_ALT,0,9225
  283.    buildacceltable 'defaccel', 'key 3 c+f8', AF_VIRTUALKEY+AF_ALT,0,9226
  284. compile endif
  285.  
  286. defc mdebug
  287.    universal ML_quicksave
  288.    universal ML_autoindent
  289.    universal ML_array_ID
  290.    universal ML_autohilite
  291.    display -12
  292.    'xcom e /c .mlepm'
  293.    .filename = '.mlepm'
  294.    .autosave = 0
  295.    insertline '>>>>>>>>>>MLEPM global dump<<<<<<<<<<', .last
  296.    insertline '', .last
  297.    insertline 'MLEPM version 0.032.000', .last
  298.    insertline '', .last
  299.    insertline 'QuickSave: 'ML_quicksave', AutoIndent: 'ML_autoindent', AutoHilite: 'ML_autohilite, .last
  300.    do_array 3, ML_array_ID, 'statusline', sl
  301.    insertline '', .last
  302.    insertline sl, .last
  303.    insertline '', .last
  304.    insertline '>>>>>>>>>>MLEPM hook dump<<<<<<<<<<', .last
  305.    insertline '', .last
  306.    insertline 'load_hook:', .last
  307.    call get_array_value(ML_array_ID,'hook.load_hook.0', items)
  308.    for i = 1 to items
  309.       do_array 3, ML_array_ID, 'hook.load_hook.'i, function
  310.       insertline i function, .last
  311.    endfor
  312.    insertline '', .last
  313.    insertline 'select_hook:', .last
  314.    call get_array_value(ML_array_ID,'hook.select_hook.0', items)
  315.    for i = 1 to items
  316.       do_array 3, ML_array_ID, 'hook.select_hook.'i, function
  317.       insertline i function, .last
  318.    endfor
  319.    insertline '', .last
  320.    insertline 'modify_hook:', .last
  321.    call get_array_value(ML_array_ID,'hook.modify_hook.0', items)
  322.    for i = 1 to items
  323.       do_array 3, ML_array_ID, 'hook.modify_hook.'i, function
  324.       insertline i function, .last
  325.    endfor
  326.    insertline '', .last
  327.    insertline 'popup_hook:', .last
  328.    call get_array_value(ML_array_ID,'hook.popup_hook.0', items)
  329.    for i = 1 to items
  330.       do_array 3, ML_array_ID, 'hook.popup_hook.'i, function
  331.       insertline i function, .last
  332.    endfor
  333.    insertline '', .last
  334.    insertline '>>>>>>>>>>MLEPM language dump<<<<<<<<<<', .last
  335.    insertline '', .last
  336.    do_array 3, ML_array_ID, 'languages', languages
  337.    insertline languages, .last
  338.    insertline '', .last
  339.    for i = 1 to words(languages)
  340.       do_array 3, ML_array_ID, 'lg.'word(languages,i), extensions
  341.       insertline 'Extensions for 'word(languages,i)' are: 'extensions, .last
  342.       for j = 1 to 4
  343.          do_array 3, ML_array_ID, 'hl.'word(languages,i)'.'j'.0', k
  344.          if k = '' then
  345.             insertline 'level 'j' is empty', .last
  346.          else
  347.             for l = 1 to k
  348.                do_array 3, ML_array_ID, 'hl.'word(languages,i)'.'j'.'l, expr
  349.                insertline 'level 'j', expr 'l': 'expr, .last
  350.             endfor
  351.          endif
  352.       endfor
  353.       insertline '', .last
  354.    endfor
  355.    insertline '>>>>>>>>>>MLEPM ring dump<<<<<<<<<<', .last
  356.    insertline '', .last
  357.    insertline '.modify  .autosave  .keyset      language   mode       filename', .last
  358.    insertline '───────────────────────────────────────────────────────────────', .last
  359.    getfileid firstid
  360.    do forever
  361.       nextfile
  362.       getfileid nextid
  363.       do_array 3, ML_array_ID, nextid'.mode', mode
  364.       insertline leftstr(.modify,9)leftstr(.autosave,11)leftstr(.keyset,12)leftstr(mgetfilelanguage(),11)leftstr(mode,11).filename, firstid.last, firstid
  365.       if nextid=firstid then
  366.          leave
  367.       endif
  368.    enddo
  369.    'mcallhook select_hook'
  370.    display 12
  371.    .modify = 0
  372.  
  373. defc mquicksave
  374.    universal ML_quicksave
  375.    uparg=upcase(arg(1))
  376.    if uparg=ON__MSG then
  377.       ML_quicksave = 1
  378.       call select_edit_keys()
  379.    elseif uparg=OFF__MSG then
  380.       ML_quicksave = 0
  381.       call select_edit_keys()
  382.    elseif uparg='' then
  383.       sayerror 'QUICKSAVE:' word(OFF__MSG ON__MSG, ML_quicksave+1)
  384.    else
  385.       sayerror INVALID_ARG__MSG ON_OFF__MSG')'
  386.       stop
  387.    endif
  388.  
  389. def f2=
  390.    universal ML_quicksave
  391.    if ML_quicksave=1 then
  392.       oldm=.modify
  393.       'xcom s'
  394.       .modify=oldm
  395.       sayerror 'Quickly saved to' .filename
  396.    else
  397.       'save'
  398.    end
  399.  
  400. def c_w=
  401.    if marktype()<>'' then
  402.       sayerror -279 -- 'Text already marked'
  403.    else
  404.       'mmarkarea 0'
  405.    endif
  406.  
  407. defc mfind
  408.    universal EPM_utility_array_ID
  409.    parse arg start_fid dest_fid style
  410.    do_array 3, EPM_utility_array_ID, 'sn.'style, style_index
  411.    class=14; line=0; col=0; off=-255
  412.    attribute_action 1, class, off, col, line, start_fid
  413.    while class do
  414.       query_attribute class, val, IsPush, off, col, line, start_fid
  415.       if val=style_index then
  416.          getline selected, line, start_fid
  417.          insertline strip(selected,'T'), dest_fid.last+1, dest_fid
  418.          attribute_action 3, class, off, col, line, start_fid
  419.       endif
  420.       class=14; off=-255; col=col+1
  421.       attribute_action 1, class, off, col, line, start_fid
  422.    endwhile
  423.  
  424. defc mgo
  425.    parse arg style fn
  426.    .line=0
  427.    do forever
  428.       line=.line; col=.col
  429.       'mnext' style
  430.       if line=.line & col=.col then
  431.          sayerror style' not found'
  432.          return
  433.       endif
  434.       if fn=substr(textline(.line),.col,length(fn)) then return; endif
  435.    enddo
  436.  
  437. defc mnext
  438.    universal EPM_utility_array_ID
  439.    parse arg style next .
  440.    do_array 3, EPM_utility_array_ID, 'sn.'style, style_index
  441.    class = 14
  442.    col = .col+1; line=.line; offst=-255
  443.    if next='P' then col=col-2; endif
  444.    do forever
  445.       attribute_action 1+(next='P'), class, offst, col, line -- 1=FIND NEXT ATTR; 2=FIND PREV ATTR
  446.       if class=0 then
  447.          return
  448.       endif
  449.       query_attribute class, val, IsPush, offst, col, line
  450.       if val=style_index & IsPush=1 then
  451.          if line < .line-.cursory+1 | line > .line-.cursory+.windowheight then
  452.             .cursory=.windowheight%2
  453.          else
  454.             .cursory=.cursory-.line+line
  455.          endif
  456.          line; .col=col
  457.          return
  458.       endif
  459.    enddo
  460.  
  461. defc mfindfunction=
  462.    getfileid start_fid
  463.    'xcom e /c .mytools'
  464.    .autosave=0
  465.    getfileid tools_fid
  466.    'mfind' start_fid tools_fid 'Function'
  467.    buff=buffer(CREATEBUF,'MYTOOLS',filesize()+.last+1,1)
  468.    rc=buffer(PUTBUF,buff,1,0,17)
  469.    .modify=0
  470.    'xcom quit'
  471.    lb=listbox('Available functions',
  472.  compile if EPM32
  473.               \0 || atol(buffer(USEDSIZEBUF,buff)) || atoi(32) || atoi(buff),
  474.  compile else
  475.               \0 || atoi(buffer(USEDSIZEBUF,buff)) || atoi(buff) || atoi(32),
  476.  compile endif
  477. --              '/~Go to/~Delete/Cancel/Help',
  478.               '/~Go to/Cancel/Help',
  479.               0,0,10,70,
  480.  compile if EVERSION >= 5.60
  481.               gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(6030) ||
  482.  compile else
  483.               atoi(1) || atoi(1) || atoi(6030) || gethwndc(APP_HANDLE) ||
  484.  compile endif
  485.               ' [In the help panels, read ''function'' instead of ''Bookmark'']' \0)
  486.    rc=buffer(FREEBUF,buff)
  487.    parse value lb with button 2 function \0
  488.    if button=\1 then
  489.       'mgo Function' function
  490. --   elseif button=\2 then
  491. --      'deletefunction' function
  492.    endif
  493.  
  494. defc mnextfunction
  495.    parse arg next .
  496.    'mnext Function' next
  497.  
  498. defc mautoindent
  499.    universal ML_autoindent
  500.    uparg=upcase(arg(1))
  501.    if uparg=ON__MSG then
  502.       ML_autoindent = 1
  503.       call select_edit_keys()
  504.    elseif uparg=OFF__MSG then
  505.       ML_autoindent = 0
  506.       call select_edit_keys()
  507.    elseif uparg='' then
  508.       sayerror 'AUTOINDENT:' word(OFF__MSG ON__MSG, ML_autoindent+1)
  509.    else
  510.       sayerror INVALID_ARG__MSG ON_OFF__MSG')'
  511.       stop
  512.    endif
  513.  
  514. defc mindentline
  515. ;   déterminer le langage
  516.    language=mgetfilelanguage()
  517.    if isadefc('mindent_'language'_line') then
  518.       'mindent_'language'_line'
  519.    else
  520.       if .line then
  521.          oldline=.line
  522.          .line=.line-1
  523.          while .line & textline(.line)='' do
  524.             .line=.line-1
  525.          endwhile
  526.          if .line then
  527.             call pfirst_nonblank()
  528.          else
  529.             .col=1
  530.          endif
  531.          .line=oldline
  532.          newpos=.col
  533.          call pfirst_nonblank()
  534.          if .col<newpos then
  535.             for i=1 to newpos-.col
  536.                keyin ' '
  537.             endfor
  538.          elseif .col>newpos then
  539.             for i=1 to .col-newpos
  540.                deletechar
  541.             endfor
  542.          endif
  543.       endif
  544.    endif
  545.  
  546. defproc mpopup
  547.    popupid=dynalink('PMWIN','WINWINDOWFROMID',atoi(0)||atoi(1)||atoi(1234),2)
  548.    choice=windowmessage(0,popupid,4097,getpminfo(EPMINFO_EDITCLIENT),arg(1))
  549.  
  550. defc mpopupmenu
  551.    language=mgetfilelanguage()
  552.    if isadefc('mpopup_'language'_menu') then
  553.       'mpopup_'language'_menu' arg(1)
  554.    else
  555. compile if EVERSION >= 5.60
  556.       'MH_popup'
  557. compile else
  558.       if arg(1)=10 then
  559.          call mpopup(11)
  560.       elseif mouse_in_mark() then
  561.          if leftstr(marktype(),1)='C' then
  562.             call mpopup(1+arg(1))
  563.          else
  564.             call mpopup(4+arg(1))
  565.          endif
  566.       elseif leftstr(marktype(),1)<>' ' then
  567.          'MH_gotoposition'
  568.          call mpopup(2+arg(1))
  569.       else
  570.          'MH_gotoposition'
  571.          call mpopup(3+arg(1))
  572.       endif
  573. compile endif
  574.    endif
  575.  
  576. defc newtop
  577.    l=.line; .cursory=1; l
  578.  
  579. defc mmarkarea
  580.    if arg(1) then
  581.       'MH_gotoposition'
  582.    endif
  583.    c=substr(textline(.line),.col,1)
  584.    k=pos(c,'(){}[]<>')
  585.    if k=0 then
  586.       if c='"' or c="'" then
  587.          getline line
  588.          getfileid fid
  589.          cnt=0
  590.          do i = 1 to .col
  591.             if substr(line,i,1)=c then
  592.                cnt=cnt+1
  593.             endif
  594.          enddo
  595.          if cnt//2 then
  596.             do i = .col+1 to length(line)
  597.                if substr(line,i,1)=c then leave
  598.                endif
  599.             enddo
  600.             setmark .line, .line, .col, i+1, 3, fid
  601.          else
  602.             do i = .col-1 to 1 by -1
  603.                if substr(line,i,1)=c then leave
  604.                endif
  605.             enddo
  606.             setmark .line, .line, i, .col+1, 3, fid
  607.          endif
  608.       elseif find_token(startcol, endcol) then
  609.          getfileid fid
  610.          call pset_mark(.line, .line, startcol, endcol, 'BLOCK', fid)
  611.       endif
  612.    else
  613.       GETSEARCH search_command -- Save user's search command.
  614.       line=.line; col=.col; n=1
  615.       search=substr('(){}[]<>',(k+1)%2*2-1,2)
  616.       if k//2 then direction='+F'; else direction='-R'; endif
  617.       if search='[]' then search='\[\]'; endif
  618. compile if EVERSION >= '5.60'
  619.       if search='()' then search='\(\)'; endif
  620.       'xcom L /['search']/ex'direction
  621. compile else
  622.       'xcom L /['search']/eg'direction
  623. compile endif
  624.       loop
  625.          repeatfind
  626.          if rc then leave; endif
  627.          if substr(textline(.line), .col, 1) = c then n=n+1; else n=n-1; endif
  628.          if n=0 then leave; endif
  629.       endloop
  630.       if rc=sayerror('String not found') then
  631.          sayerror 'Unbalanced token.'
  632.       else
  633.          getfileid fid
  634.          if k//2 then
  635.             setmark line, .line, col, .col+1, 3, fid
  636.          else
  637.             setmark .line, line, .col, col+1, 3, fid
  638.          endif
  639.          sayerror 1
  640.       endif
  641.       SETSEARCH search_command -- Restores user's command so Ctrl-F works.
  642.       .line=line; .col=col
  643.    endif
  644.  
  645. defc msetstatusline
  646.    universal ML_array_ID
  647.    parse arg statusline
  648.    do_array 2, ML_array_ID, 'statusline', statusline
  649.    'setstatusline' statusline
  650.  
  651. defproc mgetfilemode
  652.    universal ML_array_ID
  653.    getfileid fileid
  654.    if get_array_value(ML_array_ID, fileid'.mode', mode) then
  655.       return ''
  656.    else
  657.       return mode
  658.    endif
  659.  
  660. defc msetfilemode
  661.    universal ML_array_ID
  662.    getfileid fileid
  663.    parse arg mode
  664.    do_array 2, ML_array_ID, fileid'.mode', mode
  665.    'mcallhook select_hook'
  666.  
  667. defc show_mode_hook
  668.    universal ML_array_ID
  669.    if get_array_value(ML_array_ID, 'statusline', statusline) then
  670.       return
  671.    endif
  672.    getfileid fileid
  673.    if get_array_value(ML_array_ID, fileid'.mode', mode) then
  674.       mode='Text mode'
  675.    endif
  676. --   statusline = 'Line %l of %s  Column %c   %f   %i    %m    %t'
  677.    p=pos('%t',statusline)
  678.    if p then
  679.       'setstatusline' insertstr(mode,delstr(statusline,p,2),p)
  680.    endif
  681.  
  682. ; Dependencies:  put_file_as_MVST()
  683. defc msaveattributes
  684.    universal EPM_utility_array_ID
  685.    universal app_hini
  686.    universal default_font
  687.    getfileid start_fid
  688. ;; call psave_pos(savepos)
  689.    'xcom e /c attrib'
  690.    if rc<>-282 then  -- -282 = sayerror("New file")
  691.       sayerror ERROR__MSG rc BAD_TMP_FILE__MSG sayerrortext(rc)
  692.       return
  693.    endif
  694.    browse_mode = browse()     -- query current state
  695.    if browse_mode then call browse(0); endif
  696.    .autosave = 0
  697.    getfileid attrib_fid
  698.    delete  -- Delete the empty line
  699. ;; activatefile start_fid
  700.    line=0; col=1; offst=0; found_font = 0
  701.    style_line=0; style_col=0; style_offst=0; style_list=''
  702.    do forever
  703.       class = 0  -- Find any class
  704.       attribute_action 1, class, offst, col, line, start_fid -- 1=FIND NEXT ATTR
  705.       if class=0 then leave; endif
  706.       query_attribute class, val, IsPush, offst, col, line, start_fid
  707.       l = line
  708.       if class=BOOKMARK_CLASS then  -- get name
  709.          if IsPush<>4 then iterate; endif    -- If not permanent, don't keep it.
  710.          do_array 3, EPM_utility_array_ID, 'bmi.'val, bmname  -- Get the name
  711.          l = l bmname
  712.       elseif class=COLOR_CLASS then  -- don't save if out of range
  713. ;;       if val>255 then iterate; endif
  714.          if line=style_line & col=style_col & (offst=style_offst+1 | offst=style_offst+2) then iterate; endif
  715. ;;       if line=style_line & col=style_col & offst=style_offst+2 then iterate; endif
  716.       elseif class=FONT_CLASS then  -- get font info
  717. ;;       if val>255 then iterate; endif
  718.          if line=style_line & col=style_col & offst=style_offst+1 then iterate; endif
  719.          l = l queryfont(val)
  720.          found_font = 1
  721.       elseif class=STYLE_CLASS then  -- get style info
  722.          do_array 3, EPM_utility_array_ID, 'si.'val, stylename -- Get the style name
  723.          style_line=line; style_col=col; style_offst=offst
  724. --         l = l stylename
  725.          if val<256 & not pos(chr(val), style_list) then  -- a style we haven't seen yet
  726.             if style_list='' then
  727.                'xcom e /c style'
  728.                if rc<>-282 then  -- -282 = sayerror("New file")
  729.                   sayerror ERROR__MSG rc BAD_TMP_FILE__MSG sayerrortext(rc)
  730.                   if browse_mode then call browse(1); endif  -- restore browse state
  731.                   return
  732.                endif
  733.                .autosave = 0
  734.                getfileid style_fid
  735.                delete  -- Delete the empty line
  736.             endif
  737.             style_list = style_list || chr(val)
  738. compile if WANT_APPLICATION_INI_FILE
  739.             insertline stylename || \0 || queryprofile(app_hini, 'Style', stylename), style_fid.last+1, style_fid
  740. compile else
  741.             insertline stylename || \0 , style_fid.last+1, style_fid
  742. compile endif
  743.             val=pos(chr(val), style_list) -- style pos in EPM.STYLES
  744.          else
  745.             l = l stylename
  746.          endif  -- new style
  747.       endif  -- class=STYLE_CLASS
  748.       insertline class val ispush offst col l, attrib_fid.last+1, attrib_fid
  749.    enddo
  750.    if found_font & .font <> default_font then
  751.       insertline FONT_CLASS .font 0 0 0 (-1) queryfont(start_fid.font), 1, attrib_fid  -- Insert at beginning.
  752.    endif
  753.    call put_file_as_MVST(attrib_fid, start_fid, 'EPM.ATTRIBUTES')
  754.    if style_list <> '' then
  755.       call put_file_as_MVST(style_fid, start_fid, 'EPM.STYLES')
  756.       style_fid.modify = 0
  757.       'xcom quit'
  758.    endif
  759.    attrib_fid.modify = 0
  760.    'xcom quit'
  761.    if browse_mode then call browse(1); endif  -- restore browse state
  762.  
  763. ; Dependencies:  find_ea() from EA.E
  764. defc mloadattributes
  765.    universal EPM_utility_array_ID, app_hini, load_var
  766.    getfileid fid
  767.    oldmod = .modify
  768.    val = get_EAT_ASCII_value('EPM.TABS')
  769.    if val<>'' then
  770.       .tabs = val
  771.       load_var = load_var + 1  -- Flag that Tabs were set via EA
  772.    endif
  773.    val = get_EAT_ASCII_value('EPM.MARGINS')
  774.    if val<>'' then
  775.       .margins = val
  776.       load_var = load_var + 2  -- Flag that Tabs were set via EA
  777.    endif
  778.    if find_ea('EPM.STYLES', ea_seg, ea_ofs, ea_ptr1, ea_ptr2, ea_len, ea_entrylen, ea_valuelen) then
  779.       val = peek(ea_seg, ea_ptr2,min(ea_valuelen,8))
  780.       style_list=''
  781.       if leftstr(val,2)=EAT_MVST & substr(val,7,2)=EAT_ASCII then
  782.          num = itoa(substr(val,5,2),10)
  783.          ea_ptr2 = ea_ptr2 + 8
  784.          do i=1 to num
  785.             len = itoa(peek(ea_seg, ea_ptr2, 2), 10)
  786.             parse value peek(ea_seg, ea_ptr2 + 2, len) with stylename \0 stylestuff
  787. compile if WANT_APPLICATION_INI_FILE
  788.             if queryprofile(app_hini, 'Style', stylename)='' then  -- Don't have as a local style?
  789.                call setprofile(app_hini, 'Style', stylename, stylestuff)  -- Add it.
  790.             endif
  791. compile endif
  792.             style_list = style_list stylename
  793.             ea_ptr2 = ea_ptr2 + len + 2
  794.          enddo
  795.       endif
  796.    endif
  797.    need_colors=0; need_fonts=0
  798.    if find_ea('EPM.ATTRIBUTES', ea_seg, ea_ofs, ea_ptr1, ea_ptr2, ea_len, ea_entrylen, ea_valuelen) then
  799.       val = peek(ea_seg, ea_ptr2,min(ea_valuelen,8))
  800.       if leftstr(val,2)=EAT_MVST & substr(val,7,2)=EAT_ASCII then
  801.          num = itoa(substr(val,5,2),10)
  802.          ea_ptr2 = ea_ptr2 + 8
  803.          do_array 3, EPM_utility_array_ID, 'bmi.0', bmcount          -- Index says how many bookmarks there are
  804.          do_array 3, EPM_utility_array_ID, 'si.0', stylecount
  805.          fontsel=''; bg=''  -- Initialize to simplify later test
  806.          do i=1 to num
  807.             len = itoa(peek(ea_seg, ea_ptr2, 2), 10)
  808.             parse value peek(ea_seg, ea_ptr2 + 2, len) with class val ispush offst col line rest
  809.             ea_ptr2 = ea_ptr2 + len + 2
  810.             if class=BOOKMARK_CLASS then  -- get name
  811.                if not get_array_value(EPM_utility_array_ID, 'bmn.'rest, stuff) then  -- See if we already had it
  812.                   parse value stuff with oldindex oldfid .
  813.                   if oldfid = fid then
  814.                      'deletebm' rest
  815.                   endif
  816.                endif
  817.                bmcount = bmcount + 1
  818.                do_array 2, EPM_utility_array_ID, 'bmi.'bmcount, rest -- Store the name at this index position
  819.                if IsPush<2 then IsPush=4; endif  -- Update old-style bookmarks
  820.                stuff = bmcount fid IsPush  -- flag as permanent
  821.                do_array 2, EPM_utility_array_ID, 'bmn.'rest, stuff -- Store the index & fileid under this name
  822.                val = bmcount  -- Don't care what the old index was.
  823.             elseif class=COLOR_CLASS then
  824.                need_colors = 1
  825.             elseif class=FONT_CLASS then
  826.                parse value rest with fontname '.' fontsize '.' fontsel
  827.                if fontsel='' then iterate; endif  -- Bad value; discard it
  828.                val=registerfont(fontname, fontsize, fontsel)  -- Throw away old value
  829.                if line=-1 then
  830.                   .font = val
  831.                   iterate
  832.                endif
  833.                need_fonts = 1
  834.             elseif class=STYLE_CLASS then  -- Set style info
  835. compile if WANT_APPLICATION_INI_FILE
  836.                if val<256 then
  837.                   stylename = word(val, style_list)
  838.                else
  839.                   parse value rest with stylename
  840.                endif
  841.                stylestuff = queryprofile(app_hini, 'Style', stylename)
  842.                if stylestuff='' then iterate; endif  -- Shouldn't happen
  843.                parse value stylestuff with fontname '.' fontsize '.' fontsel '.' fg '.' bg
  844.                if get_array_value(EPM_utility_array_ID, 'sn.'stylename, val) then  -- Don't have it; add:
  845.                   stylecount = stylecount + 1                                 -- Increment index
  846.                   do_array 2, EPM_utility_array_ID, 'si.'stylecount, stylename  -- Save index.name
  847.                   do_array 2, EPM_utility_array_ID, 'sn.'stylename, stylecount  -- Save name.index
  848.                   val = stylecount
  849.                endif
  850. compile else
  851.                iterate
  852. compile endif
  853.             endif
  854.             insert_attribute class, val, ispush, 0, col, line
  855.             if class=STYLE_CLASS then  -- Set style info
  856.                if fontsel<>'' then
  857.                   fontid=registerfont(fontname, fontsize, fontsel)
  858.                   if fontid<>.font then  -- Only insert font change for style if different from base font.
  859.                      insert_attribute FONT_CLASS, fontid, ispush, 0, col, line
  860.                      need_fonts = 1
  861.                   endif
  862.                endif
  863.                if bg<>'' then
  864.                   insert_attribute COLOR_CLASS, bg*16 + fg, ispush, 0, col, line
  865.                   need_colors = 1
  866.                endif
  867.             endif
  868.          enddo
  869.          do_array 2, EPM_utility_array_ID, 'bmi.0', bmcount          -- Store back the new number
  870.          do_array 2, EPM_utility_array_ID, 'si.0', stylecount
  871.          if need_colors then
  872.             call attribute_on(1)  -- Colors flag
  873.          endif
  874. compile if EVERSION >= 5.50  -- GPI has font support
  875.          if need_fonts then
  876.             call attribute_on(4)  -- Mixed fonts flag
  877.          endif
  878. compile endif
  879.          call attribute_on(8)  -- "Save attributes" flag
  880.       else
  881.          sayerror UNEXPECTED_ATTRIB__MSG
  882.       endif
  883.    endif
  884.    .modify = oldmod
  885.