home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / apps.to.go / Kibitz / KibitzWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-06  |  16.6 KB  |  640 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        kibitzwindow.c
  5. ** Written by:  Eric Soldan
  6. **
  7. ** Copyright © 1990-1992 Apple Computer, Inc.
  8. ** All rights reserved. */
  9.  
  10.  
  11.  
  12. /*****************************************************************************/
  13.  
  14.  
  15.  
  16. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  17. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  18. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  19.  
  20. #ifndef __ERRORS__
  21. #include <Errors.h>
  22. #endif
  23.  
  24. #ifndef __FONTS__
  25. #include <Fonts.h>
  26. #endif
  27.  
  28. #ifndef __GWLAYERS__
  29. #include <GWLayers.h>
  30. #endif
  31.  
  32. #ifndef __RESOURCES__
  33. #include <Resources.h>
  34. #endif
  35.  
  36. #ifndef __TEXTEDITCONTROL__
  37. #include <TextEditControl.h>
  38. #endif
  39.  
  40. #ifndef __TOOLUTILS__
  41. #include <ToolUtils.h>
  42. #endif
  43.  
  44. #ifndef __UTILITIES__
  45. #include <Utilities.h>
  46. #endif
  47.  
  48.  
  49.  
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. extern short    gPrintPage;                    /* Non-zero means we are printing. */
  55. extern LayerObj    gBoardLayer;
  56. extern short    gClearSquare;
  57.  
  58. Boolean            gDescriptive;
  59. CIconHandle        gPieceCIcon[26];
  60.  
  61. static short        gLastPiece[120];
  62. static RgnHandle    gLastColorRgn;
  63.  
  64.  
  65.  
  66. /*****************************************************************************/
  67. /*****************************************************************************/
  68.  
  69.  
  70.  
  71. /* This function adds the application's controls to a window. */
  72.  
  73. #pragma segment Window
  74. OSErr    AppNewWindowControls(FileRecHndl frHndl, WindowPtr window, WindowPtr behind)
  75. {
  76.     WindowPtr        oldPort;
  77.     OSErr            err;
  78.     TEHandle        mssgIn, mssgOut;
  79.     CTEDataHndl        teData;
  80.     ControlHandle    sendMssg, beepOnMove, beepOnMssg, viewCtl;
  81.     Rect            ctlRect, brdrRect, viewRect, destRect;
  82.     ControlHandle    gameSlider, whiteStarts, blackStarts, resign, draw;
  83.     ControlHandle    record, sendSnd;
  84.     Handle            textHndl;
  85.     Boolean            messageDoc;
  86.     short            mode;
  87.     TextStyle        styl;
  88.     Handle            finf;
  89.  
  90.     GetPort(&oldPort);
  91.     SetPort(window);
  92.  
  93.     SetRect(&ctlRect,
  94.             kBoardWidth + 20,
  95.             35,
  96.             rWindowWidth - 20,
  97.             kBoardHalfHeight + kBoardVOffset - 1
  98.     );
  99.  
  100.     brdrRect = viewRect = ctlRect;
  101.     InsetRect(&viewRect, 4, 4);
  102.     destRect = viewRect;
  103.     destRect.right -= 2;
  104.         /* This fixes a TextEdit problem where the view has to be a little
  105.         ** outside the dest on the right, or else characters are clipped.
  106.         */
  107.  
  108.     finf = GetResource('finf', 128);
  109.     styl.tsFont = (*(short **)finf)[1];
  110.     styl.tsSize = (*(short **)finf)[3];
  111.  
  112.     TextFont(styl.tsFont);
  113.     TextSize(styl.tsSize);
  114.  
  115.     CTENew(rTECtl,                /* viewCtl of resID for TextEdit control. */
  116.            true,                    /* Visible.                                  */
  117.            window,                    /* Window to hold TERecord.                  */
  118.            &mssgIn,                    /* Return handle for TERecord.               */
  119.            &ctlRect,                /* Rect for view control.                  */
  120.            &destRect,                /* destRect for TERecord                  */
  121.            &viewRect,                /* viewRect for TERecord                  */
  122.            &brdrRect,                /* Used to frame a border.                  */
  123.            32000,                    /* Maximum TextEdit document length.      */
  124.            cteReadOnly+cteVScroll    /* TERecord is regular read-only.          */
  125.     );
  126.     if (mssgIn)
  127.         TESetStyle((doFont | doSize), &styl, false, mssgIn);
  128.  
  129.     OffsetRect(&ctlRect, 0, kBoardHalfHeight - 38);
  130.  
  131.     messageDoc = false;
  132.     if ((*frHndl)->doc.myColor == kMessageDoc) messageDoc = true;
  133.     if (messageDoc)
  134.         SetRect(&ctlRect, -1, -1, rWindowWidth - 14, rWindowHeight + 1);
  135.             /* When the window is a message document, the whole window is the outbox.
  136.             ** This keep the actual differences between window kinds to a minimum,
  137.             ** while altering the appearance greatly. */
  138.  
  139.     brdrRect = viewRect = ctlRect;
  140.     InsetRect(&viewRect, 4, 4);
  141.     destRect = viewRect;
  142.     destRect.right -= 2;
  143.  
  144.     mode = cteVScroll;
  145.     if (behind == (WindowPtr)-1)
  146.         if (!(*frHndl)->doc.arrangeBoard)
  147.             mode |= cteActive;
  148.     CTENew(rTECtl, true, window, &mssgOut, &ctlRect, &destRect, &viewRect, &brdrRect, 32000, mode);
  149.  
  150.     if (mssgOut) {
  151.         TESetStyle((doFont | doSize), &styl, false, mssgOut);
  152.  
  153.         viewCtl = CTEViewFromTE(mssgOut);
  154.         teData  = (CTEDataHndl)(*viewCtl)->contrlData;
  155.         (*teData)->mode |= cteActive;
  156.             /* Make sure that when a window is activated, the caret blinks.  We need
  157.             ** to do this because the window isn't necessarily opened as the front window.
  158.             ** If we create the TextEdit Control as the active control for a window that
  159.             ** isn't opened as the front window, then we will turn off the caret for
  160.             ** whatever window is the front window.  Al we are doing here is determining
  161.             ** that the message-out TextEdit Control will be the active control when the
  162.             ** window is first brought to the front. */
  163.     
  164.         textHndl = (Handle)(*frHndl)->doc.legalMoves;
  165.         (*frHndl)->doc.legalMoves = (MoveListHndl)CTESwapText(mssgOut, textHndl, nil, false);
  166.             /* AppOpenDocument may have placed some text for the out-box TextEdit
  167.             ** control temporarily in the legalMoves handle.  Move this text into
  168.             ** the out-box TextEdit control. */
  169.     }
  170.  
  171.     sendMssg   = GetNewControl(rSendMessage, window);
  172.     if (sendMssg) HiliteControl(sendMssg, 255);
  173.     beepOnMove = GetNewControl(rMoveNotify, window);
  174.     if (beepOnMove)  HiliteControl(beepOnMove, 255);
  175.     beepOnMssg = GetNewControl(rMssgNotify, window);
  176.     if (beepOnMssg)  HiliteControl(beepOnMssg, 255);
  177.  
  178.     whiteStarts = GetNewControl(rWhiteStarts, window);
  179.     if (whiteStarts) {
  180.         OffsetControl(whiteStarts, -4096, 0);
  181.         SetControlValue(whiteStarts, (*frHndl)->doc.startColor ^ 1);
  182.         ShowControl(whiteStarts);
  183.     }
  184.     blackStarts = GetNewControl(rBlackStarts, window);
  185.     if (blackStarts) {
  186.         OffsetControl(blackStarts, -4096, 0);
  187.         SetControlValue(blackStarts, (*frHndl)->doc.startColor);
  188.         ShowControl(blackStarts);
  189.     }
  190.  
  191.     resign      = GetNewControl(rResign, window);
  192.     draw        = GetNewControl(rDraw, window);
  193.     record  = GetNewControl(rRecordSound, window);
  194.     if (record) HiliteControl(record, 255);
  195.     sendSnd = GetNewControl(rSendSound, window);
  196.     if (sendSnd)   HiliteControl(sendSnd, 255);
  197.  
  198.     gameSlider = BoardSliderNew(window);
  199.  
  200.     (*frHndl)->doc.message[kMessageIn]  = mssgIn;
  201.     (*frHndl)->doc.message[kMessageOut] = mssgOut;
  202.     (*frHndl)->doc.sendMessage = sendMssg;
  203.     (*frHndl)->doc.beepOnMove  = beepOnMove;
  204.     (*frHndl)->doc.beepOnMssg  = beepOnMssg;
  205.     (*frHndl)->doc.gameSlider  = gameSlider;
  206.     (*frHndl)->doc.wbStart[0]  = whiteStarts;
  207.     (*frHndl)->doc.wbStart[1]  = blackStarts;
  208.     (*frHndl)->doc.resign      = resign;
  209.     (*frHndl)->doc.draw        = draw;
  210.     (*frHndl)->doc.record      = record;
  211.     (*frHndl)->doc.sendSnd     = sendSnd;
  212.  
  213.     if (
  214.         (mssgIn) &&
  215.         (mssgOut) &&
  216.         (sendMssg) &&
  217.         (beepOnMove) &&
  218.         (beepOnMssg) &&
  219.         (gameSlider) &&
  220.         (whiteStarts) &&
  221.         (blackStarts) &&
  222.         (resign) &&
  223.         (draw) &&
  224.         (record) &&
  225.         (sendSnd)
  226.     ) {
  227.         if (messageDoc) {
  228.             CTEHide(mssgIn);
  229.             HideControl(sendMssg);
  230.             MoveControl(sendMssg, 0, -4096);    /* So no border is drawn. */
  231.             HideControl(beepOnMove);
  232.             HideControl(beepOnMssg);
  233.             HideControl(gameSlider);
  234.             HideControl(whiteStarts);
  235.             HideControl(blackStarts);
  236.             HideControl(resign);
  237.             HideControl(draw);
  238.             HideControl(record);
  239.             HideControl(sendSnd);
  240.         }
  241.         AdjustGameSlider(frHndl);
  242.         err = noErr;
  243.     }
  244.     else
  245.         err = memFullErr;
  246.  
  247.     SetPort(oldPort);
  248.     return(err);
  249. }
  250.  
  251.  
  252.  
  253. /*****************************************************************************/
  254.  
  255.  
  256.  
  257. #pragma segment Window
  258. void    DrawTime(FileRecHndl frHndl)
  259. {
  260.     WindowPtr        oldPort;
  261.     Rect            clockRect;
  262.     short            clock, i, time[3];
  263.     unsigned long    timeLeft, displayTime;
  264.     Str32            pstr, timestr;
  265.  
  266.     if ((*frHndl)->doc.arrangeBoard) return;
  267.  
  268.     oldPort = SetFilePort(frHndl);
  269.  
  270.     TextMode(srcCopy);
  271.     TextFont(systemFont);
  272.     TextSize(0);
  273.     TextFace(normal);
  274.  
  275.     for (clock = 0; clock < 2; ++clock) {
  276.  
  277.         clockRect = BoardRect();
  278.  
  279.         if (clock == (*frHndl)->doc.invertBoard)
  280.             clockRect.top += 14;
  281.  
  282.         clockRect.left   = clockRect.right + 26;
  283.         clockRect.right  = clockRect.left + 70;
  284.         clockRect.bottom = clockRect.top + 14;
  285.  
  286.         timeLeft = (*frHndl)->doc.timeLeft[clock];
  287.         if (timeLeft == -1) {
  288.             EraseRect(&clockRect);
  289.             continue;
  290.         }
  291.  
  292.         if ((displayTime = (*frHndl)->doc.displayTime[clock]) > timeLeft)
  293.              displayTime = (*frHndl)->doc.displayTime[clock]  = timeLeft;
  294.  
  295.         MoveTo(clockRect.left + 6, clockRect.top + 14);
  296.  
  297.         for (i = 3; i;) {
  298.             displayTime /= 60;
  299.             time[--i] = displayTime % 60;
  300.         }
  301.         timestr[0] = 0;
  302.         for (i = 0; i < 3; ++i) {
  303.             pcpydec(pstr, time[i]);
  304.             if (pstr[0] == 1) pcat(timestr, "\p0");
  305.             pcat(timestr, pstr);
  306.             pcat(timestr, (StringPtr)"\1:\1:\1 " + (i << 1));    /* Append colon or space. */
  307.         }
  308.         DrawString(timestr);
  309.     }
  310.  
  311.     TextMode(srcOr);
  312.     SetPort(oldPort);
  313. }
  314.  
  315.  
  316.  
  317. /*****************************************************************************/
  318.  
  319.  
  320.  
  321. #pragma segment Window
  322. void    ImageBoardLines(short increment, short hOffset, short vOffset)
  323. {
  324.     short    i;
  325.  
  326.     PenNormal();
  327.     PenSize(1, 1);
  328.  
  329.     for (i = 0; i <= 8; i += increment) {
  330.         MoveTo(hOffset, vOffset + kBoardSqSize * i);
  331.         Line(kBoardSqSize * 8, 0);
  332.         MoveTo(hOffset + kBoardSqSize * i, vOffset);
  333.         Line(0, kBoardSqSize * 8);
  334.     }
  335.  
  336.     PenNormal();
  337. }
  338.  
  339.  
  340.  
  341. /*****************************************************************************/
  342.  
  343.  
  344.  
  345. /* Image the document into the current port. */
  346.  
  347. #pragma segment Window
  348. void    ImageDocument(FileRecHndl frHndl, Boolean justBoard)
  349. {
  350.     short            r, c, rr, cc, piece, pieceIconID, fnum, i;
  351.     short            gameIndex, lastFrom, lastTo, square, ss, hOffset, vOffset;
  352.     Boolean            toWindow, invertBoard, messageDoc;
  353.     LayerObj        windowLayer;
  354.     Rect            sqRect, theInk, boardRect;
  355.     GameListHndl    gameMoves;
  356.     WindowPtr        curPort;
  357.     TEHandle        te;
  358.     Point            pt;
  359.     RgnHandle        colorRgn, testRgn;
  360.     static short    teOffset;
  361.  
  362.     GetPort(&curPort);
  363.  
  364.     toWindow = (curPort == (*frHndl)->fileState.window);
  365.     if (!toWindow) gClearSquare = 0;
  366.  
  367.     messageDoc = false;
  368.     if ((*frHndl)->doc.myColor == kMessageDoc) messageDoc = true;
  369.  
  370.     colorRgn = testRgn = nil;
  371.  
  372.     hOffset = kBoardHOffset;
  373.     vOffset = kBoardVOffset;
  374.     if (gPrintPage > 0) {
  375.         theInk = curPort->portRect;
  376.         GetFNum("\pTimes", &fnum);
  377.         TextFont(fnum);
  378.         TextSize(12);
  379.         TextFace(normal);
  380.         hOffset = theInk.right - 10 - kBoardWidth;
  381.         vOffset = 10;
  382.         if (messageDoc) {
  383.             if (gPrintPage == 1) teOffset = 0;
  384.             te = (*frHndl)->doc.message[kMessageOut];
  385.             InsetRect(&theInk, 4, 4);
  386.             CTEPrint(te, &teOffset, &theInk);
  387.             if (teOffset == -1) gPrintPage = 0;
  388.             return;
  389.         }
  390.         if (curPort->portBits.rowBytes & 0x8000)
  391.             RectRgn(colorRgn = NewRgn(), &theInk);
  392.                 /* Print the board in grayscale or color if user has so chosen. */
  393.     }
  394.     else {
  395.         SetRectRgn(curPort->clipRgn, -30000, -30000, 30000, 30000);
  396.  
  397.         if (!messageDoc) {
  398.             if (!gPrintPage) ImageBoardLines(8, hOffset, vOffset);
  399.  
  400.             colorRgn = ScreenDepthRegion(8);        /* Screen of 8-bit or greater get color icon. */
  401.             pt.h = pt.v = 0;
  402.             GlobalToLocal(&pt);
  403.             OffsetRgn(colorRgn, pt.h, pt.v);        /* Localize the area that gets color icons. */
  404.  
  405.             if (!gPrintPage) SetLayerWorld(gBoardLayer);
  406.         }
  407.     }
  408.  
  409.     if (!colorRgn) colorRgn = NewRgn();
  410.     if (!testRgn)  testRgn  = NewRgn();
  411.  
  412.     if (!gLastColorRgn) gLastColorRgn = NewRgn();
  413.     if ((gPrintPage) || (!EqualRgn(colorRgn, gLastColorRgn)))
  414.         for (i = 0; i < 120; ++i) gLastPiece[i] = 0;
  415.             /* If printing, exporting a board, or if color region has changed, redraw all squares. */
  416.     CopyRgn(colorRgn, gLastColorRgn);
  417.  
  418.     invertBoard = (*frHndl)->doc.invertBoard;
  419.     lastFrom = lastTo = 0;
  420.     gameIndex = (*frHndl)->doc.gameIndex;
  421.     gameMoves = (*frHndl)->doc.gameMoves;
  422.     if (gameIndex) {
  423.         lastFrom = (**gameMoves)[gameIndex - 1].moveFrom;
  424.         lastTo   = (**gameMoves)[gameIndex - 1].moveTo;
  425.         if (!lastFrom) {
  426.             if (gameIndex > 1) {
  427.                 lastFrom = (**gameMoves)[gameIndex - 2].moveFrom;
  428.                 lastTo   = (**gameMoves)[gameIndex - 2].moveTo;
  429.             }
  430.         }
  431.     }
  432.  
  433.     if (gPrintPage < 2) {        /* If not printing, or printing first page... */
  434.         if (!messageDoc) {
  435.             for (r = 0; r < 8; ++r) {
  436.                 if (gClearSquare) r = (gClearSquare - START_IBNDS) / 10;
  437.  
  438.                 for (c = 0; c < 8; ++c) {
  439.                     if (gClearSquare) c = gClearSquare - START_IBNDS - 10 * r;
  440.                 
  441.                     piece = (*frHndl)->doc.theBoard[square = START_IBNDS + 10 * r + c];
  442.                     if (gClearSquare) piece = EMPTY;
  443.                     if (piece < WK) piece += KSIDEPIECE;
  444.                     if (piece > BK) piece -= KSIDEPIECE;
  445.                     pieceIconID = piece + KING;
  446.     
  447.                     rr = r;
  448.                     cc = c;
  449.                     if (invertBoard) {
  450.                         rr = 7 - r;
  451.                         cc = 7 - c;
  452.                     }
  453.                     ss = START_IBNDS + 10 * rr + cc;
  454.  
  455.                     if ((rr + cc) & 0x01) pieceIconID += 13;
  456.  
  457.                     if (!gPieceCIcon[pieceIconID])
  458.                         gPieceCIcon[pieceIconID] = ReadCIcon(pieceIconID + 257);
  459.  
  460.                     sqRect.top    = vOffset + kBoardSqSize * rr + 1;
  461.                     sqRect.left   = hOffset + kBoardSqSize * cc + 1;
  462.                     sqRect.bottom = sqRect.top  + 32;
  463.                     sqRect.right  = sqRect.left + 32;
  464.  
  465.                     if (gLastPiece[ss] != pieceIconID + 257) {
  466.                         gLastPiece[ss] = pieceIconID + 257;
  467.                         if (!RectInRgn(&sqRect, colorRgn))        /* If 1-bit, draw b/w icon. */
  468.                             DrawCIconByDepth(gPieceCIcon[pieceIconID], sqRect, 1, false);
  469.                         else {        /* Draw some combo of color and b/w icon. */
  470.                             RectRgn(testRgn, &sqRect);
  471.                             SectRgn(testRgn, colorRgn, testRgn);
  472.                             for (;;) {
  473.                                 if ((*testRgn)->rgnSize == 10) {
  474.                                     if (EqualRect(&((*testRgn)->rgnBBox), &sqRect)) {
  475.                                         DrawCIconByDepth(gPieceCIcon[pieceIconID], sqRect, 8, false);
  476.                                         break;            /* Icon completely on color monitor. */
  477.                                     }
  478.                                 }
  479.                                 DrawCIconByDepth(gPieceCIcon[pieceIconID], sqRect, 1, false);
  480.                                     /* Icon is across two monitors, so first draw it b/w. */
  481.                                 SetClip(testRgn);
  482.                                 DrawCIconByDepth(gPieceCIcon[pieceIconID], sqRect, 8, false);
  483.                                     /* Then redraw the color portion. */
  484.                                 SetRectRgn(testRgn, -30000, -30000, 30000, 30000);
  485.                                 SetClip(testRgn);
  486.                                 break;
  487.                             }
  488.                         }
  489.                     }
  490.  
  491.                     if (!gPrintPage) {
  492.                         if ((square == lastFrom) || (square == lastTo)) {
  493.                             FrameRect(&sqRect);
  494.                             gLastPiece[ss] = 0;
  495.                         }
  496.                     }
  497.  
  498.                     if (gClearSquare) break;
  499.                 }
  500.                 if (gClearSquare) break;
  501.             }
  502.         }
  503.     }
  504.  
  505.     DisposeRgn(colorRgn);
  506.     DisposeRgn(testRgn);
  507.  
  508.     if (!gPrintPage) {
  509.         if (!messageDoc)
  510.             if (!gPrintPage)
  511.                 ResetLayerWorld(gBoardLayer);
  512.         if (toWindow) {
  513.             if (!gClearSquare) {
  514.                 if (!messageDoc) {
  515.                     if (!NewLayer(&windowLayer, nil, nil, curPort, 8, 0)) {
  516.                         InsertLayer(gBoardLayer, windowLayer, 1);
  517.                         boardRect = BoardRect();
  518.                         (*windowLayer)->dstRect = boardRect;
  519.                         InvalLayer(windowLayer, boardRect, false);
  520.                         UpdateLayer(windowLayer);
  521.                         DisposeLayer(windowLayer);
  522.                     }
  523.                 }
  524.             }
  525.         }
  526.     }            
  527.  
  528.     if (gPrintPage) {                /* If printing... */
  529.         if (gPrintPage == 1)        /* If printing page 1... */
  530.             ImageBoardLines(1, hOffset, vOffset);
  531.         ImageMoveList(frHndl, theInk, hOffset);
  532.         return;
  533.     }
  534.  
  535.     if (!justBoard) {
  536.         SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
  537.         if (!messageDoc) UpdateGameStatus(frHndl);
  538.         DoDrawControls(curPort, false);
  539.         if (!messageDoc) {
  540.             OutlineControl((*frHndl)->doc.sendMessage);
  541.             DrawTime(frHndl);
  542.             DrawPalette(frHndl);
  543.         }
  544.         SetOrigin(0, 0);
  545.     }
  546. }
  547.  
  548.  
  549.  
  550. /*****************************************************************************/
  551.  
  552.  
  553.  
  554. #pragma segment Window
  555. void    ImageMoveList(FileRecHndl frHndl, Rect theInk, short hOffset)
  556. {
  557.     short    gameIndex, numGameMoves, printMoveNum, colsPerPage, colHeight;
  558.     short    pageNum, colNum, colVOffset, numMovePairs, colEndMove, hloc, vloc;
  559.     Str255    pstr;
  560.  
  561.     gameIndex    = (*frHndl)->doc.gameIndex;
  562.     numGameMoves = (*frHndl)->doc.numGameMoves;
  563.     printMoveNum = (*frHndl)->doc.startColor;
  564.     colsPerPage  = (theInk.right  - theInk.left) / 180;
  565.     colHeight    = (theInk.bottom - theInk.top) - 2 * kBoardHOffset;
  566.  
  567.     for (pageNum = 1; pageNum <= gPrintPage; ++pageNum) {
  568.  
  569.         for (colNum = 1; colNum <= colsPerPage; ++colNum) {
  570.  
  571.             hloc = colNum * 180 - 120;
  572.  
  573.             colVOffset = 0;
  574.             if (pageNum == 1) {
  575.                 if (colNum == 1) colVOffset = (3 * 20);
  576.                 if (hloc + 130 >= hOffset)
  577.                     for (; colVOffset < (kBoardHeight + 20 + kBoardVOffset); colVOffset += 20) {};
  578.                         /* Start this column below the board on 20-pixel boundary. */
  579.             }
  580.  
  581.             numMovePairs = (colHeight - colVOffset) / 20;
  582.             colEndMove   = printMoveNum + 2 * numMovePairs;
  583.  
  584.             if (pageNum == gPrintPage) {
  585.  
  586.                 if ((pageNum == 1) && (colNum == 1)) {
  587.                     MoveTo(hloc, theInk.top + 20);
  588.                     pcpy(pstr, (*frHndl)->fileState.fss.name);
  589.                     TextFace(bold + underline);
  590.                     DrawString(pstr);
  591.                     TextFace(normal);
  592.                 }
  593.  
  594.                 for (; printMoveNum < colEndMove; ++printMoveNum) {
  595.  
  596.                     RepositionBoard(frHndl, printMoveNum, false);
  597.  
  598.                     if (printMoveNum >= numGameMoves) {
  599.                         gPrintPage = 0;
  600.                         RepositionBoard(frHndl, gameIndex, false);
  601.                         return;
  602.                     }
  603.  
  604.                     vloc = theInk.top + colVOffset + 20;
  605.  
  606.                     if (!(printMoveNum & 0x01)) {
  607.                         pcpydec(pstr, printMoveNum / 2 + 1);
  608.                         MoveTo(hloc - 16 - StringWidth(pstr), vloc);
  609.                         DrawString(pstr);
  610.                         DrawString("\p)");
  611.                         MoveTo(hloc, vloc);
  612.                     }
  613.                     else {
  614.                         MoveTo(hloc + 40, vloc);
  615.                         MoveTo(hloc + 40 + 12, vloc);
  616.                         colVOffset += 20;
  617.                     }
  618.  
  619.                     if (AnnotateMove(frHndl, printMoveNum, gameIndex, pstr))
  620.                         TextFace(underline);
  621.  
  622.                     DrawString(pstr);
  623.                     TextFace(normal);
  624.                 }
  625.             }
  626.  
  627.             if ((printMoveNum = colEndMove) >= numGameMoves) {
  628.                 gPrintPage = 0;
  629.                 RepositionBoard(frHndl, gameIndex, false);
  630.                 return;
  631.             }
  632.         }
  633.     }
  634.  
  635.     RepositionBoard(frHndl, gameIndex, false);
  636. }
  637.  
  638.  
  639.  
  640.