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

📄 utilobj.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//UtilObj.cpp, (c)2000, 2001, 2002, 2003, 2004, 2005 by R. Lackner
//
//    This file is part of RLPlot.
//
//    RLPlot is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    RLPlot is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with RLPlot; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
#include "rlplot.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <fcntl.h>				//file open flags
#include <sys/stat.h>			//I/O flags
#ifdef _WINDOWS
	#include <io.h>					//for read/write
#else
	#define O_BINARY 0x0
	#include <unistd.h>
#endif

Default defs;

static LineDEF ETbgnn = {0.0, 1.0, 0x00e8e8e8L, 0L};
static LineDEF ETbgna = {0.0, 1.0, 0x00ffffffL, 0L};
static LineDEF ETbgmn = {0.0, 1.0, 0x00cbcbcbL, 0L};
static LineDEF ETbgma = {0.0, 1.0, 0x00ffffc0L, 0L};
static LineDEF yLine = {0.0, 1.0, 0x0000ffffL, 0L};
extern const LineDEF BlackLine = {0.0, 1.0, 0x00000000L, 0L};
extern const LineDEF GrayLine = {0.0, 1.0, 0x00c0c0c0L, 0L};

static FillDEF ETfbnn = {FILL_NONE, 0x00e8e8e8L, 1.0, NULL, 0x00ffffffL};
static FillDEF ETfbna = {FILL_NONE, 0x00ffffffL, 1.0, NULL, 0x00ffffffL};
static FillDEF ETfbmn = {FILL_NONE, 0x00e8cbcbL, 1.0, NULL, 0x00ffffffL};
static FillDEF ETfbma = {FILL_NONE, 0x00ffffc0L, 1.0, NULL, 0x00ffffffL};
static FillDEF yFill = {FILL_NONE, 0x0000ffffL, 1.0, NULL, 0x0000ffffL};

extern char TmpTxt[500];
extern unsigned long cObsW;				//count objects written
extern GraphObj *CurrGO, *TrackGO;		//Selected Graphic Objects
extern dragHandle *CurrHandle;
extern UndoObj Undo;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Process fields with user input text
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EditText *CurrText = 0L, *scroll_et = 0;
int scroll_dist = 0;

EditText::EditText(void *par, char *msg, int r, int c)
{
	loc.x = loc.y = crb.x = rb.x = crb.y = rb.y = 0;	Value = 0.0;
	row = r;	col = c;	disp = 0L;		text = 0L;
	CursorPos = length = Align = 0;		type = ET_UNKNOWN;		TextCol=0x00000000L;
	bgLine = &ETbgnn;					bgFill = &ETfbnn;		parent = par;
	if(msg && msg[0]) {
		SetText(msg);		FindType();
		}
	else {
		Align = TXA_VCENTER | TXA_HRIGHT;
		type = ET_UNKNOWN;
		}
	m1 = m2 = -1;						//cursor positions track marks
	ftext = 0L;							//store formula text result here
}

EditText::~EditText()
{
	HideCopyMark();
	if(CurrText == this)	CurrText = 0L;
	if(text) free(text);	text = 0L;
	if(ftext) free(ftext);	ftext = 0L;
}

bool
EditText::AddChar(int ci, anyOutput *Out, void *data_obj)
{
	char byte1, byte2, c, *tmp;
	POINT MyPos;
	int i;

	if(ci < 254 && ci > 31) c = (char)ci;
	else if(ci == 27) {						//Esc
		m1 = m2 = -1;		Redraw(Out, true);		return true;
		}
	else return false;
	if(parent) {
		((DataObj*)parent)->Command(CMD_MRK_DIRTY, 0L, 0L);
		((DataObj*)parent)->Command(CMD_SAVEPOS, 0L, 0L);
		}
	Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
	bgLine = &ETbgna; bgFill = &ETfbna; TextCol = 0x00000000L;
	if(text)length = strlen(text);
	else length = 0;
	if(text) tmp = (char *)realloc(text, length+2);
	else tmp = (char *)calloc(2, sizeof(char));
	if(!tmp) return false;
	text = tmp;
	byte1 = byte2 = 0;
	//replace mark by character if mark exists
	if(hasMark()) {			//delete marked part of text
			if(m1 > m2) Swap(m1, m2);
			if(m2 >= (short int)strlen(text)) text[m1] = 0;
			else strcpy(text+m1, text+m2);
			CursorPos = m1;
			m1 = m2 = -1;
			}
	byte1 = text[CursorPos];
	i = CursorPos;
	text[i++] = c;
	while(byte1) {
		byte2 = byte1;			byte1 = text[i];			text[i++] = byte2;
		}
	text[i] = byte1;			CursorPos++;				type = ET_UNKNOWN;
	Redraw(Out, true);
	MyPos.y = loc.y;
	MyPos.x = Align & TXA_HRIGHT ? crb.x - 2 : loc.x + 2;
	if(Out)Out->TextCursor(text, MyPos, (POINT *) NULL, &CursorPos, 
		scroll_et == this ? scroll_dist : scroll_dist=0);
	if(parent && text) {
		((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' && ci != ')' ? this : 0L, 0L);
		}
	return true;
}

void
EditText::Update(int select, anyOutput *Out, POINT *MousePos)
{
	POINT MyPos;

	if(!parent && !disp) disp = Out;
	if(select != 1 && select != 5) m1 = m2 = -1;		//no mark;
	switch(select) {
		case 0:							//just redraw with current settings
			Redraw(Out, true);
			break;
		case 5:							//dialog control
			if(!text)Align = TXA_VCENTER | TXA_HLEFT;
		case 1:							//active spread sheet cell with cursor
			if((type & 0xff) == ET_FORMULA) Align = TXA_VCENTER | TXA_HLEFT;
			if(!text && !(text = (char *) calloc(10, sizeof(char))))return;
			if(CursorPos > (int)strlen(text)) CursorPos = (int)strlen(text);
			if(MousePos && (type & 0xff) == ET_TEXT && (text && text[0] == '\'' && (bgLine == &ETbgnn || bgLine == &ETbgmn))) {
				MousePos->x += 4;
				}
			bgLine = &ETbgna; bgFill = &ETfbna; TextCol = 0x00000000L;
			if(Out) {
				Redraw(Out, true);
				MyPos.y = loc.y;			MyPos.x = Align & TXA_HRIGHT ? crb.x - 4 : loc.x + 4;
				if(MousePos && MousePos->x && MousePos->y) {
					Out->TextCursor(text, MyPos, MousePos,&CursorPos, 
					scroll_et == this ? scroll_dist : scroll_dist=0);
					}
				else if(select ==1) Out->TextCursor(text, MyPos, NULL, &CursorPos, 
					scroll_et == this ? scroll_dist : (scroll_dist=0)+2);
				}
			break;
		case 2:							//inactive spreadsheet cell
			if((type & 0xff) == ET_FORMULA) Align = TXA_VCENTER | TXA_HRIGHT;
			if(crb.x > rb.x) {
				crb.x = rb.x;	crb.y = rb.y;
				}
			if(CurrText == this) FindType();
			bgLine = &ETbgnn; bgFill = &ETfbnn; TextCol = 0x00000000L;
			if(Out) Redraw(Out, true);
			break;
		case 10:						//value filled in by external app.
			if(text && text[0]) {
				type = ET_VALUE;
				Align = TXA_VCENTER | TXA_HRIGHT;
				sscanf(text, "%lf", &Value);
				}
			break;
		case 20:						//update value only
			FindType();
			break;
		}
}

bool
EditText::Redraw(anyOutput *Out, bool display)
{
	RECT rc;
	POINT MyPos;
	char *txt, tmptxt[80];
	int w, h, o_crbx;
	bool b_clip = false;
	anyOutput *opc;
	anyResult *fmres;

	if(!parent && disp) Out = disp;
	if(loc.x <1 || rb.x < 1 || loc.y <1 || rb.y <1) return false;
	o_crbx = crb.x;			crb.x = rb.x;				crb.y = rb.y;
	if (Out) {
		if (m1 >m2) Swap(m1, m2);
		if(((type & 0xff) == ET_UNKNOWN) && text && text[0]) FindType();
		Out->TxtSet.Align = Align;		Out->TxtSet.ColTxt = TextCol;
		Out->TxtSet.ColBg = bgLine->color;
		if(text && text[0]) {
			Out->oGetTextExtent(text, strlen(text), &w, &h);
			if(CurrText == this) {
				while((crb.x - loc.x) < (w+(h>>1))) crb.x += (rb.x - loc.x);
				if(o_crbx > loc.x && o_crbx > crb.x && o_crbx < 4000) crb.x = o_crbx;
				}
			else if((crb.x - loc.x) < (w+(h>>1))) b_clip = true;
			}
		Out->SetFill(bgFill);		Out->SetLine(bgLine);
		rc.left = loc.x;			rc.right = crb.x;
		rc.top = loc.y+1;			rc.bottom = crb.y-2;
		Out->oRectangle(loc.x, loc.y, crb.x-1, crb.y-1);
		if((!text || !text[0]) && (type & 0xff) == ET_VALUE){
			sprintf(tmptxt, "%g", Value);
			if(text = (char*)realloc(text, strlen(tmptxt)+2)) strcpy(text, tmptxt);
			CursorPos = 0;
			}
		if(ftext) free(ftext);		ftext = 0L;
		if(text && text[0]){
			if((type & 0xff) == ET_FORMULA && (bgLine == &ETbgnn || bgLine == &ETbgmn)) {
				Out->TxtSet.Align = TXA_HLEFT | TXA_VCENTER;
				if(type & ET_CIRCULAR) strcpy (tmptxt, "#CIRC.");
				else if((fmres = do_formula((DataObj*)parent, text+1)) && fmres->type != ET_ERROR) {
					b_clip = false;
					if(fmres->type == ET_VALUE) {
						sprintf(tmptxt, "%g", Value = fmres->value);
						fit_num_rect(Out, rb.x - loc.x, tmptxt);
						Out->TxtSet.Align = TXA_HRIGHT | TXA_VCENTER;
						}
					else if(fmres->type == ET_TEXT) {
						if(ftext) free (ftext);		ftext = 0L;
						if(fmres->text) ftext = strdup(fmres->text);
						if(fmres->text && strlen(fmres->text)<sizeof(tmptxt)) strcpy(tmptxt, fmres->text);
						else if(fmres->text) sprintf(tmptxt,"#SIZE");
						else tmptxt[0] = 0;
						}
					else strcpy(tmptxt, "#VALUE");
					}
				else sprintf(tmptxt, "#ERROR");
				txt = tmptxt;
				}
			else if((type &0xff) == ET_VALUE) {
				Out->oGetTextExtent(text, strlen(text), &w, &h);
				if(w >= (rb.x - loc.x-8) && (bgLine == &ETbgnn || bgLine == &ETbgmn)) {
					sprintf(tmptxt, "%g", Value);
					fit_num_rect(Out, rb.x - loc.x, tmptxt);
					txt = tmptxt;		b_clip = false;
					}
				else txt = text;
				}
			else if((type & 0xff) == ET_TEXT) {
				if(text && text[0] == '\'' && (bgLine == &ETbgnn || bgLine == &ETbgmn)) {
					txt = text+1;
					}
				else txt = text;
				}
			else txt = text;
			MyPos.y = (loc.y+rb.y)>>1;
			if(Out->TxtSet.Align & TXA_HRIGHT) {	//right justified text
				MyPos.x = crb.x-4;
				}
			else {									//left justified text
				MyPos.x = loc.x+4;
				}
			if(b_clip && (opc = NewBitmapClass(w+22, rb.y-loc.y, Out->hres, Out->vres))){
				if(scroll_et != this || parent) {
					scroll_et = this;	scroll_dist = 0;
					}
				opc->Erase(bgFill->color);
				opc->SetTextSpec(&Out->TxtSet);		opc->TxtSet.Align = TXA_HLEFT | TXA_VCENTER;
				opc->oTextOut(4,(rb.y-loc.y)>>1, txt, strlen(txt));
				if(!parent && CursorPos) {
					Out->oGetTextExtent(txt, CursorPos, &w, &h);
					while((scroll_dist + w)>(rc.right-rc.left-10)) scroll_dist -=10;
					while((scroll_dist + w)<12) scroll_dist +=10;
					if(scroll_dist >0) scroll_dist=0;
					}
				else scroll_dist=0;
				Out->CopyBitmap(rc.left+1, rc.top+1, opc, 1-scroll_dist, 1, 
					rc.right-rc.left-4, rc.bottom-rc.top-2, false);
				DelBitmapClass(opc);
				}
			else {
				if(display && hasMark() && mx1 > loc.x && mx2 < crb.x) {
					Out->SetFill(&yFill);		Out->SetLine(&yLine);
					Out->oRectangle(mx1, rc.top, mx2, rc.bottom);
					Out->SetFill(bgFill);		Out->SetLine(bgLine);
					}
				scroll_dist = 0;
				Out->oTextOut(MyPos.x, MyPos.y, txt, 0);
				}
			}
		if(display) {
			if(!(Out->UpdateRect(&rc, false))) return false;
			if(hasMark() && mx1 > loc.x && mx2 < rb.x) {
				rc.left = mx1;		rc.right = mx2;
				Out->UpdateRect(&rc, true);
				Out->MrkMode = MRK_NONE;
				}
			}
		return true;
	}
	return false;
}

void
EditText::Mark(anyOutput *Out, int mark)
{
	LineDEF *ol = bgLine;
	FillDEF *of = bgFill;
	DWORD ocol = TextCol;

	m1 = m2 = -1;
	if(!parent) return;
	switch (mark){
	case 0:				//normal not active
		bgLine = &ETbgnn; bgFill = &ETfbnn; TextCol = 0x00000000L;
		break;
	case 1:				//normal active
		bgLine = &ETbgna; bgFill = &ETfbna; TextCol = 0x00000000L;
		break;
	case 2:				//mark not active
		bgLine = &ETbgmn; bgFill = &ETfbmn; TextCol = 0x00c00000L;
		break;
	case 3:				//mark active
		bgLine = &ETbgma; bgFill = &ETfbma; TextCol = 0x00ff0000L;
		break;
		}
	if(!mark || mark == 2) {
		loc.y--;	rb.y++;
		}
	Redraw(Out, true);
	if(!mark || mark == 2) {
		loc.y++;	rb.y--;
		}
	bgLine = ol;	bgFill = of;	TextCol = ocol;
}

bool
EditText::Command(int cmd, anyOutput *Out, void *data_obj)
{
	int i, j, k, w, h;
	POINT MyPos;
	MouseEvent *mev;
	static RECT rMark;
	bool bRet;
	char *tag1, *tag2;
	unsigned char *pt;

	MyPos.y = loc.y;
	MyPos.x = Align & TXA_HRIGHT ? crb.x - 4 : loc.x + 4;
	if(!(text)) return false;
	if(!parent && disp) Out = disp;		//Dialog !
	switch(cmd) {
		case CMD_MRK_DIRTY:
			type = ET_UNKNOWN;
			if(CurrText == this) {
				Command(CMD_REDRAW, Out, data_obj);
				if(parent)((DataObj*)parent)->Command(CMD_MRK_DIRTY, Out, 0L);
				}
			else if(parent) {
				((DataObj*)parent)->Command(CMD_REDRAW, Out, 0L);
				((DataObj*)parent)->Command(CMD_MRK_DIRTY, Out, 0L);
				}
			else return Command(CMD_REDRAW, Out, data_obj);
			return true;
		case CMD_SETFONT:
			if (!text || !text[0]) return false;
			type = ET_TEXT;
			if(hasMark()) {
				Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
				switch (*((int*)data_obj)) {
				case FONT_HELVETICA:
					tag1 = (char*)"<face=helvetica>";		tag2 = (char*)"</face>";		break;
				case FONT_TIMES:
					tag1 = (char*)"<face=times>";			tag2 = (char*)"</face>";		break;
				case FONT_COURIER:
					tag1 = (char*)"<face=courier>";			tag2 = (char*)"</face>";		break;
				case FONT_GREEK:
					tag1 = (char*)"<face=greek>";			tag2 = (char*)"</face>";		break;
				default:
					return false;
					}
				if(m1 < m2) {
					j = m1;	k = m2;
					}
				else if(m1 > m2) {
					j = m2; k = m1;
					}
				else return false;			//empty mark !
				for(i = 0; i < j; i++) TmpTxt[i] = text[i];
				for(j = 0, w = i; tag1[j]; j++) TmpTxt[i++] = tag1[j];
				for( ; w < k; w++) TmpTxt[i++] = text[w];
				for(j = 0; tag2[j]; j++) TmpTxt[i++] = tag2[j];
				for( ; TmpTxt[i++] = text[w]; w++);
				m1 += (w = strlen(tag1));	m2 += w;	CursorPos += w;
				CleanTags(TmpTxt, &m1, &m2, &CursorPos);
				if(text = (char*)realloc(text, strlen(TmpTxt)+2)) strcpy(text, TmpTxt);
				Command(CMD_REDRAW, Out, 0L);
				return true;
				}
			return false;
		case CMD_SETSTYLE:
			if (!text || !text[0]) return false;
			type = ET_TEXT;
			if(hasMark()) {
				Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
				switch (*((int*)data_obj)) {
				case TXS_BOLD:
					tag1 = (char*)"<b>";		tag2 = (char*)"</b>";		break;
				case ~TXS_BOLD:
					tag1 = (char*)"</b>";		tag2 = (char*)"<b>";		break;
				case TXS_ITALIC:
					tag1 = (char*)"<i>";		tag2 = (char*)"</i>";		break;
				case ~TXS_ITALIC:
					tag1 = (char*)"</i>";		tag2 = (char*)"<i>";		break;
				case TXS_UNDERLINE:
					tag1 = (char*)"<u>";		tag2 = (char*)"</u>";		break;
				case ~TXS_UNDERLINE:
					tag1 = (char*)"</u>";		tag2 = (char*)"<u>";		break;
				case TXS_SUPER:
					tag1 = (char*)"<sup>";		tag2 = (char*)"</sup>";		break;
				case ~TXS_SUPER:
					tag1 = (char*)"</sup>";		tag2 = (char*)"<sup>";		break;
				case TXS_SUB:
					tag1 = (char*)"<sub>";		tag2 = (char*)"</sub>";		break;
				case ~TXS_SUB:
					tag1 = (char*)"</sub>";		tag2 = (char*)"<sub>";		break;
				default:
					return false;
					}
				if(m1 < m2) {
					j = m1;	k = m2;
					}
				else if(m1 > m2) {
					j = m2; k = m1;
					}
				else return false;			//empty mark !
				for(i = 0; i < j; i++) TmpTxt[i] = text[i];
				for(j = 0, w = i; tag1[j]; j++) TmpTxt[i++] = tag1[j];
				for( ; w < k; w++) TmpTxt[i++] = text[w];
				for(j = 0; tag2[j]; j++) TmpTxt[i++] = tag2[j];
				for( ; TmpTxt[i++] = text[w]; w++);
				m1 += (w = strlen(tag1));	m2 += w;	CursorPos += w;
				CleanTags(TmpTxt, &m1, &m2, &CursorPos);
				if(text = (char*)realloc(text, strlen(TmpTxt)+2)) strcpy(text, TmpTxt);
				Command(CMD_REDRAW, Out, 0L);
				return true;
				}
			return false;
		case CMD_ADDTXT:
			if(data_obj && *((char*)data_obj) && text && 
				(type == ET_TEXT || type == ET_UNKNOWN || type == ET_FORMULA)){
				if(hasMark()) Command(CMD_DELETE, 0L, 0L);
				else Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
				if(m1 > -1 && m2 > -1) Command(CMD_DELETE, 0L, 0L);
				for(i = 0; i < CursorPos && text[i]; i++) TmpTxt[i] = text[i];
				j = i + sprintf(TmpTxt+i, "%s", (char*)data_obj);
				if(text[i]) sprintf(TmpTxt+j, "%s", text+i);
				if(text = (char*)realloc(text, strlen(TmpTxt)+2)) strcpy(text, TmpTxt);
				CursorPos += strlen((char*)data_obj);
				Out->Focus();
				Update(1, Out, 0L);
				}
			return true;
		case CMD_BACKSP:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -