aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gtk/PlatGTK.cxx124
-rw-r--r--include/Platform.h1
-rw-r--r--include/Scintilla.h1
-rw-r--r--include/Scintilla.iface3
-rw-r--r--src/CallTip.cxx8
-rw-r--r--src/CallTip.h18
-rw-r--r--src/Editor.cxx31
-rw-r--r--src/Editor.h12
-rw-r--r--win32/PlatWin.cxx6
-rw-r--r--win32/ScintillaWin.cxx10
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();