179
ret = caca_file_read(f, data + size, 1024);
162
ret = (ssize_t)caca_file_read(f, data + size, 1024);
183
166
caca_file_close(f);
185
ret = caca_import_memory(cv, data, size, format);
168
ret = caca_import_canvas_from_memory(cv, data, size, format);
175
/** \brief Import a memory buffer into a canvas area
177
* Import a memory buffer into the given libcaca canvas's current
178
* frame, at the specified position. For more information, see
179
* caca_import_canvas_from_memory().
181
* If an error occurs, -1 is returned and \b errno is set accordingly:
182
* - \c EINVAL Unsupported format requested or invalid coordinates.
183
* - \c ENOMEM Not enough memory to allocate canvas.
185
* \param cv A libcaca canvas in which to import the file.
186
* \param x The leftmost coordinate of the area to import to.
187
* \param y The topmost coordinate of the area to import to.
188
* \param data A memory area containing the data to be loaded into the canvas.
189
* \param len The size in bytes of the memory area.
190
* \param format A string describing the input format.
191
* \return The number of bytes read, or 0 if there was not enough data,
192
* or -1 if an error occurred.
194
ssize_t caca_import_area_from_memory(caca_canvas_t *cv, int x, int y,
195
void const *data, size_t len,
201
tmp = caca_create_canvas(0, 0);
202
ret = caca_import_canvas_from_memory(tmp, data, len, format);
205
caca_blit(cv, x, y, tmp, NULL);
207
caca_free_canvas(tmp);
212
/** \brief Import a file into a canvas area
214
* Import a file into the given libcaca canvas's current frame, at the
215
* specified position. For more information, see
216
* caca_import_canvas_from_file().
218
* If an error occurs, -1 is returned and \b errno is set accordingly:
219
* - \c ENOSYS File access is not implemented on this system.
220
* - \c ENOMEM Not enough memory to allocate canvas.
221
* - \c EINVAL Unsupported format requested or invalid coordinates.
222
* caca_import_file() may also fail and set \b errno for any of the
223
* errors specified for the routine fopen().
225
* \param cv A libcaca canvas in which to import the file.
226
* \param x The leftmost coordinate of the area to import to.
227
* \param y The topmost coordinate of the area to import to.
228
* \param filename The name of the file to load.
229
* \param format A string describing the input format.
230
* \return The number of bytes read, or 0 if there was not enough data,
231
* or -1 if an error occurred.
233
ssize_t caca_import_area_from_file(caca_canvas_t *cv, int x, int y,
234
char const *filename, char const *format)
239
tmp = caca_create_canvas(0, 0);
240
ret = caca_import_canvas_from_file(tmp, filename, format);
243
caca_blit(cv, x, y, tmp, NULL);
245
caca_free_canvas(tmp);
192
250
/** \brief Get available import formats
194
252
* Return a list of available import formats. The list is a NULL-terminated
330
388
caca_set_frame(cv, 0);
332
return 4 + control_size + data_size;
390
return (ssize_t)(4 + control_size + data_size);
335
393
seterrno(EINVAL);
339
static ssize_t import_text(caca_canvas_t *cv, void const *data, size_t size)
341
char const *text = (char const *)data;
342
unsigned int width = 0, height = 0, x = 0, y = 0, i;
344
caca_set_canvas_size(cv, width, height);
346
for(i = 0; i < size; i++)
348
unsigned char ch = *text++;
360
if(x >= width || y >= height)
368
caca_set_canvas_size(cv, width, height);
371
caca_put_char(cv, x, y, ch);
376
caca_set_canvas_size(cv, width, height = y);
381
static ssize_t import_ansi(caca_canvas_t *cv, void const *data,
382
size_t size, int utf8)
385
unsigned char const *buffer = (unsigned char const*)data;
386
unsigned int i, j, skip, growx = 0, growy = 0, dummy = 0;
387
unsigned int width, height;
389
int x = 0, y = 0, save_x = 0, save_y = 0;
397
x = cv->frames[cv->frame].x;
398
y = cv->frames[cv->frame].y;
402
caca_set_canvas_size(cv, width = 80, height = 0);
409
im.dfg = CACA_DEFAULT;
410
im.dbg = CACA_TRANSPARENT;
414
im.dfg = CACA_LIGHTGRAY;
418
caca_set_color_ansi(cv, im.dfg, im.dbg);
419
im.clearattr = caca_get_attr(cv, -1, -1);
421
ansi_parse_grcm(cv, &im, 1, &dummy);
423
for(i = 0; i < size; i += skip)
430
if(!utf8 && buffer[i] == '\x1a' && i + 7 < size
431
&& !memcmp(buffer + i + 1, "SAUCE00", 7))
432
break; /* End before SAUCE data */
434
else if(buffer[i] == '\r')
439
else if(buffer[i] == '\n')
445
else if(buffer[i] == '\t')
450
else if(buffer[i] == '\x08')
456
/* If there are not enough characters to parse the escape sequence,
457
* wait until the next try. We require 3. */
458
else if(buffer[i] == '\x1b' && i + 2 >= size)
461
/* XXX: What the fuck is this shit? */
462
else if(buffer[i] == '\x1b' && buffer[i + 1] == '('
463
&& buffer[i + 2] == 'B')
468
/* Interpret escape commands, as per Standard ECMA-48 "Control
469
* Functions for Coded Character Sets", 5.4. Control sequences. */
470
else if(buffer[i] == '\x1b' && buffer[i + 1] == '[')
472
unsigned int argc = 0, argv[101];
473
unsigned int param, inter, final;
475
/* Compute offsets to parameter bytes, intermediate bytes and
476
* to the final byte. Only the final byte is mandatory, there
477
* can be zero of the others.
478
* 0 param=2 inter final final+1
479
* +-----+------------------+---------------------+-----------------+
480
* | CSI | parameter bytes | intermediate bytes | final byte |
481
* | | 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e |
482
* | ^[[ | 0123456789:;<=>? | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ |
483
* +-----+------------------+---------------------+-----------------+
487
for(inter = param; i + inter < size; inter++)
488
if(buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f)
491
for(final = inter; i + final < size; final++)
492
if(buffer[i + final] < 0x20 || buffer[i + final] > 0x2f)
496
|| buffer[i + final] < 0x40 || buffer[i + final] > 0x7e)
497
break; /* Invalid Final Byte */
502
if(param < inter && buffer[i + param] >= 0x3c)
504
/* Private sequence, only parse what we know */
505
debug("ansi import: private sequence \"^[[%.*s\"",
506
final - param + 1, buffer + i + param);
507
continue; /* Private sequence, skip it entirely */
510
if(final - param > 100)
511
continue; /* Suspiciously long sequence, skip it */
513
/* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string
518
for(j = param; j < inter; j++)
520
if(buffer[i + j] == ';')
522
else if(buffer[i + j] >= '0' && buffer[i + j] <= '9')
523
argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0');
528
/* Interpret final byte. The code representations are given in
529
* ECMA-48 5.4: Control sequences, and the code definitions are
530
* given in ECMA-48 8.3: Definition of control functions. */
531
switch(buffer[i + final])
533
case 'H': /* CUP (0x48) - Cursor Position */
534
x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0;
535
y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0;
537
case 'A': /* CUU (0x41) - Cursor Up */
538
y -= argc ? argv[0] : 1;
542
case 'B': /* CUD (0x42) - Cursor Down */
543
y += argc ? argv[0] : 1;
545
case 'C': /* CUF (0x43) - Cursor Right */
546
x += argc ? argv[0] : 1;
548
case 'D': /* CUB (0x44) - Cursor Left */
549
x -= argc ? argv[0] : 1;
553
case 'G': /* CHA (0x47) - Cursor Character Absolute */
554
x = (argc && argv[0] > 0) ? argv[0] - 1 : 0;
556
case 'J': /* ED (0x4a) - Erase In Page */
557
savedattr = caca_get_attr(cv, -1, -1);
558
caca_set_attr(cv, im.clearattr);
559
if(!argc || argv[0] == 0)
561
caca_draw_line(cv, x, y, width, y, ' ');
562
caca_fill_box(cv, 0, y + 1, width - 1, height - 1, ' ');
564
else if(argv[0] == 1)
566
caca_fill_box(cv, 0, 0, width - 1, y - 1, ' ');
567
caca_draw_line(cv, 0, y, x, y, ' ');
569
else if(argv[0] == 2)
571
caca_fill_box(cv, 0, 0, width - 1, height - 1, ' ');
572
caca_set_attr(cv, savedattr);
574
case 'K': /* EL (0x4b) - Erase In Line */
575
if(!argc || argv[0] == 0)
576
caca_draw_line(cv, x, y, width, y, ' ');
577
else if(argv[0] == 1)
578
caca_draw_line(cv, 0, y, x, y, ' ');
579
else if(argv[0] == 2)
580
if((unsigned int)x < width)
581
caca_draw_line(cv, x, y, width - 1, y, ' ');
584
case 'P': /* DCH (0x50) - Delete Character */
585
if(!argc || argv[0] == 0)
586
argv[0] = 1; /* echo -ne 'foobar\r\e[0P\n' */
587
for(j = 0; (unsigned int)(j + argv[0]) < width; j++)
589
caca_put_char(cv, j, y,
590
caca_get_char(cv, j + argv[0], y));
591
caca_put_attr(cv, j, y,
592
caca_get_attr(cv, j + argv[0], y));
595
savedattr = caca_get_attr(cv, -1, -1);
596
caca_set_attr(cv, im.clearattr);
597
for( ; (unsigned int)j < width; j++)
598
caca_put_char(cv, j, y, ' ');
599
caca_set_attr(cv, savedattr);
601
case 'X': /* ECH (0x58) - Erase Character */
604
savedattr = caca_get_attr(cv, -1, -1);
605
caca_set_attr(cv, im.clearattr);
606
caca_draw_line(cv, x, y, x + argv[0] - 1, y, ' ');
607
caca_set_attr(cv, savedattr);
609
case 'd': /* VPA (0x64) - Line Position Absolute */
610
y = (argc && argv[0] > 0) ? argv[0] - 1 : 0;
612
case 'f': /* HVP (0x66) - Character And Line Position */
613
x = (argc > 1 && argv[1] > 0) ? argv[1] - 1 : 0;
614
y = (argc > 0 && argv[0] > 0) ? argv[0] - 1 : 0;
616
case 'h': /* SM (0x68) - FIXME */
617
debug("ansi import: set mode %i", argc ? (int)argv[0] : -1);
619
case 'l': /* RM (0x6c) - FIXME */
620
debug("ansi import: reset mode %i", argc ? (int)argv[0] : -1);
622
case 'm': /* SGR (0x6d) - Select Graphic Rendition */
624
ansi_parse_grcm(cv, &im, argc, argv);
626
ansi_parse_grcm(cv, &im, 1, &dummy);
628
case 's': /* Private (save cursor position) */
632
case 'u': /* Private (reload cursor position) */
637
debug("ansi import: unknown command \"^[[%.*s\"",
638
final - param + 1, buffer + i + param);
643
/* Parse OSC stuff. */
644
else if(buffer[i] == '\x1b' && buffer[i + 1] == ']')
647
unsigned int command = 0;
648
unsigned int mode = 2, semicolon, final;
650
for(semicolon = mode; i + semicolon < size; semicolon++)
652
if(buffer[i + semicolon] < '0' || buffer[i + semicolon] > '9')
654
command = 10 * command + (buffer[i + semicolon] - '0');
657
if(i + semicolon >= size || buffer[i + semicolon] != ';')
658
break; /* Invalid Mode */
660
for(final = semicolon + 1; i + final < size; final++)
661
if(buffer[i + final] < 0x20)
664
if(i + final >= size || buffer[i + final] != '\a')
665
break; /* Not enough data or no bell found */
666
/* FIXME: XTerm also reacts to <ESC><backslash> and <ST> */
667
/* FIXME: differenciate between not enough data (try again)
668
* and invalid data (print shit) */
672
string = malloc(final - (semicolon + 1) + 1);
673
memcpy(string, buffer + (semicolon + 1), final - (semicolon + 1));
674
string[final - (semicolon + 1)] = '\0';
675
debug("ansi import: got OSC command %i string '%s'", command,
680
/* Get the character we’re going to paste */
686
ch = caca_utf8_to_utf32((char const *)(buffer + i), &bytes);
689
/* Add a trailing zero to what we're going to read */
691
memcpy(tmp, buffer + i, size - i);
692
tmp[size - i] = '\0';
693
ch = caca_utf8_to_utf32(tmp, &bytes);
698
/* If the Unicode is invalid, assume it was latin1. */
702
wch = caca_utf32_is_fullwidth(ch) ? 2 : 1;
707
ch = caca_cp437_to_utf32(buffer[i]);
711
/* Wrap long lines or grow horizontally */
712
while((unsigned int)x + wch > width)
716
savedattr = caca_get_attr(cv, -1, -1);
717
caca_set_attr(cv, im.clearattr);
718
caca_set_canvas_size(cv, width = x + wch, height);
719
caca_set_attr(cv, savedattr);
728
/* Scroll or grow vertically */
729
if((unsigned int)y >= height)
731
savedattr = caca_get_attr(cv, -1, -1);
732
caca_set_attr(cv, im.clearattr);
735
caca_set_canvas_size(cv, width, height = y + 1);
739
int lines = (y - height) + 1;
741
for(j = 0; j + lines < height; j++)
743
memcpy(cv->attrs + j * cv->width,
744
cv->attrs + (j + lines) * cv->width, cv->width * 4);
745
memcpy(cv->chars + j * cv->width,
746
cv->chars + (j + lines) * cv->width, cv->width * 4);
748
caca_fill_box(cv, 0, height - lines,
749
cv->width - 1, height - 1, ' ');
752
caca_set_attr(cv, savedattr);
755
/* Now paste our character, if any */
758
caca_put_char(cv, x, y, ch);
763
if(growy && (unsigned int)y > height)
765
savedattr = caca_get_attr(cv, -1, -1);
766
caca_set_attr(cv, im.clearattr);
767
caca_set_canvas_size(cv, width, height = y);
768
caca_set_attr(cv, savedattr);
771
cv->frames[cv->frame].x = x;
772
cv->frames[cv->frame].y = y;
775
// caca_set_attr(cv, savedattr);
780
/* XXX : ANSI loader helper */
782
static void ansi_parse_grcm(caca_canvas_t *cv, struct import *im,
783
unsigned int argc, unsigned int const *argv)
785
static uint8_t const ansi2caca[] =
787
CACA_BLACK, CACA_RED, CACA_GREEN, CACA_BROWN,
788
CACA_BLUE, CACA_MAGENTA, CACA_CYAN, CACA_LIGHTGRAY
792
uint8_t efg, ebg; /* Effective (libcaca) fg/bg */
794
for(j = 0; j < argc; j++)
796
/* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */
797
if(argv[j] >= 30 && argv[j] <= 37)
798
im->fg = ansi2caca[argv[j] - 30];
799
else if(argv[j] >= 40 && argv[j] <= 47)
800
im->bg = ansi2caca[argv[j] - 40];
801
else if(argv[j] >= 90 && argv[j] <= 97)
802
im->fg = ansi2caca[argv[j] - 90] + 8;
803
else if(argv[j] >= 100 && argv[j] <= 107)
804
im->bg = ansi2caca[argv[j] - 100] + 8;
807
case 0: /* default rendition */
810
im->bold = im->blink = im->italics = im->negative
811
= im->concealed = im->underline = im->faint = im->strike
812
= im->proportional = 0;
814
case 1: /* bold or increased intensity */
817
case 2: /* faint, decreased intensity or second colour */
820
case 3: /* italicized */
823
case 4: /* singly underlined */
826
case 5: /* slowly blinking (less then 150 per minute) */
827
case 6: /* rapidly blinking (150 per minute or more) */
830
case 7: /* negative image */
833
case 8: /* concealed characters */
836
case 9: /* crossed-out (characters still legible but marked as to be
840
case 21: /* doubly underlined */
843
case 22: /* normal colour or normal intensity (neither bold nor
845
im->bold = im->faint = 0;
847
case 23: /* not italicized, not fraktur */
850
case 24: /* not underlined (neither singly nor doubly) */
853
case 25: /* steady (not blinking) */
856
case 26: /* (reserved for proportional spacing as specified in CCITT
857
* Recommendation T.61) */
858
im->proportional = 1;
860
case 27: /* positive image */
863
case 28: /* revealed characters */
866
case 29: /* not crossed out */
869
case 38: /* (reserved for future standardization, intended for setting
870
* character foreground colour as specified in ISO 8613-6
871
* [CCITT Recommendation T.416]) */
873
case 39: /* default display colour (implementation-defined) */
876
case 48: /* (reserved for future standardization, intended for setting
877
* character background colour as specified in ISO 8613-6
878
* [CCITT Recommendation T.416]) */
880
case 49: /* default background colour (implementation-defined) */
883
case 50: /* (reserved for cancelling the effect of the rendering
884
* aspect established by parameter value 26) */
885
im->proportional = 0;
888
debug("ansi import: unknown sgr %i", argv[j]);
895
efg = ebg = CACA_TRANSPARENT;
899
efg = im->negative ? im->bg : im->fg;
900
ebg = im->negative ? im->fg : im->bg;
906
else if(efg == CACA_DEFAULT)
911
caca_set_color_ansi(cv, efg, ebg);
915
398
* XXX: The following functions are aliases.
918
401
ssize_t cucul_import_memory(cucul_canvas_t *, void const *, size_t,
919
char const *) CACA_ALIAS(caca_import_memory);
402
char const *) CACA_ALIAS(caca_import_canvas_from_memory);
920
403
ssize_t cucul_import_file(cucul_canvas_t *, char const *,
921
char const *) CACA_ALIAS(caca_import_file);
404
char const *) CACA_ALIAS(caca_import_canvas_from_file);
405
ssize_t caca_import_memory(caca_canvas_t *, void const *, size_t, char const *)
406
CACA_ALIAS(caca_import_canvas_from_memory);
407
ssize_t caca_import_file(caca_canvas_t *, char const *, char const *)
408
CACA_ALIAS(caca_import_canvas_from_file);
922
409
char const * const * cucul_get_import_list(void)
923
410
CACA_ALIAS(caca_get_import_list);