/* * Copyright (C) 2012-2013 Robin Haberkorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "sciteco.h" #include "cmdline.h" #include "interface.h" #include "parser.h" #include "goto.h" #include "qregisters.h" #include "ring.h" #include "undo.h" #ifdef G_OS_UNIX #define INI_FILE ".teco_ini" #else #define INI_FILE "teco.ini" #endif namespace Flags { gint64 ed = 0; } static gchar *eval_macro = NULL; static gchar *mung_file = NULL; sig_atomic_t sigint_occurred = FALSE; extern "C" { static void sigint_handler(int signal); } void Interface::stdio_vmsg(MessageType type, const gchar *fmt, va_list ap) { gchar buf[255]; g_vsnprintf(buf, sizeof(buf), fmt, ap); switch (type) { case MSG_USER: g_printf("%s\n", buf); break; case MSG_INFO: g_printf("Info: %s\n", buf); break; case MSG_WARNING: g_fprintf(stderr, "Warning: %s\n", buf); break; case MSG_ERROR: g_fprintf(stderr, "Error: %s\n", buf); break; } } void Interface::process_notify(SCNotification *notify) { #ifdef DEBUG g_printf("SCINTILLA NOTIFY: code=%d\n", notify->nmhdr.code); #endif } #ifdef G_OS_WIN32 /* * Keep program self-contained under Windows * (look for profile in program's directory) */ static inline gchar * get_teco_ini(const gchar *program) { gchar *bin_dir = g_path_get_dirname(program); gchar *ini = g_build_filename(bin_dir, INI_FILE, NULL); g_free(bin_dir); return ini; } #else static inline gchar * get_teco_ini(const gchar *program __attribute__((unused))) { const gchar *home; #ifdef G_OS_UNIX home = g_get_home_dir(); #else home = g_get_user_config_dir(); #endif return g_build_filename(home, INI_FILE, NULL); } #endif /* !G_OS_WIN32 */ static inline void process_options(int &argc, char **&argv) { static const GOptionEntry option_entries[] = { {"eval", 'e', 0, G_OPTION_ARG_STRING, &eval_macro, "Evaluate macro", "macro"}, {"mung", 'm', 0, G_OPTION_ARG_FILENAME, &mung_file, "Mung file instead of " INI_FILE, "file"}, {NULL} }; GOptionContext *options; GOptionGroup *interface_group = interface.get_options(); options = g_option_context_new("- " PACKAGE_STRING); g_option_context_add_main_entries(options, option_entries, NULL); if (interface_group) g_option_context_add_group(options, interface_group); if (!g_option_context_parse(options, &argc, &argv, NULL)) { g_printf("Option parsing failed!\n"); exit(EXIT_FAILURE); } g_option_context_free(options); if (mung_file) { if (!g_file_test(mung_file, G_FILE_TEST_IS_REGULAR)) { g_printf("Cannot mung \"%s\". File does not exist!\n", mung_file); exit(EXIT_FAILURE); } } else { mung_file = get_teco_ini(argv[0]); } interface.parse_args(argc, argv); /* remaining arguments, are arguments to the munged file */ } int main(int argc, char **argv) { static GotoTable cmdline_goto_table; static QRegisterTable local_qregs; signal(SIGINT, sigint_handler); process_options(argc, argv); interface.ssm(SCI_SETCARETSTYLE, CARETSTYLE_BLOCK); interface.ssm(SCI_SETCARETFORE, 0xFFFFFF); /* * FIXME: Default styles should probably be set interface-based * (system defaults) and be changeable by TECO macros */ interface.ssm(SCI_STYLESETFORE, STYLE_DEFAULT, 0xFFFFFF); interface.ssm(SCI_STYLESETBACK, STYLE_DEFAULT, 0x000000); interface.ssm(SCI_STYLESETFONT, STYLE_DEFAULT, (sptr_t)"Courier"); interface.ssm(SCI_STYLECLEARALL); QRegisters::globals.initialize(); /* search string and status register */ QRegisters::globals.initialize("_"); /* replacement string register */ QRegisters::globals.initialize("-"); /* current buffer name and number ("*") */ QRegisters::globals.insert(new QRegisterBufferInfo()); local_qregs.initialize(); QRegisters::locals = &local_qregs; ring.edit((const gchar *)NULL); /* add remaining arguments to unnamed buffer */ for (int i = 1; i < argc; i++) { interface.ssm(SCI_APPENDTEXT, strlen(argv[i]), (sptr_t)argv[i]); interface.ssm(SCI_APPENDTEXT, 1, (sptr_t)"\n"); } /* * Execute macro or mung file */ if (eval_macro) { try { Execute::macro(eval_macro, false); } catch (...) { exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } if (g_file_test(mung_file, G_FILE_TEST_IS_REGULAR)) { if (!Execute::file(mung_file, false)) exit(EXIT_FAILURE); /* FIXME: make quit immediate in batch/macro mode (non-UNDO)? */ if (quit_requested) { /* FIXME */ exit(EXIT_SUCCESS); } } g_free(mung_file); /* * If munged file didn't quit, switch into interactive mode */ Goto::table = &cmdline_goto_table; interface.ssm(SCI_EMPTYUNDOBUFFER); undo.enabled = true; interface.event_loop(); return 0; } /* * Callbacks */ static void sigint_handler(int signal __attribute__((unused))) { sigint_occurred = TRUE; }