| 1 | /***
 | 
|---|
| 2 |  This file belongs to the Gotcha! distribution.
 | 
|---|
| 3 |  Copyright (C) 1998-2002 Thorsten Thielen <thth@c2226.de>
 | 
|---|
| 4 | 
 | 
|---|
| 5 |  This program is free software; you can redistribute it and/or modify
 | 
|---|
| 6 |  it under the terms of the GNU General Public License as published by
 | 
|---|
| 7 |  the Free Software Foundation; either version 2 of the License, or
 | 
|---|
| 8 |  (at your option) any later version.
 | 
|---|
| 9 | 
 | 
|---|
| 10 |  This program is distributed in the hope that it will be useful,
 | 
|---|
| 11 |  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 12 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 13 |  GNU General Public License for more details.
 | 
|---|
| 14 | 
 | 
|---|
| 15 |  You should have received a copy of the GNU General Public License
 | 
|---|
| 16 |  along with this program; if not, write to the Free Software
 | 
|---|
| 17 |  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|---|
| 18 |  ***/
 | 
|---|
| 19 | 
 | 
|---|
| 20 | #include <time.h>
 | 
|---|
| 21 | 
 | 
|---|
| 22 | #include "gbm\gbm.h"
 | 
|---|
| 23 | #include "gbm\gbmmem.h"
 | 
|---|
| 24 | #include "model.h"
 | 
|---|
| 25 | 
 | 
|---|
| 26 | /* ------------------------------ */
 | 
|---|
| 27 | static int StrideOf(const MOD *mod)
 | 
|---|
| 28 | {
 | 
|---|
| 29 |         return ( ( mod->gbm.w * mod->gbm.bpp + 31 ) / 32 ) * 4;
 | 
|---|
| 30 |         }
 | 
|---|
| 31 | /*...e*/
 | 
|---|
| 32 | 
 | 
|---|
| 33 | /*...sAllocateData:0:*/
 | 
|---|
| 34 | static BOOL AllocateData(MOD *mod)
 | 
|---|
| 35 |         {
 | 
|---|
| 36 |         const unsigned long stride = StrideOf(mod);
 | 
|---|
| 37 |         if ( (mod->pbData = (UCHAR*) gbmmem_malloc(stride * mod->gbm.h)) == NULL )
 | 
|---|
| 38 |             return FALSE;
 | 
|---|
| 39 |         return TRUE;
 | 
|---|
| 40 |         }
 | 
|---|
| 41 | /*...e*/
 | 
|---|
| 42 | 
 | 
|---|
| 43 | /*...sModCreate:0:*/
 | 
|---|
| 44 | MOD_ERR ModCreate(
 | 
|---|
| 45 |         int w, int h, int bpp, const GBMRGB gbmrgb[],
 | 
|---|
| 46 |         MOD *modNew
 | 
|---|
| 47 |         )
 | 
|---|
| 48 |         {
 | 
|---|
| 49 |         modNew->gbm.w   = w;
 | 
|---|
| 50 |         modNew->gbm.h   = h;
 | 
|---|
| 51 |         modNew->gbm.bpp = bpp;
 | 
|---|
| 52 |         if ( gbmrgb != NULL && bpp != 24 )
 | 
|---|
| 53 |                 memcpy(&(modNew->gbmrgb), gbmrgb, sizeof(GBMRGB) << bpp);
 | 
|---|
| 54 |         if ( !AllocateData(modNew) )
 | 
|---|
| 55 |             return MOD_ERR_MEM;
 | 
|---|
| 56 |         return MOD_ERR_OK;
 | 
|---|
| 57 |         }
 | 
|---|
| 58 | /*...e*/
 | 
|---|
| 59 | 
 | 
|---|
| 60 | /*MOD_ERR ModCreateFromHPS(
 | 
|---|
| 61 |         HPS hps, int w, int h, int bpp, //lBitCountScreen > 8 ) ? 24 : lBitCountScreen
 | 
|---|
| 62 |         MOD *modNew
 | 
|---|
| 63 |         )*/
 | 
|---|
| 64 | /*...sModCreateFromHPS:0:*/
 | 
|---|
| 65 | MOD_ERR ModCreateFromHPS(
 | 
|---|
| 66 |         HPS hps, int w, int h, int bpp,
 | 
|---|
| 67 |         MOD *modNew
 | 
|---|
| 68 |         )
 | 
|---|
| 69 |         {
 | 
|---|
| 70 |         MOD_ERR mrc;
 | 
|---|
| 71 | 
 | 
|---|
| 72 |     #pragma pack(2)
 | 
|---|
| 73 |         struct
 | 
|---|
| 74 |                 {
 | 
|---|
| 75 |                 BITMAPINFOHEADER2 bmp2;
 | 
|---|
| 76 |                 RGB2 argb2Color[0x100];
 | 
|---|
| 77 |                 } bm;
 | 
|---|
| 78 |     #pragma pack()
 | 
|---|
| 79 | 
 | 
|---|
| 80 |         if ( (mrc = ModCreate(w, h, bpp, NULL, modNew)) != MOD_ERR_OK )
 | 
|---|
| 81 |             return mrc;
 | 
|---|
| 82 | 
 | 
|---|
| 83 |         memset(&(bm.bmp2), 0, sizeof(bm.bmp2));
 | 
|---|
| 84 |         bm.bmp2.cbFix     = sizeof(BITMAPINFOHEADER2);
 | 
|---|
| 85 |         bm.bmp2.cx        = w;
 | 
|---|
| 86 |         bm.bmp2.cy        = h;
 | 
|---|
| 87 |         bm.bmp2.cBitCount = bpp;
 | 
|---|
| 88 |         bm.bmp2.cPlanes   = 1;
 | 
|---|
| 89 |         GpiQueryBitmapBits(hps, 0L, h, modNew->pbData, (BITMAPINFO2 *) &bm);
 | 
|---|
| 90 | 
 | 
|---|
| 91 |         if ( bpp != 24 )
 | 
|---|
| 92 |                 {
 | 
|---|
| 93 |                 int i;
 | 
|---|
| 94 |                 for ( i = 0; i < (1<<bpp); i++ )
 | 
|---|
| 95 |                         {
 | 
|---|
| 96 |                         modNew->gbmrgb[i].r = bm.argb2Color[i].bRed  ;
 | 
|---|
| 97 |                         modNew->gbmrgb[i].g = bm.argb2Color[i].bGreen;
 | 
|---|
| 98 |                         modNew->gbmrgb[i].b = bm.argb2Color[i].bBlue ;
 | 
|---|
| 99 |                         }
 | 
|---|
| 100 |                 }
 | 
|---|
| 101 |         return MOD_ERR_OK;
 | 
|---|
| 102 |         }
 | 
|---|
| 103 | /*...e*/
 | 
|---|
| 104 | 
 | 
|---|
| 105 | /*MOD_ERR ModWriteToFile(
 | 
|---|
| 106 |         const MOD *mod,
 | 
|---|
| 107 |         const CHAR *szFn, const CHAR *szOpt // ""
 | 
|---|
| 108 |         )*/
 | 
|---|
| 109 | /*...sModWriteToFile:0:*/
 | 
|---|
| 110 | MOD_ERR ModWriteToFile(
 | 
|---|
| 111 |         const MOD *mod,
 | 
|---|
| 112 |         const CHAR *szFn, const CHAR *szOpt
 | 
|---|
| 113 |         )
 | 
|---|
| 114 |         {
 | 
|---|
| 115 |         GBM_ERR grc;
 | 
|---|
| 116 |         int fd, ft, flag = 0;
 | 
|---|
| 117 |         GBMFT gbmft;
 | 
|---|
| 118 | 
 | 
|---|
| 119 |         if ( (grc = gbm_guess_filetype(szFn, &ft)) != GBM_ERR_OK ) {
 | 
|---|
| 120 |             return grc;
 | 
|---|
| 121 |         }
 | 
|---|
| 122 |         gbm_query_filetype(ft, &gbmft);
 | 
|---|
| 123 |         
 | 
|---|
| 124 |         switch ( mod->gbm.bpp )
 | 
|---|
| 125 |                 {
 | 
|---|
| 126 |                 case 1:         flag = GBM_FT_W1;       break;
 | 
|---|
| 127 |                 case 4:         flag = GBM_FT_W4;       break;
 | 
|---|
| 128 |                 case 8:         flag = GBM_FT_W8;       break;
 | 
|---|
| 129 |                 case 24:        flag = GBM_FT_W24;      break;
 | 
|---|
| 130 |                 default:        flag = 0;       break;
 | 
|---|
| 131 |                 }
 | 
|---|
| 132 | 
 | 
|---|
| 133 |         if ( (gbmft.flags & flag) == 0 )
 | 
|---|
| 134 |             return MOD_ERR_SUPPORT;
 | 
|---|
| 135 |         
 | 
|---|
| 136 |         if ( (fd = gbm_io_create(szFn, GBM_O_WRONLY)) == -1 )
 | 
|---|
| 137 |                 return MOD_ERR_CREATE;
 | 
|---|
| 138 |         
 | 
|---|
| 139 |         if ( (grc = gbm_write(szFn, fd, ft, &(mod->gbm), mod->gbmrgb,
 | 
|---|
| 140 |                               mod->pbData, szOpt)) != GBM_ERR_OK )
 | 
|---|
| 141 |                 {
 | 
|---|
| 142 |                 gbm_io_close(fd);
 | 
|---|
| 143 |                 unlink(szFn);
 | 
|---|
| 144 |                 return MOD_ERR_GBM(grc);
 | 
|---|
| 145 |                 }
 | 
|---|
| 146 |         
 | 
|---|
| 147 |         gbm_io_close(fd);
 | 
|---|
| 148 |         return MOD_ERR_OK;
 | 
|---|
| 149 |         }
 | 
|---|
| 150 | /*...e*/
 | 
|---|
| 151 | // ** SaveBitmap ********************************************************** /*FOLD00*/
 | 
|---|
| 152 | 
 | 
|---|
| 153 | VOID SaveBitmap (HBITMAP hbm, HPS hps, int width, int height,
 | 
|---|
| 154 |                  int bitCount, char *title)
 | 
|---|
| 155 | {
 | 
|---|
| 156 | #ifdef _DOLOGMEM_
 | 
|---|
| 157 |     LogMem("SaveBitmap", TRUE);
 | 
|---|
| 158 | #endif
 | 
|---|
| 159 |     MOD newmod;
 | 
|---|
| 160 | 
 | 
|---|
| 161 |     if( pset->QueryFileSaveStyle () == FSS_FORCEFILE )
 | 
|---|
| 162 |     {
 | 
|---|
| 163 |         PSZ psz = pset->QueryForceSaveFile();
 | 
|---|
| 164 |         psz = AddExtensionToFilename( psz );
 | 
|---|
| 165 |         ModCreateFromHPS( hps, width, height,
 | 
|---|
| 166 |                          (bitCount > 8 ) ? 24 : bitCount,
 | 
|---|
| 167 |                          &newmod );
 | 
|---|
| 168 |         ModWriteToFile(&newmod, psz, "" );
 | 
|---|
| 169 |         
 | 
|---|
| 170 | #ifdef _DOLOGMEM_
 | 
|---|
| 171 |         LogMem( "SaveBitmap-1", FALSE );
 | 
|---|
| 172 | #endif
 | 
|---|
| 173 |         return;
 | 
|---|
| 174 |     }
 | 
|---|
| 175 | 
 | 
|---|
| 176 |     if (pset->DoSound ())
 | 
|---|
| 177 |     {
 | 
|---|
| 178 |         DosBeep ( 500, 100);
 | 
|---|
| 179 |         DosBeep (1000, 100);
 | 
|---|
| 180 |         DosBeep (1500, 100);
 | 
|---|
| 181 |     }
 | 
|---|
| 182 | 
 | 
|---|
| 183 |     switch (pset->QuerySaveStyle ())
 | 
|---|
| 184 |     {
 | 
|---|
| 185 |     case SAVESTYLE_CLIPBOARD:
 | 
|---|
| 186 |         SaveBitmapToClipboard (hbm);
 | 
|---|
| 187 |         break;
 | 
|---|
| 188 | 
 | 
|---|
| 189 |     default:
 | 
|---|
| 190 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 191 |         LogDebug( "SaveBitmap()" );
 | 
|---|
| 192 | #endif
 | 
|---|
| 193 |         if (SelectSaveFile (title)) {
 | 
|---|
| 194 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 195 |             LogDebug( "Before call to SaveBitmapToFile()" );
 | 
|---|
| 196 | #endif
 | 
|---|
| 197 |             ModCreateFromHPS( hps, width, height,
 | 
|---|
| 198 |                              (bitCount > 8 ) ? 24 : bitCount,
 | 
|---|
| 199 |                              &newmod );
 | 
|---|
| 200 |             ModWriteToFile(&newmod, pset->QuerySaveFile (), "" );
 | 
|---|
| 201 | 
 | 
|---|
| 202 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 203 |             LogDebug( "After call to SaveBitmapToFile()" );
 | 
|---|
| 204 | #endif
 | 
|---|
| 205 |         }
 | 
|---|
| 206 |         break;
 | 
|---|
| 207 |     }
 | 
|---|
| 208 | 
 | 
|---|
| 209 | #ifdef _DOLOGMEM_
 | 
|---|
| 210 |     LogMem("SaveBitmap-2", FALSE);
 | 
|---|
| 211 | #endif
 | 
|---|
| 212 | }
 | 
|---|
| 213 | 
 | 
|---|
| 214 | // ** SaveBitmapToClipboard *********************************************** /*FOLD00*/
 | 
|---|
| 215 | 
 | 
|---|
| 216 | VOID SaveBitmapToClipboard (HBITMAP hbm)
 | 
|---|
| 217 | {
 | 
|---|
| 218 | #ifdef _DOLOGMEM_
 | 
|---|
| 219 |     LogMem("SaveBitmapToClipboard", TRUE);
 | 
|---|
| 220 | #endif
 | 
|---|
| 221 |     // copy the thing to the clipboard
 | 
|---|
| 222 |     WinOpenClipbrd (hab);
 | 
|---|
| 223 |     WinEmptyClipbrd (hab);
 | 
|---|
| 224 |     WinSetClipbrdData (hab, ULONG (hbm), CF_BITMAP, CFI_HANDLE);
 | 
|---|
| 225 |     WinCloseClipbrd (hab);
 | 
|---|
| 226 | #ifdef _DOLOGMEM_
 | 
|---|
| 227 |     LogMem("SaveBitmapToClipboard", FALSE);
 | 
|---|
| 228 | #endif
 | 
|---|
| 229 | }
 | 
|---|
| 230 | 
 | 
|---|
| 231 | // ** SaveBitmapToFile **************************************************** /*FOLD00*/
 | 
|---|
| 232 | #if 0
 | 
|---|
| 233 | #define CB_12HEADER       sizeof (BITMAPINFOHEADER) // == 12
 | 
|---|
| 234 | #define CB_16HEADER       (sizeof (BITMAPINFOHEADER2)-24)
 | 
|---|
| 235 | #define CB_20HEADER       sizeof (BITMAPINFOHEADER2) // == 64
 | 
|---|
| 236 | 
 | 
|---|
| 237 | 
 | 
|---|
| 238 | VOID SaveBitmapToFile (HBITMAP hbm, PSZ psz, HPS hps)
 | 
|---|
| 239 | {
 | 
|---|
| 240 |     ULONG rc;
 | 
|---|
| 241 | 
 | 
|---|
| 242 | #ifdef _DOLOGMEM_
 | 
|---|
| 243 |     LogMem("SaveBitmapToFile", TRUE);
 | 
|---|
| 244 | #endif
 | 
|---|
| 245 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 246 |     LogDebug( "Start of SaveBitmapToFile()" );
 | 
|---|
| 247 | #endif
 | 
|---|
| 248 |     // get the fullsized bitmap info header from the bitmap
 | 
|---|
| 249 |     BITMAPINFOHEADER2  bih2;
 | 
|---|
| 250 | 
 | 
|---|
| 251 |     bih2.cbFix = sizeof (BITMAPINFOHEADER2);
 | 
|---|
| 252 |     if (! GpiQueryBitmapInfoHeader (hbm, &bih2))
 | 
|---|
| 253 |     {
 | 
|---|
| 254 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 255 |         LogDebug( "SaveBitmapToFile(): Exit GpiQueryBitmapInfoHeader" );
 | 
|---|
| 256 | #endif
 | 
|---|
| 257 |         DisplayError (RSTR(IDS_HEADER_ERROR),
 | 
|---|
| 258 |                       RSTR(IDS_ERROR_COULDNOTRETRIEVEHEADER),
 | 
|---|
| 259 |                       WinGetLastError (hab));
 | 
|---|
| 260 |         return;
 | 
|---|
| 261 |     }
 | 
|---|
| 262 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 263 |     LogDebug( "SaveBitmapToFile(): GpiQueryBitmapInfoHeader ok." );
 | 
|---|
| 264 | #endif
 | 
|---|
| 265 | 
 | 
|---|
| 266 |     // get the size of the colortable
 | 
|---|
| 267 |     ULONG   cbColtab = 0L, cColors = 0L;
 | 
|---|
| 268 | 
 | 
|---|
| 269 |     if (bih2.cBitCount == 8)
 | 
|---|
| 270 |         cColors = 256L;
 | 
|---|
| 271 |     else if (bih2.cBitCount == 4)
 | 
|---|
| 272 |         cColors = 16L;
 | 
|---|
| 273 |     else if (bih2.cBitCount == 1)
 | 
|---|
| 274 |         cColors = 2L;
 | 
|---|
| 275 | 
 | 
|---|
| 276 |     cbColtab = cColors * sizeof( RGB2 );
 | 
|---|
| 277 | 
 | 
|---|
| 278 |     // get size of bits buffer and allocate it
 | 
|---|
| 279 |     ULONG cbBits =
 | 
|---|
| 280 |         (bih2.cBitCount * bih2.cx + 31L)/32L * bih2.cPlanes * 4L * bih2.cy;
 | 
|---|
| 281 |     PBYTE pb =
 | 
|---|
| 282 |         PBYTE (malloc (cbBits));
 | 
|---|
| 283 | 
 | 
|---|
| 284 |     // allocate and init the file info header
 | 
|---|
| 285 |     PBITMAPFILEHEADER2 pbfh2 =
 | 
|---|
| 286 |         PBITMAPFILEHEADER2 (malloc (sizeof (BITMAPFILEHEADER2)+cbColtab));
 | 
|---|
| 287 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 288 |     LogDebug( "SaveBitmapToFile(): Filling header." );
 | 
|---|
| 289 | #endif
 | 
|---|
| 290 | 
 | 
|---|
| 291 |     // fill the bitmap header with the bitmap data
 | 
|---|
| 292 |     memcpy (&(pbfh2->bmp2), &bih2, sizeof (BITMAPINFOHEADER2));
 | 
|---|
| 293 |     pbfh2->bmp2.cbImage = cbBits;
 | 
|---|
| 294 | 
 | 
|---|
| 295 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 296 |     LogDebug( "SaveBitmapToFile(): Before GpiQueryBitmapBits." );
 | 
|---|
| 297 | #endif
 | 
|---|
| 298 |     // grab the bits!! ;-) - and the colortable
 | 
|---|
| 299 |     if (GpiQueryBitmapBits (hps, 0, bih2.cy, pb, PBITMAPINFO2 (&(pbfh2->bmp2)))
 | 
|---|
| 300 |         == GPI_ALTERROR)
 | 
|---|
| 301 |     {
 | 
|---|
| 302 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 303 |         LogDebug( "SaveBitmapToFile(): Exit GpiQueryBitmapBits" );
 | 
|---|
| 304 | #endif
 | 
|---|
| 305 |         DisplayError (RSTR(IDS_HEADER_ERROR),
 | 
|---|
| 306 |                       RSTR(IDS_ERROR_COULDNOTGETBITMAPBITS),
 | 
|---|
| 307 |                       WinGetLastError (hab));
 | 
|---|
| 308 |         free (pb);
 | 
|---|
| 309 |         return;
 | 
|---|
| 310 |     }
 | 
|---|
| 311 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 312 |     LogDebug( "SaveBitmapToFile(): GpiQueryBitmapBits ok." );
 | 
|---|
| 313 | #endif
 | 
|---|
| 314 | 
 | 
|---|
| 315 |     pbfh2->usType   = BFT_BMAP;
 | 
|---|
| 316 |     pbfh2->offBits  = sizeof (BITMAPFILEHEADER2)-sizeof (BITMAPINFOHEADER2);
 | 
|---|
| 317 | 
 | 
|---|
| 318 |     switch (pset->QueryFileFormat ())
 | 
|---|
| 319 |     {
 | 
|---|
| 320 |     case BMF_12:
 | 
|---|
| 321 |         pbfh2->offBits += CB_12HEADER + cColors*sizeof (RGB);
 | 
|---|
| 322 |         break;
 | 
|---|
| 323 | 
 | 
|---|
| 324 |     case BMF_20:
 | 
|---|
| 325 |         pbfh2->offBits += CB_20HEADER + cColors*sizeof (RGB2);
 | 
|---|
| 326 |         break;
 | 
|---|
| 327 | 
 | 
|---|
| 328 |     default:
 | 
|---|
| 329 |         pbfh2->offBits += CB_16HEADER + cColors*sizeof (RGB2);
 | 
|---|
| 330 |         break;
 | 
|---|
| 331 |     }
 | 
|---|
| 332 | 
 | 
|---|
| 333 |     pbfh2->cbSize   = pbfh2->offBits+cbBits;
 | 
|---|
| 334 |     pbfh2->xHotspot = pbfh2->yHotspot = 0;
 | 
|---|
| 335 | 
 | 
|---|
| 336 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 337 |     LogDebug( "SaveBitmapToFile(): Before if." );
 | 
|---|
| 338 | #endif
 | 
|---|
| 339 |     if( ( pset->QueryFileFormat() == BMF_12 ) ||
 | 
|---|
| 340 |         ( pset->QueryFileFormat() == BMF_16 ) ||
 | 
|---|
| 341 |         ( pset->QueryFileFormat() == BMF_20 ) )
 | 
|---|
| 342 |     {
 | 
|---|
| 343 |         // open out file
 | 
|---|
| 344 |         FILE  *pf = fopen (psz, "wb");
 | 
|---|
| 345 |         if (! pf)
 | 
|---|
| 346 |         {
 | 
|---|
| 347 |             DisplayError (RSTR(IDS_HEADER_ERROR), RSTR(IDS_ERROR_COULDNOTOPENFILE),
 | 
|---|
| 348 |                           psz);
 | 
|---|
| 349 |             free (pb);
 | 
|---|
| 350 |             return;
 | 
|---|
| 351 |         }
 | 
|---|
| 352 | 
 | 
|---|
| 353 |         // write file info header
 | 
|---|
| 354 |         fwrite (pbfh2, sizeof (BITMAPFILEHEADER2)-sizeof (BITMAPINFOHEADER2),
 | 
|---|
| 355 |                 1, pf);
 | 
|---|
| 356 | 
 | 
|---|
| 357 |         // write bitmap info header
 | 
|---|
| 358 |         switch (pset->QueryFileFormat ())
 | 
|---|
| 359 |         {
 | 
|---|
| 360 |         case BMF_12:
 | 
|---|
| 361 |             {
 | 
|---|
| 362 |                 BITMAPINFOHEADER   bih;
 | 
|---|
| 363 | 
 | 
|---|
| 364 |                 bih.cbFix     = CB_12HEADER;
 | 
|---|
| 365 |                 bih.cx        = USHORT (bih2.cx);
 | 
|---|
| 366 |                 bih.cy        = USHORT (bih2.cy);
 | 
|---|
| 367 |                 bih.cPlanes   = bih2.cPlanes;
 | 
|---|
| 368 |                 bih.cBitCount = bih2.cBitCount;
 | 
|---|
| 369 | 
 | 
|---|
| 370 |                 fwrite (&bih, CB_12HEADER, 1, pf);
 | 
|---|
| 371 |             }
 | 
|---|
| 372 |             break;
 | 
|---|
| 373 | 
 | 
|---|
| 374 |         case BMF_20:
 | 
|---|
| 375 |             pbfh2->bmp2.cbFix = CB_20HEADER;
 | 
|---|
| 376 |             fwrite (&(pbfh2->bmp2), CB_20HEADER, 1, pf);
 | 
|---|
| 377 |             break;
 | 
|---|
| 378 | 
 | 
|---|
| 379 |         default:
 | 
|---|
| 380 |             pbfh2->bmp2.cbFix = CB_16HEADER;
 | 
|---|
| 381 |             fwrite (&(pbfh2->bmp2), CB_16HEADER, 1, pf);
 | 
|---|
| 382 |             break;
 | 
|---|
| 383 |         }
 | 
|---|
| 384 | 
 | 
|---|
| 385 |         // write colortable if present
 | 
|---|
| 386 |         if (cbColtab)
 | 
|---|
| 387 |         {
 | 
|---|
| 388 |             switch (pset->QueryFileFormat ())
 | 
|---|
| 389 |             {
 | 
|---|
| 390 |             case BMF_12:
 | 
|---|
| 391 |                 {
 | 
|---|
| 392 |                     RGB  rgb;
 | 
|---|
| 393 |                     for (USHORT i = 0; i < cColors; i++)
 | 
|---|
| 394 |                     {
 | 
|---|
| 395 |                         rgb.bRed   = PBITMAPINFO2 (&(pbfh2->bmp2))
 | 
|---|
| 396 |                             ->argbColor[i].bRed;
 | 
|---|
| 397 |                         rgb.bGreen = PBITMAPINFO2 (&(pbfh2->bmp2))
 | 
|---|
| 398 |                             ->argbColor[i].bGreen;
 | 
|---|
| 399 |                         rgb.bBlue  = PBITMAPINFO2 (&(pbfh2->bmp2))
 | 
|---|
| 400 |                             ->argbColor[i].bBlue;
 | 
|---|
| 401 |                         fwrite (&rgb, sizeof (rgb), 1, pf);
 | 
|---|
| 402 |                     }
 | 
|---|
| 403 |                 }
 | 
|---|
| 404 |                 break;
 | 
|---|
| 405 | 
 | 
|---|
| 406 |             default:
 | 
|---|
| 407 |                 fwrite (PBYTE (&(pbfh2->bmp2))+sizeof (BITMAPINFOHEADER2),
 | 
|---|
| 408 |                     cbColtab, 1, pf);
 | 
|---|
| 409 |                 break;
 | 
|---|
| 410 |             }
 | 
|---|
| 411 |         }
 | 
|---|
| 412 | 
 | 
|---|
| 413 |         // write the actual bitmap data bits
 | 
|---|
| 414 |         fwrite (pb, cbBits, 1, pf);
 | 
|---|
| 415 |         fclose (pf);
 | 
|---|
| 416 |     }
 | 
|---|
| 417 | 
 | 
|---|
| 418 | #ifdef _DOLOGDEBUG_
 | 
|---|
| 419 |     LogDebug( "SaveBitmapToFile(): Everything done, closed file" );
 | 
|---|
| 420 | #endif
 | 
|---|
| 421 | 
 | 
|---|
| 422 |     // set BITMAP file type ea
 | 
|---|
| 423 |     SetEAs( psz );
 | 
|---|
| 424 | 
 | 
|---|
| 425 |     // cleanup and return
 | 
|---|
| 426 |     free (pbfh2);
 | 
|---|
| 427 |     free (pb);
 | 
|---|
| 428 | #ifdef _DOLOGMEM_
 | 
|---|
| 429 |     LogMem("SaveBitmapToFile", FALSE);
 | 
|---|
| 430 | #endif
 | 
|---|
| 431 | }
 | 
|---|
| 432 | #endif
 | 
|---|
| 433 | // ** SetEAs ************************************************************** /*FOLD00*/
 | 
|---|
| 434 | #if 0
 | 
|---|
| 435 | BOOL SetEAs (PSZ psz)
 | 
|---|
| 436 | {
 | 
|---|
| 437 | #ifdef _DOLOGMEM_
 | 
|---|
| 438 |     LogMem("SetEAs", TRUE);
 | 
|---|
| 439 | #endif
 | 
|---|
| 440 |     // alloc memory for EA data
 | 
|---|
| 441 |     CHAR    achComment[ 100 ];
 | 
|---|
| 442 |     time_t  tim = time_t( time( NULL ) );
 | 
|---|
| 443 |     sprintf( achComment, "Captured by %s on %s", PSZ_NAMEVERSION, ctime( &tim ) );
 | 
|---|
| 444 |     PSZ     pszName = ".TYPE", pszName2 = ".COMMENT";
 | 
|---|
| 445 |     PSZ     pszValue = pset->GetFileEAType();
 | 
|---|
| 446 |     USHORT  cbName = strlen (pszName)+1, cbName2 = strlen( pszName2 )+1;
 | 
|---|
| 447 |     USHORT  cbValue = strlen (pszValue)+1, cbValue2 = strlen( achComment )+1;
 | 
|---|
| 448 |     USHORT  usMemNeeded = sizeof (FEA2LIST) + cbName + cbValue +cbName2  + cbValue2;
 | 
|---|
| 449 |     PBYTE   pb = PBYTE (malloc (usMemNeeded));
 | 
|---|
| 450 | 
 | 
|---|
| 451 |     EAOP2   eaop2;
 | 
|---|
| 452 | 
 | 
|---|
| 453 |     eaop2.fpFEA2List = (FEA2LIST FAR *) pb;
 | 
|---|
| 454 |     eaop2.fpFEA2List->cbList = usMemNeeded;
 | 
|---|
| 455 | 
 | 
|---|
| 456 |     eaop2.fpFEA2List->list[0].fEA     = 0;  // EA is no "must have"
 | 
|---|
| 457 |     eaop2.fpFEA2List->list[0].cbName  = cbName-1;
 | 
|---|
| 458 |     eaop2.fpFEA2List->list[0].cbValue = cbValue;
 | 
|---|
| 459 |     eaop2.fpFEA2List->list[1].fEA     = 0;  // EA is no "must have"
 | 
|---|
| 460 |     eaop2.fpFEA2List->list[1].cbName  = cbName2-1;
 | 
|---|
| 461 |     eaop2.fpFEA2List->list[1].cbValue = cbValue2;
 | 
|---|
| 462 | 
 | 
|---|
| 463 |     strcpy (eaop2.fpFEA2List->list[0].szName, pszName);
 | 
|---|
| 464 |     memcpy (eaop2.fpFEA2List->list[0].szName+cbName, pszValue, cbValue);
 | 
|---|
| 465 |     strcpy (eaop2.fpFEA2List->list[1].szName, pszName2);
 | 
|---|
| 466 |     memcpy (eaop2.fpFEA2List->list[1].szName+cbName2, achComment, cbValue2);
 | 
|---|
| 467 | 
 | 
|---|
| 468 |     if (DosSetPathInfo (psz, FIL_QUERYEASIZE, PVOID (&eaop2),
 | 
|---|
| 469 |                         sizeof (EAOP2), DSPI_WRTTHRU))
 | 
|---|
| 470 |     {
 | 
|---|
| 471 |         DisplayError (RSTR(IDS_HEADER_ERROR),
 | 
|---|
| 472 |                       RSTR(IDS_ERROR_COULDNOTWRITEFILETYPEEA));
 | 
|---|
| 473 |         free (pb);
 | 
|---|
| 474 | #ifdef _DOLOGMEM_
 | 
|---|
| 475 |     LogMem("SetEAs-1", FALSE);
 | 
|---|
| 476 | #endif
 | 
|---|
| 477 |         return FALSE;
 | 
|---|
| 478 |     }
 | 
|---|
| 479 | 
 | 
|---|
| 480 |     free (pb);
 | 
|---|
| 481 | #ifdef _DOLOGMEM_
 | 
|---|
| 482 |     LogMem("SetEAs-2", FALSE);
 | 
|---|
| 483 | #endif
 | 
|---|
| 484 |     return TRUE;
 | 
|---|
| 485 | }
 | 
|---|
| 486 | #endif
 | 
|---|
| 487 | // ** SelectSaveFile ****************************************************** /*FOLD00*/
 | 
|---|
| 488 | 
 | 
|---|
| 489 | BOOL SelectSaveFile (char *title)
 | 
|---|
| 490 | {
 | 
|---|
| 491 | #ifdef _DOLOGMEM_
 | 
|---|
| 492 |     LogMem("SelectSaveFile", TRUE);
 | 
|---|
| 493 | #endif
 | 
|---|
| 494 |     // if FSS_NUMFILES, create and return a new name
 | 
|---|
| 495 |     if (pset->QueryFileSaveStyle () == FSS_NUMFILES)
 | 
|---|
| 496 |     {
 | 
|---|
| 497 |         CHAR   ach[_MAX_PATH];
 | 
|---|
| 498 |         for (USHORT i = 0; i < 100; i++)
 | 
|---|
| 499 |         {
 | 
|---|
| 500 | #ifdef _QUIET_
 | 
|---|
| 501 |             if (g_installer)
 | 
|---|
| 502 |                 sprintf( ach, strlen(pset->QueryNumSaveDir()) > 3 ? "%s\\Goq%02d.%s" : "%sGoq%02d.%s",
 | 
|---|
| 503 |                         pset->QueryNumSaveDir(),  i, pset->GetFileExtension() );
 | 
|---|
| 504 |             else
 | 
|---|
| 505 | #endif
 | 
|---|
| 506 |                 sprintf( ach, strlen(pset->QueryNumSaveDir()) > 3 ? "%s\\%s%02d.%s" : "%s%s%02d.%s",
 | 
|---|
| 507 |                         pset->QueryNumSaveDir(), title, i, pset->GetFileExtension() );
 | 
|---|
| 508 |             if (access (ach, 1) != 0)
 | 
|---|
| 509 |             {
 | 
|---|
| 510 |                 pset->SetSaveFile (ach);
 | 
|---|
| 511 |                 return TRUE;
 | 
|---|
| 512 |             }
 | 
|---|
| 513 |         }
 | 
|---|
| 514 |         return FALSE;
 | 
|---|
| 515 |     }
 | 
|---|
| 516 | 
 | 
|---|
| 517 |     // ... else do a file dlg
 | 
|---|
| 518 |     FILEDLG    fdlg;
 | 
|---|
| 519 | 
 | 
|---|
| 520 |     memset (&fdlg, 0, sizeof (fdlg));
 | 
|---|
| 521 | 
 | 
|---|
| 522 |     fdlg.hMod       = GETMODULE;
 | 
|---|
| 523 |     fdlg.usDlgId    = ID_DLG_FILE;
 | 
|---|
| 524 |     fdlg.pfnDlgProc = FileDLGProcedure;
 | 
|---|
| 525 |     fdlg.cbSize     = sizeof (fdlg);
 | 
|---|
| 526 |     fdlg.fl         = FDS_SAVEAS_DIALOG | FDS_CENTER | FDS_CUSTOM;
 | 
|---|
| 527 |     fdlg.pszTitle   = RSTR(IDS_SAVESCREENSHOTTO);
 | 
|---|
| 528 |     strcpy (fdlg.szFullFile, pset->QuerySaveFile ());
 | 
|---|
| 529 | 
 | 
|---|
| 530 |     if (WinFileDlg (HWND_DESKTOP, HWND_DESKTOP, &fdlg))
 | 
|---|
| 531 |     {
 | 
|---|
| 532 |         if (fdlg.lReturn != DID_OK)
 | 
|---|
| 533 |             return FALSE;
 | 
|---|
| 534 | 
 | 
|---|
| 535 |         PSZ pszOut = fdlg.szFullFile;
 | 
|---|
| 536 | 
 | 
|---|
| 537 |         // Add bmp extension if not already present.
 | 
|---|
| 538 |         if( pset->AutoaddExtension() )
 | 
|---|
| 539 |             pszOut = AddExtensionToFilename( pszOut );
 | 
|---|
| 540 | 
 | 
|---|
| 541 |         // if file exists and user wants it, confirm overwriting
 | 
|---|
| 542 |         if (pset->ConfirmOverwrite ())
 | 
|---|
| 543 |             if (access (pszOut, 0) == 0)
 | 
|---|
| 544 |                 // let user confirm operation
 | 
|---|
| 545 |                 if (WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
 | 
|---|
| 546 |                                    RSTR(IDS_FILEEXISTSOVERWRITE),
 | 
|---|
| 547 |                                    RSTR(IDS_HEADER_WARNING), 0L,
 | 
|---|
| 548 |                                    MB_OKCANCEL | MB_QUERY | MB_DEFBUTTON2 |
 | 
|---|
| 549 |                                    MB_MOVEABLE)
 | 
|---|
| 550 |                     != MBID_OK)
 | 
|---|
| 551 |                     return FALSE;
 | 
|---|
| 552 | 
 | 
|---|
| 553 |         pset->SetSaveFile (pszOut);
 | 
|---|
| 554 |         return TRUE;
 | 
|---|
| 555 |     }
 | 
|---|
| 556 |     return FALSE;
 | 
|---|
| 557 | #ifdef _DOLOGMEM_
 | 
|---|
| 558 |     LogMem("SelectSaveFile", FALSE);
 | 
|---|
| 559 | #endif
 | 
|---|
| 560 | }
 | 
|---|
| 561 | 
 | 
|---|
| 562 | // ** FileDLGProcedure **************************************************** /*FOLD00*/
 | 
|---|
| 563 | 
 | 
|---|
| 564 | MRESULT EXPENTRY FileDLGProcedure (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
 | 
|---|
| 565 | {
 | 
|---|
| 566 | #ifdef _DOFNCOMPLETION_
 | 
|---|
| 567 |     static HDIR   hdir = NULLHANDLE;
 | 
|---|
| 568 |     static BOOL   fCompletion = FALSE;
 | 
|---|
| 569 | #endif
 | 
|---|
| 570 | 
 | 
|---|
| 571 |     switch (msg)
 | 
|---|
| 572 |     {
 | 
|---|
| 573 |     case WM_INITDLG:
 | 
|---|
| 574 | 
 | 
|---|
| 575 |         HMQ hmq;
 | 
|---|
| 576 |         BOOL bUniCodeFont;
 | 
|---|
| 577 |         CHAR ucFont[FACESIZE];
 | 
|---|
| 578 |         CHAR *lang;
 | 
|---|
| 579 | 
 | 
|---|
| 580 |         lang = getenv("LANG");
 | 
|---|
| 581 |         bUniCodeFont = FALSE;
 | 
|---|
| 582 |         if (pset->GetLangID() == RU) {
 | 
|---|
| 583 |             hmq = WinQueryWindowULong( hwnd, QWL_HMQ);
 | 
|---|
| 584 |             WinSetCp(hmq, 866);
 | 
|---|
| 585 |             //bUniCodeFont = TRUE;
 | 
|---|
| 586 |         }
 | 
|---|
| 587 |         else if (pset->GetLangID() == CZ || pset->GetLangID() == PL) {
 | 
|---|
| 588 |             hmq = WinQueryWindowULong( hwnd, QWL_HMQ);
 | 
|---|
| 589 |             WinSetCp(hmq, 852);
 | 
|---|
| 590 |             //bUniCodeFont = TRUE;
 | 
|---|
| 591 |         }
 | 
|---|
| 592 |         else {
 | 
|---|
| 593 |             hmq = WinQueryWindowULong( hwnd, QWL_HMQ);
 | 
|---|
| 594 |             WinSetCp(hmq, 850);
 | 
|---|
| 595 |         }
 | 
|---|
| 596 | 
 | 
|---|
| 597 |         if (bUniCodeFont) {
 | 
|---|
| 598 |             strcpy(ucFont, "9.Times New Roman MT 30");
 | 
|---|
| 599 |             WinSetPresParam(hwnd, PP_FONTNAMESIZE, strlen(ucFont) + 1, ucFont);
 | 
|---|
| 600 |         }
 | 
|---|
| 601 |         else if (g_installer) {
 | 
|---|
| 602 |             strcpy(ucFont, "9.WarpSans");
 | 
|---|
| 603 |             WinSetPresParam(hwnd, PP_FONTNAMESIZE, strlen(ucFont) + 1, ucFont);
 | 
|---|
| 604 |         }
 | 
|---|
| 605 |         WinSendDlgItemMsg (hwnd, WID_CB_AUTOADDEXTENSION, BM_SETCHECK,
 | 
|---|
| 606 |                            MPFROMLONG (pset->AutoaddExtension ()),
 | 
|---|
| 607 |                            MPFROMLONG (0));
 | 
|---|
| 608 |         WinSendDlgItemMsg (hwnd, WID_CB_CONFIRMOVERWRITE, BM_SETCHECK,
 | 
|---|
| 609 |                            MPFROMLONG (pset->ConfirmOverwrite ()),
 | 
|---|
| 610 |                            MPFROMLONG (0));
 | 
|---|
| 611 | /* FIXME neither work ...       WinSendDlgItemMsg (hwnd, DID_FILES_LB, WM_ENABLE,
 | 
|---|
| 612 |                            MPFROMLONG (TRUE),
 | 
|---|
| 613 |                            MPFROMLONG (0));
 | 
|---|
| 614 |         //WinEnableWindow( WinWindowFromID( hwnd, DID_FILES_LB ), TRUE ); */
 | 
|---|
| 615 |         break;
 | 
|---|
| 616 | 
 | 
|---|
| 617 | #ifdef _DOFNCOMPLETION_
 | 
|---|
| 618 |     case WM_CHAR: {
 | 
|---|
| 619 |         HWND hwndFNE = WinWindowFromID (hwnd, DID_FILENAME_ED);
 | 
|---|
| 620 |         if (WinQueryFocus (HWND_DESKTOP) == hwndFNE)
 | 
|---|
| 621 |         {
 | 
|---|
| 622 |             // tab key, downpress
 | 
|---|
| 623 |             if ((CHARMSG (&msg)->chr == 9) && !
 | 
|---|
| 624 |                 (CHARMSG (&msg)->fs & KC_KEYUP))
 | 
|---|
| 625 |             {
 | 
|---|
| 626 |                 ULONG         c = 1, fl;
 | 
|---|
| 627 |                 FILEFINDBUF3  findbuf;
 | 
|---|
| 628 |                 APIRET        rc;
 | 
|---|
| 629 |                 CHAR          ach[_MAX_PATH];
 | 
|---|
| 630 | 
 | 
|---|
| 631 |                 if (! hdir)
 | 
|---|
| 632 |                 {
 | 
|---|
| 633 |                     WinQueryWindowText (hwndFNE, _MAX_PATH-1, ach);
 | 
|---|
| 634 |                     strcat (ach, "*");
 | 
|---|
| 635 |                     fl   = FILE_NORMAL;
 | 
|---|
| 636 |                     hdir = HDIR_CREATE;
 | 
|---|
| 637 |                     rc = DosFindFirst (ach, &hdir, fl, &findbuf,
 | 
|---|
| 638 |                                        sizeof (findbuf), &c,
 | 
|---|
| 639 |                                        FIL_STANDARD);
 | 
|---|
| 640 |                 }
 | 
|---|
| 641 |                 else
 | 
|---|
| 642 |                 {
 | 
|---|
| 643 |                     rc = DosFindNext (hdir, &findbuf,
 | 
|---|
| 644 |                                       sizeof (findbuf), &c);
 | 
|---|
| 645 |                 }
 | 
|---|
| 646 | 
 | 
|---|
| 647 |                 if (! rc)
 | 
|---|
| 648 |                 {
 | 
|---|
| 649 |                     fCompletion = TRUE;
 | 
|---|
| 650 |                     WinSetWindowText (hwndFNE, findbuf.achName);
 | 
|---|
| 651 |                     fCompletion = FALSE;
 | 
|---|
| 652 |                 }
 | 
|---|
| 653 |                 else
 | 
|---|
| 654 |                     DosBeep (1000, 10);
 | 
|---|
| 655 |                 return MRESULT (FALSE);
 | 
|---|
| 656 |             }
 | 
|---|
| 657 |         } } break;
 | 
|---|
| 658 | 
 | 
|---|
| 659 |     case WM_CONTROL:
 | 
|---|
| 660 |         switch (SHORT1FROMMP (mp1))
 | 
|---|
| 661 |         {
 | 
|---|
| 662 |         case DID_FILENAME_ED:
 | 
|---|
| 663 |             if ((SHORT2FROMMP (mp1) == EN_CHANGE) ||
 | 
|---|
| 664 |                 (SHORT2FROMMP (mp1) == EN_KILLFOCUS))
 | 
|---|
| 665 |                 if (hdir && !fCompletion)
 | 
|---|
| 666 |                 {
 | 
|---|
| 667 |                     // FIXME maybe do this to when closing dialog?
 | 
|---|
| 668 |                     DosFindClose (hdir);
 | 
|---|
| 669 |                     hdir = NULLHANDLE;
 | 
|---|
| 670 |                 }
 | 
|---|
| 671 |             break;
 | 
|---|
| 672 |         }
 | 
|---|
| 673 |         break;
 | 
|---|
| 674 | #endif
 | 
|---|
| 675 | 
 | 
|---|
| 676 |     case WM_COMMAND:
 | 
|---|
| 677 |     case WM_CLOSE:
 | 
|---|
| 678 |         pset->AutoaddExtension
 | 
|---|
| 679 |             (BOOL (WinSendDlgItemMsg (hwnd, WID_CB_AUTOADDEXTENSION,
 | 
|---|
| 680 |                                       BM_QUERYCHECK, 0, 0)));
 | 
|---|
| 681 |         pset->ConfirmOverwrite
 | 
|---|
| 682 |             (BOOL (WinSendDlgItemMsg (hwnd, WID_CB_CONFIRMOVERWRITE,
 | 
|---|
| 683 |                                       BM_QUERYCHECK, 0, 0)));
 | 
|---|
| 684 |         break;
 | 
|---|
| 685 |     }
 | 
|---|
| 686 | 
 | 
|---|
| 687 |     return WinDefFileDlgProc (hwnd, msg, mp1, mp2);
 | 
|---|
| 688 | }
 | 
|---|
| 689 | 
 | 
|---|
| 690 | // ** AddExtensionToFilename ********************************************** /*FOLD00*/
 | 
|---|
| 691 | 
 | 
|---|
| 692 | PSZ AddExtensionToFilename( PSZ psz )
 | 
|---|
| 693 | {
 | 
|---|
| 694 |     // Using a static buffer here is not really good, but good enough
 | 
|---|
| 695 |     // currently as we know there will be no concurrent access.
 | 
|---|
| 696 |     static CHAR ach[_MAX_PATH];
 | 
|---|
| 697 |     PSZ pszExtension;
 | 
|---|
| 698 | 
 | 
|---|
| 699 |     PSZ apszValidExtensions[16] =
 | 
|---|
| 700 |     { "bmp", "tif", "tiff", "tga", "targa", "pcx", "pnm", "jpg", "jpeg",
 | 
|---|
| 701 |     "jpg2", "jbg", "jbig", "png", "ppm", "raw", "dib" };
 | 
|---|
| 702 | 
 | 
|---|
| 703 |     if( ! ( pszExtension = strrchr( psz, '.' ) ) ) {
 | 
|---|
| 704 |         // No extension at all - add the appropriate one.
 | 
|---|
| 705 |         sprintf( ach, "%s.%s", psz, pset->GetFileExtension() );
 | 
|---|
| 706 |     } else if( stricmp ( pszExtension+1, pset->GetFileExtension() ) == 0 ) {
 | 
|---|
| 707 |         // Correct extension already - just return unchanged filename.
 | 
|---|
| 708 |         strcpy( ach, psz );
 | 
|---|
| 709 |     } else {
 | 
|---|
| 710 |         // Some extension, but not the correct one - change or append.
 | 
|---|
| 711 |         BOOL fValidExtension = FALSE;
 | 
|---|
| 712 |         for( int i = 0; i < 16; i++ ) {
 | 
|---|
| 713 |             if( stricmp( pszExtension+1, apszValidExtensions[i] ) == 0 ) {
 | 
|---|
| 714 |                 fValidExtension = TRUE;
 | 
|---|
| 715 |                 break;
 | 
|---|
| 716 |             }
 | 
|---|
| 717 |         }
 | 
|---|
| 718 |         if( fValidExtension ) {
 | 
|---|
| 719 |             // Valid extension, but not right for current format - replace.
 | 
|---|
| 720 |             *pszExtension = '\0';
 | 
|---|
| 721 |             sprintf( ach, "%s.%s", psz, pset->GetFileExtension() );
 | 
|---|
| 722 |         } else {
 | 
|---|
| 723 |             // Some extension but not a valid image file format extension - add.
 | 
|---|
| 724 |             sprintf( ach, "%s.%s", psz, pset->GetFileExtension() );
 | 
|---|
| 725 |         }
 | 
|---|
| 726 |     }
 | 
|---|
| 727 |     return ach;
 | 
|---|
| 728 | }
 | 
|---|
| 729 | 
 | 
|---|
| 730 | // ************************************************************************
 | 
|---|