1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #include <svtools/svmedit.hxx>
32 #include <svtools/xtextedt.hxx>
33 #include <svtools/editsyntaxhighlighter.hxx>
34 #include <svtools/txtattr.hxx>
35 
36 
37 MultiLineEditSyntaxHighlight::MultiLineEditSyntaxHighlight( Window* pParent, WinBits nWinStyle,
38 	HighlighterLanguage aLanguage): MultiLineEdit(pParent,nWinStyle), mbDoBracketHilight(true)
39 {
40 	EnableUpdateData(300);
41 	aHighlighter.initialize( aLanguage );
42 }
43 
44 MultiLineEditSyntaxHighlight::MultiLineEditSyntaxHighlight( Window* pParent, const ResId& rResId ,
45 	HighlighterLanguage aLanguage): MultiLineEdit(pParent,rResId), mbDoBracketHilight(true)
46 {
47 	EnableUpdateData(300);
48 	aHighlighter.initialize( aLanguage );
49 }
50 
51 MultiLineEditSyntaxHighlight::~MultiLineEditSyntaxHighlight()
52 {
53 }
54 
55 void MultiLineEditSyntaxHighlight::EnableBracketHilight(bool aHilight)
56 {
57 	mbDoBracketHilight = aHilight;
58 }
59 
60 bool MultiLineEditSyntaxHighlight::IsBracketHilight()
61 {
62 	return mbDoBracketHilight;
63 }
64 
65 void MultiLineEditSyntaxHighlight::SetText(const String& rNewText)
66 {
67 	MultiLineEdit::SetText(rNewText);
68 	UpdateData();
69 }
70 
71 void MultiLineEditSyntaxHighlight::DoBracketHilight(sal_uInt16 aKey)
72 {
73 	TextSelection aCurrentPos = GetTextView()->GetSelection();
74 	xub_StrLen aStartPos  = aCurrentPos.GetStart().GetIndex();
75 	sal_uLong nStartPara = aCurrentPos.GetStart().GetPara();
76 	sal_uInt16 aCount = 0;
77 	int aChar = -1;
78 
79 	switch (aKey)
80 	{
81 		case '\'':	// no break
82 		case '"':
83 		{
84 			aChar = aKey;
85 			break;
86 		}
87 		case '}' :
88 		{
89 			aChar = '{';
90 			break;
91 		}
92 		case ')':
93 		{
94 			aChar = '(';
95 			break;
96 		}
97 		case ']':
98 		{
99 			aChar = '[';
100 			break;
101 		}
102 	}
103 
104 	if (aChar != -1)
105 	{
106 		for (long aPara =nStartPara; aPara>=0;--aPara)
107 		{
108             if ( aStartPos == 0 )
109                 continue;
110 
111 			String aLine( GetTextEngine()->GetText( aPara ) );
112 			for (sal_uInt16 i = ((unsigned long)aPara==nStartPara) ? aStartPos-1 : (sal_uInt16)(aLine.Len()-1); i>0; --i)
113 			{
114 				if (aLine.GetChar(i)==aChar)
115 				{
116 					if (!aCount)
117 					{
118 						GetTextEngine()->SetAttrib( TextAttribFontWeight( WEIGHT_ULTRABOLD ), aPara, i, i+1, sal_True );
119 						GetTextEngine()->SetAttrib( TextAttribFontColor( Color(0,0,0) ), aPara, i, i+1, sal_True );
120 						GetTextEngine()->SetAttrib( TextAttribFontWeight( WEIGHT_ULTRABOLD ), nStartPara, aStartPos, aStartPos, sal_True );
121 						GetTextEngine()->SetAttrib( TextAttribFontColor( Color(0,0,0) ), nStartPara, aStartPos, aStartPos, sal_True );
122 						return;
123 					}
124 					else
125 						aCount--;
126 				}
127 				if (aLine.GetChar(i)==aKey)
128 					aCount++;
129 			}
130 		}
131 	}
132 }
133 
134 long MultiLineEditSyntaxHighlight::PreNotify( NotifyEvent& rNEvt )
135 {
136 	if ( mbDoBracketHilight && (rNEvt.GetType() == EVENT_KEYINPUT) )
137 		DoBracketHilight(rNEvt.GetKeyEvent()->GetCharCode());
138 
139 	return MultiLineEdit::PreNotify(rNEvt);
140 }
141 
142 Color MultiLineEditSyntaxHighlight::GetColorValue(TokenTypes aToken)
143 {
144 	Color aColor;
145 	switch (aHighlighter.GetLanguage())
146 	{
147 		case HIGHLIGHT_SQL:
148 		{
149 			switch (aToken)
150 			{
151 				case TT_IDENTIFIER:	aColor = (ColorData)m_aColorConfig.GetColorValue(svtools::SQLIDENTIFIER).nColor; break;
152 				case TT_NUMBER:		aColor = (ColorData)m_aColorConfig.GetColorValue(svtools::SQLNUMBER).nColor; break;
153 				case TT_STRING:		aColor = (ColorData)m_aColorConfig.GetColorValue(svtools::SQLSTRING).nColor; break;
154 				case TT_OPERATOR:	aColor = (ColorData)m_aColorConfig.GetColorValue(svtools::SQLOPERATOR).nColor; break;
155 				case TT_KEYWORDS:	aColor = (ColorData)m_aColorConfig.GetColorValue(svtools::SQLKEYWORD).nColor; break;
156 				case TT_PARAMETER:  aColor = (ColorData)m_aColorConfig.GetColorValue(svtools::SQLPARAMETER).nColor; break;
157 				case TT_COMMENT:	aColor = (ColorData)m_aColorConfig.GetColorValue(svtools::SQLCOMMENT).nColor; break;
158 				default:			aColor = Color(0,0,0);
159 			}
160 			break;
161 		}
162 		case HIGHLIGHT_BASIC:
163 		{
164 			switch (aToken)
165 			{
166 				case TT_IDENTIFIER:	aColor = Color(255,0,0); break;
167 				case TT_COMMENT:	aColor = Color(0,0,45); break;
168 				case TT_NUMBER:		aColor = Color(204,102,204); break;
169 				case TT_STRING:		aColor = Color(0,255,45); break;
170 				case TT_OPERATOR:	aColor = Color(0,0,100); break;
171 				case TT_KEYWORDS:	aColor = Color(0,0,255); break;
172 				case TT_ERROR :		aColor = Color(0,255,255); break;
173 				default:			aColor = Color(0,0,0);
174 			}
175 			break;
176 		}
177 		default: aColor = Color(0,0,0);
178 
179 	}
180 	return aColor;
181 }
182 
183 void MultiLineEditSyntaxHighlight::UpdateData()
184 {
185 	// syntax highlighting
186 	// this must be possible improved by using notifychange correctly
187 	sal_Bool bTempModified = GetTextEngine()->IsModified();
188 	for (unsigned int nLine=0; nLine < GetTextEngine()->GetParagraphCount(); nLine++)
189 	{
190 		String aLine( GetTextEngine()->GetText( nLine ) );
191 		Range aChanges = aHighlighter.notifyChange( nLine, 0, &aLine, 1 );
192 
193 		GetTextEngine()->RemoveAttribs( nLine, sal_True );
194 		HighlightPortions aPortions;
195 		aHighlighter.getHighlightPortions( nLine, aLine, aPortions );
196 		for ( size_t i = 0; i < aPortions.size(); i++ )
197 		{
198 			HighlightPortion& r = aPortions[i];
199 			GetTextEngine()->SetAttrib( TextAttribFontColor( GetColorValue(r.tokenType) ), nLine, r.nBegin, r.nEnd, sal_True );
200 		}
201 	}
202 	GetTextView()->ShowCursor( false, true );
203 	GetTextEngine()->SetModified(bTempModified);
204 }
205