diff options
| -rw-r--r-- | gtk/PlatGTK.cxx | 551 | ||||
| -rw-r--r-- | gtk/ScintillaGTK.cxx | 10 | ||||
| -rw-r--r-- | include/Platform.h | 6 | ||||
| -rw-r--r-- | src/CallTip.cxx | 2 | ||||
| -rw-r--r-- | src/Editor.cxx | 36 | ||||
| -rw-r--r-- | src/Editor.h | 75 | ||||
| -rw-r--r-- | win32/PlatWin.cxx | 12 | ||||
| -rw-r--r-- | win32/ScintillaWin.cxx | 14 | 
8 files changed, 467 insertions, 239 deletions
| diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index 0a84f46a1..073e51faa 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -7,6 +7,7 @@  #include <stdio.h>  #include <stdlib.h>  #include <stddef.h> +#define assert(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__))  #include <glib.h>  #include <gdk/gdk.h> @@ -34,11 +35,50 @@  #define snprintf _snprintf  #endif +#if GTK_MAJOR_VERSION >= 2 +#define USE_PANGO 1 +#endif +  #ifdef _MSC_VER  // Ignore unreferenced local functions in GTK+ headers  #pragma warning(disable: 4505)  #endif +// On GTK+ 1.x holds a GdkFont* but on GTK+ 2.x can hold a GdkFont* or a +// PangoFontDescription*. +class FontHandle { +public: +	int ascent; +	GdkFont *pfont; +#ifdef USE_PANGO +	PangoFontDescription *pfd; +#endif +	FontHandle(GdkFont *pfont_) { +		ascent = 0; +		pfont = pfont_; +#ifdef USE_PANGO +		pfd = 0; +#endif +	} +#ifdef USE_PANGO +	FontHandle(PangoFontDescription *pfd_) { +		ascent = 0; +		pfont = 0; +		pfd = pfd_; +	} +#endif +	~FontHandle() { +		if (pfont) +			gdk_font_unref(pfont); +		pfont = 0; +#ifdef USE_PANGO +		if (pfd) +			pango_font_description_free(pfd); +		pfd = 0; +#endif +	} +}; +  struct LOGFONT {  	int size;  	bool bold; @@ -94,8 +134,8 @@ static void FontMutexUnlock() {  // X has a 16 bit coordinate space, so stop drawing here to avoid wrapping  static const int maxCoordinate = 32000; -static GdkFont *PFont(Font &f) { -	return reinterpret_cast<GdkFont *>(f.GetID()); +static FontHandle *PFont(Font &f) { +	return reinterpret_cast<FontHandle *>(f.GetID());  }  static GtkWidget *PWidget(WindowID id) { @@ -350,7 +390,7 @@ bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, boo  void FontCached::Release() {  	if (id) -		gdk_font_unref(PFont(*this)); +		delete PFont(*this);  	id = 0;  } @@ -396,7 +436,7 @@ void FontCached::ReleaseId(FontID id_) {  	FontMutexUnlock();  } -static FontID LoadFontOrSet(const char *fontspec, int characterSet) { +static GdkFont *LoadFontOrSet(const char *fontspec, int characterSet) {  	if (IsDBCSCharacterSet(characterSet)) {  		return gdk_fontset_load(fontspec);  	} else { @@ -416,8 +456,21 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  	foundary[0] = '\0';  	faceName[0] = '\0';  	charset[0] = '\0'; -	FontID newid = 0; +#ifdef USE_PANGO +	if (fontName[0] == '!') { +		PangoFontDescription *pfd = pango_font_description_new(); +		if (pfd) { +			pango_font_description_set_family(pfd, fontName+1); +			pango_font_description_set_size(pfd, size * PANGO_SCALE); +			pango_font_description_set_weight(pfd, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL); +			pango_font_description_set_style(pfd, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); +			return new FontHandle(pfd); +		} +	} +#endif + +	GdkFont *newid = 0;  	// If name of the font begins with a '-', assume, that it is  	// a full fontspec.  	if (fontName[0] == '-') { @@ -432,7 +485,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  			newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*",  				characterSet);  		} -		return newid; +		return new FontHandle(newid);  	}  	// it's not a full fontspec, build one. @@ -501,7 +554,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  		newid = gdk_fontset_load(fontset);  		if (newid) -			return newid; +			return new FontHandle(newid);  		// if fontset load failed, fall through, we'll use  		// the last font entry and continue to try and @@ -550,7 +603,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,  		newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*",  			characterSet);  	} -	return newid; +	return new FontHandle(newid);  }  Font::Font() : id(0) {} @@ -578,13 +631,17 @@ class SurfaceImpl : public Surface {  	int y;  	bool inited;  	bool createdGC; +#ifdef USE_PANGO +	PangoContext *pcontext; +	PangoLayout *layout; +#endif  public:  	SurfaceImpl();  	virtual ~SurfaceImpl(); -	void Init(); -	void Init(SurfaceID sid); -	void InitPixMap(int width, int height, Surface *surface_); +	void Init(WindowID wid); +	void Init(SurfaceID sid, WindowID wid); +	void InitPixMap(int width, int height, Surface *surface_, WindowID wid);  	void Release();  	bool Initialised(); @@ -624,7 +681,11 @@ public:  };  SurfaceImpl::SurfaceImpl() : unicodeMode(false), dbcsMode(false), drawable(0), gc(0), ppixmap(0), -x(0), y(0), inited(false), createdGC(false) { +x(0), y(0), inited(false), createdGC(false) +#ifdef USE_PANGO +, pcontext(0), layout(0) +#endif +{  }  SurfaceImpl::~SurfaceImpl() { @@ -641,6 +702,14 @@ void SurfaceImpl::Release() {  	if (ppixmap)  		gdk_pixmap_unref(ppixmap);  	ppixmap = 0; +#ifdef USE_PANGO +	if (layout) +		g_object_unref(layout); +	layout = 0; +	if (pcontext) +		g_object_unref(pcontext); +	pcontext = 0; +#endif  	x = 0;  	y = 0;  	inited = false; @@ -651,30 +720,56 @@ bool SurfaceImpl::Initialised() {  	return inited;  } -void SurfaceImpl::Init() { +// The WindowID argument is only used for Pango builds +#ifdef USE_PANGO +#define WID_NAME wid +#else +#define WID_NAME +#endif + +void SurfaceImpl::Init(WindowID WID_NAME) { +	PLATFORM_ASSERT(wid);  	Release(); +#ifdef USE_PANGO +	pcontext = gtk_widget_create_pango_context(PWidget(wid)); +	PLATFORM_ASSERT(pcontext); +	layout = pango_layout_new(pcontext); +	PLATFORM_ASSERT(layout); +#endif  	inited = true;  } -void SurfaceImpl::Init(SurfaceID sid) { +void SurfaceImpl::Init(SurfaceID sid, WindowID WID_NAME) { +	PLATFORM_ASSERT(wid); +	PLATFORM_ASSERT(sid);  	GdkDrawable *drawable_ = reinterpret_cast<GdkDrawable *>(sid);  	Release(); +#ifdef USE_PANGO +	pcontext = gtk_widget_create_pango_context(PWidget(wid)); +	layout = pango_layout_new(pcontext); +#endif  	drawable = drawable_;  	gc = gdk_gc_new(drawable_); -	//gdk_gc_set_line_attributes(gc, 1, -	//	GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_BEVEL);  	createdGC = true;  	inited = true;  } -void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_) { +void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID WID_NAME) { +	PLATFORM_ASSERT(wid); +	PLATFORM_ASSERT(surface_);  	Release(); +	SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_); +	PLATFORM_ASSERT(surfImpl->drawable); +#ifdef USE_PANGO +	pcontext = gtk_widget_create_pango_context(PWidget(wid)); +	PLATFORM_ASSERT(pcontext); +	layout = pango_layout_new(pcontext); +	PLATFORM_ASSERT(layout); +#endif  	if (height > 0 && width > 0) -		ppixmap = gdk_pixmap_new(static_cast<SurfaceImpl *>(surface_)->drawable, width, height, -1); +		ppixmap = gdk_pixmap_new(surfImpl->drawable, width, height, -1);  	drawable = ppixmap; -	gc = gdk_gc_new(static_cast<SurfaceImpl *>(surface_)->drawable); -	//gdk_gc_set_line_attributes(gc, 1, -	//	GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_BEVEL); +	gc = gdk_gc_new(surfImpl->drawable);  	createdGC = true;  	inited = true;  } @@ -821,77 +916,142 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {  	}  } -#define MAX_US_LEN 5000 +static size_t UTF8Len(char ch) { +	unsigned char uch = static_cast<unsigned char>(ch); +	if (uch < 0x80) +		return 1; +	else if (uch < (0x80 + 0x40 + 0x20)) +		return 2; +	else +		return 3; +} + +#ifdef USE_PANGO + +static char *UTF8FromLatin1(const char *s, int len) { +	char *utfForm = new char[len*2+1]; +	size_t lenU = 0; +	for (int i=0;i<len;i++) { +		unsigned int uch = static_cast<unsigned char>(s[i]); +		if (uch < 0x80) { +			utfForm[lenU++] = uch; +		} else { +			utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6)); +			utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f)); +		} +	} +	utfForm[lenU] = '\0'; +	return utfForm; +} + +static char *UTF8FromGdkWChar(GdkWChar *wctext, int wclen) { +	char *utfForm = new char[wclen*3+1];	// Maximum of 3 UTF-8 bytes per character +	size_t lenU = 0; +	for (int i = 0; i < wclen && wctext[i]; i++) { +		unsigned int uch = wctext[i]; +		if (uch < 0x80) { +			utfForm[lenU++] = static_cast<char>(uch); +		} else if (uch < 0x800) { +			utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6)); +			utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f)); +		} else { +			utfForm[lenU++] = static_cast<char>(0xE0 | (uch >> 12)); +			utfForm[lenU++] = static_cast<char>(0x80 | ((uch >> 6) & 0x3f)); +			utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f)); +		} +	} +	utfForm[lenU] = '\0'; +	return utfForm; +} + +static char *UTF8FromDBCS(const char *s, int len) { +	GdkWChar *wctext = new GdkWChar[len + 1]; +	GdkWChar *wcp = wctext; +	int wclen = gdk_mbstowcs(wcp, s, len); +	if (wclen < 1) { +		// In the annoying case when non-locale chars in the line. +		// e.g. latin1 chars in Japanese locale. +		delete []wctext; +		return 0; +	} + +	char *utfForm = UTF8FromGdkWChar(wctext, wclen); +	delete []wctext; +	return utfForm; +} + +#endif + +// On GTK+, wchar_t is 4 bytes + +const int maxLengthTextRun = 10000;  void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len,                                   ColourAllocated fore) {  	PenColour(fore);  	if (gc && drawable) { -		// Draw text as a series of segments to avoid limitations in X servers -		const int segmentLength = 1000;  		int x = rc.left; -		if (unicodeMode) { -			GdkWChar wctext[MAX_US_LEN]; -			GdkWChar *wcp = (GdkWChar *) & wctext; -			size_t wclen = UCS2FromUTF8(s, len, (wchar_t *)wctext, -			                            sizeof(wctext) / sizeof(GdkWChar) - 1); -			wctext[wclen] = L'\0'; -			int lenDraw; -			while ((wclen > 0) && (x < maxCoordinate)) { -				lenDraw = Platform::Minimum(wclen, segmentLength); -				gdk_draw_text_wc(drawable, PFont(font_), gc, -				                 x, ybase, wcp, lenDraw); -				wclen -= lenDraw; -				if (wclen > 0) { -					x += gdk_text_width_wc(PFont(font_), -					                       wcp, lenDraw); +#ifdef USE_PANGO +		if (PFont(font_)->pfd) { +			char *utfForm = 0; +			if (unicodeMode) { +				pango_layout_set_text(layout, s, len); +			} else { +				if (dbcsMode) { +					// Convert to utf8 +					utfForm = UTF8FromDBCS(s, len);  				} -				wcp += lenDraw; +				if (!utfForm)	// Latin1 or DBCS failed so treat as Latin1 +					utfForm = UTF8FromLatin1(s, len); +				pango_layout_set_text(layout, utfForm, strlen(utfForm));  			} -		} else if (dbcsMode) { -			GdkWChar wctext[MAX_US_LEN]; -			GdkWChar *wcp = (GdkWChar *) & wctext; -			int wclen = gdk_mbstowcs(wcp, s, MAX_US_LEN); - -			/* In the annoying case when non-locale chars -			 * in the line. -			 * e.g. latin1 chars in Japanese locale */ -			if (wclen < 1) { -				while ((len > 0) && (x < maxCoordinate)) { -					int lenDraw = Platform::Minimum(len, segmentLength); -					gdk_draw_text(drawable, PFont(font_), gc, -					              x, ybase, s, lenDraw); -					len -= lenDraw; -					if (len > 0) { -						x += gdk_text_width(PFont(font_), s, lenDraw); -					} -					s += lenDraw; -				} -			} else { +			pango_layout_set_font_description(layout, PFont(font_)->pfd); +			PangoLayoutLine *pll = pango_layout_get_line(layout,0); +			gdk_draw_layout_line(drawable, gc, x, ybase, pll); +			delete []utfForm; +			return; +		} +#endif +		// Draw text as a series of segments to avoid limitations in X servers +		const int segmentLength = 1000; +		bool draw8bit = true; +		if (unicodeMode || dbcsMode) { +			GdkWChar wctext[maxLengthTextRun]; +			int wclen; +			if (unicodeMode) { +				wclen = UCS2FromUTF8(s, len, +					reinterpret_cast<wchar_t *>(wctext), maxLengthTextRun - 1); +			} else {	// dbcsMode, so convert using current locale +				wclen = gdk_mbstowcs( +					wctext, s, maxLengthTextRun - 1); +			} +			if (wclen > 0) { +				draw8bit = false;  				wctext[wclen] = L'\0'; -				int lenDraw; +				GdkWChar *wcp = wctext;  				while ((wclen > 0) && (x < maxCoordinate)) { -					lenDraw = Platform::Minimum(wclen, segmentLength); -					gdk_draw_text_wc(drawable, PFont(font_), gc, -					                 x, ybase, wcp, lenDraw); +					int lenDraw = Platform::Minimum(wclen, segmentLength); +					gdk_draw_text_wc(drawable, PFont(font_)->pfont, gc, +							 x, ybase, wcp, lenDraw);  					wclen -= lenDraw; -					if (wclen > 0) { -						x += gdk_text_width_wc(PFont(font_), -						                       wcp, lenDraw); -					}  					wcp += lenDraw; - 				} +					if (wclen > 0) {	// Avoid next calculation if possible as may be expensive +						x += gdk_text_width_wc(PFont(font_)->pfont, +								       wcp, lenDraw); +					} +				}  			} -		} else { +		} +		if (draw8bit) {  			while ((len > 0) && (x < maxCoordinate)) {  				int lenDraw = Platform::Minimum(len, segmentLength); -				gdk_draw_text(drawable, PFont(font_), gc, +				gdk_draw_text(drawable, PFont(font_)->pfont, gc,  				              x, ybase, s, lenDraw);  				len -= lenDraw; -				if (len > 0) { -					x += gdk_text_width(PFont(font_), s, lenDraw); -				}  				s += lenDraw; +				if (len > 0) {	// Avoid next calculation if possible as may be expensive +					x += gdk_text_width(PFont(font_)->pfont, s, lenDraw); +				}  			}  		}  	} @@ -919,86 +1079,98 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, con  void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {  	if (font_.GetID()) {  		int totalWidth = 0; -		GdkFont *gf = PFont(font_); -		if (unicodeMode) { -			GdkWChar wctext[MAX_US_LEN]; -			size_t wclen = UCS2FromUTF8(s, len, (wchar_t *)wctext, sizeof(wctext) / sizeof(GdkWChar) - 1); -			wctext[wclen] = L'\0'; -			int poses[MAX_US_LEN]; -			size_t i; -			for (i = 0; i < wclen; i++) { -				int width = gdk_char_width_wc(gf, wctext[i]); -				totalWidth += width; -				poses[i] = totalWidth; -			} -			// map widths back to utf-8 input string -			size_t ui = 0; -			i = 0; -			const unsigned char *us = reinterpret_cast<const unsigned char *>(s); -			unsigned char uch; -			while (ui < wclen) { -				uch = us[i]; -				positions[i++] = poses[ui]; -				if (uch >= 0x80) { -					if (uch < (0x80 + 0x40 + 0x20)) { -						positions[i++] = poses[ui]; -					} else { -						positions[i++] = poses[ui]; -						positions[i++] = poses[ui]; +#ifdef USE_PANGO +		if (PFont(font_)->pfd) { +			PangoRectangle pos; +			pango_layout_set_font_description(layout, PFont(font_)->pfd); +			if (unicodeMode) { +				// Simple and direct as UTF-8 is native Pango encoding +				pango_layout_set_text(layout, s, len); +				int i = 0; +				while (i < len) { +					pango_layout_index_to_pos(layout, i+1, &pos); +					positions[i++] = PANGO_PIXELS(pos.x); +				} +			} else { +				int wclen = 0; +				if (dbcsMode) { +					GdkWChar *wctext = new GdkWChar[len + 1]; +					GdkWChar *wcp = wctext; +					wclen = gdk_mbstowcs(wcp, s, len); +					if (wclen >= 1 ) { +						// Convert to UTF-8 so can ask Pango for widths, then +						// Loop through UTF-8 and DBCS forms, taking account of different +						// character byte lengths. +						char *utfForm = UTF8FromGdkWChar(wctext, wclen); +						pango_layout_set_text(layout, utfForm, strlen(utfForm)); +						int i = 0; +						int iU = 0; +						while (i < len) { +							pango_layout_index_to_pos(layout, iU+1, &pos); +							iU += UTF8Len(utfForm[iU]); +							size_t lenChar = mblen(s+i, MB_CUR_MAX); +							while (lenChar--) { +								positions[i++] = PANGO_PIXELS(pos.x); +							} +						} +						delete []utfForm;  					} +					delete []wctext; +				} +				if (wclen < 1 ) { +					// Either Latin1 or DBCS conversion failed so treat as Latin1. +					char *utfForm = UTF8FromLatin1(s, len); +					pango_layout_set_text(layout, utfForm, strlen(utfForm)); +					int i = 0; +					int iU = 0; +					while (i < len) { +						pango_layout_index_to_pos(layout, iU+1, &pos); +						iU += UTF8Len(s[i]); +						positions[i++] = PANGO_PIXELS(pos.x); +					} +					delete []utfForm;  				} -				ui++;  			} -			int lastPos = 0; -			if (i > 0) -				lastPos = positions[i - 1]; -			while (i < static_cast<size_t>(len)) { -				positions[i++] = lastPos; +			return; +		} +#endif +		GdkFont *gf = PFont(font_)->pfont; +		bool measure8bit = true; +		if (unicodeMode || dbcsMode) { +			GdkWChar wctext[maxLengthTextRun]; +			int wclen; +			if (unicodeMode) { +				wclen = UCS2FromUTF8(s, len, +					reinterpret_cast<wchar_t *>(wctext), maxLengthTextRun - 1); +			} else {	// dbcsMode, so convert using current locale +				wclen = gdk_mbstowcs( +					wctext, s, maxLengthTextRun - 1);  			} -		} else if (dbcsMode) { -			GdkWChar wctext[MAX_US_LEN]; -			size_t wclen = (size_t)gdk_mbstowcs(wctext, s, MAX_US_LEN); -			/* In the annoying case when non-locale chars -			 * in the line. -			 * e.g. latin1 chars in Japanese locale */ -			if( (int)wclen < 1 ) { -				for (int i = 0; i < len; i++) { -					int width = gdk_char_width(gf, s[i]); -					totalWidth += width; -					positions[i] = totalWidth; -				} -			} else { +			if (wclen > 0) { +				measure8bit = false;  				wctext[wclen] = L'\0'; -				int poses[MAX_US_LEN]; -				size_t i; -				for (i = 0; i < wclen; i++) { -					int width = gdk_char_width_wc(gf, wctext[i]); +				// Map widths back to utf-8 or DBCS input string +				int i = 0; +				for (int iU = 0; iU < wclen; iU++) { +					int width = gdk_char_width_wc(gf, wctext[iU]);  					totalWidth += width; -					poses[i] = totalWidth; -				} -				size_t ui = 0; -				i = 0; -				for (ui = 0; ui< wclen; ui++) { -					GdkWChar wch[2]; -					wch[0] = wctext[ui]; -					wch[1] = L'\0'; -					gchar* mbstr = gdk_wcstombs(wch); -					if (mbstr == NULL || *mbstr == '\0') -						g_error("mbs broken\n"); -					for(int j=0; j<(int)strlen(mbstr); j++) { -						positions[i++] = poses[ui]; +					size_t lenChar; +					if (unicodeMode) { +						lenChar = UTF8Len(s[i]); +					} else { +						lenChar = mblen(s+i, MB_CUR_MAX); +					} +					while (lenChar--) { +						positions[i++] = totalWidth;  					} -					if( mbstr != NULL ) -						g_free(mbstr);  				} -				int lastPos = 0; -				if (i > 0) -					lastPos = positions[i - 1]; -				while (i < static_cast<size_t>(len)) { -					positions[i++] = lastPos; +				while (i < len) {	// In case of problems with lengths +					positions[i++] = totalWidth;  				}  			} -		} else { +		} +		if (measure8bit) { +			// Either Latin1 or conversion failed so treat as Latin1.  			for (int i = 0; i < len; i++) {  				int width = gdk_char_width(gf, s[i]);  				totalWidth += width; @@ -1006,6 +1178,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi  			}  		}  	} else { +		// No font so return an ascending range of values  		for (int i = 0; i < len; i++) {  			positions[i] = i + 1;  		} @@ -1014,24 +1187,52 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi  int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {  	if (font_.GetID()) { +#ifdef USE_PANGO +		if (PFont(font_)->pfd) { +			char *utfForm = 0; +			pango_layout_set_font_description(layout, PFont(font_)->pfd); +			PangoRectangle pos; +			if (unicodeMode) { +				pango_layout_set_text(layout, s, len); +			} else { +				if (dbcsMode) { +					// Convert to utf8 +					utfForm = UTF8FromDBCS(s, len); +				} +				if (!utfForm)	// Latin1 or DBCS failed so treat as Latin1 +					utfForm = UTF8FromLatin1(s, len); +				pango_layout_set_text(layout, utfForm, strlen(utfForm)); +			} +			pango_layout_index_to_pos(layout, len, &pos); +			int width = PANGO_PIXELS(pos.x); +			delete []utfForm; +			return width; +		} +#endif  		if (unicodeMode) { -			GdkWChar wctext[MAX_US_LEN]; +			GdkWChar wctext[maxLengthTextRun];  			size_t wclen = UCS2FromUTF8(s, len, (wchar_t *)wctext, sizeof(wctext) / sizeof(GdkWChar) - 1);  			wctext[wclen] = L'\0'; -			int width = gdk_text_width_wc(PFont(font_), wctext, wclen); -			return width; -		} else -			return gdk_text_width(PFont(font_), s, len); +			return gdk_text_width_wc(PFont(font_)->pfont, wctext, wclen); +		} else { +			return gdk_text_width(PFont(font_)->pfont, s, len); +		}  	} else {  		return 1;  	}  }  int SurfaceImpl::WidthChar(Font &font_, char ch) { -	if (font_.GetID()) -		return gdk_char_width(PFont(font_), ch); -	else +	if (font_.GetID()) { +#ifdef USE_PANGO +		if (PFont(font_)->pfd) { +			return WidthText(font_, &ch, 1); +		} +#endif +		return gdk_char_width(PFont(font_)->pfont, ch); +	} else {  		return 1; +	}  }  // Three possible strategies for determining ascent and descent of font: @@ -1050,11 +1251,23 @@ const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"                            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";  int SurfaceImpl::Ascent(Font &font_) { -	if (!font_.GetID()) +	if (!(font_.GetID()))  		return 1;  #ifdef FAST_WAY +	if (PFont(font_)->ascent > 0) +		return PFont(font_)->ascent; +#ifdef USE_PANGO +	if (PFont(font_)->pfd) { +		PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, +			PFont(font_)->pfd, pango_context_get_language(pcontext)); +		PFont(font_)->ascent = +			PANGO_PIXELS(pango_font_metrics_get_ascent(metrics)); +		pango_font_metrics_unref(metrics); +		return PFont(font_)->ascent; +	} +#endif -	return PFont(font_)->ascent; +	return PFont(font_)->pfont->ascent;  #else  	gint lbearing; @@ -1063,18 +1276,27 @@ int SurfaceImpl::Ascent(Font &font_) {  	gint ascent;  	gint descent; -	gdk_string_extents(PFont(font_), sizeString, +	gdk_string_extents(PFont(font_)->pfont, sizeString,  					   &lbearing, &rbearing, &width, &ascent, &descent);  	return ascent;  #endif  }  int SurfaceImpl::Descent(Font &font_) { -	if (!font_.GetID()) +	if (!(font_.GetID()))  		return 1;  #ifdef FAST_WAY -	return PFont(font_)->descent; +#ifdef USE_PANGO +	if (PFont(font_)->pfd) { +		PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, +			PFont(font_)->pfd, pango_context_get_language(pcontext)); +		int descent = PANGO_PIXELS(pango_font_metrics_get_descent(metrics)); +		pango_font_metrics_unref(metrics); +		return descent; +	} +#endif +	return PFont(font_)->pfont->descent;  #else  	gint lbearing; @@ -1083,7 +1305,7 @@ int SurfaceImpl::Descent(Font &font_) {  	gint ascent;  	gint descent; -	gdk_string_extents(PFont(font_), sizeString, +	gdk_string_extents(PFont(font_)->pfont, sizeString,  					   &lbearing, &rbearing, &width, &ascent, &descent);  	return descent;  #endif @@ -1102,10 +1324,7 @@ int SurfaceImpl::Height(Font &font_) {  }  int SurfaceImpl::AverageCharWidth(Font &font_) { -	if (font_.GetID()) -		return gdk_char_width(PFont(font_), 'n'); -	else -		return 1; +	return WidthChar(font_, 'n');  }  int SurfaceImpl::SetPalette(Palette *, bool) { @@ -1381,10 +1600,10 @@ void ListBoxX::Create(Window &, int, int, bool) {  void ListBoxX::SetFont(Font &scint_font) {  #if GTK_MAJOR_VERSION < 2  	GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(PWidget(list))); -	if (!gdk_font_equal(style->font, PFont(scint_font))) { +	if (!gdk_font_equal(style->font, PFont(scint_font)->pfont)) {  		style = gtk_style_copy(style);  		gdk_font_unref(style->font); -		style->font = PFont(scint_font); +		style->font = PFont(scint_font)->pfont;  		gdk_font_ref(style->font);  		gtk_widget_set_style(GTK_WIDGET(PWidget(list)), style);  		gtk_style_unref(style); @@ -1392,9 +1611,9 @@ void ListBoxX::SetFont(Font &scint_font) {  #else  	GtkStyle *styleCurrent = gtk_widget_get_style(GTK_WIDGET(PWidget(list)));  	GdkFont *fontCurrent = gtk_style_get_font(styleCurrent); -	if (!gdk_font_equal(fontCurrent, PFont(scint_font))) { +	if (!gdk_font_equal(fontCurrent, PFont(scint_font)->pfont)) {  		GtkStyle *styleNew = gtk_style_copy(styleCurrent); -		gtk_style_set_font(styleNew, PFont(scint_font)); +		gtk_style_set_font(styleNew, PFont(scint_font)->pfont);  		gtk_widget_set_style(GTK_WIDGET(PWidget(list)), styleNew);  		gtk_style_unref(styleCurrent);  	} diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 7a2bfa458..e0fd95a99 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -93,7 +93,7 @@ class ScintillaGTK : public ScintillaBase {  	gint wheelMouseIntensity;  	// Private so ScintillaGTK objects can not be copied -ScintillaGTK(const ScintillaGTK &) : ScintillaBase() {} +	ScintillaGTK(const ScintillaGTK &) : ScintillaBase() {}  	ScintillaGTK &operator=(const ScintillaGTK &) { return * this; }  public: @@ -654,7 +654,7 @@ void ScintillaGTK::FullPaint() {  	if ((PWidget(wMain))->window) {  		Surface *sw = Surface::Allocate();  		if (sw) { -			sw->Init((PWidget(wMain))->window); +			sw->Init(PWidget(wMain)->window, PWidget(wMain));  			Paint(sw, rcPaint);  			sw->Release();  			delete sw; @@ -691,7 +691,7 @@ void ScintillaGTK::SyncPaint(PRectangle rc) {  	if ((PWidget(wMain))->window) {  		Surface *sw = Surface::Allocate();  		if (sw) { -			sw->Init((PWidget(wMain))->window); +			sw->Init(PWidget(wMain)->window, PWidget(wMain));  			Paint(sw, rc);  			sw->Release();  			delete sw; @@ -1520,7 +1520,7 @@ gint ScintillaGTK::Expose(GtkWidget *, GdkEventExpose *ose) {  	paintingAllText = rcPaint.Contains(rcClient);  	Surface *surfaceWindow = Surface::Allocate();  	if (surfaceWindow) { -		surfaceWindow->Init((PWidget(wMain))->window); +		surfaceWindow->Init(PWidget(wMain)->window, PWidget(wMain));  		// Fill the corner between the scrollbars  		PRectangle rcCorner = wMain.GetClientPosition();  		if (verticalScrollBarVisible) @@ -1668,7 +1668,7 @@ void ScintillaGTK::PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *) {  gint ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {  	Surface *surfaceWindow = Surface::Allocate();  	if (surfaceWindow) { -		surfaceWindow->Init(widget->window); +		surfaceWindow->Init(widget->window, widget);  		ctip->PaintCT(surfaceWindow);  		surfaceWindow->Release();  		delete surfaceWindow; diff --git a/include/Platform.h b/include/Platform.h index ee6e07c34..fa3c9ea10 100644 --- a/include/Platform.h +++ b/include/Platform.h @@ -293,9 +293,9 @@ public:  	virtual ~Surface() {};  	static Surface *Allocate(); -	virtual void Init()=0; -	virtual void Init(SurfaceID sid)=0; -	virtual void InitPixMap(int width, int height, Surface *surface_)=0; +	virtual void Init(WindowID wid)=0; +	virtual void Init(SurfaceID sid, WindowID wid)=0; +	virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0;  	virtual void Release()=0;  	virtual bool Initialised()=0; diff --git a/src/CallTip.cxx b/src/CallTip.cxx index f95a1db14..c83e2d2fd 100644 --- a/src/CallTip.cxx +++ b/src/CallTip.cxx @@ -129,7 +129,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,  	Surface *surfaceMeasure = Surface::Allocate();  	if (!surfaceMeasure)  		return PRectangle(); -	surfaceMeasure->Init(); +	surfaceMeasure->Init(wCallTip.GetID());  	surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);  	surfaceMeasure->SetDBCSMode(codePage);  	startHighlight = 0; diff --git a/src/Editor.cxx b/src/Editor.cxx index 7569d5a60..643c8eee4 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -420,7 +420,7 @@ void Editor::RefreshColourPalette(Palette &pal, bool want) {  void Editor::RefreshStyleData() {  	if (!stylesValid) {  		stylesValid = true; -		AutoSurface surface(CodePage()); +		AutoSurface surface(this);  		if (surface) {  			vs.Refresh(*surface);  			RefreshColourPalette(palette, true); @@ -523,7 +523,7 @@ Point Editor::LocationFromPosition(int pos) {  	int line = pdoc->LineFromPosition(pos);  	int lineVisible = cs.DisplayFromDoc(line);  	//Platform::DebugPrintf("line=%d\n", line); -	AutoSurface surface(CodePage()); +	AutoSurface surface(this);  	AutoLineLayout ll(llc, RetrieveLineLayout(line));  	if (surface && ll) {  		// -1 because of adding in for visible lines in following loop. @@ -581,7 +581,7 @@ int Editor::PositionFromLocation(Point pt) {  		return pdoc->Length();  	unsigned int posLineStart = pdoc->LineStart(lineDoc);  	int retVal = posLineStart; -	AutoSurface surface(CodePage()); +	AutoSurface surface(this);  	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));  	if (surface && ll) {  		LayoutLine(lineDoc, surface, vs, ll, wrapWidth); @@ -624,7 +624,7 @@ int Editor::PositionFromLocationClose(Point pt) {  		return INVALID_POSITION;  	if (lineDoc >= pdoc->LinesTotal())  		return INVALID_POSITION; -	AutoSurface surface(CodePage()); +	AutoSurface surface(this);  	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));  	if (surface && ll) {  		LayoutLine(lineDoc, surface, vs, ll, wrapWidth); @@ -656,7 +656,7 @@ int Editor::PositionFromLineX(int lineDoc, int x) {  	if (lineDoc >= pdoc->LinesTotal())  		return pdoc->Length();  	//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine); -	AutoSurface surface(CodePage()); +	AutoSurface surface(this);  	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));  	int retVal = 0;  	if (surface && ll) { @@ -983,7 +983,7 @@ void Editor::MoveCaretInsideView(bool ensureVisible) {  int Editor::DisplayFromPosition(int pos) {  	int lineDoc = pdoc->LineFromPosition(pos);  	int lineDisplay = cs.DisplayFromDoc(lineDoc); -	AutoSurface surface(CodePage()); +	AutoSurface surface(this);  	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));  	if (surface && ll) {  		LayoutLine(lineDoc, surface, vs, ll, wrapWidth); @@ -1327,7 +1327,7 @@ bool Editor::WrapLines() {  			wrapWidth = rcTextArea.Width();  			// Ensure all of the document is styled.  			pdoc->EnsureStyledTo(pdoc->Length()); -			AutoSurface surface(CodePage()); +			AutoSurface surface(this);  			if (surface) {  				int lastLineToWrap = pdoc->LinesTotal();  				while (docLineLastWrapped <= lastLineToWrap) { @@ -1394,7 +1394,7 @@ void Editor::LinesSplit(int pixelWidth) {  		const char *eol = StringFromEOLMode(pdoc->eolMode);  		pdoc->BeginUndoAction();  		for (int line = lineStart; line <= lineEnd; line++) { -			AutoSurface surface(CodePage()); +			AutoSurface surface(this);  			AutoLineLayout ll(llc, RetrieveLineLayout(line));  			if (surface && ll) {  				unsigned int posLineStart = pdoc->LineStart(line); @@ -2214,7 +2214,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  void Editor::RefreshPixMaps(Surface *surfaceWindow) {  	if (!pixmapSelPattern->Initialised()) {  		const int patternSize=8; -		pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow); +		pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());  		// This complex procedure is to reproduce the checkerboard dithered pattern used by windows  		// for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half  		// way between the chrome colour and the chrome highlight colour making a nice transition @@ -2251,8 +2251,8 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {  	if (!pixmapIndentGuide->Initialised()) {  		// 1 extra pixel in height so can handle odd/even positions and so produce a continuous line -		pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow); -		pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow); +		pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID()); +		pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());  		PRectangle rcIG(0, 0, 1, vs.lineHeight);  		pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back.allocated);  		pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore.allocated); @@ -2270,9 +2270,9 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {  		if (!pixmapLine->Initialised()) {  			PRectangle rcClient = GetClientRectangle();  			pixmapLine->InitPixMap(rcClient.Width(), rcClient.Height(), -			                       surfaceWindow); +			                       surfaceWindow, wMain.GetID());  			pixmapSelMargin->InitPixMap(vs.fixedColumnWidth, -			                            rcClient.Height(), surfaceWindow); +			                            rcClient.Height(), surfaceWindow, wMain.GetID());  		}  	}  } @@ -2583,10 +2583,10 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) {  	if (!pfr)  		return 0; -	AutoSurface surface(pfr->hdc, CodePage()); +	AutoSurface surface(pfr->hdc, this);  	if (!surface)  		return 0; -	AutoSurface surfaceMeasure(pfr->hdcTarget, CodePage()); +	AutoSurface surfaceMeasure(pfr->hdcTarget, this);  	if (!surfaceMeasure) {  		return 0;  	} @@ -2758,7 +2758,7 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) {  int Editor::TextWidth(int style, const char *text) {  	RefreshStyleData(); -	AutoSurface surface(CodePage()); +	AutoSurface surface(this);  	if (surface) {  		return surface->WidthText(vs.styles[style].font, text, strlen(text));  	} else { @@ -3169,7 +3169,7 @@ void Editor::CheckModificationForWrap(DocModification mh) {  		if (wrapState != eWrapNone) {  			int lineDoc = pdoc->LineFromPosition(mh.position);  			if (mh.linesAdded == 0) { -				AutoSurface surface(CodePage()); +				AutoSurface surface(this);  				AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));  				if (surface && ll) {  					LayoutLine(lineDoc, surface, vs, ll, wrapWidth); @@ -3537,7 +3537,7 @@ void Editor::CursorUpOrDown(int direction, bool extend) {  int Editor::StartEndDisplayLine(int pos, bool start) {  	RefreshStyleData();  	int line = pdoc->LineFromPosition(pos); -	AutoSurface surface(CodePage()); +	AutoSurface surface(this);  	AutoLineLayout ll(llc, RetrieveLineLayout(line));  	int posRet = INVALID_POSITION;  	if (surface && ll) { diff --git a/src/Editor.h b/src/Editor.h index 5db0e870d..d7582111d 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -132,40 +132,6 @@ public:  };  /** - * A smart pointer class to ensure Surfaces are set up and deleted correctly. - */ -class AutoSurface { -private: -	Surface *surf; -public: -	AutoSurface(int codePage) { -		surf = Surface::Allocate(); -		if (surf) { -			surf->Init(); -			surf->SetUnicodeMode(SC_CP_UTF8 == codePage); -			surf->SetDBCSMode(codePage); -		} -	} -	AutoSurface(SurfaceID sid, int codePage) { -		surf = Surface::Allocate(); -		if (surf) { -			surf->Init(sid); -			surf->SetUnicodeMode(SC_CP_UTF8 == codePage); -			surf->SetDBCSMode(codePage); -		} -	} -	~AutoSurface() { -		delete surf; -	} -	Surface *operator->() const { -		return surf; -	} -	operator Surface *() const { -		return surf; -	} -}; - -/**   */  class Editor : public DocWatcher {  	// Private so Editor objects can not be copied @@ -362,7 +328,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  		bool overrideBackground, ColourAllocated background);  	void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,  		PRectangle rcLine, LineLayout *ll, int subLine=0); -    void RefreshPixMaps(Surface *surfaceWindow); +	void RefreshPixMaps(Surface *surfaceWindow);  	void Paint(Surface *surfaceWindow, PRectangle rcArea);  	long FormatRange(bool draw, RangeToFormat *pfr);  	int TextWidth(int style, const char *text); @@ -485,6 +451,45 @@ public:  	virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);  	// Public so scintilla_set_id can use it.  	int ctrlID; +	friend class AutoSurface; +}; + +/** + * A smart pointer class to ensure Surfaces are set up and deleted correctly. + */ +class AutoSurface { +private: +	Surface *surf; +public: +	AutoSurface(Editor *ed) : surf(0) { +		if (ed->wMain.GetID()) { +			surf = Surface::Allocate(); +			if (surf) { +				surf->Init(ed->wMain.GetID()); +				surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); +				surf->SetDBCSMode(ed->CodePage()); +			} +		} +	} +	AutoSurface(SurfaceID sid, Editor *ed) : surf(0) { +		if (ed->wMain.GetID()) { +			surf = Surface::Allocate(); +			if (surf) { +				surf->Init(sid, ed->wMain.GetID()); +				surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); +				surf->SetDBCSMode(ed->CodePage()); +			} +		} +	} +	~AutoSurface() { +		delete surf; +	} +	Surface *operator->() const { +		return surf; +	} +	operator Surface *() const { +		return surf; +	}  };  #endif diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 80a2e8557..23c7862ed 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -292,9 +292,9 @@ public:  	SurfaceImpl();  	virtual ~SurfaceImpl(); -	void Init(); -	void Init(SurfaceID sid); -	void InitPixMap(int width, int height, Surface *surface_); +	void Init(WindowID wid); +	void Init(SurfaceID sid, WindowID wid); +	void InitPixMap(int width, int height, Surface *surface_, WindowID wid);  	void Release();  	bool Initialised(); @@ -390,20 +390,20 @@ bool SurfaceImpl::Initialised() {  	return hdc != 0;  } -void SurfaceImpl::Init() { +void SurfaceImpl::Init(WindowID) {  	Release();  	hdc = ::CreateCompatibleDC(NULL);  	hdcOwned = true;  	::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);  } -void SurfaceImpl::Init(SurfaceID sid) { +void SurfaceImpl::Init(SurfaceID sid, WindowID) {  	Release();  	hdc = reinterpret_cast<HDC>(sid);  	::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);  } -void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_) { +void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) {  	Release();  	hdc = ::CreateCompatibleDC(static_cast<SurfaceImpl *>(surface_)->hdc);  	hdcOwned = true; diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index b303db27a..1ac55315f 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -384,7 +384,7 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) {  		pps = &ps;  		::BeginPaint(MainHWND(), pps);  	} -	AutoSurface surfaceWindow(pps->hdc, CodePage()); +	AutoSurface surfaceWindow(pps->hdc, this);  	if (surfaceWindow) {  		rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom);  		PRectangle rcClient = GetClientRectangle(); @@ -1428,7 +1428,7 @@ void ScintillaWin::ImeStartComposition() {  			int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel;  			if (sizeZoomed <= 2)	// Hangs if sizeZoomed <= 1  				sizeZoomed = 2; -			AutoSurface surface(CodePage()); +			AutoSurface surface(this);  			int deviceHeight = sizeZoomed;  			if (surface) {  				deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72; @@ -1589,7 +1589,7 @@ void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {  void ScintillaWin::RealizeWindowPalette(bool inBackGround) {  	RefreshStyleData();  	HDC hdc = ::GetDC(MainHWND()); -	AutoSurface surfaceWindow(hdc, CodePage()); +	AutoSurface surfaceWindow(hdc, this);  	if (surfaceWindow) {  		int changes = surfaceWindow->SetPalette(&palette, inBackGround);  		if (changes > 0) @@ -1608,7 +1608,7 @@ void ScintillaWin::FullPaint() {  	rcPaint = GetClientRectangle();  	paintingAllText = true;  	HDC hdc = ::GetDC(MainHWND()); -	AutoSurface surfaceWindow(hdc, CodePage()); +	AutoSurface surfaceWindow(hdc, this);  	if (surfaceWindow) {  		Paint(surfaceWindow, rcPaint);  		surfaceWindow->Release(); @@ -1931,10 +1931,14 @@ sptr_t PASCAL ScintillaWin::CTWndProc(  		} else if (iMessage == WM_PAINT) {  			PAINTSTRUCT ps;  			::BeginPaint(hWnd, &ps); -			AutoSurface surfaceWindow(ps.hdc, ctp->codePage); +			Surface *surfaceWindow = Surface::Allocate();  			if (surfaceWindow) { +				surfaceWindow->Init(ps.hdc, hWnd); +				surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctp->codePage); +				surfaceWindow->SetDBCSMode(ctp->codePage);  				ctp->PaintCT(surfaceWindow);  				surfaceWindow->Release(); +				delete surfaceWindow;  			}  			::EndPaint(hWnd, &ps);  			return 0; | 
