void WriteData(byte[] data, HexBoxPosition caretPos) { doc.Write(offset, data, 0, data.Length); var hexBox = (HexBox)hexBoxWeakRef.Target; if (hexBox != null) { hexBox.CaretPosition = caretPos; hexBox.BringCaretIntoView(); } }
bool TryUpdateOldTextInputCommand(HexWriteType type, HexBox hexBox, HexBoxPosition posBeforeWrite, ulong startOffset, byte[] originalData) { if (type != HexWriteType.ByteInput && type != HexWriteType.AsciiInput) return false; var cmd = (HexBoxUndoCommand)prevTextInputCmd.Target; if (cmd == null) return false; return cmd.TryAppend(hexBox, posBeforeWrite, startOffset, originalData); }
public HexBoxUndoCommand(HexBox hexBox, HexBoxPosition origCaretPos, ulong offset, byte[] origData, string descr) { this.doc = hexBox.Document; this.hexBoxWeakRef = new WeakReference(hexBox); this.origCaretPos = origCaretPos; this.newCaretPos = hexBox.CaretPosition; this.offset = offset; this.origData = origData; this.newData = doc.ReadBytes(offset, origData.Length); this.descr = descr; this.canExecute = false; }
bool TryUpdateOldTextInputCommand(HexWriteType type, HexBox hexBox, HexBoxPosition posBeforeWrite, ulong startOffset, byte[] originalData) { if (type != HexWriteType.ByteInput && type != HexWriteType.AsciiInput) { return(false); } var cmd = (HexBoxUndoCommand)prevTextInputCmd.Target; if (cmd == null) { return(false); } return(cmd.TryAppend(hexBox, posBeforeWrite, startOffset, originalData)); }
public void SetCaretPositionAndMakeVisible(ulong start, ulong end, bool resetKindPos = false) { // Make sure end address is also visible var kindPos = CaretPosition.KindPosition; if (resetKindPos) { if (CaretPosition.Kind != HexBoxPositionKind.HexByte) { kindPos = 0; } else { kindPos = start <= end ? HexBoxPosition.INDEX_HEXBYTE_FIRST : HexBoxPosition.INDEX_HEXBYTE_LAST; } } CaretPosition = new HexBoxPosition(end, CaretPosition.Kind, kindPos); CaretPosition = new HexBoxPosition(start, CaretPosition.Kind, kindPos); }
public bool TryAppend(HexBox hexBox, HexBoxPosition posBeforeWrite, ulong startOffset, byte[] originalData) { if (canNotAppend) return false; if (hexBoxWeakRef.Target != hexBox) return false; if (hexBox.Document == null) return false; if (originalData.Length == 0) return false; if (newCaretPos != posBeforeWrite) return false; if (newCaretPos.Offset > hexBox.CaretPosition.Offset) return false; if (newCaretPos.Kind != hexBox.CaretPosition.Kind) return false; if (newCaretPos.Offset == posBeforeWrite.Offset && newCaretPos.Kind == HexBoxPositionKind.HexByte && newCaretPos.KindPosition == HexBoxPosition.INDEX_HEXBYTE_LAST) { if (posBeforeWrite.Kind != HexBoxPositionKind.HexByte || posBeforeWrite.KindPosition != HexBoxPosition.INDEX_HEXBYTE_LAST) return false; if (originalData.Length != 1) return false; newData[newData.Length - 1] = (byte)hexBox.Document.ReadByte(posBeforeWrite.Offset); } else { if (newCaretPos.Offset != posBeforeWrite.Offset) return false; ulong c = hexBox.CaretPosition.Kind == HexBoxPositionKind.HexByte && hexBox.CaretPosition.KindPosition == HexBoxPosition.INDEX_HEXBYTE_LAST ? 1UL : 0; if (hexBox.CaretPosition.Offset - newCaretPos.Offset + c != (ulong)originalData.Length) return false; int origLen = newData.Length; Array.Resize(ref newData, origLen + originalData.Length); Array.Resize(ref origData, origLen + originalData.Length); for (int i = 0; i < originalData.Length; i++) { newData[origLen + i] = (byte)hexBox.Document.ReadByte(posBeforeWrite.Offset + (ulong)i); origData[origLen + i] = originalData[i]; } } newCaretPos = hexBox.CaretPosition; return true; }
int ToColumn(HexBoxPosition position) { int byteIndex = (int)GetLineByteIndex(position.Offset); switch (position.Kind) { case HexBoxPositionKind.Ascii: return (int)GetAsciiColumnIndex() + byteIndex; case HexBoxPositionKind.HexByte: return (int)GetHexByteColumnIndex() + byteIndex * 3 + position.KindPosition + 1; default: throw new InvalidOperationException(); } }
void SetCaretPosition(HexBoxPosition position, bool bringCaretIntoView = true) { if (position.Offset < StartOffset) position = MoveStart(position); else if (position.Offset > EndOffset) position = MoveEnd(position); if (!ShowAscii && position.Kind == HexBoxPositionKind.Ascii) position = new HexBoxPosition(position.Offset, HexBoxPositionKind.HexByte, 0); InitializeCaret(position); if (bringCaretIntoView) BringCaretIntoView(); }
HexBoxPosition MoveUp(HexBoxPosition position) { return SubPageBytes(position, 1); }
HexBoxPosition MoveToEndOfSelection(HexBoxPosition position) { var sel = Selection; if (sel == null) return position; switch (position.Kind) { case HexBoxPositionKind.Ascii: return HexBoxPosition.CreateAscii(sel.Value.To); case HexBoxPositionKind.HexByte: if (sel.Value.From <= sel.Value.To) return HexBoxPosition.CreateByte(sel.Value.To, HexBoxPosition.INDEX_HEXBYTE_LAST); return HexBoxPosition.CreateByte(sel.Value.To, HexBoxPosition.INDEX_HEXBYTE_FIRST); default: throw new InvalidOperationException(); } }
HexBoxPosition MoveStart(HexBoxPosition position) { switch (position.Kind) { case HexBoxPositionKind.Ascii: return HexBoxPosition.CreateAscii(StartOffset); case HexBoxPositionKind.HexByte: return HexBoxPosition.CreateByte(StartOffset, HexBoxPosition.INDEX_HEXBYTE_FIRST); default: throw new InvalidOperationException(); } }
HexBoxPosition MoveRight(HexBoxPosition position) { switch (position.Kind) { case HexBoxPositionKind.Ascii: return HexBoxPosition.CreateAscii(NumberUtils.AddUInt64(position.Offset, 1)); case HexBoxPositionKind.HexByte: if (position.KindPosition == HexBoxPosition.INDEX_HEXBYTE_LAST) { if (position.Offset >= EndOffset) return HexBoxPosition.CreateByte(EndOffset, HexBoxPosition.INDEX_HEXBYTE_LAST); return HexBoxPosition.CreateByte(NumberUtils.AddUInt64(position.Offset, 1), HexBoxPosition.INDEX_HEXBYTE_FIRST); } return HexBoxPosition.CreateByte(position.Offset, position.KindPosition + 1); default: throw new InvalidOperationException(); } }
HexBoxPosition MovePageDown(HexBoxPosition position) { return AddPageBytes(position, (ulong)WholeLinesPerPageAtLeastOne()); }
HexBoxPosition MoveLineEnd(HexBoxPosition position) { ulong bpl = (ulong)(visibleBytesPerLine == 0 ? 1 : visibleBytesPerLine); ulong newOffset = NumberUtils.AddUInt64(position.Offset - GetLineByteIndex(position.Offset), NumberUtils.SubUInt64(bpl, 1)); switch (position.Kind) { case HexBoxPositionKind.Ascii: return HexBoxPosition.CreateAscii(newOffset); case HexBoxPositionKind.HexByte: return HexBoxPosition.CreateByte(newOffset, HexBoxPosition.INDEX_HEXBYTE_LAST); default: throw new InvalidOperationException(); } }
public bool TryAppend(HexBox hexBox, HexBoxPosition posBeforeWrite, ulong startOffset, byte[] originalData) { if (canNotAppend) { return(false); } if (hexBoxWeakRef.Target != hexBox) { return(false); } if (hexBox.Document == null) { return(false); } if (originalData.Length == 0) { return(false); } if (newCaretPos != posBeforeWrite) { return(false); } if (newCaretPos.Offset > hexBox.CaretPosition.Offset) { return(false); } if (newCaretPos.Kind != hexBox.CaretPosition.Kind) { return(false); } if (newCaretPos.Offset == posBeforeWrite.Offset && newCaretPos.Kind == HexBoxPositionKind.HexByte && newCaretPos.KindPosition == HexBoxPosition.INDEX_HEXBYTE_LAST) { if (posBeforeWrite.Kind != HexBoxPositionKind.HexByte || posBeforeWrite.KindPosition != HexBoxPosition.INDEX_HEXBYTE_LAST) { return(false); } if (originalData.Length != 1) { return(false); } newData[newData.Length - 1] = (byte)hexBox.Document.ReadByte(posBeforeWrite.Offset); } else { if (newCaretPos.Offset != posBeforeWrite.Offset) { return(false); } ulong c = hexBox.CaretPosition.Kind == HexBoxPositionKind.HexByte && hexBox.CaretPosition.KindPosition == HexBoxPosition.INDEX_HEXBYTE_LAST ? 1UL : 0; if (hexBox.CaretPosition.Offset - newCaretPos.Offset + c != (ulong)originalData.Length) { return(false); } int origLen = newData.Length; Array.Resize(ref newData, origLen + originalData.Length); Array.Resize(ref origData, origLen + originalData.Length); for (int i = 0; i < originalData.Length; i++) { newData[origLen + i] = (byte)hexBox.Document.ReadByte(posBeforeWrite.Offset + (ulong)i); origData[origLen + i] = originalData[i]; } } newCaretPos = hexBox.CaretPosition; return(true); }
HexBoxPosition MoveLineStart(HexBoxPosition position) { ulong newOffset = position.Offset - GetLineByteIndex(position.Offset); switch (position.Kind) { case HexBoxPositionKind.Ascii: return HexBoxPosition.CreateAscii(newOffset); case HexBoxPositionKind.HexByte: return HexBoxPosition.CreateByte(newOffset, HexBoxPosition.INDEX_HEXBYTE_FIRST); default: throw new InvalidOperationException(); } }
public void SetCaretPositionAndMakeVisible(ulong start, ulong end, bool resetKindPos = false) { // Make sure end address is also visible var kindPos = CaretPosition.KindPosition; if (resetKindPos) { if (CaretPosition.Kind != HexBoxPositionKind.HexByte) kindPos = 0; else kindPos = start <= end ? HexBoxPosition.INDEX_HEXBYTE_FIRST : HexBoxPosition.INDEX_HEXBYTE_LAST; } CaretPosition = new HexBoxPosition(end, CaretPosition.Kind, kindPos); CaretPosition = new HexBoxPosition(start, CaretPosition.Kind, kindPos); }
HexBoxPosition MovePageUp(HexBoxPosition position) { return SubPageBytes(position, (ulong)WholeLinesPerPageAtLeastOne()); }
void BringIntoView(HexBoxPosition position) { if (position.Kind == HexBoxPositionKind.HexByte && position.KindPosition == HexBoxPosition.INDEX_HEXBYTE_FIRST) { // To make sure left scrolling with the mouse works, make sure that the space // character is visible. First make it visible, and then bring the new position into // view, just in case the size of the control is so small that two chars won't fit. ScrollHorizontallyToCaret(ToColumn(position) - 1); BringIntoView2(position); } else BringIntoView2(position); }
HexBoxPosition MoveRightWord(HexBoxPosition position) { switch (position.Kind) { case HexBoxPositionKind.Ascii: return HexBoxPosition.CreateAscii(NumberUtils.AddUInt64(position.Offset, 1)); case HexBoxPositionKind.HexByte: return HexBoxPosition.CreateByte(NumberUtils.AddUInt64(position.Offset, 1), HexBoxPosition.INDEX_HEXBYTE_FIRST); default: throw new InvalidOperationException(); } }
void BringIntoView2(HexBoxPosition position) { if (position.Offset < topOffset) SetTopOffset(position.Offset); else { ulong bpl = (ulong)(visibleBytesPerLine == 0 ? 1 : visibleBytesPerLine); ulong bytesPerPage = NumberUtils.MulUInt64(bpl, (ulong)this.WholeLinesPerPage()); ulong end = NumberUtils.AddUInt64(topOffset, NumberUtils.SubUInt64(bytesPerPage, 1)); if (position.Offset > end) SetBottomOffset(position.Offset); } ScrollHorizontallyToCaret(position); }
HexBoxPosition MoveToBottom(HexBoxPosition position) { ulong lineByteIndex = GetLineByteIndex(position.Offset); ulong bpl = (ulong)(visibleBytesPerLine == 0 ? 1 : visibleBytesPerLine); int linesPerPage = WholeLinesPerPage(); ulong end = linesPerPage == 0 ? topOffset : NumberUtils.AddUInt64(topOffset, bpl * (ulong)(linesPerPage - 1)); return new HexBoxPosition(NumberUtils.AddUInt64(end, lineByteIndex), position.Kind, position.KindPosition); }
HexBoxPosition EnsureInCurrentView(HexBoxPosition position) { ulong offset = position.Offset; if (offset < topOffset) offset = NumberUtils.AddUInt64(topOffset, GetLineByteIndex(offset)); else { ulong end = NumberUtils.AddUInt64(GetBottomOffset(), GetLineByteIndex(offset)); if (offset > end) offset = end; } // If it's a really long line, make sure the caret is visible first ScrollHorizontallyToCaret(position); return new HexBoxPosition(offset, position.Kind, position.KindPosition); }
HexBoxPosition MoveToTop(HexBoxPosition position) { ulong lineByteIndex = GetLineByteIndex(position.Offset); return new HexBoxPosition(NumberUtils.AddUInt64(topOffset, lineByteIndex), position.Kind, position.KindPosition); }
void InitializeCaret(HexBoxPosition position) { double horizPos = horizCol * characterWidth; if (!IsCaretVisible(position) || visibleBytesPerLine == 0) { hexCaret.SetCaret(position, horizPos, null, null); return; } int index = (int)((position.Offset - topOffset) / (ulong)visibleBytesPerLine); if (index < 0 || index >= hexLines.Count) { hexCaret.SetCaret(position, horizPos, null, null); return; } double y = index * characterHeight; var hexLine = hexLines[index]; ulong byteIndex = position.Offset - hexLine.StartOffset; Rect? rectHex = GetCharacterRect(hexLine, y, (int)(GetHexByteColumnIndex() + byteIndex * 3 + 1 + position.KindPosition)); Rect? rectAsc = GetCharacterRect(hexLine, y, (int)(GetAsciiColumnIndex() + byteIndex)); if (!ShowAscii) rectAsc = null; if (rectHex != null && position.Kind != HexBoxPositionKind.HexByte) rectHex = new Rect(rectHex.Value.X, rectHex.Value.Y, rectHex.Value.Width * 2, rectHex.Value.Height); hexCaret.SetCaret(position, horizPos, rectHex, rectAsc); }
void ScrollHorizontallyToCaret(HexBoxPosition position) { ScrollHorizontallyToCaret(ToColumn(position)); }
bool IsCaretVisible(HexBoxPosition position) { if (hexLines.Count == 0) return false; return hexLines[0].StartOffset <= position.Offset && position.Offset <= NumberUtils.AddUInt64(hexLines[hexLines.Count - 1].StartOffset, (ulong)(visibleBytesPerLine - 1)); }
HexBoxPosition SubPageBytes(HexBoxPosition position, ulong pages) { if (visibleBytesPerLine == 0) return position; ulong pageSize = (ulong)visibleBytesPerLine; ulong pageNo = (position.Offset < StartOffset ? 0 : position.Offset - StartOffset) / pageSize; if (pageNo == 0) return position; if (pages > pageNo) pages = pageNo; ulong count = NumberUtils.MulUInt64(pages, pageSize); switch (position.Kind) { case HexBoxPositionKind.Ascii: return HexBoxPosition.CreateAscii(NumberUtils.SubUInt64(position.Offset, count)); case HexBoxPositionKind.HexByte: return HexBoxPosition.CreateByte(NumberUtils.SubUInt64(position.Offset, count), position.KindPosition); default: throw new InvalidOperationException(); } }
HexBoxPosition MoveDown(HexBoxPosition position) { return AddPageBytes(position, 1); }
void UpdateCaptureMouseSelection(ulong? startOffset, HexBoxPosition position, HexPositionUI uiPos) { SetCaretPosition(position); if (startOffset == null) return; if (Selection != null || uiPos != mouseCaptureStartPosUI) Selection = new HexSelection(startOffset.Value, position.Offset); }
public void SetCaret(HexBoxPosition position, double horizOffset, Rect? hexByteCaret, Rect? asciiCaret) { if (position == Position && this.horizOffset == horizOffset && hexByteInfo.Rect == hexByteCaret && asciiInfo.Rect == asciiCaret) return; this.position = position; this.horizOffset = horizOffset; hexByteInfo.Initialize(hexByteCaret, position.Kind == HexBoxPositionKind.HexByte); asciiInfo.Initialize(asciiCaret, position.Kind == HexBoxPositionKind.Ascii); geometriesCreated = false; // Make sure caret doesn't blink when it's moving. It looks weird when quickly moving up/down blinkIsVisible = true; Redraw(); }