Missing new files in update to xterm 304
This commit is contained in:
parent
8273aa94a8
commit
7ff3194bee
3482
app/xterm/graphics_regis.c
Normal file
3482
app/xterm/graphics_regis.c
Normal file
File diff suppressed because it is too large
Load Diff
48
app/xterm/graphics_regis.h
Normal file
48
app/xterm/graphics_regis.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* $XTermId: graphics_regis.h,v 1.1 2014/04/11 19:36:41 Ross.Combs Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2014 by Ross Combs
|
||||
* Copyright 2014 by Thomas E. Dickey
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name(s) of the above copyright
|
||||
* holders shall not be used in advertising or otherwise to promote the
|
||||
* sale, use or other dealings in this Software without prior written
|
||||
* authorization.
|
||||
*/
|
||||
|
||||
#ifndef included_graphics_regis_h
|
||||
#define included_graphics_regis_h
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
#include <ptyx.h>
|
||||
|
||||
#if OPT_REGIS_GRAPHICS
|
||||
extern void parse_regis(XtermWidget xw, ANSI *params, char const *string);
|
||||
#else
|
||||
#define parse_regis(xw, params, string) /* nothing */
|
||||
#endif
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* included_graphics_regis_h */
|
640
app/xterm/graphics_sixel.c
Normal file
640
app/xterm/graphics_sixel.c
Normal file
@ -0,0 +1,640 @@
|
||||
/* $XTermId: graphics_sixel.c,v 1.8 2014/05/02 22:53:20 tom Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2014 by Ross Combs
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name(s) of the above copyright
|
||||
* holders shall not be used in advertising or otherwise to promote the
|
||||
* sale, use or other dealings in this Software without prior written
|
||||
* authorization.
|
||||
*/
|
||||
|
||||
#include <xterm.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <data.h>
|
||||
#include <VTparse.h>
|
||||
#include <ptyx.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <graphics.h>
|
||||
#include <graphics_sixel.h>
|
||||
|
||||
/***====================================================================***/
|
||||
/*
|
||||
* Parse numeric parameters which have the operator as a prefix rather than a
|
||||
* suffix as in ANSI format.
|
||||
*
|
||||
* # 0
|
||||
* #1 1
|
||||
* #1; 1
|
||||
* "1;2;640;480 4
|
||||
* #1;2;0;0;0 5
|
||||
*/
|
||||
static void
|
||||
parse_prefixedtype_params(ANSI *params, const char **string)
|
||||
{
|
||||
const char *cp = *string;
|
||||
ParmType nparam = 0;
|
||||
int last_empty = 1;
|
||||
|
||||
memset(params, 0, sizeof(*params));
|
||||
params->a_final = CharOf(*cp);
|
||||
if (*cp != '\0')
|
||||
cp++;
|
||||
|
||||
while (*cp != '\0') {
|
||||
Char ch = CharOf(*cp);
|
||||
|
||||
if (isdigit(ch)) {
|
||||
last_empty = 0;
|
||||
if (nparam < NPARAM) {
|
||||
params->a_param[nparam] =
|
||||
(ParmType) ((params->a_param[nparam] * 10)
|
||||
+ (ch - '0'));
|
||||
}
|
||||
} else if (ch == ';') {
|
||||
last_empty = 1;
|
||||
nparam++;
|
||||
} else if (ch == ' ' || ch == '\r' || ch == '\n') {
|
||||
/* EMPTY */ ;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
|
||||
*string = cp;
|
||||
if (!last_empty)
|
||||
nparam++;
|
||||
if (nparam > NPARAM)
|
||||
params->a_nparam = NPARAM;
|
||||
else
|
||||
params->a_nparam = nparam;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
RegisterNum current_register;
|
||||
RegisterNum background; /* current background color register or hole */
|
||||
int aspect_vertical;
|
||||
int aspect_horizontal;
|
||||
int declared_width; /* size as reported by the application */
|
||||
int declared_height; /* size as reported by the application */
|
||||
int row; /* context used during parsing */
|
||||
int col; /* context used during parsing */
|
||||
} SixelContext;
|
||||
|
||||
/* sixel scrolling:
|
||||
* VK100/GIGI ? (did it even support Sixel?)
|
||||
* VT125 unsupported
|
||||
* VT240 unsupported
|
||||
* VT241 unsupported
|
||||
* VT330 mode setting
|
||||
* VT382 ?
|
||||
* VT340 mode setting
|
||||
* dxterm ?
|
||||
*/
|
||||
|
||||
static void
|
||||
init_sixel_background(Graphic *graphic, SixelContext const *context)
|
||||
{
|
||||
int r, c;
|
||||
|
||||
TRACE(("initializing sixel background to size=%dx%d bgcolor=%hu\n",
|
||||
context->declared_width,
|
||||
context->declared_height,
|
||||
context->background));
|
||||
|
||||
if (context->background == COLOR_HOLE)
|
||||
return;
|
||||
|
||||
for (r = 0; r < graphic->actual_height; r++) {
|
||||
for (c = 0; c < graphic->actual_width; c++) {
|
||||
graphic->pixels[r * graphic->max_width + c] = context->background;
|
||||
}
|
||||
}
|
||||
graphic->color_registers_used[context->background] = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
set_sixel(Graphic *graphic, SixelContext const *context, int sixel)
|
||||
{
|
||||
RegisterNum color;
|
||||
int pix;
|
||||
|
||||
color = context->current_register;
|
||||
TRACE(("drawing sixel at pos=%d,%d color=%hu (hole=%d, [%d,%d,%d])\n",
|
||||
context->col,
|
||||
context->row,
|
||||
color,
|
||||
color == COLOR_HOLE,
|
||||
((color != COLOR_HOLE)
|
||||
? (unsigned) graphic->color_registers[color].r : 0U),
|
||||
((color != COLOR_HOLE)
|
||||
? (unsigned) graphic->color_registers[color].g : 0U),
|
||||
((color != COLOR_HOLE)
|
||||
? (unsigned) graphic->color_registers[color].b : 0U)));
|
||||
for (pix = 0; pix < 6; pix++) {
|
||||
if (context->col < graphic->max_width &&
|
||||
context->row + pix < graphic->max_height) {
|
||||
if (sixel & (1 << pix)) {
|
||||
if (context->col + 1 > graphic->actual_width) {
|
||||
graphic->actual_width = context->col + 1;
|
||||
}
|
||||
if (context->row + pix + 1 > graphic->actual_height) {
|
||||
graphic->actual_height = context->row + pix + 1;
|
||||
}
|
||||
graphic->pixels[
|
||||
(((context->row + pix) * graphic->max_width)
|
||||
+ context->col)
|
||||
] = color;
|
||||
}
|
||||
} else {
|
||||
TRACE(("sixel pixel %d out of bounds\n", pix));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_sixel_aspect(SixelContext const *context, Graphic *graphic)
|
||||
{
|
||||
/* We want to keep the ratio accurate but would like every pixel to have
|
||||
* the same size so keep these as whole numbers.
|
||||
*/
|
||||
/* FIXME: DEC terminals had pixels about twice as tall as they were wide,
|
||||
* and it seems the VT125 and VT24x only used data from odd graphic rows.
|
||||
* This means it basically cancels out if we ignore both, except that
|
||||
* the even rows of pixels may not be written by the application such that
|
||||
* they are suitable for display. In practice this doesn't seem to be
|
||||
* an issue but I have very few test files/programs.
|
||||
*/
|
||||
if (context->aspect_vertical < context->aspect_horizontal) {
|
||||
graphic->pixw = 1;
|
||||
graphic->pixh = ((context->aspect_vertical
|
||||
+ context->aspect_horizontal - 1)
|
||||
/ context->aspect_horizontal);
|
||||
} else {
|
||||
graphic->pixw = ((context->aspect_horizontal
|
||||
+ context->aspect_vertical - 1)
|
||||
/ context->aspect_vertical);
|
||||
graphic->pixh = 1;
|
||||
}
|
||||
TRACE(("sixel aspect ratio: an=%d ad=%d -> pixw=%d pixh=%d\n",
|
||||
context->aspect_vertical,
|
||||
context->aspect_horizontal,
|
||||
graphic->pixw,
|
||||
graphic->pixh));
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret sixel graphics sequences.
|
||||
*
|
||||
* Resources:
|
||||
* http://en.wikipedia.org/wiki/Sixel
|
||||
* http://vt100.net/docs/vt3xx-gp/chapter14.html
|
||||
* ftp://ftp.cs.utk.edu/pub/shuford/terminal/sixel_graphics_news.txt
|
||||
* ftp://ftp.cs.utk.edu/pub/shuford/terminal/all_about_sixels.txt
|
||||
*/
|
||||
void
|
||||
parse_sixel(XtermWidget xw, ANSI *params, char const *string)
|
||||
{
|
||||
TScreen *screen = TScreenOf(xw);
|
||||
Graphic *graphic;
|
||||
SixelContext context;
|
||||
Char ch;
|
||||
|
||||
switch (screen->terminal_id) {
|
||||
case 240:
|
||||
case 241:
|
||||
case 330:
|
||||
case 340:
|
||||
context.aspect_vertical = 2;
|
||||
context.aspect_horizontal = 1;
|
||||
break;
|
||||
case 382:
|
||||
context.aspect_vertical = 1;
|
||||
context.aspect_horizontal = 1;
|
||||
break;
|
||||
default:
|
||||
context.aspect_vertical = 2;
|
||||
context.aspect_horizontal = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
context.declared_width = 0;
|
||||
context.declared_height = 0;
|
||||
|
||||
context.row = 0;
|
||||
context.col = 0;
|
||||
|
||||
/* default isn't white on the VT240, but not sure what it is */
|
||||
context.current_register = 3; /* FIXME: using green, but not sure what it should be */
|
||||
|
||||
if (xw->keyboard.flags & MODE_DECSDM) {
|
||||
TRACE(("sixel scrolling enabled: inline positioning for graphic at %d,%d\n",
|
||||
screen->cur_row, screen->cur_col));
|
||||
graphic = get_new_graphic(xw, screen->cur_row, screen->cur_col, 0U);
|
||||
} else {
|
||||
TRACE(("sixel scrolling disabled: inline positioning for graphic at %d,%d\n",
|
||||
0, 0));
|
||||
graphic = get_new_graphic(xw, 0, 0, 0U);
|
||||
}
|
||||
|
||||
{
|
||||
int Pmacro = params->a_param[0];
|
||||
int Pbgmode = params->a_param[1];
|
||||
int Phgrid = params->a_param[2];
|
||||
int Pan = params->a_param[3];
|
||||
int Pad = params->a_param[4];
|
||||
int Ph = params->a_param[5];
|
||||
int Pv = params->a_param[6];
|
||||
|
||||
(void) Phgrid;
|
||||
|
||||
TRACE(("sixel bitmap graphics sequence: params=%d (Pmacro=%d Pbgmode=%d Phgrid=%d) scroll_amt=%d\n",
|
||||
params->a_nparam,
|
||||
Pmacro,
|
||||
Pbgmode,
|
||||
Phgrid,
|
||||
screen->scroll_amt));
|
||||
|
||||
switch (params->a_nparam) {
|
||||
case 7:
|
||||
if (Pan == 0 || Pad == 0) {
|
||||
TRACE(("DATA_ERROR: invalid raster ratio %d/%d\n", Pan, Pad));
|
||||
return;
|
||||
}
|
||||
context.aspect_vertical = Pan;
|
||||
context.aspect_horizontal = Pad;
|
||||
|
||||
if (Ph == 0 || Pv == 0) {
|
||||
TRACE(("DATA_ERROR: raster image dimensions are invalid %dx%d\n",
|
||||
Ph, Pv));
|
||||
return;
|
||||
}
|
||||
if (Ph > graphic->max_width || Pv > graphic->max_height) {
|
||||
TRACE(("DATA_ERROR: raster image dimensions are too large %dx%d\n",
|
||||
Ph, Pv));
|
||||
return;
|
||||
}
|
||||
context.declared_width = Ph;
|
||||
context.declared_height = Pv;
|
||||
if (context.declared_width > graphic->actual_width) {
|
||||
graphic->actual_width = context.declared_width;
|
||||
}
|
||||
if (context.declared_height > graphic->actual_height) {
|
||||
graphic->actual_height = context.declared_height;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 2:
|
||||
case 1:
|
||||
switch (Pmacro) {
|
||||
case 0:
|
||||
/* keep default aspect settings */
|
||||
break;
|
||||
case 1:
|
||||
case 5:
|
||||
case 6:
|
||||
context.aspect_vertical = 2;
|
||||
context.aspect_horizontal = 1;
|
||||
break;
|
||||
case 2:
|
||||
context.aspect_vertical = 5;
|
||||
context.aspect_horizontal = 1;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
context.aspect_vertical = 3;
|
||||
context.aspect_horizontal = 1;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
context.aspect_vertical = 1;
|
||||
context.aspect_horizontal = 1;
|
||||
break;
|
||||
default:
|
||||
TRACE(("DATA_ERROR: unknown sixel macro mode parameter\n"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
TRACE(("DATA_ERROR: unexpected parameter count (found %d)\n", params->a_nparam));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Pbgmode == 1) {
|
||||
context.background = COLOR_HOLE;
|
||||
} else {
|
||||
/* FIXME: is the default background register always zero? what about in light background mode? */
|
||||
context.background = 0;
|
||||
}
|
||||
|
||||
/* Ignore the grid parameter because it seems only printers paid attention to it.
|
||||
* The VT3xx was always 0.0195 cm.
|
||||
*/
|
||||
}
|
||||
|
||||
update_sixel_aspect(&context, graphic);
|
||||
|
||||
for (;;) {
|
||||
ch = CharOf(*string);
|
||||
if (ch == '\0')
|
||||
break;
|
||||
|
||||
if (ch >= 0x3f && ch <= 0x7e) {
|
||||
int sixel = ch - 0x3f;
|
||||
TRACE(("sixel=%x (%c)\n", sixel, (char) ch));
|
||||
if (!graphic->valid) {
|
||||
init_sixel_background(graphic, &context);
|
||||
graphic->valid = 1;
|
||||
}
|
||||
set_sixel(graphic, &context, sixel);
|
||||
context.col++;
|
||||
} else if (ch == '$') { /* DECGCR */
|
||||
/* ignore DECCRNLM in sixel mode */
|
||||
TRACE(("sixel CR\n"));
|
||||
context.col = 0;
|
||||
} else if (ch == '-') { /* DECGNL */
|
||||
int scroll_lines;
|
||||
TRACE(("sixel NL\n"));
|
||||
scroll_lines = 0;
|
||||
while (graphic->charrow - scroll_lines +
|
||||
(((context.row + 6) * graphic->pixh
|
||||
+ FontHeight(screen) - 1)
|
||||
/ FontHeight(screen)) > screen->bot_marg) {
|
||||
scroll_lines++;
|
||||
}
|
||||
context.col = 0;
|
||||
context.row += 6;
|
||||
/* If we hit the bottom margin on the graphics page (well, we just use the
|
||||
* text margin for now), the behavior is to either scroll or to discard
|
||||
* the remainder of the graphic depending on this setting.
|
||||
*/
|
||||
if (scroll_lines > 0) {
|
||||
if (xw->keyboard.flags & MODE_DECSDM) {
|
||||
Display *display = screen->display;
|
||||
xtermScroll(xw, scroll_lines);
|
||||
XSync(display, False);
|
||||
TRACE(("graphic scrolled the screen %d lines. screen->scroll_amt=%d screen->topline=%d, now starting row is %d\n",
|
||||
scroll_lines,
|
||||
screen->scroll_amt,
|
||||
screen->topline,
|
||||
graphic->charrow));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (ch == '!') { /* DECGRI */
|
||||
int Pcount;
|
||||
const char *start;
|
||||
int sixel;
|
||||
int i;
|
||||
|
||||
start = ++string;
|
||||
for (;;) {
|
||||
ch = CharOf(*string);
|
||||
if (ch != '0' &&
|
||||
ch != '1' &&
|
||||
ch != '2' &&
|
||||
ch != '3' &&
|
||||
ch != '4' &&
|
||||
ch != '5' &&
|
||||
ch != '6' &&
|
||||
ch != '7' &&
|
||||
ch != '8' &&
|
||||
ch != '9' &&
|
||||
ch != ' ' &&
|
||||
ch != '\r' &&
|
||||
ch != '\n')
|
||||
break;
|
||||
string++;
|
||||
}
|
||||
if (ch == '\0') {
|
||||
TRACE(("DATA_ERROR: sixel data string terminated in the middle of a repeat operator\n"));
|
||||
return;
|
||||
}
|
||||
if (string == start) {
|
||||
TRACE(("DATA_ERROR: sixel data string contains a repeat operator with empty count\n"));
|
||||
return;
|
||||
}
|
||||
Pcount = atoi(start);
|
||||
sixel = ch - 0x3f;
|
||||
TRACE(("sixel repeat operator: sixel=%d (%c), count=%d\n",
|
||||
sixel, (char) ch, Pcount));
|
||||
if (!graphic->valid) {
|
||||
init_sixel_background(graphic, &context);
|
||||
graphic->valid = 1;
|
||||
}
|
||||
for (i = 0; i < Pcount; i++) {
|
||||
set_sixel(graphic, &context, sixel);
|
||||
context.col++;
|
||||
}
|
||||
} else if (ch == '#') { /* DECGCI */
|
||||
ANSI color_params;
|
||||
int Pregister;
|
||||
|
||||
parse_prefixedtype_params(&color_params, &string);
|
||||
Pregister = color_params.a_param[0];
|
||||
if (Pregister >= (int) graphic->valid_registers) {
|
||||
TRACE(("DATA_WARNING: sixel color operator uses out-of-range register %d\n", Pregister));
|
||||
/* FIXME: supposedly the DEC terminals wrapped register indicies -- verify */
|
||||
while (Pregister >= (int) graphic->valid_registers)
|
||||
Pregister -= (int) graphic->valid_registers;
|
||||
TRACE(("DATA_WARNING: converted to %d\n", Pregister));
|
||||
}
|
||||
|
||||
if (color_params.a_nparam > 2 && color_params.a_nparam <= 5) {
|
||||
int Pspace = color_params.a_param[1];
|
||||
int Pc1 = color_params.a_param[2];
|
||||
int Pc2 = color_params.a_param[3];
|
||||
int Pc3 = color_params.a_param[4];
|
||||
short r, g, b;
|
||||
|
||||
TRACE(("sixel set color register=%d space=%d color=[%d,%d,%d] (nparams=%d)\n",
|
||||
Pregister, Pspace, Pc1, Pc2, Pc3, color_params.a_nparam));
|
||||
|
||||
switch (Pspace) {
|
||||
case 1: /* HLS */
|
||||
if (Pc1 > 360 || Pc2 > 100 || Pc3 > 100) {
|
||||
TRACE(("DATA_ERROR: sixel set color operator uses out-of-range HLS color coordinates %d,%d,%d\n",
|
||||
Pc1, Pc2, Pc3));
|
||||
return;
|
||||
}
|
||||
hls2rgb(Pc1, Pc2, Pc3, &r, &g, &b);
|
||||
break;
|
||||
case 2: /* RGB */
|
||||
if (Pc1 > 100 || Pc2 > 100 || Pc3 > 100) {
|
||||
TRACE(("DATA_ERROR: sixel set color operator uses out-of-range RGB color coordinates %d,%d,%d\n",
|
||||
Pc1, Pc2, Pc3));
|
||||
return;
|
||||
}
|
||||
r = (short) Pc1;
|
||||
g = (short) Pc2;
|
||||
b = (short) Pc3;
|
||||
break;
|
||||
default: /* unknown */
|
||||
TRACE(("DATA_ERROR: sixel set color operator uses unknown color space %d\n", Pspace));
|
||||
return;
|
||||
}
|
||||
update_color_register(graphic,
|
||||
(RegisterNum) Pregister,
|
||||
r, g, b);
|
||||
} else if (color_params.a_nparam == 1) {
|
||||
TRACE(("sixel switch to color register=%d (nparams=%d)\n",
|
||||
Pregister, color_params.a_nparam));
|
||||
context.current_register = (RegisterNum) Pregister;
|
||||
} else {
|
||||
TRACE(("DATA_ERROR: sixel switch color operator with unexpected parameter count (nparams=%d)\n", color_params.a_nparam));
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
} else if (ch == '"') /* DECGRA */ {
|
||||
ANSI raster_params;
|
||||
|
||||
parse_prefixedtype_params(&raster_params, &string);
|
||||
if (raster_params.a_nparam < 2) {
|
||||
TRACE(("DATA_ERROR: sixel raster attribute operator with incomplete parameters (found %d, expected 2 or 4)\n", raster_params.a_nparam));
|
||||
return;
|
||||
} {
|
||||
int Pan = raster_params.a_param[0];
|
||||
int Pad = raster_params.a_param[1];
|
||||
TRACE(("sixel raster attribute with h:w=%d:%d\n", Pan, Pad));
|
||||
if (Pan == 0 || Pad == 0) {
|
||||
TRACE(("DATA_ERROR: invalid raster ratio %d/%d\n", Pan, Pad));
|
||||
return;
|
||||
}
|
||||
context.aspect_vertical = Pan;
|
||||
context.aspect_horizontal = Pad;
|
||||
update_sixel_aspect(&context, graphic);
|
||||
}
|
||||
|
||||
if (raster_params.a_nparam >= 4) {
|
||||
int Ph = raster_params.a_param[2];
|
||||
int Pv = raster_params.a_param[3];
|
||||
|
||||
TRACE(("sixel raster attribute with h=%d v=%d\n", Ph, Pv));
|
||||
if (Ph == 0 || Pv == 0) {
|
||||
TRACE(("DATA_ERROR: raster image dimensions are invalid %dx%d\n",
|
||||
Ph, Pv));
|
||||
return;
|
||||
}
|
||||
if (Ph > graphic->max_width || Pv > graphic->max_height) {
|
||||
TRACE(("DATA_ERROR: raster image dimensions are too large %dx%d\n",
|
||||
Ph, Pv));
|
||||
return;
|
||||
}
|
||||
context.declared_width = Ph;
|
||||
context.declared_height = Pv;
|
||||
if (context.declared_width > graphic->actual_width) {
|
||||
graphic->actual_width = context.declared_width;
|
||||
}
|
||||
if (context.declared_height > graphic->actual_height) {
|
||||
graphic->actual_height = context.declared_height;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
} else if (ch == ' ' || ch == '\r' || ch == '\n') {
|
||||
/* EMPTY */ ;
|
||||
} else {
|
||||
TRACE(("DATA_ERROR: unknown sixel command %04x (%c)\n",
|
||||
(int) ch, ch));
|
||||
}
|
||||
|
||||
string++;
|
||||
}
|
||||
|
||||
/* update the screen */
|
||||
if (screen->scroll_amt)
|
||||
FlushScroll(xw);
|
||||
|
||||
if (xw->keyboard.flags & MODE_DECSDM) {
|
||||
int new_row, new_col;
|
||||
|
||||
if (screen->sixel_scrolls_right) {
|
||||
new_row = (graphic->charrow
|
||||
+ (((graphic->actual_height * graphic->pixh)
|
||||
+ FontHeight(screen) - 1)
|
||||
/ FontHeight(screen))
|
||||
- 1);
|
||||
new_col = (graphic->charcol
|
||||
+ (((graphic->actual_width * graphic->pixw)
|
||||
+ FontWidth(screen) - 1)
|
||||
/ FontWidth(screen)));
|
||||
} else {
|
||||
/* FIXME: At least of the VT382 the vertical position appears to be
|
||||
* truncated (rounded toward zero after converting to character row.
|
||||
* This code rounds up, which seems more useful, but it would be
|
||||
* better to be compatible. Verify this is true on a VT3[34]0 as
|
||||
* well.
|
||||
*/
|
||||
new_row = (graphic->charrow
|
||||
+ (((graphic->actual_height * graphic->pixh)
|
||||
+ FontHeight(screen) - 1)
|
||||
/ FontHeight(screen)));
|
||||
new_col = 0;
|
||||
}
|
||||
|
||||
TRACE(("setting text position after %dx%d graphic starting on row=%d col=%d: cursor new_row=%d new_col=%d\n",
|
||||
graphic->actual_width * graphic->pixw,
|
||||
graphic->actual_height * graphic->pixh,
|
||||
graphic->charrow,
|
||||
graphic->charcol,
|
||||
new_row, new_col));
|
||||
|
||||
if (new_col > screen->rgt_marg) {
|
||||
new_col = screen->lft_marg;
|
||||
new_row++;
|
||||
TRACE(("column past left margin, overriding to row=%d col=%d\n",
|
||||
new_row, new_col));
|
||||
}
|
||||
|
||||
while (new_row > screen->bot_marg) {
|
||||
xtermScroll(xw, 1);
|
||||
new_row--;
|
||||
TRACE(("bottom row was past screen. new start row=%d, cursor row=%d\n",
|
||||
graphic->charrow, new_row));
|
||||
}
|
||||
|
||||
if (new_row < 0) {
|
||||
TRACE(("new row is going to be negative (%d)!", new_row)); /* FIXME: this was triggering, now it isn't */
|
||||
goto finis;
|
||||
}
|
||||
set_cur_row(screen, new_row);
|
||||
set_cur_col(screen, new_col <= screen->rgt_marg ? new_col : screen->rgt_marg);
|
||||
}
|
||||
|
||||
finis:
|
||||
refresh_modified_displayed_graphics(screen);
|
||||
|
||||
TRACE(("DONE successfully parsed sixel data\n"));
|
||||
dump_graphic(graphic);
|
||||
}
|
48
app/xterm/graphics_sixel.h
Normal file
48
app/xterm/graphics_sixel.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* $XTermId: graphics_sixel.h,v 1.1 2014/04/11 19:36:41 Ross.Combs Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2014 by Ross Combs
|
||||
* Copyright 2014 by Thomas E. Dickey
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name(s) of the above copyright
|
||||
* holders shall not be used in advertising or otherwise to promote the
|
||||
* sale, use or other dealings in this Software without prior written
|
||||
* authorization.
|
||||
*/
|
||||
|
||||
#ifndef included_graphics_sixel_h
|
||||
#define included_graphics_sixel_h
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
#include <ptyx.h>
|
||||
|
||||
#if OPT_SIXEL_GRAPHICS
|
||||
extern void parse_sixel(XtermWidget xw, ANSI *params, char const *string);
|
||||
#else
|
||||
#define parse_sixel(xw, params, string) /* nothing */
|
||||
#endif
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* included_graphics_sixel_h */
|
Loading…
Reference in New Issue
Block a user