changeset 5:e3b10fb860b3

release v1.0.
author pyon@macmini
date Mon, 22 Oct 2018 22:17:02 +0900
parents 06342fc544e4
children 9a8b581c1993
files doc/Todo go/crypto.go include/auth.h include/id.h include/main.h include/rsearcher.h myapp.bin src/auth.cpp src/main.cpp src/rsearcher.cpp
diffstat 10 files changed, 344 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
--- a/doc/Todo	Mon Oct 15 20:07:38 2018 +0900
+++ b/doc/Todo	Mon Oct 22 22:17:02 2018 +0900
@@ -58,7 +58,6 @@
 * バージョンアップ
     + client に pw
     + 10分間 Idle なら password
-    + mouse gesture 次、前のタブへ
     + dark-mode の搭載
     + プライベートフォルダに写真 userid/startup.jpg, default.jpg, avatar.jpg
 
--- a/go/crypto.go	Mon Oct 15 20:07:38 2018 +0900
+++ b/go/crypto.go	Mon Oct 22 22:17:02 2018 +0900
@@ -1,7 +1,7 @@
 /*
  crypto.go  : crypto-program.
  Version    : 0.0
- Last Change: 2018-10-11 譛ィ 13:54:56.
+ Last Change: 2018-10-19 驥 15:58:10.
 
  install to: rsearcher_root/
              server_root/
@@ -23,25 +23,40 @@
 	"os"
 )
 
+var version string
+
+func init() {
+	version = "1.0"
+}
+
 func main() {
 	salt := flag.String( "s", "dummysalt", "salt." )
-
 	enca := flag.String( "a", "", "encrypt plaintext." )
 	encb := flag.String( "b", "", "encrypt csv-file." )
 	coll := flag.String( "c", "", "collate user/password." )
 
-	decr := flag.String( "d", "", "deecrypt hhs." )
+	key  := flag.String( "k", "1234567890abcdef1234567890abcdef", "key" )	// len = 32
 	encr := flag.String( "e", "", "encrypt hhs." )
+	decr := flag.String( "d", "", "decrypt hhs." )
 	ghhs := flag.String( "f", "", "get hhs info." )
 
+	pver := flag.Bool( "v", false, "print version." )
+
 	flag.Parse()
 
+	if *pver {
+		fmt.Println( "crypto [", version, "]" )
+		os.Exit( 0 )
+	}
+
+	/* Hash ( 1 word ) */
 	if *enca != "" {
 		buf := *salt + enc_sha256( *enca ) + *salt
 		fmt.Println( enc_sha256( buf ) )
 		os.Exit( 0 )	// done.
 	}
 
+	/* Hash ( csv ) */
 	if *encb != "" {
 		f, err := os.Open( *encb ); if err != nil {
 			log.Fatal( err )
@@ -63,6 +78,7 @@
 		os.Exit( 0 )	// done.
 	}
 
+	/* Password Check */
 	if *coll != "" {
 		f, err := os.Open( *coll ); if err != nil {
 			log.Fatal( err )
@@ -98,50 +114,20 @@
 		os.Exit( 0 )	// done.
 	}
 
-	key, _ := hex.DecodeString( "f368616e676520746869732070617373" )	// len = 32
+	/* Encrypto & Decrypto */
+	k, _ := hex.DecodeString( *key )	// len = 32
+	block, err := aes.NewCipher( k )
+	if err != nil {
+		panic( err )
+	}
 
-	if *decr != "" {
-		f, err := os.Open( *decr ); if err != nil {
-			log.Fatal( err )
-		}
-		defer f.Close()
-
-		ciphertext, err := ioutil.ReadAll( f )
+	// encrypto file
+	if *encr != "" {
+		plaintext, err := ioutil.ReadFile( *encr )	// 蜈・蜉佞SV縺ッ S-JIS
 		if err != nil {
 			log.Fatal( err )
 		}
 
-		block, err := aes.NewCipher( key )
-		if err != nil {
-			panic( err )
-		}
-
-		iv := ciphertext[ :aes.BlockSize ]
-		plaintext := make( []byte, len( ciphertext ) - aes.BlockSize )
-		stream := cipher.NewCTR( block, iv )
-		stream.XORKeyStream( plaintext, ciphertext[ aes.BlockSize: ] )
-
-		fmt.Printf( "%s", plaintext )
-		os.Exit( 0 )
-	}
-
-
-	if *encr != "" {
-		f, err := os.Open( *encr ); if err != nil {
-			log.Fatal( err )
-		}
-		defer f.Close()
-
-		plaintext, err := ioutil.ReadAll( f )
-		if err != nil {
-			log.Fatal( err )
-		}
-
-		block, err := aes.NewCipher( key )
-		if err != nil {
-			panic( err )
-		}
-
 		// IV 縺ッ蜈ャ髢九@縺ヲ繧ゅ>縺縺ョ縺ァ蜈磯ュ縺ォ縺、縺代※縺翫¥
 		ciphertext := make( []byte, aes.BlockSize + len( plaintext ) )
 		iv := ciphertext[ :aes.BlockSize ]
@@ -152,17 +138,37 @@
 		stream := cipher.NewCTR( block, iv )
 		stream.XORKeyStream( ciphertext[ aes.BlockSize: ], plaintext )
 
-		fmt.Printf( "%x", ciphertext )
+		fmt.Printf( "%s", ciphertext )
 		os.Exit( 0 )
 	}
 
-	if *ghhs != "" {
+	// decrypt file
+	if *decr != "" {
+		ciphertext, err := ioutil.ReadFile( *decr )
+		if err != nil {
+			log.Fatal( err )
+		}
+
+		iv := ciphertext[ :aes.BlockSize ]
+		plaintext := make( []byte, len( ciphertext[ aes.BlockSize: ] ) )
+		stream := cipher.NewCTR( block, iv )
+		stream.XORKeyStream( plaintext, ciphertext[ aes.BlockSize: ] )
+
+		fmt.Printf( "%s", plaintext )
+		os.Exit( 0 )
 	}
 
+	/* Etc */
+	if *ghhs != "" {
+		os.Exit( 0 )
+	}
+
+	/* Error */
 	fmt.Fprintf( os.Stderr, "bad argument\n" )
 	os.Exit( 1 )
 }
 
+/* Hash Function */
 func enc_sha256( text string ) string {
 	h := sha256.New()
 	h.Write( []byte( text ) )
--- a/include/auth.h	Mon Oct 15 20:07:38 2018 +0900
+++ b/include/auth.h	Mon Oct 22 22:17:02 2018 +0900
@@ -1,5 +1,5 @@
 // Filename   : auth.h
-// Last Change: 2018-10-11 木 16:23:21.
+// Last Change: 2018-10-22 月 08:41:38.
 //
 
 #ifndef __AUTH_H__
@@ -47,6 +47,7 @@
 
 		void SetServer( wxString server ) { m_server = server; };
         void CreateControls( void );
+		bool LoadDB( void );
 		bool IsValidUser( void );
 		wxString GetUser( void ) { return m_user; };
         void InDevelop( bool ); 
--- a/include/id.h	Mon Oct 15 20:07:38 2018 +0900
+++ b/include/id.h	Mon Oct 22 22:17:02 2018 +0900
@@ -1,5 +1,5 @@
 // Filename   : id.h
-// Last Change: 2018-10-12 金 16:19:50.
+// Last Change: 2018-10-22 月 12:43:44.
 //
 
 #ifndef __ID_H__
@@ -7,15 +7,18 @@
 
 #include <wx/wx.h>
 
+#define RSVER "1.0"
+#define RSRELEASE "2018.10.25"
+
 enum {
 	ID_MAIN = wxID_HIGHEST + 1,
 	ID_SEARCH,
+	ID_PSEARCH,
 	ID_LIST,
 	ID_NBOOK,
 	ID_SLDR,
 	ID_TIMER,
 	ID_LOGOUT,
-	ID_TEST,
 };
 
 #endif // __ID_H__
--- a/include/main.h	Mon Oct 15 20:07:38 2018 +0900
+++ b/include/main.h	Mon Oct 22 22:17:02 2018 +0900
@@ -1,10 +1,13 @@
 // Filename   : main.h
-// Last Change: 2018-10-12 金 16:16:45.
+// Last Change: 2018-10-19 金 16:02:35.
 //
 #include <wx/wx.h>
 #include <wx/config.h>
 #include <wx/fileconf.h>
 #include <wx/splash.h>
+#include <wx/fs_zip.h>
+#include <wx/filesys.h>
+#include <wx/wfstream.h>
 
 // private classes
 // Define a new application type, each program should derive a class from wxApp
--- a/include/rsearcher.h	Mon Oct 15 20:07:38 2018 +0900
+++ b/include/rsearcher.h	Mon Oct 22 22:17:02 2018 +0900
@@ -1,5 +1,5 @@
 // Filename   : rsearcher.h
-// Last Change: 2018-10-12 金 16:16:26.
+// Last Change: 2018-10-22 月 13:08:14.
 //
 
 #ifndef __RSEARCH_H__
@@ -29,7 +29,24 @@
 #include <wx/utils.h> 
 #include <wx/textfile.h>
 #include <wx/timer.h>
+#include <wx/hashmap.h>
 
+/* Data Class */
+class HhsClass {
+	public:
+		wxString no;
+		wxString birth;
+		wxString name;
+		wxString kana;
+		wxString addr;
+		wxString sex;
+
+		HhsClass( wxArrayString& buf );
+};
+
+WX_DECLARE_HASH_MAP( wxString, HhsClass*, wxStringHash, wxStringEqual, HhsHash );
+
+/* Control-Window Class */
 class MySearchCtrl : public wxSearchCtrl
 {
     DECLARE_EVENT_TABLE()
@@ -75,6 +92,7 @@
 		wxString	  m_user;
 		wxArrayString m_index;
 		wxTimer       m_timer;
+		HhsHash       hhash;
 	
 	protected:
 		MySearchCtrl*		m_searchCtrl;
@@ -100,36 +118,41 @@
 		wxDataViewColumn* 	m_dataViewListColumnDate;
 		wxTextCtrl* 		m_textCtrlLog;
 		wxSlider*           m_slider;
+		wxButton*           m_buttonPsearch;
 		wxButton*           m_buttonPrint;
+		wxButton*           m_buttonHelp;
 		wxButton*           m_buttonLogout;
-		wxButton*           m_buttonTest;
 	
 	public:
 		MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT( "Searcher Remote" ), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
 		~MainFrame();
 
 		void SetServer( wxString server ) { m_server = server; };
-		void SetUser( wxString user ) { m_user = user; };
+		void SetUser( wxString user ) { m_user = user; WriteLog( wxT( "[login] " ) + m_user ); };
 		void CreateControls( void );
+		void SetAccelerator( void );
 		void Cmd( wxString cmd );
 		void Search( void );
+		void PasteSeaarch( void );
 		void LoadDB( void );
-        void LoadBitmap( wxScrolledWindow* sc, wxStaticBitmap* sb, wxString file );
-        void LoadBitmaps( wxString date );
+        bool LoadBitmap( wxScrolledWindow* sc, wxStaticBitmap* sb, wxString file );
+        bool LoadBitmaps( wxString date, bool reload );
         void GetImages( wxString hhs, wxString date );
 		void PrintImages( void );
+		void WriteLog( wxString msg );
 		void RemoveFile( wxString pattern );
         void InDevelop( bool );
 
 		void OnItemSelected( wxDataViewEvent& event );
 		void OnItemDClicked( wxDataViewEvent& event );
         void OnNBookChanged( wxBookCtrlEvent& event );
+        void OnPasteSearch( wxCommandEvent& event );
         void OnPrint( wxCommandEvent& event );
 		void OnClose( wxCloseEvent& event );	// save config
 		void OnIdle( wxIdleEvent& event );
 		void OnTimer( wxTimerEvent& event );
+        void OnHelp( wxCommandEvent& event );
         void OnLogout( wxCommandEvent& event );
-        void OnTestButton( wxCommandEvent& event );
 };
 
 #endif // __RSEARCH_H__
Binary file myapp.bin has changed
--- a/src/auth.cpp	Mon Oct 15 20:07:38 2018 +0900
+++ b/src/auth.cpp	Mon Oct 22 22:17:02 2018 +0900
@@ -1,5 +1,5 @@
 // Filename   : auth.cpp
-// Last Change: 2018-10-12 驥 16:17:32.
+// Last Change: 2018-10-22 譛 16:11:52.
 //
 
 #include "id.h"
@@ -28,23 +28,6 @@
 // Event Handler
 void AuthDialog::OnShow( wxShowEvent& WXUNUSED(event) )
 {
-	if ( m_load ) return;
-	wxArrayString args;	// http get ( auth.db, hhs.db, index.db )
-	args.Add( wxT( "client.exe" ) );
-	args.Add( wxT( "-u" ) );
-	args.Add( m_server );
-
-	wxExecute( wxJoin( args, ' ', '\\' ), wxEXEC_SYNC|wxEXEC_HIDE_CONSOLE );
-
-	wxTextFile file;
-	file.Open( wxT( "auth.db" ) );
-	for ( int i = 0; i < file.GetLineCount(); i++ ) {
-		wxArrayString line = wxSplit( file.GetLine( i ), ' ', '\\' );
-		m_users.Add( line[ 0 ] );
-	}
-	file.Close();
-	
-	m_load = true;
 }
 
 void AuthDialog::OnCheckUserID( wxCommandEvent& WXUNUSED(event) )
@@ -136,6 +119,27 @@
     m_textCtrlId->SetFocus();
 }
 
+bool AuthDialog::LoadDB( void )
+{
+	// http get ( auth.db, hhs.db, index.db )
+	wxArrayString args;
+	args.Add( wxT( "client.exe" ) );
+	args.Add( wxT( "-u" ) );
+	args.Add( m_server );
+
+	wxExecute( wxJoin( args, ' ', '\\' ), wxEXEC_SYNC|wxEXEC_HIDE_CONSOLE );
+
+	// load db
+	wxTextFile file;
+	if ( !file.Open( wxT( "auth.db" ) ) ) return false;
+	for ( int i = 0; i < file.GetLineCount(); i++ ) {
+		wxArrayString line = wxSplit( file.GetLine( i ), ' ', '\\' );
+		m_users.Add( line[ 0 ] );
+	}
+	file.Close();
+	return true;
+}
+
 bool AuthDialog::IsValidUser( void )
 {
 	wxString id = m_textCtrlId->GetValue();
@@ -158,7 +162,6 @@
 
 void AuthDialog::InDevelop( bool flag )
 {
-	return;
     if ( !flag ) return;
     m_textCtrlId->SetValue( "test" );
     m_textCtrlPw->SetValue( "test" );
--- a/src/main.cpp	Mon Oct 15 20:07:38 2018 +0900
+++ b/src/main.cpp	Mon Oct 22 22:17:02 2018 +0900
@@ -1,5 +1,5 @@
 // Filename   : main.cpp
-// Last Change: 2018-10-12 驥 16:17:39.
+// Last Change: 2018-10-22 譛 16:14:28.
 //
 #include "id.h"
 #include "main.h"
@@ -26,27 +26,55 @@
     wxImage::AddHandler( new wxPNGHandler  );
 	InitSetting();
 
-	wxBitmap bmp;
-	if ( bmp.LoadFile( wxT( "./image/startup.png" ), wxBITMAP_TYPE_PNG ) ){
-		wxSplashScreen* splash = new wxSplashScreen( bmp, wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT, 4000, NULL, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE|wxSTAY_ON_TOP );
+	// Splash Screen
+	wxFileSystem::AddHandler( new wxZipFSHandler );
+	wxFileSystem* fs = new wxFileSystem();
+	wxString archive = wxT( "file:///./myapp.bin" );
+	for ( int i = 0; i < 11; i++ ) {
+		wxFSFile* file = fs->OpenFile( archive + wxString::Format( wxT( "#zip:startup%02d.png" ), i ) );
+		if ( file ) {
+			wxInputStream* s = file->GetStream();
+			wxImage image( *s, wxBITMAP_TYPE_PNG );
+			wxBitmap bmp = wxBitmap( image );
+			wxSplashScreen* splash = new wxSplashScreen( bmp, wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT, 3000, NULL, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE|wxSTAY_ON_TOP );
+			delete file;
+		}
+		wxMilliSleep( 250 );
 	}
 
-    AuthDialog *authdlg = new AuthDialog( NULL, wxID_ANY, wxT( "Check User" ), wxDefaultPosition, wxDefaultSize, wxCAPTION );
-	authdlg->SetServer( m_server );
+	unsigned int seed = (unsigned int)time( 0 );
+	srand( seed );
+	int n = rand() % 13;
+	wxFSFile* file = fs->OpenFile( archive + wxString::Format( wxT( "#zip:%02d.jpg" ), n ) );
+	if ( file ) {
+		wxInputStream* s = file->GetStream();
+		wxFileOutputStream of( wxT( "./image/hello.jpg" ) );
+		s->Read( of );
+		delete file;
+	}
+	delete fs;
 
-    MainFrame *mainframe = new MainFrame( NULL, ID_MAIN, wxT( "Re:Searcher" ), wxPoint( rect.x, rect.y ), rect.GetSize(), wxDEFAULT_FRAME_STYLE );
-	mainframe->SetServer( m_server );
-
-    if ( develop ) {
-        authdlg->InDevelop( true );
-        mainframe->InDevelop( true );
-    }
+	// Login Dialog
+    AuthDialog *authdlg = new AuthDialog( NULL, wxID_ANY, wxT( "Who are you ?" ), wxDefaultPosition, wxDefaultSize, wxCAPTION );
+	authdlg->SetServer( m_server );
+	if ( !authdlg->LoadDB() ) {
+		authdlg->Destroy();
+		return false;
+	}
 
     if ( authdlg->ShowModal() == wxID_OK ) {
+		wxString ui = wxString::Format( wxT( "./image/" ) + authdlg->GetUser() + wxT( ".jpg" ) ); 
+		if ( wxFileExists( ui ) ) wxCopyFile( ui, wxT( "./image/hello.jpg" ), true );
+
+		// Main Window
+		MainFrame *mainframe = new MainFrame( NULL, ID_MAIN, wxEmptyString, wxPoint( rect.x, rect.y ), rect.GetSize(), wxDEFAULT_FRAME_STYLE );
+		mainframe->InDevelop( true );
+		mainframe->SetServer( m_server );
 		mainframe->SetUser( authdlg->GetUser() );
+		mainframe->LoadDB();
+		mainframe->SetTitle( wxT( "Re:Searcher - " ) + authdlg->GetUser() );
 		mainframe->Show( true );
-	} else {
-		mainframe->Destroy();
+		//mainframe->Destroy();
 	}
 	authdlg->Destroy();
 
--- a/src/rsearcher.cpp	Mon Oct 15 20:07:38 2018 +0900
+++ b/src/rsearcher.cpp	Mon Oct 22 22:17:02 2018 +0900
@@ -1,13 +1,28 @@
 // Filename   : rsearcher.cpp
-// Last Change: 2018-10-12 金 16:40:12.
+// Last Change: 2018-10-22 月 16:20:03.
 //
 
 #include <wx/arrstr.h> 
 #include <wx/html/htmprint.h>
+#include <wx/clipbrd.h>
 #include "id.h"
 #include "rsearcher.h"
 #include "main.h"
 
+
+/********************/
+/** HhsClass       **/
+/********************/
+HhsClass::HhsClass( wxArrayString& buf )
+{
+	no    = buf[0];
+	birth = buf[1];
+	name  = buf[2];
+	kana  = buf[3];
+	addr  = buf[4];
+	sex   = buf[5];
+}
+
 /********************/
 /** MySearchCtrl   **/
 /********************/
@@ -126,6 +141,7 @@
 
 void MyStaticBitmap::OnMotion( wxMouseEvent& event )
 {
+	if ( event.RightIsDown() ) return;
     if ( event.Dragging() ) {
         int xv, yv, x, y;
         m_parent->GetViewStart( &xv, &yv );
@@ -173,6 +189,8 @@
     }
     // to up-right
     else if ( rad > pi / 8 && rad < pi / 8 * 3 && dx > 0 ) {
+		MainFrame* mf = (MainFrame*)FindWindowById( ID_MAIN );
+		mf->Close();
     }
 	// down
     else if ( rad > pi / 8 * 3 && rad < pi / 8 * 5 && dy > 0 ) {
@@ -203,8 +221,8 @@
 	: wxFrame( parent, id, title, pos, size, style )
 {
 	CreateControls();
-	LoadDB();
-    LoadBitmaps( wxEmptyString );
+	SetAccelerator();
+    LoadBitmaps( wxEmptyString, false );
 	m_timer.SetOwner( this, ID_TIMER );
 }
 
@@ -221,8 +239,9 @@
     EVT_DATAVIEW_ITEM_ACTIVATED( ID_LIST, MainFrame::OnItemDClicked )
     EVT_NOTEBOOK_PAGE_CHANGED( ID_NBOOK, MainFrame::OnNBookChanged )
 	EVT_BUTTON( wxID_PRINT, MainFrame::OnPrint )
+	EVT_BUTTON( ID_PSEARCH, MainFrame::OnPasteSearch )
+	EVT_BUTTON( wxID_HELP, MainFrame::OnHelp )
 	EVT_BUTTON( ID_LOGOUT, MainFrame::OnLogout )
-	EVT_BUTTON( ID_TEST, MainFrame::OnTestButton )
 	EVT_CLOSE( MainFrame::OnClose )
     EVT_IDLE( MainFrame::OnIdle )
     EVT_TIMER( ID_TIMER, MainFrame::OnTimer )
@@ -237,9 +256,9 @@
 	if ( ready.IsSameAs( wxT( "OK" ), true ) ) {
 		wxString date = m_dataViewListCtrl->GetTextValue( r, 1 );
 		date.Replace( wxT( "-" ), wxEmptyString, true );
-		LoadBitmaps( date );
+		LoadBitmaps( date, false );
 	} else {
-		LoadBitmaps( wxEmptyString );
+		LoadBitmaps( wxEmptyString, false );
 	}
 }
 
@@ -252,9 +271,8 @@
     wxString date = m_dataViewListCtrl->GetTextValue( r, 1 );
 	date.Replace( wxT( "-" ), wxEmptyString, true );
 	GetImages( m_hhs, date );
-	LoadBitmaps( date );
-
-    m_dataViewListCtrl->SetTextValue( wxT( "OK" ), r, 2 );
+	if ( LoadBitmaps( date, true ) )
+		m_dataViewListCtrl->SetTextValue( wxT( "OK" ), r, 2 );
 }
 
 void MainFrame::OnNBookChanged( wxBookCtrlEvent& WXUNUSED(event) )
@@ -267,32 +285,42 @@
 
 void MainFrame::OnClose( wxCloseEvent& WXUNUSED(event) )	// save config
 {
+	WriteLog( wxT( "[logout]" ) );
     if ( !IsIconized() && !IsMaximized() ) {
         wxGetApp().rect = this->GetRect();
     }
     Destroy();
 }
 
+void MainFrame::OnPasteSearch( wxCommandEvent& WXUNUSED(event) )
+{
+	PasteSeaarch();
+}
+
 void MainFrame::OnPrint( wxCommandEvent& WXUNUSED(event) )
 {
 	PrintImages();
 }
 
+void MainFrame::OnHelp( wxCommandEvent& WXUNUSED(event) )
+{
+	wxString version, build;
+	version = wxString::Format( wxT( "Re:Searcher-- version %s / %s\n\n" ), RSVER, RSRELEASE );
+	build   = wxString::Format( wxT( "build with %s\nrunning under %s." ), wxVERSION_STRING, wxGetOsDescription() );
+
+	wxMessageBox( version + build, wxT( "Help" ) );
+	return;
+}
+
 void MainFrame::OnLogout( wxCommandEvent& WXUNUSED(event) )
 {
 	wxMessageBox("logout");
 	return;
 }
 
-void MainFrame::OnTestButton( wxCommandEvent& WXUNUSED(event) )
-{
-	return;
-}
-
-
 void MainFrame::OnTimer( wxTimerEvent& WXUNUSED(event) )
 {
-	wxMessageBox( "timer !" );
+	//wxMessageBox( "timer !" );
 	// logout
 }
 
@@ -310,8 +338,8 @@
 {
     this->SetIcon( wxIcon( wxT( "sample" ) ) );
 	this->SetSizeHints( wxDefaultSize, wxDefaultSize );
-	//this->SetBackgroundColour( wxColour( 0, 150, 230 ) );
-	this->SetBackgroundColour( wxColour( 153, 153, 153 ) );
+	this->SetBackgroundColour( wxColour( 30, 80, 40 ) );
+	//this->SetBackgroundColour( wxColour( 153, 153, 153 ) );
 
 	wxBoxSizer* bSizerTop = new wxBoxSizer( wxHORIZONTAL );
 	
@@ -358,11 +386,11 @@
 	bSizerRight->Add( m_searchCtrl, 0, wxALL, 5 );
 	m_searchCtrl->SetFocus();
 	
-	m_textCtrlName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80, -1 ), 0 );
+	m_textCtrlName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80, -1 ), wxTE_READONLY );
 	m_textCtrlName->SetBackgroundColour( wxColour( 180, 210, 240 ) );
 	bSizerRight->Add( m_textCtrlName, 0, wxALL, 5 );
 	
-	m_textCtrlAddr = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 160, -1 ), 0 );
+	m_textCtrlAddr = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 160, -1 ), wxTE_READONLY );
 	m_textCtrlAddr->SetBackgroundColour( wxColour( 180, 210, 240 ) );
 	bSizerRight->Add( m_textCtrlAddr, 0, wxALL|wxEXPAND, 5 );
 	
@@ -379,15 +407,18 @@
 	m_slider = new wxSlider( this, ID_SLDR, 1, 1, 5, wxDefaultPosition, wxSize( -1, 200 ), wxSL_AUTOTICKS|wxSL_INVERSE|wxSL_LABELS|wxSL_VERTICAL );
 	bSizerRight->Add( m_slider, 0, wxALL, 5 );
 	
+	m_buttonPsearch = new wxButton( this, ID_PSEARCH, wxT( "Paste-Search" ), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizerRight->Add( m_buttonPsearch, 0, wxALL, 5 );
+	
 	m_buttonPrint = new wxButton( this, wxID_PRINT, wxT( "Print" ), wxDefaultPosition, wxDefaultSize, 0 );
 	bSizerRight->Add( m_buttonPrint, 0, wxALL, 5 );
 	
+	m_buttonHelp = new wxButton( this, wxID_HELP, wxT( "Help" ), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizerRight->Add( m_buttonHelp, 0, wxALL, 5 );
+	
 	m_buttonLogout = new wxButton( this, ID_LOGOUT, wxT( "Logout" ), wxDefaultPosition, wxDefaultSize, 0 );
 	bSizerRight->Add( m_buttonLogout, 0, wxALL, 5 );
 	
-	m_buttonTest = new wxButton( this, ID_TEST, wxT( "Test" ), wxDefaultPosition, wxDefaultSize, 0 );
-	bSizerRight->Add( m_buttonTest, 0, wxALL, 5 );
-	
 	bSizerTop->Add( bSizerRight, 0, wxEXPAND, 5 );
 	
 	this->SetSizer( bSizerTop );
@@ -402,10 +433,25 @@
     m_staticBitmap5 = new MyStaticBitmap( m_scrolledWindow5, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0, wxEmptyString );
 }
 
+void MainFrame::SetAccelerator( void )
+{
+	wxAcceleratorEntry entries[2];
+	entries[0].Set( wxACCEL_CTRL,  (int) 'P', wxID_PRINT );
+	entries[1].Set( wxACCEL_NORMAL,  WXK_F1,  wxID_HELP );
+	/*
+	entries[1].Set( wxACCEL_CTRL,  (int) 'X', wxID_EXIT );
+	entries[2].Set( wxACCEL_SHIFT, (int) 'A', ID_ABOUT);
+	entries[3].Set( wxACCEL_NORMAL, WXK_DELETE, wxID_CUT);
+	*/
+	wxAcceleratorTable accel( 2, entries );
+	SetAcceleratorTable( accel );
+}
+
 void MainFrame::Cmd( wxString cmd )
 {
 	m_dataViewListCtrl->DeleteAllItems();
-	LoadBitmaps( wxEmptyString );
+	LoadBitmaps( wxEmptyString, false );
+    wxRegEx reHhs( wxT( "^0[1238][0-9]{8}$" ) );
 
     if ( cmd.IsSameAs( wxT( "q" ), true ) || cmd.IsSameAs( wxT( "9" ), true ) ) {
         Close();
@@ -413,7 +459,6 @@
     }
 
     if ( cmd.IsSameAs( wxT( "c" ), true ) || cmd.IsSameAs( wxT( "cmd" ), true ) ) {
-        Close();
 		return;
     }
 
@@ -430,15 +475,15 @@
     }
 
     if ( cmd.IsSameAs( wxT( "*" ), false ) ) {
-		// cmd = clipboard // paste clipboard
+		PasteSeaarch();
+		return;
 	}
 
     if ( cmd.IsSameAs( wxT( "+" ), false ) ) {
-		// print
+		PrintImages();
         return;
 	}
 
-    wxRegEx reHhs( wxT( "^0[1238][0-9]{8}$" ) );
     if ( reHhs.Matches( cmd ) ) {
 		m_hhs = m_searchCtrl->GetValue();
 		Search();
@@ -448,13 +493,20 @@
 	wxMessageBox( wxT( "Bad Input !!" ) );
 }
 
-void MainFrame::LoadBitmap( wxScrolledWindow* sc, wxStaticBitmap* sb, wxString file )
+bool MainFrame::LoadBitmap( wxScrolledWindow* sc, wxStaticBitmap* sb, wxString file )
 {
+	sb->SetBitmap( wxNullBitmap );
+	sc->Scroll( 0, 0 );
+
+	bool ok = true;
 	if ( startup ) {
-		file = wxT( "image/hw201810.jpg" );
+		file = wxT( "image/hello.jpg" );
 		startup = false;
 	}
-	if ( !wxFileExists( file ) ) file = wxT( "image/testpattern.jpg" );
+	if ( !wxFileExists( file ) ) {
+		file = wxT( "image/testpattern.jpg" );
+		ok = false;
+	}
     wxBitmap bmp( file, wxBITMAP_TYPE_JPEG );
     int width  = bmp.GetWidth();
     int height = bmp.GetHeight();
@@ -466,22 +518,25 @@
     float w = ww - 30;
     float h = w * height / width;
     sb->SetBitmap( wxBitmap( img.Scale( w, h, wxIMAGE_QUALITY_HIGH ) ) );
-    sc->SetScrollbars( 10, 10, w / 10, h / 10 );
+    sc->SetScrollbars( 10, 10, (int)w / 10, (int)h / 10 );
 
-    for ( int i = 0; i < 5; i++ ) {
-        w *= 1.1;
-        h *= 1.1;
-        //sb->SetImage( i, wxBitmap( img.Scale( w, h, wxIMAGE_QUALITY_HIGH ) ) );
-    }
+	return ok;
 }
 
-void MainFrame::LoadBitmaps( wxString date )
+bool MainFrame::LoadBitmaps( wxString date, bool reload )
 {
-    LoadBitmap( m_scrolledWindow1, m_staticBitmap1, wxString::Format( wxT( ".cache/%08s_1" ), date ) );
-    LoadBitmap( m_scrolledWindow2, m_staticBitmap2, wxString::Format( wxT( ".cache/%08s_2" ), date ) );
-    LoadBitmap( m_scrolledWindow3, m_staticBitmap3, wxString::Format( wxT( ".cache/%08s_3" ), date ) );
-    LoadBitmap( m_scrolledWindow4, m_staticBitmap4, wxString::Format( wxT( ".cache/%08s_4" ), date ) );
-    LoadBitmap( m_scrolledWindow5, m_staticBitmap5, wxString::Format( wxT( ".cache/%08s_5" ), date ) );
+	bool ok;
+    ok = LoadBitmap( m_scrolledWindow1, m_staticBitmap1, wxString::Format( wxT( ".cache/%08s_1" ), date ) );
+    ok = LoadBitmap( m_scrolledWindow2, m_staticBitmap2, wxString::Format( wxT( ".cache/%08s_2" ), date ) );
+    ok = LoadBitmap( m_scrolledWindow3, m_staticBitmap3, wxString::Format( wxT( ".cache/%08s_3" ), date ) );
+    ok = LoadBitmap( m_scrolledWindow4, m_staticBitmap4, wxString::Format( wxT( ".cache/%08s_4" ), date ) );
+    ok = LoadBitmap( m_scrolledWindow5, m_staticBitmap5, wxString::Format( wxT( ".cache/%08s_5" ), date ) );
+
+	if ( !ok && reload ) {
+		wxSleep( 5 );
+		LoadBitmaps( date, false );
+	}
+	return ok;
 }
 
 void MainFrame::GetImages( wxString hhs, wxString date )
@@ -492,7 +547,6 @@
 	args.Add( hhs );
 	args.Add( date );
 
-	//wxMessageBox( wxJoin( args, ' ', '\\' ) );
 	int estimate = 5;
     wxProgressDialog pd( wxT( "Connecting Server" ), wxT( "Start..." ), estimate, NULL, wxPD_APP_MODAL|wxPD_ELAPSED_TIME|wxPD_REMAINING_TIME|wxPD_AUTO_HIDE );
     pd.SetSize( wxSize( 320, 140 ) );
@@ -506,6 +560,13 @@
 
 void MainFrame::Search( void )
 {
+	// hhs info
+	if ( hhash.count( m_hhs ) ) {
+		m_textCtrlName->SetValue( hhash[ m_hhs ]->name );
+		m_textCtrlAddr->SetValue( hhash[ m_hhs ]->addr );
+	}
+
+	// index
 	wxString date;
 	int match_cnt = 0;
 	for ( int i = 0; i < m_index.GetCount(); i++ ) {
@@ -519,11 +580,28 @@
 			data.clear();
 		}
 	}
-	if ( match_cnt == 0 ) wxMessageBox( wxT( "Not Matched !!" ) );
+
+	if ( match_cnt == 0 ) {
+		wxMessageBox( wxT( "Not Matched !!" ) );
+	} else {
+		wxString date = m_dataViewListCtrl->GetTextValue( 0, 1 );
+		date.Replace( wxT( "-" ), wxEmptyString, true );
+		GetImages( m_hhs, date );
+		if ( LoadBitmaps( date, true ) ) {
+			m_dataViewListCtrl->SetTextValue( wxT( "OK" ), 0, 2 );
+			m_dataViewListCtrl->SelectRow( 0 );
+		}
+	}
+
+	WriteLog( wxT( "[search] " ) + m_hhs );
 }
 
 void MainFrame::LoadDB( void )
 {
+    wxProgressDialog pd( wxT( "Load Data" ), wxT( "Now loading..." ), 100, NULL, wxPD_APP_MODAL|wxPD_ELAPSED_TIME|wxPD_REMAINING_TIME|wxPD_AUTO_HIDE );
+    pd.SetSize( wxSize( 320, 140 ) );
+	
+	// index
 	wxTextFile file;
 	file.Open( wxT( "index.db" ) );
 	for ( int i = 0; i < file.GetLineCount(); i++ )
@@ -531,13 +609,53 @@
 	file.Close();
 	m_index.Sort( true );
 
-	/*
-	file.Open( wxT( "hhs.db" ) );
-	for ( int i = 0; i < file.GetLineCount(); i++ ) {
-	//
+	// decrypto
+	wxString key = wxT( "12345678900123456789abcdefabcdef" );
+	wxArrayString args;
+	args.Add( wxT( "crypto.exe" ) );
+	args.Add( wxT( "-d" ) );
+	args.Add( wxT( "hhs.db" ) );
+	args.Add( wxT( "-k" ) );
+	args.Add( key );
+
+	wxArrayString output, errors;
+	wxExecute( wxJoin( args, ' ', '\\' ), output, errors );
+
+	for ( int i = 0; i < 100; i++ ) {
+		wxMilliSleep( 2 );
+		pd.Update( i, wxString::Format( wxT( "Now loding ... ( %0.1f %% )" ), (float)i ) );
+	}
+	if ( errors.GetCount() > 0 ) {
+		wxMessageBox( errors[0] );
+		return;
+	}
+	for ( int i = 0; i < output.GetCount(); i++ ) {
+		wxArrayString buf = wxSplit( output[i], ',', '\\' );
+		hhash[ buf[0] ] = new HhsClass( buf ); // no, birth, name, kana, addr, sex
 	}
-	file.Close();
-	*/
+}
+
+void MainFrame::PasteSeaarch( void )
+{
+	wxString s;
+	if ( wxTheClipboard->Open() ) {
+		if ( wxTheClipboard->IsSupported( wxDF_TEXT ) ) {
+			wxTextDataObject data;
+			wxTheClipboard->GetData( data );
+			s = data.GetText();
+		}
+		wxTheClipboard->Close();
+	}
+
+	s.Replace( wxT(" "), wxT(""), true );
+    wxRegEx reHhs( wxT( "^0[1238][0-9]{8}$" ) );
+	if ( reHhs.Matches( s ) ) {
+		m_searchCtrl->SetValue( s );
+		m_hhs = m_searchCtrl->GetValue();
+		Search();
+		return;
+	}
+	wxMessageBox( wxT( "Bad Input !!" ) );
 }
 
 void MainFrame::PrintImages( void )
@@ -578,6 +696,8 @@
 
 	hpout.SetHtmlText( html, wxEmptyString, false );
 	p.Print( NULL, &hpout, true );
+
+	WriteLog( wxT( "[print]" ) );
 }
 
 void MainFrame::RemoveFile( wxString pattern )
@@ -589,10 +709,28 @@
 	}
 }
 
+void MainFrame::WriteLog( wxString msg )
+{
+	wxDateTime now = wxDateTime::Now();
+	wxString file = wxGetCwd() + wxFILE_SEP_PATH + wxT( "log" ) + wxFILE_SEP_PATH + now.Format( wxT( "%Y%m%d" ) ) + wxT( ".log" );
+
+	wxTextFile logfile;
+	if ( !wxFileExists( file ) ) logfile.Create( file );
+
+	logfile.Open( file );
+	logfile.AddLine( now.Format( wxT("%Y-%m-%d %H:%M:%S ") ) + msg );
+    logfile.Write();
+    logfile.Close();
+}
+
 void MainFrame::InDevelop( bool flag )
 {
     if ( !flag ) return;
     
+	bool he = false;
+	m_buttonHelp->Enable( he );
+	m_buttonHelp->Show( he );
+
 	bool lo = false;
 	m_buttonLogout->Enable( lo );
 	m_buttonLogout->Show( lo );
@@ -601,13 +739,6 @@
 	m_slider->Enable( sl );
 	m_slider->Show( sl );
 
-	bool tb = false;
-	m_buttonTest->Enable( tb );
-	m_buttonTest->Show( tb );
-
 	return;
-
-	// search
-	m_searchCtrl->SetValue( wxT( "0100122642" ) );
 }