#include <string.h>
#include <ctype.h>
+#include "config.h"
#include "m17n-gui.h"
#include "m17n-misc.h"
#include "internal.h"
static M17NObjectArray face_table;
-static MSymbol Mlatin;
+MSymbol Mlatin;
static MSymbol M_face_prop_index;
-/** Find a realized face registered on FRAME that is realized from
- FACE and using font RFONT. If RFONT is NULL, find any that
- matches FACE. */
+static MPlist *hline_prop_list;
+static MPlist *box_prop_list;
+
+/** Special hook function pointer that does nothing. */
+static MFaceHookFunc noop_hook;
+
+/** */
+static MFaceHLineProp *
+get_hline_create (MFaceHLineProp *prop)
+{
+ MPlist *plist;
+ MFaceHLineProp *hline;
+
+ if (prop->width == 0)
+ return MPLIST_VAL (hline_prop_list);
+ MPLIST_DO (plist, MPLIST_NEXT (hline_prop_list))
+ {
+ hline = MPLIST_VAL (plist);
+ if (prop->type == hline->type
+ && prop->width == hline->width
+ && prop->color == hline->color)
+ return hline;
+ }
+ MSTRUCT_MALLOC (hline, MERROR_FACE);
+ *hline = *prop;
+ mplist_push (plist, Mt, hline);
+ return hline;
+}
+
+static MFaceBoxProp *
+get_box_create (MFaceBoxProp *prop)
+{
+ MPlist *plist;
+ MFaceBoxProp *box;
+
+ if (prop->width == 0)
+ return MPLIST_VAL (box_prop_list);
+ MPLIST_DO (plist, MPLIST_NEXT (box_prop_list))
+ {
+ box = MPLIST_VAL (plist);
+ if (prop->width == box->width
+ && prop->color_top == box->color_top
+ && prop->color_bottom == box->color_bottom
+ && prop->color_left == box->color_left
+ && prop->color_right == box->color_right
+ && prop->inner_hmargin == box->inner_hmargin
+ && prop->inner_vmargin == box->inner_vmargin
+ && prop->outer_hmargin == box->inner_hmargin
+ && prop->inner_vmargin == box->inner_vmargin)
+ return box;
+ }
+ MSTRUCT_MALLOC (box, MERROR_FACE);
+ *box = *prop;
+ mplist_push (plist, Mt, box);
+ return box;
+}
+
+/** From FRAME->realized_face_list, find a realized face based on
+ FACE. */
static MRealizedFace *
-find_realized_face (MFrame *frame, MFace *face, MRealizedFont *rfont)
+find_realized_face (MFrame *frame, MFace *face)
{
- MPlist *rface_list;
- MRealizedFace *rface;
- int i;
+ MPlist *plist;
- MPLIST_DO (rface_list, frame->realized_face_list)
+ MPLIST_DO (plist, frame->realized_face_list)
{
- rface = MPLIST_VAL (rface_list);
- if (! rfont
- || rface->rfont == rfont)
- {
- for (i = 0; i < MFACE_RATIO; i++)
- if (rface->face.property[i] != face->property[i])
- break;
- if (i == MFACE_RATIO)
- return rface;
- }
+ MRealizedFace *rface = MPLIST_VAL (plist);
+
+ if (memcmp (rface->face.property, face->property, sizeof face->property)
+ == 0)
+ return rface;
}
return NULL;
}
if (face->property[MFACE_FONTSET])
M17N_OBJECT_UNREF (face->property[MFACE_FONTSET]);
- if (face->property[MFACE_HLINE])
- free (face->property[MFACE_HLINE]);
- if (face->property[MFACE_BOX])
- free (face->property[MFACE_BOX]);
+ M17N_OBJECT_UNREF (face->frame_list);
M17N_OBJECT_UNREGISTER (face_table, face);
free (object);
}
static MPlist *
serialize_hline (MPlist *plist, MFaceHLineProp *hline)
{
- MPlist *pl = mplist ();
+ if (hline->width > 0)
+ {
+ MPlist *pl = mplist ();
- mplist_add (pl, Minteger, (void *) hline->type);
- mplist_add (pl, Minteger, (void *) hline->width);
- mplist_add (pl, Msymbol, hline->color);
- plist = mplist_add (plist, Mplist, pl);
- M17N_OBJECT_UNREF (pl);
+ mplist_add (pl, Minteger, (void *) hline->type);
+ mplist_add (pl, Minteger, (void *) hline->width);
+ mplist_add (pl, Msymbol, hline->color);
+ plist = mplist_add (plist, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
+ }
return plist;
}
static MPlist *
serialize_box (MPlist *plist, MFaceBoxProp *box)
{
- MPlist *pl = mplist ();
-
- mplist_add (pl, Minteger, (void *) box->width);
- mplist_add (pl, Minteger, (void *) box->inner_hmargin);
- mplist_add (pl, Minteger, (void *) box->inner_vmargin);
- mplist_add (pl, Minteger, (void *) box->outer_hmargin);
- mplist_add (pl, Minteger, (void *) box->outer_vmargin);
- mplist_add (pl, Msymbol, box->color_top);
- mplist_add (pl, Msymbol, box->color_bottom);
- mplist_add (pl, Msymbol, box->color_left);
- mplist_add (pl, Msymbol, box->color_right);
- plist = mplist_add (plist, Mplist, pl);
- M17N_OBJECT_UNREF (pl);
+ if (box->width > 0)
+ {
+ MPlist *pl = mplist ();
+
+ mplist_add (pl, Minteger, (void *) box->width);
+ mplist_add (pl, Minteger, (void *) box->inner_hmargin);
+ mplist_add (pl, Minteger, (void *) box->inner_vmargin);
+ mplist_add (pl, Minteger, (void *) box->outer_hmargin);
+ mplist_add (pl, Minteger, (void *) box->outer_vmargin);
+ mplist_add (pl, Msymbol, box->color_top);
+ mplist_add (pl, Msymbol, box->color_bottom);
+ mplist_add (pl, Msymbol, box->color_left);
+ mplist_add (pl, Msymbol, box->color_right);
+ plist = mplist_add (plist, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
+ }
return plist;
}
mface__init ()
{
int i;
+ MFaceHLineProp *hline;
+ MFaceBoxProp *box;
face_table.count = 0;
Mface = msymbol_as_managing_key ("face");
(void *) (mface_prop_data[i].index + 1));
}
+ hline_prop_list = mplist ();
+ MSTRUCT_CALLOC (hline, MERROR_FACE);
+ mplist_push (hline_prop_list, Mt, hline);
+ box_prop_list = mplist ();
+ MSTRUCT_CALLOC (box, MERROR_FACE);
+ mplist_push (box_prop_list, Mt, box);
+
mface__default = mface ();
+ mface__default->property[MFACE_FOUNDRY] = msymbol ("misc");
+ mface__default->property[MFACE_FAMILY] = msymbol ("fixed");
mface__default->property[MFACE_WEIGHT] = msymbol ("medium");
mface__default->property[MFACE_STYLE] = msymbol ("r");
mface__default->property[MFACE_STRETCH] = msymbol ("normal");
+ mface__default->property[MFACE_ADSTYLE] = msymbol ("");
mface__default->property[MFACE_SIZE] = (void *) 120;
mface__default->property[MFACE_FONTSET] = mfontset (NULL);
- M17N_OBJECT_REF (mface__default->property[MFACE_FONTSET]);
- /* mface__default->property[MFACE_FOREGROUND] =msymbol ("black"); */
- /* mface__default->property[MFACE_BACKGROUND] =msymbol ("white"); */
+ mface__default->property[MFACE_FOREGROUND] = msymbol ("black");
+ mface__default->property[MFACE_BACKGROUND] = msymbol ("white");
+ mface__default->property[MFACE_HLINE] = hline;
+ mface__default->property[MFACE_BOX] = box;
+ mface__default->property[MFACE_VIDEOMODE] = Mnormal;
+ mface__default->property[MFACE_HOOK_FUNC] = (void *) noop_hook;
mface_normal_video = mface ();
mface_normal_video->property[MFACE_VIDEOMODE] = (void *) Mnormal;
mface_reverse_video->property[MFACE_VIDEOMODE] = (void *) Mreverse;
{
- MFaceHLineProp *hline_prop;
+ MFaceHLineProp hline_prop;
- MSTRUCT_MALLOC (hline_prop, MERROR_FACE);
- hline_prop->type = MFACE_HLINE_UNDER;
- hline_prop->width = 1;
- hline_prop->color = Mnil;
+ hline_prop.type = MFACE_HLINE_UNDER;
+ hline_prop.width = 1;
+ hline_prop.color = Mnil;
mface_underline = mface ();
- mface_underline->property[MFACE_HLINE] = (void *) hline_prop;
+ mface_put_prop (mface_underline, Mhline, &hline_prop);
}
mface_medium = mface ();
void
mface__fini ()
{
+ MPlist *plist;
+
M17N_OBJECT_UNREF (mface__default);
M17N_OBJECT_UNREF (mface_normal_video);
M17N_OBJECT_UNREF (mface_reverse_video);
M17N_OBJECT_UNREF (mface_cyan);
M17N_OBJECT_UNREF (mface_yellow);
M17N_OBJECT_UNREF (mface_magenta);
+
+ MPLIST_DO (plist, hline_prop_list)
+ free (MPLIST_VAL (plist));
+ M17N_OBJECT_UNREF (hline_prop_list);
+ MPLIST_DO (plist, box_prop_list)
+ free (MPLIST_VAL (plist));
+ M17N_OBJECT_UNREF (box_prop_list);
+
free (work_gstring.glyphs);
mdebug__report_object ("Face", &face_table);
base faces pointed by FACES on the frame FRAME. */
MRealizedFace *
-mface__realize (MFrame *frame, MFace **faces, int num,
- MSymbol language, MSymbol charset, int size)
+mface__realize (MFrame *frame, MFace **faces, int num, int size)
{
MRealizedFace *rface;
MRealizedFont *rfont;
MFace merged_face = *(frame->face);
void **props;
int i, j;
- unsigned tick;
MGlyph g;
+ MFaceHookFunc func;
- if (num == 0 && language == Mnil && charset == Mnil && frame->rface)
+ if (num == 0 && frame->rface)
return frame->rface;
for (i = 0; i < MFACE_PROPERTY_MAX; i++)
break;
}
- for (i = 0, tick = 0; i < num; i++)
- tick += faces[i]->tick;
+ if (! mplist_find_by_value (frame->face->frame_list, frame))
+ mplist_push (frame->face->frame_list, Mt, frame);
+ for (i = 0; i < num; i++)
+ if (! mplist_find_by_value (faces[i]->frame_list, frame))
+ mplist_push (faces[i]->frame_list, Mt, frame);
if (merged_face.property[MFACE_RATIO])
{
font_size *= (int) merged_face.property[MFACE_RATIO];
font_size /= 100;
merged_face.property[MFACE_SIZE] = (void *) font_size;
+ merged_face.property[MFACE_RATIO] = 0;
}
- rface = find_realized_face (frame, &merged_face, NULL);
- if (rface && rface->tick == tick)
- return rface->ascii_rface;
+ rface = find_realized_face (frame, &merged_face);
+ if (rface)
+ return rface;
MSTRUCT_CALLOC (rface, MERROR_FACE);
+ mplist_push (frame->realized_face_list, Mt, rface);
rface->frame = frame;
rface->face = merged_face;
- rface->tick = tick;
props = rface->face.property;
-
rface->rfontset = mfont__realize_fontset (frame,
(MFontset *) props[MFACE_FONTSET],
&merged_face);
+ g.type = GLYPH_SPACE;
g.c = ' ';
num = 1;
rfont = mfont__lookup_fontset (rface->rfontset, &g, &num,
- msymbol ("latin"), language, Mnil,
- size);
-
+ Mlatin, Mnil, Mnil, size);
if (rfont)
{
rface->rfont = rfont;
g.otf_encoded = 0;
+ work_gstring.frame = frame;
work_gstring.glyphs[0] = g;
work_gstring.glyphs[0].rface = rface;
work_gstring.glyphs[1].code = MCHAR_INVALID_CODE;
}
rface->hline = (MFaceHLineProp *) props[MFACE_HLINE];
+ if (rface->hline && rface->hline->width == 0)
+ rface->hline = NULL;
rface->box = (MFaceBoxProp *) props[MFACE_BOX];
+ if (rface->box && rface->box->width == 0)
+ rface->box = NULL;
rface->ascii_rface = rface;
- mwin__realize_face (rface);
+ (*frame->driver->realize_face) (rface);
- mplist_add (frame->realized_face_list, Mt, rface);
+ func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC];
+ if (func && func != noop_hook)
+ (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]);
+ rface->non_ascii_list = mplist ();
if (rface->rfont)
{
- MSTRUCT_CALLOC (rface->nofont_rface, MERROR_FACE);
- *rface->nofont_rface = *rface;
- rface->nofont_rface->rfont = NULL;
+ MRealizedFace *nofont;
+
+ MSTRUCT_CALLOC (nofont, MERROR_FACE);
+ *nofont = *rface;
+ nofont->non_ascii_list = NULL;
+ nofont->rfont = NULL;
+ mplist_add (rface->non_ascii_list, Mt, nofont);
}
- else
- rface->nofont_rface = rface;
return rface;
}
mface__for_chars (MSymbol script, MSymbol language, MSymbol charset,
MGlyph *from_g, MGlyph *to_g, int size)
{
- MRealizedFace *rface;
MRealizedFont *rfont;
- int num = to_g - from_g, i;
+ int num = to_g - from_g;
rfont = mfont__lookup_fontset (from_g->rface->rfontset, from_g, &num,
script, language, charset, size);
if (! rfont)
+ num = 1;
+
+ to_g = from_g + num;
+ while (from_g < to_g)
{
- from_g->rface = from_g->rface->nofont_rface;
- return (from_g + 1);
- }
- rface = find_realized_face (from_g->rface->frame, &(from_g->rface->face),
- rfont);
- if (! rface)
- {
- MSTRUCT_MALLOC (rface, MERROR_FACE);
- *rface = *from_g->rface->ascii_rface;
- rface->rfont = rfont;
- {
- work_gstring.glyphs[0].code = MCHAR_INVALID_CODE;
- work_gstring.glyphs[0].rface = rface;
- mfont__get_metric (&work_gstring, 0, 1);
- rface->ascent = work_gstring.glyphs[0].ascent;
- rface->descent = work_gstring.glyphs[0].descent;
- }
- mwin__realize_face (rface);
- mplist_add (from_g->rface->frame->realized_face_list, Mt, rface);
- }
+ MGlyph *g = from_g;
+ MRealizedFace *rface = from_g++->rface;
- for (i = 0; i < num; i++, from_g++)
- from_g->rface = rface;
- return from_g;
+ while (from_g < to_g && rface == from_g->rface) from_g++;
+ if (rface->rfont != rfont)
+ {
+ MPlist *plist = mplist_find_by_value (rface->non_ascii_list, rfont);
+ MRealizedFace *new;
+
+ if (plist)
+ new = MPLIST_VAL (plist);
+ else
+ {
+ MSTRUCT_MALLOC (new, MERROR_FACE);
+ mplist_push (rface->non_ascii_list, Mt, new);
+ *new = *rface;
+ new->rfont = rfont;
+ new->non_ascii_list = NULL;
+ if (rfont)
+ {
+ new->ascent = rfont->ascent;
+ new->descent = rfont->descent;
+ }
+ }
+ while (g < from_g)
+ g++->rface = new;
+ }
+ }
+ return to_g;
}
void
mface__free_realized (MRealizedFace *rface)
{
- mwin__free_realized_face (rface);
- if (rface == rface->ascii_rface)
- {
- if (! rface->nofont_rface)
- mdebug_hook ();
- else
- free (rface->nofont_rface);
- rface->nofont_rface = NULL;
- }
+ MPlist *plist;
+
+ MPLIST_DO (plist, rface->non_ascii_list)
+ free (MPLIST_VAL (plist));
+ M17N_OBJECT_UNREF (rface->non_ascii_list);
free (rface);
}
+void
+mface__update_frame_face (MFrame *frame)
+{
+ frame->rface = NULL;
+ frame->rface = mface__realize (frame, NULL, 0, 0);
+ frame->space_width = frame->rface->space_width;
+ frame->ascent = frame->rface->ascent;
+ frame->descent = frame->rface->descent;
+}
+
/*** @} */
#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
MFace *face;
M17N_OBJECT (face, free_face, MERROR_FACE);
+ face->frame_list = mplist ();
M17N_OBJECT_REGISTER (face_table, face);
return face;
}
*copy = *face;
copy->control.ref_count = 1;
M17N_OBJECT_REGISTER (face_table, copy);
+ copy->frame_list = mplist ();
if (copy->property[MFACE_FONTSET])
M17N_OBJECT_REF (copy->property[MFACE_FONTSET]);
- if (copy->property[MFACE_HLINE])
- {
- MFaceHLineProp *val;
-
- MSTRUCT_MALLOC (val, MERROR_FACE);
- *val = *((MFaceHLineProp *) copy->property[MFACE_HLINE]);
- copy->property[MFACE_HLINE] = val;
- }
- if (copy->property[MFACE_BOX])
- {
- MFaceBoxProp *val;
-
- MSTRUCT_MALLOC (val, MERROR_FACE);
- *val = *((MFaceBoxProp *) copy->property[MFACE_BOX]);
- copy->property[MFACE_BOX] = val;
- }
-
return copy;
}
mface_merge (MFace *dst, MFace *src)
{
int i;
+ MPlist *plist;
for (i = 0; i < MFACE_PROPERTY_MAX; i++)
if (src->property[i])
{
- dst->property[i] = src->property[i];
if (i == MFACE_FONTSET)
- M17N_OBJECT_REF (dst->property[i]);
- else if (i == MFACE_HLINE)
- {
- MFaceHLineProp *val;
-
- MSTRUCT_MALLOC (val, MERROR_FACE);
- *val = *((MFaceHLineProp *) dst->property[MFACE_HLINE]);
- dst->property[MFACE_HLINE] = val;
- }
- else if (i == MFACE_BOX)
{
- MFaceBoxProp *val;
-
- MSTRUCT_MALLOC (val, MERROR_FACE);
- *val = *((MFaceBoxProp *) dst->property[MFACE_BOX]);
- dst->property[MFACE_BOX] = val;
+ M17N_OBJECT_UNREF (dst->property[i]);
+ M17N_OBJECT_REF (src->property[i]);
}
+ dst->property[i] = src->property[i];
}
+
+ MPLIST_DO (plist, dst->frame_list)
+ {
+ MFrame *frame = MPLIST_VAL (plist);
+
+ frame->tick++;
+ if (dst == frame->face)
+ mface__update_frame_face (frame);
+ }
+
return dst;
}
mface_put_prop (MFace *face, MSymbol key, void *val)
{
int index = (int) msymbol_get (key, M_face_prop_index) - 1;
+ MPlist *plist;
if (index < 0)
MERROR (MERROR_FACE, -1);
if (key == Mfontset)
- M17N_OBJECT_REF (val);
- else if (key == Mhline)
{
- MFaceHLineProp *newval;
-
- MSTRUCT_MALLOC (newval, MERROR_FACE);
- *newval = *((MFaceHLineProp *) val);
- val = newval;
+ if (face->property[index])
+ M17N_OBJECT_UNREF (face->property[index]);
+ M17N_OBJECT_REF (val);
}
+ else if (key == Mhline)
+ val = get_hline_create (val);
else if (key == Mbox)
+ val = get_box_create (val);
+
+ if (face->property[index] == val)
+ return 0;
+ face->property[index] = val;
+
+ MPLIST_DO (plist, face->frame_list)
{
- MFaceBoxProp *newval;
+ MFrame *frame = MPLIST_VAL (plist);
- MSTRUCT_MALLOC (newval, MERROR_FACE);
- *newval = *((MFaceBoxProp *) val);
- val = newval;
+ frame->tick++;
+ if (face == frame->face)
+ mface__update_frame_face (frame);
}
- face->property[index] = val;
- face->tick++;
return 0;
}
MPlist *rface_list;
MRealizedFace *rface;
- if (func)
+ if (func && func != noop_hook)
{
MPLIST_DO (rface_list, frame->realized_face_list)
{