home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / EDITOR / PT20PC.ZIP / PT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-04  |  17.8 KB  |  639 lines

  1. #include "pt.h"
  2. #include "direct.h"
  3. #include "malloc.h"
  4. #include "string.h"
  5. #include "conio.h"
  6. #include "io.h"
  7. #include "process.h"
  8. #include "stdlib.h"
  9. #include "time.h"
  10.  
  11. extern void criterr(void);
  12. extern void overlay(int);
  13.  
  14. void
  15. /* XTAG:main */
  16. main(argc, argv)
  17.     unsigned char *argv[];
  18. {
  19.  
  20. /**************************************************************************/
  21. /*   Declare the external variables                                       */
  22. /**************************************************************************/
  23.  
  24.     extern struct window *windows, *windowList;
  25.     extern unsigned char msgBuffer[];
  26.     extern unsigned char startDirectory[];
  27.     extern unsigned char currentDirectory[];
  28.     extern unsigned char startDrive;
  29.     extern unsigned char currentDrive;
  30.     extern unsigned char scrMapReset;
  31.     extern unsigned int dispMemory;
  32.     extern int debug;
  33.     extern union REGS rin, rout;
  34.     extern struct window *selWindow;
  35.     extern long selBegin, selEnd;
  36.     extern int selMode;
  37.     extern int undoSize;
  38.     extern int nextChange;
  39.     extern int addHandle;
  40.     extern unsigned char addFile[];
  41.     extern long addPosition;
  42.     extern int brIntCom[];
  43.     extern int initialWindows;
  44.     extern struct changeItem scrapBuffer;
  45.     extern struct SREGS segRegs;
  46.     extern unsigned char saveVideoMode;
  47.     extern int scrRows, scrCols;
  48.     extern unsigned char filePattern[];
  49.     extern unsigned char tagPattern[];
  50.     extern unsigned char tagMarker[];
  51.     extern struct window *activeWindow;
  52.     extern int menuLine;
  53.     extern int descrFileId;
  54.     extern jmp_buf breakEnv;
  55. #ifdef OVERLAYS
  56.     extern int overlayVector;
  57. #endif
  58.     extern int readOnly;
  59.     extern int supressFileMsgs;
  60.     extern struct menuBlock far *menus[];
  61.     extern unsigned char *copyRightMsg;
  62.     extern unsigned char *userMessages[];
  63.     extern unsigned char far * fileHandleTable;
  64.     extern int maxFiles;
  65.     extern struct openFile *files;
  66.     extern time_t timeOfLastSave;
  67.     extern unsigned char far *menuSpace;
  68.  
  69. /**************************************************************************/
  70. /*   Declare the local variables                                          */
  71. /**************************************************************************/
  72.  
  73.     int i, j, k, row, col, where;
  74.     int deltaRow, deltaCol, nWindows, topMode;
  75.     unsigned char *p;
  76.     unsigned int far * fp;
  77.     unsigned char far * oldTable;
  78.     struct window *w;
  79.     int lastState = 0;    /* restore the last state of the editor */
  80.     int hideFiles;
  81.  
  82. /**************************************************************************/
  83. /*   Save the old video mode and set a compatible video mode to use       */
  84. /**************************************************************************/
  85.  
  86. /* determine the current display mode */
  87. rin.h.ah = 15;
  88. int86(0x10, &rin, &rout);
  89. saveVideoMode = rout.h.al;
  90.  
  91. switch( saveVideoMode ) {
  92. case 7:    /* monochrome display */
  93.     dispMemory = 0xB000;
  94.     break;
  95. case 4:    /* 320x200 color */
  96.     rin.h.al = 3;    /* 80x25 color */
  97.     goto setMode;
  98. case 5:    /* 320x200 b&w */
  99. case 6:    /* 640x200 b&w */
  100.     rin.h.al = 2;    /* 80x25 b&w */
  101. setMode:
  102.     rin.h.ah = 0;    /* set video mode */
  103.     int86(0x10, &rin, &rout);
  104. default:
  105.     dispMemory = 0xB800;
  106.     break;
  107. }
  108.  
  109. /* get the segment registers */
  110. segread(&segRegs);
  111.  
  112. /**************************************************************************/
  113. /*   Get the current directory and drive so we can restore then on exit   */
  114. /**************************************************************************/
  115. (void)getcwd(&startDirectory[0], FILENAMESIZE);
  116. strcpy(currentDirectory, startDirectory);
  117. startDrive = getDefaultDrive();
  118. currentDrive = startDrive;
  119.  
  120. /**************************************************************************/
  121. /*   Read in the initialization file but first                            */
  122. /*    set the variables it might change from their default values         */
  123. /**************************************************************************/
  124.  
  125. /* set up the menu blocks */
  126.  
  127. /* This one is for dynamic menus (OPTIONS and TOPLIST and HELP) */
  128. menus[0] = (struct menuBlock far *)_fmalloc(sizeof(struct menuBlock));
  129.  
  130. /* initialize the other menus to not yet allocated */
  131. for(i = 1; i < NMENUS; ++i)
  132.     menus[i] = (struct menuBlock far *)NULL;
  133.  
  134. /* set up space for the menu characters */
  135. menuSpace = (unsigned char far *)_fmalloc(MENUSPACE);
  136.  
  137. /* set up variables */
  138. addFile[0] = '\0';
  139. strcpy(filePattern, "*.*");
  140. strcpy(tagPattern, "*.c|*.h|*.asm");
  141. strcpy(tagMarker, "XTAG:");
  142.  
  143. /* set up the default asciiMap so that setup can alter it */
  144. initKeymaps();
  145.  
  146. /* read the setup file */
  147. if( setup() ) {
  148.     cprintf(
  149.     "Cannot find \"pt.ini\" in this directory or the PATH.\r\nExiting.\r\n");
  150.     exit(1);
  151. }
  152.  
  153. /**************************************************************************/
  154. /*   Allocate a new file handle table to allow more than 20 open files    */
  155. /*   then allocate the open file table and the window structures          */
  156. /**************************************************************************/
  157. if( _osmajor == 3 ) {    /* only works for DOS 3.x */
  158.     if( 0 <= _osminor && _osminor <= 20 ) {
  159.         /* version 3.00, 3.10, and 3.20 only */
  160.         /* allocate space for the file handles */
  161.         fileHandleTable = (unsigned char far *)_fmalloc(maxFiles);
  162.         /* find the current file handle table in the PSP */
  163.         FP_OFF(fp) = 0x32;    /* at 0x32 in PSP */
  164.         FP_SEG(fp) = _psp;
  165.         row = *fp;    /* get the size of the current table */
  166.         FP_OFF(oldTable) = *(fp+1);    /* addr of current table */
  167.         FP_SEG(oldTable) = *(fp+2);
  168.         /* copy current table to new table */
  169.         for(i = 0; i < row; ++i )
  170.             fileHandleTable[i] = oldTable[i];
  171.         /* mark the rest of the handles in the new table */
  172.         /* as unopened (0xFF) */
  173.         for(i = row; i < maxFiles; ++i)
  174.             fileHandleTable[i] = 0xFF;
  175.         /* install the new table by changing the PSP fields */
  176.         *fp = (unsigned int)maxFiles;
  177.         *(fp+1) = FP_OFF(fileHandleTable);
  178.         *(fp+2) = FP_SEG(fileHandleTable);
  179.     } else if( _osminor >= 30 ) {
  180.         /* we can do the same thing wiht a simple DOS call! */
  181.         rin.h.ah = 0x67;    /* set handle count */
  182.         /* Steve Gibson's TSR example added the +1 so I am too */
  183.         /* just to be sure that I get enough handles */
  184.         rin.x.bx = maxFiles + 1;
  185.         intdos(&rin, &rout);
  186.     } else
  187.         maxFiles = 20;
  188. } else
  189.     maxFiles = 20;
  190.  
  191. /* allocate an extra file structure for use in copymove.c (insScrap) */
  192. files = (struct openFile *)malloc((maxFiles+1) * sizeof(struct openFile));
  193. windows = (struct window *)malloc(maxFiles * sizeof(struct window));
  194. if( files == NULL || windows == NULL) {
  195.     cprintf("Too many files (out of memory). Reduce maxFiles\r\n");
  196.     exit(1);
  197. }
  198.  
  199. /**************************************************************************/
  200. /*   call various initialization routines                                 */
  201. /**************************************************************************/
  202.  
  203. initWindows();
  204. initFileio();
  205. initChanges();
  206.  
  207. /**************************************************************************/
  208. /*   Process the command line options and arguments                       */
  209. /**************************************************************************/
  210.  
  211. for(i = 1; i < argc; i++) {
  212.     if( argv[i][0] == '/' || argv[i][0] == '-' ) {
  213.         for(j = 1; argv[i][j] != '\0'; j++) {
  214.             switch( argv[i][j] ) {
  215.  
  216.             case 'l':  /* restore last state */
  217.                 lastState = 1;
  218.                 break;
  219.  
  220.             case 'o':  /* overlaid windows */
  221.                 initialWindows = 0;
  222.                 break;
  223.  
  224.             case 'h':  /* horizontal split */
  225.                 initialWindows = 1;
  226.                 break;
  227.  
  228.             case 'v':  /* vertical split */
  229.                 initialWindows = 2;
  230.                 break;
  231.  
  232.             case 'r':  /* read only mode */
  233.                 readOnly = 1;
  234.                 break;
  235.  
  236.             case 'd':  /* debug flag initial value */
  237.                 debug = argv[i][++j] - '0';
  238.                 break;
  239.  
  240.             default:
  241.                 cprintf("usage: pt [/hlov] [file1] [file2] ...\r\n");
  242.                 break;
  243.             }
  244.         }
  245.     } else    /* we have reached the end of the comamnd line options */
  246.         break;
  247. }
  248.  
  249. initMouse(5, 10, 1);
  250.  
  251. /* clear the screen */
  252. scrollUp(0, 0, 0, scrRows-1, scrCols-1, 0x7);
  253.  
  254. /**************************************************************************/
  255. /*   create the menu line                                                 */
  256. /**************************************************************************/
  257.  
  258. row = (menuLine < 0 ? (scrRows-1) : 0);
  259. redrawBox(row, 0, row, scrCols-1);
  260. updateScreen(row, row);
  261.  
  262. /**************************************************************************/
  263. /*   See if "pt.msg" (the command descriptions file) is present.          */
  264. /**************************************************************************/
  265.  
  266. p = findFile("pt.msg");
  267. if( p == NULL )
  268.     descrFileId = -1;
  269. else
  270.     descrFileId = getFileId(p);
  271.  
  272. /**************************************************************************/
  273. /*   create the additions file                                            */
  274. /**************************************************************************/
  275.  
  276. strcat(addFile, "pttemp.add");
  277. makeName(addFile);
  278. addPosition = 0;
  279. addHandle = creatls(addFile, 0);
  280. if( addHandle < 0 ) {
  281.     cprintf(addHandle==-4 ? userMessages[HANDLEMSG] :
  282.         "Create of 'pttemp.add' failed", 0);
  283.     exit(1);
  284. }
  285.  
  286. /**************************************************************************/
  287. /*   create the initial windows                                           */
  288. /**************************************************************************/
  289.  
  290. nWindows = argc - i;    /* number of initial windows */
  291. if( nWindows == 0 )
  292.     nWindows = 1;    /* avoid zero-divide */
  293. topMode = CRBOTTOM;
  294. where = (menuLine > 0 ? 1 : 0);
  295. switch( initialWindows ) {
  296.     default:
  297.     case 0:    /* overlaid windows */
  298.         deltaCol = 0;
  299.         deltaRow = 0;
  300.         row = where;
  301.         col = 0;
  302.         break;
  303.     case 1:    /* horizontal split  */
  304.         deltaCol = 0;
  305.         deltaRow = (scrRows-1)/nWindows;
  306.         row = where;
  307.         col = 0;
  308.         topMode = CRTOP;
  309.         break;
  310.     case 2:    /* vertical split  */
  311.         deltaCol = (scrCols-3)/nWindows;
  312.         deltaRow = 0;
  313.         row = where;
  314.         col = 0;
  315.         topMode = CRTOP;
  316.         break;
  317. }
  318.  
  319. selWindow = NULL;
  320. where = scrRows - 1;
  321. if( menuLine < 0 )    /* bottom line menu? */
  322.     --where;    /* make room for it */
  323. supressFileMsgs = 1;
  324. hideFiles = 0;
  325.  
  326. for(k = i; k < argc; k++) {
  327.     if( strcmp( argv[k], "/H" ) == 0 ) {
  328.         hideFiles = !hideFiles;
  329.         continue;
  330.     }
  331.     sprintf(msgBuffer, "Opening file %s", argv[k]);
  332.     msg(msgBuffer, 1);
  333.     if( access(argv[k], 0) == -1) {
  334.         sprintf(msgBuffer, "y to create «%s»: ", argv[k]);
  335.         p = getInput(msgBuffer, "y", 1);
  336.         if( p == NULL || tolower(*p) != 'y' ) {
  337.             msg("Window not created", 1);
  338.             continue;
  339.         }
  340.         closels(creatls(argv[k], 0));
  341.     }
  342.     w = createWindow(argv[k], row, col, where, scrCols-1, topMode, 0);
  343.     if( hideFiles )
  344.         hideWindow(w);
  345.     row += deltaRow;
  346.     col += deltaCol;
  347. }
  348. supressFileMsgs = 0;
  349.  
  350. /**************************************************************************/
  351. /*   set up the software interrupt and other things                       */
  352. /**************************************************************************/
  353.  
  354. #ifdef OVERLAYS
  355. movedata(0, overlayVector * 4, segRegs.ds, (unsigned int)&saveOldVector, 4);
  356. overlay(overlayVector);
  357. #endif
  358.  
  359. /* set up the critical error handler */
  360. criterr();
  361.  
  362. /* if lastState then read the restore file that records the last state */
  363. /* the editor was in and restore that state */
  364. if( lastState ) {
  365.     restoreLastState();
  366. }
  367.  
  368. /* the top window is the first active window */
  369. activeWindow = windowList;
  370. if( windowList != NULL ) {
  371.     redoBorders(0);
  372.     updateScreen(0, scrRows-1);
  373. }
  374.  
  375. /**************************************************************************/
  376. /*   banner message                                                       */
  377. /**************************************************************************/
  378.  
  379. msg(copyRightMsg, 1);
  380.  
  381. /**************************************************************************/
  382. /*   set up control break processing                                      */
  383. /**************************************************************************/
  384.  
  385. /* return here if a control-break is pressed */
  386. if( setjmp(breakEnv) != 0 ) {
  387.     /***initMouse(5, 10, 1);***/
  388.     redrawBox(0, 0, scrRows-1, scrCols-1);
  389.     updateScreen(0, scrRows-1);
  390.     msg("Ctrl-Break!", 2);
  391. }
  392.  
  393. /* set up the control break interrupt handler */
  394. signal(SIGINT, ctrlBreak);
  395.  
  396. /* initialize the timeOfLastSave variable */
  397. timeOfLastSave = time(NULL);
  398.  
  399. /**************************************************************************/
  400. /*   start the main processing loop                                       */
  401. /**************************************************************************/
  402.  
  403. /* starting reading user editing commands */
  404. /* look for keystrokes and mouse buttons */
  405.  
  406. mainLoop();
  407.  
  408. /* reset the video mode */
  409. rin.h.ah = 0;    /* set video mode */
  410. rin.h.al = saveVideoMode;
  411. int86(0x10, &rin, &rout);
  412.  
  413. /* reset the cursor */
  414. if( dispMemory == 0xB000 )
  415.     setCType(12, 13);
  416. else
  417.     setCType(6, 7);
  418. col = getDOScolor();
  419.  
  420. /* clear the screen */
  421. scrollUp(0, 0, 0, scrRows-1, scrCols-1, col);
  422. setCPos(0, 0);
  423.  
  424. /* restore the original current directory and delete the add file */
  425. setDefaultDrive(startDrive);
  426. chdir(startDirectory);
  427. closels(addHandle);
  428. delete(addFile);
  429.  
  430. #ifdef OVERLAYS
  431. /* restore the interrupt vector */
  432. movedata(segRegs.ds, (unsigned int)&saveOldVector, 0, overlayVector * 4, 4);
  433. #endif
  434.  
  435. exit(0);    /* exit cleanly */
  436. } /* end of main */
  437.  
  438. /* this loop is the main processing loop of Point */
  439. void pascal
  440. /* XTAG:mainLoop */
  441. mainLoop()
  442. {
  443.     extern unsigned char msgBuffer[];
  444.     extern struct window *activeWindow;
  445.     extern time_t timeOfLastSave;
  446.     extern int autoSaveInterval;
  447.  
  448.     unsigned char ch, scan;
  449.     int where;
  450.  
  451.     while(1) {
  452.  
  453.         /* save if the time period has elapsed */
  454.         if( autoSaveInterval > 0
  455.          && (int)((time(NULL)-timeOfLastSave)/60)>=autoSaveInterval)
  456.             command(FSAVEALL, '\0', activeWindow);
  457.  
  458.         /* get any typed characters */
  459.         if( isKeystroke() != 0 ) {
  460.             ch = getKeystroke(&scan);
  461.             if( interp(ch, scan) != 0 ) {
  462.                 break;
  463.             }
  464.         }
  465.     
  466.         /* get mouse position and button press status */
  467.         if( isMouseEvent(0) ) {
  468.             where = getMouseEvent();
  469.             if( mouseButton(where) != 0 )
  470.                 break;
  471.         }
  472.     }
  473. }
  474.  
  475. int pascal
  476. /* XTAG:getDOScolor */
  477. getDOScolor()
  478. {
  479.     extern union REGS rin, rout;
  480.  
  481.     setCPos(0, 0);
  482.     cprintf(" ");
  483.     setCPos(0, 0);
  484.     rin.h.ah = 8;    /* read char/attribute */
  485.     rin.h.bh = 0;    /* page number */
  486.     int86(0x10, &rin, &rout);
  487.     return (int)rout.h.ah;
  488. }
  489.  
  490. int pascal
  491. /* XTAG:translateKey */
  492. translateKey(ch, scanCode)
  493.     unsigned char ch, scanCode;
  494. {
  495.     extern int keyMap[];
  496.     extern int asciiMap[];
  497.     
  498.     register int fn;
  499.  
  500.     /* if extended code, find the function it maps to */
  501.     if( ch == 0 )
  502.         fn = keyMap[scanCode];
  503.     else {    /* return the ASCII mapped character */
  504.         if( ch < 128 )
  505.             fn = asciiMap[ch];
  506.         else
  507.             fn = FCHARACTER;
  508.         if( ch == '+' && scanCode == 78 )
  509.             fn = FLEFTMBUTTON;
  510.         else if( ch == '-' && scanCode == 74 )
  511.             fn = FRIGHTMBUTTON;
  512.     }
  513.     return fn;
  514. }
  515.  
  516. int pascal
  517. /* XTAG:interp */
  518. interp(c, c2)
  519.     unsigned char c, c2;
  520. {
  521.     extern union REGS rin, rout;
  522.     extern int menuRow, menuCol;
  523.     extern struct window *activeWindow;
  524.     extern unsigned char msgBuffer[];
  525.  
  526.     int fn;
  527.  
  528.     /* handle things that we need to do every command */
  529.     handleTempItems();
  530.  
  531.     fn = translateKey(c, c2);
  532.     /* if extended code, find the function it maps to */
  533.     if( c == 0 )
  534.         c = c2;
  535.     menuRow = 7;
  536.     menuCol = 30;
  537.     return command(fn, c, activeWindow);
  538. }
  539.  
  540. void pascal
  541. /* XTAG:msg */
  542. msg(s, type)
  543.     unsigned char *s;
  544.     int type;
  545.     /* type = 0 --> erase even a sticky message */
  546.     /* type = 1 --> type message, but if "" redo the sticky message */
  547.     /* type = 2 --> a prompt message */
  548.     /* type = 3 --> an error message */
  549.     /* type = 4 --> a sticky message */
  550.     /* type = 5 --> message on alternative message line */
  551. {
  552.     extern int debug;
  553.     extern unsigned char border2[];
  554.     extern unsigned char borderColor;
  555.     extern unsigned char msgColor, promptColor, errorColor;
  556.     extern struct window *windowList;
  557.     extern int menuLine;
  558.     extern int lastOnTopline;
  559.     extern int isMessage;
  560.     extern int scrRows, scrCols;
  561.  
  562.     register int color;
  563.     int i, row, col;
  564.     static unsigned char stickyMessage[80] = {0};
  565.  
  566.     /* try to keep from erasing messages because of trying to erase */
  567.     /* the top line (and popup menu) command descriptions */
  568.     lastOnTopline = 0;
  569.     row = scrRows - 1;
  570.     if( menuLine < 0 )
  571.         --row;
  572.     if( type == 5 )
  573.         --row;
  574.     color = msgColor;    /* the most common case */
  575.     switch( type ) {
  576.         default:
  577.         case 0:    /* erase all messages */
  578.             stickyMessage[0] = '\0';
  579.         case 1:    /* type message -- or reinstate a sticky message */
  580.             if( s[0] == '\0' ) {    /* erase all but sticky */
  581.                 s = &stickyMessage[0];
  582.                 type = 4;  /* revert to sticky msg type */
  583.             }
  584.             break;
  585.         case 2:    /* prompt message */
  586.             color = promptColor;
  587.             break;
  588.         case 3:    /* error message */
  589.             color = errorColor;
  590.             break;
  591.         case 4:    /* sticky messages */
  592.             strncpy(stickyMessage, s, 79);
  593.             break;
  594.         case 5: /* alternative message line */
  595.             color = promptColor;
  596.             break;
  597.     }
  598.  
  599.     /* first set up the bottom line of the screen correctly */
  600.     redoBorders(1);
  601.     i = strlen(s);
  602.     if( type == 0 || i == 0 ) {
  603.         updateScreen(row, row);
  604.         return;
  605.     }
  606.  
  607.     /* only set the screenMap for the length of the message */
  608.     /* unless there are not windows and the previous message */
  609.     /* will not have been erased */
  610.     col = (windowList==NULL ? 78 : i);
  611.     setMap(row, 1, row, i, 0, msgColor);
  612.  
  613.     /* remember that a message is there */
  614.     /* message type==0 clears the message line */
  615.     isMessage = type;
  616.     col = 1;
  617.     for(i = 0; s[i] != '\0' && col < (scrCols-1); i++)
  618.         displayChar(row, col++, s[i], color);
  619.     updateScreen(row, row);
  620.  
  621.     /* Pause for errors so the user is sure to see the message. */
  622.     /* No need for instructions since anyone will try hitting */
  623.     /* a key or two if things seem stuck.  Regular user's are not */
  624.     /* supposed to see these messages anyway (only me) */
  625.     if( type == 3 ) {
  626.         incon();
  627.         msg("", 1);    /* clear the error message */
  628.     }
  629. }
  630.  
  631. void
  632. /* XTAG:ctrlBreak */
  633. ctrlBreak()
  634. {
  635.     extern jmp_buf breakEnv;
  636.  
  637.     longjmp(breakEnv, 1);
  638. }
  639.