home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / newemacs / em.c < prev    next >
Text File  |  1979-12-31  |  14KB  |  519 lines

  1. /*
  2.  * This program is in public domain; written by Dave G. Conroy.
  3.  * This file contains the
  4.  * main driving routine, and some
  5.  * keyboard processing code, for the
  6.  * MicroEMACS screen editor.
  7.  */
  8. #include    "stdio.h"
  9. #include    "ed.h"
  10.  
  11. int exitflag;            /* exit flag                */
  12. int    currow;                /* Working cursor row        */
  13. int    curcol;                /* Working cursor column    */
  14. int    fillcol;            /* Current fill column        */
  15. int    thisflag;            /* Flags, this command        */
  16. int    lastflag;            /* Flags, last command        */
  17. int    curgoal;            /* Goal column            */
  18. BUFFER    *curbp;                /* Current buffer        */
  19. WINDOW    *curwp;                /* Current window        */
  20. BUFFER    *bheadp;            /* BUFFER listhead        */
  21. WINDOW    *wheadp;            /* WINDOW listhead        */
  22. BUFFER    *blistp;            /* Buffer list BUFFER        */
  23. short    kbdm[NKBDM] = CTLX|')';        /* Macro            */
  24. short    *kbdmip;            /* Input  for above        */
  25. short    *kbdmop;            /* Output for above        */
  26. char    pat[NPAT];            /* Pattern            */
  27.  
  28. typedef    struct    {
  29.     short    k_code;            /* Key code            */
  30.     int    (*k_fp)();        /* Routine to handle it        */
  31. }    KEYTAB;
  32.  
  33. extern    int    ctrlg();        /* Abort out of things        */
  34. extern    int    quit();            /* Quit                */
  35. extern    int    ctlxlp();        /* Begin macro            */
  36. extern    int    ctlxrp();        /* End macro            */
  37. extern    int    ctlxe();        /* Execute macro        */
  38. extern    int    fileread();        /* Get a file, read only    */
  39. extern    int    filevisit();        /* Get a file, read write    */
  40. extern    int    filewrite();        /* Write a file            */
  41. extern    int    filesave();        /* Save current file        */
  42. extern    int    getccol();        /* Get current column        */
  43. extern    int    gotobol();        /* Move to start of line    */
  44. extern    int    forwchar();        /* Move forward by characters    */
  45. extern    int    gotoeol();        /* Move to end of line        */
  46. extern    int    backchar();        /* Move backward by characters    */
  47. extern    int    forwline();        /* Move forward by lines    */
  48. extern    int    backline();        /* Move backward by lines    */
  49. extern    int    forwpage();        /* Move forward by pages    */
  50. extern    int    backpage();        /* Move backward by pages    */
  51. extern    int    gotobob();        /* Move to start of buffer    */
  52. extern    int    gotoeob();        /* Move to end of buffer    */
  53. extern    int    setfillcol();        /* Set fill column.        */
  54. extern    int    setmark();        /* Set mark            */
  55. extern    int    swapmark();        /* Swap "." and mark        */
  56. extern    int    search_replace();    /* Search and replace        */
  57. extern    int    query_replace();    /* Query and replace        */
  58. extern    int    forwsearch();        /* Search forward        */
  59. extern    int    backsearch();        /* Search backwards        */
  60. extern    int    showcpos();        /* Show the cursor position    */
  61. extern    int    nextwind();        /* Move to the next window    */
  62. extern  int    prevwind();        /* Move to the previous window    */
  63. extern    int    onlywind();        /* Make current window only one    */
  64. extern    int    splitwind();        /* Split current window        */
  65. extern    int    mvdnwind();        /* Move window down        */
  66. extern    int    mvupwind();        /* Move window up        */
  67. extern    int    enlargewind();        /* Enlarge display window.    */
  68. extern    int    shrinkwind();        /* Shrink window.        */
  69. extern    int    listbuffers();        /* Display list of buffers    */
  70. extern    int    usebuffer();        /* Switch a window to a buffer    */
  71. extern    int    killbuffer();        /* Make a buffer go away.    */
  72. extern    int    reposition();        /* Reposition window        */
  73. extern    int    refresh();        /* Refresh the screen        */
  74. extern    int    twiddle();        /* Twiddle characters        */
  75. extern    int    tab();            /* Insert tab            */
  76. extern    int    newline();        /* Insert CR-LF            */
  77. extern    int    indent();        /* Insert CR-LF, then indent    */
  78. extern    int    openline();        /* Open up a blank line        */
  79. extern    int    deblank();        /* Delete blank lines        */
  80. extern    int    quote();        /* Insert literal        */
  81. extern    int    backword();        /* Backup by words        */
  82. extern    int    forwword();        /* Advance by words        */
  83. extern    int    forwdel();        /* Forward delete        */
  84. extern    int    backdel();        /* Backward delete        */
  85. extern    int    kill();            /* Kill forward            */
  86. extern    int    yank();            /* Yank back from killbuffer.    */
  87. extern    int    upperword();        /* Upper case word.        */
  88. extern    int    lowerword();        /* Lower case word.        */
  89. extern    int    upperregion();        /* Upper case region.        */
  90. extern    int    lowerregion();        /* Lower case region.        */
  91. extern    int    capword();        /* Initial capitalize word.    */
  92. extern    int    delfword();        /* Delete forward word.        */
  93. extern    int    delbword();        /* Delete backward word.    */
  94. extern    int    killregion();        /* Kill region.            */
  95. extern    int    copyregion();        /* Copy region to kill buffer.    */
  96. /* extern    int    spawncli();     */       /* run CLI in a subjob.        */
  97. /* extern    int    spawn();    */         /* Run a command in a subjob.    */
  98. extern    int    quickexit();        /* low keystroke style exit.    */
  99. extern  int togglemode();           /* toggle insert/ovrwrit mode   */
  100. extern  int     help();                 /* activate help display */
  101.  
  102. /*
  103.  * Command table.
  104.  * This table  is *roughly* in ASCII
  105.  * order, left to right across the characters
  106.  * of the command. This expains the funny
  107.  * location of the control-X commands.
  108.  */
  109. KEYTAB    keytab[] = {
  110.     CTRL|'@',        setmark,
  111.     CTRL|'A',        gotobol,
  112.     CTRL|'B',        backchar,
  113. /*     CTRL|'C',        spawncli, */    /* Run CLI in subjob.    */
  114.     CTRL|'D',        forwdel,
  115.     CTRL|'E',        gotoeol,
  116.     CTRL|'F',        forwchar,
  117.     CTRL|'G',        ctrlg,
  118.     CTRL|'H',        backdel,
  119.     CTRL|'I',        tab,
  120.     CTRL|'J',        indent,
  121.     CTRL|'K',        kill,
  122.     CTRL|'L',        refresh,
  123.     CTRL|'M',        newline,
  124.     CTRL|'N',        forwline,
  125.     CTRL|'O',        openline,
  126.     CTRL|'P',        backline,
  127.     CTRL|'Q',        quote,        /* Often unreachable    */
  128.     CTRL|'R',        backsearch,
  129.     CTRL|'S',        forwsearch,    /* Often unreachable    */
  130.     CTRL|'T',        twiddle,
  131.     CTRL|'V',        forwpage,
  132.     CTRL|'W',        killregion,
  133.     CTRL|'Y',        yank,
  134.     CTRL|'Z',        mvdnwind,
  135.     CTRL|'_',        refresh,
  136.     CTLX|CTRL|'B',        listbuffers,
  137.     CTLX|CTRL|'C',        quit,        /* Hard quit.        */
  138.     CTLX|CTRL|'F',        quickexit,    /* quick save and exit    */
  139.     CTLX|CTRL|'L',        lowerregion,
  140.     CTLX|CTRL|'O',        deblank,
  141.     CTLX|CTRL|'N',        nextwind,
  142.     CTLX|CTRL|'P',        prevwind,
  143.     CTLX|CTRL|'R',        fileread,
  144.     CTLX|CTRL|'S',        filesave,    /* Often unreachable    */
  145.     CTLX|CTRL|'U',        upperregion,
  146.     CTLX|CTRL|'V',        filevisit,
  147.     CTLX|CTRL|'W',        filewrite,
  148.     CTLX|CTRL|'X',        swapmark,
  149.     CTLX|CTRL|'Z',        shrinkwind,
  150.  /*    CTLX|'!',        spawn,    */    /* Run 1 command.    */
  151.     CTLX|'=',        showcpos,
  152.     CTLX|'(',        ctlxlp,
  153.     CTLX|')',        ctlxrp,
  154.     CTLX|'1',        onlywind,
  155.     CTLX|'2',        splitwind,
  156.     CTLX|'B',        usebuffer,
  157.     CTLX|'C',        quit,        /* Hard quit.        */
  158.     CTLX|'E',        ctlxe,
  159.     CTLX|'F',        setfillcol,
  160.     CTLX|'K',        killbuffer,
  161.     CTLX|'L',        lowerregion,
  162.     CTLX|'N',        nextwind,
  163.     CTLX|'P',        prevwind,
  164.     CTLX|'R',        fileread,
  165.     CTLX|'S',        filesave,
  166.     CTLX|'U',        upperregion,
  167.     CTLX|'V',        filevisit,
  168.     CTLX|'W',        filewrite,
  169.     CTLX|'^',        enlargewind,
  170.     META|CTRL|'H',        delbword,
  171.     META|CTRL|'R',        query_replace,
  172.     META|CTRL|'Z',        mvupwind,
  173.     META|'!',        reposition,
  174.     META|'.',        setmark,
  175.     META|'>',        gotoeob,
  176.     META|'<',        gotobob,
  177.     META|' ',        setmark,
  178.     META|'B',        backword,
  179.     META|'C',        capword,
  180.     META|'D',        delfword,
  181.     META|'F',        forwword,
  182.     META|'L',        lowerword,
  183.     META|'Q',        quote,
  184.     META|'R',        search_replace,
  185.     META|'S',        forwsearch,
  186.     META|'U',        upperword,
  187.     META|'V',        backpage,
  188.     META|'W',        copyregion,
  189.     META|'Z',        mvupwind,
  190.         META|'?',               help,
  191.     META|0x7F,        delbword,
  192.     0x7F,            backdel,
  193.     EXTKY|71,               gotobob,
  194.         EXTKY|72,               backline,
  195.     EXTKY|73,               backpage,
  196.     EXTKY|75,               backchar,
  197.         EXTKY|77,               forwchar,
  198.     EXTKY|79,               gotoeob,
  199.         EXTKY|80,               forwline,
  200.     EXTKY|81,           forwpage,
  201.     EXTKY|82,         togglemode,
  202.     EXTKY|83,        forwdel
  203. };
  204.  
  205. #define    NKEYTAB    (sizeof(keytab)/sizeof(keytab[0]))
  206.  
  207. main()
  208. {
  209.     char        bname[NBUFN];
  210.     
  211.     strcpy(bname, "main");            /* Set default buffer nm*/
  212.                         /* Initialize           */
  213.     edinit(bname);                /* Buffers, windows.    */
  214.     vtinit();                /* Displays.        */
  215.     stayres();
  216.  
  217. }
  218.  
  219.  
  220. em()
  221. {
  222.     register int    c;
  223.     register int    f;
  224.     register int    n;
  225.     register int    mflag;
  226.     extern int sgarbf;
  227.  
  228.     exitflag = FALSE;
  229.     lastflag = 0;
  230.     sgarbf   = TRUE;
  231.     save_screen_and_cursor();
  232.  
  233.                 /* Fake last flags.    */
  234. loop:
  235.     update();                /* Fix up the screen    */
  236.     c = getkey();
  237.     if (mpresf != FALSE) {
  238.         mlerase();
  239.         update();
  240.         if (c == ' ')            /* ITS EMACS does this    */
  241.             goto loop;
  242.     }
  243.     f = FALSE;
  244.     n = 1;
  245.     if (c == (CTRL|'U')) {            /* ^U, start argument    */
  246.         f = TRUE;
  247.         n = 4;                /* with argument of 4 */
  248.         mflag = 0;            /* that can be discarded. */
  249.         mlwrite("Arg: 4");
  250.         while ((c=getkey()) >='0' && c<='9' || c==(CTRL|'U') || c=='-'){
  251.             if (c == (CTRL|'U'))
  252.                 n = n*4;
  253.             /*
  254.              * If dash, and start of argument string, set arg.
  255.              * to -1.  Otherwise, insert it.
  256.              */
  257.             else if (c == '-') {
  258.                 if (mflag)
  259.                     break;
  260.                 n = 0;
  261.                 mflag = -1;
  262.             }
  263.             /*
  264.              * If first digit entered, replace previous argument
  265.              * with digit and set sign.  Otherwise, append to arg.
  266.              */
  267.             else {
  268.                 if (!mflag) {
  269.                     n = 0;
  270.                     mflag = 1;
  271.                 }
  272.                 n = 10*n + c - '0';
  273.             }
  274.             mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
  275.         }
  276.         /*
  277.          * Make arguments preceded by a minus sign negative and change
  278.          * the special argument "^U -" to an effective "^U -1".
  279.          */
  280.         if (mflag == -1) {
  281.             if (n == 0)
  282.                 n++;
  283.             n = -n;
  284.         }
  285.     }
  286.     if (c == (CTRL|'X'))            /* ^X is a prefix    */
  287.         c = CTLX | getctl();
  288.     if (kbdmip != NULL) {            /* Save macro strokes.    */
  289.         if (c!=(CTLX|')') && kbdmip>&kbdm[NKBDM-6]) {
  290.             ctrlg(FALSE, 0);
  291.             goto loop;
  292.         }
  293.         if (f != FALSE) {
  294.             *kbdmip++ = (CTRL|'U');
  295.             *kbdmip++ = n;
  296.         }
  297.         *kbdmip++ = c;
  298.     }
  299.     execute(c, f, n);            /* Do it.        */
  300.     if ( ! exitflag) goto loop;
  301.  
  302.     restore_screen_and_cursor();
  303. }
  304.  
  305. /*
  306.  * Initialize all of the buffers
  307.  * and windows. The buffer name is passed down as
  308.  * an argument, because the main routine may have been
  309.  * told to read in a file by default, and we want the
  310.  * buffer name to be right.
  311.  */
  312. edinit(bname)
  313. char    bname[];
  314. {
  315.     register BUFFER    *bp;
  316.     register WINDOW    *wp;
  317.  
  318.     bp = bfind(bname, TRUE, 0);        /* First buffer        */
  319.     blistp = bfind("[List]", TRUE, BFTEMP);    /* Buffer list buffer    */
  320.     wp = (WINDOW *) malloc(sizeof(WINDOW));    /* First window        */
  321.     if (bp==NULL || wp==NULL || blistp==NULL)
  322.         exit(1);
  323.     curbp  = bp;                /* Make this current    */
  324.     wheadp = wp;
  325.     curwp  = wp;
  326.     wp->w_wndp  = NULL;            /* Initialize window    */
  327.     wp->w_bufp  = bp;
  328.     bp->b_nwnd  = 1;            /* Displayed.        */
  329.     wp->w_linep = bp->b_linep;
  330.     wp->w_dotp  = bp->b_linep;
  331.     wp->w_doto  = 0;
  332.     wp->w_markp = NULL;
  333.     wp->w_marko = 0;
  334.     wp->w_toprow = 0;
  335.     wp->w_ntrows = NROW-1;        /* "-1" for mode line.    */
  336.     wp->w_force = 0;
  337.     wp->w_flag  = WFMODE|WFHARD;        /* Full.        */
  338. }
  339.     
  340. /*
  341.  * This is the general command execution
  342.  * routine. It handles the fake binding of all the
  343.  * keys to "self-insert". It also clears out the "thisflag"
  344.  * word, and arranges to move it to the "lastflag", so that
  345.  * the next command can look at it. Return the status of
  346.  * command.
  347.  */
  348. execute(c, f, n)
  349. {
  350.     register KEYTAB *ktp;
  351.     register int    status;
  352.  
  353.     ktp = &keytab[0];            /* Look in key table.    */
  354.     while (ktp < &keytab[NKEYTAB]) {
  355.         if (ktp->k_code == c) {
  356.             thisflag = 0;
  357.             status   = (*ktp->k_fp)(f, n);
  358.             lastflag = thisflag;
  359.             return (status);
  360.         }
  361.         ++ktp;
  362.     }
  363.  
  364.     if (c&(META|CTLX|CTRL|EXTKY)) {
  365.         mlwrite("I don't know how to do that!");
  366.         scr_co(0x07) ;
  367.         return (FALSE);
  368.     }
  369.  
  370.     /*
  371.      * If a space was typed, fill column is defined, the argument is non-
  372.      * negative, and we are now past fill column, perform word wrap.
  373.      */
  374.     if (c == ' ' && fillcol > 0 && n>=0 && getccol(FALSE) > fillcol)
  375.         wrapword();
  376.  
  377.     if ((c>=0x20 && c<=0x7E)        /* Self inserting.    */
  378.     ||  (c>=0xA0 && c<=0xFE)) {
  379.         if (n <= 0) {            /* Fenceposts.        */
  380.             lastflag = 0;
  381.             return (n<0 ? FALSE : TRUE);
  382.         }
  383.         thisflag = 0;            /* For the future.    */
  384.         /* This is new. Instead of inserting the character,
  385.            overwrite the character if in overwrite mode.
  386.         */
  387.         status   = lwrite(n, c);
  388.         lastflag = thisflag;
  389.         return (status);
  390.     }
  391.     lastflag = 0;                /* Fake last flags.    */
  392.     return (FALSE);
  393. }
  394.  
  395.  
  396. /*
  397.  * Fancy quit command, as implemented
  398.  * by Norm. If the current buffer has changed
  399.  * do a write current buffer and exit emacs,
  400.  * otherwise simply exit.
  401.  */
  402. quickexit(f, n)
  403. {
  404.     if ((curbp->b_flag&BFCHG) != 0        /* Changed.        */
  405.     && (curbp->b_flag&BFTEMP) == 0)        /* Real.        */
  406.         filesave(f, n);
  407.     quit(f, n);                /* conditionally quit    */
  408. }
  409.  
  410. /*
  411.  * Quit command. If an argument, always
  412.  * quit. Otherwise confirm if a buffer has been
  413.  * changed and not written out. Normally bound
  414.  * to "C-X C-C".
  415.  */
  416. quit(f, n)
  417. {
  418.     register int    s;
  419.  
  420.     if (f != FALSE                /* Argument forces it.    */
  421.     || anycb() == FALSE            /* All buffers clean.    */
  422.     || (s=mlyesno("Quit")) == TRUE) {    /* User says it's OK.    */
  423.         vttidy();
  424.         exitflag = TRUE;
  425.     }
  426.     return (s);
  427. }
  428.  
  429. /*
  430.  * Begin a keyboard macro.
  431.  * Error if not at the top level
  432.  * in keyboard processing. Set up
  433.  * variables and return.
  434.  */
  435. ctlxlp(f, n)
  436. {
  437.     if (kbdmip!=NULL || kbdmop!=NULL) {
  438.         mlwrite("Not now");
  439.         return (FALSE);
  440.     }
  441.     mlwrite("[Start macro]");
  442.     kbdmip = &kbdm[0];
  443.     return (TRUE);
  444. }
  445.  
  446. /*
  447.  * End keyboard macro. Check for
  448.  * the same limit conditions as the
  449.  * above routine. Set up the variables
  450.  * and return to the caller.
  451.  */
  452. ctlxrp(f, n)
  453. {
  454.     if (kbdmip == NULL) {
  455.         mlwrite("Not now");
  456.         return (FALSE);
  457.     }
  458.     mlwrite("[End macro]");
  459.     kbdmip = NULL;
  460.     return (TRUE);
  461. }
  462.  
  463. /*
  464.  * Execute a macro.
  465.  * The command argument is the
  466.  * number of times to loop. Quit as
  467.  * soon as a command gets an error.
  468.  * Return TRUE if all ok, else
  469.  * FALSE.
  470.  */
  471. ctlxe(f, n)
  472. {
  473.     register int    c;
  474.     register int    af;
  475.     register int    an;
  476.     register int    s;
  477.  
  478.     if (kbdmip!=NULL || kbdmop!=NULL) {
  479.         mlwrite("Not now");
  480.         return (FALSE);
  481.     }
  482.     if (n <= 0) 
  483.         return (TRUE);
  484.     do {
  485.         kbdmop = &kbdm[0];
  486.         do {
  487.             af = FALSE;
  488.             an = 1;
  489.             if ((c = *kbdmop++) == (CTRL|'U')) {
  490.                 af = TRUE;
  491.                 an = *kbdmop++;
  492.                 c  = *kbdmop++;
  493.             }
  494.             s = TRUE;
  495.         } while (c!=(CTLX|')') && (s=execute(c, af, an))==TRUE);
  496.         kbdmop = NULL;
  497.     } while (s==TRUE && --n);
  498.     return (s);
  499. }
  500.  
  501. /*
  502.  * Abort.
  503.  * Beep the beeper.
  504.  * Kill off any keyboard macro,
  505.  * etc., that is in progress.
  506.  * Sometimes called as a routine,
  507.  * to do general aborting of
  508.  * stuff.
  509.  */
  510. ctrlg(f, n)
  511. {
  512.     scr_co(0x07);
  513.     if (kbdmip != NULL) {
  514.         kbdm[0] = (CTLX|')');
  515.         kbdmip  = NULL;
  516.     }
  517.     return (ABORT);
  518. }
  519.