Warning and error links for GCC based targets are now working with the code editor.
This commit is contained in:
parent
0d50e3bc83
commit
99010a03bd
4 changed files with 161 additions and 28 deletions
|
@ -24,7 +24,11 @@
|
|||
#define EDITOR_H
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
void winEditorCreate(char *filename);
|
||||
void winEditorGoto(char *filename, size_t line, size_t column);
|
||||
|
||||
|
||||
#endif // EDITOR_H
|
||||
|
|
|
@ -36,4 +36,4 @@
|
|||
#define MARGIN_SCRIPT_FOLD_INDEX 1
|
||||
|
||||
|
||||
#endif //SCINTILLAHEADERS_H
|
||||
#endif // SCINTILLAHEADERS_H
|
||||
|
|
80
src/editor.c
80
src/editor.c
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "editor.h"
|
||||
#include "utils.h"
|
||||
#include "scintillaHeaders.h"
|
||||
|
@ -42,6 +41,9 @@ typedef struct EditorDataS {
|
|||
void *pLexer;
|
||||
int id;
|
||||
guint statusBarId;
|
||||
size_t textLine;
|
||||
size_t textColumn;
|
||||
gboolean editorPainted;
|
||||
} EditorDataT;
|
||||
|
||||
typedef struct LexerDataS {
|
||||
|
@ -50,6 +52,8 @@ typedef struct LexerDataS {
|
|||
} LexerDataT;
|
||||
|
||||
|
||||
static EditorDataT **_editorWindows = NULL;
|
||||
|
||||
static LexerDataT _lexerInfo[] = {
|
||||
{ "h", "cpp" },
|
||||
{ "c", "cpp" },
|
||||
|
@ -67,6 +71,7 @@ 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 EditorDataT *isAlreadyOpen(char *filename);
|
||||
static void loadEditor(EditorDataT *self);
|
||||
static void loadEditorConfig(char *lexer, EditorDataT *self);
|
||||
EVENT void menuEditorEditCopy(GtkWidget *object, gpointer userData);
|
||||
|
@ -83,6 +88,7 @@ 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);
|
||||
static gboolean winEditorGotoUpdate(gpointer userData);
|
||||
static void writeEditorConfig(char *lexer, EditorDataT *self);
|
||||
|
||||
|
||||
|
@ -157,6 +163,9 @@ EVENT void editorEditorNotify(GtkWidget *sciWidget, gint ctrlID, struct SCNotifi
|
|||
}
|
||||
break;
|
||||
|
||||
case SCN_PAINTED:
|
||||
self->editorPainted = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,6 +183,20 @@ static gboolean fileIsSupported(char *filename) {
|
|||
}
|
||||
|
||||
|
||||
static EditorDataT *isAlreadyOpen(char *filename) {
|
||||
int i;
|
||||
|
||||
for (i=0; i<arrlen(_editorWindows); i++) {
|
||||
if (strcmp(_editorWindows[i]->windowData.filename, filename) == 0) {
|
||||
// Focus the existing window.
|
||||
gtk_window_present_with_time(GTK_WINDOW(_editorWindows[i]->windowData.window), GDK_CURRENT_TIME);
|
||||
return _editorWindows[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void loadEditor(EditorDataT *self) {
|
||||
FILE *in = NULL;
|
||||
char *line = NULL;
|
||||
|
@ -364,6 +387,10 @@ EVENT void menuEditorFileOpen(GtkWidget *object, gpointer userData) {
|
|||
|
||||
if (utilFileOpen((WindowDataT *)userData, "*.*", "Code")) {
|
||||
if (!fileIsSupported(self->windowData.filename)) return;
|
||||
if (isAlreadyOpen(self->windowData.filename) != NULL) {
|
||||
DEL(self->windowData.filename);
|
||||
return;
|
||||
}
|
||||
clearEditor(self);
|
||||
setLexer(self, determineLexer(self->windowData.filename));
|
||||
loadEditor(self);
|
||||
|
@ -421,6 +448,7 @@ EVENT void menuEditorFileSaveAs(GtkWidget *object, gpointer userData) {
|
|||
|
||||
(void)object;
|
||||
|
||||
//***TODO*** If they save over an existing file that is open to edit they will have two editors open on the same filename.
|
||||
if (utilFileSaveAs((WindowDataT *)userData, "*.*", "Code")) {
|
||||
menuEditorFileSave(object, (EditorDataT *)userData);
|
||||
}
|
||||
|
@ -488,8 +516,12 @@ void winEditorCreate(char *filename) {
|
|||
NULL
|
||||
};
|
||||
|
||||
// Can we edit this?
|
||||
if (filename && !fileIsSupported(filename)) return;
|
||||
|
||||
// Is there already an editor window open for this file?
|
||||
if (isAlreadyOpen(filename) != NULL) return;
|
||||
|
||||
// Set up instance data.
|
||||
self = NEW(EditorDataT);
|
||||
self->windowData.closeWindow = winEditorClose;
|
||||
|
@ -565,6 +597,9 @@ void winEditorCreate(char *filename) {
|
|||
// Show window.
|
||||
gtk_widget_show_all(self->windowData.window);
|
||||
|
||||
// Remember window.
|
||||
arrput(_editorWindows, self);
|
||||
|
||||
if (filename != NULL) {
|
||||
self->windowData.filename = strdup(filename);
|
||||
loadEditor(self);
|
||||
|
@ -574,16 +609,59 @@ void winEditorCreate(char *filename) {
|
|||
|
||||
static void winEditorDelete(gpointer userData) {
|
||||
EditorDataT *self = (EditorDataT *)userData;
|
||||
int i;
|
||||
|
||||
// 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);
|
||||
|
||||
// Remove from open results window list.
|
||||
for (i=0; i<arrlen(_editorWindows); i++) {
|
||||
if (_editorWindows[i] == self) {
|
||||
arrdel(_editorWindows, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
utilWindowUnRegister(userData);
|
||||
|
||||
DEL(self);
|
||||
}
|
||||
|
||||
|
||||
void winEditorGoto(char *filename, size_t line, size_t column) {
|
||||
EditorDataT *self = NULL;
|
||||
|
||||
// Ensure the editor exists.
|
||||
winEditorCreate(filename);
|
||||
|
||||
// Find it.
|
||||
self = isAlreadyOpen(filename);
|
||||
if (self != NULL) {
|
||||
// Move caret after GTK has a bit to settle down.
|
||||
self->textLine = line;
|
||||
self->textColumn = column;
|
||||
self->editorPainted = FALSE;
|
||||
g_idle_add(winEditorGotoUpdate, self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean winEditorGotoUpdate(gpointer userData) {
|
||||
EditorDataT *self = (EditorDataT *)userData;
|
||||
int position;
|
||||
|
||||
// Wait for Scintilla to be ready.
|
||||
if (self->editorPainted == FALSE) return G_SOURCE_CONTINUE;
|
||||
|
||||
// Move caret.
|
||||
SSM(SCI_GRABFOCUS, 0, 0);
|
||||
position = SSM(SCI_POSITIONFROMLINE, (uptr_t)self->textLine, (sptr_t)0) + self->textColumn;
|
||||
SSM(SCI_GOTOPOS, (uptr_t)position, (sptr_t)0);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
||||
static void writeEditorConfig(char *lexer, EditorDataT *self) {
|
||||
char *name = NULL;
|
||||
char *tags = NULL;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "common.h"
|
||||
#include "results.h"
|
||||
#include "utils.h"
|
||||
#include "editor.h"
|
||||
|
||||
|
||||
typedef struct ResultsDataS {
|
||||
|
@ -45,6 +46,7 @@ typedef struct ResultsDataS {
|
|||
static ResultsDataT **_resultWindows = NULL;
|
||||
|
||||
|
||||
EVENT void messageClicked(GtkButton *widget, gpointer userData);
|
||||
EVENT void resultClicked(GtkButton *widget, gpointer userData);
|
||||
static void resultLoadRaw(gboolean release, int target, int arch, ResultsDataT *self);
|
||||
static void resultParseRaw(gboolean release, char **lineArray, ResultsDataT *self);
|
||||
|
@ -53,6 +55,34 @@ EVENT gboolean winBuildResultsClose(GtkWidget *object, gpointer userData);
|
|||
static void winBuildResultsDelete(gpointer userData);
|
||||
|
||||
|
||||
EVENT void messageClicked(GtkButton *widget, gpointer userData) {
|
||||
ResultsDataT *self = (ResultsDataT *)userData;
|
||||
const char *name = gtk_widget_get_name(GTK_WIDGET(widget));
|
||||
char *tok;
|
||||
char *temp;
|
||||
char *file;
|
||||
size_t line;
|
||||
size_t column;
|
||||
gboolean isWarning;
|
||||
|
||||
// Extract info from button name.
|
||||
tok = strdup(name);
|
||||
temp = strtok(tok, ":");
|
||||
isWarning = (temp[0] == 'w');
|
||||
temp = strtok(NULL, ":");
|
||||
file = utilCreateString("%s%s", self->project->windowData.path, temp);
|
||||
temp = strtok(NULL, ":");
|
||||
line = atol(temp);
|
||||
temp = strtok(NULL, ":");
|
||||
column = atol(temp);
|
||||
|
||||
winEditorGoto(file, line, column);
|
||||
|
||||
DEL(tok);
|
||||
DEL(file);
|
||||
}
|
||||
|
||||
|
||||
EVENT void resultClicked(GtkButton *widget, gpointer userData) {
|
||||
ResultsDataT *self = (ResultsDataT *)userData;
|
||||
const char *name = gtk_widget_get_name(GTK_WIDGET(widget));
|
||||
|
@ -60,9 +90,9 @@ EVENT void resultClicked(GtkButton *widget, gpointer userData) {
|
|||
int a;
|
||||
gboolean r;
|
||||
|
||||
// Highlight the button pressed button.
|
||||
gtk_button_set_relief(widget, GTK_RELIEF_NONE);
|
||||
gtk_button_set_relief(GTK_BUTTON(self->pressedButton), GTK_RELIEF_NORMAL);
|
||||
// Highlight the pressed button.
|
||||
gtk_button_set_relief(widget, GTK_RELIEF_NORMAL);
|
||||
gtk_button_set_relief(GTK_BUTTON(self->pressedButton), GTK_RELIEF_NONE);
|
||||
self->pressedButton = GTK_WIDGET(widget);
|
||||
|
||||
// Extract button info from widget name.
|
||||
|
@ -127,7 +157,11 @@ static void resultParseRaw(gboolean release, char **lineArray, ResultsDataT *sel
|
|||
GtkWidget *button;
|
||||
int i;
|
||||
char *temp;
|
||||
char *tok;
|
||||
char *text;
|
||||
char *file;
|
||||
size_t line;
|
||||
size_t column;
|
||||
gboolean isWarning;
|
||||
|
||||
messages = release ? self->lstRelease : self->lstDebug;
|
||||
|
@ -135,6 +169,9 @@ static void resultParseRaw(gboolean release, char **lineArray, ResultsDataT *sel
|
|||
for (i=0; i<arrlen(lineArray); i++) {
|
||||
text = NULL;
|
||||
isWarning = FALSE;
|
||||
file = NULL;
|
||||
line = 0;
|
||||
column = 0;
|
||||
|
||||
// ***TODO*** This is going to need to be a lot more complicated.
|
||||
// We need the line number and filename from multiple compilers.
|
||||
|
@ -145,6 +182,17 @@ static void resultParseRaw(gboolean release, char **lineArray, ResultsDataT *sel
|
|||
if (strstr(lineArray[i], " error: ") != NULL) {
|
||||
text = lineArray[i];
|
||||
}
|
||||
if (text) {
|
||||
tok = strdup(text);
|
||||
temp = strtok(tok, ":");
|
||||
file = strdup(temp);
|
||||
temp = strtok(NULL, ":");
|
||||
line = atol(temp) - 1;
|
||||
temp = strtok(NULL, ":");
|
||||
column = atol(temp) - 1;
|
||||
DEL(tok);
|
||||
}
|
||||
// --- The above is basically GCC only. And lame.
|
||||
|
||||
if (text) {
|
||||
// New listbox row.
|
||||
|
@ -154,10 +202,11 @@ static void resultParseRaw(gboolean release, char **lineArray, ResultsDataT *sel
|
|||
|
||||
// Icon button.
|
||||
button = gtk_button_new_from_icon_name(isWarning ? "dialog-warning" : "dialog-error", GTK_ICON_SIZE_BUTTON);
|
||||
temp = utilCreateString("%c", isWarning ? 'w' : 'e'); // We store data about this button in its name.
|
||||
temp = utilCreateString("%c:%s:%lu:%lu", isWarning ? 'w' : 'e', file, line, column); // We store data about this button in its name.
|
||||
gtk_widget_set_name(button, temp);
|
||||
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
|
||||
DEL(temp);
|
||||
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(messageClicked), self);
|
||||
|
||||
// Message.
|
||||
label = gtk_label_new(text);
|
||||
|
@ -240,6 +289,7 @@ static void resultsUpdate(ResultsDataT *self) {
|
|||
temp = utilCreateString("d%da%d", i, j); // We store data about this button in its name.
|
||||
gtk_widget_set_name(w, temp);
|
||||
DEL(temp);
|
||||
gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
|
||||
gtk_grid_attach(GTK_GRID(self->gridResults), w, 2, gridLine, 1, 1);
|
||||
g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(resultClicked), self);
|
||||
|
||||
|
@ -248,13 +298,14 @@ static void resultsUpdate(ResultsDataT *self) {
|
|||
temp = utilCreateString("r%da%d", i, j); // We store data about this button in its name.
|
||||
gtk_widget_set_name(w, temp);
|
||||
DEL(temp);
|
||||
gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
|
||||
gtk_grid_attach(GTK_GRID(self->gridResults), w, 3, gridLine, 1, 1);
|
||||
g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(resultClicked), self);
|
||||
|
||||
if (firstSystem < 0) {
|
||||
firstSystem = i;
|
||||
// Highlight the button pressed button.
|
||||
gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
|
||||
gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NORMAL);
|
||||
self->pressedButton = w;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue