Annotation of mstools/samples/sdktools/aniedit/anifile.c, revision 1.1.1.1

1.1       root        1: /****************************************************************************\
                      2: *
                      3: *     MODULE: anifile.c
                      4: *
                      5: *     PURPOSE: Processes files for the Animated Cursor Editor
                      6: *
                      7: *     Copyright 1993, Microsoft Corp.
                      8: *
                      9: *
                     10: * History:
                     11: *   21-Apr-1993 JonPa   Wrote it.
                     12: *
                     13: \****************************************************************************/
                     14: 
                     15: #include <windows.h>
                     16: #include <commdlg.h>
                     17: #include "anidefs.h"
                     18: 
                     19: /****************************************************************************\
                     20: *
                     21: *     FUNCTION: BOOL CreateFrameFromCursorFile( LPSTR pszFile )
                     22: *
                     23: *     PURPOSE:  Opens a cursor file, reads the icon info out of it,
                     24: *               and creates a frame and step for that icon, then links
                     25: *               everything together and updates the listbox.
                     26: *
                     27: *     NOTES:    This function accesses the global flag gfEditFrame.
                     28: *               If this bool is TRUE, then the currently selected frame
                     29: *               in the listbox is overwritten.  If it is false, then
                     30: *               a new frame is created and inserted after the currently
                     31: *               selected frame (or at the end if no selection).
                     32: *
                     33: * History:
                     34: *   21-Apr-1993 JonPa   Created it
                     35: *
                     36: \****************************************************************************/
                     37: BOOL CreateFrameFromCursorFile(HWND hwnd,  LPTSTR pszFile, BOOL fEdit) {
                     38:     PFRAME pf;
                     39:     HANDLE hf;
                     40:     PSTEP psOld, psNew;
                     41:     DWORD ckSize;
                     42:     int iSel;
                     43:     int cSel;
                     44: 
                     45:     cSel = GetSelStepCount(hwnd);
                     46: 
                     47:     if ( (fEdit && (cSel != 1)) || cSel > 1) {
                     48:         FmtMessageBox( hwnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP,
                     49:                 TRUE, fEdit ? MSG_MUSTEQONEFAME : MSG_LESSEQONEFRAME);
                     50:         return FALSE;
                     51:     }
                     52: 
                     53:     /* get currently selected frame */
                     54:     GetCurrentSel(hwnd, DLG_MAIN_FRAMELIST, &iSel, 1, &cSel );
                     55: 
                     56:     if (cSel == 0)
                     57:         psOld = NULL;
                     58:     else
                     59:         psOld = GetStep(hwnd, iSel);
                     60: 
                     61:     /*
                     62:      * If not editing, create a new step
                     63:      */
                     64:     if (!fEdit || !IsValidPS(psOld)) {
                     65:         psNew = NewStep();
                     66: 
                     67:         if (psNew == NULL) {
                     68:             return FALSE;
                     69:         }
                     70:     } else {
                     71:         psNew = NULL;
                     72:     }
                     73: 
                     74:     hf = CreateFile(pszFile, GENERIC_READ,
                     75:              0, NULL,
                     76:              OPEN_EXISTING,
                     77:              FILE_ATTRIBUTE_NORMAL,
                     78:              NULL);
                     79: 
                     80:     if (hf == INVALID_HANDLE_VALUE)
                     81:         return FALSE;
                     82: 
                     83:     ckSize = GetFileSize(hf, NULL);
                     84: 
                     85:     /* get the frame out of the file */
                     86:     pf = ReadIconFromFile(hwnd, hf, ckSize);
                     87:     CloseHandle(hf);
                     88: 
                     89:     if (pf == NULL) {
                     90:         if (psNew != NULL)
                     91:             FreeMem(psNew);
                     92:         return FALSE;
                     93:     }
                     94: 
                     95:     if (psNew != NULL) {
                     96: 
                     97:         if (IsValidPS(psOld)) {
                     98:             psNew->jif = psOld->jif;
                     99:             iSel += 1;
                    100:         } else {
                    101:             psNew->jif = ganiAcon.anih.jifRate;
                    102:             iSel = SendDlgItemMessage(hwnd, DLG_MAIN_FRAMELIST, LB_GETCOUNT,
                    103:                     0, 0);
                    104:         }
                    105: 
                    106:         LinkStepFrame(psNew, pf);
                    107: 
                    108:         SendDlgItemMessage(hwnd, DLG_MAIN_FRAMELIST, LB_INSERTSTRING, iSel,
                    109:             (LPARAM)psNew);
                    110: 
                    111:         SetCurrentSel(hwnd, DLG_MAIN_FRAMELIST, FALSE, iSel);
                    112: 
                    113:     } else {
                    114:         HWND hwndLB = GetDlgItem(hwnd, DLG_MAIN_FRAMELIST);
                    115: 
                    116:         /*
                    117:          * Delete the old frame and point the step to the new one.
                    118:          */
                    119:         LinkStepFrame(psOld, pf);
                    120: 
                    121:         InvalidateRect(hwndLB, NULL, TRUE);
                    122:     }
                    123: 
                    124:     return TRUE;
                    125: }
                    126: 
                    127: 
                    128: /****************************************************************************\
                    129: *
                    130: *     FUNCTION: HICON ConvertDataToIcon( PFRAME pf )
                    131: *
                    132: *     PURPOSE:
                    133: *
                    134: *
                    135: *
                    136: *
                    137: * History:
                    138: *   23-Apr-1993 JonPa   copied from Win NT USERs ReadIconGuts
                    139: *
                    140: \****************************************************************************/
                    141: HICON ConvertDataToIcon( PFRAME pf, WORD *pxHotSave, WORD *pyHotSave )
                    142: {
                    143:     NEWHEADER *pnh;
                    144:     NEWHEADER *pnhBase;
                    145:     RESDIR *prd;
                    146:     int offMatch;
                    147:     ICONFILERESDIR *pird;
                    148:     PCURSORRESOURCE pcres;
                    149:     BOOL fIcon;
                    150:     HICON hicon;
                    151:     WORD x, y;
                    152: 
                    153:     pnhBase = (NEWHEADER *)pf->abIcon;
                    154: 
                    155:     /*
                    156:      * Construct a fake array of RESDIR entries using the info at the head
                    157:      * of the file.  Store the data offset in the idIcon WORD so it can be
                    158:      * returned by RtlGetIdFromDirectory.
                    159:      */
                    160:     pnh = (NEWHEADER *)LocalAlloc(LMEM_FIXED, sizeof(NEWHEADER) +
                    161:             (pnhBase->cResources * sizeof(RESDIR)));
                    162:     if (pnh == NULL)
                    163:         return NULL;
                    164: 
                    165:     *pnh = *pnhBase;
                    166:     prd = (RESDIR *)(pnh + 1);
                    167:     pird = (ICONFILERESDIR *)(pnhBase + 1);
                    168: 
                    169:     /* prime pird for first line of loop */
                    170:     pird--;
                    171: 
                    172:     for (offMatch = 0; offMatch < (int)pnh->cResources; offMatch++, prd++) {
                    173: 
                    174:         /*
                    175:          * Get the next resource directory from the icon file.
                    176:          */
                    177: 
                    178:         ++pird;
                    179: 
                    180:         /*
                    181:          * Convert from the icon editor's resource directory format
                    182:          * to the post-RC.EXE format LookupIconIdFromDirectory expects.
                    183:          */
                    184:         if (pnh->rt == 1) {     // ICON
                    185:             prd->ResInfo.Icon.Width = pird->bWidth;
                    186:             prd->ResInfo.Icon.Height = pird->bHeight;
                    187:             prd->ResInfo.Icon.ColorCount = pird->bColorCount;
                    188:             prd->ResInfo.Icon.reserved = 0;
                    189:         } else {                // CURSOR
                    190:             prd->ResInfo.Cursor.Width = pird->bWidth;
                    191:             prd->ResInfo.Cursor.Height = pird->bHeight;
                    192:         }
                    193:         prd->Planes = 0;                // Hopefully nobody uses this
                    194:         prd->BitCount = 0;              //        "        "
                    195:         prd->BytesInRes = pird->dwDIBSize;
                    196:         prd->idIcon = (WORD)pird->dwDIBOffset;
                    197:     }
                    198: 
                    199:     /*
                    200:      * NOTE: nh.rt is NOT an RT_ type value.  For instance, nh.rt == 1 for
                    201:      * an icon file where as 1 == RT_CURSOR, not RT_ICON.
                    202:      */
                    203: 
                    204:     fIcon = (pnhBase->rt == 1);
                    205:     offMatch = LookupIconIdFromDirectory((PBYTE)pnh, fIcon);
                    206: 
                    207:     LocalFree(pnh);
                    208: 
                    209:     if (fIcon) {
                    210:         pcres = (PCURSORRESOURCE)&(pf->abIcon[offMatch]);
                    211:         *pxHotSave = gcxCursor / 2;
                    212:         *pyHotSave = gcyCursor / 2;
                    213:     } else {
                    214: 
                    215:         offMatch -= (sizeof(pcres->xHotspot) + sizeof(pcres->yHotspot));
                    216: 
                    217:         for(; pird->dwDIBOffset != (WORD)offMatch &&
                    218:                 pird != (ICONFILERESDIR *)(pnhBase + 1); pird--);
                    219: 
                    220:         pcres = (PCURSORRESOURCE)&(pf->abIcon[offMatch]);
                    221: 
                    222:         x = pcres->xHotspot;
                    223:         y = pcres->yHotspot;
                    224:         *pxHotSave = pcres->xHotspot = pird->xHotspot;
                    225:         *pyHotSave = pcres->yHotspot = pird->yHotspot;
                    226:     }
                    227: 
                    228:     hicon = CreateIconFromResource( (PBYTE)pcres,
                    229:             pf->rtag.ckSize - offMatch, fIcon, 0x00030000);
                    230: 
                    231:     if(!fIcon) {
                    232:         pcres->xHotspot = x;
                    233:         pcres->yHotspot = y;
                    234:     }
                    235: 
                    236:     return hicon;
                    237: }
                    238: 
                    239: 
                    240: 
                    241: 
                    242: /****************************************************************************\
                    243: *
                    244: *     FUNCTION: PFRAME ReadIconFromFile(HWND hwnd, HANDLE hf, DWORD ckSize)
                    245: *
                    246: *     PURPOSE:  Reads the icon info out of a file,
                    247: *               and creates a frame for that icon.
                    248: *
                    249: *
                    250: * History:
                    251: *   22-Apr-1993 JonPa   Created it
                    252: *
                    253: \****************************************************************************/
                    254: PFRAME ReadIconFromFile(HWND hwnd, HANDLE hf, DWORD ckSize) {
                    255:     PFRAME pf = AllocMem( sizeof( FRAME ) + ckSize );
                    256:     DWORD cbRead;
                    257:     PFRAME pfList;
                    258: 
                    259:     if (pf != NULL) {
                    260:         pf->cRef = 0;
                    261: 
                    262:         if (ReadFile(hf, pf->abIcon, ckSize, &cbRead, NULL) &&
                    263:                 cbRead == ckSize) {
                    264:             /* got the data, now set up the rest of the frame and link it in */
                    265:             pf->dwCheckSum = CalcCheckSum( pf->abIcon, ckSize );
                    266:             pf->rtag.ckID = FOURCC_icon;
                    267:             pf->rtag.ckSize = ckSize;
                    268: 
                    269:             /* Check if this fram is already in the list */
                    270:             for (pfList = gpfrmFrames; pfList != NULL;
                    271:                     pfList = pfList->pfrmNext ) {
                    272:                 if (pf->dwCheckSum == pfList->dwCheckSum &&
                    273:                         pf->rtag.ckSize == pfList->rtag.ckSize &&
                    274:                         memcmp( pf->abIcon, pfList->abIcon, ckSize ) == 0) {
                    275:                     /*
                    276:                      * These frames are the same, coalesce them into a
                    277:                      * sequence.
                    278:                      */
                    279:                     FreeMem(pf);
                    280:                     pf = pfList;
                    281:                     break;
                    282:                 }
                    283:             }
                    284: 
                    285:             if (pfList == NULL) {
                    286:                 /*
                    287:                  * Did not find a dup, create an icon for this frame
                    288:                  */
                    289:                 pf->hcur = ConvertDataToIcon( pf, &(pf->xHotSpot),
                    290:                         &(pf->yHotSpot) );
                    291: 
                    292:                 pf->pfrmNext = gpfrmFrames;
                    293:                 gpfrmFrames = pf;
                    294:             }
                    295: 
                    296:         } else {
                    297:             /* File Error */
                    298:             FreeMem(pf);
                    299:             pf = NULL;
                    300:         }
                    301: 
                    302:     }
                    303: 
                    304:     return pf;
                    305: }
                    306: 
                    307: /****************************************************************************\
                    308: *
                    309: *     FUNCTION: HANDLE PromptAndOpenFile( )
                    310: *
                    311: *     PURPOSE:  Pust up the standard open dialog and then opens the file
                    312: *
                    313: *
                    314: *
                    315: *
                    316: * History:
                    317: *   21-Apr-1993 JonPa   Created it
                    318: *
                    319: \****************************************************************************/
                    320: HANDLE PromptAndOpenFile(
                    321:     HWND hwnd,
                    322:     DWORD  cchFileTitle,
                    323:     LPTSTR pszFileTitle,
                    324:     DWORD  cchFileName,
                    325:     LPTSTR pszFileName,
                    326:     LPTSTR pszFilter
                    327:     )
                    328: {
                    329:     HANDLE hf = INVALID_HANDLE_VALUE;
                    330: 
                    331:     if (PromptForFile( hwnd, cchFileTitle, pszFileTitle, cchFileName,
                    332:                 pszFileName, pszFilter, NULL, FALSE )) {
                    333: 
                    334:         /* Open the file. */
                    335: 
                    336:         hf = CreateFile(pszFileName, GENERIC_READ,
                    337:                 0, NULL,
                    338:                 OPEN_EXISTING,
                    339:                 FILE_ATTRIBUTE_NORMAL,
                    340:                 NULL);
                    341: 
                    342:         if (hf == INVALID_HANDLE_VALUE) {
                    343:             FmtMessageBox( hwnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE,
                    344:                 MSG_CANTOPENFILE, pszFileName );
                    345:         }
                    346:     }
                    347: 
                    348:     return hf;
                    349: }
                    350: 
                    351: 
                    352: /****************************************************************************\
                    353: *
                    354: *     FUNCTION: HANDLE PromptForFile( )
                    355: *
                    356: *     PURPOSE:  Pust up the standard open dialog
                    357: *
                    358: *
                    359: *
                    360: *
                    361: * History:
                    362: *   28-Apr-1993 JonPa   Created it from PromptAndOpenFile
                    363: *
                    364: \****************************************************************************/
                    365: BOOL PromptForFile(
                    366:     HWND hwnd,
                    367:     DWORD  cchFileTitle,
                    368:     LPTSTR pszFileTitle,
                    369:     DWORD  cchFileName,
                    370:     LPTSTR pszFile,
                    371:     LPTSTR pszFilter,
                    372:     LPTSTR pszDlgTitle,
                    373:     BOOL fSave
                    374:     )
                    375: {
                    376:     OPENFILENAME ofn;
                    377: 
                    378:     ZeroMemory(&ofn, sizeof(ofn));
                    379: 
                    380:     /* Set the members of the OPENFILENAME structure. */
                    381: 
                    382:     ofn.lStructSize = sizeof(OPENFILENAME);
                    383:     ofn.hwndOwner = hwnd;
                    384: 
                    385:     ofn.lpstrFilter = pszFilter;
                    386:     ofn.nFilterIndex = 0;
                    387: 
                    388:     ofn.lpstrFile = pszFile;
                    389:     ofn.nMaxFile = cchFileName;
                    390: 
                    391:     ofn.lpstrFileTitle = pszFileTitle;
                    392:     ofn.nMaxFileTitle = cchFileTitle;
                    393: 
                    394:     ofn.lpstrTitle = pszDlgTitle;
                    395: 
                    396:     ofn.lpstrDefExt = gpszANI;
                    397: 
                    398:     if (fSave) {
                    399:         ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
                    400:     } else {
                    401:         ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
                    402:     }
                    403: 
                    404:     /* Display the SaveAs or Open dialog box. */
                    405: 
                    406:     return fSave ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn);
                    407: 
                    408: }
                    409: 
                    410: /****************************************************************************\
                    411: *
                    412: *     FUNCTION: BOOL ReadAniFile( HWND hwnd, HANDLE hf ) {
                    413: *
                    414: *     PURPOSE:
                    415: &
                    416: *   Loads an animatied cursor from a RIFF file.  The RIFF file format for
                    417: *   animated cursors looks like this:
                    418: *
                    419: *   RIFF( 'ACON'
                    420: *       LIST( 'INFO'
                    421: *           INAM( <name> )
                    422: *           IART( <artist> )
                    423: *       )
                    424: *       anih( <anihdr> )
                    425: *       [rate( <rateinfo> )  ]
                    426: *       ['seq '( <seq_info> )]
                    427: *       LIST( 'fram' icon( <icon_file> ) )
                    428: *   )
                    429: *
                    430: *
                    431: * History:
                    432: *   02-Oct-1991 DarrinM     Created. (in Win32 user)
                    433: *   17-Mar-1993 JonPa       Rewrote to use RIFF format instead of RAD
                    434: *   21-Apr-1993 JonPa       Copied it to anifile.c and tweeked it.
                    435: *
                    436: \****************************************************************************/
                    437: BOOL ReadAniFile( HWND hwnd, HANDLE hf ) {
                    438: 
                    439:     RTAG tag;
                    440:     DWORD cbRead;
                    441:     BOOL fSuccess = FALSE;
                    442:     JIF *pjifRate = NULL;
                    443:     DWORD *pseq = NULL;
                    444:     PFRAME *ppfram = NULL;
                    445:     int iFrame = 0;
                    446:     int i;
                    447: 
                    448:     if (!ReadTag(hf, &tag))
                    449:         return FALSE;
                    450: 
                    451:     /*
                    452:      * Make sure it's a RIFF ANI file
                    453:      */
                    454:     if (tag.ckID != FOURCC_RIFF)
                    455:         goto laiFileErr;
                    456: 
                    457:     /* read the chunk type */
                    458:     if(!ReadFile(hf, &tag.ckID, sizeof(tag.ckID), &cbRead, NULL) ||
                    459:             cbRead < sizeof(tag.ckID)) {
                    460:         goto laiFileErr;
                    461:     }
                    462: 
                    463:     if (tag.ckID != FOURCC_ACON)
                    464:         goto laiFileErr;
                    465: 
                    466:     /* look for 'anih', 'rate', 'seq ', and 'icon' chunks */
                    467:     while( ReadTag(hf, &tag)) {
                    468: 
                    469:         switch( tag.ckID ) {
                    470:         case FOURCC_anih:
                    471:             if (!ReadChunk(hf, &tag, &ganiAcon.anih))
                    472:                 goto laiFileErr;
                    473: 
                    474:             if (!(ganiAcon.anih.fl & AF_ICON) || (ganiAcon.anih.cFrames == 0))
                    475:                 goto laiFileErr;
                    476: 
                    477:             /*
                    478:              * Allocate space for the ANIHEADER, and a seq and
                    479:              * rate table (in case we run into one later).
                    480:              */
                    481: 
                    482:             pjifRate = AllocMem( ganiAcon.anih.cSteps * sizeof(JIF) +
                    483:                     ganiAcon.anih.cSteps * sizeof(DWORD) +
                    484:                     ganiAcon.anih.cSteps * sizeof(PFRAME));
                    485: 
                    486: 
                    487:             if (pjifRate == NULL)
                    488:                 goto laiFileErr;
                    489: 
                    490:             pseq = (DWORD *)(pjifRate + ganiAcon.anih.cSteps);
                    491:             ppfram = (PFRAME *)(pseq + ganiAcon.anih.cSteps);
                    492: 
                    493:             for( i = 0; i < (int)ganiAcon.anih.cSteps; i++ ) {
                    494:                 pjifRate[i] = ganiAcon.anih.jifRate;
                    495:                 pseq[i] = i;
                    496:                 ppfram[i] = NULL;
                    497:             }
                    498:             break;
                    499: 
                    500: 
                    501:         case FOURCC_rate:
                    502:             /*
                    503:              * If we find a rate chunk, read it into its preallocated
                    504:              * space.
                    505:              */
                    506:             if(!ReadChunk(hf, &tag, (PBYTE)pjifRate))
                    507:                 goto laiFileErr;
                    508:             break;
                    509: 
                    510: 
                    511:         case FOURCC_seq:
                    512:             /*
                    513:              * If we find a seq chunk, read it into its preallocated
                    514:              * space.
                    515:              */
                    516:             if(!ReadChunk(hf, &tag, (PBYTE)pseq))
                    517:                 goto laiFileErr;
                    518:             break;
                    519: 
                    520: 
                    521:         case FOURCC_LIST: {
                    522:             DWORD cbChunk = PADUP(tag.ckSize);
                    523: 
                    524:             /*
                    525:              * See if this list is the 'fram' list of icon chunks
                    526:              */
                    527:             if(!ReadFile(hf, &tag.ckID, sizeof(tag.ckID), &cbRead, NULL) ||
                    528:                     cbRead < sizeof(tag.ckID)) {
                    529:                 goto laiFileErr;
                    530:             }
                    531: 
                    532:             cbChunk -= cbRead;
                    533: 
                    534:             if (tag.ckID == FOURCC_fram) {
                    535: 
                    536:                 while(cbChunk >= sizeof(tag)) {
                    537:                     if (!ReadTag(hf, &tag))
                    538:                         goto laiFileErr;
                    539: 
                    540:                     cbChunk -= sizeof(tag);
                    541: 
                    542:                     if(tag.ckID == FOURCC_icon) {
                    543:                         PFRAME pfrm;
                    544: 
                    545:                         /*
                    546:                          * Ok, load the icon/cursor bits,
                    547:                          */
                    548:                         pfrm = ReadIconFromFile(hwnd, hf, tag.ckSize);
                    549: 
                    550:                         if (pfrm == NULL) {
                    551:                             goto laiFileErr;
                    552:                         }
                    553: 
                    554:                         for( i = 0; i < (int)ganiAcon.anih.cSteps; i++ ) {
                    555:                             if (pseq[i] == (DWORD)iFrame) {
                    556:                                 ppfram[i] = pfrm;
                    557:                             }
                    558:                         }
                    559: 
                    560:                         iFrame++;
                    561: 
                    562:                     } else {
                    563:                         /*
                    564:                          * Unknown chunk in fram list, just ignore it
                    565:                          */
                    566:                         SkipChunk(hf, &tag);
                    567:                     }
                    568: 
                    569:                     cbChunk -= PADUP(tag.ckSize);
                    570:                 }
                    571:             } else if (tag.ckID == FOURCC_INFO) {
                    572:                 /* now look for INAM and IART chunks */
                    573: 
                    574:                 while( cbChunk >= sizeof(tag) ) {
                    575: 
                    576:                     if (!ReadTag(hf, &tag))
                    577:                         goto laiFileErr;
                    578: 
                    579:                     cbChunk -= sizeof(tag);
                    580: 
                    581:                     switch( tag.ckID ) {
                    582:                     case FOURCC_INAM:
                    583:                         if (cbChunk < tag.ckSize ||
                    584:                                 !ReadChunkN(hf, &tag, ganiAcon.azTitle,
                    585:                                                 sizeof(ganiAcon.azTitle)))
                    586:                             goto laiFileErr;
                    587: 
                    588:                         cbChunk -= PADUP(tag.ckSize);
                    589:                         break;
                    590: 
                    591:                     case FOURCC_IART:
                    592:                         if (cbChunk < tag.ckSize ||
                    593:                                 !ReadChunkN(hf, &tag, ganiAcon.azCreator,
                    594:                                         sizeof(ganiAcon.azCreator)))
                    595:                             goto laiFileErr;
                    596: 
                    597:                         cbChunk -= PADUP(tag.ckSize);
                    598:                         break;
                    599: 
                    600:                     default:
                    601:                         if (!SkipChunk( hf, &tag ))
                    602:                             goto laiFileErr;
                    603: 
                    604:                         cbChunk -= PADUP(tag.ckSize);
                    605:                         break;
                    606:                     }
                    607:                 }
                    608: 
                    609:             } else {
                    610:                 /*
                    611:                  * Not the fram list or the INFO list.  Skip
                    612:                  * the rest of this chunk.  (Don't forget that we have
                    613:                  * already skipped one dword!)
                    614:                  */
                    615:                 tag.ckSize = cbChunk;
                    616:                 SkipChunk(hf, &tag);
                    617:                 break;
                    618:             }
                    619: 
                    620:             break;
                    621:         }
                    622: 
                    623: 
                    624: 
                    625:         default:
                    626:             /*
                    627:              * We're not interested in this chunk, skip it.
                    628:              */
                    629:             if(!SkipChunk(hf, &tag))
                    630:                 goto laiFileErr;
                    631:             break;
                    632: 
                    633:         }
                    634: 
                    635:     }
                    636: 
                    637:     /*
                    638:      * Update the frame count incase we coalesced some frames while reading
                    639:      * in the file.
                    640:      */
                    641:     ganiAcon.anih.cFrames = iFrame;
                    642: 
                    643:     /*
                    644:      * Now build up the listbox
                    645:      */
                    646: 
                    647:     for( i = 0; i < (int)ganiAcon.anih.cSteps; i++ ) {
                    648:         PSTEP ps;
                    649: 
                    650:         ps = NewStep();
                    651:         if (ps == NULL)
                    652:             goto laiFileErr;
                    653: 
                    654:         ps->jif = pjifRate[i];
                    655:         LinkStepFrame(ps, ppfram[i]);
                    656: 
                    657:         SendDlgItemMessage(hwnd, DLG_MAIN_FRAMELIST, LB_INSERTSTRING, i,
                    658:                 (LPARAM)ps);
                    659:     }
                    660: 
                    661:     SetDlgItemText(hwnd, DLG_MAIN_TITLE, ganiAcon.azTitle);
                    662:     SetDlgItemText(hwnd, DLG_MAIN_AUTHOR, ganiAcon.azCreator);
                    663: 
                    664:     SendDlgItemMessage(hwnd, DLG_MAIN_PREVIEW, PM_NEWCURSOR, 0, 0);
                    665:     fSuccess = TRUE;
                    666: 
                    667: laiFileErr:
                    668: 
                    669:     if (pjifRate != NULL)
                    670:         FreeMem(pjifRate);
                    671: 
                    672:     if (!fSuccess)
                    673:         NewAniCursor(hwnd);
                    674: 
                    675:     CloseHandle(hf);
                    676: 
                    677:     return fSuccess;
                    678: }
                    679: 
                    680: 
                    681: 
                    682: /***************************************************************************\
                    683: * DWORD CalcCheckSum( PBYTE pb );
                    684: *
                    685: *
                    686: * History:
                    687: *
                    688: * 23-Apr-1993 JonPa     Created.
                    689: \***************************************************************************/
                    690: DWORD CalcCheckSum( PBYTE pb, DWORD cb ) {
                    691:     DWORD dw = 0;
                    692: 
                    693:     while(cb--)
                    694:         dw += (DWORD)*pb++;
                    695: 
                    696:     return dw;
                    697: }
                    698: 
                    699: /***************************************************************************\
                    700: * ReadTag, ReadChunk, SkipChunk
                    701: *
                    702: * Some handy functions for reading RIFF files.
                    703: *
                    704: * History:
                    705: * 10-02-91 DarrinM      Created.
                    706: * 03-25-93 Jonpa        Changed to use RIFF format instead of ASDF
                    707: * 23-Apr-1993 JonPa     Copied from Win NT USER.
                    708: \***************************************************************************/
                    709: BOOL ReadTag(
                    710:     HANDLE hf,
                    711:     PRTAG ptag)
                    712: {
                    713:     DWORD cbActual;
                    714: 
                    715:     ptag->ckID = ptag->ckSize = 0L;
                    716: 
                    717:     if (!ReadFile(hf, ptag, sizeof(RTAG), &cbActual, NULL) ||
                    718:             (cbActual != sizeof(RTAG)))
                    719:         return FALSE;
                    720: 
                    721:     /* no need to align file pointer since RTAG is already word aligned */
                    722:     return TRUE;
                    723: }
                    724: 
                    725: 
                    726: BOOL ReadChunk(
                    727:     HANDLE hf,
                    728:     PRTAG ptag,
                    729:     PVOID pv)
                    730: {
                    731:     DWORD cbActual;
                    732: 
                    733:     if (!ReadFile(hf, pv, ptag->ckSize, &cbActual, NULL) ||
                    734:             (cbActual != ptag->ckSize))
                    735:         return FALSE;
                    736: 
                    737:     /* WORD align file pointer */
                    738:     if( ptag->ckSize & 1 )
                    739:         SetFilePointer(hf, 1, NULL, FILE_CURRENT);
                    740: 
                    741:     return TRUE;
                    742: }
                    743: 
                    744: 
                    745: BOOL ReadChunkN(
                    746:     HANDLE hf,
                    747:     PRTAG ptag,
                    748:     PVOID pv,
                    749:     DWORD cbMax)
                    750: {
                    751:     DWORD cbActual;
                    752:     DWORD cbRead = min( cbMax, ptag->ckSize );
                    753: 
                    754:     if (!ReadFile(hf, pv, ptag->ckSize, &cbActual, NULL) ||
                    755:             (cbActual != cbRead))
                    756:         return FALSE;
                    757: 
                    758:     /* WORD align file pointer */
                    759: 
                    760:     cbRead = ptag->ckSize - cbActual;
                    761: 
                    762:     if( ptag->ckSize & 1 )
                    763:         cbRead++;
                    764: 
                    765:     return SetFilePointer(hf, cbRead, NULL, FILE_CURRENT) != 0xFFFFFFFF;
                    766: }
                    767: 
                    768: BOOL SkipChunk(
                    769:     HANDLE hf,
                    770:     PRTAG ptag)
                    771: {
                    772:     /* Round ptag->ckSize up to nearest word boundary to maintain alignment */
                    773:     return SetFilePointer(hf, PADUP(ptag->ckSize), NULL, FILE_CURRENT) !=
                    774:             0xFFFFFFFFL;
                    775: }
                    776: 
                    777: /****************************************************************************\
                    778: *
                    779: *     FUNCTION: VOID GetTempCursorFileName( szFileName );
                    780: *
                    781: *     PURPOSE:  Create a temporary .cur filename
                    782: *
                    783: *
                    784: * History:
                    785: *   22-Apr-1993 JonPa   Created it
                    786: *
                    787: \****************************************************************************/
                    788: BOOL GetTempCursorFileName( LPTSTR pszName ) {
                    789:     TCHAR szPath[MAX_PATH];
                    790: 
                    791:     if( GetTempPath( MAX_PATH, szPath ) >= MAX_PATH )
                    792:         lstrcpy( pszName, TEXT(".") );
                    793: 
                    794: 
                    795:     return GetTempFileName(szPath, TEXT("ae"), 0, pszName) != 0;
                    796: }
                    797: 
                    798: /****************************************************************************\
                    799: *
                    800: *     FUNCTION: BOOL SaveAniFile( HWND hwnd, HANDLE hf )
                    801: *
                    802: *     PURPOSE:
                    803: &
                    804: *   Saves an animatied cursor to a RIFF file.  The RIFF file format for
                    805: *   animated cursors looks like this:
                    806: *
                    807: *   RIFF( 'ACON'
                    808: *       [LIST( 'INFO'
                    809: *           [INAM( <name> )]
                    810: *           [IART( <artist> )]
                    811: *       )]
                    812: *       anih( <anihdr> )
                    813: *       [rate( <rateinfo> )  ]
                    814: *       ['seq '( <seq_info> )]
                    815: *       LIST( 'fram' icon( <icon_file> ) )
                    816: *   )
                    817: *
                    818: *
                    819: * History:
                    820: *   29-Apr-1993 JonPa   Created it.
                    821: *
                    822: \****************************************************************************/
                    823: BOOL SaveAniFile( HWND hwnd, HANDLE hf ) {
                    824:     int cSteps, i;
                    825:     int cFrames;
                    826:     PFRAME pf;
                    827:     DWORD cbFile, cbFram, cbINFO, cbTitle, cbAuthor;
                    828:     BOOL fRate, fSeq;
                    829:     RTAG rtag;
                    830:     PJIF pjif;
                    831:     DWORD *pseq;
                    832:     PFRAME *pfrm;
                    833: 
                    834:     fRate = fSeq = FALSE;
                    835:     cbINFO = cbFram = cbFile = cbTitle = cbAuthor = 0;
                    836: 
                    837:     PausePreview(hwnd, DLG_MAIN_PREVIEW);
                    838: 
                    839:     cSteps = GetStepCount(hwnd);
                    840: 
                    841:     if( cSteps == LB_ERR ) {
                    842:         FmtMessageBox( ghwndMain, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP,
                    843:                 TRUE, MSG_OUTOFRESOUCES );
                    844:         return FALSE;
                    845:     }
                    846: 
                    847:     cFrames = 0;
                    848:     for( pf = gpfrmFrames; pf != NULL; pf = pf->pfrmNext ) {
                    849:         pf->iFrame = -1;
                    850:         cFrames++;
                    851:     }
                    852: 
                    853:     ganiAcon.anih.cSteps = cSteps;
                    854: 
                    855:     pjif = AllocMem( (sizeof(JIF) + sizeof(DWORD) + sizeof(PFRAME)) * cSteps );
                    856: 
                    857:     if(pjif == NULL)
                    858:         return FALSE;
                    859: 
                    860:     pseq = (DWORD *)&pjif[cSteps];
                    861:     pfrm = (PFRAME *)&pseq[cSteps];
                    862: 
                    863:     cFrames = 0;
                    864: 
                    865:     for( i = 0; i < cSteps; i++ ) {
                    866:         PSTEP ps;
                    867: 
                    868:         ps = GetStep(hwnd, i);
                    869: 
                    870:         if( IsValidPS(ps) ) {
                    871: 
                    872:             if (ps->pfrmFrame->iFrame == -1) {
                    873: 
                    874:                 cbFram += sizeof(RTAG);
                    875:                 cbFram += PADUP(ps->pfrmFrame->rtag.ckSize);
                    876: 
                    877:                 ps->pfrmFrame->iFrame = cFrames;
                    878:                 pfrm[cFrames++] = ps->pfrmFrame;
                    879: 
                    880:             } else
                    881:                 fSeq = TRUE;
                    882: 
                    883:             pseq[i] = ps->pfrmFrame->iFrame;
                    884: 
                    885:             if ((pjif[i] = ps->jif) != ganiAcon.anih.jifRate) {
                    886:                 fRate = TRUE;
                    887:             }
                    888:         }
                    889:     }
                    890: 
                    891:     ganiAcon.anih.cbSizeof = sizeof(ganiAcon.anih);
                    892:     ganiAcon.anih.cFrames = cFrames;
                    893:     ganiAcon.anih.fl = AF_ICON | (fSeq ? AF_SEQUENCE : 0);
                    894: 
                    895:     cbTitle = GetDlgItemTextA(hwnd, DLG_MAIN_TITLE, ganiAcon.azTitle,
                    896:                             COUNTOF(ganiAcon.azTitle));
                    897: 
                    898:     cbAuthor = GetDlgItemTextA(hwnd, DLG_MAIN_AUTHOR, ganiAcon.azCreator,
                    899:                             COUNTOF(ganiAcon.azCreator));
                    900: 
                    901:     /*
                    902:      * At this point, cbFram == the size required by all the frames,
                    903:      * add in the rate, seq, anih, and INFO list sizes as well as
                    904:      * all the other overhead.
                    905:      */
                    906: 
                    907:     cbFram += sizeof(FOURCC);     //fram type
                    908: 
                    909:     cbFile = cbFram;
                    910: 
                    911:     cbFile +=   sizeof(RTAG) +      //RIFF tag
                    912:                 sizeof(FOURCC) +    //ACON type
                    913:                     sizeof(RTAG) +      //anih tag
                    914:                         PADUP(sizeof(ANIHEADER)) +
                    915:                     sizeof(RTAG);       //LIST tag (for fram list)
                    916: 
                    917: 
                    918:     if( cbTitle || cbAuthor) {
                    919:         /*
                    920:          * Remember, azCreator, and azTitle are ANSI strings!
                    921:          */
                    922:         if( cbTitle ) {
                    923:             cbTitle = PADUP( cbTitle * sizeof(char));
                    924:             cbINFO +=   sizeof(RTAG) +     //INAM tag
                    925:                         cbTitle;
                    926:         }
                    927: 
                    928:         if (cbAuthor) {
                    929:             cbAuthor = PADUP(cbAuthor * sizeof(char));
                    930:             cbINFO +=   sizeof(RTAG) +     //IART tag
                    931:                         cbAuthor;
                    932:         }
                    933: 
                    934:         cbINFO +=  sizeof(FOURCC);      //INFO type
                    935: 
                    936:         cbFile +=   sizeof(RTAG) +      //LIST tag
                    937:                     cbINFO;
                    938:     }
                    939: 
                    940: 
                    941:     if (fSeq) {
                    942:         cbFile += sizeof(RTAG) +    //seq tag
                    943:                     PADUP(cSteps * sizeof(DWORD));
                    944:     }
                    945: 
                    946:     if (fRate) {
                    947:         cbFile += sizeof(RTAG) +    //rate tag
                    948:                     PADUP(cSteps * sizeof(JIF));
                    949:     }
                    950: 
                    951:     /*
                    952:      * Now we have all the structures built in memory, it's time to
                    953:      * write them out in RIFF ACON format!
                    954:      */
                    955:     rtag.ckID = FOURCC_RIFF;
                    956:     rtag.ckSize = cbFile;
                    957: 
                    958:     RET_CLOSE_IF_ERR( WriteTag(hf, &rtag), hf );
                    959: 
                    960:     RET_CLOSE_IF_ERR( WriteType(hf, FOURCC_ACON), hf );
                    961: 
                    962:     if( cbTitle || cbAuthor) {
                    963:         rtag.ckID = FOURCC_LIST;
                    964:         rtag.ckSize = cbINFO;
                    965: 
                    966:         RET_CLOSE_IF_ERR( WriteTag(hf, &rtag), hf );
                    967: 
                    968:         RET_CLOSE_IF_ERR( WriteType(hf, FOURCC_INFO), hf );
                    969: 
                    970:         if (cbTitle) {
                    971:             rtag.ckID = FOURCC_INAM;
                    972:             rtag.ckSize = cbTitle;
                    973:             RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, ganiAcon.azTitle), hf );
                    974:         }
                    975: 
                    976:         if (cbAuthor) {
                    977:             rtag.ckID = FOURCC_IART;
                    978:             rtag.ckSize = cbAuthor;
                    979:             RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, ganiAcon.azCreator), hf );
                    980:         }
                    981:     }
                    982: 
                    983:     /* write anih */
                    984:     rtag.ckID = FOURCC_anih;
                    985:     rtag.ckSize = sizeof(ganiAcon.anih);
                    986: 
                    987:     RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, &(ganiAcon.anih)), hf );
                    988: 
                    989:     /* if rate then write it */
                    990:     if (fRate) {
                    991:         rtag.ckID = FOURCC_rate;
                    992:         rtag.ckSize = cSteps * sizeof(JIF);
                    993: 
                    994:         RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, pjif), hf );
                    995:     }
                    996: 
                    997:     /* if seq, then write it */
                    998:     if (fSeq) {
                    999:         rtag.ckID = FOURCC_seq;
                   1000:         rtag.ckSize = cSteps * sizeof(DWORD);
                   1001: 
                   1002:         RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, pseq), hf );
                   1003:     }
                   1004: 
                   1005:     /* write the fram list */
                   1006:     rtag.ckID = FOURCC_LIST;
                   1007:     rtag.ckSize = cbFram;
                   1008: 
                   1009:     RET_CLOSE_IF_ERR( WriteTag(hf, &rtag), hf );
                   1010:     RET_CLOSE_IF_ERR( WriteType(hf, FOURCC_fram), hf );
                   1011: 
                   1012:     for( i = 0; i < cFrames; i++ ) {
                   1013:         RET_CLOSE_IF_ERR( WriteTagData(hf, &(pfrm[i]->rtag), pfrm[i]->abIcon),
                   1014:                 hf);
                   1015:     }
                   1016: 
                   1017:     /* Close the file */
                   1018:     CloseHandle(hf);
                   1019: 
                   1020:     return TRUE;
                   1021: }
                   1022: 
                   1023: 
                   1024: /***************************************************************************\
                   1025: * WriteTag, WriteType, WriteTagData
                   1026: *
                   1027: * Some handy functions for writing RIFF files.
                   1028: *
                   1029: * History:
                   1030: *   30-Apr-1993 JonPa   Created them.
                   1031: \***************************************************************************/
                   1032: BOOL WriteTag(HANDLE hf, PRTAG prtag) {
                   1033:     DWORD cbWritten;
                   1034: 
                   1035:     return (WriteFile(hf, prtag, sizeof(RTAG), &cbWritten, NULL) &&
                   1036:             cbWritten == sizeof(RTAG));
                   1037: }
                   1038: 
                   1039: BOOL WriteType(HANDLE hf, FOURCC ckID ) {
                   1040:     DWORD cbWritten;
                   1041: 
                   1042:     return (WriteFile(hf, &ckID, sizeof(FOURCC), &cbWritten, NULL) &&
                   1043:             cbWritten == sizeof(FOURCC));
                   1044: }
                   1045: 
                   1046: BOOL WriteTagData(HANDLE hf, PRTAG prtag, VOID *pvData ) {
                   1047:     DWORD cbWritten;
                   1048:     DWORD cbWrite = PADUP(prtag->ckSize);
                   1049: 
                   1050:     return  WriteTag(hf, prtag) && WriteFile(hf, pvData, cbWrite,
                   1051:             &cbWritten, NULL) && cbWritten == cbWrite;
                   1052: }
                   1053: 
                   1054: 
                   1055: 
                   1056: 
                   1057: /***************************************************************************\
                   1058: * VOID SaveFile(HWND hwnd, BOOL fPrompt)
                   1059: *
                   1060: * Conditionally Prompt the user for a name and then save the file
                   1061: *
                   1062: * History:
                   1063: *   04-May-1993 JonPa   It
                   1064: \***************************************************************************/
                   1065: VOID SaveFile(HWND hwnd, BOOL fPrompt) {
                   1066:     TCHAR szFileTitle[MAX_PATH];
                   1067:     HANDLE hf;
                   1068: 
                   1069:     szFileTitle[0] = TEXT('\0');
                   1070: 
                   1071:     if (fPrompt || ganiAcon.szFile[0] == TEXT('\0')) {
                   1072: tryagain:
                   1073:         if (!PromptForFile(hwnd, COUNTOF(szFileTitle), szFileTitle,
                   1074:                 COUNTOF(ganiAcon.szFile), ganiAcon.szFile, gpszAniFilter,
                   1075:                 NULL, TRUE)) {
                   1076:             return;
                   1077:         }
                   1078:     }
                   1079: 
                   1080:     hf = CreateFile( ganiAcon.szFile, GENERIC_WRITE, 0, NULL,
                   1081:             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
                   1082: 
                   1083:     if (hf == INVALID_HANDLE_VALUE) {
                   1084:         FmtMessageBox(hwnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE,
                   1085:                 MSG_CANTCREATEFILE, ganiAcon.szFile);
                   1086: 
                   1087:         goto tryagain;
                   1088:     }
                   1089: 
                   1090:     if( !SaveAniFile(hwnd, hf) ) {
                   1091:         FmtMessageBox(hwnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE,
                   1092:                 MSG_FILEWRITEERR, ganiAcon.szFile);
                   1093:         return;
                   1094:     }
                   1095: 
                   1096:     if (szFileTitle[0] != TEXT('\0'))
                   1097:         SetWindowFileTitle(hwnd, szFileTitle);
                   1098: 
                   1099:     ganiAcon.fDirty = FALSE;
                   1100: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.