Start of code editor.

This commit is contained in:
Scott Duensing 2023-01-26 21:35:14 -06:00
parent e10d89cc44
commit bc108fd73a
11 changed files with 475 additions and 7 deletions

View file

@ -53,6 +53,7 @@ set(SOURCE_FILES
src/project.c
src/ssh.c
src/http.c
src/editor.c
)
configure_file(include/config.h.in config.h)

30
include/editor.h Normal file
View file

@ -0,0 +1,30 @@
/*
* 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 EDITOR_H
#define EDITOR_H
void winEditorCreate(void);
#endif // EDITOR_H

View file

@ -32,4 +32,8 @@
#include "Lexilla.h"
#define SSM(m, w, l) scintilla_send_message(self->sci, m, w, l)
#define MARGIN_SCRIPT_FOLD_INDEX 1
#endif //SCINTILLAHEADERS_H

216
src/editor.c Normal file
View file

@ -0,0 +1,216 @@
/*
* 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.
*/
#include "common.h"
#include "editor.h"
#include "utils.h"
#include "scintillaHeaders.h"
typedef struct EditorDataS {
WindowDataT windowData;
GtkWidget *boxForEditor;
GtkWidget *statusBar;
GtkWidget *editor;
ScintillaObject *sci;
void *pLexer;
int id;
int statusBarId;
} EditorDataT;
static int _nextEditorId = 0;
EVENT void editorEditorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData);
EVENT gboolean winEditorClose(GtkWidget *object, gpointer userData);
static void winEditorDelete(gpointer userData);
EVENT void editorEditorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData) {
EditorDataT *self = (EditorDataT *)userData;
int lineNumber = (int)SSM(SCI_LINEFROMPOSITION, (uptr_t)notifyData->position, (sptr_t)0);
(void)sciWidget;
(void)ctrlID;
switch (notifyData->nmhdr.code) {
case SCN_MODIFIED:
if (notifyData->modificationType & SC_MOD_INSERTTEXT || notifyData->modificationType & SC_MOD_DELETETEXT) {
// Mark text dirty. SCN_SAVEPOINTLEFT isn't being reliable.
utilSetDirty((WindowDataT *)self, TRUE);
}
break;
case SCN_MARGINCLICK:
switch (notifyData->margin) {
case MARGIN_SCRIPT_FOLD_INDEX:
SSM(SCI_TOGGLEFOLD, lineNumber, (sptr_t)0);
break;
}
break;
}
}
EVENT gboolean winEditorClose(GtkWidget *object, gpointer userData) {
// userData is not reliable due to menuVectorFileClose and util indirectly calling us.
EditorDataT *self = (EditorDataT *)utilGetWindowData(object);
(void)userData;
if (self->windowData.isDirty == TRUE) {
if (utilQuestionDialog(self->windowData.window, "Exit", "You have unsaved changes. Exit?")) {
winEditorDelete(self);
return FALSE;
}
return TRUE;
}
winEditorDelete(self);
return FALSE;
}
void winEditorCreate(void) {
EditorDataT *self;
char *widgetNames[] = {
"winEditor",
"boxEditorForEditor",
"statusEditor",
NULL
};
GtkWidget **widgets[] = {
NULL,
NULL,
NULL
};
// Set up instance data.
self = NEW(EditorDataT);
self->windowData.closeWindow = winEditorClose;
// Load widgets from XML.
widgets[0] = &self->windowData.window;
widgets[1] = &self->boxForEditor;
widgets[2] = &self->statusBar;
utilGetWidgetsFromMemory("/com/kangaroopunch/joeydev/Editor.glade", widgetNames, widgets, self);
// Register window.
utilWindowRegister(self);
// Get status bar context ID.
self->statusBarId = gtk_statusbar_get_context_id(GTK_STATUSBAR(self->statusBar), "JoeyDev");
// Create Scintilla editor.
self->editor = scintilla_new();
self->sci = SCINTILLA(self->editor);
self->id = _nextEditorId++;
scintilla_set_id(self->sci, self->id);
gtk_widget_set_halign(self->editor, GTK_ALIGN_FILL);
gtk_widget_set_valign(self->editor, GTK_ALIGN_FILL);
gtk_widget_set_hexpand(self->editor, TRUE);
gtk_widget_set_vexpand(self->editor, TRUE);
gtk_box_set_child_packing(GTK_BOX(self->boxForEditor), self->editor, TRUE, TRUE, 0, GTK_PACK_START);
gtk_container_add(GTK_CONTAINER(self->boxForEditor), self->editor);
// Configure editor.
SSM(SCI_SETCODEPAGE, SC_CP_UTF8, 0);
SSM(SCI_SETIMEINTERACTION, SC_IME_WINDOWED, 0);
SSM(SCI_STYLESETCHARACTERSET, STYLE_DEFAULT, SC_CHARSET_DEFAULT);
SSM(SCI_STYLESETFONT, STYLE_DEFAULT, (sptr_t)"Monospace");
SSM(SCI_STYLESETSIZEFRACTIONAL, STYLE_DEFAULT, 11 * SC_FONT_SIZE_MULTIPLIER);
SSM(SCI_STYLESETFORE, STYLE_DEFAULT, 0xFFFFFF);
SSM(SCI_STYLESETBACK, STYLE_DEFAULT, 0);
SSM(SCI_STYLECLEARALL, 0, 0);
SSM(SCI_SETTABWIDTH, 3, 0);
//SSM(SCI_SETEOLMODE, SC_EOL_CR, 0);
SSM(SCI_SETMARGINWIDTHN, 0, (int)SSM(SCI_TEXTWIDTH, STYLE_LINENUMBER, (sptr_t)"_99999"));
SSM(SCI_SETMARGINWIDTHN, 1, 16);
SSM(SCI_SETWRAPMODE, SC_WRAP_NONE, 0);
SSM(SCI_SETCARETSTYLE, CARETSTYLE_BLOCK | CARETSTYLE_OVERSTRIKE_BLOCK, 0);
SSM(SCI_SETCARETFORE, 0x00ffff, 0);
SSM(SCI_STYLESETBACK, STYLE_LINENUMBER, 0x222222);
// Add lexer for language support.
self->pLexer = CreateLexer("cpp");
SSM(SCI_SETILEXER, 0, (sptr_t)self->pLexer);
/*
#define SCE_C_DEFAULT 0
#define SCE_C_COMMENT 1
#define SCE_C_COMMENTLINE 2
#define SCE_C_COMMENTDOC 3
#define SCE_C_NUMBER 4
#define SCE_C_WORD 5
#define SCE_C_STRING 6
#define SCE_C_CHARACTER 7
#define SCE_C_UUID 8
#define SCE_C_PREPROCESSOR 9
#define SCE_C_OPERATOR 10
#define SCE_C_IDENTIFIER 11
#define SCE_C_STRINGEOL 12
#define SCE_C_VERBATIM 13
#define SCE_C_REGEX 14
#define SCE_C_COMMENTLINEDOC 15
#define SCE_C_WORD2 16
#define SCE_C_COMMENTDOCKEYWORD 17
#define SCE_C_COMMENTDOCKEYWORDERROR 18
#define SCE_C_GLOBALCLASS 19
#define SCE_C_STRINGRAW 20
#define SCE_C_TRIPLEVERBATIM 21
#define SCE_C_HASHQUOTEDSTRING 22
#define SCE_C_PREPROCESSORCOMMENT 23
#define SCE_C_PREPROCESSORCOMMENTDOC 24
#define SCE_C_USERLITERAL 25
#define SCE_C_TASKMARKER 26
#define SCE_C_ESCAPESEQUENCE 27
*/
SSM(SCI_STYLESETFORE, SCE_C_PREPROCESSOR, 0x0080ff);
SSM(SCI_STYLESETFORE, SCE_C_COMMENT, 0x00FF00);
SSM(SCI_STYLESETFORE, SCE_C_COMMENTLINE, 0x00FF00);
SSM(SCI_STYLESETFORE, SCE_C_NUMBER, 0xFFFF00);
SSM(SCI_STYLESETFORE, SCE_C_WORD, 0xFF0000);
SSM(SCI_STYLESETFORE, SCE_C_STRING, 0xFF00FF);
SSM(SCI_STYLESETBOLD, SCE_C_OPERATOR, 1);
// Connect editor to our code.
g_signal_connect(G_OBJECT(self->editor), "sci-notify", G_CALLBACK(editorEditorNotify), self);
// Show window.
gtk_widget_show_all(self->windowData.window);
}
static void winEditorDelete(gpointer userData) {
EditorDataT *self = (EditorDataT *)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(editorEditorNotify), self);
utilWindowUnRegister(userData);
DEL(self);
}

View file

@ -25,6 +25,7 @@
#include "common.h"
#include "utils.h"
#include "project.h"
#include "editor.h"
#include "vector.h"
#include "joeydev.h"
@ -33,6 +34,7 @@ static GtkWidget *_winJoeyDev = NULL;
EVENT void toolJoeyDevAboutClicked(GtkWidget *widget, gpointer userData);
EVENT void toolJoeyDevEditorClicked(GtkWidget *widget, gpointer userData);
EVENT void toolJoeyDevProjectClicked(GtkWidget *widget, gpointer userData);
EVENT void toolJoeyDevQuitClicked(GtkWidget *widget, gpointer userData);
EVENT void toolJoeyDevVectorClicked(GtkWidget *widget, gpointer userData);
@ -64,6 +66,14 @@ EVENT void toolJoeyDevAboutClicked(GtkWidget *widget, gpointer userData) {
}
EVENT void toolJoeyDevEditorClicked(GtkWidget *widget, gpointer userData) {
(void)widget;
(void)userData;
winEditorCreate();
}
EVENT void toolJoeyDevProjectClicked(GtkWidget *widget, gpointer userData) {
(void)widget;
(void)userData;

View file

@ -193,7 +193,7 @@ gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what) {
GtkWidget *dialog;
GtkFileFilter *filter;
gboolean result = FALSE;
char *files = utilCreateString("%s Files", what);
char *files = utilCreateString("%s Files", what);
int x;
dialog = gtk_file_chooser_dialog_new("Save As",
@ -442,11 +442,14 @@ void utilWindowRegister(gpointer windowData) {
w->title = strdup(gtk_window_get_title(GTK_WINDOW(w->window)));
hmput(_windowList, w->window, windowData);
debug("Window Registered: %d\n", hmlen(_windowList));
}
int utilWindowsCloseAll(void) {
WindowDataT *w;
debug("Windows Left Open: %d\n", hmlen(_windowList));
while (hmlen(_windowList) > 0) {
w = (WindowDataT *)_windowList[0].value;
if (w->closeWindow(w->window, w) == TRUE) {
@ -469,10 +472,11 @@ int utilWindowsOpen(void) {
gboolean utilWindowUnRegister(gpointer windowData) {
int result;
int result = 0;
WindowDataT *w = (WindowDataT *)windowData;
WindowDataT *w = (WindowDataT *)windowData;
result = hmdel(_windowList, w->window);
debug("Window Unregistered: %d\n", hmlen(_windowList));
DEL(w->filename);
DEL(w->title);

View file

@ -42,8 +42,6 @@
#define RENDER_TIMEOUT 5 // In seconds
#define SSM(m, w, l) scintilla_send_message(self->sci, m, w, l)
#define MARGIN_SCRIPT_FOLD_INDEX 1
#define MARKER_ERROR_ARROW 0
#define MARKER_ERROR_HIGHLIGHT 1
#define PREVIEW_WIDTH 640
@ -1383,7 +1381,7 @@ void winVectorCreate(char *filename) {
"boxVectorForEditor",
"drawVectorImage",
"fileVectorTraceImage",
"status",
"statusVector",
NULL
};
GtkWidget **widgets[] = {

189
ui/Editor.glade Normal file
View file

@ -0,0 +1,189 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="winEditor">
<property name="can-focus">False</property>
<property name="title" translatable="yes">Editor</property>
<property name="default-width">640</property>
<property name="default-height">480</property>
<property name="icon-name">accessories-text-editor</property>
<signal name="delete-event" handler="winEditorClose" swapped="no"/>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="boxEditorForEditor">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="statusEditor">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View file

@ -69,6 +69,21 @@ Author: Scott Duensing <scott@kangaroopunch.com>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="toolJoeyDevEditor">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Editor</property>
<property name="label" translatable="yes">Editor</property>
<property name="use-underline">True</property>
<property name="icon-name">accessories-text-editor</property>
<signal name="clicked" handler="toolJoeyDevEditorClicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="toolJoeyDevVector">
<property name="visible">True</property>

View file

@ -461,7 +461,7 @@ Author: Scott Duensing <scott@kangaroopunch.com>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="status">
<object class="GtkStatusbar" id="statusVector">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">10</property>

View file

@ -4,6 +4,7 @@
<file preprocess="xml-stripblanks">JoeyDev.glade</file>
<file preprocess="xml-stripblanks">Project.glade</file>
<file preprocess="xml-stripblanks">BuildServer.glade</file>
<file preprocess="xml-stripblanks">Editor.glade</file>
<file preprocess="xml-stripblanks">Vector.glade</file>
<file>Logo.png</file>
</gresource>