editors/TextViewer.py
changeset 1911 c1298e7ffe3a
parent 1637 6f4624687b89
child 1730 64d8f52bc8c8
equal deleted inserted replaced
1910:a375e31bf312 1911:c1298e7ffe3a
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     2 # -*- coding: utf-8 -*-
     3 
     3 
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     4 # This file is part of Beremiz, a Integrated Development Environment for
     5 #based on the plcopen standard.
     5 # programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
     6 #
     6 #
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     7 # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     8 #
     8 #
     9 #See COPYING file for copyrights details.
     9 # See COPYING file for copyrights details.
    10 #
    10 #
    11 #This library is free software; you can redistribute it and/or
    11 # This program is free software; you can redistribute it and/or
    12 #modify it under the terms of the GNU General Public
    12 # modify it under the terms of the GNU General Public License
    13 #License as published by the Free Software Foundation; either
    13 # as published by the Free Software Foundation; either version 2
    14 #version 2.1 of the License, or (at your option) any later version.
    14 # of the License, or (at your option) any later version.
    15 #
    15 #
    16 #This library is distributed in the hope that it will be useful,
    16 # This program is distributed in the hope that it will be useful,
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
    17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19 #General Public License for more details.
    19 # GNU General Public License for more details.
    20 #
    20 #
    21 #You should have received a copy of the GNU General Public
    21 # You should have received a copy of the GNU General Public License
    22 #License along with this library; if not, write to the Free Software
    22 # along with this program; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    24 
    24 
    25 import re
    25 import re
    26 from types import *
    26 from types import *
    27 
    27 
    28 import wx
    28 import wx
    45     LETTERS.append(chr(ord('a') + i))
    45     LETTERS.append(chr(ord('a') + i))
    46     LETTERS.append(chr(ord('A') + i))
    46     LETTERS.append(chr(ord('A') + i))
    47 
    47 
    48 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING,
    48 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING,
    49  STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP,
    49  STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP,
    50  STC_PLC_ERROR, STC_PLC_SEARCH_RESULT] = range(10)
    50  STC_PLC_ERROR, STC_PLC_SEARCH_RESULT,
       
    51  STC_PLC_EMPTY] = range(11)
    51 [SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT, PRAGMA, DPRAGMA] = range(8)
    52 [SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT, PRAGMA, DPRAGMA] = range(8)
    52 
    53 
    53 [ID_TEXTVIEWER, ID_TEXTVIEWERTEXTCTRL,
    54 [ID_TEXTVIEWER, ID_TEXTVIEWERTEXTCTRL,
    54 ] = [wx.NewId() for _init_ctrls in range(2)]
    55 ] = [wx.NewId() for _init_ctrls in range(2)]
    55 
    56 
   256                     blockinputs = values[3]
   257                     blockinputs = values[3]
   257                 else:
   258                 else:
   258                     blockinputs = None
   259                     blockinputs = None
   259                 if values[1] != "function":
   260                 if values[1] != "function":
   260                     if blockname == "":
   261                     if blockname == "":
   261                         dialog = wx.TextEntryDialog(self.ParentWindow, "Block name", "Please enter a block name", "", wx.OK|wx.CANCEL|wx.CENTRE)
   262                         dialog = wx.TextEntryDialog(self.ParentWindow, _("Block name"), _("Please enter a block name"), "", wx.OK|wx.CANCEL|wx.CENTRE)
   262                         if dialog.ShowModal() == wx.ID_OK:
   263                         if dialog.ShowModal() == wx.ID_OK:
   263                             blockname = dialog.GetValue()
   264                             blockname = dialog.GetValue()
   264                         else:
   265                         else:
       
   266                             event.SetDragText("")                            
   265                             return
   267                             return
   266                         dialog.Destroy()
   268                         dialog.Destroy()
   267                     if blockname.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
   269                     if blockname.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
   268                         message = _("\"%s\" pou already exists!")%blockname
   270                         message = _("\"%s\" pou already exists!")%blockname
   269                     elif blockname.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
   271                     elif blockname.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
   285                 if len(values) > 2 and pou_type == "program":
   287                 if len(values) > 2 and pou_type == "program":
   286                     var_name = values[3]
   288                     var_name = values[3]
   287                     dlg = wx.TextEntryDialog(
   289                     dlg = wx.TextEntryDialog(
   288                         self.ParentWindow,
   290                         self.ParentWindow,
   289                         _("Confirm or change variable name"),
   291                         _("Confirm or change variable name"),
   290                         'Variable Drop', var_name)
   292                         _('Variable Drop'), var_name)
   291                     dlg.SetValue(var_name)
   293                     dlg.SetValue(var_name)
   292                     var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
   294                     var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
   293                     dlg.Destroy()
   295                     dlg.Destroy()
   294                     if var_name is None:
   296                     if var_name is None:
   295                         return
   297                         return
   300                     else:
   302                     else:
   301                         location = values[0]
   303                         location = values[0]
   302                         if not location.startswith("%"):
   304                         if not location.startswith("%"):
   303                             dialog = wx.SingleChoiceDialog(self.ParentWindow,
   305                             dialog = wx.SingleChoiceDialog(self.ParentWindow,
   304                                   _("Select a variable class:"), _("Variable class"),
   306                                   _("Select a variable class:"), _("Variable class"),
   305                                   ["Input", "Output", "Memory"],
   307                                   [_("Input"), _("Output"), _("Memory")],
   306                                   wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   308                                   wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   307                             if dialog.ShowModal() == wx.ID_OK:
   309                             if dialog.ShowModal() == wx.ID_OK:
   308                                 selected = dialog.GetSelection()
   310                                 selected = dialog.GetSelection()
   309                             else:
   311                             else:
   310                                 selected = None
   312                                 selected = None
   336                     initval = values[0]
   338                     initval = values[0]
   337                     var_name = values[3]
   339                     var_name = values[3]
   338                     dlg = wx.TextEntryDialog(
   340                     dlg = wx.TextEntryDialog(
   339                         self.ParentWindow,
   341                         self.ParentWindow,
   340                         _("Confirm or change variable name"),
   342                         _("Confirm or change variable name"),
   341                         'Variable Drop', var_name)
   343                         _('Variable Drop'), var_name)
   342                     dlg.SetValue(var_name)
   344                     dlg.SetValue(var_name)
   343                     var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
   345                     var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
   344                     dlg.Destroy()
   346                     dlg.Destroy()
   345                     if var_name is None:
   347                     if var_name is None:
   346                         return
   348                         return
   359             elif values[1] == "Global":
   361             elif values[1] == "Global":
   360                 var_name = values[0]
   362                 var_name = values[0]
   361                 dlg = wx.TextEntryDialog(
   363                 dlg = wx.TextEntryDialog(
   362                     self.ParentWindow,
   364                     self.ParentWindow,
   363                     _("Confirm or change variable name"),
   365                     _("Confirm or change variable name"),
   364                     'Variable Drop', var_name)
   366                     _('Variable Drop'), var_name)
   365                 dlg.SetValue(var_name)
   367                 dlg.SetValue(var_name)
   366                 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
   368                 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
   367                 dlg.Destroy()
   369                 dlg.Destroy()
   368                 if var_name is None:
   370                 if var_name is None:
   369                     return
   371                     return
   410     def SetKeywords(self, keywords):
   412     def SetKeywords(self, keywords):
   411         self.Keywords = [keyword.upper() for keyword in keywords]
   413         self.Keywords = [keyword.upper() for keyword in keywords]
   412         self.Colourise(0, -1)
   414         self.Colourise(0, -1)
   413 
   415 
   414     def RefreshJumpList(self):
   416     def RefreshJumpList(self):
   415         if self.TextSyntax != "IL":
   417         if self.TextSyntax == "IL":
   416             self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
   418             self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
   417             self.Colourise(0, -1)
   419             self.Colourise(0, -1)
   418 
   420 
   419     # Buffer the last model state
   421     # Buffer the last model state
   420     def RefreshBuffer(self):
   422     def RefreshBuffer(self):
   574             line += char
   576             line += char
   575             if char == NEWLINE:
   577             if char == NEWLINE:
   576                 self.ContextStack = []
   578                 self.ContextStack = []
   577                 current_context = self.Variables
   579                 current_context = self.Variables
   578                 if state == COMMENT:
   580                 if state == COMMENT:
   579                     self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_COMMENT)
   581                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_COMMENT)
   580                 elif state == NUMBER:
   582                 elif state == NUMBER:
   581                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   583                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   582                 elif state == WORD:
   584                 elif state == WORD:
   583                     if word in self.Keywords or word in self.TypeNames:
   585                     if word in self.Keywords or word in self.TypeNames:
   584                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
   586                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
   591                     elif self.TextSyntax == "IL" and word in self.Jumps:
   593                     elif self.TextSyntax == "IL" and word in self.Jumps:
   592                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   594                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   593                     elif word in self.EnumeratedValues:
   595                     elif word in self.EnumeratedValues:
   594                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   596                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   595                     else:
   597                     else:
   596                         self.SetStyling(current_pos - last_styled_pos, 31)
   598                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   597                         if word not in ["]", ")"] and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos):
   599                         if word not in ["]", ")"] and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos):
   598                             self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK)
   600                             self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK)
   599                             self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
   601                             self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
   600                             self.StartStyling(current_pos, 0xff)
   602                             self.StartStyling(current_pos, 0xff)
   601                 else:
   603                 else:
   602                     self.SetStyling(current_pos - last_styled_pos, 31)
   604                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   603                 last_styled_pos = current_pos
   605                 last_styled_pos = current_pos
   604                 if state != DPRAGMA:
   606                 if (state != DPRAGMA) and (state != COMMENT):
   605                     state = SPACE
   607                     state = SPACE
   606                 line = ""
   608                 line = ""
   607                 line_number += 1
   609                 line_number += 1
   608                 self.RefreshLineFolding(line_number)
   610                 self.RefreshLineFolding(line_number)
   609             elif line.endswith("(*") and state != COMMENT:
   611             elif line.endswith("(*") and state != COMMENT:
   610                 self.SetStyling(current_pos - last_styled_pos - 1, 31)
   612                 self.SetStyling(current_pos - last_styled_pos - 1, STC_PLC_EMPTY)
   611                 last_styled_pos = current_pos
   613                 last_styled_pos = current_pos
   612                 if state == WORD:
   614                 if state == WORD:
   613                     current_context = self.Variables
   615                     current_context = self.Variables
   614                 state = COMMENT
   616                 state = COMMENT
   615             elif line.endswith("{") and state not in [PRAGMA, DPRAGMA]:
   617             elif line.endswith("{") and state not in [PRAGMA, DPRAGMA]:
   616                 self.SetStyling(current_pos - last_styled_pos, 31)
   618                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   617                 last_styled_pos = current_pos
   619                 last_styled_pos = current_pos
   618                 if state == WORD:
   620                 if state == WORD:
   619                     current_context = self.Variables
   621                     current_context = self.Variables
   620                 state = PRAGMA
   622                 state = PRAGMA
   621             elif line.endswith("{{") and state == PRAGMA:
   623             elif line.endswith("{{") and state == PRAGMA:
   622                 self.SetStyling(current_pos - last_styled_pos, 31)
   624                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   623                 last_styled_pos = current_pos
   625                 last_styled_pos = current_pos
   624                 state = DPRAGMA
   626                 state = DPRAGMA
   625             elif state == COMMENT:
   627             elif state == COMMENT:
   626                 if line.endswith("*)"):
   628                 if line.endswith("*)"):
   627                     self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
   629                     self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
   628                     last_styled_pos = current_pos + 1
   630                     last_styled_pos = current_pos + 1
   629                     state = SPACE
   631                     state = SPACE
       
   632                     if len(self.CallStack) > 0:
       
   633                         current_call = self.CallStack.pop()
       
   634                     else:
       
   635                         current_call = None                    
   630             elif state == PRAGMA:
   636             elif state == PRAGMA:
   631                 if line.endswith("}"):
   637                 if line.endswith("}"):
   632                     self.SetStyling(current_pos - last_styled_pos, 31)
   638                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   633                     last_styled_pos = current_pos
   639                     last_styled_pos = current_pos
   634                     state = SPACE
   640                     state = SPACE
   635             elif state == DPRAGMA:
   641             elif state == DPRAGMA:
   636                 if line.endswith("}}"):
   642                 if line.endswith("}}"):
   637                     self.SetStyling(current_pos - last_styled_pos + 1, 31)
   643                     self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_EMPTY)
   638                     last_styled_pos = current_pos + 1
   644                     last_styled_pos = current_pos + 1
   639                     state = SPACE
   645                     state = SPACE
   640             elif (line.endswith("'") or line.endswith('"')) and state not in [STRING, WSTRING]:
   646             elif (line.endswith("'") or line.endswith('"')) and state not in [STRING, WSTRING]:
   641                 self.SetStyling(current_pos - last_styled_pos, 31)
   647                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   642                 last_styled_pos = current_pos
   648                 last_styled_pos = current_pos
   643                 if state == WORD:
   649                 if state == WORD:
   644                     current_context = self.Variables
   650                     current_context = self.Variables
   645                 if line.endswith("'"):
   651                 if line.endswith("'"):
   646                     state = STRING
   652                     state = STRING
   659             elif char in LETTERS:
   665             elif char in LETTERS:
   660                 if state == NUMBER:
   666                 if state == NUMBER:
   661                     word = "#"
   667                     word = "#"
   662                     state = WORD
   668                     state = WORD
   663                 elif state == SPACE:
   669                 elif state == SPACE:
   664                     self.SetStyling(current_pos - last_styled_pos, 31)
   670                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   665                     word = char
   671                     word = char
   666                     last_styled_pos = current_pos
   672                     last_styled_pos = current_pos
   667                     state = WORD
   673                     state = WORD
   668                 else:
   674                 else:
   669                     word += char
   675                     word += char
   670             elif char in NUMBERS or char == '.' and state != WORD:
   676             elif char in NUMBERS or char == '.' and state != WORD:
   671                 if state == SPACE:
   677                 if state == SPACE:
   672                     self.SetStyling(current_pos - last_styled_pos, 31)
   678                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   673                     last_styled_pos = current_pos
   679                     last_styled_pos = current_pos
   674                     state = NUMBER
   680                     state = NUMBER
   675                 elif state == WORD and char != '.':
   681                 elif state == WORD and char != '.':
   676                     word += char
   682                     word += char
   677             elif char == '(' and state == SPACE:
   683             elif char == '(' and state == SPACE:
   690                     elif self.TextSyntax == "IL" and word in self.Jumps:
   696                     elif self.TextSyntax == "IL" and word in self.Jumps:
   691                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   697                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   692                     elif word in self.EnumeratedValues:
   698                     elif word in self.EnumeratedValues:
   693                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   699                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   694                     else:
   700                     else:
   695                         self.SetStyling(current_pos - last_styled_pos, 31)
   701                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   696                         if word not in ["]", ")"] and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos):
   702                         if word not in ["]", ")"] and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos):
   697                             self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK)
   703                             self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK)
   698                             self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
   704                             self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
   699                             self.StartStyling(current_pos, 0xff)
   705                             self.StartStyling(current_pos, 0xff)
   700                     if char == '.':
   706                     if char == '.':
   754             elif word in self.Jumps:
   760             elif word in self.Jumps:
   755                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   761                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   756             elif word in self.EnumeratedValues:
   762             elif word in self.EnumeratedValues:
   757                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   763                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   758             else:
   764             else:
   759                 self.SetStyling(current_pos - last_styled_pos, 31)
   765                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
   760         else:
   766         else:
   761             self.SetStyling(current_pos - start_pos, 31)
   767             self.SetStyling(current_pos - start_pos, STC_PLC_EMPTY)
   762         self.ShowHighlights(start_pos, end_pos)
   768         self.ShowHighlights(start_pos, end_pos)
   763         event.Skip()
   769         event.Skip()
   764 
   770 
   765     def OnMarginClick(self, event):
   771     def OnMarginClick(self, event):
   766         if event.GetMargin() == 2:
   772         if event.GetMargin() == 2:
   802     def Find(self, direction, search_params):
   808     def Find(self, direction, search_params):
   803         if self.SearchParams != search_params:
   809         if self.SearchParams != search_params:
   804             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
   810             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
   805 
   811 
   806             self.SearchParams = search_params
   812             self.SearchParams = search_params
   807             criteria = {
       
   808                 "raw_pattern": search_params["find_pattern"],
       
   809                 "pattern": re.compile(search_params["find_pattern"]),
       
   810                 "case_sensitive": search_params["case_sensitive"],
       
   811                 "regular_expression": search_params["regular_expression"],
       
   812                 "filter": "all"}
       
   813 
       
   814             self.SearchResults = [
   813             self.SearchResults = [
   815                 (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)
   814                 (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)
   816                 for infos, start, end, text in
   815                 for infos, start, end, text in
   817                 self.Search(criteria)]
   816                 self.Search(search_params)]
   818             self.CurrentFindHighlight = None
   817             self.CurrentFindHighlight = None
   819 
   818 
   820         if len(self.SearchResults) > 0:
   819         if len(self.SearchResults) > 0:
   821             if self.CurrentFindHighlight is not None:
   820             if self.CurrentFindHighlight is not None:
   822                 old_idx = self.SearchResults.index(self.CurrentFindHighlight)
   821                 old_idx = self.SearchResults.index(self.CurrentFindHighlight)
   893                         indent = (indent / 2 + 1) * 2
   892                         indent = (indent / 2 + 1) * 2
   894                     self.Editor.AddText("\n" + " " * indent)
   893                     self.Editor.AddText("\n" + " " * indent)
   895                     key_handled = True
   894                     key_handled = True
   896             elif key == wx.WXK_BACK:
   895             elif key == wx.WXK_BACK:
   897                 if self.TextSyntax in ["ST", "ALL"]:
   896                 if self.TextSyntax in ["ST", "ALL"]:
   898                     indent = self.Editor.GetLineIndentation(line)
   897                     if not self.Editor.GetSelectedText():
   899                     if lineText.strip() == "" and indent > 0:
   898                         indent = self.Editor.GetColumn(self.Editor.GetCurrentPos())
   900                         self.Editor.DelLineLeft()
   899                         if lineText.strip() == "" and len(lineText) > 0 and indent > 0:
   901                         self.Editor.AddText(" " * ((max(0, indent - 1) / 2) * 2))
   900                             self.Editor.DelLineLeft()
   902                         key_handled = True
   901                             self.Editor.AddText(" " * ((max(0, indent - 1) / 2) * 2))
       
   902                             key_handled = True
   903             if not key_handled:
   903             if not key_handled:
   904                 event.Skip()
   904                 event.Skip()
   905         elif key in NAVIGATION_KEYS:
   905         else:
   906             event.Skip()
   906             event.Skip()
   907 
   907 
   908     def OnKillFocus(self, event):
   908     def OnKillFocus(self, event):
   909         self.Editor.AutoCompCancel()
   909         self.Editor.AutoCompCancel()
   910         event.Skip()
   910         event.Skip()