diff --git a/programs/other/table/KosFile.cpp b/programs/other/table/KosFile.cpp new file mode 100644 index 0000000000..ab7c2d4d75 --- /dev/null +++ b/programs/other/table/KosFile.cpp @@ -0,0 +1,132 @@ +#include "kosSyst.h" +#include "kosfile.h" +//#include "string.h" + + +CKosFile::CKosFile(char *fileName) +{ + // + this->fileInfo.bufferPtr = new Byte[FILE_BUFFER_SIZE]; + // + this->filePointer = 0; + this->bufferPointer = 0; + this->validBuffer = false; + // + strcpy( this->fileInfo.fileURL, fileName ); +} + + +CKosFile::~CKosFile(void) +{ + // + delete this->fileInfo.bufferPtr; +} + + +void CKosFile::ValidateBuffer() +{ + // + if ( this->validBuffer ) + { + // + if ( this->filePointer < this->bufferPointer + || this->filePointer >= (this->bufferPointer + FILE_BUFFER_SIZE) ) + { + // + this->validBuffer = false; + } + } +} + + +void CKosFile::UpdateBuffer(void) +{ + // + if ( ! this->validBuffer ) + { + // + this->fileInfo.OffsetLow = this->filePointer / OS_BLOCK_SIZE; + this->fileInfo.OffsetHigh = 0; + // + this->bufferPointer = this->fileInfo.OffsetLow * OS_BLOCK_SIZE; + // + this->fileInfo.dataCount = FILE_BUFFER_BLOCKS; + // + this->fileInfo.rwMode = 0; + // + Dword rr = kos_FileSystemAccess( &(this->fileInfo) ); + this->validBuffer = ( rr == 0 ); + } +} + + +int CKosFile::Seek(int seekFrom, int seekStep) +{ + // + switch ( seekFrom ) + { + // + case SEEK_SET: + // + this->filePointer = seekStep; + break; + // + case SEEK_CUR: + // + this->filePointer += seekStep; + break; + } + // + this->ValidateBuffer(); + // + return this->filePointer; +} + + +int CKosFile::Read(Byte *targetPtr, int readCount) +{ + int bufferLeast, result; + + // + result = 0; + // + do + { + // + this->UpdateBuffer(); + // + if ( ! this->validBuffer ) return result; + // + bufferLeast = FILE_BUFFER_SIZE - (this->filePointer - this->bufferPointer); + // + if ( bufferLeast > readCount ) bufferLeast = readCount; + // + if ( bufferLeast ) + { + // + memcpy( + targetPtr, + this->fileInfo.bufferPtr + (this->filePointer - this->bufferPointer), + bufferLeast + ); + // + targetPtr += bufferLeast; + readCount -= bufferLeast; + this->filePointer += bufferLeast; + // + result += bufferLeast; + } + // + this->ValidateBuffer(); + } + while ( readCount > 0 ); + // + return result; +} + + +int CKosFile::Write(Byte *sourcePtr, int writeCount) +{ + return 0; +} + diff --git a/programs/other/table/KosFile.h b/programs/other/table/KosFile.h new file mode 100644 index 0000000000..5f7c18e9bc --- /dev/null +++ b/programs/other/table/KosFile.h @@ -0,0 +1,26 @@ +#pragma once + +#define SEEK_SET 0 +#define SEEK_CUR 1 + +#define FILE_BUFFER_SIZE 512 +#define OS_BLOCK_SIZE 1 +#define FILE_BUFFER_BLOCKS (FILE_BUFFER_SIZE / OS_BLOCK_SIZE) + + +class CKosFile +{ +public: + CKosFile(char *fileName); + virtual ~CKosFile(void); + virtual int Read(Byte *targetPtr, int readCount); + virtual int Write(Byte *sourcePtr, int writeCount); + virtual int Seek(int seekFrom, int seekStep); +protected: + int filePointer; + int bufferPointer; + bool validBuffer; + kosFileInfo fileInfo; + virtual void ValidateBuffer(void); + virtual void UpdateBuffer(void); +}; diff --git a/programs/other/table/MCSMEMM.H b/programs/other/table/MCSMEMM.H new file mode 100644 index 0000000000..42d61eaadb --- /dev/null +++ b/programs/other/table/MCSMEMM.H @@ -0,0 +1,28 @@ +// + +struct MemBlock +{ + Dword Size; + Dword Addr; + MemBlock *Next; + MemBlock *Previous; +}; + + +#define INITIALQUEUESIZE (32 * 4) + +#define FALSE 0 +#define TRUE -1 + +#define MB_FREE 0 +#define MB_USER 1 + +#define SIZE_ALIGN 4 + + + +Byte *allocmem( Dword reqsize ); +Dword freemem( void *vaddress ); + + + diff --git a/programs/other/table/calc.cpp b/programs/other/table/calc.cpp new file mode 100644 index 0000000000..5bdf80359f --- /dev/null +++ b/programs/other/table/calc.cpp @@ -0,0 +1,1474 @@ + + +#include "func.h" +#include "parser.h" +#include "calc.h" +#include "kosSyst.h" +//#include "KosFile.h" + +extern DWORD def_col_width, def_row_height; +extern DWORD col_count, row_count; +extern char ***cells; +extern DWORD *col_width, *row_height; +extern char ***values; + +extern DWORD *col_left, *row_top; + +// буфер обмена +extern char ***buffer; +extern DWORD buf_col, buf_row; +extern DWORD buf_old_x, buf_old_y; + +extern bool sel_moved; + +int cf_x0, cf_x1, cf_y0, cf_y1; + + +#define sign(x) ((x) < 0 ? -1 : ((x) == 0 ? 0 : 1)) + + +//extern const char er_file_not_found[]; +//extern const char er_format[]; +extern const char *sFileSign; + +struct cell_list +{ + int x,y; + cell_list *next; +}; + + +// получить х-координату ячейки с номером х +int get_x(int x) +{ + int i, r = 0; + if (x > col_count) + x = col_count; + for (i = 0; i < x; i++) + r+=col_width[i]; + return r; +} + +// аналог +int get_y(int y) +{ + int i, r = 0; + if (y > row_count) + y = row_count; + for (i = 0; i < y; i++) + r+=row_height[i]; + return r; +} + + + +// сгенерить заголовок столбца +char *make_col_cap(int i) +{ + char *r = (char*)allocmem(3); + if (i <= 26) + { + r[0] = 'A' + i - 1; + r[1] = '\0'; + return r; + } + else if (i % 26 == 0) // фикс бага который не понял - да простят меня читатели и юзера + { + r[0] = (i / 26) - 1 + 'A' - 1; + r[1] = 'Z'; + r[2] = '\0'; + return r; + } + r[0] = (i / 26) + 'A' - 1; + r[1] = (i % 26) + 'A' - 1; + r[2] = '\0'; + return r; +} + +// -"- строки +char *make_row_cap(int i) +{ + char *r = (char*)allocmem(3); + if (i <= 9) + { + r[0] = '0' + i; + r[1] = '\0'; + return r; + } + r[0] = (i / 10) + '0'; + r[1] = (i % 10) + '0'; + r[2] = '\0'; + return r; +} + +// инициализация ячеек +void init() +{ + int i, j; + + //col_count = WND_W / def_col_width; + //row_count = WND_H / def_row_height; + + col_width = (DWORD*)allocmem(col_count * sizeof(DWORD)); + row_height = (DWORD*)allocmem(row_count * sizeof(DWORD)); + col_left = (DWORD*)allocmem(col_count * sizeof(DWORD)); + row_top = (DWORD*)allocmem(row_count * sizeof(DWORD)); + for (i = 0; i < col_count; i++) + { + col_width[i] = def_col_width; + } + + for (i = 0; i < row_count; i++) + { + row_height[i] = def_row_height; + } + + cells = (char***)allocmem(col_count * sizeof(char**)); + values = (char***)allocmem(col_count * sizeof(char**)); + for (i = 0; i < col_count; i++) + { + cells[i] = (char**)allocmem(row_count * sizeof(char*)); + values[i] = (char**)allocmem(row_count * sizeof(char*)); + for (j = 0; j < row_count; j++) + { + cells[i][j] = NULL; + if (i == 0 && j) + { + cells[i][j] = make_row_cap(j); + } + else if (j == 0 && i) + { + cells[i][j] = make_col_cap(i); + } + + } + } +} + +void reinit() +{ + int i, j; + + for (i = 0; i < col_count; i++) + { + col_width[i] = def_col_width; + } + + for (i = 0; i < row_count; i++) + { + row_height[i] = def_row_height; + } + + for (i = 1; i < col_count; i++) + { + for (j = 1; j < row_count; j++) + { + if (cells[i][j]) + freemem(cells[i][j]); + cells[i][j] = NULL; + if (values[i][j]) + freemem(values[i][j]); + values[i][j] = NULL; + } + } +} + +void fill_cells(int sel_x, int sel_y, int sel_end_x, int sel_end_y, int old_end_x, int old_end_y) +{ + // итак, (sel_x, sel_y) :: (old_end_x, old_end_y) - источник + // результат хранится либо в строке sel_x .. sel_end_x, либо в столбце sel_y .. sel_end_y + + int i, start, end, step, gdir = -1; + int pdir = -1; + char *source; + + cf_x0 = cf_y0 = 0; + cf_x1 = col_count; + cf_y1 = row_count; + + if (sel_end_x == -1) + sel_end_x = sel_x; + if (sel_end_y == -1) + sel_end_y = sel_y; + + // если направления выделений перпендикулярны, то просто в цикле повторяем то же, что для 1 ячейки: + + if (old_end_x == sel_end_x && sel_y == old_end_y) + { + gdir = 0; + } + else if (old_end_y == sel_end_y && sel_x == old_end_x) + { + gdir = 1; + } + + //sprintf(debuf, "fuck in ass %U %U %U %U %U %U dir %U",sel_x,sel_y,sel_end_x,sel_end_y,old_end_x,old_end_y,gdir); + //rtlDebugOutString(debuf); + if (gdir != -1) + { + int gstep = gdir ? sign(old_end_y - sel_y) : sign(old_end_x - sel_x); + if (gstep == 0) + { + /* if (gdir) + { + //old_end_y += 1; + } + else + { + //old_end_x += 1; + } + */ + gstep = 1; + } + + for (;gdir ? (sel_y != old_end_y + gstep) : (sel_x != old_end_x + gstep); + gdir ? (sel_y += gstep) : (sel_x += gstep)) + { + //sprintf(debuf, "cycle %U %U %U %U %U %U dir %U",sel_x,sel_y,sel_end_x,sel_end_y,old_end_x,old_end_y,gdir); + //rtlDebugOutString(debuf); + int dir; + source = cells[sel_x][sel_y]; + if (gdir == 0) + { + start = sel_y; + end = sel_end_y; + step = (sel_y < sel_end_y ? 1 : -1); + dir = 1; + } + else + { + start = sel_x; + end = sel_end_x; + step = (sel_x < sel_end_x ? 1 : -1); + dir = 0; + } + + //sprintf(debuf, "cyc %U %U %U %U",start,end,step,dir); + //rtlDebugOutString(debuf); + for (i = start + step; i != end + step; i += step) + { + //char **p = &cells[dir ? sel_x : i][dir ? i : sel_end_y]; + //sprintf(debuf, "to %U %U dir %U copying '%S'",dir ? sel_x : i,dir ? i : sel_y,dir,source); + //rtlDebugOutString(debuf); + if (cells[dir ? sel_x : i][dir ? i : sel_y]) + { + freemem(cells[dir ? sel_x : i][dir ? i : sel_y]); + } + if (source) + { + cells[dir ? sel_x : i][dir ? i : sel_y] = change_formula(source, dir ? 0 : (i - start), dir ? (i - start) : 0); + //cells[dir ? sel_x : i][dir ? i : sel_y] = (char *)allocmem(strlen(source) + 1); + //strcpy(cells[dir ? sel_x : i][dir ? i : sel_y], source); + } + else + cells[dir ? sel_x : i][dir ? i : sel_y] = NULL; + } + } + } + + // а вот если параллельны... + /* + + if (sel_x == sel_end_x && sel_x == old_end_x) + { + pdir = 0; + } + if (sel_y == sel_end_y && sel_y == old_end_y) + { + pdir = 1; + } + if (pdir != -1) + { + // арифметическая прогрессия - если числа. и тупо размножитьт последнее, если нет + + sprintf(debuf, "maybe arith dir %U", pdir); + rtlDebugOutString(debuf); + + int is_arith = 1; + int gstep = pdir ? sign(old_end_y - sel_y) : sign(old_end_x - sel_x); + if (gstep == 0) + gstep = 1; + + for (int i = pdir ? sel_y : sel_x; i != pdir ? (old_end_y + gstep) : (old_end_x + gstep); i++) + { + convert_error = 0; + sprintf(debuf,"cell %U %U", !pdir ? sel_x : i, !pdir ? i : sel_y); + rtlDebugOutString(debuf); + if (cells[!pdir ? sel_x : i][!pdir ? i : sel_y]) + { + double d = atof(cells[!pdir ? sel_x : i][!pdir ? i : sel_y]); + if (convert_error) + { + rtlDebugOutString("failed arith"); + is_arith = 0; + break; + } + } + else + { + is_arith = 0; + rtlDebugOutString("failed arith in null"); + break; + } + } + + double arith_first, arith_step; + if (is_arith) + { + rtlDebugOutString("really arith"); + arith_first = atof(cells[sel_x][sel_y]); + arith_step = atof(cells[pdir ? sel_x : old_end_x][pdir ? sel_y : old_end_y]) - arith_first; + arith_first += arith_step * pdir ? abs(sel_end_x - old_end_x) : abs(sel_end_y - old_end_y); + } + else + rtlDebugOutString("none arith"); + + // собственно заполнение + for (i = pdir ? old_end_y : old_end_x; i != pdir ? (sel_end_y + gstep) : (sel_end_x + gstep); i++) + { + if (cells[pdir ? sel_x : i][pdir ? i : sel_y]) + freemem(cells[pdir ? sel_x : i][pdir ? i : sel_y]); + if (is_arith) + { + cells[pdir ? sel_x : i][pdir ? i : sel_y] = ftoa(arith_first); + arith_first += arith_step; + } + else + { + if (cells[sel_x][sel_y]) + { + cells[pdir ? sel_x : i][pdir ? i : sel_y] = (char*)allocmem(strlen(cells[sel_x][sel_y]) + 1); + strcpy(cells[pdir ? sel_x : i][pdir ? i : sel_y], cells[sel_x][sel_y]); + } + } + } + } + */ + + calculate_values(); +} + +const char *csv_name = ".csv"; + +int str_is_csv(char *str) +{ + int i, j = 0; + + for (i = 0; i < strlen(str); i++) + { + if (str[i] == csv_name[j]) + { + j++; + if (j == strlen(csv_name)) + return 1; + } + else + { + j = 0; + } + } + return 0; +} + +int Kos_FileWrite(kosFileInfo &fileInfo, char *line, int mode = 3) // если mode = 2 - перезаписать файл +{ + int res = 0; + fileInfo.dataCount = strlen(line); + fileInfo.bufferPtr = (Byte*)line; + fileInfo.rwMode = mode; + res = kos_FileSystemAccess(&fileInfo); + if (res != 0) + return 0; + fileInfo.OffsetLow += fileInfo.dataCount; + return 1; +} + +int SaveCSV(char *fname) +{ + int i, j; + int min_col = col_count, min_row = row_count, max_row = -1, max_col = -1; + int first = 1; + + kosFileInfo fileInfo; + memset((Byte*)&fileInfo, 0, sizeof(fileInfo)); + strcpy(fileInfo.fileURL,fname); + fileInfo.OffsetLow = 0; + fileInfo.OffsetHigh = 0; + fileInfo.rwMode = 8; // delete + + rtlDebugOutString("savecsv: old file deleted"); + + for (i = 1; i < col_count; i++) + { + for (j = 1; j < row_count; j++) + { + if (cells[i][j]) + { + min_col = min(min_col, i); + min_row = min(min_row, j); + max_col = max(max_col, i); + max_row = max(max_row, j); + } + } + } + + sprintf(debuf, "col %U %U row", min_col, max_col, min_row, max_row); + rtlDebugOutString(debuf); + + for (j = min_row; j <= max_row; j++) + { + char buffer[1024]; // не надо так делать + int buf_len = 0; + + memset((Byte*)buffer, 0, 1024); + + for (i = min_col; i <= max_col; i++) + { + char *cur = values[i][j] ? values[i][j] : cells[i][j]; + if (cur) + { + buffer[buf_len++] = '\"'; + for (int k = 0; k < strlen(cur); k++) + { + if (cur[k] == '\"') + buffer[buf_len++] = '\"'; // кавычек - по две + buffer[buf_len++] = cur[k]; + } + buffer[buf_len++] = '\"'; + } + buffer[buf_len++] = ';'; + } + rtlDebugOutString(buffer); + // очередная строка теперь в буфере + buffer[buf_len++] = '\n'; + if (!Kos_FileWrite(fileInfo, buffer, first ? (first = 0, 2) : 3)) + return 0; + } + return 1; + +} + +#define BUF_FOR_ALL 5000 +int SaveFile(char *fname) +{ + kosFileInfo fileInfo; + char *buffer = (char*)allocmem(BUF_FOR_ALL); // ужас! но пока что достаточно + int filePointer = 0; + + int i,j; + Dword res; + + if (str_is_csv(fname)) + return SaveCSV(fname); + + + //rtlDebugOutString(fname); + + memset((Byte*)&fileInfo, 0, sizeof(fileInfo)); + strcpy(fileInfo.fileURL,fname); + fileInfo.OffsetLow = 0; + fileInfo.OffsetHigh = 0; + fileInfo.rwMode = 8; + res = kos_FileSystemAccess(&fileInfo); // удалить + fileInfo.dataCount = strlen(sFileSign); + fileInfo.bufferPtr = (Byte*)sFileSign; + fileInfo.rwMode = 2; + res = kos_FileSystemAccess(&fileInfo); + if (res != 0) + return 0; + //sprintf(debuf, "create %U",res); + //rtlDebugOutString(debuf); + fileInfo.OffsetLow += fileInfo.dataCount; + + // ширину столбцов сохраняем + memset((Byte*)buffer,0,BUF_FOR_ALL); + for (i = 1; i < col_count; i++) + { + char smalbuf[32]; + memset((Byte*)smalbuf,0,32); + sprintf(smalbuf, "%U,", col_width[i]); + strcpy(buffer+strlen(buffer),smalbuf); + } + buffer[strlen(buffer)-1] = '\n'; // заменили последнюю запятую на перевод строки + //rtlDebugOutString(buffer); + fileInfo.dataCount = strlen(buffer); + fileInfo.bufferPtr = (Byte*)buffer; + fileInfo.rwMode = 3; + res = kos_FileSystemAccess(&fileInfo); + if (res != 0) + return 0; + + // перемотать забыл я этот файл + // но уж теперь не попадусь на это! + fileInfo.OffsetLow += fileInfo.dataCount; + + // высоту строк сохраняем в файле мы + memset((Byte*)buffer,0,BUF_FOR_ALL); + for (i = 1; i < row_count; i++) + { + char smalbuf[32]; + memset((Byte*)smalbuf,0,32); + sprintf(smalbuf, "%U,", row_height[i]); + strcpy(buffer+strlen(buffer),smalbuf); + } + buffer[strlen(buffer)-1] = '\n'; // заменили последнюю запятую на перевод строки + //rtlDebugOutString(buffer); + fileInfo.dataCount = strlen(buffer); + fileInfo.bufferPtr = (Byte*)buffer; + fileInfo.rwMode = 3; + res = kos_FileSystemAccess(&fileInfo); + if (res != 0) + return 0; + + // и вновь перемотаю я сей файл + + fileInfo.OffsetLow += fileInfo.dataCount; + memset((Byte*)buffer,0,BUF_FOR_ALL); + + // сохранили параметры ячеек мы, сохраняем содержимое их теперь + + for (i = 1; i < row_count; i++) + { + for (j = 1; j < col_count; j++) + if (cells[j][i]) + { + memset((Byte*)buffer,0,512); + sprintf(buffer, "%U %U:%S\n", j, i, cells[j][i]); + fileInfo.dataCount = strlen(buffer); + fileInfo.bufferPtr = (Byte*)buffer; + fileInfo.rwMode = 3; + res = kos_FileSystemAccess(&fileInfo); + if (res != 0) + return 0; + //sprintf(debuf, "create %U",res); + //rtlDebugOutString(debuf); + fileInfo.OffsetLow += fileInfo.dataCount; + } + } + + //rtlDebugOutString("saving finished"); + + freemem(buffer); + return 1; +} + +char *Kos_FileRead(kosFileInfo &fileInfo, int &code) +{ + char buffer[512], *p, *r; + fileInfo.dataCount = 512; + fileInfo.rwMode = 0; + fileInfo.bufferPtr = (Byte *)buffer; + memset((Byte*)buffer, 0, 512); + int z = kos_FileSystemAccess(&fileInfo); + code = z; + + //sprintf(debuf, "kos file read %U", code); + //rtlDebugOutString(debuf); + + if (z != 0 && z != 6) + return NULL; + + p = buffer; + while (*p && *p++ != '\n'); + + if (p == buffer) + return NULL; + + r = (char*)allocmem(p - buffer); + memset((Byte*)r, 0, p - buffer); + //strncpy(r, buffer, p - buffer); + for (int l = 0; l < p - buffer - 1; l++) + r[l] = buffer[l]; + fileInfo.OffsetLow += p - buffer; + return r; +} + +int LoadCSV(char *fname) +{ + // clear the table + reinit(); + + kosFileInfo fileInfo; + strcpy(fileInfo.fileURL,fname); + fileInfo.OffsetLow = 0; + fileInfo.OffsetHigh = 0; + + char *line; + + int col = 1, row = 1; + int code = 0; + do + { + line = Kos_FileRead(fileInfo, code); + if (!line || *line == '\0' || (code != 0 && code != 6)) + { + sprintf(debuf, "read end, line not null = %U, code = %U", !line, code); + rtlDebugOutString(debuf); + break; + } + sprintf(debuf, "read '%S' len %U", line, strlen(line)); + rtlDebugOutString(debuf); + + // разборать строку + // выделить ;, причем вне " + int i = 0; + while (i <= strlen(line)) + { + int inPar = 0; + // inPar: 0 - не кавычки, 1 - только что была кавычка, 2 - кавычка была, но давно + int start = i; + while (i <= strlen(line)) + { + char c = line[i]; + if (!c) + c = ';'; + int yes_semicolon = 0; + + switch (inPar) + { + case 0: + if (c == '\"') + { + inPar = 1; + } + else + { + if (c == ';') + yes_semicolon = 1; + } + break; + case 1: + inPar = 2; + break; + case 2: + if (c == '\"') // она закрылась + { + inPar = 0; + } + /*else + { + if (c == ';') + yes_semicolon = 1; + + }*/ + break; + } + if (yes_semicolon) + { + // итак, line[i] = ';' + int tmp = line[start] == '"' ? 1 : 0; + int sz = i - start - tmp * 2; + if (sz > 0) + { + cells[col][row] = (char *)allocmem(sz + 1); + memset((Byte*)cells[col][row], 0, sz + 1); + int m = 0; + for (int l = 0; l < sz; l++) + { + if (line[start + tmp + l] == '\"') + { + cells[col][row][m++] = '\"'; + l++; // пропустить следующую кавычку + } + else + cells[col][row][m++] = line[start + tmp + l]; + } + sprintf(debuf, "set %U %U = '%S'", col, row, cells[col][row]); + rtlDebugOutString(debuf); + } + start = i + 1; + col++; + } + i++; + } + row++; + col = 1; + i++; + } + + } while(line); + + return 1; +} + + +int LoadFile(char *fname) +{ + kosFileInfo fileInfo; + kosBDVK bdvk; + int filePointer = 0, i, j; + Dword res, filesize; + char buffer[512 + 1]; + char *d, *s, *k; + int step = 0, items; + + if (str_is_csv(fname)) + return LoadCSV(fname); + + + //rtlDebugOutString(fname); + + strcpy(fileInfo.fileURL,fname); + fileInfo.OffsetLow = 0; + fileInfo.OffsetHigh = 0; + + fileInfo.rwMode = 5; + fileInfo.bufferPtr = (Byte *)&bdvk; + Dword rr = kos_FileSystemAccess(&fileInfo); // в CKosFile нет определения размера + //sprintf(debuf, "getsize: %U\n", rr); + //rtlDebugOutString(debuf); + if (rr != 0) + { + return -1; + } + + // clear the table + reinit(); + + //rtlDebugOutString("clear done"); + + filesize = bdvk.size_low; + + fileInfo.rwMode = 0; + fileInfo.dataCount = strlen(sFileSign); + fileInfo.bufferPtr = (Byte*)buffer; + kos_FileSystemAccess(&fileInfo); + s = (char*)sFileSign; + d = buffer; + while (*s && *d && *s++==*d++); // застрелите меня + if (*s != '\0' || *d != '\0') + { + return -2; + } + fileInfo.OffsetLow += fileInfo.dataCount; + items = 1; + while (fileInfo.OffsetLow < filesize) + { + // так прочитали ли мы ширину всех стоблцов, и длину всех строк прочитали ли мы? + fileInfo.dataCount = 512; + memset((Byte*)buffer, 0, 512); + kos_FileSystemAccess(&fileInfo); + //sprintf(debuf, "%U", fileInfo.OffsetLow); + //rtlDebugOutString(debuf); + //sprintf(debuf, "buffer: %S", buffer); + //rtlDebugOutString(debuf); + // что я увижу на доске отладки + // то мне поможет в жизненном пути + // смогу тогда своей ошибки гадкой + // причину непосредственно найти + + switch (step) + { + case 0: // стоблцы + d = buffer; + while (*d && *d != ',' && *d != '\n') d++; + //d--; + if (!*d) + { + return -2; + } + *d = '\0'; + i = atoi(buffer); + col_width[items++] = i; + if (items == col_count) + { + step++; + items = 1; // теперь высоты строк читать мы будем смело + // чтоб их восстановить и было как всегда + //sprintf(debuf, "cols read done last buf %S file pos %U",buffer,fileInfo.OffsetLow); + //rtlDebugOutString(debuf); + } + d+=2; + break; + + case 1: // строки, коих высота записана + d = buffer; + while (*d && *d != ',' && *d != '\n') d++; + //d--; + if (!*d) + { + //sprintf(debuf,"oh shit, error at %U",items); + //rtlDebugOutString(debuf); + return -2; + } + *d = '\0'; + i = atoi(buffer); + row_height[items++] = i; + /*if (items > 5) + { + sprintf(debuf, "set row from %S hei %U %U",buffer,items-1,i); + rtlDebugOutString(debuf); + }*/ + + if (items == row_count) + { + step++; // а далее лежат ячейки в файле + // записаны они в кривом формате + // ибо писал сей код я темной ночью + // но не курил травы, клянусь я вам + // иначе бы и этого не скодил + + // дебажить сей мне код премного впадлу + // но помню правило - коль написал дебажь + // немедленно - а то нах все забудешь. + // вот выпью - а там сразу за отладку. + //sprintf(debuf, "before read cells offset %U %X",fileInfo.OffsetLow,fileInfo.OffsetLow); + //rtlDebugOutString(debuf); + } + d+=2; + break; + + // о, бряки я забыл забить. о ужас. + // позор мне, на костре меня сожгите + // ведь тот, кто break не ставит после casa + // подобен ламеру, что си не знает + // смогу ли я такое пережить? + + case 2: // ячейки, ибо их содержимое сохранено здесь от исчезновения + d = buffer; + while (*d && *d++ != ' '); // оужжас. зачем только я писал этот бред.... + d--; + if (!*d) + { + return -2; + } + *d = '\0'; + i = atoi(buffer); + d++; + s=d; + while (*d && *d++ != ':'); // когда-то я удивлялся, как люди могут такую херню писать... дожил + d--; + if (!*d) + { + return -2; + } + *d = '\0'; + j = atoi(s); + //rtlDebugOutString(s); + d++; + k = d; + while (*d && *d++ != '\n'); + d--; + *d = '\0'; + d+=2; + //sprintf(debuf, "i:%U j:%U d:%S\n",i,j,k); + //rtlDebugOutString(debuf); + cells[i][j] = (char*)allocmem(strlen(k) + 1); + //memset(cells[i][j], 0, strlen(k) + 1); + strcpy(cells[i][j], k); + //sprintf(debuf, "offset: %U", fileInfo.OffsetLow); + //rtlDebugOutString(debuf); + } + fileInfo.OffsetLow += d - (char*)buffer - 1; + } + //rtlDebugOutString("loading finished"); + return 1; +} + +// очистить буфер обмена +void freeBuffer() +{ + int i, j; + + if (!buffer) + return; + for (i = 0; i < buf_col; i++) + { + for (j = 0; j < buf_row; j++) + if (buffer[i][j]) + freemem(buffer[i][j]); + freemem(buffer[i]); + } + freemem(buffer); + buffer = NULL; + buf_row = buf_col = 0; + +} + + +// далее - вычисление по формулам + +int abort_calc = 0; +cell_list *last_dep; + +// ппц, где то баг, а это типа фикс +//#define allocmem2(x) allocmem(x+1000) + +double calc_callback(char *str) +{ + int i,j,x,y; + + if (abort_calc == 1) + return 0.0; + + //rtlDebugOutString(str); + if (*str == '$') str++; + for (i = 0; i < strlen(str); i++) + if (str[i] >= '0' && str[i] <= '9') + break; + if (str[i-1] == '$') + i--; + if (i == strlen(str)) + { + abort_calc = 1; + serror(ERR_BADVARIABLE); + return 0.0; + } + x = -1; + for (j = 0; j < col_count; j++) +// if (strnicmp(str,cells[j][0],i-1)==0) + if (str[0] == cells[j][0][0] && ((i == 1) || (str[1] == cells[j][0][1]))) + { + x = j; + break; + } + if (str[i] == '$') + i++; + y = -1; + for (j = 0; j < row_count; j++) + if (strcmp(str+i,cells[0][j])==0) + { + y = j; + break; + } + if (x == -1 || y == -1) + { + abort_calc = 1; + serror(ERR_BADVARIABLE); + return 0.0; + } + + double hold; + if (values[x][y]) + if (values[x][y][0] == '#') + { + serror(ERR_BADVARIABLE); + abort_calc = 1; + } + else + { + hold = atof(values[x][y]); + //if (convert_error) // нереальный случай... + //{ + // serror(ERR_BADVARIABLE); + // abort_calc = 1; + //} + } + else + { + if (cells[x][y]) + { + hold = atof(cells[x][y]); + if (convert_error == ERROR || convert_error == ERROR_END) + { + serror(ERR_BADVARIABLE); + abort_calc = 1; + } + } + else + { + sprintf(debuf, "bad var %S", str); + rtlDebugOutString(debuf); + serror(ERR_BADVARIABLE); + abort_calc = 1; + } + } + return hold; +} + +double depend_callback(char *str) +{ + cell_list *cur; + // надо выдрать из АВ47 значения х и у. + int i,j,x,y; + + if (abort_calc == 1) + return 0.0; + + if (*str == '$') str++; + for (i = 0; i < strlen(str); i++) + if (str[i] >= '0' && str[i] <= '9') + break; + if (str[i-1] == '$') + i--; + if (i == strlen(str)) + { + abort_calc = 1; + serror(ERR_BADVARIABLE); + return 0.0; + } + x = -1; + for (j = 1; j < col_count; j++) + //if (strncmp(str,cells[j][0],i)==0) + if (str[0] == cells[j][0][0] && ((i == 1) || (str[1] == cells[j][0][1]))) + { + x = j; + break; + } + if (str[i] == '$') + i++; + + y = -1; + for (j = 1; j < row_count; j++) + if (strcmp(str+i,cells[0][j])==0) + { + y = j; + break; + } + if (x == -1 || y == -1) + { + abort_calc = 1; + serror(ERR_BADVARIABLE); + return 0.0; + } + cur = (cell_list*)allocmem(sizeof(cell_list)); + cur->x = x; + cur->y = y; + cur->next = last_dep; + last_dep = cur; + + return 0.0; +} + +cell_list *find_depend(char *str) +{ + double hold; + last_dep = NULL; + find_var = &depend_callback; + set_exp(str); + get_exp(&hold); + + return last_dep; +} + +bool is_in_list(cell_list *c1, cell_list *c2) +{ + cell_list *p = c2; + while (p) + { + if (c1->x == p->x && c1->y == p->y) + return 1; + p = p->next; + } + return 0; +} + +void calculate_values() +{ + cell_list ***depend = NULL; + cell_list *first = NULL; + cell_list *sorted = NULL, *sorted_last = NULL; + cell_list *p = NULL; + int i,j; + + //rtlDebugOutString("calc"); + + abort_calc = 0; + depend = (cell_list***)allocmem(col_count * sizeof(void*)); + for (i = 0; i < col_count; i++) + { + depend[i] = (cell_list**)allocmem(row_count * sizeof(void*)); + for (j = 0; j < row_count; j++) + { + if (values[i][j]) + freemem(values[i][j]); + values[i][j] = NULL; + + if (cells[i][j] && cells[i][j][0] == '=') + { + depend[i][j] = find_depend(cells[i][j] + 1); // после = + if (abort_calc) + { + values[i][j] = (char*)allocmem(2); + values[i][j][0] = '#'; + values[i][j][1] = '\0'; + abort_calc = 0; + continue; + } + cell_list *cur; + cur = (cell_list*)allocmem(sizeof(cell_list)); + cur->x = i; + cur->y = j; + cur->next = first; // вставили тек. ячейку в начало списка ячеек с формулами + first = cur; + } + } + } + + //rtlDebugOutString("depend end"); + // топологическая сортировка + if (!first) + goto free_memory; + + if (abort_calc) + goto free_memory; + + while (first) + { + // найти наименьший элемент. если его нет - ошибка, т.к. циклическая зависимость + cell_list *prev = NULL,*min = first; + + bool is_min; + while (min) + { + cell_list *p = first; + is_min = 1; + while (p && is_min) + { + if (is_in_list(p,depend[min->x][min->y])) + is_min = 0; + p = p->next; + } + if (is_min) + break; + prev = min; + min = min->next; + } + if (!is_min) + { + abort_calc = 1; + goto free_memory; // все плохо. ужасно. я плакаю, но пишу goto + } + // надо убрать минимум во второй список + if (prev == NULL) + { + first = first->next; + } + else + { + prev->next = min->next; + } + /* + min->next = sorted; + sorted = min; + */ + if (sorted == NULL) + { + sorted = min; + sorted_last = min; + } + else + { + sorted_last->next = min; + sorted_last = min; + min->next = NULL; + } + } + + // вычисление значений + //rtlDebugOutString("sort end"); + + p = sorted; + while (p) + { + double d; + abort_calc = 0; + set_exp(cells[p->x][p->y]+1); // все что после "=" + find_var = &calc_callback; + if (get_exp(&d)) + { + char *new_val = ftoa(d); + if (values[p->x][p->y] && strcmp(values[p->x][p->y],new_val) == 0) + { + freemem(new_val); + } + else + { + if (values[p->x][p->y]) + freemem(values[p->x][p->y]); + values[p->x][p->y] = new_val; + sel_moved = 0; + } + //sprintf(debuf,"calc %U %U formula %S result %f",p->x,p->y,cells[p->x][p->y]+1,d); + //rtlDebugOutString(debuf); + } + else + { + values[p->x][p->y] = (char*)allocmem(2); + values[p->x][p->y][0] = '#'; + values[p->x][p->y][1] = '\0'; + //sprintf(debuf,"calc %U %U formula %S result #",p->x,p->y,cells[p->x][p->y]+1); + //rtlDebugOutString(debuf); + } + p = p->next; + } + + if (abort_calc) + goto free_memory; + + //rtlDebugOutString("calc end"); + + + // освобождение памяти + +free_memory: + + p = sorted; + while (p) + { + cell_list *tmp = p->next; + cell_list *pp = depend[p->x][p->y]; + while (pp) + { + cell_list *tmp = pp->next; + freemem(pp); + pp = tmp; + } + freemem(p); + p = tmp; + } + + for (i = 0; i < col_count; i++) + freemem(depend[i]); + freemem(depend); + + //rtlDebugOutString("freemem end"); + + +} + +int parse_cell_name(char *str, int *px, int *py, int *xd, int *yd) +{ + // надо выдрать из АВ47 значения х и у. + int i,j,x,y,dx = 0,dy = 0; + + if (*str == '$') + { + str++; + dx = 1; + } + for (i = 0; i < strlen(str); i++) + if (str[i] >= '0' && str[i] <= '9') + break; + if (str[i-1] == '$') + { + i--; + dy = 1; + } + if (i == strlen(str)) + { + return 0; + } + x = -1; + for (j = 1; j < col_count; j++) + if (strncmp(str,cells[j][0],i)==0) + { + /*int p = 0, z = 1; + for (p = 0; p < i; p++) + if (!str[p] || str[p] != cells[j][0][p]) + { + z = 0; + break; + } + if (z) + */ + { + x = j; + break; + } + } + if (str[i] == '$') + i++; + y = -1; + for (j = 1; j < row_count; j++) + if (strcmp(str+i,cells[0][j])==0) + { + /* + int p = 0, z = 1; + for (p = 0;; p++) + { + if (str[i + p] != cells[0][j][p]) + { + z = 0; + break; + } + if (cells[0][j][p] == '\0') + break; + } + if (z) + */ + { + y = j; + break; + } + } + if (x == -1 || y == -1) + { + return 0; + } + *px = x; + *py = y; + if (xd) + *xd = dx; + if (yd) + *yd = dy; + return 1; +} + +char *make_cell_name(int x, int y, int xd, int yd) +{ + char *col_cap = make_col_cap(x); + char *row_cap = make_row_cap(y); + + if (x <= 0 || x > col_count || y <= 0 || y > row_count) + return NULL; + + char *res = (char*)allocmem(strlen(col_cap) + strlen(row_cap) + xd ? 1 : 0 + yd ? 1 : 0 + 1); + int i = 0; + if (xd) + { + res[i] = '$'; + i++; + } + strcpy(res + i, col_cap); + i += strlen(col_cap); + if (yd) + { + res[i] = '$'; + i++; + } + strcpy(res + i, row_cap); + i += strlen(row_cap); + res[i] = '\0'; + freemem(col_cap); + freemem(row_cap); + return res; +} + +// замены ссылки на одну ячейку +char *change_cell_ref(char *name, int sx, int sy) +{ + int x0, y0, xd, yd; + + parse_cell_name(name, &x0, &y0, &xd, &yd); + + //sprintf(debuf, "parsed cell name %S to %U %U", name, x0, y0); + //rtlDebugOutString(debuf); + + // у нас есть х0 и у0. + //sprintf(debuf, "%U in %U %U, %U in %U %U",x0, cf_x0, cf_x1, y0, cf_y0, cf_y1); + //rtlDebugOutString(debuf); + if (x0 >= cf_x0 && x0 <= cf_x1 && y0 >= cf_y0 && y0 <= cf_y1) + { + if (!xd) + { + x0 += sx; + if (x0 <= 0 || x0 > col_count) + x0 -= sx; + } + if (!yd) + { + y0 += sy; + if (y0 <= 0 || y0 > row_count) + y0 -= sy; + } + } + + return make_cell_name(x0, y0, xd, yd); +} + +// замена всех ссылок на ячейки +char *change_formula(char *name, int sx, int sy) +{ + int i = 0; + int in_name = 0; // 1 - читаем буквенную часть. 2 - читаем цифровую. 0 - читаем разделители и т.д. + int alp_len = 0, dig_len = 0; + int buf_i = 0; + + char buffer[256]; // очень плохо + memset((Byte*)buffer, 0, 256); + + //sprintf(debuf, "change formula %S by %U %U", name, sx, sy); + //rtlDebugOutString(debuf); + + while (i < strlen(name) + 1) + { + char c; + if (i == strlen(name)) + c = ' '; + else + c = name[i]; + buffer[buf_i++] = c; + + switch (in_name) + { + case 0: + { + if (isalpha2(c) || c == '$') + { + in_name = 1; + alp_len = 1; + dig_len = 0; + } + } + break; + case 1: + { + if (isalpha2(c)) + { + alp_len++; + } + else if (c == '$' || isdigit(c)) + { + in_name = 2; + dig_len++; + } + else + { + // незавершенное имя ячейки - не имя + in_name = 0; + alp_len = dig_len = 0; + } + } + break; + case 2: + { + if (isdigit(c)) + { + dig_len++; + } + else + { + if (alp_len > 0 && dig_len > 0) + { + // вот нормальная ячейка + int idx = i - alp_len - dig_len; + int len = alp_len + dig_len; + char *cell = (char*)allocmem(len + 1); + //strncpy(cell, name + i, alp_len + dig_len); + for (int l = 0; l < len; l++) + cell[l] = name[idx + l]; + cell[len] = '\0'; + + //sprintf(debuf, "found cell name '%S' alp %U dig %U", cell, alp_len, dig_len); + //rtlDebugOutString(debuf); + char *cell_new = change_cell_ref(cell, sx, sy); + //sprintf(debuf, "rename to '%S'", cell_new); + //rtlDebugOutString(debuf); + if (cell_new) + { + char cc = buffer[buf_i - 1]; + strcpy(buffer + buf_i - len - 1, cell_new); + buf_i += strlen(cell_new) - len; + buffer[buf_i - 1] = cc; + } + //freemem(cell); + //freemem(cell_new); + alp_len = dig_len = 0; + in_name = 0; + } + } + } + } + i++; + } + //sprintf(debuf, "change formula done"); + //rtlDebugOutString(debuf); + char *res = (char*)allocmem(strlen(buffer) + 1); + strcpy(res, buffer); + return res; +} + + + + diff --git a/programs/other/table/calc.h b/programs/other/table/calc.h new file mode 100644 index 0000000000..0ac460c2aa --- /dev/null +++ b/programs/other/table/calc.h @@ -0,0 +1,24 @@ + +#pragma once + +#include "KosSyst.h" + +extern int cf_x0, cf_x1, cf_y0, cf_y1; + +void calculate_values(); +int get_x(int x); +int get_y(int y); +char *make_col_cap(int i); +char *make_row_cap(int i); +void init(); +void reinit(); +int SaveFile(char *fname); +int LoadFile(char *fname); +int SaveCSV(char *fname); +int LoadCSV(char *fname); +void fill_cells(int sel_x, int sel_y, int sel_end_x, int sel_end_y, int old_end_x, int old_end_y); +int parse_cell_name(char *str, int *px, int *py, int *xd = NULL, int *yd = NULL); +char *make_cell_name(int x, int y, int xd, int yd); +char *change_formula(char *name, int sx, int sy); + +void freeBuffer(); \ No newline at end of file diff --git a/programs/other/table/func.cpp b/programs/other/table/func.cpp new file mode 100644 index 0000000000..2c7b95e0a4 --- /dev/null +++ b/programs/other/table/func.cpp @@ -0,0 +1,510 @@ + + +#include "func.h" + +int convert_error = 0; +int SysColor = 0; +char debuf[50] = ""; + + +// почему-то не было в стандартной библиотеке +void kos_DrawLine( Word x1, Word y1, Word x2, Word y2, Dword colour, Dword invert ) +{ + Dword arg1, arg2, arg3; + + // + arg1 = ( x1 << 16 ) | x2; + arg2 = ( y1 << 16 ) | y2; + arg3 = (invert)?0x01000000:colour; + // + __asm{ + mov eax, 38 + mov ebx, arg1 + mov ecx, arg2 + mov edx, arg3 + int 0x40 + } +} + +// похищено из библиотеки к C-- +void DrawRegion(Dword x,Dword y,Dword width,Dword height,Dword color1) +{ + kos_DrawBar(x,y,width,1,color1); //полоса гор сверху + kos_DrawBar(x,y+height,width,1,color1); //полоса гор снизу + kos_DrawBar(x,y,1,height,color1); //полоса верт слева + kos_DrawBar(x+width,y,1,height+1,color1); //полоса верт справа +} + + +// да, это баян +int atoi(const char* string) +{ + int res=0; + int sign=0; + const char* ptr; + for (ptr=string; *ptr && *ptr<=' ';ptr++); + if (*ptr=='-') {sign=1;++ptr;} + while (*ptr >= '0' && *ptr <= '9') + { + res = res*10 + *ptr++ - '0'; + } + if (sign) res = -res; + return res; +} + +/*int abs(int n) +{ + return (n<0)?-n:n; +}*/ + + + + + +double fabs(double x) +{ + __asm fld x + __asm fabs +} +#define M_PI 3.14159265358979323846 +double cos(double x) +{ + __asm fld x + __asm fcos +} +double sin(double x) +{ + __asm fld x + __asm fsin +} + +bool isalpha(char c) +{ + return (c==' ' || c=='\n' || c=='\t' || c=='\r'); +} + +// эта функция - велосипед. но проще было написать чем найти. +double convert(char *s, int *len) +{ + + int i; + + + double sign,res, tail, div; + + convert_error = 0; + + res = 0.0; + + i=0; + while (s[i] && isalpha(s[i])) i++; + if (len) *len=i; + if (s[i] == '\0') + { + convert_error = ERROR_END; + return 0.0; + } + + sign=1.0; + if (s[i] == '-') + { + sign=-1.0; + i++; + } + while (s[i] && s[i] >= '0' && s[i] <= '9') + { + res *= 10.0; + res += id(s[i] - '0'); + i++; + } + if (len) *len=i; + if (!s[i] || isalpha(s[i])) + return sign*res; + if (s[i] != '.' && s[i] != ',') + { + convert_error = ERROR; + return 0; + } + i++; + if (len) *len=i; + if (!s[i]) + return sign*res; + + div = 1.0; + tail = 0.0; + while (s[i] && s[i] >= '0' && s[i] <= '9') + { + tail *= 10.0; + tail += id(s[i] - '0'); + div *= 10.0; + i++; + } + res += tail/div; + if (len) *len=i; + return sign*res; +} + +/* +#define PREC 2 + +double double_tab[]={1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15}; + +// это sprintf, умеющий форматировать _только_ вещественные числа (double) %f +void format( char *Str, int len, char* Format, ... ) +{ + int i, fmtlinesize, j, k, flag; + char c; + va_list arglist; + // + va_start(arglist, Format); + + // + fmtlinesize = strlen( Format ); + // + if( fmtlinesize == 0 ) return; + + for (i = 0; i < len; i++) + Str[i] = 0; + + // + for( i = 0, j = 0; i < fmtlinesize; i++ ) + { + // + c = Format[i]; + // + if( c != '%' ) + { + Str[j++] = c; + continue; + } + // + i++; + // + if( i >= fmtlinesize ) break; + + // + flag = 0; + // + c = Format[i]; + // + switch( c ) + { + // + case '%': + Str[j++] = c; + break; + // auaia aauanoaaiiiai ?enea + case 'f': + // ii?aaaeeou ?enei oeo? ai oi?ee + double val, w; + int p; + val = va_arg(arglist, double); + if (val < 0.0) + { + Str[j++] = '-'; + val = -val; + } + for (k = 0; k < 15; k++) + if (val < double_tab[k]) + break; + + if (val < 1.0) + { + Str[j++] = '0'; + } + + for (p = 1; p < k + 1; p++) + { + Str[j++] = '0' + di(val / double_tab[k - p] - 0.499) % 10; + } + Str[j++] = '.'; + w = 0.1; + for (p = 0; p < 2; p++) + { + val-=floor(val); + Str[j++] = '0' + di(val / w - 0.499) % 10; + w /= 10.0; + } + + // + default: + break; + } + } + // + Str[j] = 0; +} + +void *memcpy(void *dst, const void *src, unsigned size) +{ + while (size--) + *((char*)dst+size) = *((char*)src+size); + return dst; +} +*/ +int strcmp(const char *s1, const char *s2) +{ + int i; + + if (s1 == NULL) + if (s2 == NULL) + return 0; + else + return 1; + else + if (s2 == NULL) + return 1; + + for (i = 0;;i++) + { + if (s1[i] == '\0') + if (s2[i] == '\0') + return 0; + else + return 1; + else + if (s2[i] == '\0') + return 1; + else + { + if (s1[i] != s2[i]) + return 1; + } + } + return 0; +} + +kol_struct_import* kol_cofflib_load(char *name) +{ +//asm ("int $0x40"::"a"(68), "b"(19), "c"(name)); + __asm + { + mov eax, 68 + mov ebx, 19 + mov ecx, name + int 0x40 + } +} + + +void* kol_cofflib_procload (kol_struct_import *imp, char *name) +{ + +int i; +for (i=0;;i++) + if ( NULL == ((imp+i) -> name)) + break; + else + if ( 0 == strcmp(name, (imp+i)->name) ) + return (imp+i)->data; +return NULL; + +} + + +unsigned kol_cofflib_procnum (kol_struct_import *imp) +{ + +unsigned i, n; + +for (i=n=0;;i++) + if ( NULL == ((imp+i) -> name)) + break; + else + n++; + +return n; + +} + + +void kol_cofflib_procname (kol_struct_import *imp, char *name, unsigned n) +{ + +unsigned i; +*name = 0; + +for (i=0;;i++) + if ( NULL == ((imp+i) -> name)) + break; + else + if ( i == n ) + { + strcpy(name, ((imp+i)->name)); + break; + } + +} + + + +/* +end of system part +*/ + + +// поскольку я портировал с древнего доса... +void line( int x1, int y1, int x2, int y2) +{ + kos_DrawLine(x1,y1,x2,y2,SysColor,0); +} + +void outtextxy( int x, int y, char *s, int len) +{ + kos_WriteTextToWindow(x,y,0,SysColor,s,len); +} + +double textwidth( char *s, int len) +{ + int i; + for (i = 0; i < len; i++) + if (s[i] == 0) + break; + return id(i * 6); +} + +double textheight( char *s, int len) +{ + return 8.0; +} + +void setcolor( DWORD color) +{ + SysColor = color; +} + +void rectangle( int x1, int y1, int x2, int y2) +{ + kos_DrawBar(x1,y1,x2-x1,y2-y1,SysColor); +} + + + +Dword kos_GetSkinHeight() +{ + __asm{ + mov eax, 48 + mov ebx, 4 + int 0x40 + } +} + +Dword kos_GetSpecialKeyState() +{ + __asm{ + mov eax, 66 + mov ebx, 3 + int 0x40 + } +} + + + +Dword kos_GetSlotByPID(Dword PID) +{ + __asm + { + push ebx + push ecx + mov eax, 18 + mov ebx, 21 + mov ecx, PID + int 0x40 + pop ecx + pop ebx + } +} + + +Dword kos_GetActiveSlot() +{ + __asm + { + push ebx + mov eax, 18 + mov ebx, 7 + int 0x40 + pop ebx + } +} + + + +void kos_GetScrollInfo(int &vert, int &hor) +{ + short v, h; + __asm + { + mov eax, 37 + mov ebx, 7 + int 0x40 + mov ebx, eax + and eax, 0xffff + mov v, ax + shr ebx, 16 + mov h, bx + } + vert = v; + hor = h; +} + + +// получение информации о состоянии "мыши" функция 37/1 +void kos_GetMouseStateWnd( Dword & buttons, int & cursorX, int & cursorY ) +{ + Dword mB; + Word curX; + Word curY; + sProcessInfo sPI; + + // + __asm{ + mov eax, 37 + mov ebx, 1 + int 0x40 + mov curY, ax + shr eax, 16 + mov curX, ax + mov eax, 37 + mov ebx, 2 + int 0x40 + mov mB, eax + } + // + kos_ProcessInfo( &sPI ); + // + buttons = mB; + cursorX = curX - sPI.processInfo.x_start; + cursorY = curY - sPI.processInfo.y_start; +} + +char *ftoa(double d) +{ + char buffer[256], *p; + sprintf(buffer, "%f", d); + p = (char*)allocmem(strlen(buffer)+1); + strcpy(p, buffer); + return p; +} + +double atof(char *s) +{ + return convert(s, NULL); +} + + +int di(double x) +{ + int a; + __asm fld x + __asm fistp a + return a; +} + +double id(int x) +{ + double a; + __asm fild x + __asm fstp a + return a; +} diff --git a/programs/other/table/func.h b/programs/other/table/func.h new file mode 100644 index 0000000000..307ca7c1af --- /dev/null +++ b/programs/other/table/func.h @@ -0,0 +1,131 @@ + +#pragma once + +#include "kosSyst.h" +#include "kosFile.h" +#include "MCSMEMM.H" + +#include + + +#define min(a,b) (((a)<(b))?(a):(b)) +#define max(a,b) (((a)>(b))?(a):(b)) + + +#define ERROR -1 +#define ERROR_END -2 + +extern int convert_error; + +#define PREC 2 + +typedef int HDC; +typedef int DWORD; + +extern int SysColor; +extern char debuf[50]; + +typedef double (*function_t)(double); + +typedef struct +{ + double x, y; +} TCoord; + +struct kosBDVK +{ + Dword attrib; + Dword name_type; + Dword create_time; + Dword create_date; + Dword access_time; + Dword access_date; + Dword modify_time; + Dword modify_date; + Dword size_low; + Dword size_high; +}; + +Dword kos_GetSlotByPID(Dword PID); +Dword kos_GetActiveSlot(); +Dword kos_GetSkinHeight(); +Dword kos_GetSpecialKeyState(); +void kos_GetMouseStateWnd( Dword & buttons, int & cursorX, int & cursorY ); +void kos_DrawLine( Word x1, Word y1, Word x2, Word y2, Dword colour, Dword invert); +void DrawRegion(Dword x,Dword y,Dword width,Dword height,Dword color1); +int atoi(const char* string); +void kos_GetScrollInfo(int &vert, int &hor); + + +Dword kos_GetSlotByPID(Dword PID); +Dword kos_GetActiveSlot(); +Dword kos_GetSkinHeight(); +Dword kos_GetSpecialKeyState(); + + +double fabs(double x); +double cos(double x); +double sin(double x); +bool isalpha(char c); +double convert(char *s, int *len=NULL); +void format( char *Str, int len, char* Format, ... ); + +void line( int x1, int y1, int x2, int y2); + +void outtextxy( int x, int y, char *s, int len); +void settextstyle( int a1, int a2, int a3); + + +double textwidth( char *s, int len); +double textheight( char *s, int len); +void setcolor( DWORD color); +void unsetcolor(HDC hdc); +void rectangle( int x1, int y1, int x2, int y2); + +typedef struct +{ +unsigned p00 ; +unsigned p04 ; +unsigned p08 ; +unsigned p12 ; +unsigned p16 ; +char p20 ; +char *p21 ; +} kol_struct70 ; + + +typedef struct +{ +unsigned p00 ; +char p04 ; +char p05[3] ; +unsigned p08 ; +unsigned p12 ; +unsigned p16 ; +unsigned p20 ; +unsigned p24 ; +unsigned p28 ; +unsigned p32[2] ; +unsigned p40 ; +} kol_struct_BDVK ; + +typedef struct +{ +char *name ; +void *data ; +} kol_struct_import ; + + + +kol_struct_import* kol_cofflib_load(char *name); +void* kol_cofflib_procload (kol_struct_import *imp, char *name); +unsigned kol_cofflib_procnum (kol_struct_import *imp); +void kol_cofflib_procname (kol_struct_import *imp, char *name, unsigned n); +int strcmp(const char* string1, const char* string2); + +char *ftoa(double d); +double atof(char *s); + + +int di(double x); +double id(int x); diff --git a/programs/other/table/hello.cpp b/programs/other/table/hello.cpp new file mode 100644 index 0000000000..4c721446ec --- /dev/null +++ b/programs/other/table/hello.cpp @@ -0,0 +1,1498 @@ + +#include "func.h" +#include "parser.h" +#include "calc.h" +#include "use_library.h" +///#include "use_library.h" +//const char header[] = "Table"; + +#define TABLE_VERSION "0.94a" + +// строки, которые выводит программа +const char *sFileSign = "KolibriTable File\n"; +const char sFilename[] = "Filename: "; +const char sSave[] = "Save"; +const char sLoad[] = "Load"; +const char sNew[] = "New"; + +const char er_file_not_found[] = "Cannot open file. "; +const char er_format[] = "Error: bad format. "; +const char msg_save[] = "File saved. "; +const char msg_load[] = "File loaded. "; +const char msg_new[] = "Memory cleared. "; + +// свой PID +Dword myPID = -1; + +// начальные размеры +#define WND_W 550 +#define WND_H 400 +// новые размеры и координаты +int wi = WND_W, he = WND_H; +int win_x, win_y; + +// цвета элементов интерфейса +#define GRID_COLOR 0xa0a0a0 +#define TEXT_COLOR 0x000000 +#define CELL_COLOR 0xffffff +#define SEL_CELL_COLOR 0xe0e0ff +#define FIXED_CELL_COLOR 0xe0e0ff +#define SEL_FIXED_CELL_COLOR 0x758FC1 +#define TEXT_SEL_FIXED_COLOR 0xffffff + +#define SCROLL_BAR_WIDTH 16 +#define SCROLL_BAR_HEIGHT 16 + +// ID кнопок +#define FILENAME_BUTTON 0x10 +#define SAVE_BUTTON 0x11 +#define LOAD_BUTTON 0x12 +#define NEW_BUTTON 0x13 +#define DRAG_BUTTON 0x20 + +#define SCROLL_LEFT_BUTTON 0x21 +#define SCROLL_RIGHT_BUTTON 0x22 +#define SCROLL_UP_BUTTON 0x23 +#define SCROLL_DOWN_BUTTON 0x24 +#define SCROLL_WIDTH 0x25 +#define SCROLL_HEIGHT 0x26 + +#define COL_BUTTON 0x100 +#define ROW_BUTTON (COL_BUTTON + 0x100) +#define COL_HEAD_BUTTON (ROW_BUTTON + 0x100) +#define ROW_HEAD_BUTTON (COL_HEAD_BUTTON + 0x100) +#define CELL_BUTTON (ROW_HEAD_BUTTON + 0x100) + + +// нижняя панель с кнопками и полем ввода +#define MENU_PANEL_HEIGHT 40 +Dword panel_y = 0; + +// для поля ввода +char edit_text[256] = ""; +edit_box cell_box = {0,9*8-5,WND_H - 16-32,0xffffff,0x6a9480,0,0x808080,0,255,(dword)&edit_text,0}; + +// ячейки - их параметры и текст +DWORD def_col_width = 80, def_row_height = 16; +DWORD col_count = 200, row_count = 100; +DWORD *col_width, *row_height; +char ***cells; +char ***values; // значения формул, если есть + +bool display_formulas = 0; // отображать ли формулы вместо значений + +// координаты отображаемых столбцов и строк +DWORD *col_left, *row_top; + +// буфер обмена +char ***buffer = NULL; +DWORD buf_col, buf_row; +DWORD buf_old_x, buf_old_y; + +// это координаты ячейки, отображаемой в ЛВ угле +DWORD scroll_x = 1, scroll_y = 1; +// это выделенная ячейка +DWORD sel_x = 1, sel_y = 1; +DWORD prev_x = 0, prev_y = 0; // предыдущая выделенная +int was_single_selection = 0; + +// конец выделения если выделено несколько ячеек +DWORD sel_end_x = sel_x, sel_end_y = sel_y; + +// флаг +bool sel_moved = 0; +bool sel_end_move = 0; +// сколько ячеек помещается в окне по х и у +DWORD nx = 0, ny = 0; + +// флаг реадктирования ячейки +//bool is_edit = 0; +#define ed_focus 2 +#define is_edit (cell_box.flags & ed_focus) + +// редактирование имени файла +bool fn_edit = 0; +char fname[256]; +edit_box file_box = {0,9*8-5,WND_H - 16-32,0xffffff,0x6a9480,0,0x808080,0,255,(dword)&fname,0}; + +// изменение размеров +#define SIZE_X 1 // состояние +#define SIZE_Y 2 +#define SIZE_SELECT 3 +#define SIZE_DRAG 4 +int size_mouse_x, size_mouse_y, size_id, size_state = 0; + +// растаскивание ячейки при ее тащении за правый нижний угол, с заполнением ячеек +int drag_x, drag_y; +int old_end_x, old_end_y; + +void draw_window(); + +//edit_box ebox = {250,14,35,0xffffff,0x6f9480,0,0xAABBCC,0,248,0,2,20,20}; + +void kos_DrawRegion(Word x, Word y,Word width, Word height, Dword color1, Word invert) +{ + kos_DrawLine(x,y,x+width-2,y,color1,invert); + kos_DrawLine(x,y+1,x,y+height-1,color1,invert); + kos_DrawLine(x+width-1,y,x+width-1,y+height-2,color1,invert); + kos_DrawLine(x+1,y+height-1,x+width-1,y+height-1,color1,invert); +} + +// edit box +/* +void KEdit() +{ + int max_char = (editbox_w) / 6; + kos_DrawBar(editbox_x,editbox_y,editbox_w-1,editbox_h-3,0xFFFFFF); //белая область + if (strlen(edit_text) nx - 1) + { + scroll_x = x; + ch = 1; + } + if (y < scroll_y || y > ny - 1) + { + scroll_y = y; + ch = 1; + } + if (ch) + { + sel_moved = 1; + draw_window(); + } + + file_box.flags &= ~ed_focus; + + cell_box.flags |= ed_focus; + cell_box.left = col_left[x] + 1; + cell_box.top = row_top[y] + 1; + cell_box.width = col_width[x] - 2; + //cell_box.height= row_height[y]; + memset((Byte*)edit_text, 0, sizeof(edit_text)); + if (cells[x][y]) + { + strcpy(edit_text, cells[x][y]); + edit_text[strlen(cells[x][y]) - 1] = '\0'; + } + cell_box.pos = cell_box.offset = 0; + + draw_window(); +} + +void stop_edit() +{ + if (is_edit) + { + cell_box.flags &= ~ed_focus; + if (cells[sel_x][sel_y]) + freemem(cells[sel_x][sel_y]); + if (strlen(edit_text) > 0) + { + cells[sel_x][sel_y] = (char*)allocmem(strlen(edit_text)+1); + strcpy(cells[sel_x][sel_y], edit_text); + } + else + cells[sel_x][sel_y] = NULL; + //memset((Byte*)edit_text,0, 256); + calculate_values(); + } + else + return; +} + +void cancel_edit() +{ + if (!is_edit) + return; + cell_box.flags &= ~ed_focus; + memset((Byte*)edit_text,0, 256); + draw_window(); +} + +void check_sel() +{ + DWORD sx0=scroll_x, sy0=scroll_y; + + if (sel_x >= nx - 1 /*&& sel_x < col_count - nx + scroll_x + 1*/) + //if (sel_x == nx) + scroll_x++; + //else + // scroll_x = sel_x; + if (sel_y >= ny - 1 /*&& sel_y < row_count - ny + scroll_y */) + //if (sel_y == ny) + scroll_y++; + //else + // scroll_y = sel_y; + + if (sel_x < scroll_x) + scroll_x = sel_x; + if (sel_y < scroll_y) + scroll_y = sel_y; + + if (sx0 != scroll_x || sy0 != scroll_y) + sel_moved = 0; // надо перерисовать все + +} + +// сдвинуть выделение +void move_sel(DWORD new_x, DWORD new_y) +{ + sel_moved = 1; + stop_edit(); + prev_x = sel_x; + prev_y = sel_y; + sel_x = new_x; + if (sel_x < 1) + sel_x = 1; + if (sel_x > col_count - 1) + sel_x = col_count - 1; + sel_end_x = sel_x; + sel_y = new_y; + if (sel_y < 1) + sel_y = 1; + if (sel_y > row_count - 1) + sel_y = row_count - 1; + sel_end_y = sel_y; + check_sel(); + draw_window(); +} + +void draw_custom_button(int x0, int y0, int sx, int sy, int blue_border) +{ + int x1 = x0 + sx; + int y1 = y0 + sy; + + if (blue_border) kos_DrawRegion(x0-1, y0-1, sx+3, sy+3, 0x94aece, 0); + + // серый прямоугольник + + kos_DrawBar(x0 + 1, y0 + 1, sx - 1, sy - 1, 0xe4dfe1); + + // две белые линии: сверху и слева + + kos_DrawLine(x0, y0, x1, y0, 0xffffff, 0); + kos_DrawLine(x0, y0, x0, y1, 0xffffff, 0); + + // две серые линии: снизу и справа + kos_DrawLine(x0, y1, x1, y1, 0xc7c7c7, 0); + kos_DrawLine(x1, y0, x1, y1, 0xc7c7c7, 0); +} + +// x - между low и high ? - необязательно low= low && x <= high):(x >= high && x <= low)); +} + +void clear_cell_slow(int px, int py) +{ + int i; + int x0 = col_width[0]; + for (i = scroll_x; i < px; i++) + { + x0 += col_width[i]; + } + int x1 = x0; + x1 += col_width[px]; + int y0 = row_height[0]; + for (i = scroll_y; i < py; i++) + { + y0 += row_height[i]; + } + int y1 = y0; + y1 += row_height[py]; + kos_DrawBar(x0 + 1, y0 + 1, x1 - x0 - 1, y1 - y0 - 1, 0xffffff); +} + +//debug +const int debugcolor[10]={0xff0000,0x00ff00,0x0000ff,0xffff00,0x00ffff,0xff00ff,0x800000,0x008000,0x000080,0x800080}; +int debugc=0; + +// рисование ячеек +#define is_x_changed(v) ((v) == sel_x || (v) == prev_x) +#define is_y_changed(v) ((v) == sel_y || (v) == prev_y) + +void draw_grid() +{ + int i,j; + long x0 = 0, y0 = 0, x = 0, y = 0, dx, popravka; + DWORD text_color; + //int lx, ly; + +// sprintf(debuf, "%U,%U", scroll_x, scroll_y); +// rtlDebugOutString(debuf); + + nx=ny=0; + + // очистить область около выделенной ячейки + if (sel_moved) + { + clear_cell_slow(sel_x, sel_y); + clear_cell_slow(prev_x, prev_y); + } + else + { + // очистить всю область ячеек + //kos_DrawBar(col_width[0]+1, row_height[0]+1, wi - SCROLL_BAR_WIDTH-col_width[0]-1, he - SCROLL_BAR_HEIGHT-row_height[0]-1, 0xffffff); + } + + col_left[0] = 0; + // ячейки - заголовки столбцов + вертикальные линии + x = col_width[0]; + nx = 1; + for (i = 1; i < col_count; i++) + { + col_left[i] = -1; + if (i >= scroll_x) + { + { + if (!sel_moved || is_x_changed(i)) + kos_DrawLine(x-x0, 0, x-x0, row_height[0], GRID_COLOR, 0); + // и заголовок ячейки по х + text_color = TEXT_COLOR; + dx = (col_width[i]-6)/2; + int dy = (row_height[0] - 8) / 2 + 1; + int cur_width = col_width[i] - 1; + if (cur_width + x - x0 > wi - SCROLL_BAR_WIDTH) + cur_width = wi - SCROLL_BAR_WIDTH - x + x0; + if (!sel_moved || (is_x_changed(i))) + if (is_between(i,sel_x,sel_end_x)) + { + kos_DrawBar(x - x0 + 1,0,cur_width,row_height[0],SEL_FIXED_CELL_COLOR); //0x0000CC + text_color = TEXT_SEL_FIXED_COLOR; + } + else + { + kos_DrawBar(x - x0 + 1,0,cur_width,row_height[0],FIXED_CELL_COLOR); + text_color = TEXT_COLOR; + } + if (!sel_moved || (is_x_changed(i))) kos_WriteTextToWindow(x-x0+2+dx,dy,0,text_color,cells[i][0],strlen(cells[i][0])); + + // есть кнопка стоблца и еще кнопка изменения ширины + if (x - x0 + col_width[i] <= wi - col_width[0]) + kos_DefineButton(x-x0+5,0,cur_width - 10,row_height[0]-1,0x60000000+COL_HEAD_BUTTON+i,0); + //kos_DefineButton(x-x0+col_width[i]-10,0,15,row_height[0]-1,0x60000000+COL_SIZE_BUTTON+i,0); + col_left[i] = x - x0; + } + if (x - x0 > wi - col_width[0]) + { + x += col_width[i]; + nx++; + break; + } + } + else + { + x0 += col_width[i]; + } + x += col_width[i]; + nx++; + } + + //kos_DefineButton(0,0,0,0,0x80000000+COL_HEAD_BUTTON+i,0); + + for (j = i + 1; j < col_count; j++) + col_left[j] = wi; + //if (!sel_moved || (is_x_changed(nx))) kos_DrawLine(x - x0, 0, x - x0, he, GRID_COLOR, 0); + + // ячейки - заголовки строк + горизонт. линии + y = row_height[0]; + ny = 1; + row_top[0] = 0; + for (i = 1; i < row_count && y - y0 < he - 10; i++) + { + row_top[i] = -1; + if (i >= scroll_y) + { + { + if (!sel_moved || (is_y_changed(i))) + kos_DrawLine(0, y - y0, wi - SCROLL_BAR_WIDTH, y - y0, GRID_COLOR, 0); + // и заголовок ячейки по y + text_color = TEXT_COLOR; + dx = (col_width[0]-6 * strlen(cells[0][i]))/2; // optimize this, change strlen + int dy = (row_height[i] - 8) / 2 + 1; + if (!sel_moved || (is_y_changed(i))) + if (is_between(i,sel_y,sel_end_y)) + { + kos_DrawBar(0,y-y0+1,col_width[0],row_height[i] - 1,SEL_FIXED_CELL_COLOR); + text_color = TEXT_SEL_FIXED_COLOR; + } + else + { + kos_DrawBar(0,y-y0+1,col_width[0],row_height[i] - 1,FIXED_CELL_COLOR); + text_color = TEXT_COLOR; + } + + if (!sel_moved || (is_y_changed(i))) + kos_WriteTextToWindow(2+dx,y-y0+dy,0,text_color,cells[0][i],strlen(cells[0][i])); + + kos_DefineButton(0,y-y0+5,col_width[0]-1,row_height[i]-6,0x60000000+ROW_HEAD_BUTTON+i,0); + //kos_DefineButton(0,y-y0+row_height[i]-5,col_width[0]-1,10,0x60000000+ROW_SIZE_BUTTON+i,0); + row_top[i] = y - y0; + } + } + else + { + y0 += row_height[i]; + } + y += row_height[i]; + ny++; + } + + kos_DefineButton(0,0,0,0,0x80000000+ROW_HEAD_BUTTON+ny-1,0); + + for (j = i + 1; j < row_count; j++) + row_top[j] = he; + if (!sel_moved || (is_y_changed(ny))) + kos_DrawLine(0, y - y0, wi - SCROLL_BAR_WIDTH, y - y0, GRID_COLOR, 0); + + if (!sel_moved || (is_x_changed(0) && is_y_changed(0))) + kos_DrawBar(0,0,col_width[0],row_height[0],FIXED_CELL_COLOR); + // ЛВ ячейка + + //sprintf(debuf, "%U, %U; %U, %U", x0, y0, nx, ny); + //rtlDebugOutString(debuf); + +// popravka = (y - y0 < he - 10); + //sprintf(debuf, "%U, %U", scroll_y, ny); + //rtlDebugOutString(debuf); + + + // сами ячейки + + y = row_height[0]; + for (i = scroll_y; i < ny; i++) + { + x = col_width[0]; + if (!sel_moved) + kos_DrawBar(col_width[0]+1, y+1, wi - SCROLL_BAR_WIDTH-col_width[0]-1, row_height[i]-1, 0xffffff); + for (j = scroll_x; j < nx-1; j++) + { + if (!sel_moved || is_x_changed(j) || is_y_changed(i)) + kos_DrawLine(col_left[j], row_top[i], col_left[j], row_height[i], GRID_COLOR, 0); + + // заголовки уже нарисованы - пропускаем их + if (i && j) + { + //kos_DrawBar(x+1, y+1, col_width[i]-1, row_height[i]-1, 0xffffff); + + //rtlDebugOutString(cap); + //if (j >= sel_x && j <= sel_end_x && i >= sel_y && i <= sel_end_y) + if (is_between(j,sel_x,sel_end_x) && is_between(i, sel_y, sel_end_y) // (j,i) - выделена + && ((!sel_moved) || (is_x_changed(j) && is_y_changed(i)))) // и ее нужно нарисовать + { + if (i == sel_y && j == sel_x) // рамка + { + kos_DrawBar(x,y,col_width[j],2,TEXT_COLOR); // up + kos_DrawBar(x,y,2,row_height[i],TEXT_COLOR); // left + kos_DrawBar(x,y+row_height[i]-2,col_width[j]-2-3,2,TEXT_COLOR); // bottom + kos_DrawBar(x+col_width[j]-2,y, 2,row_height[i]-2-3,TEXT_COLOR); // right + + kos_DrawBar(x+col_width[j]-4,y+row_height[i]-4,4,4,TEXT_COLOR); + //kos_DefineButton(x+col_width[j]-2,y+row_height[i]-2,4,4,0x60000000+DRAG_BUTTON,0x000000); + drag_x = x + col_width[j] - 4; + drag_y = y + row_height[i] - 4; + } + else + kos_DrawBar(x + 1,y + 1,col_width[j] - 2,row_height[i] - 2,SEL_CELL_COLOR); // выделена но не основная(серая) + + } + //kos_DefineButton(x,y,col_width[j]-1,row_height[i]-1,0x60000000+CELL_BUTTON+((i << 8) + j),0); + + char *text; + if (values[j][i] && values[j][i][0] == '#') + { + text = cells[j][i]; + kos_DrawRegion(x+1, y+1, col_width[j]-1, row_height[i]-1, 0xff0000, 0); + } + else + text = (values[j][i] && !display_formulas ? values[j][i] : cells[j][i]); + + int dy = (row_height[i] - 8) / 2 + 1; + + if (text) + if (strlen(text) < col_width[j]/6) + kos_WriteTextToWindow(x+2,y+dy,0,text_color,text,strlen(text)); + else + kos_WriteTextToWindow(x+2,y+dy,0,text_color,text,col_width[j]/6); + + } + if (!sel_moved || is_x_changed(j) || is_y_changed(i)) + kos_DrawLine(col_left[j]+col_width[j], row_top[i], col_left[j]+col_width[j], row_height[i], GRID_COLOR, 0); + x += col_width[j]; + } + y += row_height[i]; + } + + // Scrolls: + // horizontal + + //if (!sel_moved) kos_DrawBar(0, he - SCROLL_BAR_HEIGHT, wi - SCROLL_BAR_WIDTH, SCROLL_BAR_HEIGHT, FIXED_CELL_COLOR); + //if (!sel_moved) kos_DrawBar(scroll_x * wi / col_count, he - SCROLL_BAR_HEIGHT, wi / col_count, SCROLL_BAR_HEIGHT, SEL_FIXED_CELL_COLOR); + if (!sel_moved) + { + // горизонталь + kos_DrawBar(17, he - SCROLL_BAR_HEIGHT, wi - SCROLL_BAR_WIDTH - 32, SCROLL_BAR_HEIGHT, 0xced0d0); + // синие линии + kos_DrawRegion(0, he - SCROLL_BAR_HEIGHT, wi - SCROLL_BAR_WIDTH, SCROLL_BAR_HEIGHT+1, 0x94aece, 0); + // левая кнопка + draw_custom_button(1, he - SCROLL_BAR_HEIGHT + 1, 14, 14, 1); + kos_WriteTextToWindow(6, he - SCROLL_BAR_HEIGHT + 5, 0, 0, "\x1B", 1); + // правая + draw_custom_button(wi - SCROLL_BAR_WIDTH * 2 + 1, he - SCROLL_BAR_HEIGHT + 1, 14, 14, 1); + kos_WriteTextToWindow(wi - SCROLL_BAR_WIDTH * 2 + 6, he - SCROLL_BAR_HEIGHT + 5, 0, 0, "\x1A", 1); + // ползунок + int tmp_w = (nx - scroll_x) * (wi - SCROLL_BAR_WIDTH - 2 * 14 - 14) / (col_count + 1); + if (tmp_w < 16) + tmp_w = 16; + draw_custom_button(17 + (scroll_x - 1) * (wi - SCROLL_BAR_WIDTH - 2 * 14 - 14) / (col_count + 1), he - SCROLL_BAR_HEIGHT + 1, + tmp_w, 14, 1); + +#define sw(x,y) y,x +// не пинайте меня за это, было лень переставлять руками... + + // вертикаль + kos_DrawBar(sw(17, wi - SCROLL_BAR_WIDTH), sw(he - SCROLL_BAR_HEIGHT - 33, SCROLL_BAR_WIDTH), 0xced0d0); + // синие линии + kos_DrawRegion(sw(0, wi - SCROLL_BAR_WIDTH), sw(he - SCROLL_BAR_HEIGHT, SCROLL_BAR_WIDTH+1), 0x94aece, 0); // up + + // верхняя кнопка + draw_custom_button(sw(1, wi - SCROLL_BAR_WIDTH + 1), 14, 14, 1); + kos_WriteTextToWindow(sw(5, wi - SCROLL_BAR_WIDTH + 6), 0, 0, "\x18", 1); + // нижняя + draw_custom_button(sw(he - SCROLL_BAR_HEIGHT * 2 + 1, wi - SCROLL_BAR_WIDTH + 1), 14, 14, 1); + //draw_custom_button(sw(he - SCROLL_BAR_HEIGHT * 2 + 1, wi - SCROLL_BAR_WIDTH + 1), 14, 14, 1); + kos_WriteTextToWindow(sw(he - SCROLL_BAR_HEIGHT * 2 + 5, wi - SCROLL_BAR_WIDTH + 6), 0, 0, "\x19", 1); + // ползунок + int tmp_h = (ny - scroll_y) * (he - SCROLL_BAR_HEIGHT - 2 * 14 - 14) / (row_count + 1); + if (tmp_h < 16) + tmp_h = 16; + draw_custom_button(sw(17 + (scroll_y - 1) * (he - SCROLL_BAR_HEIGHT - 2 * 14 - 14) / (row_count + 1), wi - SCROLL_BAR_WIDTH + 1), + sw(tmp_h, 14), 1); + } +#define NO_DRAW 0x60000000 + kos_DefineButton(1, he - SCROLL_BAR_HEIGHT + 1, 14, 14, NO_DRAW + SCROLL_LEFT_BUTTON,0); + kos_DefineButton(wi - SCROLL_BAR_WIDTH * 2 + 2, he - SCROLL_BAR_HEIGHT + 1, 14, 14, NO_DRAW + SCROLL_RIGHT_BUTTON,0); + kos_DefineButton(17, he - SCROLL_BAR_HEIGHT + 1, (wi - SCROLL_BAR_WIDTH - 2 * 14), 14, NO_DRAW + SCROLL_WIDTH,0); + + kos_DefineButton(sw(1, wi - SCROLL_BAR_WIDTH + 1), 14, 14, NO_DRAW + SCROLL_UP_BUTTON,0); + kos_DefineButton(sw(he - SCROLL_BAR_HEIGHT * 2 + 2, wi - SCROLL_BAR_WIDTH + 1), 14, 14, NO_DRAW + SCROLL_DOWN_BUTTON,0); + kos_DefineButton(sw(17, wi - SCROLL_BAR_WIDTH + 1), sw((he - SCROLL_BAR_HEIGHT - 2 * 14), 14), NO_DRAW + SCROLL_HEIGHT,0); + +} + +// очень быстрое рисование сетки, в процессе изменения размеров ячеек +void draw_size_grid() +{ + //rtlDebugOutString("draw size grid"); + + kos_WindowRedrawStatus(1); + + if (size_state == SIZE_X) + { + int x, x0, i; + + x = col_width[0]; + x0 = 0; + for (i = 1; i < col_count && x - x0 + col_width[i] < wi - 10; i++) + { + if (i >= scroll_x) + { + if (i >= size_id) + kos_DrawLine(x - x0, 0, x - x0, he, 0, 1); + } + else + x0 += col_width[i]; + x += col_width[i]; + } + kos_DrawLine(x - x0, 0, x - x0, he, 0, 1); + } + else + { + int y, y0, i; + + y = row_height[0]; + y0 = 0; + for (i = 1; i < col_count && y - y0 + row_height[i] < he - 10; i++) + { + if (i >= scroll_y) + { + if (i >= size_id) + kos_DrawLine(0, y - y0, wi, y - y0, 0, 1); + } + else + y0 += row_height[i]; + y += row_height[i]; + } + kos_DrawLine(0, y - y0, wi, y - y0, 0, 1); + } + + + kos_WindowRedrawStatus(2); +} + + +// быстрое рисование выделенной области при выделении мышью +#define DCOLOR 0 +//0xff0000 +#define DINVERT 1 +void draw_drag() +{ + kos_WindowRedrawStatus(1); + + // собственно, 4 инверсные линии + + int k0 = min(sel_x, sel_end_x); + int k1 = max(sel_x, sel_end_x); + int n0 = min(sel_y, sel_end_y); + int n1 = max(sel_y, sel_end_y); + + DWORD x0 = col_left[k0] - 1; + DWORD x1 = col_left[k1] + col_width[k1] + 1; + DWORD y0 = row_top[n0] - 1; + DWORD y1 = row_top[n1] + row_height[n1] + 1; + if (x0 > wi - 1) x0 = wi - 1; + if (x1 > wi - 1) x1 = wi - 1; + if (y0 > he - 1) y0 = he - 1; + if (y1 > he - 1) y1 = he - 1; + + //sprintf(debuf,"drag %U %U %U %U",k0,k1,n0,n1); + //rtlDebugOutString(debuf); + + kos_DrawLine(x0, y0, x0, y1, DCOLOR, DINVERT); + kos_DrawLine(x0, y0, x1, y0, DCOLOR, DINVERT); + kos_DrawLine(x1, y0, x1, y1, DCOLOR, DINVERT); + kos_DrawLine(x0, y1, x1, y1, DCOLOR, DINVERT); + + kos_WindowRedrawStatus(2); +} + +void draw_window() +{ + int i; + double xx0=0.0, yy0=0.0; + sProcessInfo info; + void *p; + + if (sel_end_move) + sel_moved = 0; + + memset((Byte*)&info, 0, 1024); + + kos_ProcessInfo(&info, 0xFFFFFFFF); + + p = info.rawData + 42; // magic + wi = *(Dword *)(p); + he = *(Dword *)((Byte *)p + 4); + win_x = *(Dword *)((Byte *)p - 8); + win_y = *(Dword *)((Byte *)p - 4); + + myPID = *(Dword*)((Byte *)p - 12); + + if (wi == 0) + wi = WND_W; + if (he == 0) + he = WND_H; + + he -= kos_GetSkinHeight() + MENU_PANEL_HEIGHT; // доступная высота окна + wi -= 6 + 4; + + // start redraw + kos_WindowRedrawStatus(1); + + kos_DefineAndDrawWindow(10,40,WND_W,WND_H,0x33,0x40FFFFFF,0,0,(Dword)"Table v" TABLE_VERSION); + + if (he + MENU_PANEL_HEIGHT <= 8) + { + kos_WindowRedrawStatus(2); + return; + } + + if (!sel_moved) + { + kos_DrawBar(wi-15,he - kos_GetSkinHeight() +7,16,16,0xe4dfe1); + kos_DrawBar(0,he - kos_GetSkinHeight() + 23,wi + 1,MENU_PANEL_HEIGHT-4,0xe4dfe1); + } + +// edit_box_draw((dword)&ebox); + int y = he + kos_GetSkinHeight() - 10; + + if (!sel_moved) + { + kos_WriteTextToWindow(3 + 1, y + 3, 0x80 , 0x000000, (char*)sFilename, strlen(sFilename)); + } + + //DWORD fn_line_color = fn_edit ? 0x000000 : 0xc0c0c0; + //kos_DrawRegion(61, y - 2, 102, 18, fn_line_color, 0); + + // дальше editbox width = 100 + + // border around edit box + file_box.left = 64; + file_box.top = y - 1; + file_box.width = 98; + //editbox_h = 18; + //kos_DefineButton(62, y + 3, 100, 16, 0x60000000+FILENAME_BUTTON, 0xd0d0d0); + + + // сохранить + kos_DefineButton(20 + 160, y - 5, 60, 20, SAVE_BUTTON, 0xd0d0d0); + kos_WriteTextToWindow(22 + 160 + (60 - strlen(sSave) * 6) / 2, y + 2, 0, 0x000000, (char*)sSave, strlen(sSave)); + + // загрузить + kos_DefineButton(90 + 160, y - 5, 60, 20, LOAD_BUTTON, 0xd0d0d0); + kos_WriteTextToWindow(92 + 160 + (60 - strlen(sLoad) * 6) / 2, y + 2, 0, 0x000000, (char*)sLoad, strlen(sLoad)); + + // создать. только эту кнопу воткнуть некуда о_О + /* + kos_DefineButton(90 + 160 + 70, y - 5, 60, 20, NEW_BUTTON, 0xd0d0d0); + kos_WriteTextToWindow(92 + 160 + 10 + 70, y + 2, 0, 0x000000, (char*)sNew, strlen(sNew)); + */ + panel_y = y; + + draw_grid(); + //kos_DefineButton(0,0,WND_W,WND_H,0x60000002,0); + //if (is_edit) KEdit(); + + if ((void*)edit_box_draw != NULL) + { + if (is_edit) + edit_box_draw((DWORD)&cell_box); + edit_box_draw((DWORD)&file_box); + } + + // end redraw + kos_WindowRedrawStatus(2); + sel_moved = 0; +} + + +void process_mouse() +{ + Dword mouse_btn, ckeys, shift, ctrl; + int mouse_x, mouse_y, i, p, dx = 0, dy = 0; + int redraw = 0; + + Dword mySlot = kos_GetSlotByPID(myPID); + if (kos_GetActiveSlot() != mySlot) + return; + + edit_box_mouse((dword)&cell_box); + edit_box_mouse((dword)&file_box); + + int vert, hor; + kos_GetScrollInfo(vert, hor); + + //sprintf(debuf, "scroll %U %U", vert, hor); + //rtlDebugOutString(debuf); + + if (vert != 0) //труъ перерисовка! + { + move_sel(sel_x, sel_y + vert); + //move_sel(sel_x + hor, sel_y); + return; + } + + kos_GetMouseState(mouse_btn, mouse_x, mouse_y); + mouse_x -= 5; + mouse_y -= kos_GetSkinHeight(); + mouse_btn &= 0x0001; + + ckeys = kos_GetSpecialKeyState(); + shift = ckeys & 0x3; + + if (!size_state && !mouse_btn) + return; + if (mouse_btn && !size_state) // LMB down + { + //rtlDebugOutString("lmb down and not resize"); + + if (mouse_x >= drag_x && mouse_x <= drag_x + 4 && mouse_y >= drag_y && mouse_y <= drag_y + 4) + { + size_state = SIZE_DRAG; + old_end_x = sel_end_x; + old_end_y = sel_end_y; + } + else if (mouse_y <= row_height[0]) + { + //rtlDebugOutString("can resize cols"); + int kx = -1, i; + for (i = 0; i < col_count - 1; i++) + if (mouse_x >= col_left[i] + col_width[i] - 5 && + mouse_x <= col_left[i + 1] + 5) + { + kx = i; break; + } + if (kx != -1) + { + //sprintf(debuf,"size x %U",k); + //rtlDebugOutString(debuf); + size_id = kx; + size_state = SIZE_X; + } + } + else if (mouse_x <= col_width[0]) + { + int ky = -1; + for (i = 0; i < row_count - 1; i++) + if (mouse_y >= row_top[i] + row_height[i] - 5 && + mouse_y <= row_top[i + 1] + 5) + { + ky = i; break; + } + if (ky != -1) + { + size_id = ky; + size_state = SIZE_Y; + } + } + else // кликнута ячейка + if (mouse_x <= col_left[nx - 1] && mouse_y <= row_top[ny - 1]) + { + was_single_selection = sel_x == sel_end_x && sel_y == sel_end_y; + int kx = -1, i; + for (i = 0; i < col_count - 1; i++) + if (mouse_x >= col_left[i] && + mouse_x <= col_left[i] + col_width[i]) + { + kx = i; break; + } + int ky = -1; + for (i = 0; i < row_count - 1; i++) + if (mouse_y >= row_top[i] && + mouse_y <= row_top[i] + row_height[i]) + { + ky = i; break; + } + if (kx != -1 && ky != -1) + { + if (!shift) + { + move_sel(kx, ky); + return; + } + else + { + sel_end_x = kx; + sel_end_y = ky; + } + size_state = SIZE_SELECT; + } + } + if (size_state) + { + size_mouse_x = mouse_x; + size_mouse_y = mouse_y; + } + return; + } + else if (!mouse_btn && size_state) + { + sel_moved = 0; // чтобы была тру перерисовка + //rtlDebugOutString("resize end"); + + if (size_state == SIZE_DRAG) + { + fill_cells(sel_x, sel_y, sel_end_x, sel_end_y, old_end_x, old_end_y); + } + + sel_moved = (size_state == SIZE_SELECT && sel_x == sel_end_x && sel_y == sel_end_y && was_single_selection); + size_state = 0; + draw_window(); // все сдвинулось - надо обновиться + return; + } + if (size_state == SIZE_X && mouse_x != size_mouse_x) + { + draw_size_grid(); + col_width[size_id] += mouse_x - size_mouse_x; + if (col_width[size_id] < 15) + col_width[size_id] = 15; + else if (col_width[size_id] > wi / 2) + col_width[size_id] = wi / 2; + draw_size_grid(); + } + if (size_state == SIZE_Y && mouse_y != size_mouse_y) + { + draw_size_grid(); + row_height[size_id] += mouse_y - size_mouse_y; + if (row_height[size_id] < 15) + row_height[size_id] = 15; + else if (row_height[size_id] > he / 2) + row_height[size_id] = he / 2; + draw_size_grid(); + } + if ((size_state == SIZE_SELECT || size_state == SIZE_DRAG) && (mouse_x != size_mouse_x || mouse_y != size_mouse_y)) + { + draw_drag(); + int kx = -1, i; + for (i = 0; i < col_count - 1; i++) + if (mouse_x >= col_left[i] && + mouse_x <= col_left[i + 1]) + { + sprintf(debuf, "yyy %U",col_left[i+1]); + rtlDebugOutString(debuf); + kx = i; break; + } + int ky = -1; + for (i = 0; i < row_count - 1; i++) + if (mouse_y >= row_top[i] && + mouse_y <= row_top[i + 1]) + { + ky = i; break; + } + if (kx != -1) sel_end_x = kx; + if (kx != -1) sel_end_y = ky; + if (size_state == SIZE_DRAG) + { + if (abs(sel_end_x - sel_x) > 0) + { + sel_end_y = old_end_y; + } + else if (abs(sel_end_y - sel_y) > 0) + { + sel_end_x = old_end_x; + } + } + draw_drag(); + } + size_mouse_x = mouse_x; + size_mouse_y = mouse_y; +} + +void process_key() +{ + Dword mouse_btn, ckeys, shift, ctrl; + int mouse_x, mouse_y, i, p, dx = 0, dy = 0; + + // key pressed, read it + Byte keyCode; + ckeys = kos_GetSpecialKeyState(); + shift = ckeys & 0x3; + ctrl = ckeys & 0x0c; + //if (ctrl) + // rtlDebugOutString("control pressed!"); + dx = 0, dy = 0; + sel_moved = 0; + sel_end_move = 0; + kos_GetKey(keyCode); + + __asm + { + mov ah, keyCode + } + edit_box_key((dword)&cell_box); + edit_box_key((dword)&file_box); + + + switch (keyCode) + { + case 178: // стрелки + //dx = 0; + dy = -1; + break; + case 176: + dx = -1; + //dy = 0; + break; + case 179: + dx = 1; + //dy = 0; + break; + case 177: + //dx = 0; + dy = 1; + break; + /* + case 183: + if (sel_y < row_count-(ny - scroll_y)) // page down + dy = ny - scroll_y; + else + dy = row_count-(ny - scroll_y) - sel_y; + dx = 0; + redraw = 1; + break; + case 184: + if (sel_y > ny - scroll_y) // page up + dy= - (ny - scroll_y); + else + dy = - (ny - scroll_y) + sel_y; + dx = 0; + redraw = 1; + break; + */ + case 180: //home + dx = -sel_x + 1; + dy = 0; + draw_grid(); //draw_window(); + break; + case 181: //end + dx = col_count - (nx - scroll_x) - 1 - sel_x; + dy = 0; + draw_grid(); //draw_window(); + break; + case 27: // escape + cancel_edit(); + break; + case 182: // delete + { + int i,j,n0,n1,k0,k1; + n0 = min(sel_x, sel_end_x); + n1 = max(sel_x, sel_end_x); + k0 = min(sel_y, sel_end_y); + k1 = max(sel_y, sel_end_y); + + for (i = n0; i <= n1; i++) + for (j = k0; j <= k1; j++) + { + if (cells[i][j]) + { + freemem(cells[i][j]); + cells[i][j] = NULL; + } + } + calculate_values(); + draw_grid(); + break; + } + case 0x0D: // enter + if (is_edit) + { + stop_edit(); + draw_window(); + } + break; + //case 0x08: // backspace + /*if (is_edit || fn_edit) + { + if (strlen(edit_text) != 0) + edit_text[strlen(edit_text) - 1] = '\0'; + KEdit(); + } + else if (cells[sel_x][sel_y]) + { + start_edit(sel_x, sel_y); + } + */ + // break; + case 22: // contol-v + { + if (ctrl) + { + //rtlDebugOutString("control-v!"); + int i, j, x0, y0; + x0 = min(sel_x, sel_end_x); + y0 = min(sel_y, sel_end_y); + int delta_x = x0 - buf_old_x; + int delta_y = y0 - buf_old_y; + + for (i = 0; i < buf_col; i++) + for (j = 0; j < buf_row; j++) + { + if (i + x0 >= col_count || j + y0 >= row_count) + continue; + if (cells[i + x0][j + y0]) + freemem(cells[i + x0][j + y0]); + if (buffer[i][j]) + { + cf_x0 = buf_old_x; cf_y0 = buf_old_y; + cf_x1 = buf_old_x + buf_col; + cf_y1 = buf_old_y + buf_row; + cells[i + x0][j + y0] = change_formula(buffer[i][j], delta_x, delta_y); + //cells[i + x0][j + y0] = (char*)allocmem(strlen(buffer[i][j])); + //strcpy(cells[i + x0][j + y0], buffer[i][j]); + } + else + cells[i + x0][j + y0] = NULL; + } + + calculate_values(); + draw_window(); + break; + } + } + case 24: // control-x + case 03: // control-c + { + if (ctrl) + { + //rtlDebugOutString("control-c!"); + int i, j, x0, y0; + + freeBuffer(); + + buf_col = abs(sel_end_x - sel_x) + 1; + buf_row = abs(sel_end_y - sel_y) + 1; + x0 = min(sel_x, sel_end_x); + y0 = min(sel_y, sel_end_y); + buf_old_x = x0; + buf_old_y = y0; + + //sprintf(debuf, "%U %U %U %U", buf_col, buf_row, x0, y0); + //rtlDebugOutString(debuf); + + buffer = (char***)allocmem(buf_col * sizeof(char**)); + for (i = 0; i < buf_col; i++) + { + buffer[i] = (char**)allocmem(buf_row * sizeof(char*)); + for (j = 0; j < buf_row; j++) + { + if (cells[i + x0][j + y0]) + { + if (keyCode == 03) // ctrl-c + { + buffer[i][j] = (char*)allocmem(strlen(cells[i + x0][j + y0])); + strcpy(buffer[i][j], cells[i + x0][j + y0]); + } + else + { + buffer[i][j] = cells[i + x0][j + y0]; + cells[i + x0][j + y0] = NULL; + } + } + else + buffer[i][j] = NULL; + } + } + if (keyCode == 24) + calculate_values(); + draw_window(); + break; + } + } + case 06: // control-f + { + display_formulas = !display_formulas; + draw_grid(); //draw_window(); + break; + } + default: + + if (!is_edit && !(file_box.flags & ed_focus)) + { + start_edit(sel_x, sel_y); + if (keyCode == 8) + { + cell_box.pos = strlen(edit_text); + } + else + { + __asm + { + mov ah, keyCode + } + edit_box_key((dword)&cell_box); + } + } + if (is_edit) + edit_box_draw((dword)&cell_box); + /* + if (strlen(edit_text)<256) + { + edit_text[strlen(edit_text)]=keyCode; + edit_text[strlen(edit_text) + 1]='\0'; + KEdit(); + } + */ + break; + } + if (dx != 0) + { + if (shift) + { + sel_end_x += dx; + if (sel_end_x <= 1) + sel_end_x = 1; + else if (sel_end_x >= col_count) + sel_end_x = col_count - 1; + // sprintf(debuf,"sel end x change. sel end %U %U",sel_end_x,sel_end_y); + // rtlDebugOutString(debuf); + sel_moved = sel_end_move = 1; + //stop_edit(); + //draw_grid(); + } + else + { + } + } + if (dy != 0) + { + if (shift) + { + sel_end_y += dy; + if (sel_end_y <= 1) + sel_end_y = 1; + else if (sel_end_y >= row_count) + sel_end_y = row_count - 1; + // sprintf(debuf,"sel end y change. sel end %U %U",sel_end_x,sel_end_y); + // rtlDebugOutString(debuf); + sel_moved = sel_end_move = 1; + //stop_edit(); + //draw_grid(); + } + else + { + } + } + /* + if (sel_end_x < sel_x) + { + Dword tmp = sel_end_x; sel_end_x = sel_x; sel_x = tmp; + } + if (sel_end_y < sel_y) + { + Dword tmp = sel_end_y; sel_end_y = sel_y; sel_y = tmp; + } + */ + if ((dx || dy)) + { + if (!shift) + { + move_sel(sel_x + dx, sel_y + dy); + } + else + { + sel_moved = 0; + stop_edit(); + draw_grid(); + } + } +} + + +void process_button() +{ + Dword mouse_btn, ckeys, shift, ctrl; + int mouse_x, mouse_y, i, p, dx = 0, dy = 0; + int redraw = 0; + + Dword button; + kos_GetButtonID(button); + + /* + sprintf(debuf, "button %U", button); + rtlDebugOutString(debuf); + //*/ + + switch (button) + { + case 1: + kos_ExitApp(); + + case SCROLL_LEFT_BUTTON: + //rtlDebugOutString("scroll left btn"); + stop_edit(); + scroll_x--; + if (scroll_x <= 0) + scroll_x = 1; + sel_moved = 0; + /*if (sel_x > nx - 1) + { + nx - 1; + sel_end_x = sel_x; + }*/ + draw_window(); + return; + + case SCROLL_RIGHT_BUTTON: + //rtlDebugOutString("scroll right btn"); + stop_edit(); + scroll_x++; + if (scroll_x >= col_count - 1) + scroll_x = col_count - 1; + sel_moved = 0;/* + if (sel_x < scroll_x) + { + sel_x = scroll_x; + sel_end_x = sel_x; + }*/ + draw_window(); + return; + + case SCROLL_WIDTH: + { + //rtlDebugOutString("scroll width btn"); + stop_edit(); + kos_GetMouseState(mouse_btn, mouse_x, mouse_y); + mouse_x -= 5; + mouse_y -= kos_GetSkinHeight(); + + // всего: wi - SCROLL_BAR_WIDTH - 2 * 14 + + int tmp_w = (nx - scroll_x) * (wi - SCROLL_BAR_WIDTH - 3 * 14) / (col_count + 1); + if (tmp_w < 16) + tmp_w = 16; + scroll_x = (mouse_x - 14 - tmp_w / 2) * (col_count + 1) / (wi - SCROLL_BAR_WIDTH - 3 * 14) + 1; + if (scroll_x <= 0) + scroll_x = 1; + else if (scroll_x >= col_count - 1) + scroll_x = col_count - 1; + sel_moved = 0; + draw_window(); + return; + } + + case SCROLL_UP_BUTTON: + stop_edit(); + scroll_y--; + if (scroll_y <= 0) + scroll_y = 1; + sel_moved = 0; + //draw_window(); + draw_grid(); + /* + if (sel_y > ny - 1) + { + sel_y = ny - 1; + sel_end_y = sel_y; + }*/ + return; + + case SCROLL_DOWN_BUTTON: + stop_edit(); + scroll_y++; + if (scroll_y >= row_count - 1) + scroll_y = row_count - 1; + sel_moved = 0;/* + if (sel_y < scroll_y) + { + sel_y = scroll_y; + sel_end_y = sel_y; + }*/ + draw_grid(); + return; + + case SCROLL_HEIGHT: + { + stop_edit(); + kos_GetMouseState(mouse_btn, mouse_x, mouse_y); + mouse_x -= 5; + mouse_y -= kos_GetSkinHeight(); + int tmp_h = (ny - scroll_y) * (he - SCROLL_BAR_HEIGHT - 2 * 14) / row_count; + if (tmp_h < 16) + tmp_h = 16; + scroll_y = (mouse_y - 2 * 14) * (row_count + 1) / (he - SCROLL_BAR_HEIGHT - 3 * 14) + 1; + if (scroll_y <= 0) + scroll_y = 1; + else if (scroll_y >= row_count - 1) + scroll_y = row_count - 1; + sel_moved = 0; + draw_grid(); + return; + } + + case NEW_BUTTON: // clear the table + reinit(); + draw_window(); + break; + + case FILENAME_BUTTON: + sel_moved = 1; + stop_edit(); + fn_edit = 1; + strcpy(edit_text, fname); + draw_window(); + break; + + case SAVE_BUTTON: + stop_edit(); + kos_DrawBar(320, panel_y, wi - 320 - 10, 10, 0xe4dfe1); + if (SaveFile(fname)) + kos_WriteTextToWindow(320, panel_y, 0, 0x000000, (char*)msg_save, strlen(msg_save)); + break; + + case LOAD_BUTTON: + stop_edit(); + int r = LoadFile(fname); + kos_DrawBar(320, panel_y, wi - 320 - 10, 10, 0xe4dfe1); + if (r > 0) + { + calculate_values(); + sel_moved = 0; + draw_window(); + kos_WriteTextToWindow(320, panel_y,0,0x000000,(char*)msg_load, strlen(msg_load)); + } + else if (r == -1) + kos_WriteTextToWindow(320, panel_y,0,0x000000,(char*)er_file_not_found,strlen(er_file_not_found)); + else if (r == -2) + kos_WriteTextToWindow(320, panel_y,0,0x000000,(char*)er_format,strlen(er_format)); + break; + } + /* + if (button >= COL_BUTTON && button < ROW_BUTTON) + { + scroll_x = button - COL_BUTTON; + fn_edit = is_edit = 0; + draw_window(); + //sprintf(debuf, "col %U", scroll_x); + //rtlDebugOutString(debuf); + } + else if (button >= ROW_BUTTON && button < COL_HEAD_BUTTON) + { + scroll_y = button - ROW_BUTTON; + fn_edit = is_edit = 0; + draw_window(); + //sprintf(debuf, "row %U", scroll_y); + //rtlDebugOutString(debuf); + } + */ + if (button >= COL_HEAD_BUTTON && button < ROW_HEAD_BUTTON) + { + sel_end_x = sel_x = button - COL_HEAD_BUTTON; + sel_y = 1; + sel_end_y = row_count - 1; + stop_edit(); + draw_window(); + return; + } + else if (button >= ROW_HEAD_BUTTON && button < CELL_BUTTON) + { + sel_end_y = sel_y = button - ROW_HEAD_BUTTON; + sel_x = 1; + sel_end_x = col_count - 1; + stop_edit(); + draw_window(); + return; + } + +} + +void kos_Main() +{ + kos_InitHeap(); + load_edit_box(); + + init(); + draw_window(); + for (;;) + { + switch (kos_WaitForEvent(10)) // да, плохо. потом нужно будет просто ловить события мыши. + { + case 0: + process_mouse(); + break; + case 1: + draw_window(); + break; + case 2: + process_key(); + break; + case 3: + process_button(); + break; + //case 6: + // draw_window(); + // break; + } + } +} + diff --git a/programs/other/table/hello.dsp b/programs/other/table/hello.dsp new file mode 100644 index 0000000000..bb7d180c40 --- /dev/null +++ b/programs/other/table/hello.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="hello" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=hello - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "hello.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "hello.mak" CFG="hello - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "hello - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /Zp1 /W3 /vd0 /O2 /YX /FD /c +# SUBTRACT CPP /X +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 /nologo /base:"0" /entry:"crtStartUp" /subsystem:windows /machine:I386 /nodefaultlib /align:16 +# SUBTRACT LINK32 /pdb:none +# Begin Custom Build +InputPath=.\Release\hello.exe +SOURCE="$(InputPath)" + +"hello.kex" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + pe2kos Release\hello.exe hello.kex + +# End Custom Build +# Begin Target + +# Name "hello - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\calc.cpp +# End Source File +# Begin Source File + +SOURCE=.\func.cpp +# End Source File +# Begin Source File + +SOURCE=.\hello.cpp +# End Source File +# Begin Source File + +SOURCE=.\KosFile.cpp +# End Source File +# Begin Source File + +SOURCE=.\kosSyst.cpp +# End Source File +# Begin Source File + +SOURCE=.\math2.cpp +# End Source File +# Begin Source File + +SOURCE=.\mcsmemm.cpp +# End Source File +# Begin Source File + +SOURCE=.\parser.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\calc.h +# End Source File +# Begin Source File + +SOURCE=.\func.h +# End Source File +# Begin Source File + +SOURCE=.\KosFile.h +# End Source File +# Begin Source File + +SOURCE=.\kosSyst.h +# End Source File +# Begin Source File + +SOURCE=.\MCSMEMM.H +# End Source File +# Begin Source File + +SOURCE=.\parser.h +# End Source File +# Begin Source File + +SOURCE=.\use_library.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/programs/other/table/hello.dsw b/programs/other/table/hello.dsw new file mode 100644 index 0000000000..07550fec4b --- /dev/null +++ b/programs/other/table/hello.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "hello"=".\hello.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/programs/other/table/kosSyst.cpp b/programs/other/table/kosSyst.cpp new file mode 100644 index 0000000000..659677419b --- /dev/null +++ b/programs/other/table/kosSyst.cpp @@ -0,0 +1,894 @@ +#include "kosSyst.h" +#include "func.h" +#include + +#define atexitBufferSize 32 + + +char pureCallMessage[] = "PURE function call!"; + +char *kosExePath = NULL; + +// +void (__cdecl *atExitList[atexitBufferSize])(); +int atExitFnNum = 0; +// +int __cdecl atexit( void (__cdecl *func )( void )) +{ + // + if ( atExitFnNum < atexitBufferSize ) + { + // + atExitList[atExitFnNum++] = func; + return 0; + } + else + { + return 1; + } +} + + +// +Dword RandomSeed = 1; +// +void rtlSrand( Dword seed ) +{ + RandomSeed = seed; +} +// +Dword rtlRand( void ) +{ + //маска 0x80000776 + + Dword dwi, i; + + for ( i = 0; i < 32; i++ ) + { + + dwi = RandomSeed & 0x80000776; + + __asm{ + mov eax, dwi + mov edx, eax + bswap eax + xor eax, edx + xor al, ah + setpo al + movzx eax, al + mov dwi, eax + } + + RandomSeed = ( RandomSeed << 1 ) | ( dwi & 1 ); + } + + return RandomSeed; +} + + +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ) +{ + __asm{ + mov edi, dst + mov eax, dst + mov esi, src + mov ecx, bytesCount + rep movsb + } +} + +// +void memset( Byte *dst, Byte filler, Dword count ) +{ + // + __asm{ + mov edi, dst + mov al, filler + mov ecx, count + rep stosb + } +} + + +// +Dword rtlInterlockedExchange( Dword *target, Dword value ) +{ +// Dword result; + + // + __asm{ + mov eax, value + mov ebx, target + xchg eax, [ebx] +// mov result, eax + } + // +// return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// копирование строки +// + +char * __cdecl strcpy( char *target, const char *source ) +{ + char *result = target; + + while( target[0] = source[0] ) + { + target++; + source++; + } + + return result; +} + + +////////////////////////////////////////////////////////////////////// +// +// реверсивный поиск символа +// + +char * __cdecl strrchr( const char * string, int c ) +{ + char *cPtr; + + // + for ( cPtr = (char *)string + strlen( string ); cPtr >= string; cPtr-- ) + { + // + if ( *cPtr == c ) return cPtr; + } + // + return NULL; +} + + +////////////////////////////////////////////////////////////////////// +// +// определение длины строки +// + +int __cdecl strlen( const char *line ) +{ + int i; + + for( i=0; line[i] != 0; i++ ); + return i; +} + + + +////////////////////////////////////////////////////////////////////// +// +// перевод шестнадцатиричного числа в символ +// + +unsigned int num2hex( unsigned int num ) +{ + if( num < 10 ) + return num + '0'; + return num - 10 + 'A'; +} + + +////////////////////////////////////////////////////////////////////// +// +// вывод строки на печать. barsuk добавил %f + +//#define PREC 2 +//#define HALF 0.499 +#define PREC 6 +#define HALF 0.4999999 + +double double_tab[]={1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, +1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30}; + + +// + +Dword dectab[] = { 1000000000, 100000000, 10000000, 1000000, 100000, + 10000, 1000, 100, 10, 0 }; + +// +void sprintf( char *Str, char* Format, ... ) +{ + int i, fmtlinesize, j, k, flag; + Dword head, tail; + char c; + va_list arglist; + // + va_start(arglist, Format); + + // + fmtlinesize = strlen( Format ); + // + if( fmtlinesize == 0 ) return; + + // + for( i = 0, j = 0; i < fmtlinesize; i++ ) + { + // + c = Format[i]; + // + if( c != '%' ) + { + Str[j++] = c; + continue; + } + // + i++; + // + if( i >= fmtlinesize ) break; + + // + flag = 0; + // + c = Format[i]; + // + switch( c ) + { + // + case '%': + Str[j++] = c; + break; + // вывод строки + case 'S': + Byte* str; + str = va_arg(arglist, Byte*); + for( k = 0; ( c = str[k] ) != 0; k++ ) + { + Str[j++] = c; + } + break; + // вывод байта + case 'B': + k = va_arg(arglist, int) & 0xFF; + Str[j++] = num2hex( ( k >> 4 ) & 0xF ); + Str[j++] = num2hex( k & 0xF ); + break; + // вывод символа + case 'C': + Str[j++] = va_arg(arglist, int) & 0xFF; + break; + // вывод двойного слова в шестнадцатиричном виде + case 'X': + Dword val; + val = va_arg(arglist, Dword); + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( val >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + break; + // вывод двойного слова в десятичном виде + case 'U': + head = va_arg(arglist, Dword); + tail = 0; + for( k = 0; dectab[k] != 0; k++ ) + { + tail = head % dectab[k]; + head /= dectab[k]; + c = head + '0'; + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + // + head = tail; + } + // + c = head + '0'; + Str[j++] = c; + break; + // вещественное число в формате 7.2 + case 'f': + case 'F': + case 'g': + case 'G': + { + double val, w; + int p; + val = va_arg(arglist, double); + if (val < 0.0) + { + Str[j++] = '-'; + val = -val; + } + for (k = 0; k < 30; k++) + if (val < double_tab[k]) + break; + + if (val < 1.0) + { + Str[j++] = '0'; + } + + for (p = 1; p < k + 1; p++) + { + int d = (int)di(val / double_tab[k - p] - HALF) % 10; + Str[j++] = '0' + d; + val -= d * double_tab[k - p]; + } + Str[j++] = '.'; + w = 0.1; + for (p = 0; p < PREC - 1; p++) + { + val-=floor(val); + Str[j++] = '0' + di(val / w - HALF) % 10; + w /= 10.0; + } + } + break; + + // вывод 64-битного слова в шестнадцатиричном виде + case 'Q': + unsigned int low_dword, high_dword; + low_dword = va_arg(arglist, unsigned int); + high_dword = va_arg(arglist, unsigned int); + for( k = 7; k >= 0; k-- ) + { + // + c = num2hex ( ( ( high_dword + 1) >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + for( k=7; k >= 0; k-- ) + { + // + c = num2hex ( ( low_dword >> (k * 4) ) & 0xF ); + // + if( c == '0' ) + { + if( flag ) Str[j++] = c; + } + else + { + flag++; + Str[j++] = c; + } + } + // + if( flag == 0 ) Str[j++] = '0'; + // + break; + // + default: + break; + } + } + // + Str[j] = 0; +} + + +// функция -1 завершения процесса +void kos_ExitApp() +{ + int i; + + // + for ( i = atExitFnNum - 1; i >= 0; i-- ) + { + // + atExitList[i](); + } + // + __asm{ + mov eax, -1 + int 0x40 + } +} + + +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, + Dword mainAreaColour, + Byte headerType, + Dword headerColour, + Dword borderColour + ) +{ + Dword arg1, arg2, arg3, arg4; + + // + arg1 = ( x << 16 ) + sizeX; + arg2 = ( y << 16 ) + sizeY; + arg3 = ( mainAreaType << 24 ) | mainAreaColour; + arg4 = ( headerType << 24 ) | headerColour; + // + __asm{ + mov eax, 0 + mov ebx, arg1 + mov ecx, arg2 + mov edx, arg3 + mov esi, arg4 + mov edi, borderColour + int 0x40 + } +} + + +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ) +{ + // + __asm{ + mov eax, 1 + mov ebx, x + mov ecx, y + mov edx, colour + int 0x40 + } +} + + +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ) +{ + Dword result; + + // + __asm{ + mov eax, 2 + int 0x40 + mov result, eax + } + // + keyCode = result >> 8; + // + return ( result & 0xFF ) == 0; +} + + +// функция 3 получить время +Dword kos_GetSystemClock() +{ +// Dword result; + + // + __asm{ + mov eax, 3 + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 4 +void kos_WriteTextToWindow( + Word x, + Word y, + Byte fontType, + Dword textColour, + char *textPtr, + Dword textLen + ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | y; + arg2 = ( fontType << 24 ) | textColour; + // + __asm{ + mov eax, 4 + mov ebx, arg1 + mov ecx, arg2 + mov edx, textPtr + mov esi, textLen + int 0x40 + } +} + + +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ) +{ + // + __asm{ + mov eax, 5 + mov ebx, value + int 0x40 + } +} + + +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ) +{ + Dword arg1, arg2; + + // + arg1 = ( sizeX << 16 ) | sizeY; + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 7 + mov ebx, imagePtr + mov ecx, arg1 + mov edx, arg2 + int 0x40 + } +} + + + +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + mov eax, 8 + mov ebx, arg1 + mov ecx, arg2 + mov edx, buttonID + mov esi, colour + int 0x40 + } +} + + +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID ) +{ +// Dword result; + + // + __asm{ + mov eax, 9 + mov ebx, targetPtr + mov ecx, processID + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 10 +Dword kos_WaitForEvent() +{ +// Dword result; + + __asm{ + mov eax, 10 + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 11 +Dword kos_CheckForEvent() +{ +// Dword result; + + __asm{ + mov eax, 11 + int 0x40 +// mov result, eax + } + +// return result; +} + + +// функция 12 +void kos_WindowRedrawStatus( Dword status ) +{ + __asm{ + mov eax, 12 + mov ebx, status + int 0x40 + } +} + + +// функция 13 нарисовать полосу +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ) +{ + Dword arg1, arg2; + + // + arg1 = ( x << 16 ) | sizeX; + arg2 = ( y << 16 ) | sizeY; + // + __asm{ + mov eax, 13 + mov ebx, arg1 + mov ecx, arg2 + mov edx, colour + int 0x40 + } +} + + +// функция 17 +bool kos_GetButtonID( Dword &buttonID ) +{ + Dword result; + + // + __asm{ + mov eax, 17 + int 0x40 + mov result, eax + } + // + buttonID = result >> 8; + // + return (result & 0xFF) == 0; +} + + +// функция 23 +Dword kos_WaitForEvent( Dword timeOut ) +{ +// Dword result; + + __asm{ + mov eax, 23 + mov ebx, timeOut + int 0x40 +// mov result, eax + } + +// return result; +} + + +// получение информации о состоянии "мыши" функция 37 +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ) +{ + Dword mB; + Word curX; + Word curY; + sProcessInfo sPI; + + // + __asm{ + mov eax, 37 + mov ebx, 0 + int 0x40 + mov curY, ax + shr eax, 16 + mov curX, ax + mov eax, 37 + mov ebx, 2 + int 0x40 + mov mB, eax + } + // + kos_ProcessInfo( &sPI ); + // + buttons = mB; + cursorX = curX - sPI.processInfo.x_start; + cursorY = curY - sPI.processInfo.y_start; +} + + +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ) +{ + // + __asm{ + mov eax, 40 + mov ebx, mask + int 0x40 + } +} + + +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase, + bool valueIsPointer + ) +{ + Dword arg1, arg2; + + // + arg1 = ( valueIsPointer ? 1 : 0 ) | + ( ((Byte)nBase) << 8 ) | + ( ( digitsNum & 0x1F ) << 16 ); + arg2 = ( x << 16 ) | y; + // + __asm{ + mov eax, 47 + mov ebx, arg1 + mov ecx, value + mov edx, arg2 + mov esi, colour + int 0x40 + } +} + + +// функция 70 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ) +{ +// Dword result; + + // + __asm{ + mov eax, 70 + mov ebx, fileInfo + int 0x40 +// mov result, eax + } + // +// return result; +} + + +// функция 63 вывод символя в окно отладки +void kos_DebugOutChar( char ccc ) +{ + // + __asm{ + mov eax, 63 + mov ebx, 1 + mov cl, ccc + int 0x40 + } +} + + +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ) +{ + // + __asm{ + mov eax, 66 + mov ebx, 1 + mov ecx, mode + int 0x40 + } +} + + +// вывод строки в окно отладки +void rtlDebugOutString( char *str ) +{ + // + for ( ; str[0] != 0; str++ ) + { + kos_DebugOutChar( str[0] ); + } + // + kos_DebugOutChar( 13 ); + kos_DebugOutChar( 10 ); +} + + +// функция 64 изменение количества памяти, выделенной для программы +bool kos_ApplicationMemoryResize( Dword targetSize ) +{ + Dword result; + + // + __asm{ + mov eax, 64 + mov ebx, 1 + mov ecx, targetSize + int 0x40 + mov result, eax + } + // + return result == 0; +} + + +// функция 67 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ) +{ + // + __asm{ + mov eax, 67 + mov ebx, x + mov ecx, y + mov edx, sizeX + mov esi, sizeY + int 0x40 + } +} + +void kos_InitHeap() +{ + __asm{ + mov eax, 68 + mov ebx, 11 + int 0x40 + } +} + + + +// вызов абстрактного метода +int __cdecl _purecall() +{ + rtlDebugOutString( pureCallMessage ); + kos_ExitApp(); + return 0; +} + + +// вызов статических инициализаторов +// заодно инициализация генератора случайных чисел +//#pragma section(".CRT$XCA",long,read,write) +//#pragma section(".CRT$XCZ",long,read,write) +#pragma data_seg(".CRT$XCA") +#pragma data_seg(".CRT$XCZ") +typedef void (__cdecl *_PVFV)(void); +__declspec(allocate(".CRT$XCA")) _PVFV __xc_a[1] = { NULL }; +__declspec(allocate(".CRT$XCZ")) _PVFV __xc_z[1] = { NULL }; +// +#pragma comment(linker, "/merge:.CRT=.rdata") +// +void crtStartUp() +{ + // вызываем инициализаторы по списку, NULL'ы игнорируем + for ( _PVFV *pbegin = __xc_a; pbegin < __xc_z; pbegin++ ) + { + // + if ( *pbegin != NULL ) + (**pbegin)(); + } + // инициализируем генератор случайных чисел + rtlSrand( kos_GetSystemClock() ); + // путь к файлу процесса + kosExePath = *((char **)0x20); + // вызов главной функции приложения + kos_Main(); + // выход + kos_ExitApp(); +} + + diff --git a/programs/other/table/kosSyst.h b/programs/other/table/kosSyst.h new file mode 100644 index 0000000000..c9ad210586 --- /dev/null +++ b/programs/other/table/kosSyst.h @@ -0,0 +1,214 @@ + +#pragma once + +typedef unsigned __int32 Dword; +typedef unsigned __int16 Word; +typedef unsigned __int8 Byte; +//typedef unsigned __int32 size_t; + +#define NULL 0 + +#define MAX_PATH 256 + +#define FO_READ 0 +#define FO_WRITE 2 + +#define EM_WINDOW_REDRAW 1 +#define EM_KEY_PRESS 2 +#define EM_BUTTON_CLICK 4 +#define EM_APP_CLOSE 8 +#define EM_DRAW_BACKGROUND 16 +#define EM_MOUSE_EVENT 32 +#define EM_IPC 64 +#define EM_NETWORK 256 + +#define KM_CHARS 0 +#define KM_SCANS 1 + +#define WRS_BEGIN 1 +#define WRS_END 2 + +#define PROCESS_ID_SELF -1 + +#define abs(a) (a<0?0-a:a) + +extern "C" double acos(double x); +extern "C" double asin(double x); +extern "C" double floor(double x); +extern "C" double round(double x); +#pragma function(acos,asin) +#if _MSC_VER > 1200 +#pragma function(floor) +#endif + + +struct kosFileInfo +{ + Dword rwMode; + Dword OffsetLow; + Dword OffsetHigh; + Dword dataCount; + Byte *bufferPtr; + char fileURL[MAX_PATH]; +}; + + +struct RGB +{ + Byte b; + Byte g; + Byte r; + // + RGB() {}; + // + RGB( Dword value ) + { + r = (Byte)(value >> 16); + g = (Byte)(value >> 8); + b = (Byte)value; + }; + // + bool operator != ( RGB &another ) + { + return this->b != another.b || this->g != another.g || this->r != another.r; + }; + // + bool operator == ( RGB &another ) + { + return this->b == another.b && this->g == another.g && this->r == another.r; + }; +}; + + +union sProcessInfo +{ + Byte rawData[1024]; + struct + { + Dword cpu_usage; + Word window_stack_position; + Word window_stack_value; + Word reserved1; + char process_name[12]; + Dword memory_start; + Dword used_memory; + Dword PID; + Dword x_start; + Dword y_start; + Dword x_size; + Dword y_size; + Word slot_state; + } processInfo; +}; + +// +extern char *kosExePath; + +// +void crtStartUp(); +// +int __cdecl _purecall(); +// +int __cdecl atexit( void (__cdecl *func )( void )); +// +void rtlSrand( Dword seed ); +Dword rtlRand( void ); +// +char * __cdecl strcpy( char *target, const char *source ); +int __cdecl strlen( const char *line ); +char * __cdecl strrchr( const char * string, int c ); + +#if _MSC_VER < 1400 +extern "C" void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ); +extern "C" void memset( Byte *dst, Byte filler, Dword count ); +//#pragma intrinsic(memcpy,memset) +#else +void * __cdecl memcpy( void *dst, const void *src, size_t bytesCount ); +void memset( Byte *dst, Byte filler, Dword count ); +#endif + +void sprintf( char *Str, char* Format, ... ); +// +Dword rtlInterlockedExchange( Dword *target, Dword value ); +// функция -1 завершения процесса +void kos_ExitApp(); +// функция 0 +void kos_DefineAndDrawWindow( + Word x, Word y, + Word sizeX, Word sizeY, + Byte mainAreaType, Dword mainAreaColour, + Byte headerType, Dword headerColour, + Dword borderColour + ); +// функция 1 поставить точку +void kos_PutPixel( Dword x, Dword y, Dword colour ); +// функция 2 получить код нажатой клавиши +bool kos_GetKey( Byte &keyCode ); +// функция 3 получить время +Dword kos_GetSystemClock(); +// функция 4 +void kos_WriteTextToWindow( + Word x, Word y, + Byte fontType, + Dword textColour, + char *textPtr, + Dword textLen + ); +// функция 7 нарисовать изображение +void kos_PutImage( RGB * imagePtr, Word sizeX, Word sizeY, Word x, Word y ); +// функция 8 определить кнопку +void kos_DefineButton( Word x, Word y, Word sizeX, Word sizeY, Dword buttonID, Dword colour ); +// функция 5 пауза, в сотых долях секунды +void kos_Pause( Dword value ); +// функция 9 - информация о процессе +Dword kos_ProcessInfo( sProcessInfo *targetPtr, Dword processID = PROCESS_ID_SELF ); +// функция 10 +Dword kos_WaitForEvent(); +// функция 11 +Dword kos_CheckForEvent(); +// функция 12 +void kos_WindowRedrawStatus( Dword status ); +// функция 13 нарисовать полосу +void kos_DrawBar( Word x, Word y, Word sizeX, Word sizeY, Dword colour ); +// функция 17 +bool kos_GetButtonID( Dword &buttonID ); +// функция 23 +Dword kos_WaitForEvent( Dword timeOut ); +// +enum eNumberBase +{ + nbDecimal = 0, + nbHex, + nbBin +}; +// получение информации о состоянии "мыши" функция 37 +void kos_GetMouseState( Dword & buttons, int & cursorX, int & cursorY ); +// функция 40 установить маску событий +void kos_SetMaskForEvents( Dword mask ); +// функция 47 вывести в окно приложения число +void kos_DisplayNumberToWindow( + Dword value, + Dword digitsNum, + Word x, + Word y, + Dword colour, + eNumberBase nBase = nbDecimal, + bool valueIsPointer = false + ); +// функция 58 доступ к файловой системе +Dword kos_FileSystemAccess( kosFileInfo *fileInfo ); +// функция 63 +void kos_DebugOutChar( char ccc ); +// +void rtlDebugOutString( char *str ); +// функция 64 изменить параметры окна, параметр == -1 не меняется +void kos_ChangeWindow( Dword x, Dword y, Dword sizeX, Dword sizeY ); +// функция 67 изменение количества памяти, выделенной для программы +bool kos_ApplicationMemoryResize( Dword targetSize ); +// функция 66 режим получения данных от клавиатуры +void kos_SetKeyboardDataMode( Dword mode ); + +void kos_InitHeap(); + +// +void kos_Main(); diff --git a/programs/other/table/math2.cpp b/programs/other/table/math2.cpp new file mode 100644 index 0000000000..6b348ed777 --- /dev/null +++ b/programs/other/table/math2.cpp @@ -0,0 +1,83 @@ +#include +#include "kosSyst.h" +extern "C" int _fltused = 0; +double acos(double x) +{ + __asm { + fld qword ptr [esp+4] + fld1 + fadd st, st(1) + fld1 + fsub st, st(2) + fmulp st(1), st + fsqrt + fxch st(1) + fpatan + } +} +double asin(double x) +{ + __asm { + fld qword ptr [esp+4] + fld1 + fadd st, st(1) + fld1 + fsub st, st(2) + fmulp st(1), st + fsqrt + fpatan + ret + } +} +#if _MSC_VER <= 1200 +extern "C" double _ftol(double x) +{ + __asm { + fld qword ptr [esp+4] + push 1F3Fh + fstcw word ptr [esp+2] + fldcw word ptr [esp] + frndint + fldcw word ptr [esp+2] + add esp, 4 + } +} +#endif +double ceil(double x) +{ + __asm { + fld qword ptr [esp+4] + push 1B3Fh + fstcw word ptr [esp+2] + fldcw word ptr [esp] + frndint + fldcw word ptr [esp+2] + add esp, 4 + } +} + +double floor(double x) +{ + __asm { + fld qword ptr [esp+4] + push 173Fh + fstcw word ptr [esp+2] + fldcw word ptr [esp] + frndint + fldcw word ptr [esp+2] + add esp, 4 + } +} + +double round(double x) +{ + __asm { + fld qword ptr [esp+4] + push 133Fh + fstcw word ptr [esp+2] + fldcw word ptr [esp] + frndint + fldcw word ptr [esp+2] + add esp, 4 + } +} diff --git a/programs/other/table/mcsmemm.cpp b/programs/other/table/mcsmemm.cpp new file mode 100644 index 0000000000..8073a0e703 --- /dev/null +++ b/programs/other/table/mcsmemm.cpp @@ -0,0 +1,354 @@ +// memman.cpp : Defines the entry point for the console application. +// + +#include "kosSyst.h" +#include "mcsmemm.h" + + +void * __cdecl operator new ( size_t count, size_t element_size ) +{ + return allocmem( (Dword)(count * element_size) ); +} + +void * __cdecl operator new [] ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void * __cdecl operator new ( size_t amount ) +{ + return allocmem( (Dword)amount ); +} + +void __cdecl operator delete ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + +void __cdecl operator delete [] ( void *pointer ) +{ + if ( pointer != NULL ) freemem( pointer ); +} + +Byte *allocmem( Dword reqsize ) +{ + __asm + { + mov eax, 68 + mov ebx, 12 + mov ecx, reqsize + int 0x40 + } + +} + +Dword freemem( void *vaddress ) +{ + __asm + { + mov eax, 68 + mov ebx, 13 + mov ecx, vaddress + int 0x40 + } + +} +/* + +// +Dword mmMutex = FALSE; +MemBlock *rootfree = NULL; +MemBlock *rootuser = NULL; +bool mmInitialized = false; +Byte *mmHeapTop = NULL; + + +// +Byte * AllocMemFromSystem( Dword reqSize ) +{ + Byte *result; + sProcessInfo pInfo; + + // + if ( mmInitialized ) + { + result = mmHeapTop; + } + else + { + // + kos_ProcessInfo( &pInfo ); + // + result = (Byte *)(pInfo.processInfo.used_memory + 1); + // + mmInitialized = true; + } + // + if ( ! kos_ApplicationMemoryResize( ((Dword)result) + reqSize ) ) + { + result = NULL; + } + // + mmHeapTop = result + reqSize; + // + return result; +} + + +// +Byte *allocmem( Dword reqsize ) +{ + MemBlock *BlockForCheck; + MemBlock *LastKnownGood; + Dword tail; + Byte *address; + + //подровняем размер + if( ( tail = reqsize % SIZE_ALIGN ) != 0 ) + { + reqsize += SIZE_ALIGN - tail; + } + + LastKnownGood = NULL; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + //ищем подходящий свободный блок + if( rootfree != NULL ) + { + for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next ) + { + if ( BlockForCheck->Size >= reqsize ) + { + //нашли + if ( LastKnownGood != NULL ) + { + if ( LastKnownGood->Size >= BlockForCheck->Size ) + LastKnownGood = BlockForCheck; + } + else + LastKnownGood = BlockForCheck; + if ( LastKnownGood->Size == reqsize ) + break; + } + if ( BlockForCheck->Next == NULL ) + break; + } + } + + if ( LastKnownGood != NULL ) + { + //проверим найденный блок на возможность деления + tail = LastKnownGood->Size - reqsize; + if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) ) + { + //будем разбивать + BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail ); + BlockForCheck->Size = reqsize; + //вставим занятый блок в начало списка занатых блоков + if( rootuser != NULL ) + { + BlockForCheck->Next = rootuser; + rootuser->Previous = BlockForCheck; + BlockForCheck->Previous = NULL; + rootuser = BlockForCheck; + } + else + { + rootuser = BlockForCheck; + BlockForCheck->Next = NULL; + BlockForCheck->Previous = NULL; + } + + //изменим размер оставшейся части + LastKnownGood->Size = tail - sizeof(MemBlock); + address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + else + { + //перемести блок из очереди свободных в начало очереди занятых + //сначала выкинем его из очереди свободных + if ( LastKnownGood->Previous != NULL ) + { + LastKnownGood->Previous->Next = LastKnownGood->Next; + } + else + { + //блок стоит в начале очереди + rootfree = LastKnownGood->Next; + } + if( LastKnownGood->Next != NULL ) + { + LastKnownGood->Next->Previous = LastKnownGood->Previous; + } + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + // + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + else + { + //надо получить ещё кусочек памяти + LastKnownGood = (MemBlock *)AllocMemFromSystem( reqsize + sizeof(MemBlock) ); + // + if( LastKnownGood != NULL ) + { + LastKnownGood->Size = reqsize; + //теперь вставим его в очередь занятых + if( rootuser != NULL ) + { + LastKnownGood->Next = rootuser; + rootuser->Previous = LastKnownGood; + LastKnownGood->Previous = NULL; + rootuser = LastKnownGood; + } + else + { + rootuser = LastKnownGood; + LastKnownGood->Next = NULL; + LastKnownGood->Previous = NULL; + } + address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return address; + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + // + rtlDebugOutString( "allocmem failed." ); + kos_ExitApp(); + // + return NULL; +} + +// +Dword freemem( void *vaddress ) +{ + Dword result; + + Byte *checknext, *address = (Byte *)vaddress; + + // ждём освобождения мьютекса + while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) + { + // + kos_Pause( 1 ); + } + + MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) ); + + result = released->Size; + + //убираем блок из списка занятых + if ( released->Previous != NULL ) + { + released->Previous->Next = released->Next; + } + else + { + rootuser = released->Next; + } + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //закинем теперь этот блок в список свободных + released->Next = rootfree; + released->Previous = NULL; + rootfree = released; + if ( released->Next != NULL ) + { + released->Next->Previous = released; + } + + //теперь поищем смежные свободные блоки + checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) ); + // + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released ) + { + //собираем блоки вместе + //сначала выкинем из очереди свободных + released->Previous->Next = released->Next; + if( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //теперь увеличим размер корневого блока + rootfree->Size += released->Size + sizeof(MemBlock); + break; + } + } + //если надо, поищем блоки перед текщим. + checknext = (Byte *)(rootfree); + // + if ( released == NULL ) + { + for ( released = rootfree->Next; released != NULL; released = released->Next ) + { + if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) ) + { + //собираем блоки вместе + //увеличим размер блока + released->Size += rootfree->Size + sizeof(MemBlock); + //теперь выкинем из очереди свободных + released->Previous->Next = released->Next; + if ( released->Next != NULL ) + { + released->Next->Previous = released->Previous; + } + //и закинем его в начало очереди вместо присоединённого блока из корня списка + if ( rootfree->Next != NULL ) + { + rootfree->Next->Previous = released; + } + released->Next = rootfree->Next; + released->Previous = NULL; + rootfree = released; + break; + } + } + } + + // отпустим мьютекс + rtlInterlockedExchange( &mmMutex, FALSE ); + + return result; +} + +*/ \ No newline at end of file diff --git a/programs/other/table/mymath.h b/programs/other/table/mymath.h new file mode 100644 index 0000000000..6d911d875c --- /dev/null +++ b/programs/other/table/mymath.h @@ -0,0 +1,95 @@ +/* Rocket Forces + * Filename: mymath.h + * Version 0.1 + * Copyright (c) Serial 2007 + */ + + +extern "C" int _fltused = 0; + +#define M_PI 3.14159265358979323846 + +inline double sin(double x) +{ + __asm fld x + __asm fsin +} + +inline double cos(double x) +{ + __asm fld x + __asm fcos +} + +inline double sqrt(double x) +{ + __asm fld x + __asm fsqrt +} + +inline double acos(double x) +{ + __asm fld x + __asm fld st(0) + __asm fmul st,st(1) + __asm fld1 + __asm fsubrp st(1),st(0) + __asm fsqrt + __asm fxch st(1) + __asm fpatan +} + +inline double atan(double x) +{ + double res = acos(1 / sqrt(1 + x * x)); + if (x < 0) + { + res *= -1; + } + return res; +} + +inline int round_int(double x) +{ + int i; + static const float round_to_nearest = 0.5f; + __asm + { + fld x + fadd st, st(0) + fadd round_to_nearest + fistp i + sar i, 1 + } + return i; +} + +inline int floor_int(double x) +{ + int i; + static const float round_toward_m_i = -0.5f; + __asm + { + fld x + fadd st, st (0) + fadd round_toward_m_i + fistp i + sar i, 1 + } + return i; +} + +inline int ceil_int(double x) +{ + int i; + static const float round_toward_p_i = -0.5f; + __asm + { + fld x + fadd st, st (0) + fsubr round_toward_p_i + fistp i + sar i, 1 + } + return (-i); +} diff --git a/programs/other/table/parser.cpp b/programs/other/table/parser.cpp new file mode 100644 index 0000000000..4ea28ce854 --- /dev/null +++ b/programs/other/table/parser.cpp @@ -0,0 +1,925 @@ + + +#include "func.h" +#include "parser.h" +//#include +//#include +//#include + +// token types +#define DELIMITER 1 +#define VARIABLE 2 +#define NUMBER 3 +#define FUNCTION 4 +#define FINISHED 10 + +//#define allocmem(x) malloc(x) +//#define freemem(x) free(x) + +double epsilon = 1e-6; + +// structure for most parser functions + + char token[80]; + int token_type; + char *prog; + + int code; // error code + + +variable_callback *find_var; + +struct double_list +{ + double val; + int code; // код ошибки + double_list *next; +}; + +double tg(double d) +{ + double cosd = cos(d); + if (fabs(cosd) < epsilon) + { + serror(ERR_OVERFLOW); + return 0.0; + } + return sin(d) / cosd; +} + +double ctg(double d) +{ + double sind = sin(d); + if (fabs(sind) < epsilon) + { + serror(ERR_OVERFLOW); + return 0.0; + } + return cos(d) / sind; +} + +double exp(double x) +{ + __asm { + fld x + FLDL2E + FMUL + + FLD st(0) + + FLD1 + + FXCH + FPREM + F2XM1 + fadd + FSCALE + FSTP st(1) + } + +} + +double log(double x) +{ + //return 0.0; + if (x <= 0) + { + serror(ERR_OVERFLOW); + //return 0.0; + __asm { + fldz + } + } + __asm { + FLD1 + FLD x + FYL2X + FLDLN2 + FMUL + } +} + +double sqrt(double x) +{ + if (x < 0) + { + serror(ERR_BADPARAM); + __asm { + fldz + } + } + __asm { + fld x + fsqrt + } +} + +double atan(double x) +{ + serror(ERR_GENERAL); + return 0.0; // в лом +} + +double pow(double x, double y) +{ + return exp(y * log(x)); // +} + +double func_pi() +{ + return 3.14159265358979; +} + +double func_eps() +{ + return epsilon; +} + +double func_if(double_list *p) +{ + double_list *a, *b, *c; + a = p; + b = a->next; + if (!b) + { + serror(ERR_BADPARAM); + return 0.0; + } + c = b->next; + if (!c || c->next) + { + serror(ERR_BADPARAM); + return 0.0; + } + if (a->val != 0.0) + { + if (b->code) + code = b->code; + return b->val; + } + else + { + if (c->code) + code = c->code; + return c->val; + } +} + +double sum(double_list *p) +{ + double res = 0.0; + while (p) + { + res += p->val; + if (p->code) + code = p->code; + p = p->next; + } + return res; +} + +double func_min(double_list *p) +{ + if (!p) + serror(ERR_BADPARAM); + double res = p->val; + p = p->next; + while (p) + { + if (p->code) + code = p->code; + if (p->val < res) + res = p->val; + p = p->next; + } + return res; +} + +double func_max(double_list *p) +{ + if (!p) + serror(ERR_BADPARAM); + double res = p->val; + p = p->next; + while (p) + { + if (p->code) + code = p->code; + if (p->val > res) + res = p->val; + p = p->next; + } + return res; +} + +double avg(double_list *p) +{ + double res = 0.0; + int count = 0; + while (p) + { + if (p->code) + code = p->code; + res += p->val; + count++; + p = p->next; + } + return res / count; +} + +double func_isnull(char *str) +{ + if (code != 0) + return 0.0; + double tmp = find_var(str); + int c = code; + code = 0; + if (c != 0) + return 1.0; + return 0.0; +} + +const double HALF = 0.5; +double func_ceil(double val) // хотел round, а получился ceil... +{ + int x; + __asm fld val + __asm fld HALF // да, криворуко ^_^ + __asm fadd + __asm fistp x + __asm fild x +} + +double func_round(double val) +{ + int x; + __asm fld val + __asm fld epsilon + __asm fadd + __asm fistp x + __asm fild x +} + +const double ALMOST_HALF = 0.5 - epsilon; +double func_floor(double val) +{ + int x; + __asm fld val + __asm fld ALMOST_HALF + __asm fsub + __asm fistp x + __asm fild x +} + +double logic_xor(double a, double b) +{ + if (a == 0.0) + if (b == 0.0) + return 0.0; + else + return 1.0; + else + if (b == 0.0) + return 1.0; + else + return 0.0; +} + +double logic_and(double a, double b) +{ + if (a == 0.0) + return 0.0; + else + if (b == 0.0) + return 0.0; + else + return 1.0; +} + +double logic_or(double a, double b) +{ + if (a == 0.0) + if (b == 0.0) + return 0.0; + else + return 1.1; + else + return 1.0; +} + +double rand_seed; +double func_rand(double max) +{ + double q = (257.0 * rand_seed + 739.0); // числа от балды. надо вставить правильные. + rand_seed = q - 65536.0 * func_floor(q / 65536.0); // для хорошего распределения + return q - max * func_floor(q / max); // для модуля +} + +double func_case(double_list *p) +{ + if (!p || !p->next) + { + serror(ERR_BADPARAM); + return 0.0; + } + double x = p->val; + int count = (int)p->next->val; + int i, k; + + double_list *cur = p->next->next; + k = count; + for (i = 0; i < count; i++) + { + if (!cur) + { + serror(ERR_BADPARAM); + return 0.0; + } + if (fabs(x - cur->val) < epsilon) + { + if (k != count + 1) + { + serror(ERR_GENERAL); + return 0.0; + } + k = i; + } + cur = cur->next; + } + + for (i = 0; i < k; i++) + { + if (!cur) + { + serror(ERR_BADPARAM); + return 0.0; + } + cur = cur->next; + } + if (!cur) // проверки бип. достали бип. + { + serror(ERR_BADPARAM); + return 0.0; + } + if (cur->code) + code = cur->code; + return cur->val; +} + +#define INF_ARGS -1 +#define STR_ARG -2 + +// represents general mathematical function +typedef double(*matfunc0)(); +typedef double(*matfunc)(double); +typedef double(*matfunc2)(double,double); +typedef double(*matfunc3)(double,double,double); +typedef double(*matfunc_inf)(double_list*); +typedef double(*matfunc_str)(char*); + +// used to link function name to the function +typedef struct +{ + char name[10]; + int args; + void * f; +} func; + +// the list of functions +const int max_func = 29; +func functions[max_func] = +{ + "", 1, NULL, // не помню, с какой целью + "sin", 1, &sin, + "cos", 1, &cos, + "exp", 1, &exp, + "sqrt", 1, &sqrt, + "log", 1, &log, + "tg", 1, &tg, + "ctg", 1, &ctg, + "arcsin", 1, &asin, + "arccos", 1, &acos, + "arctg", 1, &atan, // не реализовано. возвращает ошибку ERR_GENERAL + "abs", 1, &fabs, + "pow", 2, &pow, + "if", INF_ARGS, &func_if, + "sum",INF_ARGS,&sum, + "isnull",STR_ARG,&func_isnull, // слегка ч/ж + "min",INF_ARGS,&func_min, + "max",INF_ARGS,&func_max, + "avg",INF_ARGS,&avg, + "ceil",1,&func_ceil, + "round",1,&func_round, + "floor",1,&func_floor, + "and",2,&logic_and, + "or",2,&logic_or, + "xor",2,&logic_xor, + "rand",1,&func_rand, + "case",INF_ARGS,&func_case, + "pi",0,&func_pi, + "eps",0,&func_eps +}; + +// all delimiters +#define MAXDELIM 17 +const char delim[MAXDELIM]="+-*^/%=;(),><#! "; // not bad words + + +int isdelim(char c) +{ + //return strchr(delim, c) != 0; + for (int i = 0; i < MAXDELIM; i++) + if (c == delim[i]) + return 1; + return 0; +} + +int isdigit(char c) +{ + return (c >= '0' && c <= '9'); +} + +int isalpha2(char c) +{ + return ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') || (c=='$')); +} + +int iswhite(char c) +{ + return (c==' ' || c=='\t'); +} + + +void serror(int acode) +{ + if (acode != 0) + code = acode; +} + +void set_exp(char *exp) +{ + prog = exp; +} + +int get_token() +{ + int tok; + char *temp; + (token_type) = 0; + tok = 0; + temp = (token); + + if (*(prog) == '\0') + { + *(token) = 0; + tok = FINISHED; + return ((token_type) = DELIMITER); + } + while (iswhite(*(prog))) ++(prog); + if (isdelim(*(prog))) + { + char t=*temp = *(prog); + (prog)++; + temp++; + if ((t == '>' || t == '<' || t == '!') && (*prog) && (*prog == '=')) + { + *temp = *(prog); + (prog)++; + temp++; + } + *temp = 0; + return ((token_type) = DELIMITER); + } + if (isdigit(*(prog))) + { + while (!isdelim(*(prog))) + *temp++=*(prog)++; + *temp = '\0'; + return ((token_type) = NUMBER); + } + if (isalpha2(*(prog))) + { + while (!isdelim(*(prog))) + *temp++=*(prog)++; + (token_type) = VARIABLE; + } + *temp = '\0'; + if ((token_type) == VARIABLE) + { + tok = look_up((token)); + if (tok) + (token_type) = FUNCTION; + } + return (token_type); +} + +double sign(double d) +{ + if (d > 0.0) + return 1.0; + if (d < 0.0) + return -1.0; + return 0.0; +} + +void putback() +{ + char *t; + t = (token); + for (;*t;t++) + (prog)--; +} + +int get_exp(double *hold) +{ + code = 0; + + get_token(); + if (!*(token)) + { + return 0; + } + level1( hold); + putback(); + return code==0; +} + +void level1(double *hold) +{ + char op[2]; + double h; + + level1_5( hold); + while (op[0] = *token, op[1] = (*(token+1)) ? *(token + 1) : 0, + *op == '<' || *op == '>' || *op == '=' || *op == '#' || *op == '!') + { + get_token(); + level1_5( &h); + logic(op, hold, &h); + } +} + +void level1_5(double *hold) +{ + char op; + + op = 0; + if (((token_type) == DELIMITER) && *(token) == '!') + { + op = *(token); + get_token(); + } + level2( hold); + + if (op) + { + if (*hold == 0.0) + *hold = 1.0; + else + *hold = 0.0; + } +} + +void level2(double *hold) +{ + char op; + double h; + + level3( hold); + while ((op=*(token)) == '+' || op == '-') + { + get_token(); + level3( &h); + arith(op, hold, &h); + } +} + +void level3(double *hold) +{ + char op; + double h; + + level4( hold); + while ((op=*(token)) == '*' || op == '/' || op == '%') + { + get_token(); + level4( &h); + arith( op, hold, &h); + } +} + +void level4(double *hold) +{ + double h; + level5( hold); + + if (*(token) == '^') + { + get_token(); + level5( &h); + arith( '^', hold, &h); + } +} + +void level5(double *hold) +{ + char op; + + op = 0; + if (((token_type) == DELIMITER) && *(token) == '+' || *(token) == '-') + { + op = *(token); + get_token(); + } + level6( hold); + + if (op) + unary(op, hold); +} + +void level6(double *hold) +{ + if ((*(token) == '(') && ((token_type) == DELIMITER)) + { + get_token(); + level1( hold); + if (*(token) != ')') + serror( ERR_NOBRACKET); + get_token(); + } + else + primitive( hold); +} + +void calc_function(double *hold) +{ + double_list *args = NULL, *last = NULL, *t; + double d; + int i,argc=0,save_code; + + save_code = code; + code = 0; + i = look_up(token); + + if (i == 0) + serror(ERR_BADFUNCTION); // error + + get_token(); + if (*(token) != '(') + serror(ERR_NOBRACKET); // error + //get_token(); + if (functions[i].args == STR_ARG) + { + get_token(); + d = ((matfunc_str)(functions[i].f))(token); + *hold = d; + get_token(); + if (save_code) + code = save_code; + return; + } + + //last = args = (double_list*)malloc(sizeof(double_list)); + //args->next = NULL; + //level1(&args->val); + //get_token(); + argc=0; + do + { + get_token(); + if (*token == ')') + break; + t = (double_list*)allocmem(sizeof(double_list)); + code = 0; + level1(&t->val); + t->code = code; + t->next = NULL; + if (last) + last->next = t; + else + args = t; + last = t; + argc++; + } while (*token == ','); + + code = save_code; + + if (argc != functions[i].args && functions[i].args >= 0) + { + serror(ERR_BADPARAM); + } + else + { + switch (functions[i].args) + { + case 0: + d = ((matfunc0)(functions[i].f))(); + break; + case 1: + d = ((matfunc)(functions[i].f))(args->val); + break; + case 2: + d = ((matfunc2)(functions[i].f))(args->val,args->next->val); + break; + case 3: + d = ((matfunc3)(functions[i].f))(args->val,args->next->val,args->next->next->val); + break; + case INF_ARGS: + d = ((matfunc_inf)(functions[i].f))(args); + break; + } + } + + t = args; + while (t) + { + args = t->next; + freemem(t); + t = args; + } + + *hold = d; +// else +// serror( ERR_OVERFLOW); + +} + +void primitive(double *hold) +{ + switch (token_type) + { + case VARIABLE: + *hold = find_var(token); + get_token(); + return; + case NUMBER: + // + *hold = atof((token)); + //if (sscanf(token, "%lf", hold) != 1) + *hold = convert(token); + if (convert_error == ERROR) + serror( ERR_BADNUMER); + get_token(); + return; + case FUNCTION: + calc_function( hold); + if (*token != ')') + serror(ERR_NOBRACKET); + get_token(); + return; + default: // error + return; + } +} + +void arith(char op, double *r, double *h) +{ + double t; + switch(op) + { + case '-': + *r = *r - *h; + break; + case '+': + *r = *r + *h; + break; + case '*': + *r = *r * *h; + break; + case '/': + if (fabs(*h) < epsilon) + serror( ERR_OVERFLOW); + else + *r = (*r) / (*h); + break; + case '%': + if (fabs(*h) < epsilon) + serror( ERR_OVERFLOW); + else + { + t = func_floor ((*r) / (*h)); + *r = *r - (t * (*h)); + } + break; + case '^': + *r = pow(*r, *h); + break; + } +} + +void logic(char *op, double *r, double *h) +{ + double t; + switch (*op) + { + case '<': + if (*(op+1) && *(op+1) == '=') + t = *r <= *h + epsilon ? 1.0 : 0.0; + else + t = *r < *h - epsilon? 1.0 : 0.0; + break; + case '>': + if (*(op+1) && *(op+1) == '=') + t = *r >= *h - epsilon ? 1.0 : 0.0; + else + t = *r > *h + epsilon ? 1.0 : 0.0; + break; + case '=': + t = fabs(*r - *h) <= epsilon ? 1.0 : 0.0; + break; + case '#': + t = fabs(*r - *h) > epsilon ? 1.0 : 0.0; + break; + case '!': + if (*(op+1) && *(op+1) == '=') + t = fabs(*r - *h) > epsilon ? 1.0 : 0.0; + else + serror(ERR_GENERAL); + break; + } + *r = t; +} + + +void unary(char op, double *r) +{ + if (op == '-') + *r = -(*r); +} + +bool strcmp(char *s1, char *s2) +{ + int i; + + if (s1 == NULL) + if (s2 == NULL) + return 0; + else + return 1; + else + if (s2 == NULL) + return 1; + + for (i = 0;;i++) + { + if (s1[i] == '\0') + if (s2[i] == '\0') + return 0; + else + return 1; + else + if (s2[i] == '\0') + return 1; + else + { + if (s1[i] != s2[i]) + return 1; + } + } + return 0; +} + + +bool strncmp(char *s1, char *s2, int n) +{ + int i; + + if (s1 == NULL) + if (s2 == NULL) + return 0; + else + return 1; + else + if (s2 == NULL) + return 1; + + for (i = 0;i