diff --git a/.gitignore b/.gitignore
index a48b0737..73d2a922 100644
--- a/.gitignore
+++ b/.gitignore
@@ -254,4 +254,8 @@ lib/_npm/
*.pyc
.serve_files_secret
\.DS_Store
-playground/*.js*
\ No newline at end of file
+playground/*.js*
+
+# Exclude JetBrains IDE files
+*.iml
+.idea
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 28a804d8..00000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 2eaf920f..00000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/typescript-compiler.xml b/.idea/typescript-compiler.xml
deleted file mode 100644
index 9b1ae4e6..00000000
--- a/.idea/typescript-compiler.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index a8418f64..00000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/webide.iml b/.idea/webide.iml
deleted file mode 100644
index 24643cc3..00000000
--- a/.idea/webide.iml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
deleted file mode 100644
index e32fb2b2..00000000
--- a/.idea/workspace.xml
+++ /dev/null
@@ -1,394 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- toggle
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
-
- false
- false
-
-
- true
- DEFINITION_ORDER
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Vue
-
-
-
-
- VueDuplicateTag
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- project
-
-
- true
-
-
-
- DIRECTORY
-
- false
-
-
-
-
-
-
-
-
-
- 1492290653407
-
-
- 1492290653407
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/css/HexViewer.css b/css/HexViewer.css
index 3a67e60e..06fddb6a 100644
--- a/css/HexViewer.css
+++ b/css/HexViewer.css
@@ -12,6 +12,7 @@
.hexViewer .header .hex .c8 { margin-left: 17px }
.hexViewer .selected { background:#0076e0; color:white }
+.hexViewer .cursor { background: #00ccff; }
.hexViewer .asciicell { padding: 2px 0 }
.hexViewer .hexRow { height:21px; }
diff --git a/src/HexViewer.ts b/src/HexViewer.ts
index 1160b01c..269ef897 100644
--- a/src/HexViewer.ts
+++ b/src/HexViewer.ts
@@ -100,11 +100,10 @@ export class HexViewer {
private content: JQuery;
private contentOuter: JQuery;
- public mouseDownOffset: number;
private canDeselect: boolean;
-
public selectionStart: number = -1;
public selectionEnd: number = -1;
+ public selectionCursor: number = -1;
public onSelectionChanged: (() => void);
private isRecursive: boolean;
@@ -125,15 +124,18 @@ export class HexViewer {
if ("dataOffset" in cell) {
if (e.type === "mousedown") {
this.canDeselect = this.selectionStart === cell.dataOffset && this.selectionEnd === cell.dataOffset;
- this.mouseDownOffset = cell.dataOffset;
this.content.on("mousemove", evt => this.cellMouseAction(evt));
- this.setSelection(cell.dataOffset, cell.dataOffset);
+ if (e.shiftKey) {
+ this.shiftCursor(cell.dataOffset);
+ } else {
+ this.setCursor(cell.dataOffset);
+ }
}
else if (e.type === "mousemove") {
- this.setSelection(this.mouseDownOffset, cell.dataOffset);
+ this.shiftCursor(cell.dataOffset);
this.canDeselect = false;
}
- else if (e.type === "mouseup" && this.canDeselect && this.mouseDownOffset === cell.dataOffset)
+ else if (e.type === "mouseup" && this.canDeselect && this.selectionStart === cell.dataOffset)
this.deselect();
this.contentOuter.focus();
@@ -177,12 +179,12 @@ export class HexViewer {
e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : null;
if (selDiff === null) return;
-
- var newSel = this.selectionStart + selDiff;
- if (newSel < 0) newSel = 0;
- else if (newSel >= this.dataProvider.length) newSel = this.dataProvider.length - 1;
-
- this.setSelection(newSel);
+ var newSel = this.selectionCursor + selDiff;
+ if (e.shiftKey) {
+ this.shiftCursor(newSel);
+ } else {
+ this.setCursor(newSel);
+ }
return false;
});
}
@@ -256,8 +258,10 @@ export class HexViewer {
hexCell.cell.dataOffset = asciiCell.dataOffset = dataOffset;
var isSelected = this.selectionStart <= dataOffset && dataOffset <= this.selectionEnd;
- $(hexCell.cell).toggleClass("selected", isSelected);
- $(asciiCell).toggleClass("selected", isSelected);
+ var isCursor = dataOffset === this.selectionCursor;
+ var targets = [hexCell.cell, asciiCell];
+ $(targets).toggleClass("selected", isSelected);
+ $(targets).toggleClass("cursor", isCursor);
var skipInt = 0;
for (var level = 0; level < this.maxLevel; level++) {
@@ -265,8 +269,16 @@ export class HexViewer {
var intIn = int && int.start <= dataOffset && dataOffset <= int.end;
var intStart = intIn && int.start === dataOffset;
var intEnd = intIn && int.end === dataOffset;
- hexCell.levels[level].className = `l${this.maxLevel - 1 - level} ${((intBaseIdx + intIdx) % 2 === 0) ? "even" : "odd"}` +
- (intIn ? ` m${level}` : "") + (intStart ? " start" : "") + (intEnd ? " end" : "") + (isSelected ? " selected" : "");
+ var classes = [
+ `l${this.maxLevel - 1 - level}`,
+ (intBaseIdx + intIdx) % 2 === 0 ? "even" : "odd",
+ ];
+ if (intIn) classes.push(`m${level}`);
+ if (intStart) classes.push("start");
+ if (intEnd) classes.push("end");
+ if (isSelected) classes.push("selected");
+ if (isCursor) classes.push("cursor");
+ hexCell.levels[level].className = classes.join(" ");
if (intEnd)
skipInt++;
@@ -291,16 +303,49 @@ export class HexViewer {
}
public deselect() {
- this.setSelection(-1, -1);
+ this.setCursor(-1);
}
- public setSelection(start: number, end?: number) {
+ public setCursor (cursor: number) {
+ this.selectionCursor = cursor;
+ this.setSelection(
+ this.selectionCursor
+ );
+ }
+
+ public shiftCursor (cursor: number) {
+ var start = this.selectionStart;
+ var end = this.selectionEnd;
+ if (this.selectionCursor === end) {
+ end = cursor;
+ } else if (this.selectionCursor === start) {
+ start = cursor;
+ }
+ this.selectionCursor = cursor;
+ this.setSelection(
+ Math.max(0, start),
+ end
+ );
+ }
+
+ public setSelection(start: number, end?: number, cursor?: number) {
if (this.isRecursive) return;
end = end || start;
var oldStart = this.selectionStart, oldEnd = this.selectionEnd;
- this.selectionStart = start < end ? start : end;
- this.selectionEnd = Math.min(start < end ? end : start, this.dataProvider.length - 1);
+ this.selectionStart = Math.min(start, end);
+ this.selectionEnd = Math.min(
+ Math.max(start, end),
+ this.dataProvider.length - 1
+ );
+
+ // is cursor out of bounds because called externally?
+ if (
+ this.selectionCursor < this.selectionStart
+ || this.selectionCursor > this.selectionEnd
+ ) cursor = this.selectionEnd;
+ if (cursor) this.selectionCursor = cursor;
+
if (this.selectionStart !== oldStart || this.selectionEnd !== oldEnd) {
this.isRecursive = true;
try {
@@ -322,4 +367,4 @@ export class HexViewer {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/v1/app.ts b/src/v1/app.ts
index 8fbdff78..661f1c24 100644
--- a/src/v1/app.ts
+++ b/src/v1/app.ts
@@ -207,7 +207,11 @@ class AppController {
onHexViewerSelectionChanged() {
//console.log("setSelection", ui.hexViewer.selectionStart, ui.hexViewer.selectionEnd);
- localStorage.setItem("selection", JSON.stringify({ start: this.ui.hexViewer.selectionStart, end: this.ui.hexViewer.selectionEnd }));
+ localStorage.setItem("selection", JSON.stringify({
+ start: this.ui.hexViewer.selectionStart,
+ end: this.ui.hexViewer.selectionEnd,
+ cursor: this.ui.hexViewer.selectionCursor
+ }));
var start = this.ui.hexViewer.selectionStart;
var hasSelection = start !== -1;
@@ -215,7 +219,7 @@ class AppController {
this.refreshSelectionInput();
if (this.ui.parsedDataTreeHandler && hasSelection && !this.selectedInTree) {
- var intervals = this.ui.parsedDataTreeHandler.intervalHandler.searchRange(this.ui.hexViewer.mouseDownOffset || start);
+ var intervals = this.ui.parsedDataTreeHandler.intervalHandler.searchRange(this.ui.hexViewer.selectionCursor || start);
if (intervals.items.length > 0) {
//console.log("selected node", intervals[0].id);
this.blockRecursive = true;
@@ -281,7 +285,11 @@ $(() => {
app.inputReady.then(() => {
var storedSelection = JSON.parse(localStorage.getItem("selection"));
if (storedSelection)
- app.ui.hexViewer.setSelection(storedSelection.start, storedSelection.end);
+ app.ui.hexViewer.setSelection(
+ storedSelection.start,
+ storedSelection.end,
+ storedSelection.cursor
+ );
});
var editDelay = new Delayed(500);