[sword-svn] r223 - in trunk/src: . SlideBible SlideBible/time_ce SlideBible/ui SwordReader_GUI

kalemas at crosswire.org kalemas at crosswire.org
Thu Jan 7 13:55:10 MST 2010


Author: kalemas
Date: 2010-01-07 13:55:10 -0700 (Thu, 07 Jan 2010)
New Revision: 223

Added:
   trunk/src/SlideBible/sbBase.h
   trunk/src/SlideBible/time_ce/
   trunk/src/SlideBible/time_ce/time_ce.cpp
   trunk/src/SlideBible/time_ce/time_ce.h
Modified:
   trunk/src/SlideBible.sln
   trunk/src/SlideBible/SlideBible.vcproj
   trunk/src/SlideBible/main.cpp
   trunk/src/SlideBible/sbCollection.cpp
   trunk/src/SlideBible/sbCollection.h
   trunk/src/SlideBible/sbControl.cpp
   trunk/src/SlideBible/sbControl.h
   trunk/src/SlideBible/sbCore.cpp
   trunk/src/SlideBible/sbCore.h
   trunk/src/SlideBible/sbItem.cpp
   trunk/src/SlideBible/sbItem.h
   trunk/src/SlideBible/sbList.cpp
   trunk/src/SlideBible/sbList.h
   trunk/src/SlideBible/sbTheme.cpp
   trunk/src/SlideBible/sbTheme.h
   trunk/src/SlideBible/todo.txt
   trunk/src/SlideBible/ui/scheme.txt
   trunk/src/SwordReader_GUI/SwordReader_GUI.vcproj
Log:
look in todo.txt

Modified: trunk/src/SlideBible/SlideBible.vcproj
===================================================================
--- trunk/src/SlideBible/SlideBible.vcproj	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/SlideBible.vcproj	2010-01-07 20:55:10 UTC (rev 223)
@@ -14,6 +14,9 @@
 		<Platform
 			Name="Pocket PC 2003 (ARMV4)"
 		/>
+		<Platform
+			Name="Win32"
+		/>
 	</Platforms>
 	<ToolFiles>
 	</ToolFiles>
@@ -45,7 +48,7 @@
 				ExecutionBucket="7"
 				AdditionalOptions="/D &quot;NO_VSNPRINTF&quot;"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\Dll1\winceSword\include\;..\..\..\..\sword\trunk\include\"
+				AdditionalIncludeDirectories="..\Dll1\winceSword\include\;..\..\..\..\sword\trunk\include\;..\..\..\..\sword\trunk\include\internal\regex\"
 				PreprocessorDefinitions="DEBUG;ARM;_ARM_;UNDER_CE=$(CEVER);_WIN32_WCE=$(CEVER);$(CePlatform);UNICODE;SIMPLE"
 				IgnoreStandardIncludePath="false"
 				StringPooling="true"
@@ -106,7 +109,7 @@
 			/>
 			<DeploymentTool
 				ForceDirty="-1"
-				RemoteDirectory="\StorageCard\Program Files\SwordReader\"
+				RemoteDirectory="\Storage Card\Program Files\SwordReader\"
 				RegisterOutput="0"
 				AdditionalFiles=""
 			/>
@@ -189,6 +192,94 @@
 			/>
 		</Configuration>
 		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\Dll1\winceSword\include\;..\..\..\..\sword\trunk\include\"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+				IgnoreStandardIncludePath="false"
+				StringPooling="true"
+				MinimalRebuild="false"
+				RuntimeLibrary="1"
+				RuntimeTypeInfo="true"
+				UsePrecompiledHeader="0"
+				BrowseInformation="0"
+				WarningLevel="3"
+				DebugInformationFormat="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES)"
+				Culture="1033"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/subsystem:windowsce,5.01"
+				AdditionalDependencies="aygshell.lib"
+				OutputFile="$(OutDir)/SlideBible.exe"
+				LinkIncremental="2"
+				DelayLoadDLLs="$(NOINHERIT)"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/SlideBible.pdb"
+				SubSystem="0"
+				StackReserveSize="65536"
+				StackCommitSize="4096"
+				EntryPointSymbol="WinMainCRTStartup"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+		<Configuration
 			Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
 			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
 			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
@@ -216,7 +307,7 @@
 				AdditionalOptions="/D &quot;NO_VSNPRINTF&quot;"
 				Optimization="2"
 				FavorSizeOrSpeed="2"
-				AdditionalIncludeDirectories="..\Dll1\winceSword\include\;..\..\..\..\sword\trunk\include\"
+				AdditionalIncludeDirectories="..\Dll1\winceSword\include\;..\..\..\..\sword\trunk\include\;..\..\..\..\sword\trunk\include\internal\regex\"
 				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
 				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
@@ -272,7 +363,7 @@
 			/>
 			<DeploymentTool
 				ForceDirty="-1"
-				RemoteDirectory="\StorageCard\Program Files\SwordReader\"
+				RemoteDirectory="\Storage Card\Program Files\SwordReader\"
 				RegisterOutput="0"
 				AdditionalFiles=""
 			/>
@@ -357,6 +448,91 @@
 			<DebuggerTool
 			/>
 		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/D &quot;NO_VSNPRINTF&quot;"
+				Optimization="2"
+				FavorSizeOrSpeed="2"
+				AdditionalIncludeDirectories="..\Dll1\winceSword\include\;..\..\..\..\sword\trunk\include\"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES)"
+				Culture="1033"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions=" /subsystem:windowsce,5.01"
+				AdditionalDependencies="aygshell.lib"
+				OutputFile="$(OutDir)/SlideBible.exe"
+				LinkIncremental="1"
+				DelayLoadDLLs="$(NOINHERIT)"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/SlideBible.pdb"
+				SubSystem="0"
+				StackReserveSize="65536"
+				StackCommitSize="4096"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
 	</Configurations>
 	<References>
 	</References>
@@ -366,6 +542,10 @@
 			Filter="h;hpp;hxx;hm;inl"
 			>
 			<File
+				RelativePath=".\sbBase.h"
+				>
+			</File>
+			<File
 				RelativePath=".\sbCollection.h"
 				>
 			</File>
@@ -378,10 +558,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\sbCross.h"
-				>
-			</File>
-			<File
 				RelativePath=".\sbItem.h"
 				>
 			</File>
@@ -390,10 +566,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\sbObject.h"
-				>
-			</File>
-			<File
 				RelativePath=".\sbTheme.h"
 				>
 			</File>
@@ -1697,62 +1869,6 @@
 					>
 				</File>
 			</Filter>
-			<Filter
-				Name="wince"
-				>
-				<Filter
-					Name="source"
-					>
-					<File
-						RelativePath="..\Dll1\winceSword\src\dirent.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\Dll1\winceSword\src\fcntl.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\Dll1\winceSword\src\unistd.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="header"
-					>
-					<File
-						RelativePath="..\Dll1\winceSword\include\dirent.h"
-						>
-					</File>
-					<File
-						RelativePath="..\Dll1\winceSword\include\errno.h"
-						>
-					</File>
-					<File
-						RelativePath="..\Dll1\winceSword\include\fcntl.h"
-						>
-					</File>
-					<File
-						RelativePath="..\Dll1\winceSword\include\unistd.h"
-						>
-					</File>
-					<Filter
-						Name="sys"
-						>
-						<File
-							RelativePath="..\Dll1\winceSword\include\sys\errno.h"
-							>
-						</File>
-						<File
-							RelativePath="..\Dll1\winceSword\include\sys\stat.h"
-							>
-						</File>
-						<File
-							RelativePath="..\Dll1\winceSword\include\sys\types.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-			</Filter>
 		</Filter>
 		<Filter
 			Name="source"
@@ -1787,6 +1903,62 @@
 				>
 			</File>
 		</Filter>
+		<Filter
+			Name="wince"
+			>
+			<Filter
+				Name="source"
+				>
+				<File
+					RelativePath="..\Dll1\winceSword\src\dirent.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dll1\winceSword\src\fcntl.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dll1\winceSword\src\unistd.cpp"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="header"
+				>
+				<File
+					RelativePath="..\Dll1\winceSword\include\dirent.h"
+					>
+				</File>
+				<File
+					RelativePath="..\Dll1\winceSword\include\errno.h"
+					>
+				</File>
+				<File
+					RelativePath="..\Dll1\winceSword\include\fcntl.h"
+					>
+				</File>
+				<File
+					RelativePath="..\Dll1\winceSword\include\unistd.h"
+					>
+				</File>
+				<Filter
+					Name="sys"
+					>
+					<File
+						RelativePath="..\Dll1\winceSword\include\sys\errno.h"
+						>
+					</File>
+					<File
+						RelativePath="..\Dll1\winceSword\include\sys\stat.h"
+						>
+					</File>
+					<File
+						RelativePath="..\Dll1\winceSword\include\sys\types.h"
+						>
+					</File>
+				</Filter>
+			</Filter>
+		</Filter>
 		<File
 			RelativePath=".\ui\scheme.txt"
 			>

Modified: trunk/src/SlideBible/main.cpp
===================================================================
--- trunk/src/SlideBible/main.cpp	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/main.cpp	2010-01-07 20:55:10 UTC (rev 223)
@@ -1,5 +1,5 @@
 /*************************************************************************
- * main.cpp - SlideBible main program entry
+ * main.cpp - only platform-dependent file, program entry
  *
  * author: Konstantin Maslyuk "Kalemas" mailto:kalemas at mail.ru
  *
@@ -13,23 +13,319 @@
  * General Public License for more details.
  ************************************************************************/
 
+
+
 #include "sbCore.h"
 
-sbCore * Core;
+#include <windows.h>
 
+#ifdef _WIN32_WCE
+#include <aygshell.h>
+#endif
+
+HWND Window = NULL;
+
+void sbFillRect (sbRenderContext rc, const sbRect * rect, sbColor color)
+{
+	HBRUSH brush = CreateSolidBrush(RGB(color.red,color.green,color.blue));
+	RECT   rect2 = {rect->left,rect->top,rect->right,rect->bottom};
+	FillRect ((HDC)rc, &rect2, brush);
+	DeleteObject (brush);
+}
+
+sbFont sbMakeFont ( int size, const TCHAR * face, bool bold, bool italic )
+{
+	LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT));
+	lf.lfHeight = size;			lf.lfWidth = 0;
+	lf.lfEscapement = 0;		lf.lfOrientation = 0;
+	if (bold) lf.lfWeight = 600; else lf.lfWeight = 500;
+	lf.lfItalic = italic;		lf.lfUnderline = FALSE;
+	lf.lfStrikeOut = FALSE;		lf.lfCharSet = DEFAULT_CHARSET;
+	lf.lfOutPrecision = OUT_RASTER_PRECIS;
+	lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+	lf.lfQuality = CLEARTYPE_QUALITY;
+	lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+	_tcsncpy (lf.lfFaceName, face, LF_FACESIZE); /* Wingdings, Tahoma, Courier New */
+	return (sbFont) CreateFontIndirect(&lf);
+}
+
+sbPoint sbGetTextExtent ( sbFont font, const TCHAR * text, int count )
+{
+	SIZE sz;					sbPoint ts;
+	HDC hdc = CreateCompatibleDC (NULL);
+	SelectObject (hdc,(HFONT)font);
+	for ( ; count > 0; count--)
+	{
+		GetTextExtentPoint32 (hdc,text,1,&sz);
+		ts.x += sz.cx;			ts.y = max (ts.y,sz.cy);
+		text++;
+	}
+	DeleteDC (hdc);
+	return ts;
+}
+
+void sbDrawGradient ( sbRenderContext rc, const sbRect * rect, sbColor startColor, sbColor endColor, bool vertical )
+{
+	TRIVERTEX        vert[2];	GRADIENT_RECT    gRect;
+	vert [0] .x      = rect->left;
+	vert [0] .y      = rect->top;
+	vert [0] .Red    = startColor.red   << 8;
+	vert [0] .Green  = startColor.green << 8;
+	vert [0] .Blue   = startColor.blue  << 8;
+	vert [0] .Alpha  = 0x0000;
+	vert [1] .x      = rect->right;
+	vert [1] .y      = rect->bottom;
+	vert [1] .Red    = endColor.red   << 8;
+	vert [1] .Green  = endColor.green << 8;
+	vert [1] .Blue   = endColor.blue  << 8;
+	vert [1] .Alpha  = 0x0000;
+	gRect.UpperLeft  = 0;		gRect.LowerRight = 1;
+	GradientFill((HDC)rc, vert, 2, &gRect, 1, vertical ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H);
+}
+
+void sbDrawBitmap ( sbRenderContext rc, const sbRect * rect, sbBitmap bitmap, bool stretch )
+{
+
+	HDC     thdc = CreateCompatibleDC(NULL);
+	HBITMAP obm  = (HBITMAP)SelectObject(thdc, (HBITMAP)bitmap);
+	BITMAP  bm;
+
+	GetObject(bitmap, sizeof(bm), &bm);
+
+	if ( stretch )
+	{
+		StretchBlt((HDC)rc, rect->left, rect->top, rect->width(), rect->height(), thdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
+	}
+	else
+	{
+		BitBlt((HDC)rc, rect->left, rect->top, min(rect->width(),bm.bmWidth), min(rect->height(),bm.bmHeight), thdc, 0, 0, SRCCOPY);
+	}
+	SelectObject(thdc, obm);
+	DeleteDC(thdc);
+}
+sbBitmap sbRenderContextBitmap ( sbRenderContext rc , int width, int height )
+{
+	sbAssert(Window==NULL);
+	HDC wdc = GetDC(Window);
+	HBITMAP bitmap = CreateCompatibleBitmap (wdc, width, height);
+	SelectObject((HDC)rc,bitmap);
+	SetBkMode((HDC)rc, TRANSPARENT);
+	ReleaseDC(Window,wdc);
+	return (sbBitmap)bitmap;
+}
+
+const char * sbGetLocale ()
+{
+	const char * locale = "en_US";
+
+	TCHAR userLocale [6];
+	GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME, userLocale, 6);
+
+	if (_tcscmp(userLocale, L"RUS")==0)          locale = "ru_RU-cp1251";
+	else if (_tcscmp(userLocale, L"AFK")==0)     locale = "af";
+	else if (_tcscmp(userLocale, L"BGR")==0)     locale = "bg_BG-cp1251";
+	else if (_tcscmp(userLocale, L"CSY")==0)     locale = "cs";
+	else if (_tcscmp(userLocale, L"DAN")==0)     locale = "da";
+	else if (_tcscmp(userLocale, L"ETI")==0)     locale = "et";
+	else if (_tcscmp(userLocale, L"FIN")==0)     locale = "fi";
+	else if (_tcscmp(userLocale, L"IND")==0)     locale = "id";
+	else if (_tcscmp(userLocale, L"KOR")==0)     locale = "ko";
+	else if (_tcscmp(userLocale, L"PLK")==0)     locale = "pl";
+	else if (_tcscmp(userLocale, L"ROM")==0)     locale = "ro";
+	else if (_tcscmp(userLocale, L"SKY")==0)     locale = "sk";
+	else if (_tcscmp(userLocale, L"SLV")==0)     locale = "sl";
+	else if (_tcscmp(userLocale, L"UKR")==0)     locale = "uk_UA-cp1251";
+	else if (_tcsnccmp(userLocale, L"AR", 2)==0) locale = "ar_EG-cp1256";
+	else if (_tcsnccmp(userLocale, L"EN", 2)==0) locale = "en_GB";
+	else if (_tcsnccmp(userLocale, L"DE", 2)==0) locale = "de";
+	else if (_tcsnccmp(userLocale, L"ES", 2)==0) locale = "es";
+	else if (_tcsnccmp(userLocale, L"FR", 2)==0) locale = "fr";
+	else if (_tcsnccmp(userLocale, L"IT", 2)==0) locale = "it";
+	else if (_tcsnccmp(userLocale, L"NL", 2)==0) locale = "nl";
+	else if (_tcsnccmp(userLocale, L"NO", 2)==0) locale = "no";
+	else if (_tcsnccmp(userLocale, L"PT", 2)==0) locale = "pt";
+	else if (_tcscmp(userLocale, L"USA")!=0)
+		sbMessage("Unsupported user locale: %s\n", userLocale);
+
+	return locale;
+}
+
+void sbUpdateScreen ()
+{
+	sbAssert(Window==NULL);
+	RECT rect;
+	GetClientRect(Window,&rect);
+	InvalidateRect(Window, &rect, FALSE);
+	UpdateWindow(Window);
+}
+
+void sbSetSip ( bool on )
+{
+#ifdef _WIN32_WCE
+	SIPINFO si;
+
+	if (SipStatus() == SIP_STATUS_UNAVAILABLE)
+	{
+		sbMessage("Sip is unavailable.\n");
+		return;
+	}
+
+	memset(&si, 0, sizeof(SIPINFO));
+	si.cbSize = sizeof(SIPINFO);
+
+	SHSipInfo(SPI_GETSIPINFO,0,&si,0);
+
+	if (on)
+	{
+		if (si.fdwFlags & SIPF_ON) return;
+
+		//printf("%i %i %i %i %i\n",si.fdwFlags, si.fdwFlags | SIPF_ON, si.fdwFlags & SIPF_ON, si.fdwFlags & ~SIPF_ON, si.fdwFlags ^ SIPF_ON);
+
+		si.fdwFlags |= SIPF_ON;
+
+		HWND sipWnd = FindWindow(L"SipWndClass",L"");
+
+		si.rcSipRect.top    += si.rcVisibleDesktop.bottom-si.rcSipRect.bottom;
+		si.rcSipRect.bottom += si.rcVisibleDesktop.bottom-si.rcSipRect.bottom;
+
+		SHSipInfo(SPI_SETSIPINFO,0,&si,0);
+
+		MoveWindow(sipWnd,si.rcSipRect.left,si.rcSipRect.top,si.rcSipRect.right-si.rcSipRect.left,si.rcSipRect.bottom-si.rcSipRect.top,false);
+	}
+	else
+	{
+		if (!(si.fdwFlags & SIPF_ON)) return;
+
+		si.fdwFlags ^= SIPF_ON;
+
+		SHSipInfo (SPI_SETSIPINFO,0,&si,0);
+	}
+#endif
+}
+class sbThreadData
+{
+public:
+	sbThreadData () : running (false) , abort (false) { ; }
+
+	bool    running;
+	bool    abort;
+	HANDLE  handle;
+	DWORD   id;
+	void  (*executor) (bool*);
+};
+
+DWORD WINAPI sbThreadMain ( LPVOID pData )
+{
+	sbAssert (pData==NULL);
+	sbThreadData * data = reinterpret_cast<sbThreadData*>(pData);
+	
+	sbAssert (data->executor==NULL);
+
+	data->executor(&data->abort);
+
+	data->running = false;
+	return 1;
+}
+
+sbThread sbThreadCreate (void (*executor) (bool*))
+{
+	sbThreadData * threadData = new sbThreadData ();
+
+	threadData->executor = executor;
+
+	threadData->handle = CreateThread(NULL, 0, sbThreadMain, (LPVOID)threadData, 0, &threadData->id);
+
+	if(threadData->handle)
+	{
+		threadData->running = true;
+		SetThreadPriority(threadData->handle, THREAD_PRIORITY_BELOW_NORMAL);
+	}
+
+	sbAssert (threadData->running==false);
+
+	return (sbThread)threadData;
+}
+
+void sbThreadDestroy ( sbThread theThread )
+{
+	sbThreadData * threadData = (sbThreadData*)theThread;
+	const int timeout = 2000;
+	int time = timeout;
+
+	if (!threadData->running) return;
+
+	threadData->abort = true;
+
+	SetThreadPriority(threadData->handle, THREAD_PRIORITY_ABOVE_NORMAL);
+
+	while (threadData->running && timeout > 0)
+	{
+		Sleep(1);
+		time--;
+	}
+
+	if (timeout <= 0)
+	{
+		sbMessage ("Thread terminated.\n");
+
+		TerminateThread(threadData->handle, -1);
+		threadData->running = false;
+	}
+	else if (timeout-time > 16)
+	{
+		sbMessage ("Thread termination takes %i msec.\n", timeout-time);
+	}
+
+	threadData->abort = false;
+
+	delete threadData;
+}
+
+#ifdef _WIN32_WCE
+#include "time_ce\time_ce.cpp"
+
+time_t time ( time_t * now ) { return time_ce ( now ); }
+//#define asctime asctime_ce
+//#define localtime localtime_ce
+#endif
+
+sbBitmap sbLoadBitmap ( const TCHAR * filename )
+{
+#ifdef _WIN32_WCE
+	return SHLoadImageFile(filename);
+#else
+	return LoadBitmap(NULL,filename);
+#endif
+}
+
+void            sbGetScreenRect        ( sbRect & rect )          { sbAssert (Window==NULL); RECT wr; GetClientRect(Window,&wr); rect.left = wr.left; rect.top = wr.top; rect.right = wr.right; rect.bottom = wr.bottom; }
+sbRenderContext sbCreateRenderContext  ()                         { return (sbRenderContext)CreateCompatibleDC(NULL); }
+void            sbDestroyRenderContext ( sbRenderContext rc )     { DeleteDC((HDC)rc); }
+int             sbGetLastError         ()                         { return GetLastError(); }
+void            sbDeleteFont           ( sbFont font )            { DeleteObject ((HFONT)font); }
+void            sbDeleteBitmap         ( sbBitmap bitmap )        { DeleteObject ((HBITMAP)bitmap); }
+sbFont          sbSelectFont           ( sbRenderContext rc, sbFont font ) { return (sbFont)SelectObject((HDC)rc,(HFONT)font); }
+sbColor         sbSelectColor          ( sbRenderContext rc, sbColor color ) { COLORREF old = SetTextColor((HDC)rc,RGB(color.red,color.green,color.blue)); return sbColor(GetRValue(old),GetGValue(old),GetBValue(old)); }
+void            sbDrawText             ( sbRenderContext rc, int x, int y, const TCHAR * text, int count ) { ExtTextOut((HDC)rc, x, y, ETO_OPAQUE, NULL, text, count, 0); }
+void            sbSleep                ( int milliseconds )        { Sleep (milliseconds); }
+void            sbSetTimer             ( const int timer, int refreshRate ) { sbAssert(Window==NULL); SetTimer(Window, timer, refreshRate, (TIMERPROC) NULL); }
+void            sbKillTimer            ( const int timer ) { sbAssert(Window==NULL); KillTimer(Window, timer); }
+void            sbBitBlt               ( sbRenderContext toRc, int left, int top, int width, int height, sbRenderContext fromRc, int x, int y) { BitBlt((HDC)toRc, left, top, width, height, (HDC)fromRc, x, y, SRCCOPY); }
+long            sbGetTickCount         ()                         { return GetTickCount(); }
+void            sbExit                 ( int code )               { PostQuitMessage(code); }
+
+
+
+
 LRESULT CALLBACK wndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
 	switch ( message )
 	{
-	case WM_HIBERNATE:
-		sbMessage ( "Message : WM_HIBERNATE\n" );
-		return 0;
-
 	case WM_ERASEBKGND:
 		return 1;
 
 	case WM_KILLFOCUS: // loose focus
-		Core->setSipState ( false );
+		sbSetSip ( false );
 		Core->switchList ( sbList::TYPE_NONE );
 		break;
 
@@ -38,7 +334,9 @@
 		break;
 
 	case WM_ACTIVATE:
+#ifdef _WIN32_WCE
 		SHFullScreen ( hwnd, SHFS_HIDESIPBUTTON | SHFS_HIDETASKBAR | SHFS_HIDESTARTICON );
+#endif
 		break;
 
 	case WM_PAINT:
@@ -46,30 +344,69 @@
 			PAINTSTRUCT ps;
 			HDC hdc = BeginPaint(hwnd, &ps);
 
-			Core->onPaint(hdc);
+			Core->onPaint((sbRenderContext)hdc);
 
+			/*HDC rc = CreateCompatibleDC(NULL);
+			HDC rc2 = GetDC(Window);
+			HBITMAP bmp = CreateCompatibleBitmap (rc2, 100, 100);
+			SelectObject(rc,bmp);
+			SetBkMode(rc, TRANSPARENT);
+
+			//sbFillRect(rc,&sbRect(0,0,32,100),sbColor(250,0,0));
+			//sbFillRect(rc,&sbRect(64,0,100,100),sbColor(50,128,100));
+			//sbBitBlt(hdc,32,0,100,100,rc,0,0);
+
+			RECT r1 = {0,0,32,100};
+			RECT r2 = {64,0,100,100};
+
+			HBRUSH b1 = CreateSolidBrush(RGB(250,0,0));
+			HBRUSH b2 = CreateSolidBrush(RGB(50,120,100));
+
+			FillRect(rc,&r1,b1);
+			FillRect(rc,&r2,b2);
+
+			BitBlt(hdc,0,0,100,100,rc,0,0,SRCCOPY);
+			BitBlt(hdc,0,100,100,100,rc,0,0,SRCCOPY);
+
+			DeleteObject(b1);
+			DeleteObject(b2);
+
+			DeleteObject(bmp);
+			DeleteDC(rc);
+			ReleaseDC(Window,rc2);*/
+
 			EndPaint(hwnd, &ps);
 			DeleteDC(hdc);
 			return 1;
 		}
 
-	case WM_LBUTTONDOWN:
+	
 	case WM_LBUTTONUP:
+		Core->onMouse ( LOWORD(lParam), HIWORD(lParam), MSG_MOUSE_L_UP );
+		break;
+
 	case WM_MOUSEMOVE:
-		return Core->onMouse(LOWORD(lParam), HIWORD(lParam), message);
+		Core->onMouse ( LOWORD(lParam), HIWORD(lParam), MSG_MOUSE_MOVE );
+		break;
 
+	case WM_LBUTTONDOWN:
+		Core->onMouse ( LOWORD(lParam), HIWORD(lParam), MSG_MOUSE_L_DOWN );
+		break;
+
 	case WM_KEYDOWN:
+		Core->onKey ( wParam, true );
 		break;
 
 	case WM_KEYUP:
+		Core->onKey ( wParam, false );
 		break;
 
 	case WM_CHAR:
-		Core->onChar((TCHAR)wParam);
+		Core->onChar ( (TCHAR)wParam );
 		break;
 
 	case WM_TIMER:
-		return Core->onTimer(wParam);
+		Core->onTimer ( wParam );
 		break;
 
 	case WM_CREATE:
@@ -110,19 +447,19 @@
 
 	if ( RegisterClass ( & wc ) )
 	{
-		HWND window = CreateWindow(L"SlideBible Application", L"SlideBible", WS_VISIBLE,
+		Window = CreateWindow(L"SlideBible Application", L"SlideBible", WS_VISIBLE,
 			0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
 			NULL, NULL, hInstance, NULL);
 
-		if ( window == NULL )
+		if ( Window == NULL )
 		{
-			sbMessage ( "Can not create window beacouse of %i error.\n", GetLastError() );
+			sbMessage ( "Can not create window becouse of %i error.\n", GetLastError() );
 			PostQuitMessage ( 1 );
 			return 0;
 		}
 		else
 		{
-			sbCore core ( window );
+			sbCore core;
 
 			MSG message;
 
@@ -135,6 +472,8 @@
 				}
 			}
 
+			DestroyWindow(Window);
+
 			return message.wParam;
 		}
 	}

Added: trunk/src/SlideBible/sbBase.h
===================================================================
--- trunk/src/SlideBible/sbBase.h	                        (rev 0)
+++ trunk/src/SlideBible/sbBase.h	2010-01-07 20:55:10 UTC (rev 223)
@@ -0,0 +1,192 @@
+/*************************************************************************
+* sbBase.cpp - base types, platform-independent
+*
+* author: Konstantin Maslyuk "Kalemas" mailto:kalemas at mail.ru
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation version 2.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+************************************************************************/
+
+#ifndef SBBASE_H
+#define SBBASE_H
+
+//#include <windows.h>
+//#include <tchar.h>
+
+//#include <string.h>
+
+//#include <stdio.h>
+#include <stdlib.h>
+//#include <iostream>
+//
+//#include "mmgr\mmgr.h"
+
+//#include <map>
+//#include <vector>
+#include <algorithm>
+
+void sbMessage ( const char *format , ... );
+
+#define sbAssert(condition) ((condition)?(sbMessage("sbAssert : " #condition ". at %s : %d\n", __FILE__, __LINE__), __debugbreak()) : 0)
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+/*
+ *  sbObject - memory tracker utility.
+ *  require copy operator
+ */
+/*class sbObject
+{
+public:
+	sbObject ( const char * _name_ = "Generic" )
+	{
+		name = _name_;
+		tracker[name].push_back(this);
+
+		sbMessage("Create : %s at %#x\n",name,this);
+	}
+
+	~sbObject ()
+	{
+		sbMessage("Delete : %s at %#x\n",name,this);
+
+		std::vector<sbObject*>::iterator item = std::find(tracker[name].begin(),tracker[name].end(),this);
+
+		if (item != tracker[name].end())
+		{
+			tracker[name].erase(item);
+			//if (tracker[name].size() == 0) tracker.erase(name);
+		}
+		else
+		{
+			sbMessage ( "Deletion of unrecognized \"%s\" at %#x\n",name,this);
+		}
+	}
+
+	static std::map<const char*,std::vector<sbObject*>> tracker;
+
+private:
+	const char * name;
+};*/
+
+/*
+ * sbRect - screen rect
+ */
+struct sbRect
+{
+	sbRect (int _left_ = 0, int _top_ = 0, int _right_ = 0, int _bottom_ = 0) : left (_left_) , top (_top_) , right (_right_) , bottom (_bottom_) { ; }
+
+	inline int width  () const { return (right - left); }
+	inline int height () const { return (bottom - top); }
+
+	inline bool inRect (int x, int y) const { return (x >= left && x < right && y >= top && y < bottom); }
+
+	int left, top, right, bottom;
+};
+
+/*
+ * sbLayout - screen-dimentions-independent rect
+ */
+class sbLayout
+{
+public:
+	enum
+	{
+		SYSTEM_SCREEN = 0,
+		SYSTEM_LIST,
+		SYSTEM_TOOLBAR,
+		SYSTEM_EDGE_LEFT,
+		SYSTEM_EDGE_RIGHT,
+		SYSTEM_MATRIX
+	};
+	
+	sbLayout ( unsigned char _system_ , unsigned short _order_ = 1 , unsigned short _amount_ = 1 ) : order ( _order_ ) , amount ( _amount_ ) , system ( _system_ ) { update (); }
+	
+	void update ();
+	
+	sbRect rect;
+	
+private:
+	unsigned short order;
+	unsigned short amount;
+	unsigned char  system;
+};
+
+/*
+ * sbColor - color
+ */
+struct sbColor
+{
+	sbColor ( unsigned char _red_ = 0, unsigned char _green_ = 0, unsigned char _blue_ = 0, unsigned char _alpha_ = 0 ) : red (_red_) , green(_green_) , blue (_blue_) , alpha (_alpha_) { ; }
+
+	sbColor ( const char * color ) /* "RRGGBBAA" */
+	{
+		char * stoped;
+		unsigned long data = strtoul (color,&stoped,16);
+
+		memcpy(&alpha,&data,sizeof(unsigned char)*4);
+	}
+
+	unsigned char alpha, blue, green, red;
+};
+
+struct sbPoint
+{
+	sbPoint(int _x_ = 0, int _y_ = 0) : x(_x_) , y(_y_) {;}
+
+    int x, y;
+};
+
+typedef void * sbThread;
+typedef void * sbRenderContext;
+typedef void * sbBitmap;
+typedef void * sbFont;
+
+sbThread        sbThreadCreate         ( void (*executor) (bool *) );
+void            sbThreadDestroy        ( sbThread threadData );
+void            sbFillRect             ( sbRenderContext rc, const sbRect * rect, sbColor color );
+void            sbDrawGradient         ( sbRenderContext rc, const sbRect * rect, sbColor startColor, sbColor endColor, bool vertical );
+void            sbDrawBitmap           ( sbRenderContext rc, const sbRect * rect, sbBitmap bitmap, bool stretch = false );
+void            sbGetScreenRect        ( sbRect & rect );
+sbBitmap        sbLoadBitmap           ( const TCHAR * filename );
+sbRenderContext sbCreateRenderContext  ();
+void            sbDestroyRenderContext ( sbRenderContext rc );
+int             sbGetLastError         (); /* sbGetError */
+sbFont          sbMakeFont             ( int size, const TCHAR *face, bool bold, bool italic );
+sbPoint         sbGetTextExtent        ( sbFont font, const TCHAR * text, int count );
+void            sbDeleteFont           ( sbFont font );
+void            sbDeleteBitmap         ( sbBitmap bitmap );
+sbFont          sbSelectFont           ( sbRenderContext rc, sbFont font );
+sbColor         sbSelectColor          ( sbRenderContext rc, sbColor color );
+void            sbDrawText             ( sbRenderContext rc, int x, int y, const TCHAR * text, int count );
+void            sbSleep                ( int milliseconds );
+sbBitmap        sbRenderContextBitmap  ( sbRenderContext rc , int width, int height );
+const char *    sbGetLocale            ();
+void            sbSetTimer             ( const int timer, int refreshRate );
+void            sbKillTimer            ( const int timer );
+void            sbBitBlt               ( sbRenderContext toRc, int left, int top, int width, int height, sbRenderContext fromRc, int x, int y);
+void            sbUpdateScreen         ();
+void            sbSetSip               ( bool on );
+long            sbGetTickCount         ();
+void            sbExit                 ( int code );
+
+enum
+{
+	MSG_MOUSE_L_UP = 1000,
+	MSG_MOUSE_L_DOWN,
+	MSG_MOUSE_MOVE
+};
+
+#endif

Modified: trunk/src/SlideBible/sbCollection.cpp
===================================================================
--- trunk/src/SlideBible/sbCollection.cpp	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbCollection.cpp	2010-01-07 20:55:10 UTC (rev 223)
@@ -18,90 +18,106 @@
 #include <utilxml.h>
 #include "sbCore.h"
 
+#define VERSION 0.01f
+
 sbCollection::sbCollection()
 {
-	allocated = 0;
-	data = NULL;
-	size = 0;
-	v11n = "KJV";
+	version = VERSION;
 }
 
 sbCollection::~sbCollection()
 {
-	if (data != NULL) delete [] data;
+	;
 }
 
-sbCollection::ITEM& sbCollection::add (sword::VerseKey set)
+sbCollection::item * sbCollection::add ( sword::VerseKey * verse )
 {
-	if (data == NULL)
+	int id = find (verse->getShortText());
+
+	if ( id <= 0 )
 	{
-		allocated = 8;
-		data = new ITEM [allocated];
-	}
+		time_t now; time(&now);
 
-	data[size].verse = set;
-	size++;
+		data.push_back (sbCollection::item());
+		
+		strcpy ( data.back().verse, verse->getShortText() );
 
-	if (size == allocated) // realloc
-	{
-		allocated += 8;
-		ITEM* _data = new ITEM [allocated];
-		for (int i=0; i<size; i++)
-			_data[i] = data[i];
-		delete [] data;
-		data = _data;
+		data.back().created = now;
+		data.back().visited = data.back().created;
+		data.back().custom  = 0;
+		data.back().visits  = 0;
+
+		return & data.back();
 	}
-	return data[size-1];
+	else
+		return & data[id];
+
+	return NULL;
 }
 
-void sbCollection::save (const char* filename, const char* section)
+int sbCollection::find ( const char * short_key_text , const char * range_end )
 {
-	sword::SWConfig  conf(filename);
-	conf.Load();
+	return 0;
+}
 
-	char s_size[5];
-	_itoa(size,s_size,10);
-	conf[section]["Size"] = s_size;
+void sbCollection::save ( const char * filename, const char * section )
+{
+	sword::SWConfig  config (filename);
 	
-	for (int i=0; i<size; i++)
-	{
-		char line[4];
-		sprintf(line,"%02i",i);
+	config.Load();
 
-		char buf[256];
+	char text [8];
+
+	_itoa ( data.size(), text, 10 );
+	config [section]["Size"] = text;
+
+	_snprintf (text,8,"%f", version);
+	config [section]["Version"] = text;
 		
-		_snprintf(buf,256,"<item key=\"%s\" dynamic=\"%i\">",data[i].verse.getText(), data[i].dynamic);
+	for (int i=0; i < data.size(); i++)
+	{
+		char line [4]; sprintf (line,"%02i",i);
 
-		conf[section][line] = buf;
+		char buf [256];
+			
+		_snprintf (buf,256,"<item key=\"%s\" created=\"%i\" visited=\"%i\" visits=\"%i\" custom=\"%i\">", data[i].verse, data[i].created, data[i].visited, data[i].visits, data[i].custom);
+
+		sbAssert ( strlen(buf) >= 254 );
+
+		config [section][line] = buf;
 	}
 
-	conf.Save();
+	config.Save();
 }
 
 void sbCollection::load (const char* filename, const char* section)
 {
-	sword::SWConfig  conf(filename);
-	conf.Load();
+	sword::SWConfig  config (filename);
+	config.Load();
 
-	const int t_size = atoi(conf[section].getWithDefault("Size","0"));
-	v11n = conf[section].getWithDefault("v11n","KJV");
-
-	for (int i=0; i<t_size; i++)
+	const int size = atoi (config[section].getWithDefault("Size","0"));
+	const float config_version = atof (config[section].getWithDefault("Version","0.0"));
+	
+	if ( config_version != VERSION )
 	{
-		char line[4];
-		sprintf(line,"%02i",i);
+		sbAssert ( "Wrong collection version" );
+	}
+	else
+	{
+		for (int i=0; i < size; i++)
+		{
+			char line[4]; sprintf(line,"%02i",i);
 
-		const char* buf = conf[section][line];
+			sword::XMLTag tag (config[section][line]);
 
-		sword::XMLTag tag(buf);
+			data.push_back (sbCollection::item());
 
-		sword::VerseKey key = tag.getAttribute("key");
+			strcpy ( data.back().verse, tag.getAttribute("key") );
 
-		if (strcmp(key.getVersificationSystem(),v11n))
-			sbAssert(true);
-
-		ITEM* item = &add(key);
-		
-		item->dynamic = atoi(tag.getAttribute("dynamic"));
+			data.back().created = atol(tag.getAttribute("created"));
+			data.back().visited = atol(tag.getAttribute("visited"));
+			data.back().visits  = atoi(tag.getAttribute("visits"));
+			data.back().custom  = atol(tag.getAttribute("custom"));
+		}
 	}
 }

Modified: trunk/src/SlideBible/sbCollection.h
===================================================================
--- trunk/src/SlideBible/sbCollection.h	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbCollection.h	2010-01-07 20:55:10 UTC (rev 223)
@@ -19,48 +19,43 @@
 #ifndef SBCOLLECTION_H
 #define SBCOLLECTION_H
 
+#include <vector>
 #include <versekey.h>
 
+#include "sbBase.h"
+
 class sbCollection
 {
 public:
 	sbCollection();
 	~sbCollection();
 
-	struct ITEM
+	struct item
 	{
-		bool                 dynamic:1;
+		time_t                       created;
+		time_t                       visited;
+		unsigned char                visits;
 		
-		unsigned int         created;
-		unsigned int         visited;
-		
-		unsigned short       rating;
-		unsigned char        visit;
+		unsigned long                custom;
 
-		sword::VerseKey      verse;
+		char                         verse [16];
 	};
 
-	sbCollection::ITEM&      add                (sword::VerseKey key);
+	sbCollection::item *             add              ( sword::VerseKey * verse );
+	void                             remove           ( int id );
+	int                              size             ( ) const { return data.size(); }
+	int                              find             ( const char * short_key_text , const char * range_end = NULL );
+	void                             sort             ( const char * type );
+	sbCollection::item &             get              ( const int pos ) { return data[pos]; }
 
-	void                     remove              (int id);
-	void                     remove              (sword::VerseKey key);
-	int                      count               () const {return size;}
-	int                      find                (sword::VerseKey key);
+	sbCollection::item &             operator []      ( const int pos ) { return data[pos]; }
 
-	const TCHAR*             name                () const {return title;}
-	void                     name                (TCHAR* title);
+	void                             load             ( const char* filename, const char* section );
+	void                             save             ( const char* filename, const char* section );
 
-	ITEM&                    operator[]          (const int pos) {return data[pos];}
-
-	void                     load                (const char* filename, const char* section);
-	void                     save                (const char* filename, const char* section);
-
 private:
-	ITEM*                    data;
-	const char*              v11n;
-	int                      size;
-	int                      allocated;
-	TCHAR*                   title;
+	std::vector<sbCollection::item>  data;
+	float                            version;
 };
 
 #endif

Modified: trunk/src/SlideBible/sbControl.cpp
===================================================================
--- trunk/src/SlideBible/sbControl.cpp	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbControl.cpp	2010-01-07 20:55:10 UTC (rev 223)
@@ -19,23 +19,23 @@
 sbRect layout (int index, int num, int scheme)
 {
 	const int themeSize = Core->getTheme()->size;
-	const sbRect* screenRect = &Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->rect;
+	const sbRect * screenRect = &Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->rect;
 
 	sbRect rect;
 
 	if (scheme == 1) // bottom bar
 	{
-		rect.left   (screenRect->right()*(index-1)/num);
-		rect.top    (screenRect->bottom()-(themeSize*20/100));
-		rect.right  (screenRect->right()*index/num);
-		rect.bottom (screenRect->bottom());
+		rect.left   = screenRect->right*(index-1)/num;
+		rect.top    = screenRect->bottom-(themeSize*20/100);
+		rect.right  = screenRect->right*index/num;
+		rect.bottom = screenRect->bottom;
 	}
 	else if (scheme == 2) // can switch
 	{
-		rect.left   (screenRect->right()*(index-1)/num);
-		rect.top    (screenRect->bottom()-(themeSize*40/100));
-		rect.right  (screenRect->right()*index/num);
-		rect.bottom (screenRect->bottom()-(themeSize*20/100));
+		rect.left   = screenRect->right*(index-1)/num;
+		rect.top    = screenRect->bottom-(themeSize*40/100);
+		rect.right  = screenRect->right*index/num;
+		rect.bottom = screenRect->bottom-(themeSize*20/100);
 	}
 	else if (scheme == 0) // screen matrix
 	{
@@ -47,18 +47,18 @@
 		pv = index%columns == 0 ? columns : index%columns;
 		ph = ((index-pv)/columns)+1;
 
-		rect.left (indent+((screenRect->right()-(indent*2)+sep)*(pv-1)/columns));
-		rect.top ((themeSize*10/100)+indent+((screenRect->bottom()-(themeSize*30/100)-(indent*2)+sep)*(ph-1)/rows));
-		rect.right (indent+((screenRect->right()-(indent*2)+sep)*pv/columns)-sep);
-		rect.bottom ((themeSize*10/100)+indent+((screenRect->bottom()-(themeSize*30/100)-(indent*2)+sep)*ph/rows)-sep);
+		rect.left   = indent+((screenRect->right-(indent*2)+sep)*(pv-1)/columns);
+		rect.top    = (themeSize*10/100)+indent+((screenRect->bottom-(themeSize*30/100)-(indent*2)+sep)*(ph-1)/rows);
+		rect.right  = indent+((screenRect->right-(indent*2)+sep)*pv/columns)-sep;
+		rect.bottom = (themeSize*10/100)+indent+((screenRect->bottom-(themeSize*30/100)-(indent*2)+sep)*ph/rows)-sep;
 
 		int w = rect.width();
 		int h = rect.height();
 
 		if ( h > w )
 		{
-			rect.top ( rect.top() + ((h-w)/2) );
-			rect.bottom ( rect.top() + w );
+			rect.top    = rect.top + ((h-w)/2);
+			rect.bottom = rect.top + w;
 		}
 	}
 	else
@@ -70,7 +70,6 @@
 sbControl::sbControl ( TYPE _type_ )
 : type ( _type_ )
 , text ( L"" )
-, sbObject ( "sbControl" )
 {
 	const int themeSize = Core->getTheme()->size;
 	const sbRect* screenRect = &Core->getSurface( sbCore::SURFACE::TYPE_WHOLE )->rect;
@@ -89,7 +88,10 @@
 	case TYPE_WIDE_CLOSE:            rect = layout(1,1,1);   setText(L"Close"); break;
 	case TYPE_CAN_SWITCH_LEFT:       rect = layout(1,12,2);  setText(L"<");     break;
 	case TYPE_CAN_SWITCH_RIGHT:      rect = layout(12,12,2); setText(L">");     break;
-	case TYPE_BUTTON_OPEN_FILE:      rect = sbRect ( layout(1,4,1).left() , layout(1,4,1).top() , layout(3,4,1).right() , layout(3,4,1).bottom()); setText(L""); break;
+	case TYPE_BUTTON_OPEN_FILE:      rect = layout(1,4,1);   setText(L"");      break;
+	case TYPE_OPEN_HISTORY:          rect = layout(1,4,1);   setText(L"H");    break;
+	case TYPE_OPEN_BOOKMARKS:        rect = layout(2,4,1);   setText(L"B");    break;
+	case TYPE_OPEN_READINGS:         rect = layout(3,4,1);   setText(L"R");    break;
 	case TYPE_MENU_EXIT:
 		{
 			rect = *screenRect;
@@ -128,7 +130,7 @@
 			int step = count / max + 1;
 			count = count / step;
 
-			rect = *screenRect;
+			rect = * screenRect;
 
 			for ( int i = 1; i <= count; i++ )
 			{
@@ -152,7 +154,6 @@
 sbControl::sbControl ( TYPE _type_ , const sbRect _rect_ , const TCHAR* _text_ )
 : type ( _type_ )
 , rect ( _rect_ )
-, sbObject ( "sbControl" )
 {
 	setText ( _text_ );
 }
@@ -170,29 +171,16 @@
 	for (int i = 0; i < childrens.size(); i++) delete childrens[i];
 }
 
-void sbControl::onPaint (HDC hdc) const
+void sbControl::onPaint ( sbRenderContext hdc ) const
 {
-	HFONT font = (HFONT)SelectObject(hdc, Core->getTheme()->styles[style].font);
-	sbColor color = SetTextColor(hdc, Core->getTheme()->ItemTextColor);
+	sbFont font = sbSelectFont(hdc, Core->getTheme()->styles[style].font);
+	sbColor color = sbSelectColor(hdc, Core->getTheme()->ItemTextColor);
 	
 	switch (type)
 	{
-	/*case TYPE_SHOW_CURRENT_PLACE:
-		{
-			const char * keyText = Core->currentKey.getText();
-			int length = strlen(keyText);
-			TCHAR * wideText = new TCHAR [length+1];
-			mbstowcs(wideText, keyText, length);
-			SIZE size;
-			GetTextExtentPoint32(hdc, wideText, length, &size);
-			const sbRect * rect = &Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->rect;
-			ExtTextOut (hdc, (rect->width()-size.cx)/2+rect->left(), Core->getTheme()->size/5, ETO_OPAQUE, NULL, wideText, length, 0);
-			delete [] wideText;
-		}
-		break;*/
 	case TYPE_CAN_SWITCH_LEFT:
 	case TYPE_CAN_SWITCH_RIGHT:
-		ExtTextOut ( hdc, textPos.x, textPos.y, ETO_OPAQUE, NULL, text, _tcslen(text), 0);
+		sbDrawText ( hdc, textPos.x, textPos.y, text, _tcslen(text));
 		break;
 	default:
 		if (isMenu())
@@ -203,20 +191,20 @@
 			
 			for (int i=0; i < childrens.size(); i++) childrens[i]->onPaint( hdc );
 
-			SetTextColor(hdc, Core->getTheme()->ItemMenuTextColor);
-			ExtTextOut(hdc, textPos.x, textPos.y, ETO_OPAQUE, NULL, text, _tcslen(text), 0);
+			sbSelectColor(hdc, Core->getTheme()->ItemMenuTextColor);
+			sbDrawText(hdc, textPos.x, textPos.y, text, _tcslen(text));
 
 			Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->fade = true;
 		}
 		else
 		{
 			Core->getTheme()->drawElement(hdc, &rect, sbTheme::ELEMENT::CONTROL);
-			ExtTextOut(hdc, textPos.x, textPos.y, ETO_OPAQUE, NULL, text, _tcslen(text), 0);
+			sbDrawText(hdc, textPos.x, textPos.y, text, _tcslen(text));
 		}
 	}
 
-	SelectObject(hdc, font);
-	SetTextColor(hdc, color);
+	sbSelectFont(hdc, font);
+	sbSelectColor(hdc, color);
 }
 
 void sbControl::onPressed()
@@ -238,8 +226,17 @@
 	case TYPE_OPEN_MODULE_SELECTION:
 		Core->switchList(sbList::TYPE_SELECT_MODULE);
 		break;
+	case TYPE_OPEN_HISTORY:
+		Core->switchList(sbList::TYPE_HISTORY);
+		break;
+	case TYPE_OPEN_BOOKMARKS:
+		Core->switchList(sbList::TYPE_BOOKMARKS);
+		break;
+	case TYPE_OPEN_READINGS:
+		Core->switchList(sbList::TYPE_READINGS);
+		break;
 	case TYPE_MENU_EXIT_YES:
-		PostQuitMessage(1);
+		sbExit(1);
 		break;
 	case TYPE_OPEN_NAVIGATION:
 		Core->switchList(sbList::TYPE_NAVIGATION);
@@ -273,8 +270,8 @@
 
 void sbControl::setText ( const TCHAR * _text_ )
 {
-	SIZE sz;
-	HDC hdc = CreateCompatibleDC ( NULL );
+	sbPoint sz;
+	//HDC hdc = CreateCompatibleDC ( NULL );
 
 	text = (TCHAR*)_text_;
 
@@ -291,21 +288,19 @@
 	else
 		style = sbTheme::STYLE::CAPTION;
 
-	SelectObject ( hdc, Core->getTheme()->styles[style].font );
-	GetTextExtentPoint32 ( hdc, text, _tcslen(text), &sz );
+	//SelectObject ( hdc, Core->getTheme()->styles[style].font );
+	sz = sbGetTextExtent ( Core->getTheme()->styles[style].font, text, _tcslen(text) );
 
-	textPos.x = (rect.width() - sz.cx) / 2 + rect.left();
-	textPos.y = (rect.height() - sz.cy) / 2 + rect.top();
+	textPos.x = (rect.width() - sz.x) / 2 + rect.left;
+	textPos.y = (rect.height() - sz.y) / 2 + rect.top;
 
-	DeleteDC ( hdc );
-
 	if ( isMenu() )
 	{
-		int bottom = rect.bottom();
+		int bottom = rect.bottom;
 
 		for (int i=0; i<childrens.size(); i++)
-			bottom = min(childrens[i]->rect.top(),bottom);
+			bottom = min(childrens[i]->rect.top,bottom);
 
-		textPos.y = rect.top()+((bottom-rect.top()-sz.cy)/2);
+		textPos.y = rect.top+((bottom-rect.top-sz.y)/2);
 	}
 }

Modified: trunk/src/SlideBible/sbControl.h
===================================================================
--- trunk/src/SlideBible/sbControl.h	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbControl.h	2010-01-07 20:55:10 UTC (rev 223)
@@ -17,16 +17,14 @@
 #define SBCONTROL_H
 
 #include "sbTheme.h"
-#include "sbObject.h"
+#include "sbBase.h"
 
 #include <vector>
 
-//using std::vector;
-
 // Screen Layout Generator
 sbRect layout ( int index , int num , int scheme );
 
-class sbControl : public sbObject
+class sbControl
 {
 public:
 	enum TYPE
@@ -42,6 +40,9 @@
 		TYPE_OPEN_SEARCH,
 		TYPE_OPEN_HOME,
 		TYPE_OPEN_TEXT,
+		TYPE_OPEN_BOOKMARKS,
+		TYPE_OPEN_READINGS,
+		TYPE_OPEN_HISTORY,
 		TYPE_MODE_ADD_STAR,
 		TYPE_CAN_SWITCH_LEFT,
 		TYPE_CAN_SWITCH_RIGHT,                                  // 10
@@ -65,19 +66,19 @@
 
 public:
 	                             sbControl         ( TYPE type );
-	                            ~sbControl         ( );
+	                            ~sbControl         ();
 
 private:
 								sbControl          ( TYPE type , sbRect rect , const TCHAR * text );
 
 public:
 
-	void                         operator =        ( const sbControl & control ) {;}
+	//void                         operator =        ( const sbControl & control ) {;}
 
-	void                         onPressed         ( );
-	void                         onPaint           ( HDC hdc ) const;
+	void                         onPressed         ();
+	void                         onPaint           ( sbRenderContext rc ) const;
 
-	inline bool                  hit               ( int x , int y ) const {return (rect.pointInRect(x,y));}
+	inline bool                  hit               ( int x , int y ) const {return (rect.inRect(x,y));}
 
 	const TYPE                   type;
 
@@ -91,7 +92,7 @@
 	const TCHAR                 *text;
 
 	sbTheme::STYLE::TYPE         style;
-	POINT                        textPos;
+	sbPoint                      textPos;
 
 	std::vector<sbControl*>      childrens;
 };

Modified: trunk/src/SlideBible/sbCore.cpp
===================================================================
--- trunk/src/SlideBible/sbCore.cpp	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbCore.cpp	2010-01-07 20:55:10 UTC (rev 223)
@@ -13,18 +13,22 @@
  * General Public License for more details.
  ************************************************************************/
 
-#include "sbCore.h"
 #include <markupfiltmgr.h>
 #include <localemgr.h>
 #include <SWBuf.h>
 #include <SWLog.h>
-#include "sbObject.h"
 
+#include "sbCore.h"
+
 #pragma warning(disable : 4018)
 
-std::map < const char *, int > sbObject::tracker;
+sbCore * Core;
 
-void sbMessage(const char *format , ...)
+sbList * sbCore::backgroundList;
+
+//std::map<const char*,std::vector<sbObject*>> sbObject::tracker;
+
+void sbMessage ( const char * format , ... )
 {
 	va_list args;
 
@@ -42,13 +46,10 @@
 	fclose(file);
 }
 
-sbCore::sbCore( HWND _window_ )
+sbCore::sbCore ()
 : defaultModule ( NULL )
-, hContainer ( _window_ )
 {
 	sbMessage ("Launch SlideBible Core.\n");
-
-	sbAssert ( hContainer == NULL );
 	
 	sbAssert ( Core != NULL );
 
@@ -70,43 +71,36 @@
 
 	showListBanner      = false;
 
-	memset(&threadData, 0, sizeof(THREAD_DATA));
+	backgroundThread    = NULL;
+	
+	mpOptions           = NULL;
+	mpSwordMgr          = NULL;
 
-	// init surface
-	PAINTSTRUCT ps;
-	HDC hdc = BeginPaint ( hContainer, &ps );
+	// init surfaces
+	sbGetScreenRect (rClient);
 
-	GetClientRect( hContainer, &rClient );
-
 	surfaces[SURFACE::TYPE_WHOLE].rect = rClient;
 
 	theme.init(); // this must be after init SURFACE::TYPE_WHOLE, but before SURFACE::TYPE_LIST
 
 	surfaces[SURFACE::TYPE_LIST].rect = rClient;
-	surfaces[SURFACE::TYPE_LIST].rect.bottom (surfaces[SURFACE::TYPE_LIST].rect.bottom() - theme.size/5);
+	surfaces[SURFACE::TYPE_LIST].rect.bottom -= theme.size/5;
 
 	surfaces[SURFACE::TYPE_BUFFER].rect = surfaces[SURFACE::TYPE_LIST].rect;
 
 	for (int i=0; i<SURFACE::COUNT; i++)
 	{
-		surfaces[i].hdc = CreateCompatibleDC(hdc);
-		surfaces[i].bitmap = CreateCompatibleBitmap(hdc, rClient.width(), rClient.height());
-		SelectObject(surfaces[i].hdc, surfaces[i].bitmap);
-		SetBkMode(surfaces[i].hdc, TRANSPARENT);
+		surfaces[i].hdc = sbCreateRenderContext();
+		surfaces[i].bitmap = sbRenderContextBitmap (surfaces[i].hdc, surfaces[i].rect.width(), surfaces[i].rect.height());
 		surfaces[i].needRedraw = true;
 	}
 	
-	theme.drawElement(hdc, &rClient, sbTheme::ELEMENT::BACKGROUND);
-	
-	EndPaint ( hContainer, &ps );
-	DeleteDC ( hdc );
+	sbUpdateScreen();
 
 	//sword::SWLog::getSystemLog()->setLogLevel(5);
 
 	// load options
-	mpOptions = new sword::SWConfig(".\\options.conf");
-	sbAssert ( mpOptions == NULL );
-	mpOptions->Load();
+	mpOptions = new sword::SWConfig(".\\options.conf"); sbAssert ( mpOptions == NULL ); mpOptions->Load();
 	
 	cineticDamping = (float)atof((*mpOptions)["Ui"].getWithDefault("CineticDamping", "0.95"));
 	cineticFactor  = (float)atof((*mpOptions)["Ui"].getWithDefault("CineticFactor", "0.5"));
@@ -116,39 +110,8 @@
 	versesOptimal  = atoi((*mpOptions)["Ui"].getWithDefault("versesOptimal", "50"));
 
 	// user locale
-	char *defaultLocale = "en_US";
+	sword::LocaleMgr::getSystemLocaleMgr()->setDefaultLocaleName((*mpOptions)["General"].getWithDefault("Locale", sbGetLocale()));
 
-	TCHAR userLocale [6];
-	GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME, userLocale, 6);
-	
-	if (_tcscmp(userLocale, L"RUS")==0)          defaultLocale = "ru_RU-cp1251";
-	else if (_tcscmp(userLocale, L"AFK")==0)     defaultLocale = "af";
-	else if (_tcscmp(userLocale, L"BGR")==0)     defaultLocale = "bg_BG-cp1251";
-	else if (_tcscmp(userLocale, L"CSY")==0)     defaultLocale = "cs";
-	else if (_tcscmp(userLocale, L"DAN")==0)     defaultLocale = "da";
-	else if (_tcscmp(userLocale, L"ETI")==0)     defaultLocale = "et";
-	else if (_tcscmp(userLocale, L"FIN")==0)     defaultLocale = "fi";
-	else if (_tcscmp(userLocale, L"IND")==0)     defaultLocale = "id";
-	else if (_tcscmp(userLocale, L"KOR")==0)     defaultLocale = "ko";
-	else if (_tcscmp(userLocale, L"PLK")==0)     defaultLocale = "pl";
-	else if (_tcscmp(userLocale, L"ROM")==0)     defaultLocale = "ro";
-	else if (_tcscmp(userLocale, L"SKY")==0)     defaultLocale = "sk";
-	else if (_tcscmp(userLocale, L"SLV")==0)     defaultLocale = "sl";
-	else if (_tcscmp(userLocale, L"UKR")==0)     defaultLocale = "uk_UA-cp1251";
-	else if (_tcsnccmp(userLocale, L"AR", 2)==0) defaultLocale = "ar_EG-cp1256";
-	else if (_tcsnccmp(userLocale, L"EN", 2)==0) defaultLocale = "en_GB";
-	else if (_tcsnccmp(userLocale, L"DE", 2)==0) defaultLocale = "de";
-	else if (_tcsnccmp(userLocale, L"ES", 2)==0) defaultLocale = "es";
-	else if (_tcsnccmp(userLocale, L"FR", 2)==0) defaultLocale = "fr";
-	else if (_tcsnccmp(userLocale, L"IT", 2)==0) defaultLocale = "it";
-	else if (_tcsnccmp(userLocale, L"NL", 2)==0) defaultLocale = "nl";
-	else if (_tcsnccmp(userLocale, L"NO", 2)==0) defaultLocale = "no";
-	else if (_tcsnccmp(userLocale, L"PT", 2)==0) defaultLocale = "pt";
-	else if (_tcscmp(userLocale, L"USA")!=0)
-		sbMessage("Unsupported user locale: %s\n", userLocale);
-
-	sword::LocaleMgr::getSystemLocaleMgr()->setDefaultLocaleName((*mpOptions)["General"].getWithDefault("Locale", defaultLocale));
-
 	// init sword
 	mpSwordMgr = new sword::SWMgr(new sword::MarkupFilterMgr(sword::FMT_OSIS, sword::ENC_UTF16));
 	
@@ -161,8 +124,11 @@
 
 	((sword::SWModule*)defaultModule) = currentModule;
 
-	bookmarks.load(".\\verselists.conf","Bookmarks");
-
+	// restore collections
+	collections["bookmarks"].load(".\\verselists.conf","bookmarks");
+	collections["readings"].load(".\\verselists.conf","readings");
+	collections["history"].load(".\\verselists.conf","history");
+	
 	// create ui
 	switchList ( sbList::TYPE_HOME );
 }
@@ -171,21 +137,23 @@
 {
 	threadDestroy();
 	
-	if (currentList != NULL && currentList->hasModule())
-		(*mpOptions)["Bookmarks"]["LastPlace"] = currentList->getKey()->getText();
+	if (listModule != NULL && listModule->hasModule())
+		(*mpOptions)["Bookmarks"]["LastPlace"] = listModule->getKey()->getText();
 
-	bookmarks.save(".\\verselists.conf","Bookmarks");
+	// save collections
+	for (std::map<const char*,sbCollection>::iterator it=collections.begin(); it != collections.end(); it++)
+	{
+		it->second.save(".\\verselists.conf",it->first);
+	}
 
-	sbList* lists[] = {listModule, listModuleSelection, listBookSelection, listSearch, listHome};
+	sbList * lists[] = {listModule, listModuleSelection, listBookSelection, listSearch, listHome};
 
 	for (int i=0; i<sizeof(lists)/sizeof(sbList*); i++)
 	{
 		if (lists[i] != NULL)
 		{
-			while (lists[i]->getPrev() != NULL)
-				delete lists[i]->getPrev();
-			while (lists[i]->getNext() != NULL)
-				delete lists[i]->getNext();
+			while (lists[i]->getPrev() != NULL) delete lists[i]->getPrev();
+			while (lists[i]->getNext() != NULL) delete lists[i]->getNext();
 			delete lists[i];
 		}
 	}
@@ -198,20 +166,18 @@
 
 	for (int i=0; i<SURFACE::COUNT; i++)
 	{
-		DeleteObject(surfaces[i].bitmap);
-		DeleteDC(surfaces[i].hdc);
+		sbDeleteBitmap(surfaces[i].bitmap);
+		sbDestroyRenderContext(surfaces[i].hdc);
 	}
 
-	DestroyWindow(hContainer);
+	//for (std::map<const char*,std::vector<sbObject*>>::iterator it = sbObject::tracker.begin(); it != sbObject::tracker.end(); it++)
+	//	if (it->second.size() != 0)
+	//		sbMessage ("Delete misalignment of %s (%i)\n", it->first, it->second.size());
 
-	for (std::map<const char *, int>::iterator it = sbObject::tracker.begin(); it != sbObject::tracker.end(); it++)
-		if (it->second != 0)
-			sbMessage ("new/delete misalignment for %s (%i)\n", it->first, it->second);
-
 	sbMessage ("Shutdown SlideBible Core.\n");
 }
 
-void sbCore::onPaint ( HDC hdc )
+void sbCore::onPaint ( sbRenderContext hdc )
 {
 	if (currentList != NULL)
 	{
@@ -239,8 +205,8 @@
 					surfaces[SURFACE::TYPE_BUFFER].needRedraw = false;
 				}
 
-				BitBlt(surfaces[SURFACE::TYPE_WHOLE].hdc, rClient.left(), rClient.top(), rClient.width()-listShift, rClient.height(), surfaces[SURFACE::TYPE_LIST].hdc, listShift, 0, SRCCOPY);
-				BitBlt(surfaces[SURFACE::TYPE_WHOLE].hdc, rClient.right()-listShift, rClient.top(), listShift, rClient.height(), surfaces[SURFACE::TYPE_BUFFER].hdc, 0, 0, SRCCOPY);
+				sbBitBlt(surfaces[SURFACE::TYPE_WHOLE].hdc, rClient.left, rClient.top, rClient.width()-listShift, rClient.height(), surfaces[SURFACE::TYPE_LIST].hdc, listShift, 0);
+				sbBitBlt(surfaces[SURFACE::TYPE_WHOLE].hdc, rClient.right-listShift, rClient.top, listShift, rClient.height(), surfaces[SURFACE::TYPE_BUFFER].hdc, 0, 0);
 			}
 			else
 			{
@@ -254,8 +220,8 @@
 					surfaces[SURFACE::TYPE_BUFFER].needRedraw = false;
 				}
 
-				BitBlt(surfaces[SURFACE::TYPE_WHOLE].hdc, surfaces[SURFACE::TYPE_LIST].rect.left()-listShift,  surfaces[SURFACE::TYPE_LIST].rect.top(), surfaces[SURFACE::TYPE_LIST].rect.width()+listShift, surfaces[SURFACE::TYPE_LIST].rect.height(), surfaces[SURFACE::TYPE_LIST].hdc, 0, 0, SRCCOPY);
-				BitBlt(surfaces[SURFACE::TYPE_WHOLE].hdc, surfaces[SURFACE::TYPE_LIST].rect.left(), surfaces[SURFACE::TYPE_LIST].rect.top(), surfaces[SURFACE::TYPE_LIST].rect.left()-listShift, surfaces[SURFACE::TYPE_LIST].rect.height(), surfaces[SURFACE::TYPE_BUFFER].hdc, surfaces[SURFACE::TYPE_BUFFER].rect.right()+listShift, 0, SRCCOPY);
+				sbBitBlt(surfaces[SURFACE::TYPE_WHOLE].hdc, surfaces[SURFACE::TYPE_LIST].rect.left-listShift,  surfaces[SURFACE::TYPE_LIST].rect.top, surfaces[SURFACE::TYPE_LIST].rect.width()+listShift, surfaces[SURFACE::TYPE_LIST].rect.height(), surfaces[SURFACE::TYPE_LIST].hdc, 0, 0);
+				sbBitBlt(surfaces[SURFACE::TYPE_WHOLE].hdc, surfaces[SURFACE::TYPE_LIST].rect.left, surfaces[SURFACE::TYPE_LIST].rect.top, surfaces[SURFACE::TYPE_LIST].rect.left-listShift, surfaces[SURFACE::TYPE_LIST].rect.height(), surfaces[SURFACE::TYPE_BUFFER].hdc, surfaces[SURFACE::TYPE_BUFFER].rect.right+listShift, 0);
 			}
 		}
 
@@ -267,7 +233,7 @@
 			if (!bScrollTimer)
 			{
 				bScrollTimer = true;
-				SetTimer(hContainer, TIMER_SCROLL, refreshRate, (TIMERPROC) NULL);
+				sbSetTimer(TIMER_SCROLL, refreshRate);
 			}
 			
 			if (currentList->needScroll < 0)
@@ -300,17 +266,22 @@
 		sbRect rect (input.startx-(input.tapCounter*4), input.starty-(input.tapCounter*4), input.startx+(input.tapCounter*4), input.starty+(input.tapCounter*4));
 		Core->getTheme()->drawElement(surfaces[SURFACE::TYPE_WHOLE].hdc, &rect, sbTheme::ELEMENT::TAPPED, input.tapCounter);
 	}
-	
-	BitBlt(hdc, surfaces[SURFACE::TYPE_WHOLE].rect.left(), surfaces[SURFACE::TYPE_WHOLE].rect.top(), surfaces[SURFACE::TYPE_WHOLE].rect.width(), surfaces[SURFACE::TYPE_WHOLE].rect.height(), surfaces[SURFACE::TYPE_WHOLE].hdc, 0, 0, SRCCOPY);
+
+	const SURFACE * whole = & surfaces[SURFACE::TYPE_WHOLE];
+
+	//sbFillRect(surfaces[SURFACE::TYPE_WHOLE].hdc,&rClient,sbColor(0,255,0));
+	//sbFillRect(hdc,&rClient,sbColor(0,255,0));
+
+	sbBitBlt(hdc, whole->rect.left, whole->rect.top, whole->rect.width(), whole->rect.height(), whole->hdc, 0, 0);
 }
 
-bool sbCore::onMouse (int x, int y, const int state)
+void sbCore::onMouse ( int x, int y, const int state )
 {
-	if (state == WM_LBUTTONDOWN)
+	if ( state == MSG_MOUSE_L_DOWN )
 	{
 		sbAssert(input.mousePressed == true);
 
-		if (listShift != 0) return false;
+		if (listShift != 0) return;
 
 		input.lastx = input.startx = x;
 		input.lasty = input.starty = y;
@@ -322,11 +293,11 @@
 			currentList->onPressed(x,y);
 		
 		input.tapCounter = 0;
-		SetTimer(hContainer, TIMER_TAP, 1000/10, (TIMERPROC) NULL);
+		sbSetTimer(TIMER_TAP, 1000/10);
 	}
-	else if (state == WM_MOUSEMOVE)
+	else if ( state == MSG_MOUSE_MOVE )
 	{
-		if (!input.mousePressed) return false;
+		if (!input.mousePressed) return;
 
 		const int max = theme.size/20;
 
@@ -338,12 +309,12 @@
 		if (abs(input.startx-x) > max || abs(input.starty-y) > max)
 		{
 			input.leaveZone = true;
-			KillTimer(hContainer, TIMER_TAP);
+			sbKillTimer(TIMER_TAP);
 			input.tapCounter = 0;
 		}
 
 		// update cinetic power
-		if (GetTickCount()-cineticTicks > 500)
+		if (sbGetTickCount()-cineticTicks > 500)
 		{
 			if (fabsf(cineticPower) > (float)abs(dy))
 				cineticPower = (float)dy;
@@ -354,7 +325,7 @@
 				cineticPower = (float)dy;
 		}
 
-		cineticTicks = GetTickCount();
+		cineticTicks = sbGetTickCount();
 
 		if ((dy > 0 && cineticPower < 0) || (dy < 0 && cineticPower > 0))
 			cineticPower = 0.0f;
@@ -363,7 +334,7 @@
 		{
 			if (!input.block)
 			{
-				if (abs(input.startx-x) > (rClient.right()/6)+(abs(input.starty-y)/2))
+				if (abs(input.startx-x) > (rClient.right/6)+(abs(input.starty-y)/2))
 					listShift = input.startx-x;
 				else
 					listShift = 0;
@@ -381,13 +352,13 @@
 		input.lasty = y;
 		input.lastx = x;
 	}
-	else if (state == WM_LBUTTONUP)
+	else if ( state == MSG_MOUSE_L_UP )
 	{
-		if (!input.mousePressed) return false;
+		if (!input.mousePressed) return;
 
 		// update cinetic power
 		float factor;
-		float t = (float)GetTickCount()-cineticTicks;
+		float t = (float)sbGetTickCount()-cineticTicks;
 		if (t > 500)
 		{
 			t = 1-((t-500)/1500);
@@ -395,7 +366,7 @@
 			cineticPower *= t;
 		}
 
-		factor = (abs(input.starty-y)/(rClient.bottom()*cineticFactor));
+		factor = (abs(input.starty-y)/(rClient.bottom*cineticFactor));
 
 		cineticPower *= factor;
 
@@ -409,27 +380,26 @@
 
 		if (listShift != 0)
 		{
-			SetTimer(hContainer, TIMER_SLIDE, refreshRate, (TIMERPROC) NULL);
+			sbSetTimer(TIMER_SLIDE, refreshRate);
 			cineticPower = 0.0f;
 		}
 		
 		if (fabsf(cineticPower) > 0.0f)
 		{
 			bScrollTimer = true;
-			SetTimer(hContainer, TIMER_SCROLL, refreshRate, (TIMERPROC) NULL);
+			sbSetTimer(TIMER_SCROLL, refreshRate);
 		}
 
 		input.mousePressed = false;
 		input.tapCounter = 0;
 
-		KillTimer(hContainer, TIMER_TAP);
+		sbKillTimer(TIMER_TAP);
 		
 		redraw();
 	}
-	return true;
 }
 
-bool sbCore::onTimer (const int timer)
+void sbCore::onTimer (const int timer)
 {
 	if (currentList != NULL) currentList->onTimer(timer);
 
@@ -443,8 +413,7 @@
 
 				requestedRedraw = false;
 		
-				InvalidateRect( hContainer, &rClient, false );
-				return UpdateWindow( hContainer ) != FALSE;
+				sbUpdateScreen();
 			}
 		}
 		break;
@@ -464,7 +433,7 @@
 			else
 			{
 				bScrollTimer = false;
-				KillTimer(hContainer, TIMER_SCROLL);
+				sbKillTimer(TIMER_SCROLL);
 			}
 		}
 		break;
@@ -477,7 +446,7 @@
 				redraw();
 			}
 			else
-				KillTimer(hContainer, TIMER_TAP);
+				sbKillTimer(TIMER_TAP);
 		}
 		break;
 
@@ -492,7 +461,7 @@
 				surfaces[SURFACE::TYPE_LIST  ].needRedraw = true;
 				surfaces[SURFACE::TYPE_BUFFER].needRedraw = true;
 
-				KillTimer(hContainer, TIMER_SLIDE);
+				sbKillTimer(TIMER_SLIDE);
 			}
 			else
 			{
@@ -515,12 +484,11 @@
 	case TIMER_BANNER:
 		{
 			showListBanner = false;
-			KillTimer(hContainer, TIMER_BANNER);
+			sbKillTimer(TIMER_BANNER);
 			redraw();
 		}
 		break;
 	}
-	return true;
 }
 
 void sbCore::redraw()
@@ -531,12 +499,11 @@
 	if (!redrawTimerOn)
 	{
 		redrawTimerOn = true;
-		SetTimer(hContainer, TIMER_REDRAW, refreshRate, (TIMERPROC) NULL);
+		sbSetTimer(TIMER_REDRAW, refreshRate);
 
 		requestedRedraw = false;
 		
-		InvalidateRect(hContainer, &rClient, FALSE);
-		UpdateWindow(hContainer);
+		sbUpdateScreen();
 	}
 	else
 	{
@@ -689,11 +656,11 @@
 
 	if ( showListBanner )
 	{
-		SetTimer( hContainer, TIMER_BANNER , 5000 , (TIMERPROC) NULL );
+		sbSetTimer( TIMER_BANNER , 5000 );
 	}
 	else
 	{
-		KillTimer( hContainer, TIMER_BANNER );
+		sbKillTimer( TIMER_BANNER );
 	}
 	
 	currentList->onActivate();
@@ -701,73 +668,25 @@
 	redraw();
 }
 
-DWORD WINAPI sbCore::threadMain (LPVOID pData)
-{
-	sbCore::THREAD_DATA* data = reinterpret_cast<sbCore::THREAD_DATA*>(pData);
 
-	sbMessage ("Thread Launched.\n");
-
-	while (!data->abort)
-	{
-		data->list->updateVerses(&data->abort);
-		Sleep(10);
-	}
-
-	sbMessage ("Thread Stoped.\n");
-
-	data->running = false;
-	return 0;
+void sbCore::threadMain (bool * abort)
+{
+	sbAssert(backgroundList==NULL);
+	backgroundList->updateVerses(abort);
 }
 
 void sbCore::threadCreate (sbList *list)
 {
-	if(threadData.running)
-	{
-		if (threadData.list == list)
-			return;
-		else
-			threadDestroy();
-	}
-
-	threadData.abort = false;
-	threadData.list = list;
-	threadData.handle = CreateThread(NULL, 0, sbCore::threadMain, (LPVOID)&threadData, 0, &threadData.id);
-
-    if(threadData.handle)
-	{
-		threadData.running = true;
-        SetThreadPriority(threadData.handle, THREAD_PRIORITY_BELOW_NORMAL);
-	}
+	backgroundList   = list;
+	backgroundThread = sbThreadCreate( &this->threadMain );
 }
 
 void sbCore::threadDestroy()
 {
-	const int timeout = 2000;
-	int time = timeout;
+	if ( backgroundThread != NULL ) sbThreadDestroy(backgroundThread);
 	
-	if (!threadData.running) return;
-	
-	threadData.abort = true;
-
-	SetThreadPriority(threadData.handle, THREAD_PRIORITY_ABOVE_NORMAL);
-
-	while (threadData.running && timeout > 0)
-	{
-		Sleep(1);
-		time--;
-	}
-
-	if (timeout <= 0)
-	{
-		sbMessage ("Thread terminated.\n");
-
-        TerminateThread(threadData.handle, -1);
-		threadData.running = false;
-	}
-	else if (timeout-time > 16)
-		sbMessage ("Thread termination takes %i msec.\n", timeout-time);
-	
-	threadData.abort = false;
+	backgroundThread = NULL;
+	backgroundList   = NULL;
 }
 
 void sbCore::controlPressed (sbControl::TYPE type)
@@ -780,50 +699,37 @@
 	}
 }
 
-void sbCore::setSipState (bool on)
+void sbCore::onChar ( TCHAR character )
 {
-	SIPINFO si;
-	
-	if (SipStatus() == SIP_STATUS_UNAVAILABLE)
-	{
-		sbMessage("Sip is unavailable.\n");
-		return;
-	}
+	if ( currentList != NULL ) currentList->onChar(character);
+}
 
-	memset(&si, 0, sizeof(SIPINFO));
-	si.cbSize = sizeof(SIPINFO);
+void sbCore::onKey ( int key , bool down )
+{
+	if ( currentList != NULL && down ) currentList->onKey ( key );
+}
 
-	SHSipInfo(SPI_GETSIPINFO,0,&si,0);
-
-	if (on)
+sbCollection * sbCore::getCollection ( const char * name )
+{
+	if ( name == "bookmarks" || !strcmp(name,"bookmarks") )
 	{
-		if (si.fdwFlags & SIPF_ON) return;
-
-		//printf("%i %i %i %i %i\n",si.fdwFlags, si.fdwFlags | SIPF_ON, si.fdwFlags & SIPF_ON, si.fdwFlags & ~SIPF_ON, si.fdwFlags ^ SIPF_ON);
-
-		si.fdwFlags |= SIPF_ON;
-
-		HWND sipWnd = FindWindow(L"SipWndClass",L"");
-
-		si.rcSipRect.top    += si.rcVisibleDesktop.bottom-si.rcSipRect.bottom;
-		si.rcSipRect.bottom += si.rcVisibleDesktop.bottom-si.rcSipRect.bottom;
-
-		SHSipInfo(SPI_SETSIPINFO,0,&si,0);
-
-		MoveWindow(sipWnd,si.rcSipRect.left,si.rcSipRect.top,si.rcSipRect.right-si.rcSipRect.left,si.rcSipRect.bottom-si.rcSipRect.top,false);
+		return & collections["bookmarks"];
 	}
+	else if ( name == "readings" || !strcmp(name,"readings") )
+	{
+		return & collections["readings"];
+	}
+	else if ( name == "history" || !strcmp(name,"history") )
+	{
+		return & collections["history"];
+	}
 	else
 	{
-		if (!(si.fdwFlags & SIPF_ON)) return;
+		// check verse lists
+		// check tag lists
 
-		si.fdwFlags ^= SIPF_ON;
-		
-		SHSipInfo(SPI_SETSIPINFO,0,&si,0);
+		sbAssert ( "Attempt to get wrong verse collection" );
 	}
-}
 
-void sbCore::onChar(TCHAR character)
-{
-	if (currentList != NULL)
-		currentList->onChar(character);
+	return NULL;
 }

Modified: trunk/src/SlideBible/sbCore.h
===================================================================
--- trunk/src/SlideBible/sbCore.h	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbCore.h	2010-01-07 20:55:10 UTC (rev 223)
@@ -16,18 +16,14 @@
 #ifndef SBCORE_H
 #define SBCORE_H
 
-#include <windows.h>
-#include <aygshell.h>
+#include <map>
+
 #include "sbTheme.h"
 #include "sbControl.h"
 #include "sbList.h"
 #include "sbCollection.h"
-#include "sbCross.h"
+#include "sbBase.h"
 
-void sbMessage ( const char *format , ... );
-
-#define sbAssert(condition) ((condition)?(sbMessage("sbAssert : " #condition ". at %s : %d\n", __FILE__, __LINE__), __debugbreak()) : 0)
-
 class sbCore
 {
 public:
@@ -43,8 +39,8 @@
 			COUNT
 		};
 		
-		HDC                      hdc;
-		HBITMAP                  bitmap;
+		sbRenderContext          hdc;
+		sbBitmap                 bitmap;
 		sbRect                   rect;
 		
 		bool                     needRedraw;
@@ -78,15 +74,14 @@
 		TIMER_SLIDE,
 	};
 
-	sbCore ( HWND hwnd );
-	~sbCore();
+	sbCore();
+   ~sbCore();
 	
-	bool                         onMouse          ( int x, int y, const int state );
-	void                         onPaint          ( HDC hdc );
-	bool                         onTimer          ( const int timer );
+	void                         onMouse          ( int x, int y, const int state );
+	void                         onPaint          ( sbRenderContext rc );
+	void                         onTimer          ( const int timer );
 	void                         onChar           ( TCHAR c );
-	bool                         onKeyDown        ( int key );
-	bool                         onKeyUp          ( int key );
+	void                         onKey            ( int key , bool down );
 
 	void                         redraw           ( );
 
@@ -95,10 +90,8 @@
 	sword::SWConfig *            getOptions       ( )                    {return mpOptions;}
 	const SURFACE *              getSurface       ( SURFACE::TYPE type ) {return &surfaces[type];}
 	const INPUT *                getInput         ( )                    {return &input;}
-	sbCollection *               getBookmarks     ( )                    {return &bookmarks;}
+	sbCollection *               getCollection    ( const char * name );
 	
-	void                         setSipState      ( bool on );
-	
 	void                         switchList       ( sbList::TYPE to );
 
 	void                         threadCreate     ( sbList *list );
@@ -106,22 +99,12 @@
 	
 	void                         controlPressed   ( sbControl::TYPE type );
 
-	//bool                         startTimer       ( TIMER timer );
-
 private:
-	struct THREAD_DATA
-	{
-		sbList                  *list;
-		bool                     running;
-		bool                     abort;
-		DWORD                    id;
-		HANDLE                   handle;
-	};
+	sbThread                     backgroundThread;
 
-	static DWORD WINAPI          threadMain ( LPVOID data );
+	static void                  threadMain (bool * abort);
+	static sbList               *backgroundList;
 
-	THREAD_DATA                  threadData;
-
 	sbList                      *currentList;
 
 	sbList                      *listModule;
@@ -146,14 +129,13 @@
 	sbTheme                      theme;
 
 	sbRect                       rClient;
-	HWND                         hContainer;
 	
 	SURFACE                      surfaces[SURFACE::COUNT];
 
 	sword::SWMgr                *mpSwordMgr;
 	sword::SWConfig             *mpOptions;
 
-	sbCollection                 bookmarks;
+	std::map <const char*, sbCollection> collections;
 
 	float                        cineticDamping;
 	float                        cineticFactor;

Modified: trunk/src/SlideBible/sbItem.cpp
===================================================================
--- trunk/src/SlideBible/sbItem.cpp	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbItem.cpp	2010-01-07 20:55:10 UTC (rev 223)
@@ -20,7 +20,6 @@
 : type  ( _type_ )
 , width ( _width_ )
 , index ( _index_ )
-, sbObject ( "sbItem" )
 {
 	if ( _number_ != -1 )
 	{
@@ -163,10 +162,10 @@
 
 void sbItem::setText ( const TCHAR* _text_ )
 {
-	SIZE sz;
+	sbPoint sz;
 	int  lineWidth = 0, length = _tcslen( _text_ );
 	bool skip = false,  italic = false;
-	HDC  hdc = CreateCompatibleDC ( NULL );
+	sbFont font = Core->getTheme()->styles[style].font;
 
 	sbAssert( _text_ == NULL );
 	
@@ -174,8 +173,6 @@
 
 	lines.push_back( LINE (style) );
 
-	SelectObject ( hdc, Core->getTheme()->styles[style].font );
-
 	for(int i=0; i<length; i++)
 	{
 		TCHAR c = *(_text_+i);
@@ -212,7 +209,7 @@
 
 			lines.back().style = italic == true ? sbTheme::STYLE::TEXT_ITALIC : style;
 
-			SelectObject ( hdc, Core->getTheme()->styles[lines.back().style].font );
+			font = Core->getTheme()->styles[lines.back().style].font;
 		}
 		else if (c == L'\t')
 		{
@@ -231,10 +228,10 @@
 		else if (!skip)
 		{
 			// add character
-			GetTextExtentPoint32(hdc,&c,1,&sz);
+			sz = sbGetTextExtent(font,&c,1);
 			
 			// begin new line
-			if ((lineWidth + sz.cx > width-Core->getTheme()->itemLeftMargin-Core->getTheme()->itemRightMargin) \
+			if ((lineWidth + sz.x > width-Core->getTheme()->itemLeftMargin-Core->getTheme()->itemRightMargin) \
 				&& c != L'.' && c != L',' && c != L' ')
 			{
 				lines.back().newLine = true;
@@ -248,22 +245,20 @@
 
 			if (lines.back().count == 0) lines.back().pos = i;
 
-			lines.back().width += (unsigned short) sz.cx;
+			lines.back().width += (unsigned short) sz.x;
 			
-			if (sz.cy > lines.back().height)
+			if (sz.y > lines.back().height)
 			{
-				sbAssert ((sz.cy >= 30) && (type == TYPE_VERSE));
-				lines.back().height = (unsigned short) sz.cy;
+				sbAssert ((sz.y >= 30) && (type == TYPE_VERSE));
+				lines.back().height = (unsigned short) sz.y;
 			}
 			
 			lines.back().count++;
 
-			lineWidth += (unsigned short) sz.cx;
+			lineWidth += (unsigned short) sz.x;
 		}
 	}
 
-	DeleteDC ( hdc );
-
 	lines.back().newLine = true;
 
 	height = Core->getTheme()->itemTopMargin + Core->getTheme()->itemBottomMargin;

Modified: trunk/src/SlideBible/sbItem.h
===================================================================
--- trunk/src/SlideBible/sbItem.h	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbItem.h	2010-01-07 20:55:10 UTC (rev 223)
@@ -18,9 +18,10 @@
 
 #include <vector>
 #include <string>
-#include "sbObject.h"
 
-class sbItem : private sbObject
+#include "sbBase.h"
+
+class sbItem
 {
 public:
 	enum TYPE

Modified: trunk/src/SlideBible/sbList.cpp
===================================================================
--- trunk/src/SlideBible/sbList.cpp	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbList.cpp	2010-01-07 20:55:10 UTC (rev 223)
@@ -21,31 +21,21 @@
 
 sbList::sbList ( sbList::TYPE _type_ )
 : type ( _type_ )
-, sbObject ( "sbList" )
 {
-	sbMessage("sbList of type %i initialized\n", _type_);
+	itemCurrent = itemHover = itemEdit = itemSelected = NULL;
 
-	itemCurrent        = NULL;
-	itemHover          = NULL;
-	itemEdit           = NULL;
-
 	displaceHeight     = 0;
 	displacePart       = 0.0f;
 	
 	module             = NULL;
-	
-	next               = NULL;
-	prev               = NULL;
-	parent             = NULL;
 
+	next = prev = parent = child = NULL;
+
 	rect = &Core->getSurface(sbCore::SURFACE::TYPE_LIST)->rect;
 
-	verseFirst         = NULL;
-	verseLast          = NULL;
+	verseFirst    = verseLast      = NULL;
+	versesForward = versesBackward = 0;
 
-	versesForward      = 0;
-	versesBackward     = 0;
-
 	listEndConstructed = listStartConstructed = true;
 
 	switch(type)
@@ -53,10 +43,14 @@
 	case TYPE_SEARCH:
 	case TYPE_SELECT_BOOK:
 	case TYPE_SELECT_MODULE:
-		addControl(sbControl::TYPE_OPEN_MODULE_SELECTION);
-		addControl(sbControl::TYPE_OPEN_BOOK_SELECTION);
-		addControl(sbControl::TYPE_OPEN_SEARCH);
-		addControl(sbControl::TYPE_CLOSE);
+		{
+			addControl(sbControl::TYPE_OPEN_MODULE_SELECTION);
+			addControl(sbControl::TYPE_OPEN_BOOK_SELECTION);
+			addControl(sbControl::TYPE_OPEN_SEARCH);
+			addControl(sbControl::TYPE_CLOSE);
+		
+			// fill with items in sbList::setKey
+		}
 		break;
 
 	case TYPE_MODULE_VIEW:
@@ -80,86 +74,33 @@
 
 	case TYPE_OPTIONS:
 		{
-			itemCurrent = new sbItem (sbItem::TYPE_CHECKBOX, L"v", Core->getTheme()->size/5);
-			itemCurrent->attach(new sbItem (sbItem::TYPE_DESCRIPTION, L"Background text loading", rect->width()-(Core->getTheme()->size/5)), sbItem::RIGHT);
 			TCHAR vesionText[64];
 			_sntprintf(vesionText,64,L"Current SWORD version :\n%S",sword::SWVersion::currentVersion.getText());
-			itemCurrent->attach(new sbItem (sbItem::TYPE_TEXT, vesionText, rect->width()), sbItem::NEXT);
-			itemCurrent = itemCurrent->next;
+			itemCurrent = new sbItem (sbItem::TYPE_TEXT, vesionText, rect->width()), sbItem::NEXT;
 			itemCurrent->center = true;
 
-			while ( itemCurrent->prev != NULL ) itemCurrent = itemCurrent->prev;
-
 			rect = &Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->rect;
 		}
 		break;
 
+	case TYPE_READINGS:
+	case TYPE_HISTORY:
+	case TYPE_BOOKMARKS:
+		{
+			addControl(sbControl::TYPE_WIDE_CLOSE);
+
+			// fill with items in sbList::onActivate
+		}
+		break;
+
 	case TYPE_HOME:
 		{
-			itemCurrent = new sbItem (sbItem::TYPE_HEADER, L"Welcome to\nSlideBible!", rect->width());
-
-			addControl(sbControl::TYPE_BUTTON_OPEN_FILE);
+			addControl(sbControl::TYPE_OPEN_HISTORY);
+			addControl(sbControl::TYPE_OPEN_BOOKMARKS);
+			addControl(sbControl::TYPE_OPEN_READINGS);
 			addControl(sbControl::TYPE_BUTTON_CLOSE);
 
-			if (Core->defaultModule != NULL)
-			{
-				sword::VerseKey workKey ( Core->defaultModule->getKey() );
-
-				if ((*Core->getOptions())["Bookmarks"]["LastPlace"] != "")
-				{
-					itemCurrent->attach(new sbItem (sbItem::TYPE_DESCRIPTION, L"Your Last Place :", rect->width()), sbItem::NEXT);
-					itemCurrent = itemCurrent->next;
-
-					const char * bookmark = (*Core->getOptions())["Bookmarks"]["LastPlace"];
-
-					workKey.setText ( bookmark );
-
-					TCHAR * text = new TCHAR [strlen( bookmark ) + 1];
-					mbstowcs ( text, bookmark , strlen( bookmark ) + 1 );
-
-					itemCurrent->attach(new sbItem (sbItem::TYPE_BUTTON_BOOKMARK, text, rect->width(), workKey.Index()), sbItem::NEXT);
-					itemCurrent = itemCurrent->next;
-					itemCurrent->center = true;
-
-					delete [] text;
-				}
-				else
-				{
-					workKey.setText ( "John 1:1" );
-					itemCurrent->attach(new sbItem (sbItem::TYPE_BUTTON_BOOKMARK, L"Read Bible ...", rect->width(), workKey.Index()), sbItem::NEXT);
-					itemCurrent = itemCurrent->next;
-					itemCurrent->center = true;
-				}
-
-				for (int i=0; i < Core->getBookmarks()->count(); i++)
-				{
-					if (i == 0)
-					{
-						itemCurrent->attach(new sbItem (sbItem::TYPE_DESCRIPTION, L"Your Bookmarks :", rect->width()), sbItem::NEXT);
-						itemCurrent = itemCurrent->next;
-					}
-
-					const char * bookmark = (*Core->getBookmarks())[i].verse.getText();
-
-					TCHAR * text = new TCHAR [strlen(bookmark)+1];
-					mbstowcs ( text, bookmark, strlen(bookmark)+1 );
-
-					itemCurrent->attach(new sbItem (sbItem::TYPE_BUTTON_BOOKMARK, text, rect->width(), (*Core->getBookmarks())[i].verse.Index()), sbItem::NEXT);
-					itemCurrent = itemCurrent->next;
-					itemCurrent->center = true;
-
-					delete [] text;
-				}
-
-				//addControl ( sbControl::TYPE_OPEN_TEXT );
-			}
-			else
-			{
-				itemCurrent->attach(new sbItem (sbItem::TYPE_TEXT, L"No modules Found!\n\nPlease download any Bible module from www.crosswire.org and put \"mods.d\" and \"modules\" folders into application floder.", rect->width()), sbItem::NEXT);
-				itemCurrent = itemCurrent->next;
-			}
-
-			while ( itemCurrent->prev != NULL ) itemCurrent = itemCurrent->prev;
+			// fill with items in sbList::onActivate
 		}
 		break;
 
@@ -171,8 +112,6 @@
 
 sbList::~sbList()
 {
-	sbMessage("sbList of type %i deleted\n",type);
-
 	clear();
 
 	if (next != NULL)
@@ -258,7 +197,7 @@
 /*   sbList::setKey
  *   set current position of list module
  */
-void sbList::setKey (sword::VerseKey verse)
+void sbList::setKey ( sword::VerseKey verse )
 {
 	sbMessage("sbList setKey: type:%i module:%s : %s %i:%i\n", type, (module == NULL ? "null" : module->Name()), verse.getBookName(), verse.getChapter(), verse.getVerse());
 
@@ -426,10 +365,14 @@
 
 			displaceHeight = rect->height()*2/5;
 
-			// adding blank verses starts automatically before redraw
-			// filling with text occurs in background thread
+			// adding blank verses starts automatically in sbList::onTimer(sbCore::TIMER_BEFORE_REDRAW)
+			// filling with text occurs in sbList::updateVerses
 
 			Core->redraw();
+
+			// update collections
+			sbCollection::item * mark = Core->getCollection("history")->add(&key);
+			time_t now; time(&now); mark->visited = now; mark->visits++;
 		}
 		break;
 
@@ -465,7 +408,7 @@
 /*   sbList::render
 *   draw list
 */
-void sbList::render ( HDC hdc , bool showPlace )
+void sbList::render ( sbRenderContext hdc , bool showPlace )
 {
 	sbItem *oldItem , *workItem = itemCurrent;
 	sbRect workRect;
@@ -477,30 +420,30 @@
 	{
 		if (workItem == NULL) break;
 
-		if (screenHeight > rect->bottom()) break;
+		if (screenHeight > rect->bottom) break;
 
 		oldItem = workItem;
 
 		if (Core->getTheme()->ListSeparatorHeight > 0 && workItem->prev == NULL)
 		{
-			workRect = *rect;
-			workRect.bottom ( screenHeight );
-			workRect.top ( workRect.bottom()-Core->getTheme()->ListSeparatorHeight );
+			workRect = * rect;
+			workRect.bottom = screenHeight;
+			workRect.top    = workRect.bottom - Core->getTheme()->ListSeparatorHeight;
 			Core->getTheme()->drawElement(hdc, &workRect, sbTheme::ELEMENT::SEPARATOR);
 		}
 
-		workRect = *rect;
-		workRect.right (0);
+		workRect = * rect;
+		workRect.right = 0;
 
 		// horizontal parse
 		while (workItem != NULL)
 		{
 			sbTheme::ELEMENT::TYPE element = sbTheme::ELEMENT::ITEM;
 
-			workRect.top    ( screenHeight );
-			workRect.bottom ( workRect.top() + workItem->height );
-			workRect.left   ( workRect.right() );
-			workRect.right  ( workRect.left() + workItem->width );
+			workRect.top    = screenHeight;
+			workRect.bottom = workRect.top + workItem->height;
+			workRect.left   = workRect.right;
+			workRect.right  = workRect.left + workItem->width;
 
 			if ( workItem == itemHover )       element = sbTheme::ELEMENT::ITEM_HOVER;
 			else if (workItem == itemSelected) element = sbTheme::ELEMENT::ITEM_SELECTED;
@@ -512,24 +455,22 @@
 			{
 				if ( workItem->subtext.size() > 0 )
 				{
-					SIZE size;
+					sbPoint size = sbGetTextExtent(Core->getTheme()->styles[sbTheme::STYLE::STANZA].font,workItem->subtext.c_str(), workItem->subtext.size());
 
-					SelectObject(hdc, Core->getTheme()->styles[sbTheme::STYLE::STANZA].font);
-					SetTextColor(hdc, Core->getTheme()->ItemSubTextColor);
+					sbSelectFont(hdc, Core->getTheme()->styles[sbTheme::STYLE::STANZA].font);
+					sbSelectColor(hdc, Core->getTheme()->ItemSubTextColor);
 
-					GetTextExtentPoint32(hdc, workItem->subtext.c_str(), workItem->subtext.size(), &size);
-
-					ExtTextOut(hdc, workRect.left()+((Core->getTheme()->itemLeftMargin-size.cx)/2), workRect.top(), ETO_OPAQUE, NULL, workItem->subtext.c_str(), workItem->subtext.size(), 0);
+					sbDrawText(hdc, workRect.left+((Core->getTheme()->itemLeftMargin-size.x)/2), workRect.top, workItem->subtext.c_str(), workItem->subtext.size());
 				}
 
-				SetTextColor(hdc, Core->getTheme()->ItemTextColor);
+				sbSelectColor(hdc, Core->getTheme()->ItemTextColor);
 
 				int lx = 0;
-				int ly = workRect.top() + Core->getTheme()->itemTopMargin;
+				int ly = workRect.top + Core->getTheme()->itemTopMargin;
 
 				for (int i=0; i < workItem->lines.size(); i++)
 				{
-					int x = lx + Core->getTheme()->itemLeftMargin + workRect.left();
+					int x = lx + Core->getTheme()->itemLeftMargin + workRect.left;
 					int y = ly;
 
 					// possible BUG with center alignment and many text parts
@@ -543,27 +484,26 @@
 
 					if (workItem->lines[i].count == 0) continue;
 
-					if (y + Core->getTheme()->styles[workItem->style].size >= workRect.bottom())
+					if (y + Core->getTheme()->styles[workItem->style].size >= workRect.bottom)
 						break;
 
-					if (y < rect->top() - Core->getTheme()->styles[workItem->style].size)
+					if (y < rect->top - Core->getTheme()->styles[workItem->style].size)
 						continue;
 
-					SelectObject (hdc, Core->getTheme()->styles[workItem->lines[i].style].font);
-					ExtTextOut(hdc, x, y, ETO_OPAQUE, NULL, i == 0 ? workItem->text.c_str() : workItem->text.c_str() + workItem->lines[i].pos, workItem->lines[i].count, 0);
+					sbSelectFont (hdc, Core->getTheme()->styles[workItem->lines[i].style].font);
+					sbDrawText (hdc, x, y, i == 0 ? workItem->text.c_str() : workItem->text.c_str() + workItem->lines[i].pos, workItem->lines[i].count);
 				}
 			}
 			else
 			{
 				if (workItem->subtext.size() > 0)
 				{
-					SelectObject(hdc, Core->getTheme()->styles[sbTheme::STYLE::BUTTON].font);
-					SetTextColor(hdc, Core->getTheme()->ItemSubTextColor);
+					sbSelectFont(hdc, Core->getTheme()->styles[sbTheme::STYLE::BUTTON].font);
+					sbSelectColor(hdc, Core->getTheme()->ItemSubTextColor);
 
-					SIZE sz;
-					GetTextExtentPoint32(hdc, workItem->subtext.c_str(), workItem->subtext.size(), &sz);
+					sbPoint sz = sbGetTextExtent(Core->getTheme()->styles[sbTheme::STYLE::BUTTON].font, workItem->subtext.c_str(), workItem->subtext.size());
 
-					ExtTextOut(hdc, workRect.left()+((workRect.width()-sz.cx)/2), workRect.top()+((workRect.height()-sz.cy)/2), ETO_OPAQUE, NULL, workItem->subtext.c_str(), workItem->subtext.size(), 0);
+					sbDrawText (hdc, workRect.left+((workRect.width()-sz.x)/2), workRect.top+((workRect.height()-sz.y)/2), workItem->subtext.c_str(), workItem->subtext.size());
 				}
 				else if (workItem->type != sbItem::TYPE_SPACE)
 					sbAssert(true);
@@ -571,8 +511,8 @@
 
 			if (Core->getTheme()->ListSeparatorHeight > 0)
 			{
-				workRect.top (workRect.bottom());
-				workRect.bottom (workRect.top() + Core->getTheme()->ListSeparatorHeight);
+				workRect.top    = workRect.bottom;
+				workRect.bottom = workRect.top + Core->getTheme()->ListSeparatorHeight;
 				Core->getTheme()->drawElement(hdc, &workRect, sbTheme::ELEMENT::SEPARATOR);
 			}
 
@@ -613,7 +553,7 @@
 
 	if ( showPlace && module != NULL )
 	{
-		SIZE         ks;
+		sbPoint      ks;
 		const char * kt = key.getShortText();
 		int          kl = strlen ( kt );
 		TCHAR      * kw = new TCHAR [ kl + 1 ];
@@ -625,44 +565,40 @@
 		mbstowcs ( kw, kt, kl+1 );
 		mbstowcs ( mw, mt, ml+1 );
 
-		SelectObject ( hdc, Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font );
-		GetTextExtentPoint32 ( hdc, kw, kl, &ks );
+		sbSelectFont (hdc, Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font );
+		ks = sbGetTextExtent (Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font, kw, kl);
 
-		sbRect tempRect ((rect->right()-ks.cx)/2, (Core->getTheme()->size/6)-(ks.cy/2), (rect->right()-ks.cx)/2+ks.cx, (Core->getTheme()->size/6)-(ks.cy/2)+ks.cy);
+		sbRect tempRect ((rect->right-ks.x)/2, (Core->getTheme()->size/6)-(ks.y/2), (rect->right-ks.x)/2+ks.x, (Core->getTheme()->size/6)-(ks.y/2)+ks.y);
 
-		SelectObject ( hdc, Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font );
+		sbSelectFont ( hdc, Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font );
 
 		for (int width = 0; mc < ml; mc++)
 		{
-			SIZE sz;
+			sbPoint sz = sbGetTextExtent ( Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font, mw+mc, 1 );
 
-			GetTextExtentPoint32 ( hdc, mw+mc, 1, &sz );
+			if ( width + sz.x > ks.x ) break;
 
-			if ( width + sz.cx > ks.cx ) break;
-
-			width += sz.cx;
+			width += sz.x;
 		}
 		
 		workRect = tempRect;
 
-		workRect.bottom ( workRect.bottom() + Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].size );
+		workRect.bottom += Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].size + Core->getTheme()->BannerBorderSize;
+		workRect.top    -= Core->getTheme()->BannerBorderSize;
+		workRect.left   -= Core->getTheme()->BannerBorderSize;
+		workRect.right  += Core->getTheme()->BannerBorderSize;
 
-		workRect.bottom ( workRect.bottom() + Core->getTheme()->BannerBorderSize );
-		workRect.top    ( workRect.top()    - Core->getTheme()->BannerBorderSize );
-		workRect.left   ( workRect.left()   - Core->getTheme()->BannerBorderSize );
-		workRect.right  ( workRect.right()  + Core->getTheme()->BannerBorderSize );
-
 		Core->getTheme()->drawElement ( hdc, &workRect, sbTheme::ELEMENT::BANNER );
 
 		workRect = tempRect;
 
-		SetTextColor ( hdc, Core->getTheme()->ItemMenuTextColor );
+		sbSelectColor ( hdc, Core->getTheme()->ItemMenuTextColor );
 
-		SelectObject ( hdc, Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font );
-		ExtTextOut   ( hdc, workRect.left(), workRect.top(), ETO_OPAQUE, NULL, kw, kl, 0);
+		sbSelectFont ( hdc, Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font );
+		sbDrawText ( hdc, workRect.left, workRect.top, kw, kl );
 
-		SelectObject ( hdc, Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font );
-		ExtTextOut   ( hdc, workRect.left(), workRect.top() + Core->getTheme()->styles[sbTheme::STYLE::CAPTION].size , ETO_OPAQUE, NULL, mw, mc, 0);
+		sbSelectFont ( hdc, Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font );
+		sbDrawText ( hdc, workRect.left, workRect.top + Core->getTheme()->styles[sbTheme::STYLE::CAPTION].size , mw, mc );
 	}
 
 	if (displaceHeight >= 0)
@@ -973,11 +909,11 @@
 void sbList::updateVerses ( bool * abort )
 {
 	sbAssert ( module == NULL );
+	
+	if (itemCurrent == NULL) return;
 
 	while ( ! *abort )
 	{
-		if (itemCurrent == NULL) return;
-		
 		int      displace  = displaceHeight;
 		sbItem * item      = itemCurrent;
 		bool     atEnd     = false;
@@ -994,11 +930,11 @@
 				{
 					verseLast = verseLast->prev;
 					while (verseLast->type != sbItem::TYPE_VERSE) verseLast = verseLast->prev;
-					while (verseLast->next != NULL)               delete verseLast->next;
+					while (verseLast->next != NULL) delete verseLast->next;
 					countDeleted++;
 				}
 				if ( listEndConstructed ) listEndConstructed = false;
-				versesForward-=countDeleted;
+				versesForward -= countDeleted;
 			}
 			else
 			{
@@ -1006,7 +942,7 @@
 				{
 					verseFirst = verseFirst->next;
 					while (verseFirst->type != sbItem::TYPE_VERSE) verseFirst = verseFirst->next;
-					while (verseFirst->prev != NULL)               delete verseFirst->prev;
+					while (verseFirst->prev != NULL) delete verseFirst->prev;
 					countDeleted++;
 				}
 				if ( listStartConstructed ) listStartConstructed = false;
@@ -1021,11 +957,13 @@
 			item = item->next;
 		}
 		
-		sbItem * last      = item;
-		sbItem * first     = item;
+		sbItem * last  = item;
+		sbItem * first = item;
 
 		while ( ! *abort )
 		{
+			bool needBreak = false;
+
 			// process item text
 			if ( item->type == sbItem::TYPE_VERSE && item->text.size() == 0 )
 			{
@@ -1051,10 +989,12 @@
 					item->expanding = item->height;
 					item->height    = oldHeight;
 
-					return;
+					needBreak = true;
 				}
 			}
 
+			if (needBreak) break;
+
 			if (atEnd && last->next != NULL)
 			{
 				last      = last->next;
@@ -1067,8 +1007,7 @@
 				item      = first;
 				displace -= item->height;
 			}
-			else
-				return;
+			else break;
 
 			atEnd = ! atEnd;
 		}
@@ -1083,16 +1022,12 @@
 {
 	switch ( type )
 	{
+	case sbControl::TYPE_MENU_VERSE_ADD_DYNAMIC_BOOKMARK:
 	case sbControl::TYPE_MENU_VERSE_ADD_STATIC_BOOKMARK:
-		(Core->getBookmarks()->add( key )).dynamic = false;
+		Core->getCollection("bookmarks")->add(&key);
 		removeControl ( sbControl::TYPE_MENU_CURRENT );
 		break;
 
-	case sbControl::TYPE_MENU_VERSE_ADD_DYNAMIC_BOOKMARK:
-		(Core->getBookmarks()->add( key )).dynamic = true;
-		removeControl( sbControl::TYPE_MENU_CURRENT );
-		break;
-
 	case sbControl::TYPE_MENU_VERSE_START_EDITING:
 		{
 			sbItem* item = itemCurrent;
@@ -1174,7 +1109,7 @@
 	}
 }
 
-void sbList::onTimer (const int timer)
+void sbList::onTimer ( const int timer )
 {
 	switch (timer)
 	{
@@ -1281,9 +1216,9 @@
 					bool atEnd;
 
 					if (versesForward+versesBackward > Core->versesMax)
-					{ Sleep(25); break; } // need for memory reason
+					{ sbSleep(25); break; } // need for memory reason
 
-					if (versesForward+versesBackward > Core->versesOptimal*2) Sleep(5);
+					if (versesForward+versesBackward > Core->versesOptimal*2) sbSleep(5);
 
 					if (versesForward < 15 && !listEndConstructed)        atEnd = true;
 					else if (versesBackward < 5 && !listStartConstructed) atEnd = false;
@@ -1402,12 +1337,117 @@
  */
 void sbList::onActivate ( )
 {
-	Core->setSipState(itemEdit != NULL);
+	sbSetSip (itemEdit != NULL);
 
 	if (module != NULL)
 	{
 		Core->currentModule = module;
 	}
+
+	switch (type)
+	{
+	case TYPE_HISTORY:
+	case TYPE_BOOKMARKS:
+	case TYPE_READINGS:
+		{
+			sbCollection * collection = Core->getCollection ( type == TYPE_BOOKMARKS ? "bookmarks" : type == TYPE_HISTORY ? "history" : "readings" );
+
+			if ( collection != NULL )
+			{
+				sword::VerseKey workKey ( Core->defaultModule->getKey() );
+
+				clear();
+
+				for (int i=0; i < collection->size(); i++)
+				{
+					const char * verse = collection->get(i).verse;
+
+					workKey.setText ( verse );
+
+					TCHAR * text = new TCHAR [strlen(verse)+1];
+					mbstowcs (text, verse , strlen(verse)+1);
+
+					sbItem * item = new sbItem (sbItem::TYPE_BUTTON_BOOKMARK, text, rect->width(), workKey.Index());
+
+					if ( itemCurrent == NULL )
+					{
+						itemCurrent = item;
+					}
+					else
+					{
+						itemCurrent->attach (item,sbItem::PIN::NEXT);
+						itemCurrent = itemCurrent->next;
+					}
+
+				}
+
+				while (itemCurrent->prev != NULL) itemCurrent = itemCurrent->prev;
+			}
+
+		}
+	case TYPE_HOME:
+		{
+			clear();
+			
+			itemCurrent = new sbItem (sbItem::TYPE_HEADER, L"Welcome to\nSlideBible!", rect->width());
+
+			if (Core->defaultModule != NULL)
+			{
+				sword::VerseKey workKey ( Core->defaultModule->getKey() );
+
+				if ( parent != NULL && parent->hasModule() )
+				{
+					const char * place = workKey.getText();
+
+					const TCHAR * pre = L"Return to ";
+					
+					TCHAR * text = new TCHAR [_tcslen(pre)+strlen(place)+1];
+					memcpy ( text, pre, sizeof(TCHAR)*_tcslen(pre) );
+					mbstowcs ( text+_tcslen(pre), place , strlen( place ) + 1 );
+
+					itemCurrent->attach(new sbItem (sbItem::TYPE_BUTTON_BOOKMARK, text, rect->width(), workKey.Index()), sbItem::NEXT);
+					itemCurrent = itemCurrent->next;
+					itemCurrent->center = true;
+
+					delete [] text;
+				}
+				else if ((*Core->getOptions())["Bookmarks"]["LastPlace"] != "")
+				{
+					itemCurrent->attach(new sbItem (sbItem::TYPE_DESCRIPTION, L"Your Last Place :", rect->width()), sbItem::NEXT);
+					itemCurrent = itemCurrent->next;
+
+					const char * bookmark = (*Core->getOptions())["Bookmarks"]["LastPlace"];
+
+					workKey.setText ( bookmark );
+
+					TCHAR * text = new TCHAR [strlen( bookmark ) + 1];
+					mbstowcs ( text, bookmark , strlen( bookmark ) + 1 );
+
+					itemCurrent->attach(new sbItem (sbItem::TYPE_BUTTON_BOOKMARK, text, rect->width(), workKey.Index()), sbItem::NEXT);
+					itemCurrent = itemCurrent->next;
+					itemCurrent->center = true;
+
+					delete [] text;
+				}
+				else
+				{
+					workKey.setText ( "John 1:1" );
+					itemCurrent->attach(new sbItem (sbItem::TYPE_BUTTON_BOOKMARK, L"Read Bible ...", rect->width(), workKey.Index()), sbItem::NEXT);
+					itemCurrent = itemCurrent->next;
+					itemCurrent->center = true;
+				}
+			}
+			else
+			{
+				itemCurrent->attach(new sbItem (sbItem::TYPE_TEXT, L"No modules Found!\n\nPlease download any Bible module from www.crosswire.org and put \"mods.d\" and \"modules\" folders into application folder.", rect->width()), sbItem::NEXT);
+				itemCurrent = itemCurrent->next;
+			}
+
+			while ( itemCurrent->prev != NULL ) itemCurrent = itemCurrent->prev;
+		}
+	default:
+		;
+	}
 }
 
 /*  sbList::setEditMode
@@ -1419,7 +1459,7 @@
 	{
 		// finish edit , reallocate text
 		itemEdit = NULL;
-		Core->setSipState(false);
+		sbSetSip (false);
 	}
 	else if (item != NULL)
 	{
@@ -1427,7 +1467,7 @@
 		itemEdit = item;
 		itemEditCursor = itemEdit->text.size();
 
-		Core->setSipState(true);
+		sbSetSip (true);
 	}
 	else
 		sbAssert(true);
@@ -1458,3 +1498,13 @@
 	}	
 	return false;
 }
+
+bool sbList::onKey ( int key )
+{
+	if ( itemSelected == NULL )
+	{
+		itemSelected = itemCurrent;
+		return true;
+	}
+	return false;
+}

Modified: trunk/src/SlideBible/sbList.h
===================================================================
--- trunk/src/SlideBible/sbList.h	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbList.h	2010-01-07 20:55:10 UTC (rev 223)
@@ -20,11 +20,13 @@
 #include <swmgr.h>
 #include <swmodule.h>
 #include <versekey.h>
+
 #include "sbItem.h"
 #include "sbControl.h"
-#include "sbObject.h"
+#include "sbBase.h"
+#include "sbCollection.h"
 
-class sbList : public sbObject
+class sbList
 {
 public:
 	enum TYPE
@@ -41,6 +43,8 @@
 		TYPE_FILE_VIEW,               // html / txt / rtf / doc
 		TYPE_HOME,
 		TYPE_BOOKMARKS,
+		TYPE_READINGS,
+		TYPE_HISTORY,
 		TYPE_OPTIONS,
 		TYPE_SEARCH,                  // virtual
 		TYPE_SEARCH_OPTIONS,
@@ -59,6 +63,7 @@
 	void                      onTapped       ( int x, int y );
 
 	bool                      onChar         ( TCHAR character );
+	bool                      onKey          ( int key );
 	
 	void                      onTimer        ( const int timer );
 	void                      onActivate     ( );
@@ -67,7 +72,7 @@
 	// methods
 	void                      attach         ( sbList * list, sbList::TYPE pin );
 	bool                      scroll         ( float amount );
-	void                      render         ( HDC hdc , bool showPlace = false );
+	void                      render         ( sbRenderContext rc , bool showPlace = false );
 
 	int                       displaceHeight;
 	float                     displacePart;
@@ -86,7 +91,7 @@
 	sword::VerseKey*          getKey        ( );
 	void                      updateVerses  ( bool *abort );
 
-	const std::vector<sbControl*>* getControls () const { return &controls; }
+	const std::vector<sbControl*> * getControls () const { return &controls; }
 	
 private:
 	void                      setKey  ( sword::VerseKey verse ); // to cut
@@ -130,7 +135,9 @@
 	sword::SWModule          *module;
 	sword::VerseKey           key; // to cut
 
+	sbCollection::item       *attachedReading;
+
 	// Navigation related
 };
 
-#endif
\ No newline at end of file
+#endif

Modified: trunk/src/SlideBible/sbTheme.cpp
===================================================================
--- trunk/src/SlideBible/sbTheme.cpp	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbTheme.cpp	2010-01-07 20:55:10 UTC (rev 223)
@@ -20,33 +20,6 @@
 #pragma warning(disable : 4018)
 #pragma warning(disable : 4244)
 
-sbColor getColor (const char *color) // RRGGBBAA
-{
-	static const char hex[] = "0123456789ABCDEF";
-	const int len = strlen(color);
-
-	unsigned int result = 0;
-
-	for (int c=0; c<8; c++)
-	{
-		char byte = 0x0;
-
-		if (c >= len)
-		{
-			byte = 0xF;
-		}
-		else
-		{
-			for (; byte<=0xF; byte++)
-				if (color[c] == hex[byte]) break;
-		}
-
-		result |= byte << 4*(c%2==1?c-1:c+1);
-	}
-
-	return (sbColor)result;
-}
-
 void sbTheme::init()
 {
 	sword::SWConfig  themeConf(".\\theme.conf");
@@ -56,9 +29,9 @@
 	size = min(screenRect->height(), screenRect->width());
 
 	// colors
-	ItemTextColor        = getColor(themeConf["Color"].getWithDefault("ItemText", "14141400"));
-	ItemMenuTextColor    = getColor(themeConf["Color"].getWithDefault("MenuText", "E0E0E000"));
-	ItemSubTextColor     = getColor(themeConf["Color"].getWithDefault("ItemSubText", "AAAAAA00"));
+	ItemTextColor        = sbColor(themeConf["Color"].getWithDefault("ItemText", "14141400"));
+	ItemMenuTextColor    = sbColor(themeConf["Color"].getWithDefault("MenuText", "E0E0E000"));
+	ItemSubTextColor     = sbColor(themeConf["Color"].getWithDefault("ItemSubText", "AAAAAA00"));
 
 	itemTopMargin        = size/atof(themeConf["Size"].getWithDefault("itemTopMarginDiv",    "200.0"));
 	itemLeftMargin       = size/atof(themeConf["Size"].getWithDefault("itemLeftMarginDiv",   "10.0"));
@@ -152,34 +125,34 @@
 		if (!strcmp(type,"SOLID"))
 		{
 			elements[i].type      = ELEMENT::SOLID;
-			elements[i].color     = getColor(color);
+			elements[i].color     = sbColor(color);
 		}
 		else if (!strcmp(type,"VGRAD"))
 		{
 			elements[i].type      = ELEMENT::VGRAD;
-			elements[i].color     = getColor(color);
-			elements[i].color2    = getColor(color2);
+			elements[i].color     = sbColor(color);
+			elements[i].color2    = sbColor(color2);
 		}
 		else if (!strcmp(type,"HGRAD"))
 		{
 			elements[i].type      = ELEMENT::HGRAD;
-			elements[i].color     = getColor(color);
-			elements[i].color2    = getColor(color2);
+			elements[i].color     = sbColor(color);
+			elements[i].color2    = sbColor(color2);
 		}
 		else if (!strcmp(type,"HGRAD3"))
 		{
 			elements[i].type      = ELEMENT::HGRAD3;
-			elements[i].color     = getColor(color);
-			elements[i].color2    = getColor(color2);
-			elements[i].color3    = getColor(themeConf[name].getWithDefault("Color3", ""));
+			elements[i].color     = sbColor(color);
+			elements[i].color2    = sbColor(color2);
+			elements[i].color3    = sbColor(themeConf[name].getWithDefault("Color3", ""));
 			elements[i].pos1      = atoi(themeConf[name].getWithDefault("Separation1", "500"));
 		}
 		else if (!strcmp(type,"VGRAD3"))
 		{
 			elements[i].type      = ELEMENT::VGRAD3;
-			elements[i].color     = getColor(color);
-			elements[i].color2    = getColor(color2);
-			elements[i].color3    = getColor(themeConf[name].getWithDefault("Color3", ""));
+			elements[i].color     = sbColor(color);
+			elements[i].color2    = sbColor(color2);
+			elements[i].color3    = sbColor(themeConf[name].getWithDefault("Color3", ""));
 			elements[i].pos1      = atoi(themeConf[name].getWithDefault("Separation1", "500"));
 		}
 		else if (!strcmp(type,"HOLLOW"))
@@ -189,11 +162,9 @@
 		else if (!strcmp(type,"BMP"))
 		{
 			elements[i].type      = ELEMENT::BMP;
-			elements[i].color     = getColor(themeConf[name].getWithDefault("Color", "FFFFFF00"));
+			elements[i].color     = sbColor(themeConf[name].getWithDefault("Color", "FFFFFF00"));
 
-			elements[i].tiling    = atoi(themeConf[name].getWithDefault("Tiling",  "0"));
 			elements[i].stretch   = atoi(themeConf[name].getWithDefault("Stretch", "0"));
-			elements[i].rop       = atoi(themeConf[name].getWithDefault("Rop",     "13369376")); // by default SRCCOPY
 
 			const char* filename  = themeConf[name]["Bitmap"];
 
@@ -202,9 +173,9 @@
 				filename = adaptpath(filename);
 				TCHAR* t_filename = new TCHAR [strlen(filename)+1];
 				mbstowcs(t_filename, filename, strlen(filename)+1);
-				elements[i].bitmap = SHLoadImageFile(t_filename);
+				elements[i].bitmap = sbLoadBitmap(t_filename); //SHLoadImageFile(t_filename);
 
-				int error = GetLastError();
+				int error = sbGetLastError();
 				sbAssert(error != 0);
 
 				delete [] t_filename;
@@ -224,25 +195,25 @@
 		fontNameT[i] = fontName[i];
 
 	styles[STYLE::TEXT].size          = size/(atof(themeConf["Size"].getWithDefault("TextDiv", "12.0")));
-	styles[STYLE::TEXT].font          = buildFont(styles[STYLE::TEXT].size,         fontNameT, false, false);
+	styles[STYLE::TEXT].font          = sbMakeFont(styles[STYLE::TEXT].size,         fontNameT, false, false);
 	
 	styles[STYLE::TEXT_ITALIC].size   = styles[STYLE::TEXT].size;
-	styles[STYLE::TEXT_ITALIC].font   = buildFont(styles[STYLE::TEXT_ITALIC].size,  fontNameT, false, true);
+	styles[STYLE::TEXT_ITALIC].font   = sbMakeFont(styles[STYLE::TEXT_ITALIC].size,  fontNameT, false, true);
 	
 	styles[STYLE::BUTTON].size        = size/(atof(themeConf["Size"].getWithDefault("ButtonTextDiv", "10.0")));
-	styles[STYLE::BUTTON].font        = buildFont(styles[STYLE::BUTTON].size,       fontNameT, false, false);
+	styles[STYLE::BUTTON].font        = sbMakeFont(styles[STYLE::BUTTON].size,       fontNameT, false, false);
 	
 	styles[STYLE::BUTTON_SMALL].size  = size/(atof(themeConf["Size"].getWithDefault("ButtonSmallTextDiv", "15.0")));
-	styles[STYLE::BUTTON_SMALL].font  = buildFont(styles[STYLE::BUTTON_SMALL].size, fontNameT, false, false);
+	styles[STYLE::BUTTON_SMALL].font  = sbMakeFont(styles[STYLE::BUTTON_SMALL].size, fontNameT, false, false);
 	
 	styles[STYLE::STANZA].size        = size/(atof(themeConf["Size"].getWithDefault("SubTextDiv",     "16.0")));
-	styles[STYLE::STANZA].font        = buildFont(styles[STYLE::STANZA].size,       fontNameT, true, false);
+	styles[STYLE::STANZA].font        = sbMakeFont(styles[STYLE::STANZA].size,       fontNameT, true, false);
 	
 	styles[STYLE::DESCRIPTION].size   = size/(atof(themeConf["Size"].getWithDefault("DescriptionDiv", "14.0")));
-	styles[STYLE::DESCRIPTION].font   = buildFont(styles[STYLE::DESCRIPTION].size,  fontNameT, false, false);
+	styles[STYLE::DESCRIPTION].font   = sbMakeFont(styles[STYLE::DESCRIPTION].size,  fontNameT, false, false);
 	
 	styles[STYLE::CAPTION].size       = size/(atof(themeConf["Size"].getWithDefault("HeaderDiv",      "8.0")));
-	styles[STYLE::CAPTION].font       = buildFont(styles[STYLE::CAPTION].size,      fontNameT, true, false);
+	styles[STYLE::CAPTION].font       = sbMakeFont(styles[STYLE::CAPTION].size,      fontNameT, true, false);
 
 	// clear
 	delete [] fontNameT;
@@ -250,12 +221,11 @@
 
 sbTheme::~sbTheme()
 {
-	for (int i=0; i<STYLE::COUNT; i++)
-		DeleteObject(styles[i].font);
+	for (int i=0; i<STYLE::COUNT; i++) sbDeleteFont (styles[i].font);
 
 	for (int i=0; i<ELEMENT::COUNT; i++)
 		if (elements[i].type == ELEMENT::BMP && elements[i].bitmap != NULL)
-			DeleteObject(elements[i].bitmap);
+			sbDeleteBitmap (elements[i].bitmap);
 }
 
 /*
@@ -263,10 +233,10 @@
  *  outside methods should only place element types on the screen
  *  in future real paint will be in something like flushScreen()
  */
-void sbTheme::drawElement (HDC hdc, const sbRect* rect, sbTheme::ELEMENT::TYPE type, const int animFrame) const
+void sbTheme::drawElement (sbRenderContext rc, const sbRect * rect, sbTheme::ELEMENT::TYPE type, const int animFrame) const
 {
 	bool vertical = true;
-	sbColor nc1,nc2,nc3,nc4;
+	sbColor nc1,nc2,nc3;
 	
 	switch (elements[type].type)
 	{
@@ -274,16 +244,16 @@
 		{
 			if (Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->fade)
 			{
-				nc1 = RGB(GetRValue(elements[type].color)*2/3,GetGValue(elements[type].color)*2/3,GetBValue(elements[type].color)*2/3);
+				nc1.red   = elements[type].color.red*2/3;
+				nc1.green = elements[type].color.green*2/3;
+				nc1.blue  = elements[type].color.blue*2/3;
 			}
 			else
 			{
 				nc1 = elements[type].color;
 			}
-			checkTransparentColor(nc1,rect->left(),rect->top());
-			HBRUSH brush = CreateSolidBrush(nc1);
-			FillRect(hdc, rect, brush);
-			DeleteObject(brush);
+			checkTransparentColor(nc1,rect->left,rect->top);
+			sbFillRect (rc,rect,nc1);
 		}
 		break;
 
@@ -295,17 +265,17 @@
 		{
 			if (Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->fade)
 			{
-				nc1 = RGB(GetRValue(elements[type].color)*2/3, GetGValue(elements[type].color)*2/3, GetBValue(elements[type].color)*2/3);
-				nc2 = RGB(GetRValue(elements[type].color2)*2/3,GetGValue(elements[type].color2)*2/3,GetBValue(elements[type].color2)*2/3);
+				nc1 = sbColor(elements[type].color.red*2/3,  elements[type].color.green*2/3,  elements[type].color.blue*2/3);
+				nc2 = sbColor(elements[type].color2.red*2/3, elements[type].color2.green*2/3, elements[type].color2.blue*2/3);
 			}
 			else
 			{
 				nc1 = elements[type].color;
 				nc2 = elements[type].color2;
 			}
-			checkTransparentColor(nc1,rect->left(),rect->top());
-			checkTransparentColor(nc2,rect->right(),rect->bottom());
-			DrawGradient(hdc, rect, nc1, nc2, vertical);
+			checkTransparentColor(nc1,rect->left,rect->top);
+			checkTransparentColor(nc2,rect->right,rect->bottom);
+			sbDrawGradient(rc, rect, nc1, nc2, vertical);
 		}
 		break;
 
@@ -317,9 +287,9 @@
 		{
 			if (Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->fade)
 			{
-				nc1 = RGB(GetRValue(elements[type].color)*2/3, GetGValue(elements[type].color)*2/3, GetBValue(elements[type].color)*2/3);
-				nc2 = RGB(GetRValue(elements[type].color2)*2/3,GetGValue(elements[type].color2)*2/3,GetBValue(elements[type].color2)*2/3);
-				nc3 = RGB(GetRValue(elements[type].color3)*2/3,GetGValue(elements[type].color3)*2/3,GetBValue(elements[type].color3)*2/3);
+				nc1 = sbColor(elements[type].color.red*2/3,  elements[type].color.green*2/3,  elements[type].color.blue*2/3);
+				nc2 = sbColor(elements[type].color2.red*2/3, elements[type].color2.green*2/3, elements[type].color2.blue*2/3);
+				nc3 = sbColor(elements[type].color3.red*2/3, elements[type].color3.green*2/3, elements[type].color3.blue*2/3);
 			}
 			else
 			{
@@ -332,37 +302,31 @@
 
 			if (elements[type].pos1 != 0)
 			{
+				temp = * rect;
+
 				if (vertical)
-				{
-					temp        = *rect;
-					temp.bottom ((temp.height())*elements[type].pos1/1000+temp.top());
-				}
+					temp.bottom = temp.height()*elements[type].pos1/1000+temp.top;
 				else
-				{
-					temp        = *rect;
-					temp.right  ((temp.width())*elements[type].pos1/1000+temp.left());
-				}
-				checkTransparentColor(nc1,temp.left(),temp.top());
-				checkTransparentColor(nc2,temp.right(),temp.bottom());
+					temp.right  = temp.width()*elements[type].pos1/1000+temp.left;
 
-				DrawGradient(hdc, &temp, nc1, nc2, vertical);
+				checkTransparentColor(nc1,temp.left,temp.top);
+				checkTransparentColor(nc2,temp.right,temp.bottom);
+
+				sbDrawGradient(rc, &temp, nc1, nc2, vertical);
 			}
 			if (elements[type].pos1 != 1000)
 			{
+				temp = * rect;
+
 				if (vertical)
-				{
-					temp        = *rect;
-					temp.top    ((temp.height())*elements[type].pos1/1000+temp.top());
-				}
+					temp.top  = temp.height()*elements[type].pos1/1000+temp.top;
 				else
-				{
-					temp        = *rect;
-					temp.left   ((temp.width())*elements[type].pos1/1000+temp.left());
-				}
-				checkTransparentColor(nc2,temp.left(),temp.top());
-				checkTransparentColor(nc3,temp.right(),temp.bottom());
+					temp.left = temp.width()*elements[type].pos1/1000+temp.left;
+				
+				checkTransparentColor(nc2,temp.left,temp.top);
+				checkTransparentColor(nc3,temp.right,temp.bottom);
 
-				DrawGradient(hdc, &temp, nc2, nc3, vertical);
+				sbDrawGradient(rc, &temp, nc2, nc3, vertical);
 			}
 		}
 		break;
@@ -372,25 +336,7 @@
 
 	case sbTheme::ELEMENT::BMP:
 		{
-			HDC     thdc = CreateCompatibleDC(hdc);
-			HBITMAP obm  = (HBITMAP)SelectObject(thdc, elements[type].bitmap);
-			BITMAP  bm;
-
-			GetObject(elements[type].bitmap, sizeof(bm), &bm);
-
-			if (elements[type].stretch)
-			{
-				StretchBlt(hdc, rect->left(), rect->top(), rect->width(), rect->height(), thdc, 0, 0, bm.bmWidth, bm.bmHeight, elements[type].rop);
-			}
-			else
-			{
-				if (elements[type].tiling)
-					sbAssert(true);
-				else
-					BitBlt(hdc, rect->left(), rect->top(), min(rect->width(),bm.bmWidth), min(rect->height(),bm.bmHeight), thdc, 0, 0, elements[type].rop);
-			}
-			SelectObject(thdc, obm);
-			DeleteDC(thdc);
+			sbDrawBitmap (rc,rect,elements[type].bitmap,elements[type].stretch);
 		}
 		break;
 
@@ -399,28 +345,25 @@
 	}
 }
 
-void sbTheme::checkTransparentColor (sbColor& color, int x, int y) const
+void sbTheme::checkTransparentColor ( sbColor & color , int x , int y ) const
 {
-	const unsigned char alpha = (BYTE)((color) >> 24);
-
-	if (alpha != 0)
+	if ( color.alpha != 0 ) // transparent
 	{
-		// transparent
 		if (elements[sbTheme::ELEMENT::BACKGROUND].type == sbTheme::ELEMENT::SOLID)
 		{
 			color = elements[sbTheme::ELEMENT::BACKGROUND].color;
 		}
 		else if (elements[sbTheme::ELEMENT::BACKGROUND].type == sbTheme::ELEMENT::VGRAD)
 		{
-			unsigned char r1 = GetRValue(elements[sbTheme::ELEMENT::BACKGROUND].color);
-			unsigned char g1 = GetGValue(elements[sbTheme::ELEMENT::BACKGROUND].color);
-			unsigned char b1 = GetBValue(elements[sbTheme::ELEMENT::BACKGROUND].color);
-			unsigned char r2 = GetRValue(elements[sbTheme::ELEMENT::BACKGROUND].color2);
-			unsigned char g2 = GetGValue(elements[sbTheme::ELEMENT::BACKGROUND].color2);
-			unsigned char b2 = GetBValue(elements[sbTheme::ELEMENT::BACKGROUND].color2);
-			const sbRect& rect = Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->rect;
-			int value = min(1000,((y-rect.top())*1000)/(rect.height()));
-			color = RGB(r1+((r2-r1)*value/1000),g1+((g2-g1)*value/1000),b1+((b2-b1)*value/1000));
+			unsigned char r1 = elements[sbTheme::ELEMENT::BACKGROUND].color.red;
+			unsigned char g1 = elements[sbTheme::ELEMENT::BACKGROUND].color.green;
+			unsigned char b1 = elements[sbTheme::ELEMENT::BACKGROUND].color.blue;
+			unsigned char r2 = elements[sbTheme::ELEMENT::BACKGROUND].color2.red;
+			unsigned char g2 = elements[sbTheme::ELEMENT::BACKGROUND].color2.green;
+			unsigned char b2 = elements[sbTheme::ELEMENT::BACKGROUND].color2.blue;
+			const sbRect rect = Core->getSurface(sbCore::SURFACE::TYPE_WHOLE)->rect;
+			int value = min(1000,((y-rect.top)*1000)/rect.height());
+			color = sbColor (r1+((r2-r1)*value/1000),g1+((g2-g1)*value/1000),b1+((b2-b1)*value/1000));
 		}
 		else if (elements[sbTheme::ELEMENT::BACKGROUND].type == sbTheme::ELEMENT::BMP)
 		{
@@ -430,56 +373,3 @@
 			sbAssert(true);
 	}
 }
-
-HFONT sbTheme::buildFont(int size, const TCHAR *font, BOOL bold, BOOL italic)
-{
-	LOGFONT lf;
-	memset(&lf, 0, sizeof(LOGFONT));
-
-	lf.lfHeight = size;
-	lf.lfWidth = 0;
-	lf.lfEscapement = 0;
-	lf.lfOrientation = 0;
-
-	if (bold)
-		lf.lfWeight = 600;
-	else
-		lf.lfWeight = 500;
-
-	lf.lfItalic = italic;
-	lf.lfUnderline = FALSE;
-	lf.lfStrikeOut = FALSE;
-	lf.lfCharSet = DEFAULT_CHARSET;
-	lf.lfOutPrecision = OUT_RASTER_PRECIS;
-	lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
-	lf.lfQuality = CLEARTYPE_QUALITY;
-	lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
-
-	/*	Wingdings
-		Tahoma
-		Courier New	*/
-	_tcsncpy (lf.lfFaceName, font, LF_FACESIZE);
-
-	return CreateFontIndirect(&lf);
-}
-
-void DrawGradient (HDC hdc, const RECT* iRect, COLORREF StartRGB, COLORREF EndRGB, bool vertical)
-{
-	TRIVERTEX        vert[2];
-	GRADIENT_RECT    gRect;
-	vert [0] .x      = iRect->left;
-	vert [0] .y      = iRect->top;
-	vert [0] .Red    = GetRValue(StartRGB) << 8;
-	vert [0] .Green  = GetGValue(StartRGB) << 8;
-	vert [0] .Blue   = GetBValue(StartRGB) << 8;
-	vert [0] .Alpha  = 0x0000;
-	vert [1] .x      = iRect->right;
-	vert [1] .y      = iRect->bottom; 
-	vert [1] .Red    = GetRValue(EndRGB) << 8;
-	vert [1] .Green  = GetGValue(EndRGB) << 8;
-	vert [1] .Blue   = GetBValue(EndRGB) << 8;
-	vert [1] .Alpha  = 0x0000;
-	gRect.UpperLeft  = 0;
-	gRect.LowerRight = 1;
-	GradientFill(hdc, vert, 2, &gRect, 1, vertical ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H);
-}
\ No newline at end of file

Modified: trunk/src/SlideBible/sbTheme.h
===================================================================
--- trunk/src/SlideBible/sbTheme.h	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/sbTheme.h	2010-01-07 20:55:10 UTC (rev 223)
@@ -16,7 +16,7 @@
 #ifndef SBTHEME_H
 #define SBTHEME_H
 
-#include "sbCross.h"
+#include "sbBase.h"
 
 class sbTheme
 {
@@ -28,8 +28,7 @@
 	void                  init();
 
 private:
-	HFONT                 buildFont(int size, const TCHAR *font, BOOL bold, BOOL italic);
-	void                  checkTransparentColor (sbColor& color, int x, int y) const;
+	void                  checkTransparentColor (sbColor & color, int x, int y) const;
 
 public:
 	sbColor               ItemTextColor;
@@ -50,7 +49,7 @@
 			COUNT
 		};
 
-		HFONT             font;
+		sbFont            font;
 		unsigned short    size;
 	};
 
@@ -89,14 +88,13 @@
 		sbColor           color4;
 		short             pos1;                      // gradients vertical/horizontal sparation in range 0-1000
 		short             pos2;
-		HBITMAP           bitmap;
-		char              tiling:1, stretch:1, centered:1, transparency:1;
-		DWORD             rop;
+		sbBitmap          bitmap;
+		char              stretch:1, centered:1, transparency:1;
 	};
 
 	ELEMENT               elements [ELEMENT::COUNT];
 
-	void                  drawElement (HDC hdc, const sbRect *rect, sbTheme::ELEMENT::TYPE type, const int animFrame=0) const;
+	void                  drawElement ( sbRenderContext rc, const sbRect * rect, sbTheme::ELEMENT::TYPE type, const int animFrame = 0 ) const;
 
 	int                   ListSeparatorHeight;
 	int                   BannerBorderSize;
@@ -110,6 +108,4 @@
 	int                   itemRightMargin;
 };
 
-void DrawGradient (HDC tdc, const RECT* iRect, COLORREF StartRGB, COLORREF EndRGB, bool vertical=true);
-
 #endif

Added: trunk/src/SlideBible/time_ce/time_ce.cpp
===================================================================
--- trunk/src/SlideBible/time_ce/time_ce.cpp	                        (rev 0)
+++ trunk/src/SlideBible/time_ce/time_ce.cpp	2010-01-07 20:55:10 UTC (rev 223)
@@ -0,0 +1,958 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Legalese:
+// This file is part of the OpenNETCF time.h port for Windows CE.
+// You are free to use, modify or distribute this code or any
+// derivative work that you create.  This code is provided WITHOUT
+// WARRANTY and OpenNETCF does NOT claim in any way that this code 
+// is fit for any specific or general use and holds NO RESPONSIBILITY
+// for consequences of using any of it.  It is simply provided as-is.
+//
+// About:
+// This is part of a free and open project to provide a simply way to
+// port that uses time.h functions to Windows CE.  For the latest
+// code, or to submit fixes, feature additions, etc. visit:
+//
+// http://www.opennetcf.com
+//
+// Version 0.01 - March 22, 2007
+//                Initial Release
+//
+// Version 0.02 - July 5, 2007
+//                Bug fixes.  UTC offset not properly accounted for unless SetTz had been previously called.
+//                            UTC offset used for functions like localtime_ce using old, rather than current data
+//
+///////////////////////////////////////////////////////////////////////////////
+// Many but not all of the functions were created from the following source:
+//
+// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 
+// 1. Redistributions of source code must retain the above copyright 
+//    notice, this list of conditions and the following disclaimer.  
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.  
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission. 
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+// SUCH DAMAGE.
+/////////////////////////////////////////////////////////////////////////////// 
+
+#include "time_ce.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros
+///////////////////////////////////////////////////////////////////////////////
+#define TIME_FAILURE	0xFFFFFFFF
+#define ASC_BUFF_SIZE	26  // Ascii buffer size is 26 bytes, (24 chars and CR+LF)
+#define SEC_IN_HOUR     3600L
+#define SECS_IN_MIN		60L
+#define DAYSPERWEEK		7
+#define YEAR0           1900
+#define EPOCH_YR        1970
+#define SECS_DAY        (24L * 60L * 60L)
+#define LEAPYEAR(year)  (!((year) % 4) && (((year) % 100) || !((year) % 400)))
+#define TIME_MAX        2147483647L
+
+///////////////////////////////////////////////////////////////////////////////
+// Local Variables
+///////////////////////////////////////////////////////////////////////////////
+
+// Number of seconds between local time and UTC time, includes DST bias
+//
+LONG _localtime;
+
+// Is the local time in daylight savings time
+//
+DWORD _isdst;
+
+// Bias for daylight savings time
+//
+int _dstBias;
+
+// Contains the time zone string
+//
+char tz_name[2][32];
+
+// Contains the 1/1/1970 reference date/time
+//
+const SYSTEMTIME st1970 = {1970, 1,	4, 1, 0, 0, 0, 0};
+
+// Contains the number of days per month for 
+// non leap and leap years
+//
+const int _ytab[2][12] = 
+{
+  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+
+// Contains the days of the week abreviation
+//
+static char *aday[] = {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+// Contains the days of the week full name
+//
+static char *day[] = {
+    "Sunday", "Monday", "Tuesday", "Wednesday",
+    "Thursday", "Friday", "Saturday"
+};
+
+// Contains the months of the year abreviation
+//
+static char *amonth[] = {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+// Contains the months of the year full name
+//
+static char *month[] = {
+    "January", "February", "March", "April", "May", "June",
+    "July", "August", "September", "October", "November", "December"
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward declaration of internal functions
+///////////////////////////////////////////////////////////////////////////////
+
+// Convert system time into seconds since 1970
+//
+LONGLONG SystemTimeToSecondsSince1970(SYSTEMTIME * st);
+
+// Convert seconds since 1970 into a system time
+//
+void SecondsSince1970ToSystemTime(const time_t_ce * timer, SYSTEMTIME * st, 
+								  BOOLEAN local);
+
+// Initialize the time zone information needed for the time_ce methods
+//
+void SetTz(SYSTEMTIME *_st);
+
+// Copy system time structure to tm structure
+//
+void SystemTimeToTm(SYSTEMTIME *st, struct tm * tmbuffer);
+void TmToSystemTime(struct tm * tmbuffer, SYSTEMTIME *st);
+
+// Get Julian Days from the begining of the year
+//
+DWORD JulianDays(SYSTEMTIME * st);
+
+// Method parses and formats strings
+//
+static void strfmt(char *str, const char *fmt, ...);
+
+// Reentrant version of gmttime
+//
+struct tm *gmtime_r_ce(const time_t_ce *timer, struct tm *tmbuf, BOOLEAN local);
+
+// Reentrant version of localtime
+//
+struct tm *localtime_r_ce(const time_t_ce *timer, struct tm *tmbuf);
+
+///////////////////////////////////////////////////////////////////////////////
+// Methods - The meat
+///////////////////////////////////////////////////////////////////////////////
+
+// Convert tm to a string in the format "Www Mmm dd hh:mm:ss yyyy", 
+// where Www is the weekday, Mmm the month in letters, dd the day 
+// of the month, hh:mm:ss the time, and yyyy the year. The string 
+// is followed by a newline and a terminating null character, 
+// conforming a total of 26 characters. 
+//
+char *asctime_ce(const struct tm* tmptr)
+{
+	static char ascbuf[ASC_BUFF_SIZE];
+    strftime_ce(ascbuf, ASC_BUFF_SIZE, "%c\n", tmptr);
+    return ascbuf;
+}
+
+// Return number of clock ticks since process start.
+// NOTE: This differs from standard clock since GetTickCount is the
+//       number of milliseconds since system startup not process start.
+//       This will also rollover after 49.7 days of continuous system
+//       runtime.
+//
+clock_t_ce clock_ce(void)
+{
+	return GetTickCount();
+}
+
+// Convert time_t value to string in the same format as asctime.
+//
+char* ctime_ce(const time_t_ce* timer)
+{
+	return asctime_ce(localtime_ce(timer));
+}
+
+// Returns the difference in seconds between the two times.
+//
+double difftime_ce(time_t_ce timer2, time_t_ce timer1)
+{
+	time_t_ce timediff;
+
+	if (timer2 < timer1)
+	{
+		timediff = (timer1 - timer2);
+	}
+	else
+	{
+		timediff = (timer2 - timer1);
+	}
+	return (double)timediff;
+}
+
+// Reentrant version of gmttime_ce
+//
+struct tm *gmtime_r_ce(const time_t_ce *timer, struct tm *tmbuf, BOOLEAN local)
+{
+  SYSTEMTIME	st;
+
+  SecondsSince1970ToSystemTime(timer, &st, local);
+  SetTz(&st);
+  if(_isdst) {
+    SecondsSince1970ToSystemTime(timer, &st, local);
+  }
+
+  // copy SYSTEMTIME data to tm structure
+  //
+  SystemTimeToTm(&st, tmbuf);
+
+  return tmbuf;
+
+}
+
+// Reentrant version of localtime_ce
+//
+struct tm *localtime_r_ce(const time_t_ce *timer, struct tm *tmbuf)
+{
+	return gmtime_r_ce(timer, tmbuf, TRUE);
+}
+
+// Convert a time_t value to a tm structure as UTC time. 
+//
+struct tm *gmtime_ce(const time_t_ce *timer)
+{
+	return gmtime_r_ce(timer, &tmbuf, FALSE);
+}
+
+// Convert a time_t value to a tm structure as local time. 
+//
+struct tm *localtime_ce(const time_t_ce *timer)
+{
+	return localtime_r_ce(timer, &tmbuf);
+}
+
+// time_t represents seconds since midnight January 1, 1970 UTC 
+// (coordinated universal time) in 32-bits Win32 FILETIME structure is 64-bit,
+// which represents the number of 100-nanosecond (hns) intervals since 
+// January 1, 1601 UTC (coordinate universal time) the time difference
+// between midnight January 1, 1970 and midnight January 1, 1601 is 11644473600 seconds
+//
+time_t_ce mktime_ce(struct tm *tptr)
+{
+  SYSTEMTIME st;
+  TmToSystemTime(tptr, &st);
+  SetTz(&st);
+
+  DWORD day = 0;
+	DWORD year = 0;
+	DWORD seconds = 0;
+	DWORD overflow;
+	DWORD tm_year;
+	DWORD yday, month;
+
+	// see if seconds are < 0
+	while(tptr->tm_sec < 0)
+	{
+		// steal 60 seconds from the minutes
+		tptr->tm_sec += 60;
+		tptr->tm_min--;
+	}
+	// roll any seconds > 60 into the minutes
+	tptr->tm_min += tptr->tm_sec / 60;
+	// then crop them off
+	tptr->tm_sec %= 60;
+
+	// see if minutes are < 0
+	while(tptr->tm_min < 0)
+	{
+		// steal 60 minutes from the hours
+		tptr->tm_min += 60;
+		tptr->tm_hour--;
+	}
+	// roll any minutes > 60 into the hours
+	tptr->tm_hour += tptr->tm_min / 60;
+	// then crop them off
+	tptr->tm_min %= 60;
+
+	// see if hours are < 0
+	while(tptr->tm_hour < 0)
+	{
+		// steal 24 hours from the days
+		tptr->tm_hour += 24;
+		day--;
+	}
+	// keep any "excess" days (tm doesn't have a convenient place for this)
+	day += tptr->tm_hour / 24;
+	// crop
+	tptr->tm_hour %= 24;
+
+	// roll any months > 12 into the years
+	tptr->tm_year += tptr->tm_mon / 12;
+	// then crop the off
+	tptr->tm_mon %= 12;
+
+	// see if months are < 0
+	if (tptr->tm_mon < 0) 
+	{
+		// steal 12 months from the years
+		tptr->tm_mon += 12;
+		tptr->tm_year--;
+	}
+
+	// add number of days into the month to total day
+	day += (tptr->tm_mday - 1);
+
+	// if days are < 0 then calculate the number of days
+	// checking to see if the month is a leap year month
+	while (day < 0) 
+	{
+		// If months are < 0 then steal 12 months from number of years
+		// for the day calculation
+		if(--tptr->tm_mon < 0) 
+		{
+			tptr->tm_year--;
+			tptr->tm_mon = 11;
+		}
+		day += _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon];
+	}
+	// if day is greater then the number of days in the month
+	// subtract the number of days in the month and adjust the 
+	// month
+	while (day >= _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon]) 
+	{
+		day -= _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon];
+		if (++(tptr->tm_mon) == 12) 
+		{
+			tptr->tm_mon = 0;
+			tptr->tm_year++;
+		}
+	}
+	tptr->tm_mday = day + 1;
+	year = EPOCH_YR;
+
+	// if year is less then 1970 then return error
+	if (tptr->tm_year < year - YEAR0) return (time_t) -1;
+
+	seconds = 0;
+	day = 0;                      // Means days since day 0 now
+	overflow = 0;
+
+	// Assume that when day becomes negative, there will certainly
+	// be overflow on seconds.
+	// The check for overflow needs not to be done for leapyears
+	// divisible by 400.
+	// The code only works when year (1970) is not a leapyear.
+	tm_year = tptr->tm_year + YEAR0;
+
+	// make sure we are not past the max year for 32-bit number
+	if (TIME_MAX / 365 < tm_year - year) overflow++;
+
+	// calculate number of days since EPOCH
+	day = (tm_year - year) * 365;
+
+	if (TIME_MAX - day < (tm_year - year) / 4 + 1) overflow++;
+
+	day += (tm_year - year) / 4 + ((tm_year % 4) && tm_year % 4 < year % 4);
+	day -= (tm_year - year) / 100 + ((tm_year % 100) && tm_year % 100 < year % 100);
+	day += (tm_year - year) / 400 + ((tm_year % 400) && tm_year % 400 < year % 400);
+
+	// setup for calculation of the yday or Julian day since Jan 1
+	yday = month = 0;
+
+	// add up the number of days for the preceding months
+	while (month < tptr->tm_mon)
+	{
+		yday += _ytab[LEAPYEAR(tm_year)][month];
+		month++;
+	}
+	// add the number of days in the current month
+	yday += (tptr->tm_mday - 1);
+
+	// make sure the didn't overflow
+	if (day + yday < 0) overflow++;
+
+	day += yday;
+
+	// set the year day in the structure
+	tptr->tm_yday = yday;
+
+	// calculate the weekday
+	tptr->tm_wday = (day + 4) % 7;               // Day 0 was thursday (4)
+
+	// start the seconds calculation by totaling the hours, min, seconds
+	seconds = ((tptr->tm_hour * 60L) + tptr->tm_min) * 60L + tptr->tm_sec;
+
+	// make sure we are not going to overflow
+	if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
+
+	// calculate the number of seconds for the number of days
+	seconds += day * SECS_DAY;
+
+	// Now adjust according to timezone and daylight saving time
+	if (((_localtime > 0) && (TIME_MAX - _localtime < seconds))
+	  || ((_localtime < 0) && (seconds < -_localtime)))
+		  overflow++;
+
+	// Adjust for local time zone
+  seconds += _localtime;
+
+	// return error if we are going to blow the max values
+	if (overflow) return (time_t_ce) -1;
+
+	if ((time_t_ce) seconds != seconds) return (time_t_ce) -1;
+
+	// return the number of seconds since EPOCH
+	return (time_t_ce) seconds;
+}
+
+
+// Get the current system time and convert to seconds since
+// 1/1/1970.  Store the seconds value in tloc if not a NULL pointer then
+// return the seconds value.
+//
+time_t_ce time_ce(time_t_ce *tloc)
+{
+	SYSTEMTIME	st;
+	LONGLONG	secs = 0;
+	
+	// Get current system time
+	GetSystemTime(&st);
+
+  // Set time zone information
+	//
+	SetTz(&st);
+
+	// convert system time to number of seconds since 1970
+	//
+	secs = SystemTimeToSecondsSince1970(&st);
+
+	// check for failure
+	//
+	if(secs == TIME_FAILURE)
+	{
+		return TIME_FAILURE;
+	}
+
+	// If tloc is not NULL, the return value is also stored in the location to which tloc points
+	//
+	if(tloc != NULL)
+	{
+		if(IsBadWritePtr(tloc, sizeof(time_t_ce)))
+		{
+			return TIME_FAILURE;
+		}
+		memcpy(tloc, &secs, sizeof(time_t_ce));
+	}
+	
+	return secs;
+}
+
+// The strftime function is a modified version created by the following:
+// written 6 september 1989 by jim nutt
+// released into the public domain by jim nutt
+//
+// modified 21-Oct-89 by Rob Duff
+//
+//
+// size_t strftime(char *str,
+//                 size_t maxs,
+//                 const char *fmt,
+//                 const struct tm *t)
+// 
+//      this functions acts much like a sprintf for time/date output.
+//      given a pointer to an output buffer, a format string and a
+//      time, it copies the time to the output buffer formatted in
+//      accordance with the format string.  the parameters are used
+//      as follows:
+// 
+//          str is a pointer to the output buffer, there should
+//          be at least maxs characters available at the address
+//          pointed to by str.
+// 
+//          maxs is the maximum number of characters to be copied
+//          into the output buffer, included the '\0' terminator
+// 
+//          fmt is the format string.  a percent sign (%) is used
+//          to indicate that the following character is a special
+//          format character.  the following are valid format
+//          characters:
+// 
+//              %A      full weekday name (Monday)
+//              %a      abbreviated weekday name (Mon)
+//              %B      full month name (January)
+//              %b      abbreviated month name (Jan)
+//              %c      standard date and time representation
+//              %d      day-of-month (01-31)
+//              %H      hour (24 hour clock) (00-23)
+//              %I      hour (12 hour clock) (01-12)
+//              %j      day-of-year (001-366)
+//              %M      minute (00-59)
+//              %m      month (01-12)
+//              %p      local equivalent of AM or PM
+//              %S      second (00-59)
+//              %U      week-of-year, first day sunday (00-53)
+//              %W      week-of-year, first day monday (00-53)
+//              %w      weekday (0-6, sunday is 0)
+//              %X      standard time representation
+//              %x      standard date representation
+//              %Y      year with century
+//              %y      year without century (00-99)
+//              %Z      timezone name
+//              %%      percent sign
+//
+//      the standard date string is equivalent to:
+//
+//          %a %b %d %Y
+//
+//      the standard time string is equivalent to:
+//
+//          %H:%M:%S
+//
+//      the standard date and time string is equivalent to:
+//
+//          %a %b %d %H:%M:%S %Y
+//
+//      strftime returns the number of characters placed in the
+//      buffer, not including the terminating \0, or zero if more
+//      than maxs characters were produced.
+//
+size_t strftime_ce(char *s, size_t maxs, const char *f, const struct tm *t)
+{
+	int			w;
+	char		*p, *q, *r;
+	static char	buf[26];
+
+	p = s;
+	q = s + maxs - 1;
+	while ((*f != '\0'))
+	{
+		if (*f++ == '%')
+		{
+			r = buf;
+			switch (*f++)
+			{
+				case '%' :
+					r = "%";
+					break;
+
+				case 'a' :
+					r = aday[t->tm_wday];
+					break;
+
+				case 'A' :
+					r = day[t->tm_wday];
+					break;
+
+				case 'b' :
+					r = amonth[t->tm_mon];
+					break;
+
+				case 'B' :
+					r = month[t->tm_mon];
+					break;
+
+				case 'c' :
+					strfmt(r, "%0 %0 %2 %2:%2:%2 %4",
+						  aday[t->tm_wday], amonth[t->tm_mon],
+						  t->tm_mday,t->tm_hour, t->tm_min,
+						  t->tm_sec, t->tm_year+1900);
+					break;
+
+				case 'd' :
+					strfmt(r,"%2",t->tm_mday);
+					break;
+
+				case 'H' :
+					strfmt(r,"%2",t->tm_hour);
+					break;
+
+				case 'I' :
+					strfmt(r,"%2",(t->tm_hour%12)?t->tm_hour%12:12);
+					break;
+
+				case 'j' :
+					strfmt(r,"%3",t->tm_yday+1);
+					break;
+
+				case 'm' :
+					strfmt(r,"%2",t->tm_mon+1);
+					break;
+
+				case 'M' :
+					strfmt(r,"%2",t->tm_min);
+					break;
+
+				case 'p' :
+					r = (t->tm_hour>11)?"PM":"AM";
+					break;
+
+				case 'S' :
+					strfmt(r,"%2",t->tm_sec);
+					break;
+
+				case 'U' :
+					w = t->tm_yday/7;
+					if (t->tm_yday%7 > t->tm_wday)
+						w++;
+					strfmt(r, "%2", w);
+					break;
+
+				case 'W' :
+					w = (t->tm_yday + DAYSPERWEEK -
+						(t->tm_wday ?
+						(t->tm_wday - 1) :
+						(DAYSPERWEEK - 1))) / DAYSPERWEEK;
+					strfmt(r, "%2", w);
+					break;
+
+				case 'w' :
+					strfmt(r,"%1",t->tm_wday);
+					break;
+
+				case 'x' :
+					strfmt(r, "%2/%2/%2", t->tm_mon + 1,
+						   t->tm_mday, t->tm_year+1900);
+					break;
+
+				case 'X' :
+					strfmt(r, "%2:%2:%2", t->tm_hour,
+						   t->tm_min, t->tm_sec);
+					break;
+
+				case 'y' :
+					strfmt(r,"%2",t->tm_year%100);
+					break;
+
+				case 'Y' :
+					strfmt(r,"%4",t->tm_year+1900);
+					break;
+
+				case 'Z' :
+					r = (t->tm_isdst && tz_name[1][0])?tz_name[1]:tz_name[0];
+					break;
+
+				default:
+					buf[0] = '%';		// reconstruct the format
+					buf[1] = f[-1];
+					buf[2] = '\0';
+					if (buf[1] == 0)
+						f--;			// back up if at end of string
+			}
+			while (*r)
+			{
+				if (p == q)
+				{
+					*q = '\0';
+					return 0;
+				}
+				*p++ = *r++;
+			}
+		}
+		else
+		{
+			if (p == q)
+			{
+				*q = '\0';
+				return 0;
+			}
+			*p++ = f[-1];
+		}
+	}
+	*p = '\0';
+	return p - s;
+}
+
+//
+// static void strfmt(char *str, char *fmt);
+// 
+// simple sprintf for strftime
+// 
+// each format descriptor is of the form %n
+// where n goes from zero to four
+// 
+// 0    -- string %s
+// 1..4 -- int %?.?d
+// 
+static void strfmt(char *str, const char *fmt, ...)
+{
+	int ival, ilen;
+	char *sval;
+	static int pow[5] = { 1, 10, 100, 1000, 10000 };
+	va_list vp;
+
+	va_start(vp, fmt);
+	while (*fmt)
+	{
+		if (*fmt++ == '%')
+		{
+			ilen = *fmt++ - '0';
+			if (ilen == 0)                // zero means string arg
+			{
+				sval = va_arg(vp, char*);
+				while (*sval)
+					*str++ = *sval++;
+			}
+			else                          // always leading zeros
+			{
+				ival = va_arg(vp, int);
+				while (ilen)
+				{
+					ival %= pow[ilen--];
+					*str++ = (char)('0' + ival / pow[ilen]);
+				}
+			}
+		}
+		else  *str++ = fmt[-1];
+	}
+	*str = '\0';
+	va_end(vp);
+}
+
+// internal functions
+//-----------------------------------------------------------------------------
+// Convert 100ns units since 1601 to seconds since 1970
+//
+LONGLONG SystemTimeToSecondsSince1970(SYSTEMTIME *st)
+{
+	ULARGE_INTEGER	uli;
+	FILETIME		ft;
+	ULARGE_INTEGER	uli1970;
+	FILETIME		ft1970;
+
+	// convert to a FILETIME
+	// Gives number of 100-nanosecond intervals since January 1, 1601 (UTC)
+	//
+	if(!SystemTimeToFileTime(st, &ft))
+	{
+		return TIME_FAILURE;
+	}
+
+	// convert to a FILETIME
+	// Gives number of 100-nanosecond intervals since January 1, 1970 (UTC)
+	//
+	if(!SystemTimeToFileTime(&st1970, &ft1970))
+	{
+		return TIME_FAILURE;
+	}
+
+	// Copy file time structures into ularge integer so we can do
+	// the math more easily
+	//
+	memcpy(&uli, &ft, sizeof(uli));
+	memcpy(&uli1970, &ft1970, sizeof(uli1970));
+
+	// Subtract the 1970 number of 100 ns value from the 1601 100 ns value
+	// so we can get the number of 100 ns value between 1970 and now
+	// then devide be 10,000,000 to get the number of seconds since 1970
+	//
+	uli.QuadPart = ((uli.QuadPart - uli1970.QuadPart) / 10000000);
+
+	return (LONGLONG)uli.QuadPart;
+}
+
+// Convert seconds since 1970 to a file time in 100ns units since 1601
+// then to a system time.
+//
+void SecondsSince1970ToSystemTime(const time_t_ce * timer, SYSTEMTIME * st, 
+								  BOOLEAN local)
+{
+	ULARGE_INTEGER	uli;
+	FILETIME		ft;
+	ULARGE_INTEGER	uli1970;
+	FILETIME		ft1970;
+
+	// Convert system time to file time
+	//
+	if(!SystemTimeToFileTime(&st1970, &ft1970))
+	{
+		st = NULL;
+		return;
+	}
+
+	// convert hundreds of nanosecs to secs: 1 sec = 1e7 100ns
+	// Gives number of seconds since 1/1/1601 (UTC)
+	//
+  memcpy(&uli, timer, sizeof(uli));
+  memcpy(&uli1970, &ft1970, sizeof(uli1970));
+
+	// If we want local time then subtract the number of seconds between
+	// UTC and current local time
+	//
+	if (local)
+	{
+		// Calculate 100ns since 1/1/1601 local time
+		//
+    uli.QuadPart = (((uli.QuadPart - _localtime)*10000000) + uli1970.QuadPart);
+	}
+	else
+	{
+		// Calculate 100ns since 1/1/1601 UTC
+		//
+		uli.QuadPart = ((uli.QuadPart)*10000000 + uli1970.QuadPart);
+	}
+
+	// copy data back into the ft
+	//
+	memcpy(&ft, &uli, sizeof(uli));
+
+	// convert to a SYSTEMTIME
+	//
+	if(!FileTimeToSystemTime(&ft, st))
+	{
+		st = NULL;
+		return;
+	}
+
+	return;
+}
+
+// Set the time zone information needed for the rest of the methods
+//
+void SetTz(SYSTEMTIME *_st)
+{
+	TIME_ZONE_INFORMATION	tz;
+	SYSTEMTIME				st = *_st;
+	FILETIME				ftDT; // Daylight savings file time
+	FILETIME				ftST; // Standard time file time
+	FILETIME				ft;   // file time to compare
+	int						i;
+
+	GetTimeZoneInformation(&tz);
+
+	// Convert current system time, daylight savings changover time
+	// and standard time to file time to see if current time is between
+	// the two dates.  If so then we are in daylight savings otherwise we
+	// are not.
+	//
+	SystemTimeToFileTime(&st, &ft);
+	tz.DaylightDate.wYear = st.wYear;
+	tz.StandardDate.wYear = st.wYear;
+  SystemTimeToFileTime(&tz.DaylightDate, &ftDT);
+	SystemTimeToFileTime(&tz.StandardDate, &ftST);
+
+  // -1 First file time is earlier than second file time. 
+  //  0 First file time is equal to second file time. 
+  //  1 First file time is later than second file time. 
+	//
+	if ((CompareFileTime(&ft,&ftDT) >= 0) && (CompareFileTime(&ft,&ftST) <= 0) )
+	{
+		_isdst = TRUE;
+	}
+	else
+	{
+		_isdst = FALSE;
+	}
+
+	// Set localtime difference in seconds from UTC
+	//
+	if (_isdst)
+	{
+		// Adjust for Daylight Savings Time and convert to seconds
+		//
+		_localtime = (tz.Bias + tz.DaylightBias) * SECS_IN_MIN;
+	}
+	else
+	{
+		// Convert to seconds
+		//
+		_localtime = tz.Bias * SECS_IN_MIN;
+	}
+
+	_dstBias = tz.DaylightBias;
+
+	// Set the standard and daylight strings
+	//
+	for (i=0;i<32;i++)
+	{
+		tz_name[0][i] = (char)tz.StandardName[i];
+		tz_name[1][i] = (char)tz.DaylightName[i];
+	}
+}
+
+// Copy system time structure to tm structure
+//
+void SystemTimeToTm(SYSTEMTIME *st, struct tm * tmbuffer)
+{
+	tmbuffer->tm_hour = st->wHour;
+    tmbuffer->tm_mday = st->wDay;
+    tmbuffer->tm_min = st->wMinute;
+    tmbuffer->tm_mon = st->wMonth - 1;
+    tmbuffer->tm_sec = st->wSecond;
+    tmbuffer->tm_wday = st->wDayOfWeek;
+    tmbuffer->tm_yday = JulianDays(st);		// Julian days, numer of days since Jan 1
+	tmbuffer->tm_year = st->wYear - 1900;
+	tmbuffer->tm_isdst = _isdst;			// Is Daylight Savings Time
+}
+
+void TmToSystemTime(struct tm * tmbuffer, SYSTEMTIME *st)
+{
+  st->wHour = tmbuffer->tm_hour;
+  st->wDay = tmbuffer->tm_mday;
+  st->wMinute = tmbuffer->tm_min;
+  st->wMonth = tmbuffer->tm_mon + 1;
+  st->wSecond = tmbuffer->tm_sec;
+  st->wDayOfWeek = tmbuffer->tm_wday;
+  st->wYear = tmbuffer->tm_year + 1900;
+  st->wMilliseconds = 0;
+}
+
+// Get the JulianDay from a Gregorian Date for number of days into the current
+// year
+// Algorithm from: http://www.vsg.cape.com/~pbaum/date/jdalg2.htm
+//
+DWORD JulianDays(SYSTEMTIME * st)
+{
+	int m = 0;
+	int y = 0;
+	double jdd = 0;
+	double jddYearStart = 0;
+
+	// Calculate the Julian day for the beginning of the year
+	//
+    m = 13;
+	y = st->wYear - 1;
+    jddYearStart = 1 + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400) + 1721118.5;
+
+	// Calculate Julian Day for Current Date
+	//
+	if (st->wMonth >= 3)
+	{
+		m = st->wMonth;
+		y = st->wYear;
+	}
+    jdd = st->wDay + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400) + 1721118.5;
+
+	// Subract the year start Julian date from the Current Julian date to get
+	// the number of Julian days from the year start
+	//
+	return (DWORD)(jdd - jddYearStart);
+}

Added: trunk/src/SlideBible/time_ce/time_ce.h
===================================================================
--- trunk/src/SlideBible/time_ce/time_ce.h	                        (rev 0)
+++ trunk/src/SlideBible/time_ce/time_ce.h	2010-01-07 20:55:10 UTC (rev 223)
@@ -0,0 +1,118 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Legalese:
+// This file is part of the OpenNETCF time.h port for Windows CE.
+// You are free to use, modify or distribute this code or any
+// derivative work that you create.  This code is provided WITHOUT
+// WARRANTY and OpenNETCF does NOT claim in any way that this code 
+// is fit for any specific or general use and holds NO RESPONSIBILITY
+// for consequences of using any of it.  It is simply provided as-is.
+//
+// About:
+// This is part of a free and open project to provide a simply way to
+// port that uses time.h functions to Windows CE.  For the latest
+// code, or to submit fixes, feature additions, etc. visit:
+//
+// http://www.opennetcf.com
+//
+// Version 0.01 - March 22, 2007
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef __TIME_CE_H__
+#define __TIME_CE_H__
+
+//
+// time_CE.h
+//
+ 
+#include <windows.h>
+
+/*
+// these pragmas help Studio to build for some CE platforms - use as necessary
+#pragma comment(linker, "/nodefaultlib:libc.lib")
+#pragma comment(linker, "/nodefaultlib:libcd.lib")
+#pragma comment(lib, "secchk.lib")
+*/
+
+// Number of clock ticks per second. Used by the clock() function.
+//
+#define CLOCKS_PER_SEC		1000
+
+// Macro for CLK_PER_SEC
+//
+#define CLK_TICK			CLOCKS_PER_SEC
+
+// structure definitions
+//
+#ifndef _TM_DEFINED
+struct tm {
+    int tm_sec;			// seconds
+    int tm_min;			// minutes
+    int tm_hour;		// hours
+    int tm_mday;		// day of the month
+    int tm_mon;			// month
+    int tm_year;		// years since 1900 (from 0)
+    int tm_wday;		// days since Sunday (from 0)
+    int tm_yday;		// days since Jan 1
+    int tm_isdst;		// daylight savings (summertime) flag
+    };
+#define _TM_DEFINED
+#endif
+
+// typedefs
+//
+typedef DWORD clock_t_ce;
+
+// since time_t is already defined in CE as a ULONG, we need a new definition
+//
+typedef LONGLONG time_t_ce;
+
+static struct tm tmbuf;
+
+// Convert tm to a string in the format "Www Mmm dd hh:mm:ss yyyy", 
+// where Www is the weekday, Mmm the month in letters, dd the day 
+// of the month, hh:mm:ss the time, and yyyy the year. The string 
+// is followed by a newline and a terminating null character, 
+// conforming a total of 26 characters. 
+//
+char *asctime_ce(const struct tm* tmptr);
+
+// Return number of clock ticks since process start.
+//
+clock_t_ce clock_ce(void);
+
+// Convert time_t value to string in the same format as asctime.
+//
+char* ctime_ce(const time_t_ce* timer);
+
+// Returns the difference in seconds between the two times.
+//
+double difftime_ce(time_t_ce timer2, time_t_ce timer1);
+
+// Convert a time_t value to a tm structure as UTC time. 
+//
+struct tm* gmtime_ce(const time_t_ce* timer);
+
+// Convert a time_t value to a tm structure as local time. 
+//
+struct tm* localtime_ce(const time_t_ce* timer);
+
+// Returns the Unix timestamp corresponding to the arguments given. 
+// This timestamp is a long integer containing the number of seconds between the Unix Epoch 
+// (January 1 1970 00:00:00 GMT) and the time specified. 
+//
+time_t_ce mktime_ce(struct tm *tptr);
+
+// Get the current time from the system clock. Stores that value in timer.
+// If timer is null, the value is not stored, but it is still returned by
+// the function.
+//
+time_t_ce time_ce(time_t_ce* timer);
+
+// Format tm into a date/time string
+//
+size_t strftime_ce(char *s, size_t maxs, const char *f, const struct tm *t);
+
+#endif
\ No newline at end of file

Modified: trunk/src/SlideBible/todo.txt
===================================================================
--- trunk/src/SlideBible/todo.txt	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/todo.txt	2010-01-07 20:55:10 UTC (rev 223)
@@ -1,64 +1,78 @@
 alpha
-+	make button-items min height of finger size
-+	fix findwindow on start
-+	show sword version somewhere
-+	change versification system in navigation view
-+	when mods.d not found - show tip message
-+	navigation list from last place
-+	on first use show "Read Bible ..."
-+	fix rect for Options View
-+	release congiguration
++	release configuration
 +	module view description
-~	sometimes happens something wrong with height of empty verse and verse text line height
++	huge rewrite
++		platform independent api layer
++		test base types
++			memory tracker
++			threading
++			sbColor - constructor from string
++		make it work
++			wm6.5 not started
++			release configuration not started
 	verse history
++		time function
 	timer to save configs
-
-	bookmarks, history, ratings, thematic verse lists, tags, colors
-		dialog: verse actions(favorite|send to list...|send to new list)
-		dialog: select verse(s)
-		dialog: menu verse
+	remake lists sytem
+	remake current place indicator
+	win32 platform
 		
+	verse data
+		bookmarks, history, ratings, thematic verse lists, tags, colors
+			dialog: verse actions(favorite|send to list...|send to new list)
+			dialog: select verse(s)
+			dialog: menu verse
+	?	verse features:
+			readings count (forgotten places/chapters)
+			bookmarks static/dynamic
+				on screen marks
+			attendance history: date, module, key
+			verse lists (remember for...)
+			
 	search
 		clucence
 		input text items
 +			sip control
 			cursor
 ?			copy/paste
-		
-?		verse features:
-			readings count (forgotten places/chapters)
-			bookmarks static/dynamic
-			attendance history: date, module, key
-			verse lists (remember for...)
 
-*	static / dynamic bookmarks
-		on screen marks
 
-	prepare to Huge Rewrite
+	combining unicode accents, like accute (should be in platform-dependent part)
+?	double click for zoom out
+	smart item surface cacher, create square surface of longer screen side
+		render item in sbItem::render
 	text fade
 	2. Ïàðàëèïîìå\níîí\n4 in chapter title
 	start slide to empty list, but drop to not empty produces blank screen
 	daily devotionals
 	make list scrolling more smooth
 	make verse expantion without jerks
-?	update theme from psd file
 	cross-references, footnotes
 	controls, pressed/released
 	link neighbor lists: items will be fitted by height, empty verses will be displayed hollow
 	keypad: on key pressed, keyMode activated, every button on displayed as common text, as touchscreen pressed, every button on screen become drawn as button
 	loading all locale takes too long
-	screen rotation
 	slide list and stroke down/up - link list
+ 	sometimes happens something wrong with height of empty verse and verse text line height
+	different screens and runtime orientation change
+		g-sensor support
+
+?	update theme from psd file
 ?	data abort in gwes.exe on emulator
 ?	base class for sbItem and sbControl for holding screen text
 ?	make lists pins (next/prev/left/right) links constant. so instances of same type should not change their values direct
 ?	moving to sdl
 
-beta	
-	toTest
+beta
+	to test
 		other locales, utf encoding
 		russian paths
-		different screens and runtime orientation change
+	icons and graphics
 
 release
-	sliding backgrounds
+	sliding, animated backgrounds
+	Link, like Opera Link to synchronize bookmarks and all Per Verse Data among all user devices
+		need Sword change that every verse in Bibile at every v11n has unique id
+	read html / txt / rtf / doc formats
+	another platform : android , mac os x ,  openembedded , symbian , maemo , ...
+	
\ No newline at end of file

Modified: trunk/src/SlideBible/ui/scheme.txt
===================================================================
--- trunk/src/SlideBible/ui/scheme.txt	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible/ui/scheme.txt	2010-01-07 20:55:10 UTC (rev 223)
@@ -55,4 +55,35 @@
     ежедневное чтение
     подготовка к проповеди
     поиск мест на проповеди
-    изучение Слова
\ No newline at end of file
+    изучение Слова
+    
+    
+    
+    
+    
+    LOOKS
+    
+    
+    -- Read Bible  -----------------------------
+	
+	Mattew        5:1          John        14:11
+	           opened                 4 days ago
+	  
+	1 Chronicles 6:29          All Readings
+	   15 minutes ago            3 readings more
+	   
+	Bookmarks                  History
+	     12 bookmarks          
+	
+	-- Options  --------------------------------
+	
+	Default Module :         < Russian Synodal >
+	
+	Current Sword version is 1.6.1
+	
+	
+	
+	------------                            ----
+	Select Place                            Exit
+	------------                            ----
+

Modified: trunk/src/SlideBible.sln
===================================================================
--- trunk/src/SlideBible.sln	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SlideBible.sln	2010-01-07 20:55:10 UTC (rev 223)
@@ -5,13 +5,19 @@
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
 		Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+		Release|Win32 = Release|Win32
 		Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Debug|Win32.Build.0 = Debug|Win32
 		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
 		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
 		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Release|Win32.ActiveCfg = Release|Win32
+		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Release|Win32.Build.0 = Release|Win32
 		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
 		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
 		{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)

Modified: trunk/src/SwordReader_GUI/SwordReader_GUI.vcproj
===================================================================
--- trunk/src/SwordReader_GUI/SwordReader_GUI.vcproj	2009-12-11 20:44:49 UTC (rev 222)
+++ trunk/src/SwordReader_GUI/SwordReader_GUI.vcproj	2010-01-07 20:55:10 UTC (rev 223)
@@ -449,7 +449,7 @@
 			/>
 			<DeploymentTool
 				ForceDirty="-1"
-				RemoteDirectory="\Program Files\SwordReader\"
+				RemoteDirectory="\StorageCard\Program Files\SwordReader\"
 				RegisterOutput="0"
 				AdditionalFiles="../../sword.dll"
 			/>
@@ -1173,11 +1173,11 @@
 			Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
 			>
 			<File
-				RelativePath="..\gui\BibleReader.ICO"
+				RelativePath=".\BibleReader.ICO"
 				>
 			</File>
 			<File
-				RelativePath=".\BibleReader.ICO"
+				RelativePath="..\gui\BibleReader.ICO"
 				>
 			</File>
 			<File




More information about the sword-cvs mailing list