/*
* Copyright (C) 2012-2015 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 "sciteco.h"
#include "cmdline.h"
#include "interface.h"
#include "ioview.h"
#include "parser.h"
#include "goto.h"
#include "qregisters.h"
#include "ring.h"
#include "undo.h"
#include "error.h"
/*
* Define this to pause the program at the beginning
* of main() (Windows only).
* This is a useful hack on Windows, where gdbserver
* sometimes refuses to start SciTECO but attaches
* to a running process just fine.
*/
//#define DEBUG_PAUSE
namespace SciTECO {
#define INI_FILE ".teco_ini"
/*
* defining the global objects here ensures
* a ctor/dtor order without depending on the
* GCC init_priority() attribute
*/
InterfaceCurrent interface;
IOView QRegisters::view;
/*
* Scintilla will be initialized after these
* ctors (in main()), but dtors are guaranteed
* to be executed before Scintilla's
* destruction
*/
QRegisterTable QRegisters::globals;
Ring ring;
namespace Flags {
tecoInt ed = ED_AUTOEOL;
}
static gchar *eval_macro = NULL;
static gchar *mung_file = NULL;
static gboolean mung_profile = TRUE;
sig_atomic_t sigint_occurred = FALSE;
extern "C" {
static gpointer g_malloc_exception(gsize n_bytes);
static gpointer g_calloc_exception(gsize n_blocks, gsize n_block_bytes);
static gpointer g_realloc_exception(gpointer mem, gsize n_bytes);
static void sigint_handler(int signal);
}
#if defined(G_OS_UNIX) || defined(G_OS_HAIKU)
void
interrupt(void)
{
/*
* This sends SIGINT to the entire process group,
* which makes sure that subprocesses are signalled,
* even when called from the wrong thread.
*/
if (kill(0, SIGINT))
sigint_occurred = TRUE;
}
#else /* !G_OS_UNIX && !G_OS_HAIKU */
void
interrupt(void)
{
if (raise(SIGINT))
sigint_occurred = TRUE;
}
#endif
const gchar *
get_eol_seq(gint eol_mode)
{
switch (eol_mode) {
case SC_EOL_CRLF:
return "\r\n";
case SC_EOL_CR:
return "\r";
case SC_EOL_LF:
default:
return "\n";
}
}
#ifdef G_OS_WIN32
/*
* Keep program self-contained under Windows
* Look for config files (profile and session),
* as well as standard library macros in the
* program's directory.
*/
static inline gchar *
get_default_config_path(const gchar *program)
{
return g_path_get_dirname(program);
}
#elif defined(G_OS_UNIX)
/*
* NOTE: We explicitly do not handle
* Haiku like UNIX here, since it appears to
* be uncommon on Haiku to clutter the HOME directory
* with config files.
*/
static inline gchar *
get_default_config_path(const gchar *program)
{
return g_strdup(g_getenv("HOME"));
}
#else
static inline gchar *
get_default_config_path(const gchar *program)
{
return g_strdup(g_get_user_config_dir());
}
#endif
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 "
"$SCITECOCONFIG" G_DIR_SEPARATOR_S INI_FILE, "file"},
{"no-profile", 0, G_OPTION_FLAG_REVERSE,
G_OPTION_ARG_NONE, &mung_profile,
"Do not mung "
"$SCITECOCONFIG" G_DIR_SEPARATOR_S INI_FILE
" even if it exists"},
{NULL}
};
GError *gerror = NULL;
GOptionContext *options;
GOptionGroup *interface_group = interface.get_options();
options = g_option_context_new("[--] [ARGUMENT...]");
g_option_context_set_summary(
options,
PACKAGE_STRING " -- Scintilla-based Text Editor and COrrector"
);
g_option_context_set_description(
options,
"Bug reports should go to <" PACKAGE_BUGREPORT "> or "
"<" PACKAGE_URL_DEV ">."
);
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, &gerror)) {
g_fprintf(stderr, "Option parsing failed: %s\n",
gerror->message);
g_error_free(gerror);
exit(EXIT_FAILURE);
}
g_option_context_free(options);
if (mung_file) {
if (!g_file_test(mung_file, G_FILE_TEST_IS_REGULAR)) {
g_fprintf(stderr, "Cannot mung \"%s\". File does not exist!\n",
mung_file);
exit(EXIT_FAILURE);
}
}
/* remaining arguments, are arguments to the interface */
}
static inline void
initialize_environment(const gchar *program)
{
gchar *default_configpath, *abs_path;
/*
* Initialize some "special" environment variables.
* For ease of use and because there are no threads yet,
* we modify the process environment directly.
* Later it is imported into the global Q-Register table
* and the process environment should no longer be accessed
* directly.
*
* Initialize and canonicalize $HOME.
* Therefore we can refer to $HOME as the
* current user's home directory on any platform
* and it can be re-configured even though g_get_home_dir()
* evaluates $HOME only beginning with glib v2.36.
*/
g_setenv("HOME", g_get_home_dir(), FALSE);
abs_path = get_absolute_path(g_getenv("HOME"));
g_setenv("HOME", abs_path, TRUE);
g_free(abs_path);
/*
* Initialize $SCITECOCONFIG and $SCITECOPATH
*/
default_configpath = get_default_config_path(program);
g_setenv("SCITECOCONFIG", default_configpath, FALSE);
#ifdef G_OS_WIN32
gchar *default_scitecopath;
default_scitecopath = g_build_filename(default_configpath, "lib", NIL);
g_setenv("SCITECOPATH", default_scitecopath, FALSE);
g_free(default_scitecopath);
#else
g_setenv("SCITECOPATH", SCITECOLIBDIR, FALSE);
#endif
g_free(default_configpath);
/*
* $SCITECOCONFIG and $SCITECOPATH may still be relative.
* They are canonicalized, so macros can use them even
* if the current working directory changes.
*/
abs_path = get_absolute_path(g_getenv("SCITECOCONFIG"));
g_setenv("SCITECOCONFIG", abs_path, TRUE);
g_free(abs_path);
abs_path = get_absolute_path(g_getenv("SCITECOPATH"));
g_setenv("SCITECOPATH", abs_path, TRUE);
g_free(abs_path);
/*
* Import process environment into global Q-Register
* table. While it is safe to use g_setenv() early
* on at startup, it might be problematic later on
* (e.g. it's non-thread-safe).
* Therefore the environment registers in the global
* table should be used from now on to set and get
* environment variables.
* When spawning external processes that should inherit
* the environment variables, the environment should
* be exported via QRegisters::globals.get_environ().
*/
QRegisters::globals.set_environ();
}
/*
* Callbacks
*/
class g_bad_alloc : public std::bad_alloc {
public:
const char *
what() const throw()
{
return "glib allocation";
}
};
static gpointer
g_malloc_exception(gsize n_bytes)
{
gpointer p = malloc(n_bytes);
if (!p)
throw g_bad_alloc();
return p;
}
static gpointer
g_calloc_exception(gsize n_blocks, gsize n_block_bytes)
{
gpointer p = calloc(n_blocks, n_block_bytes);
if (!p)
throw g_bad_alloc();
return p;
}
static gpointer
g_realloc_exception(gpointer mem, gsize n_bytes)
{
gpointer p = realloc(mem, n_bytes);
if (!p)
throw g_bad_alloc();
return p;
}
static void
sigint_handler(int signal)
{
sigint_occurred = TRUE;
}
} /* namespace SciTECO */
/*
* main() must be defined in the root
* namespace, so we import the "SciTECO"
* namespace. We have no more declarations
* to make in the "SciTECO" namespace.
*/
using namespace SciTECO;HTTP/1.1 200 OK
Connection: keep-alive
Connection: keep-alive
Connection: keep-alive
Content-Disposition: inline; filename="main.cpp"
Content-Disposition: inline; filename="main.cpp"
Content-Disposition: inline; filename="main.cpp"
Content-Length: 11450
Content-Length: 11450
Content-Length: 11450
Content-Security-Policy: default-src 'none'
Content-Security-Policy: default-src 'none'
Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Type: text/plain; charset=UTF-8
Content-Type: text/plain; charset=UTF-8
Date: Thu, 23 Oct 2025 05:33:20 UTC
ETag: "1f89156a2c44f43c1a6b68c17eb45443ebbd0e61"
ETag: "1f89156a2c44f43c1a6b68c17eb45443ebbd0e61"
ETag: "1f89156a2c44f43c1a6b68c17eb45443ebbd0e61"
Expires: Sun, 21 Oct 2035 05:33:19 GMT
Expires: Sun, 21 Oct 2035 05:33:20 GMT
Expires: Sun, 21 Oct 2035 05:33:20 GMT
Last-Modified: Thu, 23 Oct 2025 05:33:19 GMT
Last-Modified: Thu, 23 Oct 2025 05:33:20 GMT
Last-Modified: Thu, 23 Oct 2025 05:33:20 GMT
Server: OpenBSD httpd
Server: OpenBSD httpd
Server: OpenBSD httpd
X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
/*
* Copyright (C) 2012-2015 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 "sciteco.h"
#include "cmdline.h"
#include "interface.h"
#include "ioview.h"
#include "parser.h"
#include "goto.h"
#include "qregisters.h"
#include "ring.h"
#include "undo.h"
#include "error.h"
/*
* Define this to pause the program at the beginning
* of main() (Windows only).
* This is a useful hack on Windows, where gdbserver
* sometimes refuses to start SciTECO but attaches
* to a running process just fine.
*/
//#define DEBUG_PAUSE
namespace SciTECO {
#define INI_FILE ".teco_ini"
/*
* defining the global objects here ensures
* a ctor/dtor order without depending on the
* GCC init_priority() attribute
*/
InterfaceCurrent interface;
IOView QRegisters::view;
/*
* Scintilla will be initialized after these
* ctors (in main()), but dtors are guaranteed
* to be executed before Scintilla's
* destruction
*/
QRegisterTable QRegisters::globals;
Ring ring;
namespace Flags {
tecoInt ed = ED_AUTOEOL;
}
static gchar *eval_macro = NULL;
static gchar *mung_file = NULL;
static gboolean mung_profile = TRUE;
sig_atomic_t sigint_occurred = FALSE;
extern "C" {
static gpointer g_malloc_exception(gsize n_bytes);
static gpointer g_call