aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ioview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ioview.cpp')
-rw-r--r--src/ioview.cpp512
1 files changed, 0 insertions, 512 deletions
diff --git a/src/ioview.cpp b/src/ioview.cpp
deleted file mode 100644
index 383b9bb..0000000
--- a/src/ioview.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Copyright (C) 2012-2017 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 <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <glib/gstdio.h>
-
-#include <Scintilla.h>
-
-#include "sciteco.h"
-#include "interface.h"
-#include "undo.h"
-#include "error.h"
-#include "qregisters.h"
-#include "eol.h"
-#include "ioview.h"
-
-#ifdef HAVE_WINDOWS_H
-/* here it shouldn't cause conflicts with other headers */
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
-namespace SciTECO {
-
-#ifdef G_OS_WIN32
-
-typedef DWORD FileAttributes;
-/* INVALID_FILE_ATTRIBUTES already defined */
-
-static inline FileAttributes
-get_file_attributes(const gchar *filename)
-{
- return GetFileAttributes((LPCTSTR)filename);
-}
-
-static inline void
-set_file_attributes(const gchar *filename, FileAttributes attrs)
-{
- SetFileAttributes((LPCTSTR)filename, attrs);
-}
-
-#else
-
-typedef int FileAttributes;
-#define INVALID_FILE_ATTRIBUTES (-1)
-
-static inline FileAttributes
-get_file_attributes(const gchar *filename)
-{
- struct stat buf;
-
- return g_stat(filename, &buf) ? INVALID_FILE_ATTRIBUTES : buf.st_mode;
-}
-
-static inline void
-set_file_attributes(const gchar *filename, FileAttributes attrs)
-{
- g_chmod(filename, attrs);
-}
-
-#endif /* !G_OS_WIN32 */
-
-/**
- * Loads the view's document by reading all data from
- * a GIOChannel.
- * The EOL style is guessed from the channel's data
- * (if AUTOEOL is enabled).
- * This assumes that the channel is blocking.
- * Also it tries to guess the size of the file behind
- * channel in order to preallocate memory in Scintilla.
- *
- * Any error reading the GIOChannel is propagated as
- * an exception.
- *
- * @param channel Channel to read from.
- */
-void
-IOView::load(GIOChannel *channel)
-{
- GStatBuf stat_buf;
-
- EOLReaderGIO reader(channel);
-
- ssm(SCI_BEGINUNDOACTION);
- ssm(SCI_CLEARALL);
-
- /*
- * Preallocate memory based on the file size.
- * May waste a few bytes if file contains DOS EOLs
- * and EOL translation is enabled, but is faster.
- * NOTE: g_io_channel_unix_get_fd() should report the correct fd
- * on Windows, too.
- */
- stat_buf.st_size = 0;
- if (!fstat(g_io_channel_unix_get_fd(channel), &stat_buf) &&
- stat_buf.st_size > 0)
- ssm(SCI_ALLOCATE, stat_buf.st_size);
-
- try {
- const gchar *data;
- gsize data_len;
-
- while ((data = reader.convert(data_len)))
- ssm(SCI_APPENDTEXT, data_len, (sptr_t)data);
- } catch (...) {
- ssm(SCI_ENDUNDOACTION);
- throw; /* forward */
- }
-
- /*
- * EOL-style guessed.
- * Save it as the buffer's EOL mode, so save()
- * can restore the original EOL-style.
- * If auto-EOL-translation is disabled, this cannot
- * have been guessed and the buffer's EOL mode should
- * have a platform default.
- * If it is enabled but the stream does not contain any
- * EOL characters, the platform default is still assumed.
- */
- if (reader.eol_style >= 0)
- ssm(SCI_SETEOLMODE, reader.eol_style);
-
- if (reader.eol_style_inconsistent)
- interface.msg(InterfaceCurrent::MSG_WARNING,
- "Inconsistent EOL styles normalized");
-
- ssm(SCI_ENDUNDOACTION);
-}
-
-/**
- * Load view's document from file.
- */
-void
-IOView::load(const gchar *filename)
-{
- GError *error = NULL;
- GIOChannel *channel;
-
- channel = g_io_channel_new_file(filename, "r", &error);
- if (!channel) {
- Error err("Error opening file \"%s\" for reading: %s",
- filename, error->message);
- g_error_free(error);
- throw err;
- }
-
- /*
- * The file loading algorithm does not need buffered
- * streams, so disabling buffering should increase
- * performance (slightly).
- */
- g_io_channel_set_encoding(channel, NULL, NULL);
- g_io_channel_set_buffered(channel, FALSE);
-
- try {
- load(channel);
- } catch (Error &e) {
- Error err("Error reading file \"%s\": %s",
- filename, e.description);
- g_io_channel_unref(channel);
- throw err;
- }
-
- /* also closes file: */
- g_io_channel_unref(channel);
-}
-
-#if 0
-
-/*
- * TODO: on UNIX it may be better to open() the current file, unlink() it
- * and keep the file descriptor in the UndoToken.
- * When the operation is undone, the file descriptor's contents are written to
- * the file (which should be efficient enough because it is written to the same
- * filesystem). This way we could avoid messing around with save point files.
- */
-
-#else
-
-static gint savepoint_id = 0;
-
-class UndoTokenRestoreSavePoint : public UndoToken {
- gchar *savepoint;
- gchar *filename;
-
-#ifdef G_OS_WIN32
- FileAttributes orig_attrs;
-#endif
-
-public:
- UndoTokenRestoreSavePoint(gchar *_savepoint, const gchar *_filename)
- : savepoint(_savepoint), filename(g_strdup(_filename))
- {
-#ifdef G_OS_WIN32
- orig_attrs = get_file_attributes(filename);
- if (orig_attrs != INVALID_FILE_ATTRIBUTES)
- set_file_attributes(savepoint,
- orig_attrs | FILE_ATTRIBUTE_HIDDEN);
-#endif
- }
-
- ~UndoTokenRestoreSavePoint()
- {
- if (savepoint) {
- g_unlink(savepoint);
- g_free(savepoint);
- }
- g_free(filename);
-
- savepoint_id--;
- }
-
- void
- run(void)
- {
- if (!g_rename(savepoint, filename)) {
- g_free(savepoint);
- savepoint = NULL;
-#ifdef G_OS_WIN32
- if (orig_attrs != INVALID_FILE_ATTRIBUTES)
- set_file_attributes(filename,
- orig_attrs);
-#endif
- } else {
- interface.msg(InterfaceCurrent::MSG_WARNING,
- "Unable to restore save point file \"%s\"",
- savepoint);
- }
- }
-};
-
-static void
-make_savepoint(const gchar *filename)
-{
- gchar *dirname, *basename, *savepoint;
- gchar savepoint_basename[FILENAME_MAX];
-
- basename = g_path_get_basename(filename);
- g_snprintf(savepoint_basename, sizeof(savepoint_basename),
- ".teco-%d-%s~", savepoint_id, basename);
- g_free(basename);
- dirname = g_path_get_dirname(filename);
- savepoint = g_build_filename(dirname, savepoint_basename, NIL);
- g_free(dirname);
-
- if (g_rename(filename, savepoint)) {
- interface.msg(InterfaceCurrent::MSG_WARNING,
- "Unable to create save point file \"%s\"",
- savepoint);
- g_free(savepoint);
- return;
- }
- savepoint_id++;
-
- /*
- * NOTE: passes ownership of savepoint string to undo token.
- */
- undo.push_own<UndoTokenRestoreSavePoint>(savepoint, filename);
-}
-
-#endif
-
-void
-IOView::save(GIOChannel *channel)
-{
- EOLWriterGIO writer(channel, ssm(SCI_GETEOLMODE));
- sptr_t gap;
- gsize size;
- const gchar *buffer;
- gsize bytes_written;
-
- /* write part of buffer before gap */
- gap = ssm(SCI_GETGAPPOSITION);
- if (gap > 0) {
- buffer = (const gchar *)ssm(SCI_GETRANGEPOINTER, 0, gap);
- bytes_written = writer.convert(buffer, gap);
- g_assert(bytes_written == (gsize)gap);
- }
-
- /* write part of buffer after gap */
- size = ssm(SCI_GETLENGTH) - gap;
- if (size > 0) {
- buffer = (const gchar *)ssm(SCI_GETRANGEPOINTER, gap, (sptr_t)size);
- bytes_written = writer.convert(buffer, size);
- g_assert(bytes_written == size);
- }
-}
-
-void
-IOView::save(const gchar *filename)
-{
- GError *error = NULL;
- GIOChannel *channel;
-
-#if defined(G_OS_UNIX) || defined(G_OS_HAIKU)
- GStatBuf file_stat;
- file_stat.st_uid = -1;
- file_stat.st_gid = -1;
-#endif
- FileAttributes attributes = INVALID_FILE_ATTRIBUTES;
-
- if (undo.enabled) {
- if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
-#if defined(G_OS_UNIX) || defined(G_OS_HAIKU)
- g_stat(filename, &file_stat);
-#endif
- attributes = get_file_attributes(filename);
- make_savepoint(filename);
- } else {
- undo.push<UndoTokenRemoveFile>(filename);
- }
- }
-
- /* leaves access mode intact if file still exists */
- channel = g_io_channel_new_file(filename, "w", &error);
- if (!channel)
- throw GlibError(error);
-
- /*
- * save(GIOChannel *, const gchar *) expects a buffered
- * and blocking channel
- */
- g_io_channel_set_encoding(channel, NULL, NULL);
- g_io_channel_set_buffered(channel, TRUE);
-
- try {
- save(channel);
- } catch (Error &e) {
- Error err("Error writing file \"%s\": %s", filename, e.description);
- g_io_channel_unref(channel);
- throw err;
- }
-
- /* if file existed but has been renamed, restore attributes */
- if (attributes != INVALID_FILE_ATTRIBUTES)
- set_file_attributes(filename, attributes);
-#if defined(G_OS_UNIX) || defined(G_OS_HAIKU)
- /*
- * only a good try to inherit owner since process user must have
- * CHOWN capability traditionally reserved to root only.
- * FIXME: We should probably fall back to another save point
- * strategy.
- */
- if (fchown(g_io_channel_unix_get_fd(channel),
- file_stat.st_uid, file_stat.st_gid))
- interface.msg(InterfaceCurrent::MSG_WARNING,
- "Unable to preserve owner of \"%s\": %s",
- filename, g_strerror(errno));
-#endif
-
- /* also closes file */
- g_io_channel_unref(channel);
-}
-
-/*
- * Auxiliary functions
- */
-
-/**
- * Perform tilde expansion on a file name or path.
- *
- * This supports only strings with a "~" prefix.
- * A user name after "~" is not supported.
- * The $HOME environment variable/register is used to retrieve
- * the current user's home directory.
- */
-gchar *
-expand_path(const gchar *path)
-{
- gchar *home, *ret;
-
- if (!path)
- path = "";
-
- if (path[0] != '~' || (path[1] && !G_IS_DIR_SEPARATOR(path[1])))
- return g_strdup(path);
-
- /*
- * $HOME should not have a trailing directory separator since
- * it is canonicalized to an absolute path at startup,
- * but this ensures that a proper path is constructed even if
- * it does (e.g. $HOME is changed later on).
- */
- home = QRegisters::globals["$HOME"]->get_string();
- ret = g_build_filename(home, path+1, NIL);
- g_free(home);
-
- return ret;
-}
-
-#if defined(G_OS_UNIX) || defined(G_OS_HAIKU)
-
-gchar *
-get_absolute_path(const gchar *path)
-{
- gchar buf[PATH_MAX];
- gchar *resolved;
-
- if (!path)
- return NULL;
-
- if (realpath(path, buf)) {
- resolved = g_strdup(buf);
- } else if (g_path_is_absolute(path)) {
- resolved = g_strdup(path);
- } else {
- gchar *cwd = g_get_current_dir();
- resolved = g_build_filename(cwd, path, NIL);
- g_free(cwd);
- }
-
- return resolved;
-}
-
-bool
-file_is_visible(const gchar *path)
-{
- gchar *basename = g_path_get_basename(path);
- bool ret = *basename != '.';
-
- g_free(basename);
- return ret;
-}
-
-#elif defined(G_OS_WIN32)
-
-gchar *
-get_absolute_path(const gchar *path)
-{
- TCHAR buf[MAX_PATH];
- gchar *resolved = NULL;
-
- if (path && GetFullPathName(path, sizeof(buf), buf, NULL))
- resolved = g_strdup(buf);
-
- return resolved;
-}
-
-bool
-file_is_visible(const gchar *path)
-{
- return !(get_file_attributes(path) & FILE_ATTRIBUTE_HIDDEN);
-}
-
-#else /* !G_OS_UNIX && !G_OS_HAIKU && !G_OS_WIN32 */
-
-/*
- * This will never canonicalize relative paths.
- * I.e. the absolute path will often contain
- * relative components, even if `path` exists.
- * The only exception would be a simple filename
- * not containing any "..".
- */
-gchar *
-get_absolute_path(const gchar *path)
-{
- gchar *resolved;
-
- if (!path)
- return NULL;
-
- if (g_path_is_absolute(path)) {
- resolved = g_strdup(path);
- } else {
- gchar *cwd = g_get_current_dir();
- resolved = g_build_filename(cwd, path, NIL);
- g_free(cwd);
- }
-
- return resolved;
-}
-
-/*
- * There's no platform-independent way to determine if a file
- * is visible/hidden, so we just assume that all files are
- * visible.
- */
-bool
-file_is_visible(const gchar *path)
-{
- return true;
-}
-
-#endif /* !G_OS_UNIX && !G_OS_HAIKU && !G_OS_WIN32 */
-
-} /* namespace SciTECO */