public virtual void SetStyles(IEnumerable<StyleRun> styles)
{
this.CheckInvalid();
if (styles == null)
throw new ArgumentNullException("styles");
// We need to build a byte array with a style byte for each text byte.
// Our style runs are in character lengths (good for our user) but we need to
// convert them to byte lengths (bad for us). To do that we need to analyze the
// annotation text and determine if any of our character lengths span more than
// one byte and fill the array accordingly.
int length = this._scintilla.DirectMessage(NativeMethods.SCI_ANNOTATIONGETTEXT, new IntPtr(this._lineIndex), IntPtr.Zero).ToInt32();
var textBuffer = new byte[length];
var stylesBuffer = new byte[length];
unsafe
{
fixed (byte* bp = textBuffer)
this._scintilla.DirectMessage(NativeMethods.SCI_ANNOTATIONGETTEXT, new IntPtr(this._lineIndex), new IntPtr(bp)).ToInt32();
}
Decoder decoder = this._scintilla.Encoding.GetDecoder();
StyleRun sr;
int index = 0;
int count = 1;
using (IEnumerator<StyleRun> enumerator = styles.GetEnumerator())
{
while (enumerator.MoveNext())
{
sr = enumerator.Current;
while (sr.Length > 0 && index < stylesBuffer.Length)
{
// At the end of this loop, the 'count' variable will tell us
// how many bytes there are for one character.
while (decoder.GetCharCount(textBuffer, index, count) != 1)
count++;
// For each character of text (the unit of our style runs)
// add the appropriate number of style bytes.
for (int i = 0; i < count; i++)
stylesBuffer[index + i] = (byte)sr.Style;
index += count;
count = 1;
sr.Length--;
}
}
}
// Our processing above is designed to stop if we are given more style run data
// than we have bytes to fill. If we are given less style run data than we have
// bytes to fill, the remaining bytes just get their default value of 0.
unsafe
{
fixed (byte* bp = stylesBuffer)
this._scintilla.DirectMessage(NativeMethods.SCI_ANNOTATIONSETSTYLES, new IntPtr(this._lineIndex), new IntPtr(bp));
}
}