/****************************************************************************\ * * MODULE: anicmd.c * * PURPOSE: Processes WM_COMMANDs for the Animated Cursor Editor * * Copyright 1993-1996 Microsoft Corp. * * * History: * 21-Apr-1993 JonPa Wrote it. * \****************************************************************************/ #include #include #include #include "anidefs.h" static DWORD WINAPI ProcWaitThread( LPVOID lpv ); static BOOL CALLBACK ETWProc( HWND hwnd, LPARAM lParam ); BOOL gfEditFrame = FALSE; TCHAR gszTempFile[MAX_PATH]; /****************************************************************************\ * * FUNCTION: void AniEndDialog( HDLG hdlg, int i ) * * PURPOSE: Destroys Modless Dialogs * * * History: * 08-Sep-1995 JonPa Created it * \****************************************************************************/ #define AniEndDialog( hdlg, i ) DestroyWindow( hdlg ) /****************************************************************************\ * * FUNCTION: void LoadAniFile(hWnd, hfCursor, szFileTitle, szFile) * * PURPOSE: Loads an ANI from the given handle, and sets up ganiAcon * * * History: * 31-May-1995 JonPa Created it * \****************************************************************************/ void LoadAniFile(HWND hWnd, HANDLE hfCursor, LPTSTR szFileTitle, LPTSTR szFile) { /* delete any existing ani file */ NewAniCursor( hWnd ); /* read in the file */ if (!ReadAniFile( hWnd, hfCursor )) { FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE, MSG_INVALIDCURSORFILE, szFileTitle ); } else { /* * Put the filename in the title. */ lstrcpy(ganiAcon.szFile, szFile); SetWindowFileTitle(hWnd, szFileTitle); SetDlgItemInt( hWnd, DLG_MAIN_RATE, ganiAcon.anih.jifRate, FALSE); } ResumePreview(hWnd, DLG_MAIN_PREVIEW); } /****************************************************************************\ * * FUNCTION: DoCommand(HWND, unsigned, WORD, LONG) * * PURPOSE: Processes commands for the main dialog box * * MESSAGES: * * WM_INITDIALOG - initialize dialog box * WM_COMMAND - Input received * * COMMENTS: * * * History: * 21-Apr-1993 JonPa Created it * \****************************************************************************/ BOOL DoCommand( HWND hWnd, UINT wParam, LONG lParam ) { int cmd = LOWORD(wParam); switch(cmd){ case MENU_FILE_NEW: case DLG_MAIN_BTNNEW: /* If dirty, then prompt for save */ if(!CheckDirty(hWnd)) break; /* free used memory and init structures and dlg */ NewAniCursor(hWnd); ResumePreview(hWnd, DLG_MAIN_PREVIEW); break; case DLG_MAIN_BTNOPEN: case MENU_FILE_OPEN: { HANDLE hfCursor; TCHAR szFileTitle[MAX_PATH]; TCHAR szFile[MAX_PATH]; szFile[0] = TEXT('\0'); /* check for dirty file */ if(!CheckDirty(hWnd)) break; /* Put up the open file dialog and get the open handle back */ hfCursor = PromptAndOpenFile(hWnd, MAX_PATH, szFileTitle, COUNTOF(ganiAcon.szFile), szFile, gpszAniFilter); if (hfCursor == INVALID_HANDLE_VALUE) break; LoadAniFile(hWnd, hfCursor, szFileTitle, szFile ); break; } case DLG_MAIN_BTNSAVE: case MENU_FILE_SAVE: case MENU_FILE_SAVEAS: SaveFile(hWnd, cmd == MENU_FILE_SAVEAS); break; case MENU_FILE_INSERT: { TCHAR szFile[MAX_PATH]; szFile[0] = TEXT('\0'); /* Put up the open file dialog and get the open handle back */ if (PromptForFile(hWnd, 0, NULL, MAX_PATH, szFile, gpszCurFilter, gpszImport, FALSE)) { /* * If we got a file, open it and read the icon data, linking * it into the frame list and maintaining the steps as well. */ ganiAcon.fDirty = TRUE; CreateFrameFromCursorFile(hWnd, szFile, FALSE); } break; } case MENU_FILE_EXPORT: { #if 0 TCHAR szFile[MAX_PATH]; szFile[0] = TEXT('\0'); /* Put up the open file dialog and get the open handle back */ if (PromptForFile(hWnd, 0, NULL, MAX_PATH, szFile, NULL, gpszExport, TRUE)) { /* * If we got a file, open it and read the icon data, linking * it into the frame list and maintaining the steps as well. */ ???? } #else WRITEME(hWnd); #endif break; } case MENU_FILE_EXIT: ExitCommand(hWnd); break; case DLG_MAIN_BTNCUT: case MENU_EDIT_CUT: ganiAcon.fDirty = TRUE; FALLTHRU(MENU_EDIT_COPY); case DLG_MAIN_BTNCOPY: case MENU_EDIT_COPY: { int *piSel; int cSel; cSel = GetSelStepCount(hWnd); if( cSel > 0 && (piSel = AllocMem(cSel * sizeof(int))) != NULL) { PCLPBRDDAT pcbd, pcbdNext, *ppcbd; int i; GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, piSel, cSel, &cSel); /* Clear clipboard */ for( pcbd = gpbdClipBoard; pcbd != NULL; pcbd = pcbdNext ) { pcbdNext = pcbd->pcbdNext; DestroyClpBrdDat(pcbd); } /* * Get the steps and put them in the clipboard in the correct order */ ppcbd = &gpbdClipBoard; for( i = 0; i < cSel; i++ ) { PSTEP ps; ps = GetStep(hWnd, piSel[i]); if( IsValidPS(ps) && (pcbd = NewClpBrdDat()) != NULL) { CopyStep(&(pcbd->stp), ps); *ppcbd = pcbd; ppcbd = &(pcbd->pcbdNext); } } *ppcbd = NULL; /* * If this is a cut, then yank them out of the listbox */ if (cmd == MENU_EDIT_CUT || cmd == DLG_MAIN_BTNCUT) { qsort( piSel, cSel, sizeof(piSel[0]), RevCompInts ); for( i = 0; i < cSel; i++ ) { SendDlgItemMessage(hWnd, DLG_MAIN_FRAMELIST, LB_DELETESTRING, piSel[i], 0); } FreeMem(piSel); ClearStepSel(hWnd); } } break; } case DLG_MAIN_BTNPASTE: case MENU_EDIT_PASTE: { PCLPBRDDAT pcbd; int iSel, cSel; cSel = GetSelStepCount(hWnd); if (cSel > 1) { FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE, MSG_LESSEQONEFRAME); break; } GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, &iSel, 1, &cSel); if (cSel == 0) iSel = GetStepCount(hWnd) - 1; cSel = iSel; ganiAcon.fDirty = TRUE; for( pcbd = gpbdClipBoard; pcbd != NULL; pcbd = pcbd->pcbdNext ) { PSTEP ps = NewStep(); if (IsValidPS(ps)) { CopyStep(ps, &(pcbd->stp)); SendDlgItemMessage(hWnd, DLG_MAIN_FRAMELIST, LB_INSERTSTRING, ++cSel, (LPARAM)ps); } else { FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OKCANCEL | MB_ICONEXCLAMATION, TRUE, MSG_PASTEERR ); } } /* in this case, cSel is actually an index */ iSel += 1; ClearStepSel(hWnd); SetStepSel(hWnd, iSel, cSel); break; } case DLG_MAIN_DELFRAME: case MENU_EDIT_CLEAR: { int *piSel; int cSteps = GetSelStepCount(hWnd); int i; if (cSteps <= 0) //BUGBUG - should we put a message box up here? break; ganiAcon.fDirty = TRUE; piSel = AllocMem(cSteps * sizeof(int)); if (piSel == NULL) break; GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, piSel, cSteps, &cSteps); qsort( piSel, cSteps, sizeof(piSel[0]), RevCompInts ); for( i = 0; i < cSteps; i++ ) { SendDlgItemMessage(hWnd, DLG_MAIN_FRAMELIST, LB_DELETESTRING, piSel[i], 0); } FreeMem(piSel); ClearStepSel(hWnd); break; } case DLG_MAIN_DUPFRAME: case MENU_EDIT_DUP: /* copy */ /* paste */ ganiAcon.fDirty = TRUE; WRITEME(hWnd); break; case DLG_MAIN_EDITFRAME: case MENU_EDIT_EDITFRAME: case DLG_MAIN_ADDFRAME: case MENU_EDIT_ADDFRAME: { BOOL fEditFrame; ganiAcon.fDirty = TRUE; fEditFrame = (cmd == MENU_EDIT_EDITFRAME || cmd == DLG_MAIN_EDITFRAME); EditFrame(hWnd, fEditFrame); break; } case DLG_MAIN_STOP: PausePreview(hWnd, DLG_MAIN_PREVIEW); break; case DLG_MAIN_PLAY: ResumePreview(hWnd, DLG_MAIN_PREVIEW); break; case MENU_HELP_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(DLG_ABOUT), hWnd, About); break; case MENU_HELP_CONTENTS: //WinHelp(hWnd, TEXT("RKTOOLS.HLP"), HELP_COMMAND, (DWORD)TEXT("JI(\"RKTOOLS.HLP\">\"main\",\"aniedit\")")); //WinHelp(hWnd, TEXT("RKTOOLS.HLP"), HELP_COMMAND, (DWORD)TEXT("JI(\"RKTOOLS.HLP\",\"aniedit\")")); WinHelp(hWnd, TEXT("RKTOOLS.HLP"), HELP_COMMAND, (DWORD)TEXT("JI(\"RKTOOLS.HLP>main\",\"aniedit\")")); break; case MENU_EDIT_OPTIONS: if (DialogBox(hInst, MAKEINTRESOURCE(DLG_OPTIONS), hWnd, OptionsProc)){ InvalidateRect( GetDlgItem(hWnd, DLG_MAIN_PREVIEW), NULL, TRUE); } break; case DLG_MAIN_FRAMELIST: { HWND hwndLB = (HWND)lParam; switch(HIWORD(wParam)) { case LBN_SELCHANGE: { PSTEP ps; int cSel; LPTSTR pszText; cSel = SendMessage(hwndLB, LB_GETSELCOUNT, 0, 0); if (cSel > 1) { int *piSel; int i; pszText = FmtSprintf( cSel == GetStepCount(hWnd) ? MSG_ALLFRAMES : MSG_FRAMESSELECTED, cSel ); SetDlgItemText(hWnd, DLG_MAIN_FRAMEGRP, pszText); FmtFree( pszText ); piSel = AllocMem( cSel * sizeof(int) ); if( piSel == NULL ) break; GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, piSel, cSel, &cSel); for( i = 0; i < cSel; i++ ) { ps = GetStep(hWnd, piSel[i]); if( IsValidPS(ps) ) { if (i == 0) { ganiAcon.anih.jifRate = ps->jif; } else if(ganiAcon.anih.jifRate != ps->jif) { break; } } } if (i < cSel) { /* rates differ, wipe out jiffy edit control */ SetDlgItemText(hWnd, DLG_MAIN_RATE, ""); } else { SetDlgItemInt(hWnd, DLG_MAIN_RATE, ganiAcon.anih.jifRate, FALSE); } FreeMem(piSel); } else if (cSel == 1) { int iLBSel; GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, &iLBSel, 1, &cSel); SetPreviewStep(hWnd, DLG_MAIN_PREVIEW, iLBSel); pszText = FmtSprintf( MSG_FRAMEOFSEL, iLBSel + 1, GetStepCount(hWnd) ); SetDlgItemText(hWnd, DLG_MAIN_FRAMEGRP, pszText); FmtFree( pszText ); ps = (PSTEP)SendMessage(hwndLB, LB_GETITEMDATA, iLBSel, 0); if (IsValidPS(ps)) { SetDlgItemInt( hWnd, DLG_MAIN_RATE, ps->jif, FALSE); } } else { pszText = FmtSprintf( MSG_NOFRAMESSEL ); SetDlgItemText(hWnd, DLG_MAIN_FRAMEGRP, pszText); FmtFree( pszText ); SetPreviewStep(hWnd, DLG_MAIN_PREVIEW, 0); } break; case LBN_DBLCLK: ganiAcon.fDirty = TRUE; EditFrame(hWnd, TRUE); break; } } break; } case DLG_MAIN_RATE: { static BOOL fEditCtlHasFocus = FALSE; static BOOL fEditCtlHasChanged = FALSE; int *piSel; int cSteps; int i; switch(HIWORD(wParam)) { case EN_SETFOCUS: fEditCtlHasFocus = TRUE; break; case EN_KILLFOCUS: fEditCtlHasFocus = FALSE; break; case EN_CHANGE: cSteps = GetSelStepCount(hWnd); if (fEditCtlHasFocus && cSteps >=1 && GetWindowTextLength(GetDlgItem(hWnd, DLG_MAIN_RATE)) > 0) { JIF jif; BOOL fOK; ganiAcon.fDirty = TRUE; piSel = AllocMem( cSteps * sizeof(int) ); if (piSel == NULL) { SetFocus((HWND)lParam); break; } jif = GetDlgItemInt(hWnd, DLG_MAIN_RATE, &fOK, FALSE); if (jif == 0 || !fOK) { FmtMessageBox(hWnd, MSG_LITERAL, gszWindowTitle, MB_OK | MB_ICONEXCLAMATION, TRUE, MSG_RATERANGE); SetFocus((HWND)lParam); break; } GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, piSel, cSteps, &cSteps); for( i = 0; i < cSteps; i++ ) { PSTEP ps = GetStep(hWnd, piSel[i]); if (IsValidPS(ps)) { ps->jif = jif; } } InvalidateRect(GetDlgItem(hWnd,DLG_MAIN_FRAMELIST), NULL,TRUE); FreeMem( piSel ); } break; } break; } default: return FALSE; } return TRUE; } /****************************************************************************\ * * FUNCTION: About(HWND, unsigned, WORD, LONG) * * PURPOSE: Processes messages for "About" dialog box * * MESSAGES: * * WM_INITDIALOG - initialize dialog box * WM_COMMAND - Input received * * COMMENTS: * * No initialization is needed for this particular dialog box, but TRUE * must be returned to Windows. * * Wait for user to click on "Ok" button, then close the dialog box. * \****************************************************************************/ BOOL APIENTRY About( HWND hDlg, /* window handle of the dialog box */ UINT message, /* type of message */ UINT wParam, /* message-specific information */ LONG lParam) { switch (message) { case WM_INITDIALOG: /* message: initialize dialog box */ return (TRUE); case WM_COMMAND: /* message: received a command */ if (LOWORD(wParam) == IDOK /* "OK" box selected? */ || LOWORD(wParam) == IDCANCEL) { /*System menu close command?*/ EndDialog(hDlg, TRUE); /* Exits the dialog box */ return (TRUE); } break; } return (FALSE); /* Didn't process a message */ UNREFERENCED_PARAMETER(lParam); } /****************************************************************************\ * * FUNCTION: OptionsProc(HWND, unsigned, WORD, LONG) * * PURPOSE: Processes messages for "Options" dialog box * * MESSAGES: * * WM_INITDIALOG - initialize dialog box * WM_COMMAND - Input received * \****************************************************************************/ BOOL APIENTRY OptionsProc( HWND hDlg, /* window handle of the dialog box */ UINT message, /* type of message */ UINT wParam, /* message-specific information */ LONG lParam) { int i; int fRepaint = FALSE; switch (message) { case WM_INITDIALOG: /* message: initialize dialog box */ SendDlgItemMessage(hDlg, DLG_OPTIONS_EDITOR, EM_LIMITTEXT, MAX_PATH, 0); SetDlgItemText(hDlg, DLG_OPTIONS_EDITOR, gszCursorEditor); CheckRadioButton( hDlg, DLG_OPTIONS_RADIO_DESKCOL, DLG_OPTIONS_RADIO_WINCOL, garadColor[giradColor].id ); return (TRUE); case WM_COMMAND: /* message: received a command */ switch(LOWORD(wParam)) { case IDOK: /* * Get the new desk color */ for( i = 0; garadColor[i].id != 0; i++ ) { if( IsDlgButtonChecked(hDlg, garadColor[i].id) ) { break; } } if (i != giradColor ) { /* new color, make new brush and repaint */ if (ghbrPrevBackgnd != NULL) DeleteObject(ghbrPrevBackgnd); ghbrPrevBackgnd = CreateSolidBrush(GetSysColor(garadColor[i].idSys)); giradColor = i; fRepaint = TRUE; } /* * Get new editor */ GetDlgItemText(hDlg,DLG_OPTIONS_EDITOR, gszCursorEditor,COUNTOF(gszCursorEditor)); for( i = 0; i < COUNTOF(gszCursorEditor); i++ ) { if (gszCursorEditor[i] == TEXT('\0')) break; if (gszCursorEditor[i] == TEXT('%') && ++i < COUNTOF(gszCursorEditor) && gszCursorEditor[i] == TEXT('1')) { break; } #if defined(DBCS) && !defined(UNICODE) if (IsDBCSLeadByte(gszCursorEditor[i])) { i++; } #endif } if (i >= COUNTOF(gszCursorEditor) || gszCursorEditor[i] != TEXT('1')) { if (i >= (COUNTOF(gszCursorEditor) - 4)) { i = COUNTOF(gszCursorEditor) - 4; } lstrcpy(&gszCursorEditor[i], TEXT(" %1")); } case IDCANCEL: EndDialog(hDlg, fRepaint); /* Exits the dialog box */ return (TRUE); default: break; } break; } return (FALSE); /* Didn't process a message */ UNREFERENCED_PARAMETER(lParam); } /****************************************************************************\ * * FUNCTION: ExitCommand(HWND) * * PURPOSE: Exit the program chekcing for dirty files etc. * * \****************************************************************************/ VOID ExitCommand(HWND hWnd) { /* if file is dirty then prompt for save */ if(CheckDirty(hWnd)) AniEndDialog(hWnd, TRUE); } /****************************************************************************\ * * FUNCTION: CheckDirty(HWND) * * PURPOSE: check for dirty files and return TRUE if it is OK to continue. * * \****************************************************************************/ BOOL CheckDirty(HWND hWnd) { int idRet; /* if file is dirty then prompt for save */ if (ganiAcon.fDirty) { idRet = FmtMessageBox( hWnd, MSG_LITERAL, gszWindowTitle, MB_YESNOCANCEL | MB_ICONEXCLAMATION, TRUE, MSG_SAVEFILEQUEST, ganiAcon.szFile); switch( idRet ) { case IDYES: SaveFile(hWnd, FALSE); break; case IDNO: break; case IDCANCEL: return FALSE; } } return TRUE; } /****************************************************************************\ * * FUNCTION: HWND ExecProgram( HWND hwndCaller, LPTSTR pszCmdLine ) * * PURPOSE: Creates a process and returns the new processes main window * * RETURNS: NULL if the process could not be created, otherwise the * processes main window handle. * * SIDEEFFECT: This function will also start a thread that will block * on the process handle until the process terminates. At that * time, the thread will post a message back to the calliers * window. * * * History: * 22-Apr-1993 JonPa Created it * \****************************************************************************/ BOOL ExecProgram( HWND hwndCaller, LPTSTR pszCmdLine ) { STARTUPINFO si; PROCESS_INFORMATION pi; HWND hwnd; PTHDDATA pthd; DWORD tid; HANDLE hthrd; /* * Create the monitor thread (suspened) */ pthd = AllocMem(sizeof(THDDATA)); if (pthd == NULL) return FALSE; /* set thread data to be invalid incase we have to abort */ pthd->hprocMonitor = NULL; pthd->hwndCaller = hwndCaller; if ((hthrd = CreateThread( NULL, 0, ProcWaitThread, pthd, CREATE_SUSPENDED, &tid )) == NULL) { /* could not create the monitor thread, return error */ FreeMem(pthd); return FALSE; } /* * Create the process */ ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); si.wShowWindow = SW_SHOW; si.dwFlags = STARTF_USESHOWWINDOW; if (!CreateProcess( NULL, pszCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { ResumeThread(hthrd); // make thread localfree the data and exit return FALSE; } DPRINT(("MT:Child IDs proc/thd: 0x%lx / 0x%lx\n", pi.dwProcessId, pi.dwThreadId)); DPRINT(("MT:Child Hnd proc/thd: 0x%lx / 0x%lx\n", pi.hProcess, pi.hThread)); /* * Wait for the main window to be created */ if( WaitForInputIdle( pi.hProcess, CMS_WAIT_FOR_PROCESS ) != 0 ) { ResumeThread(hthrd); // make thread localfree the data and exit return FALSE; } DPRINT(("MT:Child is idle\n")); /* * Enumerate the new processes main thread's windows and * return the main one. */ hwnd = NULL; EnumThreadWindows( pi.dwThreadId, ETWProc, (LPARAM)&hwnd ); #if 0 if (hwnd != NULL) { pthd->hprocMonitor = pi.hProcess; pthd->hwndMonitor = hwnd; SendMessage(hwndCaller, AIM_SETCHILDAPP, 0, hwnd); } #else pthd->hprocMonitor = pi.hProcess; pthd->hwndMonitor = hwnd; if (pthd->hprocMonitor != NULL) SendMessage(hwndCaller, AIM_SETCHILDAPP, 0, (LPARAM)hwnd); #endif ResumeThread(hthrd); CloseHandle(hthrd); CloseHandle(pi.hThread); return TRUE; } /****************************************************************************\ * * FUNCTION: BOOL CALLBACK ETWProc( HWND hwnd, LPARAM lParam ) * * PURPOSE: Enumeration proc for ExecProgram. It looks for the thread's * top level window. * * History: * 22-Apr-1993 JonPa Created it * \****************************************************************************/ BOOL CALLBACK ETWProc( HWND hwnd, LPARAM lParam ) { DWORD *pdw = (DWORD *)lParam; /* * If this window has no parent, then it is a toplevel * window for the thread. Remember the last one we find since it * is probably the main window. */ if (GetParent(hwnd) == NULL) { DPRINT(("MT:EnumThdWin found 0x%lx\n", (DWORD)hwnd)); *pdw = (DWORD)hwnd; } return TRUE; } /****************************************************************************\ * * FUNCTION: DWORD ProcWaitThread( LPDWORD lpdw ) * * PURPOSE: Thread to wait on a process and then post a message * * * History: * 22-Apr-1993 JonPa Created it * \****************************************************************************/ DWORD WINAPI ProcWaitThread( LPVOID lpv ) { LPDWORD lpdw = lpv; PTHDDATA pthd = (PTHDDATA)lpdw; DWORD dwRet; if (pthd->hprocMonitor == NULL) { /* something went wrong, just exit now */ DPRINT(("wt:Aborting\n")); FreeMem( lpdw ); ExitThread(0); } DPRINT(("wt:Waiting\n")); dwRet = WaitForSingleObject( pthd->hprocMonitor, INFINITE ); DPRINT(("wt:Send AIM_PROCESSTERM\n")); SendMessage(pthd->hwndCaller, AIM_PROCESSTERM, (dwRet == WAIT_OBJECT_0), (LPARAM)pthd->hwndMonitor); CloseHandle( pthd->hprocMonitor ); FreeMem( lpdw ); ExitThread(0); return 0; } /****************************************************************************\ * * FUNCTION: void NewAniCursor( HWND hwnd ) * * PURPOSE: erase any used memory and init to a clean slate * * * History: * 22-Apr-1993 JonPa Created it * \****************************************************************************/ void NewAniCursor( HWND hwnd ) { int i, cSteps; LPTSTR psz; PausePreview(hwnd, DLG_MAIN_PREVIEW); /* Step through the list box, deleting all the lb entryies and everything * that they point to (except the icons). */ cSteps = GetStepCount(hwnd); if (cSteps != LB_ERR) { for( i = 0; i < cSteps; i++ ) { /* * Delete the top item of the list. Note that once that item * (current index 0) is deleted, then the next item will move * up and become index 0. */ SendDlgItemMessage( hwnd, DLG_MAIN_FRAMELIST, LB_DELETESTRING,0,0); } } /* * Step through the icon list deleting them. We don't need to call * DestroyFrame since we are trashing the whole chain. */ #if 0 pf = gpfrmFrames; gpfrmFrames = NULL; DON'T DO THIS!!! it will wipe out the clip board accidentally! for(; pf != NULL; pf = pfrmNext ) { pfrmNext = pf->pfrmNext; DestroyIcon( pf->hcur ); FreeMem(pf); } #endif /* * Init Ani header */ ZeroMemory( &ganiAcon, sizeof(ganiAcon) ); ganiAcon.anih.cbSizeof = sizeof(ganiAcon); ganiAcon.anih.cbSizeof = AF_ICON; ganiAcon.anih.jifRate = 10; SetDlgItemTextA(hwnd, DLG_MAIN_TITLE, ganiAcon.azTitle); SetDlgItemTextA(hwnd, DLG_MAIN_AUTHOR, ganiAcon.azCreator); SetDlgItemInt( hwnd, DLG_MAIN_RATE, ganiAcon.anih.jifRate, FALSE); PreviewCursor(hwnd, DLG_MAIN_PREVIEW); SetWindowFileTitle(hwnd, gpszUntitled ); psz = FmtSprintf(MSG_NOFRAMESSEL); SetDlgItemText(hwnd, DLG_MAIN_FRAMEGRP, psz); FmtFree( psz ); } /****************************************************************************\ * * FUNCTION: BOOL GetCurrentSel( HWND hwnd, int id, int * paiSel, * int ciSel, int *pcSel ); * * PURPOSE: Gets the selections and returns it's index * * * History: * 22-Apr-1993 JonPa Created it * \****************************************************************************/ BOOL GetCurrentSel( HWND hwnd, int id, int * paiSel, int ciSel, int *pcSel ) { #ifdef MULTISEL *pcSel = SendDlgItemMessage(hwnd,id, LB_GETSELITEMS, ciSel,(LPARAM)paiSel); if (*pcSel == LB_ERR) { *pcSel = 0; } #else *paiSel = SendDlgItemMessage(hwnd, id, LB_GETCURSEL, 0, 0); *pcSel = 1; if (*paiSel == LB_ERR) *pcSel = 0; #endif return TRUE; } /****************************************************************************\ * * FUNCTION: VOID SetCurrentSel( HWND hwnd, int id, BOOL fExtend, int iSel); * * PURPOSE: Sets the selections and returns it's index * * * History: * 29-Apr-1993 JonPa Created it * \****************************************************************************/ VOID SetCurrentSel( HWND hwnd, int id, BOOL fExtend, int iSel) { #ifdef MULTISEL if (!fExtend) { SendDlgItemMessage(hwnd, id, LB_SETSEL, FALSE, -1); } SendDlgItemMessage(hwnd, id, LB_SETSEL, TRUE, iSel); #else SendDlgItemMessage(hwnd, id, LB_SETCURSEL, iSel, 0); #endif UpdateStepSel( hwnd ); } /****************************************************************************\ * * FUNCTION: VOID EditFrame(HWND hwnd, int iSel); * * PURPOSE: Runs ImagEdit on the frame indexed by iSel * * * History: * 27-Apr-1993 JonPa * \****************************************************************************/ VOID EditFrame(HWND hWnd, BOOL fEditFrame) { LPTSTR pszCmdLine = NULL; int cchCmdLine; HANDLE hf; DWORD cb; PBYTE pbIcon; DWORD cbIcon; int iSel; int cSel; BOOL fExeced; /* create a temp .cur file name */ if( !GetTempCursorFileName( gszTempFile ) ) { FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE, MSG_OUTOFRESOUCES ); return; } cSel = GetSelStepCount(hWnd); if ( (fEditFrame && (cSel != 1)) || cSel > 1 ) { FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE, fEditFrame ? MSG_MUSTEQONEFAME : MSG_LESSEQONEFRAME); return; } /* cache the currently selected item (Singluar) */ GetCurrentSel( hWnd, DLG_MAIN_FRAMELIST, &iSel, 1, &cSel ); /* * If edit, then write the frame to the file and save checksum * otherwise write the blank cursor to the file. */ hf = CreateFile( gszTempFile, 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, gszTempFile ); return; } if (fEditFrame || cSel != 0) { PSTEP ps = GetStep(hWnd, iSel); if( !IsValidPS(ps) ) { FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE, MSG_OUTOFRESOUCES ); CloseHandle(hf); return; } pbIcon = ps->pfrmFrame->abIcon; cbIcon = ps->pfrmFrame->rtag.ckSize; } else { HRSRC hr = FindResource(hInst, MAKEINTRESOURCE(ID_BLANKCUR), MAKEINTRESOURCE(RCT_RAWDATA)); if (hr == NULL || (pbIcon =LockResource(LoadResource(hInst, hr))) == NULL) { FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE, MSG_OUTOFRESOUCES ); CloseHandle(hf); return; } cbIcon = SizeofResource(hInst, hr); } WriteFile(hf, pbIcon, cbIcon, &cb, NULL); CloseHandle(hf); /* * change .tmp to .cur */ { TCHAR szOldName[MAX_PATH]; cchCmdLine = lstrlen(gszTempFile); lstrcpy( szOldName, gszTempFile ); lstrcpy( &gszTempFile[cchCmdLine - 3], gpszCUR ); if(!MoveFile(szOldName, gszTempFile)) lstrcpy( gszTempFile, szOldName ); cchCmdLine = (cchCmdLine + lstrlen(gszCursorEditor) + 1 + 1) * sizeof(TCHAR); pszCmdLine = AllocMem(cchCmdLine); } if (pszCmdLine == NULL) return; { LPTSTR pszTempFile = gszTempFile; FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, gszCursorEditor, 0, 0, pszCmdLine, cchCmdLine, (va_list *)(DWORD)&pszTempFile); } /* spawn imagedit on the file */ fExeced = ExecProgram( hWnd, pszCmdLine ); DPRINT(("MT:Begin Defer to child\n")); FreeMem(pszCmdLine); if ( fExeced ) { gfEditFrame = fEditFrame; } else { FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP, TRUE, MSG_NOIMAGEDIT, gszCursorEditor ); } } /****************************************************************************\ * * FUNCTION: PSTEP NewStep( void ); * * * PURPOSE: Creates a new step and set's its pfrmFrame to NULL; * * * History: * 29-Apr-1993 JonPa Created it * \****************************************************************************/ PSTEP NewStep( void ) { PSTEP ps; ps = AllocMem(sizeof(STEP)); if (IsValidPS(ps)) ps->pfrmFrame = NULL; return ps; } /****************************************************************************\ * * FUNCTION: VOID DestroyStep( PSTEP ps ); * * * PURPOSE: Deletes a step, and derefernces its frame, deleting it if * necessary. * * History: * 29-Apr-1993 JonPa Created it * \****************************************************************************/ VOID DestroyStep( PSTEP ps ) { LinkStepFrame(ps, NULL); FreeMem(ps); } /****************************************************************************\ * * FUNCTION: VOID CopyStep( PSTEP psDst, PSTEP psSrc ); * * * PURPOSE: Copyies a step, bumping the ref count of the frame if it * needs it. * * History: * 07-May-1993 JonPa Created it * \****************************************************************************/ VOID CopyStep( PSTEP psDst, PSTEP psSrc ) { *psDst = *psSrc; if( psDst->pfrmFrame != NULL ) { psDst->pfrmFrame->cRef += 1; } } /****************************************************************************\ * * FUNCTION: VOID LinkStepFrame( PSTEP ps, PFRAME pf ); * * * PURPOSE: Unlinks a step from its frame and then links the new * frame in its place. If the old frame is an orphan, it * gets destroyed. * * * History: * 29-Apr-1993 JonPa Created it * \****************************************************************************/ VOID LinkStepFrame(PSTEP ps, PFRAME pf ) { PFRAME pfOld = ps->pfrmFrame; if (pf != NULL) pf->cRef++; if (pfOld != NULL && --(pfOld->cRef) == 0) DestroyFrame(pfOld); ps->pfrmFrame = pf; } /****************************************************************************\ * * FUNCTION: VOID DestroyFrame( PFRAME pf ); * * * PURPOSE: Unlinks a frame from the list, deletes its hcur, and * Frees its memory. * * * History: * 28-Apr-1993 JonPa Created it * \****************************************************************************/ VOID DestroyFrame( PFRAME pf ) { PFRAME pfList; if (pf == gpfrmFrames) { gpfrmFrames = pf->pfrmNext; } else { for( pfList = gpfrmFrames; pfList != NULL; pfList = pfList->pfrmNext ) { if (pfList->pfrmNext == pf) { break; } } if (pfList != NULL) { pfList->pfrmNext = pf->pfrmNext; } } DestroyIcon( pf->hcur ); FreeMem(pf); } /****************************************************************************\ * * FUNCTION: PCLPBRDDAT NewClpBrdDat( void ) * * * PURPOSE: Creates a new clip board data struct * * * History: * 29-Apr-1993 JonPa Created it * \****************************************************************************/ PCLPBRDDAT NewClpBrdDat( void ) { PCLPBRDDAT pcbd = AllocMem( sizeof(CLPBRDDAT) ); if (pcbd != NULL) pcbd->stp.pfrmFrame = NULL; return pcbd; } /****************************************************************************\ * * FUNCTION: VOID DestroyClpBrdDat(PCLPBRDDAT pcbd) * * * PURPOSE: Creates a new clip board data struct * * * History: * 29-Apr-1993 JonPa Created it * \****************************************************************************/ VOID DestroyClpBrdDat(PCLPBRDDAT pcbd) { LinkStepFrame(&(pcbd->stp), NULL); FreeMem(pcbd); } /****************************************************************************\ * * FUNCTION: VOID SetWindowFileTitle(HWND hWnd, LPTSTR szFileTitle) * * * PURPOSE: Sets the file title * * * History: * 30-Apr-1993 JonPa Created it * \****************************************************************************/ VOID SetWindowFileTitle(HWND hWnd, LPTSTR szFileTitle) { /* * We use LocalAlloc here instead of AllocMem because we don't really * char if it fails */ int cch = lstrlen( gszWindowTitle ) + lstrlen(szFileTitle); LPTSTR pszTitle = LocalAlloc(LPTR, (cch+4) * sizeof(TCHAR) ); if (pszTitle != NULL) { wsprintf( pszTitle, "%s - %s", gszWindowTitle, szFileTitle ); SetWindowText(hWnd, pszTitle); LocalFree(pszTitle); } else { SetWindowText(hWnd, gszWindowTitle); } } int __cdecl RevCompInts(const void *elm1, const void *elm2) { return *((int *)elm2) - *((int *)elm1); } /****************************************************************************\ * * FUNCTION: ClearStepSel * * * PURPOSE: Clears all selections from the frame list * * * History: * 02-Jul-1993 JonPa Created it * \****************************************************************************/ VOID ClearStepSel( HWND hWnd ) { int cItems = GetStepCount(hWnd); if (cItems != 0) { SendDlgItemMessage(hWnd, DLG_MAIN_FRAMELIST, LB_SELITEMRANGE, (WPARAM)FALSE, MAKELPARAM(0, cItems - 1)); } UpdateStepSel(hWnd); }