Index: /gs2-extensions/iOs-3.x/trunk/Classes/AppDefs.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/AppDefs.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/AppDefs.h	(revision 22603)
@@ -0,0 +1,29 @@
+
+#define TOP_NAVBAR_HEIGHT 45.0f
+#define BOT_NAVBAR_HEIGHT 40.0f
+
+enum UIButtonBarStyle 
+{
+  barstyleBlue = 0, barstyleBlack = 1, barstyleTransparent=2
+};
+
+
+typedef enum
+{
+  UITransitionNothing = 0,
+  UITransitionBothShiftLeft = 1,
+  UITransitionBothShiftRight = 2,
+  UITransitionBothShiftUp = 3,
+  UITransitionError4 = 4,
+  UITransitionCurrentShiftDown = 5,
+  UITransitionError6 = 6,
+  UITransitionBothShiftDown = 7,
+  UITransitionNextShiftUp = 8,
+  UITransitionNextShiftDown = 9
+} UITransitionStyle;
+
+enum GSButtonBarEnum
+{
+  GSBBBrowse=1, GSBBQuery=2, GSBBPref=3
+};
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/BrowseCascadeView.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/BrowseCascadeView.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/BrowseCascadeView.h	(revision 22603)
@@ -0,0 +1,22 @@
+
+#import "Foundation/NSTimer.h"
+#import "MenuCascadeView.h"
+
+@interface BrowseCascadeView: MenuCascadeView 
+{}
+
+-(UIView*) directEntry:(int)rowId;
+
+-(void) browseListToMenuItems:(NSMutableArray*)browseList withCollection:(NSString*)collection withGID:(NSString*)gid;
+
+-(void) createChildMenu:(NSString*)collection withTitle:(NSString*)title withGID:(NSString*)gid 
+           withBrowseList:(NSMutableArray*) browseList;
+
+-(void) tableRowSelected:(NSNotification*)notification;
+
+-(void) asynchronousLoad:(NSTimer*)timer;
+
+-(void) navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button;
+
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/BrowseCascadeView.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/BrowseCascadeView.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/BrowseCascadeView.mm	(revision 22603)
@@ -0,0 +1,210 @@
+
+#import <Foundation/Foundation.h>
+
+#import <UIKit/CDStructures.h>
+#import <UIKit/UIKit.h>
+#import <UIKit/UITable.h>
+#import <UIKit/UIProgressIndicator.h>
+
+#import "GreenstoneApplication.h"
+#import "GreenstoneAPI.h"
+//#import "SimpleWebView.h"
+#import "GSResultItem.h"
+
+#import "BrowseCascadeView.h"
+
+// ***** think about coding for orientation of iPod!!!!
+
+@implementation BrowseCascadeView
+
+
+-(UIView*) directEntry:(int)rowId
+{
+  return self;
+}
+
+
+-(void) browseListToMenuItems:(NSMutableArray*)browseList withCollection:(NSString*)collection withGID:(NSString*)gid
+{  
+  GreenstoneAPI* greenstoneAPI = [GreenstoneApplication greenstoneAPI];
+
+  NSEnumerator* browselist_enumerator = [browseList objectEnumerator];
+  NSString* childname;
+  while (childname = [browselist_enumerator nextObject]) {
+    NSString* childGID = [NSString alloc];
+
+    if (gid==nil) {
+      childGID = [childGID initWithString:childname];
+    }
+    else if ([childname hasPrefix:@"."]==NO) {
+      childGID = [childGID initWithString:childname];
+    }
+    else {
+      childGID = [childGID initWithFormat:@"%@%@",gid,childname]; 
+    }
+
+    GreenstoneApplication* toplevelApp = [GreenstoneApplication toplevelApp];
+    NSString* lang = [toplevelApp languagePref];
+    //greenstoneAPI->setLanguage(lang); // *****
+    greenstoneAPI->setLanguage("en"); 
+
+    // look up Title metadata for child's GID, and use that to display on menu
+    NSString* textTitle = nil;
+    if ([childGID hasPrefix:@"CL"]==YES) {
+      textTitle = greenstoneAPI->getMetadataFirst(collection,childGID,@"Title");
+    }
+    else {
+      // Try for dc.Title first as generally better quality than ex.Title
+      textTitle = greenstoneAPI->getMetadataFirst(collection,childGID,@"dc.Title");
+      if (textTitle == nil) {
+	textTitle = greenstoneAPI->getMetadataFirst(collection,childGID,@"Title");
+      }
+    }
+
+    [(BrowseCascadeView*)_childMenu appendMenuItem:self withItem:textTitle withGID:childGID];      
+
+  }
+}
+
+-(void) createChildMenu:(NSString*)collection withTitle:(NSString*)title withGID:(NSString*)gid 
+            withBrowseList:(NSMutableArray*) browseList
+{
+  CGRect rect = [GreenstoneApplication workAreaRect];  
+
+  // The following check isn't strictly necessary, if _childMenu is released and set to nil
+  // when you transition back to the parent
+  if (_childMenu != nil) {
+    // [_childMenu release];  // *****
+  }
+
+  _childMenu = [BrowseCascadeView alloc];
+  _childMenu = [(BrowseCascadeView*)_childMenu initWithFrame:rect withParent:self withCollection:collection withTitle:title withGID:gid]; 
+
+  [self browseListToMenuItems:browseList withCollection:collection withGID:gid];
+}
+
+
+
+-(void) tableRowSelected:(NSNotification*)notification
+{
+  UITable* table = [notification object];
+  int rowId = [table selectedRow];
+
+  UITableCell* cell = [table cellAtRow:rowId column:0];
+  [cell setSelected:FALSE withFade:TRUE];
+
+
+  GreenstoneAPI* greenstoneAPI = [GreenstoneApplication greenstoneAPI];
+  NSString* childTitle = [[_oidItem objectAtIndex:rowId] title];
+  int transStyle = UITransitionBothShiftLeft;
+
+  GreenstoneApplication* toplevelApp = [GreenstoneApplication toplevelApp];
+  NSString* lang = [toplevelApp languagePref];
+  //greenstoneAPI->setLanguage(lang); // ***** make it a param (with default) to calling fns
+  greenstoneAPI->setLanguage("en");
+
+  // Initialise with child menu
+
+  if (_collection == nil) {
+    // Root node to Browse Greenstone collections
+    NSString* childGID = [[_oidItem  objectAtIndex:rowId] oid]; 
+
+    NSString* chosenCollection = [[NSString alloc] initWithString:childGID];
+
+    NSMutableArray* classifierList = greenstoneAPI->browseToplevelList(chosenCollection);
+    [self createChildMenu:chosenCollection withTitle:childTitle withGID:nil withBrowseList:classifierList];
+    [classifierList release]; 
+
+    [GreenstoneApplication setInCollection:chosenCollection];
+    [GreenstoneApplication transitionView:transStyle fromView:self toView:_childMenu];
+  }
+  else {
+    NSString* childGID = [[_oidItem  objectAtIndex:rowId] oid]; 
+
+    if ([childGID hasPrefix:@"CL"]==YES) {
+      // Note this test is potentially flawed if a document ID starts CL...
+      // Allow this for now, since default is for it to be HASH 
+
+      NSMutableArray* classifierList = greenstoneAPI->browseClassifierList(_collection,childGID);
+
+      NSString* chosenCollection = [[NSString alloc] initWithString:_collection];
+      [self createChildMenu:chosenCollection withTitle:childTitle withGID:childGID withBrowseList:classifierList];
+      [classifierList release]; 
+
+      [GreenstoneApplication transitionView:transStyle fromView:self toView:_childMenu];
+    }
+    else {
+      NSString* childGID = [[_oidItem  objectAtIndex:rowId] oid]; 
+
+      NSString* srcurl = greenstoneAPI->getSrcUrlMetadata(_collection,childGID);
+      NSURL* url = [NSURL alloc];
+
+      if (srcurl == nil) {
+
+	NSTimer *timer = [ NSTimer scheduledTimerWithTimeInterval: 1.0 // used to be 0.3, then 0.5
+			 target: self
+			 selector: @selector(asynchronousLoad:)
+			 userInfo: childGID
+			 repeats: NO ];
+
+	url = [url initWithString:@"file:///var/code/gs2-runtime-svn/ext/iOS3.x/loading.html"]; // **** make it use proper gsdlhome
+
+      }
+      else {
+	NSString* fullurlstr = [[NSString alloc] initWithFormat:@"file://%@",srcurl];
+
+	url = [url initWithString:fullurlstr];
+	NSLog(@"** opening src URL= %@",fullurlstr);
+
+      }
+      [GreenstoneApplication showWebView:transStyle fromView:self withURL:url];
+
+    }
+  }
+}
+
+
+
+
+-(void) asynchronousLoad:(NSTimer*)timer
+{
+  NSString* childGID = [timer userInfo];
+
+  [GreenstoneApplication startWebViewBusy];
+
+  GreenstoneAPI* greenstoneAPI = [GreenstoneApplication greenstoneAPI];
+  GreenstoneApplication* toplevelApp = [GreenstoneApplication toplevelApp];
+  NSString* lang = [toplevelApp languagePref];
+  //greenstoneAPI->setLanguage(lang); // ***** make param
+  greenstoneAPI->setLanguage("en"); 
+
+  NSString* doctext = greenstoneAPI->getResolvedDocument(_collection,childGID);
+
+  [doctext writeToFile:@"/tmp/gsdoc.html" atomically:NO encoding:NSUTF8StringEncoding error:nil];
+  NSURL* url = [[NSURL alloc] initWithString:@"file:///tmp/gsdoc.html"];
+  system("chmod a+rw /tmp/gsdoc.html"); 
+  
+  [GreenstoneApplication loadURL:url];
+  // [GreenstoneApplication showWebView:0 fromView:self withURL:url]; // ****
+
+  [GreenstoneApplication stopWebViewBusy];
+}
+
+
+-(void) navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button 
+{
+  NSLog(@"_gid = %@",_gid);
+
+  switch (button) 
+  {
+    case 1:  // left button (back)
+      // if ([_gid hasPrefix:@"CL"]==YES) { // ****
+      if (_gid == nil) {
+	[GreenstoneApplication setInCollection:nil];
+      }
+      break;
+  }
+
+  [super navigationBar:navbar buttonClicked:button];
+}
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/GSResultItem.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/GSResultItem.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/GSResultItem.h	(revision 22603)
@@ -0,0 +1,24 @@
+
+#import <Foundation/NSString.h>
+
+
+// ***** rename to OIDItem
+// replace all gid with oid ...
+
+@interface GSResultItem: NSObject
+{
+  NSString* _oid;
+  NSString* _title;
+  NSString* _srcurl;
+}
+
+-(id) initWithOID:(NSString*)oid withTitle:(NSString*)title;
+-(id) initWithOID:(NSString*)oid withTitle:(NSString*)title withSrcUrl:(NSString*)srcurl;
+
+-(NSString*) oid;
+-(NSString*) title;
+-(NSString*) srcurl;
+
+-(void) dealloc;
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/GSResultItem.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/GSResultItem.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/GSResultItem.mm	(revision 22603)
@@ -0,0 +1,59 @@
+#import "GSResultItem.h"
+
+@implementation GSResultItem
+
+-(id) initWithOID:(NSString*)oid withTitle:(NSString*)title
+{
+  return [self initWithOID:oid withTitle:title withSrcUrl:nil];
+}
+
+-(id) initWithOID:(NSString*)oid withTitle:(NSString*)title withSrcUrl:(NSString*)srcurl
+{
+  self = [super init];
+
+  _oid = oid;
+  _title = title;
+  _srcurl = srcurl;
+
+  return self;
+}
+
+-(NSString*) oid
+{
+  return _oid;
+}
+
+-(NSString*) title 
+{
+  return _title;
+}
+
+-(NSString*) srcurl
+{
+  return _srcurl;
+}
+
+
+/*
+-(void) printUnused // ******
+{
+  printf("(");
+  [_oid print];
+  printf(",");
+  [_title print];
+  printf(",");
+  [_srcurl print];
+  printf(")");
+}
+*/
+
+-(void) dealloc
+{
+  [_oid release];
+  [_title release];
+  [_srcurl release];
+
+  [super dealloc];
+}
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneAPI.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneAPI.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneAPI.h	(revision 22603)
@@ -0,0 +1,66 @@
+#include "fileutil.h"
+#include "nullproto.h"
+#include "collectset.h"
+
+#import <Foundation/NSArray.h>
+
+#import <UIKit/UIApplication.h>
+
+class GreenstoneAPI
+{
+ public:
+  GreenstoneAPI(UIApplication* toplevelApp);
+  virtual ~GreenstoneAPI();
+
+  bool sanityCheck();
+  NSMutableArray* collectionList();
+  ColInfoResponse_t& collectInfo (const text_t& collection);
+  ColInfoResponse_t& collectInfo (NSString* nscollection);
+
+  void setLanguage(const text_t& lang) { _lang = lang; }
+
+  NSString* collectionmetaValue(ColInfoResponse_t& colinfo, text_t key);
+  NSString* collectionName(ColInfoResponse_t& colinfo);
+
+  NSString* getDocument(NSString* nscollection, NSString* nsgid); // ******
+  NSString* getResolvedDocument(NSString* nscollection, NSString* nsgid);
+
+  NSMutableArray* getMetadata(NSString* nscollection, NSString* nsgid, NSString* nsmetaname);
+  NSString* getMetadataFirst(NSString* nscollection, NSString* nsgid, NSString* nsmetaname);
+  NSString* getMetadataFirst(const text_t& collection, text_t& gid, text_t& metaname);
+
+  NSString* getSrcUrlMetadata(NSString* nscollection, NSString* nsgid);
+
+  NSMutableArray* browseClassifierList(NSString* nscollection, NSString* nsgid);
+  NSMutableArray* browseToplevelList(NSString* nscollection);
+
+  NSMutableArray* query(NSString* nscollection, NSString* nsquery);
+
+
+  
+  void alert(NSString* nslevel, NSString* nsmessage);
+  void alert(char* level, char* message);
+  void alert(text_t level, text_t message);
+
+ protected:
+  text_t resolveUrls(const text_t& unresolved, const text_t& collection, const text_t& archivedir);
+  text_t srclinkToUrl(const text_t& srclink, const text_t& collection, const text_t& archivedir);
+
+  bool recurse_contents(const text_t& collection, ResultDocInfo_t& section,
+			text_tset& metadata, text_t& output_text);
+
+
+  void set_queryfilter_options (const text_t& collection, FilterRequest_t &request, const text_t &querystring);
+  NSMutableArray* filterResponseToTitlesList(const text_t& collection, FilterResponse_t &sections);
+  NSMutableArray* search_single_collection (const text_t& collection, const text_t& query);
+
+ protected:
+  UIApplication* _toplevelApp;
+  text_t _lang;
+
+  collectset*   _cservers;
+  nullproto*    _nproto;
+  text_t        _gsdlhome;
+  text_t        _collecthome;
+};
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneAPI.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneAPI.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneAPI.mm	(revision 22603)
@@ -0,0 +1,827 @@
+
+#include <unistd.h>
+#include <sys/dir.h>
+
+#include "gsdlsitecfg.h"
+#include "recptprototools.h"
+
+#import <Foundation/NSString.h>
+#import <Foundation/NSArray.h>
+
+#import <UIKit/UIKit.h>
+
+#import "GSResultItem.h"
+#import "GreenstoneAPI.h"
+
+GreenstoneAPI::GreenstoneAPI(UIApplication* toplevelApp) 
+  : _toplevelApp(toplevelApp), _lang("en"),
+    _cservers(nil), _nproto(nil), _gsdlhome(), _collecthome()
+{
+  _cservers = new collectset(_gsdlhome,_collecthome); // sets gsdlhome and collecthome
+
+  cerr << "gsdlhome = " << _gsdlhome << endl;
+  cerr << "collecthome = " << _collecthome << endl;
+
+  // set up the null protocol
+  _nproto = new nullproto();
+  _nproto->set_collectset(_cservers);
+
+  comerror_t comerr = noError;
+  bool init_status = _nproto->init(comerr,cerr);
+  if (init_status==false) {
+    alert("Null Proto","null proto init returned false");
+  }
+
+  if (comerr!=noError) {
+    text_t error_message = get_comerror_string (comerr);
+    alert("Protocol Init Error",error_message);
+  }
+
+}
+
+
+GreenstoneAPI::~GreenstoneAPI()
+{
+  delete _cservers;
+  delete _nproto;
+
+}
+
+void GreenstoneAPI::alert(NSString* nslevel, NSString* nsmessage)
+{
+  // Alert sheet displayed at centre of screen.
+
+  NSArray *buttons = [NSArray arrayWithObjects:@"OK", nil];
+  UIActionSheet *alertSheet = [UIActionSheet alloc];
+  [alertSheet initWithTitle:nslevel buttons:buttons 
+    defaultButtonIndex:1 delegate:_toplevelApp context:nil];
+
+  [alertSheet setBodyText:nsmessage];
+  [alertSheet popupAlertAnimated:YES];
+}
+
+
+void GreenstoneAPI::alert(char* level, char* message)
+{
+  // Alert sheet displayed at centre of screen.
+
+  NSString* nslevel = [[NSString alloc] initWithCString: level];
+  NSString* nsmessage = [[NSString alloc] initWithCString: message];
+
+  alert(nslevel,nsmessage);
+
+  [nslevel release];
+  [nsmessage release];
+}
+
+void GreenstoneAPI::alert(text_t level, text_t message)
+{
+  char* level_cstr = level.getcstr();
+  char* message_cstr = message.getcstr();
+
+  alert(level_cstr,message_cstr);
+
+  delete [] level_cstr;
+  delete [] message_cstr;
+}
+
+bool GreenstoneAPI::sanityCheck()
+{  
+  text_t gsdl_home, unused_collecthome;
+  text_t unused_httpdomain,unused_httpprefix;
+  if (!site_cfg_read(gsdl_home,unused_collecthome,
+		     unused_httpdomain,unused_httpprefix)) {
+    // couldn't find gsdlsite.cfg file    
+
+    char cwd[128];
+    getcwd(cwd,128);
+
+    text_t sitecfg_filename = cwd;
+    sitecfg_filename += "gsdlsite.cfg"; 
+    
+    alert("Error","Unable to find " + sitecfg_filename );
+    return false;
+  }
+
+  text_t collect_dir = filename_cat(gsdl_home,"collect");
+  char* collect_dir_cstr = collect_dir.getcstr();
+
+  DIR* directorypointer = opendir(collect_dir_cstr);	
+  delete [] collect_dir_cstr;
+
+  if(directorypointer == NULL)	//If the directory could not be opened
+    {  
+      text_t mess = "No collections directory.  Please make one at: " + collect_dir;
+      alert("Error",mess);
+      return false;
+    }
+ 
+  return true;
+}
+
+
+NSMutableArray* GreenstoneAPI::collectionList()
+{
+  text_tarray collection_list;
+  comerror_t comerr;
+  
+  _nproto->get_collection_list (collection_list, comerr, cerr);
+
+  if (comerr != noError) {
+    alert("Error",get_comerror_string(comerr));
+    return nil;
+  }
+
+  int num_cols = collection_list.size();
+
+  NSMutableArray* nscollist = [[NSMutableArray alloc] initWithCapacity:num_cols];
+
+  text_tarray::iterator collection_iterator = collection_list.begin();
+  while (collection_iterator != collection_list.end())
+  {
+    text_t& colname = *collection_iterator;
+    char* colname_cstr = colname.getcstr();
+    NSString* nscolname = [[NSString alloc ] initWithCString: colname_cstr];
+    delete [] colname_cstr;
+
+    [nscollist addObject:nscolname];
+
+    collection_iterator++;
+  }
+
+  return nscollist;
+}
+
+ColInfoResponse_t& GreenstoneAPI::collectInfo (const text_t &collection)
+{
+  ColInfoResponse_t& collectinfo = *new ColInfoResponse_t();
+  comerror_t comerr;
+  _nproto->get_collectinfo(collection, collectinfo,comerr, cerr);
+
+  if (comerr != noError) {
+    alert("Error",get_comerror_string(comerr));
+  }
+
+  return collectinfo;
+}
+
+ColInfoResponse_t& GreenstoneAPI::collectInfo (NSString* nscollection)
+{
+  char const* nscollection_cstr  = [nscollection UTF8String]; 
+
+  ColInfoResponse_t& colinfo = collectInfo(nscollection_cstr);
+
+  // according to documentation, nscollectcion_cstr autorealeased
+  // => don't need to free them
+  return colinfo;
+}
+
+/* ****
+text_t GreenstoneAPI::lookupLanguagePref()
+{
+  NSString* nslang = [(GreenstoneApplication*)_toplevelApp languagePref];
+  char* lang_cstr = [nslang UTF8String];
+  text_t lang = lang_cstr;
+  [nslang release];
+
+  return lang;
+}
+*/
+
+NSString* GreenstoneAPI::collectionmetaValue(ColInfoResponse_t& colinfo,
+					     text_t key)
+{
+  text_t val = colinfo.get_collectionmeta(key,_lang);
+  char* val_cstr = val.getcstr();
+
+  NSString* nsval = [[NSString alloc] initWithCString:val_cstr];
+  delete [] val_cstr;
+
+
+  return nsval;
+}
+
+
+NSString* GreenstoneAPI::collectionName(ColInfoResponse_t& colinfo)
+{
+  return collectionmetaValue(colinfo,"collectionname");
+}
+
+
+NSString* TextTToNSString(text_t& text)
+{
+  // Make this available to other parts of program!!!
+  if (text.empty()) { return nil; }
+
+  char* text_cstr = text.getcstr();
+  NSString* nstext = [[NSString alloc ] initWithCString: text_cstr];
+  delete [] text_cstr;
+
+  return nstext;
+}
+
+bool GreenstoneAPI::recurse_contents(const text_t& collection, ResultDocInfo_t& section,
+				     text_tset& metadata, text_t& output_text)
+{  
+  // Output this section 
+  	
+  // 1. Get the title
+
+  text_t title = section.metadata["Title"].values[0];
+  output_text.append("<h3>"+title+"</h3>");
+
+  // cerr << "**** Title = " << title << endl;
+
+  // 2. Get the text
+  DocumentRequest_t docrequest;
+  DocumentResponse_t docresponse;
+  comerror_t comerr;
+  docrequest.OID = section.OID;
+
+  _nproto->get_document(collection, docrequest, docresponse, comerr, cerr);
+
+  if (comerr != noError) {
+    alert("Error",get_comerror_string(comerr));
+    return false;
+  }
+
+  output_text.append(docresponse.doc);
+	
+  // cerr << "*** appending text " << docresponse.doc << endl;
+
+  int haschildren = section.metadata["haschildren"].values[0].getint();
+  	
+  // recurse through children
+  if (haschildren == 1)
+    {
+      bool getParents = false;
+      FilterResponse_t tmp;
+
+      get_children (section.OID, collection, _lang, metadata, getParents, _nproto, tmp, cerr);
+      ResultDocInfo_tarray::iterator thisdoc = tmp.docInfo.begin();
+      ResultDocInfo_tarray::iterator lastdoc = tmp.docInfo.end();
+      
+      while (thisdoc != lastdoc) 
+	{
+	  bool recurse_ok = recurse_contents(collection,*thisdoc, metadata, output_text);
+	  if (!recurse_ok) {
+	    return false;
+	  }
+	  ++thisdoc;
+	}
+    }
+	
+  return true;
+}
+
+
+NSString* GreenstoneAPI::getResolvedDocument(NSString* nscollection, NSString* nsgid)
+{
+  char const* nscollection_cstr  = [nscollection UTF8String]; 
+  char const* nsgid_cstr         = [nsgid UTF8String]; 
+
+  text_t collection(nscollection_cstr);
+  text_t gid(nsgid_cstr);
+
+  //metadata elements needed by recurse_contents
+  text_tset metadata;
+  metadata.insert ("Title");
+  metadata.insert ("haschildren");
+
+  bool getParents = false;
+
+  FilterResponse_t inforesponse;
+  comerror_t comerr;
+
+  NSString* nsresolvedtext = nil;
+
+  if (get_info(gid, collection, _lang, metadata, getParents, _nproto, inforesponse, cerr))
+    {
+      text_t output_text;
+      text_t make_utf8 = "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n";
+
+      output_text.append("<html>\n");
+      output_text.append("  <head>\n"+make_utf8+"  </head>\n");
+
+      if (recurse_contents(collection,inforesponse.docInfo[0], metadata, output_text)) {
+
+	// cerr << "**** text = " << output_text << endl;
+
+	  // retrieve [archivedir] for this document id
+	  NSString* nsarchivedir = getMetadataFirst(nscollection,nsgid,@"archivedir");
+	  const char* nsarchivedir_cstr = [nsarchivedir UTF8String]; 
+	  text_t archivedir = nsarchivedir_cstr;
+	  [nsarchivedir release];
+	  
+	  text_t resolved_text = resolveUrls(output_text,collection,archivedir);
+	  
+	  char* resolved_text_cstr = resolved_text.getcstr();
+	  nsresolvedtext = [[NSString alloc] initWithCString:resolved_text_cstr];
+	  
+	  delete [] resolved_text_cstr;
+	  }
+      else {
+	alert("Error","Failed to get info for " + gid);
+      }
+      output_text.append("</html>\n");
+    }
+  else {
+    alert("Error","Failed to get info for " + gid);
+  }
+
+
+  return nsresolvedtext;
+}
+
+
+NSMutableArray* GreenstoneAPI::getMetadata(NSString* nscollection, NSString* nsgid, NSString* nsmetaname)
+{
+  char const* nscollection_cstr  = [nscollection UTF8String]; 
+  char const* nsgid_cstr         = [nsgid UTF8String]; 
+  char const* nsmetaname_cstr    = [nsmetaname UTF8String]; 
+
+  NSMutableArray* nsmdlist = nil;
+
+  text_t collection(nscollection_cstr);
+  text_t gid(nsgid_cstr);
+  text_t metaname(nsmetaname_cstr);
+
+  text_tset metadata;
+  metadata.insert (metaname);
+  bool getParents = false;
+  FilterResponse_t response;
+
+  if (get_info (gid, collection, _lang, metadata, getParents, _nproto, response, cerr)) {
+    int num_browse_by = response.docInfo.size();
+    if (num_browse_by>0) {
+      MetadataInfo_tmap& metadata = response.docInfo[0].metadata;
+      MetadataInfo_t& metaname_info = metadata[nsmetaname_cstr];
+      int num_browse_by = metaname_info.values.size();
+      if (num_browse_by>0) {
+	// protocol will return 1 even if there is no metadata
+	// values will be the empty string
+
+	nsmdlist = [[NSMutableArray alloc] initWithCapacity:num_browse_by];
+	
+	text_tarray& meta_val = metaname_info.values;
+	text_tarray::iterator md_iterator = meta_val.begin();
+	while (md_iterator != meta_val.end()) {
+	  text_t& mdval = *md_iterator;
+
+	  NSString* nsmdval = TextTToNSString(mdval);	  
+	  if (nsmdval != nil) {
+	    [nsmdlist addObject:nsmdval];
+	  }
+
+	  md_iterator++;	      
+	}
+
+	if ([nsmdlist count] == 0) {
+	  // no valid metadata => free list and set to nil
+	  [nsmdlist release];
+	  nsmdlist = nil;
+	}
+      }
+      else {
+	alert("Error","OID" + gid + "does not have metadata for" + metaname);
+      }
+    }
+    else {
+      alert("Error","OID" + gid + "does not have metadata for" + metaname);
+    }
+  }
+  else {
+    alert("Error","Collection has no browsing capabilities" + gid);
+  }
+
+  // according to documentation, nscollectcion_cstr, nsgid_cstr and nsmetaname_cstr autorealeased
+  // => don't need to free them
+
+  return nsmdlist;
+}
+
+
+NSString* GreenstoneAPI::getMetadataFirst(NSString* nscollection, NSString* nsgid, NSString* nsmetaname)
+{
+  NSMutableArray* all_metavalues = getMetadata(nscollection,nsgid,nsmetaname);
+ 
+  NSString* first_metavalue_copy = nil;
+
+  if (all_metavalues != nil) {
+    NSString* first_metavalue = [all_metavalues objectAtIndex:0];
+
+    first_metavalue_copy = [[NSString alloc] initWithString:first_metavalue];
+
+    [all_metavalues release];
+  }
+
+  return first_metavalue_copy;
+}
+
+NSString* GreenstoneAPI::getMetadataFirst(const text_t& collection, text_t& gid, text_t& metaname)
+{
+  char* collection_cstr = collection.getcstr();
+  char* gid_cstr = gid.getcstr();
+  char* metaname_cstr = metaname.getcstr();
+
+  NSString* nscollection = [[NSString alloc] initWithCString:collection_cstr];
+  NSString* nsgid = [[NSString alloc] initWithCString:gid_cstr];
+  NSString* nsmetaname = [[NSString alloc] initWithCString:metaname_cstr];
+
+  NSString* result = getMetadataFirst(nscollection,nsgid,nsmetaname);
+
+  delete [] collection_cstr;
+  delete [] gid_cstr;
+  delete [] metaname_cstr;
+
+  return result;
+
+}
+
+NSMutableArray* GreenstoneAPI::browseClassifierList(NSString* nscollection, NSString* nsgid)
+{
+  // **** upgrade this to use getMetadata, and then split on ';'
+
+  char const* nscollection_cstr  = [nscollection UTF8String]; 
+  char const* nsgid_cstr  = [nsgid UTF8String]; 
+
+  text_t gid = nsgid_cstr;
+
+  NSMutableArray* nscllist = nil;
+
+  text_tset metadata;
+  metadata.insert ("contains");
+  FilterResponse_t response;
+  comerror_t comerr;
+  
+  if (get_info (nsgid_cstr, nscollection_cstr, _lang, metadata, false, _nproto, response, cerr)) {
+    int num_browse_by = response.docInfo.size();
+    if (num_browse_by >0) {
+      MetadataInfo_tmap& metadata = response.docInfo[0].metadata;
+      MetadataInfo_t& contains = metadata["contains"];
+      int num_browse_by = contains.values.size();
+      if (num_browse_by>0) {
+
+	// nscllist = [[NSMutableArray alloc] initWithCapacity:num_browse_by]; ****
+	nscllist = [[NSMutableArray alloc] initWithCapacity:50];
+	
+	text_tarray& contains_val = contains.values;
+	text_tarray::iterator cl_iterator = contains_val.begin();
+	while (cl_iterator != contains_val.end()) {
+	  text_t& clname = *cl_iterator;
+
+	  // split up on ';'
+	  text_tarray split_clname;
+	  splitchar (clname.begin(), clname.end(), ';', split_clname);
+
+	  text_tarray::iterator split_cl_iterator = split_clname.begin();
+	  while (split_cl_iterator != split_clname.end()) {
+	    text_t& cl = *split_cl_iterator;
+	    NSString* nscl = nil;
+	    if (cl[0] == '\"') {
+	      text_t cl_trim = substr(cl.begin()+1,cl.end());
+	      nscl = TextTToNSString(cl_trim);
+	    }
+	    else {
+	      nscl = TextTToNSString(cl);
+	    }
+	    
+	    if (nscl != nil) {
+	      [nscllist addObject:nscl];
+	    }
+	    else {
+	      cerr << "Warning: no semicolon split classifier 'contains' metadata value found for " + gid << endl;
+	    }
+	    
+	    split_cl_iterator++;
+	  }
+	  cl_iterator++;	      
+	}
+
+	if ([nscllist count]==0) {
+	  // No valid metadata found
+	  [nscllist release];
+	  nscllist = nil;
+	}
+      }
+      else {
+	alert("Error","Collection has to browsing capabilities");
+      }
+    }
+    else {
+      alert("Error","Collection has to browsing capabilities");
+    }
+  }
+  else {
+    alert("Error",get_comerror_string(comerr));
+  }
+
+  // according to documentation, nscollectcion_cstr and nsgid_cstr autorealeased
+  // => don't need to free them
+
+  return nscllist;
+}
+
+
+NSMutableArray* GreenstoneAPI::browseToplevelList(NSString* nscollection)
+{
+  return browseClassifierList(nscollection,@"browse");
+}
+
+
+
+
+void GreenstoneAPI::set_queryfilter_options (const text_t& collection,
+					     FilterRequest_t &request, 
+					     const text_t &querystring) 
+{
+  ColInfoResponse_t& collectinfo = collectInfo(collection);
+
+  // request.filterResultOptions and request.fields (if required) should
+  // be set from the calling code
+
+  request.filterName = "QueryFilter";
+
+  OptionValue_t option;
+
+  option.name = "Term";
+  option.value = querystring;
+  request.filterOptions.push_back (option);
+
+  option.name = "QueryType";
+  option.value = "ranked";
+  request.filterOptions.push_back (option);
+
+  option.name = "MatchMode";
+  option.value = "some";
+  request.filterOptions.push_back (option);
+
+  option.name = "Casefold";
+  option.value = "true";
+  request.filterOptions.push_back (option);
+
+  option.name = "Stem";
+  option.value = "true";
+  request.filterOptions.push_back (option);
+
+  option.name = "AccentFold";
+  option.value = "true";
+  request.filterOptions.push_back (option);
+
+  text_t buildtype = collectinfo.buildType;
+
+  if (buildtype == "lucene") {
+    // Should prevent Lucene collection from doing any searching!! // ****
+    alert("Warning","Searching lucene indexed collection on iPod not currently supported");
+  }
+  else if (buildtype == "mgpp") {
+    option.name = "Level";
+    option.value = "Doc";
+    request.filterOptions.push_back (option);
+
+    option.name = "Index";
+    option.value = "idx"; // ****
+    request.filterOptions.push_back (option);
+  }
+  else {
+    cerr << "**** storing index as dte" << endl;
+    option.name = "Index";
+    option.value = "dte"; // ****
+    request.filterOptions.push_back (option);
+  }
+  
+  option.name = "Maxdocs";
+  option.value = "50";
+  request.filterOptions.push_back (option);
+
+  option.name = "StartResults";
+  option.value = "1";
+  request.filterOptions.push_back (option);
+
+  option.name = "EndResults";
+  option.value = "50";
+  request.filterOptions.push_back (option);
+  
+
+}
+
+
+text_t GreenstoneAPI::resolveUrls(const text_t& unresolved, const text_t& collection, const text_t& archivedir)
+{
+  text_t resolved = unresolved;
+
+  // *****
+  text_t httpprefix = _gsdlhome;
+  text_t httpdocimg = httpprefix +"/collect/" + collection + "/index/assoc/" + archivedir;
+
+  resolved.replace("[archivedir]",archivedir);
+  resolved.replace("[assocfilepath]",archivedir);
+  resolved.replace("[collection]",collection);
+  resolved.replace("_httpprefix_",httpprefix);
+  resolved.replace("_httpdocimg_",httpdocimg);
+
+  return resolved;
+}
+
+
+text_t GreenstoneAPI::srclinkToUrl(const text_t& srclink, const text_t& collection, const text_t& archivedir)
+{
+  text_t srcurl;
+
+  if (!srclink.empty()) {
+    // extract URL
+    text_tarray split_srclink;
+    splitchar (srclink.begin(), srclink.end(), '\"', split_srclink);
+    if (split_srclink.size()>=2) {
+      srcurl = resolveUrls(split_srclink[1],collection,archivedir);
+    }
+  }
+
+  return srcurl;
+}
+
+
+NSString* GreenstoneAPI::getSrcUrlMetadata(NSString* nscollection, NSString* nsgid)
+{
+  NSString* nssrclink = getMetadataFirst(nscollection,nsgid,@"srclink");
+  if (nssrclink == nil) {
+    return nil;
+  }
+  NSString* nsarchivedir = getMetadataFirst(nscollection,nsgid,@"archivedir");
+  //NSString* nsassocfilepath = getMetadataFirst(nscollection,nsgid,@"assocfilepath"); // ****** used?
+
+  char const* nscollection_cstr  = [nscollection UTF8String]; 
+  char const* nssrclink_cstr  = [nssrclink UTF8String]; 
+  char const* nsarchivedir_cstr  = [nsarchivedir UTF8String]; 
+
+  text_t collection = nscollection_cstr;
+  text_t srclink = nssrclink_cstr;
+  text_t archivedir = nsarchivedir_cstr;
+
+  text_t srcurl = srclinkToUrl(srclink,collection,archivedir);
+
+  NSString* nsimage = getMetadataFirst(nscollection,nsgid,@"Image"); 
+  if (nsimage != nil) {
+    char const* image_cstr  = [nsimage UTF8String]; 
+    srcurl.replace("[Image]",image_cstr);
+  }
+
+  NSString* nssrcurl = TextTToNSString(srcurl);
+  
+  return nssrcurl;
+}
+
+
+
+
+NSMutableArray* GreenstoneAPI::filterResponseToTitlesList(const text_t& collection, FilterResponse_t& sections)
+{
+  ResultDocInfo_tarray::iterator thissection = sections.docInfo.begin();
+  ResultDocInfo_tarray::iterator endsection = sections.docInfo.end();
+
+  int num_results = sections.docInfo.size();
+  NSMutableArray* nsresultlist = nil;
+
+  if (num_results>0) {
+    nsresultlist = [[NSMutableArray alloc] initWithCapacity:num_results];
+
+    while (thissection != endsection) {
+      
+      ResultDocInfo_t &docinfo = *thissection;
+      text_t& oid = docinfo.OID;
+      text_t title;
+      text_t srcurl;
+
+      MetadataInfo_tmap& metadata = docinfo.metadata;
+      MetadataInfo_t& dctitle_info = metadata["dc.Title"];
+      MetadataInfo_t& title_info = metadata["Title"];
+      if ((dctitle_info.values.size()>0) && (!dctitle_info.values[0].empty())) {
+	title = dctitle_info.values[0];
+      }
+      else if ((title_info.values.size()>0) && (!title_info.values[0].empty())) {
+	title = title_info.values[0];
+      }
+      else {
+	cerr << "Warning: could not find Title metadata for item" << endl;
+      }
+
+      MetadataInfo_t& archivedir_info = metadata["archivedir"];
+      text_t archivedir = archivedir_info.values[0];
+      
+      MetadataInfo_t& srclink_info = metadata["srclink"];
+      if (srclink_info.values.size()>0) {
+	text_t& srclink = srclink_info.values[0];
+
+	srcurl = srclinkToUrl(srclink,collection,archivedir);
+
+	
+	// ** think about embedding in routine?
+	text_t imagemdname = "Image";
+	NSString* nsimage = getMetadataFirst(collection,oid,imagemdname); 
+	//char const* image_cstr  = [nsimage UTF8String]; 
+	//text_t image = image_cstr;
+	//srcurl.replace("[Image]",image);
+	
+
+      }
+     
+      NSString* nstitle = TextTToNSString(title);
+      NSString* nsoid = TextTToNSString(oid);
+      NSString* nssrcurl = TextTToNSString(srcurl); 
+
+      GSResultItem* result_item = [[GSResultItem alloc] initWithOID:nsoid withTitle:nstitle withSrcUrl:nssrcurl];
+      
+      [nsresultlist addObject:result_item];
+
+      ++thissection;
+    }
+  }
+
+  return nsresultlist;
+}
+
+NSMutableArray* GreenstoneAPI::search_single_collection (const text_t& collection, const text_t& query)
+{
+  comerror_t comerr;
+  FilterRequest_t request;
+  FilterResponse_t response;
+
+  NSMutableArray* nsresultlist = nil;
+ 
+  // request.fields = metadata set
+  request.fields.insert ("dc.Title"); 
+  request.fields.insert ("Title"); 
+  request.fields.insert ("srclink"); 
+  request.fields.insert ("archivedir"); 
+   
+  // do the query
+  request.filterResultOptions = FROID | FRmetadata | FRtermFreq;
+  text_t formattedstring = query;
+
+  // note! formattedstring is in unicode! mg and mgpp must convert!
+  set_queryfilter_options (collection, request, formattedstring);
+
+  _nproto->filter (collection, request, response, comerr, cerr);
+
+  if (comerr != noError) {
+    alert("Error",get_comerror_string(comerr));
+    return nil;
+  }
+  else {
+    nsresultlist = filterResponseToTitlesList(collection,response);
+  }
+  
+  return nsresultlist;
+}
+
+
+
+NSMutableArray* GreenstoneAPI::query(NSString* nscollection, NSString* nsquery)
+{
+  char const* nscollection_cstr  = [nscollection UTF8String]; 
+  char const* nsquery_cstr  = [nsquery UTF8String]; 
+
+  text_t collection = nscollection_cstr;
+  text_t query = nsquery_cstr;
+
+  NSMutableArray* nsresultlist = search_single_collection(collection,query);
+
+  return nsresultlist;
+}
+
+NSString* GreenstoneAPI::getDocument(NSString* nscollection, NSString* nsgid)
+{
+  char const* nscollection_cstr  = [nscollection UTF8String]; 
+  char const* nsgid_cstr  = [nsgid UTF8String]; 
+
+  text_t gid = nsgid_cstr;
+  text_t collection = nscollection_cstr;
+
+  DocumentRequest_t docrequest;
+  DocumentResponse_t docresponse;
+  comerror_t comerr;
+
+  // get the text
+  docrequest.OID = gid;
+  _nproto->get_document(collection, docrequest, docresponse, comerr, cerr);
+  
+  if (comerr != noError) {
+    alert("Error",get_comerror_string(comerr));
+    return nil;
+  }
+
+
+  text_t& text = docresponse.doc;
+  char* text_cstr = text.getcstr();
+  NSString* nstext = [[NSString alloc] initWithCString:text_cstr];
+
+  delete [] text_cstr;
+
+  return nstext;
+}
+
+
+
+
+
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneApplication.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneApplication.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneApplication.h	(revision 22603)
@@ -0,0 +1,56 @@
+#import <UIKit/CDStructures.h>
+#import <UIKit/UIKit.h>
+#import <UIKit/UIApplication.h>
+#import <UIKit/UITable.h>
+
+#import "BrowseCascadeView.h"
+#import "QueryCascadeView.h"
+#import "PrefCascadeView.h"
+
+#import "SimpleWebView.h"
+
+#import "GreenstoneAPI.h"
+#import "GreenstoneButtonBar.h"
+
+#import "AppDefs.h"
+
+@interface GreenstoneApplication : UIApplication 
+{
+  UIWindow* _window;
+  UIButtonBar* _butbar;
+
+  BrowseCascadeView* _browseCascadeView; 
+  QueryCascadeView*  _queryCascadeView; 
+  PrefCascadeView*   _prefCascadeView; 
+}
+
+
+-(NSString*) languagePref;
+
++(GreenstoneApplication*) toplevelApp;
++(GreenstoneAPI*) greenstoneAPI;
+
++(CGRect)workAreaRect;
+
++(void) setInCollection:(NSString*)collection;
++(int) inCollectionRowId;
+
+
+-(void) applicationDidFinishLaunching: (NSNotification*)aNotification;
+
+-(void) deviceOrientationChanged:(struct __GSEvent *)event;
+
+-(void) buttonBarClicked:(id)sender;
+
++(void) transitionView:(int)eventNum fromView:(UIView*)from toView:(UIView*)to;
+
++(void) startWebViewBusy;
++(void) stopWebViewBusy;
+
++(void) loadURL:(NSURL*)url;
++(void) showWebView:(int)eventNum  fromView:(UIView*)from withURL:(NSURL*)url;
+
+-(void) alertSheet:(UIActionSheet*)sheet buttonClicked: (int)button;
+
+@end
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneApplication.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneApplication.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneApplication.mm	(revision 22603)
@@ -0,0 +1,323 @@
+#import <Foundation/NSDictionary.h>
+#import <UIKit/CDStructures.h>
+#import <UIKit/UITable.h>
+#import <UIKit/UIHardware.h>
+
+#import "GreenstoneApplication.h"
+#import "GreenstoneButtonBar.h"
+#import "SimpleWebView.h"
+
+#import "GreenstoneAPI.h"
+
+static GreenstoneApplication* _toplevelApp   = nil;
+static UITransitionView*      _transView     = nil;
+static SimpleWebView*         _webView       = nil;
+static GreenstoneAPI*         _greenstoneAPI = nil;
+
+static NSString* _inCollection = nil;
+static NSMutableDictionary* _collectionToRowId = nil;
+
+@implementation GreenstoneApplication
+
++(GreenstoneApplication*) toplevelApp {
+  return (_toplevelApp);
+}
+
++(GreenstoneAPI*) greenstoneAPI {
+  return (_greenstoneAPI);
+}
+
++(CGRect)workAreaRect
+{
+  CGRect screen_rect = [UIHardware fullScreenApplicationContentRect];
+
+  int wa_x_dim = screen_rect.size.width;
+  int wa_y_dim = screen_rect.size.height - BOT_NAVBAR_HEIGHT;
+
+  CGRect wa_rect = CGRectMake(0.0f,0.0f,wa_x_dim,wa_y_dim);
+
+  return wa_rect;
+}
+
+
++(void) setInCollection:(NSString*)collection
+{
+  NSLog(@"Setting in collection = %@",collection);
+  if (_inCollection != nil) {
+    // [_inCollection release]; // **** memory leak????
+  }
+  _inCollection = nil;
+    
+  if (collection != nil) {
+    _inCollection = [[NSString alloc] initWithString:collection];
+  }
+}
+
++(int) inCollectionRowId
+{
+  if (_inCollection == nil) {
+    return -1;
+  }
+
+  NSNumber* rowid_num = [_collectionToRowId objectForKey:_inCollection];
+  int rowid = [rowid_num intValue];
+
+  return rowid;
+}
+
+-(NSString*) languagePref
+{
+  int rowid = [GreenstoneApplication inCollectionRowId];
+
+  if (rowid>=0) {
+
+    PrefView* prefview = (PrefView*)[_prefCascadeView directEntry:rowid];
+    NSString* lang = [prefview languagePref];
+
+    return lang; // lang is allocated, make sure calling method does release
+  }
+  else {
+    return nil;
+  }
+}
+
+
+
+-(void) applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+    _toplevelApp = self;
+    _greenstoneAPI = new GreenstoneAPI(self);
+
+    _inCollection = nil;
+    _collectionToRowId = nil;
+
+    if (!_greenstoneAPI->sanityCheck()) {
+      return;
+    }
+
+    CGRect screen_rect = [UIHardware fullScreenApplicationContentRect];
+    screen_rect.origin.x = screen_rect.origin.y = 0.0f;
+
+    _window = [[UIWindow alloc] initWithContentRect: screen_rect];
+
+    CGRect workarea_rect = [GreenstoneApplication workAreaRect];
+
+    // Set up top-level browsing and search menu CascadeViews
+    _browseCascadeView = [BrowseCascadeView alloc];
+    _browseCascadeView = [_browseCascadeView initWithFrame:workarea_rect withTitle: @"Browse collection:"];
+
+    _queryCascadeView = [QueryCascadeView alloc];
+    _queryCascadeView = [_queryCascadeView initWithFrame:workarea_rect withTitle: @"Search collection:"];
+
+    _prefCascadeView = [PrefCascadeView alloc];
+    _prefCascadeView = [_prefCascadeView initWithFrame:workarea_rect withTitle: @"Collection preferences:"];
+
+    NSMutableArray* collist = _greenstoneAPI->collectionList();
+
+    int collist_len = [collist count];
+    _collectionToRowId = [[NSMutableDictionary alloc] initWithCapacity:collist_len];
+
+
+    NSEnumerator* collist_enumerator = [collist objectEnumerator];
+    int i = 0;
+    NSString* colnamedir;
+    while (colnamedir = [collist_enumerator nextObject]) {
+      ColInfoResponse_t& colinfo = _greenstoneAPI->collectInfo(colnamedir);
+      NSString* colname = _greenstoneAPI->collectionName(colinfo);
+	
+      [_browseCascadeView appendMenuItem:self withItem:colname withGID:colnamedir];
+      [_queryCascadeView appendMenuItem:self withItem:colname withGID:colnamedir];
+
+      [_prefCascadeView appendMenuItem:self withItem:colname withGID:colnamedir];
+
+      NSNumber* inum = [[NSNumber alloc] initWithInt: i];
+      [_collectionToRowId setObject:inum forKey:colnamedir];
+      [inum release]; // **** should probably add this in
+
+      i++;
+    }
+    [collist release];
+
+
+	    
+    if (_webView == nil) {
+      // setup Web browser view
+      _webView = [[SimpleWebView alloc] initWithFrame:workarea_rect];
+    }
+
+
+    if (_transView == nil) {
+      // Set up transition view
+      _transView = [[UITransitionView alloc] initWithFrame: workarea_rect];
+    }
+
+    // Set up button bar
+    int butbar_x_org = 0.0f;
+    int butbar_y_org = workarea_rect.size.height+1;
+    int butbar_x_dim = screen_rect.size.width;
+    int butbar_y_dim = BOT_NAVBAR_HEIGHT;
+
+    CGRect butbarrect = CGRectMake(butbar_x_org,butbar_y_org,butbar_x_dim,butbar_y_dim);
+    _butbar = [[GreenstoneButtonBar alloc] initInView:_window withFrame:butbarrect];
+
+    // Usual standard window stuff
+    [_window makeKeyAndVisible];
+
+    [_window addSubview: _transView ];
+    [_window addSubview: _butbar]; 
+
+    [_transView transition:0 toView:_browseCascadeView];
+}
+
+
+enum compassDirection { itNorth=0, itEast=1, itSouth=2, itWest=3};
+
+static int compass_degrees[4] = { 0, 90, 180, 270 };
+
+static int current_orientation = kOrientationVertical;
+static int current_compass_dir = itNorth;
+static int current_compass_degs = 0;
+
+-(void) deviceOrientationChanged:(struct __GSEvent *)event
+{
+    int new_orientation = [UIHardware deviceOrientation: YES];
+    
+    int new_compass_dir  = -1;
+
+    switch (new_orientation) 
+    {
+      case kOrientationVertical:
+	new_compass_dir = itNorth;
+	break;
+
+      case kOrientationHorizontalLeft:
+	new_compass_dir = itEast;
+	break;
+
+      case kOrientationHorizontalRight:
+	new_compass_dir = itWest;
+	break;
+      case kOrientationVerticalUpsideDown:
+	new_compass_dir = itSouth;
+	break;	
+    }
+
+    if (new_compass_dir>=0) {
+      int new_compass_degs = compass_degrees[new_compass_dir];
+      int degs_delta = current_compass_degs - new_compass_degs;
+
+      if (degs_delta != 0) {
+
+	current_orientation  = new_orientation;
+	current_compass_degs = new_compass_degs;
+	current_compass_dir  = new_compass_dir;
+	
+	[_webView setTransform:CGAffineTransformIdentity];
+	[_webView setRotationBy:new_compass_degs];	
+
+      }
+    }
+
+    [super deviceOrientationChanged:event];
+}
+
+
+
+-(void) buttonBarClicked:(id)sender 
+{
+    int button = [sender tag];
+    int transStyle = UITransitionNextShiftUp;
+
+    int rowid = [GreenstoneApplication inCollectionRowId];
+
+    switch (button) 
+    {
+      case GSBBBrowse:
+	if (rowid>=0) {
+	  [_transView transition:transStyle toView:[_browseCascadeView directEntry:rowid]];
+	}
+	else {
+	  [_transView transition:transStyle toView:_browseCascadeView];
+	}
+	break;
+
+      case GSBBQuery:
+	if (rowid>=0) {
+	  [_transView transition:transStyle toView:[_queryCascadeView directEntry:rowid]];
+	}
+	else {
+	  [_transView transition:transStyle toView:_queryCascadeView];
+	}
+	break;
+
+      case GSBBPref:
+	if (rowid>=0) {
+	  [_transView transition:transStyle toView:[_prefCascadeView directEntry:rowid]];
+	}
+	else {
+	  [_transView transition:transStyle toView:_prefCascadeView];
+	}
+	break;
+
+      default:
+	NSLog(@"Unrecognised button bar click: %d",button);
+	break;
+    }
+}
+
+
++(void) transitionView:(int)eventNum fromView:(UIView*)from toView:(UIView*)to
+{
+  [_transView transition:eventNum fromView:from toView:to];
+}
+
++(void) startWebViewBusy
+{
+  // cerr << "**** start busy" << endl;
+  // stub for providing "busy" cue (e.g. busy spinner, or HUD)
+}
+
++(void) stopWebViewBusy
+{
+  // cerr << "**** end busy" << endl;
+  // stub for providing "busy" cue (e.g. busy spinner, or HUD)
+}
+
++(void) loadURL:(NSURL*)url
+{
+  [_webView loadURL:url];
+}
+
++(void) showWebView:(int)eventNum  fromView:(UIView*)from withURL:(NSURL*)url
+{
+  [_webView loadURL:url];
+  [_webView setParent:from];
+  [_transView transition:eventNum fromView:from toView:_webView];
+}
+
+
+
+-(void) alertSheet:(UIActionSheet*)sheet buttonClicked:(int)button
+{	
+    [sheet dismissAnimated:YES];
+    [sheet release];
+}
+
+
+-(void) dealloc
+{
+    [_browseCascadeView release];
+    [_queryCascadeView release];
+    [_prefCascadeView release];
+
+    [_window release];
+    [_butbar release];
+
+    [super dealloc];
+}
+
+
+@end
+
+
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneButtonBar.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneButtonBar.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneButtonBar.h	(revision 22603)
@@ -0,0 +1,31 @@
+#import <CoreFoundation/CoreFoundation.h>
+#import <UIKit/UIKit.h>
+#import <UIKit/UITransitionView.h>
+#import <UIKit/UITextView.h>
+#import <UIKit/UIButtonBar.h>
+
+#define NUM_GSBAR_BUTTONS 3
+
+extern NSString *kUIButtonBarButtonAction;
+extern NSString *kUIButtonBarButtonInfo;
+extern NSString *kUIButtonBarButtonInfoOffset;
+extern NSString *kUIButtonBarButtonSelectedInfo;
+extern NSString *kUIButtonBarButtonStyle;
+extern NSString *kUIButtonBarButtonTag;
+extern NSString *kUIButtonBarButtonTarget;
+extern NSString *kUIButtonBarButtonTitle;
+extern NSString *kUIButtonBarButtonTitleVerticalHeight;
+extern NSString *kUIButtonBarButtonTitleWidth;
+extern NSString *kUIButtonBarButtonType;
+
+@interface GreenstoneButtonBar : UIButtonBar
+{}
+
+- (UIButtonBar*)initInView:(UIView*)view withFrame:(CGRect)frame;
+
+- (NSArray *)buttonBarItemList;
+
+@end
+
+
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneButtonBar.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneButtonBar.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/GreenstoneButtonBar.mm	(revision 22603)
@@ -0,0 +1,73 @@
+#import "GreenstoneButtonBar.h"
+#import "GreenstoneApplication.h"
+
+@implementation GreenstoneButtonBar
+
+- (UIButtonBar*)initInView:(UIView*)view withFrame:(CGRect)frame
+{
+    self = [super initInView: view withFrame: frame
+       withItemList: [self buttonBarItemList]];
+
+    GreenstoneApplication* app = [GreenstoneApplication toplevelApp];
+
+    [self setDelegate: app ];
+    [self setBarStyle: UIBarStyleBlack ];
+    [self setButtonBarTrackingMode: 2 ];
+
+    int buttons[NUM_GSBAR_BUTTONS] = { GSBBBrowse, GSBBQuery, GSBBPref };
+
+    [self registerButtonGroup: 0 withButtons: buttons withCount: NUM_GSBAR_BUTTONS ];
+    [self showButtonGroup: 0 withDuration: 0.0 ];
+
+    // *** This and the fact that BookmarkSelected.png seems to be back to front is a bit weird!
+    [self showSelectionForButton: 1 ];
+
+    return self;
+}
+
+- (NSArray *)buttonBarItemList 
+{
+    GreenstoneApplication* app = [GreenstoneApplication toplevelApp];
+
+    NSArray* buts 
+      = [ NSArray arrayWithObjects:
+          [ NSDictionary dictionaryWithObjectsAndKeys:
+            @"buttonBarClicked:", kUIButtonBarButtonAction,
+            @"icons/BookmarkSelected.png", kUIButtonBarButtonInfo,
+            @"icons/Bookmark.png", kUIButtonBarButtonSelectedInfo,
+            [ NSNumber numberWithInt: 1], kUIButtonBarButtonTag,
+              app, kUIButtonBarButtonTarget,
+            @"Browse", kUIButtonBarButtonTitle,
+            @"0", kUIButtonBarButtonType,
+            nil
+          ],
+
+          [ NSDictionary dictionaryWithObjectsAndKeys:
+            @"buttonBarClicked:", kUIButtonBarButtonAction,
+            @"icons/Search.png", kUIButtonBarButtonInfo,
+            @"icons/SearchSelected.png", kUIButtonBarButtonSelectedInfo,
+            [ NSNumber numberWithInt: 2], kUIButtonBarButtonTag,
+              app, kUIButtonBarButtonTarget,
+            @"Search", kUIButtonBarButtonTitle,
+            @"0", kUIButtonBarButtonType,
+            nil
+          ],
+ 
+          [ NSDictionary dictionaryWithObjectsAndKeys:
+            @"buttonBarClicked:", kUIButtonBarButtonAction,
+            @"icons/Preferences.png", kUIButtonBarButtonInfo,
+            @"icons/PreferencesSelected.png", kUIButtonBarButtonSelectedInfo,
+            [ NSNumber numberWithInt: 3], kUIButtonBarButtonTag,
+              app, kUIButtonBarButtonTarget,
+            @"Settings", kUIButtonBarButtonTitle,
+            @"0", kUIButtonBarButtonType,
+            nil
+          ],
+
+          nil
+      ];
+
+    return buts;
+}
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/MenuCascadeView.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/MenuCascadeView.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/MenuCascadeView.h	(revision 22603)
@@ -0,0 +1,40 @@
+#import <Foundation/NSObject.h>
+#import <Foundation/NSString.h>
+
+#import <UIKit/UIView.h>
+#import <UIKit/UIKit.h>
+
+#define MCInitCapacity 10
+
+@interface MenuCascadeView : UIView
+{
+  UIView* _parent;
+  UITable* _table;
+  UINavigationBar* _navbar;
+  UIView* _childMenu;
+
+  NSString* _gid;    // Greenstone id (used to access database for metadata such as CL1, CL4.1 etc)
+  NSString* _collection;
+
+  NSMutableArray* _tabrow;
+  NSMutableArray* _oidItem;
+
+}
+
+-(id) init;
+-(id) initWithFrame:(CGRect)rect;
+-(id) initWithFrame:(CGRect)rect withTitle:(NSString*)title;
+-(id) initWithFrame:(CGRect)rect withParent:(UIView*)parent 
+         withCollection:(NSString*)collection withTitle:(NSString*)title withGID:(NSString*)gid;
+
+-(void) setTitle: (NSString*)title;
+-(void) appendMenuItem: (NSObject*) app withItem:(NSString*)item_label withGID:(NSString*)childGID;
+
+-(void) navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button;
+
+
+
+-(void) dealloc;
+
+@end
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/MenuCascadeView.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/MenuCascadeView.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/MenuCascadeView.mm	(revision 22603)
@@ -0,0 +1,193 @@
+#import <Foundation/Foundation.h>
+
+#import <UIKit/CDStructures.h>
+#import <UIKit/UINavigationBar.h>
+#import <UIKit/UIWindow.h>
+#import <UIKit/UIView-Hierarchy.h>
+#import <UIKit/UIHardware.h>
+#import <UIKit/UITable.h>
+#import <UIKit/UITableCell.h>
+#import <UIKit/UITableColumn.h>
+
+#import "GreenstoneApplication.h"
+#import "GSResultItem.h"
+
+#import "MenuCascadeView.h"
+
+
+// ***** think about coding for orientation of iPod!!!!
+
+@implementation MenuCascadeView
+
+-(id) init 
+{
+  CGRect rect = [GreenstoneApplication workAreaRect];  
+  return [self initWithFrame:rect];	
+}
+
+-(id) initWithFrame:(CGRect)rect 
+{
+  return [self initWithFrame:rect withParent:nil withCollection:nil withTitle:nil withGID:nil];
+}
+
+-(id) initWithFrame:(CGRect)rect withTitle:(NSString*)title
+{
+  return [self initWithFrame:rect withParent:nil withCollection:nil withTitle:title withGID:nil];
+}
+
+-(id) initWithFrame:(CGRect)rect withParent:(UIView*)parent 
+        withCollection:(NSString*)collection withTitle:(NSString*)title withGID:(NSString*)gid
+{
+  self = [super initWithFrame:rect];
+  
+  _parent = parent;
+  _collection = collection;
+  _gid = gid;
+  _childMenu = nil;
+ 
+  _tabrow    = [[NSMutableArray alloc] initWithCapacity:MCInitCapacity];
+  _oidItem   = [[NSMutableArray alloc] initWithCapacity:MCInitCapacity];
+
+  int frame_x_dim = CGRectGetMaxX(rect)+1;
+  int frame_y_dim = CGRectGetMaxY(rect)+1;
+    
+  int tab_x_org = 0.0f;
+  int tab_y_org = TOP_NAVBAR_HEIGHT;
+  int tab_x_dim = frame_x_dim;
+  int tab_y_dim = frame_y_dim -TOP_NAVBAR_HEIGHT;
+
+  CGRect tablerect = CGRectMake(tab_x_org,tab_y_org,tab_x_dim,tab_y_dim);
+
+  _table = [[UITable alloc] initWithFrame:tablerect];
+    
+  UITableColumn *col = [[UITableColumn alloc] initWithTitle: @"MenuCascadeApp"
+		       identifier: @"menucascade" width: frame_x_dim];
+      
+  [_table addTableColumn: col]; 
+  [_table setDataSource: self];
+  [_table setDelegate: self];
+  [_table reloadData];
+  
+  int nav_x_org = 0.0f;
+  int nav_y_org = 0.0f;
+  int nav_x_dim = frame_x_dim;
+  int nav_y_dim = TOP_NAVBAR_HEIGHT;
+
+  CGRect navrect = CGRectMake(nav_x_org,nav_y_org,nav_x_dim,nav_y_dim);
+  _navbar = [[UINavigationBar alloc] initWithFrame: navrect];
+  
+  NSString* back = (parent) ? @"Back" : nil;
+  [_navbar showButtonsWithLeftTitle:back rightTitle:nil leftBack:YES];
+  [_navbar enableAnimation];
+  [_navbar setBarStyle: UIBarStyleDefault];
+  [_navbar setDelegate: self];
+
+  if (title != nil) {
+    [self setTitle:title];
+  }
+
+  [self addSubview: _navbar]; 
+  [self addSubview: _table]; 	
+
+  return self;
+}
+
+
+-(void) setTitle: (NSString*)title
+{
+  UINavigationItem* navtitle = [UINavigationItem alloc];
+  [_navbar pushNavigationItem: [navtitle initWithTitle: title]];
+}
+
+
+-(void) appendMenuItem: (NSObject*) app withItem:(NSString*)itemLabel withGID:(NSString*)childGID
+{
+  UIImageAndTextTableCell* itcell = [[UIImageAndTextTableCell alloc] init];
+  [itcell setTitle: itemLabel]; 
+    
+  if ([childGID hasPrefix:@"CL"]==YES) {
+    [itcell setShowDisclosure: YES];
+    [itcell setDisclosureStyle: 2];
+  }
+  else if (_parent == nil) {
+    // Root menu => Make disclosures look a bit different
+    [itcell setShowDisclosure: YES];
+    [itcell setDisclosureStyle: 1];
+  }
+
+  [_tabrow addObject:itcell]; 
+  [itcell retain];
+
+  if (itemLabel == nil) {
+    itemLabel = [[NSString alloc] initWithString:@"Unknown Title"];
+  }
+
+  GSResultItem* oidItem = [[GSResultItem alloc] initWithOID:childGID withTitle:itemLabel]; // *****
+  [_oidItem addObject:oidItem];  
+
+  // needed to force table view to update
+  [_table reloadData];
+
+}
+
+// ************
+// * Delegates
+// ************
+
+- (int) numberOfRowsInTable: (UITable *)table
+{
+  return [_tabrow count];
+}
+
+- (UITableCell *) table: (UITable *)table cellForRow: (int)row column: (int)col
+{
+
+
+  return [_tabrow objectAtIndex:row];
+}
+
+- (UITableCell *) table: (UITable *)table cellForRow: (int)row column: (int)col
+				reusing: (BOOL) reusing
+{
+  return [_tabrow objectAtIndex:row];
+}
+
+
+
+-(void) navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button 
+{
+  switch (button) 
+  {
+    case 1:  // left
+      // cerr << "***** Need to set collection to nil if going to top page" << endl; // ****
+      // [GreenstoneApplication setInCollection:_parent._collectcion];
+      [GreenstoneApplication transitionView:UITransitionBothShiftRight 
+         fromView:self toView:_parent];
+
+      if (_childMenu != nil) {
+	[_childMenu release];
+	_childMenu = nil;
+      }
+      break;
+
+    default:
+      NSLog(@"Unrecognised navbar button = %d",button);
+      break;
+  }
+}
+
+
+-(void) dealloc
+{
+  [_childMenu release];
+
+  [_gid release]; // **** is this ever used???
+  [_collection release];
+
+  [_tabrow release];
+  [_oidItem release];
+
+  [ super dealloc ];
+}
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/PrefCascadeView.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/PrefCascadeView.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/PrefCascadeView.h	(revision 22603)
@@ -0,0 +1,23 @@
+
+#import "PrefView.h"
+
+#import "MenuCascadeView.h"
+
+@interface PrefCascadeView: MenuCascadeView
+{
+  NSMutableArray* _prefViews;
+}
+
+-(id) initWithFrame:(CGRect)rect withParent:(UIView*)parent 
+        withCollection:(NSString*)collection withTitle:(NSString*)title withGID:(NSString*)gid;
+
+-(UIView*) directEntry:(int)rowId;
+
+-(void) appendMenuItem: (NSObject*) app withItem:(NSString*)item_label withGID:(NSString*)childGID;
+
+-(void) tableRowSelected:(NSNotification*)notification;
+
+-(void) dealloc;
+
+@end
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/PrefCascadeView.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/PrefCascadeView.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/PrefCascadeView.mm	(revision 22603)
@@ -0,0 +1,69 @@
+
+#import "GSResultItem.h"
+#import "GreenstoneApplication.h"
+
+#import "PrefCascadeView.h"
+
+@implementation PrefCascadeView
+
+-(id) initWithFrame:(CGRect)rect withParent:(UIView*)parent 
+        withCollection:(NSString*)collection withTitle:(NSString*)title withGID:(NSString*)gid
+{
+  self = [super initWithFrame:rect withParent:parent withCollection:collection 
+	  withTitle:title withGID:gid];
+
+  _prefViews = [[NSMutableArray alloc] initWithCapacity:MCInitCapacity];
+
+  return self;
+}
+
+-(void) appendMenuItem:(NSObject*)app withItem:(NSString*)item_label withGID:(NSString*)childGID
+{
+  [super appendMenuItem:app withItem:item_label withGID:childGID];
+
+  CGRect workarea_rect = [GreenstoneApplication workAreaRect];
+  PrefView* prefView = [[PrefView alloc] initWithFrame:workarea_rect 
+			withParent:self withCollection:childGID withTitle:item_label];
+
+  [_prefViews addObject:prefView];  
+
+}
+
+-(UIView*) directEntry:(int)rowId
+{
+  return [_prefViews objectAtIndex:rowId];
+}
+
+
+
+//***********
+//* Delegates
+//***********
+-(void) tableRowSelected:(NSNotification*)notification
+{
+  UITable* table = [notification object];
+  int rowId = [table selectedRow];
+
+  GreenstoneAPI* greenstoneAPI = [GreenstoneApplication greenstoneAPI];
+
+  NSString* childTitle = [[_oidItem objectAtIndex:rowId] title];
+  NSString* childGID = [[_oidItem  objectAtIndex:rowId] oid]; 
+
+  NSString* chosenCollection = [[NSString alloc] initWithString:childGID];
+
+  PrefView* prefView = [_prefViews objectAtIndex:rowId];
+  
+  [GreenstoneApplication setInCollection:chosenCollection];
+  [GreenstoneApplication transitionView:UITransitionBothShiftLeft 
+        fromView:self toView:prefView];
+
+}
+
+-(void) dealloc
+{
+  [_prefViews release];
+
+  [super dealloc];
+}
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/PrefTable.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/PrefTable.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/PrefTable.h	(revision 22603)
@@ -0,0 +1,42 @@
+#import <UIKit/CDStructures.h>
+#import <UIKit/UIKit.h>
+#import <UIKit/UIPreferencesTable.h>
+#import <UIKit/UIPreferencesTextTableCell.h>
+#import <UIKit/UISwitchControl.h>
+#import <UIKit/UISegmentedControl.h>
+#import <UIKit/UISliderControl.h>
+
+#define NUM_GROUPS 2
+#define CELLS_PER_GROUP 2
+
+@interface PrefTable : UIPreferencesTable
+{
+    UIPreferencesTableCell *cells[NUM_GROUPS][CELLS_PER_GROUP];
+    UIPreferencesTableCell *groupcell[NUM_GROUPS];
+
+    UISegmentedControl *langControl;
+
+    UISwitchControl    *stemmingControl;
+    UISwitchControl    *caseControl;
+}
+
+- (id)initWithFrame:(CGRect)rect;
+- (int)numberOfGroupsInPreferencesTable:(UIPreferencesTable *)aTable;
+- (UIPreferencesTableCell *)preferencesTable:
+    (UIPreferencesTable *)aTable
+    cellForGroup:(int)group;
+- (float)preferencesTable:(UIPreferencesTable *)aTable
+    heightForRow:(int)row
+    inGroup:(int)group
+    withProposedHeight:(float)proposed;
+- (BOOL)preferencesTable:(UIPreferencesTable *)aTable
+    isLabelGroup:(int)group;
+- (UIPreferencesTableCell *)preferencesTable:
+    (UIPreferencesTable *)aTable
+    cellForRow:(int)row
+    inGroup:(int)group;
+
+-(NSString*) languagePref;
+
+@end
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/PrefTable.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/PrefTable.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/PrefTable.mm	(revision 22603)
@@ -0,0 +1,173 @@
+#import "PrefTable.h"
+
+@implementation PrefTable
+
+- (id)initWithFrame:(CGRect)rect {
+    if ((self == [ super initWithFrame: rect ]) != nil) {
+        int i, j;
+
+        for(i=0;i<NUM_GROUPS;i++) {
+            groupcell[i] = NULL;
+            for(j=0;j<CELLS_PER_GROUP;j++)
+                cells[i][j] = NULL;
+        }
+
+        [ self setDataSource: self ];
+        [ self setDelegate: self ];
+    }
+
+    return self;
+}
+
+- (int)numberOfGroupsInPreferencesTable:(UIPreferencesTable *)aTable {
+
+    /* Number of logical groups, including labels */
+    return NUM_GROUPS;
+}
+
+ - (int)preferencesTable:(UIPreferencesTable *)aTable
+    numberOfRowsInGroup:(int)group
+{
+    switch (group) {
+        case 0:
+            return 1;
+            break;
+        case 1:
+            return 2;
+            break;
+    }
+}
+
+- (UIPreferencesTableCell *)preferencesTable:
+    (UIPreferencesTable *)aTable
+    cellForGroup:(int)group
+{
+     if (groupcell[group] != NULL)
+         return groupcell[group];
+
+     groupcell[group] = [ [ UIPreferencesTableCell alloc ] init ];
+     switch (group) {
+         case 0:
+             [ groupcell[group] setTitle: @"Presentation" ];
+             break;
+         case 1:
+             [ groupcell[group] setTitle: @"Search" ];
+             break;
+     }
+     return groupcell[group];
+}
+
+- (float)preferencesTable:(UIPreferencesTable *)aTable
+    heightForRow:(int)row
+    inGroup:(int)group
+    withProposedHeight:(float)proposed
+{
+    /* Return height for group titles */
+    if (row == -1) {
+        if (group < 2)
+            return 40;
+    }
+
+    if (group == 0 && row == 0) {
+      return 55.0;
+    }
+
+
+    return proposed;
+}
+
+- (BOOL)preferencesTable:(UIPreferencesTable *)aTable
+    isLabelGroup:(int)group
+{
+    return NO;
+}
+
+-(UIPreferencesTableCell*) preferencesTable:
+    (UIPreferencesTable *)aTable
+    cellForRow:(int)row
+    inGroup:(int)group
+{
+    UIPreferencesTableCell *cell;
+
+    if (cells[group][row] != NULL)
+        return cells[group][row];
+
+    cell = [ [ UIPreferencesTableCell alloc ] init ];
+    [ cell setEnabled: YES ];
+
+    switch (group) {
+        case (0):
+            switch (row) {
+                case (0):
+                    [ cell setTitle:@"Language" ];
+                    langControl = [ [ UISegmentedControl alloc ]
+                        initWithFrame:CGRectMake(170, 5, 135, 50)
+                    ];
+		    [ langControl insertSegment:0
+                        withTitle:@"English" animated: NO ];
+                    [ langControl insertSegment:1
+                        withTitle:@"French" animated: NO ];
+                    [ langControl selectSegment: 0 ];
+                    [ cell addSubview: langControl ];
+                    break;
+	    }
+	    break;
+        case (1):
+            switch (row) {
+                case (0):
+                    [ cell setTitle:@"Stemming" ];
+                    stemmingControl = [ [ UISwitchControl alloc ]
+                        initWithFrame:CGRectMake(170, 5, 120, 55)
+                    ];
+                    [ stemmingControl setValue: 0.0 ];
+                    [ cell addSubview: stemmingControl ];
+                    break;
+                case (1):
+                    [ cell setTitle:@"Case matching" ];
+                    caseControl = [ [ UISwitchControl alloc ]
+                        initWithFrame:CGRectMake(170, 5, 120, 30)
+                    ];
+                    [ caseControl setValue: 0.0 ];
+                    [ caseControl setAlternateColors: NO ];
+                    [ cell addSubview: caseControl ];
+                    break;
+                case (2):
+                    [ cell setTitle:@"Case matching" ];
+                    caseControl = [ [ UISwitchControl alloc ]
+                        initWithFrame:CGRectMake(170, 5, 120, 30)
+                    ];
+                    [ caseControl setValue: 0.0 ];
+                    [ caseControl setAlternateColors: NO ];
+                    [ cell addSubview: caseControl ];
+                    break;
+            }
+            break;
+	    
+    }
+
+    [ cell setShowSelection: NO ];
+    cells[group][row] = cell;
+    return cell;
+}
+
+-(NSString*) languagePref
+{
+  NSString* lang = [NSString alloc];
+
+    lang = [lang initWithString:@"en"];
+
+  NSLog(@"Not checking value. Defaulting to English");
+
+/*
+  if (langControl.selectedSegment==0) {
+    lang = [lang initWithString:@"en"];
+  }
+  else {
+    lang = [lang initWithString:@"fr"];
+  }
+*/
+
+  return lang;
+}
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/PrefView.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/PrefView.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/PrefView.h	(revision 22603)
@@ -0,0 +1,24 @@
+#import <UIKit/UIKit.h>
+
+#import "PrefTable.h"
+
+@interface PrefView : UIView
+{
+  UIView* _parent;
+  NSString* _collection;
+
+  UINavigationBar* _navbar;
+  PrefTable* _prefTable;
+
+}
+
+-(id) initWithFrame:(struct CGRect)frame withParent:(UIView*)parent 
+         withCollection:(NSString*)collection withTitle:(NSString*)title;
+
+-(void) setTitle:(NSString*)title;
+
+-(NSString*) languagePref;
+
+-(void) dealloc;
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/PrefView.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/PrefView.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/PrefView.mm	(revision 22603)
@@ -0,0 +1,107 @@
+
+
+#import <Foundation/Foundation.h> // can remove?? *****
+
+#import <UIKit/CDStructures.h>
+#import <UIKit/UIKit.h>
+
+#import "GreenstoneApplication.h"
+
+#import "PrefTable.h"
+#import "PrefView.h"
+
+
+
+@implementation PrefView
+
+- (id)initWithFrame:(struct CGRect)frame withParent:(UIView*)parent 
+        withCollection:(NSString*)collection withTitle:(NSString*)title
+{
+  self = [super initWithFrame:frame];
+
+  _parent = parent;
+  _collection = collection;
+
+  // Create the storage array.
+  // _cellResultList = [[NSMutableArray alloc] init]; // ****
+
+  int frame_x_dim = CGRectGetMaxX(frame)+1;
+  int frame_y_dim = CGRectGetMaxY(frame)+1;
+  
+  int nav_x_org = 0.0f;
+  int nav_y_org = 0.0f;
+  int nav_x_dim = frame_x_dim;
+  int nav_y_dim = TOP_NAVBAR_HEIGHT;
+  CGRect navrect = CGRectMake(nav_x_org,nav_y_org,nav_x_dim,nav_y_dim);
+
+  // Create the navigation bar.
+  _navbar = [[UINavigationBar alloc] initWithFrame: navrect];
+  //[_navbar showLeftButton:@"Back" withStyle:2 rightButton:nil withStyle:0]; // 2 = arrow left. // *** do enum for "2"
+  [_navbar showButtonsWithLeftTitle:@"Back" rightTitle:nil leftBack:YES];
+  [_navbar enableAnimation];
+  [_navbar setBarStyle: UIBarStyleDefault]; 
+  [_navbar setDelegate:self];
+
+  [self setTitle:title];
+
+
+  CGRect pref_rect = frame;
+  pref_rect.origin.y += 45;
+  pref_rect.size.height -= 45;
+
+  _prefTable = [ [ PrefTable alloc ] initWithFrame: pref_rect ];
+  [_prefTable reloadData];
+
+  // [self setTitle:collection]; // ***** can't seem to be this to work!!!! but does in MenuCascadeView
+
+
+  [self addSubview: _navbar];
+  [self addSubview: _prefTable];
+
+  return self;
+}
+
+
+-(void) setTitle:(NSString*)title
+{
+  UINavigationItem* navtitle = [UINavigationItem alloc];
+  [_navbar pushNavigationItem: [navtitle initWithTitle: title]];
+}
+
+-(NSString*) languagePref
+{
+  return [_prefTable languagePref];
+}
+
+
+//***********
+//* Delegates 
+//***********
+
+- (void)navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button
+{
+  switch (button) 
+  {
+    case 1:  // left
+      [GreenstoneApplication setInCollection:nil];
+      [GreenstoneApplication transitionView:UITransitionBothShiftRight 
+          fromView:self toView:_parent];
+      break;
+
+    default:
+      NSLog(@"Unrecognised navbar button = %d",button);
+      break;
+  }
+
+}
+
+
+-(void) dealloc
+{
+  [_collection release];
+
+  [super dealloc];
+}
+
+@end
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/PrefViewController.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/PrefViewController.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/PrefViewController.h	(revision 22603)
@@ -0,0 +1,11 @@
+
+#import <UIKit/UIKit.h>
+
+#define PREF_NUM_GROUPS 2
+#define PREF_CELLS_PER_GROUP 2
+
+@interface PrefViewController : UITableViewController <UITextFieldDelegate> {
+	UITextField *activeTextField;
+}
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/PrefViewController.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/PrefViewController.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/PrefViewController.mm	(revision 22603)
@@ -0,0 +1,209 @@
+
+#import "PrefViewController.h"
+
+
+@implementation PrefViewController
+
+- (id) init {
+    self = [ super initWithStyle: UITableViewStyleGrouped ];
+	
+    if (self != nil) {
+        self.title = @"Preferences";
+    }
+    return self;
+}
+
+/*
+// The designated initializer. Override to perform setup that is required before the view is loaded.
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
+        // Custom initialization
+    }
+    return self;
+}
+*/
+
+
+// Implement loadView to create a view hierarchy programmatically, without using a nib.
+- (void)loadView {
+	[super loadView];
+}
+
+/*
+// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
+- (void)viewDidLoad {
+    [super viewDidLoad];
+}
+*/
+
+
+/*
+ // Override to allow orientations other than the default portrait orientation.
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+	// Return YES for supported orientations
+	return (interfaceOrientation == UIInterfaceOrientationPortrait);
+}
+*/
+/*
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation duration:(NSTimeInterval)duration {
+	LogMethod();
+	switch (interfaceOrientation) {
+		 case UIInterfaceOrientationPortrait: 
+		 {
+		 }
+		 break;
+		 
+		 case UIInterfaceOrientationLandscapeRight: 
+		 {
+		 }
+		 break;
+		 
+		 case UIInterfaceOrientationLandscapeRight: 
+		 {
+		 }
+		 break;
+	}
+}
+ 
+- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+	LogMethod();
+}
+*/
+
+- (void)didReceiveMemoryWarning {
+	// Releases the view if it doesn't have a superview.
+    [super didReceiveMemoryWarning];
+	
+	// Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+	// Release any retained subviews of the main view.
+	// e.g. self.myOutlet = nil;
+	activeTextField = nil;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+
+    /* Number of logical groups, including labels ?!?*/
+    return PREF_NUM_GROUPS;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+    switch (section) {
+        case(0):
+            return 1;
+            break;
+        case(1):
+            return 2;
+            break;
+    }
+	
+    return 0;
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
+{
+    switch (section) {
+        case(0):
+            return @"Presentation";
+            break;
+        case(1):
+            return @"Search";
+            break;
+    }
+    return nil;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    NSString *CellIdentifier = [ NSString stringWithFormat: @"%d:%d", [ indexPath indexAtPosition: 0 ], [ indexPath indexAtPosition:1 ]];
+	
+    UITableViewCell *cell = [ tableView dequeueReusableCellWithIdentifier: CellIdentifier];
+	
+    if (cell == nil) {
+        cell = [ [ [ UITableViewCell alloc ] initWithFrame: CGRectZero reuseIdentifier: CellIdentifier] autorelease ];
+		
+        cell.selectionStyle = UITableViewCellSelectionStyleNone;
+		
+        switch ([ indexPath indexAtPosition: 0]) {
+            case(0):
+                switch([ indexPath indexAtPosition: 1]) {
+                    case(0):
+		      {
+			UISegmentedControl *langControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects: @"English", @"French", @"German", nil]];
+			langControl.contentMode = UIViewContentModeScaleToFill;
+			langControl.frame =  CGRectMake(145, 5, 150, 35);
+			langControl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
+			langControl.selectedSegmentIndex = 0;
+			langControl.tag = 3;
+			[langControl addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
+			langControl.segmentedControlStyle = UISegmentedControlStyleBar;
+			
+			[cell addSubview:langControl];
+			cell.textLabel.text = @"Language";
+			[langControl release];
+		      }
+		      break;
+                }
+                break;
+            case(1):
+                switch ([ indexPath indexAtPosition: 1 ]) {
+                    case(0):
+		      {
+			UISwitch *stemmingControl = [ [ UISwitch alloc ] initWithFrame: CGRectMake(200, 10, 60, 30) ];
+			stemmingControl.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
+			stemmingControl.on = YES;
+			stemmingControl.tag = 1;
+			[stemmingControl addTarget:self action:@selector(switchAction:) forControlEvents:UIControlEventValueChanged];
+			[ cell addSubview: stemmingControl ];
+			cell.textLabel.text = @"Stemming";
+			[stemmingControl release];
+		      }
+		      break;
+		    case(1):
+		      {
+			UISwitch *casematchControl = [ [ UISwitch alloc ] initWithFrame: CGRectMake(200, 10, 50, 30) ];
+			casematchControl.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
+			casematchControl.on = NO;
+			casematchControl.tag = 2;
+			[casematchControl addTarget:self action:@selector(switchAction:) forControlEvents:UIControlEventValueChanged];
+			[ cell addSubview: casematchControl ];
+			cell.textLabel.text = @"Case matching";
+			[casematchControl release];
+		      }
+		      break;
+		}
+                break;
+        }
+    }
+	
+    return cell;
+}
+
+#pragma mark ControlEventTarget Actions
+
+
+- (void)segmentAction:(UISegmentedControl*)sender
+{
+	if ([activeTextField canResignFirstResponder])
+		[activeTextField resignFirstResponder];
+	
+	DEBUGLOG(NSLog(@"segmentAction: sender = %d, segment = %d",  [sender tag], [sender selectedSegmentIndex]));
+}
+
+- (void)switchAction:(UISwitch*)sender
+{
+	if ([activeTextField canResignFirstResponder])
+		[activeTextField resignFirstResponder];
+	DEBUGLOG(NSLog(@"switchAction: sender = %d, isOn %d",  [sender tag], [sender isOn]));
+}
+
+
+- (void)dealloc {
+	[activeTextField release];
+    [super dealloc];
+}
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/QueryCascadeView.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/QueryCascadeView.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/QueryCascadeView.h	(revision 22603)
@@ -0,0 +1,22 @@
+
+#import "MenuCascadeView.h"
+#import "QueryView.h"
+
+@interface QueryCascadeView: MenuCascadeView
+{
+  NSMutableArray* _queryViews;
+}
+
+-(id) initWithFrame:(CGRect)rect withParent:(UIView*)parent 
+        withCollection:(NSString*)collection withTitle:(NSString*)title withGID:(NSString*)gid;
+
+-(UIView*) directEntry:(int)rowId;
+
+-(void) appendMenuItem:(NSObject*)app withItem:(NSString*)item_label withGID:(NSString*)childGID;
+
+-(void) tableRowSelected:(NSNotification*)notification;
+
+-(void) dealloc;
+
+@end
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/QueryCascadeView.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/QueryCascadeView.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/QueryCascadeView.mm	(revision 22603)
@@ -0,0 +1,65 @@
+
+#import "GSResultItem.h"
+#import "GreenstoneApplication.h"
+
+#import "QueryCascadeView.h"
+
+
+@implementation QueryCascadeView
+
+
+-(id) initWithFrame:(CGRect)rect withParent:(UIView*)parent 
+        withCollection:(NSString*)collection withTitle:(NSString*)title withGID:(NSString*)gid
+{
+  _queryViews = [[NSMutableArray alloc] initWithCapacity:MCInitCapacity];
+
+  return [super initWithFrame:rect withParent:parent withCollection:collection 
+	 withTitle:title withGID:gid];
+}
+
+-(void) appendMenuItem:(NSObject*)app withItem:(NSString*)item_label withGID:(NSString*)childGID
+{
+  [super appendMenuItem:app withItem:item_label withGID:childGID];
+
+  CGRect workarea_rect = [GreenstoneApplication workAreaRect];
+  QueryView* queryView = [[QueryView alloc] initWithFrame:workarea_rect 
+			withParent:self withCollection:childGID withTitle:item_label];
+
+  [_queryViews addObject:queryView];  
+
+}
+
+-(void) tableRowSelected:(NSNotification*)notification
+{
+  UITable* table = [notification object];
+  int rowId = [table selectedRow];
+
+  GreenstoneAPI* greenstoneAPI = [GreenstoneApplication greenstoneAPI];
+
+  NSString* childTitle = [[_oidItem objectAtIndex:rowId] title];  
+  NSString* childGID = [[_oidItem  objectAtIndex:rowId] oid]; 
+
+  NSString* chosenCollection = [[NSString alloc] initWithString:childGID]; 
+
+  CGRect workarea_rect = [GreenstoneApplication workAreaRect];
+  QueryView* queryView = [_queryViews objectAtIndex:rowId];
+
+  [GreenstoneApplication setInCollection:chosenCollection];
+  [GreenstoneApplication transitionView:UITransitionBothShiftLeft 
+        fromView:self toView:queryView];
+}
+
+-(UIView*) directEntry:(int)rowId
+{
+  return [_queryViews objectAtIndex:rowId];
+}
+
+-(void) dealloc
+{
+  [_queryViews release];
+
+  [super dealloc];
+}
+
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/QueryView.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/QueryView.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/QueryView.h	(revision 22603)
@@ -0,0 +1,62 @@
+#import <Foundation/Foundation.h>
+#import <Foundation/NSDictionary.h>
+
+#import <UIKit/UIKit.h>
+#import <UIKit/UITextLabel.h>
+#import <UIKit/UIKeyboard.h>
+#import <UIKit/UIImageAndTextTableCell.h>
+#import <UIKit/UISearchField.h>
+#import <UIKit/UIApplication.h>
+
+// **** can searchtablecell be done away with?
+
+@interface SearchTableCell : UIImageAndTextTableCell
+{
+        UITextLabel* song_name;
+        UITextLabel* artist_name;
+        
+@public
+        char m_Path[256];
+}
+@end
+
+
+@interface QueryView : UIView
+{
+  UIView* _parent;
+  NSString* _collection;
+
+  UIKeyboard* _keyboard;
+  BOOL _keyboardVisible;
+ 
+  UINavigationBar* _navbar;
+  //UISearchField* _searchBox;
+  UISearchBar* _searchBar;
+       
+  NSMutableArray* _cellResultList;
+  NSMutableArray* _oidItem;
+  
+  UITable* _table;
+
+}
+
+-(id) initWithFrame:(struct CGRect)frame withParent:(UIView*)parent 
+         withCollection:(NSString*)collection withTitle:(NSString*)title;
+
+-(void) setTitle:(NSString*)title;
+
+
+-(void) navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button;
+
+-(void) tableRowSelected:(NSNotification*)notification;
+-(void) asynchronousLoad:(NSTimer*)timer;
+
+-(void)keyboardInput:(id)k shouldInsertText:(id)i isMarkedText:(int)b;
+
+- (void)keyboardReturnPressed;
+- (void)ShowKeyboard;
+- (void)HideKeyboard;
+
+-(void) dealloc;
+
+@end
Index: /gs2-extensions/iOs-3.x/trunk/Classes/QueryView.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/QueryView.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/QueryView.mm	(revision 22603)
@@ -0,0 +1,404 @@
+#import <CoreFoundation/CoreFoundation.h>
+#import <Foundation/Foundation.h>
+#import <UIKit/CDStructures.h>
+#import <UIKit/UITextLabel.h>
+#import <UIKit/UIDateLabel.h> // For defaultFont.
+#import <UIKit/UITable.h>
+#import <UIKit/UITableCell.h>
+#import <UIKit/UITableColumn.h>
+//#import <UIKit/UISearchField.h>
+#import <UIKit/UISearchBar.h>
+#import <UIKit/UIFrameAnimation.h>
+#import <UIKit/UITransitionView.h>
+#import <UIKit/UIAnimator.h>
+
+#import "GreenstoneApplication.h"
+//#import "SimpleWebView.h"
+#import "GSResultItem.h"
+
+#import "QueryView.h"
+
+@implementation SearchTableCell
+
+// ***** is the following needed, or need to be modified? 
+- (void) drawContentInRect: (struct CGRect)rect selected: (BOOL) selected
+{
+  [song_name setHighlighted: selected];
+  [artist_name setHighlighted: selected];
+  [super drawContentInRect: rect selected: selected];
+}
+
+@end
+
+
+@implementation QueryView
+
+- (id)initWithFrame:(struct CGRect)frame withParent:(UIView*)parent 
+       withCollection:(NSString*)collection withTitle:(NSString*)title
+{
+  self = [super initWithFrame:frame];
+
+  _parent = parent;
+  _collection = collection;
+
+  // Create the storage array.
+  _cellResultList = [[NSMutableArray alloc] init];
+  _oidItem = [[NSMutableArray alloc] init];
+
+
+  // Create the navigation bar
+  int frame_x_dim = CGRectGetMaxX(frame)+1;
+  int frame_y_dim = CGRectGetMaxY(frame)+1;
+  
+  int nbr1_x_org = 0;
+  int nbr1_y_org = 0;
+  int nbr1_x_dim = frame_x_dim;
+  int nbr1_y_dim = TOP_NAVBAR_HEIGHT;
+
+  CGRect navbar1_rect = CGRectMake(nbr1_x_org,nbr1_y_org,nbr1_x_dim,nbr1_y_dim);
+
+  UINavigationBar* navbar1 = [[UINavigationBar alloc] initWithFrame:navbar1_rect];
+  [navbar1 showLeftButton:@"Back" withStyle:1 rightButton:nil withStyle:0]; // 2 = arrow left.
+  [navbar1 setBarStyle: UIBarStyleDefault]; 
+  [self addSubview: navbar1];
+  [navbar1 enableAnimation];
+  [navbar1 setDelegate:self];
+
+  _navbar = navbar1;
+  [self setTitle:title];
+
+
+  // Not sure if a second nav bar is really the way to get a 
+  // search box with background seamlessly merged with main nav bar
+  // Tried to make 1 navbar high enough for everything, but back 
+  // button was alligned to bottom of bar
+
+  int nbr2_x_org = nbr1_x_org;
+  int nbr2_y_org = nbr1_y_dim;
+  int nbr2_x_dim = nbr1_x_dim;
+  int nbr2_y_dim = [UISearchField defaultHeight];
+
+  CGRect navbar2_rect = CGRectMake(nbr2_x_org,nbr2_y_org,nbr2_x_dim,nbr2_y_dim);
+  UINavigationBar* navbar2 = [[UINavigationBar alloc] initWithFrame:navbar2_rect];
+  [navbar2 showLeftButton:nil withStyle:0 rightButton:nil withStyle:0]; 
+  [navbar2 enableAnimation];
+  [navbar2 setBarStyle: UIBarStyleDefault]; 
+  [navbar2 setDelegate:self];
+
+  [self addSubview: navbar2];
+
+
+  // Create the search box.
+
+  int sr_x_org = 30;
+  int sr_y_org = 0;
+  int sr_x_dim =  frame.size.width - (2*30);
+  int sr_y_dim = [UISearchField defaultHeight];
+
+  CGRect search_rect = CGRectMake(sr_x_org,sr_y_org,sr_x_dim,sr_y_dim);
+
+  _searchBar = [[UISearchBar alloc] initWithFrame:search_rect];
+  _searchBar.delegate = self;
+  _searchBar.showsCancelButton = NO;
+
+  //_searchBox = [[UISearchField alloc] initWithFrame:search_rect];
+  //[_searchBox setClearButtonStyle:2];
+  //[_searchBox setFont:[UIFont systemFontOfSize:14.0]];
+
+  ////[[_searchBox textTraits] setReturnKeyType: UIReturnKeySearch];
+  ////[[_searchBox textTraits] setEditingDelegate:self];
+  ////[[_searchBox textTraits] setAutoCapsType: NO];
+  ////[[_searchBox textTraits] setAutoCorrectionType:1];
+
+
+  [_searchBar setText:@""];
+  ////[_searchBox setDisplayEnabled:YES];
+
+  [_searchBar becomeFirstResponder];
+
+
+  // Create the table.
+  int tab_y_org = nbr2_y_org+nbr2_y_dim;
+  CGRect table_rect = CGRectMake(0, tab_y_org, frame.size.width, frame_y_dim - tab_y_org);
+
+  _table = [[UITable alloc] initWithFrame:table_rect];
+  [self addSubview: _table];
+
+  UITableColumn *col = [[UITableColumn alloc] initWithTitle: @"iMPDclient" identifier: @"column1" width: frame_x_dim];
+  [_table addTableColumn: col];
+  [_table setDelegate: self];
+  [_table setDataSource: self];
+  [_table setSeparatorStyle:1];
+  [_table setRowHeight:42.0f];
+  
+
+  // Create the keyboard
+  int kb_x_org = 0;
+  int kb_y_org = 410 - [UIKeyboard defaultSize].height;
+  int kb_x_dim = frame.size.width; // ****? what about when landscape
+  int kb_y_dim = [UIKeyboard defaultSize].height;
+  CGRect kb_rect = CGRectMake(kb_x_org,kb_y_org,kb_x_dim,kb_y_dim);
+
+  //_keyboard = [[UIKeyboard alloc] initWithFrame:kb_rect];
+
+  //[self addSubview: _keyboard];
+  //_keyboardVisible = YES;
+  
+  [navbar2 addSubview:_searchBar];
+
+  return self;
+}
+
+-(void) setTitle:(NSString*)title
+{
+  UINavigationItem* navtitle = [UINavigationItem alloc];
+  [_navbar pushNavigationItem: [navtitle initWithTitle:title]];
+}
+
+
+- (void)performQuery:(NSString *)searchtext
+{
+  GreenstoneAPI* greenstoneAPI = [GreenstoneApplication greenstoneAPI];
+  NSMutableArray* resultlist = greenstoneAPI->query(_collection,searchtext);
+
+  [_cellResultList removeAllObjects];
+  [_oidItem removeAllObjects];
+
+  if (resultlist != nil) {
+    NSEnumerator* resultlist_enumerator = [resultlist objectEnumerator];
+    GSResultItem* resultitem;
+    while (resultitem = [resultlist_enumerator nextObject]) {
+
+      SearchTableCell* cell = [[SearchTableCell alloc] init];
+      
+      NSString* resultoid = [resultitem oid];
+
+      NSString* resulttitle = [resultitem title];
+      if (resulttitle == nil) {
+	// doesn't have a valid title 
+	resulttitle = [[NSString alloc] initWithString:@"Unknown Title"];
+      }
+
+      NSString* resulturl = [resultitem srcurl];
+      if (resulturl == nil) { // **** don't need to do this check now
+	// doesn't have a valid srcurl => set as the empty string
+	resulturl = [[NSString alloc] initWithString:@""];
+      }
+
+      [cell setTitle:resulttitle];
+      [_cellResultList addObject:cell];
+      [_oidItem addObject:resultitem];
+
+      [cell release];
+    }
+    [resultlist release];
+  }
+
+  // Update the table contents.
+  [_table reloadData];
+}
+
+
+
+//***********
+//* Delegates 
+//***********
+
+-(void) navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button
+{
+  switch (button) 
+  {
+    case 1:  // left
+      [GreenstoneApplication setInCollection:nil];
+      [GreenstoneApplication transitionView:UITransitionBothShiftRight 
+          fromView:self toView:_parent];
+      break;
+
+    default:
+      NSLog(@"Unrecognised navbar button = %d",button);
+      break;
+  }
+}
+
+
+- (void)tableRowSelected:(NSNotification*)notification
+{
+  UITable* table = [notification object];
+  int rowId = [table selectedRow];
+
+  SearchTableCell* pCell = [table cellAtRow:rowId column:0];
+  [pCell setSelected:FALSE withFade:TRUE];
+
+  GSResultItem* oidItem = [_oidItem objectAtIndex:rowId];
+
+  NSString* oid = [oidItem oid];
+  NSString* srcurl = [oidItem srcurl];
+
+  NSURL *url = [NSURL alloc];
+
+  if (srcurl == nil) {
+
+    NSTimer *timer = [ NSTimer scheduledTimerWithTimeInterval: 0.3
+			 target: self
+			 selector: @selector(asynchronousLoad:)
+			 userInfo: oid
+			 repeats: NO ];
+    url = [url initWithString:@"file:///var/gs2-runtime-svn/ext/iOS3.x/loading.html"]; // ****
+
+    /* *****
+    GreenstoneAPI* greenstoneAPI = [GreenstoneApplication greenstoneAPI];
+    NSString* doctext = greenstoneAPI->getResolvedDocument(_collection,oid);
+    [doctext writeToFile:@"/tmp/gsdoc.html" atomically:NO encoding:NSUTF8StringEncoding error:nil];
+
+    // make sure file is writable by all 
+    // => allows for switching between running from command line and Springboard
+    system("chmod a+rw /tmp/gsdoc.html"); 
+
+    url = [url initWithString:@"file:///tmp/gsdoc.html"];
+    */
+
+  }
+  else {
+    NSString* fullurlstr = [[NSString alloc] initWithFormat:@"file://%@",srcurl];
+    url = [url initWithString:fullurlstr]; 
+  }
+
+  int transStyle = UITransitionBothShiftLeft;   
+  [GreenstoneApplication showWebView:transStyle fromView:self withURL:url];
+
+}
+
+-(void) asynchronousLoad:(NSTimer*)timer
+{
+  // **** This is identical to one in BrowseCascadeMenu
+  NSString* childGID = [timer userInfo];
+
+  GreenstoneAPI* greenstoneAPI = [GreenstoneApplication greenstoneAPI];
+  NSString* doctext = greenstoneAPI->getResolvedDocument(_collection,childGID);
+
+  [doctext writeToFile:@"/tmp/gsdoc.html" atomically:NO encoding:NSUTF8StringEncoding error:nil];
+  NSURL* url = [[NSURL alloc] initWithString:@"file:///tmp/gsdoc.html"];
+  system("chmod a+rw /tmp/gsdoc.html"); 
+
+  [GreenstoneApplication showWebView:0 fromView:self withURL:url];
+}
+
+
+- (int) numberOfRowsInTable: (UITable *)table
+{
+  return [_cellResultList count];
+}
+
+
+- (UITableCell *) table: (UITable *)table cellForRow: (int)row column: (int)col
+{
+  return [_cellResultList objectAtIndex:row];
+}
+
+- (UITableCell *) table: (UITable *)table cellForRow: (int)row column: (int)col reusing: (BOOL) reusing
+{
+  return [self table: table cellForRow: row column: col];
+}
+
+
+- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
+    NSString* query = [_searchBar text];
+
+    [self performQuery:query];
+}
+
+
+
+- (void)keyboardInputChangedSelection:(id)whatisthis
+{
+  // when i tap the search field, hide if keyboard is already there, or show if it isn't
+  if (!_keyboardVisible)
+    [self ShowKeyboard];
+}
+
+-(void)keyboardInput:(id)k shouldInsertText:(id)i isMarkedText:(int)b
+{
+  if ([i characterAtIndex:0] == 0xA) {
+    [self keyboardReturnPressed];
+
+    NSString* query = [_searchBar text];
+    [self performQuery:query];
+  }
+}
+
+- (void)scrollerWillStartDragging:(id)whatisthis
+{
+  // hide keyboard when start scrolling
+  if (_keyboardVisible)
+    [self HideKeyboard];
+}
+
+// --- KEYBOARD METHODS -----------------------------------------------
+
+- (void)keyboardReturnPressed
+{
+  [self HideKeyboard];
+}
+
+- (void)ShowKeyboard
+{
+  _keyboardVisible = YES;
+  
+  CGRect startFrame;
+  CGRect endFrame;
+  NSMutableArray *animations = [[NSMutableArray alloc] init];
+  
+  endFrame = CGRectMake(0.0f, 410 - [UIKeyboard defaultSize].height, 320, [UIKeyboard defaultSize].height);
+  startFrame = endFrame;
+  startFrame.origin.y = 245.0 + 216.;
+  
+  [_keyboard setFrame:startFrame];
+  
+  UIFrameAnimation *keyboardAnimation = [[UIFrameAnimation alloc] initWithTarget:_keyboard];
+  [keyboardAnimation setStartFrame:startFrame];
+  [keyboardAnimation setEndFrame:endFrame];
+  [keyboardAnimation setSignificantRectFields:2];
+  [keyboardAnimation setDelegate:self];
+  [animations addObject:keyboardAnimation];
+  [keyboardAnimation release];
+  
+  [[UIAnimator sharedAnimator] addAnimations:animations withDuration:.5 start:YES];
+}
+
+- (void)HideKeyboard
+{
+  _keyboardVisible = NO;
+  
+  CGRect startFrame;
+  CGRect endFrame;
+  NSMutableArray *animations = [[NSMutableArray alloc] init];
+  
+  startFrame = CGRectMake(0, 410 - [UIKeyboard defaultSize].height, 320, [UIKeyboard defaultSize].height);
+  endFrame = startFrame;
+  endFrame.origin.y = 245.0 + 216.;
+  
+  [_keyboard setFrame:startFrame];
+  
+  UIFrameAnimation *keyboardAnimation = [[UIFrameAnimation alloc] initWithTarget:_keyboard];
+  [keyboardAnimation setStartFrame:startFrame];
+  [keyboardAnimation setEndFrame:endFrame];
+  [keyboardAnimation setSignificantRectFields:2];
+  [keyboardAnimation setDelegate:self];
+  [animations addObject:keyboardAnimation];
+  [keyboardAnimation release];
+  
+  [[UIAnimator sharedAnimator] addAnimations:animations withDuration:.5 start:YES];
+}
+
+
+-(void) dealloc
+{
+  [_oidItem release];
+
+  [_collection release];
+
+  [super dealloc];
+}
+
+@end
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/SimpleWebView.h
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/SimpleWebView.h	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/SimpleWebView.h	(revision 22603)
@@ -0,0 +1,40 @@
+/*
+        By: Sean Heber  <sean@spiffytech.com>, J. Zdziarski
+        iApp-a-Day - November, 2007
+        BSD License
+*/
+#import <UIKit/UIKit.h>
+#import <UIKit/UIScroller.h>
+#import <UIKit/UIWebView.h>
+
+@interface MyWebView : UIWebView
+{
+
+}
+-(void) gestureEnded:(struct __GSEvent *)event;
+-(void) doubleTap:(struct __GSEvent *)event;
+
+@end
+
+@interface SimpleWebView : UIView {
+  UIView* _parent;
+  MyWebView *webView;
+  UIScroller *scroller;
+  NSURLRequest *urlRequest;
+
+  CGSize lastSize, size;
+}
+
+-(id)initWithFrame:(CGRect)frame;
+-(id)initWithFrame:(CGRect)frame withParent:(UIView*)parent;
+
+-(void) setParent:(UIView*)parent;
+
+-(id) loadURL:(NSURL*)url;
+
+
+
+-(void) dealloc;
+@end
+
+
Index: /gs2-extensions/iOs-3.x/trunk/Classes/SimpleWebView.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Classes/SimpleWebView.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Classes/SimpleWebView.mm	(revision 22603)
@@ -0,0 +1,195 @@
+/* BSD License: Based on SimpleWebView by Sean Heber  <sean@spiffytech.com>, J. Zdziarski  */
+
+#include <sys/select.h>
+
+#import <UIKit/UIView-Geometry.h>
+#import <UIKit/UIView-Rendering.h>
+
+#import "GreenstoneApplication.h"
+#import "SimpleWebView.h"
+
+// ****** change name away from SimpleWebView
+
+
+@implementation MyWebView
+- (void) gestureEnded:(struct __GSEvent *)event
+{
+    [ super gestureEnded: event ];
+    //[ _delegate gestureEnded: event ]; // *****
+}
+
+- (void) doubleTap:(struct __GSEvent *)event
+{
+    [ super doubleTap: event ];
+    //[ _delegate doubleTap: event ]; // *****
+}
+
+
+@end
+
+
+@implementation SimpleWebView
+
+-(void)view: (UIView*)v didSetFrame:(CGRect)f
+{
+    if (v == webView) {
+        [ scroller setContentSize: f.size ];
+    }
+}
+
+-(void)view:(id)v didDrawInRect:(CGRect)f duration:(float)d
+{
+    if (v == webView) {
+        size = [ webView bounds ].size;
+        if (size.height != lastSize.height
+        || size.width != lastSize.width)
+        {
+            lastSize = size;
+            [ scroller setContentSize: size ];
+        }
+    }
+}
+
+- (void)gestureEnded:(struct __GSEvent *)event {
+    [ webView redrawScaledDocument ];
+    [ webView setNeedsDisplay ];
+    [ scroller setContentSize: [ webView bounds ].size ];
+}
+
+- (void)doubleTap:(struct __GSEvent *)event {
+    struct timeval tv;
+    tv.tv_sec = 2;
+    tv.tv_usec = 0;
+    select(NULL, NULL, NULL, NULL, &tv);
+    [ webView redrawScaledDocument ];
+    [ webView setNeedsDisplay ];
+    [ scroller setContentSize: [ webView bounds ].size ];
+}
+
+
+-(void)dealloc
+{
+        [ urlRequest release ];
+        [ webView release ];
+        [ scroller release ];
+
+        [ super dealloc ];
+}
+
+-(id)initWithFrame: (CGRect)frame
+{
+  return [self initWithFrame:frame withParent:nil];
+}
+
+
+-(id)initWithFrame: (CGRect)frame withParent:(UIView*)parent
+{
+    [ super initWithFrame: frame ];
+
+    _parent = parent;
+    urlRequest = nil;
+
+    int frame_x_dim = frame.size.width;
+    int frame_y_dim = frame.size.height;
+
+    int nav_x_org = 0.0f;
+    int nav_y_org = 0.0f;
+    int nav_x_dim = frame_x_dim;
+    int nav_y_dim = TOP_NAVBAR_HEIGHT;
+    
+    CGRect navrect = CGRectMake(nav_x_org,nav_y_org,nav_x_dim,nav_y_dim);
+    UINavigationBar* navbar = [[UINavigationBar alloc] initWithFrame: navrect];
+
+    [navbar showButtonsWithLeftTitle:@"Back" rightTitle:nil leftBack:YES];
+    [navbar enableAnimation];
+    [navbar setBarStyle: UIBarStyleBlackTranslucent];  // Dark, transparent // ****
+    [navbar setDelegate: self];
+
+    int scroll_x_org = 0.0f;
+    int scroll_y_org = 0.0f;
+    int scroll_x_dim = frame_x_dim;
+    int scroll_y_dim = frame_y_dim;
+
+    CGRect scrollrect = CGRectMake(scroll_x_org,scroll_y_org,scroll_x_dim,scroll_y_dim);
+
+    scroller = [ [ UIScroller alloc ] initWithFrame: scrollrect ];
+    [ scroller setScrollingEnabled: YES ];
+    [ scroller setAdjustForContentSizeChange: YES ];
+    [ scroller setClipsSubviews: NO ];
+    [ scroller setAllowsRubberBanding: YES ];
+    [ scroller setDelegate: self ];
+
+
+    webView = [ [ MyWebView alloc ] initWithFrame: [ scroller bounds ] ];    
+    //[ webView setTilingEnabled: YES ];
+    //[ webView setTileSize: scrollrect.size ];
+    //[ webView setAutoresizes: YES];
+    [ webView setDelegate: self];
+    //[ webView setEnabledGestures: 0xFF ];
+    //[ webView setSmoothsFonts: YES ];
+    
+
+    [ self addSubview: scroller ];
+    [ scroller addSubview: webView ];
+
+    [self addSubview: navbar];
+	
+    return self;
+}
+
+
+-(void) setParent:(UIView*)parent
+{
+  _parent = parent;
+}
+
+
+-(id) loadURL:(NSURL*)url
+{
+    CGPoint zero;
+    zero.x = zero.y = 0;
+    [scroller scrollPointVisibleAtTopLeft: zero];
+
+    if (urlRequest != nil) { // ***** 
+      [urlRequest release];
+      urlRequest = nil;
+    }
+
+    urlRequest = [[NSURLRequest requestWithURL:url] retain];
+    [webView loadRequest:urlRequest];
+}
+
+
+//***********
+//* Delegates
+//***********
+
+
+
+-(void) navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button 
+{
+  switch (button) 
+  {
+    case 1:  // left
+      if (_parent != nil) {
+	// only do transition if there is a parent view to go back to
+	int transStyle = UITransitionBothShiftRight;
+	[GreenstoneApplication transitionView:transStyle fromView:self toView:_parent];
+      }
+
+      // need to think about deallocating self? // *****
+      break;
+
+    default:
+      NSLog(@"Unrecognised button = %d",button);
+      break;
+  }
+}
+
+@end
+
+
+
+
+
+
Index: /gs2-extensions/iOs-3.x/trunk/Greenstone2-Info.plist
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Greenstone2-Info.plist	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Greenstone2-Info.plist	(revision 22603)
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleDisplayName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+</dict>
+</plist>
Index: /gs2-extensions/iOs-3.x/trunk/Greenstone2.xcodeproj/project.pbxproj
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Greenstone2.xcodeproj/project.pbxproj	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Greenstone2.xcodeproj/project.pbxproj	(revision 22603)
@@ -0,0 +1,307 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		1D3623260D0F684500981E51 /* TabBarSampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* TabBarSampleAppDelegate.m */; };
+		1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+		1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+		1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
+		28216C970DB411BC00E5133A /* ListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28216C960DB411BC00E5133A /* ListViewController.m */; };
+		288765080DF74369002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765070DF74369002DB57D /* CoreGraphics.framework */; };
+		433495EA11BBBD4B0002851B /* tab_search.png in Resources */ = {isa = PBXBuildFile; fileRef = 433495E911BBBD4B0002851B /* tab_search.png */; };
+		433495EC11BBBD590002851B /* tab_star.png in Resources */ = {isa = PBXBuildFile; fileRef = 433495EB11BBBD590002851B /* tab_star.png */; };
+		433495EE11BBBD790002851B /* tab_contact.png in Resources */ = {isa = PBXBuildFile; fileRef = 433495ED11BBBD790002851B /* tab_contact.png */; };
+		433495F011BBBE090002851B /* tab_recent.png in Resources */ = {isa = PBXBuildFile; fileRef = 433495EF11BBBE090002851B /* tab_recent.png */; };
+		433495F211BBBE270002851B /* tab_list.png in Resources */ = {isa = PBXBuildFile; fileRef = 433495F111BBBE270002851B /* tab_list.png */; };
+		433495F811BBBFC30002851B /* StarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 433495F411BBBFC30002851B /* StarViewController.m */; };
+		433495F911BBBFC30002851B /* RecentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 433495F611BBBFC30002851B /* RecentViewController.m */; };
+		4334964111BBC1A00002851B /* SearchViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4334963F11BBC1A00002851B /* SearchViewController.m */; };
+		4334966B11BBCE4C0002851B /* tab_setting.png in Resources */ = {isa = PBXBuildFile; fileRef = 4334966A11BBCE4C0002851B /* tab_setting.png */; };
+		4334966E11BBCEBE0002851B /* SettingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4334966D11BBCEBE0002851B /* SettingViewController.m */; };
+		433496B111BBD5FB0002851B /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 433496B011BBD5FB0002851B /* TableViewController.m */; };
+		436409CB11BBF06C008B6A4C /* DataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 436409CA11BBF06C008B6A4C /* DataManager.m */; };
+		43640B3D11BC0DFC008B6A4C /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 43640B3C11BC0DFC008B6A4C /* Icon.png */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		1D3623240D0F684500981E51 /* TabBarSampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TabBarSampleAppDelegate.h; sourceTree = "<group>"; };
+		1D3623250D0F684500981E51 /* TabBarSampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TabBarSampleAppDelegate.m; sourceTree = "<group>"; };
+		1D6058910D05DD3D006BFB54 /* TabBarSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TabBarSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		28216C950DB411BC00E5133A /* ListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ListViewController.h; sourceTree = "<group>"; };
+		28216C960DB411BC00E5133A /* ListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ListViewController.m; sourceTree = "<group>"; };
+		288765070DF74369002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		28A0AB4B0D9B1048005BE974 /* TabBarSample_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TabBarSample_Prefix.pch; sourceTree = "<group>"; };
+		29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		433495E911BBBD4B0002851B /* tab_search.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_search.png; sourceTree = "<group>"; };
+		433495EB11BBBD590002851B /* tab_star.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_star.png; sourceTree = "<group>"; };
+		433495ED11BBBD790002851B /* tab_contact.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_contact.png; sourceTree = "<group>"; };
+		433495EF11BBBE090002851B /* tab_recent.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_recent.png; sourceTree = "<group>"; };
+		433495F111BBBE270002851B /* tab_list.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_list.png; sourceTree = "<group>"; };
+		433495F411BBBFC30002851B /* StarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StarViewController.m; sourceTree = "<group>"; };
+		433495F511BBBFC30002851B /* StarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StarViewController.h; sourceTree = "<group>"; };
+		433495F611BBBFC30002851B /* RecentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentViewController.m; sourceTree = "<group>"; };
+		433495F711BBBFC30002851B /* RecentViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentViewController.h; sourceTree = "<group>"; };
+		4334963F11BBC1A00002851B /* SearchViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SearchViewController.m; sourceTree = "<group>"; };
+		4334964011BBC1A00002851B /* SearchViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchViewController.h; sourceTree = "<group>"; };
+		4334966A11BBCE4C0002851B /* tab_setting.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_setting.png; sourceTree = "<group>"; };
+		4334966C11BBCEBE0002851B /* SettingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingViewController.h; sourceTree = "<group>"; };
+		4334966D11BBCEBE0002851B /* SettingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingViewController.m; sourceTree = "<group>"; };
+		433496AF11BBD5FB0002851B /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = "<group>"; };
+		433496B011BBD5FB0002851B /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = "<group>"; };
+		436409C911BBF06C008B6A4C /* DataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataManager.h; sourceTree = "<group>"; };
+		436409CA11BBF06C008B6A4C /* DataManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataManager.m; sourceTree = "<group>"; };
+		43640B3C11BC0DFC008B6A4C /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; };
+		8D1107310486CEB800E47090 /* TabBarSample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TabBarSample-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
+				1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
+				288765080DF74369002DB57D /* CoreGraphics.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		080E96DDFE201D6D7F000001 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				436409C911BBF06C008B6A4C /* DataManager.h */,
+				436409CA11BBF06C008B6A4C /* DataManager.m */,
+				433496AF11BBD5FB0002851B /* TableViewController.h */,
+				433496B011BBD5FB0002851B /* TableViewController.m */,
+				28216C950DB411BC00E5133A /* ListViewController.h */,
+				28216C960DB411BC00E5133A /* ListViewController.m */,
+				433495F511BBBFC30002851B /* StarViewController.h */,
+				433495F411BBBFC30002851B /* StarViewController.m */,
+				433495F711BBBFC30002851B /* RecentViewController.h */,
+				433495F611BBBFC30002851B /* RecentViewController.m */,
+				4334964011BBC1A00002851B /* SearchViewController.h */,
+				4334963F11BBC1A00002851B /* SearchViewController.m */,
+				4334966C11BBCEBE0002851B /* SettingViewController.h */,
+				4334966D11BBCEBE0002851B /* SettingViewController.m */,
+				1D3623240D0F684500981E51 /* TabBarSampleAppDelegate.h */,
+				1D3623250D0F684500981E51 /* TabBarSampleAppDelegate.m */,
+			);
+			path = Classes;
+			sourceTree = "<group>";
+		};
+		19C28FACFE9D520D11CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				1D6058910D05DD3D006BFB54 /* TabBarSample.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		29B97314FDCFA39411CA2CEA /* TabBarSample */ = {
+			isa = PBXGroup;
+			children = (
+				080E96DDFE201D6D7F000001 /* Classes */,
+				29B97315FDCFA39411CA2CEA /* Other Sources */,
+				29B97317FDCFA39411CA2CEA /* Resources */,
+				29B97323FDCFA39411CA2CEA /* Frameworks */,
+				19C28FACFE9D520D11CA2CBB /* Products */,
+			);
+			name = TabBarSample;
+			sourceTree = "<group>";
+		};
+		29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				28A0AB4B0D9B1048005BE974 /* TabBarSample_Prefix.pch */,
+				29B97316FDCFA39411CA2CEA /* main.m */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+		29B97317FDCFA39411CA2CEA /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				4334966A11BBCE4C0002851B /* tab_setting.png */,
+				433495F111BBBE270002851B /* tab_list.png */,
+				433495EB11BBBD590002851B /* tab_star.png */,
+				433495EF11BBBE090002851B /* tab_recent.png */,
+				433495E911BBBD4B0002851B /* tab_search.png */,
+				433495ED11BBBD790002851B /* tab_contact.png */,
+				43640B3C11BC0DFC008B6A4C /* Icon.png */,
+				8D1107310486CEB800E47090 /* TabBarSample-Info.plist */,
+			);
+			path = Resources;
+			sourceTree = "<group>";
+		};
+		29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
+				1D30AB110D05D00D00671497 /* Foundation.framework */,
+				288765070DF74369002DB57D /* CoreGraphics.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		1D6058900D05DD3D006BFB54 /* TabBarSample */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "TabBarSample" */;
+			buildPhases = (
+				1D60588D0D05DD3D006BFB54 /* Resources */,
+				1D60588E0D05DD3D006BFB54 /* Sources */,
+				1D60588F0D05DD3D006BFB54 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = TabBarSample;
+			productName = TabBarSample;
+			productReference = 1D6058910D05DD3D006BFB54 /* TabBarSample.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		29B97313FDCFA39411CA2CEA /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "TabBarSample" */;
+			compatibilityVersion = "Xcode 3.1";
+			hasScannedForEncodings = 1;
+			mainGroup = 29B97314FDCFA39411CA2CEA /* TabBarSample */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				1D6058900D05DD3D006BFB54 /* TabBarSample */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		1D60588D0D05DD3D006BFB54 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				433495EA11BBBD4B0002851B /* tab_search.png in Resources */,
+				433495EC11BBBD590002851B /* tab_star.png in Resources */,
+				433495EE11BBBD790002851B /* tab_contact.png in Resources */,
+				433495F011BBBE090002851B /* tab_recent.png in Resources */,
+				433495F211BBBE270002851B /* tab_list.png in Resources */,
+				4334966B11BBCE4C0002851B /* tab_setting.png in Resources */,
+				43640B3D11BC0DFC008B6A4C /* Icon.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		1D60588E0D05DD3D006BFB54 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1D60589B0D05DD56006BFB54 /* main.m in Sources */,
+				1D3623260D0F684500981E51 /* TabBarSampleAppDelegate.m in Sources */,
+				28216C970DB411BC00E5133A /* ListViewController.m in Sources */,
+				433495F811BBBFC30002851B /* StarViewController.m in Sources */,
+				433495F911BBBFC30002851B /* RecentViewController.m in Sources */,
+				4334964111BBC1A00002851B /* SearchViewController.m in Sources */,
+				4334966E11BBCEBE0002851B /* SettingViewController.m in Sources */,
+				433496B111BBD5FB0002851B /* TableViewController.m in Sources */,
+				436409CB11BBF06C008B6A4C /* DataManager.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1D6058940D05DD3E006BFB54 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = TabBarSample_Prefix.pch;
+				INFOPLIST_FILE = "TabBarSample-Info.plist";
+				PRODUCT_NAME = TabBarSample;
+			};
+			name = Debug;
+		};
+		1D6058950D05DD3E006BFB54 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = YES;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = TabBarSample_Prefix.pch;
+				INFOPLIST_FILE = "TabBarSample-Info.plist";
+				PRODUCT_NAME = TabBarSample;
+			};
+			name = Release;
+		};
+		C01FCF4F08A954540054247B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_PREPROCESSOR_DEFINITIONS = DEBUGON;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+				SDKROOT = iphoneos3.0;
+			};
+			name = Debug;
+		};
+		C01FCF5008A954540054247B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				PREBINDING = NO;
+				SDKROOT = iphoneos3.0;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "TabBarSample" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1D6058940D05DD3E006BFB54 /* Debug */,
+				1D6058950D05DD3E006BFB54 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C01FCF4E08A954540054247B /* Build configuration list for PBXProject "TabBarSample" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C01FCF4F08A954540054247B /* Debug */,
+				C01FCF5008A954540054247B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
Index: /gs2-extensions/iOs-3.x/trunk/Greenstone2_Prefix.pch
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Greenstone2_Prefix.pch	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Greenstone2_Prefix.pch	(revision 22603)
@@ -0,0 +1,16 @@
+//
+// Prefix header for all source files of the 'Greenstone2' project
+//
+
+#ifdef __OBJC__
+    #import <Foundation/Foundation.h>
+    #import <UIKit/UIKit.h>
+#endif
+
+#ifdef DEBUGON
+#define DEBUGLOG(x) x
+#define LogMethod()	NSLog(@"%@ %@", self, NSStringFromSelector(_cmd))
+#else
+#define DEBUGLOG(x)
+#define LogMethod()	
+#endif
Index: /gs2-extensions/iOs-3.x/trunk/Makefile
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/Makefile	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/Makefile	(revision 22603)
@@ -0,0 +1,207 @@
+# Makefile for iPhone Application for iPhone gcc compiler (SDK Headers)
+# (Based on TabBarSample)
+#
+# Modified to work as an extension within:
+#  <greensotne_home>/ext/iOS-3.x directory
+
+PROJECTNAME=Greenstone2
+APPFOLDER=$(PROJECTNAME).app
+MINIMUMVERSION:=3.2
+
+SDK=/var/toolchain/sys32
+
+CC=arm-apple-darwin9-gcc
+CXX=arm-apple-darwin9-g++
+LD=$(CXX)
+
+
+LDFLAGS = -arch arm -lobjc
+LDFLAGS += -framework UIKit 
+LDFLAGS += -framework CoreGraphics
+LDFLAGS += -framework Foundation 
+//LDFLAGS += -framework AVFoundation
+//LDFLAGS += -framework AddressBook
+//LDFLAGS += -framework AddressBookUI
+//LDFLAGS += -framework AudioToolbox
+//LDFLAGS += -framework AudioUnit
+//LDFLAGS += -framework CFNetwork
+//LDFLAGS += -framework CoreAudio
+//LDFLAGS += -framework CoreData
+//LDFLAGS += -framework CoreFoundation 
+LDFLAGS += -framework CoreGraphics
+//LDFLAGS += -framework GraphicsServices
+//LDFLAGS += -framework CoreLocation
+//LDFLAGS += -framework ExternalAccessory
+//LDFLAGS += -framework GameKit
+//LDFLAGS += -framework IOKit
+//LDFLAGS += -framework MapKit
+//LDFLAGS += -framework MediaPlayer
+//LDFLAGS += -framework MessageUI
+//LDFLAGS += -framework MobileCoreServices
+//LDFLAGS += -framework OpenAL
+//LDFLAGS += -framework OpenGLES
+//LDFLAGS += -framework QuartzCore
+//LDFLAGS += -framework Security
+//LDFLAGS += -framework StoreKit
+//LDFLAGS += -framework System
+//LDFLAGS += -framework SystemConfiguration
+//LDFLAGS += -framework CoreSurface
+//LDFLAGS += -framework GraphicsServices
+//LDFLAGS += -framework Celestial
+//LDFLAGS += -framework WebCore
+//LDFLAGS += -framework WebKit
+//LDFLAGS += -framework SpringBoardUI
+//LDFLAGS += -framework TelephonyUI
+//LDFLAGS += -framework JavaScriptCore
+//LDFLAGS += -framework PhotoLibrary
+
+LDFLAGS += -L"$(SDK)/usr/lib"
+LDFLAGS += -F"$(SDK)/System/Library/Frameworks"
+LDFLAGS += -F"$(SDK)/System/Library/PrivateFrameworks"
+LDFLAGS += -bind_at_load
+LDFLAGS += -multiply_defined suppress
+LDFLAGS += -march=armv6
+LDFLAGS += -mcpu=arm1176jzf-s 
+LDFLAGS += -mmacosx-version-min=10.5
+//LDFLAGS += -dynamiclib
+
+BUILDDIR=./build/$(MINIMUMVERSION)
+SRCDIR=./Classes
+RESDIR=./Resources
+
+OBJS=$(patsubst %.m,%.o,$(wildcard $(SRCDIR)/*.m))
+OBJS+=$(patsubst %.c,%.o,$(wildcard $(SRCDIR)/*.c))
+OBJS+=$(patsubst %.mm,%.o,$(wildcard $(SRCDIR)/*.mm))
+OBJS+=$(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp))
+OBJS+=$(patsubst %.mm,%.o,$(wildcard ./*.mm))
+
+PCH=$(wildcard *.pch)
+RESOURCES=$(wildcard ./*.png)
+RESOURCES+=$(wildcard $(RESDIR)/*)
+NIBS=$(patsubst %.xib,%.nib,$(wildcard Xib/*.xib))
+
+CFLAGS += -g -DDEBUG -D_DEBUG
+CFLAGS += -I"$(SDK)/usr/include" 
+CFLAGS += -std=gnu99
+CFLAGS += -Diphoneos_version_min=$(MINIMUMVERSION)
+CFLAGS += -Wno-attributes -Wno-trigraphs -Wreturn-type -Wunused-variable
+CFLAGS += $(addprefix -I,$(SRCDIR))
+
+CXXFLAGS += -g -DDEBUG -D_DEBUG
+CXXFLAGS += -I"$(SDK)/usr/include" 
+CXXFLAGS += -Diphoneos_version_min=$(MINIMUMVERSION)
+CXXFLAGS += -Wno-attributes -Wno-trigraphs -Wreturn-type -Wunused-variable
+CXXFLAGS += $(addprefix -I,$(SRCDIR))
+CXXFLAGS += -I"$(SDK)/usr/include/c++/4.2.1" 
+CXXFLAGS += -I"$(SDK)/usr/include/c++/4.2.1/armv7-apple-darwin9" 
+
+
+#--
+# Now for Greenstone specific flags
+#--
+
+GSDL_DIR = ../..
+GDBM_DIR = $(GSDL_DIR)/common-src/packages/gdbm
+
+INDEXERS_DIR  = $(GSDL_DIR)/common-src/indexers
+PACKAGES_DIR  = $(GSDL_DIR)/common-src/packages
+COMMONLIB_DIR = $(GSDL_DIR)/common-src/src/lib
+COLSERVR_DIR  = $(GSDL_DIR)/runtime-src/src/colservr
+RECPTION_DIR  = $(GSDL_DIR)/runtime-src/src/recpt
+PROTOCOL_DIR  = $(GSDL_DIR)/runtime-src/src/protocol
+
+ENABLE_ACCENTFOLD = 1
+ifeq ($(ENABLE_ACCENTFOLD), 1)
+ACCENTFOLD_LIBS = $(INDEXERS_DIR)/packages/unac/libunac.a 
+else
+ACCENTFOLD_LIBS = 
+endif
+
+
+GSDL_CFLAGS = -I$(GDBM_DIR)/include \
+	 -I$(INDEXERS_DIR)/mgpp/text \
+	 -I$(COMMONLIB_DIR) \
+         -I$(PROTOCOL_DIR) -I$(COLSERVR_DIR) -I$(RECPTION_DIR)
+
+CFLAGS   += $(GSDL_CFLAGS)
+CXXFLAGS += $(GSDL_CFLAGS)
+
+LDFLAGS  +=  -L$(GDBM_DIR)/lib -lgdbm \
+	  -L$(INDEXERS_DIR)/mg/src/text -lmgtext \
+	  -L$(INDEXERS_DIR)/mg/lib      -lmglib \
+	  -L$(INDEXERS_DIR)/mgpp/text   -lmgpptext \
+	  -L$(INDEXERS_DIR)/mgpp/lib    -lmgpplib \
+          $(COMMONLIB_DIR)/gsdllib.a \
+          $(PROTOCOL_DIR)/gsdlprotocol.a \
+          $(COLSERVR_DIR)/gsdlcolservr.a \
+          $(RECPTION_DIR)/gsdlrecpt.a \
+	  $(ACCENTFOLD_LIBS) \
+          $(PACKAGES_DIR)/iconv/lib/libiconv.a \
+	  -L$(PACKAGES_DIR)/expat/lib -lexpat \
+          -L/usr/local/lib -lgcc_eh
+
+# =======
+
+
+
+all:	$(PROJECTNAME)
+
+$(PROJECTNAME):	$(OBJS) Makefile
+	$(LD) -o $@ $(filter %.o,$^) $(LDFLAGS)
+
+#	$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@ 
+
+
+%.o:	%.m %.h $(PCH) $(filter-out $(patsubst %.o,%.h,$(OBJS)), $(wildcard $(SRCDIR)/*.h))
+	$(CC) --include $(PCH) -c $(CFLAGS) $< -o $@
+
+%.o:	%.m
+	$(CC) --include $(PCH) -c $(CFLAGS) $< -o $@
+
+%.o:	%.c %.h $(PCH)
+	$(CC) --include $(PCH) -c $(CFLAGS) $< -o $@
+
+%.o:	%.mm %.h $(PCH) $(filter-out $(patsubst %.o,%.h,$(OBJS)), $(wildcard $(SRCDIR)/*.h))
+	$(CXX) --include $(PCH) -c $(CXXFLAGS) $< -o $@
+
+%.o:	%.mm
+	$(CXX) --include $(PCH) -c $(CXXFLAGS) $< -o $@
+
+%.o:	%.cpp %.h $(PCH)
+	$(CXX) --include $(PCH) -c $(CXXFLAGS) $< -o $@
+
+dist:	$(PROJECTNAME) Makefile $(PROJECTNAME)-Info.plist $(RESOURCES)
+	@rm -rf $(BUILDDIR)
+	@mkdir -p $(BUILDDIR)/$(APPFOLDER)
+ifneq ($(RESOURCES),)
+	@-cp -r $(RESOURCES) $(BUILDDIR)/$(APPFOLDER)
+	@-$(foreach DIR, .svn .DS_Store .git* , find $(BUILDDIR)/$(APPFOLDER) -name '$(DIR)' -prune -exec rm -rfv {} \;;)
+endif
+	@cp $(PROJECTNAME)-Info.plist $(BUILDDIR)/$(APPFOLDER)/Info.plist
+	@./plutil -key CFBundleExecutable -value $(PROJECTNAME) $(BUILDDIR)/$(APPFOLDER)/Info.plist 
+	@./plutil -key CFBundleDisplayName -value $(PROJECTNAME) $(BUILDDIR)/$(APPFOLDER)/Info.plist 
+	@./plutil -key CFBundleName -value $(PROJECTNAME) $(BUILDDIR)/$(APPFOLDER)/Info.plist 
+	@./plutil -key CFBundleIdentifier -value com.yourcompany.iphone.$(PROJECTNAME) $(BUILDDIR)/$(APPFOLDER)/Info.plist
+	@./plutil -UIDeviceFamily -array $(BUILDDIR)/$(APPFOLDER)/Info.plist 
+	@./plutil -UIDeviceFamily -arrayadd -string 1 $(BUILDDIR)/$(APPFOLDER)/Info.plist 
+	@./plutil -UIDeviceFamily -arrayadd -string 2 $(BUILDDIR)/$(APPFOLDER)/Info.plist 
+	@./plutil -key NSMainNibFile -remove $(BUILDDIR)/$(APPFOLDER)/Info.plist 
+	@echo "APPL????" > $(BUILDDIR)/$(APPFOLDER)/PkgInfo
+	ldid -S $(PROJECTNAME)
+	@mv $(PROJECTNAME) $(BUILDDIR)/$(APPFOLDER)/
+
+install: dist
+	./appinstall $(BUILDDIR)/$(APPFOLDER)
+
+distclean:
+	@rm -rf $(BUILDDIR)
+
+clean:
+	@rm -f $(OBJS)
+	@rm -rf $(BUILDDIR)
+	@rm -f $(PROJECTNAME)
+
+.PHONY: all dist install distclean clean
+
+
+
Index: /gs2-extensions/iOs-3.x/trunk/gsdlsite.cfg
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/gsdlsite.cfg	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/gsdlsite.cfg	(revision 22603)
@@ -0,0 +1,59 @@
+# this file should be placed in the same directory as your library
+# executable file. it defines parameters that are particular to a
+# given site, and therefore should be edited to suit your site.
+
+# points to the GSDLHOME directory
+# This must be set, and must point to the top level Greenstone directory
+# (usually gsdl or Greenstone)
+gsdlhome    /var/code/gs2-runtime-svn 
+
+# this is the http address of GSDLHOME
+# if your webserver's DocumentRoot is set to $GSDLHOME
+# then httpprefix can be commented out
+httpprefix  /greenstone
+
+# this is the http address of the Greenstone web directory (which contains
+# images, style etc)
+# if your web directory is a top level folder inside $GSDLHOME, then this
+# can remain commented out, and will default to httpprefix/web
+#httpweb     /greenstone/web
+
+# this should contain the http address of the library.cgi script. This 
+# is not needed if the http server sets the environment variable 
+# SCRIPT_NAME
+# Generally this is not needed with Apache
+#gwcgi       /greenstone/cgi-bin/library.cgi
+
+# maxrequests is the most requests a fastcgi process
+# will serve before it exits. This can be set to a
+# low figure (like 1) while debugging and then set
+# to a high figure (like 10000) when everything is
+# working well.
+# Only applies if you are using fastcgi
+maxrequests 10000
+
+# Remote Greenstone Options (for server side)
+
+# If Perl is not already on your PATH, set the following to the 
+# full path of the perl bin directory (Perl's parent folder) 
+# and it will be prepended to the PATH.
+#perlpath /usr/bin
+
+# Options for FLI
+
+# If using Greenstone's GLIServer to run the Fedora Librarian
+# Interface (FLI), then you need to set fedora version and fedora home
+# variables, either below, or as environment variables. 
+# FEDORA_VERSION is the major version number of Fedora and  
+# FEDORA_HOME is the full path to your Fedora installation.
+# Setting fedorahome and fedoraversion here will over-ride the
+# FEDORA_HOME and FEDORA_VERSION environment variables.
+#fedorahome /full/path/to/fedora
+#fedoraversion 3
+
+# If using Greenstone's GLIServer to run the Fedora Librarian
+# Interface (FLI), then you need to set the full path to Java either as below 
+# or as the JAVA_HOME environment variable.
+# Setting javahome here will over-ride the JAVA_HOME environment variable.
+#javahome /full/path/to/j2sdk1.4-or-higher
+
Index: /gs2-extensions/iOs-3.x/trunk/loading.html
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/loading.html	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/loading.html	(revision 22603)
@@ -0,0 +1,8 @@
+<html>
+  <head>
+  </head>
+  <body>
+    <p><br><br>
+    <p>Loading ...
+  </body>
+</html>
Index: /gs2-extensions/iOs-3.x/trunk/main.mm
===================================================================
--- /gs2-extensions/iOs-3.x/trunk/main.mm	(revision 22603)
+++ /gs2-extensions/iOs-3.x/trunk/main.mm	(revision 22603)
@@ -0,0 +1,13 @@
+
+#import "GreenstoneApplication.h"
+
+int main(int argc, char **argv)
+{
+    NSAutoreleasePool* autoreleasePool = [[NSAutoreleasePool alloc] init];
+    int retVal = UIApplicationMain(argc, argv, 
+			  	   @"GreenstoneApplication", @"GreenstoneApplication");
+
+    [autoreleasePool release];
+    return retVal;
+
+}
