home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1989 …il & Dave's Excellent CD / Excellent CD HFS.raw / Moof / Goodies / DTS Goodies / WritelnWindow / wlw.p < prev    next >
Encoding:
Text File  |  1989-04-13  |  21.5 KB  |  997 lines  |  [TEXT/MPS ]

  1. UNIT wlw;
  2.     {lifted from MacApp's WriteLnWindow}
  3.     {Copyright 1985, 1986 Apple Computer, Inc}
  4.  
  5. INTERFACE
  6.  
  7. {$R-} {$D+}
  8.  
  9. USES
  10.      MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf,     
  11.     {$LOAD} PasLibIntf;
  12.  
  13. CONST
  14.     kWWEol = CHR($0D);
  15.     kForceDepth = 10;
  16.  
  17. TYPE
  18.     WrForceOptions = (forceOn, forceOff, forceUnchanged);
  19.  
  20. VAR gDebugWindowPtr:    WindowPtr;
  21.     gWrToWindow:        BOOLEAN;    {set to TRUE to enable writelns to window}
  22.     gWrToFile:            BOOLEAN;    {set to TRUE to enable writelns to file}
  23.         {both are initialized to TRUE in WWInit}
  24.  
  25. {All public procedure begin with WW (for WritelnWindow)}
  26. PROCEDURE WWInit(numLines, numCharsPerLine: INTEGER);
  27.     {Call this once at the start of your program.}
  28.  
  29. PROCEDURE WWNew(bounds: Rect; windowTitle: Str255; goAway: BOOLEAN; visible: BOOLEAN;
  30.                 outputFont, outputSize: INTEGER);
  31.     {Call this to create a WriteLn window with given title.
  32.         goAway is TRUE iff you want a go away box (IF the user clicks the go away box,
  33.             the window will be hidden but not freed);
  34.         visible is TRUE iff you want the window to be visible initially;
  35.         outputFont & output size define the font to use
  36.         }
  37.  
  38. PROCEDURE WWForceOutput(wrToWindow, wrToFile: WrForceOptions);
  39. PROCEDURE WWEndForce;
  40.     {Since it is now possible that one part of the program disables writelns to the window, you
  41.         might want to guarantee that certain writelns appear in the window.  WWForceOutput saves
  42.         the values of gWrToWindow & gWrToFile on a stack (depth = kForceDepth), and sets
  43.         these values according to the parameters.  WWEndForce simply pops the stack.}
  44.  
  45. FUNCTION  WWRedirect(vRefnum: INTEGER; fileName: Str255): OSErr;
  46.     {If you call this, then subsequent writelns will be sent to the indicated file.  (Assuming
  47.         writing to the file is enabled. Pass '' for the fileName to close any open file.}
  48.  
  49. FUNCTION  WWReadCh: CHAR;
  50. FUNCTION  WWReadLn(buffer: Ptr; byteCount: INTEGER): LONGINT;
  51. PROCEDURE WWAddText(textBuf: Ptr; byteCount: INTEGER);
  52.  
  53.     {Call before SizeWindow if you need to resize the debug window programmatically}
  54. PROCEDURE WWInvalGrowBox;
  55.     {Call after SizeWindow if you need to resize the debug window programmatically}
  56. PROCEDURE WWGrown;
  57.  
  58.     {Call the following procedures in response to events for the WriteLnWindow.
  59.         (Test the window receiving the event against gDebugWindowPtr.}
  60. PROCEDURE WWActivateEvent(modifiers: INTEGER);
  61. PROCEDURE WWMouseDown(where: INTEGER; pt: Point; modifiers: INTEGER);
  62. PROCEDURE WWUpdateEvent;
  63. PROCEDURE WWScroll(howManyLines: INTEGER); {for UTrace use; negative arg scrolls backwards}
  64.  
  65. PROCEDURE IDUWritelnWindow; {Writeln UWritelnWindow's compile time.}
  66.  
  67. FUNCTION WWFirstLGlob: LongInt;
  68. FUNCTION WWLastLGlob: LongInt;
  69. FUNCTION WWFirstGlob: LongInt;
  70. FUNCTION WWLastGlob: LongInt;
  71.  
  72. IMPLEMENTATION
  73.  
  74. {$R-}
  75. {$D+}
  76.  
  77. CONST
  78.     kWWHMargin = 5;
  79.     kWWVMargin = 10;
  80.  
  81.     _CODEV = 1;         {console device number}
  82.  
  83. TYPE    HText = ^PText;
  84.         PText = ^AText;
  85.         AText = PACKED ARRAY [0..10000] OF CHAR;
  86.  
  87.         HLineLens = ^PLineLens;
  88.         PLineLens = ^ALineLens;
  89.         ALineLens = ARRAY[0..10000] OF INTEGER;
  90.  
  91.         ForceState = RECORD
  92.             toWindow:    BOOLEAN;
  93.             toFile:     BOOLEAN;
  94.             END;
  95.  
  96.     IEFilePath =    STRING;
  97.     IEFilePathPtr = ^IEFilePath;
  98.  
  99.     IEFRefNum =     LONGINT;
  100.  
  101. VAR gLines:         INTEGER;                        {number of lines saved}
  102.     gPerLine:        INTEGER;                        {number of characters per line}
  103.     gTotal:         INTEGER;                        {number of characters in all lines together}
  104.  
  105.     gText:            HText;                            {the ring buffer: blanks pad each line to 80 chars}
  106.     gLineLens:        HLineLens;                        {# of real characters in each line; gLinesLens^^[0]
  107.                                                         is # of characters in the line that begins with
  108.                                                         gText^^[0]}
  109.  
  110.     gFirst:         INTEGER;                        {where in the ring buffer the top line starts}
  111.     gLast:            INTEGER;                        {where in the ring buffer the bottom line starts}
  112.     gPos:            INTEGER;                        {number of characters so far in the bottom line}
  113.  
  114.     gHeight:        INTEGER;                        {font height}
  115.     gLnAscent:        INTEGER;                        {font ascent}
  116.     gWidMax:        INTEGER;                        {font char width (must be monospaced)}
  117.     gSBars:         ARRAY[VHSelect] OF ControlHandle;    {the window scroll bars}
  118.     gScrollOffset:    Point;                            {the position to which we are scrolled}
  119.     gViewSize:        Point;                            {total view size}
  120.     gEndOfText:     Point;                            {the pen position after drawing all the lines}
  121.  
  122.     gStdDrag:        Rect;
  123.     gStdSize:        Rect;
  124.     gOrthogonal:    ARRAY[VHSelect] OF VHSelect;
  125.     gWRec:            WindowRecord;
  126.     gARgn:            RgnHandle;
  127.  
  128.     gGotRefnum:     BOOLEAN;
  129.     gRefnum:        INTEGER;                    {refnum for redirect output}
  130.     gVRefNum:        INTEGER;                    {likewise, vrefnum}
  131.  
  132.     gForceStack:    ARRAY[1..kForceDepth] OF ForceState;
  133.     gForcePtr:        INTEGER;
  134.  
  135.  
  136. FUNCTION  GetSaveVisRgn: RgnHandle; FORWARD;
  137.  
  138. PROCEDURE WWInstall; FORWARD;
  139. FUNCTION  WWBaseLine(ln: INTEGER): INTEGER; FORWARD;
  140. PROCEDURE WWDoScrolling; FORWARD;
  141. PROCEDURE WWDraw; FORWARD;
  142. PROCEDURE WWNewLine; FORWARD;
  143. PROCEDURE WWShowPoint(pt: Point); FORWARD;
  144. PROCEDURE WWTrackScroll(aControl: ControlHandle; partCode: INTEGER); FORWARD;
  145.  
  146.  
  147. {$S WWSeg}
  148. FUNCTION WWFirstLGlob: LongInt;
  149. BEGIN WWFirstLGlob := ORD(@gLines); END;
  150.  
  151. {$S WWSeg}
  152. FUNCTION WWLastLGlob: LongInt;
  153. BEGIN WWLastLGlob := ORD(@gForcePtr); END;
  154.  
  155. {$S WWSeg}
  156. FUNCTION WWFirstGlob: LongInt;
  157. BEGIN WWFirstGlob := ORD(@gDebugWindowPtr); END;
  158.  
  159. {$S WWSeg}
  160. FUNCTION WWLastGlob: LongInt;
  161. BEGIN WWLastGlob := ORD(@gWrToFile); END;
  162.  
  163.  
  164. {$S WWSeg}
  165. FUNCTION  GetSaveVisRgn: RgnHandle;
  166.     CONST    addr    =    $09F2;
  167.     TYPE    pRgn = ^RgnHandle;
  168.     VAR     pSaveVisRgn:    pRgn;
  169. BEGIN
  170.     pSaveVisRgn := pRgn(addr);
  171.     GetSaveVisRgn := pSaveVisRgn^;
  172. END;
  173.  
  174.  
  175. {$S WWSeg}
  176. FUNCTION  LongerSide(VAR r: Rect): VHSelect;
  177. BEGIN
  178.     WITH r DO
  179.         IF (bottom - top) >= (left - right) THEN
  180.             LongerSide := v
  181.         ELSE
  182.             LongerSide := h;
  183. END;
  184.  
  185.  
  186. {$S WWSeg}
  187. PROCEDURE WindowFocus;
  188. BEGIN
  189.     SetPort(gDebugWindowPtr);
  190.     SetOrigin(0, 0);
  191.     ClipRect(thePort^.portRect);
  192. END;
  193.  
  194.  
  195. {$S WWSeg}
  196. PROCEDURE ContentFocus;
  197.     VAR r:    Rect;
  198. BEGIN
  199.     SetPort(gDebugWindowPtr);
  200.     SetOrigin(gScrollOffset.h, gScrollOffset.v);
  201.     r := thePort^.portRect;
  202.     WITH r DO
  203.         BEGIN
  204.         right := right - 15;
  205.         bottom := bottom - 15;
  206.         END;
  207.     ClipRect(r);
  208. END;
  209.  
  210.  
  211. {$S WWInit}
  212. PROCEDURE WWInit(numLines, numCharsPerLine: INTEGER);
  213.     VAR i: INTEGER;
  214. BEGIN
  215.     gDebugWindowPtr := NIL;
  216.  
  217.     gGotRefnum := FALSE;
  218.     gWrToWindow := TRUE;
  219.     gWrToFile := TRUE;
  220.  
  221.     WWInstall;
  222.  
  223.     gForcePtr := 0;
  224.  
  225.     gLines := numLines;
  226.     gPerLine := numCharsPerLine;
  227.     gTotal := gLines * gPerLine;
  228.  
  229.     gText := HText(NewHandle(gTotal));
  230.     IF gText = NIL THEN
  231.         BEGIN
  232.         WriteLn('Not enough memory to allocate the Debug Window''s Line Array: ', gLines:1, '*', gPerLine:1);
  233.         EXIT(WWInit);
  234.         END;
  235.  
  236.     gLineLens := HLineLens(NewHandle(gLines*SIZEOF(INTEGER)));
  237.     IF gLineLens = NIL THEN
  238.         BEGIN
  239.         DisposHandle(Handle(gText));
  240.         WriteLn('Not enough memory to allocate the Debug Window''s LineLen Array: ', gLines:1);
  241.         EXIT(WWInit);
  242.         END;
  243.  
  244.     FOR i := 0 TO gLines-1 DO
  245.         gLineLens^^[i] := 0;
  246.  
  247.     gFirst := 0;
  248.     gLast := gTotal - gPerLine;
  249.     gPos := 0;
  250.  
  251.     gOrthogonal[v] := h;
  252.     gOrthogonal[h] := v;
  253. END;
  254.  
  255.  
  256. {$S WWInit}
  257. PROCEDURE WWNew(bounds: Rect; windowTitle: Str255; goAway: BOOLEAN; visible: BOOLEAN;
  258.                 outputFont, outputSize: INTEGER);
  259.     VAR fInfo:        FontInfo;
  260.         control:    ControlHandle;
  261.         i:            INTEGER;
  262.         aLine:        StringHandle;
  263.         vhs:        VHSelect;
  264.         savePort:    GrafPtr;
  265. BEGIN
  266.     GetPort(savePort);
  267.     IF gDebugWindowPtr = NIL THEN
  268.         BEGIN
  269.         gDebugWindowPtr := NewWindow(@gWRec, bounds, windowTitle, visible, documentProc,
  270.                                     POINTER(-1), goAway, 0);
  271.  
  272.         WITH screenBits.bounds DO
  273.             BEGIN
  274.             SetRect(gStdDrag, 4, 24, right - 4, bottom - 4);    {this is suggested in Inside Macintosh}
  275.             SetRect(gStdSize, 20, 20, right, bottom - 20);        {arbitrary Min size; Max size is screen}
  276.             END;
  277.  
  278.         gARgn := NewRgn;
  279.  
  280.         SetPt(gEndOfText, kWWHMargin, WWBaseLine(gLines));
  281.  
  282.         SetPort(gDebugWindowPtr);
  283.         TextFont(outputFont);
  284.         TextSize(outputSize);
  285.         GetFontInfo(fInfo);
  286.  
  287.         WITH fInfo DO
  288.             BEGIN
  289.             gHeight := ascent + descent + leading;
  290.             gLnAscent := ascent;
  291.             gWidMax := widMax;
  292.             SetPt(gViewSize, (2 * kWWHMargin) + (gPerLine * widMax), (2 * kWWVMargin) + (gHeight * gLines));
  293.             END;
  294.  
  295.         {scroll bars}
  296.         FOR vhs := v TO h DO
  297.             gSBars[vhs] := NewControl(gDebugWindowPtr, gDebugWindowPtr^.portRect, '', FALSE,
  298.                                 0, 0, 1, scrollBarProc, 0);
  299.  
  300.         {SetPt(gScrollOffset, 0, 0);}
  301.         gScrollOffset := Point(0);
  302.  
  303.         {put the scroll bars in the right place}
  304.         WWGrown;
  305.  
  306.         {force an update}
  307.         WWUpdateEvent;
  308.  
  309.         {scroll to the end, in case there is some information that needs to be displayed}
  310.         SetCtlValue(gSBars[v], MAXINT);
  311.         WWDoScrolling;
  312.         END;
  313.     SetPort(savePort);
  314. END;
  315.  
  316.  
  317. {$S WWSeg}
  318. PROCEDURE WWActivateEvent(modifiers: INTEGER);
  319.     VAR r:            Rect;
  320.         vhs:        VHSelect;
  321.         anSBar:     ControlHandle;
  322.         savePort:    GrafPtr;
  323. BEGIN
  324.     GetPort(savePort);
  325.  
  326.     WindowFocus;
  327.  
  328.     r := thePort^.portRect;
  329.  
  330.     FOR vhs := v TO h DO
  331.         BEGIN
  332.         anSBar := gSBars[vhs];
  333.         IF Odd(modifiers) THEN
  334.             ShowControl(anSBar)
  335.         ELSE
  336.             HideControl(anSBar);
  337.         END;
  338.  
  339.     DrawGrowIcon(gDebugWindowPtr);
  340.  
  341.     SetPort(savePort);
  342. END;
  343.  
  344.  
  345. {$S WWSeg}
  346. PROCEDURE WWAddText(textBuf: Ptr; byteCount: INTEGER);
  347.     CONST BS = 8;
  348.     VAR gotEOL:     BOOLEAN;
  349.         b:            QDByte;
  350.         startPtr:    Ptr;
  351.         startCount: INTEGER;
  352.         ps:         PenState;
  353.         savePort:    GrafPtr;
  354.         deleted:    BOOLEAN;
  355.         r:            Rect;
  356.  
  357.         count:        LONGINT;
  358. BEGIN
  359.     IF gWrToFile THEN
  360.         IF gGotRefnum THEN
  361.             BEGIN
  362.             count := byteCount;
  363.             IF FSWrite(gRefnum, count, textBuf) <> noErr THEN
  364.                 BEGIN
  365.                 {??? do something here ???}
  366.                 END;
  367.             END;
  368.  
  369.     IF gWrToWindow THEN
  370.         BEGIN
  371.         IF gDebugWindowPtr <> NIL THEN
  372.             GetPort(savePort);
  373.  
  374.         deleted := FALSE;
  375.  
  376.         WHILE byteCount > 0 DO
  377.             BEGIN
  378.             gotEOL := FALSE;
  379.             startPtr := textBuf;
  380.             startCount := byteCount;
  381.  
  382.             WHILE (byteCount > 0) AND (gPos < gPerLine) AND (NOT gotEOL) DO
  383.                 BEGIN
  384.                 b := QDPtr(textBuf)^;
  385.                 byteCount := byteCount - 1;
  386.                 textBuf := Ptr(LONGINT(textBuf) + 1);
  387.  
  388.                 IF b = ORD(kWWEol) THEN
  389.                     gotEOL := TRUE
  390.                 ELSE IF b <> BS THEN
  391.                     BEGIN
  392.                     gText^^[gLast+gPos] := CHAR(b);
  393.                     gPos := gPos + 1;
  394.                     END
  395.                 ELSE IF gPos > 0 THEN  {Backspace -- don't backspace past beginning of line!}
  396.                     BEGIN
  397.                     WITH gEndOfText DO
  398.                         BEGIN
  399.                         SetRect(r, h - gWidMax, v - gLnAscent, h, v + gHeight - gLnAscent);
  400.                         h := h - gWidMax;
  401.                         END;
  402.  
  403.                     IF gDebugWindowPtr <> NIL THEN
  404.                         BEGIN
  405.                         ContentFocus;
  406.                         EraseRect(r);
  407.                         END;
  408.  
  409.                     gPos := gPos - 1;
  410.                     deleted := TRUE;
  411.                     END
  412.                 ELSE
  413.                     deleted := TRUE;
  414.                 END;
  415.  
  416.             IF NOT deleted AND (gDebugWindowPtr <> NIL) THEN
  417.                 BEGIN
  418.                 ContentFocus;
  419.                 MoveTo(gEndOfText.h, gEndOfText.v);
  420.                 DrawText(QDPtr(startPtr), 0, startCount - byteCount - ORD(gotEOL));
  421.                 GetPenState(ps);
  422.                 gEndOfText := ps.pnLoc;
  423.                 END;
  424.  
  425.             IF (gPos >= gPerLine) OR gotEOL THEN
  426.                 BEGIN
  427.                 gLineLens^^[gLast DIV gPerLine] := gPos;    {remember # characters in this line}
  428.  
  429.                 WWNewLine;
  430.                 IF (byteCount > 0) AND (NOT gotEOL) THEN
  431.                     BEGIN
  432.                     gText^^[gLast] := '…';
  433.                     gPos := 1;
  434.                     END;
  435.                 END;
  436.             END;
  437.  
  438.         gLineLens^^[gLast DIV gPerLine] := gPos;
  439.  
  440.         IF gDebugWindowPtr <> NIL THEN
  441.             SetPort(savePort);
  442.         END;
  443. END;
  444.  
  445.  
  446. {$S WWSeg}
  447. FUNCTION  WWBaseLine(ln: INTEGER): INTEGER;
  448. BEGIN
  449.     WWBaseLine := kWWVMargin + (ln - 1) * gHeight;
  450. END;
  451.  
  452.  
  453. {$S WWSeg}
  454. PROCEDURE WWDoScrolling;
  455.     VAR newOffset:        Point;
  456.         delta:            Point;
  457. BEGIN
  458.     newOffset.v := GetCtlValue(gSBars[v]);
  459.     delta.v := gScrollOffset.v - newOffset.v;
  460.     newOffset.h := GetCtlValue(gSBars[h]);
  461.     delta.h := gScrollOffset.h - newOffset.h;
  462.  
  463.     IF (delta.h <> 0) OR (delta.v <> 0) THEN
  464.         BEGIN
  465.         ContentFocus;
  466.  
  467.         ScrollRect(thePort^.portRect, delta.h, delta.v, gARgn);
  468.         gScrollOffset := newOffset;
  469.  
  470.         InvalRgn(gARgn);
  471.  
  472.         WWUpdateEvent;
  473.         END;
  474. END;
  475.  
  476.  
  477. {$S WWSeg}
  478. PROCEDURE WWDraw;
  479.     VAR i:        INTEGER;
  480.         y:        INTEGER;
  481.         start:    INTEGER;
  482.         line:    INTEGER;
  483.         ps:     PenState;
  484. BEGIN
  485.     y := kWWVMargin;            {initial y corodinate}
  486.  
  487.     start := gFirst;            {offset to first character of next line to draw}
  488.     line := start DIV gPerLine; {index into gLineLens array for next line to draw; always start DIV gPerLine}
  489.  
  490.     FOR i := 1 TO gLines DO
  491.         BEGIN
  492.         MoveTo(kWWHMargin, y);
  493.  
  494.         HLock(Handle(gText));
  495.         DrawText(QDPtr(gText^), start, gLineLens^^[line]);
  496.         HUnlock(Handle(gText));
  497.  
  498.         y := y + gHeight;
  499.         start := start + gPerLine;
  500.         line := line + 1;
  501.  
  502.         IF start = gTotal THEN
  503.             BEGIN
  504.             start := 0;
  505.             line := 0;
  506.             END;
  507.         END;
  508.  
  509.     GetPenState(ps);            {remember position of last character drawn}
  510.     gEndOfText := ps.pnLoc;
  511. END;
  512.  
  513.  
  514. {$S WWSeg}
  515. PROCEDURE WWEndForce;
  516. BEGIN
  517.     IF gForcePtr <= 0 THEN
  518.         BEGIN
  519.         END
  520.     ELSE
  521.         BEGIN
  522.         WITH gForceStack[gForcePtr] DO
  523.             BEGIN
  524.             gWrToWindow := toWindow;
  525.             gWrToFile := toFile;
  526.             END;
  527.         gForcePtr := gForcePtr - 1;
  528.         END;
  529. END;
  530.  
  531.  
  532. {$S WWSeg}
  533. PROCEDURE WWForceOutput(wrToWindow, wrToFile: WrForceOptions);
  534. BEGIN
  535.     IF gForcePtr >= kForceDepth THEN
  536.         BEGIN
  537.         END
  538.     ELSE
  539.         BEGIN
  540.         gForcePtr := gForcePtr + 1;
  541.  
  542.         WITH gForceStack[gForcePtr] DO
  543.             BEGIN
  544.             toWindow := gWrToWindow;
  545.             toFile := gWrToFile;
  546.             END;
  547.  
  548.         IF wrToWindow <> forceUnchanged THEN
  549.             gWrToWindow := wrToWindow = forceOn;
  550.  
  551.         IF wrToFile <> forceUnchanged tHEN
  552.             gWrToFile := wrToFile = forceOn;
  553.         END;
  554. END;
  555.  
  556.  
  557. {$S WWSeg}
  558. PROCEDURE WWGrown;
  559.     VAR r:                Rect;
  560.         vhs:            VHSelect;
  561.         anSBar:         ControlHandle;
  562.         newMax:         INTEGER;
  563.         isVisible:        BOOLEAN;
  564.         savePort:        GrafPtr;
  565. BEGIN
  566.     GetPort(savePort);
  567.  
  568.     WindowFocus;
  569.     r.topLeft := Point(0);
  570.     r.botRight := Point(0);
  571.     ClipRect(r);
  572.  
  573.     FOR vhs := v TO h DO
  574.         BEGIN
  575.         anSBar := gSBars[vhs];
  576.  
  577.         r := thePort^.portRect;
  578.  
  579.         WITH r DO
  580.             BEGIN
  581.             {Calculate new position of scroll bar}
  582.             topLeft.vh[vhs] := topLeft.vh[vhs] - 1;
  583.             topLeft.vh[gOrthogonal[vhs]] := botRight.vh[gOrthogonal[vhs]] - 15;
  584.             botRight.vh[vhs] := botRight.vh[vhs] - 14;
  585.             botRight.vh[gOrthogonal[vhs]] := topLeft.vh[gOrthogonal[vhs]] + 16;
  586.  
  587.             {Move the scroll bar}
  588.             MoveControl(anSBar, left, top);
  589.             SizeControl(anSBar, right-left, bottom-top);
  590.  
  591.             newMax := gViewSize.vh[vhs] - (bottom - top);
  592.             IF newMax < 0 THEN
  593.                 newMax := 0;
  594.             SetCtlMax(anSBar, newMax);
  595.             END;
  596.         END;
  597.  
  598.     WWInvalGrowBox;
  599.  
  600.     WWDoScrolling;    {in case we are showing too much white space}
  601.  
  602.     SetPort(savePort);
  603. END;
  604.  
  605.  
  606. {$S WWSeg}
  607. PROCEDURE WWInvalGrowBox;
  608.     VAR r:    Rect;
  609. BEGIN
  610.     r.botRight := thePort^.portRect.botRight;
  611.     WITH r DO
  612.         BEGIN
  613.         top := bottom - 15;
  614.         left := right - 15;
  615.         END;
  616.     InvalRect(r);
  617. END;
  618.  
  619.  
  620. {$S WWSeg}
  621. PROCEDURE WWMouseDown(where: INTEGER; pt: Point; modifiers: INTEGER);
  622.     VAR r:                Rect;
  623.         sizeStuff:        RECORD CASE INTEGER OF
  624.                             1:    (growResult: LONGINT);        {Information returned by GrowRect}
  625.                             2:    (newV,                        {new vertical size}
  626.                                  newH: INTEGER);            {new horizontal size}
  627.                             3:    (newSize: Point);            {new size as a point}
  628.                         END;
  629.         partCode:        INTEGER;
  630.         whichControl:    ControlHandle;
  631.         oldSize:        Point;
  632.         savePort:        GrafPtr;
  633. BEGIN
  634.     GetPort(savePort);
  635.  
  636.     CASE where OF
  637.         inDrag:
  638.             DragWindow(gDebugWindowPtr, pt, gStdDrag);
  639.  
  640.         inGrow:
  641.             BEGIN
  642.             WindowFocus;
  643.  
  644.             WITH sizeStuff DO
  645.                 BEGIN
  646.                 WITH gDebugWindowPtr^.portRect, oldSize DO
  647.                     BEGIN
  648.                     h := right - left;
  649.                     v := bottom - top;
  650.                     END;
  651.  
  652.                 growResult := GrowWindow(gDebugWindowPtr, pt, gStdSize);
  653.                 IF growResult <> 0 THEN
  654.                     BEGIN
  655.                     WWInvalGrowBox;
  656.                     SizeWindow(gDebugWindowPtr, newH, newV, TRUE);
  657.                     WWGrown;
  658.                     END;
  659.                 END;
  660.             END;
  661.  
  662.         inGoAway:
  663.             IF TrackGoAway(gDebugWindowPtr, pt) THEN
  664.                 HideWindow(gDebugWindowPtr);
  665.  
  666.         inContent:
  667.             IF gDebugWindowPtr = FrontWindow THEN
  668.                 BEGIN
  669.                 WindowFocus;
  670.  
  671.                 GlobalToLocal(pt);
  672.                 partCode := FindControl(pt, gDebugWindowPtr, whichControl);
  673.                 IF partCode <> 0 THEN
  674.                     CASE partCode OF
  675.                         inUpButton, inDownButton, inPageUp, inPageDown:
  676.                             partCode := TrackControl(whichControl, pt, @WWTrackScroll);
  677.                         inThumb:
  678.                             BEGIN
  679.                             partCode := TrackControl(whichControl, pt, NIL);
  680.                             WWDoScrolling;
  681.                             END;
  682.                         END;
  683.                 END
  684.             ELSE
  685.                 SelectWindow(gDebugWindowPtr);
  686.         END;  {CASE}
  687.  
  688.     SetPort(savePort);
  689. END;
  690.  
  691.  
  692. {$S WWSeg}
  693. PROCEDURE WWNewLine;
  694.     VAR savePort:        GrafPtr;
  695.         i:                INTEGER;
  696.         pt:             Point;
  697.         r:                Rect;
  698. BEGIN
  699.     GetPort(savePort);
  700.  
  701.     SetPt(pt, kWWHMargin, gEndOfText.v);
  702.     WWShowPoint(pt);
  703.  
  704.     gLast := gFirst;
  705.     gPos := 0;
  706.     gLineLens^^[gLast DIV gPerLine] := gPos;    {remember # characters in new line}
  707.  
  708.     gFirst := gFirst + gPerLine;
  709.     IF gFirst = gTotal THEN
  710.         gFirst := 0;
  711.  
  712.     SetPt(gEndOfText, kWWHMargin, WWBaseLine(gLines));
  713.  
  714.     IF gDebugWindowPtr <> NIL THEN
  715.         BEGIN
  716.         ContentFocus;
  717.         SetRect(r, kWWHMargin, kWWVMargin - gLnAscent, gViewSize.h, gEndOfText.v + gHeight - gLnAscent);
  718.         ScrollRect(r, 0, -gHeight, gARgn);
  719.         InvalRgn(gARgn);
  720.  
  721.         WWUpdateEvent;
  722.         END;
  723.  
  724.     SetPort(savePort);
  725. END;
  726.  
  727.  
  728. FUNCTION  WWRedirect(vRefnum: INTEGER; fileName: Str255): OSErr;
  729.     VAR err:    OSErr;
  730.         append: BOOLEAN;
  731.         x:        LONGINT;
  732. BEGIN
  733.     IF gGotRefnum THEN
  734.         BEGIN
  735.             {truncate the file to current position}
  736.         err := GetFPos(gRefnum, x);
  737.         err := SetEOF(gRefnum, x);
  738.  
  739.         IF FSClose(gRefnum) <> noErr THEN {??? error closing file ???};
  740.         IF FlushVol(NIL, gVRefNum) <> noErr THEN {??? Another fine mess ???};
  741.         gGotRefnum := FALSE;
  742.         END;
  743.  
  744.     append := POS('>>', fileName) = 1;
  745.     IF append THEN
  746.         Delete(fileName, 1 ,2);
  747.  
  748.     IF fileName <> '' THEN
  749.         BEGIN
  750.         err := Create(fileName, vRefnum, 'MACA', 'TEXT');
  751.  
  752.         IF (err = noErr) OR (err = dupFNErr) THEN
  753.             BEGIN
  754.             err := FSOpen(fileName, vRefnum, gRefnum);
  755.             gVRefNum := vRefNum;
  756.             WWRedirect := err;
  757.  
  758.             gGotRefnum := err = noErr;
  759.  
  760.             IF gGotRefnum THEN
  761.                 IF append THEN
  762.                     BEGIN
  763.                     err := GetEOF(gRefnum, x);
  764.                     err := SetFPos(gRefnum, fsFromStart, x);
  765.                     END;
  766.             END
  767.         ELSE
  768.             WWRedirect := err;
  769.         END;
  770. END;
  771.  
  772.  
  773. PROCEDURE WWScroll(howManyLines: INTEGER);
  774.     VAR val:        INTEGER;
  775.         savePort:    GrafPtr;
  776. BEGIN
  777.     GetPort(savePort);
  778.     val := GetCtlValue(gSBars[v]);
  779.     IF ((howManyLines < 0) AND (val > GetCtlMin(gSBars[v]))) OR
  780.        ((howManyLines > 0) AND (val < GetCtlMax(gSBars[v]))) THEN
  781.         BEGIN
  782.         SetCtlValue(gSBars[v], val + howManyLines * gHeight);
  783.         WWDoScrolling;
  784.         END;
  785.     SetPort(savePort);
  786. END;
  787.  
  788.  
  789. PROCEDURE WWShowPoint(pt: Point);
  790.     VAR minToSee:    Point;
  791.         deltaCd:    INTEGER;
  792. BEGIN
  793.     IF gDebugWindowPtr <> NIL THEN
  794.         BEGIN
  795.         WindowFocus;
  796.     
  797.         SetPt(minToSee, 50, gHeight);
  798.     
  799.         {the following code is actually better than writing a loop with VHSelect}
  800.         WITH thePort^.portRect DO
  801.             BEGIN
  802.             deltaCd := pt.v + mintoSee.v - (bottom - 15 + gScrollOffset.v);
  803.             IF deltaCd <= 0 THEN
  804.                 BEGIN
  805.                 deltaCd := pt.v - minToSee.v - (top + gScrollOffset.v);
  806.                 IF deltaCd >= 0 THEN
  807.                     deltaCd := 0;
  808.                 END;
  809.             SetCtlValue(gSBars[v], GetCtlValue(gSBars[v]) + deltaCd);
  810.     
  811.             deltaCd := pt.h + mintoSee.h - (right - 15 + gScrollOffset.h);
  812.             IF deltaCd <= 0 THEN
  813.                 BEGIN
  814.                 deltaCd := pt.h - minToSee.h - (left + gScrollOffset.h);
  815.                 IF deltaCd >= 0 THEN
  816.                     deltaCd := 0;
  817.                 END;
  818.             SetCtlValue(gSBars[h], GetCtlValue(gSBars[h]) + deltaCd);
  819.             END;
  820.     
  821.         WWDoScrolling;
  822.         END;
  823. END;
  824.  
  825.  
  826. {$S WWSeg}
  827. PROCEDURE WWTrackScroll(aControl: ControlHandle; partCode: INTEGER);
  828.     VAR up:         BOOLEAN;
  829.         ctlValue:    INTEGER;
  830.         vhs:        VHSelect;
  831.         r:            Rect;
  832.         delta:        INTEGER;
  833. BEGIN
  834.     IF partCode <> 0 THEN
  835.         BEGIN
  836.         up := (partCode = inUpButton) OR (partCode = inPageUp);
  837.         ctlValue := GetCtlValue(aControl);
  838.  
  839.       {avoid flicker in setting thumb, IF user tries to scroll past end}
  840.         IF (up AND (ctlValue > GetCtlMin(aControl))) OR
  841.            (NOT up AND (ctlValue < GetCtlMax(aControl))) THEN
  842.             BEGIN
  843.             r := aControl^^.contrlRect;   {heap may compact when we call LongerSide}
  844.             vhs := LongerSide(r);          {this tells us which way we are scrolling}
  845.  
  846.             IF (partCode = inPageUp) OR (partCode = inPageDown) THEN
  847.                 WITH gDebugWindowPtr^.portRect DO
  848.                     delta := botRight.vh[vhs] - topLeft.vh[vhs] - gHeight
  849.             ELSE
  850.                 delta := gHeight;
  851.  
  852.             IF up THEN
  853.                 delta := - delta;
  854.  
  855.             SetCtlValue(aControl, ctlValue + delta);
  856.             WWDoScrolling;
  857.  
  858.             WindowFocus;
  859.             END;
  860.         END;
  861. END;
  862.  
  863.  
  864. {$S WWSeg}
  865. PROCEDURE WWUpdateEvent;
  866.     VAR savePort:        GrafPtr;
  867.         saveSaveVisRgn: RgnHandle;
  868.         saveVisRgn:     RgnHandle;
  869. BEGIN
  870.     GetPort(savePort);
  871.  
  872.     saveSaveVisRgn := NewRgn;
  873.     saveVisRgn := GetSaveVisRgn;
  874.  
  875.     CopyRgn(saveVisRgn, saveSaveVisRgn);
  876.  
  877.     BeginUpdate(gDebugWindowPtr);
  878.  
  879.     WindowFocus;
  880.  
  881.     EraseRect(thePort^.portRect);
  882.  
  883.     DrawGrowIcon(gDebugWindowPtr);
  884.     DrawControls(gDebugWindowPtr);
  885.  
  886.     ContentFocus;
  887.     WWDraw;
  888.  
  889.     EndUpdate(gDebugWindowPtr);
  890.  
  891.     CopyRgn(saveSaveVisRgn, saveVisRgn);
  892.     DisposeRgn(saveSaveVisRgn);
  893.  
  894.     SetPort(savePort);
  895. END;
  896.  
  897.  
  898. {$S WWSeg}
  899. FUNCTION WWReadCh: CHAR;
  900.     VAR savePort:    GrafPtr;
  901.         ch:         CHAR;
  902.         anEvent:    EventRecord;
  903.         r:            Rect;
  904. BEGIN
  905.     GetPort(savePort);
  906.  
  907.     ContentFocus;
  908.  
  909.     WITH gEndOfText DO
  910.         SetRect(r, h, v - gLnAscent, h + gWidMax, v + gHeight - gLnAscent);
  911.  
  912.     FillRect(r, black);
  913.     REPEAT UNTIL GetOSEvent(keyDownMask+autoKeyMask, anEvent);
  914.     EraseRect(r);
  915.  
  916.     ch := CHAR(BAND(anEvent.message, charCodeMask));
  917.  
  918.     WWReadCh := ch;
  919.  
  920.     SetPort(savePort);
  921. END;
  922.  
  923.  
  924. {$S WWSeg}
  925. FUNCTION WWReadLn(buffer: Ptr; byteCount: INTEGER): LONGINT;
  926.     CONST
  927.         CR = 13;
  928.         BS = 8;
  929.     TYPE    PA1000 = PACKED ARRAY [0..999] OF CHAR;
  930.             StrPtr = ^PA1000;
  931.     VAR ch:     CHAR;
  932.         len:        INTEGER;
  933. BEGIN
  934.     len := 0;
  935.     REPEAT
  936.         ch := WWReadCh;
  937.         IF ORD(ch) <> BS THEN
  938.             BEGIN
  939.             WWAddText(POINTER(ORD(@ch)+1), 1);
  940.             StrPtr(buffer)^[len] := CHAR(ch);
  941.             len := len + 1;
  942.             END
  943.         ELSE IF len > 0 THEN
  944.             BEGIN
  945.             WWAddText(POINTER(ORD(@ch)+1), 1);
  946.             len := len - 1;
  947.             StrPtr(buffer)^[len] := ' ';
  948.             END
  949.    UNTIL (ORD(ch)=CR) OR (len = byteCount);
  950.  
  951.    WWReadLn := len;
  952. END;
  953.  
  954.  
  955. PROCEDURE IDUWritelnWindow; {Writeln UWritelnWindow's compile time.}
  956. BEGIN
  957.     Writeln('UWritelnWindow of ', COMPDATE, ' @ ', COMPTIME);
  958. END;
  959.  
  960.  
  961. FUNCTION
  962.     wwFAccess(fName: UNIV IEFilePathPtr; opCode: LONGINT; arg: UNIV LONGINT):
  963.     LONGINT; C; EXTERNAL;
  964. FUNCTION
  965.     wwClose(fdesc: IEFRefNum):
  966.     LONGINT; C; EXTERNAL;
  967. FUNCTION
  968.     wwRead(fdesc: IEFRefNum; bufp: UNIV LONGINT; count: LONGINT):
  969.     LONGINT; C; EXTERNAL;
  970. FUNCTION
  971.     wwWrite(fdesc: IEFRefNum; bufp: UNIV LONGINT; count: LONGINT):
  972.     LONGINT; C; EXTERNAL;
  973. FUNCTION
  974.     wwIoctl(fdesc: IEFRefNum; request: LONGINT; arg: UNIV LONGINT):
  975.     LONGINT; C; EXTERNAL;
  976.  
  977. FUNCTION
  978.     _addDevHandler(
  979.         slot, dvName, dvFAccess, dvClose, dvRead, dvWrite, dvIoctl: LONGINT):
  980.     LONGINT; C; EXTERNAL;
  981.  
  982. PROCEDURE WWInstall;
  983.     VAR slot: LONGINT;
  984. BEGIN
  985.     slot := _addDevHandler(_CODEV, 0,
  986.                     ORD(@wwFAccess), ORD(@wwClose), 
  987.                     ORD(@wwRead), ORD(@wwWrite),
  988.                     ORD(@wwIoctl));
  989.     PLsetvbuf(output, NIL, 64, 100);
  990. END;
  991.  
  992.  
  993. END.
  994.  
  995.  
  996.  
  997.