home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / editors / epm / sampmacs / bookmark.e < prev    next >
Encoding:
Text File  |  1993-09-08  |  31.9 KB  |  802 lines

  1. ; This file adds bookmark support to EPM.  It can be linked in or included
  2. ; in the base .ex file.  WANT_ATTRIBUTE_SUPPORT must have been set when compiling
  3. ; the base if this is to be linked in, because DEFLOAD and DEFC SAVE have hooks
  4. ; to call routines defined herein.
  5.  
  6. compile if not defined(SMALL)  -- Being compiled separately
  7. include 'stdconst.e'
  8.  define INCLUDING_FILE = 'BOOKMARK.E'
  9. tryinclude 'MYCNF.E'
  10.  compile if not defined(SITE_CONFIG)
  11.     const SITE_CONFIG = 'SITECNF.E'
  12.  compile endif
  13.  compile if SITE_CONFIG
  14.     tryinclude SITE_CONFIG
  15.  compile endif
  16.  compile if not defined(INCLUDE_WORKFRAME_SUPPORT)
  17.    const INCLUDE_WORKFRAME_SUPPORT = 1
  18.  compile endif
  19.  compile if not defined(NLS_LANGUAGE)
  20.   const NLS_LANGUAGE = 'ENGLISH'
  21.  compile endif
  22. include NLS_LANGUAGE'.e'
  23. compile endif
  24.  
  25. const
  26.    COLOR_CLASS = 1
  27.    BOOKMARK_CLASS = 13
  28.    STYLE_CLASS =  14
  29.    FONT_CLASS =  16
  30.    EAT_ASCII    = \253\255    -- FFFD
  31.    EAT_MVST     = \222\255    -- FFDE
  32. compile if not defined(COMPILER_ERROR_COLOR)
  33.    COMPILER_ERROR_COLOR = 244  -- red + whiteb = 4 + 240
  34. compile endif
  35. compile if not defined(NO_DUPLICATE_BOOKMARKS)
  36.    NO_DUPLICATE_BOOKMARKS = 0
  37. compile endif
  38. compile if not defined(SORT_BOOKMARKS)
  39.    SORT_BOOKMARKS = 0
  40. compile endif
  41.  
  42. compile if 0  -- Menu now added in STDCTRL.E
  43. definit
  44.    universal defaultmenu, activemenu
  45.    buildsubmenu defaultmenu, 29, 'Bookmarks',             '',               0, 0
  46.      buildmenuitem defaultmenu, 29, 2901, '~Set...',           'setmark',        0, 0
  47.      buildmenuitem defaultmenu, 29, 2902, 'Set ~permanent...', 'setmarkp',       0, 0
  48.      buildmenuitem defaultmenu, 29, 2903, '~List...',          'listmark',       0, 0
  49.      buildmenuitem defaultmenu, 29, 2904, '~Delete...',        'listdeletebm',   0, 0
  50.      buildmenuitem defaultmenu, 29, 2905, \0,                  '',               4, 0
  51.      buildmenuitem defaultmenu, 29, 2906, 'Sa~ve BM as EA',    'saveattributes', 0, 0
  52.      buildmenuitem defaultmenu, 29, 2907, 'L~oad BM from EA',  'loadattributes', 0, 0
  53.    if activemenu=defaultmenu  then
  54.       showmenu activemenu
  55.    endif
  56. compile endif
  57.  
  58. defc bm, setmark
  59.    universal EPM_utility_array_ID
  60.    if browse() then
  61.       sayerror BROWSE_IS__MSG ON__MSG
  62.       return
  63.    endif
  64.    parse arg markname perm line col .
  65.    if not line then line=.line; endif
  66.    if not col then col=.col; endif
  67.    if not markname then  -- Following uses a new dialog, so no NLS xlation
  68. compile if EVERSION >= 5.21
  69.       parse value entrybox(SETMARK__MSG,'/'Set__MSG'/'Setp__MSG'/'Cancel__MSG'/'Help__MSG'/',\0,'',200,
  70.              atoi(1) || atoi(6020) || gethwndc(APP_HANDLE) ||
  71.              SETMARK_PROMPT__MSG) with button 2 markname \0
  72.       if button=\0 | button=\3 then return; endif  -- Esc or Cancel
  73.       perm = asc(button)+2  --> temp is 3; perm is 4
  74. compile else
  75.       markname = entrybox(SETMARK_PROMPT__MSG, '/'Set__MSG'/'Cancel__MSG,\0,'',200)
  76. compile endif
  77.       if not markname then
  78.          sayerror NOTHING_ENTERED__MSG
  79.          return
  80.       endif
  81.    endif
  82. compile if NO_DUPLICATE_BOOKMARKS
  83.    rc = get_array_value(EPM_utility_array_ID, 'bmn.'markname, bmindex)  -- Find that bookmark name
  84.    parse value bmindex with bmindex fid .
  85.    if not (rc | fid='') then  -- FID='' means previously deleted.
  86.       empty = ''
  87.       getfileid startid
  88.       display -2
  89.       activatefile fid
  90.       display 2
  91.       if rc then
  92.          do_array 2, EPM_utility_array_ID, 'bmi.'bmindex, empty  -- Delete the name
  93.       else
  94.          line=0; col=1; offst=0
  95.          do forever
  96.             class = BOOKMARK_CLASS
  97.             attribute_action 1, class, offst, col, line -- 1=FIND NEXT ATTR
  98.             if class=0 then leave; endif
  99.             query_attribute class, val, IsPush, offst, col, line
  100.             if val=bmindex then  -- Found!
  101.                leave
  102.             endif
  103.          enddo
  104.          if class then  -- Was found
  105.             sayerror BM_ALREADY_EXISTS__MSG
  106.             return
  107.          endif
  108.          do_array 2, EPM_utility_array_ID, 'bmi.'bmindex, empty  -- Delete the name
  109.       endif
  110.    endif
  111. compile endif -- NO_DUPLICATE_BOOKMARKS
  112.    do_array 3, EPM_utility_array_ID, 'bmi.0', bmcount          -- Index says how many bookmarks there are
  113.    bmcount = bmcount + 1
  114.    do_array 2, EPM_utility_array_ID, 'bmi.0', bmcount          -- Store back the new number
  115.    do_array 2, EPM_utility_array_ID, 'bmi.'bmcount, markname -- Store the new name at this index position
  116.    oldmod = .modify
  117.    if not isnum(perm) then perm=3; endif
  118.    insert_attribute BOOKMARK_CLASS, bmcount, perm, 0, col, line
  119.    if perm=4 then
  120.       call attribute_on(8)  -- "Save attributes" flag
  121.    else
  122.       .modify = oldmod
  123.    endif
  124.    getfileid fid
  125.    bmcount = bmcount fid perm
  126.    do_array 2, EPM_utility_array_ID, 'bmn.'markname, bmcount -- Store the index & fileid under this name
  127.  
  128. compile if EVERSION >= '5.50' & INCLUDE_WORKFRAME_SUPPORT
  129. defc compiler_error
  130.    universal EPM_utility_array_ID
  131.    universal defaultmenu, activemenu
  132.    parse arg markname perm line col .
  133.    if not line then line=.line; endif
  134.    'bm' markname perm line col
  135.    color = COMPILER_ERROR_COLOR
  136.    oldmod = .modify
  137.    getfileid fid
  138.    Insert_Attribute_Pair(COLOR_CLASS, color, line, line, 1, length(textline(line)), fid)
  139.    .modify = oldmod
  140.    call attribute_on(1)  -- Colors flag
  141.    if perm=16 then
  142.       if not attribute_on(16) then  -- Was attribute 16 off?
  143.  compile if INCLUDE_STD_MENUS
  144.          deletemenu defaultmenu, 6, 0, 0                -- Delete the Help menu
  145.  compile endif
  146.          buildsubmenu defaultmenu, 16, COMPILER_BAR__MSG, COMPILER_BARP__MSG, 0, 0
  147.              buildmenuitem defaultmenu, 16, 1601, NEXT_COMPILER_MENU__MSG, 'nextbookmark N 16'NEXT_COMPILER_MENUP__MSG, 1, 0
  148.              buildmenuitem defaultmenu, 16, 1602, PREV_COMPILER_MENU__MSG, 'nextbookmark P 16'PREV_COMPILER_MENUP__MSG, 1, 0
  149.              buildmenuitem defaultmenu, 16, 1603, \0,                '',                  4, 0
  150.              buildmenuitem defaultmenu, 16, 1604, DESCRIBE_COMPILER_MENU__MSG, 'compiler_help'DESCRIBE_COMPILER_MENUP__MSG,     1, 0
  151.              buildmenuitem defaultmenu, 16, 1605, \0,                '',                  4, 0
  152.              buildmenuitem defaultmenu, 16, 1606, CLEAR_ERRORS_MENU__MSG, 'compiler_clear'CLEAR_ERRORS_MENUP__MSG,     1, 0
  153.  compile if INCLUDE_STD_MENUS
  154.          call add_help_menu(defaultmenu, 1)
  155.  compile endif
  156.          if activemenu=defaultmenu  then
  157.             showmenu activemenu
  158.          endif
  159.       endif  -- "Added Compiler" flag
  160.    endif
  161.  
  162. defc compiler_help
  163.    universal EPM_utility_array_ID
  164.    line = .line; col = 1; offst = -300
  165.    do forever
  166.       class = BOOKMARK_CLASS
  167.       attribute_action 1, class, offst, col, line  -- 1=FIND NEXT ATTR
  168.       if class=0 | line<>.line then
  169.          sayerror NO_COMPILER_ERROR__MSG
  170.          return
  171.       endif
  172.       query_attribute class, val, IsPush, offst, col, line
  173.       if IsPush<>16 then iterate; endif  -- If not a compiler error class, skip
  174.       call get_array_value(EPM_utility_array_ID, 'bmi.'val, markname)  -- Get name for mark
  175.       if leftstr(markname,9)<>'WB_ERROR_' then iterate; endif  -- ?  Curious...
  176.       leave
  177.    enddo
  178.    parse value substr(markname,10) with linenum '_' errornum
  179.    bufhndl = buffer(CREATEBUF, 'COMPILER', MAXBUFSIZE, 1 )  -- create a private buffer
  180.    if not bufhndl then sayerror 'CREATEBUF' ERROR_NUMBER__MSG RC; return; endif
  181.    call windowmessage(0,  getpminfo(EPMINFO_EDITCLIENT),   -- Post message to edit client
  182.                       5444,               -- get compiler error messages for this line
  183.                       linenum,
  184.                       mpfrom2short(bufhndl,0) )
  185.  
  186. defc compiler_message
  187.    parse arg numlines bufsize emsgbuffer .
  188.    emsgbufptr = atol(emsgbuffer)
  189.    emsgbufseg = itoa(substr(emsgbufptr,3),10)
  190.    call listbox(DESCRIBE_ERROR__MSG,
  191. compile if EPM32
  192.                 \0 || atol(bufsize) || emsgbufptr || 7,
  193. compile else
  194.                 \0 || atoi(bufsize) || substr(emsgbufptr,3,2)  || leftstr(emsgbufptr,2) || 7,
  195. compile endif -- EPM32
  196.                 '/'DETAILS__MSG'/'Cancel__MSG'/'Help__MSG,0,1,min(numlines,12),0,
  197. compile if EVERSION >= 5.60
  198.                 gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(6090) ||
  199. compile else
  200.                 atoi(1) || atoi(1) || atoi(6090) || gethwndc(APP_HANDLE) ||
  201. compile endif
  202.                 SELECT_ERROR__MSG)
  203.    call buffer(FREEBUF, emsgbufseg)
  204.  
  205. defc compiler_help_add
  206.    universal CurrentHLPFiles
  207.    hlpfile = upcase(word(arg(1),1))
  208.    if not wordpos(hlpfile, upcase(CurrentHLPFiles)) then
  209.       hwndHelpInst = windowmessage(1,  getpminfo(APP_HANDLE),
  210. compile if EVERSION >= 5.51  -- was: 5.60
  211.                          5429,      -- EPM_Edit_Query_Help_Instance
  212. compile else
  213.                          5139,      -- EPM_QueryHelpInstance
  214. compile endif
  215.                          0,
  216.                          0)
  217.       if hwndHelpInst==0 then
  218.          -- there isn't a help instance deal with.
  219.          Sayerror NO_HELP_INSTANCE__MSG
  220.          return
  221.       endif
  222.  
  223.       newlist2 = CurrentHLPFiles hlpfile \0
  224.       retval = windowmessage(1,  hwndHelpInst,
  225.                           557,    -- HM_SET_HELP_LIBRARY_NAME
  226.                           ltoa(offset(newlist2) || selector(newlist2), 10),
  227.                           0)
  228.       if retval then
  229.          sayerror ERROR__MSG retval ERROR_ADDING_HELP__MSG hlpfile
  230.             -- revert to the previous version of the HLP list.
  231.          newlist2 = CurrentHLPFiles\0
  232.          retval2 = windowmessage(1,  hwndHelpInst,
  233.                              557,    -- HM_SET_HELP_LIBRARY_NAME
  234.                              ltoa(offset(newlist2) || selector(newlist2), 10),
  235.                              0)
  236.          if retval2 then
  237.             sayerror ERROR__MSG retval ERROR_REVERTING__MSG CurrentHLPFiles
  238.          endif
  239.          return
  240.       else
  241.          CurrentHLPFiles = CurrentHLPFiles hlpfile
  242.       endif
  243.    endif
  244.  
  245. defc compiler_clear
  246.    universal EPM_utility_array_ID
  247.    line=0; col=1; offst=0; empty = ''
  248.    oldmod = .modify
  249.    do forever
  250.       class = BOOKMARK_CLASS
  251.       attribute_action 1, class, offst, col, line -- 1=FIND NEXT ATTR
  252.       if class=0 then leave; endif  -- No more of that class
  253.       query_attribute class, val, IsPush, offst, col, line
  254.       if IsPush=16 then
  255.          attribute_action 16, class, offst, col, line -- 16=Delete attribute
  256.          if not get_array_value(EPM_utility_array_ID, 'bmi.'val, markname) then  -- Found that bookmark's name
  257.             display -2
  258.             do_array 2, EPM_utility_array_ID, 'bmi.'val, empty  -- Delete the name
  259.             do_array 2, EPM_utility_array_ID, 'bmn.'markname, empty -- Delete the index
  260.             display 2
  261.          endif
  262.          class = COLOR_CLASS
  263.          offst=-300
  264.          col = 1
  265.          line2 = line
  266.          attribute_action 1, class, offst, col, line2 -- 1=FIND NEXT ATTR
  267.          if class=0 | line2<>line then iterate; endif  -- No color class
  268.          query_attribute class, val, IsPush, offst, col, line
  269.          if val<>COMPILER_ERROR_COLOR then iterate; endif  -- Not the right color
  270.          offst2 = offst; col2 = col
  271.          attribute_action 3, class, offst2, col2, line2 -- 3=FIND MATCH ATTR
  272.          if class then
  273.             attribute_action 16, class, offst2, col2, line2 -- 16=Delete attribute
  274.          endif
  275.          class = COLOR_CLASS
  276.          attribute_action 16, class, offst, col, line -- 16=Delete attribute
  277.       endif
  278.    enddo
  279.    .modify = oldmod
  280. compile endif
  281.  
  282. defc setmarkp  -- Following uses a new dialog, so no NLS xlation
  283.    markname = entrybox(SETMARK_PROMPT__MSG, '/'Setp__MSG'/'Cancel__MSG,\0,'',200)
  284.    if markname then
  285.       'setmark' markname 4
  286.    endif
  287.  
  288. defc go, gomark
  289.    universal EPM_utility_array_ID
  290.    parse arg markname
  291.    if not markname then
  292.       sayerror NEED_BM_NAME__MSG; return
  293.    endif
  294.    rc = get_array_value(EPM_utility_array_ID, 'bmn.'markname, bmindex)  -- Find that bookmark name
  295.    parse value bmindex with bmindex fid .
  296.    if rc | fid='' then  -- FID='' means previously deleted.
  297.       sayerror UNKNOWN_BOOKMARK__MSG
  298.       return
  299.    endif
  300.    empty = ''
  301.    display -2
  302.    activatefile fid
  303.    display 2
  304.    if rc then
  305.       do_array 2, EPM_utility_array_ID, 'bmi.'bmindex, empty  -- Delete the name
  306.       do_array 2, EPM_utility_array_ID, 'bmn.'markname, empty -- Delete the index
  307.       sayerror FILE_GONE__MSG BM_DELETED__MSG
  308.       return
  309.    endif
  310. ;  call psave_pos(savepos)
  311.    line=0; col=1; offst=0
  312.    do forever
  313.       class = BOOKMARK_CLASS
  314.       attribute_action 1, class, offst, col, line -- 1=FIND NEXT ATTR
  315.       if class=0 then leave; endif
  316.       query_attribute class, val, IsPush, offst, col, line
  317.       if val=bmindex then
  318.          .cursory=.windowheight%2
  319.          line; .col=col
  320.          return
  321.       endif
  322.    enddo
  323. ;  call prestore_pos(savepos)
  324.    do_array 2, EPM_utility_array_ID, 'bmi.'bmindex, empty  -- Delete the name
  325.    do_array 2, EPM_utility_array_ID, 'bmn.'markname, empty -- Delete the index
  326.    sayerror BM_NOT_FOUND__MSG ITS_DELETED__MSG
  327.  
  328. defc listmark
  329. compile if EVERSION < 5.21
  330.    markname = listmark(GOMARK__MSG)
  331.    if markname<>'' then 'gomark' markname; endif
  332.  
  333. defc listdeletebm
  334.    markname = listmark(DELETEMARK__MSG)
  335.    if markname<>'' then 'deletebm' markname; endif
  336.  
  337. defproc listmark(button_text)
  338. compile endif  -- EVERSION < 5.21
  339.    universal EPM_utility_array_ID
  340.    do_array 3, EPM_utility_array_ID, 'bmi.0', bmcount          -- Index says how many bookmarks there are
  341.    if bmcount = 0 then sayerror NO_BOOKMARKS__MSG; return; endif
  342.    'xcom e /c bookmark'
  343.    if rc<>-282 then  -- -282 = sayerror("New file")
  344.       sayerror ERROR__MSG rc BAD_TMP_FILE__MSG sayerrortext(rc)
  345.       return
  346.    endif
  347.    browse_mode = browse()     -- query current state
  348.    if browse_mode then call browse(0); endif
  349.    .autosave = 0
  350.    getfileid bmfid
  351.    empty = ''
  352.    display -2
  353.    do i=1 to bmcount
  354.       do_array 3, EPM_utility_array_ID, 'bmi.'i, markname   -- Get name number i
  355.       if markname='' then iterate; endif  -- has been deleted
  356.        -- Find that bookmark name
  357.       if get_array_value(EPM_utility_array_ID, 'bmn.'markname, bmindex) then  -- Unexpected; ignore it & continue
  358.          iterate
  359.       endif
  360.       parse value bmindex with bmindex fid .
  361.       rc = 0
  362.       activatefile fid
  363.       if rc then  -- The file's gone; don't show the bookmark.
  364.          do_array 2, EPM_utility_array_ID, 'bmi.'bmindex, empty  -- Delete the name
  365.          do_array 2, EPM_utility_array_ID, 'bmn.'markname, empty -- Delete the index
  366.          iterate
  367.       endif
  368.       insertline markname, bmfid.last+1, bmfid
  369.    enddo
  370.    activatefile bmfid
  371. compile if SORT_BOOKMARKS
  372.    if .last>2 then
  373.       call sort(2, .last, 1, 40, bmfid, 'I')
  374.    endif
  375. compile endif -- SORT_BOOKMARKS
  376.    if browse_mode then call browse(1); endif  -- restore browse state
  377.    display 2
  378.    if not .modify then  -- Nothing added?
  379.       sayerror NO_BOOKMARKS__MSG
  380.       'xcom quit'
  381.       return
  382.    endif
  383.    buflen = filesize() + .last + 1
  384.    bufhndl = buffer(CREATEBUF, 'LISTBOX', buflen, 1 )  -- create a private buffe
  385.    if not bufhndl then sayerror 'CREATEBUF' ERROR_NUMBER__MSG RC; return; endif
  386.    noflines = buffer(PUTBUF, bufhndl, 1, 0, APPENDCR)
  387.    .modify = 0
  388.    'xcom quit'
  389. ;  display 1
  390.    if not noflines then sayerror 'PUTBUF' ERROR_NUMBER__MSG RC; return; endif
  391.    usedsize = buffer(USEDSIZEBUF,bufhndl)
  392. compile if EVERSION < 5.21  -- The old way
  393.    ret = listbox(LIST_BOOKMARKS__MSG,
  394.                  \0 || atoi(usedsize) || atoi(bufhndl)  || atoi(32),
  395.                  '/'button_text'/Cancel',1,5,min(noflines,12))
  396.    call buffer(FREEBUF, bufhndl)
  397.    return ret
  398. compile else
  399.    parse value listbox(LIST_BOOKMARKS__MSG,
  400.  compile if EPM32
  401.                        \0 || atol(usedsize) || atoi(32) || atoi(bufhndl),
  402.  compile else
  403.                        \0 || atoi(usedsize) || atoi(bufhndl) || atoi(32),
  404.  compile endif -- EPM32
  405.                        '/'GOMARK__MSG'/'DELETEMARK__MSG'/'Cancel__MSG'/'Help__MSG,1,5,min(noflines,12),0,
  406.  compile if EVERSION >= 5.60
  407.                        gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(6030)) with button 2 markname \0
  408.  compile else
  409.                        atoi(1) || atoi(1) || atoi(6030) || gethwndc(APP_HANDLE)) with button 2 markname \0
  410.  compile endif
  411.    call buffer(FREEBUF, bufhndl)
  412.    if button=\1 then  -- Go to
  413.       'gomark' markname
  414.    elseif button=\2 then
  415.       'deletebm' markname
  416.    endif
  417. compile endif -- EVERSION < 5.21
  418.  
  419. defc deletebm
  420.    universal EPM_utility_array_ID
  421.    parse arg markname
  422.    if not markname then
  423.       sayerror NEED_BM_NAME__MSG; return
  424.    endif
  425.    if get_array_value(EPM_utility_array_ID, 'bmn.'markname, bmindex) then
  426.       sayerror UNKNOWN_BOOKMARK__MSG
  427.       return
  428.    endif
  429.    empty = ''
  430.    parse value bmindex with bmindex fid perm .
  431.    do_array 2, EPM_utility_array_ID, 'bmi.'bmindex, empty  -- Delete the name
  432.    do_array 2, EPM_utility_array_ID, 'bmn.'markname, empty -- Delete the index
  433. ;; call psave_pos(savepos)
  434.    sayerror BM_DELETED__MSG
  435.    getfileid startid
  436.    display -2
  437.    activatefile fid
  438.    display 2
  439.    if rc then  -- File no longer in ring - all done.
  440.       return
  441.    endif
  442.    line=0; col=1; offst=0
  443.    do forever
  444.       class = BOOKMARK_CLASS
  445.       attribute_action 1, class, offst, col, line -- 1=FIND NEXT ATTR
  446.       if class=0 then leave; endif
  447.       query_attribute class, val, IsPush, offst, col, line
  448.       if val=bmindex then
  449.          oldmod = .modify
  450.          attribute_action 16, class, offst, col, line -- 16=Delete attribute
  451.          if perm<>4 then .modify=oldmod; endif
  452.          leave
  453.       endif
  454.    enddo
  455.    activatefile startid
  456.  
  457. defc deletebmclass
  458.    universal EPM_utility_array_ID
  459.    parse arg BMtype .
  460.    if BMtype='' then
  461.       sayerror NEED_BM_CLASS__MSG; return
  462.    endif
  463.    if BMtype=4 then
  464.       if askyesno(DELETE_PERM_BM__MSG) <> YES_CHAR then return; endif
  465.    endif
  466.    line=0; col=1; offst=0; empty = ''
  467.    oldmod = .modify
  468.    do forever
  469.       class = BOOKMARK_CLASS
  470.       attribute_action 1, class, offst, col, line -- 1=FIND NEXT ATTR
  471.       if class=0 then leave; endif  -- No more of that class
  472.       query_attribute class, val, IsPush, offst, col, line
  473.       if IsPush=BMtype then
  474.          attribute_action 16, class, offst, col, line -- 16=Delete attribute
  475.          if not get_array_value(EPM_utility_array_ID, 'bmi.'val, markname) then  -- Found that bookmark's name
  476.             display -2
  477.             do_array 2, EPM_utility_array_ID, 'bmi.'val, empty  -- Delete the name
  478.             do_array 2, EPM_utility_array_ID, 'bmn.'markname, empty -- Delete the index
  479.             display 2
  480.          endif
  481.       endif
  482.    enddo
  483.    if BMtype<>4 then .modify=oldmod; endif
  484.  
  485. ; Dependencies:  put_file_as_MVST()
  486. defc saveattributes
  487.    universal EPM_utility_array_ID
  488.    universal app_hini
  489.    universal default_font
  490.    getfileid start_fid
  491. ;; call psave_pos(savepos)
  492.    'xcom e /c attrib'
  493.    if rc<>-282 then  -- -282 = sayerror("New file")
  494.       sayerror ERROR__MSG rc BAD_TMP_FILE__MSG sayerrortext(rc)
  495.       return
  496.    endif
  497.    browse_mode = browse()     -- query current state
  498.    if browse_mode then call browse(0); endif
  499.    .autosave = 0
  500.    getfileid attrib_fid
  501.    delete  -- Delete the empty line
  502. ;; activatefile start_fid
  503.    line=0; col=1; offst=0; found_font = 0
  504.    style_line=0; style_col=0; style_offst=0; style_list=''
  505.    do forever
  506.       class = 0  -- Find any class
  507.       attribute_action 1, class, offst, col, line, start_fid -- 1=FIND NEXT ATTR
  508.       if class=0 then leave; endif
  509.       query_attribute class, val, IsPush, offst, col, line, start_fid
  510.       l = line
  511.       if class=BOOKMARK_CLASS then  -- get name
  512.          if IsPush<>4 then iterate; endif    -- If not permanent, don't keep it.
  513.          do_array 3, EPM_utility_array_ID, 'bmi.'val, bmname  -- Get the name
  514.          l = l bmname
  515.       elseif class=COLOR_CLASS then  -- don't save if out of range
  516. ;;       if val>255 then iterate; endif
  517.          if line=style_line & col=style_col & (offst=style_offst+1 | offst=style_offst+2) then iterate; endif
  518. ;;       if line=style_line & col=style_col & offst=style_offst+2 then iterate; endif
  519. compile if EVERSION >= 5.50
  520.       elseif class=FONT_CLASS then  -- get font info
  521. ;;       if val>255 then iterate; endif
  522.          if line=style_line & col=style_col & offst=style_offst+1 then iterate; endif
  523.          l = l queryfont(val)
  524.          found_font = 1
  525. compile endif
  526.       elseif class=STYLE_CLASS then  -- get style info
  527.          do_array 3, EPM_utility_array_ID, 'si.'val, stylename -- Get the style name
  528.          style_line=line; style_col=col; style_offst=offst
  529.          l = l stylename
  530.          if val<256 & not pos(chr(val), style_list) then  -- a style we haven't seen yet
  531.             if style_list='' then
  532.                'xcom e /c style'
  533.                if rc<>-282 then  -- -282 = sayerror("New file")
  534.                   sayerror ERROR__MSG rc BAD_TMP_FILE__MSG sayerrortext(rc)
  535.                   if browse_mode then call browse(1); endif  -- restore browse state
  536.                   return
  537.                endif
  538.                .autosave = 0
  539.                getfileid style_fid
  540.                delete  -- Delete the empty line
  541.             endif
  542.             style_list = style_list || chr(val)
  543. compile if WANT_APPLICATION_INI_FILE
  544.             insertline stylename || \0 || queryprofile(app_hini, 'Style', stylename), style_fid.last+1, style_fid
  545. compile else
  546.             insertline stylename || \0 , style_fid.last+1, style_fid
  547. compile endif
  548.          endif  -- new style
  549.       endif  -- class=STYLE_CLASS
  550.       insertline class val ispush offst col l, attrib_fid.last+1, attrib_fid
  551.    enddo
  552. compile if EVERSION >= 5.50
  553.    if found_font & .font <> default_font then
  554.       insertline FONT_CLASS .font 0 0 0 (-1) queryfont(start_fid.font), 1, attrib_fid  -- Insert at beginning.
  555.    endif
  556. compile endif
  557.    call put_file_as_MVST(attrib_fid, start_fid, 'EPM.ATTRIBUTES')
  558.    if style_list <> '' then
  559.       call put_file_as_MVST(style_fid, start_fid, 'EPM.STYLES')
  560.       style_fid.modify = 0
  561.       'xcom quit'
  562.    endif
  563.    attrib_fid.modify = 0
  564.    'xcom quit'
  565.    if browse_mode then call browse(1); endif  -- restore browse state
  566.  
  567. ; Dependencies:  find_ea() from EA.E
  568. defc loadattributes
  569.    universal EPM_utility_array_ID, app_hini, load_var
  570.    getfileid fid
  571.    oldmod = .modify
  572.    val = get_EAT_ASCII_value('EPM.TABS')
  573.    if val<>'' then
  574.       .tabs = val
  575.       load_var = load_var + 1  -- Flag that Tabs were set via EA
  576.    endif
  577.    val = get_EAT_ASCII_value('EPM.MARGINS')
  578.    if val<>'' then
  579.       .margins = val
  580.       load_var = load_var + 2  -- Flag that Tabs were set via EA
  581.    endif
  582.    if find_ea('EPM.STYLES', ea_seg, ea_ofs, ea_ptr1, ea_ptr2, ea_len, ea_entrylen, ea_valuelen) then
  583.       val = peek(ea_seg, ea_ptr2,min(ea_valuelen,8))
  584.       if leftstr(val,2)=EAT_MVST & substr(val,7,2)=EAT_ASCII then
  585.          num = itoa(substr(val,5,2),10)
  586.          ea_ptr2 = ea_ptr2 + 8
  587.          do i=1 to num
  588.             len = itoa(peek(ea_seg, ea_ptr2, 2), 10)
  589.             parse value peek(ea_seg, ea_ptr2 + 2, len) with stylename \0 stylestuff
  590. compile if WANT_APPLICATION_INI_FILE
  591.             if queryprofile(app_hini, 'Style', stylename)='' then  -- Don't have as a local style?
  592.                call setprofile(app_hini, 'Style', stylename, stylestuff)  -- Add it.
  593.             endif
  594. compile endif
  595.             ea_ptr2 = ea_ptr2 + len + 2
  596.          enddo
  597.       endif
  598.    endif
  599.    need_colors=0; need_fonts=0
  600.    if find_ea('EPM.ATTRIBUTES', ea_seg, ea_ofs, ea_ptr1, ea_ptr2, ea_len, ea_entrylen, ea_valuelen) then
  601.       val = peek(ea_seg, ea_ptr2,min(ea_valuelen,8))
  602.       if leftstr(val,2)=EAT_MVST & substr(val,7,2)=EAT_ASCII then
  603.          num = itoa(substr(val,5,2),10)
  604.          ea_ptr2 = ea_ptr2 + 8
  605.          do_array 3, EPM_utility_array_ID, 'bmi.0', bmcount          -- Index says how many bookmarks there are
  606.          do_array 3, EPM_utility_array_ID, 'si.0', stylecount
  607.          fontsel=''; bg=''  -- Initialize to simplify later test
  608.          do i=1 to num
  609.             len = itoa(peek(ea_seg, ea_ptr2, 2), 10)
  610.             parse value peek(ea_seg, ea_ptr2 + 2, len) with class val ispush offst col line rest
  611.             ea_ptr2 = ea_ptr2 + len + 2
  612.             if class=BOOKMARK_CLASS then  -- get name
  613.                if not get_array_value(EPM_utility_array_ID, 'bmn.'rest, stuff) then  -- See if we already had it
  614.                   parse value stuff with oldindex oldfid .
  615.                   if oldfid = fid then
  616.                      'deletebm' rest
  617.                   endif
  618.                endif
  619.                bmcount = bmcount + 1
  620.                do_array 2, EPM_utility_array_ID, 'bmi.'bmcount, rest -- Store the name at this index position
  621.                if IsPush<2 then IsPush=4; endif  -- Update old-style bookmarks
  622.                stuff = bmcount fid IsPush  -- flag as permanent
  623.                do_array 2, EPM_utility_array_ID, 'bmn.'rest, stuff -- Store the index & fileid under this name
  624.                val = bmcount  -- Don't care what the old index was.
  625.             elseif class=COLOR_CLASS then
  626.                need_colors = 1
  627. compile if EVERSION >= 5.50  -- GPI has font support
  628.             elseif class=FONT_CLASS then
  629.                parse value rest with fontname '.' fontsize '.' fontsel
  630.                if fontsel='' then iterate; endif  -- Bad value; discard it
  631.                val=registerfont(fontname, fontsize, fontsel)  -- Throw away old value
  632.                if line=-1 then
  633.                   .font = val
  634.                   iterate
  635.                endif
  636.                need_fonts = 1
  637. compile endif
  638.             elseif class=STYLE_CLASS then  -- Set style info
  639. compile if WANT_APPLICATION_INI_FILE
  640.                parse value rest with stylename .
  641.                stylestuff = queryprofile(app_hini, 'Style', stylename)
  642.                if stylestuff='' then iterate; endif  -- Shouldn't happen
  643.                parse value stylestuff with fontname '.' fontsize '.' fontsel '.' fg '.' bg
  644.                if get_array_value(EPM_utility_array_ID, 'sn.'stylename, val) then  -- Don't have it; add:
  645.                   stylecount = stylecount + 1                                 -- Increment index
  646.                   do_array 2, EPM_utility_array_ID, 'si.'stylecount, stylename  -- Save index.name
  647.                   do_array 2, EPM_utility_array_ID, 'sn.'stylename, stylecount  -- Save name.index
  648.                   val = stylecount
  649.                endif
  650. compile else
  651.                iterate
  652. compile endif
  653.             endif
  654.             insert_attribute class, val, ispush, 0, col, line
  655.             if class=STYLE_CLASS then  -- Set style info
  656. compile if EVERSION >= 5.50  -- GPI has font support
  657.                if fontsel<>'' then
  658.                   fontid=registerfont(fontname, fontsize, fontsel)
  659.                   if fontid<>.font then  -- Only insert font change for style if different from base font.
  660.                      insert_attribute FONT_CLASS, fontid, ispush, 0, col, line
  661.                      need_fonts = 1
  662.                   endif
  663.                endif
  664. compile endif
  665.                if bg<>'' then
  666.                   insert_attribute COLOR_CLASS, bg*16 + fg, ispush, 0, col, line
  667.                   need_colors = 1
  668.                endif
  669.             endif
  670.          enddo
  671.          do_array 2, EPM_utility_array_ID, 'bmi.0', bmcount          -- Store back the new number
  672.          do_array 2, EPM_utility_array_ID, 'si.0', stylecount
  673.          if need_colors then
  674.             call attribute_on(1)  -- Colors flag
  675.          endif
  676. compile if EVERSION >= 5.50  -- GPI has font support
  677.          if need_fonts then
  678.             call attribute_on(4)  -- Mixed fonts flag
  679.          endif
  680. compile endif
  681.          call attribute_on(8)  -- "Save attributes" flag
  682.       else
  683.          sayerror UNEXPECTED_ATTRIB__MSG
  684.       endif
  685.    endif
  686.    .modify = oldmod
  687.  
  688. defc nextbookmark
  689.    parse arg next bmclass .
  690.    class = BOOKMARK_CLASS
  691.    col = .col; line=.line; offst=0
  692.    if next='P' then col=col-1; endif
  693.    do forever
  694.       attribute_action 1+(next='P'), class, offst, col, line -- 1=FIND NEXT ATTR; 2=FIND PREV ATTR
  695.       if class=0 then
  696.          sayerror BM_NOT_FOUND__MSG
  697.          return
  698.       endif
  699.       query_attribute class, val, IsPush, offst, col, line
  700.       if IsPush=bmclass | bmclass='' then
  701.          .cursory=.windowheight%2
  702.          line; .col=col
  703.          return
  704.       endif
  705.    enddo
  706.  
  707. ; The following routine will put the contents of the current file into the
  708. ; .EAarea of another file as an MVST EAT_ASCII attribute.  If the given
  709. ; attribute name already exists, it will be replaced (not extended).
  710. ; Dependencies:  delete_ea()
  711. defproc put_file_as_MVST(source_fid, target_fid, ea_name)
  712.    getfileid start_fid
  713.    activatefile target_fid
  714.    call delete_ea(ea_name)
  715.    if not source_fid.last then  -- If nothing to add,
  716.       activatefile start_fid
  717.       return                    -- we're all done.
  718.    endif
  719.    activatefile source_fid  -- So filesize() will work
  720.    name_len = length(ea_name)
  721.    value_len = filesize() + 2 * .last + 8  -- Overhead: 2 bytes/rec length, + 2 bytes each EAT_MVST, codepage, numentries, EAT_ASCII
  722.    ea_len_incr = 5 + name_len + value_len  -- Overhead: 1 flags, 1 len(name), 2 len(value), 1 null ASCIIZ terminator
  723. compile if EPM32
  724.    -- +7 rather than +3 because previous calc didn't consider the length
  725.    --    of the length field.
  726.    ea_len_incr = ((ea_len_incr + 7)%4)*4;  -- round up for long word multiples
  727. compile endif
  728.    activatefile target_fid
  729.    if .eaarea then
  730.       ea_long = atol(.eaarea)
  731.       ea_seg = itoa(rightstr(ea_long,2),10)
  732.       ea_ofs = itoa(leftstr(ea_long,2),10)
  733.       ea_old_len  = ltoa(peek(ea_seg, ea_ofs, 4),10)
  734. compile if EPM32
  735.       call dynalink32(E_DLL,
  736.                       'myrealloc',
  737.                       atol(.eaarea) ||
  738.                       atol(ea_old_len+ea_len_incr) ||
  739.                       atol(0),
  740.                       2)
  741.  
  742.       r = 0
  743.  
  744. compile else
  745.       r =  dynalink('DOSCALLS',           -- Dynamic link library name
  746.                '#38',                     -- DosReAllocSeg
  747.                atoi(ea_old_len+ea_len_incr) ||  -- Number of bytes requested
  748.                rightstr(ea_long,2) )
  749. compile endif
  750.       ea_ptr = ea_seg
  751.    else
  752. compile if EPM32
  753.       ea_buffer = dynalink32(E_DLL,
  754.                              'mymalloc',
  755.                              atol(ea_len_incr+4), 2)
  756.  
  757.       ea_buffer = atol(ea_buffer)
  758.  
  759.       ea_ptr = itoa(substr(ea_buffer,3,2),10)
  760.  
  761.       r = 0
  762.  
  763. compile else
  764.       ea_buffer = "00"                    -- Initialize string pointer.
  765.       r =  dynalink('DOSCALLS',           -- Dynamic link library name
  766.                '#34',                     -- DosAllocSeg
  767.                atoi(ea_len_incr+4)    ||  -- Number of bytes requested
  768.                address(ea_buffer)     ||
  769.                atoi(0) )                  -- Share information
  770.       ea_ptr = itoa(ea_buffer,10)
  771. compile endif
  772.       ea_ofs = 0
  773.       ea_old_len  = 4           -- Point past length field
  774.    endif
  775.  
  776.    if r then sayerror ERROR__MSG r ALLOC_HALTED__MSG; stop; endif
  777.    poke ea_ptr, ea_ofs, atol(ea_old_len+ea_len_incr)
  778.    ea_ofs = ea_ofs + ea_old_len
  779. compile if EPM32
  780.    poke ea_ptr, ea_ofs  , atol(ea_len_incr) -- Start of EA:  flag byte
  781.    ea_ofs = ea_ofs + 4;
  782. compile endif
  783.    poke ea_ptr, ea_ofs  , \0              -- Start of EA:  flag byte
  784.    poke ea_ptr, ea_ofs+1, chr(name_len)
  785.    poke ea_ptr, ea_ofs+2, atoi(value_len)
  786.    poke ea_ptr, ea_ofs+4, ea_name
  787.    poke ea_ptr, ea_ofs+4+name_len, \0     -- Null byte after name
  788.    poke ea_ptr, ea_ofs+5+name_len, EAT_MVST
  789.    poke ea_ptr, ea_ofs+7+name_len, atoi(0)  -- Code page
  790.    poke ea_ptr, ea_ofs+9+name_len, atoi(source_fid.last)  -- NumEntries
  791.    poke ea_ptr, ea_ofs+11+name_len, EAT_ASCII  -- Each entry is of type ASCII
  792.    ea_ofs = ea_ofs + 13 + name_len
  793.    do i=1 to source_fid.last
  794.       getline line, i, source_fid
  795.       poke ea_ptr, ea_ofs, atoi(length(line))
  796.       poke ea_ptr, ea_ofs+2, line
  797.       ea_ofs = ea_ofs + length(line) + 2
  798.    enddo
  799.    .eaarea = mpfrom2short(ea_ptr,0)
  800.    activatefile start_fid
  801.  
  802.