59#include <glib/gstdio.h>
64#define GEANY_BUILD_ERR_HIGHLIGHT_MAX 50
110#define GBO_TO_GBG(gbo) \
111 ((gbo) > GEANY_GBO_EXEC ? GEANY_GBG_COUNT : \
112 ((gbo) >= GEANY_GBO_EXEC ? GEANY_GBG_EXEC : \
113 ((gbo) >= GEANY_GBO_MAKE_ALL ? GEANY_GBG_NON_FT : GEANY_GBG_FT)))
126#define GBO_TO_CMD(gbo) \
127 ((gbo) >= GEANY_GBO_COUNT ? (gbo) - GEANY_GBO_COUNT : \
128 ((gbo) >= GEANY_GBO_EXEC ? (gbo) - GEANY_GBO_EXEC : \
129 ((gbo) >= GEANY_GBO_MAKE_ALL ? \
130 (gbo) - GEANY_GBO_MAKE_ALL : (gbo))))
133#define GRP_CMD_TO_POINTER(grp, cmd) GUINT_TO_POINTER((((grp)&7) << 5) | ((cmd)&0x1f))
134#define GBO_TO_POINTER(gbo) (GRP_CMD_TO_POINTER(GBO_TO_GBG(gbo), GBO_TO_CMD(gbo)))
135#define GPOINTER_TO_CMD(gptr) (GPOINTER_TO_UINT(gptr)&0x1f)
136#define GPOINTER_TO_GRP(gptr) ((GPOINTER_TO_UINT(gptr)&0xe0) >> 5)
160static void build_exit_cb(GPid pid, gint status, gpointer user_data);
161static void build_iofunc(GString *
string, GIOCondition condition, gpointer data);
167static void run_exit_cb(GPid child_pid, gint status, gpointer user_data);
189 GtkAccelGroup *accel_group, GtkWidget *menuitem)
194 gtk_widget_add_accelerator(menuitem,
"activate", accel_group,
195 kb->
key, kb->
mods, GTK_ACCEL_VISIBLE);
209 return bc->working_dir;
216static void set_command(GeanyBuildCommand *bc, gint
id, gchar *str)
227 SETPTR(bc->working_dir, str);
261#ifndef PRINTBUILDCMDS
262#define PRINTBUILDCMDS FALSE
290 printf(
"filetype %s\n",ft->
name);
305 if (cl[j][i] !=
NULL && *(cl[j][i]) !=
NULL && (*(cl[j][i]))[k].exists)
310 (l = strlen((*(cl[j][i]))[k].
entries[n])) > m)
323 for (l = 0; l < 2; ++l)
328 if (cl[i][j] !=
NULL && *(cl[i][j]) !=
NULL && (*(cl[i][j]))[k].exists)
333 printf(
"%c %*.*s",c,cc[j],cc[j],(*(cl[i][j]))[k].
entries[i]);
335 printf(
"%c %*.*s",c,cc[j],cc[j],
" ");
339 printf(
"%c %*.*s",c,cc[j],cc[j],
" ");
352#define return_cmd_if(src, cmds)\
353 if (cmds != NULL && cmds[cmdindex].exists && below>src)\
356 if (printbuildcmds) \
357 printf("cmd[%u,%u]=%u\n",cmdgrp,cmdindex,src); \
358 return &(cmds[cmdindex]); \
361#define return_ft_cmd_if(src, cmds)\
362 if (ft != NULL && ft->priv->cmds != NULL \
363 && ft->priv->cmds[cmdindex].exists && below>src)\
366 if (printbuildcmds) \
367 printf("cmd[%u,%u]=%u\n",cmdgrp,cmdindex,src); \
368 return &(ft->priv->cmds[cmdindex]); \
374 guint below, guint *from)
378 guint sink, *fr = &sink;
432#define return_nonblank_regex(src, ptr)\
434 { *fr = (src); return &(ptr); }
440 guint sink, *fr = &sink;
486 default:
return NULL;
495 default:
return NULL;
509 default:
return NULL;
548 GeanyBuildCommand *bc;
557 bc[i].exists = FALSE;
560 bc[cmd].exists = FALSE;
580 GeanyBuildCommand *bc;
610 GeanyBuildCommand *c;
628 str = c->working_dir;
651 GeanyBuildCommand **g;
659 if (g ==
NULL)
return;
668 (*g)[cmd].exists = TRUE;
672 (*g)[cmd].exists = TRUE;
676 (*g)[cmd].exists = TRUE;
717 gchar *executable =
NULL;
722 stack = g_string_new(src);
726 replacement = g_path_get_basename(doc->
file_name);
731 replacement = g_path_get_dirname(doc->
file_name);
737 replacement = g_path_get_basename(executable);
743 replacement = g_strdup_printf(
"%i", line_num);
754 else if (
strstr(stack->str,
"%p"))
758 replacement = g_path_get_dirname(doc->
file_name);
765 return g_string_free(stack, FALSE);
774 gchar *argv[] = {
"/bin/sh",
"-c",
NULL,
NULL };
776 gchar *utf8_working_dir;
783 geany_debug(
"Failed to run command with no working directory");
791 utf8_working_dir = !
EMPTY(dir) ? g_strdup(dir) : g_path_get_dirname(doc->
file_name);
794 gtk_list_store_clear(
msgwindow.store_compiler);
797 g_free(utf8_working_dir);
801 argv[2] = cmd_string;
805 cmd_string = win32_expand_environment_variables(cmd);
837 GeanyBuildCommand *cmd =
NULL;
838 const gchar *cmd_working_dir;
839 gboolean autoclose = FALSE;
840 gchar *cmd_string_utf8, *working_dir_utf8, *run_cmd, *cmd_string;
846 cmd_working_dir = cmd->working_dir;
847 if (
EMPTY(cmd_working_dir))
848 cmd_working_dir =
"%d";
856 !
EMPTY(working_dir_utf8) ? working_dir_utf8 :
"<NULL>" );
864 if (vte_info.have_vte && vc->run_in_vte)
866 if (vc->skip_run_script)
879 SETPTR(cmd_string, win32_expand_environment_variables(cmd_string));
885 run_cmd = g_strdup_printf(
"\"%s\" \"%s\" %d %s", helper, *
working_dir, autoclose ? 1 : 0, cmd_string);
891 ui_set_statusbar(TRUE,
_(
"Failed to execute \"%s\" (start-script could not be created: %s)"),
892 !
EMPTY(cmd_string_utf8) ? cmd_string_utf8 :
NULL,
error->message);
905 gchar *run_cmd =
NULL;
917 if (vte_info.have_vte && vc->run_in_vte)
925 if (vc->skip_run_script)
926 vte_cmd = g_strconcat(run_cmd,
"\n",
NULL);
928 vte_cmd = g_strconcat(
"\n/bin/sh ", run_cmd,
"\n",
NULL);
931 if (! vte_send_cmd(vte_cmd))
933 const gchar *msg =
_(
"File not executed because the terminal may contain some input (press Ctrl+C or Enter to clear it).");
936 if (!vc->skip_run_script)
942 gtk_widget_grab_focus(vc->vte);
955 if (g_regex_match_simple(
"^[ \"]*cmd([.]exe)?[\" ]", locale_term_cmd, 0, 0))
958 GString *escaped_run_cmd = g_string_new(
NULL);
959 for (gchar *p = run_cmd; *p; p++)
961 if (strchr(
"()%!^\"<>&| ", *p))
962 g_string_append_c(escaped_run_cmd,
'^');
963 g_string_append_c(escaped_run_cmd, *p);
965 SETPTR(run_cmd, g_string_free(escaped_run_cmd, FALSE));
982 "Check the Terminal setting in Preferences"), utf8_term_cmd,
error->message);
983 g_free(utf8_term_cmd);
1031 gtk_widget_set_sensitive(
build_get_menu_items(-1)->menu_item[GBG_FIXED][GBF_NEXT_ERROR], TRUE);
1032 gtk_widget_set_sensitive(
build_get_menu_items(-1)->menu_item[GBG_FIXED][GBF_PREV_ERROR], TRUE);
1041static void build_iofunc(GString *
string, GIOCondition condition, gpointer data)
1043 if (condition & (G_IO_IN | G_IO_PRI))
1071 input = g_strdup(
pos);
1074 len = strlen(input);
1075 input[len - 1] =
'\0';
1076 input = g_realloc(input, len);
1082 if (
strstr(
string,
"Leaving directory") !=
NULL)
1098 msg =
_(
"Compilation failed.");
1112 msg =
_(
"Compilation finished successfully.");
1114 if (!
ui_prefs.msgwindow_visible ||
1133static void run_exit_cb(GPid child_pid, gint status, gpointer user_data)
1135 RunInfo *run_info_data = user_data;
1137 g_spawn_close_pid(child_pid);
1139 run_info_data->
pid = 0;
1153 gboolean success = TRUE;
1161 str = g_strdup_printf(
1162 "#!/bin/sh\n\nrm $0\n\ncd %s\n\n%s\n\necho \"\n\n------------------\n(program exited with code: $?)\" \
1163 \n\n%s\n", escaped_dir, cmd, (autoclose) ?
"" :
1164 "\necho \"Press return to continue\"\n#to be more compatible with shells like "
1165 "dash\ndummy_var=\"\"\nread dummy_var");
1166 g_free(escaped_dir);
1168 if (!g_file_set_contents(fname, str, -1,
error))
1172 if (success && g_chmod(fname, 0777) != 0)
1178 g_set_error(
error, G_FILE_ERROR, g_file_error_from_errno(errsv),
1179 "Failed to make file executable: %s", g_strerror(errsv));
1203 gchar *full_command, *subs_command;
1207 if (buildcmd ==
NULL)
1210 cmdstr = buildcmd->command;
1212 if (cmd_cat !=
NULL)
1215 full_command = g_strconcat(cmdstr, cmd_cat,
NULL);
1217 full_command = g_strdup(cmd_cat);
1220 full_command = cmdstr;
1227 g_free(subs_command);
1229 if (cmd_cat !=
NULL)
1230 g_free(full_command);
1255 GeanyBuildCommand *bc;
1273 _(
"Enter custom text here, all entered text is appended to the command."),
1290 if (bc !=
NULL && strcmp(bc->command,
"builtin") == 0)
1292 const gchar *uri_file_prefix;
1313#define MENU_FT_REST (GEANY_GBG_COUNT + GEANY_GBG_FT)
1314#define MENU_NON_FT_REST (GEANY_GBG_COUNT + GEANY_GBG_NON_FT)
1315#define MENU_EXEC_REST (GEANY_GBG_COUNT + GEANY_GBG_EXEC)
1317#define MENU_SEPARATOR (2*GEANY_GBG_COUNT)
1319#define MENU_NEXT_ERROR (MENU_SEPARATOR + 1)
1320#define MENU_PREV_ERROR (MENU_NEXT_ERROR + 1)
1321#define MENU_COMMANDS (MENU_PREV_ERROR + 1)
1322#define MENU_DONE (MENU_COMMANDS + 1)
1373 GtkWidget *item = gtk_image_menu_item_new_with_mnemonic(lbl);
1377 GtkWidget *image = gtk_image_new_from_stock(bs->
stock_id, GTK_ICON_SIZE_MENU);
1378 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
1380 gtk_widget_show(item);
1395 GtkAccelGroup *accel_group = gtk_accel_group_new();
1399 menu = gtk_menu_new();
1403 build_menu_items->menu_item[GBG_FIXED] = g_new0(GtkWidget*, GBF_COUNT);
1410 GtkWidget *item = gtk_separator_menu_item_new();
1411 gtk_widget_show(item);
1413 build_menu_items->menu_item[GBG_FIXED][bs->
build_cmd] = item;
1426 const gchar *lbl = (bc ==
NULL) ?
"" : bc->label;
1433 const gchar *lbl = (bc ==
NULL) ?
"" : bc->label;
1437 build_menu_items->menu = menu;
1438 gtk_widget_show(menu);
1459 guint i, cmdcount, cmd, grp;
1460 gboolean vis = FALSE;
1461 gboolean have_path, build_running, exec_running, have_errors, cmd_sensitivity;
1462 gboolean can_compile, can_build, can_make, run_sensitivity = FALSE, run_running = FALSE;
1463 GeanyBuildCommand *bc;
1474 have_errors =
build_info.message_count > 0 &&
1475 gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
msgwindow.store_compiler),
NULL) > 0;
1509 for (cmd = bs->
build_cmd; cmd < cmdcount; ++cmd)
1511 GtkWidget *menu_item =
menu_items.menu_item[grp][cmd];
1524 gtk_widget_set_sensitive(menu_item, cmd_sensitivity);
1527 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_item),
label);
1532 gtk_widget_hide(menu_item);
1538 cmd_sensitivity = (bc !=
NULL) || exec_running;
1539 gtk_widget_set_sensitive(menu_item, cmd_sensitivity);
1541 run_sensitivity = cmd_sensitivity;
1544 image = gtk_image_new_from_stock(bs->
stock_id, GTK_ICON_SIZE_MENU);
1548 image = gtk_image_new_from_stock(GTK_STOCK_STOP, GTK_ICON_SIZE_MENU);
1551 run_running = exec_running;
1552 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
1555 gtk_menu_item_set_label(GTK_MENU_ITEM(menu_item),
label);
1560 gtk_widget_hide(menu_item);
1566 run_sensitivity &= (doc !=
NULL);
1568 && have_path && ! build_running;
1570 gtk_widget_set_sensitive(
widgets.toolitem_build, can_build);
1573 gtk_widget_set_sensitive(
widgets.toolitem_make_all,
1575 && ! build_running));
1577 gtk_widget_set_sensitive(
widgets.toolitem_make_custom,
1579 && ! build_running));
1581 gtk_widget_set_sensitive(
widgets.toolitem_make_object,
1583 && ! build_running));
1585 gtk_widget_set_sensitive(
widgets.toolitem_set_args, TRUE);
1588 && have_path && ! build_running;
1589 gtk_action_set_sensitive(
widgets.compile_action, can_compile);
1590 gtk_action_set_sensitive(
widgets.build_action, can_make);
1591 gtk_action_set_sensitive(
widgets.run_action, run_sensitivity);
1602 const gchar *button_stock_id =
NULL;
1603 GtkToolButton *run_button;
1606 if (run_button !=
NULL)
1607 button_stock_id = gtk_tool_button_get_stock_id(run_button);
1617 if (run_button !=
NULL)
1618 gtk_tool_button_set_stock_id(run_button, GTK_STOCK_STOP);
1622 if (run_button !=
NULL)
1623 gtk_tool_button_set_stock_id(run_button, GTK_STOCK_EXECUTE);
1641 g_object_set(
widgets.build_action,
"tooltip",
_(
"Build the current file"),
NULL);
1652 msg =
_(
"Build the current file with Make and the default target");
1654 msg =
_(
"Build the current file with Make and the specified target");
1656 msg =
_(
"Compile the current file with Make");
1659 g_object_set(
widgets.build_action,
"tooltip", msg,
NULL);
1676 g_error_free(
error);
1747 gtk_widget_override_color(r->
entries[i], GTK_STATE_FLAG_NORMAL,
color);
1754 if (GTK_IS_BUTTON(wid))
1755 gtk_button_set_label(GTK_BUTTON(wid),
text);
1757 gtk_entry_set_text(GTK_ENTRY(wid),
text);
1794 gtk_entry_set_text(regex,
"");
1801 GtkWidget *top_level = gtk_widget_get_toplevel(wid);
1802 const gchar *old = gtk_button_get_label(GTK_BUTTON(wid));
1805 if (gtk_widget_is_toplevel(top_level) && GTK_IS_WINDOW(top_level))
1813 gtk_button_set_label(GTK_BUTTON(wid), str);
1835 N_(
"Working directory"),
1855 GeanyBuildCommand *bc;
1860 GtkStyleContext *ctx;
1864 text = g_strdup_printf(
"%d.", cmd + 1);
1868 ctx = gtk_widget_get_style_context(
label);
1869 gtk_style_context_save(ctx);
1870 gtk_style_context_get_color(ctx, GTK_STATE_FLAG_INSENSITIVE, &
insensitive_color);
1871 gtk_style_context_restore(ctx);
1873 gtk_table_attach(table,
label, column, column + 1, row, row + 1, GTK_FILL,
1887 GtkWidget *wid = roww->
entries[i] = gtk_button_new();
1888 gtk_button_set_use_underline(GTK_BUTTON(wid), TRUE);
1889 gtk_widget_set_tooltip_text(wid,
_(
"Click to set menu item label"));
1894 roww->
entries[i] = gtk_entry_new();
1897 gtk_table_attach(table, roww->
entries[i], column, column + 1, row, row + 1, xflags,
1901 clearicon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
1902 clear = gtk_button_new();
1903 gtk_button_set_image(GTK_BUTTON(
clear), clearicon);
1905 gtk_table_attach(table,
clear, column, column + 1, row, row + 1, GTK_FILL,
1913 const gchar *str =
"";
1919 else if (dst == src)
1924 if (bc !=
NULL && (dst > src))
1929 gtk_widget_set_sensitive(roww->
entries[i], FALSE);
1930 gtk_widget_set_sensitive(
clear, FALSE);
1954 guint col, row, cmdindex;
1957 gboolean sensitivity;
1965 label = gtk_label_new(
_(*ch));
1966 gtk_table_attach(table,
label, col, col + 1, 0, 1,
1969 sep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
1970 gtk_table_attach(table, sep, 0,
DC_N_COL, 1, 2, GTK_FILL, GTK_FILL | GTK_EXPAND,
1973 txt = g_strdup_printf(
_(
"%s commands"), ft->
name);
1975 txt = g_strdup_printf(
_(
"%s commands"),
_(
"No filetype"));
1979 gtk_misc_set_alignment(GTK_MISC(
label), 0.0, 0.5);
1980 gtk_table_attach(table,
label, 0,
DC_N_COL, 2, 3, GTK_FILL, GTK_FILL | GTK_EXPAND,
1984 label = gtk_label_new(
_(
"Error regular expression:"));
1985 gtk_table_attach(table,
label, 0,
DC_ENTRIES + 1, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND,
1989 sensitivity = (ft ==
NULL) ? FALSE : TRUE;
1994 sensitivity = FALSE;
1998 clearicon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
1999 clear = gtk_button_new();
2000 gtk_button_set_image(GTK_BUTTON(
clear), clearicon);
2001 g_signal_connect_swapped(
clear,
"clicked",
2005 gtk_widget_set_sensitive(fields->
fileregex, sensitivity);
2006 gtk_widget_set_sensitive(
clear, sensitivity);
2008 sep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
2009 gtk_table_attach(table, sep, 0,
DC_N_COL, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND,
2013 gtk_misc_set_alignment(GTK_MISC(
label), 0.0, 0.5);
2014 gtk_table_attach(table,
label, 0,
DC_N_COL, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND,
2019 label = gtk_label_new(
_(
"Error regular expression:"));
2020 gtk_table_attach(table,
label, 0,
DC_ENTRIES + 1, row, row + 1, GTK_FILL,
2028 sensitivity = src > dst ? FALSE : TRUE;
2032 clearicon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
2033 clear = gtk_button_new();
2034 gtk_button_set_image(GTK_BUTTON(
clear), clearicon);
2035 g_signal_connect_swapped(
clear,
"clicked",
2039 gtk_widget_set_sensitive(fields->
nonfileregex, sensitivity);
2040 gtk_widget_set_sensitive(
clear, sensitivity);
2044 _(
"Note: Item 2 opens a dialog and appends the response to the command."));
2045 gtk_misc_set_alignment(GTK_MISC(
label), 0.0, 0.5);
2046 gtk_table_attach(table,
label, 0,
DC_N_COL, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND,
2049 sep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
2050 gtk_table_attach(table, sep, 0,
DC_N_COL, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND,
2054 gtk_misc_set_alignment(GTK_MISC(
label), 0.0, 0.5);
2055 gtk_table_attach(table,
label, 0,
DC_N_COL, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND,
2059 sep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
2060 gtk_table_attach(table, sep, 0,
DC_N_COL, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND,
2065 _(
"%d, %e, %f, %p, %l are substituted in command and directory fields, see manual for details."));
2066 gtk_misc_set_alignment(GTK_MISC(
label), 0.0, 0.5);
2067 gtk_table_attach(table,
label, 0,
DC_N_COL, row, row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND,
2071 *table_data = fields;
2072 return GTK_WIDGET(table);
2081 g_free(table_data->rows[cmdindex]);
2082 g_free(table_data->rows);
2089static gint stcmp(
const gchar *a,
const gchar *b)
2097 return strcmp(a, b);
2104 if (GTK_IS_BUTTON(wid))
2105 return gtk_button_get_label(GTK_BUTTON(wid));
2107 return gtk_entry_get_text(GTK_ENTRY(wid));
2111static gboolean
read_row(BuildDestination *dst, BuildTableData table_data, guint drow, guint grp, guint cmd)
2114 gboolean changed = FALSE;
2121 if (table_data->rows[drow]->cleared)
2123 if (dst->dst[grp] !=
NULL)
2125 if (*(dst->dst[grp]) ==
NULL)
2127 (*(dst->dst[grp]))[cmd].exists = FALSE;
2128 (*(dst->dst[grp]))[cmd].changed = TRUE;
2132 if (table_data->rows[drow]->used_dst == TRUE)
2134 if (dst->dst[grp] !=
NULL)
2136 if (*(dst->dst[grp]) ==
NULL)
2140 (*(dst->dst[grp]))[cmd].exists = TRUE;
2141 (*(dst->dst[grp]))[cmd].changed = TRUE;
2154static gboolean
read_regex(GtkWidget *regexentry, gchar **src, gchar **dst)
2156 gboolean changed = FALSE;
2157 const gchar *reg = gtk_entry_get_text(GTK_ENTRY(regexentry));
2164 || strcmp(*src, reg) != 0)))
2168 SETPTR(*dst, g_strdup(reg));
2178 guint cmdindex, cmd;
2179 gboolean changed = FALSE;
2181 if (response == GTK_RESPONSE_ACCEPT)
2189 changed |=
read_regex(table_data->fileregex, table_data->fileregexstring, dst->fileregexstr);
2190 changed |=
read_regex(table_data->nonfileregex, table_data->nonfileregexstring, dst->nonfileregexstr);
2198 BuildDestination menu_dst;
2208 menu_dst.fileregexstr =
NULL;
2220 GtkWidget *
dialog, *table, *vbox;
2223 const gchar *title =
_(
"Set Build Commands");
2225 BuildTableData table_data;
2226 BuildDestination prefdsts;
2231 GTK_DIALOG_DESTROY_WITH_PARENT,
2232 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2233 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
2236 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
2239 response = gtk_dialog_run(GTK_DIALOG(
dialog));
2251 prefdsts.fileregexstr =
NULL;
2260 gtk_widget_destroy(
dialog);
2267 BuildMenuItems *items;
2270 if (items->menu ==
NULL)
2290#define set_key_grp(key, grp) (key[prefixlen + 0] = grp[0], key[prefixlen + 1] = grp[1])
2291#define set_key_cmd(key, cmd) (key[prefixlen + 3] = cmd[0], key[prefixlen + 4] = cmd[1])
2292#define set_key_fld(key, fld) (key[prefixlen + 6] = fld[0], key[prefixlen + 7] = fld[1])
2295 gchar *prefix, gboolean loc)
2299 GeanyBuildCommand *dstcmd;
2301 static gchar cmdbuf[4] =
" ";
2306 prefixlen = prefix ==
NULL ? 0 : strlen(prefix);
2313 sprintf(cmdbuf,
"%02u", cmd);
2323 dstcmd[cmd].exists = TRUE;
2332 else dstcmd[cmd].exists = FALSE;
2340 const gchar *
label, gchar *value)
2361 gchar *value, *basedir, *makebasedir;
2362 gboolean bvalue = FALSE;
2406 for (ftname = ftlist; *ftname !=
NULL; ++ftname)
2411 gchar *regkey = g_strdup_printf(
"%serror_regex", *ftname);
2434 value = g_key_file_get_string(config,
"build_settings",
"compiler",
NULL);
2441 value = g_key_file_get_string(config,
"build_settings",
"linker",
NULL);
2448 value = g_key_file_get_string(config,
"build_settings",
"run_cmd",
NULL);
2462 if (basedir ==
NULL)
2463 basedir = g_strdup(
"%d");
2464 bvalue = g_key_file_get_boolean(config,
"project",
"make_in_base_path",
NULL);
2466 makebasedir = g_strdup(basedir);
2468 makebasedir = g_strdup(
"%d");
2475 value = g_key_file_get_string(config,
"project",
"run_cmd",
NULL);
2489 g_free(makebasedir);
2493 value = g_key_file_get_string(config,
"tools",
"make_cmd",
NULL);
2499 g_strdup_printf(
"%s ", value));
2501 g_strdup_printf(
"%s %%e.o",value));
2521 prefixlen = prefix ==
NULL ? 0 : strlen(prefix);
2525 if (src[cmd].exists) ++
count;
2526 if (src[cmd].changed)
2528 static gchar cmdbuf[4] =
" ";
2531 sprintf(cmdbuf,
"%02u", cmd);
2534 if (src[cmd].exists)
2560 gchar *regkey = g_strdup_printf(
"%serror_regex", ft->
name);
2612 GPtrArray *
ft_names = g_ptr_array_new();
2615 for (guint i = 0; i < build_fts->len; i++)
2617 ft = build_fts->pdata[i];
2640 g_return_if_fail(
count >= 0);
2718 gtk_widget_show(item);
2722 widgets.toolitem_build = item;
2724 item = gtk_separator_menu_item_new();
2725 gtk_widget_show(item);
2729 item = gtk_image_menu_item_new_with_mnemonic(
_(
"_Make All"));
2730 gtk_widget_show(item);
2734 widgets.toolitem_make_all = item;
2737 item = gtk_image_menu_item_new_with_mnemonic(
_(
"Make Custom _Target..."));
2738 gtk_widget_show(item);
2742 widgets.toolitem_make_custom = item;
2745 item = gtk_image_menu_item_new_with_mnemonic(
_(
"Make _Object"));
2746 gtk_widget_show(item);
2750 widgets.toolitem_make_object = item;
2752 item = gtk_separator_menu_item_new();
2753 gtk_widget_show(item);
2758 gtk_widget_show(item);
2761 widgets.toolitem_set_args = item;
2805 item =
menu_items->menu_item[GBG_FIXED][GBF_NEXT_ERROR];
2808 item =
menu_items->menu_item[GBG_FIXED][GBF_PREV_ERROR];
2814 item =
menu_items->menu_item[GBG_FIXED][GBF_COMMANDS];
2822 if (item && gtk_widget_is_sensitive(item))
2823 gtk_menu_item_activate(GTK_MENU_ITEM(item));
static gboolean read_regex(GtkWidget *regexentry, gchar **src, gchar **dst)
static BuildMenuItems menu_items
#define GEANY_BUILD_ERR_HIGHLIGHT_MAX
void build_free_fields(BuildTableData table_data)
static GeanyBuildCommand ** get_build_group_pointer(const GeanyBuildSource src, const GeanyBuildGroup grp)
static void on_build_menu_item(GtkWidget *w, gpointer user_data)
const gchar * build_get_current_menu_item(const GeanyBuildGroup grp, const guint cmd, const GeanyBuildCmdEntries fld)
Get the string for the menu item field.
static RunInfo * run_info
static void kill_process(GPid *pid)
void build_toolbutton_build_clicked(GtkAction *action, gpointer unused)
static guint build_save_menu_grp(GKeyFile *config, GeanyBuildCommand *src, gint grp, gchar *prefix)
GeanyBuildInfo build_info
static void on_clear_dialog_row(GtkWidget *unused, gpointer user_data)
#define GPOINTER_TO_CMD(gptr)
#define set_key_cmd(key, cmd)
#define GPOINTER_TO_GRP(gptr)
static void process_build_output_line(gchar *msg, gint color)
guint build_get_group_count(const GeanyBuildGroup grp)
Get the count of commands for the group.
GtkWidget * toolitem_set_args
gboolean build_parse_make_dir(const gchar *string, gchar **prefix)
static void set_command(GeanyBuildCommand *bc, gint id, gchar *str)
struct RowWidgets RowWidgets
static void on_label_button_clicked(GtkWidget *wid, gpointer user_data)
void build_save_menu(GKeyFile *config, gpointer ptr, GeanyBuildSource src)
static const gchar * build_grp_name
static void build_load_menu_grp(GKeyFile *config, GeanyBuildCommand **dst, gint grp, gchar *prefix, gboolean loc)
static GeanyBuildCommand * get_build_cmd(GeanyDocument *doc, guint grp, guint cmdindex, guint *from)
static GeanyBuildCommand * non_ft_def
static const gchar RUN_SCRIPT_CMD[]
static void create_build_menu_item(GtkWidget *menu, GeanyKeyGroup *group, GtkAccelGroup *ag, struct BuildMenuItemSpec *bs, const gchar *lbl, guint grp, guint cmd)
static void build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *dir)
static void build_run_cmd(GeanyDocument *doc, guint cmdindex)
static GeanyBuildCommand * get_next_build_cmd(GeanyDocument *doc, guint cmdgrp, guint cmdindex, guint below, guint *from)
static GeanyBuildCommand * exec_def
#define return_ft_cmd_if(src, cmds)
static void on_build_previous_error(GtkWidget *menuitem, gpointer user_data)
static const guint entry_x_padding
static void printfcmds(void)
static GeanyBuildCommand * get_build_group(const GeanyBuildSource src, const GeanyBuildGroup grp)
static const guint entry_y_padding
static const gchar * colheads[]
static void build_exit_cb(GPid pid, gint status, gpointer user_data)
static const gchar * fixedkey
static void set_build_command_entry_text(GtkWidget *wid, const gchar *text)
void build_activate_menu_item(const GeanyBuildGroup grp, const guint cmd)
Activate the menu item.
const gchar * working_dir
static void show_build_result_message(gboolean failure)
BuildMenuItems * build_get_menu_items(gint filetype_idx)
static void build_command(GeanyDocument *doc, GeanyBuildGroup grp, guint cmd, gchar *cmd_cat)
static gboolean save_project_filetype(GeanyFiletype *ft, GKeyFile *config)
static gchar * build_create_shellscript(const gchar *working_dir, const gchar *cmd, gboolean autoclose, GError **error)
static GeanyBuildCommand * exec_proj
static gpointer last_toolbutton_action
void Callback(GtkWidget *w, gpointer u)
static void clear_all_errors(void)
static RowWidgets * build_add_dialog_row(GeanyDocument *doc, GtkTable *table, guint row, GeanyBuildSource dst, guint grp, guint cmd, gboolean dir)
void build_menu_update(GeanyDocument *doc)
static void set_row_color(RowWidgets *r, GdkRGBA *color)
static gchar * build_replace_placeholder(const GeanyDocument *doc, const gchar *src)
void build_load_menu(GKeyFile *config, GeanyBuildSource src, gpointer p)
static void on_toolbutton_build_activate(GtkWidget *menuitem, gpointer user_data)
static gchar * current_dir_entered
static const gchar * get_build_command_entry_text(GtkWidget *wid)
static void on_set_build_commands_activate(GtkWidget *w, gpointer u)
GtkAction * compile_action
static void on_clear_dialog_regex_row(GtkEntry *regex, gpointer unused)
static void run_exit_cb(GPid child_pid, gint status, gpointer user_data)
GeanyBuildCommand * build_get_menu_item(GeanyBuildSource src, GeanyBuildGroup grp, guint cmd)
GtkWidget * toolitem_make_object
GtkWidget * toolitem_build
static struct @81 default_cmds[]
void build_finalize(void)
void build_set_group_count(GeanyBuildGroup grp, gint count)
struct BuildTableFields BuildTableFields
static gboolean build_read_commands(BuildDestination *dst, BuildTableData table_data, gint response)
static gchar * id_to_str(GeanyBuildCommand *bc, gint id)
void build_set_menu_item(const GeanyBuildSource src, const GeanyBuildGroup grp, const guint cmd, const GeanyBuildCmdEntries fld, const gchar *val)
Set the string for the menu item field.
static void show_build_commands_dialog(void)
static void assign_cmd(GeanyBuildCommand *type, guint id, const gchar *label, gchar *value)
static const gchar * groups[GEANY_GBG_COUNT]
GtkWidget * build_commands_table(GeanyDocument *doc, GeanyBuildSource dst, BuildTableData *table_data, GeanyFiletype *ft)
static void add_menu_accel(GeanyKeyGroup *group, guint kb_id, GtkAccelGroup *accel_group, GtkWidget *menuitem)
#define return_cmd_if(src, cmds)
static void on_toolbutton_make_activate(GtkWidget *menuitem, gpointer user_data)
#define GRP_CMD_TO_POINTER(grp, cmd)
#define set_key_fld(key, fld)
static void on_entry_focus(GtkWidget *wid, GdkEventFocus *unused, gpointer user_data)
static GeanyBuildCommand * exec_pref
static GdkRGBA insensitive_color
static const gchar * config_keys[GEANY_BC_CMDENTRIES_COUNT]
void build_read_project(GeanyFiletype *ft, BuildTableData build_properties)
static void set_stop_button(gboolean stop)
static struct @80 widgets
static void on_make_custom_input_response(const gchar *input, gpointer data)
static gchar * prepare_run_cmd(GeanyDocument *doc, gchar **working_dir, guint cmdindex)
static GeanyBuildCommand * non_ft_pref
gchar ** build_get_regex(GeanyBuildGroup grp, GeanyFiletype *ft, guint *from)
static guint build_items_count
static gchar * regex_pref
void build_remove_menu_item(const GeanyBuildSource src, const GeanyBuildGroup grp, const gint cmd)
Remove the specified Build menu item.
static struct BuildMenuItemSpec build_menu_specs[]
static gchar * regex_proj
static gboolean read_row(BuildDestination *dst, BuildTableData table_data, guint drow, guint grp, guint cmd)
GtkWidget * toolitem_make_custom
static GeanyBuildCommand * ft_def
static void on_build_next_error(GtkWidget *menuitem, gpointer user_data)
#define GBO_TO_POINTER(gbo)
static void create_build_menu(BuildMenuItems *build_menu_items)
#define return_nonblank_regex(src, ptr)
static void on_project_close(void)
GtkWidget * toolitem_make_all
gboolean build_keybinding(guint key_id)
static guint build_groups_count[GEANY_GBG_COUNT]
#define set_key_grp(key, grp)
static gboolean printbuildcmds
static GeanyBuildCommand * non_ft_proj
static void build_iofunc(GString *string, GIOCondition condition, gpointer data)
Interface to the Build menu functionality.
GeanyBuildGroup
Groups of Build menu items.
@ GEANY_GBG_NON_FT
non filetype items.
@ GEANY_GBG_FT
filetype items
@ GEANY_GBG_EXEC
execute items
@ GEANY_GBG_COUNT
count of groups.
GeanyBuildCmdEntries
The entries of a command for a menu item.
@ GEANY_BC_COMMAND
The command to run.
@ GEANY_BC_LABEL
The menu item label, _ marks mnemonic.
@ GEANY_BC_WORKING_DIR
The directory to run in.
@ GEANY_BC_CMDENTRIES_COUNT
Count of entries.
GeanyBuildSource
Build menu item sources in increasing priority.
@ GEANY_BCS_FT
System filetype values.
@ GEANY_BCS_HOME_FT
Filetypes in ~/.config/geany/filedefs.
@ GEANY_BCS_DEF
Default values.
@ GEANY_BCS_PREF
Preferences file ~/.config/geany/geany.conf.
@ GEANY_BCS_COUNT
Count of sources.
@ GEANY_BCS_PROJ_FT
Project file filetype command.
@ GEANY_BCS_PROJ
Project file if open.
GtkWidget * dialogs_show_input_persistent(const gchar *title, GtkWindow *parent, const gchar *label_text, const gchar *default_text, GeanyInputCallback input_cb, gpointer input_cb_data)
gchar * dialogs_show_input(const gchar *title, GtkWindow *parent, const gchar *label_text, const gchar *default_text)
Asks the user for text input.
File related dialogs, miscellaneous dialogs, font dialog.
GeanyDocument * document_get_current(void)
Finds the current document.
gboolean document_save_file(GeanyDocument *doc, gboolean force)
Saves the document.
GeanyDocument * document_find_by_filename(const gchar *utf8_filename)
Finds a document with the given filename.
Document related actions: new, save, open, etc.
#define DOC_VALID(doc_ptr)
Null-safe way to check GeanyDocument::is_valid.
#define documents
Wraps GeanyData::documents_array so it can be used with C array syntax.
#define foreach_document(i)
Iterates all valid document indexes.
void editor_indicator_clear_errors(GeanyEditor *editor)
void editor_indicator_set_on_line(GeanyEditor *editor, gint indic, gint line)
Sets an indicator indic on line.
GeanyEditorPrefs editor_prefs
@ GEANY_INDICATOR_ERROR
Indicator to highlight errors in the document text.
void error(const errorSelection selection, const char *const format,...)
GeanyKeyGroup * keybindings_get_core_group(guint id)
GeanyKeyBinding * keybindings_get_item(GeanyKeyGroup *group, gsize key_id)
Looks up a keybinding item.
@ GEANY_KEY_GROUP_BUILD
Group.
@ GEANY_KEYS_BUILD_COMPILE
Keybinding.
@ GEANY_KEYS_BUILD_PREVIOUSERROR
Keybinding.
@ GEANY_KEYS_BUILD_LINK
Keybinding.
@ GEANY_KEYS_BUILD_MAKE
Keybinding.
@ GEANY_KEYS_BUILD_RUN
Keybinding.
@ GEANY_KEYS_BUILD_MAKEOWNTARGET
Keybinding.
@ GEANY_KEYS_BUILD_NEXTERROR
Keybinding.
@ GEANY_KEYS_BUILD_OPTIONS
Keybinding.
@ GEANY_KEYS_BUILD_MAKEOBJECT
Keybinding.
static GOptionEntry entries[]
void geany_debug(gchar const *format,...)
void msgwin_parse_compiler_error_line(const gchar *string, const gchar *dir, gchar **filename, gint *line)
void msgwin_show_hide(gboolean show)
void msgwin_compiler_add_string(gint msg_color, const gchar *msg)
Adds a new message in the compiler tab treeview in the messages window.
gboolean msgwin_goto_compiler_file_line(gboolean focus_editor)
void msgwin_compiler_add(gint msg_color, const gchar *format,...)
Adds a formatted message in the compiler tab treeview in the messages window.
Message window functions (status, compiler, messages windows).
@ MSG_COMPILER
Index of the compiler tab.
@ MSG_VTE
Index of the VTE tab.
@ COLOR_BLACK
Color black.
@ COLOR_DARK_RED
Color dark red.
GeanyToolPrefs tool_prefs
void project_build_properties(void)
gchar * project_get_base_path(void)
char * strstr(const char *str, const char *substr)
gint sci_get_current_line(ScintillaObject *sci)
Gets current line number.
Wrapper functions for the Scintilla editor widget SCI_* messages.
gboolean spawn_with_callbacks(const gchar *working_directory, const gchar *command_line, gchar **argv, gchar **envp, SpawnFlags spawn_flags, GIOFunc stdin_cb, gpointer stdin_data, SpawnReadFunc stdout_cb, gpointer stdout_data, gsize stdout_max_length, SpawnReadFunc stderr_cb, gpointer stderr_data, gsize stderr_max_length, GChildWatchFunc exit_cb, gpointer exit_data, GPid *child_pid, GError **error)
<simplesect kind="geany:skip"></simplesect> Executes a child program and setups callbacks.
gboolean spawn_async(const gchar *working_directory, const gchar *command_line, gchar **argv, gchar **envp, GPid *child_pid, GError **error)
Executes a child asynchronously.
gboolean spawn_kill_process(GPid pid, GError **error)
Kills a process.
Portable and convenient process spawning and communication.
#define SPAWN_WIFEXITED(status)
non-zero if the child exited normally
#define SPAWN_WEXITSTATUS(status)
exit status of a child if exited normally
void filetypes_save_commands(GeanyFiletype *ft)
GeanyFiletype * filetypes_lookup_by_name(const gchar *name)
Finds a filetype pointer from its name field.
if(!stash_group_load_from_file(group, filename)) g_warning(_("Could not load keyfile %s!")
gtk_container_add(GTK_CONTAINER(dialog->vbox), check_button)
gtk_widget_show_all(dialog)
gchar ** nonfileregexstring
struct GeanyProject * project
Currently active project or NULL if none is open.
Structure for representing an open tab with all its properties.
gchar * file_name
The UTF-8 encoded file name.
gboolean changed
Whether this document has been changed since it was last saved.
GeanyFiletype * file_type
The filetype for this document, it's only a reference to one of the elements of the global filetypes ...
gboolean is_valid
Flag used to check if this document is valid when iterating GeanyData::documents_array.
GeanyEditor * editor
The editor associated with the document.
ScintillaObject * sci
The Scintilla editor GtkWidget.
GeanyBuildCommand * ftdefcmds
gchar * projerror_regex_string
GeanyBuildCommand * filecmds
GeanyBuildCommand * homeexeccmds
GeanyBuildCommand * homefilecmds
gchar * homeerror_regex_string
GeanyBuildCommand * execcmds
GeanyBuildCommand * projfilecmds
GeanyBuildCommand * projexeccmds
gchar * name
Untranslated short name, such as "C", "None".
GeanyFiletypeID id
Index in filetypes.
gchar * error_regex_string
struct GeanyFiletypePrivate * priv
Represents a single keybinding action.
GdkModifierType mods
Modifier keys, such as GDK_CONTROL_MASK or 0.
guint key
Key value in lower-case, such as GDK_KEY_a or 0.
GtkWidget * window
Main window.
GPtrArray * build_filetypes_list
Structure for representing a project.
struct GeanyProjectPrivate * priv
Defines internationalization macros.
void ui_label_set_markup(GtkLabel *label, const gchar *format,...)
void ui_progress_bar_start(const gchar *text)
Starts a constantly pulsing progressbar in the right corner of the statusbar (if the statusbar is vis...
GtkWidget * ui_dialog_vbox_new(GtkDialog *dialog)
Makes a fixed border for dialogs without increasing the button box border.
gboolean ui_tree_view_find_next(GtkTreeView *treeview, TVMatchCallback cb)
gboolean ui_tree_view_find_previous(GtkTreeView *treeview, TVMatchCallback cb)
GeanyMainWidgets main_widgets
void ui_set_statusbar(gboolean log, const gchar *format,...)
Displays text on the statusbar.
void ui_progress_bar_stop(void)
Stops a running progress bar and hides the widget again.
GtkWidget * ui_image_menu_item_new(const gchar *stock_id, const gchar *label)
Creates a GtkImageMenuItem with a stock image and a custom label.
GtkWidget * ui_label_new_bold(const gchar *text)
GtkWidget * ui_lookup_widget(GtkWidget *widget, const gchar *widget_name)
Returns a widget from a name in a component, usually created by Glade.
User Interface general utility functions.
#define GEANY_STOCK_BUILD
void utils_open_browser(const gchar *uri)
Tries to open the given URI in a browser.
guint utils_string_replace_all(GString *haystack, const gchar *needle, const gchar *replace)
Replaces all occurrences of needle in haystack with replace.
gchar * utils_get_utf8_from_locale(const gchar *locale_text)
Converts the given string (in locale encoding) into UTF-8 encoding.
const gchar * utils_resource_dir(GeanyResourceDirType type)
void utils_str_replace_all(gchar **haystack, const gchar *needle, const gchar *replacement)
const gchar * utils_get_uri_file_prefix(void)
gboolean utils_str_equal(const gchar *a, const gchar *b)
NULL-safe string comparison.
gchar * utils_remove_ext_from_filename(const gchar *filename)
Removes the extension from filename and return the result in a newly allocated string.
void utils_free_pointers(gsize arg_count,...)
gchar * utils_get_locale_from_utf8(const gchar *utf8_text)
Converts the given UTF-8 encoded string into locale encoding.
General utility functions, non-GTK related.
#define SETPTR(ptr, result)
Assigns result to ptr, then frees the old value.
#define EMPTY(ptr)
Returns TRUE if ptr is NULL or *ptr is FALSE.