⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utilobj.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	{"<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 + -