home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 365.lha / VSnap / iffpic.c < prev    next >
C/C++ Source or Header  |  1990-04-10  |  9KB  |  403 lines

  1. /** routine for saveing an IFF picture to the clipboard...
  2.     By Stephen Vermeulen 1989.
  3.  **/
  4.  
  5. struct IOClipReq clipboardIO = 0;
  6. struct MsgPort clipboardMsgPort = 0;
  7. struct MsgPort satisfyMsgPort = 0;
  8.  
  9. #ifndef MakeID
  10. #define MakeID(a, b, c, d)\
  11.   ( ((long) (a)<<24) + ((long) (b)<<16) + ((long)(c)<<8) + (long)(d) )
  12. #endif
  13.  
  14. short CBisOpen;      /** this will be set to 1 when the clipboard has
  15.                          been successfully opened.
  16.                       **/
  17.  
  18. /** the following two routines are from a CBM example somewhere on the
  19.     Fish Disks...
  20.  **/
  21.  
  22. int CBOpen(unit)
  23. int unit;
  24. {
  25.     int error;
  26.  
  27.     /* open the clipboard device */
  28.     if ((error = OpenDevice("clipboard.device", (long) unit, &clipboardIO, 0L)) != 0)
  29.         CBisOpen = 0;
  30.  
  31.     /* Set up the message port in the I/O request */
  32.     clipboardMsgPort.mp_Node.ln_Type = NT_MSGPORT;
  33.     clipboardMsgPort.mp_Flags = 0;
  34.     clipboardMsgPort.mp_SigBit = AllocSignal(-1L);
  35.     clipboardMsgPort.mp_SigTask = (struct Task *) FindTask((char *) NULL);
  36.     AddPort(&clipboardMsgPort);
  37.     clipboardIO.io_Message.mn_ReplyPort = &clipboardMsgPort;
  38.  
  39.     satisfyMsgPort.mp_Node.ln_Type = NT_MSGPORT;
  40.     satisfyMsgPort.mp_Flags = 0;
  41.     satisfyMsgPort.mp_SigBit = AllocSignal(-1L);
  42.     satisfyMsgPort.mp_SigTask = (struct Task *) FindTask((char *) NULL);
  43.     AddPort(&satisfyMsgPort);
  44.     CBisOpen = 1;
  45. }
  46.  
  47. CBClose()
  48. {
  49.     if (CBisOpen)
  50.     {
  51.       if (clipboardMsgPort.mp_SigBit > 0)
  52.          FreeSignal(clipboardMsgPort.mp_SigBit);
  53.       if (satisfyMsgPort.mp_SigBit > 0)
  54.          FreeSignal(satisfyMsgPort.mp_SigBit);
  55.  
  56.       RemPort(&satisfyMsgPort);
  57.       RemPort(&clipboardMsgPort);
  58.       CloseDevice(&clipboardIO);
  59.       CBisOpen = 0;
  60.     }
  61. }
  62.  
  63. /** the rest of the clipboard routines are my own work **/
  64.  
  65. /** this is used to set the mode of the clipboard, to either read
  66.     or write (0 or 1)
  67.  **/
  68.  
  69. CBSetMode(mode)
  70. int mode;
  71. {
  72.   if (mode) /** write **/
  73.   {
  74.     clipboardIO.io_Command = CMD_WRITE;
  75.     clipboardIO.io_Offset = 0;
  76.     clipboardIO.io_ClipID = 0;
  77.   }
  78.   else
  79.   {
  80.     clipboardIO.io_Command = CMD_READ;
  81.     clipboardIO.io_Offset = 0;
  82.     clipboardIO.io_ClipID = 0;
  83.   }
  84. }
  85.  
  86. /** the following is the function that replaces fread(), calling
  87.     the clipboard instead.
  88.  **/
  89.  
  90. gfread(data, length, n)
  91. UBYTE *data;
  92. int length, n;
  93. {
  94.     if (CBisOpen)
  95.     {
  96.       while (n)
  97.       {
  98.         clipboardIO.io_Command = CMD_READ;
  99.         clipboardIO.io_Data = (STRPTR) data;
  100.         clipboardIO.io_Length = length;
  101.         DoIO(&clipboardIO);
  102.         data += length;
  103.         --n;
  104.       }
  105.     }
  106. }
  107.  
  108. gputc(c)
  109. char c;
  110. {
  111.     if (CBisOpen)
  112.     {
  113.       clipboardIO.io_Command = CMD_WRITE;
  114.       clipboardIO.io_Data = (STRPTR) &c;
  115.       clipboardIO.io_Length = 1;
  116.       DoIO(&clipboardIO);
  117.     }
  118. }
  119.  
  120. gfwrite(data, length, n)
  121. UBYTE *data;
  122. int length, n;
  123. {
  124.     if (CBisOpen)
  125.     {
  126.       while (n)
  127.       {
  128.         clipboardIO.io_Command = CMD_WRITE;
  129.         clipboardIO.io_Data = (STRPTR) data;
  130.         clipboardIO.io_Length = length;
  131.         DoIO(&clipboardIO);
  132.         data += length;
  133.         --n;
  134.       }
  135.     }
  136. }
  137.  
  138. CBEndSession(mode)
  139. int mode;
  140. {
  141.   if (!CBisOpen) return;
  142.   if (mode)  /** end of writing **/
  143.   {
  144.     clipboardIO.io_Command = CMD_UPDATE;
  145.     DoIO(&clipboardIO);
  146.   }
  147.   else   /** end of reading **/
  148.   {
  149.     clipboardIO.io_Command = CMD_READ;
  150.     clipboardIO.io_Offset = 2000000000; /** don't use -1L here!
  151.                                             the clipboard treats this
  152.                                             as a SIGNED quantity! **/
  153.     clipboardIO.io_Length = 1;
  154.     clipboardIO.io_Data = (STRPTR) 0;
  155.     DoIO(&clipboardIO);
  156.   }
  157. }
  158.  
  159. /** note the following does not support seeking relative to the end
  160.     of the clip...
  161.  **/
  162.  
  163. gfseek(offset, origin)
  164. long offset;
  165. int origin;
  166. {
  167.     if (CBisOpen)
  168.     {
  169.       switch (origin)
  170.       {
  171.         case 0: /** rel to begining **/
  172.           clipboardIO.io_Offset = offset;
  173.           break;
  174.         case 1: /** rel to current pos **/
  175.           clipboardIO.io_Offset += offset;
  176.           break;
  177.       }
  178.     }
  179. }
  180.  
  181. long gftell()
  182. {
  183.     if (CBisOpen)
  184.     {
  185.       return(clipboardIO.io_Offset);
  186.     }
  187.     else
  188.       return(NULL);
  189. }
  190.  
  191. gfopen(mode)
  192. char *mode;
  193. {
  194.     if (mode[0] == 'r') CBSetMode(0);
  195.     else CBSetMode(1);
  196. }
  197.  
  198. gfclose(mode)
  199. char *mode;
  200. {
  201.     if (mode[0] == 'r')
  202.     {
  203.       /** we must force a read beyond the end of the file to tell
  204.           clipboard we are done with it!
  205.        **/
  206.       CBEndSession(0);
  207.     }
  208.     else CBEndSession(1);
  209. }
  210.  
  211. #define MaxPackedSize(rowSize) ( (rowSize) + ( ((rowSize) + 127) >> 7) )
  212. #define RowBytes(w)  ((((w) + 15) >> 4) << 1)
  213.  
  214. /************************************************************
  215.   The following are the IFF read and write routines
  216. ************************************************************/
  217.  
  218. #define FORM MakeID('F', 'O', 'R', 'M')
  219. #define ILBM MakeID('I', 'L', 'B', 'M')
  220. #define BMHD MakeID('B', 'M', 'H', 'D')
  221. #define BODY MakeID('B', 'O', 'D', 'Y')
  222. #define VDFL MakeID('V', 'D', 'F', 'L')
  223. #define CMAP MakeID('C', 'M', 'A', 'P')
  224. #define GRAB MakeID('G', 'R', 'A', 'B')
  225. #define CAMG MakeID('C', 'A', 'M', 'G')
  226. #define CRNG MakeID('C', 'R', 'N', 'G')
  227.  
  228. struct BMHdr
  229. {
  230.   USHORT w, h;
  231.   SHORT  x, y;
  232.   UBYTE  nPlanes, masking, compression, pad1;
  233.   USHORT transparentColor;
  234.   UBYTE  xAspect, yAspect;
  235.   SHORT  pageWidth, pageHeight;
  236. };
  237.  
  238. struct PictHdr
  239. {
  240.   LONG IFFid, filelen, ILBMid, BMHDid, BMHDsize;
  241.   struct BMHdr bmhdr;
  242. };
  243.  
  244. char comp_buf[1036];  /* buffer to hold the compressed input data */
  245. short comp_buf_len;   /* number of bytes in the compressed buffer */
  246.  
  247. /***************************************************************
  248.   Quicky little routine that just writes a long word to the file
  249. ****************************************************************/
  250.  
  251. void write_WORD(i)
  252. LONG i;
  253. {
  254.   (void) gfwrite( (char *) &i, 4, 1);
  255. }
  256.  
  257. void write_CMAP(s, d)
  258. struct Screen *s;
  259. short d;
  260. {
  261.   short i, colour;
  262.  
  263.   if (d == 6) d == 5; /* cause of ehb */
  264.   write_WORD(CMAP);
  265.   write_WORD(3L * (1L << d));
  266.   for (i = 0; i < (1 << d); ++i)
  267.   {
  268.     colour = GetRGB4(s->ViewPort.ColorMap, (long) i);
  269.     gputc((colour & 0x0f00) >> 4);  /****** red ******/
  270.     gputc((colour & 0x00f0));       /***** green *****/
  271.     gputc((colour & 0x000f) << 4);  /****** blue *****/
  272.   }
  273. }
  274.  
  275. /************************************************************
  276.   The following routine is used by the IFF saving routines
  277.   to write the body section of the image.
  278.   Returns true if sucessful, else it returns FALSE.
  279. ************************************************************/
  280.  
  281. int save_BODY(bm, comp)
  282. struct BitMap *bm;
  283. short comp;
  284. {
  285.   short y, nbytes, bwidth, depth;
  286.   short p;
  287.   struct BitMap mybm;
  288.   char *source, *dest, *bp;
  289.  
  290.   nbytes = bwidth = bm->BytesPerRow;
  291.   mybm = *bm;
  292.   depth = bm->Depth;
  293.  
  294.   /*******************
  295.     scan down the rows
  296.   ********************/
  297.  
  298.   for (y = 0; y < bm->Rows; ++y)
  299.   {
  300.     /**************************
  301.       Sweep down the bit planes
  302.     ***************************/
  303.  
  304.     for (p = 0; p < depth; ++p)
  305.     {
  306.       bp = (char *) mybm.Planes[p];
  307.       if (comp)
  308.       {
  309.         /****************
  310.           pack this row
  311.         *****************/
  312.  
  313.         source = bp;
  314.         dest = &comp_buf[0];
  315.         nbytes = PackRow(&source, &dest, bwidth);
  316.         bp = &comp_buf[0];
  317.       }
  318.  
  319.       /************************
  320.         Now write out the data
  321.       *************************/
  322.  
  323.       gfwrite((char *) bp, nbytes, 1);
  324.       mybm.Planes[p] += bwidth;
  325.     } /* end for bitplanes */
  326.   }  /*  end for rows */
  327.   return(1);
  328. }
  329.  
  330. /************************************************************
  331.   The routine to save designated area of a raster port in
  332.   IFF format.
  333. ************************************************************/
  334.  
  335. short save_bm(bm, s)
  336. struct BitMap *bm;
  337. struct Screen *s;
  338. {
  339.   LONG vmode, body_start, body_len, file_len;
  340.   struct PictHdr Pict;
  341.   short i;
  342.   FILE *out;
  343.   char *name;
  344.  
  345.   CBOpen(0);
  346.   if (!CBisOpen) return(0);
  347.   gfopen("w");
  348.   Pict.bmhdr.w = bm->BytesPerRow << 3;
  349.   Pict.bmhdr.h = bm->Rows;
  350.   Pict.bmhdr.x = 0;
  351.   Pict.bmhdr.y = 0;
  352.   Pict.bmhdr.nPlanes = bm->Depth;
  353.   Pict.bmhdr.masking = 0;
  354.   Pict.bmhdr.compression = 1;
  355.   Pict.bmhdr.pad1 = 0;
  356.   Pict.bmhdr.transparentColor = 0;
  357.   Pict.bmhdr.xAspect = (s->Width > 400) ? 10 : 20;
  358.   Pict.bmhdr.yAspect = (s->Height > 280) ? 11 : 22;
  359.   Pict.bmhdr.pageWidth = s->Width;
  360.   Pict.bmhdr.pageHeight = s->Height;
  361.   Pict.IFFid = FORM;
  362.   Pict.filelen = 0;  /* fill in later */
  363.   Pict.ILBMid = ILBM;
  364.   Pict.BMHDid = BMHD;
  365.   Pict.BMHDsize = sizeof(struct BMHdr);
  366.   gfwrite( (char *) &Pict, (short) sizeof(struct PictHdr), 1);
  367.  
  368.   write_CMAP(s, bm->Depth);
  369.   vmode = s->ViewPort.Modes;
  370.   vmode &= HIRES | LACE | EXTRA_HALFBRITE | HAM;
  371.   write_WORD(CAMG, out);
  372.   write_WORD(4L, out);
  373.   write_WORD(vmode, out);
  374.  
  375.   /*********************
  376.   Write the BODY chunk
  377.   **********************/
  378.  
  379.   write_WORD(BODY);
  380.   write_WORD(0L);     /* fill in later */
  381.   body_start = gftell();
  382.   save_BODY(bm, 1);
  383.   body_len = gftell() - body_start; /* length of body chunk */
  384.   if (gftell() & 0x01L) gputc(0);  /* pad byte if needed */
  385.   file_len = gftell();
  386.  
  387.   /**************************
  388.   Reposition in the file
  389.   and write the actual body
  390.   and file lengths.
  391.   ***************************/
  392.  
  393.   gfseek(body_start - 4L, 0);  /* body length */
  394.   write_WORD(body_len);
  395.   gfseek(4L, 0);               /* file length */
  396.   write_WORD(file_len - 8L);
  397.   gfclose("w");
  398.   CBClose();
  399.   return(1);
  400. }
  401.  
  402.  
  403.