home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample SMSAM / SampleSMSAM Source / BuildingBlocks / WriteLineWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-28  |  22.1 KB  |  1,102 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        WriteLineWindow.c
  3.  
  4.     Copyright:    © 1991-1994 by Apple Computer, Inc.
  5.                 All rights reserved.
  6.  
  7.     Part of the AOCE Sample SMSAM Package.  Consult the license
  8.     which came with this software for your specific legal rights.
  9.  
  10. */
  11.  
  12.  
  13.  
  14. #ifndef __TYPES__
  15. #include <Types.h>
  16. #endif
  17.  
  18. #ifndef __MENUS__
  19. #include <Menus.h>
  20. #endif
  21.  
  22. #ifndef __WINDOWS__
  23. #include <Windows.h>
  24. #endif
  25.  
  26. #ifndef __WRITELINEWINDOW__
  27. #include "WriteLineWindow.h"
  28. #endif
  29.  
  30. #ifndef __MEMORY__
  31. #include <Memory.h>
  32. #endif
  33.  
  34. #ifndef __LIMITS__
  35. #include <Limits.h>
  36. #endif
  37.  
  38. #ifndef __PLSTRINGFUNCS__
  39. #ifndef THINK_CPLUS
  40. #include <PLStringFuncs.h>
  41. #else
  42. #include "PLStringFuncs.h"
  43. #endif
  44. #endif
  45.  
  46. #ifndef __SYSEQU__
  47. #include <SysEqu.h>
  48. #endif
  49.  
  50. #ifndef __ERRORS__
  51. #include <Errors.h>
  52. #endif
  53.  
  54. #ifndef __EVENTS__
  55. #include <Events.h>
  56. #endif
  57.  
  58. #ifndef __OSEVENTS__
  59. #include <OSEvents.h>
  60. #endif
  61.  
  62. #ifndef __STDIO__
  63. #include <stdio.h>
  64. #endif
  65.  
  66. /***********************************|****************************************/
  67.  
  68.  
  69. const short kWWHMargin = 5;
  70. const short kWWVMargin = 10;
  71. const short kForceDepth = 16;
  72.  
  73. enum { forceUnchanged, forceOn, forceOff };
  74.  
  75. const short    CODEV = 1;         //console device number
  76.  
  77.     typedef struct ForceState {
  78.         Boolean        toWindow;
  79.         Boolean        toFile;
  80.     } ForceState;
  81.  
  82. /***********************************|****************************************/
  83.  
  84.     WindowPtr    gDebugWindowPtr;    
  85.     short        gLines;
  86.     short        gPerLine;                        //number of characters per line
  87.     long        gTotal;                        //number of characters in all lines together
  88.     char**        gText;                            //the ring buffer: blanks pad each line to 80 chars
  89.     long**        gLineLens;                        /*# of real characters in each line; (*gLinesLens)^[0]
  90.                                                         is # of characters in the line that begins with
  91.                                                         (*gText)^[0]*/
  92.  
  93.     long        gFirst;                        //where in the ring buffer the top line starts
  94.     long        gLast;                        //where in the ring buffer the bottom line starts
  95.     short        gPos;                        //number of characters so far in the bottom line
  96.  
  97.     short        gHeight;                        //font height
  98.     short        gLnAscent;                        //font ascent
  99.     short        gWidMax;                        //font char width (must be monospaced)
  100.     ControlHandle    gSBars[2];    //the window scroll bars
  101.     Point        gScrollOffset;                            //the position to which we are scrolled
  102.     Point        gViewSize;                            //total view size
  103.     Point        gEndOfText;                            //the pen position after drawing all the lines
  104.  
  105.     Rect        gStdDrag;
  106.     Rect        gStdSize;
  107.     VHSelect    gOrthogonal[2];
  108.     WindowRecord        gWRec;
  109.     RgnHandle        gARgn;
  110.  
  111.     Boolean        gGotRefNum;
  112.     short        gRefNum;                    //refNum for redirect output
  113.     short        gVRefNum;                    //likewise, vrefNum
  114.  
  115.     ForceState    gForceStack[kForceDepth];
  116.     short        gForcePtr;
  117.  
  118.     char* gHexStr = "0123456789abcdef";
  119.     
  120.     Boolean        gScrollWindowWhenTextIsAdded ;
  121.     Boolean        gWrToWindow = false;
  122.     Boolean        gWrToFile = false;
  123.  
  124.  
  125. /***********************************|****************************************/
  126.  
  127. void WWInstall(void);
  128. long WWBaseLine(short ln);
  129. void WWDoScrolling(void);
  130. void WWFlushOutputFile(void);
  131. void WWNewLine(void);
  132. void WWTrackScroll(ControlHandle aControl, short partCode);
  133. void WWShowPoint(Point pt);
  134.  
  135. /***********************************|****************************************/
  136.  
  137. #pragma segment WWSeg
  138. RgnHandle GetSaveVisRgn(void)
  139. {
  140.     const long addr    = 0x09F2;
  141.     
  142.     return * (RgnHandle *) addr;
  143. }
  144.  
  145. #pragma segment WWSeg
  146. VHSelect LongerSide(Rect& r)
  147. {
  148.         if ((r.bottom - r.top) >= (r.left - r.right))
  149.             return v;
  150.         else
  151.             return h;
  152. }
  153.  
  154.  
  155. #pragma segment WWSeg
  156. void WindowFocus(void)
  157. {
  158.     SetPort(gDebugWindowPtr);
  159.     SetOrigin(0, 0);
  160.     ClipRect(&qd.thePort->portRect);
  161. }
  162.  
  163.  
  164. #pragma segment WWSeg
  165. void ContentFocus(void)
  166. {    Rect        r;
  167.  
  168.     SetPort(gDebugWindowPtr);
  169.     SetOrigin(gScrollOffset.h, gScrollOffset.v);
  170.     r = qd.thePort->portRect;
  171.     r.right = r.right - 15;
  172.     r.bottom = r.bottom - 15;
  173.     ClipRect(&r);
  174. }
  175.  
  176.  
  177. #pragma segment WWInit
  178. void WWInit(short numLines, short numCharsPerLine)
  179. {    
  180.     gDebugWindowPtr = NULL;
  181.  
  182.     gGotRefNum = false;
  183.     gWrToWindow = true;
  184.     gWrToFile = true;
  185.     gScrollWindowWhenTextIsAdded = false;
  186.     WWInstall();
  187.  
  188.     gForcePtr = 0;
  189.  
  190.     gLines = numLines;
  191.     gPerLine = numCharsPerLine;
  192.     gTotal = gLines * gPerLine;
  193.  
  194.     gText = (char **) NewHandleClear(gTotal);
  195.     if (gText == NULL)
  196.     {
  197.         DebugStr ("\pNot enough memory to allocate the Debug Window''s Line Array: " );
  198.         return ;
  199.     }
  200.  
  201.     gLineLens = (long **) NewHandleClear (gLines*sizeof(long));
  202.     if (gLineLens == NULL)
  203.     {
  204.         DisposeHandle(Handle(gText));
  205.         DebugStr ("\pNot enough memory to allocate the Debug Window''s LineLen Array: ");
  206.         return;
  207.     }
  208.  
  209.     gFirst = 0;
  210.     gLast = gTotal - gPerLine;
  211.     gPos = 0;
  212.  
  213.     gOrthogonal[v] = h;
  214.     gOrthogonal[h] = v;
  215. }
  216.  
  217.  
  218. #pragma segment WWInit
  219. void WWNew(Rect bounds, Str255 windowTitle, Boolean goAway, Boolean visible, short outputFont, short outputSize)
  220. {    FontInfo fInfo;
  221.     GrafPtr        savePort;
  222.  
  223.     GetPort(&savePort);
  224.     if (gDebugWindowPtr == NULL)
  225.     {
  226.         gDebugWindowPtr = NewWindow(nil, &bounds, windowTitle, visible, documentProc, (WindowPtr) -1, goAway, 0);
  227.  
  228.         SetRect(&gStdDrag, 4, 24, qd.screenBits.bounds.right - 4, qd.screenBits.bounds.bottom - 4);    //this is suggested in Inside Macintosh
  229.         SetRect(&gStdSize, 20, 20, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom - 20);        //arbitrary Minimum size; Maximum size is screen
  230.  
  231.         gARgn = NewRgn();
  232.  
  233.         SetPt(&gEndOfText, kWWHMargin, (short) WWBaseLine(gLines));
  234.  
  235.         SetPort(gDebugWindowPtr);
  236.         TextFont(outputFont);
  237.         TextSize(outputSize);
  238.         GetFontInfo(&fInfo);
  239.  
  240.         gHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
  241.         gLnAscent = fInfo.ascent;
  242.         gWidMax = fInfo.widMax;
  243.         SetPt(&gViewSize, (2 * kWWHMargin) + (gPerLine * fInfo.widMax), (2 * kWWVMargin) + (gHeight * gLines));
  244.  
  245.         //scroll bars
  246.         for ( VHSelect vhs = v; vhs <= h; ++ vhs ) {
  247.             gSBars[vhs] = NewControl(gDebugWindowPtr, &gDebugWindowPtr->portRect, "\p", false, 0, 0, 1, scrollBarProc, 0);
  248.         }
  249.  
  250.         gScrollOffset.v = gScrollOffset.h = 0;
  251.  
  252.         //put the scroll bars in the right place
  253.         WWGrown();
  254.  
  255.         //force an update
  256.         WWUpdateEvent();
  257.  
  258.         //scroll to the end, in case there is some information that needs to be displayed
  259.         SetCtlValue(gSBars[v], LONG_MAX);
  260.         WWDoScrolling();
  261.     }
  262.     SetPort(savePort);
  263. }
  264.  
  265. #pragma segment WWInit
  266. void WWNewDefault(void)
  267. {    Rect    aRect;
  268.     Str255        title ;
  269.  
  270.     SetRect (&aRect, 16, 40, 16+6*80+16, 40+12*36);
  271.     PLstrcpy ( title, (StringPtr) CurApName );
  272.     PLstrcat ( title, "\p Debug Window");
  273.     
  274.     WWNew (aRect, title, true, true, 1, 9);
  275. }
  276.  
  277.  
  278.  
  279. #pragma segment WWSeg
  280. void WWActivateEvent(short modifiers)
  281. {    Rect r;
  282.         GrafPtr        savePort;
  283.  
  284.     GetPort(&savePort);
  285.  
  286.     WindowFocus();
  287.  
  288.     r = qd.thePort->portRect;
  289.  
  290.     if ( modifiers & 0x01 )
  291.     {
  292.         ShowControl ( gSBars[v] );
  293.         ShowControl ( gSBars[h] );
  294.     }
  295.     else
  296.     {
  297.         HideControl ( gSBars[v] );
  298.         HideControl ( gSBars[h] );
  299.     }
  300.  
  301.     DrawGrowIcon(gDebugWindowPtr);
  302.  
  303.     SetPort(savePort);
  304. }
  305.  
  306.  
  307. #pragma segment WWSeg
  308. void WWAddText(Ptr textBuf, long byteCount)
  309. {
  310.     char const BS = 8;
  311.     Boolean gotEOL;
  312.     QDByte        b;
  313.     Ptr        startPtr;
  314.     long        startCount;
  315.     PenState        ps;
  316.     GrafPtr        savePort;
  317.     Boolean        deleted;
  318.     Rect        r;
  319.  
  320.     long        count;
  321.     long        filePos ;
  322.     
  323.     if (gWrToFile)
  324.         if (gGotRefNum)
  325.         {
  326.             count = byteCount;
  327.             if ( FSWrite(gRefNum, &count, textBuf) != noErr )
  328.             {
  329.             }
  330.             if ( GetFPos (gRefNum, &filePos) == noErr) 
  331.                 if ( SetEOF (gRefNum, filePos) == noErr ) 
  332.                     WWFlushOutputFile();
  333.         }
  334.  
  335.     if (gWrToWindow)
  336.     {
  337.         if (gDebugWindowPtr != NULL)
  338.             GetPort(&savePort);
  339.  
  340.         deleted = false;
  341.  
  342.         while ( byteCount > 0){
  343.             gotEOL = false;
  344.             startPtr = textBuf;
  345.             startCount = byteCount;
  346.  
  347.             while ( (byteCount > 0) && (gPos < gPerLine) && (!gotEOL)){
  348.                 b = (*QDPtr(textBuf));
  349.                 byteCount = byteCount - 1;
  350.                 textBuf = Ptr(((long)textBuf) + 1);
  351.  
  352.                 if (b == '\n')
  353.                     gotEOL = true;
  354.                 else if (b != BS)
  355.                 {
  356.                     (*gText)[gLast+gPos++] = b;
  357.                     gPos = gPos + 1;
  358.                 } 
  359.                 else if (gPos > 0)  // Backspace -- don't backspace past beginning of line!
  360.                 {
  361.                     SetRect(&r, gEndOfText.h - gWidMax, gEndOfText.v - gLnAscent, gEndOfText.h, gEndOfText.v + gHeight - gLnAscent);
  362.                     gEndOfText.h = gEndOfText.h - gWidMax;
  363.  
  364.                     if (gDebugWindowPtr != NULL)
  365.                     {
  366.                         ContentFocus();
  367.                         EraseRect(&r);
  368.                     }
  369.  
  370.                     gPos--;
  371.                     deleted = true;
  372.                 }                
  373.                 else
  374.                     deleted = true;
  375.                 }
  376.  
  377.             if (!deleted && (gDebugWindowPtr != NULL))
  378.             {
  379.                 ContentFocus();
  380.                 MoveTo(gEndOfText.h, gEndOfText.v);
  381.                 DrawText(QDPtr(startPtr), 0, (short) (startCount - byteCount - gotEOL) );
  382.                 GetPenState(&ps);
  383.                 gEndOfText = ps.pnLoc;
  384.             }
  385.  
  386.             if ((gPos >= gPerLine) || gotEOL)
  387.             {
  388.                 (*gLineLens)[gLast / gPerLine] = gPos;    //remember # characters in this line
  389.  
  390.                 WWNewLine();
  391.                 if ((byteCount > 0) && (!gotEOL))
  392.                 {
  393.                     (*gText)[gLast] = '…';
  394.                     gPos = 1;
  395.                 }
  396.             }
  397.         }
  398.  
  399.         (*gLineLens)[gLast / gPerLine] = gPos;
  400.  
  401.         if (gDebugWindowPtr != NULL)
  402.             SetPort(savePort);
  403.     }
  404. }
  405.  
  406. void WWFlushOutputFile(void)
  407. {
  408.     if ( gWrToFile )
  409.     {    ParamBlockRec    pb;
  410.  
  411.         pb.ioParam.ioRefNum = gRefNum;
  412.         
  413.         PBFlushFileSync(&pb);
  414.     }
  415. }
  416.  
  417.  
  418. #pragma segment WWSeg
  419. long WWBaseLine(short ln)
  420. {
  421.     return kWWVMargin + (ln - 1) * gHeight;
  422. }
  423.  
  424.  
  425. #pragma segment WWSeg
  426. void WWDoScrolling(void)
  427. {    Point newOffset;
  428.     Point delta;
  429.         
  430.     newOffset.v = GetCtlValue(gSBars[v]);
  431.     delta.v = gScrollOffset.v - newOffset.v;
  432.     newOffset.h = GetCtlValue(gSBars[h]);
  433.     delta.h = gScrollOffset.h - newOffset.h;
  434.  
  435.     if ((delta.h != 0) || (delta.v != 0))
  436.         {
  437.         ContentFocus();
  438.  
  439.         ScrollRect(&qd.thePort->portRect, delta.h, delta.v, gARgn);
  440.         gScrollOffset = newOffset;
  441.  
  442.         InvalRgn(gARgn);
  443.  
  444.         WWUpdateEvent();
  445.         }
  446. }
  447.  
  448.  
  449. #pragma segment WWSeg
  450. void WWDraw(void)
  451. {    
  452.     short        y;
  453.     long        start;
  454.     long        line;
  455.     PenState        ps;
  456.  
  457.     y = kWWVMargin;            //initial y corodinate
  458.  
  459.     start = gFirst;            //offset to first character of next line to draw
  460.     line = start / gPerLine; //index into gLineLens array for next line to draw; always start / gPerLine
  461.  
  462.     for ( short i = 1; i <= gLines; ++i )
  463.     {
  464.         MoveTo(kWWHMargin, y);
  465.  
  466.         HLock(Handle(gText));
  467.         DrawText(QDPtr((*gText)), (short) start, (short) (*gLineLens)[line]);
  468.         HUnlock(Handle(gText));
  469.  
  470.         y += gHeight;
  471.         start = start + gPerLine;
  472.         line++;
  473.  
  474.         if (start == gTotal)
  475.         {
  476.             start = line = 0;
  477.         }
  478.     }
  479.  
  480.     GetPenState(&ps);            //remember position of last character drawn
  481.     gEndOfText = ps.pnLoc;
  482. }
  483.  
  484.  
  485. #pragma segment WWSeg
  486. void WWEndForce(void)
  487. {
  488.     if (gForcePtr > 0)
  489.     {
  490.         gWrToWindow = gForceStack[gForcePtr].toWindow;
  491.         gWrToFile = gForceStack[gForcePtr].toFile;
  492.         gForcePtr--;
  493.     }
  494. }
  495.  
  496.  
  497. #pragma segment WWSeg
  498. void WWForceOutput(short wrToWindow, short wrToFile)
  499. {
  500.     if (gForcePtr < kForceDepth)
  501.     {
  502.         gForcePtr++;
  503.  
  504.         gForceStack[gForcePtr].toWindow = gWrToWindow;
  505.         gForceStack[gForcePtr].toFile = gWrToFile;
  506.  
  507.         if (wrToWindow != forceUnchanged)
  508.             gWrToWindow = wrToWindow == forceOn;
  509.  
  510.         if (wrToFile != forceUnchanged )
  511.             gWrToFile = wrToFile == forceOn;
  512.     }
  513. }
  514.  
  515.  
  516. #pragma segment WWSeg
  517. void WWGrown(void)
  518. {    Rect        r;
  519.         ControlHandle        anSBar;
  520.         short        newMax;
  521.         GrafPtr        savePort;
  522.  
  523.     GetPort(&savePort);
  524.  
  525.     WindowFocus();
  526.     SetRect (&r, 0, 0, 0, 0 );
  527.     ClipRect(&r);
  528.  
  529.     for (VHSelect vhs = v; vhs <= h; ++vhs )
  530.     {
  531.         anSBar = gSBars[vhs];
  532.  
  533.         r = qd.thePort->portRect;
  534.  
  535.         // Calculate new position of scroll bar
  536.         (( short *) &r.top)[vhs] = (( short *) &r.top)[vhs] - 1;
  537.         (( short *) &r.top)[gOrthogonal[vhs]] = (( short *) &r.bottom)[gOrthogonal[vhs]] - 15;
  538.         (( short *) &r.bottom)[vhs] = (( short *) &r.bottom)[vhs] - 14;
  539.         (( short *) &r.bottom)[gOrthogonal[vhs]] = (( short *) &r.top)[gOrthogonal[vhs]] + 16;
  540.  
  541.         //Move the scroll bar
  542.         MoveControl(anSBar, r.left, r.top);
  543.         SizeControl(anSBar, r.right-r.left, r.bottom-r.top);
  544.  
  545.         if ( vhs == v )
  546.             newMax = gViewSize.v - (r.bottom - r.top);
  547.         else
  548.             newMax = gViewSize.h - (r.right - r.left );
  549.         
  550.         if (newMax < 0)
  551.             newMax = 0;
  552.         SetCtlMax(anSBar, newMax);
  553.     }
  554.  
  555.     WWInvalGrowBox();
  556.  
  557.     WWDoScrolling();    //in case we are showing too much white space
  558.  
  559.     SetPort(savePort);
  560. }
  561.  
  562.  
  563. #pragma segment WWSeg
  564. void WWInvalGrowBox(void)
  565. {    Rect     r;
  566.  
  567.     r = qd.thePort->portRect;
  568.     r.top = r.bottom - 15;
  569.     r.left = r.right - 15;
  570.  
  571.     InvalRect(&r);
  572. }
  573.  
  574.  
  575. #pragma segment WWSeg
  576. void WWMouseDown(short where, Point pt, short modifiers)
  577. {    GrafPtr        savePort;
  578.     ((void*) &modifiers);
  579.     
  580.     GetPort(&savePort);
  581.  
  582.     switch (where) {
  583.         case inDrag:
  584.             DragWindow(gDebugWindowPtr, pt, &gStdDrag);
  585.             break;
  586.             
  587.         case inGrow:
  588.             WindowFocus();
  589.  
  590.             long growResult = GrowWindow(gDebugWindowPtr, pt, &gStdSize);
  591.             if (growResult != 0)
  592.             {    short newH = (short) (growResult & 0xffff );
  593.                 short newV = (short) (growResult >> 16);
  594.                 WWInvalGrowBox();
  595.                 SizeWindow(gDebugWindowPtr, newH, newV, true);
  596.                 WWGrown();
  597.             }
  598.             break;
  599.             
  600.         case inGoAway:
  601.             if (TrackGoAway(gDebugWindowPtr, pt))
  602.                 HideWindow(gDebugWindowPtr);
  603.             break;
  604.             
  605.         case inContent:
  606.             if (gDebugWindowPtr == FrontWindow())
  607.             {
  608.                 WindowFocus();
  609.                 GlobalToLocal(&pt);
  610.                 
  611.                 ControlHandle whichControl;
  612.                 long partCode = FindControl(pt, gDebugWindowPtr, &whichControl);
  613.                 switch (partCode) 
  614.                 {
  615.                     case inUpButton:
  616.                     case inDownButton:
  617.                     case inPageUp:
  618.                     case inPageDown:
  619.                         partCode = TrackControl(whichControl, pt, (ProcPtr) &WWTrackScroll);
  620.                         break;
  621.                         
  622.                     case inThumb:
  623.                         partCode = TrackControl(whichControl, pt, NULL);
  624.                         WWDoScrolling();
  625.                         break;
  626.                     
  627.                     case 0:
  628.                         break;
  629.                 }
  630.             }
  631.             else
  632.                 SelectWindow(gDebugWindowPtr);
  633.                 
  634.             break;            
  635.     }
  636.  
  637.     SetPort(savePort);
  638. }
  639.  
  640.  
  641. #pragma segment WWSeg
  642. void WWNewLine(void)
  643. {    GrafPtr         savePort;
  644.         Point        pt;
  645.         Rect        r;
  646.  
  647.     GetPort(&savePort);
  648.  
  649.     SetPt(&pt, kWWHMargin, gEndOfText.v);
  650.  
  651.     if ( gScrollWindowWhenTextIsAdded )
  652.         WWShowPoint(pt);
  653.  
  654.     gLast = gFirst;
  655.     gPos = 0;
  656.     (*gLineLens)[gLast / gPerLine] = gPos;    //remember # characters in new line
  657.  
  658.     gFirst = gFirst + gPerLine;
  659.     if (gFirst == gTotal)
  660.         gFirst = 0;
  661.  
  662.     SetPt(&gEndOfText, kWWHMargin, (short) WWBaseLine(gLines));
  663.  
  664.     if ( gDebugWindowPtr )
  665.     {
  666.         ContentFocus();
  667.         
  668.         SetRect(&r, kWWHMargin, kWWVMargin - gLnAscent, gViewSize.h, gEndOfText.v + gHeight - gLnAscent);
  669.         ScrollRect(&r, 0, -gHeight, gARgn);
  670.         InvalRgn(gARgn);
  671.  
  672.         WWUpdateEvent();
  673.     }
  674.  
  675.     SetPort(savePort);
  676. }
  677.  
  678.  
  679. OSErr WWRedirect(short vRefNum, long dirID, Str255 fileNameBase)
  680. {    OSErr         err;
  681.     Boolean        append;
  682.     long        x;
  683.  
  684.     if (gGotRefNum)
  685.     {
  686.         // Truncate the file to current position
  687.         err = GetFPos(gRefNum, &x);
  688.         err = SetEOF(gRefNum, x);
  689.  
  690.         if (FSClose(gRefNum) != noErr) /*??? error closing file ???*/;
  691.             if (FlushVol(NULL, gVRefNum) != noErr) /*??? Another fine mess ???*/;
  692.                 gGotRefNum = false;
  693.     }
  694.     
  695.     Str255 fileName;
  696.     PLstrcpy ( fileName, fileNameBase );
  697.     
  698.     append = false;
  699.  
  700.     if (PLstrlen(fileName) > 0 )
  701.     {
  702.         err = HCreate(vRefNum, dirID, fileName, 'MACA', 'TEXT');
  703.  
  704.         if ((err == noErr) || (err == dupFNErr))
  705.         {
  706.             err = HOpen(vRefNum, dirID, fileName, fsRdWrPerm, &gRefNum);
  707.             gVRefNum = vRefNum;
  708.  
  709.             gGotRefNum = err == noErr;
  710.  
  711.             if (gGotRefNum)
  712.                 if (append)
  713.                 {
  714.                     err = GetEOF(gRefNum, &x);
  715.                     err = SetFPos(gRefNum, fsFromStart, x);
  716.                 }
  717.                 else
  718.                     err = SetEOF (gRefNum, 0);
  719.             else
  720.                 err = noErr;
  721.         }
  722.     }
  723.     return noErr;
  724. }
  725.  
  726. void WWScroll(short howManyLines)
  727. {    short     val;
  728.         GrafPtr        savePort;
  729.  
  730.     GetPort(&savePort);
  731.     val = GetCtlValue(gSBars[v]);
  732.     if (((howManyLines < 0) && (val > GetCtlMin(gSBars[v]))) ||
  733.        ((howManyLines > 0) && (val < GetCtlMax(gSBars[v]))))
  734.         {
  735.         SetCtlValue(gSBars[v], val + howManyLines * gHeight);
  736.         WWDoScrolling();
  737.         }
  738.     SetPort(savePort);
  739. }
  740.  
  741.  
  742. void WWShowPoint(Point pt)
  743. {    Point     minToSee;
  744.         short        deltaCd;
  745.  
  746.     if (gDebugWindowPtr != NULL)
  747.         {
  748.         WindowFocus();
  749.  
  750.         SetPt(&minToSee, 50, gHeight);
  751.  
  752.         // the following code is actually better than writing a loop with VHSelect
  753.         deltaCd = pt.v + minToSee.v - (qd.thePort->portRect.bottom - 15 + gScrollOffset.v);
  754.         if (deltaCd <= 0)
  755.         {
  756.             deltaCd = pt.v - minToSee.v - (qd.thePort->portRect.top + gScrollOffset.v);
  757.             if (deltaCd >= 0)
  758.                 deltaCd = 0;
  759.         }
  760.         SetCtlValue(gSBars[v], GetCtlValue(gSBars[v]) + deltaCd);
  761.  
  762.         deltaCd = pt.h + minToSee.h - (qd.thePort->portRect.right - 15 + gScrollOffset.h);
  763.         if (deltaCd <= 0)
  764.         {
  765.             deltaCd = pt.h - minToSee.h - (qd.thePort->portRect.left + gScrollOffset.h);
  766.             if (deltaCd >= 0)
  767.                 deltaCd = 0;
  768.         }
  769.         SetCtlValue(gSBars[h], GetCtlValue(gSBars[h]) + deltaCd);
  770.  
  771.         WWDoScrolling();
  772.         }
  773. }
  774.  
  775.  
  776. #pragma segment WWSeg
  777. void WWTrackScroll(ControlHandle aControl, short partCode)
  778. {    Boolean         up;
  779.         short        ctlValue;
  780.         VHSelect        vhs;
  781.         Rect        r;
  782.         short        delta;
  783.  
  784.     if (partCode != 0)
  785.         {
  786.         up = (partCode == inUpButton) || (partCode == inPageUp);
  787.         ctlValue = GetCtlValue(aControl);
  788.  
  789.       //avoid flicker in setting thumb, if (user tries to scroll past end
  790.         if ((up && (ctlValue > GetCtlMin(aControl))) ||
  791.            (!up && (ctlValue < GetCtlMax(aControl))))
  792.             {
  793.             r = (*aControl)->contrlRect;   //heap may compact when we call LongerSide
  794.             vhs = LongerSide(r);          //this tells us which way we are scrolling
  795.             
  796.             if ((partCode == inPageUp) || (partCode == inPageDown))
  797.                 if ( vhs == v )
  798.                     delta = gDebugWindowPtr->portRect.bottom - gDebugWindowPtr->portRect.top;
  799.                 else
  800.                     delta = gDebugWindowPtr->portRect.right - gDebugWindowPtr->portRect.left;
  801.             else
  802.                 delta = gHeight;
  803.  
  804.             if (up)
  805.                 delta = - delta;
  806.  
  807.             SetCtlValue(aControl, ctlValue + delta);
  808.             WWDoScrolling();
  809.  
  810.             WindowFocus();
  811.             }
  812.         }
  813. }
  814.  
  815.  
  816. #pragma segment WWSeg
  817. void WWUpdateEvent(void)
  818. {    GrafPtr         savePort;
  819.         RgnHandle        saveSaveVisRgn;
  820.         RgnHandle        saveVisRgn;
  821.  
  822.     if ((gDebugWindowPtr != NULL) &&
  823.         (!EmptyRgn( ((WindowPeek)gDebugWindowPtr)->port.visRgn))) 
  824.     {
  825.         GetPort(&savePort);
  826.  
  827.         saveSaveVisRgn = NewRgn();
  828.         saveVisRgn = GetSaveVisRgn();
  829.  
  830.         CopyRgn(saveVisRgn, saveSaveVisRgn);
  831.  
  832.         BeginUpdate(gDebugWindowPtr);
  833.  
  834.         WindowFocus();
  835.  
  836.         EraseRect(&qd.thePort->portRect);
  837.  
  838.         DrawGrowIcon(gDebugWindowPtr);
  839.         DrawControls(gDebugWindowPtr);
  840.  
  841.         ContentFocus();
  842.         WWDraw();
  843.  
  844.         EndUpdate(gDebugWindowPtr);
  845.  
  846.         CopyRgn(saveSaveVisRgn, saveVisRgn);
  847.         DisposeRgn(saveSaveVisRgn);
  848.  
  849.         SetPort(savePort);
  850.     }
  851. }
  852.  
  853.  
  854. #pragma segment WWSeg
  855. char WWReadCh(void)
  856. {    GrafPtr         savePort;
  857.         char        ch;
  858.         EventRecord        anEvent;
  859.         Rect        r;
  860.  
  861.     GetPort(&savePort);
  862.  
  863.     ContentFocus();
  864.  
  865.     SetRect(&r, gEndOfText.h, gEndOfText.v - gLnAscent, gEndOfText.h + gWidMax, gEndOfText.v + gHeight - gLnAscent);
  866.  
  867.     FillRect(&r, &qd.black);
  868.     while ( GetOSEvent(keyDownMask+autoKeyMask, &anEvent))
  869.         ;
  870.     EraseRect(&r);
  871.  
  872.     ch = char(((anEvent.message) & charCodeMask));
  873.  
  874.     SetPort(savePort);
  875.  
  876.     return ch;
  877. }
  878.  
  879.  
  880. #pragma segment WWSeg
  881. long WWReadLn(Ptr buffer, short byteCount)
  882. {    
  883.     const char CR = 13;
  884.     const char BS = 8;
  885.  
  886.     short len = 0;
  887.     char ch;
  888.     do {
  889.         ch = WWReadCh();
  890.         if (ch != BS )
  891.         {
  892.             WWAddText(&ch, 1);
  893.             buffer[len++] = ch;
  894.         }
  895.         else if (len > 0)
  896.         {
  897.             WWAddText(&ch, 1);
  898.             buffer[--len] = ' ';
  899.         }
  900.     } while ( ! ( (ch==CR) || (len == byteCount)) );
  901.  
  902.    return len;
  903. }
  904.  
  905.  
  906. void IDUWritelnWindow(void) //Writeln UWritelnWindow's compile time.
  907. {
  908. //    Writeln('UWritelnWindow of ', COMPDATE, ' & ', COMPTIME);
  909. }
  910.  
  911.  
  912. long    wwFAccess(Ptr fName, long opCode, long arg );
  913. long    wwClose(long refNum);
  914. long    wwRead(long fdesc, long bufp, long count );
  915. long    wwWrite(long fdesc, long bufP, long count);
  916. long    wwIoctl(long fdesc, long request, long arg );
  917.  
  918. long    _addDevHandler( long slot, Ptr dvName, ProcPtr dvFAccess, ProcPtr dvClose, ProcPtr dvRead, ProcPtr dvWrite, ProcPtr dvIoctl );
  919.         
  920. void WWInstall(void)
  921. {    long  slot = _addDevHandler(CODEV, 0,
  922.                     (ProcPtr) wwFAccess, (ProcPtr) wwClose, (ProcPtr) wwRead, (ProcPtr) wwWrite, (ProcPtr) wwIoctl );
  923.     
  924.     setvbuf ( stdout, nil, 64, 100 );
  925. }
  926.  
  927.  
  928. /*
  929. --    Paul's Writeln routines  ----------------------------------------------------------------
  930. */
  931. Boolean WWEvent(EventRecord& event )
  932. {
  933.     WindowPtr        WindowPointedTo;        //window where the mouse is
  934.     Point        MouseLoc;
  935.     short        WindoPart;        //component of window where mouse is
  936.  
  937.     switch ( event.what )
  938.     {
  939.         case mouseDown:
  940.             {
  941.                 MouseLoc = event.where;
  942.                 WindoPart = FindWindow(MouseLoc, &WindowPointedTo);
  943.  
  944.                 if ( (WindowPointedTo == gDebugWindowPtr))
  945.                     {
  946.                         if (WindowPointedTo != FrontWindow())
  947.                             SelectWindow(WindowPointedTo);
  948.                         else
  949.                             WWMouseDown(WindoPart, MouseLoc, event.modifiers);
  950.                         return true;
  951.                     }
  952.             }
  953.             break;
  954.             
  955.         case activateEvt:
  956.             if (WindowPtr(event.message) == gDebugWindowPtr)
  957.                 {
  958.                     WWActivateEvent(event.modifiers);
  959.                     return true;
  960.                 }
  961.             break;
  962.             
  963.         case updateEvt:
  964.             if (WindowPtr(event.message) == gDebugWindowPtr)
  965.                 {
  966.                     WWUpdateEvent();
  967.                     return true;
  968.                 }
  969.             break;
  970.     }
  971. } //WWEvent
  972.  
  973. /*
  974. --    end Writeln routines  ------------------------------------------------------------
  975. */
  976.  
  977. /*
  978. -- Keith's WriteLineWindow routines --------------------------------------------------
  979. */
  980. #if 0
  981.  
  982. void WWAddDate(void)
  983. VAR
  984.     long        dateTime ;
  985.     Str255        tempStr255 ;
  986. {
  987.     GetDateTime (dateTime);
  988.     IUDateString(dateTime, shortDate, tempStr255);
  989.     write (tempStr255, ' ');
  990. }
  991.  
  992. void WWAddTime(void)
  993. VAR
  994.     long        dateTime ;
  995.     Str255        tempStr255 ;
  996. {
  997.     GetDateTime (dateTime);
  998.     IUTimeString(dateTime, true, tempStr255);
  999.     write (tempStr255, ' ');
  1000. }
  1001.  
  1002. void WWAddDateTime(void)
  1003. {
  1004.     WWAddDate();
  1005.     WWAddTime();
  1006. }
  1007. #endif
  1008.  
  1009. void WWAddEncodedText (Ptr dataPtr, long size)
  1010. {
  1011.     for ( short index = 0; index < size; ++index )
  1012.     {
  1013.         char c = dataPtr[index];
  1014.         switch ( c )
  1015.         {
  1016.             case  0: case 128: c = 'ø'; break;
  1017.             case  8: case 136: c = 'Δ'; break;
  1018.             
  1019.             case 10: case 138: c = '◊'; break;
  1020.             case 13: case 141: c = '¬'; break;
  1021.             case 222: c = '∞'; break;
  1022.         }
  1023.         WWAddText ( &c, 1 );
  1024.     }
  1025. }
  1026.  
  1027. inline long IntegerMax (long a, long b )
  1028. {
  1029.     return ( a > b ) ? a : b;
  1030. }
  1031.  
  1032. Str255& NumToHexStringF(long theNumber)
  1033. {    Str255        returnStr;
  1034.  
  1035.     returnStr[0] = sprintf ((char*) &returnStr[1], "%8x", theNumber );
  1036.     
  1037.     return returnStr;
  1038. }
  1039.  
  1040. /***********************************|****************************************/
  1041.  
  1042. void WWAddHexData (Ptr dataPtr, short dataSize )
  1043. {
  1044.     long        index ;
  1045.     Str255        result ;
  1046.     short        len ;
  1047.     char        byte ;
  1048.  
  1049.     if ( !dataPtr )
  1050.     {        
  1051.         DebugStr ("\pNo data dump, NULL data ptr");
  1052.         return;
  1053.     }
  1054.  
  1055.     if ( dataSize <= 0 )
  1056.     {
  1057.         DebugStr ("\pNo data dump, datesize <= 0");
  1058.         return;
  1059.     }
  1060.     
  1061.     long offset = 0;
  1062.  
  1063.     while (offset < dataSize)
  1064.     {
  1065.         #if 0
  1066.         WWAddText (
  1067.         write ( NumToHexStringF (offset), ':');
  1068.  
  1069.         // Put it into a Str255 because it's faster to add one string to the window than it is to add 16 
  1070.         result = '';
  1071.         for index = 0 to 15
  1072.         do
  1073.             if offset + index < dataSize
  1074.             then
  1075.                 begin
  1076.                 len = length(result);
  1077.                 byte = BytePtr(((long)dataPtr)+offset+index)^;
  1078.                 result[len+1] = gHexStr[ ((byte) >> 4)];
  1079.                 result[len+2] = gHexStr[ ((byte) & 0xF)];
  1080.                 result[len+3] = ' ';
  1081.                 //$PUSH*/ /*$R-*/ result[0] = ((char)(len + 3)); /*$POP
  1082.                 end
  1083.             else
  1084.                 begin
  1085.                 result[len+1] = ' ';
  1086.                 result[len+2] = ' ';
  1087.                 result[len+3] = ' ';
  1088.                 //$PUSH*/ /*$R-*/ result[0] = ((char)(len + 3)); /*$POP
  1089.                 end();
  1090.         write (result, '| ');
  1091.  
  1092.         WWAddEncodedText ( Ptr(((long)dataPtr)+offset), IntegerMax(dataSize - offset, 16));
  1093.  
  1094.         offset = offset + 16;
  1095.         #endif
  1096.     }
  1097. }
  1098.  
  1099. void WWShowWindow(void)
  1100. {
  1101.     ShowWindow (gDebugWindowPtr);
  1102. }