X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/d73d547a20c1a36612dc637d860113551d4ddc6a..09a1444abb2494d0db3d71e4c942f5210786b619:/src/xfaces.c diff --git a/src/xfaces.c b/src/xfaces.c index 5137ab7e72..2884bccb3b 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -1,5 +1,5 @@ /* xfaces.c -- "Face" primitives. - Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation. This file is part of GNU Emacs. @@ -336,6 +336,8 @@ extern Lisp_Object Qmode_line; Lisp_Object Qface_alias; +extern Lisp_Object Qcircular_list; + /* Default stipple pattern used on monochrome displays. This stipple pattern is used on monochrome displays instead of shades of gray for a face background color. See `set-face-stipple' for possible @@ -471,7 +473,7 @@ struct named_merge_point; static void map_tty_color P_ ((struct frame *, struct face *, enum lface_attribute_index, int *)); -static Lisp_Object resolve_face_name P_ ((Lisp_Object)); +static Lisp_Object resolve_face_name P_ ((Lisp_Object, int)); static int may_use_scalable_font_p P_ ((const char *)); static void set_font_frame_param P_ ((Lisp_Object, Lisp_Object)); static int better_font_p P_ ((int *, struct font_name *, struct font_name *, @@ -741,7 +743,7 @@ x_free_gc (f, gc) GC gc; { BLOCK_INPUT; - xassert (--ngcs >= 0); + IF_DEBUG (xassert (--ngcs >= 0)); XFreeGC (FRAME_X_DISPLAY (f), gc); UNBLOCK_INPUT; } @@ -774,7 +776,7 @@ x_free_gc (f, gc) GC gc; { BLOCK_INPUT; - xassert (--ngcs >= 0); + IF_DEBUG (xassert (--ngcs >= 0)); xfree (gc); UNBLOCK_INPUT; } @@ -1074,6 +1076,9 @@ clear_font_table (dpyinfo) #endif #ifdef WINDOWSNT w32_unload_font (dpyinfo, font_info->font); +#endif +#ifdef MAC_OS + mac_unload_font (dpyinfo, font_info->font); #endif UNBLOCK_INPUT; @@ -1513,7 +1518,7 @@ face_color_supported_p (f, color_name, background_p) XSETFRAME (frame, f); return -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM FRAME_WINDOW_P (f) ? (!NILP (Fxw_display_color_p (frame)) || xstricmp (color_name, "black") == 0 @@ -3012,7 +3017,7 @@ the WIDTH times as wide as FACE on FRAME. */) { /* This is of limited utility since it works with character widths. Keep it for compatibility. --gerd. */ - int face_id = lookup_named_face (f, face, 0); + int face_id = lookup_named_face (f, face, 0, 0); struct face *face = (face_id < 0 ? NULL : FACE_FROM_ID (f, face_id)); @@ -3201,27 +3206,63 @@ push_named_merge_point (struct named_merge_point *new_named_merge_point, +static Lisp_Object +internal_resolve_face_name (nargs, args) + int nargs; + Lisp_Object *args; +{ + Fget (args[0], args[1]); +} + +static Lisp_Object +resolve_face_name_error (ignore) + Lisp_Object ignore; +{ + return Qnil; +} /* Resolve face name FACE_NAME. If FACE_NAME is a string, intern it - to make it a symvol. If FACE_NAME is an alias for another face, - return that face's name. */ + to make it a symbol. If FACE_NAME is an alias for another face, + return that face's name. + + Return default face in case of errors. */ static Lisp_Object -resolve_face_name (face_name) +resolve_face_name (face_name, signal_p) Lisp_Object face_name; + int signal_p; { - Lisp_Object aliased; + Lisp_Object orig_face; + Lisp_Object tortoise, hare; if (STRINGP (face_name)) face_name = intern (SDATA (face_name)); - while (SYMBOLP (face_name)) + if (NILP (face_name) || !SYMBOLP (face_name)) + return face_name; + + orig_face = face_name; + tortoise = hare = face_name; + + while (1) { - aliased = Fget (face_name, Qface_alias); - if (NILP (aliased)) + face_name = hare; + hare = Fget (hare, Qface_alias); + if (NILP (hare) || !SYMBOLP (hare)) break; - else - face_name = aliased; + + face_name = hare; + hare = Fget (hare, Qface_alias); + if (NILP (hare) || !SYMBOLP (hare)) + break; + + tortoise = Fget (tortoise, Qface_alias); + if (EQ (hare, tortoise)) + { + if (signal_p) + Fsignal (Qcircular_list, Fcons (orig_face, Qnil)); + return Qdefault; + } } return face_name; @@ -3245,7 +3286,7 @@ lface_from_face_name (f, face_name, signal_p) { Lisp_Object lface; - face_name = resolve_face_name (face_name); + face_name = resolve_face_name (face_name, signal_p); if (f) lface = assq_no_quit (face_name, f->face_alist); @@ -3435,8 +3476,8 @@ set_lface_from_font_name (f, lface, fontname, force_p, may_fail_p) call into lisp. */ Lisp_Object -merge_face_heights (from, to, invalid, gcpro) - Lisp_Object from, to, invalid, gcpro; +merge_face_heights (from, to, invalid) + Lisp_Object from, to, invalid; { Lisp_Object result = invalid; @@ -3461,16 +3502,11 @@ merge_face_heights (from, to, invalid, gcpro) /* Call function with current height as argument. From is the new height. */ Lisp_Object args[2]; - struct gcpro gcpro1; - - GCPRO1 (gcpro); args[0] = from; args[1] = to; result = safe_call (2, args); - UNGCPRO; - /* Ensure that if TO was absolute, so is the result. */ if (INTEGERP (to) && !INTEGERP (result)) result = invalid; @@ -3523,8 +3559,7 @@ merge_face_vectors (f, from, to, named_merge_points) if (!UNSPECIFIEDP (from[i])) { if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i])) - to[i] = merge_face_heights (from[i], to[i], to[i], - named_merge_points); + to[i] = merge_face_heights (from[i], to[i], to[i]); else to[i] = from[i]; } @@ -3551,11 +3586,16 @@ merge_named_face (f, face_name, to, named_merge_points) if (push_named_merge_point (&named_merge_point, face_name, &named_merge_points)) { + struct gcpro gcpro1; Lisp_Object from[LFACE_VECTOR_SIZE]; int ok = get_lface_attributes (f, face_name, from, 0); if (ok) - merge_face_vectors (f, from, to, named_merge_points); + { + GCPRO1 (named_merge_point.face_name); + merge_face_vectors (f, from, to, named_merge_points); + UNGCPRO; + } return ok; } @@ -3646,8 +3686,7 @@ merge_face_ref (f, face_ref, to, err_msgs, named_merge_points) else if (EQ (keyword, QCheight)) { Lisp_Object new_height = - merge_face_heights (value, to[LFACE_HEIGHT_INDEX], - Qnil, Qnil); + merge_face_heights (value, to[LFACE_HEIGHT_INDEX], Qnil); if (! NILP (new_height)) to[LFACE_HEIGHT_INDEX] = new_height; @@ -3982,7 +4021,7 @@ FRAME 0 means change the face on all frames, and change the default CHECK_SYMBOL (face); CHECK_SYMBOL (attr); - face = resolve_face_name (face); + face = resolve_face_name (face, 1); /* If FRAME is 0, change face on all frames, and change the default for new frames. */ @@ -4034,7 +4073,7 @@ FRAME 0 means change the face on all frames, and change the default /* The default face must have an absolute size, otherwise, we do a test merge with a random height to see if VALUE's ok. */ - : merge_face_heights (value, make_number (10), Qnil, Qnil)); + : merge_face_heights (value, make_number (10), Qnil)); if (!INTEGERP (test) || XINT (test) <= 0) signal_error ("Invalid face height", value); @@ -4150,7 +4189,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (k, QCcolor)) { - if (!STRINGP (v) || SCHARS (v) == 0) + if (!NILP (v) && (!STRINGP (v) || SCHARS (v) == 0)) break; } else if (EQ (k, QCstyle)) @@ -4694,16 +4733,27 @@ x_update_menu_appearance (f) { #ifdef USE_MOTIF const char *suffix = "List"; + Bool motif = True; #else const char *suffix = ""; + Bool motif = False; +#endif +#if defined HAVE_X_I18N + extern char *xic_create_fontsetname + P_ ((char *base_fontname, Bool motif)); + char *fontsetname = xic_create_fontsetname (face->font_name, motif); +#else + char *fontsetname = face->font_name; #endif sprintf (line, "%s.pane.menubar*font%s: %s", - myname, suffix, face->font_name); + myname, suffix, fontsetname); XrmPutLineResource (&rdb, line); sprintf (line, "%s.%s*font%s: %s", - myname, popup_path, suffix, face->font_name); + myname, popup_path, suffix, fontsetname); XrmPutLineResource (&rdb, line); changed_p = 1; + if (fontsetname != face->font_name) + xfree (fontsetname); } if (changed_p && f->output_data.x->menubar_widget) @@ -4740,7 +4790,7 @@ the result will be absolute, otherwise it will be relative. */) if (EQ (value1, Qunspecified)) return value2; else if (EQ (attribute, QCheight)) - return merge_face_heights (value1, value2, value1, Qnil); + return merge_face_heights (value1, value2, value1); else return value1; } @@ -4928,7 +4978,7 @@ If FRAME is omitted or nil, use the selected frame. */) else { struct frame *f = frame_or_selected_frame (frame, 1); - int face_id = lookup_named_face (f, face, 0); + int face_id = lookup_named_face (f, face, 0, 1); struct face *face = FACE_FROM_ID (f, face_id); return face ? build_string (face->font_name) : Qnil; } @@ -5620,10 +5670,11 @@ lookup_face (f, attr, c, base_face) isn't realized and cannot be realized. */ int -lookup_named_face (f, symbol, c) +lookup_named_face (f, symbol, c, signal_p) struct frame *f; Lisp_Object symbol; int c; + int signal_p; { Lisp_Object attrs[LFACE_VECTOR_SIZE]; Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE]; @@ -5636,7 +5687,9 @@ lookup_named_face (f, symbol, c) default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); } - get_lface_attributes (f, symbol, symbol_attrs, 1); + if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p)) + return -1; + bcopy (default_face->lface, attrs, sizeof attrs); merge_face_vectors (f, symbol_attrs, attrs, 0); @@ -5657,7 +5710,7 @@ ascii_face_of_lisp_face (f, lface_id) if (lface_id >= 0 && lface_id < lface_id_to_name_size) { Lisp_Object face_name = lface_id_to_name[lface_id]; - face_id = lookup_named_face (f, face_name, 0); + face_id = lookup_named_face (f, face_name, 0, 1); } else face_id = -1; @@ -5763,7 +5816,7 @@ face_with_height (f, face_id, height) is assumed to be already realized. */ int -lookup_derived_face (f, symbol, c, face_id) +lookup_derived_face (f, symbol, c, face_id, signal_p) struct frame *f; Lisp_Object symbol; int c; @@ -5776,7 +5829,7 @@ lookup_derived_face (f, symbol, c, face_id) if (!default_face) abort (); - get_lface_attributes (f, symbol, symbol_attrs, 1); + get_lface_attributes (f, symbol, symbol_attrs, signal_p); bcopy (default_face->lface, attrs, sizeof attrs); merge_face_vectors (f, symbol_attrs, attrs, 0); return lookup_face (f, attrs, c, default_face); @@ -7078,8 +7131,9 @@ realize_x_face (cache, attrs, c, base_face) int c; struct face *base_face; { + struct face *face = NULL; #ifdef HAVE_WINDOW_SYSTEM - struct face *face, *default_face; + struct face *default_face; struct frame *f; Lisp_Object stipple, overline, strike_through, box; @@ -7275,8 +7329,8 @@ realize_x_face (cache, attrs, c, base_face) face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h); xassert (FACE_SUITABLE_FOR_CHAR_P (face, c)); - return face; #endif /* HAVE_WINDOW_SYSTEM */ + return face; } @@ -7692,6 +7746,69 @@ face_at_string_position (w, string, pos, bufpos, region_beg, } +/* Merge a face into a realized face. + + F is frame where faces are (to be) realized. + + FACE_NAME is named face to merge. + + If FACE_NAME is nil, FACE_ID is face_id of realized face to merge. + + If FACE_NAME is t, FACE_ID is lface_id of face to merge. + + BASE_FACE_ID is realized face to merge into. + + Return new face id. +*/ + +int +merge_faces (f, face_name, face_id, base_face_id) + struct frame *f; + Lisp_Object face_name; + int face_id, base_face_id; +{ + Lisp_Object attrs[LFACE_VECTOR_SIZE]; + struct face *base_face; + + base_face = FACE_FROM_ID (f, base_face_id); + if (!base_face) + return base_face_id; + + if (EQ (face_name, Qt)) + { + if (face_id < 0 || face_id >= lface_id_to_name_size) + return base_face_id; + face_name = lface_id_to_name[face_id]; + face_id = lookup_derived_face (f, face_name, 0, base_face_id, 1); + if (face_id >= 0) + return face_id; + return base_face_id; + } + + /* Begin with attributes from the base face. */ + bcopy (base_face->lface, attrs, sizeof attrs); + + if (!NILP (face_name)) + { + if (!merge_named_face (f, face_name, attrs, 0)) + return base_face_id; + } + else + { + struct face *face; + if (face_id < 0) + return base_face_id; + face = FACE_FROM_ID (f, face_id); + if (!face) + return base_face_id; + merge_face_vectors (f, face->lface, attrs, 0); + } + + /* Look up a realized face with the given face attributes, + or realize a new one for ASCII characters. */ + return lookup_face (f, attrs, 0, NULL); +} + /*********************************************************************** Tests @@ -7707,7 +7824,7 @@ dump_realized_face (face) { fprintf (stderr, "ID: %d\n", face->id); #ifdef HAVE_X_WINDOWS - fprintf (stderr, "gc: %d\n", (int) face->gc); + fprintf (stderr, "gc: %ld\n", (long) face->gc); #endif fprintf (stderr, "foreground: 0x%lx (%s)\n", face->foreground,