home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / suntar1.cpt / windows.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-13  |  25.6 KB  |  847 lines

  1. /* this file contains code from two TextEdit-based little editors: */
  2.  
  3. /*********************************************************************
  4.  
  5.     mini.windows.c
  6.  
  7.     window functions for MiniEdit
  8.     The sample application from Inside Macintosh (RoadMap p.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 supports the zoom box). Many features, however, are
  42. completely new for suntar and come from neither MiniEdit nor TESample.
  43. */
  44.  
  45. /*#include "antiglue.h"*/
  46. #include "windows.h"
  47.  
  48. extern BitMap    screenBits;
  49. #define TITLEBARHEIGHT    20
  50.  
  51. #define HScrollMax    256            /* in caratteri */
  52. #define    MaxDocWidth    16000    /* in pixel */
  53. /* per essere intelligenti, bisognerebbe che HScrollMax e MaxDocWidth siano legate alla
  54. lunghezza max delle righe nel testo (legate, e non coincidenti, perchÄ ad es 0 ha un
  55. significato speciale) ma Å molto pi¥ semplice sia un valore costante, anche molti programmi 
  56. seri fanno cosô */
  57.  
  58. int current_font=4,        /* Monaco */
  59.     current_size=9,
  60.     current_style=0,
  61.     curr_font_index;
  62.  
  63. long myClickLoop(void);
  64. void new_Hscroll_bar(window_def *,Boolean);
  65. void set_window_flags(window_def *);
  66. void dummyClickLoop(void);
  67. void CClikLoop(void);
  68. void AdjustText (window_def *);
  69. void SetVScrollMax(window_def *);
  70. void SetView(WindowPtr);
  71. pascal void ScrollProc(ControlHandle,short);
  72. void resize_controls(WindowPtr);
  73. void resize_text(WindowPtr);
  74. void testo_in_abbondanza(TEHandle,int *);
  75. short find_new_position(window_def*,short);
  76.  
  77.  
  78. void new_window()
  79. {
  80.     Rect    destRect, viewRect;
  81.     int    i,height;
  82.  
  83.     if((i=get_window_index())<0)return; /* non dovrebbe capitare, open Å disabilitato */
  84.     set_window_flags(curr_window);
  85.     
  86.     {Rect bounds;
  87.     bounds.top=MBARHEIGHT +TITLEBARHEIGHT+4 + (TITLEBARHEIGHT-6)*i;
  88.     bounds.left=4+8*i;
  89.     bounds.bottom=min(480,screenHeight) -16+3*i;
  90.     #ifdef SUNTAR
  91.     bounds.right= min(640,screenWidth) - (screenWidth<640 ? 32 : 68) +3*i;
  92.     #else
  93.     bounds.right= min(640,screenWidth) - (screenWidth<640 ? 32 : 72) +3*i;
  94.     #endif
  95.  
  96. /*    se gli si fornisce l'area allocata, NewWindow non fa altro che ritornare il 
  97.     primo parametro, quindi Å inutile leggerlo a meno di test errori... */
  98.  
  99.     if(NULL==NewWindow( curr_window, &bounds, window_title, 1, 
  100.         vecchiaROM ? 0 : 8, -1L, (curr_window->flags&NOCLOSEBOX)==0, (long)i));
  101.     }
  102.  
  103.     SetPort(myWindow);
  104.     TextFont(current_font);
  105.     TextSize(current_size);
  106.     TextFace(current_style);
  107.  
  108.     {Rect    vScrollRect;
  109.     vScrollRect = (*myWindow).portRect;
  110.     vScrollRect.left = vScrollRect.right-SBarWidth;
  111.     vScrollRect.right += 1;
  112.     vScrollRect.bottom -= SBarWidth-1;
  113.     vScrollRect.top -= 1;
  114. #ifndef SUNTAR
  115.     /* creo la scrollbar invisibile, tanto poi viene resa attiva comunque, in
  116.     modo che la sua mancanza contribuisce a rafforzare l'impressione di attesa 
  117.     del cursore a forma di orologio durante il caricamento del file */
  118.     curr_window->vScroll = NewControl( myWindow, &vScrollRect, PNS, 0, 0, 0, 
  119.         0, scrollBarProc, 0L);
  120. #else
  121.     curr_window->vScroll = NewControl( myWindow, &vScrollRect, PNS, 1, 0, 0, 
  122.         0, scrollBarProc, 0L);
  123. #endif
  124.     }
  125.  
  126. #ifdef HSCROLL
  127. #ifdef SUNTAR
  128.     if(curr_window->flags & HSCROLL) new_Hscroll_bar(curr_window,1);
  129. #else
  130.     if(curr_window->flags & HSCROLL) new_Hscroll_bar(curr_window,0);
  131. #endif
  132. #endif
  133.     {Rect destRect;
  134.     viewRect = thePort->portRect;
  135.     viewRect.right -= SBarWidth;
  136.         viewRect.bottom -= SBarWidth;
  137.     InsetRect(&viewRect, 4, 4);
  138.     destRect=viewRect;
  139. #ifdef HSCROLL
  140.     /*if(curr_window->flags & HSCROLL)
  141.     destRect.right = destRect.left + MaxDocWidth;inutile perchÄ SetView lo riassegna*/
  142. #endif
  143.     TEH=curr_window->TEH = TENew( &destRect, &viewRect );
  144.     }
  145.  
  146.  
  147. #ifdef HSCROLL
  148.     if(curr_window->flags & HSCROLL) (**TEH).crOnly=-1;
  149. #endif
  150.     /*set_window_font();*/
  151.     SetView(thePort);
  152.     curr_window->dirty = 0;
  153.     if(curr_window->flags&READONLY) curr_window->lastPrompt=32767;
  154.     if(!vecchiaROM){
  155.         TEAutoView (true,TEH); /* auto-scroll on...*/
  156.         curr_window->itsClickLoop=(**TEH).clikLoop;
  157.         (**TEH).clikLoop=(ProcPtr)myClickLoop;
  158.         }
  159.     /* il chiamante dovrê occuparsi dei valori corrente e max delle scrollbar 
  160.     (non posso farlo ora perchÄ il buffer Å ancora vuoto)
  161.     -- the caller must set the current and max values of the scrollbar (after
  162.     filling the window with the initial text, if any)
  163.      */
  164. }
  165.  
  166. static void new_Hscroll_bar(window,visible)
  167. register window_def *window;
  168. Boolean visible;
  169. {
  170.     Rect    hScrollRect;
  171.     hScrollRect = ((WindowPtr)window)->portRect;
  172.     hScrollRect.top = hScrollRect.bottom-SBarWidth;
  173.     hScrollRect.bottom += 1;
  174.     hScrollRect.right -= SBarWidth-1;
  175.     hScrollRect.left -= 1;
  176.     if(window != curr_window) visible=false;
  177.     window->hScroll = NewControl( window, &hScrollRect, PNS, visible, 0, 0, 
  178.         HScrollMax, scrollBarProc, 0L);
  179.     SetCtlValue(window->hScroll,0);
  180.     /*if(window != curr_window) HideControl( window->hScroll );*/
  181.  
  182. }
  183.  
  184. int get_window_index()
  185. {
  186. int current_index=0;
  187.  
  188. if(n_currently_open>=n_max_windows)return -1;    /* non dovrebbe succedere, il comando Å disabilitato...
  189.         -- it should never happen, if the New command is disabled when...*/
  190. while(my_windows[current_index].used) current_index++;
  191. curr_window=&my_windows[current_index];
  192. curr_window->used=true;
  193. n_currently_open++;
  194.  
  195. return current_index;
  196. }
  197.  
  198. static void set_window_flags(window)
  199. register window_def *window;
  200. {
  201. int markChar;
  202. extern MenuHandle    myMenus[4];
  203.  
  204. window->flags=default_flags;
  205. window->lastPrompt=32767;
  206. GetItemMark (myMenus[prefM], pmAutowrap, &markChar);
  207. if(!markChar) window->flags |= HSCROLL;
  208. }
  209.  
  210. #if 0
  211. /* used for debugging: print to the second window (Ok, it would be more
  212. powerful to adapt printf to print to any window...) */
  213. #include <string.h>
  214. #include "suntar.h"
  215. void print_string(buf)
  216. char*buf;
  217. {
  218. GrafPtr    savePort;
  219. GetPort( &savePort );
  220. SetPort(&my_windows[1]);
  221. TEInsert(buf,(long)strlen(buf),my_windows[1].TEH);
  222. SetPort( savePort );
  223. }
  224.  
  225. void print_int(i)
  226. {
  227. char buffer[20];
  228. my_itoa((long)i,buffer);
  229. print_string(buffer);
  230. MaintainScrollBars(&my_windows[1]);
  231. }
  232.  
  233. void print_number(desc,i)
  234. char*desc;
  235. {
  236. TESetSelect((long)32767,(long)32767,my_windows[1].TEH);
  237. print_string(desc);
  238. print_int(i);
  239. print_string("\r");
  240. MaintainScrollBars(&my_windows[1]);
  241. }
  242. #endif
  243.  
  244. /* questa routine modifica gli attributi della finestra specificata per 
  245. adeguarli alle preferenze correnti */
  246.  
  247. void apply_preferences(w)
  248. /* apply the current setting of the preferences menu to the window.
  249. I wrote this routine for a multiwindow editor where changing the
  250. preferences does not automatically change the configuration of
  251. the current window, and there was an explicit "Apply" command.
  252. In suntar there is only one window, and this routine is called
  253. every time one changes the font, style, size or the autowrap/Hscroll
  254. mode.
  255. In a different environment, one could be obliged to store different
  256. settings of the preferences menu and its submenus and restore them
  257. into the menu every time a window becomes the current window. Obviously a new
  258. window should inherit the current settings in the preferences menu
  259. */
  260.  
  261. register window_def *w;
  262. {
  263. FontInfo    fInfo;
  264. int oldbottomline;
  265. int oldflags;
  266. GrafPtr    savePort;
  267. register TEHandle myTEH=w->TEH;
  268.  
  269. GetPort( &savePort );
  270. SetPort(w);
  271.  
  272. oldflags=w->flags;
  273.  
  274. /*
  275. print_number("old val=",GetCtlValue(w->vScroll));
  276. print_number("old max=",GetCtlMax(w->vScroll)); */
  277. set_window_flags(w);
  278. (**myTEH).crOnly = (w->flags & HSCROLL) ? -1 : 0;
  279.  
  280. oldbottomline= ((**myTEH).viewRect.top - (**myTEH).destRect.top) / (**myTEH).lineHeight;
  281.         /* that's not the same as GetCtlValue, it could have been clipped to the max...*/
  282. (**myTEH).viewRect.bottom = ((WindowPtr)w)->portRect.bottom- SBarWidth;    /* perchÄ Å mantenuta
  283.             multiplo della lunghezza della linea, cambiando cambia tutto...*/
  284.  
  285. EraseRect(&(*myTEH)->viewRect);
  286. InvalRect(&((WindowPtr)w)->portRect);
  287. HidePen();
  288.  
  289. if( (oldflags&HSCROLL) != ( w->flags&HSCROLL) ){
  290.     if(!(oldflags&HSCROLL))
  291.         new_Hscroll_bar(w,1);
  292.     else
  293.         DisposeControl(w->hScroll);
  294.     }
  295.  
  296. TextSize ( (**myTEH).txSize=current_size );
  297. TextFont ( (**myTEH).txFont=current_font );
  298. TextFace ( (**myTEH).txFace=current_style );
  299.  
  300. GetFontInfo(&fInfo);
  301. (**myTEH).lineHeight=fInfo.ascent+fInfo.descent+fInfo.leading;
  302. /*print_string("new line H=");
  303. print_int(fInfo.ascent+fInfo.descent+fInfo.leading);
  304. print_string("\r");*/
  305. (**myTEH).fontAscent=fInfo.ascent;
  306. /* w->char_width=fInfo.widMax;  inutile, lo fa poi SetView */
  307.  
  308. /*
  309. se l'altezza del font Å cambiata bisogna adeguare la posizione verticale, se la larghezza
  310. Å cambiata (e non posso guardare carattere per carattere nel caso di font proporzionali...)
  311. bisogna adeguare lo shift orizzontale; in caso di autowrap, una qualunque delle due cose 
  312. e bisogna decidere dove portarsi */
  313.  
  314. if( (w->flags&HSCROLL) && (oldflags&HSCROLL)){
  315.     SetView(w);
  316.     SetVScrollMax(w);    /* lines_in_window may have changed... */
  317.     SetCtlValue(w->vScroll,oldbottomline);    /* that should still be the current value,
  318.             but it could have been clipped to the max, and the max is changed */
  319.     }
  320. else{
  321.     int oldtopchar=(**myTEH).lineStarts[oldbottomline];
  322.     /*int i;
  323.     print_number("oldtop=",oldtopchar);
  324.     print_number("old = ",((**myTEH).viewRect.top-(**myTEH).destRect.top));
  325.     print_number("bottom line=",oldbottomline); */
  326.     SetView(w);    /* che in autowrap ricalcola gli inizi di riga...*/
  327.     if( (w->flags&HSCROLL) &&  ! (oldflags&HSCROLL)){
  328.         SetCursor(&waitCursor);
  329.         TECalText(myTEH);    /*in questo caso, SetView non la chiama..
  330.                             -- only in this case, SetView does not call it */
  331.         SetCursor(&arrow);
  332.         }
  333.     if(!(w->flags&HSCROLL) )
  334.         testo_in_abbondanza(myTEH,&oldtopchar);
  335.     SetVScrollMax(w);
  336.     SetCtlValue(w->vScroll,find_new_position(w,oldtopchar) );
  337.     }
  338.  
  339. AdjustText(w);    /* che scrolla per adeguare al settaggio delle scrollbar
  340.                 -- which scrolls the text according to the scrollbar settings */
  341. ShowPen();
  342.  
  343. SetPort(savePort);
  344. /*print_number("new = ",((**myTEH).viewRect.top-(**myTEH).destRect.top));*/
  345. }
  346.  
  347. /* purtroppo alla routine di ClikLoop Å stata imposta un'interfaccia che, pur
  348. assomigliando alle regole usate dal compilatore C, non coincide con esse per 
  349. cui una routinetta di "glue" in assembly ci vuole
  350. -- unfortunately, the interface to the ClikLoop routine is not compatible
  351. with the C calling conventions */
  352.  
  353. static void dummyClickLoop()
  354. {
  355. asm{
  356. extern myClickLoop: /* questo Å il vero entry point, non voglio eseguire le operazioni
  357.                     di ingresso inserite dal compilatore...
  358.                     -- that's the true entry point, after the operations introduced
  359.                     by the compiler (probably a LINK instruction); anyway it does
  360.                     not work to pass the C function name and doin return rather than rts */
  361.     move.l        curr_window,A0
  362.     move.l        OFFSET(window_def,itsClickLoop)(A0),A0
  363.     jsr            (A0)        ; chiama prima la sua routine...
  364.     movem.l        D1-D2/A1,-(SP) ; salva i registri sporcati dalle funzioni C ma da non sporcare
  365.     }
  366.  
  367. CClikLoop();
  368. asm{
  369.     movem.l        (SP)+,D1-D2/A1
  370.     moveq        #1,D0
  371.     rts
  372.     }
  373. }
  374.  
  375. void CClikLoop()
  376. /* presa da TEsample.c, negli esempi dell'MPW, ma con forti modifiche
  377. -- from TEsample.c, heavily modified */
  378. {
  379.     RgnHandle    region;
  380.     int newscroll;
  381.     
  382.     region = NewRgn();
  383.     GetClip(region);                    /* save clip */
  384.     ClipRect(&myWindow->portRect);
  385. /* le formule qui usate ovviamente sono le stesse di MaintainScrollBars
  386. -- same formulas as in MaintainScrollBars: */
  387.     newscroll=((**TEH).viewRect.top - (**TEH).destRect.top) / (**TEH).lineHeight;
  388.     SetCtlValue(curr_window->vScroll,newscroll);
  389. #ifdef HSCROLL
  390.     if(curr_window->flags & HSCROLL){
  391.         newscroll=((**TEH).viewRect.left - (**TEH).destRect.left)/curr_window->char_width;
  392.         SetCtlValue(curr_window->hScroll,newscroll);
  393.     }
  394. #endif
  395.     SetClip(region);                    /* restore clip */
  396.     DisposeRgn(region);
  397. }
  398.  
  399.  
  400. /* i casi sono due: o la posizione Å cambiata per azioni nel contenuto della finestra
  401. (tasti return o freccia o delete o paste o autoscroll...) e allora chiamo MaintaiScrollBars  
  402. per adeguare la posizione dei bottoni delle scrollbar, o si Å agito sulle scrollbar
  403. e allora si chiama AdjustText per scrollare il testo in modo da adeguarsi
  404. -- if the position has changed for operations in the contents in the window
  405. one must call MaintaiScrollBars to adjust scroll bars, if the situation was
  406. changed due to a click/drag in the scroll bars, one must call AdjustText
  407. */
  408.  
  409. void MaintainScrollBars(w)
  410. register window_def *w;
  411. {
  412. int newscroll;
  413. register TERec *TEp=*(w->TEH);
  414. /* se andassi a leggere i valori direttamente nel ControlRecord farei degli if
  415. per non chiamare queste routines se il nuovo valore Å uguale al vecchio, ma se devo
  416. chiamare delle GetCtl... per avere il vecchio, tanto vale chiamare comunque SetCtl.. */
  417.  
  418. SetVScrollMax(w);
  419.  
  420. /* calma, Å piuttosto stupido fare 2 modifiche se sia max sia val vanno cambiati,
  421. il thumb fa dei salti piuttosto antipatici, forse Å meglio allora chiamarne una sola,
  422. ingannando... non so se sia una buona cosa, perÿ...*/
  423.  
  424. newscroll=(TEp->viewRect.top - TEp->destRect.top) / TEp->lineHeight;
  425. SetCtlValue(w->vScroll,newscroll);
  426.  
  427. #ifdef HSCROLL
  428. if(w->flags & HSCROLL){
  429.     TEp=*(w->TEH);    /* SetCtlValue may move memory */
  430.     newscroll= (TEp->viewRect.left - TEp->destRect.left)/w->char_width;
  431.     SetCtlValue(w->hScroll,newscroll);
  432.     }
  433. #endif
  434. }
  435.  
  436. static void AdjustText (w)
  437. register window_def *w;
  438. {
  439.     int oldScroll, newScroll, delta1,delta2;
  440.     register TERec *TEp=*(w->TEH);
  441.  
  442.     oldScroll = TEp->viewRect.top - TEp->destRect.top;
  443.     newScroll = GetCtlValue(w->vScroll) * TEp->lineHeight; /* does not move memory */
  444.     /*
  445.     print_number("scrollbar=",GetCtlValue(w->vScroll));
  446.     print_number("line height=",(**(w->TEH)).lineHeight);
  447.     print_number("old scroll=",oldScroll);
  448.     print_number("new scroll=",newScroll);
  449.     TEp=*(w->TEH);
  450.     */
  451.     delta1 = oldScroll - newScroll;
  452. #ifdef HSCROLL
  453.     if(w->flags & HSCROLL){
  454.         oldScroll = TEp->viewRect.left - TEp->destRect.left;
  455.         newScroll = GetCtlValue(w->hScroll)  * w->char_width;
  456.         delta2 = oldScroll - newScroll;
  457.         }
  458.     else{
  459.         delta2=0;
  460.         if(  ! (w->flags & HSCROLL) )    /* succede solo passando da scroll a autowrap */
  461.             delta2=TEp->viewRect.left-TEp->destRect.left;
  462.         }
  463. #else
  464. delta2=0;
  465. #endif
  466. if (delta1 || delta2)
  467.   TEScroll(delta2, delta1, w->TEH);
  468. }
  469.  
  470.  
  471. static void SetVScrollMax(w)
  472. register window_def *w;
  473. {
  474.     register int    n;
  475.     register TERec*TEp = *(w->TEH);
  476. /* It is a kluge necessitated by a minor bug in TE. The bug is that if the last 
  477. character in the TE text buffer is a Carriage Return, the field "nLines" may be off by one,
  478. and cause slightly incorrect updating of the window. These instructions always returns the
  479. correct number of lines in the buffer.
  480. */
  481.     n = TEp->nLines - w->linesInWindow;
  482.  
  483.     if (TEp->teLength > 0 && (*(TEp->hText))[TEp->teLength-1]==CR)
  484.         n++;
  485.  
  486.     SetCtlMax(w->vScroll, n > 0 ? n : 0);
  487.  
  488. }
  489.  
  490. #ifdef may_run_on_64K_ROM
  491. ShowSelect()
  492.  
  493. {
  494.  
  495. /* se Å attivato l'autoscroll, il TextEdit provvede a portare in vista il punto in cui
  496. sta il cursore, quindi non devo fare altro che sistemare le scroll bar, e lo faccio senza
  497. chiamare questa routine; sulle vecchie ROM l'autoscroll non Å disponibile, e allora non 
  498. posso fare a meno di cercare il punto di selezione e portarlo in vista */
  499.  
  500. SetVScrollMax(curr_window);
  501. {
  502.     register    TERec* TEp;
  503.     register    int    theLine;
  504.     
  505. /* la ricerca lineare nell'array lineStarts fa schifo, bisognerebbe usare ricerca 
  506. logaritmica. Non l'ho cambiato perchÄ viene usato solo con le ROM pre-Mac plus...
  507. Nota che l'ultimo lineStarts Å sempre uguale alla lunghezza del testo, per cui il 
  508. ciclo si ferma comunque...
  509.  */
  510.  {
  511.      register int topLine, bottomLine;
  512.     topLine = GetCtlValue(curr_window->vScroll);
  513.     bottomLine = topLine + curr_window->linesInWindow;
  514.     TEp=*TEH;
  515. #ifdef HSCROLL
  516.  /* in questo caso theLine mi serve per il calcolo in orizzontale per cui non
  517.  posso evitare di fare la ricerca */
  518.     theLine = TEp->selStart < TEp->lineStarts[bottomLine] ? 0 : bottomLine;
  519.     for (; TEp->selStart >= TEp->lineStarts[theLine+1]; theLine++)
  520.         ;
  521.     if (TEp->selStart < TEp->lineStarts[topLine] ||
  522.         TEp->selStart >= TEp->lineStarts[bottomLine]) {
  523.             SetCtlValue(curr_window->vScroll,theLine - curr_window->linesInWindow / 2);
  524.             TEp=*TEH;    /* SetCtlValue puÿ chiamare il Quickdraw e quindi anche il MemMgr */
  525.         }
  526. }
  527.  
  528. {
  529.     int strwidth;
  530.     strwidth=TextWidth( *(TEp->hText), TEp->lineStarts[theLine], 
  531.         TEp->selStart - TEp->lineStarts[theLine]);
  532.     TEp=*TEH;    /*non credo ci siano problemi, ma a scanso di guai...*/
  533.     if(strwidth< (TEp->viewRect.left-TEp->destRect.left) || 
  534.        strwidth> (TEp->viewRect.right-TEp->destRect.left) )
  535.         SetCtlValue(curr_window->hScroll,
  536.                 (strwidth+ (TEp->viewRect.left-TEp->viewRect.right)/2)/curr_window->char_width);
  537. #else
  538.     if (TEp->selStart < TEp->lineStarts[topLine] ||
  539.             TEp->selStart >= TEp->lineStarts[bottomLine]) {
  540.         theLine = TEp->selStart < TEp->lineStarts[bottomLine] ? 0 : bottomLine;
  541.         for (; TEp->selStart >= TEp->lineStarts[theLine+1]; theLine++)
  542.             ;
  543.         SetCtlValue(curr_window->vScroll,
  544.             theLine - curr_window->linesInWindow / 2);
  545.         }
  546. #endif
  547. }
  548.     AdjustText(curr_window);
  549. }}
  550. #endif
  551.  
  552.  
  553. static void SetView(w)
  554. /* SetView, da chiamare quando si crea una finestra o si modifica font, dimensione, 
  555. o attributo di autowrap; NON si occupa delle scrollbar
  556. -- to be called when a window is created or the font-size-autowrap state is
  557. changed */
  558. /* calcola viewrect e informazioni associate; per autowrap (e solo autowrap)
  559. chiama anche TECaText */
  560. register WindowPtr w;
  561. {
  562.     FontInfo fInfo;
  563.     register TERec* TEp;
  564.     GetFontInfo(&fInfo);
  565.     TEp=*(((window_def*)w)->TEH);
  566.     TEp->viewRect = w->portRect;
  567.     TEp->viewRect.right -= SBarWidth;
  568.         TEp->viewRect.bottom -= SBarWidth;
  569.     InsetRect(&TEp->viewRect, 4, 4); /*certo non chiama il memory manager...*/
  570.     ((window_def*)w)->linesInWindow =
  571.         (TEp->viewRect.bottom-TEp->viewRect.top)/TEp->lineHeight;
  572.     ((window_def*)w)->char_width=fInfo.widMax;
  573.     TEp->viewRect.bottom = TEp->viewRect.top + TEp->lineHeight*((window_def*)w)->linesInWindow;
  574. #ifdef HSCROLL
  575.     if(((window_def*)w)->flags & HSCROLL)
  576.         TEp->destRect.right = TEp->destRect.left + MaxDocWidth;
  577.     else{
  578.         TEp->destRect.right = TEp->viewRect.right;
  579.         SetCursor(&waitCursor);
  580.         TECalText(((window_def*)w)->TEH); /* anche in caso di creazione, perchÄ lo 
  581.                 faccio PRIMA di caricare il file, il buffer Å vuoto... */
  582.         SetCursor(&arrow);
  583.         }
  584. #else
  585.     TEp->destRect.right = TEp->viewRect.right;
  586.     TECalText(((window_def*)w)->TEH);
  587. #endif
  588. }
  589.  
  590. void UpdateWindow(theWindow)
  591. register WindowPtr    theWindow;
  592. {
  593.     GrafPtr    savePort;
  594.  
  595.     GetPort( &savePort );
  596.     SetPort( theWindow );
  597.     BeginUpdate( theWindow );
  598.     EraseRect(&theWindow->portRect);
  599.     DrawControls( theWindow );
  600.     DrawGrowIcon( theWindow );
  601.     TEUpdate( &theWindow->portRect, ((window_def*)theWindow)->TEH );
  602.     EndUpdate( theWindow );
  603.     SetPort( savePort );
  604. }
  605.  
  606.  
  607. static pascal void ScrollProc(theControl, theCode)
  608. ControlHandle    theControl;
  609. short                theCode;
  610. {
  611.     int    scrollAmt;
  612.  
  613.     switch (theCode) {
  614.         case 0:
  615.             return;
  616.         case inUpButton: 
  617.             scrollAmt = -1;
  618.             break;
  619.         case inDownButton: 
  620.             scrollAmt = 1;
  621.             break;
  622.         case inPageDown:
  623.         case inPageUp: 
  624.             if(theControl==curr_window->vScroll){
  625.                 scrollAmt =  ((**TEH).viewRect.bottom-(**TEH).viewRect.top) / 
  626.                     (**TEH).lineHeight - 1;
  627.                 if(!scrollAmt) scrollAmt=1;    /* with the minimum size window and the
  628.                         maximum size font it may happen */
  629.                 }
  630.             else    /* hScroll */
  631.                 scrollAmt = ((**TEH).viewRect.right-(**TEH).viewRect.left) /
  632.                     curr_window->char_width -1;
  633.             if(theCode==inPageUp) scrollAmt = -scrollAmt;
  634.             break;
  635.         }
  636.  
  637.     SetCtlValue( theControl, GetCtlValue(theControl)+scrollAmt );
  638.     AdjustText(curr_window);
  639.  
  640. }
  641.  
  642.  
  643. void DoContent(theWindow, theEvent)
  644. WindowPtr    theWindow;
  645. EventRecord    *theEvent;
  646. {
  647.     int                cntlCode;
  648.     ControlHandle     theControl;
  649.     int                pageSize;
  650.     GrafPtr            savePort;
  651.     
  652.     GetPort(&savePort);
  653.     SetPort(theWindow);
  654.     GlobalToLocal( &theEvent->where );
  655.     if (PtInRect( theEvent->where, &(**TEH).viewRect )){
  656.         TEClick( theEvent->where, (theEvent->modifiers & shiftKey )!=0, TEH);
  657.         /* senza autoscroll il TEclick non puÿ avere provocato scroll e quindi 
  658.         il punto di selezione Å ancora in vista, con autoscroll ci pensa quello
  659.         a portarlo in vista comunque, perÿ la posizione puÿ 
  660.         essere cambiata per cui su qualunque ROM: */
  661.         MaintainScrollBars(curr_window);
  662.         }
  663.     else if ((cntlCode = FindControl(theEvent->where, theWindow, &theControl)) != 0) {
  664.         if(cntlCode == inThumb) {
  665.             TrackControl(theControl, theEvent->where, 0L);
  666.             AdjustText(curr_window);
  667.             }
  668.         else
  669.             TrackControl(theControl, theEvent->where, &ScrollProc);
  670.         }
  671.     SetPort(savePort);
  672. }
  673.  
  674. void MyGrowWindow( w, p )
  675. WindowPtr w;
  676. Point p;
  677. {
  678.     GrafPtr    savePort;
  679.     long    theResult;
  680.     Rect     r;
  681.     /* in modalitê autowrap e per file lunghi questa routine e MyZoomWindow sono lente, 
  682.     ma visto che cosô non Å in modalitê scroll, suppongo che la colpa sia del ricalcolo 
  683.     degli inizi di riga per cui non c'Å niente da fare */
  684.  
  685.     GetPort( &savePort );
  686.     SetPort( w );
  687.  
  688.     SetRect(&r, 200, 90, screenBits.bounds.right, screenBits.bounds.bottom);
  689.     theResult = GrowWindow( w, p, &r );
  690.     if (theResult != 0){
  691.         EraseRect(&w->portRect);
  692.         SizeWindow( w, loword(theResult), hiword(theResult), 1);
  693.         HidePen();
  694.         resize_controls(w);
  695.         resize_text(w);
  696.         AdjustText(curr_window);
  697.         ShowPen();
  698.         }
  699.     SetPort( savePort );
  700. }
  701.  
  702. void myZoomWindow(w,where,code)
  703. register WindowPtr w;
  704. Point where;
  705. {
  706.     GrafPtr saveport;
  707.     GetPort (&saveport);
  708.     SetPort (w);
  709.     if ( TrackBox(w, where, code)) {
  710.         EraseRect(&w->portRect);
  711.         ZoomWindow (w, code, 0);
  712.         HidePen();
  713.         resize_controls(w);
  714.         resize_text(w);
  715.         AdjustText(w);
  716.         ShowPen();
  717.     }
  718.     SetPort (saveport);
  719. }
  720.  
  721.  
  722. static void resize_controls(w)
  723. register WindowPtr w;
  724. {
  725.     MoveControl(((window_def*)w)->vScroll, w->portRect.right - SBarWidth, 
  726.             w->portRect.top-1);
  727.     SizeControl(((window_def*)w)->vScroll, SBarWidth+1, 
  728.             w->portRect.bottom - w->portRect.top-(SBarWidth-2));
  729. #ifdef HSCROLL
  730.     if(((window_def*)w)->flags & HSCROLL){
  731.         int hsize=w->portRect.right - w->portRect.left-(SBarWidth-2);
  732.         MoveControl(((window_def*)w)->hScroll, w->portRect.left - 1, 
  733.             w->portRect.bottom-SBarWidth);
  734.         SizeControl(((window_def*)w)->hScroll, hsize, SBarWidth+1);
  735.         }
  736. #endif
  737. }
  738.  
  739.  
  740. static void resize_text(w)
  741. register WindowPtr w;
  742. {
  743.     int oldbottomline = GetCtlValue(((window_def*)w)->vScroll);
  744.     int oldtopchar = (*((window_def*)w)->TEH)->lineStarts [ oldbottomline ];
  745.  
  746.     InvalRect(&w->portRect);
  747.     SetView(w);
  748.     if(!(((window_def*)w)->flags&HSCROLL) )
  749.         testo_in_abbondanza(((window_def*)w)->TEH,&oldtopchar);
  750.     SetVScrollMax(w);
  751.  
  752. #ifdef HSCROLL
  753.     if(((window_def*)w)->flags & HSCROLL){
  754.         SetCtlValue(((window_def*)w)->vScroll,oldbottomline);
  755.         return;
  756.         }
  757. #endif
  758.     /* in modalitê autowrap cambiare dimensioni cambia anche la
  759.     suddivisione in righe, bisogna verificare che pi¥ o meno quello che viene
  760.     mostrato nella finestra sia sempre lo stesso pezzo di file */
  761.     SetCtlValue( ((window_def*)w)->vScroll, find_new_position(w,oldtopchar) );
  762.  
  763. }
  764.  
  765. static void testo_in_abbondanza(myTEH,oldtopchar)
  766. /* the max number of chars that the window may hold may change when
  767. resizing it, changing font or going to autowrap, delete excess text
  768. */
  769. register TEHandle myTEH;
  770. int *oldtopchar;
  771. {
  772. int olds;
  773. if( (olds=(**myTEH).nLines - 32000/(**myTEH).lineHeight )>0 ){
  774.     int olde,charsToDelete;
  775.     charsToDelete= (**myTEH).lineStarts[olds];
  776.     /*print_number("chars=",charsToDelete);
  777.     print_number("lines=",olds); */
  778.     if((*oldtopchar -= charsToDelete)<0) *oldtopchar=0;
  779.     if((olds=(**myTEH).selStart-charsToDelete)<0) olds=0;
  780.     if((olde=(**myTEH).selEnd-charsToDelete)<0) olde=0;
  781.     TESetSelect(0L, (long) charsToDelete, myTEH);
  782.     TEDelete (myTEH);
  783.     TESetSelect((long)olds, (long) olde, myTEH);
  784.     }
  785. }
  786.  
  787. short find_new_position(w,oldtopchar)
  788. /* in TeachText and in other editors, many operations change the portion
  789. of text which is visible in the window. With this routine, the window
  790. is scrolled so that the first character on top bottom remains the first
  791. character on top bottom, it that's possible, even after a resize or a
  792. change of font or size.
  793. By G. Speranza: it existed since the first 1.1 alfa version of suntar, but
  794. a silly last-minute bug destroyed its work in the shipping 1.1
  795. */
  796. window_def* w;
  797. register short oldtopchar;
  798. {
  799.     register short i=0;
  800.     register short *p= (**((window_def*)w)->TEH).lineStarts;
  801.     while(*p++ < oldtopchar) i++;
  802.     return i;
  803. }
  804.  
  805. void CloseMyWindow()
  806. /* to be called for clicks in the close box */
  807. {
  808.     curr_window->used=false;
  809.     TEDispose(TEH);
  810.     CloseWindow(curr_window);
  811.     curr_window=NULL;
  812.     n_currently_open--;
  813. }
  814.  
  815.  
  816. /******************************************************************************
  817.  PositionDialog        (from tinyEdit.c, another demo editor from Symantec, 
  818.                      but modified to center with respect the the area below the
  819.                      menu bar, I think that's what Apple meant in its guidelines )
  820.  
  821.         Center the bounding box of a dialog or alert in the upper third
  822.         of the screen.  This is the preferred location according to the
  823.         Human Interface Guidelines.
  824.         Modificato: non ho ben capito come fa quello della Apple
  825.         (utilities.c) ma ho la sensazione che faccia cosô, lascia fuori la
  826.         men¥ bar dal conto
  827.  ******************************************************************************/
  828.  
  829. void    PositionDialog(theRect)
  830. Rect *theRect;
  831. {
  832. short left,top;
  833.  
  834.                 /* Center horizontally on screen    */
  835.     left = (screenBits.bounds.right - (theRect->right - theRect->left)) / 2;
  836.  
  837.                 /* Leave twice as much space below    */
  838.                 /*   as above the rectangle        */    
  839.     top = MBARHEIGHT +
  840.      (screenBits.bounds.bottom - MBARHEIGHT - (theRect->bottom - theRect->top)) / 3;
  841.  
  842.     theRect->right += left - theRect->left;
  843.     theRect->left = left;
  844.     theRect->bottom += top - theRect->top;
  845.     theRect->top = top;
  846. }
  847.