📄 scintillagtk.cxx.svn-base
字号:
#endif
}
void ScintillaGTK::NotifyParent(SCNotification scn) {
scn.nmhdr.hwndFrom = PWidget(wMain);
scn.nmhdr.idFrom = GetCtrlID();
#if GLIB_MAJOR_VERSION < 2
gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL],
GetCtrlID(), &scn);
#else
g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0,
GetCtrlID(), &scn);
#endif
}
void ScintillaGTK::NotifyKey(int key, int modifiers) {
SCNotification scn = {0};
scn.nmhdr.code = SCN_KEY;
scn.ch = key;
scn.modifiers = modifiers;
NotifyParent(scn);
}
void ScintillaGTK::NotifyURIDropped(const char *list) {
SCNotification scn = {0};
scn.nmhdr.code = SCN_URIDROPPED;
scn.text = list;
NotifyParent(scn);
}
const char *CharacterSetID(int characterSet);
const char *ScintillaGTK::CharacterSetID() const {
return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet);
}
int ScintillaGTK::KeyDefault(int key, int modifiers) {
if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT)) {
if (key < 256) {
NotifyKey(key, modifiers);
return 0;
} else {
// Pass up to container in case it is an accelerator
NotifyKey(key, modifiers);
return 0;
}
} else {
// Pass up to container in case it is an accelerator
NotifyKey(key, modifiers);
return 0;
}
//Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers);
}
void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
#ifndef USE_GTK_CLIPBOARD
copyText.Copy(selectedText);
gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
atomClipboard,
GDK_CURRENT_TIME);
#else
GtkClipboard *clipBoard;
clipBoard = gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
return;
SelectionText *clipText = new SelectionText();
clipText->Copy(selectedText);
gtk_clipboard_set_with_data(clipBoard, clipboardTargets, nClipboardTargets,
ClipboardGetSelection, ClipboardClearSelection, clipText);
#endif
}
void ScintillaGTK::Copy() {
if (currentPos != anchor) {
#ifndef USE_GTK_CLIPBOARD
CopySelectionRange(©Text);
gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
atomClipboard,
GDK_CURRENT_TIME);
#else
GtkClipboard *clipBoard;
clipBoard = gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
return;
SelectionText *clipText = new SelectionText();
CopySelectionRange(clipText);
gtk_clipboard_set_with_data(clipBoard, clipboardTargets, nClipboardTargets,
ClipboardGetSelection, ClipboardClearSelection, clipText);
#endif
#if PLAT_GTK_WIN32
if (selType == selRectangle) {
::OpenClipboard(NULL);
::SetClipboardData(cfColumnSelect, 0);
::CloseClipboard();
}
#endif
}
}
void ScintillaGTK::Paste() {
atomSought = atomUTF8;
gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
atomClipboard, atomSought, GDK_CURRENT_TIME);
}
void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {
if (!ct.wCallTip.Created()) {
ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP);
ct.wDraw = gtk_drawing_area_new();
GtkWidget *widcdrw = PWidget(ct.wDraw); // // No code inside the G_OBJECT macro
gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), widcdrw);
#if GLIB_MAJOR_VERSION < 2
gtk_signal_connect(GTK_OBJECT(widcdrw), "expose_event",
GtkSignalFunc(ScintillaGTK::ExposeCT), &ct);
gtk_signal_connect(GTK_OBJECT(widcdrw), "button_press_event",
GtkSignalFunc(ScintillaGTK::PressCT), static_cast<void *>(this));
#else
g_signal_connect(G_OBJECT(widcdrw), "expose_event",
G_CALLBACK(ScintillaGTK::ExposeCT), &ct);
g_signal_connect(G_OBJECT(widcdrw), "button_press_event",
G_CALLBACK(ScintillaGTK::PressCT), static_cast<void *>(this));
#endif
gtk_widget_set_events(widcdrw,
GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
}
gtk_drawing_area_size(GTK_DRAWING_AREA(PWidget(ct.wDraw)),
rc.Width(), rc.Height());
ct.wDraw.Show();
if (PWidget(ct.wCallTip)->window) {
gdk_window_resize(PWidget(ct.wCallTip)->window, rc.Width(), rc.Height());
}
}
void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) {
char fulllabel[200];
strcpy(fulllabel, "/");
strcat(fulllabel, label);
GtkItemFactoryCallback menuSig = GtkItemFactoryCallback(PopUpCB);
GtkItemFactoryEntry itemEntry = {
fulllabel, NULL,
menuSig,
cmd,
const_cast<gchar *>(label[0] ? "<Item>" : "<Separator>"),
#if GTK_MAJOR_VERSION >= 2
NULL
#endif
};
gtk_item_factory_create_item(GTK_ITEM_FACTORY(popup.GetID()),
&itemEntry, this, 1);
if (cmd) {
GtkWidget *item = gtk_item_factory_get_widget_by_action(
reinterpret_cast<GtkItemFactory *>(popup.GetID()), cmd);
if (item)
gtk_widget_set_sensitive(item, enabled);
}
}
bool ScintillaGTK::OwnPrimarySelection() {
return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY)
== GTK_WIDGET(PWidget(wMain))->window) &&
(GTK_WIDGET(PWidget(wMain))->window != NULL));
}
void ScintillaGTK::ClaimSelection() {
// X Windows has a 'primary selection' as well as the clipboard.
// Whenever the user selects some text, we become the primary selection
if (currentPos != anchor && GTK_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) {
primarySelection = true;
gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
primary.Free();
} else if (OwnPrimarySelection()) {
primarySelection = true;
if (primary.s == NULL)
gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
} else {
primarySelection = false;
primary.Free();
}
}
// Detect rectangular text, convert line ends to current mode, convert from or to UTF-8
void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) {
char *data = reinterpret_cast<char *>(selectionData->data);
int len = selectionData->length;
GdkAtom selectionType = selectionData->type;
// Return empty string if selection is not a string
if ((selectionType != GDK_TARGET_STRING) && (selectionType != atomUTF8)) {
char *empty = new char[1];
empty[0] = '\0';
selText.Set(empty, 0, SC_CP_UTF8, 0, false);
return;
}
// Check for "\n\0" ending to string indicating that selection is rectangular
bool isRectangular;
#if PLAT_GTK_WIN32
isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
#else
isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n'));
#endif
char *dest;
if (selectionType == GDK_TARGET_STRING) {
dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
if (IsUnicodeMode()) {
// Unknown encoding so assume in Latin1
char *destPrevious = dest;
dest = UTF8FromLatin1(dest, len);
selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular);
delete []destPrevious;
} else {
// Assume buffer is in same encoding as selection
selText.Set(dest, len, pdoc->dbcsCodePage,
vs.styles[STYLE_DEFAULT].characterSet, isRectangular);
}
} else { // UTF-8
dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular);
#ifdef USE_CONVERTER
const char *charSetBuffer = CharacterSetID();
if (!IsUnicodeMode() && *charSetBuffer) {
//fprintf(stderr, "Convert to locale %s\n", CharacterSetID());
// Convert to locale
dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
selText.Set(dest, len, pdoc->dbcsCodePage,
vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular);
}
#endif
}
}
void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
if ((selection_data->selection == atomClipboard) ||
(selection_data->selection == GDK_SELECTION_PRIMARY)) {
if ((atomSought == atomUTF8) && (selection_data->length <= 0)) {
atomSought = atomString;
gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
selection_data->selection, atomSought, GDK_CURRENT_TIME);
} else if ((selection_data->length > 0) &&
((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8))) {
SelectionText selText;
GetGtkSelectionText(selection_data, selText);
pdoc->BeginUndoAction();
if (selection_data->selection != GDK_SELECTION_PRIMARY) {
ClearSelection();
}
int selStart = SelectionStart();
if (selText.rectangular) {
PasteRectangular(selStart, selText.s, selText.len);
} else {
pdoc->InsertString(currentPos, selText.s, selText.len);
SetEmptySelection(currentPos + selText.len);
}
pdoc->EndUndoAction();
EnsureCaretVisible();
}
}
// else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type),
// (int)(atomUTF8));
Redraw();
}
void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
dragWasDropped = true;
if (selection_data->type == atomUriList || selection_data->type == atomDROPFILES_DND) {
char *ptr = new char[selection_data->length + 1];
ptr[selection_data->length] = '\0';
memcpy(ptr, selection_data->data, selection_data->length);
NotifyURIDropped(ptr);
delete []ptr;
} else if ((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8)) {
if (selection_data->length > 0) {
SelectionText selText;
GetGtkSelectionText(selection_data, selText);
DropAt(posDrop, selText.s, false, selText.rectangular);
}
} else if (selection_data->length > 0) {
//~ fprintf(stderr, "ReceivedDrop other %p\n", static_cast<void *>(selection_data->type));
}
Redraw();
}
void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) {
#if PLAT_GTK_WIN32
// Many native win32 programs require \n line endings, so make a copy of
// the clip text now with newlines converted. Use { } to hide symbols
// from code below
SelectionText *newline_normalized = NULL;
{
int tmpstr_len;
char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF);
newline_normalized = new SelectionText();
newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular);
text = newline_normalized;
}
#endif
#if GTK_MAJOR_VERSION >= 2
// Convert text to utf8 if it isn't already
SelectionText *converted = 0;
if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {
const char *charSet = ::CharacterSetID(text->characterSet);
if (*charSet) {
int new_len;
char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false);
converted = new SelectionText();
converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular);
text = converted;
}
}
// Here is a somewhat evil kludge.
// As I can not work out how to store data on the clipboard in multiple formats
// and need some way to mark the clipping as being stream or rectangular,
// the terminating \0 is included in the length for rectangular clippings.
// All other tested aplications behave benignly by ignoring the \0.
// The #if is here because on Windows cfColumnSelect clip entry is used
// instead as standard indicator of rectangularness (so no need to kludge)
int len = strlen(text->s);
#if PLAT_GTK_WIN32 == 0
if (text->rectangular)
len++;
#endif
if (info == TARGET_UTF8_STRING) {
gtk_selection_data_set_text(selection_data, text->s, len);
} else {
gtk_selection_data_set(selection_data,
static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING),
8, reinterpret_cast<unsigned char *>(text->s), len);
}
delete converted;
#else /* Gtk 1 */
char *selBuffer = text->s;
char *tmputf = 0;
if ((info == TARGET_UTF8_STRING) || (info == TARGET_STRING)) {
int len = strlen(selBuffer);
#ifdef USE_CONVERTER
// Possible character set conversion
const char *charSetBuffer = ::CharacterSetID(text->characterSet);
if (info == TARGET_UTF8_STRING) {
//fprintf(stderr, "Copy to clipboard as UTF-8\n");
if (text->codePage != SC_CP_UTF8) {
// Convert to UTF-8
//fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer);
tmputf = ConvertText(&len, selBuffer, len, "UTF-8", charSetBuffer, false);
selBuffer = tmputf;
}
} else if (info == TARGET_STRING) {
if (text->codePage == SC_CP_UTF8) {
//fprintf(stderr, "Convert to locale %s\n", charSetBuffer);
// Convert to locale
tmputf = ConvertText(&len, selBuffer, len, charSetBuffer, "UTF-8", true);
selBuffer = tmputf;
}
}
#endif
// Here is a somewhat evil kludge.
// As I can not work out how to store data on the clipboard in multiple formats
// and need some way to mark the clipping as being stream or rectangular,
// the terminating \0 is included in the length for rectangular clippings.
// All other tested aplications behave benignly by ignoring the \0.
// The #if is here because on Windows cfColumnSelect clip entry is used
// instead as standard indicator of rectangularness (so no need to kludge)
#if PLAT_GTK_WIN32 == 0
if (text->rectangular)
len++;
#endif
gtk_selection_data_set(selection_data,
(info == TARGET_STRING) ?
static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING) : atomUTF8,
8, reinterpret_cast<unsigned char *>(selBuffer),
len);
} else if ((info == TARGET_TEXT) || (info == TARGET_COMPOUND_TEXT)) {
guchar *text;
GdkAtom encoding;
gint format;
gint new_length;
gdk_string_to_compound_text(reinterpret_cast<char *>(selBuffer),
&encoding, &format, &text, &new_length);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -