changeset 1:e4aa0e7a07ad

Second release.
author pyon@macmini
date Sun, 13 Sep 2015 14:56:42 +0900
parents cb3403ca39b1
children 50d9f4e2a540
files Makefile image/sample.ico image/sample.xpm include/adddialog.h include/mainframe.h src/adddialog.cpp src/main.cpp src/mainframe.cpp
diffstat 8 files changed, 561 insertions(+), 254 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun Aug 30 21:53:19 2015 +0900
+++ b/Makefile	Sun Sep 13 14:56:42 2015 +0900
@@ -1,5 +1,5 @@
 # Makefile for wxWidgets Application
-# Last Change: 2015-08-30 Sun 12:54:13.
+# Last Change: 2015-09-06 Sun 20:27:26.
 # by Takayuki Mutoh
 #
 
@@ -57,7 +57,7 @@
 	-mkdir -p $(OBJDIR)
 	$(CXX) -c $< -o $@ $(CXXFLAGS)
 
-$(OBJDIR)/mainframe.o: mainframe.cpp mainframe.h
+$(OBJDIR)/mainframe.o: mainframe.cpp mainframe.h qdata.h
 	$(CXX) -c $< -o $@ $(CXXFLAGS)
 
 $(OBJDIR)/adddialog.o: adddialog.cpp adddialog.h
Binary file image/sample.ico has changed
--- a/image/sample.xpm	Sun Aug 30 21:53:19 2015 +0900
+++ b/image/sample.xpm	Sun Sep 13 14:56:42 2015 +0900
@@ -1,92 +1,78 @@
-/* XPM */
-//static char *sample_xpm[] = {
-const char *sample_xpm[] = {
-/* columns rows colors chars-per-pixel */
-"32 32 53 1 ",
-"  c #FAFA00000202",
-". c #FEFE00000000",
-"X c red",
-"o c #F9F900000505",
-"O c #F5F500000909",
-"+ c #F6F600000808",
-"@ c #EBEB00001111",
-"# c #DADA00002424",
-"$ c #D8D800002626",
-"% c #C3C300003B3B",
-"& c #C6C600003838",
-"* c #C4C400003A3A",
-"= c #C1C100003D3D",
-"- c #B7B700004747",
-"; c #BCBC00004040",
-": c #BEBE00004040",
-"> c #ABAB00005151",
-", c #AAAA00005353",
-"< c #ABAB00005353",
-"1 c #999900006565",
-"2 c #959500006969",
-"3 c #5F5F00009F9F",
-"4 c #777700008787",
-"5 c #737300008B8B",
-"6 c #6D6D00009090",
-"7 c #616100009D9D",
-"8 c #626200009C9C",
-"9 c #54540000AAAA",
-"0 c #47470000B7B7",
-"q c #44440000BABA",
-"w c #42420000BCBC",
-"e c #2B2B0000D3D3",
-"r c #29290000D5D5",
-"t c #28280000D6D6",
-"y c #25250000D9D9",
-"u c #20200000DEDE",
-"i c #17170000E7E7",
-"p c #1A1A0000E3E3",
-"a c #19190000E5E5",
-"s c #13130000EBEB",
-"d c #14140000EAEA",
-"f c #10100000EDED",
-"g c #09090000F3F3",
-"h c #0D0D0000F1F1",
-"j c #0C0C0000F2F2",
-"k c #03030000FBFB",
-"l c #04040000FAFA",
-"z c #01010000FCFC",
-"x c #00000000FDFD",
-"c c #01010000FDFD",
-"v c #00000000FEFE",
-"b c blue",
-"n c None",
-/* pixels */
-"nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn",
-"nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn",
-"nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn",
-"nnnnnnnnnnnn...........nnnnnnnnn",
-"nnnnnnnnn.................nnnnnn",
-"nnnnnnn....................nnnnn",
-"nnnnnn.....................nnnnn",
-"nnnnn.....................nnnnnn",
-"nnnnn........nnnnnnn......nnnnnn",
-"nnnn.......nnnnnnnnnnnn...nnnnnn",
-"nnnn.......nnnnnnnnnnnnn..nnnnnn",
-"nnnn.......nnnnnnnnnnnnnnnnnnnnn",
-"nnnn.........nnnnnnnnnnnnnnnnnnn",
-"nnnn............nnnnnnnnnnnnnnnn",
-"nnnnn...............nnnnnnnnnnnn",
-"nnnnnn................nnnnnnnnnn",
-"nnnnnnn................nnnnnnnnn",
-"nnnnnnnnnn.<0ibfq<..*4qabbbbbnnn",
-"nnnnnnnnnnbbbbbbbb5.bbbbbbbbbbnn",
-"nnnnnnnnnnbbbnnnfbb*bb9-@nnbbbbn",
-"nnnnnnnnnbbbnnnnnbb7u*...nnnbbbn",
-"nn..nnnnnbbbnnnnnbbr.....nnbbbnn",
-"nn....nnnbbbnnnnnbbf...bbbbbbnnn",
-"nn......nbbbnnnn.bbb...bbbbbbbnn",
-"nn.......gbb....Obbf....nnnbbbbn",
-"n........ubb$...$bbr...nnnnnbbbn",
-"n........3bb1...2bb7u*nnnnnnbbbn",
-"nn.......*bba*.*ibb<bbbnnnnbbbbn",
-"nnnnnn....6bbbbbbbgnbbbbbbbbbbnn",
-"nnnnnnnnnnnnbbbbbnnnnbbbbbbbnnnn",
-"nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn",
-"nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"
-};
+/* XPM */
+//static char* sample_xpm[] = {
+const char *sample_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 41 1",
+" 	c None",
+".	c #F4F249",
+"+	c #EBED51",
+"@	c #C5D677",
+"#	c #94B9A8",
+"$	c #69A0D3",
+"%	c #4E90EE",
+"&	c #E3E859",
+"*	c #90B7AC",
+"=	c #498DF4",
+"-	c #AEC98E",
+";	c #EFEF4D",
+">	c #82AEBB",
+",	c #F1F04B",
+"'	c #75A7C7",
+")	c #6DA2CF",
+"!	c #A2C19A",
+"~	c #7DACBF",
+"{	c #CBD971",
+"]	c #C4D578",
+"^	c #4F90ED",
+"/	c #B5CD87",
+"(	c #5D98DF",
+"_	c #D4DF68",
+":	c #A3C299",
+"<	c #DEE55E",
+"[	c #649DD8",
+"}	c #B4CC88",
+"|	c #B0C98C",
+"1	c #87B1B5",
+"2	c #5091EC",
+"3	c #F0F04C",
+"4	c #629CDA",
+"5	c #86B1B6",
+"6	c #F4DD58",
+"7	c #F4938F",
+"8	c #F457BB",
+"9	c #B0CA8C",
+"0	c #F4BE6E",
+"a	c #F449C6",
+"b	c #F3F149",
+"................................",
+"...........+@#$%%$#@+...........",
+".........&*==========*&.........",
+"........-==============-........",
+"......;>================>;......",
+".....,'=======)!!)=======',.....",
+".....*======~{....{~======*.....",
+"....]=====^/......../^=====]....",
+"...;=====(_.........._(=====;...",
+".../====={............{=====/...",
+"...^====:..............:====^...",
+"..<====[................[====<..",
+"..}====|................|====}..",
+"..1===23................32===1..",
+"..4===5........678876....5===4..",
+"..%===9.......0aaaaaa0...9===%..",
+"..%===9......6aaaaaaaa6..9===%..",
+"..4===5......7aaaaaaaa7..5===4..",
+"..1===23.....8aaaaaaaa8.32===1..",
+"..}====|.....8aaaaaaaa8.|====}..",
+"..<====[.....7aaaaaaaa7.[====<..",
+"...^====:....6aaaaaaaa6:====^...",
+".../====={....0aaaaaa0{=====/...",
+"...;=====(_....678876_(=====;...",
+"....]=====^/......../^=====]....",
+".....*======~{....{~======*...b.",
+".....,'=======)!!)=======',...b.",
+"......;>================>;....b.",
+"........-==============-........",
+".........&*==========*&....b....",
+"...........+@#$%%$#@+...........",
+"................................"};
--- a/include/adddialog.h	Sun Aug 30 21:53:19 2015 +0900
+++ b/include/adddialog.h	Sun Sep 13 14:56:42 2015 +0900
@@ -1,5 +1,5 @@
 // Filename: adddialog.h
-// Last Change: 2015-08-30 Sun 16:00:48.
+// Last Change: 2015-09-12 Sat 11:49:15.
 //
 
 #ifndef __ADDDLG_H__
@@ -8,42 +8,66 @@
 #include <wx/string.h>
 #include <wx/stattext.h>
 #include <wx/gdicmn.h>
+#include <wx/font.h>
+#include <wx/colour.h>
+#include <wx/settings.h>
 #include <wx/textctrl.h>
-#include <wx/choice.h>
+#include <wx/checkbox.h>
+#include <wx/spinctrl.h>
 #include <wx/sizer.h>
 #include <wx/button.h>
 #include <wx/dialog.h>
 
 class AddDialog : public wxDialog 
 {
+    DECLARE_EVENT_TABLE()
 	private:
+        wxString m_text;
+        bool     m_owrite; 
+        int      m_maxat;
+        int      m_maxlt;
+        wxString m_desc;
 	
 	protected:
+		enum
+		{
+			ID_CKOW = wxID_HIGHEST + 101,
+            ID_SPNML,
+            ID_SPNMA,
+		};
+		
 		wxStaticText* m_staticText;
-
 		wxStaticText* m_staticTextText;
 		wxTextCtrl*   m_textCtrlText;
 		wxStaticText* m_staticTextText2;
-
-		wxStaticText* m_staticTextType;
-		wxChoice*     m_choiceType;
-		wxStaticText* m_staticTextType2;
-
-		wxStaticText* m_staticTextTime;
-		wxTextCtrl*   m_textCtrlTime;
-		wxStaticText* m_staticTextTime2;
-
+		wxStaticText* m_staticTextOverwrite;
+        wxCheckBox*   m_checkBoxOverwrite;
+		wxStaticText* m_staticTextOverwrite2;
+		wxStaticText* m_staticTextMaxLive;
+		wxSpinCtrl*   m_spinCtrlMaxLive;
+		wxStaticText* m_staticTextMaxLive2;
+		wxStaticText* m_staticTextMaxActive;
+		wxSpinCtrl*   m_spinCtrlMaxActive;
+		wxStaticText* m_staticTextMaxActive2;
 		wxStaticText* m_staticTextDesc;
 		wxTextCtrl*   m_textCtrlDesc;
 		wxStaticText* m_staticTextDesc2;
-
 		wxButton*     m_buttonAdd;
 		wxButton*     m_buttonCancel;
 	
 	public:
 		AddDialog( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Set values"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); 
 		~AddDialog();
-	
+
+        void OnCheckOverwrite( wxCommandEvent& );
+        void Init();
+        void SetValidators();
+
+        wxString GetText() {          return m_text; };
+        bool     GetOverwrite() {     return m_owrite; };
+        int      GetMaxActiveTime() { return m_maxat; };
+        int      GetMaxLiveTime() {   return m_maxlt; };
+        wxString GetDesc() {          return m_desc; };
 };
 
 #endif //__ADDDLG_H__
--- a/include/mainframe.h	Sun Aug 30 21:53:19 2015 +0900
+++ b/include/mainframe.h	Sun Sep 13 14:56:42 2015 +0900
@@ -1,10 +1,11 @@
 // Filename: mainframe.h
-// Last Change: 2015-08-30 Sun 20:35:50.
+// Last Change: 2015-09-13 Sun 13:44:36.
 //
 #ifndef __MAINFRAME_H__
 #define __MAINFRAME_H__
 
 #include <wx/listctrl.h>
+#include <wx/listbox.h>
 #include <wx/gdicmn.h>
 #include <wx/font.h>
 #include <wx/colour.h>
@@ -19,26 +20,34 @@
 #include <wx/frame.h>
 #include <wx/timer.h>
 
+#include "qdata.h"
+WX_DECLARE_HASH_MAP( int, QlipData*, wxIntegerHash, wxIntegerEqual, QlipDataHash );
+
 class MainFrame : public wxFrame 
 {
     DECLARE_EVENT_TABLE()
 	private:
-        wxTimer  m_timer;
-        int      m_current;
-        long     m_counter;
-        wxString m_last;
+        wxTimer      m_timer;
+        int          m_current;
+        int          m_counter;
+        int          m_period;
+        bool         m_bottom;
+        QlipDataHash QH;
 	
 	protected:
 		enum
 		{
-			ID_MNABOUT = wxID_HIGHEST + 1,
+			ID_MNAPPDIR = wxID_HIGHEST + 1,
+			ID_MNINTERVAL,
+			ID_MNABOUT,
 			ID_MNEXIT,
 			ID_MNLDPGIN,
 			ID_MNSVPGIN,
 
             ID_TIMER,
 			ID_TGL,
-            ID_LIST,
+            ID_LISTVIEW,
+            ID_LISTBOX,
 
 			ID_BTNUP,
 			ID_BTNDOWN,
@@ -52,9 +61,13 @@
 		wxMenu*    m_menuPlugin;
 
         wxTextCtrl*     m_textCtrlShow;
+        wxTextCtrl*     m_textCtrlRemain;
 		wxToggleButton* m_toggleBtn;
 	
-		wxListView* m_listView;
+        wxStaticText* m_staticTextCycle;
+		wxListView*   m_lisViewCycle;
+        wxStaticText* m_staticTextHist;
+		wxListBox*    m_listBoxHist;
 
 		wxButton*   m_buttonUp;
 		wxButton*   m_buttonDown;
@@ -67,13 +80,16 @@
 		~MainFrame();
 
         // Event Handlers
+        void OnMNAppdir( wxCommandEvent& );
+        void OnMNInterval( wxCommandEvent& );
         void OnMNAbout( wxCommandEvent& );
         void OnMNExit( wxCommandEvent& );
         void OnMNLoad( wxCommandEvent& );
         void OnMNSaveAs( wxCommandEvent& );
 
-        void OnDClickItem( wxListEvent& );
-        void OnSelectItem( wxListEvent& );
+        void OnLViewDClickItem( wxListEvent& );
+        void OnLViewSelectItem( wxListEvent& );
+        void OnLBoxDClickItem( wxCommandEvent& );
 
         void OnToggle( wxCommandEvent& );
         void OnTimer( wxTimerEvent& );
@@ -88,7 +104,12 @@
         void EnableButtons( bool );
         void SwapListItem( long, long );
         void ReNumberList();
-        void DoProcess();
+        int  CreateID();
+        void AddStackTime();
+        void UpdateView();
+        void UpdateHistory( wxString );
+        int  GetEmptyStack();
+        int  ToInt( wxString );
 };
 
 #endif //__MAINFRAME_H__
--- a/src/adddialog.cpp	Sun Aug 30 21:53:19 2015 +0900
+++ b/src/adddialog.cpp	Sun Sep 13 14:56:42 2015 +0900
@@ -1,6 +1,8 @@
 // Filename: adddialog.cpp
-// Last Change: 2015-08-30 Sun 16:02:17.
+// Last Change: 2015-09-13 Sun 14:34:28.
 //
+#include <wx/valgen.h>
+#include <wx/valtext.h>
 
 #include "adddialog.h"
 
@@ -11,14 +13,13 @@
 	
 	wxBoxSizer* bSizerTop = new wxBoxSizer( wxVERTICAL );
 	
-	m_staticText = new wxStaticText( this, wxID_ANY, wxT("Specify Empty text to use User input(Ctrl-c).\nDescription is option."), wxDefaultPosition, wxDefaultSize, 0 );
-	bSizerTop->Add( m_staticText, 0, wxALL|wxEXPAND, 10 );
+	m_staticText = new wxStaticText( this, wxID_ANY, wxT("Specify Empty text to Use user input(Ctrl-c).\nDescription is option."), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizerTop->Add( m_staticText, 0, wxALL|wxEXPAND, 5 );
 	
 	wxFlexGridSizer* fgSizer = new wxFlexGridSizer( 0, 3, 0, 0 );
 	fgSizer->SetFlexibleDirection( wxBOTH );
 	fgSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
 	
-    // text
 	m_staticTextText = new wxStaticText( this, wxID_ANY, wxT("Text"), wxDefaultPosition, wxDefaultSize, 0 );
 	fgSizer->Add( m_staticTextText, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
 	
@@ -28,29 +29,33 @@
 	m_staticTextText2 = new wxStaticText( this, wxID_ANY, wxT("Strings to paste"), wxDefaultPosition, wxDefaultSize, 0 );
 	fgSizer->Add( m_staticTextText2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 	
-    // type
-	m_staticTextType = new wxStaticText( this, wxID_ANY, wxT("Type"), wxDefaultPosition, wxDefaultSize, 0 );
-	fgSizer->Add( m_staticTextType, 0, wxALL|wxALIGN_RIGHT, 5 );
+	m_staticTextOverwrite = new wxStaticText( this, wxID_ANY, wxT("Overwrite"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizer->Add( m_staticTextOverwrite, 0, wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 );
+
+	m_checkBoxOverwrite = new wxCheckBox( this, ID_CKOW, wxT("allow change"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizer->Add( m_checkBoxOverwrite, 0, wxALL, 5 );
 	
-	wxString m_choiceTypeChoices[] = { wxT("a"), wxT("ab"), wxT("cc"), };
-	int m_choiceTypeNChoices = sizeof( m_choiceTypeChoices ) / sizeof( wxString );
-	m_choiceType = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceTypeNChoices, m_choiceTypeChoices, 0 );
-	fgSizer->Add( m_choiceType, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+	m_staticTextOverwrite2 = new wxStaticText( this, wxID_ANY, wxT("Check if allow change by user"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizer->Add( m_staticTextOverwrite2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 	
-	m_staticTextType2 = new wxStaticText( this, wxID_ANY, wxT("Ring / Queue / Stack"), wxDefaultPosition, wxDefaultSize, 0 );
-	fgSizer->Add( m_staticTextType2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+	m_staticTextMaxLive = new wxStaticText( this, wxID_ANY, wxT("Max LT"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizer->Add( m_staticTextMaxLive, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
 	
-    // time
-	m_staticTextTime = new wxStaticText( this, wxID_ANY, wxT("Time"), wxDefaultPosition, wxDefaultSize, 0 );
-	fgSizer->Add( m_staticTextTime, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
+	m_spinCtrlMaxLive = new wxSpinCtrl( this, ID_SPNML, wxT("5"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 28800, 0 );
+	fgSizer->Add( m_spinCtrlMaxLive, 0, wxALL, 5 );
+	
+	m_staticTextMaxLive2 = new wxStaticText( this, wxID_ANY, wxT("Maximum live time"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizer->Add( m_staticTextMaxLive2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 	
-	m_textCtrlTime = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
-	fgSizer->Add( m_textCtrlTime, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+	m_staticTextMaxActive = new wxStaticText( this, wxID_ANY, wxT("Max AT"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizer->Add( m_staticTextMaxActive, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
 	
-	m_staticTextTime2 = new wxStaticText( this, wxID_ANY, wxT("interval"), wxDefaultPosition, wxDefaultSize, 0 );
-    fgSizer->Add( m_staticTextTime2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
-
-    // desc
+	m_spinCtrlMaxActive = new wxSpinCtrl( this, ID_SPNMA, wxT("5"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 28800, 0 );
+	fgSizer->Add( m_spinCtrlMaxActive, 0, wxALL, 5 );
+	
+	m_staticTextMaxActive2 = new wxStaticText( this, wxID_ANY, wxT("Maximum active time"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizer->Add( m_staticTextMaxActive2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+	
 	m_staticTextDesc = new wxStaticText( this, wxID_ANY, wxT("Desc"), wxDefaultPosition, wxDefaultSize, 0 );
 	fgSizer->Add( m_staticTextDesc, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
 	
@@ -58,7 +63,7 @@
 	fgSizer->Add( m_textCtrlDesc, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 	
 	m_staticTextDesc2 = new wxStaticText( this, wxID_ANY, wxT("Description"), wxDefaultPosition, wxDefaultSize, 0 );
-    fgSizer->Add( m_staticTextDesc2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+	fgSizer->Add( m_staticTextDesc2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 	
 	bSizerTop->Add( fgSizer, 1, wxEXPAND, 5 );
 	
@@ -74,13 +79,58 @@
 	bSizerTop->Add( bSizerBtn, 0, wxALIGN_RIGHT, 5 );
 	
 	this->SetSizer( bSizerTop );
+
 	this->Layout();
 	bSizerTop->Fit( this );
 	
 	this->Centre( wxBOTH );
+
+    Init();
+    SetValidators();
 }
 
 AddDialog::~AddDialog()
 {
 }
 
+// Event Table
+BEGIN_EVENT_TABLE( AddDialog, wxDialog )
+    EVT_CHECKBOX( ID_CKOW, AddDialog::OnCheckOverwrite )
+END_EVENT_TABLE()
+
+/* Event Handlers & Functions */
+// Event Handlers
+void AddDialog::OnCheckOverwrite( wxCommandEvent& event )
+{
+    if ( event.IsChecked() ) {
+        m_textCtrlText->Enable( false );
+        m_textCtrlText->SetValue( wxEmptyString );
+        m_spinCtrlMaxLive->Enable( true );
+    }
+    else {
+        m_textCtrlText->Enable( true );
+        m_textCtrlText->SetValue( wxT("Something") );
+        m_spinCtrlMaxLive->Enable( false );
+    }
+}
+
+// Functions
+void AddDialog::Init()
+{
+    m_text = wxT("Something");
+    m_owrite = false; 
+    m_maxat = 5;
+    m_maxlt = 20;
+    m_desc = wxEmptyString;
+    m_spinCtrlMaxLive->Enable( false );
+}
+
+void AddDialog::SetValidators()
+{
+    m_textCtrlText->SetValidator( wxTextValidator( wxFILTER_NONE, &m_text ) );
+    m_checkBoxOverwrite->SetValidator( wxGenericValidator( &m_owrite ) );
+    m_spinCtrlMaxLive->SetValidator( wxGenericValidator( &m_maxlt ) );
+    m_spinCtrlMaxActive->SetValidator( wxGenericValidator( &m_maxat ) );
+    m_textCtrlDesc->SetValidator( wxTextValidator( wxFILTER_NONE, &m_desc ) );
+}
+
--- a/src/main.cpp	Sun Aug 30 21:53:19 2015 +0900
+++ b/src/main.cpp	Sun Sep 13 14:56:42 2015 +0900
@@ -1,5 +1,5 @@
 // Filename   : main.cpp
-// Last Change: 2015-08-26 Wed 19:51:32.
+// Last Change: 2015-09-02 Wed 21:31:52.
 //
 #include "main.h"
 #include "mainframe.h"
@@ -20,7 +20,7 @@
 {
     if ( !wxApp::OnInit() ) return false;
 
-    MainFrame *mainframe = new MainFrame( NULL, wxID_ANY, wxT("QlipBoard"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE );
+    MainFrame *mainframe = new MainFrame( NULL, wxID_ANY, wxT("QlipBoard"), wxDefaultPosition, wxSize( 400, 450 ), wxDEFAULT_FRAME_STYLE );
     mainframe->Show( true );
 
     return true;
--- a/src/mainframe.cpp	Sun Aug 30 21:53:19 2015 +0900
+++ b/src/mainframe.cpp	Sun Sep 13 14:56:42 2015 +0900
@@ -1,11 +1,12 @@
 // Filename: mainframe.cpp
-// Last Change: 2015-08-30 Sun 21:49:16.
+// Last Change: 2015-09-13 Sun 14:43:27.
 //
 #include <wx/filedlg.h>
 #include <wx/textfile.h>
 #include <wx/clipbrd.h>
 #include <wx/utils.h>
 #include <wx/msgdlg.h>
+#include "wx/numdlg.h"
 
 #include "mainframe.h"
 #include "adddialog.h"
@@ -15,16 +16,34 @@
     #include "sample.xpm"
 #endif
 
+#define COL_NO   0
+#define COL_TEXT 1
+#define COL_OW   2
+#define COL_MLT  3
+#define COL_MAL  4
+#define COL_DESC 5
+#define COL_ID   6
+
 MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) 
-    : wxFrame( parent, id, title, pos, size, style ), m_timer( this, ID_TIMER )
+    : wxFrame( parent, id, title, pos, size, style ), 
+      m_timer( this, ID_TIMER ),
+      m_counter( 0 ),
+      m_period( 5 ),
+      m_bottom( true )
 {
-	this->SetSizeHints( wxDefaultSize, wxDefaultSize );
+	this->SetSizeHints( wxSize( 500, 450 ), wxDefaultSize );
     this->SetBackgroundColour( wxColour( wxT("WHEAT") ) );
     SetIcon( wxICON( sample ) );
 
     // menu bar
 	m_menubar = new wxMenuBar( 0 );
 	m_menuFile = new wxMenu();
+	wxMenuItem* m_menuItemAppdir = new wxMenuItem( m_menuFile, ID_MNAPPDIR, wxString( wxT("Open App Forlder") ), wxEmptyString, wxITEM_NORMAL );
+	m_menuFile->Append( m_menuItemAppdir );
+
+	wxMenuItem* m_menuItemInterval = new wxMenuItem( m_menuFile, ID_MNINTERVAL, wxString( wxT("Set Interval") ), wxEmptyString, wxITEM_NORMAL );
+	m_menuFile->Append( m_menuItemInterval );
+
 	wxMenuItem* m_menuItemAbout = new wxMenuItem( m_menuFile, ID_MNABOUT, wxString( wxT("About") ), wxEmptyString, wxITEM_NORMAL );
 	m_menuFile->Append( m_menuItemAbout );
 	
@@ -53,36 +72,48 @@
 	m_textCtrlShow = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
 	bSizerShow->Add( m_textCtrlShow, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 
+	m_textCtrlRemain = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 40, -1 ), wxTE_READONLY|wxTE_CENTER );
+	bSizerShow->Add( m_textCtrlRemain, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 );
+
 	m_toggleBtn = new wxToggleButton( this, ID_TGL, wxT("ON"), wxDefaultPosition, wxSize( 60, -1 ), 0 );
 	bSizerShow->Add( m_toggleBtn, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 
 	bSizerTop->Add( bSizerShow, 0, wxEXPAND, 5 );
 	
     //
-	wxBoxSizer* bSizerList = new wxBoxSizer( wxHORIZONTAL );
+	wxBoxSizer* bSizerMain = new wxBoxSizer( wxHORIZONTAL );
 	
-	m_listView = new wxListView( this, ID_LIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_SINGLE_SEL );
-	bSizerList->Add( m_listView, 1, wxALL|wxEXPAND, 5 );
+    // list
+	wxBoxSizer* bSizerList = new wxBoxSizer( wxVERTICAL );
+
+	m_staticTextCycle = new wxStaticText( this, wxID_ANY, wxT("Cycle list"), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizerList->Add( m_staticTextCycle, 0, wxTOP|wxLEFT|wxALIGN_BOTTOM, 5 );
+
+	m_lisViewCycle = new wxListView( this, ID_LISTVIEW, wxDefaultPosition, wxSize( -1, 100 ), wxLC_REPORT|wxLC_SINGLE_SEL );
     wxListItem itemCol;
-    itemCol.SetText( wxT("No") );
-    m_listView->InsertColumn( 0, itemCol );
-    m_listView->SetColumnWidth( 0, 40 );
-    itemCol.SetText( wxT("text") );
-    m_listView->InsertColumn( 1, itemCol );
-    m_listView->SetColumnWidth( 1, 80 );
-    itemCol.SetText( wxT("time") );
-    m_listView->InsertColumn( 2, itemCol );
-    m_listView->SetColumnWidth( 2, 40 );
-    itemCol.SetText( wxT("type") );
-    m_listView->InsertColumn( 3, itemCol );
-    m_listView->SetColumnWidth( 3, 40 );
-    itemCol.SetText( wxT("desc") );
-    m_listView->InsertColumn( 4, itemCol );
-    m_listView->SetColumnWidth( 4, 80 );
-    //m_listView->EnableAlternateRowColours( true );
+    itemCol.SetText( wxT("No") );     m_lisViewCycle->InsertColumn( COL_NO,   itemCol ); m_lisViewCycle->SetColumnWidth( COL_NO,   20 );
+    itemCol.SetText( wxT("text") );   m_lisViewCycle->InsertColumn( COL_TEXT, itemCol ); m_lisViewCycle->SetColumnWidth( COL_TEXT, 80 );
+    itemCol.SetText( wxT("o/w") );    m_lisViewCycle->InsertColumn( COL_OW,   itemCol ); m_lisViewCycle->SetColumnWidth( COL_OW,   40 );
+    itemCol.SetText( wxT("live") );   m_lisViewCycle->InsertColumn( COL_MLT,  itemCol ); m_lisViewCycle->SetColumnWidth( COL_MLT,  50 );
+    itemCol.SetText( wxT("active") ); m_lisViewCycle->InsertColumn( COL_MAL,  itemCol ); m_lisViewCycle->SetColumnWidth( COL_MAL,  50 );
+    itemCol.SetText( wxT("desc") );   m_lisViewCycle->InsertColumn( COL_DESC, itemCol ); m_lisViewCycle->SetColumnWidth( COL_DESC, 80 );
+    itemCol.SetText( wxT("id") );     m_lisViewCycle->InsertColumn( COL_ID,   itemCol ); m_lisViewCycle->SetColumnWidth( COL_ID,   30 );
+    //m_lisViewCycle->EnableAlternateRowColours( true );
+	bSizerList->Add( m_lisViewCycle, 1, wxALL|wxEXPAND, 5 );
 	
+	m_staticTextHist = new wxStaticText( this, wxID_ANY, wxT("User input history"), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizerList->Add( m_staticTextHist, 0, wxTOP|wxLEFT|wxALIGN_BOTTOM, 5 );
+
+    m_listBoxHist = new wxListBox( this, ID_LISTBOX, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE );
+	bSizerList->Add( m_listBoxHist, 1, wxALL|wxEXPAND, 5 );
+
+	bSizerMain->Add( bSizerList, 1, wxEXPAND, 5 );
+
+    // button
 	wxBoxSizer* bSizerBtn = new wxBoxSizer( wxVERTICAL );
 	
+	bSizerBtn->Add( 0, 20, 0, 0, 5 );
+
 	m_buttonUp = new wxButton( this, ID_BTNUP, wxT("↑"), wxDefaultPosition, wxSize( 40, -1 ), 0 );
 	bSizerBtn->Add( m_buttonUp, 0, wxALL, 5 );
 	
@@ -100,8 +131,9 @@
 	m_buttonExit = new wxButton( this, ID_EXIT, wxT("Exit"), wxDefaultPosition, wxSize( 60, -1 ), 0 );
 	bSizerBtn->Add( m_buttonExit, 0, wxALL, 5 );
 	
-	bSizerList->Add( bSizerBtn, 0, wxEXPAND, 5 );
-	bSizerTop->Add( bSizerList, 1, wxEXPAND, 5 );
+	bSizerMain->Add( bSizerBtn, 0, wxEXPAND, 5 );
+
+	bSizerTop->Add( bSizerMain, 1, wxEXPAND, 5 );
 	
 	this->SetSizer( bSizerTop );
 	this->Layout();
@@ -115,19 +147,22 @@
 
 // Event Table
 BEGIN_EVENT_TABLE( MainFrame, wxFrame )
-    EVT_MENU( ID_MNABOUT,  MainFrame::OnMNAbout )
-    EVT_MENU( ID_MNEXIT,   MainFrame::OnMNExit )
-    EVT_MENU( ID_MNLDPGIN, MainFrame::OnMNLoad )
-    EVT_MENU( ID_MNSVPGIN, MainFrame::OnMNSaveAs )
-    EVT_LIST_ITEM_ACTIVATED( ID_LIST, MainFrame::OnDClickItem )
-    EVT_LIST_ITEM_SELECTED( ID_LIST, MainFrame::OnSelectItem )
+    EVT_MENU( ID_MNAPPDIR,   MainFrame::OnMNAppdir   )
+    EVT_MENU( ID_MNINTERVAL, MainFrame::OnMNInterval )
+    EVT_MENU( ID_MNABOUT,    MainFrame::OnMNAbout    )
+    EVT_MENU( ID_MNEXIT,     MainFrame::OnMNExit     )
+    EVT_MENU( ID_MNLDPGIN,   MainFrame::OnMNLoad     )
+    EVT_MENU( ID_MNSVPGIN,   MainFrame::OnMNSaveAs   )
+    EVT_LIST_ITEM_ACTIVATED( ID_LISTVIEW, MainFrame::OnLViewDClickItem  )
+    EVT_LIST_ITEM_SELECTED(  ID_LISTVIEW, MainFrame::OnLViewSelectItem )
+    EVT_LISTBOX_DCLICK( ID_LISTBOX, MainFrame::OnLBoxDClickItem )
     EVT_TIMER( ID_TIMER, MainFrame::OnTimer )
-    EVT_BUTTON( ID_BTNUP,     MainFrame::OnBtnUp )
+    EVT_BUTTON( ID_BTNUP,     MainFrame::OnBtnUp   )
     EVT_BUTTON( ID_BTNDOWN,   MainFrame::OnBtnDown )
-    EVT_BUTTON( ID_BTNDEL,    MainFrame::OnBtnDel )
-    EVT_BUTTON( ID_BTNADD,    MainFrame::OnBtnAdd )
+    EVT_BUTTON( ID_BTNDEL,    MainFrame::OnBtnDel  )
+    EVT_BUTTON( ID_BTNADD,    MainFrame::OnBtnAdd  )
     EVT_BUTTON( ID_EXIT,      MainFrame::OnBtnExit )
-    EVT_TOGGLEBUTTON( ID_TGL, MainFrame::OnToggle )
+    EVT_TOGGLEBUTTON( ID_TGL, MainFrame::OnToggle  )
     /*
     EVT_IDLE( MainFrame::OnIdle )
     EVT_CLOSE( MainFrame::OnClose )
@@ -136,6 +171,20 @@
 
 /* Event Handlers & Functions */
 // Event Handlers
+void MainFrame::OnMNAppdir( wxCommandEvent& WXUNUSED(event) )
+{
+    wxString app_dir = wxGetCwd();
+    wxString execmd = wxT("explorer ") + app_dir;
+    wxExecute( execmd );
+}
+
+void MainFrame::OnMNInterval( wxCommandEvent& WXUNUSED(event) )
+{
+    long t = wxGetNumberFromUser( wxT("text changed by user is preserved specified period."), wxT("Input 1-60[sec]."), wxT("Setting"), 5, 1, 60, this, wxDefaultPosition );
+    if ( t != -1 )  // canceled
+        m_period = (int)t;
+}
+
 void MainFrame::OnMNAbout( wxCommandEvent& WXUNUSED(event) )
 {
     wxInfoMessageBox( this );
@@ -154,23 +203,26 @@
 
     wxTextFile file;
     file.Open( fd.GetPath() );
-    m_listView->DeleteAllItems();
+    m_lisViewCycle->DeleteAllItems();
+    QH.clear();
     for ( int i = 0, n = 0; i < file.GetLineCount(); i++ ) {
         if ( file[i].StartsWith( wxT("#") ) ) 
             continue;
         wxArrayString s = wxSplit( file[i], ',', '\\' );
 
-        m_listView->InsertItem( n, wxString::Format( wxT("%d"), n + 1 ) );
-        m_listView->SetItem( n, 1, s[0] );
-        m_listView->SetItem( n, 2, s[1] );
-        m_listView->SetItem( n, 3, s[2] );
+        m_lisViewCycle->InsertItem( n, wxString::Format( wxT("%d"), n + 1 ) );
+        m_lisViewCycle->SetItem( n, COL_TEXT, s[0] );
+        m_lisViewCycle->SetItem( n, COL_OW,   s[1] );
+        m_lisViewCycle->SetItem( n, COL_MLT,  s[2] );
+        m_lisViewCycle->SetItem( n, COL_MAL,  s[3] );
+        m_lisViewCycle->SetItem( n, COL_DESC, s[4] );
+        m_lisViewCycle->SetItem( n, COL_ID,   s[5] );
         n++;
     }
     file.Close();
 
     m_current = 0;
-    m_last = m_listView->GetItemText( m_current, 1 );
-    m_listView->SetItemState( m_current, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
+    m_lisViewCycle->Select( m_current, true );
 }
 
 void MainFrame::OnMNSaveAs( wxCommandEvent& WXUNUSED(event) )
@@ -187,10 +239,10 @@
     else {
         file.Create();
     }
-    for ( int r = 0; r < m_listView->GetItemCount(); r++ ) {
+    for ( int r = 0; r < m_lisViewCycle->GetItemCount(); r++ ) {
         wxArrayString s;
-        for ( int c = 0; c < m_listView->GetColumnCount(); c++ ) {
-            s.Add( m_listView->GetItemText( r, c ) );
+        for ( int c = 0; c < m_lisViewCycle->GetColumnCount(); c++ ) {
+            s.Add( m_lisViewCycle->GetItemText( r, c ) );
         }
         file.AddLine( wxJoin( s, ',', '\\' ) );
     }
@@ -198,99 +250,196 @@
     file.Close();
 }
 
-void MainFrame::OnDClickItem( wxListEvent& event )
+void MainFrame::OnLViewDClickItem( wxListEvent& event )
 {
-    long i = event.GetIndex();
+    wxString s = event.GetText();
 }
 
-void MainFrame::OnSelectItem( wxListEvent& event )
+void MainFrame::OnLViewSelectItem( wxListEvent& event )
 {
     long i = event.GetIndex();
-    m_current = i;
+    m_current = (int)i;
 }
 
-// ↑
+void MainFrame::OnLBoxDClickItem( wxCommandEvent& event )
+{
+    wxString s = event.GetString();
+    m_counter = m_period;
+    if ( wxTheClipboard->Open() ) {
+        wxTheClipboard->SetData( new wxTextDataObject( s ) );
+        wxTheClipboard->Close();
+        m_listBoxHist->Delete( event.GetSelection() );
+        m_listBoxHist->Insert( s, 0 );
+        m_textCtrlShow->SetValue( s );
+        m_textCtrlRemain->SetValue( wxString::Format( wxT("%d"), m_period ) );
+    }
+    m_listBoxHist->Deselect( event.GetInt() );
+    m_listBoxHist->SetSelection( 0 );
+}
+
+// [↑]
 void MainFrame::OnBtnUp( wxCommandEvent& WXUNUSED(event) )
 {
-    long item = -1;
-    item = m_listView->GetNextItem( item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
+    long item = m_lisViewCycle->GetFirstSelected();
     if ( item == -1 || item == 0 ) return;
     SwapListItem( item, item - 1 );
     ReNumberList();
 }
 
-// ↓
+// [↓]
 void MainFrame::OnBtnDown( wxCommandEvent& WXUNUSED(event) )
 {
-    long item = -1;
-    item = m_listView->GetNextItem( item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
-    if ( item == -1 || item == m_listView->GetItemCount() - 1 ) return;
+    long item = m_lisViewCycle->GetFirstSelected();
+    if ( item == -1 || item == m_lisViewCycle->GetItemCount() - 1 ) return;
     SwapListItem( item, item + 1 );
     ReNumberList();
 }
 
-// −
+// [−] 
 void MainFrame::OnBtnDel( wxCommandEvent& WXUNUSED(event) )
 {
-    long item = -1;
-    for ( ;; ) {
-        item = m_listView->GetNextItem( item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
-        if ( item == -1 ) break;
-        m_listView->DeleteItem( item );
-        ReNumberList();
-    }
+    long item = m_lisViewCycle->GetFirstSelected();
+    if ( item == -1 ) return;
+
+    int id = ToInt( m_lisViewCycle->GetItemText( item, COL_ID ) );
+    QH.erase( id );
+
+    m_lisViewCycle->DeleteItem( item );
+    ReNumberList();
 }
 
-// +
+// [+]
 void MainFrame::OnBtnAdd( wxCommandEvent& WXUNUSED(event) )
 {
-    long item = -1;
-    for ( ;; ) {
-        item = m_listView->GetNextItem( item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
-        if ( item == -1 ) break;
-        m_listView->InsertItem( item + 1, wxEmptyString );
-        ReNumberList();
+    int r;
+    long item = m_lisViewCycle->GetFirstSelected();
+    if ( item == -1 ) r = 0;
+    else              r = item;
+
+    AddDialog add_dlg( this, wxID_ANY, wxT("Add Item"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE );
+    if ( add_dlg.ShowModal() == wxID_OK ) {
+        int id = CreateID();
+        QlipData* q = new QlipData;
+        q->id              = id; 
+        q->text            = add_dlg.GetText();
+        q->overwrite       = add_dlg.GetOverwrite();
+        q->max_active_time = add_dlg.GetMaxActiveTime();
+        q->max_live_time   = q->overwrite ? add_dlg.GetMaxLiveTime() : 0;
+        q->desc            = add_dlg.GetDesc();
+        q->active_time = 0;
+        q->live_time   = 0;
+        QH[id] = q;
+
+        m_lisViewCycle->InsertItem( r, wxEmptyString );
+        m_lisViewCycle->SetItem( r, COL_TEXT, q->text );
+        m_lisViewCycle->SetItem( r, COL_OW,   wxString::Format( wxT("%s"), q->overwrite ? wxT("true") : wxT("false") ) );
+        m_lisViewCycle->SetItem( r, COL_MAL,  wxString::Format( wxT("-- / %d"), q->max_active_time ) );
+        m_lisViewCycle->SetItem( r, COL_MLT,  wxString::Format( wxT("-- / %d"), q->max_live_time ) );
+        m_lisViewCycle->SetItem( r, COL_DESC, q->desc );
+        m_lisViewCycle->SetItem( r, COL_ID,   wxString::Format( wxT("%d"), id ) );
+        if ( q->overwrite ) 
+            m_lisViewCycle->SetItemBackgroundColour( r, wxColour( wxT("MEDIUM GOLDENROD") ) );
+        else 
+            m_lisViewCycle->SetItemBackgroundColour( r, wxColour( wxT("WHITE") ) );
     }
-    /*
-    AddDialog adlg( this, wxID_ANY, wxT("a"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE );
-    if ( adlg.ShowModal() == wxID_OK ) {
-    }
-    */
+    ReNumberList();
 }
 
 void MainFrame::OnTimer( wxTimerEvent& WXUNUSED(event) )
 {
+    wxString clipboard;
     if ( wxTheClipboard->Open() ) {
-
+        //wxMessageBox( clipboard );
         wxTextDataObject data;
         wxTheClipboard->GetData( data );
-        wxString s = data.GetText();
-        if ( !m_last.IsSameAs( s ) ) {    // the clipboard was changed by user
-            wxTheClipboard->Close();
-            m_textCtrlShow->SetValue( s );
-            for ( int r = 0; r < m_listView->GetItemCount(); r++ )
-                m_listView->SetItemState( r, 0, wxLIST_STATE_SELECTED );
-            m_counter = 5;
-            m_current = 0;
-            m_last = s;
-            m_timer.StartOnce( (int)m_counter * 1000 );
-            return;
+        clipboard = data.GetText();
+        wxTheClipboard->Close();
+
+        m_textCtrlShow->SetValue( clipboard );
+        m_textCtrlRemain->SetValue( wxT("∞") );
+        UpdateHistory( clipboard );
+    }
+    else {
+        return;
+    }
+
+    long list_num = m_lisViewCycle->GetItemCount();
+    if ( list_num == 0 ) return;
+
+    if ( m_lisViewCycle->GetSelectedItemCount() == 0 ) {
+        m_lisViewCycle->Select( 0, true );
+        m_current = 0;
+    }
+
+    AddStackTime();
+    UpdateView();
+    int r = GetEmptyStack();
+    if ( r != -1 && m_bottom ) {
+        m_timer.Stop();
+
+        int id = ToInt( m_lisViewCycle->GetItemText( r, COL_ID ) );
+        QH[id]->text = clipboard;
+        m_lisViewCycle->SetItem( r, COL_TEXT, clipboard );
+
+        wxSleep( 2 );
+        m_timer.Start( -1 );
+        m_current = 0;
+        m_lisViewCycle->Select( 0, true );
+        return;
+    }
+
+    // Main Cycle
+    if ( list_num  == 1 ) {
+        if ( m_counter == m_period ) {
+            m_counter = 0;
+            if ( wxTheClipboard->Open() ) {
+                wxString s = m_lisViewCycle->GetItemText( 0, COL_TEXT );
+                wxTheClipboard->SetData( new wxTextDataObject( s ) );
+                wxTheClipboard->Close();
+                m_textCtrlShow->SetValue( s );
+                m_textCtrlRemain->SetValue( wxT("∞") );
+            }
+        }
+        else {
+            wxString t = wxString::Format( wxT("%d"), m_period - m_counter );
+            m_textCtrlShow->SetValue( clipboard );
+            m_textCtrlRemain->SetValue( t );
+            m_counter++;
         }
 
-        wxString text = m_listView->GetItemText( m_current, 1 );
-        wxTheClipboard->SetData( new wxTextDataObject( text ) );
-        wxTheClipboard->Close();
-        m_textCtrlShow->SetValue( text );
-        m_listView->SetItemState( ( m_current + m_listView->GetItemCount() ) % m_listView->GetItemCount() - 1, 0, wxLIST_STATE_SELECTED );
-        m_listView->SetItemState( m_current, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
-        m_last = text;
+        m_lisViewCycle->Select( 0, true );
+        m_current = 0;
+        m_bottom = true;
+    }
+    else {
+        long item = m_lisViewCycle->GetFirstSelected();
+        m_current = (int)item;
+
+        int id = ToInt( m_lisViewCycle->GetItemText( item, COL_ID ) );
+        QlipData* q = QH[id];
+        if ( q->overwrite && !q->IsAlive() ) 
+            return;
 
-        wxString time = m_listView->GetItemText( m_current, 2 );
-        time.ToLong( &m_counter, 10 );
-        m_timer.StartOnce( (int)m_counter * 1000 );
+        if ( q->IsArrived() ) {
+            m_lisViewCycle->Select( m_current, false );
+            if ( ++m_current == list_num ) m_bottom = true;
+            else                           m_bottom = false;
+            m_current = m_current % list_num;
+            m_lisViewCycle->Select( m_current, true );
 
-        if ( m_current == m_listView->GetItemCount() - 1 ) m_current = 0;
-        else m_current++;
+            if ( wxTheClipboard->Open() ) {
+                int id = ToInt( m_lisViewCycle->GetItemText( m_current, COL_ID ) );
+                QlipData* qn = QH[id];
+                wxTheClipboard->SetData( new wxTextDataObject( qn->text ) );
+                wxTheClipboard->Close();
+                m_textCtrlShow->SetValue( qn->text );
+                m_textCtrlRemain->SetValue( wxString::Format( wxT("%d"), qn->max_active_time ) );
+            }
+        }
+        else {
+            int t = q->max_active_time - q->active_time;
+            m_textCtrlRemain->SetValue( wxString::Format( wxT("%d"), t ) );
+        }
     }
 }
 
@@ -299,9 +448,7 @@
     if ( m_toggleBtn->GetValue() ) {
         m_toggleBtn->SetLabel( wxT("OFF") );
         EnableButtons( false );
-        if ( m_listView->GetItemCount() > 0 ) {
-            m_timer.StartOnce( 1000 );
-        }
+        m_timer.Start( 1000 );
     }
     else {
         m_timer.Stop();
@@ -334,19 +481,98 @@
 
 void MainFrame::ReNumberList()
 {
-    for ( int i = 0; i < m_listView->GetItemCount(); i++ ) {
-        m_listView->SetItem( i, 0, wxString::Format( wxT("%d"), i + 1 ) );
+    for ( int r = 0; r < m_lisViewCycle->GetItemCount(); r++ ) {
+        m_lisViewCycle->SetItem( r, COL_NO, wxString::Format( wxT("%d"), r + 1 ) );
+        wxString s = m_lisViewCycle->GetItemText( r, COL_OW );
+        if ( s.IsSameAs( wxT("true") ) ) 
+            m_lisViewCycle->SetItemBackgroundColour( r, wxColour( wxT("MEDIUM GOLDENROD") ) );
+        else
+            m_lisViewCycle->SetItemBackgroundColour( r, wxColour( wxT("WHITE") ) );
     }
 }
 
 void MainFrame::SwapListItem( long item1, long item2 )
 {
-    for ( int c = 0; c < m_listView->GetColumnCount(); c++ ) {
-        wxString buf = m_listView->GetItemText( item1, c );
-        m_listView->SetItem( item1, c, m_listView->GetItemText( item2, c ) );
-        m_listView->SetItem( item2, c, buf );
+    for ( int c = 0; c < m_lisViewCycle->GetColumnCount(); c++ ) {
+        wxString buf = m_lisViewCycle->GetItemText( item1, c );
+        m_lisViewCycle->SetItem( item1, c, m_lisViewCycle->GetItemText( item2, c ) );
+        m_lisViewCycle->SetItem( item2, c, buf );
     }
-    m_listView->SetItemState( item1, 0, wxLIST_STATE_SELECTED );
-    m_listView->SetItemState( item2, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
+    m_lisViewCycle->Select( item1, false );
+    m_lisViewCycle->Select( item2, true  );
+}
+
+int MainFrame::CreateID()
+{
+    long max_id = 1;
+    if ( m_lisViewCycle->GetItemCount() == 0 ) 
+        return max_id;
+
+    wxArrayString id;
+    for ( int r = 0; r < m_lisViewCycle->GetItemCount(); r++ ) {
+        wxString buf = m_lisViewCycle->GetItemText( r, COL_ID );
+        id.Add( buf );
+    }
+    id.Sort();
+    wxString max = id.Last();
+    max.ToLong( &max_id, 10 );
+    return ++max_id;
+}
+
+void MainFrame::AddStackTime()
+{
+    QlipDataHash::iterator it;
+    for ( it = QH.begin(); it != QH.end(); it++ ) {
+        int id = it->first;
+        QlipData* q = it->second;
+        if ( q->overwrite ) {
+            if ( ++q->live_time == q->max_live_time ) 
+                q->Kill();
+        }
+        QH[id] = q;
+    }
 }
 
+void MainFrame::UpdateView()
+{
+    for ( int r = 0; r < m_lisViewCycle->GetItemCount(); r++ ) {
+        int id = ToInt( m_lisViewCycle->GetItemText( r, COL_ID ) );
+
+        m_lisViewCycle->SetItem( r, COL_TEXT, QH[id]->text );
+
+        wxString at = wxString::Format( wxT("%d / %d"), QH[id]->active_time, QH[id]->max_active_time );
+        m_lisViewCycle->SetItem( r, COL_MAL, at );
+
+        wxString lt = wxT("-- / --");
+        if ( QH[id]->overwrite )
+            lt = wxString::Format( wxT("%d / %d"), QH[id]->live_time, QH[id]->max_live_time );
+        m_lisViewCycle->SetItem( r, COL_MLT, lt );
+    }
+}
+
+void MainFrame::UpdateHistory( wxString s )
+{
+    if ( s.IsEmpty() ) return;
+    int row = m_listBoxHist->FindString( s, true );
+    if ( row != wxNOT_FOUND )
+        m_listBoxHist->Delete( row );
+    m_listBoxHist->Insert( s, 0 );
+}
+
+int MainFrame::GetEmptyStack()
+{
+    int row = -1;
+    for ( int r = 0; r < m_lisViewCycle->GetItemCount(); r++ ) {
+        int id = ToInt( m_lisViewCycle->GetItemText( r, COL_ID ) );
+        if ( QH[(int)id]->text.IsEmpty() ) row = r;
+    }
+    return row;
+}
+
+int MainFrame::ToInt( wxString s )
+{
+    long n = 0;
+    s.ToLong( &n, 10 );
+    return n;
+}
+