home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol083
/
ice.pli
< prev
next >
Wrap
Text File
|
1984-04-29
|
30KB
|
989 lines
ICE : procedure options(main);
/**************************************************/
/* */
/* IN CONTEXT EDITOR */
/* */
/* Re-implementation of ICE written by */
/* P. G. Main in Ratfor. */
/* */
/* Paul Tilden Aug 1981 */
/* */
/* IMPORTANT: To avoid confusion, the word */
/* LINE is used exclusively to refer to lines */
/* on the VDU screen, and ROW to refer to data */
/* in the working buffer BUF. */
/* */
/**************************************************/
%replace
true by '1'b,
false by '0'b;
%replace
huge by 32000,
linelen by 100, /* screen width */
scrlen by 16, /* screen length */
size by 100; /* nr. of rows in buf */
%replace
escape by 27,
line_feed by 10;
declare
(edt_in, edt_out, sysin, sysprint) file;
declare
nextout fixed, /* next row to be output from buf */
lastin fixed, /* last row input to buf */
posn fixed, /* equal to rmod(crow - lastin) */
crow fixed, /* current row */
delrows fixed, /* nr. of rows to be deleted but
not yet read */
inrow fixed, /* infile row nr. of lastin */
inopen bit(1), /* flag saying an input file is open */
file_end bit(1), /* eof on edt_in */
abort bit(1), /* abort edit */
scr_row fixed, /* screen row */
scr_col fixed; /* screen column */
declare
1 buf(size),
2 buf_row character(linelen) varying;
declare
upper character(26) static initial
('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
lower character(26) static initial
('abcdefghijklmnopqrstuvwxyz'),
digit character(10) static initial ('0123456789'),
blanks character(linelen) varying static;
/********************************************************/
/* */
/* MAIN PROCEDURE */
/* */
/********************************************************/
/* initialization */
open file(sysprint) print pagesize(0)
linesize(255)
title('$CON');
begin;
declare i fixed;
do i = 1 to size;
buf_row(i) = '';
end;
blanks = '';
do i = 1 to linelen;
blanks = blanks !! ' ';
end;
end;
call home_cursor;
call clear_screen;
nextout = 1;
lastin = size;
crow = lastin;
posn = size;
inrow = 0;
delrows = 0;
on undefinedfile(edt_in)
begin;
call diag('new file');
inopen = false;
file_end = true;
goto edtin_cont;
end;
open file(edt_in) input stream env(b(2048)) title('$1.$1');
inopen = true;
file_end = false;
revert undefinedfile(edt_in);
edtin_cont: ;
open file(edt_out) output stream pagesize(0) env(b(2048))
title('$1.%%%');
call get_row(lastin);
call spray(scrlen-2,scrlen-2);
/* edit file */
call edit_file;
/* file cleanup */
close file(edt_in);
close file(edt_out);
/* end */
call diag('done');
/********************************************************/
/* */
/* EDIT FILE */
/* */
/********************************************************/
edit_file: procedure;
declare
done bit(1), /* true = return to main proc. */
(cc1, cc2, cc3, cc4) character(1), /* command chars. */
(cmdbuf, /* complete command buffer */
oprnd, /* command buffer less command */
cmdsave, /* complete command buffer
save for same command */
locsave) /* complete command buffer
save for more command */
character(linelen) varying,
number fixed; /* number following command */
done = false;
do while (^done);
call get_command;
call execute_command;
end;
if ^abort then
begin; /* move remainder of edit file to output file */
declare
row fixed;
row = nextout;
drain_buf:
call put_row(row);
row = rmod(row+1);
if row ^= nextout then goto drain_buf;
do while (^file_end);
call get_row(row);
call put_row(row);
end;
end;
/********************************************************/
/* */
/* GET COMMAND LINE */
/* */
/********************************************************/
get_command: procedure;
call cursor_pos(1,scrlen-1);
call vdu_out('*');
call vdu_in(cmdbuf);
call cursor_pos(1,scrlen-1);
call clear_screen;
if length(cmdbuf) = 1 then
begin;
declare
(ch, zz) character(1);
zz = substr(cmdbuf, 1, 1);
ch = translate(zz, lower, upper);
if ch = 's' then
cmdbuf = cmdsave; /* same command */
if ch = 'm' then
cmdbuf = locsave; /* more command */
end;
/* extract command characters */
cc1 = ' '; cc2 = ' '; cc3 = ' '; cc4 = ' ';
declare
(i, j) fixed;
if length(cmdbuf) = 0 then
i = 1;
else
do;
do i = 1 to length(cmdbuf)
while (verify(translate(substr(cmdbuf,i,1),lower,upper),
lower) = 0);
substr(cmdbuf,i,1) = translate(substr(cmdbuf,i,1),
lower, upper);
end;
do j = 1 to length(cmdbuf) while (j<=4);
if j = 1 then cc1 = substr(cmdbuf,1,1);
if j = 2 then cc2 = substr(cmdbuf,2,1);
if j = 3 then cc3 = substr(cmdbuf,3,1);
if j = 4 then cc4 = substr(cmdbuf,4,1);
end;
end;
if i <= length(cmdbuf) then
if substr(cmdbuf,i,1) = ' ' then
i = i+1; /* remove space following command */
number = 0; /* convert number following command */
if i <= length(cmdbuf) then
if substr(cmdbuf,i,1) = '*' then
number = huge;
else
begin;
declare
ch character(1);
do j = i to length(cmdbuf)
while (verify(substr(cmdbuf,j,1), digit) = 0);
ch = substr(cmdbuf,j,1);
number = number * 10 +
rank(ch) - rank('0');
end;
end;
if number <= 0 then
number = 1;
oprnd = substr(cmdbuf, i);
end get_command;
/*******************************************************/
/*******************************************************/
/* */
/* EXECUTE COMMAND */
/* */
/*******************************************************/
execute_command: procedure;
declare
error bit(1); /* true = line would be trancated */
error = false;
if cc1 = 'a' then call ex_append;
else if cc1 = 'c' then call ex_change;
else if cc1 = 'd' then call ex_delete;
else if cc1 = 'f' then call ex_find;
else if cc1 = 'i' then call ex_insert;
else if cc1 = 'l' then
if cc2 = 'c' then call ex_line_change;
else if cc2 = 'e' then call ex_length;
else call ex_locate;
else if cc1 = 'm' & cc2 = 'o' then call ex_modify;
else if cc1 = 'n' then
if cc2 = 'p' then call ex_number_plus;
else call ex_number;
else if cc1 = 'o' then call ex_overtype;
else if cc1 = 'p' then
if cc2 = 'a' then call ex_paste;
else if cc2 = '-' then call ex_page_down;
else call ex_page_up;
else if cc1 = 'q' then call ex_quit;
else if cc1 = 'r' then call ex_replace;
else if cc1 = 'w' then call ex_write;
else if cc1 = '-' then call ex_line_down;
else if cc1 = ' ' then call ex_line_up;
else call diag('illegal command');
if error then
call diag('line would be too long');
if posn = size & file_end &
length(buf_row(crow)) = 0 & ^done then
if inopen then
call diag('end of file');
else
call diag('no input file open');
if rmod(lastin+1) ^= nextout then /* problem */
do;
call diag('help - lastin error');
done = true;
abort = true;
end;
if rmod(crow-lastin) ^= posn then /* problem */
do;
call diag('help - posn error');
done = true;
abort = true;
end;
/********************************************************/
/* */
/* COMMAND EXECUTORS */
/* */
/********************************************************/
/* A - append operand to current line */
ex_append: procedure;
cmdsave = cmdbuf;
if length(oprnd) + length(buf_row(crow)) > linelen then
error = true;
else
do;
buf_row(crow) = buf_row(crow) !! oprnd;
call spray(scrlen-2, scrlen-2);
end;
end ex_append;
/* C - change 1st. occurence of string in current line */
ex_change: procedure;
cmdsave = cmdbuf;
declare
(key, subst) character (linelen) varying,
(key_len, key_posn, i) fixed;
call split_string(oprnd, key, subst);
i = length(buf_row(crow));
if match(buf_row(crow), 1, i,
key, key_len, key_posn) then
do;
call change(buf_row(crow), key_len, key_posn,
subst, error);
call spray(scrlen-2, scrlen-2);
end;
else
call diag('no match');
end ex_change;
/* D - delete n lines including current line */
ex_delete: procedure;
delrows = number;
call blank;
call compress_up;
call spray(scrlen-2, scrlen-2);
end ex_delete;
/* F - find next line containing operand in column 1 */
ex_find: procedure;
locsave = cmdbuf;
declare
(junk1, junk2) fixed;
find_loop:
if crow = lastin then call swap;
crow = rmod(crow+1);
if ^(match(buf_row(crow), 1, 1, oprnd, junk1, junk2) !
(file_end & crow = lastin)) then goto find_loop;
posn = rmod(crow - lastin);
call spray(1, scrlen-2);
end ex_find;
/* I - insert lines or operand of command */
ex_insert: procedure;
if length(oprnd) = 0 then
do;
call input_lines;
call spray(scrlen-2, scrlen-2);
end;
else
do;
cmdsave = cmdbuf;
call insert_line;
buf_row(crow) = oprnd;
call spray(scrlen-2, scrlen-2);
end;
end ex_insert;
/* LE - length of line */
ex_length: procedure;
call diag(character(length(buf_row(crow))) !! ' chars');
end ex_length;
/* LC - change all occurrences of string in current line */
ex_line_change: procedure;
cmdsave = cmdbuf;
declare
(key, subst) character (linelen) varying,
(junk1, junk2, i) fixed;
call split_string(oprnd, key, subst);
i = length(buf_row(crow));
if match(buf_row(crow), 1, i,
key, junk1, junk2) then
do;
call line_change(buf_row(crow), key, subst, error);
call spray(scrlen-2, scrlen-2);
end;
else
call diag('no match');
end ex_line_change;
/* L - locate next line containing operand */
ex_locate: procedure;
locsave = cmdbuf;
declare
(junk1, junk2, i) fixed;
locate_loop:
if crow = lastin then
call swap;
crow = rmod(crow+1);
i = length(buf_row(crow));
if ^(match(buf_row(crow),1,i,
oprnd, junk1, junk2) !
(file_end & crow = lastin)) then goto locate_loop;
posn = rmod(crow-lastin);
call spray(1,scrlen-2);
end ex_locate;
/* MO - modify line */
ex_modify: procedure;
call diag('not yet implemented');
end ex_modify;
/* N - goto nominated line */
ex_number: procedure;
declare
row fixed;
row = number;
if row < inrow-size+1 then
call diag('already past');
else
if row > inrow+scrlen-2 then
do;
do while(^(inrow = row ! file_end));
call swap;
end;
crow = lastin;
posn = size;
call spray(1,scrlen-2);
end;
else
do;
do while((row > inrow-size+posn) &
^(posn = size & file_end));
call roll_up;
end;
do while(row < inrow-size+posn);
call roll_down;
end;
end;
end ex_number;
/* NP - goto n lines past current line */
ex_number_plus: procedure;
locsave = cmdbuf;
declare
row fixed;
row = number+inrow-size+posn;
if row > inrow+scrlen-2 then
do;
do while(^(inrow = row ! file_end));
call swap;
end;
crow = lastin;
posn = size;
call spray(1,scrlen-2);
end;
else
do;
do while((row > inrow-size+posn) &
^(posn = size & file_end));
call roll_up;
end;
end;
end ex_number_plus;
/* O - overtype -- delete n lines and input from vdu */
ex_overtype: procedure;
delrows = number;
call blank;
call input_lines;
call spray(scrlen-2, scrlen-2);
end ex_overtype;
/* P - roll up one or more pages */
ex_page_up: procedure;
declare
i fixed;
do i = 1 to (scrlen-3)*number while(^(posn = size &
file_end));
call roll_up;
end;
end ex_page_up;
/* P- -- roll down one page */
ex_page_down: procedure;
declare
i fixed;
do i = 1 to (scrlen-3);
call roll_down;
end;
end ex_page_down;
/* PA - paste -- change all occurences of string until eof */
ex_paste: procedure;
cmdsave = cmdbuf;
declare
(key, subst) character (linelen) varying,
(junk1, junk2, i) fixed;
call split_string(oprnd, key, subst);
do while(^(posn = size & file_end) & ^error);
i = length(buf_row(crow));
if match(buf_row(crow), 1, i,
key, junk1, junk2) then
do;
call line_change(buf_row(crow), key, subst, error);
call scroll_up;
call spray(scrlen-2, scrlen-2);
end;
if ^error then
do;
if crow = lastin then
call swap;
crow = rmod(crow+1);
posn = rmod(crow-lastin);
end;
end;
end ex_paste;
/* Q - quit -- no change to file */
ex_quit: procedure;
abort = true;
done = true;
end ex_quit;
/* R - replace current line with operand */
ex_replace: procedure;
cmdsave = cmdbuf;
buf_row(crow) = oprnd;
call compress_up;
call spray(scrlen-2, scrlen-2);
end ex_replace;
/* W - write file -- end edit */
ex_write: procedure;
done = true;
end ex_write;
/* - -- roll down 1 line */
ex_line_down: procedure;
call roll_down;
end ex_line_down;
/* return - roll up one line */
ex_line_up: procedure;
call roll_up;
end ex_line_up;
end execute_command;
/********************************************************/
end edit_file;
/********************************************************/
/********************************************************/
/* */
/* GENERAL SUPPORT PROCEDURES */
/* */
/********************************************************/
/* blank - clear delrows in buf from crow and spray */
blank: procedure;
declare
row fixed;
row = crow;
blank_loop:
buf_row(row) = '';
delrows = delrows-1;
row = rmod(row+1);
if ^(delrows <= 0 ! row = nextout) then
goto blank_loop;
call spray(scrlen-2,scrlen-2);
end blank;
/* change - replace len chars. starting at
string(place) by subst */
change: procedure(string, len, place, subst, error);
declare
(string, subst) character(linelen) varying,
(len, place) fixed,
error bit(1);
if length(string)+length(subst)-len > linelen then
error = true;
else
do;
error = false;
string = substr(string,1,place-1) !!
subst !!
substr(string,place+len);
end;
end change;
/* compress_up - compress buf upwards and re-fill
from below */
compress_up: procedure;
declare
(lf, lt) fixed;
lf = crow;
do while (lf ^= nextout & length(buf_row(lf)) = 0);
lf = rmod(lf+1);
end;
lt = crow;
do while (lf ^= nextout);
buf_row(lt) = buf_row(lf);
lf = rmod(lf+1);
lt = rmod(lt+1);
end;
do while (lt ^= nextout);
call get_row(lt);
lt = rmod(lt+1);
end;
end compress_up;
/* diag - display diagnostic message on bottom
line of screen */
diag: procedure(string);
declare
string character(linelen) varying;
call cursor_pos(5,scrlen);
call clear_line;
call vdu_out(string);
end diag;
/* get_row - get row from input file
into buf_row(row) */
get_row: procedure(row);
declare
row,i fixed;
on endfile(edt_in)
begin;
file_end = true;
buf_row(row) = '';
goto get_row_exit;
end;
if file_end then
buf_row(row) = '';
else
do;
do while (delrows > 0);
inrow = inrow+1;
get file(edt_in) edit(buf_row(row))(a);
delrows = delrows-1;
end;
inrow = inrow+1;
get file(edt_in) edit(buf_row(row))(a);
end;
revert endfile(edt_in);
get_row_exit: ;
end get_row;
/* input_lines - input keyboard data to crow */
input_lines: procedure;
input_loop:
call insert_line;
call cursor_pos(1,scrlen-2);
call clear_line;
call vdu_in(buf_row(crow));
if length(buf_row(crow)) ^= 0 then
goto input_loop;
call compress_up;
end input_lines;
/* insert_line - open up space for input */
insert_line: procedure;
declare
(lf, lt) fixed;
if length(buf_row(crow)) = 0 then
call cursor_pos(1,scrlen-2);
else
if posn < size & length(buf_row(rmod(crow+1))) = 0 then
call roll_up;
else
do;
call put_row(nextout);
lt = lastin;
lf = nextout;
do while (lf ^= crow);
lt = lf;
lf = rmod(lf+1);
buf_row(lt) = buf_row(lf);
end;
buf_row(crow) = '';
if posn < scrlen-1 then
do;
call cursor_pos(1,scrlen-1-posn);
call clear_line;
end;
call scroll_up;
end;
end insert_line;
/* line_change - change all occurences string
in line */
line_change: procedure(string, key, subst, error);
declare
(string, key, subst) character(linelen) varying,
(key_len, key_posn, place, str_len) fixed,
error bit(1);
place = 1;
error = false;
str_len = length(string);
do while (match(string, place, str_len, key,
key_len, key_posn) & ^error);
call change(string, key_len, key_posn, subst, error);
place = key_posn + length(subst);
if length(key) = 0 then
place = place + 1;
str_len = length(string);
end;
end line_change;
/* match - searches string from string(srch_start)
to string(srch_end) for a match to key.
if found, match starts at string(key_posn)
and is key_len long.
key string may include ellipsis ('...').*/
match: procedure(string, srch_start, srch_end, key, key_len,
key_posn) returns (bit(1));
declare
(string, key, zz) character(linelen) varying,
(srch_start, srch_end, key_len, key_posn, jj) fixed,
rtn bit(1);
if srch_start > srch_end then
do;
rtn = false;
return(rtn);
end;
if length(key) = 0 then
do;
key_len = 0;
key_posn = srch_start;
rtn = true;
end;
else
if index(key,'...') = 0 then
do; /* no ellipsis in key */
zz = substr(string, srch_start);
key_posn = index(zz, key)
+ srch_start-1;
if key_posn >= srch_start &
key_posn <= srch_end then
do;
key_len = length(key);
rtn = true;
end;
else
rtn = false;
end;
else
begin; /* ellipsis in key */
declare
(key_front, key_back) character (linelen)
varying,
i fixed;
i = index(key,'...');
key_front = substr(key, 1, i-1);
key_back = substr(key, i+3);
if length(key_front) = 0 then
if length(key_back) = 0 then
do;
key_posn = srch_start;
zz = substr(string, srch_start);
key_len = length(zz);
rtn = true;
end;
else
do;
key_posn = srch_start;
zz = substr(string, srch_start);
i = index(zz, key_back);
if i > 0 then
do;
key_len = i-1+length(key_back);
rtn = true;
end;
else
rtn = false;
end;
else
do;
zz = substr(string, srch_start);
key_posn = index(zz,
key_front) + srch_start-1;
if key_posn >= srch_start &
key_posn <= srch_end then
if length(key_back) = 0 then
do;
zz = substr(string, key_posn);
key_len = length(zz);
rtn = true;
end;
else
do;
jj = length(key_front);
zz = substr(string, key_posn + jj);
i = index(zz, key_back);
if i > 0 then
do;
key_len = length(key_front) +
length(key_back) +
i - 1;
rtn = true;
end;
else
rtn = false;
end;
else
rtn = false;
end;
end;
return(rtn);
end match;
/* put_row - write row to edt_out */
put_row: procedure(row);
declare
row fixed;
if length(buf_row(row)) ^= 0 then
do;
put file(edt_out) edit(buf_row(row))(a);
put file(edt_out) skip;
end;
end put_row;
/* roll_down - roll down screen */
roll_down: procedure;
if posn > 1 then
do;
posn = posn - 1;
crow = rmod(crow-1);
call scroll_down;
if posn > scrlen-2 then
call spray(1,1);
call cursor_pos(1,scrlen-1);
call clear_screen;
end;
end roll_down;
/* roll_up - roll screen up */
roll_up: procedure;
if posn = size then
call swap;
if posn < size then
do;
call scroll_up;
posn = posn + 1;
crow = rmod(crow+1);
end;
call spray(scrlen-2,scrlen-2);
end roll_up;
/* rmod - modulus function to force row address
into range 1 to size */
rmod: procedure(arg) returns (fixed);
declare
(arg, rtn) fixed;
if arg > size then
rtn = arg - size;
else if arg < 1 then
rtn = arg + size;
else
rtn = arg;
return(rtn);
end rmod;
/* split_string - take string in form
/..key../..subst../ and split
into key and substitute strings */
split_string: procedure(string, key, subst);
declare
(string, key, subst) character(linelen) varying,
(i,j) fixed;
if length(string) = 0 then
do;
key = '';
subst = '';
end;
else
do;
i = index(substr(string,2), substr(string,1,1));
if i = 0 then
do;
key = substr(string,2);
subst = '';
end;
else
do;
key = substr(string,2,i-1);
j = i + 2;
i = index(substr(string,j), substr(string,1,1));
if i = 0 then
subst = substr(string,j);
else
subst = substr(string,j,i-1);
end;
end;
end split_string;
/* spray - display screen lines sb to se */
spray: procedure(sb,se);
declare
(sb, se, line, row) fixed;
do line = sb to se;
call cursor_pos(1,line);
call clear_line();
row = rmod(crow - scrlen+2 + line);
call vdu_out(buf_row(row));
end;
end spray;
/* swap - output from nextout, input to lastin,
adjust pointers */
swap: procedure;
if length(buf_row(lastin)) ^= 0 then
do;
call put_row(nextout);
lastin = nextout;
nextout = rmod(nextout+1);
posn = posn -1;
end;
call get_row(lastin);
end swap;
/*******************************************************/
/*******************************************************/
/* */
/* VDU SUPPORT ROUTINES FOR ICE */
/* */
/*******************************************************/
/* clear line from cursor */
clear_line : procedure;
call vdu_out('^O');
end clear_line;
/* clear screen from cursor */
clear_screen: procedure;
call vdu_out('^K');
end clear_screen;
/* cursor position */
cursor_pos: procedure(col,row);
declare
str character(linelen) varying,
i fixed,
(col, row) fixed;
scr_row = row;
scr_col = col;
if row = 1 then
do;
call vdu_out('^N'); /* home cursor */
put skip;
call vdu_out('^N'); /* cursor home */
end;
else
do;
call vdu_out(ascii(escape)!!ascii(2)!!ascii(row+30));
put skip;
end;
if col ^= 1 then
do;
str = '';
i = 1;
do while (i<col);
str = str !! '^S'; /* cursor right */
i = i+1;
end;
call vdu_out(str);
end;
end cursor_pos;
/* home cursor */
home_cursor: procedure;
call cursor_pos(1,1);
end home_cursor;
/* scroll down */
scroll_down: procedure;
call vdu_out('^D');
end scroll_down;
/* scroll up */
scroll_up: procedure;
call vdu_out('^B');
end scroll_up;
/* input from vdu */
vdu_in: procedure(data);
declare
data character(linelen) varying;
get edit(data) (a);
end vdu_in;
/* output to vdu */
vdu_out: procedure(data);
declare
data character(linelen) varying;
put edit(data) (a);
end vdu_out;
/*****************************************************/
end ice;