2
* textbox.c - show a text box for messages, files or help
3
* Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
4
* Jaroslav Kysela <perex@perex.cz>
5
* Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
7
* This program is free software: you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation, either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program. If not, see <http://www.gnu.org/licenses/>.
27
#include <alsa/asoundlib.h>
28
#include "gettext_curses.h"
36
#define MAX_FILE_SIZE 1048576
38
static void create_text_box(const char *const *lines, unsigned int count,
39
const char *title, int attrs);
41
void show_error(const char *msg, int err)
49
lines[1] = strerror(err);
52
create_text_box(lines, count, _("Error"), attr_errormsg);
55
void show_alsa_error(const char *msg, int err)
63
lines[1] = snd_strerror(err);
66
create_text_box(lines, count, _("Error"), attr_errormsg);
69
static char *read_file(const char *file_name, unsigned int *file_size)
74
unsigned int allocated = 2048;
75
unsigned int bytes_read;
77
f = fopen(file_name, "r");
80
buf = casprintf(_("Cannot open file \"%s\"."), file_name);
89
buf = crealloc(buf, allocated);
90
bytes_read = fread(buf + *file_size, 1, allocated - *file_size, f);
91
*file_size += bytes_read;
92
} while (*file_size == allocated && allocated < MAX_FILE_SIZE);
94
if (*file_size > 0 && buf[*file_size - 1] != '\n' && *file_size < allocated) {
95
buf[*file_size] = '\n';
101
void show_textfile(const char *file_name)
104
unsigned int file_size;
105
unsigned int line_count;
108
const char *start_line;
110
buf = read_file(file_name, &file_size);
114
for (i = 0; i < file_size; ++i)
115
line_count += buf[i] == '\n';
116
lines = ccalloc(line_count, sizeof *lines);
119
for (i = 0; i < file_size; ++i) {
120
if (buf[i] == '\n') {
121
lines[line_count++] = start_line;
123
start_line = &buf[i + 1];
128
create_text_box(lines, line_count, file_name, attr_textbox);
133
void show_text(const char *const *lines, unsigned int count, const char *title)
135
create_text_box(lines, count, title, attr_textbox);
138
/**********************************************************************/
140
static struct widget text_widget;
142
static int widget_attrs;
143
static char **text_lines;
144
static unsigned int text_lines_count;
145
static int max_line_width;
146
static int text_box_y;
147
static int text_box_x;
148
static int max_scroll_y;
149
static int max_scroll_x;
150
static int current_top;
151
static int current_left;
153
static void update_text_lines(void)
157
const char *line_begin;
158
const char *line_end;
162
for (i = 0; i < text_box_y; ++i) {
163
width = current_left;
164
line_begin = mbs_at_width(text_lines[current_top + i], &width, 1);
165
wmove(text_widget.window, i + 1, 1);
166
if (width > current_left)
167
waddch(text_widget.window, ' ');
168
if (*line_begin != '\0') {
169
width = text_box_x - (width > current_left);
170
line_end = mbs_at_width(line_begin, &width, -1);
172
waddnstr(text_widget.window, line_begin,
173
line_end - line_begin);
175
getyx(text_widget.window, cur_y, cur_x);
176
if (cur_y == i + 1) {
177
rest_of_line = text_box_x + 1 - cur_x;
178
if (rest_of_line > 0)
179
wprintw(text_widget.window, "%*s", rest_of_line, "");
184
static void update_y_scroll_bar(void)
190
if (max_scroll_y <= 0 || text_lines_count == 0)
192
length = text_box_y * text_box_y / text_lines_count;
193
if (length >= text_box_y)
195
begin = current_top * (text_box_y - length) / max_scroll_y;
196
end = begin + length;
197
for (i = 0; i < text_box_y; ++i)
198
mvwaddch(text_widget.window, i + 1, text_box_x + 1,
199
i >= begin && i < end ? ACS_BOARD : ' ');
202
static void update_x_scroll_bar(void)
208
if (max_scroll_x <= 0 || max_line_width <= 0)
210
length = text_box_x * text_box_x / max_line_width;
211
if (length >= text_box_x)
213
begin = current_left * (text_box_x - length) / max_scroll_x;
214
end = begin + length;
215
wmove(text_widget.window, text_box_y + 1, 1);
216
for (i = 0; i < text_box_x; ++i)
217
waddch(text_widget.window, i >= begin && i < end ? ACS_BOARD : ' ');
220
static void move_x(int delta)
224
left = current_left + delta;
227
else if (left > max_scroll_x)
229
if (left != current_left) {
232
update_x_scroll_bar();
236
static void move_y(int delta)
240
top = current_top + delta;
243
else if (top > max_scroll_y)
245
if (top != current_top) {
248
update_y_scroll_bar();
252
static void on_handle_key(int key)
306
move_x(-max_scroll_x);
310
move_x(max_scroll_x);
321
static bool create(void)
325
if (screen_lines < 3 || screen_cols < 8) {
331
width = max_line_width;
332
len = get_mbs_width(title) + 2;
336
text_box_y = text_lines_count;
337
if (text_box_y > screen_lines - 2)
338
text_box_y = screen_lines - 2;
339
max_scroll_y = text_lines_count - text_box_y;
341
if (text_box_x > screen_cols - 2)
342
text_box_x = screen_cols - 2;
343
max_scroll_x = max_line_width - text_box_x;
345
widget_init(&text_widget, text_box_y + 2, text_box_x + 2,
346
SCREEN_CENTER, SCREEN_CENTER, widget_attrs, WIDGET_BORDER);
347
mvwprintw(text_widget.window, 0, (text_box_x + 2 - get_mbs_width(title) - 2) / 2, " %s ", title);
349
if (current_top > max_scroll_y)
350
current_top = max_scroll_y;
351
if (current_left > max_scroll_x)
352
current_left = max_scroll_x;
354
update_y_scroll_bar();
355
update_x_scroll_bar();
359
static void on_window_size_changed(void)
364
static void on_close(void)
368
for (i = 0; i < text_lines_count; ++i)
371
widget_free(&text_widget);
374
static struct widget text_widget = {
375
.handle_key = on_handle_key,
376
.window_size_changed = on_window_size_changed,
380
static void create_text_box(const char *const *lines, unsigned int count,
381
const char *title_, int attrs)
385
text_lines = ccalloc(count, sizeof *text_lines);
386
for (i = 0; i < count; ++i)
387
text_lines[i] = cstrdup(lines[i]);
388
text_lines_count = count;
389
max_line_width = get_max_mbs_width(lines, count);
390
title = cstrdup(title_);
391
widget_attrs = attrs;