📄 eemain.c
字号:
/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International * This software is quasi-public; it may be used freely with * like software, but may NOT be sold or made part of licensed * products without permission of the author. *//* * EEMAIN ELLE Main Command Loop */#include "elle.h"#include <stdio.h>#if !(V6)#include <signal.h>#else#include "eesigs.h" /* Use this on V6 system */#endif /*V6*/char *argfile[MAXARGFILES]; /* Filename args at startup */extern int (*sbm_debug)();extern int (*sbv_debug)();int (*vfy_vec)(); /* If non-zero, routine to verify data * after each main-loop command */main (argc, argv)int argc;char **argv;{ register int c; /* Current command character */ register int i; static int waitct; extern int errsbm();#if SUN extern int sun_rdevf; /* from EESUN */#endif#ifdef STKMEM char stackm[STKMEM]; /* Allocate some unused stack space */#endif /*STKMEM*/ sbv_debug = errsbm; /* Load with addrs of routine to */ sbm_debug = errsbm; /* process SB and SBM errors. */#ifdef STKMEM sbm_init(&stackm[0],(SBMO)STKMEM); /* Initialize mem alloc rtns */#endif /*STKMEM*/#if SUN sun_main(&argc, argv); /* On SUN, invoke window startup */#endif /*SUN*/ setbuf(stdout, (char *)NULL); /* Remove all stdio buffering */ setbuf(stderr, (char *)NULL); /* in case of error reports. */ waitct = 0; /* debugging */ doargs(argc,argv); /* Set up args */ initialize (); /* Initialize the editor */ if (argfile[0]) /* shell line arg */ find_file(argfile[0]);#if MAXARGFILES > 1 if(argfile[1]) { f_2winds(); /* Make 2 windows, go to 2nd */ i = 1;#if MAXARGFILES > 2 for (; i < MAXARGFILES; ++i)#endif /* > 2 files */ find_file(argfile[i]); /* Get further file(s) */ f_othwind(); /* Move back to 1st window */ }#endif /* > 1 file */ redp(RD_SCREEN|RD_MODE); /* Clear and show mode line */ setexit(0); /* catch for ints, ^G throws *//* -----------------------------------------------------------** ELLE MAIN LOOP***/ for (;;) { /* First set up default arg unless last cmd specified it */ if(this_cmd != ARGCMD) { exp = 1; /* Default arg is 1 */ exp_p = 0; /* Say no explicit arg */ last_cmd = this_cmd; } this_cmd = 0; askclr(); /* If stuff asked, say to clear it */ if(cmd_wait()) waitct++; else if(rd_type != 0) redisplay(); /* Redisplay if needed and no input */#if SUN sun_rdevf = 1; /* Allow mouse events on this input */#endif c = cmd_read(); /* Read an editor command */ sayclr(); /* Ask to clear echo area cleverly */#if SUN if(c != -1) /* SUN may not have real input */#endif /* if mouse event happened. */ cmd_xct(c); /* Execute the command char! */ if(vfy_vec) /* If debugging, */ (*vfy_vec)(1); /* verify data structs right away */ }}char *prof_file; /* Can specify user profile filename */doargs(argc,argv)int argc;char **argv;{ register int cnt, c; register char **av; extern int tibfmsk; int argfiles = 0; int argsignored = 0; av = argv; cnt = argc;#if V6 /* V6 doesn't have environment thus no TERM var */ /* Hack to force terminal type; analyze pgm name to get * possible ".type" suffix. */ if(cnt && (c = strlen(*av))) while(--c >= 0) { switch(av[0][c]) { case '.': tv_stype = &av[0][c+1]; case '/': break; default: continue; } break; }#endif /*V6*/ while(--cnt > 0) { ++av; if(*av[0] != '-') /* If not switch, */ { /* assume it's an input filename */ if (argfiles < MAXARGFILES) argfile[argfiles++] = *av; else ++argsignored; continue; } c = upcase(av[0][1]); switch(c) /* Switches without args */ { case 'I': /* Allow debug ints */ dbg_isw = 1; continue; case '8': /* Ask for 8-bit input */ tibfmsk = 0377; continue; case '7': /* Ask for 7-bit input */ tibfmsk = 0177; continue;#if IMAGEN case 'R': /* Debug redisplay stuff */ dbg_redp = 1; continue;#endif /*IMAGEN*/ } if(--cnt <= 0) goto stop; ++av; switch(c) /* Switches with args */ { case 'T': /* Terminal type */ tv_stype = *av; break; case 'P': prof_file = *av; default: goto stop; } continue; stop: printf("ELLE: bad switch: %s\n",*av); exit(1); } if (argsignored > 0) { printf("ELLE: more than %d file args, %d ignored.\n", MAXARGFILES, argsignored); sleep(2); /* Complain but continue after pause */ }}int f_throw(); /* throw function */int bite_bag(); /* Error handling routine */int hup_exit(); /* Hangup handling routine */struct majmode ifunmode = { "Fundamental" };initialize () /* Initialization */{#if SUN extern int sun_winfd;#endif cur_mode = fun_mode = &ifunmode; /* Set current major mode */ unrchf = pgoal = -1; if(!homedir) {#if V6 extern char *logdir(); homedir = logdir();#else /* V7 */ homedir = getenv("HOME");#endif /*-V6*/ } sbx_tset((chroff)0,0); /* Create swapout file */ /* (Temporary hack, fix up later) */ hoard(); /* Hoard a FD for write purposes */ redp_init(); /* Set up the display routines */ init_buf(); /* Set up initial buffers */ set_profile(prof_file); /* Set up user profile */#if SUN if(sun_winfd) sun_init();#endif /*SUN*/ /* Set up signal handlers */#if 0 /* not really used */ signal (SIGQUIT, f_throw); /* Quit - on ^G */#endif#if !(MINIX) signal (SIGSYS, bite_bag); /* Bad arg to Sys call */#endif signal (SIGSEGV, bite_bag); /* Segmentation Violation */#if !(COHERENT) signal (SIGILL, bite_bag); /* Illegal Instruction interrupt */ signal (SIGBUS, bite_bag); /* Bus Error interrupt */#endif /*-COHERENT*/#if !(TOPS20) /* T20 just detaches job */ signal (SIGHUP, hup_exit); /* Terminal Hangup interrupt */#endif /*-TOPS20*/}/* NOTE: This routine is not actually used, because ELLE does not * allow interrupts to do anything. *//* EFUN: "Error Throw" */f_throw () /* abort whatever is going on */{ ring_bell (); curs_lin = -1000; /* make t_curpos do something */ redp(RD_MOVE); /* crock: cursor seems to move, so fix it */ signal(SIGQUIT, f_throw); /* rearm signal *//* unwind_stack(main); */ reset(1); /* throw to main loop */}/* RING_BELL - General-purpose feeper when something goes wrong with * a function. */ring_bell(){ t_bell(); /* Tell user something's wrong */#if FX_SKMAC f_ekmac(); /* Stop collecting keyboard macro if any */#endif /*FX_SKMAC*/}/* EFUN: "Return to Superior" * Behavior here is somewhat system-dependent. If it is possible to * suspend the process and continue later, we do not ask about modified * buffers. Otherwise, we do. Questioning can always be forced by using * the prefix ^U. * Note that here we try to be very careful about not letting the user * exit while buffers are still modified, since UNIX flushes the process * if we exit. Also, the code here conspires with sel_mbuf to rotate * through all modified buffers, complaining about a different one each time, * so that the user need not even know how to select a buffer! */f_retsup(){ register char *reply; register int c; register struct buffer *b, *b2; extern struct buffer *sel_mbuf(); extern int tsf_pause; /* If we have capability of pausing and later continuing, do that, * except if CTRL-U forces us into question/save/quit behavior. */ if(tsf_pause && (exp_p != 4)) { clean_exit(); /* Return TTY to normal mode */ ts_pause(); /* Pause this inferior */ set_tty(); /* Continued, return to edit mode */ redp(RD_SCREEN); return; } /* Sigh, do more typical "Are you sure" questioning prior to * killing the editor permanently. */ b = cur_buf; if((b = sel_mbuf(b)) || (b = sel_mbuf((struct buffer *)0)) ) { if(b2 = sel_mbuf(b)) reply = ask( "Quit: buffers %s, %s,... still have changes - forget them? ", b->b_name, b2->b_name); else reply = ask( "Quit: buffer %s still has changes - forget them? ", b->b_name); } else {#if IMAGEN /* Do not ask further if nothing modified */ barf("Bye"); clean_exit(); exit(0);#else reply = ask("Quit? ");#endif /*-IMAGEN*/ } if (reply == 0) return; /* Aborted, just return */ c = upcase(*reply); /* Get 1st char of reply */ chkfree(reply); switch(c) { case 'Y':#if IMAGEN barf("Bye");#endif /*IMAGEN*/ clean_exit(); exit(0);#if 0 case 'S': /* Suspend command for debugging */ bkpt(); return;#endif /*COMMENT*/ default: /* Complain */ ring_bell(); case 'N': if(b) /* B set if we have any modified buffers */ { sel_buf(b); if(b->b_fn) saynow("Use ^X ^S to save buffer"); else saynow("Use ^X ^W to write out buffer"); } }}#if FX_WFEXIT/* EFUN: "Write File Exit" (not EMACS) - from IMAGEN config */f_wfexit(){ exp_p = 1; /* Ensure f_savefiles asks no questions */ if (! f_savefiles()) /* Save all modified buffers, but */ return; /* stay here if any save fails */ saynow("Bye"); clean_exit(); exit(0);}#endif /*FX_WFEXIT*//* Subprocess-handling stuff; put here for time being. *//* EFUN: "Push to Inferior" */#if TOPS20#include <frkxec.h> /* Support for KCC forkexec() call */#endiff_pshinf(){ register int res; register int (*sav2)(), (*sav3)(); int pid, status; char *shellname;#if IMAGEN char fullshell[64];#endif /*IMAGEN*/ sav2 = signal(SIGINT, SIG_IGN); /* Ignore TTY interrupts */ sav3 = signal(SIGQUIT, SIG_IGN); /* Ditto TTY "quit"s */ clean_exit(); /* Restore normal TTY modes */#if TOPS20 { struct frkxec fx; fx.fx_flags = FX_WAIT | FX_T20_PGMNAME; fx.fx_name = "SYS:EXEC.EXE"; fx.fx_argv = fx.fx_envp = NULL; if (forkexec(&fx) < 0) writerr("Cannot run EXEC"); }#else /*-TOPS20*/ switch(pid = fork()) { case -1: writerr("Cannot fork"); break; case 0: /* We're the child */ for(res = 3; res < 20;) /* Don't let inf hack fd's */ close(res++);#if V6 execl("/bin/sh","-sh",0);#else signal(SIGINT, SIG_DFL); /* V7 shell wants this?? */ signal(SIGQUIT, SIG_DFL); /* */#if IMAGEN if((shellname = getenv("SHELL")) == 0) shellname = "sh"; strcpy(fullshell, "/bin/"); strcat(fullshell, shellname); shellname = fullshell;#else if((shellname = getenv("SHELL")) == 0) shellname = "/bin/sh";#endif /*-IMAGEN*/ if((shellname = getenv("SHELL")) == 0) shellname = "/bin/sh"; execl(shellname, shellname, 0);#endif /*-V6*/ writerr("No shell!"); exit(1); break; default: while((res = wait(&status)) != pid && res != -1); break; }#endif /*-TOPS20*/ signal(SIGINT, sav2); /* Restore signal settings */ signal(SIGQUIT, sav3); set_tty(); /* Restore editor TTY modes */ redp(RD_SCREEN|RD_MODE); /* Done, redisplay */}/* Miscellaneous utility routines - memory alloc/free and string hacking. * If this page becomes overly large, it can be split off into a separate * file called E_MISC. */char *strdup(s)char *s; /* Note that STRCPY's return val must be its 1st arg */{ char *strcpy(); return(strcpy(memalloc((SBMO)(strlen(s)+1)), s));}char *memalloc(size)SBMO size;{ register SBMA ptr; extern SBMA sbx_malloc(); if ((ptr = (SBMA)sbx_malloc(size)) != 0) return((char *)ptr); barf("ELLE: No memory left"); askerr(); return(0); /* If we dare to continue... */}chkfree (ptr)SBMA ptr;{ if(!free(ptr)) { errbarf("Something overwrote an allocated block!"); askerr(); }}/* USTRCMP - Uppercase String Compare. * Returns 0 if mismatch, * 1 if full match, * -1 if str1 runs out first (partial match) */ustrcmp(str1,str2)char *str1, *str2;{ register char *s1, *s2; register int c; s1 = str1; s2 = str2; while(c = *s1++) { if(c != *s2 && upcase(c) != upcase(*s2)) return(0); s2++; } return(c == *s2 ? 1 : -1);}/* WRITERR(str) - Output string to standard error output.** This is a separate routine to save a little space on calls.*/writerr(str)char *str;{ return(writez(2, str));}/* WRITEZ(fd, str) - Miscellaneous general-purpose string output. */writez(fd,acp)int fd;char *acp;{ register char *cp; cp = acp; while(*cp++); write(fd,acp,cp-acp-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -