Mercurial > hg > xemacs-beta
comparison src/faces.c @ 446:1ccc32a20af4 r21-2-38
Import from CVS: tag r21-2-38
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:37:21 +0200 |
parents | 576fb035e263 |
children | 0784d089fdc9 |
comparison
equal
deleted
inserted
replaced
445:34f3776fcf0e | 446:1ccc32a20af4 |
---|---|
1152 fm->width = fi->width; | 1152 fm->width = fi->width; |
1153 } | 1153 } |
1154 } | 1154 } |
1155 } | 1155 } |
1156 | 1156 |
1157 /* Called when the updated flag has been cleared on a cachel. */ | |
1158 | |
1159 void | |
1160 update_face_cachel_data (struct face_cachel *cachel, | |
1161 Lisp_Object domain, | |
1162 Lisp_Object face) | |
1163 { | |
1164 if (XFACE (face)->dirty || UNBOUNDP (cachel->face)) | |
1165 { | |
1166 int default_face = EQ (face, Vdefault_face); | |
1167 cachel->face = face; | |
1168 | |
1169 /* We normally only set the _specified flags if the value was | |
1170 actually bound. The exception is for the default face where | |
1171 we always set it since it is the ultimate fallback. */ | |
1172 | |
1173 #define FROB(field) \ | 1157 #define FROB(field) \ |
1174 do { \ | 1158 do { \ |
1175 Lisp_Object new_val = \ | 1159 Lisp_Object new_val = \ |
1176 FACE_PROPERTY_INSTANCE (face, Q##field, domain, 1, Qzero); \ | 1160 FACE_PROPERTY_INSTANCE (face, Q##field, domain, 1, Qzero); \ |
1177 int bound = 1; \ | 1161 int bound = 1; \ |
1186 cachel->dirty = 1; \ | 1170 cachel->dirty = 1; \ |
1187 } \ | 1171 } \ |
1188 cachel->field##_specified = (bound || default_face); \ | 1172 cachel->field##_specified = (bound || default_face); \ |
1189 } while (0) | 1173 } while (0) |
1190 | 1174 |
1175 /* | |
1176 * A face's background pixmap will override the face's | |
1177 * background color. But the background pixmap of the | |
1178 * default face should not override the background color of | |
1179 * a face if the background color has been specified or | |
1180 * inherited. | |
1181 * | |
1182 * To accomplish this we remove the background pixmap of the | |
1183 * cachel and mark it as having been specified so that cachel | |
1184 * merging won't override it later. | |
1185 */ | |
1186 #define MAYBE_UNFROB_BACKGROUND_PIXMAP \ | |
1187 do \ | |
1188 { \ | |
1189 if (! default_face \ | |
1190 && cachel->background_specified \ | |
1191 && ! cachel->background_pixmap_specified) \ | |
1192 { \ | |
1193 cachel->background_pixmap = Qunbound; \ | |
1194 cachel->background_pixmap_specified = 1; \ | |
1195 } \ | |
1196 } while (0) | |
1197 | |
1198 | |
1199 /* Add a cachel for the given face to the given window's cache. */ | |
1200 | |
1201 static void | |
1202 add_face_cachel (struct window *w, Lisp_Object face) | |
1203 { | |
1204 int must_finish_frobbing = ! WINDOW_FACE_CACHEL (w, DEFAULT_INDEX); | |
1205 struct face_cachel new_cachel; | |
1206 Lisp_Object domain; | |
1207 | |
1208 reset_face_cachel (&new_cachel); | |
1209 XSETWINDOW (domain, w); | |
1210 update_face_cachel_data (&new_cachel, domain, face); | |
1211 Dynarr_add (w->face_cachels, new_cachel); | |
1212 | |
1213 /* The face's background pixmap have not yet been frobbed (see comment | |
1214 int update_face_cachel_data), so we have to do it now */ | |
1215 if (must_finish_frobbing) | |
1216 { | |
1217 int default_face = EQ (face, Vdefault_face); | |
1218 struct face_cachel *cachel | |
1219 = Dynarr_atp (w->face_cachels, Dynarr_length (w->face_cachels) - 1); | |
1220 | |
1221 FROB (background_pixmap); | |
1222 MAYBE_UNFROB_BACKGROUND_PIXMAP; | |
1223 } | |
1224 } | |
1225 | |
1226 /* Called when the updated flag has been cleared on a cachel. | |
1227 This function returns 1 if the caller must finish the update (see comment | |
1228 below), 0 otherwise. | |
1229 */ | |
1230 | |
1231 void | |
1232 update_face_cachel_data (struct face_cachel *cachel, | |
1233 Lisp_Object domain, | |
1234 Lisp_Object face) | |
1235 { | |
1236 if (XFACE (face)->dirty || UNBOUNDP (cachel->face)) | |
1237 { | |
1238 int default_face = EQ (face, Vdefault_face); | |
1239 cachel->face = face; | |
1240 | |
1241 /* We normally only set the _specified flags if the value was | |
1242 actually bound. The exception is for the default face where | |
1243 we always set it since it is the ultimate fallback. */ | |
1244 | |
1191 FROB (foreground); | 1245 FROB (foreground); |
1192 FROB (background); | 1246 FROB (background); |
1193 FROB (display_table); | 1247 FROB (display_table); |
1194 FROB (background_pixmap); | 1248 |
1195 | 1249 /* #### WARNING: the background pixmap property of faces is currently |
1196 /* | 1250 the only one dealing with images. The problem we have here is that |
1197 * A face's background pixmap will override the face's | 1251 frobbing the background pixmap might lead to image instantiation |
1198 * background color. But the background pixmap of the | 1252 which in turn might require that the cache we're building be up to |
1199 * default face should not override the background color of | 1253 date, hence a crash. Here's a typical scenario of this: |
1200 * a face if the background color has been specified or | 1254 |
1201 * inherited. | 1255 - a new window is created and it's face cache elements are |
1202 * | 1256 initialized through a call to reset_face_cachels[1]. At that point, |
1203 * To accomplish this we remove the background pixmap of the | 1257 the cache for the default and modeline faces (normaly taken care of |
1204 * cachel and mark it as having been specified so that cachel | 1258 by redisplay itself) are null. |
1205 * merging won't override it later. | 1259 - the default face has a background pixmap which needs to be |
1206 */ | 1260 instantiated right here, as a consequence of cache initialization. |
1207 if (! default_face | 1261 - the background pixmap image happens to be instantiated as a string |
1208 && cachel->background_specified | 1262 (this happens on tty's for instance). |
1209 && ! cachel->background_pixmap_specified) | 1263 - In order to do this, we need to compute the string geometry. |
1264 - In order to do this, we might have to access the window's default | |
1265 face cache. But this is the cache we're building right now, it is | |
1266 null. | |
1267 - BARF !!!!! | |
1268 | |
1269 To sum up, this means that it is in general unsafe to instantiate | |
1270 images before face cache updating is complete (appart from image | |
1271 related face attributes). The solution we use below is to actually | |
1272 detect whether we're building the window's face_cachels for the first | |
1273 time, and simply NOT frob the background pixmap in that case. If | |
1274 other image-related face attributes are ever implemented, they should | |
1275 be protected the same way right here. | |
1276 | |
1277 One note: | |
1278 * See comment in `default_face_font_info' in face.c. Who wrote it ? | |
1279 Maybe we have the begining of an answer here ? | |
1280 | |
1281 Footnotes: | |
1282 [1] See comment at the top of `allocate_window' in window.c. | |
1283 | |
1284 -- didier | |
1285 */ | |
1286 if (! WINDOWP (domain) | |
1287 || WINDOW_FACE_CACHEL (DOMAIN_XWINDOW (domain), DEFAULT_INDEX)) | |
1210 { | 1288 { |
1211 cachel->background_pixmap = Qunbound; | 1289 FROB (background_pixmap); |
1212 cachel->background_pixmap_specified = 1; | 1290 MAYBE_UNFROB_BACKGROUND_PIXMAP; |
1213 } | 1291 } |
1214 | |
1215 #undef FROB | 1292 #undef FROB |
1293 #undef MAYBE_UNFROB_BACKGROUND_PIXMAP | |
1216 | 1294 |
1217 ensure_face_cachel_contains_charset (cachel, domain, Vcharset_ascii); | 1295 ensure_face_cachel_contains_charset (cachel, domain, Vcharset_ascii); |
1218 | 1296 |
1219 #define FROB(field) \ | 1297 #define FROB(field) \ |
1220 do { \ | 1298 do { \ |
1315 } | 1393 } |
1316 cachel->display_table = Qunbound; | 1394 cachel->display_table = Qunbound; |
1317 cachel->background_pixmap = Qunbound; | 1395 cachel->background_pixmap = Qunbound; |
1318 } | 1396 } |
1319 | 1397 |
1320 /* Add a cachel for the given face to the given window's cache. */ | |
1321 | |
1322 static void | |
1323 add_face_cachel (struct window *w, Lisp_Object face) | |
1324 { | |
1325 struct face_cachel new_cachel; | |
1326 Lisp_Object window; | |
1327 | |
1328 reset_face_cachel (&new_cachel); | |
1329 XSETWINDOW (window, w); | |
1330 update_face_cachel_data (&new_cachel, window, face); | |
1331 Dynarr_add (w->face_cachels, new_cachel); | |
1332 } | |
1333 | |
1334 /* Retrieve the index to a cachel for window W that corresponds to | 1398 /* Retrieve the index to a cachel for window W that corresponds to |
1335 the specified face. If necessary, add a new element to the | 1399 the specified face. If necessary, add a new element to the |
1336 cache. */ | 1400 cache. */ |
1337 | 1401 |
1338 face_index | 1402 face_index |