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

📄 textdiagram.cpp

📁 TabBars的开源源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	// left
	DrawLine(diagram, CPoint(rect.left, rect.top), CPoint(rect.left, rect.bottom));

	// top
	DrawLine(diagram, CPoint(rect.left, rect.top), CPoint(rect.right, rect.top));

	// bottom
	DrawLine(diagram, CPoint(rect.left, rect.bottom), CPoint(rect.right, rect.bottom));

	// corners
	SetChar(diagram, rect.left, rect.top, SPACE);
	SetChar(diagram, rect.right, rect.top, SPACE);
	SetChar(diagram, rect.right, rect.bottom, SPACE);
	SetChar(diagram, rect.left, rect.bottom, SPACE);

	// text
	int nLen = rect.GetTextLen(), nX = rect.left + 1, nY = rect.top + 1;
	LPCTSTR szText = rect.GetText();

	for (int nChar = 0; nChar < nLen && nY < rect.bottom; nChar++)
	{
		char c = szText[nChar];
#ifdef _VER_CHINESE
		// new line?
		if (c == _T('\r'))
		{
			nX = rect.left + 1;
			nY++;
			nChar++; // jump '\n'
		}
		else if ( 
			(((c & 0x80) != 0) && ((nX + 1) >= rect.right)) || //it is a Chinese character,it need two bytes space
			(((c & 0x80) == 0) && (nX >= rect.right))
			)
		{
			nX = rect.left + 1;
			nY++;
			nChar--;
		}
		else
		{
			if((c & 0x80) != 0)//it is the first byte of a Chinese character
			{
				//set the first byte of this Chinese character
				SetChar(diagram, nX, nY, c);
				nX++;
				//set the next byte of this Chinese character
				nChar++;
				c = szText[nChar];
				SetChar(diagram, nX, nY, c);
				nX++;
			}
			else//general ASCII character
			{
				SetChar(diagram, nX, nY, c);
				nX++;
			}
		}
#else
		// new line?
		if (c == '\r')
		{
			nX = rect.left + 1;
			nY++;
			nChar++; // jump '\n'
		}
		else if (nX >= rect.right)
		{
			nX = rect.left + 1;
			nY++;
			nChar--;
		}
		else
		{
			SetChar(diagram, nX, nY, c);
			nX++;
		}
#endif
	}
}

void CTextDiagram::DrawConn(CStringArray& diagram, const CTDConnection& conn) const
{
	CPoint ptEnd, ptStart = conn.GetStartPos();

	for (int nSegment = 0; nSegment < conn.NumSegments(); nSegment++)
	{
		ptEnd = conn.GetSegmentPos(nSegment);

		DrawLine(diagram, ptStart, ptEnd, &conn);
		ptStart = ptEnd;
	}

	// replace start with '+'
	ptStart = conn.GetStartPos();
	SetChar(diagram, ptStart.x, ptStart.y, CHAR_START);

	// replace end with '*'
	ptEnd = conn.GetEndPos();
	SetChar(diagram, ptEnd.x, ptEnd.y, CHAR_END);

/*	// replace end with arrows
	switch (conn.GetEndDirection())
	{
	case CONN_UP:
		SetChar(diagram, ptEnd.x, ptEnd.y, CHAR_ENDUP);
		break;

	case CONN_DOWN:
		SetChar(diagram, ptEnd.x, ptEnd.y, CHAR_ENDDOWN);
		break;

	case CONN_LEFT:
		SetChar(diagram, ptEnd.x, ptEnd.y, CHAR_ENDLEFT);
		break;

	case CONN_RIGHT:
		SetChar(diagram, ptEnd.x, ptEnd.y, CHAR_ENDRIGHT);
		break;
	}
*/
}

void CTextDiagram::DrawLine(CStringArray& diagram, CPoint ptFrom, CPoint ptTo, const CTDConnection* pConn) const
{
	// must be vert or horz
	ASSERT (ptFrom.x == ptTo.x || ptFrom.y == ptTo.y);

	int nXLen = abs(ptFrom.x - ptTo.x);
	int nYLen = abs(ptFrom.y - ptTo.y);

	if (nYLen) // vert
	{
		int nFrom = (ptFrom.y > ptTo.y) ? ptTo.y : ptFrom.y;
		int nTo = (ptFrom.y > ptTo.y) ? ptFrom.y : ptTo.y;

		if (pConn && nYLen > 0)
		{
			nFrom++;

			// make sure the line is at least one char long
			// with the exception of the start and end points
			if (nTo - nFrom > 0 || ptFrom == pConn->GetStartPos() || ptTo == pConn->GetEndPos())
				nTo--;
		}

		for (int nY = nFrom; nY <= nTo; nY++)
		{
			char c = CHAR_VERT;

			if (pConn && PtInConn(ptTo.x, nY, TRUE) && !pConn->PtInConn(CPoint(ptTo.x, nY), TRUE))
				c = CHAR_CROSSOVER;

			SetChar(diagram, ptTo.x, nY, c);
		}
	}
	else if (nXLen) // horz
	{
		int nFrom = (ptFrom.x > ptTo.x) ? ptTo.x : ptFrom.x;
		int nTo = (ptFrom.x > ptTo.x) ? ptFrom.x : ptTo.x;

		for (int nX = nFrom; nX <= nTo; nX++)
		{
			char c = CHAR_HORZ;

			if (pConn && PtInConn(nX, ptTo.y, FALSE) && !pConn->PtInConn(CPoint(nX, ptTo.y), FALSE))
				c = CHAR_CROSSOVER;

			SetChar(diagram, nX, ptTo.y, c);
		}
	}
}

void CTextDiagram::ExpandTabs(CString& sLine, int nTabSize) 
{
	CString sExpanded;

	for (int nPos = 0; nPos < sLine.GetLength(); nPos++)
	{
		char c = sLine[nPos];

		if (c == '\t')
		{
			int nTabs = nTabSize - (sExpanded.GetLength() % nTabSize);

			while (nTabs--)
				sExpanded += ' ';
		}
		else
			sExpanded += c;
	}

	sLine = sExpanded;
}

char CTextDiagram::GetChar(const CStringArray& diagram, int nX, int nY)
{
	if (nY < 0 || nY >= diagram.GetSize())
		return 0;

	CString& sLine = diagram[nY];

	if (nX < 0 || nX >= sLine.GetLength())
		return 0;

	return sLine[nX];
}

BOOL CTextDiagram::SetChar(CStringArray& diagram, int nX, int nY, char c)
{
	if (!c)
		return FALSE;

	if (nY < 0 || nY >= diagram.GetSize())
	{
		ASSERT(0);
		return FALSE;
	}

	CString& sLine = diagram[nY];

	if (nX < 0 || nX >= sLine.GetLength())
	{
		ASSERT(0);
		return FALSE;
	}

	sLine.SetAt(nX, c);
	return TRUE;
}

int CTextDiagram::LineLength(const CStringArray& diagram, int nY)
{
	return (nY < 0 || nY >= diagram.GetSize()) ? 0 : diagram[nY].GetLength();
}

BOOL CTextDiagram::TestChar(const CStringArray& diagram, int nX, int nY, char cTest1, char cTest2, char cTest3)
{
	char c = GetChar(diagram, nX, nY);

	return ((cTest1 && cTest1 == c) || (cTest2 && cTest2 == c) || (cTest3 && cTest3 == c));
}

void CTextDiagram::ProcessDiagram(const CStringArray& diagram)
{
	if (!diagram.GetSize())
		return;

	CStringArray diagramTemp;
	diagramTemp.Copy(diagram);

	// 1. title
	// find the first non-empty line
	int nLine = 0;
	BOOL bContinue = TRUE;
	
	while (bContinue && nLine < diagramTemp.GetSize())
	{
		CString sLine = diagramTemp[nLine];
		sLine.TrimLeft();
		
		if (bContinue = sLine.IsEmpty())
			nLine++;
	}
	
	// title lines must begin with a ':'
	if (TestChar(diagramTemp, 0, nLine, ':'))
	{
		while (TestChar(diagramTemp, 0, nLine, ':'))
		{
			CString sLine = diagramTemp[nLine].Mid(1);
			sLine.TrimLeft();
			sLine.TrimRight();
			
			m_sTitle += sLine;
			m_sTitle += "\r\n";
			
			nLine++;
		}
		
		// remove the title lines
		while (nLine--)
			diagramTemp.RemoveAt(0);
	}

	if (!diagramTemp.GetSize())
		return;

	// 2. check boundary conditions.
	// specifically rects either of whose left or top is zero
	BOOL bFoundHorz = FALSE, bFoundVert = FALSE;

	for (int nX = 0; nX < LineLength(diagramTemp, 0) && !bFoundHorz; nX++)
		bFoundHorz = (RECT_TOP == RectStartChar(diagramTemp, nX, 0));

	for (int nY = 0; nY < diagramTemp.GetSize() && !bFoundVert; nY++)
		bFoundVert = (RECT_TOP == RectStartChar(diagramTemp, 1, nY));

	// if we find a rect at y==0 then simply add an empty line at the start
	if (bFoundHorz)
		diagramTemp.InsertAt(0, "");

	// if we find a rect at x==0 then prepeand a space to every line
	if (bFoundVert)
	{
		for (int nY = 0; nY < diagramTemp.GetSize(); nY++)
			diagramTemp[nY] = " " + diagramTemp[nY];
	}

	// 3. process rects
	for (nY = 0; nY < diagramTemp.GetSize(); nY++)
	{
		int nLineLen = LineLength(diagramTemp, nY);

		for (int nX = 0; nX < nLineLen; nX++)
		{
			AddRect(diagramTemp, nX, nY);
		}
	}

	// 4. process connections
	if (GetRectCount() > 1)
	{
		for (nY = 0; nY < diagramTemp.GetSize(); nY++)
		{
			int nLineLen = LineLength(diagramTemp, nY);

			for (int nX = 0; nX < nLineLen; nX++)
			{
				AddConn(diagramTemp, nX, nY);
			}
		}
	}
}

TDPOS CTextDiagram::RectGetNextChar(const CStringArray& diagram, TDPOS nCurPos, int& nX, int& nY) const
{
	if (PtInRect(nX, nY))
		return NONE;

	switch (nCurPos)
	{
	case RECT_TOP:
		// test change of direction first
		if (TestChar(diagram, nX + 1, nY + 1, CHAR_RIGHT, CHAR_START, CHAR_END))
		{
			nX++;
			nY++;
			return RECT_RIGHT;
		}
		else if (TestChar(diagram, nX + 1, nY, CHAR_TOP, CHAR_START, CHAR_END))
		{
			nX++;
			return RECT_TOP;
		}
		break;

	case RECT_RIGHT:
		// test change of direction first
		if (TestChar(diagram, nX - 1, nY + 1, CHAR_BOTTOM, CHAR_START, CHAR_END))
		{
			nX--;
			nY++;
			return RECT_BOTTOM;
		}
		else if (TestChar(diagram, nX, nY + 1, CHAR_RIGHT, CHAR_START, CHAR_END))
		{
			nY++;
			return RECT_RIGHT;
		}
		break;

	case RECT_BOTTOM:
		// test change of direction first
		if (TestChar(diagram, nX - 1, nY - 1, CHAR_LEFT, CHAR_START, CHAR_END))
		{
			nX--;
			nY--;
			return RECT_LEFT;
		}
		else if (TestChar(diagram, nX - 1, nY, CHAR_BOTTOM, CHAR_START, CHAR_END))
		{
			nX--;
			return RECT_BOTTOM;
		}
		break;

	case RECT_LEFT:
		// test change of direction first
		if (TestChar(diagram, nX + 1, nY - 1, CHAR_TOP, CHAR_START, CHAR_END))
		{
			nX++;
			nY--;
			return RECT_TOP;
		}
		else if (TestChar(diagram, nX, nY - 1, CHAR_LEFT, CHAR_START, CHAR_END))
		{
			nY--;
			return RECT_LEFT;
		}
		break;
	}

	return NONE;
}

TDPOS CTextDiagram::RectStartChar(const CStringArray& diagram, int nX, int nY) const
{
	if (PtInRect(nX, nY))
		return NONE;

	char c = GetChar(diagram, nX, nY);

	// test for top char
	if (c == CHAR_TOP || c == CHAR_START || c == CHAR_END)
	{
		// test for left char
		c = GetChar(diagram, nX - 1, nY + 1);
		
		if (c == CHAR_LEFT || c == CHAR_START || c == CHAR_END)
		{
			// finally test for corner char
			c = GetChar(diagram, nX - 1, nY);

			if (c == SPACE || c == CHAR_START || c == CHAR_END)
				return RECT_TOP;
		}
	}

	return NONE;
}

TDPOS CTextDiagram::ConnStartChar(const CStringArray& diagram, int nX, int nY) const
{
	if (!PtInRect(nX, nY))
		return NONE;

	char c = GetChar(diagram, nX, nY);

	if (c == CHAR_START)
	{
		// check we are on a rect border
		int nRect = IntersectRect(nX, nY);
		ASSERT (nRect != -1);

		CTDRect rect;
		
		if (GetRect(nRect, rect) && rect.GetSide(CPoint(nX, nY)) != NONE)
			return CONN_START;
	}

	// all else
	return NONE;
}

TDPOS CTextDiagram::ConnGetNextChar(const CStringArray& diagram, TDPOS nCurPos, int& nX, int& nY) const
{
	switch (nCurPos)
	{
	case CONN_START:
		// test normal chars first
		if (IntersectRect(nX + 1, nY) == -1 && TestChar(diagram, nX + 1, nY, CHAR_HORZ, CHAR_CROSSOVER))
		{
			nX++;
			return CONN_RIGHT;
		}
		else if (IntersectRect(nX - 1, nY) == -1 && TestChar(diagram, nX - 1, nY, CHAR_HORZ, CHAR_CROSSOVER))
		{
			nX--;
			return CONN_LEFT;
		}
		else if (IntersectRect(nX, nY + 1) == -1 && TestChar(diagram, nX, nY + 1, CHAR_VERT, CHAR_CROSSOVER))
		{
			nY++;
			return CONN_DOWN;
		}
		else if (IntersectRect(nX, nY - 1) == -1 && TestChar(diagram, nX, nY - 1, CHAR_VERT, CHAR_CROSSOVER))
		{
			nY--;
			return CONN_UP;
		}
		// then, if vertical, test for immediate change of direction
		else if (IntersectRect(nX, nY + 1) == -1 && TestChar(diagram, nX, nY + 1, CHAR_HORZ))
		{
			nY++;

			// which way does it go?
			if (TestChar(diagram, nX + 1, nY, CHAR_HORZ, CHAR_CROSSOVER))
				return CONN_RIGHT;
			else
				return CONN_LEFT;
		}
		else if (IntersectRect(nX, nY - 1) == -1 && TestChar(diagram, nX, nY - 1, CHAR_HORZ))
		{
			nY--;

			// which way does it go?
			if (TestChar(diagram, nX + 1, nY, CHAR_HORZ, CHAR_CROSSOVER))
				return CONN_RIGHT;
			else
				return CONN_LEFT;
		}
		break;
		
	case CONN_RIGHT:
		// 1. test for continuation
		if (TestChar(diagram, nX + 1, nY, CHAR_HORZ, CHAR_CROSSOVER))
		{
			nX++;
			return CONN_RIGHT;
		}
		// 2. test for termination
		else if (TestChar(diagram, nX + 1, nY, CHAR_END/*, CHAR_ENDRIGHT*/))
		{
			nX++;
			return CONN_END;
		}
		// 3. test for change of direction (down)
		else if (TestChar(diagram, nX, nY + 1, CHAR_VERT, CHAR_CROSSOVER))
		{
			nY++;
			return CONN_DOWN;
		}
		// 4. test for change of direction (up)
		else if (TestChar(diagram, nX, nY - 1, CHAR_VERT, CHAR_CROSSOVER))
		{
			nY--;
			return CONN_UP;
		}
		// 5. test for termination (down)
		else if (TestChar(diagram, nX, nY + 1, CHAR_END/*, CHAR_ENDDOWN*/))
		{
			nY++;
			return CONN_END;
		}
		// 6. test for termination (up)
		else if (TestChar(diagram, nX, nY - 1, CHAR_END/*, CHAR_ENDUP*/))
		{
			nY--;
			return CONN_END;
		}
		break;
		
	case CONN_LEFT:
		// 1. test for continuation
		if (TestChar(diagram, nX - 1, nY, CHAR_HORZ, CHAR_CROSSOVER))
		{
			nX--;
			return CONN_LEFT;
		}
		// 2. test for termination
		else if (TestChar(diagram, nX - 1, nY, CHAR_END/*, CHAR_ENDLEFT*/))
		{
			nX--;
			return CONN_END;
		}
		// 3. test for change of direction (down)

⌨️ 快捷键说明

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