|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.