+BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ Arg arg[1];
+
+ reversed = ! reversed;
+ if (reversed)
+ XtSetArg (arg[0], XtNlabel, "L<-R");
+ else
+ XtSetArg (arg[0], XtNlabel, "L->R");
+ XtSetValues (w, arg, 1);
+ update_seq_area ();
+}
+
+void
+AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ do_alternate_subst = ! do_alternate_subst;
+ update_seq_area ();
+}
+
+void
+FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ FeatureRec *rec = (FeatureRec *) client_data;
+ int idx, i, j;
+ Arg arg[4];
+ char *label;
+
+ if (! rec->langsys)
+ return;
+ XtSetArg (arg[0], XtNlabel, &label);
+ XtGetValues (w, arg, 1);
+ if (! strcmp (label, "all"))
+ idx = -2;
+ else if (! strcmp (label, "none"))
+ idx = -1;
+ else
+ {
+ for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
+ if (rec->features[idx].w == w)
+ break;
+ if (idx == rec->langsys->FeatureCount)
+ idx = -1;
+ }
+ if (idx < 0)
+ {
+ int on = idx == -2;
+ char str[5];
+
+ for (i = 0; i < rec->langsys->FeatureCount; i++)
+ if (rec->features[i].on != on)
+ {
+ rec->features[i].on = on;
+ if (on)
+ {
+ XtSetArg (arg[0], XtNborderWidth, 3);
+ XtSetArg (arg[1], XtNinternalHeight, 2);
+ XtSetArg (arg[2], XtNinternalWidth, 2);
+ }
+ else
+ {
+ XtSetArg (arg[0], XtNborderWidth, 1);
+ XtSetArg (arg[1], XtNinternalHeight, 4);
+ XtSetArg (arg[2], XtNinternalWidth, 4);
+ }
+ OTF_tag_name (rec->features[i].tag, str);
+ XtSetArg (arg[3], XtNlabel, str);
+ XtSetValues (rec->features[i].w, arg, 4);
+ }
+ }
+ else
+ {
+ char str[5];
+
+ rec->features[idx].on = ! rec->features[idx].on;
+ if (rec->features[idx].on)
+ {
+ XtSetArg (arg[0], XtNborderWidth, 3);
+ XtSetArg (arg[1], XtNinternalHeight, 2);
+ XtSetArg (arg[2], XtNinternalWidth, 2);
+ }
+ else
+ {
+ XtSetArg (arg[0], XtNborderWidth, 1);
+ XtSetArg (arg[1], XtNinternalHeight, 4);
+ XtSetArg (arg[2], XtNinternalWidth, 4);
+ }
+ OTF_tag_name (rec->features[idx].tag, str);
+ XtSetArg (arg[3], XtNlabel, str);
+ XtSetValues (rec->features[idx].w, arg, 4);
+ }
+ update_seq_area ();
+}
+
+void
+setup_feature_rec (FeatureRec *rec)
+{
+ int i, j;
+ Arg arg[10];
+
+ rec->langsys = NULL;
+ if (! rec->gsub_gpos)
+ return;
+ for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
+ if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
+ {
+ OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
+
+ if (langsys_tag)
+ {
+ for (j = 0; j < script->LangSysCount; j++)
+ if (script->LangSysRecord[j].LangSysTag == langsys_tag)
+ {
+ rec->langsys = script->LangSys + j;
+ break;
+ }
+ }
+ if (! rec->langsys)
+ rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
+ break;
+ }
+
+ if (! rec->langsys)
+ i = 0;
+ else
+ {
+ XtSetArg (arg[0], XtNborderWidth, 1);
+ XtSetArg (arg[1], XtNinternalHeight, 4);
+ XtSetArg (arg[2], XtNinternalWidth, 4);
+ XtSetArg (arg[3], XtNborderColor, foreground);
+ XtSetArg (arg[4], XtNsensitive, True);
+ for (i = 0; i < rec->langsys->FeatureCount; i++)
+ {
+ OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
+ int index = rec->langsys->FeatureIndex[i];
+ char label[5];
+
+ if (! rec->features[i].w)
+ {
+ Widget w = XtCreateManagedWidget ("", commandWidgetClass,
+ rec->parent, arg, 0);
+ XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
+ rec->features[i].w = w;
+ }
+
+ rec->features[i].tag = feature[index].FeatureTag;
+ rec->features[i].on = 0;
+ OTF_tag_name (rec->features[i].tag, label);
+ XtSetArg (arg[5], XtNlabel, label);
+ XtSetValues (rec->features[i].w, arg, 6);
+ }
+ }
+ XtSetArg (arg[0], XtNborderColor, background);
+ XtSetArg (arg[1], XtNsensitive, False);
+ XtSetArg (arg[2], XtNlabel, " ");
+ for (; i < rec->num_features; i++)
+ {
+ if (! rec->features[i].w)
+ {
+ Widget w = XtCreateManagedWidget ("", commandWidgetClass,
+ rec->parent, arg, 0);
+ XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
+ rec->features[i].w = w;
+ }
+ XtSetValues (rec->features[i].w, arg, 3);
+ }
+}
+
+void
+compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
+{
+ OTF_tag_name (script, name);
+ if (langsys)
+ {
+ name[4] = '(';
+ OTF_tag_name (langsys, name + 5);
+ name[9] = ')';
+ name[10] = '\0';
+ }
+}
+
+void
+decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
+{
+ *script = OTF_tag (name);
+ if (name[4])
+ *langsys = OTF_tag (name + 5);
+ else
+ *langsys = 0;
+}
+
+void
+ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ char *name;
+ OTF_Tag script, langsys;
+ Arg arg[1];
+
+ XtSetArg (arg[0], XtNlabel, &name);
+ XtGetValues (w, arg, 1);
+ decompose_script_langsys (&script, &langsys, name);
+ if (script_tag == script && langsys_tag == langsys)
+ return;
+ script_tag = script;
+ langsys_tag = langsys;
+ setup_feature_rec (&gsub);
+ setup_feature_rec (&gpos);
+ update_seq_area ();
+}
+
+Widget
+create_otf_script_widgets (Widget prev)
+{
+ Widget w;
+ Arg arg[10];
+ int n, prev_n, i, j;
+ struct {
+ OTF_Tag script;
+ OTF_Tag langsys;
+ } *script_langsys;
+ char name[11];
+ int nfeatures;
+
+ XtSetArg (arg[0], XtNborderWidth, 0);
+ XtSetArg (arg[1], XtNleft, XawChainLeft);
+ XtSetArg (arg[2], XtNright, XawChainLeft);
+ XtSetArg (arg[3], XtNtop, XawChainTop);
+ XtSetArg (arg[4], XtNbottom, XawChainTop);
+ XtSetArg (arg[5], XtNfromVert, prev);
+ XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
+ prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
+ XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
+
+ n = 0;
+ if (otf->gsub)
+ for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
+ n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
+ if (otf->gpos)
+ for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
+ n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
+ script_langsys = alloca ((sizeof script_langsys[0]) * n);
+ n = 0;
+ nfeatures = 0;
+ if (otf->gsub)
+ for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
+ {
+ OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
+
+ script_langsys[n].script = tag;
+ script_langsys[n++].langsys = 0;
+ if (nfeatures
+ < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
+ nfeatures
+ = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
+ for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
+ {
+ script_langsys[n].script = tag;
+ script_langsys[n++].langsys
+ = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
+ if (nfeatures
+ < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
+ nfeatures
+ = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
+ }
+ }
+ gsub.num_features = nfeatures;
+ if (nfeatures > 0)
+ {
+ gsub.num_features = nfeatures;
+ gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
+ memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
+ }
+ prev_n = n;
+ nfeatures = 0;
+ if (otf->gpos)
+ for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
+ {
+ OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
+ int k;
+
+ if (nfeatures
+ < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
+ nfeatures
+ = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
+ for (k = 0; k < prev_n; k++)
+ if (tag == script_langsys[k].script)
+ break;
+ if (k == prev_n)
+ {
+ script_langsys[n].script = tag;
+ script_langsys[n++].langsys = 0;
+ }
+ for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
+ {
+ int l;
+
+ if (k < prev_n)
+ {
+ OTF_Script *script = otf->gpos->ScriptList.Script + i;
+
+ for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
+ if (script->LangSysRecord[j].LangSysTag
+ == script_langsys[l].langsys)
+ break;
+ }
+ else
+ l = prev_n;
+ if (l == prev_n)
+ {
+ script_langsys[n].script = tag;
+ script_langsys[n++].langsys = 0;
+ }
+ if (nfeatures
+ < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
+ nfeatures
+ = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
+ }
+ }
+
+ if (nfeatures > 0)
+ {
+ gpos.num_features = nfeatures;
+ gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
+ memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
+ }
+
+ if (n == 0)
+ return prev;
+
+ script_tag = script_langsys[0].script;
+ langsys_tag = script_langsys[0].langsys;
+ compose_script_langsys (script_tag, langsys_tag, name);
+
+ if (n == 1)
+ {
+ XtSetArg (arg[0], XtNforeground, background);
+ XtSetArg (arg[1], XtNbackground, foreground);
+ XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
+ }
+ else
+ {
+ Widget box;
+ XtSetArg (arg[0], XtNborderWidth, 0);
+ XtSetArg (arg[1], XtNwidth, render_width - (FONT_WIDTH * 15));
+ XtSetArg (arg[2], XtNorientation, XtorientHorizontal);
+ box = XtCreateManagedWidget ("scritp-list", boxWidgetClass, prev, arg, 2);
+ XtSetArg (arg[0], XtNstate, True);
+ w = XtCreateManagedWidget (name, toggleWidgetClass, box, arg, 1);
+ XtAddCallback (w, XtNcallback, ScriptProc, NULL);
+ XtSetArg (arg[0], XtNradioGroup, w);
+ for (i = 1; i < n; i++)
+ {
+ compose_script_langsys (script_langsys[i].script,
+ script_langsys[i].langsys, name);
+ w = XtCreateManagedWidget (name, toggleWidgetClass, box, arg, 1);
+ XtAddCallback (w, XtNcallback, ScriptProc, NULL);
+ }
+ }
+ return prev;
+}
+
+
+Widget
+create_otf_widgets (Widget prev, FeatureRec *rec)
+{
+ Arg arg[10];
+ Widget w;
+
+ XtSetArg (arg[0], XtNborderWidth, 0);
+ XtSetArg (arg[1], XtNleft, XawChainLeft);
+ XtSetArg (arg[2], XtNright, XawChainLeft);
+ XtSetArg (arg[3], XtNtop, XawChainTop);
+ XtSetArg (arg[4], XtNbottom, XawChainTop);
+ XtSetArg (arg[5], XtNfromVert, prev);
+ XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
+ prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
+ arg, 7);
+ XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
+ XtSetArg (arg[0], XtNborderWidth, 1);
+ XtSetArg (arg[1], XtNinternalHeight, 4);
+ XtSetArg (arg[2], XtNinternalWidth, 4);
+ w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
+ XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
+ w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
+ XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
+
+ rec->parent = prev;
+ setup_feature_rec (rec);
+ return prev;
+}
+
+void
+create_widgets ()