Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 1289 → Rev 1290

/TCPproxy/trunk/MainForm.cs
611,8 → 611,20
 
// save default values
defaultCaption = this.Text;
}
 
 
messagesBox.BeginUpdate();
messagesBox.Clear();
 
for(int i = 0; i < 50; ++i) {
messagesBox.AppendNewLine();
messagesBox.AppendText(String.Format("Line {0} 12345689 12345689 12345689 12345689 12345689 12345689 12345689 12345689 12345689 12345689 12345689",
i+1), Color.Black, Color.Transparent, false, false, 0, 0);
}
 
messagesBox.EndUpdate();
}
 
protected override void Dispose(bool disposing)
{
clearing = true;
950,7 → 962,9
int winTop = (int)subkey.GetValue("Window.Top", -1);
int winLeft = (int)subkey.GetValue("Window.Left", -1);
 
if(winTop == -1 || winLeft == -1) {
if(winTop < 0 || winLeft < 0
|| winTop >= SystemInformation.WorkingArea.Height || winLeft >= SystemInformation.WorkingArea.Width)
{
this.StartPosition = FormStartPosition.WindowsDefaultBounds;
}
else {
1437,7 → 1451,7
messageView.Nodes.Add(treeNode);
treeNode.EnsureVisible();
if(messageView.Nodes.Count == 1) {
messageView.SelectedNode = messageView.Nodes[0];
//messageView.SelectedNode = messageView.Nodes[0];
}
}
 
/TCPproxy/trunk/ViewControl.cs
15,24 → 15,263
// FIXME move markers and selection when text is changed
public class ViewControl : Control
{
private class DisplayMeta
{
private int linesVisible = 0;
public int LinesVisible
{
get { return linesVisible; }
set { linesVisible = value; }
}
 
private int colsVisible = 0;
public int ColsVisible
{
get { return colsVisible; }
set { colsVisible = value; }
}
 
public int VisibleLength
{
get { return (colsVisible - 2); }
}
 
}
 
private class Line
{
public class SublinesCountChangedEventArgs : EventArgs
{
public int oldSublinesCount;
public int newSublinesCount;
}
 
public delegate void SublinesCountChangedEventHandler(object sender, SublinesCountChangedEventArgs e);
 
public static int NEW_LINE_LENGTH = 20;
 
private DisplayMeta displayMeta;
private Lines owner;
private Color backColor;
public Color BackColor
{
get { return backColor; }
set { backColor = value; }
}
 
private LineFragment[] fragments;
public LineFragment[] Fragments
{
get { return fragments; }
set {
fragments = value;
 
length = 0;
foreach(LineFragment fragment in fragments) {
length += fragment.indent + (fragment.text == null ? 0 : fragment.text.Length);
}
RecalcSublinesCount();
}
}
 
private int length;
public int Length
{
get { return length; }
}
 
private int sublinesCount;
public int SublinesCount
{
get { return sublinesCount; }
}
 
private int fragmentsCount;
public int FragmentsCount
{
get { return fragmentsCount; }
}
 
public Line(DisplayMeta displayMeta, Color backColor)
: this(displayMeta, backColor, new LineFragment[Line.NEW_LINE_LENGTH])
{
}
 
public Line(DisplayMeta displayMeta, Color backColor, LineFragment[] fragments)
{
this.displayMeta = displayMeta;
this.BackColor = backColor;
this.Fragments = fragments;
}
 
public event SublinesCountChangedEventHandler SublinesCountChanged;
 
public void EnsureFragmentAppend()
{
if(fragments.Length == fragmentsCount)
{
LineFragment[] newFragments = new LineFragment[fragmentsCount * 2];
Array.Copy(fragments, 0, newFragments, 0, fragmentsCount);
fragments = newFragments;
}
}
 
public void Append(LineFragment f)
{
EnsureFragmentAppend();
 
fragments[fragmentsCount++] = f;
 
length += f.indent + (f.text == null ? 0 : f.text.Length);
RecalcSublinesCount();
}
 
public void Insert(int index, LineFragment f)
{
LineFragment[] newFragments = new LineFragment[fragmentsCount + 1];
if(index > 0) {
Array.Copy(newFragments, 0, newFragments, 0, index);
}
if(fragmentsCount > index) {
Array.Copy(newFragments, index, newFragments, index+1, fragmentsCount - index);
}
 
fragments = newFragments;
 
length += f.indent + (f.text == null ? 0 : f.text.Length);
RecalcSublinesCount();
}
 
public void Delete(int beginFragment, int endFragment)
{
LineFragment[] newFragments = new LineFragment[fragmentsCount - endFragment + beginFragment];
if(beginFragment > 0) {
Array.Copy(fragments, 0, newFragments, 0, beginFragment);
}
if(endFragment < fragmentsCount) {
Array.Copy(fragments, endFragment, newFragments, beginFragment, fragmentsCount - endFragment);
}
 
Fragments = newFragments; // recalc length and count here
}
 
public void RecalcSublinesCount()
{
int newSublinesCount = (length - 1) / displayMeta.VisibleLength + 1;
if(newSublinesCount != sublinesCount) {
SublinesCountChangedEventArgs e = new SublinesCountChangedEventArgs();
e.oldSublinesCount = sublinesCount;
e.newSublinesCount = newSublinesCount;
 
sublinesCount = newSublinesCount;
 
if(SublinesCountChanged != null) {
SublinesCountChanged(this, e);
}
}
}
 
public void Truncate()
{
LineFragment[] newFragments = new LineFragment[fragmentsCount];
Array.Copy(fragments, 0, newFragments, 0, fragmentsCount);
fragments = newFragments;
}
}
 
private class Lines
{
private ArrayList lines = new ArrayList();
 
Line.SublinesCountChangedEventHandler sublinesCountChangedEventHandler;
 
private void LineSublinesCountChanged(object sender, Line.SublinesCountChangedEventArgs e)
{
sublinesCount += e.newSublinesCount - e.oldSublinesCount;
}
 
public Lines()
{
sublinesCountChangedEventHandler = new Line.SublinesCountChangedEventHandler(LineSublinesCountChanged);
}
 
public Line this[int index]
{
get { return (lines[index] as Line); }
}
 
public int Count
{
get { return lines.Count; }
}
 
private int sublinesCount;
public int SublinesCount
{
get { return sublinesCount; }
}
 
public void Add(Line line)
{
sublinesCount += line.SublinesCount;
line.SublinesCountChanged += sublinesCountChangedEventHandler;
 
lines.Add(line);
}
 
public void Insert(int index, Line line)
{
sublinesCount += line.SublinesCount;
line.SublinesCountChanged += sublinesCountChangedEventHandler;
 
lines.Insert(index, line);
}
 
public void RemoveAt(int index)
{
this[index].SublinesCountChanged -= sublinesCountChangedEventHandler;
sublinesCount -= this[index].SublinesCount;
lines.RemoveAt(index);
}
 
public IEnumerator GetEnumerator()
{
return lines.GetEnumerator();
}
 
public void RecalcSublinesCount()
{
sublinesCount = 0;
 
foreach(Line line in lines) {
line.RecalcSublinesCount();
sublinesCount += line.SublinesCount;
}
}
}
 
private struct LineFragment
{
public string text;
public Color color;
public Color backColor;
public bool italic;
public bool bold;
public int indent;
public int wrapIndent;
public string text;
public Color color;
public Color backColor;
public bool italic;
public bool bold;
public int indent;
public int wrapIndent;
}
 
private class ViewControlState
{
public bool deep;
public ArrayList lineBackColors;
public ArrayList lineFragments;
public Lines lines;
public ArrayList validMarkers;
public int curLine;
public int curSubline;
public int curCol;
public int selBeginLineOrig;
public int selBeginPosOrig;
53,20 → 292,14
}
}
 
private static int NEW_LINE_LENGTH = 20;
 
private ArrayList lineBackColors = new ArrayList();
private ArrayList lineFragments = new ArrayList();
private int lastLineLen = 0;
private int linesCount = 0;
private int linesCountToDisplay = 0;
private DisplayMeta displayMeta = new DisplayMeta();
private Lines lines = new Lines();
private int maxLineLength = 0;
 
private int curLine = 0;
private int curSubline = 0;
private int curCol = 0;
private bool updateBlocked = false;
private int linesVisible = 0;
private int colsVisible = 0;
private float fontWidth = -1.0f;
private float fontHeight = -1.0f;
private bool wordWrap = false;
147,14 → 380,11
{
lock(this)
{
lineBackColors = new ArrayList();
lineFragments = new ArrayList();
lines = new Lines();
validMarkers = new ArrayList();
lastLineLen = 0;
linesCount = 0;
linesCountToDisplay = 0;
maxLineLength = 0;
curLine = 0;
curSubline = 0;
curCol = 0;
selBeginLine = -1;
selBeginPos = -1;
173,18 → 403,38
{
if(!updateBlocked)
{
vScrollBar.Update(curLine, 0, linesCountToDisplay, 1, 1);
vScrollBar.Update(CalcVScrollBarPos(), 0, CalcVScrollBarMaximum(), 1, 1);
UpdateHScrollBar();
Invalidate();
}
}
 
private void SetVScrollBarMaximum()
{
if(!updateBlocked)
{
vScrollBar.Maximum = CalcVScrollBarMaximum();
}
}
 
private int CalcVScrollBarMaximum()
{
//return (linesCountToDisplay > linesVisible ? linesCountToDisplay - linesVisible : 0);
return (wordWrap ? lines.SublinesCount : lines.Count);
}
 
private int CalcVScrollBarPos()
{
//return (curLine > linesVisible ? curLine - linesVisible : 0);
return curLine;
}
 
private void UpdateHScrollBar()
{
if(wordWrap)
hScrollBar.Update(0, 0, 0, 1, 1);
else
hScrollBar.Update(curCol, 0, maxLineLength + 2, 1, colsVisible);
hScrollBar.Update(curCol, 0, maxLineLength + 2, 1, displayMeta.ColsVisible);
}
 
// FIXME allow to save 'frozen' state
197,10 → 447,10
lock(this)
{
state.deep = deep;
state.lineBackColors = lineBackColors;
state.lineFragments = lineFragments;
state.lines = lines;
state.validMarkers = validMarkers;
state.curLine = curLine;
state.curSubline = curSubline;
state.curCol = curCol;
state.selBeginLineOrig = selBeginLineOrig;
state.selBeginPosOrig = selBeginPosOrig;
220,35 → 470,23
 
if(s.deep) throw new NotImplementedException("Deep restore is not yet implemented");
 
if(lineBackColors.Count != lineFragments.Count) throw new ArgumentException("Wrong state");
 
lock(this)
{
BeginUpdate();
 
lineBackColors = s.lineBackColors;
lineFragments = s.lineFragments;
linesCount = lineFragments.Count;
RecalcLinesCountToDisplay();
lines = s.lines;
 
validMarkers = s.validMarkers;
 
lastLineLen = (linesCount > 0) ? ((LineFragment[])lineFragments[linesCount-1]).Length : 0;
 
maxLineLength = 0;
foreach(LineFragment[] line in lineFragments)
{
int lineLength = 0;
foreach(LineFragment frag in line)
{
lineLength += frag.indent + (frag.text == null ? 0 : frag.text.Length);
}
if(lineLength > maxLineLength) maxLineLength = lineLength;
foreach(Line line in lines) {
if(line.Length > maxLineLength) maxLineLength = line.Length;
}
 
if(restorePosition)
{
curLine = s.curLine;
curSubline = s.curSubline;
curCol = s.curCol;
selBeginLineOrig = s.selBeginLineOrig;
selBeginPosOrig = s.selBeginPosOrig;
258,6 → 496,7
else
{
curLine = 0;
curSubline = 0;
curCol = 0;
selBeginLineOrig = -1;
selBeginPosOrig = -1;
276,8 → 515,8
 
lock(this)
{
marker.beginLine = linesCount-1;
marker.beginPos = lastLineLen;
marker.beginLine = lines.Count - 1;
marker.beginPos = lines[lines.Count-1].FragmentsCount;
 
validMarkers.Add(new WeakReference(marker));
}
291,8 → 530,8
{
TextMarker m = GetTextMarker(marker);
 
m.endLine = linesCount-1;
m.endPos = lastLineLen;
m.endLine = lines.Count - 1;
m.endPos = lines[lines.Count-1].FragmentsCount;
}
}
 
319,18 → 558,16
{
lock(this)
{
LineFragment[] line = null;
int lineLen = 0;
Line line = null;
LineFragment fragment;
 
for(int i = linesCount - 1; i >= 0; i--)
for(int i = lines.Count - 1; i >= 0; i--)
{
line = (LineFragment[])lineFragments[i];
lineLen = (i == linesCount - 1) ? lastLineLen : line.Length;
if(lineLen > 0) break;
line = lines[i];
if(line.FragmentsCount > 0) break;
}
 
if(line == null || lineLen == 0)
if(line == null || line.FragmentsCount == 0)
{
fragment = new LineFragment();
fragment.color = this.ForeColor;
342,7 → 579,7
}
else
{
fragment = line[lineLen-1];
fragment = line.Fragments[line.FragmentsCount-1];
fragment.indent = 0;
}
 
372,48 → 609,22
// always called in lock(this)
private void AppendText(LineFragment fragment)
{
LineFragment[] lastLine = (linesCount > 0) ? (LineFragment[])lineFragments[linesCount-1] : null;
Line lastLine = (lines.Count > 0) ? lines[lines.Count-1] : AddEmptyLine(Color.Transparent);
 
if(lastLine == null)
{
lastLine = AddEmptyLine(Color.Transparent);
}
else if(lastLine.Length == lastLineLen)
{
LineFragment[] newLine = new LineFragment[lastLineLen * 2];
Array.Copy(lastLine, 0, newLine, 0, lastLineLen);
lastLine = newLine;
lineFragments[linesCount-1] = lastLine;
}
lastLine.Append(fragment);
 
lastLine[lastLineLen++] = fragment;
 
int lineLength = 0;
for(int i = 0; i < lastLineLen; i++)
{
lineLength += lastLine[i].indent + (lastLine[i].text == null ? 0 : lastLine[i].text.Length);
}
if(wordWrap && lineLength > 0) {
linesCountToDisplay += (lineLength - 1) / GetVisibleLength();
}
if(lineLength > maxLineLength)
{
maxLineLength = lineLength;
if(lastLine.Length > maxLineLength) {
maxLineLength = lastLine.Length;
if(!updateBlocked && !wordWrap) hScrollBar.Maximum = maxLineLength + 2;
}
 
if(!updateBlocked)
{
vScrollBar.Maximum = linesCountToDisplay;
if(curLine + linesVisible + 1 >= lastLineLen) Invalidate();
if(!updateBlocked) {
if(curLine + displayMeta.LinesVisible + 1 >= lines.Count) Invalidate();
}
 
SetVScrollBarMaximum();
}
 
private int GetVisibleLength()
{
return (colsVisible - 2);
}
 
public void AppendNewLine()
{
AppendNewLine(Color.Transparent);
423,7 → 634,7
{
lock(this)
{
SaveLastLine();
TruncateLastLine();
AddEmptyLine(backColor);
}
}
455,13 → 666,11
}
if(!isValid) throw new ArgumentException("Invalid marker");
 
if(m.beginLine > linesCount)
if(m.beginLine > lines.Count)
throw new ArgumentException("Wrong marker");
 
LineFragment[] line = (linesCount > 0) ? (LineFragment[])lineFragments[m.beginLine] : null;
int lineLen = (linesCount == 0 || m.beginLine == linesCount-1) ? lastLineLen : line.Length;
 
if(m.beginPos > lineLen)
int lineCount = (lines.Count == 0) ? 0 : lines[m.beginLine].FragmentsCount;
if(m.beginPos > lineCount)
throw new ArgumentException("Wrong marker");
 
return m;
479,14 → 688,12
// delete the middle
for(int i = m.beginLine + 1; i < m.endLine; i++)
{
lineFragments.RemoveAt(m.beginLine - lineDeleted + 1);
lineBackColors.RemoveAt(m.beginLine - lineDeleted + 1);
linesCount--;
lines.RemoveAt(m.beginLine - lineDeleted + 1);
}
if(m.endLine > m.beginLine) lineDeleted += m.endLine - m.beginLine - 1;
 
// delete the last line
if(m.beginLine != m.endLine && m.endLine < linesCount && m.endPos > 0)
if(m.beginLine != m.endLine && m.endLine < lines.Count && m.endPos > 0)
DeleteLinePart(m.endLine - lineDeleted, 0, m.endPos);
 
// update screen
503,30 → 710,21
 
private int DeleteLinePart(int lineNum, int begin, int end)
{
int deleted = 0;
LineFragment[] line = (LineFragment[])lineFragments[lineNum];
int lineLen = (lineNum == linesCount - 1) ? lastLineLen : line.Length;
int deleted = 0;
Line line = lines[lineNum];
 
if(end == 0) return 0;
 
if(end < 0) end = lineLen;
if(end < 0) end = line.FragmentsCount;
 
if(begin == 0 && end == lineLen)
{
if(begin == 0 && end == line.FragmentsCount) {
// delete whole line
deleted = 1;
lineFragments.RemoveAt(lineNum);
lineBackColors.RemoveAt(lineNum);
linesCount--;
lines.RemoveAt(lineNum);
}
else
{
else {
// delete part of line
LineFragment[] newLine = new LineFragment[(lineNum == linesCount - 1) ? line.Length : lineLen - end + begin];
if(begin > 0) Array.Copy(line, 0, newLine, 0, begin);
if(end < lineLen) Array.Copy(line, end, newLine, begin, lineLen - end);
if(lineNum == linesCount - 1) lastLineLen = lineLen - end + begin;
lineFragments[lineNum] = newLine;
line.Delete(begin, end);
}
 
return deleted;
541,7 → 739,7
 
// FIXME implement for multiple lines and fragments
 
LineFragment[] line = (LineFragment[])lineFragments[m.beginLine];
LineFragment[] line = lines[m.beginLine].Fragments;
LineFragment fragment = line[m.beginPos];
 
if(fragment.text == text && fragment.color == color && fragment.backColor == backColor
563,7 → 761,7
 
if(!updateBlocked)
{
if(m.beginLine >= curLine && m.beginLine <= curLine + linesVisible + 1) Invalidate();
if(m.beginLine >= curLine && m.beginLine <= curLine + displayMeta.LinesVisible + 1) Invalidate();
}
}
}
576,69 → 774,34
{
TextMarker m = GetTextMarker(marker);
 
LineFragment[] line = (linesCount > m.endLine) ? (LineFragment[])lineFragments[m.endLine] : null;
LineFragment fragment = new LineFragment();
Line line = (lines.Count > m.endLine) ? lines[m.endLine] : null;
LineFragment newFragment = new LineFragment();
 
fragment.text = text;
fragment.color = color;
fragment.backColor = backColor;
fragment.italic = italic;
fragment.bold = bold;
fragment.indent = indent;
fragment.wrapIndent = wrapIndent;
newFragment.text = text;
newFragment.color = color;
newFragment.backColor = backColor;
newFragment.italic = italic;
newFragment.bold = bold;
newFragment.indent = indent;
newFragment.wrapIndent = wrapIndent;
 
if(line == null)
{
if(line == null) {
line = AddEmptyLine(Color.Transparent);
lastLineLen++;
}
else if(m.endLine == linesCount - 1)
{
if(line.Length <= lastLineLen || m.endPos < lastLineLen)
{
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.Insert(m.endPos, newFragment);
 
line = newLine;
lineFragments[m.endLine] = line;
}
lastLineLen++;
}
else
{
LineFragment[] newLine = new LineFragment[line.Length + 1];
if(m.endPos > 0) Array.Copy(line, 0, newLine, 0, m.endPos);
if(line.Length > m.endPos) Array.Copy(line, m.endPos, newLine, m.endPos+1, line.Length - m.endPos);
line = newLine;
lineFragments[m.endLine] = line;
}
 
line[m.endPos] = fragment;
 
// recalc text width
int lineLength = 0;
int newLineLen = (m.endLine == linesCount - 1) ? lastLineLen : line.Length;
for(int i = 0; i < newLineLen; i++)
{
lineLength += line[i].indent + (line[i].text == null ? 0 : line[i].text.Length);
}
if(wordWrap && lineLength > 0) {
linesCountToDisplay += (lineLength - 1) / GetVisibleLength();
}
if(lineLength > maxLineLength)
{
maxLineLength = lineLength;
if(line.Length > maxLineLength) {
maxLineLength = line.Length;
if(!updateBlocked && !wordWrap) hScrollBar.Maximum = maxLineLength + 2;
}
 
// update screen
if(!updateBlocked)
{
vScrollBar.Maximum = linesCountToDisplay;
if(m.endLine >= curLine && m.endLine <= curLine + linesVisible + 1) Invalidate();
if(!updateBlocked) {
if(m.endLine >= curLine && m.endLine <= curLine + displayMeta.LinesVisible + 1) Invalidate();
}
SetVScrollBarMaximum();
 
ShiftTextMarkers(m.endLine, m.endPos, 0, 1);
if(m.beginLine == m.endLine && m.beginPos == m.endPos) m.beginPos--; // return the begin back if empty marker
656,38 → 819,43
{
TextMarker m = GetTextMarker(marker);
 
if(m.endLine == linesCount || (m.endLine == linesCount - 1 && m.endPos == lastLineLen))
if(m.endLine == lines.Count || (m.endLine == lines.Count - 1 && m.endPos == lines[lines.Count-1].FragmentsCount))
{
SaveLastLine();
TruncateLastLine();
AddEmptyLine(backColor);
}
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)
? (int)Math.Ceiling((double)(oldLineLen - m.endPos) / NEW_LINE_LENGTH) * NEW_LINE_LENGTH
: oldLineLen - m.endPos];
Line oldLine = lines[m.endLine];
lines.RemoveAt(m.endLine);
 
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);
Line line1 = new Line(displayMeta, oldLine.BackColor, new LineFragment[m.endPos]);
Line line2 = new Line(displayMeta, backColor, new LineFragment[(m.endLine == lines.Count - 1)
? (int)Math.Ceiling((double)(oldLine.FragmentsCount - m.endPos) / Line.NEW_LINE_LENGTH) * Line.NEW_LINE_LENGTH
: oldLine.FragmentsCount - m.endPos]);
 
lineFragments[m.endLine] = line1;
lineFragments.Insert(m.endLine + 1, line2);
lineBackColors.Insert(m.endLine + 1, backColor);
if(m.endPos > 0) {
LineFragment[] fragments = new LineFragment[m.endPos];
Array.Copy(oldLine.Fragments, 0, fragments, 0, m.endPos);
line1.Fragments = fragments;
}
if(oldLine.FragmentsCount - m.endPos > 0) {
LineFragment[] fragments = new LineFragment[(m.endLine == lines.Count - 1)
? (int)Math.Ceiling((double)(oldLine.FragmentsCount - m.endPos) / Line.NEW_LINE_LENGTH) * Line.NEW_LINE_LENGTH
: oldLine.FragmentsCount - m.endPos];
Array.Copy(oldLine.Fragments, m.endPos, fragments, 0, oldLine.FragmentsCount - m.endPos);
line2.Fragments = fragments;
}
 
if(m.endLine == linesCount - 1) lastLineLen = oldLineLen - m.endPos;
linesCount++;
linesCountToDisplay++;
lines.Insert(m.endLine, line1);
lines.Insert(m.endLine+1, line2);
}
 
// update screen
if(!updateBlocked)
{
if(m.endLine >= curLine && m.endLine <= curLine + linesVisible + 1) Invalidate();
vScrollBar.Maximum = linesCountToDisplay;
if(!updateBlocked) {
if(m.endLine >= curLine && m.endLine <= curLine + displayMeta.LinesVisible + 1) Invalidate();
}
SetVScrollBarMaximum();
 
ShiftTextMarkers(m.endLine, m.endPos, 1, 0);
if(m.beginLine == m.endLine && m.beginLine == m.endLine) m.beginLine--; // return the begin back if empty marker
694,25 → 862,6
}
}
 
private void RecalcLinesCountToDisplay()
{
if(wordWrap) {
linesCountToDisplay = 0;
 
int visibleLen = GetVisibleLength();
foreach(LineFragment[] line in lineFragments) {
int lineLength = 0;
foreach(LineFragment fragment in line) {
lineLength += fragment.indent + (fragment.text == null ? 0 : fragment.text.Length);
}
linesCountToDisplay += (lineLength - 1) / visibleLen + 1;
}
}
else {
linesCountToDisplay = linesCount;
}
}
 
private void ShiftTextMarkers(int line, int pos, int lineDelta, int posDelta)
{
for(int i = validMarkers.Count-1; i >= 0; i--)
760,30 → 909,22
}
}
 
private void SaveLastLine()
private void TruncateLastLine()
{
if(linesCount > 0)
if(lines.Count > 0)
{
LineFragment[] lastLine = (LineFragment[])lineFragments[linesCount-1];
LineFragment[] newLine = new LineFragment[lastLineLen];
Array.Copy(lastLine, 0, newLine, 0, lastLineLen);
lineFragments[linesCount-1] = newLine;
lines[lines.Count-1].Truncate();
}
}
 
private LineFragment[] AddEmptyLine(Color backColor)
private Line AddEmptyLine(Color backColor)
{
LineFragment[] lastLine = new LineFragment[NEW_LINE_LENGTH];
lastLineLen = 0;
lineBackColors.Add(backColor);
lineFragments.Add(lastLine);
Line line = new Line(displayMeta, backColor);
 
linesCount++;
linesCountToDisplay++;
lines.Add(line);
SetVScrollBarMaximum();
 
if(!updateBlocked) vScrollBar.Maximum = linesCountToDisplay;
 
return lastLine;
return line;
}
 
public override Font Font
813,14 → 954,14
 
private void RecalcParams()
{
fontHeight = this.Font.GetHeight();
linesVisible = (fontHeight > 0) ? (int)Math.Ceiling(this.ClientSize.Height / fontHeight) : 0;
fontHeight = this.Font.GetHeight();
displayMeta.LinesVisible = (fontHeight > 0) ? (int)Math.Ceiling(this.ClientSize.Height / fontHeight) : 0;
 
RecalcColsVisible();
RecalcLinesCountToDisplay();
lines.RecalcSublinesCount();
 
vScrollBar.LargeChange = linesVisible;
vScrollBar.Maximum = linesCountToDisplay;
vScrollBar.LargeChange = displayMeta.LinesVisible;
SetVScrollBarMaximum();
 
UpdateHScrollBar();
}
829,14 → 970,15
{
fontWidth = g.MeasureString("x", this.Font, int.MaxValue, fontMeasureFormat).Width;
RecalcColsVisible();
RecalcLinesCountToDisplay();
 
lines.RecalcSublinesCount();
UpdateHScrollBar();
}
 
private void RecalcColsVisible()
{
colsVisible = (fontWidth > 0) ? (int)Math.Ceiling(this.ClientSize.Width / fontWidth) : 0;
if(fontWidth <= 0) UpdateFontWidth(CreateGraphics());
 
displayMeta.ColsVisible = (fontWidth > 0) ? (int)Math.Ceiling(this.ClientSize.Width / fontWidth) : 0;
}
 
protected override void OnSystemColorsChanged(EventArgs e)
872,29 → 1014,31
if(fontWidth <= 0) UpdateFontWidth(g);
 
int drawLine = 0;
for(int lineNumber = curLine; drawLine < linesVisible && lineNumber < linesCount; lineNumber++)
int linesVisible = displayMeta.LinesVisible;
int colsVisible = displayMeta.ColsVisible;
int visibleLen = displayMeta.VisibleLength;
for(int lineNumber = curLine; drawLine < linesVisible && lineNumber < lines.Count; lineNumber++)
{
Color backColor = (Color)lineBackColors[lineNumber];
LineFragment[] line = (LineFragment[])lineFragments[lineNumber];
int lineLen = (lineNumber == linesCount-1) ? lastLineLen : line.Length;
Line line = (Line)lines[lineNumber];
int lineFragCount = line.FragmentsCount;
 
// line background
if(lineLen == 0 && selBeginLine <= lineNumber && lineNumber <= selEndLine)
if(lineFragCount == 0 && selBeginLine <= lineNumber && lineNumber <= selEndLine)
{
brush.Color = SystemColors.Highlight;
g.FillRectangle(brush, 0, drawLine * fontHeight, this.ClientSize.Width, fontHeight);
}
else if(backColor != Color.Transparent)
else if(line.BackColor != Color.Transparent)
{
brush.Color = backColor;
brush.Color = line.BackColor;
g.FillRectangle(brush, 0, drawLine * fontHeight, this.ClientSize.Width, fontHeight);
}
 
int indent = 0;
int shift = curCol;
for(int j = 0; j < lineLen; j++)
for(int j = 0; j < lineFragCount; j++)
{
LineFragment fragment = line[j];
LineFragment fragment = line.Fragments[j];
int curIndent = fragment.indent;
string text = fragment.text;
int textLen = (text == null) ? 0 : text.Length;
938,7 → 1082,6
// FIXME test if wrap is in fragment indent
if(wordWrap)
{
int visibleLen = GetVisibleLength();
int availableLen = visibleLen - indent - curIndent;
if(textLen > availableLen)
{
982,7 → 1125,7
selEnd = (lineNumber == selEndLine) ? selEndPos - curCol : colsVisible;
 
int selBeginBack = Math.Max(indent, selBegin);
int selLen = (j == lineLen-1) ? (selEnd - selBeginBack)
int selLen = (j == lineFragCount-1) ? (selEnd - selBeginBack)
: Math.Min(drawLen + curIndent, selEnd - selBeginBack);
 
if(selLen > 0)
1050,9 → 1193,9
 
if(drawLine >= linesVisible) break;
 
if(backColor != Color.Transparent)
if(line.BackColor != Color.Transparent)
{
brush.Color = backColor;
brush.Color = line.BackColor;
g.FillRectangle(brush, 0, drawLine * fontHeight, this.ClientSize.Width, fontHeight);
}
}
1079,17 → 1222,12
{
selBeginLineOrig = 0;
selBeginPosOrig = 0;
selEndLineOrig = linesCount-1;
selEndLineOrig = lines.Count-1;
selEndPosOrig = 0;
 
if(linesCount > 0)
if(lines.Count > 0)
{
LineFragment[] line = (LineFragment[])lineFragments[linesCount - 1];
 
for(int i = 0; i < lastLineLen; i++)
{
selEndPosOrig += line[i].indent + ((line[i].text != null) ? line[i].text.Length : 0);
}
selEndPosOrig += lines[lines.Count - 1].Length;
}
 
UpdateSelection();
1107,17 → 1245,16
 
StringBuilder b = new StringBuilder((selEndLine - selBeginLine + 1) * maxLineLength);
 
for(int lineNumber = selBeginLine; lineNumber <= selEndLine && lineNumber < linesCount; lineNumber++)
for(int lineNumber = selBeginLine; lineNumber <= selEndLine && lineNumber < lines.Count; lineNumber++)
{
int cur = 0;
int begin = (lineNumber == selBeginLine) ? Math.Max(selBeginPos, 0) : 0;
int end = (lineNumber == selEndLine) ? Math.Max(selEndPos, 0) : int.MaxValue;
 
LineFragment[] line = (LineFragment[])lineFragments[lineNumber];
int lineLen = (lineNumber == linesCount-1) ? lastLineLen : line.Length;
for(int i = 0; i < lineLen; i++)
Line line = lines[lineNumber];
for(int i = 0; i < line.FragmentsCount; i++)
{
LineFragment fragment = line[i];
LineFragment fragment = line.Fragments[i];
 
if(cur + fragment.indent <= begin || cur >= end)
{
1147,7 → 1284,7
}
 
if(cur >= end) break;
if(i == lineLen - 1) b.Append("\r\n");
if(i == line.FragmentsCount - 1) b.Append("\r\n");
}
}
 
1169,8 → 1306,13
private void MoveToVertical(int pos, bool invalidate)
{
curLine = pos;
if(curLine + linesVisible > linesCountToDisplay) curLine = linesCountToDisplay - linesVisible + 1;
if(curLine < 0) curLine = 0;
if(curLine + displayMeta.LinesVisible > lines.SublinesCount) {
curLine = lines.SublinesCount - displayMeta.LinesVisible + 1;
}
if(curLine < 0) {
curLine = 0;
}
 
vScrollBar.Value = curLine;
if(invalidate) this.Invalidate();
}
1226,7 → 1368,7
case Keys.PageDown:
lock(this)
{
MoveByVertical(linesVisible, true);
MoveByVertical(displayMeta.LinesVisible, true);
}
break;
 
1233,7 → 1375,7
case Keys.PageUp:
lock(this)
{
MoveByVertical(-linesVisible, true);
MoveByVertical(-displayMeta.LinesVisible, true);
}
break;
 
1277,7 → 1419,7
lock(this)
{
MoveToHorizontal(0, false);
MoveToVertical(linesCountToDisplay - linesVisible + 1, true);
MoveToVertical(lines.SublinesCount - displayMeta.LinesVisible + 1, true);
}
break;
 
1334,7 → 1476,7
// FIXME scroll if selection is dragged outside of the control, use timer to scroll
if(e.Y > this.ClientSize.Height && fontWidth > 0)
{
MoveToVertical(selEndLine - linesVisible + 1, true);
MoveToVertical(selEndLine - displayMeta.LinesVisible + 1, true);
}
}
}
1613,6 → 1755,7
scrollInfo.nPage = (uint)largeChange;
}
 
if(vertical) Console.WriteLine("SetRange ({4}) {0}-{1}, {2}, {3}", scrollInfo.nMin, scrollInfo.nMax, scrollInfo.nPos, scrollInfo.nPage, setPos);
SetScrollInfo(owner.Handle, vertical ? SB_VERT : SB_HORZ, ref scrollInfo, true);
}
}