aboutsummaryrefslogtreecommitdiffstats
path: root/src/term.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/term.c')
-rw-r--r--src/term.c276
1 files changed, 194 insertions, 82 deletions
diff --git a/src/term.c b/src/term.c
index 69936400a1d..1613223b97b 100644
--- a/src/term.c
+++ b/src/term.c
@@ -43,8 +43,11 @@ Boston, MA 02110-1301, USA. */
43#include "lisp.h" 43#include "lisp.h"
44#include "termchar.h" 44#include "termchar.h"
45#include "termopts.h" 45#include "termopts.h"
46#include "buffer.h"
47#include "character.h"
46#include "charset.h" 48#include "charset.h"
47#include "coding.h" 49#include "coding.h"
50#include "composite.h"
48#include "keyboard.h" 51#include "keyboard.h"
49#include "frame.h" 52#include "frame.h"
50#include "disptab.h" 53#include "disptab.h"
@@ -188,7 +191,6 @@ extern char *tgetstr ();
188 191
189#ifdef HAVE_GPM 192#ifdef HAVE_GPM
190#include <sys/fcntl.h> 193#include <sys/fcntl.h>
191#include "buffer.h"
192 194
193static void term_clear_mouse_face (); 195static void term_clear_mouse_face ();
194static void term_mouse_highlight (struct frame *f, int x, int y); 196static void term_mouse_highlight (struct frame *f, int x, int y);
@@ -549,10 +551,12 @@ tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
549 } 551 }
550} 552}
551 553
552/* Buffer to store the source and result of code conversion for terminal. */ 554/* Buffers to store the source and result of code conversion for terminal. */
553static unsigned char *encode_terminal_buf; 555static unsigned char *encode_terminal_src;
554/* Allocated size of the above buffer. */ 556static unsigned char *encode_terminal_dst;
555static int encode_terminal_bufsize; 557/* Allocated sizes of the above buffers. */
558static int encode_terminal_src_size;
559static int encode_terminal_dst_size;
556 560
557/* Encode SRC_LEN glyphs starting at SRC to terminal output codes. 561/* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
558 Set CODING->produced to the byte-length of the resulting byte 562 Set CODING->produced to the byte-length of the resulting byte
@@ -570,37 +574,73 @@ encode_terminal_code (src, src_len, coding)
570 int nchars, nbytes, required; 574 int nchars, nbytes, required;
571 register int tlen = GLYPH_TABLE_LENGTH; 575 register int tlen = GLYPH_TABLE_LENGTH;
572 register Lisp_Object *tbase = GLYPH_TABLE_BASE; 576 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
577 Lisp_Object charset_list;
573 578
574 /* Allocate sufficient size of buffer to store all characters in 579 /* Allocate sufficient size of buffer to store all characters in
575 multibyte-form. But, it may be enlarged on demand if 580 multibyte-form. But, it may be enlarged on demand if
576 Vglyph_table contains a string. */ 581 Vglyph_table contains a string or a composite glyph is
582 encountered. */
577 required = MAX_MULTIBYTE_LENGTH * src_len; 583 required = MAX_MULTIBYTE_LENGTH * src_len;
578 if (encode_terminal_bufsize < required) 584 if (encode_terminal_src_size < required)
579 { 585 {
580 if (encode_terminal_bufsize == 0) 586 if (encode_terminal_src_size == 0)
581 encode_terminal_buf = xmalloc (required); 587 encode_terminal_src = xmalloc (required);
582 else 588 else
583 encode_terminal_buf = xrealloc (encode_terminal_buf, required); 589 encode_terminal_src = xrealloc (encode_terminal_src, required);
584 encode_terminal_bufsize = required; 590 encode_terminal_src_size = required;
585 } 591 }
586 592
587 buf = encode_terminal_buf; 593 charset_list = coding_charset_list (coding);
594
595 buf = encode_terminal_src;
588 nchars = 0; 596 nchars = 0;
589 while (src < src_end) 597 while (src < src_end)
590 { 598 {
599 if (src->type == COMPOSITE_GLYPH)
600 {
601 struct composition *cmp = composition_table[src->u.cmp_id];
602 int i;
603
604 nbytes = buf - encode_terminal_src;
605 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
606
607 if (encode_terminal_src_size < nbytes + required)
608 {
609 encode_terminal_src_size = nbytes + required;
610 encode_terminal_src = xrealloc (encode_terminal_src,
611 encode_terminal_src_size);
612 buf = encode_terminal_src + nbytes;
613 }
614
615 for (i = 0; i < cmp->glyph_len; i++)
616 {
617 int c = COMPOSITION_GLYPH (cmp, i);
618
619 if (! char_charset (c, charset_list, NULL))
620 break;
621 buf += CHAR_STRING (c, buf);
622 nchars++;
623 }
624 if (i == 0)
625 {
626 /* The first character of the composition is not encodable. */
627 *buf++ = '?';
628 nchars++;
629 }
630 }
591 /* We must skip glyphs to be padded for a wide character. */ 631 /* We must skip glyphs to be padded for a wide character. */
592 if (! CHAR_GLYPH_PADDING_P (*src)) 632 else if (! CHAR_GLYPH_PADDING_P (*src))
593 { 633 {
634 int c;
635 Lisp_Object string;
636
637 string = Qnil;
594 g = GLYPH_FROM_CHAR_GLYPH (src[0]); 638 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
595 639
596 if (g < 0 || g >= tlen) 640 if (g < 0 || g >= tlen)
597 { 641 {
598 /* This glyph doesn't has an entry in Vglyph_table. */ 642 /* This glyph doesn't has an entry in Vglyph_table. */
599 if (CHAR_VALID_P (src->u.ch, 0)) 643 c = src->u.ch;
600 buf += CHAR_STRING (src->u.ch, buf);
601 else
602 *buf++ = SPACEGLYPH;
603 nchars++;
604 } 644 }
605 else 645 else
606 { 646 {
@@ -609,65 +649,90 @@ encode_terminal_code (src, src_len, coding)
609 GLYPH_FOLLOW_ALIASES (tbase, tlen, g); 649 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
610 650
611 if (GLYPH_SIMPLE_P (tbase, tlen, g)) 651 if (GLYPH_SIMPLE_P (tbase, tlen, g))
612 { 652 /* We set the multi-byte form of a character in G
613 int c = FAST_GLYPH_CHAR (g); 653 (that should be an ASCII character) at WORKBUF. */
654 c = FAST_GLYPH_CHAR (g);
655 else
656 /* We have a string in Vglyph_table. */
657 string = tbase[g];
658 }
614 659
615 if (CHAR_VALID_P (c, 0)) 660 if (NILP (string))
616 buf += CHAR_STRING (c, buf); 661 {
617 else 662 nbytes = buf - encode_terminal_src;
618 *buf++ = SPACEGLYPH; 663 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
664 {
665 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
666 encode_terminal_src = xrealloc (encode_terminal_src,
667 encode_terminal_src_size);
668 buf = encode_terminal_src + nbytes;
669 }
670 if (char_charset (c, charset_list, NULL))
671 {
672 /* Store the multibyte form of C at BUF. */
673 buf += CHAR_STRING (c, buf);
619 nchars++; 674 nchars++;
620 } 675 }
621 else 676 else
622 { 677 {
623 /* We have a string in Vglyph_table. */ 678 /* C is not encodable. */
624 Lisp_Object string; 679 *buf++ = '?';
625 680 nchars++;
626 string = tbase[g]; 681 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
627 if (! STRING_MULTIBYTE (string))
628 string = string_to_multibyte (string);
629 nbytes = buf - encode_terminal_buf;
630 if (encode_terminal_bufsize < nbytes + SBYTES (string))
631 { 682 {
632 encode_terminal_bufsize = nbytes + SBYTES (string); 683 *buf++ = '?';
633 encode_terminal_buf = xrealloc (encode_terminal_buf, 684 nchars++;
634 encode_terminal_bufsize); 685 src++;
635 buf = encode_terminal_buf + nbytes;
636 } 686 }
637 bcopy (SDATA (string), buf, SBYTES (string));
638 buf += SBYTES (string);
639 nchars += SCHARS (string);
640 } 687 }
641 } 688 }
689 else
690 {
691 unsigned char *p = SDATA (string), *pend = p + SBYTES (string);
692
693 if (! STRING_MULTIBYTE (string))
694 string = string_to_multibyte (string);
695 nbytes = buf - encode_terminal_src;
696 if (encode_terminal_src_size < nbytes + SBYTES (string))
697 {
698 encode_terminal_src_size = nbytes + SBYTES (string);
699 encode_terminal_src = xrealloc (encode_terminal_src,
700 encode_terminal_src_size);
701 buf = encode_terminal_src + nbytes;
702 }
703 bcopy (SDATA (string), buf, SBYTES (string));
704 buf += SBYTES (string);
705 nchars += SCHARS (string);
706 }
642 } 707 }
643 src++; 708 src++;
644 } 709 }
645 710
646 nbytes = buf - encode_terminal_buf; 711 if (nchars == 0)
647 coding->src_multibyte = 1;
648 coding->dst_multibyte = 0;
649 if (SYMBOLP (coding->pre_write_conversion)
650 && ! NILP (Ffboundp (coding->pre_write_conversion)))
651 { 712 {
652 run_pre_write_conversin_on_c_str (&encode_terminal_buf, 713 coding->produced = 0;
653 &encode_terminal_bufsize, 714 return NULL;
654 nchars, nbytes, coding);
655 nchars = coding->produced_char;
656 nbytes = coding->produced;
657 } 715 }
658 required = nbytes + encoding_buffer_size (coding, nbytes); 716
659 if (encode_terminal_bufsize < required) 717 nbytes = buf - encode_terminal_src;
718 coding->source = encode_terminal_src;
719 if (encode_terminal_dst_size == 0)
660 { 720 {
661 encode_terminal_bufsize = required; 721 encode_terminal_dst_size = encode_terminal_src_size;
662 encode_terminal_buf = xrealloc (encode_terminal_buf, required); 722 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
663 } 723 }
724 coding->destination = encode_terminal_dst;
725 coding->dst_bytes = encode_terminal_dst_size;
726 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
727 /* coding->destination may have been reallocated. */
728 encode_terminal_dst = coding->destination;
729 encode_terminal_dst_size = coding->dst_bytes;
664 730
665 encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes, 731 return (encode_terminal_dst);
666 nbytes, encode_terminal_bufsize - nbytes);
667 return encode_terminal_buf + nbytes;
668} 732}
669 733
670 734
735
671/* An implementation of write_glyphs for termcap frames. */ 736/* An implementation of write_glyphs for termcap frames. */
672 737
673static void 738static void
@@ -1421,11 +1486,14 @@ term_get_fkeys_1 ()
1421#ifdef static 1486#ifdef static
1422#define append_glyph append_glyph_term 1487#define append_glyph append_glyph_term
1423#define produce_stretch_glyph produce_stretch_glyph_term 1488#define produce_stretch_glyph produce_stretch_glyph_term
1489#define append_composite_glyph append_composite_glyph_term
1490#define produce_composite_glyph produce_composite_glyph_term
1424#endif 1491#endif
1425 1492
1426static void append_glyph P_ ((struct it *)); 1493static void append_glyph P_ ((struct it *));
1427static void produce_stretch_glyph P_ ((struct it *)); 1494static void produce_stretch_glyph P_ ((struct it *));
1428 1495static void append_composite_glyph P_ ((struct it *));
1496static void produce_composite_glyph P_ ((struct it *));
1429 1497
1430/* Append glyphs to IT's glyph_row. Called from produce_glyphs for 1498/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1431 terminal frames if IT->glyph_row != NULL. IT->char_to_display is 1499 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
@@ -1486,6 +1554,8 @@ produce_glyphs (it)
1486 struct it *it; 1554 struct it *it;
1487{ 1555{
1488 /* If a hook is installed, let it do the work. */ 1556 /* If a hook is installed, let it do the work. */
1557
1558 /* Nothing but characters are supported on terminal frames. */
1489 xassert (it->what == IT_CHARACTER 1559 xassert (it->what == IT_CHARACTER
1490 || it->what == IT_COMPOSITION 1560 || it->what == IT_COMPOSITION
1491 || it->what == IT_STRETCH); 1561 || it->what == IT_STRETCH);
@@ -1496,11 +1566,11 @@ produce_glyphs (it)
1496 goto done; 1566 goto done;
1497 } 1567 }
1498 1568
1499 /* Nothing but characters are supported on terminal frames. For a 1569 if (it->what == IT_COMPOSITION)
1500 composition sequence, it->c is the first character of the 1570 {
1501 sequence. */ 1571 produce_composite_glyph (it);
1502 xassert (it->what == IT_CHARACTER 1572 goto done;
1503 || it->what == IT_COMPOSITION); 1573 }
1504 1574
1505 /* Maybe translate single-byte characters to multibyte. */ 1575 /* Maybe translate single-byte characters to multibyte. */
1506 it->char_to_display = it->c; 1576 it->char_to_display = it->c;
@@ -1544,28 +1614,24 @@ produce_glyphs (it)
1544 it->pixel_width = nspaces; 1614 it->pixel_width = nspaces;
1545 it->nglyphs = nspaces; 1615 it->nglyphs = nspaces;
1546 } 1616 }
1547 else if (SINGLE_BYTE_CHAR_P (it->c)) 1617 else if (CHAR_BYTE8_P (it->c))
1548 { 1618 {
1549 if (unibyte_display_via_language_environment 1619 if (unibyte_display_via_language_environment
1550 && (it->c >= 0240 1620 && (it->c >= 0240))
1551 || !NILP (Vnonascii_translation_table)))
1552 { 1621 {
1553 int charset;
1554
1555 it->char_to_display = unibyte_char_to_multibyte (it->c); 1622 it->char_to_display = unibyte_char_to_multibyte (it->c);
1556 charset = CHAR_CHARSET (it->char_to_display); 1623 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1557 it->pixel_width = CHARSET_WIDTH (charset);
1558 it->nglyphs = it->pixel_width; 1624 it->nglyphs = it->pixel_width;
1559 if (it->glyph_row) 1625 if (it->glyph_row)
1560 append_glyph (it); 1626 append_glyph (it);
1561 } 1627 }
1562 else 1628 else
1563 { 1629 {
1564 /* Coming here means that it->c is from display table, thus we 1630 /* Coming here means that it->c is from display table, thus
1565 must send the code as is to the terminal. Although there's 1631 we must send the raw 8-bit byte as is to the terminal.
1566 no way to know how many columns it occupies on a screen, it 1632 Although there's no way to know how many columns it
1567 is a good assumption that a single byte code has 1-column 1633 occupies on a screen, it is a good assumption that a
1568 width. */ 1634 single byte code has 1-column width. */
1569 it->pixel_width = it->nglyphs = 1; 1635 it->pixel_width = it->nglyphs = 1;
1570 if (it->glyph_row) 1636 if (it->glyph_row)
1571 append_glyph (it); 1637 append_glyph (it);
@@ -1573,13 +1639,7 @@ produce_glyphs (it)
1573 } 1639 }
1574 else 1640 else
1575 { 1641 {
1576 /* A multi-byte character. The display width is fixed for all 1642 it->pixel_width = CHAR_WIDTH (it->c);
1577 characters of the set. Some of the glyphs may have to be
1578 ignored because they are already displayed in a continued
1579 line. */
1580 int charset = CHAR_CHARSET (it->c);
1581
1582 it->pixel_width = CHARSET_WIDTH (charset);
1583 it->nglyphs = it->pixel_width; 1643 it->nglyphs = it->pixel_width;
1584 1644
1585 if (it->glyph_row) 1645 if (it->glyph_row)
@@ -1669,6 +1729,57 @@ produce_stretch_glyph (it)
1669} 1729}
1670 1730
1671 1731
1732/* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1733 Called from produce_composite_glyph for terminal frames if
1734 IT->glyph_row != NULL. IT->face_id contains the character's
1735 face. */
1736
1737static void
1738append_composite_glyph (it)
1739 struct it *it;
1740{
1741 struct glyph *glyph;
1742
1743 xassert (it->glyph_row);
1744 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1745 if (glyph < it->glyph_row->glyphs[1 + it->area])
1746 {
1747 glyph->type = COMPOSITE_GLYPH;
1748 glyph->pixel_width = it->pixel_width;
1749 glyph->u.cmp_id = it->cmp_id;
1750 glyph->face_id = it->face_id;
1751 glyph->padding_p = 0;
1752 glyph->charpos = CHARPOS (it->position);
1753 glyph->object = it->object;
1754
1755 ++it->glyph_row->used[it->area];
1756 ++glyph;
1757 }
1758}
1759
1760
1761/* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1762 the composition. We simply produces components of the composition
1763 assuming that that the terminal has a capability to layout/render
1764 it correctly. */
1765
1766static void
1767produce_composite_glyph (it)
1768 struct it *it;
1769{
1770 struct composition *cmp = composition_table[it->cmp_id];
1771 int c;
1772
1773 xassert (cmp->glyph_len > 0);
1774 c = COMPOSITION_GLYPH (cmp, 0);
1775 it->pixel_width = CHAR_WIDTH (it->c);
1776 it->nglyphs = 1;
1777
1778 if (it->glyph_row)
1779 append_composite_glyph (it);
1780}
1781
1782
1672/* Get information about special display element WHAT in an 1783/* Get information about special display element WHAT in an
1673 environment described by IT. WHAT is one of IT_TRUNCATION or 1784 environment described by IT. WHAT is one of IT_TRUNCATION or
1674 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a 1785 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
@@ -3270,7 +3381,8 @@ init_tty (char *name, char *terminal_type, int must_succeed)
3270 3381
3271#endif 3382#endif
3272 3383
3273 encode_terminal_bufsize = 0; 3384 encode_terminal_src_size = 0;
3385 encode_terminal_dst_size = 0;
3274 3386
3275#ifdef HAVE_GPM 3387#ifdef HAVE_GPM
3276 terminal->mouse_position_hook = term_mouse_position; 3388 terminal->mouse_position_hook = term_mouse_position;