/* Copyright Notice: Copyright (c) 1987, 1997, 2006, 2009, 2010, 2012, 2013 * by J. Noel Chiappa * * Permission to use, copy, modify, and distribute this program * for any purpose and without fee is hereby granted, provided * that this copyright and permission notice appear on all copies * and supporting documentation, that my name not be used * in advertising or publicity pertaining to distribution of the * program without specific prior permission, and notice be given * in supporting documentation that copying and distribution is * by permission of J. Noel Chiappa. I make no representations about * the suitability of this software for any purpose. It is pro- * vided "as is" without express or implied warranty. */ /* New commands for Epsilon. * * Only a few Epsilon commands are overbound. They are: * * C-XC-R, was redo-changes, now read-file * A-C-I, was indent-under, now update-index * A-' ', was invoke-windows-menu, now set-permanent-mark * * Note that the code for 'invoke-windows-menu' doesn't work unless * it's bound to some variant of the space bar, which is why that * command is now on C-X ' '. */ #include "eel.h" #include "lcl.h" #include "kill.h" /* Defined parameters */ #define CHKINSIZ 1023 /* Max size for insert only new check */ #define INFIXSIZ 2048 /* Max size for index update */ #define HTTPLEN 4 /* sizeof("http") */ #define HTTPCF ALT(CTRL('f')) /* Uninitialized static. */ char chkinbuf[CHKINSIZ]; /* For check - see comment on getclipcbuf */ /* Forward to start of next line. */ command forward_line() on reg_tab[ALT('n')] { int opoint, omark; omark = mark; mark = opoint = point; if (search(1, "\n") != 0) return; ding(); mark = omark; point = opoint; } /* Don't exit with ^X^C - useful for main Epsilon, which should never be shut * down. */ command dont_exit() on reg_tab[ALT(CTRL('X'))] { cx_tab[CTRL('C')] = (short) abort; say("Exit disabled."); } /* Scroll the other window. */ command next_page_other_window() on reg_tab[ALT(CTRL('V'))] { window_number++; next_page(); window_number--; } /* More commands: read a file into the current buffer, throwing away the * contents, and also kill a buffer. Both of these ignore any modified buffer * contents. */ command really_read_file() on cx_tab[CTRL('R')] { modified = 0; exam_file("Read file"); } command really_kill_buffer() on cx_tab[CTRL('K')] { modified = 0; kill_buffer(); } /* Act like C-x b, but always switches to the previous buffer (if it exists); * if a previous buffer exists, and that previous buffer is not the current * buffer, that buffer is picked; if not, just gives up. */ command goto_prev_buffer() on cx_tab[ALT('b')] { if ((buf_exist(_prev_buffer) != 0) && (_prev_buffer != bufnum)) { to_buffer_num(_prev_buffer); return; } maybe_ding(bell_on_bad_key); } /* Argument shortcut; sometimes it's hard to see the number keys. For commands * which work differently with an argument (and where '4' is not viable), easy * way to give arg of '+1'. */ command arg1() on reg_tab[ALT(ESC)] { key = '1'; argument(); } /* Yet another easy argument shortcut, for '-1'. * * Harder to implement, as argument() wants to stay inside itself until it * calls the eventual command, so I can't fake out the input (as that requires * two characters) - unless I modify argument(). */ command argneg1() on reg_tab[ALT('`')] { mention("Argument: -1 "); getkey(); say(""); has_arg = 1; iter = -1; do_topkey(); } /* Permanent marks; doing an insert bashes the old mark, so this works * around that. With no arg, uses permanent mark 0. When setting low * marks, copies old value of mark to offset higher mark. */ command set_permanent_mark() on reg_tab[ALT(' ')] { int xiter; if (has_arg == 0) iter = 0; if (iter >= NPERMMK) error("Permanent mark number %d out of range", iter); if (permmark[iter] == 0) permmark[iter] = alloc_spot(); if (iter < PMKSV) { xiter = (iter + PMKSV); if (permmark[xiter] == 0) permmark[xiter] = alloc_spot(); *permmark[xiter] = *permmark[iter]; } *permmark[iter] = point; if (has_arg == 0) say("Permanent mark set"); else say("Permanent mark %d set", iter); iter = 0; } command goto_permanent_mark() on cx_tab[CTRL(' ')] { if (has_arg == 0) iter = 0; if (iter >= NPERMMK) error("Permanent mark number %d out of range", iter); if (permmark[iter] == 0) { if (has_arg == 0) error("Permanent mark not set in this buffer"); else error("Permanent mark %d not set in this buffer", iter); } point = *permmark[iter]; iter = 0; } /* Insert the top element on the kill stack in the current buffer * only if it's not already in the buffer. */ command insert_onlynew() on reg_tab[ALT(CTRL('Y'))] { if (getclipcbuf() == 0) return; insertifnew(); } /* Grab clipboard and stuff into compare buffer. * * Uses a static buffer, instead of one in the heap, to avoid all the hassle of * i) having to return two values, and ii) having to free it when done with it * (which is in another routine, anyway). */ getclipcbuf() { char *thisbuf; int csiz; get_clipboard(); thisbuf = bufname; bufname = _cur_kill_buf; csiz = size(); if (csiz > CHKINSIZ) { error("Insert too large for compare"); pop_kill(); bufname = thisbuf; return(0); } grab(0, csiz, &chkinbuf[0]); chkinbuf[size()] = '\0'; bufname = thisbuf; return(csiz); } /* Now insert string, but only if not in buffer already. * * With an argument, if there's a match, go ahead and insert anyway, * and leave mark at the duplicate. */ insertifnew() { int opoint; opoint = point; point = 0; if (search(1, &chkinbuf[0]) == 1) { say("String already in buffer"); ding(); point = matchstart; blink_screen(); point = opoint; if (has_arg == 0) return; mark = matchstart; } point = opoint; stuff(&chkinbuf[0]); build_first = 1; }