home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term33so.lha / termClip.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  11KB  |  638 lines

  1. /*
  2. **    termClip.c
  3. **
  4. **    Clipboard support routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12. STATIC struct IFFHandle    *ClipHandle;
  13. STATIC STRPTR         ClipBuffer,
  14.              ClipIndex;
  15. STATIC LONG         ClipSize,
  16.              ClipLength;
  17.  
  18.     /* ClipServer():
  19.      *
  20.      *    Quiet background process which saves data to the clipboard
  21.      *    or fills a buffer with fresh clipboard data.
  22.      */
  23.  
  24. VOID __saveds
  25. ClipServer()
  26. {
  27.     struct IOClipReq __aligned ClipRequest;
  28.  
  29.         /* Clear the request. */
  30.  
  31.     memset(&ClipRequest,0,sizeof(struct IOClipReq));
  32.  
  33.         /* Open the clipboard.device, we will not use the
  34.          * IORequest to do any IO operations on it, but
  35.          * rather to keep clipboard.device available
  36.          * when needed.
  37.          */
  38.  
  39.     if(!OpenDevice("clipboard.device",PRIMARY_CLIP,(struct IORequest *)&ClipRequest,NULL))
  40.     {
  41.         if(ClipPort = CreateMsgPort())
  42.         {
  43.             ULONG         Mask;
  44.             struct Message    *ClipMsg;
  45.             UBYTE        *Buffer;
  46.             BYTE         Terminated = FALSE;
  47.  
  48.             Signal(ThisProcess,SIG_HANDSHAKE);
  49.  
  50.             while(!Terminated)
  51.             {
  52.                 Mask = Wait(SIG_KILL | PORTMASK(ClipPort));
  53.  
  54.                 if(Mask & SIG_KILL)
  55.                     Terminated = TRUE;
  56.  
  57.                 if(Mask & PORTMASK(ClipPort))
  58.                 {
  59.                     while(ClipMsg = GetMsg(ClipPort))
  60.                     {
  61.                         Buffer = ClipMsg -> mn_Node . ln_Name;
  62.  
  63.                         if(Buffer[0])
  64.                             SaveClip(Buffer,strlen(Buffer));
  65.                         else
  66.                         {
  67.                             WORD Len = LoadClip(Buffer,256);
  68.  
  69.                             Buffer[Len] = 0;
  70.                         }
  71.  
  72.                         ReplyMsg(ClipMsg);
  73.                     }
  74.                 }
  75.             }
  76.  
  77.             DeleteMsgPort(ClipPort);
  78.         }
  79.  
  80.         CloseDevice((struct IORequest *)&ClipRequest);
  81.     }
  82.  
  83.     Forbid();
  84.  
  85.     ClipProcess = NULL;
  86.  
  87.     Signal(ThisProcess,SIG_HANDSHAKE);
  88. }
  89.  
  90.     /* CloseClip():
  91.      *
  92.      *    Close clipboard handle, stop reading.
  93.      */
  94.  
  95. VOID
  96. CloseClip()
  97. {
  98.     if(ClipHandle)
  99.     {
  100.         CloseIFF(ClipHandle);
  101.  
  102.         if(ClipHandle -> iff_Stream)
  103.             CloseClipboard((struct ClipboardHandle *)ClipHandle -> iff_Stream);
  104.  
  105.         FreeIFF(ClipHandle);
  106.  
  107.         ClipHandle = NULL;
  108.     }
  109.  
  110.     if(ClipBuffer)
  111.     {
  112.         FreeVec(ClipBuffer);
  113.  
  114.         ClipBuffer = NULL;
  115.     }
  116. }
  117.  
  118.     /* GetClip(STRPTR Buffer,WORD Len,BYTE Filter):
  119.      *
  120.      *    Read text data from clipboard and put it into the supplied buffer.
  121.      */
  122.  
  123. WORD
  124. GetClip(STRPTR Buffer,WORD Len,BYTE Filter)
  125. {
  126.     WORD BytesPut = 0;
  127.  
  128.         /* Is the read buffer already exhausted? */
  129.  
  130.     if(!ClipLength)
  131.     {
  132.             /* Is there still any data to read? */
  133.  
  134.         if(ClipSize)
  135.         {
  136.             WORD Size = MIN(ClipSize,1024);
  137.  
  138.                 /* Try to read the data and return failure if necessary. */
  139.  
  140.             if(ReadChunkBytes(ClipHandle,ClipBuffer,Size) != Size)
  141.                 return(-1);
  142.             else
  143.             {
  144.                 ClipSize    -= Size;
  145.                 ClipLength     = Size;
  146.                 ClipIndex     = ClipBuffer;
  147.             }
  148.         }
  149.         else
  150.         {
  151.                 /* We just parsed a single chunk, now go on and
  152.                  * look for another one.
  153.                  */
  154.  
  155.             if(!ParseIFF(ClipHandle,IFFPARSE_SCAN))
  156.             {
  157.                 struct ContextNode *ContextNode = CurrentChunk(ClipHandle);
  158.  
  159.                 if(ContextNode -> cn_Type == ID_FTXT)
  160.                 {
  161.                     WORD Size;
  162.  
  163.                     ClipSize    = ContextNode -> cn_Size;
  164.                     Size        = MIN(ClipSize,1024);
  165.  
  166.                     if(ReadChunkBytes(ClipHandle,ClipBuffer,Size) != Size)
  167.                         return(-1);
  168.                     else
  169.                     {
  170.                         ClipSize    -= Size;
  171.                         ClipLength     = Size;
  172.                         ClipIndex     = ClipBuffer;
  173.                     }
  174.                 }
  175.                 else
  176.                     return(-1);
  177.             }
  178.             else
  179.                 return(-1);
  180.         }
  181.     }
  182.  
  183.         /* The following loop processes the contents of
  184.          * the clipboard buffer read. Special characters
  185.          * such as LF and CR will be converted according
  186.          * to the current settings if enabled. No bytes
  187.          * will be lost, though.
  188.          */
  189.  
  190.     while(ClipLength && BytesPut < Len)
  191.     {
  192.         if(*ClipIndex == '\n')
  193.         {
  194.             if(Filter)
  195.             {
  196.                 *Buffer++ = *ClipIndex++;
  197.  
  198.                 BytesPut++;
  199.  
  200.                 ClipLength--;
  201.             }
  202.             else
  203.             {
  204.                 switch(Config -> TerminalConfig -> SendLF)
  205.                 {
  206.                     case LF_IGNORE:
  207.  
  208.                         ClipIndex++;
  209.                         ClipLength--;
  210.  
  211.                         break;
  212.  
  213.                     case LF_ASLFCR:
  214.  
  215.                         if(BytesPut + 2 <= Len)
  216.                         {
  217.                             *Buffer++ = '\n';
  218.                             *Buffer++ = '\r';
  219.  
  220.                             BytesPut += 2;
  221.  
  222.                             ClipLength--;
  223.                             ClipIndex++;
  224.                         }
  225.                         else
  226.                             return(BytesPut);
  227.  
  228.                         break;
  229.  
  230.                     case LF_ASLF:
  231.  
  232.                         *Buffer++ = *ClipIndex++;
  233.  
  234.                         BytesPut++;
  235.  
  236.                         ClipLength--;
  237.  
  238.                         break;
  239.                 }
  240.             }
  241.         }
  242.         else
  243.         {
  244.             if(*ClipIndex == '\r')
  245.             {
  246.                 if(Filter)
  247.                 {
  248.                     ClipIndex++;
  249.                     ClipLength--;
  250.                 }
  251.                 else
  252.                 {
  253.                     switch(Config -> TerminalConfig -> SendCR)
  254.                     {
  255.                         case CR_IGNORE:
  256.  
  257.                             ClipIndex++;
  258.                             ClipLength--;
  259.  
  260.                             break;
  261.  
  262.                         case CR_ASCRLF:
  263.  
  264.                             if(BytesPut + 2 <= Len)
  265.                             {
  266.                                 *Buffer++ = '\r';
  267.                                 *Buffer++ = '\n';
  268.  
  269.                                 BytesPut += 2;
  270.  
  271.                                 ClipLength--;
  272.                                 ClipIndex++;
  273.                             }
  274.                             else
  275.                                 return(BytesPut);
  276.  
  277.                             break;
  278.  
  279.                         case CR_ASCR:
  280.  
  281.                             *Buffer++ = *ClipIndex++;
  282.  
  283.                             BytesPut++;
  284.  
  285.                             ClipLength--;
  286.  
  287.                             break;
  288.                     }
  289.                 }
  290.             }
  291.             else
  292.             {
  293.                 register UBYTE c = *ClipIndex++;
  294.  
  295.                 ClipLength--;
  296.  
  297.                 if(!Filter || IsPrintable[c])
  298.                 {
  299.                     *Buffer++ = c;
  300.  
  301.                     BytesPut++;
  302.                 }
  303.             }
  304.         }
  305.     }
  306.  
  307.     return(BytesPut);
  308. }
  309.  
  310.     /* OpenClip():
  311.      *
  312.      *    Open the clipboard for sequential reading.
  313.      */
  314.  
  315. BYTE
  316. OpenClip(LONG Unit)
  317. {
  318.     BYTE Error;
  319.  
  320.     CloseClip();
  321.  
  322.     if(ClipBuffer = (STRPTR)AllocVec(1024,MEMF_ANY))
  323.     {
  324.         if(ClipHandle = AllocIFF())
  325.         {
  326.             if(ClipHandle -> iff_Stream = (ULONG)OpenClipboard(Unit))
  327.             {
  328.                 InitIFFasClip(ClipHandle);
  329.  
  330.                 if(!OpenIFF(ClipHandle,IFFF_READ))
  331.                 {
  332.                     if(!StopChunk(ClipHandle,ID_FTXT,ID_CHRS))
  333.                     {
  334.                         if(!ParseIFF(ClipHandle,IFFPARSE_SCAN))
  335.                         {
  336.                             struct ContextNode *ContextNode = CurrentChunk(ClipHandle);
  337.  
  338.                             if(ContextNode -> cn_Type == ID_FTXT)
  339.                             {
  340.                                 ClipSize    = ContextNode -> cn_Size;
  341.                                 ClipLength    = 0;
  342.  
  343.                                 return(CLIPERR_NONE);
  344.                             }
  345.                             else
  346.                                 Error = CLIPERR_NOTEXT;
  347.                         }
  348.                         else
  349.                             Error = CLIPERR_NOTEXT;
  350.                     }
  351.                     else
  352.                         Error = CLIPERR_IFF;
  353.                 }
  354.                 else
  355.                     Error = CLIPERR_OPEN;
  356.             }
  357.             else
  358.                 Error = CLIPERR_OPEN;
  359.         }
  360.         else
  361.             Error = CLIPERR_MEM;
  362.     }
  363.     else
  364.         Error = CLIPERR_MEM;
  365.  
  366.     CloseClip();
  367.  
  368.     return(Error);
  369. }
  370.  
  371.     /* GetClipContents(LONG Unit,APTR *Buffer,LONG *Size):
  372.      *
  373.      *    Merge text contents of the clipboard into a single string.
  374.      */
  375.  
  376. BYTE
  377. GetClipContents(LONG Unit,APTR *Buffer,LONG *Size)
  378. {
  379.     struct IFFHandle    *Handle;
  380.     LONG             Bytes = 0;
  381.     APTR             Store = NULL;
  382.  
  383.     if(Handle = AllocIFF())
  384.     {
  385.         if(Handle -> iff_Stream = (ULONG)OpenClipboard(Unit))
  386.         {
  387.             InitIFFasClip(Handle);
  388.  
  389.             if(!OpenIFF(Handle,IFFF_READ))
  390.             {
  391.                 if(!StopChunk(Handle,ID_FTXT,ID_CHRS))
  392.                 {
  393.                     struct ContextNode *Node;
  394.  
  395.                     while(!ParseIFF(Handle,IFFPARSE_SCAN))
  396.                     {
  397.                         Node = CurrentChunk(Handle);
  398.  
  399.                         if(Node -> cn_Type == ID_FTXT)
  400.                             Bytes += Node -> cn_Size;
  401.                     }
  402.                 }
  403.  
  404.                 CloseIFF(Handle);
  405.             }
  406.  
  407.             if(Bytes)
  408.             {
  409.                 if(!OpenIFF(Handle,IFFF_READ))
  410.                 {
  411.                     if(!StopChunk(Handle,ID_FTXT,ID_CHRS))
  412.                     {
  413.                         if(Store = AllocVec(Bytes,MEMF_ANY))
  414.                         {
  415.                             STRPTR             Index        = Store;
  416.                             LONG             BytesRead    = 0;
  417.                             struct ContextNode    *Node;
  418.  
  419.                             while(!ParseIFF(Handle,IFFPARSE_SCAN) && BytesRead < Bytes)
  420.                             {
  421.                                 Node = CurrentChunk(Handle);
  422.  
  423.                                 if(Node -> cn_Type == ID_FTXT)
  424.                                 {
  425.                                     LONG Count = Node -> cn_Size;
  426.  
  427.                                     if(BytesRead + Count > Bytes)
  428.                                         Count = Bytes - BytesRead;
  429.  
  430.                                     if(Count > 0)
  431.                                     {
  432.                                         if((Count = ReadChunkBytes(Handle,Index,Count)) > 0)
  433.                                         {
  434.                                             Index        += Count;
  435.                                             BytesRead    += Count;
  436.                                         }
  437.                                     }
  438.                                 }
  439.                             }
  440.  
  441.                             Bytes = BytesRead;
  442.                         }
  443.                     }
  444.  
  445.                     CloseIFF(Handle);
  446.                 }
  447.             }
  448.  
  449.             CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
  450.         }
  451.  
  452.         FreeIFF(Handle);
  453.     }
  454.  
  455.     if(Store && !Bytes)
  456.     {
  457.         FreeVec(Store);
  458.  
  459.         Store = NULL;
  460.     }
  461.  
  462.     *Buffer    = Store;
  463.     *Size    = Bytes;
  464.  
  465.     return((BYTE)(Store != NULL));
  466. }
  467.  
  468.     /* AddClip(STRPTR Buffer,LONG Size):
  469.      *
  470.      *    Merge previous clipboard contents with new text,
  471.      *    then store the new string in the clipboard.
  472.      */
  473.  
  474. BYTE
  475. AddClip(STRPTR Buffer,LONG Size)
  476. {
  477.     LONG    Bytes;
  478.     APTR    Store;
  479.  
  480.     if(GetClipContents(Config -> ClipConfig -> ClipboardUnit,&Store,&Bytes))
  481.     {
  482.         struct IFFHandle    *Handle;
  483.         BYTE             Success = FALSE;
  484.  
  485.         if(Handle = AllocIFF())
  486.         {
  487.             if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config -> ClipConfig -> ClipboardUnit))
  488.             {
  489.                 InitIFFasClip(Handle);
  490.  
  491.                 if(!OpenIFF(Handle,IFFF_WRITE))
  492.                 {
  493.                     if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
  494.                     {
  495.                         if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
  496.                         {
  497.                             if(WriteChunkBytes(Handle,Store,Bytes) == Bytes)
  498.                             {
  499.                                 if(WriteChunkBytes(Handle,Buffer,Size) == Size)
  500.                                 {
  501.                                     if(!PopChunk(Handle))
  502.                                         Success = TRUE;
  503.                                 }
  504.                             }
  505.                         }
  506.                     }
  507.  
  508.                     if(Success)
  509.                     {
  510.                         if(PopChunk(Handle))
  511.                             Success = FALSE;
  512.                     }
  513.  
  514.                     CloseIFF(Handle);
  515.                 }
  516.  
  517.                 CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
  518.             }
  519.  
  520.             FreeIFF(Handle);
  521.         }
  522.  
  523.         FreeVec(Store);
  524.  
  525.         return(Success);
  526.     }
  527.     else
  528.         return(SaveClip(Buffer,Size));
  529. }
  530.  
  531.     /* SaveClip(STRPTR Buffer,LONG Size):
  532.      *
  533.      *    Send a given text buffer to the clipboard.
  534.      */
  535.  
  536. BYTE
  537. SaveClip(STRPTR Buffer,LONG Size)
  538. {
  539.     BYTE Success = FALSE;
  540.  
  541.     if(Size > 0)
  542.     {
  543.         struct IFFHandle *Handle;
  544.  
  545.         if(Handle = AllocIFF())
  546.         {
  547.             if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config -> ClipConfig -> ClipboardUnit))
  548.             {
  549.                 InitIFFasClip(Handle);
  550.  
  551.                 if(!OpenIFF(Handle,IFFF_WRITE))
  552.                 {
  553.                     if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
  554.                     {
  555.                         if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
  556.                         {
  557.                             if(WriteChunkBytes(Handle,Buffer,Size) == Size)
  558.                             {
  559.                                 if(!PopChunk(Handle))
  560.                                     Success = TRUE;
  561.                             }
  562.                         }
  563.                     }
  564.  
  565.                     if(Success)
  566.                     {
  567.                         if(PopChunk(Handle))
  568.                             Success = FALSE;
  569.                     }
  570.  
  571.                     CloseIFF(Handle);
  572.                 }
  573.  
  574.                 CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
  575.             }
  576.  
  577.             FreeIFF(Handle);
  578.         }
  579.     }
  580.  
  581.     return(Success);
  582. }
  583.  
  584.     /* LoadClip(STRPTR Buffer,LONG Size):
  585.      *
  586.      *    Put the contents of the clipboard into a given
  587.      *    buffer. Note that only the first FTXT chunk will
  588.      *    be read. Since this code will only be called by
  589.      *    the clipboard server process which serves the
  590.      *    string gadget editing hook, this will hopefully
  591.      *    not be fatal. If you want more data to be read,
  592.      *    including multiple FTXT chunks, use the OpenClip(),
  593.      *    GetClip(), CloseClip() combo above.
  594.      */
  595.  
  596. LONG
  597. LoadClip(STRPTR Buffer,LONG Size)
  598. {
  599.     struct IFFHandle    *Handle;
  600.     LONG             Bytes = 0;
  601.  
  602.     if(Handle = AllocIFF())
  603.     {
  604.         if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config -> ClipConfig -> ClipboardUnit))
  605.         {
  606.             InitIFFasClip(Handle);
  607.  
  608.             if(!OpenIFF(Handle,IFFF_READ))
  609.             {
  610.                 if(!StopChunk(Handle,ID_FTXT,ID_CHRS))
  611.                 {
  612.                     if(!ParseIFF(Handle,IFFPARSE_SCAN))
  613.                     {
  614.                         struct ContextNode *ContextNode = CurrentChunk(Handle);
  615.  
  616.                         if(ContextNode -> cn_Type == ID_FTXT)
  617.                         {
  618.                             if(Size > ContextNode -> cn_Size)
  619.                                 Size = ContextNode -> cn_Size;
  620.  
  621.                             if(ReadChunkRecords(Handle,Buffer,Size,1))
  622.                                 Bytes = Size;
  623.                         }
  624.                     }
  625.                 }
  626.  
  627.                 CloseIFF(Handle);
  628.             }
  629.  
  630.             CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
  631.         }
  632.  
  633.         FreeIFF(Handle);
  634.     }
  635.  
  636.     return(Bytes);
  637. }
  638.