Editor now handles multiple lexers based on file extension.
This commit is contained in:
parent
f775bcb13c
commit
767e09969c
5 changed files with 125 additions and 15 deletions
|
@ -101,7 +101,8 @@ add_definitions(
|
|||
)
|
||||
|
||||
if(DEBUG_MODE)
|
||||
add_definitions(-O0)
|
||||
add_definitions(-O0) # -fno-stack-protector -g -fsanitize=address)
|
||||
# target_link_options(${CMAKE_PROJECT_NAME} PRIVATE -g -fsanitize=address)
|
||||
else()
|
||||
add_definitions(-O2)
|
||||
endif()
|
||||
|
|
|
@ -54,6 +54,7 @@ GtkWidget *utilFindChildWidget(GtkWidget *parent, const gchar *name);
|
|||
char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock);
|
||||
WindowDataT *utilGetWindowData(GtkWidget *window);
|
||||
gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widgets[], gpointer userData);
|
||||
void utilMessageDialog(GtkWidget *parent, char *title, char *message);
|
||||
gboolean utilMkDirP(const char *dir, const mode_t mode);
|
||||
char *utilObfuscateASCII(char *clearText);
|
||||
gboolean utilQuestionDialog(GtkWidget *parent, char *title, char *question);
|
||||
|
|
102
src/editor.c
102
src/editor.c
|
@ -20,6 +20,8 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "editor.h"
|
||||
#include "utils.h"
|
||||
|
@ -42,12 +44,29 @@ typedef struct EditorDataS {
|
|||
guint statusBarId;
|
||||
} EditorDataT;
|
||||
|
||||
typedef struct LexerDataS {
|
||||
char *extension;
|
||||
char *lexerName;
|
||||
} LexerDataT;
|
||||
|
||||
|
||||
static LexerDataT _lexerInfo[] = {
|
||||
{ "h", "cpp" },
|
||||
{ "c", "cpp" },
|
||||
{ "asm", "txt" }, //***TODO*** Need a custom lexer for these - and a way to tell different platforms apart.
|
||||
{ "txt", "txt" },
|
||||
{ "log", "txt" },
|
||||
{ "vic", "txt" }, //***TODO*** Need a custom lexer for this.
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static int _nextEditorId = 0;
|
||||
|
||||
|
||||
static void clearEditor(EditorDataT *self);
|
||||
static int determineLexer(char *filename);
|
||||
EVENT void editorEditorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotification *notifyData, gpointer userData);
|
||||
static gboolean fileIsSupported(char *filename);
|
||||
static void loadEditor(EditorDataT *self);
|
||||
static void loadEditorConfig(char *lexer, EditorDataT *self);
|
||||
EVENT void menuEditorEditCopy(GtkWidget *object, gpointer userData);
|
||||
|
@ -60,6 +79,7 @@ EVENT void menuEditorFileOpen(GtkWidget *object, gpointer userData);
|
|||
EVENT void menuEditorFileSave(GtkWidget *object, gpointer userData);
|
||||
EVENT void menuEditorFileSaveAs(GtkWidget *object, gpointer userData);
|
||||
EVENT void menuEditorHelpEditor(GtkWidget *object, gpointer userData);
|
||||
static void setLexer(EditorDataT *self, int lexer);
|
||||
static void status(EditorDataT *self, char *message);
|
||||
EVENT gboolean winEditorClose(GtkWidget *object, gpointer userData);
|
||||
static void winEditorDelete(gpointer userData);
|
||||
|
@ -78,6 +98,42 @@ static void clearEditor(EditorDataT *self) {
|
|||
}
|
||||
|
||||
|
||||
static int determineLexer(char *filename) {
|
||||
char *extension;
|
||||
int x = 0;
|
||||
int lexer = -1;
|
||||
|
||||
// Be sure this is something we can edit.
|
||||
|
||||
// Is there a file to load?
|
||||
if (filename) {
|
||||
// Find extension.
|
||||
x = strlen(filename);
|
||||
while (x >= 0) {
|
||||
x--;
|
||||
if (filename[x] == '.') break;
|
||||
}
|
||||
extension = strdup(&filename[x + 1]);
|
||||
// Make it lower case.
|
||||
for (x=0; x<strlen(extension); x++) {
|
||||
extension[x] = (char)tolower(extension[x]);
|
||||
}
|
||||
// Do we know how to cope with this?
|
||||
x = 0;
|
||||
while (_lexerInfo[x].extension != NULL) {
|
||||
if (strcmp(extension, _lexerInfo[x].extension) == 0) {
|
||||
lexer = x;
|
||||
break;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
DEL(extension);
|
||||
}
|
||||
|
||||
return lexer;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
@ -105,6 +161,19 @@ EVENT void editorEditorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotifi
|
|||
}
|
||||
|
||||
|
||||
static gboolean fileIsSupported(char *filename) {
|
||||
int lexer = determineLexer(filename);
|
||||
|
||||
// Can we edit this?
|
||||
if (lexer < 0) {
|
||||
utilMessageDialog(NULL, "Unknown File Type", "JoeyDev doesn't know how to edit this type of file.\n\nSorry.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void loadEditor(EditorDataT *self) {
|
||||
FILE *in = NULL;
|
||||
char *line = NULL;
|
||||
|
@ -272,7 +341,7 @@ EVENT void menuEditorFileNew(GtkWidget *object, gpointer userData) {
|
|||
if (!utilQuestionDialog(self->windowData.window, "New", "You have unsaved changes. Start new?")) {
|
||||
return;
|
||||
}
|
||||
status(self, "New image.");
|
||||
status(self, "New document.");
|
||||
}
|
||||
|
||||
clearEditor(self);
|
||||
|
@ -280,6 +349,9 @@ EVENT void menuEditorFileNew(GtkWidget *object, gpointer userData) {
|
|||
// Clear any filename.
|
||||
DEL(self->windowData.filename);
|
||||
|
||||
// Clear lexer.
|
||||
setLexer(self, -1);
|
||||
|
||||
// Mark clean.
|
||||
utilSetDirty((WindowDataT *)self, FALSE);
|
||||
}
|
||||
|
@ -291,7 +363,9 @@ EVENT void menuEditorFileOpen(GtkWidget *object, gpointer userData) {
|
|||
(void)object;
|
||||
|
||||
if (utilFileOpen((WindowDataT *)userData, "*.*", "Code")) {
|
||||
if (!fileIsSupported(self->windowData.filename)) return;
|
||||
clearEditor(self);
|
||||
setLexer(self, determineLexer(self->windowData.filename));
|
||||
loadEditor(self);
|
||||
}
|
||||
}
|
||||
|
@ -334,6 +408,9 @@ EVENT void menuEditorFileSave(GtkWidget *object, gpointer userData) {
|
|||
message(MSG_SEVERE, "Unknown error attempting to save %s!", self->windowData.filename);
|
||||
}
|
||||
|
||||
// Did the lexer change?
|
||||
setLexer(self, determineLexer(self->windowData.filename));
|
||||
|
||||
// Release code.
|
||||
DEL(code);
|
||||
}
|
||||
|
@ -358,6 +435,20 @@ EVENT void menuEditorHelpEditor(GtkWidget *object, gpointer userData) {
|
|||
}
|
||||
|
||||
|
||||
static void setLexer(EditorDataT *self, int lexer) {
|
||||
|
||||
if (lexer < 0) {
|
||||
DEL(self->pLexer);
|
||||
} else {
|
||||
self->pLexer = CreateLexer(_lexerInfo[lexer].lexerName);
|
||||
writeEditorConfig(_lexerInfo[lexer].lexerName, self); // Create default config if a custom one doesn't exist.
|
||||
loadEditorConfig(_lexerInfo[lexer].lexerName, self); // Load custom config.
|
||||
}
|
||||
|
||||
SSM(SCI_SETILEXER, 0, (sptr_t)self->pLexer);
|
||||
}
|
||||
|
||||
|
||||
static void status(EditorDataT *self, char *message) {
|
||||
gtk_statusbar_remove_all(GTK_STATUSBAR(self->statusBar), self->statusBarId);
|
||||
gtk_statusbar_push(GTK_STATUSBAR(self->statusBar), self->statusBarId, message);
|
||||
|
@ -397,7 +488,7 @@ void winEditorCreate(char *filename) {
|
|||
NULL
|
||||
};
|
||||
|
||||
//***TODO*** Be sure this is something we can edit as text.
|
||||
if (filename && !fileIsSupported(filename)) return;
|
||||
|
||||
// Set up instance data.
|
||||
self = NEW(EditorDataT);
|
||||
|
@ -466,12 +557,7 @@ void winEditorCreate(char *filename) {
|
|||
SSM(SCI_MARKERDEFINE, MARKER_ERROR_HIGHLIGHT, SC_MARK_BACKGROUND); // Error
|
||||
SSM(SCI_MARKERSETBACK, MARKER_ERROR_HIGHLIGHT, 127 | (0 << 8) | (0 << 16)); // RGB
|
||||
|
||||
// Add lexer for language support.
|
||||
self->pLexer = CreateLexer("cpp");
|
||||
SSM(SCI_SETILEXER, 0, (sptr_t)self->pLexer);
|
||||
|
||||
writeEditorConfig("cpp", self);
|
||||
loadEditorConfig("cpp", self);
|
||||
setLexer(self, determineLexer(filename));
|
||||
|
||||
// Connect editor to our code.
|
||||
g_signal_connect(G_OBJECT(self->editor), "sci-notify", G_CALLBACK(editorEditorNotify), self);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "http.h"
|
||||
#include "ssh.h"
|
||||
#include "utils.h"
|
||||
#include "cwalk.h"
|
||||
|
||||
|
||||
char *__resourcePath = NULL;
|
||||
|
@ -38,6 +39,12 @@ int main(int argc, char **argv) {
|
|||
unlink("memwatch.log");
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
cwk_path_set_style(CWK_STYLE_WINDOWS);
|
||||
#else
|
||||
cwk_path_set_style(CWK_STYLE_UNIX);
|
||||
#endif
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// Make sure we have a config & resources folder.
|
||||
|
|
27
src/utils.c
27
src/utils.c
|
@ -310,7 +310,7 @@ gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, cha
|
|||
GtkFileFilter *filter;
|
||||
gboolean result = FALSE;
|
||||
char *files = utilCreateString("%s Files", what);
|
||||
int x;
|
||||
size_t x;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new("Save As",
|
||||
GTK_WINDOW(self->window),
|
||||
|
@ -321,7 +321,7 @@ gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, cha
|
|||
|
||||
if (*filename != NULL) {
|
||||
memcpy(__utilFilenameBuffer, *filename, strlen(*filename) + 1);
|
||||
cwk_path_get_dirname(__utilFilenameBuffer, (size_t *)&x);
|
||||
cwk_path_get_dirname(__utilFilenameBuffer, &x);
|
||||
if (x > 0) __utilFilenameBuffer[x] = 0;
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),__utilFilenameBuffer);
|
||||
}
|
||||
|
@ -454,6 +454,21 @@ gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widg
|
|||
}
|
||||
|
||||
|
||||
void utilMessageDialog(GtkWidget *parent, char *title, char *message) {
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new(
|
||||
GTK_WINDOW(parent),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"%s", message);
|
||||
gtk_window_set_title(GTK_WINDOW(dialog), title);
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
|
||||
gboolean utilMkDirP(const char *dir, const mode_t mode) {
|
||||
char *p = NULL;
|
||||
struct stat sb;
|
||||
|
@ -584,15 +599,15 @@ void utilSetDirty(WindowDataT *self, gboolean dirty) {
|
|||
|
||||
|
||||
void utilUpdatePath(WindowDataT *self) {
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
DEL(self->path);
|
||||
|
||||
if (self->filename) {
|
||||
// Derive the path from the filename.
|
||||
self->path = strdup(self->filename);
|
||||
cwk_path_get_dirname(self->path, (size_t *)&i);
|
||||
cwk_path_get_dirname(self->path, &i);
|
||||
if (i > 0) self->path[i] = 0;
|
||||
} else {
|
||||
DEL(self->path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue