- или приводит к выходу из текстового редактора в
точку его вызова из главной программы.
Функция, реализующая текстовый редактор
-----------------------------------------------------------------
Текстовый редактор реализован в виде отдельной функции,
которую может вызвать ваша программа. Для использования этой
функции вы должны вначале организовать окно, в которое будут
вводиться и в котором будут обрабатываться текстовые данные.
void text_editor (WINDOW *wnd, char *bf, unsigned bsize)
Эта функция обрабатывает текстовые данные, вводимые в окно с
помощью текстового редактора. Указатель wnd специфицирует
предварительно установленное вами окно. Указатель bf определяет
текстовый буфер, а целое число bsize специфицирует размер буфера.
Количество строк в буфере является функцией, зависящей от размера
буфера и размеров (ширины) окна, которые устанавливаются, когда
вы организуете окно.
При вызове функции она отображает текст, начиная с первой
страницы из текстового буфера, и позволяет как ввод текстовых
данных, так и ввод команд редактирования и обработки текста с
клавиатуры. При выходе из текстового редактора буфер содержит
введенный или модифицированный пользователем текст.
Исходный листинг: editor.c
-----------------------------------------------------------------
Листинг 9.1 содержит исходный текст оконного текстового
редактора.
Листинг 9.1: editor.c
/* ------------------------- editor.c ------------------------ */
#include
#include
#include
#include
#include
#include "twindow.h"
#include "keys.h"
#define TRUE 1
#define FALSE 0
#define TAB 4
#define NEXTTAB (TAB-(x%TAB))
#define LASTTAB (((wwd-1)/TAB)*TAB)
#define PREVTAB (((x-1)%TAB)+1)
#define curr(x,y) (bfptr+(y)*wwd+(x))
#define lineno(y) ((int)(bfptr-topptr)/wwd+(y))
extern int VSG;
int last_x, last_y;
static int wht;
static int wwd;
static int wsz;
static char *topptr;
static char *bfptr;
static char *lstptr;
static int lines;
static char *endptr;
static int blkbeg;
static int blkend;
static int inserting;
static WINDOW *wnd;
static int do_display_text =1;
/* ---------- local function prototypes ----------- */
void erase_buffer(int *x, int*y);
int lastword(int x, int y);
void last_char(int *x, int *y);
void test_para(int x, int y);
int traling_spaces(int);
int first_wordlen(int y);
void paraform(int x, int y);
int blankline(int line);
void delete_word(int x, int y);
void delete_line(int y);
void delete_block(void);
void copy_block(int y);
void move_block(int y);
void mvblock(int y, int moving);
void findlast(void);
void find_end(int *x, int *y);
void carrtn(int *x, int *y, int insert);
void backspace(int *x, int *y);
void fore_word(int *x, int *y, char *bf);
int spaceup(int *x, int *y, char **bf);
void back_word(int *x, int *y, char *bf);
int spacedn(int *x, int *y, char **bf);
void forward(int *x, int *y);
int downward(int *y);
void upward(int *y);
void display_text(void);
void disp_line(int y);
void insert_line(void);
/* ----- Process text entry for a window. ----- */
void text_editor(WINDOW *wnd1, char *bf, unsigned bsize)
{
char *b, *buff;
int depart = FALSE, i, c;
int x, y, svx, svlw, tx, tabctr = 0;
wnd = wnd1;
wht = HEIGHT-2;
wwd = WIDTH-2;
topptr = bfptr = bf;
lines = bsize / wwd;
endptr = bf + wwd * lines;
blkbeg = 0;
blkend = 0;
inserting = FALSE;
x = 0;
y = 0;
display_text();
/* --------- read in text from the keyboard ---------- */
findlast();
while (TRUE) {
last_x = COL + 1 + x;
last_y = ROW + 1 + y;
cursor(last_x, last_y);
buff = curr(x, y);
if (tabctr) {
--tabctr;
c = ' ';
}
else {
c = get_char();
clear_message();
}
switch (c) {
case '\r': carrtn(&x, &y, inserting);
break;
case DN: downward(&y);
break;
case PGUP: y = 0;
for (i = 0; i < wht; i++)
upward(&y);
break;
case PGDN: y = HEIGHT - 2;
for (i = 0; i < wht; i++)
downward(&y);
y = 0;
break;
case '\t': if (x + NEXTTAB < wwd) {
if (inserting)
tabctr = NEXTTAB;
else
x += NEXTTAB;
}
else
carrtn(&x, &y, inserting);
break;
case SHIFT_HT:
if (x < TAB ) {
upward(&y);
x = LASTTAB;
}
else
x -= PREVTAB;
break;
case CTRL_FWD:
fore_word(&x, &y, buff);
break;
case CTRL_BS:
back_word(&x, &y, buff);
break;
case CTRL_B:
y = wht - 1;
break;
case CTRL_T:
y = 0;
break;
case CTRL_HOME:
x = y = 0;
bfptr = topptr;
display_text();
break;
case HOME: x = 0;
break;
case CTRL_END:
find_end(&x, &y);
display_text();
break;
case END: last_char(&x, &y);
break;
case UP: upward(&y);
break;
case F2:
case ESC: depart = TRUE;
break;
case '\b':
case BS: if (curr(x, y) == topptr)
break;
backspace(&x, &y);
if (x == wwd - 1)
last_char(&x, &y);
if (c == BS)
break;
buff = curr(x, y);
case DEL: movmem(buff+1, buff, wwd-1-x);
*(buff+wwd-1-x) = ' ';
disp_line(y);
test_para(x+1, y);
break;
case ALT_D: delete_line(y);
break;
case INS: inserting ^= TRUE;
insert_line();
break;
case F3: erase_buffer(&x, &y);
break;
case F4: paraform(0, y);
break;
case F5: blkbeg = lineno(y) + 1;
if (blkbeg > blkend)
blkend = lines;
display_text();
break;
case F6: blkbeg = lineno(y) + 1;
if (blkbeg < blkend)
blkend = 1;
display_text();
break;
case F7: move_block(y);
break;
case F8: copy_block(y);
break;
case F9: delete_block();
break;
case F10: blkbeg = blkend = 0;
display_text();
break;
case FWD: forward(&x, &y);
break;
default: if (!isprint(c))
break;
if (curr(x, y) == endptr-1 ||
(lineno(y)+1 >= lines && inserting
&& *curr(wwd-2, y) != ' ')) {
error_message(" End of Buffer ");
break;
}
if (inserting) {
buff = curr(x, y);
movmem(buff, buff + 1, wwd-1-x);
}
buff = curr(x, y);
if (buff < endptr) {
if (buff >= lstptr)
lstptr = buff + 1;
*buff = c;
disp_line(y);
}
buff = curr(wwd-1, y);
if (endptr && *buff != ' ') {
for (b = buff+1; b < endptr; b++)
if (*b==' ' && *(b + 1)==' ')
break;
movmem(buff+1, buff+2, b-buff-1);
*(buff+1) = ' ';
svx = x;
svlw = lastword(x, y);
x = wwd-1;
if (*(buff-1) != ' ')
back_word(&x, &y, buff);
tx = x;
carrtn(&x, &y, TRUE);
if (svlw)
x = svx-tx;
else {
x = svx;
--y;
}
}
forward(&x, &y);
break;
}
if (depart)
break;
}
inserting = FALSE;
insert_line();
}
/* -------- erase the buffer ---------------- */
static void erase_buffer(int *x, int *y)
{
int c = 0;
WINDOW *sur;
sur = establish_window(28, 11, 4, 24);
set_colors(sur, ALL, RED, YELLOW, BRIGHT);
display_window(sur);
wprintf(sur, " Erase text window\n Are you sure? (y/n)");
while (c != 'y' && c != 'n') {
c = get_char();
c = tolower(c);
if (c == 'y') {
lstptr = bfptr =topptr;
*x = *y = 0;
setmem(bfptr, lines * wwd, ' ');
blkbeg = blkend = 0;
display_text();
}
}
delete_window(sur);
}
/* ----- see if a word is the last word on the line ------ */
static int lastword(int x, int y)
{
char *bf = curr(x, y);
while (x++ < wwd-1)
if (*bf++ == ' ')
return 0;
return 1;
}
/* str 188 */
/* --- go to last displayable character on the line --- */
static void last_char(int *x, int *y)
{
char *bf;
*x = wwd-1;
bf = curr(0, *y);
while(*x && *(bf + *x) == ' ')
--(*x);
if (*x && *x < wwd-1)
(*x)++;
}
/* ----- test to see if paragraph should be reformed ----- */
static void test_para(int x, int y)
{
int ts, fw;
if(!scroll_lock() && y < lines) {
ts= trailing_spaces(y);
fw = fierst_wordlen(y+1);
if (fw && ts > fw)
paraform(x, y);
}
}
/* ---- count the trailing spaces on a line ----- */
static int trailing_spaces(int y)
{
int x = 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 fiest_wordlen(int y)
{
int ct = 0, x = 0;
char *bf = curr(0, y);
while (x < wwd-1 && *(bf+x) == ' ')
x++;
while (x+ct < wwd-1 && *(bf+x+ct) == ' ')
ct++;
return ct;
}
/*----------------- form a paragraph -------------------- */
static void paraform(int x, int y)
{
char *cp1, *cp2, *cpend, *svcp;
int x1;
if (blankline(lineno(y)+1))
return;
if (!blkbeg) {
blkbeg = blkend = lineno(y)+1;