Index: MpdlXmlTextServer.py
===================================================================
--- MpdlXmlTextServer.py	(revision 506)
+++ MpdlXmlTextServer.py	(revision 508)
@@ -127,4 +127,5 @@
     def getTextPage(self, mode="text", pn=1, docinfo=None, pageinfo=None):
         """returns single page from fulltext"""
+        
         logging.debug("getTextPage mode=%s, pn=%s"%(mode,pn))
         # check for cached text -- but ideally this shouldn't be called twice
@@ -139,27 +140,41 @@
             
         # stuff for constructing full urls
-        url = docinfo['url']
-        urlmode = docinfo['mode']
-        sn = pageinfo.get('sn', None)
-        highlightQuery = pageinfo.get('highlightQuery', None)
-        tocMode = pageinfo.get('tocMode', None)
-        tocPN = pageinfo.get('tocPN',None)
         characterNormalization = pageinfo.get('characterNormalization', None)
-        
+        moreTextParam = ''
         selfurl = docinfo['viewerUrl']
         
-        if mode == "dict" or mode == "text_dict":
+        if not mode:
+            # default is dict
+            mode = 'text'
+
+        modes = mode.split(',')
+        # check for multiple layers
+        if len(modes) > 1:
+            logging.debug("getTextPage: more than one mode=%s"%mode)
+            
+        # search mode
+        if 'search' in modes:
+            # add highlighting
+            highlightQuery = pageinfo.get('highlightQuery', None)
+            sn = pageinfo.get('sn', None)
+            if highlightQuery and sn:
+                moreTextParam +="&highlightQuery=%s&sn=%s"%(urllib.quote(highlightQuery),sn)
+                
+            # remove mode
+            modes.remove('search')
+                            
+        # other modes don't combine
+        if 'dict' in modes:
             # dict is called textPollux in the backend
-            textmode = "textPollux"
-        elif not mode:
-            # default is text
-            mode = "text"
-            textmode = "text"
+            textmode = 'textPollux'
+        elif len(modes) == 0:
+            # text is default mode
+            textmode = 'text'
         else:
-            textmode = mode
+            # just take first mode
+            textmode = modes[0]
         
         textParam = "document=%s&mode=%s&pn=%s&characterNormalization=%s"%(docpath,textmode,pn,characterNormalization)
-        if highlightQuery:
-            textParam +="&highlightQuery=%s&sn=%s"%(urllib.quote(highlightQuery),sn)           
+        textParam += moreTextParam
         
         # fetch the page
@@ -181,5 +196,5 @@
         
         # plain text mode
-        if mode == "text":
+        if textmode == "text":
             # get full url assuming documentViewer is parent
             selfurl = self.getLink()
@@ -195,5 +210,5 @@
             
         # text-with-links mode
-        elif mode == "dict":
+        elif textmode == "textPollux":
             if pagediv is not None:
                 viewerurl = docinfo['viewerUrl']
@@ -227,15 +242,15 @@
             
         # xml mode
-        elif mode == "xml":
+        elif textmode == "xml":
             if pagediv is not None:
                 return serialize(pagediv)
             
         # pureXml mode
-        elif mode == "pureXml":
+        elif textmode == "pureXml":
             if pagediv is not None:
                 return serialize(pagediv)
                   
         # gis mode
-        elif mode == "gis":
+        elif textmode == "gis":
             if pagediv is not None:
                 # check all a-tags
@@ -255,4 +270,106 @@
         return None
     
+
+    def getSearchResults(self, mode, query=None, docinfo=None):
+        """loads list of search results and stores XML in docinfo"""
+        logging.debug("getSearchResults mode=%s query=%s"%(mode, query))
+        if mode == "none":
+            return docinfo
+              
+        if 'resultSize_%s_%s'%(mode,query) in docinfo:
+            # cached result
+            return docinfo
+        
+        docpath = docinfo['textURLPath']
+        # we need to set a result set size
+        pagesize = 1000
+        pn = 1
+        # fetch full results
+        params = {'document': docpath,
+                  'mode': 'text',
+                  'queryType': mode,
+                  'query': query,
+                  'queryResultPageSize': 1000,
+                  'queryResultPN': 1}
+        pagexml = self.getServerData("doc-query.xql",urllib.urlencode(params))
+        #pagexml = self.getServerData("doc-query.xql","document=%s&mode=%s&queryType=%s&query=%s&queryResultPageSize=%s&queryResultPN=%s&s=%s&viewMode=%s&characterNormalization=%s&highlightElementPos=%s&highlightElement=%s&highlightQuery=%s"%(docpath, 'text', queryType, urllib.quote(query), pagesize, pn, s, viewMode,characterNormalization, highlightElementPos, highlightElement, urllib.quote(highlightQuery)))
+        dom = ET.fromstring(pagexml)
+        # page content is in <div class="queryResultPage">
+        pagediv = None
+        # ElementTree 1.2 in Python 2.6 can't do div[@class='queryResultPage']
+        alldivs = dom.findall("div")
+        for div in alldivs:
+            dc = div.get('class')
+            # page content div
+            if dc == 'queryResultPage':
+                pagediv = div
+                
+            elif dc == 'queryResultHits':
+                docinfo['resultSize_%s_%s'%(mode,query)] = getInt(div.text)
+
+        if pagediv:
+            # store XML in docinfo
+            docinfo['resultXML_%s_%s'%(mode,query)] = ET.tostring(pagediv, 'UTF-8')
+
+        logging.debug("getSearchResults: pagediv=%s"%pagediv)
+        return docinfo
+    
+
+    def getResultsPage(self, mode="text", query=None, pn=None, start=None, size=None, pageinfo=None, docinfo=None):
+        """returns single page from the table of contents"""
+        logging.debug("getResultsPage mode=%s, pn=%s"%(mode,pn))
+        # check for cached TOC
+        #TODO: cache only one search
+        if not docinfo.has_key('resultXML_%s_%s'%(mode,query)):
+            self.getSearchResults(mode=mode, query=query, docinfo=docinfo)
+            
+        resultxml = docinfo.get('resultXML_%s_%s'%(mode,query), None)
+        if not resultxml:
+            logging.error("getResultPage: unable to find resultXML")
+            return "Error: no result!"
+        
+        if size is None:
+            size = pageinfo.get('searchResultPageSize', 20)
+            
+        if start is None:
+            start = (pn - 1) * size
+
+        fullresult = ET.fromstring(resultxml)
+        
+        if fullresult:
+            # paginate
+            first = start
+            len = size
+            del fullresult[:first]
+            del fullresult[len:]
+            tocdivs = fullresult
+            
+            # check all a-tags
+            links = tocdivs.findall(".//a")
+            for l in links:
+                href = l.get('href')
+                if href:
+                    # take pn from href
+                    m = re.match(r'page-fragment\.xql.*pn=(\d+)', href)
+                    if m is not None:
+                        # and create new url (assuming parent is documentViewer)
+                        #TODO: add highlighting params
+                        url = self.getLink('pn', m.group(1))
+                        l.set('href', url)
+                    else:
+                        logging.warning("getResultPage: Problem with link=%s"%href)
+                        
+            # fix two-divs-per-row with containing div
+#            newtoc = ET.Element('div', {'class':'queryResultPage'})
+#            for (d1,d2) in zip(tocdivs[::2],tocdivs[1::2]):
+#                e = ET.Element('div',{'class':'tocline'})
+#                e.append(d1)
+#                e.append(d2)
+#                newtoc.append(e)
+                
+            return serialize(tocdivs)
+        
+        return "ERROR: no results!"
+
 
     def getToc(self, mode="text", docinfo=None):
