//
//  BasicSelectWithTable2.m
//  X-BASIC'
//
//  Created by AIG-Soft(iMac) on 2015/08/21.
//  Copyright (c) 2015年 AIG-Soft. All rights reserved.
//

#import "BasicSelectWithTable2.h"
#import "FileControl2.h"
#import "Setup.h"	// PATH_NEWFILE,SOURCE_SELECT_*
#import "libs.h"
#import "click.h"
#include <stdio.h>
#include "code2code.h"
#include "support.h"
#import "AppDelegate.h"
#import "UIView+waku.h"

@interface BasicSelectWithTable2 ()
<UIAlertViewDelegate>
{
	NSInteger		fselectSources;
	
	id 				retTarget;
	SEL 			retAction;
	SEL				cancelSelector;
	NSString		*basicPath;
	//
	NSIndexPath		*selectIndex;
	// 元
	NSMutableArray	*basFiles;		// 全BASICファイル名
	NSUInteger		cntInternal;	// 内蔵ファイル数
	NSUInteger		cntExternal;	// ユーザーファイル数
	// インデックス用
	NSArray 		*indexList;
	NSMutableArray	*basFilesWithSection;		// [selection][n]=@[そのsectionに入るファイル名群]
}
@end

#define CELL @"CELL"

// basFilesの辞書キー名
#define KEY_FNAME		@"FNAME"
#define KEY_PATH		@"PATH"
#define KEY_FINTERNAL	@"FINTERNAL"

enum { // FINTERNAL値 ; 表示上、小さいほど優先
	FILE_NEW=0,		// 新規作成
	FILE_EXTERNAL,	// ユーザー作成分
	FILE_INTERNAL,	// 内蔵
};

@implementation BasicSelectWithTable2

//-------------------------------------------------------------------

#pragma mark 初期化

-(void)setDeleteButtons
{
	UIBarButtonItem *btn=[[UIBarButtonItem alloc]
//						  initWithTitle:NSLocalStr(@"DELETE")
						  initWithImage:[UIImage imageNamed:@"Trush"]	// v3.20
						  style:UIBarButtonItemStylePlain target:self action:@selector(deleteMode:)];
	btn.tintColor=[UIColor redColor];
	self.navigationItem.leftBarButtonItem=btn;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

	self.title	  =NSLocalStr(@"BASICFILES");
	lblSelect.text=NSLocalStr(@"BASICSELECT");
	// ローカライズするため、xibで仮設定しているものをすべて削除して再設定
	[self.segSelect removeAllSegments];
	[self.segSelect insertSegmentWithTitle:NSLocalStr(@"BASICSELECT_BOTH") 		atIndex:SOURCE_SELECT_BOTH 		animated:NO];
	[self.segSelect insertSegmentWithTitle:NSLocalStr(@"BASICSELECT_EXTERNAL") 	atIndex:SOURCE_SELECT_EXTERNAL 	animated:NO];
	[self.segSelect insertSegmentWithTitle:NSLocalStr(@"BASICSELECT_INTERNAL") 	atIndex:SOURCE_SELECT_INTERNAL 	animated:NO];

	AppDelegate	*app=getAppDelegate();
	Setup *setup=app.setup;
	fselectSources=
	self.segSelect.selectedSegmentIndex=setup.fselectSources;
	
	// 表示サイズ調整 v3.20
	CGRect frame1=vwSelectView.frame; // 固定サイズ
	CGRect frame2=self.tableView.frame;
	frame2.size.height=self.view.frame.size.height-frame1.size.height;
	self.tableView.frame=frame2;
	[vwSelectView 	 setWaku:[UIColor colorWithRed:153.0/255.0 green:153.0/255.0 blue:153.0/255.0 alpha:1.0] width:1.0];

	
	// Naviにボタン追加
	UIBarButtonItem *btn=[[UIBarButtonItem alloc]
//						initWithTitle:NSLocalStr(@"CANCEL")
						initWithImage:[UIImage imageNamed:@"RunClose"]	// v3.20
						style:UIBarButtonItemStylePlain target:retTarget action:cancelSelector];
	self.navigationItem.rightBarButtonItem=btn;
	[self setDeleteButtons];

    // セルの登録
	[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CELL];
	
	// インデックス名
	// 先頭を新規作成、最後をその他にしておくこと
	indexList=@[NSLocalStr(@"NEW"),@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z",NSLocalStr(@"ETC")];

	// インデックスの背景を透明にする;インデックスありで編集した時に隠れてしまうのを回避するため
	self.tableView.sectionIndexBackgroundColor = [UIColor clearColor];
	[UITableViewCell appearance].separatorInset = UIEdgeInsetsZero;
	
	// 全ファイル数を表示するため
	[self setInternalBasicSource];
	[self setExternalBasicSource];
	
	// 指定BASICソースリストを得て表示する
	[self makeBasicSourceList];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)dealloc
{
	printSelf();
	_fclosePopover=NO;
}

//-------------------------------------------------------------------

/// 初期設定
/// viewDidLoad前に呼び出されることもあるので注意
-(void)open:(id)retTarget_ retSelector:(SEL)retSelector_ basicPath:(NSString *)basicPath_ calcelSelector:(SEL)cancelSelector_
{
	printSelf();
	
    retTarget      = retTarget_;
    retAction      = retSelector_;
    cancelSelector = cancelSelector_;
	//
#ifdef DEBUG
	nslog(@"basicPath=%p",basicPath_);
	if ([basicPath_ isEqualToString:PATH_NEWFILE]) {
		nslog(@"new_file");
	}
	nslog(@"basicPath=%@",basicPath);
#endif
	basicPath=basicPath_;
}

//-------------------------------------------------------------------

/// 編集モード設定
-(void)deleteMode:(id)sender
{
	printSelf();
	self.tableView.editing=!self.tableView.editing;
	// 編集モード時はインデックス表示を消すため
    [self.tableView reloadSectionIndexTitles];
}

#pragma mark - Table view data source

/// セクション数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [indexList count];
}

/// 指定セクション内の項目数を返す
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
	NSArray *files=basFilesWithSection[section];
    return [files count];
}

/// セルを作成する
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CELL forIndexPath:indexPath];
	UIColor *color=[UIColor blackColor];
	NSDictionary *fname=basFilesWithSection[indexPath.section][indexPath.row];
	switch ([fname[KEY_FINTERNAL] integerValue]) {
		case FILE_NEW:
			// 新規作成は削除できない
			color=[UIColor redColor];
			break;
		case FILE_INTERNAL:
			// 内蔵は削除できない
			color=[UIColor blueColor];
			break;
		default:
			break;
	}
	UILabel *lbl=cell.textLabel;
	lbl.textColor=color;
	lbl.text=fname[KEY_FNAME];
#if 0	// iOS7以降では無効になってしまう
	cell.backgroundColor=[UIColor clearColor];
#else
	UIView *bgColorView = [[UIView alloc] init];
	bgColorView.backgroundColor = [UIColor colorWithRed:(76.0/255.0) green:(161.0/255.0) blue:(255.0/255.0) alpha:0.5]; // perfect color suggested by @mohamadHafez
	bgColorView.layer.masksToBounds = YES;
	cell.selectedBackgroundView = bgColorView;
#endif
    return cell;
}

/// セクション名を返す
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
	if ([basFilesWithSection[section] count]==0) return nil; // 内容のないセクションは表示しない
	return indexList[section];
}

/// 指定文字列に相当するインデックス名を返す
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
	return [indexList indexOfObject:title];
}

/// インデックスを返す
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
	printSelf();
    if (tableView.editing) {
		// 編集中は表示しない
        return nil;
    }
	return indexList;
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/

/// 指定セルが選択可能かどうか調べる
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
	NSDictionary *fname=basFilesWithSection[indexPath.section][indexPath.row];
	if (![fname[KEY_FINTERNAL] isEqualToValue:@(FILE_EXTERNAL)]) {
		// 新規作成/内蔵は削除できない
		return NO;
	}
    return YES;
}


// 編集モード時にセルの左側に表示するマークを設定する
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
	if (tableView.editing) {
		// 今回は削除ボタンのみ
        return UITableViewCellEditingStyleDelete;
    }
	// スワイプによる削除は禁止する
    return UITableViewCellEditingStyleNone;
}

// 削除処理(個別のみ;fediting=NO)
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
	printSelf();
    switch (editingStyle) {
        case UITableViewCellEditingStyleDelete:
			selectIndex=indexPath;
			// 実削除
			[self deleteBasicFile];
            break;
        default:
        case UITableViewCellEditingStyleInsert:
            // 挿入処理はなし
            break;
    }
}

// 削除ボタンの名称を変更
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return NSLocalStr(@"DELETE");
}

#pragma mark - Table view delegate

/// セルが選択された
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
	printSelf();
	selectIndex=indexPath;
	NSDictionary *fname=basFilesWithSection[indexPath.section][indexPath.row];
	nslog(@"file=%@",fname[KEY_FNAME]);
	// デリゲートにフルパスを渡して起動
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"        // 警告回避のため
	[retTarget performSelector:retAction withObject:fname[KEY_PATH]];
#pragma clang diagnostic pop
}

//-------------------------------------------------------------------

// ソースファイル削除
-(void)deleteBasicFile
{
	printFunc();
//	nslog(@"selectIndex=%@",selectIndex);
	//
	NSDictionary *fname=basFilesWithSection[selectIndex.section][selectIndex.row];
//	nslog(@"削除fname=%@",fname);
	
	if (![fname[KEY_FINTERNAL] isEqualToValue:@(FILE_EXTERNAL)]) {
		// 新規作成/内蔵は削除できない
		// tableView側で選択不可にしているから来ないはずだけど念のため
		Alert1(@"DELETE_CHECK", [NSString stringWithFormat:NSLocalStr(@"CANTDELETE_MESSAGE"),fname[KEY_FNAME]], nil);
		return;
	}
	//
//	if ([fname[KEY_FNAME]isEqualToString:self.nowFile]) { // ファイル名のみの比較だと、内蔵とユーザーで同名ファイルがあるときに削除できないので v3.20
	if ([fname[KEY_PATH] isEqualToString:self.nowPath]) {
		// 編集中のファイルを削除するのは禁止(再起動時にファイルがないことになるので)
		Alert1(@"DELETE_CHECK", [NSString stringWithFormat:NSLocalStr(@"CANTDELETE2_MESSAGE"),fname[KEY_FNAME]], nil);
		return;
	}

	// 先に実ファイル削除
	fileDelete(fname[KEY_PATH]); // 削除はフルパス名で行う
	//
	// 全BASICソースリストを得る
	[self makeBasicFileList];

	// 表示上の削除
	// 与えているのは削除対象セル番号のindexPathの配列(一括削除が可能だからだけど、ここでは1つのみ)
	[self.tableView deleteRowsAtIndexPaths:@[selectIndex] withRowAnimation:UITableViewRowAnimationFade];
}

//-------------------------------------------------------------------

// 行数を数える
static
uwLineNO getSourceLines(UByte *source,int size)
{
	printFuncs(@"size=%d",size);
	uwLineNO lines=0;
	UByte c;
	while (size-->0) {
		c=*source;
		switch (c) {
			case CR:
				if (*(source+1)==LF) {
					source++; // CR,LFならLFも飛ばす
					size--;
				}
			case LF:
				lines++; // 行数+1
			default:
				source++;
				break;
		}
	} // while
	// プログラム終端まで来た
	nslog(@"行数=%d",lines);
	return (lines);
}

static
void freeSource(void)
{
	if (sourceTop!=NULL) {
		nslog(@"前のソース用ワークを解放");
		// ソースはmalloc()で確保しているのでfree2()にしない
		free(sourceTop);
	}
}

// ソースコード読みだし
// nsBasicFile : フルパス名
NSInteger readBasicFile(NSString *nsBasicFile,ULong *startupSize0,uwLineNO *startLines0)
{
	printFuncs(@"%@",nsBasicFile);
	
	char *basicFile;
	
	// startup対応
	FILE *startupFp;
	int startupSize=0; // なかった時のため
	*startLines0=0;
	if (![[nsBasicFile lastPathComponent]isEqualToString:STARTUP]) {
		NSString *startup=getResourceOrSavedataPath(STARTUP); // 外部 → 内蔵の優先順位
		if (startup==nil) {
			// startupがない
			nslog(@"startupがない:%@",startup);
			// なかったら読み込まないだけでエラーにはしない
		} else {
			nslog(@"スタートアップファイル=%@",startup);
			basicFile=nsStringTocString(startup); // NSStringからUTF8でCの文字列を生成する
			startupFp=fopen(basicFile,"r");
			if (startupFp!=NULL) {
				// startupはUTF8固定
				// コード変換しないのでファイルサイズそのままで読めば良い
				startupSize=(int)filelength(startupFp);
				nslog(@"stratupファイルサイズ=%d",startupSize);
				// startupSize=0もあり得る
				if (startupSize==0) {
					fclose(startupFp);
				}
			} else { // startupFp==NULL
				nslog(@"file can not open (startup)");
				// startupは上で検索されているので、通常読めないはずはないが念のため
				// starupSize=0になってる
			}
		}
	} // startup.basそのものを読み込もうとしているときはその前への読み込みはなし
	
#if 0	// デバッグ処理
	// リソースないならリソースへ、ユーザー領域ならそれへ
	nslog(@"basicFile=%s",basicFile);
	nslog(@"DocumentPath=%@",getDocumentsPath());
	nslog(@"ResourcePath=%@",getResourcePath());
	nsBasicFile=autoReplaceDocumentOrResourceDirectory(nsBasicFile);
	nslog(@"newPath=%@",nsBasicFile);
#endif
	// ユーザー指定ファイルチェック
	basicFile=nsStringTocString(nsBasicFile); // NSStringからUTF8でCの文字列を生成する
	
	FILE *fp=fopen(basicFile,"r");
	if (fp==NULL) {
		if (startupSize>0) fclose(startupFp);
		nslog(@"file can not open");
		return(RET_readBasicFile_file_not_found);
	}
	
	// ソースの形式を認識する v3.00
	int fLineNo;
	CODETYPE cType=checkFileSjisUtf8(fp,&fLineNo); // fpは巻き戻される
	nslog(@"ユーザーファイル形式(cType):%d/行番号=%d",cType,fLineNo);

	// v3.00
	nslog(@"operationStatus.fsjisInSetup=%d",operationStatus.fsjisInSetup);
	switch (operationStatus.fsjisInSetup) {
		case FSJIS_YES:
			nslog(@"強制SJISモード:");
			operationStatus.fsjis=YES;
			break;
		case FSJIS_AUTO:
			nslog(@"自動強制SJISモード:cType=%d",cType);
			operationStatus.fsjis=(cType==FILE_SJIS); // ファイルもSJISだったらYES
			break;
		case FSJIS_NO:
			nslog(@"通常モード:");
			operationStatus.fsjis=NO;
			break;
	}
	
	// ソース中のTABの数を数える
	int tabs=countTabsInFile(fp);
	tabs*=(TABWIDTH-1);
	// TABは桁位置によって変換されるスペース数が異なるが、ワーク確保上は、すべてTABWIDTHに変換されると仮定する
	// 元々TAB分1バイトは計上されているので、−1バイトしておけば良い
	
	// ソース用ワーク(スタートアップを含む)
	// SJIS→UTF8では最大でソースコードは1.5倍になる
	// ASCIIコードは同じ、半角カタカナはと2バイトコードは3バイト(サポート範囲)になる可能性がある
	// なので、とりあえず倍のサイズを確保しておく
	int size=(int)filelength(fp);
	nslog(@"ユーザーファイルサイズ=%d+TAB変換サイズ=%d",size,tabs);
	if (cType==FILE_SJIS) size*=2; // UTF8へのコード変換を伴うときは余裕を持ってワークを確保しておく(後で調整)
	size+=tabs; // それにTABの変換分を入れておく
	
	freeSource(); // 前のソース用ワークを解放
	// ↓ここはfreeAll()の対象外にするためmalloc2()にしない
	sourceTop=malloc(startupSize+size+2); // EOS+偶数境界用
	if (sourceTop==NULL) {
		// メモリー不足
		nslog(@"メモリー不足(1):size=%d",startupSize+size+2);
		if (startupSize>0) fclose(startupFp);
		fclose(fp);
		return (RET_readBasicFile_memory_error);
	}
	
	UByte *source=sourceTop;
	if (startupSize>0) {
		// startup読み込み
		// コード変換なしなので、そのまま
		// この中は表示されないのでTAB変換もしない
		nslog(@"スタートアップ読み込み");
		fread(source,startupSize,1,startupFp);
		//
		// 行数を数える
		*startLines0=getSourceLines(source,startupSize);
		//
		source+=startupSize;
		if (*(source-1)==EOT) {
			source--; // EOTで終わっているときはそれを消す
			startupSize--;
		}
		if ((ULong)source&1) {
			*source++=' '; // 偶数境界化
			startupSize++;
		}
		fclose(startupFp);
	}
	nslog(@"sourceTop=%p.source=%p,startupSize=%d",sourceTop,source,startupSize);
	
	nslog(@"ユーザーソースファイル読み込み with コード変換など");
	// 結局のところコード変換が必要なのは、強制SHIFT-JISモードでないときのcType=FILE_SJIS時のみ
	if (operationStatus.fsjis) {
		nslog(@"強制SJISモード");
		if (cType==FILE_SJIS) {
			// ファイルもSJISだった
			nslog(@"続行");
		} else {
			// ファイルはUTF8/ASCIIだった
			operationStatus.fsjis=NO; // 他の文字コードの時は強制SHIFT-JISモード解除
			// ファイルは無変換
			nslog(@"解除");
		}
		cType=FILE_ASCII;	// ファイルはいずれにせよ無変換
	} else {
		nslog(@"通常モード");
		if (cType==FILE_UTF8) cType=FILE_ASCII;	// UTF8は無変換にする(SJISはUTF8変換)
	}
	// 改行コードはLF１つのみにする(V2.8)
	UByte *bp=loadSourceFileWithCodeConvert(fp,cType,source,fLineNo,LF);
	fclose(fp);
	
	if (cType==FILE_SJIS) {
		// 必要サイズで確保し直し
		size=startupSize+(int)(bp-source)+2; // EOS+偶数境界用
		nslog(@"読み込み後サイズ=%d",size);
		sourceTop=realloc(sourceTop,size+2);
		if (sourceTop==NULL) { // 減らす方向だからエラーは出ないと思うけど念のため
			// メモリー不足
			nslog(@"メモリー不足(2):size=%d",size);
			return (RET_readBasicFile_memory_error);
		}
	}
//	nslog(@"sourceTop=%s",sourceTop);
	
	sourceEnd=sourceTop+startupSize+size;
	*sourceEnd++=EOS;
	if ((ULong)sourceEnd&1) *sourceEnd++=EOS; // 偶数アドレス化
	*startupSize0=startupSize;
	
	nslog(@"source=%p～%p(size=%d+%d)",sourceTop,sourceEnd,startupSize,size);
	// リターン値
	return(RET_readBasicFile_OK); // OK
}

//-------------------------------------------------------------------

// 内蔵BASICソース一覧取得
-(NSUInteger)setInternalBasicSource
{
	printSelfs(@"dir=%@",DIR_SYSTEM);
	
	// ファイル名(*.bas)
	NSArray *fileListInternal=[[NSBundle mainBundle]pathsForResourcesOfType:EXT_BASIC inDirectory:DIR_SYSTEM]; // 本体内部はこれ
//	NSArray *fileListInternal=files(DIR_SYSTEM,EXT_BASIC,YES,FILES_FILE,NO);
	nslog(@"fileListInternal=%@",fileListInternal);
	//
	cntInternal=0;
	NSEnumerator *emu=[fileListInternal objectEnumerator];
	NSString *path;
	while (path=[emu nextObject]) {
		NSString *fname=[path lastPathComponent];
		nslog(@"fname=%@",fname);
		switch ([fname characterAtIndex:0]) {
			default:
				[basFiles  addObject:@{KEY_FNAME:fname,
									   KEY_PATH:path,
									   KEY_FINTERNAL:@(FILE_INTERNAL)}
				 ];
				cntInternal++;
				break;
#if COMPILE_MODE==2 // Distributionの時は外す
			case '!':// 先頭が'!'で始まるファイルは、Distribution時は飛ばす
//				nslog(@"スキップ対象ファイル名:%@",fname);
#endif
			case '.':// 隠しファイルはスキップする
				break;
		}
	}
	nslog(@"basFiles(%d)=%@",(int)cntExternal,basFiles);
	lblCntInternal.text=[NSString stringWithFormat:@"%tu",cntInternal];
	lblCntAll.text     =[NSString stringWithFormat:@"%tu",cntExternal+cntInternal];
	return cntInternal;
}

// iTunes経由BASICソース一覧取得
// こちらが優先
-(NSUInteger)setExternalBasicSource
{
	printFuncs(@"dir=%@",DIR_DOCUMENTS);
	
	// ファイル名(*.bas)
//	NSArray *fileListExternal=[[NSBundle mainBundle]pathsForResourcesOfType:EXT_BASIC inDirectory:DIR_DOCUMENTS]; // iTunes経由はこれ・・・ではだめで↓これ
	NSArray *fileListExternal=files(DIR_DOCUMENTS,EXT_BASIC,YES,FILES_FILE,NO); // ファイルのみ
	nslog(@"fileListExternal=%@",fileListExternal);
	NSEnumerator *emu=[fileListExternal objectEnumerator];
	NSString *path;
	cntExternal=0;
	while (path=[emu nextObject]) {
		// 同一パス内に同一ファイル名は存在しないから排除処理なし
		NSString *fname=[path lastPathComponent];
		//nslog(@"path=%@ / %@",path,fname);
		if ([fname characterAtIndex:0]!='.') {
			[basFiles  addObject:@{KEY_FNAME:fname,
								   KEY_PATH:path,
								   KEY_FINTERNAL:@(FILE_EXTERNAL)}
			 ];
			cntExternal++;
		} // 隠しファイルはスキップする
	}
	lblCntExternal.text=[NSString stringWithFormat:@"%tu",cntExternal];
	lblCntAll.text     =[NSString stringWithFormat:@"%tu",cntExternal+cntInternal];
	nslog(@"basFiles(%d)=%@",(int)cntExternal,basFiles);
	return cntExternal;
}

//-------------------------------------------------------------------

// 全BASICソースリストを得る
// ユーザーと内蔵で同じファイル名のものがあるときは、並べて表示される
-(void)makeBasicFileList
{
	printSelf();
	if (basFiles!=nil) {
		// 前のを開放
		basFiles=nil;
		basFilesWithSection=nil;
	}
	basFiles =[[NSMutableArray alloc]init];
	
	// [0]に新規作成を入れる
	[basFiles  addObject:@{KEY_FNAME:NSLocalStr(@"NEW"), // Create a new / 新規作成
						   KEY_PATH:PATH_NEWFILE,
						   KEY_FINTERNAL:@(FILE_NEW)}
	 ];
	switch (fselectSources) {
		case SOURCE_SELECT_EXTERNAL:
			[self setExternalBasicSource]; // iTunes経由(優先)
			break;
		case SOURCE_SELECT_BOTH:
			[self setExternalBasicSource]; // iTunes経由(優先)
		case SOURCE_SELECT_INTERNAL:
			[self setInternalBasicSource]; // 内蔵
			break;
	}
	
	// basFilesをindexList別に分けてbasFilesWithSectionに格納する
	basFilesWithSection=[[NSMutableArray alloc]init];
	// まず配置状態とファイル名でソートしておく
	// 多分basFilesでもソート済みのハズだけの念のため（少なくとも配置はソート済み）
	NSArray *sortedBasFiles=[basFiles sortedArrayUsingFunction:fnameSort context:NULL];
	nslog(@"sorted basFiles=%@",sortedBasFiles);
	// まず空の要素で初期化しておく
	for (NSInteger i=0;i<[indexList count];i++) {
		[basFilesWithSection addObject:[[NSMutableArray alloc]initWithCapacity:0]];
	}
	// 分類
	for (NSDictionary *fname in sortedBasFiles) {
		nslog(@"fname=%@",fname);
		switch ([fname[KEY_FINTERNAL]intValue]) {
			case FILE_NEW:
				[basFilesWithSection[0] addObject:fname];
				break;
			case FILE_INTERNAL:
			case FILE_EXTERNAL:
			{
				NSInteger n;
				for (n=1;n<[indexList count]-1;n++) { // 新規作成とその他は除く
					NSString *idxStr=indexList[n];
					NSString *subName=[(NSString *)fname[KEY_FNAME] substringWithRange:NSMakeRange(0, [idxStr length])];
					//nslog(@"idx=%@:subName=%@",idxStr,subName);
					if ([subName caseInsensitiveCompare:idxStr]==NSOrderedSame) break; // fname[KEY_FNAME]はこの文字から始まっている
				}
				[basFilesWithSection[n] addObject:fname];
			}
				break;
		}
	}
//	nslog(@"basFilesWithSection=%@",basFilesWithSection);
}

-(void)makeBasicSourceList
{
	// 全BASICソースリストを得る
	[self makeBasicFileList];
	
	// 前回選択していたソースにポイントを合わせる
	// basicFileに相当するindexPathを得る
	selectIndex = [NSIndexPath indexPathForRow:0 inSection:0]; // とりあえず先頭；見つからない時のため（ファイル削除時 or ユーザー未作成）
	for (NSInteger section=0;section<[basFilesWithSection count];section++) {
		NSArray *sectionBasFiles=basFilesWithSection[section];
		for (NSInteger row=0;row<[sectionBasFiles count];row++) {
			NSDictionary *fname=basFilesWithSection[section][row];
			if ([fname[KEY_PATH] isEqualToString:basicPath]) {
				selectIndex = [NSIndexPath indexPathForRow:row inSection:section];
				nslog(@"fname=%@",fname);
				break;
			}
		}
	}
	[self.tableView reloadData];
	
	nslog(@"selectIndex=%@",selectIndex);
	[self.tableView selectRowAtIndexPath:selectIndex animated:YES scrollPosition:UITableViewScrollPositionTop];
}

// ファイル名ソートのための関数
NSComparisonResult fnameSort(id fname1_, id fname2_, void *context)
{
	NSDictionary *fname1=(NSDictionary *)fname1_;
	NSDictionary *fname2=(NSDictionary *)fname2_;

	// 後にファイル名でソート
	NSString *name1=fname1[KEY_FNAME];
	NSString *name2=fname2[KEY_FNAME];
	NSComparisonResult ret=[name1 caseInsensitiveCompare:name2]; // V3.00で英大文字小文字区別なしに変更(その方側がわかりやすい)
	if (ret==NSOrderedSame) {
		// 同名の時はユーザー優先
		if ([fname1[KEY_FINTERNAL] intValue]<[fname2[KEY_FINTERNAL] intValue]) {
			return NSOrderedAscending;
		}
	}
	return ret;
}

//-------------------------------------------------------------------

-(IBAction)updateSegment:(id)sender
{
	UISegmentedControl *seg=(UISegmentedControl *)sender;
	nslog(@"updateSegment=%d",(int)seg.selectedSegmentIndex);
	clickSound();

	// 記録
	AppDelegate	*app=getAppDelegate();
	Setup *setup=app.setup;
	fselectSources=
	setup.fselectSources=seg.selectedSegmentIndex;

	if (fselectSources==SOURCE_SELECT_INTERNAL) {
		// 内蔵時は削除は負荷なのでボタンを消す
		self.navigationItem.leftBarButtonItem=nil;
	} else {
		[self setDeleteButtons];
	}
	
	// 全BASICソースリストを得て表示する
	[self makeBasicSourceList];

	// テーブル更新
	[self.tableView reloadData];
}

//-------------------------------------------------------------------

@end
