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