📄 utilobj.cpp
字号:
{"<b>", ~TXS_NORMAL, TXS_BOLD, -1, 0},
{"</b>", ~TXS_BOLD, TXS_NORMAL, -1, 0},
{"<u>", ~TXS_NORMAL, TXS_UNDERLINE, -1, 0},
{"</u>", ~TXS_UNDERLINE, TXS_NORMAL, -1, 0},
{"<sup>", ~TXS_NORMAL, TXS_SUPER, -1, 0},
{"</sup>", ~TXS_SUPER, TXS_NORMAL, -1, 0},
{"<sub>", ~TXS_NORMAL, TXS_SUB, -1, 0},
{"</sub>", ~TXS_SUB, TXS_NORMAL, -1, 0},
{"<face=helvetica>", 0, 0, FONT_HELVETICA, 0},
{"<face=times>", 0, 0, FONT_TIMES, 0},
{"<face=courier>", 0, 0, FONT_COURIER, 0},
{"<face=greek>", 0, 0, FONT_GREEK, 0},
{"</face>", 0, 0, -2, 0},
{"<bullet1>", 0, 0, -1, 1}, {"<bullet2>", 0, 0, -1, 2},
{"<bullet3>", 0, 0, -1, 3}, {"<bullet4>", 0, 0, -1, 4},
{"<bullet5>", 0, 0, -1, 5}, {"<bullet6>", 0, 0, -1, 6},
{"<bullet7>", 0, 0, -1, 7}, {"<bullet8>", 0, 0, -1, 8},
{"<bullet9>", 0, 0, -1, 9}, {"<bullet10>", 0, 0, -1, 10},
{"<white>", 0, 0, -1, 100}, {"<black>", 0, 0, -1, 101},
{"<red>", 0, 0, -1, 102}, {"<blue>", 0, 0, -1, 103},
{"<green>", 0, 0, -1, 104}, {"<yellow>", 0, 0, -1, 105},
{"<cyan>", 0, 0, -1, 106}, {"<purple>", 0, 0, -1, 107},
{"<smaller>", 0, 0, -1, 200}, {"<larger>", 0, 0, -1, 201},
{0L, 0, 0, 0, 0}};
static int font_buff[256];
static unsigned font_idx=0;
fmtText::fmtText(anyOutput *o, int x, int y, char *txt)
{
if(txt && txt[0]) src=strdup(txt);
else src=0L; split_text=0L; n_split=0;
pos.x = x; pos.y = y; if(src)Parse();
if(o) DrawText(o);
}
fmtText::~fmtText()
{
SetText(0L, 0L, 0L, 0L);
}
bool
fmtText::StyleAt(int idx, TextDEF *txt_def, int *style, int *font)
{
TextDEF td;
int i, j, n;
if(!src || !split_text || (idx > (int)strlen(src))) return false;
memcpy(&td, txt_def, sizeof(TextDEF));
for(i = j = 0; i < n_split; i++) {
if((n=split_text[i].tag) >= 0 && SetTextDef(&td, n)) j += strlen(tags[n].tag);
if(j > idx) break;
if(split_text[i].txt && split_text[i].txt[0]) j += strlen(split_text[i].txt);
if(j >= idx) break;
}
if(style) *style = td.Style; if(font) *font = td.Font;
return true;
}
int
fmtText::rightTag(char *txt, int cb)
{
int i, j;
for(i = 0; tags[i].tag; i++) {
for(j=1; tags[i].tag[j] && txt[cb+j]; j++) if(tags[i].tag[j] != txt[cb+j]) break;
if(!tags[i].tag[j]) return i;
}
return -1;
}
int
fmtText::leftTag(char *txt, int cb)
{
int i, j, k;
for(i = 0; tags[i].tag; i++) {
for(j = 0, k=strlen(tags[i].tag)-1; tags[i].tag[j] && k <=cb; j++, k--) {
if(tags[i].tag[j] != txt[cb-k]) break;
}
if(!tags[i].tag[j]) return i;
}
return -1;
}
void
fmtText::cur_right(int *pos)
{
int n;
if(!src || !pos || !src[*pos]) return;
if(src[*pos] == '<' && (n=rightTag(src, *pos)) >= 0) {
*pos += strlen(tags[n].tag);
cur_right(pos);
}
else (*pos)++;
}
void
fmtText::cur_left(int *pos)
{
int n;
if(!src || !pos || !(*pos)) return;
(*pos)--;
while (src[*pos] == '>' && (n=leftTag(src, *pos)) >= 0) {
*pos -= strlen(tags[n].tag);
}
}
bool
fmtText::oGetTextExtent(anyOutput *o, int *width, int *height, int cb)
{
TextDEF td1, td2;
int i, n, l, l1, w, w1, h, h1;
if(!o || !width || !height) return false;
if(!cb) cb = strlen(src);
if(!split_text) return o->oGetTextExtent(src, cb, width, height);
memcpy(&td1, &o->TxtSet, sizeof(TextDEF)); memcpy(&td2, &o->TxtSet, sizeof(TextDEF));
for(i = w = h = l = l1 = 0; i < n_split; i++){
if((n=split_text[i].tag) >= 0 && SetTextDef(&td2, n)) {
o->SetTextSpec(&td2);
l += strlen(tags[n].tag);
}
if(split_text[i].txt && split_text[i].txt[0]){
l1 = l; l += strlen(split_text[i].txt);
if (l1 >= cb) break;
o->oGetTextExtent(split_text[i].txt, l >= cb ? cb-l1 : 0, &w1, &h1);
w += w1; h = h1 > h ? h1 : h;
if (l >= cb) break;
}
if(tags[n].font == -1 && tags[n].op > 0 && tags[n].op < 100) {
w += o->un2ix(td2.fSize/2.0);
}
}
*width = w; *height = h; o->SetTextSpec(&td1);
return true;
}
void
fmtText::SetText(anyOutput *o, char *txt, int *px, int *py)
{
int i;
if(px) pos.x = *px; if(py) pos.y = *py;
if(src && txt && !strcmp(src, txt)) {
if(o) DrawText(o);
return;
}
if(src) free(src); src = 0L;
if(split_text) {
for(i = 0; i < n_split; i++) if(split_text[i].txt) free(split_text[i].txt);
free(split_text); split_text = 0L; n_split = 0;
}
if(txt && txt[0]) src=strdup(txt); if(src)Parse();
if(o) DrawText(o);
}
void
fmtText::DrawText(anyOutput *o)
{
if(!o || !src) return;
if(split_text)DrawFormatted(o);
else o->oTextOut(pos.x, pos.y, src, 0);
}
bool
fmtText::SetTextDef(TextDEF *td, int idx)
{
if(tags[idx].and_style != tags[idx].or_style) {
td->Style &= tags[idx].and_style; td->Style |= tags[idx].or_style;
}
else if(tags[idx].font >= 0) {
font_buff[font_idx & 0xff] = td->Font; font_idx++;
td->Font = tags[idx].font;
}
else if(tags[idx].font == -2) {
font_idx--; td->Font=font_buff[font_idx & 0xff];
}
else return false;
return true;
}
bool
fmtText::Parse()
{
int i, li, j, n;
char *tmp;
if(!src || !(tmp = strdup(src))) return false;
for(i = li = 0; src[i]; i++) {
if(src[i] == '<' && (n=rightTag(src, i))>=0) {
if(split_text) { //more tags in text
if(!(split_text = (fmt_txt_info *)realloc(split_text, (n_split+1)*sizeof(fmt_txt_info)))){
free(tmp); return false;
}
for(j = li; j < i; j++) tmp[j-li]= src[j]; tmp[j-li]=0;
split_text[n_split-1].txt = strdup(tmp);
i += strlen(tags[n].tag); split_text[n_split].tag = n;
split_text[n_split++].txt = 0L;
}
else { //first tag of text
if(!(split_text = (fmt_txt_info *)calloc(2, sizeof(fmt_txt_info)))){
free(tmp); return false;
}
for(j = 0; j < i; j++) tmp[j]= src[j]; tmp[j]=0;
split_text[0].tag = -1; split_text[0].txt = strdup(tmp);
i += strlen(tags[n].tag); split_text[1].tag = n;
n_split = 2;
}
li = i; i--;
}
}
if(split_text && n_split && li < i && src[li]) split_text[n_split-1].txt = strdup(src+li);
free(tmp);
return true;
}
void
fmtText::DrawBullet(anyOutput *o, int x, int y, int type, double size, DWORD lc, DWORD fc)
{
int is;
POINT pts[5];
static FillDEF fd = {0, 0x00ffffff, 1.0, 0L, 0x00ffffff};
static LineDEF ld = {defs.GetSize(SIZE_SYM_LINE), 1.0, 0x00000000L, 0x00000000};
switch (type) {
case 3: case 4:
is = o->un2ix(size/4.1);
break;
case 5: case 6: case 7: case 8:
is = o->un2ix(size/3.7);
break;
default:
is = o->un2ix(size/4.0);
break;
}
fd.color = fc; ld.color = lc;
switch(type) {
case 1:
o->SetLine(&ld); o->SetFill(&fd);
o->oCircle(x-is, y-is, x+is, y+is);
break;
case 2:
fd.color = ld.color;
o->SetLine(&ld); o->SetFill(&fd);
o->oCircle(x-is, y-is, x+is, y+is);
break;
case 3:
o->SetLine(&ld); o->SetFill(&fd);
o->oRectangle(x-is, y-is, x+is, y+is);
break;
case 4:
fd.color = ld.color;
o->SetLine(&ld); o->SetFill(&fd);
o->oRectangle(x-is, y-is, x+is, y+is);
break;
case 5: case 6: case 7: case 8: case 9: case 10:
if(type == 6 || type == 8 || type == 10) fd.color = ld.color;
pts[0].x = pts[3].x = pts[4].x = x - is;
pts[1].x = x; pts[2].x = x+is;
if(type == 5 || type == 6) {
pts[0].y = pts[2].y = pts[3].y = y+o->un2iy(size*0.19439);
pts[1].y = y-o->un2iy(size*0.38878);
}
else if(type == 9 || type ==10) {
pts[0].y = pts[2].y = pts[4].y = y;
pts[1].y = y - is; pts[3].y = y + is; pts[3].x = x;
}
else {
pts[0].y = pts[2].y = pts[3].y = y-o->un2iy(size*0.19439);
pts[1].y = y+o->un2iy(size*0.38878);
}
o->SetLine(&ld); o->SetFill(&fd);
o->oPolygon(pts, type < 9 ? 4 : 5);
break;
}
}
void
fmtText::DrawFormatted(anyOutput *o)
{
int i, n, x, y, x1, y1, w, h;
TextDEF td1, td2;
double si, csi, fx, fy;
if(!o || !split_text) return;
memcpy(&td1, &o->TxtSet, sizeof(TextDEF)); memcpy(&td2, &o->TxtSet, sizeof(TextDEF));
si = sin(td1.RotBL *0.01745329252); csi = cos(td1.RotBL *0.01745329252);
fx = pos.x; fy = pos.y;
oGetTextExtent(o, &w, &h, 0);
if(td2.Align & TXA_HRIGHT) {
fx -= w*csi; fy += w*si;
}
else if(td2.Align & TXA_HCENTER){
fx -= (w>>1)*csi; fy += (w>>1)*si;
}
x = iround(fx); y = iround(fy);
td2.Align &= ~(TXA_HRIGHT | TXA_HCENTER); o->SetTextSpec(&td2);
for(i = 0; i < n_split; i++) if(split_text[i].txt) {
if((n=split_text[i].tag) >= 0 && SetTextDef(&td2, n)) o->SetTextSpec(&td2);
else if(n >= 0 && tags[n].op) {
x1 = x + iround(o->un2fix(td2.fSize*0.25)*csi);
y1 = y - iround(o->un2fiy(td2.fSize*0.25)*si);
if((td2.Align & TXA_VTOP) == TXA_VTOP){
y1 += iround(o->un2fiy(td2.fSize*0.5)*csi);
x1 += iround(o->un2fix(td2.fSize*0.5)*si);
}
if((td2.Align & TXA_VCENTER) == TXA_VCENTER){
y1 -= iround(o->un2fiy(td2.fSize*0.5)*csi);
x1 -= iround(o->un2fix(td2.fSize*0.5)*si);
}
if((td2.Align & TXA_VBOTTOM) == TXA_VBOTTOM){
y1 -= iround(o->un2fiy(td2.fSize)*csi);
x1 -= iround(o->un2fix(td2.fSize)*si);
}
switch (tags[n].op) {
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10:
DrawBullet(o, x1, y1, tags[n].op, td2.fSize, td2.ColTxt, 0x00ffffff);
w = o->un2ix(td2.fSize/2.0);
x = iround(fx += (w*csi)); y = iround(fy -= (w*si));
break;
case 100: td2.ColTxt = 0x00ffffffL; break;
case 101: td2.ColTxt = 0x00000000L; break;
case 102: td2.ColTxt = 0x000000ffL; break;
case 103: td2.ColTxt = 0x00ff0000L; break;
case 104: td2.ColTxt = 0x0000ff00L; break;
case 105: td2.ColTxt = 0x0000ffffL; break;
case 106: td2.ColTxt = 0x00ffff00L; break;
case 107: td2.ColTxt = 0x00ff00ffL; break;
case 200: td2.fSize *= 0.81; td2.iSize = 0; break;
case 201: td2.fSize /= 0.81; td2.iSize = 0; break;
}
o->SetTextSpec(&td2);
}
if(split_text[i].txt){
o->oTextOut(x, y, split_text[i].txt, 0);
o->oGetTextExtent(split_text[i].txt, 0, &w, &h);
x = iround(fx += (w*csi)); y = iround(fy -= (w*si));
}
}
o->SetTextSpec(&td1);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// the basic data object
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DataObj::DataObj()
{
cRows = cCols = 0;
etRows = 0L;
}
DataObj::~DataObj()
{
FlushData();
}
bool
DataObj::Init(int nR, int nC)
{
int i, j;
if(etRows)FlushData();
if(!(etRows = (EditText ***)calloc (cRows = nR, sizeof(EditText **)))) return false;
for(i = 0, cCols = nC; i < cRows; i++) {
if(!(etRows[i] = (EditText **)calloc(cCols, sizeof(EditText *)))) {
FlushData(); return false;
}
if(etRows[i]) for(j = 0; j < cCols; j++) {
etRows[i][j] = new EditText(this, 0L, i, j);
}
}
return true;
}
bool
DataObj::SetValue(int row, int col, double val)
{
if(row < 0 || row >= cRows || col < 0 || col >= cCols) return false;
if(etRows[row][col]) return etRows[row][col]->SetValue(val);
return false;
}
bool
DataObj::SetText(int row, int col, char *txt)
{
if(row < 0 || row >= cRows || col < 0 || col >= cCols) return false;
if(etRows[row][col]) return etRows[row][col]->SetText(txt);
return false;
}
bool
DataObj::GetValue(int row, int col, double *v)
{
if(row < 0 || row >= cRows || col < 0 || col >= cCols) return false;
if(etRows[row][col]) return etRows[row][col]->GetValue(v);
return false;
}
bool
DataObj::GetText(int row, int col, char *txt, int len)
{
if(row < 0 || row >= cRows || col < 0 || col >= cCols) return false;
if(txt && etRows[row][col]) return etRows[row][col]->GetText(txt, len);
return false;
}
char **
DataObj::GetTextPtr(int row, int col)
{
if(row < 0 || row >= cRows || col < 0 || col >= cCols) return 0L;
if(etRows[row][col]) return &etRows[row][col]->text;
return 0L;
}
bool
DataObj::GetResult(anyResult *r, int row, int col, bool use_last)
{
if(row < 0 || row >= cRows || col < 0 || col >= cCols) return false;
if(etRows[row][col]) return etRows[row][col]->GetResult(r, use_last);
return false;
}
bool
DataObj::GetSize(int *width, int *height)
{
if(width)*width = cCols; if(height)*height = cRows;
return true;
}
void
DataObj::FlushData()
{
int i, j;
if(etRows){
for(i = 0; i < cRows; i++) if(etRows[i]) {
for (j = 0; j< cCols; j++) if(etRows[i][j]) delete etRows[i][j];
free(etRows[i]);
}
free(etRows);
}
etRows = 0L;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Store Data Object as strings: less memory required than with DataObj
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
StrData::StrData(DataObj *par, RECT *rc)
{
int r1, c1, r2, c2, w, h;
char **tx;
pw = ph = 0; str_data = 0L;
drc.left = drc.right = drc.top = drc.bottom = 0;
if(!(src = par)) return;
src->GetSize(&pw, & ph);
if(rc) {
if(0>(h = (rc->bottom - rc->top)) || 0>(w = (rc->right - rc->left))) return;
if(!(str_data = (char***)calloc(h+1, sizeof(char**))))return;
drc.left = rc->left; drc.right = rc->right;
drc.top = rc->top; drc.bottom = rc->bottom;
for (r1 = 0, r2 = drc.top; r1 <= h; r1++, r2++) {
if(!(str_data[r1] = (char**)malloc((w+1) * sizeof(char*)))) break;
for(c1 = 0, c2= drc.left; c1 <= w; c1++, c2++) {
tx = src->GetTextPtr(r2, c2);
str_data[r1][c1] = tx && *tx && *tx[0] ? strdup(*tx) : 0L;
}
}
}
else {
if(!(str_data = (char***)calloc(ph, sizeof(char**))))return;
for (r1 = 0; r1 < ph; r1++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -