# Copyright 2006 Mounir Errami. m.errami@gmail.com
# This file is part of Bibus, a bibliographic database that can
# work together with OpenOffice.org to generate bibliographic indexes.
#
# Bibus is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Bibus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bibus; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

import mswCONST
import mswUtils
import BIB
import bibOOo
from bibOOo import CONST
import win32com.client
import win32com.gen_py
import pywintypes
from pywintypes import * 
import time,sys
#Styles
s_regular = bibOOo.CONST.bibOOo_regular #= 0
s_italic = bibOOo.CONST.bibOOo_italic # = 1
s_bold= bibOOo.CONST.bibOOo_bold #= 2
s_caps= bibOOo.CONST.bibOOo_caps #= 4
s_smallcaps= bibOOo.CONST.bibOOo_smallcaps #= 8
s_underline= bibOOo.CONST.bibOOo_underline #= 16
#Position
p_normal = bibOOo.CONST.bibOOo_normal #= 0
p_superscript = bibOOo.CONST.bibOOo_exposant# = 1
p_subscript = bibOOo.CONST.bibOOo_indice #= -1

#citation numbering, index to read in BIB.FORMAT_DICO['citation']['numbering']
n_sort =0 #=>BIB.FORMAT_DICO['citation']['numbering'][0]=True,Flase
n_fuse =1 #=>BIB.FORMAT_DICO['citation']['numbering'][1]=True,Flase
n_userange=2 #=>BIB.FORMAT_DICO['citation']['numbering'][2]=True,Flase
n_fusesep=3 #=>BIB.FORMAT_DICO['citation']['numbering'][3]=';' (it is an example)
n_rangesep=4 #=>BIB.FORMAT_DICO['citation']['numbering'][-]=';' (it is an example)

class mswFormatter:
	"""Class designed to read Style files and grab the information needed
	to apply to msword doc."""
	def __init__(self,Style,doc=None):
		self.doc = doc
		self.bibStyle = Style
		self.base_style_list = Style['citation']['base_style']
		self.nblist =Style['citation']['numbering']
		self.styleDic=self.__getStyleAsDict(self.base_style_list[0]) #this style for citations
		
####This signficantly speeds the bibliographic index formatting
		self.rangePositionList=[]
		self.pubTypeList = []
###Stuff for citation
		self.etalStyle = 0
		self.isShortToEtal=self.__setShortenedToEtAl()
		self.etalText=self.__setEtalText()
		
###Next functions are designed to interpret BIB.FORMAT_DICO['index']
	def __getIndexValue(self, key):
		"""Get values from BIB.FORMAT_DICO['index']. Key is checked. If invalid, then the value None is returned"""
		return self.bibStyle['index'][key]

	def getSortingKeys(self):
		if self.isSortByPosition():
			return None
		"""return a tuple of keys and ascending (=true) or descending (=false)"""
		tupleKeys =  self.__getIndexValue("SortKeys")
		newTuple = []
		for k in tupleKeys:
			mList = []
			mList.append(BIB.BIB_FIELDS[k[0]+1])
			mList.append(k[1])
			#mList[0]=BIB.BIB_FIELDS[k[0]]
			newTuple.append(mList)
		return newTuple
	
	def isNumberEntries(self):
		""" get the IsNumber entry from BIB.FORMAT_DICO['index']['IsNumberEntries']"""
		return self.__getIndexValue("IsNumberEntries")
	
	def getBiblioTitle(self):
		""" get the IsNumberEntry from BIB.FORMAT_DICO['index']['Title']"""
		return self.__getIndexValue('Title')
	
	def isSortByPosition(self):
		""" get the IsNumberEntry from BIB.FORMAT_DICO['index']['IsSortByPosition']"""
		return self.__getIndexValue('IsSortByPosition')
		
	def getBracket(self):
		""" get the IsNumberEntry from BIB.FORMAT_DICO['index']['IsSortByPosition']"""
		brackets=self.__getIndexValue('Bracket')
		if brackets==None:
			return '',''
		return brackets[0],brackets[1]
	
	def getSortAlgorithm(self):
		""" get the IsNumberEntry from BIB.FORMAT_DICO['index']['IsSortByPosition']
		This parameter is currently not supported for msdoc formatting
		"""
		return self.__getIndexValue('SortAlgorithm')

###Next functions are designed to interpret BIB.FORMAT_DICO['ordering']
	def getOrderAndFormatAndSeparator(self,refType):
		"""get an ordered list of field to insert in bibliography"""
		#TODO Change the name to getOrderAndFormatAndSeparator
		l_fieldOrder = []
		l_fieldSeparator = []
		l_fieldFormat = []
		l_fieldTabSize = []
		Style= self.bibStyle
		# Next constant  replaceIdentifier is to replace the identifier field that is misleading
		# I will remove this field if index is not numbered
		# I Will change it if index is number to textPosition
		replaceIdentifier = False
		for ml in Style['ordering'][refType]:
			if ml[0]=='field' and ml[1]=="Identifier":
				if self.isNumberEntries()==False:
					#continue
					"add anyway"
				else:
					replaceIdentifier = True
			if ml[0]=='field':
				l_fieldOrder.append(ml[1])
			elif ml[0]=='text':
				l_fieldOrder.append(ml[1])
				l_fieldSeparator.append(ml[1])
			elif ml[0]=='tab':
				l_fieldOrder.append('\t')
				l_fieldSeparator.append('\t')
				l_fieldFormat.append(ml[1])
				continue
			l_fieldFormat.append(ml[2])
		if replaceIdentifier==True:
			iToRep =l_fieldOrder.index("Identifier")
			l_fieldOrder[iToRep] = mswCONST.me_MSWBIBUS_BIBLIO_IDENTIFIER
		#print "l_fieldOrder",l_fieldOrder
		return (l_fieldOrder,l_fieldFormat,l_fieldSeparator)

	def getFormattedBiblioString(self,biblioList,mswdoc_instance):		
		"""This function formats the biblio according to the Style chosen by the user"""
		#print "From formatter"
		biblioString="\n"+self.getBiblioTitle()+"\n"
		entryNumber = 1
		biblioList= self.__getSortedList(biblioList)
		if self.isNumberEntries()==True and self.isSortByPosition()== False:
			#print " updateHere"
			self.__updateCitationTextNumSortedByAlpha(biblioList,mswdoc_instance)
		self.pubTypeList = []
		#############
		rangePositionList = []
		rangeStart = len(biblioString)
		# Will contain (
		#		( (start,stop), (start,stop), (start,strop)),
		#		( (start,stop), (start,stop), (start,strop)),
		#		( (start,stop), (start,stop), (start,strop)),
		#	)
		# Each line is a bibliographic entry
		# Each (start,stop) are character positions that define a range in the document. The range represent a field (author, title, separators etc...)
		#############
		for entry in biblioList:
			rangePositionEntryList=[] # A list ((start,stop),(start,stop),(start,stop)...)
			biblioEntry = ""
			listFieldOrder=[]
			listFieldFormat=[]
			listFieldSeparator=[]
			BibliographicType = mswUtils.getXmlValueFromString("BibliographicType",entry)
			#print "bibType =", BibliographicType
			if BibliographicType ==None:
				continue
			self.pubTypeList.append(BibliographicType)
			listFieldOrder, listFieldFormat,listFieldSeparator = self.getOrderAndFormatAndSeparator(BibliographicType)
			rangeEntryStart = rangeStart
			for field in listFieldOrder:
				rangePositionEntry = [] # A list (start,stop)
				#print "checking for field = >", field, "<"
				#1) We check if it is a separator field
				if listFieldSeparator.count(field)>0:
					biblioEntry=biblioEntry+field
					start = rangeEntryStart 
					stop = start + len(field)
					rangeEntryStart = stop
					rangePositionEntry.append(start)
					rangePositionEntry.append(stop)
					#print  "Found in sep"
				#2) We check if it is the identifier field, which here is the position in text 1,2,3...
				elif field == mswCONST.me_MSWBIBUS_BIBLIO_IDENTIFIER :
					strEntryNumber = str(entryNumber)
					biblioEntry = biblioEntry+strEntryNumber
					start = rangeEntryStart 
					stop = start + len(strEntryNumber)
					rangeEntryStart = stop
					rangePositionEntry.append(start)
					rangePositionEntry.append(stop)
					
				else:
					fToAdd = mswUtils.getXmlValueFromString(field,entry)
					if fToAdd !=None:
						biblioEntry=biblioEntry+fToAdd
						start = rangeEntryStart 
						stop = start + len(fToAdd)
						rangeEntryStart = stop
						#print "fToAdd = ",fToAdd," len = ", len(fToAdd)
					else:
						start = rangeEntryStart
						stop = rangeEntryStart
					rangePositionEntry.append(start)
					rangePositionEntry.append(stop)
				rangePositionEntryList.append(rangePositionEntry)
			#print "biblioEntry=",biblioEntry
			biblioString=biblioString+biblioEntry+"\n"
			rangeStart=len(biblioString)
			rangePositionList.append(rangePositionEntryList)
			entryNumber=entryNumber+1
		self.rangePositionList=rangePositionList
		return biblioString
	
	def __getSortedList(self, biblioList):
		"""Here sorts a bibliographic list according to an infinite number of keys
		However the ascending or descengind paramater is taken from the first key and applied to all others"""
		#TODO: be able to take into account sorting asc., desc. for each sorting key
		if self.isSortByPosition():
			return biblioList
		#build a list of Ids:
		entryIds = []
		sortingKeys = self.getSortingKeys()
		#print "sortingKeys=",sortingKeys
		for entry in biblioList:
			entryId =[]
			for sKey in sortingKeys:
				entryId.append(mswUtils.getXmlValueFromString(sKey[0],entry)) 
			entryId.append(entry)
			if entryId ==None:
				continue
			else:
				entryIds.append(entryId)
		#Only support acending or descending for the first key and applies it to all other
		entryIds.sort()
		if sortingKeys !=None:
			if sortingKeys[0]!=None:
				if sortingKeys[0][1]==False:
					entryIds.reverse()
		#print "entryIds=",entryIds
		newBiblioList = []
		for entry in entryIds:
			#print entryIds
			newBiblioList.append(entry[-1])
		#print "newBiblioList=",newBiblioList
		return newBiblioList
		
	def __updateCitationTextNumSortedByAlpha(self,sortedBiblioList,mswdoc_instance):
		idList = []
		for entry in sortedBiblioList:
			idList.append(mswUtils.getXmlValueFromString("Identifier",entry))
		activeDoc = mswdoc_instance.application.ActiveDocument
		for field in activeDoc.Fields:
			fId = mswUtils.getXmlValueFromString("Identifier",field.Code.Text)
			newRes = -1
			oB,cB= self.getBracket()
			try:
				newRes = oB+ unicode(idList.index(fId) +1) +cB
				field.Result.Text = newRes
			except:
				print "No value for fId"
				
	def __getStyleAsDict(self, styleNum):
		"""get the style as a dictionnary"""
		#print "styleNum =",styleNum
		styleDic = {'underline':False,'smallcaps':False,'caps':False,'bold':False,'italic':False,'regular':True}
		maxStyle = s_underline+s_smallcaps+s_caps+s_italic+s_bold+s_regular
		if styleNum>=maxStyle:
			return styleDic
		if styleNum ==-1 or styleNum==0 or styleNum ==None or styleNum=='' or styleNum>=maxStyle:
			return styleDic
		if styleNum>=s_underline:
			styleDic['underline']=True
			styleNum=styleNum-s_underline
		if styleNum>=s_smallcaps:
			styleDic['smallcaps']=True
			styleDic['caps']=False
			styleNum=styleNum-s_smallcaps
		if styleNum>=s_caps:
			styleDic['caps']=True
			styleDic['smallcaps']=False
			styleNum=styleNum-s_caps
		if styleNum>=s_bold:
			styleDic['bold']=True
			styleDic['regular']=False
			styleNum=styleNum-s_bold
		if styleNum>=s_italic:
			styleDic['italic']=True
			styleDic['regular']=False
			styleNum=styleNum-s_italic
		#print "styleDic=",styleDic
		return styleDic
		
	def __getRangePositionList(self):
		"""Range Position List is a trick to speed up formatting in word"""
		return self.rangePositionList
	
	def formatBibliographicIndex(self,mswdoc_instance):
		"""This function transforms the range start stop list into a list
		of ranges according to msword document.
		the list obtained is:
			(
				(range1,range2,range3...)	=>each line represents an biblio entry
				(range1,range2,range3...)	=>each range is a field (author,separator, title)
			)
		"""
		#1) Need the starting position of the bibliography
		biblioField = mswdoc_instance.MSWgetBibusBiblio()
		activeDoc = mswdoc_instance.application.ActiveDocument
		if biblioField==None:
			#print "noBiblioField found"
			return None
		biblioPosition = biblioField.Result.Start
		#print "biblioPosition=",biblioPosition
		#2) create a copy of the self.rangePositionList()
		newList = self.__getRangePositionList()
		#3) Replace each (start,stop) list with document.Range(start,stop)
		rangeList = []
		for biblioEntry in newList:
			rangeEntryList = []
			for biblioField in biblioEntry:
				rangeEntryList.append(activeDoc.Range(biblioField[0]+biblioPosition,biblioField[1]+biblioPosition))
			rangeList.append(rangeEntryList)
		
		self.__applyStylesToBiblioRanges(mswdoc_instance, rangeList)	
		#return rangeList		
	
	def __applyStylesToBiblioRanges(self,mswdoc_instance,rangeList):
		#1) Need styles for each type of publication BibliographicType
		aList = []
		if rangeList==aList:
			return
		TmpPubliType = {}
		publiTypeDic = {}
		for field in mswdoc_instance.application.ActiveDocument.Fields:
			bibType = mswUtils.getXmlValueFromString("BibliographicType",field.Code.Text)
			TmpPubliType[bibType]=bibType
		for bibType in TmpPubliType:
			if bibType==None :
				continue
			if TmpPubliType[bibType]==None :
				continue
			lo,lf,ls =self.getOrderAndFormatAndSeparator(bibType)
			styleList = []
			for fieldFormat in lf:
				styleList.append(self.__getStyleAsDict(fieldFormat))
			publiTypeDic[bibType]=styleList
		#print "publiTypeDic = ",publiTypeDic
		#2) Need to know, for each entry what kind of publication we have
		# this is in self.pubTypeList
		# print "self.pubTypeList=",self.pubTypeList
#		#3)Create a List of first type encontered
		bibTypeExampleList= {}
		entryNb = 0
		for rangeEntry in rangeList :
			bibTypeExampleList[self.pubTypeList[entryNb]]=rangeEntry
			entryNb=entryNb+1
		#print "bibTypeExampleList=",bibTypeExampleList
		#4)Formatte the first type encontered only
		for ftype in bibTypeExampleList:
			fieldNb = 0
			styleDic = publiTypeDic[ftype]
			for rangeField in bibTypeExampleList[ftype] :
				if fieldNb >= len (styleDic): 
					print "Continuing in __applyStylesToBiblioRanges()"
					continue
				styleToApply = styleDic[fieldNb]
				self.__applyStyleToRange(rangeField,styleToApply)
				fieldNb=fieldNb+1
		#5)Map the style to each category of BibliographicType
		entryNb=0
		for rangeEntry in rangeList :
			fieldNb = 0
			for rangeField in rangeEntry:
				rangeModel = bibTypeExampleList[self.pubTypeList[entryNb]][fieldNb]
				#print "RangeField =", rangeField, "RangeModel =", rangeModel
				self.__applyStyleToRangeFromRange(rangeField,rangeModel)
				fieldNb=fieldNb+1
			entryNb=entryNb+1
		return
	
	def __printRangeFontInfo(self,aRange):
		"""Debugging function"""
		myFont = aRange.Font
		print "myFont.Bold = ",myFont.Bold
		print "myFont.Underline = ",myFont.Underline
		print "myFont.SmallCaps = ",myFont.SmallCaps
		print "myFont.AllCaps = ",myFont.AllCaps
		print "myFont.Italic = ",myFont.Italic

	def __applyStyleToRange(self,aRange,aStyle,isSuperscript=False,isSubscript=False):
		""" This function applies a style to a MSW Range.Font object
		Style is a dictionnary {'bold':True, 'italic':False etc...}"""
		#aRange.Select
		#print "aStyle = ", aStyle
		try:
			myFont = aRange.Font
			myFont.Bold=aStyle['bold']
			myFont.Italic= aStyle['italic']#( aStyle['italic']==True )
			myFont.Underline=aStyle['underline']
			myFont.SmallCaps=aStyle['smallcaps']
			myFont.AllCaps=aStyle['caps']
			myFont.Superscript=isSuperscript
			myFont.Subscript=isSubscript
		except (pywintypes.com_error):
			print "could not set font for a beginning range"
		#self.__printRangeFontInfo(aRange)
		return myFont
	def __applyStyleToRangeFromRange(self,destRange,oriRange):
		"""Copy style from a range and applies it to another"""
		if destRange != None or oriRange != None:
			try:
				destRange.Font = oriRange.Font
			except (pywintypes.com_error):
				return None#this error is minor and doesn't need to be handled
			return oriRange.Font
			
	def applyStyleNumToRange(self,aRange,StyleNum):
		"""Convert Bibus style numbers to font information"""
		#print "StyleNum=",StyleNum+100
		aStyle = self.__getStyleAsDict(StyleNum)
		self.__applyStyleToRange(aRange,aStyle)
#### Citation format stuff
	#immediate = appliable immediatly during reference insertion
	#finalize = appliable during finalization (for time issue)
	#n.ap = non applicable 
	
	#n.ap
	def __getCitationValue(self,key):
		"""Get values from BIB.FORMAT_DICO['citation']. Key is checked. If invalid, then the value None is returned"""
		return self.bibStyle['citation'][key]
	#n.ap
	def __getCitationPosition(self):
		"""Returns the citation value for key 'base_style' = (int=style,int=position)
		style is a value from s_underline, s_bold etc...
		position is a value for p_subscript, p_normal or p_superscript
		"""
		return self.base_style_list[1]
	
	#immediate
	def isCitationSubscript(self):
		if self.__getCitationPosition() == p_subscript:
			return True
		return False
	
	#immediate
	def isCitationSuperscript(self):
		if self.__getCitationPosition() == p_superscript:
			return True
		return False
	
	#immediate
	def isCitationNormalscript(self):
		if self.__getCitationPosition() == p_normal:
			return True
		return False
	
	#immediate
	#returns a dict for style
	#styleDic = {'underline':False,'smallcaps':False,'caps':False,'bold':False,'italic':False,'regular':True}

	def getCitationStyleDic(self):
		return self.styleDic
	
	#immediate
	def isCitationSorted(self):
		return self.nblist[n_sort]
		
	#finalize
	def isCitationFused(self):
		if self.isNumberEntries():
			return self.nblist[n_fuse]
		else :
			sepInfo = self.__getCitationValue("ad")
			return sepInfo[0]
		
	#finalize
	def isCitationRanged(self): #for use range option, in Numbering, Citation tab in style
		if self.isNumberEntries():
			return self.nblist[n_userange]
		else:
			return False	
		
	#finalize
	def getCitationFuseSeparator(self): #for use range option, in Numbering, Citation tab in style
		if self.isNumberEntries():
			return self.nblist[n_fusesep]
		else :
			sepInfo = self.__getCitationValue("ad")
			return sepInfo[1]

	#finalize
	def getCitationRangeSeparator(self): #for use range option, in Numbering, Citation tab in style
		return self.nblist[n_rangesep]
	
	def preFormatCitations(self,mswFields): #give citationFields only!!!!!!!
		"""this function is called when the menu pre-format citation is clicked
		This is one of the longest function. Not complex, just long.
		"""
		if len(mswFields)==0:
			return
		if self.isNumberEntries():
			rangeList = []
			for myField in mswFields:
				#nfo = mswRef.mswRef(myField)
				#if mswUtils.isFieldCitation(myField):
				rangeList.append(myField.Result)
			if rangeList ==[]:
				return
			citationStyle = self.getCitationStyleDic()
			firstCitation = rangeList[0]
			self.__applyStyleToRange(firstCitation,citationStyle,self.isCitationSuperscript(),self.isCitationSubscript())
			for rangeCitation in rangeList :
				self.__applyStyleToRangeFromRange(rangeCitation,firstCitation)
		else:
			#print "This part is going to be hard"
			
			activeDoc = mswFields[0].Application.ActiveDocument
			oBrackets,cBrakets = self.getBracket()
			allRangeList = []
			allRangeStartList = []
			#This creates a list of triplets [0,5,8]. Each citation has a list of triplets (press ALT+F9 in doc and see the <CitationRanges> key
			#0 and 5 are range start and stop. 8 is the style for the range
			for myField in mswFields:
				#if mswUtils.isFieldCitation(myField)==False:
				#	continue
				rangeString = mswUtils.getXmlValueFromString(mswCONST.me_MSWBIBUS_CITE_RANGES,myField.Code.Text)
				thisRangeStart = myField.Result.Start
				allRangeStartList.append(thisRangeStart)
				rangeList = []
				myRangeSplit = rangeString.split(mswCONST.me_MSWBIBUS_CITE_RANGE_SEP)
				for s in myRangeSplit:
					if len(s)==0:
						continue;
					ints = s.split(mswCONST.me_MSWBIBUS_CITE_RANGE_SEP_IN)
					rangeList.append(ints)
				allRangeList.append(rangeList)
			#Now we get the first range in which all the ranges are present. 
			#This range will be formatted and we will apply the format to other ranges, using this one as a model
			#The reason is that if we formatte each piece of text, one after the other, it would take too long so
			#if I have 3 citations for example
			#citation 1 ranges are is :[[u'0', u'15', u'8'], [u'15', u'16', u'-1'], [u'16', u'20', u'16'], [u'8', u'15', u'1']]
			#This represents ranges in (SURYAWAN ET AL.,2004).
				#0-15 = SURYAWAN ET AL., style 8
				#15-16 = ,    in style -1
				#16-20 = 2004 in style 16
				#8-15 = ET AL. that has its own format and is applied at the end, here style is 1  (italic)
			#Once we have applied the format to the first complete occurence we propagate this using self.__applyStyleToRangeFromRange()
			#We copy the font from one range to the other. This strategy is much much faster that formatting each triplet
			#citation 2 ranges are is :[[u'0', u'6', u'8'], etc...]
			#apply range font to 0-6 from first complete range citation one which is 0-15, with same style, 8.
			fistCorrectRange =[]
			if len (allRangeList) ==0 or len (allRangeList[0])==0:
				print "no formatting to be done"
				return
			fistCorrectRange = allRangeList[0]
			for aRangeInList in allRangeList:
				hasFirstRange = True
				for rangeCoord in aRangeInList:
						start = thisRangeStart +int(rangeCoord[0])+len(oBrackets) # the one is for the separator character
						stop = thisRangeStart +int(rangeCoord[1]) +len(oBrackets)
						if stop-start<1:
							hasFirstRange=False
							continue
				if hasFirstRange==True:
					fistCorrectRange=aRangeInList
					break
			indexForStart = allRangeList.index(fistCorrectRange)
			if indexForStart>=len(allRangeStartList):
				print "ERROR in preformatting citation. This shouldn't affect the document"
				return
			thisRangeStart = allRangeStartList[indexForStart]
			firstListOfRange = []
			nbField = 0
			for rangeCoord in fistCorrectRange[:-1]:
				start = thisRangeStart +int(rangeCoord[0])+len(oBrackets) # the one is for the separator character
				stop = thisRangeStart +int(rangeCoord[1]) +len(oBrackets)
				aRange = activeDoc.Range(start,stop)
				#print "aformattedRange=", aRange.Text, " ---start, stop , thisRangeStarts", start, stop,thisRangeStart
				firstListOfRange.append(aRange)
				aStyle = self.__getStyleAsDict(int(rangeCoord[2]))
				self.__applyStyleToRange(aRange,aStyle,self.isCitationSuperscript(),self.isCitationSubscript())
				nbField=nbField+1
			indexInAllRangeList = 0
			for aRangeInList in allRangeList:
				#indexForStart = allRangeList[indexInAllRangeList]
				#print "looping*****", indexForStart
				if indexInAllRangeList>=len(allRangeStartList):
					print "ERROR in preformatting citation. This shouldn't affect the document"
					continue
				thisRangeStart = allRangeStartList[indexInAllRangeList]
				#print "thisRangeStart=",thisRangeStart
				nbField = 0
				#print " aRangeInList[:-1]", aRangeInList[:-1]

				for rangeCoord in aRangeInList[:-1]:
					if nbField >= len (firstListOfRange):
						print "ERROR in preformatting citation. TemplateRange has less fields that DestinationRange This shouldn't affect the document"
						continue
					modelRange = (firstListOfRange[nbField])
					start = thisRangeStart +int(rangeCoord[0])+len(oBrackets) # the one is for the separator character
					stop = thisRangeStart +int(rangeCoord[1]) +len(oBrackets)
					aRange = activeDoc.Range(start,stop)
					#print "Text = ",aRange.Text
					self.__applyStyleToRangeFromRange(aRange,modelRange)
					nbField = nbField +1
				indexInAllRangeList=indexInAllRangeList+1		
			
			#Now we can apply the etal style
			indexForStart = allRangeList.index(fistCorrectRange)
			thisRangeStart = allRangeStartList[indexForStart]
			rangeCoord = fistCorrectRange[-1]
			start = thisRangeStart +int(rangeCoord[0])+len(oBrackets) # the one is for the separator character
			stop = thisRangeStart +int(rangeCoord[1]) +len(oBrackets)
			aRange = activeDoc.Range(start,stop)
			aStyle = self.__getStyleAsDict(int(rangeCoord[2]))
			firstListOfRange.append(aRange)
			self.__applyStyleToRange(aRange,aStyle,self.isCitationSuperscript(),self.isCitationSubscript())
			indexInAllRangeList1 = 0
			for aRangeInList in allRangeList:
				thisRangeStart1 = allRangeStartList[indexInAllRangeList1]
				rangeCoord1 = aRangeInList[-1]
				modelRange1 = (firstListOfRange[-1])
				start1 = thisRangeStart1 +int(rangeCoord1[0])+len(oBrackets) # the one is for the separator character
				stop1 = thisRangeStart1 +int(rangeCoord1[1]) +len(oBrackets)
				aRange1 = activeDoc.Range(start1,stop1)
				#print " ssss1= ",start1,stop1, aRange1.Text
				#if aRange1.Text.find(self.getEtalText())!=-1:
				self.__applyStyleToRangeFromRange(aRange1,modelRange1)
				indexInAllRangeList1=indexInAllRangeList1+1
			#self.__checkForDuplicates(mswFields)
			
	def refreshCitationText(self,myField):
		return self.applyCitationTemplate(myField)
	def applyCitationTemplate(self,myField): #aField must be the citation field (MSW Field object)!
		"""Applies the Author, 2005 as text to the citation
		This function also stores information in the field to speed up formating
		The Field.Code.Text contains at the end: <CitationRanges>3-6;5-8</CitationRanges>
		These ranges indicate the position where each field starts and stops. It will help for formatting
		"""
		#1) Need to know the template
		#2) Need to Parse Author Text
		#3) Need to apply it and return it
		#testText="<Identifier>Blades2005</Identifier><BibliographicType>ARTICLE</BibliographicType><Address>AstraZeneca R&D Charnwood, Bakewell Road, Loughborough, Leicestershire LE11 5RH, England. matthew.blades@astrazeneca.com</Address><Author>Blades, Matthew J;Ison, Jon C;Ranasinghe, Ranjeeva;Findlay, John B C</Author><Journal>Protein Sci</Journal><Month>Jan</Month><Number>1</Number><Pages>13-23</Pages><Title>Automatic generation and evaluation of sparse protein signatures for families of protein structural domains</Title><Volume>14</Volume><Year>2005</Year>"
		#citaTionText=testText
		aTemplate = self.__getCitationValue("ad_template")
		autFormated = ""
		rangeStart = 0
		#print "aTemplate = ", aTemplate
		rangeString = ""
		etalRangeString = ";0*0*0"
		#styleListForFields = [] #Styles to apply to each field in citation text when not numbered
		for aField in aTemplate :
			#aField is a list = ('field','Author',6) or ('text',',',1) etc...
			fToAdd=""
			if aField[0]=="field":
				fToAdd = mswUtils.getXmlValueFromString(aField[1],myField.Code.Text)
				if fToAdd == None :
					rangeString = rangeString +";"+str(rangeStart)+"*"+str(rangeStart)+"*0"
					#styleListForFields.append(0)
					continue
				elif aField[1]=="Author":
					fToAdd,etalRangeString=self.__applyAuthorTemplate(fToAdd)
					try:
						fToAdd = unicode(fToAdd)
					except:
						fToAdd = ""
					#Here fToAdd == "None" if no author
				elif aField[1]=="Year":
					try:
						fToAdd = fToAdd+mswUtils.getXmlValueFromString(mswCONST.me_MSWBIBUS_CITE_DUPLICATES,myField.Code.Text)	
					except (TypeError):
						fToAdd
			elif aField[0]=="text":
				fToAdd = aField[1]
			rangeString = rangeString +";"+str(rangeStart)+"*"+str(rangeStart+len(fToAdd))+"*"+str(aField[2])
			rangeStart = rangeStart+len(fToAdd)
			autFormated=autFormated+fToAdd
			#styleListForFields.append(aField[2])
		#print "autFormated = ",autFormated
		rangeString=rangeString+etalRangeString+"*"+str(self.getEtalStyle())
		#print "rangeString=",rangeString," aut =",autFormated
		newCodeText = mswUtils.replaceXmlValueForKey(mswCONST.me_MSWBIBUS_CITE_RANGES,myField.Code.Text,rangeString)
		return (autFormated,newCodeText)
	
	def __applyAuthorTemplate(self, autstr):
		if len(autstr)<1:
			return ("",";0"+mswCONST.me_MSWBIBUS_CITE_RANGE_SEP_IN+"0")
		""" Applies the et al. after n names"""
		ad_author = self.__getCitationValue("ad_author")
		authorFormat = ad_author['format']
		authorFormatCite = authorFormat[0][0]
		authorFormatJoin = authorFormat[3]
		beforLastSep = authorFormatJoin[1][3]
		authorSep = authorFormatJoin[1][1]
		numberOfAuthor = authorFormatJoin[1][5]
		etalText = authorFormatJoin[1][6]
		auToReturn = autstr
		myNameSurnameSep = ''
		mySurnameSep1 =authorFormat[0][1][0]
		mySurnameSep2 =authorFormat[0][1][1]
		mySurnameSep3 =authorFormat[0][1][2]
		etalRangeString=""
		#Authors splitting
		authors = autstr.split(';')
		myAuthors = []
		nbAuthors = 0
		for aut in authors:
			nameSplit = aut.split(',')
			myAuthors.append(nameSplit)
			nAuthors = nbAuthors+1
		newAuthorList = []
		if authorFormatCite == "Format.Citation.Author.Author.author1" :
			#print "in NUMBER ONE"
			for aAut in myAuthors:
				revAut = []
				initialString =""
				prenameSplit = aAut[1].split(' ')
				for pr in prenameSplit[:-1]:
					if len(pr) >0:
						initialString = initialString+pr+mySurnameSep1
				if len(prenameSplit[-1])>0:
					initialString=initialString+prenameSplit[-1]
				revAut.append(initialString+mySurnameSep2)
				revAut.append(aAut[0]+mySurnameSep3)
				newAuthorList.append(revAut)
			auToReturn = newAuthorList

		elif authorFormatCite == "Format.Citation.Author.Author.author2" :
			#print "in NUMBER TWO"
			for aAut in myAuthors:
				revAut = []
				initialString =""
				revAut.append(aAut[0]+mySurnameSep1)
				prenameSplit = aAut[1].split(' ')
				for pr in prenameSplit[:-1]:
					if len(pr) >0:
						initialString = initialString+pr+mySurnameSep2
				if len(prenameSplit[-1])>0:
					initialString=initialString+prenameSplit[-1]
				revAut.append(initialString+mySurnameSep3)
				#print "revAut=",revAut, "   aAut=",aAut
				newAuthorList.append(revAut)
			auToReturn = newAuthorList

		elif authorFormatCite == "Format.Citation.Author.Author.author3" :
			#print "in NUMBER THREE"
			for aAut in myAuthors:
				revAut = []
				initialString =""
				prenameSplit = aAut[1].split(' ')
				for pr in prenameSplit[:-1]:
					if len(pr) >0:
						initialString = initialString+pr[0]+mySurnameSep1
				if len(prenameSplit[-1][0])>0:
					initialString=initialString+prenameSplit[-1][0]
				revAut.append(initialString+mySurnameSep2)
				revAut.append(aAut[0]+mySurnameSep3)
				newAuthorList.append(revAut)
			auToReturn = newAuthorList
		elif authorFormatCite == "Format.Citation.Author.Author.author4" :
			#print "in NUMBER FOUR"
			for aAut in myAuthors:
				revAut = []
				initialString =""
				prenameSplit = aAut[1].split(' ')
				#print "presplit = ", prenameSplit
				#print "presplit -1 =",prenameSplit[:-1]
				for pr in prenameSplit[:-1]:
					if len(pr) >0:
						initialString = initialString+pr[0]+mySurnameSep2
				if len(prenameSplit[-1][0])>0:
					initialString=initialString+prenameSplit[-1][0]
				revAut.append(aAut[0]+mySurnameSep1)
				revAut.append(initialString+mySurnameSep3)
				newAuthorList.append(revAut)
			auToReturn = newAuthorList
		elif authorFormatCite == "Format.Citation.Author.Author.author5" :
			#print "in NUMBER FIVE"
			for aAut in myAuthors:
				revAut = []
				revAut.append(aAut[0])
				revAut.append('')
				newAuthorList.append(revAut)
			auToReturn = newAuthorList
		#print "newAuthorList=",newAuthorList, 
		
		auToReturn=""
		nbAuthors = len(newAuthorList)
		#print " nbAuthors = ",nbAuthors	
		if nbAuthors==1:
			auToReturn=auToReturn+newAuthorList[0][0]
			if len(newAuthorList[0][1])>0:
				auToReturn=auToReturn+myNameSurnameSep+newAuthorList[0][1]
			etalRangeString =";0"+mswCONST.me_MSWBIBUS_CITE_RANGE_SEP_IN+"0"
		elif nbAuthors < numberOfAuthor or numberOfAuthor==0: #numberOfAuthor=0 when don't want the et al. to be added
			#print range(nbAuthors-1)
			for inbAut in range(nbAuthors-1):
				auToReturn=auToReturn+newAuthorList[inbAut][0]
				if len(newAuthorList[inbAut][1])>0:
					auToReturn=auToReturn+myNameSurnameSep+newAuthorList[inbAut][1]
				if inbAut!=nbAuthors-2:
					auToReturn =auToReturn + authorSep
				else:
					auToReturn =auToReturn
					
			auToReturn=auToReturn+beforLastSep+newAuthorList[-1][0]
			if len(newAuthorList[-1][1])>0:
					auToReturn=auToReturn+myNameSurnameSep+newAuthorList[-1][1]
			etalRangeString =";0"+mswCONST.me_MSWBIBUS_CITE_RANGE_SEP_IN+"0"
		else :
			auToReturn=auToReturn+newAuthorList[0][0]
			if len(newAuthorList[0][1])>0:
				auToReturn=auToReturn+myNameSurnameSep+newAuthorList[0][1]
			etalRangeString =";"+ str(len(auToReturn))+mswCONST.me_MSWBIBUS_CITE_RANGE_SEP_IN+str(len(auToReturn)+len(etalText))
			auToReturn = auToReturn + etalText
			#print "etalRangeString=",etalRangeString
		return (auToReturn,etalRangeString)
		

	def __checkForDuplicates(self,citationFields):	
		"""Called for finalisation and looks for duplicate"""
		t1 = time.time()
		newDuplicateDict= {}
		oBracket,cBracket = self.getBracket()
		#Adding duplicates into a list
		for aField in citationFields:
			idZero = mswUtils.getXmlValueFromString("Identifier",aField.Code.Text)
			resZero = idZero.split("#")
			disZero = aField.Result.Text
			if newDuplicateDict.has_key(disZero):
				if newDuplicateDict[disZero].count(idZero)==0:
					newDuplicateDict[disZero].append(idZero)
			else:
				newList = []
				newList.append(idZero)
				newDuplicateDict[disZero]=newList
		t2=time.time()
		for aDup in newDuplicateDict.keys():
			if len(newDuplicateDict[aDup])<2:
				del newDuplicateDict[aDup]
		t3=time.time()
		return 	newDuplicateDict	

	def addDuplicateInfo(self,citationFields):
		"""Modify the Field.Result.Text information for each field, and adds the duplicate
		information when needed. Called during finalization"""
		oBracket,cBracket = self.getBracket()
		newDuplicateDict = self.__checkForDuplicates(citationFields)
		
		fieldListTuple = []	
		for aK in newDuplicateDict.keys():
			for f in citationFields:
				aId = f.Result.Text
				if aId ==None:
					continue
				if aId==aK:
					fieldListTuple.append((aId,f))
		#print"*********flt**********"
		#print fieldListTuple
		#print"*********flt**********"
		#print"*********ndd**********"
		#print newDuplicateDict
		#print"*********ndd**********"
		#print newDuplicateDict
		for aKey in newDuplicateDict.keys():
			aGroup = newDuplicateDict[aKey]
			nbDuplicate = 97
			for aCitation in aGroup:
				for oField in fieldListTuple:
					oId = mswUtils.getXmlValueFromString("Identifier",oField[1].Code.Text)
					if oId==aCitation:
						#print "Modify duplicate info for ",aCitation,chr(nbDuplicate)
						pubYear = mswUtils.getXmlValueFromString("Year",oField[1].Code.Text)
						mswUtils.modifyFieldCodeForKey(oField[1],"Year",pubYear+str(chr(nbDuplicate)))
						
				nbDuplicate=nbDuplicate+1
		 
		#print "addDuplicate = ", time.time()-t1
	def lookForDuplicates(self,mswFields):
		"""Perofmance function, not called in normal use"""
		print "****Duplicate Performance Monitoring****"
		t1=time.time()
		self.addDuplicateInfo(mswFields)
		t3 = time.time()
		totalTime = t3-t1
		print "Total (sec.) for ~",len(mswFields)," Citations = ",totalTime 
		
	def __setShortenedToEtAl(self):
		ad_author = self.__getCitationValue("ad_author")
		authorFormat = ad_author['format']
		authorFormatJoin = authorFormat[3]
		numberOfAuthor = authorFormatJoin[1][5]
		if numberOfAuthor==0:
			self.isShortToEtal=False
		else:
			self.isShortToEtal=True
		return self.isShortToEtal

	def __setEtalText(self):
		ad_author = self.__getCitationValue("ad_author")
		authorFormat = ad_author['format']
		authorFormatJoin = authorFormat[3]
		self.etalText = authorFormatJoin[1][6]
		self.etalStyle = ad_author['etall_style']
		return self.etalText
		
	def isShortenedToEtal(self):
		return self.isShortToEtal
		
	def getEtalText(self):
		return self.etalText

	def getEtalStyle(self):
		return self.etalStyle
	
	def normalizeCitationRangeFont(self,aRange):
		aRange.Font.Bold = False
		aRange.Font.Superscript = self.isCitationSuperscript()
		aRange.Font.Subscript = self.isCitationSubscript()
	
	def fuseCitations(self,mswFields):
		if self.isNumberEntries():
			citationGroups = self.__groupCitations(mswFields)
			self.__rangeNumberedCitations(citationGroups)#fuse and range
		else :
			self.__groupCitations(mswFields)

	def __fuseTextCitations(self,citationGroups):
		"""Tentative function, not called during normal use"""
		replaceTemplate = "123456789#*987654321"
		strToReplace = replaceTemplate+self.getCitationFuseSeparator()
		for group in citationGroups:
			groupedCitationText = replaceTemplate
			for citation in group:
				groupedCitationText=groupedCitationText+self.getCitationFuseSeparator()+citation.Result.Text
			oBracket,cBracket = self.getBracket()
			groupedCitationText = groupedCitationText.replace(oBracket,"")
			groupedCitationText = groupedCitationText.replace(cBracket,"")
			groupedCitationText=oBracket+groupedCitationText+cBracket
		

		
	def __groupCitationsBefore(self,mswFields):	
		citationToFuse=[]
		fieldList = []
		try:
			#print "Calling List"
			lastField = mswFields[-1]
			firstField = mswFields[0]
		except(IndexError):
			#print "Calling Windows"
			lastField = mswFields.Item(len(mswFields))
			firstField = mswFields.Item(1)
			
		replaceChar = [u"\t",u",",u";",u" "]
		activeDoc = lastField.Application.ActiveDocument
		citationGroups = []
		citationGroupId = []
		totalGroupIds = []
		fl = []
		fl.append(firstField)
		citationGroups.append(fl)
		citationGroupId.append(unicode(mswUtils.getXmlValueFromString("Identifier",firstField.Code.Text)))
		for aField in mswFields:
			#print aField.Result,aField.Result.Start,aField.Result.End
			curId = unicode(mswUtils.getXmlValueFromString("Identifier",aField.Code.Text))
			prevField = aField.Previous
			try:
				spaceBetweenFields = activeDoc.Range(prevField.Result.End,aField.Result.Start)
			except (pywintypes.com_error,AttributeError ):
				#print "Error, spaceBetweenFields, file mswFormatter.py"
				continue
			#Stripping characters
			astripped = mswUtils.stripStringsFromList((spaceBetweenFields.Text),replaceChar)
			stripped =""
			#print "sps =", spaceBetweenFields.Text, "stripesps =",astripped
			sp = astripped.splitlines()
			stripped = stripped.join(sp)
			if len(stripped)==0:#means the two fields are contiguous
				s="nothin"
			else:	
				newGroup = []
				totalGroupIds.append(citationGroupId)
				citationGroupId=[]
				citationGroups.append(newGroup)
			if citationGroupId.count(curId)==0:
				citationGroups[-1].append(aField)
				citationGroupId.append(curId)
			else:
				aField.Result.Collapse()
				aField.Result.Delete()

		oBracket,cBracket = self.getBracket()
		
		sortedCitationGroups = []
		unSortedCitationGroups = []
		sortedCitationGroupInfo = []
		for group in citationGroups:
			#print "Groups..."
			#for cite in group:
			#	print "Cite=>%s<"%cite.Result.Text
			if len(group)<2:
				continue
			unSortedCitationGroups.append(group)
			sortedGroup = self.__sortCitationGroup(group)
			sortedCitationGroups.append(sortedGroup)
			#groupInfo=[]
			#for citation in sortedGroup:
			#	groupInfo.append((citation.Result.Text,citation.Code.Text))
			#sortedCitationGroupInfo.append(groupInfo)
		citationGroups=sortedCitationGroups
				
		if (oBracket,cBracket) !=('',''):
			for group in citationGroups:
				for acite in group[1:-1]:
					acResText = acite.Result.Text
					if acResText[0]==oBracket:
						acResText = self.getCitationFuseSeparator()+acResText[1:]
					if acResText[-1]==cBracket:
						acResText = acResText[:-1]
					acite.Result.Text=acResText
					acite.Data = mswCONST.me_MSWBIBUS_CITE_TAG
					#acite.Result.Font.Bold = False
					
				group[0].Result.Text=group[0].Result.Text[:-1]
				group[0].Data = mswCONST.me_MSWBIBUS_CITE_TAG
				group[-1].Result.Text=self.getCitationFuseSeparator()+group[-1].Result.Text[1:] #(removes first bracket)
				group[-1].Data = mswCONST.me_MSWBIBUS_CITE_TAG
				groupInfo=[]
				for citation in group:
					groupInfo.append((citation.Result.Text,citation.Code.Text))
				sortedCitationGroupInfo.append(groupInfo)
				#group[0].Result.Font.Bold=False
				#group[-1].Result.Font.Bold=False
				
		else:
			for group in citationGroups:
				for acite in group[:-1]:
					acite.Result.InsertAfter(self.getCitationFuseSeparator())
					acite.Result.Bold = False 
				groupInfo=[]
				for citation in group:
					groupInfo.append((citation.Result.Text,citation.Code.Text))
				sortedCitationGroupInfo.append(groupInfo)
		
		
		for gr in sortedCitationGroupInfo:
			print "sortedCitationGroupInfo"
			for ci in gr:
				print ci[0]
		for gr in unSortedCitationGroups:
			print "Non Sorted"
			for ci in gr:
				print ci.Result.Text
		#Moving the groups at their sorted position in the document
		newCitationGroup = []
		for group in citationGroups:
			newGroup = []
			firstCitation = group[0]
			group.reverse()
#			for cite in group[:-1]:
				#print "Groups..."
				#print "Cite=>%s<"%cite.Result.Text, "isad=", mswUtils.isFieldAddin(cite)
			for cite in group[:-1]:
				#print " Inserting Field:>%s<"%cite.Result.Text
				newField =mswUtils.insertField(cite,firstCitation,self)
					
					#Exe bug:
					#if newField.Result.Text[0]==' ':
					#	newField.Result.Text=newField.Result.Text[1:]
					#print "Correction = >%s<"%newField.Result.Text
				newGroup.append(newField)
				cite.Delete()
			newGroup.append(firstCitation)
			newGroup.reverse()
			newCitationGroup.append(newGroup)
		for group in newCitationGroup:
			for cite in group:
				if cite.Code.Text.find("BibusRef")!=-1:
					cite.Data = mswCONST.me_MSWBIBUS_CITE_TAG
		return newCitationGroup
		
	def __groupCitations(self,mswFields):	
		citationToFuse=[]
		fieldList = []
		try:
			#print "Calling List"
			lastField = mswFields[-1]
			firstField = mswFields[0]
		except(IndexError):
			#print "Calling Windows"
			lastField = mswFields.Item(len(mswFields))
			firstField = mswFields.Item(1)
			
		replaceChar = [u"\t",u",",u";",u" "]
		activeDoc = lastField.Application.ActiveDocument
		citationGroups = []
		citationGroupId = []
		totalGroupIds = []
		fl = []
		fl.append(firstField)
		citationGroups.append(fl)
		citationGroupId.append(unicode(mswUtils.getXmlValueFromString("Identifier",firstField.Code.Text)))
		for aField in mswFields:
			#print aField.Result,aField.Result.Start,aField.Result.End
			if not (mswUtils.isFieldCitation(aField)):
				continue
			curId = unicode(mswUtils.getXmlValueFromString("Identifier",aField.Code.Text))
			prevField = aField.Previous
			try:
				spaceBetweenFields = activeDoc.Range(prevField.Result.End,aField.Result.Start)
			except (pywintypes.com_error,AttributeError ):
				#print "Error, spaceBetweenFields, file mswFormatter.py"
				continue
			#Stripping characters
			astripped = mswUtils.stripStringsFromList((spaceBetweenFields.Text),replaceChar)
			stripped =""
			#print "sps =", spaceBetweenFields.Text, "stripesps =",astripped
			sp = astripped.splitlines()
			stripped = stripped.join(sp)
			if len(stripped)==0:#means the two fields are contiguous
				try:
					spaceBetweenFields.Collapse()
					spaceBetweenFields.Delete()
					#print "OK"
				except:
					pass
			else:	
				newGroup = []
				totalGroupIds.append(citationGroupId)
				citationGroupId=[]
				citationGroups.append(newGroup)
			if citationGroupId.count(curId)==0:
				citationGroups[-1].append(aField)
				citationGroupId.append(curId)
			else:
				try:
					aField.Result.Collapse()
					aField.Result.Delete()
				except:
					pass

		oBracket,cBracket = self.getBracket()
		
		sortedCitationGroups = []
		unSortedCitationGroups = []
		sortedCitationGroupInfo = []
		for group in citationGroups:
			#print "Groups..."
			#for cite in group:
			#	print "Cite=>%s<"%cite.Result.Text
			if len(group)<2:
				continue
			unSortedCitationGroups.append(group)
			sortedGroup = self.__sortCitationGroup(group)
			sortedCitationGroups.append(sortedGroup)
			#groupInfo=[]
			#for citation in sortedGroup:
			#	groupInfo.append((citation.Result.Text,citation.Code.Text))
			#sortedCitationGroupInfo.append(groupInfo)
		citationGroups=sortedCitationGroups
				
		if (oBracket,cBracket) !=('',''):
			for group in citationGroups:
				for acite in group[1:-1]:
					acResText = acite.Result.Text
					if acResText[0]==oBracket:
						acResText = self.getCitationFuseSeparator()+acResText[1:]
					if acResText[-1]==cBracket:
						acResText = acResText[:-1]
					acite.Result.Text=acResText
					acite.Data = mswCONST.me_MSWBIBUS_CITE_TAG
					#acite.Result.Font.Bold = False
					
				group[0].Result.Text=group[0].Result.Text[:-1]
				group[0].Data = mswCONST.me_MSWBIBUS_CITE_TAG
				group[-1].Result.Text=self.getCitationFuseSeparator()+group[-1].Result.Text[1:] #(removes first bracket)
				group[-1].Data = mswCONST.me_MSWBIBUS_CITE_TAG
				groupInfo=[]
				for citation in group:
					groupInfo.append((citation.Result.Text,citation.Code.Text))
				sortedCitationGroupInfo.append(groupInfo)
				#group[0].Result.Font.Bold=False
				#group[-1].Result.Font.Bold=False
				
		else:
			for group in citationGroups:
				for acite in group[:-1]:
					acite.Result.InsertAfter(self.getCitationFuseSeparator())
					acite.Result.Bold = False 
				groupInfo=[]
				for citation in group:
					groupInfo.append((citation.Result.Text,citation.Code.Text))
				sortedCitationGroupInfo.append(groupInfo)
		
#		for gr in sortedCitationGroupInfo:
#			print "sortedCitationGroupInfo"
#			for ci in gr:
#				print ci[0]
		grNb =0
		newCitationGroups =[]
		for gr in unSortedCitationGroups:
			citeNb=0
			for ci in gr:
#                                print "group: ",grNb," cite: ",citeNb," data: ",sortedCitationGroupInfo[grNb][citeNb]
				codeText = sortedCitationGroupInfo[grNb][citeNb][1]
				ci.Code.Text = mswUtils.correctCodeTextAfterFusion(codeText,self)
				ci.Result.Text = sortedCitationGroupInfo[grNb][citeNb][0]
				citeNb=citeNb+1
			newCitationGroups.append(gr)
			grNb=grNb+1
				
		for group in newCitationGroups:
			for cite in group:
				if cite.Code.Text.find("BibusRef")!=-1:
					cite.Data = mswCONST.me_MSWBIBUS_CITE_TAG
		return newCitationGroups
		
	def __rangeNumberedCitations(self,citationGroups):
		#return
		if len(citationGroups)==0:
			return
		#print "rangeNumberedCitations"
		citationToReplace = []
		oBracket,cBracket = self.getBracket()
		activeDoc = citationGroups[0][0].Application.ActiveDocument
		for group in citationGroups:
			citationToReplace.append([group[0],])
			txt =group[0].Result.Text
			stripped = group[0].Result.Text.strip(oBracket + cBracket +self.getCitationFuseSeparator() + ' ')
			prevCitationNb=-1
			try:
				prevCitationNb = int(group[0].Result.Text.strip(oBracket + cBracket +self.getCitationFuseSeparator() + ' '))
			except (ValueError):
				#print "Problem with ",group[0].Result.Text
				pass
			for citation in group[1:]:
				citeNbStr = citation.Result.Text.strip(oBracket + cBracket +self.getCitationFuseSeparator() + ' ')
				curCitationNb = int(citeNbStr)
				#print citation.Result.Text, int(citeNbStr)
				if prevCitationNb == curCitationNb - 1:
					s="Nothing"
				else:
					newGroupToRemove = []
					citationToReplace.append(newGroupToRemove)
				prevCitationNb = curCitationNb
				citationToReplace[-1].append(citation)
		#for group in citationToReplace:
			#print "new group=", len(group)
			#for cite in group:
			#	print "Cite=>%s<"%cite.Result.Text 
		for group in citationToReplace:
			#print "Len group=", len(group)
			if len(group)<3:
				continue
			for citation in group[1:-1]:
				citation.Result.Collapse()
				citation.Result.Delete()
			#print "Inserting rangeSeparator",
			group[0].Result.InsertAfter(self.getCitationRangeSeparator())
			#Exe bug
			#group[0].Result.Find.Execute(self.getCitationFuseSeparator(), ReplaceWith="")
			# Doesn't word = group[-1].Result.Text=group[1].Result.Text.replace(self.getCitationFuseSeparator(),"")#Find.Execute(self.getCitationFuseSeparator(), ReplaceWith="")
			#print "Res before replacing = ", re
			group[-1].Result.Text=group[-1].Result.Text.replace(self.getCitationFuseSeparator(),"")#Find.Execute(self.getCitationFuseSeparator(), ReplaceWith="")
			#group[0].Result.Text=group[0].Result.Text.replace(self.getCitationFuseSeparator(),"")#Find.Execute(self.getCitationFuseSeparator(), ReplaceWith="")
		#print "RangeSep = ", self.getCitationRangeSeparator()
	def __sortCitationGroup(self, group):
		#print "sorting"
		resList=[]
		sortedGroup = []
		#for cite in group :
			#print "Cite =>%s<"%cite.Result.Text," len =", len(cite.Result.Text), " Code =", cite.Code.Text[:20]
		#	if len(cite.Result.Text)==0:
		#		cite.Result.Text="Err."
		if self.isNumberEntries()==False:
			for cite in group :
				resList.append((cite.Result.Text,cite))
			resList.sort()
			for aRes in resList:
				sortedGroup.append(aRes[1]) 
			return sortedGroup
		else: 
			if self.isCitationSorted()==False:
				return group
			
			for cite in group :
				try:
					num = int(cite.Result.Text.strip(';,{}()[]<> '))
					#print "num = ", num
				except (ValueError):
					print "Error for Res = ",cite.Result.Text
					print "Error for Code = ",cite.Code.Text
					continue
				resList.append((num,cite))
			resList.sort()
			for aRes in resList:
				sortedGroup.append(aRes[1]) 
			return sortedGroup
		
		
		
		
