読者です 読者をやめる 読者になる 読者になる

ネームエントリ実装サンプル。


昨年の2月頃にも同じようなものを作っていたのですが
今見ると恥ずかしいくらい汚かったため書き直しました。
必要最小の実装のみですがこんなものでしょうか。


4/12追記。
main.c を書き直しました。
必要に応じてプロジェクト一式の方からダウンロードしてください。


NameEntry routine
Entry module test


プロジェクト一式
ttp://page.freett.com/ntr/tech/entry.zip


ソース


main.c

/*---------------------------------------------------------------------------------
	
	NameEntry routine
	Entry module test
	
	version 0.01
	Apr 11, 2010
	
	By. REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <nds.h>
#include "Entry.h"


typedef enum{
	MAIN_INIT = 0x00, 
	MAIN_EXEC, 
	MAIN_EXIT
}MAIN_ACT;

typedef struct{
	u16 act;
	u32 kdr;
	char name[ENTRY_MAX + 1];
}MainStatus;

static MainStatus st_main;


int main(void);
void main_Init(void);
void main_Exec(void);
void main_Exit(void);


//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
	
	consoleDemoInit();
	printf("NameEntry routine\nEntry module test\n\nversion 0.01\nApr 11, 2010\n\nBy REGEKATSU\n\n");
	
	printf("\x01b[10;0HINPUT ENTRY:");
	printf("\x01b[13;0HFIXED ENTRY:");
	
	printf("\x01b[19;0HKEY_UP:CHR_PREV KEY_DN:CHR_NEXT");
	printf("\x01b[20;0HKEY_LF:CUR_PREV KEY_RI:CUR_NEXT");
	printf("\x01b[21;0HKEY_A :SET ENTRY / REPEAT ENTRY");
	
	keysSetRepeat(20, 10);
	
	while(1) {
		
		swiWaitForVBlank();
		scanKeys();
		
		switch(st_main.act){
			
		case MAIN_INIT:
			main_Init();
			break;
			
		case MAIN_EXEC:
			main_Exec();
			break;
			
		case MAIN_EXIT:
			main_Exit();
			break;
			
		default:
			break;
			
		}
		
	}

}

//---------------------------------------------------------------------------------
void main_Init(void) {
//---------------------------------------------------------------------------------
	
	memset(&st_main, 0, sizeof(st_main));
	Entry_Init();
	
	printf("\x01b[16;0HExec to NameEntry...");
	
	st_main.act = MAIN_EXEC;
	
}

//---------------------------------------------------------------------------------
void main_Exec(void) {
//---------------------------------------------------------------------------------
	
	st_main.kdr = keysDownRepeat();
	
	if(st_main.kdr & KEY_UP){
		Entry_PrevChar();
		
	}else if(st_main.kdr & KEY_DOWN){
		Entry_NextChar();
		
	}else if(st_main.kdr & KEY_LEFT){
		Entry_PrevCur();
		
	}else if(st_main.kdr & KEY_RIGHT){
		Entry_NextCur();
		
	}
	
	if(keysDown() & KEY_A){
		
		if( (Entry_GetCharIdx() == CHAR_SET_ED) || (Entry_GetCurIdx() == ENTRY_MAX - 1) ){
			
			//ネームエントリを終了する。
			Entry_Exit();
			
			//ネームエントリで入力した文字列を取得する。
			memcpy(st_main.name, Entry_GetCharPtr(), ENTRY_MAX);
			printf("\x01b[13;12H%s", st_main.name);
			
			printf("\x01b[16;0HKEY_A to Repeat NameEntry...");
			
			st_main.act = MAIN_EXIT;
		}
		
	}
	
}

//---------------------------------------------------------------------------------
void main_Exit(void) {
//---------------------------------------------------------------------------------
	
	if(keysDown() & KEY_A){
		printf("\x01b[2K");
		st_main.act = MAIN_INIT;
	}
	
}

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


Entry.h

/*---------------------------------------------------------------------------------
	
	Entry module header
	
	version 0.01
	Apr 11, 2010
	
	By. REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _ENTRY_H_
#define _ENTRY_H_


//ネームエントリ可能な最大文字数。
#define ENTRY_MAX 3

//文字セットに登録のある、意味ある文字に対する定数名。
#define CHAR_SET_ED 0
#define CHAR_SET_SP 27


#ifdef __cplusplus
extern "C" {
#endif


void Entry_Init(void);
void Entry_Exit(void);
int Entry_GetCurIdx(void);
int Entry_GetCharIdx(void);
char *Entry_GetCharPtr(void);
void Entry_PrevCur(void);
void Entry_NextCur(void);
void Entry_PrevChar(void);
void Entry_NextChar(void);


#ifdef __cplusplus
}
#endif

#endif	// _ENTRY_H_


Entry.c

/*---------------------------------------------------------------------------------
	
	Entry module routine
	
	version 0.01
	Apr 11, 2010
	
	By. REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include "Entry.h"


//ネームエントリの表示位置。
#define DRAW_POSX 12
#define DRAW_POSY 10

//ネームエントリ用文字セット。
//(文字コード順でない並びを順番に扱うため文字テーブルを用意する。)
#define CHAR_SET_MAX 60

const static char char_set[CHAR_SET_MAX] = {
	'e', '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', ' ', '0', '1', 
	'2', '3', '4', '5', '6', '7', '8', '9', ':', ';', 
	'<', '>', '=', '?', '[', '@', '!', '\"', '#', '$', 
	'%', '&', '\'', '(', ')', '*', ',', '-', '.', '/'
};


//ネームエントリ用データ構造体。
typedef struct{
	char string[ENTRY_MAX + 1];
	int char_idx[ENTRY_MAX];
	int cur_idx;
}EntryStatus;

static EntryStatus st_entry;


void entry_DrawString(int x, int y, char *string);


//---------------------------------------------------------------------------------
void Entry_Init(void){
//---------------------------------------------------------------------------------
	
	//データ構造体の初期化と、表示文字列を初期状態にして表示する。
	
	memset(&st_entry, 0, sizeof(st_entry));
	
	int i;
	for(i = 0;i < ENTRY_MAX;i++){
		
		//文字配列を、文字セットに登録のある空白スペースで初期化する。
		st_entry.char_idx[i] = CHAR_SET_SP;
		st_entry.string[i] = char_set[ st_entry.char_idx[i] ];
		
	}
	st_entry.string[i] = '\0';
	
	//最初の文字を、入力終了を意味する'e'とする。
	st_entry.char_idx[0] = CHAR_SET_ED;
	st_entry.string[0] = char_set[ st_entry.char_idx[0] ];
	
	//ネームエントリ表示を開始する。
	entry_DrawString(DRAW_POSX, DRAW_POSY, st_entry.string);
	
}

//---------------------------------------------------------------------------------
void Entry_Exit(void){
//---------------------------------------------------------------------------------
	
	//表示文字列を画面より消す。
	//データ構造体はクリアせずそのままとして、次に初期化が行われるまでは値が取り出せるようにする。
	
	static char string[ENTRY_MAX + 1];
	
	memset(&string, ' ', sizeof(string));
	string[ENTRY_MAX] = '\0';
	
	//入力終了文字の指定による終了だった場合、入力終了文字を空白スペースに置き換える。
	if( st_entry.char_idx[st_entry.cur_idx] == CHAR_SET_ED ){
		st_entry.char_idx[st_entry.cur_idx] = CHAR_SET_SP;
		st_entry.string[st_entry.cur_idx] = char_set[ st_entry.char_idx[st_entry.cur_idx] ];
	}
	
	//ネームエントリ表示を終了する。
	entry_DrawString(DRAW_POSX, DRAW_POSY, string);
	
}

//---------------------------------------------------------------------------------
int Entry_GetCurIdx(void){
//---------------------------------------------------------------------------------
	
	return st_entry.cur_idx;
	
}

//---------------------------------------------------------------------------------
int Entry_GetCharIdx(void){
//---------------------------------------------------------------------------------
	
	return st_entry.char_idx[st_entry.cur_idx];
	
}

//---------------------------------------------------------------------------------
char *Entry_GetCharPtr(void){
//---------------------------------------------------------------------------------
	
	return st_entry.string;
	
}

//---------------------------------------------------------------------------------
void Entry_PrevCur(void){
//---------------------------------------------------------------------------------
	
	if(st_entry.cur_idx > 0){
		
		//現在のカーソルにある文字を空白にして、カーソルを1文字戻す。
		
		st_entry.char_idx[st_entry.cur_idx] = CHAR_SET_SP;
		st_entry.string[st_entry.cur_idx] = char_set[ st_entry.char_idx[st_entry.cur_idx] ];
		st_entry.cur_idx--;
		
		entry_DrawString(DRAW_POSX, DRAW_POSY, st_entry.string);
		
	}
	
}

//---------------------------------------------------------------------------------
void Entry_NextCur(void){
//---------------------------------------------------------------------------------
	
	//現在のカーソルにある文字が入力終了文字である場合は次の文字に進むことはできない。
	if( st_entry.char_idx[st_entry.cur_idx] == CHAR_SET_ED ) return;
	
	
	if(st_entry.cur_idx < ENTRY_MAX - 1){
		
		//カーソルを1文字進めて、ひとつ前に決定した文字を現在のカーソル文字にする。
		
		st_entry.char_idx[st_entry.cur_idx + 1] = st_entry.char_idx[st_entry.cur_idx];
		st_entry.string[st_entry.cur_idx + 1] = char_set[ st_entry.char_idx[st_entry.cur_idx + 1]];
		st_entry.cur_idx++;
		
		entry_DrawString(DRAW_POSX, DRAW_POSY, st_entry.string);
		
	}
	
}

//---------------------------------------------------------------------------------
void Entry_PrevChar(void){
//---------------------------------------------------------------------------------
	
	//現在選択してる文字を1文字前のものに戻す。
	//一番若い文字番号より以前は一番最後の文字番号へとローテートされる。
	
	if(--st_entry.char_idx[st_entry.cur_idx] < 0){
		st_entry.char_idx[st_entry.cur_idx] = CHAR_SET_MAX - 1;
	}
	st_entry.string[st_entry.cur_idx] = char_set[ st_entry.char_idx[st_entry.cur_idx] ];
	
	entry_DrawString(DRAW_POSX, DRAW_POSY, st_entry.string);
	
}

//---------------------------------------------------------------------------------
void Entry_NextChar(void){
//---------------------------------------------------------------------------------
	
	//現在選択してる文字を次の文字のものに進める。
	//一番最後の文字番号より先は一番若いの文字番号へとローテートされる。
	
	if(++st_entry.char_idx[st_entry.cur_idx] > CHAR_SET_MAX - 1){
		st_entry.char_idx[st_entry.cur_idx] = 0;
	}
	st_entry.string[st_entry.cur_idx] = char_set[ st_entry.char_idx[st_entry.cur_idx] ];
	
	entry_DrawString(DRAW_POSX, DRAW_POSY, st_entry.string);
	
}

//---------------------------------------------------------------------------------
void entry_DrawString(int x, int y, char *string){
//---------------------------------------------------------------------------------
	
	printf("\x01b[%d;%dH%s", y, x, string);
	
}

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