Logo Search packages:      
Sourcecode: sagcad version File versions  Download package

etc.c

/* ====================================================================
 * ===  Copyright (C) 1998-2007 Yutaka Sagiya. All rights reserved. ===
 * ====================================================================
 * 
 *    Project              : SagCAD
 *    Description          : CAD/CAM
 *    Source               : etc.c
 * 
 *    ----------------------------------
 * 
 *    License              : GNU General Public License (GPL)
 *    Copyright            : (C) 1998-2007 by Yutaka Sagiya
 *    email                : kappa@a6s.highway.ne.jp
 *                         : yutaka@sagiya.com
 *    Begin                : 2001/01/16
 *    Last                 : 2007/11/08
 * ====================================================================
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <gtk/gtk.h>
#include <unistd.h>

#ifdef G_OS_WIN32

#else 
#include <pwd.h>
#include <langinfo.h>
#include <locale.h>
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <iconv.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "MemoryLeak.h"
#include "List_cad.h"
#include "List_Dimension.h"
#include "List_PolyLine.h"
#include "List_Block.h"
#include "List_Undo.h"
#include "List_Select.h"
#include "List_font.h"
#define _ETC_
#include "etc.h"





/* -------------------------------------------------------------------
 * 文字列 str の中の n番目にある split_word の位置を返す
 *    
 * 「"」に囲まれた,は数えない
 *    
 */
int split_word_point(char *str, char split_word, int n)
{
      int point = 1;
      int counter = 0;
      int i;

      i = 0;
      while (*str) {
            if (*str == '\"' && i == 1)   i = 0;
            else if (*str == '\"' && i == 0)    i = 1;

            if (*str == split_word && i == 0) {
                  counter++;
                  if (n == counter) {
                        return(point);
                  }
            }
            point++;
            str++;
      }
      return 0;
}



/* -------------------------------------------------------------------
 * 文字列 str の中に split_word が何個あるかを返す
 *    
 * 「"」に囲まれた,は数えない
 *    
 */
int split_word_num(char *str, char split_word)
{
      int counter = 0;
      int i;

      i = 0;
      while (*str) {
            if (*str == '\"' && i == 1)   i = 0;
            else if (*str == '\"' && i == 0)    i = 1;
            
            if (*str == split_word && i == 0) {
                  counter++;
            }
            str++;
      }
      return(counter);
}



/* -------------------------------------------------------------------
 * 文字列 str の左から num 文字を取り出して文字列 ret に入れて返す
 *    
 * 「"」に囲まれた,は数えない
 *    
 */
int strLeft(char *str, int num, char *ret)
{
      int counter = 1;
      if ((int) strlen(str) < num)  return(0);

      while (counter <= num) {
            *ret = *str;
            counter++;
            str++;
            ret++;
      }
      *ret = '\0';
      return(1);
}



/* -------------------------------------------------------------------
 * 文字列 str の左から mid番目から num文字を取り出して
 * 文字列 ret に入れて返す
 *    
 * 「"」に囲まれた,は数えない
 *    
 */
int strMid(char *str, int mid, int num, char *ret)
{
      int counter = 1;
      if ((int)strlen(str) < mid)   return(-1 * ((int)strlen(str)));
      
      str = str + (mid - 1);
      while (*str) {
            if (*str == '\0') return (-1);
            *ret = *str;
            counter++;
            str++;
            ret++;
            if (counter > num) {
                  *ret = '\0';
                  return(1);
            }
      }
      *ret = '\0';
      return(-1);
}



/* -------------------------------------------------------------------
 * 文字列 str の右から num 文字を取り出して文字列 ret に入れて返す
 *    
 * 「"」に囲まれた,は数えない
 *    
 */
int strRight(char *str, int num, char *ret)
{
      if ((int)strlen(str) < num)   return(0);
      str = str + (strlen(str) - num);
      while (*str) {
            *ret = *str;
            str++;
            ret++;
      }
      *ret = '\0';
      return(1);
}



/* -------------------------------------------------------------------
 * スプリット文字 (split_word) で区切られて、データが並んでいる文字列 (str) の
 * num 番目のデータ文字列を取り出して文字列 (ret) に入れて返す
 *    
 * 1,2,3,4,5,6,7
 *    1 2 3 4 5 6
 * 1234567890123
 *    
 *    
 * 「"」に囲まれた,は数えない
 *    
 */
int LineDataSplit(char *str, char split_word, int num, char *ret)
{
      char DumyStr[256], StrStr[256];
      int Len, Split, Split_P[2];

      /* 文字列 str の中に split_word が何個あるかを返す */
      Split = split_word_num(str, split_word);
      if (num      > Split + 1 )    return -1;

      if (num == 1) {
            /* 文字列 str の中の n番目にある split_word の位置を返す */
            Split_P[0] = split_word_point(str, split_word, 1);
            /* 文字列 str の左から num 文字を取り出して文字列 ret に入れて返す */
            strLeft(str, Split_P[0] - 1, DumyStr);
      }
      else if (num > 1 && num <= Split) {
            /* 文字列 str の中の n番目にある split_word の位置を返す */
            Split_P[0] = split_word_point(str, split_word, num - 1);
            Split_P[1] = split_word_point(str, split_word, num);
            strMid(str, Split_P[0] + 1, Split_P[1] - Split_P[0] - 1, DumyStr);
      }
      else if (num == Split + 1) {
            /* 文字列 str の中の n番目にある split_word の位置を返す */
            Split_P[0] = split_word_point(str, split_word, num - 1);
            /* 文字列 str の右から num 文字を取り出して文字列 ret に入れて返す */
            strRight(str, strlen(str) - Split_P[0], DumyStr);
      }

      Len = strlen(DumyStr);
      if (DumyStr[0] == '\"' && DumyStr[Len - 1] == '\"') {
            if(Len > 2) {
                  strMid(DumyStr, 2, Len - 2, StrStr);
                  strcpy(ret, StrStr);
                  return Split;
            }
            else {
                  strcpy(ret, "");
                  return Split;
            }
      }
      else {
            strcpy(ret, DumyStr);
            return Split;
      }
}



/* -------------------------------------------------------------------
 * 置き換え関数
 * 
 */
void replace(char *text, char *key, char *rep)
{
      char *p, work[2*256], a[2*256];

      strcpy(work, text);
      p = search(work, key);                    /*    作業領域にコピー*/
      while (p != NULL) {
            if (strlen(work) > (256*2)-1) {
                  work[2*256-2] = '\n';
                  work[2*256-1] = '\0';
                  break;
            }
            *p = '\0';
            strcpy(a, p + strlen(key));   /* サーチ文字より後の内容を作業バッファにコピー */
            strcat(work, rep);                        /* 置きかえる文字列をworkに連結する */
            strcat(work, a);                    /* 次の位置を探す */
            p = search(p+strlen(rep), key);
      }
      strcpy(text, work);
}



/* -------------------------------------------------------------------
 * サーチ関数
 * 
 */
char *search(char *text, char *key)
{
      int m, n;
      char *p;

      m = strlen(text);
      n = strlen(key);
      for (p = text ; p <= text + m - n ; p++) {
            if (strncmp(p, key, n) == 0)  /* 2つの文字列の文字を比較します */
                  return (p);
      }
      return (NULL);
}



/* -------------------------------------------------------------------
 * ltrim
 * 
 */
int ltrim(char *str, char *ret)
{
      while (*str) {
            if (*str == ' ' || *str == '  ' || *str == '\n' || *str == '\r') {
                  str++;
            }
            else {
                  *ret = *str;
                  str++;
                  ret++;
            }
      }
      *ret = '\0';
      return 0;
}



/* -------------------------------------------------------------------
 * フルパス名からファイル名を取得する
 *    
 * char *lpszPath   ファイル名を含むパス名へのポインタ
 * char * ファイル名へのポインタ
 * ファイル名を含まないときは""へのポインタ
 * [\],[/],[:]が見つからなかった場合、引数をファイル名とみなしてそのまま返す
 *    
 * パス名の先頭から文字列を検索して,「:,\,/」のいずれかが最後に現れる地点を探す。
 * 文字を比較するときは,比較対象の文字が2バイト文字か1バイト文字かを調べる必要があります。
 *    
 * 「"」に囲まれた,は数えない
 */
char *getFileName(char *lpszPath)
{
      char *lpszPtr = lpszPath;


      while (*lpszPtr != '\0') {
            /* [\],[/],[:]を見つけたら現在地+1のポインタを保存 */
            if((*lpszPtr == '\\') || (*lpszPtr == '/') || (*lpszPtr == ':')) {
                  lpszPath = lpszPtr + 1;
            }
            /* 次の文字へ */
            lpszPtr++;
      }
      return lpszPath;
}



/* -------------------------------------------------------------------
 * ファイル名から拡張子を取り除く
 *    
 * char *lpszFileName     ファイル名へのポインタ
 * (実行後、ファイル名から拡張子が切り離される)
 */
void cutExtName(char *lpszFileName)
{
      char *pEnd = lpszFileName;
      char *pStart = lpszFileName;


      /* ディレクトリ部分の最後まで飛ぶ */
      while (*pEnd != '\0') {
            /* [\],[/],[:]を見つけたら現在地+1のポインタを保存 */
            if((*pEnd == '\\') || (*pEnd == '/') || (*pEnd == ':')) {
                  pStart = pEnd + 1;
            }
            /* 次の文字へ */
            pEnd++;
      }


      pEnd = lpszFileName;
      while (*pStart != '\0') {
            /* [.]を見つけたら現在地+1のポインタを保存 */
            if(*pStart == '.') {
                  pEnd=pStart;
            }
            /* 次の文字へ */
            pStart++;
      }


      /* ファイル名に拡張子を含まなかった場合何もしない */
      if (pEnd == lpszFileName) {
            return;
      }
      /* ファイル名から拡張子を切り離す */
      *pEnd = '\0';
}



/* -------------------------------------------------------------------
 * パス名からファイル名を取り除く
 *    
 * char *lpszPath   ファイル名を含むパス名へのポインタ
 * (実行後、パス名からファイル名が切り離される)
 *
 * パス名の先頭から文字列を検索して,「:,\,/」のいずれかが最後に現れた地点のポインタに
 * '\0' を代入することでファイル名を取り除きます。
 */
void cutFileName(char *lpszPath)
{
      char *lpszEnd = lpszPath;


      while(*lpszPath != '\0') {
            /* [\],[/],[:]を見つけたら現在地+1のポインタを保存 */
            if((*lpszPath == '\\') || (*lpszPath == '/') || (*lpszPath == ':')) {
                  lpszEnd = lpszPath + 1;
            }
            /* 次の文字へ */
            lpszPath++;
      }

      /* パス名にファイルを含まなかった場合何もしない */
      if(lpszEnd == lpszPath) {
            return;
      }
      /* パス名からファイル名を切り離す */
      *lpszEnd='\0';
      return;
}



/* -------------------------------------------------------------------
 * 実行ファイルのフルパス取得
 *    
 */
#ifdef AFTER
int GetAppPath(char *App_Path)
{
      char  szModulePath[MAXPATHLEN];


      /* 実行ファイルのフルパス取得 */
      GetModuleFileName(NULL, szModulePath, MAXPATHLEN);

      //パス名からファイル名を取り除く
      //引数:  char *lpszPath   ファイル名を含むパス名へのポインタ
      //                  (実行後、パス名からファイル名が切り離される)
      //戻り値:なし
      cutFileName(szModulePath);
      strcpy(App_Path, szModulePath);
      return 1;
}
#endif



/* -------------------------------------------------------------------
 * ファイルに1行書き込み
 * 
 * 
 * int code
 *     CHARSET_UTF8    5
 *     CHARSET_LOCALE  0
 */
int write_locale_from_utf8(char *str, FILE *stream, int code)
{
      char *locale_str;
      GError *err;
      
      if (code != CHARSET_UTF8) {
            /* Convert from UTF8 to system string */
            if (!(locale_str = g_locale_from_utf8 ( str, -1, NULL, NULL, &err))) {
                  g_printerr ( "Failed UTF-8 to locale conversion: %s\n", err->message ) ;
                  g_clear_error ( &err ) ;
                  return -1;
            }
            fputs(locale_str, stream );
            g_free(locale_str);
      }
      else {
            fputs(str, stream );
      }
      return 0;
}



/* -------------------------------------------------------------------
 * ファイルから1行読み込み
 * 
 * 
 * int code
 *     CHARSET_UTF8    5
 *     CHARSET_LOCALE  0
 */
int read_utf8_from_locale(FILE *stream, char *str, int code)
{
      int ret;
      char locale_str[1024];
      char * utf8_str;
      GError *err;
      
      ret = LineRead(stream, locale_str);
      if (ret == -1) {
            return -1;
      }
      
      
      if (code != CHARSET_UTF8) {
            /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
               sgy ファイルのロケールが合っていないと、エラーになる。
               - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
            if (!(utf8_str = g_locale_to_utf8(locale_str, -1, NULL, NULL, &err))) {
                  g_printerr ( "Failed locale to UTF-8 conversion: %s\n", err->message ) ;
                  g_clear_error ( &err ) ;
                  return -1;
            }
            strcpy(str, utf8_str);
            g_free(utf8_str);
      }
      else {
            strcpy(str, locale_str);
      }
      return ret;
}



/* -------------------------------------------------------------------
 * ストリームから1行読みこんで ret に入れて返す。
 *    
 *    
 *    1 : 1行を正常に返す。
 *    0 : ファイル終端にきた。
 */
int LineRead(FILE *stream, char *ret)
{
      int i, j;
      char c, str[1024];

      i = 0;
      j = 0;
      while((c = getc( stream )) != EOF) {
            /* CR 以外 */
            if (c == 0x0d) {
                  // 飛ばす
            }
            /* 1行読み込み完了 */
            else if(c == 0x0a) {
                  str[i] = '\0';
                  strcpy(ret, str);
                  return 1;
            }
            else {
                  str[i] = (char)c;
                  i++;
            }
            j++;
            /* 1024 bite 以上 */
            if (j == 1023) return -1;
      }
      /* EOF 終了 */
      str[i] = '\0';
      strcpy(ret, str);
      return 0;
}



/* -------------------------------------------------------------------
 * RGB(0xrrggbb) のカラーを (red, green, blue) のデータに分解
 * 
 */
int color_split(struct ColorDat *a)
{
      int red, green, blue;

      /* blue */
      blue = a->rgb & 0x0000ff;
      a->blue = blue;
      /* green */
      green = a->rgb & 0x00ff00;
      green = green >> 8;
      a->green = green;
      /* red */
      red = a->rgb & 0xff0000;
      red = red >> 16;
      a->red = red;
      return 1;
}



/* ---------------------------------------------------------------------
 * (red, green, blue) のデータを RGB(0xrrggbb) のカラーに合成
 * 
 */
long color_rgb(struct ColorDat *a)
{
      long red, green, blue;

      blue = a->blue;

      green = a->green;
      green = green << 8;

      red = a->red;
      red = red << 16;

      a->rgb = (red | green | blue);
      return (red | green | blue);
}



/* ---------------------------------------------------------------------
 * 0xrrggbb の形式のデータの "rr" と "bb" を交換する
 * Windows(0xbbggrr) のカラー  <-->  0xrrggbb  の変換
 * 
 */
long color_rb_change(long rgbcol)
{
      long color;
      long red, green, blue;

      /* red */
      red = rgbcol & 0x0000ff;
      red = red << 16;

      /* green */
      green = rgbcol & 0x00ff00;

      /* blue */
      blue = rgbcol & 0xff0000;
      blue = blue >> 16;

      color = red + green + blue;
      return color;
}



/* -------------------------------------------------------------------
 * 文字列(16進対応 0x付加)を数値に変換
 * 
 */
int atoi16(char *str)
{
      char *hexstr;

      hexstr = strstr(str, "0x");
      if(hexstr != NULL) {
            hexstr = hexstr + 2;
            return hextoint(hexstr);
      }
      else return atoi(str);
}


/* -------------------------------------------------------------------
 * 16進文字列を数値に変換
 * 
 * 用例 hextoint("B6119");
 */
int hextoint(char *str)
{
      int val;
      int sign;
      
      while (*str == ' ' || *str == '\t') str++;
      sign = 1;
      if (*str == '+') str++;
      else if (*str == '-') {
            sign = -1;
            str++;
      }
      val = 0;
      while ( (*str >= '0' && *str <= '9') ||
                  (*str >= 'A' && *str <= 'F') ||
                  (*str >= 'a' && *str <= 'f') ) {
            val <<= 4;
            if          (*str >= '0' && *str <= '9') val += *str - '0';
            else if (*str >= 'A' && *str <= 'F') val += *str - 'A' + 10;
            else                                             val += *str - 'a' + 10;
            str++;
      }

      return sign == 1 ? val : -val;
}



/* -------------------------------------------------------------------
 * 16進文字列を作成
 * 
 */
int HexString(long data, char *hex)
{
      int red, green, blue;
      char str[256];

      /* red */
      red = data & 0xff0000;
      red = red >> 16;
      /* green */
      green = data & 0x00ff00;
      green = green >> 8;
      /* blue */
      blue = data & 0x0000ff;

      sprintf(str, "%x", red);
      if (strlen(str) == 1) {
            sprintf(hex,"0x0%x", red);
      }
      else
            sprintf(hex,"0x%x", red);

      sprintf(str, "%x", green);
      if (strlen(str) == 1) {
            sprintf(str,"0%x", green);
      }
      else 
            sprintf(str,"%x", green);
      strcat(hex, str);

      sprintf(str, "%x", blue);
      if (strlen(str) == 1) {
            sprintf(str,"0%x", blue);
      }
      else 
            sprintf(str,"%x", blue);
      strcat(hex, str);
      return 1;
}





/* -------------------------------------------------------------------
 * log ファイル書きこみ
 *    
 */
int LogFileOpen(char *str)
{
      /* ファイルをオープン */ 
      if((stream_log = fopen( str, "w")) == NULL) {
//          MsgBox("LogFileOpen", "設定ファイル %s は開けませんでした。");
            return 0;
      }
      LogFileWrite("SagCAD run\n");
      return 1;
}


int LogFileWrite(char *str)
{

      if (strstr(str, "\n") == NULL) strcat(str, "\n");
      fputs(str, stream_log);
      return 1;
}


int LogFileClose(void)
{
      LogFileWrite("SagCAD stop\n");
      /* ファイルをクローズ */ 
      fclose(stream_log);
      return 1;
}



/* -------------------------------------------------------------------
 * log ファイル書きこみ
 *    
 */
int OneShotLog(char *str)
{
      FILE *stream;
      char path[256], dummy[256];


      GetConfigPath(path);

      sprintf(dummy, "%s//OneShotLog", path);

      /* ファイルをオープン */ 
      if((stream = fopen(dummy, "a")) == NULL) {
//          MsgBox("LogFileOpen", "設定ファイル %s は開けませんでした。");
            return 0;
      }

//    if (strstr(str, "\n") == NULL) strcat(str, "\n");
      fputs(str, stream);

      /* ファイルをクローズ */ 
      fclose(stream);
      return 1;
}


int DeleteOneShotLog(void)
{
      char path[256], str[256];


      GetConfigPath(path);

      sprintf(str, "%s//OneShotLog", path);
      unlink(str);

      return 0;
}



/* -------------------------------------------------------------------
 * 設定ファイルのパス取得
 *    
 * Windows の場合、実行ファイルと同じフォルダに設定ファイルを置く
 * LINUX の場合、/home/[user]/.sagcad/sagcadrc
 */
int GetConfigPath(char *path)
{
#ifdef G_OS_WIN32
      char str[256];
      FILE *fp;
      
      sprintf(path, "%s/.sagcad", g_get_home_dir());
      
      /* check & make */
      sprintf(str, "%s/sagcadrc", path);
      if((fp=fopen(str, "r")) != NULL) {
            /* find file */
            fclose(fp);
            //g_print("GetConfigPath() : .sagcad OK !\n");
      }
      else {
            if (mkdir(path) < 0) {
                  g_print("GetConfigPath() : %s nothing and not make !", path);
                  return -1;
            }
            else {
                  g_print("GetConfigPath() : %s nothing and make !", path);
            }
            //mkdir(g_get_home_dir());
            //g_print("GetConfigPath() : .sagcad No and make !");
      }
      
      return 0;
#else
      uid_t uid;
      struct passwd *pwd;

      uid = getuid();
      pwd = getpwuid(uid);
      sprintf(path, "%s/.sagcad", pwd->pw_dir);
      return 0;
#endif
}





void home_of_user(char *home)
{
#ifdef G_OS_WIN32
      sprintf(home, "%s", g_get_home_dir());
#else
      uid_t uid;
      struct passwd *pwd;

      uid = getuid();
      pwd = getpwuid(uid);
      strcpy (home, pwd->pw_dir);
#endif
}





void name_of_user(char *user)
{
#ifdef G_OS_WIN32
      sprintf(user, "%s", g_get_user_name());
#else
      uid_t uid;
      struct passwd *pwd;

      uid = getuid();
      pwd = getpwuid(uid);
      strcpy (user, pwd->pw_name);
#endif
}





/* -------------------------------------------------------------------
 * 文字列のコード変換
 * 
 * from_str : 変換元文字列
 * from_code : 変換元のコード
 * to_code : 変換後のコード
 * 
 * 変換後の文字列のポインタを返す。呼び出し側で free する。
 */
char *p_sag_iconv(char *from_str, char *from_code, char *to_code)
{
//#ifdef P_SAG_ICONV
      iconv_t cd;                         /* 変換用ディスクリプタ */
      char *inbuf;                        /* 入力用バッファ */
      char *outbuf;                       /* 出力用バッファ */
      char *outptr;                       /* テンポラリポインタ(出力用) */
      const char *inptr;                  /* テンポラリポインタ(入力用) */
      size_t inbyteleft;                  /* 入力バッファサイズ */
      size_t outbyteleft;                 /* 出力バッファサイズ */
      size_t ret;                         /* 戻り値 */
#ifdef P_SAG_ICONV
      int i;                                    /* ループカウンタ用変数 */
      int n;                                    /* バッファ長 */
#endif

      /* 入力された文字列をコピーして、長さを求める */
      inbuf = strdup(from_str);
      inbyteleft = strlen(inbuf);

      /* 出力用のバッファを確保する */
      /* malloc は、void ポインタを返すので、所望の型にキャストして使いましょう */
      outbuf = (char *)xmalloc(inbyteleft * 4 + 1);
      outbyteleft = inbyteleft * 4;
      inbyteleft = strlen(inbuf) + 1;
      if (!outbuf) {
            printf("error in malloc\n");
            return NULL;
      }

      /* 入出力用バッファのコピー(ポインタ) */
      outptr = outbuf;
      inptr = inbuf;

      /* iconv open */
      /* 文字コード変換用のディスクリプタをオープンする */
      cd = iconv_open(to_code, from_code);
      if (cd == (iconv_t)(-1)) {
            printf("error in iconv_open\n");

            switch(errno) {
                  case EMFILE:
                        printf("p_sag_iconv() : 呼び出しもとのプロセスで既にOPEN_MAX個の記述子がオープンされている\n");
                        break;
                  case ENFILE:
                        printf("p_sag_iconv() : オープンされているファイルの和が多すぎる\n");
                        break;
                  case ENOMEM:
                        printf("p_sag_iconv() : 記憶領域が不足している\n");
                        break;
                  case EINVAL:
                        printf("p_sag_iconv() : fromcodeおよびtocode引数で指定したコード変換をサポートしていない\n");
                        break;
            }

            free(inbuf);
            free(outbuf);
            return NULL;
      }

      /* iconv */
      /* 文字コード変換を実行 */
      /* iconv の引数をプロトタイプ宣言通りに型キャストすると、警告は出なくなります。*/
      ret = iconv(cd, (char **)&inptr, &inbyteleft, (char **)&outptr, &outbyteleft);
//    printf("ret1 = %d\n", ret);
      if ((size_t)(-1) != ret) {
            switch( errno ) {
                  case EBADF:
                        printf("p_sag_iconv() : コードセット・コンバーターの記述子ではない。\n");
                        break;
                  case E2BIG:
                        printf("p_sag_iconv() : 変換後の文字列取得領域不足\n");
                        break;
#ifdef ELISEQ
                  case ELISEQ:
                        printf("p_sag_iconv() : 入力バッファに変換元のコードセットに属しないデータが存在\n");
                        break;
#endif
                  case EINVAL:
                        printf("p_sag_iconv() : 入力バッファの最後に不完全な文字が存在した。\n");
                        break;
            }

            ret = iconv(cd, NULL, NULL, &outptr, &outbyteleft);
//          printf("ret2 = %d\n", ret);
            //free(outbuf);
            //return NULL;
      }

#ifdef P_SAG_ICONV
      /* 結果を標準出力に表示する */
      n = strlen(outbuf);
      printf("in sag_iconv() \n");
      printf("----------------------------------------------------------\n");
      printf("from [%s] %s \n", from_code, from_str);
      printf("to   [%s] %s \n", to_code, outbuf);
      printf("----------------------------------------------------------\n");
      for (i = 0 ; i < n ; i++) {
            printf("%x ", outbuf[i] & 0xff);
      }
      printf("\n");
      printf("----------------------------------------------------------\n");
      printf("\n");
#endif

      /* 使用したディスクリプタを閉じる */
      iconv_close(cd);

      /* 使用した領域を開放する */
      free(inbuf);

      return outbuf;
}





/* -------------------------------------------------------------------
 * 文字列のコード変換
 * 
 * from_str  : 変換元文字列
 * to_str    : 変換後の文字列が入る
 * from_code : 変換元のコード
 * to_code   : 変換後のコード
 */
int sag_iconv(char *from_str, char *to_str, char *from_code, char *to_code)
{
//#define SAG_ICONV
      iconv_t cd;                         /* 変換用ディスクリプタ */
      char *inbuf;                        /* 入力用バッファ */
      char *outbuf;                       /* 出力用バッファ */
      char *outptr;                       /* テンポラリポインタ(出力用) */
      const char *inptr;                  /* テンポラリポインタ(入力用) */
      size_t inbyteleft;                  /* 入力バッファサイズ */
      size_t outbyteleft;                 /* 出力バッファサイズ */
      size_t ret;                         /* 戻り値 */
#ifdef SAG_ICONV
      int i;                                    /* ループカウンタ用変数 */
      int n;                                    /* バッファ長 */
#endif

      /* 入力された文字列をコピーして、長さを求める */
      inbuf = strdup(from_str);
      inbyteleft = strlen(inbuf);

      /* 出力用のバッファを確保する */
      /* malloc は、void ポインタを返すので、所望の型にキャストして使いましょう */
      outbuf = (char *)xmalloc(inbyteleft * 4 + 1);
      outbyteleft = inbyteleft * 4;
      inbyteleft = strlen(inbuf) + 1;
      if (!outbuf) {
            printf("error in malloc\n");
            return 0;
      }

      /* 入出力用バッファのコピー(ポインタ) */
      outptr = outbuf;
      inptr = inbuf;

      /* iconv open */
      /* 文字コード変換用のディスクリプタをオープンする */
      cd = iconv_open(to_code, from_code);
      if (cd == (iconv_t)(-1)) {
            printf("error in iconv_open\n");
            switch(errno) {
                  case EMFILE:
                        printf("sag_iconv() : 呼び出しもとのプロセスで既にOPEN_MAX個の記述子がオープンされている\n");
                        break;
                  case ENFILE:
                        printf("sag_iconv() : オープンされているファイルの和が多すぎる\n");
                        break;
                  case ENOMEM:
                        printf("sag_iconv() : 記憶領域が不足している\n");
                        break;
                  case EINVAL:
                        printf("sag_iconv() : fromcodeおよびtocode引数で指定したコード変換をサポートしていない\n");
                        break;
            }
            free(inbuf);
            free(outbuf);
            return 0;
      }

      /* iconv */
      /* 文字コード変換を実行 */
      /* iconv の引数をプロトタイプ宣言通りに型キャストすると、警告は出なくなります。*/
      ret = iconv(cd, (char **)&inptr, &inbyteleft, (char **)&outptr, &outbyteleft);
//    printf("ret = %d\n", ret);
      if ((size_t)(-1) != ret) {
            switch( errno ) {
                  case EBADF:
                        printf("sag_iconv() : コードセット・コンバーターの記述子ではない。\n");
                        break;
                  case E2BIG:
                        printf("sag_iconv() : 変化後の文字列取得領域不足\n");
                        break;
#ifdef ELISEQ
                  case ELISEQ:
                        printf("sag_iconv() : 入力バッファに変換元のコードセットに属しないデータが存在\n");
                        break;
#endif
                  case EINVAL:
                        printf("sag_iconv() : 入力バッファの最後に不完全な文字が存在した。\n");
                        break;
            }

            ret = iconv(cd, NULL, NULL, &outptr, &outbyteleft);
//          printf("ret = %d\n", ret);
      }

#ifdef SAG_ICONV
      /* 結果を標準出力に表示する */
      n = strlen(outbuf);
      printf("in sag_iconv() \n");
      printf("----------------------------------------------------------\n");
      printf("from [%s] %s \n", from_code, from_str);
      printf("to   [%s] %s \n", to_code, outbuf);
      printf("------------------------------------------------\n");
      for (i = 0 ; i < n ; i++) {
            printf("%x ", outbuf[i] & 0xff);
      }
      printf("\n");
      printf("----------------------------------------------------------\n");
      printf("\n");
#endif

      /* 結果を戻す */
      strcpy(to_str, outbuf);

      /* 使用したディスクリプタを閉じる */
      iconv_close(cd);

      /* 使用した領域を開放する */
      free(inbuf);
      free(outbuf);

      return 1;
}





/*============================================================================
 * NAME:    conv_iconv
 * USAGE:   char *conv_iconv(const char *from_str, const char *from_code, const char *to_code)
 * PARAMS:  from_str          変換前の文字列を指すポインタ(I)
 *                from_code         変換前のコードを格納した文字配列(I)
 *                to_code                 変換後のコードを格納した文字配列(I)
 * RETURN VALUE:
 *                正常終了            char *      変換後の文字列を指すポインタ(O)
 *                異常終了            NULL  変換できなかった。
 * DESCRIPTION:
 *                文字列のコード変換
 *                from_str の文字列を from_code から to_code に文字コード変換し、
 *                変換後の文字列のポインタを返す。
 *                変換後の文字列のメモリは、呼び出し側で開放する (free) する。
 *=============================================================================
 */
char *conv_iconv(const char *from_str, const char *from_code, const char *to_code)
{
//#define CONV_ICONV
      iconv_t cd;                   /* 変換用ディスクリプタ */
      const char *inbuf_p;    /* テンポラリポインタ(入力用) */
      char *outbuf;                 /* 出力用バッファ */
      char *outbuf_p;               /* テンポラリポインタ(出力用) */
      int in_size;                  /* 入力バッファサイズ */
      int in_left;                  /* 入力バッファサイズ */
      int out_size;                 /* 出力バッファサイズ */
      int out_left;                 /* 出力バッファサイズ */
      int n_conv;
      int len;
#ifdef CONV_ICONV
      int i;                              /* ループカウンタ用変数 */
      int n;                              /* バッファ長 */
#endif


      /* 文字コード変換用のディスクリプタをオープンする */
      cd = iconv_open(to_code, from_code);
      if (cd == (iconv_t)-1) {
            return NULL;
      }


      /* 変換前の文字列のコピーと、サイズを求める */
      inbuf_p = from_str;
      in_size = strlen(from_str);
      in_left = in_size;
      out_size = (in_size + 1) * 2;
      /* 出力用のバッファを確保する */
      outbuf = (char *)g_malloc(out_size);
      if ( !outbuf ) {
            /* malloc のチェック */
            g_print ("conv_iconv() : error in malloc\n");
            return NULL;
      }
      /* 変換後の文字列のコピーと、サイズを求める */
      outbuf_p = outbuf;
      out_left = out_size;


      while ((n_conv = iconv(cd, (char **)&inbuf_p, &in_left, (char **)&outbuf_p, &out_left)) < 0) {
            if (EILSEQ == errno) {
                  inbuf_p++;
                  in_left--;
                  if (out_left == 0) {
                        len = outbuf_p - outbuf;
                        out_size *= 2;
                        outbuf = g_realloc(outbuf, out_size);
                        outbuf_p = outbuf + len;
                        out_left = out_size - len;
                  }
                  *outbuf_p++ = '_';
                  out_left--;
            }
            else if (EINVAL == errno) {
                  break;
            }
            else if (E2BIG == errno) {
                  len = outbuf_p - outbuf;
                  out_size *= 2;
                  outbuf = g_realloc(outbuf, out_size);
                  outbuf_p = outbuf + len;
                  out_left = out_size - len;
            }
            else {
                  g_print ("conv_iconv(): %s\n", g_strerror(errno));
                  break;
            }
      }

      while ((n_conv = iconv(cd, NULL, NULL, &outbuf_p, &out_left)) < 0) {
            if (E2BIG == errno) {
                  len = outbuf_p - outbuf;
                  out_size *= 2;
                  outbuf = g_realloc(outbuf, out_size);
                  outbuf_p = outbuf + len;
                  out_left = out_size - len;
            }
            else {
                  g_print ("conv_iconv(): %s\n", g_strerror(errno));
                  break;
            }
      }

      len = outbuf_p - outbuf;
      outbuf = g_realloc(outbuf, len + 1);
      outbuf[len] = '\0';

      /* 使用したディスクリプタを閉じる */
      iconv_close(cd);

#ifdef CONV_ICONV
      /* 結果を標準出力に表示する */
      n = strlen(outbuf);
      printf("----------------------------------------------------------\n");
      printf("from [%s] %s \n", from_code, from_str);
      printf("to   [%s] %s \n", to_code, outbuf);
      printf("------------------------------------------------\n");
      for (i = 0 ; i < n ; i++) {
            printf("%x ", outbuf[i] & 0xff);
      }
      printf("\n");
      printf("----------------------------------------------------------\n");
      printf("\n");
#endif

      return outbuf;
}





/* -------------------------------------------------------------------
 * UTF-8 の1文字の1バイト目から1文字のバイト数を返す
 */
int utf8_bite_num(char c)
{
      /* 4 bite */
      if ((c & 0xf0) == 0xf0) {
            return 4;
      }
      /* 3 bite */
      else if ((c & 0xe0) == 0xe0) {
            return 3;
      }
      /* 2 bite */
      else if ((c & 0xc0) == 0xc0) {
            return 2;
      }
      /* 1 bite */
      else if ((c & 0xff) < 0x80) {
            return 1;
      }

      return 0;
}





/* ====================================================================
 * ===  Copyright (C) 1998-2007 Yutaka Sagiya. All rights reserved. ===
 * ====================================================================
 *    Project              : SagCAD
 *    Source               : etc.c
 * ====================================================================
 */

Generated by  Doxygen 1.6.0   Back to index