From 5dead7d66c7f8be4adee70f8ace9ffea55747a36 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Wed, 26 Apr 2023 17:54:06 -0500 Subject: [PATCH] Launching code editor from recipe dialog now working. Removed a mess of redundant path code. --- include/common.h | 3 +- include/utils.h | 2 ++ src/project.c | 86 +++++++++++++----------------------------------- src/utils.c | 57 ++++++++++++++++++++++++++++++-- src/vector.c | 2 ++ ui/Cook.glade | 3 ++ 6 files changed, 86 insertions(+), 67 deletions(-) diff --git a/include/common.h b/include/common.h index 8092421..bae12dd 100644 --- a/include/common.h +++ b/include/common.h @@ -52,7 +52,8 @@ typedef struct WindowDataS { gboolean (*closeWindow)(GtkWidget* widget, gpointer data); gboolean isDirty; char *title; - char *filename; + char *filename; // This typically is a full absolute path. + char *path; // This will be derived from the filename. } WindowDataT; diff --git a/include/utils.h b/include/utils.h index 8e8f8b3..b2f84e8 100644 --- a/include/utils.h +++ b/include/utils.h @@ -50,6 +50,7 @@ gboolean utilFileOpen(WindowDataT *self, char *extension, char *what); char *utilFileRemoveExtension(char *filename); gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what); gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, char **filename); +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); @@ -57,6 +58,7 @@ gboolean utilMkDirP(const char *dir, const mode_t mode); char *utilObfuscateASCII(char *clearText); gboolean utilQuestionDialog(GtkWidget *parent, char *title, char *question); void utilSetDirty(WindowDataT *self, gboolean dirty); +void utilUpdatePath(WindowDataT *self); void utilWindowRegister(gpointer windowData); int utilWindowsCloseAll(void); int utilWindowsOpen(void); diff --git a/src/project.c b/src/project.c index df5e16a..9583b4a 100644 --- a/src/project.c +++ b/src/project.c @@ -81,7 +81,6 @@ typedef struct ProjectDataS { char *buildPassword; TargetT **targets; GtkWidget *tempWidget; // Used to pass data around dialogs. - char *tempString; // Used to pass data around dialogs. } ProjectDataT; typedef struct SectionDataS { @@ -164,31 +163,31 @@ EVENT void buildTargetClicked(GtkButton *widget, gpointer userData) { EVENT void btnEditRawClicked(GtkButton *widget, gpointer userData) { ProjectDataT *self = (ProjectDataT *)userData; - char *pathTemp = NULL; char *filename = NULL; - int i; + GtkWidget *lblRaw = utilFindChildWidget(self->tempWidget, "lblRaw"); (void)widget; - pathTemp = strdup(self->windowData.filename); - cwk_path_get_dirname(pathTemp, (size_t *)&i); //***TODO*** Self is getting clobbered here. WTF? - if (i > 0) pathTemp[i] = 0; + gtk_dialog_response(GTK_DIALOG(self->tempWidget), GTK_RESPONSE_CANCEL); //***TODO*** Be sure this is something we can edit as text. - filename = utilCreateString("%s%s", pathTemp, self->tempString); + filename = utilCreateString("%s%s", self->windowData.path, gtk_label_get_text(GTK_LABEL(lblRaw))); winEditorCreate(filename); DEL(filename); } EVENT void btnEditRecipeClicked(GtkButton *widget, gpointer userData) { - ProjectDataT *self = (ProjectDataT *)userData; - char *file = NULL; + ProjectDataT *self = (ProjectDataT *)userData; + char *file = NULL; + GtkWidget *fileRecipe = utilFindChildWidget(self->tempWidget, "fileRecipe"); (void)widget; - file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(self->tempWidget)); + gtk_dialog_response(GTK_DIALOG(self->tempWidget), GTK_RESPONSE_CANCEL); + + file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileRecipe)); if (utilFileExists(file)) { winEditorCreate(file); } @@ -201,35 +200,27 @@ EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData) { char *newFile = NULL; char *fromTemp = NULL; char *toTemp = NULL; - char *pathTemp = NULL; - int i; (void)widget; if (utilFileSaveOtherAs((WindowDataT *)userData, "*.c", "Recipe", &newFile)) { - pathTemp = strdup(self->windowData.filename); - cwk_path_get_dirname(pathTemp, (size_t *)&i); - if (i > 0) pathTemp[i] = 0; - fromTemp = utilCreateString("%s%s", __resourcePath, "recipe.c"); utilFileCopy(fromTemp, newFile); DEL(fromTemp); fromTemp = utilCreateString("%s%s", __resourcePath, "gitignore"); - toTemp = utilCreateString("%s%s", pathTemp, ".gitignore"); + toTemp = utilCreateString("%s%s", self->windowData.path, ".gitignore"); utilFileCopy(fromTemp, toTemp); DEL(toTemp); DEL(fromTemp); fromTemp = utilCreateString("%s%s", __resourcePath, "gitattributes"); - toTemp = utilCreateString("%s%s", pathTemp, ".gitattributes"); + toTemp = utilCreateString("%s%s", self->windowData.path, ".gitattributes"); utilFileCopy(fromTemp, toTemp); DEL(toTemp); DEL(fromTemp); - DEL(pathTemp); - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(self->tempWidget), newFile); } } @@ -255,10 +246,8 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) { GtkWidget *btnOkay; int original; int result; - int i; char *raw = NULL; char *temp = NULL; - char *path = NULL; char *widgetNames[] = { "dialogCookSettings", "lblRaw", @@ -282,13 +271,7 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) { raw = utilFileBasename(filename); gtk_label_set_text(GTK_LABEL(lblRaw), raw); - self->tempWidget = fileRecipe; - self->tempString = strdup(raw); - - // Find path of project file. - path = strdup(self->windowData.filename); - cwk_path_get_dirname(path, (size_t *)&i); - if (i > 0) path[i] = 0; + self->tempWidget = dialogCookSettings; original = findRecipeData(self, raw); if (original >= 0) { @@ -301,7 +284,7 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) { temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileRecipe)); if (temp != NULL) { // Convert to relative path. - cwk_path_get_relative(path, temp, __utilFilenameBuffer, sizeof(__utilFilenameBuffer)); + cwk_path_get_relative(self->windowData.path, temp, __utilFilenameBuffer, sizeof(__utilFilenameBuffer)); if (__utilFilenameBuffer[0] != 0) { DEL(temp); temp = strdup(__utilFilenameBuffer); @@ -315,11 +298,9 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) { } } - DEL(path); DEL(raw); self->tempWidget = NULL; - DEL(self->tempString); gtk_widget_destroy(dialogCookSettings); } @@ -416,7 +397,6 @@ static void loadProject(ProjectDataT *self) { TargetT *t = NULL; int i; int j; - char *path = NULL; char *raw = NULL; in = fopen(self->windowData.filename, "rt"); @@ -427,10 +407,6 @@ static void loadProject(ProjectDataT *self) { self->targets[i]->archs[j]->selected = FALSE; } } - // Find path of project file. - path = strdup(self->windowData.filename); - cwk_path_get_dirname(path, (size_t *)&i); - if (i > 0) path[i] = 0; // Load project. utilEnsureBufferSize((unsigned char **)&line, (int *)&len, 1024); // Not technically needed, but fixes a pointer warning from memmaker. while (getline(&line, &len, in) != -1) { @@ -442,7 +418,7 @@ static void loadProject(ProjectDataT *self) { if (strcasecmp(c, "source") == 0) { c = utilGetToken(NULL, " ", "\"", "\""); utilDequote(c); - cwk_path_get_relative(path, c, __utilFilenameBuffer, sizeof(__utilFilenameBuffer)); + cwk_path_get_relative(self->windowData.path, c, __utilFilenameBuffer, sizeof(__utilFilenameBuffer)); if (__utilFilenameBuffer[0] == 0) { projectAddToTree(self, c); } else { @@ -485,7 +461,7 @@ static void loadProject(ProjectDataT *self) { raw = strdup(c); c = utilGetToken(NULL, " ", "\"", "\""); utilDequote(c); - cwk_path_get_relative(path, c, __utilFilenameBuffer, sizeof(__utilFilenameBuffer)); + cwk_path_get_relative(self->windowData.path, c, __utilFilenameBuffer, sizeof(__utilFilenameBuffer)); if (__utilFilenameBuffer[0] == 0) { addToRecipeData(self, raw, c); } else { @@ -497,7 +473,6 @@ static void loadProject(ProjectDataT *self) { } fclose(in); DEL(line); - DEL(path); utilSetDirty((WindowDataT *)self, FALSE); // Do again - loading text marks us dirty. } else { //***TODO*** Something bad happened. @@ -543,6 +518,7 @@ EVENT void menuProjectFileNew(GtkWidget *object, gpointer userData) { // Nuke filename & mark clean. DEL(self->windowData.filename); + DEL(self->windowData.path); utilSetDirty(&self->windowData, FALSE); } @@ -650,8 +626,6 @@ EVENT void menuProjectProjectAdd(GtkWidget *object, gpointer userData) { GtkFileFilter *filter; ProjectSectionTypeT section; char *temp = NULL; - char *path = NULL; - int x; (void)object; @@ -664,10 +638,7 @@ EVENT void menuProjectProjectAdd(GtkWidget *object, gpointer userData) { ); if (self->windowData.filename != NULL) { - path = strdup(self->windowData.filename); - cwk_path_get_dirname(path, (size_t *)&x); - if (x > 0) path[x] = 0; - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),path); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),self->windowData.path); } for (section=0; sectionwindowData.path != NULL) { + cwk_path_get_relative(self->windowData.path,temp, __utilFilenameBuffer, sizeof(__utilFilenameBuffer)); DEL(temp); temp = strdup(__utilFilenameBuffer); } @@ -935,7 +906,6 @@ EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData) { int i; char *raw; char *recipe; - char *path; int result; // Only one cook at a time. Should not be able to happen. @@ -947,11 +917,6 @@ EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData) { // Remember who started the cook. _cookingProjectData = self; - // Find path of project file. - path = strdup(self->windowData.filename); - cwk_path_get_dirname(path, (size_t *)&i); - if (i > 0) path[i] = 0; - for (i=0; irecipes); i++) { // Build pathnames. cwk_path_change_basename(self->windowData.filename, self->recipes[i]->key, __utilFilenameBuffer, sizeof(__utilFilenameBuffer)); @@ -961,7 +926,7 @@ EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData) { // Run it! message(MSG_INFO, "Cooking %s", self->recipes[i]->key); - result = compilerRunRecipe(recipe, raw, path, self); + result = compilerRunRecipe(recipe, raw, self->windowData.path, self); if (result != 0) { //***TODO*** Not all negative returns are severe. message(result > 0 ? MSG_ERROR : MSG_SEVERE, "Recipe %s returned %d", self->recipes[i]->value, result); @@ -969,7 +934,6 @@ EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData) { message(MSG_INFO, "Finished Cooking"); } - DEL(path); _cookingProjectData = NULL; } @@ -1070,10 +1034,8 @@ EVENT void treeProjectRowActivated(GtkTreeView *treeView, GtkTreePath *path, Gtk GtkTreeIter iter; char *name = NULL; char *pathString = NULL; - char *pathTemp = NULL; char *filename = NULL; int section; - int i; pathString = gtk_tree_path_to_string(path); if (strstr(pathString, ":") != NULL) { @@ -1084,15 +1046,10 @@ EVENT void treeProjectRowActivated(GtkTreeView *treeView, GtkTreePath *path, Gtk debug("Double click! [%d] [%s] [%s]\n", section, pathString, name); if (section == SECTION_CODE || section == SECTION_HEADER) { - //***TODO*** We find our path way too often. Do it once and keep it. - pathTemp = strdup(self->windowData.filename); - cwk_path_get_dirname(pathTemp, (size_t *)&i); - if (i > 0) pathTemp[i] = 0; - filename = utilCreateString("%s%s", pathTemp, name); + filename = utilCreateString("%s%s", self->windowData.path, name); // Launch code editor. winEditorCreate(filename); DEL(filename); - DEL(pathTemp); } if (section == SECTION_RAW_DATA) { @@ -1323,6 +1280,7 @@ void winProjectCreate(void) { //***DEBUG*** self->windowData.filename = strdup("/home/scott/joeyapps/warehouse/Warehouse.joe"); + self->windowData.path = strdup("/home/scott/joeyapps/warehouse/"); loadProject(self); } diff --git a/src/utils.c b/src/utils.c index afc112c..15a94a7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -253,7 +253,9 @@ gboolean utilFileOpen(WindowDataT *self, char *extension, char *what) { if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { utilSetDirty((WindowDataT *)self, FALSE); DEL(self->filename); + DEL(self->path); self->filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + utilUpdatePath(self); } else { result = FALSE; } @@ -270,7 +272,7 @@ gboolean utilFileOpen(WindowDataT *self, char *extension, char *what) { char *utilFileRemoveExtension(char *filename) { - int x = strlen(filename) - 1; + int x = (int)strlen(filename) - 1; char c = 0; char *newString = NULL; @@ -293,7 +295,12 @@ char *utilFileRemoveExtension(char *filename) { gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what) { - return utilFileSaveOtherAs(self, extension, what, &self->filename); + gboolean result; + + result = utilFileSaveOtherAs(self, extension, what, &self->filename); + utilUpdatePath(self); + + return result; } @@ -339,6 +346,36 @@ gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, cha } +GtkWidget *utilFindChildWidget(GtkWidget *parent, const gchar *name) { + GList *children = NULL; + GtkWidget *widget = NULL; + + // This works on widgets with names. If a widget is referenced by + // utilGetWidgetsFromMemory, the name will be set to the ID of the + // widget. If not, you need to assign a name yourself. + + if (g_strcmp0(gtk_widget_get_name(parent), name) == 0) { + return parent; + } + + if (GTK_IS_CONTAINER(parent)) { + children = gtk_container_get_children(GTK_CONTAINER(parent)); + } + + while (children != NULL) { + widget = utilFindChildWidget(children->data, name); + + if (widget != NULL) { + return widget; + } + + children = children->next; + } + + return NULL; +} + + // https://stackoverflow.com/questions/26187037/in-c-split-char-on-spaces-with-strtok-function-except-if-between-quotes char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock) { static char *token = NULL; @@ -403,6 +440,8 @@ gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widg x = 0; while (name[x] != NULL) { *widgets[x] = GTK_WIDGET(gtk_builder_get_object(gtkBuilder, name[x])); + // Set the widget name property to the ID we used to find it. + gtk_widget_set_name(*widgets[x], name[x]); x++; } @@ -542,6 +581,20 @@ void utilSetDirty(WindowDataT *self, gboolean dirty) { } +void utilUpdatePath(WindowDataT *self) { + int i; + + if (self->filename) { + // Derive the path from the filename. + self->path = strdup(self->filename); + cwk_path_get_dirname(self->path, (size_t *)&i); + if (i > 0) self->path[i] = 0; + } else { + DEL(self->path); + } +} + + void utilWindowRegister(gpointer windowData) { WindowDataT *w = (WindowDataT *)windowData; diff --git a/src/vector.c b/src/vector.c index 7f2e645..28299f2 100644 --- a/src/vector.c +++ b/src/vector.c @@ -735,6 +735,7 @@ EVENT void menuVectorFileNew(GtkWidget *object, gpointer userData) { // Clear any filename. DEL(self->windowData.filename); + DEL(self->windowData.path); // Refresh widget. gtk_widget_queue_draw(self->drawVectorImage); @@ -1529,6 +1530,7 @@ void winVectorCreate(char *filename) { if (filename != NULL) { self->windowData.filename = strdup(filename); + utilUpdatePath((WindowDataT *)self); loadVectorImage(self); } } diff --git a/ui/Cook.glade b/ui/Cook.glade index d5b31a6..7638cf7 100644 --- a/ui/Cook.glade +++ b/ui/Cook.glade @@ -15,6 +15,9 @@ False + 10 + 10 + 10 vertical 2