/*
 * $Id: m_msg_main.c,v 1.1 2003/06/06 00:15:12 tong Exp $
 *
 *	メッセージ表示のライブラリーのインクルードソースファイル
 *
 * $Log: m_msg_main.c,v $
 * Revision 1.1  2003/06/06 00:15:12  tong
 * source files for localization from Nintendo.
 *
 * Revision 1.121  2001-02-06 18:55:20+09  sakakibara
 * Other Player Name Color 変更
 *
 * Revision 1.120  2001-02-05 13:07:44+09  sakakibara
 * 自由文字列カラーを増やした。
 *
 * Revision 1.119  2001-02-03 16:20:43+09  sakakibara
 * 自由文字列カラーを増やした。
 *
 * Revision 1.118  2001-01-28 00:59:31+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.117  2001-01-27 22:55:53+09  sakakibara
 * データの実体が無いときの処理。
 *
 * Revision 1.116  2001-01-09 13:10:14+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.115  2001-01-05 13:09:49+09  sakakibara
 * pf5 も色指定。
 *
 * Revision 1.114  2000-12-14 15:05:53+09  sakakibara
 * QItem Color 変更
 *
 * Revision 1.113  2000-12-12 23:58:43+09  sakakibara
 * 自由文字列色指定
 *
 * Revision 1.112  2000-12-12 13:31:54+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.111  2000-12-11 22:41:52+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.110  2000-12-01 21:28:23+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.109  2000-11-30 21:14:56+09  sakakibara
 * アイドリング
 *
 * Revision 1.108  2000-10-19 11:41:29+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.107  2000-10-17 14:57:48+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.106  2000-10-16 16:44:21+09  sakakibara
 * プレイヤ名 色変え
 *
 * Revision 1.105  2000-09-28 21:54:15+09  sakakibara
 * コントロール命令追加に伴う修正
 *
 * Revision 1.104  2000-09-13 20:14:45+09  otsuki
 * *** empty log message ***
 *
 * Revision 1.103  2000/08/03 08:05:41  sakakibara
 * わ
 *
 * Revision 1.102  2000-07-19 13:50:14+09  komatu
 * *** empty log message ***
 *
 * Revision 1.101  2000-07-10 16:01:06+09  sakakibara
 * レジスタ外し。
 *
 * Revision 1.100  2000-07-06 17:43:46+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.99  2000-07-05 17:49:43+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.98  2000-07-04 18:21:48+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.97  2000-07-04 18:12:37+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.96  2000-07-03 17:06:47+09  sakakibara
 * char * から unchar * へ
 *
 * Revision 1.95  2000-06-29 21:02:23+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.94  2000-06-26 14:03:09+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.93  2000-06-19 14:47:44+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.92  2000-06-16 20:08:12+09  sakakibara
 * コントロール命令追加に伴う修正
 *
 * Revision 1.91  2000-06-16 14:33:10+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.90  2000-06-15 18:09:48+09  sakakibara
 * *** empty log message ***
 *
 * Revision 1.89  2000-06-09 18:23:28+09  komatu
 * *** empty log message ***
 *
 * Revision 1.88  2000-06-09 18:16:53+09  komatu
 * *** empty log message ***
 *
 * Revision 1.87  2000-06-06 15:25:36+09  sakakibara
 * ★ 変更色々
 *
 * Revision 1.86  2000-05-25 16:18:37+09  sakakibara
 * コントロール命令追加に伴う修正
 *
 * Revision 1.85  2000-05-17 19:55:16+09  sakakibara
 * コントロール命令追加に伴う修正
 *
 * Revision 1.84  2000-05-17 18:47:21+09  sakakibara
 * 発声ＯＮ／ＯＦＦ 処理作成
 *
 * Revision 1.83  2000-05-10 16:05:16+09  sakakibara
 * コントロール命令追加に伴う修正
 *
 * Revision 1.82  2000-05-02 14:20:39+09  komatu
 * *** empty log message ***
 *
 * Revision 1.81  2000-04-25 23:18:58+09  komatu
 * *** empty log message ***
 *
 * Revision 1.80  2000-04-25 21:23:03+09  komatu
 * *** empty log message ***
 *
 * Revision 1.79  2000-04-25 17:44:56+09  sakakibara
 * コメント補足
 *
 */
/*************メッセージウインドウのメインの処理******************/


/*
 ************************************************************************
 *	index番目のコードが何バイトの命令かを調べる
 ************************************************************************
 */

/* ウインドウ構造体用 */
static int mMsg_Set_SizeCode(M_MSG_WIN *win_p, int index)
{
    unchar *data_p = win_p->msg_p->code.data;
    
    return mFont_CodeSize_idx_get(data_p, index);
}

/*-----------------------------------------------------------------*
 *
 *	指定した文字が何文字続くかを数える。
 *	(制御コードは飛ばす)
 *
 *-----------------------------------------------------------------*/
static int mMsg_Count_SameCode(unchar *data_p,		/* データ Top pointer */
			       int start_index,		/* 開始位置 */
			       int total_code,		/* データ総数 */
			       unchar check_code)	/* チェック文字 */
{
    int same_counter = 0;
    int i = start_index;
    unchar *tmp_code_p;
    unchar tmp_code;
    
    while (i < total_code) {
	tmp_code_p = data_p + i;
	tmp_code = *tmp_code_p;
	
	if (tmp_code == MOJI_CONT) {
	    i += mFont_CodeSize_get(tmp_code_p);
	} else if (tmp_code == check_code) {
	    same_counter++;
	    i++;
	} else {
	    break;
	}
    }
    
    return same_counter;
}

/*
 ************************************************************************
 *	index番目のコードが終了命令かを調べる(２コードしらべる)
 ************************************************************************
 */
/*メッセージデータ用 */
static int mMsg_Check_LastCode_forData(unchar *data_p, int index)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if(code == CONT_LAST) {
	    return(TRUE);
	}
    }
    return(FALSE);
}

/* ウインドウ構造体用 */
static int mMsg_Check_LastCode(M_MSG_WIN *win_p, int index)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Check_LastCode_forData(data_p, index));
}

/*
 ************************************************************************
 *	index番目のコードが継続命令かを調べる(２コードしらべる)
 ************************************************************************
 */
/*メッセージデータ用 */
static int mMsg_Check_ContinueCode_forData(unchar *data_p, int index)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if(code == CONT_CONTINUE) {
	    return(TRUE);
	}
    }
    return(FALSE);
}

/* ウインドウ構造体用 */
static int mMsg_Check_ContinueCode(M_MSG_WIN *win_p, int index)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Check_ContinueCode_forData(data_p, index));
}

/*
 ************************************************************************
 *	次が継続コードであるか調べる
 ************************************************************************
 */
static int mMsg_Check_NextIndex_ContinueCode(M_MSG_WIN *win_p)
{
    int code_index = win_p->now_end_font_code_cursol_index;

    if(mMsg_Check_ContinueCode(win_p, code_index)) {
	return(TRUE);
    }
    return(FALSE);
}

/*
 ************************************************************************
 *	次が終了コードであるか調べる
 ************************************************************************
 */
static int mMsg_Check_NextIndex_LastCode(M_MSG_WIN *win_p)
{
    int code_index = win_p->now_end_font_code_cursol_index;

    if(mMsg_Check_LastCode(win_p, code_index)) {
	return(TRUE);
    }
    return(FALSE);
}

/*
 ************************************************************************
 *	次が"選択ウインドウセット"コードであるか調べる
 ************************************************************************
 */
static int mMsg_Check_NextIndex_SetSelectWindowCode(M_MSG_WIN *win_p)
{
    unchar *data_p = win_p->msg_p->code.data;
    int code_index = win_p->now_end_font_code_cursol_index;
    unchar code = data_p[code_index];
    
    if(code == MOJI_CONT) {
	code = data_p[code_index+1];
	if(code == CONT_SET_SELECT_WINDOW) {
	    return(TRUE);
	}
    }
    return(FALSE);
}

/*
 ************************************************************************
 *	index番目のコードがボタン待ち命令かを調べる(２コードしらべる)
 ************************************************************************
 */
#if 0
/*メッセージデータ用 */
static int mMsg_Check_ButtonCode_forData(unchar *data_p, int index)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if((code == CONT_BUTTON) || (code == CONT_BUTTON2)) {
	    return(TRUE);
	}
    }
    return(FALSE);
}

/* ウインドウ構造体用 */
static int mMsg_Check_ButtonCode(M_MSG_WIN *win_p, int index)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Check_ButtonCode_forData(data_p, index));
}
#endif

/*
 ************************************************************************
 *	index番目のコードがクリヤー命令かを調べる(２コードしらべる)
 ************************************************************************
 */
#if 0
/*メッセージデータ用 */
static int mMsg_Check_ClearCode_forData(unchar *data_p, int index)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if(code == CONT_CLEAR) {
	    return(TRUE);
	}
    }
    return(FALSE);
}

/* ウインドウ構造体用 */
static int mMsg_Check_ClearCode(M_MSG_WIN *win_p, int index)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Check_ClearCode_forData(data_p, index));
}
#endif

/*
 ******************************************************************************************
 *	index番目のコードがカーソル移動遅延タイマーセット命令かを調べる(２コードしらべる)
 ******************************************************************************************
 */
#if 0
/*メッセージデータ用 */
static int mMsg_Check_CursolSetTimeCode_forData(unchar *data_p, int index)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if(code == CONT_CURSOL_SET_TIME) {
	    return(TRUE);
	}
    }
    return(FALSE);
}

/* ウインドウ構造体用 */
static int mMsg_Check_CursolSetTimeCode(M_MSG_WIN *win_p, int index)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Check_CursolSetTimeCode_forData(data_p, index));
}
#endif

/*
 ******************************************************************************************
 *	index番目のコードが色変え命令かを調べる(２コードしらべる)
 ******************************************************************************************
 */
#if 0
/*メッセージデータ用 */
static int mMsg_Check_ColorCode_forData(unchar *data_p, int index)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if(code == CONT_COLOR) {
	    return(TRUE);
	}
    }
    return(FALSE);
    
}

/* ウインドウ構造体用 */
static int mMsg_Check_ColorCode(M_MSG_WIN *win_p, int index)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Check_ColorCode_forData(data_p, index));
}
#endif

/*
 ******************************************************************************************
 *	index番目のカーソル移動遅延タイマーセットの値を返す
 ******************************************************************************************
 */
/*メッセージデータ用 */
static float mMsg_Get_CursolSetTimeCode_forData(unchar *data_p, int index)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if(code == CONT_CURSOL_SET_TIME) {
	    code = data_p[index+2];
	    return((float)(int)code);
	}
    }
#if DEBUG
    PRINTF(ESC_ERROR
	   "mMsg_Get_CursolSetTimeCode_forData:カーソル移動遅延タイマーセットの値を取れない!!!\n"
	   ESC_NORMAL);
#endif
    return(0.0F);
}

/* ウインドウ構造体用 */
static float mMsg_Get_CursolSetTimeCode(M_MSG_WIN *win_p, int index)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Get_CursolSetTimeCode_forData(data_p, index));
}

/*
 ******************************************************************************************
 *	index番目の色変え命令の色をゲット
 ******************************************************************************************
 */
/*メッセージデータ用 */
static int mMsg_Get_ColorCode_forData(unchar *data_p,
				      int index,
				      unchar *r_p,
				      unchar *g_p,
				      unchar *b_p)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if(code == CONT_COLOR) {
	    *r_p = data_p[index+2];
	    *g_p = data_p[index+3];
	    *b_p = data_p[index+4];
	    return(TRUE);
	}
    }
#if DEBUG
    PRINTF(ESC_ERROR
	   "mMsg_Get_ColorCode_forData:色の値を取れない!!!\n"
	   ESC_NORMAL);
#endif		    
    return(FALSE);
}

/* ウインドウ構造体用 */
static int mMsg_Get_ColorCode(M_MSG_WIN *win_p,
			      int index,
			      unchar *r_p,
			      unchar *g_p,
			      unchar *b_p)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Get_ColorCode_forData(data_p,
				      index,
				      r_p,
				      g_p,
				      b_p));
}

/*
 ******************************************************************************************
 *	index番目のデモ命令の内容をゲット
 ******************************************************************************************
 */
/*メッセージデータ用 */
static int mMsg_Get_OrderCode_forData(unchar *data_p,
				      int index,
				      int *num_p,
				      unshort *value_p)
{
    unchar code = data_p[index];
    
    if(code == MOJI_CONT) {
	code = data_p[index+1];
	if((code == CONT_SET_DEMO_ORDER_PLAYER) ||
	   (code == CONT_SET_DEMO_ORDER_NPC0) ||
	   (code == CONT_SET_DEMO_ORDER_NPC1) ||
	   (code == CONT_SET_DEMO_ORDER_NPC2) ||
	   (code == CONT_SET_DEMO_ORDER_QUEST)) {
	    unshort temp_value;
	    *num_p = (int)(data_p[index+2]);

	    temp_value = (unshort)(((int)(data_p[index+3])) << 8);
	    *value_p = (unshort)(temp_value | (0x00ff & ((int)(data_p[index+4]))));
	    return(TRUE);
	}
    }
#if DEBUG
    PRINTF(ESC_ERROR
	   "mMsg_Get_OrderCode_forData:デモの値を取れない!!!\n"
	   ESC_NORMAL);
#endif		    
    return(FALSE);
}

/* ウインドウ構造体用 */
static int mMsg_Get_OrderCode(M_MSG_WIN *win_p,
			      int index,
			      int *num_p,
			      unshort *value_p)
{
    unchar *data_p = win_p->msg_p->code.data;
    return(mMsg_Get_OrderCode_forData(data_p,
				      index,
				      num_p,
				      value_p));
}

/******************************************************************************
 *
 *	index番目の文字表示音声の ＯＮ／ＯＦＦ値 取得関数
 *
 ******************************************************************************/
static int mMsg_Get_SoundCutCode_forData(unchar *data_p, int index)
{
    if ((data_p[index] == MOJI_CONT) &&
	(data_p[index + 1] == CONT_SOUND_CUT)) {
#if DEBUG
	if (!(data_p[index + 2] == 0 || data_p[index + 2] == 1)) {
	    PRINTF(ESC_WARNING"文字表示音声命令が変？(%d %d %d)(%s %d)\n"ESC_NORMAL,
		   data_p[index], data_p[index + 1], data_p[index + 2],
		   __FILE__, __LINE__);
	}
#endif
	return (int)(data_p[index + 2]);
    } else {
#if DEBUG
	PRINTF(ESC_ERROR"文字表示音声命令が変？(%d %d %d)(%s %d)\n"ESC_NORMAL,
	       data_p[index], data_p[index + 1], data_p[index + 2],
	       __FILE__, __LINE__);
#endif
	return 0;
    }
}

/* ウインドウ構造体用 */
static int mMsg_Get_SoundCutCode(M_MSG_WIN *win_p, int index)
{
    return mMsg_Get_SoundCutCode_forData(win_p->msg_p->code.data, index);
}

/******************************************************************************
 *
 *	index番目の ＢＧＭ生成 パラメータ取得
 *
 ******************************************************************************/
static void mMsg_Get_bgm_make_forData(unchar *data_p, int index,
				      FONT_BgmNum *bgm_num_p,
				      FONT_BgmStop *bgm_stop_ex_p)
{
    unchar *code_p = &(data_p[index]);
    
    if ((*(code_p + 0) == MOJI_CONT) &&
	(*(code_p + 1) == CONT_BGM_MAKE) &&
	(*(code_p + 2) < FONT_BgmNum_END) &&
	(*(code_p + 3) < FONT_BgmStop_END)) {
	
	*bgm_num_p = (FONT_BgmNum)(*(code_p + 2));
	*bgm_stop_ex_p = (FONT_BgmStop)(*(code_p + 3));
    } else {
#if DEBUG
	PRINTF(ESC_ERROR"ＢＧＭスタート命令が変！？(%d %d %d %d)(%s %d)\n"ESC_NORMAL,
	       *(code_p + 0), *(code_p + 1), *(code_p + 2),  *(code_p + 3), 
	       __FILE__, __LINE__);
#endif
	*bgm_num_p = FONT_BgmNum_END;
	*bgm_stop_ex_p = FONT_BgmStop_END;
    }
}

/* ウインドウ構造体用 */
static void mMsg_Get_bgm_make(M_MSG_WIN *win_p, int index,
			      FONT_BgmNum *bgm_num_p,
			      FONT_BgmStop *bgm_stop_ex_p)
{
    mMsg_Get_bgm_make_forData(win_p->msg_p->code.data, index,
			      bgm_num_p, bgm_stop_ex_p);
}

/******************************************************************************
 *
 *	index番目の ＢＧＭ削除パラメータ取得
 *
 ******************************************************************************/
static void mMsg_Get_bgm_delete_forData(unchar *data_p, int index,
					FONT_BgmNum *bgm_num_p,
					FONT_BgmStop *bgm_stop_my_p)
{
    unchar *code_p = &(data_p[index]);
    
    if ((*(code_p + 0) == MOJI_CONT) &&
	(*(code_p + 1) == CONT_BGM_DELETE) &&
	(*(code_p + 2) < FONT_BgmNum_END) &&
	(*(code_p + 3) < FONT_BgmStop_END)) {
	
	*bgm_num_p = (FONT_BgmNum)(*(code_p + 2));
	*bgm_stop_my_p = (FONT_BgmStop)(*(code_p + 3));
    } else {
#if DEBUG
	PRINTF(ESC_ERROR"ＢＧＭストップ命令が変！？(%d %d %d %d)(%s %d)\n"ESC_NORMAL,
	       *(code_p + 0), *(code_p + 1), *(code_p + 2), *(code_p + 3),
	       __FILE__, __LINE__);
#endif
	*bgm_num_p = FONT_BgmNum_END;
	*bgm_stop_my_p = FONT_BgmStop_END;
    }
}

/* ウインドウ構造体用 */
static void mMsg_Get_bgm_delete(M_MSG_WIN *win_p, int index,
				FONT_BgmNum *bgm_num_p,
				FONT_BgmStop *bgm_stop_my_p)
{
    mMsg_Get_bgm_delete_forData(win_p->msg_p->code.data, index,
				bgm_num_p, bgm_stop_my_p);
}

/******************************************************************************
 *
 *	index番目の MSG_TIME_END の タイマ取得
 *
 ******************************************************************************/
static int mMsg_Get_MsgTimeEnd_time_forData(unchar *data_p, int index)
{
    unchar *code_p = &(data_p[index]);
    
    if ((*(code_p + 0) == MOJI_CONT) &&
	(*(code_p + 1) == CONT_MSG_TIME_END)) {
	return (int)(*(code_p + 2));	/* ret. (0 〜255) */
    } else {
#if DEBUG
	PRINTF(ESC_ERROR"CONT_MSG_TIME_END 変！？(%d %d %d)(%s %d)\n"ESC_NORMAL,
	       *(code_p + 0), *(code_p + 1), *(code_p + 2),
	       __FILE__, __LINE__);
#endif
        return 0;
    }
}

/* ウインドウ構造体用 */
static int mMsg_Get_MsgTimeEnd_time(M_MSG_WIN *win_p, int index)
{
    return mMsg_Get_MsgTimeEnd_time_forData(win_p->msg_p->code.data, index);
}

/*
 *	index番目のコードが MSG_TIME_END かを調べる
 */
/*メッセージデータ用 */
static int mMsg_Check_MsgTimeEndCode_forData(unchar *data_p, int index)
{
    unchar *code_p = &(data_p[index]);

    return ((*(code_p + 0) == MOJI_CONT) &&
	    (*(code_p + 1) == CONT_MSG_TIME_END));
}

/* ウインドウ構造体用 */
static int mMsg_Check_MsgTimeEndCode(M_MSG_WIN *win_p, int index)
{
    return mMsg_Check_MsgTimeEndCode_forData(win_p->msg_p->code.data,
					     index);
}

/*
 *	次がMSG_TIME_END かを調べる
 */
static int mMsg_Check_NextIndex_MsgTimeEndCode(M_MSG_WIN *win_p)
{
    return mMsg_Check_MsgTimeEndCode(win_p,
				     win_p->now_end_font_code_cursol_index);
}

/******************************************************************************
 *
 *	index番目の システム用トリガーＳＥパラメータ取得
 *
 ******************************************************************************/
static void mMsg_Get_sound_trg_sys_forData(unchar *data_p, int index,
					   FONT_TrgSys *se_num_p)
{
    unchar *code_p = &(data_p[index]);
    
    if ((*(code_p + 0) == MOJI_CONT) &&
	(*(code_p + 1) == CONT_SOUND_TRG_SYS) &&
	(*(code_p + 2) < FONT_TrgSys_END)) {
	
	*se_num_p = (FONT_TrgSys)(*(code_p + 2));
    } else {
#if DEBUG
	PRINTF(ESC_ERROR"システム用トリガーＳＥ命令が変！？(%d %d %d)(%s %d)\n"ESC_NORMAL,
	       *(code_p + 0), *(code_p + 1), *(code_p + 2),
	       __FILE__, __LINE__);
#endif
	*se_num_p = FONT_TrgSys_END;
    }
}

/* ウインドウ構造体用 */
static void mMsg_Get_sound_trg_sys(M_MSG_WIN *win_p, int index,
				   FONT_TrgSys *se_num_p)
{
    mMsg_Get_sound_trg_sys_forData(win_p->msg_p->code.data, index,
				   se_num_p);
}

/*
 ******************************************************************************
 *	指定した行のフォントカラーをセット
 ******************************************************************************
 */
static void mMsg_Set_LineFontColor(M_MSG_WIN *win_p,
				   int line_num,
				   unchar r, unchar g, unchar b, unchar a)
{
    if((0 <= line_num) && (line_num < M_MSG_TOTAL_LINE_DRAW_FONT_AREA)) {
	rgba_t *font_color_p = &(win_p->font_color[line_num]);

	font_color_p->r = r;
	font_color_p->g = g;
	font_color_p->b = b;
	font_color_p->a = a;
    }
#if DEBUG
    else {
	PRINTF(ESC_WARNING
	       "mMsg_Set_FontColor_forLine:%d そんなラインの色は変えられない!!!!!!!!!!!!!!\n"
	       ESC_NORMAL,
	       line_num);
    }
#endif

}

/*
 ******************************************************************************
 *	フォントカラーの初期化
 ******************************************************************************
 */
static void mMsg_init_FontColor(M_MSG_WIN *win_p)
{
#if 1
    int line;

    for(line = 0; line < M_MSG_TOTAL_LINE_DRAW_FONT_AREA; line++) {
	mMsg_Set_LineFontColor(win_p,
			       line,
			       M_MSG_BASIC_FONT_COLOR_R,
			       M_MSG_BASIC_FONT_COLOR_G,
			       M_MSG_BASIC_FONT_COLOR_B,
			       M_MSG_BASIC_FONT_COLOR_A);
	
    }
#else
    win_p->font_color[0].r = M_MSG_BASIC_FONT_COLOR_R;
    win_p->font_color[0].g = M_MSG_BASIC_FONT_COLOR_G;
    win_p->font_color[0].b = M_MSG_BASIC_FONT_COLOR_B;
    win_p->font_color[0].a = M_MSG_BASIC_FONT_COLOR_A;
    win_p->font_color[1].r = M_MSG_BASIC_FONT_COLOR_R;
    win_p->font_color[1].g = M_MSG_BASIC_FONT_COLOR_G;
    win_p->font_color[1].b = M_MSG_BASIC_FONT_COLOR_B;
    win_p->font_color[1].a = M_MSG_BASIC_FONT_COLOR_A;
    win_p->font_color[2].r = M_MSG_BASIC_FONT_COLOR_R;
    win_p->font_color[2].g = M_MSG_BASIC_FONT_COLOR_G;
    win_p->font_color[2].b = M_MSG_BASIC_FONT_COLOR_B;
    win_p->font_color[2].a = M_MSG_BASIC_FONT_COLOR_A;
    win_p->font_color[3].r = M_MSG_BASIC_FONT_COLOR_R;
    win_p->font_color[3].g = M_MSG_BASIC_FONT_COLOR_G;
    win_p->font_color[3].b = M_MSG_BASIC_FONT_COLOR_B;
    win_p->font_color[3].a = M_MSG_BASIC_FONT_COLOR_A;
#endif
}

/*
 ******************************************************************************
 *	現在表示中の行数の初期化
 ******************************************************************************
 */
static void mMsg_init_NowDisplayLIne(M_MSG_WIN *win_p)
{
    win_p->now_display_line = 0;
}

/*
 ******************************************************************************
 *	表示範囲のクリヤー
 ******************************************************************************
 */
static void mMsg_Clear_CursolIndex(M_MSG_WIN *win_p)
{
    win_p->now_start_font_code_cursol_index = win_p->now_end_font_code_cursol_index;
    /* フォントカラーの初期化 */
    mMsg_init_FontColor(win_p);
    /* 現在表示中の行数の初期化 */
    mMsg_init_NowDisplayLIne(win_p);
}

/*
 ************************************************************************
 *	タイマーのセット
 ************************************************************************
 */
static void mMsg_SetTimer(M_MSG_WIN *win_p, float time)
{
    /* 間を空ける為のタイマーを入れる */
    win_p->cursol_timer = time;
}

/*
 ******************************************************************************
 *	与えられた番号のメッセージデータのロムアドレスとサイズを求める
 ******************************************************************************
 */

#define M_MSG_DMA_TABLE_DUMMY_SIZE 16

/* DMA用バッファーへんすう */
typedef union {
    u64 dummy;
    int data[M_MSG_DMA_TABLE_DUMMY_SIZE / sizeof(int)];
} mMsg_dma_table_dummy;

static void mMsg_Get_MsgDataAddressAndSize(int index, u32 *rom_p, u32 *size_p)
{
    if((0 <= index) && (index < TOTAL_MSG_DATA_NUMBER)) {
	int offset;
	int size;
	
	/* テーブルの転送 */
	{
	    mMsg_dma_table_dummy ram;
	    u32 rom_p;
	    if(index & 1) {		/* 奇数なら */
		rom_p = (u32)_UC_object_msg_tableSegmentRomStart + (u32)(4 * (index - 1));
		dmacopy_fg(ram.data, rom_p, 8);
		offset = ram.data[0];
		size = ram.data[1] - offset;
	    }
	    else {
		if(index == 0) {		/* ０なら */
		    rom_p = (u32)_UC_object_msg_tableSegmentRomStart;
		    dmacopy_fg(ram.data, rom_p, 8);
		    offset = 0;
		    size = ram.data[0];
		}
		else {			/* 偶数で０でない */
		    rom_p = (u32)_UC_object_msg_tableSegmentRomStart + (u32)(4 * (index - 2));
		    dmacopy_fg(ram.data, rom_p, 16);
		    offset = ram.data[1];
		    size = ram.data[2] - offset;
		}
	    }
	}

	if(size <= M_MSG_MAX_DATA) {
	    *rom_p = (u32)_UC_object_msgSegmentRomStart + (u32)offset;
	    *size_p = (u32)size;
	}
	else {
#if DEBUG
	    PRINTF(ESC_ERROR
		   "mMsg_Get_MsgDataAddressAndSize:大きすぎるデータ! (%d %d)(%s %d)\n"
		   ESC_NORMAL,
		   size, M_MSG_MAX_DATA, __FILE__, __LINE__);
#endif	
	    *rom_p = NULL;
	    *size_p = 0;
	}
    }
    else {
#if DEBUG
	PRINTF(ESC_ERROR
	       "mMsg_Get_MsgDataAddressAndSize:無効なindex!!!!!!\n"
	       ESC_NORMAL);
#endif	
	*rom_p = NULL;
	*size_p = 0;
    }
}

/*
 ******************************************************************************
 *	メッセージデータサイズ取得
 ******************************************************************************
 */
static int mMsg_Count_MsgData(unchar *data_p)
{
    int index = 0;
    
    while(index < M_MSG_MAX_DATA) {
	if(mMsg_Check_LastCode_forData(data_p, index) ||
	   mMsg_Check_ContinueCode_forData(data_p, index) ||
	   mMsg_Check_MsgTimeEndCode_forData(data_p, index)) {
	    index += mFont_CodeSize_idx_get(data_p, index);
	    break;
	}
	index += mFont_CodeSize_idx_get(data_p, index);
    }
    
#if DEBUG
    if(index >= M_MSG_MAX_DATA) {
	PRINTF(ESC_ERROR
	       "mMsg_Count_MsgData:エンドコードが入ってない!!!!!!!!!!!!!!!!!!!!!!!\n"
	       ESC_NORMAL);
	assert(0);
    }
#endif
    
    return(index+0);
}

/*
 ******************************************************************************
 *	与えられたメッセージ領域に与えられた番号のメッセージデータをロード
 ******************************************************************************
 *	<補足>
 *	成功、失敗の真偽を返すので、ラムクリアは行っていない。
 */
static int mMsg_LoadMsgData(M_MSG_DATA *msg_p, int index, int cut)
{
    if(msg_p != NULL) {
	u32 rom_p, size;

#if DEBUG
	/* メッセージ デバッグ用 */
	mREG(80) = (short)index;
#endif
	mMsg_Get_MsgDataAddressAndSize(index, &rom_p, &size);
	if ((rom_p != NULL) && (size != 0)) {
	    u32 dma_rom_p = rom_p & 0xfffffff8;
	    u32 sub_rom_p = rom_p - dma_rom_p;
	    u32 dma_size = (sub_rom_p + size + 7) & 0xfffffff8;
#if DEBUG
	    if((dma_rom_p + dma_size) > ((u32)_UC_object_msgSegmentRomEnd)) {
		PRINTF(ESC_ERROR
		       "mMsg_LoadMsgData:セグメント境界は１６バイトアライメントされているはずなのに%x!!!!!!!!!!\n"
		       "ダミーを入れないといけなくなった（小松に連絡してください）。"
		       ESC_NORMAL, (u32)_UC_object_msgSegmentRomEnd);
		assert(0);
	    }
#endif
	    dmacopy_fg(msg_p->code.data, dma_rom_p, dma_size);
	    
#if DEBUG
	    if (mREG(5) != 1) {	/* メッセージデータチェック中は非表示 */
		PRINTF("mMsg_LoadMsgData:ゲームフレーム(%d) メッセージ(%d) ロード\n",
		       gamePT->frame_counter, index);
	    }
#endif
	    {
		int i;
		int int_size = (int)size;
		unchar *domain_data_p = msg_p->code.data;
		unchar *src_data_p = msg_p->code.data + (int)sub_rom_p;
		
		for(i = 0; i < int_size; i++) {
		    *domain_data_p++ = *src_data_p++;
		}
	    }
	    msg_p->num = index;
	    msg_p->able = TRUE;
	    msg_p->total_code = mMsg_Count_MsgData(msg_p->code.data);
	    msg_p->cut = cut;
	    return(TRUE);
	}
#if DEBUG
	else {
	    if (rom_p == NULL) {
		PRINTF(ESC_WARNING"メッセージデータ実体のアドレスが得られなかった<%d>(%s %d)\n"
		       ESC_NORMAL, index, __FILE__, __LINE__);
	    } else {
		PRINTF(ESC_WARNING"メッセージデータ実体のサイズがゼロ<%d>(%s %d)\n"ESC_NORMAL,
		       index, __FILE__, __LINE__);
	    }
	}
#endif
    }
    msg_p->able = FALSE;
    return(FALSE);
}

/*
 ******************************************************************************
 *	メッセージデータを変更して表示位置をリセット
 ******************************************************************************
 */
extern int mMsg_ChangeMsgData(M_MSG_WIN *win_p, int msg_num)
{
#if DEBUG
    if(!(mMsg_Check_main_index(win_p, M_MSG_MAIN_WAIT) ||
	 mMsg_Check_main_index(win_p, M_MSG_MAIN_NORMAL) ||
	 mMsg_Check_main_index(win_p, M_MSG_MAIN_CURSOL))) {
	PRINTF(ESC_WARNING
	       "mMsg_ChangeMsgData:メッセージのモードが不適切%d!!!!!!!\n"
	       ESC_NORMAL, win_p->main_index);
    }
    if(!((0 <= msg_num) && (msg_num < TOTAL_MSG_DATA_NUMBER))) {
	PRINTF(ESC_WARNING
	       "mMsg_ChangeMsgData:メッセージ番号が不適切%d!!!!!!!\n"
	       ESC_NORMAL, msg_num);
    }
#endif
    
    if((0 <= msg_num) && (msg_num < TOTAL_MSG_DATA_NUMBER)) {
	if(mMsg_LoadMsgData(win_p->msg_p, msg_num, FALSE)) {
//	    win_p->request_msg_num = msg_num;
	    /* 現在,何処からの文字を表示しているか(カーソル用) */
	    win_p->now_end_font_code_cursol_index = 0;
	    /* 表示範囲のクリヤー */
	    mMsg_Clear_CursolIndex(win_p);
	    mMsg_SetTimer(win_p, M_MSG_TIME_NEXT_PAGE);	    
	    return(TRUE);
	}
    }
    return(FALSE);
}

/*
 ********************************************************************************
 *	"現在,発声しているか"のフラグを解除
 ********************************************************************************
 */
static void mMsg_Unset_NowUtter(M_MSG_WIN *win_p)
{
    win_p->now_utter = FALSE;
}

/*
 ********************************************************************************
 *	"現在,発声しているか"のフラグをセット
 ********************************************************************************
 */
static void mMsg_Set_NowUtter(M_MSG_WIN *win_p)
{
    win_p->now_utter = TRUE;
}

/*
 ********************************************************************************
 *	"現在,発声しているか"のフラグをチェック
 ********************************************************************************
 */
extern int mMsg_Check_NowUtter(void)
{
    M_MSG_WIN *win_p = mMsg_Get_base_window_p();
    return((int)(win_p->now_utter));
}

/*
 ******************************************************************************
 *	メッセージウインドウの初期化
 ******************************************************************************
 */
static void mMsg_init(GAME *game_p)
{
    (void)game_p;
    /* メッセージデータの初期化 */
    mMsg_data[0].able = FALSE;		/* 現在のデータは使用可能か */
    
    /* メッセージウインドウの初期化 */
    mMsg_window[0].able = FALSE;	/* 現在のデータは使用可能か */
    mMsg_window[0].num = 0;		/* ウインドウ番号 */
    mMsg_window[0].tex_p = NULL;	/* 文字表示用テクスチャ領域へのポインタ */
    mMsg_window[0].msg_p = &(mMsg_data[0]);	/* メッセージデータのラムへのポインタ */
    mMsg_window[0].center_rectX
	= ((float)SCREEN_WD)*0.5F;	/* ウインドウの画面座標系での中心位置Ｘ */
    mMsg_window[0].center_rectY
	= ((float)SCREEN_HT)*0.5F + 65.0F + 0.4F;	/* ウインドウの画面座標系での中心位置Ｙ */
    mMsg_window[0].width = 245.0F;			/* ウインドウの幅 */
    mMsg_window[0].height = 96.0F;			/* ウインドウの高さ */
    mMsg_window[0].client_actor_p = NULL;		/* 呼び出したアクターへのポインター */
    mMsg_window[0].client_name_total = 0;	/* 名前文字数 */
    /* ウインドウの画面座標系での名前の左上Ｘ */
    mMsg_window[0].client_name_rectX = M_MSG_CLIENT_NAME_BASEX_F;
    /* ウインドウの画面座標系での名前の左上Ｙ */
    mMsg_window[0].client_name_rectY = M_MSG_CLIENT_NAME_BASEY_F;
    /* ボタン待ち表示オン・オフ */
    mMsg_window[0].display_button_turn = FALSE;

    mMsg_window[0].name_color.r = 50;
    mMsg_window[0].name_color.g = 90;
    mMsg_window[0].name_color.b = 0;
    mMsg_window[0].name_color.a = 255;
    mMsg_window[0].name_window_color.r = 160;
    mMsg_window[0].name_window_color.g = 215;
    mMsg_window[0].name_window_color.b = 30;
    mMsg_window[0].name_window_color.a = 255;
    mMsg_window[0].window_color.r = 235;
    mMsg_window[0].window_color.g = 255;
    mMsg_window[0].window_color.b = 235;
    mMsg_window[0].window_color.a = 255;

    /* フォントカラーの初期化 */
    mMsg_init_FontColor(&(mMsg_window[0]));
    /* 現在表示中の行数の初期化 */
    mMsg_init_NowDisplayLIne(&(mMsg_window[0]));
    mMsg_window[0].button_turn_color.r = 0;
    mMsg_window[0].button_turn_color.g = 0;
    mMsg_window[0].button_turn_color.b = 255;
    mMsg_window[0].button_turn_color.a = 0;
    
    mMsg_window[0].font_texScaleX = 1.0F;	/* 表示文字のスケールＸ */
    mMsg_window[0].font_texScaleY = 1.0F;	/* 表示文字のスケールＹ */
    mMsg_window[0].font_texDotW
	= M_MSG_DRAW_FONT_AREA_W+2*M_FONT_TEXSPACE_S;	/* 文字用のテクスチャ領域ドット幅 */
    mMsg_window[0].font_texDotH
	= M_MSG_DRAW_FONT_AREA_H+2*M_FONT_TEXSPACE_T;	/* 文字用のテクスチャ領域ドット高さ */
    mMsg_window[0].total_line
	= M_MSG_TOTAL_LINE_DRAW_FONT_AREA;		/* 横の行数 */
    mMsg_window[0].now_display_line
	= 0;	/* 現在表示中の行数 */

    
    /* 作業領域 */
    mMsg_window[0].timer = 0.0F;		/* 作業用タイマー */
    mMsg_SetTimer(&(mMsg_window[0]), 0.0F);
    mMsg_window[0].button_turn_timer = 0.0F;	/* ボタン待ち点滅タイマー */
    mMsg_window[0].now_start_font_code_cursol_index = 0;
			/* 現在,何処からの文字を表示しているか(カーソル用) */
    mMsg_window[0].now_end_font_code_cursol_index = 0;
    			/* 現在,何処までの文字を表示しているか(カーソル用) */
    mMsg_window[0].now_window_scale = 0.0F;	/* ウインドウのスケール */
    mMsg_window[0].now_font_scale = 1.0F;	/* 文字のスケール */

    mMsg_window[0].request_main_index = -1;	/* リクエストされたメイン処理のインデックス */
    mMsg_window[0].request_priority
	= M_MSG_REQUEST_PRIORITY_MINIMAM;	/* リクエスト優先順位 */
//    mMsg_window[0].request_msg_num
//	= MSG_DATA_NUMBER_test_0;			/* リクエストされたメッセージの番号 */
    
    mMsg_window[0].main_index
	= M_MSG_MAIN_HIDE;			/* メイン処理のインデックス */
    mMsg_window[0].flag_draw = FALSE;		/* 描画処理を通すか */
    mMsg_window[0].flag_cancel = FALSE;		/* カーソル処理キャンセル中か */
    mMsg_window[0].flag_cancel_able = FALSE;	/* カーソル処理キャンセル可能か */
    mMsg_window[0].continue_msg_num = LIMIT_UNSHORT_ABS;	/* 続くメッセージの番号(unshortの最大値なら継続キャンセル) */
    /* 外部からメッセージデータの"継続メッセージ待ち"を"終了待ち"に変えるフラグの解除 */
    mMsg_Unset_CancelNormalContinue(&(mMsg_window[0]));
    /* "ボタン押しを待たずに次へ行く為のフラグ"を解除 */
    mMsg_Unset_ForceNext(&(mMsg_window[0]));
    /* "メッセージの継続ボタンを受け付けない為のフラグ"を解除 */
    mMsg_Unset_LockContinue(&(mMsg_window[0]));

    /* 表示速度をサウンド側へ伝える */
    mMsg_sound_MessageSpeedForce(0.0F);
    /* 喜怒哀楽状態をサウンド側へ伝えるのリセット */
    mMsg_sound_MessageStatus(VOICE_STATUS_NORMAL);
    
    bitclr(mMsg_window[0].status, (M_MSG_STATIS_LAST_IDLING_REQ |
				   M_MSG_STATIS_LAST_IDLING_NOW));

    /*  */
    mMsg_window[0].free_str_cl_id[mMSG_PF_CL_TBL_1] = (unchar)mMSG_Pf_CL_ID_NONE;
    mMsg_window[0].free_str_cl_id[mMSG_PF_CL_TBL_2] = (unchar)mMSG_Pf_CL_ID_NONE;
    mMsg_window[0].free_str_cl_id[mMSG_PF_CL_TBL_5] = (unchar)mMSG_Pf_CL_ID_NONE;
    
#if DEBUG    
    if(TOTAL_MSG_DATA_NUMBER >= LIMIT_UNSHORT_ABS) {
	PRINTF(ESC_ERROR
	       "mMsg_init:メッセージ番号がLIMIT_UNSHORT_ABS以上はまずい!!!!!!!!!!!!!!!!!!!!!!!! = %d\n"
	       "LIMIT_UNSHORT_ABSは制御で使用している\n"
	       ESC_NORMAL,
	       TOTAL_MSG_DATA_NUMBER);
	assert(0);
    }
#endif
}

/*
 ********************************************************************************
 *
 *	"string_p"で与えられる文字列の,後から初めて"MOJI_space1"以外の
 *	文字が出てきた所で前からの文字数を返す(MOJI_space1は数えない)
 *
 *	又は"max_length"まで数える。
 *
 ********************************************************************************
 */
extern int mMsg_Get_Length_String(unchar *string_p, int max_length)
{
    int index;
    
    for(index = max_length-1; index >= 0; index--) {
	if(string_p[index] != MOJI_SPACE1) {
	    break;
	}
    }
    return(index+1);
}

/*
 ********************************************************************************
 *	外部から現在のメッセージウインドウの状態が
 *	"継続メッセージ待ち"かを調べる
 ********************************************************************************
 */
extern int mMsg_Check_MainNormalContinue(M_MSG_WIN *win_p)
{
    /* メイン処理のインデックスをチェック */
    if(win_p->main_index == M_MSG_MAIN_NORMAL) {
	/* 次が継続コードであるか調べる */
	if(mMsg_Check_NextIndex_ContinueCode(win_p)) {
	    return(TRUE);
	}
    }
    return(FALSE);
}

/*
 ********************************************************************************
 *	外部から現在のメッセージウインドウの状態が
 *	"ボタン待ち"かを調べる
 ********************************************************************************
 */
extern int mMsg_Check_MainNormal(M_MSG_WIN *win_p)
{
    /* メイン処理のインデックスをチェック */
    if(win_p->main_index == M_MSG_MAIN_NORMAL) {
	return(TRUE);
    }
    return(FALSE);
}

/*
 ********************************************************************************
 *	外部から現在のメッセージウインドウの状態が
 *	"隠れ"かを調べる
 ********************************************************************************
 */
extern int mMsg_Check_MainHide(M_MSG_WIN *win_p)
{
    /* メイン処理のインデックスをチェック */
    if(win_p->main_index == M_MSG_MAIN_HIDE) {
	return(TRUE);
    }
    return(FALSE);
}

/*
 ********************************************************************************
 *	外部から現在のメッセージウインドウの状態が
 *	"消滅"かを調べる
 ********************************************************************************
 */
extern int mMsg_Check_MainDisappear(M_MSG_WIN *win_p)
{
    /* メイン処理のインデックスをチェック */
    return (win_p->main_index == M_MSG_MAIN_DISAPPEAR);
}

/*
 ********************************************************************************
 *	外部からメッセージデータの
 *	"継続メッセージ待ち"を"終了待ち"に変える
 ********************************************************************************
 */
#if DEBUG
extern void DEBUG_mMsg_Set_CancelNormalContinue(M_MSG_WIN *win_p,
						const char *file,
						int line)
{
    (void)file; (void)line;
    
#if 1
    if (mREG(31) == 2) {
	PRINTF("<<<<<<<<<SET cancel_continue(%s %d)[%d](from :: %s %d)\n",
	       __FILE__, __LINE__, getP_game()->frame_counter, file, line);
    }
#endif
    win_p->cancel_continue = TRUE;
}
#else
extern void mMsg_Set_CancelNormalContinue(M_MSG_WIN *win_p)
{
    win_p->cancel_continue = TRUE;
}
#endif

/*
 ********************************************************************************
 *	外部からメッセージデータの
 *	"継続メッセージ待ち"を"終了待ち"に変えるフラグの解除
 ********************************************************************************
 */
#if DEBUG
extern void DEBUG_mMsg_Unset_CancelNormalContinue(M_MSG_WIN *win_p,
						  const char *file,
						  int line)
{
    (void)file; (void)line;
    
#if 1
    if (mREG(31) == 2) {
	PRINTF("<<<<<<<<<UNSET cancel_continue(%s %d)[%d](from :: %s %d)\n",
	       __FILE__, __LINE__, getP_game()->frame_counter, file, line);
    }
#endif
    win_p->cancel_continue = FALSE;
}
#else
extern void mMsg_Unset_CancelNormalContinue(M_MSG_WIN *win_p)
{
    win_p->cancel_continue = FALSE;
}
#endif

/*
 ********************************************************************************
 *	"ボタン押しを待たずに次へ行く為のフラグ"をセット
 ********************************************************************************
 */
#if DEBUG
extern void DEBUG_mMsg_Set_ForceNext(M_MSG_WIN *win_p,
				     const char *file,
				     int line)
{
    (void)file; (void)line;
    
#if 1
    if (mREG(31) == 2) {
	PRINTF(",,,,,,,,,,SET force_next(%s %d)[%d](from :: %s %d)\n",
	       __FILE__, __LINE__, getP_game()->frame_counter, file, line);
    }
#endif
    win_p->force_next = TRUE;
}
#else
extern void mMsg_Set_ForceNext(M_MSG_WIN *win_p)
{
    win_p->force_next = TRUE;
}
#endif

/*
 ********************************************************************************
 *	"ボタン押しを待たずに次へ行く為のフラグ"を解除
 ********************************************************************************
 */
#if DEBUG
extern void DEBUG_mMsg_Unset_ForceNext(M_MSG_WIN *win_p,
				       const char *file,
				       int line)
{
    (void)file; (void)line;
    
#if 1
    if (mREG(31) == 2) {
	PRINTF(",,,,,,,,,,UNSET force_next(%s %d)[%d](from :: %s %d)\n",
	       __FILE__, __LINE__, getP_game()->frame_counter, file, line);
    }
#endif
    win_p->force_next = FALSE;
}
#else
extern void mMsg_Unset_ForceNext(M_MSG_WIN *win_p)
{
    win_p->force_next = FALSE;
}
#endif

/*
 ********************************************************************************
 *	"メッセージの継続ボタンを受け付けない為のフラグ"の値をゲット
 ********************************************************************************
 */
extern int mMsg_Get_LockContinue(M_MSG_WIN *win_p)
{
    return(win_p->lock_continue);
}

/*
 ********************************************************************************
 *	"メッセージの継続ボタンを受け付けない為のフラグ"をセット
 ********************************************************************************
 */
#if DEBUG
extern void _mMsg_Set_LockContinue(M_MSG_WIN *win_p,
				   const char *file,
				   int line)
{
    (void)file; (void)line;
    win_p->lock_continue = TRUE;
    
#if 1
    if (mREG(31) == 2) {
	PRINTF("..........SET lock_continue(%s %d)[%d](from :: %s %d)\n",
	       __FILE__, __LINE__, getP_game()->frame_counter, file, line);
    }
#endif
}
#else
extern void mMsg_Set_LockContinue(M_MSG_WIN *win_p)
{
    win_p->lock_continue = TRUE;
}
#endif

/*
 ********************************************************************************
 *	"メッセージの継続ボタンを受け付けない為のフラグ"を解除
 ********************************************************************************
 */
#if DEBUG
extern void _mMsg_Unset_LockContinue(M_MSG_WIN *win_p,
				     const char *file,
				     int line)
{
    (void)file; (void)line;
    win_p->lock_continue = FALSE;
    
#if 1
    if (mREG(31) == 2) {
	PRINTF("..........UNSET lock_continue(%s %d)[%d](from :: %s %d)\n",
	       __FILE__, __LINE__, getP_game()->frame_counter, file, line);
    }
#endif
}
#else
extern void mMsg_Unset_LockContinue(M_MSG_WIN *win_p)
{
    win_p->lock_continue = FALSE;
}
#endif

/*-----------------------------------------------------------------------*
 *	エンドコードが来たときに時アイドリング状態にするフラグをセット
 *-----------------------------------------------------------------------*/
extern void mMsg_Set_idling_req(M_MSG_WIN *win_p)
{
    bitset(win_p->status, M_MSG_STATIS_LAST_IDLING_REQ);
}

/*-----------------------------------------------------------------------*
 *	現在アイドリング中であるかの判定
 *-----------------------------------------------------------------------*/
extern int mMsg_Check_idling_now(M_MSG_WIN *win_p)
{
    return (bitcheck(win_p->status, M_MSG_STATIS_LAST_IDLING_NOW) != FALSE);
}

/*
 ************************************************************************
 *	データの長さを変更
 *	返り値は"total_data"がいくらに変更されるべきか
 * 	("put_space != FALSE"の場合何処からスペースが入ったか)
 ************************************************************************
 *	<補足説明>
 *	src_index 以降のデータを (src_index - domain_index) だけ
 *	前にずらす．．．みたいの。
 */
extern int mMsg_MoveDataCut(unchar *data_p,	/* データの先頭ポインタ */
			    int domain_index,	/* データの何番目に詰めるか */
			    int src_index,	/* データの何番目から詰めるか */
			    int total_data,	/* data_pがいくつ在るか */
			    int put_space)	/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
{
    int changed_total_data = total_data;
    
    if(domain_index < src_index) {
	while(src_index < total_data) {
	    data_p[domain_index] = data_p[src_index];
	    domain_index++;
	    src_index++;
	}
	
	changed_total_data -= (src_index - domain_index);
	
	/* 詰めた最後尾に"MOJI_SPACE1"を入れる */
	if(put_space != FALSE) {
	    while(domain_index < total_data) {
		data_p[domain_index] = MOJI_SPACE1;
		domain_index++;
	    }
	}
    }
    else if(domain_index > src_index) {
	int total_move_data = total_data - src_index;
	int add_total_data = domain_index - src_index;
	
	changed_total_data +=  add_total_data;
	
	if(changed_total_data <= M_MSG_MAX_DATA) {	/* 選択肢と共用しているがツールでチェックしているので
							   M_CHOICE_STRING_MAX_LENGTH のチェックはここでは要らないとする */
	    int i;
	    unchar *domain_data_p = data_p + changed_total_data - 1;
	    unchar *src_data_p = data_p + total_data - 1;

	    for(i = 0; i < total_move_data; i++) {
		*domain_data_p-- = *src_data_p--;
	    }
	}
#if DEBUG
	else {
	    PRINTF(ESC_ERROR
		   "mMsg_MoveDataCut:文字列変換でデータが大きくなり過ぎた!!!!!!!!!!\n"
		   ESC_NORMAL);
	    assert(0);
	}
#endif
    }
    
    /* 総数の変更("put_space != FALSE"の場合何処からスペースが入ったか) */
    return(changed_total_data);
}

/*
 ************************************************************************
 *	文字列のコピー
 ************************************************************************
 */
static void mMsg_CopyString(unchar *domain_str_p,
			    unchar *src_str_p,
			    int total_data)
{
    int i;
    
    for(i = 0; i < total_data; i++) {
	*domain_str_p++ = *src_str_p++;
    }
}

/*
 ************************************************************************
 *	プレイヤー名色変えセット
 ************************************************************************
 */
#define MMSG_PLAYER_NAME_COLOR_R	75
#define MMSG_PLAYER_NAME_COLOR_G	95
#define MMSG_PLAYER_NAME_COLOR_B	155
static int mMsg_Set_PlayerNameColor(unchar *data_p,
				    int *start_index_p,
				    int total_code)
{
    /*
     *	文字単位の色制御命令データ
     *	(文字数データのみ毎回変更しているので注意！)
     */
    static unchar add_string[] = {
	MOJI_CONT, CONT_SET_COLOR_CHAR,	/* 色制御命令 */
	MMSG_PLAYER_NAME_COLOR_R,	/* R. */
	MMSG_PLAYER_NAME_COLOR_G,	/* G. */
	MMSG_PLAYER_NAME_COLOR_B,	/* B. */
	0,				/* 文字数 */
    };
    const int add_string_size = sizeof(add_string) / sizeof(unchar);
    unchar *name_p = nowPrivateGetP(pID.player_name[0]);
    int name_size = mMsg_Get_Length_String(name_p, PERSON_NAME_NUM);
    int hyphen_size;
    int new_total_code;
    const int start_index = *start_index_p;
    const int command_size = mFont_CodeSize_idx_get(data_p, *start_index_p);
    
    if (name_size > 0) {
	/* 名前の後ろに「ー」が何文字あるかを数える (制御コードはとばす) */
	hyphen_size = mMsg_Count_SameCode(data_p,
					  (*start_index_p) + command_size,
					  total_code,
					  MOJI_HYPHEN);
	
	/* 文字数データ変更 */
	add_string[5] = (unchar)(name_size + hyphen_size);
	
	/* データの長さの変更 */
	new_total_code = mMsg_MoveDataCut(data_p,
					  start_index + add_string_size,
					  start_index,
					  total_code,
					  FALSE);
	/* 色制御命令データコピー */
	mMsg_CopyString(data_p + start_index, add_string, add_string_size);
	
	/* index 修正 */
	*start_index_p += add_string_size;
    } else {
#if DEBUG
	PRINTF(ESC_ERROR"プレイヤ名前サイズゼロ！？<%d>(%s %d)\n"
	       ESC_NORMAL, name_size, __FILE__, __LINE__);
#endif
	new_total_code = total_code;
    }
    
    return new_total_code;
}

/*
 ************************************************************************
 *	プレイヤー名のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyPlayerName(unchar *data_p,
			       int start_index,
			       int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    unchar *string_p = nowPrivateGetP(pID.player_name[0]);
    int size_add_string = mMsg_Get_Length_String(string_p, PERSON_NAME_NUM);
    int new_total_code;
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */

    /* 名前のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string_p,
		    size_add_string);

    return(new_total_code);
}

/*
 ************************************************************************
 *	会話相手名のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyTalkName(ACTOR *talk_actor_p,
			     unchar *data_p,
			     int start_index,
			     int total_code)
{
#if 0
    if(talk_actor_p != NULL) {
	int command_size = mFont_CodeSize_idx_get(data_p, start_index);
	unchar string_p[PERSON_NAME_NUM];
	int size_add_string;
	int new_total_code;

	/** 2000. 2. 8 gen */
	mNpc_GetNpcWorldName(string_p, talk_actor_p);
	size_add_string = mMsg_Get_Length_String(string_p, PERSON_NAME_NUM);
	/* データの長さの変更 */
	new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
					  start_index + size_add_string,	/* データの何番目に詰めるか */
					  start_index + command_size,		/* データの何番目から詰めるか */
					  total_code,				/* data_pがいくつ在るか */
					  FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */

	/* 名前のコピー */
	mMsg_CopyString(&data_p[start_index],
			string_p,
			size_add_string);

	return(new_total_code);
    }
    else {
#if DEBUG
	PRINTF(ESC_WARNING
	       "mMsg_CopyTalkName:話してアクターがNULL!!!!!!!!!!!!!!!!!!!!!!!\n"
	       ESC_NORMAL);
#endif
	return(0);
    }
#else

    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    unchar string_p[PERSON_NAME_NUM];
    int size_add_string;
    int new_total_code;

    if(talk_actor_p != NULL) {
	mNpc_GetNpcWorldName(string_p, talk_actor_p);
	size_add_string = mMsg_Get_Length_String(string_p, PERSON_NAME_NUM);
    }
    else {
	size_add_string = 0;
    }
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 名前のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string_p,
		    size_add_string);
    
#if DEBUG
    if(talk_actor_p == NULL) {
	PRINTF(ESC_WARNING
	       "mMsg_CopyTalkName:話してアクターがNULL!!!!!!!!!!!!!!!!!!!!!!!\n"
	       ESC_NORMAL);
    }
#endif
	
    return(new_total_code);
    
#endif
}

/*
 ************************************************************************
 *	話し手語尾のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyTail(ACTOR *talk_actor_p,
			 unchar *data_p,
			 int start_index,
			 int total_code)
{
#if 0
    if(talk_actor_p != NULL) {
	int command_size = mFont_CodeSize_idx_get(data_p, start_index);
	unchar *string_p = mNpc_GetWordEnding(talk_actor_p);
	int size_add_string = mMsg_Get_Length_String(string_p, mNpc_WORD_ENDING_NUM);
	int new_total_code;
    
	/* データの長さの変更 */
	new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
					  start_index + size_add_string,	/* データの何番目に詰めるか */
					  start_index + command_size,		/* データの何番目から詰めるか */
					  total_code,				/* data_pがいくつ在るか */
					  FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */

	/* 語尾のコピー */
	mMsg_CopyString(&data_p[start_index],
			string_p,
			size_add_string);

	return(new_total_code);
    }
    else {
#if DEBUG
	PRINTF(ESC_WARNING
	       "mMsg_CopyTalkName:話してアクターがNULL!!!!!!!!!!!!!!!!!!!!!!!\n"
	       ESC_NORMAL);
#endif
	return(0);
    }
#else

    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    unchar *string_p = (talk_actor_p != NULL) ? mNpc_GetWordEnding(talk_actor_p) : NULL;
    int size_add_string = (talk_actor_p != NULL) ? mMsg_Get_Length_String(string_p, mNpc_WORD_ENDING_NUM) : 0;
    int new_total_code;
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */

    /* 語尾のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string_p,
		    size_add_string);

#if DEBUG
    if(talk_actor_p == NULL) {
	PRINTF(ESC_WARNING
	       "mMsg_CopyTalkName:話してアクターがNULL!!!!!!!!!!!!!!!!!!!!!!!\n"
	       ESC_NORMAL);
    }
#endif
    
    return(new_total_code);
    
#endif
}

/*
 ************************************************************************
 *	年のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyYear(unchar *data_p,
			 int start_index,
			 int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    u16 year = (u16)(int)ZCommonGet(time.rtcTime.year);
    unchar string[M_STRING_MAX_YEAR_STRING_LENGTH];	/* 右詰め文字列 */
    int size_add_string;
    int new_total_code;

    size_add_string = mString_Load_YearStringFromRom(string, year);
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 年のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string,
		    size_add_string);

    return(new_total_code);
}

/*
 ************************************************************************
 *	月のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyMonth(unchar *data_p,
			  int start_index,
			  int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    u8 month = (u8)(int)ZCommonGet(time.rtcTime.month);
    unchar string[M_STRING_MAX_MONTH_STRING_LENGTH];	/* 右詰め文字列 */
    int size_add_string;
    int new_total_code;

    size_add_string = mString_Load_MonthStringFromRom(string, month);
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,		/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 月のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string,
		    size_add_string);

    return(new_total_code);
}

/*
 ************************************************************************
 *	曜日のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyWeek(unchar *data_p,
			 int start_index,
			 int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    u8 week = (u8)(int)ZCommonGet(time.rtcTime.week);
    unchar string[M_STRING_MAX_WEEK_STRING_LENGTH];	/* 右詰め文字列 */
    int size_add_string;
    int new_total_code;

    size_add_string = mString_Load_WeekStringFromRom(string, week);
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,		/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 曜日のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string,
		    size_add_string);

    return(new_total_code);
}

/*
 ************************************************************************
 *	日のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyDay(unchar *data_p,
			int start_index,
			int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    u8 day = (u8)(int)ZCommonGet(time.rtcTime.day);
    unchar string[M_STRING_MAX_DAY_STRING_LENGTH];	/* 右詰め文字列 */
    int size_add_string;
    int new_total_code;

    size_add_string = mString_Load_DayStringFromRom(string, day);
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,		/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 日のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string,
		    size_add_string);

    return(new_total_code);
}

/*
 ************************************************************************
 *	時のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyHour(unchar *data_p,
			 int start_index,
			 int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    u8 hour = (u8)(int)ZCommonGet(time.rtcTime.hour);
    unchar string[M_STRING_MAX_HOUR_STRING_LENGTH];	/* 右詰め文字列 */
    int size_add_string;
    int new_total_code;
    
    size_add_string = mString_Load_HourStringFromRom(string, hour);
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 時のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string,
		    size_add_string);
    
    return(new_total_code);
}

/*
 ************************************************************************
 *	分のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyMin(unchar *data_p,
			int start_index,
			int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    u8 min = (u8)(int)ZCommonGet(time.rtcTime.min);
    unchar string[M_STRING_MAX_MIN_STRING_LENGTH];	/* 右詰め文字列 */
    int size_add_string;
    int new_total_code;

    size_add_string = mString_Load_MinStringFromRom(string, min);
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 分のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string,
		    size_add_string);

    return(new_total_code);
}

/*
 ************************************************************************
 *	秒のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopySec(unchar *data_p,
			int start_index,
			int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    u8 sec = (u8)(int)ZCommonGet(time.rtcTime.sec);
    unchar string[M_STRING_MAX_SEC_STRING_LENGTH];	/* 右詰め文字列 */
    int size_add_string;
    int new_total_code;

    size_add_string = mString_Load_SecStringFromRom(string, sec);
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 秒のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string,
		    size_add_string);

    return(new_total_code);
}

/*
 ************************************************************************
 *	自由文字列のコピー(返り値は書き換えた後のデータの総数)
 ************************************************************************
 */
extern int mMsg_CopyFree(M_MSG_WIN *win_p,
			 int num,
			 unchar *data_p,
			 int start_index,
			 int total_code)
{
    if(!((0 <= num) && (num < M_MSG_TOTAL_PUT_FREE_STRINGS))) {
#if DEBUG
	PRINTF(ESC_ERROR
	       "mMsg_CopyFree:おかしな置き換え番号=%d!!!!!!\n"
	       ESC_NORMAL
	       , num);
	assert(0);
#endif
	num = 0;
    }
    
    {
	int command_size = mFont_CodeSize_idx_get(data_p, start_index);
	unchar *string_p = win_p->free_str[num];
	int size_add_string = mMsg_Get_Length_String(string_p, M_MSG_PUT_FREE_STRINGS_LENGTH);
	int new_total_code;
    
	/* データの長さの変更 */
	new_total_code = mMsg_MoveDataCut(data_p,				/* データの先頭ポインタ */
					  start_index + size_add_string,	/* データの何番目に詰めるか */
					  start_index + command_size,		/* データの何番目から詰めるか */
					  total_code,				/* data_pがいくつ在るか */
					  FALSE);				/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */

	/* 自由文字列のコピー */
	mMsg_CopyString(&data_p[start_index],
			string_p,
			size_add_string);

	return(new_total_code);
    }
}

/*------------------------------------------*
 *	自由文字列 色制御命令セット
 *------------------------------------------*/
/*
 *	カラーデータ
 */
static ColorRGB MMSG_pf_cl[mMSG_Pf_CL_ID_MAX] = {
    {	0,	0,	0,	},	/* (dummy) */
    {	145,	60,	145,	},	/* QTarget */
    {	50,	130,	70,	},	/* QItem */
    {	MMSG_PLAYER_NAME_COLOR_R,
	MMSG_PLAYER_NAME_COLOR_G,
	MMSG_PLAYER_NAME_COLOR_B,    },	/* Player Name */
    {	160,	50,	75,	},	/* Other Player Name */
};

static int mMsg_Set_PfColor(unchar *data_p,	/* 文字データ */
			    int *start_index_p,	/* 現在位置格納ポインタ */
			    int total_code,	/* 実サイズ */
			    unchar *free_str_p,	/* 自由文字列へのポインタ */
			    mMSG_Pf_Cl_Id color_id)	/* カラーＩＤ */
{
    /*
     *	文字単位の色制御命令データ
     *	(R.G.B. 文字数データは毎回変更しているので注意！)
     */
#define ADD_STRING_SIZE 6
    static unchar add_string[ADD_STRING_SIZE] = {
	MOJI_CONT, CONT_SET_COLOR_CHAR,	/* 色制御命令(const) */
	0, 0, 0,			/* R.G.B. */
	0,				/* 文字数 */
    };
    int pf_size = mMsg_Get_Length_String(free_str_p, M_MSG_PUT_FREE_STRINGS_LENGTH);
    int new_total_code;
    const int start_index = *start_index_p;
    ColorRGB *cl_data_p = &(MMSG_pf_cl[color_id]);
    
    /* カラー変更 */
    add_string[2] = cl_data_p->r;
    add_string[3] = cl_data_p->g;
    add_string[4] = cl_data_p->b;
    
    /* 文字数データ変更 */
    add_string[5] = (unchar)pf_size;
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,
				      start_index + ADD_STRING_SIZE,
				      start_index,
				      total_code,
				      FALSE);
    /* 色制御命令データコピー */
    mMsg_CopyString(data_p + start_index, add_string, ADD_STRING_SIZE);
    
    /* index 修正 */
    *start_index_p += ADD_STRING_SIZE;
    
    return new_total_code;
#undef ADD_STRING_SIZE
}

/*
 ************************************************************************
 *	決定文字列のコピー(返り値は書き換えた文字数)
 ************************************************************************
 */
extern int mMsg_CopyDetermination(M_MSG_WIN *win_p,
				  unchar *data_p,
				  int start_index,
				  int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    unchar *string_p = win_p->choice_win.choice_data.string_determimation;
    int size_add_string = win_p->choice_win.choice_data.string_determimation_length;
    int new_total_code;
    
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */

    /* 決定文字列のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string_p,
		    size_add_string);
    
    return(new_total_code);
}

/*
 ************************************************************************
 *	国名のコピー(返り値は書き換えた文字数)
 ************************************************************************
 */
extern int mMsg_CopyCountryName(unchar *data_p,
				int start_index,
				int total_code)
{
    int new_total_code;
    int new_start_index;
    
    {
	int command_size = mFont_CodeSize_idx_get(data_p, start_index);
	unchar *string_p = mLd_GetLandName();
	int size_add_string = mMsg_Get_Length_String(string_p, COUNTRY_NAME_NUM);

	new_start_index = start_index + size_add_string;
	    
	/* データの長さの変更 */
	new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
					  start_index + size_add_string,	/* データの何番目に詰めるか */
					  start_index + command_size,		/* データの何番目から詰めるか */
					  total_code,				/* data_pがいくつ在るか */
					  FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
	
	/* 国名のコピー */
	mMsg_CopyString(&data_p[start_index],
			string_p,
			size_add_string);
    }
    
#if 1
    /* "むら"を付け足す */
    {
	unchar string[M_STRING_MAX_STRING_LENGTH];
	unchar *string_p = string;
	int size_add_string;

	mString_Load_StringFromRom(string_p,
				   M_STRING_MAX_STRING_LENGTH,
				   M_STRING_NUMBER_word_0);
	
	size_add_string = mMsg_Get_Length_String(string_p, M_STRING_MAX_STRING_LENGTH);

	/* データの長さの変更 */
	new_total_code = mMsg_MoveDataCut(data_p,				/* データの先頭ポインタ */
					  new_start_index + size_add_string,	/* データの何番目に詰めるか */
					  new_start_index,		/* データの何番目から詰めるか */
					  new_total_code,				/* data_pがいくつ在るか */
					  FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
	
	/* "むら"のコピー */
	mMsg_CopyString(&data_p[new_start_index],
			string_p,
			size_add_string);
    }
#endif
    
    return(new_total_code);
}

/*
 ************************************************************************
 *	０から９９乱数のコピー(返り値は書き換えた文字数)
 ************************************************************************
 */
extern int mMsg_CopyRamdomNumber2(unchar *data_p,
				  int start_index,
				  int total_code)
{
    int command_size = mFont_CodeSize_idx_get(data_p, start_index);
    unshort num = (unshort)(((int)get_random_timer(0, 100))%100);
    unchar string[2];
    int size_add_string;
    int new_total_code;
    
    /* 整数を文字列に直す */
    size_add_string = mFont_UnintToString(string,	/* 代入する文字列領域（少なくとも"figure"個ないといけない） */
					  (unint)num,	/* 変換する数値 */
					  2,	/* 下から何桁の数字を変換するか(shortならFIGURE_SHORT unintならFIGURE_UNINT) */
					  True,	/* 左詰めを行うか(右には"MOJI_SPACE1"が入る) */
					  False);	/* 左に０詰めを行うか */
	
    /* データの長さの変更 */
    new_total_code = mMsg_MoveDataCut(data_p,					/* データの先頭ポインタ */
				      start_index + size_add_string,	/* データの何番目に詰めるか */
				      start_index + command_size,		/* データの何番目から詰めるか */
				      total_code,				/* data_pがいくつ在るか */
				      FALSE);					/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */
    
    /* 乱数のコピー */
    mMsg_CopyString(&data_p[start_index],
		    string,
		    size_add_string);

    return(new_total_code);
}

/*
 ************************************************************************
 *	アイテム文字列のコピー(返り値は書き換えた文字数)
 ************************************************************************
 */
extern int mMsg_CopyItem(M_MSG_WIN *win_p,
			 int num,
			 unchar *data_p,
			 int start_index,
			 int total_code)
{
    if(!((0 <= num) && (num < M_MSG_TOTAL_PUT_ITEM_STRINGS))) {
#if DEBUG
	PRINTF(ESC_ERROR
	       "mMsg_CopyItem:おかしな置き換え番号=%d!!!!!!\n"
	       ESC_NORMAL
	       , num);
	assert(0);
#endif
	num = 0;
    }
    
    {
	int command_size = mFont_CodeSize_idx_get(data_p, start_index);
	unchar *string_p = win_p->item_str[num];
	int size_add_string = mMsg_Get_Length_String(string_p, mIN_ITEM_NAME_NUM);
	int new_total_code;
    
	/* データの長さの変更 */
	new_total_code = mMsg_MoveDataCut(data_p,				/* データの先頭ポインタ */
					  start_index + size_add_string,	/* データの何番目に詰めるか */
					  start_index + command_size,		/* データの何番目から詰めるか */
					  total_code,				/* data_pがいくつ在るか */
					  FALSE);				/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */

	/* 文字列のコピー */
	mMsg_CopyString(&data_p[start_index],
			string_p,
			size_add_string);

	return(new_total_code);
    }
}

/*
 ************************************************************************
 *	手紙文字列のコピー(返り値は書き換えた文字数)
 ************************************************************************
 */
extern int mMsg_CopyMail(M_MSG_WIN *win_p,
			 int num,
			 unchar *data_p,
			 int start_index,
			 int total_code)
{
    if(!((0 <= num) && (num < M_MSG_TOTAL_PUT_MAIL_STRINGS))) {
#if DEBUG
	PRINTF(ESC_ERROR
	       "mMsg_CopyMail:おかしな置き換え番号=%d!!!!!!\n"
	       ESC_NORMAL
	       , num);
	assert(0);
#endif
	num = 0;
    }
    
    {
	int command_size = mFont_CodeSize_idx_get(data_p, start_index);
	unchar *string_p = win_p->mail_str[num];
	int size_add_string = mMsg_Get_Length_String(string_p, M_MSG_PUT_MAIL_STRINGS_LENGTH);
	int new_total_code;

	/* 自動改行の処理 */
	
	/* データの長さの変更 */
	new_total_code = mMsg_MoveDataCut(data_p,				/* データの先頭ポインタ */
					  start_index + size_add_string,	/* データの何番目に詰めるか */
					  start_index + command_size,		/* データの何番目から詰めるか */
					  total_code,				/* data_pがいくつ在るか */
					  TRUE);				/* 詰めた最後尾に"MOJI_SPACE1"を入れるか */

	/* 文字列のコピー */
	mMsg_CopyString(&data_p[start_index],
			string_p,
			size_add_string);

	return(new_total_code);
    }
}

