home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Libraries / WASTE 1.1a4 / WASTE Source / WEHighLevelEditing.p < prev    next >
Encoding:
Text File  |  1994-11-10  |  35.4 KB  |  1,408 lines  |  [TEXT/PJMM]

  1. unit WEHighLevelEditing;
  2.  
  3. { WASTE PROJECT: }
  4. { High-Level Editing Routines }
  5.  
  6. { Copyright © 1993-1994 Marco Piovanelli }
  7. { All Rights Reserved }
  8.  
  9. interface
  10.     uses
  11.         WELowLevelEditing;
  12.  
  13.     const
  14.  
  15. { action kinds }
  16.  
  17.         weAKNone = 0;                                { null action }
  18.         weAKUnspecified = 1;                    { action of unspecified nature }
  19.         weAKTyping = 2;                            { some text has been typed in }
  20.         weAKCut = 3;                                { the selection range has been cut }
  21.         weAKPaste = 4;                                { something has been pasted }
  22.         weAKClear = 5;                                { the selection range has been deleted }
  23.         weAKDrag = 6;                                { drag and drop operation }
  24.         weAKSetStyle = 7;                        { some style has been applied to a text range }
  25.  
  26. { action flags }
  27.  
  28.         weAFIsRedo = $0001;                    { action saves edit state prior to a WEUndo call }
  29.         weAFDontSaveText = $0002;        { don't save text }
  30.         weAFDontSaveStyles = $0004;        { don't save styles }
  31.         weAFDontSaveSoup = $0008;        { don't save embedded object information }
  32.  
  33.     type
  34.  
  35.         WEActionKind = Integer;
  36.         WEActionFlags = Integer;
  37.  
  38. { a WEAction record is used to record a single editing operation on a WE instance, }
  39. { like typing some text, cutting or pasting.  A linked list of WEAction records might }
  40. { be used to implement multiple undo. }
  41.  
  42.         WEActionHandle = ^WEActionPtr;
  43.         WEActionPtr = ^WEAction;
  44.         WEAction = record
  45.                 hOwner: WEHandle;                    { handle to associated WE instance }
  46.                 hNext: WEActionHandle;            { used to keep a linked list of actions }
  47.                 hText: Handle;                            { handle to saved text }
  48.                 hStyles: Handle;                        { handle to saved styles }
  49.                 hSoup: Handle;                            { handle to saved "soup" }
  50.                 delRangeStart: LongInt;            { start of range to delete }
  51.                 delRangeLength: LongInt;            { length of range to delete }
  52.                 insRangeLength: LongInt;            { length of range to insert }
  53.                 hiliteStart: LongInt;                    { start of range to hilite }
  54.                 hiliteEnd: LongInt;                    { end of range to hilite }
  55.                 actionKind: WEActionKind;        { identifies event that caused this action to be pushed }
  56.                 actionFlags: WEActionFlags;        { miscellaneous flags }
  57.             end;  { WEAction }
  58.  
  59. { high-level editing functions }
  60.  
  61.     procedure WEKey (key: Char;
  62.                                     modifiers: Integer;
  63.                                     hWE: WEHandle);
  64.     function WEInsert (textPtr: Ptr;
  65.                                     textLength: LongInt;
  66.                                     hStyles: StScrpHandle;
  67.                                     hSoup: Handle;
  68.                                     hWE: WEHandle): OSErr;
  69.     function WEInsertObject (objectType: OSType;
  70.                                     objectDataHandle: Handle;
  71.                                     objectSize: Point;
  72.                                     hWE: WEHandle): OSErr;
  73.     function WEDelete (hWE: WEHandle): OSErr;
  74.     function WECut (hWE: WEHandle): OSErr;
  75.     function WEPaste (hWE: WEHandle): OSErr;
  76.     function WESetStyle (mode: Integer;
  77.                                     var ts: WETextStyle;
  78.                                     hWE: WEHandle): OSErr;
  79.     function WEUseStyleScrap (hStyles: StScrpHandle;
  80.                                     hWE: WEHandle): OSErr;
  81.  
  82. { high-level Undo functions }
  83.  
  84.     function WEUndo (hWE: WEHandle): OSErr;
  85.     procedure WEClearUndo (hWE: WEHandle);
  86.     function WEGetUndoInfo (var redoFlag: Boolean;
  87.                                     hWE: WEHandle): WEActionKind;
  88.  
  89. { keeping track of changes }
  90.  
  91.     function WEGetModCount (hWE: WEHandle): LongInt;
  92.     procedure WEResetModCount (hWE: WEHandle);
  93.  
  94. { actions }
  95.  
  96.     function WENewAction (rangeStart, rangeEnd: LongInt;
  97.                                     newTextLength: LongInt;
  98.                                     actionKind: WEActionKind;
  99.                                     actionFlags: WEActionFlags;
  100.                                     hWE: WEHandle;
  101.                                     var hAction: WEActionHandle): OSErr;
  102.     procedure WEDisposeAction (hAction: WEActionHandle);
  103.     function WEDoAction (hAction: WEActionHandle): OSErr;
  104.  
  105. { low-level routines for directly manipulating }
  106. { the action stack associated with a given WE instance }
  107.  
  108.     function WEGetActionStack (hWE: WEHandle): WEActionHandle;
  109.     function WEPushAction (hAction: WEActionHandle): OSErr;
  110.  
  111. { miscellaneous }
  112.  
  113.     function WECanPaste: Boolean;
  114.     procedure _WEAdjustUndoRange (moreBytes: LongInt;
  115.                                     hWE: WEHandle);
  116.     function WEIsTyping (hWE: WEHandle): Boolean;
  117.  
  118. implementation
  119.     uses
  120.         WEScraps;
  121.  
  122.     function WEGetActionStack (hWE: WEHandle): WEActionHandle;
  123.     begin
  124.         WEGetActionStack := WEActionHandle(hWE^^.hActionStack);
  125.     end;  { WEGetActionStack }
  126.  
  127.     function WEPushAction (hAction: WEActionHandle): OSErr;
  128.         var
  129.             pWE: WEPtr;
  130.             hLast: WEActionHandle;
  131.     begin
  132.         WEPushAction := noErr;
  133.  
  134. { find the last action in the given stack }
  135.         hLast := hAction;
  136.         while (hLast^^.hNext <> nil) do
  137.             hLast := hLast^^.hNext;
  138.  
  139. { prepend hAction in front of the action stack }
  140.         pWE := hAction^^.hOwner^;
  141.         hLast^^.hNext := WEActionHandle(pWE^.hActionStack);
  142.         pWE^.hActionStack := Handle(hAction);
  143.  
  144.     end;  { WEPushAction }
  145.  
  146.     function WENewAction (rangeStart, rangeEnd: LongInt;
  147.                                     newTextLength: LongInt;
  148.                                     actionKind: WEActionKind;
  149.                                     actionFlags: WEActionFlags;
  150.                                     hWE: WEHandle;
  151.                                     var hAction: WEActionHandle): OSErr;
  152.         label
  153.             0, 1;
  154.         var
  155.             pAction: WEActionPtr;
  156.             err: OSErr;
  157.     begin
  158.  
  159. { allocate a new action record }
  160.         err := _WEAllocate(SizeOf(WEAction), kAllocClear, hAction);
  161.         if (err <> noErr) then
  162.             goto 1;
  163.  
  164. { lock it down }
  165.         HLock(Handle(hAction));
  166.         pAction := hAction^;
  167.  
  168. { fill in the fields }
  169.         pAction^.hOwner := hWE;
  170.         pAction^.delRangeStart := rangeStart;
  171.         pAction^.delRangeLength := newTextLength;
  172.         pAction^.insRangeLength := rangeEnd - rangeStart;
  173.         pAction^.actionKind := actionKind;
  174.         pAction^.actionFlags := actionFlags;
  175.  
  176. { remember selection range }
  177.         WEGetSelection(pAction^.hiliteStart, pAction^.hiliteEnd, hWE);
  178.  
  179. { allocate a handle to hold the text to be saved, unless otherwise specified }
  180.         if (BitAnd(actionFlags, weAFDontSaveText) = 0) then
  181.             begin
  182.                 err := _WEAllocate(0, kAllocTemp, pAction^.hText);
  183.                 if (err <> noErr) then
  184.                     goto 1;
  185.             end;
  186.  
  187. { allocate a handle to hold the styles to be saved, unless otherwise specified }
  188.         if (BitAnd(actionFlags, weAFDontSaveStyles) = 0) then
  189.             begin
  190.                 err := _WEAllocate(0, kAllocTemp, pAction^.hStyles);
  191.                 if (err <> noErr) then
  192.                     goto 1;
  193.             end;
  194.  
  195. { allocate a handle to hold the "soup" to be saved, unless otherwise specified }
  196.         if (BitAnd(actionFlags, weAFDontSaveSoup) = 0) then
  197.             begin
  198.                 err := _WEAllocate(0, kAllocTemp, pAction^.hSoup);
  199.                 if (err <> noErr) then
  200.                     goto 1;
  201.             end;
  202.  
  203. { make a copy of text range }
  204.         err := WECopyRange(rangeStart, rangeEnd, pAction^.hText, pAction^.hStyles, pAction^.hSoup, hWE);
  205.         if (err <> noErr) then
  206.             goto 1;
  207.  
  208. { unlock action record }
  209.         HUnlock(Handle(hAction));
  210.  
  211. { skip clean-up section }
  212.         goto 0;
  213.  
  214. 1:
  215. { clean up }
  216.         _WEForgetHandle(pAction^.hText);
  217.         _WEForgetHandle(pAction^.hStyles);
  218.         _WEForgetHandle(pAction^.hSoup);
  219.         _WEForgetHandle(hAction);
  220.  
  221. 0:
  222. { return result code }
  223.         WENewAction := err;
  224.  
  225.     end;  { WENewAction }
  226.  
  227.     procedure WEDisposeAction (hAction: WEActionHandle);
  228.         var
  229.             pAction: WEActionPtr;
  230.             hNext: WEActionHandle;
  231.     begin
  232.         while (hAction <> nil) do
  233.             begin
  234.  
  235. { lock the action record }
  236.                 HLock(Handle(hAction));
  237.                 pAction := hAction^;
  238.                 hNext := pAction^.hNext;
  239.  
  240. { throw away text, styles and soup }
  241.                 _WEForgetHandle(pAction^.hText);
  242.                 _WEForgetHandle(pAction^.hStyles);
  243.                 _WEForgetHandle(pAction^.hSoup);
  244.  
  245. { throw away the action record itself }
  246.                 DisposeHandle(Handle(hAction));
  247.  
  248. { repeat the same sequence with all linked actions }
  249.                 hAction := hNext;
  250.  
  251.             end;  { while }
  252.     end;  { WEDisposeAction }
  253.  
  254.     procedure WEForgetAction (var hAction: WEActionHandle);
  255.         var
  256.             theAction: WEActionHandle;
  257.     begin
  258.         theAction := hAction;
  259.         if (theAction <> nil) then
  260.             begin
  261.                 hAction := nil;
  262.                 WEDisposeAction(theAction);
  263.             end;
  264.     end;  { WEForgetAction }
  265.  
  266.     function WEDoAction (hAction: WEActionHandle): OSErr;
  267.         label
  268.             1;
  269.         var
  270.             hRedoAction: WEActionHandle;
  271.             pAction: WEActionPtr;
  272.             hWE: WEHandle;
  273.             pWE: WEPtr;
  274.             offset, delOffset, insOffset: LongInt;
  275.             redrawStart, redrawEnd: LongInt;
  276.             saveActionLock, saveWELock, saveTextLock: Boolean;
  277.             err: OSErr;
  278.     begin
  279.  
  280. { sanity check: make sure hAction isn't NIL }
  281.         if (hAction = nil) then
  282.             begin
  283.                 WEDoAction := nilHandleErr;
  284.                 Exit(WEDoAction);
  285.             end;
  286.  
  287. { get handle to associated WE instance }
  288.         hWE := hAction^^.hOwner;
  289.  
  290. { lock the WE record }
  291.         saveWELock := _WESetHandleLock(hWE, true);
  292.         pWE := hWE^;
  293.  
  294. { hide selection highlighting and the caret }
  295.         _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE);
  296.         if BTST(pWE^.flags, weFCaretVisible) then
  297.             _WEBlinkCaret(hWE);
  298.  
  299.         redrawStart := maxLongInt;
  300.         redrawEnd := 0;
  301.  
  302.         repeat
  303.  
  304. { lock the action record }
  305.             saveActionLock := _WESetHandleLock(hAction, true);
  306.             pAction := hAction^;
  307.             offset := pAction^.delRangeStart;
  308.             delOffset := offset + pAction^.delRangeLength;
  309.             insOffset := offset + pAction^.insRangeLength;
  310.  
  311. { if undo support is enabled, save the range to be affected by this action }
  312.             if (BTST(pWE^.flags, weFUndoSupport)) then
  313.                 if (WENewAction(offset, delOffset, pAction^.insRangeLength, pAction^.actionKind, BitXor(pAction^.actionFlags, weAFIsRedo), hWE, hRedoAction) = noErr) then
  314.                     if (WEPushAction(hRedoAction) <> noErr) then
  315.                         ;
  316.  
  317.             if (pAction^.hText <> nil) then
  318.                 begin
  319.  
  320. { delete the range to replace }
  321.                     err := _WEDeleteRange(offset, delOffset, hWE);
  322.                     if (err <> noErr) then
  323.                         goto 1;
  324.  
  325. { insert the saved text }
  326.                     saveTextLock := _WESetHandleLock(pAction^.hText, true);
  327.                     err := _WEInsertText(offset, pAction^.hText^, pAction^.insRangeLength, hWE);
  328.                     IgnoreBoolean(_WESetHandleLock(pAction^.hText, saveTextLock));
  329.                     if (err <> noErr) then
  330.                         goto 1;
  331.  
  332.                 end;
  333.  
  334. { apply the saved styles, if any }
  335.             if (pAction^.hStyles <> nil) then
  336.                 begin
  337.                     err := _WEApplyStyleScrap(offset, insOffset, StScrpHandle(pAction^.hStyles), hWE);
  338.                     if (err <> noErr) then
  339.                         goto 1;
  340.                 end;
  341.  
  342. { the same goes for the soup }
  343.             if (pAction^.hSoup <> nil) then
  344.                 begin
  345.                     err := _WEApplySoup(offset, pAction^.hSoup, hWE);
  346.                     if (err <> noErr) then
  347.                         goto 1;
  348.                 end;
  349.  
  350. { adjust redraw range }
  351.             if (offset < redrawStart) then
  352.                 redrawStart := offset;
  353.             if (insOffset > redrawEnd) then
  354.                 redrawEnd := insOffset;
  355.  
  356. { unlock action record }
  357.             IgnoreBoolean(_WESetHandleLock(hAction, saveActionLock));
  358.  
  359. { go to next action }
  360.             hAction := hAction^^.hNext;
  361.  
  362.         until (hAction = nil);
  363.  
  364. { restore the original selection range }
  365.         pWE^.selStart := pAction^.hiliteStart;
  366.         pWE^.selEnd := pAction^.hiliteEnd;
  367.  
  368. { redraw the text }
  369.         err := _WERedraw(redrawStart, redrawEnd, hWE);
  370.         if (err <> noErr) then
  371.             goto 1;
  372.  
  373. { clear result code }
  374.         err := noErr;
  375.  
  376. 1:
  377. { unlock the WE record }
  378.         IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
  379.  
  380. { return result code }
  381.         WEDoAction := err;
  382.  
  383.     end;  { WEDoAction }
  384.  
  385.     function WEUndo (hWE: WEHandle): OSErr;
  386.         var
  387.             pWE: WEPtr;
  388.             hAction: WEActionHandle;
  389.             saveWELock: Boolean;
  390.     begin
  391.  
  392. { lock the WE record }
  393.         saveWELock := _WESetHandleLock(hWE, true);
  394.         pWE := hWE^;
  395.  
  396. { stop any ongoing inline input session }
  397.         WEStopInlineSession(hWE);
  398.  
  399. { "detach" the action stack from the WE instance }
  400.         hAction := WEActionHandle(pWE^.hActionStack);
  401.         pWE^.hActionStack := nil;
  402.  
  403.         if (hAction <> nil) then
  404.             begin
  405.  
  406. { undoing a change _decrements_ the modification count; }
  407. { redoing the change increments it again }
  408.                 if (BitAnd(hAction^^.actionFlags, weAFIsRedo) <> 0) then
  409.                     pWE^.modCount := pWE^.modCount + 1
  410.                 else
  411.                     pWE^.modCount := pWE^.modCount - 1;
  412.  
  413. { perform the action... }
  414.                 WEUndo := WEDoAction(hAction);
  415.  
  416. { ...and throw it away }
  417.                 WEDisposeAction(hAction);
  418.  
  419.             end
  420.         else
  421.  
  422. { return an error code if the undo buffer is empty }
  423.             WEUndo := weCantUndoErr;
  424.  
  425. { unlock the WE record }
  426.         IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
  427.  
  428.     end;  { WEUndo }
  429.  
  430.     procedure WEClearUndo (hWE: WEHandle);
  431.     begin
  432.  
  433. { dispose of the action chain associated with the given WE instance }
  434.         WEForgetAction(WEActionHandle(hWE^^.hActionStack));
  435.  
  436.     end;  { WEClearUndo }
  437.  
  438.     function WEGetUndoInfo (var redoFlag: Boolean;
  439.                                     hWE: WEHandle): WEActionKind;
  440.     begin
  441.         WEGetUndoInfo := weAKNone;        { assume no actions have been saved }
  442.         redoFlag := false;
  443.  
  444.         if (hWE^^.hActionStack <> nil) then
  445.             with WEActionHandle(hWE^^.hActionStack)^^ do
  446.                 begin
  447.                     WEGetUndoInfo := actionKind;
  448.                     redoFlag := (BitAnd(actionFlags, weAFIsRedo) <> 0);
  449.                 end;
  450.     end;  { WEGetUndoInfo }
  451.  
  452.     function WEGetModCount (hWE: WEHandle): LongInt;
  453.     begin
  454.         WEGetModCount := hWE^^.modCount;
  455.     end;  { WEGetModCount }
  456.  
  457.     procedure WEResetModCount (hWE: WEHandle);
  458.     begin
  459.         hWE^^.modCount := 0;
  460.         WEClearUndo(hWE);
  461.     end;  { WEResetModCount }
  462.  
  463.     procedure _WEAdjustUndoRange (moreBytes: LongInt;
  464.                                     hWE: WEHandle);
  465.         var
  466.             hAction: WEActionHandle;
  467.     begin
  468.         hAction := WEActionHandle(hWE^^.hActionStack);
  469.         if (hAction <> nil) then
  470.             with hAction^^ do
  471.                 delRangeLength := delRangeLength + moreBytes;
  472.     end;  { _WEAdjustUndoRange }
  473.  
  474.     function _WETypeChar (theByte: SignedByte;
  475.                                     hWE: WEHandle): OSErr;
  476.         label
  477.             0, 1;
  478.         var
  479.             pWE: WEPtr;
  480.             db: DoubleByte;
  481.             offset, endOffset, charLength: LongInt;
  482.             byteType: Integer;
  483.             saveFont: Integer;
  484.             savePort: GrafPtr;
  485.             err: OSErr;
  486.     begin
  487.         pWE := hWE^;                    { the WE record must be already locked }
  488.         charLength := 1;                { assume 1-byte character by default }
  489.         db.firstByte := theByte;
  490.         offset := pWE^.selStart;
  491.  
  492. { delete current selection, if any }
  493.         err := _WEDeleteRange(offset, pWE^.selEnd, hWE);
  494.         if (err <> noErr) then
  495.             goto 1;
  496. (*pWE^.selEnd := offset;*)
  497.  
  498. { make sure the font script is synchronized with the keyboard script }
  499.         _WESynchNullStyle(hWE);
  500.  
  501.         if BTST(pWE^.flags, weFDoubleByte) then
  502.             begin
  503.  
  504. { special processing for double-byte characters }
  505.                 if (pWE^.firstByte <> 0) then
  506.                     begin
  507.  
  508. { if this byte is the second half of a double-byte character, }
  509. { insert the two bytes at the same time (flush the double-byte cache) }
  510.                         db.firstByte := pWE^.firstByte;
  511.                         db.secondByte := theByte;
  512.                         charLength := 2;
  513.                         pWE^.firstByte := 0;
  514.                     end
  515.                 else
  516.                     begin
  517.  
  518. { determine the byte-type of theByte; first set up the port and its font }
  519.                         GetPort(savePort);
  520.                         SetPort(pWE^.port);
  521.                         saveFont := pWE^.port^.txFont;
  522.                         TextFont(pWE^.nullStyle.runStyle.tsFont);
  523.  
  524. { call CharByte }
  525.                         byteType := CharByte(@theByte, 0);
  526.  
  527. { put back font and port }
  528.                         TextFont(saveFont);
  529.                         SetPort(savePort);
  530.  
  531. { if theByte is the first half of a double-byte character, just cache it and exit }
  532.                         if (byteType = smFirstByte) then
  533.                             begin
  534.                                 pWE^.firstByte := theByte;
  535.                                 goto 0;
  536.                             end;
  537.                     end;
  538.  
  539.             end;  { if double-byte script installed }
  540.  
  541. { insert the new character into the text }
  542.         err := _WEInsertText(offset, @db, charLength, hWE);
  543.         if (err <> noErr) then
  544.             goto 1;
  545.  
  546. { adjust undo buffer for the new character }
  547.         _WEAdjustUndoRange(charLength, hWE);
  548.  
  549. { invalid the null style }
  550.         BCLR(pWE^.flags, weFUseNullStyle);
  551.  
  552. { move the insertion point after the new character }
  553.         endOffset := offset + charLength;
  554.         pWE^.selStart := endOffset;
  555.         pWE^.selEnd := endOffset;
  556.  
  557. { redraw the text }
  558.         err := _WERedraw(offset, endOffset, hWE);
  559.         if (err <> noErr) then
  560.             goto 1;
  561.  
  562. 0:
  563. { clear result code }
  564.         err := noErr;
  565.  
  566. 1:
  567. { return result code }
  568.         _WETypeChar := err;
  569.  
  570.     end;  { _WETypeChar }
  571.  
  572.     function _WEBackspace (hWE: WEHandle): OSErr;
  573.  
  574. { this routine is called by WEKey to handle the backspace key }
  575. { the WE record is guaranteed to be already locked }
  576.  
  577.         label
  578.             0, 1;
  579.         var
  580.             pWE: WEPtr;
  581.             pAction: WEActionPtr;
  582.             rangeStart, rangeEnd, charLength: LongInt;
  583.             pChars: WECharsPtr;
  584.             runInfo: WERunInfo;
  585.             saveActionLock: Boolean;
  586.             err: OSErr;
  587.     begin
  588.         pWE := hWE^;
  589.  
  590. { calculate the text range to delete }
  591. { if the selection is non-empty, delete that }
  592.         rangeStart := pWE^.selStart;
  593.         rangeEnd := pWE^.selEnd;
  594.         if (rangeStart = rangeEnd) then
  595.             begin
  596.  
  597. { otherwise the selection is an insertion point }
  598. { do nothing if insertion point is at the beginning of the text }
  599.                 if (rangeStart = 0) then
  600.                     goto 0;
  601.  
  602. { determine the byte-type of the character preceding the insertion point }
  603.                 if (WECharByte(rangeStart - 1, hWE) = smSingleByte) then
  604.                     charLength := 1
  605.                 else
  606.                     charLength := 2;
  607.                 rangeStart := rangeStart - charLength;
  608.  
  609.                 if (pWE^.hActionStack <> nil) then
  610.                     begin
  611.  
  612. { UNDO SUPPORT FOR BACKSPACES }
  613.  
  614. { lock the action record }
  615.                         saveActionLock := _WESetHandleLock(pWE^.hActionStack, true);
  616.                         pAction := WEActionHandle(pWE^.hActionStack)^;
  617.  
  618. { backspaces over the newly entered text aren't a problem }
  619.                         if (pAction^.delRangeLength > 0) then
  620.                             pAction^.delRangeLength := pAction^.delRangeLength - charLength
  621.                         else
  622.                             begin
  623.  
  624. { the hard part comes when backspacing past the new text because }
  625. { the user is about to delete a character not included in the block we saved }
  626.  
  627. { lengthen our saved text handle }
  628.                                 err := %_SetHandleSize(pAction^.hText, pAction^.insRangeLength + charLength);
  629.                                 if (err <> noErr) then
  630.                                     goto 1;
  631.  
  632. { move old contents forward }
  633.                                 pChars := WECharsHandle(pAction^.hText)^;
  634.                                 %_BlockMoveData(@pChars^[0], @pChars^[charLength], pAction^.insRangeLength);
  635.  
  636. { prepend the character to be deleted to the beginning of our saved text handle }
  637.                                 pChars^[0] := WEGetChar(rangeStart, hWE);
  638.                                 if (charLength = 2) then
  639.                                     pChars^[1] := WEGetChar(rangeStart + 1, hWE);
  640.  
  641. { adjust internal counters }
  642.                                 pAction^.insRangeLength := pAction^.insRangeLength + charLength;
  643.                                 pAction^.delRangeStart := pAction^.delRangeStart - charLength;
  644.  
  645. { get style run info associated with the about-to-be-deleted character }
  646.                                 WEGetRunInfo(rangeStart, runInfo, hWE);
  647.  
  648. { prepend a new style element to our style scrap, if necessary }
  649.                                 err := _WEPrependStyle(pAction^.hStyles, runInfo, charLength);
  650.                                 if (err <> noErr) then
  651.                                     goto 1;
  652.  
  653. { do the same with our object "soup" }
  654.                                 err := _WEPrependObject(pAction^.hSoup, runInfo, charLength);
  655.                                 if (err <> noErr) then
  656.                                     goto 1;
  657.  
  658.                             end;  { if deleting old text }
  659.  
  660. { unlock the action record }
  661.                         IgnoreBoolean(_WESetHandleLock(pWE^.hActionStack, saveActionLock));
  662.  
  663.                     end;  { if undo support is enabled }
  664.             end;  { if selection is empty }
  665.  
  666.         err := _WEDeleteRange(rangeStart, rangeEnd, hWE);
  667.         if (err <> noErr) then
  668.             goto 1;
  669.  
  670. { keep track of current selection range }
  671.         pWE^.selStart := rangeStart;
  672.         pWE^.selEnd := rangeStart;
  673.  
  674. { redraw the text }
  675.         err := _WERedraw(rangeStart, rangeStart, hWE);
  676.         if (err <> noErr) then
  677.             goto 1;
  678.  
  679. 0:
  680. { clear result code }
  681.         err := noErr;
  682.  
  683. 1:
  684. { return result code }
  685.         _WEBackspace := err;
  686.  
  687.     end;  { _WEBackspace }
  688.  
  689.     function _WEForwardDelete (hWE: WEHandle): OSErr;
  690.  
  691. { this routine is called by WEKey to handle the forward delete key }
  692. { the WE record is guaranteed to be already locked }
  693.  
  694.         label
  695.             0, 1;
  696.         var
  697.             pWE: WEPtr;
  698.             pAction: WEActionPtr;
  699.             rangeStart, rangeEnd, charLength: LongInt;
  700.             runInfo: WERunInfo;
  701.             db: DoubleByte;
  702.             saveActionLock: Boolean;
  703.             err: OSErr;
  704.     begin
  705.         pWE := hWE^;
  706.  
  707. { calculate the text range to delete }
  708. { if the selection is non-empty, delete that }
  709.         rangeStart := pWE^.selStart;
  710.         rangeEnd := pWE^.selEnd;
  711.         if (rangeStart = rangeEnd) then
  712.             begin
  713.  
  714. { otherwise the selection is an insertion point }
  715. { do nothing if insertion point is at the end of the text }
  716.                 if (rangeStart = pWE^.textLength) then
  717.                     goto 0;
  718.  
  719. { determine the byte-type of the character following the insertion point }
  720.                 if (WECharByte(rangeStart, hWE) = smSingleByte) then
  721.                     charLength := 1
  722.                 else
  723.                     charLength := 2;
  724.                 rangeEnd := rangeStart + charLength;
  725.  
  726.                 if (pWE^.hActionStack <> nil) then
  727.                     begin
  728.  
  729. { UNDO SUPPORT FOR FORWARD DELETE }
  730.  
  731. { lock the action record }
  732.                         saveActionLock := _WESetHandleLock(pWE^.hActionStack, true);
  733.                         pAction := WEActionHandle(pWE^.hActionStack)^;
  734.  
  735. { make a copy of the character about to be deleted }
  736.                         db.firstByte := SignedByte(WEGetChar(rangeStart, hWE));
  737.                         if (charLength = 2) then
  738.                             db.secondByte := SignedByte(WEGetChar(rangeStart + 1, hWE));
  739.  
  740. { append it to the end of our saved text handle }
  741.                         err := %_PtrAndHand(@db, pAction^.hText, charLength);
  742.                         if (err <> noErr) then
  743.                             goto 1;
  744.  
  745. { get style run info associated with the about-to-be-deleted character }
  746.                         WEGetRunInfo(rangeStart, runInfo, hWE);
  747.  
  748. { append a new style element to our style scrap, if necessary }
  749.                         err := _WEAppendStyle(pAction^.hStyles, runInfo, pAction^.insRangeLength);
  750.                         if (err <> noErr) then
  751.                             goto 1;
  752.  
  753. { do the same with our object soup }
  754.                         err := _WEAppendObject(pAction^.hSoup, runInfo, pAction^.insRangeLength);
  755.                         if (err <> noErr) then
  756.                             goto 1;
  757.  
  758. { adjust internal counters }
  759.                         pAction^.insRangeLength := pAction^.insRangeLength + charLength;
  760.  
  761. { unlock the action record }
  762.                         IgnoreBoolean(_WESetHandleLock(pWE^.hActionStack, saveActionLock));
  763.  
  764.                     end;  { if undo support is enabled }
  765.             end;  { if selection is empty }
  766.  
  767.         err := _WEDeleteRange(rangeStart, rangeEnd, hWE);
  768.         if (err <> noErr) then
  769.             goto 1;
  770.  
  771. { keep track of current selection range }
  772.         pWE^.selStart := rangeStart;
  773.         pWE^.selEnd := rangeStart;
  774.  
  775. { redraw the text }
  776.         err := _WERedraw(rangeStart, rangeStart, hWE);
  777.         if (err <> noErr) then
  778.             goto 1;
  779.  
  780. 0:
  781. { clear result code }
  782.         err := noErr;
  783.  
  784. 1:
  785. { return result code }
  786.         _WEForwardDelete := err;
  787.  
  788.     end;  { _WEForwardDelete }
  789.  
  790.     function WEIsTyping (hWE: WEHandle): Boolean;
  791.         var
  792.             pWE: WEPtr;
  793.     begin
  794.  
  795. { return TRUE if we're tracking a typing sequence in the specified WE instance }
  796.  
  797.         WEIsTyping := false;            { assume we aren't }
  798.         pWE := hWE^;                    { the WE record must already be locked }
  799.  
  800. { there must be an undo buffer }
  801.         if (pWE^.hActionStack = nil) then
  802.             Exit(WEIsTyping);
  803.  
  804.         with WEActionHandle(pWE^.hActionStack)^^ do
  805.             begin
  806.  
  807. { the action kind must be "typing" and the redo flag must be clear }
  808.                 if (actionKind <> weAKTyping) then
  809.                     Exit(WEIsTyping);
  810.                 if (BitAnd(actionFlags, weAFIsRedo) <> 0) then
  811.                     Exit(WEIsTyping);
  812.  
  813. { finally, the selection range mustn't have moved since the last WEKey }
  814.                 if ((pWE^.selStart = pWE^.selEnd) and (pWE^.selStart = delRangeStart + delRangeLength)) then
  815.                     WEIsTyping := true;
  816.             end;  { with }
  817.     end;  { WEIsTyping }
  818.  
  819.     procedure WEKey (key: Char;
  820.                                     modifiers: Integer;
  821.                                     hWE: WEHandle);
  822.         var
  823.             pWE: WEPtr;
  824.             hAction: WEActionHandle;
  825.             saveWELock: Boolean;
  826.     begin
  827.  
  828. { lock the WE record }
  829.         saveWELock := _WESetHandleLock(hWE, true);
  830.         pWE := hWE^;
  831.  
  832. { hide the caret if it's showing }
  833.         if BTST(pWE^.flags, weFCaretVisible) then
  834.             _WEBlinkCaret(hWE);
  835.  
  836. { hide the cursor (it will show again as soon as it's moved) }
  837.         ObscureCursor;
  838.  
  839. { dispatch on key class (arrow keys, printable characters, backspace) }
  840.         if ((ORD(key) >= kArrowLeft) and (ORD(key) <= kArrowDown)) then
  841.             _WEDoArrowKey(ORD(key), modifiers, hWE)
  842.         else
  843.             begin
  844.  
  845. { are we tracking a typing sequence? }
  846.                 if (WEIsTyping(hWE) = false) then
  847.                     begin
  848.  
  849. { nope; so start a new one }
  850. { increment modification count }
  851.                         pWE^.modCount := pWE^.modCount + 1;
  852.  
  853. { if undo support is enabled, create a new action to keep track of the typing }
  854.                         if (BTST(pWE^.flags, weFUndoSupport)) then
  855.                             begin
  856.                                 WEClearUndo(hWE);
  857.                                 if (WENewAction(pWE^.selStart, pWE^.selEnd, 0, weAKTyping, 0, hWE, hAction) = noErr) then
  858.                                     if (WEPushAction(hAction) <> noErr) then
  859.                                         ;
  860.                             end;
  861.                     end;
  862.  
  863.                 if (ORD(key) = kBackspace) then
  864.                     IgnoreShort(_WEBackspace(hWE))
  865.                 else if (ORD(key) = kForwardDelete) then
  866.                     IgnoreShort(_WEForwardDelete(hWE))
  867.                 else
  868.                     IgnoreShort(_WETypeChar(ORD(key), hWE));
  869.             end;
  870.  
  871. { unlock the WE record }
  872.         IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
  873.  
  874.     end;  { WEKey }
  875.  
  876.     function WEInsert (textPtr: Ptr;
  877.                                     textLength: LongInt;
  878.                                     hStyles: StScrpHandle;
  879.                                     hSoup: Handle;
  880.                                     hWE: WEHandle): OSErr;
  881.         label
  882.             1;
  883.         var
  884.             pWE: WEPtr;
  885.             offset, endOffset: LongInt;
  886.             hAction: WEActionHandle;
  887.             intPasteAction: Integer;
  888.             saveWELock: Boolean;
  889.             space: SignedByte;
  890.             err: OSErr;
  891.     begin
  892.  
  893. { stop any ongoing inline input session }
  894.         WEStopInlineSession(hWE);
  895.  
  896. { lock the WE record }
  897.         saveWELock := _WESetHandleLock(hWE, true);
  898.         pWE := hWE^;
  899.         offset := pWE^.selStart;
  900.  
  901. { increment modification count }
  902.         pWE^.modCount := pWE^.modCount + 1;
  903.  
  904. { if undo support is enabled, save current selection range }
  905.         if (BTST(pWE^.flags, weFUndoSupport)) then
  906.             begin
  907.                 WEClearUndo(hWE);
  908.                 if (WENewAction(offset, pWE^.selEnd, textLength, weAKUnspecified, 0, hWE, hAction) = noErr) then
  909.                     if (WEPushAction(hAction) <> noErr) then
  910.                         ;
  911.             end;
  912.  
  913. { delete current selection }
  914.         err := _WEDeleteRange(offset, pWE^.selEnd, hWE);
  915.         if (err <> noErr) then
  916.             goto 1;
  917.  
  918. { insert the new text at the insertion point }
  919.         err := _WEInsertText(offset, textPtr, textLength, hWE);
  920.         if (err <> noErr) then
  921.             goto 1;
  922.         endOffset := offset + textLength;
  923.  
  924.         if (hStyles <> nil) then
  925.             begin
  926.  
  927. { if a style scrap was supplied, apply it to the newly inserted text }
  928.                 err := _WEApplyStyleScrap(offset, endOffset, hStyles, hWE);
  929.                 if (err <> noErr) then
  930.                     goto 1;
  931.             end;
  932.  
  933.         if (hSoup <> nil) then
  934.             begin
  935.  
  936. { if an object soup was supplied, apply it to the newly inserted text }
  937.                 err := _WEApplySoup(offset, hSoup, hWE);
  938.                 if (err <> noErr) then
  939.                     goto 1;
  940.             end;
  941.  
  942. { determine whether an extra space should be added before or after the inserted text }
  943.         intPasteAction := _WEIntelligentPaste(offset, endOffset, hWE);
  944.  
  945. { add the extra space, if necessary }
  946.         if (intPasteAction <> weDontAddSpaces) then
  947.             begin
  948.  
  949.                 space := 32;
  950.                 if (intPasteAction = weAddSpaceOnLeftSide) then
  951.                     err := _WEInsertText(offset, @space, 1, hWE)
  952.                 else
  953.                     err := _WEInsertText(endOffset, @space, 1, hWE);
  954.                 if (err <> noErr) then
  955.                     goto 1;
  956.                 endOffset := endOffset + 1;
  957.  
  958. { adjust undo buffer (if any) for the extra space }
  959.                 _WEAdjustUndoRange(1, hWE);
  960.  
  961.             end;
  962.  
  963. { invalid the null style }
  964.         BCLR(pWE^.flags, weFUseNullStyle);
  965.  
  966. { move the insertion point at the end of the inserted text }
  967.         pWE^.selStart := endOffset;
  968.         pWE^.selEnd := endOffset;
  969.  
  970. { redraw the text }
  971.         err := _WERedraw(offset, endOffset, hWE);
  972.         if (err <> noErr) then
  973.             goto 1;
  974.  
  975. { clear result code }
  976.         err := noErr;
  977.  
  978. 1:
  979. { return result code }
  980.         WEInsert := err;
  981.  
  982. { unlock the WE record }
  983.         IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
  984.  
  985.     end;  { WEInsert }
  986.  
  987.     function WEInsertObject (objectType: OSType;
  988.                                     objectDataHandle: Handle;
  989.                                     objectSize: Point;
  990.                                     hWE: WEHandle): OSErr;
  991.         label
  992.             1;
  993.         var
  994.             pWE: WEPtr;
  995.             hAction: WEActionHandle;
  996.             offset, endOffset: LongInt;
  997.             ts: WETextStyle;
  998.             marker: SignedByte;
  999.             saveWELock: Boolean;
  1000.             err: OSErr;
  1001.     begin
  1002.         _WEBlockClr(@ts, SizeOf(ts));
  1003.  
  1004. { stop any ongoing inline input session }
  1005.         WEStopInlineSession(hWE);
  1006.  
  1007. { lock the WE record }
  1008.         saveWELock := _WESetHandleLock(hWE, true);
  1009.         pWE := hWE^;
  1010.         offset := pWE^.selStart;
  1011.  
  1012. { call the 'new' handler to initialize private object storage (if any) }
  1013. { and to calculate the default size for this object }
  1014.         err := _WENewObject(objectType, objectDataHandle, hWE, WEObjectDescHandle(ts.tsObject));
  1015.         if (err <> noErr) then
  1016.             goto 1;
  1017.  
  1018. { use the specified object size, unless it is (0, 0), in which case keep the default size }
  1019.         if (LongInt(objectSize) <> 0) then
  1020.             WEObjectDescHandle(ts.tsObject)^^.objectSize := objectSize;
  1021.  
  1022. { increment modification count }
  1023.         pWE^.modCount := pWE^.modCount + 1;
  1024.  
  1025. { if undo support is enabled, save current selection range }
  1026.         if (BTST(pWE^.flags, weFUndoSupport)) then
  1027.             begin
  1028.                 WEClearUndo(hWE);
  1029.                 if (WENewAction(offset, pWE^.selEnd, 1, weAKUnspecified, 0, hWE, hAction) = noErr) then
  1030.                     if (WEPushAction(hAction) <> noErr) then
  1031.                         ;
  1032.             end;
  1033.  
  1034. { delete current selection }
  1035.         err := _WEDeleteRange(offset, pWE^.selEnd, hWE);
  1036.         if (err <> noErr) then
  1037.             goto 1;
  1038.  
  1039. { insert a kObjectMarker character at the insertion point }
  1040.         marker := kObjectMarker;
  1041.         err := _WEInsertText(offset, @marker, 1, hWE);
  1042.         if (err <> noErr) then
  1043.             goto 1;
  1044.  
  1045. { move the insertion point after the inserted text }
  1046.         endOffset := offset + 1;
  1047.         pWE^.selStart := endOffset;
  1048.         pWE^.selEnd := endOffset;
  1049.  
  1050. { record a reference to the object descriptor in the style table }
  1051.         err := _WESetStyleRange(offset, endOffset, weDoObject, ts, hWE);
  1052.         ts.tsObject := kNullObject;
  1053.         if (err <> noErr) then
  1054.             goto 1;
  1055.  
  1056. { invalid the null style }
  1057.         BCLR(pWE^.flags, weFUseNullStyle);
  1058.  
  1059. { redraw the text }
  1060.         err := _WERedraw(offset, endOffset, hWE);
  1061.         if (err <> noErr) then
  1062.             goto 1;
  1063.  
  1064. { clear result code }
  1065.         err := noErr;
  1066.  
  1067. 1:
  1068. { return result code }
  1069.         WEInsertObject := err;
  1070.  
  1071. { clean up }
  1072.         _WEForgetHandle(ts.tsObject);
  1073.  
  1074. { unlock the WE record }
  1075.         IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
  1076.  
  1077.     end;  { WEInsertObject }
  1078.  
  1079.     function WEDelete (hWE: WEHandle): OSErr;
  1080.         label
  1081.             1;
  1082.         var
  1083.             pWE: WEPtr;
  1084.             hAction: WEActionHandle;
  1085.             rangeStart, rangeEnd: LongInt;
  1086.             saveWELock: Boolean;
  1087.             err: OSErr;
  1088.     begin
  1089.  
  1090. { stop any ongoing inline input session }
  1091.         WEStopInlineSession(hWE);
  1092.  
  1093. { lock the WE record }
  1094.         saveWELock := _WESetHandleLock(hWE, true);
  1095.         pWE := hWE^;
  1096.  
  1097. { get current selection range }
  1098.         rangeStart := pWE^.selStart;
  1099.         rangeEnd := pWE^.selEnd;
  1100.  
  1101. { do nothing if the selection range is empty }
  1102.         if (rangeStart < rangeEnd) then
  1103.             begin
  1104.  
  1105. { increment modification count }
  1106.                 pWE^.modCount := pWE^.modCount + 1;
  1107.  
  1108. { range extension for intelligent cut-and-paste }
  1109.                 _WEIntelligentCut(rangeStart, rangeEnd, hWE);
  1110.  
  1111. { if undo support is enabled, save the range to be deleted }
  1112.                 if (BTST(pWE^.flags, weFUndoSupport)) then
  1113.                     begin
  1114.                         WEClearUndo(hWE);
  1115.                         if (WENewAction(rangeStart, rangeEnd, 0, weAKClear, 0, hWE, hAction) = noErr) then
  1116.                             if (WEPushAction(hAction) <> noErr) then
  1117.                                 ;
  1118.                     end;
  1119.  
  1120. { delete the selection range }
  1121.                 err := _WEDeleteRange(rangeStart, rangeEnd, hWE);
  1122.                 if (err <> noErr) then
  1123.                     goto 1;
  1124.  
  1125. { reset the selection range }
  1126.                 pWE^.selStart := rangeStart;
  1127.                 pWE^.selEnd := rangeStart;
  1128.  
  1129. { redraw the text }
  1130.                 err := _WERedraw(rangeStart, rangeStart, hWE);
  1131.                 if (err <> noErr) then
  1132.                     goto 1;
  1133.  
  1134.             end;  { if non-empty selection }
  1135.  
  1136. { clear result code }
  1137.         err := noErr;
  1138.  
  1139. 1:
  1140. { return result code }
  1141.         WEDelete := err;
  1142.  
  1143. { unlock the WE record }
  1144.         IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
  1145.  
  1146.     end;  { WEDelete }
  1147.  
  1148.     function WECut (hWE: WEHandle): OSErr;
  1149.         var
  1150.             err: OSErr;
  1151.     begin
  1152.         WECut := noErr;
  1153.  
  1154. { Cut is just Copy + Delete }
  1155.         err := WECopy(hWE);
  1156.         if (err <> noErr) then
  1157.             begin
  1158.                 WECut := err;
  1159.                 Exit(WECut);
  1160.             end;
  1161.  
  1162.         err := WEDelete(hWE);
  1163.         if (err <> noErr) then
  1164.             begin
  1165.                 WECut := err;
  1166.                 Exit(WECut);
  1167.             end;
  1168.  
  1169. { change the action kind of the most recent action, if any }
  1170.         if (hWE^^.hActionStack <> nil) then
  1171.             WEActionHandle(hWE^^.hActionStack)^^.actionKind := weAKCut;
  1172.  
  1173.     end;  { WECut }
  1174.  
  1175.     function WECanPaste: Boolean;
  1176.         var
  1177.             scrapOffset: LongInt;
  1178.             objectType: OSType;
  1179.             index: Integer;
  1180.     begin
  1181.         WECanPaste := true;        { assume success }
  1182.  
  1183. { return TRUE if the desk scrap contains a text flavor }
  1184.         if (GetScrap(nil, kTypeText, scrapOffset) > 0) then
  1185.             Exit(WECanPaste);
  1186.  
  1187. { see if the desk scrap contains a flavor matching one of the registered object types }
  1188.         index := 0;
  1189.         while (_WEGetIndObjectType(index, objectType) = noErr) do
  1190.             begin
  1191.                 if (GetScrap(nil, objectType, scrapOffset) > 0) then
  1192.                     Exit(WECanPaste);
  1193.                 index := index + 1;
  1194.             end;  { while }
  1195.  
  1196.         WECanPaste := false;
  1197.     end;  { WECanPaste }
  1198.  
  1199.     function WEPaste (hWE: WEHandle): OSErr;
  1200.         label
  1201.             1;
  1202.         var
  1203.             hItem: Handle;
  1204.             hStyles: Handle;
  1205.             hSoup: Handle;
  1206.             selStart: LongInt;
  1207.             scrapOffset: LongInt;
  1208.             objectType: OSType;
  1209.             objectSize: Point;
  1210.             index: Integer;
  1211.             err: OSErr;
  1212.     begin
  1213.         hItem := nil;
  1214.         hStyles := nil;
  1215.         hSoup := nil;
  1216.         selStart := hWE^^.selStart;
  1217.  
  1218. { allocate a handle to hold a scrap item }
  1219.         err := _WEAllocate(0, kAllocTemp, hItem);
  1220.         if (err <> noErr) then
  1221.             goto 1;
  1222.  
  1223. { look for a text flavor }
  1224.         if (GetScrap(hItem, kTypeText, scrapOffset) <= 0) then
  1225.             begin
  1226.  
  1227. { no text: look for a flavor matching one of the registered object types }
  1228.                 index := 0;
  1229.                 while (_WEGetIndObjectType(index, objectType) = noErr) do
  1230.                     begin
  1231.                         if (GetScrap(hItem, objectType, scrapOffset) > 0) then
  1232.                             begin
  1233.  
  1234. { found a registered type: create a new object out of the tagged data }
  1235.                                 err := WEInsertObject(objectType, hItem, Point(0), hWE);
  1236.  
  1237. { if successful, set hItem to NIL so clean-up section won't kill the object data }
  1238.                                 if (err = noErr) then
  1239.                                     hItem := nil;
  1240.                                 goto 1;
  1241.                             end;
  1242.  
  1243. { try with next flavor }
  1244.                         index := index + 1;
  1245.                     end;  { while }
  1246.  
  1247. { nothing pasteable: return an error code }
  1248.                 err := noTypeErr;
  1249.                 goto 1;
  1250.             end;
  1251.  
  1252. { allocate a handle to hold the style scrap, if any }
  1253.         err := _WEAllocate(0, kAllocTemp, hStyles);
  1254.         if (err <> noErr) then
  1255.             goto 1;
  1256.  
  1257. { look for a 'styl' item accompanying the text }
  1258.         if (GetScrap(hStyles, kTypeStyles, scrapOffset) <= 0) then
  1259.  
  1260. { forget the handle if nothing was found or an error occurred }
  1261.             _WEForgetHandle(hStyles);
  1262.  
  1263. { allocate a handle to hold the soup, if any }
  1264.         err := _WEAllocate(0, kAllocTemp, hSoup);
  1265.         if (err <> noErr) then
  1266.             goto 1;
  1267.  
  1268. { look for a 'SOUP' item accompanying the text }
  1269.         if (GetScrap(hSoup, kTypeSoup, scrapOffset) <= 0) then
  1270.  
  1271. { forget the handle if nothing was found or an error occurred }
  1272.             _WEForgetHandle(hSoup);
  1273.  
  1274. { lock down the text }
  1275.         HLock(hItem);
  1276.  
  1277. { insert the text }
  1278.         err := WEInsert(hItem^, %_GetHandleSize(hItem), StScrpHandle(hStyles), hSoup, hWE);
  1279.  
  1280. 1:
  1281. { if successful, change the action kind of the most recent action, if any }
  1282.         if (err = noErr) then
  1283.             if (hWE^^.hActionStack <> nil) then
  1284.                 WEActionHandle(hWE^^.hActionStack)^^.actionKind := weAKPaste;
  1285.  
  1286. { clean up }
  1287.         _WEForgetHandle(hItem);
  1288.         _WEForgetHandle(hStyles);
  1289.         _WEForgetHandle(hSoup);
  1290.  
  1291. { return result code }
  1292.         WEPaste := err;
  1293.  
  1294.     end;  { WEPaste }
  1295.  
  1296.     function WESetStyle (mode: Integer;
  1297.                                     var ts: WETextStyle;
  1298.                                     hWE: WEHandle): OSErr;
  1299.         label
  1300.             1;
  1301.         var
  1302.             pWE: WEPtr;
  1303.             hAction: WEActionHandle;
  1304.             fontScript: ScriptCode;
  1305.             saveWELock: Boolean;
  1306.             err: OSErr;
  1307.     begin
  1308.  
  1309. { stop any ongoing inline input session }
  1310.         WEStopInlineSession(hWE);
  1311.  
  1312. { lock the WE record }
  1313.         saveWELock := _WESetHandleLock(hWE, true);
  1314.         pWE := hWE^;
  1315.  
  1316.         if (pWE^.selStart = pWE^.selEnd) then
  1317.             begin
  1318.  
  1319. { NULL SELECTION }
  1320. { first make sure the nullStyle field contains valid information }
  1321.                 _WESynchNullStyle(hWE);
  1322.  
  1323. { apply style changes to the nullStyle record }
  1324.                 _WECopyStyle(ts, pWE^.nullStyle.runStyle, pWE^.nullStyle.runStyle.tsFace, mode);
  1325.  
  1326. { if the font was altered, synchronize the keyboard script }
  1327.                 if BTST(pWE^.flags, weFNonRoman) then
  1328.                     if BTST(mode, kModeFont) then
  1329.                         begin
  1330.                             fontScript := Font2Script(pWE^.nullStyle.runStyle.tsFont);
  1331.                             if (fontScript <> GetEnvirons(smKeyScript)) then
  1332.                                 KeyScript(fontScript);
  1333.                         end;
  1334.  
  1335.             end
  1336.         else
  1337.             begin
  1338.  
  1339. { NON-EMPTY SELECTION }
  1340.  
  1341. { increment modification count }
  1342.                 pWE^.modCount := pWE^.modCount + 1;
  1343.  
  1344. { if undo support is enabled, save the styles of the text range to be affected }
  1345.                 if (BTST(pWE^.flags, weFUndoSupport)) then
  1346.                     begin
  1347.                         WEClearUndo(hWE);
  1348.                         if (WENewAction(pWE^.selStart, pWE^.selEnd, pWE^.selEnd - pWE^.selStart, weAKSetStyle, weAFDontSaveText + weAFDontSaveSoup, hWE, hAction) = noErr) then
  1349.                             if (WEPushAction(hAction) <> noErr) then
  1350.                                 ;
  1351.                     end;
  1352.  
  1353. { set the style of the selection range }
  1354.                 err := _WESetStyleRange(pWE^.selStart, pWE^.selEnd, mode, ts, hWE);
  1355.                 if (err <> noErr) then
  1356.                     goto 1;
  1357.  
  1358. { and redraw the text }
  1359.                 err := _WERedraw(pWE^.selStart, pWE^.selEnd, hWE);
  1360.                 if (err <> noErr) then
  1361.                     goto 1;
  1362.  
  1363.             end;
  1364.  
  1365. { clear the result code }
  1366.         err := noErr;
  1367.  
  1368. 1:
  1369. { unlock the WE record }
  1370.         IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
  1371.  
  1372. { return result code }
  1373.         WESetStyle := err;
  1374.  
  1375.     end;  { WESetStyle }
  1376.  
  1377.     function WEUseStyleScrap (hStyles: StScrpHandle;
  1378.                                     hWE: WEHandle): OSErr;
  1379.         label
  1380.             1;
  1381.         var
  1382.             pWE: WEPtr;
  1383.             saveWELock: Boolean;
  1384.             err: OSErr;
  1385.     begin
  1386.  
  1387. { lock the WE record }
  1388.         saveWELock := _WESetHandleLock(hWE, true);
  1389.         pWE := hWE^;
  1390.  
  1391. { apply the style scrap to the selection range }
  1392.         err := _WEApplyStyleScrap(pWE^.selStart, pWE^.selEnd, hStyles, hWE);
  1393.         if (err <> noErr) then
  1394.             goto 1;
  1395.  
  1396. { redraw the text }
  1397.         err := _WERedraw(pWE^.selStart, pWE^.selEnd, hWE);
  1398.  
  1399. 1:
  1400. { return result code }
  1401.         WEUseStyleScrap := err;
  1402.  
  1403. { unlock the WE record }
  1404.         IgnoreBoolean(_WESetHandleLock(hWE, saveWELock));
  1405.  
  1406.     end;  { WEUseStyleScrap }
  1407.  
  1408. end.