aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2016-01-31 06:58:18 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2016-01-31 06:58:18 +0100
commitd7e4aa16ecb0595ff0248e17fcdcfc09c7616ca0 (patch)
tree6903f426e8ee97d79c30626050a67d3686ce97cb /src
parent406cf5a58b5873f89df710d56883039ff496580e (diff)
downloadsciteco-d7e4aa16ecb0595ff0248e17fcdcfc09c7616ca0.tar.gz
CursesInfoPopup: separated the Curses popup widget from the rest of the UI code
* this has been prepared a long time ago * the popup widget does not in any way depend on the InterfaceCurses class and could be used elsewhere. * common and generic Curses drawing functions required by both the Curses UI and the CursesInfoPopup widget have been factored out into curses-utils.cpp (namespace Curses) * this improved the UI-logic separation and helped in making interface-curses.cpp smaller
Diffstat (limited to 'src')
-rw-r--r--src/interface-curses/Makefile.am4
-rw-r--r--src/interface-curses/curses-info-popup.cpp219
-rw-r--r--src/interface-curses/curses-info-popup.h89
-rw-r--r--src/interface-curses/curses-utils.cpp152
-rw-r--r--src/interface-curses/curses-utils.h39
-rw-r--r--src/interface-curses/interface-curses.cpp316
-rw-r--r--src/interface-curses/interface-curses.h51
7 files changed, 514 insertions, 356 deletions
diff --git a/src/interface-curses/Makefile.am b/src/interface-curses/Makefile.am
index a64694c..44e94da 100644
--- a/src/interface-curses/Makefile.am
+++ b/src/interface-curses/Makefile.am
@@ -6,4 +6,6 @@ AM_CXXFLAGS += -Wno-mismatched-tags
endif
noinst_LTLIBRARIES = libsciteco-interface.la
-libsciteco_interface_la_SOURCES = interface-curses.cpp interface-curses.h
+libsciteco_interface_la_SOURCES = interface-curses.cpp interface-curses.h \
+ curses-utils.cpp curses-utils.h \
+ curses-info-popup.cpp curses-info-popup.h
diff --git a/src/interface-curses/curses-info-popup.cpp b/src/interface-curses/curses-info-popup.cpp
new file mode 100644
index 0000000..7fb5110
--- /dev/null
+++ b/src/interface-curses/curses-info-popup.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2012-2016 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 <string.h>
+
+#include <glib.h>
+
+#include <curses.h>
+
+#include "curses-utils.h"
+#include "curses-info-popup.h"
+
+namespace SciTECO {
+
+void
+CursesInfoPopup::add(PopupEntryType type,
+ const gchar *name, bool highlight)
+{
+ size_t name_len = strlen(name);
+ Entry *entry = (Entry *)g_malloc(sizeof(Entry) + name_len + 1);
+
+ entry->type = type;
+ entry->highlight = highlight;
+ strcpy(entry->name, name);
+
+ longest = MAX(longest, (gint)name_len);
+ length++;
+
+ /*
+ * Entries are added in reverse (constant time for GSList),
+ * so they will later have to be reversed.
+ */
+ list = g_slist_prepend(list, entry);
+}
+
+void
+CursesInfoPopup::init_pad(attr_t attr)
+{
+ int cols = getmaxx(stdscr); /* screen width */
+ int pad_lines; /* pad height */
+ gint pad_cols; /* entry columns */
+ gint pad_colwidth; /* width per entry column */
+
+ gint cur_col;
+
+ /* reserve 2 spaces between columns */
+ pad_colwidth = MIN(longest + 2, cols - 2);
+
+ /* pad_cols = floor((cols - 2) / pad_colwidth) */
+ pad_cols = (cols - 2) / pad_colwidth;
+ /* pad_lines = ceil(length / pad_cols) */
+ pad_lines = (length+pad_cols-1) / pad_cols;
+
+ /*
+ * Render the entire autocompletion list into a pad
+ * which can be higher than the physical screen.
+ * The pad uses two columns less than the screen since
+ * it will be drawn into the popup window which has left
+ * and right borders.
+ */
+ pad = newpad(pad_lines, cols - 2);
+
+ wbkgd(pad, ' ' | attr);
+
+ /*
+ * cur_col is the row currently written.
+ * It does not wrap but grows indefinitely.
+ * Therefore the real current row is (cur_col % popup_cols)
+ */
+ cur_col = 0;
+ for (GSList *cur = list; cur != NULL; cur = g_slist_next(cur)) {
+ Entry *entry = (Entry *)cur->data;
+ gint cur_line = cur_col/pad_cols + 1;
+
+ wmove(pad, cur_line-1,
+ (cur_col % pad_cols)*pad_colwidth);
+
+ wattrset(pad, entry->highlight ? A_BOLD : A_NORMAL);
+
+ switch (entry->type) {
+ case POPUP_FILE:
+ case POPUP_DIRECTORY:
+ Curses::format_filename(pad, entry->name);
+ break;
+ default:
+ Curses::format_str(pad, entry->name);
+ break;
+ }
+
+ cur_col++;
+ }
+}
+
+void
+CursesInfoPopup::show(attr_t attr)
+{
+ int lines, cols; /* screen dimensions */
+ gint pad_lines;
+ gint popup_lines;
+ gint bar_height, bar_y;
+
+ if (!length)
+ /* nothing to display */
+ return;
+
+ getmaxyx(stdscr, lines, cols);
+
+ if (window)
+ delwin(window);
+ else
+ /* reverse list only once */
+ list = g_slist_reverse(list);
+
+ if (!pad)
+ init_pad(attr);
+ pad_lines = getmaxy(pad);
+
+ /*
+ * Popup window can cover all but one screen row.
+ * Another row is reserved for the top border.
+ */
+ popup_lines = MIN(pad_lines + 1, lines - 1);
+
+ /* window covers message, scintilla and info windows */
+ window = newwin(popup_lines, 0, lines - 1 - popup_lines, 0);
+
+ wbkgdset(window, ' ' | attr);
+
+ wborder(window,
+ ACS_VLINE,
+ ACS_VLINE, /* may be overwritten with scrollbar */
+ ACS_HLINE,
+ ' ', /* no bottom line */
+ ACS_ULCORNER, ACS_URCORNER,
+ ACS_VLINE, ACS_VLINE);
+
+ copywin(pad, window,
+ pad_first_line, 0,
+ 1, 1, popup_lines - 1, cols - 2, FALSE);
+
+ if (pad_lines <= popup_lines - 1)
+ /* no need for scrollbar */
+ return;
+
+ /* bar_height = ceil((popup_lines-1)/pad_lines * (popup_lines-2)) */
+ bar_height = ((popup_lines-1)*(popup_lines-2) + pad_lines-1) /
+ pad_lines;
+ /* bar_y = floor(pad_first_line/pad_lines * (popup_lines-2)) + 1 */
+ bar_y = pad_first_line*(popup_lines-2) / pad_lines + 1;
+
+ mvwvline(window, 1, cols-1, ACS_CKBOARD, popup_lines-2);
+ /*
+ * We do not use ACS_BLOCK here since it will not
+ * always be drawn as a solid block (e.g. xterm).
+ * Instead, simply draw reverse blanks.
+ */
+ wmove(window, bar_y, cols-1);
+ wattron(window, A_REVERSE);
+ wvline(window, ' ', bar_height);
+
+ /* progress scroll position */
+ pad_first_line += popup_lines - 1;
+ /* wrap on last shown page */
+ pad_first_line %= pad_lines;
+ if (pad_lines - pad_first_line < popup_lines - 1)
+ /* show last page */
+ pad_first_line = pad_lines - (popup_lines - 1);
+}
+
+void
+CursesInfoPopup::clear(void)
+{
+ g_slist_free_full(list, g_free);
+ list = NULL;
+ length = 0;
+ longest = 0;
+
+ pad_first_line = 0;
+
+ if (window) {
+ delwin(window);
+ window = NULL;
+ }
+
+ if (pad) {
+ delwin(pad);
+ pad = NULL;
+ }
+}
+
+CursesInfoPopup::~CursesInfoPopup()
+{
+ if (window)
+ delwin(window);
+ if (pad)
+ delwin(pad);
+ if (list)
+ g_slist_free_full(list, g_free);
+}
+
+} /* namespace SciTECO */
diff --git a/src/interface-curses/curses-info-popup.h b/src/interface-curses/curses-info-popup.h
new file mode 100644
index 0000000..01afc1f
--- /dev/null
+++ b/src/interface-curses/curses-info-popup.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012-2016 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/>.
+ */
+
+#ifndef __CURSES_INFO_POPUP_H
+#define __CURSES_INFO_POPUP_H
+
+#include <glib.h>
+
+#include <curses.h>
+
+namespace SciTECO {
+
+class CursesInfoPopup {
+public:
+ /**
+ * @bug This is identical to the type defined in
+ * interface.h. But for the sake of abstraction
+ * we cannot access it here (or in gtk-info-popup
+ * for that matter).
+ */
+ enum PopupEntryType {
+ POPUP_PLAIN,
+ POPUP_FILE,
+ POPUP_DIRECTORY
+ };
+
+private:
+ WINDOW *window; /**! window showing part of pad */
+ WINDOW *pad; /**! full-height entry list */
+
+ struct Entry {
+ PopupEntryType type;
+ bool highlight;
+ gchar name[];
+ };
+
+ GSList *list; /**! list of popup entries */
+ gint longest; /**! size of longest entry */
+ gint length; /**! total number of popup entries */
+
+ gint pad_first_line; /**! first line in pad to show */
+
+public:
+ CursesInfoPopup() : window(NULL), pad(NULL),
+ list(NULL), longest(0), length(0),
+ pad_first_line(0) {}
+
+ void add(PopupEntryType type,
+ const gchar *name, bool highlight = false);
+
+ void show(attr_t attr);
+ inline bool
+ is_shown(void)
+ {
+ return window != NULL;
+ }
+
+ void clear(void);
+
+ inline void
+ noutrefresh(void)
+ {
+ if (window)
+ wnoutrefresh(window);
+ }
+
+ ~CursesInfoPopup();
+
+private:
+ void init_pad(attr_t attr);
+};
+
+} /* namespace SciTECO */
+
+#endif
diff --git a/src/interface-curses/curses-utils.cpp b/src/interface-curses/curses-utils.cpp
new file mode 100644
index 0000000..add9a69
--- /dev/null
+++ b/src/interface-curses/curses-utils.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012-2016 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 <string.h>
+
+#include <glib.h>
+
+#include <curses.h>
+
+#include "sciteco.h"
+#include "string-utils.h"
+#include "curses-utils.h"
+
+namespace SciTECO {
+
+gsize
+Curses::format_str(WINDOW *win, const gchar *str,
+ gssize len, gint max_width)
+{
+ int old_x, old_y;
+ gint chars_added = 0;
+
+ getyx(win, old_y, old_x);
+
+ if (len < 0)
+ len = strlen(str);
+ if (max_width < 0)
+ max_width = getmaxx(win) - old_x;
+
+ while (len > 0) {
+ /*
+ * NOTE: This mapping is similar to
+ * View::set_representations()
+ */
+ switch (*str) {
+ case CTL_KEY_ESC:
+ chars_added++;
+ if (chars_added > max_width)
+ goto truncate;
+ waddch(win, '$' | A_REVERSE);
+ break;
+ case '\r':
+ chars_added += 2;
+ if (chars_added > max_width)
+ goto truncate;
+ waddch(win, 'C' | A_REVERSE);
+ waddch(win, 'R' | A_REVERSE);
+ break;
+ case '\n':
+ chars_added += 2;
+ if (chars_added > max_width)
+ goto truncate;
+ waddch(win, 'L' | A_REVERSE);
+ waddch(win, 'F' | A_REVERSE);
+ break;
+ case '\t':
+ chars_added += 3;
+ if (chars_added > max_width)
+ goto truncate;
+ waddch(win, 'T' | A_REVERSE);
+ waddch(win, 'A' | A_REVERSE);
+ waddch(win, 'B' | A_REVERSE);
+ break;
+ default:
+ if (IS_CTL(*str)) {
+ chars_added += 2;
+ if (chars_added > max_width)
+ goto truncate;
+ waddch(win, '^' | A_REVERSE);
+ waddch(win, CTL_ECHO(*str) | A_REVERSE);
+ } else {
+ chars_added++;
+ if (chars_added > max_width)
+ goto truncate;
+ waddch(win, *str);
+ }
+ }
+
+ str++;
+ len--;
+ }
+
+ return getcurx(win) - old_x;
+
+truncate:
+ if (max_width >= 3) {
+ /*
+ * Truncate string
+ */
+ wattron(win, A_UNDERLINE | A_BOLD);
+ mvwaddstr(win, old_y, old_x + max_width - 3, "...");
+ wattroff(win, A_UNDERLINE | A_BOLD);
+ }
+
+ return getcurx(win) - old_x;
+}
+
+gsize
+Curses::format_filename(WINDOW *win, const gchar *filename,
+ gint max_width)
+{
+ int old_x = getcurx(win);
+
+ gchar *filename_canon = String::canonicalize_ctl(filename);
+ size_t filename_len = strlen(filename_canon);
+
+ if (max_width < 0)
+ max_width = getmaxx(win) - old_x;
+
+ if (filename_len <= (size_t)max_width) {
+ waddstr(win, filename_canon);
+ } else {
+ const gchar *keep_post = filename_canon + filename_len -
+ max_width + 3;
+
+#ifdef G_OS_WIN32
+ const gchar *keep_pre = g_path_skip_root(filename_canon);
+ if (keep_pre) {
+ waddnstr(win, filename_canon,
+ keep_pre - filename_canon);
+ keep_post += keep_pre - filename_canon;
+ }
+#endif
+ wattron(win, A_UNDERLINE | A_BOLD);
+ waddstr(win, "...");
+ wattroff(win, A_UNDERLINE | A_BOLD);
+ waddstr(win, keep_post);
+ }
+
+ g_free(filename_canon);
+ return getcurx(win) - old_x;
+}
+
+} /* namespace SciTECO */
diff --git a/src/interface-curses/curses-utils.h b/src/interface-curses/curses-utils.h
new file mode 100644
index 0000000..abaa8e4
--- /dev/null
+++ b/src/interface-curses/curses-utils.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012-2016 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/>.
+ */
+
+#ifndef __CURSES_UTILS_H
+#define __CURSES_UTILS_H
+
+#include <glib.h>
+
+#include <curses.h>
+
+namespace SciTECO {
+
+namespace Curses {
+
+gsize format_str(WINDOW *win, const gchar *str,
+ gssize len = -1, gint max_width = -1);
+
+gsize format_filename(WINDOW *win, const gchar *filename,
+ gint max_width = -1);
+
+} /* namespace Curses */
+
+} /* namespace SciTECO */
+
+#endif
diff --git a/src/interface-curses/interface-curses.cpp b/src/interface-curses/interface-curses.cpp
index 49339d4..fa1cc97 100644
--- a/src/interface-curses/interface-curses.cpp
+++ b/src/interface-curses/interface-curses.cpp
@@ -56,6 +56,8 @@
#include "ring.h"
#include "interface.h"
#include "interface-curses.h"
+#include "curses-utils.h"
+#include "curses-info-popup.h"
#ifdef HAVE_WINDOWS_H
/* here it shouldn't cause conflicts with other headers */
@@ -243,124 +245,6 @@ rgb2curses(guint32 rgb)
return COLOR_WHITE;
}
-static gsize
-format_str(WINDOW *win, const gchar *str,
- gssize len = -1, gint max_width = -1)
-{
- int old_x, old_y;
- gint chars_added = 0;
-
- getyx(win, old_y, old_x);
-
- if (len < 0)
- len = strlen(str);
- if (max_width < 0)
- max_width = getmaxx(win) - old_x;
-
- while (len > 0) {
- /*
- * NOTE: This mapping is similar to
- * View::set_representations()
- */
- switch (*str) {
- case CTL_KEY_ESC:
- chars_added++;
- if (chars_added > max_width)
- goto truncate;
- waddch(win, '$' | A_REVERSE);
- break;
- case '\r':
- chars_added += 2;
- if (chars_added > max_width)
- goto truncate;
- waddch(win, 'C' | A_REVERSE);
- waddch(win, 'R' | A_REVERSE);
- break;
- case '\n':
- chars_added += 2;
- if (chars_added > max_width)
- goto truncate;
- waddch(win, 'L' | A_REVERSE);
- waddch(win, 'F' | A_REVERSE);
- break;
- case '\t':
- chars_added += 3;
- if (chars_added > max_width)
- goto truncate;
- waddch(win, 'T' | A_REVERSE);
- waddch(win, 'A' | A_REVERSE);
- waddch(win, 'B' | A_REVERSE);
- break;
- default:
- if (IS_CTL(*str)) {
- chars_added += 2;
- if (chars_added > max_width)
- goto truncate;
- waddch(win, '^' | A_REVERSE);
- waddch(win, CTL_ECHO(*str) | A_REVERSE);
- } else {
- chars_added++;
- if (chars_added > max_width)
- goto truncate;
- waddch(win, *str);
- }
- }
-
- str++;
- len--;
- }
-
- return getcurx(win) - old_x;
-
-truncate:
- if (max_width >= 3) {
- /*
- * Truncate string
- */
- wattron(win, A_UNDERLINE | A_BOLD);
- mvwaddstr(win, old_y, old_x + max_width - 3, "...");
- wattroff(win, A_UNDERLINE | A_BOLD);
- }
-
- return getcurx(win) - old_x;
-}
-
-static gsize
-format_filename(WINDOW *win, const gchar *filename,
- gint max_width = -1)
-{
- int old_x = getcurx(win);
-
- gchar *filename_canon = String::canonicalize_ctl(filename);
- size_t filename_len = strlen(filename_canon);
-
- if (max_width < 0)
- max_width = getmaxx(win) - old_x;
-
- if (filename_len <= (size_t)max_width) {
- waddstr(win, filename_canon);
- } else {
- const gchar *keep_post = filename_canon + filename_len -
- max_width + 3;
-
-#ifdef G_OS_WIN32
- const gchar *keep_pre = g_path_skip_root(filename_canon);
- if (keep_pre) {
- waddnstr(win, filename_canon,
- keep_pre - filename_canon);
- keep_post += keep_pre - filename_canon;
- }
-#endif
- wattron(win, A_UNDERLINE | A_BOLD);
- waddstr(win, "...");
- wattroff(win, A_UNDERLINE | A_BOLD);
- waddstr(win, keep_post);
- }
-
- g_free(filename_canon);
- return getcurx(win) - old_x;
-}
-
void
ViewCurses::initialize_impl(void)
{
@@ -385,192 +269,6 @@ InterfaceCurses::InterfaceCurses() : stdout_orig(-1), stderr_orig(-1),
}
void
-InterfaceCurses::Popup::add(PopupEntryType type,
- const gchar *name, bool highlight)
-{
- size_t name_len = strlen(name);
- Entry *entry = (Entry *)g_malloc(sizeof(Entry) + name_len + 1);
-
- entry->type = type;
- entry->highlight = highlight;
- strcpy(entry->name, name);
-
- longest = MAX(longest, (gint)name_len);
- length++;
-
- /*
- * Entries are added in reverse (constant time for GSList),
- * so they will later have to be reversed.
- */
- list = g_slist_prepend(list, entry);
-}
-
-void
-InterfaceCurses::Popup::init_pad(attr_t attr)
-{
- int cols = getmaxx(stdscr); /* screen width */
- int pad_lines; /* pad height */
- gint pad_cols; /* entry columns */
- gint pad_colwidth; /* width per entry column */
-
- gint cur_col;
-
- /* reserve 2 spaces between columns */
- pad_colwidth = MIN(longest + 2, cols - 2);
-
- /* pad_cols = floor((cols - 2) / pad_colwidth) */
- pad_cols = (cols - 2) / pad_colwidth;
- /* pad_lines = ceil(length / pad_cols) */
- pad_lines = (length+pad_cols-1) / pad_cols;
-
- /*
- * Render the entire autocompletion list into a pad
- * which can be higher than the physical screen.
- * The pad uses two columns less than the screen since
- * it will be drawn into the popup window which has left
- * and right borders.
- */
- pad = newpad(pad_lines, cols - 2);
-
- wbkgd(pad, ' ' | attr);
-
- /*
- * cur_col is the row currently written.
- * It does not wrap but grows indefinitely.
- * Therefore the real current row is (cur_col % popup_cols)
- */
- cur_col = 0;
- for (GSList *cur = list; cur != NULL; cur = g_slist_next(cur)) {
- Entry *entry = (Entry *)cur->data;
- gint cur_line = cur_col/pad_cols + 1;
-
- wmove(pad, cur_line-1,
- (cur_col % pad_cols)*pad_colwidth);
-
- wattrset(pad, entry->highlight ? A_BOLD : A_NORMAL);
-
- switch (entry->type) {
- case POPUP_FILE:
- case POPUP_DIRECTORY:
- format_filename(pad, entry->name);
- break;
- default:
- format_str(pad, entry->name);
- break;
- }
-
- cur_col++;
- }
-}
-
-void
-InterfaceCurses::Popup::show(attr_t attr)
-{
- int lines, cols; /* screen dimensions */
- gint pad_lines;
- gint popup_lines;
- gint bar_height, bar_y;
-
- if (!length)
- /* nothing to display */
- return;
-
- getmaxyx(stdscr, lines, cols);
-
- if (window)
- delwin(window);
- else
- /* reverse list only once */
- list = g_slist_reverse(list);
-
- if (!pad)
- init_pad(attr);
- pad_lines = getmaxy(pad);
-
- /*
- * Popup window can cover all but one screen row.
- * Another row is reserved for the top border.
- */
- popup_lines = MIN(pad_lines + 1, lines - 1);
-
- /* window covers message, scintilla and info windows */
- window = newwin(popup_lines, 0, lines - 1 - popup_lines, 0);
-
- wbkgdset(window, ' ' | attr);
-
- wborder(window,
- ACS_VLINE,
- ACS_VLINE, /* may be overwritten with scrollbar */
- ACS_HLINE,
- ' ', /* no bottom line */
- ACS_ULCORNER, ACS_URCORNER,
- ACS_VLINE, ACS_VLINE);
-
- copywin(pad, window,
- pad_first_line, 0,
- 1, 1, popup_lines - 1, cols - 2, FALSE);
-
- if (pad_lines <= popup_lines - 1)
- /* no need for scrollbar */
- return;
-
- /* bar_height = ceil((popup_lines-1)/pad_lines * (popup_lines-2)) */
- bar_height = ((popup_lines-1)*(popup_lines-2) + pad_lines-1) /
- pad_lines;
- /* bar_y = floor(pad_first_line/pad_lines * (popup_lines-2)) + 1 */
- bar_y = pad_first_line*(popup_lines-2) / pad_lines + 1;
-
- mvwvline(window, 1, cols-1, ACS_CKBOARD, popup_lines-2);
- /*
- * We do not use ACS_BLOCK here since it will not
- * always be drawn as a solid block (e.g. xterm).
- * Instead, simply draw reverse blanks.
- */
- wmove(window, bar_y, cols-1);
- wattron(window, A_REVERSE);
- wvline(window, ' ', bar_height);
-
- /* progress scroll position */
- pad_first_line += popup_lines - 1;
- /* wrap on last shown page */
- pad_first_line %= pad_lines;
- if (pad_lines - pad_first_line < popup_lines - 1)
- /* show last page */
- pad_first_line = pad_lines - (popup_lines - 1);
-}
-
-void
-InterfaceCurses::Popup::clear(void)
-{
- g_slist_free_full(list, g_free);
- list = NULL;
- length = 0;
- longest = 0;
-
- pad_first_line = 0;
-
- if (window) {
- delwin(window);
- window = NULL;
- }
-
- if (pad) {
- delwin(pad);
- pad = NULL;
- }
-}
-
-InterfaceCurses::Popup::~Popup()
-{
- if (window)
- delwin(window);
- if (pad)
- delwin(pad);
- if (list)
- g_slist_free_full(list, g_free);
-}
-
-void
InterfaceCurses::main_impl(int &argc, char **&argv)
{
/*
@@ -1145,13 +843,13 @@ InterfaceCurses::draw_info(void)
info_type_str = PACKAGE_NAME " - <QRegister> ";
waddstr(info_window, info_type_str);
/* same formatting as in command lines */
- format_str(info_window, info_current);
+ Curses::format_str(info_window, info_current);
break;
case INFO_TYPE_BUFFER:
info_type_str = PACKAGE_NAME " - <Buffer> ";
waddstr(info_window, info_type_str);
- format_filename(info_window, info_current);
+ Curses::format_filename(info_window, info_current);
break;
default:
@@ -1215,7 +913,7 @@ InterfaceCurses::cmdline_update_impl(const Cmdline *cmdline)
wcolor_set(cmdline_pad, SCI_COLOR_PAIR(fg, bg), NULL);
/* format effective command line */
- cmdline_len = format_str(cmdline_pad, cmdline->str, cmdline->len);
+ cmdline_len = Curses::format_str(cmdline_pad, cmdline->str, cmdline->len);
/*
* A_BOLD should result in either a bold font or a brighter
@@ -1234,8 +932,8 @@ InterfaceCurses::cmdline_update_impl(const Cmdline *cmdline)
* NOTE: This formatting will never be truncated since we're
* writing into the pad which is large enough.
*/
- cmdline_rubout_len = format_str(cmdline_pad, cmdline->str + cmdline->len,
- cmdline->rubout_len);
+ cmdline_rubout_len = Curses::format_str(cmdline_pad, cmdline->str + cmdline->len,
+ cmdline->rubout_len);
/* highlight cursor after effective command line */
if (cmdline_rubout_len) {
diff --git a/src/interface-curses/interface-curses.h b/src/interface-curses/interface-curses.h
index a6b0e1c..f29b1b4 100644
--- a/src/interface-curses/interface-curses.h
+++ b/src/interface-curses/interface-curses.h
@@ -28,6 +28,7 @@
#include <ScintillaTerm.h>
#include "interface.h"
+#include "curses-info-popup.h"
namespace SciTECO {
@@ -114,51 +115,7 @@ typedef class InterfaceCurses : public Interface<InterfaceCurses, ViewCurses> {
WINDOW *cmdline_window, *cmdline_pad;
gsize cmdline_len, cmdline_rubout_len;
- class Popup {
- WINDOW *window; /**! window showing part of pad */
- WINDOW *pad; /**! full-height entry list */
-
- struct Entry {
- PopupEntryType type;
- bool highlight;
- gchar name[];
- };
-
- GSList *list; /**! list of popup entries */
- gint longest; /**! size of longest entry */
- gint length; /**! total number of popup entries */
-
- gint pad_first_line; /**! first line in pad to show */
-
- public:
- Popup() : window(NULL), pad(NULL),
- list(NULL), longest(0), length(0),
- pad_first_line(0) {}
-
- void add(PopupEntryType type,
- const gchar *name, bool highlight = false);
-
- void show(attr_t attr);
- inline bool
- is_shown(void)
- {
- return window != NULL;
- }
-
- void clear(void);
-
- inline void
- noutrefresh(void)
- {
- if (window)
- wnoutrefresh(window);
- }
-
- ~Popup();
-
- private:
- void init_pad(attr_t attr);
- } popup;
+ CursesInfoPopup popup;
public:
InterfaceCurses();
@@ -190,9 +147,11 @@ public:
popup_add_impl(PopupEntryType type,
const gchar *name, bool highlight = false)
{
+ /* FIXME: The enum casting is dangerous */
if (cmdline_window)
/* interactive mode */
- popup.add(type, name, highlight);
+ popup.add((CursesInfoPopup::PopupEntryType)type,
+ name, highlight);
}
/* implementation of Interface::popup_show() */