blkend++;
while(blkend < lines) {
if (blankline(blkend))
break;
blkend++;
}
--blkend;
}
if(lineno(y) != blkend-1 )
x=0;
x1=x;
cp1=cp2=topptr + (blkend-1) * wwd + x;
cpend = topptr + blkend * wwd;
while(cp2 < cpend){
while(*cp2 == ' ' && cp2 < cpend)
cp2++;
if(cp2 == cpend)
break;
/* at a word */
while(*cp2 != ' ' && cp2 < cpend) {
if(x1 >= wwd-1) {
/* wrap the word */
svcp = cp1 + (wwd - 1);
while(*--cp1 != ' ') {
*cp1 = ' ';
--cp2;
}
x1 = 0;
blkbeg++;
cp1 = svcp;
}
*cp1++ = *cp2++;
x1++;
}
if(cp2 < cpend) {
*cp1++ = ' ';
x1++;
}
}
while(cp1 < cpend)
*cp1++ = ' ';
blkbeg++;
if(blkbeg <= blkend)
delete_block();
blkbeg =blkend =0;
display_text();
findlast();
}
/* ------------ test for a blank line ---------------- */
static int blankline(int line)
{
char *cp;
int x;
cp = topptr + (line-1) * wwd;
for(x=0; x < wwd; x++)
if(*(cp+x) != ' ')
break;
return(x == wwd );
}
/*------------ delete a word ------------------------ */
static void delete_word(int x, int y)
{
int wct = 0;
char *cp1, *cp2;
cp1= cp2= curr(x, y);
if(*cp2 == ' ')
while(*cp2 == ' ' && x+wct < wwd) {
wct++;
cp2++;
}
else {
while(*cp2 != ' ' && x+wct < wwd) {
wct++;
cp2++;
}
while(*cp2 == ' ' && x+wct < wwd) {
wct++;
cp2++;
}
}
movmem(cp2, cp1, wwd-x-wct);
setmem(cp1+wwd-x-wct, wct, ' ');
dispay_text();
findlast();
}
/*------------------ delete a line -----------------*/
static void delete_line(int y)
{
char *cp1, *cp2;
int len;
cp1=bfptr + y + wwd;
cp2=cp1 + wwd;
if(cp1 blkbeg-1 && lineno(y) <= blkend-1) {
error_message("Can't move/copy a blok into itself");
return;
}
len=(blkend - blkbeg + 1) * wwd;
if((hd=malloc(len)) == 0)
return;
cp1 = topptr + (blkbeg + 1) * wwd;
movmem(cp1, hd, len);
cp2 = topptr + lineno(y) * wwd;
if (moving) {
if(lineno(y) > blkbeg-1)
cp2 -= len;
do_display_text =0;
delete_block();
do_display_text =1;
}
if(cp2+len <= endptr) {
movemem(cp2, cp2 + len, endptr - cp2 - len);
movemem(hd, cp2, len);
}
free(hd);
blkbeg = blkend = 0 ;
display_text();
}
/*------------ copy a block -----------------------*/
static void copy_block(int y)
{
mvblock(y, FALSE);
findlast();
}
/*------------------- move a block -----------------*/
static void move_block(int y)
{
mvblock(y, TRUE);
}
/*-------- find the last caracter in the buffer -------*/
static void findlast()
{
register char *lp = endptr - 1;
register char *tp = topptr;
while(lp > tp && (*lp == ' ' || *lp == '\0')) {
if (*lp == '\0')
*lp = ' ';
--lp;
}
if(*lp != ' ')
lp++;
lstptr = lp;
}
/*------- go to end of the data in the buffer ---------*/
static void find_end(int *x, int *y)
{
int ct;
bfptr = lstptr;
ct = (lstptr - topptr) % wsz;
bfptr -= ct;
if (bfptr + wsz > endptr)
bfptr = endptr - wsz;
*x = 0;
*y = (ct / wwd);
downward(y);
}
/*---------------------carriage return ----------------*/
static void carrtn(int *x, int *y, int insert)
{
int insct;
char *cp, *nl;
int ctl = 2;
cp = curr(*x, *y);
nl = cp + ((cp - topptr) % wwd);
if (lineno(*y)+2 < lines)
if (insert && nl < endptr) {
insct = wwd - *x;
while (ctl--) {
if (endptr > cp + insct) {
movemem(cp, cp+insct, endptr-insct-cp);
setmem(cp, insct, ' ');
}
else if(ctl == 1)
setmem(cp, endptr - cp, ' ');
cp += insct * 2;
insct= *x;
}
}
*x = 0;
downward(y);
if (insert) {
testpara(*x, *y);
display_text();
}
if (lineno(*y)+2 < lines)
if (insert)
if ((lstptr + wwd) <= endptr)
if(lstptr > curr(*x, *y))
lstptr += wwd;
}
/* ------- move the buffer offset back one position ------ */
static void backspase(int *x, int *y)
{
if (*x == 0) {
*x = wwd - 1;
upward(y);
}
else
--(*x);
}
/* ------- move the buffer offset forward one word ------ */
static void fore_word(int *x, int *y, char *bf)
{
while (*bf != ' ') {
if (spaceup(x, y, &bf) == 0)
return;
if (*x == 0)
break;
}
while (*bf == ' ')
if (spaceup(x, y, &bf) == 0)
return;
}
static int spaceup(int *x, int *y, char **bf)
{
if (*bf == lstptr)
return 0;
(*bf)++;
forward(x, y);
return 1;
}
/* ------- move the buffer offset backrward one word ------ */
static void back_word(int *x, int *y, char *bf)
{
spacedn(x, y, &bf);
while (*bf == ' ')
if (spacedn(x, y, &bf) == 0)
return;
while (*bf != ' ') {
if (*x == 0)
return;
if (spacedn(x, y, &bf) == 0)
return;
}
spaceup(x, y, &bf);
return;
}
static int spacedn(int *x, int *y, char **bf)
{
if (*bf == topptr)
return 0;
--(*bf);
backspace(x, y);
return 1;
}
/* ------- move the buffer offset forward one position ------ */
static void backspace(int *x, int *y)
{
if (*x == 0) {
*x = wwd - 1;
upward(y);
}
else
--(*x);
}
---------------------------------------------------------------- */
static void forward(int *x, int *y)
{
int ww = wwd;
(*x)++;
if (*x == ww) {
downward(y);
*x = 0;
}
}
/* ------- move the buffer offset down one position ------ */
static int downward(int *y)
{
if (*y < wht - 1) {
(*y)++;
return 1;
}
else if ((bfptr + wsz) < endptr) {
bfptr += wwd;
scroll(wnd, UP);
disp_line(wht-1);
return 1;
}
return 0;
}
/* --------- move the buffer offset up one position ------ */
static void upward(int *y)
{
if (*y) /* !!!!!!!!!!! */
--(*y);
else if ((topptr + wwd) <= bfptr) {
bfptr -= wwd;
scroll(wnd, DN);
disp_line(0);
}
}
/* ---- display all the lines in a window ------ */
static void display_text()
{
int y = 0;
if (do_display_text)
while (y < wht)
disp_line(y++);
}
/* ---------- Display a line -------- */
static void disp_line(int y)
{
int x = 0, atr = WNORMAL;
if (blkbeg || blkend)
if (lineno(y) >= blkbeg-1)
if (lineno(y) <= blkend-1)
atr = WACCENT;
while (x < wwd) {
displine(wnd, x+1, y+1, *(bfptr+y * wwd+x), atr);
x++;
}
}
--------- set insert /exchange cursor shape -----------*/
static void insert_line()
{
set_cursor_type(inserting ? 0x0106 : 0x0607);
}
Описание программы: editor.c
-----------------------------------------------------------------
Программа editor.c содержит ряд операторов #define, которые
управляют установкой позиции табуляции в окне редактора. Значение
глобальной переменной ТАВ определено равным 4, что устанавливает
позицию табуляции в четыре любых символа. Остальные глобальные
переменные - NEXTAB, LASTTAB и PREVTAB - являются
макровыражениями, позволяющими улучшить удобочитаемость текста
программы в целом. Макрос curr возвращает указатель на символ в
буфере редактирования в зависимости от значения его координат в
окне, задаваемых аргументами X и Y. Макрос lineno возвращает
номер строки в буфере, который соответствует относительному
номеру строки в окне редактора, задаваемого значением аргумента
y.
Некоторые переменные, объявленные как external, являются
вычисляемыми и предназначены прежде всего для сокращения числа
вычислительных операций в тексте программы, что делает листинг
более удобочитаемым. Переменная wht принимает значение высоты
максимально возможной области в окне, отводимой под текст; при
вычислении значения wht делается коррекция на наличие символов
рамки окна. Переменная wwd принимает значение ширины максимально
возможной области, отводимой под текст, с учетом наличия символов
рамки окна. Переменная wsz содержит размер области окна,
отводимой под текст. Переменная lines содержит количество строк
текста, которые могут быть сохранены в текстовом буфере. Параметр
endptr является указателем на позицию последнего символа в буфере
плюс единица. Значение lstptr - указатель на последний, отличный
от пробела, символ, хранящийся в буфере. Значение topptr является
указателем на первый символ, хранящийся в буфере. Указатель bfptr
используется при листании текста постранично или скроллинга
текста; он всегда указывает на символ в буфере текста, который в
данный момент отображается в левом верхнем углу окна.
Функция text_editor вызывается в случае, если пользователю
понадобилось вводить или модифицировать текст в буфере. После
инициализации функции происходит вычисление соответствующих
значений переменных, и курсор устанавливается в начальную позицию
с координатами (0,0). При вводе пользователем символов с
клавиатуры автоматически осуществляется проверка ввода на наличие
прерываний от функциональных клавиш и управляющих сигналов. При
нажатии пользователем клавиши <ВВОД> автоматически вызывается
функция carrtn. Нажатие клавиши управления курсором <Стрелка
вниз> приведет к вызову функции downward. Нажатие клавиш
<Страница вверх> и <Страница вниз> приведут к вызову функций
upward или downward соответственно для обработки отображенных в
окне строк текста. Клавиши и ) вызовут изменение
значения текущей координаты X курсора, переместив последний в
следующую или предыдущую позицию табуляции. Клавиши приведут к вызову функций fore_word или back_word