static void right_justify(char *s)
{
int len;
len = strlen(s);
while (*s == ' ' || *s == '0' && len) {
len--;
*s++ = ' ';
}
if (len)
while (*(s+(len-1)) == ' ') {
movmem (s, s+1, len-1);
*s = ' ';
}
}
/*-----------выравнивание вправо, заполнение нулями----------*/
static void right_justify_zero_fill(char *s)
{
int len;
if (spaces(s))
return;
len = strlen(s);
while (*(s + len - 1) == ' ') {
movmem(s, s + 1, len-1);
*s = '0';
}
}
/*---------------контроль пробелов-------------*/
int spaces(char *c)
{
while (*c == ' ')
c++;
return !*c;
}
/*----------------проверка даты---------------------*/
static int validate_date(char *s)
{
static int days [] =
{ 31,28,31,30,31,30,31,31,30,31,30,31 };
char date [7];
int mo;
strcpy(date, s);
if (spaces(date))
return OK;
days[1] = (atoi(date+4)%4) ? 28 : 29;
*(date + 4) = '\0';
mo = atoi(date+2);
*(date+2) = '\0';
if (mo && mo<13 && atoi(date) && atoi(date)<=days[mo-1])
return OK;
error_message("Invalid date");
return ERROR;
}
/*---------Процесс ввода данных в шаблон экрана-----------*/
int data_entry(WINDOW *wnd)
{
FIELD *fld;
int exitcode, isvalid, done=FALSE, oldhelpkey=helpkey;
field_tally(wnd);
fld = FHEAD;
/*--накопление данных, поступающих с клавиатуры на экране --*/
while (fld != NULL && done == FALSE) {
set_help(fld->fhwin, fld->flx, fld->fly);
helpkey = (fld->fhelp) ? 0 : oldhelpkey;
wcursor(wnd, fld->fcol, fld->frow);
if (fld->fprot ==FALSE) {
reverse_video(wnd);
data_value(wnd, fld);
wcursor(wnd, fld->fcol, fld->frow);
exitcode = read_field(wnd, fld);
isvalid = (exitcode != ESC && fld->fvalid) ?
(*(fld->fvalid))(fld->fbuff) : OK;
}
else {
exitcode = FWD;
isvalid = OK;
}
if (isvalid == OK) {
normal_vileo(wnd);
data_value(wnd, fld);
switch (exitcode) { /* передано редактору */
case F1: if (fld->fhelp) {
(*(fld->fhelp))(fld->fbuff);
data_value(wnd, fld);
}
break;
case DN:
case '\r':
case '\t':
case FWD: fld = fld->fnxt;
if (fld == NULL)
fld = FHEAD;
break;
case UP:
case BS: fld = fld->fprv;
if (fld == NULL)
fld = FTAIL;
break;
default: done = endstroke(exitcode);
break;
}
}
}
helpkey = oldhelpkey;
return (exitcode);
}
/*-------- отображение приглашения к вводу---------*/
void wprompt(WINDOW *wnd, int x, int y, char *s)
{
wcursor(wnd, x, y);
wprintf(wnd, s);
}
Описание программы: entry.c
-----------------------------------------------------------------
Макроопределение FIELDCHAR программы entry.c идентифицирует
специальные символы, используемые в символьной маске поля при
определении байтов данных. По сути дела, идентифицированные с
помощью FIELDCHAR символы не являются символами в смысле данных,
так как используются в маске. В качестве значения FIELDCHAR
выступает символ нижнего подчеркивания. Вы можете изменить
определение FIELDCHAR, используя другие символы.
Привязка полей к окнам осуществляется с помощью двойного
связного списка. Список начинается и заканчивается в структуре
WINDOW для поля. Каждое поле представлено посредством структуры
FIELD, которая размещается в памяти при установке поля.
Функция init_template используется для инициализации окна с
шаблоном ввода данных. Она выполняет трассировку связного списка
FIELD и освобождает некоторые размещенные ранее в памяти
структуры FIELD.
Функция establish_field размещает в памяти и инициализирует
буфер FIELD, используя передаваемые ей при обращении значения или
принимая значения передаваемых переменных по умолчанию. Маска,
позиция размещения поля, адрес буфера и тип данных поля
передаются функции при обращении к ней. Очередная структура FIELD
добавляется в конец соответствующего связного списка FIELD,
специфицированного WINDOW. Указатель на очередную структуру FIELD
возвращается в точку вызова функции.
Функция addfield вызывается для добавления структуры FIELD к
связному списку, специфицированному WINDOW.
Функция disp_field используется для вывода значений данных,
введенных в поля, из буфера на экран дисплея. Маска данных,
передаваемая при обращении к функции, используется при
отображении содержимого поля. Обращение к функции содержит
WINDOW, указатель буфера поля и указатель маски. Подразумевается,
что курсор в окне всегда устанавливается на первую позицию
первого поля окна. Символы, хранящиеся в буфере, отображаются на
экране вместе с символами пунктуации, составляющими маску поля.
Функция data_value предназначается для отображения текущего
значения поля в окне. Функция устанавливает курсор в окне в
позицию первого символа поля и вызывает функцию disp_field,
передавая ей адрес WINDOW и адреса буфера поля и маски.
Функция field_fally используется для выдачи на экран
значений всех полей шаблона. Она осуществляет просмотр
"сверху-вниз" связного списка FIELD и осуществляет обращение к
функции data_value для каждого поля шаблона.
Функция field_window предназначена для установки оконной
help-информации для поля. Указанные при обращении к функции имя
help-информации и координаты экрана для ее выдачи копируются в
специфицированную при вызове функции структуру FIELD.
Функция clear_template обрабатывает "сверху-вниз" связной
список FIELD для специфицированного окна. Функция преобразует
буфер каждого поля шаблона в пустую строку, заканчивающуюся
нулевым символом, используя маску поля для определения
установленной при описании поля длины. Когда все поля обработаны
таким образом (почищены), функция обращается к field_fally.
Программа ввода данных работает в режимах вставки и замены
символов. Клавиша <ВСТ> () используется для переключения
режимов работы программы, а переменная insert_mode служит для
индикации текущего режима работы. Функция insert_status изменяет
тип курсора в соответствии со значением переменной insert_mode.
Режим вставки обуславливает наличие квадратного курсора, а режим
замены символов - наличие курсора в виде нижнего подчеркивания.
Для изменения формы курсора используется функция set_cursor_type
из библиотеки ibmpc.c (см. Главу 4).
Функция read_field используется для чтения введенных
пользователем в поля данных. Она устанавливает курсор в начало
поля и считывает последовательность символов в нем. Два локальных
указателя используются для трассировки вводимых данных. Указатель
mask позволяет получить текущую позицию в маске, а указатель buff
- текущую позицию в буфере. При перемещении пользователем
курсора, уничтожении или вводе символов значение этих указателей
корректируется.
При выполнении операции по уничтожению символов используется
функция Турбо Си movmem, которая используется для сдвига символов
в буфере, а также функция disp_field для отображения результатов
операции на экране.
Клавиша <ВСТ> () переключает режимы Вставки/Замены.
Если текущее поле включает в себя точку (.), то оно содержит
нули в двух крайних правых позициях (если другие значения в них
не указаны), выравнено вправо, а соответствующие указатели и
курсор устанавливаются на значащие позиции, предназначенные для
указания пенни (денежной единицы).
Если пользователь нажал клавишу, символизирующую завершение
ввода данных, то данная ситуация обрабатывается функцией
endstroke, и ввод данных завершается. В противном случае символ
будет записан в буфер. Если в данный момент обрабатывалось не
алфавитно-цифровое поле, то анализируется ситуация на предмет
ввода пользователем числа. Если было введено не число, то
выдается сообщение об ошибке, и программа не воспринимает
введенные данные, требуя их повторного ввода. Если включен режим
вставки, то данные в буфере смещаются на одну позицию вправо, а
значение поля после вставки символа отображается с помощью
функции disp_field. При этом символ записывается в буфер и
отображается на экране. Совместное использование указателей маски
и буфера позволяет "перескакивать" через символы пунктуации.
После ввода последнего символа в поле дальнейший ввод данных в
него прекращается.
После завершения ввода данные проверяются на допустимость,
даты и числа выравниваются, курсор устанавливается в
соответствующую позицию поля и содержимое полей отображается на
экране.
Функция endstroke анализирует значение клавиш и
устанавливает клавиши, которые могут привести к завершению
процесса ввода данных.
Есть две функции, занимающиеся выравниванием данных. Первая
- right_justify, выравнивающая справа и заполняющая поле
пробелами. Вторая - right_justify_zero_fill, выравнивающая справа
и заполняющая поле нулями.
Функция spaces анализирует поле на наличие всех пробелов.
Функция validate_date осуществляет проверку даты.
Функция data_entry вызывается для обработки всех полей
шаблона. Функция вызывает field_fally для выдачи на экран всех
значений данных из соответствующих буферов полей. Затем функция
обрабатывает "сверху-вниз" связный список структур FIELD и
управляет вводом данных в каждом поле.
Функция set_help вызывается для осуществления привязки
оконной help-информации к конкретному полю. Поскольку значение
глобальной переменной helpkey определено заранее, то попытка
получить для этого поля специальную help-информацию закончится
безуспешно, поскольку программа data_entry будет перехватывать
прерывание от клавиши help-функции.
Если поле не является защищенным, то функция reverse_video
вызывается каждый раз, когда необходимо получить выделенное
отображение поля в соответствии с конфигурацией цветов,
определенной параметром ACCENT. Для выдачи на экран значения
текущего поля в акцентированном режиме, определяемом параметром
ACCENT, используется функция data_value, а для ввода в программу
введенных в поле пользователем данных применяется функция
read_field. Значением, возвращаемым функцией read_field, является
итоговая последовательность символов, суть которой - введенные в
поле данные. Если поле имеет свою специальную функцию контроля
данных, то вызывается эта функция.
При условии, что контроль данных по всем параметрам прошел
нормально, функция normal_video переводит окно в так называемый
контрольный режим отображения данных, цвет которого определяется
значением NORMAL, и функция data_value повторно выводит на экран
значение поля, но уже в NORMAL-цвете. Затем анализируется
завершающая последовательность нажатия клавиш. Если ввод данных
прерван клавишей, закрепленной за вызовом специальной