home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / lang / lsc30p4u.sit / printf-2-w.c < prev    next >
Text File  |  1989-01-15  |  30KB  |  1,404 lines

  1. /*
  2.     printf routines for LightspeedC
  3.  
  4.     (C) Copyright 1986. THINK Technologies, Inc.  All rights reserved.
  5.     
  6.     NOTE: Proportional fonts can be used, but lines will wrap as if they
  7.             are monospaced.  In this version, since each line is drawn with
  8.             DrawChar or DrawText without repositioning, it will look better
  9.             than the old monospaced repositioning version of putch.
  10. */
  11.  
  12. /* If you have a non-Mac screen like a Radius or E-Machines, etc.  stdio
  13.     may not operate correctly since it normally directly moves the graphics
  14.     pen to achieve reasonable speeds in drawing characters.  By defining
  15.     _NonMacScreen_ you can convert all of the specialized code into the
  16.     standard Macintosh Toolbox traps so it will work correctly */
  17.     
  18. /* #define _NonMacScreen_ */
  19.  
  20. #include "config.h"
  21.  
  22. #ifndef _stdioh_
  23. #include "stdio.h"
  24. #endif
  25.  
  26. #ifndef    _QuickDraw_
  27. #include "QuickDraw.h"
  28. #endif
  29.  
  30. #ifndef    _FontMgr_
  31. #include "FontMgr.h"
  32. #endif
  33.  
  34. #ifndef    _MenuMgr_
  35. #include "MenuMgr.h"
  36. #endif
  37.  
  38. #ifndef    _ToolboxUtil_
  39. #include "ToolboxUtil.h"
  40. #endif
  41.  
  42. #ifndef _fopenwh_
  43. #include "fopenw.h"
  44. #endif
  45.  
  46. char *CtoPstr();
  47. char *PtoCstr();
  48. char *std_ver();
  49. void drawcursor();
  50. void Std_updatewindow();
  51.  
  52. /* screen display globals */
  53.  
  54. static WindowPtr Currentswrp = 0;
  55. static FILE *CurrentWindow = 0;
  56. static WindowPtr _exit_wp = 0;    /* for special exit window handling */
  57. static WindowPtr _console_wp = 0;
  58.  
  59. /* default font info */
  60.  
  61. static GrafPort dummyPort;
  62. static FontInfo _sf;                /* holds the info about the font */
  63. static int    _font = monaco,
  64.             _size = 9,
  65.             _face = 0,
  66.             _mode = srcOr;            /* stuff for Stdio_Config */
  67.  
  68. static RgnHandle emptyrgn;            /* used for scrolling */
  69. static Rect bounds;
  70.  
  71. Boolean _inited = false;            /* whether Mac is inited yet */
  72. static Boolean _screen = false;        /* whether screen is inited */
  73. static Boolean _click_on = true;    /* wait at exit from program */
  74. static Boolean _our_menus = false;    /* flag to indicate if our menus */
  75. static int deskacc_count = 0;        /* # desk accessories open */
  76.  
  77. Boolean _echo = true;                /* global Echo status for keyboard input */
  78. extern void (*_echo_to_printer_)();    /* global Echo call variable for printer */
  79.  
  80.  
  81. #define movecursor(swrp, x, y)\
  82. MoveTo( _LEFTEDGE + (x) * swrp->charwidth,\
  83.     _TOPEDGE + swrp->sf.ascent + ((y)+swrp->visrow-swrp->opt.maxrow) * swrp->charheight)
  84.     
  85.  
  86. /* Determine if this is one of the stdio created windows or not */
  87.  
  88. static
  89. Boolean OurWindow(window)
  90. register StdWindowRec *window;
  91. {
  92.     if (window)
  93.         if ((window == (StdWindowRec *)_exit_wp) || (window->signature == _OURSIGNATURE))
  94.             return (true);
  95.     
  96.     return (false);
  97. }
  98.  
  99. /* Dispatch via refcon field of window record for window events */
  100.  
  101. static
  102. Boolean WindowEvent(xevent)
  103. XEventRecord *xevent;
  104. {
  105. register WindowPeek wp;
  106. register eventinfo **refcon;
  107. register int (*proc)();
  108.     
  109.     if (! OurWindow(wp = (WindowPeek) xevent->window)) return (false);
  110.  
  111.     if (wp->windowKind >= 8 && (refcon = (eventinfo**) wp->refCon)
  112.             &&    (proc = (**refcon).eventProc))
  113.         return ((*proc)(xevent));
  114.     
  115.     return (false);
  116. }
  117.  
  118. /* If we set up the screen, we set up a simple menu as well
  119.     for DAs and such */
  120.  
  121. static
  122. void setup_menus()
  123. {
  124. register MenuHandle menu;        /* handle for our menus */
  125.  
  126.     InitMenus();
  127.     menu = NewMenu(1, "\p\024");    /*  apple menu  */
  128.     AddResMenu(menu, 'DRVR');
  129.     InsertMenu(menu, 0);
  130.     menu = NewMenu(2, "\pFile");
  131.     AppendMenu(menu, "\p(New;Open;Close;(Save;(-;Quit");
  132.     InsertMenu(menu, 0);
  133.     menu = NewMenu(3, "\pEdit");
  134. #ifdef _STD_PASTE_
  135.     AppendMenu(menu, "\p(Undo;(-;(Cut;(Copy;Paste;(Clear;(-");
  136. #else
  137.     AppendMenu(menu, "\p(Undo;(-;(Cut;(Copy;(Paste;(Clear;(-");
  138. #endif _STD_PASTE_
  139.  
  140.     AppendMenu(menu, CtoPstr(std_ver()));
  141.     PtoCstr(std_ver());
  142.     InsertMenu(menu, 0);
  143.     DrawMenuBar();
  144.     
  145.     _our_menus = true;
  146. }
  147.  
  148. static
  149. void do_exit()
  150. {Cursor watch;
  151.  
  152.         watch = **GetCursor(watchCursor);
  153.         SetCursor(&watch);
  154.         _click_on = false;
  155.         exit(0);
  156. }
  157.  
  158. static
  159. doMenu(event)
  160. register XEventRecord *event;
  161. {
  162. short item;
  163.  
  164.     if (event->record.what != menuEvent)
  165.         return;
  166.  
  167.     item = event->record.message;
  168.     switch (* (short *) &event->record.message)
  169.     {
  170.     case 1:
  171.         event->record.what = appleEvent;
  172.         HiliteMenu(0);
  173.         break;
  174.     case 2:
  175.         switch (item)
  176.         {
  177.         case 2:    /* Open entry on file menu */
  178.             event->record.what = openEvent;
  179.             break;
  180.             
  181.         case 3:    /* Close entry on file menu */
  182.             event->record.what = closeEvent;
  183.             break;
  184.             
  185.         case 6:    /* Quit entry on file menu */
  186.             do_exit();
  187.             break;
  188.         }
  189.         break;
  190.     case 3:
  191. #ifdef _STD_PASTE_
  192.             if (item == 5)
  193.             /* Paste entry on edit menu */
  194.             _std_setup_paste();
  195. #endif _STD_PASTE_
  196.  
  197.         HiliteMenu(0);
  198.         event->record.what = editEvent;
  199.         break;
  200.     }
  201. }
  202.  
  203. /* enable edit menu picks for undo, cut, copy, paste, etc. */
  204.  
  205. static
  206. void edit_enable()
  207. {register MenuHandle editmenu;
  208.  
  209.     if (_our_menus)
  210.     {
  211.         if (editmenu = GetMHandle(3))
  212.         {register int i;
  213.             for (i=CountMItems(editmenu); i; i--)
  214.                 EnableItem(editmenu, i);
  215.             DisableItem(editmenu, 2);    /* gray line */
  216.             DisableItem(editmenu, 7);    /* gray line */
  217.             DisableItem(editmenu, 8);    /* Library version */
  218.         }
  219.     }
  220. }
  221.  
  222. static
  223. void edit_disable()
  224. {register MenuHandle editmenu;
  225.  
  226.     if (_our_menus)
  227.     {
  228.         if (editmenu = GetMHandle(3))
  229.         {register int i;
  230.             for (i=CountMItems(editmenu); i; i--)    
  231.                 DisableItem(editmenu, i);
  232. #ifdef _STD_PASTE_
  233.             EnableItem(editmenu, 5);    /* Paste */
  234. #endif _STD_PASTE_
  235.             EnableItem(editmenu, 8);    /* Library version */
  236.         }
  237.     }
  238. }
  239.  
  240. /*
  241.  *  StdEvent - event handler
  242.  *
  243.  */
  244.  
  245. #line 0 StdEvent
  246. Boolean StdEvent(event)
  247. register EventRecord *event;
  248. {
  249. XEventRecord ev;
  250. register XEventRecord *xevent = &ev;
  251. register short item, refnum;
  252. Rect r;
  253. long size;
  254. int (*proc)();
  255. static char accessory[256];
  256.  
  257.     Init_stdio();
  258.     
  259.     /* copy event to local data structure */
  260.  
  261.     ev = *(XEventRecord*) event;
  262.     
  263.     /* reset event to point to this extended event record */
  264.     
  265.     event = (EventRecord*) &ev;
  266.     
  267.     xevent->window = FrontWindow();
  268.     
  269.     switch (event->what)
  270.     {
  271.     default:
  272.         return (WindowEvent(event));
  273.         
  274.     case nullEvent:
  275.         if (! WindowEvent(event)) return (false);
  276.         
  277.         switch (FindWindow(event->where, &xevent->window))
  278.         {
  279.         case inContent:
  280.             if (xevent->window == FrontWindow())
  281.             {
  282.                 SetPort(xevent->window);
  283.                 GlobalToLocal(&event->where);
  284.                 event->what = cursorEvent;
  285.                 return (WindowEvent(event));
  286.             }
  287.         default:
  288.             SetCursor(&arrow);
  289.             break;
  290.         }
  291.         break;
  292.  
  293.     case updateEvt:
  294.         if (! OurWindow(xevent->window = (WindowPtr) event->message))
  295.             return (false);
  296.         
  297.         BeginUpdate(xevent->window);
  298.         SetPort(xevent->window);
  299.         WindowEvent(event);
  300.         EndUpdate(xevent->window);
  301.         break;
  302.         
  303.     case activateEvt:
  304.         if (! OurWindow(xevent->window = (WindowPtr) event->message))
  305.             return (false);
  306.  
  307.         SetPort(xevent->window);
  308.         if (!(event->modifiers & activeFlag))
  309.             event->what = deactivateEvt;
  310.         WindowEvent(event);
  311.         break;
  312.         
  313.     case mouseDown:
  314.         switch (FindWindow(event->where, &xevent->window))
  315.         {
  316.         default:
  317.             return (false);
  318.  
  319.         case inMenuBar:
  320.             if (! _our_menus)
  321.                 return (false);
  322.  
  323.             xevent->window = FrontWindow();
  324.             SetCursor(&arrow);
  325.             doMenu(event);
  326.             event->message = MenuSelect(event->where);
  327.  
  328.             if (hiword(event->message) == 0) break;
  329.  
  330.             event->what = menuEvent;
  331.             doMenu(event);
  332.             switch (event->what)
  333.             {
  334.             case editEvent:
  335.                 if (SystemEdit((short) event->message - 1))
  336.                     break;
  337.                 WindowEvent(event);
  338.                 break;
  339.                 
  340.             case closeEvent:
  341.                 if (xevent->window)
  342.                 {
  343.                     refnum = ((WindowPeek) xevent->window)->windowKind;
  344.                     if (refnum < 0)
  345.                     {
  346.                         CloseDeskAcc(refnum);
  347.                     }
  348.                     else
  349.                         WindowEvent(event);
  350.                 }
  351.                 break;
  352.             
  353.             case openEvent:
  354.                 if (_console->filebuf)
  355.                 {
  356.                     if (!((WindowPeek)_console->filebuf)->visible)
  357.                     {
  358.                         ShowWindow(_console->filebuf);
  359.                         Std_updatewindow(_console->filebuf);
  360.                     }
  361.                 }
  362.                 break;
  363.                 
  364.             case appleEvent:
  365.                 GetItem(GetMHandle(hiword(event->message)),
  366.                         loword(event->message),
  367.                         accessory);
  368.                 OpenDeskAcc(accessory);
  369.                 edit_enable();
  370.                 break;
  371.             }
  372.             break;
  373.             
  374.         case inSysWindow:
  375.             SystemClick(event, xevent->window);
  376.             break;
  377.  
  378.         case inContent:
  379.             if (! OurWindow(xevent->window)) return (false);
  380.             
  381.             if (xevent->window != FrontWindow())
  382.             {
  383.                 event->what = selectEvent;
  384.                 WindowEvent(event);
  385.                 if (event->what != mouseDown)
  386.                 {
  387.                     SelectWindow(xevent->window);
  388.                     break;
  389.                 }
  390.             }
  391.             SetPort(xevent->window);
  392.             GlobalToLocal(&event->where);
  393.             if (event->message = FindControl(event->where,
  394.                                              xevent->window,
  395.                                              &xevent->control))
  396.             {
  397.                 proc = (int (*)()) (event->message > 128 ? 0L : -1L);
  398.                 if (TrackControl(xevent->control, event->where, proc) == 0)
  399.                     break;
  400.                 event->what = controlEvent;
  401.             }
  402.             WindowEvent(event);
  403.             if (event->what != dragEvent) break;
  404.             
  405.             LocalToGlobal(&event->where);
  406.             /* ... */
  407.         case inDrag:
  408.             /* don't select window if command key is down */
  409.             
  410.             if (!(event->modifiers & cmdKey))
  411.                 if (xevent->window != FrontWindow())
  412.                 {
  413.                     SelectWindow(xevent->window);
  414.                     break;
  415.                 }
  416.             SetRect(&r, 4, _MBARHEIGHT + 4, screenWidth - 4, screenHeight - 4);
  417.             SetCursor(&arrow);
  418.             DragWindow(xevent->window, event->where, &r);
  419.             break;
  420.             
  421.         case inGrow:
  422.             if (! OurWindow(xevent->window)) return (false);
  423.             
  424.             {register StdWindowRec *swrp = (StdWindowRec*)xevent->window;
  425.              
  426.             SetRect(&r,
  427.                 swrp->charwidth + _LEFTEDGE + _CONTROLWIDTH + 3,
  428.                 swrp->charheight + _TOPEDGE + _CONTROLWIDTH + 8,
  429.                 swrp->charwidth * swrp->opt.maxcol + _LEFTEDGE + _CONTROLWIDTH + 3,
  430.                 swrp->charheight * swrp->opt.maxrow + _TOPEDGE + _CONTROLWIDTH + 8);
  431.             }
  432.             
  433.             SetCursor(&arrow);
  434.             if (size = GrowWindow(xevent->window, event->where, &r))
  435.             {
  436.                 SizeWindow(xevent->window, loword(size), hiword(size), 0);
  437.                 SetPort(xevent->window);
  438.                 InvalRect(&xevent->window->portRect);
  439.                 event->what = growEvent;
  440.                 WindowEvent(event);
  441.                 {StdWindowRec *swrp = ((StdWindowRec*)xevent->window);
  442.                     swrp->viscol = (loword(size)-_CONTROLWIDTH-1-swrp->charwidth+1)/swrp->charwidth;
  443.                     swrp->visrow = (hiword(size)-_CONTROLWIDTH-1-swrp->charheight+1)/swrp->charheight;
  444.  
  445.                     /* make sure neither variable exceeds legal bounds */
  446.  
  447.                     if (swrp->viscol > swrp->opt.maxcol) swrp->viscol = swrp->opt.maxcol;
  448.                     if (swrp->visrow > swrp->opt.maxrow) swrp->visrow = swrp->opt.maxrow;
  449.                 }
  450.             }
  451.             break;
  452.  
  453.         case inGoAway:
  454.             if (! OurWindow(xevent->window)) return (false);
  455.             
  456.             SetCursor(&arrow);
  457.             if (TrackGoAway(xevent->window, event->where))
  458.             {
  459.                 event->what = closeEvent;
  460.                 WindowEvent(event);
  461.             }
  462.             break;
  463.         }
  464.         break;
  465.     }
  466.     return (true);    
  467. }
  468.  
  469. static
  470. void stdio_fontset(portp)
  471. GrafPtr portp;
  472. {
  473.     /* set up a font */
  474.     
  475.     SetPort(portp);
  476.     TextFont(_font);
  477.     TextSize(_size);
  478.     TextFace(_face);
  479.     TextMode(_mode);
  480. }
  481.  
  482. static
  483. void drawcursor(swrp, flag)
  484. register StdWindowRec *swrp;
  485. Boolean flag;
  486. {register int x, y, savey;
  487. #ifdef _NonMacScreen_
  488. Point savepoint;
  489. #endif
  490.  
  491.     if (swrp->opt.cursor_visible)
  492.     {register int mode = notPatCopy;
  493.     
  494.         if (flag == ON) mode = patCopy;
  495.         
  496.         /* adjust and save pen position */
  497.         
  498. #ifdef _NonMacScreen_
  499.         GetPen(&savepoint);
  500.         x = savepoint.h - 1;
  501.         savey = savepoint.v;
  502.         y = savey + swrp->sf.descent;
  503.         MoveTo(x,y);
  504. #else
  505.         x = ((WindowPtr)swrp)->pnLoc.h -= 1;
  506.         savey = ((WindowPtr)swrp)->pnLoc.v;
  507.         y = (((WindowPtr)swrp)->pnLoc.v += swrp->sf.descent);
  508. #endif
  509.         /* cursor is simply a vertical line */
  510.  
  511. #ifdef _NonMacScreen_
  512.         PenMode(mode);
  513. #else
  514.         ((WindowPtr)swrp)->pnMode = mode; /*improved speed on Mac screen */
  515. #endif
  516.         
  517.         LineTo(x, y - swrp->charheight);
  518.         
  519. #ifdef _NonMacScreen_
  520.         MoveTo(x+1, savey);
  521. #else
  522.         ((WindowPtr)swrp)->pnLoc.h = x + 1;
  523.         ((WindowPtr)swrp)->pnLoc.v = savey;
  524. #endif
  525.         /* redraw character where cursor is if we turned it off */
  526.         
  527.         if (flag == OFF)
  528.         {
  529.             DrawChar(swrp->screen[((swrp->toprow+swrp->row)%swrp->opt.maxrow)*swrp->opt.maxcol+swrp->col]);
  530.  
  531.             /* replaced  with below to improve speed */
  532. #ifdef _NonMacScreen_
  533.             MoveTo(x+1, savey);
  534. #else
  535.             ((WindowPtr)swrp)->pnLoc.h = x + 1;
  536.             ((WindowPtr)swrp)->pnLoc.v = savey;
  537. #endif
  538.         }
  539.     }
  540. }
  541.  
  542. #line 0 Std_updatewindow
  543. void Std_updatewindow(swrp)
  544. register StdWindowRec *swrp;
  545. {
  546. register int i, thisrow;
  547.  
  548.         SetPort(swrp);
  549.         
  550.         EraseRect(&((WindowPtr)swrp)->portRect);
  551.         
  552.         /* redraw last n rows in the visible region */
  553.  
  554.         for (i=0, 
  555.              thisrow = (swrp->toprow + (swrp->opt.maxrow-swrp->visrow)) % swrp->opt.maxrow;
  556.              i<swrp->visrow;
  557.              i++, thisrow = ++thisrow % swrp->opt.maxrow)
  558.         {
  559.             movecursor(swrp, 0, i+swrp->opt.maxrow-swrp->visrow);
  560.             DrawText(&swrp->screen[thisrow*swrp->opt.maxcol], 0, swrp->viscol);
  561.         }
  562.         
  563.         if (!swrp->opt.no_grow)
  564.         {Rect r;
  565.             /* invalidate the scroll bar regions of the window, so
  566.                     the scroll bars and grow box get drawn properly */
  567.             r = ((WindowPtr)swrp)->portRect;
  568.             r.left = r.right-_CONTROLWIDTH-2;
  569.             r.top =  r.bottom-_CONTROLWIDTH-2;
  570.             InvalRect(&r);
  571.  
  572.             DrawControls(swrp);
  573.             DrawGrowIcon(swrp);
  574.         }
  575.  
  576.         /* make sure there is no further update event on this window */
  577.         
  578.         ValidRect(&((WindowPtr)swrp)->portRect);
  579.         
  580.         movecursor(swrp, swrp->col, swrp->row);
  581.         drawcursor(swrp, ON);
  582. }
  583.  
  584. static
  585. Stdwindow_doEvent(xevent)
  586. XEventRecord *xevent;
  587. {
  588. register WindowPtr wp = xevent->window;
  589. register int i;
  590.  
  591.     switch (((EventRecord*)xevent)->what)
  592.     {
  593.     case activateEvt:
  594.         edit_disable();
  595.         break;
  596.  
  597.     case deactivateEvt:
  598.     {StdWindowRec *srp;
  599.     
  600.         edit_disable();
  601.         
  602.         if ((srp = (StdWindowRec*)FrontWindow()))
  603.             if (! OurWindow(srp))
  604.                 edit_enable();
  605.         break;
  606.     }
  607.     case updateEvt:
  608.         Std_updatewindow(wp);
  609.         break;
  610.  
  611.     case closeEvent:
  612.  
  613.         /* hide the window */
  614.         
  615.         HideWindow(wp);
  616.         
  617.         /* THIS PATCHED OUT CODE ALLOWS CLOSING ALL WINDOWS WHICH SHARE
  618.             THIS WINDOW POINTER AND RELEASING THEIR WINDOW RECORDS:
  619.         for (i= _NFILE-1; i>=0 ; i--)
  620.             if (_file[i].filebuf == (char*)wp)
  621.                 fclosew(&_file[i]);
  622.         */
  623.         
  624.         break;
  625.         
  626.     default:
  627.         /* event was not handled by us */
  628.  
  629.         return (false);
  630.     }
  631.     
  632.     /* event was handled somewhere above */
  633.     
  634.     return (true);
  635. }
  636.  
  637. #line 0 fclosew
  638. int    fclosew(who)
  639. register FILE    *who;
  640. {
  641.     if (!who->window) return (EOF);
  642.     
  643.     if (who != _console)
  644.     {
  645.         who->window = false;
  646.         who->InUse = false;
  647.         
  648.         /* Now release the memory for the window record unless
  649.             it's the console which we never should release */
  650.         
  651.         if (OurWindow(who->filebuf) && ((WindowPtr)who->filebuf != _console_wp))
  652.         {
  653.             ((StdWindowRec*)who->filebuf)->signature = 0;
  654.             DisposHandle(((WindowPeek)who->filebuf)->refCon);
  655.             DisposeWindow(who->filebuf);
  656.         }
  657.  
  658.         who->filebuf = NULL;
  659.  
  660.         if (who == CurrentWindow)
  661.         {
  662.             CurrentWindow = _console;
  663.             Currentswrp = _console_wp;
  664.         }
  665.     }
  666.     
  667.     return (0);
  668. }
  669.  
  670. static
  671. void clearscreenmem(swrp)
  672. register StdWindowRec *swrp;
  673. {
  674. register char sp = ' ';
  675. register char *begp, *p;
  676.     
  677.     /* clear screen buffer to spaces working backwards through buffer */
  678.  
  679.     p = (begp = swrp->screen) + swrp->opt.maxcol * swrp->opt.maxrow;
  680.     
  681.     while (--p >= begp) *p = sp;
  682. }
  683.  
  684. /* RMS 4/20/88 */
  685. /* procedure to determine if MultiFinder is running by checking for the
  686. existence of the WaitNextEvent() trap */
  687.  
  688. static int MFIsRunning()
  689. {    /* $8F is for _MFDispatch, $9F is the unimplemented trap */
  690.     return (GetTrapAddress(0x8FL) != GetTrapAddress(0x9FL));
  691. }
  692.  
  693. static
  694. FILE *fopenwx(titlebar, upper_left, optionsptr, whichfilevar, ourwp)
  695. char *titlebar;
  696. Point upper_left;
  697. register StdWindowOptions *optionsptr;
  698. FILE *whichfilevar;
  699. WindowPtr ourwp;
  700. {
  701. register int maxrow = 0, maxcol = 0;
  702. register FILE *who;
  703. register StdWindowRec *swrp;
  704. register Boolean grow = true, goaway = true;
  705. eventinfo et;
  706.  
  707.     Init_stdio();
  708.     
  709.     if (whichfilevar)
  710.     {
  711.         /* a specific file variable was specified */
  712.         who = whichfilevar;
  713.         
  714.         if ((!who->StdStream) || who->InUse)
  715.         {
  716.             /* don't allow this for other than standard streams */
  717.             errno = -47;    /* file busy error */
  718.             return (NULL);
  719.         }
  720.     }
  721.     else
  722.     {register int free_slot = _NFILE;
  723.         
  724.         /* look thru FILE array for an open slot */
  725.         
  726.         while ((--free_slot>=0) && _file[free_slot].InUse)
  727.             ;
  728.     
  729.         if (free_slot < 0)
  730.         {
  731.             errno = -42;     /* tmfoErr - too many files open    */
  732.             return (NULL);
  733.         }
  734.  
  735.         who = &_file[free_slot];
  736.  
  737.         if (!ourwp && optionsptr)
  738.         {
  739.             /* override defaults */
  740.             
  741.             maxcol = optionsptr->maxcol;
  742.             maxrow = optionsptr->maxrow;
  743.             
  744.             grow = !optionsptr->no_grow;
  745.             goaway = !optionsptr->no_goaway;
  746.         }
  747.     }
  748.  
  749.     /* if ourwp is nonzero, then the window is already set up and all
  750.         we need to do is set up the file record */
  751.  
  752.     if (ourwp) swrp = (StdWindowRec*) ourwp;
  753.     else
  754.     {{register int charheight;
  755.     
  756.         stdio_fontset(&dummyPort);
  757.         GetFontInfo(&_sf);
  758.         
  759.         charheight = (_sf.ascent + _sf.descent + _sf.leading);
  760.         
  761.         /* set up default number of rows and columns depending on screen */
  762.     
  763.         if (!maxrow)
  764.             maxrow = (screenHeight - upper_left.v - _TOPEDGE - _CONTROLWIDTH - 1 - charheight + 1) /
  765.                         charheight;
  766.     
  767.     /***************** RMS 4/20/88 ***************
  768.     *
  769.     *
  770.     *    If MultiFinder is running, we'll make the console window half-height,
  771.     *    so that we can see the contents while running the debugger.
  772.     *
  773.     *    As soon as a possible, "MFIsRunning()" will be replaced by a 
  774.     *    mechanism to see if the debugger is being used.
  775.     *
  776.     **********************************************/
  777.     
  778. #ifdef _HALFWINDOW_
  779.         if (MFIsRunning()) maxrow = 11;        /* half a standard screen */
  780. #endif
  781.  
  782.         if (!maxcol)
  783.             maxcol = (screenWidth - upper_left.h - _LEFTEDGE - _CONTROLWIDTH - 1 - _sf.widMax + 1) /
  784.                      _sf.widMax;
  785.     
  786.         /* create a pointer block big enough to accomodate the window record
  787.         and all of our stuff */
  788.  
  789.         if (!(swrp = (StdWindowRec*) (NewPtr(sizeof(StdWindowRec)+maxrow*maxcol))))
  790.         {
  791.             errno = -108;    /* MemFullErr - ran out of memory */
  792.             return (NULL);
  793.         }
  794.     
  795.         swrp->sf = _sf;
  796.         
  797.         swrp->charheight = charheight;
  798.         swrp->charwidth = _sf.widMax;
  799.         
  800.      }    /* just provides scoping for charheight */
  801.      
  802.         swrp->toprow = swrp->col = 0;
  803.         swrp->row = maxrow - 1;    /* start cursor at bottom of screen */
  804.         swrp->signature = _OURSIGNATURE;
  805.     
  806.         bounds.top = upper_left.v;
  807.         bounds.left = upper_left.h;
  808.         bounds.right = bounds.left + _LEFTEDGE + maxcol * swrp->charwidth + _CONTROLWIDTH + 1;
  809.         bounds.bottom = bounds.top + _TOPEDGE + maxrow * swrp->charheight + _CONTROLWIDTH + 1 + 4;
  810.     
  811.         NewWindow(swrp, &bounds, CtoPstr(titlebar), true,
  812.                     (grow ? documentProc : noGrowDocProc), -1L, goaway, 0L);
  813.         
  814.         PtoCstr(titlebar);
  815.     
  816.         /* set up event processing hooks */
  817.         
  818.         et.eventProc = Stdwindow_doEvent;
  819.         et.vscroll = 0;
  820.         PtrToHand(&et, &((WindowPeek)swrp)->refCon, sizeof et);
  821.         
  822.         stdio_fontset(swrp);
  823.         
  824.         if (grow)
  825.         {
  826.             InvalRect(&((WindowPtr)swrp)->portRect);
  827.             DrawControls(swrp);
  828.             DrawGrowIcon(swrp);
  829.         }
  830.         
  831.         ValidRect(&((WindowPtr)swrp)->portRect);
  832.     
  833.         if (optionsptr)
  834.             swrp->opt = *optionsptr;
  835.         else
  836.         {
  837.             swrp->opt.maxrow = maxrow;
  838.             swrp->viscol = swrp->opt.maxcol = maxcol;
  839.             swrp->opt.cursor_visible = true;
  840.             swrp->opt.echo_state = true;
  841.             swrp->opt._tab_width = 4;
  842.             swrp->opt.no_pull_front = false;
  843.             swrp->opt.no_grow = !grow;
  844.             swrp->opt.no_drag = false;
  845.             swrp->opt.no_goaway = !goaway;
  846.             swrp->opt.no_scroll = false;
  847.             swrp->opt.no_wrap = false;
  848.         }
  849.     
  850.         swrp->visrow = maxrow;
  851.         swrp->viscol = maxcol;
  852.         
  853.         /* clear screen memory to spaces */
  854.         
  855.         clearscreenmem(swrp);
  856.  
  857.         movecursor(swrp, swrp->col, swrp->row);
  858.         drawcursor(swrp, ON);
  859.     }
  860.  
  861.     /* set all relevant items in FILE record */
  862.     
  863.     who->filebuf    = (char *) swrp;
  864.     who->StdStream    = true;
  865.     who->InUse        = true;
  866.     who->window        = true;
  867.     who->rd            = true;            /* 11/13/87 rms - changed from FALSE */
  868.     who->wr            = true;
  869.  
  870.     return (who);
  871. }
  872.  
  873. #line 0 fopenw
  874. FILE *fopenw(titlebar, upper_left, optionsptr)
  875. char *titlebar;
  876. Point upper_left;
  877. StdWindowOptions *optionsptr;
  878. {
  879.     fopenwx(titlebar, upper_left, optionsptr, NULL, NULL);
  880. }
  881.  
  882. #line 0 setwindow
  883. int setwindow(windowfile)
  884. register FILE *windowfile;
  885. {
  886. register StdWindowRec *swrp;
  887.  
  888.     if (windowfile &&
  889.         windowfile->InUse &&
  890.         windowfile->window &&
  891.         (swrp = ((StdWindowRec*)windowfile->filebuf))->signature == _OURSIGNATURE)
  892.     {
  893.         CurrentWindow = windowfile;
  894.         Currentswrp = (WindowPtr) swrp;
  895.         _echo = swrp->opt.echo_state;
  896.     }
  897.     else
  898.         return (EOF);
  899.         
  900.     return (0);
  901. }
  902.  
  903. stdwsave(windowfile, env)
  904. FILE *windowfile;
  905. StdwsaveRecord *env;
  906. {
  907.  
  908.     Init_stdio();
  909.     env->fp = CurrentWindow;
  910.     env->wp = Currentswrp;
  911.     
  912.     return (setwindow(windowfile));
  913. }
  914.  
  915. stdwrestore(windowfile, env)
  916. FILE *windowfile;
  917. StdwsaveRecord *env;
  918. {
  919.     if (windowfile != CurrentWindow) return (EOF);
  920.     
  921.     CurrentWindow = env->fp;
  922.     Currentswrp = env->wp;
  923.     _echo = ((StdWindowRec*)Currentswrp)->opt.echo_state;
  924.     return (0);
  925. }
  926.  
  927. #line 0 Click_On()
  928. void Click_On(flag)
  929. {
  930.     _click_on = flag;
  931. }
  932.  
  933. static
  934. draw_exit_text(xevent)
  935. XEventRecord *xevent;
  936. {
  937. WindowPtr wp = xevent->window;
  938.     switch (((EventRecord*)xevent)->what)
  939.     {
  940.     case updateEvt:
  941.         SetPort(wp);
  942.         MoveTo(4, 24+_sf.descent);
  943.         DrawString("\p Click close box of this window or press Return to continue");
  944.         break;
  945.  
  946.     case closeEvent:
  947.         do_exit();
  948.         
  949.     default:
  950.         /* event not handled by us */
  951.         
  952.         return (false);
  953.     }
  954.  
  955.     /* event was handled above */
  956.  
  957.     return (true);
  958. }
  959.  
  960. static
  961. void    click_to_continue()
  962. {
  963. eventinfo et;
  964.  
  965.     /* make sure all exit routines have been called before we
  966.         do anything */
  967.  
  968.     _exiting(1);
  969.     
  970.     /* if (emptyrgn) DisposeRgn(emptyrgn); - need not bother since the
  971.         entire application heap should be vaporized shortly */
  972.     
  973.     if (_click_on)
  974.     {
  975.         /* cancel any pending events */
  976.         
  977.         FlushEvents(everyEvent, 0);
  978.  
  979.         bounds.left = bounds.top = 50;
  980.         bounds.right = 456;
  981.         bounds.bottom = 100;
  982.         
  983.         /* Put up a window and handle window events
  984.             until goaway is clicked for this window */
  985.     
  986.         _exit_wp = NewWindow(0L, &bounds, "\pExit Window",
  987.                             true, noGrowDocProc,
  988.                             -1L, true, 0L);
  989.  
  990.         et.eventProc = draw_exit_text;
  991.         PtrToHand(&et, &((WindowPeek) _exit_wp)->refCon, sizeof et);
  992.  
  993.         _font = systemFont;
  994.         _size = 12;
  995.         stdio_fontset(_exit_wp);
  996.         
  997.         /* small event loop to process window events such as bringing
  998.             to front, resizing, dragging, etc. */
  999.             
  1000.         for (;;)
  1001.         {EventRecord event;
  1002.             while (! GetNextEvent(everyEvent, &event))
  1003.             {
  1004.                 HiliteMenu(0);
  1005.                 SystemTask();
  1006.             }
  1007.             
  1008.             SetCursor(&arrow);
  1009.         
  1010.             if (event.what == keyDown && (char) event.message == '\r')
  1011.                 break;
  1012.  
  1013.             StdEvent(&event);
  1014.         }
  1015.         
  1016.         do_exit();
  1017.     }
  1018. }
  1019.  
  1020. #line 0 Stdio_Config()
  1021. void Stdio_Config(font,size,face,mode)
  1022. int    font,size,face,mode;
  1023. {
  1024.     /* modify defaults */
  1025.         
  1026.     _font = font;
  1027.     _size = size;
  1028.     _face = face;
  1029.     _mode = mode;
  1030. }
  1031.  
  1032. #line 0 Stdio_config()    /* lower case c since it was wrong in the manual! */
  1033. void Stdio_config(font,size,face,mode)
  1034. int    font,size,face,mode;
  1035. {
  1036.     Stdio_Config(font, size, face, mode);
  1037. }
  1038.  
  1039. void Init_stdio()
  1040. {
  1041. register StdWindowRec *swrp;
  1042. Point topleftcorner;
  1043.  
  1044.     if (_inited && _screen) return;
  1045.  
  1046.     if (!_inited)
  1047.     {
  1048.         _inited = true;
  1049.         InitGraf(&thePort);
  1050.         InitFonts();
  1051.         InitWindows();
  1052.         InitDialogs(0L);
  1053.         setup_menus();
  1054.         TEInit();
  1055.         FlushEvents(everyEvent, 0);
  1056.         HiliteMenu(0);
  1057.         SystemTask();
  1058.     }
  1059.  
  1060.     if (!_screen)
  1061.     {
  1062.         _screen = true;
  1063.  
  1064.         OpenPort(&dummyPort);
  1065.  
  1066.         /* this font information must be set up for fopenw to know how
  1067.              big to make the window */
  1068.         
  1069.         topleftcorner.h = 4;
  1070.         topleftcorner.v = _MBARHEIGHT + _TITLEBARHEIGHT + 4;
  1071.  
  1072.         setwindow(fopenwx("console", topleftcorner, NULL, _console, NULL));
  1073.         
  1074.         _console_wp = Currentswrp;
  1075.  
  1076.         /* unlike other windows, console is multi-purpose and
  1077.             so it is handled specially */
  1078.  
  1079.         _console->rd = true;
  1080.  
  1081.         /* set up stdout and stderr to match */
  1082.  
  1083.         if (stdout->StdStream)
  1084.             fopenwx("", topleftcorner, NULL, stdout, _console_wp);
  1085.         
  1086.         if (stderr->StdStream)
  1087.             fopenwx("", topleftcorner, NULL, stderr, _console_wp);
  1088.  
  1089.         /* set up exit procedure */
  1090.         
  1091.         onexit(click_to_continue);
  1092.         
  1093.         SetCursor(&arrow);
  1094.     }
  1095.     
  1096.       if (!emptyrgn) emptyrgn=NewRgn();
  1097. }
  1098.  
  1099. #line 0 Set_Echo()
  1100. void Set_Echo(state)
  1101. Boolean    state;
  1102. {
  1103.     _echo = state;
  1104.     if (CurrentWindow)
  1105.         ((StdWindowRec*)(Currentswrp))->opt.echo_state = state;
  1106. }
  1107.  
  1108. /* pdg - 6/10/86 - Stdio_MacInit() allows coexistence of Mac windows and
  1109.                     stdio if called with flag set to true so stdio won't
  1110.                     reinitialize all of the Mac stuff. */
  1111.  
  1112. #line 0 Stdio_MacInit()
  1113. void Stdio_MacInit(flag)
  1114. Boolean flag;
  1115. {
  1116.     _inited = flag;
  1117. }
  1118.  
  1119. #line 0 Set_Tab
  1120. void Set_Tab(len)
  1121. int    len;
  1122. {
  1123.     Init_stdio();
  1124.     ((StdWindowRec*) Currentswrp)->opt._tab_width = len > 1 ? len : 1;
  1125. }
  1126.  
  1127. #line 0 gotoxy
  1128. void    gotoxy(x,y)
  1129. register int x,y;
  1130. {
  1131. register StdWindowRec *swrp;
  1132.  
  1133.     Init_stdio();
  1134.     
  1135.     swrp = (StdWindowRec*) Currentswrp;
  1136.     
  1137.     if ((x < swrp->opt.maxcol) && (y < swrp->opt.maxrow))
  1138.     {
  1139.         drawcursor(swrp, OFF);
  1140.         swrp->col = x;
  1141.         swrp->row = y;
  1142.         movecursor(swrp, x,y);
  1143.         drawcursor(swrp, ON);
  1144.     }
  1145. }
  1146.  
  1147. #line 0 getxpos
  1148. int getxpos()
  1149. {
  1150.     Init_stdio();
  1151.     
  1152.     return (((StdWindowRec*) Currentswrp)->col);
  1153. }
  1154.  
  1155. #line 0 getypos
  1156. int getypos()
  1157. {
  1158.     Init_stdio();
  1159.     
  1160.     return (((StdWindowRec*) Currentswrp)->row);
  1161. }
  1162.  
  1163. #line 0 Get_ScreenPtr
  1164. char *Get_ScreenPtr(who)
  1165. register FILE *who;
  1166. {
  1167.     Init_stdio();
  1168.     
  1169.     if (who->InUse && who->window)
  1170.         return (((StdWindowRec*) who->filebuf)->screen);
  1171.         
  1172.     return (NULL);
  1173. }
  1174.  
  1175. #line 0 Get_WindowPtr
  1176. void *Get_WindowPtr(who)    /* actually returns a WindowPtr! */
  1177. register FILE *who;
  1178. {
  1179.     Init_stdio();
  1180.     
  1181.     if (who->InUse && who->window)
  1182.         return ((void*) who->filebuf);
  1183.         
  1184.     return (NULL);
  1185. }
  1186.  
  1187. #line 0 putch
  1188. void putch(c)
  1189. register char c;
  1190. {
  1191. register StdWindowRec *swrp;
  1192. register char *screenp;
  1193. static inited=false;
  1194.  
  1195.     if (!inited)
  1196.     {
  1197.         inited = true;
  1198.         Init_stdio();
  1199.     }
  1200.     
  1201.     if (! Currentswrp || ! CurrentWindow->InUse) return;
  1202.     
  1203.     if (_echo_to_printer_ && (Currentswrp == _console_wp))
  1204.         (*_echo_to_printer_)(c);
  1205.     
  1206.     SetPort(swrp = (StdWindowRec*) Currentswrp);
  1207.  
  1208.     if (swrp != (StdWindowRec *)FrontWindow())
  1209.         if (! swrp->opt.no_pull_front)
  1210.         {
  1211.             SelectWindow(swrp);
  1212.             Std_updatewindow(swrp);
  1213.         }
  1214.  
  1215.     /* wait here if mouse is down */
  1216.     
  1217.     while (Button());
  1218.  
  1219.     if (c<' ')
  1220.     {
  1221.         switch(c)
  1222.         {
  1223.     
  1224.         case '\t':
  1225.             {register int over;
  1226.              Boolean newline = false;
  1227.                 
  1228.                 over = swrp->opt._tab_width - (swrp->col % swrp->opt._tab_width);
  1229.                 if ((swrp->col + over) > swrp->opt.maxcol)
  1230.                 {
  1231.                     newline = true;
  1232.                     c = '\n';
  1233.  
  1234.                     over = swrp->opt.maxcol - swrp->col;
  1235.                 }
  1236.  
  1237.                 /* want to write spaces into those columns where tab is */
  1238.                 
  1239.                 if (over > 0)
  1240.                 {Rect r;
  1241.                 
  1242.                     screenp = swrp->screen +
  1243.                     (((swrp->toprow+swrp->row)%swrp->opt.maxrow) * swrp->opt.maxcol) + swrp->col - 1;
  1244.  
  1245.                     drawcursor(swrp, OFF);
  1246.  
  1247.                     /* erase character positions on screen */
  1248.             
  1249.                     r.right = (r.left = ((WindowPtr)swrp)->pnLoc.h) + over * swrp->charwidth;
  1250.                     r.top = (r.bottom = ((WindowPtr)swrp)->pnLoc.v + swrp->sf.descent) - swrp->charheight;
  1251.  
  1252.                     EraseRect(&r);
  1253.                     
  1254.                     swrp->col += over;
  1255.                     
  1256.                     while (--over>=0) *++screenp = ' ';
  1257.                 
  1258.                     movecursor(swrp, swrp->col, swrp->row);
  1259.                     
  1260.                     drawcursor(swrp, ON);
  1261.                 }
  1262.  
  1263.                 if (newline) break;
  1264.                 
  1265.                 return;
  1266.             }
  1267.  
  1268.         case '\r':    /* simply return cursor to start of line */
  1269.                     drawcursor(swrp, OFF);
  1270.                     swrp->col = 0;
  1271.                     movecursor(swrp, 0, swrp->row);
  1272.                     drawcursor(swrp, ON);
  1273.                     return;
  1274.  
  1275.         case '\b':    /* simply reposition cursor back one column */
  1276.                 {
  1277.                     /* This won't work for proportional fonts
  1278.                         since we don't have the true width handy
  1279.                         true,  it could be looked up in the font...*/
  1280.                     
  1281.                     drawcursor(swrp, OFF);
  1282.  
  1283.                     if (swrp->col == 0)
  1284.                     {
  1285.                         if (((swrp->row == 0) && (!swrp->opt.no_scroll))
  1286.                             || swrp->opt.no_wrap)
  1287.                         {
  1288.                             drawcursor(swrp, ON);
  1289.                             return;
  1290.                         }
  1291.                         
  1292.                         /* return to previous row */
  1293.                         
  1294.                         if (swrp->row == 0)
  1295.                             swrp->row = swrp->opt.maxrow;
  1296.  
  1297.                         swrp->row--;
  1298.                         swrp->col = swrp->opt.maxcol;
  1299.                     }
  1300.                     swrp->col--;
  1301.                     movecursor(swrp, swrp->col, swrp->row);
  1302.                     drawcursor(swrp, ON);
  1303.                     return;
  1304.                 }
  1305.                     
  1306.         case '\f':    
  1307.                 {Rect r;
  1308.                      
  1309.                     drawcursor(swrp, OFF);
  1310.                     
  1311.                     r = ((WindowPtr)swrp)->portRect;
  1312.                     r.right -= _CONTROLWIDTH+2;
  1313.                     r.bottom -= _CONTROLWIDTH+2;
  1314.                     EraseRect(&r);
  1315.  
  1316.                     swrp->toprow = swrp->row = swrp->col = 0;
  1317.                     
  1318.                     clearscreenmem(swrp);
  1319.  
  1320.                     movecursor(swrp, 0, 0);
  1321.                     drawcursor(swrp, ON);
  1322.                     return;
  1323.                 }
  1324.  
  1325.         case 7:        SysBeep(2);    /* Bell */
  1326.                     return;
  1327.         }
  1328.     }
  1329.  
  1330.     drawcursor(swrp, OFF);
  1331.  
  1332.     if ((c != '\n') && (swrp->col < swrp->opt.maxcol))
  1333.     {
  1334.         screenp = swrp->screen + ((swrp->toprow+swrp->row)%swrp->opt.maxrow)*swrp->opt.maxcol+swrp->col;
  1335.  
  1336.         /* dump character into the screen buffer and
  1337.             possibly draw the character */
  1338.         
  1339.         
  1340.  
  1341.         if (swrp->col < swrp->viscol)
  1342.         {
  1343.             if (*screenp != ' ')
  1344.             {Rect r;
  1345.                 /* erase this character position on screen */
  1346.                 
  1347.                 r.right = (r.left = ((WindowPtr)swrp)->pnLoc.h) + swrp->charwidth;
  1348.                 r.top = (r.bottom = ((WindowPtr)swrp)->pnLoc.v + swrp->sf.descent) - swrp->charheight;
  1349.     
  1350.                 EraseRect(&r);
  1351.             }
  1352.             
  1353.             DrawChar(*screenp = c);
  1354.         }
  1355.         else
  1356.             *screenp = c;
  1357.     }
  1358.     
  1359.     /* need to do a newline? */
  1360.  
  1361.     if ((c=='\n') || ((++swrp->col >= swrp->opt.maxcol) && !swrp->opt.no_wrap))  
  1362.     {
  1363.         if (swrp->opt.no_scroll)
  1364.             /* if we don't scroll, toprow doesn't move and the characters
  1365.                 wrap back to the first screen line */
  1366.             swrp->row = (swrp->row + 1) % swrp->opt.maxrow;
  1367.         else
  1368.         {
  1369.              if (swrp->row >= swrp->opt.maxrow-1)
  1370.             {Rect scrollrect;
  1371.              register int i;
  1372.              register char *p;
  1373.                   
  1374.                 scrollrect = ((WindowPtr)swrp)->portRect;
  1375.                 scrollrect.top += _TOPEDGE;
  1376.                 scrollrect.left += _LEFTEDGE;
  1377.                   scrollrect.right -= _CONTROLWIDTH+1;
  1378.                   scrollrect.bottom -= _CONTROLWIDTH+1;
  1379.                   
  1380.                   ScrollRect(&scrollrect,0,-swrp->charheight,emptyrgn);
  1381.         
  1382.                 /* toprow points to the new first line */
  1383.  
  1384.                 swrp->toprow = (swrp->toprow + 1) % swrp->opt.maxrow;
  1385.  
  1386.                 p = swrp->screen + ((swrp->toprow + swrp->opt.maxrow - 1) % swrp->opt.maxrow) * swrp->opt.maxcol - 1;
  1387.                 
  1388.                 /* clear the reallocated line in the buffer */
  1389.                 
  1390.                 for (i=swrp->opt.maxcol; i; i--)
  1391.                     *++p = ' ';
  1392.             }
  1393.             else
  1394.                 ++swrp->row;
  1395.         }
  1396.         
  1397.         swrp->col = 0;
  1398.         
  1399.         movecursor(swrp, 0, swrp->row);
  1400.     }
  1401.     
  1402.     drawcursor(swrp, ON);
  1403. }
  1404.