aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2008-08-29 07:53:27 +0000
committerKenichi Handa2008-08-29 07:53:27 +0000
commit58753d746d131ad0595730e76e9c66e9db5fc5f9 (patch)
tree1fe81e721171030018e54e4e60854bc9017ad47a /src
parentc3b57f2354e9f7f4be46bda9e5111582d2aa324c (diff)
downloademacs-58753d746d131ad0595730e76e9c66e9db5fc5f9.tar.gz
emacs-58753d746d131ad0595730e76e9c66e9db5fc5f9.zip
Include window.h, frame.h, dispextern.h font.h.
(Vcomposition_function_table) (get_composition_id): Don't handle COMPOSITION_WITH_GLYPH_STRING. (gstring_hash_table, gstring_work, gstring_work_headers): New variables. (gstring_lookup_cache, composition_gstring_put_cache) (composition_gstring_from_id, composition_gstring_p) (composition_gstring_width, fill_gstring_header) (fill_gstring_body, autocmp_chars, composition_compute_stop_pos) (composition_reseat_it, composition_update_it) (composition_adjust_point, Fcomposition_get_gstring): New functions. (syms_of_composite): Initialize gstring_hash_table, gstrint_work, and gstring_work_headers. DEFVAR_LISP composition-function-table. Defsubr compostion_get_gstring.
Diffstat (limited to 'src')
-rw-r--r--src/composite.c776
1 files changed, 764 insertions, 12 deletions
diff --git a/src/composite.c b/src/composite.c
index e0ac92ee20e..1e19033b5a4 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -28,6 +28,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#include "buffer.h" 28#include "buffer.h"
29#include "character.h" 29#include "character.h"
30#include "intervals.h" 30#include "intervals.h"
31#include "window.h"
32#include "frame.h"
33#include "dispextern.h"
34#include "font.h"
31 35
32/* Emacs uses special text property `composition' to support character 36/* Emacs uses special text property `composition' to support character
33 composition. A sequence of characters that have the same (i.e. eq) 37 composition. A sequence of characters that have the same (i.e. eq)
@@ -151,6 +155,7 @@ Lisp_Object Vcompose_chars_after_function;
151Lisp_Object Qauto_composed; 155Lisp_Object Qauto_composed;
152Lisp_Object Vauto_composition_function; 156Lisp_Object Vauto_composition_function;
153Lisp_Object Qauto_composition_function; 157Lisp_Object Qauto_composition_function;
158Lisp_Object Vcomposition_function_table;
154 159
155EXFUN (Fremove_list_of_text_properties, 4); 160EXFUN (Fremove_list_of_text_properties, 4);
156 161
@@ -317,10 +322,6 @@ get_composition_id (charpos, bytepos, nchars, prop, string)
317 : ((INTEGERP (components) || STRINGP (components)) 322 : ((INTEGERP (components) || STRINGP (components))
318 ? COMPOSITION_WITH_ALTCHARS 323 ? COMPOSITION_WITH_ALTCHARS
319 : COMPOSITION_WITH_RULE_ALTCHARS)); 324 : COMPOSITION_WITH_RULE_ALTCHARS));
320 if (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS
321 && VECTORP (components)
322 && ! INTEGERP (AREF (components, 0)))
323 cmp->method = COMPOSITION_WITH_GLYPH_STRING;
324 cmp->hash_index = hash_index; 325 cmp->hash_index = hash_index;
325 glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS 326 glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS
326 ? (XVECTOR (key)->size + 1) / 2 327 ? (XVECTOR (key)->size + 1) / 2
@@ -329,13 +330,7 @@ get_composition_id (charpos, bytepos, nchars, prop, string)
329 cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2); 330 cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2);
330 cmp->font = NULL; 331 cmp->font = NULL;
331 332
332 /* Calculate the width of overall glyphs of the composition. */ 333 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
333 if (cmp->method == COMPOSITION_WITH_GLYPH_STRING)
334 {
335 cmp->width = 1; /* Should be fixed later. */
336 cmp->glyph_len--;
337 }
338 else if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
339 { 334 {
340 /* Relative composition. */ 335 /* Relative composition. */
341 cmp->width = 0; 336 cmp->width = 0;
@@ -645,6 +640,705 @@ compose_text (start, end, components, modification_func, string)
645 Fput_text_property (make_number (start), make_number (end), 640 Fput_text_property (make_number (start), make_number (end),
646 Qcomposition, prop, string); 641 Qcomposition, prop, string);
647} 642}
643
644
645static Lisp_Object autocmp_chars P_ ((Lisp_Object, EMACS_INT, EMACS_INT,
646 EMACS_INT, struct window *,
647 struct face *, Lisp_Object));
648
649
650/* Lisp glyph-string handlers */
651
652/* Hash table for automatic composition. The key is a header of a
653 lgstring (Lispy glyph-string), and the value is a body of a
654 lgstring. */
655
656static Lisp_Object gstring_hash_table;
657
658static Lisp_Object gstring_lookup_cache P_ ((Lisp_Object));
659
660static Lisp_Object
661gstring_lookup_cache (header)
662 Lisp_Object header;
663{
664 struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
665 int i = hash_lookup (h, header, NULL);
666
667 return (i >= 0 ? HASH_VALUE (h, i) : Qnil);
668}
669
670Lisp_Object
671composition_gstring_put_cache (gstring, len)
672 Lisp_Object gstring;
673 int len;
674{
675 struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
676 unsigned hash;
677 Lisp_Object header, copy;
678 int i;
679
680 header = LGSTRING_HEADER (gstring);
681 hash = h->hashfn (h, header);
682 if (len < 0)
683 {
684 len = LGSTRING_GLYPH_LEN (gstring);
685 for (i = 0; i < len; i++)
686 if (NILP (LGSTRING_GLYPH (gstring, i)))
687 break;
688 len = i;
689 }
690
691 copy = Fmake_vector (make_number (len + 2), Qnil);
692 LGSTRING_SET_HEADER (copy, Fcopy_sequence (header));
693 for (i = 0; i < len; i++)
694 LGSTRING_SET_GLYPH (copy, i, Fcopy_sequence (LGSTRING_GLYPH (gstring, i)));
695 i = hash_put (h, LGSTRING_HEADER (copy), copy, hash);
696 LGSTRING_SET_ID (copy, make_number (i));
697 return copy;
698}
699
700Lisp_Object
701composition_gstring_from_id (id)
702 int id;
703{
704 struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
705
706 return HASH_VALUE (h, id);
707}
708
709static Lisp_Object fill_gstring_header P_ ((Lisp_Object, Lisp_Object,
710 Lisp_Object, Lisp_Object,
711 Lisp_Object));
712
713int
714composition_gstring_p (gstring)
715 Lisp_Object gstring;
716{
717 Lisp_Object header;
718 int i;
719
720 if (! VECTORP (gstring) || ASIZE (gstring) < 2)
721 return 0;
722 header = LGSTRING_HEADER (gstring);
723 if (! VECTORP (header) || ASIZE (header) < 2)
724 return 0;
725 if (! NILP (LGSTRING_FONT (gstring))
726 && ! FONT_OBJECT_P (LGSTRING_FONT (gstring)))
727 return 0;
728 for (i = 1; i < ASIZE (LGSTRING_HEADER (gstring)); i++)
729 if (! NATNUMP (AREF (LGSTRING_HEADER (gstring), i)))
730 return 0;
731 if (! NILP (LGSTRING_ID (gstring)) && ! NATNUMP (LGSTRING_ID (gstring)))
732 return 0;
733 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
734 {
735 Lisp_Object glyph = LGSTRING_GLYPH (gstring, i);
736 if (NILP (glyph))
737 break;
738 if (! VECTORP (glyph) || ASIZE (glyph) != LGLYPH_SIZE)
739 return 0;
740 }
741 return 1;
742}
743
744int
745composition_gstring_width (gstring, from, to, metrics)
746 Lisp_Object gstring;
747 int from, to;
748 struct font_metrics *metrics;
749{
750 Lisp_Object *glyph;
751 int width = 0;
752
753 if (metrics)
754 {
755 Lisp_Object font_object = LGSTRING_FONT (gstring);
756 struct font *font = XFONT_OBJECT (font_object);
757
758 metrics->ascent = font->ascent;
759 metrics->descent = font->descent;
760 metrics->width = metrics->lbearing = metrics->rbearing = 0;
761 }
762 for (glyph = &LGSTRING_GLYPH (gstring, from); from < to; from++, glyph++)
763 {
764 int x;
765
766 if (NILP (LGLYPH_ADJUSTMENT (*glyph)))
767 width += LGLYPH_WIDTH (*glyph);
768 else
769 width += LGLYPH_WADJUST (*glyph);
770 if (metrics)
771 {
772 x = metrics->width + LGLYPH_LBEARING (*glyph) + LGLYPH_XOFF (*glyph);
773 if (metrics->lbearing > x)
774 metrics->lbearing = x;
775 x = metrics->width + LGLYPH_RBEARING (*glyph) + LGLYPH_XOFF (*glyph);
776 if (metrics->rbearing < x)
777 metrics->rbearing = x;
778 metrics->width = width;
779 x = LGLYPH_ASCENT (*glyph) - LGLYPH_YOFF (*glyph);
780 if (metrics->ascent < x)
781 metrics->ascent = x;
782 x = LGLYPH_DESCENT (*glyph) - LGLYPH_YOFF (*glyph);
783 if (metrics->descent < x)
784 metrics->descent = x;
785 }
786 }
787 return width;
788}
789
790
791static Lisp_Object gstring_work;
792static Lisp_Object gstring_work_headers;
793
794static Lisp_Object
795fill_gstring_header (header, start, end, font_object, string)
796 Lisp_Object header, start, end, font_object, string;
797{
798 EMACS_INT from, to, from_byte;
799 EMACS_INT len, i;
800
801 if (NILP (string))
802 {
803 if (NILP (current_buffer->enable_multibyte_characters))
804 error ("Attempt to shape unibyte text");
805 validate_region (&start, &end);
806 from = XFASTINT (start);
807 to = XFASTINT (end);
808 from_byte = CHAR_TO_BYTE (from);
809 }
810 else
811 {
812 CHECK_STRING (string);
813 if (! STRING_MULTIBYTE (current_buffer->enable_multibyte_characters))
814 error ("Attempt to shape unibyte text");
815 CHECK_NATNUM (start);
816 from = XINT (start);
817 CHECK_NATNUM (end);
818 to = XINT (end);
819 if (from < 0 || from > to || to > SCHARS (string))
820 args_out_of_range_3 (string, start, end);
821 from_byte = string_char_to_byte (string, from);
822 }
823
824 len = to - from;
825 if (len == 0)
826 error ("Attempt to shape zero-length text");
827 if (VECTORP (header))
828 {
829 if (ASIZE (header) != len + 1)
830 args_out_of_range (header, make_number (len + 1));
831 }
832 else
833 {
834 if (len <= 8)
835 header = AREF (gstring_work_headers, len - 1);
836 else
837 header = Fmake_vector (make_number (len + 1), Qnil);
838 }
839
840 ASET (header, 0, font_object);
841 for (i = 0; i < len; i++)
842 {
843 int c;
844
845 if (NILP (string))
846 FETCH_CHAR_ADVANCE_NO_CHECK (c, from, from_byte);
847 else
848 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, from, from_byte);
849 ASET (header, i + 1, make_number (c));
850 }
851 return header;
852}
853
854extern void font_fill_lglyph_metrics P_ ((Lisp_Object, Lisp_Object));
855
856static void
857fill_gstring_body (gstring)
858 Lisp_Object gstring;
859{
860 Lisp_Object font_object = LGSTRING_FONT (gstring);
861 Lisp_Object header = AREF (gstring, 0);
862 EMACS_INT len = LGSTRING_CHAR_LEN (gstring);
863 EMACS_INT i;
864
865 for (i = 0; i < len; i++)
866 {
867 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
868 int c = XINT (AREF (header, i + 1));
869
870 if (NILP (g))
871 {
872 g = LGLYPH_NEW ();
873 LGSTRING_SET_GLYPH (gstring, i, g);
874 }
875 LGLYPH_SET_FROM (g, i);
876 LGLYPH_SET_TO (g, i);
877 LGLYPH_SET_CHAR (g, c);
878 if (! NILP (font_object))
879 {
880 font_fill_lglyph_metrics (g, font_object);
881 }
882 else
883 {
884 int width = XFASTINT (CHAR_TABLE_REF (Vchar_width_table, c));
885
886 LGLYPH_SET_CODE (g, c);
887 LGLYPH_SET_LBEARING (g, 0);
888 LGLYPH_SET_RBEARING (g, width);
889 LGLYPH_SET_WIDTH (g, width);
890 LGLYPH_SET_ASCENT (g, 1);
891 LGLYPH_SET_DESCENT (g, 0);
892 }
893 LGLYPH_SET_ADJUSTMENT (g, Qnil);
894 }
895 if (i < LGSTRING_GLYPH_LEN (gstring))
896 LGSTRING_SET_GLYPH (gstring, i, Qnil);
897}
898
899EXFUN (Fre_search_forward, 4);
900
901/* Try to compose the characters at CHARPOS according to CFT_ELEMENT
902 which is an element of composition-fucntion-table (which see).
903 LIMIT limits the characters to compose. STRING, if not nil, is a
904 target string. WIN is a window where the characters are being
905 displayed. */
906
907static Lisp_Object
908autocmp_chars (cft_element, charpos, bytepos, limit, win, face, string)
909 Lisp_Object cft_element;
910 EMACS_INT charpos, bytepos, limit;
911 struct window *win;
912 struct face *face;
913 Lisp_Object string;
914{
915 int count = SPECPDL_INDEX ();
916 FRAME_PTR f = XFRAME (win->frame);
917 Lisp_Object pos = make_number (charpos);
918 EMACS_INT pt = PT, pt_byte = PT_BYTE;
919
920 record_unwind_save_match_data ();
921 for (; CONSP (cft_element); cft_element = XCDR (cft_element))
922 {
923 Lisp_Object elt = XCAR (cft_element);
924 Lisp_Object re;
925 Lisp_Object font_object = Qnil, gstring;
926 EMACS_INT to;
927
928 if (! VECTORP (elt) || ASIZE (elt) != 3)
929 continue;
930 re = AREF (elt, 0);
931 if (NILP (string))
932 TEMP_SET_PT_BOTH (charpos, bytepos);
933 if (NILP (re)
934 || (STRINGP (re)
935 && (STRINGP (string)
936 ? EQ (Fstring_match (re, string, pos), pos)
937 : (! NILP (Fre_search_forward (re, make_number (limit), Qt, Qnil))
938 && EQ (Fmatch_beginning (make_number (0)), pos)))))
939 {
940 to = (NILP (re) ? charpos + 1 : XINT (Fmatch_end (make_number (0))));
941#ifdef HAVE_WINDOW_SYSTEM
942 if (FRAME_WINDOW_P (f))
943 {
944 font_object = font_range (charpos, &to, win, face, string);
945 if (! FONT_OBJECT_P (font_object))
946 {
947 if (NILP (string))
948 TEMP_SET_PT_BOTH (pt, pt_byte);
949 return unbind_to (count, Qnil);
950 }
951 }
952#endif /* not HAVE_WINDOW_SYSTEM */
953 gstring = Fcomposition_get_gstring (pos, make_number (to),
954 font_object, string);
955 if (NILP (LGSTRING_ID (gstring)))
956 {
957 Lisp_Object args[6];
958
959 args[0] = Vauto_composition_function;
960 args[1] = AREF (elt, 2);
961 args[2] = pos;
962 args[3] = make_number (to);
963 args[4] = font_object;
964 args[5] = string;
965 gstring = safe_call (6, args);
966 }
967 if (NILP (string))
968 TEMP_SET_PT_BOTH (pt, pt_byte);
969 return unbind_to (count, gstring);
970 }
971 }
972 if (NILP (string))
973 TEMP_SET_PT_BOTH (pt, pt_byte);
974 return unbind_to (count, Qnil);
975}
976
977
978/* Update cmp_it->stop_pos to the next position after CHARPOS (and
979 BYTEPOS) where character composition may happen. If BYTEPOS is
980 negative, compoute it. If it is a static composition, set
981 cmp_it->ch to -1. Otherwise, set cmp_it->ch to the character that
982 triggers a automatic composition. */
983
984void
985composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string)
986 struct composition_it *cmp_it;
987 EMACS_INT charpos, bytepos, endpos;
988 Lisp_Object string;
989{
990 EMACS_INT start, end, c;
991 Lisp_Object prop, val;
992
993 cmp_it->stop_pos = endpos;
994 if (find_composition (charpos, endpos, &start, &end, &prop, string)
995 && COMPOSITION_VALID_P (start, end, prop))
996 {
997 cmp_it->stop_pos = endpos = start;
998 cmp_it->ch = -1;
999 }
1000 if (NILP (current_buffer->enable_multibyte_characters)
1001 || ! FUNCTIONP (Vauto_composition_function))
1002 return;
1003 if (bytepos < 0)
1004 {
1005 if (STRINGP (string))
1006 bytepos = string_char_to_byte (string, charpos);
1007 else
1008 bytepos = CHAR_TO_BYTE (charpos);
1009 }
1010
1011 start = charpos;
1012 while (charpos < endpos)
1013 {
1014 if (STRINGP (string))
1015 FETCH_STRING_CHAR_ADVANCE (c, string, charpos, bytepos);
1016 else
1017 FETCH_CHAR_ADVANCE (c, charpos, bytepos);
1018 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1019 if (! NILP (val))
1020 {
1021 Lisp_Object elt;
1022
1023 for (; CONSP (val); val = XCDR (val))
1024 {
1025 elt = XCAR (val);
1026 if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1))
1027 && charpos - 1 - XFASTINT (AREF (elt, 1)) >= start)
1028 break;
1029 }
1030 if (CONSP (val))
1031 {
1032 cmp_it->stop_pos = charpos - 1 - XFASTINT (AREF (elt, 1));
1033 cmp_it->ch = c;
1034 break;
1035 }
1036 }
1037 }
1038}
1039
1040/* Check if the character at CHARPOS (and BYTEPOS) is composed
1041 (possibly with the following charaters) on window W. ENDPOS limits
1042 characters to be composed. FACE, in non-NULL, is a base face of
1043 the character. If STRING is not nil, it is a string containing the
1044 character to check, and CHARPOS and BYTEPOS are indices in the
1045 string. In that case, FACE must not be NULL.
1046
1047 If the character is composed, setup members of CMP_IT (id, nglyphs,
1048 and from), and return 1. Otherwise, update CMP_IT->stop_pos, and
1049 return 0. */
1050
1051int
1052composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string)
1053 struct composition_it *cmp_it;
1054 EMACS_INT charpos, bytepos, endpos;
1055 struct window *w;
1056 struct face *face;
1057 Lisp_Object string;
1058{
1059 if (cmp_it->ch < 0)
1060 {
1061 /* We are looking at a static composition. */
1062 EMACS_INT start, end;
1063 Lisp_Object prop;
1064
1065 find_composition (charpos, -1, &start, &end, &prop, string);
1066 cmp_it->id = get_composition_id (charpos, bytepos, end - start,
1067 prop, string);
1068 if (cmp_it->id < 0)
1069 goto no_composition;
1070 cmp_it->nchars = end - start;
1071 cmp_it->nglyphs = composition_table[cmp_it->id]->glyph_len;
1072 }
1073 else
1074 {
1075 Lisp_Object val;
1076 int i;
1077
1078 val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch);
1079 if (NILP (val))
1080 goto no_composition;
1081 val = autocmp_chars (val, charpos, bytepos, endpos, w, face, string);
1082 if (! composition_gstring_p (val))
1083 goto no_composition;
1084 if (NILP (LGSTRING_ID (val)))
1085 val = composition_gstring_put_cache (val, -1);
1086 cmp_it->id = XINT (LGSTRING_ID (val));
1087 for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++)
1088 if (NILP (LGSTRING_GLYPH (val, i)))
1089 break;
1090 cmp_it->nglyphs = i;
1091 }
1092 cmp_it->from = 0;
1093 return 1;
1094
1095 no_composition:
1096 charpos++;
1097 if (STRINGP (string))
1098 bytepos += MULTIBYTE_LENGTH_NO_CHECK (SDATA (string) + bytepos);
1099 else
1100 INC_POS (bytepos);
1101 composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
1102 return 0;
1103}
1104
1105int
1106composition_update_it (cmp_it, charpos, bytepos, string)
1107 struct composition_it *cmp_it;
1108 EMACS_INT charpos, bytepos;
1109 Lisp_Object string;
1110{
1111 int i, c;
1112
1113 if (cmp_it->ch < 0)
1114 {
1115 struct composition *cmp = composition_table[cmp_it->id];
1116
1117 cmp_it->to = cmp_it->nglyphs;
1118 if (cmp_it->nglyphs == 0)
1119 c = -1;
1120 else
1121 {
1122 for (i = 0; i < cmp->glyph_len; i++)
1123 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
1124 break;
1125 if (c == '\t')
1126 c = ' ';
1127 }
1128 cmp_it->width = cmp->width;
1129 }
1130 else
1131 {
1132 Lisp_Object gstring = composition_gstring_from_id (cmp_it->id);
1133
1134 if (cmp_it->nglyphs == 0)
1135 {
1136 c = -1;
1137 cmp_it->nchars = LGSTRING_CHAR_LEN (gstring);
1138 cmp_it->width = 0;
1139 }
1140 else
1141 {
1142 Lisp_Object glyph = LGSTRING_GLYPH (gstring, cmp_it->from);
1143 int from = LGLYPH_FROM (glyph);
1144
1145 c = LGSTRING_CHAR (gstring, from);
1146 cmp_it->nchars = LGLYPH_TO (glyph) - from + 1;
1147 cmp_it->width = (LGLYPH_WIDTH (glyph) > 0
1148 ? CHAR_WIDTH (LGLYPH_CHAR (glyph)) : 0);
1149 for (cmp_it->to = cmp_it->from + 1; cmp_it->to < cmp_it->nglyphs;
1150 cmp_it->to++)
1151 {
1152 glyph = LGSTRING_GLYPH (gstring, cmp_it->to);
1153 if (LGLYPH_FROM (glyph) != from)
1154 break;
1155 if (LGLYPH_WIDTH (glyph) > 0)
1156 cmp_it->width += CHAR_WIDTH (LGLYPH_CHAR (glyph));
1157 }
1158 }
1159 }
1160
1161 charpos += cmp_it->nchars;
1162 if (STRINGP (string))
1163 cmp_it->nbytes = string_char_to_byte (string, charpos) - bytepos;
1164 else
1165 cmp_it->nbytes = CHAR_TO_BYTE (charpos) - bytepos;
1166 return c;
1167}
1168
1169
1170int
1171composition_adjust_point (last_pt)
1172 EMACS_INT last_pt;
1173{
1174 /* Now check the automatic composition. */
1175 EMACS_INT charpos, bytepos, startpos, beg, end, pos;
1176 Lisp_Object val, cat;
1177 EMACS_INT limit;
1178 int c;
1179
1180 if (PT == BEGV || PT == ZV)
1181 return PT;
1182
1183 if (get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil)
1184 && COMPOSITION_VALID_P (beg, end, val)
1185 && beg < PT /* && end > PT <- It's always the case. */
1186 && (last_pt <= beg || last_pt >= end))
1187 return (PT < last_pt ? beg : end);
1188
1189 if (NILP (current_buffer->enable_multibyte_characters)
1190 || ! FUNCTIONP (Vauto_composition_function))
1191 return PT;
1192
1193 c = FETCH_MULTIBYTE_CHAR (PT_BYTE);
1194 cat = CHAR_TABLE_REF (Vunicode_category_table, c);
1195 if (SYMBOLP (cat)
1196 && ((c = SDATA (SYMBOL_NAME (cat))[0]) == 'C' || c == 'Z'))
1197 /* A control character is never composed. */
1198 return PT;
1199
1200 charpos = PT;
1201 bytepos = PT_BYTE;
1202 limit = (last_pt < PT ? last_pt : BEGV);
1203 do {
1204 DEC_BOTH (charpos, bytepos);
1205 c = FETCH_MULTIBYTE_CHAR (bytepos);
1206 cat = CHAR_TABLE_REF (Vunicode_category_table, c);
1207 if (SYMBOLP (cat)
1208 && ((c = SDATA (SYMBOL_NAME (cat))[0]) == 'C' || c == 'Z'))
1209 {
1210 INC_BOTH (charpos, bytepos);
1211 break;
1212 }
1213 } while (charpos > limit);
1214
1215
1216 limit = (last_pt < PT ? ZV : last_pt);
1217 if (limit > PT + 3)
1218 limit = PT + 3;
1219 startpos = charpos;
1220 while (charpos < limit)
1221 {
1222 c = FETCH_MULTIBYTE_CHAR (bytepos);
1223 if (charpos > PT)
1224 {
1225 int ch;
1226
1227 cat = CHAR_TABLE_REF (Vunicode_category_table, c);
1228 if (SYMBOLP (cat)
1229 && ((ch = SDATA (SYMBOL_NAME (cat))[0]) == 'C' || ch == 'Z'))
1230 return PT;
1231 }
1232 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1233 if (! CONSP (val))
1234 {
1235 INC_BOTH (charpos, bytepos);
1236 continue;
1237 }
1238 for (; CONSP (val); val = XCDR (val))
1239 {
1240 Lisp_Object elt = XCAR (val);
1241
1242 if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1))
1243 && (pos = charpos - XFASTINT (AREF (elt, 1))) < PT
1244 && pos >= startpos)
1245 {
1246 Lisp_Object gstring;
1247 EMACS_INT pos_byte;
1248
1249 if (XFASTINT (AREF (elt, 1)) == 0)
1250 pos_byte = bytepos;
1251 else
1252 pos_byte = CHAR_TO_BYTE (pos);
1253 gstring = autocmp_chars (val, pos, pos_byte, Z,
1254 XWINDOW (selected_window), NULL, Qnil);
1255 if (composition_gstring_p (gstring))
1256 {
1257 if (pos + LGSTRING_CHAR_LEN (gstring) > PT)
1258 {
1259 int i;
1260
1261 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
1262 {
1263 Lisp_Object glyph = LGSTRING_GLYPH (gstring, i);
1264
1265 if (NILP (glyph))
1266 break;
1267 if (pos + LGLYPH_FROM (glyph) == PT)
1268 return PT;
1269 if (pos + LGLYPH_TO (glyph) + 1 > PT)
1270 return (PT < last_pt
1271 ? pos + LGLYPH_FROM (glyph)
1272 : pos + LGLYPH_TO (glyph) + 1);
1273 }
1274 return PT;
1275 }
1276 charpos = startpos = pos + LGSTRING_CHAR_LEN (gstring);
1277 bytepos = CHAR_TO_BYTE (charpos);
1278 break;
1279 }
1280 }
1281 }
1282 if (! CONSP (val))
1283 INC_BOTH (charpos, bytepos);
1284 }
1285 return PT;
1286}
1287
1288DEFUN ("composition-get-gstring", Fcomposition_get_gstring,
1289 Scomposition_get_gstring, 4, 4, 0,
1290 doc: /* Return a glyph-string for characters between FROM and TO.
1291If the glhph string is for graphic display, FONT-OBJECT must be
1292a font-object to use for those characters.
1293Otherwise (for terminal display), FONT-OBJECT must be nil.
1294
1295If the optional 4th argument STRING is not nil, it is a string
1296containing the target characters between indices FROM and TO.
1297
1298A glhph-string is a vector containing information about how to display
1299specific character sequence. The format is:
1300 [HEADER ID GLYPH ...]
1301
1302HEADER is a vector of this form:
1303 [FONT-OBJECT CHAR ...]
1304where
1305 FONT-OBJECT is a font-object for all glyphs in the glyph-string,
1306 or nil if not yet decided.
1307 CHARs are characters to be composed by GLYPHs.
1308
1309ID is an identification number of the glyph-string. It may be nil if
1310not yet shaped.
1311
1312GLYPH is a vector whose elements has this form:
1313 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
1314 [ [X-OFF Y-OFF WADJUST] | nil] ]
1315where
1316 FROM-IDX and TO-IDX are used internally and should not be touched.
1317 C is the character of the glyph.
1318 CODE is the glyph-code of C in FONT-OBJECT.
1319 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
1320 X-OFF and Y-OFF are offests to the base position for the glyph.
1321 WADJUST is the adjustment to the normal width of the glyph.
1322
1323If GLYPH is nil, the remaining elements of the glhph-string vector
1324must be ignore. */)
1325 (from, to, font_object, string)
1326 Lisp_Object font_object, from, to, string;
1327{
1328 Lisp_Object gstring, header;
1329
1330 if (! NILP (font_object))
1331 CHECK_FONT_OBJECT (font_object);
1332 header = fill_gstring_header (Qnil, from, to, font_object, string);
1333 gstring = gstring_lookup_cache (header);
1334 if (! NILP (gstring))
1335 return gstring;
1336 LGSTRING_SET_HEADER (gstring_work, header);
1337 LGSTRING_SET_ID (gstring_work, Qnil);
1338 fill_gstring_body (gstring_work);
1339 return gstring_work;
1340}
1341
648 1342
649/* Emacs Lisp APIs. */ 1343/* Emacs Lisp APIs. */
650 1344
@@ -771,10 +1465,12 @@ See `find-composition' for more detail. */)
771void 1465void
772syms_of_composite () 1466syms_of_composite ()
773{ 1467{
1468 int i;
1469
774 Qcomposition = intern ("composition"); 1470 Qcomposition = intern ("composition");
775 staticpro (&Qcomposition); 1471 staticpro (&Qcomposition);
776 1472
777 /* Make a hash table for composition. */ 1473 /* Make a hash table for static composition. */
778 { 1474 {
779 Lisp_Object args[6]; 1475 Lisp_Object args[6];
780 extern Lisp_Object QCsize; 1476 extern Lisp_Object QCsize;
@@ -794,6 +1490,28 @@ syms_of_composite ()
794 staticpro (&composition_hash_table); 1490 staticpro (&composition_hash_table);
795 } 1491 }
796 1492
1493 /* Make a hash table for glyph-string. */
1494 {
1495 Lisp_Object args[6];
1496 extern Lisp_Object QCsize;
1497
1498 args[0] = QCtest;
1499 args[1] = Qequal;
1500 args[2] = QCweakness;
1501 args[3] = Qnil;
1502 args[4] = QCsize;
1503 args[5] = make_number (311);
1504 gstring_hash_table = Fmake_hash_table (6, args);
1505 staticpro (&gstring_hash_table);
1506 }
1507
1508 staticpro (&gstring_work_headers);
1509 gstring_work_headers = Fmake_vector (make_number (8), Qnil);
1510 for (i = 0; i < 8; i++)
1511 ASET (gstring_work_headers, i, Fmake_vector (make_number (i + 2), Qnil));
1512 staticpro (&gstring_work);
1513 gstring_work = Fmake_vector (make_number (10), Qnil);
1514
797 /* Text property `composition' should be nonsticky by default. */ 1515 /* Text property `composition' should be nonsticky by default. */
798 Vtext_property_default_nonsticky 1516 Vtext_property_default_nonsticky
799 = Fcons (Fcons (Qcomposition, Qt), Vtext_property_default_nonsticky); 1517 = Fcons (Fcons (Qcomposition, Qt), Vtext_property_default_nonsticky);
@@ -831,9 +1549,43 @@ string. In this case, the function must compose characters in the
831string. */); 1549string. */);
832 Vauto_composition_function = Qnil; 1550 Vauto_composition_function = Qnil;
833 1551
1552 DEFVAR_LISP ("composition-function-table", &Vcomposition_function_table,
1553 doc: /* Char-able of functions for automatic character composition.
1554For each character that has to be composed automatically with
1555preceding and/or following characters, this char-table contains
1556a function to call to compose that character.
1557
1558The element at index C in the table, if non-nil, is a list of
1559this form: ([PATTERN PREV-CHARS FUNC] ...)
1560
1561PATTERN is a regular expression with which C and the surrounding
1562characters must match.
1563
1564PREV-CHARS is a number of characters before C to check the
1565matching with PATTERN. If it is 0, PATTERN must match with C and
1566the following characters. If it is 1, PATTERN must match with a
1567character before C and the following characters.
1568
1569If PREV-CHARS is 0, PATTERN can be nil, which means that the
1570single character C should be composed.
1571
1572FUNC is a function to return a glyph-string representing a
1573composition of the characters matching with PATTERN. It is
1574called with one argument GSTRING.
1575
1576GSTRING is a template of a glyph-string to return. It is already
1577filled with a proper header for the characters to compose, and
1578glyphs corresponding to those characters one by one. The
1579function must return a new glyph-string of the same header as
1580GSTRING, or modify GSTRING itself and return it.
1581
1582See also the documentation of `auto-composition-mode'. */);
1583 Vcomposition_function_table = Fmake_char_table (Qnil, Qnil);
1584
834 defsubr (&Scompose_region_internal); 1585 defsubr (&Scompose_region_internal);
835 defsubr (&Scompose_string_internal); 1586 defsubr (&Scompose_string_internal);
836 defsubr (&Sfind_composition_internal); 1587 defsubr (&Sfind_composition_internal);
1588 defsubr (&Scomposition_get_gstring);
837} 1589}
838 1590
839/* arch-tag: 79cefaf8-ca48-4eed-97e5-d5afb290d272 1591/* arch-tag: 79cefaf8-ca48-4eed-97e5-d5afb290d272