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