home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
wp_dtp
/
xdme1820.lha
/
XDME
/
edit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-06
|
23KB
|
1,229 lines
/******************************************************************************
MODUL
edit.c
DESCRIPTION
Everything for editing like DEL, BS, INDENT, DELINE, INSLINE, ...
NOTES
BUGS
TODO
EXAMPLES
SEE ALSO
INDEX
HISTORY
14. Nov 1992 ada created
******************************************************************************/
/**************************************
Includes
**************************************/
#include "defs.h"
#include "clipboard.h"
#define MYDEBUG 0
#include <debug.h>
/**************************************
Globale Variable
**************************************/
/**************************************
Interne Defines & Strukturen
**************************************/
/**************************************
Interne Variable
**************************************/
/**************************************
Interne Prototypes
**************************************/
Prototype void do_bs (void);
Prototype void do_del (void);
Prototype void do_remeol (void);
Prototype void do_split (void);
Prototype int do_join (void);
Prototype void do_reformat (int);
Prototype void do_insertmode (void);
Prototype void do_insline (void);
Prototype void do_deline (void);
Prototype void do_tlate (void);
Prototype void do_justify (void);
Prototype void do_unjustify (void);
Prototype void do_indent (void);
Prototype void do_inslines (void);
Prototype void do_delete (void);
Prototype void do_delines (void);
Prototype void do_undeline (void);
Prototype void do_space (void);
Prototype void do_clipins (void);
Prototype void do_return (void);
void do_bs (void)
{
ED * ep = Ep;
RP * rp = ep->win->RPort;
short i,
col = ep->column;
Column right;
Bool is_bs = (av[0][0] == 'b');
if ((Current[col] && !is_bs) || (col && is_bs))
{
if (is_bs)
{
movmem (Current + col, Current + col - 1, Clen - col + 1);
col --;
ep->column --;
} else
movmem (Current + col + 1, Current + col, Clen - col);
Clen --;
i = ep->line;
right = ep->topcolumn + Columns;
if (!Nsu) { /* PATCH_NULL [09-Dec-92] : line added */
if (col < ep->topcolumn)
{
text_adjust (FALSE);
} else
{
if (is_inblock (i, right))
{
SetAPen (rp, BLOCK_FPEN);
SetBPen (rp, BLOCK_BPEN);
} else
{
SetAPen (rp, TEXT_FPEN);
SetBPen (rp, TEXT_BPEN);
}
SetWrMsk (rp, BLOCK_MASK);
i -= ep->topline;
ScrollRaster(rp, Xsize, 0,
COL(col - ep->topcolumn),
ROW(i),
Xpixs,
ROW(i + 1) - 1
);
if (Clen >= right)
{
right --;
Move (rp, COLT(right - ep->topcolumn), ROWT(i));
Text (rp, Current + right, 1);
}
}
} /* if !Nsu */ /* PATCH_NULL [09-Dec-92] : line added */
if (!globalflags.Comlinemode && ep->config.wordwrap)
do_reformat(0);
} else
{
globalflags.Abortcommand = 1;
}
} /* do_bs */
void do_remeol (void)
{
Current[Clen = Ep->column] = 0;
text_sync ();
text_redisplaycurrline ();
} /* do_remeol */
void do_split (void) /* split line in two at cursor pos */
{
ubyte buf[MAXLINELEN];
ED * ep = Ep;
RP * rp = ep->win->RPort;
char onLastLine;
strcpy ((char *)buf, (char *)Current+ep->column);
Current[Clen = ep->column] = '\0';
text_sync ();
SetAPen (rp, TEXT_BPEN);
SetWrMsk (rp, -1);
if (!Nsu)
RectFill (rp, COL(0), ROW(ep->line-ep->topline),
Xpixs, ROW(ep->line-ep->topline+1)-1);
SetAPen (rp, TEXT_FPEN);
text_displayseg (ep->line - ep->topline, 1);
onLastLine = (ep->line == ep->lines-1);
do_downadd ();
if (!onLastLine)
do_insline ();
strcpy ((char *)Current, (char *)buf);
Clen = strlen ((char *)Current);
text_sync ();
text_displayseg (ep->line - ep->topline, 1);
do_up ();
} /* do_split */
int do_join (void)
{
int i = Clen, j;
ED * ep = Ep;
/* Check if there is a line below and the length of both lines */
if (ep->line + 1 < ep->lines &&
LINELEN(ep,ep->line+1)+i <= MAXLINELEN-2)
{
/* Add a space */
if (i && Current[i-1] != ' ')
Current[i++] = ' ';
/* Copy the line */
strcpy((char *)Current+i, GETTEXT(ep,ep->line+1));
/* Find first nonspace */
for (j = i; Current[j] == ' '; ++j);
/* Find last space */
for (; i >= 0 && Current[i] == ' '; --i);
/* Too many spaces ? */
if (j > i+2)
movmem (Current+j, Current+i+2, strlen((char *)Current+j)+1);
/* new length */
Clen = strlen ((char *)Current);
/* redisplay */
text_sync ();
text_displayseg (ep->line - ep->topline, 1);
i = text_lineno ();
do_down ();
do_deline ();
if (i != text_lineno ())
do_up ();
return(1);
}
return(0);
} /* do_join */
/*
* n == -1 : force reformat entire paragraph
* n == 0 : only until line equalizes (from text_write())
*
* What is a paragraph? A paragraph ends whenever the left justification
* gets larger, or on a blank line.
*/
void do_reformat (int n)
{
char * str;
ED * ep = Ep;
RP * rp = ep->win->RPort;
int nlok; /* Next Line ok ? */
int lnsc; /* LastNS of Current */
int fnst; /* FirstNS of next Line */
int fnsc; /* FirstNS of Current */
int column = ep->column;
int srow = ep->line;
int crow = srow;
int erow = srow;
short dins = 0; /* relative insert lines/delete lines */
char moded = 0; /* any modifications done at all? */
char checked = 0; /* for cursor positioning. */
if (ep->config.margin == 0)
ep->config.margin = 75;
Nsu ++;
for (;;)
{
str = GETTEXT(ep,ep->line+1);
fnst = 0;
fnsc = firstns((char *)Current);
nlok = (ep->line + 1 < ep->lines && fnsc >= (fnst=firstns(str)));
if (ep->config.wwcol >= 0)
fnst = fnsc = ep->config.wwcol;
if (nlok && str[0] == 0)
nlok = 0;
lnsc = lastns((char *)Current);
if (lnsc < ep->config.margin)
{ /* space at end of line for marg-lnsc-2 letter word */
if (nlok == 0) /* but no more data to joinup */
break; /* done */
if (ep->config.margin - lnsc - 2 >= wordlen(str+fnst))
{
ep->column = 0;
Clen = lastns((char *)Current);
if (Current[Clen])
++Clen;
moded = 1;
--dins;
if (do_join())
continue;
++dins;
error ("reformat:\nMargin too big");
break;
}
if (n == 0) /* if couldn't mod line, and text_write, don't update any more */
break;
do_down ();
erow = ep->line;
continue;
}
/* no space, need to split */
/* find start of prev word */
for (;;)
{
int i = lnsc;
while (i && Current[i] != ' ')
--i;
lnsc = i;
if (i >= ep->config.margin)
{
while (i && Current[i] == ' ')
--i;
if (i < ep->config.margin)
break;
lnsc = i;
} else
break;
}
/* Word too long */
if (wordlen((char *)Current+lnsc) >= ep->config.margin)
{
error ("reformat:\nWord too long");
break;
}
if (lnsc)
{ /* ok to split at word */
++lnsc;
++dins;
ep->column = lnsc;
do_split (); /* Split at point LNSC */
do_down (); /* must insert proper amount? */
{
int indent = (nlok == 0) ? fnsc : fnst;
if (ep->config.wwcol >= 0)
indent = ep->config.wwcol;
if (!checked)
{
checked = 1;
if (lnsc <= column)
{ /* if split before cursor */
column = column - ep->column + indent;
++crow;
}
}
if (Clen + indent < 253)
{
movmem(Current, Current + indent,
strlen((char *)Current)+1);
setmem(Current, indent, ' ');
Clen += indent;
}
}
erow = ep->line;
continue;
}
if (n == 0)
break;
do_down ();
}
if (column < 0 || column > 200)
column = 0;
if (srow >= ep->lines)
{
srow = ep->lines - 1;
goto ra;
}
if (dins || srow < ep->topline || srow >= ep->topline + Lines)
{
ra:
text_sync ();
Nsu --;
ep->line = crow;
ep->column = column;
text_load ();
text_adjust (TRUE);
} else
{
text_sync ();
Nsu --;
ep->line = crow;
ep->column = column;
text_load ();
if (erow != srow)
{
if (!text_adjust (FALSE))
{
erow ++;
if (erow - ep->topline > Lines)
erow = ep->topline + Lines;
SetAPen(rp, TEXT_BPEN);
SetWrMsk (rp, -1);
RectFill(rp, COL(0), ROW(srow - ep->topline),
Xpixs, ROW(erow - ep->topline)-1);
SetAPen(rp, TEXT_FPEN);
text_displayseg(srow - ep->topline, erow - srow);
}
} else
{
text_sync ();
if (moded)
text_redisplaycurrline ();
}
}
if (column > Clen)
{
setmem(Current+Clen, column - Clen, ' ');
Current[column] = 0;
}
ep->column = column;
} /* do_reformat */
void do_insline (void)
{
ubyte *ptr;
ED *ep = Ep;
ep->modified = 1;
text_sync ();
if (makeroom (32))
{
ptr = allocline (1);
bmovl(ep->list+ep->line, ep->list+ep->line+1,ep->lines-ep->line);
GETTEXT(ep,ep->line) = ptr;
ep->lines ++;
if (ActualBlock.ep == ep)
{
if (ep->line <= ActualBlock.start_line)
ActualBlock.start_line ++;
if (ep->line <= ActualBlock.end_line)
ActualBlock.end_line ++;
}
} else
{
nomemory ();
}
text_load ();
if (Nsu == 0)
{
scroll_display (0, -1, 0, ep->line, MAXLINELEN, ep->topline+Lines);
text_displayseg (ep->line - ep->topline, 1);
}
} /* do_insline */
void do_deline (void)
{
int delline, eline;
ED *ep = Ep;
/* store line for later UNDO */
strcpy ((char *)Deline, (char *)Current);
if (ep->lines > 1)
{
ep->modified = 1;
text_sync ();
/* remove line */
freeline (GETTEXT(ep,ep->line));
bmovl (ep->list+ep->line+1, ep->list+ep->line, ep->lines-ep->line-1);
/* adjust block */
if (ActualBlock.ep == ep)
{
if (ep->line < ActualBlock.start_line)
ActualBlock.start_line --;
if (ep->line <= ActualBlock.end_line)
ActualBlock.end_line --;
}
/* remember line we deleted */
delline = ep->line;
/* line was last one */
if (ep->line >= --ep->lines)
{
/* move up one line */
--ep->line;
/* get the line into current */
text_load ();
/* line now below topline ? */
if (ep->line < ep->topline)
{
/* update screen if allowed */
if (!Nsu)
{
/* find new position */
ep->topline = ep->line - (Lines>>1);
if (ep->topline < 0)
ep->topline = 0;
text_redisplay ();
}
return;
}
}
/* get line */
text_load ();
/* update display */
if (!Nsu)
{
eline = ep->topline + Lines - 1;
if (ep->lines < eline)
eline = ep->lines +1;
scroll_display (0, 1, ep->topcolumn, delline,
ep->topcolumn+Columns-1, eline);
}
} else
{
/* no more lines in the text */
do_firstcolumn ();
do_remeol ();
ep->modified = 0;
}
} /* do_deline */
void do_tlate (void)
{
ubyte * ptr = av[1];
ED * ep = Ep;
ubyte c = Current[ep->column];
if (c == 0)
c = ' ';
switch (*ptr)
{
case '+':
c += strtol ((char *)ptr+1, NULL, 0);
break;
case '-':
c -= strtol ((char *)ptr+1, NULL, 0);
break;
case '"':
c = ptr[1];
break;
case 'u':
case 'U':
c = toupper (c);
break;
case 'l':
case 'L':
c = tolower (c);
break;
default:
c = strtol ((char *)ptr, NULL, 0);
}
if (c)
{
if (Current[ep->column] == 0)
{
Clen = ep->column + 1;
Current[Clen] = 0;
}
Current[ep->column] = c;
if (!Nsu)
{
LINE * text_line;
/* get the actual line */
text_line = GETLINE(ep,ep->line);
/* if the char fits into the line, just copy it (ie. avoid
text_sync(). Else call text_sync() */
if (ep->column < LENGTH(text_line))
(CONTENTS(text_line))[ep->column] = c;
else
text_sync ();
/* Delete the character on screen. First, find the color
we need for this operation, then draw over it */
if (is_inblock (ep->line, ep->column) & BP_INSIDE)
SetAPen (ep->win->RPort, BLOCK_BPEN);
else
SetAPen (ep->win->RPort, TEXT_BPEN);
SetWrMsk (ep->win->RPort, -1);
RectFill (ep->win->RPort, COL(ep->column), ROW(ep->line),
COL(ep->column+1)-1, ROW(ep->line+1)-1);
/* redraw that character */
redraw_textlineseg (ep->line, ep->column, ep->column + 1);
}
}
} /* do_tlate */
void do_justify (void)
{
ED *ep = Ep;
short firstnb, lastnb, i, n, fill, c, sp;
short changed = FALSE;
switch(av[1][0])
{
case 'c':
break;
case 'f':
firstnb = firstns((char *)Current);
lastnb = lastns((char *)Current);
if (firstnb < lastnb && ep->config.margin < MAXLINELEN-1)
{
n = 0;
i = firstnb;
while (i <= lastnb)
{
while ((c = Current[i]) && c != ' ')
i++;
if (i <= lastnb)
{
n++;
while (Current[i] == ' ')
i++;
}
}
fill = ep->config.margin - lastnb - 1;
i = firstnb;
Current[lastnb + 1] = 0;
if (n > 0 && fill > 0)
changed = TRUE;
while (n > 0 && fill > 0 && Current[i])
{
while ((c = Current[i]) && c != ' ')
i++;
sp = fill / n;
movmem (&Current[i], &Current[i + sp],
strlen((char *)&Current[i]) + 1);
memset ((char *)&Current[i], ' ', sp);
while (Current[i] == ' ')
i++;
fill -= sp;
n--;
}
}
break;
default:
break;
}
if (changed)
{
text_sync ();
text_redisplaycurrline ();
}
} /* do_justify */
void do_unjustify (void)
{
short i, j, waswhite = FALSE;
ubyte c;
for (i = 0; Current[i] == ' '; i++);
for (j = i; Current[i]; i++)
{
c = Current[j] = Current[i];
if (c != ' ' || !waswhite)
j++;
waswhite = (c == ' ');
}
Current[j] = 0;
if (i != j)
{
text_sync ();
text_redisplaycurrline ();
}
} /* do_unjustify */
void do_indent (void)
{
Line start,
end;
Column column;
int indent,
dir,
align,
len,
curr_indent,
leading,
trailing,
t;
char * ptr;
RP * rp;
LINE * linelist;
/* decode range */
ptr = av[1];
start = end = -1;
while (*ptr)
{
if (*ptr == '.')
{
start = end = Ep->line;
break;
} else if (isdigit(*ptr))
{
if (start == -1)
start = atoi (ptr);
else end = atoi (ptr);
while (isdigit(*ptr)) ptr ++;
ptr --;
} else if (*ptr == '$')
{
if (start == -1)
start = get_pong (*ptr - '0');
else
end = get_pong (*ptr - '0');
} else if (*ptr == 'b')
{
if (!block_ok())
{
error ("indent block:\nNo block specified");
return ;
}
if (!ptr[1])
{
start = ActualBlock.start_line;
end = ActualBlock.end_line;
} else
{
ptr ++;
if (*ptr == 's')
indent = ActualBlock.start_line;
else
indent = ActualBlock.end_line;
if (start == -1)
start = indent;
else
end = indent;
}
} else if (*ptr == 't')
{
start = 1;
end = Ep->lines;
} else if (*ptr == '_')
{
if (start == -1)
start = Ep->lines;
else
end = Ep->lines;
}
ptr ++;
} /* while (*ptr) */
if (start == -1)
{
error ("indent:\ncannot evaluate start-line");
return ;
}
if (end == -1) end = start;
if (start > end)
{
start ^= end; /* Swap ! 8-O */
end ^= start;
start ^= end;
}
/* Now find out how to indent */
ptr = av[2];
dir = 1; /* indent, i.e. insert spaces */
align = 0; /* just insert `indent' spaces */
indent = -1;
column = 0;
while (*ptr)
{
if (*ptr == '-')
dir = -1; /* outdent line, i.e. delete spaces */
else if (*ptr == '.')
align = 1; /* align line to a multiple of `indent' */
else if (*ptr == 't')
indent = Ep->config.tabstop;
else if (isdigit(*ptr))
{
indent = atoi (ptr);
while (isdigit(*ptr)) ptr++;
ptr --;
} else if (*ptr == 'c')
column = Ep->column;
ptr ++;
} /* while (*ptr) */
if (indent == -1)
{
error ("indent:\nCannot evaluate indent-amount");
return ;
}
text_sync ();
/* Note : If the line contains less spaces than indent specifies and
the user wants to outdent, the line is left-aligned, i.e. no chars
except spaces are deleted ! This is also true for indent, i.e. no
chars are moved over the right border (MAXLINELEN chars). */
linelist = Ep->list + start;
for (t=start; t <= end; t ++, linelist ++)
{
strcpy (Current, linelist[0]);
Clen = strlen (Current);
if (Clen <= column) continue;
ptr = Current + column;
while (*ptr == ' ') ptr ++;
if (!*ptr) continue; /* Empty line */
leading = (int)ptr - (int)Current;
trailing = MAXLINELEN-1 - Clen;
/* Should I align the line to a multiple of indent or just
insert/delete indent spaces ? */
if (align)
{
/* use appropriate difference */
if (dir > 0)
curr_indent = indent - (leading % indent);
else
{
curr_indent = leading % indent;
if (!curr_indent)
curr_indent = indent;
}
} else curr_indent = indent;
len = strlen (ptr) + 1;
if (dir > 0)
{
if (trailing < curr_indent)
curr_indent = trailing;
if (!curr_indent) continue;
movmem (ptr, ptr+curr_indent, len);
setmem (ptr, curr_indent, ' ');
} else
{
if (leading < curr_indent)
curr_indent = leading;
if (!curr_indent) continue;
movmem (ptr, ptr-curr_indent, len);
}
Clen = strlen (Current);
len = strlen (linelist[0]);
#ifdef DEBUG
printf ("Old len %d New Len %d BlenOld %d BlenNew %d\n",
len, Clen, ((len + 8) & ~7), ((Clen + 8) & ~7));
#endif
/* Find out if we have to allocate new memory */
/* Clen is total length in bytes while len is only strlen() */
/* TODO: Ain't work yet */
/*if ((((Clen + 8) & ~7) != ((len + 8) & ~7)))
{*/
ptr = allocline (Clen + 1);
if (!ptr)
{
nomemory ();
globalflags.Abortcommand = 1;
break;
}
freeline (linelist[0]);
linelist[0] = ptr;
/*}*/
strcpy (ptr, Current);
} /* for (t = start; t <= end; t ++, linelist ++) */
Ep->modified = 1;
text_load ();
/* Don't display if there is nothing to display */
if (end < Ep->topline)
return;
if (start < Ep->topline)
{
start = 0;
t = end - Ep->topline +1;
} else
{
t = end - start +1;
start -= Ep->topline;
if (start >= Lines)
return;
}
if (t > Lines)
t = Lines;
if (!Nsu)
{
rp = Ep->win->RPort;
end = start + t-1;
/* only clear area, if there is a line outside the block */
if (!is_inblock (start, -1) || !is_inblock (end, -1))
{
SetAPen (rp, TEXT_BPEN);
SetWrMsk (rp, BLOCK_MASK);
RectFill (rp, Xbase, ROW(start), Xpixs, ROW(start+t)-1);
}
if (!text_sync ())
text_displayseg (start, t);
}
} /* do_indent */
void do_inslines (void)
{
int lines = atoi (av[1]);
if (lines <= 0) return;
while (lines)
{
do_insline ();
lines --;
}
} /* do_inslines */
void do_delete (void)
{
char * ptr, * hptr;
hptr = ptr = Current + Ep->column;
if (*hptr == ' ')
while (*hptr == ' ') hptr ++;
else while (*hptr != ' ') hptr ++;
strcpy (ptr, hptr);
text_sync ();
text_redisplaycurrline ();
} /* do_delete */
void do_delines (void)
{
int t;
t = atoi (av[1]);
for ( ; t >= 0; t--)
do_deline ();
} /* do_delines */
/*
* Commands submitted by Markus Wenzel
*/
void do_undeline (void)
{
do_insline ();
text_load ();
strcpy((char *)Current, (char *)Deline);
text_sync ();
text_displayseg (Ep->line - Ep->topline, 1);
} /* do_undeline */
void do_clipins (void)
{
struct IOClipReq * ior;
struct cbbuf * buf;
if (!(ior = CBOpen (0)) )
return;
if (CBQueryFTXT (ior))
{
buf = CBReadCHRS (ior);
if (buf)
{
text_write ((ubyte *)buf->mem);
CBFreeBuf (buf);
}
CBReadDone (ior);
}
CBClose (ior);
} /* do_clipins */
void do_space (void)
{
ED * ep = Ep;
int insmode = ep->config.insertmode;
ep->config.insertmode = 1;
text_write (" ");
ep->config.insertmode = insmode;
} /* do_space */
void do_return (void)
{
char buf[MAXLINELEN];
char * partial;
if (globalflags.Comlinemode)
{
strcpy (buf, (char *)Current);
partial = esc_partial; /* PATCH_NULL: P -> esc_p */
esc_partial = NULL; /* PATCH_NULL: P -> esc_p */
escapecomlinemode ();
if (partial)
{
if (do_command (buf))
do_command (partial);
free(partial);
} else
do_command (buf);
} else
{
if (Ep->config.autoindent)
{ /* If user want's autoindent */
short indent; /* how much */
short line; /* Line-no. */
char * ptr; /* pointer to Ep->list[line] */
text_sync (); /* store actual line */
/* Start with current line */
indent = 0;
ptr = (char *)Current;
/* Find 1. nonspace ... */
while (isspace (*ptr))
{
ptr ++;
indent ++;
}
/* ... but not '\0'. In this case the line is empty and
indent is therefore 0 */
if (!*ptr)
indent = 0;
/* Try on, if indent is zero, line is empty and there are more
lines on top */
if (!indent && !*ptr && Ep->line)
{
line = Ep->line - 1;
/* Until 1. line */
while (line)
{
/* Try every line */
ptr = GETTEXT(Ep,line);
indent = 0;
while (isspace (*ptr))
{
ptr ++;
indent ++;
}
if (indent || *ptr)
break;
line --;
}
}
/* Not at last position in line ? then we have to split and
indent the rest */
if (Ep->column != Clen)
{
/* Split line, move to next line but shouldn't show this */
do_split ();
do_down ();
/* Indent new line */
if (indent > Ep->column)
indent -= indent - Ep->column;
if (indent > 0)
{
movmem (Current, Current+indent, Clen+1);
setmem (Current, indent, ' ');
Clen += indent;
Ep->column = indent;
} else
Ep->column = 0;
Current[Clen] = 0;
/* and position cursor */
text_sync ();
/* Show result */
text_redisplaycurrline ();
} else
{
if (Ep->line != Ep->lines-1)
{
do_down ();
do_insline ();
Ep->column = indent;
text_sync ();
} else
{
do_split ();
Ep->column = indent;
text_sync ();
do_down ();
}
}
} else
{
Ep->column = 0;
text_sync ();
do_downadd ();
}
} /* !Comlinemode */
} /* do_return */
/******************************************************************************
***** ENDE edit.c
******************************************************************************/