home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************\
- *
- * MODULE: anifile.c
- *
- * PURPOSE: Processes files for the Animated Cursor Editor
- *
- * Copyright 1993-1996 Microsoft Corp.
- *
- *
- * History:
- * 21-Apr-1993 JonPa Wrote it.
- *
- \****************************************************************************/
-
- #include <windows.h>
- #include <commdlg.h>
- #include "anidefs.h"
-
- /****************************************************************************\
- *
- * FUNCTION: BOOL CreateFrameFromCursorFile( LPSTR pszFile )
- *
- * PURPOSE: Opens a cursor file, reads the icon info out of it,
- * and creates a frame and step for that icon, then links
- * everything together and updates the listbox.
- *
- * NOTES: This function accesses the global flag gfEditFrame.
- * If this bool is TRUE, then the currently selected frame
- * in the listbox is overwritten. If it is false, then
- * a new frame is created and inserted after the currently
- * selected frame (or at the end if no selection).
- *
- * History:
- * 21-Apr-1993 JonPa Created it
- *
- \****************************************************************************/
- BOOL CreateFrameFromCursorFile(HWND hwnd, LPTSTR pszFile, BOOL fEdit) {
- PFRAME pf;
- HANDLE hf;
- PSTEP psOld, psNew;
- DWORD ckSize;
- int iSel;
- int cSel;
-
- cSel = GetSelStepCount(hwnd);
-
- if ( (fEdit && (cSel != 1)) || cSel > 1) {
- FmtMessageBox( hwnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP,
- TRUE, fEdit ? MSG_MUSTEQONEFAME : MSG_LESSEQONEFRAME);
- return FALSE;
- }
-
- /* get currently selected frame */
- GetCurrentSel(hwnd, DLG_MAIN_FRAMELIST, &iSel, 1, &cSel );
-
- if (cSel == 0)
- psOld = NULL;
- else
- psOld = GetStep(hwnd, iSel);
-
- /*
- * If not editing, create a new step
- */
- if (!fEdit || !IsValidPS(psOld)) {
- psNew = NewStep();
-
- if (psNew == NULL) {
- return FALSE;
- }
- } else {
- psNew = NULL;
- }
-
- hf = CreateFile(pszFile, GENERIC_READ,
- 0, NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (hf == INVALID_HANDLE_VALUE)
- return FALSE;
-
- ckSize = GetFileSize(hf, NULL);
-
- /* get the frame out of the file */
- pf = ReadIconFromFile(hwnd, hf, ckSize);
- CloseHandle(hf);
-
- if (pf == NULL) {
- if (psNew != NULL)
- FreeMem(psNew);
- return FALSE;
- }
-
- if (psNew != NULL) {
-
- if (IsValidPS(psOld)) {
- psNew->jif = psOld->jif;
- iSel += 1;
- } else {
- psNew->jif = ganiAcon.anih.jifRate;
- iSel = SendDlgItemMessage(hwnd, DLG_MAIN_FRAMELIST, LB_GETCOUNT,
- 0, 0);
- }
-
- LinkStepFrame(psNew, pf);
-
- SendDlgItemMessage(hwnd, DLG_MAIN_FRAMELIST, LB_INSERTSTRING, iSel,
- (LPARAM)psNew);
-
- SetCurrentSel(hwnd, DLG_MAIN_FRAMELIST, FALSE, iSel);
-
- } else {
- HWND hwndLB = GetDlgItem(hwnd, DLG_MAIN_FRAMELIST);
-
- /*
- * Delete the old frame and point the step to the new one.
- */
- LinkStepFrame(psOld, pf);
-
- InvalidateRect(hwndLB, NULL, TRUE);
- }
-
- return TRUE;
- }
-
-
- /****************************************************************************\
- *
- * FUNCTION: HICON ConvertDataToIcon( PFRAME pf )
- *
- * PURPOSE:
- *
- *
- *
- *
- * History:
- * 23-Apr-1993 JonPa copied from Win NT USERs ReadIconGuts
- *
- \****************************************************************************/
- HICON ConvertDataToIcon( PFRAME pf, WORD *pxHotSave, WORD *pyHotSave )
- {
- NEWHEADER *pnh;
- NEWHEADER *pnhBase;
- RESDIR *prd;
- int offMatch;
- ICONFILERESDIR *pird;
- PCURSORRESOURCE pcres;
- BOOL fIcon;
- HICON hicon;
- WORD x, y;
- LPBYTE pbBits;
-
- pnhBase = (NEWHEADER *)pf->abIcon;
-
- /*
- * Construct a fake array of RESDIR entries using the info at the head
- * of the file. Store the data offset in the idIcon WORD so it can be
- * returned by RtlGetIdFromDirectory.
- */
- pnh = (NEWHEADER *)LocalAlloc(LMEM_FIXED, sizeof(NEWHEADER) +
- (pnhBase->cResources * sizeof(RESDIR)));
- if (pnh == NULL)
- return NULL;
-
- *pnh = *pnhBase;
- prd = (RESDIR *)(pnh + 1);
- pird = (ICONFILERESDIR *)(pnhBase + 1);
-
- /* prime pird for first line of loop */
- pird--;
-
- for (offMatch = 0; offMatch < (int)pnh->cResources; offMatch++, prd++) {
-
- /*
- * Get the next resource directory from the icon file.
- */
-
- ++pird;
-
- /*
- * Convert from the icon editor's resource directory format
- * to the post-RC.EXE format LookupIconIdFromDirectory expects.
- */
- if (pnh->rt == 1) { // ICON
- prd->ResInfo.Icon.Width = pird->bWidth;
- prd->ResInfo.Icon.Height = pird->bHeight;
- prd->ResInfo.Icon.ColorCount = pird->bColorCount;
- prd->ResInfo.Icon.reserved = 0;
- } else { // CURSOR
- prd->ResInfo.Cursor.Width = pird->bWidth;
- prd->ResInfo.Cursor.Height = pird->bHeight;
- }
- prd->Planes = 0; // Hopefully nobody uses this
- prd->BitCount = 0; // " "
- prd->BytesInRes = pird->dwDIBSize;
- prd->idIcon = (WORD)pird->dwDIBOffset;
- }
-
- /*
- * NOTE: nh.rt is NOT an RT_ type value. For instance, nh.rt == 1 for
- * an icon file where as 1 == RT_CURSOR, not RT_ICON.
- */
-
- fIcon = (pnhBase->rt == 1);
- offMatch = LookupIconIdFromDirectory((PBYTE)pnh, fIcon);
-
- LocalFree(pnh);
-
- if (fIcon) {
- pcres = (PCURSORRESOURCE)&(pf->abIcon[offMatch]);
- *pxHotSave = gcxCursor / 2;
- *pyHotSave = gcyCursor / 2;
- } else {
-
- offMatch -= (sizeof(pcres->xHotspot) + sizeof(pcres->yHotspot));
-
- for(; pird->dwDIBOffset != (WORD)offMatch &&
- pird != (ICONFILERESDIR *)(pnhBase + 1); pird--);
-
- pcres = (PCURSORRESOURCE)&(pf->abIcon[offMatch]);
-
- x = pcres->xHotspot;
- y = pcres->yHotspot;
- *pxHotSave = pcres->xHotspot = pird->xHotspot;
- *pyHotSave = pcres->yHotspot = pird->yHotspot;
- }
-
-
- // Buffer must be aligned
- pbBits = LocalAlloc(LMEM_FIXED, pf->rtag.ckSize - offMatch );
- if (pbBits) {
- CopyMemory( pbBits, pcres, pf->rtag.ckSize - offMatch );
-
- hicon = CreateIconFromResource( pbBits,
- pf->rtag.ckSize - offMatch, fIcon, 0x00030000);
-
- LocalFree( pbBits );
- } else
- hicon = NULL;
-
- if(!fIcon) {
- pcres->xHotspot = x;
- pcres->yHotspot = y;
- }
-
- return hicon;
- }
-
-
-
-
- /****************************************************************************\
- *
- * FUNCTION: PFRAME ReadIconFromFile(HWND hwnd, HANDLE hf, DWORD ckSize)
- *
- * PURPOSE: Reads the icon info out of a file,
- * and creates a frame for that icon.
- *
- *
- * History:
- * 22-Apr-1993 JonPa Created it
- *
- \****************************************************************************/
- PFRAME ReadIconFromFile(HWND hwnd, HANDLE hf, DWORD ckSize) {
- PFRAME pf = AllocMem( sizeof( FRAME ) + ckSize );
- DWORD cbRead;
- PFRAME pfList;
-
- if (pf != NULL) {
- pf->cRef = 0;
-
- if (ReadFile(hf, pf->abIcon, ckSize, &cbRead, NULL) &&
- cbRead == ckSize) {
- /* got the data, now set up the rest of the frame and link it in */
- pf->dwCheckSum = CalcCheckSum( pf->abIcon, ckSize );
- pf->rtag.ckID = FOURCC_icon;
- pf->rtag.ckSize = ckSize;
-
- /* Check if this fram is already in the list */
- for (pfList = gpfrmFrames; pfList != NULL;
- pfList = pfList->pfrmNext ) {
- if (pf->dwCheckSum == pfList->dwCheckSum &&
- pf->rtag.ckSize == pfList->rtag.ckSize &&
- memcmp( pf->abIcon, pfList->abIcon, ckSize ) == 0) {
- /*
- * These frames are the same, coalesce them into a
- * sequence.
- */
- FreeMem(pf);
- pf = pfList;
- break;
- }
- }
-
- if (pfList == NULL) {
- /*
- * Did not find a dup, create an icon for this frame
- */
- pf->hcur = ConvertDataToIcon( pf, &(pf->xHotSpot),
- &(pf->yHotSpot) );
-
- pf->pfrmNext = gpfrmFrames;
- gpfrmFrames = pf;
- }
-
- } else {
- /* File Error */
- FreeMem(pf);
- pf = NULL;
- }
-
- }
-
- return pf;
- }
-
- /****************************************************************************\
- *
- * FUNCTION: HANDLE PromptAndOpenFile( )
- *
- * PURPOSE: Pust up the standard open dialog and then opens the file
- *
- *
- *
- *
- * History:
- * 21-Apr-1993 JonPa Created it
- *
- \****************************************************************************/
- HANDLE PromptAndOpenFile(
- HWND hwnd,
- DWORD cchFileTitle,
- LPTSTR pszFileTitle,
- DWORD cchFileName,
- LPTSTR pszFileName,
- LPTSTR pszFilter
- )
- {
- HANDLE hf = INVALID_HANDLE_VALUE;
-
- if (PromptForFile( hwnd, cchFileTitle, pszFileTitle, cchFileName,
- pszFileName, pszFilter, NULL, FALSE )) {
-
- /* Open the file. */
-
- hf = CreateFile(pszFileName, GENERIC_READ,
- 0, NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (hf == INVALID_HANDLE_VALUE) {
- FmtMessageBox( hwnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE,
- MSG_CANTOPENFILE, pszFileName );
- }
- }
-
- return hf;
- }
-
-
- /****************************************************************************\
- *
- * FUNCTION: HANDLE PromptForFile( )
- *
- * PURPOSE: Pust up the standard open dialog
- *
- *
- *
- *
- * History:
- * 28-Apr-1993 JonPa Created it from PromptAndOpenFile
- *
- \****************************************************************************/
- BOOL PromptForFile(
- HWND hwnd,
- DWORD cchFileTitle,
- LPTSTR pszFileTitle,
- DWORD cchFileName,
- LPTSTR pszFile,
- LPTSTR pszFilter,
- LPTSTR pszDlgTitle,
- BOOL fSave
- )
- {
- OPENFILENAME ofn;
-
- ZeroMemory(&ofn, sizeof(ofn));
-
- /* Set the members of the OPENFILENAME structure. */
-
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = hwnd;
-
- ofn.lpstrFilter = pszFilter;
- ofn.nFilterIndex = 0;
-
- ofn.lpstrFile = pszFile;
- ofn.nMaxFile = cchFileName;
-
- ofn.lpstrFileTitle = pszFileTitle;
- ofn.nMaxFileTitle = cchFileTitle;
-
- ofn.lpstrTitle = pszDlgTitle;
-
- ofn.lpstrDefExt = gpszANI;
-
- if (fSave) {
- ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
- } else {
- ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
- }
-
- /* Display the SaveAs or Open dialog box. */
-
- return fSave ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn);
-
- }
-
- /****************************************************************************\
- *
- * FUNCTION: BOOL ReadAniFile( HWND hwnd, HANDLE hf ) {
- *
- * PURPOSE:
- &
- * Loads an animatied cursor from a RIFF file. The RIFF file format for
- * animated cursors looks like this:
- *
- * RIFF( 'ACON'
- * LIST( 'INFO'
- * INAM( <name> )
- * IART( <artist> )
- * )
- * anih( <anihdr> )
- * [rate( <rateinfo> ) ]
- * ['seq '( <seq_info> )]
- * LIST( 'fram' icon( <icon_file> ) )
- * )
- *
- *
- * History:
- * 02-Oct-1991 DarrinM Created. (in Win32 user)
- * 17-Mar-1993 JonPa Rewrote to use RIFF format instead of RAD
- * 21-Apr-1993 JonPa Copied it to anifile.c and tweeked it.
- *
- \****************************************************************************/
- BOOL ReadAniFile( HWND hwnd, HANDLE hf ) {
-
- RTAG tag;
- DWORD cbRead;
- BOOL fSuccess = FALSE;
- JIF *pjifRate = NULL;
- DWORD *pseq = NULL;
- PFRAME *ppfram = NULL;
- int iFrame = 0;
- int i;
-
- if (!ReadTag(hf, &tag))
- goto laiFileErr;
-
- /*
- * Make sure it's a RIFF ANI file
- */
- if (tag.ckID != FOURCC_RIFF)
- goto laiFileErr;
-
- /* read the chunk type */
- if(!ReadFile(hf, &tag.ckID, sizeof(tag.ckID), &cbRead, NULL) ||
- cbRead < sizeof(tag.ckID)) {
- goto laiFileErr;
- }
-
- if (tag.ckID != FOURCC_ACON)
- goto laiFileErr;
-
- /* look for 'anih', 'rate', 'seq ', and 'icon' chunks */
- while( ReadTag(hf, &tag)) {
-
- switch( tag.ckID ) {
- case FOURCC_anih:
- if (!ReadChunk(hf, &tag, &ganiAcon.anih))
- goto laiFileErr;
-
- if (!(ganiAcon.anih.fl & AF_ICON) || (ganiAcon.anih.cFrames == 0))
- goto laiFileErr;
-
- /*
- * Allocate space for the ANIHEADER, and a seq and
- * rate table (in case we run into one later).
- */
-
- pjifRate = AllocMem( ganiAcon.anih.cSteps * sizeof(JIF) +
- ganiAcon.anih.cSteps * sizeof(DWORD) +
- ganiAcon.anih.cSteps * sizeof(PFRAME));
-
-
- if (pjifRate == NULL)
- goto laiFileErr;
-
- pseq = (DWORD *)(pjifRate + ganiAcon.anih.cSteps);
- ppfram = (PFRAME *)(pseq + ganiAcon.anih.cSteps);
-
- for( i = 0; i < (int)ganiAcon.anih.cSteps; i++ ) {
- pjifRate[i] = ganiAcon.anih.jifRate;
- pseq[i] = i;
- ppfram[i] = NULL;
- }
- break;
-
-
- case FOURCC_rate:
- /*
- * If we find a rate chunk, read it into its preallocated
- * space.
- */
- if(!ReadChunk(hf, &tag, (PBYTE)pjifRate))
- goto laiFileErr;
- break;
-
-
- case FOURCC_seq:
- /*
- * If we find a seq chunk, read it into its preallocated
- * space.
- */
- if(!ReadChunk(hf, &tag, (PBYTE)pseq))
- goto laiFileErr;
- break;
-
-
- case FOURCC_LIST: {
- DWORD cbChunk = PADUP(tag.ckSize);
-
- /*
- * See if this list is the 'fram' list of icon chunks
- */
- if(!ReadFile(hf, &tag.ckID, sizeof(tag.ckID), &cbRead, NULL) ||
- cbRead < sizeof(tag.ckID)) {
- goto laiFileErr;
- }
-
- cbChunk -= cbRead;
-
- if (tag.ckID == FOURCC_fram) {
-
- while(cbChunk >= sizeof(tag)) {
- if (!ReadTag(hf, &tag))
- goto laiFileErr;
-
- cbChunk -= sizeof(tag);
-
- if(tag.ckID == FOURCC_icon) {
- PFRAME pfrm;
-
- /*
- * Ok, load the icon/cursor bits,
- */
- pfrm = ReadIconFromFile(hwnd, hf, tag.ckSize);
-
- if (pfrm == NULL) {
- goto laiFileErr;
- }
-
- for( i = 0; i < (int)ganiAcon.anih.cSteps; i++ ) {
- if (pseq[i] == (DWORD)iFrame) {
- ppfram[i] = pfrm;
- }
- }
-
- iFrame++;
-
- } else {
- /*
- * Unknown chunk in fram list, just ignore it
- */
- SkipChunk(hf, &tag);
- }
-
- cbChunk -= PADUP(tag.ckSize);
- }
- } else if (tag.ckID == FOURCC_INFO) {
- /* now look for INAM and IART chunks */
-
- while( cbChunk >= sizeof(tag) ) {
-
- if (!ReadTag(hf, &tag))
- goto laiFileErr;
-
- cbChunk -= sizeof(tag);
-
- switch( tag.ckID ) {
- case FOURCC_INAM:
- if (cbChunk < tag.ckSize ||
- !ReadChunkN(hf, &tag, ganiAcon.azTitle,
- sizeof(ganiAcon.azTitle)))
- goto laiFileErr;
-
- cbChunk -= PADUP(tag.ckSize);
- break;
-
- case FOURCC_IART:
- if (cbChunk < tag.ckSize ||
- !ReadChunkN(hf, &tag, ganiAcon.azCreator,
- sizeof(ganiAcon.azCreator)))
- goto laiFileErr;
-
- cbChunk -= PADUP(tag.ckSize);
- break;
-
- default:
- if (!SkipChunk( hf, &tag ))
- goto laiFileErr;
-
- cbChunk -= PADUP(tag.ckSize);
- break;
- }
- }
-
- } else {
- /*
- * Not the fram list or the INFO list. Skip
- * the rest of this chunk. (Don't forget that we have
- * already skipped one dword!)
- */
- tag.ckSize = cbChunk;
- SkipChunk(hf, &tag);
- break;
- }
-
- break;
- }
-
-
-
- default:
- /*
- * We're not interested in this chunk, skip it.
- */
- if(!SkipChunk(hf, &tag))
- goto laiFileErr;
- break;
-
- }
-
- }
-
- /*
- * Update the frame count incase we coalesced some frames while reading
- * in the file.
- */
- ganiAcon.anih.cFrames = iFrame;
-
- /*
- * Now build up the listbox
- */
-
- for( i = 0; i < (int)ganiAcon.anih.cSteps; i++ ) {
- PSTEP ps;
-
- ps = NewStep();
- if (ps == NULL)
- goto laiFileErr;
-
- ps->jif = pjifRate[i];
- LinkStepFrame(ps, ppfram[i]);
-
- SendDlgItemMessage(hwnd, DLG_MAIN_FRAMELIST, LB_INSERTSTRING, i,
- (LPARAM)ps);
- }
-
- SetDlgItemText(hwnd, DLG_MAIN_TITLE, ganiAcon.azTitle);
- SetDlgItemText(hwnd, DLG_MAIN_AUTHOR, ganiAcon.azCreator);
-
- SendDlgItemMessage(hwnd, DLG_MAIN_PREVIEW, PM_NEWCURSOR, 0, 0);
- fSuccess = TRUE;
-
- laiFileErr:
-
- if (pjifRate != NULL)
- FreeMem(pjifRate);
-
- if (!fSuccess)
- NewAniCursor(hwnd);
-
- CloseHandle(hf);
-
- return fSuccess;
- }
-
-
-
- /***************************************************************************\
- * DWORD CalcCheckSum( PBYTE pb );
- *
- *
- * History:
- *
- * 23-Apr-1993 JonPa Created.
- \***************************************************************************/
- DWORD CalcCheckSum( PBYTE pb, DWORD cb ) {
- DWORD dw = 0;
-
- while(cb--)
- dw += (DWORD)*pb++;
-
- return dw;
- }
-
- /***************************************************************************\
- * ReadTag, ReadChunk, SkipChunk
- *
- * Some handy functions for reading RIFF files.
- *
- * History:
- * 10-02-91 DarrinM Created.
- * 03-25-93 Jonpa Changed to use RIFF format instead of ASDF
- * 23-Apr-1993 JonPa Copied from Win NT USER.
- \***************************************************************************/
- BOOL ReadTag(
- HANDLE hf,
- PRTAG ptag)
- {
- DWORD cbActual;
-
- ptag->ckID = ptag->ckSize = 0L;
-
- if (!ReadFile(hf, ptag, sizeof(RTAG), &cbActual, NULL) ||
- (cbActual != sizeof(RTAG)))
- return FALSE;
-
- /* no need to align file pointer since RTAG is already word aligned */
- return TRUE;
- }
-
-
- BOOL ReadChunk(
- HANDLE hf,
- PRTAG ptag,
- PVOID pv)
- {
- DWORD cbActual;
-
- if (!ReadFile(hf, pv, ptag->ckSize, &cbActual, NULL) ||
- (cbActual != ptag->ckSize))
- return FALSE;
-
- /* WORD align file pointer */
- if( ptag->ckSize & 1 )
- SetFilePointer(hf, 1, NULL, FILE_CURRENT);
-
- return TRUE;
- }
-
-
- BOOL ReadChunkN(
- HANDLE hf,
- PRTAG ptag,
- PVOID pv,
- DWORD cbMax)
- {
- DWORD cbActual;
- DWORD cbRead = min( cbMax, ptag->ckSize );
-
- if (!ReadFile(hf, pv, ptag->ckSize, &cbActual, NULL) ||
- (cbActual != cbRead))
- return FALSE;
-
- /* WORD align file pointer */
-
- cbRead = ptag->ckSize - cbActual;
-
- if( ptag->ckSize & 1 )
- cbRead++;
-
- return SetFilePointer(hf, cbRead, NULL, FILE_CURRENT) != 0xFFFFFFFF;
- }
-
- BOOL SkipChunk(
- HANDLE hf,
- PRTAG ptag)
- {
- /* Round ptag->ckSize up to nearest word boundary to maintain alignment */
- return SetFilePointer(hf, PADUP(ptag->ckSize), NULL, FILE_CURRENT) !=
- 0xFFFFFFFFL;
- }
-
- /****************************************************************************\
- *
- * FUNCTION: VOID GetTempCursorFileName( szFileName );
- *
- * PURPOSE: Create a temporary .cur filename
- *
- *
- * History:
- * 22-Apr-1993 JonPa Created it
- *
- \****************************************************************************/
- BOOL GetTempCursorFileName( LPTSTR pszName ) {
- TCHAR szPath[MAX_PATH];
-
- if( GetTempPath( MAX_PATH, szPath ) >= MAX_PATH )
- lstrcpy( pszName, TEXT(".") );
-
-
- return GetTempFileName(szPath, TEXT("ae"), 0, pszName) != 0;
- }
-
- /****************************************************************************\
- *
- * FUNCTION: BOOL SaveAniFile( HWND hwnd, HANDLE hf )
- *
- * PURPOSE:
- &
- * Saves an animatied cursor to a RIFF file. The RIFF file format for
- * animated cursors looks like this:
- *
- * RIFF( 'ACON'
- * [LIST( 'INFO'
- * [INAM( <name> )]
- * [IART( <artist> )]
- * )]
- * anih( <anihdr> )
- * [rate( <rateinfo> ) ]
- * ['seq '( <seq_info> )]
- * LIST( 'fram' icon( <icon_file> ) )
- * )
- *
- *
- * History:
- * 29-Apr-1993 JonPa Created it.
- *
- \****************************************************************************/
- BOOL SaveAniFile( HWND hwnd, HANDLE hf ) {
- int cSteps, i;
- int cFrames;
- PFRAME pf;
- DWORD cbFile, cbFram, cbINFO, cbTitle, cbAuthor;
- BOOL fRate, fSeq;
- RTAG rtag;
- PJIF pjif;
- DWORD *pseq;
- PFRAME *pfrm;
-
- fRate = fSeq = FALSE;
- cbINFO = cbFram = cbFile = cbTitle = cbAuthor = 0;
-
- PausePreview(hwnd, DLG_MAIN_PREVIEW);
-
- cSteps = GetStepCount(hwnd);
-
- if( cSteps == LB_ERR ) {
- FmtMessageBox( ghwndMain, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP,
- TRUE, MSG_OUTOFRESOUCES );
- return FALSE;
- }
-
- cFrames = 0;
- for( pf = gpfrmFrames; pf != NULL; pf = pf->pfrmNext ) {
- pf->iFrame = -1;
- cFrames++;
- }
-
- ganiAcon.anih.cSteps = cSteps;
-
- pjif = AllocMem( (sizeof(JIF) + sizeof(DWORD) + sizeof(PFRAME)) * cSteps );
-
- if(pjif == NULL)
- return FALSE;
-
- pseq = (DWORD *)&pjif[cSteps];
- pfrm = (PFRAME *)&pseq[cSteps];
-
- cFrames = 0;
-
- for( i = 0; i < cSteps; i++ ) {
- PSTEP ps;
-
- ps = GetStep(hwnd, i);
-
- if( IsValidPS(ps) ) {
-
- if (ps->pfrmFrame->iFrame == -1) {
-
- cbFram += sizeof(RTAG);
- cbFram += PADUP(ps->pfrmFrame->rtag.ckSize);
-
- ps->pfrmFrame->iFrame = cFrames;
- pfrm[cFrames++] = ps->pfrmFrame;
-
- } else
- fSeq = TRUE;
-
- pseq[i] = ps->pfrmFrame->iFrame;
-
- if ((pjif[i] = ps->jif) != ganiAcon.anih.jifRate) {
- fRate = TRUE;
- }
- }
- }
-
- ganiAcon.anih.cbSizeof = sizeof(ganiAcon.anih);
- ganiAcon.anih.cFrames = cFrames;
- ganiAcon.anih.fl = AF_ICON | (fSeq ? AF_SEQUENCE : 0);
-
- cbTitle = GetDlgItemTextA(hwnd, DLG_MAIN_TITLE, ganiAcon.azTitle,
- COUNTOF(ganiAcon.azTitle));
-
- cbAuthor = GetDlgItemTextA(hwnd, DLG_MAIN_AUTHOR, ganiAcon.azCreator,
- COUNTOF(ganiAcon.azCreator));
-
- /*
- * At this point, cbFram == the size required by all the frames,
- * add in the rate, seq, anih, and INFO list sizes as well as
- * all the other overhead.
- */
-
- cbFram += sizeof(FOURCC); //fram type
-
- cbFile = cbFram;
-
- cbFile += sizeof(FOURCC) + //ACON type
- sizeof(RTAG) + //anih tag
- PADUP(sizeof(ANIHEADER)) +
- sizeof(RTAG); //LIST tag (for fram list)
-
-
- if( cbTitle || cbAuthor) {
- /*
- * Remember, azCreator, and azTitle are ANSI strings!
- */
- if( cbTitle ) {
- cbTitle += 1; //add in ASCIIZ terminator
- cbINFO += sizeof(RTAG) + //INAM tag
- PADUP( cbTitle * sizeof(char));
- }
-
- if (cbAuthor) {
- cbAuthor += 1; //add in ASCIIZ terminator
- cbINFO += sizeof(RTAG) + //IART tag
- PADUP(cbAuthor * sizeof(char));
- }
-
- cbINFO += sizeof(FOURCC); //INFO type
-
- cbFile += sizeof(RTAG) + //LIST tag
- cbINFO;
- }
-
-
- if (fSeq) {
- cbFile += sizeof(RTAG) + //seq tag
- PADUP(cSteps * sizeof(DWORD));
- }
-
- if (fRate) {
- cbFile += sizeof(RTAG) + //rate tag
- PADUP(cSteps * sizeof(JIF));
- }
-
- /*
- * Now we have all the structures built in memory, it's time to
- * write them out in RIFF ACON format!
- */
- rtag.ckID = FOURCC_RIFF;
- rtag.ckSize = cbFile;
-
- RET_CLOSE_IF_ERR( WriteTag(hf, &rtag), hf );
-
- RET_CLOSE_IF_ERR( WriteType(hf, FOURCC_ACON), hf );
-
- if( cbTitle || cbAuthor) {
- rtag.ckID = FOURCC_LIST;
- rtag.ckSize = cbINFO;
-
- RET_CLOSE_IF_ERR( WriteTag(hf, &rtag), hf );
-
- RET_CLOSE_IF_ERR( WriteType(hf, FOURCC_INFO), hf );
-
- if (cbTitle) {
- rtag.ckID = FOURCC_INAM;
- rtag.ckSize = cbTitle;
- RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, ganiAcon.azTitle), hf );
- }
-
- if (cbAuthor) {
- rtag.ckID = FOURCC_IART;
- rtag.ckSize = cbAuthor;
- RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, ganiAcon.azCreator), hf );
- }
- }
-
- /* write anih */
- rtag.ckID = FOURCC_anih;
- rtag.ckSize = sizeof(ganiAcon.anih);
-
- RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, &(ganiAcon.anih)), hf );
-
- /* if rate then write it */
- if (fRate) {
- rtag.ckID = FOURCC_rate;
- rtag.ckSize = cSteps * sizeof(JIF);
-
- RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, pjif), hf );
- }
-
- /* if seq, then write it */
- if (fSeq) {
- rtag.ckID = FOURCC_seq;
- rtag.ckSize = cSteps * sizeof(DWORD);
-
- RET_CLOSE_IF_ERR( WriteTagData(hf, &rtag, pseq), hf );
- }
-
- /* write the fram list */
- rtag.ckID = FOURCC_LIST;
- rtag.ckSize = cbFram;
-
- RET_CLOSE_IF_ERR( WriteTag(hf, &rtag), hf );
- RET_CLOSE_IF_ERR( WriteType(hf, FOURCC_fram), hf );
-
- for( i = 0; i < cFrames; i++ ) {
- RET_CLOSE_IF_ERR( WriteTagData(hf, &(pfrm[i]->rtag), pfrm[i]->abIcon),
- hf);
- }
-
- /* Close the file */
- CloseHandle(hf);
-
- return TRUE;
- }
-
-
- /***************************************************************************\
- * WriteTag, WriteType, WriteTagData
- *
- * Some handy functions for writing RIFF files.
- *
- * History:
- * 30-Apr-1993 JonPa Created them.
- \***************************************************************************/
- BOOL WriteTag(HANDLE hf, PRTAG prtag) {
- DWORD cbWritten;
-
- return (WriteFile(hf, prtag, sizeof(RTAG), &cbWritten, NULL) &&
- cbWritten == sizeof(RTAG));
- }
-
- BOOL WriteType(HANDLE hf, FOURCC ckID ) {
- DWORD cbWritten;
-
- return (WriteFile(hf, &ckID, sizeof(FOURCC), &cbWritten, NULL) &&
- cbWritten == sizeof(FOURCC));
- }
-
- BOOL WriteTagData(HANDLE hf, PRTAG prtag, VOID *pvData ) {
- DWORD cbWritten;
- DWORD cbWrite = PADUP(prtag->ckSize);
-
- return WriteTag(hf, prtag) && WriteFile(hf, pvData, cbWrite,
- &cbWritten, NULL) && cbWritten == cbWrite;
- }
-
-
-
-
- /***************************************************************************\
- * VOID SaveFile(HWND hwnd, BOOL fPrompt)
- *
- * Conditionally Prompt the user for a name and then save the file
- *
- * History:
- * 04-May-1993 JonPa It
- \***************************************************************************/
- VOID SaveFile(HWND hwnd, BOOL fPrompt) {
- TCHAR szFileTitle[MAX_PATH];
- HANDLE hf;
-
- szFileTitle[0] = TEXT('\0');
-
- if (fPrompt || ganiAcon.szFile[0] == TEXT('\0')) {
- tryagain:
- if (!PromptForFile(hwnd, COUNTOF(szFileTitle), szFileTitle,
- COUNTOF(ganiAcon.szFile), ganiAcon.szFile, gpszAniFilter,
- NULL, TRUE)) {
- return;
- }
- }
-
- hf = CreateFile( ganiAcon.szFile, GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (hf == INVALID_HANDLE_VALUE) {
- FmtMessageBox(hwnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE,
- MSG_CANTCREATEFILE, ganiAcon.szFile);
-
- goto tryagain;
- }
-
- if( !SaveAniFile(hwnd, hf) ) {
- FmtMessageBox(hwnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE,
- MSG_FILEWRITEERR, ganiAcon.szFile);
- return;
- }
-
- if (szFileTitle[0] != TEXT('\0'))
- SetWindowFileTitle(hwnd, szFileTitle);
-
- ganiAcon.fDirty = FALSE;
- }
-