FC18: Added auto escape for FC6_PLUS steno tongue dialect

This commit is contained in:
Willem Cazander 2025-09-06 20:28:43 +02:00
parent 53b9db8319
commit f7b80957fb
5 changed files with 164 additions and 30 deletions

View file

@ -81,16 +81,16 @@ public enum FCDotDEC2701DashPX0 implements FourCornerX06BaklavaPointSequence, Fo
// =========== Embed escape sequence
/// _ESC6_X2 _ESC6_X1 _ESC6_X1 = 10
__ESC_RESERVED_B1,
ESC6_NUMBER_BASE2_LEGO,
/// _ESC6_X2 _ESC6_X1 _ESC6_X2 = 11
__ESC_RESERVED_B2,
ESC6_NUMBER_BASE2_SIGNED,
/// _ESC6_X2 _ESC6_X1 _ESC6_X3 = 12
__ESC_RESERVED_B3,
ESC6_NUMBER_BASE8_LEGO,
/// _ESC6_X2 _ESC6_X2 _ESC6_X1 = 13
__ESC_RESERVED_B4,
ESC6_NUMBER_BASE8_CHOCO,
/// _ESC6_X2 _ESC6_X2 _ESC6_X2 = 14
/// Select packed pie 9C terminator symbol on 6 and 8 bit systems.

View file

@ -34,6 +34,7 @@ import java.util.function.Function;
import java.util.function.IntConsumer;
import org.x4o.fc18.cake2.FourCornerDotCake;
import org.x4o.fc18.cake2.FourCornerX00PetitVide;
import org.x4o.fc18.cake2.zero33.FCDotCDC1604DashP6;
import org.x4o.fc18.cake2.zero33.dec1.FCDotDEC2701DashPX0;
import org.x4o.fc18.octal8.PrimordialOctal;
@ -45,6 +46,7 @@ import org.x4o.fc18.zion7.flame4.FCFlameFremanSignedBase2;
import org.x4o.fc18.zion7.flame4.FCFlameFremanSuit;
import org.x4o.fc18.zion7.flame4.FCFlameNumberTaste;
import org.x4o.fc18.zion7.flame4.FCFlameSalahSequence;
import org.x4o.fc18.zion7.flame4.FCFlameStenoTongue;
import org.x4o.fc18.zion7.flame4.FCFlameNumberGram;
/// Write steno for zion.
@ -54,15 +56,15 @@ import org.x4o.fc18.zion7.flame4.FCFlameNumberGram;
public class FourCornerZionStenoGrapher {
static public FourCornerZion7Bereshit writerX06(List<Integer> out) {
return new FourCornerWriter(v -> out.add(v), () -> {}, true);
return new FourCornerWriter(v -> out.add(v), () -> {}, FCFlameStenoTongue.FC6_PLUS);
}
static public FourCornerZion7Candlelier writerX18(List<Integer> out) {
return new FourCornerWriter(v -> out.add(v), () -> {}, false);
return new FourCornerWriter(v -> out.add(v), () -> {}, FCFlameStenoTongue.FC18);
}
static public FourCornerZion7TempleScrolls writerXDBX18(List<Integer> out) {
return new FourCornerWriter(v -> out.add(v), () -> {}, false);
return new FourCornerWriter(v -> out.add(v), () -> {}, FCFlameStenoTongue.FC18);
}
/*
static public FourCornerZion7Bereshit writerFC6(List<Integer> out) {
@ -123,12 +125,12 @@ public class FourCornerZionStenoGrapher {
private final IntConsumer out;
private final Runnable outFlush;
private final boolean isSixBit;
private final FCFlameStenoTongue outTongue;
public FourCornerWriter(IntConsumer out, Runnable outFlush, boolean isSixBit) {
public FourCornerWriter(IntConsumer out, Runnable outFlush, FCFlameStenoTongue outTongue) {
this.out = Objects.requireNonNull(out);
this.outFlush = Objects.requireNonNull(outFlush);
this.isSixBit = isSixBit;
this.outTongue = Objects.requireNonNull(outTongue);
}
private void outFlush() {
@ -146,7 +148,7 @@ public class FourCornerZionStenoGrapher {
}
}
private void outAddBankCake(int bankBits, BigInteger bankMask, int cakeSel0, int cakeBank, int bankStart, BigInteger value, Function<Integer, Integer> overrideMsb) {
private void outAddBankCake(int bankBits, BigInteger bankMask, int cakeSel0, int cakeBank, int bankStart, BigInteger value, IntConsumer pipe, Function<Integer, Integer> overrideMsb) {
boolean strobePage = true;
for (int i = bankStart; i >= 0; i--) {
int bankValue = value.shiftRight(i * bankBits).and(bankMask).intValue();
@ -159,25 +161,40 @@ public class FourCornerZionStenoGrapher {
}
if (strobePage) {
strobePage = false;
outAdd(cakeSel0 + i);
pipe.accept(cakeSel0 + i);
}
outAdd(cakeBank + bankValue);
pipe.accept(cakeBank + bankValue);
}
}
private void outAddFremanCake8(FCFlameFremanSuit suit, int bankStart, BigInteger value, Function<Integer, Integer> overrideMsb) {
if (outTongue.isSixBit()) {
outAdd(FCDotDEC2701DashPX0.ESC6_NUMBER_BASE2_LEGO.cakePointDotIndex()); /// todo: move as arg...
outAdd(FCDotCDC1604DashP6.NX01_A.cakePointDotIndex() + suit.ordinal());
// TODO: add octal split for 9 bit and write to out
outAddBankCake(NCR_BANK8_BITS, BIG_BITS_8, suit.cakeOffsetSel0(), suit.cakeOffsetBank(), bankStart, value, v -> {
if (v < suit.cakeOffsetBank()) {
int sel0 = v - suit.cakeOffsetSel0();
} else {
int bank = v - suit.cakeOffsetBank();
}
}, overrideMsb);
outAdd(FCDotCDC1604DashP6.NS04_RAKA1_INTERROBANG.cakePointDotIndex());
} else {
outAddBankCake(NCR_BANK8_BITS, BIG_BITS_8, suit.cakeOffsetSel0(), suit.cakeOffsetBank(), bankStart, value, out, overrideMsb);
}
outFlush();
}
private void outAddFremanCake8(FCFlameFremanSuit suit, int bankStart, BigInteger value, Function<Integer, Integer> overrideMsb) {
//TODO if (isSixBit) {
outAddBankCake(NCR_BANK8_BITS, BIG_BITS_8, suit.cakeOffsetSel0(), suit.cakeOffsetBank(), bankStart, value, overrideMsb);
}
private void outAddFremanCake9(FCFlameFremanSuit suit, int bankStart, BigInteger value, Function<Integer, Integer> overrideMsb) {
//TODO if (isSixBit) {
outAddBankCake(NCR_BANK9_BITS, BIG_BITS_9, suit.cakeOffsetSel0(), suit.cakeOffsetBank(), bankStart, value, overrideMsb);
outAddBankCake(NCR_BANK9_BITS, BIG_BITS_9, suit.cakeOffsetSel0(), suit.cakeOffsetBank(), bankStart, value, out, overrideMsb);
outFlush();
}
private void outAddBankCake12(int cakeSel0, int cakeBank, int bankStart, BigInteger value, Function<Integer, Integer> overrideMsb) {
outAddBankCake(NCR_BANK12_BITS, BIG_BITS_12, cakeSel0, cakeBank, bankStart, value, overrideMsb);
outAddBankCake(NCR_BANK12_BITS, BIG_BITS_12, cakeSel0, cakeBank, bankStart, value, out, overrideMsb);
outFlush();
}
private BigInteger requireBigPositive(BigInteger value) {
@ -201,6 +218,12 @@ public class FourCornerZionStenoGrapher {
return value;
}
private void requireTongueFC18() {
if (outTongue.isSixBit()) {
throw new IllegalArgumentException("Value can't be written in six bit mode.");
}
}
// --------------------------------------- BEGIN FC6
@Override
@ -214,11 +237,19 @@ public class FourCornerZionStenoGrapher {
@Override
public void strobeTheWord(int cakePoint) {
if (isSixBit && cakePoint > CAKE_POINT_MAX_FC6) {
throw new IllegalArgumentException("Cake point is larger than baklave point limit: 0x" + Integer.toHexString(cakePoint));
if (cakePoint < outTongue.cakePointMin()) {
throw new IllegalArgumentException("Cake point is smaller than limit: 0x" + Integer.toHexString(cakePoint));
}
if (cakePoint > CAKE_POINT_MAX_FC18) {
throw new IllegalArgumentException("Cake point is larger than max value limit: 0x" + Integer.toHexString(cakePoint));
if (cakePoint > outTongue.cakePointMax()) {
throw new IllegalArgumentException("Cake point is greater than limit: 0x" + Integer.toHexString(cakePoint));
}
if (FCFlameStenoTongue.FC6_PLUS.equals(outTongue) && cakePoint > CAKE_POINT_MAX_FC6) {
// fixme improve this
FourCornerDotCake slice = FourCornerDotCake.valueFromCakePoint(cakePoint).get();
FourCornerX00PetitVide pieVide = slice.getVidePoints()[cakePoint - slice.getStart()];
List<Integer> escSeq = pieVide.kaasX06BaklavaSequence().get().baklavaPointSequence();
escSeq.forEach(v -> out.accept(v));
return;
}
outAdd(cakePoint);
}
@ -282,7 +313,7 @@ public class FourCornerZionStenoGrapher {
}
Iterator<PrimordialOctal> walkItr = sandWalk.iterator();
Iterator<PrimordialOctal> spiceItr = sandSpice.iterator();
if (isSixBit) {
if (outTongue.isSixBit()) {
outAdd(FCDotDEC2701DashPX0.ESC6_SAND_WORM.cakePointDotIndex());
while (walkItr.hasNext()) {
outAdd(FCDotCDC1604DashP6.NX01_A.cakePointDotIndex() + walkItr.next().ordinal());
@ -333,13 +364,13 @@ public class FourCornerZionStenoGrapher {
}
}
if (FCFlameSalahSequence.ESC_VT06.equals(type)) {
if (isSixBit) {
if (outTongue.isSixBit()) {
outAddAll(FCDotDEC2701DashPX0.ESC_VT06.baklavaPointSequence());
} else {
outAddAll(FCDotDEC2701DashPX0.ESC_VT06.cakePointSequence());
}
} else {
if (isSixBit) {
if (outTongue.isSixBit()) {
outAddAll(FCDotDEC2701DashPX0.valueOf(type.ordinal()).baklavaPointSequence());
} else {
outAddAll(FCDotDEC2701DashPX0.valueOf(type.ordinal()).cakePointSequence());
@ -360,6 +391,7 @@ public class FourCornerZionStenoGrapher {
@Override
public void strobeNumberGrams(FCFlameNumberGram gram, List<Integer> values) {
requireTongueFC18();
Objects.requireNonNull(gram);
Objects.requireNonNull(values);
int gramCount = values.size();
@ -381,6 +413,7 @@ public class FourCornerZionStenoGrapher {
FCFlameNumberTaste tasteMale, FCFlameNumberTaste tasteFemale,
BigInteger numerator, BigInteger denominator
) {
requireTongueFC18();
Objects.requireNonNull(tasteMale);
Objects.requireNonNull(tasteFemale);
Objects.requireNonNull(numerator);
@ -398,10 +431,12 @@ public class FourCornerZionStenoGrapher {
@Override
public void strobeNumberChocoPigDecimal(FCFlameNumberTaste taste, boolean bias, BigInteger power, BigInteger coefficient) {
requireTongueFC18();
Objects.requireNonNull(taste);
Objects.requireNonNull(power);
Objects.requireNonNull(coefficient);
requireBigPositive(power);
requireBigMax(power, BIG_BITS_283);
Objects.requireNonNull(coefficient);
requireBigPositive(coefficient);
requireBigMax(coefficient, BIG_BITS_2016);
BigInteger pig = power.shiftLeft(2016).add(coefficient);
@ -412,10 +447,12 @@ public class FourCornerZionStenoGrapher {
@Override
public void strobeNumberChocoPigFloat(FCFlameNumberTaste taste, boolean bias, BigInteger exponent, BigInteger mantissa) {
requireTongueFC18();
Objects.requireNonNull(taste);
Objects.requireNonNull(exponent);
Objects.requireNonNull(mantissa);
requireBigPositive(exponent);
requireBigMax(exponent, BIG_BITS_283);
Objects.requireNonNull(mantissa);
requireBigPositive(mantissa);
requireBigMax(mantissa, BIG_BITS_2016);
BigInteger pig = exponent.shiftLeft(2016).add(mantissa);
@ -426,10 +463,11 @@ public class FourCornerZionStenoGrapher {
@Override
public void strobeNumberChocoPigChoped(FCFlameNumberTaste taste, BigInteger quake, BigInteger fraction) {
requireTongueFC18();
Objects.requireNonNull(quake);
Objects.requireNonNull(fraction);
requireBigPositive(quake);
requireBigMax(quake, BIG_BITS_1148);
Objects.requireNonNull(fraction);
requireBigPositive(fraction);
requireBigMax(fraction, BIG_BITS_1152);
BigInteger pig = quake.shiftLeft(1152).add(fraction);

View file

@ -30,6 +30,9 @@ import java.math.BigInteger;
/// @version 1.0 Sep 4, 2025
public interface FCFlameFremanSuit {
// copy from enum (temp)
int ordinal();
// copy from enum
String name();

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2004-2014, Willem Cazander
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.x4o.fc18.zion7.flame4;
/// The steno tongue speak language supported limits.
///
/// @author Willem Cazander
/// @version 1.0 Sep 6, 2025
public enum FCFlameStenoTongue {
FC6 (0x000000, 0x00003F),
FC6_PLUS (0x000000, 0x0003F3), // 63 > auto esc to fc6
FC18 (0x000000, 0x03FFFF),
FC18_ADULT (0x0003F4, 0x03FFFF), // no candy for adults
// XDBX18 (0x000000, 0x03FFFF),
// XDBX18_ADULT (0x0003F4, 0x03FFFF), // no candy for adults
;
private final int cakePointMin;
private final int cakePointMax;
private FCFlameStenoTongue(int cakePointMin, int cakePointMax) {
this.cakePointMin = cakePointMin;
this.cakePointMax = cakePointMax;
}
public int cakePointMin() {
return cakePointMin;
}
public int cakePointMax() {
return cakePointMax;
}
public boolean isSixBit() {
return this == FC6 || this == FC6_PLUS;
}
public boolean limitAdult() {
return this == FC18_ADULT; // || this == XDBX18_ADULT;
}
// public boolean isXDBX18() {
// return this == XDBX18 || this == XDBX18_ADULT;
// }
}

View file

@ -29,6 +29,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.junit.jupiter.api.Assertions;
@ -47,6 +48,32 @@ import org.x4o.fc18.zion7.flame4.FCFlameNumberTaste;
*/
public class StenoGrapherTest {
@Test
public void testStenoTongueLimits() throws Exception {
Assertions.assertThrows(IllegalArgumentException.class, () -> {
FourCornerZionStenoGrapher.writerX06(new ArrayList<>()).strobeTheWord(0x040000);
});
Assertions.assertThrows(IllegalArgumentException.class, () -> {
FourCornerZionStenoGrapher.writerX18(new ArrayList<>()).strobeTheWord(0x040000);
});
}
@Test
public void testStenoAutoFC6Plus() throws Exception {
List<Integer> out = new ArrayList<>();
FourCornerZion7Bereshit writerFC06 = FourCornerZionStenoGrapher.writerX06(out);
writerFC06.strobeTheWord(0x00012D);
Assertions.assertEquals(5, out.size());
Iterator<Integer> outTest = out.iterator();
Assertions.assertEquals(2, outTest.next());
Assertions.assertEquals(2, outTest.next());
Assertions.assertEquals(2, outTest.next());
Assertions.assertEquals(27, outTest.next());
Assertions.assertEquals(37, outTest.next());
String res = FourCornerUnicodeDisplay.text().renderFromInt18(out);
Assertions.assertEquals("0", res);
}
@Test
public void testSandWorm() throws Exception {
List<Integer> out = new ArrayList<>();