home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / epmmac.zip / CLIPBRD.E < prev    next >
Text File  |  1995-05-12  |  40KB  |  927 lines

  1. /*
  2. ╔════════════════════════════════════════════════════════════════════════════╗
  3. ║ What's it called: clipbrd.e                                                ║
  4. ║                                                                            ║
  5. ║ What does it do:  contains procedures and commands that all:               ║
  6. ║                  -Allow one to pass lines of text between edit windows     ║
  7. ║                  -Allow text to be placed in the PM clipboard              ║
  8. ║                                                                            ║
  9. ║                Text Manipulation between Edit Windows                      ║
  10. ║                ======================================                      ║
  11. ║                Copy2SharBuff  -  Copy Marked area to EPM shared buffer     ║
  12. ║                GetSharBuff    -  Get text from EPM shared buffer           ║
  13. ║                ClearSharBuf   -  Flush out Stuff in shared buffer          ║
  14. ║                Copy2DMBuff    -  Copy Marked area to "Delete Mark" buffer  ║
  15. ║                GetDMBuff    -  Get text from "Delete Mark" buffer          ║
  16. ║                                                                            ║
  17. ║                Text Manipulation between an Edit Window and PM clipboard   ║
  18. ║                ========================================================    ║
  19. ║                                                                            ║
  20. ║                copy2clip - copy marked text to the PM clipboard.           ║
  21. ║                                                                            ║
  22. ║                cut - like copy2clip, but deletes the marked text.          ║
  23. ║                                                                            ║
  24. ║                paste - retrieve text from PM clipboard to edit window.     ║
  25. ║                                                                            ║
  26. ║                                                                            ║
  27. ║ Who and When: Ralph Yozzo, Gennaro (Jerry) Cuomo, & Larry Margolis 3-88    ║
  28. ║                                                                    6/89    ║
  29. ╚════════════════════════════════════════════════════════════════════════════╝
  30. */
  31. compile if EVERSION >= 5.60
  32.    #define CR_TERMINATOR_LDFLAG           1  -- Use CR as a terminator
  33.    #define LF_TERMINATOR_LDFLAG           2  -- Use LF as a terminator
  34.    #define CRLF_TERMINATOR_LDFLAG         4  -- Use CR,LF as a terminator
  35.    #define CTRLZ_TERMINATOR_LDFLAG        8  -- Use EOF as a terminator
  36.    #define NULL_TERMINATOR_LDFLAG        16  -- Use NULL as a terminator
  37.    #define TABEXP_LDFLAG                 32  -- Expand tabs when loading
  38.    #define CRLFEOF_TERMINATOR_LDFLAG     64  -- Use CR,LF,EOF as a terminator
  39.    #define CRCRLF_TERMINATOR_LDFLAG     128  -- Use CR,CR,LF as a terminator
  40.    #define NOHEADER_LDFLAG              256  -- Buffer has no header
  41.    #define NEW_BITS_LDFLAG              512  -- Format flag is using these bits
  42.    #define STRIP_SPACES_LDFLAG         1024  -- Strip trailing spaces when loading
  43.    #define IGNORE_STORED_FORMAT_LDFLAG 2048  -- Don't use format flags saved in buffer header
  44.    #define FORCE_TERMINATOR_LDFLAG     4096  -- Require a terminator after every line
  45. compile endif
  46. compile if not defined(REFLOW_AFTER_PASTE)
  47.    const REFLOW_AFTER_PASTE = 0
  48. compile endif
  49.  
  50. /*
  51. ┌────────────────────────────────────────────────────────────────────────────┐
  52. │ Copy2SharBuff -                                                            │
  53. │                 Copy Marked area to EPM shared buffer                      │
  54. │                                                                            │
  55. │                                                                            │
  56. └────────────────────────────────────────────────────────────────────────────┘
  57. */
  58. defc Copy2SharBuff                     /* former name = CLIPBRD_pt          */
  59.    if not marktype() then              /* check if mark exists              */
  60.       return                           /* if mark doesn't exist, return     */
  61.    endif
  62.                                        /* save the dimensions of the mark   */
  63. compile if EVERSION >= 5.50
  64.    getmarkg fstline,                   /* returned:  first line of mark     */
  65. compile else
  66.    getmark fstline,                    /* returned:  first line of mark     */
  67. compile endif
  68.            lstline,                    /* returned:  last  line of mark     */
  69.            fstcol,                     /* returned:  first column of mark   */
  70.            lstcol,                     /* returned:  last  column of mark   */
  71.            mkfileid                    /* returned:  file id of marked file */
  72.  
  73.    getfileid fileid                    /* save file id of visible file      */
  74.    activatefile mkfileid               /* switch to file with mark          */
  75.    /* Try to open the buffer.  If it doesn't exist, create it.              */
  76.    bufhndl = buffer(OPENBUF, EPMSHAREDBUFFER)
  77.    if bufhndl then
  78.       opened = 1
  79.    else
  80.       -- Make a 64K buffer... memory's plentiful.  Easily changed.
  81.       bufsize = MAXBUFSIZE
  82.       bufhndl = buffer(CREATEBUF, EPMSHAREDBUFFER, bufsize)
  83.       opened = 0
  84.    endif
  85.    if not bufhndl then
  86.       sayerror CAN_NOT_OPEN__MSG EPMSHAREDBUFFER '-' ERROR_NUMBER__MSG RC
  87.       stop
  88.    endif
  89.  
  90.    /* Copy the current marked lines (up to 64k worth of data ) into EPM's */
  91.    /* shared memory buffer.                                               */
  92. compile if EVERSION >= 5.51
  93.    call buffer(PUTMARKBUF, bufhndl, fstline, lstline, APPENDCR+APPENDLF)  -- Was +FINALNULL+STRIPSPACES
  94. compile else  -- Older versions needed the null for the copy to clipboard routine
  95.    call buffer(PUTMARKBUF, bufhndl, fstline, lstline, APPENDCR+APPENDLF+FINALNULL)
  96. compile endif
  97.  
  98. compile if EVERSION >= 5.50
  99.    poke bufhndl, 28, atol(lstline-fstline+1-(lstline>.last))  -- Remember how many lines are *supposed* to be there.
  100. compile else
  101.    poke bufhndl, 28, atol(lstline-fstline+1)  -- Remember how many lines are *supposed* to be there.
  102. compile endif
  103.  
  104.    activatefile fileid
  105.    if opened then
  106.       call buffer(FREEBUF, bufhndl)
  107.    endif
  108.  
  109. /*
  110. ┌────────────────────────────────────────────────────────────────────────────┐
  111. │ GetSharBuff -                                                              │
  112. │                 Get text from EPM shared buffer.                           │
  113. │                 'O' means Overlay instead of copy.                         │
  114. │                                                                            │
  115. └────────────────────────────────────────────────────────────────────────────┘
  116. */
  117. defc GetSharBuff            /* former name = CLIPBRD_gt                 */
  118.    /* EPMSHAREDBUFFER= buffer name known between edit windows           */
  119.    -- Try to open the buffer.  If it doesn't exist, nothing to get.
  120.    bufhndl = buffer(OPENBUF, EPMSHAREDBUFFER)
  121.    if not bufhndl then
  122.       sayerror CAN_NOT_OPEN__MSG EPMSHAREDBUFFER '-' ERROR_NUMBER__MSG RC
  123.       stop
  124.    endif
  125.    call psave_pos(save_pos)
  126.    call GetBuffCommon(bufhndl, NO_MARK_NO_BUFF__MSG, arg(1))
  127.    call buffer(FREEBUF, bufhndl)
  128.    call prestore_pos(save_pos)
  129.  
  130. /*
  131. ┌────────────────────────────────────────────────────────────────────────────┐
  132. │ ClearSharBuff -                                                            │
  133. │                 Flush out stuff in  EPM shared buffer                      │
  134. │                                                                            │
  135. └────────────────────────────────────────────────────────────────────────────┘
  136. */
  137. defc ClearSharBuff
  138.    bufhndl=buffer(OPENBUF, EPMSHAREDBUFFER)
  139.    if bufhndl then
  140.       call buffer(CLEARBUF, bufhndl)
  141.       call buffer(FREEBUF, bufhndl)
  142.    endif
  143.  
  144. /*
  145. ┌────────────────────────────────────────────────────────────────────────────┐
  146. │ copy2clip                                                                  │
  147. │       copy marked text into the PM clipboard.                              │
  148. │                                                                            │
  149. │                                                                            │
  150. └────────────────────────────────────────────────────────────────────────────┘
  151. */
  152. defc copy2clip
  153.    call checkmark()                          /* Make sure there's a mark. */
  154.  
  155.    'Copy2SharBuff'   -- Recopy the marked area to the shared buffer,
  156.                      -- in case the user has modified the mark contents.
  157.  
  158.    /* Try to open the buffer.  If it doesn't exist, then we can't copy   */
  159.    bufhndl = buffer(OPENBUF, EPMSHAREDBUFFER)
  160.    if not bufhndl then
  161.       return 1                              /* buffer does not exist     */
  162.    endif
  163.    if peek(bufhndl,6,2) /== peek(bufhndl,28,2) then
  164.       sayerror TOO_MUCH_FOR_CLIPBD__MSG
  165.       return 1
  166.    endif
  167.  
  168. compile if EVERSION < '5.50'
  169.    hab=gethwnd(0)                           /* get EPM's anchorblock     */
  170.    call dynalink('PMWIN',                   /* Open PM's clipboard       */
  171.                  'WINOPENCLIPBRD',
  172.                  hab)
  173.  
  174.    call dynalink('PMWIN',                   -- Empty the clipboard completely
  175.                  'WINEMPTYCLIPBRD',         -- before filling it.
  176.                  hab)
  177.    result = dynalink(E_DLL,                 /* create a buffer and copy  */
  178.             'CLIPBOARDCOPY',                /* the contents of the EPM   */
  179.             atoi(bufhndl)||                 /* shared buffer             */
  180.             atoi(0)      ||
  181.             atoi(1),                        /* buffer to pm clipboard    */
  182.             2)                              /* return long               */
  183.  
  184.    /* Clipboardcopy allocates a buffer of memory                         */
  185.    /* we don't have to worry about freeing the buffer that clipboardcopy */
  186.    /* allocates... PM will free it                                       */
  187.  
  188.    call dynalink('PMWIN',                   /* call PM function to       */
  189.                  'WINSETCLIPBRDDATA',       /* move data into the PM e cb*/
  190.                   hab ||                    /* anchor block              */
  191.                   atol(result) ||           /* pointer to text.          */
  192.                   atoi(1) ||                /* format (TEXT)             */
  193.                   atoi(256))                /* selector                  */
  194.  
  195.    call dynalink('PMWIN',
  196.                  'WINCLOSECLIPBRD',
  197.                  hab)
  198.    call buffer(FREEBUF, bufhndl)
  199.  
  200. compile else
  201. --  Copying to the Clipboard using the EToolkit message:
  202. --  EPM_EDIT_CLIPBOARDCOPY -  mp1 = pointer to memory buffer containing
  203. --                                  contents to copy to the clipboard.
  204. --                            mp2 = flag that describes what type of buffer
  205. --                                  was passed in mp1.
  206. --                                  0=CF_TEXT type buffer, terminated by nul
  207. --                                  1=EPM shared memory buffer (32byte head)
  208. --  When the contents of mp1 is copied to the clipboard a EPM defc event is
  209. --  called by the name of PROCESSCLIPBOARDCOPY.  Arg(1) of this function is
  210. --  the original buffer passed in as mp1.  The caller may choose to free
  211. --  the buffer during this command.    if zero is passed as arg(1), an error
  212. --  was encountered.  An error message should be displayed at this point.
  213.  
  214.    call windowmessage(0,  getpminfo(EPMINFO_EDITCLIENT),
  215.                       5441,               -- EPM_EDIT_CLIPBOARDCOPY
  216. ; compile if POWERPC
  217. ;                      bufhndl,
  218. ; compile else
  219.                       mpfrom2short( bufhndl, 0),
  220. ; compile endif
  221.                       1)
  222.  
  223. defc processclipboardcopy
  224.    result=arg(1)
  225.    if result then      -- If non-zero, free the buffer.
  226. ; compile if POWERPC
  227. ;      call buffer(FREEBUF, result)  -- pass the pointer
  228. ; compile else
  229.       call buffer(FREEBUF, itoa(substr(atol(result),3,2),10))  -- pass just the selector
  230. ; compile endif
  231.    endif
  232.  
  233. compile endif -- EVERSION < '5.50'
  234.  
  235. /*
  236. ┌────────────────────────────────────────────────────────────────────────────┐
  237. │ cut                                                                        │
  238. │       copy marked text into the PM clipboard, then delete the mark.        │
  239. │                                                                            │
  240. │                                                                            │
  241. └────────────────────────────────────────────────────────────────────────────┘
  242. */
  243. defc cut
  244.    'copy2clip'
  245.    if not RC then
  246.       getmark firstline,lastline,firstcol,lastcol,markfileid
  247.       markfileid.line = firstline
  248.       if leftstr(marktype(), 1)<>'L' then
  249.          markfileid.col = firstcol
  250.       endif
  251.       call pdelete_mark()
  252.    endif
  253.  
  254. /*
  255. ┌─────────────────────────────────────────────────────────────────────────┐
  256. │ paste                                                                   │
  257. │                                                                         │
  258. │    retrieve text from PM clipboard to edit window                       │
  259. │                                                                         │
  260. └─────────────────────────────────────────────────────────────────────────┘
  261. */
  262. defc paste
  263. compile if WANT_CUA_MARKING = 'SWITCH'
  264.    universal CUA_marking_switch
  265. compile endif
  266.    arg1 = upcase(arg(1))
  267. compile if EVERSION >= '6.03'
  268.    if .readonly then
  269.       sayerror READ_ONLY__MSG
  270.       return
  271.    endif
  272. compile endif
  273.    if browse() then
  274.       sayerror BROWSE_IS__MSG ON__MSG
  275.       return
  276.    endif
  277.    if not .line & (arg1='C' | arg1='B') then
  278.       if .last then  -- Can't paste into line 0
  279.          sayerror -281  -- "Source destination conflict"
  280.          return
  281.       endif
  282.       insert         -- If file is empty, insert a blank line & paste there.
  283.       begin_line
  284.    endif
  285. compile if EVERSION < '5.50'
  286.    if not clipcheck(format) then
  287.       sayerror CLIPBOARD_ERROR__MSG
  288.       return
  289.    endif
  290.    if format<>256 then                 -- no text in clipboard
  291.       sayerror CLIPBOARD_EMPTY__MSG
  292.       return
  293.    endif
  294.  
  295.  compile if EPM32  -- The following is unnecessary; we're inside EVERSION < 5.50 ...
  296.    hab=gethwndc(0)                          -- get EPM's anchorblock
  297.    call dynalink32('PMWIN',                   /* Open PM's clipboard       */
  298.                    '#793',  -- WINOPENCLIPBRD
  299.                     hab)
  300.  
  301.    result = dynalink32('PMWIN',               /* call PM function to       */
  302.                        '#806',  -- WINQUERYCLIPBRDDATA  /* look at the data in the cb*/
  303.                        hab ||                 /* anchor block              */
  304.                        atol(1),               /* data format ( TEXT )      */
  305.                        4)                     /* return a 4 byte result    */
  306.  
  307.    result = dynalink32(E_DLL,                 /* create a buffer and copy  */
  308.                        'ClipboardCopy',       /*                           */
  309.                        atol(result) ||        /*                           */
  310.                        atol(0),               /* pm clipboard to shared buf*/
  311.                        4)                     /*                           */
  312.    call dynalink32('PMWIN',
  313.                    '#707',  -- WINCLOSECLIPBRD
  314.                    hab)
  315.  compile else
  316.    hab=gethwnd(0)                          -- get EPM's anchorblock
  317.    call dynalink('PMWIN',                   /* Open PM's clipboard       */
  318.                  'WINOPENCLIPBRD',
  319.                  hab)
  320.  
  321.    result = dynalink('PMWIN',               /* call PM function to       */
  322.                      'WINQUERYCLIPBRDDATA', /* look at the data in the cb*/
  323.                      hab ||                 /* anchor block              */
  324.                      atoi(1),               /* data format ( TEXT )      */
  325.                      2)                     /* return a 4 byte result    */
  326.  
  327.    result = dynalink(E_DLL,                 /* create a buffer and copy  */
  328.                      'CLIPBOARDCOPY',       /*                           */
  329.                      atol(result) ||        /*                           */
  330.                      atoi(0),               /* pm clipboard to shared buf*/
  331.                      2)                     /*                           */
  332.    call dynalink('PMWIN',
  333.                  'WINCLOSECLIPBRD',
  334.                  hab)
  335.  compile endif  -- EPM32
  336.  
  337.    result=itoa(substr(atol(result),3,2),10) /* convert from bin to str   */
  338.    if arg1='C' | arg1='B' then
  339.       poke result, 8, chr(68-asc(arg1))              -- 'C'->1; 'B'->2; mark as a character or block buffer
  340.  compile if WANT_CUA_MARKING
  341.       if arg1='C' &
  342.   compile if WANT_CUA_MARKING = 'SWITCH'
  343.          CUA_marking_switch &
  344.   compile endif
  345.          marktype()
  346.       then
  347.          call pbegin_mark()
  348.          call pdelete_mark()
  349.          'ClearSharBuff'       /* Remove Content in EPM shared text buffer */
  350.       endif
  351.  compile endif
  352.  compile if REFLOW_AFTER_PASTE
  353.    start_line = .line
  354.    start_linetext = textline(.line)
  355.    start_col = .col+1
  356.  compile endif
  357.       call psave_mark(savemark)                        -- Save the user's mark
  358.       call GetBuffCommon(result, NOTHING_TO_PASTE__MSG, arg1)
  359.       -- clause continued below for common stuff.
  360. compile else  -- if EVERSION < 5.50
  361. --  Pasting from the PM Clipboard using the EToolkit message:
  362. --  EPM_EDIT_CLIPBOARDPASTE-  mp1 = flag that describes the type of paste
  363. --                                  that is desired.  A paste could be of
  364. --                            the following types; 'C' for Character, 'B' for
  365. --                            block and 'L' for line.
  366. --  During the processing of this message the text in the PM clipboard is
  367. --  queried.  Once this is done an EPM defc event is
  368. --  called by the name of PROCESSCLIPBOARDPASTE.  Arg(1) of this function
  369. --  contains a pointer to a buffer containing a copy of the text found in
  370. --  the PM clipboard.   Arg(2) of this function is
  371. --  the original flag passed in as mp1.  The caller may choose to free
  372. --  the buffer during this command.    if zero is passed as arg(1), an error
  373. --  was encountered.  An error message should be displayed at this point.
  374.    mark=upcase(arg(1))
  375.    if mark<>'C' and  mark<>'B' then
  376.       mark='L'
  377.    endif
  378.    call windowmessage(0,  getpminfo(EPMINFO_EDITCLIENT),
  379.                       5442,               -- EPM_EDIT_CLIPBOARDPASTE
  380.                       asc(mark), 0)
  381.  
  382. defc processclipboardpaste
  383.  compile if WANT_CUA_MARKING = 'SWITCH'
  384.    universal CUA_marking_switch
  385.  compile endif
  386.  
  387.    parse arg result mark .
  388.    if not result then
  389.       sayerror CLIPBOARD_ERROR__MSG
  390.       return
  391.    endif
  392.  
  393.    if mark=67 | mark=66 then  -- asc('C') | asc('B')
  394.  compile if REFLOW_AFTER_PASTE
  395.    start_line = .line
  396.    start_linetext = textline(.line)
  397.    start_col = .col + 1
  398.  compile endif
  399.       poke result, 8, chr(68-mark)              -- 'C'->1; 'B'->2; mark as a character or block buffer
  400.  compile if WANT_CUA_MARKING
  401.       if mark=67 &
  402.   compile if WANT_CUA_MARKING = 'SWITCH'
  403.          CUA_marking_switch &
  404.   compile endif
  405.          marktype()
  406.       then
  407.          getmark x, x, x, x, mark_fid
  408.          getfileid cur_fid
  409.          if mark_fid=cur_fid then
  410.             call pbegin_mark()
  411.             call pdelete_mark()
  412.          else
  413.             unmark
  414.             sayerror MARKED_OTHER__MSG
  415.          endif
  416.          'ClearSharBuff'       /* Remove content in EPM shared text buffer */
  417.       endif
  418.  compile endif
  419.       call psave_mark(savemark)                        -- Save the user's mark
  420.       call GetBuffCommon(result, NOTHING_TO_PASTE__MSG, chr(mark))
  421. compile endif -- EVERSION < '5.50'
  422.       -- Two cases join here, in the middle of this IF statement.
  423.       call prestore_mark(savemark)                     -- Restore the user's mark
  424.    else
  425.       oldsize = .last
  426.  compile if REFLOW_AFTER_PASTE
  427.       start_line = .line + 1
  428.       start_linetext = textline(.line)
  429.       start_col = 1
  430.  compile endif
  431. compile if EVERSION >= 5.60
  432.       call buffer(GETBUF2, result, 1, 0,
  433.                   CR_TERMINATOR_LDFLAG + LF_TERMINATOR_LDFLAG + CRLF_TERMINATOR_LDFLAG +
  434.                   CRCRLF_TERMINATOR_LDFLAG + NEW_BITS_LDFLAG + FORCE_TERMINATOR_LDFLAG)
  435.       if textline(.line+.last-oldsize)=='' then
  436.          deleteline .line+.last-oldsize
  437.       endif
  438. compile elseif EVERSION >= 5.50
  439.       call buffer(GETBUF2, result)          /* put buffer into text      */
  440. compile else
  441.       call buffer(GETBUF, result)           /* put buffer into text      */
  442. compile endif -- EVERSION >= 5.50
  443.       '+'(.last-oldsize)
  444.    endif
  445. compile if REFLOW_AFTER_PASTE
  446.    parse value .margins with . rm .
  447.    if rm < MAXMARGIN then
  448.  compile if REFLOW_AFTER_PASTE = 'WIDER' | REFLOW_AFTER_PASTE = 'PROMPT_IF_WIDE'
  449.     must_reflow = FALSE
  450.     do i=start_line to .line
  451.       if length(textline(i))>rm then
  452.          must_reflow = TRUE
  453.          leave
  454.       endif
  455.     enddo
  456.     if must_reflow then
  457.   compile if REFLOW_AFTER_PASTE = 'PROMPT_IF_WIDE'
  458.      refresh
  459.    compile if defined(ULTIMAIL_DLG_TITLE)
  460.      if MBID_YES=winmessagebox(ULTIMAIL_DLG_TITLE,
  461.    compile else
  462.      if MBID_YES=winmessagebox('',
  463.    compile endif
  464.                                WIDE_PASTE__MSG,
  465.                                MB_YESNO + MB_QUERY + MB_DEFBUTTON2 + MB_MOVEABLE)
  466.      then
  467.   compile endif
  468.  compile endif
  469.       call psave_mark(savemark)        -- Save the user's mark
  470. ;     call psave_pos(savepos)          -- We should now be at the end of the insertion.
  471.       to_end = .last - .line           -- Remember how far from end, because # lines
  472.                                        -- from start will change as we reflow.
  473.       insert_attribute 13, 0, 2, 0, start_col, start_line  -- Place a bookmark on the char. after the pasted text
  474.       cur_line = start_line
  475.       stopit = 0
  476.       do forever
  477.          unmark
  478.          cur_line                      -- Go to first pasted line
  479.          do while textline(.line)=''   -- Skip blank lines
  480.             if .line=.last then stopit=1; leave; endif
  481.             down
  482.          enddo
  483.          if stopit then leave; endif   -- If no non-blank, nothing to do.
  484.          mark_line
  485.          cur_line = .line
  486.          call pfind_blank_line()
  487.          if .line<>cur_line then       -- Stop at line before next blank line
  488.             up
  489.          else                          -- No blank lines?  Go to bottom.
  490.             bottom
  491.          endif
  492.          if start_linetext='' then  -- Pasted onto a blank line?
  493.             if .last-.line < to_end then
  494.                if .last - to_end < cur_line then
  495.                   leave
  496.                endif
  497.                .line = .last - to_end
  498.             endif
  499.          endif
  500.          mark_line
  501.          reflow
  502.          getmark firstmarkline, lastmarkline
  503.          if lastmarkline = .last | .last - lastmarkline <= to_end then
  504.             leave
  505.          else
  506.             cur_line = lastmarkline + 1
  507.          endif
  508.       enddo
  509.       class = 13  -- BOOKMARK_CLASS
  510.       col=start_col; line=start_line; offst=0
  511.       attribute_action 1, class, offst, col, line  -- 1=FIND NEXT ATTR
  512.       if class=13 then
  513.          query_attribute class, val, IsPush, offst, col, line
  514.          line; .col=col
  515.          attribute_action 16, class, offst, col, line -- 16=Delete attribute
  516.       endif
  517.       call prestore_mark(savemark)                     -- Restore the user's mark
  518.  compile if REFLOW_AFTER_PASTE = 'WIDER' | REFLOW_AFTER_PASTE = 'PROMPT_IF_WIDE'
  519.   compile if REFLOW_AFTER_PASTE = 'PROMPT_IF_WIDE'
  520.      endif -- MBID_YES
  521.   compile endif
  522.     endif  -- must_reflow
  523.  compile endif
  524.    endif  -- rm < MAXMARGIN
  525. compile endif  -- REFLOW_AFTER_PASTE
  526.  
  527. compile if POWERPC  -- Pseudo-tiled memory; have to free with myfree()
  528.    call dynalink32(E_DLL,         -- dynamic link library name
  529.                    'myfree',                   -- DosFreeSeg
  530.                    atoi(0) ||  -- add an offset to make the selector an address
  531.                    atoi(result))
  532. compile elseif EPM32
  533.    call dynalink32('DOSCALLS',        /* dynamic link library name         */
  534.                    '#304',             /* DosFreeSeg                        */
  535.                    ltoa(atoi(0) || atoi(result), 10))
  536. compile else
  537.    call dynalink('DOSCALLS',        /* dynamic link library name         */
  538.                  '#39',             /* DosFreeSeg                        */
  539.                  atoi(result))
  540. compile endif
  541.  
  542. compile if WANT_DM_BUFFER
  543. definit
  544.    universal DMbuf_handle
  545.    DMbuf_handle = 0
  546.  
  547. defexit
  548.    universal DMbuf_handle
  549.    if DMbuf_handle then
  550.       call buffer(FREEBUF, DMbuf_handle)              -- Free the OPEN
  551.    endif
  552.  
  553. /*
  554. ┌────────────────────────────────────────────────────────────────────────────┐
  555. │ Copy2DMBuff -                                                              │
  556. │                 Copy Marked area to "Delete Mark" buffer                   │
  557. │                                                                            │
  558. │                                                                            │
  559. └────────────────────────────────────────────────────────────────────────────┘
  560. */
  561. defc Copy2DMBuff
  562.    universal DMbuf_handle
  563.    themarktype = marktype()
  564.    if not themarktype then             /* check if mark exists              */
  565.       return                           /* if mark doesn't exist, return     */
  566.    endif
  567.                                        /* save the dimensions of the mark   */
  568.    getmark fstline,                    /* returned:  first line of mark     */
  569.            lstline,                    /* returned:  last  line of mark     */
  570.            fstcol,                     /* returned:  first column of mark   */
  571.            lstcol,                     /* returned:  last  column of mark   */
  572.            mkfileid                    /* returned:  file id of marked file */
  573.  
  574.    if themarktype='BLOCK' then  -- Size of block, + 2 per line for CR, LF
  575.       size=(lstcol-fstcol+3) * (lstline-fstline+1) + 3
  576.    else                       -- Probably much larger than we need, but must assume:
  577.       size=(MAXCOL+2) * (lstline-fstline+1) +3  -- 255 chars/line + CR, LF
  578.    endif
  579.    /* Try to open the buffer.  If it doesn't exist or is too small, create it. */
  580.    if not DMbuf_handle then
  581.       DMbuf_handle = buffer(OPENBUF, EPMDMBUFFER)
  582.       if DMbuf_handle then
  583.          call buffer(FREEBUF, DMbuf_handle)              -- Free the OPEN
  584.       endif
  585.    endif
  586.    if DMbuf_handle then
  587.       maxsize  = buffer(MAXSIZEBUF,DMbuf_handle)
  588.       if size > maxsize & maxsize < MAXBUFSIZE then
  589.          success=buffer(FREEBUF, DMbuf_handle)        -- Free the original CREATE
  590.          if not success then
  591.             sayerror ERROR__MSG rc TRYING_TO_FREE__MSG EPMDMBUFFER BUFFER__MSG
  592.          endif
  593.          DMbuf_handle = ''
  594.       endif
  595.    endif
  596.    if not DMbuf_handle then
  597.       DMbuf_handle = buffer(CREATEBUF, EPMDMBUFFER, min(size,MAXBUFSIZE), 1)
  598.    endif
  599.    if not DMbuf_handle then
  600.       messageNwait(CAN_NOT_OPEN__MSG EPMDMBUFFER '-' ERROR_NUMBER__MSG RC)
  601.       return
  602.    endif
  603.  
  604.    getfileid fileid                    /* save file id of visible file      */
  605.    activatefile mkfileid               /* switch to file with mark          */
  606.    /* Copy the current marked lines (up to 64k worth of data ) into EPM's */
  607.    /* shared memory buffer.                                               */
  608.    call buffer(PUTMARKBUF, DMbuf_handle, fstline, lstline, APPENDCR+APPENDLF)
  609.  
  610.    poke DMbuf_handle, 28, atol(lstline-fstline+1)  -- Remember how many lines are *supposed* to be there.
  611.  
  612.    activatefile fileid
  613.  
  614.  
  615. /*
  616. ┌────────────────────────────────────────────────────────────────────────────┐
  617. │ GetDMBuff -                                                                │
  618. │                 Get text from "Delete Mark" buffer.                        │
  619. │                                                                            │
  620. │                                                                            │
  621. └────────────────────────────────────────────────────────────────────────────┘
  622. */
  623. defc GetDMBuff
  624.    universal DMbuf_handle
  625.    -- Try to open the buffer.  If it doesn't exist, nothing to get.
  626. ;; DMbuf_handle = buffer(OPENBUF, EPMDMBUFFER)
  627. ;; -- (If it doesn't exist in this window, the lines were deleted from some other window.)
  628.    if not DMbuf_handle then
  629. ;;    sayerror 'Unable to open a buffer named' EPMDMBUFFER'.  Error number 'RC
  630.       sayerror NO_MARK_DELETED__MSG
  631.       return
  632.    endif
  633.    call psave_mark(savemark)                              -- Save the user's mark
  634.    call GetBuffCommon(DMbuf_handle, NO_TEXT_RECOVERED__MSG)  -- (This marks what's recovered)
  635.    call prestore_mark(savemark)                           -- Restore the user's mark
  636. compile endif  -- WANT_DM_BUFFER
  637.  
  638.  
  639. /*
  640. ┌────────────────────────────────────────────────────────────────────────────┐
  641. │ GetBuffCommon                                                              │
  642. │                 Common code called by GetSharBuff, Paste and GetDMBuff     │
  643. │                                                                            │
  644. └────────────────────────────────────────────────────────────────────────────┘
  645. */
  646. defproc GetBuffCommon(bufhndl, errormsg)
  647. compile if WANT_CUA_MARKING = 'SWITCH'
  648.    universal CUA_marking_switch
  649. compile endif
  650.    markt = buffer(MARKTYPEBUF, bufhndl)
  651.    getfileid activefid                  -- get current files file id
  652.    if not markt & arg(3)<>'O' then      -- MARKT=0 ==> line mark (simple case)
  653.       noflines = buffer(GETBUF, bufhndl)   -- Retrieve data from shared EPM buf
  654.       if noflines then
  655.          call pset_mark(.line+1,.line+noflines,1,MAXCOL,'LINE',activefid)
  656.          '+'noflines
  657.          call verify_buffer_size(bufhndl, noflines)
  658.       else
  659.          sayerror errormsg
  660.       endif
  661.       return                            -- ... and that's all.
  662.    endif
  663.  
  664.    cur_line_len = length(textline(.line))
  665.    'xcom e /q /c epmbuff.cpy'           -- edit a temp hidden file
  666.    .visible=0                           -- (hide file)
  667.    getfileid tmpfileid                  -- get hidden file's id
  668.  
  669. compile if EVERSION >= 5.60
  670.    noflines = buffer(GETBUF2, bufhndl, 1, 0,
  671.                      CR_TERMINATOR_LDFLAG + LF_TERMINATOR_LDFLAG + CRLF_TERMINATOR_LDFLAG +
  672.                      CRCRLF_TERMINATOR_LDFLAG + NEW_BITS_LDFLAG + FORCE_TERMINATOR_LDFLAG)
  673. compile elseif EVERSION >= 5.50
  674.    noflines = buffer(GETBUF2, bufhndl)  -- retrieve data from shared EPM buf
  675. compile else
  676.    noflines = buffer(GETBUF, bufhndl)   -- retrieve data from shared EPM buf
  677. compile endif -- EVERSION >= 5.50
  678.    if not noflines then
  679.       'xcom quit'
  680.       sayerror errormsg
  681.       return
  682.    endif
  683. compile if EVERSION < 5.50
  684.    insert_attribute 13, 0, 2, 0, activefid.col, activefid.line, activefid  -- Place a bookmark on the character
  685. compile endif
  686.  
  687. compile if EVERSION >= 5.50
  688.    orig_lines = ltoa(peek(bufhndl,28,4),10)
  689.  compile if EVERSION = 5.50
  690.    if orig_lines & orig_lines = noflines-1 & markt = 2 & textline(.last)==\0 then  -- Block mark?  Get rid of extra blank line
  691.  compile else
  692. ;  sayerror 'orig_lines='orig_lines 'noflines='noflines 'markt='markt '.last='.last 'textline(.last)="'textline(.last)'"'
  693.    if (not orig_lines | orig_lines = noflines-1) & markt = 2 & textline(.last)=='' then  -- Block mark?  Get rid of extra blank line
  694.  compile endif
  695.       noflines = noflines-1
  696.       deleteline .last
  697.    endif
  698. compile endif
  699.    length_last = length(textline(.last))
  700.    split_start = 0; split_end = 0
  701.    '+1'                              -- advance to next line in hidden
  702.    if markt=2 | markt=4 then            -- Mark type is BLOCK(G)
  703.       markblock                         -- block mark first character
  704.       noflines+1                        -- advance down to last line
  705.       if arg(3)='B' then                -- Block-marking from clipboard;
  706.          .col=longestline()             -- move cursor to end of longest line
  707.       else                              -- Was originally a block; width is OK.
  708.          .col=length_last               -- move to last character
  709.       endif
  710.       markblock                         -- complete block mark
  711.    elseif markt=1 | markt=3 then        -- Mark type is Character(G)
  712.       split_start = activefid.col + length(textline(2)) > MAXCOL
  713.       split_end = cur_line_len - activefid.col + length_last > MAXCOL
  714. compile if EVERSION >= 5.50
  715.       setmark 2, .last, 1, length_last+1, 3, tmpfileid  -- 3 = CHARG mark
  716. compile else
  717.       mark_char                         -- character mark first char
  718.       noflines+1                        -- advance down to last
  719.       .col=length_last                  -- move to last character
  720.       mark_char                         -- complete character mark
  721. compile endif
  722.    else
  723.       mark_line                         -- line mark first line
  724.       noflines+1                        -- advance down to last
  725.       mark_line                         -- complete line mark
  726.    endif
  727.  
  728.    activatefile activefid               -- activate destination file
  729.    rc=0                                 -- clear return code before copy
  730.    if arg(3)='O' then
  731. compile if WANT_CHAR_OPS
  732.       call pcommon_adjust_overlay('O')  -- copy mark
  733. compile else
  734.       overlay_block
  735. compile endif
  736.    else
  737.       if split_end then split; endif
  738.       if split_start then split; '+1'; begin_line; endif
  739.       call pcopy_mark()                 -- copy mark
  740.    endif
  741.    if rc then                           -- Test for memory too full for copy_mark.
  742.       display -4
  743.       sayerror ERROR_COPYING__MSG
  744.       display 4
  745.    endif
  746.  
  747.    activatefile tmpfileid               -- activate temp file
  748.    'xcom q'                             -- quit it
  749.    activatefile activefid               -- activate destination file
  750. compile if EVERSION < 5.50
  751.    class = 13  -- BOOKMARK_CLASS
  752.    col=.col+1; line=.line; offst=0
  753.    attribute_action 1, class, offst, col, line  -- 1=FIND NEXT ATTR
  754.    if class=13 then
  755.       query_attribute class, val, IsPush, offst, col, line
  756.       line; .col=col
  757.       attribute_action 16, class, offst, col, line -- 16=Delete attribute
  758.    endif
  759. compile else  -- 5.50 does char marks internally, so moving to the end of the mark will always work.
  760.    call pend_mark()
  761. ;  sayerror 'length_last='length_last'; .col='.col'; cl1, cl2 =' cl1 cl2
  762.    if length_last then  -- Move right by 'executekey right', to handle stream mode.
  763.  compile if WANT_CUA_MARKING = 'SWITCH'
  764.       save_CUA = CUA_marking_switch
  765.       CUA_marking_switch = 0
  766.  compile endif
  767.  compile if WANT_CUA_MARKING  -- Turn off CUA marking, so moving right won't unmark.
  768.       'togglecontrol 25 0'
  769.  compile endif
  770.       executekey right           -- This is all we really want to do...
  771.  compile if WANT_CUA_MARKING = 'SWITCH'
  772.       CUA_marking_switch = save_CUA
  773.       'togglecontrol 25' CUA_marking_switch
  774.  compile elseif WANT_CUA_MARKING
  775.       'togglecontrol 25 1'
  776.  compile endif
  777.    endif
  778. compile endif
  779.    call verify_buffer_size(bufhndl, noflines)
  780.  
  781. defproc verify_buffer_size(bufhndl, noflines)
  782.    orig_lines = ltoa(peek(bufhndl,28,4),10)
  783.    if orig_lines <> noflines & orig_lines then  -- If 0, assume never set.
  784.       display -4
  785.       sayerror ONLY__MSG noflines LINES_OF__MSG orig_lines RECOVERED__MSG
  786.       display 4
  787.    endif
  788.  
  789. defc clipview =
  790.    if not clipcheck(format) then
  791.       sayerror CLIPBOARD_ERROR__MSG
  792.       return
  793.    endif
  794.    if format<>256 then                 -- no text in clipboard
  795.       sayerror CLIPBOARD_EMPTY__MSG
  796.       return
  797.    endif
  798.    "open 'paste C' 'postme clipview2'"
  799.  
  800. defc clipview2 =
  801.    if .filename=UNNAMED_FILE_NAME then
  802.       .filename=CLIPBOARD_VIEW_NAME
  803.       .autosave = 0
  804.       .modify = 0
  805. compile if EVERSION >= '6.03'
  806.       .readonly = 1
  807. compile else
  808.       call browse(1)
  809. compile endif
  810.    endif
  811.  
  812. defproc clipcheck(var format)  -- Returns error code; if OK, sets FORMAT
  813. compile if EPM32
  814.    hab=gethwndc(0)                         -- get EPM's anchorblock
  815.    format = \0\0\0\0                       -- (reserve four bytes)
  816.    rc=dynalink32('PMWIN',                   -- call PM function to
  817.                  '#807',   -- look at the data in the cb
  818.                  hab              ||         -- anchor block
  819.                  atol(1)          ||         -- data format ( TEXT )
  820.                  address(format), 4)
  821. --   format = ltoa(format,10)                -- Convert format to ASCII
  822.    format = 1024
  823. compile else
  824.    hab=gethwnd(0)                          -- get EPM's anchorblock
  825.    format = \0\0                           -- (reserve two bytes)
  826.    rc=dynalink('PMWIN',                    -- call PM function to
  827.                'WINQUERYCLIPBRDFMTINFO',   -- look at the data in the cb
  828.                hab              ||         -- anchor block
  829.                atoi(1)          ||         -- data format ( TEXT )
  830.                address(format))
  831. --   format = itoa(format,10)                -- Convert format to ASCII
  832.    format = 256
  833. compile endif
  834.    return rc
  835.  
  836. compile if EVERSION >= 5.50
  837. defc insert_text_file
  838.    universal default_edit_options
  839.    get_file = strip(arg(1))
  840.    if get_file='' then sayerror NO_FILENAME__MSG 'GET'; return; endif
  841.    if pos(argsep,get_file) then
  842.       sayerror INVALID_OPTION__MSG
  843.       return
  844.    endif
  845.    getfileid fileid
  846.    s_last=.last
  847.    display -1
  848.    'e /q /d' get_file
  849.    editrc=rc
  850.    getfileid gfileid
  851.    if editrc = -282 | not .last then  -- -282 = sayerror('New file')
  852.       'q'
  853.       display 1
  854.       if editrc= -282 then
  855.          sayerror FILE_NOT_FOUND__MSG':  'get_file
  856.       else
  857.          sayerror FILE_IS_EMPTY__MSG':  'get_file
  858.       endif
  859.       return
  860.    endif
  861.    if editrc & editrc<>-278 then  -- -278  sayerror('Lines truncated') then
  862.       display 1
  863.       sayerror editrc
  864.       stop
  865.    endif
  866.    call psave_mark(save_mark)
  867.  compile if WANT_BOOKMARKS
  868.    if not .levelofattributesupport then
  869.       'loadattributes'
  870.    endif
  871.  compile endif
  872.    get_file_attrib = .levelofattributesupport
  873.    if rightstr(textline(.last), 1) = \26 then  -- Ends with EOF?
  874.       incr = 0
  875.    else
  876.       incr = 1
  877.    endif
  878.    setmark 1, .last, 1, length(textline(.last))+incr, 3, gfileid  -- 3 = CHARG mark
  879.    activatefile fileid
  880.    if not .last then
  881.       insert
  882.       .col = 1
  883.    elseif .line = .last then
  884.       xxx = .mousex
  885.       yyy = .mousey
  886.       map_point 5, xxx, yyy, off, comment;  -- map screen to line
  887.       if xxx > .last then  -- Dropped below bottom of file; append to end.
  888.          insert
  889.          .col = 1
  890.       endif
  891.    endif
  892.    rc=0
  893.    copy_mark
  894.    copy_rc=rc           -- Test for memory too full for copy_mark.
  895.    activatefile gfileid
  896.    'q'
  897.    parse value save_mark with s_firstline s_lastline s_firstcol s_lastcol s_mkfileid s_mt
  898.    if fileid=s_mkfileid then           -- May have to move the mark.
  899.       diff=fileid.last-s_last          -- (Adjustment for difference in size)
  900.       if fileid.line<s_firstline then s_firstline=s_firstline+diff; endif
  901.       if fileid.line<s_lastline then s_lastline=s_lastline+diff; endif
  902.    endif
  903.    call prestore_mark(s_firstline s_lastline s_firstcol s_lastcol s_mkfileid s_mt)
  904.    activatefile fileid
  905.    if get_file_attrib // 2 then
  906.       call attribute_on(1)  -- Colors flag
  907.    endif
  908.  compile if EVERSION >= '6.01b'
  909.    if get_file_attrib bitand 4 then
  910.  compile else
  911.    if get_file_attrib % 4 - 2 * (get_file_attrib % 8) then
  912.  compile endif
  913.       call attribute_on(4)  -- Mixed fonts flag
  914.    endif
  915.  compile if EVERSION >= '6.01b'
  916.    if get_file_attrib bitand 8 then
  917.  compile else
  918.    if get_file_attrib % 8 - 2 * (get_file_attrib % 16) then
  919.  compile endif
  920.       call attribute_on(8)  -- "Save attributes" flag
  921.    endif
  922.    display 1
  923.    if copy_rc & copy_rc<>-281 then
  924.       sayerror NOT_2_COPIES__MSG get_file
  925.    endif
  926. compile endif
  927.