Artifact Content

Not logged in

Artifact fcaa4b48ba621d24c91cb8fc4f69fc4ff092b925



#include "stdafx.h"
#include "NoahApp.h"
#include "SubDlg.h"

int CArcViewDlg::st_nLife;

BOOL CArcViewDlg::onInit()
{
	char cstr[100];
	kiStr str;
	kiPath path;
	SHFILEINFO sfi,lfi;
	HIMAGELIST hImS,hImL;
	kiListView ctrl( this, IDC_FILELIST );
	__int64 filesize_sum = 0;

	//-- ダイアログ一個生成の印
	hello();
	m_bSmallFirst[0] = m_bSmallFirst[1] = m_bSmallFirst[2] =
	m_bSmallFirst[3] = m_bSmallFirst[4] = m_bSmallFirst[5] = true;

	//-- 真ん中に&前に
	setCenter( hwnd(), app()->mainhwnd() );
	setFront( hwnd() );

	//-- アイコン
	path = m_fname.basedir, path += m_fname.sname;
	hImS = (HIMAGELIST)::SHGetFileInfo( path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_SMALLICON );
	hImL = (HIMAGELIST)::SHGetFileInfo( path, 0, &lfi, sizeof(lfi), SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_LARGEICON );
	sendMsg( WM_SETICON, ICON_BIG,   (LPARAM)lfi.hIcon );
	sendMsg( WM_SETICON, ICON_SMALL, (LPARAM)sfi.hIcon );

	//-- タイトル
	sendMsg( WM_SETTEXT, 0, (LPARAM)kiPath(m_fname.lname).name() );

	//-- 解凍先
	sendMsgToItem( IDC_DDIR, WM_SETTEXT, 0, (LPARAM)(const char*)m_ddir );

	//-- リスト
	if( !m_pArc->list( m_fname, m_files ) || m_files.len()==0 )
	{
		m_bAble = false;
		ctrl.insertColumn( 0, "", 510 );
		ctrl.insertItem( 0, str.loadRsrc(IDS_NOLIST) );
	}
	else
	{
		m_bAble = ( 0 != (m_pArc->ability() & aMeltEach) );

		ctrl.setImageList( hImL, hImS );
		ctrl.insertColumn( 0, str.loadRsrc(IDS_FNAME),   110 );
		ctrl.insertColumn( 1, str.loadRsrc(IDS_SIZE),    70,  LVCFMT_RIGHT );
		ctrl.insertColumn( 2, str.loadRsrc(IDS_DATETIME),100, LVCFMT_RIGHT );
		ctrl.insertColumn( 3, str.loadRsrc(IDS_RATIO),   55,  LVCFMT_RIGHT );
		ctrl.insertColumn( 4, str.loadRsrc(IDS_METHOD),  50,  LVCFMT_RIGHT );
		ctrl.insertColumn( 5, str.loadRsrc(IDS_PATH),    130 );

		FILETIME ftm;
		SYSTEMTIME stm;

		//-- アイテム
		for( unsigned int i=0,k=0; i!=m_files.len(); i++ )
			if( m_files[i].isfile )
			{
#define			usiz (m_files[i].inf.dwOriginalSize)
#define			csiz (m_files[i].inf.dwCompressedSize)
#define			method (m_files[i].inf.szMode)
#define			date (m_files[i].inf.wDate)
#define			time (m_files[i].inf.wTime)
				path = m_files[i].inf.szFileName;

				// ファイル名
				ctrl.insertItem( k, path.name(),
					(LPARAM)(&m_files[i]), kiSUtil::getSysIcon(path.ext()) );

				// サイズ
				if( usiz == 0xffffffff )
					ctrl.setSubItem( k, 1, "????" );
				else
					ctrl.setSubItem( k, 1, str.setInt( usiz,true ) );

				// 時間
				if( ::DosDateTimeToFileTime( date, time, &ftm )
				 && ::FileTimeToSystemTime( &ftm, &stm ) )
				{
					*cstr=0;
					::GetDateFormat( LOCALE_USER_DEFAULT, 0, &stm,
									 "yy/MM/dd", cstr, sizeof(cstr) );
					str=cstr;
					::GetTimeFormat( LOCALE_USER_DEFAULT, 0, &stm,
									 " HH:mm", cstr, sizeof(cstr) );
					str+=cstr;
					ctrl.setSubItem( k, 2, str );
				}

				// 圧縮率
				filesize_sum += usiz;
				if( usiz==0 )		ctrl.setSubItem( k, 3, "100%" );
				else if( csiz==0 )	ctrl.setSubItem( k, 3, "????" );
				else				ctrl.setSubItem( k, 3, str.setInt( (int)(((__int64)csiz)*100/usiz) )+='%' );

				// メソッド
				ctrl.setSubItem( k, 4, method );

				// パス
				path.beDirOnly();
				ctrl.setSubItem( k, 5, path );

				k++;

#undef			usiz
#undef			csiz
#undef			method
#undef			date
#undef			time
			}

		//-- ドラッグ&ドロップフォーマット登録
		FORMATETC fmt;
		fmt.cfFormat = CF_HDROP;
		fmt.ptd      = NULL;
		fmt.dwAspect = DVASPECT_CONTENT;
		fmt.lindex   = -1;
		fmt.tymed    = TYMED_HGLOBAL;
		addFormat( fmt );
	}

	//-- 情報 --
	char tmp[255];
	kiStr full_filename = m_fname.basedir + m_fname.lname;
	__int64 filesize_arc = kiFile::getSize64(full_filename);
	if( filesize_sum==0 ) filesize_sum = 1;
	wsprintf( tmp, kiStr().loadRsrc(IDS_ARCVIEW_MSG),
		m_files.len(),
		(int)(filesize_arc*100 / filesize_sum),
		(const char*)m_pArc->arctype_name(full_filename)
	);
	sendMsgToItem( IDC_STATUSBAR, WM_SETTEXT, 0, (long)tmp );

	if( !m_bAble )
	{
		static const UINT items[] = { IDC_SELECTINV,IDC_REF,IDC_MELTEACH,IDC_SHOW,IDC_DDIR };
		for( int i=0; i!=sizeof(items)/sizeof(UINT); i++ )
			::EnableWindow( item(items[i]), FALSE );
	}

	return FALSE;
}

bool CArcViewDlg::onOK()
{
	setdir();
	m_pArc->melt( m_fname, m_ddir );
	myapp().open_folder( m_ddir, 1 );
	kiSUtil::switchCurDirToExeDir(); // 念のため
	return onCancel();
}

bool CArcViewDlg::onCancel()
{
	::SetCurrentDirectory( m_fname.basedir );
	m_tdir.remove();
	if( kiSUtil::exist(m_tdir) )
	{
		kiStr tmp(600);
		if( IDNO==app()->msgBox( tmp.loadRsrc(IDS_EXECUTING), NULL, MB_YESNO|MB_DEFBUTTON2 ) )
			return false;
	}

	kiListView(this,IDC_FILELIST).setImageList( NULL, NULL );
	byebye();
	return true;
}

bool CArcViewDlg::giveData( const FORMATETC& fmt, STGMEDIUM* stg, bool firstcall )
{
	if( firstcall )
		if( 0x8000<=m_pArc->melt( m_fname, m_tdir, &m_files ) )
			return false;

	unsigned int i;
	BOOL fWide = (app()->osver().dwPlatformId==VER_PLATFORM_WIN32_NT);
	kiArray<kiPath> lst;
	kiPath tmp;
	int flen = 0;
	wchar_t wbuf[600];

	for( i=0; i!=m_files.len(); i++ )
		if( m_files[i].selected )
		{
			tmp = m_tdir;
			tmp += m_files[i].inf.szFileName;

			lst.add( tmp );
			if( fWide )
				flen += (::MultiByteToWideChar( CP_ACP, 0, tmp, -1, wbuf, 600 )+1)*2;
			else
				flen += (tmp.len()+1);
		}

	HDROP hDrop = (HDROP)::GlobalAlloc( GHND, sizeof(DROPFILES)+flen+1 );

	DROPFILES* dr = (DROPFILES*)::GlobalLock( hDrop );
	dr->pFiles = sizeof(DROPFILES);
	dr->pt.x   = dr->pt.y = 0;
	dr->fNC    = FALSE;
	dr->fWide  = fWide;

	char* buf = (char*)(&dr[1]);
	for( i=0; i!=lst.len(); i++ )
	{
		if( fWide )
		{
			flen = ::MultiByteToWideChar( CP_ACP, 0, lst[i], -1, wbuf, 600 );
			ki_memcpy( buf, wbuf, flen*2 );
			for( int k=0; k!=flen; k++ )
				if( ((wchar_t*)buf)[k] == '/' )
					((wchar_t*)buf)[k] = '\\';
			buf += flen*2;
		}
		else
		{
			ki_strcpy( buf,lst[i] );
			for( int k=0; k!=lst[i].len(); k++ )
				if( buf[k] == '/' )
					buf[k] = '\\';
			buf += lst[i].len() + 1;
		}
	}
	*buf=0;
	if( fWide )
		buf[1]='\0';

	::GlobalUnlock( hDrop );

	stg->hGlobal        = hDrop;
	stg->tymed          = TYMED_HGLOBAL;
	stg->pUnkForRelease = NULL;
	return true;
}

BOOL CALLBACK CArcViewDlg::proc( UINT msg, WPARAM wp, LPARAM lp )
{
	switch( msg )
	{
	//-- メインウインドウ指定 ---------------------
	case WM_ACTIVATE:
		if( LOWORD(wp)==WA_ACTIVE || LOWORD(wp)==WA_CLICKACTIVE )
		{
			app()->setMainWnd( this );
			return TRUE;
		}
		break;

	//-- リサイズ関連の処理 ---------------------
	case WM_GETMINMAXINFO:
		{
			RECT self,child;
			::GetWindowRect( hwnd(), &self );
			::GetWindowRect( item(IDC_REF), &child );
			POINT& sz = ((MINMAXINFO*)lp)->ptMinTrackSize;
			sz.x = child.right - self.left + 18;
			sz.y = child.bottom - self.top + 100;
		}
		return TRUE;
	case WM_SIZE:
		if( wp!=SIZE_MAXHIDE && wp!=SIZE_MINIMIZED )
		{
			RECT self,ref,child,sbar;
			::GetWindowRect( hwnd(), &self );
			::GetWindowRect( item(IDC_REF), &ref );
			::GetWindowRect( item(IDC_FILELIST), &child );
			::GetClientRect( item(IDC_STATUSBAR), &sbar );

			::SetWindowPos( item(IDC_FILELIST), NULL, 0, 0,
				LOWORD(lp),
				(self.bottom-ref.bottom)-(child.top-ref.bottom)
				-(sbar.bottom-sbar.top)-10,
				SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER );

			::GetClientRect( hwnd(), &self );
			::SetWindowPos( item(IDC_STATUSBAR), NULL, sbar.left,
				self.bottom - (sbar.bottom-sbar.top),
				0, 0, SWP_NOSIZE|SWP_NOOWNERZORDER|SWP_NOZORDER );
		}
		break;

	case WM_NOTIFY:
		if( wp==IDC_FILELIST && m_bAble )
		{
			NMHDR* phdr=(NMHDR*)lp;
			if( phdr->code==LVN_BEGINDRAG || phdr->code==LVN_BEGINRDRAG )
			{
				if( setSelection() )
					kiDropSource::DnD( this, DROPEFFECT_COPY );
				return TRUE;
			}
			else if( phdr->code==LVN_COLUMNCLICK )
				DoSort( ((NMLISTVIEW*)lp)->iSubItem );
			else if( phdr->code==NM_DBLCLK )
				sendMsg( WM_COMMAND, IDC_SHOW );
			else if( phdr->code==NM_RCLICK )
			{
				if( setSelection() )
					DoRMenu();
			}
		}
		break;

	case WM_COMMAND:
		switch( LOWORD(wp) )
		{
		case IDC_SELECTINV: // 選択反転
			{
				LVITEM item;
				item.mask = LVIF_STATE;
				item.stateMask = LVIS_SELECTED;
				int j,m=sendMsgToItem( IDC_FILELIST, LVM_GETITEMCOUNT );
				for( j=0; j!=m; j++ )
				{
					item.state = ~sendMsgToItem( IDC_FILELIST, LVM_GETITEMSTATE, j, LVIS_SELECTED );
					sendMsgToItem( IDC_FILELIST, LVM_SETITEMSTATE, j, (LPARAM)&item );
				}
				::SetFocus( this->item(IDC_FILELIST) );
			}
			return TRUE;

		case IDC_REF: // 解凍先設定
			kiSUtil::getFolderDlgOfEditBox( item(IDC_DDIR), hwnd(), kiStr().loadRsrc(IDS_CHOOSEDIR) );
			return TRUE;

		case IDC_MELTEACH: // 一部解凍
			if( setSelection() )
			{
				setdir();
				int result = m_pArc->melt( m_fname, m_ddir, &m_files );
				if( result<0x8000 )
					myapp().open_folder( m_ddir, 1 );
				else if( result != 0x8020 )
				{
					char str[255];
					wsprintf( str, "%s\nError No: [%x]",
						(const char*)kiStr().loadRsrc( IDS_M_ERROR ), result );
					app()->msgBox( str );
				}
				kiSUtil::switchCurDirToExeDir(); // 念のため
			}
			return TRUE;

		case IDC_SHOW: // 表示
			if( setSelection() )
			{
				int assocCnt = hlp_cnt_check();
				if( 0x8000 > m_pArc->melt( m_fname, m_tdir, &m_files ) )
				{
					if( assocCnt != -1 )
						m_files[assocCnt].selected = false;
					for( unsigned i=0; i!=m_files.len(); i++ )
						if( m_files[i].selected )
						{
							kiPath tmp(m_tdir);
							char yen[MAX_PATH];
							ki_strcpy( yen, m_files[i].inf.szFileName );
							for( char* p=yen; *p; p=kiStr::next(p) )
								if( *p=='/' )
									*p = '\\';
							tmp += yen;
							::ShellExecute( hwnd(), NULL, tmp, NULL, m_tdir, SW_SHOWDEFAULT );
						}
				}
				kiSUtil::switchCurDirToExeDir(); // 念のため
			}
			return TRUE;
		}
	}
	return FALSE;
}

int CArcViewDlg::hlp_cnt_check()
{
	// 一個目の選択済みファイルが .hlp か否か
	for( unsigned i=0; i!=m_files.len(); i++ )
		if( m_files[i].selected )
			break;
	if( i==m_files.len() )
		return -1;
	int x = kiPath::ext(m_files[i].inf.szFileName)-m_files[i].inf.szFileName;
	if( 0!=ki_strcmpi( "hlp", m_files[i].inf.szFileName+x ) )
		return -1;

	// .cnt のファイル名
	char cntpath[FNAME_MAX32];
	ki_strcpy( cntpath, m_files[i].inf.szFileName );
	cntpath[x]='c', cntpath[x+1]='n', cntpath[x+2]='t';

	// .cntも一時的に選択する
	for( i=0; i!=m_files.len(); i++ )
		if( 0==ki_strcmpi( cntpath, m_files[i].inf.szFileName ) )
		{
			if( m_files[i].selected )
				return -1;
			m_files[i].selected = true;
			return i;
		}
	return -1;
}

int CALLBACK CArcViewDlg::lv_compare( LPARAM p1, LPARAM p2, LPARAM type )
{
	bool rev = false;
	if( type>=10000 )
		rev=true, type-=10000;
	int ans = 0;

	INDIVIDUALINFO *a1=&((arcfile*)p1)->inf, *a2=&((arcfile*)p2)->inf;
	switch( type )
	{
	case 0: //NAME
		ans = ::lstrcmp( kiPath::name(a1->szFileName),
			             kiPath::name(a2->szFileName) );
		break;
	case 1: //SIZE
		ans = (signed)a1->dwOriginalSize - (signed)a2->dwOriginalSize;
		break;
	case 2: //DATE,TIME
		ans = (signed)a1->wDate - (signed)a2->wDate;
		if( ans==0 )
			ans = (signed)a1->wTime - (signed)a2->wTime;
		break;
	case 3:{//RATIO
		int cr1, cr2;
		if( a1->dwOriginalSize==0 )        cr1=100;
		else if( a1->dwCompressedSize==0 ) cr1=-1;
		else cr1 = (a1->dwCompressedSize*100)/(a1->dwOriginalSize);
		if( a2->dwOriginalSize==0 )        cr2=100;
		else if( a2->dwCompressedSize==0 ) cr2=-1;
		else cr2 = (int)((((__int64)a2->dwCompressedSize)*100)/(a2->dwOriginalSize));
		ans = cr1 - cr2;
		}break;
	case 4: //METHOD
		ans = ::lstrcmp( a1->szMode, a2->szMode );
		break;
	case 5:{//PATH
		kiPath pt1(a1->szFileName), pt2(a2->szFileName);
		pt1.beDirOnly(), pt2.beDirOnly();
		ans = ::lstrcmp( pt1, pt2 );
		}break;
	}

	return rev ? -ans : ans;
}

void CArcViewDlg::DoSort( int col )
{
	WPARAM p = col + (m_bSmallFirst[col] ? 0 : 10000);
	sendMsgToItem( IDC_FILELIST, LVM_SORTITEMS, p, (LPARAM)lv_compare );
	m_bSmallFirst[col] = !m_bSmallFirst[col];
}

void CArcViewDlg::GenerateDirMenu( HMENU m, int& id, StrArray* sx, const kiPath& pth )
{
	// フォルダ内リストアップ
	kiFindFile ff;
	ff.begin( kiPath(pth)+="*" );
	for( WIN32_FIND_DATA fd; ff.next(&fd); )
		if( fd.cFileName[0]!='.'
		 && !(fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) )
		{
			kiPath fullpath(pth); fullpath+=fd.cFileName;
			const int pID=id;
			MENUITEMINFO mi = { sizeof(MENUITEMINFO) };

			if( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
			{
				// 再帰的に
				mi.fMask = MIIM_SUBMENU | 0x00000040;// (MIIM_STRING)
				mi.hSubMenu = ::CreatePopupMenu();
				GenerateDirMenu( mi.hSubMenu, id, sx,
					kiPath(kiPath(fullpath)+="\\") );
			}
			else
			{
				const char* ext = kiPath::ext(fd.cFileName);
				if( ::lstrlen(ext) > 4 ) continue;
				if( 0==::lstrcmpi(ext,"lnk") )
					*const_cast<char*>(ext-1) = '\0';
				mi.fMask = MIIM_ID | 0x00000040;// (MIIM_STRING)
				mi.wID = id++;
				sx->add( fullpath );
			}

			mi.dwTypeData = const_cast<char*>((const char*)fd.cFileName);
			mi.cch        = ::lstrlen(fd.cFileName);
			::InsertMenuItem( m, pID, FALSE, &mi );
		}
}

void CArcViewDlg::DoRMenu()
{
	// メニュー作成
	HMENU m = ::CreatePopupMenu();
	POINT pt; ::GetCursorPos( &pt );
	const int IDSTART = 128;

	// フォルダの中身をリストアップしつつメニューに追加
	int id = IDSTART;
	StrArray lst;
	GenerateDirMenu( m, id, &lst, kiPath(CSIDL_SENDTO) );

	// メニュー表示
	id = ::TrackPopupMenu( m,
		TPM_LEFTALIGN|TPM_TOPALIGN|TPM_RETURNCMD|TPM_NONOTIFY,
		pt.x, pt.y, 0, hwnd(), NULL );
	::DestroyMenu( m );

	// 結果処理
	if( id != 0 )
	{
		kiStr cmd;
		if( 0x8000>m_pArc->melt( m_fname, m_tdir, &m_files ) )
		{
			for( UINT i=0; i!=m_files.len(); i++ )
				if( m_files[i].selected )
				{
					cmd += "\"";
					cmd += m_tdir;
					const char* buf = m_files[i].inf.szFileName;
					for( int k=0; buf[k]; ++k )
						cmd += ( buf[k]=='/' ? '\\' : buf[k] );
					cmd += "\" ";
				}
			ShellExecute(hwnd(),NULL,lst[id-IDSTART],cmd,NULL,SW_SHOW);
		}
	}
}