diff options
| author | Karl Heuer | 1997-02-20 06:59:25 +0000 |
|---|---|---|
| committer | Karl Heuer | 1997-02-20 06:59:25 +0000 |
| commit | dc43ef945f98a6d5f90aa9e09ddd9d724f187856 (patch) | |
| tree | 151c664f2fc55364a6ae0c3c94705947e02d1648 /src | |
| parent | e6c7c98823ac95f36ca0c83653a8e33a88cc604e (diff) | |
| download | emacs-dc43ef945f98a6d5f90aa9e09ddd9d724f187856.tar.gz emacs-dc43ef945f98a6d5f90aa9e09ddd9d724f187856.zip | |
Include charset.h, ccl.h, and fontset.h.
(PER_CHAR_METRIC): New macro.
(dumpglyphs): New argument CMPCHARP. Handle multibyte characters.
(XTwrite_glyphs, redraw_previous_char, redraw_following_char):
Supply argument CMPCHARP to dumpglyphs.
(dumprectangle): Display whole glyph of wide-column characters.
Supply argument CMPCHARP to dumpglyphs.
(show_mouse_face): Supply argument CMPCHARP to dumpglyphs.
(x_draw_box): Pay attention to wide-column characters.
(x_draw_single_glyph): Supply argument CMPCHARP to dumpglyphs.
(x_new_font): Call fs_load_font for actual font loading work.
(x_new_fontset): New function.
(x_get_font_info, x_list_fonts, x_load_font, x_query_font): New
functions providing API to fontset handler.
(x_term_init): Initialize several new members of struct x_display_info.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 940 |
1 files changed, 733 insertions, 207 deletions
diff --git a/src/xterm.c b/src/xterm.c index 279906e2307..6bd821c1011 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -68,6 +68,9 @@ Boston, MA 02111-1307, USA. */ | |||
| 68 | /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */ | 68 | /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */ |
| 69 | /* #include <sys/param.h> */ | 69 | /* #include <sys/param.h> */ |
| 70 | 70 | ||
| 71 | #include "charset.h" | ||
| 72 | #include "ccl.h" | ||
| 73 | #include "fontset.h" | ||
| 71 | #include "frame.h" | 74 | #include "frame.h" |
| 72 | #include "dispextern.h" | 75 | #include "dispextern.h" |
| 73 | #include "termhooks.h" | 76 | #include "termhooks.h" |
| @@ -490,6 +493,19 @@ XTcursor_to (row, col) | |||
| 490 | } | 493 | } |
| 491 | } | 494 | } |
| 492 | 495 | ||
| 496 | |||
| 497 | /* Return a pointer to per char metric information in FONT of a | ||
| 498 | character pointed by B (*XChar2b). */ | ||
| 499 | |||
| 500 | #define PER_CHAR_METRIC(font, b) \ | ||
| 501 | ((font)->per_char \ | ||
| 502 | ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \ | ||
| 503 | + (((font)->min_byte1 || (font)->max_byte1) \ | ||
| 504 | ? (((b)->byte1 - (font)->min_byte1) \ | ||
| 505 | * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \ | ||
| 506 | : 0)) \ | ||
| 507 | : &((font)->max_bounds)) | ||
| 508 | |||
| 493 | /* Display a sequence of N glyphs found at GP. | 509 | /* Display a sequence of N glyphs found at GP. |
| 494 | WINDOW is the x-window to output to. LEFT and TOP are starting coords. | 510 | WINDOW is the x-window to output to. LEFT and TOP are starting coords. |
| 495 | HL is 1 if this text is highlighted, 2 if the cursor is on it, | 511 | HL is 1 if this text is highlighted, 2 if the cursor is on it, |
| @@ -497,6 +513,11 @@ XTcursor_to (row, col) | |||
| 497 | JUST_FOREGROUND if 1 means draw only the foreground; | 513 | JUST_FOREGROUND if 1 means draw only the foreground; |
| 498 | don't alter the background. | 514 | don't alter the background. |
| 499 | 515 | ||
| 516 | CMPCHARP if non NULL is a pointer to the struct cmpchar_info, which | ||
| 517 | means drawing glyphs on the same column. This is set to non NULL | ||
| 518 | only when recursively called within dumpglyphs to draw a composite | ||
| 519 | character specified by CMPCHAR. | ||
| 520 | |||
| 500 | FONT is the default font to use (for glyphs whose font-code is 0). | 521 | FONT is the default font to use (for glyphs whose font-code is 0). |
| 501 | 522 | ||
| 502 | Since the display generation code is responsible for calling | 523 | Since the display generation code is responsible for calling |
| @@ -504,62 +525,122 @@ XTcursor_to (row, col) | |||
| 504 | the display structure, we can assume that the face code on each | 525 | the display structure, we can assume that the face code on each |
| 505 | glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one | 526 | glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one |
| 506 | to which we can actually apply intern_face. | 527 | to which we can actually apply intern_face. |
| 507 | Call this function with input blocked. */ | 528 | Call this function with input blocked. |
| 529 | |||
| 530 | Return overall pixel width of the drawn glyphs. */ | ||
| 508 | 531 | ||
| 509 | #if 1 | 532 | #if 1 |
| 510 | /* This is the multi-face code. */ | 533 | /* This is the multi-face code. */ |
| 511 | 534 | ||
| 512 | static void | 535 | static int |
| 513 | dumpglyphs (f, left, top, gp, n, hl, just_foreground) | 536 | dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp) |
| 514 | struct frame *f; | 537 | struct frame *f; |
| 515 | int left, top; | 538 | int left, top; |
| 516 | register GLYPH *gp; /* Points to first GLYPH. */ | 539 | register GLYPH *gp; /* Points to first GLYPH. */ |
| 517 | register int n; /* Number of glyphs to display. */ | 540 | register int n; /* Number of glyphs to display. */ |
| 518 | int hl; | 541 | int hl; |
| 519 | int just_foreground; | 542 | int just_foreground; |
| 543 | struct cmpchar_info *cmpcharp; | ||
| 520 | { | 544 | { |
| 521 | /* Holds characters to be displayed. */ | 545 | /* Holds characters to be displayed. */ |
| 522 | char *buf = (char *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*buf)); | 546 | XChar2b *buf = (XChar2b *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*buf)); |
| 523 | register char *cp; /* Steps through buf[]. */ | 547 | register XChar2b *cp; /* Steps through buf[]. */ |
| 524 | register int tlen = GLYPH_TABLE_LENGTH; | 548 | register int tlen = GLYPH_TABLE_LENGTH; |
| 525 | register Lisp_Object *tbase = GLYPH_TABLE_BASE; | 549 | register Lisp_Object *tbase = GLYPH_TABLE_BASE; |
| 526 | Window window = FRAME_X_WINDOW (f); | 550 | Window window = FRAME_X_WINDOW (f); |
| 527 | int orig_left = left; | 551 | int orig_left = left; |
| 552 | int gidx = 0; | ||
| 553 | int pixel_width; | ||
| 528 | 554 | ||
| 529 | while (n > 0) | 555 | while (n > 0) |
| 530 | { | 556 | { |
| 531 | /* Get the face-code of the next GLYPH. */ | 557 | /* Get the face-code of the next GLYPH. */ |
| 532 | int cf, len; | 558 | int cf, len; |
| 533 | GLYPH g = *gp; | 559 | GLYPH g = *gp; |
| 560 | int ch, charset; | ||
| 561 | /* HIGHEST and LOWEST are used while drawing a composite | ||
| 562 | character. The meanings are described later. */ | ||
| 563 | int highest, lowest; | ||
| 534 | 564 | ||
| 535 | GLYPH_FOLLOW_ALIASES (tbase, tlen, g); | 565 | GLYPH_FOLLOW_ALIASES (tbase, tlen, g); |
| 536 | cf = FAST_GLYPH_FACE (g); | 566 | cf = (cmpcharp ? cmpcharp->face_work : FAST_GLYPH_FACE (g)); |
| 567 | ch = FAST_GLYPH_CHAR (g); | ||
| 568 | charset = CHAR_CHARSET (ch); | ||
| 569 | if (charset == CHARSET_COMPOSITION) | ||
| 570 | { | ||
| 571 | /* We must draw components of the composite character on the | ||
| 572 | same column. */ | ||
| 573 | cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (ch)]; | ||
| 574 | |||
| 575 | /* Set the face in the slot for work. */ | ||
| 576 | cmpcharp->face_work = cf; | ||
| 577 | |||
| 578 | /* We don't need the return value ... */ | ||
| 579 | dumpglyphs (f, left, top, cmpcharp->glyph, cmpcharp->glyph_len, | ||
| 580 | hl, just_foreground, cmpcharp); | ||
| 581 | /* ... because the width of just drawn text can be | ||
| 582 | calculated as follows. */ | ||
| 583 | left += FONT_WIDTH (f->output_data.x->font) * cmpcharp->width; | ||
| 584 | |||
| 585 | ++gp, --n; | ||
| 586 | while (gp && (*gp & GLYPH_MASK_PADDING)) ++gp, --n; | ||
| 587 | cmpcharp = NULL; | ||
| 588 | continue; | ||
| 589 | } | ||
| 537 | 590 | ||
| 538 | /* Find the run of consecutive glyphs with the same face-code. | 591 | /* Find the run of consecutive glyphs which can be drawn with |
| 539 | Extract their character codes into BUF. */ | 592 | the same GC (i.e. the same charset and the same face-code). |
| 593 | Extract their character codes into BUF. | ||
| 594 | If CMPCHARP is not NULL, face-code is not checked because we | ||
| 595 | use only the face specified in `cmpcharp->face_work'. */ | ||
| 540 | cp = buf; | 596 | cp = buf; |
| 541 | while (n > 0) | 597 | while (n > 0) |
| 542 | { | 598 | { |
| 599 | int this_charset, c1, c2; | ||
| 600 | |||
| 543 | g = *gp; | 601 | g = *gp; |
| 544 | GLYPH_FOLLOW_ALIASES (tbase, tlen, g); | 602 | GLYPH_FOLLOW_ALIASES (tbase, tlen, g); |
| 545 | if (FAST_GLYPH_FACE (g) != cf) | 603 | ch = FAST_GLYPH_CHAR (g); |
| 604 | SPLIT_CHAR (ch, this_charset, c1, c2); | ||
| 605 | if (this_charset != charset | ||
| 606 | || (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf)) | ||
| 546 | break; | 607 | break; |
| 547 | 608 | ||
| 548 | *cp++ = FAST_GLYPH_CHAR (g); | 609 | if (c2) |
| 549 | --n; | 610 | cp->byte1 = c1, cp->byte2 = c2; |
| 550 | ++gp; | 611 | else |
| 612 | cp->byte1 = 0, cp->byte2 = c1; | ||
| 613 | ++cp; | ||
| 614 | ++gp, --n; | ||
| 615 | while (gp && (*gp & GLYPH_MASK_PADDING)) | ||
| 616 | ++gp, --n; | ||
| 551 | } | 617 | } |
| 552 | 618 | ||
| 553 | /* LEN gets the length of the run. */ | 619 | /* LEN gets the length of the run. */ |
| 554 | len = cp - buf; | 620 | len = cp - buf; |
| 621 | /* PIXEL_WIDTH get the pixcel width of the run. */ | ||
| 622 | pixel_width | ||
| 623 | = (FONT_WIDTH (f->output_data.x->font) | ||
| 624 | * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset))); | ||
| 555 | 625 | ||
| 556 | /* Now output this run of chars, with the font and pixel values | 626 | /* Now output this run of chars, with the font and pixel values |
| 557 | determined by the face code CF. */ | 627 | determined by the face code CF. */ |
| 558 | { | 628 | { |
| 559 | struct face *face = FRAME_DEFAULT_FACE (f); | 629 | struct face *face = FRAME_DEFAULT_FACE (f); |
| 560 | XFontStruct *font = FACE_FONT (face); | 630 | XFontStruct *font = NULL; |
| 561 | GC gc = FACE_GC (face); | 631 | GC gc; |
| 562 | int stippled = 0; | 632 | int stippled = 0; |
| 633 | /* A flag to tell if we have already filled background. We | ||
| 634 | fill background in advance in the following cases: | ||
| 635 | 1) A face has stipple. | ||
| 636 | 2) A height of font is different from that of the current line. | ||
| 637 | 3) Drawing a composite character. | ||
| 638 | After filling background, we draw glyphs by XDrawString16. */ | ||
| 639 | int background_filled; | ||
| 640 | /* Baseline position of a character, offset from TOP. */ | ||
| 641 | int baseline; | ||
| 642 | /* The property value of `_MULE_RELATIVE_COMPOSE'. */ | ||
| 643 | int relative_compose = 0; | ||
| 563 | 644 | ||
| 564 | /* HL = 3 means use a mouse face previously chosen. */ | 645 | /* HL = 3 means use a mouse face previously chosen. */ |
| 565 | if (hl == 3) | 646 | if (hl == 3) |
| @@ -578,8 +659,6 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) | |||
| 578 | face = FRAME_MODE_LINE_FACE (f); | 659 | face = FRAME_MODE_LINE_FACE (f); |
| 579 | else | 660 | else |
| 580 | face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]); | 661 | face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]); |
| 581 | font = FACE_FONT (face); | ||
| 582 | gc = FACE_GC (face); | ||
| 583 | if (FACE_STIPPLE (face)) | 662 | if (FACE_STIPPLE (face)) |
| 584 | stippled = 1; | 663 | stippled = 1; |
| 585 | } | 664 | } |
| @@ -590,12 +669,78 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) | |||
| 590 | else if (hl == 1) | 669 | else if (hl == 1) |
| 591 | { | 670 | { |
| 592 | face = FRAME_MODE_LINE_FACE (f); | 671 | face = FRAME_MODE_LINE_FACE (f); |
| 593 | font = FACE_FONT (face); | ||
| 594 | gc = FACE_GC (face); | ||
| 595 | if (FACE_STIPPLE (face)) | 672 | if (FACE_STIPPLE (face)) |
| 596 | stippled = 1; | 673 | stippled = 1; |
| 597 | } | 674 | } |
| 598 | 675 | ||
| 676 | /* Setting appropriate font and gc for this charset. */ | ||
| 677 | if (charset != CHARSET_ASCII) | ||
| 678 | { | ||
| 679 | int font_id; | ||
| 680 | int fontset = FACE_FONTSET (face); | ||
| 681 | struct font_info *fontp; | ||
| 682 | |||
| 683 | if ((fontset < 0 && (fontset = FRAME_FONTSET (f)) < 0) | ||
| 684 | || !(fontp = fs_load_font (f, FRAME_X_FONT_TABLE (f), | ||
| 685 | charset, NULL, fontset))) | ||
| 686 | goto font_not_found; | ||
| 687 | |||
| 688 | font = (XFontStruct *) (fontp->font); | ||
| 689 | gc = FACE_NON_ASCII_GC (face); | ||
| 690 | XSetFont (FRAME_X_DISPLAY (f), gc, font->fid); | ||
| 691 | if (font->max_byte1 != 0) | ||
| 692 | baseline = (f->output_data.x->line_height | ||
| 693 | + font->ascent - font->descent) / 2; | ||
| 694 | else | ||
| 695 | baseline = (f->output_data.x->font_baseline | ||
| 696 | - fontp->baseline_offset); | ||
| 697 | if (cmpcharp && cmpcharp->cmp_rule == NULL) | ||
| 698 | relative_compose = fontp->relative_compose; | ||
| 699 | |||
| 700 | /* We have to change code points in the following cases. */ | ||
| 701 | if (fontp->font_encoder) | ||
| 702 | { | ||
| 703 | /* This font requires CCL program to calculate code | ||
| 704 | point of characters. */ | ||
| 705 | struct ccl_program *ccl = fontp->font_encoder; | ||
| 706 | |||
| 707 | if (CHARSET_DIMENSION (charset) == 1) | ||
| 708 | for (cp = buf; cp < buf + len; cp++) | ||
| 709 | { | ||
| 710 | ccl->reg[0] = charset; | ||
| 711 | ccl->reg[1] = cp->byte2; | ||
| 712 | ccl_driver (ccl, NULL, NULL, 0, 0, NULL); | ||
| 713 | cp->byte2 = ccl->reg[1]; | ||
| 714 | } | ||
| 715 | else | ||
| 716 | for (cp = buf; cp < buf + len; cp++) | ||
| 717 | { | ||
| 718 | ccl->reg[0] = charset; | ||
| 719 | ccl->reg[1] = cp->byte1, ccl->reg[2] = cp->byte2; | ||
| 720 | ccl_driver (ccl, NULL, NULL, 0, 0, NULL); | ||
| 721 | cp->byte1 = ccl->reg[1], cp->byte2 = ccl->reg[2]; | ||
| 722 | } | ||
| 723 | } | ||
| 724 | else if (fontp->encoding[charset]) | ||
| 725 | { | ||
| 726 | int enc = fontp->encoding[charset]; | ||
| 727 | |||
| 728 | if ((enc == 1 || enc == 2) && CHARSET_DIMENSION (charset) == 2) | ||
| 729 | for (cp = buf; cp < buf + len; cp++) | ||
| 730 | cp->byte1 |= 0x80; | ||
| 731 | if (enc == 1 || enc == 3) | ||
| 732 | for (cp = buf; cp < buf + len; cp++) | ||
| 733 | cp->byte2 |= 0x80; | ||
| 734 | } | ||
| 735 | } | ||
| 736 | else | ||
| 737 | { | ||
| 738 | font = FACE_FONT (face); | ||
| 739 | baseline = FONT_BASE (font); | ||
| 740 | font_not_found: | ||
| 741 | gc = FACE_GC (face); | ||
| 742 | } | ||
| 743 | |||
| 599 | #define FACE_DEFAULT (~0) | 744 | #define FACE_DEFAULT (~0) |
| 600 | 745 | ||
| 601 | /* Now override that if the cursor's on this character. */ | 746 | /* Now override that if the cursor's on this character. */ |
| @@ -604,9 +749,10 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) | |||
| 604 | /* The cursor overrides stippling. */ | 749 | /* The cursor overrides stippling. */ |
| 605 | stippled = 0; | 750 | stippled = 0; |
| 606 | 751 | ||
| 607 | if ((!face->font | 752 | if (!cmpcharp |
| 608 | || face->font == (XFontStruct *) FACE_DEFAULT | 753 | && (!font |
| 609 | || face->font == f->output_data.x->font) | 754 | || font == (XFontStruct *) FACE_DEFAULT |
| 755 | || font == f->output_data.x->font) | ||
| 610 | && face->background == f->output_data.x->background_pixel | 756 | && face->background == f->output_data.x->background_pixel |
| 611 | && face->foreground == f->output_data.x->foreground_pixel) | 757 | && face->foreground == f->output_data.x->foreground_pixel) |
| 612 | { | 758 | { |
| @@ -635,7 +781,10 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) | |||
| 635 | xgcv.background = face->foreground; | 781 | xgcv.background = face->foreground; |
| 636 | xgcv.foreground = face->background; | 782 | xgcv.foreground = face->background; |
| 637 | } | 783 | } |
| 638 | xgcv.font = face->font->fid; | 784 | if (font) |
| 785 | xgcv.font = font->fid; | ||
| 786 | else | ||
| 787 | xgcv.font = FACE_FONT (face)->fid; | ||
| 639 | xgcv.graphics_exposures = 0; | 788 | xgcv.graphics_exposures = 0; |
| 640 | mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; | 789 | mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; |
| 641 | if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc) | 790 | if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc) |
| @@ -658,35 +807,130 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) | |||
| 658 | if (font == (XFontStruct *) FACE_DEFAULT) | 807 | if (font == (XFontStruct *) FACE_DEFAULT) |
| 659 | font = f->output_data.x->font; | 808 | font = f->output_data.x->font; |
| 660 | 809 | ||
| 661 | if (just_foreground) | 810 | if (font && (just_foreground || (cmpcharp && gidx > 0))) |
| 662 | XDrawString (FRAME_X_DISPLAY (f), window, gc, | 811 | background_filled = 1; |
| 663 | left, top + FONT_BASE (font), buf, len); | 812 | else if (!font |
| 813 | || stippled | ||
| 814 | || f->output_data.x->line_height != FONT_HEIGHT (font) | ||
| 815 | || cmpcharp) | ||
| 816 | { | ||
| 817 | if (!stippled) | ||
| 818 | /* This is to fill a rectangle with background color. */ | ||
| 819 | XSetStipple (FRAME_X_DISPLAY (f), gc, | ||
| 820 | FRAME_X_DISPLAY_INFO (f)->null_pixel); | ||
| 821 | /* Turn stipple on. */ | ||
| 822 | XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled); | ||
| 823 | |||
| 824 | /* Draw stipple or background color on background. */ | ||
| 825 | XFillRectangle (FRAME_X_DISPLAY (f), window, gc, | ||
| 826 | left, top, pixel_width, | ||
| 827 | f->output_data.x->line_height); | ||
| 828 | |||
| 829 | /* Turn stipple off. */ | ||
| 830 | XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid); | ||
| 831 | |||
| 832 | background_filled = 1; | ||
| 833 | if (cmpcharp) | ||
| 834 | /* To assure not to fill background while drawing | ||
| 835 | remaining components. */ | ||
| 836 | just_foreground = 1; | ||
| 837 | } | ||
| 664 | else | 838 | else |
| 839 | background_filled = 0; | ||
| 840 | |||
| 841 | if (font) | ||
| 665 | { | 842 | { |
| 666 | if (stippled) | 843 | if (cmpcharp) |
| 667 | { | 844 | { |
| 668 | /* Turn stipple on. */ | 845 | XCharStruct *pcm; /* Pointer to per char metric info. */ |
| 669 | XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled); | 846 | int i; |
| 670 | 847 | ||
| 671 | /* Draw stipple on background. */ | 848 | if ((cmpcharp->cmp_rule || relative_compose) |
| 672 | XFillRectangle (FRAME_X_DISPLAY (f), window, gc, | 849 | && gidx == 0) |
| 673 | left, top, | 850 | { |
| 674 | FONT_WIDTH (font) * len, | 851 | /* This is the first character. Initialize variables. |
| 675 | FONT_HEIGHT (font)); | 852 | HIGHEST is the highest position of glyphs ever |
| 853 | written, LOWEST the lowest position. */ | ||
| 854 | int x_offset = 0; | ||
| 855 | |||
| 856 | pcm = PER_CHAR_METRIC (font, buf); | ||
| 857 | highest = pcm->ascent + 1; | ||
| 858 | lowest = - pcm->descent; | ||
| 859 | |||
| 860 | if (cmpcharp->cmp_rule) | ||
| 861 | x_offset = (cmpcharp->col_offset[0] | ||
| 862 | * FONT_WIDTH (f->output_data.x->font)); | ||
| 863 | /* Draw the first character at the normal position. */ | ||
| 864 | XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | ||
| 865 | left + x_offset, top + baseline, buf, 1); | ||
| 866 | i = 1; | ||
| 867 | gidx++; | ||
| 868 | } | ||
| 869 | else | ||
| 870 | i = 0; | ||
| 676 | 871 | ||
| 677 | /* Turn stipple off. */ | 872 | for (; i < len; i++, gidx++) |
| 678 | XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid); | 873 | { |
| 874 | int x_offset = 0, y_offset = 0; | ||
| 679 | 875 | ||
| 680 | /* Draw the text, solidly, onto the stipple pattern. */ | 876 | if (relative_compose) |
| 681 | XDrawString (FRAME_X_DISPLAY (f), window, gc, | 877 | { |
| 682 | left, top + FONT_BASE (font), buf, len); | 878 | pcm = PER_CHAR_METRIC (font, buf + i); |
| 879 | if (- pcm->descent >= relative_compose) | ||
| 880 | { | ||
| 881 | /* Draw above the current glyphs. */ | ||
| 882 | y_offset = highest + pcm->descent; | ||
| 883 | highest += pcm->ascent + pcm->descent; | ||
| 884 | } | ||
| 885 | else if (pcm->ascent <= 0) | ||
| 886 | { | ||
| 887 | /* Draw beneath the current glyphs. */ | ||
| 888 | y_offset = lowest - pcm->ascent; | ||
| 889 | lowest -= pcm->ascent + pcm->descent; | ||
| 890 | } | ||
| 891 | } | ||
| 892 | else if (cmpcharp->cmp_rule) | ||
| 893 | { | ||
| 894 | int gref = (cmpcharp->cmp_rule[gidx] - 0xA0) / 9; | ||
| 895 | int nref = (cmpcharp->cmp_rule[gidx] - 0xA0) % 9; | ||
| 896 | int bottom, top; | ||
| 897 | |||
| 898 | /* Re-encode GREF and NREF so that they specify | ||
| 899 | only Y-axis information: | ||
| 900 | 0:top, 1:base, 2:bottom, 3:center */ | ||
| 901 | gref = gref / 3 + (gref == 4) * 2; | ||
| 902 | nref = nref / 3 + (nref == 4) * 2; | ||
| 903 | |||
| 904 | pcm = PER_CHAR_METRIC (font, buf + i); | ||
| 905 | bottom = ((gref == 0 ? highest : gref == 1 ? 0 | ||
| 906 | : gref == 2 ? lowest | ||
| 907 | : (highest + lowest) / 2) | ||
| 908 | - (nref == 0 ? pcm->ascent + pcm->descent | ||
| 909 | : nref == 1 ? pcm->descent : nref == 2 ? 0 | ||
| 910 | : (pcm->ascent + pcm->descent) / 2)); | ||
| 911 | top = bottom + (pcm->ascent + pcm->descent); | ||
| 912 | if (top > highest) | ||
| 913 | highest = top; | ||
| 914 | if (bottom < lowest) | ||
| 915 | lowest = bottom; | ||
| 916 | y_offset = bottom + pcm->descent; | ||
| 917 | x_offset = (cmpcharp->col_offset[gidx] | ||
| 918 | * FONT_WIDTH (f->output_data.x->font)); | ||
| 919 | } | ||
| 920 | XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | ||
| 921 | left + x_offset, top + baseline - y_offset, | ||
| 922 | buf + i, 1); | ||
| 923 | } | ||
| 683 | } | 924 | } |
| 925 | else if (background_filled) | ||
| 926 | XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | ||
| 927 | left, top + baseline, buf, len); | ||
| 684 | else | 928 | else |
| 685 | XDrawImageString (FRAME_X_DISPLAY (f), window, gc, | 929 | XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc, |
| 686 | left, top + FONT_BASE (font), buf, len); | 930 | left, top + baseline, buf, len); |
| 687 | 931 | ||
| 688 | /* Clear the rest of the line's height. */ | 932 | /* Clear the rest of the line's height. */ |
| 689 | if (f->output_data.x->line_height != FONT_HEIGHT (font)) | 933 | if (f->output_data.x->line_height > FONT_HEIGHT (font)) |
| 690 | XClearArea (FRAME_X_DISPLAY (f), window, left, | 934 | XClearArea (FRAME_X_DISPLAY (f), window, left, |
| 691 | top + FONT_HEIGHT (font), | 935 | top + FONT_HEIGHT (font), |
| 692 | FONT_WIDTH (font) * len, | 936 | FONT_WIDTH (font) * len, |
| @@ -694,42 +938,70 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground) | |||
| 694 | we have to clear. */ | 938 | we have to clear. */ |
| 695 | f->output_data.x->line_height - FONT_HEIGHT (font), | 939 | f->output_data.x->line_height - FONT_HEIGHT (font), |
| 696 | False); | 940 | False); |
| 697 | } | ||
| 698 | 941 | ||
| 699 | #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS, | 942 | #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS, |
| 700 | which often is not up to date yet. */ | 943 | which often is not up to date yet. */ |
| 701 | if (!just_foreground) | 944 | if (!just_foreground) |
| 945 | { | ||
| 946 | if (left == orig_left) | ||
| 947 | redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left), | ||
| 948 | PIXEL_TO_CHAR_ROW (f, top), hl == 1); | ||
| 949 | if (n == 0) | ||
| 950 | redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)), | ||
| 951 | PIXEL_TO_CHAR_ROW (f, top), hl == 1); | ||
| 952 | } | ||
| 953 | #endif | ||
| 954 | } | ||
| 955 | else | ||
| 702 | { | 956 | { |
| 703 | if (left == orig_left) | 957 | /* There's no appropriate font for this glyph. Just show |
| 704 | redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left), | 958 | rectangles. */ |
| 705 | PIXEL_TO_CHAR_ROW (f, top), hl == 1); | 959 | |
| 706 | if (n == 0) | 960 | if (cmpcharp) |
| 707 | redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)), | 961 | XDrawRectangle |
| 708 | PIXEL_TO_CHAR_ROW (f, top), hl == 1); | 962 | (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
| 963 | left, top + 1, | ||
| 964 | pixel_width - 2, f->output_data.x->line_height - 3); | ||
| 965 | else | ||
| 966 | { | ||
| 967 | int left_offset; | ||
| 968 | int left_skip_step = (FONT_WIDTH (f->output_data.x->font) | ||
| 969 | * CHARSET_WIDTH (charset)); | ||
| 970 | |||
| 971 | for (left_offset = 0; left_offset < pixel_width; | ||
| 972 | left_offset += left_skip_step) | ||
| 973 | XDrawRectangle | ||
| 974 | (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | ||
| 975 | left + left_offset, top + 1, | ||
| 976 | left_skip_step - 2, f->output_data.x->line_height - 3); | ||
| 977 | } | ||
| 709 | } | 978 | } |
| 710 | #endif | 979 | |
| 711 | |||
| 712 | /* We should probably check for XA_UNDERLINE_POSITION and | 980 | /* We should probably check for XA_UNDERLINE_POSITION and |
| 713 | XA_UNDERLINE_THICKNESS properties on the font, but let's | 981 | XA_UNDERLINE_THICKNESS properties on the font, but let's |
| 714 | just get the thing working, and come back to that. */ | 982 | just get the thing working, and come back to that. */ |
| 715 | { | 983 | { |
| 716 | int underline_position = 1; | 984 | /* Setting underline position based on the metric of the |
| 985 | current font results in shaky underline if it strides | ||
| 986 | over different fonts. So, we set the position based only | ||
| 987 | on the default font of this frame. */ | ||
| 988 | int underline_position = f->output_data.x->font_baseline + 1; | ||
| 717 | 989 | ||
| 718 | if (font->descent <= underline_position) | 990 | if (underline_position >= f->output_data.x->line_height) |
| 719 | underline_position = font->descent - 1; | 991 | underline_position = f->output_data.x->line_height - 1; |
| 720 | 992 | ||
| 721 | if (face->underline) | 993 | if (face->underline) |
| 722 | XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 994 | XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 723 | FACE_GC (face), | 995 | FACE_GC (face), |
| 724 | left, (top | 996 | left, top + underline_position, pixel_width, 1); |
| 725 | + FONT_BASE (font) | ||
| 726 | + underline_position), | ||
| 727 | len * FONT_WIDTH (font), 1); | ||
| 728 | } | 997 | } |
| 729 | 998 | ||
| 730 | left += len * FONT_WIDTH (font); | 999 | if (!cmpcharp) |
| 1000 | left += pixel_width; | ||
| 731 | } | 1001 | } |
| 732 | } | 1002 | } |
| 1003 | |||
| 1004 | return (left - orig_left); | ||
| 733 | } | 1005 | } |
| 734 | #endif /* 1 */ | 1006 | #endif /* 1 */ |
| 735 | 1007 | ||
| @@ -796,7 +1068,7 @@ XTwrite_glyphs (start, len) | |||
| 796 | dumpglyphs (f, | 1068 | dumpglyphs (f, |
| 797 | CHAR_TO_PIXEL_COL (f, curs_x), | 1069 | CHAR_TO_PIXEL_COL (f, curs_x), |
| 798 | CHAR_TO_PIXEL_ROW (f, curs_y), | 1070 | CHAR_TO_PIXEL_ROW (f, curs_y), |
| 799 | start, len, highlight, 0); | 1071 | start, len, highlight, 0, NULL); |
| 800 | 1072 | ||
| 801 | /* If we drew on top of the cursor, note that it is turned off. */ | 1073 | /* If we drew on top of the cursor, note that it is turned off. */ |
| 802 | if (curs_y == f->phys_cursor_y | 1074 | if (curs_y == f->phys_cursor_y |
| @@ -923,7 +1195,7 @@ redraw_previous_char (f, x, y, highlight_flag) | |||
| 923 | dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x), | 1195 | dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x), |
| 924 | CHAR_TO_PIXEL_ROW (f, y), | 1196 | CHAR_TO_PIXEL_ROW (f, y), |
| 925 | &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x], | 1197 | &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x], |
| 926 | x - start_x, highlight_flag, 1); | 1198 | x - start_x, highlight_flag, 1, NULL); |
| 927 | } | 1199 | } |
| 928 | } | 1200 | } |
| 929 | 1201 | ||
| @@ -959,7 +1231,7 @@ redraw_following_char (f, x, y, highlight_flag) | |||
| 959 | dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x), | 1231 | dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x), |
| 960 | CHAR_TO_PIXEL_ROW (f, y), | 1232 | CHAR_TO_PIXEL_ROW (f, y), |
| 961 | &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x], | 1233 | &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x], |
| 962 | end_x - x, highlight_flag, 1); | 1234 | end_x - x, highlight_flag, 1, NULL); |
| 963 | } | 1235 | } |
| 964 | } | 1236 | } |
| 965 | #endif /* 0 */ | 1237 | #endif /* 0 */ |
| @@ -1476,11 +1748,19 @@ dumprectangle (f, left, top, cols, rows) | |||
| 1476 | if (! active_frame->enable[y] || left > active_frame->used[y]) | 1748 | if (! active_frame->enable[y] || left > active_frame->used[y]) |
| 1477 | continue; | 1749 | continue; |
| 1478 | 1750 | ||
| 1751 | while (*line & GLYPH_MASK_PADDING) | ||
| 1752 | { | ||
| 1753 | /* We must display the whole glyph of a wide-column | ||
| 1754 | character. */ | ||
| 1755 | left--; | ||
| 1756 | line--; | ||
| 1757 | cols++; | ||
| 1758 | } | ||
| 1479 | dumpglyphs (f, | 1759 | dumpglyphs (f, |
| 1480 | CHAR_TO_PIXEL_COL (f, left), | 1760 | CHAR_TO_PIXEL_COL (f, left), |
| 1481 | CHAR_TO_PIXEL_ROW (f, y), | 1761 | CHAR_TO_PIXEL_ROW (f, y), |
| 1482 | line, min (cols, active_frame->used[y] - left), | 1762 | line, min (cols, active_frame->used[y] - left), |
| 1483 | active_frame->highlight[y], 0); | 1763 | active_frame->highlight[y], 0, NULL); |
| 1484 | } | 1764 | } |
| 1485 | 1765 | ||
| 1486 | /* Turn the cursor on if we turned it off. */ | 1766 | /* Turn the cursor on if we turned it off. */ |
| @@ -2234,7 +2514,7 @@ show_mouse_face (dpyinfo, hl) | |||
| 2234 | FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column, | 2514 | FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column, |
| 2235 | endcolumn - column, | 2515 | endcolumn - column, |
| 2236 | /* Highlight with mouse face if hl > 0. */ | 2516 | /* Highlight with mouse face if hl > 0. */ |
| 2237 | hl > 0 ? 3 : 0, 0); | 2517 | hl > 0 ? 3 : 0, 0, NULL); |
| 2238 | } | 2518 | } |
| 2239 | 2519 | ||
| 2240 | /* If we turned the cursor off, turn it back on. */ | 2520 | /* If we turned the cursor off, turn it back on. */ |
| @@ -4254,7 +4534,13 @@ x_draw_box (f, x, y) | |||
| 4254 | int top = CHAR_TO_PIXEL_ROW (f, y); | 4534 | int top = CHAR_TO_PIXEL_ROW (f, y); |
| 4255 | int width = FONT_WIDTH (f->output_data.x->font); | 4535 | int width = FONT_WIDTH (f->output_data.x->font); |
| 4256 | int height = f->output_data.x->line_height; | 4536 | int height = f->output_data.x->line_height; |
| 4537 | int c = FAST_GLYPH_CHAR (f->phys_cursor_glyph); | ||
| 4538 | int charset = CHAR_CHARSET (c); | ||
| 4257 | 4539 | ||
| 4540 | /* If cursor is on a multi-column character, multiply WIDTH by columns. */ | ||
| 4541 | width *= (charset == CHARSET_COMPOSITION | ||
| 4542 | ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width | ||
| 4543 | : CHARSET_WIDTH (charset)); | ||
| 4258 | XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 4544 | XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 4259 | f->output_data.x->cursor_gc, | 4545 | f->output_data.x->cursor_gc, |
| 4260 | left, top, width - 1, height - 1); | 4546 | left, top, width - 1, height - 1); |
| @@ -4293,7 +4579,7 @@ x_draw_single_glyph (f, row, column, glyph, highlight) | |||
| 4293 | dumpglyphs (f, | 4579 | dumpglyphs (f, |
| 4294 | CHAR_TO_PIXEL_COL (f, column), | 4580 | CHAR_TO_PIXEL_COL (f, column), |
| 4295 | CHAR_TO_PIXEL_ROW (f, row), | 4581 | CHAR_TO_PIXEL_ROW (f, row), |
| 4296 | &glyph, 1, highlight, 0); | 4582 | &glyph, 1, highlight, 0, NULL); |
| 4297 | } | 4583 | } |
| 4298 | 4584 | ||
| 4299 | static void | 4585 | static void |
| @@ -4825,140 +5111,17 @@ x_new_font (f, fontname) | |||
| 4825 | struct frame *f; | 5111 | struct frame *f; |
| 4826 | register char *fontname; | 5112 | register char *fontname; |
| 4827 | { | 5113 | { |
| 4828 | int already_loaded; | 5114 | struct font_info *fontp |
| 4829 | int n_matching_fonts; | 5115 | = fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1); |
| 4830 | XFontStruct *font_info; | ||
| 4831 | char **font_names; | ||
| 4832 | |||
| 4833 | /* Get a list of all the fonts that match this name. Once we | ||
| 4834 | have a list of matching fonts, we compare them against the fonts | ||
| 4835 | we already have by comparing font ids. */ | ||
| 4836 | font_names = (char **) XListFonts (FRAME_X_DISPLAY (f), fontname, | ||
| 4837 | 1024, &n_matching_fonts); | ||
| 4838 | /* Apparently it doesn't set n_matching_fonts to zero when it can't | ||
| 4839 | find any matches; font_names == 0 is the only clue. */ | ||
| 4840 | if (! font_names) | ||
| 4841 | n_matching_fonts = 0; | ||
| 4842 | |||
| 4843 | /* Don't just give up if n_matching_fonts is 0. | ||
| 4844 | Apparently there's a bug on Suns: XListFontsWithInfo can | ||
| 4845 | fail to find a font, but XLoadQueryFont may still find it. */ | ||
| 4846 | |||
| 4847 | /* See if we've already loaded a matching font. */ | ||
| 4848 | already_loaded = -1; | ||
| 4849 | if (n_matching_fonts != 0) | ||
| 4850 | { | ||
| 4851 | int i, j; | ||
| 4852 | |||
| 4853 | for (i = 0; i < FRAME_X_DISPLAY_INFO (f)->n_fonts; i++) | ||
| 4854 | for (j = 0; j < n_matching_fonts; j++) | ||
| 4855 | if (!strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].name, font_names[j]) | ||
| 4856 | || !strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name, font_names[j])) | ||
| 4857 | { | ||
| 4858 | already_loaded = i; | ||
| 4859 | fontname = FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name; | ||
| 4860 | goto found_font; | ||
| 4861 | } | ||
| 4862 | } | ||
| 4863 | found_font: | ||
| 4864 | |||
| 4865 | /* If we have, just return it from the table. */ | ||
| 4866 | if (already_loaded >= 0) | ||
| 4867 | f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font; | ||
| 4868 | /* Otherwise, load the font and add it to the table. */ | ||
| 4869 | else | ||
| 4870 | { | ||
| 4871 | int i; | ||
| 4872 | char *full_name; | ||
| 4873 | XFontStruct *font; | ||
| 4874 | int n_fonts; | ||
| 4875 | |||
| 4876 | /* Try to find a character-cell font in the list. */ | ||
| 4877 | #if 0 | ||
| 4878 | /* A laudable goal, but this isn't how to do it. */ | ||
| 4879 | for (i = 0; i < n_matching_fonts; i++) | ||
| 4880 | if (! font_info[i].per_char) | ||
| 4881 | break; | ||
| 4882 | #else | ||
| 4883 | i = 0; | ||
| 4884 | #endif | ||
| 4885 | 5116 | ||
| 4886 | /* See comment above. */ | 5117 | if (!fontp) |
| 4887 | if (n_matching_fonts != 0) | 5118 | return Qnil; |
| 4888 | fontname = font_names[i]; | ||
| 4889 | |||
| 4890 | font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname); | ||
| 4891 | if (! font) | ||
| 4892 | { | ||
| 4893 | /* Free the information from XListFonts. */ | ||
| 4894 | if (n_matching_fonts) | ||
| 4895 | XFreeFontNames (font_names); | ||
| 4896 | return Qnil; | ||
| 4897 | } | ||
| 4898 | |||
| 4899 | /* Do we need to create the table? */ | ||
| 4900 | if (FRAME_X_DISPLAY_INFO (f)->font_table_size == 0) | ||
| 4901 | { | ||
| 4902 | FRAME_X_DISPLAY_INFO (f)->font_table_size = 16; | ||
| 4903 | FRAME_X_DISPLAY_INFO (f)->font_table | ||
| 4904 | = (struct font_info *) xmalloc (FRAME_X_DISPLAY_INFO (f)->font_table_size | ||
| 4905 | * sizeof (struct font_info)); | ||
| 4906 | } | ||
| 4907 | /* Do we need to grow the table? */ | ||
| 4908 | else if (FRAME_X_DISPLAY_INFO (f)->n_fonts | ||
| 4909 | >= FRAME_X_DISPLAY_INFO (f)->font_table_size) | ||
| 4910 | { | ||
| 4911 | FRAME_X_DISPLAY_INFO (f)->font_table_size *= 2; | ||
| 4912 | FRAME_X_DISPLAY_INFO (f)->font_table | ||
| 4913 | = (struct font_info *) xrealloc (FRAME_X_DISPLAY_INFO (f)->font_table, | ||
| 4914 | (FRAME_X_DISPLAY_INFO (f)->font_table_size | ||
| 4915 | * sizeof (struct font_info))); | ||
| 4916 | } | ||
| 4917 | |||
| 4918 | /* Try to get the full name of FONT. Put it in full_name. */ | ||
| 4919 | full_name = 0; | ||
| 4920 | for (i = 0; i < font->n_properties; i++) | ||
| 4921 | { | ||
| 4922 | if (FRAME_X_DISPLAY_INFO (f)->Xatom_FONT == font->properties[i].name) | ||
| 4923 | { | ||
| 4924 | char *name = XGetAtomName (FRAME_X_DISPLAY (f), | ||
| 4925 | (Atom) (font->properties[i].card32)); | ||
| 4926 | char *p = name; | ||
| 4927 | int dashes = 0; | ||
| 4928 | |||
| 4929 | /* Count the number of dashes in the "full name". | ||
| 4930 | If it is too few, this isn't really the font's full name, | ||
| 4931 | so don't use it. | ||
| 4932 | In X11R4, the fonts did not come with their canonical names | ||
| 4933 | stored in them. */ | ||
| 4934 | while (*p) | ||
| 4935 | { | ||
| 4936 | if (*p == '-') | ||
| 4937 | dashes++; | ||
| 4938 | p++; | ||
| 4939 | } | ||
| 4940 | |||
| 4941 | if (dashes >= 13) | ||
| 4942 | full_name = name; | ||
| 4943 | |||
| 4944 | break; | ||
| 4945 | } | ||
| 4946 | } | ||
| 4947 | |||
| 4948 | n_fonts = FRAME_X_DISPLAY_INFO (f)->n_fonts; | ||
| 4949 | FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1); | ||
| 4950 | bcopy (fontname, FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1); | ||
| 4951 | if (full_name != 0) | ||
| 4952 | FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = full_name; | ||
| 4953 | else | ||
| 4954 | FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name; | ||
| 4955 | f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font; | ||
| 4956 | FRAME_X_DISPLAY_INFO (f)->n_fonts++; | ||
| 4957 | |||
| 4958 | if (full_name) | ||
| 4959 | fontname = full_name; | ||
| 4960 | } | ||
| 4961 | 5119 | ||
| 5120 | f->output_data.x->font = (XFontStruct *) (fontp->font); | ||
| 5121 | f->output_data.x->font_baseline | ||
| 5122 | = (f->output_data.x->font->ascent + fontp->baseline_offset); | ||
| 5123 | f->output_data.x->fontset = -1; | ||
| 5124 | |||
| 4962 | /* Compute the scroll bar width in character columns. */ | 5125 | /* Compute the scroll bar width in character columns. */ |
| 4963 | if (f->scroll_bar_pixel_width > 0) | 5126 | if (f->scroll_bar_pixel_width > 0) |
| 4964 | { | 5127 | { |
| @@ -4986,17 +5149,44 @@ x_new_font (f, fontname) | |||
| 4986 | there are no faces yet, so this font's height is the line height. */ | 5149 | there are no faces yet, so this font's height is the line height. */ |
| 4987 | f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font); | 5150 | f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font); |
| 4988 | 5151 | ||
| 4989 | { | 5152 | return build_string (fontp->full_name); |
| 4990 | Lisp_Object lispy_name; | 5153 | } |
| 5154 | |||
| 5155 | /* Give frame F the fontset named FONTSETNAME as its default font, and | ||
| 5156 | return the full name of that fontset. FONTSETNAME may be a wildcard | ||
| 5157 | pattern; in that case, we choose some font that fits the pattern. | ||
| 5158 | The return value shows which font we chose. */ | ||
| 4991 | 5159 | ||
| 4992 | lispy_name = build_string (fontname); | 5160 | Lisp_Object |
| 5161 | x_new_fontset (f, fontsetname) | ||
| 5162 | struct frame *f; | ||
| 5163 | char *fontsetname; | ||
| 5164 | { | ||
| 5165 | int fontset = fs_query_fontset (f, fontsetname); | ||
| 5166 | struct fontset_info *fontsetp; | ||
| 5167 | Lisp_Object result; | ||
| 4993 | 5168 | ||
| 4994 | /* Free the information from XListFonts. The data | 5169 | if (fontset < 0) |
| 4995 | we actually retain comes from XLoadQueryFont. */ | 5170 | return Qnil; |
| 4996 | XFreeFontNames (font_names); | ||
| 4997 | 5171 | ||
| 4998 | return lispy_name; | 5172 | fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset]; |
| 4999 | } | 5173 | |
| 5174 | if (!fontsetp->fontname[CHARSET_ASCII]) | ||
| 5175 | /* This fontset doesn't contain ASCII font. */ | ||
| 5176 | return Qnil; | ||
| 5177 | |||
| 5178 | result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]); | ||
| 5179 | |||
| 5180 | if (!STRINGP (result)) | ||
| 5181 | /* Can't load ASCII font. */ | ||
| 5182 | return Qnil; | ||
| 5183 | |||
| 5184 | /* Since x_new_font doesn't update any fontset information, do it now. */ | ||
| 5185 | f->output_data.x->fontset = fontset; | ||
| 5186 | fs_load_font (f, FRAME_X_FONT_TABLE (f), | ||
| 5187 | CHARSET_ASCII, XSTRING (result)->data, fontset); | ||
| 5188 | |||
| 5189 | return build_string (fontsetname); | ||
| 5000 | } | 5190 | } |
| 5001 | 5191 | ||
| 5002 | /* Calculate the absolute position in frame F | 5192 | /* Calculate the absolute position in frame F |
| @@ -5896,6 +6086,326 @@ x_wm_set_icon_position (f, icon_x, icon_y) | |||
| 5896 | } | 6086 | } |
| 5897 | 6087 | ||
| 5898 | 6088 | ||
| 6089 | /* Interface to fontset handler. */ | ||
| 6090 | |||
| 6091 | /* Return a pointer to struct font_info of font FONT_IDX of frame F. */ | ||
| 6092 | struct font_info * | ||
| 6093 | x_get_font_info (f, font_idx) | ||
| 6094 | FRAME_PTR f; | ||
| 6095 | int font_idx; | ||
| 6096 | { | ||
| 6097 | return (FRAME_X_FONT_TABLE (f) + font_idx); | ||
| 6098 | } | ||
| 6099 | |||
| 6100 | |||
| 6101 | /* Return a list of names of available fonts matching PATTERN on frame | ||
| 6102 | F. If SIZE is not 0, it is the size (maximum bound width) of fonts | ||
| 6103 | to be listed. Frame F NULL means we have not yet created any | ||
| 6104 | frame on X, and consult the first display in x_display_list. | ||
| 6105 | MAXNAMES sets a limit on how many fonts to match. */ | ||
| 6106 | |||
| 6107 | Lisp_Object | ||
| 6108 | x_list_fonts (f, pattern, size, maxnames) | ||
| 6109 | FRAME_PTR f; | ||
| 6110 | Lisp_Object pattern; | ||
| 6111 | int size; | ||
| 6112 | int maxnames; | ||
| 6113 | { | ||
| 6114 | Lisp_Object list, newlist, key; | ||
| 6115 | Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display; | ||
| 6116 | |||
| 6117 | key = Fcons (pattern, make_number (maxnames)); | ||
| 6118 | |||
| 6119 | if (f == NULL) | ||
| 6120 | list = Qnil; | ||
| 6121 | else | ||
| 6122 | /* See if we cached the result for this particular query. */ | ||
| 6123 | list = Fassoc (key, | ||
| 6124 | XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr); | ||
| 6125 | |||
| 6126 | if (!NILP (list)) | ||
| 6127 | list = XCONS (list)->cdr; | ||
| 6128 | else | ||
| 6129 | { | ||
| 6130 | /* At first, put PATTERN in the cache. */ | ||
| 6131 | int num_fonts; | ||
| 6132 | char **names; | ||
| 6133 | |||
| 6134 | BLOCK_INPUT; | ||
| 6135 | names = XListFonts (dpy, XSTRING (pattern)->data, maxnames, &num_fonts); | ||
| 6136 | UNBLOCK_INPUT; | ||
| 6137 | |||
| 6138 | if (names) | ||
| 6139 | { | ||
| 6140 | int i; | ||
| 6141 | Lisp_Object tem; | ||
| 6142 | |||
| 6143 | /* Make a list of all the fonts we got back. | ||
| 6144 | Store that in the font cache for the display. */ | ||
| 6145 | for (i = 0; i < num_fonts; i++) | ||
| 6146 | { | ||
| 6147 | char *p = names[i]; | ||
| 6148 | int average_width = -1, dashes = 0, width = 0; | ||
| 6149 | |||
| 6150 | /* Count the number of dashes in NAMES[I]. If there are | ||
| 6151 | 14 dashes, and the field value following 12th dash | ||
| 6152 | (AVERAGE_WIDTH) is 0, this is a auto-scaled font | ||
| 6153 | which is of no use. Let's ignore it. */ | ||
| 6154 | while (*p) | ||
| 6155 | if (*p++ == '-') | ||
| 6156 | { | ||
| 6157 | dashes++; | ||
| 6158 | if (dashes == 7) /* PIXEL_SIZE field */ | ||
| 6159 | width = atoi (p); | ||
| 6160 | else if (dashes == 12) /* AVERAGE_WIDTH field */ | ||
| 6161 | average_width = atoi (p); | ||
| 6162 | } | ||
| 6163 | if (dashes < 14 || average_width != 0) | ||
| 6164 | { | ||
| 6165 | tem = build_string (names[i]); | ||
| 6166 | if (NILP (Fassoc (tem, list))) | ||
| 6167 | { | ||
| 6168 | if (STRINGP (Vx_pixel_size_width_font_regexp) | ||
| 6169 | && (fast_string_match_ignore_case | ||
| 6170 | (Vx_pixel_size_width_font_regexp, names[i]) | ||
| 6171 | >= 0)) | ||
| 6172 | /* We can set the value of PIXEL_SIZE to the | ||
| 6173 | width of this font. */ | ||
| 6174 | list = Fcons (Fcons (tem, make_number (width)), list); | ||
| 6175 | else | ||
| 6176 | /* For the moment, width is not known. */ | ||
| 6177 | list = Fcons (Fcons (tem, Qnil), list); | ||
| 6178 | } | ||
| 6179 | } | ||
| 6180 | } | ||
| 6181 | XFreeFontNames (names); | ||
| 6182 | } | ||
| 6183 | |||
| 6184 | if (f != NULL) | ||
| 6185 | XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr | ||
| 6186 | = Fcons (Fcons (key, list), | ||
| 6187 | XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr); | ||
| 6188 | } | ||
| 6189 | |||
| 6190 | if (NILP (list)) | ||
| 6191 | return Qnil; | ||
| 6192 | |||
| 6193 | newlist = Qnil; | ||
| 6194 | |||
| 6195 | /* Make a list of the fonts that have the right width. */ | ||
| 6196 | for (; CONSP (list); list = XCONS (list)->cdr) | ||
| 6197 | { | ||
| 6198 | Lisp_Object tem = XCONS (list)->car; | ||
| 6199 | int keeper; | ||
| 6200 | |||
| 6201 | if (!CONSP (tem) || NILP (XCONS (tem)->car)) | ||
| 6202 | continue; | ||
| 6203 | if (!size) | ||
| 6204 | keeper = 1; | ||
| 6205 | else | ||
| 6206 | { | ||
| 6207 | if (!INTEGERP (XCONS (tem)->cdr)) | ||
| 6208 | { | ||
| 6209 | XFontStruct *thisinfo; | ||
| 6210 | |||
| 6211 | BLOCK_INPUT; | ||
| 6212 | thisinfo = XLoadQueryFont (dpy, | ||
| 6213 | XSTRING (XCONS (tem)->car)->data); | ||
| 6214 | UNBLOCK_INPUT; | ||
| 6215 | |||
| 6216 | if (thisinfo) | ||
| 6217 | { | ||
| 6218 | XCONS (tem)->cdr = make_number (thisinfo->max_bounds.width); | ||
| 6219 | XFreeFont (dpy, thisinfo); | ||
| 6220 | } | ||
| 6221 | else | ||
| 6222 | XCONS (tem)->cdr = make_number (0); | ||
| 6223 | } | ||
| 6224 | keeper = XINT (XCONS (tem)->cdr) == size; | ||
| 6225 | } | ||
| 6226 | if (keeper) | ||
| 6227 | newlist = Fcons (XCONS (tem)->car, newlist); | ||
| 6228 | } | ||
| 6229 | |||
| 6230 | return newlist; | ||
| 6231 | } | ||
| 6232 | |||
| 6233 | /* Load font named FONTNAME of the size SIZE for frame F, and return a | ||
| 6234 | pointer to the structure font_info while allocating it dynamically. | ||
| 6235 | If SIZE is 0, load any size of font. | ||
| 6236 | If loading is failed, return NULL. */ | ||
| 6237 | |||
| 6238 | struct font_info * | ||
| 6239 | x_load_font (f, fontname, size) | ||
| 6240 | struct frame *f; | ||
| 6241 | register char *fontname; | ||
| 6242 | int size; | ||
| 6243 | { | ||
| 6244 | struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | ||
| 6245 | Lisp_Object font_names; | ||
| 6246 | |||
| 6247 | /* Get a list of all the fonts that match this name. Once we | ||
| 6248 | have a list of matching fonts, we compare them against the fonts | ||
| 6249 | we already have by comparing names. */ | ||
| 6250 | font_names = x_list_fonts (f, build_string (fontname), size, 256); | ||
| 6251 | |||
| 6252 | if (!NILP (font_names)) | ||
| 6253 | { | ||
| 6254 | Lisp_Object tail; | ||
| 6255 | int i; | ||
| 6256 | |||
| 6257 | for (i = 0; i < dpyinfo->n_fonts; i++) | ||
| 6258 | for (tail = font_names; CONSP (tail); tail = XCONS (tail)->cdr) | ||
| 6259 | if (!strcmp (dpyinfo->font_table[i].name, | ||
| 6260 | XSTRING (XCONS (tail)->car)->data) | ||
| 6261 | || !strcmp (dpyinfo->font_table[i].full_name, | ||
| 6262 | XSTRING (XCONS (tail)->car)->data)) | ||
| 6263 | return (dpyinfo->font_table + i); | ||
| 6264 | } | ||
| 6265 | |||
| 6266 | /* Load the font and add it to the table. */ | ||
| 6267 | { | ||
| 6268 | char *full_name; | ||
| 6269 | XFontStruct *font; | ||
| 6270 | struct font_info *fontp; | ||
| 6271 | unsigned long value; | ||
| 6272 | |||
| 6273 | if (!NILP (font_names)) | ||
| 6274 | fontname = XSTRING (XCONS (font_names)->car)->data; | ||
| 6275 | |||
| 6276 | BLOCK_INPUT; | ||
| 6277 | font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname); | ||
| 6278 | UNBLOCK_INPUT; | ||
| 6279 | if (!font || (size && font->max_bounds.width != size)) | ||
| 6280 | return NULL; | ||
| 6281 | |||
| 6282 | /* Do we need to create the table? */ | ||
| 6283 | if (dpyinfo->font_table_size == 0) | ||
| 6284 | { | ||
| 6285 | dpyinfo->font_table_size = 16; | ||
| 6286 | dpyinfo->font_table | ||
| 6287 | = (struct font_info *) xmalloc (dpyinfo->font_table_size | ||
| 6288 | * sizeof (struct font_info)); | ||
| 6289 | } | ||
| 6290 | /* Do we need to grow the table? */ | ||
| 6291 | else if (dpyinfo->n_fonts | ||
| 6292 | >= dpyinfo->font_table_size) | ||
| 6293 | { | ||
| 6294 | dpyinfo->font_table_size *= 2; | ||
| 6295 | dpyinfo->font_table | ||
| 6296 | = (struct font_info *) xrealloc (dpyinfo->font_table, | ||
| 6297 | (dpyinfo->font_table_size | ||
| 6298 | * sizeof (struct font_info))); | ||
| 6299 | } | ||
| 6300 | |||
| 6301 | fontp = dpyinfo->font_table + dpyinfo->n_fonts; | ||
| 6302 | |||
| 6303 | /* Now fill in the slots of *FONTP. */ | ||
| 6304 | BLOCK_INPUT; | ||
| 6305 | fontp->font = font; | ||
| 6306 | fontp->font_idx = dpyinfo->n_fonts; | ||
| 6307 | fontp->name = (char *) xmalloc (strlen (fontname) + 1); | ||
| 6308 | bcopy (fontname, fontp->name, strlen (fontname) + 1); | ||
| 6309 | |||
| 6310 | /* Try to get the full name of FONT. Put it in FULL_NAME. */ | ||
| 6311 | full_name = 0; | ||
| 6312 | if (XGetFontProperty (font, XA_FONT, &value)) | ||
| 6313 | { | ||
| 6314 | char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value); | ||
| 6315 | char *p = name; | ||
| 6316 | int dashes = 0; | ||
| 6317 | |||
| 6318 | /* Count the number of dashes in the "full name". | ||
| 6319 | If it is too few, this isn't really the font's full name, | ||
| 6320 | so don't use it. | ||
| 6321 | In X11R4, the fonts did not come with their canonical names | ||
| 6322 | stored in them. */ | ||
| 6323 | while (*p) | ||
| 6324 | { | ||
| 6325 | if (*p == '-') | ||
| 6326 | dashes++; | ||
| 6327 | p++; | ||
| 6328 | } | ||
| 6329 | |||
| 6330 | if (dashes >= 13) | ||
| 6331 | { | ||
| 6332 | full_name = (char *) xmalloc (p - name + 1); | ||
| 6333 | bcopy (name, full_name, p - name + 1); | ||
| 6334 | } | ||
| 6335 | |||
| 6336 | XFree (name); | ||
| 6337 | } | ||
| 6338 | |||
| 6339 | if (full_name != 0) | ||
| 6340 | fontp->full_name = full_name; | ||
| 6341 | else | ||
| 6342 | fontp->full_name = fontp->name; | ||
| 6343 | |||
| 6344 | fontp->size = font->max_bounds.width; | ||
| 6345 | fontp->height = font->ascent + font->descent; | ||
| 6346 | |||
| 6347 | /* The slot `encoding' specifies how to map a character | ||
| 6348 | code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to | ||
| 6349 | the font code-points (0x20..0x7F, 0xA0..0xFF, 0x2020..0x7F7F, | ||
| 6350 | 0xA0A0..0xFFFF, 0x20A0..0x7FFF, or 0xA020..0xFF7F). For the | ||
| 6351 | moment, we don't know which charset uses this font. So, we set | ||
| 6352 | informatoin in fontp->encoding[1] which is never used by any | ||
| 6353 | charset. If mapping can't be decided, set -1. */ | ||
| 6354 | fontp->encoding[1] | ||
| 6355 | = (font->max_byte1 == 0 | ||
| 6356 | /* 1-byte font */ | ||
| 6357 | ? (font->min_char_or_byte2 < 0x80 | ||
| 6358 | ? (font->max_char_or_byte2 < 0x80 | ||
| 6359 | ? 0 /* 0x20..0x7F */ | ||
| 6360 | : -1) /* 0x20..0xFF (can't decide) */ | ||
| 6361 | : 1) /* 0xA0..0xFF */ | ||
| 6362 | /* 2-byte font */ | ||
| 6363 | : (font->min_byte1 < 0x80 | ||
| 6364 | ? (font->max_byte1 < 0x80 | ||
| 6365 | ? (font->min_char_or_byte2 < 0x80 | ||
| 6366 | ? (font->max_char_or_byte2 < 0x80 | ||
| 6367 | ? 0 /* 0x2020..0x7F7F */ | ||
| 6368 | : -1) /* 0x2020..0x7FFF (can't decide) */ | ||
| 6369 | : 3) /* 0x20A0..0x7FFF */ | ||
| 6370 | : -1) /* 0x20??..0xA0?? (can't decide) */ | ||
| 6371 | : (font->min_char_or_byte2 < 0x80 | ||
| 6372 | ? (font->max_char_or_byte2 < 0x80 | ||
| 6373 | ? 2 /* 0xA020..0xFF7F */ | ||
| 6374 | : -1) /* 0xA020..0xFFFF (can't decide) */ | ||
| 6375 | : 1))); /* 0xA0A0..0xFFFF */ | ||
| 6376 | |||
| 6377 | fontp->baseline_offset | ||
| 6378 | = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value) | ||
| 6379 | ? (long) value : 0); | ||
| 6380 | fontp->relative_compose | ||
| 6381 | = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value) | ||
| 6382 | ? (long) value : 0); | ||
| 6383 | |||
| 6384 | UNBLOCK_INPUT; | ||
| 6385 | dpyinfo->n_fonts++; | ||
| 6386 | |||
| 6387 | return fontp; | ||
| 6388 | } | ||
| 6389 | } | ||
| 6390 | |||
| 6391 | /* Return a pointer to struct font_info of a font named FONTNAME for frame F. | ||
| 6392 | If no such font is loaded, return NULL. */ | ||
| 6393 | struct font_info * | ||
| 6394 | x_query_font (f, fontname) | ||
| 6395 | struct frame *f; | ||
| 6396 | register char *fontname; | ||
| 6397 | { | ||
| 6398 | struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | ||
| 6399 | int i; | ||
| 6400 | |||
| 6401 | for (i = 0; i < dpyinfo->n_fonts; i++) | ||
| 6402 | if (!strcmp (dpyinfo->font_table[i].name, fontname) | ||
| 6403 | || !strcmp (dpyinfo->font_table[i].full_name, fontname)) | ||
| 6404 | return (dpyinfo->font_table + i); | ||
| 6405 | return NULL; | ||
| 6406 | } | ||
| 6407 | |||
| 6408 | |||
| 5899 | /* Initialization. */ | 6409 | /* Initialization. */ |
| 5900 | 6410 | ||
| 5901 | #ifdef USE_X_TOOLKIT | 6411 | #ifdef USE_X_TOOLKIT |
| @@ -6139,14 +6649,14 @@ x_term_init (display_name, xrm_option, resource_name) | |||
| 6139 | = XInternAtom (dpyinfo->display, "WM_MOVED", False); | 6649 | = XInternAtom (dpyinfo->display, "WM_MOVED", False); |
| 6140 | dpyinfo->Xatom_editres | 6650 | dpyinfo->Xatom_editres |
| 6141 | = XInternAtom (dpyinfo->display, "Editres", False); | 6651 | = XInternAtom (dpyinfo->display, "Editres", False); |
| 6142 | dpyinfo->Xatom_FONT | ||
| 6143 | = XInternAtom (dpyinfo->display, "FONT", False); | ||
| 6144 | dpyinfo->Xatom_CLIPBOARD | 6652 | dpyinfo->Xatom_CLIPBOARD |
| 6145 | = XInternAtom (dpyinfo->display, "CLIPBOARD", False); | 6653 | = XInternAtom (dpyinfo->display, "CLIPBOARD", False); |
| 6146 | dpyinfo->Xatom_TIMESTAMP | 6654 | dpyinfo->Xatom_TIMESTAMP |
| 6147 | = XInternAtom (dpyinfo->display, "TIMESTAMP", False); | 6655 | = XInternAtom (dpyinfo->display, "TIMESTAMP", False); |
| 6148 | dpyinfo->Xatom_TEXT | 6656 | dpyinfo->Xatom_TEXT |
| 6149 | = XInternAtom (dpyinfo->display, "TEXT", False); | 6657 | = XInternAtom (dpyinfo->display, "TEXT", False); |
| 6658 | dpyinfo->Xatom_COMPOUND_TEXT | ||
| 6659 | = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False); | ||
| 6150 | dpyinfo->Xatom_DELETE | 6660 | dpyinfo->Xatom_DELETE |
| 6151 | = XInternAtom (dpyinfo->display, "DELETE", False); | 6661 | = XInternAtom (dpyinfo->display, "DELETE", False); |
| 6152 | dpyinfo->Xatom_MULTIPLE | 6662 | dpyinfo->Xatom_MULTIPLE |
| @@ -6161,12 +6671,28 @@ x_term_init (display_name, xrm_option, resource_name) | |||
| 6161 | = XInternAtom (dpyinfo->display, "NULL", False); | 6671 | = XInternAtom (dpyinfo->display, "NULL", False); |
| 6162 | dpyinfo->Xatom_ATOM_PAIR | 6672 | dpyinfo->Xatom_ATOM_PAIR |
| 6163 | = XInternAtom (dpyinfo->display, "ATOM_PAIR", False); | 6673 | = XInternAtom (dpyinfo->display, "ATOM_PAIR", False); |
| 6674 | /* For properties of font. */ | ||
| 6675 | dpyinfo->Xatom_PIXEL_SIZE | ||
| 6676 | = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False); | ||
| 6677 | dpyinfo->Xatom_MULE_BASELINE_OFFSET | ||
| 6678 | = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False); | ||
| 6679 | dpyinfo->Xatom_MULE_RELATIVE_COMPOSE | ||
| 6680 | = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False); | ||
| 6164 | 6681 | ||
| 6165 | dpyinfo->cut_buffers_initialized = 0; | 6682 | dpyinfo->cut_buffers_initialized = 0; |
| 6166 | 6683 | ||
| 6167 | connection = ConnectionNumber (dpyinfo->display); | 6684 | connection = ConnectionNumber (dpyinfo->display); |
| 6168 | dpyinfo->connection = connection; | 6685 | dpyinfo->connection = connection; |
| 6169 | 6686 | ||
| 6687 | { | ||
| 6688 | char null_bits[] = { 0x00 }; | ||
| 6689 | |||
| 6690 | dpyinfo->null_pixel | ||
| 6691 | = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window, | ||
| 6692 | null_bits, 1, 1, (long) 0, (long) 0, | ||
| 6693 | 1); | ||
| 6694 | } | ||
| 6695 | |||
| 6170 | #ifdef subprocesses | 6696 | #ifdef subprocesses |
| 6171 | /* This is only needed for distinguishing keyboard and process input. */ | 6697 | /* This is only needed for distinguishing keyboard and process input. */ |
| 6172 | if (connection != 0) | 6698 | if (connection != 0) |