1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-15 23:35:34 +00:00

[sixel] Small progress.

You can see images. In ~/.mailcap:
image/*; img2sixel %s; copiousoutput
This commit is contained in:
Witold Filipczyk 2023-05-19 21:31:51 +02:00
parent ee29a8877b
commit c0a140f4f3
11 changed files with 254 additions and 7 deletions

View File

@ -163,6 +163,10 @@ init_document(struct cache_entry *cached, struct document_options *options)
init_list(document->timeouts);
#endif
#ifdef CONFIG_LIBSIXEL
init_list(document->images);
#endif
#ifdef CONFIG_COMBINE
document->comb_x = -1;
document->comb_y = -1;

View File

@ -21,6 +21,7 @@ struct ecmascript_timeout;
struct el_form_control;
struct frame_desc;
struct frameset_desc;
struct image;
struct module;
struct screen_char;
@ -305,6 +306,9 @@ struct document {
struct el_box clipboard_box;
enum clipboard_status clipboard_status;
#ifdef CONFIG_LIBSIXEL
LIST_OF(struct image) images;
#endif
};
#define document_has_frames(document_) ((document_) && (document_)->frame_desc)

View File

@ -5,6 +5,7 @@
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -25,6 +26,7 @@
#include "protocol/uri.h"
#include "terminal/color.h"
#include "terminal/draw.h"
#include "terminal/sixel.h"
#include "util/color.h"
#include "util/error.h"
#include "util/memory.h"
@ -560,7 +562,7 @@ add_document_line(struct plain_renderer *renderer,
prev_char = line_pos > 0 ? line[line_pos - 1] : '\0';
next_char = (line_pos + charlen < width) ?
line[line_pos + charlen] : '\0';
line[line_pos + charlen] : '\0';
/* Do not expand tabs that precede back-spaces; this saves the
* back-space code some trouble. */
@ -639,10 +641,45 @@ add_document_line(struct plain_renderer *renderer,
if (template_->attr)
template_->attr |= pos->attr;
} else if (line_char == 27) {
decode_esc_color(line, &line_pos, width,
#ifdef CONFIG_LIBSIXEL
if (line_pos + 1 < width && line[line_pos + 1] == 'P' && line_pos + 2 < width && line[line_pos + 2] == 'q') {
while (1) {
char *end = (char *)memchr(line + line_pos + 1, 27, width - line_pos - 1);
if (end == NULL) {
break;
}
if (end[1] == '\\') {
struct string pixels;
if (!init_string(&pixels)) {
break;
}
add_bytes_to_string(&pixels, line + line_pos, end + 2 - line - line_pos);
int ile = add_image_to_document(document, &pixels, lineno) + 1;
realloc_line(document, pos - startpos, lineno);
for (int i = 0; i < ile; i++) {
realloc_line(document, 0, lineno + i);
}
renderer->lineno += ile;
lineno += ile;
line_pos = end + 2 - line;
startpos = pos = realloc_line(document, width, lineno);
goto zero;
} else {
line_pos = end - line;
}
}
} else
#endif
{
decode_esc_color(line, &line_pos, width,
&saved_renderer_template,
doc_opts->color_mode, &was_reversed);
*template_ = saved_renderer_template;
*template_ = saved_renderer_template;
}
} else {
int added_chars = 0;
@ -700,6 +737,7 @@ add_document_line(struct plain_renderer *renderer,
next:
line_pos += charlen;
cells += cell;
zero:
}
mem_free(line);
@ -749,11 +787,11 @@ add_document_lines(struct plain_renderer *renderer)
int last_space = 0;
int tab_spaces = 0;
int step = 0;
int cells = 0;
int cells = 0;
/* End of line detection: We handle \r, \r\n and \n types. */
for (width = 0; (width < length) &&
(cells < renderer->max_width);) {
for (width = 0; (width < length) &&
(cells < renderer->max_width);) {
if (source[width] == ASCII_CR)
step++;
if (source[width + step] == ASCII_LF)

View File

@ -1,6 +1,9 @@
if conf_data.get('CONFIG_MOUSE')
srcs += files('mouse.c')
endif
if conf_data.get('CONFIG_LIBSIXEL')
srcs += files('sixel.c')
endif
if conf_data.get('CONFIG_TERMINFO')
srcs += files('terminfo.c')
endif

View File

@ -20,6 +20,7 @@
#include "terminal/hardio.h"
#include "terminal/kbd.h"
#include "terminal/screen.h"
#include "terminal/sixel.h"
#include "terminal/terminal.h"
#ifdef CONFIG_TERMINFO
#include "terminal/terminfo.h"
@ -675,7 +676,7 @@ done_screen_drivers(struct module *xxx)
/** Adds the term code for positioning the cursor at @a x and @a y to
* @a string. The template term code is: "\033[<y>;<x>H" */
static inline struct string *
struct string *
add_cursor_move_to_string(struct string *screen, int y, int x)
{
#ifdef CONFIG_TERMINFO
@ -1372,6 +1373,8 @@ add_char_true(struct string *screen, struct screen_driver *driver,
} \
}
#include <stdio.h>
/*! Updating of the terminal screen is done by checking what needs to
* be updated using the last screen. */
void
@ -1453,6 +1456,9 @@ redraw_screen(struct terminal *term)
copy_screen_chars(screen->last_image, screen->image, term->width * term->height);
screen->was_dirty = 0;
#ifdef CONFIG_LIBSIXEL
try_to_draw_images(term);
#endif
}
void

View File

@ -8,6 +8,7 @@ extern "C" {
struct bitfield;
struct module;
struct screen_char;
struct string;
struct terminal;
/** The terminal's screen manages */
@ -50,6 +51,8 @@ void erase_screen(struct terminal *term);
/** Meeep! */
void beep_terminal(struct terminal *term);
struct string *add_cursor_move_to_string(struct string *screen, int y, int x);
extern struct module terminal_screen_module;
#ifdef __cplusplus

110
src/terminal/sixel.c Normal file
View File

@ -0,0 +1,110 @@
/** Terminal sixel routines.
* @file */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sixel.h>
#include "elinks.h"
#include "document/document.h"
#include "osdep/osdep.h"
#include "terminal/hardio.h"
#include "terminal/screen.h"
#include "terminal/sixel.h"
#include "terminal/terminal.h"
/* encode settings object */
struct sixel_decoder {
unsigned int ref;
char *input;
char *output;
sixel_allocator_t *allocator;
};
void
try_to_draw_images(struct terminal *term)
{
struct image *im;
foreach (im, term->images) {
struct string text;
if (!init_string(&text)) {
return;
}
add_cursor_move_to_string(&text, im->y + 1, im->x + 1);
add_string_to_string(&text, &im->sixel);
if (text.length) {
if (term->master) want_draw();
hard_write(term->fdout, text.source, text.length);
if (term->master) done_draw();
}
done_string(&text);
}
}
void
delete_image(struct image *im)
{
del_from_list(im);
done_string(&im->sixel);
mem_free(im);
}
int
add_image_to_document(struct document *doc, struct string *pixels, int lineno)
{
struct image *im = mem_calloc(1, sizeof(*im));
if (!im) {
return 0;
}
sixel_decoder_t *decoder = NULL;
SIXELSTATUS status = sixel_decoder_new(&decoder, NULL);
if (status != SIXEL_OK) {
return 0;
}
unsigned char *indexed_pixels = NULL;
unsigned char *palette = NULL;
int ncolors;
int width;
int height;
int ile = 0;
status = sixel_decode_raw(
(unsigned char *)pixels->source,
pixels->length,
&indexed_pixels,
&width,
&height,
&palette,
&ncolors,
decoder->allocator
);
if (SIXEL_FAILED(status)) {
goto end;
}
im->y = lineno + 1;
im->x = 0;
im->width = width;
im->height = height;
*(&im->sixel) = *pixels;
ile = (height + 15) / 16;
add_to_list(doc->images, im);
end:
sixel_allocator_free(decoder->allocator, indexed_pixels);
sixel_allocator_free(decoder->allocator, palette);
sixel_decoder_unref(decoder);
return ile;
}

38
src/terminal/sixel.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef EL__TERMINAL_SIXEL_H
#define EL__TERMINAL_SIXEL_H
#include "util/lists.h"
#include "util/string.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef CONFIG_LIBSIXEL
struct document;
struct terminal;
struct image {
LIST_HEAD(struct image);
struct string sixel;
int x;
int y;
int width;
int height;
};
void delete_image(struct image *im);
void try_to_draw_images(struct terminal *term);
/* return height of image in terminal rows */
int add_image_to_document(struct document *doc, struct string *pixels, int lineno);
#endif
#ifdef __cplusplus
}
#endif
#endif /* EL__TERMINAL_SIXEL_H */

View File

@ -35,6 +35,7 @@
#include "terminal/hardio.h"
#include "terminal/kbd.h"
#include "terminal/screen.h"
#include "terminal/sixel.h"
#include "terminal/terminal.h"
#ifdef CONFIG_TERMINFO
#include "terminal/terminfo.h"
@ -117,6 +118,9 @@ init_term(int fdin, int fdout)
#endif
init_list(term->windows);
#ifdef CONFIG_LIBSIXEL
init_list(term->images);
#endif
term->fdin = fdin;
term->fdout = fdout;
term->master = (term->fdout == get_output_handle());
@ -184,6 +188,11 @@ destroy_terminal(struct terminal *term)
while (!list_empty(term->windows))
delete_window((struct window *)term->windows.next);
#ifdef CONFIG_LIBSIXEL
while (!list_empty(term->images)) {
delete_image((struct image *)term->images.next);
}
#endif
/* mem_free_if(term->cwd); */
mem_free_if(term->title);
if (term->screen) done_screen(term->screen);

View File

@ -172,6 +172,10 @@ struct terminal {
void *textarea_data;
struct term_event_mouse prev_mouse_event;
#ifdef CONFIG_LIBSIXEL
LIST_OF(struct image) images;
#endif
};
#define do_not_ignore_next_mouse_event(term) \

View File

@ -5,6 +5,7 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
@ -29,6 +30,7 @@
#include "session/location.h"
#include "session/session.h"
#include "terminal/draw.h"
#include "terminal/sixel.h"
#include "terminal/tab.h"
#include "terminal/terminal.h"
#include "util/error.h"
@ -458,6 +460,32 @@ draw_doc(struct session *ses, struct document_view *doc_view, int active)
if (vs->current_link == -1)
vs->current_link = 0;
}
#ifdef CONFIG_LIBSIXEL
while (!list_empty(term->images)) {
delete_image((struct image *)term->images.next);
}
if (list_empty(term->images)) {
struct image *im;
foreach (im, doc_view->document->images) {
if (im) {
struct image *im_copy = mem_calloc(1, sizeof(*im_copy));
if (im_copy) {
if (init_string(&im_copy->sixel)) {
add_string_to_string(&im_copy->sixel, &im->sixel);
im_copy->x = im->x;
im_copy->y = im->y;
im_copy->width = im->width;
im_copy->height = im->height;
add_to_list(term->images, im_copy);
}
}
}
}
}
#endif
}
static void