2018-05-15 17:36:45 +00:00
|
|
|
/**
|
|
|
|
* @author n1474335 [n1474335@gmail.com]
|
|
|
|
* @copyright Crown Copyright 2016
|
|
|
|
* @license Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2022-07-10 22:01:22 +01:00
|
|
|
import {EditorSelection} from "@codemirror/state";
|
2022-09-16 16:00:39 +01:00
|
|
|
import {chrEncWidth} from "../../core/lib/ChrEnc.mjs";
|
2018-05-15 17:36:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Waiter to handle events related to highlighting in CyberChef.
|
|
|
|
*/
|
|
|
|
class HighlighterWaiter {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* HighlighterWaiter constructor.
|
|
|
|
*
|
|
|
|
* @param {App} app - The main view object for CyberChef.
|
|
|
|
* @param {Manager} manager - The CyberChef event manager.
|
|
|
|
*/
|
|
|
|
constructor(app, manager) {
|
|
|
|
this.app = app;
|
|
|
|
this.manager = manager;
|
|
|
|
|
2022-07-10 22:01:22 +01:00
|
|
|
this.currentSelectionRanges = [];
|
2018-05-15 17:36:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-07-10 22:01:22 +01:00
|
|
|
* Handler for selection change events in the input and output
|
2018-05-15 17:36:45 +00:00
|
|
|
*
|
2022-07-10 22:01:22 +01:00
|
|
|
* Highlights the given offsets in the input or output.
|
|
|
|
* We will only highlight if:
|
|
|
|
* - input hasn't changed since last bake
|
|
|
|
* - last bake was a full bake
|
|
|
|
* - all operations in the recipe support highlighting
|
2018-05-15 17:36:45 +00:00
|
|
|
*
|
2022-07-10 22:01:22 +01:00
|
|
|
* @param {string} io
|
|
|
|
* @param {ViewUpdate} e
|
2018-05-15 17:36:45 +00:00
|
|
|
*/
|
2022-07-10 22:01:22 +01:00
|
|
|
selectionChange(io, e) {
|
|
|
|
// Confirm we are not currently baking
|
|
|
|
if (!this.app.autoBake_ || this.app.baking) return false;
|
2018-05-15 17:36:45 +00:00
|
|
|
|
2022-07-10 22:01:22 +01:00
|
|
|
// Confirm this was a user-generated event to prevent looping
|
|
|
|
// from setting the selection in this class
|
|
|
|
if (!e.transactions[0].isUserEvent("select")) return false;
|
2018-05-15 17:36:45 +00:00
|
|
|
|
2022-07-10 22:01:22 +01:00
|
|
|
this.currentSelectionRanges = [];
|
2018-05-15 17:36:45 +00:00
|
|
|
|
2022-07-10 22:01:22 +01:00
|
|
|
// Confirm some non-empty ranges are set
|
2022-07-11 11:43:48 +01:00
|
|
|
const selectionRanges = e.state.selection.ranges;
|
2018-05-15 17:36:45 +00:00
|
|
|
|
2022-09-16 16:00:39 +01:00
|
|
|
// Adjust offsets based on the width of the character set
|
2022-10-21 18:29:52 +01:00
|
|
|
const inputCharacterWidth = chrEncWidth(this.manager.input.getChrEnc());
|
|
|
|
const outputCharacterWidth = chrEncWidth(this.manager.output.getChrEnc());
|
2022-09-16 16:00:39 +01:00
|
|
|
let ratio = 1;
|
|
|
|
if (inputCharacterWidth !== outputCharacterWidth &&
|
|
|
|
inputCharacterWidth !== 0 && outputCharacterWidth !== 0) {
|
|
|
|
ratio = io === "input" ?
|
|
|
|
inputCharacterWidth / outputCharacterWidth :
|
|
|
|
outputCharacterWidth / inputCharacterWidth;
|
|
|
|
}
|
|
|
|
|
2022-07-10 22:01:22 +01:00
|
|
|
// Loop through ranges and send request for output offsets for each one
|
|
|
|
const direction = io === "input" ? "forward" : "reverse";
|
|
|
|
for (const range of selectionRanges) {
|
|
|
|
const pos = [{
|
2022-09-16 16:00:39 +01:00
|
|
|
start: Math.floor(range.from * ratio),
|
|
|
|
end: Math.floor(range.to * ratio)
|
2022-07-10 22:01:22 +01:00
|
|
|
}];
|
|
|
|
this.manager.worker.highlight(this.app.getRecipeConfig(), direction, pos);
|
2018-05-15 17:36:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Displays highlight offsets sent back from the Chef.
|
|
|
|
*
|
2022-07-10 22:01:22 +01:00
|
|
|
* @param {Object[]} pos - The position object for the highlight.
|
2018-05-15 17:36:45 +00:00
|
|
|
* @param {number} pos.start - The start offset.
|
|
|
|
* @param {number} pos.end - The end offset.
|
|
|
|
* @param {string} direction
|
|
|
|
*/
|
|
|
|
displayHighlights(pos, direction) {
|
|
|
|
if (!pos) return;
|
2022-10-21 13:57:46 +01:00
|
|
|
if (this.manager.tabs.getActiveTab("input") !== this.manager.tabs.getActiveTab("output")) return;
|
2019-05-07 14:33:38 +01:00
|
|
|
|
2018-05-15 17:36:45 +00:00
|
|
|
const io = direction === "forward" ? "output" : "input";
|
2022-07-10 22:01:22 +01:00
|
|
|
this.highlight(io, pos);
|
2018-05-15 17:36:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2022-09-16 16:00:39 +01:00
|
|
|
* Sends selection updates to the relevant EditorView.
|
2018-05-15 17:36:45 +00:00
|
|
|
*
|
2022-07-10 22:01:22 +01:00
|
|
|
* @param {string} io - The input or output
|
|
|
|
* @param {Object[]} ranges - An array of position objects to highlight
|
|
|
|
* @param {number} ranges.start - The start offset
|
|
|
|
* @param {number} ranges.end - The end offset
|
|
|
|
*/
|
|
|
|
async highlight(io, ranges) {
|
|
|
|
if (!this.app.options.showHighlighter) return false;
|
|
|
|
if (!this.app.options.attemptHighlight) return false;
|
|
|
|
if (!ranges || !ranges.length) return false;
|
|
|
|
|
|
|
|
const view = io === "input" ?
|
|
|
|
this.manager.input.inputEditorView :
|
|
|
|
this.manager.output.outputEditorView;
|
|
|
|
|
|
|
|
// Add new SelectionRanges to existing ones
|
|
|
|
for (const range of ranges) {
|
2022-07-11 11:43:48 +01:00
|
|
|
if (typeof range.start !== "number" ||
|
|
|
|
typeof range.end !== "number")
|
|
|
|
continue;
|
|
|
|
const selection = range.end <= range.start ?
|
|
|
|
EditorSelection.cursor(range.start) :
|
|
|
|
EditorSelection.range(range.start, range.end);
|
|
|
|
|
|
|
|
this.currentSelectionRanges.push(selection);
|
2022-07-10 22:01:22 +01:00
|
|
|
}
|
2022-07-02 19:23:03 +01:00
|
|
|
|
2022-07-10 22:01:22 +01:00
|
|
|
// Set selection
|
|
|
|
if (this.currentSelectionRanges.length) {
|
2022-07-11 11:43:48 +01:00
|
|
|
try {
|
|
|
|
view.dispatch({
|
|
|
|
selection: EditorSelection.create(this.currentSelectionRanges),
|
|
|
|
scrollIntoView: true
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
// Ignore Range Errors
|
|
|
|
if (!err.toString().startsWith("RangeError")) {
|
|
|
|
console.error(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2022-07-10 22:01:22 +01:00
|
|
|
}
|
2018-05-15 17:36:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
export default HighlighterWaiter;
|