[sword-svn] r235 - in trunk/src/SlideBible: . bin platform/wince platform/wince/sys

kalemas at crosswire.org kalemas at crosswire.org
Mon May 24 12:44:18 MST 2010


Author: kalemas
Date: 2010-05-24 12:44:18 -0700 (Mon, 24 May 2010)
New Revision: 235

Added:
   trunk/src/SlideBible/SlideBible.sln
   trunk/src/SlideBible/platform/wince/fcntl.cpp
Removed:
   trunk/src/SlideBible/platform/wince/fcntl.cpp
Modified:
   trunk/src/SlideBible/SlideBible.vcproj
   trunk/src/SlideBible/bin/SlideBible.exe
   trunk/src/SlideBible/bin/SlideBible_Win32.exe
   trunk/src/SlideBible/main.cpp
   trunk/src/SlideBible/platform/wince/fcntl.h
   trunk/src/SlideBible/platform/wince/sys/errno.h
   trunk/src/SlideBible/platform/wince/time_ce.cpp
   trunk/src/SlideBible/platform/wince/unistd.cpp
   trunk/src/SlideBible/platform/wince/unistd.h
   trunk/src/SlideBible/sbBase.h
   trunk/src/SlideBible/sbControl.cpp
   trunk/src/SlideBible/sbControl.h
   trunk/src/SlideBible/sbCore.cpp
   trunk/src/SlideBible/sbCore.h
   trunk/src/SlideBible/sbFeatures.cpp
   trunk/src/SlideBible/sbFeatures.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
Log:
+	limit history
+	currentVerse from defaultModule
+	perfomance optimization: sbItem caching, can work only if background is solid
+	banner showing current place make as sbItem
+	Global Options switch in one module cause switch in another
	module manager
+		reinit Sword
+		message boxes before installing module
+		installManager data in special folder
	module features
+		options dialog
+		strongs and morphs
+		option sbItem with text like "Strongs: On" + option value enumeration
	search
+		input text items
+			sip control

Copied: trunk/src/SlideBible/SlideBible.sln (from rev 223, trunk/src/SlideBible.sln)
===================================================================
--- trunk/src/SlideBible/SlideBible.sln	                        (rev 0)
+++ trunk/src/SlideBible/SlideBible.sln	2010-05-24 19:44:18 UTC (rev 235)
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SlideBible", "SlideBible.vcproj", "{F0CEF277-24C5-45BC-A0D0-56BE5A64AB94}"
+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)
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

Modified: trunk/src/SlideBible/SlideBible.vcproj
===================================================================
--- trunk/src/SlideBible/SlideBible.vcproj	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/SlideBible.vcproj	2010-05-24 19:44:18 UTC (rev 235)
@@ -51,7 +51,7 @@
 				AdditionalOptions="/D "NO_VSNPRINTF""
 				Optimization="0"
 				AdditionalIncludeDirectories=".\platform\wince\;..\..\..\..\sword\trunk\include\;..\..\..\..\sword\trunk\include\internal\regex\"
-				PreprocessorDefinitions="DEBUG;ARM;_ARM_;UNDER_CE=$(CEVER);_WIN32_WCE=$(CEVER);$(CePlatform);UNICODE;SIMPLE"
+				PreprocessorDefinitions="DEBUG;ARM;_ARM_;UNDER_CE=$(CEVER);_WIN32_WCE=$(CEVER);$(CePlatform);UNICODE;SIMPLE;HAVE_STRERROR;NEED_STRDUP"
 				IgnoreStandardIncludePath="false"
 				GeneratePreprocessedFile="0"
 				StringPooling="true"
@@ -80,7 +80,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="aygshell.lib"
+				AdditionalDependencies="aygshell.lib Ws2.lib cellcore.lib"
 				OutputFile="$(OutDir)/SlideBible.exe"
 				LinkIncremental="2"
 				DelayLoadDLLs="$(NOINHERIT)"
@@ -247,7 +247,7 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				AdditionalIncludeDirectories=".\platform\win32\;..\..\..\..\sword\trunk\include\;..\..\..\..\sword\trunk\include\internal\regex\"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRTDBG_MAP_ALLOC;REGEX_MALLOC;DEBUG"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRTDBG_MAP_ALLOC;REGEX_MALLOC;DEBUG;_CRT_SECURE_NO_WARNINGS"
 				IgnoreStandardIncludePath="false"
 				StringPooling="true"
 				MinimalRebuild="false"
@@ -276,7 +276,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				RegisterOutput="true"
-				AdditionalDependencies="msimg32.Lib"
+				AdditionalDependencies="msimg32.Lib Ws2_32.lib"
 				OutputFile="$(OutDir)/SlideBible.exe"
 				LinkIncremental="2"
 				DelayLoadDLLs="$(NOINHERIT)"
@@ -341,7 +341,7 @@
 				Optimization="2"
 				FavorSizeOrSpeed="2"
 				AdditionalIncludeDirectories=".\platform\wince\;..\..\..\..\sword\trunk\include\;..\..\..\..\sword\trunk\include\internal\regex\"
-				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
+				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_STRERROR;NEED_STRDUP"
 				StringPooling="true"
 				RuntimeLibrary="0"
 				StructMemberAlignment="3"
@@ -364,7 +364,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions=" /subsystem:windowsce,5.01"
-				AdditionalDependencies="aygshell.lib"
+				AdditionalDependencies="aygshell.lib Ws2.lib cellcore.lib"
 				OutputFile="$(OutDir)/SlideBible.exe"
 				LinkIncremental="1"
 				DelayLoadDLLs="$(NOINHERIT)"
@@ -630,6 +630,14 @@
 					Name="utilfuns"
 					>
 					<File
+						RelativePath="..\..\..\..\sword\trunk\src\utilfuns\ftplib.c"
+						>
+					</File>
+					<File
+						RelativePath="..\..\..\..\sword\trunk\src\utilfuns\ftpparse.c"
+						>
+					</File>
+					<File
 						RelativePath="..\..\..\..\sword\trunk\src\utilfuns\regex.c"
 						>
 					</File>
@@ -689,6 +697,10 @@
 							>
 						</File>
 						<File
+							RelativePath="..\..\..\..\sword\trunk\src\utilfuns\zlib\gzio.c"
+							>
+						</File>
+						<File
 							RelativePath="..\..\..\..\sword\trunk\src\utilfuns\zlib\infblock.c"
 							>
 						</File>
@@ -753,6 +765,10 @@
 							>
 						</File>
 						<File
+							RelativePath="..\..\..\..\sword\trunk\src\utilfuns\zlib\untgz.c"
+							>
+						</File>
+						<File
 							RelativePath="..\..\..\..\sword\trunk\src\utilfuns\zlib\zutil.c"
 							>
 						</File>
@@ -1234,6 +1250,18 @@
 						>
 					</File>
 					<File
+						RelativePath="..\..\..\..\sword\trunk\src\mgr\ftplibftpt.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\..\..\..\sword\trunk\src\mgr\ftptrans.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\..\..\..\sword\trunk\src\mgr\installmgr.cpp"
+						>
+					</File>
+					<File
 						RelativePath="..\..\..\..\sword\trunk\src\mgr\localemgr.cpp"
 						>
 					</File>

Modified: trunk/src/SlideBible/bin/SlideBible.exe
===================================================================
(Binary files differ)

Modified: trunk/src/SlideBible/bin/SlideBible_Win32.exe
===================================================================
(Binary files differ)

Modified: trunk/src/SlideBible/main.cpp
===================================================================
--- trunk/src/SlideBible/main.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/main.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -22,9 +22,12 @@
 #ifdef _WIN32_WCE
 #include <aygshell.h>
 
-#include <fcntl.cpp>
 #include <time_ce.cpp>
 #include <unistd.cpp>
+#include <fcntl.cpp>
+
+//#include <ruby/winsock2.c>
+
 #endif
 
 #include <filemgr.h>
@@ -39,30 +42,30 @@
 // Functions
 void sbMessage ( const char * format , ... )
 {
+	char buffer [1024];
+
 	va_list args;
-
-	static FileDesc * file = NULL;
+	va_start(args, format);
 	
-	file = FileMgr::getSystemFileMgr()->open(".\\log.txt", file == NULL ? FileMgr::WRONLY|FileMgr::CREAT|FileMgr::TRUNC : FileMgr::WRONLY|FileMgr::APPEND );
-	
-	if (file->getFd() <= 0) return;
-	
-	va_start(args, format);
+	int l = _vsnprintf(buffer, 1024, format, args); if (l == -1) l = 1024;
 
-	char buffer [1024];
-	int l = _vsnprintf(buffer, 1024, format, args);
+	va_end(args);
 
-	file->write(buffer,l == -1 ? 1024 : l);
-
-#ifndef _WIN32_WCE
+#ifdef _WIN32_WCE
+	printf(buffer);
+#else
 	OutputDebugStringA(buffer);
-#else
-	printf(buffer);
 #endif
 
-	va_end(args);
+	//static FileDesc * file = NULL;
+	//file = FileMgr::getSystemFileMgr()->open(".\\log.txt", file == NULL ? FileMgr::WRONLY|FileMgr::CREAT|FileMgr::TRUNC : FileMgr::WRONLY|FileMgr::APPEND );
+	static FileDesc * file = FileMgr::getSystemFileMgr()->open(".\\log.txt", FileMgr::WRONLY|FileMgr::CREAT|FileMgr::TRUNC );
 
-	FileMgr::getSystemFileMgr()->close(file);
+	if (file->getFd() > 0)
+	{
+		file->write(buffer,l);
+		//FileMgr::getSystemFileMgr()->close(file);
+	}
 }
 
 void sbFillRect ( sbSurface rc, const sbRect * rect, sbColor color )
@@ -305,7 +308,7 @@
 
 	if (timeout <= 0)
 	{
-		sbMessage ("Thread terminated.\n");
+		sbMessage ("Thread termination forced.\n");
 
 		TerminateThread(threadData->handle, -1);
 		threadData->running = false;
@@ -362,13 +365,27 @@
 	LineTo((HDC)rc, to.x, to.y); 
 }
 
-sbColor sbSelectColor ( sbSurface rc, sbColor color )
+void sbSelectColor ( sbSurface rc, sbColor color )
 {
-	COLORREF old = SetTextColor((HDC)rc,RGB(color.red,color.green,color.blue));
-	return sbColor(GetRValue(old),GetGValue(old),GetBValue(old));
+	//static sbColor * prevColor = NULL;
+	//if (prevColor == &color) return *prevColor;
+	SetTextColor((HDC)rc,RGB(color.red,color.green,color.blue));
+	//prevColor = &color;
 }
 
+bool sbQueryBox ( const TCHAR * question )
+{
+	return MessageBox(Window,question,L"Question :",MB_YESNO) == IDYES;
+}
 
+int sbWcsToMbs ( const TCHAR * wcs , char * mbs , int length )
+{
+	if (!length)
+		return WideCharToMultiByte(CP_UTF8,0,wcs,-1,NULL,0,NULL,NULL);
+	return WideCharToMultiByte(CP_UTF8,0,wcs,-1,mbs,length,NULL,NULL);
+}
+
+
 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; }
 void            sbDeleteFont           ( sbFont font )            { DeleteObject ((HFONT)font); }
 void            sbDeleteBitmap         ( sbBitmap bitmap )        { DeleteObject ((HBITMAP)bitmap); }
@@ -381,9 +398,9 @@
 void            sbStretchBlt           ( sbSurface toRc, sbRect toRect , sbSurface fromRc, sbRect fromRect ) { StretchBlt((HDC)toRc, toRect.left, toRect.top, toRect.width(), toRect.height(), (HDC)fromRc, fromRect.left, fromRect.top, fromRect.width(), fromRect.height(), SRCCOPY); }
 long            sbGetTickCount         ()                         { return GetTickCount(); }
 void            sbExit                 ( int code )               { PostQuitMessage(code); }
+void            sbWaitMode             ( bool wait )              { if (wait) SetCursor ( LoadCursor ( NULL, IDC_WAIT ) ); else SetCursor ( LoadCursor ( NULL, IDC_ARROW ) ); }
 
 
-
 LRESULT CALLBACK wndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
 	switch ( message )
@@ -459,8 +476,343 @@
 	return DefWindowProc(hwnd, message, wParam, lParam);
 }
 
-#include <stdio.h>
+#if 0//#ifdef _WIN32_WCE
 
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#include <tchar.h>
+#include <strsafe.h>
+
+struct in_addr BIN_IPV4_ADDR_LOOPBACK = {127, 0, 0, 1};
+struct in6_addr BIN_IPV6_ADDR_LOOPBACK =   {   0x0, 0x0,
+	0x0, 0x0,
+	0x0, 0x0,
+	0x0, 0x0,
+	0x0, 0x0,
+	0x0, 0x0,
+	0x0, 0x0,
+	0x0, 0x1 };
+#define   MAX_LOCAL_NAME_LEN               64
+
+//Function Prototypes
+BOOL IsNetPresent();
+
+int netTest(const char * adress)
+{
+	WSADATA WSAData;
+
+	WSAStartup(MAKEWORD(2,2), &WSAData);
+	sbMessage("Network Connection %s present", IsNetPresent() ? "IS" : "is NOT");
+	WSACleanup();
+
+	return 0;
+}
+
+//
+// Determine if you have a IPv4 or IPv6 network address.
+//
+BOOL IsNetPresent()
+{
+	BOOL bFoundLocalAddr = FALSE;
+	char szAddrASCII[MAX_LOCAL_NAME_LEN];
+	ADDRINFO AddrHints, *pAI, *pAddrInfo;
+
+	//
+	// Get the local host's name in ASCII text.
+	//
+	if(gethostname(szAddrASCII, MAX_LOCAL_NAME_LEN - 1))
+	{
+		sbMessage("Error getting local host name, error = %d\r\n", WSAGetLastError());
+		return FALSE;
+	}
+
+	//
+	// To obtain a list of all the local
+	// addresses, resolve the local name with getaddrinfo for all
+	// protocol families.
+	//
+
+	memset(&AddrHints, 0, sizeof(AddrHints));
+	AddrHints.ai_family = PF_UNSPEC;
+	AddrHints.ai_flags = AI_PASSIVE;
+
+	if(getaddrinfo(szAddrASCII, "10", &AddrHints, &pAddrInfo))
+	{
+		sbMessage("getaddrinfo(%hs) error %d", szAddrASCII, WSAGetLastError());
+		return FALSE;
+	}
+
+	//
+	// Search the addresses returned.
+	// If any of them match the loopback address, then
+	// are not connected to an outside network.
+	//
+	// Note: This will not tell you how many networks you
+	// are connected to.  If one or more networks are present,
+	// then the loopback addresses will not be included in the
+	// list returned from getaddrinfo.
+	//
+
+	bFoundLocalAddr = TRUE;
+	for(pAI = pAddrInfo; pAI != NULL && bFoundLocalAddr; pAI = pAI->ai_next)
+	{
+		if(pAI->ai_family == PF_INET)
+		{
+			if(memcmp(&(((SOCKADDR_IN *)(pAI->ai_addr))->sin_addr), &BIN_IPV4_ADDR_LOOPBACK, sizeof(BIN_IPV4_ADDR_LOOPBACK)) == 0)
+				bFoundLocalAddr = FALSE;
+		}
+		else if(pAI->ai_family == PF_INET6)
+		{
+			if(memcmp(&(((SOCKADDR_IN6 *)(pAI->ai_addr))->sin6_addr), &BIN_IPV6_ADDR_LOOPBACK, sizeof(BIN_IPV6_ADDR_LOOPBACK)) == 0)
+				bFoundLocalAddr = FALSE;  
+		}
+	}
+
+	freeaddrinfo(pAddrInfo);
+
+	return bFoundLocalAddr;
+}
+
+#endif
+
+#if 0//#ifdef _WIN32_WCE
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <strsafe.h>
+
+char pBuf[] = "WinCE Echo Test Packet";
+
+#define DEFAULT_FAMILY        AF_UNSPEC
+#define DEFAULT_SOCKTYPE    SOCK_STREAM
+#define BUFFER_SIZE            23                // length of "WinCE Echo Test Packet"
+
+int netTest (const char * szRemoteName)
+{
+	SOCKET sock = INVALID_SOCKET;
+	int nFamily = DEFAULT_FAMILY;
+	int nSockType = DEFAULT_SOCKTYPE;
+	SOCKADDR_STORAGE ssRemoteAddr;
+	int cbXfer, cbTotalRecvd, cbRemoteAddrSize;
+	WSADATA wsaData;
+	ADDRINFO Hints, *AddrInfo = NULL, *AI;
+	char szRemoteAddrString[128];
+	fd_set fdReadSet;
+	TIMEVAL timeout = {2, 0};
+	char pRecvBuf[BUFFER_SIZE];
+
+	if(WSAStartup(MAKEWORD(2,2), &wsaData))
+	{
+		// WSAStartup failed
+		return -1;
+	}
+
+	sbMessage("Communicating with server - %hs\r\n",szRemoteName);
+
+	//
+	// Resolve the server name/address
+	//
+
+	memset(&Hints, 0, sizeof(Hints));
+	Hints.ai_family = nFamily;
+	Hints.ai_socktype = nSockType;
+
+	if(getaddrinfo(szRemoteName, "1234", &Hints, &AddrInfo))
+	{
+		sbMessage("ERROR: Couldn't get resolve the server name/address!\r\n");
+		
+		if(sock != INVALID_SOCKET)
+		{
+			shutdown(sock, SD_BOTH);
+			closesocket(sock);
+		}
+
+		if(AddrInfo)
+			freeaddrinfo(AddrInfo);
+
+		WSACleanup();
+
+		return 0;
+	}
+
+	//
+	// Attempt to connect to each address until we find one that succeeds
+	//
+
+	for(AI = AddrInfo; AI != NULL; AI = AI->ai_next) 
+	{
+		if((AI->ai_family == PF_INET) || (AI->ai_family == PF_INET6)) // only want PF_INET or PF_INET6
+		{
+			sock = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
+			if (sock != INVALID_SOCKET)
+			{
+				if (AI->ai_socktype == SOCK_STREAM)
+				{
+					if(connect(sock, AI->ai_addr, AI->ai_addrlen) == SOCKET_ERROR)
+					{
+						// Connect failed, let's close this socket and try again on the next address in the list
+						closesocket(sock);
+						continue;
+					}
+				}
+
+				sbMessage ("connect() succeeded or we're a UDP socket\r\n");
+				break;
+			}
+		}
+	}
+
+	if (AI == NULL) 
+	{
+		sbMessage("ERROR: Unable to connect to any of the server's addresses!\r\n");
+		
+		if(sock != INVALID_SOCKET)
+		{
+			shutdown(sock, SD_BOTH);
+			closesocket(sock);
+		}
+
+		if(AddrInfo)
+			freeaddrinfo(AddrInfo);
+
+		WSACleanup();
+
+		return 0;
+	}
+
+	//
+	// Send data to the server
+	//
+
+	cbXfer = 0;
+	cbXfer = sendto(sock, pBuf, sizeof(pBuf), 0, AI->ai_addr, AI->ai_addrlen);
+
+	if(cbXfer != sizeof(pBuf))
+	{
+		sbMessage("ERROR: Couldn't send the data! error = %d\r\n"), WSAGetLastError();
+		
+		if(sock != INVALID_SOCKET)
+		{
+			shutdown(sock, SD_BOTH);
+			closesocket(sock);
+		}
+
+		if(AddrInfo)
+			freeaddrinfo(AddrInfo);
+
+		WSACleanup();
+
+		return 0;
+	}
+
+	if (getnameinfo(AI->ai_addr, AI->ai_addrlen,
+		szRemoteAddrString, sizeof(szRemoteAddrString), NULL, 0, NI_NUMERICHOST) != 0)
+		strcpy(szRemoteAddrString, "");
+
+	sbMessage("SUCCESS - Sent %d bytes to address %hs\r\n", cbXfer, szRemoteAddrString);
+
+	//
+	// Receive the echo'd data back from the server
+	//
+
+	FD_ZERO(&fdReadSet);
+	FD_SET(sock, &fdReadSet);
+
+	if(select(0, &fdReadSet, NULL, NULL, &timeout) != 1)
+	{
+		sbMessage("ERROR: Server hasn't responded in %d milliseconds\r\n"), ((timeout.tv_sec * 1000) + (timeout.tv_sec / 1000));
+		
+		if(sock != INVALID_SOCKET)
+		{
+			shutdown(sock, SD_BOTH);
+			closesocket(sock);
+		}
+
+		if(AddrInfo)
+			freeaddrinfo(AddrInfo);
+
+		WSACleanup();
+
+		return 0;
+	}
+
+	cbTotalRecvd = 0;
+	do
+	{
+		cbRemoteAddrSize = sizeof(ssRemoteAddr);
+		cbXfer = recvfrom(sock, pRecvBuf + cbTotalRecvd, sizeof(pRecvBuf) - cbTotalRecvd, 0, 
+			(SOCKADDR *)&ssRemoteAddr, &cbRemoteAddrSize);
+		cbTotalRecvd += cbXfer;
+	} while(cbXfer > 0 && cbTotalRecvd < sizeof(pRecvBuf));
+
+	if(cbXfer == SOCKET_ERROR)
+	{
+		sbMessage("ERROR: Couldn't receive the data! Error = %d\r\n", WSAGetLastError());
+		
+		if(sock != INVALID_SOCKET)
+		{
+			shutdown(sock, SD_BOTH);
+			closesocket(sock);
+		}
+
+		if(AddrInfo)
+			freeaddrinfo(AddrInfo);
+
+		WSACleanup();
+
+		return 0;
+	}
+	else if(cbTotalRecvd != sizeof(pRecvBuf))
+	{
+		sbMessage("ERROR: Server didn't send back all the expected data!\r\n");
+		
+		if(sock != INVALID_SOCKET)
+		{
+			shutdown(sock, SD_BOTH);
+			closesocket(sock);
+		}
+
+		if(AddrInfo)
+			freeaddrinfo(AddrInfo);
+
+		WSACleanup();
+
+		return 0;
+	}
+
+	if(nSockType == SOCK_STREAM)
+	{
+		memset(&ssRemoteAddr, 0, sizeof(ssRemoteAddr));
+		cbRemoteAddrSize = sizeof(ssRemoteAddr);
+		getpeername(sock, (SOCKADDR *)&ssRemoteAddr, &cbRemoteAddrSize);
+	}
+
+	if (getnameinfo((SOCKADDR *)&ssRemoteAddr, cbRemoteAddrSize,
+		szRemoteAddrString, sizeof(szRemoteAddrString), NULL, 0, NI_NUMERICHOST) != 0)
+		strcpy(szRemoteAddrString, "");
+
+	sbMessage("SUCCESS - Received %d bytes back from address %hs\r\n", cbTotalRecvd, szRemoteAddrString);
+
+	if(sock != INVALID_SOCKET)
+	{
+		shutdown(sock, SD_BOTH);
+		closesocket(sock);
+	}
+
+	if(AddrInfo)
+		freeaddrinfo(AddrInfo);
+
+	WSACleanup();
+
+	return 1;
+}
+
+#endif
+
+//#include <bombus-ng-md/Socket.cpp>
+//#include <swconfig.h>
+
 int WINAPI _tWinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
 {
 	const TCHAR * appClass = L"SlideBible Application";
@@ -468,6 +820,47 @@
 	
 	int exitCode = 0;
 
+	//netTest("google.com");
+
+	/*{
+		sword::SWConfig conf (".\\options.conf");
+		conf.Load();
+
+		const char * host = conf["Test"].getWithDefault("address","speedguide.net");
+		const int port = atoi (conf["Test"].getWithDefault("port","7"));
+		const char * req = (conf["Test"].getWithDefault("request","SlideBible test echo."));
+
+		Socket::initWinsocks();
+
+		Socket::networkUp();
+
+		long ip = Socket::resolveUrl(host);
+		sbMessage("Connecting to %s at %u.%u.%u.%u\n",host,(ip>>0)&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,(ip>>24)&0xFF);
+
+		Socket * ts = new Socket (ip,port);
+
+		int b = ts->write(req,strlen(req));
+
+		sbMessage ("Writen : %i\n",b);
+
+		Sleep(2000);
+
+		char rb [256];
+		memset (&rb,0,256);
+		b = ts->read(rb,256);
+
+		Sleep(2000);
+
+		sbMessage ("Received : %i %s\n",b,rb);
+
+		sbMessage ("Statistics : %s\n",ts->getStatistics());
+
+		delete ts;
+	}*/
+
+	//mkdir("./20081216195754/modules/texts/ztext/ury_WBTI_2005");
+	//FileMgr::getSystemFileMgr()->createParent("./20081216195754/modules/texts/ztext/ury_WBTI_2005");
+
 	HWND hwnd = FindWindow ( appClass, appTitle );
 
 	if (hwnd)

Deleted: trunk/src/SlideBible/platform/wince/fcntl.cpp
===================================================================
--- trunk/src/SlideBible/platform/wince/fcntl.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/platform/wince/fcntl.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -1,6 +0,0 @@
-char* getenv(char* anything) {return 0;};
-void perror(char * message) {};
-int errno;
-extern "C" {
-void abort() {};
-}
\ No newline at end of file

Added: trunk/src/SlideBible/platform/wince/fcntl.cpp
===================================================================
--- trunk/src/SlideBible/platform/wince/fcntl.cpp	                        (rev 0)
+++ trunk/src/SlideBible/platform/wince/fcntl.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -0,0 +1,101 @@
+
+extern "C"
+{
+void abort() {};
+
+char * getenv(char* anything)
+{
+	return "";
+};
+
+char * strerror ( int errno )
+{
+	sbMessage ("errno : %i\n",errno);
+	return "";
+}
+
+int WSAGetLastError( void );
+
+void perror ( char * message )
+{
+	static struct { int no; const char *msg; } *msgp, msgs[] = {
+		{ 10, "SSL Certificate Issuer unknown" },
+		{ WSAEINTR, "Interrupted system call" },
+		{ WSAEBADF, "Bad file descriptor" },
+		{ WSAEACCES, "Permission denied" },
+		{ WSAEFAULT, "Bad address" },
+		{ WSAEINVAL, "Invalid argument" },
+		{ WSAEMFILE, "Too many open files" },
+		{ WSAEWOULDBLOCK, "Another winsock call while a blocking function was in progress" },
+		{ WSAEINPROGRESS, "Operation now in progress" },
+		{ WSAEALREADY, "Operation already in progress" },
+		{ WSAENOTSOCK, "Socket operation on non-socket" },
+		{ WSAEDESTADDRREQ, "Destination address required" },
+		{ WSAEMSGSIZE, "Message too long" },
+		{ WSAEPROTOTYPE, "Protocol wrong type for socket" },
+		{ WSAENOPROTOOPT, "Protocol not available" },
+		{ WSAEPROTONOSUPPORT, "Protocol not supported" },
+		{ WSAESOCKTNOSUPPORT, "Socket type not supported" },
+		{ WSAEOPNOTSUPP, "Operation not supported" },
+		{ WSAEPFNOSUPPORT, "Protocol family not supported" },
+		{ WSAEAFNOSUPPORT, "Address family not supported" },
+		{ WSAEADDRINUSE, "Address already in use" },
+		{ WSAEADDRNOTAVAIL, "Can't assign requested address" },
+		{ WSAENETDOWN, "Network is down" },
+		{ WSAENETUNREACH, "Network is unreachable" },
+		{ WSAENETRESET, "Network dropped connection on reset" },
+		{ WSAECONNABORTED, "Software caused connection abort" },
+		{ WSAECONNRESET, "Connection reset by peer" },
+		{ WSAENOBUFS, "No buffer space available" },
+		{ WSAEISCONN, "Socket is already connected" },
+		{ WSAENOTCONN, "Socket is not connected" },
+		{ WSAESHUTDOWN, "Can't send after socket shutdown" },
+		{ WSAETOOMANYREFS, "Too many references: can't splice" },
+		{ WSAETIMEDOUT, "Operation timed out" },
+		{ WSAECONNREFUSED, "Connection refused" },
+		{ WSAELOOP, "Too many levels of symbolic links" },
+		{ WSAENAMETOOLONG, "File name too long" },
+		{ WSAEHOSTDOWN, "Host is down" },
+		{ WSAEHOSTUNREACH, "No route to host" },
+		{ WSAENOTEMPTY, "Directory not empty" },
+		{ WSAEPROCLIM, "Too many processes" },
+		{ WSAEUSERS, "Too many users" },
+		{ WSAEDQUOT, "Disc quota exceeded" },
+		{ WSAESTALE, "Stale NFS file handle" },
+		{ WSAEREMOTE, "Too many levels of remote in path" },
+		{ WSASYSNOTREADY, "Network subsystem is unvailable" },
+		{ WSAVERNOTSUPPORTED, "WinSock version is not supported" },
+		{ WSANOTINITIALISED, "Successful WSAStartup() not yet performed" },
+		{ WSAEDISCON, "Graceful shutdown in progress" },
+		/* Resolver errors */
+		{ WSAHOST_NOT_FOUND, "No such host is known" },
+		{ WSATRY_AGAIN, "Host not found, or server failed" },
+		{ WSANO_RECOVERY, "Unexpected server error encountered" },
+		{ WSANO_DATA, "Valid name without requested data" },
+		//{ WSANO_ADDRESS, "No address, look for MX record" },
+		{ 0, NULL }
+	};
+
+	long code = GetLastError();
+
+	for (msgp=msgs; msgp->msg; msgp++)
+	{
+		if (code==msgp->no)
+		{
+			sbMessage ("perror in %s : %s\n",message,msgp->msg);
+			return;
+		}
+	}
+
+	sbMessage ("perror in %s GetLastError:%i\n",message,code);
+};
+
+char * tmpnam ( char * str )
+{
+	static int counter = 0;
+	sprintf(str,".\\file%u.tmp",counter++);
+	return str;
+};
+
+int errno;
+}

Modified: trunk/src/SlideBible/platform/wince/fcntl.h
===================================================================
--- trunk/src/SlideBible/platform/wince/fcntl.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/platform/wince/fcntl.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -21,8 +21,20 @@
 #define O_BINARY       0x8000  /* file mode is binary (untranslated) */
 
 /* WinCE unsupported */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern error_t errno;
 char* getenv(char* anything);
+
+char * strerror (int errno);
 void perror(char * message);
 
+char * tmpnam(char *);
+
+#ifdef __cplusplus
+};
 #endif
+
+#endif

Modified: trunk/src/SlideBible/platform/wince/sys/errno.h
===================================================================
--- trunk/src/SlideBible/platform/wince/sys/errno.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/platform/wince/sys/errno.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -1,126 +1,131 @@
-#define	EPERM 1		/* Not super-user */
+
+#include <fcntl.h>
+
+
+//#define	EPERM 1		/* Not super-user */
 #define	ENOENT 2	/* No such file or directory */
-#define	ESRCH 3		/* No such process */
-#define	EINTR 4		/* Interrupted system call */
-#define	EIO 5		/* I/O error */
-#define	ENXIO 6		/* No such device or address */
-#define	E2BIG 7		/* Arg list too long */
-#define	ENOEXEC 8	/* Exec format error */
-#define	EBADF 9		/* Bad file number */
-#define	ECHILD 10	/* No children */
-#define	EAGAIN 11	/* No more processes */
-#define	ENOMEM 12	/* Not enough core */
-#define	EACCES 13	/* Permission denied */
-#define	EFAULT 14	/* Bad address */
-#define	ENOTBLK 15	/* Block device required */
-#define	EBUSY 16	/* Mount device busy */
-#define	EEXIST 17	/* File exists */
-#define	EXDEV 18	/* Cross-device link */
-#define	ENODEV 19	/* No such device */
-#define	ENOTDIR 20	/* Not a directory */
-#define	EISDIR 21	/* Is a directory */
-#define	EINVAL 22	/* Invalid argument */
-#define	ENFILE 23	/* Too many open files in system */
-#define	EMFILE 24	/* Too many open files */
-#define	ENOTTY 25	/* Not a typewriter */
-#define	ETXTBSY 26	/* Text file busy */
-#define	EFBIG 27	/* File too large */
-#define	ENOSPC 28	/* No space left on device */
-#define	ESPIPE 29	/* Illegal seek */
-#define	EROFS 30	/* Read only file system */
-#define	EMLINK 31	/* Too many links */
-#define	EPIPE 32	/* Broken pipe */
-#define	EDOM 33		/* Math arg out of domain of func */
-#define	ERANGE 34	/* Math result not representable */
-#define	ENOMSG 35	/* No message of desired type */
-#define	EIDRM 36	/* Identifier removed */
-#define	ECHRNG 37	/* Channel number out of range */
-#define	EL2NSYNC 38	/* Level 2 not synchronized */
-#define	EL3HLT 39	/* Level 3 halted */
-#define	EL3RST 40	/* Level 3 reset */
-#define	ELNRNG 41	/* Link number out of range */
-#define	EUNATCH 42	/* Protocol driver not attached */
-#define	ENOCSI 43	/* No CSI structure available */
-#define	EL2HLT 44	/* Level 2 halted */
-#define	EDEADLK 45	/* Deadlock condition */
-#define	ENOLCK 46	/* No record locks available */
-#define EBADE 50	/* Invalid exchange */
-#define EBADR 51	/* Invalid request descriptor */
-#define EXFULL 52	/* Exchange full */
-#define ENOANO 53	/* No anode */
-#define EBADRQC 54	/* Invalid request code */
-#define EBADSLT 55	/* Invalid slot */
-#define EDEADLOCK 56	/* File locking deadlock error */
-#define EBFONT 57	/* Bad font file fmt */
-#define ENOSTR 60	/* Device not a stream */
-#define ENODATA 61	/* No data (for no delay io) */
-#define ETIME 62	/* Timer expired */
-#define ENOSR 63	/* Out of streams resources */
-#define ENONET 64	/* Machine is not on the network */
-#define ENOPKG 65	/* Package not installed */
-#define EREMOTE 66	/* The object is remote */
-#define ENOLINK 67	/* The link has been severed */
-#define EADV 68		/* Advertise error */
-#define ESRMNT 69	/* Srmount error */
-#define	ECOMM 70	/* Communication error on send */
-#define EPROTO 71	/* Protocol error */
-#define	EMULTIHOP 74	/* Multihop attempted */
-#define	ELBIN 75	/* Inode is remote (not really error) */
-#define	EDOTDOT 76	/* Cross mount point (not really error) */
-#define EBADMSG 77	/* Trying to read unreadable message */
-#define EFTYPE 79	/* Inappropriate file type or format */
-#define ENOTUNIQ 80	/* Given log. name not unique */
-#define EBADFD 81	/* f.d. invalid for this operation */
-#define EREMCHG 82	/* Remote address changed */
-#define ELIBACC 83	/* Can't access a needed shared lib */
-#define ELIBBAD 84	/* Accessing a corrupted shared lib */
-#define ELIBSCN 85	/* .lib section in a.out corrupted */
-#define ELIBMAX 86	/* Attempting to link in too many libs */
-#define ELIBEXEC 87	/* Attempting to exec a shared library */
-#define ENOSYS 88	/* Function not implemented */
-#define ENMFILE 89      /* No more files */
-#define ENOTEMPTY 90	/* Directory not empty */
-#define ENAMETOOLONG 91	/* File or path name too long */
-#define ELOOP 92	/* Too many symbolic links */
-#define EOPNOTSUPP 95	/* Operation not supported on transport endpoint */
-#define EPFNOSUPPORT 96 /* Protocol family not supported */
-#define ECONNRESET 104  /* Connection reset by peer */
-#define ENOBUFS 105	/* No buffer space available */
-#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
-#define EPROTOTYPE 107	/* Protocol wrong type for socket */
-#define ENOTSOCK 108	/* Socket operation on non-socket */
-#define ENOPROTOOPT 109	/* Protocol not available */
-#define ESHUTDOWN 110	/* Can't send after socket shutdown */
-#define ECONNREFUSED 111	/* Connection refused */
-#define EADDRINUSE 112		/* Address already in use */
-#define ECONNABORTED 113	/* Connection aborted */
-#define ENETUNREACH 114		/* Network is unreachable */
-#define ENETDOWN 115		/* Network interface is not configured */
-#define ETIMEDOUT 116		/* Connection timed out */
-#define EHOSTDOWN 117		/* Host is down */
-#define EHOSTUNREACH 118	/* Host is unreachable */
-#define EINPROGRESS 119		/* Connection already in progress */
-#define EALREADY 120		/* Socket already connected */
-#define EDESTADDRREQ 121	/* Destination address required */
-#define EMSGSIZE 122		/* Message too long */
-#define EPROTONOSUPPORT 123	/* Unknown protocol */
-#define ESOCKTNOSUPPORT 124	/* Socket type not supported */
-#define EADDRNOTAVAIL 125	/* Address not available */
-#define ENETRESET 126
-#define EISCONN 127		/* Socket is already connected */
-#define ENOTCONN 128		/* Socket is not connected */
-#define ETOOMANYREFS 129
-#define EPROCLIM 130
-#define EUSERS 131
-#define EDQUOT 132
-#define ESTALE 133
-#define ENOTSUP 134		/* Not supported */
-#define ENOMEDIUM 135   /* No medium (in tape drive) */
-#define ENOSHARE 136    /* No such host or network path */
-#define ECASECLASH 137  /* Filename exists with different case */
-#define EILSEQ 138
-#define EOVERFLOW 139	/* Value too large for defined data type */
+//#define	ESRCH 3		/* No such process */
+//#define	EINTR 4		/* Interrupted system call */
+//#define	EIO 5		/* I/O error */
+//#define	ENXIO 6		/* No such device or address */
+//#define	E2BIG 7		/* Arg list too long */
+//#define	ENOEXEC 8	/* Exec format error */
+//#define	EBADF 9		/* Bad file number */
+//#define	ECHILD 10	/* No children */
+//#define	EAGAIN 11	/* No more processes */
+//#define	ENOMEM 12	/* Not enough core */
+//#define	EACCES 13	/* Permission denied */
+//#define	EFAULT 14	/* Bad address */
+//#define	ENOTBLK 15	/* Block device required */
+//#define	EBUSY 16	/* Mount device busy */
+//#define	EEXIST 17	/* File exists */
+//#define	EXDEV 18	/* Cross-device link */
+//#define	ENODEV 19	/* No such device */
+//#define	ENOTDIR 20	/* Not a directory */
+//#define	EISDIR 21	/* Is a directory */
+//#define	EINVAL 22	/* Invalid argument */
+//#define	ENFILE 23	/* Too many open files in system */
+//#define	EMFILE 24	/* Too many open files */
+//#define	ENOTTY 25	/* Not a typewriter */
+//#define	ETXTBSY 26	/* Text file busy */
+//#define	EFBIG 27	/* File too large */
+//#define	ENOSPC 28	/* No space left on device */
+//#define	ESPIPE 29	/* Illegal seek */
+//#define	EROFS 30	/* Read only file system */
+//#define	EMLINK 31	/* Too many links */
+//#define	EPIPE 32	/* Broken pipe */
+//#define	EDOM 33		/* Math arg out of domain of func */
+//#define	ERANGE 34	/* Math result not representable */
+//#define	ENOMSG 35	/* No message of desired type */
+//#define	EIDRM 36	/* Identifier removed */
+//#define	ECHRNG 37	/* Channel number out of range */
+//#define	EL2NSYNC 38	/* Level 2 not synchronized */
+//#define	EL3HLT 39	/* Level 3 halted */
+//#define	EL3RST 40	/* Level 3 reset */
+//#define	ELNRNG 41	/* Link number out of range */
+//#define	EUNATCH 42	/* Protocol driver not attached */
+//#define	ENOCSI 43	/* No CSI structure available */
+//#define	EL2HLT 44	/* Level 2 halted */
+//#define	EDEADLK 45	/* Deadlock condition */
+//#define	ENOLCK 46	/* No record locks available */
+//#define EBADE 50	/* Invalid exchange */
+//#define EBADR 51	/* Invalid request descriptor */
+//#define EXFULL 52	/* Exchange full */
+//#define ENOANO 53	/* No anode */
+//#define EBADRQC 54	/* Invalid request code */
+//#define EBADSLT 55	/* Invalid slot */
+//#define EDEADLOCK 56	/* File locking deadlock error */
+//#define EBFONT 57	/* Bad font file fmt */
+//#define ENOSTR 60	/* Device not a stream */
+//#define ENODATA 61	/* No data (for no delay io) */
+//#define ETIME 62	/* Timer expired */
+//#define ENOSR 63	/* Out of streams resources */
+//#define ENONET 64	/* Machine is not on the network */
+//#define ENOPKG 65	/* Package not installed */
+//#define EREMOTE 66	/* The object is remote */
+//#define ENOLINK 67	/* The link has been severed */
+//#define EADV 68		/* Advertise error */
+//#define ESRMNT 69	/* Srmount error */
+//#define	ECOMM 70	/* Communication error on send */
+//#define EPROTO 71	/* Protocol error */
+//#define	EMULTIHOP 74	/* Multihop attempted */
+//#define	ELBIN 75	/* Inode is remote (not really error) */
+//#define	EDOTDOT 76	/* Cross mount point (not really error) */
+//#define EBADMSG 77	/* Trying to read unreadable message */
+//#define EFTYPE 79	/* Inappropriate file type or format */
+//#define ENOTUNIQ 80	/* Given log. name not unique */
+//#define EBADFD 81	/* f.d. invalid for this operation */
+//#define EREMCHG 82	/* Remote address changed */
+//#define ELIBACC 83	/* Can't access a needed shared lib */
+//#define ELIBBAD 84	/* Accessing a corrupted shared lib */
+//#define ELIBSCN 85	/* .lib section in a.out corrupted */
+//#define ELIBMAX 86	/* Attempting to link in too many libs */
+//#define ELIBEXEC 87	/* Attempting to exec a shared library */
+//#define ENOSYS 88	/* Function not implemented */
+//#define ENMFILE 89      /* No more files */
+//#define ENOTEMPTY 90	/* Directory not empty */
+//#define ENAMETOOLONG 91	/* File or path name too long */
+//#define ELOOP 92	/* Too many symbolic links */
+//#define EOPNOTSUPP 95	/* Operation not supported on transport endpoint */
+//#define EPFNOSUPPORT 96 /* Protocol family not supported */
+//#define ECONNRESET 104  /* Connection reset by peer */
+//#define ENOBUFS 105	/* No buffer space available */
+//#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
+//#define EPROTOTYPE 107	/* Protocol wrong type for socket */
+//#define ENOTSOCK 108	/* Socket operation on non-socket */
+//#define ENOPROTOOPT 109	/* Protocol not available */
+//#define ESHUTDOWN 110	/* Can't send after socket shutdown */
+//#define ECONNREFUSED 111	/* Connection refused */
+//#define EADDRINUSE 112		/* Address already in use */
+//#define ECONNABORTED 113	/* Connection aborted */
+//#define ENETUNREACH 114		/* Network is unreachable */
+//#define ENETDOWN 115		/* Network interface is not configured */
+//#define ETIMEDOUT 116		/* Connection timed out */
+//#define EHOSTDOWN 117		/* Host is down */
+//#define EHOSTUNREACH 118	/* Host is unreachable */
+//#define EINPROGRESS 119		/* Connection already in progress */
+//#define EALREADY 120		/* Socket already connected */
+//#define EDESTADDRREQ 121	/* Destination address required */
+//#define EMSGSIZE 122		/* Message too long */
+//#define EPROTONOSUPPORT 123	/* Unknown protocol */
+//#define ESOCKTNOSUPPORT 124	/* Socket type not supported */
+//#define EADDRNOTAVAIL 125	/* Address not available */
+//#define ENETRESET 126
+//#define EISCONN 127		/* Socket is already connected */
+//#define ENOTCONN 128		/* Socket is not connected */
+//#define ETOOMANYREFS 129
+//#define EPROCLIM 130
+//#define EUSERS 131
+//#define EDQUOT 132
+//#define ESTALE 133
+//#define ENOTSUP 134		/* Not supported */
+//#define ENOMEDIUM 135   /* No medium (in tape drive) */
+//#define ENOSHARE 136    /* No such host or network path */
+//#define ECASECLASH 137  /* Filename exists with different case */
+//#define EILSEQ 138
+//#define EOVERFLOW 139	/* Value too large for defined data type */
 
-#define EWOULDBLOCK EAGAIN	/* Operation would block */
 
+//#define EWOULDBLOCK EAGAIN	/* Operation would block */
+
 #define __ELASTERROR 2000	/* Users can add values starting here */

Modified: trunk/src/SlideBible/platform/wince/time_ce.cpp
===================================================================
--- trunk/src/SlideBible/platform/wince/time_ce.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/platform/wince/time_ce.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -253,6 +253,12 @@
 	return gmtime_r_ce(timer, &tmbuf, FALSE);
 }
 
+struct tm *gmtime (const time_t * timer)
+{
+	time_t_ce timer_ce = *timer;
+	return gmtime_r_ce(&timer_ce, &tmbuf, FALSE);
+}
+
 // Convert a time_t value to a tm structure as local time. 
 //
 struct tm *localtime_ce(const time_t_ce *timer)

Modified: trunk/src/SlideBible/platform/wince/unistd.cpp
===================================================================
--- trunk/src/SlideBible/platform/wince/unistd.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/platform/wince/unistd.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -139,9 +139,26 @@
 	DWORD attribs = GetFileAttributes(buf);
 
 	if (attribs == 0xFFFFFFFF)
-		retVal = 1;
+	{
+		int err = GetLastError();
+		switch (err)
+		{
+		case ERROR_PATH_NOT_FOUND:
+			//sbMessage ("access : %s : ERROR_PATH_NOT_FOUND\n",path);
+			return 1;
+		default:
+			//sbMessage ("access : %s : %i\n",path,err);
+			return 1;
+		}
+	}
 	else if (((mode & O_RDWR) || (mode & O_WRONLY)) && (attribs & FILE_ATTRIBUTE_READONLY))
+	{
 		retVal = 1;
+	}
+	else if (attribs & FILE_ATTRIBUTE_DIRECTORY)
+	{
+		return 0;
+	}
 
 	return retVal;
 }
@@ -165,19 +182,97 @@
 	return retVal;
 }
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
+int mkdir ( const char * path )
+{
+	wchar_t wbuf[MAX_PATH];
+
+	mbstowcs(wbuf, adaptpath(path), MAX_PATH);
+
+	return CreateDirectory(wbuf,NULL) ? 0 : 1;
+}
+
+int remove (const char * path)
+{
+	const char * winPath = adaptpath(path);
+	wchar_t wbuf[MAX_PATH];
+
+	mbstowcs(wbuf, winPath, MAX_PATH);
+
+	return DeleteFile(wbuf);
+}
+
 // TODO: create a directory
-int mkdir(const char *)
+int _mkdir ( const char * dir)
 {
-	return 0;
+	return mkdir(dir);
 }
 
 // TODO: delete a file
-int remove(const char *)
+int _unlink (const char * file)
 {
-	return 0;
+	return remove(file);
 }
 
+void rewind(FILE * file)
+{
+	lseek ( (int)file , 0 , SEEK_SET );
+}
+
+FILE * _fdopen(int fd, const char * type)
+{
+	return (FILE *)fd;
+}
+
+FILE * fopen_wce (const char * path, const char * mode)
+{
+	int m = 0;
+
+	if (!strcmp(mode,"rb"))
+		m = O_RDONLY;
+	else if (!strcmp(mode,"wb") || !strcmp(mode,"w"))
+		m = O_WRONLY | O_CREAT | O_TRUNC;
+	else
+		sbAssert(true);
+
+	int ret = open ( path , m );
+
+	if (ret == -1)
+	{
+		sbMessage ("Failed to open %s %s\n",path,mode);
+		ret = NULL;
+	}
+
+	return (FILE *)ret;
+}
+
+size_t fread_wce (void * buf, size_t size, size_t count, FILE * fd)
+{
+	return (size_t) read ((int)fd, buf, count*size);
+}
+
+size_t fwrite_wce (const void * buf, size_t size, size_t count, FILE * fd)
+{
+	return (size_t) write ((int)fd, buf, count*size );
+}
+
+int    fclose_wce (FILE * fd)
+{
+	return close ((int)fd);
+}
+
+int    fseek_wce (FILE * fd, long offset, int whence)
+{
+	return lseek ((int)fd, offset, whence);
+}
+
+#ifdef __cplusplus
+};
+#endif
+
 const char* adaptpath ( const char * path )
 {
 	static SWBuf retVal;

Modified: trunk/src/SlideBible/platform/wince/unistd.h
===================================================================
--- trunk/src/SlideBible/platform/wince/unistd.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/platform/wince/unistd.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -28,9 +28,39 @@
 int write(int fd, const void * buf, size_t count);
 off_t lseek(int fildes, off_t offset, int whence);
 int access(const char* path, int mode);
-int mkdir(const char *);
-int remove(const char *);
 int stat(const char *, struct stat *);
 const char* adaptpath(const char *path);
 
+//inline int __cdecl _mkdir (const char * dir) { return mkdir(dir); }
+//inline int __cdecl _unlink (const char * path) { return remove(path); }
+//#define _unlink remove
+
+#ifdef __cplusplus
+extern "C" {
 #endif
+
+int mkdir(const char *);
+int remove(const char *);
+int _mkdir(const char *);
+int _unlink(const char *);
+void rewind(FILE * file);
+
+FILE * fopen_wce (const char *, const char *);
+size_t fread_wce (void *, size_t, size_t, FILE *);
+size_t fwrite_wce (const void *, size_t, size_t, FILE *);
+int    fclose_wce (FILE *);
+int    fseek (FILE *, long, int);
+
+#ifdef __cplusplus
+};
+#endif
+
+
+#define fopen fopen_wce
+#define fread fread_wce
+#define fwrite fwrite_wce
+#define fclose fclose_wce
+#define fseek fseek_wce
+
+
+#endif

Modified: trunk/src/SlideBible/sbBase.h
===================================================================
--- trunk/src/SlideBible/sbBase.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbBase.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -87,30 +87,45 @@
 
 sbThread        sbThreadCreate         ( void (*executor) (bool *) );
 void            sbThreadDestroy        ( sbThread threadData );
-void            sbFillRect             ( sbSurface, const sbRect * rect, sbColor color );
-void            sbDrawGradient         ( sbSurface, const sbRect * rect, sbColor startColor, sbColor endColor, bool vertical );
+
+void            sbGetScreenRect        ( sbRect & rect );
+void            sbUpdateScreen         ();
+
 void            sbDrawBitmap           ( sbSurface, const sbRect * rect, sbBitmap bitmap, bool stretch = false );
-void            sbGetScreenRect        ( sbRect & rect );
 sbBitmap        sbLoadBitmap           ( const TCHAR * filename );
+void            sbDeleteBitmap         ( sbBitmap bitmap );
+
+void            sbDrawText             ( sbSurface, int x, int y, const TCHAR * text, int count );
+sbPoint         sbGetTextExtent        ( sbFont, const TCHAR * text, int count );
+sbFont          sbMakeFont             ( int size, const TCHAR *face, bool bold, bool italic );
+void            sbDeleteFont           ( sbFont );
+
+void            sbBitBlt               ( sbSurface, sbRect toRect , sbSurface fromRc, sbPoint fromXy );
+void            sbStretchBlt           ( sbSurface, sbRect toRect , sbSurface fromRc, sbRect fromRect );
 sbSurface       sbSurfaceCreate        ( int width, int height );
 void            sbSurfaceDestroy       ( sbSurface );
-sbFont          sbMakeFont             ( int size, const TCHAR *face, bool bold, bool italic );
-sbPoint         sbGetTextExtent        ( sbFont, const TCHAR * text, int count );
-void            sbDeleteFont           ( sbFont );
-void            sbDeleteBitmap         ( sbBitmap bitmap );
+
 sbFont          sbSelectFont           ( sbSurface, sbFont );
-sbColor         sbSelectColor          ( sbSurface, sbColor );
-void            sbDrawText             ( sbSurface, int x, int y, const TCHAR * text, int count );
+void            sbSelectColor          ( sbSurface, sbColor );
+
+void            sbFillRect             ( sbSurface, const sbRect * rect, sbColor color );
+void            sbDrawGradient         ( sbSurface, const sbRect * rect, sbColor startColor, sbColor endColor, bool vertical );
 void            sbDrawLine             ( sbSurface, sbPoint from, sbPoint to, sbColor, int thickness );
+
+void            sbSetTimer             ( const int timer, int refreshRate );
+void            sbKillTimer            ( const int timer );
+
+long            sbGetTickCount         ();
 void            sbSleep                ( int milliseconds );
+
 const char *    sbGetLocale            ();
-void            sbSetTimer             ( const int timer, int refreshRate );
-void            sbKillTimer            ( const int timer );
-void            sbBitBlt               ( sbSurface, sbRect toRect , sbSurface fromRc, sbPoint fromXy );
-void            sbStretchBlt           ( sbSurface, sbRect toRect , sbSurface fromRc, sbRect fromRect );
-void            sbUpdateScreen         ();
+int             sbWcsToMbs             ( const TCHAR * wcs , char * mbs = NULL , int length = 0 );
+
 void            sbSetSip               ( bool on );
-long            sbGetTickCount         ();
+
+bool            sbQueryBox             ( const TCHAR * question );
+
+void            sbWaitMode             ( bool wait );
 void            sbExit                 ( int code );
 
 enum

Modified: trunk/src/SlideBible/sbControl.cpp
===================================================================
--- trunk/src/SlideBible/sbControl.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbControl.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -87,22 +87,30 @@
 	switch (type)
 	{
 	// navigation
-	case TYPE_OPEN_BOOK_SELECTION:   rect = layout(1,16,0,5);    setText(L"Book");    break;
-	case TYPE_OPEN_MODULE_SELECTION: rect = layout(1,16,5,11);   setText(L"Module");  break;
+
+	case TYPE_OPEN_BOOK_SELECTION:   rect = layout(1,16,0,6);    setText(L"Book");    break;
+	case TYPE_OPEN_SEARCH:           rect = layout(1,16,6,11);   setText(L"Search");  break;
 	case TYPE_CLOSE:                 rect = layout(1,16,11,16);  setText(L"Back");    break;
+
+	case TYPE_OPEN_SEARCH_2:         rect = layout(1,16,0,6);    setText(L"Search");  break;
+	case TYPE_OPEN_MODULE_SELECTION: rect = layout(1,16,6,11);   setText(L"Module");  break;
+
 	// list
 	case TYPE_OPEN_NAVIGATION_LIST:  rect = layout(1,16,0,5);    setText(L"Goto");    break;
-	case TYPE_LIST_SPACE:            rect = layout(1,16,5,11);   setText(L"Options"); break;
+	case TYPE_OPEN_OPTIONS:          rect = layout(1,16,5,11);   setText(L"Options"); break;
 	case TYPE_OPEN_HOME:             rect = layout(1,16,11,16);  setText(L"Home");    break;
 	// home
 	case TYPE_OPEN_NAVIGATION:       rect = layout(1,16,0,6);    setText(L"Goto");    break;
 	case TYPE_OPEN_HISTORY:          rect = layout(1,16,6,11);   setText(L"History"); break;
 	case TYPE_EXIT:                  rect = layout(1,16,11,16);  setText(L"Exit");    break;
+	// module installer disclaimer
+	case TYPE_INSTALLER_DISCLAIMER_ACCEPT  : rect = layout(1,2,0,1); setText(L"Accept"); break;
+	case TYPE_INSTALLER_DISCLAIMER_DECLINE : rect = layout(1,2,1,2); setText(L"Decline"); break;
 	// other
+	case TYPE_WIDE_MODULES:          rect = layout(1,1,1);       setText(L"Close");   break;
+	case TYPE_WIDE_CLOSE:            rect = layout(1,1,1);       setText(L"Close");   break;
 	case TYPE_MODE_ADD_STAR:         rect = layout(1,4,2);       setText(L"*");       break;
-	case TYPE_OPEN_SEARCH:           rect = layout(1,4,3);       setText(L"S");       break;
 	case TYPE_OPEN_TEXT:             rect = layout(1,4,2);       setText(L"H");       break;
-	case TYPE_WIDE_CLOSE:            rect = layout(1,1,1);       setText(L"Close");   break;
 	case TYPE_CAN_SWITCH_LEFT:       rect = layout(2,12,1);      setText(L"<");       break;
 	case TYPE_CAN_SWITCH_RIGHT:      rect = layout(2,12,12);     setText(L">");       break;
 	case TYPE_BUTTON_OPEN_FILE:      rect = layout(1,4,1);       setText(L"");        break;
@@ -197,13 +205,18 @@
 	case TYPE_OPEN_MODULE_SELECTION:
 	case TYPE_CLOSE:
 	case TYPE_OPEN_NAVIGATION_LIST:
-	case TYPE_LIST_SPACE:
+	case TYPE_OPEN_OPTIONS:
 	case TYPE_OPEN_HOME:
 	case TYPE_OPEN_NAVIGATION:
 	case TYPE_OPEN_HISTORY:
 	case TYPE_EXIT:
 	case TYPE_WIDE_CLOSE:
+	case TYPE_WIDE_MODULES:
 	case TYPE_MENU_CANCEL:
+	case TYPE_INSTALLER_DISCLAIMER_ACCEPT:
+	case TYPE_INSTALLER_DISCLAIMER_DECLINE:
+	case TYPE_OPEN_SEARCH:
+	case TYPE_OPEN_SEARCH_2:
 		{
 			Core->getTheme()->drawElement(hdc, &rect, sbTheme::ELEMENT::PANEL);
 			sbSelectColor(hdc, Core->getTheme()->fadeColor(Core->getTheme()->elements[sbTheme::ELEMENT::PANEL].textColor,textPos.x,textPos.y));
@@ -258,11 +271,22 @@
 	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:              sbExit(1);                                       break;
+	case TYPE_WIDE_MODULES:               Core->switchList(sbList::TYPE_MODULE_VIEW);      break;
 	case TYPE_WIDE_CLOSE:                 Core->switchList(sbList::TYPE_HOME);             break;
 	case TYPE_CLOSE:                      Core->switchList(sbList::TYPE_MODULE_VIEW);      break;
-	case TYPE_LIST_SPACE:
+	case TYPE_OPEN_OPTIONS:               Core->switchList(sbList::TYPE_MENU_OPTIONS);     break;
+	case TYPE_OPEN_SEARCH_2:
+	case TYPE_OPEN_SEARCH:                Core->switchList(sbList::TYPE_SEARCH);           break;
 	case TYPE_CAN_SWITCH_LEFT:
 	case TYPE_CAN_SWITCH_RIGHT:                                                            break;
+	case TYPE_INSTALLER_DISCLAIMER_ACCEPT:
+		Core->installMgr.setUserDisclaimerConfirmed(true);
+		Core->switchList(sbList::TYPE_MODULE_INSTALLER);
+		break;
+	case TYPE_INSTALLER_DISCLAIMER_DECLINE: Core->switchList(sbList::TYPE_SELECT_MODULE);      break;
+	//case TYPE_EXIT:
+	//	if (sbQueryBox(L"Do you want exit?")) sbExit(1);
+	//	break;
 
 	default:
 		{

Modified: trunk/src/SlideBible/sbControl.h
===================================================================
--- trunk/src/SlideBible/sbControl.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbControl.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -40,6 +40,7 @@
 		TYPE_OPEN_MODULE_SELECTION,
 		TYPE_OPEN_BOOK_SELECTION,
 		TYPE_OPEN_SEARCH,
+		TYPE_OPEN_SEARCH_2,
 		TYPE_OPEN_HOME,
 		TYPE_OPEN_TEXT,
 		TYPE_OPEN_BOOKMARKS,
@@ -60,10 +61,15 @@
 		TYPE_MENU_EXIT_YES,
 		TYPE_MENU_EXIT_NO,
 		TYPE_MENU_EXIT_MINIMIZE,
+		TYPE_OPEN_OPTIONS,
+		TYPE_WIDE_MODULES,
+		TYPE_INSTALLER_DISCLAIMER_ACCEPT,
+		TYPE_INSTALLER_DISCLAIMER_DECLINE,
 		TYPE_MENU_SET_VERSE,                                    // num verses
 		TYPE_MENU_SET_VERSE_MAX = TYPE_MENU_SET_VERSE + 200,
 		TYPE_SET_VERSE,                                         // activate verse
-		TYPE_SET_VERSE_MAX = TYPE_SET_VERSE + 200
+		TYPE_SET_VERSE_MAX = TYPE_SET_VERSE + 200,
+		TYPE_COUNT
 	};
 
 public:

Modified: trunk/src/SlideBible/sbCore.cpp
===================================================================
--- trunk/src/SlideBible/sbCore.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbCore.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -13,21 +13,23 @@
  * General Public License for more details.
  ************************************************************************/
 
+#include "sbCore.h"
+
 #include <markupfiltmgr.h>
 #include <localemgr.h>
 #include <SWBuf.h>
 #include <SWLog.h>
 
-#include "sbCore.h"
+#include <algorithm>
 
 #pragma warning(disable : 4018) // signed/unsigned mismatch
-#pragma warning(disable : 4244) // signed/unsigned mismatch
+#pragma warning(disable : 4244)
 
 // Globals
 sbCore * Core;
 sbList * sbCore::backgroundList;
 
-sbCore::sbCore ()
+sbCore::sbCore () : installMgr ("./install/",&installStatus)
 {
 	sbMessage ("Launch SlideBible Core.\n");
 	
@@ -38,31 +40,36 @@
 	time(&systemStarted);
 
 	// init data
-	currentList         = sbList::TYPE_HOME;
-	redrawTimerOn       = false;
-	requestedRedraw     = false;
+	currentList          = sbList::TYPE_HOME;
+	redrawTimerOn        = false;
+	requestedRedraw      = false;
 
-	listShift           = 0;
+	listShift            = 0;
 
-	showBanner          = false;
+	showBanner           = false;
 
-	backgroundThread    = NULL;
+	backgroundThread     = NULL;
 	
-	options             = NULL;
-	swordMgr            = NULL;
+	options              = NULL;
+	swordMgr             = NULL;
 
-	currentModule       = NULL;
+	fadeSurface          = false;
+	bScrollTimer         = false;
 
-	fadeSurface         = false;
-	bScrollTimer        = false;
+	swordMgr             = NULL;
+	currentModule        = NULL;
 
-	sword::SWLog::getSystemLog()->setLogLevel(5);
+	changedGlobalOptions = false;
 
+	waitMode             = false;
+
 	// load options
 	options = new sword::SWConfig(".\\options.conf");
 	sbAssert ( options == NULL );
 	options->Load();
 
+	sword::SWLog::getSystemLog()->setLogLevel(atoi((*options)["Sword"].getWithDefault("DebugLevel", "4")));
+
 	cineticDamping    = atof((*options)["Ui"].getWithDefault("CineticDamping", "0.95"));
 	cineticFactor     = atof((*options)["Ui"].getWithDefault("CineticFactor", "0.5"));
 	refreshRate       = 1000/atoi((*options)["Ui"].getWithDefault("RefreshRate", "30"));
@@ -70,9 +77,9 @@
 	versesMax         = atoi((*options)["Ui"].getWithDefault("versesMax", "500"));
 	versesOptimal     = atoi((*options)["Ui"].getWithDefault("versesOptimal", "50"));
 
-	showFps           = atoi((*options)["Ui"].getWithDefault("showFps", "1"));
+	showFps           = (bool)atoi((*options)["Ui"].getWithDefault("showFps", "0"));
 
-	stretchSurface    = atoi((*options)["Ui"].getWithDefault("stretchSurface", "0"));
+	stretchSurface    = (bool)atoi((*options)["Ui"].getWithDefault("stretchSurface", "0"));
 	stretchVertical   = atof((*options)["Ui"].getWithDefault("stretchVertical", "1.0"));
 	stretchHorizontal = atof((*options)["Ui"].getWithDefault("stretchHorizontal", "1.0"));
 
@@ -85,21 +92,8 @@
 		rClient.right  = rClient.width() * stretchHorizontal + rClient.left;
 	}
 
-	//surfaces[SURFACE::TYPE_WHOLE].rect = rClient;
+	theme.init();
 
-	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 -= theme.PanelSize;
-
-	surfaces[SURFACE::TYPE_BUFFER].rect = surfaces[SURFACE::TYPE_LIST].rect;
-
-	for (int i=0; i<SURFACE::COUNT; i++)
-	{
-		surfaces[i].hdc = sbSurfaceCreate(surfaces[i].rect.width(), surfaces[i].rect.height());
-		surfaces[i].needRedraw = true;
-	}*/
-
 	drawSurface = sbSurfaceCreate (rClient.width(), rClient.height());
 	
 	sbUpdateScreen();
@@ -107,26 +101,8 @@
 	// user locale
 	sword::LocaleMgr::getSystemLocaleMgr()->setDefaultLocaleName((*options)["General"].getWithDefault("Locale", sbGetLocale()));
 
-	// init sword
-	swordMgr = new sword::SWMgr(new sword::MarkupFilterMgr(sword::FMT_OSIS, sword::ENC_UTF16));
-	
-	sbAssert(swordMgr == NULL);
+	initSword();
 
-	defaultModule = swordMgr->getModule((*options)["General"].getWithDefault("DefaultModule", "KJV"));
-
-	if (defaultModule == NULL )
-	{
-		for (sword::ModMap::iterator it = swordMgr->Modules.begin(); it != swordMgr->Modules.end(); it++)
-		{
-			if (!strcmp((*it).second->Type(), "Biblical Texts"))
-			{
-				defaultModule = swordMgr->Modules.begin()->second;
-				break;
-			}
-		}
-	}
-
-	// restore features
 	features.load();
 
 	sbSetTimer( TIMER_SAVE_CONFIG, 5*60*1000 );
@@ -156,13 +132,10 @@
 	if (swordMgr != NULL) delete swordMgr;
 	if (options  != NULL) delete options;
 
-	//for (int i=0; i<SURFACE::COUNT; i++)
-	//{
-	//	sbSurfaceDestroy(surfaces[i].hdc);
-	//}
-
 	sbSurfaceDestroy(drawSurface);
 
+	for (int i=0; i < strings.size(); i++) free((char*)strings[i]);
+
 	sbMessage ("Shutdown SlideBible Core.\n");
 }
 
@@ -248,6 +221,17 @@
 		sbDrawText(drawSurface, 4, 3, text, _tcslen(text));
 	}
 
+	if (waitMode)
+	{
+		sbPoint s = sbGetTextExtent(theme.styles[sbTheme::STYLE::TEXT].font,waitMessage, _tcslen(waitMessage));
+		s.x = (rClient.width()-s.x)/2;
+		s.y = rClient.height()-theme.PanelSize-(s.y*1.5f);
+
+		sbSelectFont(drawSurface,theme.styles[sbTheme::STYLE::TEXT].font);
+		sbSelectColor(drawSurface, Core->getTheme()->fadeColor(Core->getTheme()->ItemSubTextColor, s.x, s.y));
+		sbDrawText(drawSurface, s.x, s.y, waitMessage, _tcslen(waitMessage));
+	}
+
 	if (stretchSurface)
 	{
 		sbRect rect;
@@ -260,9 +244,6 @@
 
 void sbCore::onMouse ( int x, int y, const int state )
 {
-	static int scrolldatay [2];
-	static int scrolldataticks [2];
-
 	keypadController = false;
 
 	if (stretchSurface)
@@ -291,8 +272,8 @@
 
 		sbSetTimer(TIMER_TAP, 1000/10);
 
-		scrolldatay[0]     = y;
-		scrolldataticks[0] = sbGetTickCount();
+		input.scrollDataY[0]     = y;
+		input.scrollDataTicks[0] = sbGetTickCount();
 	}
 	else if ( state == MSG_MOUSE_MOVE )
 	{
@@ -310,13 +291,13 @@
 			input.tapCounter = 0;
 		}
 
-		scrolldataticks[1] = sbGetTickCount();
-		scrolldatay[1]     = y;
+		input.scrollDataTicks[1] = sbGetTickCount();
+		input.scrollDataY[1]     = y;
 
-		if (scrolldataticks[1] - scrolldataticks[0] > 200)
+		if (input.scrollDataTicks[1] - input.scrollDataTicks[0] > 200)
 		{
-			scrolldatay[0]     = scrolldatay[1] + (int)((scrolldatay[0]-scrolldatay[1]) * (200.0f/(scrolldataticks[1]-scrolldataticks[0])));
-			scrolldataticks[0] = scrolldataticks[1] - 200;
+			input.scrollDataY[0]     = input.scrollDataY[1] + (int)((input.scrollDataY[0]-input.scrollDataY[1]) * (200.0f/(input.scrollDataTicks[1]-input.scrollDataTicks[0])));
+			input.scrollDataTicks[0] = input.scrollDataTicks[1] - 200;
 		}
 
 		if (lists[currentList] != NULL)
@@ -345,22 +326,24 @@
 	{
 		if (!input.mousePressed) return;
 
-		scrolldataticks[1] = sbGetTickCount();
-		scrolldatay[1]     = y;
+		input.scrollDataTicks[1] = sbGetTickCount();
+		input.scrollDataY[1]     = y;
 
-		if (scrolldataticks[1] - scrolldataticks[0] > 200)
+		if (input.scrollDataTicks[1] - input.scrollDataTicks[0] > 200)
 		{
-			scrolldatay[0]     = scrolldatay[1] + ((scrolldatay[0]-scrolldatay[1]) * (200.0f/(scrolldataticks[1]-scrolldataticks[0])));
-			scrolldataticks[0] = scrolldataticks[1] - 200;
+			input.scrollDataY[0]     = input.scrollDataY[1] + ((input.scrollDataY[0]-input.scrollDataY[1]) * (200.0f/(input.scrollDataTicks[1]-input.scrollDataTicks[0])));
+			input.scrollDataTicks[0] = input.scrollDataTicks[1] - 200;
 		}
 
-		float speed = (scrolldatay[1]-scrolldatay[0])/(float)max((scrolldataticks[1]-scrolldataticks[0]),120);
+		float speed = (input.scrollDataY[1]-input.scrollDataY[0])/(float)max((input.scrollDataTicks[1]-input.scrollDataTicks[0]),120);
 		
 		cineticPower = (speed*50.0f) + (cineticPower*min(fabs(speed)*200.0f/Core->getTheme()->size,1.0f));
 		
-		//sbMessage ("Ticks %i\t Y %i\t cineticPower %f\n", scrolldataticks[0], scrolldatay[0], cineticPower);
-		//sbMessage ("Ticks %i\t Y %i\t Duration %i\t Speed %f\n", scrolldataticks[1], scrolldatay[1],scrolldataticks[1]-scrolldataticks[0],speed);
+		sbMessage ("Ticks %i\t Y %i\t cineticPower %f\n", input.scrollDataTicks[0], input.scrollDataY[0], cineticPower);
+		sbMessage ("Ticks %i\t Y %i\t Duration %i\t Speed %f\n", input.scrollDataTicks[1], input.scrollDataY[1],input.scrollDataTicks[1]-input.scrollDataTicks[0],speed);
 
+		sbKillTimer ( TIMER_TAP );
+
 		if (lists[currentList] != NULL)
 		{
 			lists[currentList]->onReleased(x,y);
@@ -383,8 +366,6 @@
 
 		input.mousePressed = false;
 		input.tapCounter   = 0;
-
-		sbKillTimer ( TIMER_TAP );
 		
 		redraw();
 	}
@@ -404,6 +385,8 @@
 			features.save();
 
 			if (options != NULL) options->Save();
+
+			installMgr.saveInstallConf();
 		}
 		break;
 
@@ -554,31 +537,17 @@
 			switchList( sbList::TYPE_HOME );
 			return;
 		}
-
-		// fix hollow module view
-		/*if (type == sbList::TYPE_MODULE_VIEW && lists[type]->module == NULL)
-		{
-			if (lists[type]->getNext() != NULL && lists[type]->getNext()->module == currentModule && lists[type]->getNext()->place.Index() == currentVerse.Index())
-			{
-				lists[type] = lists[type]->getNext();
-			}
-			else if (lists[type]->getPrev() != NULL && lists[type]->getPrev()->module == currentModule && lists[type]->getPrev()->place.Index() == currentVerse.Index())
-			{
-				lists[type] = lists[type]->getPrev();
-			}
-			else if (lists[type]->getPrev() != NULL || lists[type]->getNext() != NULL)
-			{
-				sbAssert ( true );
-			}
-		}*/
 	}
 
 	currentList = type;
 
 	threadDestroy();
 
-	lists[currentList]->onActivate();
+	if (oldList != lists[currentList]) lists[currentList]->onActivate();
 
+	if (currentList == sbList::TYPE_MODULE_VIEW && lists[currentList]->module != NULL)
+		Core->threadCreate(lists[currentList]);
+
 	showBanner = oldList != NULL && lists[currentList] != NULL && oldList->type == sbList::TYPE_MODULE_VIEW && lists[currentList]->type == sbList::TYPE_MODULE_VIEW;
 
 	if (showBanner) sbSetTimer ( TIMER_BANNER , 5000 ); else sbKillTimer ( TIMER_BANNER );
@@ -591,10 +560,22 @@
 {
 	sbAssert ( backgroundList == NULL );
 
-	backgroundList->process ( abort );
+	//sbMessage ("threadMain : start\n");
+
+	// backgroundList can be with itemCurrent == NULL on first call
+	while (!*abort)
+	{
+		backgroundList->process ( abort );
+		sbSleep(5);
+	}
+	
+	sbAssert(*abort == false);
+
+	//sbMessage ("threadMain : end , abort %i\n", *abort);
 }
 
-void sbCore::threadCreate (sbList *list)
+
+void sbCore::threadCreate (sbList * list)
 {
 	sbMessage ("threadCreate\n");
 
@@ -636,3 +617,65 @@
 	if ( lists[currentList] != NULL && down ) lists[currentList]->onKey ( key );
 }
 
+const char * sbCore::holdString ( const char * string )
+{
+	if (string == NULL || strlen(string) == 0) return NULL;
+
+	for (int i=0; i < strings.size(); i++)
+	{
+		if (!strcmp(string,strings[i])) return strings[i];
+	}
+
+	strings.push_back(_strdup(string));
+
+	return strings.back();
+}
+
+void sbCore::initSword ()
+{
+	const char * curMod = currentModule == NULL ? NULL : holdString(currentModule->Name());
+
+	sbMessage ("Init Sword\n");
+
+	if (swordMgr != NULL) delete swordMgr;
+
+	swordMgr = new sword::SWMgr(new sword::MarkupFilterMgr(sword::FMT_OSIS, sword::ENC_UTF16));
+
+	sbAssert(swordMgr == NULL);
+
+	defaultModule = swordMgr->getModule((*options)["General"].getWithDefault("DefaultModule", "KJV"));
+
+	if (defaultModule == NULL )
+	{
+		for (sword::ModMap::iterator it = swordMgr->Modules.begin(); it != swordMgr->Modules.end(); it++)
+		{
+			if (!strcmp((*it).second->Type(), "Biblical Texts"))
+			{
+				defaultModule = swordMgr->Modules.begin()->second;
+				break;
+			}
+		}
+	}
+
+	if (defaultModule != NULL)
+	{
+		currentVerse.copyFrom(defaultModule->getKey());
+
+		sword::StringList sl = swordMgr->getGlobalOptions();
+
+		for (sword::StringList::iterator it = sl.begin(); it != sl.end(); it++)
+		{
+			const char * option = holdString(*it);
+
+			std::vector<const char *>::iterator f = std::find(moduleOptions.begin(),moduleOptions.end(),option);
+			
+			if (f == moduleOptions.end()) moduleOptions.push_back(option);
+
+#ifdef _DEBUG
+			swordMgr->setGlobalOption(option,"On");
+#endif
+		}
+	}
+
+	currentModule = curMod == NULL ? NULL : swordMgr->getModule( curMod );
+}

Modified: trunk/src/SlideBible/sbCore.h
===================================================================
--- trunk/src/SlideBible/sbCore.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbCore.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -23,28 +23,12 @@
 #include "sbList.h"
 #include "sbFeatures.h"
 
+#include <installmgr.h>
+#include <ftptrans.h>
+
 class sbCore
 {
-public:
-	/*struct SURFACE
-	{
-		SURFACE () : fade ( false ) , needRedraw ( false ) { ; }
-
-		enum TYPE
-		{
-			TYPE_LIST = 0,
-			TYPE_BUFFER,
-			TYPE_WHOLE,
-			COUNT
-		};
-		
-		sbSurface          hdc;
-		sbRect                   rect;
-		
-		bool                     needRedraw;
-		mutable bool             fade;
-	};*/
-	
+public:	
 	struct INPUT
 	{
 		INPUT () { memset (this,0,sizeof(INPUT)); }
@@ -57,6 +41,9 @@
 		int                      tapCounter;
 
 		mutable bool             block;
+
+		int                      scrollDataY [2];
+		int                      scrollDataTicks [2];
 	};
 
 	enum TIMER
@@ -84,9 +71,10 @@
 	const sbTheme *              getTheme         ()                     {return &theme;}
 	sword::SWMgr *               getSword         ()                     {return swordMgr;}
 	sword::SWConfig *            getOptions       ()                     {return options;}
-	//const SURFACE *              getSurface       ( SURFACE::TYPE type ) {return &surfaces[type];}
 	const INPUT *                getInput         ()                     {return &input;}
 	const sbRect &               getRect          ()                     {return rClient;}
+
+	void                         initSword        ();
 	
 	void                         switchList       ( sbList::TYPE to );
 
@@ -95,6 +83,8 @@
 	
 	void                         controlPressed   ( sbControl::TYPE type );
 
+	const char *                 holdString     ( const char * string );
+
 private:
 	sbThread                     backgroundThread;
 
@@ -104,12 +94,11 @@
 	sbList::TYPE                 currentList;
 	sbList::TYPE                 overlayList;
 
-	std::map < sbList::TYPE , sbList * >   lists;
+	std::map<sbList::TYPE,sbList *> lists;
 
 	int                          listShift;
 
 	float                        cineticPower;
-	//int                          cineticTicks;
 
 	INPUT                        input;
 
@@ -128,8 +117,6 @@
 	float                        stretchVertical;
 	float                        stretchHorizontal;
 	
-	//SURFACE                      surfaces[SURFACE::COUNT]; // CUT
-
 	sword::SWMgr                *swordMgr;
 	sword::SWConfig             *options;
 
@@ -140,7 +127,11 @@
 	bool                         showBanner;
 	bool                         showFps;
 
+	std::vector<const char*>     strings;
+
 public:
+	sword::InstallMgr            installMgr;
+	sword::StatusReporter        installStatus;
 
 	sbFeatures                   features;
 
@@ -151,16 +142,24 @@
 	unsigned int                 versesOptimal;
 
 	// Core shared data
-	sword::SWModule             *defaultModule;     // base module for all new module views
-	sword::SWModule             *currentModule;     // module of active list, null if module view was not activated
+	sword::SWModule             *defaultModule;          // base module for all new module views
+	sword::SWModule             *currentModule;          // module of active list, null if module view was not activated
 
-	sword::VerseKey              currentVerse;      // last place
+	sword::VerseKey              currentVerse;           // last place
 
-	bool                         goVerse;           // necessity of transition, with currentVerse and currentModule
-	int                          goReading;         // need attach reading on activate, default -1
+	bool                         goVerse;                // necessity of transition, with currentVerse and currentModule
+	int                          goReading;              // need attach reading on activate, default -1
+	bool                         changedGlobalOptions;   // fixes : Global Options switch in one module cause switch in another
 
 	time_t                       systemStarted;
-	bool                         keypadController;  // whether user control with keypad / touchscreen
+	bool                         keypadController;       // whether user control with keypad / touchscreen
+
+	std::vector<const char *>    moduleOptions;          // array of option names
+
+	sword::ListKey               searchRange;
+
+	bool                         waitMode;
+	const TCHAR                 *waitMessage;
 };
 
 extern sbCore * Core;

Modified: trunk/src/SlideBible/sbFeatures.cpp
===================================================================
--- trunk/src/SlideBible/sbFeatures.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbFeatures.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -29,23 +29,9 @@
 
 sbFeatures::~sbFeatures()
 {
-	for (int i=0; i<strings.size(); i++) free((char*)strings[i]);
+	//for (int i=0; i<strings.size(); i++) free((char*)strings[i]);
 }
 
-const char * sbFeatures::holdString (const char * string)
-{
-	if (string == NULL || strlen(string) == 0) return NULL;
-
-	for (int i=0; i < strings.size(); i++)
-	{
-		if (!strcmp(string,strings[i])) return strings[i];
-	}
-
-	strings.push_back(_strdup(string));
-
-	return strings.back();
-}
-
 void sbFeatures::load ()
 {
 	if (Core->defaultModule == NULL) return;
@@ -75,7 +61,7 @@
 					XMLNode n = xh.getChildNode("history",i);
 					History h;
 
-					h.module     = holdString(n.getAttribute("module"));
+					h.module     = Core->holdString(n.getAttribute("module"));
 					h.visitStart = atol(n.getAttribute("visitStart"));
 					h.visitEnd   = atol(n.getAttribute("visitEnd"));
 					h.placeStart = atol(n.getAttribute("placeStart"));
@@ -91,7 +77,7 @@
 void sbFeatures::save()
 {
 	if (Core->defaultModule == NULL) return;
-
+	
 	XMLNode xml = XMLNode::createXMLTopNode("xml",true);
 
 	char buf [32];
@@ -105,7 +91,8 @@
 
 	XMLNode xh = xf.addChild("History");
 
-	for (int i=0; i < history.size(); i++)
+	// limit history to 100 entries
+	for (int i = max(100,history.size())-100; i < history.size(); i++)
 	{
 		XMLNode n = xh.addChild("history");
 

Modified: trunk/src/SlideBible/sbFeatures.h
===================================================================
--- trunk/src/SlideBible/sbFeatures.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbFeatures.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -59,15 +59,13 @@
 
 	void                      dump ();
 
-	const char *              holdString     ( const char * string );
-
 	static const int          revision;
 
 	//std::vector<Reading>      readings;
 	std::vector<History>      history;
 
-private:
-	std::vector<const char*>  strings;
+//private:
+//	std::vector<const char*>  strings;
 
 };
 

Modified: trunk/src/SlideBible/sbItem.cpp
===================================================================
--- trunk/src/SlideBible/sbItem.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbItem.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -16,10 +16,16 @@
 #include "sbCore.h"
 #include "sbItem.h"
 
+#pragma warning(disable : 4018) // signed/unsigned mismatch
+
 sbItem::sbItem ( sbItem::TYPE _type_, const TCHAR *_text_, int _width_, long _index_, int _number_ )
 : type  ( _type_ )
 , width ( _width_ )
 , index ( _index_ )
+, next  (NULL)
+, prev  (NULL)
+, left  (NULL)
+, right (NULL)
 {
 	if ( _number_ != -1 )
 	{
@@ -41,6 +47,12 @@
 	
 	switch ( type )
 	{
+	case TYPE_CENTRED_DESCRIPTION:
+		center = true;
+		style = sbTheme::STYLE::DESCRIPTION;
+		lines.reserve(1);
+		break;
+
 	case TYPE_DESCRIPTION:
 	case TYPE_BUTTON_CHAPTER_NEXT:
 	case TYPE_BUTTON_CHAPTER_PREV:
@@ -51,25 +63,45 @@
 	case TYPE_CHECKBOX:
 		center = true;
 
+	case TYPE_MODULE_INSTALLER_MODULE:
+	case TYPE_MODULE_INSTALLER_UPDATE:
+	case TYPE_SEARCH_RANGE_START:
+	case TYPE_SEARCH_RANGE_END:
+		style = sbTheme::STYLE::BUTTON;
+		break;
+
 	case TYPE_BUTTON_BOOKMARK:
 	case TYPE_BUTTON_SELECTION_BOOK:
 	case TYPE_BUTTON_SELECTION_CHAPTER:
 	case TYPE_BUTTON_SELECTION_MODULE:
+	case TYPE_SWITCH_MODULE_OPTION:
+	case TYPE_OPEN_MODULE_INSTALLER:
+	case TYPE_START_SEARCH:
+	case TYPE_TEXT_FIELD:
 		style = sbTheme::STYLE::BUTTON;
 		lines.reserve(2);
+		center = true;
 		break;
 
 	case TYPE_BUTTON_BOOKMARK_SMALL:
 		style = sbTheme::STYLE::BUTTON_SMALL;
 		lines.reserve(2);
+		center = true;
 		break;
 
 	case TYPE_HEADER:
+	case TYPE_MODULE_INSTALLER_REPO:
 		style = sbTheme::STYLE::CAPTION;
 		center = true;
 		lines.reserve(1);
 		break;
 
+	case TYPE_GOTO_MODULES:
+	case TYPE_GO_HISTORY:
+		style = sbTheme::STYLE::TEXT;
+		center = true;
+		break;
+
 	default:
 		style = sbTheme::STYLE::TEXT;
 	}
@@ -78,11 +110,6 @@
 	height      = Core->getTheme()->styles[style].size + Core->getTheme()->itemMargins.top + Core->getTheme()->itemMargins.bottom;
 	expanding   = 0;
 
-	next  = NULL;
-	prev  = NULL;
-	left  = NULL;
-	right = NULL;
-
 	processed = false;
 
 	if ( _text_ != NULL ) setText ( _text_ );
@@ -175,6 +202,8 @@
 	bool skip = false,  italic = false;
 	sbFont font = Core->getTheme()->styles[style].font;
 
+	bool manualLines = false;
+	
 	char changeStyle = style;
 
 	LINE currentLine;
@@ -183,17 +212,35 @@
 	currentLine.pos     = 0;
 	currentLine.count   = 0;
 	currentLine.width   = 0;
-	currentLine.height  = 0;     // only last line, with newLine = true, contains most large height
-	currentLine.newLine = false; // should be false always
+	currentLine.height  = 0;     // only last line, with ending = true, contains most large height
+	currentLine.ending  = false; // last text part in line
 
+	// TODO: std::vector<int[3]> (start line position, end line position, begin of <w> tag)
+	std::vector<LINE> underline;
+
 	sbAssert( _text_ == NULL );
-	
-	if ( ! lines.empty() ) lines.clear();
 
+	if (!lines.empty())
+		lines.clear();
+
+	text = _text_;
+
+	switch (type)
+	{
+	case TYPE_BANNER:
+	case TYPE_HISTORY:
+	case TYPE_SEARCH_RANGE_START:
+	case TYPE_SEARCH_RANGE_END:
+		manualLines = true;
+		break;
+	}
+
+	// parse text
 	for(int i=0; i<length; i++)
 	{
 		TCHAR c = *(_text_+i);
 
+		// process xml tags here
 		if (c == L'<')
 		{
 			if (currentLine.count > 0)
@@ -216,19 +263,131 @@
 				// TODO push from stack
 				currentLine.style = style;
 			}
-			else if (_tcsncmp(_text_+i+1,L"s ",2) == 0)
+			else if (_tcsncmp(_text_+i+1,L"w ",2) == 0)
 			{
-				if (_tcsncmp(_text_+i+1,L"s t=\"6\"",7) == 0)
-					currentLine.style = sbTheme::STYLE::DESCRIPTION;
-				else if (_tcsncmp(_text_+i+1,L"s t=\"5\"",7) == 0)
-					currentLine.style = sbTheme::STYLE::CAPTION;
+				if ( underline.size() == 0 && lineWidth > 0)
+				{
+					underline.push_back(LINE());
+					underline.back().width = lineWidth;
+				}
 				else
-					sbAssert( true );
+				{
+					int width = 0;
+					for (int i = 0; i < underline.size(); i++) width += underline[i].width;
+
+					if (width < lineWidth)
+					{
+						underline.push_back(LINE());
+						underline.back().width = lineWidth - width;
+					}
+				}
+
+				bool lemma = false;
+				bool morph = false;
+
+				for (int ii = i+3; ii < length && _text_[ii] != L'>'; ii++)
+				{
+
+					if (_tcsncmp(_text_+ii,L"lemma=\"",7) == 0)
+					{
+						ii += 7;
+						lemma = true;
+					}
+					else if (_tcsncmp(_text_+ii,L"morph=\"",7) == 0)
+					{
+						ii += 7;
+						morph = true;
+					}
+
+					if (_tcsncmp(_text_+ii,L"strong:",7) == 0)
+					{
+						sbAssert(!lemma);
+						ii += 7;
+						for (int e = ii;;e++)
+						{
+							if (_text_[e] == L' ' || _text_[e] == L'\"')
+							{
+								underline.push_back(LINE());
+								underline.back().pos = ii;
+								underline.back().type = LINE::STRONG;
+								underline.back().count = e-ii;
+								underline.back().height = Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].size;
+								underline.back().style = sbTheme::STYLE::TEXT_UNDER;
+								underline.back().width = sbGetTextExtent(Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].font,_text_+ii,e-ii).x;
+								underline.back().width += sbGetTextExtent(Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].font,L" ",1).x;
+
+								ii = e;
+								break;
+							}
+						}
+					}
+					else if (_tcsncmp(_text_+ii,L"strongMorph:",12) == 0)
+					{
+						sbAssert(!morph);
+						ii += 12;
+						for (int e = ii;;e++)
+						{
+							if (_text_[e] == L' ' || _text_[e] == L'\"')
+							{
+								underline.push_back(LINE());
+								underline.back().pos = ii;
+								underline.back().type = LINE::MORPH;
+								underline.back().count = e-ii;
+								underline.back().height = Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].size;
+								underline.back().style = sbTheme::STYLE::TEXT_UNDER;
+								underline.back().width = sbGetTextExtent(Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].font,_text_+ii,e-ii).x;
+								underline.back().width += sbGetTextExtent(Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].font,L" ",1).x;
+
+								ii = e;
+								break;
+							}
+						}
+					}
+					else if (_tcsncmp(_text_+ii,L"robinson:",9) == 0)
+					{
+						sbAssert(!morph);
+						ii += 9;
+						for (int e = ii;;e++)
+						{
+							if (_text_[e] == L' ' || _text_[e] == L'\"')
+							{
+								underline.push_back(LINE());
+								underline.back().pos = ii;
+								underline.back().type = LINE::MORPH;
+								underline.back().count = e-ii;
+								underline.back().height = Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].size;
+								underline.back().style = sbTheme::STYLE::TEXT_UNDER;
+								underline.back().width = sbGetTextExtent(Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].font,_text_+ii,e-ii).x;
+								underline.back().width += sbGetTextExtent(Core->getTheme()->styles[sbTheme::STYLE::TEXT_UNDER].font,L" ",1).x;
+
+								ii = e;
+								break;
+							}
+						}
+					}
+				}
 			}
+			else if (_tcsncmp(_text_+i+1,L"s ",2) == 0)
+			{
+				for (int ii = i+2; ii < length && _text_[ii] != L'>'; ii++)
+				{
+					if (_tcsncmp(_text_+ii,L" t=",3) == 0)
+					{
+						if      (_tcsncmp(_text_+ii+3,L"\"6\"",3) == 0) currentLine.style = sbTheme::STYLE::DESCRIPTION;
+						else if (_tcsncmp(_text_+ii+3,L"\"5\"",3) == 0) currentLine.style = sbTheme::STYLE::CAPTION;
+						else if (_tcsncmp(_text_+ii+3,L"\"4\"",3) == 0) currentLine.style = sbTheme::STYLE::STANZA;
+						else if (_tcsncmp(_text_+ii+3,L"\"1\"",3) == 0) currentLine.style = sbTheme::STYLE::TEXT_ITALIC;
+						else sbAssert (true);
+
+						ii += 6;
+					}
+				}
+			}
 			else if (_tcsncmp(_text_+i+1,L"/s>",3) == 0)
 			{
 				// TODO push from stack
 				currentLine.style = style;
+				currentLine.type = LINE::TYPE::NONE;
 			}
 		}
 		else if (skip && c == L'>')
@@ -240,8 +399,16 @@
 			lineWidth = 0;
 
 			lines.push_back(currentLine);
-			lines.back().newLine = true;
+			lines.back().ending = true;
 
+			// finish line, sync code
+			if (underline.size())
+			{
+				for (int i = 0; i < underline.size(); i++) lines.push_back(underline[i]);
+				underline.clear();
+				lines.back().ending = true;
+			}
+
 			currentLine.count = currentLine.width = currentLine.height = 0;
 		}
 		else if (!skip)
@@ -256,15 +423,26 @@
 				currentLine.pos = i;
 			}
 			
+			// TODO determine is last symbol, next symbol must be one of "\n <"
+			// TODO break lines if sz.x + lineWidth >= width-Core->getTheme()->itemMargins.left
+
 			// line will be too long, divide lines
 			if ((lineWidth + sz.x > width-Core->getTheme()->itemMargins.left-Core->getTheme()->itemMargins.right) \
-				&& c != L'.' && c != L',' && c != L' ')
+				&& c != L'.' && c != L',' && c != L' ' && c != L'!' && c != L'?' && c != L';' && c != L':' && !manualLines)
 			{
+				lines.push_back(currentLine);
+				lines.back().ending = true;
+
+				// finish line, sync code
+				if (underline.size())
+				{
+					for (int i = 0; i < underline.size(); i++) lines.push_back(underline[i]);
+					underline.clear();
+					lines.back().ending = true;
+				}
+
 				lineWidth = 0;
 
-				lines.push_back(currentLine);
-				lines.back().newLine = true;
-
 				currentLine.count = currentLine.width = currentLine.height = 0;
 			}
 
@@ -282,47 +460,83 @@
 
 			lineWidth += (unsigned short) sz.x;
 		}
+
+		// TODO: process end of line here
 	}
 
 	if (currentLine.count > 0)
 	{
 		lines.push_back(currentLine);
-		lines.back().newLine = true;
+		lines.back().ending = true;
 	}
 	else if (lines.size() > 0)
 	{
-		lines.back().newLine = true;
+		lines.back().ending = true;
 	}
 
-	height = Core->getTheme()->itemMargins.top + Core->getTheme()->itemMargins.bottom;
+	// finish line, sync code
+	if (underline.size())
+	{
+		for (int i = 0; i < underline.size(); i++) lines.push_back(underline[i]);
+		underline.clear();
+		lines.back().ending = true;
+	}
 
 	if (type == sbItem::TYPE_HISTORY)
 	{
+		height = Core->getTheme()->itemMargins.top + Core->getTheme()->itemMargins.bottom;
 		height += max (Core->getTheme()->styles[sbTheme::STYLE::CAPTION].size,Core->getTheme()->styles[sbTheme::STYLE::TEXT].size+Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].size);
 	}
-	else
+	else if (type == TYPE_BANNER && lines.size() == 2)
 	{
-		for (int i=0; i<lines.size(); i++) if (lines[i].newLine) height += lines[i].height;
+		height = (Core->getTheme()->BannerBorderSize * 2) + Core->getTheme()->styles[lines[0].style].size + Core->getTheme()->styles[lines[1].style].size;
 	}
+	else if (type == TYPE_SEARCH_RANGE_START || type == TYPE_SEARCH_RANGE_END)
+	{
+		height = Core->getTheme()->itemMargins.top + Core->getTheme()->itemMargins.bottom + lines[0].height;
+		width  = Core->getTheme()->itemMargins.left + Core->getTheme()->itemMargins.left + lines[0].width;
 
-	// hack to make space for buttons
-	if ((style == sbTheme::STYLE::BUTTON || style == sbTheme::STYLE::BUTTON_SMALL) && height < Core->getTheme()->size/6)
+		if (height < Core->getTheme()->size/6)
+		{
+			lines.insert(lines.begin(),LINE(style,true,0,((Core->getTheme()->size/6)-height)/2));
+			height = Core->getTheme()->size/6;
+		}
+	}
+	else
 	{
-		lines.insert(lines.begin(),LINE(style,true,0,((Core->getTheme()->size/6)-height)/2));
-		height = Core->getTheme()->size/6;
+		height = Core->getTheme()->itemMargins.top + Core->getTheme()->itemMargins.bottom;
+
+		if (type == TYPE_TEXT_FIELD && lines.size() == 0) height += Core->getTheme()->styles[style].size;
+
+		for (int i=0; i<lines.size(); i++) if (lines[i].ending) height += lines[i].height;
+		
+		// hack to make space for buttons
+		if ((style == sbTheme::STYLE::BUTTON || style == sbTheme::STYLE::BUTTON_SMALL) && height < Core->getTheme()->size/6)
+		{
+			lines.insert(lines.begin(),LINE(style,true,0,((Core->getTheme()->size/6)-height)/2));
+			height = Core->getTheme()->size/6;
+		}
 	}
-	
-	text = _text_;    // need to be set last
-
-	// processed = true; // maybe i do not need it ?
 }
 
 void sbItem::render ( sbSurface surface, const sbRect & rect, sbTheme::ELEMENT::TYPE element ) const
 {
 	Core->getTheme()->drawElement( surface, &rect, element );
 
-	if (type == sbItem::TYPE_HISTORY)
+	if (type == sbItem::TYPE_BANNER)
 	{
+		sbAssert (lines.size() != 2);
+
+		sbSelectColor(surface, Core->getTheme()->fadeColor(Core->getTheme()->elements[sbTheme::ELEMENT::BANNER].textColor,rect.left,rect.top));
+
+		sbSelectFont (surface, Core->getTheme()->styles[lines[0].style].font);
+		sbDrawText   (surface, rect.left + Core->getTheme()->BannerBorderSize, rect.top + Core->getTheme()->BannerBorderSize, text.c_str() + lines[0].pos, lines[0].count);
+
+		sbSelectFont (surface, Core->getTheme()->styles[lines[1].style].font);
+		sbDrawText   (surface, rect.left + Core->getTheme()->BannerBorderSize, rect.top + Core->getTheme()->BannerBorderSize + lines[0].height, text.c_str() + lines[1].pos, lines[1].count);
+	}
+	else if (type == sbItem::TYPE_HISTORY)
+	{
 		sbAssert (lines.size() != 3);
 
 		sbSelectFont (surface, Core->getTheme()->styles[lines[0].style].font);
@@ -357,17 +571,18 @@
 
 			for (int i=0; i < lines.size(); i++)
 			{
+				if (center && lx == 0)
+				{
+					int w = 0;
+					for (int ii=i; ii < lines.size(); ii++) if (lines[ii].ending) { w += lines[ii].width; break; } else w += lines[ii].width;
+					lx += (rect.width()-Core->getTheme()->itemMargins.left-Core->getTheme()->itemMargins.right - w)/2;
+				}
+
 				int x = lx + Core->getTheme()->itemMargins.left + rect.left;
 				int y = ly;
 
-				// possible BUG with center alignment and many text parts
-				if (center)
+				if (lines[i].ending)
 				{
-					x += (rect.width()-Core->getTheme()->itemMargins.left-Core->getTheme()->itemMargins.right-lines[i].width)/2;
-				}
-
-				if (lines[i].newLine)
-				{
 					lx = 0;
 					ly += lines[i].height;
 				}
@@ -381,8 +596,23 @@
 				if (y >= rect.bottom) break;                                                        // clip bottom
 
 				sbSelectFont(surface, Core->getTheme()->styles[lines[i].style].font);
-				sbSelectColor(surface, Core->getTheme()->fadeColor(Core->getTheme()->elements[element].textColor,x,y));
 
+				switch (lines[i].type)
+				{
+				case sbItem::LINE::TYPE::NONE:
+					sbSelectColor(surface, Core->getTheme()->fadeColor(Core->getTheme()->elements[element].textColor,x,y));
+					break;
+				case sbItem::LINE::TYPE::STRONG:
+					sbSelectColor(surface, Core->getTheme()->fadeColor(Core->getTheme()->ItemStrongColor,x,y));
+					break;
+				case sbItem::LINE::TYPE::MORPH:
+					sbSelectColor(surface, Core->getTheme()->fadeColor(Core->getTheme()->ItemMorphColor,x,y));
+					break;
+				case sbItem::LINE::TYPE::WORDS_OF_CHRIST:
+					sbSelectColor(surface, Core->getTheme()->fadeColor(Core->getTheme()->ItemRedColor,x,y));
+					break;
+				}
+
 				sbDrawText (surface, x, y, text.c_str() + lines[i].pos, lines[i].count);
 			}
 		}
@@ -400,7 +630,7 @@
 
 				sbDrawText (surface, pos.x, pos.y, subtext.c_str(), subtext.size());
 			}
-			else if ( type != sbItem::TYPE_SPACE )
+			else if ( type != sbItem::TYPE_SPACE && type != sbItem::TYPE_TEXT_FIELD )
 			{
 				sbAssert(true);
 			}

Modified: trunk/src/SlideBible/sbItem.h
===================================================================
--- trunk/src/SlideBible/sbItem.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbItem.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -63,10 +63,12 @@
 		TYPE_ICON,
 		TYPE_TEXT,
 		TYPE_DESCRIPTION,                   // small text
+		TYPE_CENTRED_DESCRIPTION,
 		TYPE_VERSE,                         // linked to verse, versification?
 		TYPE_TEXT_WITH_DESCRIPTION,
-		TYPE_TEXT_FIELD,                    // this will require SIP, i think we will controll input panel, default input panel will be selected in options
+		TYPE_TEXT_FIELD,
 		TYPE_CHECKBOX,
+		TYPE_SWITCH_MODULE_OPTION,
 		TYPE_BUTTON_CHAPTER_NEXT,
 		TYPE_BUTTON_CHAPTER_PREV,
 		TYPE_BUTTON_SELECTION_MODULE,
@@ -87,12 +89,49 @@
 		TYPE_GOTO_MODULES,
 		TYPE_GO_HISTORY,
 		TYPE_HISTORY,
-		TYPE_GO_READING
+		TYPE_OPEN_MODULE_INSTALLER,
+		TYPE_MODULE_INSTALLER_REPO,
+		TYPE_MODULE_INSTALLER_MODULE,
+		TYPE_MODULE_INSTALLER_UPDATE,
+		TYPE_START_SEARCH,
+		TYPE_SEARCH_RANGE_START,
+		TYPE_SEARCH_RANGE_END,
+		TYPE_GO_READING,
+		TYPE_BANNER
 	};
+
+	// Types
+	enum LOOK
+	{
+		LOOK_NONE = 0,
+		LOOK_TEXT,
+		LOOK_DESCRIPTION,
+		LOOK_CAPTION,
+		LOOK_CHECK_BUTTON,
+		LOOK_INPUT_TEXT,
+		LOOK_SEPARATOR,
+		LOOK_PANEL,
+		LOOK_MENU,
+		LOOK_COUNT
+	};
+
+	enum DO
+	{
+		DO_NONE = 0,
+		DO_CHANGE_PLACE,
+		DO_CHANGE_VIEW,
+		DO_SIP_RAISE,
+		DO_COUNT
+	};
+
+	static sbItem * addText (sbItem * parent, const TCHAR * text);
+	static sbItem * add (DO action, LOOK view, const TCHAR * text, sbRect place, long parameter = -1);
 	
+	// hide
 	sbItem( sbItem::TYPE type, const TCHAR * text, int width, long index = -1, int number = -1 );
 	~sbItem();
 
+																		           /* remove */
 	void                          render ( sbSurface surface, const sbRect & rect, sbTheme::ELEMENT::TYPE element ) const;
 
 	const TYPE                    type;
@@ -104,7 +143,9 @@
 	bool                          processed;
 
 	bool                          center;
+
 	bool                          highlighted;
+	bool                          active;
 	
 	unsigned short                height;
 	unsigned short                width;
@@ -113,17 +154,25 @@
 	
 	struct LINE
 	{
-		LINE ( char _style_ = 0, bool _newLine_ = false , unsigned short _width_ = 0 ,unsigned short _height_ = 0 ,  unsigned short _pos_ = 0,
-			unsigned short _count_ = 0 ) : pos (_pos_) , width (_width_) , height (_height_) ,
-			style (_style_) , count (_count_) , newLine (_newLine_) { ; }
+		LINE ( char _style_ = 0, bool _newLine_ = false , unsigned short _width_ = 0 ,unsigned short _height_ = 0 ,  unsigned short _pos_ = 0, unsigned short _count_ = 0 ) :
+			pos (_pos_) , width (_width_) , height (_height_) , style (_style_) , count (_count_) , ending (_newLine_) , type (0) { ; }
 
+		enum TYPE
+		{
+			NONE = 0,
+			STRONG,
+			MORPH,
+			WORDS_OF_CHRIST,
+			BREAKING_LINE
+		};
+
 		unsigned short            pos;
+		unsigned short            count;
 		unsigned short            width;
 		unsigned short            height;
 		char                      style;
-		unsigned short            count;
-
-		bool                      newLine;
+		char                      type;
+		bool                      ending:1;
 	};
 
 	std::vector<LINE>             lines;
@@ -131,7 +180,9 @@
 	void                          setText       ( const TCHAR * text );
 
 	long                          index;
+	//void                         *parameter;
 
+	// remove
 	enum PIN
 	{
 		NEXT, PREV, LEFT, RIGHT

Modified: trunk/src/SlideBible/sbList.cpp
===================================================================
--- trunk/src/SlideBible/sbList.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbList.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -17,13 +17,206 @@
 #include <swversion.h>
 #include <time.h>
 
+#include <algorithm>
 
+
 #pragma warning ( disable : 4018 )
 #pragma warning ( disable : 4996 )
 
+// Simple cacher for sbItem
+class sbDrawCache
+{
+public:
+	struct CACHE
+	{
+		sbItem               *item;
+		sbRect                rect;
+		int                   used;
+
+		bool operator < (const CACHE & other) const
+		{
+			if (rect.top < other.rect.top)
+				return true;
+			return false;
+		}
+	};
+
+	sbDrawCache ()
+	{
+		initialized = false;
+		surface     = NULL;
+	}
+
+	~sbDrawCache()
+	{
+		if (surface != NULL) sbSurfaceDestroy(surface);
+	}
+
+
+	bool blit (sbSurface surf, sbItem * item, sbRect & rect)
+	{
+		// can place in cache
+		if (!initialized) return false;
+
+		// check if cached
+		for ( std::list<CACHE>::iterator it = cache.begin(); it != cache.end(); it++ )
+		{
+			if ( (*it).item == item )
+			{
+				if (debug) sbMessage ("In cache %i [%i,%i] used %i\n",(*it).item,(*it).rect.top,(*it).rect.bottom,(*it).used);
+
+				if ((*it).used < -500) return false;
+
+				(*it).used += 3;
+				sbBitBlt(surf,rect,surface,sbPoint((*it).rect.left,(*it).rect.top));
+				return true;
+			}
+		}
+
+		// try cache
+		sbRect place (0,0,item->width,item->height);
+
+		for (std::list<CACHE>::iterator it = cache.begin() ; it != cache.end(); it++ )
+		{
+			if ( !(place.top > (*it).rect.bottom || place.bottom < (*it).rect.top) )
+			{
+				if (debug) sbMessage ("Move place in cache from %i to %i\n",place.top,(*it).rect.bottom+1);
+
+				place.top = (*it).rect.bottom+1;
+				place.bottom = place.top + item->height;
+			}
+			else
+				break;
+		}
+
+		if (place.bottom > height)
+		{
+			if (debug) sbMessage ("Cache full\n");
+			full = true;
+			return false;
+		}
+
+		// place in cache
+		CACHE ci;
+		ci.item = item;
+		ci.used = 15;
+		ci.rect = place;
+
+		cache.push_back(ci);
+
+		cache.sort();
+
+		if (debug) sbMessage ("Place in cache %i [%i,%i]\n",ci.item,ci.rect.top,ci.rect.bottom);
+
+		item->render(surface,ci.rect,item->type == sbItem::TYPE_BANNER ? sbTheme::ELEMENT::BANNER : sbTheme::ELEMENT::ITEM);
+		//sbFillRect(surface,&sbRect(ci.rect.right-20,ci.rect.top,ci.rect.right,ci.rect.top+20),sbColor("FF0066FF"));
+		sbBitBlt(surf,rect,surface,sbPoint(ci.rect.left,ci.rect.top));
+		return true;
+	}
+
+	void prepare ()
+	{
+		if (!initialized)
+		{
+			full = false;
+
+			int memoryUse = atoi((*Core->getOptions())["General"].getWithDefault("DrawCacheSize","0"));
+				
+			if (memoryUse == 0) memoryUse = Core->getRect().width() * Core->getRect().height() * 3 /*bits per pixel*/ * 5 /*multiplier*/;
+
+			width = Core->getRect().width();
+
+			height = memoryUse / width / 3;
+
+			if (height > width)
+			{
+				surface = sbSurfaceCreate(width,height);
+				sbAssert (surface == NULL);
+				initialized = true;
+				sbMessage ("Cache created of size %i x %i\n",width,height);
+
+				debug = atoi((*Core->getOptions())["General"].getWithDefault("DrawCacheDebug","0"));
+			}
+			else
+			{
+				sbMessage ("Draw cache not created\n");
+			}
+		}
+
+		if (!initialized) return;
+
+		if (debug) sbMessage ("Begin Paint\n");
+
+		//we can remove from cache only in main thread
+		for ( std::list<CACHE>::iterator it = cache.begin(); it != cache.end();)
+		{
+			if ((*it).used < -300)
+			{
+				if (debug) sbMessage ("Erased %i\n",(*it).item);
+
+				cache.erase(it);
+				it = cache.begin();
+			}
+			else
+				it++;
+		}
+
+		cache.sort();
+
+		std::list<CACHE>::iterator useless (cache.begin());
+
+		for ( std::list<CACHE>::iterator it = cache.begin(); it != cache.end(); it++ )
+		{
+			(*it).used--;
+
+			if ((*it).used < (*useless).used)
+				useless = it;
+
+			if (debug) sbMessage ("Cache %i [%i,%i] %i\n",(*it).item,(*it).rect.top,(*it).rect.bottom,(*it).used);
+		}
+
+		if (useless != cache.end() && (full || (*useless).used < -100))
+		{
+			if (debug) sbMessage ("Erased %i\n",(*useless).item);
+			cache.erase(useless);
+			full = false;
+		}
+
+		if (debug) sbMessage ("\n");
+	}
+
+	void remove (sbItem * item)
+	{
+		if (!initialized) return;
+
+		for ( std::list<CACHE>::iterator it = cache.begin(); it != cache.end(); it++ )
+		{
+			if ((*it).item == item)
+			{
+				(*it).used = -1000;
+				return;
+			}
+		}
+	}
+
+private:
+	std::list<CACHE>            cache;
+	sbSurface                   surface;
+
+	int                         width;
+	int                         height;
+
+	bool                        initialized;
+	bool                        full;
+
+	bool                        debug;
+};
+
+sbDrawCache DrawCache;
+
 sbList::sbList ( sbList::TYPE _type_ ) : type ( _type_ )
 {
-	itemCurrent = itemHover = itemEdit = itemSelected = NULL;
+	itemCurrent = itemHover = itemEdit = itemSelected = itemBanner = itemMenu = NULL;
 
 	next = prev = NULL;
 
@@ -32,11 +225,6 @@
 
 	attachedReading    = attachedHistory = -1;
 
-	verseFirst         = verseLast      = NULL;
-	versesForward      = versesBackward = 0;
-
-	listEndConstructed = listStartConstructed = true;
-
 	controlSelected    = -1;
 
 	rect               = Core->getRect();
@@ -44,40 +232,56 @@
 
 	switch(type)
 	{
-	case TYPE_SELECT_BOOK:
 	case TYPE_SELECT_MODULE:
-		{
-			addControl(sbControl::TYPE_OPEN_MODULE_SELECTION);
-			addControl(sbControl::TYPE_OPEN_BOOK_SELECTION);
-			addControl(sbControl::TYPE_CLOSE);
-		}
+		addControl(sbControl::TYPE_OPEN_SEARCH);
+		addControl(sbControl::TYPE_OPEN_BOOK_SELECTION);
+		addControl(sbControl::TYPE_CLOSE);
 		break;
 
-	case TYPE_MODULE_VIEW:
-		{
-			addControl(sbControl::TYPE_OPEN_NAVIGATION_LIST);
-			addControl(sbControl::TYPE_LIST_SPACE);
-			addControl(sbControl::TYPE_OPEN_HOME);
+	case TYPE_SELECT_BOOK:
+		addControl(sbControl::TYPE_OPEN_MODULE_SELECTION);
+		addControl(sbControl::TYPE_OPEN_SEARCH_2);
+		addControl(sbControl::TYPE_CLOSE);
+		break;
 
-			listEndConstructed = listStartConstructed = false;
-		}
+
+	case TYPE_SEARCH:
+		addControl(sbControl::TYPE_OPEN_MODULE_SELECTION);
+		addControl(sbControl::TYPE_OPEN_BOOK_SELECTION);
+		addControl(sbControl::TYPE_CLOSE);
 		break;
 
+	case TYPE_MODULE_INSTALLER_DISCLAIMER:
+		addControl(sbControl::TYPE_INSTALLER_DISCLAIMER_ACCEPT);
+		addControl(sbControl::TYPE_INSTALLER_DISCLAIMER_DECLINE);
+		break;
+
+	case TYPE_MODULE_INSTALLER:
+		addControl(sbControl::TYPE_WIDE_MODULES);
+		break;
+
+	case TYPE_MODULE_VIEW:
+		addControl(sbControl::TYPE_OPEN_NAVIGATION_LIST);
+		addControl(sbControl::TYPE_OPEN_OPTIONS);
+		addControl(sbControl::TYPE_OPEN_HOME);
+		after.constructed = before.constructed = false;
+		break;
+
 	case TYPE_READINGS:
 	case TYPE_HISTORY:
 	case TYPE_BOOKMARKS:
 	case TYPE_SELECT_VERSE:
-		{
-			addControl(sbControl::TYPE_WIDE_CLOSE);
-		}
+		addControl(sbControl::TYPE_WIDE_CLOSE);
 		break;
 
+	case TYPE_MENU_OPTIONS:
+		addControl(sbControl::TYPE_WIDE_MODULES);
+		break;
+
 	case TYPE_HOME:
-		{
-			addControl(sbControl::TYPE_OPEN_NAVIGATION);
-			addControl(sbControl::TYPE_OPEN_HISTORY);
-			addControl(sbControl::TYPE_EXIT);
-		}
+		addControl(sbControl::TYPE_OPEN_NAVIGATION);
+		addControl(sbControl::TYPE_OPEN_HISTORY);
+		addControl(sbControl::TYPE_EXIT);
 		break;
 
 	default:
@@ -100,6 +304,17 @@
 	}
 
 	for (int i=0; i < controls.size(); i++) delete controls[i];
+
+	if (itemBanner) delete itemBanner;
+
+	// remove menu
+	if (itemMenu != NULL)
+	{
+		while (itemMenu->next != NULL) delete itemMenu->next;
+		//while (itemMenu->prev != NULL) delete itemMenu->prev;
+		delete itemMenu;
+		itemMenu = NULL;
+	}
 }
 
 void sbList::attach (sbList * list, sbList::TYPE to)
@@ -148,20 +363,24 @@
 {
 	if (itemCurrent != NULL)
 	{
-		while (itemCurrent->prev != NULL) delete itemCurrent->prev;
-
-		while (itemCurrent->next != NULL) delete itemCurrent->next;
-
+		while (itemCurrent->prev != NULL)
+		{
+			DrawCache.remove(itemCurrent->prev);
+			delete itemCurrent->prev;
+		}
+		while (itemCurrent->next != NULL)
+		{
+			DrawCache.remove(itemCurrent->next);
+			delete itemCurrent->next;
+		}
+		DrawCache.remove(itemCurrent);
 		delete itemCurrent;
 
 		itemCurrent    = NULL;
-		verseFirst     = NULL;
-		verseLast      = NULL;
-		versesForward  = 0;
-		versesBackward = 0;
+		before = after = BOUND();
 		displace       = 0;
 
-		if (type == TYPE_MODULE_VIEW) listStartConstructed = listEndConstructed = false;
+		if (type == TYPE_MODULE_VIEW) before.constructed = after.constructed = false;
 	}
 }
 
@@ -179,6 +398,8 @@
 
 	Core->getTheme()->drawElement ( hdc, &workRect, sbTheme::ELEMENT::BACKGROUND );
 
+	if (sideDisplacement <= 0) DrawCache.prepare();
+
 	while ( true )
 	{
 		if (workItem == NULL) break;
@@ -200,7 +421,7 @@
 			workRect.left   = workRect.right;
 			workRect.right  = workRect.left + workItem->width;
 
-			if (type == TYPE_HISTORY && workItem->type == sbItem::TYPE_DESCRIPTION)
+			if ((type == TYPE_HISTORY || type == TYPE_MENU_OPTIONS) && workItem->type == sbItem::TYPE_CENTRED_DESCRIPTION)
 				element = sbTheme::ELEMENT::ITEM_SEPARATOR;
 
 			if ( workItem == itemHover )
@@ -208,7 +429,10 @@
 			else if ( workItem->highlighted )
 				element = sbTheme::ELEMENT::ITEM_HIGHLIGHTED;
 
-			workItem->render(hdc,workRect,element);
+			if (workItem->type != sbItem::TYPE_VERSE || workItem->text.size() == 0 || workItem->expanding != 0 || !workItem->processed || Core->fadeSurface)
+				workItem->render(hdc,workRect,element);
+			else if (!DrawCache.blit(hdc,workItem,workRect))
+				workItem->render(hdc,workRect,element);
 
 			if ( workItem == itemSelected ) selectedRect = workRect;
 
@@ -234,6 +458,28 @@
 		workItem = workItem->next;
 	}
 
+	// menu
+	if (itemMenu != NULL)
+	{
+		workItem        = itemMenu;
+		workRect.top    = menuPosition.y;
+		workRect.left   = menuPosition.x;
+		workRect.right  = workRect.left + workItem->width;
+		
+		while ( true )
+		{
+			if (workItem == NULL) break;
+
+			workRect.bottom = workRect.top  + workItem->height;
+
+			workItem->render(hdc,workRect,sbTheme::ELEMENT::ANOTHER_MENU);
+
+			workRect.top = workRect.bottom;
+
+			workItem = workItem->next;
+		}
+	}
+
 	// scrolling
 	if (itemSelected == NULL)
 	{
@@ -253,7 +499,7 @@
 			needFill = false;
 		}
 
-		if ((needScroll > 0 && !listEndConstructed) || (needScroll < 0 && !listStartConstructed)) needScroll = 0;
+		if ((needScroll > 0 && !after.constructed) || (needScroll < 0 && !before.constructed)) needScroll = 0;
 	}
 	else
 	{
@@ -265,58 +511,69 @@
 		}
 	}
 
-	// banner
+	// banner, item over the list that show current place
 	if ( showPlace && module != NULL )
 	{
-		sbPoint      ks;
-		const char * kt = place.getShortText();
-		int          kl = strlen ( kt );
-		TCHAR      * kw = new TCHAR [ kl + 1 ];
-		const char * mt = module->Description();
-		int          ml = strlen ( mt );
-		TCHAR      * mw = new TCHAR [ ml + 1 ];
-		int          mc = 0;
-		
-		mbstowcs ( kw, kt, kl+1 );
-		mbstowcs ( mw, mt, ml+1 );
+		if (itemBanner == NULL)
+		{
+			itemBanner = new sbItem (sbItem::TYPE_BANNER,L"",0);
+			itemBanner->center = true;
+		}
 
-		sbSelectFont (hdc, Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font );
-		ks = sbGetTextExtent (Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font, kw, kl);
+		if (itemBanner->index != place.Index())
+		{
+			DrawCache.remove(itemBanner);
 
-		sbRect tempRect ((rect.right-ks.x)/2+sideDisplacement, (Core->getTheme()->size/6)-(ks.y/2), (rect.right-ks.x)/2+ks.x+sideDisplacement, (Core->getTheme()->size/6)-(ks.y/2)+ks.y);
+			sbPoint      ks;
+			const char * kt = place.getShortText();
+			int          kl = strlen ( kt );
+			TCHAR      * kw = new TCHAR [ kl + 1 ];
+			const char * mt = Core->getSword()->getModule(module)->Description();
+			int          ml = strlen ( mt );
+			TCHAR      * mw = new TCHAR [ ml + 1 ];
+			int          mc = 0;
 
-		sbSelectFont ( hdc, Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font );
+			TCHAR        finalText [64];
+		
+			mbstowcs ( kw, kt, kl+1 );
+			mbstowcs ( mw, mt, ml+1 );
 
-		for (int width = 0; mc < ml; mc++)
-		{
-			sbPoint sz = sbGetTextExtent ( Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font, mw+mc, 1 );
+			sbSelectFont (hdc, Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font );
+			ks = sbGetTextExtent (Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font, kw, kl);
 
-			if ( width + sz.x > ks.x ) break;
+			sbSelectFont ( hdc, Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font );
 
-			width += sz.x;
-		}
-		
-		workRect = tempRect;
+			for (int width = 0; mc < ml; mc++)
+			{
+				sbPoint sz = sbGetTextExtent ( Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font, mw+mc, 1 );
 
-		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;
+				if ( width + sz.x > ks.x ) break;
 
-		Core->getTheme()->drawElement ( hdc, &workRect, sbTheme::ELEMENT::BANNER );
+				width += sz.x;
+			}
 
-		workRect = tempRect;
+			if (mc < ml && mc > 0)
+			{
+				mw[mc-1] = L'…';
+				mw[mc]   = L'\0';
+			}
 
-		sbSelectColor ( hdc, Core->getTheme()->elements[sbTheme::ELEMENT::BANNER].textColor );
+			_sntprintf(finalText,64,L"<s t=\"5\">%s</s><s t=\"6\">%s</s>",kw,mw);
 
-		sbSelectFont ( hdc, Core->getTheme()->styles[sbTheme::STYLE::CAPTION].font );
-		sbDrawText ( hdc, workRect.left, workRect.top, kw, kl );
+			itemBanner->index = place.Index();
+			itemBanner->width = ks.x + (Core->getTheme()->BannerBorderSize * 2);
+			itemBanner->setText(finalText);
+		
+			delete [] kw;
+			delete [] mw;
+		}
 
-		sbSelectFont ( hdc, Core->getTheme()->styles[sbTheme::STYLE::DESCRIPTION].font );
-		sbDrawText ( hdc, workRect.left, workRect.top + Core->getTheme()->styles[sbTheme::STYLE::CAPTION].size , mw, mc );
+		workRect.left   = (rect.width()-itemBanner->width)/2 + sideDisplacement;
+		workRect.right  = workRect.left + itemBanner->width;
+		workRect.top    = (Core->getTheme()->size/6)-(itemBanner->height/2);
+		workRect.bottom = workRect.top + itemBanner->height;
 
-		delete [] kw;
-		delete [] mw;
+		if (!DrawCache.blit(hdc,itemBanner,workRect)) itemBanner->render(hdc,workRect,sbTheme::ELEMENT::BANNER);
 	}
 }
 
@@ -364,32 +621,38 @@
 	if (itemCurrent == NULL) return NULL;
 
 	sbItem* i = itemCurrent;
-	int top = (int)displace;
+	int top   = (int)displace;
+	int left  = 0;
 
+	if (itemMenu != NULL)
+	{
+		i    = itemMenu;
+		top  = menuPosition.y;
+		left = menuPosition.x;
+	}
+	
 	while (i != NULL && top < rect.height())
 	{
 		if (y > top && y < top + i->height)
 		{
-			int left = 0;
+			int l = left;
 			
 			while (i != NULL)
 			{
-				if (x > left && x < left + i->width)
+				if (x > l && x < l + i->width)
 					return i;
 
-				left += i->width;
+				l += i->width;
 				i = i->right;
 			}
 
 			return NULL;
 		}
-
 		top += i->height;
 		top += Core->getTheme()->ListSeparatorHeight;
 
 		i = i->next;
 	}
-
 	return NULL;
 }
 
@@ -456,17 +719,186 @@
 
 	sbItem * item = getItem(x,y);
 
-	if (item == NULL) return;
+	if (item != NULL)
+	{
+		onItem(item);
+	}
 
-	if (itemEdit != NULL && item != itemEdit) setEditMode (false);
+	if (itemEdit != NULL && item != itemEdit) setEditMode ( NULL );
 
-	onItem(item);
+	// remove menu
+	if (itemMenu != NULL)
+	{
+		while (itemMenu->next != NULL) delete itemMenu->next;
+		//while (itemMenu->prev != NULL) delete itemMenu->prev;
+		delete itemMenu;
+		itemMenu = NULL;
+	}
 }
 
+
+ void sbList_Percent (char percent, void * data)
+ {
+	 TCHAR tempText [32];
+	 _sntprintf(tempText,32,L"Search : %i%%",percent);
+	 Core->waitMode = true;
+	 Core->waitMessage = tempText;
+	 sbUpdateScreen();
+ }
+
+#include <windows.h>
+
+
 void sbList::onItem ( sbItem * item )
 {
+	TCHAR tempText[256];
+
 	switch (item->type)
 	{
+	case sbItem::TYPE_TEXT_FIELD:
+		setEditMode (item);
+		break;
+
+	case sbItem::TYPE_SEARCH_RANGE_START:
+	case sbItem::TYPE_SEARCH_RANGE_END:
+		{
+			sword::VerseKey workKey = Core->currentModule == NULL ? Core->defaultModule->getKey() : Core->currentModule->getKey();
+
+			if (Core->searchRange.Count() != 1)
+				Core->searchRange = workKey.ParseVerseList("Gen-Rev",NULL,true,true);
+
+			workKey.Index(item->index);
+
+			if (item->type == sbItem::TYPE_SEARCH_RANGE_END)
+				((sword::VerseKey *)Core->searchRange.getElement(0))->UpperBound(workKey);
+			else
+				((sword::VerseKey *)Core->searchRange.getElement(0))->LowerBound(workKey);
+		}
+		break;
+
+	case sbItem::TYPE_START_SEARCH:
+		{
+			int s = sbWcsToMbs(item->prev->text.c_str());
+			char * request = new char [s+1];
+			sbWcsToMbs(item->prev->text.c_str(),request,s);
+
+			sbWaitMode (true);
+
+			Core->currentModule->createSearchFramework();
+
+			sbMessage ("Start search %s\n",request);
+
+			sword::ListKey result = Core->currentModule->search(request,0,0,&Core->searchRange,0,sbList_Percent,request);
+
+			sbItem * tempItem = item;
+			
+			while (item->next != NULL) delete item->next;
+
+			for (int i = 0; i < result.Count(); i++)
+			{
+				sbMessage ("\t%s\n",result.GetElement(i)->getText());
+				mbstowcs(tempText,result.GetElement(i)->getText(),256);
+				tempItem->attach(new sbItem (sbItem::TYPE_BUTTON_BOOKMARK,tempText,rect.width(),result.GetElement(i)->Index()),sbItem::PIN::NEXT);
+				tempItem = tempItem->next;
+			}
+
+			Core->currentModule->deleteSearchFramework();
+
+			sbWaitMode (false);
+			Core->waitMode = false;
+
+			delete [] request;
+		}
+		break;
+
+	case sbItem::TYPE_MODULE_INSTALLER_MODULE:
+	case sbItem::TYPE_MODULE_INSTALLER_UPDATE:
+		{
+			sword::InstallSource * source = NULL;
+
+			for (sbItem * i = item; i != NULL; i = i->prev) if (i->type == sbItem::TYPE_MODULE_INSTALLER_REPO) { source = (sword::InstallSource *)i->index; break; }
+
+			sbAssert (source == NULL);
+
+			sbWaitMode(true);
+
+			int success = -1;
+
+			sword::SWModule * module = ((sword::SWModule*)item->index);
+
+			_sntprintf(tempText,256,L"Dou you want to install %S of size %S KB ?\n",module->Name(),module->getConfigEntry("InstallSize"));
+			
+			if (sbQueryBox(tempText))
+				success = Core->installMgr.installModule(Core->getSword(),"",module->Name(),source);
+
+			if (success >= 0)
+			{
+				Core->initSword();
+				sbWaitMode(false);
+				Core->switchList(sbList::TYPE_SELECT_MODULE);
+			}
+			else
+				sbWaitMode(false);
+		}
+		break;
+
+	case sbItem::TYPE_MODULE_INSTALLER_REPO:
+		{
+			sword::InstallSource * source = (sword::InstallSource *)item->index;
+
+			if (item->next == NULL || !(item->next->type == sbItem::TYPE_MODULE_INSTALLER_MODULE || item->next->type == sbItem::TYPE_MODULE_INSTALLER_UPDATE))
+			{
+				std::map<sword::SWModule *,int> diff = Core->installMgr.getModuleStatus(*Core->getSword(),*source->getMgr());
+
+				for (std::map<sword::SWModule *,int>::iterator it = diff.begin(); it != diff.end(); it++)
+				{
+					if ( (*it).second & sword::InstallMgr::MODSTAT_NEW )
+					{
+						_sntprintf(tempText,256,L"%S\n<s t=\"6\">%S\n[%S]</s>",(*it).first->Name(),(*it).first->Description(),(*it).first->Type());
+						item->attach(new sbItem (sbItem::TYPE_MODULE_INSTALLER_MODULE,tempText,rect.width(),(long)(*it).first),sbItem::NEXT);
+					}
+					else if ( (*it).second & sword::InstallMgr::MODSTAT_UPDATED )
+					{
+						_sntprintf(tempText,128,L"%S<s t=\"6\"> - Update\n%S\n[%S]</s>",(*it).first->Name(),(*it).first->Description(),(*it).first->Type());
+						item->attach(new sbItem (sbItem::TYPE_MODULE_INSTALLER_UPDATE,tempText,rect.width(),(long)(*it).first),sbItem::NEXT);
+					}
+
+				}
+			}
+			else
+			{
+				while (item->next != NULL && (item->next->type == sbItem::TYPE_MODULE_INSTALLER_MODULE || item->next->type == sbItem::TYPE_MODULE_INSTALLER_UPDATE) )
+					delete item->next;
+			}
+		}
+		break;
+
+	case sbItem::TYPE_OPEN_MODULE_INSTALLER:
+		{
+			if (!Core->installMgr.isUserDisclaimerConfirmed())
+				Core->switchList(sbList::TYPE_MODULE_INSTALLER_DISCLAIMER);
+			else
+				Core->switchList(sbList::TYPE_MODULE_INSTALLER);
+		}
+		break;
+
+	case sbItem::TYPE_SWITCH_MODULE_OPTION:
+		{
+			// set next option value
+			sword::StringList sl = Core->getSword()->getGlobalOptionValues(Core->moduleOptions[item->index]);
+			const char * co = Core->getSword()->getGlobalOption(Core->moduleOptions[item->index]);
+			sword::StringList::iterator it = std::find(sl.begin(),sl.end(),co);
+
+			if (it == sl.end() || ++it == sl.end()) it = sl.begin();
+
+			Core->getSword()->setGlobalOption(Core->moduleOptions[item->index], (*it));
+
+			// update text
+			_sntprintf(tempText,256,L"%S : %S",Core->moduleOptions[item->index],Core->getSword()->getGlobalOption(Core->moduleOptions[item->index]));
+			item->setText(tempText);
+		}
+		break;
+
 	case sbItem::TYPE_GOTO_MODULES:
 		{
 			Core->switchList(sbList::TYPE_MODULE_VIEW);
@@ -489,8 +921,11 @@
 	case sbItem::TYPE_BUTTON_BOOKMARK_SMALL:
 		{
 			Core->goVerse       = true;
-			Core->currentModule = Core->defaultModule;
-			Core->currentVerse.copyFrom(Core->defaultModule->getKey());
+			if (Core->currentModule == NULL)
+			{
+				Core->currentModule = Core->defaultModule;
+				Core->currentVerse.copyFrom(Core->defaultModule->getKey());
+			}
 			Core->currentVerse.Index ( item->index );
 
 			Core->switchList(sbList::TYPE_MODULE_VIEW);
@@ -515,13 +950,10 @@
 				for (int i=0; i < workKey.getChapterMax(); i++)
 				{
 					workKey.setChapter(i+1);
-					TCHAR text[8];
-					_itot(workKey.getChapter(), text, 10);
+					_itot(workKey.getChapter(), tempText, 10);
 					
-					sbItem *item = new sbItem (sbItem::TYPE_BUTTON_SELECTION_CHAPTER, text, rect.width()/3, workKey.Index());
+					sbItem *item = new sbItem (sbItem::TYPE_BUTTON_SELECTION_CHAPTER, tempText, rect.width()/3, workKey.Index());
 
-					item->center = true;
-
 					if (tmpItem->type == sbItem::TYPE_BUTTON_SELECTION_CHAPTER &&
 						(tmpItem->right == NULL || tmpItem->right->right == NULL))
 					{
@@ -600,17 +1032,31 @@
 	{
 		addControl(sbControl::TYPE_MENU_VERSE);
 	}
+	else if (item->type == sbItem::TYPE_BUTTON_SELECTION_BOOK || item->type == sbItem::TYPE_BUTTON_SELECTION_CHAPTER)
+	{
+		sbAssert (itemMenu != NULL);
+
+		itemMenu = new sbItem (sbItem::TYPE::TYPE_SEARCH_RANGE_START,L"Search from",rect.width()/2,item->index);
+		itemMenu->attach(new sbItem (sbItem::TYPE::TYPE_SEARCH_RANGE_END,L"Search to",rect.width()/2,item->index),sbItem::PIN::NEXT);
+
+		menuPosition = sbPoint (max(Core->getTheme()->size/10,x-itemMenu->width),max(Core->getTheme()->size/10,y-itemMenu->height-itemMenu->next->height));
+	}
 }
 
+
 /*   sbList::process
  *   fill verses with text from module
  *   also delete unnecessary items
  */
 void sbList::process ( bool * abort )
 {
-	sbAssert ( module == NULL );
 	sbAssert ( type != sbList::TYPE_MODULE_VIEW );
 
+	sword::SWModule * mod = Core->getSword()->getModule(module);
+
+	sbAssert ( module == NULL );
+	sbAssert ( mod    == NULL );
+
 	sword::VerseKey workKey ( place );
 	
 	if (itemCurrent == NULL) return;
@@ -622,34 +1068,42 @@
 		bool     atEnd     = false;
 		
 		// delete unnecessary items, it should be in background thread ...
-		if ( versesForward + versesBackward > Core->versesOptimal )
+		if ( before.verseCount + after.verseCount > Core->versesOptimal )
 		{
 			int countDeleted = 0;
-			int needDelete = ( versesForward + versesBackward ) / Core->versesOptimal * 10;
+			int needDelete = ( before.verseCount + after.verseCount ) / Core->versesOptimal * 10;
 
-			if ( versesForward > versesBackward )
+			if ( after.verseCount > before.verseCount )
 			{
 				while ( countDeleted < needDelete )
 				{
-					verseLast = verseLast->prev;
-					while (verseLast->type != sbItem::TYPE_VERSE) verseLast = verseLast->prev;
-					while (verseLast->next != NULL) delete verseLast->next;
+					after.verse = after.verse->prev;
+					while (after.verse->type != sbItem::TYPE_VERSE) after.verse = after.verse->prev;
+					while (after.verse->next != NULL)
+					{
+						DrawCache.remove(after.verse->next);
+						delete after.verse->next;
+					}
 					countDeleted++;
 				}
-				if ( listEndConstructed ) listEndConstructed = false;
-				versesForward -= countDeleted;
+				if ( after.constructed ) after.constructed = false;
+				after.verseCount -= countDeleted;
 			}
 			else
 			{
 				while ( countDeleted < needDelete )
 				{
-					verseFirst = verseFirst->next;
-					while (verseFirst->type != sbItem::TYPE_VERSE) verseFirst = verseFirst->next;
-					while (verseFirst->prev != NULL) delete verseFirst->prev;
+					before.verse = before.verse->next;
+					while (before.verse->type != sbItem::TYPE_VERSE) before.verse = before.verse->next;
+					while (before.verse->prev != NULL)
+					{
+						DrawCache.remove(before.verse->prev);
+						delete before.verse->prev;
+					}
 					countDeleted++;
 				}
-				if ( listStartConstructed ) listStartConstructed = false;
-				versesBackward -= countDeleted;
+				if ( before.constructed ) before.constructed = false;
+				before.verseCount -= countDeleted;
 			}
 		}
 
@@ -667,16 +1121,17 @@
 		{
 			if ( item->type == sbItem::TYPE_VERSE && item->processed == false )
 			{
+				DrawCache.remove(item);
+
 				workKey.Index ( item->index );
 
-				module->SetKey ( workKey );
+				mod->SetKey ( workKey );
 
-				TCHAR * text = (TCHAR*) module->RenderText();
+				TCHAR * text = (TCHAR*) mod->RenderText();
 
-				item->processed = true;
+				int length = _tcslen ( text );
 
-				if ( _tcslen ( text ) == 0 ) break;
-
+				if ( length == 0 ) break;
 				int oldHeight = item->height;
 
 				item->setText ( text );
@@ -684,6 +1139,8 @@
 				item->expanding = item->height;
 				item->height    = oldHeight;
 
+				item->processed = true;
+
 				break; // start again
 			}
 
@@ -723,7 +1180,6 @@
 	{
 	case sbControl::TYPE_MENU_VERSE_ADD_DYNAMIC_BOOKMARK:
 	case sbControl::TYPE_MENU_VERSE_ADD_STATIC_BOOKMARK:
-		//Core->getCollection("bookmarks")->add(&place); /*TODO retrieve current key from Core*/
 		removeControl ( sbControl::TYPE_MENU_CURRENT );
 		break;
 
@@ -866,7 +1322,7 @@
 								{
 									if ( y + item->height < halfscreen )
 									{
-										scroll ( -add );
+										scroll ( (float)-add );
 										y -= add;
 									}
 									else
@@ -908,8 +1364,8 @@
 				{
 					itemCurrent = new sbItem (sbItem::TYPE_VERSE, NULL, rect.width(), workKey.Index(), workKey.getVerse());
 
-					verseFirst = itemCurrent;
-					verseLast = itemCurrent;
+					before.verse = itemCurrent;
+					after.verse = itemCurrent;
 
 					if (workKey.getVerse() == 1)
 					{
@@ -928,26 +1384,26 @@
 				{
 					bool atEnd;
 
-					if (versesForward+versesBackward > Core->versesMax) { sbSleep(25); break; } // need for memory reason
+					if (after.verseCount+before.verseCount > Core->versesMax) { sbSleep(25); break; } // need for memory reason
 
-					if (versesForward+versesBackward > Core->versesOptimal * 2) sbSleep(5);
+					if (after.verseCount+before.verseCount > Core->versesOptimal * 2) sbSleep(5);
 
-					if (versesForward < 15 && !listEndConstructed)        atEnd = true;
-					else if (versesBackward < 5 && !listStartConstructed) atEnd = false;
+					if (after.verseCount < 15 && !after.constructed) atEnd = true;
+					else if (before.verseCount < 5 && !before.constructed) atEnd = false;
 					else if (added > 4) break;
 					else
 					{
-						if (versesForward+versesBackward > Core->versesOptimal/2) break;
+						if (before.verseCount+after.verseCount > Core->versesOptimal/2) break;
 
 						atEnd = added%2==0;
-						if ((listEndConstructed && atEnd) || (listStartConstructed && !atEnd))
+						if ((after.constructed && atEnd) || (before.constructed && !atEnd))
 						{
 							added++;
 							continue;
 						}
 					}
 
-					sbItem* item = atEnd ? verseLast : verseFirst;
+					sbItem* item = atEnd ? after.verse : before.verse;
 					int index = 0;
 
 					while (true)
@@ -967,13 +1423,13 @@
 
 						if (atEnd)
 						{
-							verseLast = item->next;
-							versesForward++;
+							after.verse = item->next;
+							after.verseCount++;
 						}
 						else
 						{
-							verseFirst = item->prev;
-							versesBackward++;
+							before.verse = item->prev;
+							before.verseCount++;
 						}
 
 						if (workKey.getVerse() == 1)
@@ -994,20 +1450,18 @@
 
 							if (atEnd)
 							{
-								verseLast->attach(new sbItem (sbItem::TYPE_HEADER, headerText, rect.width(), workKey.Index()), sbItem::PREV);
-								verseLast->prev->center = true;
+								after.verse->attach(new sbItem (sbItem::TYPE_HEADER, headerText, rect.width(), workKey.Index()), sbItem::PREV);
 							}
 							else
 							{
-								verseFirst->attach(new sbItem (sbItem::TYPE_HEADER, headerText, rect.width(), workKey.Index()), sbItem::PREV);
-								verseFirst->prev->center = true;
+								before.verse->attach(new sbItem (sbItem::TYPE_HEADER, headerText, rect.width(), workKey.Index()), sbItem::PREV);
 							}
 						}
 						added++;
 					}
 					else
 					{
-						atEnd ? listEndConstructed = true : listStartConstructed = true;
+						atEnd ? after.constructed = true : before.constructed = true;
 					}
 				}
 			}
@@ -1019,8 +1473,8 @@
 				{
 					if (itemCurrent->type == sbItem::TYPE_VERSE)
 					{
-						versesBackward--;
-						versesForward++;
+						before.verseCount--;
+						after.verseCount++;
 					}
 
 					itemCurrent = itemCurrent->prev;
@@ -1034,7 +1488,7 @@
 					displace += itemCurrent->height + Core->getTheme()->ListSeparatorHeight;
 
 					if (itemCurrent->type == sbItem::TYPE_VERSE)
-					{ versesBackward++; versesForward--; }
+					{ before.verseCount++; after.verseCount--; }
 
 					itemCurrent = itemCurrent->next;
 				}
@@ -1049,7 +1503,7 @@
  */
 void sbList::onActivate ( )
 {
-	static TCHAR tempText [128];
+	static TCHAR tempText [256];
 
 	sbSetSip ( itemEdit != NULL );
 
@@ -1057,11 +1511,116 @@
 
 	switch (type)
 	{
+	case TYPE_SEARCH:
+		{
+			//clear();
+
+			if (Core->currentModule != NULL)
+			{
+				if (!Core->searchRange.Count())
+				{
+					sword::VerseKey workKey = Core->currentModule->getKey();
+					Core->searchRange = workKey.ParseVerseList("Gen-Rev",NULL,true,true);
+				}
+
+				if (!itemCurrent || itemCurrent->type == sbItem::TYPE_TEXT)
+				{
+					clear ();
+					// TODO: gray inactive text for text fields "type here"
+					itemCurrent = new sbItem (sbItem::TYPE_TEXT_FIELD,L"",rect.width());
+					itemCurrent->attach(new sbItem (sbItem::TYPE_START_SEARCH,L"",rect.width()),sbItem::PIN::NEXT);
+				}
+
+				sbItem * workItem = itemCurrent;
+				while (workItem->prev != NULL) workItem = workItem->prev;
+				while (workItem->type != sbItem::TYPE_START_SEARCH && workItem->next != NULL) workItem = workItem->next;
+				
+				_sntprintf(tempText,256,L"Search ...\n<s t=\"6\">%S</s>",Core->searchRange.getRangeText());
+				workItem->setText(tempText);
+			}
+			else
+			{
+				itemCurrent = new sbItem (sbItem::TYPE_TEXT,L"No Module Selected",rect.width());
+			}
+		}
+		break;
+
+	case TYPE_MODULE_INSTALLER_DISCLAIMER:
+		{
+			clear();
+			itemCurrent = new sbItem (sbItem::TYPE_TEXT,L"WARNING\n \nAlthough Install Manager provides a convenient way for installing and upgrading SWORD components, it also uses a systematic method for accessing sites which gives packet sniffers a target to lock into for singling out users.\n \nIF YOU LIVE IN A PERSECUTED COUNTRY AND DO NOT WISH TO RISK DETECTION, YOU SHOULD <b>NOT</b> USE INSTALL MANAGER'S REMOTE SOURCE FEATURES.\n \nAlso, Remote Sources other than CrossWire may contain less than quality modules, modules with unorthodox content, or even modules which are not legitimately distributable.  Many repositories contain wonderfully useful content.  These repositories simply are not reviewed or maintained by CrossWire and CrossWire cannot be held responsible for their content.\n \nIf you understand this and are willing to enable remote source features then type yes at the prompt.",rect.width());
+		}
+		break;
+
+	case TYPE_MODULE_INSTALLER:
+		{
+			sbItem * tempItem;
+			bool refreshed = (bool)atoi((*Core->installMgr.installConf)["General"].getWithDefault("Refreshed","0"));
+
+			clear();
+
+			sbWaitMode ( true );
+
+			int success;
+			if (!refreshed) success = Core->installMgr.refreshRemoteSourceConfiguration();
+
+			if (success != 0) sbMessage ("Install Manager Refresh Sources : %i\n",success);
+
+			for (sword::InstallSourceMap::iterator it = Core->installMgr.sources.begin(); it != Core->installMgr.sources.end(); it++)
+			{
+				_sntprintf(tempText,256,L"%S",(*it).second->caption);
+
+				tempItem = new sbItem (sbItem::TYPE_MODULE_INSTALLER_REPO,tempText,rect.width(),(long)(*it).second);
+
+				if (itemCurrent == NULL) itemCurrent = tempItem; else itemCurrent->attach(tempItem,sbItem::NEXT);
+
+				if (!refreshed) Core->installMgr.refreshRemoteSource((*it).second);
+
+				Core->installMgr.getModuleStatus(*Core->getSword(),*(*it).second->getMgr());
+			}
+
+			sbWaitMode ( false );
+
+			if (itemCurrent == NULL)
+			{
+				itemCurrent = new sbItem (sbItem::TYPE_TEXT,L"No Repositories found",rect.width());
+			}
+			else
+			{
+				(*Core->installMgr.installConf)["General"]["Refreshed"] = "1";
+			}
+
+			while (itemCurrent != NULL && itemCurrent->prev != NULL) itemCurrent = itemCurrent->prev;
+		}
+		break;
+
+	case TYPE_MENU_OPTIONS:
+		{
+			clear();
+
+			itemCurrent = new sbItem(sbItem::TYPE_CENTRED_DESCRIPTION,L"Module Options :",rect.width());
+
+			for (int i = 0; i < Core->moduleOptions.size(); i++)
+			{
+				_sntprintf(tempText,256,L"%S : %S",Core->moduleOptions[i],Core->getSword()->getGlobalOption(Core->moduleOptions[i]));
+				
+				sbItem * item = new sbItem(sbItem::TYPE_SWITCH_MODULE_OPTION,tempText,rect.width(),i);
+
+				itemCurrent->attach(item,sbItem::NEXT);
+				itemCurrent = itemCurrent->next;
+			}
+
+			while (itemCurrent->prev != NULL) itemCurrent = itemCurrent->prev;
+
+			Core->changedGlobalOptions = true;
+		}
+		break;
+
 	case TYPE_SELECT_VERSE:
 		{
 			clear ();
 
-			_sntprintf(tempText,128,L"%S %i",Core->currentVerse.getBookName(),Core->currentVerse.getChapter());
+			_sntprintf(tempText,256,L"%S %i",Core->currentVerse.getBookName(),Core->currentVerse.getChapter());
 
 			itemCurrent = new sbItem (sbItem::TYPE_HEADER, tempText, rect.width(), Core->currentVerse.Index());
 
@@ -1078,8 +1637,6 @@
 
 				sbItem * item = new sbItem (sbItem::TYPE_BUTTON_BOOKMARK_SMALL, text, rect.width()/4, workKey.Index());
 
-				item->center = true;
-
 				if (tempItem->type == sbItem::TYPE_BUTTON_BOOKMARK_SMALL &&
 					(tempItem->right == NULL || tempItem->right->right == NULL || tempItem->right->right->right == NULL))
 				{
@@ -1125,7 +1682,7 @@
 
 			displace = saveDisplacement;
 
-			itemCurrent = new sbItem (sbItem::TYPE_HEADER, L"Welcome to\nSlideBible!", rect.width());
+			itemCurrent = new sbItem (sbItem::TYPE_HEADER, L"Welcome to\nSlideBible Beta!", rect.width());
 
 			if ( Core->defaultModule != NULL )
 			{
@@ -1147,7 +1704,6 @@
 
 					itemCurrent->attach(new sbItem (sbItem::TYPE_GOTO_MODULES, text, rect.width()), sbItem::NEXT);
 					itemCurrent = itemCurrent->next;
-					itemCurrent->center = true;
 
 					delete [] text;
 				}
@@ -1170,7 +1726,6 @@
 
 					itemCurrent->attach(new sbItem (sbItem::TYPE_GO_HISTORY, text, rect.width(), Core->features.history.size()-1), sbItem::NEXT);
 					itemCurrent = itemCurrent->next;
-					itemCurrent->center = true;
 
 					delete [] text;
 				}
@@ -1179,19 +1734,19 @@
 					workKey.setText ( "John 1:1" );
 					itemCurrent->attach(new sbItem (sbItem::TYPE_BUTTON_BOOKMARK, L" \nRead Bible ...\n ", 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->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;
+				itemCurrent->attach (new sbItem (sbItem::TYPE_OPEN_MODULE_INSTALLER,L"Install Modules ...", rect.width()),sbItem::NEXT);
+				itemCurrent = itemCurrent->next;
 			}
 
-			_sntprintf(tempText,128,L"About :\nVersion built on %S\n Using SWORD version %S",__DATE__,sword::SWVersion::currentVersion.getText());
-			itemCurrent->attach(new sbItem (sbItem::TYPE_DESCRIPTION, tempText, rect.width()), sbItem::NEXT);
+			_sntprintf(tempText,256,L"About :\nBuilt on %S\nUsing SWORD version %S",__DATE__,sword::SWVersion::currentVersion.getText());
+			itemCurrent->attach(new sbItem (sbItem::TYPE_CENTRED_DESCRIPTION, tempText, rect.width()), sbItem::NEXT);
 			itemCurrent = itemCurrent->next;
-			itemCurrent->center = true;
 
 			while ( itemCurrent->prev != NULL ) itemCurrent = itemCurrent->prev;
 		}
@@ -1205,21 +1760,38 @@
 
 				sbAssert ( Core->currentModule == NULL );
 
-				module = Core->currentModule;
+				module = Core->holdString(Core->currentModule->Name());
 
 				clear();
 
 				place.copyFrom ( Core->currentVerse );
 
+				if (itemBanner)
+				{
+					DrawCache.remove(itemBanner);
+					delete itemBanner;
+					itemBanner = NULL;
+				}
+
 				displace = rect.height()*2.0f/5.0f;
 
 				// adding blank verses starts automatically in sbList::onTimer(sbCore::TIMER_BEFORE_REDRAW)
 				// filling with text occurs in sbList::process in another thread
 
 				// update history
-				attachedHistory = Core->features.addHistory(module->Name(),place.Index());
+				attachedHistory = Core->features.addHistory(module,place.Index());
 
 				Core->redraw();
+
+				if (options.size() != Core->moduleOptions.size())
+				{
+					options.resize(Core->moduleOptions.size());
+
+					for (int i=0; i<Core->moduleOptions.size(); i++)
+					{
+						options[i] = Core->holdString(Core->getSword()->getGlobalOption(Core->moduleOptions[i]));
+					}
+				}
 			}
 
 			if (module != NULL)
@@ -1227,14 +1799,35 @@
 				if (next == NULL) attach (new sbList(sbList::TYPE_MODULE_VIEW), sbList::PIN_NEXT);
 				if (prev == NULL) attach (new sbList(sbList::TYPE_MODULE_VIEW), sbList::PIN_PREV);
 
-				Core->threadCreate(this);
+				// if global options changed , reprocess items text
+				bool needReprocess = false;
 
+				if (!Core->changedGlobalOptions)
+				{
+					for (int i = 0; i < options.size(); i++)
+						Core->getSword()->setGlobalOption(Core->moduleOptions[i],options[i]);
+				}
 
-				if (module != NULL)
+				for (int i=0; i < Core->moduleOptions.size(); i++)
 				{
-					Core->currentModule = module;
-					Core->currentVerse.copyFrom ( place );
+					if (strcmp(Core->getSword()->getGlobalOption(Core->moduleOptions[i]),options[i]))
+					{
+						needReprocess = true;
+						options[i] = Core->holdString(Core->getSword()->getGlobalOption(Core->moduleOptions[i]));
+					}
 				}
+
+				if (needReprocess)
+				{
+					for (sbItem * item = itemCurrent; item != NULL; item = item->next) item->processed = false;
+					for (sbItem * item = itemCurrent; item != NULL; item = item->prev) item->processed = false;
+				}
+
+				//Core->threadCreate(this);
+
+				Core->currentModule = Core->getSword()->getModule(module);
+				Core->currentVerse.copyFrom ( place );
+				Core->changedGlobalOptions = false;
 			}
 		}
 		break;
@@ -1260,7 +1853,6 @@
 				mbstowcs(text,book,strlen(book)+1);
 
 				sbItem *item = new sbItem (sbItem::TYPE_BUTTON_SELECTION_BOOK, text, rect.width(), workKey.Index());
-				item->center = true;
 
 				delete [] text;
 
@@ -1293,6 +1885,7 @@
 
 	case TYPE_SELECT_MODULE:
 		{
+			sbItem * tempItem;
 			int id = 0;
 
 			clear();
@@ -1303,15 +1896,10 @@
 
 				if (!strcmp(mod->Type(), "Biblical Texts"))
 				{
-					TCHAR * text = new TCHAR[strlen(mod->Description())+1];
-					for(int i=0; i<=strlen(mod->Description()); i++)
-						text[i] = mod->Description()[i];
+					_sntprintf(tempText,128,L"%S\n<s t=\"6\">%S</s>",mod->Name(),mod->Description());
 
-					sbItem *item = new sbItem (sbItem::TYPE_BUTTON_SELECTION_MODULE, text, rect.width(), (long)mod);
-					item->center = true;
+					sbItem *item = new sbItem (sbItem::TYPE_BUTTON_SELECTION_MODULE, tempText, rect.width(), (long)mod);
 
-					delete [] text;
-
 					if (Core->currentModule == mod) item->highlighted = true;
 
 					if (itemCurrent == NULL)
@@ -1336,15 +1924,10 @@
 
 				if (!strcmp(mod->Type(), "Commentaries"))
 				{
-					TCHAR * text = new TCHAR [strlen(mod->Description())+1];
-					for(int i=0;i<=strlen(mod->Description()); i++)
-						text[i] = mod->Description()[i];
+					_sntprintf(tempText,128,L"%S\n<s t=\"6\">%S</s>",mod->Name(),mod->Description());
 
-					sbItem *item = new sbItem (sbItem::TYPE_BUTTON_SELECTION_MODULE, text, rect.width(), (long)mod);
-					item->center = true;
+					sbItem *item = new sbItem (sbItem::TYPE_BUTTON_SELECTION_MODULE, tempText, rect.width(), (long)mod);
 
-					delete [] text;
-
 					if (Core->currentModule == mod) item->highlighted = true;
 
 					if (itemCurrent == NULL)
@@ -1361,14 +1944,16 @@
 				id++;
 			}
 
+			tempItem = new sbItem (sbItem::TYPE_OPEN_MODULE_INSTALLER,L"Install Modules ...", rect.width());
+
+			if (itemCurrent == NULL) itemCurrent = tempItem; else itemCurrent->attach(tempItem,sbItem::NEXT);
+
 			while (itemCurrent->prev != NULL) itemCurrent = itemCurrent->prev;
 		}
 		break;
 
 	case TYPE_HISTORY:
 		{
-			TCHAR tempText [128];
-
 			bool createdNow = false;
 			bool createdToday = false;
 			bool createdYesterday = false;
@@ -1399,7 +1984,7 @@
 
 			clear();
 			
-			for (int h = Core->features.history.size()-1; h >= 0 ; h--)
+			for (int h = Core->features.history.size()-1; h >= 0 && Core->features.history.size()-h <= 50 ; h--)
 			{
 				sbFeatures::History * hi = &Core->features.history[h];
 
@@ -1414,7 +1999,7 @@
 				{
 					if(!createdNow)
 					{
-						timeHeader = new sbItem (sbItem::TYPE_DESCRIPTION, L"Now", rect.width());
+						timeHeader = new sbItem (sbItem::TYPE_CENTRED_DESCRIPTION, L"Now", rect.width());
 						createdNow = true;
 					}
 				}
@@ -1422,7 +2007,7 @@
 				{
 					if(!createdToday)
 					{
-						timeHeader = new sbItem (sbItem::TYPE_DESCRIPTION, L"Today", rect.width());
+						timeHeader = new sbItem (sbItem::TYPE_CENTRED_DESCRIPTION, L"Today", rect.width());
 						createdToday = true;
 					}
 				}
@@ -1430,7 +2015,7 @@
 				{
 					if(!createdYesterday)
 					{
-						timeHeader = new sbItem (sbItem::TYPE_DESCRIPTION, L"Yesterday", rect.width());
+						timeHeader = new sbItem (sbItem::TYPE_CENTRED_DESCRIPTION, L"Yesterday", rect.width());
 						createdYesterday = true;
 					}
 				}
@@ -1438,27 +2023,25 @@
 				{
 					if(!createdWeek)
 					{
-						timeHeader = new sbItem (sbItem::TYPE_DESCRIPTION, L"Last Week", rect.width());
+						timeHeader = new sbItem (sbItem::TYPE_CENTRED_DESCRIPTION, L"Last Week", rect.width());
 						createdWeek = true;
 					}
 				}
 				else if (!createdOlder)
 				{
-					timeHeader = new sbItem (sbItem::TYPE_DESCRIPTION, L"Older", rect.width());
+					timeHeader = new sbItem (sbItem::TYPE_CENTRED_DESCRIPTION, L"Older", rect.width());
 					createdOlder = true;
 				}
 
 				if (timeHeader != NULL)
 				{
-					timeHeader->center = true;
-
 					if ( itemCurrent == NULL )
 					{
 						itemCurrent = timeHeader;
 					}
 					else
 					{
-						itemCurrent->attach(timeHeader,sbItem::PIN::NEXT);
+						itemCurrent->attach(timeHeader,sbItem::NEXT);
 						itemCurrent = itemCurrent->next;
 					}
 				}
@@ -1471,7 +2054,7 @@
 				}
 				else
 				{
-					itemCurrent->attach(item,sbItem::PIN::NEXT);
+					itemCurrent->attach(item,sbItem::NEXT);
 					itemCurrent = itemCurrent->next;
 				}
 			}
@@ -1516,8 +2099,11 @@
 
 		if (character == 0x08)
 		{
-			text = itemEdit->text;
-			text.erase(--itemEditCursor);
+			if (itemEdit->text.size() > 0)
+			{
+				text = itemEdit->text;
+				text.erase(--itemEditCursor);
+			}
 		}
 		else
 		{
@@ -1620,10 +2206,18 @@
 		Core->redraw();
 		break;
 
-	case 0x1B: //VK_ESCAPE
+	case 0x1B: // VK_ESCAPE
 		sbExit(1);
 		break;
 
+/*	case 0x44: // VK_D
+		Core->initSword();
+		break;
+
+	case 0x42: // VK_B
+		sbAssert(true);
+		break;
+*/
 	default:
 		return false;
 	}

Modified: trunk/src/SlideBible/sbList.h
===================================================================
--- trunk/src/SlideBible/sbList.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbList.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -35,7 +35,6 @@
 		TYPE_CURRENT,                 // virtual, to update current list
 		PIN_NEXT,                     // pin
 		PIN_PREV,                     // pin
-		//PIN_PARENT,                   // pin
 		TYPE_MODULE_VIEW,
 		TYPE_SELECT_MODULE,
 		TYPE_SELECT_BOOK,
@@ -46,20 +45,21 @@
 		TYPE_BOOKMARKS,
 		TYPE_READINGS,
 		TYPE_HISTORY,
-		//TYPE_OPTIONS,
-		//TYPE_SEARCH,                  // virtual
 		TYPE_SEARCH_OPTIONS,
 		TYPE_SEARCH_RESULTS,
-		//TYPE_NAVIGATION,              // virtual
 		TYPE_MENU_EXIT,
 		TYPE_MENU_SELECT_VERSE,
 		TYPE_MENU_SELECT_CHAPTER,
+		TYPE_MENU_OPTIONS,
+		TYPE_MODULE_INSTALLER_DISCLAIMER,
+		TYPE_MODULE_INSTALLER,
+		TYPE_SEARCH,
 		TYPES_COUNT
 	};
 	
 	sbList ( sbList::TYPE type );
 	~sbList ();
- 
+
 	// event handlers
 	void                      onPressed           ( int x, int y );
 	void                      onReleased          ( int x, int y );
@@ -80,7 +80,6 @@
 	void                      render              ( sbSurface rc , bool showPlace = false , int sideDisplacement = 0 );
 
 	float                     displace;
-	//float                     displacePart;
 	int                       screenHeight;
 
 	int                       needScroll;
@@ -99,24 +98,47 @@
 	void                      clear               ();
 	sbItem*                   getItem             ( int x , int y ) const;
 
+	struct sbMenu
+	{
+		sbItem * item;
+		sbRect   rect;
+		int      displace;
+	};
+
+	class sbMinilog
+	{
+		typedef std::list<std::pair<sbItem*,sbPoint>> ITEM;
+		ITEM                  items;
+	};
+
+	sbMinilog                 minilog;
+
 	sbItem                   *itemCurrent;
 	sbItem                   *itemHover;
 	sbItem                   *itemSelected;
 
+	sbItem                   *itemBanner;
 
+	sbItem                   *itemMenu;
+	sbPoint                   menuPosition;
+
 	void                      setEditMode         ( sbItem * item );
 	sbItem                   *itemEdit;
 	int                       itemEditCursor;
 
 	// Module List Related
-	sbItem                   *verseFirst;
-	sbItem                   *verseLast;
 
-	int                       versesForward;
-	int                       versesBackward;
+	struct BOUND
+	{
+		BOUND () { memset (this,0,sizeof(BOUND)); constructed = true; }
 
-	bool                      listStartConstructed;
-	bool                      listEndConstructed;
+		sbItem               *verse;
+		int                   verseCount;
+		bool                  constructed;
+		int                   height;
+	};
+
+	BOUND                     before,after;
 	
 	// List Related
 	sbList                   *next;
@@ -127,13 +149,14 @@
 
 	std::vector<sbControl*>   controls;
 
-
 	sbRect                    rect;
 
+	std::vector<const char *> options;
+
 public:
 	int                       controlSelected;
 
-	sword::SWModule          *module;
+	const char               *module;
 	sword::VerseKey           place;
 
 	int                       attachedReading;

Modified: trunk/src/SlideBible/sbTheme.cpp
===================================================================
--- trunk/src/SlideBible/sbTheme.cpp	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbTheme.cpp	2010-05-24 19:44:18 UTC (rev 235)
@@ -25,13 +25,15 @@
 {
 	XMLNode xml = XMLNode::openFileHelper(".\\theme.xml");
 
-	//const sbRect * screenRect = &Core->Surface(sbCore::SURFACE::TYPE_WHOLE)->rect;
 	size = min(Core->getRect().height(), Core->getRect().width());
 
 	ItemSubTextColor    = sbColor(xml.getChildNodeByPath("List/Item/SubText").getAttribute("color","909090FF"));
 	ItemMenuTextColor   = sbColor(xml.getChildNodeByPath("Menu/Text"        ).getAttribute("color","FFFFFFFF"));
 	SelectionFrameColor = sbColor(xml.getChildNodeByPath("Selection"        ).getAttribute("color","FFE020FF"));
 	FadingColor         = sbColor(xml.getChildNodeByPath("Background/Fade"  ).getAttribute("color","00000060"));
+	ItemStrongColor     = sbColor(xml.getChildNodeByPath("List/Item/Text"   ).getAttribute("colorStrong","22007760"));
+	ItemMorphColor      = sbColor(xml.getChildNodeByPath("List/Item/Text"   ).getAttribute("colorMorph","00553360"));
+	ItemRedColor        = sbColor(xml.getChildNodeByPath("List/Item/Text"   ).getAttribute("colorRed","FFDD0060"));
 	
 	itemMargins.top     = size*atof(xml.getChildNodeByPath("List/Item/Margins").getAttribute("top",   "0.01"));
 	itemMargins.left    = size*atof(xml.getChildNodeByPath("List/Item/Margins").getAttribute("left",  "0.1"));
@@ -48,19 +50,21 @@
 		XMLNode e;
 
 		if (i == ELEMENT::ITEM)
-			e = xml.getChildNodeByPath("List/Item/e",           "<e textColor=\"505050FF\"><s c=\"FFFFFF00\"/></e>");
+			e = xml.getChildNodeByPath("List/Item/e",           "<e textColor=\"505050FF\"><s c=\"F8F8F8FF\"/></e>");
 		else if (i == ELEMENT::ITEM_SEPARATOR)
-			e = xml.getChildNodeByPath("List/ItemSeparator/e",  "<e textColor=\"FFFFFFFF\" gradient=\"1\" vertical=\"1\"><s c=\"66808AFF\"/><s c=\"90B0B8FF\"/></e>");
+			e = xml.getChildNodeByPath("List/ItemSeparator/e",  "<e textColor=\"FFFFFFFF\" gradient=\"1\" vertical=\"1\"><s c=\"66808AAF\"/><s c=\"90B0B8AF\"/></e>");
 		else if (i == ELEMENT::ITEM_HIGHLIGHTED)
 			e = xml.getChildNodeByPath("List/ItemHighlighted/e","<e textColor=\"141414FF\" gradient=\"1\" vertical=\"1\"><s c=\"FF55AA00\"/><s c=\"FF55AA60\"/><s c=\"FF55AA00\"/></e>");
 		else if (i == ELEMENT::ITEM_PRESSED)
-			e = xml.getChildNodeByPath("List/ItemHover/e",      "<e textColor=\"141414FF\" gradient=\"1\" vertical=\"1\"><s c=\"FFFF0000\"/><s c=\"FFFF0060\"/><s c=\"FFFF0000\"/></e>");
+			e = xml.getChildNodeByPath("List/ItemHover/e",      "<e textColor=\"505050FF\"><s c=\"FFFFFF00\"/></e>");//"<e textColor=\"141414FF\" gradient=\"1\" vertical=\"1\"><s c=\"FFFF0000\"/><s c=\"FFFF0060\"/><s c=\"FFFF0000\"/></e>");
 		else if (i == ELEMENT::SEPARATOR)
 			e = xml.getChildNodeByPath("List/Separator/e",      "<e textColor=\"FFFFFFFF\" gradient=\"1\" vertical=\"0\"><s c=\"FFFFFF00\"/><s c=\"E0E0E080\"/><s c=\"FFFFFF00\"/></e>");
 		else if (i == ELEMENT::BACKGROUND)
 			e = xml.getChildNodeByPath("Background/e",          "<e textColor=\"141414FF\"><s c=\"F8F8F8FF\"/></e>");
 		else if (i == ELEMENT::MENU)
 			e = xml.getChildNodeByPath("Menu/Button/e",         "<e textColor=\"FFFFFFFF\" gradient=\"1\" vertical=\"1\"><s c=\"A0C0D0FF\"/><s c=\"9098A0FF\"/></e>");
+		else if (i == ELEMENT::ANOTHER_MENU)
+			e = xml.getChildNodeByPath("Menu/Another/e",         "<e textColor=\"FFFFFFFF\"><s c=\"76808AFF\"/></e>");
 		else if (i == ELEMENT::MENU_PRESSED)
 			e = xml.getChildNodeByPath("Menu/ButtonPressed/e",  "<e textColor=\"141414FF\" gradient=\"1\" vertical=\"1\"><s c=\"CBDADDFF\"/><s c=\"FFFFFFFF\"/></e>");
 		else if (i == ELEMENT::PANEL)
@@ -99,33 +103,39 @@
 	for (int i = 0; i <= strlen ( cfont ); i++) tfont [i] = cfont[i];
 
 	styles[STYLE::TEXT].size          = size*(atof(xml.getChildNodeByPath("List/Item/Text").getAttribute("fontSize","0.08")));
-	styles[STYLE::TEXT].font          = sbMakeFont(styles[STYLE::TEXT].size,         tfont, false, false);
+	styles[STYLE::TEXT].font          = sbMakeFont(styles[STYLE::TEXT].size,           tfont, false, false);
 	
 	styles[STYLE::TEXT_ITALIC].size   = styles[STYLE::TEXT].size;
-	styles[STYLE::TEXT_ITALIC].font   = sbMakeFont(styles[STYLE::TEXT_ITALIC].size,  tfont, false, true);
+	styles[STYLE::TEXT_ITALIC].font   = sbMakeFont(styles[STYLE::TEXT_ITALIC].size,    tfont, false, true);
 	
 	styles[STYLE::BUTTON].size        = size*(atof(xml.getChildNodeByPath("Menu").getAttribute("fontSize","0.093")));
-	styles[STYLE::BUTTON].font        = sbMakeFont(styles[STYLE::BUTTON].size,       tfont, true, false);
+	styles[STYLE::BUTTON].font        = sbMakeFont(styles[STYLE::BUTTON].size,         tfont, true, false);
 	
 	styles[STYLE::BUTTON_SMALL].size  = styles[STYLE::BUTTON].size*2/3;
-	styles[STYLE::BUTTON_SMALL].font  = sbMakeFont(styles[STYLE::BUTTON_SMALL].size, tfont, true, false);
+	styles[STYLE::BUTTON_SMALL].font  = sbMakeFont(styles[STYLE::BUTTON_SMALL].size,   tfont, true, false);
 	
 	styles[STYLE::STANZA].size        = size*(atof(xml.getChildNodeByPath("List/Item/SubText").getAttribute("fontSize","0.06")));
-	styles[STYLE::STANZA].font        = sbMakeFont(styles[STYLE::STANZA].size,       tfont, true, false);
+	styles[STYLE::STANZA].font        = sbMakeFont(styles[STYLE::STANZA].size,         tfont, true, false);
 	
 	styles[STYLE::DESCRIPTION].size   = styles[STYLE::TEXT].size*2/3;
-	styles[STYLE::DESCRIPTION].font   = sbMakeFont(styles[STYLE::DESCRIPTION].size,  tfont, false, false);
+	styles[STYLE::DESCRIPTION].font   = sbMakeFont(styles[STYLE::DESCRIPTION].size,    tfont, false, false);
 	
 	styles[STYLE::CAPTION].size       = styles[STYLE::TEXT].size/2*3;
-	styles[STYLE::CAPTION].font       = sbMakeFont(styles[STYLE::CAPTION].size,      tfont, true, false);
+	styles[STYLE::CAPTION].font       = sbMakeFont(styles[STYLE::CAPTION].size,        tfont, true, false);
 
+	styles[STYLE::TEXT_UNDER].size    = size*(atof(xml.getChildNodeByPath("List/Item/Text").getAttribute("textUnderSize","0.036")));
+	styles[STYLE::TEXT_UNDER].font    = sbMakeFont(styles[STYLE::TEXT_UNDER].size,     tfont, true, false);
+
+	styles[STYLE::TEXT_FOOTNOTE].size = size*(atof(xml.getChildNodeByPath("List/Item/Text").getAttribute("textFootnoteSize","0.05")));
+	styles[STYLE::TEXT_FOOTNOTE].font = sbMakeFont(styles[STYLE::STANZA].TEXT_FOOTNOTE,tfont, true, false);
+
 	delete [] tfont;
 
 	// cache background
-	listBackground = sbSurfaceCreate(max(Core->getRect().width(),Core->getRect().height()),max(Core->getRect().width(),Core->getRect().height()));
+	//listBackground = sbSurfaceCreate(max(Core->getRect().width(),Core->getRect().height()),max(Core->getRect().width(),Core->getRect().height()));
 
-	drawElement(listBackground,&sbRect(Core->getRect().left,Core->getRect().top,Core->getRect().right,Core->getRect().bottom-PanelSize),ELEMENT::BACKGROUND);
-	drawElement(listBackground,&sbRect(Core->getRect().left,Core->getRect().bottom-PanelSize,Core->getRect().right,Core->getRect().bottom),ELEMENT::PANEL);
+	//drawElement(listBackground,&sbRect(Core->getRect().left,Core->getRect().top,Core->getRect().right,Core->getRect().bottom-PanelSize),ELEMENT::BACKGROUND);
+	//drawElement(listBackground,&sbRect(Core->getRect().left,Core->getRect().bottom-PanelSize,Core->getRect().right,Core->getRect().bottom),ELEMENT::PANEL);
 }
 
 sbTheme::~sbTheme()
@@ -137,11 +147,11 @@
 
 void sbTheme::drawElement ( sbSurface rc , const sbRect * rect , sbTheme::ELEMENT::TYPE type ) const
 {
-	if (rc != listBackground && !Core->fadeSurface && (type == ELEMENT::BACKGROUND || type == ELEMENT::PANEL))
-	{
-		sbBitBlt(rc,*rect,listBackground,sbPoint(rect->left,rect->top));
-		return;
-	}
+	//if (rc != listBackground && !Core->fadeSurface && (type == ELEMENT::BACKGROUND || type == ELEMENT::PANEL))
+	//{
+	//	sbBitBlt(rc,*rect,listBackground,sbPoint(rect->left,rect->top));
+	//	return;
+	//}
 
 	for (int i = 0; i < elements[type].fill.size(); i++)
 	{
@@ -235,4 +245,4 @@
 	sbDrawLine(surface, sbPoint(x1,y2-round), sbPoint(x1,y1+round),color,SelectionFrameWidth);
 	sbDrawLine(surface, sbPoint(x1,y1+round), sbPoint(x1+(round/3),y1+(round/3)),color,SelectionFrameWidth);
 	sbDrawLine(surface, sbPoint(x1+(round/3),y1+(round/3)), sbPoint(x1+round,y1),color,SelectionFrameWidth);
-}
\ No newline at end of file
+}

Modified: trunk/src/SlideBible/sbTheme.h
===================================================================
--- trunk/src/SlideBible/sbTheme.h	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/sbTheme.h	2010-05-24 19:44:18 UTC (rev 235)
@@ -30,6 +30,9 @@
 	sbColor               fadeColor ( const sbColor & color, int x, int y ) const;
 
 	sbColor               ItemSubTextColor;
+	sbColor               ItemStrongColor;
+	sbColor               ItemMorphColor;
+	sbColor               ItemRedColor;
 	sbColor               ItemMenuTextColor;
 	sbColor               SelectionFrameColor;
 	sbColor               FadingColor;
@@ -40,6 +43,8 @@
 		{
 			TEXT = 0,
 			TEXT_ITALIC,
+			TEXT_UNDER,
+			TEXT_FOOTNOTE,
 			BUTTON,
 			BUTTON_SMALL,
 			STANZA,
@@ -71,6 +76,7 @@
 			//PANEL_SELECTED,
 			MENU,
 			MENU_PRESSED,
+			ANOTHER_MENU,
 			//MENU_SELECTED,
 			BANNER,
 			COUNT

Modified: trunk/src/SlideBible/todo.txt
===================================================================
--- trunk/src/SlideBible/todo.txt	2010-04-19 20:23:37 UTC (rev 234)
+++ trunk/src/SlideBible/todo.txt	2010-05-24 19:44:18 UTC (rev 235)
@@ -1,27 +1,43 @@
 ALPHA
-+	render tasks
-+		stretch mode - render performed on surface with custom size, then StretchBlt on screen
-+		cache background on first render
-+		render recieve horizontal displacement
-+		remove sbCore::SURFACE
-+	keypad
-+		cursor
-+		active control
-+		control / list mode
-+			method to smooth-delayed-scroll list
-+	lists instead menus
 +	combining unicode accents, like accute, should be in platform-dependent part [I don't know how it's fixed]
--	move to msvs 2010 express
-+	fix sbList::rect
 +	2. Ïàðàëèïîìå\níîí\n4 in chapter title
 +	text retriveing stopped on empty verses
 +	close menus on fail-click
++	limit history
++	currentVerse from defaultModule
++	perfomance optimization: sbItem caching, can work only if background is solid
++	banner showing current place make as sbItem
++	Global Options switch in one module cause switch in another
+	do not break lines if there is only one character on the next line.
+	module manager
+		raise connection
++		reinit Sword
++		message boxes before installing module
++		installManager data in special folder
 	module features
++		options dialog
 		words of Christ in red
-		strongs and morphs
++		strongs and morphs
 		headings
-		options dialog
+		cross-references
+		footnotes
++		option sbItem with text like "Strongs: On" + option value enumeration
+	search
+		clucence
++		input text items
++			sip control
+			cursor
+		range selection
+			menus in PlaceSelection dialog: Search From | Search To
+		request encoding ?
+	lexicon / dictionary modules
 	testament persitence check
+	better strongs/morphs placement in sbItem text
+	sbItem::getItem (sbDirection)
+		global directions NEXT, PREV, LEFT, RIGHT
+	sometime DrawCache mix up items
+	
+	XNA port
 
 
 	loading all locales takes too long
@@ -29,14 +45,12 @@
 		also look into xiphos dirent.cpp
 		maybe deploy packages for only language
 	warning war - clean build log from warnings
-	perfomance optimization
-		sbItem::LINE caching
-		can work only if background is solid
 	controls, pressed/released
 	volume +/- scroll half of screen, long press linvolve cinetic scroll with increasing speed, zoom-/+ scroll as mouse scroll
 	built-in theme
 		version tag in theme xml
-		export theme on start if not exist
+			if version == 0 - always replace
+			if version != built-in version replace with built-in version
 	in chapter selection dialog on book expanding , move book item up
 	make chapter selection dialog with large buttons and scrolling
 	menu on long tap will be small with only text, as in opera mini
@@ -48,8 +62,21 @@
 	scrollbar
 		count list height, if listStartConstructed and listEndConstructed
 		proper method to scroll list
+	
+	Framework Improvements
+		named constructors for sbItem
+		sbItem: visual action parameter
+		remove sbControl
+		sbItem * sbList::panel
+		sbItem * sbList::menu
+		sbList::BOUND sbList::before,after {pixels,lastItem,numItems,finished}
+		wait mode
+			sbWaitMode ( const TCHAR * )
+			search accepts void (*precent) (char , void *)
+			module installer - ?
+		menus based on sbList
+?		divide from backend
 
-
 BETA
 	to test
 		other locales, utf encoding
@@ -59,16 +86,8 @@
 			Greek
 
 1.1 RELEASE
-	search
-		clucence
-		input text items
-+			sip control
-			cursor
-?			copy/paste
 	different screens and runtime orientation change
 		g-sensor option
-	cross-references, footnotes
-		will be shown in verse context menu, or by multitouch expand
 	daily devotionals
 	genbooks
 	dictionaries
@@ -91,7 +110,6 @@
 	icons and graphics
 		graphics theme uses large png file
 		remove built-in theme, application will not run if theme not found
-	module manager
 	unlock locked modules
 
 1.3 RELEASE




More information about the sword-cvs mailing list