Мир программирования

 


Найти: на:


Меню
Партнеры
Счетчики
Реклама

Техника программирования на Turbo C
Глава 4


Автор: Ал. Стивенс

Функции общего назначения

Эта книга посвящена программному обеспечению, и следующие разделы содержат набор инструментальных программных средств, которые могут быть использованы при создании прикладных систем. Эти инструментальные средства написаны на языке Си, транслируются с помощью компилятора Турбо Си и готовы к тому, чтобы быть включенными в ваши программы. Эти функции могут рассматриваться как расширения языка Си, если будут присоединены к и без того достаточно обширной библиотеке стандартных расширений Турбо Си. Настоящий раздел описывает функции первого уровня, которые необходимо включать в программы, использующие эти библиотеки. Представленные в данном разделе функции являются функциями общего назначения, выполняющими операции низкого уровня (специфическими для аппаратуры IBM PC) по управлению дисплеем и клавиатурой. Вы можете посчитать недостаточно обоснованным применение некоторых из этих функций в своих программах. Назначением этих функций является поддержка функций библиотеки высокого уровня, также рассматриваемых в этой книге. В этом смысле они полезны, и вы можете найти для них применение. Кроме того, глубина вашего понимания функций, представленных в книге, зависит от осмысления вами всех функций, в том числе и тех, которые вы не будете использовать в своих программах.

При чтении описаний этих функций обращайтесь к листингу 4.1 программы ibmpc.c, который приводится после описаний. void clear_screen()

Эта функция очищает экран и устанавливает курсор в левый верхний угол. Экран заполняется символами пробела, и атрибуты символов извлекаются из символьной переменной attrib, описанной в программе ibmpc.c. Значение этого атрибута соответствует байту атрибута в видеопамяти, сопутствующему каждому байту ASCII-кода при записи символа в видеопамять. Более подробная информация по этому вопросу содержится в разделе 5. Переменная attrib принимает значение, которое соответствует установке черного цвета для фона символа и белого цвета для самого символа. Если вы желаете другое значение атрибута, то должны изменить значение этой переменной перед вызовом функции clear_screen.

int vmode()

Эта функция возвращает код текущего режима системы формирования изображения. Она прeжде всего предназначена для определения того, как программе интерпретировать содержимое видеопамяти: как содержимое видеопамяти в монохромном режиме или в алфавитно-цифровом режиме для Цветного Графического Адаптера (CGA) и для Усовершенствованного Графического Адаптера (EGA). Эти устройства более подробно рассматриваются в разделе 5. Функция vmode возвращает код 7, если IBM PC работает в монохромном режиме. Любое другое значение обозначает алфавитно-цифровой режим для контроллеров CGA и EGA.

void cursor(int x,int y)

Эта функция устанавливает курсор в позицию на экране, определяемую координатами X и Y. Координаты (0,0) соответствуют левому верхнему углу экрана. Значение координаты X изменяется в диапазоне от 0 до 79, а координаты Y - в диапазоне от 0 до 24.

void curr_cursor(int *x, int *y)

Эта функция считывает текущее положение курсора и записывает значения координат X и Y в адреса памяти, определяемые с помощью указателей перед обращением к функции.

int set_cursor_type(int t)

Эта функция устанавливает текущий размер курсора, интерпретируемый программами из этой книги как тип курсора. Размер обозначается целочисленной переменной, которая содержит в старшем байте номер начальной растровой линии курсора и в младшем байте - номер конечной растровой линии курсора.

Редактор текстов и программа ввода данных, представленные в следующих разделах, используют возможность изменения размера курсора для обозначения того, какой из режимов установлен: Вставки или Замены. Курсор прямоугольной формы обозначает, что установлен режим Вставки, он определяется значением переменной, равным 0x0106. При этом курсор занимает растровые линии с 1 по 6 того знакоместа, в котором он находится. Курсор в виде знака подчеркивания обозначает режим Замены и определяется значением переменной, равным 0x0607. При этом курсор занимает растровые линии 6 и 7 знакоместа.

int get_char()

Эта функция является очень важной, так как выполняет несколько крайне необходимых действий в вызывающих ее программах. get_char принимает поступающий от клавиатуры символ путем использования программ ROM-BIOS IBM PC. Ее главное назначение состоит в приеме одиночного символа от клавиатуры без эха, без преобразования и без обращения к функциям DOS. Кроме того, она выполняет следующие дополнительные функции.В то время, как система ожидает нажатия клавиши, функция get _char вызывает программные прерывания по вектору 0x28, так называемые прерывания DOSOK. Это прерывание и его значение для создания резидентных утилит более подробно рассматриваются в разделе 11.

Когда вы нажимаете функциональную клавишу, ROM BIOS возвращает двубайтный код. Первый байт имеет нулевое значение и обозначает, что следующий за ним код символа соответствует функциональной клавише. Этот второй байт содержит 7-битный ASCII- код, который является уникальным для каждой функциональной клавиши. Eсли не учитывать первый нулевой байт, то реакция на нажатие функциональных клавиш сходна с реакцией на нажатие клавиш, соответствующих ASCII-символам, в частности, буквам. Функция get_char преобразует двубайтную последовательность, возвращаемую ROM-BIOS в ответ на нажатие функциональной клавиши, в 8-битный код, позволяющий отличать функциональные клавиши от нефункциональных. Функция осуществляет это преобразование путем установки старшего разряда в байте, содержащем АSCII-код символа и следующем за нулевым байтом. Формируемые коды описыватся в исходном файле keys.h как глобальные символы (см. листинг 4.2).

Функция get_char oжидает нажатия функциональной клавиши, обозначенной Help. Код, соответствующий функциональной клавише Help, присвоен целочисленной глобальной переменной, названной helpkey. Первоначально этой переменной присваивается нулевое значение, но программные средства, которые работают с окном Help, предназначенным для отображения справочной информациии, будут присваивать этой переменной значение, соответствующее функциональной клавише. При нажатии функциональной клавиши Help функция get_char проверяет значение глобального указателя функций, названного helpfunc. Если указатель имеет ненулевое значение, то функция get_char вызывает адресуемую с помощью указателя helpfunc функцию выдачи справочной информации.

void vpoke(unsigned vseg,unsigned adr,unsigned chr) int
vpeek (unsigned vseg,unsigned adr)

Эти две функции считывают из видеопамяти коды символов и атрибуты символов и записывают их в видеопамять. Для того, чтобы использовать эти функции, вы должны разобраться в организации видеопамяти IBM PC, а также принципах формирования изображения. В тело функций vpoke и vpeek включены фрагменты на ассемблере. Для того, чтобы оттранслировать эти функции, вы должны иметь программу Macro Assembler (MASM) фирмы Microsoft, поскольку именно она используется в Турбо Си для трансляции ассемблерных фрагментов. Включение ассемблерных фрагментов необходимо только в том случае, если ваши программы работают в системах, использущих Цветной Графический Адаптер (CGA) или совместимый с ним адаптер. Смысл этого требования разъясняется в разделе 5. Если у вас нет контроллера CGA или если вы хотите работать с функциями, не используя ассемблер, то удалите эти функции из исходного модуля ibmpc.c и вставьте в файл twindow.h из раздела 6 следующие операторы:

#define vpoke(vseg,adr,chr) poke(vseg,adr,chr)
#define vpeek(vseg,adr) peek(vseg,adr)

Эти макроопределения заменят функции vpoke и vpeek и избавят от необходимости использования макроассемблера для функций работы с окнами из этой книги.

Исходные модули функций общего назначения

Листинг 4.1 представляет собой исходный текст программы ibmpc.c, которая содержит функции, описанные в данном разделе. Вследствие того, что функции включают фрагменты на ассемблере, программу лучше транслировать с помощью командного компилятора tcc, а не компилятора tc Интегрированной Среды.Чтобы оттранслировать файл ibmpc.c, введите следующую команду (не набирая промптер С>):

С>tcc -c ibmpc

Листинг 4.1: ibmpc.c

/* ibmpc.c */
/* Функции нижнего уровня, обращающиеся к BIOS и аппаратным
средствам РС */

#pragma inline #include <dos.h> static union REGS rg;

/* позиция курсора */

void cursor(int x,int y) {
rg.x.ax = 0x0200;
rg.x.bx = 0;
rg.x.dx = ((y << 8) & 0xff00) + x;
int86( 16, &rg, &rg);
}

/* возвратить позицию курсора */

void curr_cursor( int *x, int *y )
{
rg.x.ax = 0x0300;
rg.x.bx = 0;
int86( 16, &rg, &rg );
*x = rg.h.dl;
*y = rg.h.dh;
}

/* установить тип курсора */

void set_cursor_type( int t )
{
rg.x.ax = 0x0100;
rg.x.bx = 0;
rg.x.cx = t;
int86( 16, &rg, &rg );
}
char attrib = 7;

/* очистить экран */

void clear_screen()
{
cursor(0, 0);
rg.h.al = ' ';
rg.h.ah = 9;
rg.x.bx = attrib;
rg.x.cx = 2000;
int86( 16, &rg, &rg );
}

/* возвратить режим работы видеоконтроллера*/

int vmode()
{
rg.h.ah = 15;
int86( 16, &rg, &rg);
return rg.h.al;
}

/* проверить клавишу Scroll Lock */

int scroll_lock()
{
rg.x.ax = 0x0200;
int86( 0x16, &rg, &rg);
return rg.h.al & 0x10;
}
void (* helpfunc)();
int helpkey = 0;
int helping = 0;

/* принять символ от клавиатуры */

int get_char()
{
int c;
while (1) {
rg.h.ah = 1;
int86(0x16, &rg, &rg);
if (rg.x.flags & 0x40) {
int86(0x28, &rg, &rg);
continue;
}
rg.h.ah = 0;
int86(0x16, &rg, &rg);
if (rg.h.al == 0)
c = rg.h.ah | 128;
else
c = rg.h.al;
if (c == helpkey && helpfunc) {
if (!helping) {
helping = 1;
(*helpfunc)();
helping = 0;
continue;
}
}
break;
}
return c;
}

/* занести код символа и его атрибуты в видеопамять */

void vroke(unsigned vseg, unsigned adr, unsigned chr)
{
if (vseg == 45056)
/* монохромный режим */
poke(vseg, adr, chr);
else {
_DI = adr;
/* смещение до адреса символа в видеопамяти */
_ES = vseg; /* адрес сегмента видеопамяти */
asm cld;
_BX = chr;
/* атрибуты и код символа */
_DX = 986; /* состояние видеопорта */

/* ждать начала обратного хода луча*/

do
asm in al,dx;
while (_AL & 1);

/* ждать завершения обратного хода луча */

do
asm in al,dx;
while (!(_AL & 1));
_AL = _BL;
asm stosb;
/* запомнить символ */

/* ждать начала обратного хода луча */

do
asm in al,dx;
while (_AL & 1);

/* ждать завершения обратнога хода луча */

do
asm in al,dx;
while (!(_AL & 1));
_AL = _BL;
asm stosb;
/* запомнить атрибуты */
}
}

/* считать код символа и его атрибуты из видеопамяти */

int vpeek(unsigned vseg, unsigned adr)
{
int ch, at;
if (vseg == 45056)
/* монохромный режим */
return peek(vseg, adr);
asm push ds;
_DX = 986;
/* состояние видеопорта */
_DS = vseg; /* адрес сегмента видеопамяти */
_SI = adr;/* смещение до адреса символа в видеопамяти */
asm cld;

/* ждать начала обратного хода луча */

do
asm in al,dx;
while (_AL & 1);

/* ждать завершения обратного хода луча */

do
asm in al,dx;
while (!(_AL & 1));
asm lodsb; /* считать символ */
_BL = _AL;

/* ждать начала обратного хода луча */

do
asm in al,dx;
while (_AL & 1);

/* ждать завершения обратного хода луча */

do
asm in al,dx;
while (!(_AL & 1));
asm lodsb;
/* считать атрибут */
_BH = _AL;
_AX = _BX;
asm pop ds;
return _AX;
}

/* keys.h */

#define HT 9
#define RUBOUT 8
#define BELL 7
#define ESC 27
#define SHIFT_HT 143
#define CTRL_T 20
#define CTRL_B 2
#define CTRL_D 4
#define ALT_D 160

#define F1 187
#define F2 188
#define F3 189
#define F4 190
#define F5 191
#define F6 192
#define F7 193
#define F8 194
#define F9 195
#define F10 196

#define HOME 199
#define UP 200
#define PGUP 201
#define BS 203
#define FWD 205
#define END 207
#define DN 208
#define PGDN 209
#define INS 210
#define DEL 211

#define CTRL_HOME 247
#define CTRL_BS 243
#define CTRL_FWD 244
#define CTRL_END 245

Заключение

На основе представленных выше функций нижнего уровня в разделе 5 будет развиваться и объясняться концепция экранных окон, которая составляет следующий, более высокий, уровень в многоуровневом наборе функций, описываемых в данной книге.



Опрос

Конкурсы
Реклама

 

Web дизайн: Бурлаков Михаил    

Web программирование: Бурлаков Михаил

Используются технологии uCoz