home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8810.arc
/
C_COLU.ARC
/
EDITOR.C
next >
Wrap
Text File
|
1988-08-30
|
22KB
|
746 lines
/* ----------------------- editor.c ---------------------- */
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <mem.h>
#include <ctype.h>
#include <alloc.h>
#include "window.h"
#include "editor.h"
#define NEXTTAB (TAB-(ev.curr_x%TAB))
#define LASTTAB ((ev.wwd/TAB)*TAB)
#define PREVTAB (((ev.curr_x-1)%TAB)+1)
struct edit_env ev; /* the editor environment */
int do_display_text = TRUE; /* turns display on/off */
extern struct wn wkw; /* the current window */
int forcechar; /* externally force a kb char */
void (*status_line)(void); /* called once each keystroke */
void (*editfunc)(int); /* for unknown keystrokes */
/* ---------- local function prototypes ----------- */
static int lastword(void);
static void last_char(void);
static void test_para(int);
static int trailing_spaces(int);
static int first_wordlen(int);
static int last_wordlen(void);
static void paraform(int);
static int blankline(int);
static void delete_word(void);
static void delete_line(void);
static void delete_block(void);
static void mvblock(int);
static void carrtn(int);
static void backspace(void);
static void fore_word(void);
static int spaceup(void);
static void back_word(void);
static int spacedn(void);
static void forward(void);
static int downward(void);
static void upward(void);
static void display_text(int);
static void disp_line(int y);
static void findlast(void);
/* ----- Process text entry for a window. ---- */
int text_editor(char *bf, int editlines, int editwidth)
{
int depart, i, c;
int svx, svlw, tx, tabctr, wraplen;
current_window();
depart = FALSE;
tabctr = 0;
if (ev.envinuse == FALSE) {
ev.wdo = &wkw;
ev.wwd = editwidth;
ev.wsz = ev.wwd * ev.wdo->ht;
ev.topptr = ev.bfptr = bf;
ev.nolines = editlines;
ev.endptr = bf + ev.wwd * ev.nolines;
ev.edinsert = INSERTING;
ev.reforming = REFORMING;
ev.envinuse = TRUE;
}
set_cursor_type(ev.edinsert ? 0x0106 : 0x0607);
display_text(0);
findlast();
/* ------- read text/command from the keyboard ------ */
while (depart == FALSE) {
ev.nowptr = curr(ev.curr_x, ev.curr_y);
if (status_line)
(*status_line)(); /* external status line func */
gotoxy(ev.curr_x + 2, ev.curr_y + 2);
if (tabctr) { /* expand typed tabs */
--tabctr;
c = ' ';
}
else
c = forcechar ? forcechar : getkey();
forcechar = 0;
switch (c) {
/* ------------ fixed editor commands ----------------- */
case '\r':
carrtn(ev.edinsert);
break;
case UP:
upward();
break;
case DN:
downward();
break;
case FWD:
forward();
break;
case '\b':
case BS:
if (!(ev.curr_x || ev.curr_y))
break;
backspace();
if (ev.curr_x == ev.wwd - 1)
last_char();
if (c == BS)
break;
ev.nowptr = curr(ev.curr_x, ev.curr_y);
case DEL:
movmem(ev.nowptr+1,ev.nowptr,
ev.wwd-1-ev.curr_x);
*(ev.nowptr+ev.wwd-1-ev.curr_x) = ' ';
disp_line(ev.curr_y);
test_para(ev.curr_x+1);
ev.text_changed = TRUE;
break;
case PGUP:
ev.curr_y = 0;
do_display_text = FALSE;
for (i = 0; i < ev.wdo->ht; i++)
upward();
do_display_text = TRUE;
display_text(0);
break;
case PGDN:
ev.curr_y = ev.wdo->ht-1;
do_display_text = FALSE;
for (i = 0; i < ev.wdo->ht; i++)
downward();
do_display_text = TRUE;
display_text(0);
ev.curr_y = 0;
break;
case '\t':
if (ev.curr_x + NEXTTAB < ev.wwd) {
if (ev.edinsert)
tabctr = NEXTTAB;
else
ev.curr_x += NEXTTAB;
}
else
carrtn(ev.edinsert);
break;
/* -------- configured editor commands --------------- */
case REPAINT:
display_text(ev.curr_y);
break;
case BACKTAB:
if (ev.curr_x < TAB) {
upward();
ev.curr_x = LASTTAB;
}
else
ev.curr_x -= PREVTAB;
break;
case NEXTWORD:
fore_word();
break;
case PREVWORD:
back_word();
break;
case BOTSCREEN:
ev.curr_y = ev.wdo->ht - 1;
break;
case TOPSCREEN:
ev.curr_y = 0;
break;
case BEGIN_BUFFER:
ev.curr_x = ev.curr_y = 0;
ev.bfptr = ev.topptr;
display_text(0);
break;
case END_BUFFER:
do_display_text = FALSE;
ev.curr_x = 0;
while (downward())
if (curr(0,ev.curr_y) >= ev.lstptr)
break;
do_display_text = TRUE;
display_text(0);
break;
case BEGIN_LINE:
ev.curr_x = 0;
break;
case END_LINE:
last_char();
break;
case DELETE_LINE:
delete_line();
ev.text_changed = TRUE;
break;
case DELETE_WORD:
delete_word();
ev.text_changed = TRUE;
test_para(ev.curr_x);
break;
case INSERT:
ev.edinsert ^= TRUE;
set_cursor_type(ev.edinsert ? 0x106 : 0x607);
break;
case ESC:
case QUIT:
depart = TRUE;
break;
case PARAGRAPH:
paraform(0);
ev.text_changed = TRUE;
break;
case BEGIN_BLOCK:
ev.blkbeg = lineno(ev.curr_y) + 1;
if (ev.blkbeg > ev.blkend)
ev.blkend = ev.blkbeg;
display_text(0);
break;
case END_BLOCK:
ev.blkend = lineno(ev.curr_y) + 1;
if (ev.blkend < ev.blkbeg)
ev.blkbeg = ev.blkend;
display_text(0);
break;
case MOVE_BLOCK:
mvblock(TRUE);
ev.text_changed = TRUE;
break;
case COPY_BLOCK:
mvblock(FALSE);
ev.text_changed = TRUE;
break;
case DELETE_BLOCK:
delete_block();
ev.text_changed = TRUE;
display_text(0);
break;
case HIDE_BLOCK:
ev.blkbeg = ev.blkend = 0;
display_text(0);
break;
default:
if (!isprint(c)) {
/* ---- not recognized by editor --- */
if (editfunc) {
/* --- extended commands --- */
(*editfunc)(c);
findlast();
display_text(0);
}
else
putch(BELL);
break;
}
/* --- displayable char: put in buffer --- */
if (ev.nowptr == ev.endptr-1 ||
(lineno(ev.curr_y)+1 >=
ev.nolines && ev.edinsert &&
*curr(ev.wwd-2, ev.curr_y) != ' ')) {
error_message("End of buffer...");
break;
}
if (ev.edinsert) /* --- if insert mode --- */
movmem(ev.nowptr,ev.nowptr+1,
ev.wwd-1-ev.curr_x);
if (ev.nowptr < ev.endptr) {
if (ev.nowptr >= ev.lstptr)
ev.lstptr = ev.nowptr + 1;
*ev.nowptr = (char) c; /* put in buff */
disp_line(ev.curr_y);
}
if (ev.nowptr == curr(ev.wwd-1, ev.curr_y) &&
c == ' ' && ev.edinsert) {
if (strncmp(curr(0,ev.curr_y+1),
" ",TAB) == 0) {
carrtn(TRUE);
break;
}
}
else if (ev.endptr &&
*curr(ev.wwd-1, ev.curr_y) != ' ') {
/* ------- word wrap is needed ------- */
ev.nowptr = curr(ev.wwd-1, ev.curr_y);
svx = ev.curr_x; /* save x vector */
svlw = lastword(); /* last word on line?*/
ev.curr_x = ev.wwd-1;
if (*(ev.nowptr-1) != ' ')
back_word();
tx = ev.curr_x;
wraplen = last_wordlen();
if (trailing_spaces(ev.curr_y+1) <
wraplen+2)
carrtn(TRUE);
else if (strncmp(curr(0,ev.curr_y+1),
" ",TAB) == 0)
carrtn(TRUE);
else {
ev.nowptr = curr(0, ev.curr_y+1);
movmem(ev.nowptr,ev.nowptr+wraplen+1,
ev.wwd-wraplen-1);
setmem(ev.nowptr, wraplen+1, ' ');
movmem(curr(ev.curr_x,ev.curr_y),
ev.nowptr,wraplen);
setmem(curr(ev.curr_x,ev.curr_y),
wraplen, ' ');
disp_line(ev.curr_y);
downward();
disp_line(ev.curr_y);
}
if (svlw)
ev.curr_x = svx-tx;
else
ev.curr_x = svx, --ev.curr_y;
}
forward();
ev.text_changed = TRUE;
break;
}
}
return c;
}
/* ----- see if a word is the last word on the line ------ */
static int lastword()
{
int x = ev.curr_x;
char *bf = curr(ev.curr_x, ev.curr_y);
while (x++ < ev.wwd-1)
if (*bf++ == ' ')
return 0;
return 1;
}
/* --- go to last displayable character on the line --- */
static void last_char()
{
char *bf = curr(0, ev.curr_y);
ev.curr_x = ev.wwd-1;
while (ev.curr_x && *(bf + ev.curr_x) == ' ')
--ev.curr_x;
if (ev.curr_x && ev.curr_x < ev.wwd - 1)
ev.curr_x++;
}
/* ----- test to see if paragraph should be reformed ----- */
static void test_para(int x)
{
int ts, fw;
int svb, sve;
if (ev.reforming && ev.curr_y < ev.nolines) {
ts = trailing_spaces(ev.curr_y);
fw = first_wordlen(ev.curr_y+1);
if (fw && ts > fw) {
svb = ev.blkbeg, sve = ev.blkend;
ev.blkbeg = ev.blkend = 0;
paraform(x);
ev.blkbeg = svb, ev.blkend = sve;
if (svb)
display_text(0);
}
}
}
/* ---- count the trailing spaces on a line ----- */
static int trailing_spaces(int y)
{
int x = ev.wwd-1, ct = 0;
char *bf = curr(0, y);
while (x >= 0) {
if (*(bf + x) != ' ')
break;
--x;
ct++;
}
return ct;
}
/* ----- count the length of the first word on a line --- */
static int first_wordlen(int y)
{
int ct = 0, x = 0;
char *bf = curr(0, y);
while (x < ev.wwd-1 && *bf == ' ')
x++, bf++;
while (x < ev.wwd-1 && *bf != ' ')
ct++, x++, bf++;
return ct;
}
/* ----- count the length of the last word on a line --- */
static int last_wordlen()
{
int ct = 0, x = ev.wwd-1;
char *bf = curr(x, ev.curr_y);
while (x && *bf == ' ')
--x, --bf;
while (x && *bf != ' ')
--x, --bf, ct++;
return ct;
}
/* ------------ form a paragraph -------------- */
static void paraform(int x)
{
char *cp1, *cp2, *cpend, *svcp;
int x1, y1, firstline = TRUE;
int y = ev.curr_y;
if (!ev.blkbeg) { /* ---- if block not marked ---- */
if (blankline(lineno(y)+1))
return; /* next line is blank, no reform */
ev.blkbeg=ev.blkend=lineno(y)+1; /* pseudoblock */
ev.blkend++;
y1 = y+1;
while (ev.blkend < ev.nolines) { /* look for para */
if (strncmp(curr(0, y1++), " ", TAB) == 0)
break;
ev.blkend++;
}
--ev.blkend;
}
if (lineno(y) != ev.blkbeg-1)
x = 0;
x1 = x;
cp1 = cp2 = ev.topptr + (ev.blkbeg - 1) * ev.wwd + x;
cpend = ev.topptr + ev.blkend * ev.wwd;
while (cp2 < cpend) {
while (*cp2 == ' ' && cp2 < cpend) {
if (firstline)
*cp1++ = *cp2, x1++;
cp2++;
}
firstline = FALSE;
if (cp2 == cpend)
break;
/* ---- at a word ---- */
while (*cp2 != ' ' && cp2 < cpend) {
if (x1 >= ev.wwd-1) {
/* wrap the word */
svcp = cp1 + (ev.wwd - x1);
while (*--cp1 != ' ')
*cp1 = ' ', --cp2;
x1 = 0;
ev.blkbeg++;
cp1 = svcp;
if (y < ev.wdo->ht)
disp_line(y++);
}
*cp1++ = *cp2++;
x1++;
}
if (cp2 < cpend)
*cp1++ = ' ', x1++;
}
while (cp1 < cpend)
*cp1++ = ' ';
ev.blkbeg++;
if (y < ev.wdo->ht)
disp_line(y++);
firstline = ev.blkbeg;
if (ev.blkbeg <= ev.blkend) {
delete_block();
display_text(y);
}
ev.blkbeg = ev.blkend = 0;
if (firstline)
display_text(0);
}
/* ------- test for a blank line ---------- */
static int blankline(int line)
{
char *cp = ev.topptr + (line-1) * ev.wwd;
int x = ev.wwd;
while (x--)
if (*cp++ != ' ')
break;
return !(x > -1);
}
/* ------------- delete a word -------------- */
static void delete_word()
{
int wct = 0;
char *cp1, *cp2;
cp1 = cp2 = curr(ev.curr_x, ev.curr_y);
if (*cp2 == ' ')
while (*cp2 == ' ' && ev.curr_x + wct < ev.wwd)
wct++, cp2++;
else {
while (*cp2 != ' ' && ev.curr_x + wct < ev.wwd)
wct++, cp2++;
while (*cp2 == ' ' && ev.curr_x + wct < ev.wwd)
wct++, cp2++;
}
movmem(cp2, cp1, ev.wwd - ev.curr_x - wct);
setmem(cp1 + ev.wwd - ev.curr_x - wct, wct, ' ');
disp_line(ev.curr_y);
}
/* ----------- delete a line --------------- */
static void delete_line()
{
char *cp1, *cp2;
int len;
cp1 = ev.bfptr + ev.curr_y * ev.wwd;
cp2 = cp1 + ev.wwd;
if (cp1 < ev.lstptr) {
len = ev.endptr - cp2;
movmem(cp2, cp1, len);
ev.lstptr -= ev.wwd;
setmem(ev.endptr - ev.wwd, ev.wwd, ' ');
display_text(ev.curr_y);
}
}
/* ----------- delete a block ------------- */
static void delete_block()
{
char *cp1, *cp2;
int len;
if (!ev.blkbeg || !ev.blkend) {
error_message("No block marked ...");
return;
}
cp1 = ev.topptr + ev.blkend * ev.wwd;
cp2 = ev.topptr + (ev.blkbeg - 1) * ev.wwd;
len = ev.endptr - cp1;
movmem(cp1, cp2, len);
setmem(cp2 + len, ev.endptr - (cp2 + len), ' ');
ev.blkbeg = ev.blkend = 0;
ev.lstptr -= cp1 - cp2;
}
/* ------- move and copy text blocks -------- */
static void mvblock(int moving)
{
char *cp1, *cp2, *hd;
unsigned len;
if (!ev.blkbeg || !ev.blkend) {
error_message("No block marked ...");
return;
}
if (lineno(ev.curr_y) >= ev.blkbeg-1
&& lineno(ev.curr_y) <= ev.blkend-1) {
error_message("Don't move/copy a block into itself");
return;
}
len = (ev.blkend - ev.blkbeg + 1) * ev.wwd;
if ((hd = malloc(len)) == NULL)
return;
cp1 = ev.topptr + (ev.blkbeg-1) * ev.wwd;
movmem(cp1, hd, len);
cp2 = ev.topptr + lineno(ev.curr_y) * ev.wwd;
if (moving) {
if (lineno(ev.curr_y) > ev.blkbeg-1)
cp2 -= len;
delete_block();
}
if (cp2+len <= ev.endptr) {
movmem(cp2, cp2 + len, ev.endptr - cp2 - len);
movmem(hd, cp2, len);
ev.lstptr += cp1 - cp2;
}
else
error_message("Not enough room...");
free(hd);
ev.blkbeg = ev.blkend = 0;
display_text(0);
}
/* ------- find the last character in the buffer -------- */
static void findlast()
{
char *lp = ev.endptr - 1, *tp = ev.topptr;
while (lp > tp && *lp == ' ')
--lp;
if (*lp != ' ')
lp++;
ev.lstptr = lp;
}
/* -------- carriage return -------- */
static void carrtn(int insert)
{
int insct;
char *cp = curr(ev.curr_x, ev.curr_y);
char *nl = cp+((cp-ev.topptr)%ev.wwd);
int ctl = 2;
if (lineno(ev.curr_y) + 2 < ev.nolines)
if (insert && nl < ev.endptr) {
insct = ev.wwd - ev.curr_x;
while (ctl--) {
if (ev.endptr > cp + insct) {
movmem(cp, cp+insct, ev.endptr-insct-cp);
setmem(cp, insct, ' ');
}
else if (ctl == 1)
setmem(cp, ev.endptr - cp, ' ');
cp += insct * 2;
insct = ev.curr_x;
}
}
ev.curr_x = 0;
downward();
if (insert) {
ev.text_changed = TRUE;
test_para(0);
display_text(ev.curr_y-1);
if (lineno(ev.curr_y) + 2 < ev.nolines)
if ((ev.lstptr + ev.wwd) <= ev.endptr)
if (ev.lstptr > curr(ev.curr_x, ev.curr_y))
ev.lstptr += ev.wwd;
}
}
/* ------- move the buffer offset back one position ------ */
static void backspace()
{
if (ev.curr_x == 0) {
if (ev.curr_y)
ev.curr_x = ev.wwd - 1;
upward();
}
else
--ev.curr_x;
}
/* -------- move the buffer offset forward one word ------ */
static void fore_word()
{
while (*ev.nowptr != ' ') {
if (spaceup() == 0)
return;
if (ev.curr_x == 0)
break;
}
while (*ev.nowptr == ' ')
if (spaceup() == 0)
return;
}
static int spaceup()
{
if (ev.nowptr >= ev.lstptr)
return 0;
ev.nowptr++;
forward();
return 1;
}
/* ------- move the buffer offset backward one word ------ */
static void back_word()
{
spacedn();
while (*ev.nowptr == ' ')
if (spacedn() == 0)
return;
while (*ev.nowptr != ' ') {
if (ev.curr_x == 0)
return;
if (spacedn() == 0)
return;
}
spaceup();
}
static int spacedn()
{
if (ev.nowptr == ev.topptr)
return 0;
--ev.nowptr;
backspace();
return 1;
}
/* ----- move the buffer offset forward one position ----- */
static void forward()
{
int ww = ev.wwd;
if (++ev.curr_x == ww) {
downward();
ev.curr_x = 0;
}
}
/* ------- move the buffer offset down one position ------ */
static int downward()
{
if (ev.curr_y < ev.wdo->ht - 1) {
ev.curr_y++;
return 1;
}
else if ((ev.bfptr + ev.wsz) < ev.endptr) {
ev.bfptr += ev.wwd;
if (do_display_text) {
scroll_window(1);
disp_line(ev.wdo->ht-1);
}
return 1;
}
return 0;
}
/* -------- move the buffer offset up one position ------ */
static void upward()
{
if (ev.curr_y)
--ev.curr_y;
else if ((ev.topptr + ev.wwd) <= ev.bfptr) {
ev.bfptr -= ev.wwd;
if (do_display_text) {
scroll_window(0);
disp_line(0);
}
}
}
/* ---- display lines in a window ------ */
static void display_text(y)
{
while (y < ev.wdo->ht)
disp_line(y++);
}
/* ---------- Display a line -------- */
static void disp_line(int y)
{
char ln[81];
if (lineno(y) >= ev.blkbeg-1)
if (lineno(y) <= ev.blkend-1) {
textcolor(BLOCKFG);
textbackground(BLOCKBG);
}
movmem(ev.bfptr+y*ev.wwd, ln, ev.wwd);
ln[ev.wwd] = '\0';
writeline(2, y+2, ln);
textcolor(TEXTFG);
textbackground(TEXTBG);
}