diff options
| author | Kim F. Storm | 2003-03-16 20:45:46 +0000 |
|---|---|---|
| committer | Kim F. Storm | 2003-03-16 20:45:46 +0000 |
| commit | 133c764e3110b91ed475e6e8313aed57d4020595 (patch) | |
| tree | 36f2c39cc33f5516a5b85f6f84b8289eacb51c09 /src | |
| parent | d5cc60b8f99957c6569cf7471f1fe3ec1570da85 (diff) | |
| download | emacs-133c764e3110b91ed475e6e8313aed57d4020595.tar.gz emacs-133c764e3110b91ed475e6e8313aed57d4020595.zip | |
Consolidate gui-independent "glyph string" code here.
(dump_glyph_string): Moved here.
(init_glyph_string, append_glyph_string_lists, append_glyph_string)
(prepend_glyph_string_lists, get_glyph_face_and_encoding)
(fill_composite_glyph_string, fill_glyph_string)
(fill_image_glyph_string, fill_stretch_glyph_string)
(left_overwritten, left_overwriting, right_overwritten)
(right_overwriting, get_char_face_and_encoding)
(set_glyph_string_background_width, compute_overhangs_and_x)
(append_glyph, append_composite_glyph, produce_image_glyph)
(take_vertical_position_into_account, append_stretch_glyph)
(produce_stretch_glyph): New generic functions (based on X version).
Call platform specific functions through rif.
(INIT_GLYPH_STRING): New macro, hides W32 details.
(BUILD_STRETCH_GLYPH_STRING, BUILD_IMAGE_GLYPH_STRING)
(BUILD_CHAR_GLYPH_STRINGS, BUILD_COMPOSITE_GLYPH_STRING)
(BUILD_GLYPH_STRINGS): Generic macros (based on X version).
(x_draw_glyphs, x_get_glyph_overhangs, x_produce_glyphs)
(notice_overwritten_cursor):
Generic functions exported to platform modules. Users changed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 2048 |
1 files changed, 2048 insertions, 0 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 592c205ad72..56657202c01 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -280,6 +280,7 @@ Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height; | |||
| 280 | Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; | 280 | Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; |
| 281 | Lisp_Object Qmargin; | 281 | Lisp_Object Qmargin; |
| 282 | extern Lisp_Object Qheight; | 282 | extern Lisp_Object Qheight; |
| 283 | extern Lisp_Object QCwidth, QCheight, QCascent; | ||
| 283 | 284 | ||
| 284 | /* Non-nil means highlight trailing whitespace. */ | 285 | /* Non-nil means highlight trailing whitespace. */ |
| 285 | 286 | ||
| @@ -15660,6 +15661,1996 @@ invisible_p (propval, list) | |||
| 15660 | 15661 | ||
| 15661 | 15662 | ||
| 15662 | /*********************************************************************** | 15663 | /*********************************************************************** |
| 15664 | Glyph Display | ||
| 15665 | ***********************************************************************/ | ||
| 15666 | |||
| 15667 | #if GLYPH_DEBUG | ||
| 15668 | |||
| 15669 | void | ||
| 15670 | dump_glyph_string (s) | ||
| 15671 | struct glyph_string *s; | ||
| 15672 | { | ||
| 15673 | fprintf (stderr, "glyph string\n"); | ||
| 15674 | fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n", | ||
| 15675 | s->x, s->y, s->width, s->height); | ||
| 15676 | fprintf (stderr, " ybase = %d\n", s->ybase); | ||
| 15677 | fprintf (stderr, " hl = %d\n", s->hl); | ||
| 15678 | fprintf (stderr, " left overhang = %d, right = %d\n", | ||
| 15679 | s->left_overhang, s->right_overhang); | ||
| 15680 | fprintf (stderr, " nchars = %d\n", s->nchars); | ||
| 15681 | fprintf (stderr, " extends to end of line = %d\n", | ||
| 15682 | s->extends_to_end_of_line_p); | ||
| 15683 | fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font)); | ||
| 15684 | fprintf (stderr, " bg width = %d\n", s->background_width); | ||
| 15685 | } | ||
| 15686 | |||
| 15687 | #endif /* GLYPH_DEBUG */ | ||
| 15688 | |||
| 15689 | /* Initialize glyph string S. CHAR2B is a suitably allocated vector | ||
| 15690 | of XChar2b structures for S; it can't be allocated in | ||
| 15691 | init_glyph_string because it must be allocated via `alloca'. W | ||
| 15692 | is the window on which S is drawn. ROW and AREA are the glyph row | ||
| 15693 | and area within the row from which S is constructed. START is the | ||
| 15694 | index of the first glyph structure covered by S. HL is a | ||
| 15695 | face-override for drawing S. */ | ||
| 15696 | |||
| 15697 | #ifdef HAVE_NTGUI | ||
| 15698 | #define OPTIONAL_HDC(hdc) hdc, | ||
| 15699 | #define DECLARE_HDC(hdc) HDC hdc; | ||
| 15700 | #define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f)) | ||
| 15701 | #define RELEASE_HDC(hdc, f) release_frame_dc ((f), (hdc)) | ||
| 15702 | #endif | ||
| 15703 | |||
| 15704 | #ifndef OPTIONAL_HDC | ||
| 15705 | #define OPTIONAL_HDC(hdc) | ||
| 15706 | #define DECLARE_HDC(hdc) | ||
| 15707 | #define ALLOCATE_HDC(hdc, f) | ||
| 15708 | #define RELEASE_HDC(hdc, f) | ||
| 15709 | #endif | ||
| 15710 | |||
| 15711 | static void | ||
| 15712 | init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl) | ||
| 15713 | struct glyph_string *s; | ||
| 15714 | DECLARE_HDC (hdc) | ||
| 15715 | XChar2b *char2b; | ||
| 15716 | struct window *w; | ||
| 15717 | struct glyph_row *row; | ||
| 15718 | enum glyph_row_area area; | ||
| 15719 | int start; | ||
| 15720 | enum draw_glyphs_face hl; | ||
| 15721 | { | ||
| 15722 | bzero (s, sizeof *s); | ||
| 15723 | s->w = w; | ||
| 15724 | s->f = XFRAME (w->frame); | ||
| 15725 | #ifdef HAVE_NTGUI | ||
| 15726 | s->hdc = hdc; | ||
| 15727 | #endif | ||
| 15728 | s->display = FRAME_X_DISPLAY (s->f); | ||
| 15729 | s->window = FRAME_X_WINDOW (s->f); | ||
| 15730 | s->char2b = char2b; | ||
| 15731 | s->hl = hl; | ||
| 15732 | s->row = row; | ||
| 15733 | s->area = area; | ||
| 15734 | s->first_glyph = row->glyphs[area] + start; | ||
| 15735 | s->height = row->height; | ||
| 15736 | s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); | ||
| 15737 | |||
| 15738 | /* Display the internal border below the tool-bar window. */ | ||
| 15739 | if (s->w == XWINDOW (s->f->tool_bar_window)) | ||
| 15740 | s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f); | ||
| 15741 | |||
| 15742 | s->ybase = s->y + row->ascent; | ||
| 15743 | } | ||
| 15744 | |||
| 15745 | |||
| 15746 | /* Append the list of glyph strings with head H and tail T to the list | ||
| 15747 | with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */ | ||
| 15748 | |||
| 15749 | static INLINE void | ||
| 15750 | append_glyph_string_lists (head, tail, h, t) | ||
| 15751 | struct glyph_string **head, **tail; | ||
| 15752 | struct glyph_string *h, *t; | ||
| 15753 | { | ||
| 15754 | if (h) | ||
| 15755 | { | ||
| 15756 | if (*head) | ||
| 15757 | (*tail)->next = h; | ||
| 15758 | else | ||
| 15759 | *head = h; | ||
| 15760 | h->prev = *tail; | ||
| 15761 | *tail = t; | ||
| 15762 | } | ||
| 15763 | } | ||
| 15764 | |||
| 15765 | |||
| 15766 | /* Prepend the list of glyph strings with head H and tail T to the | ||
| 15767 | list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the | ||
| 15768 | result. */ | ||
| 15769 | |||
| 15770 | static INLINE void | ||
| 15771 | prepend_glyph_string_lists (head, tail, h, t) | ||
| 15772 | struct glyph_string **head, **tail; | ||
| 15773 | struct glyph_string *h, *t; | ||
| 15774 | { | ||
| 15775 | if (h) | ||
| 15776 | { | ||
| 15777 | if (*head) | ||
| 15778 | (*head)->prev = t; | ||
| 15779 | else | ||
| 15780 | *tail = t; | ||
| 15781 | t->next = *head; | ||
| 15782 | *head = h; | ||
| 15783 | } | ||
| 15784 | } | ||
| 15785 | |||
| 15786 | |||
| 15787 | /* Append glyph string S to the list with head *HEAD and tail *TAIL. | ||
| 15788 | Set *HEAD and *TAIL to the resulting list. */ | ||
| 15789 | |||
| 15790 | static INLINE void | ||
| 15791 | append_glyph_string (head, tail, s) | ||
| 15792 | struct glyph_string **head, **tail; | ||
| 15793 | struct glyph_string *s; | ||
| 15794 | { | ||
| 15795 | s->next = s->prev = NULL; | ||
| 15796 | append_glyph_string_lists (head, tail, s, s); | ||
| 15797 | } | ||
| 15798 | |||
| 15799 | |||
| 15800 | /* Get face and two-byte form of character glyph GLYPH on frame F. | ||
| 15801 | The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is | ||
| 15802 | a pointer to a realized face that is ready for display. */ | ||
| 15803 | |||
| 15804 | static INLINE struct face * | ||
| 15805 | get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p) | ||
| 15806 | struct frame *f; | ||
| 15807 | struct glyph *glyph; | ||
| 15808 | XChar2b *char2b; | ||
| 15809 | int *two_byte_p; | ||
| 15810 | { | ||
| 15811 | struct face *face; | ||
| 15812 | |||
| 15813 | xassert (glyph->type == CHAR_GLYPH); | ||
| 15814 | face = FACE_FROM_ID (f, glyph->face_id); | ||
| 15815 | |||
| 15816 | if (two_byte_p) | ||
| 15817 | *two_byte_p = 0; | ||
| 15818 | |||
| 15819 | if (!glyph->multibyte_p) | ||
| 15820 | { | ||
| 15821 | /* Unibyte case. We don't have to encode, but we have to make | ||
| 15822 | sure to use a face suitable for unibyte. */ | ||
| 15823 | STORE_XCHAR2B (char2b, 0, glyph->u.ch); | ||
| 15824 | } | ||
| 15825 | else if (glyph->u.ch < 128 | ||
| 15826 | && glyph->face_id < BASIC_FACE_ID_SENTINEL) | ||
| 15827 | { | ||
| 15828 | /* Case of ASCII in a face known to fit ASCII. */ | ||
| 15829 | STORE_XCHAR2B (char2b, 0, glyph->u.ch); | ||
| 15830 | } | ||
| 15831 | else | ||
| 15832 | { | ||
| 15833 | int c1, c2, charset; | ||
| 15834 | |||
| 15835 | /* Split characters into bytes. If c2 is -1 afterwards, C is | ||
| 15836 | really a one-byte character so that byte1 is zero. */ | ||
| 15837 | SPLIT_CHAR (glyph->u.ch, charset, c1, c2); | ||
| 15838 | if (c2 > 0) | ||
| 15839 | STORE_XCHAR2B (char2b, c1, c2); | ||
| 15840 | else | ||
| 15841 | STORE_XCHAR2B (char2b, 0, c1); | ||
| 15842 | |||
| 15843 | /* Maybe encode the character in *CHAR2B. */ | ||
| 15844 | if (charset != CHARSET_ASCII) | ||
| 15845 | { | ||
| 15846 | struct font_info *font_info | ||
| 15847 | = FONT_INFO_FROM_ID (f, face->font_info_id); | ||
| 15848 | if (font_info) | ||
| 15849 | glyph->font_type | ||
| 15850 | = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p); | ||
| 15851 | } | ||
| 15852 | } | ||
| 15853 | |||
| 15854 | /* Make sure X resources of the face are allocated. */ | ||
| 15855 | xassert (face != NULL); | ||
| 15856 | PREPARE_FACE_FOR_DISPLAY (f, face); | ||
| 15857 | return face; | ||
| 15858 | } | ||
| 15859 | |||
| 15860 | |||
| 15861 | /* Fill glyph string S with composition components specified by S->cmp. | ||
| 15862 | |||
| 15863 | FACES is an array of faces for all components of this composition. | ||
| 15864 | S->gidx is the index of the first component for S. | ||
| 15865 | OVERLAPS_P non-zero means S should draw the foreground only, and | ||
| 15866 | use its physical height for clipping. | ||
| 15867 | |||
| 15868 | Value is the index of a component not in S. */ | ||
| 15869 | |||
| 15870 | static int | ||
| 15871 | fill_composite_glyph_string (s, faces, overlaps_p) | ||
| 15872 | struct glyph_string *s; | ||
| 15873 | struct face **faces; | ||
| 15874 | int overlaps_p; | ||
| 15875 | { | ||
| 15876 | int i; | ||
| 15877 | |||
| 15878 | xassert (s); | ||
| 15879 | |||
| 15880 | s->for_overlaps_p = overlaps_p; | ||
| 15881 | |||
| 15882 | s->face = faces[s->gidx]; | ||
| 15883 | s->font = s->face->font; | ||
| 15884 | s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id); | ||
| 15885 | |||
| 15886 | /* For all glyphs of this composition, starting at the offset | ||
| 15887 | S->gidx, until we reach the end of the definition or encounter a | ||
| 15888 | glyph that requires the different face, add it to S. */ | ||
| 15889 | ++s->nchars; | ||
| 15890 | for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i) | ||
| 15891 | ++s->nchars; | ||
| 15892 | |||
| 15893 | /* All glyph strings for the same composition has the same width, | ||
| 15894 | i.e. the width set for the first component of the composition. */ | ||
| 15895 | |||
| 15896 | s->width = s->first_glyph->pixel_width; | ||
| 15897 | |||
| 15898 | /* If the specified font could not be loaded, use the frame's | ||
| 15899 | default font, but record the fact that we couldn't load it in | ||
| 15900 | the glyph string so that we can draw rectangles for the | ||
| 15901 | characters of the glyph string. */ | ||
| 15902 | if (s->font == NULL) | ||
| 15903 | { | ||
| 15904 | s->font_not_found_p = 1; | ||
| 15905 | s->font = FRAME_FONT (s->f); | ||
| 15906 | } | ||
| 15907 | |||
| 15908 | /* Adjust base line for subscript/superscript text. */ | ||
| 15909 | s->ybase += s->first_glyph->voffset; | ||
| 15910 | |||
| 15911 | xassert (s->face && s->face->gc); | ||
| 15912 | |||
| 15913 | /* This glyph string must always be drawn with 16-bit functions. */ | ||
| 15914 | s->two_byte_p = 1; | ||
| 15915 | |||
| 15916 | return s->gidx + s->nchars; | ||
| 15917 | } | ||
| 15918 | |||
| 15919 | |||
| 15920 | /* Fill glyph string S from a sequence of character glyphs. | ||
| 15921 | |||
| 15922 | FACE_ID is the face id of the string. START is the index of the | ||
| 15923 | first glyph to consider, END is the index of the last + 1. | ||
| 15924 | OVERLAPS_P non-zero means S should draw the foreground only, and | ||
| 15925 | use its physical height for clipping. | ||
| 15926 | |||
| 15927 | Value is the index of the first glyph not in S. */ | ||
| 15928 | |||
| 15929 | static int | ||
| 15930 | fill_glyph_string (s, face_id, start, end, overlaps_p) | ||
| 15931 | struct glyph_string *s; | ||
| 15932 | int face_id; | ||
| 15933 | int start, end, overlaps_p; | ||
| 15934 | { | ||
| 15935 | struct glyph *glyph, *last; | ||
| 15936 | int voffset; | ||
| 15937 | int glyph_not_available_p; | ||
| 15938 | |||
| 15939 | xassert (s->f == XFRAME (s->w->frame)); | ||
| 15940 | xassert (s->nchars == 0); | ||
| 15941 | xassert (start >= 0 && end > start); | ||
| 15942 | |||
| 15943 | s->for_overlaps_p = overlaps_p, | ||
| 15944 | glyph = s->row->glyphs[s->area] + start; | ||
| 15945 | last = s->row->glyphs[s->area] + end; | ||
| 15946 | voffset = glyph->voffset; | ||
| 15947 | |||
| 15948 | glyph_not_available_p = glyph->glyph_not_available_p; | ||
| 15949 | |||
| 15950 | while (glyph < last | ||
| 15951 | && glyph->type == CHAR_GLYPH | ||
| 15952 | && glyph->voffset == voffset | ||
| 15953 | /* Same face id implies same font, nowadays. */ | ||
| 15954 | && glyph->face_id == face_id | ||
| 15955 | && glyph->glyph_not_available_p == glyph_not_available_p) | ||
| 15956 | { | ||
| 15957 | int two_byte_p; | ||
| 15958 | |||
| 15959 | s->face = get_glyph_face_and_encoding (s->f, glyph, | ||
| 15960 | s->char2b + s->nchars, | ||
| 15961 | &two_byte_p); | ||
| 15962 | s->two_byte_p = two_byte_p; | ||
| 15963 | ++s->nchars; | ||
| 15964 | xassert (s->nchars <= end - start); | ||
| 15965 | s->width += glyph->pixel_width; | ||
| 15966 | ++glyph; | ||
| 15967 | } | ||
| 15968 | |||
| 15969 | s->font = s->face->font; | ||
| 15970 | s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id); | ||
| 15971 | |||
| 15972 | /* If the specified font could not be loaded, use the frame's font, | ||
| 15973 | but record the fact that we couldn't load it in | ||
| 15974 | S->font_not_found_p so that we can draw rectangles for the | ||
| 15975 | characters of the glyph string. */ | ||
| 15976 | if (s->font == NULL || glyph_not_available_p) | ||
| 15977 | { | ||
| 15978 | s->font_not_found_p = 1; | ||
| 15979 | s->font = FRAME_FONT (s->f); | ||
| 15980 | } | ||
| 15981 | |||
| 15982 | /* Adjust base line for subscript/superscript text. */ | ||
| 15983 | s->ybase += voffset; | ||
| 15984 | |||
| 15985 | xassert (s->face && s->face->gc); | ||
| 15986 | return glyph - s->row->glyphs[s->area]; | ||
| 15987 | } | ||
| 15988 | |||
| 15989 | |||
| 15990 | /* Fill glyph string S from image glyph S->first_glyph. */ | ||
| 15991 | |||
| 15992 | static void | ||
| 15993 | fill_image_glyph_string (s) | ||
| 15994 | struct glyph_string *s; | ||
| 15995 | { | ||
| 15996 | xassert (s->first_glyph->type == IMAGE_GLYPH); | ||
| 15997 | s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id); | ||
| 15998 | xassert (s->img); | ||
| 15999 | s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id); | ||
| 16000 | s->font = s->face->font; | ||
| 16001 | s->width = s->first_glyph->pixel_width; | ||
| 16002 | |||
| 16003 | /* Adjust base line for subscript/superscript text. */ | ||
| 16004 | s->ybase += s->first_glyph->voffset; | ||
| 16005 | } | ||
| 16006 | |||
| 16007 | |||
| 16008 | /* Fill glyph string S from a sequence of stretch glyphs. | ||
| 16009 | |||
| 16010 | ROW is the glyph row in which the glyphs are found, AREA is the | ||
| 16011 | area within the row. START is the index of the first glyph to | ||
| 16012 | consider, END is the index of the last + 1. | ||
| 16013 | |||
| 16014 | Value is the index of the first glyph not in S. */ | ||
| 16015 | |||
| 16016 | static int | ||
| 16017 | fill_stretch_glyph_string (s, row, area, start, end) | ||
| 16018 | struct glyph_string *s; | ||
| 16019 | struct glyph_row *row; | ||
| 16020 | enum glyph_row_area area; | ||
| 16021 | int start, end; | ||
| 16022 | { | ||
| 16023 | struct glyph *glyph, *last; | ||
| 16024 | int voffset, face_id; | ||
| 16025 | |||
| 16026 | xassert (s->first_glyph->type == STRETCH_GLYPH); | ||
| 16027 | |||
| 16028 | glyph = s->row->glyphs[s->area] + start; | ||
| 16029 | last = s->row->glyphs[s->area] + end; | ||
| 16030 | face_id = glyph->face_id; | ||
| 16031 | s->face = FACE_FROM_ID (s->f, face_id); | ||
| 16032 | s->font = s->face->font; | ||
| 16033 | s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id); | ||
| 16034 | s->width = glyph->pixel_width; | ||
| 16035 | voffset = glyph->voffset; | ||
| 16036 | |||
| 16037 | for (++glyph; | ||
| 16038 | (glyph < last | ||
| 16039 | && glyph->type == STRETCH_GLYPH | ||
| 16040 | && glyph->voffset == voffset | ||
| 16041 | && glyph->face_id == face_id); | ||
| 16042 | ++glyph) | ||
| 16043 | s->width += glyph->pixel_width; | ||
| 16044 | |||
| 16045 | /* Adjust base line for subscript/superscript text. */ | ||
| 16046 | s->ybase += voffset; | ||
| 16047 | |||
| 16048 | /* The case that face->gc == 0 is handled when drawing the glyph | ||
| 16049 | string by calling PREPARE_FACE_FOR_DISPLAY. */ | ||
| 16050 | xassert (s->face); | ||
| 16051 | return glyph - s->row->glyphs[s->area]; | ||
| 16052 | } | ||
| 16053 | |||
| 16054 | |||
| 16055 | /* EXPORT for RIF: | ||
| 16056 | Set *LEFT and *RIGHT to the left and right overhang of GLYPH on | ||
| 16057 | frame F. Overhangs of glyphs other than type CHAR_GLYPH are | ||
| 16058 | assumed to be zero. */ | ||
| 16059 | |||
| 16060 | void | ||
| 16061 | x_get_glyph_overhangs (glyph, f, left, right) | ||
| 16062 | struct glyph *glyph; | ||
| 16063 | struct frame *f; | ||
| 16064 | int *left, *right; | ||
| 16065 | { | ||
| 16066 | *left = *right = 0; | ||
| 16067 | |||
| 16068 | if (glyph->type == CHAR_GLYPH) | ||
| 16069 | { | ||
| 16070 | XFontStruct *font; | ||
| 16071 | struct face *face; | ||
| 16072 | struct font_info *font_info; | ||
| 16073 | XChar2b char2b; | ||
| 16074 | XCharStruct *pcm; | ||
| 16075 | |||
| 16076 | face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL); | ||
| 16077 | font = face->font; | ||
| 16078 | font_info = FONT_INFO_FROM_ID (f, face->font_info_id); | ||
| 16079 | if (font /* ++KFS: Should this be font_info ? */ | ||
| 16080 | && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type))) | ||
| 16081 | { | ||
| 16082 | if (pcm->rbearing > pcm->width) | ||
| 16083 | *right = pcm->rbearing - pcm->width; | ||
| 16084 | if (pcm->lbearing < 0) | ||
| 16085 | *left = -pcm->lbearing; | ||
| 16086 | } | ||
| 16087 | } | ||
| 16088 | } | ||
| 16089 | |||
| 16090 | |||
| 16091 | /* Return the index of the first glyph preceding glyph string S that | ||
| 16092 | is overwritten by S because of S's left overhang. Value is -1 | ||
| 16093 | if no glyphs are overwritten. */ | ||
| 16094 | |||
| 16095 | static int | ||
| 16096 | left_overwritten (s) | ||
| 16097 | struct glyph_string *s; | ||
| 16098 | { | ||
| 16099 | int k; | ||
| 16100 | |||
| 16101 | if (s->left_overhang) | ||
| 16102 | { | ||
| 16103 | int x = 0, i; | ||
| 16104 | struct glyph *glyphs = s->row->glyphs[s->area]; | ||
| 16105 | int first = s->first_glyph - glyphs; | ||
| 16106 | |||
| 16107 | for (i = first - 1; i >= 0 && x > -s->left_overhang; --i) | ||
| 16108 | x -= glyphs[i].pixel_width; | ||
| 16109 | |||
| 16110 | k = i + 1; | ||
| 16111 | } | ||
| 16112 | else | ||
| 16113 | k = -1; | ||
| 16114 | |||
| 16115 | return k; | ||
| 16116 | } | ||
| 16117 | |||
| 16118 | |||
| 16119 | /* Return the index of the first glyph preceding glyph string S that | ||
| 16120 | is overwriting S because of its right overhang. Value is -1 if no | ||
| 16121 | glyph in front of S overwrites S. */ | ||
| 16122 | |||
| 16123 | static int | ||
| 16124 | left_overwriting (s) | ||
| 16125 | struct glyph_string *s; | ||
| 16126 | { | ||
| 16127 | int i, k, x; | ||
| 16128 | struct glyph *glyphs = s->row->glyphs[s->area]; | ||
| 16129 | int first = s->first_glyph - glyphs; | ||
| 16130 | |||
| 16131 | k = -1; | ||
| 16132 | x = 0; | ||
| 16133 | for (i = first - 1; i >= 0; --i) | ||
| 16134 | { | ||
| 16135 | int left, right; | ||
| 16136 | x_get_glyph_overhangs (glyphs + i, s->f, &left, &right); | ||
| 16137 | if (x + right > 0) | ||
| 16138 | k = i; | ||
| 16139 | x -= glyphs[i].pixel_width; | ||
| 16140 | } | ||
| 16141 | |||
| 16142 | return k; | ||
| 16143 | } | ||
| 16144 | |||
| 16145 | |||
| 16146 | /* Return the index of the last glyph following glyph string S that is | ||
| 16147 | not overwritten by S because of S's right overhang. Value is -1 if | ||
| 16148 | no such glyph is found. */ | ||
| 16149 | |||
| 16150 | static int | ||
| 16151 | right_overwritten (s) | ||
| 16152 | struct glyph_string *s; | ||
| 16153 | { | ||
| 16154 | int k = -1; | ||
| 16155 | |||
| 16156 | if (s->right_overhang) | ||
| 16157 | { | ||
| 16158 | int x = 0, i; | ||
| 16159 | struct glyph *glyphs = s->row->glyphs[s->area]; | ||
| 16160 | int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars); | ||
| 16161 | int end = s->row->used[s->area]; | ||
| 16162 | |||
| 16163 | for (i = first; i < end && s->right_overhang > x; ++i) | ||
| 16164 | x += glyphs[i].pixel_width; | ||
| 16165 | |||
| 16166 | k = i; | ||
| 16167 | } | ||
| 16168 | |||
| 16169 | return k; | ||
| 16170 | } | ||
| 16171 | |||
| 16172 | |||
| 16173 | /* Return the index of the last glyph following glyph string S that | ||
| 16174 | overwrites S because of its left overhang. Value is negative | ||
| 16175 | if no such glyph is found. */ | ||
| 16176 | |||
| 16177 | static int | ||
| 16178 | right_overwriting (s) | ||
| 16179 | struct glyph_string *s; | ||
| 16180 | { | ||
| 16181 | int i, k, x; | ||
| 16182 | int end = s->row->used[s->area]; | ||
| 16183 | struct glyph *glyphs = s->row->glyphs[s->area]; | ||
| 16184 | int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars); | ||
| 16185 | |||
| 16186 | k = -1; | ||
| 16187 | x = 0; | ||
| 16188 | for (i = first; i < end; ++i) | ||
| 16189 | { | ||
| 16190 | int left, right; | ||
| 16191 | x_get_glyph_overhangs (glyphs + i, s->f, &left, &right); | ||
| 16192 | if (x - left < 0) | ||
| 16193 | k = i; | ||
| 16194 | x += glyphs[i].pixel_width; | ||
| 16195 | } | ||
| 16196 | |||
| 16197 | return k; | ||
| 16198 | } | ||
| 16199 | |||
| 16200 | |||
| 16201 | /* Get face and two-byte form of character C in face FACE_ID on frame | ||
| 16202 | F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero | ||
| 16203 | means we want to display multibyte text. DISPLAY_P non-zero means | ||
| 16204 | make sure that X resources for the face returned are allocated. | ||
| 16205 | Value is a pointer to a realized face that is ready for display if | ||
| 16206 | DISPLAY_P is non-zero. */ | ||
| 16207 | |||
| 16208 | static INLINE struct face * | ||
| 16209 | get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p) | ||
| 16210 | struct frame *f; | ||
| 16211 | int c, face_id; | ||
| 16212 | XChar2b *char2b; | ||
| 16213 | int multibyte_p, display_p; | ||
| 16214 | { | ||
| 16215 | struct face *face = FACE_FROM_ID (f, face_id); | ||
| 16216 | |||
| 16217 | if (!multibyte_p) | ||
| 16218 | { | ||
| 16219 | /* Unibyte case. We don't have to encode, but we have to make | ||
| 16220 | sure to use a face suitable for unibyte. */ | ||
| 16221 | STORE_XCHAR2B (char2b, 0, c); | ||
| 16222 | face_id = FACE_FOR_CHAR (f, face, c); | ||
| 16223 | face = FACE_FROM_ID (f, face_id); | ||
| 16224 | } | ||
| 16225 | else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL) | ||
| 16226 | { | ||
| 16227 | /* Case of ASCII in a face known to fit ASCII. */ | ||
| 16228 | STORE_XCHAR2B (char2b, 0, c); | ||
| 16229 | } | ||
| 16230 | else | ||
| 16231 | { | ||
| 16232 | int c1, c2, charset; | ||
| 16233 | |||
| 16234 | /* Split characters into bytes. If c2 is -1 afterwards, C is | ||
| 16235 | really a one-byte character so that byte1 is zero. */ | ||
| 16236 | SPLIT_CHAR (c, charset, c1, c2); | ||
| 16237 | if (c2 > 0) | ||
| 16238 | STORE_XCHAR2B (char2b, c1, c2); | ||
| 16239 | else | ||
| 16240 | STORE_XCHAR2B (char2b, 0, c1); | ||
| 16241 | |||
| 16242 | /* Maybe encode the character in *CHAR2B. */ | ||
| 16243 | if (face->font != NULL) | ||
| 16244 | { | ||
| 16245 | struct font_info *font_info | ||
| 16246 | = FONT_INFO_FROM_ID (f, face->font_info_id); | ||
| 16247 | if (font_info) | ||
| 16248 | rif->encode_char (c, char2b, font_info, 0); | ||
| 16249 | } | ||
| 16250 | } | ||
| 16251 | |||
| 16252 | /* Make sure X resources of the face are allocated. */ | ||
| 16253 | #ifdef HAVE_X_WINDOWS | ||
| 16254 | if (display_p) | ||
| 16255 | #endif | ||
| 16256 | { | ||
| 16257 | xassert (face != NULL); | ||
| 16258 | PREPARE_FACE_FOR_DISPLAY (f, face); | ||
| 16259 | } | ||
| 16260 | |||
| 16261 | return face; | ||
| 16262 | } | ||
| 16263 | |||
| 16264 | |||
| 16265 | /* Set background width of glyph string S. START is the index of the | ||
| 16266 | first glyph following S. LAST_X is the right-most x-position + 1 | ||
| 16267 | in the drawing area. */ | ||
| 16268 | |||
| 16269 | static INLINE void | ||
| 16270 | set_glyph_string_background_width (s, start, last_x) | ||
| 16271 | struct glyph_string *s; | ||
| 16272 | int start; | ||
| 16273 | int last_x; | ||
| 16274 | { | ||
| 16275 | /* If the face of this glyph string has to be drawn to the end of | ||
| 16276 | the drawing area, set S->extends_to_end_of_line_p. */ | ||
| 16277 | struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID); | ||
| 16278 | |||
| 16279 | if (start == s->row->used[s->area] | ||
| 16280 | && s->area == TEXT_AREA | ||
| 16281 | && ((s->hl == DRAW_NORMAL_TEXT | ||
| 16282 | && (s->row->fill_line_p | ||
| 16283 | || s->face->background != default_face->background | ||
| 16284 | || s->face->stipple != default_face->stipple | ||
| 16285 | || s->row->mouse_face_p)) | ||
| 16286 | || s->hl == DRAW_MOUSE_FACE | ||
| 16287 | || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) | ||
| 16288 | && s->row->fill_line_p))) | ||
| 16289 | s->extends_to_end_of_line_p = 1; | ||
| 16290 | |||
| 16291 | /* If S extends its face to the end of the line, set its | ||
| 16292 | background_width to the distance to the right edge of the drawing | ||
| 16293 | area. */ | ||
| 16294 | if (s->extends_to_end_of_line_p) | ||
| 16295 | s->background_width = last_x - s->x + 1; | ||
| 16296 | else | ||
| 16297 | s->background_width = s->width; | ||
| 16298 | } | ||
| 16299 | |||
| 16300 | |||
| 16301 | /* Compute overhangs and x-positions for glyph string S and its | ||
| 16302 | predecessors, or successors. X is the starting x-position for S. | ||
| 16303 | BACKWARD_P non-zero means process predecessors. */ | ||
| 16304 | |||
| 16305 | static void | ||
| 16306 | compute_overhangs_and_x (s, x, backward_p) | ||
| 16307 | struct glyph_string *s; | ||
| 16308 | int x; | ||
| 16309 | int backward_p; | ||
| 16310 | { | ||
| 16311 | if (backward_p) | ||
| 16312 | { | ||
| 16313 | while (s) | ||
| 16314 | { | ||
| 16315 | if (rif->compute_glyph_string_overhangs) | ||
| 16316 | rif->compute_glyph_string_overhangs (s); | ||
| 16317 | x -= s->width; | ||
| 16318 | s->x = x; | ||
| 16319 | s = s->prev; | ||
| 16320 | } | ||
| 16321 | } | ||
| 16322 | else | ||
| 16323 | { | ||
| 16324 | while (s) | ||
| 16325 | { | ||
| 16326 | if (rif->compute_glyph_string_overhangs) | ||
| 16327 | rif->compute_glyph_string_overhangs (s); | ||
| 16328 | s->x = x; | ||
| 16329 | x += s->width; | ||
| 16330 | s = s->next; | ||
| 16331 | } | ||
| 16332 | } | ||
| 16333 | } | ||
| 16334 | |||
| 16335 | |||
| 16336 | |||
| 16337 | /* The following macros are only called from x_draw_glyphs below. | ||
| 16338 | They reference the following parameters of that function directly: | ||
| 16339 | `w', `row', `area', and `overlap_p' | ||
| 16340 | as well as the following local variables: | ||
| 16341 | `s', `f', and `hdc' (in W32) */ | ||
| 16342 | |||
| 16343 | #ifdef HAVE_NTGUI | ||
| 16344 | /* On W32, silently add local `hdc' variable to argument list of | ||
| 16345 | init_glyph_string. */ | ||
| 16346 | #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \ | ||
| 16347 | init_glyph_string (s, hdc, char2b, w, row, area, start, hl) | ||
| 16348 | #else | ||
| 16349 | #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \ | ||
| 16350 | init_glyph_string (s, char2b, w, row, area, start, hl) | ||
| 16351 | #endif | ||
| 16352 | |||
| 16353 | /* Add a glyph string for a stretch glyph to the list of strings | ||
| 16354 | between HEAD and TAIL. START is the index of the stretch glyph in | ||
| 16355 | row area AREA of glyph row ROW. END is the index of the last glyph | ||
| 16356 | in that glyph row area. X is the current output position assigned | ||
| 16357 | to the new glyph string constructed. HL overrides that face of the | ||
| 16358 | glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X | ||
| 16359 | is the right-most x-position of the drawing area. */ | ||
| 16360 | |||
| 16361 | /* SunOS 4 bundled cc, barfed on continuations in the arg lists here | ||
| 16362 | and below -- keep them on one line. */ | ||
| 16363 | #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ | ||
| 16364 | do \ | ||
| 16365 | { \ | ||
| 16366 | s = (struct glyph_string *) alloca (sizeof *s); \ | ||
| 16367 | INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \ | ||
| 16368 | START = fill_stretch_glyph_string (s, row, area, START, END); \ | ||
| 16369 | append_glyph_string (&HEAD, &TAIL, s); \ | ||
| 16370 | s->x = (X); \ | ||
| 16371 | } \ | ||
| 16372 | while (0) | ||
| 16373 | |||
| 16374 | |||
| 16375 | /* Add a glyph string for an image glyph to the list of strings | ||
| 16376 | between HEAD and TAIL. START is the index of the image glyph in | ||
| 16377 | row area AREA of glyph row ROW. END is the index of the last glyph | ||
| 16378 | in that glyph row area. X is the current output position assigned | ||
| 16379 | to the new glyph string constructed. HL overrides that face of the | ||
| 16380 | glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X | ||
| 16381 | is the right-most x-position of the drawing area. */ | ||
| 16382 | |||
| 16383 | #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ | ||
| 16384 | do \ | ||
| 16385 | { \ | ||
| 16386 | s = (struct glyph_string *) alloca (sizeof *s); \ | ||
| 16387 | INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \ | ||
| 16388 | fill_image_glyph_string (s); \ | ||
| 16389 | append_glyph_string (&HEAD, &TAIL, s); \ | ||
| 16390 | ++START; \ | ||
| 16391 | s->x = (X); \ | ||
| 16392 | } \ | ||
| 16393 | while (0) | ||
| 16394 | |||
| 16395 | |||
| 16396 | /* Add a glyph string for a sequence of character glyphs to the list | ||
| 16397 | of strings between HEAD and TAIL. START is the index of the first | ||
| 16398 | glyph in row area AREA of glyph row ROW that is part of the new | ||
| 16399 | glyph string. END is the index of the last glyph in that glyph row | ||
| 16400 | area. X is the current output position assigned to the new glyph | ||
| 16401 | string constructed. HL overrides that face of the glyph; e.g. it | ||
| 16402 | is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the | ||
| 16403 | right-most x-position of the drawing area. */ | ||
| 16404 | |||
| 16405 | #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ | ||
| 16406 | do \ | ||
| 16407 | { \ | ||
| 16408 | int c, face_id; \ | ||
| 16409 | XChar2b *char2b; \ | ||
| 16410 | \ | ||
| 16411 | c = (row)->glyphs[area][START].u.ch; \ | ||
| 16412 | face_id = (row)->glyphs[area][START].face_id; \ | ||
| 16413 | \ | ||
| 16414 | s = (struct glyph_string *) alloca (sizeof *s); \ | ||
| 16415 | char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \ | ||
| 16416 | INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ | ||
| 16417 | append_glyph_string (&HEAD, &TAIL, s); \ | ||
| 16418 | s->x = (X); \ | ||
| 16419 | START = fill_glyph_string (s, face_id, START, END, overlaps_p); \ | ||
| 16420 | } \ | ||
| 16421 | while (0) | ||
| 16422 | |||
| 16423 | |||
| 16424 | /* Add a glyph string for a composite sequence to the list of strings | ||
| 16425 | between HEAD and TAIL. START is the index of the first glyph in | ||
| 16426 | row area AREA of glyph row ROW that is part of the new glyph | ||
| 16427 | string. END is the index of the last glyph in that glyph row area. | ||
| 16428 | X is the current output position assigned to the new glyph string | ||
| 16429 | constructed. HL overrides that face of the glyph; e.g. it is | ||
| 16430 | DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most | ||
| 16431 | x-position of the drawing area. */ | ||
| 16432 | |||
| 16433 | #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ | ||
| 16434 | do { \ | ||
| 16435 | int cmp_id = (row)->glyphs[area][START].u.cmp_id; \ | ||
| 16436 | int face_id = (row)->glyphs[area][START].face_id; \ | ||
| 16437 | struct face *base_face = FACE_FROM_ID (f, face_id); \ | ||
| 16438 | struct composition *cmp = composition_table[cmp_id]; \ | ||
| 16439 | int glyph_len = cmp->glyph_len; \ | ||
| 16440 | XChar2b *char2b; \ | ||
| 16441 | struct face **faces; \ | ||
| 16442 | struct glyph_string *first_s = NULL; \ | ||
| 16443 | int n; \ | ||
| 16444 | \ | ||
| 16445 | base_face = base_face->ascii_face; \ | ||
| 16446 | char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \ | ||
| 16447 | faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \ | ||
| 16448 | /* At first, fill in `char2b' and `faces'. */ \ | ||
| 16449 | for (n = 0; n < glyph_len; n++) \ | ||
| 16450 | { \ | ||
| 16451 | int c = COMPOSITION_GLYPH (cmp, n); \ | ||
| 16452 | int this_face_id = FACE_FOR_CHAR (f, base_face, c); \ | ||
| 16453 | faces[n] = FACE_FROM_ID (f, this_face_id); \ | ||
| 16454 | get_char_face_and_encoding (f, c, this_face_id, \ | ||
| 16455 | char2b + n, 1, 1); \ | ||
| 16456 | } \ | ||
| 16457 | \ | ||
| 16458 | /* Make glyph_strings for each glyph sequence that is drawable by \ | ||
| 16459 | the same face, and append them to HEAD/TAIL. */ \ | ||
| 16460 | for (n = 0; n < cmp->glyph_len;) \ | ||
| 16461 | { \ | ||
| 16462 | s = (struct glyph_string *) alloca (sizeof *s); \ | ||
| 16463 | INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL); \ | ||
| 16464 | append_glyph_string (&(HEAD), &(TAIL), s); \ | ||
| 16465 | s->cmp = cmp; \ | ||
| 16466 | s->gidx = n; \ | ||
| 16467 | s->x = (X); \ | ||
| 16468 | \ | ||
| 16469 | if (n == 0) \ | ||
| 16470 | first_s = s; \ | ||
| 16471 | \ | ||
| 16472 | n = fill_composite_glyph_string (s, faces, overlaps_p); \ | ||
| 16473 | } \ | ||
| 16474 | \ | ||
| 16475 | ++START; \ | ||
| 16476 | s = first_s; \ | ||
| 16477 | } while (0) | ||
| 16478 | |||
| 16479 | |||
| 16480 | /* Build a list of glyph strings between HEAD and TAIL for the glyphs | ||
| 16481 | of AREA of glyph row ROW on window W between indices START and END. | ||
| 16482 | HL overrides the face for drawing glyph strings, e.g. it is | ||
| 16483 | DRAW_CURSOR to draw a cursor. X and LAST_X are start and end | ||
| 16484 | x-positions of the drawing area. | ||
| 16485 | |||
| 16486 | This is an ugly monster macro construct because we must use alloca | ||
| 16487 | to allocate glyph strings (because x_draw_glyphs can be called | ||
| 16488 | asynchronously). */ | ||
| 16489 | |||
| 16490 | #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ | ||
| 16491 | do \ | ||
| 16492 | { \ | ||
| 16493 | HEAD = TAIL = NULL; \ | ||
| 16494 | while (START < END) \ | ||
| 16495 | { \ | ||
| 16496 | struct glyph *first_glyph = (row)->glyphs[area] + START; \ | ||
| 16497 | switch (first_glyph->type) \ | ||
| 16498 | { \ | ||
| 16499 | case CHAR_GLYPH: \ | ||
| 16500 | BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ | ||
| 16501 | HL, X, LAST_X); \ | ||
| 16502 | break; \ | ||
| 16503 | \ | ||
| 16504 | case COMPOSITE_GLYPH: \ | ||
| 16505 | BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ | ||
| 16506 | HL, X, LAST_X); \ | ||
| 16507 | break; \ | ||
| 16508 | \ | ||
| 16509 | case STRETCH_GLYPH: \ | ||
| 16510 | BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ | ||
| 16511 | HL, X, LAST_X); \ | ||
| 16512 | break; \ | ||
| 16513 | \ | ||
| 16514 | case IMAGE_GLYPH: \ | ||
| 16515 | BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ | ||
| 16516 | HL, X, LAST_X); \ | ||
| 16517 | break; \ | ||
| 16518 | \ | ||
| 16519 | default: \ | ||
| 16520 | abort (); \ | ||
| 16521 | } \ | ||
| 16522 | \ | ||
| 16523 | set_glyph_string_background_width (s, START, LAST_X); \ | ||
| 16524 | (X) += s->width; \ | ||
| 16525 | } \ | ||
| 16526 | } \ | ||
| 16527 | while (0) | ||
| 16528 | |||
| 16529 | |||
| 16530 | /* Draw glyphs between START and END in AREA of ROW on window W, | ||
| 16531 | starting at x-position X. X is relative to AREA in W. HL is a | ||
| 16532 | face-override with the following meaning: | ||
| 16533 | |||
| 16534 | DRAW_NORMAL_TEXT draw normally | ||
| 16535 | DRAW_CURSOR draw in cursor face | ||
| 16536 | DRAW_MOUSE_FACE draw in mouse face. | ||
| 16537 | DRAW_INVERSE_VIDEO draw in mode line face | ||
| 16538 | DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it | ||
| 16539 | DRAW_IMAGE_RAISED draw an image with a raised relief around it | ||
| 16540 | |||
| 16541 | If OVERLAPS_P is non-zero, draw only the foreground of characters | ||
| 16542 | and clip to the physical height of ROW. | ||
| 16543 | |||
| 16544 | Value is the x-position reached, relative to AREA of W. */ | ||
| 16545 | |||
| 16546 | int | ||
| 16547 | x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) | ||
| 16548 | struct window *w; | ||
| 16549 | int x; | ||
| 16550 | struct glyph_row *row; | ||
| 16551 | enum glyph_row_area area; | ||
| 16552 | int start, end; | ||
| 16553 | enum draw_glyphs_face hl; | ||
| 16554 | int overlaps_p; | ||
| 16555 | { | ||
| 16556 | struct glyph_string *head, *tail; | ||
| 16557 | struct glyph_string *s; | ||
| 16558 | int last_x, area_width; | ||
| 16559 | int x_reached; | ||
| 16560 | int i, j; | ||
| 16561 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 16562 | DECLARE_HDC (hdc); | ||
| 16563 | |||
| 16564 | ALLOCATE_HDC (hdc, f); | ||
| 16565 | |||
| 16566 | /* Let's rather be paranoid than getting a SEGV. */ | ||
| 16567 | end = min (end, row->used[area]); | ||
| 16568 | start = max (0, start); | ||
| 16569 | start = min (end, start); | ||
| 16570 | |||
| 16571 | /* Translate X to frame coordinates. Set last_x to the right | ||
| 16572 | end of the drawing area. */ | ||
| 16573 | if (row->full_width_p) | ||
| 16574 | { | ||
| 16575 | /* X is relative to the left edge of W, without scroll bars | ||
| 16576 | or fringes. */ | ||
| 16577 | int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f); | ||
| 16578 | |||
| 16579 | x += window_left_x; | ||
| 16580 | area_width = XFASTINT (w->width) * CANON_X_UNIT (f); | ||
| 16581 | last_x = window_left_x + area_width; | ||
| 16582 | |||
| 16583 | if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | ||
| 16584 | { | ||
| 16585 | int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f); | ||
| 16586 | if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) | ||
| 16587 | last_x += width; | ||
| 16588 | else | ||
| 16589 | x -= width; | ||
| 16590 | } | ||
| 16591 | |||
| 16592 | x += FRAME_INTERNAL_BORDER_WIDTH (f); | ||
| 16593 | /* ++KFS: W32 and MAC versions had -= in next line (bug??) */ | ||
| 16594 | last_x += FRAME_INTERNAL_BORDER_WIDTH (f); | ||
| 16595 | } | ||
| 16596 | else | ||
| 16597 | { | ||
| 16598 | x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x); | ||
| 16599 | area_width = window_box_width (w, area); | ||
| 16600 | last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width); | ||
| 16601 | } | ||
| 16602 | |||
| 16603 | /* Build a doubly-linked list of glyph_string structures between | ||
| 16604 | head and tail from what we have to draw. Note that the macro | ||
| 16605 | BUILD_GLYPH_STRINGS will modify its start parameter. That's | ||
| 16606 | the reason we use a separate variable `i'. */ | ||
| 16607 | i = start; | ||
| 16608 | BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x); | ||
| 16609 | if (tail) | ||
| 16610 | x_reached = tail->x + tail->background_width; | ||
| 16611 | else | ||
| 16612 | x_reached = x; | ||
| 16613 | |||
| 16614 | /* If there are any glyphs with lbearing < 0 or rbearing > width in | ||
| 16615 | the row, redraw some glyphs in front or following the glyph | ||
| 16616 | strings built above. */ | ||
| 16617 | if (head && !overlaps_p && row->contains_overlapping_glyphs_p) | ||
| 16618 | { | ||
| 16619 | int dummy_x = 0; | ||
| 16620 | struct glyph_string *h, *t; | ||
| 16621 | |||
| 16622 | /* Compute overhangs for all glyph strings. */ | ||
| 16623 | if (rif->compute_glyph_string_overhangs) | ||
| 16624 | for (s = head; s; s = s->next) | ||
| 16625 | rif->compute_glyph_string_overhangs (s); | ||
| 16626 | |||
| 16627 | /* Prepend glyph strings for glyphs in front of the first glyph | ||
| 16628 | string that are overwritten because of the first glyph | ||
| 16629 | string's left overhang. The background of all strings | ||
| 16630 | prepended must be drawn because the first glyph string | ||
| 16631 | draws over it. */ | ||
| 16632 | i = left_overwritten (head); | ||
| 16633 | if (i >= 0) | ||
| 16634 | { | ||
| 16635 | j = i; | ||
| 16636 | BUILD_GLYPH_STRINGS (j, start, h, t, | ||
| 16637 | DRAW_NORMAL_TEXT, dummy_x, last_x); | ||
| 16638 | start = i; | ||
| 16639 | compute_overhangs_and_x (t, head->x, 1); | ||
| 16640 | prepend_glyph_string_lists (&head, &tail, h, t); | ||
| 16641 | } | ||
| 16642 | |||
| 16643 | /* Prepend glyph strings for glyphs in front of the first glyph | ||
| 16644 | string that overwrite that glyph string because of their | ||
| 16645 | right overhang. For these strings, only the foreground must | ||
| 16646 | be drawn, because it draws over the glyph string at `head'. | ||
| 16647 | The background must not be drawn because this would overwrite | ||
| 16648 | right overhangs of preceding glyphs for which no glyph | ||
| 16649 | strings exist. */ | ||
| 16650 | i = left_overwriting (head); | ||
| 16651 | if (i >= 0) | ||
| 16652 | { | ||
| 16653 | BUILD_GLYPH_STRINGS (i, start, h, t, | ||
| 16654 | DRAW_NORMAL_TEXT, dummy_x, last_x); | ||
| 16655 | for (s = h; s; s = s->next) | ||
| 16656 | s->background_filled_p = 1; | ||
| 16657 | compute_overhangs_and_x (t, head->x, 1); | ||
| 16658 | prepend_glyph_string_lists (&head, &tail, h, t); | ||
| 16659 | } | ||
| 16660 | |||
| 16661 | /* Append glyphs strings for glyphs following the last glyph | ||
| 16662 | string tail that are overwritten by tail. The background of | ||
| 16663 | these strings has to be drawn because tail's foreground draws | ||
| 16664 | over it. */ | ||
| 16665 | i = right_overwritten (tail); | ||
| 16666 | if (i >= 0) | ||
| 16667 | { | ||
| 16668 | BUILD_GLYPH_STRINGS (end, i, h, t, | ||
| 16669 | DRAW_NORMAL_TEXT, x, last_x); | ||
| 16670 | compute_overhangs_and_x (h, tail->x + tail->width, 0); | ||
| 16671 | append_glyph_string_lists (&head, &tail, h, t); | ||
| 16672 | } | ||
| 16673 | |||
| 16674 | /* Append glyph strings for glyphs following the last glyph | ||
| 16675 | string tail that overwrite tail. The foreground of such | ||
| 16676 | glyphs has to be drawn because it writes into the background | ||
| 16677 | of tail. The background must not be drawn because it could | ||
| 16678 | paint over the foreground of following glyphs. */ | ||
| 16679 | i = right_overwriting (tail); | ||
| 16680 | if (i >= 0) | ||
| 16681 | { | ||
| 16682 | BUILD_GLYPH_STRINGS (end, i, h, t, | ||
| 16683 | DRAW_NORMAL_TEXT, x, last_x); | ||
| 16684 | for (s = h; s; s = s->next) | ||
| 16685 | s->background_filled_p = 1; | ||
| 16686 | compute_overhangs_and_x (h, tail->x + tail->width, 0); | ||
| 16687 | append_glyph_string_lists (&head, &tail, h, t); | ||
| 16688 | } | ||
| 16689 | } | ||
| 16690 | |||
| 16691 | /* Draw all strings. */ | ||
| 16692 | for (s = head; s; s = s->next) | ||
| 16693 | rif->draw_glyph_string (s); | ||
| 16694 | |||
| 16695 | if (area == TEXT_AREA | ||
| 16696 | && !row->full_width_p | ||
| 16697 | /* When drawing overlapping rows, only the glyph strings' | ||
| 16698 | foreground is drawn, which doesn't erase a cursor | ||
| 16699 | completely. */ | ||
| 16700 | && !overlaps_p) | ||
| 16701 | { | ||
| 16702 | int x0 = head ? head->x : x; | ||
| 16703 | int x1 = tail ? tail->x + tail->background_width : x; | ||
| 16704 | |||
| 16705 | x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0); | ||
| 16706 | x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1); | ||
| 16707 | |||
| 16708 | /* ++KFS: W32 and MAC versions had following test here: | ||
| 16709 | if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0) | ||
| 16710 | */ | ||
| 16711 | |||
| 16712 | if (XFASTINT (w->left_margin_width) != 0) | ||
| 16713 | { | ||
| 16714 | int left_area_width = window_box_width (w, LEFT_MARGIN_AREA); | ||
| 16715 | x0 -= left_area_width; | ||
| 16716 | x1 -= left_area_width; | ||
| 16717 | } | ||
| 16718 | |||
| 16719 | notice_overwritten_cursor (w, area, x0, x1, | ||
| 16720 | row->y, MATRIX_ROW_BOTTOM_Y (row)); | ||
| 16721 | } | ||
| 16722 | |||
| 16723 | /* Value is the x-position up to which drawn, relative to AREA of W. | ||
| 16724 | This doesn't include parts drawn because of overhangs. */ | ||
| 16725 | x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached); | ||
| 16726 | if (!row->full_width_p) | ||
| 16727 | { | ||
| 16728 | /* ++KFS: W32 and MAC versions only had this test here: | ||
| 16729 | if (area > LEFT_MARGIN_AREA) | ||
| 16730 | */ | ||
| 16731 | |||
| 16732 | if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0) | ||
| 16733 | x_reached -= window_box_width (w, LEFT_MARGIN_AREA); | ||
| 16734 | if (area > TEXT_AREA) | ||
| 16735 | x_reached -= window_box_width (w, TEXT_AREA); | ||
| 16736 | } | ||
| 16737 | |||
| 16738 | RELEASE_HDC (hdc, f); | ||
| 16739 | |||
| 16740 | return x_reached; | ||
| 16741 | } | ||
| 16742 | |||
| 16743 | |||
| 16744 | /* Store one glyph for IT->char_to_display in IT->glyph_row. | ||
| 16745 | Called from x_produce_glyphs when IT->glyph_row is non-null. */ | ||
| 16746 | |||
| 16747 | static INLINE void | ||
| 16748 | append_glyph (it) | ||
| 16749 | struct it *it; | ||
| 16750 | { | ||
| 16751 | struct glyph *glyph; | ||
| 16752 | enum glyph_row_area area = it->area; | ||
| 16753 | |||
| 16754 | xassert (it->glyph_row); | ||
| 16755 | xassert (it->char_to_display != '\n' && it->char_to_display != '\t'); | ||
| 16756 | |||
| 16757 | glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; | ||
| 16758 | if (glyph < it->glyph_row->glyphs[area + 1]) | ||
| 16759 | { | ||
| 16760 | glyph->charpos = CHARPOS (it->position); | ||
| 16761 | glyph->object = it->object; | ||
| 16762 | glyph->pixel_width = it->pixel_width; | ||
| 16763 | glyph->voffset = it->voffset; | ||
| 16764 | glyph->type = CHAR_GLYPH; | ||
| 16765 | glyph->multibyte_p = it->multibyte_p; | ||
| 16766 | glyph->left_box_line_p = it->start_of_box_run_p; | ||
| 16767 | glyph->right_box_line_p = it->end_of_box_run_p; | ||
| 16768 | glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent | ||
| 16769 | || it->phys_descent > it->descent); | ||
| 16770 | glyph->padding_p = 0; | ||
| 16771 | glyph->glyph_not_available_p = it->glyph_not_available_p; | ||
| 16772 | glyph->face_id = it->face_id; | ||
| 16773 | glyph->u.ch = it->char_to_display; | ||
| 16774 | glyph->font_type = FONT_TYPE_UNKNOWN; | ||
| 16775 | ++it->glyph_row->used[area]; | ||
| 16776 | } | ||
| 16777 | } | ||
| 16778 | |||
| 16779 | /* Store one glyph for the composition IT->cmp_id in IT->glyph_row. | ||
| 16780 | Called from x_produce_glyphs when IT->glyph_row is non-null. */ | ||
| 16781 | |||
| 16782 | static INLINE void | ||
| 16783 | append_composite_glyph (it) | ||
| 16784 | struct it *it; | ||
| 16785 | { | ||
| 16786 | struct glyph *glyph; | ||
| 16787 | enum glyph_row_area area = it->area; | ||
| 16788 | |||
| 16789 | xassert (it->glyph_row); | ||
| 16790 | |||
| 16791 | glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; | ||
| 16792 | if (glyph < it->glyph_row->glyphs[area + 1]) | ||
| 16793 | { | ||
| 16794 | glyph->charpos = CHARPOS (it->position); | ||
| 16795 | glyph->object = it->object; | ||
| 16796 | glyph->pixel_width = it->pixel_width; | ||
| 16797 | glyph->voffset = it->voffset; | ||
| 16798 | glyph->type = COMPOSITE_GLYPH; | ||
| 16799 | glyph->multibyte_p = it->multibyte_p; | ||
| 16800 | glyph->left_box_line_p = it->start_of_box_run_p; | ||
| 16801 | glyph->right_box_line_p = it->end_of_box_run_p; | ||
| 16802 | glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent | ||
| 16803 | || it->phys_descent > it->descent); | ||
| 16804 | glyph->padding_p = 0; | ||
| 16805 | glyph->glyph_not_available_p = 0; | ||
| 16806 | glyph->face_id = it->face_id; | ||
| 16807 | glyph->u.cmp_id = it->cmp_id; | ||
| 16808 | glyph->font_type = FONT_TYPE_UNKNOWN; | ||
| 16809 | ++it->glyph_row->used[area]; | ||
| 16810 | } | ||
| 16811 | } | ||
| 16812 | |||
| 16813 | |||
| 16814 | /* Change IT->ascent and IT->height according to the setting of | ||
| 16815 | IT->voffset. */ | ||
| 16816 | |||
| 16817 | static INLINE void | ||
| 16818 | take_vertical_position_into_account (it) | ||
| 16819 | struct it *it; | ||
| 16820 | { | ||
| 16821 | if (it->voffset) | ||
| 16822 | { | ||
| 16823 | if (it->voffset < 0) | ||
| 16824 | /* Increase the ascent so that we can display the text higher | ||
| 16825 | in the line. */ | ||
| 16826 | it->ascent += abs (it->voffset); | ||
| 16827 | else | ||
| 16828 | /* Increase the descent so that we can display the text lower | ||
| 16829 | in the line. */ | ||
| 16830 | it->descent += it->voffset; | ||
| 16831 | } | ||
| 16832 | } | ||
| 16833 | |||
| 16834 | |||
| 16835 | /* Produce glyphs/get display metrics for the image IT is loaded with. | ||
| 16836 | See the description of struct display_iterator in dispextern.h for | ||
| 16837 | an overview of struct display_iterator. */ | ||
| 16838 | |||
| 16839 | static void | ||
| 16840 | produce_image_glyph (it) | ||
| 16841 | struct it *it; | ||
| 16842 | { | ||
| 16843 | struct image *img; | ||
| 16844 | struct face *face; | ||
| 16845 | |||
| 16846 | xassert (it->what == IT_IMAGE); | ||
| 16847 | |||
| 16848 | face = FACE_FROM_ID (it->f, it->face_id); | ||
| 16849 | img = IMAGE_FROM_ID (it->f, it->image_id); | ||
| 16850 | xassert (img); | ||
| 16851 | |||
| 16852 | /* Make sure X resources of the face and image are loaded. */ | ||
| 16853 | PREPARE_FACE_FOR_DISPLAY (it->f, face); | ||
| 16854 | prepare_image_for_display (it->f, img); | ||
| 16855 | |||
| 16856 | it->ascent = it->phys_ascent = image_ascent (img, face); | ||
| 16857 | it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent; | ||
| 16858 | it->pixel_width = img->width + 2 * img->hmargin; | ||
| 16859 | |||
| 16860 | it->nglyphs = 1; | ||
| 16861 | |||
| 16862 | if (face->box != FACE_NO_BOX) | ||
| 16863 | { | ||
| 16864 | if (face->box_line_width > 0) | ||
| 16865 | { | ||
| 16866 | it->ascent += face->box_line_width; | ||
| 16867 | it->descent += face->box_line_width; | ||
| 16868 | } | ||
| 16869 | |||
| 16870 | if (it->start_of_box_run_p) | ||
| 16871 | it->pixel_width += abs (face->box_line_width); | ||
| 16872 | if (it->end_of_box_run_p) | ||
| 16873 | it->pixel_width += abs (face->box_line_width); | ||
| 16874 | } | ||
| 16875 | |||
| 16876 | take_vertical_position_into_account (it); | ||
| 16877 | |||
| 16878 | if (it->glyph_row) | ||
| 16879 | { | ||
| 16880 | struct glyph *glyph; | ||
| 16881 | enum glyph_row_area area = it->area; | ||
| 16882 | |||
| 16883 | glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; | ||
| 16884 | if (glyph < it->glyph_row->glyphs[area + 1]) | ||
| 16885 | { | ||
| 16886 | glyph->charpos = CHARPOS (it->position); | ||
| 16887 | glyph->object = it->object; | ||
| 16888 | glyph->pixel_width = it->pixel_width; | ||
| 16889 | glyph->voffset = it->voffset; | ||
| 16890 | glyph->type = IMAGE_GLYPH; | ||
| 16891 | glyph->multibyte_p = it->multibyte_p; | ||
| 16892 | glyph->left_box_line_p = it->start_of_box_run_p; | ||
| 16893 | glyph->right_box_line_p = it->end_of_box_run_p; | ||
| 16894 | glyph->overlaps_vertically_p = 0; | ||
| 16895 | glyph->padding_p = 0; | ||
| 16896 | glyph->glyph_not_available_p = 0; | ||
| 16897 | glyph->face_id = it->face_id; | ||
| 16898 | glyph->u.img_id = img->id; | ||
| 16899 | glyph->font_type = FONT_TYPE_UNKNOWN; | ||
| 16900 | ++it->glyph_row->used[area]; | ||
| 16901 | } | ||
| 16902 | } | ||
| 16903 | } | ||
| 16904 | |||
| 16905 | |||
| 16906 | /* Append a stretch glyph to IT->glyph_row. OBJECT is the source | ||
| 16907 | of the glyph, WIDTH and HEIGHT are the width and height of the | ||
| 16908 | stretch. ASCENT is the percentage/100 of HEIGHT to use for the | ||
| 16909 | ascent of the glyph (0 <= ASCENT <= 1). */ | ||
| 16910 | |||
| 16911 | static void | ||
| 16912 | append_stretch_glyph (it, object, width, height, ascent) | ||
| 16913 | struct it *it; | ||
| 16914 | Lisp_Object object; | ||
| 16915 | int width, height; | ||
| 16916 | double ascent; | ||
| 16917 | { | ||
| 16918 | struct glyph *glyph; | ||
| 16919 | enum glyph_row_area area = it->area; | ||
| 16920 | |||
| 16921 | xassert (ascent >= 0 && ascent <= 1); | ||
| 16922 | |||
| 16923 | glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; | ||
| 16924 | if (glyph < it->glyph_row->glyphs[area + 1]) | ||
| 16925 | { | ||
| 16926 | glyph->charpos = CHARPOS (it->position); | ||
| 16927 | glyph->object = object; | ||
| 16928 | glyph->pixel_width = width; | ||
| 16929 | glyph->voffset = it->voffset; | ||
| 16930 | glyph->type = STRETCH_GLYPH; | ||
| 16931 | glyph->multibyte_p = it->multibyte_p; | ||
| 16932 | glyph->left_box_line_p = it->start_of_box_run_p; | ||
| 16933 | glyph->right_box_line_p = it->end_of_box_run_p; | ||
| 16934 | glyph->overlaps_vertically_p = 0; | ||
| 16935 | glyph->padding_p = 0; | ||
| 16936 | glyph->glyph_not_available_p = 0; | ||
| 16937 | glyph->face_id = it->face_id; | ||
| 16938 | glyph->u.stretch.ascent = height * ascent; | ||
| 16939 | glyph->u.stretch.height = height; | ||
| 16940 | glyph->font_type = FONT_TYPE_UNKNOWN; | ||
| 16941 | ++it->glyph_row->used[area]; | ||
| 16942 | } | ||
| 16943 | } | ||
| 16944 | |||
| 16945 | |||
| 16946 | /* Produce a stretch glyph for iterator IT. IT->object is the value | ||
| 16947 | of the glyph property displayed. The value must be a list | ||
| 16948 | `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs | ||
| 16949 | being recognized: | ||
| 16950 | |||
| 16951 | 1. `:width WIDTH' specifies that the space should be WIDTH * | ||
| 16952 | canonical char width wide. WIDTH may be an integer or floating | ||
| 16953 | point number. | ||
| 16954 | |||
| 16955 | 2. `:relative-width FACTOR' specifies that the width of the stretch | ||
| 16956 | should be computed from the width of the first character having the | ||
| 16957 | `glyph' property, and should be FACTOR times that width. | ||
| 16958 | |||
| 16959 | 3. `:align-to HPOS' specifies that the space should be wide enough | ||
| 16960 | to reach HPOS, a value in canonical character units. | ||
| 16961 | |||
| 16962 | Exactly one of the above pairs must be present. | ||
| 16963 | |||
| 16964 | 4. `:height HEIGHT' specifies that the height of the stretch produced | ||
| 16965 | should be HEIGHT, measured in canonical character units. | ||
| 16966 | |||
| 16967 | 5. `:relative-height FACTOR' specifies that the height of the | ||
| 16968 | stretch should be FACTOR times the height of the characters having | ||
| 16969 | the glyph property. | ||
| 16970 | |||
| 16971 | Either none or exactly one of 4 or 5 must be present. | ||
| 16972 | |||
| 16973 | 6. `:ascent ASCENT' specifies that ASCENT percent of the height | ||
| 16974 | of the stretch should be used for the ascent of the stretch. | ||
| 16975 | ASCENT must be in the range 0 <= ASCENT <= 100. */ | ||
| 16976 | |||
| 16977 | #define NUMVAL(X) \ | ||
| 16978 | ((INTEGERP (X) || FLOATP (X)) \ | ||
| 16979 | ? XFLOATINT (X) \ | ||
| 16980 | : - 1) | ||
| 16981 | |||
| 16982 | |||
| 16983 | static void | ||
| 16984 | produce_stretch_glyph (it) | ||
| 16985 | struct it *it; | ||
| 16986 | { | ||
| 16987 | /* (space :width WIDTH :height HEIGHT. */ | ||
| 16988 | Lisp_Object prop, plist; | ||
| 16989 | int width = 0, height = 0; | ||
| 16990 | double ascent = 0; | ||
| 16991 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | ||
| 16992 | XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f); | ||
| 16993 | |||
| 16994 | PREPARE_FACE_FOR_DISPLAY (it->f, face); | ||
| 16995 | |||
| 16996 | /* List should start with `space'. */ | ||
| 16997 | xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace)); | ||
| 16998 | plist = XCDR (it->object); | ||
| 16999 | |||
| 17000 | /* Compute the width of the stretch. */ | ||
| 17001 | if (prop = Fplist_get (plist, QCwidth), | ||
| 17002 | NUMVAL (prop) > 0) | ||
| 17003 | /* Absolute width `:width WIDTH' specified and valid. */ | ||
| 17004 | width = NUMVAL (prop) * CANON_X_UNIT (it->f); | ||
| 17005 | else if (prop = Fplist_get (plist, QCrelative_width), | ||
| 17006 | NUMVAL (prop) > 0) | ||
| 17007 | { | ||
| 17008 | /* Relative width `:relative-width FACTOR' specified and valid. | ||
| 17009 | Compute the width of the characters having the `glyph' | ||
| 17010 | property. */ | ||
| 17011 | struct it it2; | ||
| 17012 | unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); | ||
| 17013 | |||
| 17014 | it2 = *it; | ||
| 17015 | if (it->multibyte_p) | ||
| 17016 | { | ||
| 17017 | int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT) | ||
| 17018 | - IT_BYTEPOS (*it)); | ||
| 17019 | it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len); | ||
| 17020 | } | ||
| 17021 | else | ||
| 17022 | it2.c = *p, it2.len = 1; | ||
| 17023 | |||
| 17024 | it2.glyph_row = NULL; | ||
| 17025 | it2.what = IT_CHARACTER; | ||
| 17026 | x_produce_glyphs (&it2); | ||
| 17027 | width = NUMVAL (prop) * it2.pixel_width; | ||
| 17028 | } | ||
| 17029 | else if (prop = Fplist_get (plist, QCalign_to), | ||
| 17030 | NUMVAL (prop) > 0) | ||
| 17031 | width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x; | ||
| 17032 | else | ||
| 17033 | /* Nothing specified -> width defaults to canonical char width. */ | ||
| 17034 | width = CANON_X_UNIT (it->f); | ||
| 17035 | |||
| 17036 | /* Compute height. */ | ||
| 17037 | if (prop = Fplist_get (plist, QCheight), | ||
| 17038 | NUMVAL (prop) > 0) | ||
| 17039 | height = NUMVAL (prop) * CANON_Y_UNIT (it->f); | ||
| 17040 | else if (prop = Fplist_get (plist, QCrelative_height), | ||
| 17041 | NUMVAL (prop) > 0) | ||
| 17042 | height = FONT_HEIGHT (font) * NUMVAL (prop); | ||
| 17043 | else | ||
| 17044 | height = FONT_HEIGHT (font); | ||
| 17045 | |||
| 17046 | /* Compute percentage of height used for ascent. If | ||
| 17047 | `:ascent ASCENT' is present and valid, use that. Otherwise, | ||
| 17048 | derive the ascent from the font in use. */ | ||
| 17049 | if (prop = Fplist_get (plist, QCascent), | ||
| 17050 | NUMVAL (prop) > 0 && NUMVAL (prop) <= 100) | ||
| 17051 | ascent = NUMVAL (prop) / 100.0; | ||
| 17052 | else | ||
| 17053 | ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font); | ||
| 17054 | |||
| 17055 | if (width <= 0) | ||
| 17056 | width = 1; | ||
| 17057 | if (height <= 0) | ||
| 17058 | height = 1; | ||
| 17059 | |||
| 17060 | if (it->glyph_row) | ||
| 17061 | { | ||
| 17062 | Lisp_Object object = it->stack[it->sp - 1].string; | ||
| 17063 | if (!STRINGP (object)) | ||
| 17064 | object = it->w->buffer; | ||
| 17065 | append_stretch_glyph (it, object, width, height, ascent); | ||
| 17066 | } | ||
| 17067 | |||
| 17068 | it->pixel_width = width; | ||
| 17069 | it->ascent = it->phys_ascent = height * ascent; | ||
| 17070 | it->descent = it->phys_descent = height - it->ascent; | ||
| 17071 | it->nglyphs = 1; | ||
| 17072 | |||
| 17073 | if (face->box != FACE_NO_BOX) | ||
| 17074 | { | ||
| 17075 | if (face->box_line_width > 0) | ||
| 17076 | { | ||
| 17077 | it->ascent += face->box_line_width; | ||
| 17078 | it->descent += face->box_line_width; | ||
| 17079 | } | ||
| 17080 | |||
| 17081 | if (it->start_of_box_run_p) | ||
| 17082 | it->pixel_width += abs (face->box_line_width); | ||
| 17083 | if (it->end_of_box_run_p) | ||
| 17084 | it->pixel_width += abs (face->box_line_width); | ||
| 17085 | } | ||
| 17086 | |||
| 17087 | take_vertical_position_into_account (it); | ||
| 17088 | } | ||
| 17089 | |||
| 17090 | /* RIF: | ||
| 17091 | Produce glyphs/get display metrics for the display element IT is | ||
| 17092 | loaded with. See the description of struct display_iterator in | ||
| 17093 | dispextern.h for an overview of struct display_iterator. */ | ||
| 17094 | |||
| 17095 | void | ||
| 17096 | x_produce_glyphs (it) | ||
| 17097 | struct it *it; | ||
| 17098 | { | ||
| 17099 | it->glyph_not_available_p = 0; | ||
| 17100 | |||
| 17101 | if (it->what == IT_CHARACTER) | ||
| 17102 | { | ||
| 17103 | XChar2b char2b; | ||
| 17104 | XFontStruct *font; | ||
| 17105 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | ||
| 17106 | XCharStruct *pcm; | ||
| 17107 | int font_not_found_p; | ||
| 17108 | struct font_info *font_info; | ||
| 17109 | int boff; /* baseline offset */ | ||
| 17110 | /* We may change it->multibyte_p upon unibyte<->multibyte | ||
| 17111 | conversion. So, save the current value now and restore it | ||
| 17112 | later. | ||
| 17113 | |||
| 17114 | Note: It seems that we don't have to record multibyte_p in | ||
| 17115 | struct glyph because the character code itself tells if or | ||
| 17116 | not the character is multibyte. Thus, in the future, we must | ||
| 17117 | consider eliminating the field `multibyte_p' in the struct | ||
| 17118 | glyph. */ | ||
| 17119 | int saved_multibyte_p = it->multibyte_p; | ||
| 17120 | |||
| 17121 | /* Maybe translate single-byte characters to multibyte, or the | ||
| 17122 | other way. */ | ||
| 17123 | it->char_to_display = it->c; | ||
| 17124 | if (!ASCII_BYTE_P (it->c)) | ||
| 17125 | { | ||
| 17126 | if (unibyte_display_via_language_environment | ||
| 17127 | && SINGLE_BYTE_CHAR_P (it->c) | ||
| 17128 | && (it->c >= 0240 | ||
| 17129 | || !NILP (Vnonascii_translation_table))) | ||
| 17130 | { | ||
| 17131 | it->char_to_display = unibyte_char_to_multibyte (it->c); | ||
| 17132 | it->multibyte_p = 1; | ||
| 17133 | it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display); | ||
| 17134 | face = FACE_FROM_ID (it->f, it->face_id); | ||
| 17135 | } | ||
| 17136 | else if (!SINGLE_BYTE_CHAR_P (it->c) | ||
| 17137 | && !it->multibyte_p) | ||
| 17138 | { | ||
| 17139 | it->multibyte_p = 1; | ||
| 17140 | it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display); | ||
| 17141 | face = FACE_FROM_ID (it->f, it->face_id); | ||
| 17142 | } | ||
| 17143 | } | ||
| 17144 | |||
| 17145 | /* Get font to use. Encode IT->char_to_display. */ | ||
| 17146 | get_char_face_and_encoding (it->f, it->char_to_display, it->face_id, | ||
| 17147 | &char2b, it->multibyte_p, 0); | ||
| 17148 | font = face->font; | ||
| 17149 | |||
| 17150 | /* When no suitable font found, use the default font. */ | ||
| 17151 | font_not_found_p = font == NULL; | ||
| 17152 | if (font_not_found_p) | ||
| 17153 | { | ||
| 17154 | font = FRAME_FONT (it->f); | ||
| 17155 | boff = FRAME_BASELINE_OFFSET (it->f); | ||
| 17156 | font_info = NULL; | ||
| 17157 | } | ||
| 17158 | else | ||
| 17159 | { | ||
| 17160 | font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id); | ||
| 17161 | boff = font_info->baseline_offset; | ||
| 17162 | if (font_info->vertical_centering) | ||
| 17163 | boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; | ||
| 17164 | } | ||
| 17165 | |||
| 17166 | if (it->char_to_display >= ' ' | ||
| 17167 | && (!it->multibyte_p || it->char_to_display < 128)) | ||
| 17168 | { | ||
| 17169 | /* Either unibyte or ASCII. */ | ||
| 17170 | int stretched_p; | ||
| 17171 | |||
| 17172 | it->nglyphs = 1; | ||
| 17173 | |||
| 17174 | pcm = rif->per_char_metric (font, &char2b, | ||
| 17175 | FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display)); | ||
| 17176 | it->ascent = FONT_BASE (font) + boff; | ||
| 17177 | it->descent = FONT_DESCENT (font) - boff; | ||
| 17178 | |||
| 17179 | if (pcm) | ||
| 17180 | { | ||
| 17181 | it->phys_ascent = pcm->ascent + boff; | ||
| 17182 | it->phys_descent = pcm->descent - boff; | ||
| 17183 | it->pixel_width = pcm->width; | ||
| 17184 | } | ||
| 17185 | else | ||
| 17186 | { | ||
| 17187 | it->glyph_not_available_p = 1; | ||
| 17188 | it->phys_ascent = FONT_BASE (font) + boff; | ||
| 17189 | it->phys_descent = FONT_DESCENT (font) - boff; | ||
| 17190 | it->pixel_width = FONT_WIDTH (font); | ||
| 17191 | } | ||
| 17192 | |||
| 17193 | /* If this is a space inside a region of text with | ||
| 17194 | `space-width' property, change its width. */ | ||
| 17195 | stretched_p = it->char_to_display == ' ' && !NILP (it->space_width); | ||
| 17196 | if (stretched_p) | ||
| 17197 | it->pixel_width *= XFLOATINT (it->space_width); | ||
| 17198 | |||
| 17199 | /* If face has a box, add the box thickness to the character | ||
| 17200 | height. If character has a box line to the left and/or | ||
| 17201 | right, add the box line width to the character's width. */ | ||
| 17202 | if (face->box != FACE_NO_BOX) | ||
| 17203 | { | ||
| 17204 | int thick = face->box_line_width; | ||
| 17205 | |||
| 17206 | if (thick > 0) | ||
| 17207 | { | ||
| 17208 | it->ascent += thick; | ||
| 17209 | it->descent += thick; | ||
| 17210 | } | ||
| 17211 | else | ||
| 17212 | thick = -thick; | ||
| 17213 | |||
| 17214 | if (it->start_of_box_run_p) | ||
| 17215 | it->pixel_width += thick; | ||
| 17216 | if (it->end_of_box_run_p) | ||
| 17217 | it->pixel_width += thick; | ||
| 17218 | } | ||
| 17219 | |||
| 17220 | /* If face has an overline, add the height of the overline | ||
| 17221 | (1 pixel) and a 1 pixel margin to the character height. */ | ||
| 17222 | if (face->overline_p) | ||
| 17223 | it->ascent += 2; | ||
| 17224 | |||
| 17225 | take_vertical_position_into_account (it); | ||
| 17226 | |||
| 17227 | /* If we have to actually produce glyphs, do it. */ | ||
| 17228 | if (it->glyph_row) | ||
| 17229 | { | ||
| 17230 | if (stretched_p) | ||
| 17231 | { | ||
| 17232 | /* Translate a space with a `space-width' property | ||
| 17233 | into a stretch glyph. */ | ||
| 17234 | double ascent = (double) FONT_BASE (font) | ||
| 17235 | / FONT_HEIGHT (font); | ||
| 17236 | append_stretch_glyph (it, it->object, it->pixel_width, | ||
| 17237 | it->ascent + it->descent, ascent); | ||
| 17238 | } | ||
| 17239 | else | ||
| 17240 | append_glyph (it); | ||
| 17241 | |||
| 17242 | /* If characters with lbearing or rbearing are displayed | ||
| 17243 | in this line, record that fact in a flag of the | ||
| 17244 | glyph row. This is used to optimize X output code. */ | ||
| 17245 | if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width)) | ||
| 17246 | it->glyph_row->contains_overlapping_glyphs_p = 1; | ||
| 17247 | } | ||
| 17248 | } | ||
| 17249 | else if (it->char_to_display == '\n') | ||
| 17250 | { | ||
| 17251 | /* A newline has no width but we need the height of the line. */ | ||
| 17252 | it->pixel_width = 0; | ||
| 17253 | it->nglyphs = 0; | ||
| 17254 | it->ascent = it->phys_ascent = FONT_BASE (font) + boff; | ||
| 17255 | it->descent = it->phys_descent = FONT_DESCENT (font) - boff; | ||
| 17256 | |||
| 17257 | if (face->box != FACE_NO_BOX | ||
| 17258 | && face->box_line_width > 0) | ||
| 17259 | { | ||
| 17260 | it->ascent += face->box_line_width; | ||
| 17261 | it->descent += face->box_line_width; | ||
| 17262 | } | ||
| 17263 | } | ||
| 17264 | else if (it->char_to_display == '\t') | ||
| 17265 | { | ||
| 17266 | int tab_width = it->tab_width * CANON_X_UNIT (it->f); | ||
| 17267 | int x = it->current_x + it->continuation_lines_width; | ||
| 17268 | int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; | ||
| 17269 | |||
| 17270 | /* If the distance from the current position to the next tab | ||
| 17271 | stop is less than a canonical character width, use the | ||
| 17272 | tab stop after that. */ | ||
| 17273 | if (next_tab_x - x < CANON_X_UNIT (it->f)) | ||
| 17274 | next_tab_x += tab_width; | ||
| 17275 | |||
| 17276 | it->pixel_width = next_tab_x - x; | ||
| 17277 | it->nglyphs = 1; | ||
| 17278 | it->ascent = it->phys_ascent = FONT_BASE (font) + boff; | ||
| 17279 | it->descent = it->phys_descent = FONT_DESCENT (font) - boff; | ||
| 17280 | |||
| 17281 | if (it->glyph_row) | ||
| 17282 | { | ||
| 17283 | double ascent = (double) it->ascent / (it->ascent + it->descent); | ||
| 17284 | append_stretch_glyph (it, it->object, it->pixel_width, | ||
| 17285 | it->ascent + it->descent, ascent); | ||
| 17286 | } | ||
| 17287 | } | ||
| 17288 | else | ||
| 17289 | { | ||
| 17290 | /* A multi-byte character. Assume that the display width of the | ||
| 17291 | character is the width of the character multiplied by the | ||
| 17292 | width of the font. */ | ||
| 17293 | |||
| 17294 | /* If we found a font, this font should give us the right | ||
| 17295 | metrics. If we didn't find a font, use the frame's | ||
| 17296 | default font and calculate the width of the character | ||
| 17297 | from the charset width; this is what old redisplay code | ||
| 17298 | did. */ | ||
| 17299 | |||
| 17300 | pcm = rif->per_char_metric (font, &char2b, | ||
| 17301 | FONT_TYPE_FOR_MULTIBYTE (font, it->c)); | ||
| 17302 | |||
| 17303 | if (font_not_found_p || !pcm) | ||
| 17304 | { | ||
| 17305 | int charset = CHAR_CHARSET (it->char_to_display); | ||
| 17306 | |||
| 17307 | it->glyph_not_available_p = 1; | ||
| 17308 | it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f)) | ||
| 17309 | * CHARSET_WIDTH (charset)); | ||
| 17310 | it->phys_ascent = FONT_BASE (font) + boff; | ||
| 17311 | it->phys_descent = FONT_DESCENT (font) - boff; | ||
| 17312 | } | ||
| 17313 | else | ||
| 17314 | { | ||
| 17315 | it->pixel_width = pcm->width; | ||
| 17316 | it->phys_ascent = pcm->ascent + boff; | ||
| 17317 | it->phys_descent = pcm->descent - boff; | ||
| 17318 | if (it->glyph_row | ||
| 17319 | && (pcm->lbearing < 0 | ||
| 17320 | || pcm->rbearing > pcm->width)) | ||
| 17321 | it->glyph_row->contains_overlapping_glyphs_p = 1; | ||
| 17322 | } | ||
| 17323 | it->nglyphs = 1; | ||
| 17324 | it->ascent = FONT_BASE (font) + boff; | ||
| 17325 | it->descent = FONT_DESCENT (font) - boff; | ||
| 17326 | if (face->box != FACE_NO_BOX) | ||
| 17327 | { | ||
| 17328 | int thick = face->box_line_width; | ||
| 17329 | |||
| 17330 | if (thick > 0) | ||
| 17331 | { | ||
| 17332 | it->ascent += thick; | ||
| 17333 | it->descent += thick; | ||
| 17334 | } | ||
| 17335 | else | ||
| 17336 | thick = - thick; | ||
| 17337 | |||
| 17338 | if (it->start_of_box_run_p) | ||
| 17339 | it->pixel_width += thick; | ||
| 17340 | if (it->end_of_box_run_p) | ||
| 17341 | it->pixel_width += thick; | ||
| 17342 | } | ||
| 17343 | |||
| 17344 | /* If face has an overline, add the height of the overline | ||
| 17345 | (1 pixel) and a 1 pixel margin to the character height. */ | ||
| 17346 | if (face->overline_p) | ||
| 17347 | it->ascent += 2; | ||
| 17348 | |||
| 17349 | take_vertical_position_into_account (it); | ||
| 17350 | |||
| 17351 | if (it->glyph_row) | ||
| 17352 | append_glyph (it); | ||
| 17353 | } | ||
| 17354 | it->multibyte_p = saved_multibyte_p; | ||
| 17355 | } | ||
| 17356 | else if (it->what == IT_COMPOSITION) | ||
| 17357 | { | ||
| 17358 | /* Note: A composition is represented as one glyph in the | ||
| 17359 | glyph matrix. There are no padding glyphs. */ | ||
| 17360 | XChar2b char2b; | ||
| 17361 | XFontStruct *font; | ||
| 17362 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | ||
| 17363 | XCharStruct *pcm; | ||
| 17364 | int font_not_found_p; | ||
| 17365 | struct font_info *font_info; | ||
| 17366 | int boff; /* baseline offset */ | ||
| 17367 | struct composition *cmp = composition_table[it->cmp_id]; | ||
| 17368 | |||
| 17369 | /* Maybe translate single-byte characters to multibyte. */ | ||
| 17370 | it->char_to_display = it->c; | ||
| 17371 | if (unibyte_display_via_language_environment | ||
| 17372 | && SINGLE_BYTE_CHAR_P (it->c) | ||
| 17373 | && (it->c >= 0240 | ||
| 17374 | || (it->c >= 0200 | ||
| 17375 | && !NILP (Vnonascii_translation_table)))) | ||
| 17376 | { | ||
| 17377 | it->char_to_display = unibyte_char_to_multibyte (it->c); | ||
| 17378 | } | ||
| 17379 | |||
| 17380 | /* Get face and font to use. Encode IT->char_to_display. */ | ||
| 17381 | it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display); | ||
| 17382 | face = FACE_FROM_ID (it->f, it->face_id); | ||
| 17383 | get_char_face_and_encoding (it->f, it->char_to_display, it->face_id, | ||
| 17384 | &char2b, it->multibyte_p, 0); | ||
| 17385 | font = face->font; | ||
| 17386 | |||
| 17387 | /* When no suitable font found, use the default font. */ | ||
| 17388 | font_not_found_p = font == NULL; | ||
| 17389 | if (font_not_found_p) | ||
| 17390 | { | ||
| 17391 | font = FRAME_FONT (it->f); | ||
| 17392 | boff = FRAME_BASELINE_OFFSET (it->f); | ||
| 17393 | font_info = NULL; | ||
| 17394 | } | ||
| 17395 | else | ||
| 17396 | { | ||
| 17397 | font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id); | ||
| 17398 | boff = font_info->baseline_offset; | ||
| 17399 | if (font_info->vertical_centering) | ||
| 17400 | boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; | ||
| 17401 | } | ||
| 17402 | |||
| 17403 | /* There are no padding glyphs, so there is only one glyph to | ||
| 17404 | produce for the composition. Important is that pixel_width, | ||
| 17405 | ascent and descent are the values of what is drawn by | ||
| 17406 | draw_glyphs (i.e. the values of the overall glyphs composed). */ | ||
| 17407 | it->nglyphs = 1; | ||
| 17408 | |||
| 17409 | /* If we have not yet calculated pixel size data of glyphs of | ||
| 17410 | the composition for the current face font, calculate them | ||
| 17411 | now. Theoretically, we have to check all fonts for the | ||
| 17412 | glyphs, but that requires much time and memory space. So, | ||
| 17413 | here we check only the font of the first glyph. This leads | ||
| 17414 | to incorrect display very rarely, and C-l (recenter) can | ||
| 17415 | correct the display anyway. */ | ||
| 17416 | if (cmp->font != (void *) font) | ||
| 17417 | { | ||
| 17418 | /* Ascent and descent of the font of the first character of | ||
| 17419 | this composition (adjusted by baseline offset). Ascent | ||
| 17420 | and descent of overall glyphs should not be less than | ||
| 17421 | them respectively. */ | ||
| 17422 | int font_ascent = FONT_BASE (font) + boff; | ||
| 17423 | int font_descent = FONT_DESCENT (font) - boff; | ||
| 17424 | /* Bounding box of the overall glyphs. */ | ||
| 17425 | int leftmost, rightmost, lowest, highest; | ||
| 17426 | int i, width, ascent, descent; | ||
| 17427 | |||
| 17428 | cmp->font = (void *) font; | ||
| 17429 | |||
| 17430 | /* Initialize the bounding box. */ | ||
| 17431 | if (font_info | ||
| 17432 | && (pcm = rif->per_char_metric (font, &char2b, | ||
| 17433 | FONT_TYPE_FOR_MULTIBYTE (font, it->c)))) | ||
| 17434 | { | ||
| 17435 | width = pcm->width; | ||
| 17436 | ascent = pcm->ascent; | ||
| 17437 | descent = pcm->descent; | ||
| 17438 | } | ||
| 17439 | else | ||
| 17440 | { | ||
| 17441 | width = FONT_WIDTH (font); | ||
| 17442 | ascent = FONT_BASE (font); | ||
| 17443 | descent = FONT_DESCENT (font); | ||
| 17444 | } | ||
| 17445 | |||
| 17446 | rightmost = width; | ||
| 17447 | lowest = - descent + boff; | ||
| 17448 | highest = ascent + boff; | ||
| 17449 | leftmost = 0; | ||
| 17450 | |||
| 17451 | if (font_info | ||
| 17452 | && font_info->default_ascent | ||
| 17453 | && CHAR_TABLE_P (Vuse_default_ascent) | ||
| 17454 | && !NILP (Faref (Vuse_default_ascent, | ||
| 17455 | make_number (it->char_to_display)))) | ||
| 17456 | highest = font_info->default_ascent + boff; | ||
| 17457 | |||
| 17458 | /* Draw the first glyph at the normal position. It may be | ||
| 17459 | shifted to right later if some other glyphs are drawn at | ||
| 17460 | the left. */ | ||
| 17461 | cmp->offsets[0] = 0; | ||
| 17462 | cmp->offsets[1] = boff; | ||
| 17463 | |||
| 17464 | /* Set cmp->offsets for the remaining glyphs. */ | ||
| 17465 | for (i = 1; i < cmp->glyph_len; i++) | ||
| 17466 | { | ||
| 17467 | int left, right, btm, top; | ||
| 17468 | int ch = COMPOSITION_GLYPH (cmp, i); | ||
| 17469 | int face_id = FACE_FOR_CHAR (it->f, face, ch); | ||
| 17470 | |||
| 17471 | face = FACE_FROM_ID (it->f, face_id); | ||
| 17472 | get_char_face_and_encoding (it->f, ch, face->id, | ||
| 17473 | &char2b, it->multibyte_p, 0); | ||
| 17474 | font = face->font; | ||
| 17475 | if (font == NULL) | ||
| 17476 | { | ||
| 17477 | font = FRAME_FONT (it->f); | ||
| 17478 | boff = it->f->output_data.x->baseline_offset; | ||
| 17479 | font_info = NULL; | ||
| 17480 | } | ||
| 17481 | else | ||
| 17482 | { | ||
| 17483 | font_info | ||
| 17484 | = FONT_INFO_FROM_ID (it->f, face->font_info_id); | ||
| 17485 | boff = font_info->baseline_offset; | ||
| 17486 | if (font_info->vertical_centering) | ||
| 17487 | boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; | ||
| 17488 | } | ||
| 17489 | |||
| 17490 | if (font_info | ||
| 17491 | && (pcm = rif->per_char_metric (font, &char2b, | ||
| 17492 | FONT_TYPE_FOR_MULTIBYTE (font, ch)))) | ||
| 17493 | { | ||
| 17494 | width = pcm->width; | ||
| 17495 | ascent = pcm->ascent; | ||
| 17496 | descent = pcm->descent; | ||
| 17497 | } | ||
| 17498 | else | ||
| 17499 | { | ||
| 17500 | width = FONT_WIDTH (font); | ||
| 17501 | ascent = 1; | ||
| 17502 | descent = 0; | ||
| 17503 | } | ||
| 17504 | |||
| 17505 | if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS) | ||
| 17506 | { | ||
| 17507 | /* Relative composition with or without | ||
| 17508 | alternate chars. */ | ||
| 17509 | left = (leftmost + rightmost - width) / 2; | ||
| 17510 | btm = - descent + boff; | ||
| 17511 | if (font_info && font_info->relative_compose | ||
| 17512 | && (! CHAR_TABLE_P (Vignore_relative_composition) | ||
| 17513 | || NILP (Faref (Vignore_relative_composition, | ||
| 17514 | make_number (ch))))) | ||
| 17515 | { | ||
| 17516 | |||
| 17517 | if (- descent >= font_info->relative_compose) | ||
| 17518 | /* One extra pixel between two glyphs. */ | ||
| 17519 | btm = highest + 1; | ||
| 17520 | else if (ascent <= 0) | ||
| 17521 | /* One extra pixel between two glyphs. */ | ||
| 17522 | btm = lowest - 1 - ascent - descent; | ||
| 17523 | } | ||
| 17524 | } | ||
| 17525 | else | ||
| 17526 | { | ||
| 17527 | /* A composition rule is specified by an integer | ||
| 17528 | value that encodes global and new reference | ||
| 17529 | points (GREF and NREF). GREF and NREF are | ||
| 17530 | specified by numbers as below: | ||
| 17531 | |||
| 17532 | 0---1---2 -- ascent | ||
| 17533 | | | | ||
| 17534 | | | | ||
| 17535 | | | | ||
| 17536 | 9--10--11 -- center | ||
| 17537 | | | | ||
| 17538 | ---3---4---5--- baseline | ||
| 17539 | | | | ||
| 17540 | 6---7---8 -- descent | ||
| 17541 | */ | ||
| 17542 | int rule = COMPOSITION_RULE (cmp, i); | ||
| 17543 | int gref, nref, grefx, grefy, nrefx, nrefy; | ||
| 17544 | |||
| 17545 | COMPOSITION_DECODE_RULE (rule, gref, nref); | ||
| 17546 | grefx = gref % 3, nrefx = nref % 3; | ||
| 17547 | grefy = gref / 3, nrefy = nref / 3; | ||
| 17548 | |||
| 17549 | left = (leftmost | ||
| 17550 | + grefx * (rightmost - leftmost) / 2 | ||
| 17551 | - nrefx * width / 2); | ||
| 17552 | btm = ((grefy == 0 ? highest | ||
| 17553 | : grefy == 1 ? 0 | ||
| 17554 | : grefy == 2 ? lowest | ||
| 17555 | : (highest + lowest) / 2) | ||
| 17556 | - (nrefy == 0 ? ascent + descent | ||
| 17557 | : nrefy == 1 ? descent - boff | ||
| 17558 | : nrefy == 2 ? 0 | ||
| 17559 | : (ascent + descent) / 2)); | ||
| 17560 | } | ||
| 17561 | |||
| 17562 | cmp->offsets[i * 2] = left; | ||
| 17563 | cmp->offsets[i * 2 + 1] = btm + descent; | ||
| 17564 | |||
| 17565 | /* Update the bounding box of the overall glyphs. */ | ||
| 17566 | right = left + width; | ||
| 17567 | top = btm + descent + ascent; | ||
| 17568 | if (left < leftmost) | ||
| 17569 | leftmost = left; | ||
| 17570 | if (right > rightmost) | ||
| 17571 | rightmost = right; | ||
| 17572 | if (top > highest) | ||
| 17573 | highest = top; | ||
| 17574 | if (btm < lowest) | ||
| 17575 | lowest = btm; | ||
| 17576 | } | ||
| 17577 | |||
| 17578 | /* If there are glyphs whose x-offsets are negative, | ||
| 17579 | shift all glyphs to the right and make all x-offsets | ||
| 17580 | non-negative. */ | ||
| 17581 | if (leftmost < 0) | ||
| 17582 | { | ||
| 17583 | for (i = 0; i < cmp->glyph_len; i++) | ||
| 17584 | cmp->offsets[i * 2] -= leftmost; | ||
| 17585 | rightmost -= leftmost; | ||
| 17586 | } | ||
| 17587 | |||
| 17588 | cmp->pixel_width = rightmost; | ||
| 17589 | cmp->ascent = highest; | ||
| 17590 | cmp->descent = - lowest; | ||
| 17591 | if (cmp->ascent < font_ascent) | ||
| 17592 | cmp->ascent = font_ascent; | ||
| 17593 | if (cmp->descent < font_descent) | ||
| 17594 | cmp->descent = font_descent; | ||
| 17595 | } | ||
| 17596 | |||
| 17597 | it->pixel_width = cmp->pixel_width; | ||
| 17598 | it->ascent = it->phys_ascent = cmp->ascent; | ||
| 17599 | it->descent = it->phys_descent = cmp->descent; | ||
| 17600 | |||
| 17601 | if (face->box != FACE_NO_BOX) | ||
| 17602 | { | ||
| 17603 | int thick = face->box_line_width; | ||
| 17604 | |||
| 17605 | if (thick > 0) | ||
| 17606 | { | ||
| 17607 | it->ascent += thick; | ||
| 17608 | it->descent += thick; | ||
| 17609 | } | ||
| 17610 | else | ||
| 17611 | thick = - thick; | ||
| 17612 | |||
| 17613 | if (it->start_of_box_run_p) | ||
| 17614 | it->pixel_width += thick; | ||
| 17615 | if (it->end_of_box_run_p) | ||
| 17616 | it->pixel_width += thick; | ||
| 17617 | } | ||
| 17618 | |||
| 17619 | /* If face has an overline, add the height of the overline | ||
| 17620 | (1 pixel) and a 1 pixel margin to the character height. */ | ||
| 17621 | if (face->overline_p) | ||
| 17622 | it->ascent += 2; | ||
| 17623 | |||
| 17624 | take_vertical_position_into_account (it); | ||
| 17625 | |||
| 17626 | if (it->glyph_row) | ||
| 17627 | append_composite_glyph (it); | ||
| 17628 | } | ||
| 17629 | else if (it->what == IT_IMAGE) | ||
| 17630 | produce_image_glyph (it); | ||
| 17631 | else if (it->what == IT_STRETCH) | ||
| 17632 | produce_stretch_glyph (it); | ||
| 17633 | |||
| 17634 | /* Accumulate dimensions. Note: can't assume that it->descent > 0 | ||
| 17635 | because this isn't true for images with `:ascent 100'. */ | ||
| 17636 | xassert (it->ascent >= 0 && it->descent >= 0); | ||
| 17637 | if (it->area == TEXT_AREA) | ||
| 17638 | it->current_x += it->pixel_width; | ||
| 17639 | |||
| 17640 | it->descent += it->extra_line_spacing; | ||
| 17641 | |||
| 17642 | it->max_ascent = max (it->max_ascent, it->ascent); | ||
| 17643 | it->max_descent = max (it->max_descent, it->descent); | ||
| 17644 | it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent); | ||
| 17645 | it->max_phys_descent = max (it->max_phys_descent, it->phys_descent); | ||
| 17646 | } | ||
| 17647 | |||
| 17648 | |||
| 17649 | |||
| 17650 | |||
| 17651 | |||
| 17652 | |||
| 17653 | /*********************************************************************** | ||
| 15663 | Cursor types | 17654 | Cursor types |
| 15664 | ***********************************************************************/ | 17655 | ***********************************************************************/ |
| 15665 | 17656 | ||
| @@ -15857,6 +17848,63 @@ get_window_cursor_type (w, width, active_cursor) | |||
| 15857 | return NO_CURSOR; | 17848 | return NO_CURSOR; |
| 15858 | } | 17849 | } |
| 15859 | 17850 | ||
| 17851 | |||
| 17852 | /* Notice when the text cursor of window W has been completely | ||
| 17853 | overwritten by a drawing operation that outputs glyphs in AREA | ||
| 17854 | starting at X0 and ending at X1 in the line starting at Y0 and | ||
| 17855 | ending at Y1. X coordinates are area-relative. X1 < 0 means all | ||
| 17856 | the rest of the line after X0 has been written. Y coordinates | ||
| 17857 | are window-relative. */ | ||
| 17858 | |||
| 17859 | void | ||
| 17860 | notice_overwritten_cursor (w, area, x0, x1, y0, y1) | ||
| 17861 | struct window *w; | ||
| 17862 | enum glyph_row_area area; | ||
| 17863 | int x0, y0, x1, y1; | ||
| 17864 | { | ||
| 17865 | #ifdef HAVE_CARBON | ||
| 17866 | /* ++KFS: Why is there a special version of this for the mac ? */ | ||
| 17867 | if (area == TEXT_AREA | ||
| 17868 | && w->phys_cursor_on_p | ||
| 17869 | && y0 <= w->phys_cursor.y | ||
| 17870 | && y1 >= w->phys_cursor.y + w->phys_cursor_height | ||
| 17871 | && x0 <= w->phys_cursor.x | ||
| 17872 | && (x1 < 0 || x1 > w->phys_cursor.x)) | ||
| 17873 | w->phys_cursor_on_p = 0; | ||
| 17874 | #else | ||
| 17875 | if (area == TEXT_AREA && w->phys_cursor_on_p) | ||
| 17876 | { | ||
| 17877 | int cx0 = w->phys_cursor.x; | ||
| 17878 | int cx1 = cx0 + w->phys_cursor_width; | ||
| 17879 | int cy0 = w->phys_cursor.y; | ||
| 17880 | int cy1 = cy0 + w->phys_cursor_height; | ||
| 17881 | |||
| 17882 | if (x0 <= cx0 && (x1 < 0 || x1 >= cx1)) | ||
| 17883 | { | ||
| 17884 | /* The cursor image will be completely removed from the | ||
| 17885 | screen if the output area intersects the cursor area in | ||
| 17886 | y-direction. When we draw in [y0 y1[, and some part of | ||
| 17887 | the cursor is at y < y0, that part must have been drawn | ||
| 17888 | before. When scrolling, the cursor is erased before | ||
| 17889 | actually scrolling, so we don't come here. When not | ||
| 17890 | scrolling, the rows above the old cursor row must have | ||
| 17891 | changed, and in this case these rows must have written | ||
| 17892 | over the cursor image. | ||
| 17893 | |||
| 17894 | Likewise if part of the cursor is below y1, with the | ||
| 17895 | exception of the cursor being in the first blank row at | ||
| 17896 | the buffer and window end because update_text_area | ||
| 17897 | doesn't draw that row. (Except when it does, but | ||
| 17898 | that's handled in update_text_area.) */ | ||
| 17899 | |||
| 17900 | if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1)) | ||
| 17901 | && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p) | ||
| 17902 | w->phys_cursor_on_p = 0; | ||
| 17903 | } | ||
| 17904 | } | ||
| 17905 | #endif | ||
| 17906 | } | ||
| 17907 | |||
| 15860 | 17908 | ||
| 15861 | /*********************************************************************** | 17909 | /*********************************************************************** |
| 15862 | Initialization | 17910 | Initialization |