home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 June / MacFormat 25.iso / Shareware City / Developers / ICAppSourceKit1.0 / ICText.p < prev    next >
Encoding:
Text File  |  1994-11-11  |  11.6 KB  |  460 lines  |  [TEXT/PJMM]

  1. unit ICText;
  2.  
  3. interface
  4.  
  5.     function TextCreate (var data: univ ptr; window: DialogPtr; item: integer; font: integer; size: integer; locked: boolean): OSErr;
  6.     procedure TextDestroy (var data: univ ptr);
  7.     procedure TextDraw (data: univ ptr);
  8.     procedure TextActivate (data: univ ptr; activate: boolean);
  9.     procedure TextClick (data: univ ptr; er: eventRecord);
  10.     procedure TextIdle (data: univ ptr);
  11.     procedure TextKey (data: univ ptr; er: EventRecord);
  12.     procedure TextSetSelect (data: univ ptr; selStart, selEnd: integer);
  13.     procedure TextGetSelect (data: univ ptr; var selStart, selEnd: integer);
  14.     procedure TextGetSize (data: univ ptr; var text_size: longint);
  15.     procedure TextInsert (data: univ ptr; h: Handle);
  16.     procedure TextGet (data: univ ptr; h: Handle);
  17.     procedure TextMove (data: univ ptr; r: Rect);
  18.  
  19.     procedure TextCut (data: univ ptr);
  20.     procedure TextCopy (data: univ ptr);
  21.     procedure TextPaste (data: univ ptr);
  22.     procedure TextClear (data: univ ptr);
  23.  
  24.     procedure NopCaretHook; { asm }
  25.  
  26. implementation
  27.  
  28.     uses
  29.         ICDialogs;
  30.  
  31.     type
  32.         ItemData = record
  33.                 window: DialogPtr;
  34.                 item: integer;
  35.                 te: TEHandle;
  36.                 fi: FontInfo;
  37.                 lineheight: integer;
  38.                 active: boolean;
  39.             end;
  40.         ItemDataPtr = ^ItemData;
  41.  
  42.     function TextCreate (var data: univ ptr; window: DialogPtr; item: integer; font: integer; size: integer; locked: boolean): OSErr;
  43.         var
  44.             err: OSErr;
  45.             idp: ItemDataPtr;
  46.             view, dest: rect;
  47.             saved: SavedWindowInfo;
  48.     begin
  49.         data := NewPtr(SizeOf(ItemData));
  50.         err := MemError;
  51.         if err = noErr then begin
  52.             idp := ItemDataPtr(data);
  53.             idp^.window := window;
  54.             idp^.item := item;
  55.             idp^.te := nil;
  56.             idp^.active := true;
  57.             EnterWindow(window, font, size, [], saved);
  58.             with idp^ do begin
  59.                 GetDItemRect(window, item, dest);
  60.                 view := dest;
  61.                 GetFontInfo(fi);
  62.                 lineheight := fi.leading + fi.ascent + fi.descent;
  63.                 dest.bottom := dest.top + (dest.bottom - dest.top) div lineheight * lineheight;
  64.                 te := TENew(dest, view);
  65.                 if locked then begin
  66.                     te^^.caretHook := @NopCaretHook; { Disable the caret }
  67.                 end;
  68.                 TEAutoView(true, te);
  69.             end;
  70.             ExitWindow(saved);
  71.             if err <> nOErr then begin
  72.                 TextDestroy(data);
  73.             end;
  74.         end;
  75.         TextCreate := err;
  76.     end;
  77.  
  78.     procedure TextDestroy (var data: univ ptr);
  79.         var
  80.             idp: ItemDataPtr;
  81.     begin
  82.         idp := ItemDataPtr(data);
  83.         if data <> nil then begin
  84.             if idp^.te <> nil then begin
  85.                 TEDispose(idp^.te);
  86.             end;
  87.             DisposePtr(data);
  88.             data := nil;
  89.         end;
  90.     end;
  91.  
  92.     procedure TextDraw (data: univ ptr);
  93.         var
  94.             idp: ItemDataPtr;
  95.             r: rect;
  96.     begin
  97.         idp := ItemDataPtr(data);
  98.         GetDItemRect(idp^.window, idp^.item, r);
  99.         EraseRect(r);
  100.         TEUpdate(idp^.te^^.viewRect, idp^.te);
  101.     end;
  102.  
  103.     procedure TextActivate (data: univ ptr; activate: boolean);
  104.         var
  105.             idp: ItemDataPtr;
  106.     begin
  107.         idp := ItemDataPtr(data);
  108.         idp^.active := activate;
  109.         if idp^.active then begin
  110.             TEActivate(idp^.te);
  111.         end
  112.         else begin
  113.             TEDeactivate(idp^.te);
  114.         end;
  115.     end;
  116.  
  117.     procedure TextClick (data: univ ptr; er: EventRecord);
  118.         var
  119.             idp: ItemDataPtr;
  120.             control: controlHandle;
  121.             value, part: integer;
  122.     begin
  123.         idp := ItemDataPtr(data);
  124.         with idp^ do begin
  125.             SetPort(window);
  126.             GlobalToLocal(er.where);
  127.             part := FindControl(er.where, window, control);
  128.             if part = 0 then begin
  129.                 if PtInRect(er.where, te^^.viewRect) then begin
  130.                     TEClick(er.where, BAND(er.modifiers, shiftKey) <> 0, te);
  131.                 end;
  132.             end
  133.             else begin
  134.             end;
  135.         end;
  136.     end;
  137.  
  138.     procedure TextIdle (data: univ ptr);
  139.         var
  140.             idp: ItemDataPtr;
  141.     begin
  142.         idp := ItemDataPtr(data);
  143.         TEIdle(idp^.te);
  144.     end;
  145.  
  146.     procedure TextKey (data: univ ptr; er: EventRecord);
  147.         var
  148.             idp: ItemDataPtr;
  149.     begin
  150.         idp := ItemDataPtr(data);
  151.         if BAND(er.modifiers, cmdKey) = 0 then begin
  152.             TEKey(chr(BAND(er.message, $FF)), idp^.te);
  153.         end;
  154. {    Adjust;}
  155.     end;
  156.  
  157.     procedure TextSetSelect (data: univ ptr; selStart, selEnd: integer);
  158.         var
  159.             idp: ItemDataPtr;
  160.     begin
  161.         idp := ItemDataPtr(data);
  162.         TESetSelect(selStart, selEnd, idp^.te);
  163.     end; (* TextSetSelect *)
  164.  
  165.     procedure TextGetSelect (data: univ ptr; var selStart, selEnd: integer);
  166.         var
  167.             idp: ItemDataPtr;
  168.     begin
  169.         idp := ItemDataPtr(data);
  170.         selStart := idp^.te^^.selStart;
  171.         selEnd := idp^.te^^.selEnd;
  172.     end;
  173.  
  174.     procedure TextGetSize (data: univ ptr; var text_size: longint);
  175.         var
  176.             idp: ItemDataPtr;
  177.     begin
  178.         idp := ItemDataPtr(data);
  179.         text_size := GetHandleSize(idp^.te^^.hText);
  180.     end;
  181.  
  182.     procedure TextInsert (data: univ ptr; h: Handle);
  183.         var
  184.             idp: ItemDataPtr;
  185.             s: signedByte;
  186.     begin
  187.         idp := ItemDataPtr(data);
  188.         s := HGetState(h);
  189.         HLock(h);
  190.         TEInsert(h^, GetHandleSize(h), idp^.te);
  191.         HSetState(h, s);
  192.     end; (* TextInsert *)
  193.  
  194.     procedure TextGet (data: univ ptr; h: Handle);
  195.         var
  196.             idp: ItemDataPtr;
  197.             source_size: longint;
  198.             source: Handle;
  199.     begin
  200.         idp := ItemDataPtr(data);
  201.         source := Handle(TEGetText(idp^.te));
  202.         source_size := GetHandleSize(source);
  203.         SetHandleSize(h, source_size);
  204.         if MemError = noErr then begin
  205.             BlockMove(source^, h^, source_size);
  206.         end
  207.         else begin
  208.             SetHandleSize(h, 0);
  209.         end; (* if *)
  210.     end; (* TextGet *)
  211.  
  212.     procedure TextMove (data: univ ptr; r: Rect);
  213.         var
  214.             idp: ItemDataPtr;
  215.     begin
  216.         idp := ItemDataPtr(data);
  217.         idp^.te^^.viewRect := r;
  218.         idp^.te^^.destRect := r;
  219.         TECalText(idp^.te);
  220.     end;
  221.  
  222.     procedure TextCut (data: univ ptr);
  223.         var
  224.             idp: ItemDataPtr;
  225.             junk: longint;
  226.     begin
  227.         idp := ItemDataPtr(data);
  228.         TECut(idp^.te);
  229.         junk := ZeroScrap;
  230.         junk := TEToScrap;
  231.     end;
  232.  
  233.     procedure TextCopy (data: univ ptr);
  234.         var
  235.             idp: ItemDataPtr;
  236.             junk: longint;
  237.     begin
  238.         idp := ItemDataPtr(data);
  239.         TECopy(idp^.te);
  240.         junk := ZeroScrap;
  241.         junk := TEToScrap;
  242.     end;
  243.  
  244.     procedure TextPaste (data: univ ptr);
  245.         var
  246.             idp: ItemDataPtr;
  247.     begin
  248.         idp := ItemDataPtr(data);
  249.         if TEFromScrap = noErr then begin
  250.             TEPaste(idp^.te);
  251.         end; (* if *)
  252.     end;
  253.  
  254.     procedure TextClear (data: univ ptr);
  255.         var
  256.             idp: ItemDataPtr;
  257.     begin
  258.         idp := ItemDataPtr(data);
  259.         TEDelete(idp^.te);
  260.     end;
  261.  
  262. end.
  263.  
  264.  
  265. procedure AdjustTE (te: TEHandle; hc, vc: integer);
  266. {Scroll the TERec around to match up to the potentially updated scrollbar}
  267. {values. This is really useful when the window resizes such that the}
  268. {scrollbars become inactive and the TERec had been previously scrolled.}
  269.     var
  270.         value: INTEGER;
  271. begin
  272.     with te^^ do
  273.         TEScroll((viewRect.left - destRect.left) - hc, (viewRect.top - destRect.top) - (vc * lineHeight), te);
  274. end; {AdjustTE}
  275.  
  276. function AdjustHV (isVert: BOOLEAN; control: ControlHandle; te: TEHandle; canRedraw: BOOLEAN): integer;
  277. {Calculate the new control maximum value and current value, whether it is the horizontal or}
  278. {vertical scrollbar. The vertical max is calculated by comparing the number of lines to the}
  279. {vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document}
  280. {width to the width of the viewRect. The current values are set by comparing the offset between}
  281. {the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by}
  282. {calling ShowControl.}
  283.     var
  284.         value, lines, max: INTEGER;
  285.         oldValue, oldMax: INTEGER;
  286.         cliprgn: RgnHandle;
  287.         r: rect;
  288. begin
  289.     oldValue := GetCtlValue(control);
  290.     oldMax := GetCtlMax(control);
  291.     with te^^ do begin
  292.         if isVert then begin
  293.             lines := nLines;
  294.         {since nLines isn’t right if the last character is a return, check for that case}
  295.             if (teLength > 0) & (Ptr(ORD(hText^) + teLength - 1)^ = 13) then
  296.                 lines := lines + 1;
  297.             max := lines - ((viewRect.bottom - viewRect.top) div lineHeight);
  298.         end
  299.         else
  300.             max := destRect.right - destRect.left - (viewRect.right - viewRect.left);
  301.         if max < 0 then
  302.             max := 0;            {check for negative values}
  303.         if isVert then
  304.             value := (viewRect.top - destRect.top) div lineHeight
  305.         else
  306.             value := viewRect.left - destRect.left;
  307.         if value < 0 then
  308.             value := 0
  309.         else if value > max then
  310.             value := max;                    {pin the value to within range}
  311.     end;
  312.     SetPort(te^^.inPort);
  313.     clipRgn := NewRgn;
  314.     GetClip(clipRgn);
  315.     SetRect(r, 0, 0, 0, 0);
  316.     ClipRect(r);
  317.     SetCtlMax(control, max);
  318.     SetClip(clipRgn);
  319.     DisposeRgn(clipRgn);
  320.     SetCtlValue(control, value);
  321.     if canRedraw and ((max <> oldMax) or (value <> oldValue)) then
  322.         ShowControl(control);            {check to see if the control can be re-drawn}
  323.     AdjustHV := value;
  324. end; {AdjustHV}
  325.  
  326. procedure TEStaticObject.Adjust;
  327.     var
  328.         hc, vc: integer;
  329. begin
  330.     vc := AdjustHV(true, vcontrol, te, false);
  331.     hc := AdjustHV(false, hcontrol, te, false);
  332.     AdjustTE(te, hc, vc);
  333. end; {AdjustScrollValues}
  334. { Common algorithm for pinning the value of a control. It returns the actual amount }
  335. { the value of the control changed. }
  336. procedure CommonAction (control: ControlHandle; var amount: integer);
  337.     var
  338.         value, max: integer;
  339. begin
  340.     value := GetCtlValue(control);
  341.     max := GetCtlMax(control);
  342.     amount := value - amount;
  343.     if (amount <= 0) then
  344.         amount := 0
  345.     else if (amount >= max) then
  346.         amount := max;
  347.     SetCtlValue(control, amount);
  348.     amount := value - amount;   { calculate true change }
  349. end; { CommonAction  }
  350.  
  351. var
  352.     actionTE: TEHandle;
  353.  
  354. { Determines how much to change the value of the vertical scrollbar by and how }
  355. { much to scroll the TE record.}
  356. procedure VActionProc (control: ControlHandle; part: integer);
  357.     var
  358.         amount: integer;
  359.         window: WindowPtr;
  360. begin
  361.     if (part <> 0) then begin
  362.         window := control^^.contrlOwner;
  363.         case part of
  364.             inUpButton, inDownButton:        { one line  }
  365.                 amount := 1;
  366.             inPageUp, inPageDown:            { one page  }
  367.                 with actionTE^^, viewRect do
  368.                     amount := (bottom - top) div lineHeight;
  369.         end;
  370.         if ((part = inDownButton) or (part = inPageDown)) then
  371.             amount := -amount;        { reverse direction for a downer  }
  372.         CommonAction(control, amount);
  373.         if (amount <> 0) then
  374.             TEScroll(0, amount * actionTE^^.lineHeight, actionTE);
  375.     end;
  376. end; { VActionProc }
  377.  
  378. { Determines how much to change the value of the horizontal scrollbar by and how }
  379. { much to scroll the TE record. }
  380. procedure HActionProc (control: ControlHandle; part: integer);
  381.     var
  382.         amount: integer;
  383.         window: WindowPtr;
  384. begin
  385.     if (part <> 0) then begin
  386.         window := control^^.contrlOwner;
  387.         case part of
  388.             inUpButton, inDownButton:        { a few pixels }
  389.                 amount := 8;
  390.             inPageUp, inPageDown:            { a page width }
  391.                 with actionTE^^.viewRect do
  392.                     amount := (right - left);
  393.         end;
  394.         if ((part = inDownButton) or (part = inPageDown)) then
  395.             amount := -amount;        { reverse direction }
  396.         CommonAction(control, amount);
  397.         if (amount <> 0) then
  398.             TEScroll(amount, 0, actionTE);
  399.     end;
  400. end; { HActionProc }
  401. if part = inThumb then begin
  402.     value := GetCtlValue(control);
  403.     part := TrackControl(control, er.where, nil);
  404.     if part <> 0 then begin
  405.         value := value - GetCtlValue(control);
  406.         if value <> 0 then
  407.             if control = vcontrol then
  408.                 TEScroll(0, value * te^^.lineHeight, te)
  409.             else
  410.                 TEScroll(value, 0, te);
  411.     end;
  412. end
  413. else begin
  414.     actionTE := te;
  415.     if control = vcontrol then
  416.         value := TrackControl(control, er.where, @VActionProc)
  417.     else
  418.         value := TrackControl(control, er.where, @HActionProc);
  419. end;
  420. function TEStaticObject.EditMenuEnabled: boolean;
  421.     var
  422.         i: integer;
  423. begin
  424.     for i := EMundo to EMselectall do
  425.         if i <> EMundo + 1 then
  426.             SetEditMenuItem(i);
  427.     EditMenuEnabled := (te^^.selStart < te^^.selEnd) or (te^^.teLength > 0);
  428. end;
  429.  
  430. procedure TEStaticObject.SetEditMenuItem (item: integer);
  431. begin
  432.     case item of
  433.         EMundo, EMcut, EMpaste, EMclear:  { Can't undo, cut, copy, paste in a static edit thingy }
  434.             SetIDItemEnable(M_Edit, item, false);
  435.         EMcopy: 
  436.             SetIDItemEnable(M_Edit, item, te^^.selStart < te^^.selEnd);  { Can copy iff there is a selection }
  437.         EMselectall: 
  438.             SetIDItemEnable(M_Edit, item, te^^.teLength > 0);  { Can select all iff there is something to select }
  439.         otherwise
  440.     end;
  441. end;
  442.  
  443. procedure TEStaticObject.DoEditMenu (item: integer);
  444.     var
  445.         oe: OSErr;
  446.         loe: longInt;
  447. begin
  448.     case item of
  449.         EMcopy:  begin
  450.             TECopy(te);
  451.             loe := ZeroScrap;
  452.             oe := TEToScrap;
  453.         end;
  454.         EMselectall:  begin
  455.             SetPort(window);
  456.             TESetSelect(0, maxLongInt, te);
  457.         end;
  458.         otherwise
  459.     end;
  460. end;