SDK:TXString: Difference between revisions

From Vectorworks Developer
Jump to navigation Jump to search
Line 315: Line 315:
== Displaying Content in Xcode Debug Area ==
== Displaying Content in Xcode Debug Area ==


<code lang="cpp">
<code lang="Python">
#=========================================================================================
#=========================================================================================
# The following code is for displaying TXString content in Xcode debug area.
# The following code is for displaying TXString content in Xcode debug area.

Revision as of 01:50, 26 January 2018

.SDK|SDK ..SDK:Types|SDK Types ..VCOM:VCOM (Vectorworks Component Object Model)|VCOM Basics ..VCOM:Class Reference|VCOM Class Reference

What is this?

TXString is one of the SDK generic types. It is used to represent a string in VectorWorks plug-in communications.

TXString is Unicode-compliant since Vectorworks 2018.

Comments about encoding issues

VectorWorks generally stores strings in a Mac encoding. The most common is MacRoman, which is used for most European languages (English, German, French, etc.).

If a system is set to Japanese, then it will use MacJapanese.

Other common Mac encodings are MacKorean, MacChineseTrad, MacChineseSimp, MacGreek, MacHebrew and MacArabic.

While the MacRoman encoding is used by the Macintosh OS, the Windows OS has its own equivalent, which our code commonly refers to as Ansi (two important methods in TXString are MacToAnsi and AnsiToMac).

A single byte character has 256 possible values, and the lowest 128 possible values (0x00 to 0x7F) are the same in MacRoman and the Windows equivalent encodings.

The lowercase and uppercase letters in the English alphabet, numbers, and most punctuation symbols are in the lowest 128 values, so they are represented the same in the MacRoman and equivalent Windows encodings.

However, many characters we would consider special are commonly used in German, French and other European languages, and they are in the highest 128 values.

Some examples are an 'é' with an accent mark or a 'ü' with umlauts.

If our code does not properly handle the encoding for strings with special characters, the user will see them displayed improperly.

Generally VectorWorks keeps strings in the Mac encoding.

When strings are read in from Macintosh resources, they are kept in the Mac encoding (this may not be true for strings from DITL resources, which are usually just displayed in a dialog, but these are only used in a few older dialogs).

Strings stored in a VW document are all in the Mac encoding. If a user is running on Windows and enters a string in a dialog, when our code first gets the string it will be in the Ansi encoding, and our code will convert it to the Mac encoding.

If a string is displayed in a dialog and the user is running in Windows, the string will be converted from Mac format to Ansi format before it is passed to the OS to display it. The layout manager system takes care for all of this, and its interface uses the Mac format.

A layout manager function for setting static text passes the text in Mac format. A layout manager function for getting the text from an edit box will return the text in the Mac format.

However VectorWorks filing code does not keep strings in the Mac encoding, but uses the native encoding (Mac when running on the Mac and Ansi when running on Windows).

The interface for the IFileIdentifier and IFolderIdentifier classes uses the native encoding. If code sets a IFileIdentifier, passing it a path, and it is running on Windows, the path needs to be passed in Ansi format. If code gets a path from a IFileIdentifier, and it is running on Windows, the path will be returned in Ansi format.

The interface for VectorScript uses the Mac encoding. Any string passed to a VS command should be in Mac encoding, and any strings received from a VS command are in Mac encoding.

Whenever a string needs to be converted from Mac to Ansi format, it is best to use the TXString method TXString::MacToAnsi, and to convert from Ansi to Mac, use TXString::AnsiToMac. These methods do nothing when called on the Mac.

If called when on a double-byte system (Japanese, Chinese, Korean), these methods only do something for a few non-standard Japanese characters. The shift-JIS Japanese encoding is identical on Mac and Windows except for a few characters.

Either that is true of the Korean and Chinese encoding, or any strings in those languages will not display properly if moved to another platform.

If the system is set to Greek, we use special tables for converting between MacGreek and Windows Greek encodings.

If the system is set to any other single-byte language, we use tables for converting between MacRoman and the Windows equivalent.

This means our MacToAnsi and AnsiToMac code does not support other single-byte scripts.

For example, if a user enters classnames in the Russian script, the classnames will not display properly if the VectorWorks document is moved to the opposite platform.

Definition

class GS_COMP_API TXString : public TDebugObject
{
public:	
	TXString();
	explicit TXString(size_t nInitialSize);
	TXString(const TXString &src);
	TXString(const char *src);
	TXString(const char *src, size_t len);
	TXString(ConstGSStringPtr src);
	TXString(char ch, size_t cnt);
	TXString(short strListID, short index);

	template <size_t maxCharLen>
		TXString(const PStr<maxCharLen>& src);

	virtual ~TXString();

	// overloaded assignment
	TXString& operator=(const TXString& src);
	TXString& operator=(const char *src);	
	TXString& operator=(ConstGSStringPtr src);
	TXString& operator=(char ch);
	
	template <size_t maxCharLen>
		TXString& operator=(const PStr<maxCharLen>& src);

	size_t GetLength() const;
	unsigned char GetPascalLength() const;
	bool SetLength(size_t len);
	bool SetLength(size_t len, char fill);
	void Truncate(size_t len);
	bool IsEmpty() const;
	void Empty(bool bQuick=false);
	void Clear();
	// Free any extra memory being used to hold string data.
	void FreeExtra();

	void CopyInto(GSCStrPtr sz) const;
	void CopyInto(GSStringPtr ps) const;

	char GetAt(size_t nIndex) const;
	char operator[](int nIndex) const;
	char& operator[](int nIndex);
	void SetAt(size_t nIndex, char ch);

	operator const char*() const;
	operator const unsigned char*() const;
	
	// Use these two functions to pass a TXString as a non-const string parameter.
	// *** NOTE: You MUST call ReleaseUnsafePtr afterwards to reset the TXString length fields
	char* GetUnsafeCharPtr(size_t len);
	unsigned char* GetUnsafeUnsignedCharPtr(size_t len)	;
	void ReleaseUnsafePtr();

	// This function is older, but we didn't want to change the whole project right away.
	void ReleaseUnsafeCharPtr();
	
	// string concatenation
	const TXString& operator+=(const TXString& string);
	const TXString& operator+=(char ch);
	const TXString& operator+=(const char *sz);
	const TXString& operator+=(const unsigned char *ps);

	template <size_t maxCharLen>
		const TXString& operator+=(const PStr<maxCharLen>& string);
	
	TXString& operator<<(const TXString& str);
	TXString& operator<<(char ch);
	TXString& operator<<(const char *sz);
	TXString& operator<<(const unsigned char *ps);
	TXString& operator<<(long n);

	template <size_t maxCharLen>
		TXString& operator<<(const PStr<maxCharLen>& str);

	// string comparison
	int Compare(const TXString &str) const;
	int Compare(const char *sz) const;
	int Compare(const unsigned char *pstr) const;
	template <size_t maxCharLen>
		int Compare(const PStr<maxCharLen> &str) const;

	int CompareNoCase(const TXString &str) const;
	int CompareNoCase(const char *sz) const;
	int CompareNoCase(const unsigned char *pstr) const;
	template <size_t maxCharLen>
		int CompareNoCase(const PStr<maxCharLen> &str) const;

	// simple sub-string extraction
	TXString Mid(size_t nFirst, size_t nCount) const;
	TXString Mid(size_t nFirst) const;
	TXString Left(size_t nCount) const;
	TXString Right(size_t nCount) const;

	TXString SpanIncluding(const TXString &str) const;
	TXString SpanIncluding(const char *sz) const;
	TXString SpanIncluding(const unsigned char *ps) const;
	TXString SpanExcluding(const TXString &str) const;
	TXString SpanExcluding(const char *sz) const;
	TXString SpanExcluding(const unsigned char *ps) const;

	// Deleting and Inserting
	void Delete(size_t pos, size_t len);
	void Insert(size_t pos, const char *sz);
	void Insert(size_t pos, const unsigned char *ps);
	void Insert(size_t pos, char ch, size_t cnt = 1);
	void Replace(const char *oldStr, const char *newStr, bool bIgnoreCase = false);
	void Replace(const char *oldStr, char newChar, bool bIgnoreCase = false);

	// upper/lower/reverse conversion
	void MakeUpper();
	void MakeLower();
	void MakeReverse();

	// Trimming whitespace (either side).
	void Trim();
	void TrimLeft();
	void TrimRight();

	// Searching from left to right.  Return starting index, or -1 if not found.
	int Find(char ch, int nStart = 0) const;
	int FindNoSJISCheck(char ch, int nStart = 0) const;
	int FindOneOf(const TXString &charSet) const;
	int FindOneOf(const char *szCharSet) const;
	int FindOneOf(const unsigned char *psCharSet) const;
	int FindNotOneOf(const TXString &charSet) const;
	int FindNotOneOf(const char *szCharSet) const;
	int FindNotOneOf(const unsigned char *psCharSet) const;

	// Searching from right to left.  Return starting index, or -1 if not found.
	int ReverseFind(char ch, bool checkForJISChar = true) const;
	int ReverseFindOneOf(const TXString &charSet) const;
	int ReverseFindOneOf(const char *szCharSet) const;
	int ReverseFindOneOf(const unsigned char *pstrCharSet) const;
	int ReverseFindNotOneOf(const TXString &charSet) const;
	int ReverseFindNotOneOf(const char *szCharSet) const;
	int ReverseFindNotOneOf(const unsigned char *pstrCharSet) const;

	// Look for a specific sub-string.
	int Find(const TXString &sub, bool bIgnoreCase = false) const;
	int Find(const char *szSub, bool bIgnoreCase = false) const;
	int Find(const unsigned char *psSub, bool bIgnoreCase = false) const;
	int Find(size_t nFirst, const TXString &sub, bool bIgnoreCase = false) const;
	int Find(size_t nFirst, const char *szSub, bool bIgnoreCase = false) const;
	int Find(size_t nFirst, const unsigned char *psSub, bool bIgnoreCase = false) const;

	bool Load(short strListID, short index, EEmptyHandling allowEmpty = eDontAllowEmptyResult);

	// simple formatting
	// passing a class reference before a variable-length argument list doesn't work in windows
	void Format(const char *szFormat, ...);
	void Format(const unsigned char *psFormat, ...);
	void Format(short strList, short index, ...);
	void VFormat(const char *szFormat, va_list marker);
	void itoa(int value);
	int atoi() const;
	Real64 atof() const;
	operator int() const;
	operator Real64() const;

	short AnsiToMac();
	short MacToAnsi();

			/** 
				@brief Converts windows new line characters to mac new line characters
			
				The Mac has only a single line feed character (10) as a new line while
				Windows has a carriage return (13) followed by a line feed (10). This
				function removes any line feed characters in the string.
			*/
	void	WinToMacNewLine ();

			/** 
				@brief Converts mac new line characters to windows new line characters
				
				Prepends a carriage return (13) to an existing line feed character (10)
				if one does not already exist.
			*/
	void	MacToWinNewLine ();	
};

Function

<to be supplied>

Iterators

TConstForwardIterator

class TConstForwardIterator
{
public:
	TConstForwardIterator(const TXString &str, int nStart=0);
	TConstForwardIterator& operator++();
	TConstForwardIterator& operator--();
	operator bool() const;
	bool operator==(char ch) const;
	int GetPosition() const;
	char GetChar() const;
	char GetNextChar() const;
	char GetPrevChar() const;
};

TConstReverseIterator

class TConstReverseIterator
{
public:
	TConstReverseIterator(const TXString &str);
	TConstReverseIterator& operator++();
	TConstReverseIterator& operator--();
	operator bool() const;
	bool operator==(char ch) const;
	int GetPosition() const;
	char GetChar() const;
	char GetNextChar() const;
	char GetPrevChar() const;
};

TForwardIterator

class TForwardIterator : public TConstForwardIterator
{
public:
	TForwardIterator(const TXString &str, int nStart=0);
	TXString& operator*() const;
	TXString* operator->() const;
};

TReverseIterator

class TReverseIterator : public TConstReverseIterator
{
public:
	TReverseIterator(const TXString &str);
	TXString& operator*() const;	
	TXString* operator->() const;
};

Displaying Content in Xcode Debug Area

#=========================================================================================
# The following code is for displaying TXString content in Xcode debug area.
# Add the following code to "~/.lldbinit".
# These code will take effect after Xcode restarts.

#=========================================================================================
import sys
import lldb
import lldb.formatters.Logger

CATEGORY_NAME = "vectorworks"

#=========================================================================================
# For displaying StdUStr summary in Xcode
def StdUStrSummary(valobj,internal_dict):
	middle = valobj.GetChildAtIndex(0).GetChildAtIndex(0).GetChildAtIndex(0).GetChildAtIndex(0)
	__s = middle.GetChildAtIndex(1)
	modeAndSize = __s.GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned(0)
	
	# String to be returned later.
	retStr = u'u"'
	
	if (modeAndSize & 1) == 0:  # Short/static form
		size = (modeAndSize >> 1)
		
		# Current max array size is 11. If size is greater than 11, this object is not 
		# initialized and the content should be empty.
		if size < 12:	
			txCharBuf = __s.GetChildAtIndex(1).GetPointeeData(0, size).uint16
		
			for i in range(size):
				if txCharBuf[i] == 0:
					break;
				retStr = retStr + unichr(txCharBuf[i])
			
	else:  # Long/dynamic form
		__l = middle.GetChildAtIndex(0)
		
		# We only show the first 1000 characters.
		size = __l.GetChildAtIndex(1).GetValueAsUnsigned(0)
		if size > 1000:
			size = 1000
		txCharBuf = __l.GetChildAtIndex(2).GetPointeeData(0, size).uint16
		
		for i in range(size):
			if txCharBuf[i] == 0:
				break;
			retStr = retStr + unichr(txCharBuf[i])
			
	retStr = retStr + u'"'
	
	return retStr.encode('utf-8')

#=========================================================================================
# For displaying TXString summary in Xcode
def TXStringSummary(valobj,internal_dict):
	return StdUStrSummary(valobj.GetChildMemberWithName('stdUStr'), internal_dict)

#=========================================================================================
def __lldb_init_module(debugger, dict):
	reload(sys)
	sys.setdefaultencoding('utf-8')

	# StdUStr and TXString
	debugger.HandleCommand('type summary add -F lldb_vectorworks.StdUStrSummary StdUStr --category %s' % CATEGORY_NAME)
	debugger.HandleCommand('type summary add -F lldb_vectorworks.TXStringSummary TXString --category %s' % CATEGORY_NAME)

	# Enable the vectorworks category
	debugger.HandleCommand("type category enable %s" % CATEGORY_NAME)
	
#=========================================================================================

See Also