home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / xview / guidexv / gdd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-14  |  44.3 KB  |  1,974 lines

  1. /*
  2.  * This file is a product of Sun Microsystems, Inc. and is provided for
  3.  * unrestricted use provided that this legend is included on all tape
  4.  * media and as a part of the software program in whole or part.  Users
  5.  * may copy or modify this file without charge, but are not authorized to
  6.  * license or distribute it to anyone else except as part of a product
  7.  * or program developed by the user.
  8.  * 
  9.  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  10.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  11.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  12.  * 
  13.  * This file is provided with no support and without any obligation on the
  14.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  15.  * modification or enhancement.
  16.  * 
  17.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  18.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  19.  * OR ANY PART THEREOF.
  20.  * 
  21.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  22.  * or profits or other special, indirect and consequential damages, even
  23.  * if Sun has been advised of the possibility of such damages.
  24.  * 
  25.  * Sun Microsystems, Inc.
  26.  * 2550 Garcia Avenue
  27.  * Mountain View, California  94043
  28.  */
  29.  
  30. #ifndef lint
  31. static char    sccsid[] = "@(#)gdd.c    2.38 91/10/15 Copyright 1991 Sun Microsystems";
  32. #endif
  33.  
  34. #include <stdio.h>
  35. #include <sys/param.h>
  36. #ifdef SVR4
  37. #include <sys/dirent.h>
  38. #else
  39. #include <sys/dir.h>
  40. #endif
  41. #include <sys/stat.h>
  42. #include <xview/xview.h>
  43. #include <xview/panel.h>
  44. #include <xview/canvas.h>
  45. #include <xview/dragdrop.h>
  46. #include <xview/xv_xrect.h>
  47. #include <xview/svrimage.h>
  48. #include "gdd.h"
  49.  
  50. /* Internal Functions */
  51. static void    drop_site_append();
  52. static void    fill_drop_info();
  53. static void    free_drop_info();
  54. static void    begin_item_transfer();
  55. static void    stop_dragdrop();
  56. static void    drop_site_on();
  57. static void    init_dnd_code_table();
  58. static void    set_drag_data();
  59.  
  60. /* 
  61.  * Temporary buffer size for managing INCR (incremental) transfers thru 
  62.  * the selection service 
  63.  */
  64. #define XFER_BUFSIZ    5000
  65.  
  66. /*
  67.  * Flag used to keep state during selection transfers.
  68.  */
  69. #define TARGET_RESPONSE         0x1
  70. #define HOST_RESPONSE           0x2
  71. #define TRANSPORT_RESPONSE      0x4
  72. #define FILE_NAME_RESPONSE      0x8
  73. #define DATA_LABEL_RESPONSE     0x10
  74. #define BYTES_REQUESTED         0x20
  75. #define BYTES_XFERRED           0x40
  76.  
  77. #define RESPONSE_LEVEL_1        0x1f
  78. #define RESPONSE_LEVEL_2        0x7f
  79.  
  80.  
  81. /*
  82.  * Structure used to store the data as it is being accumulated.
  83.  */
  84. typedef struct
  85. {
  86.     char    *data;
  87.     int    alloc_size;
  88.     int    bytes_used;
  89. } CHAR_BUF;
  90.  
  91.  
  92. /* 
  93.  * Context structure for describing the current drag/drop action 
  94.  */
  95. typedef struct
  96. {
  97.     Atom            *target_list;
  98.     int             num_targets;
  99.     Atom            *transport_list;
  100.     int             num_transports;
  101.     char            *data_label;
  102.     int             object_count;
  103.     char            *source_host;
  104.     char            *source_name;
  105.     char            *source_filename;
  106.     Atom            chosen_target;
  107.     Atom            chosen_transport;
  108.     int             transfer_state;
  109.     int             processing_stream;
  110.     int             state_mask;
  111.     int             stop_hit;
  112.     int             objects_transferred;
  113.     char        *tmpfile_name;
  114.     FILE        *fd;
  115. } GDD_CONTEXT;
  116.  
  117.  
  118. /*
  119.  * Structure to store information for each drop_site/drop_target.
  120.  */
  121. typedef struct Dnd_drop_site
  122. {
  123.     Xv_opaque        item;
  124.     Event            *event;
  125.     int            is_drop_site;
  126.     int            is_move;
  127.     struct Dnd_drop_site    *next;
  128.     Xv_opaque        drop_site;
  129.     Rect            *rectlist;
  130.     void             (*drop_func)();
  131.     void             (*drag_func)();
  132. } GDD_DROP_SITE;
  133.  
  134. #ifdef SVR4
  135. static char            Hostname[MAXNAMELEN];
  136. #else
  137. static char            Hostname[MAXHOSTNAMELEN];
  138. #endif
  139. static GDD_CONTEXT        *D;
  140. GDD_DROP_SITE            *Drop_sites;
  141. GDD_DROP_SITE            *Current_drop_site;
  142. GDD_DROP_INFO            *Drop_info;
  143. static Selection_requestor    Sel;
  144. static Xv_Server        My_server;
  145. static Xv_opaque        Base_frame;
  146. static char            *Dnd_codes[8];
  147. static char             xfer_data_buf[XFER_BUFSIZ];
  148.  
  149. static int            debug_on = 0;
  150. #define DEBUG_FLAG         debug_on
  151.  
  152. #define DP(a)    {if( DEBUG_FLAG ) printf a ; }
  153.  
  154.  
  155. static Atom text_atom;
  156. static Atom current_type;
  157. static Atom incr_atom;
  158. static Atom targets_atom;
  159. static Atom length_atom;
  160. static Atom host_atom;
  161. static Atom file_name_atom;
  162. static Atom atm_file_name_atom;
  163. static Atom delete_atom;
  164. static Atom selection_end_atom;
  165. static Atom dragdrop_done_atom;
  166. static Atom data_label_atom;
  167. static Atom name_atom;
  168. static Atom alternate_transport_atom;
  169. static Atom available_types_atom;
  170. static Atom enumeration_count_atom;
  171. static Atom enumeration_item_atom;
  172. static Atom null_atom;
  173.  
  174.  
  175. /*
  176.  * Initialize the drag and drop code table.
  177.  */
  178. static void
  179. init_dnd_code_table()
  180. {
  181.     Dnd_codes[0] = (char *) dgettext("libguidexv",
  182.                      "Dragdrop: Completed");
  183.     Dnd_codes[1] = (char *) dgettext("libguidexv",
  184.                      "Dragdrop: Error");
  185.     Dnd_codes[2] = (char *) dgettext("libguidexv",
  186.                      "Dragdrop: Illegal Target");
  187.     Dnd_codes[3] = (char *) dgettext("libguidexv",
  188.                      "Dragdrop: Timed out");
  189.     Dnd_codes[4] = (char *) dgettext("libguidexv",
  190.                      "Dragdrop: Unable to obtain selection");
  191.     Dnd_codes[5] = (char *) dgettext("libguidexv",
  192.                      "Dragdrop: Dropped on root window");
  193.     Dnd_codes[6] = (char *) dgettext("libguidexv",
  194.                      "Dragdrop: Aborted");
  195.     Dnd_codes[7] = (char *) dgettext("libguidexv",
  196.                      "Dragdrop: Unknown return code");
  197. }
  198.  
  199. /*
  200.  * Determine if a certain atom is in a list of atoms.
  201.  */
  202. static int
  203. #ifdef __STDC__
  204. atom_in_list(Atom atom, Atom *atom_list, int length)
  205. #else
  206. atom_in_list(atom, atom_list, length)
  207.     Atom    atom;
  208.     Atom    *atom_list;
  209.     int    length;
  210. #endif
  211. {
  212.     int    i;
  213.  
  214.     if (!atom_list)
  215.         return(False);
  216.  
  217.     for (i = 0; i < length; i++)
  218.         if (atom_list[i] == atom)
  219.             return(True);
  220.  
  221.     return(False);
  222. }
  223.  
  224. /* 
  225.  * Clears the context block in preparation for a new drag/drop transaction. 
  226.  */
  227. static void
  228. #ifdef __STDC__
  229. clear_context(GDD_CONTEXT *dnd_ptr, int all_state)
  230. #else
  231. clear_context(dnd_ptr, all_state)
  232.     GDD_CONTEXT    *dnd_ptr;
  233.     int         all_state;
  234. #endif
  235. {
  236.     if (dnd_ptr->target_list)
  237.         free(dnd_ptr->target_list);
  238.     dnd_ptr->target_list = NULL;
  239.  
  240.     dnd_ptr->num_targets = 0;
  241.  
  242.     if (all_state)
  243.     {
  244.         dnd_ptr->objects_transferred = 0;
  245.         dnd_ptr->object_count = 0;
  246.     }
  247.  
  248.     if (dnd_ptr->transport_list)
  249.         free(dnd_ptr->transport_list);
  250.     dnd_ptr->transport_list = NULL;
  251.  
  252.     dnd_ptr->num_transports = 0;
  253.     if (dnd_ptr->data_label)
  254.         free(dnd_ptr->data_label);
  255.     dnd_ptr->data_label = NULL;
  256.  
  257.     if (dnd_ptr->source_host)
  258.         free(dnd_ptr->source_host);
  259.     dnd_ptr->source_host = NULL;
  260.  
  261.     if (dnd_ptr->source_name)
  262.         free(dnd_ptr->source_name);
  263.     dnd_ptr->source_name = NULL;
  264.  
  265.     if (dnd_ptr->source_filename)
  266.         free(dnd_ptr->source_filename);
  267.     dnd_ptr->source_filename = NULL;
  268.  
  269.     dnd_ptr->chosen_target     = 0;
  270.     dnd_ptr->chosen_transport  = 0;
  271.  
  272.     dnd_ptr->state_mask        = 0;
  273.     dnd_ptr->stop_hit          = 0;
  274.     dnd_ptr->processing_stream = 0;
  275.     if (dnd_ptr->tmpfile_name)
  276.         free(dnd_ptr->tmpfile_name);
  277.     dnd_ptr->tmpfile_name      = NULL;
  278.     dnd_ptr->fd            = 0;
  279. }
  280.  
  281. /*
  282.  * Copy str from character 0 to end to strbuf.
  283.  */
  284. static void
  285. #ifdef __STDC__
  286. strcpyupto(char *strbuf, char *str, char *end)
  287. #else
  288. strcpyupto(strbuf, str, end)
  289.     char *strbuf;
  290.     char *str;
  291.     char *end;
  292. #endif
  293. {
  294.     while (str != end)
  295.         *strbuf++ = *str++;
  296.  
  297.     *strbuf = '\0';
  298. }
  299.  
  300. /*
  301.  * Parse the input string into dir and file.
  302.  * The resulting file and dir is stored in the file and dir variable.
  303.  * Note: dir and file have to be pre-allocated memory.
  304.  */
  305. static int
  306. #ifdef __STDC__
  307. parse_path(char *somedir, char *somefile, char *dir, char *file)
  308. #else
  309. parse_path(somedir, somefile, dir, file)
  310.     char    *somedir;
  311.     char    *somefile;
  312.     char    *dir;
  313.     char    *file;
  314. #endif
  315. {
  316.     char     *file_index;
  317.     char    path[MAXPATHLEN];
  318.  
  319.     if (somedir && *somedir)
  320.     {
  321.         strcpy(path, somedir);
  322.         strcat(path, "/");
  323.         strcat(path, somefile);
  324.     } else
  325.         strcpy(path, somefile);
  326.  
  327.     if (!path || !*path)
  328.         return FALSE;
  329.  
  330.     file_index = strrchr(path, '/');
  331.  
  332.     if (file_index)
  333.     {
  334.         strcpy(file, file_index+1);
  335.         strcpyupto(dir, path, file_index);
  336.     }
  337.     else
  338.     {
  339.         strcpy(file, path);
  340.         strcpy(dir, "./");
  341.     }
  342.     
  343.     return TRUE;
  344. }
  345.  
  346.  
  347. /* 
  348.  * Huge monolithic routine that processes all the replies 
  349.  * to the questions that I ask about the current drag/drop 
  350.  * selection.  These requests are made in groups, and the 
  351.  * routine contains a state machine whose current state is stored 
  352.  * in the D block.  This routine updates the 
  353.  * state machine as replies, or failed replies come in.  
  354.  * Changes in state may require issuing new requests for data, 
  355.  * which are processed by this same routine.  
  356.  */
  357. static void
  358. #ifdef __STDC__
  359. reply_proc (Selection_requestor sel_req, Atom target, Atom type,
  360.         Xv_opaque replyBuf, unsigned long len, int format )
  361. #else
  362. reply_proc ( sel_req, target, type, replyBuf, len, format )
  363.     Selection_requestor      sel_req;
  364.     Atom               target;
  365.     Atom               type;
  366.     Xv_opaque           replyBuf;
  367.     unsigned long          len;
  368.     int                format;
  369. #endif
  370. {
  371.     char        *atom_name;
  372.     char        *target_name;
  373.     int        *err_ptr = (int *) replyBuf;
  374.     char        *char_buf = (char *) replyBuf;
  375.     int        old_length;
  376.     int        end_enum_context = -1;
  377.     int        print_file();
  378.     GDD_DROP_INFO    *di; 
  379.  
  380.     /* 
  381.      * Try to turn the type and target atoms into 
  382.      * some useful text for debugging. To use this feature, set the
  383.      * debug_on variable to 1 and recompile the package.
  384.      */
  385.     if (debug_on)
  386.     {
  387.         if (type > 0)
  388.             atom_name = XGetAtomName((Display *)
  389.                          xv_get(My_server,
  390.                             XV_DISPLAY), type);
  391.         else
  392.             atom_name = "[None]";
  393.         if (target > 0)
  394.             target_name = XGetAtomName((Display *)
  395.                            xv_get(My_server,
  396.                               XV_DISPLAY),
  397.                            target);
  398.         else
  399.             target_name = "[None]";
  400.  
  401.         DP(("reply_proc: type = %s/%d, target %s/%d\n",
  402.             atom_name, type, target_name, target));
  403.         DP(("                      len = %d, format = %d, buf = %d, state %x\n",
  404.             len, format, err_ptr, D->state_mask));
  405.     }
  406.  
  407.     /* 
  408.      * Simply processing the return from the termination 
  409.      * request.  No action necessary.
  410.      */
  411.     if ((target == selection_end_atom) ||
  412.         (target == enumeration_item_atom))
  413.         return;
  414.  
  415.     if ((len == SEL_ERROR) && ((*err_ptr) == SEL_BAD_CONVERSION))
  416.     {
  417.         /* 
  418.          * A conversion of some type failed.  Mark
  419.          * the state variable 
  420.          */
  421.         if (target == targets_atom)
  422.             D->state_mask |= TARGET_RESPONSE;
  423.         else if (target == host_atom)
  424.             D->state_mask |= HOST_RESPONSE;
  425.         else if (target == alternate_transport_atom)
  426.             D->state_mask |= TRANSPORT_RESPONSE;
  427.         else if (target == file_name_atom)
  428.             D->state_mask |= FILE_NAME_RESPONSE;
  429.         else if (target == data_label_atom)
  430.             D->state_mask |= DATA_LABEL_RESPONSE;
  431.     }
  432.     else if (len == SEL_ERROR)
  433.     {
  434.         /* 
  435.          * Some internal error happened as a result of 
  436.          * an earlier posted request.  Tell the user. The messages
  437.          * are very curt because the Drag and Drop package
  438.          * and the selection service package do not provide
  439.          * a detailed description of the error.
  440.          */
  441.  
  442.         switch (*err_ptr)
  443.         {
  444.         case SEL_BAD_PROPERTY :
  445.                 xv_set(Base_frame, FRAME_LEFT_FOOTER,
  446.                    dgettext("libguidexv",
  447.                     "Dragdrop: Bad property"), 0);
  448.                   break;
  449.               case SEL_BAD_TIME:
  450.                   xv_set(Base_frame, FRAME_LEFT_FOOTER,
  451.                    dgettext("libguidexv",
  452.                     "Dragdrop: Bad time"), 0);
  453.                   break;
  454.               case SEL_BAD_WIN_ID:
  455.                   xv_set(Base_frame, FRAME_LEFT_FOOTER,
  456.                    dgettext("libguidexv",
  457.                     "Dragdrop: Bad window id"), 0);
  458.                   break;
  459.               case SEL_TIMEDOUT:
  460.                   xv_set(Base_frame, FRAME_LEFT_FOOTER,
  461.                    dgettext("libguidexv",
  462.                     "Dragdrop: Timed out"), 0);
  463.                   break;
  464.               case SEL_PROPERTY_DELETED:
  465.                   xv_set(Base_frame, FRAME_LEFT_FOOTER,
  466.                    dgettext("libguidexv",
  467.                     "Dragdrop: Property deleted"), 0);
  468.                   break;
  469.               case SEL_BAD_PROPERTY_EVENT:
  470.                   xv_set(Base_frame, FRAME_LEFT_FOOTER,
  471.                    dgettext("libguidexv",
  472.                     "Dragdrop: Bad property event"), 0);
  473.                   break;
  474.         }
  475.         stop_dragdrop();
  476.         return;
  477.     }
  478.     else if (type == incr_atom)
  479.         D->processing_stream = TRUE;
  480.         else if ((target == XA_STRING) ||
  481.          (target == text_atom))
  482.     {
  483.         /* 
  484.          * Data stream coming thru. 
  485.          */
  486.         if (len && !D->stop_hit)
  487.         {
  488.             /*
  489.              * The length is non-zero, so data, and 
  490.              * not the end of transmission. Create a name
  491.              * for the temporary file.
  492.              */
  493.             if (!D->tmpfile_name)
  494.             {
  495.                 D->tmpfile_name =
  496.                     strdup(tempnam("/tmp", "guide"));
  497.                 D->fd = fopen(D->tmpfile_name, "w");
  498.             }
  499.  
  500.             fwrite(char_buf, 1, len, D->fd);
  501.  
  502.             if (!D->processing_stream)
  503.             {
  504.  
  505.                 fclose(D->fd);
  506.  
  507.                 /*
  508.                  * We tell the source that we are all done
  509.                  * and call the applications callback
  510.                  * function for the given drop_site/target.
  511.                  */
  512.  
  513.                 DP(("should print object number %d of %d, data_label: %s, tmpfile: %s\n", 
  514.                     D->objects_transferred + 1, 
  515.                     D->object_count, 
  516.                     D->data_label,
  517.                     D->tmpfile_name));
  518.                 
  519.                 fill_drop_info(D, &di, char_buf, len);
  520.                 Current_drop_site->drop_func(Current_drop_site->item, Current_drop_site->event, di);
  521.                 free_drop_info(di);
  522.  
  523.                 D->state_mask |= BYTES_XFERRED;
  524.             }
  525.         }
  526.             else if (D->processing_stream)
  527.         {
  528.             /* 
  529.              * The length was 0, so we have the 
  530.              * end of a data transmission. Fill the drop_info
  531.              * data structure and call the application's
  532.              * callback function for the given drop_site/target.
  533.              */
  534.             fclose(D->fd);
  535.  
  536.             DP(("should print object number %d of %d, data_label: %s\n", 
  537.                 D->objects_transferred, 
  538.                 D->object_count, 
  539.                 D->data_label));
  540.  
  541.             fill_drop_info(D, &di, char_buf, len);
  542.             Current_drop_site->drop_func(Current_drop_site->item,
  543.                              Current_drop_site->event,  di);
  544.             free_drop_info(di);
  545.  
  546.             D->state_mask |= BYTES_XFERRED;
  547.  
  548.         }
  549.         else
  550.         {
  551.  
  552.             stop_dragdrop();
  553.             return;
  554.         }
  555.     }
  556.     else if (target == targets_atom)
  557.     {
  558.         if (len)
  559.         {
  560.             if (D->target_list &&
  561.                 !D->processing_stream)
  562.             {
  563.                 free(D->target_list);
  564.                 D->target_list = NULL;
  565.             }
  566.  
  567.             if (!D->target_list)
  568.             {
  569.                 D->target_list = (Atom *)
  570.                     malloc(len * sizeof(Atom));
  571.                 memcpy((char *) D->target_list, char_buf,
  572.                        len * sizeof(Atom));
  573.                 if (!D->processing_stream)
  574.                 {
  575.                     D->state_mask |=
  576.                         TARGET_RESPONSE;
  577.                 }
  578.             }
  579.             else
  580.             {
  581.                 D->target_list = (Atom *)
  582.                     realloc(D->target_list,
  583.                         D->num_targets * sizeof(Atom)
  584.                         + len * sizeof(Atom));
  585.                 memcpy((char *) &D->target_list[D->num_targets
  586.                                 - 1],
  587.                        char_buf, len * sizeof(Atom));
  588.             }
  589.         }
  590.         else
  591.         {
  592.             D->state_mask |= TARGET_RESPONSE;
  593.             D->processing_stream = FALSE;
  594.         }
  595.  
  596.         D->num_targets += len;
  597.     }
  598.     else if (target == alternate_transport_atom)
  599.     {
  600.         if (len)
  601.         {
  602.             if (D->transport_list &&
  603.                 !D->processing_stream)
  604.             {
  605.                 free(D->transport_list);
  606.                 D->transport_list = NULL;
  607.             }
  608.  
  609.             if (!D->transport_list)
  610.             {
  611.                 D->transport_list = (Atom *)
  612.                     malloc(len * sizeof(Atom));
  613.                 memcpy((char *) D->transport_list, char_buf,
  614.                        len * sizeof(Atom));
  615.                 if (!D->processing_stream)
  616.                 {
  617.                     D->state_mask |=
  618.                         TRANSPORT_RESPONSE;
  619.                 }
  620.             }
  621.             else
  622.             {
  623.                 D->transport_list = (Atom *)
  624.                     realloc(D->transport_list,
  625.                         D->num_transports * sizeof(Atom) +
  626.                         len * sizeof(Atom));
  627.                 memcpy((char *) &D->
  628.                        transport_list[D->num_transports - 1],
  629.                        char_buf, len * sizeof(Atom));
  630.             }
  631.         }
  632.         else
  633.         {
  634.             D->state_mask |= TRANSPORT_RESPONSE;
  635.             D->processing_stream = FALSE;
  636.         }
  637.  
  638.         D->num_transports += len;
  639.     }
  640.     else if (target == name_atom)
  641.     {
  642.         if (len)
  643.         {
  644.             if (D->source_name && !D->processing_stream)
  645.             {
  646.                 free(D->source_name);
  647.                 D->source_name = NULL;
  648.             }
  649.  
  650.             if (!D->source_name)
  651.             {
  652.                 D->source_name = (char *)
  653.                     malloc(len + 1);
  654.                 memcpy(D->source_name, char_buf, len);
  655.                 D->source_name[len] = NULL;
  656.                 if (!D->processing_stream)
  657.                     D->state_mask |= HOST_RESPONSE;
  658.             }
  659.             else
  660.             {
  661.                 old_length = strlen(D->source_name);
  662.                 D->source_name = (char *) realloc(D->source_name, old_length + len + 1);
  663.                 memcpy(&D->source_name[old_length], char_buf, len);
  664.                 D->source_name[old_length + len] = NULL;
  665.             }
  666.         }
  667.         else
  668.         {
  669.             D->state_mask |= HOST_RESPONSE;
  670.             D->processing_stream = FALSE;
  671.         }
  672.     }
  673.     else if (target == host_atom)
  674.     {
  675.         if (len)
  676.         {
  677.             if (D->source_host && !D->processing_stream)
  678.             {
  679.                 free(D->source_host);
  680.                 D->source_host = NULL;
  681.             }
  682.  
  683.             if (!D->source_host)
  684.             {
  685.                 D->source_host = (char *)
  686.                     malloc(len + 1);
  687.                 memcpy(D->source_host, char_buf, len);
  688.                 D->source_host[len] = NULL;
  689.                 if (!D->processing_stream)
  690.                     D->state_mask |= HOST_RESPONSE;
  691.             }
  692.             else
  693.             {
  694.                 old_length = strlen(D->source_host);
  695.                 D->source_host = (char *) realloc(D->source_host, old_length + len + 1);
  696.                 memcpy(&D->source_host[old_length], char_buf, len);
  697.                 D->source_host[old_length + len] = NULL;
  698.             }
  699.         }
  700.         else
  701.         {
  702.             D->state_mask |= HOST_RESPONSE;
  703.             D->processing_stream = FALSE;
  704.         }
  705.     }
  706.     else if (target == file_name_atom)
  707.     {
  708.         if (len)
  709.         {
  710.             if (D->source_filename && !D->processing_stream)
  711.             {
  712.                 free(D->source_filename);
  713.                 D->source_filename = NULL;
  714.             }
  715.  
  716.             if (!D->source_filename)
  717.             {
  718.                 D->source_filename = (char *)
  719.                     malloc(len + 1);
  720.                 memcpy(D->source_filename, char_buf, len);
  721.                 D->source_filename[len] = NULL;
  722.                 if (!D->processing_stream)
  723.                     D->state_mask |= FILE_NAME_RESPONSE;
  724.             }
  725.             else
  726.             {
  727.                 old_length = strlen(D->source_filename);
  728.                 D->source_filename = (char *) realloc(D->source_filename, old_length + len + 1);
  729.                 memcpy(&D->source_filename[old_length], char_buf, len);
  730.                 D->source_filename[old_length + len] = NULL;
  731.             }
  732.         }
  733.         else
  734.         {
  735.             D->state_mask |= FILE_NAME_RESPONSE;
  736.             D->processing_stream = FALSE;
  737.         }
  738.     }
  739.     else if (target == data_label_atom)
  740.     {
  741.         if (len)
  742.         {
  743.             if (D->data_label && !D->processing_stream)
  744.             {
  745.                 free(D->data_label);
  746.                 D->data_label = NULL;
  747.             }
  748.  
  749.             if (!D->data_label)
  750.             {
  751.                 D->data_label = (char *)
  752.                     malloc(len + 1);
  753.                 memcpy(D->data_label, char_buf, len);
  754.                 D->data_label[len] = NULL;
  755.                 if (!D->processing_stream)
  756.                     D->state_mask |= DATA_LABEL_RESPONSE;
  757.             }
  758.             else
  759.             {
  760.                 old_length = strlen(D->data_label);
  761.                 D->data_label = (char *) realloc(D->data_label, old_length + len + 1);
  762.                 memcpy(&D->data_label[old_length], char_buf, len);
  763.                 D->data_label[old_length + len] = NULL;
  764.             }
  765.         }
  766.         else
  767.         {
  768.             D->state_mask |= DATA_LABEL_RESPONSE; 
  769.             D->processing_stream = FALSE;
  770.         }
  771.     }
  772.     else
  773.         return;
  774.  
  775.     if (D->state_mask == RESPONSE_LEVEL_1)
  776.     {
  777.         DP(("first batch of replies processed, asking for second\n"));
  778.  
  779.                 if ((!atom_in_list(XA_STRING, D->target_list, D->num_targets)) &&
  780.                     (!atom_in_list(atm_file_name_atom, D->transport_list, D->num_targets)) &&
  781.                     (!atom_in_list(text_atom, D->target_list, D->num_targets)))
  782.  
  783.         {
  784.             xv_set(Base_frame, FRAME_LEFT_FOOTER, dgettext("libguidexv","Dragdrop: Unknown type of data"), 0);
  785.             stop_dragdrop();
  786.             return;
  787.         }
  788.  
  789.         if (!atom_in_list(XA_STRING, D->target_list, D->num_targets))
  790.             D->chosen_target = text_atom;
  791.         else
  792.             D->chosen_target = XA_STRING;
  793.     
  794.         /* 
  795.          * Determine what sort of data we have coming,
  796.          * get the host name to go with the file name.
  797.          */
  798.     
  799.         if (atom_in_list(atm_file_name_atom,
  800.                  D->transport_list, D->num_transports) && 
  801.             D->source_filename)
  802.         {
  803.             if (!strcoll(Hostname, D->source_host))
  804.             {
  805.                 /* 
  806.                  * A valid filename has been recieved. Fill
  807.                  * the drop_info_structure and call the
  808.                  * application's callback function for the
  809.                  * given drop_site/target.
  810.                  */
  811.                 fill_drop_info(D, &di, char_buf, len);
  812.                 Current_drop_site->drop_func(Current_drop_site->item, Current_drop_site->event, di);
  813.                 free_drop_info(di);
  814.  
  815.                 DP(("should print object number %d of %d, host: %s, name: %s\n",
  816.                     D->objects_transferred, 
  817.                     D->object_count, 
  818.                     D->source_host, 
  819.                     D->source_filename));
  820.  
  821.                 D->objects_transferred++;
  822.                 if (D->objects_transferred < D->object_count)
  823.                 {
  824.                     clear_context(D, FALSE);
  825.                     begin_item_transfer();
  826.                     return;
  827.                 }
  828.                 else
  829.                 {
  830.                     stop_dragdrop();
  831.                     return;
  832.                 }
  833.             }
  834.         }
  835.         /* 
  836.          * Data stream comming in. 
  837.          */
  838.         DP(("asking for data stream, target %d (%s)\n",
  839.             D->chosen_target,
  840.             xv_get(My_server, SERVER_ATOM_NAME,
  841.                D->chosen_target)));
  842.  
  843.         xv_set(Sel,
  844.                SEL_REPLY_PROC, reply_proc,
  845.                SEL_TYPES, 
  846.                enumeration_item_atom,
  847.                D->chosen_target, 
  848.                enumeration_item_atom,
  849.                0,
  850.  
  851.                SEL_TYPE_INDEX, 0,
  852.                SEL_PROP_TYPE, XA_INTEGER,
  853.                SEL_PROP_DATA, &D->objects_transferred,
  854.                SEL_PROP_FORMAT, 32,
  855.                SEL_PROP_LENGTH, 1,
  856.                SEL_TYPE_INDEX, 2,
  857.                SEL_PROP_TYPE, XA_INTEGER,
  858.                SEL_PROP_DATA, &end_enum_context,
  859.                SEL_PROP_FORMAT, 32,
  860.                SEL_PROP_LENGTH, 1,
  861.  
  862.                0 );
  863.     
  864.         sel_post_req(Sel);
  865.  
  866.         D->state_mask |= BYTES_REQUESTED;
  867.  
  868.     }
  869.     else if (D->state_mask == RESPONSE_LEVEL_2)
  870.     {
  871.  
  872.         D->objects_transferred++;
  873.         if (D->objects_transferred < D->object_count)
  874.         {
  875.             clear_context(D, FALSE);
  876.             begin_item_transfer();
  877.         }
  878.         else
  879.         {
  880.             stop_dragdrop();
  881.             return;
  882.         }
  883.     }
  884.  
  885. }
  886.  
  887. /* 
  888.  * Big routine to answer all the queries comming from the destination.
  889.  * It uses data extacted from the drop_info data structure that has
  890.  * been filled by the application before the drag has started.
  891.  */
  892. int
  893. #ifdef __STDC__
  894. convert_proc(Selection_owner seln, Atom *type, Xv_opaque *data,
  895.          unsigned long *length, int *format)
  896. #else
  897. convert_proc(seln, type, data, length, format)
  898.     Selection_owner     seln;
  899.     Atom        *type;
  900.     Xv_opaque    *data;
  901.     unsigned long    *length;
  902.     int        *format;
  903. #endif
  904. {
  905.     int        length_buf;
  906.     char        *atom_name;
  907.     static Atom    target_list[12];
  908.     static Atom    types_list[2];
  909.     char        tmpfile [MAXPATHLEN];
  910.  
  911.  
  912.     /* 
  913.      * Try to turn the type and target atoms into 
  914.      *  some useful text for debugging. 
  915.      */
  916.     if (debug_on)
  917.     {
  918.         printf("convert_proc conversion called\n");
  919.  
  920.         if (type != NULL)
  921.             atom_name = XGetAtomName((Display *)xv_get(My_server, XV_DISPLAY), *type);
  922.         else
  923.             atom_name = "[None]";
  924.  
  925.         printf("convert_proc: being asked to convert %s\n", atom_name);
  926.     }
  927.  
  928.     /* 
  929.     * Interesting sidelight here.  You cannot simply set the type 
  930.     * in the reply to the type requested.  It must be the actual 
  931.     * type of the data returned.  HOST_NAME, for example would 
  932.     * be returned as type STRING. 
  933.     */
  934.  
  935.     if ((*type == selection_end_atom) || (*type == dragdrop_done_atom))
  936.     {
  937.         /* 
  938.          * Destination has told us it has completed the drag
  939.          * and drop transaction.  We should respond with a
  940.          * zero-length NULL reply and inform the application that
  941.          * the drag has been completed.
  942.          */
  943.  
  944.             Current_drop_site->drag_func(Current_drop_site->item, 
  945.                      Current_drop_site->event, 
  946.                      NULL, 
  947.                      GDD_DRAG_COMPLETED);    
  948.  
  949.         xv_set(xv_get(Current_drop_site->item, PANEL_DROP_DND), 
  950.             SEL_CONVERT_PROC, NULL, 
  951.             NULL);
  952.  
  953.         xv_set(Base_frame, 
  954.             FRAME_LEFT_FOOTER, dgettext("libguidexv", "Dragdrop: Completed"), 
  955.             NULL);
  956.  
  957.         *format = 32;
  958.         *length = 0;
  959.         *data = NULL;
  960.         *type = null_atom;
  961.         return(True);
  962.     } 
  963.  
  964.     else if (*type == delete_atom) 
  965.     {
  966.         /* 
  967.          * In our case, we chose not to listen to delete 
  968.             * commands on the drag/drop item.  The user can
  969.          * check for a MOVE event and delete the data if
  970.          * desired when the drop in completed. 
  971.          */
  972.  
  973.         *format = 32;
  974.         *length = 0;
  975.         *data = NULL;
  976.         *type = null_atom;
  977.         return(True);
  978.     } 
  979.     else if (*type == length_atom)
  980.     {
  981.         if (Drop_info->length)
  982.         {
  983.             length_buf = Drop_info->length;
  984.             *format = 32;
  985.             *length = 1;
  986.             *type = XA_INTEGER;
  987.             *data = (Xv_opaque) &length_buf;
  988.             return(True);
  989.         }
  990.     } 
  991.     else if (*type == enumeration_count_atom)
  992.     {
  993.         length_buf = 1;
  994.         *format = 32;
  995.         *length = 1;
  996.         *type = XA_INTEGER;
  997.         *data = (Xv_opaque) &length_buf;
  998.         return(True);
  999.     } 
  1000.     else if (*type == name_atom)
  1001.     {
  1002.         *format = 8;
  1003.         *length = strlen(Drop_info->app_name);
  1004.         *type = XA_STRING;
  1005.         *data = (Xv_opaque) Drop_info->app_name;
  1006.         return (True);
  1007.     }
  1008.     else if (*type == host_atom)
  1009.     {
  1010.         /* 
  1011.          * Return the hostname that the application 
  1012.          * is running on 
  1013.          */
  1014.         *format = 8;
  1015.         *length = strlen(Hostname);
  1016.         *data = (Xv_opaque) Hostname;
  1017.         *type = XA_STRING;
  1018.         return(True);
  1019.     } 
  1020.     else if (*type == alternate_transport_atom)
  1021.     {
  1022.         /* 
  1023.          * This request should return all of the targets 
  1024.          * that can be converted on this selection.  This 
  1025.          * includes the types, as well as the queries that 
  1026.          * can be issued. 
  1027.          */
  1028.  
  1029.         if ((Drop_info->filename && *Drop_info->filename))
  1030.         {
  1031.             *format = 32;
  1032.             *length = 1;
  1033.             *type = XA_ATOM;
  1034.             target_list[0] = atm_file_name_atom;
  1035.             *data = (Xv_opaque) target_list;
  1036.             return(True);
  1037.         }
  1038.         else
  1039.             return(False);
  1040.     } 
  1041.     else if (*type == targets_atom)
  1042.     {
  1043.  
  1044.         /* 
  1045.          * This request should return all of the targets 
  1046.          * that can be converted on this selection.  This 
  1047.          * includes the types, as well as the queries that 
  1048.          * can be issued. 
  1049.          */
  1050.  
  1051.         *format = 32;
  1052.         *length = 0;
  1053.         *type = XA_ATOM;
  1054.         target_list[(*length)++] = XA_STRING;
  1055.         target_list[(*length)++] = text_atom;
  1056.         target_list[(*length)++] = delete_atom;
  1057.         target_list[(*length)++] = targets_atom;
  1058.         target_list[(*length)++] = host_atom;
  1059.         target_list[(*length)++] = length_atom;
  1060.         target_list[(*length)++] = selection_end_atom;
  1061.         target_list[(*length)++] = dragdrop_done_atom;
  1062.         target_list[(*length)++] = available_types_atom;
  1063.         target_list[(*length)++] = name_atom;
  1064.  
  1065.         if (current_type)
  1066.         {
  1067.             target_list[*length] = current_type;
  1068.             (*length)++;
  1069.         }
  1070.         if (!(Drop_info->filename && *Drop_info->filename))
  1071.         {
  1072.             target_list[*length] = alternate_transport_atom;
  1073.             (*length)++;
  1074.         }
  1075.         *data = (Xv_opaque) target_list;
  1076.         return(True);
  1077.         } 
  1078.     else if (*type == available_types_atom)
  1079.     {
  1080.         /* 
  1081.          * This target returns all of the data types that 
  1082.          * the holder can convert on the selection. 
  1083.          */
  1084.         *format = 32;
  1085.         *length = 0;
  1086.         *type = XA_ATOM;
  1087.         types_list[(*length)++] = XA_STRING;
  1088.         if (current_type)
  1089.         {
  1090.             types_list[(*length)++] = current_type;
  1091.         }
  1092.         *data = (Xv_opaque) types_list;
  1093.         return(True);
  1094.         } 
  1095.     else if (*type == file_name_atom)
  1096.     {
  1097.         if (Drop_info->filename && *Drop_info->filename)
  1098.         {
  1099.             sprintf (tmpfile, "%s", Drop_info->filename);
  1100.  
  1101.             *format = 8;
  1102.             *length = strlen(tmpfile);
  1103.             *data = (Xv_opaque) tmpfile;
  1104.             *type = XA_STRING;
  1105.             return(True);
  1106.         }
  1107.         else
  1108.             return(False);
  1109.         } 
  1110.     else if (*type == data_label_atom)
  1111.     {
  1112.         if (Drop_info->data_label && *Drop_info->data_label)
  1113.         {
  1114.             sprintf (tmpfile, "%s", Drop_info->data_label);
  1115.  
  1116.             *format = 8;
  1117.             *length = strlen(tmpfile);
  1118.             *data = (Xv_opaque) tmpfile;
  1119.             *type = XA_STRING;
  1120.             return(True);
  1121.         }
  1122.         else
  1123.             return(False);
  1124.         } 
  1125.     else if ((*type == XA_STRING) || (*type == text_atom) || 
  1126.          (*type == current_type)) 
  1127.         {
  1128.  
  1129.         *format = 8;
  1130.         *length = Drop_info->length;
  1131.         if (Drop_info->data && *Drop_info->data)
  1132.             *data = (Xv_opaque) Drop_info->data;
  1133.         else
  1134.             *data = (Xv_opaque) Drop_info->filename;
  1135.         xfer_data_buf[*length] = NULL;
  1136.  
  1137.         if ((*type == text_atom) && current_type)
  1138.             *type = current_type;
  1139.  
  1140.         return(True);
  1141.     }
  1142.     else
  1143.     {
  1144.         /* 
  1145.          * Let the default convert procedure deal with the
  1146.          * request.
  1147.          */
  1148.  
  1149.         return(sel_convert_proc(seln, type, data, length, format));
  1150.     }
  1151. }
  1152.  
  1153.  
  1154. /* 
  1155.  * Stop the drag and drop operation.  Converts _SUN_SELECTION_END 
  1156.  * on the current selection, signaling the end, and then 
  1157.  * puts the rest of the application back to normal. 
  1158.  */
  1159. static void
  1160. stop_dragdrop()
  1161.  
  1162. {
  1163.     int    length, format;
  1164.  
  1165.     DP(("stop_dragdrop called\n"));
  1166.     /*
  1167.      * This code can be used to support a move operation.
  1168.       if (Current_drop_site->is_move)
  1169.       {
  1170.       xv_set(Sel, SEL_TYPE, delete_atom, 0);
  1171.       (void)xv_get(Sel, SEL_DATA, &length, &format);
  1172.       }
  1173.       */
  1174.  
  1175.     /* Signal termination of transaction */
  1176.     xv_set(Sel,
  1177.            SEL_REPLY_PROC, reply_proc,
  1178.            SEL_TYPES, 
  1179.            selection_end_atom, 
  1180.            0,
  1181.            0 );
  1182.  
  1183.     sel_post_req(Sel);
  1184.  
  1185.     /* reactivate the drop site */
  1186.  
  1187.     drop_site_on();
  1188.      
  1189.     clear_context(D, TRUE);
  1190. }
  1191.  
  1192. /*
  1193.  * Activate and de-activate the drop sites/targets.
  1194.  */
  1195. static void
  1196. drop_site_on()
  1197. {
  1198.  
  1199.     GDD_DROP_SITE     *ds;
  1200.  
  1201.     for (ds = Drop_sites; ds; ds = ds->next)
  1202.     {
  1203.         if (ds->is_drop_site)
  1204.             xv_set(ds->drop_site,
  1205.                    DROP_SITE_DELETE_REGION_PTR, NULL,
  1206.                    DROP_SITE_REGION_PTR, ds->rectlist,
  1207.                    0);
  1208.         else
  1209.             xv_set(ds->drop_site, PANEL_BUSY, FALSE, NULL);
  1210.     }
  1211. }
  1212.  
  1213.  
  1214. /*
  1215.  * Set up the atoms that we will support, assign the convert proc,
  1216.  * and post the initial selection request.
  1217.  */
  1218. static void
  1219. begin_item_transfer()
  1220. {
  1221.     int    end_enum_context = -1;
  1222.  
  1223.     xv_set(Sel,
  1224.            SEL_REPLY_PROC, reply_proc,
  1225.            SEL_TYPES, 
  1226.            enumeration_item_atom,
  1227.            targets_atom,
  1228.            host_atom,
  1229.            name_atom,
  1230.            alternate_transport_atom, 
  1231.            file_name_atom,
  1232.            data_label_atom,    
  1233.            enumeration_item_atom,
  1234.            0,
  1235.  
  1236.            SEL_TYPE_INDEX, 0,
  1237.            SEL_PROP_TYPE, XA_INTEGER,
  1238.            SEL_PROP_DATA, &D->objects_transferred,
  1239.            SEL_PROP_FORMAT, 32,
  1240.            SEL_PROP_LENGTH, 1,
  1241.            SEL_TYPE_INDEX, 6,
  1242.            SEL_PROP_TYPE, XA_INTEGER,
  1243.            SEL_PROP_DATA, &end_enum_context,
  1244.            SEL_PROP_FORMAT, 32,
  1245.            SEL_PROP_LENGTH, 1,
  1246.  
  1247.            0 );
  1248.  
  1249.     sel_post_req(Sel); 
  1250. }
  1251.  
  1252.  
  1253. /* 
  1254.  * Initial routine to kick of the transfer process.
  1255.  */
  1256. static void
  1257. #ifdef __STDC__
  1258. load_from_dragdrop(Xv_Server server, Event *event)
  1259. #else
  1260. load_from_dragdrop(server, event)
  1261.     Xv_Server    server;
  1262.     Event        *event;
  1263. #endif
  1264. {
  1265.     int        length, format;
  1266.     int        *count_ptr;
  1267.     GDD_DROP_SITE    *ds;
  1268.  
  1269.     if (debug_on)
  1270.     {
  1271.         printf("load_from_dragdrop: called\n");
  1272.     }
  1273.  
  1274.  
  1275.     /* deactivate the drop sites/targets */
  1276.     for (ds = Drop_sites; ds; ds = ds->next)
  1277.     {
  1278.         if (ds->is_drop_site)
  1279.             xv_set(ds->drop_site,
  1280.                 DROP_SITE_DELETE_REGION_PTR, NULL,
  1281.                 0);
  1282.         else
  1283.             xv_set(ds->drop_site, PANEL_BUSY, TRUE, NULL);
  1284.     }
  1285.  
  1286.     /* clear the left footer for new response status */
  1287.  
  1288.     xv_set(Base_frame, FRAME_LEFT_FOOTER, "", 0);
  1289.  
  1290.     clear_context(D, TRUE);
  1291.  
  1292.     xv_set(Sel, SEL_TYPE, enumeration_count_atom, 0);
  1293.  
  1294.     count_ptr = (int *) xv_get(Sel, SEL_DATA, &length, &format);
  1295.  
  1296.     if ((length <= 0) || !count_ptr)
  1297.     {
  1298.         /* 
  1299.          * Not supporting enumeration count is not necessarily 
  1300.          * fatal.  We just assume 1. 
  1301.          */
  1302.         D->object_count = 1;
  1303.     }
  1304.     else
  1305.     {
  1306.         D->object_count = *count_ptr;
  1307.     }
  1308.  
  1309.     if (debug_on)
  1310.         printf("holder had %d items\n", D->object_count);
  1311.  
  1312.     begin_item_transfer();
  1313.  
  1314.     if (debug_on)
  1315.     {
  1316.         printf("load_from_dragdrop: after sel_post_req\n");
  1317.     }
  1318.  
  1319. }
  1320.  
  1321. /* 
  1322.  * Event proc used to track Drag and Drop events for the application.
  1323.  */
  1324. Notify_value
  1325. #ifdef __STDC__
  1326. gdd_load_event_proc(Xv_opaque window, Event *event,
  1327.             Notify_arg arg, Notify_event_type type)
  1328. #else
  1329. gdd_load_event_proc(window, event, arg, type)
  1330.     Xv_opaque               window;
  1331.     Event                   *event;
  1332.     Notify_arg              arg;
  1333.     Notify_event_type       type;
  1334. #endif
  1335. {
  1336.     GDD_DROP_SITE    *ds;
  1337.  
  1338.            Xv_Server       server = XV_SERVER_FROM_WINDOW(event_window(event));
  1339.  
  1340.     /* 
  1341.      * Make sure the package has been initialized.
  1342.      */
  1343.     if (!Base_frame)
  1344.     {
  1345.         printf("gdd: gdd_init_dragdrop(frame_handle) has not been called, the drag and drop package has not been initialized.\n");
  1346.  
  1347.         return;
  1348.     }
  1349.  
  1350.     switch (event_action(event))
  1351.     {
  1352.     case ACTION_DRAG_COPY:
  1353.     case ACTION_DRAG_MOVE:
  1354.         
  1355.         Current_drop_site = NULL;
  1356.  
  1357.         /* Determine if this is a drop site or a drop target. If
  1358.          * it's a drop target, then just pass the event through
  1359.          * and let the drop target notify proc handle the event.
  1360.          * If it is a drop site, then figure out which one it is
  1361.          * and make it the current drop site.
  1362.          */
  1363.         for (ds = Drop_sites; ds; ds = ds->next)
  1364.         {
  1365.             if (!ds->is_drop_site && 
  1366.                 rect_includespoint((Rect *) xv_get(ds->drop_site,
  1367.                                    XV_RECT), event->ie_locx, event->ie_locy))
  1368.             {
  1369.                 /* Item is a drop target */
  1370.                 return (notify_next_event_func(window, 
  1371.                                    (Notify_event) event, arg, type));
  1372.             }
  1373.  
  1374.             /*
  1375.              * We can use the macro dnd_site_id() to access
  1376.              * the site id of the drop site that was
  1377.              * dropped on.
  1378.              */
  1379.             if (xv_get(ds->drop_site,
  1380.                    DROP_SITE_ID) == dnd_site_id(event))
  1381.             {
  1382.                 Current_drop_site = ds;
  1383.                 Current_drop_site->item = window;
  1384.                 Current_drop_site->event = event;
  1385.                 if (event_action(event) ==  
  1386.                     ACTION_DRAG_MOVE)
  1387.                     ds->is_move = TRUE;
  1388.                 else
  1389.                     ds->is_move = FALSE;
  1390.                 break;
  1391.             }
  1392.         }
  1393.  
  1394.         if (!Sel)
  1395.             Sel = xv_create(window, SELECTION_REQUESTOR, 0);
  1396.  
  1397.                 /* 
  1398.          * To acknowledge the drop and to associate the
  1399.          * rank of the source's selection to our
  1400.          * requestor selection object, we call
  1401.          * dnd_decode_drop().
  1402.          */
  1403.  
  1404.             if (dnd_decode_drop(Sel, event) != XV_ERROR) 
  1405.         {
  1406.             if (Current_drop_site)
  1407.                         load_from_dragdrop(server, event);
  1408.             } 
  1409.         else
  1410.         {
  1411.             if (debug_on)
  1412.                         printf ("drop error\n");
  1413.         }
  1414.  
  1415.         return NOTIFY_DONE;
  1416.     }
  1417.  
  1418.     return (notify_next_event_func(window, (Notify_event) event, arg, type));
  1419. }
  1420.  
  1421. /*
  1422.  * Notify procedure for drop targets to deal with drag and drop operations.
  1423.  */
  1424. int
  1425. #ifdef __STDC__
  1426. gdd_drop_target_notify_proc(Panel_item item, unsigned int value, Event *event)
  1427. #else
  1428. gdd_drop_target_notify_proc(item, value, event)
  1429.     Panel_item    item;
  1430.     unsigned int    value;
  1431.     Event        *event;
  1432. #endif
  1433. {
  1434.  
  1435.     GDD_DROP_SITE    *ds;
  1436.            Xv_Server       server;
  1437.         Drag_drop    dnd = xv_get(item, PANEL_DROP_DND);
  1438.  
  1439.     if (!Base_frame)
  1440.     {
  1441.         printf("gdd: gdd_init_dragdrop(frame_handle) has not been called, the drag and drop package has not been initialized.\n");
  1442.  
  1443.         return XV_ERROR;
  1444.     }
  1445.  
  1446.     Sel = (Selection_requestor) xv_get(item, PANEL_DROP_SEL_REQ);
  1447.  
  1448.     switch (event_action(event))
  1449.     {
  1450.     case ACTION_DRAG_COPY:
  1451.     case ACTION_DRAG_MOVE:
  1452.  
  1453.         Current_drop_site = NULL;
  1454.  
  1455.         for (ds = Drop_sites; ds; ds = ds->next)
  1456.         {
  1457.             if (!ds->is_drop_site && (item == ds->drop_site) &&
  1458.                 ds->drop_func)
  1459.             {
  1460.                 Current_drop_site = ds;
  1461.                 Current_drop_site->item = item; 
  1462.                 Current_drop_site->event = event; 
  1463.                 if (event_action(event) ==  
  1464.                     ACTION_DRAG_MOVE)
  1465.                     ds->is_move = TRUE;
  1466.                 else
  1467.                     ds->is_move = FALSE;
  1468.                 break;
  1469.  
  1470.             }
  1471.         }
  1472.  
  1473.         if (Current_drop_site)
  1474.         {
  1475.             server = XV_SERVER_FROM_WINDOW(event_window(event));
  1476.                        load_from_dragdrop(server, event);
  1477.         }
  1478.  
  1479.         break;
  1480.  
  1481.     case LOC_DRAG:
  1482.         if (value == XV_OK)
  1483.         {
  1484.             Current_drop_site = NULL;
  1485.  
  1486.             for (ds = Drop_sites; ds; ds = ds->next)
  1487.             {
  1488.                 if (!ds->is_drop_site && item == ds->drop_site)
  1489.                 {
  1490.                     Current_drop_site = ds;
  1491.                     Current_drop_site->item = item; 
  1492.                     Current_drop_site->event = event; 
  1493.                     break;
  1494.  
  1495.                 }
  1496.             }
  1497.  
  1498.             if (Current_drop_site && Current_drop_site->drag_func)
  1499.             {
  1500.                 Drop_info = (GDD_DROP_INFO *) calloc(1, sizeof(GDD_DROP_INFO));
  1501.                 Current_drop_site->drag_func(item, event, Drop_info, GDD_DRAG_STARTED);    
  1502.                 set_drag_data(&Drop_info);
  1503.  
  1504.                 xv_set(dnd, SEL_CONVERT_PROC, convert_proc, NULL);
  1505.             }
  1506.         }
  1507.         else
  1508.                   xv_set(Base_frame, 
  1509.                    FRAME_LEFT_FOOTER, Dnd_codes[MIN(value, 7)], 
  1510.                    NULL);
  1511.  
  1512.         break;
  1513.     default:
  1514.         break;
  1515.     }
  1516.  
  1517.     return XV_ERROR;
  1518. }
  1519.  
  1520. /*
  1521.  * Initialize the dragdrop package. Set up a frame handle to post 
  1522.  * messages to.
  1523.  */
  1524. void
  1525. #ifdef __STDC__
  1526. gdd_init_dragdrop(Xv_opaque frame)
  1527. #else
  1528. gdd_init_dragdrop(frame)
  1529.     Xv_opaque frame;
  1530.  
  1531. #endif
  1532. {
  1533.     static int    initialized = FALSE;
  1534.  
  1535.     if (!frame || (xv_get(frame, FRAME_LEFT_FOOTER) == XV_ERROR))
  1536.     {
  1537.         fprintf(stderr, "Invalid Base Frame handle passed to gdd_init_dragdrop().\n");
  1538.     }
  1539.     else
  1540.         Base_frame = frame;
  1541.  
  1542.     /*
  1543.      * Initialize atom variables and error messages. Only do
  1544.      * this once.
  1545.      */
  1546.     if (initialized)
  1547.         return;
  1548.  
  1549.     My_server = XV_SERVER_FROM_WINDOW(Base_frame);
  1550. #ifdef SVR4    
  1551.     gethostname(Hostname, MAXNAMELEN);
  1552. #else
  1553.     gethostname(Hostname, MAXHOSTNAMELEN);
  1554. #endif
  1555.  
  1556.     text_atom = xv_get(My_server, SERVER_ATOM, "TEXT");
  1557.     incr_atom = xv_get(My_server, SERVER_ATOM, "INCR");
  1558.     targets_atom = xv_get(My_server, SERVER_ATOM, "TARGETS");
  1559.     length_atom = xv_get(My_server, SERVER_ATOM, "LENGTH");
  1560.     host_atom = xv_get(My_server, SERVER_ATOM, "_SUN_FILE_HOST_NAME");
  1561.     name_atom = xv_get(My_server, SERVER_ATOM, "NAME");
  1562.     file_name_atom = xv_get(My_server, SERVER_ATOM, "FILE_NAME");
  1563.     atm_file_name_atom = xv_get(My_server, SERVER_ATOM,
  1564.                     "_SUN_ATM_FILE_NAME");
  1565.     delete_atom = xv_get(My_server, SERVER_ATOM, "DELETE");
  1566.     selection_end_atom = xv_get(My_server, SERVER_ATOM, "_SUN_SELECTION_END");
  1567.     dragdrop_done_atom = xv_get(My_server, SERVER_ATOM, "_SUN_DRAGDROP_DONE");
  1568.     data_label_atom = xv_get(My_server, SERVER_ATOM, "_SUN_DATA_LABEL");
  1569.     alternate_transport_atom = xv_get(My_server, SERVER_ATOM, "_SUN_ALTERNATE_TRANSPORT_METHODS");
  1570.     available_types_atom = xv_get(My_server, SERVER_ATOM, "_SUN_AVAILABLE_TYPES");
  1571.  
  1572.     enumeration_count_atom = xv_get(My_server, SERVER_ATOM, "_SUN_ENUMERATION_COUNT");
  1573.     enumeration_item_atom = xv_get(My_server, SERVER_ATOM, "_SUN_ENUMERATION_ITEM");
  1574.     null_atom = xv_get(My_server, SERVER_ATOM, "NULL");
  1575.     current_type = NULL;
  1576.     
  1577.     D = (GDD_CONTEXT *) malloc(sizeof(GDD_CONTEXT));
  1578.     memset((char *) D, NULL, sizeof(GDD_CONTEXT));
  1579.     
  1580.     init_dnd_code_table();
  1581.  
  1582.     initialized = TRUE;
  1583. }
  1584.  
  1585. /*
  1586.  * Register a drop site with the drag and drop target. Basically just
  1587.  * adds a new data structure to a linked list.
  1588.  */
  1589. void
  1590. #ifdef __STDC__
  1591. gdd_register_drop_site(Xv_opaque drop_site, void (*f)())
  1592. #else
  1593. gdd_register_drop_site(drop_site, f)
  1594.     Xv_opaque    drop_site;
  1595.     void         (*f)();
  1596. #endif
  1597. {
  1598.     GDD_DROP_SITE    *ds;
  1599.  
  1600.     ds = (GDD_DROP_SITE *) calloc(1, sizeof(GDD_DROP_SITE));
  1601.     
  1602.     ds->drop_site = drop_site;
  1603.     ds->is_drop_site = TRUE;
  1604.     ds->drop_func = f;
  1605.  
  1606.     drop_site_append(&Drop_sites, ds);
  1607.  
  1608. }
  1609.  
  1610. /*
  1611.  * Register a drop target with the drag and drop target. Basically,
  1612.  * just adds a new data structure to a linked list. 
  1613.  */
  1614. void
  1615. #ifdef __STDC__
  1616. gdd_register_drop_target(Xv_opaque target_item, void (*drop_func)(),
  1617.              void (*drag_func)())
  1618. #else
  1619. gdd_register_drop_target(target_item, drop_func, drag_func)
  1620.     Xv_opaque    target_item;
  1621.     void         (*drop_func)();
  1622.     void         (*drag_func)();
  1623. #endif
  1624. {
  1625.     GDD_DROP_SITE    *ds;
  1626.  
  1627.     ds = (GDD_DROP_SITE *) calloc(1, sizeof(GDD_DROP_SITE));
  1628.  
  1629.     ds->drop_site = target_item;
  1630.     ds->is_drop_site = FALSE;
  1631.     ds->drop_func = drop_func;
  1632.     if (drag_func)
  1633.     {
  1634.         ds->drag_func = drag_func;
  1635.     }
  1636.  
  1637.     drop_site_append(&Drop_sites, ds);
  1638.  
  1639. }
  1640.  
  1641. /* Unregister a drop site or a drop target from the drag and drop 
  1642.  * package.
  1643.  */
  1644. void
  1645. #ifdef __STDC__
  1646. gdd_unregister_drop_site(Xv_opaque drop_site)
  1647. #else
  1648. gdd_unregister_drop_site(drop_site)
  1649.     Xv_opaque    drop_site;
  1650. #endif
  1651. {
  1652.  
  1653.     GDD_DROP_SITE     *ds;
  1654.     GDD_DROP_SITE     *previous;
  1655.         Drag_drop    dnd; 
  1656.  
  1657.     for (ds = Drop_sites, previous = Drop_sites; ds; ds = ds->next)
  1658.     {
  1659.         if (ds->drop_site == drop_site)
  1660.         {
  1661.             if (ds == Drop_sites)
  1662.             {
  1663.                 Drop_sites = ds->next;
  1664.             }
  1665.             else
  1666.             {
  1667.                 previous->next = ds->next;
  1668.             }
  1669.             
  1670.             /*
  1671.              * If drop target, make sure that it does not
  1672.              * have a convert proc on it.
  1673.              */
  1674.             if (!ds->is_drop_site)
  1675.             {
  1676.                  dnd = xv_get(drop_site, PANEL_DROP_DND);
  1677.                 if (dnd)
  1678.                     xv_set(dnd,
  1679.                         SEL_CONVERT_PROC, NULL,
  1680.                         NULL);
  1681.              }
  1682.  
  1683.             free(ds);
  1684.             break;
  1685.         }
  1686.         else
  1687.             previous = ds;
  1688.     }
  1689. }
  1690.  
  1691. /*
  1692.  * Activate a drop site. Accepts a pointer to a list of Rect structures
  1693.  * that indicate which regions within a pane are valid drop regions.
  1694.  * The list needs to be terminated with a Rect whose width or height
  1695.  * are set to zero. This function only works for previously registered
  1696.  * drop sites.
  1697.  * If NULL is passed in in the rectlist field, the region will become
  1698.  * a non-active region within the window.
  1699.  */
  1700. void
  1701. #ifdef __STDC__
  1702. gdd_activate_drop_site(Xv_opaque drop_site, Rect rectlist[])
  1703. #else
  1704. gdd_activate_drop_site(drop_site, rectlist)
  1705.     Xv_opaque    drop_site;
  1706.     Rect        rectlist[];
  1707. #endif
  1708. {
  1709.     int        i, count;
  1710.     GDD_DROP_SITE    *ds;
  1711.     Rect        *rp;
  1712.  
  1713.     for (ds = Drop_sites; ds; ds = ds->next)
  1714.     {
  1715.         if (ds->drop_site == drop_site)
  1716.             break;
  1717.     }
  1718.  
  1719.     if (!ds || !ds->drop_site)
  1720.     {
  1721.         fprintf(stderr, "gdd_activate_drop_site: Invalid drop site\n");
  1722.         return;
  1723.     }
  1724.  
  1725.  
  1726.     if (rectlist)
  1727.     {
  1728.         for (count = 0, rp = rectlist; !rect_isnull(rp); rp++, count++)
  1729.             ;
  1730.  
  1731.         if (!ds->rectlist)
  1732.             ds->rectlist = (Rect *) malloc((count + 1) *
  1733.                                sizeof(Rect));
  1734.         else if (sizeof(ds->rectlist) != ((count +1) * sizeof(Rect)))
  1735.         {
  1736.             free(ds->rectlist);
  1737.             ds->rectlist = (Rect *) malloc((count + 1) *
  1738.                                sizeof(Rect));
  1739.         }
  1740.  
  1741.         for (i = 0, rp = rectlist; !rect_isnull(rp); rp++, i++)
  1742.             ds->rectlist[i] = *rp;
  1743.         ds->rectlist[i] = *rp; /* include last item (Null item) */
  1744.  
  1745.  
  1746.         if (ds->rectlist)
  1747.         {
  1748.             xv_set(ds->drop_site,
  1749.                    DROP_SITE_REGION_PTR, ds->rectlist,
  1750.                    0);
  1751.         }
  1752.     }
  1753.     else
  1754.     {
  1755.         free(ds->rectlist);
  1756.         xv_set(ds->drop_site, DROP_SITE_DELETE_REGION_PTR, NULL, 0);
  1757.     }
  1758. }
  1759.  
  1760. /*
  1761.  * Utility function to add data structures to the link list.
  1762.  */
  1763. static void
  1764. #ifdef __STDC__
  1765. drop_site_append(GDD_DROP_SITE **drop_site, GDD_DROP_SITE *ds)
  1766. #else
  1767. drop_site_append(drop_site, ds)
  1768.     GDD_DROP_SITE    **drop_site, *ds;
  1769. #endif
  1770. {
  1771.     
  1772.     if (!(*drop_site))
  1773.     {
  1774.         *drop_site = (GDD_DROP_SITE *) calloc(1,
  1775.                               sizeof(GDD_DROP_SITE));
  1776.         *drop_site = ds;
  1777.         (*drop_site)->next = NULL;
  1778.     }
  1779.     else
  1780.     {
  1781.         ds->next = *drop_site;
  1782.         *drop_site = ds;
  1783.     }
  1784. }
  1785.  
  1786. /*
  1787.  * Ready a drop info structure to pass back to the application after
  1788.  * a drop has been processed.
  1789.  */
  1790. static void
  1791. #ifdef __STDC__
  1792. fill_drop_info(GDD_CONTEXT *dnd_ptr, GDD_DROP_INFO **di_ptr,
  1793.            char *char_buf, int len)
  1794. #else
  1795. fill_drop_info(dnd_ptr, di_ptr, char_buf, len)
  1796.     GDD_CONTEXT    *dnd_ptr;
  1797.     GDD_DROP_INFO     **di_ptr;
  1798.     char        *char_buf;
  1799.     int        len;
  1800. #endif
  1801. {
  1802.     char    dir[MAXPATHLEN];
  1803.     char    file[MAXPATHLEN];
  1804.  
  1805.     *di_ptr = (GDD_DROP_INFO *) calloc(1, sizeof(GDD_DROP_INFO));
  1806.  
  1807.     if (dnd_ptr->tmpfile_name &&
  1808.         (strcmp(dnd_ptr->tmpfile_name, "") != 0 ))
  1809.     {
  1810.         if (dnd_ptr->data_label)
  1811.         {
  1812.             parse_path(NULL, dnd_ptr->tmpfile_name, dir, file);
  1813.             sprintf(file,"%s/%s", dir, dnd_ptr->data_label);
  1814.             rename(dnd_ptr->tmpfile_name, file);
  1815.             strcpy(dnd_ptr->tmpfile_name, file);
  1816.         }
  1817.     }    
  1818.  
  1819.     if (dnd_ptr->data_label)
  1820.         (*di_ptr)->data_label = strdup(dnd_ptr->data_label);
  1821.     if (dnd_ptr->source_host)
  1822.         (*di_ptr)->source_host =  strdup(dnd_ptr->source_host);
  1823.     if (dnd_ptr->source_name)
  1824.         (*di_ptr)->app_name =  strdup(dnd_ptr->source_name);
  1825.     if (dnd_ptr->source_filename)
  1826.         (*di_ptr)->filename =  strdup(dnd_ptr->source_filename);
  1827.     if (dnd_ptr->tmpfile_name)
  1828.         (*di_ptr)->tmpfile =  strdup(dnd_ptr->tmpfile_name);
  1829.     if(char_buf && len > 0)
  1830.     {
  1831.         (*di_ptr)->data = strdup(char_buf);
  1832.         (*di_ptr)->length = len;
  1833.     }
  1834.  
  1835. }
  1836.  
  1837. /*
  1838.  * Free up the drop info structure.
  1839.  */
  1840. static void
  1841. #ifdef __STDC__
  1842. free_drop_info(GDD_DROP_INFO *di_ptr)
  1843. #else
  1844. free_drop_info(di_ptr)
  1845.     GDD_DROP_INFO    *di_ptr;
  1846. #endif
  1847. {
  1848.     if (!di_ptr)
  1849.         return;
  1850.  
  1851.     if (di_ptr->data_label)
  1852.         free(di_ptr->data_label);
  1853.     if (di_ptr->source_host)
  1854.         free(di_ptr->source_host);
  1855.     if (di_ptr->app_name)
  1856.         free(di_ptr->app_name);
  1857.     if (di_ptr->filename)
  1858.         free(di_ptr->filename);
  1859.     if (di_ptr->data)
  1860.         free(di_ptr->data);
  1861.     if (di_ptr->tmpfile)
  1862.     {
  1863.         unlink(di_ptr->tmpfile);
  1864.         free(di_ptr->tmpfile);
  1865.     }
  1866.     
  1867.     free(di_ptr);
  1868. }
  1869.  
  1870. /*
  1871.  * Set up any drag data that needs to be set but wasn't by the application.
  1872.  */
  1873. static void
  1874. #ifdef __STDC__
  1875. set_drag_data(GDD_DROP_INFO **di)
  1876. #else
  1877. set_drag_data(di)
  1878.     GDD_DROP_INFO    **di;
  1879. #endif
  1880. {
  1881.     if (((*di)->data && *(*di)->data) && !(*di)->length)
  1882.         (*di)->length = strlen((*di)->data);
  1883. }
  1884.  
  1885.  
  1886. /*
  1887.  * Utility function to be used for experimentation with different
  1888.  * kind of sources dropping on the application.
  1889.  */
  1890. void
  1891. #ifdef __STDC__
  1892. gdd_print_drop_info(GDD_DROP_INFO *di)
  1893. #else
  1894. gdd_print_drop_info(di)
  1895.     GDD_DROP_INFO    *di;
  1896. #endif
  1897. {
  1898.     
  1899.     printf("\tdata_label: %s\n", di->data_label ? di->data_label : "");
  1900.     printf("\tsource_host: %s\n", di->source_host ? di->source_host : "");
  1901.     printf("\tapp_name: %s\n", di->app_name ? di->app_name : "");
  1902.     printf("\tfilename: %s\n", di->filename ? di->filename : "");
  1903.     printf("\ttmpfile: %s\n", di->tmpfile ? di->tmpfile : "");
  1904.     printf("\tlength: %d\n", di->length);
  1905.     printf("\tdata: %s\n", di->data ? di->data : "");
  1906.     printf("\n");
  1907. }
  1908.  
  1909. /*
  1910.  * NOTE: This routine is no longer supported. It has been replaced with
  1911.  * the new Drag and Drop package.
  1912.  *
  1913.  * Get the name of the file being dragged and dropped.  Sets the file name
  1914.  * and returns 0 if successful, otherwise returns -1.
  1915.  */
  1916. int
  1917. #ifdef __STDC__
  1918. gdd_get_drag_name(Xv_window window, char *name)
  1919. #else
  1920. gdd_get_drag_name(window, name)
  1921.     Xv_window       window;            /* event window */
  1922.     char           *name;            /* MAXPATHLEN length buffer */
  1923. #endif
  1924. {
  1925.     printf("gdd_get_drag_name is no longer a supported function\n");
  1926.     return -1;
  1927. }
  1928.  
  1929. /*
  1930.  * NOTE: This routine is no longer supported. It has been replaced with
  1931.  * the new Drag and Drop package.
  1932.  *
  1933.  * Send the name of a file being dragged and dropped.  Returns 0 if 
  1934.  * successful, otherwise -1.
  1935.  */
  1936. int
  1937. #ifdef __STDC__
  1938. gdd_set_drag_name(Xv_window source_win, Xv_window dest_win,
  1939.           int x, int y, char *name)
  1940. #else
  1941. gdd_set_drag_name(source_win, dest_win, x, y, name)
  1942.     Xv_window    source_win;        /* source window */
  1943.     Xv_window    dest_win;        /* destination window */
  1944.     int        x;            /* drop x */
  1945.     int        y;            /* drop y */
  1946.     char           *name;            /* file name */
  1947. #endif
  1948. {
  1949.     printf("gdd_set_drag_name is no longer a supported function\n");
  1950.     return -1;
  1951. }
  1952.  
  1953. /*
  1954.  * NOTE: This routine is no longer supported. It has been replaced with
  1955.  * the new Drag and Drop package.
  1956.  *
  1957.  * Drag a glyph around the screen, send an ACTION_DRAG_LOAD message to
  1958.  * the window under the pointer when dropped.  Returns XID of winow dropped
  1959.  * on, -1 for error.
  1960.  */
  1961. int
  1962. #ifdef __STDC__
  1963. gdd_drag_file(Xv_window src_win, Server_image drag_image, char *filename)
  1964. #else
  1965. gdd_drag_file(src_win, drag_image, filename)
  1966.     Xv_window    src_win;
  1967.     Server_image    drag_image;
  1968.     char        *filename;
  1969. #endif
  1970. {
  1971.     printf("gdd_set_drag_name is no longer a supported function\n");
  1972.     return -1;
  1973. }
  1974.