home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / selection.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  40.7 KB  |  1,694 lines

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "selection.h"
  20. #include <libi18n.h>
  21. #include <layers.h>
  22. #include <sys/utsname.h>
  23. #include <pwd.h>
  24. #include <Xm/CutPaste.h>    /* for PasteQuote clipboard hackery */
  25. /*#include <Xm/AtomMgr.h>*/
  26.  
  27. #include "intl_csi.h"
  28. #include "felocale.h"
  29.  
  30. static char          *fe_clipboard_text   = NULL;
  31. static char          *fe_clipboard_html   = NULL;
  32. static char          *fe_clipboard_data   = NULL;
  33. static unsigned long  fe_clipboard_dlen   = 0;
  34. static Time           fe_clipboard_time   = 0;
  35. static Widget         fe_clipboard_widget = NULL;
  36. static XP_Bool        fe_clipboard_motif  = False;
  37. static XP_Bool        fe_clipboard_empty  = True;
  38.  
  39. static char          *fe_selection_text   = NULL;
  40. static char          *fe_selection_html   = NULL;
  41. static char          *fe_selection_data   = NULL;
  42. static unsigned long  fe_selection_dlen   = 0;
  43. static Time           fe_selection_time   = 0;
  44. static Widget         fe_selection_widget = NULL;
  45. static MWContext     *fe_selection_ctx    = NULL;
  46. static MWContext     *fe_selection_lost   = NULL;
  47. static XP_Bool        fe_selection_empty  = True;
  48.  
  49. static char fe_clipboard_data_name[] = "NETSCAPE_HTML";
  50. static char fe_clipboard_html_name[] = "HTML";
  51. static char fe_clipboard_text_name[] = "STRING";
  52. static char fe_clipboard_app_name[] = "MOZILLA";
  53.  
  54. #define XFE_CCP_DATA (fe_clipboard_data_name)
  55. #define XFE_CCP_HTML (fe_clipboard_html_name)
  56. #define XFE_CCP_TEXT (fe_clipboard_text_name)
  57. #define XFE_CCP_NAME (fe_clipboard_app_name)
  58.  
  59. /* Selections
  60.  */
  61.  
  62. static Boolean
  63. fe_selection_converter (Widget widget, Atom *selection, Atom *target,
  64.             Atom *type_ret, XtPointer *value_ret,
  65.             unsigned long *length_ret, int *format_ret)
  66. {
  67.   Display *dpy = XtDisplay (widget);
  68.   XTextProperty tmp_prop;
  69.   int status;
  70.   MWContext *context = fe_WidgetToMWContext (widget);
  71.  
  72.   Atom COMPOUND_TEXT = XmInternAtom(dpy, "COMPOUND_TEXT", False);
  73.   Atom XA_TARGETS   = XmInternAtom (dpy, "TARGETS", False);
  74.   Atom XA_TIMESTAMP = XmInternAtom (dpy, "TIMESTAMP", False);
  75.   Atom XA_NETSCAPE  = XmInternAtom (dpy, XFE_CCP_DATA, False);
  76.   Atom XA_HTML      = XmInternAtom (dpy, XFE_CCP_HTML, False);
  77.   Atom XA_TEXT      = XmInternAtom (dpy, "TEXT", False);
  78.   Atom XA_LENGTH    = XmInternAtom (dpy, "LENGTH", False);
  79.   Atom XA_FILE_NAME = XmInternAtom (dpy, "FILE_NAME", False);
  80.   Atom XA_OWNER_OS  = XmInternAtom (dpy, "OWNER_OS", False);
  81.   Atom XA_HOST_NAME = XmInternAtom (dpy, "HOST_NAME", False);
  82.   Atom XA_USER      = XmInternAtom (dpy, "USER", False);
  83.   Atom XA_CLASS     = XmInternAtom (dpy, "CLASS", False);
  84.   Atom XA_NAME      = XmInternAtom (dpy, "NAME", False);
  85.   Atom XA_CLIENT_WINDOW = XmInternAtom (dpy, "CLIENT_WINDOW", False);
  86.   Atom XA_PROCESS   = XmInternAtom (dpy, "PROCESS", False);
  87. #if 0
  88.   Atom XA_CHARACTER_POSITION = XmInternAtom (dpy, "CHARACTER_POSITION", False);
  89. #endif
  90.  
  91.   char *text = 0;
  92.   char *html = 0;
  93.   char *data = 0;
  94.   unsigned long dlen = 0;
  95.   Time time = 0;
  96.   char *loc;
  97.   INTL_CharSetInfo c;
  98.  
  99.   XP_ASSERT (context);
  100.  
  101.   c = LO_GetDocumentCharacterSetInfo(context);
  102.  
  103.   if (*selection == XA_PRIMARY) {
  104.       text = fe_selection_text;
  105.       html = fe_selection_html;
  106.       data = fe_selection_data;
  107.       dlen = fe_selection_dlen;
  108.       time = fe_selection_time;
  109.   }
  110.   else {
  111. #ifdef DEBUG_rhess
  112.       fprintf(stderr, "fe_selection_converter::[ CLIPBOARD ] -- NOT\n");
  113. #endif
  114.       return False;
  115.   }
  116.  
  117.   if (!text && !html && !data) {
  118. #ifdef DEBUG_rhess
  119.       fprintf(stderr, "fe_selection_converter::[ NULL ]\n");
  120. #endif
  121.       *value_ret = NULL;
  122.       *length_ret = 0;
  123.       *type_ret = None;
  124.       *format_ret = 0;
  125.       return False;
  126.   }
  127.  
  128.   /* I can't believe the contortions we need to go through here!! */
  129.  
  130.   if (*target == XA_TARGETS)
  131.     {
  132.       Atom *av = (Atom *) malloc (sizeof (Atom) * 20);
  133.       int ac = 0;
  134.       av [ac++] = XA_TARGETS;
  135.       av [ac++] = XA_TIMESTAMP;
  136.       av [ac++] = XA_NETSCAPE;
  137.       av [ac++] = XA_HTML;
  138.       av [ac++] = XA_TEXT;
  139.       av [ac++] = XA_STRING;
  140.       av [ac++] = XA_LENGTH;
  141. #if 0
  142.       av [ac++] = XA_CHARACTER_POSITION;
  143. #endif
  144.       av [ac++] = XA_FILE_NAME;
  145.       av [ac++] = XA_OWNER_OS;
  146.       av [ac++] = XA_HOST_NAME;
  147.       av [ac++] = XA_USER;
  148.       av [ac++] = XA_CLASS;
  149.       av [ac++] = XA_NAME;
  150.       av [ac++] = XA_CLIENT_WINDOW;
  151.       av [ac++] = XA_PROCESS;
  152.       av [ac++] = COMPOUND_TEXT;
  153.  
  154.       /* Other types that might be interesting (from the R6 ICCCM):
  155.  
  156.      XA_MULTIPLE        (this is a pain and nobody uses it)
  157.      XA_LINE_NUMBER        start and end lines of the selection
  158.      XA_COLUMN_NUMBER    start and end column of the selection
  159.      XA_BACKGROUND        a list of Pixel values
  160.      XA_FOREGROUND        a list of Pixel values
  161.      XA_PIXMAP        a list of pixmap IDs (of the images?)
  162.      XA_DRAWABLE        a list of drawable IDs (?)
  163.  
  164.      XA_COMPOUND_TEXT    for text
  165.  
  166.      Hairy Image Conversions:
  167.      XA_APPLE_PICT        for images
  168.      XA_POSTSCRIPT
  169.      XA_ENCAPSULATED_POSTSCRIPT aka _ADOBE_EPS
  170.      XA_ENCAPSULATED_POSTSCRIPT_INTERCHANGE aka _ADOBE_EPSI
  171.      XA_ODIF        ISO Office Document Interchange Format
  172.        */
  173.       *value_ret = av;
  174.       *length_ret = ac;
  175.       *type_ret = XA_ATOM;
  176.       *format_ret = 32;
  177.       return True;
  178.    }
  179.   else if (*target == XA_TIMESTAMP)
  180.     {
  181.       Time *timestamp;
  182.       timestamp = (Time *) malloc (sizeof (Time));
  183.       *timestamp = time;
  184.       *value_ret = (char *) timestamp;
  185.       *length_ret = 1;
  186.       *type_ret = XA_TIMESTAMP;
  187.       *format_ret = 32;
  188.       return True;
  189.     }
  190.   else if (*target == XA_NETSCAPE)
  191.       {
  192.           if (dlen > 0) {
  193.               text = XP_ALLOC(dlen+1);
  194.               
  195.               memcpy(text, data, dlen);
  196.               
  197.               *value_ret = text;
  198.               *length_ret = dlen;
  199.           }
  200.           else {
  201.               *value_ret = NULL;
  202.               *length_ret = 0;
  203.           }
  204.           *type_ret = XA_NETSCAPE;
  205.           *format_ret = 8;
  206.           return True;
  207.       }
  208.   else if (*target == XA_HTML)
  209.       {
  210.           *value_ret = strdup (html);
  211.           *length_ret = strlen (html);
  212.           *type_ret = XA_HTML;
  213.           *format_ret = 8;
  214.           return True;
  215.       }
  216.   else if (((*target == XA_TEXT) && (INTL_GetCSIWinCSID(c) == CS_LATIN1)) ||
  217.            (*target == XA_STRING))
  218.     {
  219.       *value_ret = strdup (text);
  220.       *length_ret = strlen (text);
  221.       *type_ret = XA_STRING;
  222.       *format_ret = 8;
  223.       return True;
  224.     }
  225.   else if (*target == XA_TEXT)
  226.     {
  227.       loc = (char *) fe_ConvertToLocaleEncoding (INTL_GetCSIWinCSID(c),
  228.                                                  (unsigned char *) text);
  229.       status = XmbTextListToTextProperty (dpy, &loc, 1, XStdICCTextStyle,
  230.                                           &tmp_prop);
  231.       if (loc != text)
  232.         {
  233.           XP_FREE (loc);
  234.         }
  235.       if (status == Success)
  236.         {
  237.           *value_ret = (XtPointer) tmp_prop.value;
  238.           *length_ret = tmp_prop.nitems;
  239.           *type_ret = tmp_prop.encoding;    /* STRING or COMPOUND_TEXT */
  240.           *format_ret = tmp_prop.format;
  241.         }
  242.       else
  243.         {
  244.           *value_ret = NULL;
  245.           *length_ret = 0;
  246.           return False;
  247.         }
  248.       return True;
  249.     }
  250.   else if (*target == COMPOUND_TEXT)
  251.     {
  252.       loc = (char *) fe_ConvertToLocaleEncoding (INTL_GetCSIWinCSID(c),
  253.                                                  (unsigned char *) text);
  254.       status = XmbTextListToTextProperty (dpy, &loc, 1, XCompoundTextStyle,
  255.                                           &tmp_prop);
  256.       if (loc != text)
  257.         {
  258.           XP_FREE (loc);
  259.         }
  260.       if (status == Success)
  261.         {
  262.           *value_ret = (XtPointer) tmp_prop.value;
  263.           *length_ret = tmp_prop.nitems;
  264.           *type_ret = COMPOUND_TEXT;
  265.           *format_ret = 8;
  266.         }
  267.       else
  268.         {
  269.           *value_ret = NULL;
  270.           *length_ret = 0;
  271.           return False;
  272.         }
  273.       return True;
  274.     }
  275.   else if (*target == XA_LENGTH)
  276.     {
  277.       int *len = (int *) malloc (sizeof (int));
  278.       *len = strlen (text);
  279.       *value_ret = len;
  280.       *length_ret = 1;
  281.       *type_ret = XA_INTEGER;
  282.       *format_ret = 32;
  283.       return True;
  284.     }
  285. #if 0
  286.   else if (*target == XA_CHARACTER_POSITION)
  287.     {
  288.       int32 *ends = (int32 *) malloc (sizeof (int32) * 2);
  289.       LO_Element *s, *e;
  290.       CL_Layer *layer;
  291.       
  292.       /* oops, this doesn't actually give me character positions -
  293.      just LO_Elements and indexes into them. */
  294.       LO_GetSelectionEndpoints (context, &s, &e, &ends[0], &ends[1], &layer);
  295.       *value_ret = ends;
  296.       *length_ret = 2;
  297.       *type_ret = XA_INTEGER;
  298.       *format_ret = 32;
  299.       return True;
  300.     }
  301. #endif
  302.   else if (*target == XA_FILE_NAME)
  303.     {
  304.       History_entry *current = SHIST_GetCurrent (&context->hist);
  305.       if (!current || !current->address)
  306.     return False;
  307.       *value_ret = strdup (current->address);
  308.       *length_ret = strlen (current->address);
  309.       *type_ret = XA_STRING;
  310.       *format_ret = 8;
  311.       return True;
  312.     }
  313.   else if (*target == XA_OWNER_OS)
  314.     {
  315.       char *os;
  316.       struct utsname uts;
  317.       if (uname (&uts) < 0)
  318.     os = "uname failed";
  319.       else
  320.     os = uts.sysname;
  321.       *value_ret = strdup (os);
  322.       *length_ret = strlen (os);
  323.       *type_ret = XA_STRING;
  324.       *format_ret = 8;
  325.       return True;
  326.     }
  327.   else if (*target == XA_HOST_NAME)
  328.     {
  329.       char name [255];
  330.       if (gethostname (name, sizeof (name)))
  331.     return False;
  332.       *value_ret = strdup (name);
  333.       *length_ret = strlen (name);
  334.       *type_ret = XA_STRING;
  335.       *format_ret = 8;
  336.       return True;
  337.     }
  338.   else if (*target == XA_USER)
  339.     {
  340.       struct passwd *pw = getpwuid (geteuid ());
  341.       char *real_uid = (pw ? pw->pw_name : "");
  342.       char *user_uid = getenv ("LOGNAME");
  343.       if (! user_uid) user_uid = getenv ("USER");
  344.       if (! user_uid) user_uid = real_uid;
  345.       if (! user_uid)
  346.     return False;
  347.       *value_ret = strdup (user_uid);
  348.       *length_ret = strlen (user_uid);
  349.       *type_ret = XA_STRING;
  350.       *format_ret = 8;
  351.       return True;
  352.     }
  353.   else if (*target == XA_CLASS)
  354.     {
  355.       *value_ret = strdup (fe_progclass);
  356.       *length_ret = strlen (fe_progclass);
  357.       *type_ret = XA_STRING;
  358.       *format_ret = 8;
  359.       return True;
  360.     }
  361.   else if (*target == XA_NAME)
  362.     {
  363.       *value_ret = strdup (fe_progname);
  364.       *length_ret = strlen (fe_progname);
  365.       *type_ret = XA_STRING;
  366.       *format_ret = 8;
  367.       return True;
  368.     }
  369.   else if (*target == XA_CLIENT_WINDOW)
  370.     {
  371.       Window *window;
  372.       window = (Window *) malloc (sizeof (Window));
  373.       *window = XtWindow (CONTEXT_WIDGET (context));
  374.       *value_ret = window;
  375.       *length_ret = 1;
  376.       *type_ret = XA_WINDOW;
  377.       *format_ret = 32;
  378.       return True;
  379.     }
  380.   else if (*target == XA_PROCESS)
  381.     {
  382.       pid_t *pid;
  383.       pid = (pid_t *) malloc (sizeof (pid_t));
  384.       *pid = getpid ();
  385.       *value_ret = pid;
  386.       *length_ret = 1;
  387.       *type_ret = XA_INTEGER;
  388.       *format_ret = 32;
  389.       return True;
  390.     }
  391.   else if (*target == XA_COLORMAP)
  392.     {
  393.       Colormap *cmap;
  394.       cmap = (Colormap *) malloc (sizeof (Colormap));
  395.       *cmap = fe_cmap(context);
  396.       *value_ret = cmap;
  397.       *length_ret = 1;
  398.       *type_ret = XA_COLORMAP;
  399.       *format_ret = 32;
  400.       return True;
  401.     }
  402.  
  403.   return False;
  404. }
  405.  
  406. static Boolean
  407. fe_clipboard_converter (Widget widget, Atom *selection, Atom *target,
  408.                         Atom *type_ret, XtPointer *value_ret,
  409.                         unsigned long *length_ret, int *format_ret)
  410. {
  411.     Display *dpy = XtDisplay (widget);
  412.     XTextProperty tmp_prop;
  413.     int status;
  414.     
  415.     Atom XA_TARGETS       = XmInternAtom (dpy, "TARGETS", False);
  416.     Atom XA_TIMESTAMP     = XmInternAtom (dpy, "TIMESTAMP", False);
  417.     Atom XA_TEXT          = XmInternAtom (dpy, "TEXT", False);
  418.     Atom XA_HTML          = XmInternAtom (dpy, XFE_CCP_HTML, False);
  419.     Atom XA_NETSCAPE      = XmInternAtom (dpy, XFE_CCP_DATA, False);
  420.     Atom XA_LENGTH        = XmInternAtom (dpy, "LENGTH", False);
  421.     
  422.     char *text = NULL;
  423.     char *html = NULL;
  424.     char *data = NULL;
  425.     unsigned long dlen = 0;
  426.     Time time = 0;
  427.     
  428.     if (*selection == XmInternAtom (dpy, "CLIPBOARD", False)) {
  429.         text = fe_clipboard_text;
  430.         html = fe_clipboard_html;
  431.         data = fe_clipboard_data;
  432.         dlen = fe_clipboard_dlen;
  433.         time = fe_clipboard_time;
  434.     }
  435.     else {
  436. #ifdef DEBUG_rhess
  437.         fprintf(stderr, "fe_clipboard_converter::[ PRIMARY ] -- NOT\n");
  438. #endif
  439.         return False;
  440.     }
  441.     
  442.     if (!text && !html && !data) {
  443. #ifdef DEBUG_rhess
  444.         fprintf(stderr, "fe_clipboard_converter::[ NULL ]\n");
  445. #endif
  446.         return False;
  447.     }
  448.  
  449.     if (*target == XA_TARGETS)
  450.         {
  451.             Atom *av = (Atom *) malloc (sizeof (Atom) * 20);
  452.             int ac = 0;
  453.             av [ac++] = XA_TARGETS;
  454.             av [ac++] = XA_TIMESTAMP;
  455.             av [ac++] = XA_TEXT;
  456.             av [ac++] = XA_HTML;
  457.             av [ac++] = XA_NETSCAPE;
  458.             av [ac++] = XA_STRING;
  459.             av [ac++] = XA_LENGTH;
  460.             
  461.             *value_ret = av;
  462.             *length_ret = ac;
  463.             *type_ret = XA_ATOM;
  464.             *format_ret = 32;
  465.             return True;
  466.         }
  467.     else if (*target == XA_TIMESTAMP) 
  468.         {
  469.             Time *timestamp;
  470.             timestamp = (Time *) malloc (sizeof (Time));
  471.             *timestamp = time;
  472.             *value_ret = (char *) timestamp;
  473.             *length_ret = 1;
  474.             *type_ret = XA_TIMESTAMP;
  475.             *format_ret = 32;
  476.             return True;
  477.         }
  478.     else if ((*target == XA_TEXT) || 
  479.              (*target == XA_STRING)) 
  480.         {
  481.             if (text) {
  482.                 *value_ret = strdup (text);
  483.                 *length_ret = strlen (text);
  484.                 *type_ret = XA_STRING;
  485.                 *format_ret = 8;
  486.                 return True;
  487.             }
  488.             else {
  489.                 return False;
  490.             }
  491.         }
  492.     else if (*target == XA_HTML)
  493.         {
  494.             if (html) {
  495.                 *value_ret = strdup (html);
  496.                 *length_ret = strlen (html);
  497.                 *type_ret = XA_HTML;
  498.                 *format_ret = 8;
  499.                 return True;
  500.             }
  501.             else {
  502.                 return False;
  503.             }
  504.         }
  505.     else if (*target == XA_NETSCAPE)
  506.         {
  507.             if (dlen > 0) {
  508.                 text = XP_ALLOC(dlen+1);
  509.  
  510.                 memcpy(text, data, dlen);
  511.  
  512.                 *value_ret = text;
  513.                 *length_ret = dlen;
  514.             }
  515.             else {
  516.                 *value_ret = NULL;
  517.                 *length_ret = 0;
  518.             }
  519.             *type_ret = XA_NETSCAPE;
  520.             *format_ret = 8;
  521.             return True;
  522.         }
  523.     else if (*target == XA_LENGTH) 
  524.         {
  525.             int *len = (int *) malloc (sizeof (int));
  526.  
  527.             if (text) {
  528.                 *len = strlen(text);
  529.                 *value_ret = len;
  530.                 *length_ret = 1;
  531.                 *type_ret = XA_INTEGER;
  532.                 *format_ret = 32;
  533.                 return True;
  534.             }
  535.             else {
  536.                 return False;
  537.             }
  538.         }
  539.  
  540.     return False;
  541. }
  542.  
  543. Boolean
  544. fe_own_selection_p (MWContext *context, Boolean clip_p)
  545. {
  546.     Widget mainw = CONTEXT_WIDGET(context);
  547.     Display *dpy = XtDisplay (mainw);
  548.  
  549.     if (clip_p) {
  550.  
  551.         /* Is there an internal clipboard entry? */
  552.         if (fe_clipboard_text) {
  553.             return True;
  554.         } else {
  555.             Atom atom = XmInternAtom (dpy, "CLIPBOARD", False);
  556.  
  557.             /* Is there an external clipboard owner? */
  558.             if (XGetSelectionOwner (dpy, atom)) {
  559.                 return True;
  560.             }
  561.         }
  562.     }
  563.     else {
  564.         /* Do we own the internal selection entry? */
  565.         if (mainw == fe_selection_widget) {
  566.             return True;
  567.         } else {
  568.             Window window = XGetSelectionOwner (dpy, XA_PRIMARY);
  569.             Widget selection_widget = XtWindowToWidget(dpy, window);
  570.  
  571.             /* Is there a selection widget? */
  572.             if (selection_widget) {
  573.                 XmTextPosition left, right;
  574.                 MWContext *ref;
  575.  
  576.                 ref = fe_WidgetToMWContext(selection_widget);
  577.                 ref = XP_GetNonGridContext (ref);
  578.  
  579.                 /* Does the selection widget belong to us?
  580.                  * and is there a true selection?     
  581.                  */
  582.                 if (ref == context
  583.                     && (XmIsText(selection_widget)
  584.                         || XmIsTextField(selection_widget))
  585.                     && XmTextGetSelectionPosition(selection_widget,
  586.                                                   &left, &right)
  587.                     && ((right - left) > 0)) {
  588.                     return True;
  589.                 }
  590.             }
  591.         }
  592.     }
  593.     return False;
  594. }
  595.  
  596. /* Used by XFE_HTMLView::isCommandEnabled() */
  597. Boolean
  598. fe_can_cut (MWContext *context)
  599. {
  600.   return fe_own_selection_p(context, FALSE);
  601. }
  602.  
  603. /* Used by XFE_HTMLView::isCommandEnabled() */
  604. Boolean
  605. fe_can_copy (MWContext *context)
  606. {
  607.   return fe_own_selection_p(context, FALSE);
  608. }
  609.  
  610. /* Used by XFE_HTMLView::isCommandEnabled() */
  611. Boolean
  612. fe_can_paste (MWContext *context)
  613. {
  614.   return fe_own_selection_p(context, TRUE);
  615. }
  616.  
  617. Window
  618. xfe_GetClipboardWindow(Widget focus)
  619. {
  620.     Window target = NULL;
  621.  
  622.     if (fe_clipboard_widget)
  623.         target = XtWindow(fe_clipboard_widget);
  624.     else
  625.         target = XtWindow(focus);
  626.  
  627. #ifdef DEBUG_rhess
  628.     fprintf(stderr, "xfe_GetClipboardWindow::[ %p ][ %p ]\n", 
  629.             XtWindow(focus), target);
  630. #endif
  631.     return target;
  632. }
  633.  
  634. static void
  635. fe_clipboard_loser (Widget widget, Atom *selection)
  636. {
  637.     Display *dpy = XtDisplay (widget);
  638.  
  639.     if (*selection == XmInternAtom (dpy, "CLIPBOARD", False)) {
  640. #ifdef DEBUG_rhess
  641.         fprintf(stderr, "fe_clipboard_loser::[ ]\n");
  642. #endif
  643.         fe_DisownClipboard (widget, 0);
  644.     }
  645.     else {
  646. #ifdef DEBUG_rhess
  647.         fprintf(stderr, "fe_clipboard_loser::[ invalid atom ]\n");
  648. #endif
  649.     }
  650. }
  651.  
  652. static void
  653. fe_selection_loser (Widget widget, Atom *selection)
  654. {
  655.     Display *dpy = XtDisplay (widget);
  656.     MWContext *context = fe_WidgetToMWContext (widget);
  657.  
  658.     if (! context) {
  659.         /* Are you talking to me? */
  660. #ifdef DEBUG_rhess
  661.         fprintf(stderr, "fe_selection_loser::[ NULL ]\n");
  662. #endif
  663.     }
  664.     else if (*selection == XA_PRIMARY) {
  665. #ifdef DEBUG_rhess
  666.         fprintf(stderr, "fe_selection_loser::[ PRIMARY ]\n");
  667. #endif
  668.         fe_DisownPrimarySelection(widget, 0);
  669.     }
  670.     else {
  671. #ifdef DEBUG_rhess
  672.         fprintf(stderr, "fe_selection_loser::[ ERROR ][ invalid target ]\n");
  673. #endif
  674.     }
  675. }
  676.  
  677. static void
  678. fe_set_clipboard(Widget focus, Time time, 
  679.                  char *text, char* html, char* data, unsigned long data_len,
  680.                  XP_Bool motif_p)
  681. {
  682.     if (fe_clipboard_text) {
  683.         XP_FREE(fe_clipboard_text);
  684.         fe_clipboard_text = NULL;
  685.     }
  686.     
  687.     if (fe_clipboard_html) {
  688.         XP_FREE(fe_clipboard_html);
  689.         fe_clipboard_html = NULL;
  690.     }
  691.     
  692.     if (fe_clipboard_data) {
  693.         XP_FREE(fe_clipboard_data);
  694.         fe_clipboard_data = NULL;
  695.     }
  696.  
  697.     if (text) {
  698.         fe_clipboard_text = XP_STRDUP(text);
  699. #ifdef DEBUG_rhess
  700.         fprintf(stderr, 
  701.                 "fe_set_clipboard::[ %d ] TEXT\n", strlen(text));
  702. #endif
  703.     }
  704.  
  705.     if (html) {
  706.         fe_clipboard_html = XP_STRDUP(html);
  707. #ifdef DEBUG_rhess
  708.         fprintf(stderr, 
  709.                 "fe_set_clipboard::[ %d ] HTML\n", strlen(html));
  710. #endif
  711.     }
  712.  
  713.     if (data) {
  714.         fe_clipboard_data = XP_ALLOC(data_len+1);
  715.         memcpy(fe_clipboard_data, data, data_len);
  716. #ifdef DEBUG_rhess
  717.         fprintf(stderr, 
  718.                 "fe_set_clipboard::[ %d ] DATA\n", data_len);
  719. #endif
  720.     }
  721.  
  722.     fe_clipboard_dlen   = data_len;
  723.     fe_clipboard_time   = time;
  724.     fe_clipboard_widget = focus;
  725.     fe_clipboard_motif  = motif_p;
  726.     fe_clipboard_empty  = False;
  727. }
  728.  
  729. static void
  730. fe_set_selection(Widget focus, Time time, 
  731.                  char *text, char* html, char* data, unsigned long data_len,
  732.                  MWContext* ctx
  733.                  )
  734. {
  735.     if (fe_selection_text) {
  736.         XP_FREE(fe_selection_text);
  737.         fe_selection_text = NULL;
  738.     }
  739.  
  740.     if (fe_selection_html) {
  741.         XP_FREE(fe_selection_html);
  742.         fe_selection_html = NULL;
  743.     }
  744.  
  745.     if (fe_selection_data) {
  746.         XP_FREE(fe_selection_data);
  747.         fe_selection_data = NULL;
  748.     }
  749.  
  750.     if (text) {
  751.         fe_selection_text = XP_STRDUP(text);
  752. #ifdef DEBUG_rhess
  753.         fprintf(stderr, 
  754.                 "fe_set_selection::[ %d ] TEXT\n", strlen(text));
  755. #endif
  756.     }
  757.  
  758.     if (html) {
  759.         fe_selection_html = XP_STRDUP(html);
  760. #ifdef DEBUG_rhess
  761.         fprintf(stderr, 
  762.                 "fe_set_selection::[ %d ] HTML\n", strlen(html));
  763. #endif
  764.     }
  765.  
  766.     if (data) {
  767.         fe_selection_data = XP_ALLOC(data_len+1);
  768.         memcpy(fe_selection_data, data, data_len);
  769. #ifdef DEBUG_rhess
  770.         fprintf(stderr, 
  771.                 "fe_set_selection::[ %d ] DATA\n", data_len);
  772. #endif
  773.     }
  774.  
  775.     if (fe_selection_ctx) {
  776.         if (fe_selection_lost) {
  777. #ifdef DEBUG_rhess
  778.             fprintf(stderr, "WARNING... [ lost in fe_set_selection ][ %p ]\n",
  779.                     fe_selection_lost);
  780. #endif            
  781.         }
  782.         fe_selection_lost = fe_selection_ctx;
  783.     }
  784.  
  785.     fe_selection_ctx    = ctx;
  786.     fe_selection_dlen   = data_len;
  787.     fe_selection_time   = time;
  788.     fe_selection_widget = focus;
  789.     fe_selection_empty  = False;
  790. }
  791.  
  792. static void
  793. fe_clear_clipboard()
  794. {
  795.     if (fe_clipboard_empty) {
  796.     }
  797.     else {
  798.         fe_clipboard_empty  = True;
  799. #ifdef DEBUG_rhess
  800.         fprintf(stderr, "fe_clear_clipboard::[ ]\n");
  801. #endif
  802.         if (fe_clipboard_text) {
  803.             XP_FREE( fe_clipboard_text );
  804.             fe_clipboard_text = NULL;
  805.         }
  806.     
  807.         if (fe_clipboard_html) {
  808.             XP_FREE( fe_clipboard_html );
  809.             fe_clipboard_html = NULL;
  810.         }
  811.     
  812.         if (fe_clipboard_data) {
  813.             XP_FREE( fe_clipboard_data );
  814.             fe_clipboard_data = NULL;
  815.         }
  816.     
  817.         fe_clipboard_dlen   = 0;
  818.         fe_clipboard_time   = 0;
  819.         fe_clipboard_widget = NULL;
  820.         fe_clipboard_motif  = False;
  821.     }
  822. }
  823.  
  824. static void
  825. fe_clear_selection()
  826. {
  827.     if (fe_selection_empty) {
  828.     }
  829.     else {
  830.         fe_selection_empty  = True;
  831. #ifdef DEBUG_rhess
  832.         fprintf(stderr, "fe_clear_selection::[ ]\n");
  833. #endif
  834.         if (fe_selection_text) {
  835.             XP_FREE( fe_selection_text );
  836.             fe_selection_text = NULL;
  837.         }
  838.         
  839.         if (fe_selection_html) {
  840.             XP_FREE( fe_selection_html );
  841.             fe_selection_html = NULL;
  842.         }
  843.         
  844.         if (fe_selection_data) {
  845.             XP_FREE( fe_selection_data );
  846.             fe_selection_data = NULL;
  847.         }
  848.     
  849.         if (fe_selection_ctx) {
  850.             if (fe_selection_lost) {
  851. #ifdef DEBUG_rhess
  852.                 fprintf(stderr, 
  853.                         "WARING... [ lost in fe_clear_selection ][ %p ]\n",
  854.                         fe_selection_lost);
  855. #endif            
  856.             }
  857.             fe_selection_lost = fe_selection_ctx;
  858.         }
  859.  
  860.         fe_selection_ctx    = NULL;
  861.         fe_selection_dlen   = 0;
  862.         fe_selection_time   = 0;
  863.         fe_selection_widget = NULL;
  864.     }
  865. }
  866.  
  867. #ifdef EDITOR
  868.  
  869. static void
  870. fe_edt_selection_loser (Widget widget, Atom *selection)
  871. {
  872.     Display *dpy = XtDisplay (widget);
  873.     MWContext *context = fe_WidgetToMWContext (widget);
  874.  
  875.     if (! context) {
  876.         /* Are you talking to me? */
  877. #ifdef DEBUG_rhess
  878.         fprintf(stderr, "fe_edt_selection_loser::[ NULL ]\n");
  879. #endif
  880.     }
  881.     else if (*selection == XA_PRIMARY) {
  882. #ifdef DEBUG_rhess
  883.         fprintf(stderr, "fe_edt_selection_loser::[ PRIMARY ]\n");
  884. #endif
  885.         fe_EditorDisownSelection (context, 0, False);
  886.     }
  887.     else if (*selection == XmInternAtom (dpy, "CLIPBOARD", False)) {
  888. #ifdef DEBUG_rhess
  889.         fprintf(stderr, "fe_edt_selection_loser::[ CLIPBOARD ]\n");
  890. #endif
  891.         fe_EditorDisownSelection (context, 0, True);
  892.     }
  893. }
  894.  
  895. void
  896. fe_OwnEDTSelection (MWContext *context, Time time, Boolean clip_p, 
  897.                     char *text, char *html, char *data, unsigned long data_len)
  898. {
  899.     Widget mainw = CONTEXT_WIDGET(context);
  900.     Display *dpy = XtDisplay (mainw);
  901.     Atom atom = (clip_p ? XmInternAtom (dpy, "CLIPBOARD", False) : XA_PRIMARY);
  902.  
  903.     if (clip_p)
  904.         {
  905. #ifdef DEBUG_rhess
  906.             fprintf(stderr, "fe_own_edt_selection::[ CLIPBOARD ]\n");
  907. #endif
  908.             fe_clear_clipboard();
  909.  
  910.             fe_set_clipboard(mainw, time, 
  911.                              text, html, data, data_len, False);
  912.  
  913.             if (text) {
  914.                 XtOwnSelection (mainw, atom, time,
  915.                                 fe_clipboard_converter,  /* conversion proc */
  916.                                 fe_edt_selection_loser,  /* lost proc */
  917.                                 0);                         /* ACK proc */
  918.             }
  919.         }
  920.     else
  921.         {
  922. #ifdef DEBUG_rhess
  923.             fprintf(stderr, "fe_own_edt_selection::[ PRIMARY ]\n");
  924. #endif
  925.             fe_clear_selection();
  926.  
  927.             fe_set_selection(mainw, time, 
  928.                              text, html, data, data_len, context);
  929.  
  930.             if (text) {
  931.                 XtOwnSelection (mainw, atom, time,
  932.                                 fe_selection_converter,  /* conversion proc */
  933.                                 fe_edt_selection_loser,  /* lost proc */
  934.                                 0);                         /* ACK proc */
  935.             }
  936.         }
  937. }
  938.  
  939. #endif /* EDITOR */
  940.  
  941. void
  942. fe_OwnClipboard(Widget focus, Time time,
  943.                 char* text, char* html, char* data, unsigned long data_len,
  944.                 XP_Bool motif_p)
  945. {
  946.   Display *dpy = XtDisplay (focus);
  947.   Atom atom = XmInternAtom (dpy, "CLIPBOARD", False);
  948.  
  949.   if ((text && (strlen(text) > 0)) || 
  950.       (html && (strlen(html) > 0)) || 
  951.       (data && (data_len > 0))
  952.       ) {
  953.       fe_clear_clipboard();
  954.  
  955.       fe_set_clipboard(focus, time, text, html, data, data_len, motif_p);
  956.  
  957. #ifdef DEBUG_rhess
  958.       if (data) {
  959.           if (html) {
  960.               if (text) {
  961.                   fprintf(stderr, "fe_OwnClipboard::[ %p ][ %d, %d, %d ]\n", 
  962.                           focus, strlen(text), strlen(html), data_len);
  963.               }
  964.               else {
  965.                   fprintf(stderr, "fe_OwnClipboard::[ %p ][ NULL, %d, %d ]\n", 
  966.                           focus, strlen(html), data_len);
  967.               }
  968.           }
  969.           else {
  970.               if (text) {
  971.                   fprintf(stderr, "fe_OwnClipboard::[ %p ][ %d, NULL, %d ]\n", 
  972.                           focus, strlen(text), data_len);
  973.               }
  974.               else {
  975.                   fprintf(stderr, 
  976.                           "fe_OwnClipboard::[ %p ][ NULL, NULL, %d ]\n", 
  977.                           focus, data_len);
  978.               }
  979.           }
  980.       }
  981.       else {
  982.           if (html) {
  983.               if (text) {
  984.                   fprintf(stderr, "fe_OwnClipboard::[ %p ][ %d, %d, NULL ]\n",
  985.                           focus, strlen(text), strlen(html));
  986.               }
  987.               else {
  988.                   fprintf(stderr, 
  989.                           "fe_OwnClipboard::[ %p ][ NULL, %d, NULL ]\n", 
  990.                           focus, strlen(html));
  991.               }
  992.           }
  993.           else {
  994.               if (text) {
  995.                   fprintf(stderr, 
  996.                           "fe_OwnClipboard::[ %p ][ %d, NULL, NULL ]\n",
  997.                           focus, strlen(text));
  998.               }
  999.               else {
  1000.                   fprintf(stderr, 
  1001.                           "fe_OwnClipboard::[ %p ][ NULL, NULL, NULL ]\n", 
  1002.                           focus);
  1003.               }
  1004.           }
  1005.       }
  1006. #endif
  1007.       XtOwnSelection (focus, atom, time,
  1008.                       fe_clipboard_converter,    /* conversion proc */
  1009.                       fe_clipboard_loser,        /* lost proc */
  1010.                       0);                        /* ACK proc */
  1011.   }
  1012.  
  1013. }
  1014.  
  1015. void
  1016. fe_DisownClipboard(Widget focus, Time time)
  1017. {
  1018.     Display *dpy = XtDisplay (focus);
  1019.     Atom atom = XmInternAtom (dpy, "CLIPBOARD", False);
  1020.     XtDisownSelection (focus, atom, time);
  1021.  
  1022.     if (focus == fe_clipboard_widget) {
  1023. #ifdef DEBUG_rhess
  1024.         fprintf(stderr, "fe_DisownClipboard::[ %p ]\n", focus);
  1025. #endif
  1026.         fe_clear_clipboard();
  1027.     }
  1028. }
  1029.  
  1030. void
  1031. fe_OwnPrimarySelection(Widget focus, Time time,
  1032.                        char* text, char* html, 
  1033.                        char* data, unsigned long data_len,
  1034.                        MWContext* context)
  1035. {
  1036.   Display *dpy = XtDisplay (focus);
  1037.   Atom atom = XA_PRIMARY;
  1038.  
  1039.   if ((text && (strlen(text) > 0)) || 
  1040.       (html && (strlen(html) > 0)) || 
  1041.       (data && (data_len > 0))
  1042.       ) {
  1043.       fe_clear_selection();
  1044.  
  1045.       fe_set_selection(focus, time, text, html, data, data_len, context);
  1046.  
  1047. #ifdef DEBUG_rhess
  1048.       if (text) {
  1049.           if (html) {
  1050.               fprintf(stderr, 
  1051.                       "fe_OwnPrimarySelection::[ %p ][ %d, %d, %d ]\n", 
  1052.                       focus, strlen(text), strlen(html), data_len);
  1053.           }
  1054.           else {
  1055.               fprintf(stderr, 
  1056.                       "fe_OwnPrimarySelection::[ %p ][ %d, 0, %d ]\n", 
  1057.                       focus, strlen(text), data_len);
  1058.           }
  1059.       }
  1060.       else {
  1061.           if (html) {
  1062.               fprintf(stderr, "fe_OwnPrimarySelection::[ %p ][ 0, %d, %d ]\n", 
  1063.                       focus, strlen(html), data_len);
  1064.           }
  1065.           else {
  1066.               fprintf(stderr, "fe_OwnPrimarySelection::[ %p ][ 0, 0, %d ]\n", 
  1067.                       focus, data_len);
  1068.           }
  1069.       }
  1070. #endif
  1071.       XtOwnSelection (focus, atom, time,
  1072.                       fe_selection_converter,    /* conversion proc */
  1073.                       fe_selection_loser,        /* lost proc */
  1074.                       0);                        /* ACK proc */
  1075.   }
  1076.  
  1077. }
  1078.  
  1079. void
  1080. fe_DisownPrimarySelection(Widget focus, Time time)
  1081. {
  1082.     Display *dpy = XtDisplay (focus);
  1083.     Atom atom = XA_PRIMARY;
  1084.  
  1085.     XtDisownSelection (focus, atom, time);
  1086.  
  1087.     if (fe_selection_lost) {
  1088.         LO_ClearSelection(fe_selection_lost);
  1089.         fe_selection_lost = NULL;
  1090.     }
  1091.     else {
  1092.         if (focus == fe_selection_widget) {
  1093. #ifdef DEBUG_rhess
  1094.             fprintf(stderr, "fe_DisownPrimarySelection::[ %p ]\n", focus);
  1095. #endif
  1096.             if (fe_selection_empty) {
  1097. #ifdef DEBUG_rhess
  1098.                 fprintf(stderr, "fe_DisownPrimarySelection::[ punt ]\n");
  1099. #endif
  1100.             }
  1101.             else {
  1102.                 if (fe_selection_ctx) {
  1103. #ifdef EDITOR
  1104.                     if ((fe_selection_ctx->type == 
  1105.                          MWContextMessageComposition) ||
  1106.                         (fe_selection_ctx->type == MWContextEditor)) {
  1107.                         if (!fe_ContextHasPopups(fe_selection_ctx)) {
  1108. #ifdef DEBUG_rhess
  1109.                             fprintf(stderr, 
  1110.                                     "fe_DisownPrimarySelection::[ %p ] EDT\n",
  1111.                                     fe_selection_ctx);
  1112. #endif
  1113.                             EDT_ClearSelection(fe_selection_ctx);
  1114.                         }
  1115.                     }
  1116.                     else {
  1117. #endif /* EDITOR */
  1118.  
  1119. #ifdef DEBUG_rhess
  1120.                         fprintf(stderr, 
  1121.                                 "fe_DisownPrimarySelection::[ %p ] LO\n",
  1122.                                 fe_selection_ctx);
  1123. #endif
  1124.                         LO_ClearSelection(fe_selection_ctx);
  1125. #ifdef EDITOR
  1126.                     }
  1127. #endif
  1128.                     fe_selection_ctx = NULL;
  1129.                 }
  1130.                 fe_clear_selection();
  1131.             }
  1132.         }
  1133.     }
  1134. }
  1135.  
  1136. void
  1137. fe_OwnSelection (MWContext *context, Time time, Boolean clip_p)
  1138. {
  1139.     Widget mainw = CONTEXT_WIDGET(context);
  1140.     char *text = (char *) LO_GetSelectionText (context);
  1141.  
  1142.     if (clip_p) {
  1143.         fe_OwnClipboard(mainw, time, 
  1144.                         text, NULL, NULL, 0, False);
  1145.     }
  1146.     else {
  1147.         fe_OwnPrimarySelection(mainw, time, 
  1148.                                text, NULL, NULL, 0, context);
  1149.     }
  1150. }
  1151.  
  1152. void
  1153. fe_DisownSelection (MWContext *context, Time time, Boolean clip_p)
  1154. {
  1155.     Widget mainw = CONTEXT_WIDGET(context);
  1156.  
  1157.     if (clip_p) {
  1158.         if (fe_clipboard_widget) {
  1159. #ifdef DEBUG_rhess
  1160.             fprintf(stderr, "fe_DisownSelection::[ CLIPBOARD ]\n");
  1161. #endif
  1162.             fe_DisownClipboard(mainw, time);
  1163.         }
  1164.     }
  1165.     else {
  1166.         if (fe_selection_widget) {
  1167. #ifdef DEBUG_rhess
  1168.             fprintf(stderr, "fe_DisownSelection::[ PRIMARY ]\n");
  1169. #endif
  1170.             fe_DisownPrimarySelection(mainw, time);
  1171.         }
  1172.     }
  1173. }
  1174.  
  1175.  
  1176. int
  1177. xfe_clipboard_retrieve_work(Widget focus,
  1178.                             char* name,
  1179.                             char** buf, unsigned long* buf_len_a,
  1180.                             Time timestamp) 
  1181. {
  1182.     Display* display  = XtDisplay(focus);
  1183.     Window   window   = xfe_GetClipboardWindow(focus);
  1184.     int      cb_result;
  1185.     long     private_id;
  1186.     int      i;
  1187.  
  1188.     char    *clip_data = NULL;
  1189.     char     work_data[512];
  1190.  
  1191.     unsigned long length   = 0;
  1192.     unsigned long clip_len = 0;
  1193.  
  1194.     cb_result = XmClipboardLock(display, window);
  1195.  
  1196.     if (cb_result != ClipboardSuccess) {
  1197. #ifdef DEBUG_rhess
  1198.         fprintf(stderr, "xfe_clipboard_retrieve::[ FAILED LOCK ]\n");
  1199. #endif
  1200.         *buf_len_a = 0;
  1201.         *buf       = NULL;
  1202.         return cb_result;
  1203.     }
  1204.         
  1205. #ifdef DEBUG_rhess
  1206.     fprintf(stderr, "xfe_clipboard_retrieve::[ LOCK ]\n");
  1207. #endif
  1208.  
  1209.     cb_result = XmClipboardInquireLength(display, window,
  1210.                                          name, &length);
  1211.  
  1212.     if (cb_result != ClipboardSuccess) {
  1213. #ifdef DEBUG_rhess
  1214.         fprintf(stderr, "xfe_clipboard_retrieve::[ FAILED INQUIRE ]\n");
  1215. #endif
  1216.         XmClipboardUnlock(display, window, TRUE);
  1217.  
  1218.         *buf_len_a = 0;
  1219.         *buf       = NULL;
  1220.         return cb_result;
  1221.     }
  1222.         
  1223.     clip_data = XP_ALLOC(length+1);
  1224.     clip_len  = 0;
  1225.  
  1226. #ifdef DEBUG_rhess
  1227.     fprintf(stderr, "xfe_clipboard_retrieve::[ %d ]\n", length);
  1228. #endif
  1229.  
  1230.     cb_result = XmClipboardRetrieve(display, window,
  1231.                                     name,
  1232.                                     (XtPointer) clip_data,
  1233.                                     length,
  1234.                                     &clip_len,
  1235.                                     &private_id);
  1236.  
  1237. #ifdef DEBUG_rhess
  1238.     fprintf(stderr, "xfe_clipboard_retrieve::[ %d ]\n", clip_len);
  1239. #endif
  1240.     clip_data[clip_len] = '\0';
  1241.  
  1242.     *buf_len_a = clip_len;
  1243.     *buf       = clip_data;
  1244.  
  1245.     XmClipboardUnlock(display, window, TRUE);
  1246.  
  1247. #ifdef DEBUG_rhess
  1248.     fprintf(stderr, "xfe_clipboard_retrieve::[ UNLOCK ]\n");
  1249. #endif
  1250.  
  1251.     return cb_result;
  1252. }
  1253.  
  1254. char *
  1255. xfe2_GetClipboardText (Widget focus, int32 *internal)
  1256. {
  1257.     unsigned long length;
  1258.     int       cb_result;
  1259.  
  1260.     Display*  display   = XtDisplay(focus);
  1261.     Window    window    = xfe_GetClipboardWindow(focus);
  1262.     Time      timestamp = XtLastTimestampProcessed (display);
  1263.  
  1264.     struct fe_MWContext_cons *rest;
  1265.  
  1266.     char     *clip_data = NULL;
  1267.     char     *clip_name = NULL;
  1268.     int       i;
  1269.  
  1270.     if (fe_clipboard_motif || !fe_clipboard_widget) {
  1271.         *internal = 0;
  1272.     }
  1273.     else {
  1274.         MWContext *context = fe_WidgetToMWContext(fe_clipboard_widget);
  1275.  
  1276.         *internal = (int) context;
  1277.     }
  1278.  
  1279.     /*
  1280.      * NOTE:  look in our "internal" clipboard cache...
  1281.      *        - [ shortcut for internal paste ]
  1282.      *
  1283.      */
  1284.     if (!clip_data) {
  1285.         if (fe_clipboard_text) {
  1286. #ifdef DEBUG_rhess
  1287.             fprintf(stderr, "xfe2_GetClipboardText::[ cache ]\n");
  1288. #endif
  1289.             clip_data = XP_STRDUP(fe_clipboard_text);
  1290.         }
  1291.     }
  1292.  
  1293.     if (!clip_data) { /* go look on real CLIPBOARD */
  1294.  
  1295.         clip_name = XFE_CCP_TEXT;
  1296. #ifdef DEBUG_rhess
  1297.         fprintf(stderr, "xfe2_GetClipboardText::[ retrieve ]\n");
  1298. #endif
  1299.         cb_result = xfe_clipboard_retrieve_work(focus,
  1300.                                                 clip_name,
  1301.                                                 &clip_data, &length,
  1302.                                                 timestamp);
  1303.  
  1304.         if (cb_result != ClipboardSuccess) {
  1305. #ifdef DEBUG_rhess
  1306.             fprintf(stderr, "xfe2_GetClipboardText::[ failed ]\n");
  1307. #endif
  1308.             XP_FREE(clip_data);
  1309.             clip_data = NULL;
  1310.             clip_name = NULL;
  1311.         }
  1312.     } 
  1313.  
  1314.     return clip_data;
  1315. }
  1316.  
  1317. static void
  1318. fe_text_insert (Widget text, const char *s, int16 charset)
  1319. {
  1320.   /* Gee, I wonder what other gratuitous junk I need to worry about? */
  1321.   Boolean pdel = True;
  1322.   XtVaGetValues (text, XmNpendingDelete, &pdel, 0);
  1323.  
  1324.   if (XmIsText (text))
  1325.     {
  1326.       char *s2 = strdup (s); /* This is nuts: it wants to modify the string! */
  1327.       char *loc;
  1328.       if (pdel) XmTextRemove (text);
  1329.       loc = (char *) fe_ConvertToLocaleEncoding (charset,
  1330.                                                  (unsigned char *) s2);
  1331.       XmTextInsert (text, XmTextGetInsertionPosition (text), loc);
  1332.       if (loc != s2)
  1333.         {
  1334.           free (loc);
  1335.         }
  1336.       free (s2);
  1337.     }
  1338.   else if (XmIsTextField (text))
  1339.     {
  1340.       char *s2 = strdup (s); /* This is nuts: it wants to modify the string! */
  1341.       char *loc;
  1342.       if (pdel) XmTextFieldRemove (text);
  1343.       loc = (char *) fe_ConvertToLocaleEncoding (charset,
  1344.                                                  (unsigned char *) s2);
  1345.       XmTextFieldInsert (text, XmTextFieldGetInsertionPosition (text), loc);
  1346.       if (loc != s2)
  1347.         {
  1348.           free (loc);
  1349.         }
  1350.       free (s2);
  1351.     }
  1352.   else
  1353.     abort ();
  1354. }
  1355.  
  1356. XP_Bool
  1357. fe_InternalSelection(XP_Bool clip_p, 
  1358.                      unsigned long *text_len, 
  1359.                      unsigned long *html_len,
  1360.                      unsigned long *data_len) 
  1361. {
  1362.     XP_Bool gotcha = False;
  1363.     char *text = NULL;
  1364.     char *html = NULL;
  1365.     char *data = NULL;
  1366.     unsigned long dlen = 0;
  1367.  
  1368.     if (clip_p) {
  1369.         text = fe_clipboard_text;
  1370.         html = fe_clipboard_html;
  1371.         data = fe_clipboard_data;
  1372.         dlen = fe_clipboard_dlen;
  1373.     }
  1374.     else {
  1375.         text = fe_selection_text;
  1376.         html = fe_selection_html;
  1377.         data = fe_selection_data;
  1378.         dlen = fe_selection_dlen;
  1379.     }
  1380.  
  1381.     if (text) {
  1382.         *text_len = strlen(text);
  1383.         gotcha = True;
  1384.     }
  1385.     else {
  1386.         *text_len = 0;
  1387.     }
  1388.  
  1389.     if (html) {
  1390.         *html_len = strlen(html);
  1391.         gotcha = True;
  1392.     }
  1393.     else {
  1394.         *html_len = 0;
  1395.     }
  1396.  
  1397.     if (dlen > 0) {
  1398.         *data_len = dlen;
  1399.         gotcha = True;
  1400.     }
  1401.     else {
  1402.         *data_len = 0;
  1403.     }
  1404.         
  1405.     return gotcha;
  1406. }
  1407.  
  1408. char *
  1409. fe_GetPrimaryText(void)
  1410. {
  1411. #ifdef DEBUG_rhess
  1412.     if (fe_selection_text) 
  1413.         fprintf(stderr, 
  1414.                 "fe_GetPrimaryText::[ %d ]\n", strlen(fe_selection_text));
  1415.     else
  1416.         fprintf(stderr,
  1417.                 "fe_GetPrimaryText::[ NULL ]\n");
  1418. #endif
  1419.     return fe_selection_text;
  1420. }
  1421.  
  1422. char *
  1423. fe_GetPrimaryHtml(void)
  1424. {
  1425. #ifdef DEBUG_rhess
  1426.     if (fe_selection_html)
  1427.         fprintf(stderr, 
  1428.                 "fe_GetPrimaryHtml::[ %d ]\n", strlen(fe_selection_html));
  1429.     else
  1430.         fprintf(stderr,
  1431.                 "fe_GetPrimaryHtml::[ NULL ]\n");
  1432. #endif
  1433.     return fe_selection_html;
  1434. }
  1435.  
  1436. char *
  1437. fe_GetPrimaryData(unsigned long *length)
  1438. {
  1439. #ifdef DEBUG_rhess
  1440.     if (fe_selection_data && (fe_selection_dlen > 0)) 
  1441.         fprintf(stderr, 
  1442.                 "fe_GetPrimaryData::[ %d ]\n", fe_selection_dlen);
  1443.     else
  1444.         fprintf(stderr,
  1445.                 "fe_GetPrimaryData::[ NULL ]\n");
  1446. #endif
  1447.     *length = fe_selection_dlen;
  1448.  
  1449.     if (fe_selection_dlen > 0) {
  1450.         return fe_selection_data;
  1451.     }
  1452.     else {
  1453.         return NULL;
  1454.     }
  1455. }
  1456.  
  1457. char *
  1458. fe_GetInternalText(void)
  1459. {
  1460. #ifdef DEBUG_rhess
  1461.     if (fe_clipboard_text) 
  1462.         fprintf(stderr, 
  1463.                 "fe_GetInternalText::[ %d ]\n", strlen(fe_clipboard_text));
  1464.     else
  1465.         fprintf(stderr,
  1466.                 "fe_GetInternalText::[ NULL ]\n");
  1467. #endif
  1468.     return fe_clipboard_text;
  1469. }
  1470.  
  1471. char *
  1472. fe_GetInternalHtml(void)
  1473. {
  1474. #ifdef DEBUG_rhess
  1475.     if (fe_clipboard_html) 
  1476.         fprintf(stderr, 
  1477.                 "fe_GetInternalHtml::[ %d ]\n", strlen(fe_clipboard_html));
  1478.     else
  1479.         fprintf(stderr,
  1480.                 "fe_GetInternalHtml::[ NULL ]\n");
  1481. #endif
  1482.     return fe_clipboard_html;
  1483. }
  1484.  
  1485. char *
  1486. fe_GetInternalData(unsigned long *length)
  1487. {
  1488. #ifdef DEBUG_rhess
  1489.     if (fe_clipboard_data && (fe_clipboard_dlen > 0)) 
  1490.         fprintf(stderr, 
  1491.                 "fe_GetInternalData::[ %d ]\n", fe_clipboard_dlen);
  1492.     else
  1493.         fprintf(stderr,
  1494.                 "fe_GetInternalData::[ NULL ]\n");
  1495. #endif
  1496.     *length = fe_clipboard_dlen;
  1497.  
  1498.     if (fe_clipboard_dlen > 0) {
  1499.         return fe_clipboard_data;
  1500.     }
  1501.     else {
  1502.         return NULL;
  1503.     }
  1504. }
  1505.  
  1506. /*
  1507.  * NOTE:  we need this to support the unified cut/copy/paste mechanism...
  1508.  *
  1509.  *        - this allows translations to call cut/copy on a specific widget
  1510.  *
  1511.  */
  1512. void
  1513. xfe_TextCopy(MWContext *context, Widget focus, XP_Bool cut)
  1514. {
  1515.     XP_Bool text_wp = False;
  1516.     XP_Bool text_fp = False;
  1517.     char      *clip = NULL;
  1518.     Time       time = 0;
  1519.  
  1520.     if (!focus) 
  1521.         return;
  1522.  
  1523.     text_wp = XmIsText(focus);
  1524.     text_fp = XmIsTextField(focus);
  1525.  
  1526.     if (text_wp || text_fp) {
  1527.  
  1528.         clip = fe_GetTextSelection(focus);
  1529.         if (clip) {
  1530.             time = XtLastTimestampProcessed(XtDisplay(focus));
  1531.  
  1532.             fe_OwnClipboard(focus, time, 
  1533.                             clip, NULL, NULL, 0, True);
  1534.             XP_FREE(clip);
  1535.             
  1536.             if (cut) {
  1537.                 if (text_wp)
  1538.                     XmTextRemove(focus);
  1539.                 else
  1540.                     XmTextFieldRemove(focus);
  1541. #ifdef DEBUG_rhess
  1542.                 fprintf(stderr, "xfe_TextCopy::[ CUT ]\n");
  1543. #endif
  1544.             }
  1545. #ifdef DEBUG_rhess
  1546.             else {
  1547.                 fprintf(stderr, "xfe_TextCopy::[ ]\n");
  1548.             }
  1549. #endif            
  1550.         }
  1551. #ifdef DEBUG_rhess
  1552.         else {
  1553.             fprintf(stderr, "xfe_TextCopy::[ failed to get selection ]\n");
  1554.         }
  1555. #endif
  1556.     }
  1557. }
  1558.  
  1559. /* Motif sucks!  XmTextPaste() gets stuck if you're pasting from one
  1560.    widget to another in the same application! */
  1561. void
  1562. xfe_TextPaste (MWContext *context, Widget text, XP_Bool quote_p)
  1563. {
  1564.   struct fe_MWContext_cons *rest;
  1565.   char *clip = 0;
  1566.   int16 charset = CS_LATIN1;
  1567.   INTL_CharSetInfo csi;
  1568.  
  1569.   int32 internal = 0;
  1570.   MWContext *con = NULL;
  1571.  
  1572.   clip = xfe2_GetClipboardText(text, &internal);
  1573.  
  1574.   if (internal) {
  1575.       con = (MWContext *) internal;
  1576.       csi = LO_GetDocumentCharacterSetInfo(con);
  1577.       charset = INTL_GetCSIWinCSID(csi);
  1578.   }
  1579.   else {
  1580.       charset = INTL_DefaultWinCharSetID(NULL);
  1581.   }
  1582.  
  1583. #ifdef MOZ_MAIL_NEWS
  1584.   if (clip && quote_p)
  1585.     {
  1586.       char *n = MSG_ConvertToQuotation (clip);
  1587.       XP_ASSERT(n);
  1588.       XP_FREE(clip);
  1589.       clip = n;
  1590.       if (!clip) return;
  1591.     }
  1592. #endif
  1593.  
  1594.   if (clip)
  1595.     {
  1596. #ifdef DEBUG_rhess
  1597.       fprintf(stderr, "xfe_TextPaste::[ insert ][ %d ]--[ %d ] [ %s ]\n", 
  1598.               charset, CS_LATIN1, clip);
  1599. #endif
  1600.       fe_text_insert (text, clip, charset);
  1601.       XP_FREE(clip);
  1602.     }
  1603.   else
  1604.     XBell (XtDisplay (text), 0);
  1605. }
  1606.  
  1607.  
  1608. typedef enum { fe_Cut, fe_Copy, fe_Paste, fe_PasteQuoted } fe_CCP;
  1609.  
  1610. static void
  1611. fe_ccp (MWContext *context, XEvent *event, fe_CCP ccp)
  1612. {
  1613.   Widget focus = XmGetFocusWidget (CONTEXT_WIDGET (context));
  1614.   char *clip = NULL;
  1615.   Time time = (event && (event->type == KeyPress ||
  1616.              event->type == KeyRelease)
  1617.            ? event->xkey.time :
  1618.            event && (event->type == ButtonPress ||
  1619.              event->type == ButtonRelease)
  1620.            ? event->xbutton.time :
  1621.            XtLastTimestampProcessed (XtDisplay(CONTEXT_WIDGET (context))));
  1622.  
  1623.   if ((CONTEXT_WIDGET(context) != fe_selection_widget
  1624.        || (ccp != fe_Cut && ccp != fe_Copy))
  1625.       && focus && (XmIsText (focus) || XmIsTextField (focus)))
  1626.     switch (ccp)
  1627.       {
  1628.       case fe_Cut:       
  1629.           xfe_TextCopy (context, focus, TRUE);
  1630.           break;
  1631.       case fe_Copy:       
  1632.           xfe_TextCopy (context, focus, FALSE);
  1633.           break;
  1634.       case fe_Paste:       
  1635.           xfe_TextPaste (context, focus, FALSE); 
  1636.           break;
  1637.       case fe_PasteQuoted: 
  1638.           xfe_TextPaste (context, focus, TRUE); 
  1639.           break;
  1640.       default:           
  1641.           XP_ASSERT(0); 
  1642.           break;
  1643.       }
  1644.   else
  1645.     {
  1646.         if (focus && ccp == fe_Copy) {
  1647.             fe_OwnSelection(context, time, True);
  1648.         }
  1649.         else {
  1650.             XBell (XtDisplay (CONTEXT_WIDGET (context)), 0);
  1651.         }
  1652.     }
  1653. }
  1654.  
  1655. void
  1656. fe_cut_cb (Widget widget, XtPointer closure, XtPointer call_data)
  1657. {
  1658.   MWContext *context = (MWContext *) closure;
  1659.   XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
  1660.   fe_UserActivity (context);
  1661.  
  1662.   fe_ccp (context, (cb ? cb->event : 0), fe_Cut);
  1663. }
  1664.  
  1665. void
  1666. fe_copy_cb (Widget widget, XtPointer closure, XtPointer call_data)
  1667. {
  1668.   MWContext *context = (MWContext *) closure;
  1669.   XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
  1670.   fe_UserActivity (context);
  1671.  
  1672.   fe_ccp (context, (cb ? cb->event : 0), fe_Copy);
  1673. }
  1674.  
  1675. void
  1676. fe_paste_cb (Widget widget, XtPointer closure, XtPointer call_data)
  1677. {
  1678.   MWContext *context = (MWContext *) closure;
  1679.   XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
  1680.   fe_UserActivity (context);
  1681.  
  1682.   fe_ccp (context, (cb ? cb->event : 0), fe_Paste);
  1683. }
  1684.  
  1685. void
  1686. fe_paste_quoted_cb (Widget widget, XtPointer closure, XtPointer call_data)
  1687. {
  1688.   MWContext *context = (MWContext *) closure;
  1689.   XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
  1690.   fe_UserActivity (context);
  1691.  
  1692.   fe_ccp (context, (cb ? cb->event : 0), fe_PasteQuoted);
  1693. }
  1694.