#	Programmer:	Daniel Pozmanter
#	E-mail:		drpython@bluebottle.com
#	Note:		You must reply to the verification e-mail to get through.
#
#	Copyright 2003-2005 Daniel Pozmanter
#
#	Distributed under the terms of the GPL (GNU Public License)
#
#	DrPython is free software; you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation; either version 2 of the License, or
#	(at your option) any later version.
#
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#
#	You should have received a copy of the GNU General Public License
#	along with this program; if not, write to the Free Software
#	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
	
#The StyledTextControl Base Class

import re, string
import wx
import wx.stc
import drPopUp
import drShortcuts, drShortcutsFile
from drDragAndDrop import drDropTarget
from drFindReplaceDialog import drFinder

#*******************************************************************************************************

class DrStyledTextControl(wx.stc.StyledTextCtrl):
	def __init__(self, parent, id, grandparent):
		wx.stc.StyledTextCtrl.__init__(self, parent, id)
		
		#Constants:
		
		self.PYTHON_FILE = 0
		self.CPP_FILE = 1
		self.HTML_FILE = 2
		self.TEXT_FILE = 3
		
		self.IsAPrompt = False
		
		self.IndicatorSetStyle(0, wx.stc.STC_INDIC_HIDDEN)
	
		self.grandparent = grandparent
	
		self.Finder = drFinder(grandparent, self)
	
		#Python!!!!
		self.filetype = 0
			
		self.stclabelarray = drShortcutsFile.GetSTCShortcutList()
		self.stcactionarray = drShortcuts.GetSTCCommandList()
				
		self.ID_POPUP_BASE = 33000
		
		#Speed Optimization Submitted by Franz
		self.SetModEventMask(wx.stc.STC_PERFORMED_UNDO | wx.stc.STC_PERFORMED_REDO |\
		wx.stc.STC_MOD_DELETETEXT | wx.stc.STC_MOD_INSERTTEXT)
		
		self.droptarget = drDropTarget(self)
		
		self.SetDropTarget(self.droptarget)

		#WIERD!
		self.SetProperty("tab.timmy.whinge.level", "1")
						
		#Right Click Menu
		self.UsePopUp(0)
								
		self.SetMarginType(0, wx.stc.STC_MARGIN_SYMBOL)
		self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
		
		self.SetMarginWidth(0, 0)
		self.SetMarginWidth(1, 0)
		self.SetMarginWidth(2, 0)
		
		self.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL)
		self.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS)
		
		self.SetScrollWidth(1)
			
		self.retab = re.compile('^\t+', re.MULTILINE)
		self.respaces = re.compile('^ +', re.MULTILINE)
		self.remixedoutright = re.compile('(^\t+ )|(^ +\t)', re.MULTILINE)

		self.indentationtype = 2
		
		self.renonwhitespace = re.compile('\S')
						
		if (self.grandparent.prefs.doceolmode[self.filetype] == 1):
			self.SetEOLMode(wx.stc.STC_EOL_CRLF)
		elif (self.grandparent.prefs.doceolmode[self.filetype] == 2):
			self.SetEOLMode(wx.stc.STC_EOL_CR)
		else:
			self.SetEOLMode(wx.stc.STC_EOL_LF)
				
		self.Bind(wx.EVT_RIGHT_DOWN, self.OnPopUp)
		self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)

	def CheckIndentation(self, text=None):
		if text is None:
			text = self.GetText()
		if len(text) < 1:
			return 2
			
		tabs = (self.retab.search(text) is not None)
		spaces = (self.respaces.search(text) is not None)
		mixed = (self.remixedoutright.search(text) is not None)
				
		if mixed or (tabs and spaces):
			return 0
		elif tabs:
			return 1
		elif spaces:
			return -1
		return 2

	def EnsurePositionIsVisible(self, position):
		self.GotoPos(self.PositionFromLine(self.LineFromPosition(position)))
		
		self.EnsureCaretVisible()
		
		self.GotoPos(position)
		
		self.EnsureCaretVisible()

	def GetEndOfLineCharacter(self):
		emode = self.GetEOLMode()
		if emode == wx.stc.STC_EOL_CR:
			return '\r'
		elif emode == wx.stc.STC_EOL_CRLF:
			return '\r\n'
		return '\n'

	def GetIndentationCharacter(self):
		#What is this document using?
		result = self.CheckIndentation()
		if result == 0:
			if self.grandparent.prefs.docusetabs[self.filetype]:
				result = 1
			else:
				result = -1
				
		if (result == 1):
			compchar = '\t'
		else:
			compchar = ' '
		
		return compchar

	def OnLeftDown(self, event):
		self.droptarget.SetModifierDown(event.ControlDown())
		if self.grandparent.prefs.draganddropmode != 1:
			pos = self.PositionFromPoint(wx.Point(event.GetX(), event.GetY()))
			s, e = self.GetSelection()
			if (pos > s) and (pos < e):
				self.SetSelection(pos, pos)
				return
		event.Skip()

	def OnPopUp(self, event):
		drPopUp.OnPopUp(self, event)

	def OnPopUpMenu(self, event):
		drPopUp.OnPopUpMenu(self, event)

	def Paste(self):
		if wx.TheClipboard.IsOpened():
			wx.TheClipboard.Close()
		wx.TheClipboard.Open()
		tdo = wx.TextDataObject()
		data = wx.TheClipboard.GetData(tdo)
		if data:
			text = tdo.GetText()

			#Clean Up the Text:
			
			#Line Endings First:
			emode = self.GetEOLMode()
			if emode == wx.stc.STC_EOL_CR:
				text = self.grandparent.FormatMacReTarget.sub('\r', text)
			elif emode == wx.stc.STC_EOL_CRLF:
				text = self.grandparent.FormatWinReTarget.sub('\r\n', text)
			else:
				text = self.grandparent.FormatUnixReTarget.sub('\n', text)
			
			line, pos = self.GetCurLine()
			
			skipfirstline = self.renonwhitespace.search(line[:pos]) is not None

			#Now Indentation:
			if self.indentationtype == -1:
				text = self.SetToSpaces(-1, text)
			elif self.indentationtype == 1:
				text = self.SetToTabs(-1, text, skipfirstline)
			else:
				if self.grandparent.prefs.docusetabs[self.filetype]:
					text = self.SetToTabs(-1, text, skipfirstline)
				else:
					text = self.SetToSpaces(-1, text)
				if self.grandparent.prefs.docusetabs[self.filetype]:
					self.indentationtype = 1
				else:
					self.indentationtype = -1
				
			s, e = self.GetSelection()
			if (e - s) > 0:
				self.SetTargetStart(s)
				self.SetTargetEnd(e)
				self.ReplaceTarget(text)
				pos = self.GetCurrentPos()
			else:
				pos = self.GetCurrentPos()
				self.InsertText(pos, text)
				
			self.GotoPos(pos + len(text))
		
		self.OnModified(None)
			
		wx.TheClipboard.Close()

	def SetSelectedText(self, text):
		self.SetTargetStart(self.GetSelectionStart())
		self.SetTargetEnd(self.GetSelectionEnd())
		self.ReplaceTarget(text)
	
	def SetToSpaces(self, tabwidth=-1, text=''):
		if tabwidth < 0:
			tabwidth = self.grandparent.prefs.doctabwidth[self.filetype]
		eol = self.GetEndOfLineCharacter()
		regex = re.compile('(\S)|' + eol)
		if len(text) < 1:
			text = self.GetText()
			SetTheText = True
		else:
			SetTheText = False
		lines = text.split(eol)
		new_lines = []
		for line in lines:
			result = regex.search(line + eol)
			if result is not None:
				end = result.start()
				new_lines.append(line[0:end].expandtabs(tabwidth) + line[end:])
			else:
				new_lines.append(line)
		newtext = string.join(new_lines, eol)
		self.indentationtype = -1
		self.SetupTabs(False)
		if SetTheText:
			self.SetText(newtext)
		else:
			return newtext
		
	def SetToTabs(self, tabwidth=-1, text='', skipfirstline=False):
		if tabwidth < 0:
			tabwidth = self.grandparent.prefs.doctabwidth[self.filetype] - 1
		else:
			tabwidth -= 1
		eol = self.GetEndOfLineCharacter()
		regex = re.compile('(\S)|' + eol)
		#Create Target String
		y = 0
		oof = " "
		while (y < tabwidth):
			oof = oof + " "
			y = y + 1
		#Continue
		if len(text) < 1:
			text = self.GetText()
			SetTheText = True
		else:
			SetTheText = False
		lines = text.split(eol)
		new_lines = []
		x = 0
		for line in lines:
			result = regex.search(line + eol)
			if result is not None:
				end = result.start()
				newline = line[0:end].replace(oof, "\t")
				if x == 0 and skipfirstline:
					newline = newline + line[end:]
				else:
					newline = newline.replace(' ', '') + line[end:]
				new_lines.append(newline)
			else:
				new_lines.append(line)
			x += 1
		newtext = string.join(new_lines, eol)
		
		self.indentationtype = 1
		self.SetupTabs(True)
		
		if SetTheText:
			self.SetText(newtext)
		else:
			return newtext
		
	def SetupTabs(self, UseTabs=-1):
		if UseTabs == -1:
			UseTabs = self.grandparent.prefs.docusetabs[self.filetype]
			
		self.SetUseTabs(UseTabs)
		
		self.tabwidth = self.grandparent.prefs.doctabwidth[self.filetype]
		self.addchar = '\t'
		if (not UseTabs):
			#franz: x not referenced
			self.addchar = "\t".expandtabs(self.tabwidth)

syntax highlighted by Code2HTML, v. 0.9.1