/* Miranda NG: the free IM client for Microsoft* Windows* Copyright (с) 2012-17 Miranda NG project (https://miranda-ng.org), Copyright (c) 2000-08 Miranda ICQ/IM project, all portions of this codebase are copyrighted to the people listed in contributors.txt. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Created by Anton Senko aka ZORG , tweaked by Artem Shpynov aka FYR */ #include "stdafx.h" void rowCalculateMinSize(ROWCELL* cell); void rowEqualize(ROWCELL* cell); void rowResetEmptyRects(ROWCELL* cell); void rowDeleteTree(ROWCELL* cell); //extern ROWCELL * gl_RowRoot; // Указатель на корневой тэг < contact> в шаблоне //ROWOBJECTS RowTA; // Структура, через которую осуществляется доступ к элементам контакта. // Формируется при выполнении фу-и RowParce. Неявный параметр фуи rowParserGetParam // Формируется при выполнении фу-и RowParce. Неявный параметр фуи rowParserGetParam char *tmplbuf; // Буфер для хранения шаблона в текстовом виде ROWCELL *cppInitModernRow(ROWCELL ** tabAccess) { int fsize; int seq = 0; ROWCELL * RowRoot = nullptr; FILE * hFile; int i = 0; if (!db_get_b(0, "ModernData", "UseAdvancedRowLayout", SETTING_ROW_ADVANCEDLAYOUT_DEFAULT)) return nullptr; tmplbuf = nullptr; if (db_get_b(0, "ModernData", "UseAdvancedRowLayout", SETTING_ROW_ADVANCEDLAYOUT_DEFAULT) == 1) tmplbuf = db_get_sa(0, "ModernData", "RowTemplate"); if (tmplbuf) { rowParse(RowRoot, RowRoot, tmplbuf, i, seq, tabAccess); mir_free(tmplbuf); return RowRoot; } if (hFile = fopen("template.txt", "rb")) { fsize = _filelength(_fileno(hFile)); tmplbuf = (char*)malloc(fsize + 1); memset(tmplbuf, 0, (fsize + 1)); for (i = 0; i < fsize; i++) tmplbuf[i] = getc(hFile); tmplbuf[i] = 0; i = 0; rowParse(RowRoot, RowRoot, tmplbuf, i, seq, tabAccess); db_set_s(0, "ModernData", "RowTemplate", tmplbuf); free(tmplbuf); fclose(hFile); return RowRoot; } return nullptr; } void cppDeleteTree(ROWCELL * RowRoot) { ROWCELL *rc = RowRoot; rowDeleteTree(rc); } int cppCalculateRowHeight(ROWCELL *RowRoot) { if (RowRoot == nullptr) return 0; RowRoot->h = 0; RowRoot->w = 0; rowResetEmptyRects(RowRoot); rowCalculateMinSize(RowRoot); rowEqualize(RowRoot); return RowRoot->r.bottom; } void cppCalculateRowItemsPos(ROWCELL *RowRoot, int width) { rowSizeWithReposition(RowRoot, width); } // rowAddCell // Выделяет необходимое кол-во дин. памяти для структуры ROWCELL // и связывает ее с деревом описания контакта // link - поле child или next, родительской структуры ROWCELL // cont - тип контейнера: строка, столбец или корневой узел // // const ROWCELL * rowAddCell(ROWCELL* &link, int cont) { link = (ROWCELL*)malloc(sizeof(ROWCELL)); memset(link, 0, sizeof(ROWCELL)); link->cont = cont; return link; } // rowDeleteTree // Освобождает память занятую деревом описания контакта // cell - адрес корневого узла дерева описания контакта // // void rowDeleteTree(ROWCELL* cell) { if (!cell) return; if (cell->child) rowDeleteTree((ROWCELL*)(cell->child)); if (cell->next) rowDeleteTree((ROWCELL*)(cell->next)); free(cell); cell = nullptr; return; } // rowParserGetNextWord // Выбирает из потока данных (сейчас файлового) очередное слово. // Словом считается последовательность символов, ограниченная знаками: SP, < , >, ;, TAB, CR, LF // символы от ; и до конца строки считаются комментарием. // NOTE: Данная реализация не совсем подходит для включения ее в ModernCL, // а по сему, тут надо будет переделывать // tbuf - указатель на буфер содержащий текст шаблона // hbuf - указатель буфера // // char * rowParserGetNextWord(char *tbuf, int &hbuf) { static char buf[256]; char ch; int j = -1; memset(buf, 0, sizeof(buf)); while (tbuf[hbuf] != 0) { ch = tbuf[hbuf]; // Remark found if (ch == ';') { if (j >= 0) return buf; while (tbuf[hbuf] != 10 && tbuf[hbuf] != 13) hbuf++; } // Tag-bracers found if (!(ch == '>' && j < 0)) //not single '>' found { if ((ch == '<' || ch == '>') && j >= 0) { if (ch == '>') { if (buf[0] == '/' || buf[0] == '<') buf[++j] = ch; hbuf++; } return buf; } if (ch == ' ' || ch == 9 || ch == 10 || ch == 13 || ch == ';' || ch == '>') { if (ch == '>') { buf[++j] = ch; hbuf++; } if (j >= 0) return buf; // Word is selected } else buf[++j] = ch; } hbuf++; } return nullptr; } // rowParserGetParam // ищет и интерпретирует слова в шаблоне, заключенные между тэгами // cell - указатель на текущий интерпретируемый контейнер шаблона // tbuf - указатель на буфер содержащий текст шаблона // hbuf - указатель буфера // // void rowParserGetParam(ROWCELL* &cell, char *tbuf, int &hbuf) { char * word = rowParserGetNextWord(tbuf, hbuf); int param = 0; if (!_strnicmp(word, "avatar", mir_strlen(word))) param = TC_AVATAR; else if (!_strnicmp(word, "text1", mir_strlen(word))) param = TC_TEXT1; else if (!_strnicmp(word, "text2", mir_strlen(word))) param = TC_TEXT2; else if (!_strnicmp(word, "text3", mir_strlen(word))) param = TC_TEXT3; else if (!_strnicmp(word, "status", mir_strlen(word))) param = TC_STATUS; else if (!_strnicmp(word, "extra", mir_strlen(word))) param = TC_EXTRA; else if (!_strnicmp(word, "extra1", mir_strlen(word))) param = TC_EXTRA1; else if (!_strnicmp(word, "extra2", mir_strlen(word))) param = TC_EXTRA2; else if (!_strnicmp(word, "extra3", mir_strlen(word))) param = TC_EXTRA3; else if (!_strnicmp(word, "extra4", mir_strlen(word))) param = TC_EXTRA4; else if (!_strnicmp(word, "extra5", mir_strlen(word))) param = TC_EXTRA5; else if (!_strnicmp(word, "extra6", mir_strlen(word))) param = TC_EXTRA6; else if (!_strnicmp(word, "extra7", mir_strlen(word))) param = TC_EXTRA7; else if (!_strnicmp(word, "extra8", mir_strlen(word))) param = TC_EXTRA8; else if (!_strnicmp(word, "extra9", mir_strlen(word))) param = TC_EXTRA9; else if (!_strnicmp(word, "time", mir_strlen(word))) param = TC_TIME; else if (!_strnicmp(word, "space", mir_strlen(word))) param = TC_SPACE; else if (!_strnicmp(word, "fspace", mir_strlen(word))) param = TC_FIXED; else if (!_strnicmp(word, "left", mir_strlen(word))) param = TC_LEFT; else if (!_strnicmp(word, "top", mir_strlen(word))) param = TC_TOP; else if (!_strnicmp(word, "vcenter", mir_strlen(word))) param = TC_VCENTER; else if (!_strnicmp(word, "hcenter", mir_strlen(word))) param = TC_HCENTER; else if (!_strnicmp(word, "right", mir_strlen(word))) param = TC_RIGHT; else if (!_strnicmp(word, "bottom", mir_strlen(word))) param = TC_BOTTOM; else if (!_strnicmp(word, "layer", mir_strlen(word))) cell->layer = TRUE; else if (!_strnicmp(word, "width", mir_strlen(word))) param = TC_WIDTH; else if (!_strnicmp(word, "height", mir_strlen(word))) param = TC_HEIGHT; else { hbuf -= (int)mir_strlen(word); return; } if (param > TC_TEXT3 && param != TC_SPACE) cell->hasfixed = 1; switch (param) { case TC_TEXT1: case TC_TEXT2: case TC_TEXT3: case TC_SPACE: cell->sizing = 1; case TC_STATUS: case TC_AVATAR: case TC_EXTRA: case TC_EXTRA1: case TC_EXTRA2: case TC_EXTRA3: case TC_EXTRA4: case TC_EXTRA5: case TC_EXTRA6: case TC_EXTRA7: case TC_EXTRA8: case TC_EXTRA9: case TC_TIME: case TC_FIXED: cell->type = param; break; case TC_HCENTER: case TC_RIGHT: cell->halign = param; break; case TC_VCENTER: case TC_BOTTOM: cell->valign = param; break; case TC_WIDTH: word = rowParserGetNextWord(tbuf, hbuf); param = atoi(word); cell->w = param; break; case TC_HEIGHT: word = rowParserGetNextWord(tbuf, hbuf); param = atoi(word); cell->h = param; } rowParserGetParam(cell, tbuf, hbuf); return; } // rowParse // Ищет в шаблоне теги < contact>, < tr> и < tc>, и добавляет соответствующие узлы // в дерево описания контакта // cell - поле child или next родительского контейнера // parent - указатель на родительский контейнер // tbuf - указатель на буфер содержащий текст шаблона // hbuf - указатель буфера // sequence - нужно задавать 0, это очередность нахождения // BOOL rowParse(ROWCELL* &cell, ROWCELL* parent, char *tbuf, int &hbuf, int &sequence, ROWCELL** RowTabAccess) { char * word; word = rowParserGetNextWord(tbuf, hbuf); int cont; if (!_strnicmp(word, "