Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************/
- /* Интерфейсная часть модуля CRT.h */
- /******************************************************************************/
- #define CrtH
- // Флаг настройки устройства/отладки программы
- // Если закомментарен - сдача по ТУ (нету вывода отладочной инфы)
- // в протокол и т.п. (для условной компиляции #ifdef debug)
- // #define debug
- // ============= Цвета символов (0x00..0x0F) и фона (0x00..0x07) ===============
- #define clBlack 0x00 // Чёрный
- #define clNavy 0x01 // Тёмно-синий
- #define clGreen 0x02 // Тёмно-зелёный
- #define clTeal 0x03 // Сине-зелёный
- #define clMaroon 0x04 // Тёмно-красный
- #define clPurple 0x05 // Фиолетовый
- #define clOlive 0x06 // Охра
- #define clSilver 0x07 // Светло-серый
- #define clGray 0x08 // Тёмно-серый
- #define clBlue 0x09 // Синий
- #define clLime 0x0A // Салатовый
- #define clAqua 0x0B // Голубой
- #define clRed 0x0C // Красный
- #define clFuchsia 0x0D // Ярко-фиолетовый
- #define clYellow 0x0E // Жёлтый
- #define clWhite 0x0F // Белый
- #define clBlink 0x80 // Мигание текста
- // ================ Символы псевдографики (кодировка ISO) ======================
- #define Codepage_ISO
- //#define Codepage_DOS
- #ifdef Codepage_ISO
- #define HorzBorder1 0xA4 // Горизонтальная граница одинарная
- #define VertBorder1 0xA5 // Вертикальная граница одинарная
- #define CornerLU11 0xA0 // Левый верхний угол
- #define CornerRU11 0xA1 // Правый верхний угол
- #define CornerRD11 0xA2 // Правый нижний угол
- #define CornerLD11 0xA3 // Левый нижний угол
- #define DotBarLite 0x9B // Слабозакрашенный прямоугольник
- #define DotBarMiddle 0x9C // Среднезакрашенный прямоугольник
- #define DotBarDark 0x9D // Сильнозакрашенный прямоугольник
- #define SolidBar 0xAB // Закрашенный прямоугольник
- #endif
- // ================ Символы псевдографики (кодировка DOS) ======================
- #ifdef Codepage_DOS
- #define HorzBorder1 0xC4 // Горизонтальная граница одинарная
- #define VertBorder1 0xB3 // Вертикальная граница одинарная
- #define CornerLU11 0xDA // Левый верхний угол
- #define CornerRU11 0xBF // Правый верхний угол
- #define CornerRD11 0xD9 // Правый нижний угол
- #define CornerLD11 0xC0 // Левый нижний угол
- #define DotBarLite 0xB0 // Слабозакрашенный прямоугольник
- #define DotBarMiddle 0xB1 // Среднезакрашенный прямоугольник
- #define DotBarDark 0xB2 // Сильнозакрашенный прямоугольник
- #define SolidBar 0xDB // Закрашенный прямоугольник
- #endif
- // ============================ Кнопки диалогов ================================
- #define ButtonsCount 7 // Количество возможных кнопок
- #define btNoButtons 0 // Без кнопок
- #define btOk 0x01 // OK
- #define btYes 0x02 // Да
- #define btNo 0x04 // Нет
- #define btCancel 0x08 // Отмена
- #define btAbort 0x10 // Прервать
- #define btRetry 0x20 // Повтор
- #define btIgnore 0x40 // Пропустить
- #define btOkCancel btOk | btCancel // Ок, Отмена
- #define btYesNo btYes | btNo // Да, Нет
- #define btYesNoCancel btYesNo | btCancel // Да, Нет, Отмена
- #define btAbortRetryIgnore btAbort | btRetry | btIgnore // Прервать, Повтор, Пропустить
- // ========================= Результаты диалогов ===============================
- #define mrNone 0x00 // пустой ответ
- #define mrOk 0x01 // OK
- #define mrYes 0x02 // Да
- #define mrNo 0x03 // Нет
- #define mrCancel 0x04 // Отмена
- #define mrAbort 0x05 // Прервать
- #define mrRetry 0x06 // Повтор
- #define mrIgnore 0x07 // Пропустить
- // ====================== Коды клавиатурных клавиш =============================
- #define kbBkSpc 8 // BackSpace
- #define kbTab 9 // Tab
- #define kbEnter 13 // Enter
- #define kbEsc 27 // Escape
- #define kbSpace 32 // Пробел
- #define kbUp 72 // Стрелка вверх
- #define kbLeft 75 // Стрелка влево
- #define kbRight 77 // Стрелка вправо
- #define kbDown 80 // Стрелка вниз
- #define kbF1 59 // F1
- #define kbF2 60 // F2
- #define kbF3 61 // F3
- #define kbF4 62 // F4
- #define kbF5 63 // F5
- #define kbF6 64 // F6
- #define kbF7 65 // F7
- #define kbF8 66 // F8
- #define kbF9 67 // F9
- #define kbF10 68 // F10
- #define kbF11 133 // F11
- #define kbF12 134 // F12
- #define kb0 48 // Клавиша "0"
- #define kb1 49 // Клавиша "1"
- #define kb2 50 // Клавиша "2"
- #define kb3 51 // Клавиша "3"
- #define kb4 52 // Клавиша "4"
- #define kb5 53 // Клавиша "5"
- #define kb6 54 // Клавиша "6"
- #define kb7 55 // Клавиша "7"
- #define kb8 56 // Клавиша "8"
- #define kb9 57 // Клавиша "9"
- // ======================== Логические константы ===============================
- #define true 1
- #define false 0
- // ========================== Системы счисления ================================
- #define IntDec 10 // Десятичный
- #define IntHex 16 // Шестнадцатеричный
- #define IntOct 8 // Восьмеричный
- #define IntBin 2 // Двоичный
- #define DecDigits "0123456789" // Десятичные цифры
- #define HexDigits "0123456789ABCDEFabcdef" // Шестнадцатеричные цифры
- #define OctDigits "01234567" // Восьмеричные цифры
- #define BinDigids "01" // Двоичные цифры
- #define FloatSymbols "0123456789.eE-+" // Цифры числе с плав. точкой
- // ==================== Разновидности вводимых данных ==========================
- #define ivtInt 0 // Вводится целое число (10-чное со знаком | 16-чное | 8-чное)
- #define ivtFloat 1 // Вводится десятичное дробное со знаком
- #define ivtString 2 // Вводится любая строка
- // ============= Строки сообщений об ошибках (кодировка ISO) ===================
- #ifdef Codepage_ISO
- #define errIsNotIntValue "Неверный ввод целого числа."
- #define errIsNotFloatValue "Неверный ввод десятичного числа."
- #define errIsWider16Bit "Число шире 16 бит. Оно должно быть в пределах:\n -32768...+32767 (dec)\n 0...0xFFFF (hex)\n 0...0177777 (oct)."
- #define errIsWider32Bit "Число шире 32 бит. Оно должно быть в пределах:\n -2147483648...+2147483647 (dec)\n 0...0xFFFFFFFF (hex)\n 0...37777777777 (oct)."
- #endif
- // ============= Строки сообщений об ошибках (кодировка DOS) ===================
- #ifdef Codepage_DOS
- #define errIsNotIntValue "Is not integer value."
- #define errIsNotFloatValue "Is not floating-point value."
- #define errIsWider16Bit "This value is out of 16-bit bounds. It must be between:\n -32768...+32767 (dec)\n 0...0xFFFF (hex)\n 0...0177777 (oct)."
- #define errIsWider32Bit "This value is out of 32-bit bounds. It must be between:\n -2147483648...+2147483647 (dec)\n 0...0xFFFFFFFF (hex)\n 0...37777777777 (oct)."
- #endif
- // ============== Параметры сообщений об ошибках по умолчанию ==================
- #ifdef Codepage_ISO
- #define errTitle " Ошибка "
- #endif
- #ifdef Codepage_DOS
- #define errTitle " Error "
- #endif
- #define errBorderColor clYellow
- #define errTextColor clWhite
- #define errBackground clMaroon
- #define errButtons btOk
- #define errDefaultButton 1
- #define errbtForeground clLime
- #define errbtBackground clBlack
- // ============== Параметры информационных сообщений по умолчанию ==============
- #ifdef Codepage_ISO
- #define infTitle " Информация "
- #endif
- #ifdef Codepage_DOS
- #define infTitle " Information "
- #endif
- #define infBorderColor clYellow
- #define infTextColor clNavy
- #define infBackground clTeal
- #define infButtons btOk
- #define infDefaultButton 1
- #define infbtForeground clLime
- #define infbtBackground clBlack
- // =============== Параметры сообщений с запросами по умолчанию ================
- #ifdef Codepage_ISO
- #define reqTitle " Запрос "
- #endif
- #ifdef Codepage_DOS
- #define reqTitle " Request "
- #endif
- #define reqBorderColor clWhite
- #define reqTextColor clYellow
- #define reqBackground clPurple
- #define reqButtons btYesNo
- #define reqDefaultButton 1
- #define reqbtForeground clLime
- #define reqbtBackground clBlack
- // ============== Параметры сообщений с выбором опции по умолчанию =============
- #ifdef Codepage_ISO
- #define selTitle " Выбор "
- #endif
- #ifdef Codepage_DOS
- #define selTitle " Select "
- #endif
- #define selBorderColor clYellow
- #define selTextColor clWhite
- #define selBackground clPurple
- #define selButtons btNoButtons
- // =================== Параметры окон ввода по умолчанию =======================
- #ifdef Codepage_ISO
- #define inpTitle " Ввод "
- #endif
- #ifdef Codepage_DOS
- #define inpTitle " Input "
- #endif
- #define inpBorderColor clYellow
- #define inpTextColor clWhite
- #define inpBackground clNavy
- #define inpInpForeground clLime
- #define inpInpBackground clBlack
- // ========================== Прочие константы =================================
- #define MaxMessageWidth 74 // Максимальная ширина окна сообщения
- #define MaxMessageHeight 19 // Максимальная высота окна сообщения
- #define GaugeWidth 40 // Длина индикатора прогресса включая \0
- #define LogDivider "================================================================================\n"
- #define SysTimerFreq 0x1234DCL // тактовая частота системного таймера
- // ============================ Типы данных ====================================
- typedef unsigned char UCHAR; // 8 бит без знака
- typedef unsigned int UINT; // 16 бит без знака
- typedef unsigned long ULONG; // 32 бита без знака
- typedef char bool; // true|false - логическое
- typedef char* string; // строка символов с нулём на конце
- typedef char TColor; // Цвет или фон
- typedef char TModalResult; // Результат показа диалога/запроса
- // Координаты курсора и/или символа
- typedef struct
- {
- char Col; // X
- char Row; // Y
- } TTextPoint;
- // Символ и его атрибуты
- typedef struct
- {
- char Col; // X
- char Row; // Y
- TColor Foreground; // Цвет
- TColor Background; // Фон
- char Symbol; // Сам символ
- } TSymbolAttribs;
- // Прямоугольная область экрана в текстовом режиме
- typedef struct
- {
- char Left; // Левый и
- char Top; // верхний угол
- char Width; // Ширина и
- char Height; // высота в символах
- } TTextRect;
- // Структура окна сообщения
- typedef struct // Переделать !!!!!!!!!!!!!!!!!!!!!
- {
- string Message; // Текст сообщения
- string Title; // Заголовок сообщения
- TColor BorderColor; // Цвет рамки
- TColor TextColor; // Цвет текста
- TColor Background; // Фон окна сообщения
- UINT Buttons; // Набор кнопок
- char DefaultButton; // Номер кнопки по умолчанию (нумерация с единицы, 0 - нету кнопки по умолчанию)
- TColor btForeground; // Цвет текста кнопок
- TColor btBackground; // Фон текста кнопок
- TColor InpForeground; // Цвет текста поля ввода (для диалогов ввода)
- TColor InpBackground; // Фон текста поля ввода (для диалогов ввода)
- string InputValue; // Введённая строка (для диалогов ввода)
- } TMessageParams;
- // Параметры для функции вывода прогресса выполнения
- typedef struct
- {
- string Message; // Текст сообщения
- string Title; // Заголовок сообщения
- TColor clComplete; // Цвет полосы выполнения
- TColor clUncomplete; // фон полосы выполнения
- TColor Foreground; // Цвет текста (XXX%)
- TColor Background; // Фон текста (XXX%)
- TColor MsgColor; // Цвет текста сообщения
- float OldProgress; // Предыдущее значение прогресса
- TTextPoint From; // Откуда начинается индикатор
- TTextRect Rect; // Место расположения окна
- UINT* ScreenBuffer; // Буфер для запоминания части экрана
- } TProgressParams;
- // Типы окон (окна ввода и вывода сообщений об ошибках/информации)
- typedef enum
- {
- wndError, // Сообщение об ошибке
- wndInfo, // Простое сообщение
- wndRequest, // Запрос типа (да/нет)
- wndSelect, // Выбор опции
- wndInput // Ввод данных
- } TMessageStyle;
- // Типы окон прогресса выполнения и задержки
- typedef enum
- {
- wndProgress, // Прогресс
- wndDelay // Задержка
- } TProgressStyle;
- // Составляющие времени
- typedef struct
- {
- UINT Hr; // Часы
- UINT Min; // Минуты
- UINT Sec; // Секунды
- UINT mSec; // Миллисекунды
- } TTimeStamp;
- // ======================== Прототипы функций ==================================
- // Работа с курсором
- char WhereX(void);
- char WhereY(void);
- void WhereXY(char*, char*);
- void GotoXY(char, char);
- void HideCursor(void);
- void ShowCursor(void);
- // Вывод текста в цвете
- void ColorSymbol(char, char, char, TColor, TColor);
- void ColorPrint(string, TColor, TColor);
- void GetSymbolAttribs(TSymbolAttribs*);
- void InvertColors(TTextPoint, char);
- void ShadowSymbols(TTextPoint, char);
- // Работа с областями экрана
- void MakeRect(TTextRect*, char, char, char, char);
- void FillTextRect(TTextRect, char, TColor, TColor);
- void ClearTextRect(TTextRect, TColor);
- void CenterRect(TTextRect* Rect);
- // Диалоги, сообщения и пр
- void DrawFrame(TTextRect, string, TColor, TColor);
- int PrintTextbox(TTextRect, string, TColor, TColor);
- void GetWindowDefaults(TMessageParams*, TMessageStyle);
- TModalResult ShowMessage(TMessageParams*);
- TModalResult InputBox(TMessageParams*, char); // Fix (04.06.2008)
- TModalResult InputBoxDef(TMessageParams*, string, char); // New (04.06.2008)
- bool InputInt(TMessageParams*, int*);
- bool InputFloat(TMessageParams*, float*);
- int SelectOption(TMessageParams*, int);
- void BeginProgress(TProgressParams*);
- void ShowProgressI(int, int, TProgressParams*); // Fix (21.05.2009)
- void ShowProgressF(float, float, TProgressParams*);
- void EndProgress(TProgressParams*);
- void BeginMessageNonModal(TProgressParams*); // New (06.10.2008)
- void UpdateMessageNonModal(TProgressParams*); // New (06.10.2008)
- void EndMessageNonModal(TProgressParams*); // New (06.10.2008)
- char GetButtonsSpace(UINT Buttons);
- void DrawButtons(TMessageParams*, TTextPoint);
- TModalResult GetModalResult(TMessageParams*, TTextPoint);
- TModalResult GetInputString(TMessageParams*, string, TTextPoint, char); // Fix (04.06.2008)
- TModalResult GetInputStringDef(TMessageParams*, string, TTextPoint, char); // New (04.06.2008)
- void Assert(const bool, string); // New (02.06.2011)
- // Работа с окнами и видеопамятью
- UINT CopyWindow(TTextRect, UINT*);
- void PasteWindow(TTextRect, UINT*);
- UINT SaveWindow2File(TTextRect, string);
- void SaveScreen2File(string);
- // Работа с памятью
- void FillBufferInt(int*, int, ...); // Fix (28.06.2011)
- void FillBufferChar(UCHAR*, int, ...); // New (28.06.2011)
- // Работа со строками
- int GetLinesCount(string, int*);
- bool CharInCharset(char, string);
- UINT GetCharCount(char, string);
- char CenterString(string, char);
- void MakeString(string, char, UINT);
- bool StrIsDec(string);
- bool StrIsHex(string);
- bool StrIsOct(string);
- bool StrIsFloat(string);
- bool TryStr2Int(string, int*);
- bool TryStr2Long(string, long*);
- bool TryStr2Float(string, float*);
- bool TryStr2Double(string, double*);
- bool CheckIntLength(string, char);
- // Математические и логические функции
- int RoundI(float);
- long RoundL(float);
- bool GetBitInt(UINT, char);
- char GetBitCountInt(UINT);
- bool BetweenInt(int, int, int);
- bool BetweenLong(long, long, long);
- bool BetweenFloat(float, float, float);
- // Работа с лог-файлом
- bool OpenLog(string);
- void CloseLog(void);
- void Add2Log(string);
- void AddChar2Log(UCHAR, string);
- void AddInt2Log(int, string);
- void AddInt2LogF(int, string, char);
- void AddLong2Log(long, string);
- void AddFloat2Log(float, string);
- void AddDouble2Log(double, string);
- void AddBool2Log(bool, string);
- void AddModalResult2Log(TModalResult);
- void AddStr2Log(string, string);
- void AddRect2Log(TTextRect, string);
- // Работа с датой и временем
- void DecodeTime(float, TTimeStamp*);
- void Sleep(ULONG);
- bool Delay(float, TProgressParams*);
- // Работа со звуком
- void Beep(UINT, ULONG);
- void Sound(UINT);
- void NoSound(void);
- // Работа с клавиатурой
- bool KeyPressed(UCHAR); // New (17.06.2010)
- bool EscapePressed(void); // New (17.06.2010)
- /******************************************************************************/
- /******************************************************************************/
- /* Модуль универсальных вспомогательных подпрограмм для СП "Базис" КАСАК-85 */
- /* Его захотел написать min@y™ aka "EXXON VALDES - чилавег и порохот", */
- /* используя электронный вариант старинной книжки Герберта Шилдта */
- /* "Си для профессиональных программистов". */
- /* Начат в пятницу 30.11.2007 */
- /* mailto:minay.tm@gmail.com */
- /* Версия файла 1.02 (21.05.2009) */
- /******************************************************************************/
- #ifndef CrtH
- #include "CRT.h"
- #endif
- #include <dos.h>
- #include <stdio.h>
- #include <math.h>
- #include <malloc.h>
- #include <string.h>
- #include <time.h>
- #include <io.h>
- #include <fcntl.h>
- #include <stdarg.h>
- #ifdef Codepage_ISO
- string ButtonCaptions[ButtonsCount] = {" OK ",
- " Да ",
- " Нет ",
- " Отмена ",
- " Прервать ",
- " Повтор ",
- " Пропустить "};
- #else
- string ButtonCaptions[ButtonsCount] = {" OK ",
- " Yes ",
- " No ",
- " Cancel ",
- " Abort ",
- " Retry ",
- " Ignore "};
- #endif
- // ========================== Глобальные переменные ============================
- //TProgressParams ProgressParams;
- //UINT* ScreenBuffer; // Буфер для запоминания части экрана
- FILE* LogFile; // Файл лога
- TTextPoint OldCursor; // Координаты курсора до применения HideCursor()
- char* Ini; // Буфер для загрузки/хранения/чтения файла настроек
- //==============================================================================
- //============================= Работа с курсором ==============================
- //==============================================================================
- //------------------------- Чтение строки курсора ------------------------------
- char WhereX(void)
- {
- union REGS r;
- r.h.ah = 3; // чтение текущей позиции курсора
- r.h.bh = 0; // видеостраница
- int86(0x10, &r, &r);
- return r.h.dl;
- }
- //------------------------ Чтение столбца курсора ------------------------------
- char WhereY(void)
- {
- union REGS r;
- r.h.ah = 3; // чтение текущей позиции курсора
- r.h.bh = 0; // видеостраница
- int86(0x10, &r, &r);
- return r.h.dh;
- }
- //------------- Чтение текущих координат позиции курсора -----------------------
- void WhereXY(char *x, char *y)
- {
- union REGS r;
- r.h.ah = 3; // чтение текущей позиции курсора
- r.h.bh = 0; // видеостраница
- int86(0x10, &r, &r);
- *x = r.h.dl;
- *y = r.h.dh;
- }
- //----------------------- установка курсора в x,y ------------------------------
- void GotoXY(char x, char y)
- {
- union REGS r;
- r.h.ah = 2; // функция установки курсора
- r.h.dl = x; // координата колонки
- r.h.dh = y; // координата строки
- r.h.bh = 0; // видео страница
- int86(0x10, &r, &r);
- }
- // ------------------------- Скрытие курсора -----------------------------------
- void HideCursor(void)
- {
- OldCursor.Col = WhereX();
- OldCursor.Row = WhereY();
- GotoXY(0, 25);
- }
- //----------- Восстановление курсора, скрытого функцией HideCursor() -----------
- void ShowCursor(void)
- {
- GotoXY(OldCursor.Col, OldCursor.Row);
- }
- //==============================================================================
- //======================= Ввод/вывод текста в цвете ============================
- //==============================================================================
- //---------------- Печать символа с координатами Col, Row в цвете --------------
- void ColorSymbol(char Symbol, // Символ
- char Col, // Номер колонки
- char Row, // Номер строки
- TColor Foreground, // цвет текста
- TColor Background) // цвет фона
- {
- union REGS r;
- char Color = (Foreground & 0x8F) | ((Background & 0x07) << 4);
- GotoXY(Col, Row);
- r.h.ah = 9; // функция отображения символа и его атрибутов
- r.h.al = Symbol; // отображаемый символ
- r.h.bl = Color; // атрибуты цвета
- r.h.bh = 0; // видеостраница 0
- r.x.cx = 1; // отобразить за единицу времени ( такт )
- int86(0x10, &r, &r);
- GotoXY(Col + 1, Row);
- }
- //------------------------- Печать строки в цвете ------------------------------
- void ColorPrint(string s, // строка
- TColor Foreground, // цвет текста
- TColor Background) // цвет фона
- {
- char x, y;
- UCHAR Symbol;
- TColor UserFG = Foreground; // пользовательский цвет символов
- WhereXY(&x, &y); // получение текущей позиции курсора
- while (*s)
- {
- if (*s == '\n') // обработка символа новой строки
- {
- printf("\n");
- s++;
- x = 0, y++; // переход на следующую строку
- continue;
- }
- /* ИДЕЯ:
- Если в строке встретился символ с кодом от 0x80 до 0x8F,
- при выводе заменить его на пробел, а Foreground заменить на код_символа & 0x0F
- для вывода текста другим цветом.
- Если встретился символ 0x90, вернуть цвет обратно. */
- Symbol = *s++; // символ, который щас будет выводиться на консоль
- // ищу пользовательский цвет
- if ((Symbol & 0xF0) == 0x80)
- {
- UserFG = Symbol & 0x0F;
- //Symbol = ' '; // заменяю на пробел
- continue;
- }
- // ищу терминатор юзерского цвета
- else if (Symbol == 0x90)
- {
- UserFG = Foreground;
- //Symbol = ' '; // заменяю на пробел
- continue;
- }
- //else if ((Symbol == '.') || (Symbol == ',') || (Symbol == ':') || (Symbol == ';'))
- // UserFG = Foreground;
- //ColorSymbol(*s++, x, y, UserFG, Background);
- ColorSymbol(Symbol, x, y, UserFG, Background);
- GotoXY(x++, y); // перемещение курсора
- } // while
- GotoXY(x++, y);
- }
- // Чтение символа и его атрибутов
- // с позиции ((*SymbolAttribs).Row, (*SymbolAttribs).Col)
- void GetSymbolAttribs(TSymbolAttribs* SymbolAttribs)
- {
- union REGS r;
- GotoXY((*SymbolAttribs).Col, (*SymbolAttribs).Row);
- r.h.ah = 8; // функция чтения символа
- r.h.bh = 0; // видео страница
- int86(0x10, &r, &r); // Символ и атрибут - al и ah соответственно
- (*SymbolAttribs).Symbol = r.h.al;
- (*SymbolAttribs).Foreground = (r.h.ah & 0x8F);
- (*SymbolAttribs).Background = (r.h.ah & 0x70) >> 4;
- }
- // Инвертирование цвета и фона строки символов экрана начиная с точки From
- void InvertColors(TTextPoint From, char Count)
- {
- TSymbolAttribs SymbolAttribs;
- SymbolAttribs.Row = From.Row; // начальная
- SymbolAttribs.Col = From.Col; // точка
- while ((SymbolAttribs.Col < 80) && Count)
- {
- GetSymbolAttribs(&SymbolAttribs); // читаю атрибуты символа
- ColorSymbol(SymbolAttribs.Symbol,
- SymbolAttribs.Col,
- SymbolAttribs.Row,
- ~(SymbolAttribs.Foreground) & 0x0F,
- ~(SymbolAttribs.Background) & 0x07);
- SymbolAttribs.Col++;
- Count--;
- } // while
- }
- // Создание эффекта тени (используется для диалоговых окон) начиная с точки From
- void ShadowSymbols(TTextPoint From, char Count)
- {
- TSymbolAttribs SymbolAttribs;
- SymbolAttribs.Row = From.Row; // начальная
- SymbolAttribs.Col = From.Col; // точка
- while ((SymbolAttribs.Col < 80) && Count)
- {
- GetSymbolAttribs(&SymbolAttribs); // читаю атрибуты символа
- ColorSymbol(SymbolAttribs.Symbol,
- SymbolAttribs.Col,
- SymbolAttribs.Row,
- clGray,
- clBlack);
- SymbolAttribs.Col++;
- Count--;
- } // while
- }
- //==============================================================================
- //======================== Работа с областями экрана ===========================
- //==============================================================================
- void MakeRect(TTextRect* R,
- char Left, // Левый и
- char Top, // верхний угол
- char Width, // Ширина и
- char Height) // высота в символах
- {
- (*R).Left = Left;
- (*R).Top = Top;
- (*R).Width = Width;
- (*R).Height = Height;
- };
- // Заливка части экрана Rect символом Symbol цвета Foreground и фона Background
- void FillTextRect(TTextRect Rect,
- char Symbol,
- TColor Foreground,
- TColor Background)
- {
- int x, y, Count = 0;
- for (y = Rect.Top; y < Rect.Height + Rect.Top; y++)
- for (x = Rect.Left; x < Rect.Width + Rect.Left; x++)
- {
- ColorSymbol(Symbol, x, y, Foreground, Background);
- Count++;
- }
- }
- // Очистка части экрана Rect цветом фона Background
- void ClearTextRect(TTextRect Rect,
- TColor Background)
- {
- FillTextRect(Rect, ' ', Background, Background);
- }
- // Центрирование прямоугольника относительно центра экрана (80 х 25)
- void CenterRect(TTextRect* Rect)
- {
- (*Rect).Top = 12 - (*Rect).Height / 2;
- (*Rect).Left = 40 - (*Rect).Width / 2;
- }
- //==============================================================================
- //========================= Диалоги, сообщения и пр ============================
- //==============================================================================
- // Рисование рамки, обрамляющей область Rect цветом Foreground
- // и фоном Background, а также очитстка области внутри рамки пробелами
- // + вывод заголовка Title вверху по центру
- void DrawFrame(TTextRect Rect,
- string Title, // Текст заголовка, если надо
- TColor Foreground,
- TColor Background)
- {
- register int i;
- char TitleCol; // Относительная координата 0-го символа заголовка, если он задан
- TTextPoint ShadFrom; // Точка начала строк затенения
- // Углы
- ClearTextRect(Rect, Background);
- ColorSymbol(CornerLU11, Rect.Left, Rect.Top, Foreground, Background); // левый верхний
- ColorSymbol(CornerLD11, Rect.Left, Rect.Top + Rect.Height - 1, Foreground, Background); // левый нижний
- ColorSymbol(CornerRU11, Rect.Left + Rect.Width - 1, Rect.Top, Foreground, Background); // правый верхний
- ColorSymbol(CornerRD11, Rect.Left + Rect.Width - 1, Rect.Top + Rect.Height - 1, Foreground, Background); // правый нижний
- // Горизонтальные линии
- for (i = 0; i != Rect.Width - 2; i++)
- {
- ColorSymbol(HorzBorder1, i + Rect.Left + 1, Rect.Top, Foreground, Background);
- ColorSymbol(HorzBorder1, i + Rect.Left + 1, Rect.Top + Rect.Height - 1, Foreground, Background);
- }
- // Вертикальные линии
- for (i = 0; i != Rect.Height - 2; i++)
- {
- ColorSymbol(VertBorder1, Rect.Left, i + Rect.Top + 1, Foreground, Background);
- ColorSymbol(VertBorder1, Rect.Left + Rect.Width - 1, i + Rect.Top + 1, Foreground, Background);
- }
- // Вывод заголовка вверху по центру
- if (*Title)
- {
- TitleCol = CenterString(Title, Rect.Width);
- GotoXY(TitleCol + Rect.Left, Rect.Top);
- ColorPrint(Title, Foreground, Background);
- }
- // Вывод тени справа и внизу
- ShadFrom.Col = Rect.Left + 2;
- ShadFrom.Row = Rect.Top + Rect.Height;
- ShadowSymbols(ShadFrom, Rect.Width);
- ShadFrom.Col = Rect.Left + Rect.Width;
- for (i = 0; i != Rect.Height - 1; i++)
- {
- ShadFrom.Row = Rect.Top + 1 + i;
- ShadowSymbols(ShadFrom, 2);
- }
- }
- // Печать цветного текста внутри прямоугольника Rect (исключая границы!)
- // Возвращает количество напечатанных символов
- /*
- int PrintTextbox(TTextRect Rect,
- string Text,
- TColor Foreground,
- TColor Background)
- {
- int Count = 0; // номер текущего символа (кроме \n)
- int Col = Rect.Left + 1, // номера строки и
- Row = Rect.Top + 1; // колонки (относительно начала координат [0, 0])
- while ((*Text) && (Row < Rect.Top + Rect.Height - 1))
- {
- // если перенос строки - перехожу на след. строку
- if (*Text == '\n')
- {
- Text++; // Пропуск \n
- Row++, Col = Rect.Left + 1; // след. строка
- continue;
- }
- // Если упёрся в правый край области - перехожу на след. строку
- if (Col == Rect.Left + Rect.Width - 1)
- Row++, Col = Rect.Left + 1; // след. строка
- GotoXY(Col, Row);
- ColorSymbol(*Text, Col, Row, Foreground, Background);
- Count++;
- Col++;
- Text++;
- } // while
- return Count;
- } */
- int PrintTextbox(TTextRect Rect,
- string Text,
- TColor Foreground,
- TColor Background)
- {
- int Count = 0; // номер текущего символа (кроме \n)
- int Col = Rect.Left + 1, // номера строки и
- Row = Rect.Top + 1; // колонки (относительно начала координат [0, 0])
- UCHAR Symbol;
- TColor UserFG = Foreground; // пользовательский цвет символов
- while ((*Text) && (Row < Rect.Top + Rect.Height - 1))
- {
- // если перенос строки - перехожу на след. строку
- if (*Text == '\n')
- {
- Text++; // Пропуск \n
- Row++, Col = Rect.Left + 1; // след. строка
- continue;
- }
- // Если упёрся в правый край области - перехожу на след. строку
- if (Col == Rect.Left + Rect.Width - 1)
- Row++, Col = Rect.Left + 1; // след. строка
- /* ИДЕЯ:
- Если в строке встретился символ с кодом от 0x80 до 0x8F,
- при выводе заменить его на пробел, а Foreground заменить на код_символа & 0x0F
- для вывода текста другим цветом.
- Если встретился символ 0x90 или символы-разделители (.,:;),
- вернуть цвет обратно. */
- Symbol = *Text++; // символ, который щас будет выводиться на консоль
- // ищу пользовательский цвет
- if ((Symbol & 0xF0) == 0x80)
- {
- UserFG = Symbol & 0x0F;
- //Symbol = ' '; // заменяю на пробел
- continue;
- }
- // ищу терминатор юзерского цвета
- else if (Symbol == 0x90)
- {
- UserFG = Foreground;
- //Symbol = ' '; // заменяю на пробел
- continue;
- }
- //else if ((Symbol == '.') || (Symbol == ',') || (Symbol == ':') || (Symbol == ';'))
- // UserFG = Foreground;
- GotoXY(Col, Row);
- ColorSymbol(Symbol, Col, Row, UserFG, Background);
- Count++;
- Col++;
- //Text++;
- } // while
- return Count;
- }
- // Установка параметров сообщений по умолчанию
- // Style - тип окна сообщения:
- // typedef enum {wndError, wndInfo, wndSelect, wndInput} TMessageStyle;
- void GetWindowDefaults(TMessageParams* Params, TMessageStyle Style)
- {
- switch (Style)
- {
- case wndError:
- (*Params).Title = errTitle;
- (*Params).BorderColor = errBorderColor;
- (*Params).TextColor = errTextColor;
- (*Params).Background = errBackground;
- (*Params).Buttons = errButtons;
- (*Params).DefaultButton = errDefaultButton;
- (*Params).btForeground = errbtForeground;
- (*Params).btBackground = errbtBackground;
- break;
- case wndInfo:
- (*Params).Title = infTitle;
- (*Params).BorderColor = infBorderColor;
- (*Params).TextColor = infTextColor;
- (*Params).Background = infBackground;
- (*Params).Buttons = infButtons;
- (*Params).DefaultButton = infDefaultButton;
- (*Params).btForeground = infbtForeground;
- (*Params).btBackground = infbtBackground;
- break;
- case wndRequest:
- (*Params).Title = reqTitle;
- (*Params).BorderColor = reqBorderColor;
- (*Params).TextColor = reqTextColor;
- (*Params).Background = reqBackground;
- (*Params).Buttons = reqButtons;
- (*Params).DefaultButton = reqDefaultButton;
- (*Params).btForeground = reqbtForeground;
- (*Params).btBackground = reqbtBackground;
- break;
- case wndSelect:
- (*Params).Title = selTitle;
- (*Params).BorderColor = selBorderColor;
- (*Params).TextColor = selTextColor;
- (*Params).Background = selBackground;
- break;
- case wndInput:
- (*Params).Title = inpTitle;
- (*Params).BorderColor = inpBorderColor;
- (*Params).TextColor = inpTextColor;
- (*Params).Background = inpBackground;
- (*Params).InpForeground = inpInpForeground;
- (*Params).InpBackground = inpInpBackground;
- (*Params).Buttons = btNoButtons;
- break;
- } // switch
- }
- // Вывод на экран окна сообщения.
- TModalResult ShowMessage(TMessageParams* Params)
- {
- int Len = strlen((*Params).Message); // Длина сообщения
- int MaxLen; // длина самой длинной из строк сообщения
- UINT* Buffer; // Буфер под сохранение участка экрана
- TTextRect Rect; // Область окна
- char ButtonSpace; // Длина поля кнопок
- TTextPoint ButtonsFrom; // Координата начала строки кнопок
- TModalResult ModalResult; // Результат функции (какую кнопку нажали)
- // Вычисление координат окна, чтобы оно было по центру экрана
- ButtonSpace = GetButtonsSpace((*Params).Buttons);
- Rect.Height = GetLinesCount((*Params).Message, &MaxLen) + 2 + 2; // 2 - под рамку, 2 - под кнопки
- if (MaxLen > ButtonSpace)
- Rect.Width = MaxLen + 2; // Длина кнопок уже сообщения
- else
- Rect.Width = ButtonSpace + 2; // Длина кнопок шире сообщения
- //AddInt2Log(MaxLen, "MaxLen");
- //AddInt2Log(ButtonSpace, "ButtonSpace");
- //AddRect2Log(Rect, "Rect");
- CenterRect(&Rect); // Центрирование окна
- // Запоминаю часть экрана
- //Buffer = malloc(Rect.Width * Rect.Height * 2);
- // Выделение памяти под прямоугольник с учётом тени
- Buffer = malloc(2 * (Rect.Width * Rect.Height + 2 * Rect.Height + Rect.Width + 2));
- CopyWindow(Rect, Buffer);
- // Рисую рамку и выдаю текст
- DrawFrame(Rect, (*Params).Title, (*Params).BorderColor, (*Params).Background);
- PrintTextbox(Rect, (*Params).Message, (*Params).TextColor, (*Params).Background);
- // Кнопки
- ButtonsFrom.Col = (Rect.Left + 1) + ((Rect.Width - ButtonSpace) / 2) - 1; // Центрирование кнопок относительно окна
- ButtonsFrom.Row = Rect.Top + Rect.Height - 2;
- DrawButtons(Params, ButtonsFrom); // Рисую кнопки
- // Опрос клавы
- ModalResult = GetModalResult(Params, ButtonsFrom);
- //AddModalResult2Log(ModalResult);
- // восстанавливаю чать экрана и курсор
- PasteWindow(Rect, Buffer);
- free(Buffer); // Fix (08.07.2011)
- ShowCursor();
- return ModalResult;
- }
- // Вывод на экран окна ввода тестовой строки.
- // По умолчанию отображается пустая строка. Максимальная длина = MaxLen.
- // Результат возвращается в (*Params).InputValue.
- TModalResult InputBox(TMessageParams* Params, char MaxLength)
- {
- int Len = strlen((*Params).Message); // Длина сообщения
- int MaxLen; // длина самой длинной из строк сообщения
- UINT* Buffer; // Буфер под сохранение участка экрана
- TTextRect Rect; // Область окна
- TTextPoint InputFrom; // Координата начала поля ввода
- TModalResult ModalResult; // Результат функции
- string InputField = (string)malloc(MaxLength + 1); // строка поля ввода
- // Вычисление координат окна, чтобы оно было по центру экрана
- Rect.Height = GetLinesCount((*Params).Message, &MaxLen) + 2 + 2; // 2 - под рамку, 2 - под строку ввода
- if (MaxLen > MaxLength)
- Rect.Width = MaxLen + 2; // Длина поля ввода уже сообщения
- else
- Rect.Width = MaxLength + 5; // Длина поля ввода шире сообщения
- CenterRect(&Rect); // Центрирование окна
- // Запоминаю часть экрана
- // Выделение памяти под прямоугольник с учётом тени
- Buffer = malloc(2 * (Rect.Width * Rect.Height + 2 * Rect.Height + Rect.Width + 2));
- CopyWindow(Rect, Buffer);
- // Рисую рамку и выдаю текст
- DrawFrame(Rect, (*Params).Title, (*Params).BorderColor, (*Params).Background);
- PrintTextbox(Rect, (*Params).Message, (*Params).TextColor, (*Params).Background);
- // Поле ввода
- InputFrom.Col = Rect.Left + 2;
- InputFrom.Row = Rect.Top + Rect.Height - 2;
- // Опрос клавы
- ModalResult = GetInputString(Params, InputField, InputFrom, MaxLength);
- // восстанавливаю часть экрана и курсор
- PasteWindow(Rect, Buffer);
- // Освобождаю память из-под (*Params).InputValue, если надо
- if ((*Params).InputValue) free((*Params).InputValue);
- if (ModalResult == mrOk) (*Params).InputValue = strdup(InputField);
- free(Buffer); // Fix (08.07.2011)
- free(InputField);
- return ModalResult;
- }
- // Вывод на экран окна ввода тестовой строки.
- // По умолчанию отображается Default. Максимальная длина = MaxLen.
- // Результат возвращается в (*Params).InputValue.
- TModalResult InputBoxDef(TMessageParams* Params, string Default, char MaxLength)
- {
- int Len = strlen((*Params).Message); // Длина сообщения
- int MaxLen; // длина самой длинной из строк сообщения
- UINT* Buffer; // Буфер под сохранение участка экрана
- TTextRect Rect; // Область окна
- TTextPoint InputFrom; // Координата начала поля ввода
- TModalResult ModalResult; // Результат функции
- char InputField[80]; // = (string)malloc(MaxLength + 1); // строка поля ввода
- // Вычисление координат окна, чтобы оно было по центру экрана
- Rect.Height = GetLinesCount((*Params).Message, &MaxLen) + 2 + 2; // 2 - под рамку, 2 - под строку ввода
- if (MaxLen > MaxLength)
- Rect.Width = MaxLen + 2; // Длина поля ввода уже сообщения
- else
- Rect.Width = MaxLength + 5; // Длина поля ввода шире сообщения
- CenterRect(&Rect); // Центрирование окна
- // Запоминаю часть экрана
- // Выделение памяти под прямоугольник с учётом тени
- Buffer = malloc(2 * (Rect.Width * Rect.Height + 2 * Rect.Height + Rect.Width + 2));
- CopyWindow(Rect, Buffer);
- // Рисую рамку и выдаю текст
- DrawFrame(Rect, (*Params).Title, (*Params).BorderColor, (*Params).Background);
- PrintTextbox(Rect, (*Params).Message, (*Params).TextColor, (*Params).Background);
- // Поле ввода
- InputFrom.Col = Rect.Left + 2;
- InputFrom.Row = Rect.Top + Rect.Height - 2;
- // Значение по умолчанию, передающееся в функцию GetInputStringDef()
- strcpy(InputField, Default);
- // Опрос клавы
- ModalResult = GetInputStringDef(Params, InputField, InputFrom, MaxLength);
- // восстанавливаю часть экрана и курсор
- PasteWindow(Rect, Buffer);
- // Освобождаю память из-под (*Params).InputValue, если надо
- if ((*Params).InputValue) free((*Params).InputValue);
- if (ModalResult == mrOk) (*Params).InputValue = strdup(InputField);
- free(Buffer); // Fix (08.07.2011)
- return ModalResult;
- }
- // Вывод на экран окна ввода 16-битного целого.
- // Максимальная длина = 13 символов (эдак с запасом).
- // Результат возвращается в *Value. Результат = true, если юзер ввёл
- // ПРАВИЛЬНОЕ число (в десятичном | шестнадцатеричном | восьмеричном) формате
- // и нажал Enter. Esc - отмена, функция вернёт false.
- bool InputInt(TMessageParams* Params, int* Value)
- {
- TModalResult mr;
- TMessageParams ErrorParams;
- bool Result;
- do // пока юзер не введёт правильно число или не нажмёт отмену
- {
- mr = InputBox(Params, 13);
- if (mr == mrCancel) return false; // Нажали отмену
- // Перевод строки в число
- Result = TryStr2Int((*Params).InputValue, Value);
- // Если число корректно, то проверка на разрядность
- if (Result)
- {
- Result = CheckIntLength((*Params).InputValue, 16);
- // И если только проверена разрядность, то результат верен!
- if (Result) return true;
- else ErrorParams.Message = errIsWider16Bit; // Ошибка - число не лезет в 16 бит
- }
- // Если число некорректно - другое сообшение об ошибке
- else ErrorParams.Message = errIsNotIntValue; // Ошибка - строка не есть целое
- // Вывод сообщения об ошибке
- GetWindowDefaults(&ErrorParams, wndError); // параметры окна с ошибкой по умолчанию
- #ifdef Codepage_ISO
- ErrorParams.Title = " Неверный ввод ";
- #endif
- #ifdef Codepage_DOS
- ErrorParams.Title = " Input error ";
- #endif
- ShowMessage(&ErrorParams);
- }
- while (true);
- }
- // Вывод на экран окна ввода демятичного числа (с плав. точкой).
- // Максимальная длина = 13 символов (для точности после точки).
- // Результат возвращается в *Value. Результат = true, если юзер ввёл
- // ПРАВИЛЬНОЕ число (т.е. корректное)
- // и нажал Enter. Esc - отмена, функция вернёт false.
- bool InputFloat(TMessageParams* Params, float* Value)
- {
- TMessageParams ErrorParams;
- do // пока юзер не введёт правильно число или не нажмёт отмену
- {
- if (InputBox(Params, 13) == mrCancel) return false; // Нажали отмену
- // Перевод строки в число
- if (TryStr2Float((*Params).InputValue, Value)) return true;
- else // Если число некорректно - сообшение об ошибке
- {
- GetWindowDefaults(&ErrorParams, wndError); // параметры окна с ошибкой по умолчанию
- #ifdef Codepage_ISO
- ErrorParams.Title = " Неверный ввод ";
- #endif
- #ifdef Codepage_DOS
- ErrorParams.Title = " Input error ";
- #endif
- ErrorParams.Message = errIsNotFloatValue; // Ошибка - строка не есть число с пл. точкой
- ShowMessage(&ErrorParams);
- } // else
- }
- while (true);
- }
- // Вывод на экран окна выбора одной из опций. Сами опции задаются в
- // Params.Message и разделяются символами "\n".
- // DefaultOption - опция по умолчанию.
- // Результат функции - номер выбранной опции (нумерация с единицы).
- int SelectOption(TMessageParams* Params, int DefaultOption)
- {
- int MaxLen; // длина самой длинной из строк сообщения
- UINT* Buffer; // Буфер под сохранение участка экрана
- TTextRect Rect; // Область окна
- int OptionsCount = GetLinesCount((*Params).Message, &MaxLen); // Кол-во опций
- char Key; // Код нажатой клавиши
- int Selection; // Текущая выбранная опция
- TTextPoint InvertFrom; // Точка, откуда выделять (инвертировать) текущую опцию
- int Result = 0; // Результат функции (номер выбраной опции)
- bool Redraw = true; // Перерисовывать меню или нет (в случае нажатия не тех клавиш)
- // Вычисление координат окна, чтобы оно было по центру экрана
- Rect.Height = OptionsCount + 2; // Высота окна, 2 - под рамку
- Rect.Width = MaxLen + 2; // Ширина окна, 2 - под рамку
- CenterRect(&Rect); // Центрирование окна
- InvertFrom.Col = Rect.Left + 1; // Координата Х выделения опции
- // Запоминаю часть экрана
- //Buffer = malloc(Rect.Width * Rect.Height * 2);
- // Выделение памяти под прямоугольник с учётом тени
- Buffer = malloc(2 * (Rect.Width * Rect.Height + 2 * Rect.Height + Rect.Width + 2));
- CopyWindow(Rect, Buffer);
- // Рисую рамку и выдаю текст
- DrawFrame(Rect, (*Params).Title, (*Params).BorderColor, (*Params).Background);
- PrintTextbox(Rect, (*Params).Message, (*Params).TextColor, (*Params).Background);
- // Выделение по умолчанию
- if ((DefaultOption > 0) && (DefaultOption <= OptionsCount))
- Selection = DefaultOption;
- else Selection = 1;
- // Опрос клавы
- while (!Result)
- {
- // выделяю опцию
- if (Redraw)
- {
- InvertFrom.Row = Rect.Top + Selection;
- InvertColors(InvertFrom, MaxLen);
- HideCursor();
- }
- Key = getch(); // Код клавиши
- switch (Key)
- {
- case 0: // Клавиши со стрелками
- Key = getch(); // Скан-код клавиши
- if ((Key == kbUp) || (Key == kbLeft)) // стрелка вверх или влево
- {
- InvertColors(InvertFrom, MaxLen); // Снятие выделения с текущей опции
- if (Selection > 1) Selection--;
- else Selection = OptionsCount;
- Redraw = true;
- }
- else if ((Key == kbDown) || (Key == kbRight)) // стрелка вниз или вправо
- {
- InvertColors(InvertFrom, MaxLen); // Снятие выделения с текущей опции
- if (Selection < OptionsCount) Selection++;
- else Selection = 1;
- Redraw = true;
- }
- else Redraw = false;
- break;
- case 13: // Enter
- Result = Selection;
- break;
- case kb1: // Клавиши "1"..."9"
- case kb2:
- case kb3:
- case kb4:
- case kb5:
- case kb6:
- case kb7:
- case kb8:
- case kb9:
- if ((Key - kb0) <= OptionsCount)
- Result = (Key - kb0);
- break;
- default: Redraw = false;
- } // switch
- } // while
- // восстанавливаю чать экрана и курсор
- PasteWindow(Rect, Buffer);
- free(Buffer); // Fix (08.07.2011)
- ShowCursor();
- return Result;
- }
- // Показ окна прогресса выполнения (по центру экрана)
- void BeginProgress(TProgressParams* Params)
- {
- TTextRect Rect; // Область окна
- int MaxLen; // для GetLinesCount()
- //Rect.Height = GetLinesCount((*Params).Message, &MaxLen) + 2 + 2 + 2; // 2 - под рамку, 2 - под индикатор, 2 - под разделители;
- Rect.Height = GetLinesCount((*Params).Message, &MaxLen) + 2 + 2;
- if (MaxLen > (GaugeWidth + 9))
- Rect.Width = MaxLen + 2; // Длина кнопок уже сообщения
- else
- Rect.Width = GaugeWidth + 11; // Длина кнопок шире сообщения
- //MakeRect(&Rect, 0, 0, GaugeWidth + 11, RectHeight);
- CenterRect(&Rect);
- // Запоминаю участок экрана для последующего восстановления
- //(*Params).ScreenBuffer = malloc(Rect.Width * Rect.Height * 2);
- // Выделение памяти под прямоугольник с учётом тени
- (*Params).ScreenBuffer = malloc(2 * (Rect.Width * Rect.Height + 2 * Rect.Height + Rect.Width + 2));
- CopyWindow(Rect, (*Params).ScreenBuffer);
- // Запоминаю параметры прогресса
- (*Params).OldProgress = -1;
- (*Params).From.Col = Rect.Left + 2;
- (*Params).From.Row = Rect.Top + Rect.Height - 2;
- (*Params).Rect = Rect;
- // Рисую окно прогресса с текстом и индикатором
- DrawFrame(Rect,(*Params).Title, (*Params).Foreground, (*Params).Background);
- PrintTextbox(Rect, (*Params).Message, (*Params).MsgColor, (*Params).Background);
- ShowProgressI(0, 100, Params);
- }
- // Показ прогресса выполнения относительно целой величины
- void ShowProgressI(int Current, int Total, TProgressParams* Params)
- {
- char Gauge[GaugeWidth + 1], Percent[10];
- int i, Space;
- double Progress = 100.0 * Current / Total; // Fix (21.05.2009)
- if (Progress > 100.0) Progress = 100.0;
- if (Progress == (*Params).OldProgress) return;
- (*Params).OldProgress = Progress;
- // Вывожу переменный текст сообщения над индикатором
- PrintTextbox((*Params).Rect, (*Params).Message, (*Params).MsgColor, (*Params).Background);
- // Отступ между индикатором и числом процентов
- if (Progress < 9.95) Space = 3; // Fix (21.05.2009)
- else if (Progress < 100.0) Space = 2;
- else Space = 1;
- GotoXY((*Params).From.Col, (*Params).From.Row);
- GotoXY((*Params).From.Col, (*Params).From.Row);
- // Заполнение индикатора символами
- for (i = 0; i < GaugeWidth; ++i)
- Gauge[i] = SolidBar;
- // Вычисление номера символа, где надо поставить \0x00
- i = (int)(Progress * (GaugeWidth / 100.0)); // ЗАМЕНИТЬ на MakeStr() !!!!!!!!!!!!!!!!!!!!!!!!!!
- if (i <= GaugeWidth)
- Gauge[i] = 0;
- // Вывод индикатора выполненного
- ColorPrint(Gauge, (*Params).clComplete, (*Params).clComplete);
- Gauge[i] = SolidBar; // Возвращаю сивол назад
- // Вычисление номера символа, где надо поставить \0x00
- i = GaugeWidth - (int)(Progress * (GaugeWidth / 100.0));
- Gauge[i] = 0;
- // Вывод индикатора НЕвыполненного
- ColorPrint(Gauge, (*Params).clUncomplete, (*Params).clUncomplete);
- // Вывод процентов
- //sprintf(Percent, "%.1f%%", Progress);
- //sprintf(Percent, "%4.1f%%", Progress);
- sprintf(Percent, " %d%%", (int)Progress);
- //GotoXY((*Params).From.Col + GaugeWidth + 1, WhereY()); // Вывод строки пробелов (поверх процентов)
- //ColorPrint(" ", (*Params).Foreground, (*Params).Background);
- GotoXY((*Params).From.Col + GaugeWidth + Space, WhereY());
- ColorPrint(Percent, (*Params).Foreground, (*Params).Background);
- }
- // Показ прогресса выполнения относительно дробной величины
- void ShowProgressF(float Current, float Total, TProgressParams* Params)
- {
- char Gauge[GaugeWidth + 1], Percent[10];
- int i, Space;
- float Progress = 100.0 * Current / Total;
- if (Progress > 100.0) Progress = 100.0;
- if (Progress == (*Params).OldProgress) return;
- (*Params).OldProgress = Progress;
- // Вывожу переменный текст сообщения над индикатором
- PrintTextbox((*Params).Rect, (*Params).Message, (*Params).MsgColor, (*Params).Background);
- // Отступ между индикатором и числом процентов
- if (Progress < 10.0)
- Space = 3;
- else if (Progress < 100.0)
- Space = 2;
- else Space = 1;
- GotoXY((*Params).From.Col, (*Params).From.Row);
- // Заполнение индикатора символами
- for (i = 0; i < GaugeWidth; ++i)
- Gauge[i] = SolidBar;
- // Вычисление номера символа, где надо поставить \0x00
- i = (int)(Progress * (GaugeWidth / 100.0)); // ЗАМЕНИТЬ на MakeStr() !!!!!!!!!!!!!!!!!!!!!!!!!!
- if (i <= GaugeWidth)
- Gauge[i] = 0;
- // Вывод индикатора выполненного
- ColorPrint(Gauge, (*Params).clComplete, (*Params).clComplete);
- Gauge[i] = SolidBar; // Возвращаю сивол назад
- // Вычисление номера символа, где надо поставить \0x00
- i = GaugeWidth - (int)(Progress * (GaugeWidth / 100.0));
- Gauge[i] = 0;
- // Вывод индикатора НЕвыполненного
- ColorPrint(Gauge, (*Params).clUncomplete, (*Params).clUncomplete);
- // Вывод процентов
- //sprintf(Percent, "%4.1f%%", Progress); // todo : поковырять форматирование
- sprintf(Percent, " %d%%", (int)Progress);
- GotoXY((*Params).From.Col + GaugeWidth + Space, WhereY());
- ColorPrint(Percent, (*Params).Foreground, (*Params).Background);
- }
- // Скрытие окна прогресса и восстановление области экрана из-под него
- void EndProgress(TProgressParams* Params)
- {
- PasteWindow((*Params).Rect, (*Params).ScreenBuffer);
- free((*Params).ScreenBuffer);
- }
- // Показ немодального окна сообщения (окна сообщения с ожиданием)
- void BeginMessageNonModal(TProgressParams* Params)
- {
- TTextRect Rect; // Область окна
- int MaxLen; // для GetLinesCount()
- Rect.Height = GetLinesCount((*Params).Message, &MaxLen) + 2;
- Rect.Width = MaxLen + 2; // Длина окна
- CenterRect(&Rect);
- // Запоминаю участок экрана для последующего восстановления
- // Выделение памяти под прямоугольник с учётом тени
- (*Params).ScreenBuffer = malloc(2 * (Rect.Width * Rect.Height + 2 * Rect.Height + Rect.Width + 2));
- CopyWindow(Rect, (*Params).ScreenBuffer);
- // Запоминаю параметры прогресса
- (*Params).Rect = Rect;
- // Рисую окно ожидания с текстом
- DrawFrame(Rect,(*Params).Title, (*Params).Foreground, (*Params).Background);
- PrintTextbox(Rect, (*Params).Message, (*Params).MsgColor, (*Params).Background);
- }
- // Обновление немодального окна сообщения (окна сообщения с ожиданием)
- void UpdateMessageNonModal(TProgressParams* Params)
- {
- // Вывожу переменный текст сообщения над индикатором
- PrintTextbox((*Params).Rect, (*Params).Message, (*Params).MsgColor, (*Params).Background);
- }
- // Скрытие немодального окна сообщения (окна сообщения с ожиданием)
- void EndMessageNonModal(TProgressParams* Params)
- {
- PasteWindow((*Params).Rect, (*Params).ScreenBuffer);
- free((*Params).ScreenBuffer);
- }
- // Расчёт длины кнопок диалога в символах
- char GetButtonsSpace(UINT Buttons)
- {
- int Index, Count = 0, Space = 0;
- for (Index = 0; Index != ButtonsCount; Index++)
- if (GetBitInt(Buttons, Index))
- {
- Space = Space + strlen(ButtonCaptions[Index]);
- Count++;
- }
- if (Count > 1)
- Space = Space + Count - 1; // Кнопки разделены одним пробелом
- return Space;
- }
- // Вывод строки кнопок окна сообщения начиная с точки From
- void DrawButtons(TMessageParams* Params, TTextPoint From)
- {
- int Index, Len = 0;
- int Count = 0; // Количество кнопок
- GotoXY(From.Col, From.Row);
- for (Index = 0; Index != ButtonsCount; Index++)
- if (GetBitInt((*Params).Buttons, Index))
- {
- Count++;
- Len += strlen(ButtonCaptions[Index]) + 1;
- if (Count != (*Params).DefaultButton) // Кнопка не по умолчанию - рисую цвет текста кнопки = цвет текста, фон кнопки = цвету фона
- ColorPrint(ButtonCaptions[Index], (*Params).TextColor, (*Params).Background);
- /*else // Кнопка по умолчанию - рисую инвертированной
- ColorPrint(ButtonCaptions[Index], ~((*Params).btForeground) & 0x0F, ~((*Params).btBackground) & 0x07);*/
- else // Кнопка по умолчанию (выделенная)
- ColorPrint(ButtonCaptions[Index], (*Params).btForeground, (*Params).btBackground);
- GotoXY(From.Col + Len, From.Row);
- }
- HideCursor(); // Скрытие курсора
- }
- TModalResult GetModalResult(TMessageParams* Params, TTextPoint From)
- {
- char Key, Result, Bit, Count;
- char ButtonCount = GetBitCountInt((*Params).Buttons); // Количество кнопок
- do // цикл опроса клавиатуры
- {
- Key = getch();
- if (!Key) Key = getch(); // Вторичный опрос (для кнопок со стрелками)
- //AddInt2LogF(Key, "Key", IntHex);
- switch (Key)
- {
- case kbTab: // Tab - переключение активной кнопки
- case kbRight: // а также клавиши
- case kbDown: // "вправо" и "вниз"
- if ((*Params).DefaultButton < ButtonCount) ((*Params).DefaultButton)++;
- else (*Params).DefaultButton = 1;
- DrawButtons(Params, From);
- break;
- case kbLeft: // клавиши
- case kbUp: // "влево" и "вверх"
- if ((*Params).DefaultButton > 1) ((*Params).DefaultButton)--;
- else (*Params).DefaultButton = ButtonCount;
- DrawButtons(Params, From);
- break;
- // Если среди кнопок есть кнопка "Отмена", то реакция на ESC
- case kbEsc:
- if ((*Params).Buttons & btCancel) return mrCancel;
- break;
- // Нажатие на активную кнопку (реакция на ENTER)
- // Номер кнопки - это номер установленного бита в (*Params).Buttons
- // справа налево плюс 1
- case kbEnter:
- Count = 0;
- for (Bit = 0; Bit < ButtonsCount; Bit++) // Считаю единицы
- {
- if (((*Params).Buttons >> Bit) & 1) Count++;
- if (Count == (*Params).DefaultButton) return Bit + 1;
- } // for
- break;
- } // switch
- } while (true);
- }
- // Ввод строки
- TModalResult GetInputString(TMessageParams* Params, string S, TTextPoint From, char MaxLength)
- {
- UCHAR Key;
- int i, Len;
- char P[80]; // = (string)malloc(MaxLength + 1);
- char E[80]; // = (string)malloc(MaxLength + 2); // Строка пробелов для затирки вводимых данных при BkSpc
- MakeString(E, ' ', MaxLength + 1);
- MakeString(P, 0, MaxLength);
- //strcpy(P, S);
- //for (i = 0; i < MaxLength; i++) P[i] = 0;
- GotoXY(From.Col, From.Row);
- ColorPrint(E, (*Params).InpForeground, (*Params).InpBackground);
- GotoXY(From.Col, From.Row);
- ColorPrint(P, (*Params).InpForeground, (*Params).InpBackground);
- do // цикл опроса клавиатуры
- {
- Key = getch();
- if (!Key) // Пропускаю функциональные клавиши
- {
- getch();
- continue;
- }
- Len = strlen(P);
- if ((Key > 31) && (Len < MaxLength))
- {
- P[Len] = Key;
- P[Len + 1] = 0;
- GotoXY(From.Col, From.Row);
- ColorPrint(P, (*Params).InpForeground, (*Params).InpBackground);
- }
- else if ((Key == kbBkSpc) && strlen(P))
- {
- P[strlen(P) - 1] = 0;
- GotoXY(From.Col, From.Row);
- ColorPrint(E, (*Params).InpForeground, (*Params).InpBackground);
- GotoXY(From.Col, From.Row);
- ColorPrint(P, (*Params).InpForeground, (*Params).InpBackground);
- }
- } while ((Key != 13) && (Key != 27));
- if (Key == 13)
- {
- strcpy(S, P);
- return mrOk;
- }
- else return mrCancel;
- }
- // Ввод строки со значением по умолчанию.
- TModalResult GetInputStringDef(TMessageParams* Params,
- string S,
- TTextPoint From,
- char MaxLength)
- {
- UCHAR Key;
- int i, Len;
- char P[80]; // = (string)malloc(MaxLength + 1);
- char E[80]; // = (string)malloc(MaxLength + 2); // Строка пробелов для затирки вводимых данных при BkSpc
- MakeString(E, ' ', MaxLength + 1);
- strcpy(P, S);
- GotoXY(From.Col, From.Row);
- ColorPrint(E, (*Params).InpForeground, (*Params).InpBackground);
- GotoXY(From.Col, From.Row);
- ColorPrint(P, (*Params).InpForeground, (*Params).InpBackground);
- do // цикл опроса клавиатуры
- {
- Key = getch();
- if (!Key) // Пропускаю функциональные клавиши
- {
- getch();
- continue;
- }
- Len = strlen(P);
- if ((Key > 31) && (Len < MaxLength))
- {
- P[Len] = Key;
- P[Len + 1] = 0;
- GotoXY(From.Col, From.Row);
- ColorPrint(P, (*Params).InpForeground, (*Params).InpBackground);
- }
- else if ((Key == kbBkSpc) && strlen(P))
- {
- P[Len - 1] = 0;
- GotoXY(From.Col, From.Row);
- ColorPrint(E, (*Params).InpForeground, (*Params).InpBackground);
- GotoXY(From.Col, From.Row);
- ColorPrint(P, (*Params).InpForeground, (*Params).InpBackground);
- }
- }
- while ((Key != 13) && (Key != 27));
- if (Key == 13)
- {
- strcpy(S, P);
- return mrOk;
- }
- else return mrCancel;
- }
- // Отладочная функция. Выводит сообщение об ошибке с текстом Msg,
- // если Condition == false.
- void Assert(const bool Condition, string Msg) // New (02.06.2011)
- {
- TMessageParams EP;
- if (Condition) return;
- GetWindowDefaults(&EP, wndError);
- EP.Title = " Assert ";
- EP.Message = Msg;
- ShowMessage(&EP);
- }
- //==============================================================================
- //=================== Работа с окнами и видеопамятью ===========================
- //==============================================================================
- // Сохранение части экрана в буфере ScreenBuffer
- // Возвращает количество сохранённых символов
- UINT CopyWindow(TTextRect Rect, UINT* Buffer)
- {
- union REGS r;
- register int i, j;
- UINT Saved = 0;
- for (i = Rect.Top; i < Rect.Height + Rect.Top + 1; i++) // + 1 - с учётом тени внизу (1 символ)
- for (j = Rect.Left; j < Rect.Width + Rect.Left + 2; j++) // + 2 - с учётом тени справа (2 символа)
- {
- GotoXY(j, i);
- r.h.ah = 8; // функция чтения символа
- r.h.bh = 0; // видео страница
- *Buffer++ = int86(0x10, &r, &r); // Символ и атрибут - al и ah соответственно
- Saved++;
- } // for
- return Saved;
- }
- // Восстановление части экрана из буфера ScreenBuffer
- void PasteWindow(TTextRect Rect, UINT *ScreenBuffer)
- {
- union REGS r;
- register int i, j;
- for (i = Rect.Top; i < Rect.Height + Rect.Top + 1; i++) // + 1 - с учётом тени внизу (1 символ)
- for (j = Rect.Left; j < Rect.Width + Rect.Left + 2; j++) // + 2 - с учётом тени справа (2 символа)
- {
- GotoXY(j, i);
- r.h.ah = 9; // функция записи символа
- r.h.bh = 0; // видео страница
- r.x.cx = 1; /* число повторений символа */
- r.h.al = (*ScreenBuffer) & 0xFF; /* символ */
- r.h.bl = ((*ScreenBuffer) >> 8) & 0xFF; /* атрибут */
- *ScreenBuffer++;
- int86(0x10, &r, &r);
- } // for
- }
- UINT SaveWindow2File(TTextRect Rect, string FileName)
- {
- union REGS r;
- register int i, j;
- UINT Saved = 0;
- FILE* f;
- if (!(f = fopen(FileName, "w")))
- {
- printf(" Ошибка при открытии файла %s. ", FileName);
- return 0;
- };
- for (i = Rect.Top; i < Rect.Height + Rect.Top; i++)
- {
- for (j = Rect.Left; j < Rect.Width + Rect.Left; j++)
- {
- GotoXY(j, i);
- r.h.ah = 8; // функция чтения символа
- r.h.bh = 0; // видео страница
- int86(0x10, &r, &r);
- putc(r.h.al, f);
- Saved++;
- } // for
- putc('\n', f);
- }
- fclose(f);
- return Saved;
- }
- /* сохранение содержимого экрана в дисковом файле */
- void SaveScreen2File(char *fname)
- {
- FILE *fp;
- union REGS r;
- register char x,y;
- if (!(fp=fopen(fname,"w")))
- {
- printf(" Файл не может быть открыт ");
- exit(1);
- }
- for (y = 0; y<25; y++)
- {
- for (x=0; x<80; x++)
- {
- GotoXY(x, y);
- r.h.ah = 8; /* чтение символа */
- r.h.bh = 0; /* видеостраница */
- int86(0x10, &r, &r);
- putc(r.h.al, fp); /* выдача (печать) символа */
- }
- putc('\n', fp);
- }
- fclose(fp);
- }
- //==============================================================================
- //============================= Работа спамятью ================================
- //==============================================================================
- // Заполнение буфера значениями int.
- // Осторожно! Размер буфера должен быть не меньше Len!
- void FillBufferInt(int* Buffer, int Len,...) // Fix (28.06.2011)
- {
- //int x; // Аргумент(ы) со значениями
- va_list Ptr; // указатель на аргументы
- int Index = 0;
- va_start(Ptr, Len);
- // Заполнение буфера
- while (Index < Len)
- {
- Buffer[Index] = va_arg(Ptr, int);
- Index++;
- }
- va_end(Ptr);
- }
- // Заполнение буфера значениями char.
- // Осторожно! Размер буфера должен быть не меньше Len!
- void FillBufferChar(UCHAR* Buffer, int Len,...) // New (28.06.2011)
- {
- //int x; // Аргумент(ы) со значениями
- va_list Ptr; // указатель на аргументы
- int Index = 0;
- va_start(Ptr, Len);
- // Заполнение буфера
- while (Index < Len)
- {
- Buffer[Index] = (UCHAR)va_arg(Ptr, int);
- Index++;
- }
- va_end(Ptr);
- }
- //==============================================================================
- //============================ Работа со строками ==============================
- //==============================================================================
- // Подсчёт количества строк в сообщении и длины самой длинной из строк MaxLen
- int GetLinesCount(string S, int* MaxLen)
- {
- int Count = 1;
- int max = 0;
- int LineLen = 0; // длина текущей строки сообщения (с учётом \n)
- *MaxLen = 0;
- if (!*S) return 0;
- while (*S)
- {
- // пропускаю символы пользователького цвета текста
- if ((*S >= 0x80) && (*S <= 0x90))
- continue;
- max++, LineLen++;
- // если перенос строки
- if (*S++ == '\n')
- {
- LineLen = 0;
- Count++;
- if ((max - 1) > *MaxLen)
- *MaxLen = max - 1; // -1, чтобы не считать \n
- max = 0;
- } // if
- // если длина строки превышает пределы (вылазит за окно сообщения)
- else if (LineLen == (MaxMessageWidth - 2))
- {
- LineLen = 0;
- Count++;
- *MaxLen = MaxMessageWidth - 2;
- } // else
- } // while
- // Если не проходит по высоте - обрезаю кол-во строк
- if (Count > MaxMessageHeight - 2)
- Count = MaxMessageHeight - 2;
- // Если сообщение однострочное без \n, то MaxLen присваиваю значение здесь
- if (LineLen > *MaxLen)
- *MaxLen = LineLen;
- return Count;
- }
- // Вхождение символа C в состав набора символов Charset
- bool CharInCharset(char C, string Charset)
- {
- while (*Charset)
- if (*Charset++ == C) return true;
- return false;
- }
- // Подсчёт количества вхождений символа C в строке S
- UINT GetCharCount(char C, string S)
- {
- UINT Count = 0;
- while (*S)
- if (*S++ == C) Count++;
- return Count;
- }
- // Центрирование строки относительно ширины поля для её вывода.
- // Возвращает количество символов - смещение влево первого символа строки,
- // чтобы при выводе строка оказалась в середине поля для её вывода
- char CenterString(string S, char Width)
- {
- int L = strlen(S);
- if (L >= Width) // Если строка по длине равна или больше области вывода
- return 0;
- else
- return (Width - L) / 2;
- }
- // Заполнение сроки S символами C и вставка нуля в конец
- // Внимание! Длина строки не проверяется и должна быть больше Count - 1 !!!
- void MakeString(string S, char C, UINT Count)
- {
- UINT Index;
- for (Index = 0; Index < Count; Index++)
- *S++ = C;
- *S = 0;
- }
- // Проверка: строка есть целое десятичное число
- bool StrIsDec(string S)
- {
- if (!*S) return false; // строка пустая?
- if (*S == '0') return false; // с нуля - только восьмеричные числа
- if ((*S == '-') || (*S == '+')) S++; // Впереди может быть знак минус или плюс
- while (*S)
- if (!CharInCharset(*S++, DecDigits)) return false;
- return true;
- }
- // Проверка: строка есть целое шестнадцатеричное число
- bool StrIsHex(string S)
- {
- if (!*S) return false; // строка пустая?
- if (strnicmp(S, "0x", 2)) return false; // строка начинается на (0x | 0X)?
- S += 2; // Продвигаю указатель на 2 символа (пропускаю 0x)
- while (*S)
- if (!CharInCharset(*S++, HexDigits)) return false;
- return true;
- }
- // Проверка: строка есть целое восьмеричное число
- bool StrIsOct(string S)
- {
- if (!*S) return false; // строка пустая?
- if (strncmp(S, "0", 1)) return false; // строка начинается на 0?
- while (*S)
- if (!CharInCharset(*S++, OctDigits)) return false;
- return true;
- }
- // Проверка: строка есть число с плавающей точкой (дробное)
- bool StrIsFloat(string S)
- {
- int eCount = 0;
- if (!*S) return false; // строка пустая?
- if ((*S == '-') || (*S == '+')) S++; // Впереди может быть знак минус или плюс
- // Строка должна начинаться цифрой (если есть знак - после знака):
- if (!CharInCharset(*S, DecDigits)) return false;
- // Строка должна кончаться цифрой:
- if (!CharInCharset(S[strlen(S) - 1], DecDigits)) return false;
- // Десятичная точка может быть одна или не быть совсем
- if (GetCharCount('.', S) > 1) return false;
- // Показатель 10^x (e или E) может быть только 1 шт.
- eCount = GetCharCount('e', S) + GetCharCount('E', S);
- if (eCount > 1) return false;
- // Проверка валидности символов
- while (*S)
- if (!CharInCharset(*S++, FloatSymbols)) return false;
- return true;
- }
- // Перевод строки в 16-битное целое со знаком.
- // Возвращает true, если строка есть (10-чное | 16-чное | 8-чное)
- bool TryStr2Int(string S, int* Value)
- {
- string Format;
- if (StrIsDec(S)) Format = "%d";
- else if (StrIsHex(S)) Format = "0x%x";
- else if (StrIsOct(S)) Format = "%o";
- else return false;
- return sscanf(S, Format, Value);
- }
- // Перевод строки в 32-битное целое со знаком.
- // Возвращает true, если строка есть (10-чное | 16-чное | 8-чное)
- bool TryStr2Long(string S, long* Value)
- {
- string Format;
- if (StrIsDec(S)) Format = "%ld";
- else if (StrIsHex(S)) Format = "0x%lx";
- else if (StrIsOct(S)) Format = "%lo";
- else return false;
- return sscanf(S, Format, Value);
- }
- // Перевод строки в десятичное (с пл. точкой) со знаком
- bool TryStr2Float(string S, float* Value)
- {
- //AddStr2Log(S, "S"); // для отладки
- if (StrIsFloat(S))
- return sscanf(S, "%f", Value);
- else
- return false;
- }
- // Перевод строки в десятичное (с пл. точкой) со знаком двойной точности
- bool TryStr2Double(string S, double* Value)
- {
- //AddStr2Log(S, "S");
- if (StrIsFloat(S))
- return sscanf(S, "%lf", Value);
- else
- return false;
- }
- // Проверка длины введённого числа на разрядность
- // BitCount = (16 | 32)
- // ==== интервалы для 16 бит: ====
- // - -32768...+32767
- // - 0x0000...0xFFFF
- // - 0000000...0177777
- // ==== интервалы для 32 бит: ====
- // - -2147483648...+2147483647
- // - 0x00000000...0xFFFFFFFF
- // - 00000000000...37777777777
- bool CheckIntLength(string Value, char BitCount)
- {
- string Limit; // Эталон
- // ----------- 16-битные ------------
- if (BitCount == 16)
- {
- if (StrIsDec(Value)) // Десятичные
- {
- if (*Value == '-') Limit = "-32768"; // отрицательное
- else if (*Value == '+') Limit = "+32767"; // положительное с плюсом
- else Limit = "32767"; // положительное, начинающееся с цифры
- } // if
- else if (StrIsHex(Value)) Limit = "0xFFFF"; // 16-ричные
- else if (StrIsOct(Value)) Limit = "0177777"; // 8-ричные
- else return false; // Ваще не число!
- } // if (BitCount == 16)
- // ----------- 32-битные ------------
- else
- {
- if (StrIsDec(Value)) // Десятичные
- {
- if (*Value == '-') Limit = "-2147483648"; // отрицательное
- else if (*Value == '+') Limit = "+2147483647"; // положительное с плюсом
- else Limit = "2147483647"; // положительное, начинающееся с цифры
- } // if
- else if (StrIsHex(Value)) Limit = "0xFFFFFFFF"; // 16-ричные
- else if (StrIsOct(Value)) Limit = "37777777777"; // 8-ричные
- else return false; // Ваще не число!
- } // else
- //--- Вывод в лог ----
- //AddStr2Log(Value, "Value");
- //AddStr2Log(Limit, "Limit");
- // сразу на выход, если длина строки не равна длине эталона
- // функция strcmpi() выдаёт тогда неверный результат, а мне оно не надо
- if (strlen(Limit) < strlen(Value)) return false;
- if (strlen(Limit) > strlen(Value)) return true;
- // И только при равенстве длин этих строк их можно нормально сравнивайть побайтно
- if (strcmpi(Value, Limit) > 0) return false;
- else return true;
- }
- // Загрузка текстового файла в строку с выделением памяти под неё.
- // Символы <cr><lf> заменяются на <lf>, в конце добавляется 0.
- // В параметре Len возвращается длина строки (исключая последний 0).
- // Функция возвращает указатель на строку. Для освобождения памяти
- // используй функцию free().
- // В случае ошибки функция возвратит NULL.
- /*string LoadStrFromFile(string FileName)
- {
- UINT iSize; // 16 бит (вполне, чтоб не путаться с лонгами, это геморрой)
- UINT Readed; // сколько прочитано
- string Result = NULL;
- int hFile = open(FileName, O_RDONLY | O_TEXT);
- if (hFile != -1)
- //AddInt2Log(hFile, "hFile");
- if (Result)
- {
- iSize = ((UINT)(filelength(hFile) & 0xFFFF));
- //AddInt2Log(iSize, "iSize");
- Result = malloc(iSize + 1); // +1 - для завершающего нуля, это же строка!
- if (Result)
- {
- Readed = read(hFile, Result, iSize);
- Result[Readed] = 0; // Заверщающий ноль
- close(hFile);
- }
- else Result = false;
- }
- return Result;
- } */
- //==============================================================================
- //================= Математические и логические функции ========================
- //==============================================================================
- // Функции НОРМАЛЬНОГО округления дробного числа до целого с учётом знака
- // Не нашёл аналога в стандартных функциях, поэтому пришлось написать
- // аналог паскалевской функции Round().
- int RoundI(float X)
- {
- double IntPart;
- double Frac = modf(X, &IntPart);
- if (fabs(Frac) < 0.5) return (int)floor(X); // Округление до меньшего целого
- else return (int)ceil(X); // Округление до большего целого
- }
- long RoundL(float X)
- {
- double IntPart;
- double Frac = modf(X, &IntPart);
- if (fabs(Frac) < 0.5) return (long)floor(X); // Округление до меньшего целого
- else return (long)ceil(X); // Округление до большего целого
- }
- // Проверка, установлен ли бит номер Bit в 16-битном целом
- bool GetBitInt(UINT Value, char Bit)
- {
- return ((1 << Bit) & Value);
- }
- // Подсчёт количества установленных бит в 16-битном целом
- char GetBitCountInt(UINT Value)
- {
- char Index, Count = 0;
- for (Index = 0; Index != 16; Index++)
- if ((Value >> Index) & 1) Count++;
- return Count;
- }
- // Является ли 16-битное целое Value в пределах LoLimit <= Value <= HiLimit
- bool BetweenInt(int Value, int LoLimit, int HiLimit)
- {
- //if ((Value >= LoLimit) && (Value <= HiLimit)) return true;
- //else return false;
- return ((Value >= LoLimit) && (Value <= HiLimit)); // fix (17.08.2010)
- }
- // Является ли 32-битное целое Value в пределах LoLimit <= Value <= HiLimit
- bool BetweenLong(long Value, long LoLimit, long HiLimit)
- {
- //if ((Value >= LoLimit) && (Value <= HiLimit)) return true;
- //else return false;
- return ((Value >= LoLimit) && (Value <= HiLimit)); // fix (17.08.2010)
- }
- // Является ли дробное Value в пределах LoLimit <= Value <= HiLimit
- bool BetweenFloat(float Value, float LoLimit, float HiLimit)
- {
- //AddFloat2Log(Value, "Value");
- //AddFloat2Log(LoLimit, "LoLimit");
- //AddFloat2Log(HiLimit, "HiLimit");
- //if (((Value - LoLimit) >= 0) && ((Value - HiLimit) <= 0)) return true;
- //else return false;
- //if ((Value >= LoLimit) && (Value <= HiLimit)) return true;
- //else return false;
- return ((Value >= LoLimit) && (Value <= HiLimit)); // fix (17.08.2010)
- }
- //==============================================================================
- //========================== Работа с лог-файлом ===============================
- //==============================================================================
- // Открытие лог-файла
- bool OpenLog(string FileName)
- {
- char Time[10];
- LogFile = fopen(FileName, "w");
- if (LogFile)
- {
- _strtime(Time);
- fprintf(LogFile, LogDivider);
- fprintf(LogFile, " Лог начат %s\n", Time);
- fprintf(LogFile, LogDivider);
- }
- return (LogFile != 0);
- }
- // Закрытие лог-файла
- void CloseLog(void)
- {
- if (LogFile)
- {
- fprintf(LogFile, LogDivider);
- fclose(LogFile);
- }
- }
- // Добавление в лог простой строки
- void Add2Log(string S)
- {
- if (LogFile)
- {
- fprintf(LogFile, "%s\n", S);
- fflush(LogFile);
- }
- }
- // Добавление в лог значения 8-битного char:
- // - в формате Name = 'Value' [0xXX] при Value > 31;
- // - в формате Name = {Value} [0xXX] при Value <= 31;
- void AddChar2Log(UCHAR Value, string Name)
- {
- if (LogFile)
- {
- if (Value > 31) fprintf(LogFile, " %s = '%c' [0x%02X]\n", Name, Value, Value);
- else fprintf(LogFile, " %s = {%d} [0x%02X]\n", Name, Value, Value);
- fflush(LogFile);
- }
- }
- // Добавление в лог значение 16-битного целого в формате Name = Value
- void AddInt2Log(int Value, string Name)
- {
- if (LogFile)
- {
- fprintf(LogFile, " %s = %d\n", Name, Value);
- fflush(LogFile);
- }
- }
- // Добавление в лог значение 16-битного целого в формате Name = Value
- // в системе счисления F = (IntDec | IntHex | IntOct)
- void AddInt2LogF(int Value, string Name, char F)
- {
- if (LogFile)
- {
- switch (F)
- {
- case IntDec:
- fprintf(LogFile, " %s = %d\n", Name, Value);
- break;
- case IntHex:
- fprintf(LogFile, " %s = 0x%04X\n", Name, Value);
- break;
- case IntOct:
- fprintf(LogFile, " %s = %07o\n", Name, Value);
- break;
- } // switch
- fflush(LogFile);
- }
- }
- // Добавление в лог значение 32-битного целого в формате Name = Value
- void AddLong2Log(long Value, string Name)
- {
- if (LogFile)
- {
- fprintf(LogFile, " %s = %ld\n", Name, Value);
- fflush(LogFile);
- }
- }
- // Добавление в лог значения с плав. точкой в формате Name = Value
- void AddFloat2Log(float Value, string Name)
- {
- if (LogFile)
- {
- fprintf(LogFile, " %s = %f\n", Name, Value);
- fflush(LogFile);
- }
- }
- // Добавление в лог значения с плав. точкой double в формате Name = Value
- void AddDouble2Log(double Value, string Name)
- {
- if (LogFile)
- {
- fprintf(LogFile, " %s = %lf\n", Name, Value);
- fflush(LogFile);
- }
- }
- // Добавление в лог значения логического типа в формате Name = (true | false)
- void AddBool2Log(bool Value, string Name)
- {
- if (LogFile)
- {
- if (Value) fprintf(LogFile, " %s = true\n", Name);
- else fprintf(LogFile, " %s = false\n", Name);
- fflush(LogFile);
- }
- }
- // Добавление в лог строкового эквивалента TModalResult
- void AddModalResult2Log(TModalResult Value)
- {
- if (LogFile && (Value <= ButtonsCount))
- {
- if (Value)
- fprintf(LogFile, " ModalResult = %s (%d)\n", ButtonCaptions[Value - 1], Value);
- else
- fprintf(LogFile, " ModalResult = mrNone (0)\n");
- fflush(LogFile);
- }
- }
- // Добавление в лог значения строки в формате Name = Value
- void AddStr2Log(string Value, string Name)
- {
- if (LogFile)
- {
- fprintf(LogFile, " %s = %s\n", Name, Value);
- fflush(LogFile);
- }
- }
- void AddRect2Log(TTextRect Value, string Name)
- {
- if (LogFile)
- {
- fprintf(LogFile, " %s: Left = %d, Top = %d, Width = %d, Height = %d\n",
- Name, Value.Left, Value.Top, Value.Width, Value.Height);
- fflush(LogFile);
- }
- }
- //==============================================================================
- //======================= Работа с файлом настроек =============================
- //==============================================================================
- // Загрузка настроек в буфер
- /*bool LoadIni(string FileName)
- {
- int hFile = open(FileName, O_RDONLY | O_TEXT);
- bool Result = (hFile != -1);
- UINT iSize; // 16 бит (вполне, чтоб не путаться с лонгами, это геморрой)
- UINT Readed; // сколько прочитано
- int i;
- AddInt2Log(hFile, "hFile");
- if (Result)
- {
- iSize = ((UINT)(filelength(hFile) & 0xFFFF));
- AddInt2Log(iSize, "iSize");
- Ini = malloc(iSize + 1); // +1 - для завершающего нуля, это же строка!
- //for (i = 0; i != (iSize + 1); i++) Ini[i] = 0; // Обнуление буфера
- if (Ini)
- {
- Readed = read(hFile, Ini, iSize);
- Result = (Readed != -1);
- Ini[Readed] = 0; // Заверщающий ноль
- close(hFile);
- }
- else Result = false;
- }
- return Result;
- }
- // Освобождение памяти из-под буфера Ini
- void FreeIni(void)
- {
- if (Ini) free(Ini);
- }
- // Чтение целого параметра с именем Name из Ini в Value.
- // Если чтение произвести невозможно по причинам:
- // * буфер не инициализирован (NULL);
- // * параметра с именем Name не существует;
- // * строку, сопоставленную имени параметра не удалось перевести в число,
- // функция возвращает значение Default.
- int IniReadInt(string Name, int Default)
- {
- } */
- //==============================================================================
- //====================== Работа с датой и временем =============================
- //==============================================================================
- // ================== Декодирование времени ========================
- void DecodeTime(float Seconds, TTimeStamp* T)
- {
- double Trunc; // Секунды
- long Sec; // Целое число секунд всего
- double Frac = modf(Seconds, &Trunc); // миллисекунды
- if (Frac < 0.0) Frac = 0.0; // Чтобы не было отрицательного времени
- Sec = (long)floor(Trunc); // Целое число секунд всего
- (*T).Hr = Sec / 3600; // Часы
- (*T).Min = (Sec % 3600) / 60; // Минуты в часе
- (*T).Sec = Sec % 60; // Секунды в минуте
- (*T).mSec = (UINT)floor(Frac * 1e+3); // Целое число миллисекунд
- }
- // Задержка не менее mSeconds миллисекунд
- void Sleep(ULONG mSeconds)
- {
- ULONG Estimated = 0;
- ULONG Begin = clock();
- // clock() - кол-во миллисекунд, прошедших от запуска программы
- long Cycles = 0; // Debug
- do
- {
- Estimated = labs(clock() - Begin);
- Cycles++;
- } while (Estimated < mSeconds);
- }
- // Задержка Seconds секунд (дробное число) с показом прогресса выполнения.
- // Возвращает false, если юзер нажал "отмену". При Seconds < 0.5 окно прогресса
- // не показывается.
- bool Delay(float Seconds, TProgressParams* Params)
- {
- char Key = 0;
- float Estimated = 0.0; // кол-во СЕКУНД, прошедших от запуска функции
- float Remained; // кол-во СЕКУНД, оставшихся до конца задержки
- float Begin = clock() / 1000.0; // кол-во СЕКУНД, прошедших от запуска проги
- long Count = 0; // для отладки
- TTimeStamp T; // Для отображения оставшегося времени и заголовка
- char Title[40]; // Для формирования заголовка окна
- // При Seconds < 0.5 окно прогресса не показывается
- if (Seconds < 0.5)
- {
- Sleep((ULONG)RoundL(Seconds * 1000));
- return true;
- }
- // Перевод Seconds в строку типа HH:MM:SS.mS и вывод в заголовок
- DecodeTime(Seconds, &T);
- #ifdef Codepage_DOS
- sprintf(Title, " Delay %02d:%02d:%02d.%03d ", T.Hr, T.Min, T.Sec, T.mSec);
- #endif
- #ifdef Codepage_ISO
- sprintf(Title, " Задержка %02d:%02d:%02d.%03d ", T.Hr, T.Min, T.Sec, T.mSec);
- #endif
- (*Params).Title = Title;
- // Вывод онка задержки
- BeginProgress(Params);
- // Цикл задержки с выводом прогресса выполнения
- do
- {
- Estimated = fabs((clock() / 1000.0) - Begin);
- Remained = Seconds - Estimated;
- // Перевод Remained в строку типа HH:MM:SS.mS и вывод, сколько осталось времени
- DecodeTime(Remained, &T);
- #ifdef Codepage_DOS
- sprintf(Title, " Remain time %02d:%02d:%02d.%03d ", T.Hr, T.Min, T.Sec, T.mSec);
- #endif
- #ifdef Codepage_ISO
- sprintf(Title, " Осталось %02d:%02d:%02d.%03d ", T.Hr, T.Min, T.Sec, T.mSec);
- #endif
- (*Params).Message = Title;
- ShowProgressF(Estimated, Seconds, Params);
- // Проверка клавиши ESC
- if (kbhit()) Key = getch();
- Count++;
- }
- while ((Estimated < Seconds) && (Key != 27)); // do
- // Скрытие окна задержки
- EndProgress(Params);
- //AddLong2Log(Count, "Count");
- return (Key != 27);
- }
- //==============================================================================
- //========================== Работа со звуком ==================================
- //=========(не поверил бы, что работает в WinXP, пока не сам не проверил)=======
- //==============================================================================
- // Звучание динамика на частоте Frequency в течение Pause миллисекунд
- void Beep(UINT Frequency, ULONG Pause)
- {
- UCHAR Temp;
- union // Счётчик
- {
- ULONG Divisor;
- UCHAR Bytes[2];
- }
- Count;
- Count.Divisor = SysTimerFreq / Frequency; // вычисление небходимого значения счетчика
- outp(0x43, 0xB6); // обращение к таймеру 8253 после установки счетчика
- outp(0x42, Count.Bytes[0]); // пересылка младшего байта
- outp(0x42, Count.Bytes[1]); // пересылка старшего байта
- Temp = inp(0x61); // чтение существующего шаблона бит
- outp(0x61, (Temp | 0x03)); // установка битов 0 и 1
- Sleep(Pause); // Задержка в миллисекундах
- outp(0x61, Temp); // восстановление первоначального значения шаблона бит для отключения динамика
- }
- UCHAR sndTemp; // Для след. 2х функций (содержимое порта 0x61)
- // Включение звучания динамика на частоте Frequency
- void Sound(UINT Frequency)
- {
- union // Счётчик
- {
- ULONG Divisor;
- UCHAR Bytes[2];
- }
- Count;
- Count.Divisor = SysTimerFreq / Frequency; // вычисление небходимого значения счетчика
- outp(0x43, 0xB6); // обращение к таймеру 8253 после установки счетчика
- outp(0x42, Count.Bytes[0]); // пересылка младшего байта
- outp(0x42, Count.Bytes[1]); // пересылка старшего байта
- sndTemp = inp(0x61); // чтение существующего шаблона бит
- outp(0x61, (sndTemp | 0x03)); // установка битов 0 и 1
- }
- // Включение звучания динамика
- void NoSound(void)
- {
- outp(0x61, sndTemp); // восстановление первоначального значения шаблона бит для отключения динамика
- }
- /*
- ================================== Памятка ===================================
- 1. Сделать нормальную работу со строками через realloc(), т.е. чтоб были
- функции Insert(), Delete() и прочие.
- + 2. Сделать звук типа Sound(Frequency).
- + 3. Сделать функции ввода целого, дробного.
- + 4. При вводе под DOS первого символа какая-то херня творится со строкой ввода.
- 5. Сделать работу с файлом настроек.
- 6. Сделать функцию, возвращающую текущую версию модуля и дату компиляции.
- 7. Сделать функции ввода с пределами.
- */
- //==============================================================================
- //=========================== Работа с клавиатурой =============================
- //==============================================================================
- // Проверка нажатия клавиши с кодом Key
- bool KeyPressed(UCHAR Key) // New (17.06.2010)
- {
- if (kbhit())
- if (getch() == Key) return true;
- return false;
- }
- // Проверка нажатия клавиши Escape
- bool EscapePressed(void) // New (17.06.2010)
- {
- if (kbhit())
- if (getch() == kbEsc) return true;
- return false;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement