#define	STRICT
#include	<windows.h>
#include	"kctrl.h"
#include	"diatrain.h"
#include	"compat.h"

BOOL		g_bNarrow = FALSE ;
char		*StrDayMask[] = {
	"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT", "HOL",
} ;
int			Num_StrDayMask = 8 ;
#define		MASK_ALL		0xFF
#define		MASK_INDEX		0x80000000

#define		is_index(d)		((d)&MASK_INDEX)
#define		get_index(d)	((d)&~MASK_INDEX)

/*-------------------------------------------------------------------------*
 * DetailInfo
 *-------------------------------------------------------------------------*/
/*
 * DetailInfo のコンストラクタ
 */
DetailInfo::DetailInfo( char mark )
{
	m_cMark = mark ;
	m_pText = 0 ;
}

/*
 * DetailInfo のデストラクタ
 */
DetailInfo::~DetailInfo()
{
	if ( m_pText ) {
		delete[] m_pText ;
	}
}

/*
 * 文字列をセットする
 */
void
DetailInfo::set( LPCSTR text )
{
	if ( m_pText ) {
		delete[] m_pText ;
	}
	if ( *text ) {
		m_pText = new CHAR[ strlen( text ) + 1 ] ;
		strcpy( m_pText, text ) ;
	} else {
		m_pText = 0 ;
	}
}

/*
 * 新しいマークと文字列をセットする
 */
void
DetailInfo::append( List *pList, char mark, LPCSTR text )
{
	DetailInfo	*cur ;
	Iterator	l( *pList ) ;

	while ( cur = (DetailInfo*) l() ) {
		if ( cur->is_mark( mark ) ) {
			cur->set( text ) ;
			return ;
		}
	}
	cur = new DetailInfo( mark ) ;
	cur->set( text ) ;
	pList->append( cur ) ;
}

/*
 * 指定されたマークを持つ内容情報を探す
 */
DetailInfo*
DetailInfo::find( List *pList, char mark )
{
	DetailInfo	*cur ;
	Iterator	l( *pList ) ;

	while ( cur = (DetailInfo*) l() ) {
		if ( cur->is_mark( mark ) ) {
			return cur ;
		}
	}
	return NULL ;
}

/*-------------------------------------------------------------------------*
 * MinInfo
 *-------------------------------------------------------------------------*/
/*
 * MinInfo のコンストラクタ
 */
MinInfo::MinInfo( HourInfo *parent, BYTE min, DWORD mask )
{
	m_pParent = parent ;
	m_bMinute = min ;
	m_cDetail = m_cExtra = 0 ;
	m_dDayMask = mask ;
}

/*
 * MinInfo のコンストラクタ
 */
MinInfo::MinInfo( MinInfo *base )
{
	m_pParent = base->m_pParent ;
	m_bMinute = base->m_bMinute ;
	m_cDetail = base->m_cDetail ;
	m_cExtra = base->m_cExtra ;
	m_dDayMask = base->m_dDayMask ;
}

/*
 * 分の比較を行う
 */
int
MinInfo::cmp( MinInfo *min ) const
{
	return (int) m_bMinute - (int) min->get_min() ;
}

/*
 * 新しい分情報を追加する
 */
void
MinInfo::append( List *pList, MinInfo *pMin )
{
	Iterator	l( *pList ) ;
	MinInfo		*cur, *last = 0 ;

	while ( cur = (MinInfo*) l() ) {
		if ( cur->cmp( pMin ) > 0 ) {
			pList->insert( pMin, last ) ;
			return ;
		}
		last = cur ;
	}
	/* なかった場合は最後に追加 */
	pList->append( pMin ) ;
}

/*
 * 表示文字列を作成する
 */
void
MinInfo::make_str_normal( char *ptr ) const
{
	BYTE		tmp ;
	DetailInfo	*detail ;

	tmp = get_hour() ;
	*ptr++ = (tmp / 10) + '0' ;
	*ptr++ = (tmp % 10) + '0' ;
	*ptr++ = ':' ;
	tmp = get_min() ;
	*ptr++ = (tmp / 10) + '0' ;
	*ptr++ = (tmp % 10) + '0' ;
	if ( !g_bNarrow ) {
		*ptr++ = ' ' ;
	}
	*ptr++ = ' ' ;
	detail = DetailInfo::find( m_pParent->get_detail(), m_cDetail ) ;
	if ( detail ) {
		strcpy( ptr, detail->get_text() ) ;
		ptr += strlen( ptr ) ;
	}
	detail = DetailInfo::find( m_pParent->get_detail(), m_cExtra ) ;
	if ( detail ) {
		strcpy( ptr, detail->get_text() ) ;
		ptr += strlen( ptr ) ;
	}
	*ptr = 0 ;
}

/*
 * 表示文字列を作成する
 */
void
MinInfo::make_str_on_now( char *ptr, WORD now ) const
{
	WORD		time, tmp ;
	BYTE		hour, min ;
	DetailInfo	*detail ;

	hour = get_hour() ;
	min = get_min() ;
	time = ((WORD) hour) * 60 + (WORD) min ;
	if ( g_bNarrow ) {
		*ptr++ = (hour / 10) + '0' ;
		*ptr++ = (hour % 10) + '0' ;
		*ptr++ = ':' ;
		*ptr++ = (min / 10) + '0' ;
		*ptr++ = (min % 10) + '0' ;
		*ptr++ = ' ' ;
		if ( time >= now && (time - now < 600) ) {
			time -= now ;
			if ( !time ) {
				strcpy( ptr, "発車 " ), ptr += 5 ;
			} else {
				if ( time < 60 ) {
					*ptr++ = ' ' ;
					*ptr++ = ' ' ;
				} else {
					tmp = time / 60 ;
					*ptr++ = (tmp % 10) + '0' ;
					*ptr++ = ':' ;
					time %= 60 ;
				}
				*ptr++ = (time / 10) + '0' ;
				*ptr++ = (time % 10) + '0' ;
				*ptr++ = ' ' ;
			}
		}
	} else {
		*ptr++ = (hour / 10) + '0' ;
		*ptr++ = (hour % 10) + '0' ;
		*ptr++ = ':' ;
		*ptr++ = (min / 10) + '0' ;
		*ptr++ = (min % 10) + '0' ;
		*ptr++ = ' ' ;
		*ptr++ = ' ' ;
		if ( time >= now && (time - now < 600) ) {
			time -= now ;
			if ( !time ) {
				strcpy( ptr, "発車です " ), ptr += 11 ;
			} else {
				if ( time < 60 ) {
					strcpy( ptr, "あと " ), ptr += 5 ;
				} else {
					*ptr++ = (time / 60) + '0' ;
					strcpy( ptr, "時間" ), ptr += 4 ;
					time %= 60 ;
				}
				*ptr++ = (time / 10) + '0' ;
				*ptr++ = (time % 10) + '0' ;
				strcpy( ptr, "分  " ), ptr += 4 ;
			}
		}
	}
	detail = DetailInfo::find( m_pParent->get_detail(), m_cDetail ) ;
	if ( detail ) {
		strcpy( ptr, detail->get_text() ) ;
		ptr += strlen( ptr ) ;
	}
	detail = DetailInfo::find( m_pParent->get_detail(), m_cExtra ) ;
	if ( detail ) {
		strcpy( ptr, detail->get_text() ) ;
		ptr += strlen( ptr ) ;
	}
	*ptr = 0 ;
}

/*
 * アラーム表示文字列を作成する
 */
void
MinInfo::make_str_on_alarm( char *ptr ) const
{
	DetailInfo	*detail ;
	BYTE		hour, min ;

	hour = get_hour() ;
	min = get_min() ;
	*ptr++ = '[' ;
	*ptr++ = (hour / 10) + '0' ;
	*ptr++ = (hour % 10) + '0' ;
	*ptr++ = ':' ;
	*ptr++ = (min / 10) + '0' ;
	*ptr++ = (min % 10) + '0' ;
	*ptr++ = ']' ;
	*ptr++ = ' ' ;
	detail = DetailInfo::find( m_pParent->get_detail(), m_cDetail ) ;
	if ( detail ) {
		strcpy( ptr, detail->get_text() ) ;
		ptr += strlen( ptr ) ;
	}
	detail = DetailInfo::find( m_pParent->get_detail(), m_cExtra ) ;
	if ( detail ) {
		strcpy( ptr, detail->get_text() ) ;
		ptr += strlen( ptr ) ;
	}
	*ptr = 0 ;
}

/*
 * 表示文字列を作成する
 */
void
MinInfo::make_str_for_message( char *ptr ) const
{
	DetailInfo	*detail ;

	detail = DetailInfo::find( m_pParent->get_detail(), m_cDetail ) ;
	if ( detail ) {
		strcpy( ptr, detail->get_text() ) ;
		ptr += strlen( ptr ) ;
	}
	detail = DetailInfo::find( m_pParent->get_detail(), m_cExtra ) ;
	if ( detail ) {
		strcpy( ptr, detail->get_text() ) ;
		ptr += strlen( ptr ) ;
	}
	*ptr = 0 ;
}

/*-------------------------------------------------------------------------*
 * HourInfo
 *-------------------------------------------------------------------------*/
/*
 * HourInfo のコンストラクタ
 */
HourInfo::HourInfo( TimeTableInfo *pTable, BYTE hour )
{
	m_pParent = pTable ;
	m_bHour = hour ;
}

List*
HourInfo::get_detail()
{
	return m_pParent->get_detail() ;
}

/*
 * 指定された時間と比較する
 */
int
HourInfo::cmp( BYTE hour ) const
{
	return (int) m_bHour - (int) hour ;
}

/*
 * 時間情報に分情報を追加する
 */
void
HourInfo::append( MinInfo *pMin )
{
	MinInfo::append( &m_oMin, pMin ) ;
}

/*
 * 指定された分以降の一覧を作成する
 */
void
HourInfo::pickup( List *pList, DWORD mask, BYTE start_min )
{
	BYTE		min ;
	MinInfo		*cur ;
	Iterator	l( m_oMin ) ;

	while ( cur = (MinInfo*) l() ) {
		min = cur->get_min() ;
		if ( min < start_min ) {
			continue ;
		} else if ( !(cur->get_mask() & mask) ) {
			continue ;
		}
		pList->append( new MinInfo( cur ) ) ;
	}
}

/*
 * 新しい時間を追加する
 */
HourInfo*
HourInfo::append( List *pList, TimeTableInfo *pTable, BYTE hour )
{
	Iterator	l( *pList ) ;
	HourInfo	*cur, *last = 0 ;

	while ( cur = (HourInfo*) l() ) {
		int		ret = cur->cmp( hour ) ;
		if ( ret == 0 ) {
			/* 等しい時間があった場合 */
			return cur ;
		} else if ( ret > 0 ) {
			/* より大きい時間になった場合 */
			cur = new HourInfo( pTable, hour ) ;
			pList->insert( cur, last ) ;
			return cur ;
		}
		last = cur ;
	}
	/* 該当する時間がなかった場合 */
	cur = new HourInfo( pTable, hour ) ;
	pList->insert( cur, last ) ;
	return cur ;
}

/*-------------------------------------------------------------------------*
 * TimeTableInfo
 *-------------------------------------------------------------------------*/
/*
 * TimeTableInfo のコンストラクタ
 */
TimeTableInfo::TimeTableInfo()
{
	*m_sTitle = 0 ;
	m_dNumMask = 0 ;
}

/*
 * NextTrain フォーマットでの曜日情報を取得する
 */
DWORD
TimeTableInfo::parse_day_nextfmt( LPSTR ptr ) const
{
	int			i ;
	DWORD		event ;
	char		c, *start ;

	event = 0 ;
	while ( (c = *ptr++) && c == '[' ) {
		start = ptr ;
		ptr = strchr( ptr, ']' ) ;
		if ( !ptr ) {
			break ;
		}
		*ptr++ = 0 ;
		for ( i = 0 ; i < Num_StrDayMask ; i ++ ) {
			if ( !strcmpi( start, StrDayMask[ i ] ) ) {
				break ;
			}
		}
		if ( i >= Num_StrDayMask ) {
			continue ;
		}
		event |= 0x01 << i ;
	}
	return event ;
}

/*
 * 日付マスクを追加する
 */
int
TimeTableInfo::add_mask( char c, DWORD newmask )
{
	for ( int i = 0 ; i < m_dNumMask ; i ++ ) {
		if ( m_cMark[ i ] == c ) {
			return i ;
		}
	}
	m_cMark[ m_dNumMask ] = c ;
	m_dMask[ m_dNumMask ] = newmask ;
	return m_dNumMask ++ ;
}

static	char
skip_white_spaces( LPSTR *_line )
{
	char	c, *line = *_line ;

	while ( (c = *line++) && (c == ' ' || c == '\t') ) {
	}
	(*_line) = line - 1 ;
	return c ;
}

/*
 * ファイルフォーマットを調べる
 */
BOOL
TimeTableInfo::check_format( LPSTR line )
{
	char	c ;

	while ( (c = *line++) && (c == ' ' || c == '\t') ) {
	}
	if ( !c ) {
		return TRUE ;
	} else if ( c == ';' ) {
		return TRUE ;
	} else if ( c == '#' ) {
		m_dFormat = FORMAT_DIA ;
		return TRUE ;
	}
	m_dFormat = FORMAT_NEXT ;
	return TRUE ;
}

/*
 * DiaTrain形式で行を解釈する
 */
BOOL
TimeTableInfo::read_diatrain( LPSTR line )
{
	int			index ;
	MinInfo		*pMin ;
	HourInfo	*pHour ;
	BYTE		hour, min ;
	char		c, *start, *ptr ;

	c = skip_white_spaces( &line ) ;
	if ( !c || c == ';' || c == '#' ) {
		return TRUE ;
	}
	if ( c == ':' || (isalpha( c ) && line[1] == ':') ) {
		char	detail ;

		/* 付加文字列の追加 */
		if ( c == ':' ) {
			line ++ ;
			detail = -- m_cLast ;
		} else {
			line += 2 ;
			detail = c ;
		}
		m_cCur = detail ;
		DetailInfo::append( &m_oDetail, m_cCur, line ) ;
		return TRUE ;
	} else if ( c == '=' || (c && line[1] == '=') ) {
		/* 時間帯文字列の定義 */
		if ( c == '=' ) {
			line ++ ;
			c = 0 ;
		} else {
			line += 2 ;
		}
		index = add_mask( c, MASK_ALL ) ;
		m_dMask[ index ] = parse_day_nextfmt( line ) ;
		return TRUE ;
	}
	while ( line ) {
		WORD	tmp ;
		char	extra = 0 ;

		index = 0 ;
		c = skip_white_spaces( &line ) ;
		/* 付加文字列を取得する */
		if ( !isdigit( c ) ) {
			extra = c ;
			c = *++ line ;
			if ( !isdigit( c ) ) {
				break ;
			}
		}
		start = line ;
		if ( line = strchr( line, ' ' ) ) {
			*line ++ = 0 ;
		}
		/* 日付情報を取得する */
		ptr = &start[ strlen( start ) - 1 ] ;
		c = *ptr ;
		if ( !isdigit( c ) ) {
			index = add_mask( c, MASK_ALL ) ;
			*ptr = 0 ;
		}
		/* 発車時刻を取得する */
		tmp = (WORD) atol( start ) ;
		hour = (BYTE) (tmp / 100) ;
		min = (BYTE) (tmp % 100) ;
		if ( hour > m_bMaxHour ) {
			m_bMaxHour = hour ;
		}
		/* 発車時刻の登録 */
		pHour = HourInfo::append( &m_oHour, this, hour ) ;
		pMin = new MinInfo( pHour, min, index ) ;
		pMin->set_detail( m_cCur ) ;
		pMin->set_extra( extra ) ;
		pHour->append( pMin ) ;
	}
	return TRUE ;
}

/*
 * DiaTrain形式の場合の日付マスク調整
 */
void
TimeTableInfo::adjust_diatrain()
{
	HourInfo	*hour ;
	Iterator	lh( m_oHour ) ;

	while ( hour = (HourInfo*) lh() ) {
		MinInfo		*min ;
		Iterator	lm( *hour->get_min() ) ;

		while ( min = (MinInfo*) lm() ) {
			DWORD	mask = min->get_mask() ;
			min->set_mask( m_dMask[ mask ] ) ;
		}
	}
}

/*
 * NEXT形式で行を解釈する
 */
BOOL
TimeTableInfo::read_nextfmt( LPSTR line )
{
	DWORD		mask ;
	MinInfo		*pMin ;
	HourInfo	*pHour ;
	BYTE		hour, min ;
	char		*ptr, c, *start, detail, extra, *ptr2 ;

	c = *line ;
	if ( !c || c == ';' || c == '$' ) {
		/* 次の行を読み込む */
		return TRUE ;
	} else if ( c == '[' ) {
		mask = parse_day_nextfmt( line ) ;
		mask &= m_dDefMask ;
		m_dDefMask &= ~mask ;
		if ( mask ) {
			m_dMask[ m_dNumMask ++ ] = mask ;
			m_dCurMask = mask ;
		}
		m_bLastHour = 0 ;
		return TRUE ;
	} else if ( c == ':' || (isalpha( c ) && line[1] == ':') ) {
		/* 付加文字列の追加 */
		if ( c == ':' ) {
			line ++ ;
			c = -1 ;
		} else {
			line += 2 ;
		}
		DetailInfo::append( &m_oDetail, c, line ) ;
		return TRUE ;
	} else if ( c == '=' || (c && line[1] == '=') ) {
		/* 時間帯文字列の定義 */
		if ( c == '=' ) {
			line ++ ;
			c = 0 ;
		} else {
			line += 2 ;
		}
		DWORD	index = add_mask( c, MASK_ALL ) ;
		m_dMask[ index ] = parse_day_nextfmt( line ) ;
		return TRUE ;
	}
	ptr = strchr( line, ':' ) ;
	if ( !ptr ) {
		/* ':'がない場合 */
		return TRUE ;
	}
	*ptr++ = 0 ;
	/* 時間を取り出す */
	hour = (BYTE) atol( line ) ;
	if ( hour < m_bLastHour ) {
		hour += 24 ;
	} else {
		m_bLastHour = hour ;
	}
	if ( hour > m_bMaxHour ) {
		m_bMaxHour = hour ;
	}
	while ( ptr ) {
		DWORD	index = m_dCurMask ;

		/* 分の先頭に移動する */
		while ( (c = *ptr) && (c == ' ') ) {
			ptr ++ ;
		}
		if ( !*ptr ) {
			/* 時間の後に何もない場合 */
			break ;
		}
		start = ptr ;
		ptr = strchr( start, ' ' ) ;
		if ( ptr ) {
			*ptr++ = 0 ;
		}
		/* 付加文字列を取得する */
		detail = extra = 0 ;
		if ( isalpha( *start ) ) {
			detail = *start++ ;
			if ( isalpha( *start ) ) {
				extra = *start++ ;
			}
		}
		if ( !detail ) {
			detail = -1 ;
		}
		/* 日付情報を取得する */
		ptr2 = &start[ strlen( start ) - 1 ] ;
		c = *ptr2 ;
		if ( !isdigit( c ) ) {
			index = MASK_INDEX | add_mask( c, MASK_ALL ) ;
			*ptr2 = 0 ;
		}
		/* 発車時刻を取得する */
		min = (BYTE) atol( start ) ;
		/* 発車時刻の登録 */
		pHour = HourInfo::append( &m_oHour, this, hour ) ;
		pMin = new MinInfo( pHour, min, index ) ;
		pMin->set_detail( detail ) ;
		pMin->set_extra( extra ) ;
		pHour->append( pMin ) ;
	}
	return TRUE ;
}

/*
 * NEXT形式の場合の日付マスク調整
 */
void
TimeTableInfo::adjust_nextfmt()
{
	HourInfo	*hour ;
	Iterator	lh( m_oHour ) ;

	/* デフォルト日付マスクを作成する */
	if ( !m_dMask[ 0 ] ) {
		m_dMask[ 0 ] = m_dDefMask ;
	}
	while ( hour = (HourInfo*) lh() ) {
		MinInfo		*min ;
		Iterator	lm( *hour->get_min() ) ;

		while ( min = (MinInfo*) lm() ) {
			DWORD	mask = min->get_mask() ;
			if ( is_index( mask ) ) {
				mask = get_index( mask ) ;
				min->set_mask( m_dMask[ mask ] ) ;
			}
		}
	}
}

/*
 * ファイルからNEXT形式の時刻表データを読み込む
 */
BOOL
TimeTableInfo::read( LPCTSTR fn )
{
	BOOL		ret ;
	FILE		*fp ;
	char		line[ 256 ], *ptr ;

	m_bLastHour = 0 ;
	m_dFormat = FORMAT_NONE ;
	m_cLast = -1 ;
	m_cCur = m_cLast ;
	DetailInfo::append( &m_oDetail, m_cLast, "" ) ;
	m_dCurMask = MASK_INDEX ;
	m_dDefMask = MASK_ALL ;
	m_oHour.clear() ;
	m_oDetail.clear() ;
	fp = fopenW( fn, TEXT("r") ) ;
	if ( fp == NULL ) {
		return FALSE ;
	}
	m_bMaxHour = 0 ;
	m_dNumMask = 0 ;
	m_cMark[ m_dNumMask ] = 0 ;
	m_dMask[ m_dNumMask ++ ] = 0 ;
	while ( fgets( line, sizeof line - 1, fp ) ) {
		line[ sizeof line - 1 ] = 0 ;
		if ( ptr = strchr( line, '\r' ) ) {
			*ptr = 0 ;
		}
		if ( ptr = strchr( line, '\n' ) ) {
			*ptr = 0 ;
		}
		if ( m_dFormat == FORMAT_NONE && !check_format( line ) ) {
			break ;
		}
		switch ( m_dFormat ) {
		case FORMAT_DIA:	ret = read_diatrain( line ) ;	break ;
		case FORMAT_NEXT:	ret = read_nextfmt( line ) ;	break ;
		default:			ret = TRUE ;					break ;
		}
		if ( !ret ) {
			break ;
		}
	}
	switch ( m_dFormat ) {
	case FORMAT_DIA:	adjust_diatrain() ;	break ;
	case FORMAT_NEXT:	adjust_nextfmt() ;	break ;
	}
	fclose( fp ) ;
	return TRUE ;
}

/*
 * 現在時間を求める(必要ならば24を加える)
 */
BYTE
TimeTableInfo::get_hour( BYTE hour ) const
{
	if ( m_bMaxHour >= 24 & hour <= m_bMaxHour - 24 ) {
		hour += 24 ;
	}
	return hour ;
}

/*
 * 指定された時間の一覧を作成する
 * hour==0xFFで現在時刻以降
 * hour==0xFEで本日分全部
 */
int
TimeTableInfo::pickup( List *list, WORD base, BYTE hour )
{
	SYSTEMTIME	st ;
	DWORD		mask ;
	HourInfo	*cur ;
	BYTE		hour1, min ;
	Iterator	l( m_oHour ) ;

	GetLocalTime( &st ) ;
	mask = 0x01 << st.wDayOfWeek ;
	list->clear() ;
	if ( hour == HOUR_NOW || hour == HOUR_ALL ) {
		if ( hour == HOUR_NOW ) {
			/* 現在時刻を元に抽出する */
			hour = get_hour( (BYTE) (base / 60) ) ;
			min = (BYTE) (base % 60) ;
		} else {
			/* 本日分をすべて抽出 */
			hour = min = 0 ;
		}
		while ( cur = (HourInfo*) l() ) {
			hour1 = cur->get_hour() ;
			if ( hour1 == hour ) {
				cur->pickup( list, mask, min ) ;
			} else if ( hour1 > hour ) {
				cur->pickup( list, mask, 0 ) ;
			}
		}
	} else {
		while ( cur = (HourInfo*) l() ) {
			hour1 = cur->get_hour() ;
			if ( hour1 == hour ) {
				cur->pickup( list, mask, 0 ) ;
			} else if ( hour1 > hour ) {
				break ;
			}
		}
	}
	return list->count() ;
}

/*
 * 現在時刻までの一覧内容を削除する
 */
int
TimeTableInfo::delete_until_now( List *list, WORD base )
{
	SYSTEMTIME	st ;
	MinInfo		*cur ;
	int			i, count = 0 ;
	BYTE		hour, hour1, min ;
	Iterator	l( *list ) ;

	GetLocalTime( &st ) ;
	hour = get_hour( (BYTE) (base / 60) ) ;
	min = (BYTE) (base % 60) ;
	while ( cur = (MinInfo*) l() ) {
		hour1 = cur->get_hour() ;
		if ( hour1 < hour || (hour1 == hour && cur->get_min() < min) ) {
			count ++ ;
		} else if ( hour1 > hour ) {
			break ;
		}
	}
	for ( i = 0 ; i < count ; i ++ ) {
		list->delete_first() ;
	}
	return count ;
}

/*-------------------------------------------------------------------------*
 * FileTableInfo
 *-------------------------------------------------------------------------*/
List	FileTableInfo::FileList ;

/*
 * FileTableInfo のコンストラクタ
 */
FileTableInfo::FileTableInfo( LPCTSTR path, LPCSTR text )
{
	wcscpy( m_sPath, path ) ;
	strcpy( m_sText, text ) ;
}

/*
 * ファイルリストを読み込む
 */
BOOL
FileTableInfo::read_nextfmt( LPCTSTR fn )
{
	FILE		*fp ;
	TCHAR		pathstr[ MAX_PATH ] ;
	char		line[ 256 ], *ptr, *path, *detail, c ;

	FileList.clear() ;
	/* 定義ファイルを読み込む */
	fp = fopenW( fn, TEXT("r") ) ;
	if ( fp == NULL ) {
		return FALSE ;
	}
	while ( fgets( line, sizeof line - 1, fp ) ) {
		line[ sizeof line - 1 ] = 0 ;
		ptr = strchr( line, '\r' ) ;
		if ( ptr ) {
			*ptr = 0 ;
		}
		ptr = strchr( line, '\n' ) ;
		if ( ptr ) {
			*ptr = 0 ;
		}
		c = *line ;
		if ( !c || c == ';' ) {
			/* 次の行を読み込む */
			continue ;
		} else if ( c == '[' ) {
			break ;
		}
		path = line ;
		while ( (c = *path++) && (c == ' ' || c == '\t') ) {
		}
		if ( !c ) {
			continue ;
		}
		if ( detail = strchr( -- path, ';' ) ) {
			*detail++ = 0 ;
		} else {
			detail = "" ;
		}
		if ( ptr = strchr( path, ' ' ) ) {
			*ptr = 0 ;
		}
		if ( ptr = strchr( path, '\t' ) ) {
			*ptr = 0 ;
		}
		sjis2unicode( (LPBYTE) path, pathstr, sizeof pathstr ) ;
		FileList.append( new FileTableInfo( pathstr, detail ) ) ;
	}
	fclose( fp ) ;
	return FileList.count() ? TRUE : FALSE ;
}

int
FileTableInfo::list_proc( int index, const BYTE **ptr, int *len )
{
	if ( index < 0 ) {
		return FileList.count() ;
	} else if ( index >= (int) FileList.count() ) {
		return -1 ;
	}
	Iterator		l( FileList, index ) ;
	FileTableInfo	*cur = (FileTableInfo*) l() ;
	*ptr = (LPBYTE) cur->get_detail() ;
	*len = strlen( (LPSTR) *ptr ) ;
	return 0 ;
}

LPCTSTR
FileTableInfo::get_path( int index )
{
	Iterator		l( FileList, index ) ;
	FileTableInfo	*cur = (FileTableInfo*) l() ;
	return cur ? cur->get_path() : TEXT("") ;
}

LPCSTR
FileTableInfo::get_detail( int index )
{
	Iterator		l( FileList, index ) ;
	FileTableInfo	*cur = (FileTableInfo*) l() ;
	return cur ? cur->get_detail() : "" ;
}
