aboutsummaryrefslogtreecommitdiffhomepage
path: root/gtk/ScintillaGTK.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/ScintillaGTK.cxx')
-rw-r--r--gtk/ScintillaGTK.cxx233
1 files changed, 160 insertions, 73 deletions
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index b066ab7b2..d75072d27 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -79,7 +79,9 @@ class ScintillaGTK : public ScintillaBase {
int scrollBarHeight;
// Because clipboard access is asynchronous, copyText is created by Copy
+#if GTK_MAJOR_VERSION == 1
SelectionText copyText;
+#endif
SelectionText primary;
@@ -90,10 +92,10 @@ class ScintillaGTK : public ScintillaBase {
GtkWidgetClass *parentClass;
- GdkAtom atomClipboard;
+ static GdkAtom atomClipboard;
+ static GdkAtom atomUTF8;
+ static GdkAtom atomString;
GdkAtom atomSought;
- GdkAtom atomUTF8;
- GdkAtom atomString;
#if PLAT_GTK_WIN32
CLIPFORMAT cfColumnSelect;
@@ -162,10 +164,15 @@ private:
virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
bool OwnPrimarySelection();
virtual void ClaimSelection();
- void GetGtkSelectionText(const GtkSelectionData *selectionData, SelectionText &selText);
+ void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText);
void ReceivedSelection(GtkSelectionData *selection_data);
void ReceivedDrop(GtkSelectionData *selection_data);
- void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
+ static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
+#if GTK_MAJOR_VERSION >= 2
+ static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data);
+ static void ClipboardClearSelection(GtkClipboard* clip, void *data);
+#endif
+
void UnclaimSelection(GdkEventSelection *selection_event);
void Resize(int width, int height);
@@ -262,6 +269,19 @@ enum {
TARGET_UTF8_STRING
};
+GdkAtom ScintillaGTK::atomClipboard = GDK_NONE;
+GdkAtom ScintillaGTK::atomUTF8 = GDK_NONE;
+GdkAtom ScintillaGTK::atomString = GDK_NONE;
+
+static const GtkTargetEntry clipboardTargets[] = {
+ { "UTF8_STRING", 0, TARGET_UTF8_STRING },
+ { "STRING", 0, TARGET_STRING },
+// { "TEXT", 0, TARGET_TEXT },
+// { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
+ { "text/uri-list", 0, 0 },
+};
+static const gint nClipboardTargets = sizeof(clipboardTargets) / sizeof(clipboardTargets[0]);
+
static GtkWidget *PWidget(Window &w) {
return reinterpret_cast<GtkWidget *>(w.GetID());
}
@@ -289,11 +309,6 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
sci = sci_;
wMain = GTK_WIDGET(sci);
- atomClipboard = GDK_NONE;
- atomSought = GDK_NONE;
- atomUTF8 = GDK_NONE;
- atomString = GDK_NONE;
-
#if PLAT_GTK_WIN32
// There does not seem to be a real standard for indicating that the clipboard
// contains a rectangular selection, so copy Developer Studio.
@@ -678,27 +693,23 @@ void ScintillaGTK::Initialise() {
gtk_widget_grab_focus(PWidget(wMain));
- static const GtkTargetEntry targets[] = {
- { "UTF8_STRING", 0, TARGET_UTF8_STRING },
- { "STRING", 0, TARGET_STRING },
-// { "TEXT", 0, TARGET_TEXT },
-// { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
- { "text/uri-list", 0, 0 },
- };
- static const gint n_targets = sizeof(targets) / sizeof(targets[0]);
-
gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
- targets, n_targets);
+ clipboardTargets, nClipboardTargets);
- atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE);
- atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE);
- atomString = gdk_atom_intern("STRING", FALSE);
+ if (atomClipboard == GDK_NONE)
+ atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE);
+ if (atomUTF8 == GDK_NONE)
+ atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE);
+ if (atomString == GDK_NONE)
+ atomString = gdk_atom_intern("STRING", FALSE);
+#if GTK_MAJOR_VERSION == 1
gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), atomClipboard,
- targets, n_targets);
+ clipboardTargets, nClipboardTargets);
+#endif
gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain)),
- GTK_DEST_DEFAULT_ALL, targets, n_targets,
+ GTK_DEST_DEFAULT_ALL, clipboardTargets, nClipboardTargets,
static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE));
SetTicking(true);
@@ -1125,18 +1136,46 @@ int ScintillaGTK::KeyDefault(int key, int modifiers) {
}
void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
- copyText.Copy(selectedText.s, selectedText.len);
+#if GTK_MAJOR_VERSION == 1
+ copyText.Copy(selectedText.s, selectedText.len, selectedText.characterSet);
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.s, selectedText.len, selectedText.characterSet);
+
+ gtk_clipboard_set_with_data(clipBoard, clipboardTargets, nClipboardTargets,
+ ClipboardGetSelection, ClipboardClearSelection, clipText);
+
+#endif
}
void ScintillaGTK::Copy() {
if (currentPos != anchor) {
+#if GTK_MAJOR_VERSION == 1
CopySelectionRange(&copyText);
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);
@@ -1210,14 +1249,14 @@ void ScintillaGTK::ClaimSelection() {
primarySelection = true;
gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
- primary.Set(0, 0);
+ primary.Set(0, 0, 0);
} else if (OwnPrimarySelection()) {
primarySelection = true;
if (primary.s == NULL)
gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
} else {
primarySelection = false;
- primary.Set(0, 0);
+ primary.Set(0, 0, 0);
}
}
@@ -1285,7 +1324,7 @@ char *ConvertLineEnds(size_t *pLenOut, const char *s, size_t len, int eolMode) {
}
// Detect rectangular text, convert line ends to current mode, convert from or to UTF-8
-void ScintillaGTK::GetGtkSelectionText(const GtkSelectionData *selectionData, SelectionText &selText) {
+void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) {
char *data = reinterpret_cast<char *>(selectionData->data);
size_t len = selectionData->length;
GdkAtom selectionType = selectionData->type;
@@ -1294,35 +1333,56 @@ void ScintillaGTK::GetGtkSelectionText(const GtkSelectionData *selectionData, Se
if ((selectionType != GDK_TARGET_STRING) && (selectionType != atomUTF8)) {
char *empty = new char[1];
empty[0] = '\0';
- selText.Set(empty,0);
+ selText.Set(empty, 0, SC_CP_UTF8);
return;
}
// Check for "\n\0" ending to string indicating that selection is rectangular
- bool isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n'));
- // Need to convert to correct newline form for this file: win32gtk *always* returns
- // only \n line delimiter from clipboard, and linux/unix gtk may also not send the
- // form that matches the document (this is probably not effectively standardized by X)
+ bool isRectangular;
+#if PLAT_GTK_WIN32
+ isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
+#else
+ isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n'));
+#endif
+
+#if GTK_MAJOR_VERSION >= 2
+ char *dest;
+ char *utf8 = reinterpret_cast<char*>(gtk_selection_data_get_text(selectionData));
+ if (utf8 != NULL) {
+ dest = ConvertLineEnds(&len, utf8, strlen(utf8), pdoc->eolMode);
+ g_free(utf8);
+ }
+ else {
+ dest = new char[1];
+ dest[0] = '\0';
+ len = 0;
+ }
+ selText.Set(dest, len, SC_CP_UTF8, isRectangular);
+#else
char *dest = ConvertLineEnds(&len, data, len, pdoc->eolMode);
- selText.Set(dest, len, isRectangular);
+ if (selectionType == GDK_TARGET_STRING)
+ selText.Set(dest, len, pdoc->dbcsCodePage, isRectangular);
+ else
+ selText.Set(dest, len, SC_CP_UTF8, isRectangular);
+#endif
#if !PLAT_GTK_WIN32
// Possible character set conversion
const char *charSetBuffer = CharacterSetID();
if (*charSetBuffer) {
if (IsUnicodeMode()) {
- if (selectionType == GDK_TARGET_STRING) {
+ if (selText.characterSet != SC_CP_UTF8) {
// Convert to UTF-8
//fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer);
- dest = ConvertText(&len, dest, len, "UTF-8", charSetBuffer);
- selText.Set(dest, len, isRectangular);
+ dest = ConvertText(&len, selText.s, selText.len, "UTF-8", charSetBuffer);
+ selText.Set(dest, len, SC_CP_UTF8, selText.rectangular);
}
} else {
- if (selectionType == atomUTF8) {
+ if (selText.characterSet == SC_CP_UTF8) {
//fprintf(stderr, "Convert to locale %s\n", charSetBuffer);
// Convert to locale
- dest = ConvertText(&len, dest, len, charSetBuffer, "UTF-8");
- selText.Set(dest, len, isRectangular);
+ dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8");
+ selText.Set(dest, len, pdoc->dbcsCodePage, selText.rectangular);
}
}
}
@@ -1340,9 +1400,6 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8))) {
SelectionText selText;
GetGtkSelectionText(selection_data, selText);
-#if PLAT_GTK_WIN32
- selText.rectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
-#endif
pdoc->BeginUndoAction();
int selStart = SelectionStart();
@@ -1379,53 +1436,61 @@ void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
Redraw();
}
+
+
void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) {
- if (selection_data->selection == GDK_SELECTION_PRIMARY) {
- if (primary.s == NULL) {
- CopySelectionRange(&primary);
- }
- text = &primary;
- }
+#if GTK_MAJOR_VERSION >= 2
+ // Convert text to utf8 if it isn't already
+ if (text->characterSet != SC_CP_UTF8) {
+ const char *charSet = ::CharacterSetID(text->characterSet);
+ size_t new_len;
+ char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet);
+ text->Set(tmputf, new_len, SC_CP_UTF8, text->rectangular);
+ }
+
+ // 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
+ gtk_selection_data_set_text(selection_data, text->s, len);
+
+#else /* Gtk 1 */
char *selBuffer = text->s;
#if PLAT_GTK_WIN32
- // win32gtk requires \n delimited lines and doesn't work right with
- // other line formats, so make a copy of the clip text now with
- // newlines converted
- char *tmpstr = new char[text->len + 1];
- char *sptr = selBuffer;
- char *dptr = tmpstr;
- while (*sptr != '\0') {
- if (pdoc->eolMode == SC_EOL_CR && *sptr == '\r') {
- *dptr++ = '\n';
- sptr++;
- } else if (pdoc->eolMode != SC_EOL_CR && *sptr == '\r') {
- sptr++;
- } else {
- *dptr++ = *sptr++;
- }
- }
- *dptr = '\0';
+
+ // Many native win32 programs require \n line endings,
+ // so make a copy of the clip text now with newlines converted
+
+ size_t new_len;
+ char *tmpstr = ConvertLineEnds(&new_len, selBuffer, text->len, SC_EOL_LF);
selBuffer = tmpstr;
#endif
-
char *tmputf = 0;
if ((info == TARGET_UTF8_STRING) || (info == TARGET_STRING)) {
size_t len = strlen(selBuffer);
#if !PLAT_GTK_WIN32
// Possible character set conversion
- const char *charSetBuffer = CharacterSetID();
+ const char *charSetBuffer = ::CharacterSetID(text->characterSet);
if (info == TARGET_UTF8_STRING) {
//fprintf(stderr, "Copy to clipboard as UTF-8\n");
- if (!IsUnicodeMode()) {
+ if (text->characterSet != 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);
selBuffer = tmputf;
}
} else if (info == TARGET_STRING) {
- if (IsUnicodeMode()) {
+ if (text->characterSet == SC_CP_UTF8) {
//fprintf(stderr, "Convert to locale %s\n", charSetBuffer);
// Convert to locale
tmputf = ConvertText(&len, selBuffer, len, charSetBuffer, "UTF-8");
@@ -1466,14 +1531,26 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
#if PLAT_GTK_WIN32
delete []tmpstr;
#endif
+#endif /* Gtk >= 2 */
+}
+
+#if GTK_MAJOR_VERSION >= 2
+void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) {
+ GetSelection(selection_data, info, static_cast<SelectionText*>(data));
}
+void ScintillaGTK::ClipboardClearSelection(GtkClipboard *, void *data) {
+ SelectionText *obj = static_cast<SelectionText*>(data);
+ delete obj;
+}
+#endif
+
void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) {
//Platform::DebugPrintf("UnclaimSelection\n");
if (selection_event->selection == GDK_SELECTION_PRIMARY) {
//Platform::DebugPrintf("UnclaimPrimarySelection\n");
if (!OwnPrimarySelection()) {
- primary.Set(0, 0);
+ primary.Set(0, 0, 0);
primarySelection = false;
FullPaint();
}
@@ -2104,7 +2181,17 @@ void ScintillaGTK::SelectionGet(GtkWidget *widget,
GtkSelectionData *selection_data, guint info, guint) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
//Platform::DebugPrintf("Selection get\n");
- sciThis->GetSelection(selection_data, info, &sciThis->copyText);
+ if (selection_data->selection == GDK_SELECTION_PRIMARY) {
+ if (sciThis->primary.s == NULL) {
+ sciThis->CopySelectionRange(&sciThis->primary);
+ }
+ sciThis->GetSelection(selection_data, info, &sciThis->primary);
+ }
+#if GTK_MAJOR_VERSION == 1 /* Gtk 2+ uses GtkClipboard for non-primary selections. */
+ else {
+ sciThis->GetSelection(selection_data, info, &sciThis->copyText);
+ }
+#endif
}
gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event) {