summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 140da05)
raw | patch | inline | side by side (parent: 140da05)
author | Max Kellermann <max@duempel.org> | |
Tue, 20 Oct 2009 06:00:13 +0000 (08:00 +0200) | ||
committer | Max Kellermann <max@duempel.org> | |
Tue, 20 Oct 2009 06:00:13 +0000 (08:00 +0200) |
The hscroll object knows the location on the screen and the text.
Upon initialization, it installs a GLib timer which updates the screen
every second.
Upon initialization, it installs a GLib timer which updates the screen
every second.
diff --git a/src/hscroll.c b/src/hscroll.c
index ace5bde9e4b4876cc33c98b7cf9ae719c768b6fc..32988d0fdf6b1b895415079a7610e56577413114 100644 (file)
--- a/src/hscroll.c
+++ b/src/hscroll.c
g_free(tmp);
return buf;
}
+
+/**
+ * This timer scrolls the area by one and redraws.
+ */
+static gboolean
+hscroll_timer_callback(gpointer data)
+{
+ struct hscroll *hscroll = data;
+
+ hscroll_step(hscroll);
+ hscroll_draw(hscroll);
+ wrefresh(hscroll->w);
+ return true;
+}
+
+void
+hscroll_set(struct hscroll *hscroll, unsigned x, unsigned y, unsigned width,
+ const char *text)
+{
+ assert(hscroll != NULL);
+ assert(hscroll->w != NULL);
+ assert(text != NULL);
+
+ if (hscroll->text != NULL && hscroll->x == x && hscroll->y == y &&
+ hscroll->width == width && strcmp(hscroll->text, text) == 0)
+ /* no change, do nothing (and, most importantly, do
+ not reset the current offset!) */
+ return;
+
+ hscroll_clear(hscroll);
+
+ hscroll->x = x;
+ hscroll->y = y;
+ hscroll->width = width;
+
+ /* obtain the ncurses attributes and the current color, store
+ them */
+ wattr_get(hscroll->w, &hscroll->attrs, &hscroll->pair, NULL);
+
+ hscroll->text = g_strdup(text);
+ hscroll->offset = 0;
+ hscroll->source_id = g_timeout_add_seconds(1, hscroll_timer_callback,
+ hscroll);
+}
+
+void
+hscroll_clear(struct hscroll *hscroll)
+{
+ assert(hscroll != NULL);
+
+ if (hscroll->text == NULL)
+ return;
+
+ g_source_remove(hscroll->source_id);
+
+ g_free(hscroll->text);
+ hscroll->text = NULL;
+}
+
+void
+hscroll_draw(struct hscroll *hscroll)
+{
+ attr_t old_attrs;
+ short old_pair;
+ char *p;
+
+ assert(hscroll != NULL);
+ assert(hscroll->w != NULL);
+ assert(hscroll->text != NULL);
+
+ /* set stored attributes and color */
+ wattr_get(hscroll->w, &old_attrs, &old_pair, NULL);
+ wattr_set(hscroll->w, hscroll->attrs, hscroll->pair, NULL);
+
+ /* scroll the string, and draw it */
+ p = strscroll(hscroll, hscroll->text, hscroll->separator,
+ hscroll->width);
+ mvwaddstr(hscroll->w, hscroll->y, hscroll->x, p);
+ g_free(p);
+
+ /* restore previous attributes and color */
+ wattr_set(hscroll->w, old_attrs, old_pair, NULL);
+}
diff --git a/src/hscroll.h b/src/hscroll.h
index d266c8a335d8b50e46a424ad5d8f97c0196e2eaa..b3047b5c4d5d39bdc39c6462b4024b2bbb7ce53d 100644 (file)
--- a/src/hscroll.h
+++ b/src/hscroll.h
#include <glib.h>
+#ifdef HAVE_NCURSESW_NCURSES_H
+#include <ncursesw/ncurses.h>
+#else
+#include <ncurses.h>
+#endif
+
+/**
+ * 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.
+ */
struct hscroll {
+ WINDOW *w;
+ const char *separator;
+
+ /**
+ * The bounding coordinates on the screen.
+ */
+ unsigned x, y, width;
+
+ /**
+ * ncurses attributes for drawing the text.
+ */
+ attr_t attrs;
+
+ /**
+ * ncurses colors for drawing the text.
+ */
+ short pair;
+
+ /**
+ * The scrolled text, in the current locale.
+ */
+ char *text;
+
+ /**
+ * 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;
};
static inline void
strscroll(struct hscroll *hscroll, const char *str, const char *separator,
unsigned width);
+/**
+ * Initializes a #hscroll object allocated by the caller.
+ */
+static inline void
+hscroll_init(struct hscroll *hscroll, WINDOW *w, const char *separator)
+{
+ hscroll->w = w;
+ hscroll->separator = separator;
+}
+
+/**
+ * Sets a text to scroll. This installs a timer which redraws every
+ * second with the current window attributes. Call hscroll_clear() to
+ * disable it. This function automatically removes the old text.
+ */
+void
+hscroll_set(struct hscroll *hscroll, unsigned x, unsigned y, unsigned width,
+ const char *text);
+
+/**
+ * Removes the text and the timer. It may be reused with
+ * hscroll_set().
+ */
+void
+hscroll_clear(struct hscroll *hscroll);
+
+/**
+ * Explicitly draws the scrolled text. Calling this function is only
+ * allowed if there is a text currently.
+ */
+void
+hscroll_draw(struct hscroll *hscroll);
+
#endif
diff --git a/src/screen_browser.c b/src/screen_browser.c
index 89c84abedcb76f3867061940b9ad206d43ff311b..52d76f1a7e5bb2a22799872813c113445b4e7708 100644 (file)
--- a/src/screen_browser.c
+++ b/src/screen_browser.c
case MPD_ENTITY_TYPE_SONG:
paint_song_row(w, y, width, selected, highlight,
- mpd_entity_get_song(entity));
+ mpd_entity_get_song(entity), NULL);
break;
case MPD_ENTITY_TYPE_PLAYLIST:
diff --git a/src/screen_queue.c b/src/screen_queue.c
index 02978eab5fd291b890b770fc77ef19cc0059c5ef..c5be09af82a7751f2d0670f3eb10c43a3d0f09b1 100644 (file)
--- a/src/screen_queue.c
+++ b/src/screen_queue.c
struct mpdclient *c;
} completion_callback_data_t;
-/*
static struct hscroll hscroll;
-static guint scroll_source_id;
-*/
#endif
static struct mpdclient_playlist *playlist;
screen_queue_save_selection();
}
-/*
-#ifndef NCMPC_MINI
-static gboolean
-scroll_timer_callback(G_GNUC_UNUSED gpointer data)
-{
- scroll_source_id = 0;
-
- hscroll_step(&hscroll);
- screen_queue_repaint();
- return false;
-}
-#endif
-*/
-
static const char *
screen_queue_lw_callback(unsigned idx, G_GNUC_UNUSED void *data)
{
strfsong(songname, MAX_SONG_LENGTH, options.list_format, song);
- /*
-#ifndef NCMPC_MINI
- if (idx == lw->selected)
- {
- if (options.scroll && utf8_width(songname) > (unsigned)COLS) {
- static unsigned current_song;
- char *tmp;
-
- if (current_song != lw->selected) {
- hscroll_reset(&hscroll);
- current_song = lw->selected;
- }
-
- tmp = strscroll(&hscroll, songname, options.scroll_sep,
- MAX_SONG_LENGTH);
- g_strlcpy(songname, tmp, MAX_SONG_LENGTH);
- g_free(tmp);
-
- if (scroll_source_id == 0)
- scroll_source_id =
- g_timeout_add(1000,
- scroll_timer_callback,
- NULL);
- } else {
- hscroll_reset(&hscroll);
-
- if (scroll_source_id != 0) {
- g_source_remove(scroll_source_id);
- scroll_source_id = 0;
- }
- }
- }
-#endif
- */
-
return songname;
}
screen_queue_init(WINDOW *w, int cols, int rows)
{
lw = list_window_init(w, cols, rows);
+
+#ifndef NCMPC_MINI
+ if (options.scroll)
+ hscroll_init(&hscroll, w, options.scroll_sep);
+#endif
}
static gboolean
g_source_remove(timer_hide_cursor_id);
timer_hide_cursor_id = 0;
}
+
+#ifndef NCMPC_MINI
+ if (options.scroll)
+ hscroll_clear(&hscroll);
+#endif
}
static void
bool selected, G_GNUC_UNUSED void *data)
{
const struct mpd_song *song;
+ struct hscroll *row_hscroll;
assert(playlist != NULL);
assert(i < playlist_length(playlist));
song = playlist_get(playlist, i);
+#ifdef NCMPC_MINI
+ row_hscroll = NULL;
+#else
+ row_hscroll = selected && options.scroll && lw->selected == i
+ ? &hscroll : NULL;
+#endif
+
paint_song_row(w, y, width, selected,
(int)mpd_song_get_id(song) == current_song_id,
- song);
+ song, row_hscroll);
}
static void
screen_queue_paint(void)
{
+#ifndef NCMPC_MINI
+ if (options.scroll)
+ hscroll_clear(&hscroll);
+#endif
+
list_window_paint2(lw, screen_queue_paint_callback, NULL);
}
diff --git a/src/song_paint.c b/src/song_paint.c
index 5b7966be18bb877c9476c507365efb8cf59015f4..0e2e74194383f3fb25f19ce3cf1c8377f3cddb04 100644 (file)
--- a/src/song_paint.c
+++ b/src/song_paint.c
#include "paint.h"
#include "strfsong.h"
#include "utils.h"
+#include "hscroll.h"
+#include "charset.h"
#include "config.h"
#include <mpd/client.h>
void
paint_song_row(WINDOW *w, G_GNUC_UNUSED unsigned y, unsigned width,
- bool selected, bool highlight, const struct mpd_song *song)
+ bool selected, bool highlight, const struct mpd_song *song,
+ G_GNUC_UNUSED struct hscroll *hscroll)
{
char buffer[width * 4];
char duration[32];
format_duration_short(duration, sizeof(duration),
mpd_song_get_duration(song));
- wmove(w, y, width - strlen(duration) - 1);
+ width -= strlen(duration) + 1;
+ wmove(w, y, width);
waddch(w, ' ');
waddstr(w, duration);
}
+
+ if (hscroll != NULL && utf8_width(buffer) >= width) {
+ hscroll_set(hscroll, 0, y, width, buffer);
+ hscroll_draw(hscroll);
+ }
#endif
}
diff --git a/src/song_paint.h b/src/song_paint.h
index c4581aafc3ebd664b7de1a3ff91f3b04225216f0..9136fba89c875a884aa8786dac9f475cde326f16 100644 (file)
--- a/src/song_paint.h
+++ b/src/song_paint.h
#endif
struct mpd_song;
+struct hscroll;
/**
* Paints a song into a list window row. The cursor must be set to
* @param selected true if the row is selected
* @param highlight true if the row is highlighted
* @param song the song object
+ * @param hscroll an optional hscroll object
*/
void
paint_song_row(WINDOW *w, unsigned y, unsigned width,
- bool selected, bool highlight, const struct mpd_song *song);
+ bool selected, bool highlight, const struct mpd_song *song,
+ struct hscroll *hscroll);
#endif
diff --git a/src/status_bar.c b/src/status_bar.c
index 657008c4eb892c7432b55b67a7cb61de453ee04b..00724e3aae062952b1a9ab96ca74368f0c6de862 100644 (file)
--- a/src/status_bar.c
+++ b/src/status_bar.c
p->message_source_id = 0;
#ifndef NCMPC_MINI
- hscroll_reset(&p->hscroll);
- p->scroll_source_id = 0;
+ if (options.scroll)
+ hscroll_init(&p->hscroll, p->window.w, options.scroll_sep);
+
p->prev_status = NULL;
p->prev_song = NULL;
#endif
{
delwin(p->window.w);
- if (p->message_source_id != 0)
- g_source_remove(p->message_source_id);
-}
-
#ifndef NCMPC_MINI
-static gboolean
-scroll_timer_callback(gpointer data)
-{
- struct status_bar *p = data;
-
- p->scroll_source_id = 0;
-
- hscroll_step(&p->hscroll);
- status_bar_paint(p, p->prev_status, p->prev_song);
- doupdate();
- return false;
-}
+ if (options.scroll)
+ hscroll_clear(&p->hscroll);
#endif
+}
static gboolean
status_bar_clear_message(gpointer data)
/* scroll if the song name is to long */
#ifndef NCMPC_MINI
if (options.scroll && utf8_width(songname) > (unsigned)width) {
- char *tmp = strscroll(&p->hscroll, songname,
- options.scroll_sep, width);
-
- g_strlcpy(songname, tmp, sizeof(songname));
- g_free(tmp);
-
- if (p->scroll_source_id == 0)
- p->scroll_source_id =
- g_timeout_add(1000,
- scroll_timer_callback,
- p);
- } else if (p->scroll_source_id != 0) {
- g_source_remove(p->scroll_source_id);
- p->scroll_source_id = 0;
+ hscroll_set(&p->hscroll, x, 0, width, songname);
+ hscroll_draw(&p->hscroll);
+ } else {
+ if (options.scroll)
+ hscroll_clear(&p->hscroll);
+ mvwaddstr(w, 0, x, songname);
}
-#endif
- //mvwaddnstr(w, 0, x, songname, width);
+#else
mvwaddstr(w, 0, x, songname);
+#endif
#ifndef NCMPC_MINI
- } else if (p->scroll_source_id != 0) {
- g_source_remove(p->scroll_source_id);
- p->scroll_source_id = 0;
+ } else if (options.scroll) {
+ hscroll_clear(&p->hscroll);
#endif
}
{
WINDOW *w = p->window.w;
+#ifndef NCMPC_MINI
+ if (options.scroll)
+ hscroll_clear(&p->hscroll);
+#endif
+
wmove(w, 0, 0);
wclrtoeol(w);
colors_use(w, COLOR_STATUS_ALERT);
diff --git a/src/status_bar.h b/src/status_bar.h
index bfbb2c04654103add9649b071f788be65457f4bc..c4a54708cbf706c3b762441240d6f41c2c2c7c9b 100644 (file)
--- a/src/status_bar.h
+++ b/src/status_bar.h
#ifndef NCMPC_MINI
struct hscroll hscroll;
- guint scroll_source_id;
const struct mpd_status *prev_status;
const struct mpd_song *prev_song;