home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / cstepm.zip / fold.e < prev    next >
Text File  |  1994-08-18  |  9KB  |  239 lines

  1. /* Fold.e, by Larry Margolis
  2.  
  3.   Code for folding of procedures.  Place the cursor on a brace or parenthesis,
  4.   and enter FOLD in the EPM command dialog.  The code between the character
  5.   the cursor is on and the matching bracket will be folded (actually, displayed
  6.   in a 1-point type).  Place the cursor inside the folded text and enter the
  7.   UNFOLD (or EXPAND) command to restore it.
  8.  
  9.   Installation:  This can be included in your base .ex files by adding the line:
  10.      include 'fold.e'
  11.   to your MYSTUFF.E or MYEXTRA.E, or compiled as a separate .ex file and linked
  12.   when you want to use it.  If compiled separately, you can also enter the FOLD
  13.   command to fold text without linking fold.ex, and FOLD 0 or FOLD OFF to
  14.   expand folded text.  FOLD ? gives help.  (That's what the DEFMAIN accomplishes.)
  15. */
  16.  
  17. compile if EVERSION < '5.50'
  18.    Error:  This only supports EPM 5.50 or above - mixed font support is required.
  19. compile endif
  20.  
  21. const GOLD = '(){}[]<>'  -- Parens, braces, brackets & angle brackets.
  22.       C_TOKS = '#if #ifdef #ifndef #endif #else #elif'
  23.  
  24. compile if not defined('SMALL')  -- being compiled as a stand-alone module
  25. defmain
  26.    uparg = upcase(arg(1))
  27.    if uparg=0 | uparg='OFF' then
  28.       'unfold'
  29.    elseif uparg=1 | uparg='ON' | uparg='' then
  30.       'fold'
  31.    else
  32.       gold2='     '
  33.       do i=1 to length(GOLD)
  34.          gold2 = gold2 substr(GOLD, i, 1)
  35.       enddo
  36.  compile if EVERSION >= '5.60'
  37.       call winmessagebox('Fold', 'Place cursor on one of:'\n gold2\n'or a #if, #elif, #else, #endif, or COMPILE (followed by IF, ELSEIF, ELSE or ENDIF), then enter FOLD to fold text.  Place cursor inside folded text and enter FOLD OFF to expand it.',
  38.                          16384+48) -- MOVEABLE + MB_INFORMATION
  39.  compile else
  40.       call winmessagebox('Fold', 'Place cursor on one of:'\n gold2\n'then enter FOLD to fold text.  Place cursor inside folded text and enter FOLD OFF to expand it.', 16384+48) -- MOVEABLE + MB_INFORMATION
  41.  compile endif
  42.    endif
  43.  
  44.  compile if EVERSION >= 6
  45.    EA_comment "CUSTEPM's FOLD command, for code folding and unfolding."
  46.  compile endif
  47. compile endif
  48.  
  49. const
  50.    COLOR_CLASS = 1
  51.    BOOKMARK_CLASS = 13
  52.    STYLE_CLASS =  14
  53.    FONT_CLASS =  16
  54.  
  55.    FIND_NEXT_ATTR_SUBOP = 1
  56.    FIND_PREV_ATTR_SUBOP = 2
  57.    FIND_MATCH_ATTR_SUBOP = 3
  58.    DELETE_ATTR_SUBOP = 16
  59.  
  60. defc fold =
  61.    call psave_pos(savepos)
  62. compile if EVERSION >= '5.50'
  63.    case = 'e'
  64.    id = ''
  65.    force_search = 0
  66. compile endif
  67.    n=1
  68.    c=substr(textline(.line),.col,1)
  69.    GETSEARCH search_command -- Save user's search command.
  70.    k=pos(c,GOLD)            --  '(){}[]<>'
  71.    if k then
  72.       search = substr(GOLD,(k+1)%2*2-1,2)
  73. compile if EVERSION >= '5.60'
  74.       incr = 0
  75. compile endif
  76.    else
  77. compile if EVERSION >= '5.60'
  78.       if find_token(startcol, endcol) then
  79.          getline line
  80.          id = substr(line, startcol, (endcol-startcol)+1)
  81.       endif
  82.       if wordpos(id, C_TOKS) then
  83.          k = (id<>'#endif')  -- Search forwards if not #endif
  84.          if k then  -- move to beginning
  85.             .col = startcol
  86.             c = 'i'
  87.             search = '#(if((n?def)|):w|endif|else|elif)'
  88.          else       -- move to end, so first Locate will hit this instance.
  89.             .col = endcol
  90.             c = 'e'
  91.             search = '#(if((n?def)|):w|endif)'
  92.          endif
  93.          incr = 1
  94.          force_search = substr(id, 3, 1)='l'  -- #else or #elif
  95.       elseif lowcase(id)='compile' &
  96.              wordpos(lowcase(word(substr(line, endcol+1), 1)), 'if endif else elseif') then
  97.          case = 'c'  -- Case insensitive
  98.          k = (lowcase(word(substr(line, endcol+1), 1))<>'endif')
  99.          if k then  -- move to beginning
  100.             .col = startcol
  101.             c = 'i'
  102.             search = 'compile:w((end|else|)if|else)'
  103.          else       -- move to end, so first Locate will hit this instance.
  104.             end_line
  105.             c = 'e'
  106.             search = 'compile:w(end|)if'
  107.          endif
  108.          id=lowcase(id)
  109.          incr = 0
  110.          force_search = lowcase(substr(word(substr(line, endcol+1), 1), 2, 1))='l'  -- ELSE or ELSEIF
  111.       else
  112. compile endif
  113.          sayerror 'Not a balanceable character.'
  114.          return
  115. compile if EVERSION >= '5.60'
  116.       endif
  117. compile endif
  118.    endif
  119.    fstline=.line; fstcol=.col
  120.    if k//2 then direction='+F'; else direction='-R'; endif
  121.    if search='[]' then search='\[\]'; endif
  122. compile if EVERSION >= '5.60'
  123.    if search='()' then search='\(\)'; endif
  124.    if id='' then search='['search']'; endif
  125.    if force_search then
  126.       setsearch 'xcom l /'search'/x'case||direction
  127.    else
  128.       'xcom L /'search'/x'case||direction
  129.    endif
  130. compile else
  131.    'xcom L /['search']/eg'direction
  132. compile endif
  133.    loop
  134.       repeatfind
  135.       if rc then leave; endif
  136. compile if EVERSION >= '5.60'
  137.       if id='compile' then
  138.          tab_word
  139.          if lowcase(substr(textline(.line), .col+1, 1)) = 'l' then -- COMPILE_ELSE or COMPILE_ELSEIF
  140.             if n>1 then  -- If not our nesting level,
  141.                iterate   -- ignore it.
  142.             else
  143.                backtab_word
  144.                leave
  145.             endif
  146.          endif
  147.          if lowcase(substr(textline(.line), .col+incr, 1)) = c then n=n+1; else n=n-1; endif
  148.          backtab_word
  149.       else
  150.          if id<>'' then
  151.             if lowcase(substr(textline(.line), .col+2, 1))='l' then  -- #else | #elif
  152.                if n>1 then  -- If not our nesting level,
  153.                   iterate   -- ignore it.
  154.                else
  155.                   backtab_word
  156.                   leave
  157.                endif
  158.             endif
  159.          endif
  160.          if substr(textline(.line), .col+incr, 1) = c then n=n+1; else n=n-1; endif
  161.       endif
  162. compile else
  163.       if substr(textline(.line), .col, 1) = c then n=n+1; else n=n-1; endif
  164. compile endif
  165.       if n=0 then leave; endif
  166.    endloop
  167.    if rc=sayerror('String not found') then
  168.       sayerror 'Unbalanced token.'
  169.    else
  170.       sayerror 1
  171.    endif
  172.    SETSEARCH search_command -- Restores user's command so Ctrl-F works.
  173.    lstline = .line; lstcol = .col
  174.    if not rc then
  175.       getfileid fid
  176.       fontid=registerfont('Courier', 1, 0)
  177.       call attribute_on(4)  -- Mixed fonts flag
  178.       if not (k//2) then  -- adjust the order
  179.          parse value fstline lstline fstcol lstcol with lstline fstline lstcol fstcol
  180.       endif
  181.       if id then
  182.          fstcol = length(textline(fstline)) + 1
  183.          lstcol = 0
  184.       else
  185.          fstcol = fstcol + 1        -- Want to display the brace, paren, etc.
  186.          if leftstr(textline(lstline), lstcol-1) = '' then
  187.             lstcol = 0
  188.          else
  189.             lstcol = lstcol - 1
  190.          endif
  191.       endif
  192. ;getfileid fld, 'fold.e'
  193. ;insertline '; k='k'; k//2='k//2'; not1='(not k//2)'; not2='(not (k//2))'; Insert_Attribute_Pair(16,' fontid',' fstline',' lstline',' fstcol',' lstcol',' fid')', fld.last+1, fld
  194.       oldmod = .modify
  195.       Insert_Attribute_Pair(FONT_CLASS, fontid, fstline, lstline, fstcol, lstcol, fid)
  196.       .modify = oldmod
  197.    endif
  198.    call prestore_pos(savepos)
  199.    right
  200.    refresh
  201.    left
  202.  
  203. defc unfold, expand =
  204.    fontid=registerfont('Courier', 1, 0)
  205.    class = 16  -- STYLE_CLASS
  206.    line=.line; col=.col; offst=0
  207.    if pos(substr(textline(.line), .col, 1), GOLD) then
  208.       col = col + 1
  209.    elseif find_token(startcol, endcol) then
  210.       wrd = substr(textline(.line), startcol, (endcol-startcol)+1)
  211.       if wordpos(wrd, C_TOKS) | lowcase(wrd)='compile' then
  212.          line = line + 1; col = 1
  213.       endif
  214.    endif
  215.    do forever
  216.       attribute_action FIND_PREV_ATTR_SUBOP, class, offst, col, line
  217.       if class=0 then   -- not found
  218.          sayerror 'Not found - cursor must be after start of folded text.'
  219.          return
  220.       endif
  221.       query_attribute class, val, IsPush, offst, col, line
  222.       if IsPush & val=fontid then leave; endif
  223.       offst = offst-1
  224.    enddo
  225.               -- OK, at this point we've got the beginning attribute.
  226.    fstline = line; fstcol = col; fstoff = offst
  227.    oldmod = .modify
  228.    attribute_action FIND_MATCH_ATTR_SUBOP, class, offst, col, line
  229.    if class then
  230.       attribute_action DELETE_ATTR_SUBOP, class, offst, col, line
  231.    endif
  232.    class = 16  -- STYLE_CLASS
  233.    attribute_action DELETE_ATTR_SUBOP, class, fstoff, fstcol, fstline
  234.    right
  235.    refresh
  236.    left
  237.    .modify = oldmod
  238.  
  239.