Хрестоматия по программированию на Си в Unix
move( 3, 10 ); printw( "F%d - удалить строку, F%c - вставить строку",
7, '8' );
mvwprintw(stdscr, 4,10, "ESC - выход, CTRL/C - прервать просмотр");
/* wprintw(w, fmt, ...) - аналог printf для окон */
/* В нижний правый угол экрана ничего не выводить:
* на некоторых терминалах это роллирует экран и тем самым
* портит нам картинку.
*/
wattrset( stdscr, A_NORMAL );
wmove( stdscr, LINES-1, COLS-1 );
waddch( stdscr, ' ' );
wnoutrefresh( stdscr );
/* виртуальное проявление окна. */
run = need1 = need2 = 1; /* оба файла не достигли конца */
/* прерывать просмотр по CTRL/C */
save = signal(SIGINT, stop);
while( run && (need1 || need2)){
if( need1 ){
/* прочесть строку из первого файла */
if( fgets( buffer, sizeof buffer, fp1 ) == NULL )
need1 = 0; /* конец файла */
else{
/* выдать строку в окно */
waddstr( w1, buffer );
}
}
if( need2 ){
/* прочесть строку из второго файла */
if( fgets( buffer, sizeof buffer, fp2 ) == NULL )
need2 = 0; /* конец файла */
else{
waddstr( w2, buffer );
/* wnoutrefresh( w2 ); */
}
}
/* Проявить w1 поверх w2 */
touchwin( wbase2 ); wnoutrefresh( wbase2 );
touchwin( w2 ); wnoutrefresh( w2 );
touchwin( wbase1 ); wnoutrefresh( wbase1 );
touchwin( w1 ); wnoutrefresh( w1 );
/* touchwin - пометить окно как целиком измененное.
* wnoutrefresh - переписать изменения в новый образ
* экрана в памяти. */
/* Проявить изображение на экране терминала
* (вывести новый образ экрана). При этом выводятся
* лишь ОТЛИЧИЯ от текущего содержимого экрана
* (с целью оптимизации).
*/
doupdate();
}
fclose(fp1); fclose(fp2);
/* восстановить спасенную реакцию на сигнал */
signal(SIGINT, save);
/* Редактирование в окнах */
noecho(); /* выкл. эхо-отображение */
cbreak(); /* немедленный ввод набранных клавиш
* (без нажатия кнопки \n) */
keypad( w1, TRUE ); /* распознавать функц. кнопки */
keypad( w2, TRUE );
scrollok( w1, FALSE ); /* запретить роллирование окна */
w = w1; /* текущее активное окно */
for( ;; ){
int y, x; /* координаты курсора в окне */
wrefresh( w ); /* обновить окно. Примерно соответствует
* wnoutrefresh(w);doupdate(); */
c = wgetch( w ); /* ввести символ с клавиатуры */
/* заметим, что в режиме noecho() символ не
* отобразится в окне без нашей помощи !
*/
getyx( w, y, x ); /* узнать координаты курсора в окне */
/* не надо &y &x, т.к. это макрос, превращающийся в пару присваиваний */
switch( c ){
case KEY_LEFT: /* шаг влево */
waddch( w, '\b' );
break;
case KEY_RIGHT: /* шаг вправо */
wmove( w, y, x+1 );
break;
case KEY_UP: /* шаг вверх */
wmove( w, y-1, x );
break;
case KEY_DOWN: /* шаг вниз */
wmove( w, y+1, x );
break;
case KEY_HOME: /* в начало строки */
case KEY_LL: /* KEY_END в конец строки */
{ int xbeg, xend;
wbegend(w, &xbeg, &xend);
wmove(w, y, c==KEY_HOME ? xbeg : xend);
break;
}
case '\t': /* табуляция */
x += 8 - (x % 8);
if( x >= wcols( w ))
x = wcols(w)-1;
wmove(w, y, x);
break;
case KEY_BACKTAB: /* обратная табуляция */
x -= 8 - (x % 8);
if( x < 0 ) x = 0;
wmove( w, y, x );
break;
case '\b': /* забой */
case KEY_BACKSPACE:
case '\177':
if( !x ) break; /* ничего */
wmove( w, y, x-1 );
/* and fall to ... (и провалиться в) */
case KEY_DC: /* удаление над курсором */
wdelch( w );
break;
case KEY_IC: /* вставка пробела над курсором */
winsch( w, ' ' );
break;
case KEY_IL:
case KEY_F(8): /* вставка строки */
winsertln( w );
break;
case KEY_DL: /* удаление строки */
case KEY_F(7):
wdeleteln( w );
break;
case ESC: /* ESC - выход */
goto out;
case KEY_F(1): /* переключение активного окна */
if( w == w1 ){
touchwin( wbase2 ); wnoutrefresh( wbase2 );
touchwin( w2 ); wnoutrefresh( w2 );
w = w2;
} else {
touchwin( wbase1 ); wnoutrefresh( wbase1 );
touchwin( w1 ); wnoutrefresh( w1 );
w = w1;
}
break;
case KEY_F(5): /* переключение режима редактирования */
mode = ! mode;
break;
case ctrl('A'): /* перерисовка экрана */
RedrawScreen(); break;
case '\n': case '\r':
waddch( w, '\n' );
break;
default: /* добавление символа в окно */
if( c >= 0400 ){
beep(); /* гудок */
break; /* функц. кнопка - не буква */
}
if( mode ){
winsch( w, ' ' ); /* раздвинь строку */
}
waddch( w, c ); /* выдать символ в окно */
break;
}
}
out:
wrefresh( w ); wsave(w);
bad:
die(0); /* вызов без возврата */
}
/* Сохранить содержимое окна в файл, обрезая концевые пробелы */
wsave(w) WINDOW *w;
{
FILE *fp = fopen("win.out", "w");
register int x,y, lastnospace; int xs, ys;
getyx(w, ys, xs);
for( y=0; y < wlines(w); y++ ){
/* поиск последнего непробела */
for( lastnospace = (-1), x=0; x < wcols(w); x++ )
/* читаем символ из координат (x,y) окна */
if((mvwinch(w,y,x) & A_CHARTEXT) != ' ' )
lastnospace = x;
/* запись в файл */
for( x=0 ; x <= lastnospace; x++ ){
wmove(w,y,x);
putc( winch(w) & A_CHARTEXT, fp );
}
putc( '\n', fp );
}
fclose(fp);
wmove(w, ys, xs ); /* вернуть курсор на прежнее место */
}
/* На самом деле
* winch(w) = wtext(w)[ wcury(w) ][ wcurx(w) ];
* Предложим еще один, более быстрый способ чтения памяти окна
* (для ЗАПИСИ в окно он непригоден, т.к. curses еще
* специальным образом помечает ИЗМЕНЕННЫЕ области окон).
*/
/* Найти начало и конец строки */
int wbegend(w, xbeg, xend) WINDOW *w; int *xbeg, *xend;
{
/* Тип chtype: 0xFF - код символа; 0xFF00 - атрибуты */
chtype ch, *thisline = wtext(w)[ wcury(w) ];
register x, notset = TRUE;
*xbeg = *xend = 0;
for(x=0; x < wcols(w); x++)
/* & A_CHARTEXT игнорирует атрибуты символа */
if(((ch=thisline[x]) & A_CHARTEXT) != ' '){
if((*xend = x+1) >= wcols(w))
*xend = wcols(w) - 1;
if(notset){ notset = FALSE; *xbeg=x; }
}
return (*xend - *xbeg);
}
/* Пример 17 */
/* Window management: "стопка" окон
* cc -DTEST -DUSG w.c -lncurses -lx
*
*____ Файл w.h для Пример 17, Пример 19, Пример 21, Пример 23 _____ */
#include "wcur.h" /* Тот же, что в Пример 16 */
extern int botw, topw;
extern struct WindowList { /* Элемент списка окон */
WINDOW *w; /* окно */
int next; /* следующее окно в списке */
char busy; /* 0:слот свободен, 1:окно видимо, -1:окно спрятано */
} wins[]; /* значения поля busy: */
#define W_VISIBLE 1 /* окно видимо */
#define W_FREE 0 /* слот таблицы свободен */
#define W_HIDDEN (-1) /* окно спрятано */
#define EOW (-1)
#define WIN(n) wins[n].w
/* если совсем нет видимых окон... */
#define TOPW (topw != EOW ? WIN(topw) : stdscr)
#define BOTW (botw == EOW ? stdscr : WIN(botw))
#define MAXW 15
#define iswindow(n) wins[n].busy
int RaiseWin (WINDOW *w); void PopWin ();
void DestroyWin(WINDOW *w, int destroy);
int HideWin (WINDOW *w);
#define KillWin(w) DestroyWin(w, TRUE)
#define DropWin(w) DestroyWin(w, FALSE)
#define PushWin(w) RaiseWin(w)
#define BAR_HOR 01 /* окно имеет горизонтальный scroll bar */
#define BAR_VER 02 /* окно имеет вертикальный scroll bar */
#define DX 2 /* отступ от краев окна */
#define BARWIDTH 2 /* ширина scroll bar-а */
#define BARHEIGHT 1 /* высота */
/* Вычисление координат строки выбора в окне */
#define WY(title, y) ((y) + (title ? 3 : 1))
#define WX(x) ((x) + 1 + DX)
#define XEND(w,scrollok) (wcols(w)-((scrollok & BAR_VER) ? BARWIDTH+2 : 1))
void whorline (WINDOW *w, int y, int x1, int x2);
void wverline (WINDOW *w, int x, int y1, int y2);
void wbox (WINDOW *w, int x1, int y1, int x2, int y2);
void wborder (WINDOW *w);
void wboxerase (WINDOW *w, int x1, int y1, int x2, int y2);
void WinBorder (WINDOW *w, int bgattrib, int titleattrib, char *title,
int scrollok, int clear);
void WinScrollBar(WINDOW *w, int whichbar, int n, int among,
char *title, int bgattrib);
/* Спасение/восстановление позиции курсора */
typedef struct { int x, y; } Point;
#define SetPoint(p, yy, xx) { (p).x = (xx); (p).y = (yy);}
#define GetBack(p, w) wmove((w), (p).y, (p).x)
/* _______________________ файл w.c _____________________________ */