diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 689 |
1 files changed, 365 insertions, 324 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index d0b557c3595..3f73391c0aa 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -188,6 +188,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 188 | #include "coding.h" | 188 | #include "coding.h" |
| 189 | #include "process.h" | 189 | #include "process.h" |
| 190 | #include "region-cache.h" | 190 | #include "region-cache.h" |
| 191 | #include "font.h" | ||
| 191 | #include "fontset.h" | 192 | #include "fontset.h" |
| 192 | #include "blockinput.h" | 193 | #include "blockinput.h" |
| 193 | 194 | ||
| @@ -767,7 +768,6 @@ static enum prop_handled handle_display_prop P_ ((struct it *)); | |||
| 767 | static enum prop_handled handle_composition_prop P_ ((struct it *)); | 768 | static enum prop_handled handle_composition_prop P_ ((struct it *)); |
| 768 | static enum prop_handled handle_overlay_change P_ ((struct it *)); | 769 | static enum prop_handled handle_overlay_change P_ ((struct it *)); |
| 769 | static enum prop_handled handle_fontified_prop P_ ((struct it *)); | 770 | static enum prop_handled handle_fontified_prop P_ ((struct it *)); |
| 770 | static enum prop_handled handle_auto_composed_prop P_ ((struct it *)); | ||
| 771 | 771 | ||
| 772 | /* Properties handled by iterators. */ | 772 | /* Properties handled by iterators. */ |
| 773 | 773 | ||
| @@ -779,7 +779,6 @@ static struct props it_props[] = | |||
| 779 | {&Qface, FACE_PROP_IDX, handle_face_prop}, | 779 | {&Qface, FACE_PROP_IDX, handle_face_prop}, |
| 780 | {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop}, | 780 | {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop}, |
| 781 | {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop}, | 781 | {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop}, |
| 782 | {&Qauto_composed, AUTO_COMPOSED_PROP_IDX, handle_auto_composed_prop}, | ||
| 783 | {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop}, | 782 | {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop}, |
| 784 | {NULL, 0, NULL} | 783 | {NULL, 0, NULL} |
| 785 | }; | 784 | }; |
| @@ -2574,6 +2573,8 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) | |||
| 2574 | it->w = w; | 2573 | it->w = w; |
| 2575 | it->f = XFRAME (w->frame); | 2574 | it->f = XFRAME (w->frame); |
| 2576 | 2575 | ||
| 2576 | it->cmp_it.id = -1; | ||
| 2577 | |||
| 2577 | /* Extra space between lines (on window systems only). */ | 2578 | /* Extra space between lines (on window systems only). */ |
| 2578 | if (base_face_id == DEFAULT_FACE_ID | 2579 | if (base_face_id == DEFAULT_FACE_ID |
| 2579 | && FRAME_WINDOW_P (it->f)) | 2580 | && FRAME_WINDOW_P (it->f)) |
| @@ -3181,6 +3182,7 @@ compute_stop_pos (it) | |||
| 3181 | { | 3182 | { |
| 3182 | register INTERVAL iv, next_iv; | 3183 | register INTERVAL iv, next_iv; |
| 3183 | Lisp_Object object, limit, position; | 3184 | Lisp_Object object, limit, position; |
| 3185 | EMACS_INT charpos, bytepos; | ||
| 3184 | 3186 | ||
| 3185 | /* If nowhere else, stop at the end. */ | 3187 | /* If nowhere else, stop at the end. */ |
| 3186 | it->stop_charpos = it->end_charpos; | 3188 | it->stop_charpos = it->end_charpos; |
| @@ -3191,19 +3193,22 @@ compute_stop_pos (it) | |||
| 3191 | properties. */ | 3193 | properties. */ |
| 3192 | object = it->string; | 3194 | object = it->string; |
| 3193 | limit = Qnil; | 3195 | limit = Qnil; |
| 3194 | position = make_number (IT_STRING_CHARPOS (*it)); | 3196 | charpos = IT_STRING_CHARPOS (*it); |
| 3197 | bytepos = IT_STRING_BYTEPOS (*it); | ||
| 3195 | } | 3198 | } |
| 3196 | else | 3199 | else |
| 3197 | { | 3200 | { |
| 3198 | int charpos; | 3201 | EMACS_INT pos; |
| 3199 | 3202 | ||
| 3200 | /* If next overlay change is in front of the current stop pos | 3203 | /* If next overlay change is in front of the current stop pos |
| 3201 | (which is IT->end_charpos), stop there. Note: value of | 3204 | (which is IT->end_charpos), stop there. Note: value of |
| 3202 | next_overlay_change is point-max if no overlay change | 3205 | next_overlay_change is point-max if no overlay change |
| 3203 | follows. */ | 3206 | follows. */ |
| 3204 | charpos = next_overlay_change (IT_CHARPOS (*it)); | 3207 | charpos = IT_CHARPOS (*it); |
| 3205 | if (charpos < it->stop_charpos) | 3208 | bytepos = IT_BYTEPOS (*it); |
| 3206 | it->stop_charpos = charpos; | 3209 | pos = next_overlay_change (charpos); |
| 3210 | if (pos < it->stop_charpos) | ||
| 3211 | it->stop_charpos = pos; | ||
| 3207 | 3212 | ||
| 3208 | /* If showing the region, we have to stop at the region | 3213 | /* If showing the region, we have to stop at the region |
| 3209 | start or end because the face might change there. */ | 3214 | start or end because the face might change there. */ |
| @@ -3219,12 +3224,11 @@ compute_stop_pos (it) | |||
| 3219 | property changes. */ | 3224 | property changes. */ |
| 3220 | XSETBUFFER (object, current_buffer); | 3225 | XSETBUFFER (object, current_buffer); |
| 3221 | limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT); | 3226 | limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT); |
| 3222 | position = make_number (IT_CHARPOS (*it)); | ||
| 3223 | |||
| 3224 | } | 3227 | } |
| 3225 | 3228 | ||
| 3226 | /* Get the interval containing IT's position. Value is a null | 3229 | /* Get the interval containing IT's position. Value is a null |
| 3227 | interval if there isn't such an interval. */ | 3230 | interval if there isn't such an interval. */ |
| 3231 | position = make_number (charpos); | ||
| 3228 | iv = validate_interval_range (object, &position, &position, 0); | 3232 | iv = validate_interval_range (object, &position, &position, 0); |
| 3229 | if (!NULL_INTERVAL_P (iv)) | 3233 | if (!NULL_INTERVAL_P (iv)) |
| 3230 | { | 3234 | { |
| @@ -3268,6 +3272,9 @@ compute_stop_pos (it) | |||
| 3268 | } | 3272 | } |
| 3269 | } | 3273 | } |
| 3270 | 3274 | ||
| 3275 | composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, | ||
| 3276 | it->stop_charpos, it->string); | ||
| 3277 | |||
| 3271 | xassert (STRINGP (it->string) | 3278 | xassert (STRINGP (it->string) |
| 3272 | || (it->stop_charpos >= BEGV | 3279 | || (it->stop_charpos >= BEGV |
| 3273 | && it->stop_charpos >= IT_CHARPOS (*it))); | 3280 | && it->stop_charpos >= IT_CHARPOS (*it))); |
| @@ -3600,7 +3607,8 @@ face_before_or_after_it_pos (it, before_p) | |||
| 3600 | /* For composition, we must check the character after the | 3607 | /* For composition, we must check the character after the |
| 3601 | composition. */ | 3608 | composition. */ |
| 3602 | pos = (it->what == IT_COMPOSITION | 3609 | pos = (it->what == IT_COMPOSITION |
| 3603 | ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string) | 3610 | ? string_pos (IT_STRING_CHARPOS (*it) |
| 3611 | + it->cmp_it.nchars, it->string) | ||
| 3604 | : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string)); | 3612 | : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string)); |
| 3605 | 3613 | ||
| 3606 | if (it->current.overlay_string_index >= 0) | 3614 | if (it->current.overlay_string_index >= 0) |
| @@ -3650,7 +3658,7 @@ face_before_or_after_it_pos (it, before_p) | |||
| 3650 | if (it->what == IT_COMPOSITION) | 3658 | if (it->what == IT_COMPOSITION) |
| 3651 | /* For composition, we must check the position after the | 3659 | /* For composition, we must check the position after the |
| 3652 | composition. */ | 3660 | composition. */ |
| 3653 | pos.charpos += it->cmp_len, pos.bytepos += it->len; | 3661 | pos.charpos += it->cmp_it.nchars, pos.bytepos += it->len; |
| 3654 | else | 3662 | else |
| 3655 | INC_TEXT_POS (pos, it->multibyte_p); | 3663 | INC_TEXT_POS (pos, it->multibyte_p); |
| 3656 | } | 3664 | } |
| @@ -4624,97 +4632,6 @@ string_buffer_position (w, string, around_charpos) | |||
| 4624 | `composition' property | 4632 | `composition' property |
| 4625 | ***********************************************************************/ | 4633 | ***********************************************************************/ |
| 4626 | 4634 | ||
| 4627 | static enum prop_handled | ||
| 4628 | handle_auto_composed_prop (it) | ||
| 4629 | struct it *it; | ||
| 4630 | { | ||
| 4631 | enum prop_handled handled = HANDLED_NORMALLY; | ||
| 4632 | |||
| 4633 | if (FUNCTIONP (Vauto_composition_function)) | ||
| 4634 | { | ||
| 4635 | Lisp_Object val = Qnil; | ||
| 4636 | EMACS_INT pos, limit = -1; | ||
| 4637 | |||
| 4638 | if (STRINGP (it->string)) | ||
| 4639 | pos = IT_STRING_CHARPOS (*it); | ||
| 4640 | else | ||
| 4641 | pos = IT_CHARPOS (*it); | ||
| 4642 | |||
| 4643 | val = Fget_text_property (make_number (pos), Qauto_composed, it->string); | ||
| 4644 | if (! NILP (val)) | ||
| 4645 | { | ||
| 4646 | Lisp_Object cmp_prop; | ||
| 4647 | EMACS_INT cmp_start, cmp_end; | ||
| 4648 | |||
| 4649 | if (get_property_and_range (pos, Qcomposition, &cmp_prop, | ||
| 4650 | &cmp_start, &cmp_end, it->string) | ||
| 4651 | && cmp_start == pos | ||
| 4652 | && COMPOSITION_METHOD (cmp_prop) == COMPOSITION_WITH_GLYPH_STRING) | ||
| 4653 | { | ||
| 4654 | Lisp_Object gstring = COMPOSITION_COMPONENTS (cmp_prop); | ||
| 4655 | Lisp_Object font_object = LGSTRING_FONT (gstring); | ||
| 4656 | |||
| 4657 | if (! EQ (font_object, | ||
| 4658 | font_at (-1, pos, FACE_FROM_ID (it->f, it->face_id), | ||
| 4659 | it->w, it->string))) | ||
| 4660 | /* We must re-compute the composition for the | ||
| 4661 | different font. */ | ||
| 4662 | val = Qnil; | ||
| 4663 | } | ||
| 4664 | |||
| 4665 | if (! NILP (val)) | ||
| 4666 | { | ||
| 4667 | Lisp_Object end; | ||
| 4668 | |||
| 4669 | /* As Fnext_single_char_property_change is very slow, we | ||
| 4670 | limit the search to the current line. */ | ||
| 4671 | if (STRINGP (it->string)) | ||
| 4672 | limit = SCHARS (it->string); | ||
| 4673 | else | ||
| 4674 | limit = find_next_newline_no_quit (pos, 1); | ||
| 4675 | end = Fnext_single_char_property_change (make_number (pos), | ||
| 4676 | Qauto_composed, | ||
| 4677 | it->string, | ||
| 4678 | make_number (limit)); | ||
| 4679 | |||
| 4680 | if (XINT (end) < limit) | ||
| 4681 | /* The current point is auto-composed, but there exist | ||
| 4682 | characters not yet composed beyond the | ||
| 4683 | auto-composed region. There's a possiblity that | ||
| 4684 | the last characters in the region may be newly | ||
| 4685 | composed. */ | ||
| 4686 | val = Qnil; | ||
| 4687 | } | ||
| 4688 | } | ||
| 4689 | if (NILP (val) && ! STRINGP (it->string)) | ||
| 4690 | { | ||
| 4691 | if (limit < 0) | ||
| 4692 | limit = (STRINGP (it->string) ? SCHARS (it->string) | ||
| 4693 | : find_next_newline_no_quit (pos, 1)); | ||
| 4694 | if (pos < limit) | ||
| 4695 | { | ||
| 4696 | int count = SPECPDL_INDEX (); | ||
| 4697 | Lisp_Object args[5]; | ||
| 4698 | |||
| 4699 | if (FRAME_WINDOW_P (it->f)) | ||
| 4700 | limit = font_range (pos, limit, | ||
| 4701 | FACE_FROM_ID (it->f, it->face_id), | ||
| 4702 | it->f, it->string); | ||
| 4703 | args[0] = Vauto_composition_function; | ||
| 4704 | specbind (Qauto_composition_function, Qnil); | ||
| 4705 | args[1] = make_number (pos); | ||
| 4706 | args[2] = make_number (limit); | ||
| 4707 | args[3] = it->window; | ||
| 4708 | args[4] = it->string; | ||
| 4709 | safe_call (5, args); | ||
| 4710 | unbind_to (count, Qnil); | ||
| 4711 | } | ||
| 4712 | } | ||
| 4713 | } | ||
| 4714 | |||
| 4715 | return handled; | ||
| 4716 | } | ||
| 4717 | |||
| 4718 | /* Set up iterator IT from `composition' property at its current | 4635 | /* Set up iterator IT from `composition' property at its current |
| 4719 | position. Called from handle_stop. */ | 4636 | position. Called from handle_stop. */ |
| 4720 | 4637 | ||
| @@ -4724,7 +4641,6 @@ handle_composition_prop (it) | |||
| 4724 | { | 4641 | { |
| 4725 | Lisp_Object prop, string; | 4642 | Lisp_Object prop, string; |
| 4726 | EMACS_INT pos, pos_byte, start, end; | 4643 | EMACS_INT pos, pos_byte, start, end; |
| 4727 | enum prop_handled handled = HANDLED_NORMALLY; | ||
| 4728 | 4644 | ||
| 4729 | if (STRINGP (it->string)) | 4645 | if (STRINGP (it->string)) |
| 4730 | { | 4646 | { |
| @@ -4751,8 +4667,6 @@ handle_composition_prop (it) | |||
| 4751 | && COMPOSITION_VALID_P (start, end, prop) | 4667 | && COMPOSITION_VALID_P (start, end, prop) |
| 4752 | && (STRINGP (it->string) || (PT <= start || PT >= end))) | 4668 | && (STRINGP (it->string) || (PT <= start || PT >= end))) |
| 4753 | { | 4669 | { |
| 4754 | int id; | ||
| 4755 | |||
| 4756 | if (start != pos) | 4670 | if (start != pos) |
| 4757 | { | 4671 | { |
| 4758 | if (STRINGP (it->string)) | 4672 | if (STRINGP (it->string)) |
| @@ -4760,63 +4674,17 @@ handle_composition_prop (it) | |||
| 4760 | else | 4674 | else |
| 4761 | pos_byte = CHAR_TO_BYTE (start); | 4675 | pos_byte = CHAR_TO_BYTE (start); |
| 4762 | } | 4676 | } |
| 4763 | id = get_composition_id (start, pos_byte, end - start, prop, string); | 4677 | it->cmp_it.id = get_composition_id (start, pos_byte, end - start, |
| 4678 | prop, string); | ||
| 4764 | 4679 | ||
| 4765 | if (id >= 0) | 4680 | if (it->cmp_it.id >= 0) |
| 4766 | { | 4681 | { |
| 4767 | struct composition *cmp = composition_table[id]; | 4682 | it->cmp_it.nchars = COMPOSITION_LENGTH (prop); |
| 4768 | 4683 | it->cmp_it.nglyphs = -1; | |
| 4769 | if (cmp->glyph_len == 0) | ||
| 4770 | { | ||
| 4771 | /* No glyph. */ | ||
| 4772 | if (STRINGP (it->string)) | ||
| 4773 | { | ||
| 4774 | IT_STRING_CHARPOS (*it) = end; | ||
| 4775 | IT_STRING_BYTEPOS (*it) = string_char_to_byte (it->string, | ||
| 4776 | end); | ||
| 4777 | } | ||
| 4778 | else | ||
| 4779 | { | ||
| 4780 | IT_CHARPOS (*it) = end; | ||
| 4781 | IT_BYTEPOS (*it) = CHAR_TO_BYTE (end); | ||
| 4782 | } | ||
| 4783 | return HANDLED_RECOMPUTE_PROPS; | ||
| 4784 | } | ||
| 4785 | |||
| 4786 | it->stop_charpos = end; | ||
| 4787 | push_it (it); | ||
| 4788 | |||
| 4789 | it->method = GET_FROM_COMPOSITION; | ||
| 4790 | it->cmp_id = id; | ||
| 4791 | it->cmp_len = COMPOSITION_LENGTH (prop); | ||
| 4792 | /* For a terminal, draw only the first (non-TAB) character | ||
| 4793 | of the components. */ | ||
| 4794 | if (composition_table[id]->method == COMPOSITION_WITH_GLYPH_STRING) | ||
| 4795 | { | ||
| 4796 | /* FIXME: This doesn't do anything!?! */ | ||
| 4797 | Lisp_Object lgstring = AREF (XHASH_TABLE (composition_hash_table) | ||
| 4798 | ->key_and_value, | ||
| 4799 | cmp->hash_index * 2); | ||
| 4800 | } | ||
| 4801 | else | ||
| 4802 | { | ||
| 4803 | int i; | ||
| 4804 | |||
| 4805 | for (i = 0; i < cmp->glyph_len; i++) | ||
| 4806 | if ((it->c = COMPOSITION_GLYPH (composition_table[id], i)) | ||
| 4807 | != '\t') | ||
| 4808 | break; | ||
| 4809 | } | ||
| 4810 | if (it->c == '\t') | ||
| 4811 | it->c = ' '; | ||
| 4812 | it->len = (STRINGP (it->string) | ||
| 4813 | ? string_char_to_byte (it->string, end) | ||
| 4814 | : CHAR_TO_BYTE (end)) - pos_byte; | ||
| 4815 | handled = HANDLED_RETURN; | ||
| 4816 | } | 4684 | } |
| 4817 | } | 4685 | } |
| 4818 | 4686 | ||
| 4819 | return handled; | 4687 | return HANDLED_NORMALLY; |
| 4820 | } | 4688 | } |
| 4821 | 4689 | ||
| 4822 | 4690 | ||
| @@ -4872,7 +4740,6 @@ next_overlay_string (it) | |||
| 4872 | it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0); | 4740 | it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0); |
| 4873 | pop_it (it); | 4741 | pop_it (it); |
| 4874 | xassert (it->sp > 0 | 4742 | xassert (it->sp > 0 |
| 4875 | || it->method == GET_FROM_COMPOSITION | ||
| 4876 | || (NILP (it->string) | 4743 | || (NILP (it->string) |
| 4877 | && it->method == GET_FROM_BUFFER | 4744 | && it->method == GET_FROM_BUFFER |
| 4878 | && it->stop_charpos >= BEGV | 4745 | && it->stop_charpos >= BEGV |
| @@ -4904,6 +4771,8 @@ next_overlay_string (it) | |||
| 4904 | SET_TEXT_POS (it->current.string_pos, 0, 0); | 4771 | SET_TEXT_POS (it->current.string_pos, 0, 0); |
| 4905 | it->method = GET_FROM_STRING; | 4772 | it->method = GET_FROM_STRING; |
| 4906 | it->stop_charpos = 0; | 4773 | it->stop_charpos = 0; |
| 4774 | if (it->cmp_it.stop_pos >= 0) | ||
| 4775 | it->cmp_it.stop_pos = 0; | ||
| 4907 | } | 4776 | } |
| 4908 | 4777 | ||
| 4909 | CHECK_IT (it); | 4778 | CHECK_IT (it); |
| @@ -5218,6 +5087,7 @@ push_it (it) | |||
| 5218 | p = it->stack + it->sp; | 5087 | p = it->stack + it->sp; |
| 5219 | 5088 | ||
| 5220 | p->stop_charpos = it->stop_charpos; | 5089 | p->stop_charpos = it->stop_charpos; |
| 5090 | p->cmp_it = it->cmp_it; | ||
| 5221 | xassert (it->face_id >= 0); | 5091 | xassert (it->face_id >= 0); |
| 5222 | p->face_id = it->face_id; | 5092 | p->face_id = it->face_id; |
| 5223 | p->string = it->string; | 5093 | p->string = it->string; |
| @@ -5230,13 +5100,6 @@ push_it (it) | |||
| 5230 | p->u.image.image_id = it->image_id; | 5100 | p->u.image.image_id = it->image_id; |
| 5231 | p->u.image.slice = it->slice; | 5101 | p->u.image.slice = it->slice; |
| 5232 | break; | 5102 | break; |
| 5233 | case GET_FROM_COMPOSITION: | ||
| 5234 | p->u.comp.object = it->object; | ||
| 5235 | p->u.comp.c = it->c; | ||
| 5236 | p->u.comp.len = it->len; | ||
| 5237 | p->u.comp.cmp_id = it->cmp_id; | ||
| 5238 | p->u.comp.cmp_len = it->cmp_len; | ||
| 5239 | break; | ||
| 5240 | case GET_FROM_STRETCH: | 5103 | case GET_FROM_STRETCH: |
| 5241 | p->u.stretch.object = it->object; | 5104 | p->u.stretch.object = it->object; |
| 5242 | break; | 5105 | break; |
| @@ -5273,6 +5136,7 @@ pop_it (it) | |||
| 5273 | --it->sp; | 5136 | --it->sp; |
| 5274 | p = it->stack + it->sp; | 5137 | p = it->stack + it->sp; |
| 5275 | it->stop_charpos = p->stop_charpos; | 5138 | it->stop_charpos = p->stop_charpos; |
| 5139 | it->cmp_it = p->cmp_it; | ||
| 5276 | it->face_id = p->face_id; | 5140 | it->face_id = p->face_id; |
| 5277 | it->current = p->current; | 5141 | it->current = p->current; |
| 5278 | it->position = p->position; | 5142 | it->position = p->position; |
| @@ -5288,13 +5152,6 @@ pop_it (it) | |||
| 5288 | it->object = p->u.image.object; | 5152 | it->object = p->u.image.object; |
| 5289 | it->slice = p->u.image.slice; | 5153 | it->slice = p->u.image.slice; |
| 5290 | break; | 5154 | break; |
| 5291 | case GET_FROM_COMPOSITION: | ||
| 5292 | it->object = p->u.comp.object; | ||
| 5293 | it->c = p->u.comp.c; | ||
| 5294 | it->len = p->u.comp.len; | ||
| 5295 | it->cmp_id = p->u.comp.cmp_id; | ||
| 5296 | it->cmp_len = p->u.comp.cmp_len; | ||
| 5297 | break; | ||
| 5298 | case GET_FROM_STRETCH: | 5155 | case GET_FROM_STRETCH: |
| 5299 | it->object = p->u.comp.object; | 5156 | it->object = p->u.comp.object; |
| 5300 | break; | 5157 | break; |
| @@ -5754,7 +5611,6 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) = | |||
| 5754 | { | 5611 | { |
| 5755 | next_element_from_buffer, | 5612 | next_element_from_buffer, |
| 5756 | next_element_from_display_vector, | 5613 | next_element_from_display_vector, |
| 5757 | next_element_from_composition, | ||
| 5758 | next_element_from_string, | 5614 | next_element_from_string, |
| 5759 | next_element_from_c_string, | 5615 | next_element_from_c_string, |
| 5760 | next_element_from_image, | 5616 | next_element_from_image, |
| @@ -5763,6 +5619,19 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) = | |||
| 5763 | 5619 | ||
| 5764 | #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it) | 5620 | #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it) |
| 5765 | 5621 | ||
| 5622 | |||
| 5623 | /* Return 1 iff a character at CHARPOS (and BYTEPOS) is composed | ||
| 5624 | (possibly with the following characters). */ | ||
| 5625 | |||
| 5626 | #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS) \ | ||
| 5627 | ((IT)->cmp_it.id >= 0 \ | ||
| 5628 | || ((IT)->cmp_it.stop_pos == (CHARPOS) \ | ||
| 5629 | && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \ | ||
| 5630 | (IT)->end_charpos, (IT)->w, \ | ||
| 5631 | FACE_FROM_ID ((IT)->f, (IT)->face_id), \ | ||
| 5632 | (IT)->string))) | ||
| 5633 | |||
| 5634 | |||
| 5766 | /* Load IT's display element fields with information about the next | 5635 | /* Load IT's display element fields with information about the next |
| 5767 | display element from the current position of IT. Value is zero if | 5636 | display element from the current position of IT. Value is zero if |
| 5768 | end of buffer (or C string) is reached. */ | 5637 | end of buffer (or C string) is reached. */ |
| @@ -6037,6 +5906,7 @@ get_next_display_element (it) | |||
| 6037 | } | 5906 | } |
| 6038 | } | 5907 | } |
| 6039 | 5908 | ||
| 5909 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 6040 | /* Adjust face id for a multibyte character. There are no multibyte | 5910 | /* Adjust face id for a multibyte character. There are no multibyte |
| 6041 | character in unibyte text. */ | 5911 | character in unibyte text. */ |
| 6042 | if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION) | 5912 | if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION) |
| @@ -6045,12 +5915,24 @@ get_next_display_element (it) | |||
| 6045 | && FRAME_WINDOW_P (it->f)) | 5915 | && FRAME_WINDOW_P (it->f)) |
| 6046 | { | 5916 | { |
| 6047 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | 5917 | struct face *face = FACE_FROM_ID (it->f, it->face_id); |
| 6048 | int pos = (it->s ? -1 | ||
| 6049 | : STRINGP (it->string) ? IT_STRING_CHARPOS (*it) | ||
| 6050 | : IT_CHARPOS (*it)); | ||
| 6051 | 5918 | ||
| 6052 | it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string); | 5919 | if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0) |
| 5920 | { | ||
| 5921 | /* Automatic composition with glyph-string. */ | ||
| 5922 | Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id); | ||
| 5923 | |||
| 5924 | it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face); | ||
| 5925 | } | ||
| 5926 | else | ||
| 5927 | { | ||
| 5928 | int pos = (it->s ? -1 | ||
| 5929 | : STRINGP (it->string) ? IT_STRING_CHARPOS (*it) | ||
| 5930 | : IT_CHARPOS (*it)); | ||
| 5931 | |||
| 5932 | it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string); | ||
| 5933 | } | ||
| 6053 | } | 5934 | } |
| 5935 | #endif | ||
| 6054 | 5936 | ||
| 6055 | /* Is this character the last one of a run of characters with | 5937 | /* Is this character the last one of a run of characters with |
| 6056 | box? If yes, set IT->end_of_box_run_p to 1. */ | 5938 | box? If yes, set IT->end_of_box_run_p to 1. */ |
| @@ -6105,6 +5987,20 @@ set_iterator_to_next (it, reseat_p) | |||
| 6105 | invisible lines that are so because of selective display. */ | 5987 | invisible lines that are so because of selective display. */ |
| 6106 | if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p) | 5988 | if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p) |
| 6107 | reseat_at_next_visible_line_start (it, 0); | 5989 | reseat_at_next_visible_line_start (it, 0); |
| 5990 | else if (it->cmp_it.id >= 0) | ||
| 5991 | { | ||
| 5992 | IT_CHARPOS (*it) += it->cmp_it.nchars; | ||
| 5993 | IT_BYTEPOS (*it) += it->cmp_it.nbytes; | ||
| 5994 | if (it->cmp_it.to < it->cmp_it.nglyphs) | ||
| 5995 | it->cmp_it.from = it->cmp_it.to; | ||
| 5996 | else | ||
| 5997 | { | ||
| 5998 | it->cmp_it.id = -1; | ||
| 5999 | composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), | ||
| 6000 | IT_BYTEPOS (*it), it->stop_charpos, | ||
| 6001 | Qnil); | ||
| 6002 | } | ||
| 6003 | } | ||
| 6108 | else | 6004 | else |
| 6109 | { | 6005 | { |
| 6110 | xassert (it->len != 0); | 6006 | xassert (it->len != 0); |
| @@ -6114,23 +6010,6 @@ set_iterator_to_next (it, reseat_p) | |||
| 6114 | } | 6010 | } |
| 6115 | break; | 6011 | break; |
| 6116 | 6012 | ||
| 6117 | case GET_FROM_COMPOSITION: | ||
| 6118 | xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions); | ||
| 6119 | xassert (it->sp > 0); | ||
| 6120 | pop_it (it); | ||
| 6121 | if (it->method == GET_FROM_STRING) | ||
| 6122 | { | ||
| 6123 | IT_STRING_BYTEPOS (*it) += it->len; | ||
| 6124 | IT_STRING_CHARPOS (*it) += it->cmp_len; | ||
| 6125 | goto consider_string_end; | ||
| 6126 | } | ||
| 6127 | else if (it->method == GET_FROM_BUFFER) | ||
| 6128 | { | ||
| 6129 | IT_BYTEPOS (*it) += it->len; | ||
| 6130 | IT_CHARPOS (*it) += it->cmp_len; | ||
| 6131 | } | ||
| 6132 | break; | ||
| 6133 | |||
| 6134 | case GET_FROM_C_STRING: | 6013 | case GET_FROM_C_STRING: |
| 6135 | /* Current display element of IT is from a C string. */ | 6014 | /* Current display element of IT is from a C string. */ |
| 6136 | IT_BYTEPOS (*it) += it->len; | 6015 | IT_BYTEPOS (*it) += it->len; |
| @@ -6186,8 +6065,26 @@ set_iterator_to_next (it, reseat_p) | |||
| 6186 | case GET_FROM_STRING: | 6065 | case GET_FROM_STRING: |
| 6187 | /* Current display element is a character from a Lisp string. */ | 6066 | /* Current display element is a character from a Lisp string. */ |
| 6188 | xassert (it->s == NULL && STRINGP (it->string)); | 6067 | xassert (it->s == NULL && STRINGP (it->string)); |
| 6189 | IT_STRING_BYTEPOS (*it) += it->len; | 6068 | if (it->cmp_it.id >= 0) |
| 6190 | IT_STRING_CHARPOS (*it) += 1; | 6069 | { |
| 6070 | IT_STRING_CHARPOS (*it) += it->cmp_it.nchars; | ||
| 6071 | IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes; | ||
| 6072 | if (it->cmp_it.to < it->cmp_it.nglyphs) | ||
| 6073 | it->cmp_it.from = it->cmp_it.to; | ||
| 6074 | else | ||
| 6075 | { | ||
| 6076 | it->cmp_it.id = -1; | ||
| 6077 | composition_compute_stop_pos (&it->cmp_it, | ||
| 6078 | IT_STRING_CHARPOS (*it), | ||
| 6079 | IT_STRING_BYTEPOS (*it), | ||
| 6080 | it->stop_charpos, it->string); | ||
| 6081 | } | ||
| 6082 | } | ||
| 6083 | else | ||
| 6084 | { | ||
| 6085 | IT_STRING_BYTEPOS (*it) += it->len; | ||
| 6086 | IT_STRING_CHARPOS (*it) += 1; | ||
| 6087 | } | ||
| 6191 | 6088 | ||
| 6192 | consider_string_end: | 6089 | consider_string_end: |
| 6193 | 6090 | ||
| @@ -6330,6 +6227,12 @@ next_element_from_string (it) | |||
| 6330 | it->what = IT_EOB; | 6227 | it->what = IT_EOB; |
| 6331 | return 0; | 6228 | return 0; |
| 6332 | } | 6229 | } |
| 6230 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), | ||
| 6231 | IT_STRING_BYTEPOS (*it)) | ||
| 6232 | && next_element_from_composition (it)) | ||
| 6233 | { | ||
| 6234 | return 1; | ||
| 6235 | } | ||
| 6333 | else if (STRING_MULTIBYTE (it->string)) | 6236 | else if (STRING_MULTIBYTE (it->string)) |
| 6334 | { | 6237 | { |
| 6335 | int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); | 6238 | int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); |
| @@ -6360,6 +6263,12 @@ next_element_from_string (it) | |||
| 6360 | it->c = ' ', it->len = 1; | 6263 | it->c = ' ', it->len = 1; |
| 6361 | CHARPOS (position) = BYTEPOS (position) = -1; | 6264 | CHARPOS (position) = BYTEPOS (position) = -1; |
| 6362 | } | 6265 | } |
| 6266 | else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), | ||
| 6267 | IT_STRING_BYTEPOS (*it)) | ||
| 6268 | && next_element_from_composition (it)) | ||
| 6269 | { | ||
| 6270 | return 1; | ||
| 6271 | } | ||
| 6363 | else if (STRING_MULTIBYTE (it->string)) | 6272 | else if (STRING_MULTIBYTE (it->string)) |
| 6364 | { | 6273 | { |
| 6365 | int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); | 6274 | int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); |
| @@ -6546,14 +6455,16 @@ next_element_from_buffer (it) | |||
| 6546 | && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos) | 6455 | && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos) |
| 6547 | run_redisplay_end_trigger_hook (it); | 6456 | run_redisplay_end_trigger_hook (it); |
| 6548 | 6457 | ||
| 6458 | if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it)) | ||
| 6459 | && next_element_from_composition (it)) | ||
| 6460 | { | ||
| 6461 | return 1; | ||
| 6462 | } | ||
| 6463 | |||
| 6549 | /* Get the next character, maybe multibyte. */ | 6464 | /* Get the next character, maybe multibyte. */ |
| 6550 | p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); | 6465 | p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); |
| 6551 | if (it->multibyte_p && !ASCII_BYTE_P (*p)) | 6466 | if (it->multibyte_p && !ASCII_BYTE_P (*p)) |
| 6552 | { | 6467 | it->c = STRING_CHAR_AND_LENGTH (p, 0, it->len); |
| 6553 | int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE) | ||
| 6554 | - IT_BYTEPOS (*it)); | ||
| 6555 | it->c = string_char_and_length (p, maxlen, &it->len); | ||
| 6556 | } | ||
| 6557 | else | 6468 | else |
| 6558 | it->c = *p, it->len = 1; | 6469 | it->c = *p, it->len = 1; |
| 6559 | 6470 | ||
| @@ -6625,22 +6536,43 @@ run_redisplay_end_trigger_hook (it) | |||
| 6625 | } | 6536 | } |
| 6626 | 6537 | ||
| 6627 | 6538 | ||
| 6628 | /* Deliver a composition display element. The iterator IT is already | 6539 | /* Deliver a composition display element. Unlike the other |
| 6629 | filled with composition information (done in | 6540 | next_element_from_XXX, this function is not registered in the array |
| 6630 | handle_composition_prop). Value is always 1. */ | 6541 | get_next_element[]. It is called from next_element_from_buffer and |
| 6542 | next_element_from_string when necessary. */ | ||
| 6631 | 6543 | ||
| 6632 | static int | 6544 | static int |
| 6633 | next_element_from_composition (it) | 6545 | next_element_from_composition (it) |
| 6634 | struct it *it; | 6546 | struct it *it; |
| 6635 | { | 6547 | { |
| 6636 | it->what = IT_COMPOSITION; | 6548 | it->what = IT_COMPOSITION; |
| 6637 | it->position = (STRINGP (it->string) | 6549 | it->len = it->cmp_it.nbytes; |
| 6638 | ? it->current.string_pos | ||
| 6639 | : it->current.pos); | ||
| 6640 | if (STRINGP (it->string)) | 6550 | if (STRINGP (it->string)) |
| 6641 | it->object = it->string; | 6551 | { |
| 6552 | if (it->c < 0) | ||
| 6553 | { | ||
| 6554 | IT_STRING_CHARPOS (*it) += it->cmp_it.nchars; | ||
| 6555 | IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes; | ||
| 6556 | return 0; | ||
| 6557 | } | ||
| 6558 | it->position = it->current.string_pos; | ||
| 6559 | it->object = it->string; | ||
| 6560 | it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it), | ||
| 6561 | IT_STRING_BYTEPOS (*it), it->string); | ||
| 6562 | } | ||
| 6642 | else | 6563 | else |
| 6643 | it->object = it->w->buffer; | 6564 | { |
| 6565 | if (it->c < 0) | ||
| 6566 | { | ||
| 6567 | IT_CHARPOS (*it) += it->cmp_it.nchars; | ||
| 6568 | IT_BYTEPOS (*it) += it->cmp_it.nbytes; | ||
| 6569 | return 0; | ||
| 6570 | } | ||
| 6571 | it->position = it->current.pos; | ||
| 6572 | it->object = it->w->buffer; | ||
| 6573 | it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it), | ||
| 6574 | IT_BYTEPOS (*it), Qnil); | ||
| 6575 | } | ||
| 6644 | return 1; | 6576 | return 1; |
| 6645 | } | 6577 | } |
| 6646 | 6578 | ||
| @@ -15674,7 +15606,7 @@ dump_glyph (row, glyph, area) | |||
| 15674 | else if (glyph->type == COMPOSITE_GLYPH) | 15606 | else if (glyph->type == COMPOSITE_GLYPH) |
| 15675 | { | 15607 | { |
| 15676 | fprintf (stderr, | 15608 | fprintf (stderr, |
| 15677 | " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n", | 15609 | " %5d %4c %6d %c %3d 0x%05x", |
| 15678 | glyph - row->glyphs[TEXT_AREA], | 15610 | glyph - row->glyphs[TEXT_AREA], |
| 15679 | '+', | 15611 | '+', |
| 15680 | glyph->charpos, | 15612 | glyph->charpos, |
| @@ -15684,8 +15616,12 @@ dump_glyph (row, glyph, area) | |||
| 15684 | ? 'S' | 15616 | ? 'S' |
| 15685 | : '-')), | 15617 | : '-')), |
| 15686 | glyph->pixel_width, | 15618 | glyph->pixel_width, |
| 15687 | glyph->u.cmp_id, | 15619 | glyph->u.cmp.id); |
| 15688 | '.', | 15620 | if (glyph->u.cmp.automatic) |
| 15621 | fprintf (stderr, | ||
| 15622 | "[%d-%d]", | ||
| 15623 | glyph->u.cmp.from, glyph->u.cmp.to); | ||
| 15624 | fprintf (stderr, " . %4d %1.1d%1.1d\n" | ||
| 15689 | glyph->face_id, | 15625 | glyph->face_id, |
| 15690 | glyph->left_box_line_p, | 15626 | glyph->left_box_line_p, |
| 15691 | glyph->right_box_line_p); | 15627 | glyph->right_box_line_p); |
| @@ -19609,70 +19545,45 @@ fill_composite_glyph_string (s, base_face, overlaps) | |||
| 19609 | int overlaps; | 19545 | int overlaps; |
| 19610 | { | 19546 | { |
| 19611 | int i; | 19547 | int i; |
| 19548 | /* For all glyphs of this composition, starting at the offset | ||
| 19549 | S->gidx, until we reach the end of the definition or encounter a | ||
| 19550 | glyph that requires the different face, add it to S. */ | ||
| 19551 | struct face *face; | ||
| 19612 | 19552 | ||
| 19613 | xassert (s); | 19553 | xassert (s); |
| 19614 | 19554 | ||
| 19615 | s->for_overlaps = overlaps; | 19555 | s->for_overlaps = overlaps; |
| 19616 | 19556 | s->face = NULL; | |
| 19617 | if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING) | 19557 | s->font = NULL; |
| 19618 | { | 19558 | for (i = s->cmp_from; i < s->cmp->glyph_len; i++) |
| 19619 | Lisp_Object gstring | ||
| 19620 | = AREF (XHASH_TABLE (composition_hash_table)->key_and_value, | ||
| 19621 | s->cmp->hash_index * 2); | ||
| 19622 | |||
| 19623 | s->face = base_face; | ||
| 19624 | s->font = base_face->font; | ||
| 19625 | for (i = 0, s->nchars = 0; i < s->cmp->glyph_len; i++, s->nchars++) | ||
| 19626 | { | ||
| 19627 | Lisp_Object g = LGSTRING_GLYPH (gstring, i); | ||
| 19628 | unsigned code; | ||
| 19629 | XChar2b * store_pos; | ||
| 19630 | if (NILP (g)) | ||
| 19631 | break; | ||
| 19632 | code = LGLYPH_CODE (g); | ||
| 19633 | store_pos = s->char2b + i; | ||
| 19634 | STORE_XCHAR2B (store_pos, code >> 8, code & 0xFF); | ||
| 19635 | } | ||
| 19636 | s->width = s->cmp->pixel_width; | ||
| 19637 | } | ||
| 19638 | else | ||
| 19639 | { | 19559 | { |
| 19640 | /* For all glyphs of this composition, starting at the offset | 19560 | int c = COMPOSITION_GLYPH (s->cmp, i); |
| 19641 | S->gidx, until we reach the end of the definition or encounter a | ||
| 19642 | glyph that requires the different face, add it to S. */ | ||
| 19643 | struct face *face; | ||
| 19644 | 19561 | ||
| 19645 | s->face = NULL; | 19562 | if (c != '\t') |
| 19646 | s->font = NULL; | ||
| 19647 | for (i = s->gidx; i < s->cmp->glyph_len; i++) | ||
| 19648 | { | 19563 | { |
| 19649 | int c = COMPOSITION_GLYPH (s->cmp, i); | 19564 | int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c, |
| 19565 | -1, Qnil); | ||
| 19650 | 19566 | ||
| 19651 | if (c != '\t') | 19567 | face = get_char_face_and_encoding (s->f, c, face_id, |
| 19568 | s->char2b + i, 1, 1); | ||
| 19569 | if (face) | ||
| 19652 | { | 19570 | { |
| 19653 | int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c, | 19571 | if (! s->face) |
| 19654 | -1, Qnil); | ||
| 19655 | |||
| 19656 | face = get_char_face_and_encoding (s->f, c, face_id, | ||
| 19657 | s->char2b + i, 1, 1); | ||
| 19658 | if (face) | ||
| 19659 | { | 19572 | { |
| 19660 | if (! s->face) | 19573 | s->face = face; |
| 19661 | { | 19574 | s->font = s->face->font; |
| 19662 | s->face = face; | ||
| 19663 | s->font = s->face->font; | ||
| 19664 | } | ||
| 19665 | else if (s->face != face) | ||
| 19666 | break; | ||
| 19667 | } | 19575 | } |
| 19576 | else if (s->face != face) | ||
| 19577 | break; | ||
| 19668 | } | 19578 | } |
| 19669 | ++s->nchars; | ||
| 19670 | } | 19579 | } |
| 19671 | 19580 | ++s->nchars; | |
| 19672 | /* All glyph strings for the same composition has the same width, | ||
| 19673 | i.e. the width set for the first component of the composition. */ | ||
| 19674 | s->width = s->first_glyph->pixel_width; | ||
| 19675 | } | 19581 | } |
| 19582 | s->cmp_to = i; | ||
| 19583 | |||
| 19584 | /* All glyph strings for the same composition has the same width, | ||
| 19585 | i.e. the width set for the first component of the composition. */ | ||
| 19586 | s->width = s->first_glyph->pixel_width; | ||
| 19676 | 19587 | ||
| 19677 | /* If the specified font could not be loaded, use the frame's | 19588 | /* If the specified font could not be loaded, use the frame's |
| 19678 | default font, but record the fact that we couldn't load it in | 19589 | default font, but record the fact that we couldn't load it in |
| @@ -19690,7 +19601,43 @@ fill_composite_glyph_string (s, base_face, overlaps) | |||
| 19690 | /* This glyph string must always be drawn with 16-bit functions. */ | 19601 | /* This glyph string must always be drawn with 16-bit functions. */ |
| 19691 | s->two_byte_p = 1; | 19602 | s->two_byte_p = 1; |
| 19692 | 19603 | ||
| 19693 | return s->gidx + s->nchars; | 19604 | return s->cmp_to; |
| 19605 | } | ||
| 19606 | |||
| 19607 | static int | ||
| 19608 | fill_gstring_glyph_string (s, face_id, start, end, overlaps) | ||
| 19609 | struct glyph_string *s; | ||
| 19610 | int face_id; | ||
| 19611 | int start, end, overlaps; | ||
| 19612 | { | ||
| 19613 | struct glyph *glyph, *last; | ||
| 19614 | Lisp_Object lgstring; | ||
| 19615 | int i; | ||
| 19616 | |||
| 19617 | s->for_overlaps = overlaps; | ||
| 19618 | glyph = s->row->glyphs[s->area] + start; | ||
| 19619 | last = s->row->glyphs[s->area] + end; | ||
| 19620 | s->cmp_id = glyph->u.cmp.id; | ||
| 19621 | s->cmp_from = glyph->u.cmp.from; | ||
| 19622 | s->cmp_to = glyph->u.cmp.to; | ||
| 19623 | s->face = FACE_FROM_ID (s->f, face_id); | ||
| 19624 | lgstring = composition_gstring_from_id (s->cmp_id); | ||
| 19625 | s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring)); | ||
| 19626 | glyph++; | ||
| 19627 | while (glyph < last | ||
| 19628 | && glyph->u.cmp.automatic | ||
| 19629 | && glyph->u.cmp.id == s->cmp_id) | ||
| 19630 | s->cmp_to = (glyph++)->u.cmp.to; | ||
| 19631 | |||
| 19632 | for (i = s->cmp_from; i < s->cmp_to; i++) | ||
| 19633 | { | ||
| 19634 | Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i); | ||
| 19635 | unsigned code = LGLYPH_CODE (lglyph); | ||
| 19636 | |||
| 19637 | STORE_XCHAR2B ((s->char2b + i), code >> 8, code & 0xFF); | ||
| 19638 | } | ||
| 19639 | s->width = composition_gstring_width (lgstring, s->cmp_from, s->cmp_to, NULL); | ||
| 19640 | return glyph - s->row->glyphs[s->area]; | ||
| 19694 | } | 19641 | } |
| 19695 | 19642 | ||
| 19696 | 19643 | ||
| @@ -19837,7 +19784,6 @@ get_per_char_metric (f, font, char2b) | |||
| 19837 | { | 19784 | { |
| 19838 | static struct font_metrics metrics; | 19785 | static struct font_metrics metrics; |
| 19839 | unsigned code = (XCHAR2B_BYTE1 (char2b) << 8) | XCHAR2B_BYTE2 (char2b); | 19786 | unsigned code = (XCHAR2B_BYTE1 (char2b) << 8) | XCHAR2B_BYTE2 (char2b); |
| 19840 | struct font *fontp; | ||
| 19841 | 19787 | ||
| 19842 | if (! font || code == FONT_INVALID_CODE) | 19788 | if (! font || code == FONT_INVALID_CODE) |
| 19843 | return NULL; | 19789 | return NULL; |
| @@ -19875,10 +19821,27 @@ x_get_glyph_overhangs (glyph, f, left, right) | |||
| 19875 | } | 19821 | } |
| 19876 | else if (glyph->type == COMPOSITE_GLYPH) | 19822 | else if (glyph->type == COMPOSITE_GLYPH) |
| 19877 | { | 19823 | { |
| 19878 | struct composition *cmp = composition_table[glyph->u.cmp_id]; | 19824 | if (! glyph->u.cmp.automatic) |
| 19825 | { | ||
| 19826 | struct composition *cmp = composition_table[glyph->u.cmp.id]; | ||
| 19827 | |||
| 19828 | if (cmp->rbearing - cmp->pixel_width) | ||
| 19829 | *right = cmp->rbearing - cmp->pixel_width; | ||
| 19830 | if (cmp->lbearing < 0); | ||
| 19831 | *left = - cmp->lbearing; | ||
| 19832 | } | ||
| 19833 | else | ||
| 19834 | { | ||
| 19835 | Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id); | ||
| 19836 | struct font_metrics metrics; | ||
| 19879 | 19837 | ||
| 19880 | *right = cmp->rbearing - cmp->pixel_width; | 19838 | composition_gstring_width (gstring, glyph->u.cmp.from, |
| 19881 | *left = - cmp->lbearing; | 19839 | glyph->u.cmp.to, &metrics); |
| 19840 | if (metrics.rbearing > metrics.width) | ||
| 19841 | *right = metrics.rbearing; | ||
| 19842 | if (metrics.lbearing < 0) | ||
| 19843 | *left = - metrics.lbearing; | ||
| 19844 | } | ||
| 19882 | } | 19845 | } |
| 19883 | } | 19846 | } |
| 19884 | 19847 | ||
| @@ -20142,7 +20105,7 @@ compute_overhangs_and_x (s, x, backward_p) | |||
| 20142 | INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ | 20105 | INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ |
| 20143 | append_glyph_string (&HEAD, &TAIL, s); \ | 20106 | append_glyph_string (&HEAD, &TAIL, s); \ |
| 20144 | s->x = (X); \ | 20107 | s->x = (X); \ |
| 20145 | START = fill_glyph_string (s, face_id, START, END, overlaps); \ | 20108 | START = fill_glyph_string (s, face_id, START, END, overlaps); \ |
| 20146 | } \ | 20109 | } \ |
| 20147 | while (0) | 20110 | while (0) |
| 20148 | 20111 | ||
| @@ -20160,7 +20123,7 @@ compute_overhangs_and_x (s, x, backward_p) | |||
| 20160 | do { \ | 20123 | do { \ |
| 20161 | int face_id = (row)->glyphs[area][START].face_id; \ | 20124 | int face_id = (row)->glyphs[area][START].face_id; \ |
| 20162 | struct face *base_face = FACE_FROM_ID (f, face_id); \ | 20125 | struct face *base_face = FACE_FROM_ID (f, face_id); \ |
| 20163 | int cmp_id = (row)->glyphs[area][START].u.cmp_id; \ | 20126 | int cmp_id = (row)->glyphs[area][START].u.cmp.id; \ |
| 20164 | struct composition *cmp = composition_table[cmp_id]; \ | 20127 | struct composition *cmp = composition_table[cmp_id]; \ |
| 20165 | XChar2b *char2b; \ | 20128 | XChar2b *char2b; \ |
| 20166 | struct glyph_string *first_s; \ | 20129 | struct glyph_string *first_s; \ |
| @@ -20176,7 +20139,7 @@ compute_overhangs_and_x (s, x, backward_p) | |||
| 20176 | INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ | 20139 | INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ |
| 20177 | append_glyph_string (&(HEAD), &(TAIL), s); \ | 20140 | append_glyph_string (&(HEAD), &(TAIL), s); \ |
| 20178 | s->cmp = cmp; \ | 20141 | s->cmp = cmp; \ |
| 20179 | s->gidx = n; \ | 20142 | s->cmp_from = n; \ |
| 20180 | s->x = (X); \ | 20143 | s->x = (X); \ |
| 20181 | if (n == 0) \ | 20144 | if (n == 0) \ |
| 20182 | first_s = s; \ | 20145 | first_s = s; \ |
| @@ -20188,6 +20151,28 @@ compute_overhangs_and_x (s, x, backward_p) | |||
| 20188 | } while (0) | 20151 | } while (0) |
| 20189 | 20152 | ||
| 20190 | 20153 | ||
| 20154 | /* Add a glyph string for a glyph-string sequence to the list of strings | ||
| 20155 | between HEAD and TAIL. */ | ||
| 20156 | |||
| 20157 | #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ | ||
| 20158 | do { \ | ||
| 20159 | int face_id; \ | ||
| 20160 | XChar2b *char2b; \ | ||
| 20161 | Lisp_Object gstring; \ | ||
| 20162 | \ | ||
| 20163 | face_id = (row)->glyphs[area][START].face_id; \ | ||
| 20164 | gstring = (composition_gstring_from_id \ | ||
| 20165 | ((row)->glyphs[area][START].u.cmp.id)); \ | ||
| 20166 | s = (struct glyph_string *) alloca (sizeof *s); \ | ||
| 20167 | char2b = (XChar2b *) alloca ((sizeof *char2b) \ | ||
| 20168 | * LGSTRING_GLYPH_LEN (gstring)); \ | ||
| 20169 | INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ | ||
| 20170 | append_glyph_string (&(HEAD), &(TAIL), s); \ | ||
| 20171 | s->x = (X); \ | ||
| 20172 | START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \ | ||
| 20173 | } while (0) | ||
| 20174 | |||
| 20175 | |||
| 20191 | /* Build a list of glyph strings between HEAD and TAIL for the glyphs | 20176 | /* Build a list of glyph strings between HEAD and TAIL for the glyphs |
| 20192 | of AREA of glyph row ROW on window W between indices START and END. | 20177 | of AREA of glyph row ROW on window W between indices START and END. |
| 20193 | HL overrides the face for drawing glyph strings, e.g. it is | 20178 | HL overrides the face for drawing glyph strings, e.g. it is |
| @@ -20198,47 +20183,50 @@ compute_overhangs_and_x (s, x, backward_p) | |||
| 20198 | to allocate glyph strings (because draw_glyphs can be called | 20183 | to allocate glyph strings (because draw_glyphs can be called |
| 20199 | asynchronously). */ | 20184 | asynchronously). */ |
| 20200 | 20185 | ||
| 20201 | #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ | 20186 | #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ |
| 20202 | do \ | 20187 | do \ |
| 20203 | { \ | 20188 | { \ |
| 20204 | HEAD = TAIL = NULL; \ | 20189 | HEAD = TAIL = NULL; \ |
| 20205 | while (START < END) \ | 20190 | while (START < END) \ |
| 20206 | { \ | 20191 | { \ |
| 20207 | struct glyph *first_glyph = (row)->glyphs[area] + START; \ | 20192 | struct glyph *first_glyph = (row)->glyphs[area] + START; \ |
| 20208 | switch (first_glyph->type) \ | 20193 | switch (first_glyph->type) \ |
| 20209 | { \ | 20194 | { \ |
| 20210 | case CHAR_GLYPH: \ | 20195 | case CHAR_GLYPH: \ |
| 20211 | BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ | 20196 | BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ |
| 20212 | HL, X, LAST_X); \ | 20197 | HL, X, LAST_X); \ |
| 20213 | break; \ | 20198 | break; \ |
| 20214 | \ | 20199 | \ |
| 20215 | case COMPOSITE_GLYPH: \ | 20200 | case COMPOSITE_GLYPH: \ |
| 20216 | BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ | 20201 | if (first_glyph->u.cmp.automatic) \ |
| 20217 | HL, X, LAST_X); \ | 20202 | BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \ |
| 20218 | break; \ | 20203 | HL, X, LAST_X); \ |
| 20219 | \ | 20204 | else \ |
| 20220 | case STRETCH_GLYPH: \ | 20205 | BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ |
| 20221 | BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ | 20206 | HL, X, LAST_X); \ |
| 20222 | HL, X, LAST_X); \ | 20207 | break; \ |
| 20223 | break; \ | 20208 | \ |
| 20224 | \ | 20209 | case STRETCH_GLYPH: \ |
| 20225 | case IMAGE_GLYPH: \ | 20210 | BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ |
| 20226 | BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ | 20211 | HL, X, LAST_X); \ |
| 20227 | HL, X, LAST_X); \ | 20212 | break; \ |
| 20228 | break; \ | 20213 | \ |
| 20229 | \ | 20214 | case IMAGE_GLYPH: \ |
| 20230 | default: \ | 20215 | BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ |
| 20231 | abort (); \ | 20216 | HL, X, LAST_X); \ |
| 20232 | } \ | 20217 | break; \ |
| 20233 | \ | 20218 | \ |
| 20234 | if (s) \ | 20219 | default: \ |
| 20235 | { \ | 20220 | abort (); \ |
| 20236 | set_glyph_string_background_width (s, START, LAST_X); \ | 20221 | } \ |
| 20237 | (X) += s->width; \ | 20222 | \ |
| 20238 | } \ | 20223 | if (s) \ |
| 20239 | } \ | 20224 | { \ |
| 20240 | } \ | 20225 | set_glyph_string_background_width (s, START, LAST_X); \ |
| 20241 | while (0) | 20226 | (X) += s->width; \ |
| 20227 | } \ | ||
| 20228 | } \ | ||
| 20229 | } while (0) | ||
| 20242 | 20230 | ||
| 20243 | 20231 | ||
| 20244 | /* Draw glyphs between START and END in AREA of ROW on window W, | 20232 | /* Draw glyphs between START and END in AREA of ROW on window W, |
| @@ -20559,8 +20547,9 @@ append_glyph (it) | |||
| 20559 | IT_EXPAND_MATRIX_WIDTH (it, area); | 20547 | IT_EXPAND_MATRIX_WIDTH (it, area); |
| 20560 | } | 20548 | } |
| 20561 | 20549 | ||
| 20562 | /* Store one glyph for the composition IT->cmp_id in IT->glyph_row. | 20550 | /* Store one glyph for the composition IT->cmp_it.id in |
| 20563 | Called from x_produce_glyphs when IT->glyph_row is non-null. */ | 20551 | IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is |
| 20552 | non-null. */ | ||
| 20564 | 20553 | ||
| 20565 | static INLINE void | 20554 | static INLINE void |
| 20566 | append_composite_glyph (it) | 20555 | append_composite_glyph (it) |
| @@ -20581,6 +20570,18 @@ append_composite_glyph (it) | |||
| 20581 | glyph->descent = it->descent; | 20570 | glyph->descent = it->descent; |
| 20582 | glyph->voffset = it->voffset; | 20571 | glyph->voffset = it->voffset; |
| 20583 | glyph->type = COMPOSITE_GLYPH; | 20572 | glyph->type = COMPOSITE_GLYPH; |
| 20573 | if (it->cmp_it.ch < 0) | ||
| 20574 | { | ||
| 20575 | glyph->u.cmp.automatic = 0; | ||
| 20576 | glyph->u.cmp.id = it->cmp_it.id; | ||
| 20577 | } | ||
| 20578 | else | ||
| 20579 | { | ||
| 20580 | glyph->u.cmp.automatic = 1; | ||
| 20581 | glyph->u.cmp.id = it->cmp_it.id; | ||
| 20582 | glyph->u.cmp.from = it->cmp_it.from; | ||
| 20583 | glyph->u.cmp.to = it->cmp_it.to; | ||
| 20584 | } | ||
| 20584 | glyph->avoid_cursor_p = it->avoid_cursor_p; | 20585 | glyph->avoid_cursor_p = it->avoid_cursor_p; |
| 20585 | glyph->multibyte_p = it->multibyte_p; | 20586 | glyph->multibyte_p = it->multibyte_p; |
| 20586 | glyph->left_box_line_p = it->start_of_box_run_p; | 20587 | glyph->left_box_line_p = it->start_of_box_run_p; |
| @@ -20590,7 +20591,6 @@ append_composite_glyph (it) | |||
| 20590 | glyph->padding_p = 0; | 20591 | glyph->padding_p = 0; |
| 20591 | glyph->glyph_not_available_p = 0; | 20592 | glyph->glyph_not_available_p = 0; |
| 20592 | glyph->face_id = it->face_id; | 20593 | glyph->face_id = it->face_id; |
| 20593 | glyph->u.cmp_id = it->cmp_id; | ||
| 20594 | glyph->slice = null_glyph_slice; | 20594 | glyph->slice = null_glyph_slice; |
| 20595 | glyph->font_type = FONT_TYPE_UNKNOWN; | 20595 | glyph->font_type = FONT_TYPE_UNKNOWN; |
| 20596 | ++it->glyph_row->used[area]; | 20596 | ++it->glyph_row->used[area]; |
| @@ -21447,9 +21447,11 @@ x_produce_glyphs (it) | |||
| 21447 | } | 21447 | } |
| 21448 | it->multibyte_p = saved_multibyte_p; | 21448 | it->multibyte_p = saved_multibyte_p; |
| 21449 | } | 21449 | } |
| 21450 | else if (it->what == IT_COMPOSITION) | 21450 | else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0) |
| 21451 | { | 21451 | { |
| 21452 | /* Note: A composition is represented as one glyph in the | 21452 | /* A static compositoin. |
| 21453 | |||
| 21454 | Note: A composition is represented as one glyph in the | ||
| 21453 | glyph matrix. There are no padding glyphs. | 21455 | glyph matrix. There are no padding glyphs. |
| 21454 | 21456 | ||
| 21455 | Important is that pixel_width, ascent, and descent are the | 21457 | Important is that pixel_width, ascent, and descent are the |
| @@ -21457,18 +21459,12 @@ x_produce_glyphs (it) | |||
| 21457 | the overall glyphs composed). */ | 21459 | the overall glyphs composed). */ |
| 21458 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | 21460 | struct face *face = FACE_FROM_ID (it->f, it->face_id); |
| 21459 | int boff; /* baseline offset */ | 21461 | int boff; /* baseline offset */ |
| 21460 | struct composition *cmp = composition_table[it->cmp_id]; | 21462 | struct composition *cmp = composition_table[it->cmp_it.id]; |
| 21461 | int glyph_len = cmp->glyph_len; | 21463 | int glyph_len = cmp->glyph_len; |
| 21462 | struct font *font = face->font; | 21464 | struct font *font = face->font; |
| 21463 | 21465 | ||
| 21464 | it->nglyphs = 1; | 21466 | it->nglyphs = 1; |
| 21465 | 21467 | ||
| 21466 | if (cmp->method == COMPOSITION_WITH_GLYPH_STRING) | ||
| 21467 | { | ||
| 21468 | PREPARE_FACE_FOR_DISPLAY (it->f, face); | ||
| 21469 | font_prepare_composition (cmp, it->f); | ||
| 21470 | } | ||
| 21471 | else | ||
| 21472 | /* If we have not yet calculated pixel size data of glyphs of | 21468 | /* If we have not yet calculated pixel size data of glyphs of |
| 21473 | the composition for the current face font, calculate them | 21469 | the composition for the current face font, calculate them |
| 21474 | now. Theoretically, we have to check all fonts for the | 21470 | now. Theoretically, we have to check all fonts for the |
| @@ -21488,7 +21484,6 @@ x_produce_glyphs (it) | |||
| 21488 | int lbearing, rbearing; | 21484 | int lbearing, rbearing; |
| 21489 | int i, width, ascent, descent; | 21485 | int i, width, ascent, descent; |
| 21490 | int left_padded = 0, right_padded = 0; | 21486 | int left_padded = 0, right_padded = 0; |
| 21491 | int face_id; | ||
| 21492 | int c; | 21487 | int c; |
| 21493 | XChar2b char2b; | 21488 | XChar2b char2b; |
| 21494 | struct font_metrics *pcm; | 21489 | struct font_metrics *pcm; |
| @@ -21771,6 +21766,52 @@ x_produce_glyphs (it) | |||
| 21771 | if (it->glyph_row) | 21766 | if (it->glyph_row) |
| 21772 | append_composite_glyph (it); | 21767 | append_composite_glyph (it); |
| 21773 | } | 21768 | } |
| 21769 | else if (it->what == IT_COMPOSITION) | ||
| 21770 | { | ||
| 21771 | /* A dynamic (automatic) composition. */ | ||
| 21772 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | ||
| 21773 | Lisp_Object gstring; | ||
| 21774 | struct font_metrics metrics; | ||
| 21775 | |||
| 21776 | gstring = composition_gstring_from_id (it->cmp_it.id); | ||
| 21777 | it->pixel_width | ||
| 21778 | = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to, | ||
| 21779 | &metrics); | ||
| 21780 | if (it->glyph_row | ||
| 21781 | && (metrics.lbearing < 0 || metrics.rbearing > metrics.width)) | ||
| 21782 | it->glyph_row->contains_overlapping_glyphs_p = 1; | ||
| 21783 | it->ascent = it->phys_ascent = metrics.ascent; | ||
| 21784 | it->descent = it->phys_descent = metrics.descent; | ||
| 21785 | if (face->box != FACE_NO_BOX) | ||
| 21786 | { | ||
| 21787 | int thick = face->box_line_width; | ||
| 21788 | |||
| 21789 | if (thick > 0) | ||
| 21790 | { | ||
| 21791 | it->ascent += thick; | ||
| 21792 | it->descent += thick; | ||
| 21793 | } | ||
| 21794 | else | ||
| 21795 | thick = - thick; | ||
| 21796 | |||
| 21797 | if (it->start_of_box_run_p) | ||
| 21798 | it->pixel_width += thick; | ||
| 21799 | if (it->end_of_box_run_p) | ||
| 21800 | it->pixel_width += thick; | ||
| 21801 | } | ||
| 21802 | /* If face has an overline, add the height of the overline | ||
| 21803 | (1 pixel) and a 1 pixel margin to the character height. */ | ||
| 21804 | if (face->overline_p) | ||
| 21805 | it->ascent += overline_margin; | ||
| 21806 | take_vertical_position_into_account (it); | ||
| 21807 | if (it->ascent < 0) | ||
| 21808 | it->ascent = 0; | ||
| 21809 | if (it->descent < 0) | ||
| 21810 | it->descent = 0; | ||
| 21811 | |||
| 21812 | if (it->glyph_row) | ||
| 21813 | append_composite_glyph (it); | ||
| 21814 | } | ||
| 21774 | else if (it->what == IT_IMAGE) | 21815 | else if (it->what == IT_IMAGE) |
| 21775 | produce_image_glyph (it); | 21816 | produce_image_glyph (it); |
| 21776 | else if (it->what == IT_STRETCH) | 21817 | else if (it->what == IT_STRETCH) |