diff options
-rw-r--r-- | gtk/ScintillaGTK.cxx | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index d14bc57ac..7a2fa7406 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -46,6 +46,7 @@ class ScintillaGTK : public ScintillaBase { GdkEventButton evbtn; bool capturedMouse; bool dragWasDropped; + char *primarySelectionCopy; static GdkAtom clipboard_atom; @@ -80,6 +81,7 @@ private: virtual void Paste(); virtual void CreateCallTipWindow(PRectangle rc); virtual void AddToPopUp(const char *label, int cmd=0, bool enabled=true); + bool OwnPrimarySelection(); virtual void ClaimSelection(); void ReceivedSelection(GtkSelectionData *selection_data); void ReceivedDrop(GtkSelectionData *selection_data); @@ -142,7 +144,8 @@ enum { ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) : adjustmentv(0), adjustmenth(0), pasteBuffer(0), pasteBufferIsRectangular(false), - capturedMouse(false), dragWasDropped(false) { + capturedMouse(false), dragWasDropped(false), + primarySelectionCopy(0) { sci = sci_; wMain = GTK_WIDGET(sci); @@ -150,6 +153,7 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) : } ScintillaGTK::~ScintillaGTK() { + delete []primarySelectionCopy; } gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/, ScintillaGTK *sciThis) { @@ -539,16 +543,26 @@ void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) { } } +bool ScintillaGTK::OwnPrimarySelection() { + return (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) \ + == GTK_WIDGET(wDraw.GetID())->window); +} + 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_selection_owner_set(GTK_WIDGET(wDraw.GetID()), - GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); - } else if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == - GTK_WIDGET(wDraw.GetID())->window) { - gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); - } + if (currentPos != anchor) { + gtk_selection_owner_set(GTK_WIDGET(wDraw.GetID()), + GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); + delete []primarySelectionCopy; + primarySelectionCopy = NULL; + } else if (OwnPrimarySelection()) { + if (primarySelectionCopy == NULL) + gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); + } else { + delete []primarySelectionCopy; + primarySelectionCopy = NULL; + } } void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) { @@ -557,7 +571,6 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) { if (((selection_data->selection == clipboard_atom)|| (selection_data->selection == GDK_SELECTION_PRIMARY)) && (selection_data->length > 0)) { - //if (selection_data->length > 0) { char *ptr = reinterpret_cast<char *>(selection_data->data); unsigned int len = selection_data->length; for (unsigned int i=0; i<static_cast<unsigned int>(selection_data->length); i++) { @@ -566,14 +579,16 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) { } pdoc->BeginUndoAction(); int selStart = SelectionStart(); - ClearSelection(); + if (selection_data->selection != GDK_SELECTION_PRIMARY) { + ClearSelection(); + } // Check for "\n\0" ending to string indicating that selection is rectangular bool isRectangular = ((selection_data->length > 1) && (ptr[selection_data->length-1] == 0 && ptr[selection_data->length-2] == '\n')); if (isRectangular) { PasteRectangular(selStart, ptr, len); } else { - pdoc->InsertString(currentPos, ptr, len); + pdoc->InsertString(currentPos, ptr, len); SetEmptySelection(currentPos + len); } pdoc->EndUndoAction(); @@ -597,11 +612,16 @@ void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) { } void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, char *text, bool isRectangular) { -//Platform::DebugPrintf("GetSelection %d\n", info); char *selBuffer = text; + char *tmpBuffer = NULL; // Buffer to be freed + if (selection_data->selection == GDK_SELECTION_PRIMARY) { -//Platform::DebugPrintf("GetSelection PRIMARY\n"); - selBuffer = CopySelectionRange(); + if (primarySelectionCopy != NULL) { + selBuffer = primarySelectionCopy; + } else { + tmpBuffer = CopySelectionRange(); + selBuffer = tmpBuffer; + } } if (info == TARGET_STRING) { @@ -613,15 +633,10 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, ch // All other tested aplications behave benignly by ignoring the \0. if (isRectangular) len++; -//Platform::DebugPrintf("GetSelection STRING %d %s %d\n", selection_data->type, -//isRectangular ? "rect" : "stream", len); gtk_selection_data_set(selection_data, GDK_SELECTION_TYPE_STRING, 8, reinterpret_cast<unsigned char *>(selBuffer), len); } else if ((info == TARGET_TEXT) || (info == TARGET_COMPOUND_TEXT)) { -//Platform::DebugPrintf("GetSelection TEXT\n"); -//if (info == TARGET_COMPOUND_TEXT) -//Platform::DebugPrintf("GetSelection COMPOUND\n"); guchar *text; GdkAtom encoding; gint format; @@ -633,11 +648,7 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, ch gdk_free_compound_text(text); } -//Platform::DebugPrintf("GetSelection FREE\n"); - if (selection_data->selection == GDK_SELECTION_PRIMARY) { - delete []selBuffer; - } -//Platform::DebugPrintf("GetSelection END\n"); + delete []tmpBuffer; } void ScintillaGTK::Resize(int width, int height) { @@ -711,10 +722,14 @@ gint ScintillaGTK::Press(GtkWidget *, GdkEventButton *event, ScintillaGTK *sciTh event->state & GDK_CONTROL_MASK, event->state & GDK_CONTROL_MASK); } else if (event->button == 2) { - // Grab the primary selection - gtk_selection_convert(GTK_WIDGET(sciThis->wDraw.GetID()), - GDK_SELECTION_PRIMARY, - gdk_atom_intern("STRING", FALSE), event->time); + // Grab the primary selection if it exists + Position pos = sciThis->PositionFromLocation(pt); + if (sciThis->OwnPrimarySelection() && sciThis->primarySelectionCopy == NULL) + sciThis->primarySelectionCopy = sciThis->CopySelectionRange(); + + sciThis->SetSelection(pos, pos); + gtk_selection_convert(GTK_WIDGET(sciThis->wDraw.GetID()), GDK_SELECTION_PRIMARY, + gdk_atom_intern("STRING", FALSE), event->time); } else if (event->button == 3 && sciThis->displayPopupMenu) { // PopUp menu // Convert to screen |