home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / edit / point20 / command.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-18  |  16.8 KB  |  696 lines

  1. #include "pt.h"
  2. #include "malloc.h"
  3. #include "string.h"
  4. #include "process.h"
  5. #include "io.h"
  6. #include "stdlib.h"
  7. #include "conio.h"
  8.  
  9. #define STACKSIZE 2048
  10.  
  11. int pascal
  12. /* XTAG:command */
  13. command(fn, c, w)
  14.     int fn;
  15.     unsigned char c;
  16.     register struct window *w;
  17. {
  18.     extern unsigned char msgBuffer[];
  19.     extern unsigned char textBuffer[];
  20.     extern int debug;
  21.     extern struct window *selWindow;
  22.     extern struct window *activeWindow;
  23.     extern long selBegin, selEnd;
  24.     extern union REGS rin, rout;
  25.     extern int overType;
  26.     extern int searchMode;
  27.     extern int realSearchMode;
  28.     extern int mousePresent;
  29.     extern int scrRows, scrCols;
  30.     extern int i43lines;
  31.     extern unsigned char buttonVector[];
  32.     extern int menuRow, menuCol;
  33.     extern int lastOnTopline;
  34.     extern int lastCommand;
  35.     extern int macroIndex;
  36.     extern int macroSize;
  37.     extern int macroState;
  38.     extern int selMode;
  39.     extern int lastFn;
  40. /*    extern int errno;  */
  41. #ifdef OVERLAYS
  42.     extern int filesToOpen;
  43.     extern int primaryFilesToOpen;
  44.     extern struct openFile *ffsToOpen[];
  45.     extern unsigned char *overlayMap[];
  46.     extern unsigned char *stktop;
  47.     extern unsigned char primaryOverlay[];
  48.     extern unsigned char secondaryOverlay[];
  49.     extern unsigned char overlayString[];
  50.     extern unsigned char *overlayArguments;
  51.     extern int overlayState;
  52.     extern int quitExecuted;
  53. #endif
  54.     extern unsigned char *userMessages[];
  55.     extern struct openFile *files;
  56.     extern unsigned char maxTextCycles;
  57.     extern unsigned char maxBorderCycles;
  58.     extern struct SREGS segRegs;
  59.     extern struct menuBlock far *menus[];
  60.     extern struct optionItem options[];
  61.     extern unsigned char saveVideoMode;
  62.     extern union REGS rin, rout;
  63.     extern unsigned int dispMemory;
  64.  
  65.     int row1, col1;
  66.     int r1, r2;
  67.     int i, n;
  68.     long cp;
  69.     unsigned char ch;
  70.     unsigned char *fileName;
  71.     struct window *w2;
  72.     unsigned char *s, buffer[64];
  73. #ifdef OVERLAYS
  74.     unsigned char *userArgs;
  75.     unsigned char *saveStktop;
  76. #endif
  77.  
  78. /* since we are about to issue a command, we do not need to erase */
  79. /* the command description on the top line (so don't) */
  80. lastOnTopline = 0;
  81.  
  82. startOver:
  83.  
  84. #ifdef OVERLAYS
  85. if( 200 <= fn && fn <= 255 ) {
  86.     fileName = overlayMap[fn-200];
  87. doOverlay:
  88.  
  89.     n = strlen(fileName) - 1;
  90.     if( fileName[n] == ' ' )
  91.         userArgs = getInput("Execute: ", fileName, 5);
  92.     else
  93.         userArgs = fileName;
  94.  
  95.     /* allow user to cancel */
  96.     if( userArgs == NULL ) {
  97.         msg("Command cancelled", 1);
  98.         goto returnLocation;
  99.     }
  100.  
  101.     /* make a copy of the command line */
  102.     strncpy(overlayString, userArgs, 128);
  103.  
  104.     overlayArguments = strchr(overlayString, ' ');
  105.     if( overlayArguments != NULL )
  106.         *overlayArguments++ = '\0';
  107.     else
  108.         overlayArguments = "";
  109.  
  110.     /* see if this overlay is loaded and inactive */
  111.  
  112.     /* see if this is a primary or secondary overlay */
  113.     n = strlen(overlayString) - 1;
  114.     if( overlayString[n] == '*' ) {    /* primary overlay is to be loaded */
  115.         /* eliminate the '*' which means the overlay is primary */
  116.         overlayString[n] = '\0';
  117.  
  118.         if( (overlayState & 0x1) != 0 ) {
  119.             /* a primary overlay is already loaded */
  120.             if( strcmp(primaryOverlay, overlayString) == 0 ) {
  121.                 /* same overlay, reactivate this one */
  122.                 if( (overlayState & 0x2) != 0 ) {
  123.                     strcpy(textBuffer, "0");
  124.                     secondaryOverlay[0] = '\0';
  125.                     overlayState &= ~0x2;
  126.                     overlayState |= 0x14;
  127.                 } else {
  128.                     strcpy(textBuffer, overlayArguments);
  129.                 }
  130.             } else {
  131.                 /* remember the name of the new overlay */
  132.                 strcpy(primaryOverlay, overlayString);
  133.                 strcpy(textBuffer, "0");
  134.                 /* indicate we are unloading a primary */
  135.                 /* overlay */
  136.                 overlayState |= 0x8;
  137.                 /* check for secondary overlay */
  138.                 if( (overlayState & 0x2) != 0 ) {
  139.                     overlayState &= ~0x2;
  140.                     overlayState |= 0x4;
  141.                     secondaryOverlay[0] = '\0';
  142.                 } else {
  143.                 }
  144.             }
  145.             /* Drop out of command loop. This will return to */
  146.             /* "overlayDriver()" which will return (from the */
  147.             /* software interrupt)to the overlay. */
  148.             return 1;
  149.         } else {
  150.             strcpy(primaryOverlay, overlayString);
  151.             overlayState |= 0x1;
  152.             /* see if we have to unload the secondary overlay */
  153.             if( (overlayState & 0x2) != 0 ) {
  154.                 strcpy(textBuffer, "0");
  155.                 overlayState &= ~0x2;
  156.                 overlayState |= 0x4;
  157.                 secondaryOverlay[0] = '\0';
  158.                 return 1;
  159.             }
  160.             /* else, drop though and load the overlay */
  161.         }
  162.     } else {    /* secondary overlay is to be loaded */
  163.         if( (overlayState & 0x2) != 0 ) {
  164.             /* a secondary overlay is already loaded */
  165.             if( strcmp(secondaryOverlay, overlayString) == 0 ) {
  166.                 /* same overlay, reactivate this one */
  167.                 strcpy(textBuffer, overlayArguments);
  168.             } else {
  169.                 /* different overlay, unload this one */
  170.                 /* 0 argument means to exit the overlay */
  171.                 strcpy(textBuffer, "0");
  172.                 strcpy(secondaryOverlay, overlayString);
  173.                 /* indicate we are unloading an overlay */
  174.                 overlayState |= 0x4;
  175.             }
  176.             /* Drop out of command loop. This will return to */
  177.             /* "overlayDriver()" which will return (from the */
  178.             /* software interrupt)to the overlay. */
  179.             return 1;
  180.         } else {
  181.             strcpy(secondaryOverlay, overlayString);
  182.             overlayState |= 0x2;
  183.             /* drop though and load the overlay */
  184.         }
  185.     }
  186.  
  187. retryOverlay:
  188.     /* save the old value of stktop */
  189.     saveStktop = stktop;
  190.  
  191.     /* set up the stack to use when the overlay calls us back */
  192.     stktop = malloc(STACKSIZE);
  193.     if( stktop == NULL ) {
  194.         msg(userMessages[NOSPACEMSG], 3);
  195.         goto returnLocation;
  196.     }
  197.     stktop += STACKSIZE-8;
  198.  
  199.     /* We have to reopen any files opened by the overlay when it */
  200.     /* exits since DOS will close them automatically. If fileToOpen */
  201.     /* is already non-zero then an overlay is already loaded. */
  202.     if( filesToOpen == 0 )
  203.         filesToOpen = 1;
  204.     else
  205.         primaryFilesToOpen = filesToOpen;
  206.  
  207.     n = spawnlp(0, overlayString, overlayString, overlayArguments, NULL);
  208.     if( n == -1 ) {
  209.         sprintf(msgBuffer,
  210. "Overlay %s could NOT be executed [Press any key to continue]",
  211.             overlayString);
  212.         msg(msgBuffer, 3);
  213.     } else if( n > 0 ) {
  214.         sprintf(msgBuffer, "Overlay %s returned error code of 0x%X",
  215.             overlayString, n);
  216.         msg(msgBuffer, 1);
  217.     } 
  218.  
  219.     /* free up the stack space */
  220.     stktop -= STACKSIZE-8;
  221.     free(stktop);
  222.     /* now restore the previous value of stktop */
  223.     stktop = saveStktop;
  224.  
  225.     /* reopen any files that were opened during the overlay */
  226.     /* since DOS will have closed them automatically */
  227.     /* if this is a secondary overlay that is exiting, then only */
  228.     /* reopen the files that were opened since the secondary */
  229.     /* overlay was loaded */
  230.     if( primaryFilesToOpen > 0 )
  231.         n = primaryFilesToOpen;
  232.     else
  233.         n = 1;
  234.     for(i = n; i < filesToOpen; ++i) {
  235.         ff = ffsToOpen[i-1];
  236.         ff->origHandle = openls(ff->origName, 0);
  237.     }
  238.     if( primaryFilesToOpen > 0 ) {
  239.         filesToOpen = primaryFilesToOpen;
  240.         primaryFilesToOpen = 0;
  241.     } else
  242.         filesToOpen = 0;
  243.     
  244.     if( quitExecuted )
  245.         return 1;
  246.  
  247.     if( (overlayState & 0x4) != 0 ) {
  248.         /* see if we have to unload the primary overlay also */
  249.         overlayState &= ~0x4;
  250.         if( (overlayState & 0x8) != 0 ) {
  251.             strcpy(textBuffer, "0");  /* unload overlay arg. */
  252.             return 1;
  253.         }
  254.         if( (overlayState & 0x10) != 0 ) {
  255.             overlayState &= ~0x10;
  256.             strcpy(textBuffer, overlayArguments);
  257.             return 1;
  258.         }
  259.         goto retryOverlay;
  260.     } else if( (overlayState & 0x8) != 0 ) {
  261.         overlayState &= ~0x8;
  262.         goto retryOverlay;
  263.     } else if( (overlayState & 0x2) != 0 ) {
  264.         overlayState &= ~0x2;
  265.         secondaryOverlay[0] = '\0';
  266.     } else {    /* overlayState == 0x1 (primary overlay only) */
  267.         primaryOverlay[0] = '\0';
  268.         overlayState = 0;
  269.     }
  270.  
  271.     initMouse(5, 10, 0);
  272.     goto returnLocation;
  273. }
  274. #endif
  275.  
  276. if( fn < 50 ) {
  277.     n = command2(fn, c, w);
  278.     if( fn != FMOUSECOM1 && fn != FMOUSECOM2
  279.         && fn != FDONOTHING && fn > 0 ) {
  280.         lastCommand = fn;
  281.     }
  282.     lastFn = fn;
  283.     if( n != 2 )
  284.         return n;
  285.     /* return value of 2 means that select and extend want the */
  286.     /* change menu command to be executed */
  287.     fn = FCHANGEMENU;
  288.     /* and drop through since change menu >= 50 */
  289. }
  290.  
  291. /* else do commands 50 and up */
  292.  
  293. switch( fn ) {
  294.  
  295. case FAUTOSAVEINTERVAL:case FAUTOSCROLLRATE:case FAUTOINDENT:
  296. case FBORDERCOLORS:case FCENTERMENUS:
  297. case FDOUBLECLICKDELAY:case FFILEPATTERN:case FFILESORT:case FFINDWHOLEWORDS:
  298. case FFSDIRS:case FFSMENU:case FFSPATTERNS:case FHELPMODE:case FI43LINES:
  299. case FIGNORECASE:  case FLINESOVERFIND: case FMSGCOLORS:    
  300. case FPATHNAMES:   case FOVERTYPE: case FRESEARCH:
  301. case FOREADONLY:   case FREDEFINE:      case FRIGHTMARGIN:
  302. case FSCROLLDELAY: case FSCROLLRATE:    case FSEARCHMODE: case FSMOOTHSCROLL:
  303. case FTABWIDTH:    case FTOPONFIND:  case FTAGPATTERN:
  304. case FTAGMARKER:   case FTEXTCOLORS:    case FUNIXMODE:   case FVIDEOMODE:
  305.     n = 0;
  306.     while( options[n].commandNumber != fn ) {
  307.         if( options[n].index == OLASTITEM ) {
  308.             /* this "cannot happen" */
  309.             msg("System Error (command.c:~300)", 3);
  310.             break;
  311.         }
  312.         ++n;
  313.     }
  314.     r1 = options[n].type;
  315.     if( r1 == OINTEGER || r1 == OSTRING
  316.      || r1 == UINTEGER || r1 == USTRING ) {
  317.         if( r1 == OINTEGER || r1 == UINTEGER )
  318.             sprintf(buffer, "%d", *(options[n].variable));
  319.         else
  320.             strcpy(buffer,
  321.                 (unsigned char *)(options[n].variable));
  322.         sprintf(textBuffer, "New value for option `%s': ",
  323.             options[n].name );
  324.         s = getInput(textBuffer, buffer, 0);
  325.         if( s == NULL ) {
  326.             msg("Option value not changed", 1);
  327.             break;
  328.         }
  329.     } else
  330.         s = NULL;
  331.     setOption(n, s, w);
  332.     redrawBox(0, 0, scrRows-1, scrCols-1);
  333.     updateScreen(0, scrRows-1);
  334.     break;
  335.  
  336. case FTAG:
  337. case FTAGSEL:
  338. case FCTAG:
  339. case FCTAGSEL:
  340.     (void)findTag(fn);
  341.     break;
  342.  
  343. case FKEYWORD:
  344. case FKEYWORDSEL:
  345.     (void)findKeyword(fn);
  346.     break;
  347.  
  348. #ifdef GENIUS66
  349. case F66LINES:    /* special code for the Genius display */
  350.     msg("Setting up MDS 66 line text mode for Genius monitor", 1);
  351.     dispMemory = 0xB000;
  352.     saveVideoMode = 8;
  353.     rin.h.al = 8;    /* 80x66 MDS (Genius) */
  354.     rin.h.ah = 0;    /* set video mode */
  355.     int86(0x10, &rin, &rout);
  356.     outpw(0x3B0, 0x1);
  357.     outpw(0x3B8, 0x28);
  358.     outpw(0x3D8, 0x0);
  359.     initMouse(5, 10, 1);
  360.     goto redrawScreen;
  361. #endif
  362.  
  363. case FREPLACECMD:
  364.     execCmd(fn);
  365.     break;
  366.  
  367. case FCYCLECOLORS:
  368.  
  369. #ifdef BARNEY
  370. /* determine the current display mode */
  371. rin.h.ah = 15;
  372. int86(0x10, &rin, &rout);
  373. i = rout.h.al;
  374. sprintf(msgBuffer, "mode=0x%X, new mode?", i);
  375. s = getInput(msgBuffer, "2", 0);
  376. sscanf(s, "%x", &saveVideoMode);
  377. rin.h.al = saveVideoMode;
  378. rin.h.ah = 0;    /* set video mode */
  379. int86(0x10, &rin, &rout);
  380. initMouse(5, 10, 1);
  381. redrawBox(0, 0, scrRows-1, scrCols-1);
  382. updateScreen(0, scrRows-1);
  383. break;
  384. #endif
  385.     if( w == NULL )
  386.         break;
  387. /******************************************
  388.     fileName = getInput("t(ext), b(order), a(ll): ", "a", 1);
  389.     ch = tolower(*fileName);
  390. ******************************************/
  391.     ch = 'a';
  392.     if( ch == 't' || ch == 'a' ) {
  393.         if( ++(w->textCycle) >= maxTextCycles )
  394.             w->textCycle = 0;
  395.     }
  396.     if( ch == 'b' || ch == 'a' ) {
  397.         if( ++(w->borderCycle) >= maxBorderCycles )
  398.             w->borderCycle = 0;
  399.     }
  400.     setWindowColors(w);
  401.     goto redrawScreen;
  402.  
  403. case FREADONLY:
  404.     if( w == NULL )
  405.         break;
  406.     if( files[w->fileId].readOnly ) {
  407.         /* file is readOnly now.  Only allow writing if the */
  408.         /* file being edited has DOS write permission */
  409.         /* check for read and write permissions (6 => RW) */
  410.         if( access(files[w->fileId].origName, 6) == 0 )
  411.             files[w->fileId].readOnly = 0;
  412.     } else
  413.         /* allow any file to be readOnly */
  414.         files[w->fileId].readOnly = 1;
  415. redrawScreen:
  416.     redrawBox(0, 0, scrRows-1, scrCols-1);
  417.     updateScreen(0, scrRows-1);
  418.     break;
  419.  
  420. #ifdef OVERLAYS
  421. case FOVERLAY:
  422.     fileName = getInput("File to execute (and arguments): ", "", 0);
  423.     goto doOverlay;
  424. #endif
  425.  
  426. case FSWAPTOP:
  427.     if( w == NULL )
  428.         break;
  429.     doTopWindow(w, 3);
  430.     break;
  431.  
  432. case FRECAPITALIZE:
  433.     if( selWindow == NULL )
  434.         break;
  435.     ch = readChar(selWindow->fileId, selBegin);
  436.     selEnd = selBegin;
  437.     if( !isascii(ch) ) {
  438.         ++selBegin;
  439.         break;
  440.     }
  441.     if( ch == '\r' ) {
  442.         /* scan past all newlines and returns */
  443.         while( 1 ) {
  444.             ch = readChar(selWindow->fileId, ++selBegin);
  445.             if( ch != '\r' && ch != '\n' )
  446.                 break;
  447.         }
  448.         selEnd = selBegin;
  449.         goto redrawScreen;
  450.     }
  451.     if( isupper(ch) )
  452.         ch = _tolower(ch);
  453.     else if( islower(ch) )
  454.         ch = _toupper(ch);
  455.     deleteChars(selWindow->fileId, NOUPDATE, 0);
  456.     insChar(ch, 1);
  457.     break;
  458.  
  459. case FTOPSELFILE:
  460.     if( w == NULL )
  461.         break;
  462.     /* remember where we came from */
  463.     w->rowLastline = w->numTopline;
  464.     w->posTopline = 0;
  465.     w->numTopline = 1;
  466.     w->indent = 0;
  467.  
  468.     /* move the selection to the top of the file */
  469.     eraseSelection();
  470.     selWindow = w;
  471.     selBegin = 0;
  472.     selEnd = 0;
  473.     if( readChar(w->fileId, 0L) == '\r' ) {
  474.         if( readChar(w->fileId, 1L) == '\n' )
  475.             selEnd = 1;
  476.     }
  477.     redrawWindow(w);
  478.     break;
  479.  
  480. case FRECORDMACRO:
  481.     switch( macroState ) {
  482.     case 0:
  483.         macroIndex = 0;
  484.         macroState = 1;
  485.         msg("Recording keystrokes in macro buffer", 4);
  486.         break;
  487.     case 1:
  488.         /* remove the FRECORDMACRO keystroke */
  489.         macroSize = macroIndex - 2;
  490.         macroState = 0;
  491.         msg("", 0);    /* erase the sticky message */
  492.         msg("End recording keystrokes", 1);
  493.         break;
  494.     case 2:
  495.         msg("No recursive macros", 1);
  496.         break;
  497.     }
  498.     break;
  499.  
  500. case FPLAYMACRO:
  501.     macroState = 2;
  502.     macroIndex = 0;
  503.     break;
  504.  
  505. case FJUSTIFY:
  506.     if( w == NULL )
  507.         break;
  508.     justifyLines();
  509.     break;
  510.  
  511. case FMENU1:  case FMENU2:  case FMENU3:  case FMENU4:
  512. case FMENU5:  case FMENU6:  case FMENU7:  case FMENU8:
  513. case FMENU9:  case FMENU10: case FMENU11: case FMENU12:
  514. case FMENU13: case FMENU14: case FMENU15: case FMENU16:
  515.     fn = menu(menus[CommandToMenuNumber(fn)], menuRow, menuCol);
  516.     goto startOver;
  517.  
  518. case FCHANGEMENU:
  519.     /* find the button and shift state and look up the command */
  520.  
  521.     /* get the present mouse button state into r1 */
  522.     if( mousePresent ) {
  523.         rin.x.ax = 3;
  524.         int86(51, &rin, &rout);
  525.         r1 = rout.x.bx;
  526.         /* record where to put the menu */
  527.         menuRow = rout.x.dx>>3;
  528.         menuCol = rout.x.cx>>3;
  529.     } else {
  530.         r1 = 0x0;
  531.         /* record where to put the menu */
  532.         getCPos(&menuRow, &menuCol);
  533.     }
  534.  
  535.     /* find the shift state of the keyboard */
  536.     rin.h.ah = 2;
  537.     int86(0x16, &rin, &rout);
  538.  
  539.     /* mask of the Ins, Caps, Num, and Scroll states */
  540.     r2 = rout.h.al & 0xF;
  541.  
  542.     /* fix r2 so that either shift keys implies shift */
  543.     /* shift over bit1 and OR bit0 with it */
  544.     r2 = (r2>>1) | (r2&0x1);
  545.  
  546.     /* adjust for cursor simulation of the mouse */
  547.     if( !mousePresent )
  548.         r2 = 0x0;
  549.  
  550.     /* get the command number from the table */
  551.     i =  (r2<<3) + r1;
  552.     fn= buttonVector[i];
  553.     goto startOver;
  554.  
  555. case FCONTEXTMENU:
  556.     doContextMenu();
  557.     break;
  558.  
  559. case FMATCHCHAR:    /* find the matching character */
  560.     matchChar();
  561.     break;
  562.  
  563. case FCOPYTO:    /* copy selection to this point */
  564.     n = COPY;
  565.     goto moveAndCopy;
  566.  
  567. case FMOVETO:    /* move selection to this point */
  568.     n = MOVE;
  569. moveAndCopy:
  570.     if( w == NULL )
  571.         break;
  572.     up2Buttons(&row1, &col1);
  573.     /* find out what window (if any) and where the mouse was */
  574.     xyToPos(&row1, &col1, &i, &cp, &w2);
  575.     /* if the user moves outside the window then abort the move or copy */
  576.     if( i != INSIDEWINDOW || w2 != w )
  577.         break;
  578.     /* adjust to the selection mode */
  579.     cp = adjustSelMode(w->fileId, cp);
  580.     copyMove(selWindow, selBegin, selEnd, w, cp, n);
  581.     break;
  582.  
  583. case FBACKSEARCH:
  584.     if( w == NULL )
  585.         break;
  586.     realSearchMode = searchMode;
  587.     if( n != 1 )
  588.         searchMode = 1;
  589.     else
  590.         searchMode = 0;
  591.     searchFor(1, w);
  592.     searchMode = realSearchMode;
  593.     realSearchMode = -1;
  594.     break;
  595.  
  596. case FHELP:
  597.     help(lastCommand);
  598.     break;
  599.  
  600. case FGOTOSELECTION:
  601.     if( w == NULL )
  602.         break;
  603.     doGoSel(w);
  604.     break;
  605.  
  606. case FEXCHSCRAP:
  607.     if( selWindow == NULL )
  608.         break;
  609.     exchWithScrap();
  610.     break;
  611.  
  612. case FCOPYSCRAP:
  613.     if( selWindow == NULL )
  614.         break;
  615.     copyToScrap(selWindow, selBegin, selEnd);
  616.     msg("The selection has been copied to the scrap buffer", 1);
  617.     break;
  618.  
  619. case FGOBACKTO:
  620.     if( w == NULL )
  621.         break;
  622.     doGoto(w, w->rowLastline);
  623.     break;
  624.  
  625. case FINSKEY:
  626.     if( selWindow == NULL )
  627.         break;
  628.     insScrap(1);
  629.     break;
  630.  
  631. case FWORDLEFT:
  632. case FWORDRIGHT:
  633.     cursor(fn, mousePresent);
  634.     /* only move the cursor if the mouse is present */
  635.     break;
  636.  
  637. case FLOADSEL:
  638.     if( w == NULL )
  639.         doNewWindow(FNEWWINDOW, 0);
  640.     else
  641.         loadWindow(w, fn);
  642.     break;
  643.  
  644. case FDELNOSCRAP:
  645.     if( selWindow == NULL )
  646.         break;
  647.     deleteChars(selWindow->fileId, UPDATEWINDOWS, 0);
  648.     break;
  649.  
  650. case FNEWSEL:
  651.     doNewWindow(fn, 0);
  652.     break;
  653.  
  654. case FSAVEFILE:
  655.     if( w == NULL )
  656.         break;
  657.     saveFile(w);
  658.     redoBorders(0);
  659.     /* use scrRows-2 to avoid erasing the "File saved ..." message */
  660.     updateScreen(0, scrRows-2);
  661.     break;
  662.  
  663. case FSELGOTO:
  664.     if( w == NULL )
  665.         break;
  666.     fileName = getSelection(&textBuffer[0]);
  667.     /* skip past any non-numeric characters at the front */
  668.     while( 1 ) {
  669.         ch = *fileName;
  670.         if( ch == '\0' || ('0'<=ch && ch<='9') )
  671.             break;
  672.         ++fileName;
  673.     }
  674.     n = atoi(fileName);
  675.     if( n != 0 )
  676.         doGoto(w, n);
  677.     else
  678.         msg("Invalid line number", 2);
  679.     break;
  680.  
  681. case FCLOSESAVE:
  682.     if( w == NULL )
  683.         break;
  684.     closeWindow(w, 0, 1);
  685.     break;
  686.  
  687. default:
  688.     msg("No action is defined for that key [Alt-h for HELP]", 1);
  689.     break;
  690. }
  691. lastFn = fn;
  692. if( fn != FDONOTHING && fn > 0 ) 
  693.     lastCommand = fn;
  694. return 0;
  695. }
  696.