Commit 15e2c31d authored by Robert Sprowson's avatar Robert Sprowson
Browse files

Edit UTF-8 text in text entry with backspace correctly

On starting a new string using the text entry tool, cache the current alphabet, then when backspace is pressed handle deletes properly when the alphabet is UTF-8 by skipping over continuation marks until a non continuation mark is found.
The backspace code can afford to be simplistic because any invalid UTF-8 sequences already in the file when it is opened will end up (via Ctrl-E) in a Wimp writeable, which is handled by the Wimp's robust code. Only newly created strings are able to have backspace applied, so by definition they were entered just moments earlier, and so reasonable to assume they're valid UTF-8.

Having entered a string, get the bounding box right by calling Font_ScanString rather than manually walking the string with Font_CharBBox (Font_ScanString was already being used for transformed text, so rotated bounding boxes were right). Now the two are common, make a font_scanstring() function to handle both.

This could be further simplified by just editing existing strings in place, see ticket #426.

Version 1.30. Tagged as 'Draw-1_30'
parent 61f4df80
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "1.29"
Module_Version SETA 129
Module_MajorVersion SETS "1.30"
Module_Version SETA 130
Module_MinorVersion SETS ""
Module_Date SETS "02 May 2016"
Module_ApplicationDate SETS "02-May-16"
Module_Date SETS "27 Oct 2016"
Module_ApplicationDate SETS "27-Oct-16"
Module_ComponentName SETS "Draw"
Module_ComponentPath SETS "castle/RiscOS/Sources/Apps/Draw"
Module_FullVersion SETS "1.29"
Module_HelpVersion SETS "1.29 (02 May 2016)"
Module_FullVersion SETS "1.30"
Module_HelpVersion SETS "1.30 (27 Oct 2016)"
END
/* (1.29)
/* (1.30)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 1.29
#define Module_MajorVersion_CMHG 1.30
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 02 May 2016
#define Module_Date_CMHG 27 Oct 2016
#define Module_MajorVersion "1.29"
#define Module_Version 129
#define Module_MajorVersion "1.30"
#define Module_Version 130
#define Module_MinorVersion ""
#define Module_Date "02 May 2016"
#define Module_Date "27 Oct 2016"
#define Module_ApplicationDate "02-May-16"
#define Module_ApplicationDate "27-Oct-16"
#define Module_ComponentName "Draw"
#define Module_ComponentPath "castle/RiscOS/Sources/Apps/Draw"
#define Module_FullVersion "1.29"
#define Module_HelpVersion "1.29 (02 May 2016)"
#define Module_LibraryVersionInfo "1:29"
#define Module_FullVersion "1.30"
#define Module_HelpVersion "1.30 (27 Oct 2016)"
#define Module_LibraryVersionInfo "1:30"
......@@ -72,45 +72,6 @@ draw_bboxtyp *draw_displ_bbox (draw_objptr hdrptr)
}
#endif
os_error *draw_displ_font_stringpixbbox (font fonth, char *ptr,
draw_bboxtyp *boundp)
{ os_error *err = 0;
draw_bboxtyp bound = draw_big_box;
int x, y, x2, y2;
ftracef0 ("draw_displ_font_stringpixbbox\n");
x = y = 0;
while (*ptr)
{ font_info info;
err = font_charbbox (fonth, *ptr, font_OSCOORDS, &info);
err = font_converttoos (x, y, &x2, &y2);
if (x2+info.minx < bound.x0) bound.x0 = x2+info.minx;
if (y2+info.miny < bound.y0) bound.y0 = y2+info.miny;
if (x2+info.maxx > bound.x1) bound.x1 = x2+info.maxx;
if (y2+info.maxy > bound.y1) bound.y1 = y2+info.maxy;
{ font_string fs;
fs.s = ptr;
fs.x = fs.y = INT_MAX;
fs.split = -1;
fs.term = 1;
err = font_strwidth (&fs);
x += fs.x; y += fs.y;
ptr++;
}
}
*boundp = bound;
return (err);
}
/*(r/c)lpo is last point omitted */
/*(r/c)fpo is first point omitted */
/*(r/c)beo is both ends omitted */
......
......@@ -813,7 +813,7 @@ void draw_enter_delete(diagrec *diag)
bbox2 = bbox1;
bbox2.x1 = bbox2.x0;
draw_obj_deltext_char(diag); /* delete char */
draw_obj_deltext_char(diag); /* backspace char */
if (draw_obj_findtext_len (diag) == 0) /* if string empty, */
diag->misc->substate = state_text_caret; /* change state */
......
......@@ -32,6 +32,7 @@
#include <stdlib.h>
#include <string.h>
#include <swis.h>
#include "Global/Countries.h"
#include "bbc.h"
#include "bezierarc.h"
......@@ -107,6 +108,8 @@ void draw_obj_fileheader(diagrec *diag)
diag->misc->ghostlimit += sizeof(draw_fileheader);
}
static int draw_currentalphabet; /*cached system alphabet*/
static draw_groupnametyp twelvespaces = { ' ',' ',' ',' ',
' ',' ',' ',' ',
' ',' ',' ',' ',};
......@@ -115,6 +118,7 @@ void draw_obj_start(diagrec *diag, draw_tagtyp tag)
{ draw_objptr hdrptr;
int hdr_off = diag->misc->ghostlimit;
int junk;
ftracef0 ("draw_obj_start\n");
hdrptr.bytep = diag->paper + diag->misc->ghostlimit;
......@@ -136,6 +140,8 @@ void draw_obj_start(diagrec *diag, draw_tagtyp tag)
case draw_OBJTEXT:
diag->misc->ghostlimit += sizeof(draw_textstrhdr) + sizeof (char);
hdrptr.textp->text[0] = 0; /* Null text string */
draw_currentalphabet = 127; /* Read alphabet */
os_byte(71, &draw_currentalphabet, &junk);
break;
case draw_OBJPATH:
......@@ -645,10 +651,23 @@ int draw_obj_findtext_len(diagrec *diag) /* Count chars incase string is */
void draw_obj_deltext_char(diagrec *diag) /* Assumes at least 1 char present */
{ char *to = diag->paper + diag->misc->ghostlimit;
int bytes;
ftracef0 ("draw_obj_deltext_char\n");
*(to-2) = '\0'; /* Knock out with a null */
diag->misc->ghostlimit -= sizeof (char);
if (draw_currentalphabet == ISOAlphabet_UTF8)
{ to -= 2; /* Byte before the null */
bytes = 1;
while ((*to & 0xC0) == 0x80) /* Skip continuation marks */
{ bytes++;
to--;
}
*to = '\0'; /* Knock out with a null */
}
else
{ *(to-2) = '\0'; /* Knock out with a null */
bytes = 1; /* Not UTF-8, so 1 character = 1 byte */
}
diag->misc->ghostlimit -= (bytes * sizeof (char));
}
void draw_obj_addtext_term(diagrec *diag) /* text has 1 null terminator*/
......@@ -856,12 +875,40 @@ void draw_obj_bound_minmax2(draw_objptr hdrptr, draw_bboxtyp *boundp)
draw_obj_bound_minmax(bbox->x1, bbox->y1, boundp);
}
/* Local implementation of oddly missing function from RISC_OSLib */
static os_error *font_scanstring(const char *text, int options, font fonth,
const drawmod_transmat *matrix, draw_bboxtyp *bbox)
{ os_error *error;
os_regset reg_set;
struct {struct {int x, y;} space_offset; struct {int x, y;} char_offset;
int split_char; draw_bboxtyp bbox;} block;
options |= 1 << 5 /*R5 -> coordinate block*/ |
1 << 8 /*R0 = initial font handle*/ |
1 << 18 /*return bbox*/;
if (matrix != NULL)
{ options |= 1 << 6 /*R6 -> trfm*/;
reg_set.r [6] = (int) matrix;
}
reg_set.r [0] = fonth;
reg_set.r [1] = (int) text;
reg_set.r [2] = options;
reg_set.r [3] = INT_MAX;
reg_set.r [4] = INT_MAX;
reg_set.r [5] = (int) memset (&block, 0, sizeof block);
error = os_swix (Font_ScanString, &reg_set);
*bbox = block.bbox;
return error;
}
/* Code to find the bbox for just the current text object. FALSE on error */
BOOL draw_obj_findTextBox(draw_objptr hdrptr, draw_bboxtyp *bbox)
{ os_error *err = 0;
font fonth;
char *text;
{ BOOL ok = TRUE;
font fonth;
const char *text;
ftracef0 ("draw_obj_findTextBox\n");
text = &hdrptr.textp->text [0];
......@@ -871,19 +918,20 @@ BOOL draw_obj_findTextBox(draw_objptr hdrptr, draw_bboxtyp *bbox)
/* fsizex & fsizey are in 1/640ths point, current font managers */
/* take 1/16ths point, so scale by 1/40 (ie 16/640) */
if (err = font_find(draw_fontcat.name[hdrptr.textp->textstyle.fontref],
MAXZOOMFACTOR*hdrptr.textp->fsizex/40,
MAXZOOMFACTOR*hdrptr.textp->fsizey/40,
0,0, &fonth), !err)
{ err = draw_displ_font_stringpixbbox(fonth, text, bbox);
font_lose(fonth);
if (!err)
{ /* Calculate actual bbox in Draw units */
bbox->x0 = (bbox->x0 << 8)/MAXZOOMFACTOR + hdrptr.textp->coord.x;
bbox->x1 = (bbox->x1 << 8)/MAXZOOMFACTOR + hdrptr.textp->coord.x;
bbox->y0 = (bbox->y0 << 8)/MAXZOOMFACTOR + hdrptr.textp->coord.y;
bbox->y1 = (bbox->y1 << 8)/MAXZOOMFACTOR + hdrptr.textp->coord.y;
ok = font_find (draw_fontcat.name[hdrptr.textp->textstyle.fontref],
MAXZOOMFACTOR*hdrptr.textp->fsizex/40,
MAXZOOMFACTOR*hdrptr.textp->fsizey/40,
0,0, &fonth) == NULL;
if (ok)
{ ok = font_scanstring (text, 0, fonth, NULL, bbox) == NULL;
font_lose (fonth);
if (ok)
{ /* Calculate actual bbox in Draw units from millipoints */
bbox->x0 = (bbox->x0 << 8)/(400*MAXZOOMFACTOR) + hdrptr.textp->coord.x;
bbox->x1 = (bbox->x1 << 8)/(400*MAXZOOMFACTOR) + hdrptr.textp->coord.x;
bbox->y0 = (bbox->y0 << 8)/(400*MAXZOOMFACTOR) + hdrptr.textp->coord.y;
bbox->y1 = (bbox->y1 << 8)/(400*MAXZOOMFACTOR) + hdrptr.textp->coord.y;
return(TRUE);
}
......@@ -892,9 +940,7 @@ BOOL draw_obj_findTextBox(draw_objptr hdrptr, draw_bboxtyp *bbox)
/*Either text is in system font, OR an unfound fancy font (so rendered in */
/*system font) or some font manager call went bang, so.. */
/*Return BBox for system font. Assumes character base line is row 7 (of 8)*/
/*Calculate actual bbox in Draw units*/
/*Return BBox for system font. */
bbox->x0 = hdrptr.textp->coord.x;
bbox->x1 = hdrptr.textp->coord.x +
hdrptr.textp->fsizex*strlen(hdrptr.textp->text);
......@@ -902,7 +948,7 @@ BOOL draw_obj_findTextBox(draw_objptr hdrptr, draw_bboxtyp *bbox)
/* Assume char base line is row 7 (of 8) */
bbox->y1 = hdrptr.textp->coord.y + (7*hdrptr.textp->fsizey)/8;
bbox->y0 = bbox->y1 - hdrptr.textp->fsizey;
return !err;
return ok;
}
static void bound_text(draw_objptr hdrptr)
......@@ -1101,11 +1147,10 @@ static BOOL find_trfmtext_bbox (draw_objptr hdrptr, draw_bboxtyp *bbox)
{ os_error *error;
font h;
char *text;
os_regset reg_set;
struct {struct {int x, y;} space_offset; struct {int x, y;} char_offset;
int split_char; draw_bboxtyp bbox;} block;
int i;
int options;
size_t i;
const char *text;
draw_bboxtyp bounds;
ftracef0 ("find_trfmtext_bbox\n");
text = &hdrptr.trfmtextp->text [0];
......@@ -1114,66 +1159,37 @@ static BOOL find_trfmtext_bbox (draw_objptr hdrptr, draw_bboxtyp *bbox)
return find_trfmtext_system_bbox (hdrptr, bbox);
else
{ /*Find the untransformed font.*/
if ((error = font_find
(draw_fontcat.name [hdrptr.trfmtextp->textstyle.fontref],
MAXZOOMFACTOR*hdrptr.trfmtextp->fsizex/40,
MAXZOOMFACTOR*hdrptr.trfmtextp->fsizey/40,
0, 0, &h)) != NULL)
return FALSE;
reg_set.r [0] = h;
reg_set.r [1] = (int) text;
reg_set.r [2] =
1 << 5 /*R5 -> coordinate block*/ |
1 << 6 /*R6 -> trfm*/ |
1 << 8 /*R0 = initial font handle*/ |
hdrptr.trfmtextp->flags.kerned << 9 |
hdrptr.trfmtextp->flags.direction << 10 |
1 << 18 /*return bbox*/;
reg_set.r [3] = INT_MAX;
reg_set.r [4] = INT_MAX;
reg_set.r [5] = (int) memset (&block, 0, sizeof block);
reg_set.r [6] = (int) &hdrptr.trfmtextp->trfm; /*no translation used*/
if ((error = os_swix (Font_ScanString, &reg_set)) != NULL)
error = font_find (draw_fontcat.name [hdrptr.trfmtextp->textstyle.fontref],
MAXZOOMFACTOR*hdrptr.trfmtextp->fsizex/40,
MAXZOOMFACTOR*hdrptr.trfmtextp->fsizey/40,
0, 0, &h);
if (error != NULL) return FALSE;
options = (hdrptr.trfmtextp->flags.kerned ? font_KERN : 0) |
(hdrptr.trfmtextp->flags.direction ? font_RTOL : 0);
error = font_scanstring (text, options, h, &hdrptr.trfmtextp->trfm, &bounds);
if (error != NULL)
{ /*On error, try again without the trfm matrix. We don't
actually have any right at all to assume that Font_ScanString goes
wrong in the same ways and for the same reasons as Font_Paint, but
we don't have much choice.*/
ftracef1 ("find_trfmtext_bbox: *ERROR* \"%s\"\n", error->errmess);
reg_set.r [0] = h;
reg_set.r [1] = (int) text;
/*Turn off bit 6*/
reg_set.r [2] =
1 << 5 /*R5 -> coordinate block*/ |
1 << 8 /*R0 = initial font handle*/ |
hdrptr.trfmtextp->flags.kerned << 9 |
hdrptr.trfmtextp->flags.direction << 10 |
1 << 18 /*return bbox*/;
reg_set.r [3] = INT_MAX;
reg_set.r [4] = INT_MAX;
reg_set.r [5] = (int) memset (&block, 0, sizeof block);
reg_set.r [6] = (int) &hdrptr.trfmtextp->trfm; /*no translation used*/
error = os_swix (Font_ScanString, &reg_set);
error = font_scanstring (text, options, h, NULL, &bounds);
}
font_lose (h);
if (error != NULL)
{ ftracef1 ("find_trfmtext_bbox: *ERROR* \"%s\"\n", error->errmess);
font_lose (h);
return FALSE;
}
ftracef4 ("find_trfmtext_bbox: font manager gives bbox of "
"(%d, %d, %d, %d)\n", block.bbox.x0, block.bbox.y0,
block.bbox.x1, block.bbox.y1);
font_lose (h);
"(%d, %d, %d, %d)\n", bounds.x0, bounds.y0,
bounds.x1, bounds.y1);
for (i = 0; i < 4; i++)
{ (&bbox->x0) [i] = ((&block.bbox.x0) [i] << 8)/(400*MAXZOOMFACTOR);
{ /*Convert from millipoints to transformed Draw units*/
(&bbox->x0) [i] = ((&bounds.x0) [i] << 8)/(400*MAXZOOMFACTOR);
(&bbox->x0) [i] +=
!(i & 1)? hdrptr.trfmtextp->coord.x: hdrptr.trfmtextp->coord.y;
}
......
......@@ -75,9 +75,6 @@ extern void draw_displ_showcaret (viewrec *vuue);
extern void draw_displ_showcaret_if_up (diagrec *diag);
extern os_error *draw_displ_font_stringpixbbox (font fonth, char *ptr,
draw_bboxtyp *boundp);
#ifndef USETAGBBOX
extern draw_bboxtyp *draw_displ_bbox (draw_objptr hdrptr);
#else
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment