hscroll: move code to class BasicMarquee
authorMax Kellermann <max@musicpd.org>
Wed, 21 Feb 2018 20:00:34 +0000 (21:00 +0100)
committerMax Kellermann <max@musicpd.org>
Wed, 21 Feb 2018 20:15:06 +0000 (21:15 +0100)
meson.build
src/BasicMarquee.cxx [new file with mode: 0644]
src/BasicMarquee.hxx [new file with mode: 0644]
src/hscroll.cxx
src/hscroll.hxx
test/meson.build
test/run_hscroll.cxx

index ee16204..7910294 100644 (file)
@@ -222,6 +222,7 @@ if not mini
   sources += [
     'src/db_completion.cxx',
     'src/xterm_title.cxx',
+    'src/BasicMarquee.cxx',
     'src/hscroll.cxx',
     'src/match.cxx',
     'src/conf.cxx',
diff --git a/src/BasicMarquee.cxx b/src/BasicMarquee.cxx
new file mode 100644 (file)
index 0000000..9b5252a
--- /dev/null
@@ -0,0 +1,76 @@
+/* ncmpc (Ncurses MPD Client)
+ * (c) 2004-2018 The Music Player Daemon Project
+ * Project homepage: http://musicpd.org
+ *
+ * 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "BasicMarquee.hxx"
+#include "charset.hxx"
+
+#include <glib.h>
+
+#include <assert.h>
+#include <string.h>
+
+char *
+BasicMarquee::ScrollString()
+{
+       assert(text != nullptr);
+       assert(separator != nullptr);
+
+       /* create a buffer containing the string and the separator */
+       char *tmp = replace_locale_to_utf8(g_strconcat(text, separator,
+                                                      text, separator, nullptr));
+       if (offset >= (unsigned)g_utf8_strlen(tmp, -1) / 2)
+               offset = 0;
+
+       /* create the new scrolled string */
+       char *buf = g_utf8_offset_to_pointer(tmp, offset);
+       utf8_cut_width(buf, width);
+
+       /* convert back to locale */
+       buf = utf8_to_locale(buf);
+       g_free(tmp);
+       return buf;
+}
+
+bool
+BasicMarquee::Set(unsigned _width, const char *_text)
+{
+       assert(separator != nullptr);
+       assert(_text != nullptr);
+
+       if (text != nullptr && _width == width && strcmp(_text, text) == 0)
+               /* no change, do nothing (and, most importantly, do
+                  not reset the current offset!) */
+               return false;
+
+       Clear();
+
+       width = _width;
+
+       text = g_strdup(_text);
+       offset = 0;
+
+       return true;
+}
+
+void
+BasicMarquee::Clear()
+{
+       g_free(text);
+       text = nullptr;
+}
diff --git a/src/BasicMarquee.hxx b/src/BasicMarquee.hxx
new file mode 100644 (file)
index 0000000..93be628
--- /dev/null
@@ -0,0 +1,80 @@
+/* ncmpc (Ncurses MPD Client)
+ * (c) 2004-2018 The Music Player Daemon Project
+ * Project homepage: http://musicpd.org
+ *
+ * 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef BASIC_MARQUEE_HXX
+#define BASIC_MARQUEE_HXX
+
+/**
+ * This class is used to auto-scroll text which does not fit on the
+ * screen.  Call hscroll_init() to initialize the object,
+ * hscroll_clear() to free resources, and hscroll_set() to begin
+ * scrolling.
+ */
+class BasicMarquee {
+       const char *separator;
+
+       /**
+        * The available screen width (in cells).
+        */
+       unsigned width;
+
+       /**
+        * The scrolled text, in the current locale.
+        */
+       char *text = nullptr;
+
+       /**
+        * The current scrolling offset.  This is a character
+        * position, not a screen column.
+        */
+       unsigned offset;
+
+public:
+       void Init(const char *_separator) {
+               separator = _separator;
+       }
+
+       bool IsDefined() const {
+               return text != nullptr;
+       }
+
+       /**
+        * Sets a text to scroll.  Call Clear() to disable it.
+        *
+        * @return false if nothing was changed
+        */
+       bool Set(unsigned width, const char *text);
+
+       /**
+        * Removes the text.  It may be reused with Set().
+        */
+       void Clear();
+
+       void Rewind() {
+               offset = 0;
+       }
+
+       void Step() {
+               ++offset;
+       }
+
+       char *ScrollString();
+};
+
+#endif
index 7b4ef22..1052aa2 100644 (file)
 #include "charset.hxx"
 #include "ncfix.h"
 
-#include <assert.h>
-#include <string.h>
+#include <algorithm>
 
-char *
-hscroll::ScrollString()
-{
-       assert(text != nullptr);
-       assert(separator != nullptr);
-
-       /* create a buffer containing the string and the separator */
-       char *tmp = replace_locale_to_utf8(g_strconcat(text, separator,
-                                                      text, separator, nullptr));
-       if (offset >= (unsigned)g_utf8_strlen(tmp, -1) / 2)
-               offset = 0;
-
-       /* create the new scrolled string */
-       char *buf = g_utf8_offset_to_pointer(tmp, offset);
-       utf8_cut_width(buf, width);
-
-       /* convert back to locale */
-       buf = utf8_to_locale(buf);
-       g_free(tmp);
-       return buf;
-}
+#include <assert.h>
 
 gboolean
 hscroll::TimerCallback(gpointer data)
@@ -68,44 +47,34 @@ hscroll::Set(unsigned _x, unsigned _y, unsigned _width, const char *_text)
        assert(w != nullptr);
        assert(_text != nullptr);
 
-       if (text != nullptr && _x == x && _y == y &&
-           _width == width && strcmp(_text, text) == 0)
-               /* no change, do nothing (and, most importantly, do
-                  not reset the current offset!) */
-               return;
-
-       Clear();
-
        x = _x;
        y = _y;
-       width = _width;
+
+       if (!basic.Set(_width, _text))
+               return;
 
        /* obtain the ncurses attributes and the current color, store
           them */
        fix_wattr_get(w, &attrs, &pair, nullptr);
 
-       text = g_strdup(_text);
-       offset = 0;
-       source_id = g_timeout_add_seconds(1, TimerCallback, this);
+       if (source_id == 0)
+               source_id = g_timeout_add_seconds(1, TimerCallback, this);
 }
 
 void
 hscroll::Clear()
 {
-       if (text == nullptr)
-               return;
-
-       g_source_remove(source_id);
+       basic.Clear();
 
-       g_free(text);
-       text = nullptr;
+       if (source_id != 0)
+               g_source_remove(std::exchange(source_id, 0));
 }
 
 void
 hscroll::Paint()
 {
        assert(w != nullptr);
-       assert(text != nullptr);
+       assert(basic.IsDefined());
 
        /* set stored attributes and color */
        attr_t old_attrs;
@@ -114,7 +83,7 @@ hscroll::Paint()
        wattr_set(w, attrs, pair, nullptr);
 
        /* scroll the string, and draw it */
-       char *p = ScrollString();
+       char *p = basic.ScrollString();
        mvwaddstr(w, y, x, p);
        g_free(p);
 
index 82554c7..f2196ff 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "config.h"
 #include "ncmpc_curses.h"
+#include "BasicMarquee.hxx"
 
 #include <glib.h>
 
  */
 class hscroll {
        WINDOW *w;
-       const char *separator;
+
+       BasicMarquee basic;
 
        /**
-        * The bounding coordinates on the screen.
+        * The postion on the screen.
         */
-       unsigned x, y, width;
+       unsigned x, y;
 
        /**
         * ncurses attributes for drawing the text.
@@ -50,27 +52,16 @@ class hscroll {
         */
        short pair;
 
-       /**
-        * The scrolled text, in the current locale.
-        */
-       char *text = nullptr;
-
-       /**
-        * The current scrolling offset.  This is a character
-        * position, not a screen column.
-        */
-       gsize offset;
-
        /**
         * The id of the timer which updates the scrolled area every
         * second.
         */
-       guint source_id;
+       guint source_id = 0;
 
 public:
        void Init(WINDOW *_w, const char *_separator) {
                w = _w;
-               separator = _separator;
+               basic.Init(_separator);
        }
 
        /**
@@ -87,15 +78,13 @@ public:
        void Clear();
 
        void Rewind() {
-               offset = 0;
+               basic.Rewind();
        }
 
        void Step() {
-               ++offset;
+               basic.Step();
        }
 
-       char *ScrollString();
-
        /**
         * Explicitly draws the scrolled text.  Calling this function
         * is only allowed if there is a text currently.
index ca24524..e2001b4 100644 (file)
@@ -2,12 +2,11 @@ executable(
   'run_hscroll',
   'run_hscroll.cxx',
   objects: ncmpc.extract_objects(
-    'src/hscroll.cxx',
+    'src/BasicMarquee.cxx',
     'src/charset.cxx',
   ),
   include_directories: inc,
   dependencies: [
-    curses_dep,
     glib_dep,
   ],
 )
index c28c48f..3b644f6 100644 (file)
@@ -1,4 +1,4 @@
-#include "hscroll.hxx"
+#include "BasicMarquee.hxx"
 #include "config.h"
 
 #include <glib.h>
@@ -10,7 +10,6 @@
 
 int main(int argc, char **argv)
 {
-       struct hscroll hscroll;
        char *p;
        unsigned width, count;
 
@@ -26,8 +25,9 @@ int main(int argc, char **argv)
        width = atoi(argv[3]);
        count = atoi(argv[4]);
 
-       hscroll.Init(nullptr, argv[2]);
-       hscroll.Set(0, 0, width, argv[1]);
+       BasicMarquee hscroll;
+       hscroll.Init(argv[2]);
+       hscroll.Set(width, argv[1]);
 
        for (unsigned i = 0; i < count; ++i) {
                p = hscroll.ScrollString();