diff --git a/medit/medit-app.c b/medit/medit-app.c index 9a522b3f..4e4d9175 100644 --- a/medit/medit-app.c +++ b/medit/medit-app.c @@ -82,6 +82,12 @@ int _medit_parse_options (const char *const program_name, --app-name=NAME Set instance name to NAME if it's not already\n\ running\n" +#define STR_HELP_NEW_WINDOW "\ + -w, --new-window Open file in a new window\n" + +#define STR_HELP_NEW_TAB "\ + -t, --new-tab Open file in a new tab\n" + #define STR_HELP_MODE "\ -m, --mode=[simple|project] Use specified mode\n" @@ -115,6 +121,8 @@ int _medit_parse_options (const char *const program_name, --pid=PID Use existing instance with process id PID\n\ --app-name=NAME Set instance name to NAME if it's not already\n\ running\n\ + -w, --new-window Open file in a new window\n\ + -t, --new-tab Open file in a new tab\n\ -m, --mode=[simple|project] Use specified mode\n\ -p, --project=PROJECT Open project file PROJECT\n\ -l, --line=LINE Open file and position cursor on line LINE\n\ @@ -137,6 +145,12 @@ char _medit_opt_pid; /* Set to 1 if option --app-name has been specified. */ char _medit_opt_app_name; +/* Set to 1 if option --new-window (-w) has been specified. */ +char _medit_opt_new_window; + +/* Set to 1 if option --new-tab (-t) has been specified. */ +char _medit_opt_new_tab; + /* Set to 1 if option --mode (-m) has been specified. */ char _medit_opt_mode; @@ -198,6 +212,8 @@ int _medit_parse_options (const char *const program_name, const int argc, char * static const char *const optstr__new_app = "new-app"; static const char *const optstr__pid = "pid"; static const char *const optstr__app_name = "app-name"; + static const char *const optstr__new_window = "new-window"; + static const char *const optstr__new_tab = "new-tab"; static const char *const optstr__mode = "mode"; static const char *const optstr__project = "project"; static const char *const optstr__line = "line"; @@ -211,6 +227,8 @@ int _medit_parse_options (const char *const program_name, const int argc, char * _medit_opt_use_session = 0; _medit_opt_pid = 0; _medit_opt_app_name = 0; + _medit_opt_new_window = 0; + _medit_opt_new_tab = 0; _medit_opt_mode = 0; _medit_opt_project = 0; _medit_opt_line = 0; @@ -370,6 +388,8 @@ int _medit_parse_options (const char *const program_name, const int argc, char * case 'n': if (strncmp (option + 1, optstr__new_app + 1, option_len - 1) == 0) { + if (option_len <= 4) + goto error_long_opt_ambiguous; if (argument != 0) { option = optstr__new_app; @@ -378,6 +398,30 @@ int _medit_parse_options (const char *const program_name, const int argc, char * _medit_opt_new_app = 1; break; } + if (strncmp (option + 1, optstr__new_tab + 1, option_len - 1) == 0) + { + if (option_len <= 4) + goto error_long_opt_ambiguous; + if (argument != 0) + { + option = optstr__new_tab; + goto error_unexpec_arg_long; + } + _medit_opt_new_tab = 1; + break; + } + if (strncmp (option + 1, optstr__new_window + 1, option_len - 1) == 0) + { + if (option_len <= 4) + goto error_long_opt_ambiguous; + if (argument != 0) + { + option = optstr__new_window; + goto error_unexpec_arg_long; + } + _medit_opt_new_window = 1; + break; + } goto error_unknown_long_opt; case 'p': if (strncmp (option + 1, optstr__pid + 1, option_len - 1) == 0) @@ -498,6 +542,12 @@ int _medit_parse_options (const char *const program_name, const int argc, char * _medit_arg_use_session = 0; _medit_opt_use_session = 1; break; + case 't': + _medit_opt_new_tab = 1; + break; + case 'w': + _medit_opt_new_window = 1; + break; default: fprintf (stderr, STR_ERR_UNKNOWN_SHORT_OPT, program_name, *option); return -1; @@ -509,7 +559,7 @@ int _medit_parse_options (const char *const program_name, const int argc, char * } return i; } -#line 64 "../../../medit/medit-app.opag" +#line 65 "../../../medit/medit-app.opag" #undef STR_HELP #define STR_HELP \ @@ -651,6 +701,7 @@ main (int argc, char *argv[]) guint32 stamp; guint32 line = 0; const char *name = NULL; + guint options = 0; init_mem_stuff (); @@ -723,6 +774,10 @@ main (int argc, char *argv[]) if (_medit_arg_line) line = strtol (_medit_arg_line, NULL, 10); + if (_medit_opt_new_window) + options |= MOO_EDIT_OPEN_NEW_WINDOW; + if (_medit_opt_new_tab) + options |= MOO_EDIT_OPEN_NEW_TAB; if (_medit_opt_pid) name = _medit_arg_pid; @@ -747,7 +802,7 @@ main (int argc, char *argv[]) if (name) { - if (moo_app_send_files (app, files, line, stamp, name)) + if (moo_app_send_files (app, files, line, stamp, name, options)) exit (0); if (!_medit_opt_app_name) @@ -757,7 +812,7 @@ main (int argc, char *argv[]) } } - if ((!new_instance && !_medit_opt_app_name && moo_app_send_files (app, files, line, stamp, NULL)) || + if ((!new_instance && !_medit_opt_app_name && moo_app_send_files (app, files, line, stamp, NULL, options)) || !moo_app_init (app)) { gdk_notify_startup_complete (); @@ -776,7 +831,7 @@ main (int argc, char *argv[]) moo_editor_new_window (editor); if (files && *files) - moo_app_open_files (app, files, line, stamp); + moo_app_open_files (app, files, line, stamp, options); g_strfreev (files); diff --git a/medit/medit-app.opag b/medit/medit-app.opag index 5ce23340..d3d659c5 100644 --- a/medit/medit-app.opag +++ b/medit/medit-app.opag @@ -49,6 +49,8 @@ n new-app "Run new instance of application" s use-session "[=yes|no] Load and save session" optarg pid "=PID Use existing instance with process id PID" reqarg app-name "=NAME Set instance name to NAME if it's not already running" reqarg +w new-window "Open file in a new window" +t new-tab "Open file in a new tab" m mode "=[simple|project] Use specified mode" reqarg p project "=PROJECT Open project file PROJECT" reqarg l line "=LINE Open file and position cursor on line LINE" reqarg @@ -59,7 +61,7 @@ l line "=LINE Open file and position cursor on line LINE" version "Display version information and exit" return h help "Display this help text and exit" return %% -#line 64 "../../../medit/medit-app.opag" +#line 65 "../../../medit/medit-app.opag" #undef STR_HELP #define STR_HELP \ @@ -201,6 +203,7 @@ main (int argc, char *argv[]) guint32 stamp; guint32 line = 0; const char *name = NULL; + guint options = 0; init_mem_stuff (); @@ -273,6 +276,10 @@ main (int argc, char *argv[]) if (_medit_arg_line) line = strtol (_medit_arg_line, NULL, 10); + if (_medit_opt_new_window) + options |= MOO_EDIT_OPEN_NEW_WINDOW; + if (_medit_opt_new_tab) + options |= MOO_EDIT_OPEN_NEW_TAB; if (_medit_opt_pid) name = _medit_arg_pid; @@ -297,7 +304,7 @@ main (int argc, char *argv[]) if (name) { - if (moo_app_send_files (app, files, line, stamp, name)) + if (moo_app_send_files (app, files, line, stamp, name, options)) exit (0); if (!_medit_opt_app_name) @@ -307,7 +314,7 @@ main (int argc, char *argv[]) } } - if ((!new_instance && !_medit_opt_app_name && moo_app_send_files (app, files, line, stamp, NULL)) || + if ((!new_instance && !_medit_opt_app_name && moo_app_send_files (app, files, line, stamp, NULL, options)) || !moo_app_init (app)) { gdk_notify_startup_complete (); @@ -326,7 +333,7 @@ main (int argc, char *argv[]) moo_editor_new_window (editor); if (files && *files) - moo_app_open_files (app, files, line, stamp); + moo_app_open_files (app, files, line, stamp, options); g_strfreev (files); diff --git a/medit/medit.1 b/medit/medit.1 index fb45c754..a9333615 100644 --- a/medit/medit.1 +++ b/medit/medit.1 @@ -50,6 +50,12 @@ then it will send files given on the command line to that instance and exit. .B \-l, \-\-line LINE Open file and position cursor on line \fBLINE\fP. .TP +.B \-w, \-\-new-window +Open file in a new window. +.TP +.B \-t, \-\-new-tab +Open file in a new tab. +.TP .B \-\-log[=FILE] Show debug output or write it to \fBFILE\fP. .TP diff --git a/moo/mooapp/mooapp.c b/moo/mooapp/mooapp.c index e170fe53..a9d11187 100644 --- a/moo/mooapp/mooapp.c +++ b/moo/mooapp/mooapp.c @@ -966,10 +966,12 @@ moo_app_send_files (MooApp *app, char **files, guint32 line, guint32 stamp, - const char *pid) + const char *pid, + guint options) { gboolean result; GString *msg; + char **p; g_return_val_if_fail (MOO_IS_APP (app), FALSE); @@ -979,14 +981,14 @@ moo_app_send_files (MooApp *app, msg = g_string_new (NULL); - g_string_append_printf (msg, "%s%08x%08x", CMD_OPEN_URIS, stamp, line); + g_string_append_printf (msg, "%s%08x%08x", CMD_OPEN_URIS, stamp, 0u); - while (files && *files) + for (p = files; p && *p; ++p) { char *freeme = NULL, *uri; const char *basename, *filename; - basename = *files++; + basename = *p; if (g_path_is_absolute (basename)) { @@ -1000,7 +1002,10 @@ moo_app_send_files (MooApp *app, g_free (dir); } - uri = g_filename_to_uri (filename, NULL, NULL); + if (p != files) + line = 0; + + uri = _moo_edit_filename_to_uri (filename, line, options); if (uri) { @@ -1452,7 +1457,8 @@ _moo_app_exec_cmd (MooApp *app, static void moo_app_new_file (MooApp *app, const char *filename, - guint32 line) + guint32 line, + guint options) { #ifdef MOO_BUILD_EDIT MooEditor *editor = moo_app_get_editor (app); @@ -1490,10 +1496,7 @@ moo_app_new_file (MooApp *app, *colon = 0; } - if (line > 0) - moo_editor_open_file_line (editor, norm_name, line - 1, NULL); - else - moo_editor_new_file (editor, NULL, NULL, norm_name, NULL); + _moo_editor_open_file (editor, norm_name, line, options); } g_free (norm_name); @@ -1680,24 +1683,28 @@ moo_app_open_uris (MooApp *app, { char **p; - for (p = uris; p && *p; ++p) + for (p = uris; p && *p && **p; ++p) { - char *filename = g_filename_from_uri (*p, NULL, NULL); + guint line_here = 0; + guint options = 0; + char *filename; + + filename = _moo_edit_uri_to_filename (*p, &line_here, &options); + + if (p != uris) + line = 0; + if (line_here) + line = line_here; if (filename) - { - if (p == uris && line > 0) - moo_app_new_file (app, filename, line); - else - moo_app_new_file (app, filename, 0); - } + moo_app_new_file (app, filename, line, options); g_free (filename); } } else { - moo_app_new_file (app, NULL, 0); + moo_app_new_file (app, NULL, 0, 0); } moo_editor_present (app->priv->editor, stamp); @@ -1711,7 +1718,8 @@ void moo_app_open_files (MooApp *app, char **files, guint32 line, - guint32 stamp) + guint32 stamp, + guint options) { #ifdef MOO_BUILD_EDIT char **p; @@ -1722,9 +1730,9 @@ moo_app_open_files (MooApp *app, for (p = files; p && *p; ++p) { if (p == files && line > 0) - moo_app_new_file (app, *p, line); + moo_app_new_file (app, *p, line, options); else - moo_app_new_file (app, *p, 0); + moo_app_new_file (app, *p, 0, options); } moo_editor_present (app->priv->editor, stamp); @@ -1766,7 +1774,7 @@ moo_app_exec_cmd_real (MooApp *app, break; case MOO_APP_CMD_OPEN_FILE: - moo_app_new_file (app, data, 0); + moo_app_new_file (app, data, 0, 0); break; case MOO_APP_CMD_OPEN_URIS: moo_app_open_uris (app, data); diff --git a/moo/mooapp/mooapp.h b/moo/mooapp/mooapp.h index 3fb24618..d999cfca 100644 --- a/moo/mooapp/mooapp.h +++ b/moo/mooapp/mooapp.h @@ -114,11 +114,13 @@ gboolean moo_app_send_files (MooApp *app, char **files, guint32 line, guint32 stamp, - const char *pid); + const char *pid, + guint options); void moo_app_open_files (MooApp *app, char **files, guint32 line, - guint32 stamp); + guint32 stamp, + guint options); void moo_app_reload_python_plugins (void); diff --git a/moo/mooedit/mooeditor.c b/moo/mooedit/mooeditor.c index 54ffc722..5ab3e0ee 100644 --- a/moo/mooedit/mooeditor.c +++ b/moo/mooedit/mooeditor.c @@ -31,6 +31,7 @@ #include "mooutils/mooi18n.h" #include #include +#include #define RECENT_ACTION_ID "OpenRecent" @@ -2512,3 +2513,172 @@ moo_editor_apply_prefs (MooEditor *editor) "save-backups", backups, NULL); } + + +char * +_moo_edit_filename_to_uri (const char *filename, + guint line, + guint options) +{ + GString *string; + char *uri; + GError *error = NULL; + + g_return_val_if_fail (filename != NULL, NULL); + + if (!(uri = g_filename_to_uri (filename, NULL, &error))) + { + g_warning ("%s: could not convert filename to URI: %s", + G_STRLOC, error->message); + g_error_free (error); + return NULL; + } + + if (!line == 0 && !options) + return uri; + + string = g_string_new (uri); + g_string_append (string, "?"); + + if (line > 0) + g_string_append_printf (string, "line=%u;", line); + + if (options) + { + g_string_append (string, "options="); + if (options & MOO_EDIT_OPEN_NEW_WINDOW) + g_string_append (string, "new-window"); + if (options & MOO_EDIT_OPEN_NEW_TAB) + g_string_append (string, "new-tab"); + g_string_append (string, ";"); + } + + g_free (uri); + g_print ("%s\n", string->str); + return g_string_free (string, FALSE); +} + +static void +parse_options (const char *optstring, + guint *line, + guint *options) +{ + char **p, **comps; + + comps = g_strsplit (optstring, ";", 0); + + for (p = comps; p && *p; ++p) + { + if (!strncmp (*p, "line=", strlen ("line="))) + { + /* doesn't matter if there is an error */ + *line = strtoul (*p + strlen ("line="), NULL, 10); + } + else if (!strncmp (*p, "options=", strlen ("options="))) + { + char **opts, **op; + opts = g_strsplit (*p + strlen ("options="), ",", 0); + for (op = opts; op && *op; ++op) + { + if (!strcmp (*op, "new-window")) + *options |= MOO_EDIT_OPEN_NEW_WINDOW; + else if (!strcmp (*op, "new-tab")) + *options |= MOO_EDIT_OPEN_NEW_TAB; + } + g_strfreev (opts); + } + } + + g_strfreev (comps); +} + +char * +_moo_edit_uri_to_filename (const char *uri, + guint *line, + guint *options) +{ + const char *question_mark; + const char *optstring = NULL; + char *freeme = NULL; + char *filename; + GError *error = NULL; + + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (line != NULL, NULL); + g_return_val_if_fail (options != NULL, NULL); + + *line = 0; + *options = 0; + + question_mark = strchr (uri, '?'); + + if (question_mark && question_mark > uri) + { + freeme = g_strndup (uri, question_mark - uri); + optstring = question_mark + 1; + uri = freeme; + } + + if (!(filename = g_filename_from_uri (uri, NULL, &error))) + { + g_warning ("%s: could not convert URI to filename: %s", + G_STRLOC, error->message); + g_error_free (error); + g_free (freeme); + return NULL; + } + + if (optstring) + parse_options (optstring, line, options); + + g_free (freeme); + return filename; +} + +void +_moo_editor_open_file (MooEditor *editor, + const char *filename, + guint line, + guint options) +{ + MooEdit *doc; + MooEditWindow *window; + + g_return_if_fail (MOO_IS_EDITOR (editor)); + g_return_if_fail (filename != NULL); + + doc = moo_editor_get_doc (editor, filename); + + if (doc) + { + if (line > 0) + moo_text_view_move_cursor (MOO_TEXT_VIEW (doc), line - 1, 0, FALSE, FALSE); + moo_editor_set_active_doc (editor, doc); + gtk_widget_grab_focus (GTK_WIDGET (doc)); + return; + } + + window = moo_editor_get_active_window (editor); + doc = window ? moo_edit_window_get_active_doc (window) : NULL; + + if (!doc || !moo_edit_is_empty (doc)) + { + gboolean new_window = moo_prefs_get_bool (moo_edit_setting (MOO_EDIT_PREFS_OPEN_NEW_WINDOW)); + + if (options & MOO_EDIT_OPEN_NEW_TAB) + new_window = FALSE; + else if (options & MOO_EDIT_OPEN_NEW_WINDOW) + new_window = TRUE; + + if (new_window) + window = moo_editor_new_window (editor); + } + + doc = moo_editor_new_file (editor, window, NULL, filename, NULL); + g_return_if_fail (doc != NULL); + + moo_editor_set_active_doc (editor, doc); + if (line > 0) + moo_text_view_move_cursor (MOO_TEXT_VIEW (doc), line - 1, 0, FALSE, TRUE); + gtk_widget_grab_focus (GTK_WIDGET (doc)); +} diff --git a/moo/mooedit/mooeditor.h b/moo/mooedit/mooeditor.h index f010e16b..1bba5488 100644 --- a/moo/mooedit/mooeditor.h +++ b/moo/mooedit/mooeditor.h @@ -155,6 +155,23 @@ void _moo_editor_save_session (MooEditor *editor, MooMarkupNode *xml); +enum { + MOO_EDIT_OPEN_NEW_WINDOW = 1u << 0, + MOO_EDIT_OPEN_NEW_TAB = 1u << 1 +}; + +char *_moo_edit_filename_to_uri (const char *filename, + guint line, + guint options); +char *_moo_edit_uri_to_filename (const char *uri, + guint *line, + guint *options); +void _moo_editor_open_file (MooEditor *editor, + const char *filename, + guint line, + guint options); + + G_END_DECLS #endif /* MOO_EDITOR_H */ diff --git a/moo/mooedit/mooeditprefs.c b/moo/mooedit/mooeditprefs.c index 3eda92a5..03110f23 100644 --- a/moo/mooedit/mooeditprefs.c +++ b/moo/mooedit/mooeditprefs.c @@ -98,6 +98,7 @@ _moo_edit_init_prefs (void) NEW_KEY_BOOL (MOO_EDIT_PREFS_STRIP, FALSE); NEW_KEY_BOOL (MOO_EDIT_PREFS_USE_TABS, TRUE); + NEW_KEY_BOOL (MOO_EDIT_PREFS_OPEN_NEW_WINDOW, FALSE); NEW_KEY_STRING (MOO_EDIT_PREFS_TITLE_FORMAT, "%a - %f%s"); NEW_KEY_STRING (MOO_EDIT_PREFS_TITLE_FORMAT_NO_DOC, "%a"); diff --git a/moo/mooedit/mooeditprefs.h b/moo/mooedit/mooeditprefs.h index ab6f04ee..31066751 100644 --- a/moo/mooedit/mooeditprefs.h +++ b/moo/mooedit/mooeditprefs.h @@ -29,6 +29,7 @@ const char *moo_edit_setting (const char *setting_name); #define MOO_EDIT_PREFS_TITLE_FORMAT "window_title" #define MOO_EDIT_PREFS_TITLE_FORMAT_NO_DOC "window_title_no_doc" #define MOO_EDIT_PREFS_USE_TABS "use_tabs" +#define MOO_EDIT_PREFS_OPEN_NEW_WINDOW "open_new_window" #define MOO_EDIT_PREFS_DEFAULT_LANG "default_lang" #define MOO_EDIT_PREFS_SAVE_SESSION "save_session" diff --git a/moo/moopython/pygtk/mooapp-pygtk.defs b/moo/moopython/pygtk/mooapp-pygtk.defs index 58dc28e1..ffbd72cb 100644 --- a/moo/moopython/pygtk/mooapp-pygtk.defs +++ b/moo/moopython/pygtk/mooapp-pygtk.defs @@ -147,6 +147,7 @@ '("int" "line" (default "-1")) '("guint32" "stamp" (default "0")) '("const-char*" "pid" (null-ok) (default "NULL")) + '("guint" "options" (default "0")) ) )