📄 platgtk.cxx.svn-base
字号:
// Scintilla source code edit control
// PlatGTK.cxx - implementation of platform facilities on GTK+/Linux
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <glib.h>
#include <gmodule.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "Platform.h"
#include "Scintilla.h"
#include "ScintillaWidget.h"
#include "UniConversion.h"
#include "XPM.h"
/* GLIB must be compiled with thread support, otherwise we
will bail on trying to use locks, and that could lead to
problems for someone. `glib-config --libs gthread` needs
to be used to get the glib libraries for linking, otherwise
g_thread_init will fail */
#define USE_LOCK defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE)
/* Use fast way of getting char data on win32 to work around problems
with gdk_string_extents. */
#define FAST_WAY
#ifdef G_OS_WIN32
#define snprintf _snprintf
#endif
#if GTK_MAJOR_VERSION >= 2
#define USE_PANGO 1
#include "Converter.h"
#endif
#ifdef _MSC_VER
// Ignore unreferenced local functions in GTK+ headers
#pragma warning(disable: 4505)
#endif
enum encodingType { singleByte, UTF8, dbcs};
struct LOGFONT {
int size;
bool bold;
bool italic;
int characterSet;
char faceName[300];
};
#if USE_LOCK
static GMutex *fontMutex = NULL;
static void InitializeGLIBThreads() {
if (!g_thread_supported()) {
g_thread_init(NULL);
}
}
#endif
static void FontMutexAllocate() {
#if USE_LOCK
if (!fontMutex) {
InitializeGLIBThreads();
fontMutex = g_mutex_new();
}
#endif
}
static void FontMutexFree() {
#if USE_LOCK
if (fontMutex) {
g_mutex_free(fontMutex);
fontMutex = NULL;
}
#endif
}
static void FontMutexLock() {
#if USE_LOCK
g_mutex_lock(fontMutex);
#endif
}
static void FontMutexUnlock() {
#if USE_LOCK
if (fontMutex) {
g_mutex_unlock(fontMutex);
}
#endif
}
// On GTK+ 1.x holds a GdkFont* but on GTK+ 2.x can hold a GdkFont* or a
// PangoFontDescription*.
class FontHandle {
int width[128];
encodingType et;
public:
int ascent;
GdkFont *pfont;
#ifdef USE_PANGO
PangoFontDescription *pfd;
int characterSet;
#endif
FontHandle(GdkFont *pfont_) {
et = singleByte;
ascent = 0;
pfont = pfont_;
#ifdef USE_PANGO
pfd = 0;
characterSet = -1;
#endif
ResetWidths(et);
}
#ifdef USE_PANGO
FontHandle(PangoFontDescription *pfd_, int characterSet_) {
et = singleByte;
ascent = 0;
pfont = 0;
pfd = pfd_;
characterSet = characterSet_;
ResetWidths(et);
}
#endif
~FontHandle() {
if (pfont)
gdk_font_unref(pfont);
pfont = 0;
#ifdef USE_PANGO
if (pfd)
pango_font_description_free(pfd);
pfd = 0;
#endif
}
void ResetWidths(encodingType et_) {
et = et_;
for (int i=0; i<=127; i++) {
width[i] = 0;
}
}
int CharWidth(unsigned char ch, encodingType et_) {
int w = 0;
FontMutexLock();
if ((ch <= 127) && (et == et_)) {
w = width[ch];
}
FontMutexUnlock();
return w;
}
void SetCharWidth(unsigned char ch, int w, encodingType et_) {
if (ch <= 127) {
FontMutexLock();
if (et != et_) {
ResetWidths(et_);
}
width[ch] = w;
FontMutexUnlock();
}
}
};
// X has a 16 bit coordinate space, so stop drawing here to avoid wrapping
static const int maxCoordinate = 32000;
static FontHandle *PFont(Font &f) {
return reinterpret_cast<FontHandle *>(f.GetID());
}
static GtkWidget *PWidget(WindowID id) {
return reinterpret_cast<GtkWidget *>(id);
}
static GtkWidget *PWidget(Window &w) {
return PWidget(w.GetID());
}
Point Point::FromLong(long lpoint) {
return Point(
Platform::LowShortFromLong(lpoint),
Platform::HighShortFromLong(lpoint));
}
Palette::Palette() {
used = 0;
allowRealization = false;
allocatedPalette = 0;
allocatedLen = 0;
size = 100;
entries = new ColourPair[size];
}
Palette::~Palette() {
Release();
delete []entries;
entries = 0;
}
void Palette::Release() {
used = 0;
delete [](reinterpret_cast<GdkColor *>(allocatedPalette));
allocatedPalette = 0;
allocatedLen = 0;
delete []entries;
size = 100;
entries = new ColourPair[size];
}
// This method either adds a colour to the list of wanted colours (want==true)
// or retrieves the allocated colour back to the ColourPair.
// This is one method to make it easier to keep the code for wanting and retrieving in sync.
void Palette::WantFind(ColourPair &cp, bool want) {
if (want) {
for (int i=0; i < used; i++) {
if (entries[i].desired == cp.desired)
return;
}
if (used >= size) {
int sizeNew = size * 2;
ColourPair *entriesNew = new ColourPair[sizeNew];
for (int j=0; j<size; j++) {
entriesNew[j] = entries[j];
}
delete []entries;
entries = entriesNew;
size = sizeNew;
}
entries[used].desired = cp.desired;
entries[used].allocated.Set(cp.desired.AsLong());
used++;
} else {
for (int i=0; i < used; i++) {
if (entries[i].desired == cp.desired) {
cp.allocated = entries[i].allocated;
return;
}
}
cp.allocated.Set(cp.desired.AsLong());
}
}
void Palette::Allocate(Window &w) {
if (allocatedPalette) {
gdk_colormap_free_colors(gtk_widget_get_colormap(PWidget(w)),
reinterpret_cast<GdkColor *>(allocatedPalette),
allocatedLen);
delete [](reinterpret_cast<GdkColor *>(allocatedPalette));
allocatedPalette = 0;
allocatedLen = 0;
}
GdkColor *paletteNew = new GdkColor[used];
allocatedPalette = paletteNew;
gboolean *successPalette = new gboolean[used];
if (paletteNew) {
allocatedLen = used;
int iPal = 0;
for (iPal = 0; iPal < used; iPal++) {
paletteNew[iPal].red = entries[iPal].desired.GetRed() * (65535 / 255);
paletteNew[iPal].green = entries[iPal].desired.GetGreen() * (65535 / 255);
paletteNew[iPal].blue = entries[iPal].desired.GetBlue() * (65535 / 255);
paletteNew[iPal].pixel = entries[iPal].desired.AsLong();
}
gdk_colormap_alloc_colors(gtk_widget_get_colormap(PWidget(w)),
paletteNew, allocatedLen, FALSE, TRUE,
successPalette);
for (iPal = 0; iPal < used; iPal++) {
entries[iPal].allocated.Set(paletteNew[iPal].pixel);
}
}
delete []successPalette;
}
static const char *CharacterSetName(int characterSet) {
switch (characterSet) {
case SC_CHARSET_ANSI:
return "iso8859-*";
case SC_CHARSET_DEFAULT:
return "iso8859-*";
case SC_CHARSET_BALTIC:
return "iso8859-13";
case SC_CHARSET_CHINESEBIG5:
return "*-*";
case SC_CHARSET_EASTEUROPE:
return "*-2";
case SC_CHARSET_GB2312:
return "gb2312.1980-*";
case SC_CHARSET_GREEK:
return "*-7";
case SC_CHARSET_HANGUL:
return "ksc5601.1987-*";
case SC_CHARSET_MAC:
return "*-*";
case SC_CHARSET_OEM:
return "*-*";
case SC_CHARSET_RUSSIAN:
return "*-r";
case SC_CHARSET_CYRILLIC:
return "*-cp1251";
case SC_CHARSET_SHIFTJIS:
return "jisx0208.1983-*";
case SC_CHARSET_SYMBOL:
return "*-*";
case SC_CHARSET_TURKISH:
return "*-9";
case SC_CHARSET_JOHAB:
return "*-*";
case SC_CHARSET_HEBREW:
return "*-8";
case SC_CHARSET_ARABIC:
return "*-6";
case SC_CHARSET_VIETNAMESE:
return "*-*";
case SC_CHARSET_THAI:
return "iso8859-11";
case SC_CHARSET_8859_15:
return "iso8859-15";
default:
return "*-*";
}
}
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,
char *charset, int charset_len) {
// supported font strings include:
// foundary-fontface-isoxxx-x
// fontface-isoxxx-x
// foundary-fontface
// fontface
if (strchr(fontName, '-')) {
char tmp[300];
char *d1 = NULL, *d2 = NULL, *d3 = NULL;
strncpy(tmp, fontName, sizeof(tmp) - 1);
d1 = strchr(tmp, '-');
// we know the first dash exists
d2 = strchr(d1 + 1, '-');
if (d2)
d3 = strchr(d2 + 1, '-');
if (d3) {
// foundary-fontface-isoxxx-x
*d2 = '\0';
foundary[0] = '-';
foundary[1] = '\0';
strncpy(faceName, tmp, foundary_len - 1);
strncpy(charset, d2 + 1, charset_len - 1);
} else if (d2) {
// fontface-isoxxx-x
*d1 = '\0';
strcpy(foundary, "-*-");
strncpy(faceName, tmp, faceName_len - 1);
strncpy(charset, d1 + 1, charset_len - 1);
} else {
// foundary-fontface
foundary[0] = '-';
foundary[1] = '\0';
strncpy(faceName, tmp, faceName_len - 1);
strncpy(charset, CharacterSetName(characterSet), charset_len - 1);
}
} else {
strncpy(foundary, "-*-", foundary_len);
strncpy(faceName, fontName, faceName_len - 1);
strncpy(charset, CharacterSetName(characterSet), charset_len - 1);
}
}
static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, int size, bool bold, bool italic) {
memset(&lf, 0, sizeof(lf));
lf.size = size;
lf.bold = bold;
lf.italic = italic;
lf.characterSet = characterSet;
strncpy(lf.faceName, faceName, sizeof(lf.faceName) - 1);
}
/**
* Create a hash from the parameters for a font to allow easy checking for identity.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -