/****************************************************************** * xttmgr.c - 系統字型管理 * 作者 : Firefly ( firefly@firefly.idv.tw ) * *******************************************************************/ #include #include FT_FREETYPE_H #include FT_MODULE_H #include FT_TRUETYPE_IDS_H #include FT_TRUETYPE_TABLES_H #include FT_SFNT_NAMES_H #include #include #include #include #include #include #include #include #include #include #include #include #include "ttos2val.h" #include "charmaps.h" struct xlfd_rec { int face_no; int has_big; char foundry[128]; char family[128]; char weight[32]; char slant; char width[32]; char spacing; char encoding_name[128]; }; struct fp_rec { char path[256]; }; struct xlfd_rec *xlfdList; static int num_xlfds = 0; struct fp_rec *fpList; static int num_fps = 0; struct fp_rec *conList; static int num_cons = 0; static FT_Library library; static char *ProgName; /* 程式名稱 */ static int have_module = 0; /* 系統預設的 encoding 表格指引檔位置 */ static char *encodings_path= "/usr/X11R6/lib/X11/fonts/encodings/encodings.dir"; /* XFree86 的設定檔 */ static char *conf3_path = "/etc/X11/XF86Config"; static char *conf_path = "/etc/X11/XF86Config-4"; /* xfs 的字型設定檔 */ static char *fsconfig = "/etc/X11/fs/config"; /* 所管理的字型存放位置 */ static char *font_path = "/usr/X11R6/lib/X11/fonts/TrueType/"; /* 真實字型檔放置位置 */ static char *base_path = "/usr/share/fonts/ttf/"; /* fonts.dir 所在位置 */ static char *font_dir = "/usr/X11R6/lib/X11/fonts/TrueType/fonts.dir"; /* fonts.scale 所在位置 */ static char *font_scale = "/usr/X11R6/lib/X11/fonts/TrueType/fonts.scale"; /* 暫存檔檔名 */ static char *temp_file = "/tmp/_xttmgr.tmp"; /* 非亞洲語系允許 miss 掉的數目上限 */ static int max_miss = 5; /* 容許 miss 數目 */ /* font face 數目 */ static int num_faces; static int Check_Font_Face( char *filename ); static void Usage( void ); /* 檢查檔案是否存在的副程式 (1:存在, 0:不存在) */ static int File_Exist( char *path ); /* 強制建立目錄(1:失敗, 0:成功) */ static int Force_Mkdir( char *path ); /* 新增字型 */ static int Add_Font( char *filename ); /* 複製檔案 */ static int Copy_File( char *source, char *target ); /* 判斷字型是否已經安裝 (1:已安裝, 0:沒有) */ static int Is_Install( char *filename ); /* 字串 A 在 字串 B 的位置( -1:表示沒有 ) */ static int Stra_At_Strb( char *stra, char *strb ); /* 判斷是否為 CJK 字元集 (1:是, 0:否) */ static int Is_CJK( char *encoding_name ); /* 取得製造商名稱 */ static void Get_Foundry_Name( FT_Face face, char *buffer ); static int Gen_Encoding( char *filename ); /* 內部預設 encoding 表格 */ static void Read_Encoding_Table( FT_Face face ); /* 比對系統 encoding 表格 */ static int Read_Encoding_Dir( FT_Face face ); /* 開啟指定的 encoding file 並掃描是否符合 */ static int Check_Encoding( FT_Face face, char *file_name ); /* 加入新的 Encoding */ static int Add_XLFD( FT_Face face, char *encoding_name ); /* 檢查 Encoding 是否重複 ( 1:是 0:沒有 )*/ static int Check_Dup_XLFD( FT_Face face, char *encoding_name ); /* 更新 fonts.dir、fonts.scale */ static int Update_Font_Files( char *font_file, char *path ); /* 移除字型 */ static int Remove_Font( char *filename ); /* 字型資訊 */ static int Font_Info( char *filename ); static int Get_Name_String( FT_Face face, FT_UShort name_id, char *buffer ); /* 重新設定 XF86Config 之 FontPath & module */ static int Init_Config( void ); /* 讀取 xfs 之 config 內的 fontpath 返回值就是總數 0:沒有讀到任何資料 */ static int Read_xfsconfig( void ); static int List_All_Fontpath( void ); static int Make_Font_Dir( char *fontpath ); static int Rebuild_All_Dir( void ); static void XSet_fp( char *path ); static int Update_XfsConfig( void ); static int Add_Font_Path( char *path, int nocheck ); static int Remove_Font_Path( char *path ); /* 主程式 */ int main( int argc, char *argv[] ) { char mode = '\0'; int status = 0; uid_t uid = getuid( ); /* 取得 User ID */ ProgName = basename((char *)argv[0] ); if ( ProgName[0] == '/' ) ProgName ++; /* 檢查使用者是否為 root ? */ if ( uid != 0 ) { fprintf( stderr, "%s: This program is used only for 'root'\n", ProgName ); exit (1); } if ( Force_Mkdir( font_path ) ){ fprintf( stderr, "%s: Can not create \"%s\".\n", ProgName, font_path ); exit(1); } if ( Force_Mkdir( base_path ) ){ fprintf( stderr, "%s: Can not create \"%s\".\n", ProgName, base_path ); exit(1); } /* 初始 Freetype library */ if ( FT_Init_FreeType( &library ) ) { fprintf( stderr, "%s: Could not initialize FreeType library.\n", ProgName ); exit(1); } /* 預先讀入 xfs 的 config 所指定的 Font path */ Read_xfsconfig(); switch ( argc ) { case 2: /* */ if ( strcmp( argv[1], "--list" ) == 0 ) { return ( List_All_Fontpath( ) ); } if ( strcmp( argv[1], "--auto" ) == 0 ) { Add_Font_Path( font_path, 1 ); return ( Rebuild_All_Dir( ) ); } if ( strcmp( argv[1], "--initcfg" ) == 0 ) { return ( Init_Config( ) ); } if ( strcmp( argv[1], "--rebuild" ) == 0 ) { return ( Rebuild_All_Dir( ) ); } if ( strcmp( argv[1], "--mkfdir" ) == 0 ) { return ( Make_Font_Dir( "." ) ); } Usage( ); return 1; case 3: /* */ if ( strcmp( argv[1], "--add" ) == 0 ) { mode = 'a'; } if ( strcmp( argv[1], "--remove" ) == 0 ) { mode = 'r'; } if ( strcmp( argv[1], "--info" ) == 0 ) { mode = 'i'; } if ( strcmp( argv[1], "--mkfdir" ) == 0 ) { mode = 'm'; } if ( strcmp( argv[1], "--addpath" ) == 0 ) { mode = 'A'; } if ( strcmp( argv[1], "--rmpath" ) == 0 ) { mode = 'R'; } break ; default: Usage( ); exit (1); } /* 新增、移除、查看 */ if ( mode == 'a' || mode == 'r' || mode == 'i' ) { if ( File_Exist( argv[2] ) == 0 ) { fprintf( stderr, "%s: \"%s\" not found.\n", ProgName, argv[2] ); exit(1); } if ( Check_Font_Face( argv[2] ) ) { fprintf( stderr, "%s: \"%s\" not a TrueType font.\n", ProgName, argv[2] ); exit(1); } } switch ( mode ) { case 'a': status = Add_Font( argv[2] ); break; case 'r': status = Remove_Font( argv[2] ); break; case 'i': status = Font_Info( argv[2] ); break; case 'm': status = Make_Font_Dir( argv[2] ); break; case 'A': status = Add_Font_Path( argv[2], 0 ); break; case 'R': status = Remove_Font_Path( argv[2] ); break; default: Usage( ); status = 1; } /* 關掉 FreeType Library */ FT_Done_FreeType( library ); return status ; } static int Check_Font_Face( char *filename ) { FT_Face face; int is_sfnt = 0; num_faces = 0; /* 先將 face 總數設為 0 */ /* 取得第一個(編號0) Face 的資料 */ if ( FT_New_Face( library, filename, 0, &face ) ) { return 1; } num_faces = face->num_faces; /* 紀錄共有多少個 faces */ is_sfnt = FT_IS_SFNT( face ); FT_Done_Face( face ); /* 檢查該檔案是否是 TrueType 檔 */ return is_sfnt; } static void Usage( void ) { printf( "\nX-TrueType Font Manager 0.9.6\n" ); printf( "\nUsage: %s [option]\n", ProgName ); printf( "option:\n" ); printf( " --add Add new TrueType font\n" ); printf( " --remove Remove TrueType font\n" ); printf( " --info View font informationt\n" ); printf( " --list List all font path\n" ); printf( " --auto Modify config file and rebuild all TrueType fonts\n" ); printf( " --initcfg Modify your \"XF86Config\" file\n" ); printf( " --rebuild Rebuild all TrueType fonts ( slowly )\n" ); printf( "\nexpert option:\n" ); printf( " --mkfdir name of the TrueType font directory, default is \".\"\n" ); printf( " --addpath [/dir name] Add a path to path table\n" ); printf( " --rmpath [/dir name] Remove a path from path table\n" ); printf( "\n" ); } static int List_All_Fontpath( void ) { int i; if ( num_fps == 0 ) { return 1; } printf( "\n" ); for ( i = 0 ; i < num_fps ; i ++ ) { printf( "%d: %s\n", i + 1, fpList[i].path ); } return 0; } /*---------------------------------- File_Exist - 檢查檔案是否存在的副程式 (1:存在, 0:不存在) ------------------------------------*/ static int File_Exist( char *path ) { FILE *fp = fopen( path, "r" ); int exist = 1; /* 預設為存在 */ if ( fp ) { fclose( fp ); } else { exist = 0; } return exist; } /********************************************************** * 強制建立目錄 **********************************************************/ static int Force_Mkdir( char *path ) { int ret = 0; /* 預設為成功 */ DIR *dir; int len = strlen( path ); char *workdir = (char *)malloc( len + 2 ); int i; /* 掃描字串 */ for ( i = 0 ; i < len ; i ++ ) { workdir[i] = path[i]; /* 如果有 '/' 字元出現,就查看有沒有這個目錄 */ if ( path[i] == '/' ) { workdir[i+1] = '\0'; dir = opendir( workdir ); if ( dir == NULL ) { ret = mkdir( workdir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH ); if ( ret != 0 ) break; } else { closedir( dir ); } } } free( workdir ); return ret; } /***************************************** * Add_Font - 新增字型 ******************************************/ static int Add_Font( char *filename ) { char link_name[256]; char copy_name[256]; char base_name[256]; strcpy( base_name, basename( filename ) ); /* 擷取檔名 */ /* 查看這個字型檔是否已經安裝過了 */ if ( Is_Install( base_name ) ) { fprintf( stderr, "\"%s\" has installed.\n", base_name ); return 1; } /* 製作完整路徑 */ strcpy( link_name, font_path ); strcat( link_name, base_name ); strcpy( copy_name, base_path ); strcat( copy_name, base_name ); /* 如果目的檔不存在,就複製過去 */ if ( File_Exist( copy_name ) == 0 ) { printf( "Copy \"%s\" to \"%s\"....\n", filename, copy_name ); if ( Copy_File( filename, copy_name ) != 0 ) { fprintf( stderr, "Can not copy \"%s\" to \"%s\"\n", filename, copy_name ); return 1; } } /* 做一個連結到剛複製的檔案 */ symlink( copy_name, link_name ); Gen_Encoding( filename ); Update_Font_Files( base_name, font_path ); XSet_fp( font_path ); printf( "\"%s\" has added OK.\n", base_name ); return ( Add_Font_Path( font_path, 0 ) ); } static int Copy_File( char *source, char *target ) { int ret = 0; /* 預設為成功 */ int s_fp, t_fp; char *buffer = (char *)malloc( 102400 ); int rbytes; s_fp = open( source, O_RDONLY ); if ( s_fp != -1 ) { t_fp = open( target, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); if ( t_fp != -1 ) { while ( ( rbytes = read( s_fp, buffer, 102400 ) ) > 0 ) { write( t_fp, buffer, rbytes ); } close( t_fp ); } else { ret = 1; } close( s_fp ); } else { ret = 1; } free( buffer ); return ret; } static int Is_Install( char *filename ) { FILE *fp; int ret = 0; /* 預設為沒有安裝 */ char *buffer = (char *)malloc( 512); if ( ( fp = fopen( font_dir, "r" ) ) != 0 ) { while ( fgets( buffer, 512, fp ) ) { if ( Stra_At_Strb( filename, buffer ) != -1 ) { ret = 1; break ; } } fclose( fp ); } return ret; } /*-------------------------------------------------------- * 找出字串 B 中是否有字串 A --------------------------------------------------------*/ static int Stra_At_Strb( char *stra, char *strb ) { int found = -1 ; /* 預設是沒有 */ int a_len = strlen( stra ); int b_len = strlen( strb ) - a_len; int i; for ( i = 0 ; i < b_len ; i ++ ) { if ( strncmp( stra, strb + i, a_len ) == 0 ) { found = i; break ; } } return found ; } static int Gen_Encoding( char *filename ) { FT_Face face; FT_CharMap charmap; TT_OS2 *os2; int face_idx, pos; /* 依序取出各個 Face 的資料 */ for ( face_idx=0 ; face_idx < num_faces ; face_idx++ ) { FT_New_Face( library, filename, face_idx, &face ); face->face_index = face_idx; os2 = FT_Get_Sfnt_Table( face, ft_sfnt_os2 ); for ( pos = 0 ; pos < face->num_charmaps ; pos ++ ) { charmap = face->charmaps[pos]; if ( charmap->encoding == ft_encoding_symbol ) { Add_XLFD( face, "microsoft-symbol" ); } if ( charmap->encoding == ft_encoding_unicode ) { Add_XLFD( face, "iso10646-1" ); } if ( charmap->encoding == ft_encoding_sjis ) { Add_XLFD( face, "jisx0201.1976-0" ); Add_XLFD( face, "jisx0208.1983-0" ); } if ( charmap->encoding == ft_encoding_gb2312 ) { Add_XLFD( face, "gb2312.1980-0" ); } if ( charmap->encoding == ft_encoding_big5 ) { Add_XLFD( face, "big5-0" ); Add_XLFD( face, "big5.cp950-0" ); Add_XLFD( face, "big5.eten-0" ); Add_XLFD( face, "big5hkscs-0" ); } if ( charmap->encoding == ft_encoding_wansung ) { Add_XLFD( face, "ksc5601.1987-0" ); } if ( charmap->encoding == ft_encoding_johab ) { Add_XLFD( face, "ksc5601.1987-0" ); } if ( os2->ulCodePageRange1 & TT_CODEPAGE_RANGE_932){ Add_XLFD( face, "jisx0208.1983-0" ); } if ( os2->ulCodePageRange1 & TT_CODEPAGE_RANGE_936){ Add_XLFD( face, "gb2312.1980-0" ); } if ( os2->ulCodePageRange1 & TT_CODEPAGE_RANGE_950){ Add_XLFD( face, "big5-0" ); Add_XLFD( face, "big5.cp950-0" ); Add_XLFD( face, "big5.eten-0" ); Add_XLFD( face, "big5hkscs-0" ); } if ( os2->ulCodePageRange1 & TT_CODEPAGE_RANGE_949){ Add_XLFD( face, "ksc5601.1987-0" ); } if ( os2->ulCodePageRange1 & TT_CODEPAGE_RANGE_1361){ Add_XLFD( face, "ksc5601.1987-0" ); } } Read_Encoding_Table( face ); /* 比對內部 encoding 表格 */ if ( !Read_Encoding_Dir( face ) ) { fprintf( stderr, "Warning: Can't reading \"%s\".\n", encodings_path ); fprintf( stderr, "some encoding may be lost.\n" ); } FT_Done_Face( face ); /* 關閉 face */ } return 0; } static void Read_Encoding_Table( FT_Face face ) { int idx = 0,i; int miss, sb; while ( single_table[idx].istable ) { miss = 0; sb = 0 ; while ( single_table[idx].mappingtable[sb] != NOCODE ) { if ( FT_Get_Char_Index( face, single_table[idx].mappingtable[sb] ) == 0 ) miss ++ ; sb ++ ; } if ( miss <= max_miss ) { i = 0; while ( single_table[idx].alias[i] !=NULL ) { Add_XLFD( face, (char *)single_table[idx].alias[i] ); i++; } } idx ++; } } static int Read_Encoding_Dir( FT_Face face ) { int num_encodings ; FILE *fd, *exist ; char buffer[1024]; char encoding[128]; char file_name[512]; fd = fopen( encodings_path, "r" ); if ( fd == NULL ) { return 0; /* 無法開啟就不繼續 */ } fscanf( fd, "%d\n", &num_encodings ); /* 讀取第一行,代表有多少個 encoding */ while ( fgets( buffer, 1024, fd ) ) { sscanf( buffer, "%s %s\n", encoding, file_name ); if ( ( exist = fopen( file_name, "r" ) ) != 0 ) { fclose( exist ); if ( Check_Dup_XLFD( face, encoding ) == 0 ) { if ( Check_Encoding( face, file_name ) ) { Add_XLFD( face, encoding ); } } } } fclose( fd ); return 1; } static int Check_Encoding( FT_Face face, char *file_name ) { FILE *input = NULL; gzFile *zinput = NULL; char line[512]; char *split[4] ; unsigned int i, j, sw; unsigned int miss = 0, num_chars = 0; unsigned int single_byte = 1; /* 1:單 byte 字集,0:雙 byte 字集 */ int start_range, end_range, char_code; float pmiss; char *endptr; char fmt; char *p; for ( i = 0 ; i < 4 ; i++ ) split[i] = (char *)malloc(512); if ( toupper( file_name[ strlen( file_name ) - 1 ] ) == 'Z' ) { zinput = gzopen( file_name, "r" ); fmt = 'z'; } else { input = fopen( file_name, "r" ); fmt = 'a'; } sw = 0; while ( 1 ) { if ( fmt == 'z' ) { p = gzgets( zinput, line, sizeof( line ) ); } else { p = fgets( line, sizeof( line ), input ); } if ( p == NULL ) break; for ( i = 0 ; i < 4; i++ ) split[i][0] = '\0'; /* /清除陣列 */ sscanf( line, "%s %s %s %s\n", split[0], split[1], split[2], split[3] ); if ( strncasecmp( split[0], "SIZE", 4 ) == 0 && strncasecmp( split[1], "0x", 2 ) == 0 && strncasecmp( split[2], "0x", 2 ) == 0 ) { single_byte = 0; continue ; } if ( strcasecmp( split[0], "STARTMAPPING" ) == 0 && strcasecmp( split[1], "unicode" ) == 0 ) { sw = 1; continue ; } if ( strcasecmp( split[0], "ENDMAPPING" ) == 0 ) { if ( sw ) break ; sw = 0; continue; } /* 取出字集內碼 * 必須第一以及第二元素皆為 0x 開頭 */ if ( sw && strncasecmp( split[0], "0x", 2 ) == 0 && strncasecmp( split[1], "0x", 2 ) == 0 ) { start_range = strtol( split[0], &endptr, 0 ); /* 如果第三個元素也是 0xNNNN 的話,表示這是一段 range */ if ( strncasecmp( split[2], "0x", 2 ) == 0 ) { end_range = strtol( split[1], &endptr, 0 ); char_code = strtol( split[2], &endptr, 0 ); } else { /* 否則就是 1 對 1 的關係 */ end_range = start_range; char_code = strtol( split[1], &endptr, 0 ); } for ( j = start_range ; j <= end_range ; j ++ ) { if ( FT_Get_Char_Index( face, char_code ) == 0 ) { miss ++; } char_code ++; num_chars ++; } } } if ( fmt == 'z' ) { gzclose( zinput ); } else { fclose( input ); } for ( i = 0 ; i < 4 ; i++ ) free( split[i] ); if ( num_chars == 0 ) { return 0; } /* 如果是單字元字集的話,最多允許 miss 掉 5 個字 */ if ( single_byte ) { return ( miss <= max_miss ? 1 : 0 ); } else { /* CJK 字元集允許 miss 掉 4 % 以下個字 */ pmiss = ( ( miss * 100 ) / num_chars ); return ( pmiss <= 3 ? 1 : 0 ); } } static int Add_XLFD( FT_Face face, char *encoding_name ) { TT_OS2 *os2; int pos, len, i; char foundry_name[128]; /* 看看有沒有重複的 encoding */ if ( Check_Dup_XLFD( face, encoding_name ) ) return 0; os2 = FT_Get_Sfnt_Table( face, ft_sfnt_os2 ); num_xlfds++; xlfdList = realloc( xlfdList, sizeof( struct xlfd_rec ) * num_xlfds ); pos = num_xlfds - 1 ; switch ( os2->usWeightClass ) { case TT_FW_THIN: strcpy( xlfdList[pos].weight, "thin" ); break ; case TT_FW_EXTRALIGHT: strcpy( xlfdList[pos].weight, "extra light" ); break ; case TT_FW_LIGHT: strcpy( xlfdList[pos].weight, "light" ); break; case TT_FW_SEMIBOLD: strcpy( xlfdList[pos].weight, "semi bold" ); break ; case TT_FW_BOLD: strcpy( xlfdList[pos].weight, "bold" ); break ; case TT_FW_EXTRABOLD: strcpy( xlfdList[pos].weight, "extra bold" ); break ; case TT_FW_BLACK: strcpy( xlfdList[pos].weight, "black" ); break; case TT_FW_NORMAL: case TT_FW_MEDIUM: default: strcpy( xlfdList[pos].weight, "medium" ); break ; } switch ( os2->usWidthClass ) { case TT_FWIDTH_ULTRA_CONDENSED: strcpy( xlfdList[pos].width, "ultra condensed" ); break; case TT_FWIDTH_EXTRA_CONDENSED: strcpy( xlfdList[pos].width, "extra condensed" ); break; case TT_FWIDTH_CONDENSED: strcpy( xlfdList[pos].width, "condensed" ); break; case TT_FWIDTH_SEMI_CONDENSED: strcpy( xlfdList[pos].width, "semi condensed" ); break; case TT_FWIDTH_SEMI_EXPANDED: strcpy( xlfdList[pos].width, "semi expanded" ); break; case TT_FWIDTH_EXPANDED: strcpy( xlfdList[pos].width, "expanded" ); break; case TT_FWIDTH_EXTRA_EXPANDED: strcpy( xlfdList[pos].width, "extra expanded" ); break; case TT_FWIDTH_ULTRA_EXPANDED: strcpy( xlfdList[pos].width, "ultra expanded" ); break; default: strcpy( xlfdList[pos].width, "normal" ); break; } xlfdList[pos].slant = os2->fsSelection & TT_SELECTION_ITALIC ? 'i' : 'r'; xlfdList[pos].face_no = face->face_index; /* 紀錄 face no */ xlfdList[pos].has_big = ( face->units_per_EM > 1024 ) ? 1 : 0; if ( Is_CJK( encoding_name ) ) { xlfdList[pos].spacing = 'c'; /* cjk or unicode 一律為 c */ } else { xlfdList[pos].spacing = FT_IS_FIXED_WIDTH(face) ? 'm' : 'p'; } /* family name 不可帶有 "-" 字元,換成 "_" */ if ( face->family_name ) { strcpy( xlfdList[pos].family, face->family_name ); } else { Get_Name_String( face, TT_NAME_ID_FONT_FAMILY, xlfdList[pos].family ); } len = strlen( xlfdList[pos].family ); for ( i = 0 ; i < len ; i++ ) { if ( xlfdList[pos].family[i] == '-' ) xlfdList[pos].family[i] = '_'; } xlfdList[pos].family[len] = '\0'; Get_Foundry_Name( face, foundry_name ); strcpy( xlfdList[pos].foundry, foundry_name ); strcpy( xlfdList[pos].encoding_name, encoding_name ); return 0; } /* 檢查是否為 CJK 字元集 */ static int Is_CJK( char *encoding_name ) { char *cjk[] = { "big5", "gb", "jis", "ksc", "ksx", "iso10646" }; int iscjk = 0; /* 預設為否 */ int pos = 0; for ( pos = 0 ; pos < 6 ; pos ++ ) { if ( strncasecmp( cjk[ pos ], encoding_name, strlen( cjk[ pos ] ) ) == 0 ){ iscjk = 1; break; } } return iscjk; } static void Get_Foundry_Name( FT_Face face, char *buffer ) { TT_OS2 *os2 = FT_Get_Sfnt_Table( face, ft_sfnt_os2 ); char code[5]; int found = 0; static struct { const char code[4]; const char *foundry; } *p, foundries[] = { { "2REB", "2Rebels"}, { "3ip" , "Three Islands Press"}, { "3ip ", "Three Islands Press"}, { "ABC" , "Altek Instruments"}, { "ABC ", "Altek Instruments"}, { "ACUT", "Acute Type"}, { "ADBE", "adobe"}, { "AGFA", "Agfa Typographic Systems"}, { "ALTS", "altsys"}, { "AOP" , "An Art of Penguin"}, { "AOP ", "An Art of Penguin"}, { "APPL", "Apple"}, { "ARPH", "Arphic Technology Co."}, { "ATEC", "alltype"}, { "AZLS", "Azalea Software, Inc."}, { "B&H", "b&h"}, { "B&H ", "b&h"}, { "BARS", "CIA (BAR CODES) UK"}, { "BERT", "Berthold"}, { "BITM", "Bitmap Software"}, { "BITS", "Bitstream"}, { "BLAH", "Mister Bla's Fontworx"}, { "BOYB", "I. Frances"}, { "BRTC", "Bear Rock Technologies"}, { "BWFW", "B/W Fontworks"}, { "C&C", "Carter & Cone"}, { "C&C ", "Carter & Cone"}, { "CAK" , "pluginfonts.com"}, { "CAK ", "pluginfonts.com"}, { "CANO", "cannon"}, { "CASL", "H.W. Caslon & Company Ltd."}, { "COOL", "Cool Fonts"}, { "CTDL", "China Type Design Ltd."}, { "DAMA", "Dalton Maag Limited"}, { "DS" , "Dainippon Screen Mfg. Co., Inc."}, { "DS ", "Dainippon Screen Mfg. Co., Inc."}, { "DSCI", "Design Science, Inc."}, { "DTC", "Digital Typeface Corp."}, { "DTC ", "Digital Typeface Corp."}, { "DTPS", "DTP Software"}, { "DUXB", "Duxbury Systems, Inc."}, { "DYNA", "DynaLab"}, { "ECF" , "emerald city fontwerks"}, { "ECF ", "emerald city fontwerks"}, { "EDGE", "Rivers Edge Corp."}, { "EFF" , "Electronic Font Foundry"}, { "EFF ", "Electronic Font Foundry"}, { "EFNT", "E Fonts L.L.C."}, { "ELSE", "elseware"}, { "EPSN", "epson"}, { "ERAM", "eraman"}, { "ESIG", "E_Signature"}, { "FBI", "The Font Bureau, Inc."}, { "FBI ", "The Font Bureau, Inc."}, { "FCAB", "The Font Cabinet"}, { "FJ", "Fujitsu"}, { "FJ ", "Fujitsu"}, { "FONT", "Font Source"}, { "FS" , "Formula Solutions"}, { "FS ", "Formula Solutions"}, { "FSE" , "Font Source Europe"}, { "FSE ", "Font Source Europe"}, { "FSI" , "FSI Fonts und Software GmbH"}, { "FSI ", "FSI Fonts und Software GmbH"}, { "FTFT", "FontFont"}, { "FWRE", "Fontware Limited"}, { "GALA", "Galapagos"}, { "GD" , "GD Fonts"}, { "GD ", "GD Fonts"}, { "GLYF", "Glyph Systems"}, { "GPI", "Gamma Productions, Inc."}, { "GPI ", "Gamma Productions, Inc."}, { "HILL", "Hill Systems"}, { "HOUS", "House Industries"}, { "HP", "hp"}, { "HP ", "hp"}, { "HY", "HanYang System"}, { "HY ", "HanYang System"}, { "IBM", "IBM"}, { "IBM ", "IBM"}, { "IDEE", "IDEE TYPOGRAFICA"}, { "IDF", "International Digital Fonts"}, { "IDF ", "International Digital Fonts"}, { "ILP", "Indigenous Languages Project"}, { "ILP ", "Indigenous Languages Project"}, { "ITC", "itc"}, { "ITC ", "itc"}, { "IMPR", "impress"}, { "ITF" , "International Typefounders, Inc."}, { "ITF ", "International Typefounders, Inc."}, { "KATF", "Kingsley/ATF"}, { "LANS", "Lanston Type Co., Ltd."}, { "LARA", "Larabiefonts"}, { "LEAF", "Interleaf, Inc."}, { "LETR", "letraset"}, { "LGX" , "Logix Research Institute, Inc."}, { "LGX ", "Logix Research Institute, Inc."}, { "LING", "Linguist's Software"}, { "LINO", "linotype"}, { "LP", "LetterPerfect Fonts"}, { "LP ", "LetterPerfect Fonts"}, { "LTRX", "lighttracks"}, { "MACR", "macromedia"}, { "MC" , "Cerajewski Computer Consulting"}, { "MC ", "Cerajewski Computer Consulting"}, { "MILL", "Millan"}, { "MJ" , "Majus Corporation"}, { "MJ ", "Majus Corporation"}, { "MLGC", "Micrologic Software"}, { "MONO", "monotype"}, { "MS", "microsoft"}, { "MS ", "microsoft"}, { "MSCR", "Majus Corporation"}, { "MT", "monotype"}, { "MT ", "monotype"}, { "MTY" , "Motoya Co. ,LTD."}, { "MTY ", "Motoya Co. ,LTD."}, { "MUTF", "CACHE Enterprise Sdn. Bhd"}, { "NB" , "No Bodoni Typography"}, { "NB ", "No Bodoni Typography"}, { "NDTC", "Neufville Digital"}, { "NEC", "nec"}, { "NEC ", "nec"}, { "NIS" , "NIS Corporation"}, { "NIS ", "NIS Corporation"}, { "ORBI", "Orbit Enterprises, Inc."}, { "P22" , "P22 Inc."}, { "P22 ", "P22 Inc."}, { "PARA", "ParaType"}, { "PDWX", "Parsons Design Workx"}, { "PF" , "Phil's Fonts, Inc."}, { "PF ", "Phil's Fonts, Inc."}, { "PRFS", "Production First Software"}, { "QMSI", "QMS/Imagen"}, { "RICO", "Ricoh"}, { "RKFN", "R K Fonts"}, { "robo", "Buro Petr van Blokland"}, { "RUDY", "RudynFluffy"}, { "SAX" , "s.a.x. Software gmbh"}, { "SAX ", "s.a.x. Software gmbh"}, { "Sean", "The FontSite"}, { "SFI" , "Software Friends"}, { "SFI ", "Software Friends"}, { "SFUN", "Soft Union"}, { "SG" , "Scooter Graphics"}, { "SG ", "Scooter Graphics"}, { "SIG" , "Signature Software, Inc."}, { "SIG ", "Signature Software, Inc."}, { "skz" , "Celtic Lady's Fonts"}, { "skz ", "Celtic Lady's Fonts"}, { "SN" , "SourceNet"}, { "SN ", "SourceNet"}, { "SOHO", "Soft Horizons"}, { "SOS" , "Standing Ovations Software"}, { "SOS ", "Standing Ovations Software"}, { "STF" , "Brian Sooy & Co + Sooy Type Foundry"}, { "STF ", "Brian Sooy & Co + Sooy Type Foundry"}, { "STON", "ZHUHAI Stone"}, { "SUNW", "sunwalk fontworks"}, { "SWFT", "Swfte International"}, { "SYN" , "SynFonts"}, { "SYN ", "SynFonts"}, { "TDR" , "Tansin A. Darcos & Co."}, { "TDR ", "Tansin A. Darcos & Co."}, { "TF" , "Treacyfaces/Headliners"}, { "TF ", "Treacyfaces/Headliners"}, { "TILD", "SIA Tilde"}, { "TPTC", "TEST PILOT"}, { "TR" , "Type Revivals"}, { "TR ", "Type Revivals"}, { "TS" , "TamilSoft Corporation"}, { "TS ", "TamilSoft Corporation"}, { "UA" , "UnAuthorized Type"}, { "UA ", "UnAuthorized Type"}, { "URW", "urw"}, { "URW ", "urw"}, { "VKP" , "Vijay K. Patel"}, { "VKP ", "Vijay K. Patel"}, { "VLKF", "Visualogik Technology & Design"}, { "VOG" , "Martin Vogel"}, { "VOG ", "Martin Vogel"}, { "Y&Y" , "y&y"}, { "Y&Y ", "y&y"}, { "ZeGr", "Zebra Font Factory"}, { "zeta", "Tangram Studio"}, { "ZSFT", "ZSoft"}, { {0,}, 0} }; code[0] = toupper(os2->achVendID[0]); code[1] = toupper(os2->achVendID[1]); code[2] = toupper(os2->achVendID[2]); code[3] = toupper(os2->achVendID[3]); code[4] = 0; for ( p = foundries ; p->foundry ; p++ ) { if ( memcmp( p->code, code, strlen( code ) ) == 0 ) { strcpy( buffer, p->foundry ); found = 1; break; } } if ( !found ) { strcpy( buffer, "misc" ); } } static int Check_Dup_XLFD( FT_Face face, char *encoding_name ) { int Isdup = 0; /* 預設是沒有 */ int i; if ( num_xlfds > 0) { for ( i = 0 ; i < num_xlfds ; i ++ ) { if ( xlfdList[i].face_no == face->face_index && strcmp( xlfdList[i].encoding_name, encoding_name ) == 0 ) { Isdup = 1; break; } } } return Isdup ; } /* 在指定的目錄下,產生 fonts.dir 以及 fonts.scale */ static int Update_Font_Files( char *font_file, char *path ) { char *weight_table[] = { "medium", "bold" }; char *ds_table[] = { "\0", "ds=y:" }; char *slant_table[] = { "r", "i" }; char *ai_table[] = { "\0", "ai=0.3:" }; char fn[64]; int wcnt, scnt; int num_lines; FILE *fontdirfp, *fontscalefp; FILE *tmpfp; char buffer[512]; char f_dir[256], f_scale[256]; int i; char bw[10]; tmpfp = fopen( temp_file, "w+" ); /* 開啟暫存檔 */ if ( !tmpfp ) { fprintf( stderr, "Can't open temp file \"%s\".\n", temp_file); return 1; } strcpy( f_dir, path ); strcat( f_dir, "fonts.dir" ); strcpy( f_scale, path ); strcat( f_scale, "fonts.scale" ); if ( File_Exist( f_dir ) ) { fontdirfp = fopen( f_dir, "r+" ); if ( fontdirfp ) { fscanf( fontdirfp, "%d\n", &num_lines ); num_lines = 0; while ( fgets( buffer, 512, fontdirfp ) ) { fputs( buffer, tmpfp); num_lines ++; } fclose( fontdirfp ); } } else { num_lines = 0; } for ( i = 0 ; i < num_xlfds ; i ++ ) { for ( wcnt = 0 ; wcnt < 2 ; wcnt ++ ) { for ( scnt = 0 ; scnt < 2 ; scnt ++ ) { if ( xlfdList[i].face_no == 0 ) { fn[0] = '\0'; } else { sprintf( fn, "fn=%d:", xlfdList[i].face_no ); } if ( xlfdList[i].spacing == 'c'&& xlfdList[i].has_big ) { strcpy( bw, "bw=0.5:" ); } else { bw[0] = '\0'; } fprintf( tmpfp, "%s%s%s%s%s%s -%s-%s-%s-%s-%s--0-0-0-0-%c-0-%s\n", fn, ( xlfdList[i].spacing == 'm' ) ? "vl=y:eb=y:" : "\0", bw, ds_table[wcnt], ai_table[scnt], font_file, xlfdList[i].foundry, xlfdList[i].family, weight_table[wcnt], slant_table[scnt], xlfdList[i].width, xlfdList[i].spacing, xlfdList[i].encoding_name ); num_lines ++; } } } rewind( tmpfp ); /* 將原來的 fonts.dir 內容清空 */ fontdirfp = fopen( f_dir, "w" ); fontscalefp = fopen( f_scale, "w" ); fprintf( fontdirfp, "%d\n", num_lines ); fprintf( fontscalefp, "%d\n", num_lines ); while ( fgets( buffer, 512, tmpfp ) ) { fputs( buffer, fontdirfp ); fputs( buffer, fontscalefp ); } fclose( tmpfp ); fclose( fontdirfp ); fclose( fontscalefp ); remove( temp_file ); /* 移除暫存檔案 */ return 0; } /************************************************************************** * * 移除字型設定 * *************************************************************************/ static int Remove_Font( char *filename ) { FILE *fontdirfp; FILE *fontscalefp; FILE *tmpfp; char *base_name; char *link_name; int base_len = strlen( basename( filename ) ); char buffer[512]; int num_lines; base_name = (char *)malloc( base_len + 1 ); /* 配置空間 */ strcpy( base_name, basename( filename ) ); /* 擷取檔名 */ if ( !Is_Install( base_name ) ) { fprintf( stderr, "\"%s\" not installed.\n", base_name ); return 1; } /* 配置空間 */ link_name = (char *)malloc( strlen(font_path) + base_len + 1 ); /* 製作完整路徑 */ strcpy( link_name, font_path ); strcat( link_name, base_name ); fontdirfp = fopen( font_dir, "r" ); tmpfp = fopen( temp_file, "w+" ); /* 讀取 fonts.dir 並過濾掉移除的字型後,寫入暫存檔 */ if ( fontdirfp && tmpfp ) { fscanf( fontdirfp, "%d\n", &num_lines ); num_lines = 0; while ( fgets( buffer, 512, fontdirfp ) ) { if ( Stra_At_Strb( base_name, buffer ) == -1 ) { fputs( buffer, tmpfp); num_lines ++; /* 紀錄寫入的行數 */ } } fclose( fontdirfp ); } /* */ rewind( tmpfp ); fontdirfp = fopen( font_dir, "w" ); fontscalefp = fopen( font_scale, "w" ); if ( fontdirfp && fontscalefp) { fprintf( fontdirfp, "%d\n", num_lines ); fprintf( fontscalefp, "%d\n", num_lines ); while ( fgets( buffer, 512, tmpfp ) ) { fputs( buffer, fontdirfp ); fputs( buffer, fontscalefp ); } fclose( fontdirfp ); fclose( fontscalefp ); } fclose( tmpfp ); remove( temp_file ); /* 移除暫存檔案 */ remove( link_name ); /* 移除連結*/ printf( "\"%s\" has removed OK.\n", base_name ); free( base_name ); free( link_name ); XSet_fp( font_path ); return 0; } /************************************************************************** * * 顯示字型的詳細資訊 * *************************************************************************/ static int Font_Info( char *filename ) { FT_Face face; FT_ULong face_idx; FT_Int pos, num_encodings; FT_CharMap charmap; TT_OS2 *os2; FT_UShort platform_id, encoding_id; char *platform_name=NULL; char *encoding_name=NULL; int i; char copyright[1024]; char version[1024]; char trademark[1024]; char family_name[256]; char style_name[256]; char postscript_name[256]; char foundry_name[128]; Gen_Encoding( filename ); /* 依序取出各個 Face 的資料 */ for ( face_idx = 0 ; face_idx < num_faces ; face_idx++ ) { FT_New_Face( library, filename, face_idx, &face ); os2 = FT_Get_Sfnt_Table( face, ft_sfnt_os2 ); printf( "============ Face index : %ld ============\n", face_idx ); Get_Name_String( face, TT_NAME_ID_COPYRIGHT, copyright ); printf( "版權資訊 : %s\n", copyright ); Get_Name_String( face, TT_NAME_ID_VERSION_STRING, version ); printf( "版本資訊 : %s\n", version ); Get_Name_String( face, TT_NAME_ID_TRADEMARK, trademark ); printf( "商標資訊 : %s\n", trademark ); Get_Foundry_Name( face, foundry_name ); printf( " 製造商 : %s\n", foundry_name ); printf( "..........................................\n\n" ); #if 1 Get_Name_String( face, TT_NAME_ID_FONT_FAMILY, family_name ); Get_Name_String( face, TT_NAME_ID_FONT_SUBFAMILY, style_name ); Get_Name_String( face, TT_NAME_ID_PS_NAME, postscript_name ); #endif #if 0 if ( face->family_name ) { strcpy( family_name, face->family_name ); strcpy( postscript_name, FT_Get_Postscript_Name( face ) ); } else { Get_Name_String( face, TT_NAME_ID_FONT_FAMILY, family_name ); Get_Name_String( face, TT_NAME_ID_PS_NAME, postscript_name ); } if ( face->style_name ) { strcpy( style_name, face->style_name ); } else { Get_Name_String( face, TT_NAME_ID_FONT_SUBFAMILY, style_name ); } #endif printf( "Font family name : %s\n", family_name ); printf( "Font style name : %s\n", style_name ); printf( "Postscript name : %s\n", postscript_name ); printf( "Number of glyphs : %ld\n", face->num_glyphs ); printf( "..........................................\n\n" ); /*module = &face->driver->root; printf( "模組名稱 : %s\n", module->clazz->module_name );*/ printf( "\nFace flags :\n" ); printf( " HAS_HORIZONTAL : %s\n", FT_HAS_HORIZONTAL( face ) ? "yes" : "no" ); printf( " HAS_VERTICAL : %s\n", FT_HAS_VERTICAL( face ) ? "yes" : "no" ); printf( " HAS_KERNING : %s\n", FT_HAS_KERNING( face ) ? "yes" : "no" ); printf( " IS_SCALABLE : %s\n", FT_IS_SCALABLE( face ) ? "yes" : "no" ); printf( " IS_SFNT : %s\n", FT_IS_SFNT( face ) ? "yes" : "no" ); printf( " IS_FIXED_WIDTH : %s\n", FT_IS_FIXED_WIDTH( face ) ? "yes" : "no" ); printf( " HAS_FIXED_SIZES : %s\n", FT_HAS_FIXED_SIZES( face ) ? "yes" : "no" ); printf( " HAS_FAST_GLYPHS : %s\n", FT_HAS_FAST_GLYPHS( face ) ? "yes" : "no" ); printf( " HAS_GLYPH_NAMES : %s\n", FT_HAS_GLYPH_NAMES( face ) ? "yes" : "no" ); printf( " HAS_MULTIPLE_MASTERS : %s\n", FT_HAS_MULTIPLE_MASTERS( face ) ? "yes" : "no" ); if ( face->num_fixed_sizes > 0 ) { printf( "\n%d 種固定 Size (Height x Width) :\n", face->num_fixed_sizes ); for ( pos = 0 ; pos < face->num_fixed_sizes ; pos++ ) { printf( " (%d). : %d x %d \n", pos, face->available_sizes[pos].height, face->available_sizes[pos].width ); } } printf( " Units per_EM : %d\n", face->units_per_EM ); printf( " ascender : %d", face->ascender ); printf( " descender : %d", face->descender ); printf( " Height : %d\n", face->height ); printf( " Max advance width : %d, Max advance height :%d\n", face->max_advance_width, face->max_advance_height ); printf( " Underline position :%d\n",face->underline_position ); printf( " Underline thickness :%d\n",face->underline_thickness ); printf( " (xMin:%ld, yMin:%ld)\n", face->bbox.xMin, face->bbox.yMin ); printf( " (xMax:%ld, yMax:%ld)\n", face->bbox.xMax, face->bbox.yMax ); printf( "..........................................\n" ); printf( "\nCharacter maps = %d\n", face->num_charmaps ); for ( pos = 0 ; pos < face->num_charmaps ; pos ++ ) { charmap = face->charmaps[pos]; platform_id = charmap->platform_id; encoding_id = charmap->encoding_id; switch ( platform_id ) { case TT_PLATFORM_APPLE_UNICODE: platform_name = "Apple Unicode"; break; case TT_PLATFORM_MACINTOSH: platform_name = "Apple"; break; case TT_PLATFORM_ISO: platform_name = "Iso"; break; case TT_PLATFORM_MICROSOFT: platform_name = "Windows"; break; case TT_PLATFORM_CUSTOM: platform_name = "Custom"; break; case TT_PLATFORM_ADOBE: platform_name = "Adobe"; break; default: platform_name = "Unknow"; break; } if ( charmap->encoding == ft_encoding_none ) { encoding_name = "none"; } else if ( charmap->encoding == ft_encoding_symbol ) { encoding_name = "Symbol"; } else if ( charmap->encoding == ft_encoding_unicode ) { encoding_name = "Unicode"; } else if ( charmap->encoding == ft_encoding_latin_2 ) { encoding_name = "Latin2"; } else if ( charmap->encoding == ft_encoding_sjis ) { encoding_name = "Shift-JIS"; } else if ( charmap->encoding == ft_encoding_gb2312 ) { encoding_name = "Gb2312"; } else if ( charmap->encoding == ft_encoding_big5 ) { encoding_name = "Big5"; } else if ( charmap->encoding == ft_encoding_wansung ) { encoding_name = "Wansung"; } else if ( charmap->encoding == ft_encoding_johab ) { encoding_name = "Johab"; } else if ( charmap->encoding == ft_encoding_adobe_standard ) { encoding_name = "Standard"; } else if ( charmap->encoding == ft_encoding_adobe_expert ) { encoding_name = "Expert"; } else if ( charmap->encoding == ft_encoding_adobe_custom ) { encoding_name = "Custom"; } else if ( charmap->encoding == ft_encoding_apple_roman ) { encoding_name = "Roman"; } else encoding_name = "unknow"; printf( " Map %d, platform_id : %d(%s), encoding_id : %d(%s)\n", pos, platform_id, platform_name, encoding_id, encoding_name ); } FT_Done_Face( face ); num_encodings = 0; printf( "\n字元集 :\n" ); for ( i = 0 ; i < num_xlfds ; i ++ ) { if ( xlfdList[i].face_no == face_idx ) { printf( " %s\n", xlfdList[i].encoding_name ); num_encodings ++; } } printf( "..........................................\n" ); } return 0; } static int Get_Name_String( FT_Face face, FT_UShort name_id, char *buffer ) { FT_UInt sfnt_count; FT_SfntName sfnt_name; FT_UShort idx; /* 取得資訊總數 */ sfnt_count = FT_Get_Sfnt_Name_Count( face ); for ( idx = 0 ; idx < sfnt_count ; idx++ ) { FT_Get_Sfnt_Name( face, idx, &sfnt_name ); if ( sfnt_name.name_id == name_id && sfnt_name.encoding_id == 0 ) { strncpy( buffer, (char *)sfnt_name.string, sfnt_name.string_len ); buffer[ sfnt_name.string_len ] = '\0' ; return 1; } } buffer[0] = '\0'; return 0; } static int Init_Config( void ) { FILE *confp, *tmpfp; char buffer[512]; char split1[512]; char split2[512]; char conf_file[256]; int i; int mode = 0; int have_xtt = 0; if ( !File_Exist( conf_path ) ) { fprintf( stderr, "Warning: Can't find `%s'.\n", conf_path ); fprintf( stderr, "Using config file :`%s'.\n", conf3_path ); strcpy( conf_file, conf3_path ); } else { strcpy( conf_file, conf_path ); } chmod( conf_file, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH ); confp = fopen( conf_file, "r" ); tmpfp = fopen( temp_file, "w+" ); while ( fgets( buffer, sizeof( buffer ), confp ) ) { split1[0] = '\0'; split2[0] = '\0'; sscanf( buffer, "%s %s\n", split1, split2 ); switch ( mode ) { case 1: if ( strncasecmp( "FontPath", split1, 8 ) == 0 ) { continue; } break; case 2: if ( strncasecmp( "Load", split1, 4 ) == 0 ) { if ( strncasecmp( "\"freetype\"",split2,10) ==0 || strncasecmp( "\"xtt\"",split2,5) == 0 || strncasecmp( "\"type1\"",split2,7) == 0 ) { if ( strncasecmp( "\"xtt\"",split2,5) == 0 ) { have_xtt = 1; } continue; } } break ; } fputs( buffer, tmpfp ); if ( strncasecmp( "Section", split1, 7 ) == 0 && strncasecmp( "\"Files\"" , split2, 7 ) == 0 ) { for ( i = 0 ; i < num_fps ; i++ ) { sprintf( buffer, " FontPath \"%s\"\n", fpList[i].path ); fputs( buffer, tmpfp ); XSet_fp( fpList[i].path ); } fputs( " FontPath \"unix/:7100\"\n", tmpfp ); mode = 1; continue; } if ( strncasecmp( "Section", split1, 7 ) == 0 && strncasecmp( "\"Module\"" , split2, 8 ) == 0 ) { sprintf( buffer, " Load \"xtt\"\n" ); fputs( buffer, tmpfp ); sprintf( buffer, " Load \"type1\"\n" ); fputs( buffer, tmpfp ); mode = 2; continue; } if ( strncasecmp( "EndSection", split1, 10 ) == 0 ) { if ( mode == 1 && have_module == 0 ) { fputs( "\nSection \"Module\"\n", tmpfp ); fputs( " Load \"xtt\"\n", tmpfp ); fputs( " Load \"type1\"\n", tmpfp ); fputs( " Load \"dbe\"\n", tmpfp ); fputs( " Load \"GLcore\"\n", tmpfp ); fputs( " Load \"dri\"\n", tmpfp ); fputs( " Load \"glx\"\n", tmpfp ); fputs( " Load \"extmod\"\n", tmpfp ); fputs( "EndSection\n\n", tmpfp ); } mode = 0; } } fclose( confp ); confp = fopen( conf_file, "w" ); rewind( tmpfp ); while ( fgets( buffer, sizeof( buffer ), tmpfp ) ) { fputs( buffer, confp ); } fclose( confp ); fclose( tmpfp ); remove( temp_file ); printf( "Your `%s\' has been modifed. ^^\n", conf_file ); if ( !have_xtt ) { printf( "You must restart X-Window system now.\n" ); } return 0; } /* 讀取 xfs 之 config 內的 fontpath 返回值就是總數 0:沒有讀到任何資料 */ static int Read_xfsconfig( void ) { FILE *xfsfp, *confp; char conf_file[256]; char buffer[512]; char split1[512]; char split2[512]; char split3[512]; num_fps = 0; num_cons = 0; xfsfp = fopen( fsconfig, "r" ); /* 開啟 xfs 的字型設定檔 */ if ( xfsfp ) { while ( fgets( buffer, sizeof( buffer ), xfsfp ) ) { split1[0] = '\0'; split2[0] = '\0'; split3[0] = '\0'; sscanf( buffer, "%s %s %s\n", split1, split2 ,split3 ); if ( strncasecmp( "catalogue", split1, 9 ) == 0 ) { strcpy( split1, split3 ); } if ( split1[0] == '/' ) { num_fps ++; if ( split1[strlen(split1)-1] == ',' ) { split1[strlen(split1)-1] = '\0'; } fpList = realloc( fpList, sizeof( struct fp_rec ) * num_fps ); strcpy( fpList[num_fps-1].path, split1 ); } } fclose( xfsfp ); } else { fprintf( stderr, "Warning: Can't Read \"%s\".\n", fsconfig ); return 0; } if ( !File_Exist( conf_path ) ) { strcpy( conf_file, conf3_path ); } else { strcpy( conf_file, conf_path ); } confp = fopen( conf_file, "r" ); if ( confp == NULL ) return 0; while ( fgets( buffer, sizeof( buffer ), confp ) ) { split1[0] = '\0'; split2[0] = '\0'; sscanf( buffer, "%s %s\n", split1, split2 ); /* 找到 Section "Module" */ if ( strncasecmp( "Section", split1, 7 ) == 0 && strncasecmp( "\"Module\"" , split2, 8 ) == 0 ) { have_module = 1; } } fclose( confp ); return num_fps; } static int Make_Font_Dir( char *fontpath ) { char ext[5]; char len; char curpath[256]; DIR *dir; struct dirent *dirent; struct stat stat; int num_files = 0; int delete = 1; char pwd[256]; /* 判斷行尾是否有 '/',沒有的話就加上 */ strcpy( curpath, fontpath ); len = strlen( curpath ); if ( curpath[ len - 1 ] != '/' ) strcat( curpath, "/" ); /* 看看是否為實際目錄 */ if ( ( dir = opendir( curpath ) ) == NULL ) { printf( "%s: \"%s\" not a directory\n", ProgName, fontpath ); return 1; } /* 掃描目錄下的 TrueType 檔 */ chdir( curpath ); getcwd( pwd, sizeof( pwd ) ); while ( ( dirent = readdir( dir ) ) != NULL ) { /* 排除目錄 */ lstat( dirent->d_name, &stat ); if ( S_ISDIR( stat.st_mode ) ) continue; /* 檢查副檔名是否為 ttf or ttc */ len = strlen( dirent->d_name ); if ( len < 4 ) continue; strncpy( ext, dirent->d_name + len - 4, 4 ); if ( strncasecmp( ext, ".ttf", 4 ) !=0 && strncasecmp( ext, ".ttc", 4 ) !=0 ) continue; num_files ++; printf( "checking %s ", dirent->d_name ); if ( Check_Font_Face( dirent->d_name ) ) { printf( "[fail]\n" ); } else { if ( delete == 1 ) { remove( "encodings.dir" ); remove( "fonts.dir" ); remove( "fonts.scale" ); remove( "fonts.alias" ); remove( "XftCache" ); delete = 0; } num_xlfds = 0; Gen_Encoding( dirent->d_name ); Update_Font_Files( dirent->d_name, curpath ); printf( "[OK]\n" ); if ( num_xlfds ) { free( xlfdList ); xlfdList = NULL; } } } closedir( dir ); /* 關閉目錄 */ if ( num_files == 0 ) { fprintf( stderr, "%s: can't find any TrueType files\n", ProgName ); } else { Add_Font_Path( pwd, 0 ); } return 0; } static int Rebuild_All_Dir( void ) { int i; char yn = ' '; while ( yn != 'y' && yn != 'n' && yn != '\013') { printf( "\nWarning: Rebuild all TrueType fonts should take a period time.\n"); printf( "Are you sure ( y / n ) ? default is 'n' :" ); yn = getchar(); } if ( yn == 'y' ) { for ( i = 0 ; i < num_fps ; i ++ ) { printf( "Rebuilding %s..................\n", fpList[i].path ); Make_Font_Dir( fpList[i].path ); XSet_fp( fpList[i].path ); } } return 0; } static void XSet_fp( char *path ) { char cmd[256]; char dir[256]; strcpy( dir, path ); if ( dir[ strlen( path ) - 1 ] == '/' ) dir[ strlen( path ) - 1 ] = '\0'; sprintf( cmd, "xset -fp %s 2>/dev/null 1>/dev/null", dir ); system( cmd ); sprintf( cmd, "xset +fp %s 2>/dev/null 1>/dev/null", dir ); system( cmd ); } static int Update_XfsConfig( void ) { FILE *xfsfp, *tmpfp; char buffer[512]; char split[512]; int i, k; if ( num_fps == 0 ) return 1; /* 將 FontPath 排序 */ for ( i = 0 ; i < num_fps ; i ++ ) { if ( Stra_At_Strb( ":", fpList[i].path ) == -1 ) { for ( k = i + 1 ; k < num_fps ; k ++ ) { if ( strcmp( fpList[i].path, fpList[k].path ) > 0 ) { strcpy( buffer, fpList[i].path ); strcpy( fpList[i].path, fpList[k].path ); strcpy( fpList[k].path, buffer ); } } } } tmpfp = fopen( temp_file, "w+" ); xfsfp = fopen( fsconfig, "r" ); while ( fgets( buffer, sizeof( buffer ), xfsfp ) ) { split[0] = '\0'; sscanf( buffer, "%s\n", split ); if ( strncasecmp( "catalogue", split, 9 ) == 0 ) { sprintf( buffer, "catalogue = %s,\n", fpList[0].path ); fputs( buffer, tmpfp ); for ( i = 1 ; i < num_fps ; i ++ ) { if ( i == ( num_fps - 1 ) ) { sprintf( buffer, " %s\n", fpList[i].path ); } else { sprintf( buffer, " %s,\n", fpList[i].path ); } fputs( buffer, tmpfp ); } continue ; } if ( split[0] != '/' ) fputs( buffer, tmpfp ); } fclose( xfsfp ); rewind( tmpfp ); xfsfp = fopen( fsconfig, "w" ); while ( fgets( buffer, sizeof( buffer ), tmpfp ) ) { fputs( buffer, xfsfp ); } fclose( xfsfp ); fclose( tmpfp ); remove( temp_file ); return 0; } static int Add_Font_Path( char *path, int nocheck ) { DIR *dir; char newpath[256]; int len = strlen( path ); int i; int found = 0; /* 去掉結尾的 '/'(如果有的話) */ strcpy( newpath, path ); if ( len != 1 && newpath[ len - 1 ] == '/' ) { newpath[ len - 1 ] = '\0'; } if ( nocheck == 0 ) { if ( path[0] != '/' ) { fprintf( stderr, "font directories must be absolute, not adding `%s'\n", path ); return 1; } /* 檢查 path 是否正確 */ dir = opendir( path ); if ( dir == NULL ) { fprintf( stderr, "`%s' not a directory\n", path ); return 1; } else { closedir( dir ); } /* 查對該目錄下,有無 fonts.dir 這個檔案 */ chdir( newpath ); if ( !File_Exist( "fonts.dir" ) ) { fprintf( stderr, "`%s' not a font path\n", newpath ); return 1; } } /* 比對是否已經有這個路徑了 */ for ( i = 0 ; i < num_fps ; i++ ) { if ( strcmp( newpath, fpList[i].path ) == 0 ) { found = 1; if ( nocheck == 0 ) return 1; break; } } if ( found == 0 ) { num_fps ++; fpList = realloc( fpList, sizeof( struct fp_rec ) * num_fps ); strcpy( fpList[num_fps-1].path, newpath ); } /* 更新 /etc/X11/fs/config */ /* 如果成功, 再更新 /etc/X11/XF86Config 的 FontPath */ if ( Update_XfsConfig( ) == 0 ) Init_Config(); return 0; } static int Remove_Font_Path( char *path ) { char newpath[256]; int len = strlen( path ); int i; int found = -1; if ( path[0] != '/' ) { fprintf( stderr, "font directories must be absolute, not adding `%s'\n", path ); return 1; } /* 去掉結尾的 '/'(如果有的話) */ strcpy( newpath, path ); if ( len != 1 && newpath[ len - 1 ] == '/' ) { newpath[ len - 1 ] = '\0'; } /* 比對是否已經有這個路徑了 */ for ( i = 0 ; i < num_fps ; i++ ) { if ( strcmp( newpath, fpList[i].path ) == 0 ) { found = i; break; } } /* 沒有找到相同路徑就不繼續了 */ if ( found == -1 ) return 1; /* 將資料往前挪 */ for ( i = found + 1 ; i < num_fps ; i ++ ) { strcpy( fpList[i - 1].path, fpList[i].path ); } num_fps --; fpList = realloc( fpList, sizeof( struct fp_rec ) * num_fps ); /* 更新 /etc/X11/fs/config */ /* 如果成功, 再更新 /etc/X11/XF86Config 的 FontPath */ if ( Update_XfsConfig( ) == 0 ) Init_Config(); return 0; }