diff options
Diffstat (limited to 'Build/source/texk/xdvik/gui/selection.c')
-rw-r--r-- | Build/source/texk/xdvik/gui/selection.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/gui/selection.c b/Build/source/texk/xdvik/gui/selection.c new file mode 100644 index 00000000000..e0bef1e5f1e --- /dev/null +++ b/Build/source/texk/xdvik/gui/selection.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2004 Stefan Ulrich + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "xdvi-config.h" +#include "xdvi.h" + +#include <string.h> + +#include <X11/Xatom.h> +#include <X11/StringDefs.h> + +#if HAVE_X11_XMU_XMU_H +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/Xmu.h> +#endif + +#include "events.h" +#include "util.h" +#include "encodings.h" +#include "message-window.h" +#include "selection.h" +#include "statusline.h" + +/* + * Set the current X selection (i.e. the primary selection AKA XA_PRIMARY). + * Most of this is copied from Asente/Converse/Swick: X Window System Toolkit Manual + */ + +/* This is file scope since deliver_selection_cb() needs access to it. + * I guess we could also store it in an Atom, but why bother ... + */ +static char *m_selection_text = NULL; +static char *m_cvt_selection_text = NULL; +static size_t m_selection_size = 0; + +/* helper routine */ +static Atom +fetch_atom(Widget w, const char *name) +{ + Atom a; + XrmValue source, dest; + + source.size = strlen(name) + 1; + source.addr = (char *)name; + dest.size = sizeof a; + dest.addr = (caddr_t)&a; + + (void)XtConvertAndStore(w, XtRString, &source, XtRAtom, &dest); + return a; +} + +/* Lose the selection */ +static void +lose_selection_cb(Widget w, Atom *selection) +{ + UNUSED(w); + UNUSED(selection); + + text_change_region(TEXT_SEL_CLEAR, NULL); +} + +static char * +utf8_to_native_encoding(const char *utf8) +{ + static const char *text_encoding = NULL; + + /* convert to user encoding, similar to search-internal.c */ + if (text_encoding == NULL) { + text_encoding = get_text_encoding(); + } + + if (memicmp(text_encoding, "iso-8859-1", strlen("iso-8859-1")) == 0 + || memicmp(text_encoding, "iso8859-1", strlen("iso8859-1")) == 0) { + return str_utf8_to_iso_8859_1(utf8); + } + else if (memicmp(text_encoding, "utf-8", strlen("utf-8")) != 0 + && memicmp(text_encoding, "utf8", strlen("utf8")) != 0) { + /* some other encoding */ + return iconv_convert_string("utf-8", text_encoding, utf8); + } + /* fallback */ + return xstrdup(utf8); +} + +/* Deliver the selection. Only supports XA_STRING. */ +static Boolean +deliver_selection_cb(Widget w, + Atom *selection, + Atom *target, + Atom *type, + XtPointer *value, + unsigned long *length, + int *format) +{ + Atom targets = fetch_atom(w, "TARGETS"); + Atom utf8_string = fetch_atom(w, "UTF8_STRING"); + + TRACE_GUI((stderr, "selection target = %lu (%s)", + *target, XGetAtomName(DISP, *target))); + + if (m_selection_text == NULL) /* paranoia */ + return False; + +#if HAVE_X11_XMU_XMU_H + if (*target == targets) { + /* TARGETS handling copied from xclipboard.c */ + Atom* targetP; + Atom* std_targets; + unsigned long std_length; + XSelectionRequestEvent* req = XtGetSelectionRequest(w, *selection, (XtRequestId)NULL); + + TRACE_GUI((stderr, "Selection type: targets")); + XmuConvertStandardSelection(w, req->time, selection, + target, type, (XPointer*)&std_targets, &std_length, format); + *value = XtMalloc(sizeof(Atom)*(std_length + 2)); + targetP = *(Atom**)value; + *length = std_length + 2; + *targetP++ = XA_COMPOUND_TEXT(DISP); + *targetP++ = XA_STRING; + memcpy((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); + XtFree((char*)std_targets); + *type = XA_ATOM; + *format = sizeof(Atom) * 8; + return True; + } + else +#endif + if (*target == utf8_string) { + TRACE_GUI((stderr, "Selection type: UTF8_STRING")); + *type = *target; + *value = (XtPointer)XtNewString(m_selection_text); + /* *value = (XtPointer)m_selection_text; */ + *length = strlen(m_selection_text); + *format = 8; + return True; + } + else if (*target == XA_STRING) { + char *ptr = utf8_to_native_encoding(m_selection_text); + TRACE_GUI((stderr, "Selection type: XA_STRING")); + strncpy(m_cvt_selection_text, ptr, m_selection_size); + m_cvt_selection_text[m_selection_size - 1] = '\0'; /* ensure termination */ + free(ptr); + *type = *target; + *value = (XtPointer)XtNewString(m_cvt_selection_text); + /* *value = (XtPointer)m_selection_text; */ + *length = strlen(m_cvt_selection_text); + *format = 8; + return True; + } +#if HAVE_X11_XMU_XMU_H + else if (*target == XA_COMPOUND_TEXT(DISP) || *target == XA_TEXT(DISP)) { + const char *cl[1]; + char *ptr; + int retval; + + XTextProperty ct; + XICCEncodingStyle style = XStdICCTextStyle; + + TRACE_GUI((stderr, "Selection type: XA_COMPOUND_TEXT")); + ptr = utf8_to_native_encoding(m_selection_text); + strncpy(m_cvt_selection_text, ptr, m_selection_size); + m_cvt_selection_text[m_selection_size - 1] = '\0'; /* ensure termination */ + cl[0] = m_cvt_selection_text; + + *type = *target; + retval = XmbTextListToTextProperty(DISP, (char **)cl, 1, style, &ct); + + if (retval == XNoMemory || retval == XLocaleNotSupported || retval == XConverterNotFound) { + statusline_print(STATUS_MEDIUM, "XmbTextListToTextProperty failed: %d", retval); + return False; + } + + *value = ct.value; + *length = ct.nitems; + *format = 8; + return True; + } +#endif + else { +#if HAVE_X11_XMU_XMU_H + TRACE_GUI((stderr, "Selection type: standard selection")); + if (XmuConvertStandardSelection(w, CurrentTime, selection, + target, type, (XPointer *)value, length, format)) + return True; + else { +#endif + TRACE_GUI((stderr, "Selection type unsupported: %lu (%s)", + (unsigned long)*target, XGetAtomName(DISP, *target))); + statusline_print(STATUS_MEDIUM, + "X client asked for an unsupported selection target type: %lu (%s)", + (unsigned long)*target, XGetAtomName(DISP, *target)); + return False ; +#if HAVE_X11_XMU_XMU_H + } +#endif + } +} + +/* do it */ +Boolean +set_selection(const char *text, Widget w) +{ + /* caller should make sure that text is never longer than 4 * XMaxRequestSize(DISP) - 32 */ + if (m_selection_text == NULL) { + m_selection_size = 4 * XMaxRequestSize(DISP); + m_selection_text = xmalloc(m_selection_size); + m_cvt_selection_text = xmalloc(m_selection_size); + } + strncpy(m_selection_text, text, m_selection_size); + m_selection_text[m_selection_size - 1] = '\0'; /* ensure termination */ + + return XtOwnSelection(w, XA_PRIMARY, XtLastTimestampProcessed(XtDisplay(w)), + deliver_selection_cb, + lose_selection_cb, + (XtSelectionDoneProc)NULL); +} + +void +unset_selection(Widget w) +{ + XtDisownSelection(w, XA_PRIMARY, XtLastTimestampProcessed(XtDisplay(w))); +} + |