home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / clipview / clipfile.c next >
Encoding:
C/C++ Source or Header  |  1990-07-05  |  8.5 KB  |  302 lines

  1. /*
  2.  * CLIPFILE.C -- File handling for ClipView
  3.  * Created by Microsoft Corporation, 1989
  4.  *
  5.  * This file contains one routine:  SaveClipboard(), which uses
  6.  * the OPENDLG library to put up a File...Save... dialog box.
  7.  *
  8.  * After getting a file name, it tries to save the current rendered format.
  9.  */
  10. #define INCL_BITMAPFILEFORMAT
  11. #define    INCL_DOSFILEMGR
  12. #define INCL_DOSMEMMGR
  13. #define INCL_GPIBITMAPS
  14. #define    INCL_GPIMETAFILES
  15. #define    INCL_WINCLIPBOARD
  16. #define    INCL_WINERRORS
  17. #include <os2.h>
  18. #include <opendlg.h>
  19. #include <string.h>
  20. #include "clipview.h"
  21. /*
  22.  * Globals
  23.  */
  24. extern HAB    vhab;            /* Anchor block        */
  25. extern HWND    vhwndClient;        /* Main client area    */
  26. /*
  27.     Macros
  28. */
  29. #define CHK(f) fSuccess = fSuccess && (f)
  30. #define LOADSTRING(id, sz) WinLoadString(vhab, (HMODULE) NULL, id, MAXLEN, sz)
  31. /*
  32.     Private function prototypes
  33. */
  34. BOOL SaveText(HFILE hf, PSZ pszText);
  35.  
  36. BOOL SaveClipboard(HWND hwnd, USHORT usFormat) {
  37. /*
  38.     Save the clipboard contents in several formats.
  39.     The "Save BITMAP" code is similar to that in the LINEFRAC sample.
  40. */
  41.     BOOL        fSuccess = TRUE;     /* Did we succeed in saving? */
  42.     ULONG        hItem;             /* Handle from QueryClipbrdData */
  43.     /*
  44.     Variables needed for File...Save... dialog.
  45.     */
  46.     DLF         dlf;             /* Dialog file */
  47.     HFILE        hf;             /* Handle to output file */
  48.     UCHAR        szExt[8];         /* Default extension */
  49.     UCHAR        szInst[MAXLEN];      /* Instructions */
  50.     UCHAR        szMessage[MAXLEN];   /* Various messages */
  51.     UCHAR        szTitle[MAXTITLELEN];/* Application title */
  52.     /*
  53.     Variables needed for saving Metafiles
  54.     */
  55.     HMF         hmfCopy;         /* Clipboard metafile copy */
  56.     /*
  57.     Variables needed for saving BITMAPs
  58.     */
  59.     BITMAPINFOHEADER    bmp;        /* Header to be queried */
  60.     HDC         hdcMemory;    /* Memory DC for the BITMAP */
  61.     HPS         hpsMemory;    /* ...and it's associated PS */
  62.     PBITMAPFILEHEADER    pbfh;        /* bmp + color table */
  63.     POINTL        ptlOrigin;    /* Bitmap origin */
  64.     SEL         selBuffer;    /* Selector to actual BITMAP */
  65.     SEL         selHeader;    /* Selector for the BMP header */
  66.     SIZEL        sizl;        /* Used in PS creation */
  67.     ULONG        cbBuffer;    /* No. of bytes in buffer */
  68.     USHORT        cbExtra;    /* No. of bytes in "final" segment */
  69.     USHORT        cbHeader;    /* No. of bytes in header */
  70.     USHORT        cbWrite1;    /* No. of bytes to be written... */
  71.     USHORT        cbWrite2;    /* ...in the two-part sel writes */
  72.     USHORT        cbWritten;    /* No. of bytes actually written */
  73.     USHORT        cSegs;        /* No. of segments to write */
  74.     USHORT        i;        /* Which segment is being written? */
  75.     USHORT        usHugeShift;
  76.     /*
  77.     Open the clipboard
  78.     */
  79.     if (!WinOpenClipbrd(vhab))
  80.     return FALSE;
  81.     /*
  82.     Get the clipboard data
  83.     */
  84.     if (hItem = WinQueryClipbrdData(vhab, usFormat)) {
  85.     /*
  86.         Put up the Save... file dialog with the appropriate extensions
  87.     */
  88.     switch (usFormat) {
  89.         case CF_TEXT:
  90.         case CF_DSPTEXT:     strcpy(szExt, "\\*.TXT");  break;
  91.  
  92.         case CF_BITMAP:
  93.         case CF_DSPBITMAP:     strcpy(szExt, "\\*.BMP");  break;
  94.  
  95.         case CF_METAFILE:
  96.         case CF_DSPMETAFILE: strcpy(szExt, "\\*.MET");  break;
  97.  
  98.         default:         strcpy(szExt, "\\*.*");    break;
  99.     }
  100.     /*
  101.         Put the string "Saving Format:  <format>" in the Save dialog box
  102.     */
  103.     GetFormatName(usFormat, szMessage);
  104.     LOADSTRING(IDS_SAVETITLE, szTitle);
  105.     strcat(szTitle, szMessage);
  106.  
  107.     LOADSTRING(IDS_APPNAME, szMessage);
  108.     LOADSTRING(IDS_INST, szInst);
  109.  
  110.     SetupDLF(&dlf, DLG_SAVEDLG, &hf,
  111.          (PSZ) szExt, (PSZ) szMessage, (PSZ) szTitle, (PSZ) szInst);
  112.  
  113.     dlf.szFileName[0] = dlf.szOpenFile[0] = '\0';
  114.     /*
  115.         Put up a Save file dialog, and respond appropriately to
  116.         the return status.
  117.     */
  118.     switch (DlgFile(hwnd, &dlf)) {
  119.         case TDF_ERRMEM:
  120.         case TDF_INVALID:
  121.         case TDF_NOSAVE:
  122.         fSuccess = FALSE;
  123.  
  124.         /* fall through... */
  125.         default:
  126.         break;
  127.     }
  128.  
  129.     if (fSuccess) {
  130.       switch (usFormat) {
  131.  
  132.         case CF_TEXT:
  133.         case CF_DSPTEXT:
  134.         CHK(SaveText(hf, MAKEP((SEL) hItem, 0)));
  135.         DosClose(hf);
  136.         break;
  137.  
  138.         case CF_BITMAP:
  139.         case CF_DSPBITMAP:
  140.         /*
  141.             Initialize the Memory DC and its PS
  142.         */
  143.         sizl.cx = sizl.cy = 0L;
  144.         hdcMemory = DevOpenDC(vhab, OD_MEMORY, "*", 0L, NULL, NULL);
  145.         hpsMemory = GpiCreatePS(vhab, hdcMemory, &sizl,
  146.                   GPIA_ASSOC | GPIT_MICRO | PU_PELS);
  147.         /*
  148.             Draw the BITMAP into the Memory DC
  149.         */
  150.         CHK(GpiSetBitmap(hpsMemory, (HBITMAP) hItem) != HBM_ERROR);
  151.         ptlOrigin.x = ptlOrigin.y = 0L;
  152.         CHK(WinDrawBitmap(hpsMemory, (HBITMAP) hItem, NULL,
  153.                &ptlOrigin, CLR_BLACK, CLR_BACKGROUND, DBM_NORMAL));
  154.         /*
  155.             Get information about the BITMAP
  156.         */
  157.         CHK(GpiQueryBitmapParameters((HBITMAP) hItem, &bmp) == GPI_OK);
  158.         /*
  159.             Compute the size of the buffer, and allocate
  160.             Make sure that > 64K BITMAPs are handled
  161.             (this code is from LFFILE.C)
  162.         */
  163.         cbBuffer = ( ((((ULONG)bmp.cBitCount*(ULONG) bmp.cx)+31L)/32L)
  164.                 * 4L * (ULONG) bmp.cy * (ULONG) bmp.cPlanes );
  165.         cSegs   = (USHORT) (cbBuffer >> 16);
  166.         cbExtra = (USHORT) (cbBuffer & 0xFFFFL);
  167.         CHK(!DosAllocHuge(cSegs, cbExtra, &selBuffer, 0, 0));
  168.         CHK(!DosGetHugeShift(&usHugeShift));
  169.         /*
  170.             Compute the size of the BITMAPFILEHEADER + color table...
  171.             ...then allocate it.
  172.         */
  173.         cbHeader = (USHORT) (sizeof(BITMAPFILEHEADER)
  174.                 + (sizeof(RGB) << bmp.cBitCount));
  175.         CHK(!DosAllocSeg(cbHeader, &selHeader, SEG_NONSHARED));
  176.         pbfh = MAKEP(selHeader, 0);
  177.         /*
  178.             Copy the BITMAP information from the BITMAPINFOHEADER
  179.         */
  180.         pbfh->bmp.cbFix     = 12;
  181.         pbfh->bmp.cx        = bmp.cx;
  182.         pbfh->bmp.cy        = bmp.cy;
  183.         pbfh->bmp.cPlanes   = bmp.cPlanes;
  184.         pbfh->bmp.cBitCount = bmp.cBitCount;
  185.         /*
  186.             Get the actual BITMAP bits
  187.         */
  188.         CHK(GpiQueryBitmapBits(hpsMemory, 0L, (LONG) bmp.cy,
  189.                MAKEP(selBuffer, 0), (PBITMAPINFO) &(pbfh->bmp))
  190.             != GPI_ALTERROR);
  191.         /*
  192.             Set up the file header
  193.         */
  194.         pbfh->usType        = BFT_BMAP;
  195.         pbfh->cbSize        = cbHeader + cbBuffer;
  196.         pbfh->xHotspot        = bmp.cx / 2;    /* Anywhere will do */
  197.         pbfh->yHotspot        = bmp.cy / 2;
  198.         pbfh->offBits        = cbHeader;
  199.         /*
  200.         Blast the BITMAP to a file...
  201.         */
  202.         /*
  203.             ...first, the header...
  204.         */
  205.         CHK(!DosWrite(hf, pbfh, cbHeader, &cbWritten));
  206.         /*
  207.             ...then, the possibly large BITMAP itself
  208.         */
  209.         for (i = 0; i <= cSegs; ++i) {
  210.             if (i < cSegs) {
  211.             /*
  212.             If we a 64K segment, write it in two
  213.             parts.     This must be done because
  214.             DosWrite() can only write 64K - 1
  215.             characters at once.
  216.             */
  217.             cbWrite1 = cbWrite2 = 0x8000;
  218.             } else {
  219.             /*
  220.             The last segment is always small enough
  221.             to write entirely.
  222.             */
  223.             cbWrite1 = cbExtra; cbWrite2 = 0;
  224.             }
  225.  
  226.             if (cbWrite1) {
  227.             CHK(!DosWrite(hf,
  228.                 MAKEP((selBuffer + (i << usHugeShift)), 0),
  229.                 cbWrite1, &cbWritten));
  230.             if (cbWrite2) {
  231.                 CHK(!DosWrite(hf,
  232.                 MAKEP((selBuffer + (i<<usHugeShift)),cbWrite1),
  233.                 cbWrite2, &cbWritten));
  234.             }
  235.             }
  236.         }
  237.         /*
  238.             Clean up
  239.  
  240.             Error codes are not checked here because the file has
  241.             already been saved.
  242.         */
  243.         DosClose(hf);
  244.         GpiSetBitmap(hpsMemory, NULL);
  245.         GpiDestroyPS(hpsMemory);
  246.         DevCloseDC(hdcMemory);
  247.         break;
  248.  
  249.         case CF_METAFILE:
  250.         case CF_DSPMETAFILE:
  251.         /*
  252.             Save metafile
  253.  
  254.             We close and delete the file, because GpiSaveMetaFile()
  255.             only allows the user to create a new file.
  256.  
  257.             We copy the metafile because GpiSaveMetafile()
  258.             removes the data from the application's memory.
  259.         */
  260.         DosClose(hf);
  261.         CHK(!DosDelete(dlf.szFileName, 0L));
  262.         CHK((hmfCopy = GpiCopyMetaFile((HMF) hItem)) != GPI_ERROR);
  263.         CHK(GpiSaveMetaFile(hmfCopy, dlf.szFileName) != GPI_ERROR);
  264.         break;
  265.  
  266.         default:
  267.         /*
  268.             It may be reasonable to add support for other formats
  269.             here, by saving a bitmap of the current window contents.
  270.  
  271.             But for now, close the file and return an error message.
  272.         */
  273.         DosClose(hf);
  274.         fSuccess = FALSE;
  275.         break;
  276.       }
  277.     }
  278.     } else
  279.     fSuccess = FALSE;    /* Couldn't query the clipboard format! */
  280.     /*
  281.     Clean up
  282.     */
  283.     WinCloseClipbrd(vhab);
  284.     return fSuccess;
  285. }
  286.  
  287. BOOL SaveText(HFILE hf, PSZ pszText) {
  288. /*
  289.     Save text format
  290.  
  291.     Count the number of characters, then write them.
  292. */
  293.     PSZ     pszCounter;     /* Temporary to count chars in sel */
  294.     ULONG   ulcch = 0;        /* The number of characters */
  295.     USHORT  cbWritten;        /* No. of bytes actually written */
  296.  
  297.     pszCounter = pszText;
  298.     while (*pszCounter++) ulcch++;
  299.  
  300.     return(!DosWrite(hf, pszText, (USHORT) ulcch, &cbWritten));
  301. }
  302.