home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume17 / tcl-editor / part08 / windows.c < prev   
Encoding:
C/C++ Source or Header  |  1992-03-18  |  17.9 KB  |  783 lines

  1. /* $Header: /nfs/unmvax/faculty/crowley/x/pt/RCS/windows.c,v 1.9 1992/03/04 17:07:18 crowley Exp crowley $ */
  2.  
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include "pt.h"
  6. #include <stdio.h>
  7. #include <sys/file.h>
  8. #ifdef uts
  9. #include <fcntl.h>
  10. #endif
  11.  
  12. /* the list of active windows, top to bottom */
  13. struct window *windowList = NULL;
  14.  
  15. /* the active window */
  16. struct window *activeWindow = NULL;
  17.  
  18. extern struct openFile *files;
  19.  
  20. void
  21. initWindows()
  22. {
  23.     extern char charTable[];
  24.  
  25.     charTable['\n'] = 1;
  26.     charTable[BLOCK_EOF] = 2;
  27.     charTable['\t'] = 3;
  28. }
  29.  
  30. void
  31. MakeWindowActive( w )
  32.     struct window *w;
  33. {
  34.     extern struct window *activeWindow;
  35.  
  36.     if( w != activeWindow ) {
  37.         /* remember the old active window */
  38.         struct window *oldw = activeWindow;
  39.  
  40.         activeWindow = w;
  41.         banner( oldw, 0 );
  42.         banner( w, 0 );
  43.     }
  44. }
  45.  
  46. struct window *
  47. createWindow( w, fileName, geometry )
  48.     struct window * w;
  49.     char * fileName;
  50.     char * geometry;
  51. {
  52.     extern struct window *selWindow;
  53.     extern Offset selBegin, selEnd;
  54.     extern char msgBuffer[];
  55.     extern int maxFiles;
  56.     extern int debug;
  57.     extern int autoZoom;
  58.     extern char * textFont;
  59.     extern int hypertextOn;
  60.     extern Display *MainDisplay;
  61. #ifdef HYPERTEXT
  62.     extern DBM *currentDB;
  63.     extern Document currentDocument;
  64. #endif
  65.     extern unsigned char beginMarkerChar;
  66.     extern Tcl_Interp * interp;
  67.     extern BrowserData * mainBrowser;
  68.     extern Window MainWindow;
  69.  
  70.     int createToo = (w == NULL);
  71.     char * name;
  72.  
  73.     if( createToo ) {    /* we need to create the window as well as */
  74.                 /* load the new file into it */
  75.         w = (struct window *) PtMalloc( sizeof(struct window),
  76.                         "Window structure" );
  77.     }
  78.  
  79.     w->fileId = getFileId(fileName);
  80.     w->realFileId = w->fileId;
  81.     if( w->fileId == -1 ) {
  82.         /* file not found, do not open the window */
  83.         printf( "File %s not found\n", fileName );
  84.         return NULL;
  85.     }
  86. #ifdef HYPERTEXT
  87.     if( hypertextOn && getFileByte(w->fileId,0) == (int)beginMarkerChar ) {
  88.         /* This is a hypertext file */
  89.         extern MapID naturalMap;
  90.         FileID fileID;
  91.         unsigned int flags;
  92.         BlockID blockID;
  93.  
  94.         w->db = currentDB;
  95.         w->document = currentDocument;
  96.         fileID = LookupFileByName( w->db, w->document,
  97.                         files[w->fileId].origName );
  98.         if( fileID == NullObject ) {
  99.             printf(
  100. "ERROR: could not find file %s. Displaying as an ordinary file\n",
  101.                 files[w->fileId].origName );
  102.             goto ordinary_file;
  103.         }
  104.         w->file = GetFile( w->db, fileID, ALLOCATE );
  105.  
  106.         /* get the inital view */
  107.         w->view = NULL;    /* not using views yet */
  108.  
  109.         /* get the maps from the initial view */
  110.         w->blockMap = GetMap( w->db, naturalMap, ALLOCATE);
  111.         if( w->blockMap == NULL ) {
  112.             printf( "Cannot find natural map in database %s\n",
  113.                                 fileName );
  114.             return NULL;
  115.         }
  116.         /* Maybe later we can fetch these */
  117.         w->fromLinkMap = NULL;
  118.         w->toLinkMap = NULL;
  119.  
  120.         /* get the initial block of the initial view */
  121.         (void)ReadBlockMarker( w->fileId, 1, &blockID, &flags );
  122.         w->block = GetBlock( w->db, blockID, ALLOCATE);
  123.         if( w->block == NULL ) {
  124.             printf( "Cannot find initial block in database %s\n",
  125.                                 fileName );
  126.             return NULL;
  127.         }
  128.  
  129.         /* Split up the file so that all block markers are in */
  130.         /* separate pieces.  Other code depends on this to be true. */
  131.         SeparateBlockMarkers( w );
  132.  
  133.         /* fileId already copied to realFileId (above) */
  134.         w->fileId = CreateViewFile( w );
  135.     } else {
  136.     ordinary_file:
  137.         /* This is an ordinary file */
  138.         w->db = NULL;
  139.         w->document = NULL;
  140.         w->view = NULL;
  141.         w->block = NULL;
  142.         w->blockMap = NULL;
  143.         w->fromLinkMap = NULL;
  144.         w->toLinkMap = NULL;
  145.         w->file = NULL;
  146.     }
  147. #endif
  148.  
  149.     w->posTopline = 0;
  150.  
  151.     if( createToo ) {
  152.         /* insert w into the doubly linked windowList */
  153.         if( windowList == NULL ) {
  154.             w->prevWindow = NULL;
  155.             w->nextWindow = NULL;
  156.             windowList = w;
  157.         } else {
  158.             windowList->prevWindow = w;
  159.             w->prevWindow = NULL;
  160.             w->nextWindow = windowList;
  161.             windowList = w;
  162.         }
  163.     }
  164.  
  165.     w->nameOffset = getBaseName(files[w->fileId].origName);
  166.  
  167.     /* set the default window parameters */
  168.     w->posBotline = 0;
  169.     w->numTopline = 1;
  170.     w->numBotline = -1;
  171.     w->indent = 0;
  172.     
  173.     /* set up the last row cache */
  174.     w->posCurLast = 0;
  175.     w->lastPosTop = 0;
  176.     w->rowCurLast = 0;
  177.  
  178.     /* set up the margins */
  179.     w->topMargin = 2;
  180.     w->leftMargin = 4;
  181.  
  182.     /* set up the font name */
  183.     w->font.name = PtMalloc(strlen(textFont)+1, "font name");
  184.     strcpy(w->font.name, textFont);
  185.     /* height = 0 will ensure that the old font will not be reused */
  186.     (w->font).height = 0;
  187.     
  188.     /* create the three GCs needed by each window */
  189.     (w->font).gc_normal = XCreateGC(MainDisplay, MainWindow,
  190.                     0, NULL);
  191.     (w->font).gc_selected = XCreateGC(MainDisplay, MainWindow,
  192.                     0, NULL);
  193.     (w->font).gc_underline = XCreateGC(MainDisplay, MainWindow,
  194.                     0, NULL);
  195.  
  196.     /* other setups */
  197.     w->x_window_id = NULL;
  198.     w->oldWidth = 0;
  199.     w->closeInform = NULL;
  200.     w->lineNumbers = 0;
  201.     
  202.     /* if there is a file in the window and there is not current */
  203.     /* selection, then move the selection to the new window */
  204.     if( w->fileId != -1 && selWindow == NULL ) {
  205.         /* put the selection at the first char in this window */
  206.         selWindow = w;
  207.         selBegin = 0;
  208.         selEnd = 0;
  209.     }
  210.  
  211.     if( createToo ) {
  212.         w->screen_image = NULL;
  213.         /* this will cause a call to WorkspaceResized on the */
  214.         /* first expose event */
  215.         w->nRows = 0;
  216.         /*  create a text window */
  217.         (void)ExecTclCommand( "update" );
  218.         sprintf( msgBuffer, "TextWindow %s", geometry );
  219.         name = ExecTclCommand( msgBuffer );
  220.         w->tk_pathname = Tk_GetUid( name );
  221.         w->tk_toplevel = Tk_NameToWindow( interp, w->tk_pathname,
  222.                         mainBrowser->tk_toplevel );
  223.         sprintf( msgBuffer, "%s.VScrollAndText.Text", w->tk_pathname );
  224.         w->tk_text = Tk_NameToWindow( interp, msgBuffer,
  225.                         w->tk_toplevel);
  226.         w->x_window_id = Tk_WindowId( w->tk_text );
  227.  
  228.         (void)ExecTclCommand( "update" );
  229.  
  230.         /* zoom of necessary */
  231.         if( autoZoom )
  232.             ZoomWindow( w, 0 );
  233.     }
  234.  
  235.     /* make the new window the active window */
  236.     MakeWindowActive( w );
  237.  
  238.     /* update the list of open windows */
  239.     NewOpenList();
  240.  
  241.     return w;
  242. }
  243.  
  244. int
  245. closeWindow(w, ask)
  246.     register struct window *w;
  247.     int ask;
  248. {
  249.     extern struct window *selWindow;
  250.     extern struct window *activeWindow;
  251.     extern Offset selBegin, selEnd;
  252.     extern char msgBuffer[];
  253.     extern int debug;
  254.  
  255.     struct window * w_prev, * w_next;
  256.  
  257.     /* first destroy the widget tree (the shell is the top) */
  258.     
  259. #ifdef HYPERTEXT
  260.     /* free the objects and close the database */
  261.     if( w->db != NULL ) {
  262.         PutFile( w->db, w->file, RELEASE );
  263.         PutBlock( w->db, w->block, RELEASE );
  264.         PutMap( w->db, w->blockMap, RELEASE );
  265.         PutView( w->db, w->view, RELEASE );
  266.         PutDocument( w->db, w->document, RELEASE );
  267.     }
  268. #endif
  269.  
  270.     if( closeFile(w->fileId, ask) == -1 )
  271.         return -1;
  272.  
  273.     /* unlink this window from the window list */
  274.     w_prev = w->prevWindow;
  275.     w_next = w->nextWindow;
  276.     if( w_prev == NULL )
  277.         windowList = w_next;
  278.     else
  279.         w_prev->nextWindow = w_next;
  280.     if( w_next != NULL )
  281.         w_next->prevWindow = w_prev;
  282.     if( windowList == NULL )
  283.         activeWindow = NULL;
  284.  
  285.     /* is the selection in this window? */
  286.     if( w == selWindow ) {
  287.         /* move the selection to the top window */
  288.         selWindow = windowList;
  289.         if( selWindow != NULL ) {
  290.             selBegin = 0;
  291.             selEnd = selBegin;
  292.         }
  293.     }
  294.  
  295.     /* is this the active window? */
  296.     if( w == activeWindow ) {
  297.         MakeWindowActive( selWindow );
  298.     }
  299.  
  300.     (void)ExecTclCommand( "update" );
  301.     Tk_DestroyWindow( w->tk_toplevel );
  302.     (void)ExecTclCommand( "update" );
  303.  
  304.     /* free any allocated strings */
  305.     if( w->closeInform != NULL ) {
  306.         sprintf( msgBuffer, "catch {send %s %s}", w->closeInform,
  307.                             w->tk_pathname );
  308.         (void)ExecTclCommand( msgBuffer );
  309.         PtFree( w->closeInform );
  310.     }
  311.  
  312.     PtFree( w->font.name );
  313.  
  314.     PtFree( w->screen_image );
  315.  
  316.     PtFree( (char *)w );
  317.  
  318.     /* update the list of open windows */
  319.     NewOpenList();
  320.  
  321.     return 0;
  322. }
  323.  
  324. static int timerIsOn = 0;
  325. static Tk_TimerToken timer_token = NULL;
  326. int intervalRows = 0;
  327. int scrollDown = 0;
  328. struct window * scroll_window;
  329.  
  330. static void
  331. DoOneHScroll()
  332. {
  333.     extern int undoMotion;
  334.     extern Display *MainDisplay;
  335.  
  336.     struct fontDataStruct *font = &( scroll_window->font);
  337.     int col1, col2, incr1, incr2, cols, wide;
  338.  
  339. #ifdef LATERLATER
  340.     if( undoMotion ) {
  341.         /* record in the change history */
  342.         thisChange = GetNewChange( ff );
  343.         thisChange->type = CMOTION;
  344.         thisChange->lineNumber = scroll_window->numTopline;
  345.         thisChange->length = scroll_window->numTopline + intervalRows;
  346.         thisChange->w = scroll_window;
  347.         thisChange->flags = 0;
  348.         RecordChange( ff, thisChange );
  349.     }
  350. #endif
  351.     cols = intervalRows;
  352.     wide = font->width;
  353.     if( scrollDown ) {
  354.         scroll_window->indent += cols;
  355.         incr1 = cols * wide;
  356.         incr2 = 0;
  357.         col1 = (scroll_window->nCols) - cols;
  358.         col2 = scroll_window->nCols - 1;
  359.     } else {
  360.         /* do not allow scrolling off the beginning */
  361.         if( cols > scroll_window->indent )
  362.             cols = scroll_window->indent;
  363.         scroll_window->indent -= cols;
  364.         incr1 = 0;
  365.         incr2 = cols * wide;
  366.         col1 = 0;
  367.         col2 = cols - 1;
  368.     }
  369.     XCopyArea( MainDisplay, scroll_window->x_window_id,
  370.         scroll_window->x_window_id, font->gc_normal,
  371.         scroll_window->leftMargin + incr1, 0,
  372.         (scroll_window->nCols - cols) * wide,
  373.         Tk_Height(scroll_window->tk_toplevel),
  374.         scroll_window->leftMargin + incr2, 0 );
  375.     drawWindowFast(scroll_window, 0, scroll_window->nRows-1, col1, col2 );
  376. }
  377.  
  378. /*ARGSUSED*/
  379. static void
  380. repeatHScroll( clientData )
  381.     ClientData clientData;
  382. {
  383.     DoOneHScroll();
  384.     timer_token = Tk_CreateTimerHandler( 100, repeatHScroll, 0 );
  385. }
  386.  
  387. void
  388. HScroll( w, how, x, button )
  389.     struct window *w;
  390.     int how;
  391.     int x;
  392.     int button;
  393. {
  394.     int top_unit;
  395.  
  396.     /* how = 0 ==> tk scrolling */
  397.     /* how = 1 ==> button press */
  398.     /* how = 2 ==> button release */
  399.     /* how = 3 ==> button motion */
  400.  
  401.     scroll_window = w;
  402.     switch( how ) {
  403.     case 0:        /* Tk scrolling */
  404.         top_unit = x;
  405.         intervalRows = top_unit - (w->indent);
  406.         break;
  407.     case 1:        /* button press */
  408.         intervalRows = (x - w->leftMargin) / (w->font).width;
  409.         switch( button ) {
  410.         case 1:
  411.             scrollDown = 0;
  412.             break;
  413.         case 2:
  414.             goto thumbing;
  415.         case 3:
  416.             scrollDown = 1;
  417.             break;
  418.         }
  419.         if( !timerIsOn ) {
  420.             DoOneHScroll();
  421.             timer_token = Tk_CreateTimerHandler( 500,
  422.                             repeatHScroll, 0 );
  423.             timerIsOn = 1;
  424.         }
  425.         break;
  426.     case 2:        /* (left or right) button release */
  427.         if( timerIsOn ) {
  428.             timerIsOn = 0;
  429.             Tk_DeleteTimerHandler( timer_token );
  430.         }
  431.         return;
  432.     case 3:        /* (middle) button motion */
  433.     thumbing:
  434.         intervalRows = w->indent
  435.                 - (x - w->leftMargin) / (w->font).width;
  436.         DoOneHScroll();
  437.         break;
  438.     }
  439.  
  440.     /* always scroll at least one column */
  441.     if( intervalRows < 1 )
  442.         intervalRows = 1;
  443. }
  444.  
  445. int
  446. DoOneVScroll()
  447. {
  448.     extern int undoMotion;
  449.     extern Display *MainDisplay;
  450.  
  451.     struct fontDataStruct *font = &(scroll_window->font);
  452.     int fid = scroll_window->fileId;
  453.     struct changeItem *thisChange;
  454.     int rowsScrolled, high, incr1, incr2, row1, row2;
  455.     struct openFile * ff = &files[fid];
  456.     int copy_height;
  457.  
  458.     if( undoMotion ) {
  459.         /* record in the change history */
  460.         thisChange = GetNewChange( ff );
  461.         thisChange->type = CMOTION;
  462.         thisChange->lineNumber = scroll_window->numTopline;
  463.         thisChange->length = scroll_window->numTopline + intervalRows;
  464.         thisChange->w = scroll_window;
  465.         thisChange->flags = 0;
  466.         RecordChange( ff, thisChange );
  467.     }
  468.  
  469.     rowsScrolled = intervalRows;
  470.     high = font->height;
  471.     copy_height = (scroll_window->nRows - intervalRows) * high;
  472.     if( scrollDown ) {
  473.         scroll_window->posTopline = nextLine( fid,
  474.                 scroll_window->posTopline, &rowsScrolled );
  475.         scroll_window->numTopline += rowsScrolled;
  476.         scroll_window->numBotline += rowsScrolled;
  477.         incr1 = rowsScrolled * high;
  478.         incr2 = 0;
  479.         row1 = scroll_window->nRows - rowsScrolled;
  480.         if( rowsScrolled < intervalRows )
  481.             row1 = rowsScrolled + 1;
  482.         row2 = scroll_window->nRows-1;
  483.     } else {
  484.         /* do not allow scrolling off the beginning */
  485.         if( scroll_window->posTopline <= 0 )
  486.             return 0;
  487.         scroll_window->posTopline = prevLine( fid,
  488.                 scroll_window->posTopline, &rowsScrolled);
  489.         scroll_window->numTopline -= rowsScrolled;
  490.         scroll_window->numBotline -= rowsScrolled;
  491.         row1 = intervalRows - rowsScrolled;
  492.         if( row1 > 0 )
  493.             copy_height += row1 * high;
  494.         incr1 = 0;
  495.         incr2 = rowsScrolled * high;
  496.         row1 = 0;
  497.         row2 = rowsScrolled - 1;
  498.     }
  499.     /* only copy if we can use part of the present window */
  500.     if( intervalRows < scroll_window->nRows ) {
  501.         XCopyArea( MainDisplay, scroll_window->x_window_id,
  502.             scroll_window->x_window_id, font->gc_normal,
  503.             0, scroll_window->topMargin + incr1,
  504.             Tk_Width(scroll_window->tk_toplevel), copy_height,
  505.             0, scroll_window->topMargin + incr2 );
  506.         if( scrollDown && scroll_window->posBotline
  507.                     == fileSize(scroll_window->fileId) ) {
  508.             XClearArea( MainDisplay, scroll_window->x_window_id,
  509.                 0, copy_height,
  510.                 Tk_Width(scroll_window->tk_text),
  511.                 Tk_Height(scroll_window->tk_text)-copy_height,
  512.                 False
  513.             );
  514.             return rowsScrolled;
  515.         }
  516.     } else {
  517.         /* we went through the above calculations in order to get */
  518.         /* posTopline, numTopline and numBotline updated */
  519.         /* now fix up row1 and row2 */
  520.         row1 = 0;
  521.         row2 = scroll_window->nRows - 1;
  522.     }
  523.     drawWindowFast(scroll_window, row1, row2, 0, scroll_window->nCols-1 );
  524.     return rowsScrolled;
  525. }
  526.  
  527. /*ARGSUSED*/
  528. static void
  529. repeatVScroll( clientData )
  530.     ClientData clientData;
  531. {
  532.     (void)DoOneVScroll();
  533.     timer_token = Tk_CreateTimerHandler( 100, repeatVScroll, 0 );
  534. }
  535.  
  536. void
  537. VScroll( w, how, y, button )
  538.     struct window *w;
  539.     int how;
  540.     int y;
  541.     int button;
  542. {
  543.     /* how = 0 ==> tk scrolling */
  544.     /* how = 1 ==> button press */
  545.     /* how = 2 ==> button release */
  546.     /* how = 3 ==> button motion */
  547.     extern int button1ScrollsDown;
  548.  
  549.     int row1, row;
  550.     int fid = w->fileId;
  551.     Offset cp, offset;
  552.     int top_unit;
  553.     int delta, inwindow;
  554.     int scrollbar_height;
  555.  
  556.     scroll_window = w;
  557.     switch( how ) {
  558.     case 0:        /* Tk scrolling */
  559.         top_unit = y;
  560.         inwindow = w->posBotline - w->posTopline;
  561.         if( inwindow < 1 )
  562.             inwindow = 1;
  563.         delta = top_unit - w->posTopline;
  564.         if( delta < 0 ) {
  565.             delta = -delta;
  566.             scrollDown = 0;
  567.         } else
  568.             scrollDown = 1;
  569.         intervalRows = (w->nRows * delta) / inwindow;
  570.         if( intervalRows < 1 )
  571.             intervalRows = 1;
  572.         (void)DoOneVScroll();
  573.         break;
  574.     case 1:        /* button press */
  575.         intervalRows = (y - w->topMargin) / (w->font).height;
  576.         /* always scroll at least one line */
  577.         if( intervalRows < 1 )
  578.             intervalRows = 1;
  579.         switch( button ) {
  580.         case 1:
  581.             scrollDown = button1ScrollsDown;
  582.             break;
  583.         case 2:
  584.             goto thumbing;
  585.         case 3:
  586.             scrollDown = 1 - button1ScrollsDown;
  587.             break;
  588.         }
  589.         if( !timerIsOn ) {
  590.             (void)DoOneVScroll();
  591.             timer_token = Tk_CreateTimerHandler( 300,
  592.                             repeatVScroll, 0 );
  593.             timerIsOn = 1;
  594.         }
  595.         break;
  596.     case 2:        /* (left or right) button release */
  597.         if( timerIsOn ) {
  598.             timerIsOn = 0;
  599.             Tk_DeleteTimerHandler( timer_token );
  600.         }
  601.         return;
  602.     case 3:        /* (middle) button motion */
  603.     thumbing:
  604.         /* we get negative y values when the (grabbed) mouse goes */
  605.         /* above the scroll bar area.  Consider them zero. */
  606.         /* Also adjust for the case where the mouse pointer */
  607.         /* moves below the scrollbar area. */
  608.         scrollbar_height = Tk_Height(w->tk_text);
  609.         if( y < 0 )
  610.             y = 0;
  611.         else if( y > scrollbar_height )
  612.             y = scrollbar_height;
  613.         cp = fileSize( fid );
  614.         offset = (int)( ((double)y * cp) / scrollbar_height );
  615.         if( offset > cp )
  616.             offset = cp;
  617.         cp = w->posTopline;
  618.         row = w->numTopline;
  619.         while( cp < offset ) {
  620.             row1 = 1;
  621.             cp = nextLine( fid, cp, &row1 );
  622.             row += row1;
  623.         }
  624.         while( cp > offset ) {
  625.             row1 = 1;
  626.             cp = prevLine( fid, cp, &row1 );
  627.             row -= row1;
  628.         }
  629.         intervalRows = row - w->numTopline;
  630.         if( intervalRows == 0 )
  631.             return;
  632.         if( intervalRows < 0 ) {
  633.             intervalRows = -intervalRows;
  634.             scrollDown = 0;
  635.         } else
  636.             scrollDown = 1;
  637.         (void)DoOneVScroll();
  638.         break;
  639.     }
  640. }
  641.  
  642.  
  643. void
  644. topWindow(w)
  645.     register struct window *w;
  646. {
  647.     MakeWindowActive( w );
  648. }
  649.  
  650. void
  651. ZoomWindow( w, how )
  652.     struct window *w;
  653.     int how;
  654. {
  655.     extern int display_height;
  656.     extern int display_width;
  657.     extern Display *MainDisplay;
  658.     extern int debug;
  659.  
  660.     if( w->oldWidth == 0 ) {    /* not zoomed */
  661.         /* first save the present geometry */
  662.         w->oldX = Tk_X( w->tk_toplevel );
  663.         w->oldY = Tk_Y( w->tk_toplevel );
  664.         w->oldWidth = Tk_Width( w->tk_toplevel );
  665.         w->oldHeight = Tk_Height( w->tk_toplevel );
  666.  
  667.         /* now set up to zoomed geometry */
  668.         Tk_MoveResizeWindow( w->tk_toplevel,
  669.             (how ? 4 : w->oldX),
  670.             3,
  671.             (how ? display_width-8 : w->oldWidth),
  672.             display_height-37
  673.         );
  674.     } else {    /* unzoom */
  675.         /* restore the old geometry */
  676.         Tk_MoveResizeWindow( w->tk_toplevel,
  677.             w->oldX, w->oldY-25, w->oldWidth, w->oldHeight );
  678.         /* set up so that it indicates not zoomed */
  679.         w->oldWidth = 0;
  680.     }
  681. }
  682.  
  683. struct window *
  684. GetNewFile(w, fileName, geometry)
  685.     struct window * w;
  686.     char * fileName;
  687.     char * geometry;
  688. {
  689.     extern char msgBuffer[];
  690.     extern char textBuffer[];
  691.     extern char * returnString;
  692.  
  693.     int n;
  694.  
  695.     if( fileName == NULL ) {
  696. cancelWindow:
  697.         msg("New file cancelled", 1);
  698.         return NULL;
  699.     }
  700.     fileName = noWhiteSpace(fileName);
  701.     strcpy(textBuffer, fileName);
  702.     if( access(textBuffer, 0) == -1 ) {
  703.         sprintf( msgBuffer,
  704.             "MakeModalYesNo \"%s\" \"%s %s %s\" \"%s\" \"%s\"",
  705.             "Create file?",
  706.             "File", fileName, "does not exist.",
  707.             "Create it",
  708.             "Cancel new file" );
  709.         (void)ExecTclCommand( msgBuffer );
  710.         command( FWAITFORRETURNSTRING, "","","","","","");
  711.         if( returnString[0] != 'y' ) {
  712.             goto cancelWindow;
  713.         }
  714.         n = open(textBuffer, O_CREAT, 0644);
  715.         if( n < 0 ) {
  716.             sprintf(msgBuffer, "Cannot create %s: ", textBuffer);
  717.             msg(msgBuffer, 1);
  718.             goto cancelWindow;
  719.         } else
  720.             close(n);
  721.     }
  722.     return createWindow( w, textBuffer, geometry );
  723. }
  724.  
  725.  
  726. struct window *
  727. FindWindowByTkName( name )
  728.     char * name;
  729. {
  730.     extern struct window * windowList;
  731.  
  732.     struct window * w = windowList;
  733.     Tk_Uid uid_of_name = Tk_GetUid( name );
  734.  
  735.     while( w != NULL ) {
  736.         if( w->tk_pathname == uid_of_name  )
  737.             break;
  738.         w = w->nextWindow;
  739.     }
  740.     return w;
  741. }
  742.  
  743. void
  744. bottomFile( w )
  745.     struct window *w;
  746. {
  747.     extern int debug;
  748.  
  749.     Offset cp;
  750.     int j;
  751.     int i;
  752.     int fid = w->fileId;
  753.  
  754.     if( w == NULL )
  755.         return;
  756.     /* remember where we came from */
  757.     w->rowLastline = w->numTopline;
  758.     cp = w->posBotline;
  759.  
  760.     /* find the last line of the file */
  761.     i = 0;
  762.     while( 1 ) {
  763.         j = 1;
  764.         cp = nextLine( fid, cp, &j );
  765.         /* if j==0, we could not go down a line */
  766.         /* so we are at the end */
  767.         if( j == 0 )
  768.             break;
  769.         ++i;
  770.     }
  771.     ++i;    /* one more line so EOF mark shows */
  772.  
  773.     /* now move the window down and redraw it */
  774.     j = i;    /* since i is a register variable, we must use j here */
  775.     w->posTopline = nextLine( fid, w->posTopline, &j );
  776.     w->posBotline = cp;
  777.     w->numTopline += j;
  778.     w->numBotline += j;
  779.     w->indent = 0;
  780.     drawWindow(w);
  781. }
  782.  
  783.