diff --git a/src/args.c b/src/args.c index 8e7c8fc56..54dcb918c 100644 --- a/src/args.c +++ b/src/args.c @@ -1,11 +1,12 @@ /* Handle command line arguments. - Copyright (C) 2009, 2011 + Copyright (C) 2009, 2010, 2011, 2012 The Free Software Foundation, Inc. Written by: Slava Zanko , 2009. + Andrew Borodin , 2011, 2012. This file is part of the Midnight Commander. @@ -60,9 +61,6 @@ gboolean mc_args__force_colors = FALSE; /* Don't load keymap form file and use default one */ gboolean mc_args__nokeymap = FALSE; -/* Line to start the editor on */ -int mc_args__edit_start_line = 0; - char *mc_args__last_wd_file = NULL; /* when enabled NETCODE, use folowing file as logfile */ @@ -179,10 +177,10 @@ static const GOptionEntry argument_main_table[] = { }, { - "edit", 'e', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, + "edit", 'e', G_OPTION_FLAG_IN_MAIN | G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, parse_mc_e_argument, - N_("Edits one file"), - ""}, + N_("Edit files"), + " ..." }, { NULL, '\0', 0, 0, NULL, NULL, NULL /* Complete struct initialization */ @@ -443,11 +441,11 @@ static gboolean parse_mc_e_argument (const gchar * option_name, const gchar * value, gpointer data, GError ** error) { (void) option_name; + (void) value; (void) data; (void) error; mc_global.mc_run_mode = MC_RUN_EDITOR; - mc_run_param0 = g_strdup (value); return TRUE; } @@ -467,6 +465,113 @@ parse_mc_v_argument (const gchar * option_name, const gchar * value, gpointer da return TRUE; } +/* --------------------------------------------------------------------------------------------- */ +/** + * Get list of filenames (and line numbers) from command line, when mc called as editor + * + * @param argc count of all arguments + * @param argv array of strings, contains arguments + * @return list of mcedit_arg_t objects + */ + +static GList * +parse_mcedit_arguments (int argc, char **argv) +{ + GList *flist = NULL; + int i; + int first_line_number = -1; + + for (i = 0; i < argc; i++) + { + char *tmp; + char *end, *p; + mcedit_arg_t *arg; + + tmp = argv[i]; + + /* + * First, try to get line number as +lineno. + */ + if (*tmp == '+') + { + long lineno; + char *error; + + lineno = strtol (tmp + 1, &error, 10); + + if (*error == '\0') + { + /* this is line number */ + first_line_number = (int) lineno; + continue; + } + /* this is file name */ + } + + /* + * Check for filename:lineno, followed by an optional colon. + * This format is used by many programs (especially compilers) + * in error messages and warnings. It is supported so that + * users can quickly copy and paste file locations. + */ + end = tmp + strlen (tmp); + p = end; + + if (p > tmp && p[-1] == ':') + p--; + while (p > tmp && g_ascii_isdigit ((gchar) p[-1])) + p--; + + if (tmp < p && p < end && p[-1] == ':') + { + char *fname; + vfs_path_t *tmp_vpath, *fname_vpath; + struct stat st; + + fname = g_strndup (tmp, p - 1 - tmp); + tmp_vpath = vfs_path_from_str (tmp); + fname_vpath = vfs_path_from_str (fname); + + /* + * Check that the file before the colon actually exists. + * If it doesn't exist, create new file. + */ + if (mc_stat (tmp_vpath, &st) == -1 && mc_stat (fname_vpath, &st) != -1) + { + arg = mcedit_arg_vpath_new (fname_vpath, atoi (p)); + vfs_path_free (tmp_vpath); + } + else + { + arg = mcedit_arg_vpath_new (tmp_vpath, 1); + vfs_path_free (fname_vpath); + } + + g_free (fname); + } + else + arg = mcedit_arg_new (tmp, 1); + + flist = g_list_prepend (flist, arg); + } + + if (flist == NULL) + flist = g_list_prepend (flist, mcedit_arg_new (NULL, 1)); + else if (first_line_number != -1) + { + /* overwrite line number for first file */ + GList *l; + + if (first_line_number == 0) + first_line_number = 1; + + l = g_list_last (flist); + ((mcedit_arg_t *) l->data)->line_number = first_line_number; + } + + return flist; +} + /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ @@ -633,84 +738,7 @@ mc_setup_by_args (int argc, char **argv, GError ** error) { /* mce* or vi is link to mc */ - mc_run_param0 = g_strdup (""); - if (tmp != NULL) - { - /* - * Check for filename:lineno, followed by an optional colon. - * This format is used by many programs (especially compilers) - * in error messages and warnings. It is supported so that - * users can quickly copy and paste file locations. - */ - char *end, *p; - - end = tmp + strlen (tmp); - p = end; - - if (p > tmp && p[-1] == ':') - p--; - while (p > tmp && g_ascii_isdigit ((gchar) p[-1])) - p--; - if (tmp < p && p < end && p[-1] == ':') - { - char *fname; - struct stat st; - vfs_path_t *tmp_vpath, *fname_vpath; - gboolean ok; - - fname = g_strndup (tmp, p - 1 - tmp); - tmp_vpath = vfs_path_from_str (tmp); - fname_vpath = vfs_path_from_str (fname); - /* - * Check that the file before the colon actually exists. - * If it doesn't exist, revert to the old behavior. - */ - ok = mc_stat (tmp_vpath, &st) == -1 && mc_stat (fname_vpath, &st) != -1; - vfs_path_free (tmp_vpath); - vfs_path_free (fname_vpath); - - if (ok) - { - mc_run_param0 = fname; - mc_args__edit_start_line = atoi (p); - } - else - { - g_free (fname); - goto try_plus_filename; - } - } - else - { - try_plus_filename: - if (*tmp == '+' && g_ascii_isdigit ((gchar) tmp[1])) - { - int start_line; - - start_line = atoi (tmp); - - /* - * If start_line is zero, position the cursor at the - * beginning of the file as other editors (vi, nano) - */ - if (start_line == 0) - start_line++; - - if (start_line > 0) - { - char *file; - - file = (argc > 1) ? argv[2] : NULL; - if (file != NULL) - { - tmp = file; - mc_args__edit_start_line = start_line; - } - } - } - mc_run_param0 = g_strdup (tmp); - } - } + mc_run_param0 = parse_mcedit_arguments (argc - 1, &argv[1]); mc_global.mc_run_mode = MC_RUN_EDITOR; } else if (strncmp (base, "mcv", 3) == 0 || strcmp (base, "view") == 0) @@ -755,8 +783,11 @@ mc_setup_by_args (int argc, char **argv, GError ** error) switch (mc_global.mc_run_mode) { case MC_RUN_EDITOR: + mc_run_param0 = parse_mcedit_arguments (argc - 1, &argv[1]); + break; + case MC_RUN_VIEWER: - /* mc_run_param0 is set up in parse_mc_e_argument() and parse_mc_v_argument() */ + /* mc_run_param0 is set up in parse_mc_v_argument() */ break; case MC_RUN_DIFFVIEWER: @@ -782,3 +813,55 @@ mc_setup_by_args (int argc, char **argv, GError ** error) } /* --------------------------------------------------------------------------------------------- */ +/** + * Create mcedit_arg_t object from file name and the line number. + * + * @param file_name file name + * @param line_number line number + * @return mcedit_arg_t object + */ + +mcedit_arg_t * +mcedit_arg_new (const char *file_name, int line_number) +{ + return mcedit_arg_vpath_new (vfs_path_from_str (file_name), line_number); +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Create mcedit_arg_t object from vfs_path_t object and the line number. + * + * @param file_vpath file path object + * @param line_number line number + * @return mcedit_arg_t object + */ + +mcedit_arg_t * +mcedit_arg_vpath_new (vfs_path_t * file_vpath, int line_number) +{ + mcedit_arg_t *arg; + + arg = g_new (mcedit_arg_t, 1); + arg->file_vpath = file_vpath; + if (line_number == 0) + line_number = 1; + arg->line_number = line_number; + + return arg; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Free the mcedit_arg_t object. + * + * @param arg mcedit_arg_t object + */ + +void +mcedit_arg_free (mcedit_arg_t * arg) +{ + vfs_path_free (arg->file_vpath); + g_free (arg); +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/args.h b/src/args.h index 463d9c481..fe0e64d77 100644 --- a/src/args.h +++ b/src/args.h @@ -2,6 +2,7 @@ #define MC__ARGS_H #include "lib/global.h" /* gboolean */ +#include "lib/vfs/vfs.h" /* vfs_path_t */ /*** typedefs(not structures) and defined constants **********************************************/ @@ -9,13 +10,18 @@ /*** structures declarations (and typedefs of structures)*****************************************/ +typedef struct +{ + vfs_path_t *file_vpath; + int line_number; +} mcedit_arg_t; + /*** global variables defined in .c file *********************************************************/ extern gboolean mc_args__force_xterm; extern gboolean mc_args__nomouse; extern gboolean mc_args__force_colors; extern gboolean mc_args__nokeymap; -extern int mc_args__edit_start_line; extern char *mc_args__last_wd_file; extern char *mc_args__netfs_logfile; extern char *mc_args__keymap_file; @@ -27,5 +33,10 @@ gboolean mc_args_parse (int *argc, char ***argv, const char *translation_domain, gboolean mc_args_show_info (void); gboolean mc_setup_by_args (int argc, char **argv, GError ** error); +mcedit_arg_t *mcedit_arg_new (const char *file_name, int line_number); +mcedit_arg_t *mcedit_arg_vpath_new (vfs_path_t * file_vpath, int line_number); +void mcedit_arg_free (mcedit_arg_t * arg); + /*** inline functions ****************************************************************************/ + #endif /* MC__ARGS_H */ diff --git a/src/editor/edit.h b/src/editor/edit.h index dfdd8aeb4..f6928f985 100644 --- a/src/editor/edit.h +++ b/src/editor/edit.h @@ -61,7 +61,8 @@ extern int show_right_margin; void edit_stack_init (void); void edit_stack_free (void); -gboolean edit_file (const vfs_path_t * _file_vpath, int line); +gboolean edit_file (const vfs_path_t * file_vpath, int line); +gboolean edit_files (const GList * files); char *edit_get_file_name (const WEdit * edit); int edit_get_curs_col (const WEdit * edit); diff --git a/src/editor/editwidget.c b/src/editor/editwidget.c index 013707152..bcd1da2e8 100644 --- a/src/editor/editwidget.c +++ b/src/editor/editwidget.c @@ -59,6 +59,7 @@ #include "src/main.h" /* home_dir */ #include "src/filemanager/cmd.h" /* view_other_cmd(), save_setup_cmd() */ #include "src/learn.h" /* learn_keys() */ +#include "src/args.h" /* mcedit_arg_t */ #include "edit-impl.h" #include "editwidget.h" @@ -1013,14 +1014,37 @@ edit_callback (Widget * w, widget_msg_t msg, int parm) /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +/** + * Edit one file. + * + * @param file_vpath file object + * @param line line number + * @return TRUE if no errors was occured, FALSE otherwise + */ gboolean -edit_file (const vfs_path_t * _file_vpath, int line) +edit_file (const vfs_path_t * file_vpath, int line) +{ + mcedit_arg_t arg = { (vfs_path_t *) file_vpath, line }; + GList *files; + gboolean ok; + + files = g_list_prepend (NULL, &arg); + ok = edit_files (files); + g_list_free (files); + + return ok; +} +/* --------------------------------------------------------------------------------------------- */ + +gboolean +edit_files (const GList *files) { static gboolean made_directory = FALSE; Dlg_head *edit_dlg; WMenuBar *menubar; - gboolean ok; + const GList *file; + gboolean ok = FALSE; if (!made_directory) { @@ -1053,8 +1077,17 @@ edit_file (const vfs_path_t * _file_vpath, int line) add_widget (edit_dlg, buttonbar_new (TRUE)); - ok = edit_add_window (edit_dlg, edit_dlg->y + 1, edit_dlg->x, - edit_dlg->lines - 2, edit_dlg->cols, _file_vpath, line); + for (file = files; file != NULL; file = g_list_next (file)) + { + mcedit_arg_t *f = (mcedit_arg_t *) file->data; + gboolean f_ok; + + f_ok = edit_add_window (edit_dlg, edit_dlg->y + 1, edit_dlg->x, + edit_dlg->lines - 2, edit_dlg->cols, + f->file_vpath, f->line_number); + /* at least one file has been opened succefully */ + ok = ok || f_ok; + } if (ok) run_dlg (edit_dlg); diff --git a/src/filemanager/midnight.c b/src/filemanager/midnight.c index ccfe7c180..8559978c0 100644 --- a/src/filemanager/midnight.c +++ b/src/filemanager/midnight.c @@ -580,7 +580,7 @@ create_panels (void) current_mode = startup_left_mode; other_mode = startup_right_mode; /* if mc_run_param0 is NULL, working directory will be used for the left panel */ - current_dir = mc_run_param0; + current_dir = (char *) mc_run_param0; /* mc_run_param1 is never NULL. It is setup from command line or from panels.ini * (value of other_dir). mc_run_param1 will be used for the right panel */ other_dir = mc_run_param1; @@ -600,7 +600,7 @@ create_panels (void) if (mc_run_param0 != NULL) { current_dir = NULL; - other_dir = mc_run_param0; + other_dir = (char *) mc_run_param0; } else { @@ -973,29 +973,21 @@ prepend_cwd_on_local (const char *filename) static gboolean mc_maybe_editor_or_viewer (void) { - int ret; + gboolean ret; switch (mc_global.mc_run_mode) { #ifdef USE_INTERNAL_EDIT case MC_RUN_EDITOR: - { - vfs_path_t *vpath = NULL; - - if (mc_run_param0 != NULL && *mc_run_param0 != '\0') - vpath = vfs_path_from_str (mc_run_param0); - - ret = edit_file (vpath, mc_args__edit_start_line); - vfs_path_free (vpath); - } + ret = edit_files ((GList *) mc_run_param0); break; #endif /* USE_INTERNAL_EDIT */ case MC_RUN_VIEWER: { vfs_path_t *vpath = NULL; - if (mc_run_param0 != NULL && *mc_run_param0 != '\0') - vpath = prepend_cwd_on_local (mc_run_param0); + if (mc_run_param0 != NULL && *(char *) mc_run_param0 != '\0') + vpath = prepend_cwd_on_local ((char *) mc_run_param0); ret = view_file (vpath, 0, 1); vfs_path_free (vpath); @@ -1007,10 +999,10 @@ mc_maybe_editor_or_viewer (void) break; #endif /* USE_DIFF_VIEW */ default: - ret = 0; + ret = FALSE; } - return (ret != 0); + return ret; } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/main.c b/src/main.c index 8fecc39ed..7c95fac89 100644 --- a/src/main.c +++ b/src/main.c @@ -96,7 +96,7 @@ int use_internal_view = 1; /* If set, use the builtin editor */ int use_internal_edit = 1; -char *mc_run_param0 = NULL; +void *mc_run_param0 = NULL; char *mc_run_param1 = NULL; /* The user's shell */ @@ -630,7 +630,13 @@ main (int argc, char *argv[]) str_uninit_strings (); - g_free (mc_run_param0); + if (mc_global.mc_run_mode != MC_RUN_EDITOR) + g_free (mc_run_param0); + else + { + g_list_foreach ((GList *) mc_run_param0, (GFunc) mcedit_arg_free, NULL); + g_list_free ((GList *) mc_run_param0); + } g_free (mc_run_param1); mc_config_deinit_config_paths (); diff --git a/src/main.h b/src/main.h index eebf64056..03800374c 100644 --- a/src/main.h +++ b/src/main.h @@ -42,11 +42,11 @@ struct mc_fhl_struct; /* * MC_RUN_FULL: dir for left panel - * MC_RUN_EDITOR: file to edit + * MC_RUN_EDITOR: list of files to edit * MC_RUN_VIEWER: file to view * MC_RUN_DIFFVIEWER: first file to compare */ -extern char *mc_run_param0; +extern void *mc_run_param0; /* * MC_RUN_FULL: dir for right panel * MC_RUN_EDITOR: unused