Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / librelogo / source / LibreLogo / LibreLogo.py
blob33fe172631ad59b9523d157ce819863ec8e84897
1 # -*- encoding: UTF-8 -*-
2 # -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
4 # This file is part of the LibreOffice project.
6 # This Source Code Form is subject to the terms of the Mozilla Public
7 # License, v. 2.0. If a copy of the MPL was not distributed with this
8 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 from __future__ import unicode_literals
11 import sys, os, uno, unohelper
12 import re, random, traceback, itertools
13 import threading, time as __time__
15 try:
16 unicode
17 next = lambda l: l.next() # python 2
18 except:
19 unicode, long = str, int # support python 3
21 urebootstrap = os.environ["URE_BOOTSTRAP"]
22 if "vnd.sun.star.pathname" in urebootstrap:
23 __lngpath__ = re.sub(r"^vnd.sun.star.pathname:(.*)program(/|\\)fundamental([.]ini|rc)$", "\\1", urebootstrap)
24 else:
25 __lngpath__ = unohelper.fileUrlToSystemPath(re.sub("program/(fundamental.ini|fundamentalrc)$", "", urebootstrap))
26 __lngpath__ = __lngpath__ + "share/Scripts/python/LibreLogo/".replace("/", os.sep)
27 __translang__ = "am|ca|cs|de|dk|el|en|eo|es|et|fr|hu|it|ja|nl|no|pl|pt|ru|se|sl" # FIXME supported languages for language guessing, expand this list, according to the localizations
28 __lng__ = {}
29 __docs__ = {}
30 __prevcode__ = None
31 __prevlang__ = None
32 __prevcompiledcode__ = None
33 __thread__ = None
34 __lock__ = threading.Lock()
35 __halt__ = False
36 __compiled__ = ""
37 __group__ = 0
38 __groupstack__ = []
39 __grouplefthang__ = 0
40 __comp__ = {}
41 __strings__ = []
42 __colors__ = {}
43 __COLORS__ = ['BLACK', 0x000000], ['SILVER', 0xc0c0c0], ['GRAY', 0x808080], \
44 ['WHITE', 0xffffff], ['MAROON', 0x800000], ['RED', 0xff0000], \
45 ['PURPLE', 0x800080], ['FUCHSIA', 0xff00ff], ['GREEN', 0x008000], \
46 ['LIME', 0x00ff00], ['OLIVE', 0x808000], ['YELLOW', 0xffff00], \
47 ['NAVY', 0x000080], ['BLUE', 0x0000ff], ['TEAL', 0x008080], \
48 ['AQUA', 0x00ffff], ['PINK', 0xffc0cb], ['TOMATO', 0xff6347], \
49 ['ORANGE', 0xffa500], ['GOLD', 0xffd700], ['VIOLET', 0x9400d3], \
50 ['SKYBLUE', 0x87ceeb], ['CHOCOLATE', 0xd2691e], ['BROWN', 0xa52a2a], \
51 ['INVISIBLE', 0xffffffff]
52 __STRCONST__ = [i[0] for i in __COLORS__] + ['NONE', 'BEVEL', 'MITER', 'ROUNDED', 'SOLID', 'DASH', 'DOTTED', 'BOLD', 'ITALIC', 'UPRIGHT', 'NORMAL', "HOUR", "PT", "INCH", "MM", "CM"]
53 __SLEEP_SLICE_IN_MILLISECONDS__ = 500
54 __PT_TO_TWIP__ = 20
55 __MM_TO_PT__ = 1/(25.4/72)
56 __MM10_TO_TWIP__ = 1/(2540.0/72/20) # 0.01 mm to twentieth point
57 __FILLCOLOR__ = 0x8000ff00
58 __LINEWIDTH__ = 0.5 * __PT_TO_TWIP__
59 __ENCODED_STRING__ = "_s_%s___"
60 __DECODE_STRING_REGEX__ = "_s_([0-9]+)___"
61 __LINEBREAK__ = "#_@L_i_N_e@_#"
62 __TURTLE__ = "turtle"
63 __ACTUAL__ = "actual"
64 __BASEFONTFAMILY__ = "Linux Biolinum G"
65 __LineStyle_DOTTED__ = 2
67 class __Doc__:
68 def __init__(self, doc):
69 self.doc = doc
70 try:
71 self.drawpage = doc.DrawPage # Writer
72 except:
73 self.drawpage = doc.DrawPages.getByIndex(0) # Draw, Impress
74 self.shapecache = {}
75 self.shapecount = itertools.count()
76 self.time = 0
77 self.zoomvalue = 0
78 self.initialize()
80 def initialize(self):
81 self.pen = 1
82 self.pencolor = 0
83 self.pensize = __LINEWIDTH__
84 self.linestyle = __LineStyle_SOLID__
85 self.linejoint = __ROUNDED__
86 self.linecap = __Cap_NONE__
87 self.oldlc = 0
88 self.oldlw = 0
89 self.oldls = __LineStyle_SOLID__
90 self.oldlj = __ROUNDED__
91 self.continuous = True
92 self.areacolor = __FILLCOLOR__
93 self.hatch = None
94 self.textcolor = 0
95 self.fontfamily = __BASEFONTFAMILY__
96 self.fontheight = 12
97 self.fontweight = 100
98 self.fontstyle = 0
100 from math import pi, sin, cos, asin, sqrt
102 from com.sun.star.awt import Point as __Point__
103 from com.sun.star.drawing import LineDash as __LineDash__
104 from com.sun.star.drawing import Hatch as __Hatch__
105 from com.sun.star.drawing import PolyPolygonBezierCoords as __Bezier__
106 from com.sun.star.text.TextContentAnchorType import AT_PAGE as __AT_PAGE__
107 from com.sun.star.text.WrapTextMode import THROUGHT as __THROUGHT__
108 from com.sun.star.drawing.LineCap import BUTT as __Cap_NONE__
109 from com.sun.star.drawing.LineCap import ROUND as __Cap_ROUND__
110 from com.sun.star.drawing.LineCap import SQUARE as __Cap_SQUARE__
111 from com.sun.star.drawing.LineJoint import NONE as __Joint_NONE__
112 from com.sun.star.drawing.LineJoint import BEVEL as __BEVEL__
113 from com.sun.star.drawing.LineJoint import MITER as __MITER__
114 from com.sun.star.drawing.LineJoint import ROUND as __ROUNDED__
115 from com.sun.star.drawing.FillStyle import NONE as __FillStyle_NONE__
116 from com.sun.star.drawing.LineStyle import NONE as __LineStyle_NONE__
117 from com.sun.star.drawing.LineStyle import SOLID as __LineStyle_SOLID__
118 from com.sun.star.drawing.LineStyle import DASH as __LineStyle_DASHED__
119 from com.sun.star.drawing.DashStyle import RECT as __DashStyle_RECT__
120 from com.sun.star.drawing.DashStyle import ROUND as __DashStyle_ROUND__
121 from com.sun.star.drawing.DashStyle import ROUNDRELATIVE as __DashStyle_ROUNDRELATIVE__
122 from com.sun.star.drawing.CircleKind import FULL as __FULL__
123 from com.sun.star.drawing.CircleKind import SECTION as __SECTION__
124 from com.sun.star.drawing.CircleKind import CUT as __CUT__
125 from com.sun.star.drawing.CircleKind import ARC as __ARC__
126 from com.sun.star.awt.FontSlant import NONE as __Slant_NONE__
127 from com.sun.star.awt.FontSlant import ITALIC as __Slant_ITALIC__
128 from com.sun.star.awt import Size as __Size__
129 from com.sun.star.awt import WindowDescriptor as __WinDesc__
130 from com.sun.star.awt.WindowClass import MODALTOP as __MODALTOP__
131 from com.sun.star.awt.VclWindowPeerAttribute import OK as __OK__
132 from com.sun.star.awt.VclWindowPeerAttribute import OK_CANCEL as __OK_CANCEL__
133 from com.sun.star.awt.VclWindowPeerAttribute import YES_NO_CANCEL as __YES_NO_CANCEL__ # OK_CANCEL, YES_NO, RETRY_CANCEL, DEF_OK, DEF_CANCEL, DEF_RETRY, DEF_YES, DEF_NO
134 from com.sun.star.awt.PushButtonType import OK as __Button_OK__
135 from com.sun.star.awt.PushButtonType import CANCEL as __Button_CANCEL__
136 from com.sun.star.util.MeasureUnit import APPFONT as __APPFONT__
137 from com.sun.star.beans import PropertyValue as __property__
138 from com.sun.star.lang import Locale
140 def __getprop__(name, value):
141 p, p.Name, p.Value = __property__(), name, value
142 return p
144 __uilocale__ = uno.getComponentContext().ServiceManager.createInstance("com.sun.star.configuration.ConfigurationProvider").\
145 createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess",\
146 (__getprop__("nodepath", "/org.openoffice.Setup/L10N"),)).getByName("ooLocale") + '-' # handle missing Country of locale 'eo'
148 def __l12n__(lng):
149 try:
150 return __lng__[lng]
151 except:
152 try:
153 __lng__[lng] = dict([[i.decode("unicode-escape").split("=")[0].strip(), i.decode("unicode-escape").split("=")[1].strip().strip("|")] for i in open(__lngpath__ + "LibreLogo_" + lng + ".properties", 'rb').readlines() if b"=" in i])
154 return __lng__[lng]
155 except Exception:
156 __trace__()
157 return None
159 # dot for dotted line (implemented as an array of dot-headed arrows, because PostScript dot isn't supported by Writer)
160 def __gendots__(n):
161 return [__Point__(round(sin(360.0/n * i * pi/180.0) * 600), round(cos(360.0/n * i * pi/180) * 600)) for i in range(n)]
162 __bezierdot__ = __Bezier__()
163 __bezierdot__.Coordinates = (tuple(__gendots__(32)),)
164 __bezierdot__.Flags = ((0,) * 32,)
166 # turtle shape
167 __TURTLESHAPE__ = [tuple([(__Point__(-120, 130), __Point__(-245, 347), __Point__(-291, 176), ), (__Point__(0, -500), __Point__(126, -375), __Point__(0, -250), __Point__(-124, -375), ), (__Point__(295, 170), __Point__(124, 124), __Point__(250, 340), ), (__Point__(466, -204), __Point__(224, -269), __Point__(71, -180), __Point__(313, -116), ), (__Point__(-75, -175), __Point__(-292, -300), __Point__(-417, -83), ), (__Point__(250, 0), __Point__(0, -250), __Point__(-250, 0), __Point__(0, 250), )] +
168 [(i,) for i in __gendots__(32)] + # single points for wider selection
169 [(__Point__(0, 0),)]), # last point for position handling
170 ((__Point__(0, 0),),)] # hidden turtle (single point to draw at the left border of the page area)
172 def __getdocument__():
173 global __docs__, _
174 doc = XSCRIPTCONTEXT.getDocument()
175 try:
176 _ = __docs__[doc.Title]
177 _.doc.Title # Is existing instance (not the garbage of the previous instance of a reopened document or a new "Untitled 1")?
178 except:
179 _ = __Doc__(doc)
180 __docs__[doc.Title] = _
182 # input function, result: input string or 0
183 def Input(s):
184 global __halt__
185 try:
186 ctx = uno.getComponentContext()
187 smgr = ctx.ServiceManager
188 text = ""
190 # dialog
191 d = smgr.createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", ctx)
192 ps = _.doc.CurrentController.Frame.ContainerWindow.getPosSize()
193 lo = _.doc.CurrentController.Frame.ContainerWindow.convertSizeToLogic(__Size__(ps.Width, ps.Height), __APPFONT__)
194 d.PositionX, d.PositionY, d.Width, d.Height = lo.Width/2 - 75, lo.Height/2 - 25, 150, 50
196 # label
197 l = d.createInstance("com.sun.star.awt.UnoControlFixedTextModel" )
199 if type(s) == list:
200 text = s[1]
201 s = s[0]
202 l.PositionX, l.PositionY, l.Width, l.Height, l.Name, l.TabIndex, l.Label = 5, 4, 140, 14, "l1", 2, s
204 # textbox or combobox
205 e = d.createInstance("com.sun.star.awt.UnoControlEditModel")
206 e.PositionX, e.PositionY, e.Width, e.Height, e.Name, e.TabIndex = 5, 14, 140, 12, "e1", 0
208 # buttons
209 b = d.createInstance( "com.sun.star.awt.UnoControlButtonModel" )
210 b.PositionX, b.PositionY, b.Width, b.Height, b.Name, b.TabIndex, b.PushButtonType, b.DefaultButton = 55, 32, 45, 14, "b1", 1, __Button_OK__, True
211 b2 = d.createInstance( "com.sun.star.awt.UnoControlButtonModel" )
212 b2.PositionX, b2.PositionY, b2.Width, b2.Height, b2.Name, b2.TabIndex, b2.PushButtonType = 100, 32, 45, 14, "b2", 1, __Button_CANCEL__
214 # insert the control models into the dialog model
215 d.insertByName( "l1", l)
216 d.insertByName( "b1", b)
217 d.insertByName( "b2", b2)
218 d.insertByName( "e1", e)
220 # create the dialog control and set the model
221 controlContainer = smgr.createInstanceWithContext("com.sun.star.awt.UnoControlDialog", ctx)
222 controlContainer.setModel(d)
224 # create a peer
225 toolkit = smgr.createInstanceWithContext("com.sun.star.awt.ExtToolkit", ctx)
226 controlContainer.setVisible(False)
227 controlContainer.createPeer(toolkit, None)
229 # execute it
230 inputtext = controlContainer.execute()
231 if inputtext:
232 inputtext = e.Text
233 else:
234 __halt__ = True
236 # dispose the dialog
237 controlContainer.dispose()
238 return inputtext
239 except Exception:
240 __trace__()
242 def __string__(s, decimal = None): # convert decimal sign, localized BOOL and SET
243 if not decimal:
244 decimal = _.decimal
245 if decimal == ',' and type(s) == float:
246 return str(s).replace(".", ",")
247 if type(s) in [list, tuple, dict, set]:
248 __strings__ = []
249 s = re.sub("(?u)(['\"])(([^'\"]|\\['\"])*)(?<!\\\\)\\1", __encodestring__, str(s)) # XXX fix double '\'\"'
250 if decimal == ',':
251 s = s.replace(".", ",")
252 return re.sub(__DECODE_STRING_REGEX__, __decodestring__, \
253 s.replace('set', __locname__('SET')).replace('True', __locname__('TRUE')).replace('False', __locname__('FALSE')))
254 if type(s) in [str, unicode]:
255 return s
256 elif type(s) == bool:
257 return __locname__(str(s).upper())
258 return str(s)
260 def Print(s):
261 global __halt__
262 s = __string__(s, _.decimal)
263 if not MessageBox(_.doc.CurrentController.Frame.ContainerWindow, s[:500] + s[500:5000].replace('\n', ' '), "", "messbox", __OK_CANCEL__):
264 __halt__ = True
266 def MessageBox(parent, message, title, msgtype = "messbox", buttons = __OK__):
267 msgtypes = ("messbox", "infobox", "errorbox", "warningbox", "querybox")
268 if not (msgtype in msgtypes):
269 msgtype = "messbox"
270 d = __WinDesc__()
271 d.Type = __MODALTOP__
272 d.WindowServiceName = msgtype
273 d.ParentIndex = -1
274 d.Parent = parent
275 d.WindowAttributes = buttons
276 tk = parent.getToolkit()
277 msgbox = tk.createWindow(d)
278 msgbox.setMessageText(message)
279 if title:
280 msgbox.setCaptionText(title)
281 return msgbox.execute()
283 def Random(r):
284 try:
285 return r * random.random()
286 except:
287 return list(r)[int(random.random() * len(r))]
289 def to_ascii(s):
290 return s.encode("unicode-escape").decode("utf-8").replace("\\u", "__u__").replace(r"\x", "__x__")
292 def to_unicode(s):
293 return bytes(s.replace("__x__", r"\x").replace("__u__", "\\u"), "ascii").decode("unicode-escape")
295 def __trace__():
296 if 'PYUNO_LOGLEVEL' in os.environ:
297 print(traceback.format_exc())
299 def __locname__(name, l = -1):
300 if l == -1:
301 l = _.lng
302 for i in __l12n__(l):
303 if i == name.upper():
304 return __l12n__(l)[i].split("|")[0] # return with the first localized name
305 return to_unicode(name)
307 def __getcursor__(fulltext):
308 try:
309 text = _.doc.getCurrentController().getViewCursor().getText().createTextCursor() # copy selection (also in frames)
310 text.gotoRange(_.doc.getCurrentController().getViewCursor(), False)
311 if fulltext:
312 1/len(text.getString()) # exception, if zero length
313 except:
314 text = _.doc.getText().createTextCursorByRange(_.doc.getText().getStart())
315 text.gotoEnd(True)
316 return text
318 def __translate__(arg = None):
319 global _
320 __getdocument__()
321 selection = __getcursor__(True)
322 __initialize__()
323 __setlang__()
324 # detect language
325 text = selection.getString()
326 # remove comments and strings
327 text = re.sub(r"[ ]*;[^\n]*", "", re.sub(r"['„“‘«»「][^\n'”“‘’«»」]*['”“‘’«»」]", "", re.sub(r"^[ \t]*[;#][^\n]*", "", text)))
328 text = " ".join(set(re.findall("(?u)\w+", text)) - set(re.findall("(?u)\w*\d+\w*", text))).lower() # only words
329 ctx = uno.getComponentContext()
330 guess = ctx.ServiceManager.createInstanceWithContext("com.sun.star.linguistic2.LanguageGuessing", ctx)
331 guess.disableLanguages(guess.getEnabledLanguages())
332 guess.enableLanguages(tuple([Locale(i, "", "") for i in __translang__.split("|")]))
333 guess = guess.guessPrimaryLanguage(text, 0, len(text))
334 try:
335 l = {'cs': 'cs_CZ', 'el': 'el_GR', 'en': 'en_US', 'pt': 'pt_BR'}[guess.Language]
336 except:
337 l = guess.Language + '_' + guess.Language.upper()
338 lang = __l12n__(l)
339 if not lang:
340 lang = __l12n__(guess.Language)
341 if not lang:
342 lang = __l12n__(_.lng)
343 if not lang:
344 lang = __l12n__("en_US")
345 lq = '\'' + lang['LEFTSTRING'].replace("|", "")
346 rq = '\'' + lang['RIGHTSTRING'].replace("|", "")
347 __strings__ = []
349 text = re.sub("(?u)([%s])([^\n%s]*)(?<!\\\\)[%s]" % (lq, rq, rq), __encodestring__, selection.getString())
350 text = re.sub('(?u)(?<![0-9])(")(~?\w*)', __encodestring__, text)
352 # translate the program to the language of the document FIXME space/tab
353 exception = ['DECIMAL']
354 in1 = lang['IN'].upper()
355 in2 = __l12n__(_.lng)['IN'].split("|")[0].upper()
356 if in1[0] == '-' and in2[0] != '-': # "for x y-in" -> "for x in y"
357 exception += ['IN']
358 text = re.sub(r"(?ui)\b((?:%s) +:?\w+) +([^\n]+)(?:%s) +(?=[[] |[[]\n)" % (lang['FOR'], in1), "\\1 %s \\2 " % in2, text)
359 text = re.sub(r"(?ui)(:?\b\w+|[[][^[\n]*])\b(?:%s)\b" % in1, "%s \\1" % in2, text)
360 elif in1[0] != '-' and in2[0] == '-': # "for x in y" -> "for x y-in"
361 exception += ['IN']
362 text = re.sub(r"(?ui)(?<=\n)((?:%s)\b +:?\w+) +(?:%s) +([^\n]+?) +(?=[[] |[[]\n)" % (lang['FOR'], in1), "\\1 \\2%s " % in2, text)
363 text = re.sub(r"(?ui)(?<!:)\b(?:%s) +(:?\b\w+|[[][^[\n]*])\b" % in1, "\\1%s" % in2, text)
364 for i in set(lang) - set(exception):
365 text = re.sub(r'(?ui)(?<!:)\b(%s)\b' % lang[i], __l12n__(_.lng)[i].split("|")[0].upper(), text)
366 text = re.sub(r"(?<=\d)[%s](?=\d)" % lang['DECIMAL'], __l12n__(_.lng)['DECIMAL'], text)
368 # decode strings
369 quoted = u"(?ui)(?<=%s)(%%s)(?=%s)" % (__l12n__(_.lng)['LEFTSTRING'][0], __l12n__(_.lng)['RIGHTSTRING'][0])
370 text = re.sub(__DECODE_STRING_REGEX__, __decodestring2__, text)
371 for i in __STRCONST__:
372 text = re.sub(quoted % lang[i], __l12n__(_.lng)[i].split("|")[0].upper(), text)
373 selection.setString(text)
374 # convert to paragraphs
375 __dispatcher__(".uno:ExecuteSearch", (__getprop__("SearchItem.SearchString", r"\n"), __getprop__("SearchItem.ReplaceString", r"\n"), \
376 __getprop__("Quiet", True), __getprop__("SearchItem.Command", 3), __getprop__("SearchItem.StyleFamily", 2), \
377 __getprop__("SearchItem.AlgorithmType", 1), __getprop__("SearchItem.RowDirection", 1), __getprop__("SearchItem.SearchFlags", 65536)))
379 class LogoProgram(threading.Thread):
380 def __init__(self, code):
381 self.code = code
382 threading.Thread.__init__(self)
384 def run(self):
385 global __thread__
386 try:
387 exec(self.code)
388 if _.origcursor:
389 __dispatcher__(".uno:Escape")
390 try:
391 _.doc.CurrentController.getViewCursor().gotoRange(_.origcursor, False)
392 except:
393 _.doc.CurrentController.getViewCursor().gotoRange(_.origcursor.getStart(), False)
394 except Exception as e:
395 try:
396 TRACEPATTERN = '"<string>", line '
397 message = traceback.format_exc()
398 l = re.findall(TRACEPATTERN + '[0-9]+', message)
399 if len(l) > 0 and not "SystemExit" in message:
400 line = len(re.findall(__LINEBREAK__, ''.join(self.code.split("\n")[:int(l[-1][len(TRACEPATTERN):])]))) + 1
401 caption = __l12n__(_.lng)['LIBRELOGO']
402 if __prevcode__ and "\n" in __prevcode__:
403 __gotoline__(line)
404 caption = __l12n__(_.lng)['ERROR'] % line
405 parent = _.doc.CurrentController.Frame.ContainerWindow
406 if "maximum recursion" in message:
407 MessageBox(parent, __l12n__(_.lng)['ERR_STOP'] + " " + __l12n__(_.lng)['ERR_MAXRECURSION'] % sys.getrecursionlimit(), __l12n__(_.lng)['LIBRELOGO'])
408 elif "cannot initialize memory" in message or "Couldn't instantiate" in message:
409 MessageBox(parent, __l12n__(_.lng)['ERR_STOP'] + " " + __l12n__(_.lng)['ERR_MEMORY'], __l12n__(_.lng)['LIBRELOGO'])
410 elif "ZeroDivisionError" in message:
411 MessageBox(parent, __l12n__(_.lng)['ERR_ZERODIVISION'], caption, "errorbox")
412 elif "IndexError" in message:
413 MessageBox(parent, __l12n__(_.lng)['ERR_INDEX'], caption, "errorbox")
414 elif "KeyError" in message:
415 MessageBox(parent, __l12n__(_.lng)['ERR_KEY'] % eval(re.search("KeyError: ([^\n]*)", message).group(1)), caption, "errorbox")
416 elif "NameError" in message:
417 if "__repeat__" in message:
418 MessageBox(parent, __l12n__(_.lng)['ERR_ARGUMENTS'] % (__locname__('REPEAT'), 1, 0), caption, "errorbox")
419 else:
420 MessageBox(parent, __l12n__(_.lng)['ERR_NAME'] % \
421 to_unicode(re.search("(?<=name ')[\w_]*(?=')", message).group(0)), caption, "errorbox")
422 elif "TypeError" in message and "argument" in message and "given" in message:
423 r = re.search("([\w_]*)[(][)][^\n]* (\w+) arguments? [(](\d+)", message) # XXX later: handle 'no arguments' + plural
424 MessageBox(parent, __l12n__(_.lng)['ERR_ARGUMENTS'] % (__locname__(r.group(1)), r.group(2), r.group(3)), caption, "errorbox")
425 else:
426 origline = __compiled__.split("\n")[line-1]
427 if not "com.sun.star" in message and not "__repeat__" in message and not "*)" in message and ("[" in origline or "]" in origline):
428 MessageBox(parent, __l12n__(_.lng)['ERR_BLOCK'], caption, "errorbox")
429 else:
430 MessageBox(parent, __l12n__(_.lng)['ERROR'] %line, __l12n__(_.lng)['LIBRELOGO'], "errorbox")
431 __trace__()
432 except:
433 pass
434 with __lock__:
435 __thread__ = None
438 def __encodestring__(m):
439 __strings__.append(re.sub("\\[^\\]", "", m.group(2)))
440 return __ENCODED_STRING__ % (len(__strings__) - 1)
442 def __decodestring__(m):
443 return "u'%s'" % __strings__[int(m.group(1))]
445 def __decodestring2__(m):
446 return __l12n__(_.lng)['LEFTSTRING'][0] + __strings__[int(m.group(1))] + __l12n__(_.lng)['RIGHTSTRING'][0]
448 def __initialize__():
449 global __halt__, __thread__
450 __getdocument__()
451 _.zoomvalue = _.doc.CurrentController.getViewSettings().ZoomValue
452 shape = __getshape__(__TURTLE__)
453 if not shape:
454 shape = _.doc.createInstance( "com.sun.star.drawing.PolyPolygonShape" )
455 shape.AnchorType = __AT_PAGE__
456 shape.TextWrap = __THROUGHT__
457 shape.Opaque = True
458 _.drawpage.add(shape)
459 shape.PolyPolygon = __TURTLESHAPE__[0]
460 _.shapecache[__TURTLE__] = shape
461 shape.Name = __TURTLE__
462 _.initialize()
463 turtlehome()
464 _.doc.CurrentController.select(shape)
465 shape.FillColor, transparence = __splitcolor__(_.areacolor)
466 shape.LineColor, shape.LineTransparence = __splitcolor__(_.pencolor)
467 elif shape.Visible:
468 if shape.FillStyle == __FillStyle_NONE__:
469 _.areacolor = 0xffffffff
470 else:
471 _.areacolor = shape.FillColor + (int(255.0 * shape.FillTransparence/100) << 24)
472 if shape.LineWidth != round((1 + _.pen * 2) * __PT_TO_TWIP__ / __MM10_TO_TWIP__) and shape.LineWidth != round(__LINEWIDTH__ / __MM10_TO_TWIP__):
473 _.pensize = shape.LineWidth * __MM10_TO_TWIP__
474 if shape.LineStyle == __LineStyle_NONE__: # - none -
475 __pen__(0)
476 else:
477 if shape.LineStyle == __LineStyle_SOLID__:
478 __pen__(1)
479 _.pencolor = shape.LineColor + (int(255.0 * shape.LineTransparence/100) << 24)
480 shape.LineJoint = __ROUNDED__
481 shape.Shadow = True
482 shape.FillColor, transparence = __splitcolor__(_.areacolor)
483 shape.FillTransparence = min(95, transparence)
484 shape.ShadowColor, shape.ShadowTransparence, shape.ShadowXDistance, shape.ShadowYDistance = (0, 20, 0, 0)
485 shape.LineWidth = min(_.pensize, (1 + _.pen * 2) * __PT_TO_TWIP__) / __MM10_TO_TWIP__
486 shape.SizeProtect = True
488 def pagesize(n = -1):
489 if n == -1:
490 ps = _.doc.CurrentController.getViewCursor().PageStyleName
491 page = _.doc.StyleFamilies.getByName("PageStyles").getByName(ps)
492 return [page.Width * __MM10_TO_TWIP__ / __PT_TO_TWIP__, page.Height * __MM10_TO_TWIP__ / __PT_TO_TWIP__]
493 return None
495 def turtlehome():
496 turtle = __getshape__(__TURTLE__)
497 if turtle:
498 ps = _.doc.CurrentController.getViewCursor().PageStyleName
499 page = _.doc.StyleFamilies.getByName("PageStyles").getByName(ps)
500 turtle.setPosition(__Point__((page.Width - turtle.BoundRect.Width)/2, (page.Height - turtle.BoundRect.Height)/2))
501 turtle.LineStyle = __LineStyle_SOLID__
502 turtle.LineJoint = __MITER__
503 turtle.LineWidth = min(_.pensize, (1 + _.pen * 2) * __PT_TO_TWIP__) / __MM10_TO_TWIP__
504 turtle.LineColor, none = __splitcolor__(_.pencolor)
505 turtle.LineTransparence = 25
506 turtle.RotateAngle = 0
507 turtle.ZOrder = 1000
509 def __pen__(n):
510 _.pen = n
511 turtle = __getshape__(__TURTLE__)
512 if turtle:
513 if n:
514 turtle.LineStyle = __LineStyle_SOLID__
515 turtle.LineWidth = min(_.pensize, 3 * __PT_TO_TWIP__) / __MM10_TO_TWIP__
516 else:
517 turtle.LineStyle = __LineStyle_DASHED__
518 turtle.LineDash = __LineDash__(__DashStyle_RECT__, 0, 0, 1, __PT_TO_TWIP__, __PT_TO_TWIP__)
519 turtle.LineWidth = min(_.pensize, __PT_TO_TWIP__) / __MM10_TO_TWIP__
522 def __visible__(shape, visible = -1): # for OOo 3.2 compatibility
523 try:
524 if visible == -1:
525 return shape.Visible
526 shape.Visible = visible
527 except:
528 return True
530 def hideturtle():
531 turtle = __getshape__(__TURTLE__)
532 if turtle and turtle.Visible:
533 z = turtle.getPosition()
534 z = __Point__(z.X + turtle.BoundRect.Width / 2.0, z.Y + turtle.BoundRect.Height / 2.0)
535 turtle.PolyPolygon = __TURTLESHAPE__[1]
536 __visible__(turtle, False)
537 turtle.LineTransparence, turtle.FillTransparence = 100, 100 # for saved files
538 turtle.setPosition(z)
539 __dispatcher__(".uno:Escape")
541 def showturtle():
542 turtle = __getshape__(__TURTLE__)
543 if turtle and not turtle.Visible:
544 if not turtle.Parent:
545 _.drawpage.add(turtle)
546 z = turtle.getPosition()
547 r, turtle.RotateAngle = turtle.RotateAngle, 0
548 turtle.PolyPolygon, turtle.RotateAngle = __TURTLESHAPE__[0], r
549 z = __Point__(z.X - turtle.BoundRect.Width / 2.0, z.Y - turtle.BoundRect.Height / 2.0)
550 turtle.setPosition(z)
551 __visible__(turtle, True)
552 pencolor(_.pencolor)
553 fillcolor(_.areacolor)
554 pensize(_.pensize/__PT_TO_TWIP__)
555 _.doc.CurrentController.select(__getshape__(__TURTLE__))
556 elif not turtle:
557 __initialize__()
559 def left(arg=None):
560 if __thread__:
561 return None
562 __initialize__()
563 turtle = uno.getComponentContext().ServiceManager.createInstance('com.sun.star.drawing.ShapeCollection')
564 turtle.add(__getshape__(__TURTLE__))
565 _.doc.CurrentController.select(turtle)
566 rotate(__TURTLE__, 1500)
567 return None
569 def right(arg=None):
570 if __thread__:
571 return None
572 __initialize__()
573 turtle = uno.getComponentContext().ServiceManager.createInstance('com.sun.star.drawing.ShapeCollection')
574 turtle.add(__getshape__(__TURTLE__))
575 _.doc.CurrentController.select(turtle)
576 rotate(__TURTLE__, -1500)
577 return None
579 def goforward(arg=None):
580 if __thread__:
581 return None
582 __initialize__()
583 turtle = uno.getComponentContext().ServiceManager.createInstance('com.sun.star.drawing.ShapeCollection')
584 turtle.add(__getshape__(__TURTLE__))
585 _.doc.CurrentController.select(turtle)
586 forward(10)
587 return None
589 def gobackward(arg=None):
590 if __thread__:
591 return None
592 __initialize__()
593 turtle = uno.getComponentContext().ServiceManager.createInstance('com.sun.star.drawing.ShapeCollection')
594 turtle.add(__getshape__(__TURTLE__))
595 _.doc.CurrentController.select(turtle)
596 backward(10)
597 return None
599 def commandline(arg=None, arg2=None):
600 run(arg, arg2)
602 def __setlang__():
603 global _
604 c = _.doc.CurrentController.getViewCursor()
605 locs = [i for i in [c.CharLocale, c.CharLocaleAsian, c.CharLocaleComplex] if i.Language != 'zxx'] # not None language
606 # FIXME-BCP47: this needs adaption to language tags, a simple split on
607 # '-' and assuming second field would be country would already fail if
608 # a script tag was present.
609 loc = Locale(__uilocale__.split('-')[0], __uilocale__.split('-')[1], '')
610 if locs and loc not in locs:
611 loc = locs[0]
612 _.lng = loc.Language + '_' + loc.Country
613 if not __l12n__(_.lng):
614 _.lng = loc.Language
615 if not __l12n__(_.lng):
616 _.lng = "en_US"
618 def run(arg=None, arg2 = -1):
619 global _, __thread__, __halt__, _, __prevcode__, __prevlang__, __prevcompiledcode__
620 if __thread__:
621 return None
622 with __lock__:
623 __thread__ = 1
624 try:
625 __getdocument__()
626 _.origcursor = None
627 if arg2 == -1:
628 _.origcursor, _.cursor = __getcursor__(False), __getcursor__(True)
629 __dispatcher__(".uno:Escape")
630 c = _.doc.Text.createTextCursor() # go to the first page
631 c.gotoStart(False)
632 _.doc.CurrentController.getViewCursor().gotoRange(c, False)
633 __initialize__()
634 __setlang__()
635 arg2 = _.cursor.getString()
636 if len(arg2) > 20000:
637 if MessageBox(_.doc.CurrentController.Frame.ContainerWindow, __l12n__(_.lng)['ERR_NOTAPROGRAM'], __l12n__(_.lng)['LIBRELOGO'], "querybox", __YES_NO_CANCEL__) != 2:
638 with __lock__:
639 __thread__ = None
640 return None
641 else:
642 __initialize__()
643 __setlang__()
644 if __prevcode__ and __prevcode__ == arg2 and __prevlang__ == _.lng:
645 __thread__ = LogoProgram(__prevcompiledcode__)
646 else:
647 __prevcode__ = arg2
648 __prevlang__ = _.lng
649 __prevcompiledcode__ = __compil__(arg2)
650 __thread__ = LogoProgram(__prevcompiledcode__)
651 __halt__ = False
652 turtle = uno.getComponentContext().ServiceManager.createInstance('com.sun.star.drawing.ShapeCollection')
653 turtle.add(__getshape__(__TURTLE__))
654 _.doc.CurrentController.select(turtle)
655 __thread__.start()
656 except Exception as e:
657 __thread__ = None
658 __trace__()
659 return None
661 def stop(arg=None):
662 global __halt__
663 with __lock__:
664 __halt__ = True
665 return None
667 def home(arg=None):
668 if __thread__:
669 return None
670 __getdocument__()
671 turtle = __getshape__(__TURTLE__)
672 if turtle:
673 __removeshape__(__TURTLE__)
674 _.drawpage.remove(turtle)
675 __initialize__()
676 __dispatcher__(".uno:Escape")
677 if not __halt__:
678 return None
679 _.pencolor = 0
680 _.pensize = __LINEWIDTH__
681 _.areacolor = __FILLCOLOR__
682 pen = 1
683 __removeshape__(__ACTUAL__)
685 def clearscreen(arg=None):
686 if __thread__:
687 return None
688 __getdocument__()
689 turtle = __getshape__(__TURTLE__)
690 if not turtle:
691 __initialize__()
692 if not __halt__:
693 return
694 __cs__(False)
695 __dispatcher__(".uno:Escape")
697 def __checkhalt__():
698 global __thread__, __halt__
699 if __halt__:
700 with __lock__:
701 __thread__ = None
702 sys.exit()
704 def __cs__(select = True):
705 turtle = __getshape__(__TURTLE__)
706 visible = False
707 if turtle and turtle.Visible:
708 __visible__(turtle, False)
709 visible = True
710 if _.doc.CurrentController.select(_.drawpage) and \
711 _.doc.CurrentController.getSelection().ImplementationName == "com.sun.star.drawing.SvxShapeCollection":
712 __dispatcher__(".uno:Delete")
713 if turtle and visible:
714 __visible__(turtle, True)
715 if select:
716 _.doc.CurrentController.select(_.drawpage)
718 def __dispatcher__(s, properties = (), doc = 0):
719 ctx = XSCRIPTCONTEXT.getComponentContext()
720 d = ctx.ServiceManager.createInstanceWithContext("com.sun.star.frame.DispatchHelper", ctx)
721 if doc != 0:
722 d.executeDispatch(doc.CurrentController.Frame, s, "", 0, properties)
723 else:
724 d.executeDispatch(_.doc.CurrentController.Frame, s, "", 0, properties)
726 def __getshape__(shapename):
727 try:
728 if _.shapecache[shapename].Parent:
729 return _.shapecache[shapename]
730 _.shapecache.pop(shapename)
731 except:
732 pass
733 return None
735 def __angle__(deg):
736 if deg == u'any':
737 return random.random() * 36000
738 return deg * 100
740 def turnleft(deg):
741 rotate(__TURTLE__, __angle__(deg))
743 def turnright(deg):
744 rotate(__TURTLE__, -__angle__(deg))
746 def heading(deg = -1, go = False):
747 turtle = __getshape__(__TURTLE__)
748 if deg == -1:
749 return -turtle.RotateAngle / 100 + 360
750 else:
751 if deg == u'any':
752 turtle.RotateAngle = random.random() * 36000
753 elif type(deg) == list:
754 pos = turtle.getPosition()
755 px, py = pos.X + turtle.BoundRect.Width / 2.0, pos.Y + turtle.BoundRect.Height / 2.0
756 dx = px * __MM10_TO_TWIP__ - deg[0] * __PT_TO_TWIP__
757 dy = deg[1] * __PT_TO_TWIP__ - py * __MM10_TO_TWIP__
758 n = sqrt(dx**2 + dy**2)
759 if dy > 0 and n > 0:
760 turtle.RotateAngle = a = -(180 + asin(dx / n) / (pi/180)) * 100 + 72000 # +720 for max(angle, preciseAngle) of __go__()
761 elif n > 0:
762 turtle.RotateAngle = a = asin(dx / n) / (pi/180) * 100 + 72000
763 if go and n > 0:
764 __go__(__TURTLE__, -n, False, a)
765 else:
766 turtle.RotateAngle = -deg * 100
768 def rotate(shapename, deg):
769 shape = __getshape__(shapename)
770 if shape:
771 shape.RotateAngle = shape.RotateAngle + deg
773 def forward(n):
774 if type(n) == list:
775 pos = position()
776 angle = heading()
777 dx = n[1] * sin((pi/180) * angle) + n[0] * sin((pi/180)*(angle + 90))
778 dy = n[1] * cos((pi/180) * angle) + n[0] * cos((pi/180)*(angle + 90))
779 position([pos[0] + dx, pos[1] - dy])
780 else:
781 __go__(__TURTLE__, -n * __PT_TO_TWIP__)
783 def backward(n):
784 if type(n) == list:
785 forward([-n[0], -n[1]])
786 turnright(180)
787 else:
788 __go__(__TURTLE__, n * __PT_TO_TWIP__)
790 def __dots__(n, pos, dx, dy, r = -1, q = 0): # dots for dotted polyline or circle
791 f = [1, 4, 4, 4, 4][q]
792 k = abs(int(1.0 * n / max(20, _.pensize) / 2.0 / f))
793 dots = []
794 px, py = pos.X, pos.Y
795 for i in range(k + 1):
796 if k > 0:
797 if r != -1:
798 px, py = pos.X + sin(((f-1)*(q-1)*30 + 360.0/f/k * i) * pi/180.0) * r[0], pos.Y + cos(((f-1)*(q-1)*30 + 360.0/f/k * i) * pi/180) * r[1]
799 else:
800 px, py = pos.X + round(i * dx/k), pos.Y + round(i * dy/k)
801 dots += [(__Point__(px, py), __Point__(px + 7, py + 7))]
802 return dots
804 def __draw__(d, count = True):
805 shape = _.doc.createInstance( "com.sun.star.drawing." + d)
806 shape.AnchorType = __AT_PAGE__
807 shape.TextWrap = __THROUGHT__
808 __visible__(shape, False)
809 while __zoom__(): # temporary fix program halt with continuous zoom
810 while __zoom__():
811 __time__.sleep(0.2)
812 __time__.sleep(0.2)
813 _.drawpage.add(shape)
814 if __group__:
815 __group__.add(shape)
816 if count:
817 _.shapecache[next(_.shapecount)] = str(_.time)
818 return shape
820 def __zoom__():
821 z = _.doc.CurrentController.getViewSettings().ZoomValue
822 if z != _.zoomvalue:
823 _.zoomvalue = z
824 return True
825 return False
827 def __lefthang__(shape):
828 global __grouplefthang__
829 if __group__:
830 p = shape.getPosition()
831 if p.X < __grouplefthang__:
832 __grouplefthang__ = p.X
834 def __go__(shapename, n, dot = False, preciseAngle = -1):
835 turtle = __getshape__(shapename)
836 turtlepos = None
837 if shapename == __TURTLE__:
838 try:
839 turtlepos = turtle.PolyPolygon[-1][-1]
840 except:
841 pass
842 pos = turtle.getPosition()
843 dx = n * sin((pi/180)*(max(turtle.RotateAngle, preciseAngle)/100))
844 dy = n * cos((pi/180)*(max(turtle.RotateAngle, preciseAngle)/100))
845 turtle.setPosition(__Point__(pos.X + dx / __MM10_TO_TWIP__, pos.Y + dy / __MM10_TO_TWIP__))
846 if (_.pencolor != _.oldlc or _.pensize != _.oldlw or _.linestyle != _.oldls or _.linejoint != _.oldlj or _.linecap != _.oldlcap):
847 __removeshape__(__ACTUAL__)
848 shape = None
849 else:
850 shape = __getshape__(__ACTUAL__)
851 _.oldlw = _.pensize
852 _.oldlc = _.pencolor
853 _.oldls = _.linestyle
854 _.oldlj = _.linejoint
855 _.oldlcap = _.linecap
856 if shape and not _.pen and not dot:
857 _.continuous = False
858 return
859 c, c2 = __Point__(pos.X + turtle.BoundRect.Width / 2.0, pos.Y + turtle.BoundRect.Height / 2.0), __Point__(round(dx), round(dy))
860 if shape and "LineShape" in shape.ShapeType:
861 if _.continuous or dot:
862 last = shape.PolyPolygon[-1][-1]
863 if not (turtlepos and (abs(last.X - turtlepos.X) > 100 or abs(last.Y - turtlepos.Y) > 100) and
864 (not __group__ or (shape.getPosition().X > 0 and turtle.getPosition().X > 0))): # picture [ ] keeps hanging shapes
865 if dot or _.linestyle == __LineStyle_DOTTED__:
866 shape.PolyPolygon = tuple( list(shape.PolyPolygon) + __dots__(n, turtlepos, dx, dy))
867 else:
868 last.X = last.X + c2.X
869 last.Y = last.Y + c2.Y
870 shape.PolyPolygon = tuple( list(shape.PolyPolygon[:-1]) + [tuple( list(shape.PolyPolygon[-1]) + [last])])
871 __lefthang__(shape)
872 return
873 elif turtlepos:
874 shape.PolyPolygon = tuple( list(shape.PolyPolygon) + [(turtlepos, __Point__(turtlepos.X + c2.X, turtlepos.Y + c2.Y))])
875 _.continuous = True
876 __lefthang__(shape)
877 return
878 if not _.pen and not dot:
879 return
880 shape = __draw__("PolyLineShape")
881 shape.RotateAngle = 0
882 shape.PolyPolygon = tuple([tuple([__Point__(0, 0)])])
883 shape.setPosition(c)
884 last = shape.PolyPolygon[-1][-1]
885 last2 = __Point__(last.X + c2.X, last.Y + c2.Y)
886 shape.LineStyle, shape.LineDash = __linestyle__(_.linestyle)
887 shape.LineJoint = _.linejoint
888 shape.LineCap = _.linecap
889 if dot or _.linestyle == __LineStyle_DOTTED__:
890 shape.PolyPolygon = tuple( list(shape.PolyPolygon) + __dots__(n, last, c2.X, c2.Y))
891 shape.LineStart = __bezierdot__
892 shape.LineStartCenter = True
893 shape.LineStartWidth = max(20, _.pensize) / __MM10_TO_TWIP__
894 shape.LineWidth = 0
895 else:
896 shape.PolyPolygon = tuple([tuple( list(shape.PolyPolygon[-1]) + [last2])])
897 shape.LineWidth = _.pensize / __MM10_TO_TWIP__
898 shape.LineColor, shape.LineTransparence = __splitcolor__(_.pencolor)
899 if shape.LineTransparence == 100:
900 shape.LineStyle = 0
901 __visible__(shape, True)
902 shape.Name = __ACTUAL__
903 _.shapecache[__ACTUAL__] = shape
904 _.oldlw = _.pensize
905 _.oldlc = _.pencolor
906 _.oldls = _.linestyle
907 _.oldlj = _.linejoint
908 _.oldlcap = _.linecap
909 _.continuous = True
910 __lefthang__(shape)
912 def __fillit__(filled = True):
913 oldshape = __getshape__(__ACTUAL__)
914 if oldshape and oldshape.LineStartCenter:
915 __removeshape__(__ACTUAL__) # FIXME close dotted polyline
916 return
917 if oldshape and "LineShape" in oldshape.ShapeType:
918 shape = __draw__("PolyPolygonShape", False)
919 shape.PolyPolygon = oldshape.PolyPolygon
920 shape.setPosition(oldshape.getPosition())
921 shape.LineStyle, shape.LineDash = __linestyle__(_.linestyle)
922 shape.LineJoint = _.linejoint
923 shape.LineCap = _.linecap
924 shape.LineWidth = _.pensize / __MM10_TO_TWIP__
925 shape.LineColor, shape.LineTransparence = __splitcolor__(_.pencolor)
926 shape.FillColor, shape.FillTransparence = __splitcolor__(_.areacolor)
927 if _.hatch:
928 shape.FillBackground = True if shape.FillTransparence != 100 else False
929 shape.FillHatch = _.hatch
930 shape.FillStyle = 3
931 else:
932 shape.FillStyle = int(filled)
933 if shape.LineTransparence == 100:
934 shape.LineStyle = 0
935 if shape.FillTransparence == 100:
936 shape.FillTransparence = 0 # for hatching and better modifications on UI
937 if not _.hatch:
938 shape.FillStyle = 0
939 shape.setString(oldshape.getString())
940 oldshape.Name = ""
941 shape.Name = __ACTUAL__
942 _.shapecache[__ACTUAL__] = shape
943 if __group__:
944 __group__.remove(oldshape)
945 __visible__(shape, True)
946 _.drawpage.remove(oldshape)
947 elif oldshape and "PolyPolygon" in oldshape.ShapeType:
948 oldshape.LineStyle = int(_.pen)
949 oldshape.LineJoint = _.linejoint
950 oldshape.LineCap = _.linecap
951 if _.hatch:
952 oldshape.FillBackground = True
953 oldshape.FillHatch = _.hatch
954 oldshape.FillStyle = 3
955 else:
956 oldshape.FillStyle = int(filled)
957 oldshape.LineWidth = _.pensize / __MM10_TO_TWIP__
958 oldshape.LineColor, oldshape.LineTransparence = __splitcolor__(_.pencolor)
959 oldshape.FillColor, oldshape.FillTransparence = __splitcolor__(_.areacolor)
961 def point():
962 oldpen, _.pen = _.pen, 1
963 oldstyle, _.linestyle = _.linestyle, __LineStyle_DOTTED__
964 __go__(__TURTLE__, 0, True)
965 _.pen, _.linestyle = oldpen, oldstyle
967 def __boxshape__(shapetype, l):
968 turtle = __getshape__(__TURTLE__)
969 shape = __draw__(shapetype + "Shape")
970 pos = turtle.getPosition()
971 pos.X = pos.X - (l[0] * __PT_TO_TWIP__ / __MM10_TO_TWIP__ / 2) + turtle.BoundRect.Width / 2.0
972 pos.Y = pos.Y - (l[1] * __PT_TO_TWIP__ / __MM10_TO_TWIP__ / 2) + turtle.BoundRect.Height / 2.0
973 shape.setPosition(pos)
974 shape.setSize(__Size__(l[0] * __PT_TO_TWIP__ / __MM10_TO_TWIP__, l[1] * __PT_TO_TWIP__ / __MM10_TO_TWIP__))
975 shape.LineStyle, shape.LineDash = __linestyle__(_.linestyle)
976 shape.LineWidth = _.pensize / __MM10_TO_TWIP__
977 shape.LineJoint = _.linejoint
978 shape.LineCap = _.linecap
979 shape.LineColor, shape.LineTransparence = __splitcolor__(_.pencolor)
980 shape.FillColor, shape.FillTransparence = __splitcolor__(_.areacolor)
981 if _.hatch:
982 shape.FillBackground = True if shape.FillTransparence != 100 else False
983 shape.FillHatch = _.hatch
984 shape.FillStyle = 3
985 else:
986 shape.FillStyle = 1
987 if shape.LineTransparence == 100:
988 shape.LineStyle = 0
989 if shape.FillTransparence == 100:
990 shape.FillTransparence = 0 # for hatching and better modifications on UI
991 if not _.hatch:
992 shape.FillStyle = 0
993 shape.RotateAngle = turtle.RotateAngle
994 if shapetype == "Rectangle" and len(l) > 2:
995 shape.CornerRadius = (l[2] * __PT_TO_TWIP__) / __MM10_TO_TWIP__
996 elif shapetype == "Ellipse" and len(l) > 2:
997 try:
998 shape.CircleKind = __SECTION__
999 shape.CircleStartAngle = (-l[3] - 270) * 100
1000 shape.CircleEndAngle = (-l[2] - 270) * 100
1001 shape.CircleKind = [__FULL__, __SECTION__, __CUT__, __ARC__][l[4]]
1002 except:
1003 pass
1004 __visible__(shape, True)
1005 __removeshape__(__ACTUAL__)
1006 _.shapecache[__ACTUAL__] = shape
1007 __lefthang__(shape)
1009 def ellipse(l):
1010 if type(l) != type([]): # default for circle and square
1011 l = [l, l]
1012 if _.linestyle == __LineStyle_DOTTED__:
1013 __groupstart__()
1014 _.linestyle = __LineStyle_SOLID__
1015 pc, _.pencolor = _.pencolor, 0xff000000
1016 ellipse(l)
1017 _.pencolor, _.linestyle = pc, __LineStyle_DOTTED__
1018 point()
1019 shape = __getshape__(__ACTUAL__)
1020 shape.PolyPolygon = tuple(__dots__(max(l[0], l[1]) * pi * __PT_TO_TWIP__, shape.PolyPolygon[0][0], 0, 0, [i/2.0 * __PT_TO_TWIP__ for i in l]))
1021 turtle = __getshape__(__TURTLE__)
1022 shape.RotateAngle = turtle.RotateAngle
1023 __groupend__()
1024 else:
1025 __boxshape__("Ellipse", l)
1027 def rectangle(l):
1028 if type(l) != type([]): # default for circle and square
1029 l = [l, l]
1030 if _.linestyle == __LineStyle_DOTTED__:
1031 __groupstart__()
1032 _.linestyle = __LineStyle_SOLID__
1033 pc, _.pencolor = _.pencolor, 0xff000000
1034 rectangle(l)
1035 _.pencolor, _.linestyle = pc, __LineStyle_DOTTED__
1036 point()
1037 shape = __getshape__(__ACTUAL__)
1038 if type(l) != type([]):
1039 l = [l, l]
1040 if len(l) == 2:
1041 l = l + [0]
1042 l = [i * __PT_TO_TWIP__ for i in l]
1043 c = shape.PolyPolygon[0][0]
1044 k = [min(l[0] / 2.0, l[2]), min(l[1] / 2.0, l[2])]
1045 p = __dots__(l[0] - 2 * k[0], __Point__(c.X - l[0]/2 + k[0], c.Y - l[1]/2), l[0] - 2 * k[0], 0)
1046 p = p[:-1] + __dots__(l[1] - 2 * k[1], __Point__(c.X + l[0]/2, c.Y - l[1]/2 + k[1]), 0, l[1] - 2 * k[1])
1047 p = p[:-1] + __dots__(l[0] - 2 * k[0], __Point__(c.X + l[0]/2 - k[0], c.Y + l[1]/2), -l[0] + 2 * k[0], 0)
1048 p = p[:-1] + __dots__(l[1] - 2 * k[1], __Point__(c.X - l[0]/2, c.Y + l[1]/2 - k[1]), 0, -l[1] + 2 * k[1])
1049 if l[2] > 0:
1050 p = p + __dots__(max(k) * 2 * pi, __Point__(c.X - l[0]/2 + k[0], c.Y - l[1]/2 + k[1]), 0, 0, k, 3)[1:]
1051 p = p + __dots__(max(k) * 2 * pi, __Point__(c.X + l[0]/2 - k[0], c.Y - l[1]/2 + k[1]), 0, 0, k, 2)[1:]
1052 p = p + __dots__(max(k) * 2 * pi, __Point__(c.X + l[0]/2 - k[0], c.Y + l[1]/2 - k[1]), 0, 0, k, 1)[1:]
1053 p = p + __dots__(max(k) * 2 * pi, __Point__(c.X - l[0]/2 + k[0], c.Y + l[1]/2 - k[1]), 0, 0, k, 4)[1:]
1054 shape.PolyPolygon = tuple(p)
1055 turtle = __getshape__(__TURTLE__)
1056 shape.RotateAngle = turtle.RotateAngle
1057 __groupend__()
1058 else:
1059 __boxshape__("Rectangle", l)
1061 def label(st):
1062 if type(st) != type([]):
1063 st = [0, 0, st]
1064 # get text size
1065 shape = _.doc.createInstance( "com.sun.star.drawing.TextShape")
1066 shape.TextAutoGrowWidth = True
1067 shape.Visible = False
1068 actual = __getshape__(__ACTUAL__)
1069 _.drawpage.add(shape)
1070 text(shape, st[2])
1071 z = shape.getSize()
1072 # show text using RectangleShape (for correct SVG export)
1073 ac, pc = _.areacolor, _.pencolor
1074 _.areacolor, _.pencolor = 0xff000000, 0xff000000 # invisible
1075 rectangle([z.Width / (__PT_TO_TWIP__ / __MM10_TO_TWIP__), z.Height / (__PT_TO_TWIP__ / __MM10_TO_TWIP__)])
1076 _.drawpage.remove(shape)
1077 _.pencolor, _.areacolor = pc, ac
1078 lab = __getshape__(__ACTUAL__)
1079 text(lab, st[2])
1080 if st[0] != 0 or st[1] != 0:
1081 pos = position()
1082 angle = heading()
1083 n = [st[0] * z.Width/2, st[1] * z.Height/2]
1084 dx = n[1] * sin((pi/180) * angle) + n[0] * sin((pi/180)*(angle + 90))
1085 dy = n[1] * cos((pi/180) * angle) + n[0] * cos((pi/180)*(angle + 90))
1086 lab.setPosition(__Point__(round(pos[0] * __PT_TO_TWIP__ / __MM10_TO_TWIP__ + dx - lab.BoundRect.Width/2), round(pos[1] * __PT_TO_TWIP__ / __MM10_TO_TWIP__ - dy - lab.BoundRect.Height/2)))
1087 _.shapecache[__ACTUAL__] = actual
1089 def text(shape, st):
1090 if shape:
1091 shape.setString(__string__(st, _.decimal))
1092 c = shape.createTextCursor()
1093 c.gotoStart(False)
1094 c.gotoEnd(True)
1095 c.CharColor, none = __splitcolor__(_.textcolor)
1096 c.CharHeight = _.fontheight
1097 c.CharWeight = __fontweight__(_.fontweight)
1098 c.CharPosture = __fontstyle__(_.fontstyle)
1099 c.CharFontName = _.fontfamily
1101 def sleep(t):
1102 _.time = _.time + t
1103 __removeshape__(__ACTUAL__)
1104 for i in range(int(t/__SLEEP_SLICE_IN_MILLISECONDS__)):
1105 __checkhalt__()
1106 __time__.sleep(0.5)
1107 __checkhalt__()
1108 __time__.sleep(t%__SLEEP_SLICE_IN_MILLISECONDS__/1000.0)
1110 def __removeshape__(shapename):
1111 try:
1112 _.shapecache.pop(shapename).Name = ""
1113 except:
1114 pass
1116 def __fontweight__(w):
1117 if type(w) == int:
1118 return w
1119 elif re.match(__l12n__(_.lng)['BOLD'], w, flags = re.I):
1120 return 150
1121 elif re.match(__l12n__(_.lng)['NORMAL'], w, flags = re.I):
1122 return 100
1123 return 100
1125 def __fontstyle__(w):
1126 if type(w) == int:
1127 return w
1128 elif re.match(__l12n__(_.lng)['ITALIC'], w, flags = re.I):
1129 return __Slant_ITALIC__
1130 elif re.match(__l12n__(_.lng)['UPRIGHT'], w, flags = re.I):
1131 return __Slant_NONE__
1132 return __Slant_NONE__
1134 def __color__(c):
1135 if type(c) in [int, float, long]:
1136 return c
1137 if type(c) == unicode:
1138 if c == u'any':
1139 return int(random.random() * 2**31) # max. 50% transparency
1140 if c[0:1] == '~':
1141 c = __componentcolor__(__colors__[_.lng][c[1:].lower()])
1142 for i in range(3):
1143 c[i] = max(min(c[i] + int(random.random() * 64) - 32, 255), 0)
1144 return __color__(c)
1145 return __colors__[_.lng][c.lower()]
1146 if type(c) == list:
1147 if len(c) == 1:
1148 return __COLORS__[int(c[0])][1]
1149 if len(c) == 3:
1150 return (int(c[0])%256 << 16) + (int(c[1])%256 << 8) + int(c[2])%256
1151 return (int(c[3])%256 << 24) + (int(c[0])%256 << 16) + (int(c[1])%256 << 8) + int(c[2])%256
1153 def __linestyle__(s):
1154 if _.pen == 0:
1155 return 0, __LineDash__()
1156 if _.linestyle == __LineStyle_DASHED__:
1157 return _.linestyle, __LineDash__(__DashStyle_RECT__, 0, 0, 1, 100, 100)
1158 elif _.linestyle == __LineStyle_DOTTED__:
1159 return __LineStyle_DASHED__, __LineDash__(__DashStyle_RECT__, 1, 1, 0, 0, 100000)
1160 elif type(s) == list:
1161 return __LineStyle_DASHED__, __LineDash__((s[5:6] or [0])[0], s[0], s[1] * __PT_TO_TWIP__, s[2], s[3] * __PT_TO_TWIP__, s[4] * __PT_TO_TWIP__)
1162 return s, __LineDash__()
1164 def fillstyle(s):
1165 if type(s) == list:
1166 color, null = __splitcolor__(__color__(s[1]))
1167 _.hatch = __Hatch__(s[0] - 1, color, s[2] * __PT_TO_TWIP__, s[3] * 10)
1168 elif s == 0:
1169 _.hatch = None
1170 elif s <= 10: # using hatching styles of Writer
1171 fillstyle([[1, 0, 5, 0], [1, 0, 5, 45], [1, 0, 5, -45], [1, 0, 5, 90], [2, [127, 0, 0], 5, 45], [2, [127, 0, 0], 5, 0], [2, [0, 0, 127], 5, 45], [2, [0, 0, 127], 5, 0], [3, [0, 0, 127], 5, 0], [1, 0, 25, 45]][s-1])
1173 def __splitcolor__(c):
1174 """Split color constants to RGB (3-byte) + transparency (%)"""
1175 return int(c) & 0xffffff, (int(c) >> 24) / (255.0/100)
1177 def __componentcolor__(c):
1178 a = [ (c & 0xff0000) >> 16, (c & 0xff00) >> 8, c & 0xff ]
1179 if c > 2**24:
1180 a.append((c & 0xff000000) >> 24)
1181 return a
1183 def pencolor(n = -1):
1184 if n != -1:
1185 _.pencolor = __color__(n)
1186 turtle = __getshape__(__TURTLE__)
1187 if turtle and __visible__(turtle):
1188 turtle.LineColor, turtle.LineTransparence = __splitcolor__(_.pencolor)
1189 else:
1190 return __componentcolor__(_.pencolor)
1192 def pensize(n = -1):
1193 if n != -1:
1194 if n == 'any':
1195 _.pensize = random.random() * 10 * __PT_TO_TWIP__
1196 else:
1197 _.pensize = n * __PT_TO_TWIP__
1198 turtle = __getshape__(__TURTLE__)
1199 if turtle and __visible__(turtle):
1200 turtle.LineWidth = min(_.pensize, (1 + _.pen * 2) * __PT_TO_TWIP__) / __MM10_TO_TWIP__
1201 return _.pensize / __PT_TO_TWIP__
1203 def penstyle(n = -1):
1204 if n == -1:
1205 try:
1206 return __locname__(_.linestyle.value)
1207 except:
1208 return __locname__('DOTTED')
1209 if type(n) == list and len(n) >= 5:
1210 _.linestyle = n
1211 elif re.match(__l12n__(_.lng)['SOLID'], n, flags = re.I):
1212 _.linestyle = __LineStyle_SOLID__
1213 elif re.match(__l12n__(_.lng)['DASH'], n, flags = re.I):
1214 _.linestyle = __LineStyle_DASHED__
1215 elif re.match(__l12n__(_.lng)['DOTTED'], n, flags = re.I):
1216 _.linestyle = __LineStyle_DOTTED__
1218 def penjoint(n = -1):
1219 if n == -1:
1220 return __locname__(_.linejoint.value)
1221 if re.match(__l12n__(_.lng)['NONE'], n, flags = re.I):
1222 _.linejoint = __Joint_NONE__
1223 elif re.match(__l12n__(_.lng)['BEVEL'], n, flags = re.I):
1224 _.linejoint = __BEVEL__
1225 elif re.match(__l12n__(_.lng)['MITER'], n, flags = re.I):
1226 _.linejoint = __MITER__
1227 elif re.match(__l12n__(_.lng)['ROUNDED'], n, flags = re.I):
1228 _.linejoint = __ROUNDED__
1230 def pencap(n = -1):
1231 if n == -1:
1232 return __locname__(_.linecap.value.replace('BUTT', 'NONE'))
1233 if re.match(__l12n__(_.lng)['NONE'], n, flags = re.I):
1234 _.linecap = __Cap_NONE__
1235 elif re.match(__l12n__(_.lng)['ROUNDED'], n, flags = re.I):
1236 _.linecap = __Cap_ROUND__
1237 elif re.match(__l12n__(_.lng)['SQUARE'], n, flags = re.I):
1238 _.linecap = __Cap_SQUARE__
1240 def fillcolor(n = -1):
1241 if n != -1:
1242 _.areacolor = __color__(n)
1243 turtle = __getshape__(__TURTLE__)
1244 if turtle and __visible__(turtle):
1245 turtle.FillColor, transparence = __splitcolor__(_.areacolor)
1246 turtle.FillTransparence = min(95, transparence)
1247 else:
1248 return __componentcolor__(_.areacolor)
1250 def fontcolor(n = -1):
1251 if n != -1:
1252 _.textcolor = __color__(n)
1253 else:
1254 return __componentcolor__(_.textcolor)
1256 def position(n = -1):
1257 turtle = __getshape__(__TURTLE__)
1258 if turtle:
1259 if n != -1:
1260 if n == 'any':
1261 ps = pagesize()
1262 heading([random.random() * ps[0], random.random() * ps[1]], True)
1263 else:
1264 heading(n, True)
1265 else:
1266 pos = turtle.getPosition()
1267 pos.X, pos.Y = pos.X + turtle.BoundRect.Width / 2.0, pos.Y + turtle.BoundRect.Height / 2.0
1268 return [ pos.X * __MM10_TO_TWIP__ / __PT_TO_TWIP__, pos.Y * __MM10_TO_TWIP__ / __PT_TO_TWIP__ ]
1270 def __groupstart__(name = ""):
1271 global __group__, __grouplefthang__, __groupstack__
1272 __removeshape__(__ACTUAL__)
1273 __groupstack__.append(__group__)
1274 if name != "": # store pic name (for correct repcount)
1275 __groupstack__.append(name)
1276 if ".SVG" == name[-4:].upper():
1277 _.time = 0
1278 _.shapecount = itertools.count()
1279 __groupstack__.append(__grouplefthang__)
1280 __group__ = uno.getComponentContext().ServiceManager.createInstance('com.sun.star.drawing.ShapeCollection')
1281 __grouplefthang__ = 0
1283 def create_svg_animation(m):
1284 global _
1285 id = int(m.group(1))
1286 if id - 3 in _.shapecache:
1287 t = _.shapecache[id-3]
1288 opacity = "100" if t == "0" else "0"
1289 name = "" if id != 3 else "id=\"first\""
1290 start = "%sms;last.end+%sms" % (t, t) if id == 3 else "first.end+%dms" % (int(t) - int(_.shapecache[0]))
1291 return '<g id="id%s" opacity="0"><animate %s attributeName="opacity" from="100" to="100" begin="%s" dur="1ms" fill="freeze"/><animate attributeName="opacity" from="100" to="%s" begin="last.end" dur="1ms" fill="freeze"/>' % (m.group(1), name, start, opacity)
1292 return m.group()
1294 def create_valid_svg_file(filename):
1295 with open(filename, "r") as f:
1296 s = f.read()
1297 s = re.sub('(?s)(<g\\sid="[^"]*)\(([^"]*)\)', '\\1\\2', s) # bad "(", ")" in xml:id
1298 s = re.sub('(?s)<g\\sooo:[^>]*>', '', s) # remove non standard attributes
1299 s = re.sub('(?s)<defs class="EmbeddedBulletChars">.*(?=<defs class="TextEmbeddedBitmaps")', '', s) # remove unused parts
1300 s = re.sub('(?s)(<path stroke-width="[^"]*"[^<]*)stroke-width="[^"]*"', '\\1', s) # double stroke-width
1301 s = re.sub('(?s)<svg\\s+version="1.2"', '<svg version="1.1"', s) # for W3C Validator
1302 if _.time > 0:
1303 s = re.sub('<g id="id([0-9]+)">', create_svg_animation, s)
1304 m = re.match('(?s)(.*<animate[^>]*first[.]end.([0-9]+)[^>]* dur=")1ms"', s)
1305 lasttime = _.time - int(m.group(2)) - int(_.shapecache[0]) + 1
1306 if lasttime > 1:
1307 s = re.sub('(?s)(.*<animate[^>]*first[.]end.([0-9]+)[^>]* dur=")1ms"', m.group(1) + str(lasttime) + 'ms" id="last"', s)
1308 with open(filename, 'w') as f:
1309 f.write(s)
1311 def __groupend__(name = ""):
1312 global __group__, __grouplefthang__, __groupstack__, __halt__
1313 g = 0
1314 if __group__.getCount() > 1:
1315 if __grouplefthang__ < 0:
1316 for i in range(__group__.Count):
1317 s = __group__.getByIndex(i)
1318 p = s.getPosition()
1319 p.X = p.X + -__grouplefthang__
1320 s.setPosition(p)
1321 g = _.drawpage.group(__group__)
1322 p = g.getPosition()
1323 p.X = p.X + __grouplefthang__
1324 g.setPosition(p)
1325 else:
1326 g = _.drawpage.group(__group__)
1327 g.TextWrap = __THROUGHT__
1328 elif __group__.getCount() == 1:
1329 g = __group__.getByIndex(0)
1330 __grouplefthang__ = min(__groupstack__.pop(), __grouplefthang__)
1331 if name != "":
1332 name = __groupstack__.pop()
1333 if name and ".SVG" == name[-4:].upper() and g:
1334 _.doc.CurrentController.select(g)
1335 __dispatcher__(".uno:Copy")
1336 ctx = XSCRIPTCONTEXT.getComponentContext()
1337 d = ctx.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
1338 draw = d.loadComponentFromURL("private:factory/sdraw", "_blank", 0, ())
1339 drawpage = draw.getDrawPages().getByIndex(0)
1340 while XSCRIPTCONTEXT.getDocument() != draw:
1341 if XSCRIPTCONTEXT.getDocument() not in [draw, _.doc, None]:
1342 __halt__ = True
1343 return
1344 __time__.sleep(0.1)
1345 __dispatcher__(".uno:Paste", (), draw)
1346 __dispatcher__(".uno:FormatGroup", (), draw)
1347 pic = drawpage.getByIndex(0)
1348 pic.setPosition(__Point__((g.BoundRect.Width - g.Size.Width)//2, (g.BoundRect.Height - g.Size.Height)//2))
1349 drawpage.Height, drawpage.Width = g.BoundRect.Height, g.BoundRect.Width
1350 if not os.path.isabs(name):
1351 name = os.path.expanduser('~') + os.path.sep + name
1352 __dispatcher__(".uno:ExportTo", (__getprop__("URL", unohelper.systemPathToFileUrl(name)), __getprop__("FilterName", "draw_svg_Export")), draw)
1353 draw.close(True)
1354 while XSCRIPTCONTEXT.getDocument() != _.doc:
1355 if XSCRIPTCONTEXT.getDocument() not in [draw, _.doc, None]:
1356 __halt__ = True
1357 return
1358 __time__.sleep(0.1)
1359 create_valid_svg_file(name)
1360 __group__ = __groupstack__.pop()
1361 if __group__ and g:
1362 __group__.add(g)
1363 __removeshape__(__ACTUAL__)
1365 def __int__(x): # handle eg. int("10cm")
1366 if type(x) == str or type(x) == unicode:
1367 x = __float__(x)
1368 return int(x)
1370 def __float__(x): # handle eg. float("10,5cm")
1371 if type(x) == str or type(x) == unicode:
1372 for i in __comp__[_.lng]:
1373 x = re.sub(u"(?iu)" + i[0], i[1], x)
1374 x = eval(x)
1375 return float(x)
1377 def fontheight(n = -1):
1378 if n != -1:
1379 _.fontheight = n
1380 else:
1381 return _.fontheight
1383 def fontweight(n = -1):
1384 if n != -1:
1385 _.fontweight = n
1386 else:
1387 return _.fontweight
1389 def fontfamily(s = -1):
1390 if s != -1:
1391 _.fontfamily = s
1392 else:
1393 return _.fontfamily
1395 def fontstyle(n = -1):
1396 if n != -1:
1397 _.fontstyle = n
1398 else:
1399 return _.fontstyle
1401 def __loadlang__(lang, a):
1402 global comp, __colors__
1403 __colors__[lang] = {}
1404 for i in __COLORS__:
1405 for j in a[i[0]].split("|"):
1406 __colors__[lang][j] = i[1]
1407 for i in a:
1408 if not i[0:3] in ["LIB", "ERR", "PT", "INC", "MM", "CM", "HOU", "DEG"] and not i in __STRCONST__: # uppercase native commands
1409 a[i] = a[i].upper()
1410 repcount = a['REPCOUNT'].split('|')[0]
1411 loopi = itertools.count()
1412 loop = lambda r: "%(i)s = 1\n%(orig)s%(j)s = %(i)s\n%(i)s += 1\n" % \
1413 { "i": repcount + str(next(loopi)), "j": repcount, "orig": re.sub( r"(?ui)(?<!:)\b%s\b" % repcount, repcount + str(next(loopi)-1), r.group(0)) }
1414 __comp__[lang] = [
1415 [r"(?i)(?<!:)(\b|(?=[-:]))(?:%s)\b" % "|".join([a[i].lower() for i in a if not "_" in i and i != "DECIMAL"]), lambda s: s.group().upper()], # uppercase all native commands in the source code
1416 [r"(?<!:)\b(?:%s) \[(?= |\n)" % a['GROUP'], "\n__groupstart__()\nfor __groupindex__ in range(2):\n[\nif __groupindex__ == 1:\n[\n__groupend__()\nbreak\n]\n"],
1417 [r"(?<!:)\b(?:%s) (%s[^[]*)\[(?= |\n)" % (a['GROUP'], __DECODE_STRING_REGEX__), "\n__groupstart__(\\1)\nfor __groupindex__ in range(2):\n[\nif __groupindex__ == 1:\n[\n__groupend__(\\1)\nbreak\n]\n"],
1418 [r"(?<!:)\b(?:%s)\b" % a['GROUP'], "\n__removeshape__(__ACTUAL__)\n"],
1419 [r"(\n| )][ \n]*\[(\n| )", "\n]\nelse:\n[\n"], # if/else block
1420 [r"(?<!\n)\[(?= |\n)", ":\n[\n"], # start block
1421 [r"( ]|\n]$)", "\n]\n"], # finish block
1422 [r"(?<!:)\b(?:%s)\b" % a['FOR'], "\nfor"],
1423 [r"(?<!:)\b(?:%s)\b" % a['REPEAT'], "\n__repeat__"],
1424 [r"(?<!:)\b(?:%s)\b" % a['BREAK'], "\nbreak"],
1425 [r"(?<!:)\b(?:%s)\b" % a['CONTINUE'], "\ncontinue"],
1426 [r"(?<!:)\b(?:%s)\b" % a['REPCOUNT'], repcount],
1427 [r"(?<!:)\b(?:%s)\b" % a['IF'], "\nif"],
1428 [r"(?<!:)\b(?:%s)\b" % a['WHILE'], "\nwhile"],
1429 [r"(?<!:)\b(?:%s)\b" % a['OUTPUT'], "\nreturn"],
1430 [r"\n(if|while|return) [^\n]*", lambda r: re.sub("(?<![=!<>])=(?!=)", "==", r.group(0))], # = -> ==, XXX x = y = 1?
1431 [r"(?<=\n)(for\b :?\w+) ([^\n]+)(?<=\w|]|}|\))(?=-|:)(?:%s)\b" % a['IN'], "\\1 in \\2"], # "for x y-in" -> "for x in y"
1432 [r"(:?\b\w+|[[][^[\n]*])\b(?:%s)\b" % a['IN'], "in \\1"], # "x y-in" -> "x in y"
1433 [r"(?<!:)\b(?:%s)\b" % a['IN'], "in"],
1434 [r"(?<!:)\b(?:%s)\b[ \t]+(:?\w+)\b(?! in\b)" % a['FOR'], "\nfor \\1 in"],
1435 [r"(?<=\n)__repeat__ :\n", "while True:\n"], # infinite loop
1436 [r"(?<=\n)(for|while) (?!__groupindex__)[^\n]*:\n\[\n", loop], # loop variables for repcount (not groupindex loop)
1437 [r"(?<=\n)__repeat__([^\n]*\w[^\n]*):(?=\n)", "for %s in range(1, 1+int(\\1)):" % repcount], # repeat block
1438 [r"(?<=\d)[%s](?=\d)" % a['DECIMAL'], "."], # decimal sign
1439 [r"(?<!/)/(?!/)", "*1.0/"], # fix division: /1 -> /1.0, but not with //
1440 [r"\b([0-9]+([,.][0-9]+)?)(%s)\b" % a['HOUR'], lambda r: str(float(r.group(1).replace(",", "."))*30)], # 12h = 12*30°
1441 [r"(?<=\d)(%s)" % a['DEG'], ""], # 1° -> 1
1442 [r"(?<!:)\b(?:__def__)[ \t]+(\w+)\b[ \t]*([:]?\w[^\n]*)", "\ndef \\1(\\2):\n["],
1443 [r"(?<!:)\b(?:__def__)\s+(\w+)", "\ndef \\1():\n["],
1444 [r"(?<!:)\b(?:%s)\b" % a['END'], "\n]"],
1445 [r"(?<!:)\b(?:%s)\b" % a['GLOBAL'], "global"],
1446 [r"(?<!:)\b(?:%s)\b" % a['TRUE'], "True"],
1447 [r"(?<!:)\b(?:%s)\b" % a['FALSE'], "False"],
1448 [r"(?<!:)\b(?:%s)\b" % a['NOT'], "not"],
1449 [r"(?<!:)\b(?:%s)\b" % a['AND'], "and"],
1450 [r"(?<!:)\b(?:%s)\b" % a['OR'], "or"],
1451 [r"(?<!:)\b(?:%s)\b" % a['INT'], "__int__"],
1452 [r"(?<!:)\b(?:%s)\b" % a['FLOAT'], "__float__"],
1453 [r"(?<!:)\b(?:%s)\b" % a['STR'], "__string__"],
1454 [r"(?<!:)\b(?:%s)\b" % a['COUNT'], "len"],
1455 [r"(?<!:)\b(?:%s)\b" % a['ROUND'], "round"],
1456 [r"(?<!:)\b(?:%s)\b" % a['ABS'], "abs"],
1457 [r"(?<!:)\b(?:%s)\b" % a['SIN'], "sin"],
1458 [r"(?<!:)\b(?:%s)\b" % a['COS'], "cos"],
1459 [r"(?<!:)\b(?:%s)\b" % a['PI'], "pi"],
1460 [r"(?<!:)\b(?:%s)\b" % a['SQRT'], "sqrt"],
1461 [r"(?<!:)\b(?:%s)\b" % a['MIN'], "min"],
1462 [r"(?<!:)\b(?:%s)\b" % a['MAX'], "max"],
1463 [r"(?<!:)\b(?:%s)\b" % a['STOP'], "\nreturn None"],
1464 [r"(?<!:)\b(?:%s)\b" % a['CLEARSCREEN'], "\n__cs__()"],
1465 [r"(?<!:)\b(?:%s)(\s+|$)" % a['PENCOLOR'], "\n)pencolor("],
1466 [r"(?<!:)\b(?:%s)(\s+|$)" % a['PENSTYLE'], "\n)penstyle("],
1467 [r"(?<!:)\b(?:%s)(\s+|$)" % a['PENJOINT'], "\n)penjoint("],
1468 [r"(?<!:)\b(?:%s)(\s+|$)" % a['PENCAP'], "\n)pencap("],
1469 [r"(?<!:)\b(?:%s)(\s+|$)" % a['FILLCOLOR'], "\n)fillcolor("],
1470 [r"(?<!:)\b(?:%s)(\s+|$)" % a['FILLSTYLE'], "\n)fillstyle("],
1471 [r"(?<!:)\b(?:%s)(\s+|$)" % a['FONTCOLOR'], "\n)fontcolor("],
1472 [r"(?<!:)\b(?:%s)(\s+|$)" % a['FONTFAMILY'], "\n)fontfamily("],
1473 [r"(?<!:)\b(?:%s)(\s+|$)" % a['FONTHEIGHT'], "\n)fontheight("],
1474 [r"(?<!:)\b(?:%s)(\s+|$)" % a['FONTWEIGHT'], "\n)fontweight("],
1475 [r"(?<!:)\b(?:%s)(\s+|$)" % a['FONTSTYLE'], "\n)fontstyle("],
1476 [r"(?<!:)\b(?:%s)(\s+|$)" % a['PENWIDTH'], "\n)pensize("],
1477 [r"(?<!:)\b(?:%s)\b" % a['PENDOWN'], "\n__pen__(1)"],
1478 [r"(?<!:)\b(?:%s)\b" % a['PENUP'], "\n__pen__(0)"],
1479 [r"(?<!:)\b(?:%s)\b" % a['HIDETURTLE'], "\nhideturtle()"],
1480 [r"(?<!:)\b(?:%s)\b" % a['SHOWTURTLE'], "\nshowturtle()"],
1481 [r"(?<!:)\b(?:%s)\b\[" % a['POSITION'], "position()["],
1482 [r"(?<!:)\b(?:%s)\b(?!\()" % a['POSITION'], "\n)position("],
1483 [r"(?<!:)\b(?:%s)\b" % a['HEADING'], "\n)heading("],
1484 [r"(?<!:)\b(?:%s)\b" % a['PAGESIZE'], "pagesize()"],
1485 [r"(?<!:)\b(?:%s)\b" % a['POINT'], "\npoint()"],
1486 [r"(?<!:)\b(?:%s)\b" % (a['ELLIPSE'] + "|" + a['CIRCLE']), "\n)ellipse("],
1487 [r"(?<!:)\b(?:%s)\b" % (a['RECTANGLE'] + "|" + a['SQUARE']), "\n)rectangle("],
1488 [r"(?<!:)\b(?:%s)\b" % a['CLOSE'], "\n__fillit__(False)"],
1489 [r"(?<!:)\b(?:%s)\b" % a['FILL'], "\n__fillit__()"],
1490 [r"(?<!:)\b(?:%s)\b" % a['LABEL'], "\n)label("],
1491 [r"(?<!:)\b(?:%s)\b" % a['TEXT'], "\n)text(__getshape__(__ACTUAL__),"],
1492 [r"(text\([ \t]*\"[^\"\n\)]*)", "\\1\"\n"],
1493 [r"(?<!:)\b(?:%s)\b" % a['HOME'], "\nturtlehome()"],
1494 [r"(?<!:)\b(?:%s)\b" % a['SLEEP'], "\n)sleep("],
1495 [r"(?<!:)\b(?:%s)\b" % a['FORWARD'], "\n)forward("],
1496 [r"(?<!:)\b(?:%s)\b" % a['BACKWARD'], "\n)backward("],
1497 [r"(?<!:)\b(?:%s)\b" % a['TURNRIGHT'], "\n)turnright("],
1498 [r"(?<!:)\b(?:%s)\b" % a['RANDOM'], "Random"],
1499 [r"(?<!:)\b(?:%s)\b(?= \d)" % 'Random', "random.random()*"],
1500 [r"(?<!:)\b(?:%s)\b" % a['SET'], "set"],
1501 [r"(?<!:)\b(?:%s)\b" % a['RANGE'], "range"],
1502 [r"(?<!:)\b(?:%s)\b" % a['LIST'], "list"],
1503 [r"(?<!:)\b(?:%s)\b" % a['TUPLE'], "tuple"],
1504 [r"(?<!:)\b(?:%s)\b" % a['SORTED'], "sorted"],
1505 [r"(?<!:)\b(?:%s)\b ?\(" % a['RESEARCH'], "re.search('(?u)'+"],
1506 [r"(?<!:)\b(?:%s)\b ?\(" % a['RESUB'], "re.sub('(?u)'+"],
1507 [r"(?<!:)\b(?:%s)\b ?\(" % a['REFINDALL'], "re.findall('(?u)'+"],
1508 [r"(?<!:)\b(?:%s)\b" % a['ANY'], "u'any'"],
1509 [r"(?<!:)\b(?:%s) (\w+|[[][^\]]*])\b" % a['INPUT'], " Input(\\1)"],
1510 [r"(?<!:)\b(?:%s)\b" % a['PRINT'], "\n)Print("],
1511 [r"(?<!:)\b(?:%s)\b" % a['TURNLEFT'], "\n)turnleft("],
1512 [r"\b([0-9]+([,.][0-9]+)?)(%s)\b" % a['PT'], "\\1"],
1513 [r"\b([0-9]+([,.][0-9]+)?)(%s)(?!\w)" % a['INCH'], lambda r: str(float(r.group(1).replace(",", "."))*72)],
1514 [r"\b([0-9]+([,.][0-9]+)?)(%s)\b" % a['MM'], lambda r: str(float(r.group(1).replace(",", "."))*__MM_TO_PT__)],
1515 [r"\b([0-9]+([,.][0-9]+)?)(%s)\b" % a['CM'], lambda r: str(float(r.group(1).replace(",", "."))*__MM_TO_PT__*10)],
1516 [r"\b(__(?:int|float|string)__len|round|abs|sin|cos|sqrt|set|list|tuple|sorted)\b ((?:\w|\d+([,.]\d+)?|0[xX][0-9a-fA-F]+|[-+*/]| )+)\)" , "\\1(\\2))" ], # fix parsing: (1 + sqrt x) -> (1 + sqrt(x))
1517 [r"(?<=[-*/=+,]) ?\n\)(\w+)\(", "\\1()"], # read attributes, eg. x = fillcolor
1518 [r"(?<=return) ?\n\)(\w+)\(", "\\1()"], # return + user function
1519 [r"(?<=(?:Print|label)\() ?\n\)(\w+)\(", "\\1()\n"] # Print/label + user function
1522 def __concatenation__(r): # keep line positions with extra line breaks
1523 s = re.subn("~[ \t]*\n", " ", r.group(0))
1524 return s[0] + "\n" * s[1]
1526 def __compil__(s):
1527 global _, comp, __strings__, __compiled__
1528 try:
1529 c = _.doc.CurrentController.getViewCursor()
1530 locs = [i for i in [c.CharLocale, c.CharLocaleAsian, c.CharLocaleComplex] if i.Language != 'zxx'] # not None language
1531 loc = Locale(__uilocale__.split('-')[0], __uilocale__.split('-')[1], '')
1532 if locs and loc not in locs:
1533 loc = locs[0]
1534 try:
1535 _.lng = loc.Language + '_' + loc.Country
1536 __loadlang__(_.lng, __l12n__(_.lng))
1537 except:
1538 __trace__()
1539 _.lng = loc.Language
1540 __loadlang__(_.lng, __l12n__(_.lng))
1541 except:
1542 __trace__()
1543 _.lng = 'en_US'
1544 if not _.lng in __comp__:
1545 __loadlang__(_.lng, __l12n__(_.lng))
1547 _.decimal = __l12n__(_.lng)['DECIMAL']
1548 names = {}
1550 rmsp = re.compile(r"[ ]*([=+*/]|==|<=|>=|<>|!=|-[ ]+)[ ]*")
1551 chsp = re.compile(r"[ \t]+")
1552 chch = re.compile(r"(?u)(?<!\w):(?=\w)")
1553 parenfix = re.compile(r"(?ui)(\([^\(\[\]\)]+)]\)")
1555 # remove CR characters and split lines
1556 s = re.sub(r'[ \t\r]*(?=\n)', '', s)
1558 # remove full line comments
1559 s = re.sub(r"^[ \t]*[;#][^\n]*", "", s)
1560 s = re.sub(r"(?<=\n)[ \t]*[;#][^\n]*", "", s)
1562 # concatenate lines
1563 __compiled__ = re.sub(r'([^\n]*~[ \t]*\n)+[^\n]*', __concatenation__, s)
1565 # sign original line breaks
1566 s = re.sub("(?<=\n)", __LINEBREAK__ + "\n", __compiled__)
1568 # encode strings
1569 lq = '\'' + __l12n__(_.lng)['LEFTSTRING'].replace("|", "")
1570 rq = '\'' + __l12n__(_.lng)['RIGHTSTRING'].replace("|", "")
1571 __strings__ = []
1572 s = re.sub("(?u)([%s])([^\n%s]*)(?<!\\\\)[%s]" % (lq, rq, rq), __encodestring__, s)
1573 s = re.sub('(?u)(?<![0-9])(")(~?\w*)', __encodestring__, s)
1575 # remove extra spaces
1576 s = chsp.sub(" ", s)
1578 # remove inline comments
1579 s = re.sub(r"[ ]*;[^\n]*", "", s)
1581 # n-dash and m-dash as minus signs
1582 s = re.sub(r"(?u)[–—]", "-", s)
1584 # replace procedure names
1585 s = re.sub(r"(?i)^[ ]*(%s)[ ]+" % __l12n__(_.lng)['TO'], "__def__ ", s)
1586 s = re.sub(r"(?i)\n[ ]*(%s)[ ]+" % __l12n__(_.lng)['TO'], "\n__def__ ", s)
1587 subnames = re.findall(u"(?iu)(?<=__def__ )\w+", s)
1588 globs = ""
1589 functions = ["range", "__int__", "__float__", "Random", "Input", "__string__", "len", "round", "abs", "sin", "cos", "sqrt", "set", "list", "tuple", "re.sub", "re.search", "re.findall", "sorted", "min", "max"]
1591 if len(subnames) > 0:
1592 globs = "global %s" % ", ".join(subnames)
1593 # search user functions (function calls with two or more arguments need explicite Python parentheses)
1594 functions += [ re.findall("(?u)\w+",i[0])[0] for i in re.findall(r"""(?iu)(?<=__def__ )([^\n]*)\n # beginning of a procedure
1595 (?:[^\n]*(?<!\b(%(END)s))\n)* # 0 or more lines (not END)
1596 [^\n]*\b(?:%(OUTPUT)s)\b[^\n]*\n # line with OUTPUT (functions = procedures with OUTPUT)
1597 (?:[^\n]*(?<!\b(?:%(END)s))\n)* # 0 or more lines (not END)
1598 [ \t]*\b(?:%(END)s)\b""" % __l12n__(_.lng), s, re.X) ] # final END (XXX multiple names of "END" doesn't supported)
1599 # add line breaks before procedure calls
1600 procedures = set(subnames) - set(functions)
1601 if len(procedures) > 0:
1602 s = re.sub(r"(?<!__def__)(?<![-+=*/])(?<!%s)(?:^|[ \t]+)(" % ")(?<!".join(functions) + "|".join(procedures) + ")(?!\w)", r"\n\1", s)
1604 # compile native Logo
1605 for i in __comp__[_.lng]:
1606 s = re.sub(u"(?u)" + i[0], i[1], s)
1607 indent = 0
1608 result = ""
1609 func = re.compile("(?iu)(def (\w+))(\(.*\):)")
1610 expr = r"""(?iu)(?<!def[ ])(?<![:\w])%(name)s(?!\w)(?!\()(?![ ]\()
1612 ([ ]+\[*([-+]|\([ ]?)*((%(functions)s)\b[ ]*\(*)*
1613 (?:0x[0-9a-f]+|[0-9]+([,.][0-9]+)?|:?\w+(?:[.]\w+[\(]?[\)]?)?]*|\[])]*[\)]*
1615 (?:[ ]*([+*/,<>]|//|==|<=|>=|<>|!=)[ ]*|[ ]*-[ ]+|-|[ ]*[*][*][ ]*) # operators, eg. "**", " - ", "-", "- "
1616 \[*([-+]|\([ ]?)* # minus sign, parenthesis
1617 ((%(functions)s)\b[ ]*\(*)*(0x[0-9a-f]+|[0-9]+([.,][0-9]+)?|:?\w+(?:[.]\w+[\(]?[\)]?)?)]*
1618 ([ ]?\))*)*
1619 [\)]*){,%(repeat)s}
1622 chargsp = re.compile(r"(?<![\(,])(?<!%s) (?!\)|,)" % ")(?<!".join(functions))
1624 # compile to Python
1625 joinfunc = "|".join(functions)
1626 funcnames = {}
1628 for i in s.split("\n"):
1629 i = i.strip()
1630 if i[0:4] == 'def ':
1631 s = func.search(i)
1632 if s.group(3) == '():':
1633 names[s.group(2)] = (0, "")
1634 else:
1635 s2 = len(chsp.findall(s.group(3))) + 1
1636 i = s.group(1) + chsp.sub(", ", s.group(3))
1637 names[s.group(2)] = (s2, re.compile(expr % {"name": s.group(2), "functions": joinfunc, "repeat": s2}, re.X))
1638 for j in functions:
1639 if j in i:
1640 if not j in funcnames:
1641 funcnames[j] = (1, re.compile(expr % {"name": j, "functions": joinfunc, "repeat": 1 + 2 * int(j == 'range')}, re.X))
1642 r = funcnames[j][1].search(i)
1643 while r:
1644 i = i[:r.start()] + j + '(' + chargsp.sub(", ", rmsp.sub(lambda l: l.group(1).strip(), r.group(1).strip())) + ')' + i[r.end():]
1645 i = parenfix.sub("\\1)]", i)
1646 r = funcnames[j][1].search(i)
1647 for j in names:
1648 if j in i:
1649 if names[j][0] == 0:
1650 if not j in functions:
1651 i = re.sub(r"(?iu)(?<!def )(?<![_\w])\b%s\b(?!\w)" %j, j+'()', i)
1652 else:
1653 r = names[j][1].search(i)
1654 if r:
1655 i = i[:r.start()] + j + '(' + chargsp.sub(", ", rmsp.sub(lambda l: l.group(1).strip(), r.group(1).strip())) + ')' + i[r.end():]
1656 i = parenfix.sub("\\1)]", i)
1657 if i[0:1] == '[':
1658 i = i[1:]
1659 indent += 1
1660 result = result + "\n" + " " * indent + "__checkhalt__()\n"
1661 if i[0:1] == ')':
1662 i = i[1:] + ')'
1663 result = result + "\n" + " " * indent + i
1664 if i[0:1] == ']':
1665 result = result[:-1]
1666 indent -= 1
1668 # colon_to_underline in Logo variables
1669 result = chch.sub("_", result)
1671 # character encoding
1672 result = to_ascii(result).replace(r"\n", "\n")
1674 # decode strings
1675 result = re.sub(__DECODE_STRING_REGEX__, __decodestring__, result)
1676 return to_ascii(globs) + "\n" + result
1678 def __gotoline__(n):
1679 _.cursor.collapseToStart()
1680 for i in range(1, n):
1681 _.cursor.gotoNextParagraph(False)
1682 try:
1683 _.doc.CurrentController.getViewCursor().gotoRange(_.cursor, False)
1684 except:
1685 __dispatcher__(".uno:Escape")
1686 _.doc.CurrentController.getViewCursor().gotoRange(_.cursor.getStart(), False)
1688 g_exportedScripts = left, right, goforward, gobackward, run, stop, home, clearscreen, commandline, __translate__
1689 g_ImplementationHelper = unohelper.ImplementationHelper()
1690 g_ImplementationHelper.addImplementation( \
1691 None,"org.openoffice.script.LibreLogo", \
1692 ("org.openoffice.script.ServiceLibreLogo",),)
1694 # vim: set noet sw=4 ts=4: