1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

add perl code for textbuffer-formats

- compatibility shim for new line

- make format accessible from perl

- fix perl line IDs being mixed up due to wrapper
This commit is contained in:
ailin-nemui 2019-08-08 21:54:30 +02:00
parent 6b93d6e338
commit 57fb173130
7 changed files with 170 additions and 17 deletions

View File

@ -108,6 +108,7 @@ textui_sources = \
textui/TextBufferView.xs \
textui/Statusbar.xs \
textui/Makefile.PL.in \
textui/wrapper_buffer_line.h \
textui/typemap \
textui/module.h

View File

@ -1,5 +1,7 @@
#define PERL_NO_GET_CONTEXT
#include "module.h"
#include "wrapper_buffer_line.h"
#include <irssi/src/fe-text/textbuffer-formats.h>
MODULE = Irssi::TextUI::TextBuffer PACKAGE = Irssi
PROTOTYPES: ENABLE
@ -12,7 +14,7 @@ Irssi::TextUI::Line
textbuffer_line_prev(line)
Irssi::TextUI::Line line
CODE:
RETVAL = line->prev;
RETVAL = perl_wrap_buffer_line(line->buffer, line->line->prev);
OUTPUT:
RETVAL
@ -20,13 +22,12 @@ Irssi::TextUI::Line
textbuffer_line_next(line)
Irssi::TextUI::Line line
CODE:
RETVAL = line->next;
RETVAL = perl_wrap_buffer_line(line->buffer, line->line->next);
OUTPUT:
RETVAL
void
textbuffer_line_get_text(buffer, line, coloring)
Irssi::TextUI::TextBuffer buffer
textbuffer_line_get_text(line, coloring)
Irssi::TextUI::Line line
int coloring
PREINIT:
@ -34,8 +35,36 @@ PREINIT:
SV *result;
PPCODE:
str = g_string_new(NULL);
textbuffer_line2text(buffer, line, coloring, str);
textbuffer_line2text(line->buffer, line->line, coloring, str);
result = new_pv(str->str);
XPUSHs(sv_2mortal(result));
g_string_free(str, TRUE);
void
textbuffer_line_get_format(line)
Irssi::TextUI::Line line
PREINIT:
HV *hv;
AV *av;
LINE_REC *l;
TEXT_BUFFER_FORMAT_REC *f;
int i;
PPCODE:
hv = newHV();
l = line->line;
if (l->info.format != NULL) {
f = l->info.format;
(void) hv_store(hv, "module", 6, new_pv(f->module), 0);
(void) hv_store(hv, "format", 6, new_pv(f->format), 0);
(void) hv_store(hv, "server_tag", 10, new_pv(f->server_tag), 0);
(void) hv_store(hv, "target", 6, new_pv(f->target), 0);
(void) hv_store(hv, "nick", 4, new_pv(f->nick), 0);
av = newAV();
for (i = 0; i < f->nargs; i++) {
av_push(av, new_pv(f->args[i]));
}
(void) hv_store(hv, "args", 4, newRV_noinc((SV *) av), 0);
} else {
(void) hv_store(hv, "text", 4, new_pv(l->info.text), 0);
}
XPUSHs(sv_2mortal(newRV_noinc((SV *) hv)));

View File

@ -1,5 +1,6 @@
#define PERL_NO_GET_CONTEXT
#include "module.h"
#include "wrapper_buffer_line.h"
MODULE = Irssi::TextUI::TextBufferView PACKAGE = Irssi::TextUI::TextBuffer PREFIX = textbuffer_
PROTOTYPES: ENABLE
@ -33,6 +34,10 @@ textbuffer_view_clear(view)
Irssi::TextUI::Line
textbuffer_view_get_lines(view)
Irssi::TextUI::TextBufferView view
CODE:
RETVAL = perl_wrap_buffer_line(view->buffer, textbuffer_view_get_lines(view));
OUTPUT:
RETVAL
void
textbuffer_view_scroll(view, lines)
@ -43,16 +48,24 @@ void
textbuffer_view_scroll_line(view, line)
Irssi::TextUI::TextBufferView view
Irssi::TextUI::Line line
CODE:
textbuffer_view_scroll_line(view, line->line);
Irssi::TextUI::LineCache
textbuffer_view_get_line_cache(view, line)
Irssi::TextUI::TextBufferView view
Irssi::TextUI::Line line
CODE:
RETVAL = textbuffer_view_get_line_cache(view, line->line);
OUTPUT:
RETVAL
void
textbuffer_view_remove_line(view, line)
Irssi::TextUI::TextBufferView view
Irssi::TextUI::Line line
CODE:
textbuffer_view_remove_line(view, line->line);
void
textbuffer_view_remove_all_lines(view)
@ -68,6 +81,8 @@ textbuffer_view_set_bookmark(view, name, line)
Irssi::TextUI::TextBufferView view
char *name
Irssi::TextUI::Line line
CODE:
textbuffer_view_set_bookmark(view, name, line->line);
void
textbuffer_view_set_bookmark_bottom(view, name)
@ -78,6 +93,10 @@ Irssi::TextUI::Line
textbuffer_view_get_bookmark(view, name)
Irssi::TextUI::TextBufferView view
char *name
CODE:
RETVAL = perl_wrap_buffer_line(view->buffer, textbuffer_view_get_bookmark(view, name));
OUTPUT:
RETVAL
void
textbuffer_view_redraw(view)

View File

@ -1,11 +1,17 @@
#define PERL_NO_GET_CONTEXT
#include "module.h"
#include "wrapper_buffer_line.h"
void perl_statusbar_init(void);
void perl_statusbar_deinit(void);
static int initialized = FALSE;
static SV *buffer_line_bless(TEXT_BUFFER_REC *buffer, LINE_REC *line)
{
return perl_buffer_line_bless(perl_wrap_buffer_line(buffer, line));
}
static void perl_main_window_fill_hash(HV *hv, MAIN_WINDOW_REC *window)
{
(void) hv_store(hv, "active", 6, plain_bless(window->active, "Irssi::UI::Window"), 0);
@ -20,9 +26,9 @@ static void perl_main_window_fill_hash(HV *hv, MAIN_WINDOW_REC *window)
static void perl_text_buffer_fill_hash(HV *hv, TEXT_BUFFER_REC *buffer)
{
(void) hv_store(hv, "first_line", 10, plain_bless(buffer->first_line, "Irssi::TextUI::Line"), 0);
(void) hv_store(hv, "first_line", 10, buffer_line_bless(buffer, buffer->first_line), 0);
(void) hv_store(hv, "lines_count", 11, newSViv(buffer->lines_count), 0);
(void) hv_store(hv, "cur_line", 8, plain_bless(buffer->cur_line, "Irssi::TextUI::Line"), 0);
(void) hv_store(hv, "cur_line", 8, buffer_line_bless(buffer, buffer->cur_line), 0);
(void) hv_store(hv, "last_eol", 8, newSViv(buffer->last_eol), 0);
}
@ -38,20 +44,22 @@ static void perl_text_buffer_view_fill_hash(HV *hv, TEXT_BUFFER_VIEW_REC *view)
(void) hv_store(hv, "ypos", 4, newSViv(view->ypos), 0);
(void) hv_store(hv, "startline", 9, plain_bless(view->startline, "Irssi::TextUI::Line"), 0);
(void) hv_store(hv, "startline", 9, buffer_line_bless(view->buffer, view->startline), 0);
(void) hv_store(hv, "subline", 7, newSViv(view->subline), 0);
(void) hv_store(hv, "hidden_level", 12, newSViv(view->hidden_level), 0);
(void) hv_store(hv, "bottom_startline", 16, plain_bless(view->bottom_startline, "Irssi::TextUI::Line"), 0);
(void) hv_store(hv, "bottom_startline", 16,
buffer_line_bless(view->buffer, view->bottom_startline), 0);
(void) hv_store(hv, "bottom_subline", 14, newSViv(view->bottom_subline), 0);
(void) hv_store(hv, "empty_linecount", 15, newSViv(view->empty_linecount), 0);
(void) hv_store(hv, "bottom", 6, newSViv(view->bottom), 0);
}
static void perl_line_fill_hash(HV *hv, LINE_REC *line)
static void perl_line_fill_hash(HV *hv, struct Buffer_Line_Wrapper *line)
{
(void) hv_store(hv, "info", 4, plain_bless(&line->info, "Irssi::TextUI::LineInfo"), 0);
(void) hv_store(hv, "info", 4, plain_bless(&Line(line)->info, "Irssi::TextUI::LineInfo"),
0);
}
static void perl_line_cache_fill_hash(HV *hv, LINE_CACHE_REC *cache)
@ -242,7 +250,7 @@ CODE:
format_create_dest(&dest, NULL, NULL, level, window);
text = format_string_expand(str, NULL);
text2 = g_strconcat(text, "\n", NULL);
gui_printtext_after_time(&dest, prev, text2, time);
gui_printtext_after_time(&dest, Line(prev), text2, time);
g_free(text);
g_free(text2);
@ -257,13 +265,14 @@ PREINIT:
TEXT_DEST_REC dest;
CODE:
format_create_dest(&dest, NULL, NULL, level, window);
gui_printtext_after_time(&dest, prev, str, time);
gui_printtext_after_time(&dest, Line(prev), str, time);
Irssi::TextUI::Line
last_line_insert(window)
Irssi::UI::Window window
CODE:
RETVAL = WINDOW_GUI(window)->insert_after;
RETVAL = perl_wrap_buffer_line(WINDOW_GUI(window)->view->buffer,
WINDOW_GUI(window)->insert_after);
OUTPUT:
RETVAL
@ -281,7 +290,7 @@ PREINIT:
TEXT_DEST_REC dest;
CODE:
format_create_dest(&dest, server, target, level, NULL);
gui_printtext_after_time(&dest, prev, str, time);
gui_printtext_after_time(&dest, Line(prev), str, time);
BOOT:
irssi_boot(TextUI__Statusbar);

View File

@ -11,7 +11,7 @@
typedef MAIN_WINDOW_REC *Irssi__TextUI__MainWindow;
typedef TEXT_BUFFER_REC *Irssi__TextUI__TextBuffer;
typedef TEXT_BUFFER_VIEW_REC *Irssi__TextUI__TextBufferView;
typedef LINE_REC *Irssi__TextUI__Line;
typedef struct Buffer_Line_Wrapper *Irssi__TextUI__Line;
typedef LINE_CACHE_REC *Irssi__TextUI__LineCache;
typedef LINE_INFO_REC *Irssi__TextUI__LineInfo;
typedef SBAR_ITEM_REC *Irssi__TextUI__StatusbarItem;

View File

@ -2,7 +2,7 @@ TYPEMAP
Irssi::TextUI::MainWindow T_PlainObj
Irssi::TextUI::TextBuffer T_PlainObj
Irssi::TextUI::TextBufferView T_PlainObj
Irssi::TextUI::Line T_PlainObj
Irssi::TextUI::Line T_BufferLineWrapper
Irssi::TextUI::LineCache T_PlainObj
Irssi::TextUI::LineInfo T_PlainObj
Irssi::TextUI::StatusbarItem T_PlainObj
@ -12,8 +12,13 @@ INPUT
T_PlainObj
$var = irssi_ref_object($arg)
T_BufferLineWrapper
$var = irssi_ref_buffer_line_wrap($arg)
OUTPUT
T_PlainObj
$arg = plain_bless($var, \"$type\");
T_BufferLineWrapper
$arg = perl_buffer_line_bless($var);

View File

@ -0,0 +1,90 @@
#ifndef IRSSI_PERL_TEXTUI_WRAPPER_BUFFER_LINE_H
#define IRSSI_PERL_TEXTUI_WRAPPER_BUFFER_LINE_H
/* This Buffer_Line_Wrapper is a compatibility shim so that the Perl
* API does not change in Irssi ABI 24 even though the C API was
* changed. That way scripts can continue to work unchanged. */
struct Buffer_Line_Wrapper {
LINE_REC *line;
TEXT_BUFFER_REC *buffer;
};
#define Line(wrapper) ((wrapper) == NULL ? NULL : (wrapper)->line)
static int magic_free_buffer_line(pTHX_ SV *sv, MAGIC *mg)
{
struct Buffer_Line_Wrapper *wrap = (struct Buffer_Line_Wrapper *) mg->mg_ptr;
g_free(wrap);
mg->mg_ptr = NULL;
sv_setiv(sv, 0);
return 0;
}
static MGVTBL vtbl_free_buffer_line = { NULL, NULL, NULL, NULL, magic_free_buffer_line };
static struct Buffer_Line_Wrapper *perl_wrap_buffer_line(TEXT_BUFFER_REC *buffer, LINE_REC *line)
{
struct Buffer_Line_Wrapper *wrap;
if (line == NULL)
return NULL;
wrap = g_new0(struct Buffer_Line_Wrapper, 1);
wrap->buffer = buffer;
wrap->line = line;
return wrap;
}
/* This function is more or less a copy of plain_bless, but with a
special divertion to put the wrapper in _wrapper and the original
line pointer in _irssi, in order to stay compatible with signals
and scripts */
static SV *perl_buffer_line_bless(struct Buffer_Line_Wrapper *object)
{
SV *ret, **tmp;
HV *hv;
const char *stash = "Irssi::TextUI::Line";
if (object == NULL)
return &PL_sv_undef;
ret = irssi_bless_plain(stash, object);
hv = hvref(ret);
tmp = hv_fetch(hv, "_irssi", 6, 0);
sv_magic(*tmp, NULL, '~', NULL, 0);
SvMAGIC(*tmp)->mg_private = 0x1551; /* HF */
SvMAGIC(*tmp)->mg_virtual = &vtbl_free_buffer_line;
SvMAGIC(*tmp)->mg_ptr = (char *) object;
(void) hv_store(hv, "_wrapper", 8, *tmp, 0);
/* We have to put the Line Pointer in _irssi, not the
compatibility wrapper */
*tmp = newSViv((IV) object->line);
return ret;
}
/* This function is a copy of irssi_ref_object, but looking up the
wrapper object in _wrapper instead */
static void *irssi_ref_buffer_line_wrap(SV *o)
{
SV **sv;
HV *hv;
void *p;
hv = hvref(o);
if (hv == NULL)
return NULL;
sv = hv_fetch(hv, "_wrapper", 8, 0);
if (sv == NULL)
croak("variable is damaged");
p = GINT_TO_POINTER(SvIV(*sv));
return p;
}
#endif