You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by rs...@apache.org on 2023/12/21 21:07:22 UTC
(daffodil-vscode) branch main updated: Implemented Indexable ByteValue Indications
This is an automated email from the ASF dual-hosted git repository.
rstrickland pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil-vscode.git
The following commit(s) were added to refs/heads/main by this push:
new d7f7088 Implemented Indexable ByteValue Indications
d7f7088 is described below
commit d7f70889a07f5769e425fb03aa260a54ad8c0a8a
Author: Davin Shearer <sc...@gmail.com>
AuthorDate: Thu Oct 19 12:14:23 2023 -0400
Implemented Indexable ByteValue Indications
- Added indexable indication array for ByteValues within the viewport displays.
- Created categorical byte indiciations values & CSS selectors.
Closes #784
---
src/dataEditor/dataEditorClient.ts | 9 ++
.../CustomByteDisplay/DataLineFeed.svelte | 155 ++++++++++--------
.../CustomByteDisplay/DataValue.svelte | 82 ++--------
.../CustomByteDisplay/SelectedByteEdit.svelte | 6 +-
.../DataDisplays/Header/DisplayHeader.svelte | 19 +--
.../components/Header/fieldsets/FileMetrics.svelte | 2 +-
.../Header/fieldsets/SearchReplace.svelte | 38 +++--
.../components/Header/fieldsets/SearchReplace.ts | 112 ++++++++++---
src/svelte/src/components/dataEditor.svelte | 7 +-
src/svelte/src/components/globalStyles.css | 2 +
src/svelte/src/components/layouts/Tooltip.svelte | 2 +-
src/svelte/src/stores/index.ts | 41 ++++-
.../ByteCategories/CategoryIndications.ts | 114 ++++++++++++++
.../src/utilities/ByteCategories/IByteCategory.ts | 84 ++++++++++
.../src/utilities/ByteCategories/IIndication.ts | 42 +++++
src/svelte/src/utilities/display.ts | 1 -
src/svelte/src/utilities/highlights.ts | 174 +++++++++++++++------
17 files changed, 638 insertions(+), 252 deletions(-)
diff --git a/src/dataEditor/dataEditorClient.ts b/src/dataEditor/dataEditorClient.ts
index 75bdede..03f9eb8 100644
--- a/src/dataEditor/dataEditorClient.ts
+++ b/src/dataEditor/dataEditorClient.ts
@@ -459,11 +459,17 @@ export class DataEditorClient implements vscode.Disposable {
case MessageCommand.undoChange:
await undo(this.omegaSessionId)
await this.sendChangesInfo()
+ this.panel.webview.postMessage({
+ command: MessageCommand.clearChanges,
+ })
break
case MessageCommand.redoChange:
await redo(this.omegaSessionId)
await this.sendChangesInfo()
+ this.panel.webview.postMessage({
+ command: MessageCommand.clearChanges,
+ })
break
case MessageCommand.profile:
@@ -525,6 +531,9 @@ export class DataEditorClient implements vscode.Disposable {
) {
await clear(this.omegaSessionId)
await this.sendChangesInfo()
+ this.panel.webview.postMessage({
+ command: MessageCommand.clearChanges,
+ })
}
break
diff --git a/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataLineFeed.svelte b/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataLineFeed.svelte
index 5dd49f1..065aed3 100644
--- a/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataLineFeed.svelte
+++ b/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataLineFeed.svelte
@@ -31,6 +31,8 @@ limitations under the License.
seekOffsetInput,
visableViewports,
dataDislayLineAmount,
+ replaceQuery,
+ searchResultsUpdated,
} from '../../../stores'
import {
EditByteModes,
@@ -62,10 +64,8 @@ limitations under the License.
type CSSThemeClass,
} from '../../../utilities/colorScheme'
import {
- selectionHighlights,
- searchResultsHighlights,
- updateSearchResultsHighlights,
- searchResultsUpdated,
+ viewportByteIndicators,
+ categoryCSSSelectors,
} from '../../../utilities/highlights'
import { bytesPerRow } from '../../../stores'
export let awaitViewportSeek: boolean
@@ -169,7 +169,7 @@ limitations under the License.
bytes: Array<ByteValue>
highlight: 'even' | 'odd'
}
-
+
enum ViewportScrollDirection {
DECREMENT = -1,
NONE = 0,
@@ -181,10 +181,13 @@ limitations under the License.
let viewportDataContainer: HTMLDivElement
let selectedByteElement: HTMLDivElement
let themeClass: CSSThemeClass
- let activeSelection: Uint8Array
let lineTopFileOffset: number
- let searchResults: Uint8Array
+ let makingSelection = false
+ $: {
+ makingSelection =
+ $selectionDataStore.startOffset >= 0 && $selectionDataStore.active === false
+ }
onMount(() => {
viewportDataContainer = document.getElementById(
CONTAINER_ID
@@ -215,13 +218,10 @@ limitations under the License.
}
$: {
- activeSelection = $selectionHighlights
- searchResults = $searchResultsHighlights
if (
- (viewportData.fileOffset >= 0 &&
- !awaitViewportSeek &&
- $dataFeedLineTop >= 0) ||
- $searchResultsUpdated
+ viewportData.fileOffset >= 0 &&
+ !awaitViewportSeek &&
+ $dataFeedLineTop >= 0
) {
if (
viewportLines.length !== 0 &&
@@ -243,6 +243,10 @@ limitations under the License.
}
}
$: byteElementWidth = byteDivWidthFromRadix(dataRadix)
+ $: viewportByteIndicators.updateSelectionIndications($selectionDataStore)
+ $: viewportByteIndicators.updateSearchIndications($searchQuery, viewportData.fileOffset)
+ $: viewportByteIndicators.updateReplaceIndications($replaceQuery, viewportData.fileOffset)
+
function generate_line_data(
startIndex: number,
@@ -359,21 +363,21 @@ limitations under the License.
: atViewportHead && !atFileHead
}
- function mousedown(event: CustomEvent<ByteSelectionEvent>) {
+ function mousedown(event: ByteSelectionEvent) {
selectionDataStore.update((selections) => {
selections.active = false
- selections.startOffset = event.detail.targetByte.offset
+ selections.startOffset = event.targetByte.offset
selections.endOffset = -1
selections.originalEndOffset = -1
return selections
})
}
- function mouseup(event: CustomEvent<ByteSelectionEvent>) {
+ function mouseup(event: ByteSelectionEvent) {
selectionDataStore.update((selections) => {
selections.active = true
- selections.endOffset = event.detail.targetByte.offset
- selections.originalEndOffset = event.detail.targetByte.offset
+ selections.endOffset = event.targetByte.offset
+ selections.originalEndOffset = event.targetByte.offset
adjust_event_offsets()
return selections
})
@@ -383,7 +387,7 @@ limitations under the License.
return
}
- set_byte_selection(event.detail)
+ setByteSelection(event)
}
function adjust_event_offsets() {
@@ -391,13 +395,15 @@ limitations under the License.
const end = $selectionDataStore.endOffset
if (start > end) {
- $selectionDataStore.startOffset = end
- $selectionDataStore.originalEndOffset = start
- $selectionDataStore.endOffset = start
+ selectionDataStore.update( selections => {
+ selections.startOffset = end
+ selections.endOffset = start
+ return selections
+ })
}
}
- function set_byte_selection(selectionEvent: ByteSelectionEvent) {
+ function setByteSelection(selectionEvent: ByteSelectionEvent) {
$focusedViewportId = selectionEvent.fromViewport
$selectedByte =
@@ -471,6 +477,47 @@ limitations under the License.
}
}
+ function mouseover_handler(e: Event) {
+ if(!makingSelection) return
+
+ const target = e.target as HTMLDivElement
+ let targetViewportIndex = parseInt(target.getAttribute('offset')!)
+
+ selectionDataStore.update((selections) => {
+ selections.endOffset = targetViewportIndex
+ adjust_event_offsets()
+ return selections
+ })
+ }
+
+ function mouseclick_handler(e: Event) {
+ const type = e.type
+ const targetElement = e.target as HTMLDivElement
+ let targetViewportIndex = parseInt(targetElement.getAttribute('offset')!)
+ let byteText: string | undefined = targetElement.innerHTML
+ let byteValue: number = byteText === undefined ? -1 : parseInt(byteText)
+
+ let targetByte: ByteValue = {
+ offset: targetViewportIndex,
+ text: byteText,
+ value: byteValue
+ }
+ const byteSelectionEvent: ByteSelectionEvent =
+ {
+ targetElement: targetElement,
+ targetByte: targetByte,
+ fromViewport: targetElement.id.includes('logical') ? 'logical' : 'physical',
+ }
+
+ switch(type) {
+ case 'mousedown':
+ mousedown(byteSelectionEvent)
+ break
+ case 'mouseup':
+ mouseup(byteSelectionEvent)
+ }
+ }
+
window.addEventListener('keydown', navigation_keydown_event)
window.addEventListener('message', (msg) => {
switch (msg.data.command) {
@@ -485,30 +532,31 @@ limitations under the License.
selectedByteElement = document.getElementById(
$selectedByte.offset.toString()
) as HTMLDivElement
-
- updateSearchResultsHighlights(
- $searchQuery.searchResults,
- viewportData.fileOffset,
- $searchQuery.byteLength
- )
}
break
}
})
+
</script>
-{#if $selectionDataStore.active && $editMode === EditByteModes.Single}
- {#key $selectedByte || selectedByteElement || dataRadix || $editorActionsAllowed === EditActionRestrictions.None}
- <SelectedByteEdit
- byte={$selectedByte}
- on:seek
- on:applyChanges
- on:handleEditorEvent
- />
- {/key}
-{/if}
-<div class="container" style:height id={CONTAINER_ID}>
+<svelte:window on:mousemove={mouseover_handler}/>
+<!-- svelte-ignore a11y-mouse-events-have-key-events -->
+<!-- svelte-ignore a11y-click-events-have-key-events -->
+<div class="container" style:height id={CONTAINER_ID}
+ on:mousedown={mouseclick_handler}
+ on:mouseup={mouseclick_handler}
+>
+ {#if $selectionDataStore.active && $editMode == EditByteModes.Single}
+ {#key $selectedByte || selectedByteElement || dataRadix || $editorActionsAllowed == EditActionRestrictions.None}
+ <SelectedByteEdit
+ byte={$selectedByte}
+ on:seek
+ on:applyChanges
+ on:handleEditorEvent
+ />
+ {/key}
+ {/if}
{#each viewportLines as viewportLine, i}
<div class={`line ${viewportLine.highlight} ${themeClass}`}>
<div class="address" id="address">
@@ -523,17 +571,10 @@ limitations under the License.
{#each viewportLine.bytes as byte}
<DataValue
{byte}
- isSelected={activeSelection[byte.offset] === 1}
- possibleSelection={activeSelection[byte.offset] === 2}
- isSearchResult={searchResults[byte.offset] >>
- activeSelection[byte.offset]}
id={'physical'}
- radix={dataRadix}
+ categoryIndicationSelectors={categoryCSSSelectors($viewportByteIndicators[byte.offset])}
width={byteElementWidth}
disabled={byte.value === -1}
- bind:selectionData={$selectionDataStore}
- on:mouseup={mouseup}
- on:mousedown={mousedown}
/>
{/each}
</div>
@@ -546,17 +587,10 @@ limitations under the License.
{#each viewportLine.bytes as byte}
<DataValue
{byte}
- isSelected={activeSelection[byte.offset] === 1}
- possibleSelection={activeSelection[byte.offset] === 2}
- isSearchResult={searchResults[byte.offset] >>
- activeSelection[byte.offset]}
+ categoryIndicationSelectors={categoryCSSSelectors($viewportByteIndicators[byte.offset])}
id={'logical'}
- radix={dataRadix}
width={byteElementWidth}
disabled={byte.value === -1}
- bind:selectionData={$selectionDataStore}
- on:mouseup={mouseup}
- on:mousedown={mousedown}
/>
{/each}
</div>
@@ -697,15 +731,6 @@ limitations under the License.
flex-direction: column;
margin: 0 5px;
}
- span.submit-bpr-input {
- font-size: 14px;
- cursor: pointer;
- margin: 0 5px;
- }
- span.submit-bpr-input:hover {
- font-weight: bold;
- cursor: pointer;
- }
div.container {
display: flex;
flex-direction: column;
diff --git a/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataValue.svelte b/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataValue.svelte
index ab12df4..e839ff1 100644
--- a/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataValue.svelte
+++ b/src/svelte/src/components/DataDisplays/CustomByteDisplay/DataValue.svelte
@@ -15,61 +15,18 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<script lang="ts">
- import { createEventDispatcher } from 'svelte'
import {
latin1Undefined,
- type ByteSelectionEvent,
type ByteValue,
type ViewportDataType,
} from './BinaryData'
- import type { SelectionData_t } from '../../../stores'
import type { ByteDivWidth } from '../../../utilities/display'
- import type { RadixValues } from '../../../stores/configuration'
- import { selectionHighlightMask } from '../../../utilities/highlights'
export let id: ViewportDataType
export let byte: ByteValue
- export let selectionData: SelectionData_t
- export let radix: RadixValues
export let disabled = false
export let width: ByteDivWidth = '20px'
- export let isSelected = false
- export let possibleSelection = false
- export let isSearchResult = 0
-
- const eventDispatcher = createEventDispatcher()
-
- let makingSelection = false
-
- $: {
- makingSelection =
- selectionData.startOffset >= 0 && selectionData.active === false
- $selectionHighlightMask = makingSelection === true ? 1 : 0
- }
-
- function mouse_enter_handle(event: MouseEvent) {
- if (!makingSelection) return
- if (disabled) {
- selectionData.endOffset = -1
- makingSelection = false
- return
- }
- selectionData.endOffset = byte.offset
- }
- function mouse_leave_handle(event: MouseEvent) {
- if (!makingSelection) return
- selectionData.endOffset = -1
- }
- function mouse_event_handle(event: MouseEvent) {
- const type = event.type
- const targetElement = event.target
- if (id === 'logical') byte.text = String.fromCharCode(byte.value)
- eventDispatcher(type, {
- targetElement: targetElement,
- targetByte: byte,
- fromViewport: id,
- } as ByteSelectionEvent)
- }
+ export let categoryIndicationSelectors: string
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
@@ -78,33 +35,21 @@ limitations under the License.
{:else if id === 'physical'}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
- class="byte"
- class:isSelected
- class:isSearchResult
- class:possibleSelection
+ class={'byte ' + categoryIndicationSelectors}
id={id + '-' + byte.offset.toString()}
style:width
- on:mouseup={mouse_event_handle}
- on:mousedown={mouse_event_handle}
- on:mouseenter={mouse_enter_handle}
- on:mouseleave={mouse_leave_handle}
+ offset={byte.offset}
>
{byte.text}
</div>
{:else}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
- class="byte"
- class:isSelected
- class:isSearchResult
- class:possibleSelection
+ class={'byte ' + categoryIndicationSelectors}
id={id + '-' + byte.offset.toString()}
style:width={'20px'}
class:latin1Undefined={latin1Undefined(byte.value)}
- on:mouseup={mouse_event_handle}
- on:mousedown={mouse_event_handle}
- on:mouseenter={mouse_enter_handle}
- on:mouseleave={mouse_leave_handle}
+ offset={byte.offset}
>
{latin1Undefined(byte.value) ? '' : String.fromCharCode(byte.value)}
</div>
@@ -118,29 +63,24 @@ limitations under the License.
align-items: center;
flex-direction: row;
font-family: var(--monospace-font);
- /* border-radius: 5px; */
border-style: solid;
border-width: 2px;
border-color: transparent;
height: 20px;
text-align: center;
transition: all 0.25s;
- }
- div.byte.isSelected,
- div.byte.isSearchResult,
- div.byte.possibleSelection {
border-radius: 5px;
+ user-select: none;
}
- div.byte.isSelected {
+ div.byte.selected {
background-color: var(--color-secondary-light);
color: var(--color-secondary-darkest);
}
- div.byte.isSearchResult {
- background-color: var(--color-tertiary-light);
- color: var(--color-secondary-darkest);
+ div.byte.searchresult {
+ border-color: var(--color-search-result);
}
- div.byte.possibleSelection {
- border-color: var(--color-secondary-light);
+ div.byte.replacement {
+ border-color: var(--color-replace-result);
}
div.byte:hover {
border-color: var(--color-secondary-mid);
diff --git a/src/svelte/src/components/DataDisplays/CustomByteDisplay/SelectedByteEdit.svelte b/src/svelte/src/components/DataDisplays/CustomByteDisplay/SelectedByteEdit.svelte
index 251b0f7..6915110 100644
--- a/src/svelte/src/components/DataDisplays/CustomByteDisplay/SelectedByteEdit.svelte
+++ b/src/svelte/src/components/DataDisplays/CustomByteDisplay/SelectedByteEdit.svelte
@@ -343,7 +343,7 @@ limitations under the License.
class="delete {themeClass}"
id={actionElements['delete'].id}
style:width={elementDivWidth}
- on:click={send_delete}
+ on:mousedown|stopPropagation={send_delete}
>
<Tooltip alwaysEnabled={true} description={'Delete byte'}>
✖
@@ -358,7 +358,7 @@ limitations under the License.
class="insert-before {themeClass}"
id={actionElements['insert-before'].id}
style:width={elementDivWidth}
- on:click={send_insert}
+ on:mousedown|stopPropagation={send_insert}
>
<Tooltip alwaysEnabled={true} description={'Insert as preceding byte'}>
⇤
@@ -372,7 +372,7 @@ limitations under the License.
class="insert-after {themeClass}"
id={actionElements['insert-after'].id}
style:width={elementDivWidth}
- on:click={send_insert}
+ on:mousedown|stopPropagation={send_insert}
>
<Tooltip alwaysEnabled={true} description={'Insert as following byte'}>
⇥
diff --git a/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte b/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
index 4628e78..1bf2900 100644
--- a/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
+++ b/src/svelte/src/components/DataDisplays/Header/DisplayHeader.svelte
@@ -20,11 +20,8 @@ limitations under the License.
displayRadix,
seekOffset,
seekOffsetInput,
- selectionDataStore,
seekOffsetSearchType,
- selectionSize,
bytesPerRow,
- viewport,
visableViewports
} from '../../../stores'
import {
@@ -34,11 +31,9 @@ limitations under the License.
RADIX_OPTIONS,
} from '../../../stores/configuration'
import { UIThemeCSSClass } from '../../../utilities/colorScheme'
- import { createEventDispatcher } from 'svelte'
import { OffsetSearchType } from '../../Header/fieldsets/SearchReplace'
import { byteDivWidthFromRadix } from '../../../utilities/display'
let bitIndexStr = '01234567'
- let selectionOffsetText: string
let offsetLine: string[] = []
$: {
@@ -49,14 +44,6 @@ limitations under the License.
)
}
- $: selectionOffsetText = setSelectionOffsetInfo(
- 'Selection',
- $viewport.fileOffset + $selectionDataStore.startOffset,
- $viewport.fileOffset + $selectionDataStore.endOffset,
- $selectionSize,
- $addressRadix
- )
-
function generate_offset_headers(
addressRadix: RadixValues,
displayRadix: RadixValues,
@@ -127,14 +114,14 @@ limitations under the License.
{#if $displayRadix === RADIX_OPTIONS.Binary}
{#each offsetLine as offset}
<div class="physical-addr-seg binary" style:min-width={byteDivWidthFromRadix($displayRadix)}>
- <div>{offset}</div>
- <div>{bitIndexStr}</div>
+ <div><b>{offset}</b></div>
+ <div><b>{bitIndexStr}</b></div>
</div>
{/each}
{:else}
{#each offsetLine as offset}
<div class="physical-addr-seg" style:min-width={byteDivWidthFromRadix($displayRadix)}>
- {offset}
+ <b>{offset}</b>
</div>
{/each}
{/if}
diff --git a/src/svelte/src/components/Header/fieldsets/FileMetrics.svelte b/src/svelte/src/components/Header/fieldsets/FileMetrics.svelte
index 83d6365..73e714f 100644
--- a/src/svelte/src/components/Header/fieldsets/FileMetrics.svelte
+++ b/src/svelte/src/components/Header/fieldsets/FileMetrics.svelte
@@ -19,7 +19,7 @@ limitations under the License.
import FlexContainer from '../../layouts/FlexContainer.svelte'
import { MessageCommand } from '../../../utilities/message'
import { vscode } from '../../../utilities/vscode'
- import { saveable, fileMetrics } from '../../../stores'
+ import { saveable, fileMetrics, replaceQuery } from '../../../stores'
import { createEventDispatcher } from 'svelte'
import SidePanel from '../../layouts/SidePanel.svelte'
import ByteFrequencyGraph from '../../DataMetrics/DataMetrics.svelte'
diff --git a/src/svelte/src/components/Header/fieldsets/SearchReplace.svelte b/src/svelte/src/components/Header/fieldsets/SearchReplace.svelte
index 12c8c90..16f24c7 100644
--- a/src/svelte/src/components/Header/fieldsets/SearchReplace.svelte
+++ b/src/svelte/src/components/Header/fieldsets/SearchReplace.svelte
@@ -42,13 +42,8 @@ limitations under the License.
import { createEventDispatcher } from 'svelte'
import { UIThemeCSSClass } from '../../../utilities/colorScheme'
import ToggleableButton from '../../Inputs/Buttons/ToggleableButton.svelte'
- import {
- clearSearchResultsHighlights,
- updateSearchResultsHighlights,
- } from '../../../utilities/highlights'
- import { viewport } from '../../../stores'
import { EditActionRestrictions } from '../../../stores/configuration'
- import { OffsetSearchType } from './SearchReplace'
+ import { OffsetSearchType, clear_queryable_results } from './SearchReplace'
import Tooltip from '../../layouts/Tooltip.svelte'
const eventDispatcher = createEventDispatcher()
@@ -201,7 +196,8 @@ limitations under the License.
searchStarted = false
replaceStarted = false
matchOffset = -1
- clearSearchResultsHighlights()
+ clear_queryable_results()
+
eventDispatcher('clearDataDisplays')
}
@@ -210,25 +206,24 @@ limitations under the License.
// handle search results
case MessageCommand.searchResults:
if (msg.data.data.searchResults.length > 0) {
- $searchQuery.searchResults = msg.data.data.searchResults
- $searchQuery.byteLength = msg.data.data.searchDataBytesLength
+ searchQuery.updateSearchResults(msg.data.data)
switch (direction) {
case 'Home':
- hasNext = msg.data.data.overflow
+ hasNext = $searchQuery.overflow
hasPrev = false
break
case 'End':
hasNext = false
- hasPrev = msg.data.data.overflow
+ hasPrev = $searchQuery.overflow
break
case 'Forward':
- hasNext = msg.data.data.overflow
+ hasNext = $searchQuery.overflow
hasPrev = justReplaced ? preReplaceHasPrev : true
justReplaced = false
break
case 'Backward':
hasNext = true
- hasPrev = msg.data.data.overflow
+ hasPrev = $searchQuery.overflow
break
}
matchOffset = $searchQuery.searchResults[0]
@@ -240,17 +235,12 @@ limitations under the License.
showReplaceOptions = true
showSearchOptions = false
}
- $searchQuery.overflow = msg.data.data.overflow
} else {
matchOffset = -1
$searchQuery.overflow = showSearchOptions = showReplaceOptions = false
+ searchQuery.clear()
}
searchStarted = replaceStarted = false
- updateSearchResultsHighlights(
- $searchQuery.searchResults,
- $viewport.fileOffset,
- $searchQuery.byteLength
- )
$searchQuery.processing = false
break
@@ -259,8 +249,11 @@ limitations under the License.
searchStarted = replaceStarted = false
if (msg.data.data.replacementsCount > 0) {
// subtract 1 from the next offset because search next will add 1
- clearSearchResultsHighlights()
matchOffset = msg.data.data.nextOffset - 1
+ replaceQuery.addResult({
+ byteLength: msg.data.data.replaceDataBytesLength,
+ offset: msg.data.data.nextOffset - msg.data.data.replaceDataBytesLength
+ })
preReplaceHasPrev = hasPrev
justReplaced = true
searchNext()
@@ -270,6 +263,11 @@ limitations under the License.
}
$replaceQuery.processing = false
break
+
+ case MessageCommand.clearChanges:
+ cancel()
+ break
+
}
})
</script>
diff --git a/src/svelte/src/components/Header/fieldsets/SearchReplace.ts b/src/svelte/src/components/Header/fieldsets/SearchReplace.ts
index e1f739b..c09193a 100644
--- a/src/svelte/src/components/Header/fieldsets/SearchReplace.ts
+++ b/src/svelte/src/components/Header/fieldsets/SearchReplace.ts
@@ -16,8 +16,9 @@
*/
import { SimpleWritable } from '../../../stores/localStore'
-import { addressRadix, seekOffsetInput } from '../../../stores'
-import { get } from 'svelte/store'
+import { replaceQuery, searchQuery } from '../../../stores'
+import { VIEWPORT_CAPACITY_MAX } from '../../../stores/configuration'
+import { viewportByteIndicators } from '../../../utilities/highlights'
export enum OffsetSearchType {
ABSOLUTE,
@@ -29,16 +30,38 @@ export type RelativeSeekSign = '+' | '-'
interface QueryableData {
input: string
processing: boolean
- isValid: boolean
+ initiaited: boolean
+ iterableDataFromOffset(offset: number): IndexCriteria
}
-class SearchData implements QueryableData {
+
+export type IndexCriteria = {
+ start: number
+ end: number
+ data: any[]
+}
+export class SearchData implements QueryableData {
input: string = ''
processing: boolean = false
- isValid: boolean = false
+ initiaited: boolean = false
searchIndex: number = 0
searchResults: Array<number> = []
overflow: boolean = false
byteLength: number = 0
+ iterableDataFromOffset(offset: number): IndexCriteria {
+ const start = this.searchResults.findIndex((x) => x >= offset)
+ const end = this.searchResults.findIndex(
+ (x) => x >= offset + VIEWPORT_CAPACITY_MAX
+ )
+ let ret: IndexCriteria = {
+ start: start,
+ end: end,
+ data: this.searchResults.slice(
+ start,
+ end >= 0 ? end : this.searchResults.length
+ ),
+ }
+ return ret
+ }
}
export class SearchQuery extends SimpleWritable<SearchData> {
protected init(): SearchData {
@@ -47,39 +70,84 @@ export class SearchQuery extends SimpleWritable<SearchData> {
public clear() {
this.update((query) => {
query.processing = false
+ query.initiaited = false
query.searchIndex = 0
query.searchResults = []
+ viewportByteIndicators.clearIndication('searchresult')
return query
})
}
- public updateSearchResults(offset?: number) {
+ public updateSearchResults(msgData: any) {
this.update((query) => {
- query.searchIndex = !offset
- ? Math.abs(
- (query.searchResults.length + query.searchIndex) %
- query.searchResults.length
- )
- : Math.abs(
- (query.searchResults.length + offset) % query.searchResults.length
- )
-
- seekOffsetInput.update((_) => {
- return query.searchResults[query.searchIndex].toString(
- get(addressRadix)
- )
- })
+ query.initiaited = true
+ query.searchResults = msgData.searchResults
+ query.byteLength = msgData.searchDataBytesLength
+ query.overflow = msgData.overflow
return query
})
}
}
-class ReplaceData implements QueryableData {
+/**
+Object that defines describes an instance of a replacement that occured during a Search & Replace query.
+@param offset **File** offset of where the replacement occured.
+@param byteLength Byte length of the replacement data.
+*/
+export type DataReplacement = {
+ offset: number
+ byteLength: number
+}
+
+export class ReplaceData implements QueryableData {
input: string = ''
processing: boolean = false
- isValid: boolean = false
+ initiaited: boolean = false
+ results: Array<DataReplacement> = []
+ iterableDataFromOffset(offset: number): IndexCriteria {
+ const start = this.results.findIndex((x) => x.offset >= offset)
+ const end = this.results.findIndex(
+ (x) => x.offset >= offset + VIEWPORT_CAPACITY_MAX
+ )
+ const withinRange = start >= 0
+ const data = withinRange
+ ? this.results.slice(start, end >= 0 ? end : this.results.length)
+ : []
+ let ret: IndexCriteria = {
+ start: start,
+ end: end,
+ data: data,
+ }
+ return ret
+ }
}
export class ReplaceQuery extends SimpleWritable<ReplaceData> {
protected init(): ReplaceData {
return new ReplaceData()
}
+ public addResult(result: DataReplacement) {
+ this.update((data) => {
+ data.initiaited = true
+ data.results.push(result)
+ return data
+ })
+ }
+ public pop() {
+ this.update((data) => {
+ data.results.pop()
+ return data
+ })
+ }
+ public clear() {
+ this.update((data) => {
+ data.processing = false
+ data.results = []
+ data.initiaited = false
+ return data
+ })
+ }
+}
+
+export function clear_queryable_results() {
+ searchQuery.clear()
+ replaceQuery.clear()
}
diff --git a/src/svelte/src/components/dataEditor.svelte b/src/svelte/src/components/dataEditor.svelte
index 32b5285..4b4ee42 100644
--- a/src/svelte/src/components/dataEditor.svelte
+++ b/src/svelte/src/components/dataEditor.svelte
@@ -61,8 +61,8 @@ limitations under the License.
ViewportData_t,
} from './DataDisplays/CustomByteDisplay/BinaryData'
import { byte_count_divisible_offset } from '../utilities/display'
- import { clearSearchResultsHighlights } from '../utilities/highlights'
import Help from './layouts/Help.svelte'
+ import { viewportByteIndicators } from '../utilities/highlights'
$: $UIThemeCSSClass = $darkUITheme ? CSSThemeClass.Dark : CSSThemeClass.Light
@@ -248,16 +248,15 @@ limitations under the License.
function clearQueryableData() {
searchQuery.clear()
- clearSearchResultsHighlights()
}
function handleKeyBind(event: Event) {
const kbdEvent = event as KeyboardEvent
if (key_is_mappable(kbdEvent.key)) {
- elementKeypressEventMap.run(document.activeElement.id, kbdEvent)
+ if(document.activeElement) // document.activeElement is possibly undefined / null
+ elementKeypressEventMap.run(document.activeElement.id, kbdEvent)
return
}
- if ($editMode === EditByteModes.Multiple) return
switch (kbdEvent.key) {
case 'Escape':
clearDataDisplays()
diff --git a/src/svelte/src/components/globalStyles.css b/src/svelte/src/components/globalStyles.css
index 916f9b3..765897f 100644
--- a/src/svelte/src/components/globalStyles.css
+++ b/src/svelte/src/components/globalStyles.css
@@ -60,6 +60,8 @@ html {
--color-tertiary-dark: #5f816b;
--color-tertiary-darkest: #232f27;
--color-alternate-grey: #bbb5bd;
+ --color-search-result: #69a0a7;
+ --color-replace-result: #5f816b;
}
/* Global LEGEND Styles */
diff --git a/src/svelte/src/components/layouts/Tooltip.svelte b/src/svelte/src/components/layouts/Tooltip.svelte
index f04abff..e313e34 100644
--- a/src/svelte/src/components/layouts/Tooltip.svelte
+++ b/src/svelte/src/components/layouts/Tooltip.svelte
@@ -101,7 +101,7 @@ limitations under the License.
}
.fit-content {
- max-width: 150px;
+ max-width: 250px;
min-width: 50px;
max-height: 50px;
min-height: 25px;
diff --git a/src/svelte/src/stores/index.ts b/src/svelte/src/stores/index.ts
index 66b3c8e..fe60eb1 100644
--- a/src/svelte/src/stores/index.ts
+++ b/src/svelte/src/stores/index.ts
@@ -43,7 +43,6 @@ import {
type RadixValues,
type BytesPerRow,
EditActionRestrictions,
- VIEWPORT_CAPACITY_MAX,
} from './configuration'
import type { AvailableHelpSections } from '../components/layouts/Help'
@@ -60,6 +59,34 @@ export class SelectionData_t {
this.originalEndOffset >= 0
)
}
+ public editedLength(): number {
+ return this.endOffset - this.startOffset
+ }
+ public originalLength(): number {
+ return this.originalEndOffset - this.startOffset
+ }
+ public selectionIndexIsAnEdit(index: number): boolean {
+ const editOffsetLength = this.originalLength() - this.editedLength()
+ const editStartOffset = this.originalEndOffset - editOffsetLength
+
+ return index <= this.originalEndOffset
+ ? index >= editStartOffset
+ : index <= editStartOffset
+ }
+ public isEmpty(): boolean {
+ return this.editedLength() + 1 == 0
+ }
+ public editStartOffset() {
+ return (
+ this.originalEndOffset - (this.originalLength() - this.editedLength())
+ )
+ }
+ public editLengthDelta() {
+ return this.endOffset - this.originalEndOffset + 1
+ }
+ public makingSelection() {
+ return this.startOffset >= 0 && this.originalEndOffset === -1
+ }
}
class SelectionData extends SimpleWritable<SelectionData_t> {
@@ -76,6 +103,10 @@ export enum EditModeRestrictions {
OverwriteOnly,
}
+/**************************************************************************/
+/* Writable Stores */
+/**************************************************************************/
+
// noinspection JSUnusedGlobalSymbols
// theme to use for the UI
@@ -155,6 +186,12 @@ export const dataDislayLineAmount = writable(20)
export type VisibleViewports = 'physical' | 'logical' | 'all'
export const visableViewports = writable('all' as VisibleViewports)
+
+export const searchResultsUpdated = writable(false)
+
+/**************************************************************************/
+/* Derived Stores */
+/**************************************************************************/
// Can the user's selection derive both edit modes?
export const regularSizedFile = derived(fileMetrics, ($fileMetrics) => {
return $fileMetrics.computedSize >= 2
@@ -204,7 +241,7 @@ export const replaceable = derived(
}
if ($selectionData.active) {
replaceErr.update(() => {
- return 'Cannot replace while viewport data is selected'
+ return "Can't replace while selection active"
})
return false
}
diff --git a/src/svelte/src/utilities/ByteCategories/CategoryIndications.ts b/src/svelte/src/utilities/ByteCategories/CategoryIndications.ts
new file mode 100644
index 0000000..72e57fc
--- /dev/null
+++ b/src/svelte/src/utilities/ByteCategories/CategoryIndications.ts
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { CategoryOne, type ByteCategory, CategoryTwo } from './IByteCategory'
+
+class ByteIndicationCategories {
+ private _categories: {
+ [key: string]: ByteCategory
+ } = {}
+ private _bitsUtilized: number = 0
+
+ public addIndicationCategory(category: ByteCategory) {
+ if (this._bitsUtilized + category.bitLength() > 8)
+ throw new Error('Category addition would exceed bit limit')
+ this._categories[category.name()] = category
+ this._bitsUtilized += category.bitLength()
+
+ return this
+ }
+ public category(name: string): ByteCategory {
+ return this._categories[name]
+ }
+ public categoryOfIndication(indicationName: string): ByteCategory {
+ for (const category in this._categories)
+ if (this._categories[category].contains(indicationName))
+ return this._categories[category]
+
+ throw new Error(
+ `No ByteCategory found with ByteIndication named ${indicationName}`
+ )
+ }
+ public categoryValueByIndication(
+ category: ByteCategory,
+ indicationName: string
+ ): number {
+ return category.indexOf(indicationName) << this.categoryBitPos(category)
+ }
+ public clearIndication(data: Uint8Array, indicationName: string) {
+ const category = this.categoryOfIndication(indicationName)
+ data.forEach((byte, i, data) => {
+ const categoryValueOfByte = byte & this.categoryMask(category)
+ if (
+ categoryValueOfByte ===
+ this.categoryValueByIndication(category, indicationName)
+ )
+ data[i] &= this.categoryMask(category) ^ 0xff
+ })
+ }
+ public clearAndSetIf(
+ data: Uint8Array,
+ indication: string,
+ predicate: (byte: number, index: number) => boolean
+ ) {
+ const category = this.categoryOfIndication(indication)
+ if (!category) {
+ console.error(`No ByteCategory contains the indication: ${indication}`)
+ return
+ }
+
+ data.forEach((byte, i, data) => {
+ data[i] &= this.categoryMask(category) ^ 0xff
+ if (predicate(byte, i))
+ data[i] |= this.categoryValueByIndication(category, indication)
+ })
+ }
+ public categoryCSSSelector(
+ category: ByteCategory,
+ byteIndicationValue: number
+ ) {
+ const maskedByteValue = byteIndicationValue & this.categoryMask(category)
+ const indicationIndex = maskedByteValue >> this.categoryBitPos(category)
+ const indication = category.indicators()[indicationIndex]
+ return indication != undefined
+ ? indication.selector()
+ : category.indexOf('none')
+ }
+ private categoryMask(category: ByteCategory): number {
+ const categoryBitPos = this.categoryBitPos(category)
+ const categoryBitLength = category.bitLength()
+ return (Math.pow(2, categoryBitLength) - 1) << categoryBitPos
+ }
+ private indexOf(category: ByteCategory) {
+ let i = 0
+ for (let _category in this._categories) {
+ if (category.name() === this._categories[_category].name()) {
+ return i
+ }
+ i++
+ }
+ return -1
+ }
+ private categoryBitPos(category: ByteCategory): number {
+ return this.indexOf(category) * category.bitLength()
+ }
+}
+
+export const ViewportByteCategories = new ByteIndicationCategories()
+ViewportByteCategories.addIndicationCategory(CategoryOne).addIndicationCategory(
+ CategoryTwo
+)
diff --git a/src/svelte/src/utilities/ByteCategories/IByteCategory.ts b/src/svelte/src/utilities/ByteCategories/IByteCategory.ts
new file mode 100644
index 0000000..55b29fa
--- /dev/null
+++ b/src/svelte/src/utilities/ByteCategories/IByteCategory.ts
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ NoIndication,
+ type IByteIndication,
+ ByteIndication,
+} from './IIndication'
+
+export interface IByteCategory {
+ addIndication(selectorName: string): void
+ bitLength(): number
+ name(): string
+ indicators(): readonly IByteIndication[]
+ at(index: number): IByteIndication
+ indexOf(selectorName: string): number
+ contains(selectorName: string): boolean
+}
+
+export class ByteCategory implements IByteCategory {
+ private _indicators: IByteIndication[] = [NoIndication]
+
+ constructor(
+ private _name: string,
+ private _bitLength: number
+ ) {
+ if (_bitLength > 8)
+ throw new Error('Byte category indications cannot exceed 8 bits.')
+ }
+ addIndication(selectorName: string) {
+ this._indicators.push(new ByteIndication(selectorName))
+ return this
+ }
+ bitLength() {
+ return this._bitLength
+ }
+ name() {
+ return this._name
+ }
+ indicators() {
+ return this._indicators
+ }
+ at(index: number) {
+ return index >= this._indicators.length || index < 0
+ ? this._indicators[0]
+ : this._indicators[index]
+ }
+ indexOf(selectorName: string) {
+ const target = selectorName
+ let ret = -1
+
+ this._indicators.forEach((categoryObj, i) => {
+ if (categoryObj.selector() === target) ret = i
+ })
+ if (ret < 0)
+ throw new Error(`Indication category "${selectorName}" not found.`)
+ else return ret
+ }
+ contains(selectorName: string): boolean {
+ for (let i = 0; i < this._indicators.length; i++)
+ if (this._indicators[i].selector() == selectorName) return true
+ return false
+ }
+}
+
+export const CategoryOne = new ByteCategory('one', 4)
+CategoryOne.addIndication('selected')
+
+export const CategoryTwo = new ByteCategory('two', 4)
+CategoryTwo.addIndication('searchresult').addIndication('replacement')
diff --git a/src/svelte/src/utilities/ByteCategories/IIndication.ts b/src/svelte/src/utilities/ByteCategories/IIndication.ts
new file mode 100644
index 0000000..7a6dede
--- /dev/null
+++ b/src/svelte/src/utilities/ByteCategories/IIndication.ts
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export interface IByteIndication {
+ selector(): string
+ equals(categoryArg: IByteIndication): boolean
+}
+
+class NullIndication implements IByteIndication {
+ equals(categoryArg: IByteIndication): boolean {
+ return this.selector() === categoryArg.selector()
+ }
+ selector(): string {
+ return 'none'
+ }
+}
+
+export class ByteIndication implements IByteIndication {
+ constructor(private _selector: string) {}
+ equals(categoryArg: IByteIndication): boolean {
+ return this.selector() === categoryArg.selector()
+ }
+ selector(): string {
+ return this._selector.toLowerCase()
+ }
+}
+
+export const NoIndication: NullIndication = new NullIndication()
diff --git a/src/svelte/src/utilities/display.ts b/src/svelte/src/utilities/display.ts
index 6b0f522..481d539 100644
--- a/src/svelte/src/utilities/display.ts
+++ b/src/svelte/src/utilities/display.ts
@@ -12,7 +12,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-
import {
EditByteModes,
type BytesPerRow,
diff --git a/src/svelte/src/utilities/highlights.ts b/src/svelte/src/utilities/highlights.ts
index bb00644..4442a6d 100644
--- a/src/svelte/src/utilities/highlights.ts
+++ b/src/svelte/src/utilities/highlights.ts
@@ -15,62 +15,144 @@
* limitations under the License.
*/
-import { derived, readable, writable } from 'svelte/store'
-import { selectionDataStore } from '../stores'
+import { SelectionData_t, searchResultsUpdated } from '../stores'
+import { VIEWPORT_CAPACITY_MAX } from '../stores/configuration'
+import { SimpleWritable } from '../stores/localStore'
+import type {
+ DataReplacement,
+ ReplaceData,
+ SearchData,
+} from '../components/Header/fieldsets/SearchReplace'
+import { ViewportByteCategories } from './ByteCategories/CategoryIndications'
-let selectionHighlightLUT = new Uint8Array(1024)
-export let selectionHighlightMask = writable(0)
+class ViewportByteIndications extends SimpleWritable<Uint8Array> {
+ protected init(): Uint8Array {
+ return new Uint8Array(VIEWPORT_CAPACITY_MAX).fill(0)
+ }
+ public clearIndication(indicationName: string) {
+ this.store.update((indications) => {
+ ViewportByteCategories.clearIndication(indications, indicationName)
+ return indications
+ })
+ }
+ public updateSearchIndications(
+ searchQuery: SearchData,
+ viewportFileOffset: number
+ ) {
+ if (searchQuery.searchResults.length > 0) {
+ const resultsIterable =
+ searchQuery.iterableDataFromOffset(viewportFileOffset)
+ const { data } = resultsIterable
+ const start = data[0]
+ const byteLength = searchQuery.byteLength
-let searchResultsHighlightLUT = new Uint8Array(1024).fill(0)
+ this.store.update((indications) => {
+ ViewportByteCategories.clearAndSetIf(
+ indications,
+ 'searchresult',
+ (_, i) => {
+ const adjustIndex = i + viewportFileOffset
+ return adjustIndex >= start && adjustIndex < start + byteLength
+ }
+ )
+ searchResultsUpdated.set(true)
+ return indications
+ })
+ }
+ }
-export enum HightlightCategoryMasks {
- None = 0,
- ActiveSelection = 1,
- ConsideredForSelection = 2,
- SearchResult = 4,
-}
+ public updateReplaceIndications(
+ replaceData: ReplaceData,
+ viewportFileOffset: number
+ ) {
+ const resultsIterable =
+ replaceData.iterableDataFromOffset(viewportFileOffset)
-export const selectionHighlights = derived(
- [selectionDataStore, selectionHighlightMask],
- ([$selectionData, $selectionHighlightMask]) => {
- let start = $selectionData.startOffset
- let end =
- $selectionHighlightMask === 0
- ? $selectionData.originalEndOffset
- : $selectionData.endOffset
- if (start > end && end > -1) [start, end] = [end, start]
+ if (resultsIterable.data.length > 0) {
+ const { offset, byteLength } = resultsIterable.data[0] as DataReplacement
+ this.store.update((indications) => {
+ ViewportByteCategories.clearAndSetIf(
+ indications,
+ 'replacement',
+ (_, i) => {
+ const adjustIndex = i + viewportFileOffset
+ return adjustIndex >= offset && adjustIndex < offset + byteLength
+ }
+ )
+ return indications
+ })
+ }
+ }
+ public updateSelectionIndications(selectionData: SelectionData_t) {
+ const category1 = ViewportByteCategories.category('one')
+ const start = selectionData.startOffset
+ const editedEnd = selectionData.endOffset + 1
+ const originalEnd = selectionData.originalEndOffset
- for (let i = 0; i < 1024; i++) {
- selectionHighlightLUT[i] =
- i >= start && i <= end ? 1 << $selectionHighlightMask : 0
+ if (!selectionData.makingSelection() && !selectionData.active) {
+ this.store.update((indications) => {
+ ViewportByteCategories.clearIndication(indications, 'selected')
+ return indications
+ })
+ }
+ if (selectionData.active || selectionData.makingSelection()) {
+ const offsetPartitions = [
+ generateSelectionCategoryParition(0, start, (byte) => {
+ byte[0] &= ~category1.indexOf('selected')
+ }),
+ generateSelectionCategoryParition(start, editedEnd, (byte) => {
+ byte[0] |= category1.indexOf('selected')
+ }),
+ generateSelectionCategoryParition(
+ Math.max(originalEnd, editedEnd),
+ VIEWPORT_CAPACITY_MAX - start,
+ (byte) => {
+ byte[0] &= ~category1.indexOf('selected')
+ }
+ ),
+ ]
+ this.store.update((indications) => {
+ for (const partition of offsetPartitions) {
+ for (let i = partition.start; i < partition.end; i++)
+ partition.assignByte(indications.subarray(i, i + 1))
+ }
+ return indications
+ })
}
+ }
+}
- return selectionHighlightLUT
+export const viewportByteIndicators = new ViewportByteIndications()
+
+type CategoryOffsetParition = {
+ start: number
+ end: number
+ assignByte: (byte: Uint8Array) => void
+}
+function generateSelectionCategoryParition(
+ start: number,
+ end: number,
+ assignmentFn: (byte: Uint8Array) => void
+): CategoryOffsetParition {
+ return {
+ start,
+ end,
+ assignByte: assignmentFn,
}
-)
+}
-export const searchResultsHighlights = readable(searchResultsHighlightLUT)
-export const searchResultsUpdated = writable(false)
-export function updateSearchResultsHighlights(
- data: number[],
- viewportFileOffset: number,
- byteWidth: number
-) {
- const criteriaStart = data.findIndex((x) => x >= viewportFileOffset)
- const criteriaEnd = data.findIndex((x) => x >= viewportFileOffset + 1024)
- const searchCriteria = data.slice(
- criteriaStart,
- criteriaEnd >= 0 ? criteriaEnd : data.length
+export function categoryCSSSelectors(byteIndicationValue: number): string {
+ let ret = ''
+ const CategoryOneSelector = ViewportByteCategories.categoryCSSSelector(
+ ViewportByteCategories.category('one'),
+ byteIndicationValue
+ )
+ const CategoryTwoSelector = ViewportByteCategories.categoryCSSSelector(
+ ViewportByteCategories.category('two'),
+ byteIndicationValue
)
- searchResultsHighlightLUT.fill(0)
+ ret += CategoryOneSelector + ' ' + CategoryTwoSelector
- searchCriteria.forEach((offset) => {
- for (let i = 0; i < byteWidth; i++)
- searchResultsHighlightLUT[offset - viewportFileOffset + i] = 1
- })
- searchResultsUpdated.set(true)
-}
-export function clearSearchResultsHighlights() {
- searchResultsHighlightLUT.fill(0)
+ return ret
}