home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Pascal / Applications / NIH Image 1.59 / 1.59 Source / Text.p < prev    next >
Encoding:
Text File  |  1995-05-11  |  18.1 KB  |  716 lines  |  [TEXT/PJMM]

  1. unit text;
  2. {This unit contains routines for opening, saving, scrolling and editing text windows.}
  3.  
  4. interface
  5.  
  6.     uses
  7.         Memory, QuickDraw, Packages, Menus, Events, Fonts, Scrap, ToolUtils, Resources, Errors, Palettes, StandardFile, globals, Utilities, Graphics, File2;
  8.  
  9.     procedure UpdateScrollBars;
  10.     procedure UpdateTextWindow (WhichWindow: WindowPtr);
  11.     procedure ActivateTextWindow (WhichWindow: WindowPtr; Activating: boolean);
  12.     procedure DoMouseDownInText (event: EventRecord; WhichWindow: WindowPtr);
  13.     procedure ScrollText;
  14.     procedure GrowTextWindow (NewSize: LongInt);
  15.     function MakeNewTextWindow (name: str255; width, height: integer): boolean;
  16.     function OpenTextFile (name: str255; RefNum: integer): boolean;
  17.     procedure DoKeyDownInText (ch: char);
  18.     procedure ChangeFontOrSize;
  19.     procedure DoTextCopy;
  20.     procedure DoTextPaste;
  21.     procedure DoTextClear;
  22.     procedure SaveText;
  23.     procedure SaveTextAs;
  24.     function SaveTextChanges: integer;
  25.     procedure InsertText (str: str255; EndOfLine: boolean);
  26.     procedure DoFind;
  27.     procedure DecrementTextWindowNums (num: integer);
  28.     procedure SaveTextUsingPath (name:str255);
  29.     procedure SelectAllText;
  30.  
  31.  
  32. implementation
  33.  
  34.  
  35.     type
  36.         CharArrayType = packed array[0..32767] of char;
  37.         CharArrayPtr = ^CharArrayType;
  38.  
  39.  
  40.     procedure UpdateScrollBars;
  41.         var
  42.             vMax, vValue, hMax, hValue: integer;
  43.     begin
  44.         with TextInfo^ do begin
  45.                 hlock(handle(TextTE));
  46.                 with TextTE^^, TextTE^^.viewRect do begin
  47.                         vTextPageSize := (bottom - top) div LineHeight;
  48.                         hTextPageSize := right - left;
  49.                         vMax := nLines - vTextPageSize;
  50.                         hMax := 0;
  51.                         vValue := (top - destRect.top) div LineHeight;
  52.                         hValue := left - destRect.left;
  53.                         if vMax < 0 then
  54.                             vMax := 0;
  55.                         if vValue < 0 then
  56.                             vValue := 0;
  57.                         if hMax < 0 then
  58.                             hMax := 0;
  59.                         if vValue < 0 then
  60.                             vValue := 0;
  61.                         SetControlMaximum(vTextScrollBar, vMax);
  62.                         SetControlValue(vTextScrollBar, vValue);
  63.                         SetControlMaximum(hTextScrollBar, hMax);
  64.                         SetControlValue(hTextScrollBar, hValue);
  65.                     end;
  66.                 hunlock(handle(TextTE));
  67.             end;
  68. {ShowMessage(concat('nListColumns= ', Long2str(nListColumns), crStr, 'hListPageSize= ', long2str(hListPageSize)));}
  69.     end;
  70.  
  71.  
  72.     procedure SetTextInfo;
  73.   {Updates TextInfo so it points to the active text window.}
  74.         var
  75.             kind: integer;
  76.     begin
  77.         kind := CurrentWindow;
  78.     end;
  79.  
  80.  
  81.     procedure UpdateTextWindow (WhichWindow: WindowPtr);
  82.     begin
  83.         TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  84.         if TextInfo <> nil then
  85.             with TextInfo^ do begin
  86.                     SetPort(TextWindowPtr);
  87.                     DrawControls(TextWindowPtr);
  88.                     DrawGrowIcon(TextWindowPtr);
  89.                     EraseRect(TextTE^^.viewRect);
  90.                     TEUpdate(TextTE^^.viewRect, TextTE);
  91.                     UpdateScrollBars;
  92.                 end; {with}
  93.         SetTextInfo;
  94.     end;
  95.  
  96.  
  97.     procedure ActivateTextWindow (WhichWindow: WindowPtr; Activating: boolean);
  98.     begin
  99.         if Activating then
  100.             UpdateTextWindow(WhichWindow);
  101.         TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  102.         if TextInfo <> nil then
  103.             with TextInfo^ do
  104.                 if Activating then begin
  105.                         TEActivate(TextTE);
  106.                         ShowControl(hTextScrollBar);
  107.                         ShowControl(vTextScrollBar);
  108.                         WhatToUndo := NothingToUndo;
  109.                     end
  110.                 else begin
  111.                         TEDeactivate(TextTE);
  112.                         HideControl(hTextScrollBar);
  113.                         HideControl(vTextScrollBar);
  114.                     end;
  115.         SetTextInfo;
  116.     end;
  117.  
  118.  
  119.     procedure SetFontSize;
  120.         var
  121.             fInfo: FontInfo;
  122.     begin
  123.         with TextInfo^ do begin
  124.                 SetPort(TextWindowPtr);
  125.                 TextFont(CurrentFontID);
  126.                 TextSize(CurrentSize);
  127.                 with TextTE^^, fInfo do begin
  128.                         GetFontInfo(fInfo);
  129.                         TxSize := CurrentSize;
  130.                         LineHeight := ascent + descent + leading;
  131.                         FontAscent := ascent;
  132.                     end;
  133.             end;
  134.     end;
  135.  
  136.  
  137.     procedure InitTextEdit;
  138.         var
  139.             dRect, vRect: rect;
  140.     begin
  141.         with TextInfo^ do begin
  142.                 SetPort(TextWindowPtr);
  143.                 SetRect(vrect, 0, 0, TextWidth - ScrollBarWidth, TextHeight - ScrollBarWidth);
  144.                 drect := vrect;
  145.                 InsetRect(drect, 4, 4);
  146.                 TextTE := TENew(drect, vrect);
  147.                 with TextTE^^ do begin
  148.                         TxFont := CurrentFontID;
  149.                         SetFontSize;
  150.                         crOnly := 1; {do word wrap}
  151.                     end;
  152.                 TESetSelect(0, 0, TextTE);
  153.                 UpdateScrollBars;
  154.                 TEAutoView(true, TextTE); {Enable auto-scrolling}
  155.             end;
  156.     end;
  157.  
  158.  
  159.     procedure ScrollText;
  160.         var
  161.             value: integer;
  162.     begin
  163.         with TextInfo^, TextInfo^.TextTE^^ do
  164.             TEScroll(0, (viewRect.top - destRect.top) - (GetControlValue(vTextScrollBar) * LineHeight), TextTE);
  165.     end;
  166.  
  167.  
  168.     procedure ScrollAction (theCtl: ControlHandle; partCode: integer);
  169.         var
  170.             bInc, pInc, delta: integer;
  171.     begin
  172.         if TextInfo <> nil then
  173.             with TextInfo^ do begin
  174.                     if theCtl = vTextScrollBar then begin
  175.                             bInc := 1;
  176.                             pInc := vTextPageSize
  177.                         end
  178.                     else begin
  179.                             bInc := 4;
  180.                             pInc := hTextPageSize
  181.                         end;
  182.                     case partCode of
  183.                         kControlUpButtonPart: 
  184.                             delta := -bInc;
  185.                         kControlDownButtonPart: 
  186.                             delta := bInc;
  187.                         kControlPageUpPart: 
  188.                             delta := -pInc;
  189.                         kControlPageDownPart: 
  190.                             delta := pInc;
  191.                         otherwise
  192.                             exit(ScrollAction);
  193.                     end;
  194.                     SetControlValue(theCtl, GetControlValue(theCtl) + delta);
  195.                     ScrollText;
  196.                 end; {with}
  197.     end;
  198.  
  199.  
  200.     procedure DoMouseDownInText (event: EventRecord; WhichWindow: WindowPtr);
  201.         var
  202.             theCtl: ControlHandle;
  203.             cValue: integer;
  204.             loc: point;
  205.     begin
  206.         TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  207.         if TextInfo = nil then
  208.             exit(DoMouseDownInText);
  209.         SelectWindow(WhichWindow);
  210.         SetPort(WhichWindow);
  211.         loc := event.where;
  212.         GlobalToLocal(loc);
  213.         with TextInfo^ do
  214.             if PtInRect(loc, TextTE^^.viewRect) then begin
  215.                     TEClick(loc, BitTst(@event.modifiers, 6), TextTE);
  216.                     UpdateScrollBars;
  217.                 end
  218.             else
  219.                 case FindControl(loc, WhichWindow, theCtl) of
  220.                     kControlUpButtonPart, kControlDownButtonPart, kControlPageUpPart, kControlPageDownPart: 
  221.                         if TrackControl(theCtl, loc, TextScrollActionProc) <> 0 then
  222.                             ;
  223.                     kControlIndicatorPart: 
  224.                         if TrackControl(theCtl, loc, nil) <> 0 then
  225.                             ScrollText;
  226.                     otherwise
  227.                 end;
  228.     end;
  229.  
  230.  
  231.     procedure GrowTextWindow (NewSize: LongInt);
  232.     begin
  233.         if TextInfo <> nil then
  234.             with TextInfo^ do begin
  235.                     TextWidth := LoWrd(NewSize);
  236.                     TextHeight := HiWrd(NewSize);
  237.                     SetPort(TextWindowPtr);
  238.                     SizeWindow(TextWindowPtr, TextWidth, TextHeight, true);
  239.                     EraseRect(TextWindowPtr^.PortRect);
  240.                     MoveControl(hTextScrollBar, -1, TextHeight - ScrollBarWidth);
  241.                     MoveControl(vTextScrollBar, TextWidth - ScrollBarWidth, -1);
  242.                     SizeControl(hTextScrollBar, TextWidth - 13, ScrollBarWidth + 1);
  243.                     SizeControl(vTextScrollBar, ScrollBarWidth + 1, TextHeight - 13);
  244.                     InvalRect(TextWindowPtr^.PortRect);
  245.                     with TextTE^^ do begin
  246.                             SetRect(viewRect, 0, 0, TextWidth - ScrollBarWidth, TextHeight - ScrollBarWidth);
  247.                             viewRect.bottom := (viewRect.bottom div lineHeight) * lineHeight;
  248.                             destRect := viewRect;
  249.                             InsetRect(destRect, 4, 4);
  250.                         end;
  251.                     TECalText(TextTE);
  252.                     ScrollText;
  253.                 end; {with}
  254.     end;
  255.  
  256.  
  257.     function MakeNewTextWindow (name: str255; width, height: integer): boolean;
  258.         var
  259.             wrect, crect: rect;
  260.     begin
  261.         MakeNewTextWindow := false;
  262.         if nTextWindows >= 10 then begin
  263.                 PutError(concat('NIH Image cannot open more than ', long2str(MaxTextWindows), ' text windows.'));
  264.                 exit(MakeNewTextWindow);
  265.             end;
  266.         TextInfo := TextInfoPtr(NewPtr(SizeOf(TextInfoRec)));
  267.         if TextInfo = nil then
  268.             exit(MakeNewTextWindow);
  269.         with TextInfo^ do begin
  270.                 TextWidth := width;
  271.                 TextHeight := height;
  272.                 TextLeft := PicLeft;
  273.                 TextTop := PicTop;
  274.                 PicLeft := PicLeft + hPicOffset;
  275.                 PicTop := PicTop + vPicOffset;
  276.                 if ((PicLeft + TextWidth) > ScreenWidth) or ((PicTop + TextHeight) > ScreenHeight) then begin
  277.                         PicLeft := PicLeftBase;
  278.                         PicTop := PicTopBase;
  279.                     end;
  280.                 if (TextTop + TextHeight) > ScreenHeight then
  281.                     TextHeight := ScreenHeight - TextTop - 4;
  282.                 SetRect(wrect, TextLeft, TextTop, TextLeft + TextWidth, TextTop + TextHeight);
  283.                 TextWindowPtr := NewWindow(nil, wrect, name, true, 0, pointer(-1), true, 0);
  284.                 if TextWindowPtr = nil then begin
  285.                         DisposePtr(ptr(TextInfo));
  286.                         TextInfo := nil;
  287.                         exit(MakeNewTextWindow);
  288.                     end;
  289.                 WindowPeek(TextWindowPtr)^.WindowKind := TextKind;
  290.                 WindowPeek(TextWindowPtr)^.RefCon := LongInt(TextInfo);
  291.                 SetRect(crect, TextWidth - ScrollBarWidth, -1, TextWidth + 1, TextHeight - 14);
  292.                 vTextScrollBar := NewControl(TextWindowPtr, crect, '', true, 0, 0, TextHeight - 14, ScrollBarProc, 0);
  293.                 SetRect(crect, -1, TextHeight - ScrollBarWidth, TextWidth - 14, TextHeight + 1);
  294.                 hTextScrollBar := NewControl(TextWindowPtr, crect, '', true, 0, 0, TextWidth - 14, ScrollBarProc, 0);
  295.                 InitTextEdit;
  296.                 DrawControls(TextWindowPtr);
  297.                 WhatToUndo := NothingToUndo;
  298.                 TextTitle := name;
  299.                 TextRefNum := 0;
  300.                 Changes := false;
  301.                 TooBig := false;
  302.                 InsertMenuItem(WindowsMenuH, 'Dummy', WindowsMenuItems - 1 + nTextWindows);
  303.                 SetMenuItemText(WindowsMenuH, WindowsMenuItems + nTextWindows, name);
  304.                 nTextWindows := nTextWindows + 1;
  305.                 WindowNum := nTextWindows;
  306.                 TextWindow[nTextWindows] := TextWindowPtr;
  307.                 if TextScrollActionProc=nil
  308.                     {then TextScrollActionProc:=NewControlActionProc(@ScrollAction);} {ppc-bug}
  309.                     then TextScrollActionProc:=NewRoutineDescriptor(@ScrollAction, uppControlActionProcInfo, GetCurrentISA);
  310.                 MakeNewTextWindow := true;
  311.             end; {with}
  312.     end;
  313.  
  314.  
  315.     function OpenTextFile (name: str255; RefNum: integer): boolean;
  316.         var
  317.             err: OSErr;
  318.             f, item: integer;
  319.             TextFileSize: LongInt;
  320.             LargerThan32K: boolean;
  321.     begin
  322.         OpenTextFile := false;
  323.         if FreeMem < MinFree then begin
  324.                 PutError('Not enough memory to open this text file.');
  325.                 exit(OpenTextFile);
  326.             end;
  327.         LargerThan32K := false;
  328.         err := FSOpen(name, RefNum, f);
  329.         err := GetEof(f, TextFileSize);
  330.         if TextFileSize > MaxTextBufSize then begin
  331.                 item := PutMessageWithCancel('This text file is larger than 32K. Would you like to to open the first 32K?');
  332.                 if item = cancel then begin
  333.                         err := fsclose(f);
  334.                         exit(OpenTextFile);
  335.                     end
  336.                 else begin
  337.                         TextFileSize := 30000;
  338.                         LargerThan32K := true;
  339.                     end;
  340.             end;
  341.         if not MakeNewTextWindow(name, 500, 400) then begin
  342.                 err := fsclose(f);
  343.                 exit(OpenTextFile);
  344.             end;
  345.         with TextInfo^ do begin
  346.                 SetHandleSize(TextTE^^.hText, TextFileSize);
  347.                 if MemError <> noErr then begin
  348.                         err := fsclose(f);
  349.                         PutError('Out of memory.');
  350.                         DisposePtr(ptr(TextInfo));
  351.                         TextInfo := nil;
  352.                         exit(OpenTextFile);
  353.                     end;
  354.                 err := SetFPos(f, fsFromStart, 0);
  355.                 ShowWatch;
  356.                 TextTE^^.teLength := TextFileSize;
  357.                 err := fsRead(f, TextFileSize, TextTE^^.hText^);
  358.                 if err <> noErr then begin
  359.                         TextTE^^.teLength := 0;
  360.                         SetHandleSize(TextTE^^.hText, 0);
  361.                         err := fsclose(f);
  362.                         exit(OpenTextFile);
  363.                     end;
  364.                 TECalText(TextTE);
  365.                 TextTitle := name;
  366.                 TextRefNum := RefNum;
  367.                 TooBig := LargerThan32K;
  368.             end; {with}
  369.         err := fsclose(f);
  370.         OpenTextFile := true;
  371.     end;
  372.  
  373.  
  374.     procedure DoKeyDownInText (ch: char);
  375.     begin
  376.         if TextInfo <> nil then begin
  377.                 TEKey(ch, TextInfo^.TextTE);
  378.                 TextInfo^.Changes := true;
  379.                 UpdateScrollBars;
  380. {with TextInfo^ do ShowMessage(concat(long2str(TextTE^^.teLength), '  ', long2str(GetHandleSize(TextTE^^.hText))));}
  381.                 WhatToUndo := NothingToUndo;
  382.             end;
  383.     end;
  384.  
  385.  
  386.     procedure ChangeFontOrSize;
  387.     begin
  388.         if TextInfo <> nil then
  389.             with TextInfo^ do begin
  390.                     TextTE^^.TxFont := CurrentFontID;
  391.                     SetFontSize;
  392.                     SetPort(TextWindowPtr);
  393.                     EraseRect(TextTE^^.viewRect);
  394.                     TEUpdate(TextTE^^.viewRect, TextTE);
  395.                     UpdateScrollBars;
  396.                 end; {with}
  397.     end;
  398.  
  399.  
  400.     procedure DoTextCopy;
  401.         var
  402.             err: OSErr;
  403.     begin
  404.         if TextInfo <> nil then begin
  405.                 TECopy(TextInfo^.TextTE);
  406.                 err := ZeroScrap;
  407.                 if err = NoErr then begin
  408.                         err := TEToScrap;
  409.                         WhatsOnClip := NothingOnClip; {It is on System Scrap}
  410.                     end;
  411.             end;
  412.     end;
  413.  
  414.  
  415.     procedure DoTextPaste;
  416.         var
  417.             err: OSErr;
  418.     begin
  419.         if TextInfo <> nil then begin
  420.                 err := TEFromScrap;
  421.                 if err = NoErr then
  422.                     TEPaste(TextInfo^.TextTE);
  423.                 TextInfo^.Changes := true;
  424.                 UpdateScrollBars;
  425.                 WhatToUndo := NothingToUndo;
  426.             end;
  427.     end;
  428.  
  429.  
  430.     procedure DoTextClear;
  431.         var
  432.             err: OSErr;
  433.     begin
  434.         if TextInfo <> nil then begin
  435.                 TEDelete(TextInfo^.TextTE);
  436.                 TextInfo^.Changes := true;
  437.             end;
  438.         UpdateScrollBars;
  439.         WhatToUndo := NothingToUndo;
  440.     end;
  441.  
  442.  
  443.     procedure DoSaveText;
  444.         var
  445.             err, f: integer;
  446.             TheInfo: FInfo;
  447.             ByteCount: LongInt;
  448.     begin
  449.         if TextInfo <> nil then
  450.             with TextInfo^ do begin
  451.                     hlock(handle(TextTE));
  452.                     with TextTE^^ do begin
  453.                             ByteCount := TELength;
  454.                             if ByteCount = 0 then
  455.                                 exit(DoSaveText);
  456.                             err := GetFInfo(TextTitle, TextRefNum, TheInfo);
  457.                             case err of
  458.                                 NoErr: 
  459.                                     if TheInfo.fdType <> 'TEXT' then begin
  460.                                             TypeMismatch(TextTitle);
  461.                                             exit(DoSaveText)
  462.                                         end;
  463.                                 FNFerr:  begin
  464.                                         err := create(TextTitle, TextRefNum, 'Imag', 'TEXT');
  465.                                         if CheckIO(err) <> 0 then
  466.                                             exit(DoSaveText);
  467.                                     end;
  468.                                 otherwise
  469.                                     if CheckIO(err) <> 0 then
  470.                                         exit(DoSaveText)
  471.                             end;
  472.                             ShowWatch;
  473.                             err := fsopen(TextTitle, TextRefNum, f);
  474.                             if CheckIO(err) <> 0 then
  475.                                 exit(DoSaveText);
  476.                             err := fswrite(f, ByteCount, hText^);
  477.                             if CheckIO(err) <> 0 then
  478.                                 exit(DoSaveText);
  479.                             err := SetEof(f, ByteCount);
  480.                             err := fsclose(f);
  481.                             err := FlushVol(nil, TextRefNum);
  482.                             Changes := false;
  483.                         end; {with}
  484.                     hunlock(handle(TextTE));
  485.                 end; {with}
  486.     end;
  487.  
  488.  
  489.     procedure SaveTextAs;
  490.         var
  491.             where: Point;
  492.             reply: SFReply;
  493.     begin
  494.         if TextInfo <> nil then begin
  495.                 where.v := 60;
  496.                 where.h := 100;
  497.                 SFPutFile(where, 'Save Text as?', TextInfo^.TextTitle, nil, reply);
  498.                 if reply.good then
  499.                     with reply, TextInfo^ do begin
  500.                             TextTitle := fname;
  501.                             TextRefNum := vRefNum;
  502.                             DoSaveText;
  503.                             SetWTitle(TextWindowPtr, TextTitle);
  504.                             SetMenuItemText(WindowsMenuH, WindowsMenuItems - 1 + WindowNum, TextTitle);
  505.                         end;
  506.             end;
  507.     end;
  508.  
  509.  
  510.     procedure SaveTextUsingPath(name:str255);
  511.     var
  512.         SaveTitle:str255;
  513.     begin
  514.         if TextInfo <> nil then with TextInfo^ do begin
  515.             SaveTitle:=TextTitle;
  516.             TextTitle := name;
  517.             TextRefNum := 0;
  518.             DoSaveText;
  519.             TextTitle:=SaveTitle;
  520.         end;
  521.     end;
  522.     
  523.     
  524.     procedure SaveText;
  525.     begin
  526.         if TextInfo <> nil then begin
  527.                 with TextInfo^ do
  528.                     if (TextRefNum = 0) or TooBig then
  529.                         SaveTextAs
  530.                     else
  531.                         DoSaveText;
  532.             end;
  533.     end;
  534.  
  535.  
  536.     function SaveTextChanges: integer;
  537.         const
  538.             yesID = 1;
  539.             NoID = 2;
  540.             CancelID = 3;
  541.         var
  542.             id: integer;
  543.             reply: SFReply;
  544.     begin
  545.         id := 0;
  546.         with TextInfo^ do
  547.             if changes and not TooBig then begin
  548.                     if macro and (MacroCommand = DisposeC) then begin
  549.                             SaveTextChanges := ok;
  550.                             exit(SaveTextChanges);
  551.                         end;
  552.                     ParamText(TextTitle, '', '', '');
  553.                     InitCursor;
  554.                     id := alert(600, nil);
  555.                     if id = yesID then
  556.                         SaveText;
  557.                 end; {if changes}
  558.         if id = cancelID then
  559.             SaveTextChanges := cancel
  560.         else
  561.             SaveTextChanges := ok;
  562.     end;
  563.  
  564.  
  565. procedure InsertText (str: str255; EndOfLine: boolean);
  566.   var
  567.    text: Ptr;
  568.    len: LongInt;
  569.  begin
  570.   if TextInfo <> nil then
  571.    with TextInfo^ do
  572.     begin
  573.      if EndOfLine then
  574.      str := concat(str, cr);
  575.      len := length(str);
  576.      if (TextTE^^.TELength + len) > 32767 then begin
  577.        AbortMacro;
  578.        exit(InsertText);
  579.      end;
  580.      if len > 0 then
  581.       begin
  582.        TEDelete(TextTE);
  583.        text := Ptr(Ord4(@str) + 1);
  584.        TEInsert(text, len, TextTE);
  585.        Changes := true;
  586.        UpdateScrollBars;
  587.        WhatToUndo := NothingToUndo;
  588.       end;
  589.     end;
  590.  end;
  591.  
  592.  
  593.  
  594.     procedure GoToLine (str: str255; data: CharArrayPtr);
  595.         var
  596.             pos, line: integer;
  597.             found: boolean;
  598.             n: LongInt;
  599.     begin
  600.         with TextInfo^.TextTE^^ do begin
  601.                 found := false;
  602.                 delete(str, 1, 1);
  603.                 StringToNum(str, n);
  604.                 pos := 0;
  605.                 line := 1;
  606.                 if n = 1 then
  607.                     found := true
  608.                 else
  609.                     repeat
  610.                         if data^[pos] = cr then
  611.                             line := line + 1;
  612.                         pos := pos + 1;
  613.                         if line = n then begin
  614.                                 found := true;
  615.                                 leave;
  616.                             end;
  617.                     until (pos >= teLength);
  618.                 if found then begin
  619.                         TESetSelect(pos, pos, TextInfo^.TextTE);
  620.                         TEKey('x', TextInfo^.TextTE);
  621.                         TEKey(BackSpace, TextInfo^.TextTE);
  622.                         UpdateScrollBars;
  623.                     end
  624.                 else
  625.                     beep;
  626.             end;
  627.     end;
  628.  
  629.  
  630.     procedure DoFind;
  631.         const
  632.             StringID = 3;
  633.         var
  634.             mylog: DialogPtr;
  635.             item: integer;
  636.             i, firstpos, lastpos, pos: integer;
  637.             slength: integer;
  638.             match: boolean;
  639.             data: CharArrayPtr;
  640.             c: char;
  641.             str: str255;
  642.     begin
  643.         if TextInfo = nil then
  644.             exit(DoFind);
  645.         hlock(handle(TextInfo^.TextTE));
  646.         with TextInfo^.TextTE^^ do begin
  647.                 if not OptionKeyWasDown then begin
  648.                         InitCursor;
  649.                         ParamText('What would you like to find?', '', '', '');
  650.                         mylog := GetNewDialog(170, nil, pointer(-1));
  651.                         SetDString(MyLog, StringID, SearchString);
  652.                         SelectdialogItemText(MyLog, StringID, 0, 32767);
  653.                         OutlineButton(MyLog, ok, 16);
  654.                         repeat
  655.                             ModalDialog(nil, item);
  656.                         until (item = ok) or (item = cancel);
  657.                         if item = cancel then begin
  658.                                 DisposeDialog(mylog);
  659.                                 exit(DoFind)
  660.                             end;
  661.                         SearchString := GetDString(MyLog, StringID);
  662.                         DisposeDialog(mylog);
  663.                     end;
  664.                 slength := Length(SearchString);
  665.                 if slength = 0 then
  666.                     exit(DoFind);
  667.                 str := SearchString;
  668.                 MakeLowerCase(str);
  669.                 data := CharArrayPtr(htext^);
  670.                 if (slength > 1) and (str[1] = '#') and (str[2] >= '0') and (str[2] <= '9') then begin
  671.                         GoToLine(str, data);
  672.                         hunlock(handle(TextInfo^.TextTE));
  673.                         exit(DoFind);
  674.                     end;
  675.                 match := false;
  676.                 lastpos := teLength - slength - 1;
  677.                 match := false;
  678.                 for firstpos := selEnd to lastpos do begin
  679.                         match := true;
  680.                         for i := 1 to slength do begin
  681.                                 c := data^[firstpos + i - 1];
  682.                                 if (c >= 'A') and (c <= 'Z') then
  683.                                     c := chr(ord(c) + 32);
  684.                                 if c <> str[i] then begin
  685.                                         match := false;
  686.                                         leave
  687.                                     end;
  688.                             end;
  689.                         if match then begin
  690.                                 pos := firstpos;
  691.                                 leave;
  692.                             end;
  693.                     end;
  694.                 if match then begin
  695.                         TESetSelect(pos, pos, TextInfo^.TextTE);
  696.                         TEKey('x', TextInfo^.TextTE);
  697.                         TEKey(BackSpace, TextInfo^.TextTE);
  698.                         TESetSelect(pos, pos + slength, TextInfo^.TextTE);
  699.                         UpdateScrollBars;
  700.                     end
  701.                 else
  702.                     beep;
  703.             end; {with}
  704.         hunlock(handle(TextInfo^.TextTE));
  705.     end;
  706.     
  707.     
  708.     procedure SelectAllText;
  709.     begin
  710.         if TextInfo<>nil then
  711.             TESetSelect(0, TextInfo^.TextTE^^.TELength, TextInfo^.TextTE)
  712.     end;
  713.  
  714.  
  715.  
  716. end.