@ -33,14 +33,14 @@ namespace ICSharpCode.TextEditor
{
{
int fontHeight ;
int fontHeight ;
//Hashtable charWitdh = new Hashtable();
//Hashtable charWitdh = new Hashtable();
StringFormat measureStringFormat = ( StringFormat ) StringFormat . GenericTypographic . Clone ( ) ;
//StringFormat measureStringFormat = (StringFormat)StringFormat.GenericTypographic.Clone();
Highlight highlight ;
Highlight highlight ;
int physicalColumn = 0 ; // used for calculating physical column during paint
int physicalColumn = 0 ; // used for calculating physical column during paint
public void Dispose ( )
public void Dispose ( )
{
{
measureCache . Clear ( ) ;
measureCache . Clear ( ) ;
measureStringFormat . Dispose ( ) ;
//measureStringFormat.Dispose();
}
}
public Highlight Highlight {
public Highlight Highlight {
@ -101,11 +101,11 @@ namespace ICSharpCode.TextEditor
public TextView ( TextArea textArea ) : base ( textArea )
public TextView ( TextArea textArea ) : base ( textArea )
{
{
measureStringFormat . LineAlignment = StringAlignment . Near ;
/ * measureStringFormat . LineAlignment = StringAlignment . Near ;
measureStringFormat . FormatFlags = StringFormatFlags . MeasureTrailingSpaces |
measureStringFormat . FormatFlags = StringFormatFlags . MeasureTrailingSpaces |
StringFormatFlags . FitBlackBox |
StringFormatFlags . FitBlackBox |
StringFormatFlags . NoWrap |
StringFormatFlags . NoWrap |
StringFormatFlags . NoClip ;
StringFormatFlags . NoClip ; * /
base . Cursor = Cursors . IBeam ;
base . Cursor = Cursors . IBeam ;
OptionsChanged ( ) ;
OptionsChanged ( ) ;
@ -113,8 +113,9 @@ namespace ICSharpCode.TextEditor
static int GetFontHeight ( Font font )
static int GetFontHeight ( Font font )
{
{
int h = font . Height ;
int height1 = TextRenderer . MeasureText ( "_" , font ) . Height ;
return ( h < 1 6 ) ? h + 1 : h ;
int height2 = ( int ) Math . Ceiling ( font . GetHeight ( ) ) ;
return Math . Max ( height1 , height2 ) + 1 ;
}
}
float spaceWidth ;
float spaceWidth ;
@ -145,9 +146,9 @@ namespace ICSharpCode.TextEditor
public void OptionsChanged ( )
public void OptionsChanged ( )
{
{
this . lastFont = TextEditorProperties . Font ;
this . lastFont = TextEditorProperties . FontContainer . RegularFont ;
this . fontHeight = GetFontHeight ( lastFont ) ;
this . fontHeight = GetFontHeight ( lastFont ) ;
// use minin um width - in some fonts, space has no width but kerning is used instead
// use minim um width - in some fonts, space has no width but kerning is used instead
// -> DivideByZeroException
// -> DivideByZeroException
this . spaceWidth = Math . Max ( GetWidth ( ' ' , lastFont ) , 1 ) ;
this . spaceWidth = Math . Max ( GetWidth ( ' ' , lastFont ) , 1 ) ;
// tab should have the width of 4*'x'
// tab should have the width of 4*'x'
@ -162,7 +163,7 @@ namespace ICSharpCode.TextEditor
}
}
// Just to ensure that fontHeight and char widths are always correct...
// Just to ensure that fontHeight and char widths are always correct...
if ( lastFont ! = TextEditorProperties . Font ) {
if ( lastFont ! = TextEditorProperties . FontContainer . RegularFont ) {
OptionsChanged ( ) ;
OptionsChanged ( ) ;
base . TextArea . BeginInvoke ( new MethodInvoker ( base . TextArea . Refresh ) ) ;
base . TextArea . BeginInvoke ( new MethodInvoker ( base . TextArea . Refresh ) ) ;
}
}
@ -307,11 +308,11 @@ namespace ICSharpCode.TextEditor
g . FillRectangle ( backgroundBrush , rect ) ;
g . FillRectangle ( backgroundBrush , rect ) ;
physicalColumn + = text . Length ;
physicalColumn + = text . Length ;
g . DrawString ( text ,
DrawString ( g ,
textArea . Fon t ,
text ,
BrushRegistry . GetBrush ( drawSelected ? selectionColor . Color : Color . Gray ) ,
textArea . Font ,
rect ,
drawSelected ? selectionColor . Color : Color . Gray ,
measureStringFormat ) ;
rect . X , rect . Y ) ;
g . DrawRectangle ( BrushRegistry . GetPen ( drawSelected ? Color . DarkGray : Color . Gray ) , rect . X , rect . Y , rect . Width , rect . Height ) ;
g . DrawRectangle ( BrushRegistry . GetPen ( drawSelected ? Color . DarkGray : Color . Gray ) , rect . X , rect . Y , rect . Width , rect . Height ) ;
// Bugfix for the problem - of overdrawn right rectangle lines.
// Bugfix for the problem - of overdrawn right rectangle lines.
@ -411,6 +412,7 @@ namespace ICSharpCode.TextEditor
TextWord currentWord ;
TextWord currentWord ;
TextWord nextCurrentWord = null ;
TextWord nextCurrentWord = null ;
FontContainer fontContainer = TextEditorProperties . FontContainer ;
for ( int wordIdx = 0 ; wordIdx < currentLine . Words . Count ; wordIdx + + ) {
for ( int wordIdx = 0 ; wordIdx < currentLine . Words . Count ; wordIdx + + ) {
currentWord = currentLine . Words [ wordIdx ] ;
currentWord = currentLine . Words [ wordIdx ] ;
if ( currentWordOffset < startColumn ) {
if ( currentWordOffset < startColumn ) {
@ -534,7 +536,7 @@ namespace ICSharpCode.TextEditor
float wordWidth = DrawDocumentWord ( g ,
float wordWidth = DrawDocumentWord ( g ,
currentWord . Word ,
currentWord . Word ,
new Point ( ( int ) physicalXPos , lineRectangle . Y ) ,
new Point ( ( int ) physicalXPos , lineRectangle . Y ) ,
currentWord . Font ,
currentWord . Get Font( fontContainer ) ,
wordForeColor ,
wordForeColor ,
wordBackBrush ) ;
wordBackBrush ) ;
wordRectangle = new RectangleF ( physicalXPos , lineRectangle . Y , wordWidth , lineRectangle . Height ) ;
wordRectangle = new RectangleF ( physicalXPos , lineRectangle . Y , wordWidth , lineRectangle . Height ) ;
@ -598,12 +600,12 @@ namespace ICSharpCode.TextEditor
g . FillRectangle ( backBrush , //num == 0 ? Brushes.LightBlue : num == 1 ? Brushes.LightGreen : Brushes.Yellow,
g . FillRectangle ( backBrush , //num == 0 ? Brushes.LightBlue : num == 1 ? Brushes.LightGreen : Brushes.Yellow,
new RectangleF ( position . X , position . Y , ( float ) Math . Ceiling ( wordWidth + 1 ) , FontHeight ) ) ;
new RectangleF ( position . X , position . Y , ( float ) Math . Ceiling ( wordWidth + 1 ) , FontHeight ) ) ;
g . DrawString ( word ,
DrawString ( g ,
font ,
word ,
BrushRegistry . GetBrush ( foreColor ) ,
font ,
position . X ,
foreColor ,
position . Y ,
position . X ,
measureStringFormat ) ;
position . Y ) ;
return wordWidth ;
return wordWidth ;
}
}
@ -625,15 +627,15 @@ namespace ICSharpCode.TextEditor
}
}
}
}
Dictionary < WordFontPair , floa t> measureCache = new Dictionary < WordFontPair , floa t> ( ) ;
Dictionary < WordFontPair , in t> measureCache = new Dictionary < WordFontPair , in t> ( ) ;
// split words after 1000 characters. Fixes GDI+ crash on very longs words, for example
// split words after 1000 characters. Fixes GDI+ crash on very longs words, for example
// a 100 KB Base64-file without any line breaks.
// a 100 KB Base64-file without any line breaks.
const int MaximumWordLength = 1 0 0 0 ;
const int MaximumWordLength = 1 0 0 0 ;
floa t MeasureStringWidth ( Graphics g , string word , Font font )
in t MeasureStringWidth ( Graphics g , string word , Font font )
{
{
floa t width ;
in t width ;
if ( word = = null | | word . Length = = 0 )
if ( word = = null | | word . Length = = 0 )
return 0 ;
return 0 ;
@ -659,15 +661,12 @@ namespace ICSharpCode.TextEditor
// txt.GetPositionFromCharIndex(txt.SelectionStart)
// txt.GetPositionFromCharIndex(txt.SelectionStart)
// (Verdana 10, highlighting makes GetP... bold) -> note the space between 'x' and '('
// (Verdana 10, highlighting makes GetP... bold) -> note the space between 'x' and '('
// this also fixes "jumping" characters when selecting in non-monospace fonts
// this also fixes "jumping" characters when selecting in non-monospace fonts
Rectangle rect = new Rectangle ( 0 , 0 , 3 2 7 6 8 , 1 0 0 0 ) ;
width = TextRenderer . MeasureText ( g , word , font , new Size ( short . MaxValue , short . MaxValue ) , textFormatFlags ) . Width ;
CharacterRange [ ] ranges = { new CharacterRange ( 0 , word . Length ) } ;
Region [ ] regions = new Region [ 1 ] ;
measureStringFormat . SetMeasurableCharacterRanges ( ranges ) ;
regions = g . MeasureCharacterRanges ( word , font , rect , measureStringFormat ) ;
width = regions [ 0 ] . GetBounds ( g ) . Right ;
measureCache . Add ( new WordFontPair ( word , font ) , width ) ;
measureCache . Add ( new WordFontPair ( word , font ) , width ) ;
return width ;
return width ;
}
}
const TextFormatFlags textFormatFlags = TextFormatFlags . NoPadding | TextFormatFlags . NoPrefix ;
#endregion
#endregion
#region Conversion Functions
#region Conversion Functions
@ -803,7 +802,7 @@ namespace ICSharpCode.TextEditor
paintPos + = ( column - oldColumn ) * spaceWidth ;
paintPos + = ( column - oldColumn ) * spaceWidth ;
break ;
break ;
default :
default :
paintPos + = GetWidth ( ch , TextEditorProperties . Font ) ;
paintPos + = GetWidth ( ch , TextEditorProperties . FontContainer . RegularFont ) ;
+ + column ;
+ + column ;
break ;
break ;
}
}
@ -877,7 +876,7 @@ namespace ICSharpCode.TextEditor
paintPos + = ( column - oldColumn ) * WideSpaceWidth ;
paintPos + = ( column - oldColumn ) * WideSpaceWidth ;
break ;
break ;
default :
default :
paintPos + = GetWidth ( ch , TextEditorProperties . Font ) ;
paintPos + = GetWidth ( ch , TextEditorProperties . FontContainer . RegularFont ) ;
+ + column ;
+ + column ;
break ;
break ;
}
}
@ -905,6 +904,7 @@ namespace ICSharpCode.TextEditor
if ( words = = null ) return 0 ;
if ( words = = null ) return 0 ;
int wordCount = words . Count ;
int wordCount = words . Count ;
int wordOffset = 0 ;
int wordOffset = 0 ;
FontContainer fontContainer = TextEditorProperties . FontContainer ;
for ( int i = 0 ; i < wordCount ; i + + ) {
for ( int i = 0 ; i < wordCount ; i + + ) {
TextWord word = words [ i ] ;
TextWord word = words [ i ] ;
if ( wordOffset > = end )
if ( wordOffset > = end )
@ -924,7 +924,7 @@ namespace ICSharpCode.TextEditor
int wordStart = Math . Max ( wordOffset , start ) ;
int wordStart = Math . Max ( wordOffset , start ) ;
int wordLength = Math . Min ( wordOffset + word . Length , end ) - wordStart ;
int wordLength = Math . Min ( wordOffset + word . Length , end ) - wordStart ;
string text = Document . GetText ( currentLine . Offset + wordStart , wordLength ) ;
string text = Document . GetText ( currentLine . Offset + wordStart , wordLength ) ;
drawingPos + = MeasureStringWidth ( g , text , word . Font ? ? TextEditorProperties . Font ) ;
drawingPos + = MeasureStringWidth ( g , text , word . Get Font( fontContainer ) ? ? fontContainer . Regular Font) ;
break ;
break ;
}
}
wordOffset + = word . Length ;
wordOffset + = word . Length ;
@ -1023,7 +1023,7 @@ namespace ICSharpCode.TextEditor
drawingPos + = CountColumns ( ref column , foldEnd , f . StartColumn , f . StartLine , g ) ;
drawingPos + = CountColumns ( ref column , foldEnd , f . StartColumn , f . StartLine , g ) ;
foldEnd = f . EndColumn ;
foldEnd = f . EndColumn ;
column + = f . FoldText . Length ;
column + = f . FoldText . Length ;
drawingPos + = MeasureStringWidth ( g , f . FoldText , TextEditorProperties . Font ) ;
drawingPos + = MeasureStringWidth ( g , f . FoldText , TextEditorProperties . FontContainer . RegularFont ) ;
}
}
drawingPos + = CountColumns ( ref column , foldEnd , logicalColumn , logicalLine , g ) ;
drawingPos + = CountColumns ( ref column , foldEnd , logicalColumn , logicalLine , g ) ;
g . Dispose ( ) ;
g . Dispose ( ) ;
@ -1038,33 +1038,38 @@ namespace ICSharpCode.TextEditor
g . DrawRectangle ( Pens . Blue , rect ) ;
g . DrawRectangle ( Pens . Blue , rect ) ;
}
}
void DrawString ( Graphics g , string text , Font font , Color color , float x , float y )
{
TextRenderer . DrawText ( g , text , font , new Point ( ( int ) x , ( int ) y ) , color , textFormatFlags ) ;
}
void DrawInvalidLineMarker ( Graphics g , float x , float y )
void DrawInvalidLineMarker ( Graphics g , float x , float y )
{
{
HighlightColor invalidLinesColor = textArea . Document . HighlightingStrategy . GetColorFor ( "InvalidLines" ) ;
HighlightColor invalidLinesColor = textArea . Document . HighlightingStrategy . GetColorFor ( "InvalidLines" ) ;
g . DrawString ( "~" , invalidLinesColor . Font , BrushRegistry . GetBrush ( invalidLinesColor . Color ) , x , y , measureStringFormat ) ;
DrawString ( g , "~" , invalidLinesColor . GetFont ( TextEditorProperties . FontContainer ) , invalidLinesColor . Color , x , y ) ;
}
}
void DrawSpaceMarker ( Graphics g , Color color , float x , float y )
void DrawSpaceMarker ( Graphics g , Color color , float x , float y )
{
{
HighlightColor spaceMarkerColor = textArea . Document . HighlightingStrategy . GetColorFor ( "SpaceMarkers" ) ;
HighlightColor spaceMarkerColor = textArea . Document . HighlightingStrategy . GetColorFor ( "SpaceMarkers" ) ;
g . DrawString ( "\u00B7" , spaceMarkerColor . Font , BrushRegistry . GetBrush ( color ) , x , y , measureStringFormat ) ;
DrawString ( g , "\u00B7" , spaceMarkerColor . GetFont ( TextEditorProperties . FontContainer ) , color , x , y ) ;
}
}
void DrawTabMarker ( Graphics g , Color color , float x , float y )
void DrawTabMarker ( Graphics g , Color color , float x , float y )
{
{
HighlightColor tabMarkerColor = textArea . Document . HighlightingStrategy . GetColorFor ( "TabMarkers" ) ;
HighlightColor tabMarkerColor = textArea . Document . HighlightingStrategy . GetColorFor ( "TabMarkers" ) ;
g . DrawString ( "\u00BB" , tabMarkerColor . Font , BrushRegistry . GetBrush ( color ) , x , y , measureStringFormat ) ;
DrawString ( g , "\u00BB" , tabMarkerColor . GetFont ( TextEditorProperties . FontContainer ) , color , x , y ) ;
}
}
float DrawEOLMarker ( Graphics g , Color color , Brush backBrush , float x , float y )
float DrawEOLMarker ( Graphics g , Color color , Brush backBrush , float x , float y )
{
{
float width = GetWidth ( ' \ u00B6 ' , TextEditorProperties . Font ) ;
HighlightColor eolMarkerColor = textArea . Document . HighlightingStrategy . GetColorFor ( "EOLMarkers" ) ;
float width = GetWidth ( ' \ u00B6 ' , eolMarkerColor . GetFont ( TextEditorProperties . FontContainer ) ) ;
g . FillRectangle ( backBrush ,
g . FillRectangle ( backBrush ,
new RectangleF ( x , y , width , fontHeight ) ) ;
new RectangleF ( x , y , width , fontHeight ) ) ;
HighlightColor eolMarkerColor = textArea . Document . HighlightingStrategy . GetColorFor ( "EOLMarkers" ) ;
DrawString ( g , "\u00B6" , eolMarkerColor . GetFont ( TextEditorProperties . FontContainer ) , color , x , y ) ;
g . DrawString ( "\u00B6" , eolMarkerColor . Font , BrushRegistry . GetBrush ( color ) , x , y , measureStringFormat ) ;
return width ;
return width ;
}
}