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

  1. ; Various routines used for manipulating extended attributes.  Used by EPM.
  2.  
  3. const
  4.    EAT_ASCII    = \253\255    -- FFFD
  5.    EAT_MVMT     = \223\255    -- FFDF
  6.  
  7. ;  Returns 1 if attribute name exists; sets VAR args.  EA_SEG, EA_OFS =
  8. ; start of EA buffer.  EA_PTR1, 2 = pointers to start of entry and value,
  9. ; respectively, if name was found.  EA_LEN, EA_ENTRYLEN, EA_VALUELEN = length
  10. ; of EA area, of entry, and of value, respectively.
  11. ; Dependencies:  None
  12. defproc find_ea(name, var ea_seg, var ea_ofs, var ea_ptr1, var ea_ptr2, var ea_len, var ea_entrylen, var ea_valuelen) =
  13.    ea_long = atol(.eaarea)
  14. ;  ea_seg = itoa(rightstr(ea_long,2),10)
  15.    ea_seg = ltoa(rightstr(ea_long,2)\0\0,10)
  16. ;  ea_ofs = itoa(leftstr(ea_long,2),10)
  17.    ea_ofs = ltoa(leftstr(ea_long,2)\0\0,10)
  18.    if not .eaarea then return ''; endif
  19.    ea_len  = ltoa(peek(ea_seg, ea_ofs, 4),10)
  20.    ea_end = ea_ofs + ea_len
  21.    ea_ptr1 = ea_ofs + 4                     -- Point past length of FEAList
  22.    do while ea_ptr1 < ea_len
  23. ;     ea_flag = itoa(peek(ea_seg, ea_ptr1, 1)\0,16)
  24. compile if EVERSION < '6.00'
  25.       ea_namelen  = asc(peek(ea_seg, ea_ptr1+1, 1))
  26.       ea_valuelen = ltoa(peek(ea_seg, ea_ptr1+2, 2)\0\0,10)
  27.       ea_entrylen = ea_namelen + 5 + ea_valuelen
  28.       if name = peekz(ea_seg, ea_ptr1+4) then
  29.          ea_ptr2 = ea_ptr1+5+ea_namelen  -- Point to start of EA value
  30.          return 1
  31.       endif
  32. compile else
  33.       ea_namelen  = asc(peek(ea_seg, ea_ptr1+5, 1))
  34.       ea_valuelen = ltoa(peek(ea_seg, ea_ptr1+6, 2)\0\0,10)
  35.       ea_entrylen = ltoa(peek(ea_seg, ea_ptr1, 4),10)
  36.       if not ea_entrylen then
  37.          ea_entrylen = ea_len - ea_ptr1
  38.       endif
  39.       if name = peekz(ea_seg, ea_ptr1+8) then
  40.          ea_ptr2 = ea_ptr1+9+ea_namelen  -- Point to start of EA value
  41.          return 1
  42.       endif
  43. compile endif
  44.       ea_ptr1 = ea_ptr1 + ea_entrylen       -- Point to start of next entry
  45.    enddo
  46.  
  47.  
  48. ; Dependencies:  None
  49. defc addea, add_ea =                 -- Adds a single name / value pair to an existing EA list
  50.    parse arg name data
  51.    if name='' then
  52.       sayerror 'ADD_EA <name> <value> adds the extended attribute value specified to the current file.'
  53.       return
  54.    endif
  55.    name_len = length(name)
  56.    data_len = length(data)
  57. compile if EPM32
  58.    ea_len_incr = ((16 + name_len + data_len)%4)*4;  -- align on 32bit boundary (+13 for overhead +3 for rounding)
  59. compile else
  60.    ea_len_incr = 9 + name_len + data_len
  61. compile endif
  62.    if .eaarea then
  63.       ea_long = atol(.eaarea)
  64. ;     ea_seg = itoa(rightstr(ea_long,2),10)
  65.       ea_seg = ltoa(rightstr(ea_long,2)\0\0,10)
  66. ;     ea_ofs = itoa(leftstr(ea_long,2),10)
  67.       ea_ofs = ltoa(leftstr(ea_long,2)\0\0,10)
  68.       ea_old_len  = ltoa(peek(ea_seg, ea_ofs, 4),10)
  69. compile if EPM32
  70.       dynalink32(E_DLL,
  71.                  'myrealloc',
  72.                  ea_long ||
  73.                  atol(ea_old_len+ea_len_incr) ||
  74.                  atol(0),
  75.                  2)
  76.  
  77.       r = 0
  78. compile else
  79.       r =  dynalink('DOSCALLS',           -- Dynamic link library name
  80.                '#38',                     -- DosReAllocSeg
  81.                atoi(ea_old_len+ea_len_incr) ||  -- Number of bytes requested
  82.                rightstr(ea_long,2) )
  83. compile endif  -- EPM32
  84.       ea_ptr = ea_seg
  85.    else
  86. compile if EPM32
  87.       ea_buffer = atol(dynalink32(E_DLL,
  88.                                   'mymalloc',
  89.                                   atol(ea_len_incr+4), 2))
  90.  
  91.       ea_ptr  = ltoa(substr(ea_buffer, 3, 2)\0\0, 10)
  92.  
  93.       r = 0
  94. compile else
  95.       ea_buffer = "00"                    -- Initialize string pointer.
  96.       r =  dynalink('DOSCALLS',           -- Dynamic link library name
  97.                '#34',                     -- DosAllocSeg
  98.                atoi(ea_len_incr+4)    ||  -- Number of bytes requested
  99.                address(ea_buffer)     ||
  100.                atoi(0) )                  -- Share information
  101. ;     ea_ptr = itoa(ea_buffer,10)
  102.       ea_ptr = ltoa(ea_buffer\0\0,10)
  103. compile endif  -- EPM32
  104.       ea_ofs = 0
  105.       ea_old_len  = 4           -- Point past length field
  106.    endif
  107.  
  108.    if r then sayerror ERROR__MSG r ALLOC_HALTED__MSG; stop; endif
  109.    poke ea_ptr, ea_ofs, atol(ea_old_len+ea_len_incr)
  110.    ea_ofs = ea_ofs + ea_old_len
  111. compile if EVERSION < '6.00'
  112.    poke ea_ptr, ea_ofs  , \0              -- Start of EA:  flag byte
  113.    poke ea_ptr, ea_ofs+1, chr(name_len)
  114.    poke ea_ptr, ea_ofs+2, atoi(data_len + 4)     -- Value length = len(data) + len(data_type) + len(data_len)
  115.    poke ea_ptr, ea_ofs+4, name
  116.    poke ea_ptr, ea_ofs+4+name_len, \0     -- Null byte after name
  117.    poke ea_ptr, ea_ofs+5+name_len, EAT_ASCII
  118.    poke ea_ptr, ea_ofs+7+name_len, atoi(data_len)
  119.    poke ea_ptr, ea_ofs+9+name_len, data
  120. compile else
  121.  
  122.    -- we need to make sure the last entry is marked with zero length
  123.    --   to find the last entry, just look for
  124.    --   a bogus entry.  "\1\2\4\3\5" seems pretty unlikely.
  125.    call find_ea("\1\2\4\3\5", xx_seg, xx_ofs, xx_ptr1, xx_ptr2, xx_len, xx_entrylen, xx_valuelen);
  126.    if (xx_len>4) and xx_entrylen then
  127.       poke ea_ptr, xx_len-xx_entrylen, atol(xx_entrylen);
  128.    endif
  129.  
  130.    poke ea_ptr, ea_ofs+0, atol(0) -- Start of EA:  size (last one is always marked as zero)
  131.    poke ea_ptr, ea_ofs+4, \0              -- flag byte
  132.    poke ea_ptr, ea_ofs+5, chr(name_len)
  133.    poke ea_ptr, ea_ofs+6, atoi(data_len + 4)     -- Value length = len(data) + len(data_type) + len(data_len)
  134.    poke ea_ptr, ea_ofs+8, name
  135.    poke ea_ptr, ea_ofs+8+name_len, \0     -- Null byte after name
  136.    poke ea_ptr, ea_ofs+9+name_len, EAT_ASCII
  137.    poke ea_ptr, ea_ofs+11+name_len, atoi(data_len)
  138.    poke ea_ptr, ea_ofs+13+name_len, data
  139. compile endif
  140.    .eaarea = mpfrom2short(ea_ptr,0)
  141.  
  142.  
  143. ; Dependencies:  find_ea
  144. defproc get_EAT_ASCII_value(name) =  -- Returns the value for a given attribute name
  145.    if find_ea(name, ea_seg, ea_ofs, ea_ptr1, ea_ptr2, ea_len, ea_entrylen, ea_valuelen) then
  146.       stuff = peek(ea_seg, ea_ptr2, min(ea_valuelen,4))
  147.       if leftstr(stuff,2) = EAT_ASCII & ea_valuelen > 4 then
  148.          return peek(ea_seg, ea_ptr2+4, min(itoa(substr(stuff,3,2),10),MAXCOL))
  149.       endif
  150.    endif
  151.  
  152.  
  153. ; Dependencies:  find_ea()
  154. defproc delete_ea(name) =
  155.    parse arg name .
  156.    if not find_ea(name, ea_seg, ea_ofs, ea_ptr1, ea_ptr2, ea_len, ea_entrylen, ea_valuelen) then
  157.       return
  158.    endif
  159.    newlen = ea_len - ea_entrylen
  160.    poke ea_seg, ea_ofs, atol(newlen)
  161. compile if EVERSION < '5.21'
  162.    junk = 'junk'  -- Avoid problem due to bug in MEMCPYX in EPM 5.20
  163. compile endif
  164.    if ea_ptr1+ea_entrylen < ea_len then  -- If in the middle, close it up
  165.       call memcpyx(atoi(ea_ptr1) || atoi(ea_seg), atoi(ea_ptr1+ea_entrylen) || atoi(ea_seg), ea_len - ea_ptr1 - ea_entrylen)
  166.    endif
  167. compile if EPM32
  168. --   call dynalink32('DOSCALLS',
  169. --                   '#305',                -- DosSetMem
  170. --                   atol(ea_seg\0\0) ||
  171. --                   atol(.eaarea) ||
  172. --                   atol(newlen)  ||
  173. --                   atol(19) )             -- PAG_READ | PAG_WRITE | PAG_COMMIT
  174.    call dynalink32(E_DLL,
  175.                   'myrealloc',
  176.                   \0\0 || ea_seg ||
  177.                   atol(newlen) ||
  178.                   atol(0),
  179.                   2)
  180. compile else
  181.    call dynalink('DOSCALLS',           -- Dynamic link library name
  182.             '#38',                     -- DosReAllocSeg
  183.             atoi(newlen)           ||  -- Number of bytes requested
  184.             atoi(ea_seg) )
  185. compile endif  -- EPM32
  186.  
  187.  
  188. ; Dependencies:  find_ea(), delete_ea(), add_ea
  189. defc type =
  190.    found = find_ea('.TYPE', ea_seg, ea_ofs, ea_ptr1, ea_ptr2, ea_len, ea_entrylen, ea_valuelen)
  191.    if not found | ea_valuelen=0 then
  192.       answer = winmessagebox(TYPE_TITLE__MSG, NO_FILE_TYPE__MSG, 16388) -- YESNO + MOVEABLE
  193.    elseif peek(ea_seg, ea_ptr2, 2)=EAT_ASCII then
  194. ;     type = peek(ea_seg, ea_ptr2+4, min(itoa(peek(ea_seg, ea_ptr2+2, 2), 10), MAXCOL))
  195.       type = peek(ea_seg, ea_ptr2+4, min(ltoa(peek(ea_seg, ea_ptr2+2, 2)\0\0, 10), MAXCOL))
  196.       answer = winmessagebox(TYPE_TITLE__MSG, ONE_FILE_TYPE__MSG\13 type\13\13CHANGE_QUERY__MSG, 16388) -- YESNO + MOVEABLE
  197.    elseif peek(ea_seg, ea_ptr2, 2)=EAT_MVMT then
  198. ;     ea_numentries = itoa(peek(ea_seg, ea_ptr2+4, 2),10)
  199.       ea_numentries = ltoa(peek(ea_seg, ea_ptr2+4, 2)\0\0,10)
  200.       if ea_numentries=1 then
  201.          type = ONE_FILE_TYPE__MSG
  202.       else
  203.          type = MANY_FILE_TYPES__MSG
  204.       endif
  205.       ea_entry_ofs = ea_ptr2+6
  206.       do i=1 to ea_numentries
  207. ;        ea_entrylen = itoa(peek(ea_seg, ea_entry_ofs+2, 2),10)
  208.          ea_entrylen = ltoa(peek(ea_seg, ea_entry_ofs+2, 2)\0\0,10)
  209.          if peek(ea_seg, ea_entry_ofs, 2)=EAT_ASCII then
  210.             type = type\13 || peek(ea_seg, ea_entry_ofs+4,min(ea_entrylen,MAXCOL))
  211.          else
  212.             type = type\13 || NON_ASCII__MSG
  213.          endif
  214.          ea_entry_ofs = ea_entry_ofs + ea_entrylen + 4
  215.       enddo
  216.       answer = winmessagebox(TYPE_TITLE__MSG, type\13\13CHANGE_QUERY__MSG, 16388) -- YESNO + MOVEABLE
  217.    else
  218.       answer = winmessagebox(TYPE_TITLE__MSG, NON_ASCII_TYPE__MSG\13CHANGE_QUERY__MSG, 16388) -- YESNO + MOVEABLE
  219.    endif
  220.    if answer=6 then
  221. compile if EVERSION < 5.21
  222.       newtype = listbox(SELECT_TYPE__MSG, TYPE_LIST__MSG)
  223.       if newtype then
  224. compile else
  225.       parse value listbox(TYPE_TITLE__MSG, TYPE_LIST__MSG, '/'SET__MSG'/'CANCEL__MSG'/'HELP__MSG, 0, 0, 0, 0,
  226.  compile if EVERSION >= 5.60
  227.                           gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(6040) ||
  228.  compile else
  229.                           atoi(1) || atoi(1) || atoi(6040) || gethwndc(APP_HANDLE) ||
  230.  compile endif
  231.                           SELECT_TYPE__MSG) with button 2 newtype \0
  232.       if newtype & (button=\1) then
  233. compile endif  -- EVERSION < 5.21
  234.          if found then call delete_ea('.TYPE'); endif
  235.          'add_ea .TYPE' newtype
  236.       endif
  237.    endif
  238.  
  239.  
  240. ; Dependencies:  find_ea(), delete_ea(), add_ea
  241. defc subject =
  242. compile if EPATH = 'LAMPATH'
  243.    universal inboxpath
  244.    parse value .userstring with '(' spid ')'
  245.    if spid='' then
  246. compile endif -- EPATH = 'LAMPATH'
  247.       subj = ''
  248. compile if EPATH = 'LAMPATH'
  249.    else
  250.       subj = find_subj()
  251.    endif
  252. compile endif -- EPATH = 'LAMPATH'
  253.    found = find_ea('.SUBJECT', ea_seg, ea_ofs, ea_ptr1, ea_ptr2, ea_len, ea_entrylen, ea_valuelen)
  254.    if arg(1)='' then
  255.       max_len = MAXCOL - length(SUBJECT_IS__MSG) - length(CHANGE_QUERY__MSG) - 5
  256.       if not found | ea_valuelen=0 then
  257. compile if EPATH = 'LAMPATH'
  258.          if subj='' | upcase(subj)='NO SUBJECT' then
  259. compile endif -- EPATH = 'LAMPATH'
  260.             answer = winmessagebox(SUBJ_TITLE__MSG, NO_SUBJECT__MSG, 16388) -- YESNO + MOVEABLE
  261. compile if EPATH = 'LAMPATH'
  262.          else
  263.             newsubj = subj
  264.             if length(subj)>max_len then
  265.                newsubj = leftstr(subj, max_len-3)'...'
  266.             endif
  267.             answer = winmessagebox(SUBJ_TITLE__MSG, SUBJECT_IS__MSG\13 newsubj\13\13||CHANGE_QUERY__MSG, 16388) -- YESNO + MOVEABLE
  268.          endif
  269. compile endif -- EPATH = 'LAMPATH'
  270.       elseif peek(ea_seg, ea_ptr2, 2)=EAT_ASCII then
  271.          subj = peek(ea_seg, ea_ptr2+4, min(ltoa(peek(ea_seg, ea_ptr2+2, 2)\0\0, 10), MAXCOL))
  272.          newsubj = subj
  273.          if length(subj)>max_len then
  274.             newsubj = leftstr(subj, max_len-3)'...'
  275.          endif
  276.          answer = winmessagebox(SUBJ_TITLE__MSG, SUBJECT_IS__MSG\13 newsubj\13\13||CHANGE_QUERY__MSG, 16388) -- YESNO + MOVEABLE
  277.       else
  278.          answer = winmessagebox(SUBJ_TITLE__MSG, NON_ASCII_SUBJECT__MSG\13||CHANGE_QUERY__MSG, 16388) -- YESNO + MOVEABLE
  279.       endif
  280.    else  -- arg(1) not null
  281.       answer = 6
  282.    endif
  283.    if answer=6 then
  284. compile if EVERSION < 5.21  -- The old way
  285.       if arg(1)='' then
  286.          newsubj = entrybox(SELECT_SUBJECT__MSG, '', subj, 40, 230)
  287.       else
  288.          newsubj = arg(1)
  289.       endif
  290.       if newsubj then
  291. compile else
  292.       if arg(1)='' then
  293.          parse value entrybox(SUBJ_TITLE__MSG, '/'SET__MSG'/'CANCEL__MSG'/'HELP__MSG, subj, 40,
  294.  compile if EVERSION >= 5.60 -- long strings
  295.                 260,
  296.  compile else
  297.                 230,  -- 255 limit on strings; must leave room for 'add_ea...'
  298.  compile endif
  299.                 atoi(1) || atoi(6050) || gethwndc(APP_HANDLE) || SELECT_SUBJECT__MSG) with button 2 newsubj \0
  300.       else
  301.          newsubj = arg(1)
  302.          button = \1
  303.       endif
  304.       if newsubj & (button=\1) then
  305. compile endif
  306.          if found then call delete_ea('.SUBJECT'); endif
  307.          'add_ea .SUBJECT' newsubj
  308. compile if EPATH = 'LAMPATH'
  309.          if spid<>'' then
  310.             if not .modify then 'save /q'; endif  -- If file not modified, save new EA, otherwise, let user save it.
  311.             i = lastpos('\',spid)
  312.             if not i then                -- Unexpected error
  313.                sayerror 'Bad spoolid.'
  314.                return
  315.             endif
  316.             getfileid startid
  317.             path = upcase(leftstr(spid,i-1))
  318.             if path=inboxpath then
  319.                indxname = path'\inbox.ndx'
  320.             else
  321.                indxname = path'.ndx'
  322.             endif
  323.             display -2
  324.             success = lock_index(indxname)
  325.             display 2
  326.             if not success then
  327.                sayerror 'Failed to lock index file.'
  328.                return
  329.             endif
  330.             if rc=sayerror('New file') or rc=sayerror('Lines truncated') or (not rc & not .last) then
  331.                call free_index()
  332.                return
  333.             endif
  334.             getfileid fid
  335.             if rc then
  336.                if startid<>fid then call free_index(); endif
  337.                return
  338.             endif
  339.             getsearch oldsearch
  340.             call psave_mark(savemark)
  341.             0
  342.             call pset_mark(1, .last, 28, 44, 'BLOCK', fid)
  343.             parse value substr(spid,i+1) with filename '.' filetype
  344.             display -2
  345.             'xcom l /'leftstr(filename,8) leftstr(filetype,8)'/cm'
  346.             lrc = rc
  347.             display 2
  348.             call prestore_mark(savemark)
  349.             setsearch oldsearch
  350.             retval = ''
  351.             if not lrc then
  352.                getline line
  353.                subjstart = pos('', line, 84)
  354.                subjend = pos('', line, subjstart+1)
  355.                if subjstart & subjend then
  356.  compile if EVERSION >= 5.60
  357.                   line = insertstr(newsubj, delstr(line, subjstart+1, subjend-subjstart-1), subjstart)
  358.  compile else  -- Must limit index line to 255 characters.
  359.                   line = insertstr(newsubj, delstr(line, subjstart+1, subjend-subjstart-1), subjstart, min(length(newsubj), 255-length(line)+(subjend-subjstart-1)))
  360.  compile endif
  361.                   replaceline line, .line
  362.                   call fn2spoolid(startid.filename, spoolid)
  363.                   call LAM_SPOOL_CMD(5505, spoolid, line)   -- x1581; LAM VIEWED
  364.                   sayerror 'Subject updated in index file.'
  365.                endif
  366.             endif
  367.             call free_index()
  368.             activatefile startid
  369.          endif  -- spid<>''
  370. compile endif -- EPATH = 'LAMPATH'
  371.       endif  -- newsubj
  372.    endif  -- answer = 'YES'
  373.