| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 | #include "terminal.h"#include <string.h>#include <stdarg.h>static char tmpCommand[40];//-----------------------------------------------------------------------------// Microrl callbacks//-----------------------------------------------------------------------------extern "C" {    //Configure terminal    void configure_terminal() {        pTerminal->configure();    }    //Print micrrl callback    void print_terminal(const char *str) {        pTerminal->print(str);    }    //Execute microrl callback    int execute_terminal(int argc, const char * const * argv) {        return pTerminal->execute(argc, argv);}    //Sigint microrl callback    void sigint_terminal (void) {        pTerminal->sigint();}        //Complete microrl callback    char** completion_terminal (int argc, const char * const * argv) {        return pTerminal->completion(argc, argv);}}//-----------------------------------------------------------------------------// Terminal class//-----------------------------------------------------------------------------Terminal::Terminal():    m_countPrintFunction(0),    prl(&rl){    memset(&f_print, 0, sizeof(f_print));    memset(tmpCommand, 0, sizeof(tmpCommand));}//Configure microrl callbacksvoid Terminal::configure(){      m_countPrintFunction = 0;    prl = &rl;    memset(&f_print, 0, sizeof(f_print));    memset(tmpCommand, 0, sizeof(tmpCommand));	    microrl_init (prl, ::print_terminal);    microrl_set_execute_callback (prl, ::execute_terminal);    microrl_set_sigint_callback (prl, ::sigint_terminal);    microrl_set_complete_callback (prl, ::completion_terminal);}void Terminal::connectCallback() {    printeol();    printll("Hello stranger. It is goot day for work :)");    }//Insert char to microrlvoid Terminal::insert(int ch) {    microrl_insert_char(prl, ch);}//Out message to all terminalsvoid Terminal::print(const char *str) {    for (int i = 0; i < m_countPrintFunction; i++) {        if (f_print[i] != 0) {            f_print[i](str);        }    }}void Terminal::printl(const char * str) {    print(str);    print(EOL);}void Terminal::printll(const char * str) {    print(str);    print(EOL);    print(EOL);}void Terminal::eol() {    print(EOL);}void Terminal::printeol() {    print(EOL);}//Execute microrl callbacksint Terminal::execute(int argc, const char * const *argv) {    return 0;}char* helloNull[] = {0};//Comletion microrl callbackschar ** Terminal::completion(int argc, const char * const * argv) {    int i = 0;    i++;    return helloNull;}//Sigint microrl callbacksvoid Terminal::sigint(){}//Add external print functionvoid Terminal::addPrint(InterfacePrint print_func) {    if (m_countPrintFunction < COUNT_TERMINAL_INTERFACE) {        f_print[m_countPrintFunction] = print_func;        m_countPrintFunction++;    }}//-----------------------------------------------------------------------------// Вывод команд в терминал//-----------------------------------------------------------------------------//Очистка экранаvoid Terminal::clearScreen() {    //Clear    print("\033[2J");            //Move to up left corner    print("\033[H");    }//Сдвинуть в указанную позициюvoid Terminal::moveToPos(uint32_t h, uint32_t v){    uint32_t sizeCommand = 0;    getCommand_MoveToPos(tmpCommand, sizeCommand, h, v);    print(tmpCommand);}//Сдвинуть в верхний левый уголvoid Terminal::moveToUpLeftCorner() {    //Move to up left corner    print("\033[H");    }//Reset terminal to initial state void Terminal::reset() {    //Сбросить настройки терминала    print("\033c");}//Сбросить аттрибуты текстаvoid Terminal::resetAttribute() {    print("\033[0m");}//Сохранить позицию курсора и атрибутыvoid Terminal::saveCursorPos() {    //Save cursor position and attributes     print("\0337");    }//Востановить позицию курсора и аттрибутыvoid Terminal::restoreCursorPos() {    //Restore cursor position and attributes     print("\0338");    }//Скрыть курсовvoid Terminal::hideCursor() {    print("\033[8m");}//Очистить строкуvoid Terminal::clearCurrentLine() {    print("\033[2K");}void write(const char* src, int src_size, char* dst, uint32_t& size) {    memcpy(&dst[size], src, src_size);    size += src_size;}//Формирование команды для установки курсора в заданную позициюuint32_t Terminal::getCommand_MoveToPos(    char* res_command, uint32_t& res_size, uint32_t h, uint32_t v){        //Esc[Line;ColumnH    res_size = 0;        write("\x1B[", 2, res_command, res_size);                char* vStr = utoa(v);    uint32_t sizeV = strlen(vStr);    write(vStr, sizeV, res_command, res_size);        write(";", 1, res_command, res_size);        char* hStr = utoa(h);    uint32_t sizeH = strlen(hStr);    write(hStr, sizeH, res_command, res_size);    write("H", 1, res_command, res_size);    write("\0", 1, res_command, res_size);     return res_size;}//Формирование команды для сдвига курсора вверх на n позицийuint32_t Terminal::getCommand_MoveUpNLines(    char* res_command, uint32_t& res_size, uint32_t n){    return 0;}//Формирование команды для сдвига курсора вниз на n позицийuint32_t Terminal::getCommand_MoveDownNLines(    char* res_command, uint32_t& res_size, uint32_t n){    return 0;}//Формирование команды для сдвига курсора вправо на n позицийuint32_t Terminal::getCommand_MoveRightNLines(    char* res_command, uint32_t& res_size, uint32_t n){    return 0;}//Формирование команды для сдвига курсора влево на n позицийuint32_t Terminal::getCommand_MoveLeftNLines(    char* res_command, uint32_t& res_size, uint32_t n){    return 0;}//Формирование команды для установки цвета текстаuint32_t Terminal::getCommand_SetTextColor(char* res_command, uint32_t& res_size, TextColor color){    //Esc[3ColorH    res_size = 0;        write("\x1B[3", 3, res_command, res_size);            char* vStr = utoa(color);    write(vStr, 1, res_command, res_size);    write("m", 1, res_command, res_size);       write("\0", 1, res_command, res_size);             return res_size;}//Формирование команды для установки аттрибута подчёркиванияuint32_t Terminal::getCommand_UnderlineText(char* res_command, uint32_t& res_size){    res_size = 0;        write("\x1B[4m", 4, res_command, res_size);    write("\0", 1, res_command, res_size);     return res_size;}//-----------------------------------------------------------------------------// Класс реализации таблицы//-----------------------------------------------------------------------------Table::Table() {}//-----------------------------------------------------------------------------// Вывод элементов таблицы//-----------------------------------------------------------------------------//Вывод сктроки в заданную ячейкуvoid Table::outToCell(uint8_t col, uint8_t row, const char* str) {    //CellAttribute &cell = cells[col][row];    //print(cell.pos_command);    //print(cell.color_command);    pTerminal->resetAttribute();        //Выводим атрибуты    CellAttribute &cell = cells[col][row];        print(cell.attributes);        //Выводим строку    print(str);        //Выводим пробелы на до конца ячейки    int32_t countSpace = m_width[col] - strlen(str) - 1;     for (uint8_t i = 0; i < countSpace; i++)        print(" ");        }//Вывод значения в заданную ячейкуvoid Table::outToCell(uint8_t col, uint8_t row, uint32_t val)  {    outToCell(col, row, utoa(val));}//Выводим в нужную строку разделяющую линиюvoid Table::outCrossLine(uint8_t row) {        uint32_t line = m_y + row;    pTerminal->moveToPos(m_x, line);    printCrossLine(line);        }//Вывод внешней границы в строкеvoid Table::outExternalBorder() {        uint32_t line = m_y;                    printTopLine(line);            for (uint8_t r = 0; r < m_row; r++)        printTextLine(line);        printBottomLine(line);                                                      }//Печать статической части таблицыvoid Table::outStatic() {    pTerminal->saveCursorPos();    outExternalBorder();    pTerminal->restoreCursorPos();    }//Печатает в таблице счётчик ячеекvoid Table::outCellNumber(){    uint32_t count = 0;    for (uint8_t c = 0; c < m_col; c ++) {        for (uint8_t r = 0; r < m_row; r++) {            print(cells[c][r].attributes);                        print(utoa(count));            count ++;        }    }}void Table::startUpdate() {    pTerminal->saveCursorPos();}void Table::endUpdate() {    pTerminal->restoreCursorPos();}//-----------------------------------------------------------------------------// Конфигурация талицы//-----------------------------------------------------------------------------//Задать геометрию таблицы void Table::setGeometry(uint8_t x, uint8_t y, uint8_t col, uint8_t row, uint32_t width, ...){       setPos(x, y);    setSize(col, row);        if ((m_col == 0) || (m_row == 0))        return;        //Читаем ширину колонок    va_list ap;    va_start(ap, width);         uint8_t c = 0;    m_width[c] = width;        do {        c++;        m_width[c] = va_arg(ap, int32_t);    } while (c < m_col);                va_end(ap);          resetAttributes();    }//Задать геометрию таблицы void Table::setGeometry(uint8_t x, uint8_t y, uint8_t col, uint8_t row, const uint32_t* width) {    setPos(x, y);    setSize(col, row);        if ((m_col == 0) || (m_row == 0))        return;        for (int c = 0; c < m_col; c++)        m_width[c] = width[c];               resetAttributes();    }//Установить позицию таблицыvoid Table::setPos(uint8_t x, uint8_t y) {     m_x = x; m_y = y;}//Установить размеры таблицыvoid Table::setSize(uint8_t col, uint8_t row) {    m_col = col;    m_row = row;        if (m_col > MAX_COL)        m_col = MAX_COL;        if (m_row > MAX_ROW)        m_row = MAX_ROW;}//Сброс аттрибутов для ячеекvoid Table::resetAttributes(){    //Добавляем аттрибут для перемещения    //курсора в начало каждой ячейки    for (uint8_t c = 0; c < m_col; c ++) {        for (uint8_t r = 0; r < m_row; r++) {            clearCellAttributes(c, r);                        addCellPosAttribute(c, r);                      }    }}//-----------------------------------------------------------------------------// Работа с аттрибутами//-----------------------------------------------------------------------------//Атрибуты - строка с управляющими командами для//терминала VT100, которые выводятся в терминал//перед выводом в ячейку (перемещение курсора//на ячейку, установка цвета)static char tmpAttr[20];static uint32_t tmpAttrSize = 0; //Расчитать для начала ячейки позицию курсора void Table::addCellPosAttribute(uint8_t col, uint8_t row) {             //Расчитываем позицию курсора для ячейки    uint32_t y = m_y + 1;    uint32_t x = m_x + 1;        for (uint32_t c = 0; c < col; c++)        x += m_width[c];        x += col;    y += row;        //Формируем команду перемещения курсора в рассчитанную позицию    pTerminal->getCommand_MoveToPos(tmpAttr, tmpAttrSize, x, y);        addCellAttribute(col, row, tmpAttr);        }//Добавить аттрибут цвета текстаvoid Table::addCellColorAttribute(uint8_t col, uint8_t row, TextColor color) {    pTerminal->getCommand_SetTextColor(tmpAttr, tmpAttrSize, color);     addCellAttribute(col, row, tmpAttr);     }//Добавить аттрибут цвета текстаvoid Table::addCellUnderlineAttribute(uint8_t col, uint8_t row) {    pTerminal->getCommand_UnderlineText(tmpAttr, tmpAttrSize);     addCellAttribute(col, row, tmpAttr);     }//Очистить аттрибуты ячейки void Table::clearCellAttributes(uint8_t col, uint8_t row) {              CellAttribute& cell = cells[col][row];        cell.text = 0;            char* attributes = cell.attributes;    uint32_t attrSize = sizeof(cell.attributes);        memset(attributes, 0, attrSize);}//Дописать аттрибут к ячейкеvoid Table::addCellAttribute(uint8_t col, uint8_t row, const char* attr) {    CellAttribute& cell = cells[col][row];            uint8_t attrSize = strlen(cell.attributes);        char* dst = &cell.attributes[attrSize];        attrSize = strlen(attr);    memcpy(dst, attr, attrSize);}//-----------------------------------------------------------------------------// Работа с выводом элементов рамки//-----------------------------------------------------------------------------//Символы псевдографики//----------------------------------------//─│┌┐└┘├┤┬┴┼═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥╦╧╨╩╪╫╬//----------------------------------------//Печать верхней границы рамкиvoid Table::printTopLine(uint32_t& line) {    printFrameLine(line, "┌", "┐", "┬", "─");}//Печать линии в таблицеvoid Table::printCrossLine(uint32_t& line) {    printFrameLine(line, "├", "┤", "┼", "─");}//Печать рамки для отдельной строкиvoid Table::printTextLine(uint32_t& line) {    printFrameLine(line, "│", "│", "│", " ");}//Печать нижней границы рамки таблицыvoid Table::printBottomLine(uint32_t& line) {    printFrameLine(line, "└", "┘", "┴", "─");}////Печать верхней границы рамки//void Table::printTopLine(uint32_t& line) {//    printFrameLine(line, "╔", "╗", "╤", "═");//}////Печать линии в таблице//void Table::printCrossLine(uint32_t& line) {//    printFrameLine(line, "╟", "╢", "┼", "─");//}////Печать рамки для отдельной строки//void Table::printTextLine(uint32_t& line) {//    printFrameLine(line, "║", "║", "│", " ");//}////Печать нижней границы рамки таблицы//void Table::printBottomLine(uint32_t& line) {//    printFrameLine(line, "╚", "╝", "╧", "═");//}//Выводит строку рамки таблицыvoid Table::printFrameLine(uint32_t& line,     const char* lc, const char* rc, const char* cr, const char* ln){    pTerminal->moveToPos(m_x, line);        //Left corner    print(lc);        for (uint8_t c = 0; c < m_col; c++)     {        //Print line charachter        uint8_t width = 0;        while (width < m_width[c]) {            print(ln);            width++;        }        if (c < (m_col - 1))             //Print cross character            print(cr);        else            //Print right corner            print(rc);      }    line++;}void Table::print(const char* str) {    pTerminal->print(str);}//-----------------------------------------------------------------------------// Преобразование числа в строку ANSI C через быстрое деление//-----------------------------------------------------------------------------struct divmod10_t{    uint32_t quot;    uint8_t rem;};inline static divmod10_t divmodu10(uint32_t n){    divmod10_t res;    res.quot = n >> 1;    res.quot += res.quot >> 1;    res.quot += res.quot >> 4;    res.quot += res.quot >> 8;    res.quot += res.quot >> 16;    uint32_t qq = res.quot;    res.quot >>= 3;    res.rem = uint8_t(n - ((res.quot << 1) + (qq & ~7ul)));    if(res.rem > 9)    {        res.rem -= 10;        res.quot++;    }    return res;}static char utoaBuffer[13];//utoa fast divchar * utoa(uint32_t value){    char* buffer = &utoaBuffer[1];    buffer += 11;    *--buffer = 0;    do    {        divmod10_t res = divmodu10(value);        *--buffer = res.rem + '0';        value = res.quot;    }    while (value != 0);    return buffer;}//utoa fast divchar * itoa(int32_t value){    //Чёто неохото было гуглить. Мой    //тупой вариант взятия модуля    uint32_t unsignedValue = value;    if (value < 0)        unsignedValue = (uint32_t)(value - (2*value));        char* unsignedStr = utoa(unsignedValue);        //Добавляем знак минус в начало    if (value < 0) {        unsignedStr--;        *unsignedStr = '-';           }               return unsignedStr;}
 |