xml-copy-editor-code/src/xmlctrl.cpp

2218 lines
68 KiB
C++
Raw Normal View History

/*
* Copyright 2005-2007 Gerald Schmidt.
*
* This file is part of Xml Copy Editor.
*
* Xml Copy Editor 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; version 2 of the License.
*
* Xml Copy Editor 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 Xml Copy Editor; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
2007-09-07 23:17:30 +02:00
#include "xmlctrl.h"
#include "xmlpromptgenerator.h"
#include "xmlshallowvalidator.h"
#include "xmlencodinghandler.h"
#include <utility>
// adapted from wxSTEdit (c) 2005 John Labenski, Otto Wyss
#define XMLCTRL_HASBIT(value, bit) (((value) & (bit)) != 0)
2007-09-08 00:25:30 +02:00
BEGIN_EVENT_TABLE ( XmlCtrl, wxStyledTextCtrl )
EVT_CHAR ( XmlCtrl::OnChar )
EVT_KEY_DOWN ( XmlCtrl::OnKeyPressed )
EVT_IDLE ( XmlCtrl::OnIdle )
EVT_STC_MARGINCLICK ( wxID_ANY, XmlCtrl::OnMarginClick )
EVT_LEFT_DOWN ( XmlCtrl::OnMouseLeftDown )
EVT_LEFT_UP ( XmlCtrl::OnMouseLeftUp )
EVT_RIGHT_UP ( XmlCtrl::OnMouseRightUp )
EVT_MIDDLE_DOWN ( XmlCtrl::OnMiddleDown )
2007-09-07 23:17:30 +02:00
END_EVENT_TABLE()
2007-09-08 00:25:30 +02:00
XmlCtrl::XmlCtrl (
wxWindow *parent,
XmlCtrlProperties propertiesParameter,
bool *protectTagsParameter,
int visibilityStateParameter,
int typeParameter,
wxWindowID id,
const char *buffer, // could be NULL
size_t bufferLen,
const std::string& catalogPathParameter,
const std::string& basePathParameter,
const std::string& auxPathParameter,
const wxPoint& position,
const wxSize& size,
long style ) : wxStyledTextCtrl ( parent, id, position, size, style ),
type ( typeParameter ),
protectTags ( protectTagsParameter ),
visibilityState ( visibilityStateParameter ),
catalogPath ( catalogPathParameter ),
basePath ( basePathParameter ),
auxPath ( auxPathParameter )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
SetEOLMode ( wxSTC_EOL_LF );
SetPasteConvertEndings ( true ); // essential to avoid double-spaced paste
currentMaxLine = 1;
validationRequired = dtdFound = false;
applyProperties ( propertiesParameter );
SetTabWidth ( 2 );
SetWrapStartIndent ( 2 );
SetWrapVisualFlags ( wxSTC_WRAPVISUALFLAG_START );
SetUseTabs ( false );
SetBackSpaceUnIndents ( true );
SetTabIndents ( false );
SetUndoCollection ( false );
// handle NULL buffer
if ( !buffer )
{
buffer = DEFAULT_XML_DECLARATION_UTF8;
bufferLen = strlen ( DEFAULT_XML_DECLARATION_UTF8 );
}
SendMsg ( 2001, bufferLen, ( long ) ( const char * ) buffer );
SetSelection ( 0, 0 );
// position cursor
if ( type == FILE_TYPE_XML &&
bufferLen > 5 &&
buffer[0] == '<' &&
buffer[1] == '?' &&
buffer[2] == 'x' &&
buffer[3] == 'm' &&
buffer[4] == 'l' &&
GetLineCount() > 1 )
{
GotoLine ( 1 ); // == line 2 of the document
}
SetSavePoint();
SetUndoCollection ( true );
AutoCompSetSeparator ( '<' );
applyVisibilityState ( visibilityState );
lineBackgroundState = BACKGROUND_STATE_NORMAL;
for ( int i = 0; i < wxSTC_INDIC_MAX; ++i ) // start from 1 to disable faulty default indication
IndicatorSetStyle ( i, wxSTC_INDIC_HIDDEN );
IndicatorSetStyle ( 2, wxSTC_INDIC_SQUIGGLE );
IndicatorSetForeground ( 0, *wxRED );
2007-09-07 23:17:30 +02:00
}
// taken from wxStyledNotebook (c) Eran Ifrah <eranif@bezeqint.net>
2007-09-08 00:25:30 +02:00
static wxColor LightColour ( const wxColour& color, int percent )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int rd, gd, bd, high = 0;
wxColor end_color = wxT ( "WHITE" );
rd = end_color.Red() - color.Red();
gd = end_color.Green() - color.Green();
bd = end_color.Blue() - color.Blue();
high = 100;
// We take the percent way of the color from color --> white
int i = percent;
int r = color.Red() + ( ( i*rd*100 ) /high ) /100;
int g = color.Green() + ( ( i*gd*100 ) /high ) /100;
int b = color.Blue() + ( ( i*bd*100 ) /high ) /100;
return wxColor ( r, g, b );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::OnIdle ( wxIdleEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( properties.number && type != FILE_TYPE_BINARY )
adjustNoColumnWidth();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::OnChar ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( *protectTags )
{
SetOvertype ( false );
if ( GetSelectionStart() != GetSelectionEnd() )
adjustSelection();
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosRight();
}
if ( ( !properties.completion || GetOvertype() ) &&
!*protectTags )
{
event.Skip();
return;
}
switch ( event.GetKeyCode() )
{
2007-09-07 23:17:30 +02:00
case '<':
2007-09-08 00:25:30 +02:00
handleOpenAngleBracket ( event );
return;
2007-09-07 23:17:30 +02:00
case '>':
2007-09-08 00:25:30 +02:00
handleCloseAngleBracket ( event );
return;
2007-09-07 23:17:30 +02:00
case ' ':
2007-09-08 00:25:30 +02:00
handleSpace ( event );
return;
2007-09-07 23:17:30 +02:00
case '=':
2007-09-08 00:25:30 +02:00
handleEquals ( event );
return;
2007-09-07 23:17:30 +02:00
case '&':
2007-09-08 00:25:30 +02:00
handleAmpersand ( event );
return;
2007-09-07 23:17:30 +02:00
case '/':
2007-09-08 00:25:30 +02:00
handleForwardSlash ( event );
return;
2007-09-07 23:17:30 +02:00
default:
2007-09-08 00:25:30 +02:00
break;
}
event.Skip();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::handleBackspace ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
protectHeadLine();
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
validationRequired = true;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( canMoveLeftAt ( GetCurrentPos() ) )
2007-09-07 23:17:30 +02:00
{
event.Skip();
return;
}
int currentPos, limitPos;
2007-09-08 00:25:30 +02:00
currentPos = GetCurrentPos();
if ( currentPos < 1 )
2007-09-07 23:17:30 +02:00
return;
2007-09-08 00:25:30 +02:00
limitPos = currentPos - 1;
// tag
int limitStyle = getLexerStyleAt ( limitPos );
//limitStyle &= ~wxSTC_INDIC2_MASK;
if ( GetCharAt ( limitPos ) == '>' &&
( limitStyle == wxSTC_H_TAG ||
limitStyle == wxSTC_H_TAGUNKNOWN ||
limitStyle == wxSTC_H_TAGEND ||
limitStyle == wxSTC_H_XMLSTART ||
limitStyle == wxSTC_H_XMLEND ) )
{
if ( GetSelectionStart() != GetSelectionEnd() )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( *protectTags )
adjustSelection();
else
event.Skip();
return;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
if ( !properties.deleteWholeTag )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( ! ( *protectTags ) )
event.Skip();
2007-09-07 23:17:30 +02:00
return;
}
2007-09-08 00:25:30 +02:00
// delete tag to left of caret
for ( ;
limitPos &&
GetCharAt ( limitPos ) != '<';
limitPos-- )
;
SetSelection ( currentPos, limitPos );//(limitPos, currentPos);
if ( *protectTags )
{
SetReadOnly ( true ); // needed to prevent erroneous BS insertion by control
int ret =
wxMessageBox ( _ ( "Delete tag?" ),
_ ( "Tags Locked" ),
wxOK | wxCANCEL | wxICON_QUESTION );
SetReadOnly ( false );
if ( ret != wxOK )
{
return;
}
// ensure selection is set correctly
if ( GetSelectionStart() != currentPos || GetSelectionEnd() != limitPos )
SetSelection ( currentPos, limitPos );
}
2007-09-07 23:17:30 +02:00
DeleteBack();
return;
}
2007-09-08 00:25:30 +02:00
// entity reference
else if ( GetCharAt ( limitPos ) == ';' && getLexerStyleAt ( limitPos ) == wxSTC_H_ENTITY )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
// delete entity to left of caret
for ( ;
limitPos &&
getLexerStyleAt ( limitPos ) == wxSTC_H_ENTITY &&
GetCharAt ( limitPos ) != '&';
limitPos-- )
;
SetSelection ( limitPos, currentPos );
if ( *protectTags )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
SetReadOnly ( true ); // needed to prevent erroneous BS insertion by control
int ret =
wxMessageBox ( _ ( "Delete entity reference?" ),
_ ( "Tags Locked" ),
wxOK | wxCANCEL | wxICON_QUESTION );
SetReadOnly ( false );
if ( ret != wxOK )
return;
// ensure selection is set correctly
if ( GetSelectionStart() != currentPos || GetSelectionEnd() != limitPos )
SetSelection ( currentPos, limitPos );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
DeleteBack();
return;
}
else if ( *protectTags )
{
return;
}
event.Skip();
}
void XmlCtrl::handleDelete ( wxKeyEvent& event )
{
protectHeadLine();
validationRequired = true;
// unindent range
int start, end, startLine, endLine;
start = GetSelectionStart();
end = GetSelectionEnd();
startLine = LineFromPosition ( start );
endLine = LineFromPosition ( end );
if ( startLine != endLine )
{
if ( startLine > endLine )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int temp;
temp = startLine;
startLine = endLine;
endLine = temp;
temp = start;
start = end;
end = temp;
}
if ( GetColumn ( start ) < GetLineIndentation ( startLine ) &&
GetColumn ( end ) < GetLineIndentation ( endLine ) )
{
for ( int i = startLine; i <= endLine; i++ )
{
int current = GetLineIndentation ( i );
if ( current > 0 )
SetLineIndentation ( i, current - 1 );
}
2007-09-07 23:17:30 +02:00
return;
}
}
2007-09-08 00:25:30 +02:00
if ( !canMoveRightAt ( GetCurrentPos() ) &&
GetSelectionStart() == GetSelectionEnd() )
{
int currentPos, limitPos;
limitPos = currentPos = GetCurrentPos();
// tag
int limitStyle = getLexerStyleAt ( limitPos );
if ( GetCharAt ( limitPos ) == '<' &&
( limitStyle == wxSTC_H_TAG ||
limitStyle == wxSTC_H_TAGUNKNOWN ||
limitStyle == wxSTC_H_TAGEND ||
limitStyle == wxSTC_H_XMLSTART ||
limitStyle == wxSTC_H_XMLEND
) )
{
if ( GetSelectionStart() != GetSelectionEnd() )
{
if ( *protectTags )
adjustSelection();
else
event.Skip();
return;
}
if ( !properties.deleteWholeTag )
{
if ( ! ( *protectTags ) )
event.Skip();
return;
}
for ( ;
GetCharAt ( limitPos ) != '>' && limitPos < GetLength();
limitPos++ )
{
if ( limitPos > ( currentPos + BUFSIZ ) )
{
event.Skip();
return;
}
}
if ( currentPos != limitPos )
{
SetSelection ( currentPos, limitPos + 1 );
if ( *protectTags )
{
int ret =
wxMessageBox ( _ ( "Delete tag?" ),
_ ( "Tags Locked" ),
wxOK | wxCANCEL | wxICON_QUESTION );
if ( ret != wxOK )
return;
}
DeleteBack();
return;
}
}
// entity
else if ( GetCharAt ( limitPos ) == '&' && getLexerStyleAt ( limitPos ) == wxSTC_H_ENTITY )
{
for ( ;
getLexerStyleAt ( limitPos ) == wxSTC_H_ENTITY && limitPos <= GetLength();
limitPos++ )
{
if ( GetCharAt ( limitPos ) == ';' )
break;
else if ( GetCharAt ( limitPos ) == '\n' || limitPos > ( currentPos + BUFSIZ ) )
{
event.Skip();
return;
}
}
if ( currentPos != limitPos )
{
SetSelection ( currentPos, limitPos + 1 );
if ( *protectTags )
{
int ret =
wxMessageBox ( _ ( "Delete entity reference?" ),
_ ( "Tags Locked" ),
wxOK | wxCANCEL | wxICON_QUESTION );
if ( ret != wxOK )
return;
}
DeleteBack();
return;
}
}
else if ( *protectTags )
return;
}
event.Skip();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::handleOpenAngleBracket ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( AutoCompActive() )
AutoCompCancel();
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( *protectTags )
{
AddText ( _T ( "&lt;" ) );
return;
}
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
validationRequired = true;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
AddText ( _T ( "<" ) );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
int pos = GetCurrentPos();
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
// exit conditions based on style
int style = getLexerStyleAt ( pos );
//style &= ~wxSTC_INDIC2_MASK;
switch ( style )
{
2007-09-07 23:17:30 +02:00
case wxSTC_H_DOUBLESTRING:
case wxSTC_H_SINGLESTRING:
2007-09-08 00:25:30 +02:00
return;
2007-09-07 23:17:30 +02:00
default:
2007-09-08 00:25:30 +02:00
break;
}
// determine parent element
int parentCloseAngleBracket;
parentCloseAngleBracket = getParentCloseAngleBracket ( pos );
if ( parentCloseAngleBracket < 0 )
return;
wxString wideParent = getLastElementName ( parentCloseAngleBracket );
if ( wideParent.empty() )
return;
std::string parent = ( const char * ) wideParent.mb_str ( wxConvUTF8 );
if ( elementMap.find ( parent ) == elementMap.end() )
return;
wxString choice, conversion;
std::set<std::string> childSet = elementMap[parent];
std::set<std::string>::iterator it;
for ( it = childSet.begin(); it != childSet.end(); it++ )
{
if ( !choice.empty() )
choice.append ( _T ( "<" ) );
conversion = wxString ( it->c_str(), wxConvUTF8, it->size() );
choice.append ( conversion );
}
if ( !choice.empty() )
UserListShow ( 0, choice );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::handleCloseAngleBracket ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( AutoCompActive() )
AutoCompCancel();
if ( *protectTags )
{
AddText ( _T ( "&gt;" ) );
return;
}
validationRequired = true;
wxString insertBuffer;
int pos;
pos = GetCurrentPos();
wxString elementName = getLastElementName ( pos );
if ( !elementName.empty() )
{
std::map<std::string, std::set<std::string> > map;
std::string elementNameUtf8 = ( const char * ) elementName.mb_str ( wxConvUTF8 );
attributeMap.insert ( make_pair ( elementNameUtf8, map ) );
}
// exit condition 1
if ( pos <= 1 )
{
event.Skip();
return;
}
// exit condition 2 (empty tag/end of CDATA section)
else if ( GetCharAt ( pos - 1 ) == '/' ||
GetCharAt ( pos - 1 ) == ']' )
{
event.Skip();
return;
}
// exit condition 3 (comment/CDATA)
else if ( getLexerStyleAt ( pos - 1 ) == wxSTC_H_COMMENT ||
getLexerStyleAt ( pos - 1 ) == wxSTC_H_CDATA ||
( getLexerStyleAt ( pos - 1 ) == wxSTC_H_DOUBLESTRING && ( GetCharAt ( pos - 1 ) != '"' ) ) ||
( getLexerStyleAt ( pos - 1 ) == wxSTC_H_SINGLESTRING && ( GetCharAt ( pos - 1 ) != '\'' ) ) )
{
event.Skip();
return;
}
if ( !elementName.empty() )
{
if ( !properties.insertCloseTag )
{
event.Skip();
return;
}
AddText ( _T ( ">" ) );
insertBuffer += _T ( "</" );
insertBuffer += elementName;
insertBuffer += _T ( ">" );
InsertText ( pos + 1, insertBuffer );
SetSelection ( pos + 1, pos + 1 );
}
else
event.Skip();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::handleEquals ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( AutoCompActive() )
AutoCompCancel();
wxString choice, elementName, attributeName, conversion;
std::string elementNameUtf8, attributeNameUtf8;
int pos = GetCurrentPos();
if ( pos <= 0 || getLexerStyleAt ( pos - 1 ) != wxSTC_H_ATTRIBUTE )
{
event.Skip();
return;
}
AddText ( _T ( "=\"\"" ) );
SetSelection ( pos + 2, pos + 2 );
// tbd: identify possible attribute values
elementName = getLastElementName ( pos );
attributeName = getLastAttributeName ( pos );
elementNameUtf8 = elementName.mb_str ( wxConvUTF8 );
attributeNameUtf8 = attributeName.mb_str ( wxConvUTF8 );
std::set<std::string> valueSet;
valueSet = attributeMap[elementNameUtf8][attributeNameUtf8];
if ( valueSet.empty() )
return;
std::set<std::string>::iterator valueSetIterator;
int cutoff = BUFSIZ;
for ( valueSetIterator = valueSet.begin();
valueSetIterator != valueSet.end();
valueSetIterator++ )
{
if ( ! ( cutoff-- ) )
break;
if ( !choice.empty() )
choice.Append ( _T ( "<" ) );
conversion = wxString (
valueSetIterator->c_str(),
wxConvUTF8,
valueSetIterator->size() );
choice.Append ( conversion );
}
if ( !choice.empty() )
UserListShow ( 0, choice );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::handleSpace ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( AutoCompActive() )
AutoCompCancel();
wxString elementName, choice, conversion;
std::string elementNameUtf8;
int pos = GetCurrentPos();
std::map<std::string, std::set<std::string> > currentAttributeMap;
std::map<std::string, std::set<std::string> >::iterator
attributeIterator;
if ( pos <= 2 )
{
event.Skip();
return;
}
int style = getLexerStyleAt ( pos - 1 );
//style &= ~wxSTC_INDIC2_MASK;
char c = GetCharAt ( pos - 1 );
bool proceed = false;
// space pressed after element name
if (
style == wxSTC_H_TAG ||
style == wxSTC_H_TAGUNKNOWN ||
style == wxSTC_H_ATTRIBUTEUNKNOWN ||
style == wxSTC_H_ATTRIBUTE )
{
proceed = true;
}
// space pressed after attribute value
else if (
( style == wxSTC_H_DOUBLESTRING ||
style == wxSTC_H_SINGLESTRING ) &&
( c == '\'' || c == '"' ) &&
GetCharAt ( pos - 2 ) != '=' )
{
proceed = true;
}
int tagStartPos = getTagStartPos ( pos );
if ( !proceed || tagStartPos == -1 )
{
event.Skip();
return;
}
AddText ( _T ( " " ) );
elementName = getLastElementName ( pos );
wxString tag = GetTextRange ( tagStartPos, pos );
elementNameUtf8 = elementName.mb_str ( wxConvUTF8 );
if ( attributeMap.find ( elementNameUtf8 ) == attributeMap.end() )
return;
currentAttributeMap = attributeMap[elementNameUtf8];
for (
attributeIterator = currentAttributeMap.begin();
attributeIterator != currentAttributeMap.end();
attributeIterator++ )
{
conversion = wxString (
attributeIterator->first.c_str(),
wxConvUTF8,
attributeIterator->first.size() );
// avoid duplicate attributes
if ( tag.Contains ( conversion + _T ( "=" ) ) )
continue;
if ( !choice.empty() )
choice.Append ( _T ( "<" ) );
choice.Append ( conversion );
}
if ( !choice.empty() )
UserListShow ( 0, choice );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::handleAmpersand ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( AutoCompActive() )
AutoCompCancel();
validationRequired = true;
if ( *protectTags )
{
AddText ( _T ( "&amp;" ) );
return;
}
int pos, style;
pos = GetCurrentPos();
style = getLexerStyleAt ( pos );
if ( style != wxSTC_H_COMMENT &&
style != wxSTC_H_CDATA &&
style != wxSTC_H_TAGUNKNOWN &&
entitySet.size() >= 4 ) // min. 4 default entities
{
AddText ( _T ( "&" ) );
wxString choice;
std::set<std::string>::iterator it;
it = entitySet.begin();
choice += wxString ( it->c_str(), wxConvUTF8, it->size() );
choice += _T ( ";" );
for ( it++; it != entitySet.end(); it++ )
{
choice += _T ( "<" );
choice += wxString ( it->c_str(), wxConvUTF8, it->size() );
choice += _T ( ";" );
}
UserListShow ( 0, choice );
}
else
event.Skip();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::handleForwardSlash ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( AutoCompActive() )
AutoCompCancel();
int pos = GetCurrentPos();
if (
( pos <= 0 ) ||
GetCharAt ( pos - 1 ) != '<' ||
getLexerStyleAt ( pos ) == wxSTC_H_COMMENT ||
getLexerStyleAt ( pos ) == wxSTC_H_CDATA )
{
event.Skip();
return;
}
AddText ( _T ( "/" ) );
int parentCloseAngleBracket = getParentCloseAngleBracket ( pos );
if ( parentCloseAngleBracket < 0 )
return;
wxString wideParent = getLastElementName ( parentCloseAngleBracket );
if ( wideParent.empty() )
return;
AddText ( wideParent + _T ( ">" ) );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::OnKeyPressed ( wxKeyEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( *protectTags && GetSelectionStart() != GetSelectionEnd() )
{
adjustSelection();
}
if ( *protectTags )
SetOvertype ( false );
//bool autoindent;
int pos, iteratorPos, maxPos; // omitted startPos, line, newPos
char c;
wxString s;
switch ( event.GetKeyCode() )
{
2007-09-07 23:17:30 +02:00
case WXK_RETURN:
2007-09-08 00:25:30 +02:00
if ( AutoCompActive() )
{
AutoCompComplete();
return;
}
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( *protectTags )
adjustPosRight();
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
insertNewLine();
2007-09-07 23:17:30 +02:00
return;
2007-09-08 00:25:30 +02:00
case WXK_RIGHT:
pos = GetCurrentPos();
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( *protectTags && !canMoveRightAt ( pos ) )
{
SetSelection ( pos + 1, pos + 1 );
adjustPosRight();
return;
}
maxPos = GetLength();
c = GetCharAt ( pos );
if ( c == '<' && event.ControlDown() && !event.ShiftDown() )
{
for (
iteratorPos = pos;
iteratorPos < maxPos &&
GetCharAt ( iteratorPos ) != ' ' &&
GetCharAt ( iteratorPos ) != '>' &&
GetCharAt ( iteratorPos ) != '\n';
++iteratorPos )
;
++iteratorPos;
SetSelection ( iteratorPos, iteratorPos );
return;
}
else
break;
2007-09-07 23:17:30 +02:00
case WXK_LEFT:
2007-09-08 00:25:30 +02:00
pos = GetCurrentPos();
if ( *protectTags && !canMoveLeftAt ( pos ) )
{
adjustPosLeft();
return;
}
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( pos < 3 )
break;
c = GetCharAt ( pos - 1 );
if ( c == '>' && event.ControlDown() && !event.ShiftDown() )
{
for (
iteratorPos = pos - 1;
iteratorPos > 0 &&
GetCharAt ( iteratorPos ) != '<' &&
GetCharAt ( iteratorPos ) != ' ' &&
GetCharAt ( iteratorPos ) != '=' &&
GetCharAt ( iteratorPos ) != '\n';
--iteratorPos )
;
if (
GetCharAt ( iteratorPos ) != '<' &&
GetCharAt ( iteratorPos ) != '=' )
++iteratorPos;
SetSelection ( iteratorPos, iteratorPos );
return;
}
else
break;
2007-09-07 23:17:30 +02:00
case WXK_UP:
2007-09-08 00:25:30 +02:00
if ( *protectTags )
{
LineUp();
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosLeft();
return;
}
break;
2007-09-07 23:17:30 +02:00
case WXK_DOWN:
2007-09-08 00:25:30 +02:00
if ( *protectTags )
{
LineDown();
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosRight();
return;
}
break;
2007-09-07 23:17:30 +02:00
case WXK_INSERT:
2007-09-08 00:25:30 +02:00
if ( *protectTags )
return;
break;
2007-09-07 23:17:30 +02:00
case WXK_BACK:
2007-09-08 00:25:30 +02:00
handleBackspace ( event );
return;
2007-09-07 23:17:30 +02:00
case WXK_TAB:
2007-09-08 00:25:30 +02:00
if ( *protectTags )
{
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosRight();
}
break;
2007-09-07 23:17:30 +02:00
case WXK_HOME:
2007-09-08 00:25:30 +02:00
if ( *protectTags && !event.ControlDown() && !event.ShiftDown() )
{
Home();
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosLeft();
return;
}
break;
2007-09-07 23:17:30 +02:00
case WXK_END:
2007-09-08 00:25:30 +02:00
if ( *protectTags && !event.ControlDown() && !event.ShiftDown() )
{
LineEnd();
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosRight();
return;
}
break;
2007-09-07 23:17:30 +02:00
case WXK_PAGEUP:
2007-09-08 00:25:30 +02:00
if ( *protectTags )
{
PageUp();
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosLeft();
return;
}
break;
2007-09-07 23:17:30 +02:00
case WXK_PAGEDOWN:
2007-09-08 00:25:30 +02:00
if ( *protectTags )
{
PageDown();
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosRight();
return;
}
break;
2007-09-07 23:17:30 +02:00
case WXK_DELETE:
2007-09-08 00:25:30 +02:00
handleDelete ( event );
return;
2007-09-07 23:17:30 +02:00
default:
2007-09-08 00:25:30 +02:00
break;
}
event.Skip();
}
wxString XmlCtrl::getLastElementName ( int pos )
{
if ( pos < 1 )
return _T ( "" );
int startPos, iteratorPos;
for ( startPos = pos - 1; startPos >= 0; --startPos )
{
char c = GetCharAt ( startPos );
if ( c == '>' )
return _T ( "" );
else if ( c == '<' )
break;
}
// exit if not found or closing/declaration/command tag
if ( GetCharAt ( startPos ) != '<' ||
GetCharAt ( startPos + 1 ) == '/' ||
GetCharAt ( startPos + 1 ) == '?' ||
GetCharAt ( startPos + 1 ) == '!' )
return _T ( "" );
++startPos;
for ( iteratorPos = startPos;
iteratorPos < pos &&
GetCharAt ( iteratorPos ) != ' ' &&
GetCharAt ( iteratorPos ) != '\n' &&
GetCharAt ( iteratorPos ) != '\t' &&
GetCharAt ( iteratorPos ) != '/' &&
GetCharAt ( iteratorPos ) != '>';
++iteratorPos )
;
if ( startPos == iteratorPos )
return _T ( "" );
return GetTextRange ( startPos, iteratorPos );
}
std::set<wxString> XmlCtrl::getChildren ( const wxString& parent )
{
std::string parentUtf8 = ( const char * ) parent.mb_str ( wxConvUTF8 );
std::set<wxString> mySet;
if ( elementMap.find ( parentUtf8 ) == elementMap.end() )
return mySet;
std::set<std::string> myUtf8Set = elementMap[parentUtf8];
std::string currentUtf8;
wxString currentWide;
std::set<std::string>::iterator it;
for ( it = myUtf8Set.begin(); it != myUtf8Set.end(); it++ )
{
currentUtf8 = *it;
currentWide = wxString ( currentUtf8.c_str(), wxConvUTF8, currentUtf8.size() );
mySet.insert ( currentWide );
}
return mySet;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
wxString XmlCtrl::getLastAttributeName ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( pos < 1 )
return _T ( "" );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
int startPos;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
for ( startPos = pos - 1; startPos >= 0; --startPos )
{
char c = GetCharAt ( startPos );
if ( c == ' ' || c == '<' )
break;
}
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( GetCharAt ( startPos ) != ' ' ||
startPos >= pos - 1 )
return _T ( "" );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
return GetTextRange ( startPos + 1, pos );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
int XmlCtrl::getParentCloseAngleBracket ( int pos, int range )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int cutoff, iteratorPos, depth;
cutoff = ( ( pos - range ) > 2 ) ? pos - range : 2;
depth = 1;
for (
iteratorPos = pos;
iteratorPos > cutoff;
--iteratorPos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int type, style;
style = getLexerStyleAt ( iteratorPos );
//style &= ~wxSTC_INDIC2_MASK;
if ( GetCharAt ( iteratorPos ) == '>' &&
( style == wxSTC_H_TAG ||
style == wxSTC_H_TAGUNKNOWN ) )
{
type = getTagType ( iteratorPos );
switch ( type )
{
case ( TAG_TYPE_CLOSE ) :
++depth;
break;
case ( TAG_TYPE_OPEN ) :
--depth;
break;
case ( TAG_TYPE_EMPTY ) :
case ( TAG_TYPE_OTHER ) :
case ( TAG_TYPE_ERROR ) :
break;
}
//(isCloseTag(iteratorPos)) ? ++depth : --depth;
if ( !depth )
return iteratorPos;
}
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
return -1;
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::adjustNoColumnWidth()
{
2007-09-08 00:25:30 +02:00
int maxLine = GetLineCount();
if ( maxLine == currentMaxLine )
return;
int digits, charWidth, width;
digits = 0;
do
{
++digits;
maxLine /= 10;
}
while ( maxLine );
digits = ( digits > 2 ) ? digits : 2;
charWidth = TextWidth ( wxSTC_STYLE_LINENUMBER, _T ( "9" ) );
width = ( digits + 2 ) * charWidth;
SetMarginWidth ( 0, width );
currentMaxLine = maxLine;
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::updatePromptMaps()
{
2007-09-08 00:25:30 +02:00
wxString buffer = GetText();
std::string bufferUtf8;
bufferUtf8 = ( const char * ) buffer.mb_str ( wxConvUTF8 );
XmlEncodingHandler::setUtf8 ( bufferUtf8, true );
updatePromptMaps ( bufferUtf8.c_str(), bufferUtf8.size() );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::updatePromptMaps ( const char *buffer, size_t bufferLen )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
attributeMap.clear();
elementMap.clear();
std::auto_ptr<XmlPromptGenerator> xpg ( new XmlPromptGenerator (
catalogPath,
basePath,
auxPath ) );
xpg->parse ( buffer, bufferLen );
xpg->getAttributeMap ( attributeMap );
xpg->getRequiredAttributeMap ( requiredAttributeMap );
xpg->getElementMap ( elementMap );
xpg->getEntitySet ( entitySet );
dtdFound = xpg->getDtdFound();
entitySet.insert ( "apos" );
entitySet.insert ( "quot" );
entitySet.insert ( "lt" );
entitySet.insert ( "gt" );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::applyProperties (
XmlCtrlProperties propertiesParameter,
bool zoomOnly )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
properties = propertiesParameter;
SetZoom ( ( type != FILE_TYPE_BINARY ) ? properties.zoom : 0 );
if ( zoomOnly )
return;
SetCaretLineVisible ( properties.currentLine );
SetIndentationGuides (
( type != FILE_TYPE_BINARY ) ? properties.indentLines : false );
SetWrapMode ( ( type != FILE_TYPE_BINARY ) ? properties.wrap : false );
SetViewWhiteSpace (
( properties.whitespaceVisible ) ?
wxSTC_WS_VISIBLEAFTERINDENT : wxSTC_WS_INVISIBLE );
switch ( type )
{
2007-09-07 23:17:30 +02:00
case FILE_TYPE_BINARY:
2007-09-08 00:25:30 +02:00
SetLexer ( wxSTC_LEX_NULL );
break;
2007-09-07 23:17:30 +02:00
case FILE_TYPE_CSS:
2007-09-08 00:25:30 +02:00
SetLexer ( wxSTC_LEX_CSS );
break;
2007-09-07 23:17:30 +02:00
default:
2007-09-08 00:25:30 +02:00
SetLexer ( wxSTC_LEX_XML );
break;
}
setColorScheme (
( type != FILE_TYPE_BINARY ) ? properties.colorScheme : COLOR_SCHEME_NONE );
// line no margin
if ( properties.number ) // permit line nos for large files
{
SetMarginType ( 0, wxSTC_MARGIN_NUMBER ); // width set at idle time
adjustNoColumnWidth();
}
else
SetMarginWidth ( 0, 0 );
SetMarginWidth ( 1, 0 );
if ( properties.fold && type != FILE_TYPE_BINARY )
{
// folding margin
SetMarginType ( 2, wxSTC_MARGIN_SYMBOL );
SetMarginMask ( 2, wxSTC_MASK_FOLDERS );
SetMarginSensitive ( 2, true );
SetMarginWidth ( 2, 16 );
// define folding markers
MarkerDefine ( wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUSCONNECTED, *wxWHITE, *wxBLACK );
MarkerDefine ( wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUSCONNECTED, *wxWHITE, *wxBLACK );
MarkerDefine ( wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_TCORNER, *wxWHITE, *wxBLACK );
MarkerDefine ( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_LCORNER, *wxWHITE, *wxBLACK );
MarkerDefine ( wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_VLINE, *wxWHITE, *wxBLACK );
MarkerDefine ( wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS, *wxWHITE, *wxBLACK );
MarkerDefine ( wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS, *wxWHITE, *wxBLACK );
}
else
{
SetMarginWidth ( 2, 0 );
}
if ( type != FILE_TYPE_BINARY )
{
Colourise ( 0, -1 );
}
wxString value = ( properties.fold && type != FILE_TYPE_BINARY ) ? _T ( "1" ) : _T ( "0" );
SetProperty ( _T ( "fold" ), value );
SetProperty ( _T ( "fold.compact" ), value );
SetProperty ( _T ( "fold.html" ), value );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::OnMarginClick ( wxStyledTextEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
const int line = LineFromPosition ( event.GetPosition() );
const int margin = event.GetMargin();
// let others process this first
if ( GetParent()->GetEventHandler()->ProcessEvent ( event ) )
return;
if ( margin == 2 )
{
const int level = GetFoldLevel ( line );
if ( ( ( level ) & ( wxSTC_FOLDLEVELHEADERFLAG ) ) != 0 )
ToggleFold ( line );
}
else
event.Skip();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::OnMouseLeftDown ( wxMouseEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
SetMouseDownCaptures ( !*protectTags );
event.Skip();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::OnMouseLeftUp ( wxMouseEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
event.Skip();
if ( *protectTags && !canInsertAt ( GetCurrentPos() ) )
adjustPosRight();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::OnMouseRightUp ( wxMouseEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( *protectTags )
return;
event.Skip();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
bool XmlCtrl::isCloseTag ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int iteratorPos;
for ( iteratorPos = pos; iteratorPos >= 0; --iteratorPos )
{
if ( GetCharAt ( iteratorPos ) == '<' && getLexerStyleAt ( iteratorPos ) == wxSTC_H_TAG )
return ( GetCharAt ( iteratorPos + 1 ) == '/' ) ? true : false;
}
return false;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
int XmlCtrl::getTagStartPos ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int iteratorPos;
for ( iteratorPos = pos; iteratorPos >= 0; --iteratorPos )
{
if ( GetCharAt ( iteratorPos ) == '<' && getLexerStyleAt ( iteratorPos ) == wxSTC_H_TAG )
return iteratorPos;
}
return -1;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
int XmlCtrl::getAttributeStartPos ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int iteratorPos;
char c;
bool attributeSeen = false;
for ( iteratorPos = pos; iteratorPos > 0; iteratorPos-- )
{
c = GetCharAt ( iteratorPos );
if ( ( getLexerStyleAt ( iteratorPos ) ) == wxSTC_H_ATTRIBUTE )
attributeSeen = true;
else if ( ( c == ' ' || c == '\t' || c == '\n' ) && attributeSeen )
return iteratorPos;
}
return -1;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
int XmlCtrl::getAttributeSectionEndPos ( int pos, int range )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int iteratorPos, limit, style;
limit = pos + range;
for ( iteratorPos = pos; iteratorPos < limit; iteratorPos++ )
{
style = getLexerStyleAt ( iteratorPos );
switch ( style )
{
case wxSTC_H_TAG:
case wxSTC_H_TAGEND:
case wxSTC_H_XMLEND:
case wxSTC_H_QUESTION:
return iteratorPos;
default:
continue;
}
}
return -1;
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::adjustCursor()
{
2007-09-08 00:25:30 +02:00
if ( !canInsertAt ( GetCurrentPos() ) )
adjustPosRight();
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
bool XmlCtrl::canInsertAt ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( pos < 0 )
return false;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
int style = getLexerStyleAt ( pos );
//style &= ~wxSTC_INDIC2_MASK;
switch ( style )
{
2007-09-07 23:17:30 +02:00
case wxSTC_H_TAG:
case wxSTC_H_TAGUNKNOWN:
case wxSTC_H_QUESTION:
case wxSTC_H_CDATA:
case wxSTC_H_COMMENT:
case wxSTC_H_SGML_DEFAULT:
2007-09-08 00:25:30 +02:00
return ( GetCharAt ( pos ) == '<' ) ? true : false;
2007-09-07 23:17:30 +02:00
case wxSTC_H_ENTITY:
2007-09-08 00:25:30 +02:00
return ( GetCharAt ( pos ) == '&' ) ? true : false;
2007-09-07 23:17:30 +02:00
case wxSTC_H_DEFAULT:
2007-09-08 00:25:30 +02:00
return true;
}
return false;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
bool XmlCtrl::canMoveRightAt ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int style = getLexerStyleAt ( pos );
//style &= ~wxSTC_INDIC2_MASK;
switch ( style )
{
2007-09-07 23:17:30 +02:00
case wxSTC_H_DEFAULT:
2007-09-08 00:25:30 +02:00
return true;
}
return false;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
bool XmlCtrl::canMoveLeftAt ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( pos < 1 )
return false;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
int style = getLexerStyleAt ( pos - 1 );
//style &= ~wxSTC_INDIC2_MASK;
switch ( style )
{
2007-09-07 23:17:30 +02:00
case wxSTC_H_DEFAULT:
2007-09-08 00:25:30 +02:00
return true;
}
return false;
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::adjustPosRight()
{
2007-09-08 00:25:30 +02:00
int pos, max;
bool canInsert = false;
pos = GetCurrentPos();
max = GetLength();
for ( ; pos <= max; pos++ )
if ( canInsertAt ( pos ) )
{
canInsert = true;
break;
}
SetSelection ( pos, pos );
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::adjustPosLeft()
{
2007-09-08 00:25:30 +02:00
int pos;
bool canInsert = false;
pos = GetCurrentPos() - 1;
if ( pos < 0 )
{
SetSelection ( 0, 0 );
return;
}
for ( ; pos > 0; pos-- )
if ( canInsertAt ( pos ) )
{
canInsert = true;
break;
}
SetSelection ( pos, pos );
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::adjustSelection()
{
2007-09-08 00:25:30 +02:00
int start, end, iterator;
start = GetSelectionStart();
end = GetSelectionEnd();
// exit condition 1
if ( start == end && canInsertAt ( start ) )
return;
// exit condition 2
else if ( !canInsertAt ( start ) || start > end )
{
SetSelection ( start, start );
return;
}
for ( iterator = start; iterator < end; iterator++ )
{
if ( !canMoveRightAt ( iterator ) )
break;
}
SetSelection ( start, iterator );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::setColorScheme ( int scheme )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
StyleSetFaceName ( wxSTC_STYLE_DEFAULT, properties.font );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
switch ( scheme )
{
2007-09-07 23:17:30 +02:00
case COLOR_SCHEME_DEFAULT:
2007-09-08 00:25:30 +02:00
StyleSetForeground ( wxSTC_STYLE_DEFAULT, *wxBLACK );
StyleSetBackground ( wxSTC_STYLE_DEFAULT, *wxWHITE );
StyleClearAll();
baseBackground = LightColour ( wxTheColourDatabase->Find ( _T ( "YELLOW" ) ), 20 );
alternateBackground = LightColour ( wxTheColourDatabase->Find ( _T ( "YELLOW" ) ), 60 );
SetCaretLineBackground ( baseBackground );
SetCaretForeground ( *wxBLACK );
SetSelBackground ( true, wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
if ( type == FILE_TYPE_CSS )
{
// CSS colours
StyleSetForeground ( wxSTC_CSS_DEFAULT, *wxBLACK );
StyleSetForeground ( wxSTC_CSS_TAG, *wxBLUE );
StyleSetForeground ( wxSTC_CSS_CLASS, *wxBLUE );
StyleSetForeground ( wxSTC_CSS_PSEUDOCLASS, *wxBLUE );
StyleSetForeground ( wxSTC_CSS_UNKNOWN_PSEUDOCLASS, *wxBLUE );
StyleSetForeground ( wxSTC_CSS_OPERATOR, *wxBLUE );
StyleSetForeground ( wxSTC_CSS_IDENTIFIER, *wxBLUE );
StyleSetForeground ( wxSTC_CSS_UNKNOWN_IDENTIFIER, *wxBLUE );
StyleSetForeground ( wxSTC_CSS_VALUE, *wxBLACK );
StyleSetForeground ( wxSTC_CSS_COMMENT,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_CSS_ID, *wxBLACK );
StyleSetForeground ( wxSTC_CSS_IMPORTANT, *wxRED );
StyleSetForeground ( wxSTC_CSS_DIRECTIVE, *wxBLUE );
StyleSetForeground ( wxSTC_CSS_DOUBLESTRING, *wxRED );
StyleSetForeground ( wxSTC_CSS_SINGLESTRING, *wxRED );
StyleSetForeground ( wxSTC_CSS_IDENTIFIER2, *wxRED );
StyleSetForeground ( wxSTC_CSS_ATTRIBUTE, *wxBLUE );
}
else // XML
{
StyleSetForeground ( wxSTC_H_DEFAULT, *wxBLACK );
StyleSetForeground ( wxSTC_H_TAG, *wxBLUE );
StyleSetForeground ( wxSTC_H_TAGUNKNOWN, *wxBLUE );
StyleSetForeground ( wxSTC_H_ATTRIBUTE, *wxRED );
StyleSetForeground ( wxSTC_H_ATTRIBUTEUNKNOWN, *wxRED );
StyleSetForeground ( wxSTC_H_NUMBER, *wxBLACK );
StyleSetForeground ( wxSTC_H_DOUBLESTRING, *wxBLACK );
StyleSetForeground ( wxSTC_H_SINGLESTRING, *wxBLACK );
StyleSetForeground ( wxSTC_H_OTHER, *wxBLUE );
StyleSetForeground ( wxSTC_H_COMMENT,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_ENTITY, *wxRED );
StyleSetForeground ( wxSTC_H_TAGEND, *wxBLUE );
StyleSetForeground ( wxSTC_H_XMLSTART,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_XMLEND,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_CDATA, *wxRED );
StyleSetForeground ( wxSTC_H_QUESTION,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
for ( int i = wxSTC_H_SGML_DEFAULT; i <= wxSTC_H_SGML_BLOCK_DEFAULT; i++ )
StyleSetForeground ( i, *wxBLUE );
StyleSetForeground ( wxSTC_H_SGML_ENTITY, *wxRED );
StyleSetForeground ( wxSTC_H_SGML_SPECIAL, *wxBLACK );
StyleSetForeground ( wxSTC_H_SGML_SIMPLESTRING, *wxRED );
StyleSetForeground ( wxSTC_H_SGML_DEFAULT,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
}
break;
2007-09-07 23:17:30 +02:00
case COLOR_SCHEME_DEFAULT_BACKGROUND:
2007-09-08 00:25:30 +02:00
StyleSetForeground ( wxSTC_STYLE_DEFAULT, *wxBLACK );
StyleSetBackground ( wxSTC_STYLE_DEFAULT, *wxWHITE );
StyleClearAll();
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
baseBackground = LightColour ( wxTheColourDatabase->Find ( _T ( "YELLOW" ) ), 20 );
alternateBackground = LightColour ( wxTheColourDatabase->Find ( _T ( "YELLOW" ) ), 60 );
SetCaretLineBackground ( baseBackground );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
SetCaretForeground ( *wxBLACK );
SetSelBackground ( true, wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( type == FILE_TYPE_CSS )
{
// CSS colours
StyleSetForeground ( wxSTC_CSS_DEFAULT, *wxBLACK );
StyleSetForeground ( wxSTC_CSS_TAG,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_CLASS,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_PSEUDOCLASS,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_UNKNOWN_PSEUDOCLASS,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_OPERATOR,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_IDENTIFIER,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_UNKNOWN_IDENTIFIER,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_VALUE, *wxBLACK );
StyleSetForeground ( wxSTC_CSS_COMMENT,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_CSS_ID, *wxBLACK );
StyleSetForeground ( wxSTC_CSS_IMPORTANT,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_CSS_DIRECTIVE,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_DOUBLESTRING,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_CSS_SINGLESTRING,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_CSS_IDENTIFIER2,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_CSS_ATTRIBUTE,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
}
else // XML
{
StyleSetForeground ( wxSTC_H_DEFAULT, *wxBLACK );
StyleSetForeground ( wxSTC_H_TAG,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_TAGUNKNOWN,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_ATTRIBUTE,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_ATTRIBUTEUNKNOWN,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_NUMBER,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_DOUBLESTRING,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_SINGLESTRING,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_OTHER,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_COMMENT,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_ENTITY,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_TAGEND,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_XMLSTART,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_XMLEND,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
StyleSetForeground ( wxSTC_H_CDATA,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_QUESTION,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
for ( int i = wxSTC_H_SGML_DEFAULT; i <= wxSTC_H_SGML_BLOCK_DEFAULT; i++ )
StyleSetForeground ( i, wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_SGML_ENTITY,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_SGML_SPECIAL, *wxBLACK );
StyleSetForeground ( wxSTC_H_SGML_SIMPLESTRING,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_SGML_DEFAULT,
wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
}
break;
2007-09-07 23:17:30 +02:00
case COLOR_SCHEME_REDUCED_GLARE:
2007-09-08 00:25:30 +02:00
StyleSetForeground ( wxSTC_STYLE_DEFAULT,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetBackground ( wxSTC_STYLE_DEFAULT,
wxTheColourDatabase->Find ( _T ( "MIDNIGHT BLUE" ) ) );
StyleClearAll();
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
baseBackground = LightColour ( wxTheColourDatabase->Find ( _T ( "NAVY" ) ), 0 );
alternateBackground = LightColour ( wxTheColourDatabase->Find ( _T ( "NAVY" ) ), 10 );
SetCaretLineBackground ( baseBackground );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
StyleSetForeground ( wxSTC_STYLE_LINENUMBER, *wxBLACK );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
SetCaretForeground ( *wxWHITE );
SetSelBackground ( true, wxTheColourDatabase->Find ( _T ( "GREY" ) ) );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( type == FILE_TYPE_CSS )
{
// CSS colours
StyleSetForeground ( wxSTC_CSS_DEFAULT,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetForeground ( wxSTC_CSS_TAG,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_CLASS,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_PSEUDOCLASS,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_UNKNOWN_PSEUDOCLASS,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_OPERATOR,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_IDENTIFIER,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_UNKNOWN_IDENTIFIER,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_VALUE, *wxWHITE );
StyleSetForeground ( wxSTC_CSS_COMMENT,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetForeground ( wxSTC_CSS_ID, *wxWHITE );
StyleSetForeground ( wxSTC_CSS_IMPORTANT,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_CSS_DIRECTIVE,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_CSS_DOUBLESTRING,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_CSS_SINGLESTRING,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_CSS_IDENTIFIER2,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_CSS_ATTRIBUTE,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
}
else // XML
{
StyleSetForeground ( wxSTC_H_DEFAULT, *wxWHITE );
StyleSetForeground ( wxSTC_H_TAG,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_TAGUNKNOWN,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_ATTRIBUTE,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_ATTRIBUTEUNKNOWN,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_NUMBER,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetForeground ( wxSTC_H_DOUBLESTRING,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetForeground ( wxSTC_H_SINGLESTRING,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetForeground ( wxSTC_H_OTHER,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_COMMENT,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetForeground ( wxSTC_H_ENTITY,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_TAGEND,
wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_XMLSTART,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetForeground ( wxSTC_H_XMLEND,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
StyleSetForeground ( wxSTC_H_CDATA,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_QUESTION,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
for ( int i = wxSTC_H_SGML_DEFAULT; i <= wxSTC_H_SGML_BLOCK_DEFAULT; i++ )
StyleSetForeground ( i, wxTheColourDatabase->Find ( _T ( "SKY BLUE" ) ) );
StyleSetForeground ( wxSTC_H_SGML_ENTITY,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_SGML_SPECIAL, *wxWHITE );
StyleSetForeground ( wxSTC_H_SGML_SIMPLESTRING,
wxTheColourDatabase->Find ( _T ( "ORANGE" ) ) );
StyleSetForeground ( wxSTC_H_SGML_DEFAULT,
wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
}
break;
2007-09-07 23:17:30 +02:00
case COLOR_SCHEME_NONE:
2007-09-08 00:25:30 +02:00
baseBackground = LightColour ( wxTheColourDatabase->Find ( _T ( "YELLOW" ) ), 20 );
alternateBackground = LightColour ( wxTheColourDatabase->Find ( _T ( "YELLOW" ) ), 60 );
SetCaretLineBackground ( baseBackground );
SetSelBackground ( true, wxTheColourDatabase->Find ( _T ( "LIGHT GREY" ) ) );
SetCaretForeground ( *wxBLACK );
StyleSetForeground ( wxSTC_STYLE_DEFAULT, *wxBLACK );
StyleSetBackground ( wxSTC_STYLE_DEFAULT, *wxWHITE );
StyleClearAll();
break;
2007-09-07 23:17:30 +02:00
default:
2007-09-08 00:25:30 +02:00
break;
}
if ( type == FILE_TYPE_CSS )
{
StyleSetBold ( wxSTC_CSS_CLASS, true );
StyleSetBold ( wxSTC_CSS_PSEUDOCLASS, true );
StyleSetBold ( wxSTC_CSS_UNKNOWN_PSEUDOCLASS, true );
StyleSetBold ( wxSTC_CSS_DOUBLESTRING, true );
StyleSetBold ( wxSTC_CSS_SINGLESTRING, true );
StyleSetBold ( wxSTC_CSS_DIRECTIVE, true );
}
else
{
StyleSetBold ( wxSTC_H_XMLSTART, true );
StyleSetBold ( wxSTC_H_XMLEND, true );
StyleSetBold ( wxSTC_H_ATTRIBUTEUNKNOWN, true );
StyleSetBold ( wxSTC_H_ENTITY, true );
StyleSetBold ( wxSTC_H_QUESTION, true );
StyleSetBold ( wxSTC_H_SGML_ENTITY, true );
StyleSetBold ( wxSTC_H_SGML_DEFAULT, true );
}
applyVisibilityState ( visibilityState );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::applyVisibilityState ( int state )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( type == FILE_TYPE_BINARY )
return;
visibilityState = state;
bool visible;
// hide tags/attributes
visible = ( state == HIDE_ATTRIBUTES || state == HIDE_TAGS ) ? false : true;
StyleSetVisible ( wxSTC_H_OTHER, visible );
StyleSetVisible ( wxSTC_H_ATTRIBUTE, visible );
StyleSetVisible ( wxSTC_H_ATTRIBUTEUNKNOWN, visible );
StyleSetVisible ( wxSTC_H_DOUBLESTRING, visible );
StyleSetVisible ( wxSTC_H_SINGLESTRING, visible );
// hide tags
visible = ( state == HIDE_TAGS ) ? false : true;
StyleSetVisible ( wxSTC_H_TAG, visible );
StyleSetVisible ( wxSTC_H_TAGUNKNOWN, visible );
StyleSetVisible ( wxSTC_H_TAGEND, visible );
StyleSetVisible ( wxSTC_H_XMLSTART, visible );
StyleSetVisible ( wxSTC_H_XMLEND, visible );
StyleSetVisible ( wxSTC_H_CDATA, visible );
StyleSetVisible ( wxSTC_H_QUESTION, visible );
StyleSetVisible ( wxSTC_H_COMMENT, visible );
for ( int i = wxSTC_H_SGML_DEFAULT; i <= wxSTC_H_SGML_BLOCK_DEFAULT; i++ )
StyleSetVisible ( i, visible );
Colourise ( 0, -1 );
2007-09-07 23:17:30 +02:00
}
int XmlCtrl::getType()
{
2007-09-08 00:25:30 +02:00
return type;
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::foldAll()
{
2007-09-08 00:25:30 +02:00
expandFoldsToLevel ( 1, false );
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::unfoldAll()
{
2007-09-08 00:25:30 +02:00
expandFoldsToLevel ( wxSTC_FOLDLEVELNUMBERMASK, true );
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::toggleFold()
{
2007-09-08 00:25:30 +02:00
int pos, line, level;
pos = GetCurrentPos();
if ( pos == -1 )
return;
line = LineFromPosition ( pos );
level = GetFoldLevel ( line );
if ( XMLCTRL_HASBIT ( level, wxSTC_FOLDLEVELHEADERFLAG ) )
ToggleFold ( line );
2007-09-07 23:17:30 +02:00
}
// adapted from wxSTEdit (c) 2005 John Labenski, Otto Wyss
2007-09-08 00:25:30 +02:00
void XmlCtrl::expandFoldsToLevel ( int level, bool expand )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
Colourise ( 0, -1 );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
const int line_n = GetLineCount();
for ( int n = 0; n < line_n; n++ )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int line_level = GetFoldLevel ( n );
if ( XMLCTRL_HASBIT ( line_level, wxSTC_FOLDLEVELHEADERFLAG ) )
{
line_level -= wxSTC_FOLDLEVELBASE;
line_level &= wxSTC_FOLDLEVELNUMBERMASK;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( ( ( expand && ( line_level <= level ) ) ||
( !expand && ( line_level >= level ) ) ) && ( GetFoldExpanded ( n ) != expand ) )
ToggleFold ( n );
}
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
EnsureCaretVisible(); // seems to keep it in nearly the same place
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::protectHeadLine()
{
2007-09-08 00:25:30 +02:00
if ( *protectTags || !properties.fold )
return;
int pos1, pos2, line1, line2, level;
pos1 = GetSelectionStart();
pos2 = GetSelectionEnd();
line1 = LineFromPosition ( pos1 );
line2 = LineFromPosition ( pos2 );
if ( line2 < line1 )
{
int temp = line1;
line1 = line2;
line2 = temp;
}
for ( int i = line1; i <= line2; i++ )
{
level = GetFoldLevel ( i );
if ( XMLCTRL_HASBIT ( level, wxSTC_FOLDLEVELHEADERFLAG ) && !GetFoldExpanded ( i ) )
ToggleFold ( i );
}
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
wxString XmlCtrl::getOpenTag ( const wxString& element )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
wxString openTag;
openTag = _T ( "<" ) + element;
std::set<std::string> requiredAttributeSet;
std::set<std::string>::iterator it;
std::string key = ( const char * ) element.mb_str ( wxConvUTF8 );
requiredAttributeSet = requiredAttributeMap[key];
if ( !requiredAttributeSet.empty() )
{
for ( it = requiredAttributeSet.begin(); it != requiredAttributeSet.end(); it++ )
{
openTag += _T ( " " );
openTag += wxString ( it->c_str(), wxConvUTF8, it->size() );
openTag += _T ( "=\"\"" );
}
}
openTag += _T ( ">" );
return openTag;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
bool XmlCtrl::insertChild ( const wxString& child )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int start, end;
start = GetSelectionStart();
end = GetSelectionEnd();
int offset;
wxString openTag, closeTag;
openTag = getOpenTag ( child );
closeTag = _T ( "</" ) + child + _T ( ">" );
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( start == end )
{
if ( !canInsertAt ( start ) )
return false;
//tag = _T("<") + child + _T(">");
offset = openTag.Length();
wxString tag;
tag = openTag + closeTag;
InsertText ( start, tag );
SetSelection ( start + offset, start + offset );
SetFocus();
return true;
}
if ( *protectTags )
adjustSelection();
//wxString openTag, closeTag;
//openTag = _T("<") + child + _T(">");
//closeTag = _T("</") + child + _T(">");
offset = openTag.Length();
if ( start > end )
{
int temp = end;
start = end;
end = temp;
}
InsertText ( start, openTag );
InsertText ( end + offset, closeTag );
SetSelection ( start + offset, end + offset );
2007-09-07 23:17:30 +02:00
return true;
}
2007-09-08 00:25:30 +02:00
bool XmlCtrl::insertSibling ( const wxString& sibling, const wxString& parent )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int start = GetSelectionStart();
int limit = GetLength();
wxString parentCloseTag = _T ( "</" ) + parent + _T ( ">" );
int parentCloseTagStart = FindText ( start, limit, parentCloseTag );
if ( parentCloseTagStart == -1 ||
!canInsertAt ( parentCloseTagStart + parentCloseTag.Length() ) )
return false;
int insertionPoint = parentCloseTagStart + parentCloseTag.Length();
SetSelection ( insertionPoint, insertionPoint );
insertNewLine();
wxString openTag, closeTag;
int newCurrentPos, newAdjustedPos;
newCurrentPos = GetCurrentPos();
openTag = getOpenTag ( sibling );
closeTag = _T ( "</" ) + sibling + _T ( ">" );
InsertText ( newCurrentPos, openTag + closeTag );
newAdjustedPos = newCurrentPos + openTag.Length();
SetSelection ( newAdjustedPos, newAdjustedPos );
return true;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
bool XmlCtrl::insertEntity ( const wxString& entity )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( *protectTags )
adjustCursor();
wxString insertBuffer;
insertBuffer.Printf ( _T ( "&%s;" ), entity.c_str() );
int pos = GetCurrentPos();
InsertText ( GetCurrentPos(), insertBuffer );
pos += insertBuffer.size();
SetSelection ( pos, pos );
return true;
2007-09-07 23:17:30 +02:00
}
wxString XmlCtrl::getParent()
{
2007-09-08 00:25:30 +02:00
int current, parentCloseAngleBracket;
current = GetCurrentPos();
parentCloseAngleBracket = getParentCloseAngleBracket ( current );
return getLastElementName ( parentCloseAngleBracket );
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::insertNewLine()
{
2007-09-08 00:25:30 +02:00
bool autoindent = false;
int pos, line, startPos, iteratorPos, newPos;
pos = GetCurrentPos();
line = LineFromPosition ( pos );
startPos = PositionFromLine ( line );
iteratorPos = startPos;
for ( iteratorPos = startPos;
( GetCharAt ( iteratorPos ) == ' ' ||
GetCharAt ( iteratorPos ) == '\t' ) &&
iteratorPos < pos;
++iteratorPos )
autoindent = true;
wxString s = GetTextRange ( startPos, iteratorPos );
NewLine();
if ( autoindent )
{
newPos = PositionFromLine ( line + 1 );
InsertText ( newPos, s );
SetSelection ( newPos + s.size(), newPos + s.size() );
}
2007-09-07 23:17:30 +02:00
}
void XmlCtrl::toggleLineBackground()
{
2007-09-08 00:25:30 +02:00
if ( !properties.toggleLineBackground || visibilityState != HIDE_TAGS )
{
if ( lineBackgroundState != BACKGROUND_STATE_NORMAL )
{
SetCaretLineBackground ( baseBackground );
lineBackgroundState = BACKGROUND_STATE_NORMAL;
}
return;
}
lineBackgroundState = ( lineBackgroundState == BACKGROUND_STATE_NORMAL ) ?
BACKGROUND_STATE_LIGHT : BACKGROUND_STATE_NORMAL;
SetCaretLineBackground ( ( lineBackgroundState == BACKGROUND_STATE_NORMAL ) ? baseBackground : alternateBackground );
2007-09-07 23:17:30 +02:00
}
std::set<std::string> XmlCtrl::getEntitySet()
{
2007-09-08 00:25:30 +02:00
return entitySet;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
bool XmlCtrl::shallowValidate ( int maxLine, bool segmentOnly )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( !properties.validateAsYouType || type != FILE_TYPE_XML )
return true;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
validationRequired = false;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( !maxLine )
maxLine = GetLineCount();
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
std::string bufferUtf8;
int startLine, columnOffset;
startLine = columnOffset = 0;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( !segmentOnly )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
clearErrorIndicators ( maxLine );
bufferUtf8 = myGetTextRaw();
}
else
{
int current,
line,
lineEnd,
parentCloseAngleBracket,
parentStartAngleBracket,
memory;
current = GetCurrentPos();
line = LineFromPosition ( current );//PositionFromLine(current);
// try to include next line
lineEnd = GetLineEndPosition ( line + 1 );
if ( lineEnd == -1 )
lineEnd = GetLineEndPosition ( line );
// fetch parent
parentCloseAngleBracket = getParentCloseAngleBracket ( current );
parentStartAngleBracket = getTagStartPos ( parentCloseAngleBracket );
if ( parentStartAngleBracket == -1 )
return false;
memory = parentStartAngleBracket;
// fetch grandparent if not at start of document
if ( parentStartAngleBracket > 1 )
{
parentCloseAngleBracket =
getParentCloseAngleBracket ( parentStartAngleBracket - 1 );
parentStartAngleBracket = getTagStartPos ( parentCloseAngleBracket );
if ( parentStartAngleBracket == -1 )
parentStartAngleBracket = memory;
}
startLine = LineFromPosition ( parentStartAngleBracket );
if ( startLine == line )
{
columnOffset = parentStartAngleBracket - PositionFromLine ( line );
// disallow negative offsets
if ( columnOffset < 0 )
columnOffset = 0;
}
// sanity-check range
if ( lineEnd <= parentStartAngleBracket )
return false;
// clear indicators within range
StartStyling ( parentStartAngleBracket, wxSTC_INDIC2_MASK );
int length = lineEnd - parentStartAngleBracket;
SetStyling ( length, 0 );
// tweak raw getTextRange variant
wxString wideBuffer = GetTextRange ( parentStartAngleBracket, lineEnd );
bufferUtf8 = ( const char * ) wideBuffer.mb_str ( wxConvUTF8 );
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
return shallowValidate ( bufferUtf8.c_str(), bufferUtf8.size(), startLine,
maxLine, columnOffset, segmentOnly );
/*
bool res = validator->parse(bufferUtf8, (segmentOnly) ? false : true);
if (!validator->getOverrideFailure() && (!res || !validator->isValid()))
{
std::vector<std::pair<int, int> > positionVector = validator->getPositionVector();
if (res == XML_STATUS_ERROR)
{
positionVector.push_back(validator->getErrorPosition());
}
std::vector<std::pair<int, int> >::iterator it;
for (it = positionVector.begin(); it != positionVector.end(); it++)
{
int line, column;
line = (it->first - 1) + startLine;
column = it->second + columnOffset;
setErrorIndicator(line, column);
}
return false;
}
return true;
*/
}
bool XmlCtrl::shallowValidate ( const char *buffer,
size_t bufferLen,
int startLine,
int maxLine,
int columnOffset,
bool segmentOnly )
{
std::auto_ptr<XmlShallowValidator> validator ( new XmlShallowValidator (
elementMap,
attributeMap,
requiredAttributeMap,
entitySet,
maxLine,
segmentOnly ) );
bool res = validator->parse ( buffer, bufferLen, ( segmentOnly ) ? false : true );
if ( !validator->getOverrideFailure() && ( !res || !validator->isValid() ) )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
std::vector<std::pair<int, int> > positionVector = validator->getPositionVector();
if ( res == XML_STATUS_ERROR )
{
positionVector.push_back ( validator->getErrorPosition() );
}
std::vector<std::pair<int, int> >::iterator it;
for ( it = positionVector.begin(); it != positionVector.end(); it++ )
{
int line, column;
line = ( it->first - 1 ) + startLine;
column = it->second + columnOffset;
setErrorIndicator ( line, column );
}
return false;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
return true;
2007-09-07 23:17:30 +02:00
}
std::string XmlCtrl::myGetTextRaw()
{
2007-09-08 00:25:30 +02:00
int len = GetTextLength();
char *buf = new char[len+1];
SendMsg ( 2182, len+1, ( long ) buf );
buf[len] = '\0';
std::string ret ( buf );
delete[] buf;
return ret;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::setErrorIndicator ( int line, int column )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int startPos, endPos;
startPos = PositionFromLine ( line ) + column;
endPos = GetLineEndPosition ( line );
StartStyling ( startPos, wxSTC_INDIC2_MASK );
int length = endPos - startPos;
/*
from CellBuffer.cxx:
PLATFORM_ASSERT(lengthStyle == 0 ||
(lengthStyle > 0 && lengthStyle + position < length));
*/
if ( length == 0 || ( length > 0 && length + startPos < GetLength() ) )
{
SetStyling ( length, wxSTC_INDIC2_MASK );
}
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::clearErrorIndicators ( int maxLine )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( maxLine < 1 )
return;
int documentLength = GetLength();
if ( !documentLength )
return;
StartStyling ( 0, wxSTC_INDIC2_MASK );
int length;
length = ( maxLine ) ? GetLineEndPosition ( maxLine ) : documentLength;
SetStyling ( length, 0 );
2007-09-07 23:17:30 +02:00
}
bool XmlCtrl::getValidationRequired()
{
2007-09-08 00:25:30 +02:00
return validationRequired;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::setValidationRequired ( bool b )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
validationRequired = b;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
int XmlCtrl::getTagType ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int iteratorPos;
// preliminary checks
if ( pos < 2 )
{
return TAG_TYPE_ERROR;
}
else if ( GetCharAt ( pos - 1 ) == '/' )
{
return TAG_TYPE_EMPTY;
}
// go to start of tag
for ( iteratorPos = pos; iteratorPos >= 0; --iteratorPos )
{
int style = getLexerStyleAt ( iteratorPos );
//style &= ~wxSTC_INDIC2_MASK;
2007-09-07 23:17:30 +02:00
2007-09-08 00:25:30 +02:00
if ( GetCharAt ( iteratorPos ) == '<' &&
( style == wxSTC_H_TAG || style == wxSTC_H_TAGUNKNOWN ) )
break;
}
if ( GetCharAt ( iteratorPos ) != '<' )
return TAG_TYPE_ERROR;
char c = GetCharAt ( iteratorPos + 1 );
if ( c == '!' || c == '?' )
return TAG_TYPE_OTHER;
else if ( c == '/' )
{
return TAG_TYPE_CLOSE;
}
else
{
return TAG_TYPE_OPEN;
}
2007-09-07 23:17:30 +02:00
}
// fetch style int disregarding indicator
2007-09-08 00:25:30 +02:00
int XmlCtrl::getLexerStyleAt ( int pos )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
int style = GetStyleAt ( pos );
style &= ~wxSTC_INDIC2_MASK;
return style;
2007-09-07 23:17:30 +02:00
}
bool XmlCtrl::getDtdFound()
{
2007-09-08 00:25:30 +02:00
return dtdFound;
2007-09-07 23:17:30 +02:00
}
2007-09-08 00:25:30 +02:00
void XmlCtrl::OnMiddleDown ( wxMouseEvent& event )
2007-09-07 23:17:30 +02:00
{
2007-09-08 00:25:30 +02:00
if ( GetSelectionStart() == GetSelectionEnd() )
{
event.Skip();
return;
}
Copy();
long x, y;
event.GetPosition ( &x, &y );
int pastePosition = PositionFromPointClose ( x, y );
if ( pastePosition == wxSTC_INVALID_POSITION )
{
event.Skip();
return;
}
SetSelection ( pastePosition, pastePosition );
Paste();
2007-09-07 23:17:30 +02:00
}