reman3/Rayman_X/cpa/Appli/WinS2B/App.cpp

951 lines
32 KiB
C++

//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// FILE : App.cpp
// AUTHOR : Catalin Cocos
//__________________________________________________________________________________________________
#include "stdinc.h"
#include "app.h"
#include "resource.h"
#include "list.h"
#include "Tree.h"
#include "Process.h"
CScr2bin CnvEng; // the file converter
HWND hWApp; // the application main window
HWND hWToolbar; // the toolbar
HWND hWStatusbar; // the Statusbar
HWND hWList; // the collection file list
HWND hWTree; // the tree view
HWND hWListView; // the list view
HWND hWOut; // the output window
HWND hWFilter; // the Filter list view
int FILTER_WIDTH;
HINSTANCE hInstance; // the current instance
int ToolbarHeight; // the height of the toolbar
int StatusHeight; // the height of the status bar
char CrtCfg[MAX_PATH];
float SplitX = .3f;
float SplitY = .2f;
int nFocusWnd = 0;
int SplitDrag = FALSE, SplitMode;
enum { SD_VERTICAL = 0x01, SD_HORIZONTAL = 0x02, SD_FILTER = 0x04};
BOOL Active = TRUE;
// operating:
int OperatingMode = ID_MODE_NORMAL;
BOOL volatile Processing = FALSE;
int OperatingState = -1;
BOOL ProcessingState = TRUE;
BOOL FilterActive = FALSE;
void OnIdle()
{
if(FilterActive != CnvEng.IsFilteringActive())
{
FilterActive = !FilterActive;
HMENU hMenu = GetSubMenu(GetMenu( hWApp ), 3);
CheckMenuItem( hMenu, ID_MODE_FILTER, FilterActive? MF_CHECKED: MF_UNCHECKED);
SendMessage( hWToolbar, TB_CHECKBUTTON, ID_MODE_FILTER, FilterActive? TRUE: FALSE);
}
if(Processing != ProcessingState)
{
ProcessingState = Processing;
UINT state = (Processing? MF_GRAYED: MF_ENABLED);
HMENU hMenu = GetSubMenu(GetMenu( hWApp ), 3);
EnableMenuItem( hMenu, ID_MODE_NORMAL, state);
EnableMenuItem( hMenu, ID_MODE_FORCED, state);
EnableMenuItem( hMenu, ID_MODE_CLEAN, state);
EnableMenuItem( hMenu, ID_MODE_FILTER, state);
hMenu = GetSubMenu(GetMenu( hWApp ), 2);
EnableMenuItem( hMenu, ID_ACTION_PROCESS_LISTS, state);
EnableMenuItem( hMenu, ID_ACTION_PROCESS_SELECTION, state);
EnableMenuItem( hMenu, ID_ACTION_PROCESS_ALL, state);
EnableMenuItem( hMenu, ID_ACTION_PROCESS_CANCEL, Processing? MF_ENABLED: MF_GRAYED);
state = (Processing? FALSE: TRUE);
SendMessage( hWToolbar, TB_ENABLEBUTTON, ID_MODE_NORMAL, state);
SendMessage( hWToolbar, TB_ENABLEBUTTON, ID_MODE_FORCED, state);
SendMessage( hWToolbar, TB_ENABLEBUTTON, ID_MODE_CLEAN, state);
SendMessage( hWToolbar, TB_ENABLEBUTTON, ID_MODE_FILTER, state);
SendMessage( hWToolbar, TB_ENABLEBUTTON, ID_ACTION_PROCESS_LISTS, state);
SendMessage( hWToolbar, TB_ENABLEBUTTON, ID_ACTION_PROCESS_SELECTION, state);
SendMessage( hWToolbar, TB_ENABLEBUTTON, ID_ACTION_PROCESS_ALL, state);
SendMessage( hWToolbar, TB_ENABLEBUTTON, ID_ACTION_PROCESS_CANCEL, !state);
int listCount = ListView_GetItemCount( hWFilter );
LV_ITEM filterItem = { LVIF_STATE, 0, 0, (Processing && CnvEng.IsFilteringActive())? LSTATE_LOCKED: 0, LSTATE_LOCKED };
for(filterItem.iItem = 0; filterItem.iItem<listCount; filterItem.iItem++)
ListView_SetItem( hWFilter, &filterItem);
if(!Processing)
{
SendMessage( hWToolbar, TB_CHECKBUTTON, ID_ACTION_PROCESS_LISTS, FALSE);
SendMessage( hWToolbar, TB_CHECKBUTTON, ID_ACTION_PROCESS_SELECTION, FALSE);
SendMessage( hWToolbar, TB_CHECKBUTTON, ID_ACTION_PROCESS_ALL, FALSE);
}
}
if(OperatingState != OperatingMode)
{
OperatingState = OperatingMode;
HMENU hMenu = GetSubMenu(GetMenu( hWApp ), 3);
CheckMenuItem( hMenu, ID_MODE_NORMAL, OperatingMode==ID_MODE_NORMAL? MF_CHECKED: MF_UNCHECKED);
CheckMenuItem( hMenu, ID_MODE_FORCED, OperatingMode==ID_MODE_FORCED? MF_CHECKED: MF_UNCHECKED);
CheckMenuItem( hMenu, ID_MODE_CLEAN, OperatingMode==ID_MODE_CLEAN? MF_CHECKED: MF_UNCHECKED);
SendMessage( hWToolbar, TB_CHECKBUTTON, ID_MODE_NORMAL, OperatingMode==ID_MODE_NORMAL? TRUE: FALSE);
SendMessage( hWToolbar, TB_CHECKBUTTON, ID_MODE_FORCED, OperatingMode==ID_MODE_FORCED? TRUE: FALSE);
SendMessage( hWToolbar, TB_CHECKBUTTON, ID_MODE_CLEAN, OperatingMode==ID_MODE_CLEAN? TRUE: FALSE);
}
}
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// configuration
//__________________________________________________________________________________________________
LRESULT CALLBACK AppWndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
static BOOL bRefresh = TRUE;
switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wp))
{
case ID_MODE_FILTER: CnvEng.SetFiltering(!CnvEng.IsFilteringActive()); break;
case ID_MODE_NORMAL:
case ID_MODE_FORCED:
case ID_MODE_CLEAN:
OperatingState = -1;
OperatingMode = LOWORD(wp);
break;
case ID_NEXT_WINDOW: nFocusWnd+=2;
case ID_PREV_WINDOW: nFocusWnd+=4;
nFocusWnd%=5;
RestoreFocus();
break;
case ID_FILEOPEN:
{
bRefresh = FALSE;
char filename[_MAX_PATH] = "";
OPENFILENAME ofn ={sizeof(OPENFILENAME),hWApp,hInstance,
"Configuration files (*.s2b)\0*.s2b\0",NULL,0,0,filename,_MAX_PATH,NULL,0,NULL,"Load Configuration",
OFN_FILEMUSTEXIST,0,NULL,NULL,0,NULL,NULL};
if(GetOpenFileName(&ofn))
{
SaveConfiguration();
strcpy(CrtCfg, filename);
LoadConfiguration();
Refresh();
UpdateAppName();
}
}
break;
case ID_FILESAVEAS:
{
bRefresh = FALSE;
char filename[_MAX_PATH] = "";
OPENFILENAME ofn ={sizeof(OPENFILENAME),hWApp,hInstance,
"Configuration files (*.s2b)\0*.s2b\0",NULL,0,0,filename,_MAX_PATH,NULL,0,NULL,"Save Configuration As...",
0,0,NULL,"s2b",0,NULL,NULL};
if(GetSaveFileName(&ofn))
{
strcpy(CrtCfg, filename);
SaveConfiguration();
UpdateAppName();
}
}
case ID_FILESAVE: SaveConfiguration(); break;
break;
case ID_FILE_EXIT: PostMessage( hwnd, WM_CLOSE, 0,0); break;
case ID_EDIT_MARK:
if(GetFocus())
PostMessage( GetFocus(), WM_COMMAND, ID_SELECT_TOGGLE, 0);
break;
case ID_EDIT_RECURSE:
break;
case ID_EDIT_INSERT_LIST:
{
bRefresh = FALSE;
char filename[_MAX_PATH] = "";
OPENFILENAME ofn ={sizeof(OPENFILENAME),NULL,hInstance,
"Collection files (*.txt, *.log)\0*.txt;*.log\0",NULL,0,0,filename,_MAX_PATH,NULL,0,NULL,"Load Configuration",
OFN_FILEMUSTEXIST,0,NULL,NULL,0,NULL,NULL};
if(GetOpenFileName(&ofn))
InsertCollectionFile(hWList, filename);
}
break;
case ID_EDIT_REMOVE_ALL_LISTS: DeleteCollectionList(); break;
case ID_EDIT_CLEARSEL: CleanSelection(); break;
case ID_EDIT_CLEARALL: DeleteCollectionList(); CleanSelection(); break;
case ID_ACTION_PROCESS_LISTS: Process(PROCESS_COLLECTIONS); break;
case ID_ACTION_PROCESS_SELECTION: Process(PROCESS_SELECTION); break;
case ID_ACTION_PROCESS_ALL: Process(PROCESS_ALL); break;
case ID_ACTION_PROCESS_CANCEL: StopProcessing(); break;
default: return DefWindowProc(hwnd, msg, wp, lp);
}
break;
case WM_MOUSEMOVE:
if(SplitDrag)
{
RECT r;
GetClientRect( hWApp, &r);
if(SplitMode & SD_HORIZONTAL)
SplitY = ((float)HIWORD(lp) - ToolbarHeight)/(r.bottom - ToolbarHeight - StatusHeight);
if(SplitMode & SD_VERTICAL)
SplitX = ((float)LOWORD(lp) - FILTER_WIDTH - 3)/(r.right - FILTER_WIDTH -3);
if(SplitMode & SD_FILTER)
FILTER_WIDTH = LOWORD(lp) - 1;
PositionChildwindows();
}
else
{
SplitMode = 0;
RECT r;
GetClientRect( hWApp, &r);
int xSplit = (int)((r.right - FILTER_WIDTH -3)*SplitX) + FILTER_WIDTH + 3;
int ySplit = (int)((r.bottom - ToolbarHeight - StatusHeight )*SplitY) + ToolbarHeight;
if(LOWORD(lp)-FILTER_WIDTH < 3) SplitMode |= SD_FILTER;
if(abs(xSplit - LOWORD(lp)) < 2) SplitMode |= SD_VERTICAL;
if(abs(abs(ySplit - HIWORD(lp))) < 2) SplitMode |= SD_HORIZONTAL;
switch(SplitMode)
{
case SD_FILTER:
case SD_VERTICAL: SetCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDC_VERTICAL_SPLIT))); break;
case SD_HORIZONTAL: SetCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDC_HORIZONTAL_SPLIT))); break;
default: SetCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDC_SPLIT_ALL)));
}
}
break;
case WM_NCLBUTTONUP:
case WM_NCMOUSEMOVE:
pListTip->Show( NULL, NULL);
return DefWindowProc(hwnd, msg, wp, lp);
case WM_LBUTTONDOWN:
{
SplitDrag = TRUE;
RECT r;
GetClientRect( hWApp, &r);
r.top += ToolbarHeight;
r.bottom-=StatusHeight;
if(SplitMode & SD_FILTER);// r.right -= 6;
else r.left = FILTER_WIDTH + 4;
MapWindowPoints( hwnd, NULL, (LPPOINT) &r, 2);
SetCapture( hwnd );
ClipCursor( &r );
}
break;
case WM_LBUTTONUP:
SplitDrag = FALSE;
ReleaseCapture();
ClipCursor( NULL );
break;
case WM_SIZING:
{ // main window size control
RECT* lprc = (LPRECT) lp;
if(lprc->right - lprc->left < MIN_CLIENTX )
if(wp == WMSZ_LEFT || wp == WMSZ_BOTTOMLEFT || wp == WMSZ_TOPLEFT)
lprc->left -= MIN_CLIENTX + lprc->left - lprc->right;
else lprc->right += MIN_CLIENTX + lprc->left - lprc->right;
if(lprc->bottom - lprc->top < MIN_CLIENTY )
if(wp == WMSZ_TOP || wp == WMSZ_TOPLEFT || wp == WMSZ_TOPRIGHT)
lprc->top -= MIN_CLIENTY + lprc->top - lprc->bottom;
else lprc->bottom += MIN_CLIENTY + lprc->top - lprc->bottom;
}
break;
case WM_SIZE:
{ // toolbar/statusbar repositioning
SendMessage(hWStatusbar, WM_SIZE, wp, lp);
SendMessage(hWToolbar, WM_SIZE, wp, lp);
PositionChildwindows();
}
break;
case WM_CLOSE:
if(!Processing)
{
SaveConfiguration(); // save the current configuration
DestroyWindow( hwnd ); // default processing
}
else MessageBox( hwnd, "You cannot close the application while processing.\n\rPlease choose the Cancel Processing command before closing the application",
"Script Converter", MB_ICONHAND|MB_OK);
break;
case WM_DESTROY:
Active = FALSE;
PostQuitMessage(0);
break;
case WM_NOTIFY:
switch(((LPNMHDR)lp)->code)
{
case TTN_NEEDTEXT:
{
LPTOOLTIPTEXT lpttt;
lpttt = (LPTOOLTIPTEXT) lp;
lpttt->hinst = hInstance;
switch ( lpttt->hdr.idFrom)
{
// set the needed tooltip text (for the toolbar)
case ID_FILEOPEN: lpttt->lpszText = "Open a previously saved Configuration file (Ctrl+O) "; break;
case ID_FILESAVE: lpttt->lpszText = "Save the current Configuration (Ctrl+S)"; break;
case ID_FILESAVEAS: lpttt->lpszText = "Save the current Configuration using a new name (Shft+S)"; break;
case ID_EDIT_INSERT_LIST: lpttt->lpszText = "Insert Collections"; break;
case ID_EDIT_REMOVE_ALL_LISTS: lpttt->lpszText = "Clear Collection List"; break;
case ID_EDIT_CLEARSEL: lpttt->lpszText = "Clear Selection"; break;
case ID_EDIT_CLEARALL: lpttt->lpszText = "Clear all (both collections and selection)"; break;
case ID_ACTION_PROCESS_LISTS: lpttt->lpszText = "Process Collection List (F7)"; break;
case ID_ACTION_PROCESS_SELECTION: lpttt->lpszText = "Process current selection (Shft+F7)"; break;
case ID_ACTION_PROCESS_ALL: lpttt->lpszText = "Process all (both collection list and selection) (Ctrl+F7)"; break;
case ID_ACTION_PROCESS_CANCEL: lpttt->lpszText = "Cancel Processing (Esc)"; break;
case ID_MODE_NORMAL: lpttt->lpszText = "Standard mode (process out-of-date files)"; break;
case ID_MODE_FORCED: lpttt->lpszText = "Forced mode (forced conversion of all selected files)"; break;
case ID_MODE_CLEAN: lpttt->lpszText = "Clean-up mode (delete the corresponding binary files)"; break;
case ID_MODE_FILTER: lpttt->lpszText = "Toggle Filtered Processing"; break;
default: return DefWindowProc(hwnd, msg, wp, lp);
}
}
break;
case TVN_SELCHANGED:
if(Active) DisplayView( ((NM_TREEVIEW*)lp)->itemNew.hItem, (CDirInfo*)((NM_TREEVIEW*)lp)->itemNew.lParam );
break;
case TVN_GETDISPINFO:
{
TV_DISPINFO *ptvdi = (TV_DISPINFO *)lp;
char fName[_MAX_PATH+10];
strcpy(fName, ((CDirInfo*)ptvdi->item.lParam)->FileName());
strcat(fName, "\\*.*");
WIN32_FIND_DATA fd;
ptvdi->item.cChildren = 0;
HANDLE hSearch = FindFirstFile( fName, &fd );
for(BOOL Found = (hSearch != INVALID_HANDLE_VALUE); Found; Found = FindNextFile( hSearch, &fd))
if((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (fd.cFileName[0] != '.'))
{
ptvdi->item.cChildren = 1;
break;
}
if( hSearch != INVALID_HANDLE_VALUE ) FindClose( hSearch );
}
break;
case TVN_DELETEITEM:
delete (CDirInfo*)((NM_TREEVIEW*)lp)->itemOld.lParam;
break;
case TVN_ITEMEXPANDED:
{
NM_TREEVIEW* pnmtv = (NM_TREEVIEW *) lp;
if(pnmtv->action == TVE_COLLAPSE)
{
HTREEITEM hItem, hPrevItem = NULL;
for( hItem = TreeView_GetChild(hWTree, pnmtv->itemNew.hItem); hItem; )
{
TV_ITEM ti = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hItem, 0, ~0 };
TreeView_GetItem( hWTree, &ti);
if((ti.state & TVIS_EXPANDED) ||
(ti.state & TVIS_OVERLAYMASK) ||
((ti.state & TVIS_STATEIMAGEMASK) == TI_STATE_FILES) ||
((ti.state & TVIS_STATEIMAGEMASK) == TI_STATE_RECURSE)
||((CDirInfo*)ti.lParam)->GetSize())
{
hItem = TreeView_GetNextSibling( hWTree, hPrevItem = hItem );
continue;
}
TreeView_DeleteItem( hWTree, hItem);
hItem =(hPrevItem?
TreeView_GetNextSibling( hWTree, hPrevItem ):
TreeView_GetChild(hWTree, pnmtv->itemNew.hItem));
}
}
}
break;
case TVN_ITEMEXPANDING:
if(((NM_TREEVIEW*)lp)->action == TVE_EXPAND)
SetTreeItemChildren(&((NM_TREEVIEW*)lp)->itemNew);
break;
default:
switch(((NMHDR*)lp)->idFrom)
{
case IDW_LIST:
{
NM_LISTVIEW* pList = (NM_LISTVIEW*) lp;
if(IsWindowVisible(hWList) && pList->hdr.code == LVN_ITEMCHANGED && pList->uNewState & LVIS_FOCUSED )
PostMessage( hWList, WM_USER+10, pList->iItem, 0);
}
break;
default: return DefWindowProc(hwnd, msg, wp, lp);
}
}
break;
case WM_ACTIVATE:
if(LOWORD(wp) != WA_INACTIVE )
{
//refresh the app;
if( bRefresh )
{
Active = FALSE;
Refresh();
Active = TRUE;
}
bRefresh = TRUE;
RestoreFocus();
}
break;
default:return DefWindowProc(hwnd, msg, wp, lp);
}
return 0;
}
void MakeToolbar( HWND hwnd )
{
TBBUTTON but[] ={//{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0}, // the buttons
{29,ID_MODE_FILTER,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0},
{STD_FILEOPEN,ID_FILEOPEN,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{STD_FILESAVE,ID_FILESAVE,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{15,ID_FILESAVEAS,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0},
{20,ID_EDIT_INSERT_LIST,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0},
{21,ID_EDIT_REMOVE_ALL_LISTS,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{23,ID_EDIT_CLEARSEL,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{24,ID_EDIT_CLEARALL,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0},
{17,ID_ACTION_PROCESS_LISTS,TBSTATE_ENABLED,TBSTYLE_CHECK,0,0},
{18,ID_ACTION_PROCESS_SELECTION,TBSTATE_ENABLED,TBSTYLE_CHECK,0,0},
{19,ID_ACTION_PROCESS_ALL,TBSTATE_ENABLED,TBSTYLE_CHECK,0,0},
{16,ID_ACTION_PROCESS_CANCEL,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0},
{25,ID_MODE_NORMAL,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{26,ID_MODE_FORCED,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
{27,ID_MODE_CLEAN,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0},
};
hWToolbar= CreateToolbarEx(hwnd,WS_VISIBLE|WS_CHILD|TBSTYLE_TOOLTIPS,IDW_TOOLBAR,0, // create the toolbar
hInstance,NULL,but,20,18,18,16,15,sizeof(TBBUTTON));
TBADDBITMAP bit={HINST_COMMCTRL,IDB_STD_SMALL_COLOR}; // standard button bitmats
SendMessage(hWToolbar,TB_ADDBITMAP,16,(LPARAM)&bit); // add standard bitmaps
bit.hInst = hInstance;
bit.nID = IDB_TOOLBAR; // our button bitmaps
SendMessage(hWToolbar,TB_ADDBITMAP,34,(LPARAM)&bit); // add our bitmaps
}
void PositionChildwindows()
{
RECT r;
GetClientRect( hWApp, &r);
r.right -= FILTER_WIDTH + 3;
int xSplit = (int)(r.right*SplitX);
int ySplit = (int)((r.bottom - ToolbarHeight - StatusHeight )*SplitY);
MoveWindow( hWFilter, 0, ToolbarHeight, FILTER_WIDTH, r.bottom - ToolbarHeight - StatusHeight, TRUE );
MoveWindow( hWList, FILTER_WIDTH +3, ToolbarHeight, xSplit- 1, ySplit - 1, TRUE );
MoveWindow( hWOut, FILTER_WIDTH +3 + xSplit+2, ToolbarHeight, r.right - xSplit - 2, ySplit - 1, TRUE );
MoveWindow( hWTree, FILTER_WIDTH +3, ToolbarHeight + ySplit + 2, xSplit- 1, r.bottom- ToolbarHeight - StatusHeight - ySplit - 2, TRUE );
MoveWindow( hWListView, FILTER_WIDTH +3 + xSplit+2, ToolbarHeight + ySplit + 2, r.right - xSplit- 2, r.bottom- ToolbarHeight - StatusHeight - ySplit - 2, TRUE );
}
void SaveTreeItemChildren(HANDLE cfgFile, HTREEITEM hParent, BOOL SaveLastExpanded = TRUE)
{
BOOL LastExpanded = FALSE;
if(SaveLastExpanded)
{
LastExpanded = TRUE;
TV_ITEM tie = {TVIF_STATE|TVIF_HANDLE, 0,0,TVIS_EXPANDED };
for(tie.hItem = TreeView_GetChild( hWTree, hParent); tie.hItem; tie.hItem = TreeView_GetNextSibling(hWTree, tie.hItem))
{
TreeView_GetItem( hWTree, &tie );
if( tie.state & TVIS_EXPANDED)
{
LastExpanded = FALSE;
break;
}
}
}
TV_ITEM ti = {TVIF_STATE|TVIF_HANDLE|TVIF_PARAM, hParent,0,0 };
TreeView_GetItem( hWTree, &ti );
if(!(ti.state & TVIS_EXPANDED)) SaveLastExpanded = FALSE;
if(((CDirInfo*)ti.lParam)->GetSize() ||
ti.state & (TVIS_SELECTED|LVIS_FOCUSED) ||
ti.state & TVIS_EXPANDED && LastExpanded ||
(ti.state & TVIS_STATEIMAGEMASK) == TI_STATE_FILES ||
(ti.state & TVIS_STATEIMAGEMASK) == TI_STATE_RECURSE )
{
// save this item
CDirInfo* pDi = (CDirInfo*)ti.lParam;
StoreFileName(cfgFile, (char*)pDi->FileName(), CrtCfg); // the relative path to the directory
int Files = pDi->GetSize();
StoreItem( cfgFile, Files); // the number of selected files in the directory
for(int i = 0; i< Files; i++ ) // the name of the files
StoreItem( cfgFile,(char*)(*pDi)[i]->FileName());
if(!LastExpanded) ti.state &= ~TVIS_EXPANDED;
StoreItem( cfgFile, ti.state );
}
if(SaveLastExpanded || ti.state & TVIS_OVERLAYMASK)
// save the children (the ones needed)
for(HTREEITEM hChild = TreeView_GetChild( hWTree, hParent); hChild; hChild = TreeView_GetNextSibling(hWTree, hChild))
SaveTreeItemChildren( cfgFile, hChild, SaveLastExpanded);
}
void SaveConfiguration()
{
HCURSOR hOldCursor = SetCursor( LoadCursor(NULL, IDC_WAIT));
char* szIni = GetAppPathPlus( INIFILE ); // get configuration file name
HANDLE iniFile = CreateFile(szIni,GENERIC_WRITE, 0,NULL,CREATE_ALWAYS,0,NULL); // open the defs file
if( iniFile != INVALID_HANDLE_VALUE)
{
StoreFileName(iniFile, CrtCfg, szIni);
CloseHandle(iniFile);
}
delete[] szIni; // we don't need it anymore
HANDLE cfgFile = CreateFile(CrtCfg,GENERIC_WRITE, 0,NULL,CREATE_ALWAYS,0,NULL); // open the defs file
if( cfgFile != INVALID_HANDLE_VALUE)
{
// save the configuration
WINDOWPLACEMENT FramePos = { sizeof(WINDOWPLACEMENT) };
GetWindowPlacement( hWApp, &FramePos);
StoreItem(cfgFile, FramePos);
StoreItem(cfgFile, SplitX);
StoreItem(cfgFile, SplitY);
StoreItem(cfgFile, nFocusWnd);
//save the collection list
int listCount = ListView_GetItemCount( hWList );
StoreItem(cfgFile, listCount);
LV_ITEM testItem = { LVIF_STATE|LVIF_PARAM, 0, 0, LVIS_SELECTED, ~0 };
for(testItem.iItem = 0; testItem.iItem<listCount; testItem.iItem++)
{
ListView_GetItem( hWList, &testItem);
StoreItem(cfgFile, testItem.state);
StoreFileName(cfgFile, (char*)testItem.lParam, CrtCfg);
}
//save the selection tree
for(HTREEITEM hChild = TreeView_GetRoot(hWTree); hChild; hChild = TreeView_GetNextSibling(hWTree, hChild))
SaveTreeItemChildren( cfgFile, hChild);
StoreItem(cfgFile, "");
StoreItem( cfgFile, OperatingMode);
//save the filter list
listCount = ListView_GetItemCount( hWFilter );
StoreItem(cfgFile, listCount);
char szFilterExt[_MAX_EXT];
LV_ITEM filterItem = { LVIF_STATE|LVIF_TEXT, 0, 0, 0, ~0, szFilterExt, _MAX_EXT};
for(filterItem.iItem = 0; filterItem.iItem<listCount; filterItem.iItem++)
{
ListView_GetItem( hWFilter, &filterItem);
StoreItem(cfgFile, szFilterExt);
StoreItem(cfgFile, filterItem.state);
}
// save filtering status
BOOL bFiltering = CnvEng.IsFilteringActive();
StoreItem( cfgFile, bFiltering);
StoreItem( cfgFile, FILTER_WIDTH);
//saving ends here
//---------------------------------------------------
CloseHandle(cfgFile);
}
SetCursor( hOldCursor );
}
void ConstructTreeItem(HTREEITEM hSibling, UINT state, char* szFolderName, CDirInfo* pDirInfo);
HTREEITEM hSelected;
BOOL LoadConfiguration()
{
BOOL Maximized = FALSE;
HCURSOR hOldCursor = SetCursor( LoadCursor(NULL, IDC_WAIT));
SetWindowText( hWStatusbar, "Loading Configuration, please wait...");
ListView_DeleteAllItems( hWFilter );
FILTER_WIDTH = ListView_GetStringWidth( hWFilter, "WWW") +16 + 7 + GetSystemMetrics(SM_CXVSCROLL);
// load the application configuration
HANDLE cfgFile = CreateFile(CrtCfg,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); // open the defs file
if( cfgFile != INVALID_HANDLE_VALUE)
{
// clear the previous configuration
DeleteCollectionList(); // clear the collection list
ShowWindow( hWTree, SW_HIDE );
InitTree(); // re-initialize the tree view
// we have a saved configuration file
WINDOWPLACEMENT FramePos;
LoadItem (cfgFile, FramePos);
LoadItem (cfgFile, SplitX);
LoadItem (cfgFile, SplitY);
LoadItem (cfgFile, nFocusWnd);
RestoreFocus();
// load the collection list
int listCount;
LoadItem(cfgFile, listCount);
char* pathStr, FName[_MAX_FNAME+1];
LV_ITEM testItem = { LVIF_TEXT|LVIF_STATE|LVIF_PARAM, 0, 0, LVIS_SELECTED, ~0, FName };
for(testItem.iItem = 0; testItem.iItem<listCount; testItem.iItem++)
{
LoadItem(cfgFile, testItem.state);
LoadFileName(cfgFile, pathStr, CrtCfg);
_splitpath( pathStr, NULL, NULL, FName, NULL);
testItem.lParam = (LONG)pathStr;
ListView_InsertItem( hWList, &testItem);
}
// load the tree
char* szFolderName = NULL;
LoadFileName(cfgFile, szFolderName, CrtCfg );
while ( szFolderName )
{
// load the folder
CDirInfo* pDirInfo = new CDirInfo(szFolderName);
int Files;
LoadItem( cfgFile, Files); // the number of selected files in the directory
pDirInfo->SetSize(Files);
char* szFileName;
for(int i = 0; i< Files; i++ ) // the name of the files
{
LoadItem( cfgFile,szFileName);
pDirInfo->SetAt( i, new CFileName(szFileName));
delete[] szFileName;
}
UINT state;
LoadItem( cfgFile, state );
BOOL Drive = FALSE;
if( szFolderName[strlen(szFolderName) -1] == ':')
{
// the directory is, in fact, a drive
TV_ITEM it = { TVIF_HANDLE|TVIF_PARAM, 0 };
for( it.hItem = TreeView_GetRoot( hWTree ); it.hItem; it.hItem = TreeView_GetNextSibling(hWTree, it.hItem) )
{
TreeView_GetItem( hWTree, &it);
if(!strcmpi(szFolderName, ((CDirInfo*)(it.lParam))->FileName()))
{
Drive = TRUE;
break;
}
}
}
WIN32_FIND_DATA fd;
HANDLE hfind = INVALID_HANDLE_VALUE;
if( Drive ||
(((hfind = FindFirstFile(szFolderName, &fd)) != INVALID_HANDLE_VALUE) &&
(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
{
// construct the tree item
ConstructTreeItem( NULL, state, szFolderName, pDirInfo);
}
if(hfind != INVALID_HANDLE_VALUE) FindClose( hfind );
delete[] szFolderName;
LoadFileName(cfgFile, szFolderName, CrtCfg );
}
LoadItem( cfgFile, OperatingMode);
char* szExt;
LV_ITEM filterItem = { LVIF_STATE|LVIF_TEXT, 0, 0, 0, ~0 };
BOOL bFiltering = FALSE;
CnvEng.SetFiltering( FALSE );
if(LoadItem(cfgFile, listCount))
{
//load filter list
for(int i = 0; i<listCount; i++)
{
LoadItem( cfgFile, szExt);
filterItem.pszText = szExt;
LoadItem( cfgFile, filterItem.state);
if( CnvEng.EnableExtension( szExt, filterItem.state & LSTATE_CHECKED ) )
ListView_InsertItem( hWFilter, &filterItem );
delete[] szExt;
}
// load filter state
LoadItem( cfgFile, bFiltering);
CnvEng.SetFiltering( bFiltering );
}
LoadItem( cfgFile, FILTER_WIDTH);
// loading ends here
//---------------------------------------------------------------
TreeView_EnsureVisible( hWTree, hSelected);
CloseHandle(cfgFile);
SetWindowPlacement( hWApp, &FramePos);
PositionChildwindows();
if(FramePos.showCmd == SW_SHOWMAXIMIZED) Maximized = TRUE;
ShowWindow( hWTree, SW_SHOWNA );
}
int listCount = CnvEng.GetExtCount();
LV_FINDINFO fi = {LVFI_STRING};
LV_ITEM filterItem = { LVIF_STATE|LVIF_TEXT, 0, 0, 0, LVIS_STATEIMAGEMASK };
for( int i = 0; i< listCount; i++)
{
CFileExtension* pExt = CnvEng.Extension(i);
fi.psz = pExt->Name();
if( ListView_FindItem( hWFilter, -1, &fi ) < 0)
{
filterItem.state = (pExt->IsEnabled()? LSTATE_CHECKED: LSTATE_UNCHECKED);
filterItem.pszText = (char*)fi.psz;
ListView_InsertItem( hWFilter, &filterItem);
}
}
SetCursor( hOldCursor );
SetWindowText( hWStatusbar, "Ready");
return Maximized;
}
void ConstructTreeItem(HTREEITEM hParent, UINT state, char* szFolderName, CDirInfo* pDirInfo)
{
char* end = strchr(szFolderName, '\\');
if(end) *end = 0;
HTREEITEM hMatch = NULL;
char FolderName[_MAX_PATH];
TV_ITEM it = { TVIF_HANDLE|TVIF_TEXT|TVIF_PARAM, 0, 0, 0, FolderName, _MAX_PATH };
for( it.hItem = TreeView_GetChild( hWTree, hParent ); it.hItem; it.hItem = TreeView_GetNextSibling(hWTree, it.hItem) )
{
TreeView_GetItem( hWTree, &it);
if(!strcmpi(szFolderName, FolderName) ||
(szFolderName[strlen(szFolderName) -1] == ':' &&
!strcmpi(szFolderName, ((CDirInfo*)(it.lParam))->FileName())))
{
//we have a match
hMatch = it.hItem;
// expand the item if necessary
if( !end )
{
// this is the target item
delete (CDirInfo*) it.lParam;
TV_ITEM set = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hMatch,
state, ~(TVIS_EXPANDED|TVIS_EXPANDEDONCE|TVIS_EXPANDPARTIAL|TVIS_SELECTED|LVIS_FOCUSED)};
set.lParam = (LPARAM) pDirInfo;
TreeView_SetItem(hWTree, &set);
if(state & TVIS_SELECTED)
TreeView_SelectItem(hWTree, hSelected = hMatch);
}
if(state & TVIS_EXPANDED)
{
TV_ITEM get = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hMatch, 0, ~0 };
TreeView_GetItem(hWTree, &get);
int Exp = TreeView_Expand (hWTree, hMatch, TVE_EXPAND );
TreeView_GetItem(hWTree, &get);
SetTreeItemChildren( &get );
}
break;
}
}
if(!hMatch)
{
TV_ITEM get = { TVIF_HANDLE|TVIF_STATE, hParent, 0, ~0 };
if(hParent && (hParent))
TreeView_GetItem(hWTree, &get);
TV_INSERTSTRUCT tis =
{ hParent, TVI_SORT ,
{ TVIF_CHILDREN|TVIF_SELECTEDIMAGE|TVIF_PARAM|TVIF_IMAGE|TVIF_STATE|TVIF_TEXT,
NULL,((get.state & TVIS_STATEIMAGEMASK)>TI_STATE_FILES)? TI_STATE_LOCKED:TI_STATE_NONE,
TVIS_STATEIMAGEMASK, szFolderName, 0, 0, 1, I_CHILDRENCALLBACK, 0
}
};
// set the item's info
if( end )
{
// we didn't yet reached the item - we are inserting its predecessors
int length = strlen(pDirInfo->FileName()) - lstrlen( end + 1 ) -1;
char* name = (char*) memcpy( new char[length +1], pDirInfo->FileName(), length );
name[length] = 0;
tis.item.lParam = (LPARAM) (new CDirInfo(name));
delete[] name;
}
else
{
// this is the item
tis.item.state = state;
tis.item.stateMask = ~0;
tis.item.lParam = (LPARAM) pDirInfo;
}
hMatch = TreeView_InsertItem(hWTree, &tis);
if( !end && state & TVIS_SELECTED)
TreeView_SelectItem(hWTree, hSelected = hMatch);
}
if( end )
ConstructTreeItem( hMatch, state, end+1, pDirInfo);
else
{
NotifyChildren(hMatch);
NotifyParents(hMatch);
}
}
void UpdateAppName()
{
char fname[2*_MAX_FNAME + 40] = APPNAME" [";
char drive[_MAX_PATH], dir[_MAX_PATH];
_splitpath( CrtCfg, drive, dir, fname+ strlen(APPNAME) +5, NULL);
strcat( fname, "]");
SetWindowText(hWApp, fname);
strcat(drive, dir);
SetCurrentDirectory( drive );
}
void RestoreFocus()
{
switch(nFocusWnd)
{
case FOCUS_OUT: SetFocus(hWOut); break;
case FOCUS_TREE: SetFocus(hWTree); break;
case FOCUS_LISTVIEW: SetFocus(hWListView); break;
case FOCUS_FILTER: SetFocus(hWFilter); break;
//case FOCUS_LIST:
default: SetFocus(hWList); break;
}
}
HTREEITEM RefreshTreeItemChildren(HTREEITEM hChild)
{
TV_ITEM it = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hChild };
TreeView_GetItem( hWTree, &it);
const char* name = ((CDirInfo*)(it.lParam))->FileName();
//test the folder existence
if( name[strlen(name)-1] != ':')
{
WIN32_FIND_DATA fd;
HANDLE hfind = FindFirstFile(name, &fd);
if((hfind == INVALID_HANDLE_VALUE) ||
!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
HTREEITEM hParent = TreeView_GetParent( hWTree, hChild);
TreeView_DeleteItem( hWTree, hChild);
if(hParent) NotifyParents(hParent);
hChild = NULL;
}
if(hfind != INVALID_HANDLE_VALUE) FindClose( hfind );
}
HTREEITEM hTgt, hPrev = NULL;
if(hChild)
{
// the folder exists, we are verifying the existence of selected files
CDirInfo* pDi = (CDirInfo*)it.lParam;
char fName[_MAX_PATH+10];
BOOL ViewChanged = FALSE;
WIN32_FIND_DATA fd;
for(int i = pDi->GetUpperBound(); i>=0; i--)
{
strcpy(fName, name);
strcat(fName,"\\");
strcat(fName, (*pDi)[i]->FileName());
HANDLE hSearch = FindFirstFile( fName, &fd );
if(hSearch == INVALID_HANDLE_VALUE || fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
pDi->DeleteAt(i);
ViewChanged = TRUE;
}
if(hSearch != INVALID_HANDLE_VALUE) FindClose(hSearch);
}
if(ViewChanged)
NotifyParents(hChild);
if(ViewChanged && (it.state & TVIS_SELECTED ))
DisplayView( hChild, (CDirInfo*)it.lParam);
if(it.state & TVIS_SELECTED)
{
// add the eventually inserted files
strcpy(fName, name);
strcat(fName, "\\*.*");
UINT state = ((it.state & TVIS_STATEIMAGEMASK) > TI_STATE_NONE? LSTATE_LOCKED: LSTATE_UNCHECKED);
HANDLE hSearch = FindFirstFile( fName, &fd );
for(BOOL Found = (hSearch != INVALID_HANDLE_VALUE); Found; Found = FindNextFile( hSearch, &fd))
if(!(fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM )) &&
CnvEng.IsFileKnown( fd.cFileName))
{
LV_FINDINFO fi = {LVFI_STRING, fd.cFileName };
if( ListView_FindItem( hWListView, -1, &fi) < 0 )
{
LV_ITEM a = {LVIF_TEXT|LVIF_STATE|LVIF_PARAM,ListView_GetItemCount(hWListView),0,
state,0, fd.cFileName, 0,0, (LPARAM) hChild };
ListView_InsertItem( hWListView, &a);
}
}
if(hSearch != INVALID_HANDLE_VALUE) FindClose(hSearch);
}
// test the childs existence
for(hTgt = TreeView_GetChild(hWTree, hChild); hTgt; )
if(RefreshTreeItemChildren(hTgt))
{
hPrev = hTgt;
hTgt = TreeView_GetNextSibling(hWTree, hTgt);
}
else hTgt = (hPrev?TreeView_GetNextSibling(hWTree, hPrev):TreeView_GetChild(hWTree, hChild));
if(it.state & (TVIS_EXPANDED|TVIS_EXPANDEDONCE))
SetTreeItemChildren( &it );
}
return hChild;
}
void Refresh()
{
// refresh the list
{
HANDLE hFile;
int maxCnt = ListView_GetItemCount( hWList );
for( int i = maxCnt-1 ; i>=0; i-- )
{
LV_ITEM it = {LVIF_PARAM, i, 0};
ListView_GetItem( hWList, &it);
hFile = CreateFile( (char*)it.lParam,0,0,NULL,OPEN_EXISTING,0,NULL); // open the file
if(hFile == INVALID_HANDLE_VALUE)
{
delete[] (char*)it.lParam;
ListView_DeleteItem( hWList, i);
}
else CloseHandle(hFile);
}
if(IsWindowVisible(hWList))
PostMessage( hWList, WM_USER+10, ListView_GetNextItem( hWList, -1, LVNI_FOCUSED ), 0);
}
// refresh the tree
for(HTREEITEM hChild = TreeView_GetRoot(hWTree); hChild; hChild = TreeView_GetNextSibling(hWTree, hChild))
RefreshTreeItemChildren(hChild);
}
void CleanTreeItemChildren(HTREEITEM hChild)
{
TV_ITEM ti = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hChild, 0, ~0 };
TreeView_GetItem( hWTree, &ti);
ti.state &= ~(TVIS_STATEIMAGEMASK|TVIS_OVERLAYMASK);
ti.state |= TI_STATE_NONE;
((CDirInfo*)ti.lParam)->DeleteAll();
TreeView_SetItem( hWTree, &ti);
if(ti.state & TVIS_SELECTED)
DisplayView( hChild, (CDirInfo*)ti.lParam);
HTREEITEM hNext;
if(!(ti.state&TVIS_EXPANDED))
while( hNext = TreeView_GetChild( hWTree, hChild)) TreeView_DeleteItem( hWTree, hNext);
else
for( hNext = TreeView_GetChild( hWTree, hChild); hNext; hNext = TreeView_GetNextSibling( hWTree, hNext))
CleanTreeItemChildren(hNext);
}
void CleanSelection()
{
for(HTREEITEM hChild = TreeView_GetRoot(hWTree); hChild; hChild = TreeView_GetNextSibling(hWTree, hChild))
CleanTreeItemChildren(hChild);
}