home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
eel
/
pntstk04.zip
/
POINTSTK.E
< prev
Wrap
Text File
|
1991-08-12
|
14KB
|
566 lines
/*
* For Epsilon version 5.0:
*
* Copyright (C) 1991, K. Shane Hartman
*
* This file is free software; you can redistribute it and/or modify
* it so long as this notice is preserved and no fee is charged (other than
* reasonable media fees) for distribution. You are forbidden to deny these
* rights to any other user of Epsilon. Lugaru Software Ltd. may incorporate
* any and all of this code into Epsilon and have all rights to
* the code, since it is only useful for Epsilon. It would be better if
* implemented at a lowlevel, though, rather than EEL.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Implements stack of points that can be pushed and popped ala Gnu Emacs
* or Zmacs. Also, implements registers (named points) like Gnu emacs.
*
* If POINTSTK_DONT_SUPERSEDE is NOT defined (default NOT defined), this
* file will supersede many Lugaru commands so that the point is pushed
* whenever these commands are executed. In general, these commands are
* the ones that can take you far away from where you were (like
* goto-end, pluck-tag, etc.). To go back to where you were you can just
* do C-u Alt-Space (or M-x pop-point).
*
* If POINTSTK_VERBOSE is defined (default NOT defined), then you will be
* told in the echo area every time the point has been pushed or popped.
* Otherwise, the commands are quiet (except for explicit push or pop
* point commands).
*
* Registers are like bookmarks. You use C-x S (set-register) to remember
* a position and a buffer (where you are when the command is issued). You
* are prompted for a single character name ('A' - 'Z'). C-x J (jump-register)
* can be used to return to the remembered position (C-x J Z would return
* to the location stored in register Z.
*
* Also note the commented command M-x edit-registers.
*
*
* Revison History: for epsilon 5.0
* Send bug fixes, comments or suggestions to shane@ai.mit.edu.
*
* Version 1.2: 07/17/91 shane@ai.mit.edu distributed
* Version 1.3: 08/02/91 shane@ai.mit.edu Offer Lugaru rights to the code.
* Version 1.4: 08/09/91 johnk@wrq.com (John Kercheval) add automatic pushes
* for several key functions. Move push and pop messages to
* push_or_pop_point to prevent unwanted messages during
* processing. Make pop_point and push_point commands so they
* are bindable.
* 08/12/91 shane@ai.mit.edu Integrated these
* changes and added conditionals to control the verbose messages
* and superceding of routines (POINTSTK_DONT_SUPERSEDE,
* POINTSTK_VERBOSE). The default behavior is to add automatic
* pushes and do them quietly as described above.
*
*/
#include "eel.h"
/*
* POINT STACK
*/
#define STACK_DEPTH 32 /* Maximum stack depth */
typedef struct selt
{
int spot;
char *buff;
} SELT;
SELT point_stack[STACK_DEPTH]; /* Points are saved here */
int stackp = 0;
/*
* REGISTERS
*/
typedef struct reg
{
int *spot;
char *buff;
} REGISTER;
#define REGCOUNT 26
REGISTER registers[REGCOUNT];
/*
* Initialization
*/
init_point_stack()
{
int i;
for (i = 0; i < REGCOUNT; i++)
{
registers[i].buff = 0;
registers[i].spot = 0;
}
for (i = 0; i < STACK_DEPTH; i++)
{
point_stack[i].spot = 0;
point_stack[i].buff = 0;
}
stackp = 0;
#ifndef POINTSTK_DONT_SUPERSEDE
/*
* function name replacements for pointstk sensitive functions
*/
if (!find_index ("old_goto_end"))
replace_name ("goto_end", "old_goto_end");
else
drop_name ("goto_end");
replace_name ("pstk_goto_end", "goto_end");
if (!find_index ("old_goto_beginning"))
replace_name ("goto_beginning", "old_goto_beginning");
else
drop_name ("goto_beginning");
replace_name ("pstk_goto_beginning", "goto_beginning");
if (!find_index ("old_pluck_tag"))
replace_name ("pluck_tag", "old_pluck_tag");
else
drop_name ("pluck_tag");
replace_name ("pstk_pluck_tag", "pluck_tag");
if (!find_index ("old_goto_tag"))
replace_name ("goto_tag", "old_goto_tag");
else
drop_name ("goto_tag");
replace_name ("pstk_goto_tag", "goto_tag");
if (!find_index ("old_regex_search"))
replace_name ("regex_search", "old_regex_search");
else
drop_name ("regex_search");
replace_name ("pstk_regex_search", "regex_search");
if (!find_index ("old_incremental_search"))
replace_name ("incremental_search", "old_incremental_search");
else
drop_name ("incremental_search");
replace_name ("pstk_incremental_search", "incremental_search");
if (!find_index ("reverse_incremental_search"))
replace_name ("reverse_incremental_search", "old_reverse_incremental_search");
else
drop_name ("reverse_incremenatal_search");
replace_name ("pstk_reverse_incremental_search", "reverse_incremental_search");
if (!find_index ("old_reverse_regex_search"))
replace_name ("reverse_regex_search", "old_reverse_regex_search");
else
drop_name ("reverse_regex_search");
replace_name ("pstk_reverse_regex_search", "reverse_regex_search");
if (!find_index ("old_reverse_string_search"))
replace_name ("reverse_string_search", "old_reverse_string_search");
else
drop_name ("reverse_string_search");
replace_name ("pstk_reverse_string_search", "reverse_string_search");
if (!find_index ("old_string_search"))
replace_name ("string_search", "old_string_search");
else
drop_name ("string_search");
replace_name ("pstk_string_search", "string_search");
if (!find_index ("old_start_process"))
replace_name ("start_process", "old_start_process");
else
drop_name ("start_process");
replace_name ("pstk_start_process", "start_process");
if (!find_index ("old_goto_line"))
replace_name ("goto_line", "old_goto_line");
else
drop_name ("goto_line");
replace_name ("pstk_goto_line", "goto_line");
if (!find_index ("old_find_file"))
replace_name ("find_file", "old_find_file");
else
drop_name ("find_file");
replace_name ("pstk_find_file", "find_file");
if (!find_index ("old_visit_file"))
replace_name ("visit_file", "old_visit_file");
else
drop_name ("visit_file");
replace_name ("pstk_visit_file", "visit_file");
if (!find_index ("old_make"))
replace_name ("make", "old_make");
else
drop_name ("make");
replace_name ("pstk_make", "make");
if (!find_index ("old_next_error"))
replace_name ("next_error", "old_next_error");
else
drop_name ("next_error");
replace_name ("pstk_next_error", "next_error");
#endif /* POINTSTK_DONT_SUPERSEDE */
}
/*
* Functions with added support for point stack. These "wrappers" push
* the point stack and then execute the old command (courtesy of John
* Kercheval). This way, you don't have to modify all the Lugaru code to
* push the point stack. Since I (shane) have already done so, I have
* conditionalized the code so that if POINTSK_DONT_SUPERSEDE is defined,
* this will not occur. Most users will probably want to leave
* POINTSK_DONT_SUPERSEDE undefined (unless you have already changed all
* the Lugaru code as I have done).
*
* There is one advantage to modifying Lugaru code: these superseded commands
* push the point even if the original command is aborted (or fails). If you
* modify Lugaru code, you can insert calls to do_push_point at exactly the
* right place. Given the hassle of maintaining changes between releases of
* Epsilon, the approach below is probably better.
*/
#ifndef POINTSTK_DONT_SUPERSEDE
pstk_goto_end() {
push_point();
old_goto_end();
}
pstk_goto_beginning() {
push_point();
old_goto_beginning();
}
pstk_pluck_tag() {
push_point();
old_pluck_tag();
}
pstk_goto_tag() {
push_point();
old_goto_tag();
}
pstk_regex_search() {
push_point();
old_regex_search();
}
pstk_incremental_search() {
push_point();
old_incremental_search();
}
pstk_reverse_incremental_search() {
push_point();
old_reverse_incremental_search();
}
pstk_reverse_regex_search() {
push_point();
old_reverse_regex_search();
}
pstk_reverse_string_search() {
push_point();
old_reverse_string_search();
}
pstk_string_search() {
push_point();
old_string_search();
}
pstk_start_process() {
push_point();
old_start_process();
}
pstk_goto_line() {
push_point();
old_goto_line();
}
pstk_find_file() {
push_point();
old_find_file();
}
pstk_visit_file() {
push_point();
old_visit_file();
}
pstk_make() {
push_point();
old_make();
}
pstk_next_error() {
push_point();
old_next_error();
}
#endif /* POINTSTK_DONT_SUPERSEDE */
when_loading()
{
init_point_stack();
}
/*************
* Point Stack
*/
do_push_point(bpoint, bname)
int bpoint;
char *bname;
{
if (stackp == (STACK_DEPTH - 1))
{
int i;
if (point_stack[0].buff)
free (point_stack[0].buff);
for (i = 1; i < STACK_DEPTH; i++)
{
point_stack[i - 1].buff = point_stack[i].buff;
point_stack[i - 1].spot = point_stack[i].spot;
}
stackp--;
}
point_stack[stackp].spot = bpoint;
point_stack[stackp].buff = malloc (strlen (bname) + 1);
strcpy (point_stack[stackp].buff, bname);
stackp++;
#ifdef POINTSTK_VERBOSE
say ("Point pushed.");
#endif
}
command push_point()
{
do_push_point (point, bufname);
}
command pop_point()
{
int i;
tail_recurse:
if (stackp > 0 && point_stack[--stackp].buff)
{
if (!exist (point_stack[stackp].buff))
{
free (point_stack[stackp].buff);
point_stack[stackp].buff = 0;
goto tail_recurse;
}
to_buffer (point_stack[stackp].buff);
point = point_stack[stackp].spot;
free (point_stack[stackp].buff);
point_stack[stackp].buff = 0;
point_stack[stackp].spot = 0;
#ifdef POINTSTK_VERBOSE
say ("Point popped");
#endif
}
else
{
stackp = 0;
ding ();
}
}
/*
* With argument pops the stack and moves you there
* With no argument, saves the point and buffer name on the stack
*/
command
push_or_pop_point() on reg_tab[ALT(' ')]
{
if (has_arg)
{
iter = 0;
if (stackp > 0)
{
pop_point ();
#ifndef POINTSTK_VERBOSE
say ("Point popped.");
#endif
}
else
exchange_point_and_mark ();
}
else
{
mark = point;
push_point ();
#ifndef POINTSTK_VERBOSE
say ("Point pushed");
#endif
}
}
/***********
* Registers
*/
clear_register(reg)
REGISTER *reg;
{
if (reg->buff)
{
free (reg->buff);
reg->buff = 0;
}
if (reg->spot)
{
free_spot (reg->spot);
reg->spot = 0;
}
}
command
set_register() on cx_tab['s']
{
char k;
int reg;
say ("Set Register: ");
term_position (14, 24);
k = getkey ();
if (k == abort_key)
error ("Aborted");
reg = toupper (k);
reg -= 'A';
if (reg < 0 || reg >= REGCOUNT)
error ("Invalid register: %c", (char) k);
clear_register (®isters[reg]);
registers[reg].buff = malloc (strlen (bufname) + 1);
strcpy (registers[reg].buff, bufname);
registers[reg].spot = alloc_spot ();
say ("Set register %c", (char) (reg + 'A'));
}
jump_register_1(k)
char k;
{
int reg = toupper (k);
reg -= 'A';
if (reg >= 0 && reg < REGCOUNT)
{
if (registers[reg].buff && registers[reg].spot)
{
if (exist (registers[reg].buff))
{
to_buffer (registers[reg].buff);
point = *registers[reg].spot;
say ("");
return;
}
clear_register (®isters[reg]);
}
}
error ("Invalid register: %c", (char) k);
}
command
jump_register() on cx_tab['j']
{
char k;
int reg;
say ("Jump Register: ");
term_position (15, 24);
k = getkey ();
if (k == abort_key)
error ("Aborted");
jump_register_1 (k);
}
/*
* I dont use this but its ok. It gives a buffer list of bookmarks and
* lets you select one. M-x edit-registers.
*
*/
#ifdef WANT_EDIT_REGISTERS
reged_jump()
{
jump_register_1 (key);
}
keytable reged_tab;
when_loading()
{
int i;
for (i = 0; i < NUMKEYS; i++)
{
reged_tab[i] = -1;
}
for (i = 'a'; i <= 'z'; i++)
{
reged_tab[i] = (short) reged_jump;
reged_tab[i + 'A' - 'a'] = (short) case_indirect;
}
}
char reged_mode_name[] = "Registers";
command edit_registers() on cx_tab[CTRL('J')]
{
int i;
int valid = 0;
char *obufname = bufname;
zap ("*Registers*");
bufname = "*Registers*";
mode_keys = reged_tab;
major_mode = reged_mode_name;
make_mode ();
for (i = 0; i < REGCOUNT; i++)
{
if (registers[i].buff && registers[i].spot && exist (registers[i].buff))
{
char line[60];
int opoint;
int start;
int end;
bufname = registers[i].buff;
opoint = point;
start = point = *registers[i].spot;
to_end_line();
end = point;
if (end - start >= sizeof (line))
end = start + sizeof (line) - 1;
grab (start, end, line);
point = opoint;
bufname = "*Registers*";
bprintf ("%c: %s\n", (char) ('A' + i), line);
valid++;
}
}
bufname = obufname;
if (valid)
{
char k;
view_buffer ("*Registers*");
k = getkey ();
k = (char) toupper (k);
if (k >= 'A' && k <= 'Z')
jump_register_1 (k);
}
else
{
say ("No registers set");
ding ();
}
delete_buffer ("*Registers*");
}
#endif