Техника программирования на турбо-С
#include
#include
#include
#include
#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 (c) {
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 (c) {
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(c) ||
*(keys+ky)==tolower(c))
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));
}
/* видеофункции низкого уровня */
/* обменивает содержимое видеообраза и буфера сохранения */