diff options
author | nyamatongwe <unknown> | 2003-01-12 04:02:43 +0000 |
---|---|---|
committer | nyamatongwe <unknown> | 2003-01-12 04:02:43 +0000 |
commit | 7087f3740b3411d950594815ec2f32280c080692 (patch) | |
tree | 0d044674b7e8558b555e1f8c3e0698bd2f2fa8dc | |
parent | 01eabfc39bbf258af987be07d72dc0c7db7a903f (diff) | |
download | scintilla-mirror-7087f3740b3411d950594815ec2f32280c080692.tar.gz |
Additions from Yukihiro Nakai to enable DBCS mode on GTK+.
DBCS mode for Surface so that different font and text drawing code can be
invoked on GTK+.
-rw-r--r-- | gtk/PlatGTK.cxx | 124 | ||||
-rw-r--r-- | include/Platform.h | 1 | ||||
-rw-r--r-- | include/Scintilla.h | 1 | ||||
-rw-r--r-- | include/Scintilla.iface | 3 | ||||
-rw-r--r-- | src/CallTip.cxx | 8 | ||||
-rw-r--r-- | src/CallTip.h | 18 | ||||
-rw-r--r-- | src/Editor.cxx | 31 | ||||
-rw-r--r-- | src/Editor.h | 12 | ||||
-rw-r--r-- | win32/PlatWin.cxx | 6 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 10 |
10 files changed, 172 insertions, 42 deletions
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index 58dbd742a..ebf949566 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -232,6 +232,18 @@ static const char *CharacterSetName(int characterSet) { } } +static bool IsDBCSCharacterSet(int characterSet) { + switch (characterSet) { + case SC_CHARSET_GB2312: + case SC_CHARSET_HANGUL: + case SC_CHARSET_SHIFTJIS: + case SC_CHARSET_CHINESEBIG5: + return true; + default: + return false; + } +} + static void GenerateFontSpecStrings(const char *fontName, int characterSet, char *foundary, int foundary_len, char *faceName, int faceName_len, @@ -384,6 +396,14 @@ void FontCached::ReleaseId(FontID id_) { FontMutexUnlock(); } +static FontID LoadFontOrSet(const char *fontspec, int characterSet) { + if (IsDBCSCharacterSet(characterSet)) { + return gdk_fontset_load(fontspec); + } else { + return gdk_font_load(fontspec); + } +} + FontID FontCached::CreateNewFont(const char *fontName, int characterSet, int size, bool bold, bool italic) { char fontset[1024]; @@ -401,7 +421,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, // If name of the font begins with a '-', assume, that it is // a full fontspec. if (fontName[0] == '-') { - if (strchr(fontName, ',')) { + if (strchr(fontName, ',') || IsDBCSCharacterSet(characterSet)) { newid = gdk_fontset_load(fontName); } else { newid = gdk_font_load(fontName); @@ -409,7 +429,8 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, if (!newid) { // Font not available so substitute a reasonable code font // iso8859 appears to only allow western characters. - newid = gdk_font_load("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*"); + newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*", + characterSet); } return newid; } @@ -502,7 +523,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, italic ? "-i" : "-r", size * 10, charset); - newid = gdk_font_load(fontspec); + newid = LoadFontOrSet(fontspec, characterSet); if (!newid) { // some fonts have oblique, not italic snprintf(fontspec, @@ -513,7 +534,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, italic ? "-o" : "-r", size * 10, charset); - newid = gdk_font_load(fontspec); + newid = LoadFontOrSet(fontspec, characterSet); } if (!newid) { snprintf(fontspec, @@ -526,7 +547,8 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, if (!newid) { // Font not available so substitute a reasonable code font // iso8859 appears to only allow western characters. - newid = gdk_font_load("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*"); + newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*", + characterSet); } return newid; } @@ -548,6 +570,7 @@ void Font::Release() { class SurfaceImpl : public Surface { bool unicodeMode; + bool dbcsMode; GdkDrawable *drawable; GdkGC *gc; GdkPixmap *ppixmap; @@ -595,10 +618,12 @@ public: void FlushCachedState(); void SetUnicodeMode(bool unicodeMode_); + void SetDBCSMode(int codePage); }; -SurfaceImpl::SurfaceImpl() : unicodeMode(false), drawable(0), gc(0), ppixmap(0), -x(0), y(0), inited(false), createdGC(false) {} +SurfaceImpl::SurfaceImpl() : unicodeMode(false), dbcsMode(false), drawable(0), gc(0), ppixmap(0), +x(0), y(0), inited(false), createdGC(false) { +} SurfaceImpl::~SurfaceImpl() { Release(); @@ -822,6 +847,40 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const ch } wcp += lenDraw; } + } 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 { + 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); + } + wcp += lenDraw; + } + } } else { while ((len > 0) && (x < maxCoordinate)) { int lenDraw = Platform::Minimum(len, segmentLength); @@ -882,6 +941,49 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi while (i < static_cast<size_t>(len)) { positions[i++] = lastPos; } + } 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 { + 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; + } + 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]; + } + 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; + } + } } else { for (int i = 0; i < len; i++) { int width = gdk_char_width(gf, s[i]); @@ -1009,6 +1111,10 @@ void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { unicodeMode = unicodeMode_; } +void SurfaceImpl::SetDBCSMode(int codePage) { + dbcsMode = codePage == SC_CP_DBCS; +} + Surface *Surface::Allocate() { return new SurfaceImpl; } @@ -1361,7 +1467,7 @@ static void init_pixmap(ListImage *list_image, GtkWidget *window) { if (list_image->bitmap) gdk_bitmap_unref(list_image->bitmap); list_image->bitmap = NULL; - + list_image->pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL , gtk_widget_get_colormap(window), &(list_image->bitmap), NULL , (gchar **) xpm_lineform); @@ -1476,7 +1582,7 @@ void ListBoxX::RegisterImage(int type, const char *xpm_data) { } else { list_image = g_new0(ListImage, 1); list_image->xpm_data = xpm_data; - g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type), + g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type), (gpointer) list_image); } } diff --git a/include/Platform.h b/include/Platform.h index ee31063e3..9061449e2 100644 --- a/include/Platform.h +++ b/include/Platform.h @@ -329,6 +329,7 @@ public: virtual void FlushCachedState()=0; virtual void SetUnicodeMode(bool unicodeMode_)=0; + virtual void SetDBCSMode(int codePage)=0; }; /** diff --git a/include/Scintilla.h b/include/Scintilla.h index 74efc3f78..8df32be4c 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -83,6 +83,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SETTABWIDTH 2036 #define SCI_GETTABWIDTH 2121 #define SC_CP_UTF8 65001 +#define SC_CP_DBCS 1 #define SCI_SETCODEPAGE 2037 #define SCI_SETUSEPALETTE 2039 #define MARKER_MAX 31 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index bb7ee0a15..bade44fd2 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -221,6 +221,9 @@ get int GetTabWidth=2121(,) # This is the same value as CP_UTF8 in Windows val SC_CP_UTF8=65001 +# The SC_CP_DBCS value can be used to indicate a DBCS mode for GTK+. +val SC_CP_DBCS=1 + # Set the code page used to interpret the bytes of the document as characters. # The SC_CP_UTF8 value can be used to enter Unicode mode. set void SetCodePage=2037(int codePage,) diff --git a/src/CallTip.cxx b/src/CallTip.cxx index d67173b08..f95a1db14 100644 --- a/src/CallTip.cxx +++ b/src/CallTip.cxx @@ -117,19 +117,21 @@ void CallTip::PaintCT(Surface *surfaceWindow) { } PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, - const char *faceName, int size, bool unicodeMode_) { + const char *faceName, int size, + int codePage_) { if (val) delete []val; val = new char[strlen(defn) + 1]; if (!val) return PRectangle(); strcpy(val, defn); - unicodeMode = unicodeMode_; + codePage = codePage_; Surface *surfaceMeasure = Surface::Allocate(); if (!surfaceMeasure) return PRectangle(); surfaceMeasure->Init(); - surfaceMeasure->SetUnicodeMode(unicodeMode); + surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage); + surfaceMeasure->SetDBCSMode(codePage); startHighlight = 0; endHighlight = 0; inCallTipMode = true; diff --git a/src/CallTip.h b/src/CallTip.h index 9f5025f63..877d9f34e 100644 --- a/src/CallTip.h +++ b/src/CallTip.h @@ -29,22 +29,22 @@ public: ColourPair colourSel; ColourPair colourShade; ColourPair colourLight; - bool unicodeMode; - + int codePage; + CallTip(); ~CallTip(); - + /// Claim or accept palette entries for the colours required to paint a calltip. void RefreshColourPalette(Palette &pal, bool want); - + void PaintCT(Surface *surfaceWindow); - + /// Setup the calltip and return a rectangle of the area required. - PRectangle CallTipStart(int pos, Point pt, const char *defn, - const char *faceName, int size, bool unicodeMode_); - + PRectangle CallTipStart(int pos, Point pt, const char *defn, + const char *faceName, int size, int codePage_); + void CallTipCancel(); - + /// Set a range of characters to be displayed in a highlight style. /// Commonly used to highlight the current parameter. void SetHighlight(int start, int end); diff --git a/src/Editor.cxx b/src/Editor.cxx index ddd9fbcd6..c9833b03a 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -419,7 +419,7 @@ void Editor::RefreshColourPalette(Palette &pal, bool want) { void Editor::RefreshStyleData() { if (!stylesValid) { stylesValid = true; - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); if (surface) { vs.Refresh(*surface); RefreshColourPalette(palette, true); @@ -499,7 +499,7 @@ Point Editor::LocationFromPosition(int pos) { int line = pdoc->LineFromPosition(pos); int lineVisible = cs.DisplayFromDoc(line); //Platform::DebugPrintf("line=%d\n", line); - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); LineLayout *ll = RetrieveLineLayout(line); if (surface && ll) { // -1 because of adding in for visible lines in following loop. @@ -552,7 +552,7 @@ int Editor::PositionFromLocation(Point pt) { int lineDoc = cs.DocFromDisplay(visibleLine); if (lineDoc >= pdoc->LinesTotal()) return pdoc->Length(); - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); int retVal = 0; LineLayout *ll = RetrieveLineLayout(lineDoc); if (surface && ll) { @@ -600,7 +600,7 @@ int Editor::PositionFromLocationClose(Point pt) { return INVALID_POSITION; if (lineDoc >= pdoc->LinesTotal()) return INVALID_POSITION; - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); LineLayout *ll = RetrieveLineLayout(lineDoc); if (surface && ll) { LayoutLine(lineDoc, surface, vs, ll, wrapWidth); @@ -634,7 +634,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(IsUnicodeMode()); + AutoSurface surface(CodePage()); LineLayout *ll = RetrieveLineLayout(lineDoc); int retVal = 0; if (surface && ll) { @@ -935,7 +935,7 @@ void Editor::MoveCaretInsideView(bool ensureVisible) { int Editor::DisplayFromPosition(int pos) { int lineDoc = pdoc->LineFromPosition(pos); int lineDisplay = cs.DisplayFromDoc(lineDoc); - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); LineLayout *ll = RetrieveLineLayout(lineDoc); if (surface && ll) { LayoutLine(lineDoc, surface, vs, ll, wrapWidth); @@ -1272,7 +1272,7 @@ bool Editor::WrapLines() { wrapWidth = rcTextArea.Width(); // Ensure all of the document is styled. pdoc->EnsureStyledTo(pdoc->Length()); - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); if (surface) { int lastLineToWrap = pdoc->LinesTotal(); while (docLineLastWrapped <= lastLineToWrap) { @@ -2356,10 +2356,10 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) { if (!pfr) return 0; - AutoSurface surface(pfr->hdc, IsUnicodeMode()); + AutoSurface surface(pfr->hdc, CodePage()); if (!surface) return 0; - AutoSurface surfaceMeasure(pfr->hdcTarget, IsUnicodeMode()); + AutoSurface surfaceMeasure(pfr->hdcTarget, CodePage()); if (!surfaceMeasure) { return 0; } @@ -2531,7 +2531,7 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) { int Editor::TextWidth(int style, const char *text) { RefreshStyleData(); - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); if (surface) { return surface->WidthText(vs.styles[style].font, text, strlen(text)); } else { @@ -2935,7 +2935,7 @@ void Editor::CheckModificationForWrap(DocModification mh) { if (wrapState != eWrapNone) { int lineDoc = pdoc->LineFromPosition(mh.position); if (mh.linesAdded == 0) { - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); LineLayout *ll = RetrieveLineLayout(lineDoc); if (surface && ll) { LayoutLine(lineDoc, surface, vs, ll, wrapWidth); @@ -3303,7 +3303,7 @@ void Editor::CursorUpOrDown(int direction, bool extend) { int Editor::StartEndDisplayLine(int pos, bool start) { RefreshStyleData(); int line = pdoc->LineFromPosition(pos); - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); LineLayout *ll = RetrieveLineLayout(line); int posRet = INVALID_POSITION; if (surface && ll) { @@ -4554,6 +4554,13 @@ bool Editor::IsUnicodeMode() const { return pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage); } +int Editor::CodePage() const { + if (pdoc) + return pdoc->dbcsCodePage; + else + return 0; +} + static bool ValidMargin(unsigned long wParam) { return wParam < ViewStyle::margins; } diff --git a/src/Editor.h b/src/Editor.h index 714efc755..5517065b6 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -138,18 +138,20 @@ class AutoSurface { private: Surface *surf; public: - AutoSurface(bool unicodeMode) { + AutoSurface(int codePage) { surf = Surface::Allocate(); if (surf) { surf->Init(); - surf->SetUnicodeMode(unicodeMode); + surf->SetUnicodeMode(SC_CP_UTF8 == codePage); + surf->SetDBCSMode(codePage); } } - AutoSurface(SurfaceID sid, bool unicodeMode) { + AutoSurface(SurfaceID sid, int codePage) { surf = Surface::Allocate(); if (surf) { surf->Init(sid); - surf->SetUnicodeMode(unicodeMode); + surf->SetUnicodeMode(SC_CP_UTF8 == codePage); + surf->SetDBCSMode(codePage); } } ~AutoSurface() { @@ -459,6 +461,8 @@ protected: // ScintillaBase subclass needs access to much of Editor void EnsureLineVisible(int lineDoc, bool enforcePolicy); int ReplaceTarget(bool replacePatterns, const char *text, int length=-1); + int CodePage() const; + virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0; public: diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 9519001b4..6e2ff1b1a 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -322,6 +322,7 @@ public: void FlushCachedState(); void SetUnicodeMode(bool unicodeMode_); + void SetDBCSMode(int codePage); }; SurfaceImpl::SurfaceImpl() : @@ -692,6 +693,10 @@ void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { unicodeMode=unicodeMode_; } +void SurfaceImpl::SetDBCSMode(int) { + // No action on window as automatically handled by system. +} + Surface *Surface::Allocate() { return new SurfaceImpl; } @@ -1051,6 +1056,7 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { if (surfaceItem) { surfaceItem->Init(pDrawItem->hDC); //surf->SetUnicodeMode(unicodeMode); + //surf->SetDBCSMode(codePage); int left = pDrawItem->rcItem.left; PRectangle rc(left + 1, pDrawItem->rcItem.top, left + 1 + widthPix, pDrawItem->rcItem.bottom); diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index fb9ec1633..983a5906f 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -379,7 +379,7 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) { pps = &ps; ::BeginPaint(MainHWND(), pps); } - AutoSurface surfaceWindow(pps->hdc, IsUnicodeMode()); + AutoSurface surfaceWindow(pps->hdc, CodePage()); if (surfaceWindow) { rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom); PRectangle rcClient = GetClientRectangle(); @@ -1426,7 +1426,7 @@ void ScintillaWin::ImeStartComposition() { int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel; if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1 sizeZoomed = 2; - AutoSurface surface(IsUnicodeMode()); + AutoSurface surface(CodePage()); int deviceHeight = sizeZoomed; if (surface) { deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72; @@ -1587,7 +1587,7 @@ void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) { void ScintillaWin::RealizeWindowPalette(bool inBackGround) { RefreshStyleData(); HDC hdc = ::GetDC(MainHWND()); - AutoSurface surfaceWindow(hdc, IsUnicodeMode()); + AutoSurface surfaceWindow(hdc, CodePage()); if (surfaceWindow) { int changes = surfaceWindow->SetPalette(&palette, inBackGround); if (changes > 0) @@ -1606,7 +1606,7 @@ void ScintillaWin::FullPaint() { rcPaint = GetClientRectangle(); paintingAllText = true; HDC hdc = ::GetDC(MainHWND()); - AutoSurface surfaceWindow(hdc, IsUnicodeMode()); + AutoSurface surfaceWindow(hdc, CodePage()); if (surfaceWindow) { Paint(surfaceWindow, rcPaint); surfaceWindow->Release(); @@ -1929,7 +1929,7 @@ sptr_t PASCAL ScintillaWin::CTWndProc( } else if (iMessage == WM_PAINT) { PAINTSTRUCT ps; ::BeginPaint(hWnd, &ps); - AutoSurface surfaceWindow(ps.hdc, ctp->unicodeMode); + AutoSurface surfaceWindow(ps.hdc, ctp->codePage); if (surfaceWindow) { ctp->PaintCT(surfaceWindow); surfaceWindow->Release(); |