public void OnHomeOrEnd(MultiLineEntry entry, bool home) { var linech = entry.GetLinesCharsCount(); // sepos = 1 if at end of whole text, -1 if at begin, else it will always be 0 sbyte sepos = (sbyte)(entry.CaretIndex == 0 ? -1 : entry.CaretIndex == entry.Text.Length ? 1 : 0); int caretpos = entry.CaretIndex; for (int l = 0; l < linech.Length; l++) { caretpos -= linech[l]; if (!home) { int txtlen = entry.Text.Length; if (caretpos == -1 && sepos <= 0 || sepos > 0 || txtlen == 0) { if (entry.CaretIndex == txtlen && ActiveInternalPage + 1 < BookPageCount) { _AtEnd = 1; } entry.SetCaretPosition(txtlen); break; } if (caretpos < 0 || sepos < 0) { entry.SetCaretPosition(entry.CaretIndex - caretpos - (l + 1 != linech.Length ? 1 : 0)); break; } } else { if (caretpos == 0 && (sepos == 0 || l + 2 == linech.Length && linech[l + 1] == 0) || sepos < 0) { if (entry.CaretIndex == 0 && ActiveInternalPage > 0) { _AtEnd = -1; } entry.SetCaretPosition(0); break; } if (caretpos < 0 || sepos > 0 && caretpos == 0) { entry.SetCaretPosition(entry.CaretIndex - (linech[l] + caretpos)); break; } } } }
public void Scale(MultiLineEntry entry, bool fromleft) { var linech = entry.GetLinesCharsCount(entry.Text); int caretpos = entry.CaretIndex; (int, int)selection = entry.GetSelectionArea(); bool multilinesel = selection.Item1 != -1; if (!multilinesel) { for (int l = 0; l < linech.Length && !_scale; l++) { caretpos -= linech[l]; _scale = fromleft ? caretpos == -linech[l] : caretpos == 0; } if (fromleft) { _scale = _scale && (ActiveInternalPage > 0 || entry.CaretIndex > 0); } } entry.RemoveChar(fromleft); }
public PBookData(BookGump gump) : base(0x66) { EnsureSize(256); WriteUInt(gump.LocalSerial); List <int> changed = new List <int>(); for (int i = 1; i < gump.PageChanged.Length; i++) { if (gump.PageChanged[i]) { changed.Add(i); } } WriteUShort((ushort)changed.Count); for (int i = changed.Count - 1; i >= 0; --i) { WriteUShort((ushort)changed[i]); MultiLineEntry mle = gump.m_Pages[changed[i] - 1].TxEntry; StringBuilder sb = new StringBuilder(mle.Text); int rows = 0; if (sb.Length > 0) { var lcc = mle.GetLinesCharsCount(mle.Text); rows = Math.Min(MaxBookLines, lcc.Length); int pos = lcc.Sum(); for (int l = rows - 1; l >= 0; --l) { if (pos > 0 && (lcc[l] == 0 || sb[pos - 1] != '\n')) { sb.Insert(pos, '\n'); } pos -= lcc[l]; } } var splits = sb.ToString().Split('\n'); int length = splits.Length; WriteUShort((ushort)Math.Min(length, MaxBookLines)); if (length > MaxBookLines && changed[i] >= gump.BookPageCount) { Log.Error($"Book page {changed[i]} split into too many lines: {length - MaxBookLines} Additional lines will be lost"); } for (int j = 0; j < length; j++) { // each line should BE < 53 chars long, even if 80 is admitted (the 'dot' is the least space demanding char, '.', // a page full of dots is 52 chars exactly, but in multibyte things might change in byte size!) if (j < MaxBookLines) { if (IsNewBook) { byte[] buf = Encoding.UTF8.GetBytes(splits[j]); if (buf.Length > 79) { Log.Error($"Book page {changed[i]} single line too LONG, total lenght -> {buf.Length} vs MAX 79 bytes allowed, some content might get lost"); splits[j] = splits[j].Substring(0, 79); } WriteBytes(buf, 0, buf.Length); WriteByte(0); } else { if (splits[j].Length > 79) { Log.Error($"Book page {changed[i]} single line too LONG, total lenght -> {splits[j].Length} vs MAX 79 bytes allowed, some content might get lost"); splits[j] = splits[j].Substring(0, 79); } WriteASCII(splits[j]); } } } } }