source: salt-libreoffice-addon/trunk/fuentes/salt/sltooo.py @ 473

Last change on this file since 473 was 473, checked in by daduve, 3 years ago

Adding files

File size: 96.7 KB
Line 
1#C:/Python27/python
2# -*- coding: utf-8 -*-
3
4import sys
5sys.path.append(sys.exec_prefix)
6
7sltversion="4.1.19"
8
9#Constantes que indican la plataforma
10esLinux=False
11esMac=False
12miHOME='APPDATA'
13pyLIB=sys.exec_prefix+"\\lib"
14if sys.platform.lower().find('linux')>=0:
15  esLinux=True
16  miHOME='HOME'
17  pyLIB=sys.exec_prefix+"/lib"
18
19sys.path.append(pyLIB)
20
21import os
22# 1. Obtener srvPath
23if esLinux:
24  srvPath="/usr/share/salt-server"
25else:
26  srvPath=os.environ['PROGRAMFILES'] + "/salt4"
27 
28srvPath=os.path.abspath(srvPath)
29srvPath2=os.path.abspath(os.environ[miHOME]+"/salt4") #alternativo
30
31# 2. Obtener usrPath
32usrPath=os.path.abspath(os.environ[miHOME]+"/.salt4")
33try:
34        if os.environ['USERNAME']=='root':
35                usrPath=os.path.abspath("/root/.salt4")
36except:
37        pass
38
39try:
40        if os.environ['USER']=='root':
41                usrPath=os.path.abspath("/root/.salt4")
42except:
43        pass
44 
45if not os.path.exists(usrPath):
46  os.mkdir(usrPath)
47
48
49# 3. Buscar archivo de configuracion
50if not os.path.exists(os.path.abspath(srvPath+'/sltsrv.config')) and os.path.exists(os.path.abspath(srvPath2+'/sltsrv.config')):
51  srvPath=srvPath2
52 
53# 4. Copiar config si es necesario
54_config=os.path.abspath('/var/lib/salt/sltsrv.config')
55if not os.path.exists(_config):
56  _config=os.path.abspath(srvPath+'/sltsrv.config')
57if os.path.exists(_config):
58  if os.path.exists(os.path.abspath(usrPath+'/sltsrv.config')):
59    fsrv=open(_config,'rb')
60    fusr=open(os.path.abspath(usrPath+'/sltsrv.config'),'rb')
61    cfgsrv=eval(fsrv.read())
62    cfgusr=eval(fusr.read())
63    fsrv.close()
64    fusr.close()
65    if not 'entorn' in cfgsrv or not 'entorn' in cfgusr or not 'sltinitime' in cfgsrv['entorn'] or not 'sltinitime' in cfgusr['entorn'] or cfgsrv['entorn']['sltinitime']!=cfgusr['entorn']['sltinitime']:
66      import shutil
67      shutil.copy(_config,os.path.abspath(usrPath+'/sltsrv.config'))
68      try:
69        for root,dirs, files in os.walk(usrPath):
70          for name in files:
71            if name[0:3]=='tmp':
72              os.remove(os.path.join(root,name))
73      except:
74        pass
75  else:
76    import shutil
77    shutil.copy(_config,os.path.abspath(usrPath+'/sltsrv.config'))
78    try:
79        for root,dirs, files in os.walk(usrPath):
80          for name in files:
81            if name[0:3]=='tmp':
82              os.remove(os.path.join(root,name))
83    except:
84      pass
85   
86# Leer configuracion
87f=open(os.path.abspath(usrPath+'/sltsrv.config'),'rb')
88scfg=f.read()
89f.close()
90cfg=eval(scfg)
91if 'entorn' in cfg:
92  if 'sltsrvpaths' in cfg['entorn']:
93    sys.path.extend(cfg['entorn']['sltsrvpaths'])
94     
95ooopath=sys.executable
96bn=os.path.basename(ooopath)
97ooopath=os.path.dirname(ooopath)
98ooopathpy=""
99while bn!="":
100  if bn.lower()=="program":
101    ooopath=os.path.abspath(ooopath+"/program")
102    break
103  elif bn.lower().find("python-")>-1:
104    ooopathpy=os.path.abspath(ooopath+"/"+bn)
105  bn=os.path.basename(ooopath)
106  ooopath=os.path.dirname(ooopath)
107#if ooopathpy!="":
108#  sys.path.append(os.path.abspath(ooopathpy+"/lib"))
109#  sys.path.append(os.path.abspath(ooopathpy))
110#else:
111#  sys.path.append(os.path.abspath(ooopath+"/python-core-2.3.4/lib"))
112#  sys.path.append(os.path.abspath(ooopath+"/python-core-2.3.4"))
113#sys.path.append(ooopath)
114
115import uno
116try:
117  import unohelper
118except:
119  pass
120import socket
121import codecs
122import platform
123import doooLib
124import syslog
125
126from com.sun.star.task import XJobExecutor
127
128# ----------------------------------------------
129# Definiciones de Salt
130# ----------------------------------------------
131#Busqueda de palabras
132#Constantes usadas en PalabraAnt y PalabraSig
133EST_INI = 0           #'Estado inicial
134EST_ESP = 1           #'Espacios (viene de INI o TXT)
135EST_TXT = 2           #'Texto (viene de INI)
136EST_ESPTXT = 3        #'Texto (viene de ESP)
137
138#Constantes que definen la estructura de cada elemento de colTx
139tx_paltext=0
140tx_nordori=1
141tx_carfinpal=2
142tx_italica=3
143tx_italicaori=4
144
145#Apostrofe tipografico
146apotpgr=chr(146)
147if esLinux:
148  apotpgr="\xe2\x80\x99"
149
150def Llog(msg):
151  syslog.syslog(syslog.LOG_DEBUG,str(msg))
152
153def PalabraSig(doc,lscurs=[]):
154  _ret = None
155  #
156  #   Obtener la primera palabra siguiente a la posicion de partida
157  #
158  #   Entrada:    doc: documento (sltDoc)
159  #   El cursor se queda con la palabra encontrada seleccionada
160  #
161  #   Salida:     lscurs: Lista de cursores para traduccion adicional (si hay)
162  #
163  #   Retorno:    Palabra encontrada ("" si no hay mas palabras),
164  #               caracter de fin de palabra
165  #               Fin de parrafo no/si(0/1)
166  # VB2PY (UntranslatedCode) On Error GoTo PalabraSig_ME
167  finpar=0
168  c=""
169  estado=EST_INI
170  cesp=u",.;:{}/[]<>?¿¡!ªº()%\"" + ucode(chr(145)) + ucode(chr(146)) + ucode(chr(147)) + ucode(chr(148)) + ucode(chr(132)) + ucode(chr(171)) + ucode(chr(187)) + ucode(chr(188)) + ucode(chr(10)) + ucode(chr(12)) + ucode(chr(9)) + ucode(chr(11)) + ucode(chr(160)) + ucode(chr(150)) + ucode(chr(151)) + ucode(chr(215)) + ucode(chr(247))
171  #Buscar palabra siguiente (pi y pf)
172  doc.cur.collapseToEnd()
173  if doc.cur.Footnote!=None:
174    tc=doc.cur.Footnote.Text.createTextCursor()
175    tc.gotoStart(0)
176    lscurs.append(tc)
177    doc.cur.goRight(1,0)
178  elif doc.cur.Endnote!=None:
179    tc=doc.cur.Endnote.Text.createTextCursor()
180    tc.gotoStart(0)
181    lscurs.append(tc)
182    while doc.cur.Endnote!=None:
183      doc.cur.goRight(1,0)
184  ret=doc.NextChar()
185  while ret==True and finpar <=1:
186    if len(doc.Char())==0:
187      ret=doc.NextChar()
188    if not ret:
189      finpar=1
190    c = doc.cur.String[-1]
191    #FiltroApo(c, txDOC, pf)
192    if estado==EST_INI:
193      if escesp(c,cesp):
194        estado=EST_ESPTXT
195        break
196      elif c==" ":
197        doc.cur.collapseToEnd()
198      else:
199        estado=EST_TXT
200    elif estado== EST_TXT:
201      if escesp(c,cesp):
202        doc.cur.goLeft(1,1)
203        estado=EST_ESPTXT
204        break
205      elif c==" ":
206        doc.cur.goLeft(1,1)
207        estado=EST_ESPTXT
208        break
209      elif doc.cur.Footnote!=None:
210        estado=EST_ESPTXT
211        break
212      elif doc.cur.Endnote!=None:
213        estado=EST_ESPTXT
214        break
215    if finpar==1:
216      #ya era fin de parrafo
217      break
218    ret=doc.NextChar()
219 
220  cf = c
221  if estado == EST_ESPTXT:
222    #Solo hay nueva palabra si hemos llegado al estado TXT desde ESP
223    _ret = doc.Char()
224  elif not ret:
225    #No habia mas caracteres
226    finpar=True
227    _ret=doc.Char()
228  elif doc.isEnd() and len(doc.Char())>0:
229    #.. o es la ultima
230    finpar=True
231    _ret=doc.Char()
232  else:
233    _ret = ''
234 
235  #Tratamos numbering
236  p=_ret.find('.')
237  if p==-1:
238    p=_ret.find(')')
239  if p>0:
240    _ret=_ret[p+1:]
241   
242  return _ret,cf,finpar
243
244def sltDate():
245  #Fecha del addon
246  if os.path.exists(os.path.abspath(__file__)):
247    return time.localtime(os.stat(os.path.abspath(__file__))[8])
248  else:
249    return None
250
251def FiltroApo(c, tx, p):
252  #
253  #   Comprobar si se trata de un caracter ' usado como
254  #   comillas o como apostrofe. Para ser apóstrofe ha de
255  #   ser sel tipo letra'letra, siendo letra una caracter
256  #   entre a y z. Si es un carácter ' usado como comillas
257  #   cambiarlo por "
258  #
259  #   Entrada:    c: Carácter actual (puede modificarlo)
260  #               tx: TXTextControl que contiene el texto
261  #                   a analizar
262  #               p: Posición del carácter a analizar (la
263  #                   primera posición del texto es la 1)
264  #
265  #
266  if c == '\'':
267    EsApo = False
268    if p > 1 and p < Len(tx):
269      _select11 = LCase(Mid(tx, p - 1, 1))
270      if ('a' <= _select11 <= 'z') or (_select11 == 'à') or (_select11 == 'á') or (_select11 == 'è') or (_select11 == 'é') or (_select11 == 'í') or (_select11 == 'ò') or (_select11 == 'ó') or (_select11 == 'ú'):
271        _select12 = LCase(Mid(tx, p + 1, 1))
272        if ('a' <= _select12 <= 'z') or (_select12 == 'à') or (_select12 == 'á') or (_select12 == 'è') or (_select12 == 'é') or (_select12 == 'í') or (_select12 == 'ò') or (_select12 == 'ó') or (_select12 == 'ú'):
273          EsApo = True
274    if not EsApo:
275      #Actua como comillas
276      c = '"'
277
278def ucode(s):
279  return str(s)#,'utf-8')
280
281def ucodeSiLinux(s):
282  chars_w_l=[("\xc2\x92","\xe2\x80\x99")]
283  try:
284    if esLinux:
285      # Es interesante saber por que se ha comentado esta linea
286      # en tiempos ignotos era necesario hacer una conversion entre lo que devolvia el server
287      # y nuestro script en el cliente. Antes todo era bytes y ahora ya son strings, si intentamos
288      # codificar un string sobre un string, python3 no lo soporta.
289      #s=str(s, encoding='UTF-8')
290      for ch_w_l in chars_w_l:
291        s=s.replace(ch_w_l[0],ch_w_l[1])
292  except Exception as e:
293     Llog(str(e))
294
295  return s
296
297def msg(mod,txt):
298  #sacar texto en el propio documento
299  texto=mod.Text
300  cursor=texto.createTextCursor()
301  cursor.gotoEnd(0)
302  cursor.String=txt
303 
304def uts(s):
305  #Pasar cadena unicode a string
306  i=0
307  t=""
308 
309  while i<len(s):
310    c=s[i]
311    if ord(c)>255:
312      c=quitarFF(c)
313    t=t+chr(ord(c))
314    i=i+1
315
316  return t
317
318def quitarFF(pal):
319  #Eliminar caracteres unicode superiores a 255
320  n=ord(pal)
321  if n==8216 or n==8219 or n==8224:
322    ret="'"
323  elif n==8221:
324    ret=chr(148)
325  elif n==8220:
326    ret=chr(147)
327  elif n==8217:
328    ret=chr(146)
329  else:
330    ret="_"
331  return ret
332
333def escesp(c,cesp):
334  #Ver si hay que considerar el caracter como un caracter especial
335  if ord(c)>255:
336    n=ord(c)
337    if n==8216 or n==8217 or n==8219 or n==8224:
338      return False
339    else:
340      return True
341  elif cesp.find(c)>-1:
342    return True
343  else:
344    return False
345
346def isnumber(s):
347  #Comprobar si el contenido de la cadena s es un número
348  #Retorno: True, si es un número
349  #         False, si no es un número
350  return uts(s).replace(".","").replace(",","").replace(" ","").replace("\t","").replace("'","").isdigit()
351
352def Query(datos):
353  #Petición al servidor, esperando su respuesta
354  #Entrada: datos: Datos a enviar al servidor
355  #Retorno: Respuesta del servidor (o None)
356  import urllib
357  params = urllib.urlencode({'salt4msg': datos})
358  #f = urllib.urlopen("http://192.168.163.153/?%s" % params)
359  #fsrv = urllib.urlopen("http://localhost/salt/?%s" % params) # Con Tomcat
360  fsrv = urllib.urlopen("http://localhost:8080/?%s" % params) # Sin Tomcat
361  #f = urllib.urlopen("http://salt.desar.cult.gva.es/?%s" % params)
362  datos=fsrv.read()
363  if datos==None or datos[0]=="<":
364    datos=None
365    #No hay servidor
366    import os,time
367    f=open(os.path.abspath(usrPath+'/sltsrv.config'),'rb')
368    scfg=f.read()
369    f.close()
370    cfg=eval(scfg)
371    if 'entorn' in cfg:
372      if 'sltsrvexe' in cfg['entorn']:
373        if 'sltsrvpath' in cfg['entorn']:
374          sltsrvpath=os.path.abspath(cfg['entorn']['sltsrvpath'])
375          os.chdir(sltsrvpath)
376        if 'sltsrvexe' in cfg['entorn']:
377          sltsrvargs=cfg['entorn']['sltsrvexe']
378          sltsrvexe=os.path.abspath(sltsrvargs[0])
379        if esLinux:
380          modo=os.P_NOWAIT
381        else:
382          modo=os.P_DETACH
383        os.spawnve(modo,sltsrvexe,sltsrvargs,os.environ)
384        i=5
385        while i>0:
386          time.sleep(2)
387          import urllib
388          fsrv = urllib.urlopen("http://localhost/salt/?%s" % params)
389          datos=fsrv.read()
390          if datos==None or datos[0]=="<":
391            i=i-1
392            datos=None
393          else:
394            break
395        if datos==None or datos[0]=="<": 
396          msg=MsgWindow('Cal iniciar el servidor Salt4')
397      else:
398        msg=MsgWindow('Cal iniciar el servidor Salt4')
399  return datos 
400
401def socketConnect():
402  #return "web" # Conexion a de web service (sltsrw)
403  try:
404    sck=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
405    sck.connect(('localhost',20001))
406  except:
407    #iniciar server
408    import os,time
409    f=open(os.path.abspath(usrPath+'/sltsrv.config'),'rb')
410    scfg=f.read()
411    f.close()
412    cfg=eval(scfg)
413    if 'entorn' in cfg:
414      if 'sltsrvexe' in cfg['entorn']:
415        if 'sltsrvpath' in cfg['entorn']: 
416          sltsrvpath=os.path.abspath(cfg['entorn']['sltsrvpath'])
417          os.chdir(sltsrvpath)
418        if 'sltsrvexe' in cfg['entorn']:
419          sltsrvargs=cfg['entorn']['sltsrvexe']
420          sltsrvexe=os.path.abspath(sltsrvargs[0])
421        if esLinux:
422          modo=os.P_NOWAIT
423        else:
424          modo=os.P_DETACH
425        os.spawnve(modo,sltsrvexe,sltsrvargs,os.environ)
426        i=5
427        while i>0:
428          try:
429            time.sleep(2)
430            sck.connect(('localhost',20001))
431          except:
432            i=i-1
433          else:
434            break
435        if i<=0:
436          msg=MsgWindow('Cal iniciar el servidor Salt4')
437          sck=None
438      else:
439        msg=MsgWindow('Cal iniciar el servidor Salt4')
440        sck=None
441  return sck
442
443def ListaDoc(doc,mod,colTx,colPalDu,comando):
444  #
445  #   Pasar lista de palabras al documento.
446  #   Se pasan al documento párrafos completos
447  #   doc: documento
448  #   mod: currentComponent (para crear Anotaciones)
449  #   colTx: lista de palabras
450  #   colPalDu:lista de palabras dudosas
451  #   comando: comando ejecutado
452  #
453  doc.gotoStart()   #inicio del párrafo
454  i=0
455  j=0
456  pal,cf,fp=PalabraSig(doc)
457  while pal != "": #and j<len(colTx):
458    if j>=len(colTx):
459      #Sobran palabras en el documento
460      hayespsig=True
461      doc.cur.String=""
462      if doc.cur.goRight(1,1)==True:
463        if doc.cur.String!=" ":
464          hayespsig=False
465        doc.cur.collapseToStart()
466      if doc.cur.goLeft(1,1) == True:
467        if doc.cur.String==" " and hayespsig:
468          #Eliminar espacio anterior
469          doc.cur.String=""
470        else:
471          doc.cur.collapseToEnd()
472    elif colTx[j][tx_nordori]>i:
473      #Eliminar palabra del documento
474      hayespsig=True
475      doc.cur.String=""
476      if doc.cur.goRight(1,1)==True:
477        if doc.cur.String!=" ":
478          hayespsig=False
479        doc.cur.collapseToStart()
480      if doc.cur.goLeft(1,1) == True:
481        if doc.cur.String==" " and hayespsig:
482          #Eliminar espacio anterior
483          doc.cur.String=""
484        else:
485          doc.cur.collapseToEnd()
486    elif colTx[j][tx_nordori]==i:
487      #Sustituir/insertar palabras
488      if j in colPalDu and mod!=None:
489        #Hay que anotar palabra dudosa
490        nota=mod.createInstance("com.sun.star.text.TextField.Annotation")
491        nota.Author="Salt4"+"."+colPalDu[j]['dtr']+"."+ comando
492        nota.Content="_clau=" + colPalDu[j]['Clave'] + "_\n" + colPalDu[j]['Info']
493        #mod.Text.insertTextContent(doc.cur, nota, False)
494        doc.cur.Text.insertTextContent(doc.cur, nota, False)
495      pal=colTx[j][tx_paltext]
496      while j < len(colTx)-1:
497        if colTx[j + 1][tx_nordori] == i:
498          j = j + 1
499          pal = pal + ' ' + colTx[j][tx_paltext]
500        else:
501          break
502      #doc.cur.String=pal 
503      if pal!="_":
504        pal=ucodeSiLinux(pal)
505        doc.cur.String=pal
506      j = j + 1
507      doc.cur.collapseToEnd()
508    #Siguiente palabra
509    i=i+1
510    pal,cf,fp=PalabraSig(doc)
511   
512def DocLista(doc,colTx,lscurs=[]):
513  #
514  #   Obtener una lista de palabras a partir de un documento
515  #
516  #   Entrada: doc: documento cuyas palabras hay que pasar a la lista.
517  #
518  #   Funcionamiento: Se pasan a la lista párrafos completos o sentencias si porsent=True
519  #
520  #   Salida:  colTx: Lista de palabras del documento
521  #
522 
523  doc.gotoStart()   #inicio del párrafo
524  colTx = []
525  i=0
526  pal,cf,fp=PalabraSig(doc,lscurs)
527  while pal != "":
528    #Hay nueva palabra
529    if len(pal)==1 and ord(pal)>255:
530      pal=quitarFF(pal)
531    if len(cf)==1 and ord(cf)>255:
532      cf=quitarFF(cf)
533    pal=uts(pal)
534    txpal=(pal,i,uts(cf),0,0)
535    colTx.append(txpal)
536    #Siguiente palabra (si no es fin de párrafo)
537    #if cur.isEndOfParagraph() or fp==1:
538    if doc.isEnd() or fp==1:
539      break
540    i = i + 1
541    pal,cf,fp = PalabraSig(doc,lscurs)
542  return colTx
543
544def xTrad(model,vcursor,comando):
545  #1. Crea la ventana oPro (indicador de progreso)
546  #2. Llama a Trad en otro thread
547  #Los dos threads se comunican a traves de un evento para "cancelar proceso"
548  sck=socketConnect()
549  oPro=ProWindow()
550  if sck!=None:
551    sck.close()
552    import threading
553    t=threading.Thread(target=Trad,args=(model,vcursor,args,oPro))
554    t.start()
555
556def Trad(model,vcursor,comando,oPro):
557  #Traducir el documento actual o una parte de al
558  #Entrada: model: 
559  #         vcursor: view cursor en el documento a traducir
560  #         comando: traduccion directa o inversa
561  #         oPro: StatusIndicator (proceso)
562  #Traduccion por parrafos
563  #Se traduce desde el parrafo en el que este el cursor.
564  #Si hay seleccion se traduce solo la parte seleccionada
565  ti=time.clock()
566 
567  try:
568    text=vcursor.getText()
569    cur=text.createTextCursorByRange(vcursor.getStart())
570    i=n=0
571    essel=False
572    sel=model.getCurrentSelection()
573    while i<sel.getCount():
574      if len(sel.getByIndex(i).getString())>0:
575        essel=True
576        n=n+sel.getByIndex(i).getString().count(' ')+1
577      i=i+1
578    doc=sltDoc(model,cur,unit='s')
579    oPro.start("Salt",100)
580    sck=socketConnect()
581    if doc.ProcStart():
582      #1. Traduccion del documento
583      if not essel:
584        TradCur(doc,comando,sck,oPro,u"Salt [document]")
585      else:
586        #2. Traducir seleccion
587        doc.wordstot=(float(n))*1.1
588        i=0
589        while i<sel.getCount():
590          if len(sel.getByIndex(i).getString())>0:
591            text=sel.getByIndex(i).getText()
592            cur=text.createTextCursorByRange(sel.getByIndex(i).getStart())
593            curfin=text.createTextCursorByRange(sel.getByIndex(i).getEnd())
594            doc.Refresh(cur,curfin)
595            TradCur(doc,comando,sck,oPro,u"Salt [selecció]")
596          i=i+1
597 
598      #3. Traduccion de notas a pie de pagina
599      if doc.ProcSeguir() and not essel:
600        tbs=model.getFootnotes()
601        i=0
602        n=tbs.getCount()
603        while i<n:
604          tb=tbs.getByIndex(i)
605          ccur=tb.createTextCursor()
606          doc.Refresh(ccur)
607          TradCur(doc,comando,sck,oPro,u"Salt[notes peu]")
608          i=i+1
609 
610      #4. Traduccion de notas al final del documento
611      if doc.ProcSeguir() and not essel:
612        tbs=model.getEndnotes()
613        i=0
614        n=tbs.getCount()
615        while i<n:
616          tb=tbs.getByIndex(i)
617          ccur=tb.createTextCursor()
618          doc.Refresh(ccur)
619          TradCur(doc,comando,sck,oPro,u"Salt[notes final]")
620          i=i+1
621 
622      #5. Traduccipn de tablas (solo si no es seleccion)
623      if doc.ProcSeguir() and not essel:
624        tbs=model.getTextTables()
625        i=0
626        n=tbs.getCount()
627        while i<n:
628          tb=tbs.getByIndex(i)
629          cnames=tb.getCellNames()
630          for cname in cnames:
631            cell=tb.getCellByName(cname)
632            ccur=cell.createTextCursor()
633            doc.Refresh(ccur)
634            TradCur(doc,comando,sck,oPro,u"Salt[taules]")
635          i=i+1
636 
637      #6. Traduccion de notas a pie de pagina
638      if doc.ProcSeguir() and not essel:
639        tbs=model.getTextFrames()
640        i=0
641        n=tbs.getCount()
642        while i<n:
643          tb=tbs.getByIndex(i)
644          ccur=tb.createTextCursor()
645          doc.Refresh(ccur)
646          TradCur(doc,comando,sck,oPro,u"Salt[marcs]")
647          i=i+1
648 
649      #7. Traduccion de cabecera (solo si no es seleccion)
650      if doc.ProcSeguir() and not essel:
651        tbs=model.StyleFamilies.getByName("PageStyles")
652        tb=tbs.getByName("Standard")
653        if tb.HeaderText!=None:
654          ccur=tb.HeaderText.createTextCursor()
655          doc.Refresh(ccur)
656          TradCur(doc,comando,sck,oPro,u"Salt[capçalera]")
657 
658  except Exception as e:
659    pass
660  #finally:
661  doc.ProcEnd()
662  oPro.end()
663  #sck.close()
664  oPro=None
665  doc=None
666  vcursor=None
667  model=None   
668  if sck!=None and sck!="web":
669    sck.close()
670 
671  tf=time.clock()
672  print("tiempo:",tf-ti)
673  f.close()
674# def Trad
675
676
677def TradCur(doc,comando,sck,oPro,oProText=""):
678  #Traduccion de una parte del documento (cursor)
679  #Entrada: doc: contiene un cursor a la parte del documento a procesar
680  #         cur: cursor a las frases a traducir
681  #         comando: traduccion directa o inversa
682  #         sck: Socket con el servidor
683  #         oPro: indicador de proceso
684  #ret=doc.gotoStart()
685  ret=True
686  while ret==True and sck!=None and doc.ProcSeguir() and not doc.isEndSel():
687    try:
688      #1. Obtener lista de palabras
689      colPalDu={}
690      colTx=[]
691      doc.Marca()
692      colTx=doc.DocLista(colTx)
693      #doc.Marca2()
694     
695      if len(colTx)>0:
696        #Refrescar barra de progreso
697        doc.addNumWords(len(colTx))
698        oPro.setValue(100-doc.percentPte())
699        oPro.setText(oProText)
700         
701        #1. La palabra saltstop en el texto detiene el proceso
702        if colTx[0][0].lower()=='saltstop':
703          st=sltEstado(doc.model)
704          st.Stop()
705          break
706
707        #2. Orden de traducción
708        datos=str((comando,(colTx,colPalDu))).encode('latin-1')
709        if sck=="web":
710          datos=Query(datos).encode('latin-1')
711        else:
712          sck.send(datos)
713          datos=sck.recv(128000).decode('latin-1')
714        comandorec,(colTx,colPalDu)=eval(datos)
715   
716        #3. Actualizar documento (si no lo anula el servidor)
717        if comandorec!="void":
718          doc.Sync()
719          try:
720           
721            doc.ListaDoc(colTx,colPalDu,comando)
722          except Exception as e:
723           
724            Llog(str(e))
725            #doc.Sync2()
726
727         
728 
729      ret=doc.cur.gotoNextWord(0)
730      #if ret==True:
731        #ret=not doc.isEnd()
732       
733      #if ret==True:
734        #ret=doc.gotoStart()
735   
736    except Exception as e:
737      break
738
739def _Trad_(model,vcursor,comando,oPro):
740  #Traducir el documento actual o una parte de él
741  #Entrada: model: 
742  #         vcursor: view cursor en el documento a traducir
743  #         comando: traducción directa o inversa
744  #         oPro: StatusIndicator (proceso)
745  #Traducción por párrafos
746  #Se traduce desde el párrafo en el que está el cursor.
747  #Si hay selección se traduce sólo la parte seleccionada
748  fintrad=False
749  saltatrad=False
750  try:
751    text=vcursor.getText()
752    cur=text.createTextCursorByRange(vcursor.getStart())
753    if len(vcursor.String)>0:
754      #Marcar inicio y fin de range
755      selcur=text.createTextCursorByRange(vcursor.getStart())
756      selcur.gotoRange(vcursor.getEnd(),1)
757    else:
758      selcur=None
759    doc=sltDoc(model,cur,unit='s',selcur=selcur)
760    #sck=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
761    #sck.connect(('localhost',20001))
762    oPro.start("Salt",100)
763    sck=socketConnect()
764    ret=doc.gotoStart()
765    while ret==True and sck!=None:
766      #1. Obtener lista de palabras
767      lscurs=[]
768      colPalDu={}
769      colTx=[]
770      doc.Marca()
771      colTx=DocLista(doc,colTx,lscurs)
772      if len(colTx)>0:
773        #0. Posición actual
774        doc.addNumWords(len(colTx))
775        oPro.setValue(100-doc.percentPte())
776        oPro.setText("Salt [document]")
777       
778        #1. Comprobar palabras de control
779        if colTx[0][0].lower()=='saltstop':
780          fintrad=True
781          break
782        elif colTx[0][0].lower()=='saltsalt':
783          sdes=model.createSearchDescriptor()
784          sdes.SearchString="Saltcont"
785          rdes=model.findNext(doc.cur.getEnd(),sdes)
786          doc.cur.gotoRange(rdes.getEnd(),0)
787        else:
788          #2. Orden de traducción
789          datos=str((comando,(colTx,colPalDu))).encode('latin-1')
790          sck.send(datos)
791          datos=sck.recv(128000).decode('latin-1')
792          comandorec,(colTx,colPalDu)=eval(datos)
793       
794          #3. Actualizar documento (si no lo anula el servidor)
795          if comandorec!="void":
796            doc.Sync()
797            ListaDoc(doc,model,colTx,colPalDu,comando)
798     
799          #4. Traducción de notas al pie
800          if lscurs!=None:
801            for cur in lscurs:
802              _TradAux_(model,cur,comando,sck)
803           
804      ret=doc.Next()
805      if ret==True:
806        ret=doc.gotoStart()
807       
808    #5. Traducción de tablas (solo si no es selección)
809    if not fintrad: # and not doc.esRange():
810      tbs=model.getTextTables()
811      i=0
812      n=tbs.getCount()
813      while i<n:
814        oPro.setValue(100*i/n)
815        oPro.setText("Salt [taules]")
816        tb=tbs.getByIndex(i)
817        cnames=tb.getCellNames()
818        for cname in cnames:
819          cell=tb.getCellByName(cname)
820          ccur=cell.createTextCursor()
821          _TradAux_(model,ccur,comando,sck,oPro,100*i/n,"Salt[taules]")
822        i=i+1
823       
824  finally:
825    oPro.end()
826    sck.close()
827    oPro=None
828    doc.Close()
829    vcursor=None
830    model=None
831
832def _TradAux_(model,cur,comando,sck,oPro=None,valPro=0,txtPro=""):
833  #Traducción auxiliar de frases al margen del documento
834  #Entrada: model: 
835  #         cur: cursor a las frases a traducir
836  #         comando: traducción directa o inversa
837  #         sck: Socket con el servidor
838  #         oPro: Si !=None, refrescar indicador de proceso
839  doc=sltDoc(model,cur,unit='s')
840  ret=doc.gotoStart()
841  while ret==True and sck!=None:
842    try:
843      #1. Obtener lista de palabras
844      colPalDu={}
845      colTx=[]
846      doc.Marca()
847      colTx=DocLista(doc,colTx)
848     
849      #Refrescar barra de progreso
850      if oPro!=None:
851        oPro.setValue(valPro)
852        oPro.setText(txtPro)
853       
854      #2. Orden de traducción
855      datos=str((comando,(colTx,colPalDu))).encode('latin-1')
856      sck.send(datos)
857      datos=sck.recv(128000).decode('latin-1')
858      comandorec,(colTx,colPalDu)=eval(datos)
859   
860      #3. Actualizar documento (si no lo anula el servidor)
861      if comandorec!="void":
862        doc.Sync()
863        ListaDoc(doc,model,colTx,colPalDu,comando)
864 
865      ret=doc.Next()
866      if ret==True:
867        ret=doc.gotoStart()
868    except:
869      break
870def Ajuda(desktop):
871  #Iniciar html ayuda
872  ajuPath=""
873  if 'entorn' in cfg:
874    if 'helpath' in cfg['entorn']:
875      ajuPath=cfg['entorn']['helpath']
876  if esLinux:
877    if ajuPath=="":
878      ajuPath="/usr/share/salt4/WebHelp/Ajuda_SALT.htm"
879    os.system("firefox "+ajuPath+" &")
880  else:
881    if ajuPath=="":
882      ajuPath=os.path.abspath(srvPath+"\WebHelp\Ajuda_SALT.htm")
883    os.startfile(ajuPath)
884  #url=unohelper.systemPathToFileUrl(ajuPath) 
885  #desktop.loadComponentFromURL(url,"_blank",0,())
886 
887def Prueba(model,doc):
888  print("inicio")
889  ret=True
890  while ret:
891    ret=doc.cur.gotoEndOfSentence(1)
892    print (ret,uts(doc.cur.String))
893    doc.cur.collapseToEnd()
894    ret=doc.Next()
895  print("fin")
896#def sysPaths():
897  ##incluir paths en sys.path
898  #fin1=fin2=False
899  #for root,dirs,files in os.walk('/'):
900    #for name in files:
901      #if name=='sltsrv.bat':
902        #sys.path.append(root)
903        #fin2=True
904      #elif name=='swriter.exe' and root.find('program')>=0:
905        #sys.path.append(root)
906        #sys.path.append(root+'/program/python-core-2.3.4')
907        #sys.path.append(root+'/program/python-core-2.3.4/lib')
908        #fin1=True
909    #if fin1 and fin2:
910      #break
911
912def Rev(oCtv,comando):
913  #Revisión de un documento
914  oCtv.BuscaNotas()
915  if not oCtv.Siguiente(ini=-1):
916    oCtv.windowClose()
917 
918class sltDoc:
919  """Documento para traducir o revisar.
920     Pueden estar formado por sentencias o párrafos o cualquier otra unidad
921     """
922  def __init__(self,model,cur,unit="p",pos=False,curfin=None):
923    #unit indica si la unidad de proceso son sentencias o párrafos
924    #pos indica si hay que mantener la posición del cursor
925    #curfin !=None: se trata de una selección y no podemos pasar más allá de curfin
926    self.cnor='abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMNÑOPQRSTUVWXYZáéíóúàèòïüÁÉÍÓÚÀÈÒÏÜ'
927    try:
928      self.cesp=",.;:{}[]<>?¿¡!()\'%\"" + '\u0027'# + ucode(chr(145)) + ucode(chr(146)) + ucode(chr(147)) + ucode(chr(148)) + ucode(chr(132)) + ucode(chr(188)) + ucode(chr(10)) + ucode(chr(12))  + ucode(chr(13))+ ucode(chr(9)) + ucode(chr(11)) + ucode(chr(160)) + ucode(chr(150)) + ucode(chr(151)) + ucode(chr(215)) + ucode(chr(247)) + ucode('\xab') + ucode('\xbb') + '\u201c' + '\u201d' + '\u2013' + '\u2014' + '\u2022' #+ ucode(chr(171)) + ucode(chr(187))
929    except Exception as e:
930      pass
931    self.model=model
932    self.cur=cur #cursor en el documento
933    text=self.cur.getText()
934    self.dcur=text.createTextCursorByRange(self.cur.getStart()) #duplicado de cur
935    self.unit=unit[0] #frase virtual: s (entence), p (aragrph)
936    self.poscursor=0
937    self.tr=None
938    self.curfin=curfin
939    self.wordspro=float(0)
940    self.wordstot=(float(model.WordCount))*1.1
941    self.paleliminada=False
942    self.nounicarizda=False
943   
944  def Refresh(self,cur,curfin=None):
945    self.cur=cur
946    text=self.cur.getText()
947    self.dcur=text.createTextCursorByRange(self.cur.getStart()) #duplicado de cur
948    self.curfin=curfin
949   
950  def listaGrobjs(self):
951    #Obtener la lista de graficos incluidos en el mismo documento "como caracter"
952    #Retorno: Lista (o [])
953    #ASCHAR=uno.getConstantByName("com.sun.star.text.TextContentAnchorType.AS_CHARACTER")
954    gros=self.model.getGraphicObjects()
955    i=0
956    lista=[]
957    while i<gros.getCount():
958      gro=gros.getByIndex(i)
959      try:
960        c=self.cur.getText().createTextCursorByRange(gro.getAnchor().getStart())
961        lista.append(gro)
962      except:
963        pass
964      i=i+1
965    return lista
966 
967  def saltaGrobjs(self):
968    #Salta imágenes grobjs
969    #Retorno: True/False si/no ha habido imágenes
970    _ret=False
971    i=0
972    while i<len(self.lsgrobj):
973      if self.cur.getText().compareRegionStarts(self.cur.getStart(),self.lsgrobj[i].getAnchor().getStart())==0:
974        #saltar un caracter
975        self.cur.goRight(1,0)
976        self.saltaGrobjs()
977        _ret=True
978        break
979      i=i+1
980    return _ret
981 
982  def gotoStart(self,selec=0):
983    #Ir al inicio de la frase
984    ret=True
985    #if self.unit=="s":
986      #ret=self.cur.gotoStartOfSentence(selec)
987    #else:
988      #ret=self.cur.gotoStartOfParagraph(selec)
989    if self.selcur!=None:
990      #la primera palabra no puede terminar antes de rstart
991      text=self.cur.getText()
992      rcur=text.createTextCursorByRange(self.cur)
993      ret=rcur.gotoEndOfWord(0)
994      while text.compareRegionStarts(rcur,self.selcur.getStart())==1:
995        #palabra fuera de la selección
996        ret=rcur.gotoNextWord(0)
997        ret=rcur.gotoEndOfWord(0)
998        self.cur.gotoRange(rcur,0)
999      self.cur.gotoStartOfWord(0)
1000    return ret
1001 
1002  def gotoEnd(self,selec=0):
1003    #Ir al final de la frase
1004    if self.unit=="s":
1005      ret=self.cur.gotoEndOfSentence(selec)
1006    else:
1007      ret=self.cur.gotoEndOfParagraph(selec)
1008    if self.selcur!=None:
1009      #la última palabra no puede empezar después de fin de selección
1010      text=self.cur.getText()
1011      rcur=text.createTextCursorByRange(self.cur)
1012      ret=rcur.gotoStartOfWord(0)
1013      while text.compareRegionStarts(rcur,self.selcur.getEnd())==-1:
1014        #palabra fuera de la selección
1015        ret=rcur.gotoPreviousWord(0)
1016        ret=rcur.gotoStartOfWord(0)
1017        self.cur.gotoRange(rcur,0)
1018    return ret
1019 
1020  def Next(self):
1021    #Siguiente frase
1022    #Retorno: True/False: si/no hay nueva frase y el cursor queda en la nueva frase
1023    #Saltar imágenes en el texto
1024    #if self.saltaGrobjs():
1025      #ret=self.cur.gotoStartOfSentence(0)
1026    #else:
1027      #ret=self.cur.gotoNextSentence(0)
1028    #ret=self.cur.gotoNextSentence(0)
1029    #if self.curant!=None:
1030      #ret=True
1031      #while ret and  self.cur.getText().compareRegionStarts(self.cur.getStart(),self.curant.getStart())>=0:
1032        ##No podemos entrar dos veces en la misma posición
1033        #ret=self.cur.gotoNextWord(0)
1034    #Si hay imágenes, saltarlas
1035    self.cur.collapseToStart()
1036    ret=self.cur.goRight(1,1)
1037    while ret and len(self.cur.String)==0:
1038      #Responde True pero no avanza: es una imagen: saltarla
1039      self.cur.collapseToEnd()
1040      ret=self.cur.goRight(1,1)
1041    self.cur.collapseToStart()
1042   
1043    #ret=self.cur.gotoNextWord(0)
1044    ret=self.cur.gotoNextSentence(0)
1045    if not ret:
1046      #ret=self.cur.goRight(2,0) # lo que había
1047      ret=self.cur.goRight(1,1)
1048      while ret:
1049        #hemos podido ir 1 caracter a la derecha ...
1050        if len(self.cur.String)>0:
1051          #a) el caracter está seleccionado: lo normal
1052          self.cur.collapseToEnd()
1053          break
1054        else:
1055          #b) no hay caracter: es imagen (saltar)
1056          self.cur.collapseToEnd()
1057          ret=self.cur.goRight(1,1)
1058      self.cur.collapseToEnd()
1059    if ret and self.selcur!=None:
1060      #Comprobar que no nos salimos de una selección (range)
1061      text=self.cur.getText()
1062      rcur=text.createTextCursorByRange(self.cur)
1063      rcur.collapseToEnd()
1064      if text.compareRegionStarts(rcur,self.selcur.getEnd())==-1:
1065        #Fuera de range
1066        ret=False     
1067    if ret==True:
1068      ret=self.gotoStart(0)
1069    return ret
1070 
1071  def NextWord(self):
1072    #Ir a la siguiente palabra (excepto si se ha eliminado una palabra)
1073    if not self.paleliminada:
1074      ret=self.cur.gotoNextWord(0)
1075    else:
1076      ret=True
1077      self.paleliminada=False
1078      self.nounicarizda=True
1079    return ret
1080 
1081  def NextChar(self):
1082    #Siguiente caracter, manteniendo los anteriores
1083    #Devuelve False si no hay más caracteres o es eop/eos
1084    #n=len(self.cur.String)
1085    trs=self.cur.getStart()
1086    self.cur.collapseToEnd()
1087    eop=self.isEnd()
1088    if not eop:
1089      eop=self.cur.isEndOfParagraph()
1090    #self.cur.goLeft(n,0)
1091    #self.cur.goRight(n,1)
1092    self.cur.gotoRange(trs,1)
1093    if not eop:
1094      #text=self.cur.getText()
1095      #rcur=text.createTextCursorByRange(self.cur)
1096      lenpal=len(self.cur.String)
1097      ret=self.cur.goRight(1,1)
1098      if ret:
1099        if len(self.cur.String)==lenpal:
1100          #Responde True pero no avanza: es una imagen, considerar como eop/eos
1101          ret=False
1102          #if lenpal>0:
1103          #Para no incluir la imagen junto a la palabra
1104          self.cur.goLeft(1,1)
1105          #self.cur.gotoRange(rcur,1)
1106    else:
1107      ret=False
1108    return ret
1109 
1110  def Char(self):
1111    #Devuelve el caracter o selección actual
1112    return self.cur.String
1113 
1114  def isEnd(self):
1115    #Ver si es fin de frase
1116    #Retorno: True si es fin de frase
1117    ret=False
1118    if self.unit=="s":
1119      ret=self.cur.isEndOfSentence()
1120      if ret:
1121        #evitar el caso núm.
1122        self.dcur.gotoRange(self.cur.getEnd(),0)
1123        self.dcur.gotoStartOfWord(1)
1124        if uts(self.dcur.String).lower()=="n\xfam.":
1125          #parche para evitar que detecte endOfSentence por el punto
1126          ret=False
1127      if not ret:
1128        ret=self.cur.isEndOfParagraph()
1129    else:
1130      ret=self.cur.isEndOfParagraph()
1131    return ret
1132 
1133  def isEndSel(self):
1134    #Ver si es fin de seleccionn
1135    #Retorno: True si es fin de seleccion
1136    ret=False
1137    if self.curfin!=None:
1138      text=self.cur.getText()
1139      #rcur=text.createTextCursorByRange(self.cur)
1140      #rcur.collapseToEnd()
1141      if text.compareRegionStarts(self.cur.getStart(),self.curfin.getEnd())!=1:
1142        #Fuera de range
1143        ret=True
1144    return ret
1145 
1146  def addNumWords(self,n):
1147    #Anyadir al contador de palabras procesadas
1148    self.wordspro=self.wordspro+n
1149   
1150  def percentPte(self):
1151    #Devuelve el % de palabras pte hasta el final del documento
1152    if self.wordspro>self.wordstot:
1153      self.wordspro=self.wordstot
1154    n=100*((self.wordstot-self.wordspro)/self.wordstot)
1155    if n<=0:
1156      n=1
1157    if n>=100:
1158      n=99
1159    return n
1160 
1161  def Content(self):
1162    #Devuelve el contenido (texto) de la frase
1163    self.gotoStart(0)
1164    self.gotoEnd(1)
1165    return self.cur.String
1166 
1167  def Caracs(self):
1168    self.cur.gotoStart(0)
1169    ret=self.cur.goRight(1,1)
1170    while ret:
1171      print (uts(self.cur.String))
1172      if self.isEnd():
1173        print ('EOF1')
1174      self.cur.collapseToEnd()
1175      if self.isEnd():
1176        print ('EOF2')
1177      ret=self.cur.goRight(1,1)
1178
1179  def Marca(self):
1180    #Guardar la posicion del cursor
1181    self.tr=self.cur.getStart()
1182   
1183  def Sync(self):
1184    self.cur.gotoRange(self.tr,0)
1185
1186  def Marca2(self):
1187    #Guardar la posicion del cursor
1188    self.tr2=self.cur.getStart()
1189   
1190  def Sync2(self):
1191    if self.tr2!=None:
1192      self.cur.gotoRange(self.tr2,0)
1193
1194  def esMarca2(self):
1195    #Comprueba si self.cur ha alcanzado Marca2 (self.tr2)
1196    #Retorno: True si self.cur ha alcanzado a self.tr2; si no lo ha alcanzado False
1197    if self.tr2!=None:
1198      if self.cur.getText().compareRegionStarts(self.cur.getStart(),self.tr2)==1:
1199        return False
1200      else:
1201        return True
1202
1203  def ProcStart(self):
1204    #Inicio de proceso: anotar marca 'en proceso'
1205    #Retorno: True si podemos seguir; False si no podemos seguir
1206
1207    _ret=True
1208    try:
1209      descri=self.model.DocumentProperties.Description
1210    except Exception as e:
1211      descri=""
1212    if len(descri)>=8:
1213      if descri[-8:]=="Saltstop":
1214        #Quitar parca stop y poner marca 'en proceso'
1215        descri=descri[0:-8]+"Saltstop"
1216        self.model.DocumentProperties.Description=descri
1217      elif descri[-8:]=="Saltproc":
1218        #Ya hay un procso en marcha
1219        _ret=False
1220        #descri=descri+"Saltproc"
1221        #self.model.DocumentInfo.Description=descri
1222    else:
1223      #Poner marca 'en proceso' (si no esta ya puesta)
1224      descri=descri+"Saltproc"
1225      # LliureX
1226      self.model.DocumentProperties.Description=descri
1227    return _ret
1228 
1229  def ProcEnd(self):
1230    #Fin del proceso: quitar marcas
1231    descri=self.model.DocumentProperties.Description
1232    if len(descri)>=8:
1233      if descri[-8:]=="Saltstop" or descri[-8:]=="Saltproc":
1234        #Quitar marca
1235        descri=descri[0:-8]
1236        self.model.DocumentProperties.Description=descri
1237 
1238  def ProcSeguir(self):
1239    #Comprobar si se debe seguir o cancelar el proceso
1240    #Retorno: True: seguir proceso; False: cancelar
1241    _ret=True
1242    descri=self.model.DocumentProperties.Description
1243    # Self document info search
1244    if len(descri)>=8:
1245      if descri[-8:]=="Saltstop":
1246        _ret=False
1247    return _ret
1248   
1249  def DocLista(self,colTx):
1250    #
1251    #   Obtener una lista de palabras a partir del documento actual
1252    #
1253    #   Funcionamiento: Se pasan a la lista parrafos completos o sentencias si porsent=True
1254    #
1255    #   Salida:  colTx: Lista de palabras del documento
1256    #
1257    colTx = []
1258    i=0
1259    _ret=True
1260    #ret=self.cur.gotoStartOfWord(0)
1261    ret=True
1262    while ret:
1263      #Hay nueva palabra
1264      _ret=self.cur.gotoEndOfWord(1)
1265      if _ret:
1266        pal=self.cur.String
1267        self.dcur.gotoRange(self.cur.getEnd(),0)
1268        if self.dcur.goRight(1,1):
1269          cf=uts(self.dcur.String)
1270        else:
1271          cf=" "
1272        if cf=="-":
1273          self.dcur.goRight(1,1)
1274          if (self.cnor).find(self.dcur.String[-1])!=-1:
1275            #Guion dentro de la palabra (xxx-xxx)
1276            _ret=self.cur.gotoNextWord(1)
1277            _ret=self.cur.gotoEndOfWord(1)
1278            pal=self.cur.String
1279            self.dcur.gotoRange(self.cur.getEnd(),0)
1280            if self.dcur.goRight(1,1):
1281              cf=uts(self.dcur.String)
1282            else:
1283              cf=" "
1284      else:
1285        #Pueden ser notas
1286        _ret=True
1287        pal=""
1288        self.dcur.gotoRange(self.cur.getStart(),0)
1289        ret=self.dcur.gotoNextWord(0)
1290        text=self.cur.getText()
1291        while ret and self.cur.goRight(1,0):
1292          if text.compareRegionStarts(self.cur.getEnd(),self.dcur.getStart())!=1:
1293            break
1294          elif self.cur.Footnote!=None or self.cur.Endnote!=None:
1295            #es nota
1296            #self.cur.gotoStartOfWord(1)
1297            self.dcur.gotoRange(self.cur.getEnd(),0)
1298            self.cur.gotoStartOfWord(0)
1299            self.cur.gotoRange(self.dcur.getEnd(),1)
1300            pal=self.cur.String
1301            cf=" "
1302            _ret=False
1303            break
1304        if pal=="":
1305          self.cur.gotoStartOfWord(0)
1306          if self.cur.gotoEndOfWord(1):
1307            pal=self.cur.String
1308            if pal!="":
1309              self.dcur.gotoRange(self.cur.getEnd(),0)
1310              if self.dcur.goRight(1,1):
1311                cf=uts(self.dcur.String)
1312              else:
1313                cf=" "
1314            else:
1315              break
1316          else:
1317            break
1318          #break
1319      self.dcur.gotoRange(self.cur.getStart(),0)
1320      self.dcur.collapseToStart()
1321      self.dcur.goLeft(1,1)
1322      if self.dcur.String!="" and self.cesp.find(self.dcur.String)>-1:
1323        #palabra unicaracter a la izda
1324        palesp=uts(self.dcur.String)
1325        txpal=(palesp,i,palesp,0,0)
1326        colTx.append(txpal)
1327        i=i+1
1328      palesp=""
1329      self.dcur.gotoRange(self.cur.getEnd(),0)
1330      self.dcur.collapseToEnd()
1331      self.dcur.goRight(1,1)
1332      if self.dcur.String!="" and self.cesp.find(self.dcur.String)>-1:
1333        if uts(self.dcur.String)!='\n' and uts(self.dcur.String)!='\r' and uts(self.dcur.String)!='\t':
1334          #palabra unicaracter a la dcha
1335          palesp=uts(self.dcur.String)
1336          cf=palesp
1337      #elif self.dcur.String=="-":
1338        ##es guión: tratar como una sola palabra...
1339        #if self.dcur.gotoEndOfWord(1):
1340          ##...si no es guión usado como paréntesis
1341          #if self.dcur.String.find(" ")==-1:
1342            #self.cur.gotoRange(self.dcur.getEnd(),1)
1343            #pal=self.cur.String
1344            #cf=" "
1345      _p=pal.find(')')
1346      if _p==-1:
1347        _p=pal.rfind('.')
1348      if _p==-1:
1349        _p=pal.rfind(' ')
1350      if len(pal)>0 and _p>0 and pal.find("www")==-1 and pal.find("http")==-1 and pal.find("@")==-1:
1351        if pal.find(u".\xba")>0 or pal.find(u".\xaa")>0:
1352          #casos n.º n.ª 7.º 7.ª > nº nª 7º 7ª
1353          pal=pal.replace(".","")
1354        elif pal[-1]=="." and pal[0:-1].isdigit():
1355          # caso xx. saltar todo
1356          pal=""
1357        elif isnumber(pal[_p+1:]):
1358          #caso .xx saltar todo
1359          #pal=""
1360          pass
1361        elif len(pal)>0 and _p>0 and _p<len(pal)-1 and not(isnumber(pal[0:_p]) and isnumber(pal[_p+1:])) and pal.find("-")==-1: # and (pal[_p]==")" or (pal[_p]=="." and isnumber(pal[0:_p]))):
1362          #caso xx.palabra Hay una anotación incluida en la palabra: saltarla
1363          _cur=self.cur.getText().createTextCursorByRange(self.cur.getStart())
1364          if _cur.isStartOfParagraph():
1365            #Para asegurar que es inicio de párrafo
1366            pal=pal[_p+1:]
1367          #_p=pal.find(' ')
1368          #if _p>-1:
1369            #pal=pal[_p:].lstrip() #casos x.x Palabra, provisinalmente desactivado
1370      #if len(pal)>0 and self.cesp.find(pal[0])>-1:
1371      while len(pal)>0 and (self.cesp+u'-').find(pal[0])>-1:
1372        #El primer caracter de pal es car especial (ej: ¡)
1373        ci=uts(pal[0])
1374        pal=pal[1:]
1375        txpal=(ci,i,ci,0,0)
1376        colTx.append(txpal)
1377        i=i+1
1378         
1379      if len(pal)>0 and self.cesp.find(pal[-1])>-1:
1380        #El último car de pal es caracter de fin (ej: un .)
1381        if len(pal)>1:
1382          cf=uts(pal[-1])
1383          pal=uts(pal[0:-1])
1384          #self.cur.goLeft(1,1)
1385          #n=1
1386          while len(pal)>0 and '1234567890'.find(pal[-1])>-1 and cf!='\xba' and cf!='\xaa':
1387            #Eliminar números (son notas?)
1388            pal=uts(pal[0:-1])
1389            #self.cur.goLeft(1,1)
1390            #n=n+1
1391          #self.cur.collapseToEnd()
1392          #self.cur.goRight(n,0)
1393          if pal!="":
1394            txpal=(pal,i,cf,0,0)
1395            colTx.append(txpal)
1396            i=i+1
1397          txpal=(cf,i,cf,0,0)
1398          colTx.append(txpal)
1399          i=i+1
1400        else:
1401          pal=uts(pal)
1402          txpal=(pal,i,pal,0,0)
1403          colTx.append(txpal)
1404          i=i+1
1405      elif len(pal)>0:
1406        #caso normal
1407        #el replace es por si hay guión automático de separación de palabras
1408        pal=uts(pal.strip()).replace("\xad","")
1409        txpal=(pal,i,cf,0,0)
1410        colTx.append(txpal)
1411        i=i+1
1412      if palesp!="":
1413        #palabra unicaracter a la dcha
1414        txpal=(palesp,i,palesp,0,0)
1415        colTx.append(txpal)
1416        i=i+1
1417        self.cur.gotoRange(self.dcur.getEnd(),0)
1418       
1419      #Siguiente palabra (si no es fin de párrafo o frase)
1420      self.cur.collapseToEnd()
1421      self.Marca2()
1422      if self.isEnd() or self.isEndSel():
1423        break
1424      ret=self.cur.gotoNextWord(0)
1425
1426    if ret and not _ret:
1427      #Volver una palabra atrás para no perder la siguiente palabra
1428      self.cur.gotoPreviousWord(0)
1429    return colTx
1430
1431  def ListaDoc(self,colTx,colPalDu,comando):
1432  #
1433  #   Pasar lista de palabras al documento.
1434  #   Se pasan al documento parrafos completos
1435  #   colTx: lista de palabras
1436  #   colPalDu:lista de palabras dudosas
1437  #   comando: comando ejecutado
1438  #   También usa:
1439  #   self.doc: documento actual
1440  #   self.model: currentComponent (para crear Anotaciones)
1441  #
1442    i=0
1443    j=0
1444    _ret=True
1445    #ret=self.cur.gotoStartOfWord(0)
1446    ret=True
1447    while ret:
1448      #Hay nueva palabra
1449      _ret=self.cur.gotoEndOfWord(1)
1450      if _ret:
1451        pal=self.cur.String
1452        self.dcur.gotoRange(self.cur.getEnd(),0)
1453        if self.dcur.goRight(1,1):
1454          cf=uts(self.dcur.String)
1455        else:
1456          cf=" "
1457        if cf=="-":
1458          self.dcur.goRight(1,1)
1459          if (self.cnor).find(self.dcur.String[-1])!=-1:
1460            #Guion dentro de la palabra (xxx-xxx)
1461            _ret=self.cur.gotoNextWord(1)
1462            _ret=self.cur.gotoEndOfWord(1)
1463            pal=self.cur.String
1464            self.dcur.gotoRange(self.cur.getEnd(),0)
1465            if self.dcur.goRight(1,1):
1466              cf=uts(self.dcur.String)
1467            else:
1468              cf=" "
1469      else:
1470        #Pueden ser notas
1471        pal=""
1472        self.dcur.gotoRange(self.cur.getStart(),0)
1473        ret=self.dcur.gotoNextWord(0)
1474        text=self.cur.getText()
1475        while ret and self.cur.goRight(1,0):
1476          if text.compareRegionStarts(self.cur.getEnd(),self.dcur.getStart())!=1:
1477            break
1478          elif self.cur.Footnote!=None or self.cur.Endnote!=None:
1479            #es nota
1480            #self.cur.gotoStartOfWord(1)
1481            self.dcur.gotoRange(self.cur.getEnd(),0)
1482            self.cur.gotoStartOfWord(0)
1483            self.cur.gotoRange(self.dcur.getEnd(),1)
1484            pal=self.cur.String
1485            break
1486        if pal=="":
1487          self.cur.gotoStartOfWord(0)
1488          if self.cur.gotoEndOfWord(1):
1489            pal=self.cur.String
1490            if pal!="":
1491              self.dcur.gotoRange(self.cur.getEnd(),0)
1492              if self.dcur.goRight(1,1):
1493                cf=uts(self.dcur.String)
1494              else:
1495                cf=" "
1496            else:
1497              break
1498          else:
1499            break
1500          #break
1501      self.dcur.gotoRange(self.cur.getStart(),0)
1502      self.dcur.collapseToStart()
1503      self.dcur.goLeft(1,1)
1504      #if not self.nounicarizda and self.dcur.String!="" and self.cesp.find(self.dcur.String)>-1:
1505     
1506      if self.dcur.String!="" and self.cesp.find(self.dcur.String)>-1:
1507        #palabra unicaracter a la izda
1508        palesp=uts(self.dcur.String)
1509        j=self.ListaDocPal(self.dcur,colTx,colPalDu,comando,i,j)
1510        i=i+1
1511      self.nounicarizda=False
1512      palesp=""
1513      self.dcur.gotoRange(self.cur.getEnd(),0)
1514      self.dcur.collapseToEnd()
1515      self.dcur.goRight(1,1)
1516      if self.dcur.String!="" and self.cesp.find(self.dcur.String)>-1:
1517        if uts(self.dcur.String)!='\n' and uts(self.dcur.String)!='\r' and uts(self.dcur.String)!='\t':
1518          #palabra unicaracter a la dcha
1519          palesp=uts(self.dcur.String)
1520      #elif self.dcur.String=="-":
1521        ##es guión: tratar como una sola palabra...
1522        #if self.dcur.gotoEndOfWord(1):
1523          ##...si no es guión usado como paréntesis
1524          #if self.dcur.String.find(" ")==-1:
1525            #self.cur.gotoRange(self.dcur.getEnd(),1)
1526            #pal=self.cur.String
1527      _p=pal.find(')')
1528      if _p==-1:
1529        _p=pal.rfind('.')
1530      if _p==-1:
1531        _p=pal.rfind(' ')
1532      if len(pal)>0 and _p>0 and pal.find("www")==-1 and pal.find("http")==-1 and pal.find("@")==-1:
1533        if pal.find(u".\xba")>0 or pal.find(u".\xaa")>0:
1534          #casos n.º n.ª 7.º 7.ª > nº nª 7º 7ª
1535          pal=pal.replace(".","")
1536        elif pal[-1]=="." and pal[0:-1].isdigit():
1537          # caso xx. saltar todo
1538          pal=""
1539        elif isnumber(pal[_p+1:]):
1540          #caso .xx saltar todo
1541          #pal=""
1542          pass
1543        elif len(pal)>0 and _p>0 and _p<len(pal)-1 and not(isnumber(pal[0:_p]) and isnumber(pal[_p+1:])) and pal.find("-")==-1: #  and (pal[_p]==")" or (pal[_p]=="." and isnumber(pal[0:_p]))):
1544          #pass
1545          #caso xx.palabra Hay un numbering incluida en la palabra: no hacer nada
1546          _cur=self.cur.getText().createTextCursorByRange(self.cur.getStart())
1547          if _cur.isStartOfParagraph():
1548            #Para asegurar que es inicio de párrafo
1549            pal=pal[_p+1:]
1550          #text=self.cur.getText()
1551          #_cur=text.createTextCursorByRange(self.cur.getEnd())
1552          #self.cur.collapseToStart()
1553          #self.cur.goRight(_p+1,0)
1554          #self.cur.gotoRange(_cur.getEnd(),1)
1555      #if len(pal)>0 and self.cesp.find(pal[0])>-1:
1556     
1557      while len(pal)>0 and (self.cesp+u'-').find(pal[0])>-1:
1558        #El primer caracter de pal es car especial (ej: ¡)
1559        text=self.cur.getText()
1560        _cur=text.createTextCursorByRange(self.cur.getEnd())
1561        self.cur.collapseToStart()
1562        self.cur.goRight(1,1)
1563        j=self.ListaDocPal(self.cur,colTx,colPalDu,comando,i,j)
1564        i=i+1
1565        self.cur.collapseToEnd()
1566        self.cur.gotoRange(_cur.getEnd(),1)
1567        pal=self.cur.String
1568
1569      if len(pal)>0 and self.cesp.find(pal[-1])>-1:
1570        #El último car de pal es caracter de fin (ej: un .)
1571        if len(pal)>1:
1572         
1573          cf=uts(pal[-1])
1574         
1575          pal=uts(pal[0:-1])
1576          self.cur.goLeft(1,1)
1577          n=0
1578          while len(self.cur.String)>1 and '1234567890'.find(self.cur.String[-1])>-1 and cf!='\xba' and cf!='\xaa':
1579            #Eliminar números (son notas?)
1580            pal=uts(pal[0:-1])
1581            self.cur.goLeft(1,1)
1582            n=n+1
1583          if self.cur.String!="":
1584            j=self.ListaDocPal(self.cur,colTx,colPalDu,comando,i,j)
1585            i=i+1
1586          self.cur.collapseToEnd()
1587          self.cur.goRight(n,0)
1588          self.cur.goRight(1,1)
1589          j=self.ListaDocPal(self.cur,colTx,colPalDu,comando,i,j)
1590          i=i+1
1591        else:
1592          pal=uts(pal)
1593          j=self.ListaDocPal(self.cur,colTx,colPalDu,comando,i,j)
1594          i=i+1
1595      elif len(pal)>0:
1596        #caso normal
1597        pal=uts(pal)
1598        j=self.ListaDocPal(self.cur,colTx,colPalDu,comando,i,j)
1599        i=i+1
1600      if palesp!="":
1601        #palabra unicaracter a la dcha
1602        #self.cur.gotoRange(self.dcur.getStart(),0)
1603        #self.cur.gotoRange(self.dcur.getEnd(),1)
1604        j=self.ListaDocPal(self.dcur,colTx,colPalDu,comando,i,j)
1605        i=i+1
1606        self.cur.gotoRange(self.dcur.getEnd(),0)
1607
1608      #Siguiente palabra (si no es fin de párrafo o frase)
1609      self.cur.collapseToEnd()
1610      if self.isEnd() or self.isEndSel() or self.esMarca2():
1611        break
1612      #ret=self.cur.gotoNextWord(0)
1613      ret=self.NextWord()
1614
1615    if ret and not _ret:
1616      #Volver una palabra atrás para no perder la siguiente palabra
1617      self.cur.gotoPreviousWord(0)
1618   
1619 
1620  def ListaDocPal(self,cur,colTx,colPalDu,comando,i,j):
1621    #Trata una palabra para actualizar el documento
1622    #self.model es el modelo
1623    #cur contiene la palabra a actualizar (en el documento)
1624    #i es el indice de la palabra en el documento
1625    #j es el indice en colTx
1626    #Retorno: j (lo modifica esta funcion)
1627    self.paleliminada=False
1628    palendoc=cur.String
1629    if j>=len(colTx):
1630     
1631      #Sobran palabras en el documento
1632      hayespsig=False
1633      haypuntosig=False
1634      elimespacio=True
1635      cur.String=""
1636      self.paleliminada=True
1637      if cur.goLeft(1,1):
1638        if len(cur.String)==1 and ord(cur.String)>32:
1639          elimespacio=False
1640        cur.collapseToEnd()
1641      if elimespacio:
1642        if cur.goRight(1,1)==True and cur.String==" ":
1643          cur.String=""
1644        else:
1645          cur.collapseToStart()
1646          if cur.goLeft(1,1)==True and cur.String==" " and palendoc!=u"\xa1" and palendoc!=u"\xbf":
1647            cur.String=""
1648          else:
1649            cur.collapseToEnd()
1650      #if cur.goRight(1,1)==True:
1651        #if self.cesp.find(cur.String)>-1:
1652          #haypuntosig=True
1653        #elif cur.String==" ":
1654          #hayespsig=True
1655        #cur.collapseToStart()
1656      #if cur.goLeft(1,1) == True:
1657        #if cur.String==" " and (hayespsig or haypuntosig):
1658          ##Eliminar espacio anterior
1659          #cur.String=""
1660        #else:
1661          #cur.collapseToEnd()
1662    elif colTx[j][tx_nordori]>i:
1663     
1664      #Eliminar palabra del documento
1665      hayespant=False
1666      hayespsig=False
1667      haypuntosig=False
1668      elimespacio=True
1669      cur.String=""
1670      self.paleliminada=True
1671      if cur.goLeft(1,1):
1672        if len(cur.String)==1 and ord(cur.String)>32 and ord(cur.String)<256 and "([{".find(cur.String)==-1:
1673          elimespacio=False
1674        cur.collapseToEnd()
1675      if elimespacio:
1676        if cur.goRight(1,1)==True and cur.String==" ":
1677          if cur.goRight(1,1)==True:
1678            if ord(cur.String[-1])>256:
1679              cur.collapseToEnd()
1680            else:
1681              cur.goLeft(1,1)
1682          cur.String=""
1683        else:
1684          cur.collapseToStart()
1685          if cur.goLeft(1,1)==True and cur.String==" " and palendoc!=u"\xa1" and palendoc!=u"\xbf":
1686            cur.String=""
1687          else:
1688            cur.collapseToEnd()
1689      #if cur.goRight(1,1)==True:
1690        #if self.cesp.find(cur.String)>-1:
1691          #haypuntosig=True
1692        #elif cur.String==" ":
1693          #hayespsig=True
1694        #cur.collapseToStart()
1695      #if cur.goLeft(1,1) == True:
1696        #if cur.String==" " and (hayespsig or haypuntosig):
1697          ##Eliminar espacio anterior
1698          #cur.String=""
1699        #else:
1700          #cur.collapseToEnd()
1701    elif colTx[j][tx_nordori]==i:
1702     
1703      #Sustituir/insertar palabras
1704      if j in colPalDu and self.model!=None:
1705        #Hay que anotar palabra dudosa
1706        nota=self.model.createInstance("com.sun.star.text.TextField.Annotation")
1707        nota.Author="Salt4"+"."+colPalDu[j]['dtr']+"."+ comando
1708        contenido="_clau=" + colPalDu[j]['Clave'] + "_\n" + colPalDu[j]['Info']
1709        nota.Content=ucodeSiLinux(contenido)
1710        #self.model.Text.insertTextContent(doc.cur, nota, False)
1711        cur.Text.insertTextContent(cur, nota, False)
1712      pal=colTx[j][tx_paltext]
1713      #1.Sustituir
1714      if pal!="_" and pal!=uts(cur.String):
1715       
1716        pal=ucodeSiLinux(pal)
1717        #pal=pal.replace("'",apotpgr)
1718        palori=cur.String
1719        cur.String=pal
1720        self.ListaDocPalComas(cur,palori,colTx,j)
1721      j=j+1
1722       
1723      #2.Insertar
1724      while j <= len(colTx)-1:
1725        if colTx[j][tx_nordori] == i:
1726          pal=ucodeSiLinux(' ')
1727          cur.collapseToEnd()
1728          cur.String=pal
1729          cur.collapseToEnd()
1730          if j in colPalDu and self.model!=None:
1731            #Hay que anotar palabra dudosa
1732            nota=self.model.createInstance("com.sun.star.text.TextField.Annotation")
1733            nota.Author="Salt4"+"."+colPalDu[j]['dtr']+"."+ comando
1734            contenido="_clau=" + colPalDu[j]['Clave'] + "_\n" + colPalDu[j]['Info']
1735            nota.Content=ucodeSiLinux(contenido)
1736            #self.model.Text.insertTextContent(doc.cur, nota, False)
1737            cur.Text.insertTextContent(cur, nota, False)
1738          pal=colTx[j][tx_paltext]
1739          pal = ucodeSiLinux(pal)
1740          #pal=pal.replace("'",apotpgr)
1741          cur.collapseToEnd()
1742          palori=cur.String
1743          cur.String=pal
1744          self.ListaDocPalComas(cur,palori,colTx,j)
1745          cur.collapseToEnd()
1746          #cur.getText().insertString(cur.getEnd(),pal,True)
1747          j = j + 1
1748        else:
1749          break
1750     
1751      #while j < len(colTx)-1:
1752        #if colTx[j + 1][tx_nordori] == i:
1753          #j = j + 1
1754          #pal = pal + ' ' + colTx[j][tx_paltext]
1755        #else:
1756          #break
1757      ##doc.cur.String=pal 
1758      #if pal!="_" and pal!=uts(cur.String):
1759        #pal=ucodeSiLinux(pal)
1760        #cur.String=pal
1761        ##cur.getText().insertString(cur.getEnd(),pal,False)
1762        ##cur.String=""
1763        ##cur.goRight(len(pal),1)
1764       
1765      #j = j + 1
1766    return j
1767 
1768  def ListaDocPalComas(self,cur,palori,colTx,j):
1769    #Comprobación de espacios antes de "coma"
1770    #Entrada: cur: Cursor actual después de realizarse la sustitución de la palabra
1771    #         palori: Palabra original, antes de realizar la sustitución de la palabra
1772    #         colTx: Lista de palabras
1773    #         j: Palabra actual de la lista
1774    if cur.String == "," or cur.String == "." or cur.String == ";" or cur.String == "?" or cur.String == "!" or cur.String == u'\u201d':
1775      #La nueva palabra es una coma ...
1776      _cur=cur.getText().createTextCursorByRange(cur.getStart())
1777      _cur.gotoRange(cur.getStart(),0)
1778      _cur.goLeft(1,1)
1779      if _cur.String == " ":
1780        # ... si hay espacio anterior, quitarlo
1781        _cur.String=""
1782    elif palori == "," or palori == "." or palori == ";" or palori == "?" or palori == "!" or palori == u'\u201d':
1783      #La palabra sustituida era una coma ...
1784      if cur.String != "," and cur.String != "." and cur.String != ";" and cur.String != "?" and cur.String != "!" and cur.String != u'\u201d':
1785        # ... y la nueva no ...
1786        _cur=cur.getText().createTextCursorByRange(cur.getStart())
1787        _cur.gotoRange(cur.getStart(),0)
1788        _cur.goLeft(1,1)
1789        if _cur.String != " ":
1790          # ... si no hay espacio anterior, anyadirlo
1791          _cur.collapseToEnd()
1792          _cur.String=" "
1793    #elif cur.String == u'\u201c' and palori!=u'\u201c':
1794      ##La nueva palabra es una doble comilla de inicio ...
1795      #_cur=cur.getText().createTextCursorByRange(cur.getStart())
1796      #_cur.gotoRange(cur.getEnd(),0)
1797      #_cur.goRight(1,1)
1798      #if _cur.String == " ":
1799        ## ... si hay espacio posterior, quitarlo
1800        #_cur.String=""
1801    elif palori == u'\u201c' or palori==u'¡' or palori==u'¿':
1802      #La palabra sustituida era una doble comilla de inicio ...
1803      if cur.String != u'\u201c' and cur.String != u'¡' and cur.String != u'¿':
1804        # ... y la nueva no ...
1805        _cur=cur.getText().createTextCursorByRange(cur.getStart())
1806        _cur.gotoRange(cur.getEnd(),0)
1807        _cur.goRight(1,1)
1808        if _cur.String != " ":
1809          # ... si no hay espacio posterior, anyadirlo
1810          _cur.collapseToStart()
1811          _cur.String=" "
1812    else:
1813      #Comprobar si hay que eliminar un espacio anterior
1814      if j>0 and colTx[j-1][tx_paltext]=='\x93':
1815        _cur=cur.getText().createTextCursorByRange(cur.getStart())
1816        _cur.gotoRange(cur.getStart(),0)
1817        _cur.goLeft(1,1)
1818        if _cur.String == " ":
1819          # ... si hay espacio posterior, quitarlo
1820          _cur.String=""
1821       
1822
1823# end of class sltDoc
1824
1825class sltEstado:
1826  #Permite controlar el estado de los procesos de Traduccion y correccion
1827  def __init__(self,model):
1828    #diccionario de procesos activos: {'Titulo':estado,...}
1829    #estado puede ser: 'enproceso','stop'
1830    self.model=model
1831  def Stop(self):
1832    #Poner marca de que hay que cancelar el proceso
1833    descri=self.model.DocumentInfo.Description
1834    Llog("stop "+str(descri))
1835    if len(descri)>=8:
1836      if descri[-8:]=="Saltproc":
1837        #Estas en proceso: poner la marca de detener
1838        descri=descri[0:-8]+"Saltstop"
1839        self.model.DocumentInfo.Description=descri
1840  def Info(self):
1841    #Informacion sobre este proceso
1842    return self.model.DocumentInfo.Description
1843   
1844# end of class sltEstado
1845   
1846class ooUNOext:
1847  #simular la clase ooUNOobj llamada desde sltooo_extern (test)
1848  def __init__(self, ctx):
1849    #component context
1850    self.ctx=ctx
1851   
1852  def Llog(msg):
1853    syslog.syslog(syslog.LOG_DEBUG,str(msg))
1854   
1855  def action(self,args):
1856    smgr = self.ctx.ServiceManager
1857    doooLib.getServiceManager(sMan=smgr)
1858    doooLib.getDesktop()
1859   
1860    # retrieve the desktop object
1861    desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.ctx )
1862   
1863    # get current document model
1864    model = desktop.getCurrentComponent()
1865   
1866    # access the document's text property
1867    #text = model.Text
1868   
1869    # create a cursor
1870    #cursor = text.createTextCursor()
1871   
1872    #Cursor
1873    vcursorsupplier=model.getCurrentController()
1874    vcursor=vcursorsupplier.getViewCursor()
1875    Llog(str(args))
1876    #Funcion a realizar
1877    if args=="trad" or args=="tradi" or args=="corr":
1878      #oPro=ProWindow(model)
1879      oPro=vcursorsupplier.getStatusIndicator()
1880      #Trad(model,vcursor,args,oPro)
1881      Trad(model,vcursor,args,oPro)
1882    elif args=="startrev":
1883      #import threading
1884      ##Escuchar peticiones
1885      #t=threading.Thread(target=ListenFields,args=(model,))
1886      #t.setDaemon(True)
1887      #t.start()
1888      ListenFields(model)
1889    elif args=="rev":
1890      oTest=CtvWindow(model)
1891      oTest.BuscaNotas()
1892      if not oTest.Siguiente(ini=-1):
1893        oTest.windowClose()
1894      oTest.cmbSubs_clicked(None)
1895      oTest.Espera()
1896    elif args=="config":
1897      #Opcions de configiracio
1898      oTest=ConfigWindow()
1899      #oTest.cmbActu_clicked(None)
1900      oTest.Espera()
1901    elif args=="ajuda":
1902      Ajuda(desktop)
1903    elif args=="stop":
1904      Llog("STOP Inicial")
1905      msg=MsgWindow(str(procesos.Info(model)))
1906      #global varglobal
1907      #print str(model)
1908    elif args=="verbs":
1909      oTest=VerbsWindow(model)
1910      oTest.Load()
1911      oTest.Espera()
1912    elif args=="mouse":
1913      ListenFields(model)
1914      Espera()     
1915   
1916# implement a UNO component by deriving from the standard unohelper.Base class
1917# and from the interface(s) you want to implement.
1918class ooUNOobj( unohelper.Base, XJobExecutor ):
1919  def __init__( self, ctx ):
1920    # store the component context for later use
1921    self.ctx = ctx
1922
1923  def trigger( self, args ):
1924    # note: args[0] == "HelloWorld", see below config settings
1925   
1926    # retrieve the desktop object
1927    desktop = self.ctx.ServiceManager.createInstanceWithContext(
1928            "com.sun.star.frame.Desktop", self.ctx )
1929    doooLib.getServiceManager(sMan=self.ctx.ServiceManager)
1930
1931    # get current document model
1932    model = desktop.getCurrentComponent()
1933
1934    # access the document's text property
1935    #text = model.Text
1936
1937    # create a cursor
1938    #cursor = text.createTextCursor()
1939
1940    #Cursor
1941    vcursorsupplier=model.getCurrentController()
1942    vcursor=vcursorsupplier.getViewCursor()
1943    #Funcion a realizar
1944    if args=="trad" or args=="tradi" or args=="corr":
1945      #Realizar orden
1946      #oPro=ProWindow(model)
1947     
1948      oPro=vcursorsupplier.getStatusIndicator()
1949      import threading
1950      t=threading.Thread(target=Trad,args=(model,vcursor,args,oPro))
1951      #t.setDaemon(False)
1952      t.start()
1953      #Trad(model,cur,args)
1954    #elif args=="rev":
1955      #oCtv=CtvWindow(model)
1956      #import threading
1957      #t=threading.Thread(target=Rev,args=(oCtv,args))     
1958    elif args=="rev":
1959      #Rev(model)
1960      #ListenFields(model)
1961      oCtv=CtvWindow(model)
1962      oCtv.BuscaNotas()
1963      if not oCtv.Siguiente(ini=-1):
1964        oCtv.windowClose()
1965      #oCtv.Espera()
1966    elif args=="config":
1967      #Opcions de configiracio
1968      oConfig=ConfigWindow()
1969    elif args=="ajuda":
1970      #Ayuda en linea
1971      Ajuda(desktop)
1972    elif args=="stop":
1973      #Detener proceso
1974      st=sltEstado(model)
1975      st.Stop()
1976
1977from doooWindowLib import DBListenerWindow
1978import time
1979
1980class ConfigWindow(DBListenerWindow):
1981  def __init__(self):
1982    DBListenerWindow.__init__( self, u"Opcions de configuració" )
1983    self.setWindowPosSize(100,100,515,645)
1984    self.addFixedText( "lblOrtografia", 10, 10, 200, 14, u"Ortografia i morfosintaxi:" )
1985    self.addGroupBox("grpDemostra",10,30,200,55,u"Demostratius")
1986    self.addOptionButton("optDemostra2",10+10,30+20,200-20,20,u"Simples(este,eixe)", itemListenerProc = self.optDemostra2_clicked)
1987    self.addOptionButton("optDemostra1",10+10,30+50,200-20,20,u"Reforçats(aquest,aqueix)", itemListenerProc = self.optDemostra1_clicked)
1988    self.addGroupBox("grpIncoac",10,110,200,55,u"Incoatius")
1989    self.addOptionButton("optIncoac2",10+10,110+20,200-20,20,u"Increment -ix (patix)", itemListenerProc = self.optIncoac2_clicked)
1990    self.addOptionButton("optIncoac1",10+10,110+50,200-20,20,u"Increment -eix (pateix)", itemListenerProc = self.optIncoac2_clicked)
1991    self.addGroupBox("grpPlu",10,190,200,55,u"Plural de -sc, -st i -xt")
1992    self.addOptionButton("optPlu1",10+10,190+20,200-20,20,u"Terminació -os (foscos)")
1993    self.addOptionButton("optPlu2",10+10,190+50,200-20,20,u"Terminació -s (foscs)")
1994    self.addGroupBox("grpAcc",10,270,200,55,u"Accentuació")
1995    self.addOptionButton("optAcc1",10+10,270+20,200-20,20,u"(café)")
1996    self.addOptionButton("optAcc2",10+10,270+50,200-20,20,u"(cafè)")
1997    self.addGroupBox("grpTop",10,350,200,55,u"Topònims")
1998    self.addOptionButton("optTopOfi",10+10,350+20,200-20,20,u"Oficials  (Cheste)")
1999    self.addOptionButton("optTopHist",10+10,350+50,200-20,20,u"Històrics  (Xest)")
2000    self.addFixedText( "lblRevisio", 220, 10, 200, 14, u"Revisió:" )
2001    self.addGroupBox("grpPaDes",220,30,200,55,u"Paraules desconegudes")
2002    self.addOptionButton("optIgnPaDes",220+10,30+20,200-20,20,u"Ignorar")
2003    self.addOptionButton("optDetPaDes",220+10,30+50,200-20,20,u"Detectar")
2004    self.addGroupBox("grpNpDes",220,110,200,55,u"Noms propis desconeguts")
2005    self.addOptionButton("optIgnNpDes",220+10,110+20,200-20,20,u"Ignorar")
2006    self.addOptionButton("optDetNpDes",220+10,110+50,200-20,20,u"Detectar")
2007    self.addGroupBox("grpMa",220,190,200,55,u"Ús de majúscules")
2008    self.addOptionButton("optIgnMa",220+10,190+20,200-20,20,u"Ignorar")
2009    self.addOptionButton("optDetMa",220+10,190+50,200-20,20,u"Detectar")
2010    self.addGroupBox("grpDSem",220,270,200,55,u"Doblets semàntics")
2011    self.addOptionButton("optIgnDSem",220+10,270+20,200-20,20,u"Ignorar")
2012    self.addOptionButton("optDetDSem",220+10,270+50,200-20,20,u"Detectar")
2013    self.addGroupBox("grpOpConfig",220,350,200,55,u"Op. de configuració")
2014    self.addOptionButton("optIgnOpConfig",220+10,350+20,200-20,20,u"Ignorar")
2015    self.addOptionButton("optDetOpConfig",220+10,350+50,200-20,20,u"Detectar")
2016    self.addGroupBox("grpCfgVoid",10,430,410,80,u"Ajustar traducció de frases en altres llengües(llatí...)")
2017    self.addFixedText( "lblCfgVoid1", 20, 460, 200, 14, u"No traduir si la frase té més de" )
2018    self.addEdit( "txtNPalTot", 250, 460, 100, 14, "",textListenerProc=self.txtNPalTot_changed )
2019    self.setEditEditable("txtNPalTot",True)
2020    self.addFixedText( "lblCfgVoid1b", 20, 480, 175, 14, u"paraules i n'hi ha més d'un" )
2021    self.addEdit( "txtPercent", 200, 480, 22, 14, "", textListenerProc=self.txtPercent_changed )
2022    self.setEditEditable("txtPercent",True)
2023    self.addFixedText( "lblCfgVoid1c", 225, 480, 14, 14, u"%" )
2024    self.addFixedText( "lblCfgVoid2", 20, 500, 250, 14, u"de paraules desconegudes." )
2025    self.addButton( "cmbNoVoid", 10+30+250, 450+40, 100, 20, u"Traduir sempre", actionListenerProc = self.cmbNoVoid_clicked ) 
2026    self.addGroupBox("grpVers",10,530,410,30,u"Versió de l'addon")
2027    self.addFixedText( "lblVers", 10+30, 530+20, 300, 12, u"Salt 4.0" )
2028    self.addButton( "cmbActu", 10+50, 580, 100, 30, u"Actualitzar", actionListenerProc = self.cmbActu_clicked ) 
2029    self.addButton( "cmbCancel", 220+50, 580, 100, 30, u"Cancel·lar", actionListenerProc = self.cmbCancel_clicked ) 
2030
2031    self.setEnable("grpAcc",False)
2032    self.setEnable("optAcc1",False)
2033    self.setEnable("optAcc2",False)
2034
2035    wpos={'left':100,'top':100,'width':515,'height':645}
2036    self.setWindowPosSize( wpos['left'], wpos['top'], 515, 645 )
2037
2038    self.terminar=False
2039
2040    #Acceso al servidor para cargar/salvar configuración
2041    self.sck=socketConnect()
2042    if self.sck==None:
2043      self.terminar=True
2044      self.windowClose()
2045    else:
2046      #Cargar configuración actual
2047      scfg=""
2048      datos=str(("cfgload","")).encode('utf-8')
2049      self.sck.send(datos)
2050      datos=self.sck.recv(128000).decode('utf-8')
2051      comandorec,scfg=eval(datos)
2052      self.cfg=eval(scfg)
2053      if 'config' in self.cfg:
2054        if 'demostratius' in self.cfg['config']:
2055          self.setOptTrue(self.cfg['config']['demostratius']==1,'optDemostra2','optDemostra1')
2056        if 'incoatius' in self.cfg['config']:
2057          self.setOptTrue(self.cfg['config']['incoatius']==1,'optIncoac2','optIncoac1')
2058        if 'plural' in self.cfg['config']:
2059          self.setOptTrue(self.cfg['config']['plural']==1,'optPlu1','optPlu2')
2060        if 'acc' in self.cfg['config']:
2061          self.setOptTrue(self.cfg['config']['acc']==1,'optAcc1','optAcc2')
2062        if 'top' in self.cfg['config']:
2063          self.setOptTrue(self.cfg['config']['top']==1,'optTopOfi','optTopHist')
2064        if 'pades' in self.cfg['config']:
2065          self.setOptTrue(self.cfg['config']['pades']==1,'optIgnPaDes','optDetPaDes')
2066        if 'npdes' in self.cfg['config']:
2067          self.setOptTrue(self.cfg['config']['npdes']==1,'optIgnNpDes','optDetNpDes')
2068        if 'maj' in self.cfg['config']:
2069          self.setOptTrue(self.cfg['config']['maj']==1,'optIgnMa','optDetMa')
2070        if 'dsem' in self.cfg['config']:
2071          self.setOptTrue(self.cfg['config']['dsem']==1,'optIgnDSem','optDetDSem')
2072        if 'opconfig' in self.cfg['config']:
2073          self.setOptTrue(self.cfg['config']['opconfig']==1,'optIgnOpConfig','optDetOpConfig')
2074        if 'void_npalmin' in self.cfg['config']:
2075          txt=str(self.cfg['config']['void_npalmin'])
2076          self.setEditText("txtNPalTot",txt)
2077        if 'void_percent' in self.cfg['config']:
2078          txt=str(self.cfg['config']['void_percent'])
2079          self.setEditText("txtPercent",txt)
2080   
2081        #Acc está en función de otras opciones
2082        self.OptActivarAcc()
2083       
2084    #Versión del addon
2085    txt="Addon salt " +sltversion #+ str(sltDate())
2086    self.setFixedTextText("lblVers",txt)
2087   
2088 
2089  #Eventos
2090  def txtNPalTot_changed(self,oTextEvent):
2091    txt=self.getEditText("txtNPalTot")
2092    if len(txt)>0:
2093      if not txt[-1].isdigit():
2094        #Sólo números
2095        txt=txt[0:-1]
2096        self.setEditText("txtNPalTot",txt)
2097      elif int(txt)>9999:
2098        txt='9999'
2099        self.setEditText("txtNPalTot",txt)
2100       
2101  def txtPercent_changed(self,oTextEvent):
2102    txt=self.getEditText("txtPercent")
2103    if len(txt)>0:
2104      if not txt[-1].isdigit():
2105        #Sólo números
2106        txt=txt[0:-1]
2107        self.setEditText("txtPercent",txt)
2108      elif int(txt)>100:
2109        txt='100'
2110        self.setEditText("txtPercent",txt)
2111
2112  def cmbActu_clicked( self, oActionEvent ): 
2113    """This is called when the Actu button is clicked."""
2114    #Actualizar los datos de configuración
2115    if 'config' in  self.cfg:
2116      self.cfg['config']['demostratius']=self.getOptVal('optDemostra2')
2117      self.cfg['config']['incoatius']=self.getOptVal('optIncoac2')
2118      self.cfg['config']['plural']=self.getOptVal('optPlu1')
2119      self.cfg['config']['acc']=self.getOptVal('optAcc1')
2120      self.cfg['config']['top']=self.getOptVal('optTopOfi')
2121      self.cfg['config']['pades']=self.getOptVal('optIgnPaDes')
2122      self.cfg['config']['npdes']=self.getOptVal('optIgnNpDes')
2123      self.cfg['config']['maj']=self.getOptVal('optIgnMa')
2124      self.cfg['config']['dsem']=self.getOptVal('optIgnDSem')
2125      self.cfg['config']['opconfig']=self.getOptVal('optIgnOpConfig')
2126      txt=self.getEditText("txtNPalTot")
2127      if not txt.isdigit():
2128        txt='9999'
2129      self.cfg['config']['void_npalmin']=int(txt)
2130      txt=self.getEditText("txtPercent")
2131      if not txt.isdigit():
2132        txt='100'
2133      self.cfg['config']['void_percent']=int(txt)
2134       
2135    scfg=str(self.cfg)
2136    datos=str(("cfgsave",scfg)).encode('utf-8')
2137    self.sck.send(datos)
2138    datos=self.sck.recv(128000).decode('utf-8')
2139   
2140    self.terminar=True
2141    self.windowClose()
2142
2143  def cmbCancel_clicked( self, oActionEvent ): 
2144    """This is called when the Cancel button is clicked."""
2145    self.terminar=True
2146    self.windowClose()
2147
2148  def cmbNoVoid_clicked( self, oActionEvent ): 
2149    """This is called when the button is clicked."""
2150    self.setEditText("txtNPalTot",'9999')
2151    self.setEditText("txtPercent",'100')
2152   
2153  def optDemostra2_clicked(self,oActionEvent):
2154    self.OptActivarAcc()
2155   
2156  def optDemostra1_clicked(self,oActionEvent):
2157    self.OptActivarAcc()
2158
2159  def optIncoac2_clicked(self,oActionEvent):
2160    self.OptActivarAcc()
2161
2162  def optIncoac1_clicked(self,oActionEvent):
2163    self.OptActivarAcc()
2164
2165  def windowClosed(self,oActionEvent):
2166    self.terminar=True
2167    self.sck.close()
2168    rect=self.getWindowPosSize()
2169    self.wp["configwindow"]=str({'left':rect.X,'top':rect.Y,'width':rect.Width,'height':rect.Height})
2170    self.wp.sync()
2171    selp.wp.close()
2172
2173  #Métodos
2174  def Espera(self):
2175    while not self.terminar:
2176        time.sleep(1)
2177 
2178  def OptActivarAcc(self):
2179    #Activar/desactivar la elección cafè/café
2180    if self.getOptionButtonState("optDemostra1")==True and self.getOptionButtonState("optIncoac1")==True:
2181      self.setEnable("grpAcc",True)
2182      self.setEnable("optAcc1",True)
2183      self.setEnable("optAcc2",True)
2184    else:
2185      self.setOptionButtonState("optAcc1",True)
2186      self.setEnable("grpAcc",False)
2187      self.setEnable("optAcc1",False)
2188      self.setEnable("optAcc2",False)
2189
2190  def setOptTrue(self,cnd,optSiTrue,optSiFalse):
2191    # Poner un opt True según una condición:
2192    # Si cnd==True, el botón llamado optSiTrue se pone True
2193    # Si cnd == False, el botón llamado optSiFalse se pone True
2194    if cnd:
2195      self.setOptionButtonState(optSiTrue,True)
2196    else:
2197      self.setOptionButtonState(optSiFalse,True)
2198
2199  def getOptVal(self,opt):
2200    #Devuelve el valor asociado al OptionButton cuyo nombre es opt en el fichero de configuración
2201    #Si opt==True: devuelve 1
2202    #Si opt==False: devuelve 2
2203    if self.getOptionButtonState(opt)==True:
2204      return 1
2205    else:
2206      return 2
2207   
2208class CtvWindow(DBListenerWindow):
2209  def __init__(self,model):
2210    DBListenerWindow.__init__( self, u"Paraules dubtoses de:"+model.getCurrentController().getFrame().Title )
2211
2212    self.addFixedText( "lblPaDubt", 6, 2, 120, 12, u"Paraula dubtosa:" )
2213    self.addFixedText( "lblPaPro", 6, 34, 120, 12, u"Proposta de canvi:" )
2214    self.addFixedText( "lblAlt", 6, 56, 86, 12, u"Alternatives:" )       
2215    self.addFixedText( "lblTipErr", 6, 196, 86, 12, u"Tipus d'error:" )
2216    self.addEdit( "txtMens", 122, 196, 253, 16, "" )
2217    self.setEditEditable("txtMens",False)
2218    self.addEdit( "txtPalErr", 122, 5, 253, 16, "" )
2219    self.setEditEditable("txtPalErr",False)
2220    self.addEdit( "txtPal", 122, 34, 253, 16, "" )
2221    self.setEditEditable("txtPal",True)
2222    self.addButton( "cmbSubs", 382, 4, 120, 20, u"Substituir", actionListenerProc = self.cmbSubs_clicked ) 
2223    self.addButton( "cmbSubsSempre", 382, 35, 120, 20, u"Substituir sempre", actionListenerProc = self.cmbSubsSempre_clicked ) 
2224    self.addButton( "cmbIgno", 382, 66, 120, 20, u"Ignorar", actionListenerProc = self.cmbIgno_clicked ) 
2225    self.addButton( "cmbIgnoSempre", 382, 97, 120, 20, u"Ignorar sempre", actionListenerProc = self.cmbIgnoSempre_clicked )
2226    self.addButton( "cmbElimMarques", 382, 128, 120, 20, u"Eliminar marques", actionListenerProc = self.cmbElimMarques_clicked ) 
2227    self.addButton( "cmbCancel", 382, 156, 120, 20, u"Cancel·lar", actionListenerProc = self.cmbCancel_clicked ) 
2228    self.addCheckBox( "chkAfegir", 382, 182, 130, 20, u"Afegir a dic. pers.", itemListenerProc = self.chkAfegir_clicked ) 
2229    self.addCheckBox( "chkCont", 382, 202, 130, 20, u"Continuar revisió", itemListenerProc = self.chkCont_clicked ) 
2230    self.addListBox( "lbxAlt", 6, 75,369, 83, bDropdown=False,itemListenerProc = self.lbxAlt_clicked )
2231
2232    wpos={'left':0x100,'top':0x200,'width':0x23c,'height':0x0e0}
2233    self.setWindowPosSize( wpos['left'], wpos['top'], 620, 0x0e0 )
2234    #self.setWindowPosSize( wpos['left'], wpos['top'], 0x23c, 0x0e0 )
2235
2236    #variables para acceder al documento
2237    self.model=model
2238    self.oDocView=None
2239    self.oNotas=None
2240    self.oNota=None
2241    self.curNota=None
2242    self.oAnchor=None
2243    self.oText=None
2244    self.lsNotas=[]
2245    self.iNotas=0
2246
2247    #Informació sobre la paraula dudosa actual
2248    self._prauclau_ = "clau"
2249    self._praunumalts_ = "numalts" #Núm. de alternativas
2250    self._prautxtdu_ = "txtdu" #Texto dudoso
2251    self._prautxtpro_ = "txtpro" #Texto propuesto '(corresponde a la primera alternativa)
2252    self._praualt_ = "alt" #Las diferentes alternativas se identifican como $altn=
2253    self._praudescrierror_ = "error"  #Texto que describe el tipo de error
2254    self._praunpretro_ = "npretro" #Núm. palabras a retroceder para corregir en el proceso de revisión (si 0 no corregir)
2255    self._praucolor_ = "txtcolor" #Color original del texto dudoso
2256
2257    self.praucom=""             #Comando que produjo la anotación
2258    self.prauclau=""            #Palabra(s) en el documento
2259    self.praunumalts=0
2260    self.prautxtdu=""
2261    self.prautxtpro=""
2262    self.prautxtpal=""          #Alternativa propuesta
2263    self.praudescrierror=""
2264    self.praunpretro=0
2265    self.praudtr=""             #Traducción directa o inversa
2266    self.cmd=""
2267    self.continuar=True
2268    self.afegir=False
2269    self.terminar=False
2270
2271    #Acceso al servidor para revisar frases
2272    self.sck=socketConnect()
2273    if self.sck==None:
2274      self.terminar=True
2275      self.windowClose()
2276   
2277  #Eventos
2278  def cmbSubs_clicked(self, oActionEvent):
2279    #Actualizar información
2280    self.cmd="cmbSubs"
2281    self.LeeCtv()
2282   
2283    #Localizar palabra en el documento
2284    cur=self.DamePalEnNota()
2285   
2286    #Eliminar anotación
2287    self.oText.removeTextContent(self.oNota)
2288    self.lsNotas.pop(self.iNotas)
2289   
2290    #Substituir palabra en el documento
2291    self.Substituir(cur)
2292   
2293    #Ver si hay que añadir al dicc. personal (TODO)
2294   
2295    #Seguir o terminar
2296    if self.continuar:
2297      if not self.Siguiente(ini=-2):
2298        self.windowClose()
2299    else:
2300      self.windowClose()
2301   
2302  def cmbSubsSempre_clicked(self, oActionEvent):
2303    #Actualizar información
2304    self.cmd="cmbSubsSempre"
2305    self.LeeCtv()
2306   
2307    #Localizar palabra en el documento
2308    cur=self.DamePalEnNota()
2309   
2310    #Eliminar anotación
2311    self.oText.removeTextContent(self.oNota)
2312    self.lsNotas.pop(self.iNotas)
2313   
2314    #Substituir palabra en el documento
2315    self.Substituir(cur)
2316   
2317    #Sustituir todas las que sean iguales
2318    i=0
2319    txtclau=self.prauclau
2320    txtpro=self.prautxtpro
2321    txtdubt=self.prautxtdu
2322    iactual=self.iNotas
2323    while i<len(self.lsNotas):
2324      if self.EsNota(i):
2325        self.oNota,self.oAnchor,self.oText,cur=self.lsNotas[i]
2326        info=self.oNota.Content
2327        self.InfoCtv(info)
2328        cur=self.DamePalEnNota()
2329        self.curNota=cur
2330        if self.prautxtdu==txtdubt:
2331          self.prautxtpro=txtpro
2332          self.oText.removeTextContent(self.oNota)
2333          self.lsNotas.pop(i)
2334          self.Substituir(cur)
2335          if i<iactual:
2336            iactual=iactual-1
2337        else:
2338          i=i+1
2339    self.iNotas=iactual
2340   
2341    #Seguir o terminar
2342    if self.continuar:
2343      if not self.Siguiente(ini=-2):
2344        self.windowClose()
2345    else:
2346      self.windowClose()
2347
2348  def cmbIgno_clicked(self, oActionEvent):
2349    #Actualizar información
2350    self.cmd="cmbIgno"
2351    self.LeeCtv()
2352   
2353    #Dejar palabra original en el documento y quitar marca
2354    self.curNota.CharContoured=False
2355    self.curNota.String=self.prautxtdu
2356
2357    #Eliminar anotación
2358    self.oText.removeTextContent(self.oNota)
2359    self.lsNotas.pop(self.iNotas)
2360   
2361    #Seguir o terminar
2362    if self.continuar:
2363      if not self.Siguiente():
2364        self.windowClose()
2365    else:
2366      self.windowClose()
2367
2368  def cmbIgnoSempre_clicked(self, oActionEvent):
2369    #Actualizar información
2370    self.cmd="cmbIgnoSempre"
2371    self.LeeCtv()
2372   
2373    #Dejar palabra original en el documento y quitar marca
2374    self.curNota.CharContoured=False
2375    self.curNota.String=self.prautxtdu
2376
2377    #Eliminar anotación
2378    self.oText.removeTextContent(self.oNota)
2379    self.lsNotas.pop(self.iNotas)
2380
2381    #Ignorar todas las que sean iguales
2382    i=0
2383    txtdubt=self.prautxtdu
2384    iactual=self.iNotas
2385    while i<len(self.lsNotas):
2386      if self.EsNota(i):
2387        self.oNota,self.oAnchor,self.oText,cur=self.lsNotas[i]
2388        info=self.oNota.Content
2389        self.InfoCtv(info)
2390        cur=self.DamePalEnNota()
2391        self.curNota=cur
2392        if self.prautxtdu==txtdubt:
2393          self.curNota.String=self.prautxtdu
2394          self.oText.removeTextContent(self.oNota)
2395          self.lsNotas.pop(i)
2396          if i<iactual:
2397            iactual=iactual-1
2398        else:
2399          i=i+1
2400    self.iNotas=iactual
2401   
2402    #Seguir o terminar
2403    if self.continuar:
2404      if not self.Siguiente():
2405        self.windowClose()
2406    else:
2407      self.windowClose()
2408
2409  def cmbElimMarques_clicked(self,oActionEvent):
2410    self.curNota.CharContoured=False
2411    for nota in self.lsNotas:
2412      nota[2].removeTextContent(nota[0])
2413    self.lsNotas=[]
2414    self.Siguiente()
2415    #ret=self.Siguiente(0)
2416    #while ret:
2417      #self.curNota.CharContoured=False
2418      #self.oText.removeTextContent(self.oNota)
2419      #self.lsNotas.pop(self.iNotas)
2420      #ret=self.Siguiente()
2421    self.windowClose()
2422   
2423  def cmbCancel_clicked( self, oActionEvent ): 
2424    """This is called when the Cancel button is clicked."""
2425    self.cmd="cmbCancel"
2426    self.afegir=False
2427    self.continuar=False
2428    self.windowClose()
2429
2430  def chkAfegir_clicked(self,oItemEvent):
2431    pass
2432  def chkCont_clicked(self,oItemEvent):
2433    pass
2434  def lbxAlt_clicked(self,oItemEvent):
2435    txt=self.getListBoxSelectedItem("lbxAlt")
2436    txt=self.DamePalEnLista(txt)
2437    self.setEditText("txtPal",txt)
2438 
2439  def windowClosed(self,oActionEvent):
2440    self.sck.close()
2441    self.curNota.CharContoured=False
2442    self.terminar=True
2443    rect=self.getWindowPosSize()
2444    self.wp["ctvwindow"]=str({'left':rect.X,'top':rect.Y,'width':rect.Width,'height':rect.Height})
2445    self.wp.sync()
2446    selp.wp.close()
2447    if self.continuar:
2448      msg=MsgWindow('No hi ha paraules pendents de revisar.')
2449  def windowClosing(self,oActionEvent):
2450    pass
2451  def windowDeactivated(self,oActionEvent):
2452    pass
2453
2454  #Métodos
2455  def Espera(self):
2456    while not self.terminar:
2457        time.sleep(1)
2458 
2459  def BuscaNotas(self):
2460    #Buscar todas las notas del documento y guardar la información en self.lsNotas
2461    #lsNotas=[(oNota,oAnchor,oText,cur)...]
2462    self.lsNotas=[]
2463    if self.terminar:
2464      return
2465    oNotas=self.model.getTextFields().createEnumeration()
2466    while oNotas.hasMoreElements():
2467      oNota=oNotas.nextElement()
2468      if oNota.supportsService("com.sun.star.text.TextField.Annotation"):
2469        if oNota.Author[0:4]=="Salt":
2470          #Obtener cursor "de la nota"
2471          oAnchor=oNota.getAnchor()
2472          oText=oAnchor.getText()
2473          cur=oText.createTextCursorByRange(oAnchor.getStart())
2474          #Incluir en la lista en orden creciente
2475          estetx=False
2476          i=0
2477          while i<len(self.lsNotas):
2478            if oText==self.lsNotas[i][2]:
2479              #el mismo text
2480              estetx=True
2481              if oText.compareRegionStarts(cur.getStart(),self.lsNotas[i][3].getStart())==1:
2482                self.lsNotas.insert(i,(oNota,oAnchor,oText,cur))
2483                break
2484            elif estetx:
2485              #añadir al final del grupo anterior
2486              self.lsNotas.insert(i,(oNota,oAnchor,oText,cur))
2487              break
2488            #seguir buscando
2489            i=i+1
2490          if i==len(self.lsNotas):
2491            #añadir al final
2492            self.lsNotas.append((oNota,oAnchor,oText,cur))
2493
2494  def EsNota(self,i):
2495    #Comprobar que la nota cuyo índice en la lista es i sigue existiendo
2496    #Si no existe la borra de la lista
2497    #Retorno: True, si existe, False si no existe
2498    _ret=True
2499    if i>=0 and i<len(self.lsNotas):
2500      oNota=self.lsNotas[i][0]
2501      try:
2502        info=oNota.Content
2503      except:
2504        #Ha habido error: la nota ya no existe
2505        _ret=False
2506        self.lsNotas.pop(i)
2507    return _ret
2508       
2509  def Siguiente(self,ini=-1):
2510    #Buscar la siguiente anotación en el documento
2511    #Entrada: Si ini>-1, buscar este número de anotación
2512    #         Si ini==-1, buscar desde el cursor "del ratón"
2513    #         Si ini==-2, buscar siguiente
2514    #Retorno: True, si se ha encontrado anotación; False, si no hay anotaciones
2515    _ret=False
2516    if len(self.lsNotas)==0:
2517      self.oNota=self.oAnchor=self.oText=self.curNota=None
2518      return _ret
2519    haynotas=False
2520    oNota=None
2521    oAnchor=None
2522    oText=None
2523    cur=None
2524    vcur=self.model.getCurrentController().getViewCursor()
2525    if ini==-1:
2526      #Obtener cursor del ratón
2527      text=vcur.getText()
2528      rcur=text.createTextCursorByRange(vcur.getStart())
2529      self.iNotas=0
2530      while self.iNotas<len(self.lsNotas):
2531        if text==self.lsNotas[self.iNotas][2]:
2532          if text.compareRegionStarts(rcur.getStart(),self.lsNotas[self.iNotas][3].getStart())==1:
2533            oNota,oAnchor,oText,cur=self.lsNotas[self.iNotas]
2534            break
2535        self.iNotas=self.iNotas+1
2536    elif ini==-2:
2537      if self.iNotas<len(self.lsNotas):
2538        oNota,oAnchor,oText,cur=self.lsNotas[self.iNotas] 
2539    else:
2540      self.iNotas=ini
2541      if self.iNotas<len(self.lsNotas) and self.iNotas>=0:
2542        oNota,oAnchor,oText,cur=self.lsNotas[self.iNotas]
2543    if oNota==None:
2544      self.iNotas=0
2545      oNota,oAnchor,oText,cur=self.lsNotas[self.iNotas]
2546    if oNota!=None:
2547      #Comprobar que la nota sigue existiendo
2548      try:
2549        info=oNota.Content
2550      except:
2551        #Ha habido error: la nota ya no existe
2552        self.lsNotas.pop(self.iNotas)
2553        _ret=self.Siguiente()
2554        return _ret
2555     
2556      _ret=True
2557      self.oNota=oNota
2558      self.oAnchor=oAnchor
2559      self.oText=oText
2560      self.praudtr=self.oNota.Author[6:7]
2561      self.praucom=self.oNota.Author[8:]
2562      info=self.oNota.Content
2563      self.InfoCtv(info)
2564      cur=self.DamePalEnNota()
2565      cur.CharContoured=True
2566      self.curNota=cur
2567      #Que se vea la palabra dudosa
2568      vcur.gotoRange(cur.getStart(),0)
2569    return _ret
2570 
2571  def Siguiente_(self,ini=-1):
2572    #Buscar la siguiente anotación en el documento
2573    #Entrada: Si ini>-1, buscar desde esa posición
2574    #         Si ini<0, buscar desde el cursor "del ratón"
2575    #Retorno: True, si se ha encontrado anotación; False, si no hay anotaciones
2576    _ret=False
2577    haynotas=False
2578    oNotaActual=None
2579    oAnchorActual=None
2580    oTextActual=None
2581    curactual=None
2582   
2583    if ini<0:
2584      #Obtener cursor del ratón
2585      vcur=self.model.getCurrentController().getViewCursor()
2586      rcur=vcur.getText().createTextCursorByRange(vcur.getStart())   
2587      rcur.gotoStart(1)
2588      lenanterior=len(rcur.String)
2589    else:
2590      lenanterior=ini
2591    #Analizar notas
2592    self.oNotas=self.model.getTextFields().createEnumeration()
2593    while self.oNotas.hasMoreElements():
2594      self.oNota=self.oNotas.nextElement()
2595      if self.oNota.supportsService("com.sun.star.text.TextField.Annotation"):
2596        if self.oNota.Author[0:4]=="Salt":
2597          self.praudtr=self.oNota.Author[6:7]
2598          self.praucom=self.oNota.Author[8:]
2599          haynotas=True
2600          #Obtener cursor "de la nota"
2601          self.oAnchor=self.oNota.getAnchor()
2602          self.oText=self.oAnchor.getText()
2603          cur=self.oText.createTextCursorByRange(self.oAnchor.getStart())
2604          cur.gotoStart(1)
2605          if len(cur.String)>lenanterior:
2606            #Puede ser esta
2607            if oNotaActual!=None:
2608              if len(curactual.String)>len(cur.String):
2609                #Este es mejor
2610                oNotaActual=self.oNota
2611                oAnchorActual=self.oAnchor
2612                oTextActual=self.oText
2613                curactual=cur
2614            else:
2615              oNotaActual=self.oNota
2616              oAnchorActual=self.oAnchor
2617              oTextActual=self.oText
2618              curactual=cur
2619         
2620    if oNotaActual!=None:
2621      #Procesar esta nota
2622      _ret=True
2623      self.oNota=oNotaActual
2624      self.oAnchor=oAnchorActual
2625      self.oText=oTextActual
2626      info=self.oNota.Content
2627      self.InfoCtv(info)
2628      cur=self.DamePalEnNota()
2629      cur.CharContoured=True
2630      self.curNota=cur
2631      #Que se vea la palabra dudosa
2632      vcur.gotoRange(cur.getStart(),0)
2633    elif haynotas:
2634      #Si no hemos encontrado ninguna, probar desde el principio
2635      _ret=self.Siguiente(ini=0)
2636    else:
2637      _ret=False
2638    return _ret
2639     
2640  def InfoLeer(self,info,cod):
2641    #'   Leer un elemento de la información adicional que se
2642    #'   guarda junto a cada texto dudoso, en el proceso
2643    #'   automático
2644    #'
2645    #'   Entrada:    info: String de información adicional
2646    #'               cod: Código a buscar
2647    #'
2648    #'   Retorno:     Texto informativo correspondiente a
2649    #'                       cod, si existe ese elemento en Info
2650    #'                       (en caso contrario "")
2651    txt=""
2652    pi=info.find("_"+cod+"=")
2653    if pi>=0:
2654      pi=pi+len(cod)+2
2655      pf=info.find("_",pi)
2656      if pf>=0:
2657        txt=info[pi:pf]
2658      else:
2659        txt=info[pi:]
2660    return txt
2661 
2662  def InfoCtv(self,info):
2663    #Pasar a la ventana la información sobre la palabra dudosa contenida en info
2664    self.prauclau=self.InfoLeer(info,self._prauclau_)
2665   
2666    txt=self.InfoLeer(info,self._praunumalts_)
2667    if txt.isdigit():
2668      self.praunumalts=int(txt)
2669    else:
2670      self.praunumalts=0
2671     
2672    self.prautxtdu=self.InfoLeer(info,self._prautxtdu_)
2673    self.setEditText("txtPalErr",self.prautxtdu)
2674
2675    self.prautxtpro=self.InfoLeer(info,self._prautxtpro_)
2676    self.prautxtpal=self.prautxtpro
2677    self.setEditText("txtPal",self.prautxtpal)
2678   
2679    self.removeListBoxItems("lbxAlt",0,self.getListBoxItemCount("lbxAlt"))
2680    for i in range(1,self.praunumalts+1):
2681      txt=self.InfoLeer(info,self._praualt_ + str(i))
2682      self.addListBoxItem("lbxAlt",txt)
2683
2684    self.praudescrierror=self.InfoLeer(info,self._praudescrierror_)
2685    self.setEditText("txtMens",self.praudescrierror)
2686   
2687    txt=self.InfoLeer(info,self._praunpretro_)
2688    if txt.isdigit():
2689      self.praunpretro=int(txt)
2690    else:
2691      self.praunpretro=0
2692
2693    self.setCheckBoxState("chkCont",self.continuar)
2694
2695  def LeeCtv(self):
2696    #Actualiza determinadas variables a partir de la informacion en CtvWindow
2697    self.prautxtpro=self.getEditText("txtPal")
2698    self.afegir=self.getCheckBoxState("chkAfegir")
2699    self.continuar=self.getCheckBoxState("chkCont")
2700
2701  def DamePalEnLista(self,txt):
2702    #'
2703    #'   Nos da una palabra sin los caracteres informativos de lbxAlt
2704    #'
2705    #'   Entrada:    txt: Texto al que queremos quitar caracteres informativos
2706    #'
2707    #'   Retorno:    Texto sin los caracteres informativos ("" si empieza por esp)
2708    pal=""
2709    if len(txt)>0:
2710      if txt[0]!=" ":
2711        pal=txt
2712        p=pal.find(".")
2713        if p>=0:
2714          pal=pal[p+1:]
2715          p=pal.find("[")
2716          if p>=0:
2717            pal=pal[0:p].strip()
2718          else:
2719            pal=pal.strip()
2720    return pal
2721
2722  def DamePalEnNota(self):
2723    #Obtener la palabra correspondiente a la anotación actual
2724    #Retorno: cursor con el texto de la anotación actual seleccionado
2725    cur=self.oText.createTextCursorByRange(self.oAnchor.getStart())
2726    cur.goRight(1,0) #saltar anotación
2727    doc=sltDoc(self.model,cur,pos=True)
2728    pal,cf,fp=PalabraSig(doc)
2729    if self.prauclau.lower()!=doc.cur.String.lower():
2730      p=doc.cur.String.lower().find(self.prauclau.lower())
2731      if p>0:
2732        p=len(doc.cur.String)-p
2733        doc.cur.collapseToEnd()
2734        doc.cur.goLeft(p,1)
2735    if self.prauclau.find(" ")>=0:
2736      #Hay que sustituir más de una palabra
2737      p=self.prauclau.lower().find(doc.cur.String.lower())
2738      if p>=0:
2739        nizda=p
2740        ncent=len(doc.cur.String)
2741        ndcha=len(self.prauclau)-nizda-ncent
2742        if nizda>0 or ndcha>0:
2743          if nizda>0 and self.oText.compareRegionStarts(self.oAnchor.getStart(),doc.cur.getStart())==1:
2744            nizda=nizda+1
2745          if ndcha>0 and self.oText.compareRegionStarts(self.oAnchor.getStart(),doc.cur.getEnd())==-1:
2746            ndcha=ndcha+1
2747          doc.cur.collapseToStart()
2748          doc.cur.goLeft(nizda,0)
2749          doc.cur.goRight(nizda+ncent+ndcha,1)
2750    return doc.cur
2751 
2752  def Substituir(self,cur):
2753    #Substituir la palabra actual
2754    #cur=self.DamePalEnNota()
2755    cur.CharContoured=False
2756    if self.prauclau.lower()==cur.String.lower():
2757      cur.String=self.prautxtpro
2758      #Revisar frase modificada
2759      if self.praucom=="trad" or self.praucom=="tradi":
2760        if self.praudtr=="i":
2761          comando="revi"
2762        else:
2763          comando="rev"
2764        self.Rev(cur,comando,self.sck)
2765
2766  def Rev(self,cur,comando,sck):
2767    #Revisar frase modificada
2768    #Entrada:   
2769    #         cur: cursor en el documento a revisar
2770    #         comando: revision directa o inversa ('rev','revi')
2771    #         sck: Socket con el servidor Salt
2772    selcur=self.RevSelec(cur)
2773    cur.gotoRange(selcur.getStart(),0)
2774    doc=sltDoc(self.model,cur,unit='s',curfin=selcur.getEnd())
2775    #sck=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
2776    #sck.connect(('localhost',20001))
2777    #ret=doc.gotoStart()
2778    ret=True
2779    while ret==True and sck!=None and not doc.isEndSel():
2780      #1. Obtener lista de palabras
2781      colPalDu={}
2782      colTx=[]
2783      doc.Marca()
2784      colTx=doc.DocLista(colTx)
2785 
2786      if len(colTx)>0:
2787        #2. Orden de correcion de la frase
2788        datos=str((comando,(colTx,colPalDu))).encode('latin-1')
2789        sck.send(datos)
2790        datos=sck.recv(128000).decode('latin-1')
2791        comandorec,(colTx,colPalDu)=eval(datos)
2792   
2793        #3. Actualizar documento
2794        if comandorec!="void":
2795          colPalDu={}
2796          doc.Sync()
2797          doc.ListaDoc(colTx,colPalDu,comando)
2798
2799      ret=doc.cur.gotoNextWord(0)
2800
2801  def RevSelec(self,cur,n=2):
2802    #Obtener una selección (rango) a revisar a partir de la palabra actual en cur
2803    #n es el número de palabras a cada lado
2804    #No puede sobrepasar notas ni hacia delante ni hacia atrás
2805    #Retorno:cursor que tiene seleccionado el rango
2806    nacur=npcur=None
2807    text=cur.getText()
2808    if self.iNotas>0:
2809      if text==self.lsNotas[self.iNotas-1][2]:
2810        nacur=self.lsNotas[self.iNotas-1][3]
2811        nacur.goRight(1,0)
2812    if self.iNotas<len(self.lsNotas)-2:
2813      if text==self.lsNotas[self.iNotas+1][2]:
2814        npcur=self.lsNotas[self.iNotas+1][3]
2815    reta=retb=True
2816    rcura=text.createTextCursorByRange(cur)
2817    rcurp=text.createTextCursorByRange(cur)
2818    raok=rcura.getStart()
2819    rpok=rcurp.getEnd()
2820    rcurp.collapseToEnd()
2821    rcurp.gotoNextWord(0)
2822    while n>0 and (reta or retb):
2823      reta=rcura.gotoPreviousWord(1)
2824      retp=rcurp.gotoEndOfWord(1)
2825      if n>1:
2826        retp=rcurp.gotoNextWord(1)
2827      #Comprobar que no sobrepasamos notas
2828      if nacur!=None:
2829        if text.compareRegionStarts(nacur,rcura)==1:
2830          raok=rcura.getStart()
2831      else:
2832        raok=rcura.getStart()
2833      if npcur!=None:
2834        if text.compareRegionEnds(rcurp,npcur)==1:
2835          rpok=rcurp.getEnd()
2836      else:
2837        rpok=rcurp.getEnd()
2838      n=n-1
2839    selcur=text.createTextCursorByRange(raok)
2840    selcur.gotoRange(rpok,1)
2841    return selcur
2842
2843# end of class CtvWindow
2844
2845class ProWindow(DBListenerWindow):
2846  def __init__(self,model):
2847    #DBListenerWindow.__init__( self, "Processant" ,nWindowAttributes=uno.getConstantByName("com.sun.star.awt.WindowAttribute.SHOW")+uno.getConstantByName("com.sun.star.awt.WindowAttribute.MOVEABLE"))
2848    DBListenerWindow.__init__( self, "Processant:"+model.getCurrentController().getFrame().Title)
2849    #self.addProgressBar("prbPro",5,10,300,16)
2850    self.addImageControl("imgPro1",5,10,300,16,nBorder=2)
2851    self.addImageControl("imgPro2",5,10,0,16,nBorder=2)
2852    self.setImageControlBackgroundColor("imgPro2",int(255))
2853    #self.addFixedText("txtPro",5,10,300,16)
2854    #self.setFixedTextAlignment("txtPro",1)
2855    self.addButton( "cmbCancel", 310, 10, 60, 16, "Cancel·lar", actionListenerProc = self.cmbCancel_clicked ) 
2856   
2857    wpos={'left':100,'top':200,'width':460,'height':40}
2858    self.setWindowPosSize( wpos['left'], wpos['top'], wpos['width'], wpos['height'] )
2859
2860    #La barra de progreso por defecto entre 0 y 100
2861    #self.setProgressRange("prbPro",0,100)
2862   
2863    self.Min=0
2864    self.Max=100
2865   
2866    self.terminar=False
2867   
2868  #Eventos
2869  def cmbCancel_clicked( self, oActionEvent ): 
2870    """This is called when the Cancel button is clicked."""
2871    self.terminar=True
2872   
2873  def windowClosed(self,oActionEvent):
2874    self.terminar=True
2875    rect=self.getWindowPosSize()
2876    self.wp["prowindow"]=str({'left':rect.X,'top':rect.Y,'width':rect.Width,'height':rect.Height})
2877    self.wp.sync()
2878    selp.wp.close()
2879   
2880  def windowClosing(self,oActionEvent):
2881    pass
2882
2883  #Métodos
2884  def Close(self):
2885    #Cerrar ventana
2886    self.windowClose()
2887 
2888  def Cancel(self):
2889    #Devuelve True si hay que terminar (proceso cancelado)
2890    return self.terminar
2891 
2892  def MinMax(self,min,max):
2893    #Asigna los valores mínimo y máximo de la barra de progreso
2894    #self.setProgressRange("prbPro",min,max)
2895    #self.setProgressValue("prbPro",min)
2896    self.Min=min
2897    self.Max=max
2898   
2899  def Value(self,valor):
2900    #Asigna un valor a la barra de progreso
2901    #self.setProgressValue("prbPro",valor)
2902    rect1=self.getControl("imgPro1").getPosSize()
2903    w2=(valor/(self.Max-self.Min))*rect1.Width
2904    if w2<0:
2905      w2=0
2906    if w2>rect1.Width:
2907      w2=rect1.Width
2908    rect2=self.getControl("imgPro2").getPosSize()
2909    self.setSize("imgPro2",w2,rect2.Height)
2910    #self.setFixedTextText("txtPro",str(int(valor)) + " %")
2911    #self.windowToFront()
2912 
2913# end of class ProWindow
2914
2915class MsgWindow(DBListenerWindow):
2916  def __init__(self,msg):
2917    DBListenerWindow.__init__( self, u"Missatge de Salt")
2918    self.addFixedText("txtMsg",5,10,300,16,msg)
2919    self.setFixedTextAlignment("txtMsg",1)
2920    self.addButton( "cmbCancel", 310, 10, 60, 16, u"Cancel·lar", actionListenerProc = self.cmbCancel_clicked ) 
2921    wpos={'left':100,'top':200,'width':460,'height':40}
2922    self.setWindowPosSize( wpos['left'], wpos['top'], 460, 40 )
2923    self.windowToFront()
2924
2925  #Eventos
2926  def cmbCancel_clicked( self, oActionEvent ): 
2927    """This is called when the Cancel button is clicked."""
2928    self.windowClose()
2929   
2930  def windowClosed(self,oActionEvent):
2931    rect=self.getWindowPosSize()
2932    self.wp["msgwindow"]=str({'left':rect.X,'top':rect.Y,'width':rect.Width,'height':rect.Height})
2933    self.wp.sync()
2934    selp.wp.close()
2935    pass
2936
2937# end of class MsgWindow
2938
2939class CtvMouse:
2940  def __init__(self):
2941    pass
2942  def RegisterMouseClickHandler(self):
2943    pass
2944   
2945# end of class CtvMouse
2946
2947# pythonloader looks for a static g_ImplementationHelper variable
2948g_ImplementationHelper = unohelper.ImplementationHelper()
2949
2950#
2951g_ImplementationHelper.addImplementation( \
2952                ooUNOobj,                        # UNO object class
2953                "org.openoffice.Office.addon.salt.trad.ooUNOobj", # implementation name
2954                                                                                        # Change this name for your own
2955                                                        # script
2956                ("com.sun.star.task.Job",),)          # list of implemented services
2957                                                    # (the only service)
Note: See TracBrowser for help on using the repository browser.