예제 #1
0
struct MATH *MathTableNew(SplineFont *sf) {
    struct MATH *math = gcalloc(1,sizeof(struct MATH));	/* Too big for chunkalloc */
    int emsize = sf->ascent+sf->descent;
    DBounds b;
    SplineChar *sc;

    math->ScriptPercentScaleDown	= 80;
    math->ScriptScriptPercentScaleDown	= 60;
    math->DelimitedSubFormulaMinHeight	= emsize*1.5;
    /* No default given for math->DisplayOperatorMinHeight */
    /* No default given for math->AxisHeight */
    sc = SFGetChar(sf,'x',NULL);
    if ( sc!=NULL ) {
	SplineCharFindBounds(sc,&b);
	math->AccentBaseHeight = b.maxy;
    }
    sc = SFGetChar(sf,'I',NULL);
    if ( sc!=NULL ) {
	SplineCharFindBounds(sc,&b);
	math->FlattenedAccentBaseHeight = b.maxy;
    }
    if ( sf->pfminfo.subsuper_set )
	math->SubscriptShiftDown = sf->pfminfo.os2_subyoff;
    math->SubscriptTopMax = math->AccentBaseHeight;		/* X-height */
    /* No default given for math->SubscriptBaselineDropMin */
    if ( sf->pfminfo.subsuper_set )
	math->SuperscriptShiftUp = sf->pfminfo.os2_supyoff;
    /* No default given for math->SuperscriptShiftUpCramped */
    math->SuperscriptBottomMin = math->AccentBaseHeight;	/* X-height */
    /* No default given for math->SuperscriptBaselineDropMax */
    math->SubSuperscriptGapMin = 4*sf->uwidth;			/* 4* default rule thickness */
    math->SuperscriptBottomMaxWithSubscript = math->AccentBaseHeight;	/* X-height */
    math->SpaceAfterScript = emsize/24;				/* .5pt at 12pt */
    math->StackGapMin = 3*sf->uwidth;				/* 3* default rule thickness */
    math->StackDisplayStyleGapMin = 7*sf->uwidth;
    math->StretchStackGapAboveMin = math->UpperLimitGapMin;
    math->StretchStackGapBelowMin = math->LowerLimitGapMin;
    math->FractionNumeratorDisplayStyleShiftUp = math->StackTopDisplayStyleShiftUp;
    math->FractionDenominatorDisplayStyleShiftDown = math->StackBottomDisplayStyleShiftDown;
    math->FractionNumeratorGapMin = sf->uwidth;
    math->FractionNumeratorDisplayStyleGapMin = 3*sf->uwidth;
    math->FractionRuleThickness = sf->uwidth;
    math->FractionDenominatorGapMin = sf->uwidth;
    math->FractionDenominatorDisplayStyleGapMin = 3*sf->uwidth;
    math->OverbarVerticalGap = 3*sf->uwidth;
    math->OverbarRuleThickness = sf->uwidth;
    math->OverbarExtraAscender = sf->uwidth;
    math->UnderbarVerticalGap = 3*sf->uwidth;
    math->UnderbarRuleThickness = sf->uwidth;
    math->UnderbarExtraDescender = sf->uwidth;
    math->RadicalVerticalGap = sf->uwidth;
    math->RadicalExtraAscender = sf->uwidth;
    math->RadicalKernBeforeDegree = 5*emsize/18;
    math->RadicalKernAfterDegree = -10*emsize/18;
    math->RadicalDegreeBottomRaisePercent = 60;

    math->MinConnectorOverlap = emsize/50;
return( math );
}
예제 #2
0
파일: splinefont.c 프로젝트: zauguin/LuaTeX
static SplineChar *_SFMakeChar(SplineFont *sf,EncMap *map,int enc) {
    SplineChar dummy, *sc;
    SplineFont *ssf;
    int j, real_uni, gid;
    extern const int cns14pua[], amspua[];

    if ( enc>=map->enccount )
	gid = -1;
    else
	gid = map->map[enc];
    if ( sf->subfontcnt!=0 && gid!=-1 ) {
	ssf = NULL;
	for ( j=0; j<sf->subfontcnt; ++j )
	    if ( gid<sf->subfonts[j]->glyphcnt ) {
		ssf = sf->subfonts[j];
		if ( ssf->glyphs[gid]!=NULL ) {
return( ssf->glyphs[gid] );
		}
	    }
	sf = ssf;
    }

    if ( gid==-1 || (sc = sf->glyphs[gid])==NULL ) {
	if (( map->enc->is_unicodebmp || map->enc->is_unicodefull ) &&
		( enc>=0xe000 && enc<=0xf8ff ) &&
		( sf->uni_interp==ui_ams || sf->uni_interp==ui_trad_chinese ) &&
		( real_uni = (sf->uni_interp==ui_ams ? amspua : cns14pua)[enc-0xe000])!=0 ) {
	    if ( real_uni<map->enccount ) {
		SplineChar *sc;
		/* if necessary, create the real unicode code point */
		/*  and then make us be a duplicate of it */
		sc = _SFMakeChar(sf,map,real_uni);
		map->map[enc] = gid = sc->orig_pos;
		SCCharChangedUpdate(sc,ly_all);
return( sc );
	    }
	}

	SCBuildDummy(&dummy,sf,map,enc);
	/* Let's say a user has a postscript encoding where the glyph ".notdef" */
	/*  is assigned to many slots. Once the user creates a .notdef glyph */
	/*  all those slots should fill in. If they don't they damn well better*/
	/*  when the user clicks on one to edit it */
	/* Used to do that with all encodings. It just confused people */
	if ( map->enc->psnames!=NULL &&
		(sc = SFGetChar(sf,dummy.unicodeenc,dummy.name))!=NULL ) {
	    map->map[enc] = sc->orig_pos;
return( sc );
	}
	sc = SFSplineCharCreate(sf);
	sc->unicodeenc = dummy.unicodeenc;
	sc->name = copy(dummy.name);
	sc->width = dummy.width;
	sc->orig_pos = 0xffff;
	/*SCLigDefault(sc);*/
	SFAddGlyphAndEncode(sf,sc,map,enc);
    }
return( sc );
}
예제 #3
0
static SplineChar *SCHasVertVariant(SplineChar *sc) {
    PST *pst;

    if ( sc==NULL )
return( NULL );

    for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
	if ( pst->type==pst_substitution &&
		(FeatureTagInFeatureScriptList(CHR('v','e','r','t'),pst->subtable->lookup->features) ||
		 FeatureTagInFeatureScriptList(CHR('v','r','t','2'),pst->subtable->lookup->features)) ) {
return( SFGetChar(sc->parent,-1,pst->u.subs.variant));
	}
    }
return( NULL );
}
예제 #4
0
static OTLookup *CreateMacLookup(SplineFont1 *sf,ASM1 *sm) {
   OTLookup *otl=chunkalloc(sizeof(OTLookup));
   int i, ch;
   char *pt, *start;
   SplineChar *sc;

   otl->features=chunkalloc(sizeof(FeatureScriptLangList));
   if (sm->sm.type==asm_kern) {
      otl->lookup_type=kern_statemachine;
      otl->next=sf->sf.gsplookups[1];
      sf->sf.gsplookups[1]=otl;
      otl->features->featuretag =
	 (sm->sm.flags&0x8000)?CHR('v', 'k', 'r', 'n'):CHR('k', 'e',
								 'r', 'n');
   } else {
      otl->lookup_type =
	 sm->sm.type==asm_indic?morx_indic:sm->sm.type ==
	 asm_context?morx_context:morx_insert;
      otl->next=sf->sf.gsplookups[0];
      sf->sf.gsplookups[0]=otl;
      otl->features->featuretag=(sm->feature << 16)|(sm->setting);
      otl->features->ismac=true;
   }
   otl->lookup_flags=0;

   for (i=4; i<sm->sm.class_cnt; ++i) {
      for (start=sm->sm.classes[i];; start=pt) {
	 while (*start==' ')
	    ++start;
	 if (*start=='\0')
	    break;
	 for (pt=start; *pt != '\0' && *pt != ' '; ++pt);
	 ch=*pt;
	 *pt='\0';
	 sc=SFGetChar(&sf->sf, -1, start);
	 if (sc != NULL)
	    FListAppendScriptLang(otl->features, SCScriptFromUnicode(sc),
				  DEFAULT_LANG);
	 *pt=ch;
      }
   }

   /* We will set the lookup_index after we've ordered the list */
   /* We will set the lookup_name after we've assigned the index */
   /* We will add one subtable soon */
   return (otl);
}
예제 #5
0
static int AnchorD_GlyphChanged(GGadget *g, GEvent *e) {
    AnchorDlg *a = GDrawGetUserData(GGadgetGetWindow(g));
    if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
	GTextInfo *sel = GGadgetGetListItemSelected(g);

	if ( sel!=NULL ) {
	    AnchorPoint *ap = sel->userdata;
	    if ( ap==Add_Mark )
		AddAnchor(a,a->sc->parent,a->ap->anchor,true);
	    else if ( ap==Add_Base )
		AddAnchor(a,a->sc->parent,a->ap->anchor,false);
	    else {
		char *name = u2utf8_copy(sel->text);
		SplineChar *sc = SFGetChar(a->sc->parent,-1,name);

		free(name);
		AnchorD_ChangeGlyph(a,sc,ap);
	    }
	}
    }
return( true );
}
예제 #6
0
static void AnchorD_NextPrev(AnchorDlg *a,int incr) {
    GGadget *g = GWidgetGetControl(a->gw,CID_Glyph);
    int len;
    GTextInfo **ti = GGadgetGetList(g,&len);
    int sel = GGadgetGetFirstListSelectedItem(g);

    for ( sel += incr; sel>0 && sel<len; sel+=incr ) {
	if ( !( ti[sel]->userdata == Add_Mark ||
		ti[sel]->userdata == Add_Base ||
		ti[sel]->line ||
		ti[sel]->disabled ))
    break;
    }
    if ( sel==0 || sel>=len )
	GDrawBeep(NULL);
    else {
	char *name = u2utf8_copy(ti[sel]->text);
	SplineChar *sc = SFGetChar(a->sc->parent,-1,name);

	free(name);
	GGadgetSelectOneListItem(g,sel);
	AnchorD_ChangeGlyph(a,sc,ti[sel]->userdata);
    }
}
예제 #7
0
static SplineChar*
u_WordlistEscapedInputStringToRealString_readGlyphName(
    SplineFont *sf, unichar_t* in, unichar_t* in_end,
    unichar_t** updated_in, unichar_t* glyphname )
{
    int startedWithBackSlash = (*in == '\\');
    if( *in != '/' && *in != '\\' )
	return 0;
    bool startsWithBackSlash = *in == '\\';
    // move over the delimiter that we know we are on
    in++;
    unichar_t* startpos = in;

    // Get the largest possible 'glyphname' from the input stream.
    memset( glyphname, '\0', PATH_MAX );
    unichar_t* outname = glyphname;
    while( *in != '/'
	   && ( !startsWithBackSlash || *in != '\\' )
	   && *in != ' ' && *in != ']' && in != in_end )
    {
	*outname = *in;
	++outname;
	in++;
    }
    bool FullMatchEndsOnSpace = 0;
    unichar_t* maxpos = in;
    unichar_t* endpos = maxpos-1;
    TRACE("WordlistEscapedInputStringToRealString_readGlyphName(x1) -->:%s:<--\n", u_to_c(glyphname));

    int loopCounter = 0;
    int firstLookup = 1;
    for( ; endpos >= startpos; endpos--, loopCounter++ )
    {
//	printf("WordlistEscapedInputStringToRealString_readGlyphName(trim loop top) gn:%s\n", u_to_c(glyphname) );
	SplineChar* sc = 0;
	
	if( startedWithBackSlash )
	{
	    if( glyphname[0] == 'u' )
		glyphname++;

	    unichar_t* endptr = 0;
	    long unicodepoint = u_strtoul( glyphname+1, &endptr, 16 );
	    TRACE("AAA glyphname:%s\n", u_to_c(glyphname+1) );
	    TRACE("AAA unicodepoint:%ld\n", unicodepoint );
	    sc = SFGetChar( sf, unicodepoint, 0 );
	    if( sc && endptr )
	    {
		unichar_t* endofglyphname = glyphname + u_strlen(glyphname);
		/* printf("glyphname:%p\n", glyphname ); */
		/* printf("endptr:%p endofglyphname:%p\n", endptr, endofglyphname ); */
		for( ; endptr < endofglyphname; endptr++ )
		    --endpos;
	    }
	    if( !sc )
	    {
//		printf("WordlistEscapedInputStringToRealString_readGlyphName() no char found for backslashed unicodepoint:%ld\n", unicodepoint );
		uc_strcpy(glyphname,"backslash");
		sc = SFGetChar( sf, -1, u_to_c(glyphname) );
		endpos = startpos;
	    }
	}
	else
	{
	    if( uc_startswith( glyphname, "uni"))
	    {
		unichar_t* endptr = 0;
		long unicodepoint = u_strtoul( glyphname+3, &endptr, 16 );
                SplineChar* tmp = 0;
		TRACE("uni prefix, codepoint: %ld\n", unicodepoint );
		sc = SFGetChar( sf, unicodepoint, 0 );
                if ((tmp = SFGetChar( sf, -1, u_to_c(glyphname) ))) {
		    TRACE("have subst. char: %s\n", tmp->name );
                    sc = tmp;
                } else {
		    if( sc && endptr )
		    {
		        unichar_t* endofglyphname = glyphname + u_strlen(glyphname);
//		        printf("endptr:%p endofglyphname:%p\n", endptr, endofglyphname );
		        for( ; endptr < endofglyphname; endptr++ )
                            --endpos;
		    }
                }
	    }
	    
	    if( firstLookup && glyphname[0] == '#' )
	    {
		unichar_t* endptr = 0;
		long unicodepoint = u_strtoul( glyphname+1, &endptr, 16 );
//		printf("WordlistEscapedInputStringToRealString_readGlyphName() unicodepoint:%ld\n", unicodepoint );
		sc = SFGetChar( sf, unicodepoint, 0 );
		if( sc && endptr )
		{
		    unichar_t* endofglyphname = glyphname + u_strlen(glyphname);
//		    printf("endptr:%p endofglyphname:%p\n", endptr, endofglyphname );
		    for( ; endptr < endofglyphname; endptr++ )
			--endpos;
		}
	    }
	    if( !sc )
	    {
//		printf("WordlistEscapedInputStringToRealString_readGlyphName(getchar) gn:%s\n", glyphname );
		sc = SFGetChar( sf, -1, u_to_c(glyphname) );
	    }
	}

	if( sc )
	{
//	    printf("WordlistEscapedInputStringToRealString_readGlyphName(found!) gn:%s start:%p end:%p\n", glyphname, startpos, endpos );
	    if( !loopCounter && FullMatchEndsOnSpace )
	    {
		endpos++;
	    }
	    *updated_in = endpos;
	    return sc;
	}
	if( glyphname[0] != '\0' )
	    glyphname[ u_strlen(glyphname)-1 ] = '\0';
    }


    *updated_in = endpos;

    // printf("WordlistEscapedInputStringToRealString_readGlyphName(end) gn:%s\n", glyphname );
    return 0;
}
예제 #8
0
static SplineChar*
WordlistEscapedInputStringToRealString_readGlyphName(
    SplineFont *sf, char* in, char* in_end,
    char** updated_in, char* glyphname )
{
//    printf("WordlistEscapedInputStringToRealString_readGlyphName(top)\n");

    int startedWithBackSlash = (*in == '\\');
    if( *in != '/' && *in != '\\' )
	return 0;
    // move over the delimiter that we know we are on
    in++;
    char* startpos = in;

    // Get the largest possible 'glyphname' from the input stream.
    memset( glyphname, '\0', PATH_MAX );
    char* outname = glyphname;
    while( *in != '/' && *in != ' ' && *in != ']' && in != in_end )
    {
	*outname = *in;
	++outname;
	in++;
    }
    bool FullMatchEndsOnSpace = 0;
    char* maxpos = in;
    char* endpos = maxpos-1;
//    printf("WordlistEscapedInputStringToRealString_readGlyphName(x1) -->:%s:<--\n", glyphname);
//    printf("WordlistEscapedInputStringToRealString_readGlyphName(x2) %c %p %p\n",*in,startpos,endpos);

    int loopCounter = 0;
    int firstLookup = 1;
    for( ; endpos >= startpos; endpos--, loopCounter++ )
    {
//	printf("WordlistEscapedInputStringToRealString_readGlyphName(trim loop top) gn:%s\n", glyphname );
	SplineChar* sc = 0;
	if( startedWithBackSlash )
	{
	    if( glyphname[0] == 'u' )
		glyphname++;

	    char* endptr = 0;
	    long unicodepoint = strtoul( glyphname+1, &endptr, 16 );
	    TRACE("AAA glyphname:%s\n", glyphname+1 );
	    TRACE("AAA unicodepoint:%ld\n", unicodepoint );
	    sc = SFGetChar( sf, unicodepoint, 0 );
	    if( sc && endptr )
	    {
		char* endofglyphname = glyphname + strlen(glyphname);
		for( ; endptr < endofglyphname; endptr++ )
		    --endpos;
	    }
	    if( !sc )
	    {
//		printf("WordlistEscapedInputStringToRealString_readGlyphName() no char found for backslashed unicodepoint:%ld\n", unicodepoint );
		strcpy(glyphname,"backslash");
		sc = SFGetChar( sf, -1, glyphname );
		endpos = startpos;
	    }
	}
	else
	{
	    if( firstLookup && glyphname[0] == '#' )
	    {
		char* endptr = 0;
		long unicodepoint = strtoul( glyphname+1, &endptr, 16 );
//		printf("WordlistEscapedInputStringToRealString_readGlyphName() unicodepoint:%ld\n", unicodepoint );
		sc = SFGetChar( sf, unicodepoint, 0 );
		if( sc && endptr )
		{
		    char* endofglyphname = glyphname + strlen(glyphname);
//		    printf("endptr:%p endofglyphname:%p\n", endptr, endofglyphname );
		    for( ; endptr < endofglyphname; endptr++ )
			--endpos;
		}
	    }
	    if( !sc )
	    {
//		printf("WordlistEscapedInputStringToRealString_readGlyphName(getchar) gn:%s\n", glyphname );
		sc = SFGetChar( sf, -1, glyphname );
	    }
	}

	if( sc )
	{
//	    printf("WordlistEscapedInputStringToRealString_readGlyphName(found!) gn:%s start:%p end:%p\n", glyphname, startpos, endpos );
	    if( !loopCounter && FullMatchEndsOnSpace )
	    {
		endpos++;
	    }
	    *updated_in = endpos;
	    return sc;
	}
	if( glyphname[0] != '\0' )
	    glyphname[ strlen(glyphname)-1 ] = '\0';
    }


    *updated_in = endpos;

    // printf("WordlistEscapedInputStringToRealString_readGlyphName(end) gn:%s\n", glyphname );
    return 0;
}
예제 #9
0
파일: sfundo.c 프로젝트: JasonH1/fontforge
void SFUndoPerform( SFUndoes* undo, SplineFont* sf )
{
    char* sfdchunk = 0;
    FILE* sfd = 0;

    switch(undo->type) {
    case sfut_fontinfo:
	sfdchunk = undo->sfdchunk;
	printf("font level undo, font info sfd:%s\n", sfdchunk );
	sfd = MakeTemporaryFile();
	fwrite( sfdchunk, strlen(sfdchunk), 1, sfd );
	fseek( sfd, 0, SEEK_SET );

	SFD_GetFontMetaDataData d;
	SFD_GetFontMetaDataData_Init( &d );
	visitSFDFragment( sfd, sf, SFD_GetFontMetaData, &d );
	break;
    case sfut_lookups_kerns:
    case sfut_lookups:
	sfdchunk = undo->sfdchunk;
	if( !sfdchunk ) {
	    ff_post_error(_("Undo information incomplete"),_("There is a splinefont level undo, but it does not contain any information to perform the undo. This is an application error, please report what you last did to the lookup tables so the developers can try to reproduce the issue and fix it."));
	    SFUndoRemoveAndFree( sf, undo );
	    return;
	}

	// Roll it on back!
	sfd = MakeTemporaryFile();
	fwrite( sfdchunk, strlen(sfdchunk), 1, sfd );
	fseek( sfd, 0, SEEK_SET );

	while( 1 ) {
	    char* name = SFDMoveToNextStartChar( sfd );
	    if( !name )
		break;

	    int unienc = 0;
	    SplineChar *sc;
	    sc = SFGetChar( sf, unienc, name );
	    if( !sc ) {
		ff_post_error(_("Bad undo"),_("couldn't find the character %s"), name );
		break;
	    }
	    if( sc ) {
		// Free the stuff in sc->psts so we don't leak it.
		if( undo->type == sfut_lookups ) {
		    PSTFree(sc->possub);
		    sc->possub = 0;
		}
		char tok[2000];
		getname( sfd, tok );
		SFDGetPSTs( sfd, sc, tok );
		SFDGetKerns( sfd, sc, tok );
	    }
	    free(name);
	}

	if( undo->type == sfut_lookups_kerns ) {
	    SFDFixupRefs( sf );
	}
	break;
    }
}
예제 #10
0
void SFShowLigatures(SplineFont *sf,SplineChar *searchfor) {
    int i, cnt;
    char **choices=NULL;
    int *where=NULL;
    SplineChar *sc, *sc2;
    char *pt, *line;
    char *start, *end, ch;
    PST *pst;

    while ( 1 ) {
	for ( i=cnt=0; i<sf->glyphcnt; ++i ) {
	    if ( (sc=sf->glyphs[i])!=NULL && SCDrawsSomething(sc) ) {
		for ( pst=sc->possub; pst!=NULL; pst=pst->next )
			if ( pst->type==pst_ligature &&
				(searchfor==NULL || PSTContains(pst->u.lig.components,searchfor->name))) {
		    if ( choices!=NULL ) {
			line = pt = galloc((strlen(sc->name)+13+3*strlen(pst->u.lig.components)));
			strcpy(pt,sc->name);
			pt += strlen(pt);
			if ( sc->unicodeenc!=-1 && sc->unicodeenc<0x10000 ) {
			    *pt++='(';
			    pt = utf8_idpb(pt,sc->unicodeenc);
			    *pt++=')';
			}
			/* *pt++ = 0x21d0;*/ /* left arrow */
			strcpy(pt," ⇐ "); pt += strlen(pt);
			for ( start= pst->u.lig.components; ; start=end ) {
			    while ( *start==' ' ) ++start;
			    if ( *start=='\0' )
			break;
			    for ( end=start+1; *end!='\0' && *end!=' '; ++end );
			    ch = *end;
			    *end = '\0';
			    strcpy( pt,start );
			    pt += strlen(pt);
			    sc2 = SFGetChar(sf,-1,start);
			    *end = ch;
			    if ( sc2!=NULL && sc2->unicodeenc!=-1 && sc2->unicodeenc<0x10000 ) {
				*pt++='(';
				*pt++ = sc2->unicodeenc;
				*pt++=')';
			    }
			    *pt++ = ' ';
			}
			pt[-1] = '\0';
			choices[cnt] = line;
			where[cnt] = i;
		    }
		    ++cnt;
		}
	    }
	}
	if ( choices!=NULL )
    break;
	choices = galloc((cnt+2)*sizeof(unichar_t *));
	where = galloc((cnt+1)*sizeof(int));
	if ( cnt==0 ) {
	    choices[0] = copy("<No Ligatures>");
	    where[0] = -1;
	    choices[1] = NULL;
    break;
	}
    }
    choices[cnt] = NULL;
    i = gwwv_choose(_("Ligatures"),(const char **) choices,cnt,0,_("Select a ligature to view"));
    if ( i!=-1 && where[i]!=-1 )
	CharViewCreate(sf->glyphs[where[i]],(FontView *) sf->fv,-1);
    free(where);
    for ( i=0; i<cnt; ++i )
	free(choices[i]);
    free(choices);
}
예제 #11
0
static SplineChar *AddAnchor(AnchorDlg *a, SplineFont *sf, AnchorClass *ac,
	int ismarklike) {
    char *ret, *def;
    SplineChar *sc;
    int isliga = false, ismrk=false, maxlig=-1;
    AnchorPoint *ap;
    PST *pst;
    int i;

    def = copy(".notdef");
    for (;;) {
	ret = gwwv_ask_string(_("Provide a glyph name"),def,_("Please identify a glyph by name, and FontForge will add an anchor to that glyph."));
	free(def);
	if ( ret==NULL )
return( NULL );
	sc = SFGetChar(sf,-1,ret);
	def = ret;
	if ( sc==NULL )
	    ff_post_error(_("Non-existant glyph"), _("The glyph, %.80s, is not in the font"), ret );
	else {
	    isliga = ismrk = false;
	    for ( ap=sc->anchor ; ap!=NULL; ap=ap->next ) {
		if ( ap->type == at_baselig )
		    isliga = true;
		else if ( ap->type == at_basemark || ap->type == at_mark )
		    ismrk = true;
		if ( ap->anchor == ac ) {
		    if ( (ap->type == at_centry ||
			    (ap->type == at_mark && ac->type==act_mkmk) ||
			    ap->type == at_baselig ) && ismarklike==-1 )
			ismarklike = false;
		    else if ( (ap->type == at_cexit || (ap->type == at_basemark && ac->type==act_mkmk)) && ismarklike==-1 )
			ismarklike = true;
		    else if ( ap->type != at_baselig ||
			      ( ap->type == at_baselig && ismarklike>0 ))
			ff_post_error(_("Duplicate Anchor Class"), _("The glyph, %.80s, already contains an anchor in this class, %.80s."), ret, ac->name );
		    else if ( maxlig<ap->lig_index )
			maxlig = ap->lig_index;
	    break;
		}
	    }
	    if ( ap==NULL )
    break;
	}
    }

    ap = chunkalloc(sizeof(AnchorPoint));
    ap->anchor = ac;
    ap->me.x = ap->me.y = 0;
    ap->next = sc->anchor;
    sc->anchor = ap;
    SCCharChangedUpdate(sc,ly_none);

    if ( sc->width==0 ) ismrk = true;
    for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
	if ( pst->type == pst_ligature || pst->type == pst_lcaret ) {
	    isliga = true;
    break;
	}
    }

    if ( isliga || (ac->type==act_mklg && ismarklike==0 ) ) {
	ap->type = at_baselig;
	ap->lig_index = maxlig+1;
    } else if ( ismrk && ismarklike!=0 )
	ap->type = at_mark;
    else if ( ismarklike==0 && (ismrk || ac->type==act_mkmk) )
	ap->type = at_basemark;
    else if ( ac->type == act_curs ) {
	if ( ismarklike==true )
	    ap->type = at_centry;
	else
	    ap->type = at_cexit;
    } else if ( ismarklike==true )
	ap->type = at_mark;
    else
	ap->type = at_basechar;

    if ( a!=NULL ) {
	GTextInfo **ti = AnchorD_GlyphsInClass(a);
	GGadgetSetList(GWidgetGetControl(a->gw,CID_Glyph),ti,false);
	for ( i=0; ti[i]->text!=NULL || ti[i]->line; ++i ) {
	    if ( ti[i]->userdata == ap ) {
		GGadgetSelectOneListItem(GWidgetGetControl(a->gw,CID_Glyph),i);
	break;
	    }
	}
	AnchorD_ChangeGlyph(a,sc,ap);
    }
return( sc );
}