home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / GNU_C++ / LIB / CFLIB-11.LZH / src / dragdrop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-01  |  7.0 KB  |  335 lines

  1. /*
  2.  * Drag & drop sample code.
  3.  * Copyright 1992 Atari Corporation
  4.  *
  5.  * global variables used:
  6.  * gl_apid: our AES application id
  7.  *
  8.  * BUGS/CAVEATS:
  9.  * This code is not re-entrant (it uses a static
  10.  * variable for the pipe name and for saving the
  11.  * SIGPIPE signal handler).
  12.  *
  13.  * While doing the drag and drop, the SIGPIPE
  14.  * signal (write on an empty pipe) is ignored
  15.  */
  16. #include <string.h>
  17.  
  18. #ifdef __MINT__
  19. #include <mint/atarierr.h>
  20. #include <signal.h>
  21. static __Sigfunc    oldpipesig;
  22. #else
  23. #include <atarierr.h>
  24. static long    oldpipesig;
  25. #endif
  26.  
  27. #include "intern.h"
  28.  
  29. static char            pipename[] = "u:\\pipe\\dragdrop.aa";
  30.  
  31.  
  32. /* Code for originator */
  33.  
  34.  
  35. /*
  36.  * ddcreate: create a pipe for doing the drag & drop,
  37.  *           and send an AES message to the receipient
  38.  *           application telling it about the drag & drop
  39.  *           operation.
  40.  *
  41.  * Input Parameters:
  42.  * apid:    AES id of the window owner
  43.  * winid:    target window (0 for background)
  44.  * msx, msy:    mouse X and Y position
  45.  *        (or -1, -1 if a fake drag & drop)
  46.  * kstate:    shift key state at time of event
  47.  *
  48.  * Output Parameters:
  49.  * exts:    A 32 byte buffer into which the
  50.  *        receipient's 8 favorite
  51.  *        extensions will be copied.
  52.  *
  53.  * Returns:
  54.  * A positive file descriptor (of the opened
  55.  * drag & drop pipe) on success.
  56.  * -1 if the receipient doesn't respond or
  57.  *    returns DD_NAK
  58.  * -2 if appl_write fails
  59.  */
  60. int dd_create(int apid, int winid, int msx, int msy, int kstate, char *exts)
  61. {
  62.     int     fd, i;
  63.     short    msg[8];
  64.     long     fd_mask;
  65.     char     c;
  66.  
  67.     pipename[17] = pipename[18] = 'A';
  68.     fd = -1;
  69.     do 
  70.     {
  71.         pipename[18]++;
  72.         if (pipename[18] > 'Z') 
  73.         {
  74.             pipename[17]++;
  75.             if (pipename[17] > 'Z')
  76.                 break;
  77.         }
  78.         /* FA_HIDDEN means "get EOF if nobody has pipe open for reading" */
  79.         fd = (int)Fcreate(pipename, FA_HIDDEN);
  80.     } 
  81.     while (fd == EACCDN);
  82.  
  83.     if (fd < 0) 
  84.         return fd;
  85.  
  86.     /* construct and send the AES message */
  87.     msg[0] = AP_DRAGDROP;
  88.     msg[1] = gl_apid;
  89.     msg[2] = 0;
  90.     msg[3] = winid;
  91.     msg[4] = msx;
  92.     msg[5] = msy;
  93.     msg[6] = kstate;
  94.     msg[7] = (pipename[17] << 8) | pipename[18];
  95.     i = appl_write(apid, (int)sizeof(msg), msg);
  96.     if (i == 0) 
  97.     {
  98.         Fclose(fd);
  99.         return -2;
  100.     }
  101.  
  102.     /* now wait for a response */
  103.     fd_mask = 1L << fd;
  104.     i = Fselect(DD_TIMEOUT, &fd_mask, 0L, 0L);
  105.     if (!i || !fd_mask)     /* timeout happened */
  106.     {
  107.         Fclose(fd);
  108.         return -1;
  109.     }
  110.  
  111.     /* read the 1 byte response */
  112.     i = (int)Fread(fd, 1L, &c);
  113.     if (i != 1 || c != DD_OK) 
  114.     {
  115.         Fclose(fd);
  116.         return -1;
  117.     }
  118.  
  119.     /* now read the "preferred extensions" */
  120.     i = (int)Fread(fd, DD_EXTSIZE, exts);
  121.     if (i != DD_EXTSIZE) 
  122.     {
  123.         Fclose(fd);
  124.         return -1;
  125.     }
  126.  
  127. #ifdef __MINT__
  128.     oldpipesig = signal(SIGPIPE, SIG_IGN);
  129. #else
  130.     oldpipesig = (long)Psignal(SIGPIPE, SIG_IGN);
  131. #endif
  132.     return fd;
  133. }
  134.  
  135.  
  136. /*
  137.  * ddstry: see if the receipient is willing to accept a certain
  138.  *         type of data (as indicated by "ext")
  139.  *
  140.  * Input parameters:
  141.  * fd        file descriptor returned from ddcreate()
  142.  * ext        pointer to the 4 byte file type
  143.  * name        pointer to the name of the data
  144.  * size        number of bytes of data that will be sent
  145.  *
  146.  * Output parameters: none
  147.  *
  148.  * Returns:
  149.  * DD_OK    if the receiver will accept the data
  150.  * DD_EXT    if the receiver doesn't like the data type
  151.  * DD_LEN    if the receiver doesn't like the data size
  152.  * DD_NAK    if the receiver aborts
  153.  */
  154. int dd_stry(int fd, char *ext, char *name, long size)
  155. {
  156.     short    hdrlen, i;
  157.     char     c;
  158.  
  159.     /* 4 bytes for extension, 4 bytes for size, 1 byte for
  160.      * trailing 0
  161.      */
  162.     hdrlen = 9 + strlen(name);
  163.     i = Fwrite(fd, 2L, &hdrlen);
  164.  
  165.     /* now send the header */
  166.     if (i != 2) 
  167.         return DD_NAK;
  168.     i = Fwrite(fd, 4L, ext);
  169.     i += Fwrite(fd, 4L, &size);
  170.     i += Fwrite(fd, (long)strlen(name)+1, name);
  171.     if (i != hdrlen) 
  172.         return DD_NAK;
  173.  
  174.     /* wait for a reply */
  175.     i = Fread(fd, 1L, &c);
  176.     if (i != 1) 
  177.         return DD_NAK;
  178.     return c;
  179. }
  180.  
  181.  
  182. /* Code for either receipient or originator */
  183.  
  184.  
  185. /*
  186.  * ddclose: close a drag & drop operation
  187.  */
  188. void    dd_close(int fd)
  189. {
  190. #ifdef __MINT__
  191.     (void)signal(SIGPIPE, oldpipesig);
  192. #else
  193.     Psignal(SIGPIPE, (void *)oldpipesig);
  194. #endif
  195.     (void)Fclose(fd);
  196. }
  197.  
  198.  
  199.  
  200. /* Code for receipient */
  201.  
  202.  
  203. /*
  204.  * ddopen: open a drag & drop pipe
  205.  *
  206.  * Input Parameters:
  207.  * ddnam:    the pipe's name (from the last word of
  208.  *        the AES message)
  209.  * preferext:    a list of DD_NUMEXTS 4 byte extensions we understand
  210.  *        these should be listed in order of preference
  211.  *        if we like fewer than DD_NUMEXTS extensions, the
  212.  *        list should be padded with 0s
  213.  *
  214.  * Output Parameters: none
  215.  *
  216.  * Returns:
  217.  * A (positive) file handle for the drag & drop pipe, on success
  218.  * -1 if the drag & drop is aborted
  219.  * A negative error number if an error occurs while opening the
  220.  * pipe.
  221.  */
  222. int    dd_open(int ddnam, char *preferext)
  223. {
  224.     int     fd;
  225.     char    outbuf[DD_EXTSIZE+1];
  226.  
  227.     pipename[18] = ddnam & 0x00ff;
  228.     pipename[17] = (ddnam & 0xff00) >> 8;
  229.  
  230.     fd = (int)Fopen(pipename, 2);
  231.     if (fd < 0) return fd;
  232.  
  233.     outbuf[0] = DD_OK;
  234.     strncpy(outbuf+1, preferext, DD_EXTSIZE);
  235.  
  236. #ifdef __MINT__
  237.     oldpipesig = signal(SIGPIPE, SIG_IGN);
  238. #else
  239.     oldpipesig = (long)Psignal(SIGPIPE, SIG_IGN);
  240. #endif
  241.  
  242.     if (Fwrite(fd, (long)DD_EXTSIZE+1, outbuf) != DD_EXTSIZE+1) 
  243.     {
  244.         dd_close(fd);
  245.         return -1;
  246.     }
  247.  
  248.     return fd;
  249. }
  250.  
  251.  
  252. /*
  253.  * ddrtry: get the next header from the drag & drop originator
  254.  *
  255.  * Input Parameters:
  256.  * fd:        the pipe handle returned from ddopen()
  257.  *
  258.  * Output Parameters:
  259.  * name:    a pointer to the name of the drag & drop item
  260.  *        (note: this area must be at least DD_NAMEMAX bytes long)
  261.  * whichext:    a pointer to the 4 byte extension
  262.  * size:    a pointer to the size of the data
  263.  *
  264.  * Returns:
  265.  * TRUE on success
  266.  * FALSE if the originator aborts the transfer
  267.  *
  268.  * Note: it is the caller's responsibility to actually
  269.  * send the DD_OK byte to start the transfer, or to
  270.  * send a DD_NAK, DD_EXT, or DD_LEN reply with ddreply().
  271.  */
  272. int dd_rtry(int fd, char *name, char *whichext, long *size)
  273. {
  274.     short    hdrlen;
  275.     int     i;
  276.     char     buf[80];
  277.  
  278.     i = (int)Fread(fd, 2L, &hdrlen);
  279.     if (i != 2) 
  280.         return FALSE;
  281.     if (hdrlen < 9)     /* this should never happen */
  282.         return FALSE;
  283.     i = (int)Fread(fd, 4L, whichext);
  284.     if (i != 4) 
  285.         return FALSE;
  286.     whichext[4] = 0;
  287.     i = (int)Fread(fd, 4L, size);
  288.     if (i != 4) 
  289.         return FALSE;
  290.     hdrlen -= 8;
  291.     if (hdrlen > DD_NAMEMAX)
  292.         i = DD_NAMEMAX;
  293.     else
  294.         i = hdrlen;
  295.     if (Fread(fd, (long)i, name) != i) 
  296.         return FALSE;
  297.     hdrlen -= i;
  298.  
  299.     /* skip any extra header */
  300.     while (hdrlen > 80) 
  301.     {
  302.         Fread(fd, 80L, buf);
  303.         hdrlen -= 80;
  304.     }
  305.     if (hdrlen > 0)
  306.         Fread(fd, (long)hdrlen, buf);
  307.  
  308.     return TRUE;
  309. }
  310.  
  311.  
  312. /*
  313.  * ddreply: send a 1 byte reply to the drag & drop originator
  314.  *
  315.  * Input Parameters:
  316.  * fd:        file handle returned from ddopen()
  317.  * ack:        byte to send (e.g. DD_OK)
  318.  *
  319.  * Output Parameters:
  320.  * none
  321.  *
  322.  * Returns: TRUE on success, FALSE on failure
  323.  * in the latter case the file descriptor is closed
  324.  */
  325. int dd_reply(int fd, int ack)
  326. {
  327.     char c = ack;
  328.  
  329.     if (Fwrite(fd, 1L, &c) == 1L) 
  330.         return TRUE;
  331.     else
  332.         Fclose(fd);
  333.     return FALSE;
  334. }
  335.