home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / suntar1.cpt / mainEvent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  35.4 KB  |  1,255 lines

  1. /* this file contains code from two TextEdit-based little editors: */
  2.  
  3. /*********************************************************************
  4.  
  5.     MiniEdit.c
  6.  
  7.     The sample application from Inside Macintosh (RoadMap p.
  8.     15-17)
  9.     beefed up a bit by Stephen Z. Stein, Symantec Corp.
  10.  
  11. *********************************************************************/
  12. /*------------------------------------------------------------------------------
  13. #
  14. #    Apple Macintosh Developer Technical Support
  15. #
  16. #    MultiFinder-Aware TextEdit Sample Application
  17. #
  18. #    TESample.c
  19. #
  20. #    Copyright ⌐ 1989 Apple Computer, Inc.
  21. #    All rights reserved.
  22. #
  23. ------------------------------------------------------------------------------*/
  24.  
  25. /* the integration of the two environments (MiniEdit is autowrap-only, TESample
  26. is horizontal scroll only, both are single-window and their programming style is 
  27. often radically different) is by us: */
  28.  
  29. /*******************************************************************************\
  30.  
  31. main events module
  32.  
  33. suntar, ⌐1991-92 Sauro & Gabriele Speranza
  34.  
  35. This program is public domain, feel free to use it or part of it for anything
  36.  
  37. \*******************************************************************************/
  38.  
  39. /* In general, we have kept the general structure of MiniEdit (which is easier to
  40. understand) but inserting many small excerpts of code from TESample (which is more
  41. powerful: for example, it's MultiFinder aware). Many features, however, are
  42. completely new for suntar and come from neither MiniEdit nor TESample.
  43. */
  44.  
  45. #include "antiglue.h"
  46. #include "system7.h"
  47.  
  48. /* inutili, sono in MacHeaders
  49. #include <QuickDraw.h>
  50. #include <MacTypes.h>
  51. #include <FontMgr.h>
  52. #include <WindowMgr.h>
  53. #include <MenuMgr.h>
  54. #include <TextEdit.h>
  55. #include <DialogMgr.h>
  56. #include <EventMgr.h>
  57. #include <DeskMgr.h>
  58. #include <FileMgr.h>
  59. #include <ToolboxUtil.h>
  60. #include <ControlMgr.h>
  61. */
  62.  
  63.  
  64. #include "windows.h"
  65. #include "suntar.h"
  66.  
  67. #define REQUIREDSTACK 16384
  68.  
  69. void (*my_add_menus)() =NULL;        /* aggiunta men¥ dopo il men¥ preferences 
  70.                                     --add items in the preferences menu and further menus
  71.                                     */
  72. void (*my_handle_menus)(long)=NULL;        /* gestione nuove entry in qualunque men¥ 
  73.                                     -- handles selection of any application-installed menu item
  74.                                     */
  75. void (*my_event_filter)(EventRecord*)=NULL;    /* permette di "filtrare" un evento, dopo che
  76.                 MainEvent ha chiamato GetNextEvent e prima che lo
  77.                 gestisca, basta settare il campo what a nullEvent per 
  78.                 sopprimere la gestione standard
  79.                 -- event filter !
  80.                 */
  81. int (*my_at_exit)();            /* azioni da compiere al Quit 
  82.                                 --quit handler
  83.                                 */
  84.  
  85. static short quit_selection;
  86. static short n_about_entries;
  87. unsigned char PNS[]="\p";
  88. Point badmount_point={80,112};
  89.  
  90. window_def        my_windows[n_max_windows];    /* si potrebbe anche renderla una lista
  91.                                             per non avere un valore massimo... ma mi fa comodo
  92.                                             cosô per decidere dove posizionare le finestre */
  93. short            n_currently_open=0;
  94. window_def        *curr_window=NULL;    /* la finestra attualmente corrente 
  95.                                     -- if the currently active window belongs to this module,
  96.                                     curr_window must point to it (and the current grafport
  97.                                     is set to it)
  98.                                     */
  99. TEHandle        TEH;            /* della finestra corrente...
  100.                                 -- copy of curr_window->TEH */
  101.  
  102. static WindowPtr foreign_window[n_max_foreign];
  103. static upd_proc update_handler[n_max_foreign],activate_handler[n_max_foreign];
  104.  
  105. MenuHandle        myMenus[4];
  106. MenuHandle        fontM[3];
  107. #ifdef SUNTAR
  108. MenuHandle        hqxM;
  109. #endif
  110. Cursor            editCursor;
  111. Cursor            waitCursor;
  112. static struct acur{
  113.     short n_cursors;
  114.     short delay;
  115.     Ptr cursor_ID_or_Ptr[1000];    /* the true size depends on the size of the resource */
  116.     } *rot_cursor;
  117.  
  118. extern int current_font,current_size,current_style,curr_font_index;
  119.  
  120. /* #define    kNoEvents                0        / * no events mask */
  121. /* GMac is used to hold the result of a SysEnvirons call. This makes
  122.    it convenient for any routine to check the environment. It is
  123.    global information, anyway. */
  124. SysEnvRec    gMac;                /* set up by Initialize */
  125.  
  126. /* GHasWaitNextEvent is set at startup, and tells whether the WaitNextEvent
  127.    trap is available. If it is false, we know that we must call GetNextEvent. */
  128. Boolean        gHasWaitNextEvent;    /* set up by Initialize */
  129. Boolean        gHasResolveAlias;
  130. Boolean        gHasCustomPutFile;
  131.  
  132. /* GInBackground is maintained by our OSEvent handling routines. Any part of
  133.    the program can check it to find out if it is currently in the background. */
  134. Boolean        gInBackground=false;        /* maintained by Initialize and DoEvent */
  135.  
  136. /* kSysEnvironsVersion is passed to SysEnvirons to tell it which version of the
  137.    SysEnvRec we understand. */
  138. #define    kSysEnvironsVersion        1
  139. #define _WaitNextEvent    0xA860
  140. #define _AliasDispatch    0xA823
  141. #define _Gestalt        0xA1AD
  142. #define _InitGraf        0xA86E
  143. #define _Unimplemented    0xA89F
  144.  
  145. #define TrapType Trap_Type
  146. typedef unsigned char Trap_Type;        /* changed name, to avoid a conflict with
  147.                                         newer standard headers which might have that
  148.                                         declaration */
  149. void my_init(void);
  150. void SetUpMenus(void);
  151. void crea_menu_font(void);
  152. void set_marks_size(void);
  153. void set_marks_style(void);
  154. void DoFile(int);
  155. void SetUpCursors(void);
  156. Boolean _TrapAvailable(short,TrapType);
  157. unsigned long GetSleep(void);
  158.  
  159.  
  160.  
  161. static void my_init()
  162. {
  163. register int i;
  164.     SetUpMenus();
  165.     for(i=0;i<n_max_windows;i++)
  166.         my_windows[i].used=false;
  167.     SetUpCursors();
  168.     for(i=0;i<n_max_foreign;i++)
  169.         foreign_window[i]=NULL;
  170. }
  171.  
  172. void install_handlers(window,upd_handler,act_handler)
  173. WindowPtr window;
  174. upd_proc upd_handler;
  175. upd_proc act_handler;
  176. {
  177. int i=0;
  178. while(i<n_max_foreign){
  179.      if(foreign_window[i]==NULL){
  180.          foreign_window[i]=window;
  181.          update_handler[i]=upd_handler;
  182.          activate_handler[i]=act_handler;
  183.          return;
  184.          }
  185.      i++;
  186.      }
  187. }
  188.  
  189. void remove_handlers(window)
  190. WindowPtr window;
  191. {
  192. int i=0;
  193. while(i<n_max_foreign){
  194.      if(foreign_window[i]==window){
  195.          foreign_window[i]=NULL;
  196.          return;
  197.          }
  198.      i++;
  199.      }
  200. }
  201.  
  202. void UpdateFilter (theEvent)
  203. register EventRecord *theEvent;
  204. /* to be called exclusively for update & activate events */
  205. {
  206. /* It's annoying to be obliged to handle update and activate events; furthermore,
  207. according to TN 304 update events should never be ignored, even during a ModalDialog
  208. (which ignores them if they are not for the dialog itself, unless you specify a 
  209. filter which handles them).
  210.  Hence, when suntar began to have a number of windows and dialogs, I preferred
  211. to do things in a way that is complex but surely works in any situation,
  212. centralizing the handling of updates and activates: when calling ModalDialog one
  213. must use this filter, when calling MainEvent or get_event updates and activates
  214. are NOT returned to the caller, but are handled internally (just as happens to
  215. updates when one installs a picture in windowPic, but probably nobody has ever
  216. used that method for a dialog).
  217.  
  218. It's always a good programming rule to rewrite something when the program grows
  219. and the old, simple method begins to be inadequate for the job.
  220. */
  221. if(ourTE(theEvent->message)){
  222.     if(theEvent->what==updateEvt)
  223.         UpdateWindow((WindowPtr)theEvent->message);
  224.     else    /* activate */
  225.         DoActivate((WindowPtr)theEvent->message,theEvent->modifiers & activeFlag );
  226.     theEvent->what=nullEvent;
  227.     }
  228. else if(theEvent->message){
  229.     int entry_n;
  230.     for(entry_n=0;entry_n<n_max_foreign;entry_n++){
  231.         if((WindowPtr)theEvent->message==foreign_window[entry_n]){
  232.             if(theEvent->what==updateEvt){
  233.                 if(update_handler[entry_n])
  234.                     (*update_handler[entry_n])(theEvent);
  235.                 }
  236.             else{
  237.                 if(activate_handler[entry_n])
  238.                     (*activate_handler[entry_n])(theEvent);
  239.                 }
  240.             theEvent->what=nullEvent;
  241.             break;
  242.             }
  243.         }
  244.     }
  245. return;
  246. }
  247.  
  248. void MainEvent()
  249. /* see the comment at the beginning of suntar.c for understanding this routine 
  250. and the two following ones: suntar has NOT a main event loop... */
  251. {
  252.     EventRecord        myEvent;
  253.     if(get_event(&myEvent)){
  254.         if(my_event_filter!=NULL) (*my_event_filter)(&myEvent);
  255.         handle_event(&myEvent);
  256.         }
  257. }
  258.  
  259.  
  260. Boolean get_event(myEvent)
  261. EventRecord        *myEvent;
  262. {
  263.     Boolean retcode;
  264.     if(curr_window)
  265.         TEIdle(curr_window->TEH);
  266.  
  267.  
  268. #ifdef SUNTAR
  269.     /* window 0 is the console window, and old text must be deleted if the
  270.     TextEdit limit of 32 kbytes is approached... */
  271.     if( my_windows[0].used && ((**my_windows[0].TEH).teLength >maxTElength-4000 ||
  272.         /* according to TN 237, there is another limit to the size of a TextEdit
  273.         record: the destination rect must not be taller than 32767 pixels: 
  274.         that limit is more stringent only if the line height in pixels is bigger
  275.         than the average line length in characters, a very rare situation,
  276.         unless you set the font size to 36 or 48, or use a small autowrap window  */
  277.         (**my_windows[0].TEH).nLines > 32000/(**my_windows[0].TEH).lineHeight) )
  278.             SilentSuppression(50);
  279. #endif
  280.  
  281.  
  282.     #ifdef SUNTAR
  283.     #define MY_MASK (everyEvent& ~diskMask)
  284.     if( ! (retcode=GetOSEvent (diskMask,myEvent)) ){    /* otherwise the disk is mounted... */
  285.     #else
  286.     #define MY_MASK everyEvent
  287.     #endif
  288.         /* use WNE if it is available */
  289.         if ( gHasWaitNextEvent ) {
  290.             long delay=GetSleep();
  291.             /*AdjustCursor(mouse, cursorRgn);*/
  292.             if(delay==-1){
  293.                 OSEventAvail(kNoEvents, myEvent);    /* we aren't interested in any events */
  294.                                                     /* just the mouse position */
  295.                 MaintainCursor(myEvent->where);
  296.                 }
  297.             retcode= WaitNextEvent(MY_MASK, myEvent,
  298.                 delay, NULL/*cursorRgn*/);
  299.                 /* in suntar disk insertions are masked, but
  300.                 WaitNextEvent returns, so that the event may be caught by the
  301.                 following GetOSEvent call above, hence the disk is mounted only if 
  302.                 it's a Mac disk */
  303.             }
  304.         else {
  305.             SystemTask();
  306.             retcode= GetNextEvent(MY_MASK, myEvent);
  307.             }
  308.         #ifdef SUNTAR
  309.         }
  310.         #endif
  311.     MaintainCursor(myEvent->where);
  312.     if(retcode && (myEvent->what==updateEvt || myEvent->what==activateEvt) ){
  313.         UpdateFilter(myEvent);
  314.         return myEvent->what!=nullEvent;
  315.         }
  316.     return retcode;
  317. }
  318.  
  319. void handle_event(myEvent)
  320.     register EventRecord    *myEvent;
  321. {
  322.     WindowPtr        whichWindow;
  323. /*    RgnHandle        cursorRgn;*/
  324.     int                code;
  325.  
  326. /*printf("event=%x\n",myEvent->what);*/
  327. /*print_number("event=",(int)myEvent->what);*/
  328.  
  329.     switch (myEvent->what) {
  330.     case mouseDown:
  331.         code=FindWindow( myEvent->where, &whichWindow );
  332. /*printf("place=%d\n",code);*/
  333.         switch (code) {
  334.         case inDesk:
  335.             SysBeep(5);
  336.             break;
  337.         case inMenuBar:
  338.             MaintainMenus();
  339.             DoCommand( MenuSelect(myEvent->where));
  340.             break;
  341.         case inSysWindow:
  342.             SystemClick( myEvent, whichWindow );
  343.             break;
  344.         case inDrag:
  345.             {
  346.             Rect    dragRect;
  347.             dragRect.left=0;
  348.             dragRect.top=MBARHEIGHT;
  349.             dragRect.right=screenBits.bounds.right;
  350.             dragRect.bottom=screenBits.bounds.bottom;
  351.             InsetRect(&dragRect,4,4);
  352.             DragWindow( whichWindow, myEvent->where, &dragRect );
  353.             }
  354.             break;
  355.         case inGrow:
  356.             if (curr_window)
  357.                 MyGrowWindow( whichWindow, myEvent->where );
  358.             break;
  359.         case inZoomOut:
  360.         case inZoomIn:
  361.             if(curr_window)
  362.                 myZoomWindow(whichWindow,myEvent->where,code);
  363.             break;
  364.         case inGoAway:
  365.             if (curr_window)
  366.                 if (TrackGoAway( whichWindow, myEvent->where) )
  367.                     DoFile(opClose);
  368.             break;
  369.         case inContent:
  370.             if (whichWindow != FrontWindow()){
  371.                 SelectWindow(whichWindow);
  372.                 }
  373.             else
  374.                 if (curr_window)
  375.                     DoContent(whichWindow, myEvent);
  376.             break;
  377.         default: ;
  378.         } /* end switch FindWindow */
  379.         break;
  380.     case autoKey:
  381.         if((myEvent->modifiers & cmdKey) != 0)    /*niente autorepeat sui comandi!
  382.                     --no autorepeat on commands ! */
  383.             break;    /* else prosegui in sequenza...
  384.                     -- else behave as a keyDown */
  385.     case keyDown:
  386.         DoKeyDown( (unsigned char) myEvent->message, myEvent->modifiers );
  387.         break;
  388.     /* moved to UpdateFilter
  389.     case activateEvt:
  390.         if (ourTE((WindowPtr)myEvent->message)){
  391.             SetPort((WindowPtr)myEvent->message);
  392.             DoActivate((WindowPtr)myEvent->message,myEvent->modifiers & activeFlag );
  393.             }
  394.         else{
  395.             if (myEvent->modifiers & activeFlag )
  396.                 SetPort((WindowPtr)myEvent->message);
  397.             }
  398.         break;
  399.         */
  400.     case kOSEvent:    /* eventi del MultiFinder */
  401.         {
  402.         WindowPtr w;
  403.         switch ((myEvent->message >> 24) & 0x0FF) {        /* high byte of message */
  404.             case kMouseMovedMessage:
  405.                 /*MaintainCursor(myevent->where);*/            /* mouse-moved is an idle event */
  406.                 break;
  407.             case kSuspendResumeMessage:
  408.                 gInBackground = (myEvent->message & kResumeMask) == 0;
  409.                 w=FrontWindow();
  410.  
  411.                 myEvent->message=(long)w;
  412.                 myEvent->what=activateEvt;        /* suspend/resume is also an activate/deactivate */
  413.                 myEvent->modifiers = !gInBackground ? activeFlag : 0;
  414.                 UpdateFilter(myEvent);        /* my handler of activate events */
  415. #ifdef SUNTAR
  416.                 if(gInBackground){
  417.                     if( going_to_background() && ourTE(w))
  418.                         HiliteWindow (w,false);        /* going_to_background does some
  419.                                 dirty things which may leave the window incorrectly 
  420.                                 highlighted */
  421.                     SetCursor(&arrow);    /* some applications do not set the cursor
  422.                             when they go to foreground... */
  423.                     MainEvent();    /* per andarci subito in background... non 
  424.                         posso fare aspettare la prossima chiamata 
  425.                         --immediately go to background: in suntar going_to_background
  426.                         may do a delay, I can't return to a routine which is going to do
  427.                         further work before calling MainEvent again
  428.                         when MultiFinder is waiting to switch me to background
  429.                         */
  430.                     return;
  431.                     }
  432. #endif
  433.                 break;
  434.         }}
  435.         break;
  436.     /* moved to UpdateFilter
  437.     case updateEvt: 
  438.         if (ourTE((WindowPtr)myEvent->message)) 
  439.             UpdateWindow((WindowPtr)myEvent->message);
  440.         break;
  441.     */
  442.     case diskEvt:
  443.     /*    It is not a bad idea to at least call DIBadMount in response
  444.         to a diskEvt, so that the user can format a floppy. */
  445.         #ifndef SUNTAR
  446.         if ( hiword(myEvent->message) != noErr )
  447.             DIBadMount(badmount_point, myEvent->message);
  448.         #else
  449.         unexpected_disk_insertion(myEvent->message);
  450.         #endif
  451.  
  452.         break;
  453.     default: ;
  454.     } /* end of case myEvent->what */
  455. }
  456.  
  457. /* gestione tasti */
  458.  
  459. void DoKeyDown( theChar, modifiers )
  460. register unsigned char theChar;
  461. short modifiers;
  462. {
  463.  
  464. if ((modifiers & cmdKey) != 0) {
  465.     long mnk;
  466.     MaintainMenus();
  467.     mnk=MenuKey( theChar );
  468.     if(hiword(mnk) == 0){ /* non esiste un tale comando, o non Å abilitato...
  469.                     --command not existing or not enabled
  470.                     */
  471.         SysBeep(5);
  472.         FlushEvents( keyDownMask|autoKeyMask, 0 );
  473.         }
  474.     else{
  475.         SetPort(curr_window);
  476.         DoCommand( mnk );
  477.         }
  478.     return;
  479.     }
  480. else if (curr_window){
  481.     SetPort(curr_window);
  482.     if (theChar== enter_key) /* il TextEdit non lo gestisce
  483.                 --TextEdit does not know that enter is a "return" char
  484.                  */
  485.         theChar=CR;
  486.     if( theChar >= 28 &&theChar <= 31){    /* Å un tasto cursore 
  487.                             --a cursor key
  488.                             */
  489.         TEKey( theChar, TEH );
  490.         }
  491.     else if    ( theChar == DelChar) /* questo Å gestito correttamente, ma per poter 
  492.                                 poi aggiungere al programma l'undo bisogna gestirlo 
  493.                                 direttamente, e la gestione per console Å diversa... */
  494.         if( curr_window->flags&READONLY && ((**TEH).selStart<curr_window->lastPrompt 
  495.             || (**TEH).selStart==curr_window->lastPrompt &&(**TEH).selStart==(**TEH).selEnd))
  496.             SysBeep(5);
  497.         else{
  498.             TEKey( theChar, TEH );
  499.             curr_window->dirty = 1;
  500.             }
  501. #ifndef AUTOSELECT
  502.     else if( curr_window->flags&READONLY && (**TEH).selStart<curr_window->lastPrompt){
  503.         SysBeep(5);
  504.         FlushEvents( keyDownMask|autoKeyMask, 0 );    /* Å facile battere pi¥ caratteri 
  505.                                     insieme, e il beep dê tempo per accumularli...*/
  506.         }
  507. #endif
  508.     else if ( curr_window->flags&READONLY && curr_window->lastPrompt == 32767){
  509.     /* a console window completely read-only */
  510.         SysBeep(5);
  511.         FlushEvents( keyDownMask|autoKeyMask, 0 );
  512.         }
  513.     else if((*TEH)->teLength - ((*TEH)->selEnd - (*TEH)->selStart) + 1 < maxTElength ){
  514.         /* a console window with a read-only part on top and a read/write part
  515.         on bottom */
  516.         if(theChar==CR&&(curr_window->flags&CONSOLE)){
  517.             TESetSelect (32767L ,32767L, TEH);
  518.             TEKey( CR, TEH );
  519.             curr_window->lastPrompt=32767;    /* questo Å l'unico segno visibile dall'esterno 
  520.                                             che il return c'Å stato
  521.                                             -- it's the only state change remembering
  522.                                             that there was a carriage return */
  523.             }
  524.         else{
  525.         /* non so se sia il caso di gestire a parte anche altri caratteri, tipo l'escape */
  526. #ifdef AUTOSELECT
  527.             if( curr_window->flags&READONLY && (**TEH).selStart<curr_window->lastPrompt)
  528.                 TESetSelect(32767L,32767L,TEH);
  529. #endif
  530.             TEKey( theChar, TEH );
  531.             curr_window->dirty = 1;
  532.             }
  533.         }
  534.     else{    /* buffer pieno ! */
  535.         SysBeep(5);
  536.         ParamText("\pNo more space in window",PNS,PNS,PNS);
  537.         my_alert();
  538.         FlushEvents( keyDownMask|autoKeyMask, 0 );
  539.         }
  540.     SCR_BAR_AND_TEXT_IN_SYNC
  541.     }
  542. }
  543.  
  544.  
  545. void DoActivate(w,active_flag)
  546. register window_def* w;
  547. short active_flag;
  548. {
  549. GrafPtr    savePort;
  550. if (!active_flag ) GetPort( &savePort );
  551. SetPort(w);        /* pare che non guasti, per proteggersi da DA e (sotto
  552.                 MultiFinder) altri programmi che si comportino male; e poi,
  553.                 tutto il modulo presume che se curr_window Å != NULL allora
  554.                 la porta corrente Å lei
  555.                 -- in this module, all routines think that if curr_window is
  556.                 not 0, then the current port is curr_window */
  557. if (active_flag ) {
  558.     Rect r;
  559.     curr_window=w;
  560.     TEH=w->TEH;
  561.     TEActivate( w->TEH );
  562.     if(curr_window==&my_windows[0]){
  563.         /* posso averci fatto delle print, col che posizione e dimensioni
  564.         complessive sono cambiate
  565.         -- if printf has added text while the window was not in foreground,
  566.         the scrollbar was not updated to reflect the current state
  567.         */
  568.         SCR_BAR_AND_TEXT_IN_SYNC
  569.         }
  570.     ShowControl( w->vScroll );
  571. #ifdef HSCROLL
  572.     if( w->flags&HSCROLL) ShowControl( w->hScroll);
  573. #endif
  574.     TEFromScrap();
  575.     /* the growbox needs to be redrawn on activation: */
  576.     r=((WindowPtr)w)->portRect;
  577.     r.top = r.bottom - (SBarWidth+1);
  578.     r.left = r.right - (SBarWidth+1);
  579.     InvalRect(&r);        
  580.     }
  581. else {
  582.     ZeroScrap();
  583.     TEToScrap();
  584.     TEDeactivate(w->TEH);
  585.     HideControl( w->vScroll );
  586. #ifdef HSCROLL
  587.     if( w->flags&HSCROLL) HideControl( w->hScroll );
  588. #endif
  589.     DrawGrowIcon(w);
  590.     curr_window=NULL;
  591.     SetPort( savePort );
  592.     }
  593. }
  594.  
  595.  
  596. static void SetUpMenus()
  597. {
  598.     int    i;
  599.  
  600.     myMenus[appleM] = GetMenu( appleID );
  601.     if(myMenus[appleM]==NULL){
  602.         SysBeep(5);
  603.         SysBeep(5);
  604.         SysBeep(5);
  605.         ExitToShell();
  606.         }
  607.     n_about_entries=CountMItems(myMenus[appleM]);
  608.     if(n_about_entries>0)
  609.         AppendMenu(myMenus[appleM], "\p(-");
  610.     AddResMenu( myMenus[appleM], 'DRVR' );
  611.  
  612.     myMenus[fileM] = GetMenu(fileID);
  613.     quit_selection=CountMItems(myMenus[fileM]);
  614.  
  615.     crea_menu_font();
  616. #ifdef SUNTAR
  617.     hqxM=GetMenu(hqxID);
  618.     InsertMenu(hqxM, -1);
  619. #endif
  620.  
  621.     myMenus[editM] = GetMenu(editID);
  622.     myMenus[prefM] = GetMenu(prefID);
  623.     for ( (i=appleM); (i<sizeof(myMenus)/sizeof(MenuHandle)); i++ ) 
  624.         InsertMenu(myMenus[i], 0) ;
  625.     if(my_add_menus!=NULL)
  626.         (*my_add_menus)();
  627.  
  628.     DrawMenuBar();
  629.  
  630. }
  631.  
  632.  
  633. static void crea_menu_font()
  634. {
  635. int i,font_n;
  636.     Str255 fontName;
  637. /* gestione men¥ dei font */
  638. /* ispirata al dimostrativo in Pascal di Carlo Rogialli, SP Computer aprile 1989
  639. -- inspired to the demo program in Pascal by Carlo Rogialli, in an italian magazine 
  640.  */
  641.     fontM[0]=GetMenu(fontID);
  642.     AddResMenu( fontM[0], 'FONT' );
  643.     fontM[1]=GetMenu(sizeID);
  644.     fontM[2]=GetMenu(styleID);
  645.     for(i=0;i<3;i++)
  646.         InsertMenu(fontM[i], -1);
  647.  
  648.     curr_font_index=1+CountMItems(fontM[0]);
  649.     do{
  650.         curr_font_index--;
  651.         GetItem(fontM[0],curr_font_index,&fontName);
  652.         GetFNum(fontName,&font_n);
  653.         /*printf("font %p %d\n",fontName,font_n);*/
  654.         }
  655.     while(font_n!=current_font &&curr_font_index>0);    /* se il font monaco non Å presente 
  656.                                                 si comporta stranamente ma almeno non crasha */        
  657.     SetItemMark (fontM[0], curr_font_index, 'Ñ');
  658.  
  659.     for(i=CountMItems(fontM[1]);i>0;i--){    /* if a size is checked, accept it; otherwise,
  660.                         use the default value (9) */
  661.         int markChar;
  662.         GetItemMark (fontM[1],i,&markChar);
  663.         if(markChar==checkMark){
  664.             char sizestr[16];
  665.             GetItem(fontM[1],i,sizestr);
  666.             current_size=pstrtoi(sizestr);
  667.             break;
  668.             }
  669.         }
  670.     set_marks_size();
  671.     set_marks_style();
  672. }
  673.  
  674. static void set_marks_size()
  675. {
  676. int i,size;
  677. char sizestr[16];
  678. for(i=CountMItems(fontM[1]);i>0;i--){
  679.     GetItem(fontM[1],i,sizestr);
  680.     if(RealFont(current_font, (size=pstrtoi(sizestr))) )
  681.         SetItemStyle(fontM[1],i,outline);
  682.     else
  683.         SetItemStyle(fontM[1],i,0);
  684.     CheckItem (fontM[1], i, size==current_size );
  685.     }
  686. }
  687.  
  688. static void set_marks_style()
  689. {
  690. int i,mask;
  691. CheckItem (fontM[2], 1, current_style==0 );
  692. mask=1;
  693. for(i=2;i<=6;i++){
  694.     CheckItem (fontM[2], i, (current_style&mask) !=0 );
  695.     mask <<=1;
  696.     }
  697. }
  698.  
  699. void DoFont( mResult)
  700. long mResult;
  701. {
  702.     Str255    fontName;
  703.  
  704.     switch (hiword(mResult)) {
  705.     case fontID:
  706.         CheckItem (fontM[0], curr_font_index, false );
  707.         SetItemMark (fontM[0], curr_font_index=loword( mResult ), 'Ñ');
  708.         GetItem(fontM[0],curr_font_index,&fontName);
  709.         GetFNum(fontName,¤t_font);
  710.         set_marks_size();    /* Å cambiato l'essere real font o no
  711.                             -- "real font" sizes are represented differently,
  712.                             hence I must recompute their state */
  713.         break;
  714.     case sizeID:
  715.         {char sizestr[16];
  716.         GetItem(fontM[1],loword( mResult ),sizestr);
  717.         current_size= pstrtoi(sizestr);
  718.         }
  719.         set_marks_size();
  720.         break;
  721.     case styleID:
  722.         if(loword( mResult )==1)
  723.             current_style=0;
  724.         else
  725.             current_style ^= (1<< (loword( mResult )-2)) ;
  726.         set_marks_style();
  727.         break;
  728.     }
  729. }
  730.  
  731. void DoCommand( mResult )
  732. long mResult;
  733. {
  734.     int        theItem, temp;
  735.  
  736.     theItem = loword( mResult );
  737.     switch (hiword(mResult)) {
  738.     case appleID:
  739.         if(theItem<=n_about_entries)
  740.             my_handle_menus(mResult);
  741.         else
  742.             {Str255    name;
  743.             GrafPtr savePort;
  744.  
  745.             GetPort(&savePort);
  746.             GetItem(myMenus[appleM], theItem, &name);
  747.             OpenDeskAcc( &name );
  748.             SetPort( savePort );
  749.             }
  750.         break;
  751.     case fileID: 
  752.         if(theItem==quit_selection){
  753.             DoFile(opQuit);
  754.             if(my_at_exit!=NULL)
  755.                 if( !(*my_at_exit)()) break;    /* quit cancelled */
  756.             HiliteMenu(0);
  757.             ExitToShell();
  758.             }
  759.         else
  760.             (*my_handle_menus)(mResult);
  761.         break;
  762.     case editID:
  763. /* la funzione MaintaiMenus dovrebbe disabilitare i comandi di editing se non esiste 
  764. una finestra corrente, ma per prudenza Å meglio controllare sempre...
  765. -- The commands are disabled when they are meaningless, but it's better to check
  766. anyway
  767. */
  768.         if (SystemEdit(theItem-1)==0) {
  769. #ifndef AUTOSELECT
  770.             if( curr_window==NULL || theItem!=copyCommand && (curr_window->flags&READONLY) &&
  771.                 (**TEH).selStart<curr_window->lastPrompt ){
  772.                 SysBeep(5);
  773.                 break;
  774.                 }
  775. #else
  776.             if( curr_window==NULL ||  theItem!=copyCommand && theItem!=pasteCommand && 
  777.                 (curr_window->flags&READONLY) && (**TEH).selStart<curr_window->lastPrompt ) {
  778.                 SysBeep(5);
  779.                 break;
  780.                 }
  781.             if( theItem==pasteCommand && (curr_window->flags&READONLY) ){
  782.             /* un paste in una console si comporta in modo complicato: a parte che 
  783.             comunque non fa il paste di caratteri CR, accetta di essere eseguito 
  784.             anche quando non si Å dopo il prompt, portandocisi automaticamente, e se 
  785.             Å selezionato qualcosa fa un copy di esso, prchÄ sia nella parte read only
  786.             -- a paste to a console is handled in a complex way: it performs autocopy
  787.             (if something was selected, copy it to the clipboard), then autoselect
  788.             (if the selection point is in the read-only portion of the window, move
  789.             it to the end), and it truncates long clipboards and refuses to paste
  790.             carriage returns */
  791.                 if( curr_window->lastPrompt == 32767 ){
  792.                     /* Å del tutto readonly, non console, quindi ho sbagliato a non dare errore */
  793.                     SysBeep(5);
  794.                     break;
  795.                     }
  796.                 if( (**TEH).selStart < curr_window->lastPrompt ){
  797.                     /* autocopy */
  798.                     if( (**TEH).selStart != (**TEH).selEnd && 
  799.                         (**TEH).selEnd < curr_window->lastPrompt)
  800.                             TECopy (TEH);
  801.                     TESetSelect(32767L,32767L,TEH);
  802.                     }
  803.                 }
  804. #endif
  805.             switch (theItem) {
  806.             case cutCommand:
  807.                 TECut( TEH );
  808.                 curr_window->dirty = 1;
  809.                 break;
  810.             case copyCommand:
  811.                 TECopy( TEH );
  812.                 break;
  813.             case pasteCommand:
  814.                 {
  815.                 register int i=TEGetScrapLen();
  816.                 if(curr_window->flags&CONSOLE && i>300 ) i=300; /* troppo per una riga sola... */
  817.                 if ( i + ((*TEH)->teLength -
  818.                             ((*TEH)->selEnd - (*TEH)->selStart)) > maxTElength ){
  819.                     ParamText("\pInsufficient space for pasting",PNS,PNS,PNS);
  820.                     my_alert();
  821.                     }
  822.                 else{
  823.                     if( curr_window->flags&CONSOLE){
  824.                 /* in modalitê console, non ha senso il paste di un carriage return! */
  825.                         char **scrap= TEScrapHandle();
  826.                         register char *p,*q;
  827.                         TEDelete(TEH);
  828.                         HLock(scrap);    /*TEInsert vuole un Ptr...*/
  829.                         q= *scrap;
  830.                         while(i>0){
  831.                             p=q;
  832.                             while(i>0&&*q!=CR) q++,--i;
  833.                             if(p!=q)TEInsert(p,(long)(q-p),TEH);
  834.                             if(i>0){    /* e quindi *q==CR */
  835.                                 TEKey(' ',TEH);
  836.                                 q++;i--;
  837.                                 }
  838.                             }
  839.                         HUnlock(scrap);
  840.  
  841.                         /*for(n=0;n<i;n++)
  842.                             TEKey ( ((*scrap)[n]==CR) ? ' ' : (*scrap)[n] ,TEH); */
  843.                         }
  844.                     else
  845.                         TEPaste( TEH );
  846.                     curr_window->dirty = 1;
  847.                     }
  848.                 }
  849.                 break;
  850.             case clearCommand:
  851.                 TEDelete( TEH );
  852.                 curr_window->dirty = 1;
  853.                 break;
  854.             default: ;/* non esistono altri comandi abilitati*/
  855.             }
  856.             SCR_BAR_AND_TEXT_IN_SYNC
  857.         }
  858.         break;
  859.     case prefID:
  860.         switch(theItem){
  861.         case pmAutowrap:
  862.             {int markChar;
  863.             GetItemMark (myMenus[prefM], pmAutowrap, &markChar);
  864.             CheckItem (myMenus[prefM], pmAutowrap, !markChar);
  865.             if(my_windows[0].used) apply_preferences(&my_windows[0]);
  866.             }
  867.             break;
  868.         default:
  869.             (*my_handle_menus)(mResult);
  870.         }
  871.         break;
  872.     case fontID:
  873.     case sizeID:
  874.     case styleID:
  875.         DoFont( mResult);
  876.         if(my_windows[0].used) apply_preferences(&my_windows[0]);
  877.         break;
  878.     default:
  879.         (*my_handle_menus)(mResult);
  880.     }
  881.     HiliteMenu(0);
  882. }
  883.  
  884. static void DoFile( operation )
  885. int        operation;
  886.  
  887. {
  888.     switch (operation) {
  889.     case opClose:
  890.         if(curr_window!=NULL)
  891.             CloseMyWindow();
  892.         break;
  893.     case opQuit:
  894.         ZeroScrap();
  895.         TEToScrap();
  896.         break;
  897.     }
  898. }
  899.  
  900.  
  901. void MaintainCursor(pt)
  902. Point        pt;
  903. {
  904. /* lo chiamo dopo GetNextEvent, col che lo so giê dove sta il mouse (al pi¥, l'evento
  905. potrebbe essere un po' vecchio, se il programma ha delle situazioni in cui per lungo
  906. tempo non riceve eventi, la posizione cosô determinata puÿ essere diversa da quella corrente) */
  907. static unsigned long next_rotation=0;
  908. static short current_cursor=0;
  909.  
  910.     if(gInBackground) return;
  911.     if(sto_lavorando){
  912.         if(((WindowPeek)FrontWindow())->windowKind<0)
  913.             /*SetCursor(&arrow) no, the desk accessory will take its decision,
  914.                 anyway the event which brought it to front caused a SetCursor(&arrow) */
  915.                 ;
  916.         else{
  917.             if(Ticks>next_rotation){
  918.                 next_rotation=Ticks+rot_cursor->delay;
  919.                 if(++current_cursor>=rot_cursor->n_cursors) 
  920.                     current_cursor=0;
  921.                 }
  922.             SetCursor( rot_cursor->cursor_ID_or_Ptr[current_cursor] );
  923.             }
  924.         }
  925.     else{
  926.         current_cursor=0;
  927.         if (curr_window && (WindowPtr)FrontWindow()==(WindowPtr)curr_window) {
  928.             SetPort(curr_window);
  929.             GlobalToLocal(&pt);
  930.             if ( PtInRect(pt, &(**TEH).viewRect ) ){
  931.                 SetCursor( &editCursor);
  932.                 return;
  933.                 }
  934.             }
  935.         SetCursor( &arrow );
  936.         }
  937. }
  938.  
  939. void MaintainMenus()
  940. {
  941.  
  942. /*
  943. In presenza di console, readonly etc. le condizioni per cui i comandi del men¥
  944. Edit sono leciti diventano complicate, ho cercato di copiarle da DoCommand, con
  945. l'idea che Å meglio lasciarne abilitati di quelli che poi danno errore piuttosto
  946. che disabilitarne di quelli che sono eseguibili
  947. -- the conditions for allowing a command are complex, but since doCommands does
  948. its own checks, I duplicated those tests and in case of difference it's
  949. better to let the item enabled when it should be disabled then vice-versa
  950. */
  951.  
  952. WindowPtr w=FrontWindow();
  953. Boolean selected,all_readonly,sel_readonly;
  954.  
  955.     if ( ! ourTE(w) ) {
  956.         Boolean en=isDAwindow(w);
  957.         en_dis_edit(undoCommand ,en);
  958.         en_dis_edit(pasteCommand ,en);
  959.         en_dis_edit(cutCommand ,en);
  960.         en_dis_edit(copyCommand ,en);
  961.         en_dis_edit(clearCommand ,en);
  962.         }
  963.     else {
  964.         /*
  965.         EnableItem(myMenus[prefM],pmAutowrap);
  966.         EnableItem(myMenus[prefM],pmFont);
  967.         EnableItem(myMenus[prefM],pmSize);
  968.         EnableItem(myMenus[prefM],pmStyle);
  969.         */
  970.         DisableItem( myMenus[editM], undoCommand );
  971.         selected = (**TEH).selStart!=(**TEH).selEnd;
  972.         en_dis_edit(copyCommand,selected);
  973.         if(curr_window->flags&CONSOLE){
  974. /* questo Å pensato per una console con autoselect e autocopy */
  975.             all_readonly= curr_window->lastPrompt==32767;
  976.             sel_readonly= (**TEH).selStart<curr_window->lastPrompt;
  977.             en_dis_edit(cutCommand, selected&&!sel_readonly);
  978.             en_dis_edit(clearCommand, selected&&!sel_readonly);
  979.             en_dis_edit(pasteCommand,!all_readonly&&(TEGetScrapLen()>0||selected));
  980.             }
  981.         else{
  982.             en_dis_edit(cutCommand, selected);
  983.             en_dis_edit(clearCommand, selected);
  984.             en_dis_edit(pasteCommand,TEGetScrapLen()>0);
  985.             }
  986.  
  987.     }
  988.     #ifdef SUNTAR
  989.     MaintainApplSpecificMenus();
  990.     #endif
  991. }
  992.  
  993. void en_dis_edit(item,flag)
  994. short item;
  995. Boolean flag;
  996. {
  997. if(flag)
  998.     EnableItem(myMenus[editM], item);
  999. else
  1000.     DisableItem(myMenus[editM], item);
  1001. }
  1002.  
  1003. static void SetUpCursors()
  1004. {
  1005.     CursHandle    hCurs;
  1006.     int i;
  1007.  
  1008.     hCurs = GetCursor(1);
  1009.     editCursor = **hCurs;
  1010.     hCurs = GetCursor(watchCursor);
  1011.     waitCursor = **hCurs;
  1012.  
  1013.     ResrvMem ((Size)200);
  1014.     hCurs=GetResource('acur',128);
  1015.     HLock(hCurs);
  1016.     rot_cursor= *hCurs;
  1017.     if(rot_cursor->delay==0) rot_cursor->delay=10;
  1018.  
  1019.     for(i=0;i<rot_cursor->n_cursors;i++){
  1020.         ResrvMem ((Size)sizeof(Cursor));
  1021.         hCurs=GetCursor(hiword(rot_cursor->cursor_ID_or_Ptr[i]));
  1022.         HLock(hCurs);
  1023.         rot_cursor->cursor_ID_or_Ptr[i]= *hCurs;
  1024.         }
  1025. }
  1026.  
  1027.  
  1028. int SilentSuppression (nlines)
  1029.  
  1030. /* questa funzione serve per implementare finestre di console: in quel caso, 
  1031. l'utente puÿ tornare indietro a vedere che Å successo nel passato ma la storia
  1032. passata non gli interesserê poi moltissimo, per cui se il buffer del TextEdit 
  1033. si riempie Å molto meno dannoso per lui cancellargli a tradimento le cose pi¥ 
  1034. vecchie che dare errore.
  1035. La funzione cerca di cancellare le prime nlines righe, ma riduce il numero se 
  1036. le ultime sono visibili sullo schermo o fanno parte della selezione, in ogni
  1037. caso ritorna il numero di righe soppresse. Sullo schermo l'unico effetto 
  1038. visibile Å uno spostamento del bottone della scrollbar verticale (la posizione 
  1039. relativa entro il buffer Å cambiata).
  1040. -- Deletes the first nlines lines of the content of the window, without
  1041. letting the user suspect what's happening (the scroll bar button is the only
  1042. thing on the screen which may be modified)
  1043. */
  1044. {
  1045. int olds,olde,deltax,deltay,oktodelete,charsToDelete,linesOutOfScreen;
  1046. Rect oldr;
  1047. GrafPtr savePort;
  1048. register TERec *TEp;
  1049.  
  1050.     TEp = *my_windows[0].TEH;
  1051.     linesOutOfScreen=(TEp->viewRect.top-TEp->destRect.top)/TEp->lineHeight;
  1052.     if(linesOutOfScreen<nlines) nlines=linesOutOfScreen;
  1053.  
  1054.     do{
  1055.         if(nlines<=0) return 0;
  1056.         charsToDelete= TEp->lineStarts[nlines];
  1057.         if( ! (oktodelete=TEp->selStart>charsToDelete) ) 
  1058.             nlines--;
  1059.         }
  1060.     while(!oktodelete);
  1061.  
  1062.     olds=TEp->selStart-charsToDelete;
  1063.     olde=TEp->selEnd-charsToDelete;
  1064.     oldr=TEp->destRect;
  1065.  
  1066.     GetPort( &savePort );
  1067.     SetPort( &my_windows[0]);
  1068.     HidePen();
  1069.     TESetSelect(0L, (long) charsToDelete, my_windows[0].TEH);
  1070.     TEDelete (my_windows[0].TEH);
  1071.     TESetSelect((long)olds, (long) olde, my_windows[0].TEH);
  1072.     TEp = *my_windows[0].TEH;
  1073.     deltax= oldr.left - TEp->destRect.left;
  1074.     deltay= oldr.top+nlines*TEp->lineHeight - TEp->destRect.top;
  1075.     if(deltax || deltay)
  1076.         TEScroll(deltax,deltay,my_windows[0].TEH);
  1077.     /* si potrebbe fare un ValidRect, ma allora bisogna sottrarci la vecchia regione
  1078.     di update e io questi giochi non li so ancora fare. Comunque, ho provato e il
  1079.     main loop non riceve alcun evento di update dopo il fatto, se qualcuno ritraccia
  1080.     allora Å direttamente il TextEdit */
  1081.     ShowPen();
  1082.     MaintainScrollBars(&my_windows[0]);
  1083.  
  1084.     if(my_windows[0].lastPrompt!=32767)
  1085.         if((my_windows[0].lastPrompt -= charsToDelete) <0)
  1086.             my_windows[0].lastPrompt=0;
  1087.     SetPort(savePort);
  1088.     return nlines;
  1089. }
  1090.  
  1091. #if 0
  1092. /*  from TESample.c */
  1093. /*    Check to see if a given trap is implemented. This is only used by the
  1094.     Initialize routine in this program, so we put it in the Initialize segment.
  1095.     The recommended approach to see if a trap is implemented is to see if
  1096.     the address of the trap routine is the same as the address of the
  1097.     Unimplemented trap. */
  1098. /*    1.02 - Needs to be called after call to SysEnvirons so that it can check
  1099.     if a ToolTrap is out of range of a pre-MacII ROM. */
  1100.  
  1101. Boolean TrapAvailable(tNumber,tType)
  1102.     short        tNumber;
  1103.     Trap_Type    tType;
  1104. {
  1105.     if ( ( tType == (unsigned char) ToolTrap ) &&
  1106.         ( gMac.machineType > envMachUnknown ) &&
  1107.         ( gMac.machineType < envMacII ) ) {        /* it's a 512KE, Plus, or SE */
  1108.         tNumber = tNumber & 0x03FF;
  1109.         if ( tNumber > 0x01FF )                    /* which means the tool traps */
  1110.             tNumber = _Unimplemented;            /* only go to 0x01FF */
  1111.     }
  1112.     return NGetTrapAddress(tNumber, tType) != GetTrapAddress(_Unimplemented);
  1113. } /*TrapAvailable*/
  1114. #else
  1115. /* this one is suggested by Inside Mac volume VI, hence probably it's better;
  1116. but we did not want to have three function to do what a single one would do,
  1117. and a #define for _GetTrapType is evaluated at compile time... */
  1118.  
  1119. #define _GetTrapType(theTrap) ((theTrap & 0x0800) !=0 )
  1120. #define TrapAvailable(theTrap) _TrapAvailable(theTrap,_GetTrapType(theTrap) )
  1121.  
  1122.  
  1123. Boolean    _TrapAvailable(short theTrap,TrapType tType)
  1124. {
  1125.     /* TrapType tType;
  1126.  
  1127.     tType = GetTrapType(theTrap); */
  1128.     if (tType == ToolTrap) {
  1129.         theTrap &= 0x07FF;
  1130.         if (theTrap >= 
  1131.             (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E,ToolTrap) ?
  1132.                 0x0200 : 0x0400) )
  1133.             theTrap = _Unimplemented;
  1134.     }
  1135.  
  1136.     return NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented, ToolTrap);
  1137. }
  1138.  
  1139. #endif
  1140.  
  1141.  
  1142. /*    Calculate a sleep value for WaitNextEvent. This takes into account the things
  1143.     that DoIdle does with idle time. */
  1144. #define MAXLONG 0xFFFFFFFF
  1145. unsigned long GetSleep()
  1146. {
  1147.     long        sleep;
  1148.     WindowPtr    window;
  1149.     TEHandle    te;
  1150.  
  1151.     if(sto_lavorando) return 0L;
  1152.     if ( gInBackground)
  1153.         sleep = MAXLONG;
  1154.     else if(!curr_window){
  1155.         #ifndef SUNTAR
  1156.         sleep = MAXLONG;
  1157.         #else
  1158.         sleep = 40;    /* under System 6, with the Finder and WaitNextEvent in ROM, I
  1159.                     do NOT get a null event when an event arrives but it's masked.
  1160.                     Since to be able to catch disk insertions by GetOSEvent and be
  1161.                     MultiFinder aware it's essential to perform a GetOSEvent with
  1162.                     little delay relative to the disk insertion, I must use a short
  1163.                     sleep time even if nothing need be done (it would be better to
  1164.                     call GetNextEvent, since the Finder can't exploit the free time,
  1165.                     and under MultiFinder and System 7 the null event arrives,
  1166.                     but ther is no way to know whether I'm under MultiFinder or not !)
  1167.                     */
  1168.         #endif
  1169.         }
  1170.     else{
  1171.         if (curr_window && (*TEH)->selStart == (*TEH)->selEnd )
  1172.             sleep = GetCaretTime();        /* blink time for the insertion point */
  1173.         else
  1174.             sleep=60;    /* non uso le region per aggiornare la forma del cursore, 
  1175.                 quindi ho bisogno di lavorare ogni tanto anche se non ho un punto 
  1176.                 di inserzione lampeggiante
  1177.                 -- I need to be periodically called to update the cursor shape,
  1178.                 it would be better to use the MouseMoved event but this way is easier
  1179.                 */
  1180.         }
  1181.     return sleep;
  1182. } /*GetSleep*/
  1183.  
  1184.  
  1185. void InitConsole()
  1186. {    
  1187.     InitGraf(&thePort);
  1188.     InitFonts();
  1189.     FlushEvents( everyEvent, 0 );
  1190.     InitWindows();
  1191.     InitMenus();
  1192.     MoreMasters();
  1193.     MoreMasters();    /* the typical heap of suntar has 100 used handles, obviously
  1194.                     peek values may go beyond 128, hence three master blocks (one
  1195.                     preallocated and two MoreMasters) avoid having a new nonrelocatable
  1196.                     block placed among relocatable blocks */
  1197.     TEInit();
  1198.     InitDialogs(0L);
  1199.     InitCursor();
  1200.     if(ApplLimit> CurStackBase-(long)REQUIREDSTACK )
  1201.         SetApplLimit(CurStackBase-(long)REQUIREDSTACK);
  1202.     MaxApplZone();
  1203.  
  1204.     /*    Ignore the error returned from SysEnvirons; even if an error occurred,
  1205.         the SysEnvirons glue will fill in the SysEnvRec. You can save a redundant
  1206.         call to SysEnvirons by calling it after initializing AppleTalk. */
  1207.  
  1208.     SysEnvirons(kSysEnvironsVersion, &gMac);
  1209.  
  1210.     /* Make sure that the machine has at least 128K ROMs. If it doesn't, exit. */
  1211.  
  1212.     if (gMac.machineType < 0){SysBeep(5); ExitToShell();}
  1213.  
  1214.     gHasWaitNextEvent = TrapAvailable(_WaitNextEvent /*, ToolTrap*/);
  1215.     gHasResolveAlias  = TrapAvailable(_AliasDispatch /*, ToolTrap*/);
  1216.     gHasCustomPutFile=false;
  1217.     if(TrapAvailable(_Gestalt /*, ToolTrap*/)){
  1218.         long response;
  1219.         OSErr err;
  1220.         #ifdef HAS_GESTALT_GLUE
  1221.         err=Gestalt('stdf',&response);
  1222.         #else    /* the libraries of Think C 4 don't contain Gestalt... */
  1223.         asm{
  1224.             move.l #'stdf',D0
  1225.             dc.w _Gestalt
  1226.             move.l A0,response
  1227.             move.w D0,err
  1228.             }
  1229.         #endif
  1230.         gHasCustomPutFile= err==noErr && ((int)response&1);
  1231.         }
  1232.  
  1233.     my_init();
  1234. }
  1235.  
  1236.  
  1237. /* conversione stringa Pascal -> intero
  1238. pascal string to integer
  1239. */
  1240. long pstrtoi(str)
  1241. Str255 str;
  1242. {
  1243. register int i=str[0];
  1244. register unsigned char *p=&str[1];
  1245. register long val=0;
  1246.  
  1247. while(i>0 && *p==' ') p++,i--;
  1248. while(i>0 && *p>='0' && *p <='9' ){
  1249.     /* val = val*10+ *p -'0'; */
  1250.     val<<=1;
  1251.     val += (val<<2) + (*p -'0');
  1252.     p++;    i--;
  1253.     }
  1254. return val;
  1255. }