WordListLine WordlistEscapedInputStringToParsedDataComplex( SplineFont* sf, const unichar_t* input_const, WordlistEscapedInputStringToRealString_getFakeUnicodeOfScFunc getUnicodeFunc, void* udata ) { unichar_t* input = u_copy( input_const ); WordListChar* ret = calloc( WordListLineSz, sizeof(WordListChar)); WordListChar* out = ret; unichar_t* in = input; unichar_t* in_end = input + u_strlen(input); // trim comment and beyond from input { unichar_t* p = input; while( p && p < in_end ) { p = u_strchr( p, '#' ); if( p > input && *(p-1) == '/' ) { p++; continue; } if( p ) *p = '\0'; break; } } in_end = input + u_strlen(input); int addingGlyphsToSelected = 0; int currentGlyphIndex = -1; for ( ; in < in_end; in++ ) { unichar_t ch = *in; TRACE("in:%p end:%p got char %d %c\n", in, in_end, ch, ch ); if( ch == '[' ) { addingGlyphsToSelected = 1; continue; } if( ch == ']' ) { addingGlyphsToSelected = 0; continue; } int isSelected = addingGlyphsToSelected; currentGlyphIndex++; if( ch == '/' || ch == '\\' ) { // start of a glyph name unichar_t glyphname[ PATH_MAX+1 ]; unichar_t* updated_in = 0; SplineChar* sc = u_WordlistEscapedInputStringToRealString_readGlyphName( sf, in, in_end, &updated_in, glyphname ); if( sc ) { in = updated_in; int n = getUnicodeFunc( sc, udata ); if( n == -1 ) { /* * Okay, this probably means we've got an unencoded glyph (generally * used for OpenType substitutions). * Redeem the value from the SplineFont datamap instead of fetching from * the Unicode identifier. */ n = sf->map->backmap[sc->orig_pos]; /* * Unencoded glyphs have special mappings in the SplineFont that * start from 65536 (values beyond Unicode, 65535 being the reserved * "frontier" value). */ if ( (sf->map->enc->is_unicodebmp || sf->map->enc->is_unicodefull) && n < 65536 ) { TRACE("ToRealString: backmapped position does not match Unicode encoding\n"); TRACE("orig_pos: %d, backmap: %d, attached unicode enc: %d\n", sc->orig_pos, n, sc->unicodeenc ); TRACE("ToRealString: INVALID CHAR POSITION, name: %s\n", sc->name ); } } out->sc = sc; out->isSelected = isSelected; out->currentGlyphIndex = currentGlyphIndex; out->n = n; out++; /* out = utf8_idpb( out, n, 0 ); */ /* if( !out ) */ /* printf("ToRealString error on out\n"); */ continue; } } /* If we reach this point, we're looking based on codepoint. */ SplineChar* sc = SFGetOrMakeChar( sf, (int)ch, 0 ); out->sc = sc; out->isSelected = isSelected; out->currentGlyphIndex = currentGlyphIndex; out++; } free(input); return(ret); }
/** * Process the given kvmsg from the server. If create is set and we do * not have any charview for a changed glyph then we first create a * charview for it. This allows the updates from a server to be * processed at startup time, getting us up to speed with any glyphs * that have changed. * * This function is mainly called in response to an update which is * published from the server. However, in sessionJoin() we also call * here to handle the incremental updates to glyphs that have occurred * after the SFD was sent to the server. */ static void zeromq_subscriber_process_update( cloneclient_t* cc, kvmsg_t *kvmsg, int create ) { cc->sequence = kvmsg_sequence (kvmsg); if( cc->sequence >= cc->roundTripTimerWaitingSeq ) cc->roundTripTimerWaitingSeq = 0; char* uuid = kvmsg_get_prop (kvmsg, "uuid" ); byte* data = kvmsg_body (kvmsg); size_t data_size = kvmsg_size (kvmsg); printf("cc process_update() uuid:%s\n", uuid ); FontView* fv = FontViewFind( FontViewFind_byXUIDConnected, uuid ); printf("fv:%p\n", fv ); if( fv ) { if( !data_size ) { printf("WARNING: zero length message!\n" ); return; } SplineFont *sf = fv->b.sf; if( !sf ) { printf("ERROR: font view does not have the splinefont set!\n" ); return; } char* pos = kvmsg_get_prop (kvmsg, "pos" ); char* name = kvmsg_get_prop (kvmsg, "name" ); printf("pos:%s\n", pos ); // SplineChar *sc = sf->glyphs[ atoi(pos) ]; SplineChar* sc = SFGetOrMakeChar( sf, -1, name ); printf("sc:%p\n", sc ); if( !sc ) { printf("WARNING: font view does not have a glyph for pos:%s\n", pos ); printf("WARNING: font view does not have a glyph for name:%s\n", name ); return; } printf("sc.name:%s\n", sc->name ); printf("data.size:%ld\n", data_size ); if( DEBUG_SHOW_SFD_CHUNKS ) printf("data:%s\n", data ); int current_layer = 0; if( !sc->views && create ) { int show = 0; CharView* cv = CharViewCreateExtended( sc, fv, -1, show ); printf("created charview:%p\n", cv ); } for( CharViewBase* cv = sc->views; cv; cv = cv->next ) { printf("have charview:%p\n", cv ); char filename[PATH_MAX]; snprintf(filename, PATH_MAX, "%s/fontforge-collab-inx-%d.sfd", getTempDir(), getpid() ); GFileWriteAll( filename, (char*)data); FILE* file = fopen( filename, "rb" ); Undoes* undo = SFDGetUndo( sf, file, sc, "UndoOperation", "EndUndoOperation", current_layer ); fclose(file); if( !undo ) { printf("***** ERROR ****** reading back undo instance!\n"); printf("data: %s\n\n", data ); } if( undo ) { // NOT HANDLED! if( undo->undotype == ut_statehint ) { printf("*** warning ut_statehint not handled\n"); break; } printf("________________________ READ undo.layer: %d dm:%d layer_sz:%d\n", undo->layer, cv->drawmode, cv->sc->layer_cnt ); int selectedlayer = cv->drawmode; if( undo->layer != UNDO_LAYER_UNKNOWN ) selectedlayer = undo->layer; // use oldlayer to store current setting and switch to the // selected layer for this block. int oldlayer = cv->drawmode; cv->drawmode = selectedlayer; undo->next = 0; undo->next = cv->layerheads[selectedlayer]->redoes; cv->layerheads[selectedlayer]->redoes = undo; CVDoRedo( cv ); char* isLocalUndo = kvmsg_get_prop (kvmsg, "isLocalUndo" ); if( isLocalUndo ) { if( isLocalUndo[0] == '1' ) { Undoes* undo = cv->layerheads[selectedlayer]->undoes; if( undo ) { cv->layerheads[selectedlayer]->undoes = undo->next; undo->next = cv->layerheads[selectedlayer]->redoes; cv->layerheads[selectedlayer]->redoes = undo; } } } if( cv->drawmode != oldlayer ) { cv->drawmode = oldlayer; CVCharChangedUpdate( cv ); } } break; } } printf ("I: processed update=%d\n", (int) cc->sequence); }