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