home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 426.lha / ClipFile_v1.02 / src / clip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-07  |  10.1 KB  |  468 lines

  1. /* clip.c
  2.  * Written by David N. Junod - August 28, 1990.
  3.  * Main routines for CF (ClipFile).
  4.  *
  5.  * CF was written so that I could quickly, an easily, access (test) the
  6.  * clipboard while writing the clipboard routines for rexxutil.library
  7.  * (and the clipboard example for AmigaMail).
  8.  *
  9.  * BTW---This program isn't written in my usual style.  This time around I
  10.  * went for using as many of the SAS/C functions as possible.
  11.  *
  12.  */
  13.  
  14. #include <exec/types.h>
  15. #include <exec/libraries.h>
  16. #include <exec/memory.h>
  17. #include <exec/ports.h>
  18. #include <dos/dos.h>
  19. #include <dos/notify.h>
  20. #include <devices/clipboard.h>
  21. #include <clib/exec_protos.h>
  22. #include <clib/dos_protos.h>
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <fcntl.h>
  28. #include <error.h>
  29.  
  30. #include "cf.h"
  31. #include "cf_protos.h"
  32.  
  33. /* So that we can check OS versions... */
  34. extern struct Library *SysBase;
  35.  
  36. /* IO file name buffer */
  37. char name[256];
  38.  
  39. /* File notification file name buffer */
  40. char notify[256];
  41.  
  42. /* Disable Lattice/SASC CTRL-C handling */
  43. int CXBRK (void)
  44. {
  45.     return (0);
  46. }
  47.  
  48. int chkabort (void)
  49. {
  50.     return (0);
  51. }
  52.  
  53. void main (int argc, char **argv)
  54. {
  55.     /* Make sure we were called from the Shell */
  56.     if (argc > 0)
  57.     {
  58.     LONG unit = PRIMARY_CLIP;
  59.     UBYTE idbuff[6] = {NULL};
  60.     int fh = -1;        /* File handle */
  61.     int mode = 0;        /* File access mode */
  62.     int prot = 0;        /* File protection mode */
  63.     int acs = 0;        /* Access mode */
  64.     int next = 1;        /* Option counter */
  65.     unsigned int count;    /* Bytes read/written */
  66.     unsigned int length;    /* Bytes to transfer */
  67.     char option;        /* Option pointer */
  68.     char *odata;        /* Option data pointer */
  69.     BOOL cook = TRUE;    /* Do we process the buffer? */
  70.     struct MsgPort *mp;    /* Notification message port */
  71.     char opts[] = "urwn";    /* Options that require data */
  72.  
  73.     for (next = 1; (odata = argopt (argc, argv, opts, &next, &option)) != NULL;)
  74.     {
  75.         switch (toupper(option))
  76.         {
  77.         case '?':
  78.         case 'H':
  79.             help ();
  80.             break;
  81.  
  82.         case 'F':
  83.             cook = FALSE;
  84.             break;
  85.  
  86.         case 'Q':
  87.             cook = FALSE;
  88.             acs = CF_QUERY;
  89.             break;
  90.  
  91.         case 'C':
  92.             cook = FALSE;
  93.             acs = CF_CLEAR;
  94.             break;
  95.  
  96.         case 'N':
  97.             if (SysBase->lib_Version < 36)
  98.             fprintf (stderr, "-n option requires AmigaOS 2.0\n");
  99.             else
  100.             {
  101.             if (*odata)
  102.             {
  103.                 /* Remember the notification name */
  104.                 strcpy (notify, odata);
  105.  
  106.                 /* Set the access mode */
  107.                 acs = CF_NOTIFY;
  108.             }
  109.             else
  110.             {
  111.                 fprintf (stderr, "-n option requires a file name\n");
  112.                 exit (5);
  113.             }
  114.             }
  115.             break;
  116.  
  117.         case 'U':
  118.             if (*odata)
  119.             {
  120.             unit = (LONG) atoi (odata);
  121.  
  122.             if (unit < 0L || unit > 255L)
  123.             {
  124.                 fprintf (stderr, "Clipboard unit must range from 0 to 255\n");
  125.                 exit (5);
  126.             }
  127.             }
  128.             else
  129.             {
  130.             fprintf (stderr, "-u option requires a number from 0 to 255\n");
  131.             exit (5);
  132.             }
  133.             break;
  134.  
  135.         case 'R':
  136.             if (*odata)
  137.             {
  138.             strcpy (name, odata);
  139.  
  140.             if (access (name, 4) == -1)
  141.             {
  142.                 fprintf (stderr, "Can't read file %s\n", name);
  143.                 exit (5);
  144.             }
  145.  
  146.             /* Set the access mode */
  147.             mode = O_RDONLY;
  148.             acs = CF_READ;
  149.             }
  150.             else
  151.             {
  152.             fprintf (stderr, "-r option requires a name\n");
  153.             exit (5);
  154.             }
  155.             break;
  156.  
  157.         case 'W':
  158.             if (*odata)
  159.             {
  160.             strcpy (name, odata);
  161.  
  162.             if ((access (name, 0) == 0) &&
  163.                 (access (name, 2) == -1))
  164.             {
  165.                 fprintf (stderr, "Can't write to file %s\n", name);
  166.                 exit (5);
  167.             }
  168.  
  169.             /* Set the access mode */
  170.             mode = O_WRONLY | O_CREAT | O_TRUNC;
  171.             acs = CF_WRITE;
  172.             }
  173.             else
  174.             {
  175.             fprintf (stderr, "-r option requires a name\n");
  176.             exit (5);
  177.             }
  178.             break;
  179.  
  180.         default:
  181.             fprintf (stderr, "%c is not a supported option\n", option);
  182.             exit (5);
  183.             break;
  184.         }
  185.     }
  186.  
  187.     /* See if help is needed */
  188.     if ((argc == 2 && (strcmp (argv[1], "?") == 0)) || next < argc)
  189.         help ();
  190.  
  191.     /* Do we need to open/create a file? */
  192.     if (acs == CF_READ || acs == CF_WRITE)
  193.     {
  194.         /* Open/create the file */
  195.         if ((fh = open (name, mode, prot)) == -1)
  196.         {
  197.         /* Display why we failed */
  198.         perror ("CF; open");
  199.  
  200.         /* Clear the access flag */
  201.         acs = 0;
  202.         }
  203.     }
  204.  
  205.     /* Attempt to open the designated clipboard unit */
  206.     if (CBOpen (unit) == 0L)
  207.     {
  208.         struct Buffer *buff = NULL;
  209.  
  210.         switch (acs)
  211.         {
  212.         case 0:    /* Just browsing, thanks */
  213.             if (buff = CBRead (cook))
  214.             {
  215.             if (cook && (buff->b_Type == 0))
  216.                 printf ("%s\n", (STRPTR) buff->b_Buff);
  217.             else
  218.                 printf ("Contents are %s\n",
  219.                     PrintID (buff->b_Type, idbuff));
  220.             }
  221.             else
  222.             printf ("clipboard is empty\n");
  223.             break;
  224.  
  225.         case CF_QUERY:
  226.             if (buff = CBRead (cook))
  227.             printf ("%s, %ld\n",
  228.                     PrintID (buff->b_Type, idbuff), buff->b_ClipID);
  229.             else
  230.             printf ("empty\n");
  231.             break;
  232.  
  233.         case CF_READ:
  234.             if (buff = fillbuffer (fh))
  235.             CBWrite (buff);
  236.             break;
  237.  
  238.         case CF_WRITE:
  239.             if (buff = CBRead (cook))
  240.             {
  241.             /* Compute number of bytes to write */
  242.             length = buff->b_Size - sizeof (struct Buffer);
  243.  
  244.             /* Write the buffer */
  245.             count = write (fh, (char *) buff->b_Buff, length);
  246.             }
  247.             break;
  248.  
  249.         case CF_NOTIFY:
  250.             /* Create a message port */
  251.             if (mp = CreatePort (NULL, NULL))
  252.             {
  253.             struct NotifyRequest *nr;
  254.             LONG msize;
  255.  
  256.             /* Calculate size of allocation */
  257.             msize = sizeof (struct NotifyRequest);
  258.  
  259.             /* Allocate the notification request record */
  260.             if (nr = (struct NotifyRequest *) AllocMem (msize, MEMF_CLEAR))
  261.             {
  262.                 /* Fill in the notification request */
  263.                 nr->nr_Name = notify;
  264.                 nr->nr_stuff.nr_Msg.nr_Port = mp;
  265.                 nr->nr_Flags = NRF_SEND_MESSAGE | NRF_WAIT_REPLY;
  266.  
  267.                 /* Start the notification */
  268.                 StartNotify (nr);
  269.  
  270.                 /* Handle notification messages */
  271.                 HandleNotify (mp);
  272.  
  273.                 /* Say that we're not interested any longer */
  274.                 EndNotify (nr);
  275.  
  276.                 /* Free the notification request */
  277.                 FreeMem ((APTR) nr, msize);
  278.             }
  279.             else
  280.                 fprintf (stderr, "Couldn't allocate notify request\n");
  281.  
  282.             /* Delete our message port */
  283.             DeletePort (mp);
  284.             }
  285.             else
  286.             fprintf (stderr, "Couldn't create message port\n");
  287.  
  288.             break;
  289.  
  290.         case CF_CLEAR:
  291.             CBClear();
  292.             break;
  293.         }
  294.  
  295.         /* Free the temporary buffer */
  296.         freebuffer (buff);
  297.  
  298.         /* Close the clipboard */
  299.         CBClose ();
  300.     }
  301.  
  302.     /* See if we opened a file */
  303.     if (fh != -1)
  304.     {
  305.         /* Close the file, and change the file mode if we created the file */
  306.         if ((close (fh) == 0) && (mode == O_WRONLY))
  307.         {
  308.         if (chmod (name, S_IWRITE | S_IREAD))
  309.             perror ("PF; chmod");
  310.         }
  311.     }
  312.     }
  313. }
  314.  
  315. VOID HandleNotify (struct MsgPort * mp)
  316. {
  317.     LONG sigbits;
  318.     BOOL going = TRUE;
  319.  
  320.     /* Build the signal bits that we're going to wait on */
  321.     sigbits = (1L << mp->mp_SigBit) | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F;
  322.  
  323.     /* Loop until we get a signal or error */
  324.     while (going)
  325.     {
  326.     struct NotifyMessage *nmsg;
  327.     LONG sigsr;
  328.  
  329.     /* Wait for a message to come in */
  330.     sigsr = Wait (sigbits);
  331.  
  332.     /* See if we got a ^C signal */
  333.     if (sigsr & SIGBREAKF_CTRL_C)
  334.     {
  335.         printf ("process watching %s aborted\n", notify);
  336.  
  337.         /* Signal the end... */
  338.         going = FALSE;
  339.     }
  340.  
  341.     /* See if we got a ^F signal */
  342.     if (sigsr & SIGBREAKF_CTRL_F)
  343.         printf ("watching %s\n", notify);
  344.  
  345.     /* See if we have a file notification message */
  346.     if (sigsr & (1L << mp->mp_SigBit))
  347.     {
  348.         int fh, i, error;
  349.  
  350.         /* Get each notification message and reply to it */
  351.         while (nmsg = (struct NotifyMessage *) GetMsg (mp))
  352.         ReplyMsg ((struct Message *) nmsg);
  353.  
  354.         /* For some reason, DPaint does something with the file twice,
  355.          * if it already exists, so wait around until we have read
  356.          * access to the file.  So, when getting notification on a
  357.          * DPaint brush, we'll actually get two messages. */
  358.         for (i = 0, error = (-1); (error == (-1) && i < 100); i++)
  359.         if ((error = access (notify, 4)) == (-1))
  360.             Delay (10);
  361.  
  362.         /* Open the file */
  363.         if ((fh = open (notify, O_RDONLY, 0)) == -1)
  364.         {
  365.         /* Build the error string */
  366.         sprintf (name, "CF;  %s", notify);
  367.  
  368.         /* Display why we failed */
  369.         perror (name);
  370.  
  371.         /* Don't continue */
  372.         going = FALSE;
  373.         }
  374.         else
  375.         {
  376.         struct Buffer *buff;
  377.  
  378.         /* Get contents of the file */
  379.         if (buff = fillbuffer (fh))
  380.         {
  381.             /* Write the buffer to the clipboard */
  382.             CBWrite (buff);
  383.  
  384.             /* Free the temporary buffer */
  385.             freebuffer (buff);
  386.         }
  387.  
  388.         /* Close the file */
  389.         close (fh);
  390.         }
  391.     }
  392.     }
  393. }
  394.  
  395. void help (void)
  396. {
  397.  
  398.     printf ("CF (ClipFile) version 1.0\n");
  399.     printf ("Written by David N. Junod\n");
  400.     printf ("\n");
  401.     printf ("-h        Display this message\n");
  402.     printf ("-u <unit>    Clipboard unit, ranging from 0 to 255.\n");
  403.     printf ("-r <file>    Place the contents of <file> into the clipboard.\n");
  404.     printf ("-w <file>    Place the contents of the clipboard into <file>.\n");
  405.     printf ("-f        Don't convert FTXT form to ASCII\n");
  406.     printf ("-q        Query clipboard unit contents type\n");
  407.     printf ("-c        Clear the clipboard unit\n");
  408.     printf ("-n <file>    Watch the named file and place it into the clipboard\n");
  409.     printf ("        whenever it changes.  Must send a break signal to shutdown\n");
  410.     printf ("        the process\n");
  411.  
  412.     exit (0);
  413. }
  414.  
  415. struct Buffer *fillbuffer (int fh)
  416. {
  417.     struct Buffer *buff = NULL;
  418.     long msize = NULL;
  419.     long count, length;
  420.  
  421.     /* Make sure we have a file handle */
  422.     if (fh >= 0)
  423.     {
  424.     /* Find out how big the file is */
  425.     if ((length = lseek (fh, 0L, 2)) >= 0L)
  426.     {
  427.         /* Seek back to the beginning */
  428.         lseek (fh, 0L, 0);
  429.  
  430.         /* Calculate the size of the buffer */
  431.         msize = sizeof (struct Buffer) + length;
  432.  
  433.         /* Allocate the buffer */
  434.         if (buff = (struct Buffer *) AllocMem (msize, MEMF_CLEAR))
  435.         {
  436.         buff->b_Size = msize;
  437.         buff->b_Type = 0;
  438.  
  439.         /* Point the buffer at the right place */
  440.         buff->b_Buff = (VOID *) ((buff) + 1);
  441.  
  442.         /* Fill in the buffer */
  443.         if ((count = read (fh, (char *) buff->b_Buff, length)) == -1)
  444.         {
  445.             /* Display error message */
  446.             perror ("CF; read");
  447.  
  448.             /* Discard buffer */
  449.             FreeMem ((APTR) buff, msize);
  450.             buff = NULL;
  451.         }
  452.         else
  453.         {
  454.             LONG *buffer;
  455.  
  456.             buffer = (LONG *) buff->b_Buff;
  457.             if (buffer[0] == ID_FORM)
  458.             buff->b_Type = buffer[2];
  459.             else if (count == 0L)
  460.             buff->b_Type = ID_FTXT;
  461.         }
  462.         }
  463.     }
  464.     }
  465.  
  466.     return (buff);
  467. }
  468.