Basic drawing script parsing and execution is working.

This commit is contained in:
Scott Duensing 2022-11-26 17:53:53 -06:00
parent e49b5793fc
commit 7551144902
5 changed files with 247 additions and 65 deletions

View file

@ -30,7 +30,9 @@ set(SOURCE_FILES
src/utils.c src/utils.c
src/joeydev.c src/joeydev.c
src/vector.c src/vector.c
src/array.c src/draw.c) src/array.c
src/draw.c
)
add_executable(${CMAKE_PROJECT_NAME} ${SOURCE_FILES}) add_executable(${CMAKE_PROJECT_NAME} ${SOURCE_FILES})

View file

@ -0,0 +1,35 @@
/*
* JoeyDev
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SCINTILLAHEADERS_H
#define SCINTILLAHEADERS_H
#define PLAT_GTK 1
#define GTK 3
#include "Scintilla.h"
#include "SciLexer.h"
#include "ScintillaWidget.h"
#include "Lexilla.h"
#endif //SCINTILLAHEADERS_H

View file

@ -352,10 +352,10 @@ void jlDrawLine(jlContextT *c, jint16 x1, jint16 y1, jint16 x2, jint16 y2) {
jbyte jlDrawPixelGet(jlContextT *c, jint16 x, jint16 y) { jbyte jlDrawPixelGet(jlContextT *c, jint16 x, jint16 y) {
int offset = (x + y * 320) * 4; unsigned int offset = (x + y * 320) * 4;
int r = c->_pixels[offset + 1]; int r = c->_pixels[offset + 2];
int g = c->_pixels[offset + 2]; int g = c->_pixels[offset + 1];
int b = c->_pixels[offset + 3]; int b = c->_pixels[offset];
int index = 0; int index = 0;
int i; int i;
@ -372,12 +372,13 @@ jbyte jlDrawPixelGet(jlContextT *c, jint16 x, jint16 y) {
void jlDrawPixelSet(jlContextT *c, jint16 x, jint16 y) { void jlDrawPixelSet(jlContextT *c, jint16 x, jint16 y) {
int offset = (x + y * 320) * 4; unsigned int offset = (x + y * 320) * 4;
c->_pixels[offset] = 255; c->_pixels[offset] = c->_jlPalette[c->_jlDrawColor].b;
c->_pixels[offset + 1] = c->_jlPalette[c->_jlDrawColor].r; c->_pixels[offset + 1] = c->_jlPalette[c->_jlDrawColor].g;
c->_pixels[offset + 2] = c->_jlPalette[c->_jlDrawColor].g; c->_pixels[offset + 2] = c->_jlPalette[c->_jlDrawColor].r;
c->_pixels[offset + 3] = c->_jlPalette[c->_jlDrawColor].b; // We're using CAIRO_FORMAT_RGB24 so the upper 8 bits are not used.
//c->_pixels[offset + 3] = 255; // This is alpha in CAIRO_FORMAT_ARGB32 mode.
} }

View file

@ -21,6 +21,7 @@
#include "common.h" #include "common.h"
#include "scintillaHeaders.h"
#include "joeydev.h" #include "joeydev.h"
#include "stddclmr.h" #include "stddclmr.h"
@ -30,6 +31,7 @@ int main(int argc, char **argv) {
gtk_init(&argc, &argv); gtk_init(&argc, &argv);
winJoeyDevCreate(); winJoeyDevCreate();
gtk_main(); gtk_main();
scintilla_release_resources();
return 0; return 0;
} }

View file

@ -28,14 +28,7 @@
#include "common.h" #include "common.h"
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "scintillaHeaders.h"
#define PLAT_GTK 1
#define GTK 3
#include "Scintilla.h"
#include "SciLexer.h"
#include "ScintillaWidget.h"
#include "Lexilla.h"
#include "gladeVector.h" #include "gladeVector.h"
#include "vector.h" #include "vector.h"
#include "utils.h" #include "utils.h"
@ -44,6 +37,8 @@
#define SSM(m, w, l) scintilla_send_message(self->sci, m, w, l) #define SSM(m, w, l) scintilla_send_message(self->sci, m, w, l)
#define MARGIN_SCRIPT_FOLD_INDEX 1 #define MARGIN_SCRIPT_FOLD_INDEX 1
#define MARKER_ERROR_ARROW 0
#define MARKER_ERROR_HIGHLIGHT 1
enum PassE { enum PassE {
@ -74,6 +69,12 @@ typedef struct CommandsS {
} CommandsT; } CommandsT;
typedef struct PointS {
int x;
int y;
} PointT;
static int _nextEditorId = 0; static int _nextEditorId = 0;
@ -82,27 +83,30 @@ EVENT void editorVectorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCN
EVENT void menuVectorFileClose(GtkWidget *object, gpointer userData); EVENT void menuVectorFileClose(GtkWidget *object, gpointer userData);
static gboolean parseBox(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseBox(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseCircle(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseCircle(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseClear(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseColor(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseColor(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseComment(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseComment(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseEllipse(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseEllipse(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseFill(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseFill(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseLine(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseLine(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parsePalette(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parsePlot(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parsePlot(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseRectangle(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseRectangle(PassT pass, char **tokenEnd, VectorDataT *self);
static gboolean parseReset(PassT pass, char **tokenEnd, VectorDataT *self); static gboolean parseReset(PassT pass, char **tokenEnd, VectorDataT *self);
static void parser(PassT pass, gpointer userData); static void parser(PassT pass, gpointer userData);
static gboolean parserGetNextValue(char *token, char **valueEnd, int *x);
static gboolean parserGetWord(char *word, char **tokenEnd); static gboolean parserGetWord(char *word, char **tokenEnd);
static gboolean parserGetX(char **tokenEnd, int *x); static gboolean parserGetX(char **tokenEnd, int *x);
static gboolean parserGetXY(char **tokenEnd, int *x, int *y); static gboolean parserGetXY(char **tokenEnd, int *x, int *y);
static gboolean parserGetXYZ(char **tokenEnd, int *x, int *y, int *z);
EVENT gboolean winVectorClose(GtkWidget *object, gpointer userData); EVENT gboolean winVectorClose(GtkWidget *object, gpointer userData);
static void winVectorDelete(gpointer userData); static void winVectorDelete(gpointer userData);
EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer userData) { EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer userData) {
VectorDataT *self = (VectorDataT *)userData; VectorDataT *self = (VectorDataT *)userData;
cairo_surface_t *target = cairo_get_target(cr); int width = cairo_image_surface_get_width(self->surface);
int width = cairo_image_surface_get_width(target); int height = cairo_image_surface_get_height(self->surface);
int height = cairo_image_surface_get_height(target);
(void)widget; (void)widget;
(void)userData; (void)userData;
@ -118,39 +122,36 @@ EVENT gboolean drawVectorImageDraw(GtkWidget *widget, cairo_t *cr, gpointer user
cairo_surface_flush(self->surface); cairo_surface_flush(self->surface);
printf("Redrew image\n");
return FALSE; return FALSE;
} }
EVENT void editorVectorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData) { EVENT void editorVectorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData) {
VectorDataT *self = (VectorDataT *)userData; VectorDataT *self = (VectorDataT *)userData;
int lineNumber = (int)SSM(SCI_LINEFROMPOSITION, (uptr_t)notifyData->position , (sptr_t)0); int lineNumber = (int)SSM(SCI_LINEFROMPOSITION, (uptr_t)notifyData->position, (sptr_t)0);
(void)sciWidget; (void)sciWidget;
(void)ctrlID; (void)ctrlID;
//printf("Notification %d\n", notifyData->nmhdr.code); //printf("Notification %d\n", notifyData->modificationType);
switch (notifyData->nmhdr.code) { switch (notifyData->nmhdr.code) {
case SCN_CHARADDED: case SCN_MODIFIED:
if (notifyData->modificationType & SC_MOD_INSERTTEXT || notifyData->modificationType & SC_MOD_DELETETEXT) {
// Parse code.
parser(PASS_DRAW, userData); parser(PASS_DRAW, userData);
// Refresh widget.
gtk_widget_queue_draw(self->drawVectorImage); gtk_widget_queue_draw(self->drawVectorImage);
break; // Mark text dirty. SCN_SAVEPOINTLEFT isn't being reliable.
self->windowData.isDirty = TRUE;
case SCN_SAVEPOINTLEFT: }
self->windowData.isDirty = TRUE; //***TODO*** I don't think this is very accurate.
break;
case SCN_SAVEPOINTREACHED:
self->windowData.isDirty = FALSE;
break; break;
case SCN_MARGINCLICK: case SCN_MARGINCLICK:
switch (notifyData->margin) { switch (notifyData->margin) {
case MARGIN_SCRIPT_FOLD_INDEX: case MARGIN_SCRIPT_FOLD_INDEX:
SSM(SCI_TOGGLEFOLD, lineNumber, (sptr_t)0); SSM(SCI_TOGGLEFOLD, lineNumber, (sptr_t) 0);
break; break;
} }
break; break;
@ -177,6 +178,8 @@ static gboolean parseBox(PassT pass, char **tokenEnd, VectorDataT *self) {
if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE; if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE;
if (!parserGetWord("TO", tokenEnd)) return FALSE; if (!parserGetWord("TO", tokenEnd)) return FALSE;
if (!parserGetXY(tokenEnd, &x2, &y2)) return FALSE; if (!parserGetXY(tokenEnd, &x2, &y2)) return FALSE;
if (x2 < x1 || x1 < 0 || x2 < 0 || x1 > 319 || x2 > 319) return FALSE;
if (y2 < y1 || y1 < 0 || y2 < 0 || y1 > 199 || y2 > 199) return FALSE;
switch (pass) { switch (pass) {
case PASS_DRAW: case PASS_DRAW:
@ -200,6 +203,8 @@ static gboolean parseCircle(PassT pass, char **tokenEnd, VectorDataT *self) {
if (!parserGetX(tokenEnd, &r)) return FALSE; if (!parserGetX(tokenEnd, &r)) return FALSE;
if (!parserGetWord("AT", tokenEnd)) return FALSE; if (!parserGetWord("AT", tokenEnd)) return FALSE;
if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE; if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE;
if (x1 < 0 || x1 > 319) return FALSE;
if (y1 < 0 || y1 > 199) return FALSE;
switch (pass) { switch (pass) {
case PASS_DRAW: case PASS_DRAW:
@ -214,12 +219,27 @@ static gboolean parseCircle(PassT pass, char **tokenEnd, VectorDataT *self) {
} }
static gboolean parseClear(PassT pass, char **tokenEnd, VectorDataT *self) {
switch (pass) {
case PASS_DRAW:
jlDrawClear(self->jlc);
break;
case PASS_GENERATE:
break;
}
return TRUE;
}
static gboolean parseColor(PassT pass, char **tokenEnd, VectorDataT *self) { static gboolean parseColor(PassT pass, char **tokenEnd, VectorDataT *self) {
int c; int c;
// Color (short) // Color (short)
if (!parserGetX(tokenEnd, &c)) return FALSE; if (!parserGetX(tokenEnd, &c)) return FALSE;
if (c < 0 || c > 15) return FALSE;
switch (pass) { switch (pass) {
case PASS_DRAW: case PASS_DRAW:
@ -256,6 +276,8 @@ static gboolean parseEllipse(PassT pass, char **tokenEnd, VectorDataT *self) {
if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE; if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE;
if (!parserGetWord("TO", tokenEnd)) return FALSE; if (!parserGetWord("TO", tokenEnd)) return FALSE;
if (!parserGetXY(tokenEnd, &x2, &y2)) return FALSE; if (!parserGetXY(tokenEnd, &x2, &y2)) return FALSE;
if (x2 < x1 || x1 < 0 || x2 < 0 || x1 > 319 || x2 > 319) return FALSE;
if (y2 < y1 || y1 < 0 || y2 < 0 || y1 > 199 || y2 > 199) return FALSE;
switch (pass) { switch (pass) {
case PASS_DRAW: case PASS_DRAW:
@ -271,10 +293,27 @@ static gboolean parseEllipse(PassT pass, char **tokenEnd, VectorDataT *self) {
static gboolean parseFill(PassT pass, char **tokenEnd, VectorDataT *self) { static gboolean parseFill(PassT pass, char **tokenEnd, VectorDataT *self) {
// Fill (on|to) (value),(value) int c = 16;
int x1;
int y1;
// Fill (value),(value) {to (value}
if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE;
if (x1 < 0 || x1 > 319) return FALSE;
if (y1 < 0 || y1 > 199) return FALSE;
// Do they want to fill to a certain color? Or over the current color?
if (parserGetWord("TO", tokenEnd)) {
if (!parserGetX(tokenEnd, &c)) return FALSE;
if (c < 0 || c > 15) return FALSE;
}
switch (pass) { switch (pass) {
case PASS_DRAW: case PASS_DRAW:
if (c > 15) {
jlDrawFill(self->jlc, x1, y1);
} else {
jlDrawFillTo(self->jlc, x1, y1, c);
}
break; break;
case PASS_GENERATE: case PASS_GENERATE:
@ -286,13 +325,67 @@ static gboolean parseFill(PassT pass, char **tokenEnd, VectorDataT *self) {
static gboolean parseLine(PassT pass, char **tokenEnd, VectorDataT *self) { static gboolean parseLine(PassT pass, char **tokenEnd, VectorDataT *self) {
int x;
PointT p1;
PointT p2;
PointT *points = NULL;
// Line (value),(value) to (value),(value) [to ...] // Line (value),(value) to (value),(value) [to ...]
if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE; if (!parserGetXY(tokenEnd, &p1.x, &p1.y)) return FALSE;
if (!parserGetWord("TO", tokenEnd)) return FALSE; if (!parserGetWord("TO", tokenEnd)) return FALSE;
if (!parserGetXY(tokenEnd, &x2, &y2)) return FALSE; if (!parserGetXY(tokenEnd, &p2.x, &p2.y)) return FALSE;
if (p1.x < 0 || p1.x > 319) return FALSE;
if (p1.y < 0 || p1.y > 199) return FALSE;
if (p2.x < 0 || p2.x > 319) return FALSE;
if (p2.y < 0 || p2.y > 199) return FALSE;
arrput(points, p1);
arrput(points, p2);
while (parserGetWord("TO", tokenEnd)) {
if (!parserGetXY(tokenEnd, &p1.x, &p1.y)) {
// Error. Unwind array.
while (arrlen(points) > 0) arrdel(points, 0);
arrfree(points);
return FALSE;
}
arrput(points, p1);
}
switch (pass) { switch (pass) {
case PASS_DRAW: case PASS_DRAW:
for (x=0; x<arrlen(points)-1; x++) {
jlDrawLine(self->jlc, points[x].x, points[x].y, points[x+1].x, points[x+1].y);
}
break;
case PASS_GENERATE:
break;
}
// Unwind array.
while (arrlen(points) > 0) arrdel(points, 0);
arrfree(points);
return TRUE;
}
static gboolean parsePalette(PassT pass, char **tokenEnd, VectorDataT *self) {
int i;
int r;
int g;
int b;
if (!parserGetX(tokenEnd, &i)) return FALSE;
if (!parserGetWord("AS", tokenEnd)) return FALSE;
if (!parserGetXYZ(tokenEnd, &r, &g, &b)) return FALSE;
if (i < 0 || i > 15) return FALSE;
if (r < 0 || r > 15) return FALSE;
if (g < 0 || g > 15) return FALSE;
if (b < 0 || b > 15) return FALSE;
switch (pass) {
case PASS_DRAW:
jlPaletteSet(self->jlc, i, r, g, b);
break; break;
case PASS_GENERATE: case PASS_GENERATE:
@ -309,6 +402,8 @@ static gboolean parsePlot(PassT pass, char **tokenEnd, VectorDataT *self) {
// Plot (value),(value) // Plot (value),(value)
if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE; if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE;
if (x1 < 0 || x1 > 319) return FALSE;
if (y1 < 0 || y1 > 199) return FALSE;
switch (pass) { switch (pass) {
case PASS_DRAW: case PASS_DRAW:
@ -333,6 +428,8 @@ static gboolean parseRectangle(PassT pass, char **tokenEnd, VectorDataT *self) {
if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE; if (!parserGetXY(tokenEnd, &x1, &y1)) return FALSE;
if (!parserGetWord("TO", tokenEnd)) return FALSE; if (!parserGetWord("TO", tokenEnd)) return FALSE;
if (!parserGetXY(tokenEnd, &x2, &y2)) return FALSE; if (!parserGetXY(tokenEnd, &x2, &y2)) return FALSE;
if (x2 < x1 || x1 < 0 || x2 < 0 || x1 > 319 || x2 > 319) return FALSE;
if (y2 < y1 || y1 < 0 || y2 < 0 || y1 > 199 || y2 > 199) return FALSE;
switch (pass) { switch (pass) {
case PASS_DRAW: case PASS_DRAW:
@ -373,6 +470,7 @@ static void parser(PassT pass, gpointer userData) {
VectorDataT *self = (VectorDataT *)userData; VectorDataT *self = (VectorDataT *)userData;
int length = SSM(SCI_GETLENGTH, 0, 0); int length = SSM(SCI_GETLENGTH, 0, 0);
int x; int x;
int lineNumber = 0;
char *code; char *code;
char *line; char *line;
char *lineEnd; char *lineEnd;
@ -382,11 +480,13 @@ static void parser(PassT pass, gpointer userData) {
CommandsT commands[] = { CommandsT commands[] = {
{ "BOX", parseBox }, { "BOX", parseBox },
{ "CIRCLE", parseCircle }, { "CIRCLE", parseCircle },
{ "CLEAR", parseClear },
{ "COLOR", parseColor }, { "COLOR", parseColor },
{ "//", parseComment }, { "//", parseComment },
{ "ELLIPSE", parseEllipse }, { "ELLIPSE", parseEllipse },
{ "FILL", parseFill }, { "FILL", parseFill },
{ "LINE", parseLine }, { "LINE", parseLine },
{ "PALETTE", parsePalette },
{ "PLOT", parsePlot }, { "PLOT", parsePlot },
{ "RECTANGLE", parseRectangle }, { "RECTANGLE", parseRectangle },
{ "RESET", parseReset }, { "RESET", parseReset },
@ -400,6 +500,12 @@ static void parser(PassT pass, gpointer userData) {
// Fetch code. // Fetch code.
SSM(SCI_GETTEXT, length, (sptr_t)code); SSM(SCI_GETTEXT, length, (sptr_t)code);
if (pass == PASS_DRAW) {
// Clear error markers.
SSM(SCI_MARKERDELETEALL, MARKER_ERROR_ARROW, 0);
SSM(SCI_MARKERDELETEALL, MARKER_ERROR_HIGHLIGHT, 0);
}
// Parse code. // Parse code.
line = strtok_r(code, "\n", &lineEnd); line = strtok_r(code, "\n", &lineEnd);
while (line != NULL) { while (line != NULL) {
@ -417,11 +523,14 @@ static void parser(PassT pass, gpointer userData) {
} }
x++; x++;
} }
if (lineOkay == FALSE) { if (lineOkay == FALSE && pass == PASS_DRAW) {
//***TODO*** Mark lines that fail to parse. // Mark lines that fail to parse.
SSM(SCI_MARKERADD, lineNumber, MARKER_ERROR_ARROW);
SSM(SCI_MARKERADD, lineNumber, MARKER_ERROR_HIGHLIGHT);
} }
// Move to next line. // Move to next line.
line = strtok_r(NULL, "\n", &lineEnd); line = strtok_r(NULL, "\n", &lineEnd);
lineNumber++;
} }
// Release code. // Release code.
@ -450,6 +559,24 @@ static void parser(PassT pass, gpointer userData) {
*/ */
} }
static gboolean parserGetNextValue(char *token, char **valueEnd, int *x) {
char *value;
char *endPtr = NULL;
// Return next value in a comma separated list.
//***TODO*** Variable support.
value = strtok_r(token, ",", valueEnd);
if (value == NULL) return FALSE;
errno = 0; endPtr = NULL;
*x = (int)strtol(value, &endPtr, 10);
if (errno != 0) return FALSE;
return TRUE;
}
static gboolean parserGetWord(char *word, char **tokenEnd) { static gboolean parserGetWord(char *word, char **tokenEnd) {
char *token; char *token;
@ -482,27 +609,32 @@ static gboolean parserGetX(char **tokenEnd, int *x) {
static gboolean parserGetXY(char **tokenEnd, int *x, int *y) { static gboolean parserGetXY(char **tokenEnd, int *x, int *y) {
char *token; char *token;
char *value;
char *valueEnd; char *valueEnd;
char *endPtr;
// Return values of X,Y pair. // Return values of X,Y pair.
//***TODO*** Variable support.
token = strtok_r(NULL, " ", tokenEnd); token = strtok_r(NULL, " ", tokenEnd);
if (token == NULL) return FALSE; if (token == NULL) return FALSE;
value = strtok_r(token, ",", &valueEnd); if (!parserGetNextValue(token, &valueEnd, x)) return FALSE;
if (value == NULL) return FALSE; if (!parserGetNextValue(NULL, &valueEnd, y)) return FALSE;
errno = 0; endPtr = NULL;
*x = (int)strtol(value, &endPtr, 10);
if (errno != 0) return FALSE;
value = strtok_r(NULL, ",", &valueEnd); return TRUE;
if (value == NULL) return FALSE; }
errno = 0; endPtr = NULL;
*y = (int)strtol(value, &endPtr, 10);
if (errno != 0) return FALSE; static gboolean parserGetXYZ(char **tokenEnd, int *x, int *y, int *z) {
char *token;
char *valueEnd;
// Return values of X,Y pair.
token = strtok_r(NULL, " ", tokenEnd);
if (token == NULL) return FALSE;
if (!parserGetNextValue(token, &valueEnd, x)) return FALSE;
if (!parserGetNextValue(NULL, &valueEnd, y)) return FALSE;
if (!parserGetNextValue(NULL, &valueEnd, z)) return FALSE;
return TRUE; return TRUE;
} }
@ -560,8 +692,8 @@ void winVectorCreate(void) {
SSM(SCI_STYLESETBACK, STYLE_DEFAULT, 0); SSM(SCI_STYLESETBACK, STYLE_DEFAULT, 0);
SSM(SCI_STYLECLEARALL, 0, 0); SSM(SCI_STYLECLEARALL, 0, 0);
SSM(SCI_SETTABWIDTH, 3, 0); SSM(SCI_SETTABWIDTH, 3, 0);
SSM(SCI_SETMARGINWIDTHN, 0, (int)SSM(SCI_TEXTWIDTH, STYLE_LINENUMBER, (sptr_t)"99999")); SSM(SCI_SETMARGINWIDTHN, 0, (int)SSM(SCI_TEXTWIDTH, STYLE_LINENUMBER, (sptr_t)"_99999"));
SSM(SCI_SETMARGINWIDTHN, 1, 0); SSM(SCI_SETMARGINWIDTHN, 1, 16);
SSM(SCI_SETWRAPMODE, SC_WRAP_WORD, 0); SSM(SCI_SETWRAPMODE, SC_WRAP_WORD, 0);
SSM(SCI_SETWRAPVISUALFLAGS, SC_WRAPVISUALFLAG_END, 0); SSM(SCI_SETWRAPVISUALFLAGS, SC_WRAPVISUALFLAG_END, 0);
SSM(SCI_SETWRAPINDENTMODE, SC_WRAPINDENT_INDENT, 0); SSM(SCI_SETWRAPINDENTMODE, SC_WRAPINDENT_INDENT, 0);
@ -584,18 +716,25 @@ void winVectorCreate(void) {
SSM(SCI_STYLESETFORE, SCE_C_STRING, 0xFF00FF); SSM(SCI_STYLESETFORE, SCE_C_STRING, 0xFF00FF);
SSM(SCI_STYLESETBOLD, SCE_C_OPERATOR, 1); SSM(SCI_STYLESETBOLD, SCE_C_OPERATOR, 1);
// Margin markers.
SSM(SCI_MARKERDEFINE, MARKER_ERROR_ARROW, SC_MARK_SHORTARROW); // Error
SSM(SCI_MARKERSETBACK, MARKER_ERROR_ARROW, 255 | (0 << 8) | (0 << 16)); // RGB
SSM(SCI_MARKERDEFINE, MARKER_ERROR_HIGHLIGHT, SC_MARK_BACKGROUND); // Error
SSM(SCI_MARKERSETBACK, MARKER_ERROR_HIGHLIGHT, 127 | (0 << 8) | (0 << 16)); // RGB
// Debug // Debug
SSM(SCI_INSERTTEXT, 0, (sptr_t) SSM(SCI_INSERTTEXT, 0, (sptr_t)
"reset\n" "reset\n"
"palette 15 as 15,0,0\n"
"color 15\n" "color 15\n"
"box 0,0 to 319,299\n" "box 0,0 to 319,199\n"
); );
// Connect editor to our code. // Connect editor to our code.
g_signal_connect(G_OBJECT(self->editor), "sci-notify", G_CALLBACK(editorVectorNotify), self); g_signal_connect(G_OBJECT(self->editor), "sci-notify", G_CALLBACK(editorVectorNotify), self);
// Create our drawing surface and context. // Create our drawing surface and context.
self->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 320, 200); self->surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 320, 200);
self->cr = cairo_create(self->surface); self->cr = cairo_create(self->surface);
cairo_surface_flush(self->surface); cairo_surface_flush(self->surface);
self->surfacePointer = cairo_image_surface_get_data(self->surface); self->surfacePointer = cairo_image_surface_get_data(self->surface);
@ -610,6 +749,9 @@ void winVectorCreate(void) {
static void winVectorDelete(gpointer userData) { static void winVectorDelete(gpointer userData) {
VectorDataT *self = (VectorDataT *)userData; VectorDataT *self = (VectorDataT *)userData;
// Scintilla keeps sending events after we delete things it expects to still exist. Prevent that.
g_signal_handlers_disconnect_by_func(G_OBJECT(self->editor), G_CALLBACK(editorVectorNotify), self);
utilWindowUnRegister(userData); utilWindowUnRegister(userData);
jlContextDel(&self->jlc); jlContextDel(&self->jlc);