/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */ /* * Copyright 1997-2000 by Eric House (fixin@peak.org). All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef USE_STDIO # include # include #endif #include "comtypes.h" #include "dictnryp.h" #include "xwstream.h" #include "strutils.h" #ifdef CPLUS extern "C" { #endif /***************************************************************************** * ****************************************************************************/ void setBlankTile( DictionaryCtxt* dctx ) { XP_U16 i; dctx->blankTile = -1; /* no known blank */ for ( i = 0; i < dctx->nFaces; ++i ) { if ( dctx->faces16[i] == 0 ) { dctx->blankTile = (XP_U8)i; XP_LOGF( "blank tile index: %d", i ); break; } } } /* setBlankTile */ XP_Bool dict_hasBlankTile( DictionaryCtxt* dict ) { return dict->blankTile >= 0; } /* dict_hasBlankTile */ Tile dict_getBlankTile( DictionaryCtxt* dict ) { XP_ASSERT( dict_hasBlankTile(dict) ); return (Tile)dict->blankTile; } /* dict_getBlankTile */ XP_U16 dict_getTileValue( DictionaryCtxt* dict, Tile tile ) { tile &= TILE_VALUE_MASK; XP_ASSERT( tile < dict->nFaces ); tile *= 2; return dict->countsAndValues[tile+1]; } /* dict_getTileValue */ static XP_UCHAR dict_getTileChar( DictionaryCtxt* dict, Tile tile ) { XP_ASSERT( tile < dict->nFaces ); XP_ASSERT( (dict->faces16[tile] & 0xFF00) == 0 ); /* no unicode yet */ return (XP_UCHAR)dict->faces16[tile]; } /* dict_getTileValue */ XP_U16 dict_numTiles( DictionaryCtxt* dict, Tile tile ) { tile *= 2; return dict->countsAndValues[tile]; } /* dict_numTiles */ XP_U16 dict_numTileFaces( DictionaryCtxt* dict ) { return dict->nFaces; } /* dict_numTileFaces */ XP_U16 dict_tilesToString( DictionaryCtxt* ctxt, Tile* tiles, XP_U16 nTiles, XP_UCHAR* buf ) { XP_UCHAR* bufIn = buf; while ( nTiles-- ) { Tile tile = *tiles++; XP_UCHAR face = dict_getTileChar(ctxt, tile); if ( IS_SPECIAL(face) ) { XP_UCHAR* chars = ctxt->chars[(XP_U16)face]; XP_U16 len = XP_STRLEN( chars ); XP_MEMCPY( buf, chars, len ); buf += len; } else { XP_ASSERT ( tile != ctxt->blankTile ); /* printing blank should be handled by specials mechanism */ *buf++ = face; } } *buf = '\0'; return buf - bufIn; } /* dict_tilesToString */ Tile dict_tileForString( DictionaryCtxt* dict, XP_UCHAR* key ) { XP_U16 nFaces = dict_numTileFaces( dict ); Tile tile; XP_Bool keyNotSpecial = XP_STRLEN((char*)key) == 1; for ( tile = 0; tile < nFaces; ++tile ) { XP_UCHAR face = dict_getTileChar( dict, tile ); if ( IS_SPECIAL(face) ) { XP_UCHAR* chars = dict->chars[(XP_U16)face]; if ( 0 == XP_STRNCMP( chars, key, XP_STRLEN(chars) ) ) { return tile; } } else if ( keyNotSpecial && (face == *key) ) { return tile; } } return EMPTY_TILE; } /* dict_tileForChar */ XP_Bool dict_tilesAreSame( DictionaryCtxt* dict1, DictionaryCtxt* dict2 ) { XP_Bool result = XP_FALSE; Tile i; XP_U16 nTileFaces = dict_numTileFaces( dict1 ); if ( nTileFaces == dict_numTileFaces( dict2 ) ) { for ( i = 0; i < nTileFaces; ++i ) { XP_UCHAR face1, face2; if ( dict_getTileValue( dict1, i ) != dict_getTileValue( dict2, i ) ){ break; } #if 1 face1 = dict_getTileChar( dict1, i ); face2 = dict_getTileChar( dict2, i ); if ( face1 != face2 ) { break; } #else face1 = dict_getTileChar( dict1, i ); face2 = dict_getTileChar( dict2, i ); if ( IS_SPECIAL(face1) != IS_SPECIAL(face2) ) { break; } if ( IS_SPECIAL(face1) ) { XP_UCHAR* chars1 = dict1->chars[face1]; XP_UCHAR* chars2 = dict2->chars[face2]; XP_U16 len = XP_STRLEN(chars1); if ( 0 != XP_STRNCMP( chars1, chars2, len ) ) { break; } } else if ( face1 != face2 ) { break; } #endif if ( dict_numTiles( dict1, i ) != dict_numTiles( dict2, i ) ) { break; } } result = i == nTileFaces; /* did we get that far */ } return result; } /* dict_tilesAreSame */ void dict_writeToStream( DictionaryCtxt* dict, XWStreamCtxt* stream ) { XP_U16 maxCount = 0; XP_U16 maxValue = 0; XP_U16 i, nSpecials; XP_U16 maxCountBits, maxValueBits; stream_putBits( stream, 6, dict->nFaces ); for ( i = 0; i < dict->nFaces*2; i+=2 ) { XP_U16 count, value; count = dict->countsAndValues[i]; if ( maxCount < count ) { maxCount = count; } value = dict->countsAndValues[i+1]; if ( maxValue < value ) { maxValue = value; } } maxCountBits = bitsForMax( maxCount ); maxValueBits = bitsForMax( maxValue ); stream_putBits( stream, 3, maxCountBits ); /* won't be bigger than 5 */ stream_putBits( stream, 3, maxValueBits ); for ( i = 0; i < dict->nFaces*2; i+=2 ) { stream_putBits( stream, maxCountBits, dict->countsAndValues[i] ); stream_putBits( stream, maxValueBits, dict->countsAndValues[i+1] ); } for ( i = 0; i < dict->nFaces; ++i ) { stream_putU8( stream, (XP_U8)dict->faces16[i] ); } for ( nSpecials = i = 0; i < dict->nFaces; ++i ) { XP_UCHAR face = dict_getTileChar( dict, (Tile)i ); if ( IS_SPECIAL( face ) ) { stringToStream( stream, dict->chars[nSpecials++] ); } } } /* dict_writeToStream */ static void freeSpecials( DictionaryCtxt* dict ) { Tile t; XP_U16 nSpecials; for ( nSpecials = t = 0; t < dict->nFaces; ++t ) { XP_UCHAR face = dict_getTileChar( dict, t ); if ( IS_SPECIAL( face ) ) { XP_ASSERT( !!dict->chars[nSpecials] ); XP_FREE( dict->mpool, dict->chars[nSpecials] ); if ( !!dict->bitmaps[nSpecials].largeBM ) { XP_FREE( dict->mpool, dict->bitmaps[nSpecials].largeBM ); } if ( !!dict->bitmaps[nSpecials].smallBM ) { XP_FREE( dict->mpool, dict->bitmaps[nSpecials].smallBM ); } ++nSpecials; } } if ( nSpecials > 0 ) { XP_FREE( dict->mpool, dict->chars ); XP_FREE( dict->mpool, dict->bitmaps ); } } /* freeSpecials */ static void common_destructor( DictionaryCtxt* dict ) { freeSpecials( dict ); XP_FREE( dict->mpool, dict->countsAndValues ); XP_FREE( dict->mpool, dict->faces16 ); XP_FREE( dict->mpool, dict ); } /* dict */ void dict_loadFromStream( DictionaryCtxt* dict, XWStreamCtxt* stream ) { XP_U8 nFaces; XP_U16 maxCountBits, maxValueBits; XP_U16 i, nSpecials; XP_UCHAR* localTexts[32]; XP_ASSERT( !dict->destructor ); dict->destructor = common_destructor; nFaces = (XP_U8)stream_getBits( stream, 6 ); maxCountBits = (XP_U16)stream_getBits( stream, 3 ); maxValueBits = (XP_U16)stream_getBits( stream, 3 ); dict->nFaces = nFaces; dict->countsAndValues = (XP_U8*)XP_MALLOC( dict->mpool, sizeof(dict->countsAndValues[0]) * nFaces * 2 ); for ( i = 0; i < dict->nFaces*2; i+=2 ) { dict->countsAndValues[i] = (XP_U8)stream_getBits( stream, maxCountBits ); dict->countsAndValues[i+1] = (XP_U8)stream_getBits( stream, maxValueBits ); } dict->faces16 = (XP_CHAR16*)XP_MALLOC( dict->mpool, sizeof(dict->faces16[0]) * nFaces ); for ( i = 0; i < dict->nFaces; ++i ) { dict->faces16[i] = (XP_CHAR16)stream_getU8( stream ); } for ( nSpecials = i = 0; i < nFaces; ++i ) { XP_UCHAR face = dict_getTileChar( dict, (Tile)i ); if ( IS_SPECIAL( face ) ) { XP_UCHAR* txt = stringFromStream( MPPARM(dict->mpool) stream ); XP_ASSERT( !!txt ); localTexts[nSpecials] = txt; ++nSpecials; } } if ( nSpecials > 0 ) { dict->bitmaps = (SpecialBitmaps*)XP_MALLOC( dict->mpool, nSpecials * sizeof(*dict->bitmaps) ); XP_MEMSET( dict->bitmaps, 0, nSpecials * sizeof(*dict->bitmaps) ); dict->chars = (XP_UCHAR**)XP_MALLOC( dict->mpool, nSpecials * sizeof(*dict->chars) ); XP_MEMCPY(dict->chars, localTexts, nSpecials * sizeof(*dict->chars)); } setBlankTile( dict ); } /* dict_loadFromStream */ XP_UCHAR* dict_getName( DictionaryCtxt* dict ) { XP_ASSERT( !!dict ); return dict->name; } /* dict_getName */ XP_Bool dict_faceIsBitmap( DictionaryCtxt* dict, Tile tile ) { XP_UCHAR face = dict_getTileChar( dict, tile ); return /* face != 0 && */IS_SPECIAL(face); } /* dict_faceIsBitmap */ XP_Bitmap dict_getFaceBitmap( DictionaryCtxt* dict, Tile tile, XP_Bool isLarge ) { SpecialBitmaps* bitmaps; XP_UCHAR face = dict_getTileChar( dict, tile ); XP_ASSERT( dict_faceIsBitmap( dict, tile ) ); XP_ASSERT( !!dict->bitmaps ); bitmaps = &dict->bitmaps[(XP_U16)face]; return isLarge? bitmaps->largeBM:bitmaps->smallBM; } /* dict_getFaceBitmap */ #ifdef STUBBED_DICT #define BLANK_FACE '\0' static XP_U8 stub_english_data[] = { /* count value face */ 9, 1, 'A', 2, 3, 'B', 2, 3, 'C', 4, 2, 'D', 12, 1, 'E', 2, 4, 'F', 3, 2, 'G', 2, 4, 'H', 9, 1, 'I', 1, 8, 'J', 1, 5, 'K', 4, 1, 'L', 2, 3, 'M', 6, 1, 'N', 8, 1, 'O', 2, 3, 'P', 1, 10, 'Q', 6, 1, 'R', 4, 1, 'S', 6, 1, 'T', 4, 1, 'U', 2, 4, 'V', 2, 4, 'W', 1, 8, 'X', 2, 4, 'Y', 1, 10, 'Z', 2, 0, BLANK_FACE, /* BLANK1 */ }; void setStubbedSpecials( DictionaryCtxt* dict ) { dict->chars = XP_MALLOC( dict->mpool, sizeof(char*) ); dict->chars[0] = "_"; } /* setStubbedSpecials */ void destroy_stubbed_dict( DictionaryCtxt* dict ) { XP_FREE( dict->mpool, dict->countsAndValues ); XP_FREE( dict->mpool, dict->faces16 ); XP_FREE( dict->mpool, dict->chars ); XP_FREE( dict->mpool, dict->name ); XP_FREE( dict->mpool, dict->bitmaps ); XP_FREE( dict->mpool, dict ); } /* destroy_stubbed_dict */ DictionaryCtxt* make_stubbed_dict( MPFORMAL_NOCOMMA ) { DictionaryCtxt* dict = XP_MALLOC( mpool, sizeof(*dict) ); XP_U8* data = stub_english_data; XP_U16 datasize = sizeof(stub_english_data); XP_U16 i; XP_MEMSET( dict, 0, sizeof(*dict) ); MPASSIGN( dict->mpool, mpool ); dict->name = copyString( MPPARM(mpool) "Stub dictionary" ); dict->nFaces = datasize/3; dict->destructor = destroy_stubbed_dict; dict->faces16 = XP_MALLOC( mpool, dict->nFaces * sizeof(dict->faces16[0]) ); for ( i = 0; i < datasize/3; ++i ) { dict->faces16[i] = (XP_CHAR16)data[(i*3)+2]; } dict->countsAndValues = XP_MALLOC( mpool, dict->nFaces*2 ); for ( i = 0; i < datasize/3; ++i ) { dict->countsAndValues[i*2] = data[(i*3)]; dict->countsAndValues[(i*2)+1] = data[(i*3)+1]; } dict->bitmaps = XP_MALLOC( mpool, sizeof(SpecialBitmaps) ); dict->bitmaps->largeBM = dict->bitmaps->largeBM = NULL; setStubbedSpecials( dict ); setBlankTile( dict ); return dict; } /* make_subbed_dict */ #endif /* STUBBED_DICT */ #ifndef OVERRIDE_EDGE_FOR_INDEX array_edge* dict_edge_for_index( DictionaryCtxt* dict, XP_U32 index ) { array_edge* result; if ( index == 0 ) { result = NULL; } else { XP_ASSERT( index < dict->numEdges ); #ifdef NODE_CAN_4 index *= dict->nodeSize; #else index *= 3; #endif result = &dict->base[index]; } return result; } /* dict_edge_for_index */ #endif #ifdef CPLUS } #endif