summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
Diffstat (limited to 'render')
-rw-r--r--render/textplain.c918
-rw-r--r--render/textplain.h102
2 files changed, 536 insertions, 484 deletions
diff --git a/render/textplain.c b/render/textplain.c
index d3768889d..5d28d9c54 100644
--- a/render/textplain.c
+++ b/render/textplain.c
@@ -17,8 +17,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for text/plain (implementation).
+/**
+ * \file
+ *
+ * plain text content handling implementation.
*/
#include <assert.h>
@@ -85,7 +87,6 @@ typedef struct textplain_content {
#define CHUNK 32768 /* Must be a power of 2 */
#define MARGIN 4
-
#define TAB_WIDTH 8 /* must be power of 2 currently */
#define TEXT_SIZE 10 * FONT_SIZE_SCALE /* Unscaled text size in pt */
@@ -100,96 +101,13 @@ static plot_font_style_t textplain_style = {
static int textplain_tab_width = 256; /* try for a sensible default */
-static void textplain_fini(void);
-static nserror textplain_create(const content_handler *handler,
- lwc_string *imime_type, const http_parameter *params,
- llcache_handle *llcache, const char *fallback_charset,
- bool quirks, struct content **c);
-static nserror textplain_create_internal(textplain_content *c,
- lwc_string *charset);
-static bool textplain_process_data(struct content *c,
- const char *data, unsigned int size);
-static bool textplain_convert(struct content *c);
-static void textplain_mouse_track(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
-static void textplain_mouse_action(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
-static bool textplain_keypress(struct content *c, uint32_t key);
-static void textplain_search(struct content *c, void *gui_data,
- search_flags_t flags, const char *string);
-static void textplain_search_clear(struct content *c);
-static void textplain_reformat(struct content *c, int width, int height);
-static void textplain_destroy(struct content *c);
-static bool textplain_redraw(struct content *c, struct content_redraw_data *data,
- const struct rect *clip, const struct redraw_context *ctx);
-static void textplain_open(struct content *c, struct browser_window *bw,
- struct content *page, struct object_params *params);
-void textplain_close(struct content *c);
-char *textplain_get_selection(struct content *c);
-static nserror textplain_clone(const struct content *old,
- struct content **newc);
-static content_type textplain_content_type(void);
-
-static parserutils_error textplain_charset_hack(const uint8_t *data, size_t len,
- uint16_t *mibenum, uint32_t *source);
-static bool textplain_drain_input(textplain_content *c,
- parserutils_inputstream *stream, parserutils_error terminator);
-static bool textplain_copy_utf8_data(textplain_content *c,
- const uint8_t *buf, size_t len);
-static int textplain_coord_from_offset(const char *text, size_t offset,
- size_t length);
-static float textplain_line_height(void);
-
-static const content_handler textplain_content_handler = {
- .fini = textplain_fini,
- .create = textplain_create,
- .process_data = textplain_process_data,
- .data_complete = textplain_convert,
- .reformat = textplain_reformat,
- .destroy = textplain_destroy,
- .mouse_track = textplain_mouse_track,
- .mouse_action = textplain_mouse_action,
- .keypress = textplain_keypress,
- .search = textplain_search,
- .search_clear = textplain_search_clear,
- .redraw = textplain_redraw,
- .open = textplain_open,
- .close = textplain_close,
- .get_selection = textplain_get_selection,
- .clone = textplain_clone,
- .type = textplain_content_type,
- .no_share = true,
-};
-
static lwc_string *textplain_default_charset;
-/**
- * Initialise the text content handler
- */
-nserror textplain_init(void)
-{
- lwc_error lerror;
- nserror error;
-
- lerror = lwc_intern_string("Windows-1252", SLEN("Windows-1252"),
- &textplain_default_charset);
- if (lerror != lwc_error_ok) {
- return NSERROR_NOMEM;
- }
-
- error = content_factory_register_handler("text/plain",
- &textplain_content_handler);
- if (error != NSERROR_OK) {
- lwc_string_unref(textplain_default_charset);
- }
-
- return error;
-}
/**
* Clean up after the text content handler
*/
-void textplain_fini(void)
+static void textplain_fini(void)
{
if (textplain_default_charset != NULL) {
lwc_string_unref(textplain_default_charset);
@@ -197,67 +115,37 @@ void textplain_fini(void)
}
}
-/**
- * Create a CONTENT_TEXTPLAIN.
- */
-
-nserror textplain_create(const content_handler *handler,
- lwc_string *imime_type, const http_parameter *params,
- llcache_handle *llcache, const char *fallback_charset,
- bool quirks, struct content **c)
-{
- textplain_content *text;
- nserror error;
- lwc_string *encoding;
-
- text = calloc(1, sizeof(textplain_content));
- if (text == NULL)
- return NSERROR_NOMEM;
-
- error = content__init(&text->base, handler, imime_type, params,
- llcache, fallback_charset, quirks);
- if (error != NSERROR_OK) {
- free(text);
- return error;
- }
-
- error = http_parameter_list_find_item(params, corestring_lwc_charset,
- &encoding);
- if (error != NSERROR_OK) {
- encoding = lwc_string_ref(textplain_default_charset);
- }
- error = textplain_create_internal(text, encoding);
- if (error != NSERROR_OK) {
- lwc_string_unref(encoding);
- free(text);
- return error;
- }
-
- lwc_string_unref(encoding);
-
- *c = (struct content *) text;
-
- return NSERROR_OK;
-}
-
-/*
- * Hack around bug in libparserutils: if the client provides an
- * encoding up front, but does not provide a charset detection
- * callback, then libparserutils will replace the provided encoding
- * with UTF-8. This breaks our input handling.
+/**
+ * Work around feature in libparserutils
+ *
+ * if the client provides an encoding up front, but does not provide a
+ * charset detection callback, then libparserutils will replace the
+ * provided encoding with UTF-8. This breaks our input handling.
*
- * We avoid this by providing a callback that does precisely nothing,
+ * Avoid this by providing a callback that does precisely nothing,
* thus preserving whatever charset information we decided on in
* textplain_create.
*/
-parserutils_error textplain_charset_hack(const uint8_t *data, size_t len,
- uint16_t *mibenum, uint32_t *source)
+static parserutils_error
+textplain_charset_hack(const uint8_t *data,
+ size_t len,
+ uint16_t *mibenum,
+ uint32_t *source)
{
return PARSERUTILS_OK;
-}
+}
+
-nserror textplain_create_internal(textplain_content *c, lwc_string *encoding)
+/**
+ * setup plain text render.
+ *
+ * \param[in] c content object.
+ * \param[in] encoding the encoding of the content.
+ * \return NSERROR_OK else appropriate error code.
+ */
+static nserror
+textplain_create_internal(textplain_content *c, lwc_string *encoding)
{
char *utf8_data;
parserutils_inputstream *stream;
@@ -270,18 +158,18 @@ nserror textplain_create_internal(textplain_content *c, lwc_string *encoding)
if (utf8_data == NULL)
goto no_memory;
- error = parserutils_inputstream_create(lwc_string_data(encoding), 0,
- textplain_charset_hack, &stream);
+ error = parserutils_inputstream_create(lwc_string_data(encoding), 0,
+ textplain_charset_hack, &stream);
if (error == PARSERUTILS_BADENCODING) {
/* Fall back to Windows-1252 */
error = parserutils_inputstream_create("Windows-1252", 0,
- textplain_charset_hack, &stream);
+ textplain_charset_hack, &stream);
}
if (error != PARSERUTILS_OK) {
free(utf8_data);
goto no_memory;
}
-
+
c->encoding = lwc_string_ref(encoding);
c->inputstream = stream;
c->utf8_data = utf8_data;
@@ -299,28 +187,110 @@ nserror textplain_create_internal(textplain_content *c, lwc_string *encoding)
no_memory:
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+
return NSERROR_NOMEM;
}
-bool textplain_drain_input(textplain_content *c,
- parserutils_inputstream *stream,
- parserutils_error terminator)
+
+/**
+ * Create a CONTENT_TEXTPLAIN.
+ */
+static nserror
+textplain_create(const content_handler *handler,
+ lwc_string *imime_type,
+ const http_parameter *params,
+ llcache_handle *llcache,
+ const char *fallback_charset,
+ bool quirks,
+ struct content **c)
+{
+ textplain_content *text;
+ nserror error;
+ lwc_string *encoding;
+
+ text = calloc(1, sizeof(textplain_content));
+ if (text == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ error = content__init(&text->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(text);
+ return error;
+ }
+
+ error = http_parameter_list_find_item(params, corestring_lwc_charset,
+ &encoding);
+ if (error != NSERROR_OK) {
+ encoding = lwc_string_ref(textplain_default_charset);
+ }
+
+ error = textplain_create_internal(text, encoding);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(encoding);
+ free(text);
+ return error;
+ }
+
+ lwc_string_unref(encoding);
+
+ *c = (struct content *) text;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * copy utf8 encoded data
+ */
+static bool
+textplain_copy_utf8_data(textplain_content *c, const uint8_t *buf, size_t len)
+{
+ if (c->utf8_data_size + len >= c->utf8_data_allocated) {
+ /* Compute next multiple of chunk above the required space */
+ size_t allocated;
+ char *utf8_data;
+
+ allocated = (c->utf8_data_size + len + CHUNK - 1) & ~(CHUNK - 1);
+ utf8_data = realloc(c->utf8_data, allocated);
+ if (utf8_data == NULL)
+ return false;
+
+ c->utf8_data = utf8_data;
+ c->utf8_data_allocated = allocated;
+ }
+
+ memcpy(c->utf8_data + c->utf8_data_size, buf, len);
+ c->utf8_data_size += len;
+
+ return true;
+}
+
+
+/**
+ * drain input
+ */
+static bool
+textplain_drain_input(textplain_content *c,
+ parserutils_inputstream *stream,
+ parserutils_error terminator)
{
static const uint8_t *u_fffd = (const uint8_t *) "\xef\xbf\xfd";
const uint8_t *ch;
size_t chlen, offset = 0;
- while (parserutils_inputstream_peek(stream, offset, &ch, &chlen) !=
- terminator) {
+ while (parserutils_inputstream_peek(stream, offset, &ch, &chlen) !=
+ terminator) {
/* Replace all instances of NUL with U+FFFD */
if (chlen == 1 && *ch == 0) {
if (offset > 0) {
/* Obtain pointer to start of input data */
- parserutils_inputstream_peek(stream, 0,
- &ch, &chlen);
+ parserutils_inputstream_peek(stream, 0,
+ &ch, &chlen);
/* Copy from it up to the start of the NUL */
- if (textplain_copy_utf8_data(c, ch,
- offset) == false)
+ if (textplain_copy_utf8_data(c, ch,
+ offset) == false)
return false;
}
@@ -338,12 +308,12 @@ bool textplain_drain_input(textplain_content *c,
if (offset > CHUNK) {
/* Obtain pointer to start of input data */
- parserutils_inputstream_peek(stream, 0,
- &ch, &chlen);
+ parserutils_inputstream_peek(stream, 0,
+ &ch, &chlen);
/* Emit the data we've read */
- if (textplain_copy_utf8_data(c, ch,
- offset) == false)
+ if (textplain_copy_utf8_data(c, ch,
+ offset) == false)
return false;
/* Advance the inputstream */
@@ -356,7 +326,7 @@ bool textplain_drain_input(textplain_content *c,
if (offset > 0) {
/* Obtain pointer to start of input data */
- parserutils_inputstream_peek(stream, 0, &ch, &chlen);
+ parserutils_inputstream_peek(stream, 0, &ch, &chlen);
/* Emit any data remaining */
if (textplain_copy_utf8_data(c, ch, offset) == false)
return false;
@@ -368,44 +338,20 @@ bool textplain_drain_input(textplain_content *c,
return true;
}
-bool textplain_copy_utf8_data(textplain_content *c,
- const uint8_t *buf, size_t len)
-{
- if (c->utf8_data_size + len >= c->utf8_data_allocated) {
- /* Compute next multiple of chunk above the required space */
- size_t allocated;
- char *utf8_data;
-
- allocated = (c->utf8_data_size + len + CHUNK - 1) & ~(CHUNK - 1);
- utf8_data = realloc(c->utf8_data, allocated);
- if (utf8_data == NULL)
- return false;
-
- c->utf8_data = utf8_data;
- c->utf8_data_allocated = allocated;
- }
-
- memcpy(c->utf8_data + c->utf8_data_size, buf, len);
- c->utf8_data_size += len;
-
- return true;
-}
-
/**
* Process data for CONTENT_TEXTPLAIN.
*/
-
-bool textplain_process_data(struct content *c,
- const char *data, unsigned int size)
+static bool
+textplain_process_data(struct content *c, const char *data, unsigned int size)
{
textplain_content *text = (textplain_content *) c;
parserutils_inputstream *stream = text->inputstream;
union content_msg_data msg_data;
parserutils_error error;
- error = parserutils_inputstream_append(stream,
- (const uint8_t *) data, size);
+ error = parserutils_inputstream_append(stream,
+ (const uint8_t *) data, size);
if (error != PARSERUTILS_OK) {
goto no_memory;
}
@@ -425,8 +371,7 @@ no_memory:
/**
* Convert a CONTENT_TEXTPLAIN for display.
*/
-
-bool textplain_convert(struct content *c)
+static bool textplain_convert(struct content *c)
{
textplain_content *text = (textplain_content *) c;
parserutils_inputstream *stream = text->inputstream;
@@ -452,10 +397,23 @@ bool textplain_convert(struct content *c)
/**
- * Reformat a CONTENT_TEXTPLAIN to a new width.
+ * Calculate the line height, in pixels
+ *
+ * \return Line height, in pixels
*/
+static float textplain_line_height(void)
+{
+ /* Size is in points, so convert to pixels.
+ * Then use a constant line height of 1.2 x font size.
+ */
+ return FIXTOFLT(FDIV((FMUL(FLTTOFIX(1.2), FMUL(nscss_screen_dpi, INTTOFIX((textplain_style.size / FONT_SIZE_SCALE))))), F_72));
+}
-void textplain_reformat(struct content *c, int width, int height)
+
+/**
+ * Reformat a CONTENT_TEXTPLAIN to a new width.
+ */
+static void textplain_reformat(struct content *c, int width, int height)
{
textplain_content *text = (textplain_content *) c;
char *utf8_data = text->utf8_data;
@@ -521,23 +479,25 @@ void textplain_reformat(struct content *c, int width, int height)
if (term || next_col >= columns) {
if (line_count % 1024 == 0) {
- line1 = realloc(line,
- sizeof(struct textplain_line) *
+ line1 = realloc(line,
+ sizeof(struct textplain_line) *
(line_count + 1024 + 3));
if (!line1)
goto no_memory;
text->physical_line = line = line1;
}
+
if (term) {
line[line_count-1].length = i - line_start;
/* skip second char of CR/LF or LF/CR pair */
if (i + 1 < utf8_data_size &&
- utf8_data[i+1] != utf8_data[i] &&
- (utf8_data[i+1] == '\n' || utf8_data[i+1] == '\r'))
+ utf8_data[i+1] != utf8_data[i] &&
+ (utf8_data[i+1] == '\n' ||
+ utf8_data[i+1] == '\r')) {
i++;
- }
- else {
+ }
+ } else {
if (space) {
/* break at last space in line */
i = space;
@@ -545,6 +505,7 @@ void textplain_reformat(struct content *c, int width, int height)
} else
line[line_count-1].length = i - line_start;
}
+
line[line_count++].start = line_start = i + 1;
col = 0;
space = 0;
@@ -574,7 +535,7 @@ no_memory:
* Destroy a CONTENT_TEXTPLAIN and free all resources it owns.
*/
-void textplain_destroy(struct content *c)
+static void textplain_destroy(struct content *c)
{
textplain_content *text = (textplain_content *) c;
@@ -594,7 +555,7 @@ void textplain_destroy(struct content *c)
}
-nserror textplain_clone(const struct content *old, struct content **newc)
+static nserror textplain_clone(const struct content *old, struct content **newc)
{
const textplain_content *old_text = (textplain_content *) old;
textplain_content *text;
@@ -628,7 +589,7 @@ nserror textplain_clone(const struct content *old, struct content **newc)
}
if (old->status == CONTENT_STATUS_READY ||
- old->status == CONTENT_STATUS_DONE) {
+ old->status == CONTENT_STATUS_DONE) {
if (textplain_convert(&text->base) == false) {
content_destroy(&text->base);
return NSERROR_CLONE_FAILED;
@@ -638,71 +599,27 @@ nserror textplain_clone(const struct content *old, struct content **newc)
return NSERROR_OK;
}
-content_type textplain_content_type(void)
-{
- return CONTENT_TEXTPLAIN;
-}
-
-/**
- * Handle mouse tracking (including drags) in a TEXTPLAIN content window.
- *
- * \param c content of type textplain
- * \param bw browser window
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- */
-void textplain_mouse_track(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
+static content_type textplain_content_type(void)
{
- textplain_content *text = (textplain_content *) c;
-
- if (browser_window_get_drag_type(bw) == DRAGGING_SELECTION && !mouse) {
- int dir = -1;
- size_t idx;
-
- if (selection_dragging_start(&text->sel))
- dir = 1;
-
- idx = textplain_offset_from_coords(c, x, y, dir);
- selection_track(&text->sel, mouse, idx);
-
- browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);
- }
-
- switch (browser_window_get_drag_type(bw)) {
-
- case DRAGGING_SELECTION: {
- int dir = -1;
- size_t idx;
-
- if (selection_dragging_start(&text->sel)) dir = 1;
-
- idx = textplain_offset_from_coords(c, x, y, dir);
- selection_track(&text->sel, mouse, idx);
- }
- break;
-
- default:
- textplain_mouse_action(c, bw, mouse, x, y);
- break;
- }
+ return CONTENT_TEXTPLAIN;
}
/**
* Handle mouse clicks and movements in a TEXTPLAIN content window.
*
- * \param c content of type textplain
- * \param bw browser window
- * \param mouse mouse state on action
- * \param x coordinate of mouse
- * \param y coordinate of mouse
+ * \param c content of type textplain
+ * \param bw browser window
+ * \param mouse mouse state on action
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
*/
-
-void textplain_mouse_action(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
+static void
+textplain_mouse_action(struct content *c,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
{
textplain_content *text = (textplain_content *) c;
browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
@@ -718,7 +635,7 @@ void textplain_mouse_action(struct content *c, struct browser_window *bw,
if (selection_dragging(&text->sel)) {
browser_window_set_drag_type(bw,
- DRAGGING_SELECTION, NULL);
+ DRAGGING_SELECTION, NULL);
status = messages_get("Selecting");
}
@@ -738,14 +655,63 @@ void textplain_mouse_action(struct content *c, struct browser_window *bw,
/**
+ * Handle mouse tracking (including drags) in a TEXTPLAIN content window.
+ *
+ * \param c content of type textplain
+ * \param bw browser window
+ * \param mouse state of mouse buttons and modifier keys
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ */
+static void
+textplain_mouse_track(struct content *c,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ textplain_content *text = (textplain_content *) c;
+
+ if (browser_window_get_drag_type(bw) == DRAGGING_SELECTION && !mouse) {
+ int dir = -1;
+ size_t idx;
+
+ if (selection_dragging_start(&text->sel))
+ dir = 1;
+
+ idx = textplain_offset_from_coords(c, x, y, dir);
+ selection_track(&text->sel, mouse, idx);
+
+ browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);
+ }
+
+ switch (browser_window_get_drag_type(bw)) {
+
+ case DRAGGING_SELECTION: {
+ int dir = -1;
+ size_t idx;
+
+ if (selection_dragging_start(&text->sel)) dir = 1;
+
+ idx = textplain_offset_from_coords(c, x, y, dir);
+ selection_track(&text->sel, mouse, idx);
+ }
+ break;
+
+ default:
+ textplain_mouse_action(c, bw, mouse, x, y);
+ break;
+ }
+}
+
+
+/**
* Handle keypresses.
*
* \param c content of type CONTENT_TEXTPLAIN
* \param key The UCS4 character codepoint
* \return true if key handled, false otherwise
*/
-
-bool textplain_keypress(struct content *c, uint32_t key)
+static bool textplain_keypress(struct content *c, uint32_t key)
{
textplain_content *text = (textplain_content *) c;
struct selection *sel = &text->sel;
@@ -778,6 +744,27 @@ bool textplain_keypress(struct content *c, uint32_t key)
/**
+ * Terminate a search.
+ *
+ * \param c content of type text
+ */
+static void textplain_search_clear(struct content *c)
+{
+ textplain_content *text = (textplain_content *) c;
+
+ assert(c != NULL);
+
+ free(text->search_string);
+ text->search_string = NULL;
+
+ if (text->search != NULL) {
+ search_destroy_context(text->search);
+ }
+ text->search = NULL;
+}
+
+
+/**
* Handle search.
*
* \param c content of type text
@@ -785,16 +772,16 @@ bool textplain_keypress(struct content *c, uint32_t key)
* \param flags search flags
* \param string search string
*/
-void textplain_search(struct content *c, void *gui_data,
- search_flags_t flags, const char *string)
+static void textplain_search(struct content *c, void *gui_data,
+ search_flags_t flags, const char *string)
{
textplain_content *text = (textplain_content *) c;
assert(c != NULL);
if (string != NULL && text->search_string != NULL &&
- strcmp(string, text->search_string) == 0 &&
- text->search != NULL) {
+ strcmp(string, text->search_string) == 0 &&
+ text->search != NULL) {
/* Continue prev. search */
search_step(text->search, flags, string);
@@ -811,7 +798,7 @@ void textplain_search(struct content *c, void *gui_data,
}
text->search = search_create_context(c, CONTENT_TEXTPLAIN,
- gui_data);
+ gui_data);
if (text->search == NULL)
return;
@@ -829,39 +816,21 @@ void textplain_search(struct content *c, void *gui_data,
/**
- * Terminate a search.
- *
- * \param c content of type text
- */
-void textplain_search_clear(struct content *c)
-{
- textplain_content *text = (textplain_content *) c;
-
- assert(c != NULL);
-
- free(text->search_string);
- text->search_string = NULL;
-
- if (text->search != NULL)
- search_destroy_context(text->search);
- text->search = NULL;
-}
-
-
-/**
* Draw a CONTENT_TEXTPLAIN using the current set of plotters (plot).
*
+ * x, y, clip_[xy][01] are in target coordinates.
+ *
* \param c content of type CONTENT_TEXTPLAIN
* \param data redraw data for this content redraw
* \param clip current clip region
* \param ctx current redraw context
* \return true if successful, false otherwise
- *
- * x, y, clip_[xy][01] are in target coordinates.
*/
-
-bool textplain_redraw(struct content *c, struct content_redraw_data *data,
- const struct rect *clip, const struct redraw_context *ctx)
+static bool
+textplain_redraw(struct content *c,
+ struct content_redraw_data *data,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
{
textplain_content *text = (textplain_content *) c;
struct browser_window *bw = text->bw;
@@ -931,20 +900,20 @@ bool textplain_redraw(struct content *c, struct content_redraw_data *data,
next_offset = utf8_next(text_d, length, next_offset);
if (!text_redraw(text_d + offset, next_offset - offset,
- line[lineno].start + offset, 0,
- &textplain_style,
- tx, y + (lineno * scaled_line_height),
- clip, line_height, data->scale, false,
- (struct content *)text, &text->sel,
- text->search, ctx))
+ line[lineno].start + offset, 0,
+ &textplain_style,
+ tx, y + (lineno * scaled_line_height),
+ clip, line_height, data->scale, false,
+ (struct content *)text, &text->sel,
+ text->search, ctx))
return false;
if (next_offset >= length)
break;
res = guit->layout->width(&textplain_style,
- &text_d[offset],
- next_offset - offset,
+ &text_d[offset],
+ next_offset - offset,
&width);
/* locate end of string and align to next tab position */
if (res == NSERROR_OK) {
@@ -953,9 +922,11 @@ bool textplain_redraw(struct content *c, struct content_redraw_data *data,
ntx = x + ((1 + (tx - x) / tab_width) * tab_width);
- /* if the tab character lies within the selection, if any,
- then we must draw it as a filled rectangle so that it's
- consistent with background of the selected text */
+ /* if the tab character lies within the
+ * selection, if any, then we must draw it as
+ * a filled rectangle so that it's consistent
+ * with background of the selected text
+ */
if (bw) {
unsigned tab_ofst = line[lineno].start + next_offset;
@@ -965,17 +936,21 @@ bool textplain_redraw(struct content *c, struct content_redraw_data *data,
if (selection_defined(sel)) {
unsigned start_idx, end_idx;
if (selection_highlighted(sel,
- tab_ofst, tab_ofst + 1,
- &start_idx, &end_idx))
+ tab_ofst,
+ tab_ofst + 1,
+ &start_idx,
+ &end_idx))
highlighted = true;
}
if (!highlighted && (text->search != NULL)) {
unsigned start_idx, end_idx;
if (search_term_highlighted(c,
- tab_ofst, tab_ofst + 1,
- &start_idx, &end_idx,
- text->search))
+ tab_ofst,
+ tab_ofst + 1,
+ &start_idx,
+ &end_idx,
+ text->search))
highlighted = true;
}
@@ -1006,9 +981,11 @@ bool textplain_redraw(struct content *c, struct content_redraw_data *data,
/**
* Handle a window containing a CONTENT_TEXTPLAIN being opened.
*/
-
-void textplain_open(struct content *c, struct browser_window *bw,
- struct content *page, struct object_params *params)
+static void
+textplain_open(struct content *c,
+ struct browser_window *bw,
+ struct content *page,
+ struct object_params *params)
{
textplain_content *text = (textplain_content *) c;
@@ -1022,13 +999,13 @@ void textplain_open(struct content *c, struct browser_window *bw,
/**
* Handle a window containing a CONTENT_TEXTPLAIN being closed.
*/
-
-void textplain_close(struct content *c)
+static void textplain_close(struct content *c)
{
textplain_content *text = (textplain_content *) c;
- if (text->search != NULL)
+ if (text->search != NULL) {
search_destroy_context(text->search);
+ }
text->bw = NULL;
}
@@ -1037,20 +1014,107 @@ void textplain_close(struct content *c)
/**
* Return an textplain content's selection context
*/
-
-char *textplain_get_selection(struct content *c)
+static char *textplain_get_selection(struct content *c)
{
textplain_content *text = (textplain_content *) c;
return selection_get_copy(&text->sel);
}
+
/**
- * Retrieve number of lines in content
+ * Convert a character offset within a line of text into the
+ * horizontal co-ordinate
+ *
+ * The conversion takes into account the font being used and any tabs
+ * in the text
*
- * \param c Content to retrieve line count from
- * \return Number of lines
+ * \param text line of text
+ * \param offset char offset within text
+ * \param length line length
+ * \return x ordinate
*/
+static int
+textplain_coord_from_offset(const char *text, size_t offset, size_t length)
+{
+ int x = 0;
+
+ while (offset > 0) {
+ size_t next_offset = 0;
+ int tx;
+
+ while (next_offset < offset && text[next_offset] != '\t') {
+ next_offset = utf8_next(text, length, next_offset);
+ }
+
+ guit->layout->width(&textplain_style, text, next_offset, &tx);
+
+ x += tx;
+
+ if (next_offset >= offset)
+ break;
+
+ /* align to next tab boundary */
+ next_offset++;
+ x = (1 + (x / textplain_tab_width)) * textplain_tab_width;
+ offset -= next_offset;
+ text += next_offset;
+ length -= next_offset;
+ }
+
+ return x;
+}
+
+
+/**
+ * plain text content handler table
+ */
+static const content_handler textplain_content_handler = {
+ .fini = textplain_fini,
+ .create = textplain_create,
+ .process_data = textplain_process_data,
+ .data_complete = textplain_convert,
+ .reformat = textplain_reformat,
+ .destroy = textplain_destroy,
+ .mouse_track = textplain_mouse_track,
+ .mouse_action = textplain_mouse_action,
+ .keypress = textplain_keypress,
+ .search = textplain_search,
+ .search_clear = textplain_search_clear,
+ .redraw = textplain_redraw,
+ .open = textplain_open,
+ .close = textplain_close,
+ .get_selection = textplain_get_selection,
+ .clone = textplain_clone,
+ .type = textplain_content_type,
+ .no_share = true,
+};
+
+
+/* exported interface documented in render/textplain.h */
+nserror textplain_init(void)
+{
+ lwc_error lerror;
+ nserror error;
+
+ lerror = lwc_intern_string("Windows-1252",
+ SLEN("Windows-1252"),
+ &textplain_default_charset);
+ if (lerror != lwc_error_ok) {
+ return NSERROR_NOMEM;
+ }
+
+ error = content_factory_register_handler("text/plain",
+ &textplain_content_handler);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(textplain_default_charset);
+ }
+
+ return error;
+}
+
+
+/* exported interface documented in render/textplain.h */
unsigned long textplain_line_count(struct content *c)
{
textplain_content *text = (textplain_content *) c;
@@ -1060,12 +1124,8 @@ unsigned long textplain_line_count(struct content *c)
return text->physical_line_count;
}
-/**
- * Retrieve the size (in bytes) of text data
- *
- * \param c Content to retrieve size of
- * \return Size, in bytes, of data
- */
+
+/* exported interface documented in render/textplain.h */
size_t textplain_size(struct content *c)
{
textplain_content *text = (textplain_content *) c;
@@ -1075,21 +1135,8 @@ size_t textplain_size(struct content *c)
return text->utf8_data_size;
}
-/**
-
- * Return byte offset within UTF8 textplain content.
- *
- * given the co-ordinates of a point within a textplain content. 'dir'
- * specifies the direction in which to search (-1 = above-left, +1 =
- * below-right) if the co-ordinates are not contained within a line.
- *
- * \param c content of type CONTENT_TEXTPLAIN
- * \param x x ordinate of point
- * \param y y ordinate of point
- * \param dir direction of search if not within line
- * \return byte offset of character containing (or nearest to) point
- */
+/* exported interface documented in render/textplain.h */
size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir)
{
textplain_content *textc = (textplain_content *) c;
@@ -1122,8 +1169,9 @@ size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir)
size_t next_offset = 0;
int width = INT_MAX;
- while (next_offset < length && text[next_offset] != '\t')
+ while (next_offset < length && text[next_offset] != '\t') {
next_offset = utf8_next(text, length, next_offset);
+ }
if (next_offset < length) {
guit->layout->width(&textplain_style,
@@ -1163,94 +1211,12 @@ size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir)
}
-/**
- * Given a byte offset within the text, return the line number
- * of the line containing that offset (or -1 if offset invalid)
- *
- * \param c content of type CONTENT_TEXTPLAIN
- * \param offset byte offset within textual representation
- * \return line number, or -1 if offset invalid (larger than size)
- */
-
-int textplain_find_line(struct content *c, unsigned offset)
-{
- textplain_content *text = (textplain_content *) c;
- struct textplain_line *line;
- int nlines;
- int lineno = 0;
-
- assert(c != NULL);
-
- line = text->physical_line;
- nlines = text->physical_line_count;
-
- if (offset > text->utf8_data_size)
- return -1;
-
-/* \todo - implement binary search here */
- while (lineno < nlines && line[lineno].start < offset)
- lineno++;
- if (line[lineno].start > offset)
- lineno--;
-
- return lineno;
-}
-
-
-/**
- * Convert a character offset within a line of text into the
- * horizontal co-ordinate, taking into account the font being
- * used and any tabs in the text
- *
- * \param text line of text
- * \param offset char offset within text
- * \param length line length
- * \return x ordinate
- */
-
-int textplain_coord_from_offset(const char *text, size_t offset, size_t length)
-{
- int x = 0;
-
- while (offset > 0) {
- size_t next_offset = 0;
- int tx;
-
- while (next_offset < offset && text[next_offset] != '\t') {
- next_offset = utf8_next(text, length, next_offset);
- }
-
- guit->layout->width(&textplain_style, text, next_offset, &tx);
-
- x += tx;
-
- if (next_offset >= offset)
- break;
-
- /* align to next tab boundary */
- next_offset++;
- x = (1 + (x / textplain_tab_width)) * textplain_tab_width;
- offset -= next_offset;
- text += next_offset;
- length -= next_offset;
- }
-
- return x;
-}
-
-
-/**
- * Given a range of byte offsets within a UTF8 textplain content,
- * return a box that fully encloses the text
- *
- * \param c content of type CONTENT_TEXTPLAIN
- * \param start byte offset of start of text range
- * \param end byte offset of end
- * \param r rectangle to be completed
- */
-
-void textplain_coords_from_range(struct content *c, unsigned start,
- unsigned end, struct rect *r)
+/* exported interface documented in render/textplain.h */
+void
+textplain_coords_from_range(struct content *c,
+ unsigned start,
+ unsigned end,
+ struct rect *r)
{
textplain_content *text = (textplain_content *) c;
float line_height = textplain_line_height();
@@ -1273,42 +1239,38 @@ void textplain_coords_from_range(struct content *c, unsigned start,
r->y0 = (int)(MARGIN + lineno * line_height);
if (lineno + 1 <= nlines || line[lineno + 1].start >= end) {
- /* \todo - it may actually be more efficient just to run
- forwards most of the time */
+ /* \todo - it may actually be more efficient just to
+ * run forwards most of the time
+ */
/* find end */
lineno = textplain_find_line(c, end);
r->x0 = 0;
r->x1 = text->formatted_width;
- }
- else {
+ } else {
/* single line */
const char *text = utf8_data + line[lineno].start;
- r->x0 = textplain_coord_from_offset(text, start - line[lineno].start,
- line[lineno].length);
+ r->x0 = textplain_coord_from_offset(text,
+ start - line[lineno].start,
+ line[lineno].length);
- r->x1 = textplain_coord_from_offset(text, end - line[lineno].start,
- line[lineno].length);
+ r->x1 = textplain_coord_from_offset(text,
+ end - line[lineno].start,
+ line[lineno].length);
}
r->y1 = (int)(MARGIN + (lineno + 1) * line_height);
}
-/**
- * Return a pointer to the requested line of text.
- *
- * \param c content of type CONTENT_TEXTPLAIN
- * \param lineno line number
- * \param poffset receives byte offset of line start within text
- * \param plen receives length of returned line
- * \return pointer to text, or NULL if invalid line number
- */
-
-char *textplain_get_line(struct content *c, unsigned lineno,
- size_t *poffset, size_t *plen)
+/* exported interface documented in render/textplain.h */
+char *
+textplain_get_line(struct content *c,
+ unsigned lineno,
+ size_t *poffset,
+ size_t *plen)
{
textplain_content *text = (textplain_content *) c;
struct textplain_line *line;
@@ -1325,20 +1287,41 @@ char *textplain_get_line(struct content *c, unsigned lineno,
}
-/**
- * Return a pointer to the raw UTF-8 data, as opposed to the reformatted
- * text to fit the window width. Thus only hard newlines are preserved
- * in the saved/copied text of a selection.
- *
- * \param c content of type CONTENT_TEXTPLAIN
- * \param start starting byte offset within UTF-8 text
- * \param end ending byte offset
- * \param plen receives validated length
- * \return pointer to text, or NULL if no text
- */
+/* exported interface documented in render/textplain.h */
+int textplain_find_line(struct content *c, unsigned offset)
+{
+ textplain_content *text = (textplain_content *) c;
+ struct textplain_line *line;
+ int nlines;
+ int lineno = 0;
+
+ assert(c != NULL);
+
+ line = text->physical_line;
+ nlines = text->physical_line_count;
+
+ if (offset > text->utf8_data_size) {
+ return -1;
+ }
+
+/* \todo - implement binary search here */
+ while (lineno < nlines && line[lineno].start < offset) {
+ lineno++;
+ }
+ if (line[lineno].start > offset) {
+ lineno--;
+ }
-char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end,
- size_t *plen)
+ return lineno;
+}
+
+
+/* exported interface documented in render/textplain.h */
+char *
+textplain_get_raw_data(struct content *c,
+ unsigned start,
+ unsigned end,
+ size_t *plen)
{
textplain_content *text = (textplain_content *) c;
size_t utf8_size;
@@ -1359,26 +1342,8 @@ char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end,
return text->utf8_data + start;
}
-/**
- * Calculate the line height, in pixels
- *
- * \return Line height, in pixels
- */
-float textplain_line_height(void)
-{
- /* Size is in points, so convert to pixels.
- * Then use a constant line height of 1.2 x font size.
- */
- return FIXTOFLT(FDIV((FMUL(FLTTOFIX(1.2), FMUL(nscss_screen_dpi,
- INTTOFIX((textplain_style.size / FONT_SIZE_SCALE))))), F_72));
-}
-/**
- * Get the browser window containing a textplain content
- *
- * \param c text/plain content
- * \return the browser window
- */
+/* exported interface documented in render/textplain.h */
struct browser_window *textplain_get_browser_window(struct content *c)
{
textplain_content *text = (textplain_content *) c;
@@ -1388,4 +1353,3 @@ struct browser_window *textplain_get_browser_window(struct content *c)
return text->bw;
}
-
diff --git a/render/textplain.h b/render/textplain.h
index 6a88c3470..0f0128e56 100644
--- a/render/textplain.h
+++ b/render/textplain.h
@@ -17,12 +17,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for text/plain (interface).
+/**
+ * \file
+ *
+ * Interface to content handler for plain text.
*/
-#ifndef _NETSURF_RENDER_TEXTPLAIN_H_
-#define _NETSURF_RENDER_TEXTPLAIN_H_
+#ifndef NETSURF_RENDER_TEXTPLAIN_H
+#define NETSURF_RENDER_TEXTPLAIN_H
#include <stddef.h>
#include "netsurf/mouse.h"
@@ -32,20 +34,106 @@ struct hlcache_handle;
struct http_parameter;
struct rect;
+/**
+ * Initialise the text content handler
+ *
+ * \return NSERROR_OK on success else appropriate error code.
+ */
nserror textplain_init(void);
-/* access to lines for text selection and searching */
+
+/**
+ * Retrieve number of lines in content
+ *
+ * \param[in] c Content to retrieve line count from
+ * \return Number of lines
+ */
unsigned long textplain_line_count(struct content *c);
+
+
+/**
+ * Retrieve the size (in bytes) of text data
+ *
+ * \param[in] c Content to retrieve size of
+ * \return Size, in bytes, of data
+ */
size_t textplain_size(struct content *c);
+
+/**
+ * Return byte offset within UTF8 textplain content.
+ *
+ * given the co-ordinates of a point within a textplain content. 'dir'
+ * specifies the direction in which to search (-1 = above-left, +1 =
+ * below-right) if the co-ordinates are not contained within a line.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] x x ordinate of point
+ * \param[in] y y ordinate of point
+ * \param[in] dir direction of search if not within line
+ * \return byte offset of character containing (or nearest to) point
+ */
size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir);
+
+
+/**
+ * Given a range of byte offsets within a UTF8 textplain content,
+ * return a box that fully encloses the text
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] start byte offset of start of text range
+ * \param[in] end byte offset of end
+ * \param[out] r rectangle to be completed
+ */
void textplain_coords_from_range(struct content *c,
unsigned start, unsigned end, struct rect *r);
+
+/**
+ * Return a pointer to the requested line of text.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] lineno line number
+ * \param[out] poffset receives byte offset of line start within text
+ * \param[out] plen receives length of returned line
+ * \return pointer to text, or NULL if invalid line number
+ */
char *textplain_get_line(struct content *c, unsigned lineno,
size_t *poffset, size_t *plen);
+
+
+/**
+ * Find line number of byte in text
+ *
+ * Given a byte offset within the text, return the line number
+ * of the line containing that offset.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] offset byte offset within textual representation
+ * \return line number, or -1 if offset invalid (larger than size)
+ */
int textplain_find_line(struct content *c, unsigned offset);
-char *textplain_get_raw_data(struct content *c,
- unsigned start, unsigned end, size_t *plen);
+
+
+/**
+ * Return a pointer to the raw UTF-8 data, as opposed to the reformatted
+ * text to fit the window width. Thus only hard newlines are preserved
+ * in the saved/copied text of a selection.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] start starting byte offset within UTF-8 text
+ * \param[in] end ending byte offset
+ * \param[out] plen receives validated length
+ * \return pointer to text, or NULL if no text
+ */
+char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end, size_t *plen);
+
+
+/**
+ * Get the browser window containing a textplain content
+ *
+ * \param[in] c text/plain content
+ * \return the browser window
+ */
struct browser_window *textplain_get_browser_window(struct content *c);
#endif