Skip to content

Commit

Permalink
Merge pull request #3632 from retcurve/edgewrite
Browse files Browse the repository at this point in the history
EdgeWrite: Accented characters
  • Loading branch information
thyttan authored Nov 1, 2024
2 parents 64c5ac9 + 34c3553 commit 7da2895
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 33 deletions.
1 change: 1 addition & 0 deletions apps/kbedgewrite/ChangeLog
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
0.01: New App!
0.02: Accents and extended mode characters
11 changes: 9 additions & 2 deletions apps/kbedgewrite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ To display the in app character chart, long press the screen; you can scroll thr

For a full character chart see [EwChart.pdf](EwChart.pdf)

**Supported:** Letters (including capitals), numbers, backspace, word backspace, space, punctuation, new line, and some cursor controls (left, right, word left/right, home, end).
**Supported:** Letters (including capitals), numbers, backspace, word backspace, space, punctuation, new line, accents, extended mode (if characters are supported by the vector font), and some cursor controls (left, right, word left/right, home, end).

**Unsupported:** Extended mode, accents, and word-level stroking.
**Unsupported:** Word-level stroking.

## Settings

Font size can be selected in Settings app > "Apps" > "EdgeWrite Keyboard"

## Author

Woogal [github](https://github.com/retcurve)
78 changes: 77 additions & 1 deletion apps/kbedgewrite/characterset.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,93 @@
"2425": "`",
"31": " \n",
"24": " ",
"46": "\xb7",
"432146": "\xb0",
"412346": "\xb0",
"123246": "\xae",
"2123246": "\xae",
"123146": "\xae",
"2123146": "\xae",
"2346": "\xac",
"32146": "\xa9",
"41236": "\xa2",
"24316": "\xd7",
"31246": "\xd7",
"316": "\xf7",
"136": "\xf7",
"232146": "\x80",
"23246": "\x80",
"132146": "\x80",
"412316": "\x80",
"323146": "\x80",
"324146": "\x80",
"24346": "\xa5",
"243416": "\xa5",
"2143416": "\xa5",
"34146": "\xf0",
"342146": "\xf0",
"343146": "\xf0",
"4214346": "\xf0",
"414346": "\xf0",
"434146": "\xf0",
"123416": "\xf0",
"2123416": "\xf0",
"1346": "\xe6",
"1246": "\xe6",
"13416": "\xe6",
"12416": "\xe6",
"3214346": "\xe6",
"21416": "\xdf",
"213416": "\xdf",
"212416": "\xdf",
"141216": "\xdf",
"1341216": "\xdf",
"121416": "\xdf",
"1232416": "\xdf",
"1231416": "\xdf",
"21232416": "\xdf",
"21231416": "\xdf",
"2321416": "\xdf",
"2146": "\xa3",
"21436": "\xb5",
"214346": "\xb5",
"121436": "\xb5",
"1214346": "\xb5",
"3214316": "\xf8",
"3412316": "\xf8",
"4126": "\xbf",
"216": "\xa1",
"346": "\xa6",
"21236": "\xb1",
"212326": "\xb1",
"31426": "\xa4",
"24136": "\xa4",
"3146": "\xab",
"2416": "\xbb",
"32": "#bs",
"41": "#wbs",
"12": "#pu-on",
"43": "#pu-on",
"325": "#pu-off",
"415": "#pu-off",
"42": "#ex-on",
"326": "#ex-off",
"416": "#ex-off",
"323": "#cur-left",
"232": "#cur-right",
"414": "#cur-word-left",
"141": "#cur-word-right",
"4141": "#cur-home",
"1414": "#cur-end"
"1414": "#cur-end",
"242": "#grave",
"313": "#acute",
"431": "#circumflex",
"421": "#circumflex",
"3421": "#tilde",
"43412": "#umlaut",
"43214": "#ring",
"41234": "#ring",
"142": "#cedilla",
"143": "#cedilla"
}

192 changes: 164 additions & 28 deletions apps/kbedgewrite/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,161 @@ exports.input = function(options) {
let chartX = 0;
let chartY = 0;

let settings = Object.assign({
fontSize: 32,
}, require('Storage').readJSON("kbedgewrite.json", true));

let shouldShowWidgetBar = Bangle.appRect.y > 0;

options = options||{};
let text = options.text;
// Substring doesn't play well with UTF8
if (E.isUTF8(text)) {
text = E.decodeUTF8(text);
}
let wrappedText = '';

if ('string' != typeof text) text='';

// Colours for number of corner occurrences
let colours = ['#ff0', '#0f0', '#f00', '#00f' ,'#0ff', '#f0f', '#fff'];

const cornerSize = g.getWidth() / 3;
let punctuationMode = false;
let extendedMode = false;
let path = '';
let cursorPos = text.length;
let chartShown = false;

let characterSet = Object.assign({}, require('Storage').readJSON('kbedgewrite.charset.json', true) || {});

function draw() {
g.clearRect(Bangle.appRect).setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2);
const accentedCharacters = {
'#grave': {
'a': String.fromCharCode(0xE0),
'A': String.fromCharCode(0xC0),
'e': String.fromCharCode(0xE8),
'E': String.fromCharCode(0xC8),
'i': String.fromCharCode(0xEC),
'I': String.fromCharCode(0xCC),
'o': String.fromCharCode(0xF2),
'O': String.fromCharCode(0xD2),
'u': String.fromCharCode(0xF9),
'U': String.fromCharCode(0xD9)
},
'#acute': {
'a': String.fromCharCode(0xE1),
'A': String.fromCharCode(0xC1),
'e': String.fromCharCode(0xE9),
'E': String.fromCharCode(0xC9),
'i': String.fromCharCode(0xED),
'I': String.fromCharCode(0xCD),
'o': String.fromCharCode(0xF3),
'O': String.fromCharCode(0xD3),
'u': String.fromCharCode(0xFA),
'U': String.fromCharCode(0xDA),
'y': String.fromCharCode(0xFD),
'Y': String.fromCharCode(0xDD)
},
'#circumflex': {
'a': String.fromCharCode(0xE2),
'A': String.fromCharCode(0xC2),
'e': String.fromCharCode(0xEA),
'E': String.fromCharCode(0xCA),
'i': String.fromCharCode(0xEE),
'I': String.fromCharCode(0xCE),
'o': String.fromCharCode(0xF4),
'O': String.fromCharCode(0xD4),
'u': String.fromCharCode(0xFB),
'U': String.fromCharCode(0xDB)
},
'#umlaut': {
'a': String.fromCharCode(0xE4),
'A': String.fromCharCode(0xC4),
'e': String.fromCharCode(0xEB),
'E': String.fromCharCode(0xCB),
'i': String.fromCharCode(0xEF),
'I': String.fromCharCode(0xCF),
'o': String.fromCharCode(0xF6),
'O': String.fromCharCode(0xD6),
'u': String.fromCharCode(0xFC),
'U': String.fromCharCode(0xDC),
'y': String.fromCharCode(0xFF)
},
'#tilde': {
'a': String.fromCharCode(0xE3),
'A': String.fromCharCode(0xC3),
'n': String.fromCharCode(0xF1),
'N': String.fromCharCode(0xD1),
'o': String.fromCharCode(0xF5),
'O': String.fromCharCode(0xD5)
},
'#ring': {
'a': String.fromCharCode(0xE5),
'A': String.fromCharCode(0xC5)
},
'#cedilla': {
'c': String.fromCharCode(0xE7),
'C': String.fromCharCode(0xC7)
},

};

function wrapText() {
let stringToWrap = text.substring(0, cursorPos) + '_' + text.substring(cursorPos);
let l = [];
let startPos = 0;

// Draw the text string
let l = g.setFont('6x8:4').wrapString(text.substring(0, cursorPos) + '_' + text.substring(cursorPos), g.getWidth());
if (!l) l = [];
if (l.length>5) {
g.setFont("Vector", settings.fontSize); // set the font so we can calculate a string width

// Wrap the string into array of lines that will fit the screen width
for (let i = 0; i < stringToWrap.length; i++) {
// wrap if string is too long or we hit a line break
if (stringToWrap.charCodeAt(i) == 10 || g.stringWidth(stringToWrap.substring(startPos, i+1)) > 176) {
l.push(stringToWrap.substring(startPos, i));
// skip the line break
if (stringToWrap.charCodeAt(i) == 10) {
i++;
}
startPos = i;
}
}
// Add the final line
l.push(stringToWrap.substring(startPos));

// Number of lines that can fit on the screen
let numLines = Math.floor(g.getHeight() / g.getFontHeight());

// If too many lines, reposition so the cursor can be seen
if (l.length > numLines) {
let textPos = 0;
let lineNum;
for (lineNum = 0; lineNum < l.length; lineNum++) {
textPos = textPos + l[lineNum].length - 1;
textPos = textPos + l[lineNum].length;
if (textPos >= cursorPos) break;
}
l=l.slice(lineNum - l.length - 5);
l=l.slice(lineNum - l.length - numLines + 1);
}

wrappedText = l.join('\n');
}

function draw() {
g.clearRect(Bangle.appRect).setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2);

g.setColor(g.theme.fg);
g.setFont("Vector", settings.fontSize);
g.setFontAlign(-1, -1, 0);
g.drawString(l.join('\n'), Bangle.appRect.x, Bangle.appRect.y);
g.drawString(wrappedText, Bangle.appRect.x, Bangle.appRect.y);

// Draw punctuation flag
if (punctuationMode > 0) {
// Draw punctuation or extended flags
if (punctuationMode || extendedMode) {
let x = (g.getWidth() / 2) - 12;
let y = g.getHeight() - 32;
g.setColor('#F00');
g.setColor(punctuationMode ? '#F00' : '#0F0');
g.fillRect(x,y,x+24,y+32);
g.setColor('#FFF');
g.setFont('6x8:4');
g.drawString('P', x+4, y+4, false);
g.drawString(punctuationMode ? 'P' : 'E', x+4, y+4, false);
}

// Draw corners
Expand All @@ -69,30 +179,27 @@ exports.input = function(options) {
}

function processPath() {
let capital = false;

// Punctuation paths end in 5
if (punctuationMode) {
path = path + '5';
}

// Capital letters end in 2, remove that and set a capital flag
// but only if the path isn't 232 (cursor right)
if (path != '232' && path.length > 2 && path.slice(-1) == '2') {
path = path.slice(0,-1);
capital = true;
// Extended paths end in 6
if (extendedMode) {
path = path + '6';
}

// Find character from path
let char = characterSet[path];

// Handle capitals
if (capital && char != 'undefined') {
if (char.charCodeAt(0)>96 && char.charCodeAt(0)<123) {
char = char.toUpperCase();
} else {
// Anything that can't be capitalised is an invalid path
char = undefined;
// Unknown character, but ends in a 2 so may be a capital letter
if (char == 'undefined' && path.slice(-1) == '2') {
// Remove the 2 and look for a letter
char = characterSet[path.slice(0,-1)];
// Handle capitals
if (char != 'undefined') {
if (char.charCodeAt(0)>96 && char.charCodeAt(0)<123) {
char = char.toUpperCase();
}
}
}

Expand Down Expand Up @@ -129,6 +236,17 @@ exports.input = function(options) {
punctuationMode = false;
break;
}
// Enable extended mode
case '#ex-on': {
extendedMode = true;
break;
}
// Disable extended mode
case '#ex-off': {
extendedMode = false;
break;
}
// Cursor controls
case '#cur-left': {
if (cursorPos > 0) {
cursorPos--;
Expand Down Expand Up @@ -168,6 +286,22 @@ exports.input = function(options) {
cursorPos = text.length;
break;
}
// Accents
case '#grave':
case '#acute':
case '#circumflex':
case '#umlaut':
case '#tilde':
case '#ring':
case '#cedilla':
// If the previous character can be accented, replace it with the accented version
if (cursorPos > 0) {
char = accentedCharacters[char][text.substring(cursorPos-1, cursorPos)];
if (char != 'undefined') {
text = text.substring(0, cursorPos-1) + char + text.substring(cursorPos);
}
}
break;
// Append character
default: {
text = text.substring(0, cursorPos) + char + text.substring(cursorPos);
Expand All @@ -184,6 +318,7 @@ exports.input = function(options) {
if (!chartShown) {
if (e.b == 0) { // Finger lifted, process completed path
processPath();
wrapText();
draw();
} else {
let corner = 0;
Expand Down Expand Up @@ -220,6 +355,7 @@ exports.input = function(options) {
// Draw initial string
require("widget_utils").hide();
g.setBgColor(g.theme.bg);
wrapText();
draw();

return new Promise((resolve,reject) => {
Expand Down
Loading

0 comments on commit 7da2895

Please sign in to comment.