home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 133_01 / e < prev    next >
Text File  |  1985-03-10  |  11KB  |  503 lines

  1. /*
  2. CUG-HEADER:
  3.    TITLE: "e screen editor"
  4.    VER: 4.8
  5.    AUTHOR: G.N. GILBERT
  6.    O.S.: CP/M 2.2  CP/M 3.0
  7.    DESC: a complete screen editor for programmers, with lots
  8.          of useful features, an easy to use interface,
  9.          virtual memory management, 'undo' facility etc.
  10.    KEYWORDS: editor, programming environment, tool
  11.    DATE: 1/30/1985
  12. */
  13.  
  14. /*
  15.     e screen editor
  16.  
  17.     (C) G. Nigel Gilbert, MICROLOGY, 1981
  18.     licensed for private non-profitmaking use 1983
  19.  
  20.     August-December 1981
  21.  
  22.     FILE: e
  23.  
  24.     FUNCTIONS: main, initialise, edit, finish, seldisk, askforfile,
  25.            xit, startstop
  26.  
  27.     PURPOSE: initialise; process commands, finish
  28.  
  29. */
  30.  
  31. #include "e.h"
  32.  
  33. main(argc,argv)
  34. int argc;
  35. char **argv;
  36. {
  37.     int argn, i, startline;
  38.     char *dig, cpmversion;
  39.  
  40. /**************************Default option settings***************************/
  41.  
  42.     autoin=YES;    /*auto indent  [YES/NO]*/
  43.     backup=NO;    /*make ".BAK" file [YES/NO]*/
  44.     trail=NO;    /*don't strip trailing blanks [YES/NO]*/
  45.     helpon=NO;    /*start with help menu on [YES/NO]*/
  46.     tabwidth=8;    /*tab stops every n cols [number]*/
  47.     displaypos=YES;    /*display line:column at top of screen*/
  48.     blockscroll=NO;    /*don't scroll whole page, just current line*/
  49.     pagingdisk=0;    /*create buffer file on this disk -
  50.                 set to either 0 (for currently logged-in disk)
  51.                 or to desired disk letter  (eg 'B') */
  52.     wboot=NO;    /*do a warm boot at end of edit [YES/NO]
  53.                 (ignored for non CP/M 2.x systems)
  54.                 SET THIS OPTION TO YES if you do not have an
  55.                 entirely standard CP/M 2.x system */
  56.     hilight=YES;    /*highlight current line*/
  57.  
  58. /***********************End of default option settings***********************/
  59.  
  60.     switch(bdos(VERNO,0) & 0xf0) {
  61.         case 0x20 :    /* CP/M 2.x */
  62.             cpm2x=YES;
  63.             break;
  64.         case 0x31 :    /* CP/M 3.1 [CP/M Plus] */
  65.             bdos(CPM3ERRORMODE, 0xfe);   /*set error mode to
  66.                             return and display
  67.                             error */
  68.             cpm2x=NO;            /*disable fast
  69.                             re-boot option*/
  70.             break;
  71.         default:    /*weird CP/M*/
  72.             cpm2x=NO;
  73.             break;
  74.         }
  75.  
  76.     /*initialisations only done once at start of all editing: */
  77.  
  78.     inbufp=0;
  79.     startline=1;
  80.     filename[0]=name[0]=ans[0]=patt[0]=changeto[0]=opts[0]='\0';
  81.  
  82.  
  83.     argn=0;
  84.     while (++argn < argc)
  85.         if (*argv[argn] == '-') {
  86.             dig=argv[argn]+1;
  87.             switch(*dig) {
  88.             case 'A' :
  89.                 autoin=!autoin;
  90.                 break;
  91.             case 'B' :
  92.                 backup=!backup;
  93.                 break;
  94.             case 'L' :
  95.                 displaypos=!displaypos;
  96.                 break;
  97.             case 'H' :
  98.                 blockscroll=!blockscroll;
  99.                 break;
  100.             case 'I' :
  101.                 hilight=!hilight;
  102.                 break;
  103.             case 'T' :
  104.                 tabwidth=0;
  105.                 while (*++dig) tabwidth=tabwidth*10+*dig-'0';
  106.                 break;
  107.             case 'S' :
  108.                 trail=!trail;
  109.                 break;
  110.             case 'V' :
  111.                 helpon=!helpon;
  112.                 break;
  113.             case 'X' :
  114.                 wboot=!wboot;
  115.                 break;
  116.             case 'D' :
  117.                 pagingdisk=*(dig+1);
  118.                 if (pagingdisk >= 'A' && pagingdisk <= 'P') break;
  119.             default  :
  120.                 if (isdigit(*dig)) {
  121.                     for (startline=0; *dig; dig++)
  122.                         startline=startline*10 + *dig - '0';
  123.                     break;
  124.                     }
  125.                 puts("Illegal option: ");
  126.                 puts(argv[argn]);
  127.                 exit();
  128.                 }
  129.             }
  130.         else strcpy(filename[0] ? name : filename,argv[argn]);
  131.  
  132.     terminit();
  133.     keytranslate();
  134.  
  135.     startstop(YES);
  136.  
  137.     do {
  138.         initialise(startline);
  139.         edit();
  140.         startline=1;
  141.         }
  142.     while (YES);
  143. }
  144.  
  145. initialise(startline)
  146. int startline;
  147. {
  148.     /*initialisations that are done before editing each new file: */
  149.  
  150.     cursorx=charn=offset=lastoff=from=to=histptr=histcnt=ncommand=0;
  151.     cursory=topline=lastread=lastl=findir=1;
  152.     isdim=replace=repeat=blocking=blankedmess=storehist=NO;
  153.     pfirst=-100;
  154.     goteof=YES;
  155.     errmess=NULL;
  156.  
  157.     curdsk=bdos(CURDSK);
  158.  
  159.     initvm();
  160.  
  161.     text[0]='\0';
  162.     cline=1;
  163.     altered=YES;
  164.     puttext();
  165.  
  166.     if (filename[0]) {
  167.         putclr();
  168.         gotoxy(8,11);
  169.         puts("e  screen editor  version ");
  170.         puts(VERSION);
  171.         puts("  MICROLOGY 1983");
  172.         gotoxy(20,12);
  173.         terminal();
  174.         while (opentext(filename) == FAIL) {
  175.             askforfile();
  176.             if (!filename[0]) goto newfile;
  177.             }
  178.         lastl=UNKNOWN;
  179.         lastread=0;
  180.         goteof=NO;
  181.         if (name[0]) {
  182.             strcpy(filename,name);
  183.             name[0]='\0';
  184.             }
  185.         format(filename);
  186.         }
  187. newfile: errmess=NULL;
  188.     gettext(startline);
  189.     cline=loc(startline,0);
  190.     putclr();
  191.     if (helpon) dohelp();
  192.     putpage();
  193. }
  194.  
  195. edit()        /*command processor*/
  196. {
  197.     char c;
  198.     int to;
  199.  
  200.     setjmp(mainmenu);
  201.  
  202.     while (YES) {
  203.         goodline=cline;
  204.         unmess();
  205.         putlineno(cline);
  206.         resetcursor();
  207.         c=getkey();
  208.         if (errmess != NULL) {
  209.             errmess=NULL;
  210.             putstatusline(cline);
  211.             }
  212.         ncommand++;
  213.         storehist=YES;
  214.         switch(c) {
  215.         case DOWNKEY    :
  216.             moveline(1);
  217.             break;
  218.         case UPKEY    :
  219.             moveline(-1);
  220.             break;
  221.         case LEFTKEY    :
  222.             movechar(-1);
  223.             break;
  224.         case RIGHTKEY    :
  225.             movechar(1);
  226.             break;
  227.         case LEFTWKEY    :
  228.             moveword(-1);
  229.             break;
  230.         case RIGHTWKEY    :
  231.             moveword(1);
  232.             break;
  233.         case BOLKEY    :
  234.             sync(0);
  235.             break;
  236.         case EOLKEY    :
  237.             sync(strlen(text));
  238.             break;
  239.         case UPPAGE    :
  240.             movepage(-1);
  241.             break;
  242.         case DOWNPAGE    :
  243.             movepage(0);
  244.             break;
  245.         case HOMEKEY    :
  246.             if (jumpline(lastl-cline)) sync(strlen(text));
  247.             break;
  248.         case BOFKEY    :
  249.             if (jumpline(1-cline)) sync(0);
  250.             break;
  251.         case DELLEFT    :
  252.             deletechar(-1);
  253.             break;
  254.         case DELRIGHT    :
  255.             deletechar(0);
  256.             break;
  257.         case DELLNKEY    :
  258.             text[0]='\0';
  259.             crdelete((cline == lastl ? -1 : 0));
  260.             break;
  261.         case DELWDKEY    :
  262.             deleteword();
  263.             break;
  264.         case JUMPKEY    :
  265.             putmess("Jump to? ");
  266.             scans(ans,6);
  267.             if ((to=atoi(ans))) jumpline(to-cline);
  268.             break;
  269.         case FINDKEY    :
  270.             replace=NO;
  271.             findorrep();
  272.             break;
  273.         case ALTERKEY    :
  274.             replace=YES;
  275.             findorrep();
  276.             break;
  277.         case REPKEY    :
  278.             repeat=YES;
  279.             dofindrep(1);
  280.             repeat=NO;
  281.             break;
  282.         case BLOCKKEY    :
  283.             blockops();
  284.             break;
  285.         case RDFILEKEY    :
  286.             putmess("File to read? ");
  287.             scans(name,FILELEN);
  288.             if (strlen(name) > 0) {
  289.                 readfile(name);
  290.                 putpage();
  291.                 }
  292.             break;
  293.         case HELPKEY    :
  294.             if (helpon) {
  295.                 helpon=NO;
  296.                 unmess();
  297.                 }
  298.             else {
  299.                 helpon=YES;
  300.                 dohelp();
  301.                 }
  302.             break;
  303.         case CR        :
  304.             crinsert(0);
  305.             break;
  306.         case CRSTILL    :
  307.             crinsert(-1);
  308.             break;
  309.         case ENVIRKEY   :
  310.             envir();
  311.             break;
  312.         case QUITKEY    :
  313.             if (finish()) return;
  314.             break;
  315.         case UNDOKEY    :
  316.             undo();
  317.             break;
  318.         case TAB:
  319.             insertchar('\t');
  320.             break;
  321.         case ESCKEY    :
  322.             resetcursor();
  323.             c=inchar();
  324.         default        :
  325.             insertchar(c);
  326.             break;
  327.             }
  328.         }
  329. }
  330.  
  331. finish()    /*return YES to edit another file; NO to return to current file
  332.           or don't return, but exit if finished altogther */
  333. {
  334.     int abandon;
  335.     char c, tempname[FILELEN], namebak[FILELEN], *strcpy(), getlow();
  336.  
  337.     putmess("W|rite edited text to file, |A|bandon all edits, or |R|eturn? ");
  338.     while ( (c=getlow()) != 'w' && c != 'a' && c != 'r');
  339.     putch(c);
  340.     if (c == 'r') return NO;
  341.     abandon= c == 'a';
  342.     if (c == 'w') {
  343.         if (!filename[0]) {
  344.             putmess("File to write to? ");
  345.             scans(filename,FILELEN);
  346.             format(filename);
  347.             if (filename[0] <= ' ' || (!backup && !exists(filename)))
  348.             {
  349.                 filename[0]='\0';
  350.                 return NO;
  351.                 }
  352.             }
  353.         if (backup) {    /*delete old bak file*/
  354.             retag(strcpy(namebak,filename),"BAK");
  355.             if (checkexists(namebak) && funlink(namebak) == FAIL) {
  356.                 error("Can't delete backup file");
  357.                 return NO;
  358.                 }
  359.             }
  360.         strcpy(tempname,filename); /*keep old name in 'filename'*/
  361.         retag(tempname,"$$$"); /*new file called'.$$$'*/
  362.         if (writefile(1,lastl,tempname,filename,YES) == FAIL) return NO;
  363.         /*check original file still exists - may have been deleted or
  364.            renamed by user */
  365.         if (checkexists(filename)) {
  366.             if (backup) {
  367.                 /*orig. file becomes '.bak' */
  368.                 if (frename(filename,namebak) == FAIL) {
  369.                     error("Can't rename old file to .BAK");
  370.                     goto failed;
  371.                     }
  372.                 }
  373.             else {
  374.                 /*delete orig file*/
  375.                 if (funlink(filename) == FAIL) {
  376.                     error("Can't delete old file");
  377.     failed:             /*if can't delete/rename old file, change
  378.                         new name to '.$$$'*/
  379.                     strcpy(filename,tempname);
  380.                     goto nowrite;
  381.                     }
  382.                 }
  383.             }
  384.         frename(tempname,filename); /*new file goes from '$$$' to orig name*/
  385.         }
  386. nowrite:
  387.     putmess("E|xit to CP/M, |R|eturn to this file, or edit |A|nother file? ");
  388.     while ( (c=getlow()) != 'e' && c!='a' && c!='r');
  389.     putch(c);
  390.     switch(c) {
  391.     case 'e' :
  392.         if (pagefd != NOFILE) {
  393.             close(pagefd);
  394.             funlink(pagingfile);
  395.             }
  396.         xit();
  397.     case 'a' :
  398.         fclose(textbuf);
  399.         if (pagefd != NOFILE) {
  400.             close(pagefd);
  401.             funlink(pagingfile);
  402.             }
  403.         askforfile();
  404.         return YES;
  405.  
  406.     case 'r' :
  407.         if (!abandon) {
  408.             gotoxy(WAITPOS,0);
  409.             opentext(filename);
  410.             lastl=UNKNOWN;
  411.             lastread=0;
  412.             goteof=NO;
  413.             initvm();
  414.             gettext(cline);
  415.             errmess=NULL;
  416.             putstatusline(cline);
  417.             }
  418.         return NO;
  419.         }
  420. }
  421.  
  422. xit()        /*leave the editor, either by returning to CCP or by
  423.         warm booting, according to X option*/
  424. {
  425.     unsigned *cpm;
  426.  
  427.     deleteline(0,23);
  428.     gotoxy(0,22);
  429.  
  430.     termfini();    /*close down terminal*/
  431.     startstop(NO);
  432.  
  433.     if (!cpm2x || wboot) exit();
  434.     else {
  435.         cpm=6;
  436.         /*call the standard return address within CCP - this is
  437.         just after where CCP calls a user program to start it off -
  438.         to avaoid having to do a warm boot */
  439.         call(*cpm-6-CCP+0x75f);
  440.         }
  441. }
  442.  
  443. askforfile()    /*get another file to edit into 'filename' */
  444. {
  445.     int drive, n;
  446.  
  447.     while(YES) {
  448.         printdirectory(curdsk);
  449.         puts("Name of file to edit     |or [return] to create a new file,\n");
  450.         puts(" |A:-P: to change drive,     0/-15/ to change user area,\n");
  451.         puts(" |[escape] to exit)|          ? ");
  452.         if (scans(filename,FILELEN) == ESCKEY) xit();
  453.         for (n=0; isdigit(filename[n]); n++);
  454.         if (filename[n] == '/' && !filename[n+1]) {
  455.             bdos(USERCODE,atoi(filename));
  456.             continue;
  457.             }
  458.         if (filename[1] == ':' && !filename[2] &&
  459.             (drive=toupper(filename[0])-'A') >= 0 && drive < 16) {
  460.                 if (seldisk(drive)) continue;
  461.                 bdos(RESETDRV,1 << (curdsk=drive));
  462.                 continue;
  463.                 }
  464.         name[0]='\0';
  465.         return;
  466.         }
  467. }
  468.  
  469. seldisk(drive)        /*log in 'drive', returning 0 for success, else FAIL */
  470. int drive;
  471. {
  472.     if (dskcheck(setjmp(dskerr))) return FAIL;
  473.     bdos(SELDSK,drive);
  474.     return 0;
  475. }
  476.  
  477. startstop(sw)        /*set up system to catch BDOS errors - or close
  478.                 it down*/
  479. int sw;
  480. {
  481.     char *bdosbase;
  482.     int i,*six,*errbase,err1(),err2(),err3(),err4();
  483.  
  484.     if (!cpm2x) return;    /*only works for CP/M 2.x */
  485.  
  486.     six=6;
  487.     bdosbase=*six;
  488.     errbase=bdosbase+3;
  489.  
  490.     if (sw) {
  491.         for (i=0; i < 4; i++) errold[i]=*(errbase+i);
  492.         *(errbase)=err1;
  493.         *(errbase+1)=err2;
  494.         *(errbase+2)=err3;
  495.         *(errbase+3)=err4;
  496.         }
  497.     else for (i=0; i < 4; i++) *(errbase+i)=errold[i];
  498. }
  499. ,0);
  500.             opentext(filename);
  501.             lastl=UNKNOWN;
  502.             lastread=0;
  503.             goteo