Жанр: Учеба
Техника программирования на турбо-С
...--------------
Эта функция перемещает окно в самое переднее положение
относительно других окон. Окно, если оно видимо, отображается
поверх остальных. Используйте эту функцию только для слоеных
окон.
void rear_window(WINDOW *wnd)
-----------------------------
Эта функция перемещает окно в самое заднее положение
относительно других окон. Окно, если оно видимо, отображается под
всеми остальными. Используйте эту функцию только для слоеных
окон.
int get_selection(WINDOW *wnd, int sel, char *keys)
---------------------------------------------------
Эта функция позволяет использовать окно в качестве меню. Вы
должны создать окно и записать в него несколько строк текста,
скажем, функцией wprintf. Вы можете использовать set_colors для
установки значений цветов ACCENT в окне (по умолчанию - черные
буквы на белом фоне). Затем вы вызываете get_selection. Функция
использует окно в качестве меню, каждая строка которого
представляет альтернативу выбора. Альтернативы подсвечиваются
цветом ACCENT. Целочисленное значение sel используется для
первоначального размещения яркого блока курсора меню на одной из
альтернатив. Значение 1 соответствует первой альтернативе, 2 -
второй и т.д.
Пользователь может перемещать блок меню вверх и вниз
клавишами управления курсором и производить выбор в меню клавишей
"Ввод". Клавиша "Ключ" применяется для выхода из этого процесса.
Ссылка keys указывает на строку значений клавиш, которые
могут использоваться для выбора из меню. Некоторые системы меню
разрешают пользователю применять нажатия клавиш наряду с
перемещением блока курсора. Для выключения этой возможности
передайте параметру keys ссылку NULL.
Эта функция возвращает целочисленное значение, равное номеру
выбранной в меню альтернативы. Значение обычно равняется единице
и более, однако, если пользователь нажимает клавишу "Ключ",
функция возвращает нуль. Функция будет также возвращать значения
FWD или BS, если пользователь нажимает клавиши управления
курсором вправо или влево. Эти значения определены в keys.h.
void error_message(char *s)
---------------------------
Эта функция выдает сообщение об ошибке, указываемое ссылкой
s, и включает звуковой сигнал. Сообщение отображается в
окне в нижнем правом квадранте экрана. Сообщение остается на
экране после завершения функции.
void clear_message()
--------------------
Эта функция удаляет сообщение об ошибке, если оно было
выдано функцией error_message.
Листинги оконных функций
-----------------------------------------------------------------
Данные листинги содержат исходные файлы функций поддержки
окна. Приводятся два листинга: twindow.h и twindow.c. Каждый
листинг сопровождается описанием его содержания.
Исходный листинг: twindow.h
---------------------------
Листинг 6.1, twindow.h, определяет оконные структуры и
содержит прототипы для функций. Вы должны включать их в любую
исходную программу, которая использует оконные функции.
Листинг 6.1: twindow.h
/* twindow.h */
/* Выделите это определение из комментария для стековых окон,
* но не для слоеных окон.
*
* #define FASTWINDOWS
*
*/
/* window colors */
#define RED 4
#define GREEN 2
#define BLUE 1
#define WHITE (RED+GREEN+BLUE)
#define YELLOW (RED+GREEN)
#define AQUA (GREEN+BLUE)
#define MAGENTA (RED+BLUE)
#define BLACK 0
#define BRIGHT 8
#define DIM 0
#define BORDER 0
#define TITLE 1
#define ACCENT 2
#define NORMAL 3
#define ALL 4
#define TRUE 1
#define FALSE 0
#define ERROR -1
#define OK 0
/* оконные управляющие структуры */
typedef struct field { /* описание поля ввода данных */
char *fmask; /* маска поля ввода данных */
int fprot; /* защита поля */
char *fbuff; /* буфер поля */
int ftype; /* тип поля */
int from; /* строка поля */
int fcol; /* столбец поля */
void (*fhelp)(); /* функция подсказки поля */
char *fhwin; /* функция подсказки окна */
int flx, fly; /* расположение подсказки окна */
int (*fvalid)(); /* функция заполнения поля */
struct field *fnxt; /* следующее поле выдачи */
struct field *fprv; /* предыдущее поле выдачи */
} FIELD;
typedef struct _wnd {
int _wv; /* истина, если окно видимо */
int _hd; /* истина, если окно скрыто */
char *_ws; /* указывает на блок сохранения окна */
char *_tl; /* указывает на заголовок окна */
int _wx; /* nv x координата */
int _wy; /* nv y координата */
int _ww; /* ширина окна */
int _wh; /* высота окна */
int _wsp; /* указатель прокрутки */
int _sp; /* указатель выбора */
int _cr; /* позиция х курсора */
int btype; /* тип рамки */
int wcolor[4]; /* цвета окна */
int _pn; /* предыдущий нормальный цвет */
struct _wnd *_nx; /* указывает на следующее окно */
struct _wnd *_pv; /* указывает на предыдущее окно */
FIELD *_fh; /* указывает на 1-е поле ввода данных */
FIELD *_ft; /* указывает на последнее поле ввода данных */
} WINDOW;
typedef struct w_menu {
char *mname;
char **mselcs;
void (**func)();
} MENU;
#define SAV (wnd-"_ws)
#define WTITLE (wnd-"_tl)
#define COL (wnd-"_wx)
#define ROW (wnd-"_wy)
#define WIDTH (wnd-"_ww)
#define HEIGHT (wnd-"_wh)
#define SCROLL (wnd-"_wsp)
#define SELECT (wnd-"_sp)
#define WCURS (wnd-"_cr)
#define WBORDER (wnd-"wcolor[BORDER])
#define WTITLEC (wnd-"wcolor[TITLE])
#define WACCENT (wnd-"wcolor[ACCENT])
#define WNORMAL (wnd-"wcolor[NORMAL])
#define PNORMAL (wnd-"_pn)
#define BTYPE (wnd-"btype)
#define NEXT (wnd-"_nx)
#define PREV (wnd-"_pv)
#define WCOLOR (wnd-"wcolor)
#define VISIBLE (wnd-"_wv)
#define HIDDEN (wnd-"_hd)
#define FHEAD (wnd-"_fh)
#define FTAIL (wnd-"_ft)
#define NW (wcs[wnd-"btype].nw)
#define NE (wcs[wnd-"btype].ne)
#define SE (wcs[wnd-"btype].se)
#define SW (wcs[wnd-"btype].sw)
#define SIDE (wcs[wnd-"btype].side)
#define LINE (wcs[wnd-"btype].line)
/* ПРОТОТИПЫ ФУНКЦИЙ И МАКРОСЫ */
/* общецелевые функции и макросы */
void clear_screen(void);
int vmode(void);
void cursor(int, int);
void curr_cursor(int *, int *);
int cursor_type(void);
void set_cursor_type(int);
int get_char(void);
int scroll_lock(void);
void vpoke(unsigned, unsigned, unsigned);
int vpeek(unsigned, unsigned);
/* оконные функции и макросы */
WINDOW *establish_window(int, int, int, int);
void set_border(WINDOW *, int);
void set_colors(WINDOW *, int, int, int, int);
void set_intensity(WINDOW *, int);
void set_title(WINDOW *, char *);
void display_window(WINDOW *);
void delete_window(WINDOW *);
void clear_window(WINDOW *);
void hide_window(WINDOW *);
void wprintf(WINDOW *, char *, ...);
void wputchar(WINDOW *, int);
void close_all(void);
void wcursor(WINDOW *, int x, int y);
void error_message(char *);
void clear_message(void);
int get_selection(WINDOW *, int, char *);
#define reverse_video(wnd) wnd-"wcolor[3]=wnd-"wcolor[2]
#define normal_video(wnd) wnd-"wcolor[3]=wnd-"_pn
#define rmove_window(wnd,x,y) repos_wnd(wnd, x, y, 0)
#define move_window(wnd,x,y) repos_wnd(wnd, COL-x, ROW-y, 0)
#define forefront(wnd) repos_wnd(wnd, 0, 0, 1)
#define rear_window(wnd) repos_wnd(wnd, 0, 0, -1)
/* внутренние для оконных процессов */
void accent(WINDOW *);
void deaccent(WINDOW *);
void scroll(WINDOW *, int);
void repos_wnd(WINDOW *, int, int, int);
void acline(WINDOW *, int);
#define accent(wnd) acline(wnd, WACCENT)
#define deaccent(wnd) acline(wnd, WNORMAL)
#define clr(bg,fg,in) ((fg)|(bg""4)|(in))
#define vad(x,y) ((y)*160+(x)*2)
#ifdef FASTWINDOWS
#define cht(ch,at) (((ch)&255)|((at)""8))
#define displ(w,x,y,c,a) vpoke(VSG,vad(x+COL,y+ROW),cht(c,a))
#define dget(w,x,y) vpeek(VSG,vad(x+COL,y+ROW))
#define verify_wnd(w) (*(w)=listtail)!=0
#else
void displ(WINDOW *wnd, int x, int y, int ch, int at);
#endif
/* функция редактора */
void text_editor(WINDOW *, char *, unsigned);
/* функция меню */
void menu_select(char *name, MENU *mn);
/* функция подсказки */
void load_help(char *);
void set_help(char *, int, int);
/* функция ввода данных */
void init_template(WINDOW *);
FIELD *establish_field(WINDOW *, int, int, char *, char *, int);
void clear_template(WINDOW *);
void field_tally(WINDOW *);
int data_entry(WINDOW *);
void wprompt(WINDOW *, int, int, char *);
void error_message(char *);
void clear_notice(void);
void field_window(FIELD *, char *, int, int);
#define field_protect(f,s) f-"fprot=s
#define field_help(f,h) f-"fhelp=h
#define field_validate(f,v) f-"fvalid=v
Описание программы: twindow.h
-----------------------------------------------------------------
Глобальная переменная FASTWINDOWS определена внутри
комментария в представленной программе. Включение переменной
рассчитано на применение стековой оконной конфигурации. Без
изменений при компиляции будет принята слоеная оконная
конфигурация. Для компиляции стековой оконной системы необходимо
выделить оператор #define из комментария.
Структура FIELD используется для определения полей ввода
данных внутри области данных в окнах. Этот процесс описан в
Главе 8.
Структура WINDOW описывает окно для системы . Каждому окну
назначается одна структура этого типа.
Структура MENU используется программным обеспечением
оконных меню в Главе 10. Должен быть массив структур MENU с
одним элементом для каждого проталкиваемого вниз меню.
Список операторов #define используется для придания
операторам в twindow.c лучшей читаемости. Мнемонические имена
соответствуют элементам структуры WINDOW, указанной ссылкой
wnd. Все функции в twindow.c используют имя этой ссылки по
соглашению.
twindow.h содержит прототипы для всех оконных функций,
которые будут вызываться прикладными программами.
Исходный листинг: twindow.c.
----------------------------
Листинг 6.2 - это twindow.c. Он содержит все описанные
ранее в этой главе функции. Вы должны откомпилировать его и
связывать его объектный модуль с любой программой, которая
использует окна. Поскольку он вызывает функции из ibmpc.c, его
объектный модуль должен быть также включен в редактирование
связей.
Листинг 6-2: twindow.c
/* twindow.c */
#include "stdio.h"
#include "ctype.h"
#include "stdarg.h"
#include "dos.h"
#include "alloc.h"
#include "stdlib.h"
#include "string.h"
#include "twindow.h"
#include "keys.h"
#define TABS 4
#define SCRNHT 25
#define SCRNWIDTH 80
#define ON 1
#define OFF 0
#define ERROR -1
/* локальные прототипы */
redraw(WINDOW *wnd);
wframe(WINDOW *wnd);
dtitle(WINDOW *wnd);
int *waddr(WINDOW *wnd, int x, int y);
vswap(WINDOW *wnd);
vsave(WINDOW *wnd);
vrstr(WINDOW *wnd);
add_list(WINDOW *wnd);
beg_list(WINDOW *wnd);
remove_list(WINDOW *wnd);
insert_list(WINDOW *wl, WINDOW *w2);
#ifndef FASTWINDOWS
int dget(WINDOW *wnd, int x, int y);
verify_wnd(WINDOW **wl);
#endif
/* массив наборов символов рамки */
struct {
int nw, ne, se, sw, side, line;
} wcs[] = {
{218,191,217,192,179,196}, /* одинарная линия */
{201,187,188,200,186,205}, /* двойная линия */
{214,183,189,211,186,196}, /* одинарный верх, двойные бока */
{213,184,190,212,179,205}, /* двойной верх, одинарные бока */
{194,194,217,192,179,196}, /* выталкиваемое вниз меню */
};
/* голова и хвост связанного списка оконных структур */
WINDOW *listhead = NULL;
WINDOW *listtail = NULL;
int VSG; /* адрес видеосегмента */
/* создание нового окна */
WINDOW *establish_window(x, y, h, w)
{
WINDOW *wnd;
VSG = (vmode() == 7 ? 0xb000 : 0xb800);
if ((wnd = (WINDOW *) malloc(sizeof (WINDOW))) == NULL)
return NULL;
/* параметры ограничений */
WTITLE = "";
HEIGHT = min(h, SCRNHT);
WIDTH = min(w, SCRNWIDTH);
COL = max(0, min(x, SCRNWIDTH-WIDTH));
ROW = max(0, min(y, SCRNHT-HEIGHT));
WCURS = 0;
SCROLL = 0;
SELECT = 1;
BTYPE = 0;
VISIBLE = HIDDEN = 0;
PREV = NEXT = NULL;
FHEAD = FTAIL = NULL;
WBORDER=WNORMAL=PNORMAL=WTITLEC =
clr(BLACK, WHITE, BRIGHT);
WACCENT = clr(WHITE, BLACK, DIM);
if ((SAV = malloc(WIDTH * HEIGHT * 2)) == (char *) 0)
return NULL;
add_list(wnd);
#ifndef FASTWINDOWS
clear_window(wnd);
wframe(wnd);
#endif
return wnd;
}
/* установить рамку окна */
void set_border(WINDOW *wnd, int btype)
{
if (verify_wnd(&wnd)) {
BTYPE = btype;
redraw(wnd);
}
}
/* установить цвета */
void set_colors(WINDOW *wnd,int area, int bg, int fg, int inten)
{
if (vmode() == 7) {
if (bg != WHITE && bg != BLACK)
return;
if (fg != WHITE && fg != BLACK)
return;
}
if (verify_wnd(&wnd)) {
if (area == ALL)
while (area)
WCOLOR [--area] = clr(bg, fg, inten);
else
WCOLOR [area] = clr(bg, fg, inten);
redraw(wnd);
}
}
/* установить яркость окна */
void set_intensity(WINDOW *wnd, int inten)
{
int area = ALL;
if (verify_wnd(&wnd)) {
while (area) {
WCOLOR [--area] &= ~BRIGHT;
WCOLOR [area] |= inten;
}
redraw(wnd);
}
}
/* установить заголовок */
void set_title(WINDOW *wnd, char *title)
{
if (verify_wnd(&wnd)) {
WTITLE = title;
redraw(wnd);
}
}
/* перевыдать окно при изменении атрибута */
static redraw(WINDOW *wnd)
{
#ifndef FASTWINDOWS
int x, y, chat, atr;
for (y = 1; y " HEIGHT-1; y++)
for (x = 1; x " WIDTH-1; x++) {
chat = dget(wnd, x, y);
atr = (((chat""8)&255) ==
PNORMAL ? WNORMAL : WACCENT);
displ(wnd, x, y, chat&255, atr);
}
wframe(wnd);
#endif
PNORMAL = WNORMAL;
}
/* выдать созданное окно */
void display_window(WINDOW *wnd)
{
if (verify_wnd(&wnd) && !VISIBLE) {
VISIBLE = 1;
#ifdef FASTWINDOWS
if (HIDDEN) {
HIDDEN = 0;
vrstr(wnd);
}
else {
vsave(wnd);
clear_window(wnd);
wframe(wnd);
}
#else
vswap(wnd);
#endif
}
}
/* закрыть все окна */
void close_all()
{
WINDOW *sav, *wnd = listtail;
while (wnd) {
sav = PREV;
delete_window(wnd);
wnd = sav;
}
}
/* удалить окно */
void delete_window(WINDOW *wnd)
{
if (verify_wnd(&wnd)) {
hide_window(wnd);
free(SAV);
remove_list(wnd); /* удалить окно из списка */
free(wnd);
}
}
/* скрыть окно */
void hide_window(WINDOW *wnd)
{
if (verify_wnd(&wnd) && VISIBLE) {
#ifndef FASTWINDOWS
vswap(wnd);
#else
vrstr(wnd);
#endif
HIDDEN = 1;
VISIBLE = 0;
}
}
#ifndef FASTWINDOWS
/* перемещение окна в его 3-х мерном плане */
void repos_wnd(WINDOW *wnd, int x, int y, int z)
{
WINDOW *twnd;
int x1, y1, chat;
if (!verify_wnd(&wnd))
return;
twnd = establish_window(x+COL, y+ROW, HEIGHT, WIDTH);
twnd -" _tl = WTITLE;
twnd -" btype = BTYPE;
twnd -" wcolor[BORDER] = WBORDER;
twnd -" wcolor[TITLE] = WTITLEC;
twnd -" wcolor[ACCENT] = WACCENT;
twnd -" wcolor[NORMAL] = WNORMAL;
twnd -" _wsp = SCROLL;
twnd -" _cr = WCURS;
if (z != 1) {
remove_list(twnd);
if (z == 0)
insert_list(twnd, wnd);
else
beg_list(twnd);
}
for (y1 = 0; y1 " twnd-"_wh; y1++)
for (x1 = 0; x1 " twnd-"_ww; x1++) {
chat = dget(wnd, x1, y1);
displ(twnd, x1, y1, chat&255, (chat""8)&255);
}
twnd-"_wv = 1;
vswap(twnd);
hide_window(wnd);
free(SAV);
remove_list(wnd);
*wnd = *twnd;
insert_list(wnd, twnd);
remove_list(twnd);
free(twnd);
}
#endif
/* очистить область окна */
void clear_window(WINDOW *wnd)
{
register int x1, y1;
if (verify_wnd(&wnd))
for (y1 = 1; y1 " HEIGHT-1; y1++)
for (x1 = 1; x1 " WIDTH-1; x1++)
displ(wnd,x1, y1, ' ', WNORMAL);
}
/* изобразить окно */
static wframe(WINDOW *wnd)
{
register int x1, y1;
if (!verify_wnd(&wnd))
return;
/* заголовок окна */
displ(wnd,0, 0, NW, WBORDER);
dtitle(wnd);
displ(wnd,WIDTH-1, 0, NE, WBORDER);
/* боковые стороны окна */
for (y1 = 1; y1 " HEIGHT-1; y1++) {
displ(wnd,0, y1, SIDE, WBORDER);
displ(wnd,WIDTH-1, y1, SIDE, WBORDER);
}
/* низ окна */
displ(wnd,0, y1, SW, WBORDER);
for (x1 = 1; x1 " WIDTH-1; x1++)
displ(wnd,x1, y1, LINE, WBORDER);
displ(wnd,x1, y1, SE, WBORDER);
}
/* выдать заголовок окна */
static dtitle(WINDOW *wnd)
{
int x1 = 1, i, ln;
char *s = WTITLE;
if (!verify_wnd(&wnd))
return;
if (s) {
ln = strlen(s);
if (ln " WIDTH-2)
i = 0;
else
i = ((WIDTH-2-ln) / 2);
if (i " 0)
while (i--)
displ(wnd, x1++, 0, LINE, WBORDER);
while (*s && x1 " WIDTH-1)
displ(wnd, x1++, 0, *s++, WTITLEC);
}
while (x1 " WIDTH-1)
displ(wnd, x1++, 0, LINE, WBORDER);
}
/* оконно-ориентированная printf */
void wprintf(WINDOW *wnd, char *ln, ...)
{
char dlin [100], *dl = dlin;
if (verify_wnd(&wnd)) {
va_list ap;
va_start(ap, ln);
vsprintf(dlin, ln, ap);
va_end(ap);
while (*dl)
wputchar(wnd, *dl++);
}
}
/* записать символ в окно */
void wputchar(WINDOW *wnd, int c)
{
if (!verify_wnd(&wnd))
return;
switch © {
case '\n':
if (SCROLL == HEIGHT-3)
scroll(wnd, UP);
else
SCROLL++;
WCURS = 0;
break;
case '\t':
do displ(wnd,(WCURS++)+3,SCROLL+1,'',WNORMAL);
while ((WCURS%TABS) && (WCURS+1) " WIDTH-1);
break;
default: ;
if ((WCURS+1) " WIDTH-1) {
displ(wnd, WCURS+1, SCROLL+1, c, WNORMAL);
WCURS++;
}
break;
}
}
/* установить курсор окна */
void wcursor(WINDOW *wnd, int x, int y)
{
if (verify_wnd(&wnd) && x " WIDTH-1 && y " HEIGHT-1) {
WCURS = x;
SCROLL = y;
cursor(COL+x+1, ROW+y+1);
}
}
/* позволяет пользователю произвести оконный выбор */
int get_selections(WINDOW *wnd, int s, char *keys)
{
int c = 0, ky;
if (!verify_wnd(&wnd))
return 0;
SELECT = s;
while (c != ESC && c != '\r' && c != BS && c != FWD) {
accent(wnd);
c = get_char();
deaccent(wnd);
switch © {
case UP: if (SELECT " 1)
SELECT--;
else
SELECT = SCROLL+1;
break;
case DN: if (SELECT " SCROLL+1)
SELECT++;
else
SELECT = 1;
break;
case '\r':
case ESC:
case FWD:
case BS: break;
default: if (keys) {
ky = 0;
while (*(keys + ky)) {
if (*(keys+ky)==toupper© ||
*(keys+ky)==tolower©)
return ky + 1;
ky++;
}
}
break;
}
}
return c == '\r' ? SELECT : c == ESC ? 0 : c;
}
union REGS rg;
/* прокручивает содержимое окна вверх или вниз */
void scroll(WINDOW *wnd, int dir)
{
int row = HEIGHT-1, col, chat;
if (!verify_wnd(&wnd))
return;
if (NEXT == NULL && HEIGHT " 3 && VISIBLE) {
rg.h.ah = dir == UP ? 6 : 7;
rg.h.al = 1;
rg.h.bh = WNORMAL;
rg.h.cl = COL + 1;
rg.h.ch = ROW + 1;
rg.h.dl = COL + WIDTH - 2;
rg.h.dh = ROW + HEIGHT - 2;
int86(16, &rg, &rg);
return;
}
if (dir == UP) {
for (row = 2; row " HEIGHT-1; row++)
for (col = 1; col " WIDTH-1; col++) {
chat = dget(wnd, col, row);
displ(wnd,col,row-1,chat&255,(chat""8)&255);
}
for (col = 1; col " WIDTH-1; col++)
displ(wnd, col, row-1, ' ', WNORMAL);
}
else {
for (row = HEIGHT-2; row " 1; --row)
for (col = 1; col " WIDTH-1; col++) {
chat = dget(wnd, col, row-1);
displ(wnd,col,row,chat&255,(chat""8)&255);
}
for (col = 1; col " WIDTH-1; col++)
displ(wnd, col, row, '', WNORMAL);
}
}
#ifndef FASTWINDOWS
/* вычисляет абрис отображаемого символа окна */
static int *waddr(WINDOW *wnd, int x, int y)
{
WINDOW *nxt = NEXT;
int *vp;
if (!VISIBLE)
return (int *) (SAV+y*(WIDTH*2)+x*2);
x += COL;
y += ROW;
while (nxt) {
if (nxt-"_wv)
if (x "= nxt-"_wx && x "= nxt-"_wx + nxt-"_ww-1)
if (y "= nxt-"_wy &&
y "= nxt-"_wy + nxt-"_wh-1) {
x -= nxt-"_wx;
y -= nxt-"_wy;
vp = (int *)
((nxt-"_ws) +y*(nxt-"_ww*2)+x*2);
return vp;
}
nxt = nxt-"_nx;
}
return NULL;
}
/* выдать символ в окно */
void displ(WINDOW *wnd, int x, int y, int ch, int at)
{
int *vp;
int vch = (ch&255)|(at""8);
if ((vp = waddr(wnd, x, y)) != NULL)
*vp = vch;
else
vpoke(VSG,vad(x+COL,y+ROW),vch);
}
/* получить отображенный символ из окна */
static int dget(WINDOW *wnd, int x, int y)
{
int *vp;
if ((vp = waddr(wnd, x, y)) != NULL)
return *vp;
return vpeek(VSG,vad(x+COL,y+ROW));
}
/* видеофункции низкого уровня */
/* обменивает содержимое видеообраза и буфера сохранения */
static vswap(WINDOW *wnd)
{
int x, y, chat;
int *bf = (int *) SAV;
for (y = 0; y " HEIGHT; y++)
for (x = 0; x " WIDTH; x++) {
chat = *bf;
*bf++ = dget(wnd, x, y);
displ(wnd, x, y, chat&255, (chat""8)&255);
}
}
#else
/* сохраняет видеопамять в буфере сохранения */
static vsave(WINDOW *wnd)
{
int x, y;
int *bf = (int *) SAV;
for (y = 0; y " HEIGHT; y++)
for (x = 0; x " WIDTH; x++)
*bf++ = vpeek(VSG, vad(x+COL, y+ROW));
}
/* восстанавливает видеопамять из буфера сохранения */
static vrstr(WINDOW *wnd)
{
int x, y;
int *bf = (int *) SAV;
for (y = 0; y " HEIGHT; y++)
for (x = 0; x " WIDTH; x++)
vpoke(VSG,vad(x+COL, y+ROW), *bf++);
}
#endif
/* заменяет яркость строки, указываемой SELECT */
void acline(WINDOW *wnd, int set)
{
int x, ch;
if (!verify_wnd(&wnd))
return;
for (x = 1; x " WIDTH - 1; x++) {
ch = dget(wnd, x, SELECT) & 255;
displ(wnd, x, SELECT, ch, set);
}
}
/* ФУНКЦИИ ОБРАБОТКИ СПИСКА */
/* добавляет окно в конец списка */
static add_list(WINDOW *wnd)
{
if (listtail) {
PREV = listtail;
listtail-"_nx = wnd;
}
listtail = wnd;
if (!listhead)
listhead = wnd;
}
/* добавляет окно в начало списка */
static beg_list(WINDOW *wnd)
{
if (listhead) {
NEXT = listhead;
listhead-"_pv = wnd;
}
listhead = wnd;
if (!listtail)
listtail = wnd;
}
/* удаляет окно из списка */
static remove_list(WINDOW *wnd)
{
if (NEXT)
NEXT-"_pv = PREV;
if (PREV)
PREV-"_nx = NEXT;
if (listhead == wnd)
listhead = NEXT;
if (listtail == wnd)
listtail = PREV;
NEXT = PREV = NULL;
}
/* вставляет w 1 после w 2 */
static insert_list(WINDOW *w1, WINDOW *w2)
{
w1-"_pv = w2;
w1-"_nx = w2-"_nx;
w2-"_nx = w1;
if (w1-"_nx == NULL)
listtail = w1;
else
w1-"_nx-"_pv = w1;
}
#ifndef FASTWINDOWS
/* проверяет наличие окна в списке */
static verify_wnd(WINDOW **w1)
{
WINDOW *wnd;
wnd = listhead;
if (*w1 == NULL)
*w1 = listtail;
else {
while (wnd != NULL) {
if (*w1 == wnd)
break;
wnd = NEXT;
}
}
return wnd != NULL;
}
#endif
WINDOW *ewnd = NULL;
/* сообщение об ошибках */
void error_message(char *s)
{
ewnd = establish_window(50, 22, 3, max(10, strlen(s)+2));
set_colors(ewnd, ALL, RED, YELLOW, BRIGHT);
set_title(ewnd, " ERROR! ");
display_window(ewnd);
wprintf(ewnd, s);
putchar(BELL);
}
void clear_message()
{
if (ewnd)
delete_window(ewnd);
ewnd = NULL;
}
Описание программы: twindow.c
-----------------------------
Далее описывается исходная программа twindow.c. Для каждой
функции описывается, что она делает и как работает. Программист
может использовать эти описания для понимания текста программы.
Объявления внешних данных в twindow.c включают прототипы для
каждой функции, локальные в исходном файле, массив структур для
определения пяти типов рамки окна, головной и хвостовой указатели
для списка структур WINDOW.
Рамка окна управляется элементом структуры WINDOW, которая
устанавливает окно. Этот элемент является целочисленным смещением
в таблице типов рамки. Вход, на который указывает смещение,
содержит шесть значений, каждое из которых представляет одну из
сторон или узлов окна. Первое значение определяет верхний левый
или северо-западный угол. Имя переменной (nw, ne, se, sw)
сообщает вам, какой угол определяется. Целое число side
относится к вертикальным сторонам рамки; целое число line
соответствует верхней и нижней горизонтальным линиям рамки.
Значения относятся к символам из набора графических символов
ПЭВМ.
Две WINDOW-ссылки listhead и listtail являются головным и
хвостовым указателями для списка окон. Когда создаются окна, они
добавляются к этому списку. Первоначально эти два указателя равны
NULL. Когда создается первое окно, выделяется память для
структуры WINDOW, и ее адрес копируется в оба указателя. У списка
имеется голова, указывающая на первое окно списка, и хвост,
указывающий на последнее. Когда создается второе окно, его адрес
копируется в хвостовой указатель. Кроме того, адрес второго окна
записывается в указатель _nx в первой структуре WINDOW, а адрес
первой записывается в указатель _pv второй. Голова списка
указывает на первое окно, которое указывает на второе и т.д.
Хвост списка указывает на последнее окно. Каждое окно также
указывает на своего предшественника в цепи, следовательно, список
является двунаправленной структурой данных, называемой двусвязным
списком. (Для знакомства со списковыми структурами данных см.:
Brady. С Development Tools for the IBM PC. - 1986.).
Функция establish_window инициализирует переменную VSG
адресом сегмента видеопамяти. Функция распределяет память для
структуры WINDOW и инициализирует эту структуру оконными
характеристиками, принимаемыми по умолчанию, а также размером и
координатами, заданными при вызове функции. Она выделяет память
для буфера сохранения видеопамяти и записывает адрес буфера в
структуру WINDOW. После инициализации структуры
...Поділитися у соцмережах