home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Tools - Objects / MacApp / MacApp CD Release / MacApp 2.0.1 (Many Libraries) / Libraries / UTranscriptView.inc1.p < prev    next >
Encoding:
Text File  |  1990-10-25  |  19.9 KB  |  798 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { UTranscriptView.inc1.p }
  4. { copyright © 1985-1990 by Apple Computer, Inc.  All rights reserved. }
  5.  
  6. {$IFC NOT qDebugTheDebugger}
  7. {$W+}
  8. {$R-}
  9. {$Init-}
  10. {$OV-}
  11. {$ENDC}
  12. {$IFC qNames}
  13. {$D+}
  14. {$ENDC}
  15.  
  16. {--------------------------------------------------------------------------------------------------}
  17. {$S WWSeg}
  18.  
  19. PROCEDURE IDUTranscriptView;                            { Writeln UTranscriptView's compile time. }
  20. { Writeln UTranscriptView's compile time. }
  21.  
  22.     BEGIN
  23.     WriteLn('UTranscriptView of ', COMPDATE, ' @ ', COMPTIME);
  24.     END;
  25.  
  26. {--------------------------------------------------------------------------------------------------}
  27. {$S WWSeg}
  28.  
  29. FUNCTION TTranscriptView.RowToIndex(row: INTEGER): INTEGER;
  30. { Returns the row as an index for fLineLengths and fLineStarts }
  31.  
  32.     BEGIN
  33.     IF fFirstLineIndex + row < fRows THEN
  34.         RowToIndex := fFirstLineIndex + row
  35.     ELSE
  36.         RowToIndex := fFirstLineIndex + row - fRows;
  37.     END;
  38.  
  39. {--------------------------------------------------------------------------------------------------}
  40. {$S WWSeg}
  41.  
  42. FUNCTION TTranscriptView.IndexToRow(index: INTEGER): INTEGER;
  43. { Returns the index as a row }
  44.  
  45.     BEGIN
  46.     IF index - fFirstLineIndex >= 0 THEN
  47.         IndexToRow := index - fFirstLineIndex
  48.     ELSE
  49.         IndexToRow := index - fFirstLineIndex + fRows;
  50.     END;
  51.  
  52. {--------------------------------------------------------------------------------------------------}
  53. {$S WWSeg}
  54.  
  55. FUNCTION TTranscriptView.IndexToLocal(index: INTEGER): INTEGER;
  56. { returns the v-coordinate of the given row }
  57.  
  58.     BEGIN
  59.     IndexToLocal := kVMargin + (IndexToRow(index) + 1) * fFontHeight - fFontInfo.leading -
  60.                     fFontInfo.descent;
  61.     END;
  62.  
  63. {--------------------------------------------------------------------------------------------------}
  64. {$S WWSeg}
  65.  
  66. FUNCTION TTranscriptView.LocalToIndex(local: INTEGER): INTEGER;
  67. { returns the line that contains the v coordinate }
  68.  
  69.     BEGIN
  70.     LocalToIndex := RowToIndex(((local - kVMargin - fFontInfo.leading - fFontInfo.descent) + 1) DIV
  71.                                fFontHeight);
  72.     END;
  73.  
  74. {--------------------------------------------------------------------------------------------------}
  75. {$S WWSeg}
  76.  
  77. PROCEDURE TTranscriptView.InstallTextStyle(theStyle: TextStyle);
  78.  
  79.     VAR
  80.         savePort:            GrafPtr;
  81.         aFontInfo:            FontInfo;
  82.  
  83.     BEGIN
  84.     GetTextStyleFontInfo(theStyle, aFontInfo);
  85.     fTextStyle := theStyle;
  86.     fFontInfo := aFontInfo;
  87.  
  88.     WITH aFontInfo DO
  89.         fFontHeight := Ascent + descent + leading;
  90.  
  91.     Resize((2 * kHMargin) + (fCols * fFontInfo.widMax), (2 * kVMargin) + (fFontHeight *
  92.            (fInsertionPt.v + 1)), kInvalidate);
  93.     END;
  94.  
  95. {--------------------------------------------------------------------------------------------------}
  96. {$S WWSeg}
  97.  
  98. FUNCTION TTranscriptView.IndexColToLocal(index, col: INTEGER): Point;
  99.  
  100.     BEGIN
  101.     IndexColToLocal.v := IndexToLocal(index);
  102.     HLock(Handle(fText));
  103.     IndexColToLocal.h := kHMargin + TextWidth(QDPtr(fText^), fLineStarts^^[index], col);
  104.     HUnLock(Handle(fText));
  105.     END;
  106.  
  107. {--------------------------------------------------------------------------------------------------}
  108. {$S WWSeg}
  109.  
  110. FUNCTION TTranscriptView.LocalToCol(local: INTEGER): INTEGER;
  111. { returns the line that contains the v coordinate }
  112.  
  113.     BEGIN
  114.     {??? LocalToCol := ((local - kVMargin) + 1) DIV fFontHeight;}
  115.     END;
  116.  
  117. {--------------------------------------------------------------------------------------------------}
  118. {$S WWSeg}
  119.  
  120. FUNCTION TTranscriptView.PrevIndex(ln: INTEGER): INTEGER;
  121. { returns the line previous to the line; wrapped circularly }
  122.  
  123.     BEGIN
  124.     IF ln - 1 < 0 THEN
  125.         PrevIndex := fRows - 1
  126.     ELSE
  127.         PrevIndex := ln - 1;
  128.     END;
  129.  
  130. {--------------------------------------------------------------------------------------------------}
  131. {$S WWSeg}
  132.  
  133. FUNCTION TTranscriptView.SuccIndex(ln: INTEGER): INTEGER;
  134. { returns the line succeeding the line; wrapped circularly }
  135.  
  136.     BEGIN
  137.     IF ln + 1 >= fRows THEN
  138.         SuccIndex := 0
  139.     ELSE
  140.         SuccIndex := ln + 1;
  141.     END;
  142.  
  143. {--------------------------------------------------------------------------------------------------}
  144. {$S WWSeg}
  145.  
  146. FUNCTION TTranscriptView.GetInsertionPointRect: Rect;
  147.  
  148.     VAR
  149.         pt:                 Point;
  150.         insertionPtIndex:    INTEGER;
  151.  
  152.     BEGIN
  153.     WITH pt DO
  154.         BEGIN
  155.         insertionPtIndex := RowToIndex(fInsertionPt.v);
  156.         pt := IndexColToLocal(insertionPtIndex, fLineLengths^^[insertionPtIndex]);
  157.         SetRect(GetInsertionPointRect, h, v - fFontInfo.Ascent, h + 1, v + fFontInfo.descent);
  158.         END;
  159.     END;
  160.  
  161. {--------------------------------------------------------------------------------------------------}
  162. {$S WWInit}
  163.  
  164. PROCEDURE TTranscriptView.CommonInit(itsSuperView: TView;
  165.                                      outputFont, outputSize: INTEGER;
  166.                                      numLines, numCharsPerLine: INTEGER);
  167.  
  168.     VAR
  169.         aFontInfo:            FontInfo;
  170.         control:            ControlHandle;
  171.         i:                    INTEGER;
  172.         aLine:                StringHandle;
  173.         vhs:                VHSelect;
  174.         VPt:                VPoint;
  175.         zoomedOutSize:        Point;
  176.  
  177.     BEGIN
  178.     fHelpProc := NIL;
  179.     fText := NIL;
  180.     fLineLengths := NIL;
  181.     fLineStarts := NIL;
  182.  
  183.     fGotRefnum := FALSE;
  184.     fWrToWindow := TRUE;
  185.     fWrToFile := TRUE;
  186.     fUpdateRgn := NIL;
  187.  
  188.     fForcePtr := 0;
  189.  
  190.     fRows := numLines;                                    { # lines in window }
  191.     fCols := numCharsPerLine;                            { chars / line }
  192.     fTotal := fRows * fCols;                            { total chars in window }
  193.  
  194.     fText := TextHandle(NewPermHandle(fTotal));
  195.     FailNil(fText);
  196.  
  197.     fLineLengths := LineLensHandle(NewPermHandle(fRows * SIZEOF(INTEGER)));
  198.     FailNil(fLineLengths);
  199.  
  200.     fLineStarts := LineLensHandle(NewPermHandle(fRows * SIZEOF(INTEGER)));
  201.     FailNil(fLineStarts);
  202.  
  203.     fUpdateRgn := MakeNewRgn;
  204.  
  205.     FOR i := 0 TO fRows - 1 DO
  206.         fLineLengths^^[i] := 0;
  207.  
  208.     FOR i := 0 TO fRows - 1 DO
  209.         fLineStarts^^[i] := 0;
  210.  
  211.     fFirstLineIndex := 0;
  212.  
  213.     fLastInsertionPointTime := 0;
  214.     fInsertionPointOn := FALSE;
  215.     fInsertionPt.v := 0;
  216.     fInsertionPt.h := 0;
  217.     fLastCh := chr(0);
  218.  
  219.     {$Push} {$H-}
  220.     SetTextStyle(fTextStyle, outputFont, [], outputSize, gRGBBlack);
  221.     GetTextStyleFontInfo(fTextStyle, aFontInfo);
  222.     {$Pop}
  223.  
  224.     WITH aFontInfo DO
  225.         fFontHeight := Ascent + descent + leading;
  226.  
  227.     END;
  228.  
  229. {--------------------------------------------------------------------------------------------------}
  230. {$S WWInit}
  231.  
  232. PROCEDURE TTranscriptView.ITranscriptView(itsSuperView: TView;
  233.                                           outputFont, outputSize: INTEGER;
  234.                                           numLines, numCharsPerLine: INTEGER);
  235.  
  236.     VAR
  237.         VPt:                VPoint;
  238.  
  239.     BEGIN
  240.     IView(NIL, itsSuperView, gZeroVPt, gZeroVPt, sizeFixed, sizeFixed);
  241.     CommonInit(itsSuperView, outputFont, outputSize, numLines, numCharsPerLine);
  242.  
  243.     Resize((2 * kHMargin) + (fCols * fFontInfo.widMax), 2 * kVMargin, kDontInvalidate);
  244.     END;
  245.  
  246. {--------------------------------------------------------------------------------------------------}
  247. {$S WWInit}
  248.  
  249. PROCEDURE TTranscriptView.IRes(itsDocument: TDocument;
  250.                                itsSuperView: TView;
  251.                                VAR itsParams: Ptr);
  252.  
  253.     VAR
  254.         vhs:                VHSelect;
  255.  
  256.     BEGIN
  257.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  258.  
  259.     CommonInit(itsSuperView, 1, 9, 120, 100);
  260.  
  261.     Resize((2 * kHMargin) + (fCols * fFontInfo.widMax), 2 * kVMargin, kDontInvalidate);
  262.     END;
  263.  
  264. {--------------------------------------------------------------------------------------------------}
  265.  
  266. PROCEDURE CallHelpProc(actionProc: ProcPtr);
  267.     INLINE $205F, $4E90;
  268. {  MOVE.L  (A7)+,A0
  269. JSR (A0)
  270. }
  271.  
  272. {--------------------------------------------------------------------------------------------------}
  273. {$S MAHelp}
  274.  
  275. FUNCTION TTranscriptView.DoHelp(VAR info: EventInfo;
  276.                                 VAR message: UNIV LONGINT): TCommand;
  277.  
  278.     BEGIN
  279.     DoHelp := NIL;
  280.     IF fHelpProc <> NIL THEN
  281.         CallHelpProc(fHelpProc);
  282.     END;
  283.  
  284. {--------------------------------------------------------------------------------------------------}
  285. {$S WWSeg}
  286.  
  287. PROCEDURE TTranscriptView.RevealInsertionPoint;
  288.  
  289.     VAR
  290.         r:                    Rect;
  291.         vr:                 VRect;
  292.         p:                    Point;
  293.  
  294.     BEGIN
  295.     IF Focus THEN
  296.         BEGIN
  297.         {$Push} {$H-}
  298.         SetPortTextStyle(fTextStyle);
  299.         {$Pop}
  300.  
  301.         r := GetInsertionPointRect;
  302.         RectToVRect(r, vr);
  303.         SetPt(p, fFontInfo.widMax, fFontHeight + kVMargin);
  304.         RevealRect(vr, p, kRedraw);
  305.         END;
  306.     END;
  307.  
  308. {--------------------------------------------------------------------------------------------------}
  309. {$S WWSeg}
  310.  
  311. PROCEDURE TTranscriptView.RevealInsertionPointLine;
  312.  
  313.     VAR
  314.         r:                    Rect;
  315.         vr:                 VRect;
  316.         p:                    Point;
  317.  
  318.     BEGIN
  319.     r := GetInsertionPointRect;
  320.     RectToVRect(r, vr);
  321.     vr.left := flocation.h;
  322.     SetPt(p, 0, fFontHeight + kVMargin);
  323.     RevealRect(vr, p, kRedraw);
  324.     END;
  325.  
  326. {--------------------------------------------------------------------------------------------------}
  327. {$S WWSeg}
  328.  
  329. PROCEDURE TTranscriptView.AddTextToFile(textBuf: Ptr;
  330.                                         byteCount: INTEGER);
  331.  
  332.     VAR
  333.         count:                LONGINT;
  334.  
  335.     BEGIN
  336.     IF fGotRefnum THEN
  337.         BEGIN
  338.         count := byteCount;
  339.         IF FSWrite(fRefnum, count, textBuf) <> noErr THEN
  340.             BEGIN
  341.             { ??? do something here ??? }
  342.             END;
  343.         END;
  344.     END;
  345.  
  346. {--------------------------------------------------------------------------------------------------}
  347. {$S WWSeg}
  348.  
  349. PROCEDURE TTranscriptView.AddText(textBuf: Ptr;
  350.                                   byteCount: INTEGER);
  351.  
  352.     VAR
  353.         ch:                 Char;
  354.         count:                LONGINT;
  355.         gotBS:                BOOLEAN;
  356.         gotEOL:             BOOLEAN;
  357.         pt:                 Point;
  358.         r, r2:                Rect;
  359.         startCount:         INTEGER;
  360.         startPtr:            Ptr;
  361.         vr:                 VRect;
  362.         newOffset:            INTEGER;
  363.         tempIndex:            INTEGER;
  364.         startLength:        INTEGER;
  365.         aScroller:            TScroller;
  366.         insertionPtIndex:    INTEGER;
  367.         doInfiniteScroll:    BOOLEAN;
  368.  
  369.     BEGIN
  370.     IF fWrToFile THEN
  371.         AddTextToFile(textBuf, byteCount);
  372.  
  373.     IF fWrToWindow THEN
  374.     { draw as many lines as we got }
  375.         WHILE byteCount > 0 DO
  376.             BEGIN
  377.             gotEOL := FALSE;
  378.             gotBS := FALSE;
  379.             startPtr := textBuf;
  380.             startCount := byteCount;
  381.             insertionPtIndex := RowToIndex(fInsertionPt.v);
  382.             startLength := fLineLengths^^[insertionPtIndex];
  383.  
  384.             { Scan for a chunk to save }
  385.             WHILE (byteCount > 0) & (fLineLengths^^[insertionPtIndex] < fCols) & (NOT gotEOL) &
  386.                   (NOT gotBS) DO
  387.                 BEGIN
  388.                 {$push} {$R-}
  389.                 ch := chr(QDPtr(textBuf)^);
  390.                 {$pop}
  391.                 textBuf := Ptr(ORD(textBuf) + 1);
  392.                 byteCount := byteCount - 1;
  393.  
  394.                 CASE ch OF
  395.                     kWWEol:
  396.                         gotEOL := TRUE;
  397.                     chBackspace:
  398.                         gotBS := TRUE;
  399.                     OTHERWISE
  400.                         BEGIN
  401.                         tempIndex := fLineStarts^^[insertionPtIndex] + fLineLengths^^[
  402.                                      insertionPtIndex];
  403.                         fText^^[tempIndex] := ch;
  404.                         fLineLengths^^[insertionPtIndex] := fLineLengths^^[insertionPtIndex] + 1;
  405.                         END;
  406.                 END;
  407.                 END;
  408.  
  409.             { Draw the chunk if possible }
  410.             IF Focus THEN
  411.                 BEGIN
  412.                 {$Push} {$H-}
  413.                 SetPortTextStyle(fTextStyle);
  414.                 {$Pop}
  415.                 IF NOT gotBS THEN
  416.                     BEGIN
  417.                     WITH pt, r DO
  418.                         BEGIN
  419.                         pt := IndexColToLocal(insertionPtIndex, startLength);
  420.                         MoveTo(h, v);
  421.                         DrawText(QDPtr(startPtr), 0, startCount - byteCount - ORD(gotEOL));
  422.                         END;
  423.                     END
  424.                 ELSE
  425.                     BEGIN
  426.                     IF fLineLengths^^[insertionPtIndex] > 0 THEN { don't backspace past beginning of
  427.                                                                   line! }
  428.                         BEGIN
  429.                         r2 := GetInsertionPointRect;
  430.                         fLineLengths^^[insertionPtIndex] := fLineLengths^^[insertionPtIndex] - 1;
  431.                         r := GetInsertionPointRect;
  432.                         r.right := r2.right;
  433.                         InvalidRect(r);
  434.                         END;
  435.                     END;
  436.                 END;
  437.  
  438.             { handle newline and line wrap if any }
  439.             IF gotEOL | (fLineLengths^^[insertionPtIndex] >= fCols) THEN
  440.                 BEGIN
  441.                 { set the starting offset of the next line in the buffer }
  442.                 newOffset := fLineStarts^^[insertionPtIndex] + fLineLengths^^[insertionPtIndex] + 1;
  443.                 IF newOffset >= (fTotal - fCols) THEN    { save space for a full line }
  444.                     newOffset := 0;
  445.  
  446.                 fInsertionPt.v := fInsertionPt.v + 1;
  447.                 IF fInsertionPt.v = fRows THEN
  448.                     BEGIN
  449.                     fInsertionPt.v := fRows - 1;
  450.                     fFirstLineIndex := SuccIndex(fFirstLineIndex);
  451.                     doInfiniteScroll := TRUE;
  452.                     END
  453.                 ELSE
  454.                     doInfiniteScroll := FALSE;
  455.                 insertionPtIndex := SuccIndex(insertionPtIndex);
  456.  
  457.                 fLineStarts^^[insertionPtIndex] := newOffset; { offset to store text at }
  458.                 fLineLengths^^[insertionPtIndex] := 0;    { new line starts out zero length }
  459.  
  460.                 IF Focus THEN
  461.                     BEGIN
  462.                     aScroller := GetScroller(FALSE);
  463.                     {$Push} {$H-}
  464.                     IF EqualVPt(aScroller.fTranslation, aScroller.fMaxTranslation) THEN
  465.                     {$Pop}
  466.                         BEGIN
  467.                         IF doInfiniteScroll THEN
  468.                             BEGIN
  469.                             GetVisibleRect(r);
  470.                             ScrollRect(r, 0, - fFontHeight, fUpdateRgn);
  471.                             END;
  472.                         END
  473.                     ELSE
  474.                         BEGIN
  475.                         IF doInfiniteScroll THEN
  476.                         { pretend we're up a line }
  477.                             BEGIN
  478.                             gLongOffset.v := max(gLongOffset.v - fFontHeight, 0);
  479.                             aScroller.fTranslation.v := max(aScroller.fTranslation.v - fFontHeight,
  480.                                                             0);
  481.                             END;
  482.                         RevealInsertionPointLine;
  483.                         END;
  484.                     END;
  485.  
  486.                 { Dynamic sizing of view }
  487.                 IF fInsertionPt.v < fRows THEN
  488.                     Resize((2 * kHMargin) + (fCols * fFontInfo.widMax), (2 * kVMargin) +
  489.                            (fFontHeight * (fInsertionPt.v + 1)), kDontInvalidate);
  490.  
  491.                 END;
  492.             Update;                                     { Make sure everything is nice and visible }
  493.             END;
  494.     END;
  495. {--------------------------------------------------------------------------------------------------}
  496. {$S WWSeg}
  497.  
  498. PROCEDURE TTranscriptView.EndForce;
  499.  
  500.     BEGIN
  501.     IF fForcePtr <= 0 THEN
  502.         BEGIN
  503.         END
  504.     ELSE
  505.         BEGIN
  506.         WITH fForceStack[fForcePtr] DO
  507.             BEGIN
  508.             fWrToWindow := toWindow;
  509.             fWrToFile := toFile;
  510.             END;
  511.         fForcePtr := fForcePtr - 1;
  512.         END;
  513.     END;
  514.  
  515. {--------------------------------------------------------------------------------------------------}
  516. {$S WWSeg}
  517.  
  518. PROCEDURE TTranscriptView.ForceOutput(wrToWindow, wrToFile: WrForceOptions);
  519.  
  520.     BEGIN
  521.     IF fForcePtr >= kForceDepth THEN
  522.         BEGIN
  523.         END
  524.     ELSE
  525.         BEGIN
  526.         fForcePtr := fForcePtr + 1;
  527.  
  528.         WITH fForceStack[fForcePtr] DO
  529.             BEGIN
  530.             toWindow := fWrToWindow;
  531.             toFile := fWrToFile;
  532.             END;
  533.  
  534.         IF wrToWindow <> WrForceUnchanged THEN
  535.             fWrToWindow := wrToWindow = WrForceOn;
  536.  
  537.         IF wrToFile <> WrForceUnchanged THEN
  538.             fWrToFile := wrToFile = WrForceOn;
  539.         END;
  540.     END;
  541.  
  542. {--------------------------------------------------------------------------------------------------}
  543. {$S WWSeg}
  544.  
  545. FUNCTION TTranscriptView.Redirect(vRefnum: INTEGER;
  546.                                   fileName: StringPtr): OSErr;
  547.  
  548.     VAR
  549.         err:                OSErr;
  550.         wantToAppend:        BOOLEAN;
  551.         x:                    LONGINT;
  552.         fndrInfo:            fInfo;
  553.         aRefNum:            INTEGER;
  554.         aFileName:            Str255;
  555.  
  556.     BEGIN
  557.     Redirect := noErr;
  558.     IF fGotRefnum THEN
  559.         BEGIN
  560.         { truncate the file to current position }
  561.         err := GetFPos(fRefnum, x);
  562.         err := SetEOF(fRefnum, x);
  563.         err := FSClose(fRefnum);
  564.         err := FlushVol(NIL, fVRefNum);
  565.         fGotRefnum := FALSE;
  566.         END;
  567.  
  568.     IF fileName <> NIL THEN
  569.         BEGIN
  570.         wantToAppend := POS('>>', fileName^) = 1;
  571.         IF wantToAppend THEN
  572.             aFileName := Copy(fileName^, 3, length(fileName^) - 2)
  573.         ELSE
  574.             aFileName := fileName^;
  575.  
  576.         IF aFileName <> '' THEN
  577.             BEGIN
  578.             err := Create(aFileName, vRefnum, 'MPS ', 'TEXT');
  579.  
  580.             IF err = dupFNErr THEN
  581.                 BEGIN
  582.                 err := GetFInfo(aFileName, 0, fndrInfo);
  583.                 IF err = noErr THEN
  584.                     IF fndrInfo.fdType <> 'TEXT' THEN
  585.                         err := dupFNErr;
  586.                 END;
  587.  
  588.             IF err = noErr THEN
  589.                 BEGIN
  590.                 err := FSOpen(aFileName, vRefnum, aRefNum);
  591.                 fRefnum := aRefNum;
  592.                 fVRefNum := vRefnum;
  593.                 Redirect := err;
  594.  
  595.                 fGotRefnum := err = noErr;
  596.  
  597.                 IF fGotRefnum THEN
  598.                     IF wantToAppend THEN
  599.                         BEGIN
  600.                         err := GetEOF(fRefnum, x);
  601.                         err := SetFPos(fRefnum, fsFromStart, x);
  602.                         END;
  603.                 END
  604.             ELSE
  605.                 Redirect := err;
  606.             END;
  607.         END;
  608.     END;
  609. {--------------------------------------------------------------------------------------------------}
  610. {$S WWSeg}
  611.  
  612. PROCEDURE TTranscriptView.Scroll(howManyLines: INTEGER);
  613.  
  614.     BEGIN
  615.     IF howManyLines <> 0 THEN
  616.         GetScroller(FALSE).ScrollBy(0, howManyLines * fFontHeight, kRedraw);
  617.     END;
  618.  
  619. {--------------------------------------------------------------------------------------------------}
  620. {$S WWSeg}
  621.  
  622. FUNCTION TTranscriptView.DoKeyCommand(ch: Char;
  623.                                       aKeyCode: INTEGER;
  624.                                       VAR info: EventInfo): TCommand; OVERRIDE;
  625.  
  626.     VAR
  627.         message:            LONGINT;
  628.  
  629.     BEGIN
  630.     DoKeyCommand := NIL;
  631.     EraseRect(GetInsertionPointRect);
  632.     IF info.theCmdKey THEN
  633.         CASE ch OF
  634.             chReturn:
  635.                 ch := chDown;
  636.             chBackspace:
  637.                 ch := chUp;
  638.         END;
  639.  
  640.     CASE ch OF
  641.         chPageUp, chPageDown, chHome, chEnd:
  642.             DoKeyCommand := INHERITED DoKeyCommand(ch, aKeyCode, info);
  643.         chDown:
  644.             Scroll(1);
  645.         chUp:
  646.             Scroll( - 1);
  647.         chHelp:
  648.             IF fHelpProc <> NIL THEN
  649.                 DoKeyCommand := DoHelp(info, message)
  650.             ELSE
  651.                 fLastCh := ch;
  652.  
  653.         OTHERWISE
  654.             fLastCh := ch;
  655.     END;
  656.     END;
  657.  
  658. {--------------------------------------------------------------------------------------------------}
  659. {$S WWSeg}
  660.  
  661. FUNCTION TTranscriptView.DoIdle(phase: IdlePhase): BOOLEAN; OVERRIDE;
  662.  
  663.     BEGIN
  664.     IF Focus THEN
  665.         BEGIN
  666.         IF GetWindow.fIsActive THEN
  667.         {$Push} {$H-}
  668.             SetPortTextStyle(fTextStyle);
  669.         {$Pop}
  670.         IF (TickCount - fLastInsertionPointTime) >= GetCaretTime THEN
  671.             BEGIN
  672.             fLastInsertionPointTime := TickCount;
  673.             IF fInsertionPointOn THEN
  674.                 EraseRect(GetInsertionPointRect)
  675.             ELSE
  676.                 FillRect(GetInsertionPointRect, black);
  677.             fInsertionPointOn := NOT fInsertionPointOn;
  678.             END
  679.         END;
  680.     DoIdle := FALSE;
  681.     END;
  682.  
  683. {--------------------------------------------------------------------------------------------------}
  684. {$S WWSeg}
  685.  
  686. PROCEDURE TTranscriptView.Draw(area: Rect); OVERRIDE;
  687.  
  688.     VAR
  689.         currIndex:            INTEGER;                    { index of line to draw }
  690.         startIndex:         INTEGER;                    { save of the first line to draw's index }
  691.         y:                    INTEGER;                    { y coord to draw at }
  692.  
  693.     BEGIN
  694.     {$Push} {$H-}
  695.     SetPortTextStyle(fTextStyle);
  696.     {$Pop}
  697.  
  698.     currIndex := LocalToIndex(area.top);
  699.     y := IndexToLocal(currIndex);                        { initial y coordinate snapped to a row }
  700.  
  701.     HLock(Handle(fText));
  702.     REPEAT
  703.         MoveTo(kHMargin, y);
  704.         DrawText(QDPtr(fText^), fLineStarts^^[currIndex], fLineLengths^^[currIndex]);
  705.         currIndex := SuccIndex(currIndex);
  706.         y := y + fFontHeight;
  707.     UNTIL (((y - fFontInfo.Ascent) > area.bottom) | (currIndex = fFirstLineIndex));
  708.     HUnLock(Handle(fText));
  709.  
  710.     INHERITED Draw(area);
  711.     END;
  712.  
  713. {--------------------------------------------------------------------------------------------------}
  714. {$S MASelCommand}
  715.  
  716. FUNCTION TTranscriptView.HandleMouseDown(theMouse: VPoint;
  717.                                          VAR info: EventInfo;
  718.                                          VAR hysteresis: Point;
  719.                                          VAR theCommand: TCommand): BOOLEAN; OVERRIDE;
  720.  
  721.     BEGIN
  722.     info.affectsMenus := FALSE;                         { Try to keep the debugger from interfering
  723.                                                          too much }
  724.     HandleMouseDown := INHERITED HandleMouseDown(theMouse, info, hysteresis, theCommand);
  725.     END;
  726.  
  727. {--------------------------------------------------------------------------------------------------}
  728. {$S MAClose}
  729.  
  730. PROCEDURE TTranscriptView.Free; OVERRIDE;
  731.  
  732.     BEGIN
  733.     IF Redirect(0, NIL) <> noErr THEN;
  734.  
  735.     Handle(fText) := DisposeIfHandle(fText);
  736.     Handle(fLineLengths) := DisposeIfHandle(fLineLengths);
  737.     Handle(fLineStarts) := DisposeIfHandle(fLineStarts);
  738.  
  739.     INHERITED Free;
  740.     END;
  741.  
  742. {--------------------------------------------------------------------------------------------------}
  743. {$S MAFields}
  744.  
  745. PROCEDURE TTranscriptView.Fields(PROCEDURE DoToField(fieldName: Str255;
  746.                                                      fieldAddr: Ptr;
  747.                                                      fieldType: INTEGER)); OVERRIDE;
  748.  
  749.     VAR
  750.         theFlag:            BOOLEAN;
  751.         i:                    INTEGER;
  752.  
  753.     BEGIN
  754.     DoToField('TTranscriptView', NIL, bClass);
  755.  
  756.     DoToField('fWrToWindow', @fWrToWindow, bBoolean);
  757.     DoToField('fWrToFile', @fWrToFile, bBoolean);
  758.     DoToField('fCols', @fCols, bInteger);
  759.     DoToField('fRows', @fRows, bInteger);
  760.     DoToField('fTotal', @fTotal, bInteger);
  761.     DoToField('fText', @fText, bHandle);
  762.     DoToField('fLineLengths', @fLineLengths, bHandle);
  763.     DoToField('fLineStarts', @fLineStarts, bHandle);
  764.  
  765.     DoToField('fFirstLineIndex', @fFirstLineIndex, bInteger);
  766.  
  767.     {$Push} {$H-}
  768.     TextStyleFields('fTextStyle', fTextStyle, DoToField);
  769.     {$Pop}
  770.     DoToField('fFontHeight', @fFontHeight, bInteger);
  771.     DoToField('fFontInfo', NIL, bTitle);
  772.     DoToField('  ascent', @fFontInfo.Ascent, bInteger);
  773.     DoToField('  descent', @fFontInfo.descent, bInteger);
  774.     DoToField('  widMax', @fFontInfo.widMax, bInteger);
  775.     DoToField('  leading', @fFontInfo.leading, bInteger);
  776.  
  777.     DoToField('fGotRefnum', @fGotRefnum, bBoolean);
  778.     DoToField('fRefnum', @fRefnum, bInteger);
  779.     DoToField('fVRefNum', @fVRefNum, bInteger);
  780.  
  781.     DoToField('fHelpProc', @fHelpProc, bPointer);
  782.     DoToField('fLastInsertionPointTime', @fLastInsertionPointTime, bLongint);
  783.     DoToField('fInsertionPointOn', @fInsertionPointOn, bBoolean);
  784.     DoToField('fInsertionPt', @fInsertionPt, bPoint);
  785.     DoToField('fLastCh', @fLastCh, bChar);
  786.     DoToField('fUpdateRgn', @fUpdateRgn, bRgnHandle);
  787.  
  788.     DoToField('fForcePtr', @fForcePtr, bInteger);
  789.     DoToField('fForceStack', NIL, bTitle);
  790.     FOR i := 1 TO kForceDepth DO
  791.         BEGIN
  792.         DoToField(Concat(ConcatNumber(' [', i), '].toWindow'), @fForceStack[i].toWindow, bBoolean);
  793.         DoToField(Concat(ConcatNumber(' [', i), '].toFile'), @fForceStack[i].toFile, bBoolean);
  794.         END;
  795.  
  796.     INHERITED Fields(DoToField);
  797.     END;
  798.