97,7 → 97,7 |
| ControlStyles.ResizeRedraw, true); |
|
fontMeasureFormat.LineAlignment = StringAlignment.Near; |
fontMeasureFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.FitBlackBox |
fontMeasureFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.FitBlackBox |
| StringFormatFlags.NoWrap | StringFormatFlags.NoClip; |
|
vScrollBar = new ScrollBarsControl(this, true); |
122,7 → 122,7 |
get |
{ |
CreateParams cp = base.CreateParams; |
if(!base.DesignMode) |
if(!base.DesignMode) |
{ |
cp.Style = cp.Style | WS_HSCROLL | WS_VSCROLL; |
cp.ExStyle = cp.ExStyle | WS_EX_CLIENTEDGE; |
134,9 → 134,9 |
public bool WordWrap |
{ |
get { return wordWrap; } |
set |
{ |
wordWrap = value; |
set |
{ |
wordWrap = value; |
RecalcParams(); |
Invalidate(); |
// FIXME recalc number of lines for the vertical scroll bar |
164,7 → 164,7 |
selEndLineOrig = -1; |
selEndPosOrig = -1; |
|
if(!updateBlocked) |
if(!updateBlocked) |
{ |
vScrollBar.Update(curLine, 0, linesCount, 1, 1); |
UpdateHScrollBar(); |
207,7 → 207,7 |
|
public void RestoreState(object state, bool restorePosition) |
{ |
if(!(state is ViewControlState)) |
if(!(state is ViewControlState)) |
throw new ArgumentException("Can restore only from object returned by SaveState()"); |
|
ViewControlState s = (ViewControlState)state; |
230,7 → 230,7 |
foreach(LineFragment[] line in lineFragments) |
{ |
int lineLength = 0; |
foreach(LineFragment frag in line) |
foreach(LineFragment frag in line) |
{ |
lineLength += frag.indent + (frag.text == null ? 0 : frag.text.Length); |
} |
246,7 → 246,7 |
selEndLineOrig = s.selEndLineOrig; |
selEndPosOrig = s.selEndPosOrig; |
} |
else |
else |
{ |
curLine = 0; |
curCol = 0; |
323,7 → 323,7 |
if(lineLen > 0) break; |
} |
|
if(line == null || lineLen == 0) |
if(line == null || lineLen == 0) |
{ |
fragment = new LineFragment(); |
fragment.color = this.ForeColor; |
333,7 → 333,7 |
fragment.indent = 0; |
fragment.wrapIndent = 0; |
} |
else |
else |
{ |
fragment = line[lineLen-1]; |
fragment.indent = 0; |
367,7 → 367,7 |
{ |
LineFragment[] lastLine = (linesCount > 0) ? (LineFragment[])lineFragments[linesCount-1] : null; |
|
if(lastLine == null) |
if(lastLine == null) |
{ |
lastLine = AddEmptyLine(Color.Transparent); |
} |
386,13 → 386,13 |
{ |
lineLength += lastLine[i].indent + (lastLine[i].text == null ? 0 : lastLine[i].text.Length); |
} |
if(lineLength > maxLineLength) |
if(lineLength > maxLineLength) |
{ |
maxLineLength = lineLength; |
if(!updateBlocked && !wordWrap) hScrollBar.Maximum = maxLineLength + 2; |
} |
|
if(!updateBlocked) |
if(!updateBlocked) |
{ |
if(curLine + linesVisible + 1 >= lastLineLen) Invalidate(); |
} |
414,7 → 414,7 |
|
private TextMarker GetTextMarker(object marker) |
{ |
if(!(marker is TextMarker)) |
if(!(marker is TextMarker)) |
throw new ArgumentException("Can mark only with object returned by BeginMark()"); |
|
TextMarker m = (TextMarker)marker; |
429,9 → 429,9 |
{ |
validMarkers.RemoveAt(i); |
} |
else |
else |
{ |
if(refer.Target == m) |
if(refer.Target == m) |
{ |
isValid = true; |
} |
474,7 → 474,7 |
DeleteLinePart(m.endLine - lineDeleted, 0, m.endPos); |
|
// update screen |
if(!updateBlocked) |
if(!updateBlocked) |
{ |
Invalidate(); |
} |
503,7 → 503,7 |
lineBackColors.RemoveAt(lineNum); |
linesCount--; |
} |
else |
else |
{ |
// delete part of line |
LineFragment[] newLine = new LineFragment[(lineNum == linesCount - 1) ? line.Length : lineLen - end + begin]; |
516,7 → 516,7 |
return deleted; |
} |
|
public void ChangeText(object marker, string text, Color color, Color backColor, |
public void ChangeText(object marker, string text, Color color, Color backColor, |
bool italic, bool bold, int indent, int wrapIndent) |
{ |
lock(this) |
528,8 → 528,8 |
LineFragment[] line = (LineFragment[])lineFragments[m.beginLine]; |
LineFragment fragment = line[m.beginPos]; |
|
if(fragment.text == text && fragment.color == color && fragment.backColor == backColor |
&& fragment.italic == italic && fragment.bold == bold && fragment.indent == indent |
if(fragment.text == text && fragment.color == color && fragment.backColor == backColor |
&& fragment.italic == italic && fragment.bold == bold && fragment.indent == indent |
&& fragment.wrapIndent == wrapIndent) |
{ |
return; // the fragment is not changed |
545,7 → 545,7 |
|
line[m.beginPos] = fragment; |
|
if(!updateBlocked) |
if(!updateBlocked) |
{ |
if(m.beginLine >= curLine && m.beginLine <= curLine + linesVisible + 1) Invalidate(); |
} |
553,7 → 553,7 |
} |
|
// side effect - the given marker is moved to position after the inserted text |
public void InsertText(object marker, string text, Color color, Color backColor, |
public void InsertText(object marker, string text, Color color, Color backColor, |
bool italic, bool bold, int indent, int wrapIndent) |
{ |
lock(this) |
571,7 → 571,7 |
fragment.indent = indent; |
fragment.wrapIndent = wrapIndent; |
|
if(line == null) |
if(line == null) |
{ |
line = AddEmptyLine(Color.Transparent); |
lastLineLen++; |
580,16 → 580,17 |
{ |
if(line.Length <= lastLineLen || m.endPos < lastLineLen) |
{ |
LineFragment[] newLine = new LineFragment[lastLineLen * (line.Length == lastLineLen ? 2 : 1)]; |
LineFragment[] newLine = new LineFragment[lastLineLen * (line.Length + 1 >= lastLineLen ? 2 : 1)]; |
|
if(m.endPos > 0) Array.Copy(line, 0, newLine, 0, m.endPos); |
if(lastLineLen > m.endPos) Array.Copy(line, m.endPos, newLine, m.endPos+1, lastLineLen - m.endPos); |
|
line = newLine; |
lineFragments[m.endLine] = line; |
} |
lastLineLen++; |
} |
else |
else |
{ |
LineFragment[] newLine = new LineFragment[line.Length + 1]; |
if(m.endPos > 0) Array.Copy(line, 0, newLine, 0, m.endPos); |
607,7 → 608,7 |
{ |
lineLength += line[i].indent + (line[i].text == null ? 0 : line[i].text.Length); |
} |
if(lineLength > maxLineLength) |
if(lineLength > maxLineLength) |
{ |
maxLineLength = lineLength; |
if(!updateBlocked && !wordWrap) hScrollBar.Maximum = maxLineLength + 2; |
614,7 → 615,7 |
} |
|
// update screen |
if(!updateBlocked) |
if(!updateBlocked) |
{ |
if(m.endLine >= curLine && m.endLine <= curLine + linesVisible + 1) Invalidate(); |
} |
640,13 → 641,14 |
SaveLastLine(); |
AddEmptyLine(backColor); |
} |
else |
else |
{ |
LineFragment[] oldLine = (LineFragment[])lineFragments[m.endLine]; |
int oldLineLen = (m.endLine == linesCount - 1) ? lastLineLen : oldLine.Length; |
LineFragment[] line1 = new LineFragment[m.endPos]; |
LineFragment[] line2 = new LineFragment[ |
(m.endLine == linesCount - 1) ? NEW_LINE_LENGTH : oldLine.Length - m.endPos]; |
LineFragment[] line2 = new LineFragment[(m.endLine == linesCount - 1) |
? (int)Math.Ceiling((double)(oldLineLen - m.endPos) / NEW_LINE_LENGTH) * NEW_LINE_LENGTH |
: oldLineLen - m.endPos]; |
|
if(m.endPos > 0) Array.Copy(oldLine, 0, line1, 0, m.endPos); |
if(oldLineLen - m.endPos > 0) Array.Copy(oldLine, m.endPos, line2, 0, oldLineLen - m.endPos); |
654,13 → 656,13 |
lineFragments[m.endLine] = line1; |
lineFragments.Insert(m.endLine + 1, line2); |
lineBackColors.Insert(m.endLine + 1, backColor); |
linesCount++; |
|
if(m.endLine == linesCount - 1) lastLineLen = oldLineLen - m.endPos; |
linesCount++; |
} |
|
// update screen |
if(!updateBlocked) |
if(!updateBlocked) |
{ |
if(m.endLine >= curLine && m.endLine <= curLine + linesVisible + 1) Invalidate(); |
vScrollBar.Maximum = linesCount; |
681,7 → 683,7 |
{ |
validMarkers.RemoveAt(i); |
} |
else |
else |
{ |
TextMarker m = (TextMarker)refer.Target; |
|
691,7 → 693,7 |
} |
} |
|
private void ShiftTextMarkerBorder(ref int borderLine, ref int borderPos, |
private void ShiftTextMarkerBorder(ref int borderLine, ref int borderPos, |
int line, int pos, int lineDelta, int posDelta) |
{ |
if(borderLine > line) |
812,7 → 814,7 |
{ |
lock(this) |
{ |
try |
try |
{ |
Graphics g = e.Graphics; |
SolidBrush brush = new SolidBrush(Color.Black); |
850,7 → 852,7 |
int textLen = (text == null) ? 0 : text.Length; |
|
// calc shift using curCol |
if(shift > 0) |
if(shift > 0) |
{ |
if(shift < fragment.indent) |
{ |
857,9 → 859,9 |
curIndent -= shift; |
shift = 0; |
} |
else if(shift < textLen + fragment.indent) |
else if(shift < textLen + fragment.indent) |
{ |
if(text != null) |
if(text != null) |
{ |
text = text.Substring(shift - fragment.indent); |
textLen = text.Length; |
867,7 → 869,7 |
shift = 0; |
curIndent = 0; |
} |
else |
else |
{ |
curIndent = 0; |
shift -= textLen + fragment.indent; |
877,7 → 879,7 |
} |
|
// draw the line, m.b. split it to several display lines |
while(true) |
while(true) |
{ |
string drawText = text; |
int drawLen = textLen; |
890,7 → 892,7 |
{ |
int visibleLen = colsVisible - 2; |
int availableLen = visibleLen - indent - curIndent; |
if(textLen > availableLen) |
if(textLen > availableLen) |
{ |
if(textLen == 0 || availableLen < 0) |
{ |
919,7 → 921,7 |
if(fragment.backColor != Color.Transparent && (indent >= 0) && (drawLen + curIndent > 0)) |
{ |
brush.Color = fragment.backColor; |
g.FillRectangle(brush, indent * fontWidth, drawLine * fontHeight, |
g.FillRectangle(brush, indent * fontWidth, drawLine * fontHeight, |
(float)Math.Ceiling((drawLen + curIndent) * fontWidth), fontHeight); |
} |
|
932,13 → 934,13 |
selEnd = (lineNumber == selEndLine) ? selEndPos - curCol : colsVisible; |
|
int selBeginBack = Math.Max(indent, selBegin); |
int selLen = (j == lineLen-1) ? (selEnd - selBeginBack) |
int selLen = (j == lineLen-1) ? (selEnd - selBeginBack) |
: Math.Min(drawLen + curIndent, selEnd - selBeginBack); |
|
if(selLen > 0) |
{ |
brush.Color = SystemColors.Highlight; |
g.FillRectangle(brush, selBeginBack * fontWidth, drawLine * fontHeight, |
g.FillRectangle(brush, selBeginBack * fontWidth, drawLine * fontHeight, |
(float)Math.Ceiling(selLen* fontWidth), fontHeight); |
} |
} |
969,7 → 971,7 |
} |
} |
|
if(s1 != null) |
if(s1 != null) |
{ |
brush.Color = fragment.color; |
g.DrawString(s1, font, brush, indent * fontWidth, drawLine * fontHeight, fontMeasureFormat); |
976,7 → 978,7 |
p2 = s1.Length; |
} |
|
if(s2 != null) |
if(s2 != null) |
{ |
brush.Color = SystemColors.HighlightText; |
g.DrawString(s2, font, brush, (indent + p2) * fontWidth, drawLine * fontHeight, fontMeasureFormat); |
983,7 → 985,7 |
p3 = p2 + s2.Length; |
} |
|
if(s3 != null) |
if(s3 != null) |
{ |
brush.Color = fragment.color; |
g.DrawString(s3, font, brush, (indent + p3) * fontWidth, drawLine * fontHeight, fontMeasureFormat); |
1049,7 → 1051,7 |
|
public string SelectedText |
{ |
get |
get |
{ |
lock(this) |
{ |
1075,7 → 1077,7 |
} |
else |
{ |
for(int j = fragment.indent - 1; j >= 0; j--) |
for(int j = fragment.indent - 1; j >= 0; j--) |
{ |
if(cur >= begin && cur < end) b.Append(' '); |
cur++; |
1082,7 → 1084,7 |
} |
} |
|
if(fragment.text != null) |
if(fragment.text != null) |
{ |
int curEnd = cur + fragment.text.Length; |
if(begin <= cur && curEnd <= end) |
1136,7 → 1138,7 |
{ |
curCol = 0; |
} |
else |
else |
{ |
curCol = pos; |
if(curCol < 0) curCol = 0; |
1163,7 → 1165,7 |
case Keys.Home: |
case Keys.End: |
return true; |
|
|
default: |
return base.IsInputKey(keyData); |
} |
1186,7 → 1188,7 |
MoveByVertical(-linesVisible, true); |
} |
break; |
|
|
case Keys.Down: |
lock(this) |
{ |
1193,7 → 1195,7 |
MoveByVertical(1, true); |
} |
break; |
|
|
case Keys.Up: |
lock(this) |
{ |
1200,7 → 1202,7 |
MoveByVertical(-1, true); |
} |
break; |
|
|
case Keys.Right: |
lock(this) |
{ |
1207,7 → 1209,7 |
MoveByHorizontal(1, true); |
} |
break; |
|
|
case Keys.Left: |
lock(this) |
{ |
1214,7 → 1216,7 |
MoveByHorizontal(-1, true); |
} |
break; |
|
|
case Keys.Home: |
lock(this) |
{ |
1222,7 → 1224,7 |
MoveToVertical(0, true); |
} |
break; |
|
|
case Keys.End: |
lock(this) |
{ |
1230,7 → 1232,7 |
MoveToVertical(linesCount - linesVisible + 1, true); |
} |
break; |
|
|
default: |
base.OnKeyDown(e); |
break; |
1276,13 → 1278,13 |
|
protected override void OnMouseMove(MouseEventArgs e) |
{ |
if(e.Button == MouseButtons.Left) |
if(e.Button == MouseButtons.Left) |
{ |
lock(this) |
{ |
UpdateSelectionEnd(e.X, e.Y); |
// FIXME scroll if selection is dragged outside of the control, use timer to scroll |
if(e.Y > this.ClientSize.Height && fontWidth > 0) |
if(e.Y > this.ClientSize.Height && fontWidth > 0) |
{ |
MoveToVertical(selEndLine - linesVisible + 1, true); |
} |
1339,7 → 1341,7 |
{ |
case WM_VSCROLL: |
vScrollBar.HandleWindowMessage(ref m); |
break; |
break; |
|
case WM_HSCROLL: |
hScrollBar.HandleWindowMessage(ref m); |
1389,7 → 1391,7 |
case WM_VSCROLL: |
if(!vertical) |
throw new ArgumentException("I'm horizontal scroll bar, can not handle vertical scroll"); |
break; |
break; |
|
case WM_HSCROLL: |
if(vertical) |
1406,7 → 1408,7 |
|
switch(cmd) |
{ |
case SB_LINEDOWN: |
case SB_LINEDOWN: |
type = ScrollEventType.SmallIncrement; |
currentValue += smallChange; |
update = true; |
1413,7 → 1415,7 |
break; |
|
case SB_LINEUP: |
type = ScrollEventType.SmallDecrement; |
type = ScrollEventType.SmallDecrement; |
currentValue -= smallChange; |
update = true; |
break; |
1430,28 → 1432,28 |
update = true; |
break; |
|
case SB_TOP: |
case SB_TOP: |
type = ScrollEventType.First; |
currentValue = minimum; |
update = true; |
break; |
|
case SB_BOTTOM: |
case SB_BOTTOM: |
type = ScrollEventType.Last; |
currentValue = maximum; |
update = true; |
break; |
|
case SB_ENDSCROLL: |
type = ScrollEventType.EndScroll; |
case SB_ENDSCROLL: |
type = ScrollEventType.EndScroll; |
break; |
|
case SB_THUMBTRACK: |
case SB_THUMBTRACK: |
type = ScrollEventType.ThumbTrack; |
currentValue = GetTrackPos(); |
break; |
|
case SB_THUMBPOSITION: |
case SB_THUMBPOSITION: |
type = ScrollEventType.ThumbPosition; |
currentValue = GetTrackPos(); |
update = true; |
1468,7 → 1470,7 |
|
private int GetTrackPos() |
{ |
lock(this) |
lock(this) |
{ |
scrollInfo.fMask = SIF_TRACKPOS; |
GetScrollInfo(owner.Handle, vertical ? SB_VERT : SB_HORZ, ref scrollInfo); |
1478,7 → 1480,7 |
|
public int Value |
{ |
get |
get |
{ |
return currentValue; |
} |
1493,8 → 1495,8 |
public bool ShowAlways |
{ |
get { return showAlways; } |
set |
{ |
set |
{ |
showAlways = value; |
SetRange(false); |
} |
1502,7 → 1504,7 |
|
public int Minimum |
{ |
get |
get |
{ |
return minimum; |
} |
1516,7 → 1518,7 |
|
public int Maximum |
{ |
get |
get |
{ |
return maximum; |
} |
1541,7 → 1543,7 |
|
private void SetRange(bool setPos) |
{ |
lock(this) |
lock(this) |
{ |
scrollInfo.fMask = SIF_RANGE | SIF_PAGE; |
if(showAlways) scrollInfo.fMask |= SIF_DISABLENOSCROLL; |
1549,7 → 1551,7 |
scrollInfo.nMax = maximum; |
scrollInfo.nPage = (uint)largeChange; |
|
if(setPos || currentValue < minimum || currentValue > maximum) |
if(setPos || currentValue < minimum || currentValue > maximum) |
{ |
if(currentValue < minimum) currentValue = minimum; |
if(currentValue > maximum) currentValue = maximum; |
1566,10 → 1568,10 |
SetScrollInfo(owner.Handle, vertical ? SB_VERT : SB_HORZ, ref scrollInfo, true); |
} |
} |
|
|
public int SmallChange |
{ |
get |
get |
{ |
return smallChange; |
} |
1583,7 → 1585,7 |
|
public int LargeChange |
{ |
get |
get |
{ |
return largeChange; |
} |
1593,7 → 1595,7 |
if(value < 0) throw new ArgumentException("LargeChange must be non-negative"); |
largeChange = value; |
|
lock(this) |
lock(this) |
{ |
scrollInfo.fMask = SIF_PAGE; |
if(showAlways) scrollInfo.fMask |= SIF_DISABLENOSCROLL; |
1610,7 → 1612,7 |
if(currentValue < minimum) currentValue = minimum; |
if(currentValue > maximum) currentValue = maximum; |
|
lock(this) |
lock(this) |
{ |
scrollInfo.fMask = SIF_POS; |
if(showAlways) scrollInfo.fMask |= SIF_DISABLENOSCROLL; |
1621,9 → 1623,9 |
|
protected virtual void OnScroll(ScrollEventArgs e) |
{ |
if(Scroll != null) |
if(Scroll != null) |
{ |
Scroll(this, e); |
Scroll(this, e); |
} |
} |
|
1656,15 → 1658,15 |
private const uint SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS); |
|
/* |
typedef struct tagSCROLLINFO { |
UINT cbSize; |
UINT fMask; |
int nMin; |
int nMax; |
UINT nPage; |
int nPos; |
int nTrackPos; |
} SCROLLINFO, *LPSCROLLINFO; |
typedef struct tagSCROLLINFO { |
UINT cbSize; |
UINT fMask; |
int nMin; |
int nMax; |
UINT nPage; |
int nPos; |
int nTrackPos; |
} SCROLLINFO, *LPSCROLLINFO; |
typedef SCROLLINFO CONST *LPCSCROLLINFO; |
*/ |
|
1671,17 → 1673,17 |
[StructLayout(LayoutKind.Sequential, Pack=4, CharSet=CharSet.Auto)] |
private struct SCROLLINFO |
{ |
public uint cbSize; |
public uint fMask; |
public int nMin; |
public int nMax; |
public uint nPage; |
public int nPos; |
public int nTrackPos; |
public uint cbSize; |
public uint fMask; |
public int nMin; |
public int nMax; |
public uint nPage; |
public int nPos; |
public int nTrackPos; |
} |
|
/* |
BOOL GetScrollInfo( |
BOOL GetScrollInfo( |
HWND hwnd, |
int fnBar, |
LPSCROLLINFO lpsi |