#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//==== Работа с "собранным файлом"
//#include <sys\stat.h>
//====
// цвет фона
#define colorfon
BLACK
// цвет текста
#define colortxt
LIGHTGRAY
// цвет выделенной
строки в меню
#define color2 CYAN
// цвет строки поддсказки
#define color1 RED
// цвет
"тела" меню
#define colormenu
YELLOW
// стартовая позиция на экране
#define str_begin
1
#define row_begin
1
// максимальная длина строк - вопрос/вариант ответа
#define l_str_max
30
// максимальное количество строк вопроса
#define k_str_max
5
// структура констант текстового режима
struct
text_info ti;
// запрос текущего текстового режима заполнение структуры ti
int help_txt(void);
// программа "диалог"
int step_d( char *);
// очистить экран
void clear(void);
// вывод в "нормальном" цвете
void n_cputs(int, int, char
*);
// вывод в "подсвеченном" цвете
void v_cputs(int, int, char
*);
// вывод в "СПРАВОЧНОМ" цвете
void s_cputs(int, int, char
*);
// вывод в справочном
цвете с "закраской" всей строки вывода
void h_cputs(int, int, char
*);
// модель функциональных частей
int fun_fun(int);
// чтение данных из файла - читается Запись, но возращается С строка в buf
// длиной не более l_str_max из файла h
// в конце файла возращается NULL
char * mfgets(char *, int, FILE * );
char * mfgets( char* buf,
int l_str, FILE* h)
{
char
c;
int
l=0, buf_l=0;
c=fgetc(h);
if
(c == EOF ) return NULL;
while
( (c != '\n') && (c != '\r') && (c != EOF) )
{
if ( (l++)
< (l_str-1) ) buf[buf_l++]=c;
c=fgetc(h);
};
buf[buf_l]='\0';
return
buf;
};
//=========================================================
// модель функциональных частей -----начало программы
int fun_fun(int n)
{ char *fun_menu[] = {
"функциональная часть № 1 Страуступа",
"функциональная часть № 2 Бадда",
"функциональная часть № 3 Буча",
"функциональная часть № 4 вводный курс",
"функциональная часть № 5 язык JAVA",
"функциональная часть № 6 JAVA скрипт",
"функциональная часть № 7 Кернигана",
"функциональная часть № 8 Справочник С++",
"функциональная часть № 9 Функции С++",
"функциональная часть № 10 Нортона",
"функциональная часть № 11 Фигурнова",
"функциональная часть № 12 Таненбаума",
"функциональная часть № 13 Столлингса",
"функциональная часть № 14 Олифера",
"функциональная часть № 15 реализациях",
"функциональная часть № 16 алгоритмах",
"функциональная часть № 17 книгу Бека",
"функциональная часть № 18 конспект лек.",
"функциональная часть № 19 справочник",
"функциональная часть № 20 Бредли",
"функциональная часть № 21 Джурден" };
textbackground(color1);
gotoxy(row_begin,ti.winbottom-1);
clreol();
cprintf("***
Работа %d функциональной части ...", n);
gotoxy(row_begin,ti.winbottom);
clreol();
cprintf("***
%s ***", fun_menu[n-1]);
textbackground(colorfon);
getchar();
return
0;
};
// модель функциональных частей -----конец программы
// главная программа ------ начало
int main(void)
{
int
kod;
// код возврата
help_txt(); // определить текущий текстовый режим
while
( 1 )
{
clear();
//@@@@@
kod=step_d("menu_link.txt"); // выбор из меню
//@@@@@@
printf(" =====> kod= %d \n", kod);
// для тестирования
// можно
использовать оператор swith
if ( kod
== 0 ) break;
if ( kod
>= 1 && kod <=21 )
{ fun_fun(kod); continue;}
else
{ printf("Ошибка в структурах файлов
меню - не допустимый код возврата\n");
getch();
break;
};
};
return
0;
};
// главная программа ------ конец
void clear()
{
textcolor(colortxt);
textbackground(colorfon);
clrscr(); return;};
void n_cputs(int nx, int
ny, char * str)
{textbackground(colormenu); //colorfon);
gotoxy(nx,ny);
cputs(str); return;};
void v_cputs(int nx, int
ny, char * str)
{textbackground(color2); gotoxy(nx,ny); cputs(str);
textbackground(colorfon);
return;};
void s_cputs(int nx, int
ny, char * str)
{textbackground(color1);
gotoxy(nx,ny); cputs(str);
textbackground(colorfon);
return;};
void h_cputs(int nx, int
ny, char * str)
{textbackground(color1);
gotoxy(1,ny);
clreol();
gotoxy(nx,ny);
cputs(str);
textbackground(colorfon);
return;};
// программы организации СТЕКА
// память для СТЕКА
int s_str[10],
s_row[10];
//char s_file[10][80]; //@@@@@@@@@@@@@@
int s_file[10];
// указатель СТЕКА
int s_ptr=-1;
// поместить в СТЕК
int stek_push(int, int, int ); //@@@@@@ char * );
// взять из СТЕКА
int stek_pop(int &str, int
&row, int & ); //@@@@@@@@@@@@char * file);
// программы работы с стеком
int stek_push(int str, int
row, int file)
{ //printf("s_ptr=%d str=%d row=%d file=%d\n", s_ptr, str, row,
file); getchar();
s_ptr++;
if(s_ptr
> 9) {printf("переполнение стека str=%d, row=%d,\n file=%s", str, row, file);
exit(16); };
s_str[s_ptr] = str;
s_row[s_ptr] = row;
// @@@@ strcpy(s_file[s_ptr],
file);
s_file[s_ptr]=file;
return
1;
};
int stek_pop(int &str, int
&row, int &file ) //@@@@&char * file)
{
if(s_ptr <= 0 ) return 0;
str
= s_str[s_ptr];
row
= s_row[s_ptr];
//@@@@@ strcpy(file,s_file[s_ptr]);
file=s_file[s_ptr];
s_ptr--;
return
1;
};
//=======================================================
// работа с файлом в ОП
char TFILE[1000][l_str_max];
//таблица
int nTFILE; // кол-во элементов
// указатель следующей строки в TFILE
int tTFILE;
// открыть файл и сформировать таблицу в памяти....(упрощенный
вариант)
int t_open(char * nfile)
{
// struct stat statbuf;
char buf[l_str_max];
int n=0;
FILE *h;
h=fopen(nfile, "r");
if (h == NULL ){printf( "Cannot open input file
<%s> \n", nfile); getch(); return -1;};
while (mfgets(buf,
l_str_max, h) != NULL )
{
strcpy(TFILE[n],buf);
// printf("<%s>\n", TFILE[n]);
n++;
};
nTFILE=n;
// getchar();
fclose(h);
return 0;
};
// "Тфайл" - установить
указатель на заданную запись файла.....
int t_seek(int n)
{
if ( n
<= 0 && n > nTFILE)
{ printf( "Ошибка в указателе №
строки %d \n", n); getch(); return
0;};
tTFILE=n; return 1;
};
// чтение данных из Тфайла - читается
Запись, но возращается С
строка в buf
// длиной не более l_str_max из файла h
// в конце файла возращается NULL
char * t_mfgets(char * );
char * t_mfgets( char* buf)
{
if
( tTFILE >= nTFILE ) return NULL;
strcpy(buf, TFILE[tTFILE]);
tTFILE++;
return buf;
};
//
//========================================================
// программа - шаг диалога
int step_d( char * mfile)
{
// < > строки вопроса
// #
// < > строки ответа
// #
// строки функций
"ответа" - 0 или 1 затем
пробел
// затем код_возврата или имя_файла_шага_меню
// если в строке код_возврата =
-1, то подьем на предыдущий шаг диалога
int
num_str,
// номер текущей строки
rc=-1, // "код возврата"
num, //
номер служебной строки ответов
k; //
рабочая переменная
int
finish;
// "флаг завершения" выбора в меню
//@@@ char nfile[80]; // текущее имя файла шага диалога
int
nfile;
//@@@@@@@@
char
buf[l_str_max]; // буфер ввода
char
cnum;
// ответ
char
vvv[5][l_str_max]; //
массив для ВОПРОСА
char
menu[10][l_str_max]; //
массив для организации "меню"
unsigned
int max_len; //
максимальная длина строки варианта ответа
int
x,y,
// рабочие переменные - индексы menu
ymax,
// мах количество ответов + 1
amax,
// max
строк вопроса
ytek, //
относительная текущая (подсвеченная) позиция в меню
old_ytek; //
относительная "старая"(подсвеченная) позиция
в меню
//@@@@ FILE *h; //
указатель на файл шага диалога
int
tek_str_begin=str_begin; // позиция начала диалога
int
tek_row_begin=row_begin;
// НАЧАЛЬНЫЕ УСТАНОВКИ
help_txt(); // определить текущий текстовый режим
//@@@ strcpy(nfile, mfile);
//@@@@@@@@
t_open(mfile);
nfile=0;
//@@@@@@
s_ptr=-1; // "инициализировать СТЕК"
stek_push(tek_str_begin, tek_row_begin, nfile);
clear();
beg:
//@@ h=fopen(nfile, "r");
//@@ if (h == NULL ){cprintf( "Cannot open input file
<%s> \n", nfile); getch(); return -1;};
t_seek(nfile);
// начало шага диалога.....
gotoxy(tek_row_begin,tek_str_begin);
num_str=tek_str_begin;
// читает строчки вопроса задаем
вопрос
for(y=0;y<5;y++)
for(x=0; x <l_str_max; x++) vvv[y][x]='
'; // "чистим" массив
for(y=0;
y<5; y++) vvv[y][l_str_max-1]='\0';
max_len=0; // максимальная длина строки варианта ответа
amax=0; // счетчик строк ответа
next:
if
( t_mfgets(buf) == NULL )
//@@@@@@, l_str_max, h)
== NULL )
{ cprintf( "Ошибка в области
вопроса строка N %d в файле <%s>
\n", num_str-tek_str_begin+1, nfile);
return -1; };
if
(buf[0] == '#' ) goto nask; // вопрос задали
strcpy(vvv[amax],buf); // запишим вопрос
в массив
// для красоты
max_len=(strlen(buf) > max_len ) ? strlen(buf) : max_len;
amax++;
goto
next;
nask:
// варианты ответа сохраняем в массив....
for(y=0;y<10;y++)
for(x=0;x<l_str_max; x++) menu[y][x]=' '; // "чистим"
массив
for(y=0;
y<10; y++) menu[y][l_str_max-1]='\0';
ymax=0; // счетчик
вариантов ответа
nextv:
if
( t_mfgets(buf) == NULL )
//@@@ , l_str_max, h)
== NULL )
{cprintf( "Ошибка в области
ответа строка N %d в файле <%s>
\n", num_str-str_begin+1, nfile);
return -1; };
if
(buf[0] == '#' ) goto ask; // закончили вводить вариатны
ответа
strcpy(menu[ymax],buf); // запишим выриант ответа в массив меню
// для красоты
max_len=(strlen(buf) > max_len ) ? strlen(buf) : max_len;
ymax++;
goto
nextv;
ask:
// выравняем текст вопроса и
ответа по максимальной длине строки
варианта ответа
for(y=0;
y< ymax; y++)
{ menu[y][strlen(menu[y])]=' ';
menu[y][max_len]='\0';};
// вывод вопроса
for(y=0;
y< amax; y++)
{ vvv[y][strlen(vvv[y])]=' '; vvv[y][max_len]='\0';
s_cputs(tek_row_begin, num_str, vvv[y]); // вывод вопроса
num_str++;
};
// "общий"
- справочный текст для пользователя
h_cputs(1,ti.winbottom-1," Выбирите при помощи
срелок вариант ответа");
h_cputs(1,ti.winbottom, "
и подтвердите его клавишей Enter");
// вывод возможных ответов
ytek=0;
for
( y=0; y < ymax; y++)
n_cputs(tek_row_begin,num_str+y, menu[y]); //вывод на экран выриантов
ответа меню
// подсветка ytek
v_cputs(tek_row_begin,num_str+ytek, menu[ytek]);
old_ytek=ytek; // запомнит "подсвеченную" позицию
// начальные установки выполнили
// цикл приема номера выбранного пункта меню
ask_menu:
n_cputs(tek_row_begin,num_str+old_ytek, menu[old_ytek]); //
убрать подсветку "старой" строки
v_cputs(tek_row_begin,num_str+ytek, menu[ytek]); //
установить подсветку "новой" стоки
old_ytek=ytek; //
запомнит "подсвеченную" позицию
finish=0; // флаг завершения выбора - нет завершения
// принять символ с
клавиатуры и изменить ytek
zzz:
if
( (cnum=getch()) == '\0' ) cnum=getch(); /* 0x50 - стрелка вниз
0x48 - стрелка вверх
0x4b - стрелка на лево
0x4d - стрелка на право
0x1b - ESC
0X0d - Enter
*/
// cprintf("<%x>\n",cnum);
switch
(cnum)
{
case 0x50: //
стрелка вниз
if ((ytek+1) >= ymax ) {ytek=0; break;};
ytek++; break;
case 0x48: //
стрелка вверх
if ( (ytek-1) < 0 ) {ytek=ymax-1; break;};
ytek--; break;
case 0x0d: // ENTER
finish=1;
break;
case 0x1b: // ESC
ytek=-1;
finish=1; break;
default:
break;
};
if
( finish == 1 && ytek !=
-1 )
{
rc=ytek+1;
goto kon;
};
if (finish==1 && ytek ==
-1 )
{
rc=0;
goto kon;
};
goto
ask_menu; //
повторить выбор
kon:
if ( rc==0 ) // Нажали сброс - ESC
{
//@@@ fclose(h);
// обработаем
предыдущий файл - узел диалога
// надо "вытереть" текущий диалог
for ( y=0; y
< (tek_str_begin+ymax)+1; y++)
{ gotoxy(tek_row_begin,tek_str_begin+y); //начало строк вывода
clreol(); };
// можно ли
подняться на предыдущий шаг????
if (stek_pop(tek_str_begin,
tek_row_begin, nfile) == 0 )
{ return 0; } ;
goto beg;
};
num=rc;
// чтение служебных
строк до служебной строки (включительно) выбранного ответа
for
(k=1; k <= num; k++) if ( t_mfgets(buf) == NULL ) /*, l_str_max, h) == NULL )*/ {goto err; };
// анализ типа строки
ответа
// printf("buf=<%s> k=%d\n", buf, num); getchar();
if
(buf[0] == '0')
// ВСЕ - код возврата....
{ sscanf( buf+2, "%d", &rc);
// моделируем нажатие ESC
if (rc==-1) { rc=0; goto kon; };
//@@@fclose(h);
return rc; };
if
(buf[0] == '1')
// новый узел диалога....
{ //@@@@fclose(h);
//printf("до стека nfile=%d\n",
nfile); getchar();
stek_push(tek_str_begin, tek_row_begin, nfile);
//@@@@@@@@@@@@@@@@@@@@@@
//@@@@sscanf( buf+2, "%s", nfile);
sscanf( buf+2, "%d", &nfile);
// printf("после чтения nfile=%d\n",
nfile); getchar();
tek_str_begin+=(ytek+amax);
tek_row_begin+=max_len;
goto beg; };
err:
printf("
Ошибка структуры файла в области
служебных строк\n");
getchar();
exit(16);
return
-1;
};
// справочные данные по текущему текстовому режиму
int help_txt(void)
{
gettextinfo(&ti);
/*
cprintf("Левая
граница: %2d\r\n",ti.winleft);
cprintf("Верхняя
граница: %2d\r\n",ti.wintop);
cprintf("Правая
граница: %2d\r\n",ti.winright);
cprintf("Нижняя
граница: %2d\r\n",ti.winbottom);
cprintf("Атрибуты: %2d\r\n",ti.attribute);
cprintf("Нормальные
атрибуты: %2d\r\n",ti.normattr);
cprintf("Текущий
режим: %2d\r\n",ti.currmode);
cprintf("Высота
экрана: %2d\r\n",ti.screenheight);
cprintf("Ширина
экрана: %2d\r\n",ti.screenwidth);
cprintf("Координата
х:
%2d\r\n",ti.curx);
cprintf("Координата
y: %2d\r\n",ti.cury);
getch();
*/
return
0;
}