Cursor movement for equation editing
This commit is contained in:
parent
af424d1baa
commit
0a4b91edb0
|
@ -6,6 +6,8 @@
|
|||
#define TEX_TEX
|
||||
|
||||
#include <TeX/config.h>
|
||||
#include <TeX/edit.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//---
|
||||
|
@ -85,10 +87,12 @@ void TeX_free(struct TeX_Env *formula);
|
|||
|
||||
/* TeX_draw(): Render a parsed formula
|
||||
@formula Formula to render
|
||||
@context Used to place the cursor; can be set to NULL is there is none.
|
||||
This function does not draw the cursor but may its position.
|
||||
@x x coordinate of the left-side of the bounding box (included)
|
||||
@y y coordinate of the top-size of the bounding box (included)
|
||||
@color Requested color for the rendered pixels */
|
||||
void TeX_draw(struct TeX_Env *formula, int x, int y, int color);
|
||||
void TeX_draw(struct TeX_Env *formula, struct editContext * context, int x, int y, int color);
|
||||
|
||||
/* TeX_interpret(): Parse and render, in sequence
|
||||
This function parses the provided formula, renders it and then frees it.
|
||||
|
|
|
@ -43,11 +43,13 @@ struct TeX_Class
|
|||
void TeX_line(int x1, int y1, int x2, int y2, int color);
|
||||
void TeX_text(char const *str, int x, int y, int color);
|
||||
|
||||
@node A node of the described class, for rendering
|
||||
@x Horizontal coordinate of the requested rendering position
|
||||
@y Vertical coordinate of the requested rendering position
|
||||
@color Requested rendering color */
|
||||
void (*render)(struct TeX_Node const * node, int x, int y, int color);
|
||||
@node A node of the described class, for rendering
|
||||
@context Used to place the cursor; can be set to NULL is there is none.
|
||||
This function does not draw the cursor but may its position.
|
||||
@x Horizontal coordinate of the requested rendering position
|
||||
@y Vertical coordinate of the requested rendering position
|
||||
@color Requested rendering color */
|
||||
void (*render)(struct TeX_Node const * node, struct editContext * context, int x, int y, int color);
|
||||
|
||||
/* Sub- and superscript mode, see <TeX/flow.h> for available modes */
|
||||
int mode;
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
//---
|
||||
// edit: Structures related to cursor movement and editing
|
||||
//---
|
||||
|
||||
#ifndef TEX_EDIT
|
||||
#define TEX_EDIT
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct editContext {
|
||||
bool elementIsText;
|
||||
union {
|
||||
struct TeX_Flow* cursorFlow;
|
||||
struct TeX_Node* cursorText;
|
||||
};
|
||||
int offset;
|
||||
|
||||
int cursorX;
|
||||
int cursorY;
|
||||
};
|
||||
|
||||
// An enum for action that the cursor can take
|
||||
enum cursorAction {
|
||||
CURSOR_MOVE_LEFT,
|
||||
CURSOR_MOVE_RIGHT
|
||||
};
|
||||
|
||||
// An enum of return values for the move_cursor function
|
||||
enum cursorMoveResult {
|
||||
// The cursor was found and updated, and the recursive search can end
|
||||
SUCCESS,
|
||||
// The cursor was not found, and the recursive search should continue
|
||||
CURSOR_NOT_HERE,
|
||||
|
||||
// For these values where the cursor exits, the parent is responsible for
|
||||
// moving the cursor out of the flow or node.
|
||||
// It may also choose to ingore the cursor exit and keep the cursor in the
|
||||
// flow or node, for example if there is no parent to move the cursor to.
|
||||
|
||||
// The cursor exited the flow or node out of the right side
|
||||
CURSOR_PAST_END,
|
||||
// The cursor exited the flow or node out of the left side
|
||||
CURSOR_PAST_START
|
||||
};
|
||||
|
||||
#endif /* TEX_EDIT */
|
|
@ -6,6 +6,7 @@
|
|||
#define TEX_ENV
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct TeX_Node;
|
||||
|
||||
|
@ -34,7 +35,7 @@ struct TeX_Env
|
|||
void (*layout)(TeX_Env *env, int display);
|
||||
|
||||
/* render(): Render environment */
|
||||
void (*render)(TeX_Env *env, int x, int y, int color);
|
||||
void (*render)(TeX_Env *env, struct editContext * context, int x, int y, int color);
|
||||
|
||||
/* Dimensions */
|
||||
uint16_t width;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef TEX_FLOW
|
||||
#define TEX_FLOW
|
||||
|
||||
#include <TeX/edit.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct TeX_Node;
|
||||
|
@ -19,6 +20,8 @@ struct TeX_Flow
|
|||
struct TeX_Node *first;
|
||||
struct TeX_Node *last;
|
||||
|
||||
uint32_t elements;
|
||||
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t line;
|
||||
|
@ -64,9 +67,17 @@ void TeX_flow_free(struct TeX_Flow *flow);
|
|||
characters and subscripts/superscripts. Modifies the flow's metadata. */
|
||||
void TeX_flow_layout(struct TeX_Flow *flow, int display);
|
||||
|
||||
/* TeX_flow_cursor_action(): Perform a cursor action on a flow
|
||||
This function performs a cursor action on a flow, like moving left or right.
|
||||
This is recursive, and should usually be called on the top-level flow.
|
||||
If it is called on a non-top-level flow, it will restrict the movement to
|
||||
within the flow; the cursor will be to able to move within in but not exit.
|
||||
Returns a cursorMoveResult enum; see edit.h for details of the return value. */
|
||||
enum cursorMoveResult TeX_flow_cursor_action(struct TeX_Flow * flow, struct editContext * context, enum cursorAction action);
|
||||
|
||||
/* TeX_flow_render(): Render a flow and all its components
|
||||
This function renders all horizontal objects in a flow. The layout of the
|
||||
flow must have been computed. */
|
||||
void TeX_flow_render(struct TeX_Flow const * flow, int x, int y, int color);
|
||||
void TeX_flow_render(struct TeX_Flow const * flow, struct editContext * context, int x, int y, int color);
|
||||
|
||||
#endif /* TEX_FLOW */
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <TeX/config.h>
|
||||
#include <TeX/defs.h>
|
||||
#include <TeX/edit.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -97,6 +99,9 @@ void TeX_node_layout(struct TeX_Node *node, int display);
|
|||
|
||||
/* TeX_node_render(): Render a node and its children
|
||||
The node's layout must have been computed first. */
|
||||
void TeX_node_render(struct TeX_Node const * node, int x, int y, int color);
|
||||
void TeX_node_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color);
|
||||
|
||||
enum cursorMoveResult move_cursor_node(struct TeX_Node *node, struct editContext * context, enum cursorAction action);
|
||||
enum cursorMoveResult cursor_enter_node(struct TeX_Node *node, struct editContext * context, enum cursorAction action);
|
||||
|
||||
#endif /* TEX_NODE */
|
||||
|
|
|
@ -72,9 +72,9 @@ struct TeX_Env *TeX_parse(char const *formula, int display)
|
|||
}
|
||||
|
||||
/* TeX_draw(): Render a parsed formula */
|
||||
void TeX_draw(struct TeX_Env *formula, int x, int y, int color)
|
||||
void TeX_draw(struct TeX_Env *formula, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
formula->render(formula, x, y, color);
|
||||
formula->render(formula, context, x, y, color);
|
||||
}
|
||||
|
||||
/* TeX_interpret(): Parse and render, in sequence */
|
||||
|
@ -83,6 +83,6 @@ void TeX_interpret(char const *formula, int display, int x, int y, int color)
|
|||
struct TeX_Env *env = TeX_parse(formula, display);
|
||||
if(!env) return;
|
||||
|
||||
TeX_draw(env, x, y, color);
|
||||
TeX_draw(env, NULL, x, y, color);
|
||||
TeX_free(env);
|
||||
}
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
#include <TeX/flow.h>
|
||||
#include <TeX/env.h>
|
||||
#include <TeX/classes.h>
|
||||
#include <TeX/edit.h>
|
||||
|
||||
#include <TeX/interface.h>
|
||||
#include <TeX/defs.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
@ -36,8 +38,22 @@ void text_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = h >> 1;
|
||||
}
|
||||
|
||||
void text_render(struct TeX_Node const * node, int x, int y, int color)
|
||||
void text_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
if (context != NULL && context->elementIsText && context->cursorText == node) {
|
||||
// Render a cursor
|
||||
// Temporarily cap the length of the string to the cursor position
|
||||
char old = node->text[context->offset + 1];
|
||||
node->text[context->offset + 1] = '\0';
|
||||
// Measure the width of the string
|
||||
int w, h;
|
||||
TeX_size((char const *)node->text, &w, &h);
|
||||
// Restore the string
|
||||
node->text[context->offset + 1] = old;
|
||||
// Update the cursor position to inside the text
|
||||
context->cursorX = x + w;
|
||||
context->cursorY = y;
|
||||
}
|
||||
TeX_text((void *)node->text, x, y, color);
|
||||
}
|
||||
|
||||
|
@ -54,9 +70,9 @@ void env_layout(struct TeX_Node *node, int display)
|
|||
node->line = node->env->line;
|
||||
}
|
||||
|
||||
void env_render(struct TeX_Node const * node, int x, int y, int color)
|
||||
void env_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
node->env->render(node->env, x, y, color);
|
||||
node->env->render(node->env, context, x, y, color);
|
||||
}
|
||||
|
||||
//---
|
||||
|
@ -96,7 +112,7 @@ void frac_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = h(0) + spacing + thickness / 2;
|
||||
}
|
||||
|
||||
void frac_render(struct TeX_Node const * node, int x, int y, int color)
|
||||
void frac_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
/* Fraction bar */
|
||||
for(int i = 0; i < TEX_FRACTION_BAR_THICKNESS; i++)
|
||||
|
@ -107,12 +123,14 @@ void frac_render(struct TeX_Node const * node, int x, int y, int color)
|
|||
|
||||
/* First argument */
|
||||
TeX_flow_render(args[0],
|
||||
context,
|
||||
x + ((node->width - w(0)) >> 1),
|
||||
y,
|
||||
color);
|
||||
|
||||
/* Second argument */
|
||||
TeX_flow_render(args[1],
|
||||
context,
|
||||
x + ((node->width - w(1)) >> 1),
|
||||
y + h(0) + 2*TEX_FRACTION_SPACING + TEX_FRACTION_BAR_THICKNESS,
|
||||
color);
|
||||
|
@ -165,7 +183,7 @@ void leftright_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->width = 1;
|
||||
}
|
||||
|
||||
void leftright_render(struct TeX_Node const * node, int x, int y, int color)
|
||||
void leftright_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
int h = node->height, w = node->width, l = node->line;
|
||||
|
||||
|
@ -285,10 +303,10 @@ void supsubscript_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = l(0);
|
||||
}
|
||||
|
||||
void supsubscript_render(struct TeX_Node const * node, int x, int y,
|
||||
int color)
|
||||
void supsubscript_render(struct TeX_Node const * node, struct editContext * context,
|
||||
int x, int y, int color)
|
||||
{
|
||||
TeX_flow_render(args[0], x, y, color);
|
||||
TeX_flow_render(args[0], context, x, y, color);
|
||||
}
|
||||
|
||||
//---
|
||||
|
@ -306,8 +324,8 @@ void sum_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = 4;
|
||||
}
|
||||
|
||||
void sum_render(TEX_UNUSED struct TeX_Node const * node, int x, int y,
|
||||
int color)
|
||||
void sum_render(TEX_UNUSED struct TeX_Node const * node, struct editContext * context,
|
||||
int x, int y, int color)
|
||||
{
|
||||
TeX_line(x, y, x + 8, y, color);
|
||||
TeX_line(x, y, x + 4, y + 4, color);
|
||||
|
@ -330,7 +348,7 @@ void prod_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = 4;
|
||||
}
|
||||
|
||||
void prod_render(TEX_UNUSED struct TeX_Node const * node, int x, int y,
|
||||
void prod_render(TEX_UNUSED struct TeX_Node const * node, struct editContext * context, int x, int y,
|
||||
int color)
|
||||
{
|
||||
TeX_line(x, y, x + 8, y, color);
|
||||
|
@ -353,7 +371,7 @@ void int_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = TEX_INT_HEIGHT >> 1;
|
||||
}
|
||||
|
||||
void int_render(struct TeX_Node const * node, int x, int y, int color)
|
||||
void int_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
int h = node->height;
|
||||
|
||||
|
@ -397,7 +415,7 @@ void vec_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = l(0) + TEX_VEC_SPACING + arrow_height;
|
||||
}
|
||||
|
||||
void vec_render(struct TeX_Node const * node, int x, int y, int color)
|
||||
void vec_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
int length = TEX_VEC_ARROW_LENGTH;
|
||||
int arrow_height = 2 * length + 1;
|
||||
|
@ -411,6 +429,7 @@ void vec_render(struct TeX_Node const * node, int x, int y, int color)
|
|||
|
||||
/* First argument */
|
||||
TeX_flow_render(args[0],
|
||||
context,
|
||||
x + TEX_VEC_MARGIN,
|
||||
y + TEX_VEC_SPACING + arrow_height,
|
||||
color);
|
||||
|
@ -431,7 +450,7 @@ void lim_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = h >> 1;
|
||||
}
|
||||
|
||||
void lim_render(TEX_UNUSED struct TeX_Node const * node, int x, int y,
|
||||
void lim_render(TEX_UNUSED struct TeX_Node const * node, struct editContext * context, int x, int y,
|
||||
int color)
|
||||
{
|
||||
TeX_text("lim", x, y, color);
|
||||
|
@ -492,7 +511,7 @@ void sqrt_layout(struct TeX_Node *node, TEX_UNUSED int display)
|
|||
node->line = l(0) + TEX_SQRT_MARGIN + 1;
|
||||
}
|
||||
|
||||
void sqrt_render(struct TeX_Node const * node, int x, int y, int color)
|
||||
void sqrt_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
int slanted = TEX_SQRT_SLANTED && h(0) <= TEX_SQRT_SLANT_MAX;
|
||||
int w = node->width;
|
||||
|
@ -509,6 +528,7 @@ void sqrt_render(struct TeX_Node const * node, int x, int y, int color)
|
|||
TeX_line(x + w - 1, y, x + w - 1, y + TEX_SQRT_BAR_LENGTH, color);
|
||||
|
||||
TeX_flow_render(args[0],
|
||||
context,
|
||||
x + base + TEX_SQRT_MARGIN,
|
||||
y + 1 + TEX_SQRT_MARGIN,
|
||||
color);
|
||||
|
|
|
@ -63,10 +63,10 @@ static void primary_layout(struct TeX_Env *env, int display)
|
|||
env->line = p->flow->line;
|
||||
}
|
||||
|
||||
static void primary_render(struct TeX_Env *env, int x, int y, int color)
|
||||
static void primary_render(struct TeX_Env *env, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
struct TeX_Env_Primary *p = (void *)env;
|
||||
TeX_flow_render(p->flow, x, y, color);
|
||||
TeX_flow_render(p->flow, context, x, y, color);
|
||||
}
|
||||
|
||||
struct TeX_Env *TeX_env_primary(void)
|
||||
|
@ -200,7 +200,7 @@ static void matrix_layout(struct TeX_Env *env, int display)
|
|||
env->line = env->height >> 1;
|
||||
}
|
||||
|
||||
static void matrix_render(struct TeX_Env *env, int x, int y, int color)
|
||||
static void matrix_render(struct TeX_Env *env, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
struct TeX_Env_Matrix *m = (void *)env;
|
||||
|
||||
|
@ -218,6 +218,7 @@ static void matrix_render(struct TeX_Env *env, int x, int y, int color)
|
|||
int rh = m->rowline[row] + m->rowdepth[row];
|
||||
|
||||
if(flow) TeX_flow_render(flow,
|
||||
context,
|
||||
x + dx + ((cw - flow->width) >> 1),
|
||||
y + dy + ((rh - flow->height) >> 1),
|
||||
color);
|
||||
|
|
122
src/flow.c
122
src/flow.c
|
@ -1,9 +1,13 @@
|
|||
#include <TeX/node.h>
|
||||
#include <TeX/flow.h>
|
||||
#include <TeX/classes.h>
|
||||
#include <TeX/interface.h>
|
||||
#include <TeX/edit.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//---
|
||||
// Flow construction and destruction functions
|
||||
|
@ -19,6 +23,7 @@ struct TeX_Flow *TeX_flow_add_node(struct TeX_Flow *flow, struct TeX_Node*node)
|
|||
{
|
||||
flow->last->next = node;
|
||||
flow->last = node;
|
||||
flow->elements++;
|
||||
return flow;
|
||||
}
|
||||
|
||||
|
@ -27,6 +32,7 @@ struct TeX_Flow *TeX_flow_add_node(struct TeX_Flow *flow, struct TeX_Node*node)
|
|||
if(!flow) return NULL;
|
||||
|
||||
flow->first = flow->last = node;
|
||||
flow->elements = 1;
|
||||
return flow;
|
||||
}
|
||||
|
||||
|
@ -378,15 +384,125 @@ void TeX_flow_layout(struct TeX_Flow *flow, int display)
|
|||
flow->width = max(x - TEX_LAYOUT_SPACING, 0);
|
||||
}
|
||||
|
||||
enum cursorMoveResult TeX_flow_cursor_action(struct TeX_Flow * flow, struct editContext * context, enum cursorAction action) {
|
||||
if (context->cursorFlow != flow)
|
||||
{
|
||||
// Search all the nodes in the flow for the cursor
|
||||
struct TeX_Node* node = flow->first;
|
||||
int offset = 0;
|
||||
while (node != NULL)
|
||||
{
|
||||
int returnCode = move_cursor_node(node, context, action);
|
||||
|
||||
if (returnCode == SUCCESS)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
else if (returnCode == CURSOR_NOT_HERE)
|
||||
{
|
||||
// Keep searching
|
||||
}
|
||||
else if (returnCode == CURSOR_PAST_END)
|
||||
{
|
||||
// Put the cursor in this flow after the node
|
||||
context->elementIsText = false;
|
||||
context->cursorFlow = flow;
|
||||
context->offset = offset + 1;
|
||||
return SUCCESS;
|
||||
}
|
||||
else if (returnCode == CURSOR_PAST_START)
|
||||
{
|
||||
// Put the cursor in this flow before the node
|
||||
context->elementIsText = false;
|
||||
context->cursorFlow = flow;
|
||||
context->offset = offset;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
offset++;
|
||||
}
|
||||
return CURSOR_NOT_HERE;
|
||||
}
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case CURSOR_MOVE_LEFT:
|
||||
if (context->offset <= 0)
|
||||
{
|
||||
context->offset = 0;
|
||||
return CURSOR_PAST_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the node at offset
|
||||
// As this is a linked list we have to iterate through it which is inefficient
|
||||
// TODO: Change it to a normal array, or store the pointer to the node in the editContext (which will need a doubly linked list)
|
||||
struct TeX_Node* node = flow->first;
|
||||
for (int i = 0; i < context->offset - 1; i++)
|
||||
{
|
||||
node = node->next;
|
||||
}
|
||||
int returncode = cursor_enter_node(node, context, action);
|
||||
if (returncode == CURSOR_PAST_START)
|
||||
{
|
||||
// Put the cursor in this flow before the node
|
||||
context->offset--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CURSOR_MOVE_RIGHT:
|
||||
if (context->offset >= flow->elements)
|
||||
{
|
||||
context->offset = flow->elements;
|
||||
return CURSOR_PAST_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the node at offset
|
||||
// As this is a linked list we have to interate through it which is inefficient
|
||||
// TODO: Change it to a normal array, or store the pointer to the node in the editContext (which will need a doubly linked list)
|
||||
struct TeX_Node* node = flow->first;
|
||||
for (int i = 0; i < context->offset; i++)
|
||||
{
|
||||
node = node->next;
|
||||
}
|
||||
int returncode = cursor_enter_node(node, context, action);
|
||||
if (returncode == CURSOR_PAST_END)
|
||||
{
|
||||
context->offset++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* TeX_flow_render(): Render a flow and all its components */
|
||||
void TeX_flow_render(struct TeX_Flow const * flow, int x, int y, int color)
|
||||
void TeX_flow_render(struct TeX_Flow const * flow, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
struct TeX_Node const * node;
|
||||
|
||||
int offset = 0;
|
||||
for(node = flow->first; node; node = node->next)
|
||||
{
|
||||
TeX_node_render(node, x + node->x, y + flow->line -
|
||||
node->line + node->l, color);
|
||||
if (context != NULL && !context->elementIsText && context->cursorFlow == flow && context->offset == offset)
|
||||
{
|
||||
// Render a cursor
|
||||
context->cursorX = x + node->x;
|
||||
context->cursorY = y + flow->line - 4;
|
||||
}
|
||||
|
||||
TeX_node_render(node, context, x + node->x,
|
||||
y + flow->line - node->line + node->l, color);
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (context != NULL && !context->elementIsText &&context->cursorFlow == flow && context->offset == offset)
|
||||
{
|
||||
// Render a cursor
|
||||
context->cursorX = x + flow->width;
|
||||
context->cursorY = y + flow->line - 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
118
src/node.c
118
src/node.c
|
@ -3,7 +3,10 @@
|
|||
#include <TeX/flow.h>
|
||||
#include <TeX/env.h>
|
||||
#include <TeX/classes.h>
|
||||
#include <TeX/interface.h>
|
||||
#include <TeX/edit.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -15,6 +18,117 @@
|
|||
((node)->type == TEX_NODECLASS_TEXT || \
|
||||
(node)->type == TEX_NODECLASS_ENV)
|
||||
|
||||
enum cursorMoveResult move_cursor_node(struct TeX_Node *node, struct editContext * context, enum cursorAction action)
|
||||
{
|
||||
if (node->type == 0)
|
||||
{
|
||||
// Text
|
||||
if (!context->elementIsText || context->cursorText != node)
|
||||
return CURSOR_NOT_HERE;
|
||||
|
||||
if (action == CURSOR_MOVE_LEFT)
|
||||
{
|
||||
if (context->offset <= 0)
|
||||
return CURSOR_PAST_START;
|
||||
|
||||
context->offset--;
|
||||
return SUCCESS;
|
||||
}
|
||||
if (action == CURSOR_MOVE_RIGHT) {
|
||||
if (context->offset >= strlen(node->text) - 2)
|
||||
return CURSOR_PAST_END;
|
||||
|
||||
context->offset++;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
if (node->type > 1)
|
||||
{
|
||||
if (node->args[0] == NULL)
|
||||
return CURSOR_NOT_HERE;
|
||||
|
||||
int returnCode = TeX_flow_cursor_action(node->args[0], context, action);
|
||||
if (returnCode == SUCCESS)
|
||||
return returnCode;
|
||||
if (returnCode == CURSOR_PAST_END)
|
||||
{
|
||||
// Go to the denominator
|
||||
if (node->args[1] == NULL)
|
||||
return CURSOR_PAST_END;
|
||||
|
||||
context->elementIsText = false;
|
||||
context->cursorFlow = node->args[1];
|
||||
context->offset = 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
if (returnCode != CURSOR_NOT_HERE)
|
||||
return returnCode;
|
||||
|
||||
if (node->args[1] == NULL)
|
||||
return CURSOR_NOT_HERE;
|
||||
|
||||
returnCode = TeX_flow_cursor_action(node->args[1], context, action);
|
||||
if (returnCode == CURSOR_PAST_START)
|
||||
{
|
||||
// Go to the numerator
|
||||
context->elementIsText = false;
|
||||
context->cursorFlow = node->args[0];
|
||||
context->offset = node->args[0]->elements;
|
||||
return SUCCESS;
|
||||
}
|
||||
return returnCode;
|
||||
}
|
||||
// TODO: matrices
|
||||
return CURSOR_NOT_HERE;
|
||||
}
|
||||
|
||||
enum cursorMoveResult cursor_enter_node(struct TeX_Node *node, struct editContext * context, enum cursorAction action)
|
||||
{
|
||||
enum cursorMoveResult skipPast = action == CURSOR_MOVE_RIGHT ? CURSOR_PAST_END : CURSOR_PAST_START;
|
||||
|
||||
if (node->type == 0)
|
||||
{
|
||||
int len = strlen(node->text);
|
||||
if (len == 1) return skipPast;
|
||||
// Text
|
||||
context->elementIsText = true;
|
||||
context->cursorText = node;
|
||||
context->offset = action == CURSOR_MOVE_RIGHT ? 0 : len - 2;
|
||||
return SUCCESS;
|
||||
}
|
||||
if (node->type > 1)
|
||||
{
|
||||
if (action == CURSOR_MOVE_RIGHT)
|
||||
{
|
||||
// Enter the numerator
|
||||
if (node->args[0] == NULL)
|
||||
return CURSOR_PAST_END;
|
||||
|
||||
context->elementIsText = false;
|
||||
context->cursorFlow = node->args[0];
|
||||
context->offset = 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
else if (action == CURSOR_MOVE_LEFT)
|
||||
{
|
||||
// Enter the denominator
|
||||
struct TeX_Flow *denom = node->args[1];
|
||||
if (denom == NULL)
|
||||
denom = node->args[0];
|
||||
|
||||
if (denom == NULL)
|
||||
return CURSOR_PAST_START;
|
||||
|
||||
context->elementIsText = false;
|
||||
context->cursorFlow = denom;
|
||||
context->offset = denom->elements;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
// TODO: matrices
|
||||
return skipPast;
|
||||
}
|
||||
|
||||
/* TeX_node_text(): Make a text node */
|
||||
struct TeX_Node *TeX_node_text(char const *utf8)
|
||||
{
|
||||
|
@ -131,13 +245,13 @@ void TeX_node_layout(struct TeX_Node *node, int display)
|
|||
}
|
||||
|
||||
/* TeX_node_render(): Render a node and its children */
|
||||
void TeX_node_render(struct TeX_Node const * node, int x, int y, int color)
|
||||
void TeX_node_render(struct TeX_Node const * node, struct editContext * context, int x, int y, int color)
|
||||
{
|
||||
/* Don't render hidden or invalid elements */
|
||||
if(node->hidden) return;
|
||||
|
||||
/* For non trivial classes, use the class' special function */
|
||||
TeX_class_of(node)->render(node, x, y, color);
|
||||
TeX_class_of(node)->render(node, context, x, y, color);
|
||||
}
|
||||
|
||||
//---
|
||||
|
|
Loading…
Reference in New Issue