+#include "hspwnd.h"
+#include "supio.h"
+#include "dpmread.h"
+#include "stack.h"
+#include "strbuf.h"
+#include "hsp3code.h"
+#include "hsp3debug.h"
+#include "hsp3config.h"
+#include "hsp3int.h"
+
+#define strp(dsptr) &hspctx->mem_mds[dsptr]
+
+/*------------------------------------------------------------*/
+/*
+ system data
+*/
+/*------------------------------------------------------------*/
+
+static HSP3TYPEINFO *hsp3tinfo; // HSP3 type info structure (strbuf)
+static int tinfo_cur; // Current type info ID
+#define GetTypeInfoPtr( type ) (&hsp3tinfo[type])
+
+static HSPCTX *hspctx; // Current Context
+static unsigned short *mcs; // Current PC ptr
+static unsigned short *mcsbak;
+static int val,type,exflg;
+static short csvalue, csvalue2;
+static int hspevent_opt; // Event enable flag
+static MPModVarData modvar_init;
+static int sptr_res;
+static int arrayobj_flag;
+
+static HSPEXINFO mem_exinfo; // HSPEXINFO本体
+
+#ifdef HSPDEBUG
+static HSP3DEBUG dbginfo;
+static int dbgmode;
+#endif
+
+PVal *plugin_pval; // プラグインに渡される変数ポインタの実態
+PVal *mpval; // code_getで使用されたテンポラリ変数
+static PVal *mpval_int; // code_getで使用されたテンポラリ変数(int用)
+static PVal prmvar; // パラメーターテンポラリ変数の実態
+
+static unsigned char *mem_di_val; // Debug VALS info ptr
+static int srcname;
+static int funcres; // 関数の戻り値型
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+
+static int getU32(unsigned short *mcs) {
+ return (mcs[1] << 16) | (mcs[0]);
+}
+
+static inline void __code_next( void )
+{
+ // Get 1 command block
+ // (ver3.0以降用)
+ //
+// register unsigned short csvalue;
+ mcsbak = mcs;
+ csvalue = *mcs++;
+ exflg = csvalue & (EXFLG_1|EXFLG_2);
+ type = csvalue & CSTYPE;
+ if ( csvalue & EXFLG_3 ) {
+ // 32bit val code
+ //
+ val = getU32(mcs);
+ mcs+=2;
+// printf( "%08x | type[%d] val[%d] ex[%d]\n",(int)(mcs-hspctx->mem_mcs), type,val,exflg );
+ return;
+ }
+ // 16bit val code
+ val = (int)(*mcs++);
+
+// printf( "%08x : type[%d] val[%d] ex[%d]\n",(int)(mcs-hspctx->mem_mcs), type,val,exflg );
+}
+
+
+void code_next( void )
+{
+ __code_next();
+}
+
+
+void code_puterror( HSPERROR error )
+{
+ // エラー例外を発生させる
+ //
+ if ( error == HSPERR_NONE ) {
+ hspctx->runmode = RUNMODE_END;
+ return;
+ }
+ throw error;
+}
+
+
+int code_getexflg( void )
+{
+ return exflg;
+}
+
+
+static inline void calcprm( HspVarProc *proc, PDAT *pval, int exp, void *ptr )
+{
+ // Caluculate parameter args (valiant)
+ //
+ switch(exp) {
+ case CALCCODE_ADD:
+ proc->AddI( pval, ptr );
+ break;
+ case CALCCODE_SUB:
+ proc->SubI( pval, ptr );
+ break;
+ case CALCCODE_MUL:
+ proc->MulI( pval, ptr );
+ break;
+ case CALCCODE_DIV:
+ proc->DivI( pval, ptr );
+ break;
+ case CALCCODE_MOD: // '%'
+ proc->ModI( pval, ptr );
+ break;
+
+ case CALCCODE_AND:
+ proc->AndI( pval, ptr );
+ break;
+ case CALCCODE_OR:
+ proc->OrI( pval, ptr );
+ break;
+ case CALCCODE_XOR:
+ proc->XorI( pval, ptr );
+ break;
+
+ case CALCCODE_EQ:
+ proc->EqI( pval, ptr );
+ break;
+ case CALCCODE_NE:
+ proc->NeI( pval, ptr );
+ break;
+ case CALCCODE_GT:
+ proc->GtI( pval, ptr );
+ break;
+ case CALCCODE_LT:
+ proc->LtI( pval, ptr );
+ break;
+ case CALCCODE_GTEQ: // '>='
+ proc->GtEqI( pval, ptr );
+ break;
+ case CALCCODE_LTEQ: // '<='
+ proc->LtEqI( pval, ptr );
+ break;
+
+ case CALCCODE_RR: // '>>'
+ proc->RrI( pval, ptr );
+ break;
+ case CALCCODE_LR: // '<<'
+ proc->LrI( pval, ptr );
+ break;
+ case '(':
+ throw HSPERR_INVALID_ARRAY;
+ default:
+ throw HSPVAR_ERROR_INVALID;
+ }
+}
+
+
+static inline void calcprmf( int &mval, int exp, int p )
+{
+ // Caluculate parameter args (int)
+ //
+ switch(exp) {
+ case CALCCODE_ADD:
+ mval += p;
+ break;
+ case CALCCODE_SUB:
+ mval -= p;
+ break;
+ case CALCCODE_MUL:
+ mval *= p;
+ break;
+ case CALCCODE_DIV:
+ if ( p == 0 ) throw( HSPVAR_ERROR_DIVZERO );
+ mval /= p;
+ break;
+ case CALCCODE_MOD: // '%'
+ if ( p == 0 ) throw( HSPVAR_ERROR_DIVZERO );
+ mval %= p;
+ break;
+
+ case CALCCODE_AND:
+ mval &= p;
+ break;
+ case CALCCODE_OR:
+ mval |= p;
+ break;
+ case CALCCODE_XOR:
+ mval ^= p;
+ break;
+
+ case CALCCODE_EQ:
+ mval = (mval==p);
+ break;
+ case CALCCODE_NE:
+ mval = (mval!=p);
+ break;
+ case CALCCODE_GT:
+ mval = (mval>p);
+ break;
+ case CALCCODE_LT:
+ mval = (mval='
+ mval = (mval>=p);
+ break;
+ case CALCCODE_LTEQ: // '<='
+ mval = (mval<=p);
+ break;
+
+ case CALCCODE_RR: // '>>'
+ mval >>= p;
+ break;
+ case CALCCODE_LR: // '<<'
+ mval <<= p;
+ break;
+
+ case '(':
+ throw HSPERR_INVALID_ARRAY;
+ default:
+ throw HSPVAR_ERROR_INVALID;
+ }
+}
+
+
+static void inline code_calcop( int op )
+{
+ // スタックから引数を2つPOPしたものを演算する
+ //
+ HspVarProc *varproc;
+ STMDATA *stm1;
+ STMDATA *stm2;
+ char *ptr;
+ int tflag;
+ int basesize;
+
+ stm2 = StackPeek;
+ //stm1 = stm2-1;
+ stm1 = StackPeek2;
+ tflag = stm1->type;
+
+ //if ( tflag > HSP3_FUNC_MAX ) throw HSPERR_UNKNOWN_CODE;
+ //Alertf( "(%d) %d %d %d",tflag, stm1->ival, op, stm2->ival );
+
+ if ( tflag == HSPVAR_FLAG_INT ) {
+ if ( stm2->type == HSPVAR_FLAG_INT ) { // HSPVAR_FLAG_INT のみ高速化
+ calcprmf( stm1->ival, op, stm2->ival ); // 高速化された演算(intのみ)
+ StackDecLevel; // stack->Pop() の代わり(高速に)
+ stm2->ival = stm1->ival; // 1段目スタックの値を入れ替える
+ return;
+ }
+ }
+
+ mpval = HspVarCoreGetPVal( tflag );
+ varproc = HspVarCoreGetProc( tflag );
+
+ if ( mpval->mode == HSPVAR_MODE_NONE ) { // 型に合わせたテンポラリ変数を初期化
+ if ( varproc->flag == 0 ) {
+ throw HSPERR_TYPE_INITALIZATION_FAILED;
+ }
+ HspVarCoreClearTemp( mpval, tflag ); // 最小サイズのメモリを確保
+ }
+
+ varproc->Set( mpval, (PDAT *)mpval->pt, STM_GETPTR(stm1) ); // テンポラリ変数に初期値を設定
+
+ ptr = STM_GETPTR(stm2);
+ if ( tflag != stm2->type ) { // 型が一致しない場合は変換
+ if ( stm2->type >= HSPVAR_FLAG_USERDEF ) {
+ ptr = (char *)HspVarCoreGetProc(stm2->type)->CnvCustom( ptr, tflag );
+ } else {
+ ptr = (char *)varproc->Cnv( ptr, stm2->type );
+ }
+ }
+ calcprm( varproc, (PDAT *)mpval->pt, op, ptr ); // 計算を行なう
+ StackPop();
+ StackPop();
+
+ if ( varproc->aftertype != tflag ) { // 演算後に型が変わる場合
+ tflag = varproc->aftertype;
+ varproc = HspVarCoreGetProc( tflag );
+ }
+ basesize = varproc->basesize;
+ if ( basesize < 0 ) {
+ basesize = varproc->GetSize( (PDAT *)mpval->pt );
+ }
+ StackPush( tflag, mpval->pt, basesize );
+}
+
+
+static void code_checkarray( PVal *pval )
+{
+ // Check PVal Array information
+ // (配列要素(int)の取り出し)
+ //
+ int chk,i;
+ PVal temp;
+ HspVarCoreReset( pval ); // 配列ポインタをリセットする
+
+ if ( type == TYPE_MARK ) {
+ if ( val == '(' ) {
+ code_next();
+ // 整数値のみサポート
+ while(1) {
+ HspVarCoreCopyArrayInfo( &temp, pval ); // 状態を保存
+ chk = code_get(); // パラメーターを取り出す
+ if ( chk<=PARAM_END ) { throw HSPERR_BAD_ARRAY_EXPRESSION; }
+ if ( mpval->flag != HSPVAR_FLAG_INT ) { throw HSPERR_TYPE_MISMATCH; }
+ HspVarCoreCopyArrayInfo( pval, &temp ); // 状態を復帰
+ i = *(int *)(mpval->pt);
+ HspVarCoreArray( pval, i ); // 配列要素指定(整数)
+ if ( chk == PARAM_SPLIT ) break;
+ }
+ code_next(); // ')'を読み飛ばす
+ return;
+ }
+ }
+}
+
+
+static inline void code_arrayint2( PVal *pval, int offset )
+{
+ // 配列要素の指定 (index)
+ // ( Reset後に次元数だけ連続で呼ばれます )
+ //
+ if ( pval->arraycnt >= 5 ) throw HSPVAR_ERROR_ARRAYOVER;
+ if ( pval->arraycnt == 0 ) {
+ pval->arraymul = 1; // 最初の値
+ } else {
+ pval->arraymul *= pval->len[ pval->arraycnt ];
+ }
+ pval->arraycnt++;
+ if ( offset < 0 ) throw HSPVAR_ERROR_ARRAYOVER;
+ if ( offset >= (pval->len[ pval->arraycnt ]) ) {
+ if ((pval->arraycnt >= 4 )||( pval->len[ pval->arraycnt+1 ]==0 )) {
+ if ( pval->support & HSPVAR_SUPPORT_FLEXARRAY ) {
+ //Alertf("Expand.(%d)",offset);
+ HspVarCoreReDim( pval, pval->arraycnt, offset+1 ); // 配列を拡張する
+ pval->offset += offset * pval->arraymul;
+ return;
+ }
+ }
+ throw HSPVAR_ERROR_ARRAYOVER;
+ }
+ pval->offset += offset * pval->arraymul;
+}
+
+
+static void code_checkarray2( PVal *pval )
+{
+ // Check PVal Array information
+ // (配列要素(int)の取り出し)(配列の拡張に対応)
+ //
+ int chk,i;
+ PVal temp;
+ HspVarCoreReset( pval ); // 配列ポインタをリセットする
+
+ if ( type == TYPE_MARK ) {
+ if ( val == '(' ) {
+ code_next();
+ // 整数値のみサポート
+ while(1) {
+ HspVarCoreCopyArrayInfo( &temp, pval ); // 状態を保存
+ chk = code_get(); // パラメーターを取り出す
+ if ( chk<=PARAM_END ) { throw HSPERR_BAD_ARRAY_EXPRESSION; }
+ if ( mpval->flag != HSPVAR_FLAG_INT ) { throw HSPERR_TYPE_MISMATCH; }
+ HspVarCoreCopyArrayInfo( pval, &temp ); // 状態を復帰
+ i = *(int *)(mpval->pt);
+ code_arrayint2( pval, i );
+ if ( chk == PARAM_SPLIT ) break;
+ }
+ code_next(); // ')'を読み飛ばす
+ return;
+ }
+ }
+}
+
+
+static char *code_checkarray_obj( PVal *pval, int *mptype )
+{
+ // Check PVal Array object information
+ // ( 配列要素(オブジェクト)の取り出し )
+ // ( 返値 : 汎用データのポインタ )
+ // ( mptype : 汎用データのタイプを返す )
+ //
+ char *ptr;
+ HspVarProc *varproc;
+/*
+ FlexValue *fv;
+ if ( pval->support & HSPVAR_SUPPORT_STRUCTACCEPT ) { // 構造体受け付け
+ code_checkarray( pval );
+ if ( pval->support & HSPVAR_SUPPORT_CLONE ) { // クローンのチェック
+ fv = (FlexValue *)HspVarCorePtr( pval );
+ *mptype = fv->clonetype;
+ return (fv->ptr);
+ }
+ if (( type != TYPE_STRUCT )||( exflg )) {
+ *mptype = MPTYPE_VAR;
+ return HspVarCorePtr( pval );
+ }
+ varproc = HspVarCoreGetProc( pval->flag );
+ ptr = varproc->ArrayObject( pval, mptype );
+ return ptr;
+ }
+
+ if ( pval->support & HSPVAR_SUPPORT_CLONE ) { // クローンのチェック
+ fv = (FlexValue *)HspVarCorePtr( pval );
+ *mptype = fv->clonetype;
+ return (fv->ptr);
+ }
+*/
+
+ *mptype = pval->flag;
+ HspVarCoreReset( pval ); // 配列ポインタをリセットする
+
+ if ( type == TYPE_MARK ) {
+ if ( val == '(' ) { // 配列がある場合
+ code_next();
+// if ( pval->support & HSPVAR_SUPPORT_ARRAYOBJ ) {
+ varproc = HspVarCoreGetProc( pval->flag );
+ ptr = (char *)varproc->ArrayObjectRead( pval, mptype );
+ code_next(); // ')'を読み飛ばす
+ return ptr;
+// }
+// code_checkarray( pval );
+ }
+ }
+ return (char *)HspVarCorePtr( pval );
+}
+
+
+/*
+static char *code_get_varsub( PVal *pval, int *restype )
+{
+ // pvalの実体を検索する(HSPVAR_SUPPORT_ARRAYOBJ時のみ)
+ // ( 返値が実体ポインタとなる )
+ //
+ char *ptr;
+ ptr = (char *)code_checkarray_obj( pval, restype );
+ return code_get_proxyvar( ptr, restype );
+}
+*/
+
+
+char *code_get_proxyvar( char *ptr, int *mptype )
+{
+ // マルチパラメーターの変数を処理する
+ //
+ MPVarData *var;
+ PVal *getv_pval;
+ switch( *mptype ) { // マルチパラメーターを取得
+ case MPTYPE_SINGLEVAR:
+ var = (MPVarData *)ptr;
+ getv_pval = var->pval;
+ getv_pval->offset = var->aptr;
+ if ( type == TYPE_MARK ) if ( val == '(' ) throw HSPERR_INVALID_ARRAY;
+ //HspVarCoreReset( getv_pval );
+ break;
+ case MPTYPE_LOCALSTRING:
+ *mptype = MPTYPE_STRING;
+ return *(char **)ptr;
+ case MPTYPE_LABEL:
+ *mptype = HSPVAR_FLAG_LABEL;
+ return ptr;
+ case MPTYPE_ARRAYVAR:
+ var = (MPVarData *)ptr;
+ getv_pval = var->pval;
+ if ( getv_pval->support & HSPVAR_SUPPORT_MISCTYPE ) {
+ return code_checkarray_obj( getv_pval, mptype );
+ } else {
+ code_checkarray( getv_pval );
+ }
+ break;
+ case MPTYPE_LOCALVAR:
+ getv_pval = (PVal *)ptr;
+ if ( getv_pval->support & HSPVAR_SUPPORT_MISCTYPE ) {
+ return code_checkarray_obj( getv_pval, mptype );
+ } else {
+ code_checkarray( getv_pval );
+ }
+ break;
+ default:
+ return ptr;
+ }
+ *mptype = getv_pval->flag;
+ return (char *)HspVarCorePtr( getv_pval );
+}
+
+
+static void code_checkarray_obj2( PVal *pval )
+{
+ // Check PVal Array object information
+ // ( 配列要素(オブジェクト)の取り出し・変数指定時 )
+ // ( 変数の内容を参照する場合にはcode_checkarray_objを使用します )
+ //
+ HspVarProc *varproc;
+ HspVarCoreReset( pval ); // 配列ポインタをリセットする
+
+ arrayobj_flag = 0;
+ if ( type == TYPE_MARK ) {
+ if ( val == '(' ) { // 配列がある場合
+ code_next();
+ varproc = HspVarCoreGetProc( pval->flag );
+ varproc->ArrayObject( pval );
+ arrayobj_flag = 1;
+ code_next(); // ')'を読み飛ばす
+ }
+ }
+}
+
+
+
+int code_get( void )
+{
+ // parameter analysis
+ // result: 0=ok(PARAM_OK) -1=end(PARAM_END) -2=default(PARAM_DEFAULT)
+ // (エラー発生時は例外が発生します)
+ //
+ STMDATA *stm;
+ PVal *argpv;
+ HspVarProc *varproc;
+ HSP3TYPEINFO *info;
+ MPModVarData *var;
+ FlexValue *fv;
+ char *out;
+ STRUCTPRM *prm;
+ char *ptr;
+ int tflag;
+ int basesize;
+ int tmpval;
+ int stack_def;
+ int resval;
+
+ if (exflg&EXFLG_1) return PARAM_END; // パラメーター終端
+ if (exflg&EXFLG_2) { // パラメーター区切り(デフォルト時)
+ exflg^=EXFLG_2;
+ return PARAM_DEFAULT;
+ }
+ if ( type == TYPE_MARK ) {
+ if ( val == 63 ) { // パラメーター省略時('?')
+ code_next();
+ exflg&=~EXFLG_2;
+ return PARAM_DEFAULT;
+ }
+ if ( val == ')' ) { // 関数内のパラメーター省略時
+ exflg&=~EXFLG_2;
+ return PARAM_ENDSPLIT;
+ }
+ }
+
+ if ( csvalue & EXFLG_0 ) { // 単一の項目(高速化)
+ switch(type) {
+ case TYPE_INUM:
+ mpval = mpval_int;
+ *(int *)mpval->pt =val;
+ break;
+ case TYPE_DNUM:
+ case TYPE_STRING:
+ varproc = HspVarCoreGetProc( type );
+ mpval = HspVarCoreGetPVal( type );
+ if ( mpval->mode == HSPVAR_MODE_NONE ) { // 型に合わせたテンポラリ変数を初期化
+ if ( varproc->flag == 0 ) {
+ throw HSPERR_TYPE_INITALIZATION_FAILED;
+ }
+ HspVarCoreClearTemp( mpval, type ); // 最小サイズのメモリを確保
+ }
+ varproc->Set( mpval, (PDAT *)(mpval->pt), strp(val) ); // テンポラリ変数に初期値を設定
+ break;
+ default:
+ throw HSPERR_UNKNOWN_CODE;
+ }
+ code_next();
+ exflg&=~EXFLG_2;
+ return 0;
+ }
+
+ resval = 0;
+ stack_def = StackGetLevel; // スタックのレベルを取得
+
+ while(1) {
+ //Alertf( "type%d val%d exflg%d",type,val,exflg );
+ //printf( "type%d val%d exflg%d\n",type,val,exflg );
+
+ switch(type) {
+ case TYPE_MARK:
+ if ( val == ')' ) { // 引数の終了マーク
+ if ( stack_def == StackGetLevel ) { throw HSPERR_WRONG_EXPRESSION; }
+ resval = PARAM_SPLIT;
+ exflg |= EXFLG_2;
+ break;
+ }
+ code_calcop( val );
+ code_next();
+ break;
+ case TYPE_VAR:
+ argpv = &hspctx->mem_var[val];
+ code_next();
+ tflag = argpv->flag;
+ if ( argpv->support & HSPVAR_SUPPORT_MISCTYPE ) {
+ ptr = (char *)code_checkarray_obj( argpv, &tflag );
+ } else {
+ code_checkarray( argpv );
+ ptr = (char *)HspVarCorePtr( argpv );
+ }
+ varproc = HspVarCoreGetProc( tflag );
+ basesize = varproc->basesize;
+ if ( basesize < 0 ) { basesize = varproc->GetSize( (PDAT *)ptr ); }
+ StackPush( tflag, ptr, basesize );
+ break;
+ case TYPE_INUM:
+ StackPushi( val );
+ code_next();
+ break;
+ case TYPE_STRING:
+ StackPush( type, strp(val) );
+ code_next();
+ break;
+ case TYPE_DNUM:
+ StackPush( type, strp(val), sizeof(double) );
+ code_next();
+ break;
+ case TYPE_STRUCT:
+ prm = &hspctx->mem_minfo[val];
+ code_next();
+ out = ((char *)hspctx->prmstack );
+ if ( out == NULL ) throw HSPERR_INVALID_PARAMETER;
+ if ( prm->subid != STRUCTPRM_SUBID_STACK ) {
+ var = (MPModVarData *)out;
+ if (( var->magic != MODVAR_MAGICCODE )||( var->subid != prm->subid )||(var->pval->flag != TYPE_STRUCT )) throw HSPERR_INVALID_STRUCT_SOURCE;
+ fv = (FlexValue *)HspVarCorePtrAPTR( var->pval, var->aptr );
+ if ( fv->type == FLEXVAL_TYPE_NONE ) throw HSPERR_INVALID_STRUCT_SOURCE;
+ out = (char *)fv->ptr;
+ }
+ out += prm->offset;
+ tflag = prm->mptype;
+ ptr = (char *)code_get_proxyvar( out, &tflag );
+ varproc = HspVarCoreGetProc( tflag );
+ basesize = varproc->basesize;
+ if ( basesize < 0 ) { basesize = varproc->GetSize( (PDAT *)ptr ); }
+ StackPush( tflag, ptr, basesize );
+ break;
+ case TYPE_LABEL: {
+ unsigned short *tmpval = hspctx->mem_mcs + hspctx->mem_ot[val];
+ StackPush( HSPVAR_FLAG_LABEL, (char *)&tmpval, sizeof(unsigned short *) );
+ code_next();
+ break;
+ }
+ default:
+ // リダイレクト(reffunc)使用チェック
+ //
+ info = GetTypeInfoPtr( type );
+ if ( info->reffunc == NULL ) {
+ throw HSPERR_INVALID_PARAMETER;
+ }
+ tmpval = val;
+ code_next();
+ ptr = (char *)info->reffunc( &tflag, tmpval ); // タイプごとの関数振り分け
+ basesize = HspVarCoreGetProc( tflag )->GetSize( (PDAT *)ptr );
+ StackPush( tflag, ptr, basesize );
+ break;
+ }
+
+ if ( exflg ) { // パラメーター終端チェック
+ exflg&=~EXFLG_2;
+ break;
+ }
+ }
+
+ stm = StackPeek;
+ tflag = stm->type;
+
+ if ( tflag == HSPVAR_FLAG_INT ) { // int型の場合は直接値を設定する(高速化)
+ mpval = mpval_int;
+ *(int *)mpval->pt = stm->ival;
+ } else {
+ varproc = HspVarCoreGetProc( tflag );
+ mpval = HspVarCoreGetPVal( tflag );
+
+ if ( mpval->mode == HSPVAR_MODE_NONE ) { // 型に合わせたテンポラリ変数を初期化
+ if ( varproc->flag == 0 ) {
+ throw HSPERR_TYPE_INITALIZATION_FAILED;
+ }
+ HspVarCoreClearTemp( mpval, tflag ); // 最小サイズのメモリを確保
+ }
+ varproc->Set( mpval, (PDAT *)(mpval->pt), STM_GETPTR(stm) ); // テンポラリ変数に初期値を設定
+ }
+
+ StackPop();
+ if ( stack_def != StackGetLevel ) { // スタックが正常に復帰していない
+ throw HSPERR_STACK_OVERFLOW;
+ }
+
+ return resval;
+}
+
+
+char *code_gets( void )
+{
+ // 文字列パラメーターを取得
+ //
+ int chk;
+ chk = code_get();
+ if ( chk<=PARAM_END ) { throw HSPERR_NO_DEFAULT; }
+ if ( mpval->flag != HSPVAR_FLAG_STR ) { throw HSPERR_TYPE_MISMATCH; }
+ return (mpval->pt);
+}
+
+
+char *code_getds( const char *defval )
+{
+ // 文字列パラメーターを取得(デフォルト値あり)
+ //
+ int chk;
+ chk = code_get();
+ if ( chk<=PARAM_END ) { return (char *)defval; }
+ if ( mpval->flag != HSPVAR_FLAG_STR ) { throw HSPERR_TYPE_MISMATCH; }
+ return (mpval->pt);
+}
+
+char *code_getas(void)
+{
+#ifdef HSPUTF8
+ HSPCHAR *s;
+ HSPAPICHAR *hactmp1 = 0;
+ char *actmp1 = 0;
+ s = code_gets();
+ chartoapichar(s, &hactmp1);
+ apichartoansichar(hactmp1, &actmp1);
+ freehac(&hactmp1);
+ sbCopy(&hspctx->stmp,actmp1,strlen(actmp1)+1);
+ freeac(&actmp1);
+ return hspctx->stmp;
+#else
+ return code_gets();
+#endif
+}
+
+char *code_getads(const char *defval)
+{
+#ifdef HSPUTF8
+ HSPCHAR *s;
+ HSPAPICHAR *hactmp1 = 0;
+ char *actmp1 = 0;
+ s = code_getds(defval);
+ if (s == defval){
+ return s;
+ }
+ chartoapichar(s, &hactmp1);
+ apichartoansichar(hactmp1, &actmp1);
+ freehac(&hactmp1);
+ sbCopy(&hspctx->stmp,actmp1,strlen(actmp1)+1);
+ freeac(&actmp1);
+ return hspctx->stmp;
+#else
+ return code_getds( defval );
+#endif
+}
+
+char *code_getdsi( const char *defval )
+{
+ // 文字列パラメーターを取得(デフォルト値あり・数値も可)
+ //
+ int chk;
+ char *ptr;
+ chk = code_get();
+ if ( chk<=PARAM_END ) { return (char *)defval; }
+
+ ptr = mpval->pt;
+ if ( mpval->flag != HSPVAR_FLAG_STR ) { // 型が一致しない場合は変換
+ //ptr = (char *)HspVarCoreCnv( mpval->flag, HSPVAR_FLAG_STR, ptr );
+ ptr = (char *)HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_STR );
+ }
+ return ptr;
+}
+
+
+int code_geti( void )
+{
+ // 数値パラメーターを取得
+ //
+ int chk;
+ chk = code_get();
+ if ( chk<=PARAM_END ) { throw HSPERR_NO_DEFAULT; }
+ if ( mpval->flag != HSPVAR_FLAG_INT ) {
+ if ( mpval->flag != HSPVAR_FLAG_DOUBLE ) throw HSPERR_TYPE_MISMATCH;
+ return (int)(*(double *)(mpval->pt)); // doubleの時はintに変換
+ }
+ return *(int *)(mpval->pt);
+}
+
+
+int code_getdi( const int defval )
+{
+ // 数値パラメーターを取得(デフォルト値あり)
+ //
+ int chk;
+ chk = code_get();
+ if ( chk<=PARAM_END ) { return defval; }
+ if ( mpval->flag != HSPVAR_FLAG_INT ) {
+ if ( mpval->flag != HSPVAR_FLAG_DOUBLE ) throw HSPERR_TYPE_MISMATCH;
+ return (int)(*(double *)(mpval->pt)); // doubleの時はintに変換
+ }
+ return *(int *)(mpval->pt);
+}
+
+
+double code_getd( void )
+{
+ // 数値(double)パラメーターを取得
+ //
+ int chk;
+ chk = code_get();
+ if ( chk<=PARAM_END ) { throw HSPERR_NO_DEFAULT; }
+ if ( mpval->flag != HSPVAR_FLAG_DOUBLE ) {
+ if ( mpval->flag != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH;
+ return (double)(*(int *)(mpval->pt)); // intの時はdoubleに変換
+ }
+ return *(double *)(mpval->pt);
+}
+
+
+double code_getdd( const double defval )
+{
+ // 数値(double)パラメーターを取得(デフォルト値あり)
+ //
+ int chk;
+ chk = code_get();
+ if ( chk<=PARAM_END ) { return defval; }
+ if ( mpval->flag != HSPVAR_FLAG_DOUBLE ) {
+ if ( mpval->flag != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH;
+ return (double)(*(int *)(mpval->pt)); // intの時はdoubleに変換
+ }
+ return *(double *)(mpval->pt);
+}
+
+
+static APTR code_getv_sub( PVal **pval )
+{
+ // pvalの実体を検索する(マルチパラメーターの場合があるため)
+ // ( 返値が新しいPValポインタとなる )
+ //
+ PVal *getv_pval;
+// MPVarData *var;
+ int mptype;
+
+ mptype = MPTYPE_VAR;
+ getv_pval = *pval;
+ if ( getv_pval->support & HSPVAR_SUPPORT_MISCTYPE ) { // 連想配列などの検索
+ code_checkarray_obj2( getv_pval );
+ return HspVarCoreGetAPTR( getv_pval );
+ }
+ code_checkarray2( *pval ); // 通常の配列検索(拡張あり)
+ return HspVarCoreGetAPTR( getv_pval );
+}
+
+/*
+static APTR code_getv_sub2( PVal **pval )
+{
+ // pvalの実体を検索する(マルチパラメーターの場合があるため)
+ // ( 返値が新しいPValポインタとなる )
+ //
+ PVal *getv_pval;
+ MPVarData *var;
+ int mptype;
+
+ mptype = MPTYPE_VAR;
+ getv_pval = *pval;
+ if ( getv_pval->support & HSPVAR_SUPPORT_MISCTYPE ) { // 連想配列などの検索
+ var = (MPVarData *)code_checkarray_obj( getv_pval, &mptype );
+ return code_getv_proxy( pval, var, mptype );
+ }
+ code_checkarray2( *pval ); // 通常の配列検索
+ return HspVarCoreGetAPTR( getv_pval );
+}
+*/
+
+APTR code_getv_proxy( PVal **pval, MPVarData *var, int mptype )
+{
+ PVal *getv_pval;
+ APTR aptr;
+ switch( mptype ) { // マルチパラメーターを取得
+ case MPTYPE_VAR:
+ return HspVarCoreGetAPTR( *pval );
+ case MPTYPE_SINGLEVAR:
+ getv_pval = var->pval;
+ aptr = var->aptr;
+ if ( type == TYPE_MARK ) if ( val == '(' ) throw HSPERR_INVALID_ARRAY;
+ break;
+ case MPTYPE_ARRAYVAR:
+ getv_pval = var->pval;
+ aptr = code_getv_sub( &getv_pval );
+ break;
+ case MPTYPE_LOCALVAR:
+ getv_pval = (PVal *)var;
+ aptr = code_getv_sub( &getv_pval );
+ break;
+ default:
+ throw HSPERR_VARIABLE_REQUIRED;
+ }
+ *pval = getv_pval;
+ return aptr;
+}
+
+
+static inline APTR code_getva_struct( PVal **pval )
+{
+ // 置き換えパラメーターを変数の代わりに取得
+ //
+ MPModVarData *var;
+ FlexValue *fv;
+ STRUCTPRM *prm;
+ APTR aptr;
+ char *out;
+ int i;
+
+ i = val;
+ code_next();
+ out = ((char *)hspctx->prmstack );
+ if ( out == NULL ) throw HSPERR_INVALID_PARAMETER;
+
+ if ( i == STRUCTCODE_THISMOD ) { // thismod
+ var = (MPModVarData *)out;
+ if ( var->magic != MODVAR_MAGICCODE ) throw HSPERR_INVALID_STRUCT_SOURCE;
+ *pval = var->pval;
+ exflg&=EXFLG_1;
+ return var->aptr;
+ }
+
+ prm = &hspctx->mem_minfo[i];
+ if ( prm->subid != STRUCTPRM_SUBID_STACK ) {
+ var = (MPModVarData *)out;
+ if (( var->magic != MODVAR_MAGICCODE )||( var->subid != prm->subid )||(var->pval->flag != TYPE_STRUCT )) throw HSPERR_INVALID_STRUCT_SOURCE;
+ fv = (FlexValue *)HspVarCorePtrAPTR( var->pval, var->aptr );
+ if ( fv->type == FLEXVAL_TYPE_NONE ) throw HSPERR_INVALID_STRUCT_SOURCE;
+ out = (char *)fv->ptr;
+ }
+ out += prm->offset;
+ aptr = code_getv_proxy( pval, (MPVarData *)out, prm->mptype );
+ exflg&=EXFLG_1; // for 2nd prm_get
+ return aptr;
+}
+
+
+APTR code_getva( PVal **pval )
+{
+ // 変数パラメーターを取得(pval+APTR)
+ //
+ PVal *getv_pval;
+ APTR aptr;
+ if ( exflg ) { throw HSPERR_VARIABLE_REQUIRED; } // パラメーターなし(デフォルト時)
+
+ if ( type == TYPE_STRUCT ) { // 置き換えパラメーター時
+ return code_getva_struct( pval );
+ }
+ if ( type != TYPE_VAR ) { throw HSPERR_VARIABLE_REQUIRED; }
+
+ getv_pval = &hspctx->mem_var[val];
+ code_next();
+
+ aptr = code_getv_sub( &getv_pval );
+
+ exflg&=EXFLG_1; // for 2nd prm_get
+ *pval = getv_pval;
+ return aptr;
+}
+
+
+PVal *code_getpval( void )
+{
+ // 変数パラメーターを取得(PVal)
+ //
+ PVal *getv_pval;
+ APTR aptr;
+ aptr = code_getva( &getv_pval );
+ if ( aptr != 0 ) throw HSPERR_BAD_ARRAY_EXPRESSION;
+ return getv_pval;
+}
+
+
+
+unsigned short *code_getlb( void )
+{
+ // ラベルパラメーターを取得
+ //
+ if ( type != TYPE_LABEL ) {
+ int chk;
+ unsigned short *p;
+ chk = code_get();
+ if ( chk<=PARAM_END ) { throw HSPERR_LABEL_REQUIRED; }
+ if ( mpval->flag != HSPVAR_FLAG_LABEL ) { throw HSPERR_LABEL_REQUIRED; }
+ p = *(unsigned short **)mpval->pt;
+ if ( p == NULL ) { // ラベル型変数の初期値はエラーに
+ throw HSPERR_LABEL_REQUIRED;
+ }
+ mcs = mcsbak;
+ return p;
+ }
+ return (unsigned short *)( hspctx->mem_mcs + (hspctx->mem_ot[val]) );
+}
+
+
+unsigned short *code_getlb2( void )
+{
+ unsigned short *s;
+ s = code_getlb();
+ code_next();
+ exflg&=~EXFLG_2;
+ return s;
+}
+
+
+STRUCTPRM *code_getstprm( void )
+{
+ // 構造体パラメーターを取得
+ //
+ STRUCTPRM *prm;
+ if ( type != TYPE_STRUCT ) throw HSPERR_STRUCT_REQUIRED;
+ prm = &hspctx->mem_minfo[ val ];
+ code_next();
+ exflg&=~EXFLG_2;
+ return prm;
+}
+
+
+STRUCTDAT *code_getstruct( void )
+{
+ // 構造体パラメーターを取得
+ //
+ STRUCTDAT *st;
+ STRUCTPRM *prm;
+ prm = code_getstprm();
+ if ( prm->mptype != MPTYPE_STRUCTTAG ) throw HSPERR_STRUCT_REQUIRED;
+ st = &hspctx->mem_finfo[ prm->subid ];
+ return st;
+}
+
+
+STRUCTDAT *code_getcomst( void )
+{
+ // COM構造体パラメーターを取得
+ //
+ STRUCTDAT *st;
+ if ( type != TYPE_DLLCTRL ) throw HSPERR_TYPE_MISMATCH;
+ val -= TYPE_OFFSET_COMOBJ;
+ if ( val < 0 ) throw HSPERR_TYPE_MISMATCH;
+ st = &hspctx->mem_finfo[ val ];
+ code_next();
+ exflg&=~EXFLG_2;
+ return st;
+}
+
+
+/*
+void code_setv( PVal *pval, PDAT *dat, int type, void *ptr )
+{
+ // 変数にパラメーターを指定する
+ //
+ PDAT *p;
+ HspVarProc *proc;
+
+ p = dat;
+ proc = HspVarCoreGetProc( type );
+ if ( pval->flag != type ) {
+ HspVarCoreReset( pval );
+ p = HspVarCorePtr( pval ); // 要素0のPDATポインタを取得
+ if ( p != dat ) throw HSPERR_INVALID_ARRAYSTORE;
+ HspVarCoreClear( pval, type ); // 最小サイズのメモリを確保
+ p = proc->GetPtr( pval ); // PDATポインタを取得
+ }
+ proc->Set( p, ptr );
+}
+*/
+
+void code_setva( PVal *pval, APTR aptr, int type, const void *ptr )
+{
+ // 変数にパラメーターを指定する
+ //
+ HspVarProc *proc;
+ pval->offset = aptr;
+ proc = HspVarCoreGetProc( type );
+ if ( pval->flag != type ) {
+ if ( aptr != 0 ) throw HSPERR_INVALID_ARRAYSTORE;
+ HspVarCoreClear( pval, type ); // 最小サイズのメモリを確保
+ }
+ proc->Set( pval, proc->GetPtr( pval ), ptr );
+}
+
+
+char *code_getvptr( PVal **pval, int *size )
+{
+ // 変数ポインタを得る
+ //
+ APTR aptr;
+ aptr = code_getva( pval );
+ return (char *)HspVarCoreGetBlockSize( *pval, HspVarCorePtrAPTR( *pval,aptr ), size );
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ call-return process function
+*/
+/*------------------------------------------------------------*/
+
+static void customstack_delete( STRUCTDAT *st, char *stackptr )
+{
+ // custom command stack delete
+ //
+ int i;
+ char *out;
+ char *ss;
+ STRUCTPRM *prm;
+ prm = &hspctx->mem_minfo[ st->prmindex ];
+ for(i=0;iprmmax;i++) { // パラメーターを取得
+ if ( prm->mptype == MPTYPE_LOCALSTRING ) {
+ out = stackptr + prm->offset;
+ ss = *(char **)out;
+ sbFree( ss );
+ } else if ( prm->mptype == MPTYPE_LOCALVAR ) {
+ HspVarCoreDispose( (PVal *)(stackptr + prm->offset) );
+ }
+ prm++;
+ }
+}
+
+void cmdfunc_return( void )
+{
+ // return execute
+ //
+ STMDATA *stm;
+ HSPROUTINE *r;
+
+ if ( StackGetLevel == 0 ) throw HSPERR_RETURN_WITHOUT_GOSUB;
+
+ stm = StackPeek;
+ r = (HSPROUTINE *)STM_GETPTR(stm);
+
+ if ( stm->type == TYPE_EX_CUSTOMFUNC ) {
+ customstack_delete( r->param, (char *)(r+1) ); // カスタム命令のローカルメモリを解放
+ }
+
+ mcs=r->mcsret;
+ hspctx->prmstack = r->oldtack; // 以前のスタックに戻す
+
+ hspctx->sublev--;
+ code_next();
+
+ StackPop();
+}
+
+#ifdef HSPEMSCRIPTEN
+static void cmdfunc_gosub( unsigned short *subr, unsigned short *retpc )
+{
+ // gosub execute
+ //
+ HSPROUTINE r;
+ r.mcsret = retpc;
+ r.stacklev = hspctx->sublev++;
+ r.oldtack = hspctx->prmstack;
+ r.param = NULL;
+ StackPush( TYPE_EX_SUBROUTINE, (char *)&r, sizeof(HSPROUTINE) );
+
+ code_setpc( subr );
+}
+#else
+static int cmdfunc_gosub( unsigned short *subr )
+{
+ // gosub execute
+ //
+ HSPROUTINE r;
+ r.mcsret = mcs;
+ r.stacklev = hspctx->sublev++;
+ r.oldtack = hspctx->prmstack;
+ r.param = NULL;
+ StackPush( TYPE_EX_SUBROUTINE, (char *)&r, sizeof(HSPROUTINE) );
+
+ mcs = subr;
+ code_next();
+
+ // gosub内で呼び出しを完結させる
+ //
+ while(1) {
+#ifdef HSPDEBUG
+ if ( dbgmode ) code_dbgtrace(); // トレースモード時の処理
+#endif
+ if ( GetTypeInfoPtr( type )->cmdfunc( val ) ) { // タイプごとの関数振り分け
+ if ( hspctx->runmode == RUNMODE_RETURN ) {
+ cmdfunc_return();
+ break;
+ } else {
+ hspctx->msgfunc( hspctx );
+ }
+ if ( hspctx->runmode == RUNMODE_END ) {
+ return RUNMODE_END;
+ }
+ }
+ }
+
+ return RUNMODE_RUN;
+}
+#endif
+
+
+static int code_callfunc( int cmd )
+{
+ // ユーザー拡張命令を呼び出す
+ //
+ STRUCTDAT *st;
+ HSPROUTINE *r;
+ int size;
+ char *p;
+
+ st = &hspctx->mem_finfo[cmd];
+
+ size = sizeof(HSPROUTINE) + st->size;
+ r = (HSPROUTINE *)StackPushSize( TYPE_EX_CUSTOMFUNC, size );
+ p = (char *)(r+1);
+ code_expandstruct( p, st, CODE_EXPANDSTRUCT_OPT_NONE ); // スタックの内容を初期化
+
+ r->oldtack = hspctx->prmstack; // 以前のスタックを保存
+ hspctx->prmstack = (void *)p; // 新規スタックを設定
+
+ r->mcsret = mcsbak; // 戻り場所
+ r->stacklev = hspctx->sublev++; // ネストを進める
+ r->param = st;
+
+ mcs = (unsigned short *)( hspctx->mem_mcs + (hspctx->mem_ot[ st->otindex ]) );
+ code_next();
+
+ // 命令内で呼び出しを完結させる
+ //
+ while(1) {
+
+#ifdef HSPDEBUG
+ if ( dbgmode ) code_dbgtrace(); // トレースモード時の処理
+#endif
+ if ( GetTypeInfoPtr( type )->cmdfunc( val ) ) { // タイプごとの関数振り分け
+ if ( hspctx->runmode == RUNMODE_END ) {
+ throw HSPERR_NONE;
+ }
+ if ( hspctx->runmode == RUNMODE_RETURN ) {
+ cmdfunc_return();
+ break;
+ } else {
+ hspctx->msgfunc( hspctx );
+ }
+ }
+ }
+
+ return RUNMODE_RUN;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ structure process function
+*/
+/*------------------------------------------------------------*/
+
+APTR code_newstruct( PVal *pval )
+{
+ int i,max;
+ APTR ofs;
+ FlexValue *fv;
+ ofs = 0;
+ if ( pval->flag != TYPE_STRUCT ) return 0;
+ fv = (FlexValue *)pval->pt;
+ max = pval->len[1];
+ for( i=0;imem_minfo[ st->prmindex ];
+
+ for(i=0;iprmmax;i++) { // パラメーターを取得
+ out = p + prm->offset;
+ //Alertf("(%d)type%d index%d/%d offset%d", st->subid, prm->mptype, st->prmindex + i, st->prmmax, prm->offset);
+ switch( prm->mptype ) {
+ case MPTYPE_INUM:
+ *(int *)out = code_getdi(0);
+ break;
+ case MPTYPE_MODULEVAR:
+ {
+ MPModVarData *var;
+ PVal *refpv;
+ APTR refap;
+ var = (MPModVarData *)out;
+ refap = code_getva( &refpv );
+ var->magic = MODVAR_MAGICCODE;
+ var->subid = prm->subid;
+ var->pval = refpv;
+ var->aptr = refap;
+ break;
+ }
+ case MPTYPE_IMODULEVAR:
+ case MPTYPE_TMODULEVAR:
+ *(MPModVarData *)out = modvar_init;
+ break;
+ case MPTYPE_SINGLEVAR:
+ case MPTYPE_ARRAYVAR:
+ {
+ MPVarData *var;
+ PVal *refpv;
+ APTR refap;
+ var = (MPVarData *)out;
+ refap = code_getva( &refpv );
+ var->pval = refpv;
+ var->aptr = refap;
+ break;
+ }
+ case MPTYPE_LABEL:
+ *(unsigned short **)out = code_getlb2();
+ break;
+ case MPTYPE_DNUM:
+ {
+ //*(double *)out = code_getd();
+ double d = code_getd();
+ memcpy(out, &d, sizeof(double));
+ break;
+ }
+ case MPTYPE_LOCALSTRING:
+ {
+ char *str;
+ char *ss;
+ str = code_gets();
+ ss = sbAlloc( (int)strlen(str)+1 );
+ strcpy( ss, str );
+ *(char **)out = ss;
+ break;
+ }
+ case MPTYPE_LOCALVAR:
+ {
+ PVal *pval;
+ PDAT *dst;
+ HspVarProc *proc;
+ pval = (PVal *)out;
+ pval->mode = HSPVAR_MODE_NONE;
+ if ( option & CODE_EXPANDSTRUCT_OPT_LOCALVAR ) {
+ chk = code_get(); // パラメーター値を取得
+ if ( chk == PARAM_OK ) {
+ pval->flag = mpval->flag; // 仮の型
+ HspVarCoreClear( pval, mpval->flag ); // 最小サイズのメモリを確保
+ proc = HspVarCoreGetProc( pval->flag );
+ dst = proc->GetPtr( pval ); // PDATポインタを取得
+ proc->Set( pval, dst, mpval->pt );
+ break;
+ }
+ }
+ pval->flag = HSPVAR_FLAG_INT; // 仮の型
+ HspVarCoreClear( pval, HSPVAR_FLAG_INT ); // グローバル変数を0にリセット
+ break;
+ }
+ case MPTYPE_STRUCTTAG:
+ break;
+ default:
+ throw HSPERR_INVALID_STRUCT_SOURCE;
+ }
+ prm++;
+ }
+}
+
+
+void code_delstruct( PVal *in_pval, APTR in_aptr )
+{
+ // モジュール変数を破棄する
+ //
+ int i;
+ char *p;
+ char *out;
+ STRUCTPRM *prm;
+ STRUCTDAT *st;
+ PVal *pval;
+ FlexValue *fv;
+
+ fv = (FlexValue *)HspVarCorePtrAPTR( in_pval, in_aptr );
+
+ if ( fv->type != FLEXVAL_TYPE_ALLOC ) return;
+
+ prm = &hspctx->mem_minfo[ fv->customid ];
+ st = &hspctx->mem_finfo[ prm->subid ];
+ p = (char *)fv->ptr;
+
+ if ( fv->clonetype == 0 ) {
+
+ //Alertf( "del:%d",st->otindex );
+ if ( st->otindex ) { // デストラクタを起動
+ modvar_init.magic = MODVAR_MAGICCODE;
+ modvar_init.subid = prm->subid;
+ modvar_init.pval = in_pval;
+ modvar_init.aptr = in_aptr;
+ code_callfunc( st->otindex );
+ }
+
+ for(i=0;iprmmax;i++) { // パラメーターを取得
+ out = p + prm->offset;
+ switch( prm->mptype ) {
+ case MPTYPE_LOCALVAR:
+ pval = (PVal *)out;
+ HspVarCoreDispose( pval );
+ break;
+ }
+ prm++;
+ }
+ }
+
+ //Alertf("STRUCT:BYE");
+ sbFree( fv->ptr );
+ fv->type = FLEXVAL_TYPE_NONE;
+}
+
+
+void code_delstruct_all( PVal *pval )
+{
+ // モジュール変数全体を破棄する
+ //
+ int i;
+ if ( pval->mode == HSPVAR_MODE_MALLOC ) {
+ for(i=0;ilen[1];i++) {
+ code_delstruct( pval, i );
+ }
+ }
+}
+
+
+char *code_stmp( int size )
+{
+ // stmp(文字列一時バッファ)を指定サイズで初期化する
+ //
+ if ( size > 1024 ) { hspctx->stmp = sbExpand( hspctx->stmp, size ); }
+ return hspctx->stmp;
+}
+
+
+char *code_stmpstr( char *src )
+{
+ // stmp(文字列一時バッファ)にsrcをコピーする
+ //
+ char *p;
+ p = code_stmp( (int)strlen( src ) + 1 );
+ strcpy( p, src );
+ return p;
+}
+
+
+char *code_getsptr( int *type )
+{
+ int fl;
+ char *bp;
+ if ( code_get() <= PARAM_END ) {
+ fl = HSPVAR_FLAG_INT;
+ sptr_res = 0;
+ bp = (char *)&sptr_res;
+ } else {
+ fl = mpval->flag;
+ bp = mpval->pt;
+ if (( fl != HSPVAR_FLAG_INT )&&( fl != HSPVAR_FLAG_STR )) {
+ throw HSPERR_TYPE_MISMATCH;
+ }
+ }
+ *type = fl;
+ return bp;
+}
+
+/*------------------------------------------------------------*/
+/*
+ type process function
+*/
+/*------------------------------------------------------------*/
+
+static int reffunc_intfunc_ivalue;
+
+/*
+ rev 43
+ mingw : warning : 有符号型と無符号型の比較
+ に対処
+*/
+#define ETRLOOP ((int)0x80000000)
+
+#define GETLOP(num) (&(hspctx->mem_loop[num]))
+
+static int cmdfunc_default( int cmd )
+{
+ // cmdfunc : default
+ //
+ int tmp;
+ if ( exflg & EXFLG_1 ) {
+ tmp = type;
+ code_next();
+ if (( tmp == TYPE_INTFUNC )||( tmp == TYPE_EXTSYSVAR )) throw HSPERR_FUNCTION_SYNTAX;
+ throw HSPERR_WRONG_NAME;
+ }
+ throw HSPERR_TOO_MANY_PARAMETERS;
+ return RUNMODE_ERROR;
+}
+
+
+static int cmdfunc_custom( int cmd )
+{
+ // custom command execute
+ //
+ STRUCTDAT *st;
+ code_next();
+
+ st = &hspctx->mem_finfo[cmd];
+ if ( st->index != STRUCTDAT_INDEX_FUNC ) throw HSPERR_SYNTAX;
+
+ return code_callfunc( cmd );
+}
+
+
+static void *reffunc_custom( int *type_res, int arg )
+{
+ // custom function execute
+ //
+ STRUCTDAT *st;
+ void *ptr;
+ int old_funcres;
+
+ // 返値のタイプを設定する
+ //
+ st = &hspctx->mem_finfo[arg];
+ if ( st->index != STRUCTDAT_INDEX_CFUNC ) throw HSPERR_SYNTAX;
+ old_funcres = funcres;
+ funcres = TYPE_ERROR;
+
+ // '('で始まるかを調べる
+ //
+ if ( type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( val != '(' ) throw HSPERR_INVALID_FUNCPARAM;
+
+ code_next();
+ code_callfunc( arg );
+
+ *type_res = funcres; // 返値のタイプを指定する
+ switch( funcres ) { // 返値のポインタを設定する
+ case TYPE_STRING:
+ ptr = hspctx->refstr;
+ break;
+ case TYPE_DNUM:
+ ptr = &hspctx->refdval;
+ break;
+ case TYPE_INUM:
+ ptr = &hspctx->stat;
+ break;
+ default:
+ if ( hspctx->runmode == RUNMODE_END ) {
+ throw HSPERR_NONE;
+ }
+ throw HSPERR_NORETVAL;
+ }
+
+ // ')'で終わるかを調べる
+ //
+ if ( type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( val != ')' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ funcres = old_funcres;
+ return ptr;
+}
+
+
+static int cmdfunc_var( int cmd )
+{
+ // cmdfunc : TYPE_VAR
+ // (変数代入 : 変数名が先頭に来る場合)
+ //
+ PVal *pval;
+ HspVarProc *proc;
+ APTR aptr;
+ void *ptr;
+ PDAT *dst;
+ int chk,exp,incval;
+ int baseaptr;
+
+#ifdef HSPDEBUG
+ if (( exflg & EXFLG_1 ) == 0 ) throw HSPERR_TOO_MANY_PARAMETERS;
+#endif
+
+ exflg = 0; // code_nextを使わない時に必要
+ aptr = code_getva( &pval ); // 変数を取得
+
+ if ( type != TYPE_MARK ) { mcs = mcsbak; throw HSPERR_SYNTAX; }
+ exp = val;
+ code_next(); // 次のコードへ
+
+ if ( exflg ) { // インクリメント(+)・デクリメント(-)
+ proc = HspVarCoreGetProc( pval->flag );
+ incval = 1;
+ if ( pval->flag == HSPVAR_FLAG_INT ) { ptr = &incval; } else {
+ ptr = (int *)proc->Cnv( &incval, HSPVAR_FLAG_INT ); // 型がINTでない場合は変換
+ }
+ dst = HspVarCorePtrAPTR( pval, aptr );
+ switch( exp ) {
+ case CALCCODE_ADD:
+ proc->AddI( dst, ptr );
+ break;
+ case CALCCODE_SUB:
+ proc->SubI( dst, ptr );
+ break;
+ default:
+ throw HSPERR_SYNTAX;
+ }
+ return RUNMODE_RUN;
+ }
+
+ chk = code_get(); // パラメーター値を取得
+ if ( chk != PARAM_OK ) { throw HSPERR_SYNTAX; }
+
+ proc = HspVarCoreGetProc( pval->flag );
+ dst = HspVarCorePtrAPTR( pval, aptr );
+ ptr = mpval->pt;
+ if ( exp == CALCCODE_EQ ) { // '='による代入
+ if ( pval->support & HSPVAR_SUPPORT_NOCONVERT ) { // 型変換なしの場合
+ if ( arrayobj_flag ) {
+ proc->ObjectWrite( pval, ptr, mpval->flag );
+ return RUNMODE_RUN;
+ }
+ }
+ if ( pval->flag != mpval->flag ) {
+ if ( aptr != 0 ) throw HSPERR_INVALID_ARRAYSTORE; // 型変更の場合は配列要素0のみ
+ HspVarCoreClear( pval, mpval->flag ); // 最小サイズのメモリを確保
+ proc = HspVarCoreGetProc( pval->flag );
+ dst = proc->GetPtr( pval ); // PDATポインタを取得
+ }
+ proc->Set( pval, dst, ptr );
+ if ( exflg ) return RUNMODE_RUN;
+
+ chk = pval->len[1];
+ if ( chk == 0 ) baseaptr = aptr; else baseaptr = aptr % chk;
+ aptr -= baseaptr;
+
+ while(1) {
+ if ( exflg ) break;
+ chk = code_get(); // パラメーター値を取得
+ if ( chk != PARAM_OK ) { throw HSPERR_SYNTAX; }
+ if ( pval->flag != mpval->flag ) {
+ throw HSPERR_INVALID_ARRAYSTORE; // 型変更はできない
+ }
+ ptr = mpval->pt;
+ baseaptr++;
+
+ pval->arraycnt = 0; // 配列指定カウンタをリセット
+ pval->offset = aptr;
+ code_arrayint2( pval, baseaptr ); // 配列チェック
+
+ dst = HspVarCorePtr( pval );
+ proc->Set( pval, dst, ptr ); // 次の配列にたたき込む
+ }
+ return RUNMODE_RUN;
+ }
+
+ // 変数+演算子による代入
+ //
+ if ( pval->flag != mpval->flag ) { // 型が一致しない場合は変換
+ ptr = HspVarCoreCnvPtr( mpval, pval->flag );
+ //ptr = proc->Cnv( ptr, mpval->flag );
+ }
+ calcprm( proc, dst, exp, ptr );
+ if ( proc->aftertype != pval->flag ) { // 演算後に型が変わる場合
+ throw HSPERR_TYPE_MISMATCH;
+ }
+ return RUNMODE_RUN;
+}
+
+
+static void cmdfunc_return_setval( void )
+{
+ // 引数をシステム変数にセットする(返値用)
+ //
+ if ( code_get() <= PARAM_END ) return;
+
+ hspctx->retval_level = hspctx->sublev;
+ funcres = mpval->flag;
+
+ switch( funcres ) {
+ case HSPVAR_FLAG_INT:
+ hspctx->stat = *(int *)mpval->pt;
+ break;
+ case HSPVAR_FLAG_STR:
+ sbStrCopy( &hspctx->refstr, mpval->pt );
+ break;
+ case HSPVAR_FLAG_DOUBLE:
+ hspctx->refdval = *(double *)mpval->pt;
+ break;
+ default:
+ throw HSPERR_TYPE_MISMATCH;
+ }
+}
+
+
+static int cmdfunc_ifcmd( int cmd )
+{
+ // 'if' command execute
+ //
+ int i;
+ unsigned short *mcstmp;
+ i=(int)*mcs;mcs++; // skip offset get
+ mcstmp=mcs+i;
+ if (val==0) { // 'if'
+ code_next(); // get first token
+ if ( code_geti() ) return RUNMODE_RUN; // if true
+ }
+ mcs=mcstmp;
+ code_next();
+ return RUNMODE_RUN;
+}
+
+
+static void cmdfunc_mref( PVal *pval, int prm )
+{
+ // mref command
+ //
+ int t,size;
+ char *out;
+ HSPEXINFO *exinfo;
+
+ if ( prm & 1024 ) throw HSPERR_UNSUPPORTED_FUNCTION;
+ if ( prm >= 0x40 ) {
+ exinfo = hspctx->exinfo2;
+ if ( exinfo->HspFunc_mref != NULL ) exinfo->HspFunc_mref( pval, prm );
+ return;
+ }
+ if (( prm & 0x30 )||( prm >= 8 )) throw HSPERR_UNSUPPORTED_FUNCTION;
+
+ out = ((char *)hspctx->prmstack );
+ if ( out == NULL ) throw HSPERR_ILLEGAL_FUNCTION;
+ t = HSPVAR_FLAG_INT; size = sizeof(int);
+ HspVarCoreDupPtr( pval, t, (out+(size*prm)), size );
+}
+
+
+static int cmdfunc_prog( int cmd )
+{
+ // cmdfunc : TYPE_PROGCMD
+ //
+
+ int p1,p2,p3,p4,p5;
+
+ code_next(); // 次のコードを取得(最初に必ず必要です)
+
+ switch( cmd ) { // サブコマンドごとの分岐
+
+ case 0x00: // goto
+ mcs = code_getlb();
+ code_next();
+ break;
+
+ case 0x01: // gosub
+#ifdef HSPEMSCRIPTEN
+ {
+ unsigned short *sbr;
+ sbr = code_getlb();
+ cmdfunc_gosub( sbr, mcs );
+ break;
+ }
+#else
+ {
+ unsigned short *sbr;
+ sbr = code_getlb();
+ return cmdfunc_gosub( sbr );
+ }
+#endif
+ case 0x02: // return
+#ifdef HSPEMSCRIPTEN
+ if ( hspctx->prmstack != NULL ) cmdfunc_return_setval();
+#else
+ if ( exflg == 0 ) cmdfunc_return_setval();
+#endif
+ //return cmdfunc_return();
+ hspctx->runmode = RUNMODE_RETURN;
+ return RUNMODE_RETURN;
+
+ case 0x03: // break
+ if (hspctx->looplev==0) throw HSPERR_LOOP_WITHOUT_REPEAT;
+ hspctx->looplev--;
+ mcs = code_getlb();
+ code_next();
+ break;
+
+ case 0x04: // repeat
+ {
+ LOOPDAT *lop;
+ unsigned short *label;
+ if (hspctx->looplev>=(HSP3_REPEAT_MAX-1)) throw HSPERR_TOO_MANY_NEST;
+ label = code_getlb();
+ code_next();
+ p1 = code_getdi( ETRLOOP );
+ p2 = code_getdi( 0 );
+ if ( p1==0 ) { // 0は即break
+ mcs=label;
+ code_next();
+ break;
+ }
+ if ( p1<0 ) p1=ETRLOOP; else p1+=p2;
+ hspctx->looplev++;
+ lop=GETLOP(hspctx->looplev);
+ lop->cnt = p2;
+ lop->time = p1;
+ lop->pt = mcsbak;
+ break;
+ }
+
+ case 0x05: // loop
+ {
+ LOOPDAT *lop;
+ if (hspctx->looplev==0) throw HSPERR_LOOP_WITHOUT_REPEAT;
+ lop=GETLOP(hspctx->looplev);
+ lop->cnt++;
+ if ( lop->time != ETRLOOP ) { // not eternal loop
+ if ( lop->cnt >= lop->time ) {
+ hspctx->looplev--;
+ break;
+ }
+ }
+ mcs=lop->pt;
+ code_next();
+ break;
+ }
+
+ case 0x06: // continue
+ {
+ LOOPDAT *lop;
+ unsigned short *label;
+ label = code_getlb();
+ lop=GETLOP(hspctx->looplev);
+ code_next();
+ p2=lop->cnt + 1;
+ p1 = code_getdi( p2 );
+ lop->cnt = p1 - 1;
+ mcs=label;
+ val=0x05;type=TYPE_PROGCMD;exflg=0; // set 'loop' code
+ break;
+ }
+
+ case 0x07: // wait
+ hspctx->waitcount = code_getdi( 100 );
+ hspctx->runmode = RUNMODE_WAIT;
+ return RUNMODE_WAIT;
+
+ case 0x08: // await
+ p1=code_getdi( 0 );
+ //p2=code_getdi( -1 );
+ hspctx->waitcount = p1;
+ hspctx->waittick = -1;
+ //if ( p2 > 0 ) hspctx->waitbase = p2;
+ hspctx->runmode = RUNMODE_AWAIT;
+ return RUNMODE_AWAIT;
+
+ case 0x09: // dim
+ case 0x0a: // sdim
+ case 0x0d: // dimtype
+ {
+ HspVarProc *proc;
+ PVal *pval;
+ int fl;
+ pval = code_getpval();
+ fl = TYPE_INUM;
+ if ( cmd == 0x0d ) {
+ fl = code_geti();
+ proc = HspVarCoreGetProc( fl );
+ if ( proc->flag == 0 ) throw HSPERR_ILLEGAL_FUNCTION;
+ }
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ p4 = code_getdi( 0 );
+ if ( cmd == 0x0a ) {
+ p5 = code_getdi( 0 );
+ HspVarCoreDimFlex( pval, TYPE_STRING, p1, p2, p3, p4, p5 );
+ //HspVarCoreAllocBlock( pval, HspVarCorePtrAPTR( pval, 0 ), p1 );
+ break;
+ }
+ HspVarCoreDim( pval, fl, p1, p2, p3, p4 );
+ break;
+ }
+
+ case 0x0b: // foreach
+ {
+ LOOPDAT *lop;
+ unsigned short *label;
+ if (hspctx->looplev>=(HSP3_REPEAT_MAX-1)) throw HSPERR_TOO_MANY_NEST;
+ label = code_getlb();
+ code_next();
+ hspctx->looplev++;
+ lop=GETLOP(hspctx->looplev);
+ lop->cnt = 0;
+ lop->time = ETRLOOP;
+ lop->pt = mcsbak;
+ break;
+ }
+ case 0x0c: // (hidden)foreach check
+ {
+ int i;
+ PVal *pval;
+ LOOPDAT *lop;
+ unsigned short *label;
+ if (hspctx->looplev==0) throw HSPERR_LOOP_WITHOUT_REPEAT;
+ label = code_getlb();
+ code_next();
+ lop=GETLOP(hspctx->looplev);
+
+ pval = code_getpval();
+ if ( lop->cnt >= pval->len[1] ) { // ループ終了
+ hspctx->looplev--;
+ mcs = label;
+ code_next();
+ break;
+ }
+ if ( pval->support & HSPVAR_SUPPORT_VARUSE ) {
+ i = HspVarCoreGetUsing( pval, HspVarCorePtrAPTR( pval, lop->cnt ) );
+ if ( i == 0 ) { // スキップ
+ mcs=label;
+ val=0x05;type=TYPE_PROGCMD;exflg=0; // set 'loop' code
+ }
+ }
+ break;
+ }
+ case 0x0e: // dup
+ {
+ PVal *pval_m;
+ PVal *pval;
+ APTR aptr;
+ pval_m = code_getpval();
+ aptr = code_getva( &pval );
+ HspVarCoreDup( pval_m, pval, aptr );
+ break;
+ }
+ case 0x0f: // dupptr
+ {
+ PVal *pval_m;
+ pval_m = code_getpval();
+ p1 = code_geti();
+ p2 = code_geti();
+ p3 = code_getdi( HSPVAR_FLAG_INT );
+ if ( p2<=0 ) throw HSPERR_ILLEGAL_FUNCTION;
+ if ( HspVarCoreGetProc(p3)->flag == 0 ) throw HSPERR_ILLEGAL_FUNCTION;
+ HspVarCoreDupPtr( pval_m, p3, (void *)p1, p2 );
+ break;
+ }
+
+ case 0x10: // end
+ hspctx->endcode = code_getdi(0);
+ hspctx->runmode = RUNMODE_END;
+ return RUNMODE_END;
+ case 0x1b: // assert
+ p1 = code_getdi( 0 );
+ if ( p1 ) break;
+ hspctx->runmode = RUNMODE_ASSERT;
+ return RUNMODE_ASSERT;
+ case 0x11: // stop
+ hspctx->runmode = RUNMODE_STOP;
+ return RUNMODE_STOP;
+
+ case 0x12: // newmod
+ case 0x13: // setmod
+ {
+ char *p;
+ PVal *pval;
+ APTR aptr;
+ FlexValue *fv;
+ STRUCTDAT *st;
+ STRUCTPRM *prm;
+ if ( cmd == 0x12 ) {
+ pval = code_getpval();
+ aptr = code_newstruct(pval);
+ }
+ else {
+ aptr = code_getva( &pval );
+ }
+ st = code_getstruct();
+ fv = code_setvs(pval, aptr, NULL, st->size, st->prmindex);
+ fv->type = FLEXVAL_TYPE_ALLOC;
+ p = sbAlloc( fv->size );
+ fv->ptr = (void *)p;
+ prm = &hspctx->mem_minfo[ st->prmindex ];
+ if ( prm->mptype != MPTYPE_STRUCTTAG ) throw HSPERR_STRUCT_REQUIRED;
+ code_expandstruct(p, st, CODE_EXPANDSTRUCT_OPT_NONE);
+ if (prm->offset != -1) {
+ modvar_init.magic = MODVAR_MAGICCODE;
+ modvar_init.subid = prm->subid;
+ modvar_init.pval = pval;
+ modvar_init.aptr = aptr;
+ return code_callfunc(prm->offset);
+ }
+ break;
+ }
+ case 0x14: // delmod
+ {
+ PVal *pval;
+ APTR aptr;
+ aptr = code_getva( &pval );
+ if ( pval->flag != TYPE_STRUCT ) throw HSPERR_TYPE_MISMATCH;
+ code_delstruct( pval, aptr );
+ break;
+ }
+/*
+ case 0x15: // alloc
+ {
+ PVal *pval;
+ pval = code_getpval();
+ p1 = code_getdi( 0 );
+ if ( p1 <= 64 ) p1 = 64;
+ HspVarCoreDim( pval, TYPE_STRING, 1, 0, 0, 0 );
+ HspVarCoreAllocBlock( pval, HspVarCorePtrAPTR( pval, 0 ), p1 );
+ break;
+ }
+*/
+ case 0x16: // mref
+ {
+ PVal *pval_m;
+ pval_m = code_getpval();
+ p1 = code_getdi(0);
+ cmdfunc_mref( pval_m, p1 );
+ break;
+ }
+ case 0x17: // run
+ sbStrCopy( &hspctx->refstr, code_gets() );
+ code_stmpstr( code_getds("") );
+ throw HSPERR_EXITRUN;
+
+ case 0x18: // exgoto
+ {
+ PVal *pval;
+ APTR aptr;
+ int *ival;
+ int i;
+ unsigned short *label;
+ aptr = code_getva( &pval );
+ if ( pval->flag != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH;
+ ival = (int *)HspVarCorePtrAPTR( pval, aptr );
+ p1=code_getdi( 0 );
+ p2=code_getdi( 0 );
+ label = code_getlb2();
+ i = 0;
+ if ( p1 >= 0 ) {
+ if ( (*ival) >= p2 ) i++;
+ } else {
+ if ( (*ival) <= p2 ) i++;
+ }
+ if ( i ) code_setpc( label);
+ break;
+ }
+
+ case 0x19: // on
+ {
+ unsigned short *label;
+ unsigned short *otbak;
+ p1=code_getdi( 0 );
+ if ( type != TYPE_PROGCMD ) throw HSPERR_SYNTAX;
+ if ( val >= 0x02 ) throw HSPERR_SYNTAX; // goto/gosub以外はエラー
+ p2 = 0; p3 = val; otbak = NULL;
+ code_next();
+ while( (exflg&EXFLG_1)==0 ) {
+ label = code_getlb2();
+ if ( p1 == p2 ) {
+ if ( p3 ) {
+ otbak = label; // on~gosub
+ } else {
+ code_setpc( label); // on~goto
+ break;
+ }
+ }
+ p2++;
+ }
+ if ( otbak != NULL ) {
+ code_call( otbak );
+ return hspctx->runmode;
+ }
+ break;
+ }
+
+ case 0x1a: // mcall
+ {
+ PVal *pval;
+ HspVarProc *varproc;
+ pval = code_getpval();
+ varproc = HspVarCoreGetProc( pval->flag );
+ varproc->ObjectMethod( pval );
+ break;
+ }
+ case 0x1c: // logmes
+ code_stmpstr( code_getdsi("") );
+ hspctx->runmode = RUNMODE_LOGMES;
+ return RUNMODE_LOGMES;
+
+ case 0x1d: // newlab
+ {
+ PVal *pval;
+ APTR aptr;
+ unsigned short *label;
+ int i;
+ aptr = code_getva( &pval );
+ label = NULL;
+ switch( type ) {
+ case TYPE_INUM:
+ i = code_geti();
+ if ( i == 0 ) label = mcsbak;
+ if ( i == 1 ) label = mcs;
+ break;
+ case TYPE_LABEL:
+ label = code_getlb2();
+ break;
+ default:
+ throw HSPERR_TYPE_MISMATCH;
+ }
+ code_setva( pval, aptr, HSPVAR_FLAG_LABEL, &label );
+ break;
+ }
+
+ case 0x1e: // resume
+ break;
+
+ case 0x1f: // yield
+ break;
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ return RUNMODE_RUN;
+}
+
+
+static void *reffunc_sysvar( int *type_res, int arg )
+{
+ // reffunc : TYPE_SYSVAR
+ // (内蔵システム変数)
+ //
+ void *ptr;
+
+ // 返値のタイプを設定する
+ //
+ *type_res = HSPVAR_FLAG_INT; // 返値のタイプを指定する
+ ptr = &reffunc_intfunc_ivalue; // 返値のポインタ
+
+ switch( arg ) {
+
+ // int function
+ case 0x000: // system
+ reffunc_intfunc_ivalue = 0;
+ break;
+ case 0x001: // hspstat
+ reffunc_intfunc_ivalue = hspctx->hspstat;
+ break;
+ case 0x002: // hspver
+ reffunc_intfunc_ivalue = vercode | mvscode;
+ break;
+ case 0x003: // stat
+ reffunc_intfunc_ivalue = hspctx->stat;
+ break;
+ case 0x004: // cnt
+ reffunc_intfunc_ivalue = hspctx->mem_loop[hspctx->looplev].cnt;
+ break;
+ case 0x005: // err
+ reffunc_intfunc_ivalue = hspctx->err;
+ break;
+ case 0x006: // strsize
+ reffunc_intfunc_ivalue = hspctx->strsize;
+ break;
+ case 0x007: // looplev
+ reffunc_intfunc_ivalue = hspctx->looplev;
+ break;
+ case 0x008: // sublev
+ reffunc_intfunc_ivalue = hspctx->sublev;
+ break;
+
+ case 0x009: // iparam
+ reffunc_intfunc_ivalue = hspctx->iparam;
+ break;
+ case 0x00a: // wparam
+ reffunc_intfunc_ivalue = hspctx->wparam;
+ break;
+ case 0x00b: // lparam
+ reffunc_intfunc_ivalue = hspctx->lparam;
+ break;
+ case 0x00c: // refstr
+ *type_res = HSPVAR_FLAG_STR;
+ ptr = (void *)hspctx->refstr;
+ break;
+ case 0x00d: // refdval
+ *type_res = HSPVAR_FLAG_DOUBLE;
+ ptr = (void *)&hspctx->refdval;
+ break;
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ return ptr;
+}
+
+
+
+/*------------------------------------------------------------*/
+/*
+ controller
+*/
+/*------------------------------------------------------------*/
+
+static void hsp3typeinit_var( HSP3TYPEINFO *info )
+{
+ info->cmdfunc = cmdfunc_var;
+}
+
+static void hsp3typeinit_prog( HSP3TYPEINFO *info )
+{
+ info->cmdfunc = cmdfunc_prog;
+}
+
+static void hsp3typeinit_ifcmd( HSP3TYPEINFO *info )
+{
+ info->cmdfunc = cmdfunc_ifcmd;
+}
+
+static void hsp3typeinit_sysvar( HSP3TYPEINFO *info )
+{
+ info->reffunc = reffunc_sysvar;
+}
+
+static void hsp3typeinit_custom( HSP3TYPEINFO *info )
+{
+ info->cmdfunc = cmdfunc_custom;
+ info->reffunc = reffunc_custom;
+}
+
+static void hsp3typeinit_default( int type )
+{
+ // typeinfoの初期化
+ HSP3TYPEINFO *info;
+ info = GetTypeInfoPtr( type );
+ info->type = type;
+ info->option = 0;
+ info->hspctx = hspctx;
+ info->hspexinfo = hspctx->exinfo2;
+ info->cmdfunc = cmdfunc_default;
+ info->reffunc = NULL;
+ info->termfunc = NULL;
+ info->eventfunc = NULL;
+}
+
+
+HSP3TYPEINFO *code_gettypeinfo( int type )
+{
+ // 指定されたタイプのHSP3TYPEINFO構造体を取得します。
+ // ( typeがマイナスの場合は、新規typeIDを発行 )
+ //
+ int id;
+ HSP3TYPEINFO *info;
+ id = type;
+ if ( id < 0 ) {
+ id = tinfo_cur++;
+ hsp3tinfo = (HSP3TYPEINFO *)sbExpand( (char *)hsp3tinfo, sizeof(HSP3TYPEINFO) * tinfo_cur );
+ hsp3typeinit_default( id );
+ }
+ info = GetTypeInfoPtr( id );
+ return info;
+}
+
+
+void code_setctx( HSPCTX *ctx )
+{
+ // HSPコンテキストを設定
+ //
+ hspctx = ctx;
+}
+
+
+void code_def_msgfunc(HSPCTX *ctx )
+{
+ // デフォルトのHSPメッセージコールバック
+ //
+ ctx->runmode = RUNMODE_END;
+}
+
+
+void code_resetctx( HSPCTX *ctx )
+{
+ // コンテキストのリセット(オブジェクトロード後の初期化)
+ //
+ mpval_int = HspVarCoreGetPVal(HSPVAR_FLAG_INT);
+ HspVarCoreClearTemp( mpval_int, HSPVAR_FLAG_INT ); // int型のテンポラリを初期化
+
+ ctx->err = HSPERR_NONE;
+#ifdef HSPDEBUG
+ ctx->hspstat = HSPSTAT_DEBUG;
+#else
+ ctx->hspstat = 0;
+#endif
+ ctx->waitbase = 5;
+ ctx->lasttick = 0;
+ ctx->looplev = 0;
+ ctx->sublev = 0;
+ ctx->stat = 0;
+ ctx->strsize = 0;
+ ctx->runmode = RUNMODE_RUN;
+ ctx->prmstack = NULL;
+ ctx->note_pval = NULL;
+ ctx->notep_pval = NULL;
+ ctx->msgfunc = code_def_msgfunc;
+}
+
+HSPCTX *code_getctx( void )
+{
+ return hspctx;
+}
+
+void code_enable_typeinfo( HSP3TYPEINFO *info )
+{
+ // typeinfoを有効にする(オプションチェック)
+ //
+ hspevent_opt |= info->option;
+}
+
+
+static HspVarProc *HspFunc_getproc( int id )
+{
+ return (&hspvarproc[id]);
+}
+
+
+HSPERROR code_geterror( void )
+{
+ return hspctx->err;
+}
+
+void code_setpc( const unsigned short *pc )
+{
+ // プログラムカウンタを設定
+ //
+ if ( hspctx->runmode == RUNMODE_END ) return;
+ mcs = (unsigned short *)pc;
+ code_next();
+ hspctx->runmode = RUNMODE_RUN;
+}
+
+void code_setpci( const unsigned short *pc )
+{
+ // プログラムカウンタを設定(interrput)
+ //
+ code_setpc( pc );
+ hspctx->runmode = RUNMODE_INTJUMP;
+}
+
+void code_call( const unsigned short *pc )
+{
+ // サブルーチンジャンプを行なう
+ //
+ mcs = mcsbak;
+#ifdef HSPEMSCRIPTEN
+ cmdfunc_gosub( (unsigned short *)pc, mcs );
+#else
+ cmdfunc_gosub( (unsigned short *)pc );
+#endif
+ if ( hspctx->runmode == RUNMODE_END ) return;
+ hspctx->runmode = RUNMODE_RUN;
+}
+
+unsigned short *code_getpcbak( void )
+{
+ //mcsbakを返す
+ return mcsbak;
+}
+
+//
+// Error report routines
+//
+int code_getdebug_line( void )
+{
+ return code_getdebug_line( mcsbak );
+}
+int code_getdebug_line( unsigned short* pt )
+{
+ // Get current debug line info
+ // (最後に実行した場所を示す)
+ // result : 0=none others=line#
+ //
+#ifdef HSPDEBUG
+ unsigned char *mem_di;
+ unsigned char ofs;
+ int cl,a,tmp,curpt,debpt;
+
+ mem_di = hspctx->mem_di;
+ debpt=0;
+ curpt = (int)( pt - hspctx->mem_mcs );
+ if ( mem_di[0]==255) return -1;
+
+ cl=0;a=0;
+ while(1) {
+ ofs=mem_di[a++];
+ switch( ofs ) {
+ case 252:
+ debpt+=(mem_di[a+1]<<8)+mem_di[a];
+ if (curpt<=debpt) return cl;
+ cl++;
+ a+=2;
+ break;
+ case 253:
+ a+=5;
+ break;
+ case 254:
+ tmp = (mem_di[a+2]<<16)+(mem_di[a+1]<<8)+mem_di[a];
+ if ( tmp ) srcname = tmp;
+ cl=(mem_di[a+4]<<8)+mem_di[a+3];
+ a+=5;
+ break;
+ case 255:
+ return -1;
+ default:
+ debpt+=ofs;
+ if (curpt<=debpt) return cl;
+ cl++;
+ break;
+ }
+ }
+ return cl;
+#else
+ return -1;
+#endif
+}
+
+
+int code_debug_init( void )
+{
+ // mem_di_valを更新
+ //
+ unsigned char ofs;
+ unsigned char *mem_di;
+ int cl,a;
+
+ cl=0;a=0;
+ mem_di_val = NULL;
+ mem_di = hspctx->mem_di;
+ if ( mem_di[0]==255) return -1;
+ while(1) {
+ ofs=mem_di[a++];
+ switch( ofs ) {
+ case 252:
+ a+=2;
+ break;
+ case 253:
+ mem_di_val=&mem_di[a-1];
+ return 0;
+ case 254:
+ cl=(mem_di[a+4]<<8)+mem_di[a+3];
+ a+=5;
+ break;
+ case 255:
+ return -1;
+ default:
+ cl++;
+ break;
+ }
+ }
+ return cl;
+}
+
+
+char *code_getdebug_varname( int val_id )
+{
+ unsigned char *mm;
+ int i;
+ if ( mem_di_val == NULL ) return "";
+ mm = mem_di_val + ( val_id * 6 );
+ i = (mm[3]<<16)+(mm[2]<<8)+mm[1];
+ return strp(i);
+}
+
+
+int code_getdebug_seekvar( const char *name )
+{
+ unsigned char *mm;
+ int i,ofs;
+ if ( mem_di_val != NULL ) {
+ mm = mem_di_val;
+ for(i=0;ihsphed->max_val;i++) {
+ ofs = (mm[3]<<16)+(mm[2]<<8)+mm[1];
+ if ( strcmp( strp( ofs ), name ) == 0 ) return i;
+ mm += 6;
+ }
+ }
+ return -1;
+}
+
+
+char *code_getdebug_name( void )
+{
+ return strp(srcname);
+}
+
+
+int code_exec_wait( int tick )
+{
+ // 時間待ち(wait)
+ // (awaitに変換します)
+ //
+ if ( hspctx->waitcount <= 0 ) {
+ hspctx->runmode = RUNMODE_RUN;
+ return RUNMODE_RUN;
+ }
+ hspctx->waittick = tick + ( hspctx->waitcount * 10 );
+ return RUNMODE_AWAIT;
+}
+
+
+int code_exec_await( int tick )
+{
+ // 時間待ち(await)
+ //
+ if ( hspctx->waittick < 0 ) {
+ if ( hspctx->lasttick == 0 ) hspctx->lasttick = tick;
+ hspctx->waittick = hspctx->lasttick + hspctx->waitcount;
+ }
+ if ( tick >= hspctx->waittick ) {
+ hspctx->lasttick = tick;
+ hspctx->runmode = RUNMODE_RUN;
+ return RUNMODE_RUN;
+ }
+ return RUNMODE_AWAIT;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ code main interface
+*/
+/*------------------------------------------------------------*/
+
+static int error_dummy = 0; // 2.61互換のためのダミー値
+
+static int code_cnv_get( void )
+{
+ // データを取得(プラグイン交換用)
+ //
+ hspctx->exinfo.mpval = &mpval;
+ return code_get();
+}
+
+static void *code_cnv_getv( void )
+{
+ // 変数データアドレスを取得(2.61互換用)
+ //
+ char *ptr;
+ int size;
+ ptr = code_getvptr( &plugin_pval, &size );
+ hspctx->exinfo.mpval = &plugin_pval;
+ return (void *)ptr;
+}
+
+static int code_cnv_realloc( PVal *pv, int size, int mode )
+{
+ // 変数データバッファを拡張(2.61互換用)
+ //
+ PDAT *ptr;
+ ptr = HspVarCorePtrAPTR( pv, 0 );
+ HspVarCoreAllocBlock( pv, ptr, size );
+ return 0;
+}
+
+void code_init( void )
+{
+ int i;
+ HSPEXINFO *exinfo;
+
+ sbInit(); // 可変メモリバッファ初期化
+ StackInit();
+ HspVarCoreInit(); // ストレージコア初期化
+ mpval = HspVarCoreGetPVal(0);
+ hspevent_opt = 0; // イベントオプションを初期化
+
+ // exinfoの初期化
+ //
+ exinfo = &mem_exinfo;
+
+ // 2.61互換フィールド
+ exinfo->ver = vercode;
+ exinfo->min = mvscode;
+ exinfo->er = &error_dummy;
+ exinfo->pstr = hspctx->stmp;
+ exinfo->stmp = hspctx->refstr;
+ exinfo->strsize = &hspctx->strsize;
+ exinfo->refstr = hspctx->refstr;
+ exinfo->HspFunc_prm_getv = code_cnv_getv;
+
+ exinfo->HspFunc_val_realloc = code_cnv_realloc;
+ exinfo->HspFunc_fread = dpm_read;
+ exinfo->HspFunc_fsize = dpm_exist;
+
+ // 共用フィールド
+ exinfo->nptype = &type;
+ exinfo->npval = &val;
+ exinfo->mpval = &mpval;
+
+ exinfo->HspFunc_prm_geti = code_geti;
+ exinfo->HspFunc_prm_getdi = code_getdi;
+ exinfo->HspFunc_prm_gets = code_getas;
+ exinfo->HspFunc_prm_getds = code_getads;
+ exinfo->HspFunc_getbmscr = NULL;
+ exinfo->HspFunc_addobj = NULL;
+ exinfo->HspFunc_setobj = NULL;
+ exinfo->HspFunc_setobj = NULL;
+
+ // 3.0拡張フィールド
+ exinfo->hspctx = hspctx;
+ exinfo->npexflg = &exflg;
+ exinfo->HspFunc_setobj = NULL;
+
+ exinfo->HspFunc_puterror = code_puterror;
+ exinfo->HspFunc_getproc = HspFunc_getproc;
+ exinfo->HspFunc_seekproc = HspVarCoreSeekProc;
+ exinfo->HspFunc_prm_next = code_next;
+ exinfo->HspFunc_prm_get = code_cnv_get;
+ exinfo->HspFunc_prm_getlb = code_getlb2;
+ exinfo->HspFunc_prm_getpval = code_getpval;
+ exinfo->HspFunc_prm_getva = code_getva;
+ exinfo->HspFunc_prm_setva = code_setva;
+ exinfo->HspFunc_prm_getd = code_getd;
+ exinfo->HspFunc_prm_getdd = code_getdd;
+
+ exinfo->HspFunc_malloc = sbAlloc;
+ exinfo->HspFunc_free = sbFree;
+ exinfo->HspFunc_expand = sbExpand;
+ exinfo->HspFunc_addirq = code_addirq;
+ exinfo->HspFunc_hspevent = code_event;
+ exinfo->HspFunc_registvar = HspVarCoreRegisterType;
+ exinfo->HspFunc_setpc = code_setpc;
+ exinfo->HspFunc_call = code_call;
+
+ exinfo->HspFunc_dim = HspVarCoreDimFlex;
+ exinfo->HspFunc_redim = HspVarCoreReDim;
+ exinfo->HspFunc_array = HspVarCoreArray;
+
+ // 3.1拡張フィールド
+ exinfo->HspFunc_varname = code_getdebug_varname;
+ exinfo->HspFunc_seekvar = code_getdebug_seekvar;
+
+ exinfo->HspFunc_prm_getns = code_gets;
+ exinfo->HspFunc_prm_getnds = code_getds;
+ // HSPCTXにコピーする
+ //
+ memcpy( &hspctx->exinfo, exinfo, sizeof(HSPEXINFO30) );
+ hspctx->exinfo2 = exinfo;
+
+ // 標準typefunc登録
+ //
+ hsp3tinfo = (HSP3TYPEINFO *)sbAlloc( sizeof(HSP3TYPEINFO) * HSP3_FUNC_MAX );
+ tinfo_cur = HSP3_FUNC_MAX;
+ for(i=0;imem_irq = NULL;
+ hspctx->irqmax = 0;
+ for(i=0;irefstr = sbAlloc( HSPCTX_REFSTR_MAX );
+ hspctx->fnbuffer = sbAlloc( HSP_MAX_PATH );
+ hspctx->stmp = sbAlloc( HSPCTX_REFSTR_MAX );
+ hspctx->cmdline = sbAlloc( HSPCTX_CMDLINE_MAX );
+
+#ifdef HSPDEBUG
+ // デバッグ情報の初期化
+ //
+ mem_di_val = NULL;
+ dbgmode = HSPDEBUG_NONE;
+ dbginfo.hspctx = hspctx;
+ dbginfo.line = 0;
+ dbginfo.fname = NULL;
+ dbginfo.get_value = code_dbgvalue;
+ dbginfo.get_varinf = code_dbgvarinf;
+ dbginfo.dbg_close = code_dbgclose;
+ dbginfo.dbg_curinf = code_dbgcurinf;
+ dbginfo.dbg_set = code_dbgset;
+ dbginfo.dbg_callstack = code_dbgcallstack;
+#endif
+
+}
+
+
+
+void code_termfunc( void )
+{
+ // コードの終了処理
+ //
+ int i;
+ int prmmax;
+ STRUCTDAT *st;
+ HSP3TYPEINFO *info;
+ PVal *pval;
+
+ // モジュール変数デストラクタ呼び出し
+ //
+#ifdef HSPERR_HANDLE
+ try {
+#endif
+ prmmax = hspctx->hsphed->max_val;
+ pval = hspctx->mem_var;
+ for(i=0;iflag == HSPVAR_FLAG_STRUCT ) code_delstruct_all( pval );
+ pval++;
+ }
+#ifdef HSPERR_HANDLE
+ }
+ catch( ... ) {
+ }
+#endif
+
+ // クリーンアップモジュールの呼び出し
+ //
+#ifdef HSPERR_HANDLE
+ try {
+#endif
+ prmmax = hspctx->hsphed->max_finfo / sizeof(STRUCTDAT);
+ i = prmmax;
+ while(1) {
+ i--; if ( i < 0 ) break;
+ st = &hspctx->mem_finfo[ i ];
+ if (( st->index == STRUCTDAT_INDEX_FUNC )&&( st->funcflag & STRUCTDAT_FUNCFLAG_CLEANUP )) {
+ code_callfunc( i );
+ }
+ }
+#ifdef HSPERR_HANDLE
+ }
+ catch( ... ) {
+ }
+#endif
+
+ // タイプの終了関数をすべて呼び出す
+ //
+ for(i=tinfo_cur-1;i>=0;i--) {
+ info = GetTypeInfoPtr( i );
+ if ( info->termfunc != NULL ) info->termfunc( 0 );
+ }
+
+}
+
+
+void code_bye( void )
+{
+ // コード実行を終了
+ //
+ HspVarCoreBye();
+
+ // コード用のメモリを解放する
+ //
+ if ( hspctx->mem_irq != NULL ) sbFree( hspctx->mem_irq );
+
+ sbFree( hspctx->cmdline );
+ sbFree( hspctx->stmp );
+ sbFree( hspctx->fnbuffer );
+ sbFree( hspctx->refstr );
+
+ sbFree( hsp3tinfo );
+ StackTerm();
+ sbBye();
+}
+
+
+int code_execcmd( void )
+{
+ // 命令実行メイン
+ //
+ int i;
+ hspctx->endcode = 0;
+
+rerun:
+ hspctx->looplev = 0;
+ hspctx->sublev = 0;
+ StackReset();
+
+#ifdef HSPERR_HANDLE
+ try {
+#endif
+#ifdef HSPEMSCRIPTEN
+ {
+#else
+ while(1) {
+#endif
+ //Alertf( "#%d,%d line%d",type,val,code_getdebug_line() );
+ //Alertf( "#%d,%d",type,val );
+ //printf( "#%d,%d line%d\n",type,val,code_getdebug_line() );
+ //stack->Reset();
+ //stack->StoreLevel();
+ //stack->ResumeLevel();
+
+#ifdef HSPDEBUG
+ if ( dbgmode ) code_dbgtrace(); // トレースモード時の処理
+#endif
+
+ if ( GetTypeInfoPtr( type )->cmdfunc( val ) ) { // タイプごとの関数振り分け
+ if ( hspctx->runmode == RUNMODE_RETURN ) {
+ cmdfunc_return();
+ } else {
+ hspctx->msgfunc( hspctx );
+ }
+ if ( hspctx->runmode == RUNMODE_END ) {
+ return RUNMODE_END;
+// i = hspctx->runmode;
+// break;
+ }
+ }
+#ifdef HSPEMSCRIPTEN
+ return RUNMODE_RUN;
+#else
+#endif
+ }
+#ifdef HSPERR_HANDLE
+ }
+
+ catch( HSPERROR code ) { // HSPエラー例外処理
+ if ( code == HSPERR_NONE ) {
+ i = RUNMODE_END;
+ } else if ( code == HSPERR_INTJUMP ) {
+ goto rerun;
+ } else if ( code == HSPERR_EXITRUN ) {
+ i = RUNMODE_EXITRUN;
+ } else {
+ i = RUNMODE_ERROR;
+ hspctx->err = code;
+ hspctx->runmode = i;
+ if ( code_isirq( HSPIRQ_ONERROR ) ) {
+ code_sendirq( HSPIRQ_ONERROR, 0, (int)code, code_getdebug_line() );
+ if ( hspctx->runmode != i ) goto rerun;
+ return i;
+ }
+ }
+ }
+#endif
+
+#ifdef SYSERR_HANDLE
+ catch( ... ) { // その他の例外発生時
+ hspctx->err = HSPERR_UNKNOWN_CODE;
+ return RUNMODE_ERROR;
+ }
+#endif
+ hspctx->runmode = i;
+ return i;
+}
+
+#ifdef HSPEMSCRIPTEN
+int code_execcmd_one( int& prev )
+{
+ // 命令実行メイン
+ //
+ int i;
+ hspctx->endcode = 0;
+
+rerun:
+ if (prev == 0) {
+ hspctx->looplev = 0;
+ hspctx->sublev = 0;
+ StackReset();
+ prev = 1;
+ }
+
+#ifdef HSPERR_HANDLE
+ try {
+#endif
+ {
+ //Alertf( "#%d,%d line%d",type,val,code_getdebug_line() );
+ //Alertf( "#%d,%d",type,val );
+ //printf( "#%d,%d line%d\n",type,val,code_getdebug_line() );
+ //stack->Reset();
+ //stack->StoreLevel();
+ //stack->ResumeLevel();
+
+#ifdef HSPDEBUG
+ if ( dbgmode ) code_dbgtrace(); // トレースモード時の処理
+#endif
+
+ if ( GetTypeInfoPtr( type )->cmdfunc( val ) ) { // タイプごとの関数振り分け
+ if ( hspctx->runmode == RUNMODE_RETURN ) {
+ cmdfunc_return();
+ } else {
+ hspctx->msgfunc( hspctx );
+ }
+ if ( hspctx->runmode == RUNMODE_END ) {
+ return RUNMODE_END;
+// i = hspctx->runmode;
+// break;
+ }
+ }
+ return RUNMODE_RUN;
+ }
+#ifdef HSPERR_HANDLE
+ }
+
+ catch( HSPERROR code ) { // HSPエラー例外処理
+ //printf( "#catch %d\n", code );
+ if ( code == HSPERR_NONE ) {
+ i = RUNMODE_END;
+ } else if ( code == HSPERR_INTJUMP ) {
+ goto rerun;
+ } else if ( code == HSPERR_EXITRUN ) {
+ i = RUNMODE_EXITRUN;
+ } else {
+ i = RUNMODE_ERROR;
+ hspctx->err = code;
+ hspctx->runmode = i;
+ if ( code_isirq( HSPIRQ_ONERROR ) ) {
+ code_sendirq( HSPIRQ_ONERROR, 0, (int)code, code_getdebug_line() );
+ if ( hspctx->runmode != i ) {
+ prev = 0;
+ return RUNMODE_RUN;
+ }
+ return i;
+ }
+ }
+ }
+#endif
+
+#ifdef SYSERR_HANDLE
+ catch( ... ) { // その他の例外発生時
+ hspctx->err = HSPERR_UNKNOWN_CODE;
+ return RUNMODE_ERROR;
+ }
+#endif
+ hspctx->runmode = i;
+ return i;
+}
+#endif
+
+int code_execcmd2( void )
+{
+ // 部分的な実行を行なう(ENDSESSION用)
+ //
+ while(1) {
+ if ( GetTypeInfoPtr( type )->cmdfunc( val ) ) { // タイプごとの関数振り分け
+ break;
+ }
+ }
+ return hspctx->runmode;
+}
+
+
+
+/*------------------------------------------------------------*/
+/*
+ EVENT controller
+*/
+/*------------------------------------------------------------*/
+
+static int call_eventfunc( int option, int event, int prm1, int prm2, void *prm3 )
+{
+ // 各タイプのイベントコールバックを呼び出す
+ //
+ int i,res;
+ HSP3TYPEINFO *info;
+ for( i=HSP3_TYPE_USER; ioption & option ) {
+ if ( info->eventfunc != NULL ) {
+ res = info->eventfunc( event, prm1, prm2, prm3 );
+ if ( res ) return res;
+ }
+ }
+ }
+ return 0;
+}
+
+
+static char *dirlist_target;
+static short evcategory[]={
+0, // HSPEVENT_NONE
+HSPEVENT_ENABLE_COMMAND, // HSPEVENT_COMMAND
+HSPEVENT_ENABLE_HSPIRQ, // HSPEVENT_HSPIRQ
+HSPEVENT_ENABLE_GETKEY, // HSPEVENT_GETKEY
+HSPEVENT_ENABLE_GETKEY, // HSPEVENT_STICK
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FNAME
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FREAD
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FWRITE
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FEXIST
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FDELETE
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FMKDIR
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FCHDIR
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FCOPY
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FDIRLIST1
+HSPEVENT_ENABLE_FILE, // HSPEVENT_FDIRLIST2
+HSPEVENT_ENABLE_PICLOAD, // HSPEVENT_GETPICSIZE
+HSPEVENT_ENABLE_PICLOAD, // HSPEVENT_PICLOAD
+};
+
+int code_event( int event, int prm1, int prm2, void *prm3 )
+{
+ // HSP内部イベント実行
+ // (result:0=Not care/1=Done)
+ //
+ int res;
+ res = call_eventfunc( evcategory[event], event, prm1, prm2, prm3 );
+ if ( res ) return res;
+
+ switch( event ) {
+ case HSPEVENT_COMMAND:
+ // All commands (type,val,n/a)
+ break;
+
+ case HSPEVENT_HSPIRQ:
+ // HSP Interrupt (IRQid,iparam,param_ptr)
+ code_execirq( (IRQDAT *)prm3, prm1, prm2 );
+ break;
+
+ case HSPEVENT_GETKEY:
+ // Key input (IDcode,option,resval ptr)
+ case HSPEVENT_STICK:
+ // Stick input (IDcode,option,resval ptr)
+ break;
+
+ case HSPEVENT_FNAME:
+ // set FNAME (n/a,n/a,nameptr)
+ strncpy( hspctx->fnbuffer, (char *)prm3, HSP_MAX_PATH-1 );
+#ifdef HSP3IMP
+ // HSP3IMP用セキュリティ対応
+ if ( SecurityCheck( hspctx->fnbuffer ) ) throw HSPERR_FILE_IO;
+#endif
+ break;
+ case HSPEVENT_FREAD:
+ // fread (fseek,size,loadptr)
+ res = dpm_read( hspctx->fnbuffer, prm3, prm2, prm1 );
+ if ( res < 0 ) throw HSPERR_FILE_IO;
+ hspctx->strsize = res;
+ break;
+ case HSPEVENT_FWRITE:
+ // fwrite (fseek,size,saveptr)
+ res = mem_save( hspctx->fnbuffer, prm3, prm2, prm1 );
+ if ( res < 0 ) throw HSPERR_FILE_IO;
+ hspctx->strsize = res;
+ break;
+ case HSPEVENT_FEXIST:
+ // exist (n/a,n/a,n/a)
+ hspctx->strsize = dpm_exist( hspctx->fnbuffer );
+ break;
+ case HSPEVENT_FDELETE:
+ // delete (n/a,n/a,n/a)
+#ifdef HSP3IMP
+ // HSP3IMP用セキュリティ対応
+ throw HSPERR_FILE_IO;
+#endif
+ if ( delfile( hspctx->fnbuffer ) == 0 ) throw HSPERR_FILE_IO;
+ break;
+ case HSPEVENT_FMKDIR:
+ // mkdir (n/a,n/a,n/a)
+ if ( makedir( hspctx->fnbuffer ) ) throw HSPERR_FILE_IO;
+ break;
+ case HSPEVENT_FCHDIR:
+ // chdir (n/a,n/a,n/a)
+ if ( changedir( hspctx->fnbuffer ) ) throw HSPERR_FILE_IO;
+ break;
+ case HSPEVENT_FCOPY:
+ // bcopy (n/a,n/a,dst filename)
+ if ( dpm_filecopy( hspctx->fnbuffer, (char *)prm3 ) ) throw HSPERR_FILE_IO;
+ break;
+ case HSPEVENT_FDIRLIST1:
+ // dirlist1 (opt,n/a,result ptr**)
+ {
+ char **p;
+ dirlist_target = sbAlloc( 0x1000 );
+ hspctx->stat = dirlist( hspctx->fnbuffer, &dirlist_target, prm1 );
+ p = (char **)prm3;
+ *p = dirlist_target;
+ break;
+ }
+ case HSPEVENT_FDIRLIST2:
+ // dirlist2 (n/a,n/a,n/a)
+ sbFree( dirlist_target );
+ break;
+
+ case HSPEVENT_GETPICSIZE:
+ // getpicsize (n/a,n/a,resval ptr)
+ break;
+ case HSPEVENT_PICLOAD:
+ // picload (n/a,n/a,HDC)
+ break;
+
+ }
+ return 0;
+}
+
+
+void code_bload( char *fname, int ofs, int size, void *ptr )
+{
+ code_event( HSPEVENT_FNAME, 0, 0, fname );
+ code_event( HSPEVENT_FREAD, ofs, size, ptr );
+}
+
+
+void code_bsave( char *fname, int ofs, int size, void *ptr )
+{
+ code_event( HSPEVENT_FNAME, 0, 0, fname );
+ code_event( HSPEVENT_FWRITE, ofs, size, ptr );
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ IRQ controller
+*/
+/*------------------------------------------------------------*/
+
+IRQDAT *code_getirq( int id )
+{
+ return &hspctx->mem_irq[ id ];
+}
+
+
+void code_enableirq( int id, int sw )
+{
+ // IRQの有効・無効切り替え
+ //
+ IRQDAT *irq;
+ irq = code_getirq( id );
+ if ( sw == 0 ) {
+ irq->flag = IRQ_FLAG_DISABLE;
+ return;
+ }
+
+ if ( id != HSPIRQ_USERDEF ) {
+ if (( irq->opt == IRQ_OPT_CALLBACK && irq->callback == NULL)||
+ ( irq->opt != IRQ_OPT_CALLBACK && irq->ptr == NULL)) {
+ return;
+ }
+ }
+ irq->flag = IRQ_FLAG_ENABLE;
+}
+
+
+void code_setirq( int id, int opt, int custom, unsigned short *ptr )
+{
+ // IRQイベントを設定する
+ //
+ IRQDAT *irq;
+ irq = code_getirq( id );
+ irq->flag = IRQ_FLAG_ENABLE;
+ irq->opt = opt;
+ irq->ptr = ptr;
+ irq->custom = custom;
+}
+
+
+int code_isirq( int id )
+{
+ // 指定したIRQイベントがENABLEかを調べる
+ //
+ if ( hspctx->mem_irq[ id ].flag != IRQ_FLAG_ENABLE ) return 0;
+ return 1;
+}
+
+
+int code_sendirq( int id, int iparam, int wparam, int lparam )
+{
+ // 指定したIRQイベントを発生
+ //
+ IRQDAT *irq;
+ irq = code_getirq( id );
+ irq->iparam = iparam;
+ code_event( HSPEVENT_HSPIRQ, wparam, lparam, irq );
+ return hspctx->runmode;
+}
+
+
+int code_isuserirq( void )
+{
+ // カスタム指定のIRQイベントがあるかどうか調べる
+ //
+ if ( hspctx->irqmax > HSPIRQ_USERDEF ) {
+ if ( hspctx->mem_irq[ HSPIRQ_USERDEF ].flag == IRQ_FLAG_ENABLE ) return 1;
+ }
+ return 0;
+}
+
+
+int code_irqresult( int *value )
+{
+ // IRQイベントの戻り値を取得する
+ //
+ *value = ( hspctx->stat );
+ return ( hspctx->retval_level );
+}
+
+
+int code_checkirq( int id, int message, int wparam, int lparam )
+{
+ // 指定したメッセージに対応するイベントを発生
+ //
+ int i,cur;
+ IRQDAT *irq;
+ for( i=HSPIRQ_MAX; iirqmax; i++ ) {
+ irq = &hspctx->mem_irq[ i ];
+ if ( irq->custom == message ) {
+ if ( irq->custom2 == id ) {
+ if ( irq->flag == IRQ_FLAG_ENABLE ) {
+ hspctx->intwnd_id = id;
+ hspctx->retval_level = 0;
+ cur = hspctx->sublev + 1;
+ if ( irq->callback != NULL ) {
+ irq->callback( irq, wparam, lparam );
+ } else {
+ code_sendirq( i, irq->custom, wparam, lparam );
+ if ( hspctx->retval_level != cur ) return 0; // returnの戻り値がなければ0を返す
+ }
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+IRQDAT *code_seekirq( int actid, int custom )
+{
+ // 指定したcustomを持つIRQを検索する
+ //
+ int i;
+ IRQDAT *irq;
+ for( i=0; iirqmax; i++ ) {
+ irq = code_getirq( i );
+ if ( irq->flag != IRQ_FLAG_NONE ) {
+ if (( irq->custom == custom )&&( irq->custom2 == actid )) {
+ if ( irq->opt != IRQ_OPT_CALLBACK ) return irq;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+IRQDAT *code_addirq( void )
+{
+ // IRQを追加する
+ //
+ int id;
+ IRQDAT *irq;
+ id = hspctx->irqmax++;
+ if ( hspctx->mem_irq == NULL) {
+ hspctx->mem_irq = (IRQDAT *)sbAlloc( sizeof(IRQDAT) );
+ } else {
+ hspctx->mem_irq = (IRQDAT *)sbExpand( (char *)hspctx->mem_irq, sizeof(IRQDAT) * (hspctx->irqmax) );
+ }
+ irq = code_getirq( id );
+ irq->flag = IRQ_FLAG_DISABLE;
+ irq->opt = IRQ_OPT_GOTO;
+ irq->custom = -1;
+ irq->iparam = 0;
+ irq->ptr = NULL;
+ irq->callback = NULL;
+ return irq;
+}
+
+
+void code_execirq( IRQDAT *irq, int wparam, int lparam )
+{
+ // IRQを実行する
+ //
+ hspctx->iparam = irq->iparam;
+ hspctx->wparam = wparam;
+ hspctx->lparam = lparam;
+ if ( irq->opt == IRQ_OPT_GOTO ) {
+ code_setpci( irq->ptr );
+ }
+ if ( irq->opt == IRQ_OPT_GOSUB ) {
+ mcs = mcsbak;
+#ifdef HSPEMSCRIPTEN
+ code_call( irq->ptr );
+#else
+ cmdfunc_gosub( (unsigned short *)irq->ptr );
+ if ( hspctx->runmode != RUNMODE_END ) {
+ hspctx->runmode = RUNMODE_RUN;
+ }
+#endif
+ }
+ //Alertf("sublev%d", hspctx->sublev );
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ Debug support
+*/
+/*------------------------------------------------------------*/
+
+#ifdef HSPDEBUG
+
+int code_getdbgmode( void )
+{
+ return dbgmode;
+}
+
+static char *dbgbuf;
+
+/*
+ rev 49
+ BT#190: return命令へ長い文字列を指定するとメモリアクセス違反が起こる
+ に対処。
+
+ 実際はデバッグウィンドウで変数内容以外の長い文字列を表示するとバッファオーバーフローが起きていた。
+*/
+
+static void code_adddbg3( char const * s1, char const * sep, char const * s2 )
+{
+ char tmp[ 2048 ];
+ strncpy( tmp, s1, 64 );
+ strncat( tmp, sep, 8 );
+ strncat( tmp, s2, 1973 );
+ strcat( tmp, "\r\n" );
+ sbStrAdd( &dbgbuf, tmp );
+}
+
+
+void code_adddbg( char * name, char * str )
+{
+ code_adddbg3( name, "\r\n", str );
+}
+
+
+void code_adddbg2( char * name, char * str )
+{
+ code_adddbg3( name, ":", str );
+}
+
+
+void code_adddbg( char *name, double val )
+{
+ char tmp[ 400 ];
+ sprintf( tmp, "%-36.16f", val );
+ code_adddbg( name, tmp );
+}
+
+
+void code_adddbg( char *name, int val )
+{
+ char tmp[32];
+#ifdef HSPWIN
+ _itoa( val, tmp, 10 );
+#else
+ sprintf( tmp, "%d", val);
+#endif
+ code_adddbg( name, tmp );
+}
+
+
+void code_adddbg2( char *name, int val )
+{
+ char tmp[32];
+#ifdef HSPWIN
+ _itoa( val, tmp, 10 );
+#else
+ sprintf( tmp, "%d", val);
+#endif
+ code_adddbg2( name, tmp );
+}
+
+
+char *code_inidbg( void )
+{
+ dbgbuf = sbAlloc( 0x4000 );
+ return dbgbuf;
+}
+
+
+void code_dbg_global( void )
+{
+ HSPHED *hed;
+ hed = hspctx->hsphed;
+ code_adddbg( "axサイズ", hed->allsize );
+ code_adddbg( "コードサイズ", hed->max_cs );
+ code_adddbg( "データサイズ", hed->max_ds );
+ code_adddbg( "変数予約", hed->max_val );
+ code_adddbg( "実行モード", hspctx->runmode );
+ code_adddbg( "stat", hspctx->stat );
+ code_adddbg( "cnt", hspctx->mem_loop[hspctx->looplev].cnt );
+ code_adddbg( "looplev", hspctx->looplev );
+ code_adddbg( "sublev", hspctx->sublev );
+ code_adddbg( "iparam", hspctx->iparam );
+ code_adddbg( "wparam", hspctx->wparam );
+ code_adddbg( "lparam", hspctx->lparam );
+ code_adddbg( "refstr", hspctx->refstr );
+ code_adddbg( "refdval", hspctx->refdval );
+}
+
+
+/*
+ rev 53
+ 書き直し。
+*/
+
+static void code_dbgdump( char const * mem, int size )
+{
+ // memory Hex dump
+ //
+ int adr = 0;
+ char t[ 512 ];
+ char tline[ 1024 ];
+ while ( adr < size ) {
+ sprintf( tline, "%04X", adr );
+ for ( int i = 0; i < 8 && adr < size; ++i, ++adr ) {
+ sprintf( t, " %02X", static_cast< unsigned char >( mem[ adr ] ) );
+ strcat( tline, t );
+ }
+ strcat( tline, "\r\n" );
+ sbStrAdd( &dbgbuf, tline );
+ }
+}
+
+
+static void code_dbgvarinf_ext( PVal *pv, void *src, char *buf )
+{
+ // 特殊な変数の内容を取得
+ // (256bytes程度のバッファを確保しておいて下さい)
+ //
+ switch( pv->flag ) {
+ case HSPVAR_FLAG_LABEL:
+ sprintf( buf,"LABEL $%p", *(void **)src );
+ break;
+ case HSPVAR_FLAG_STRUCT:
+ {
+ FlexValue *fv;
+ fv = (FlexValue *)src;
+ if ( fv->type == FLEXVAL_TYPE_NONE ) {
+ sprintf( buf,"STRUCT (Empty)" );
+ } else {
+ sprintf( buf,"STRUCT ID%d-%d PTR$%p SIZE%d(%d)", fv->myid, fv->customid, (void *)(fv->ptr), fv->size, fv->type );
+ }
+ break;
+ }
+#ifndef HSP_COM_UNSUPPORTED
+ case HSPVAR_FLAG_COMSTRUCT:
+ sprintf( buf,"COMPTR $%p", *(void **)src );
+ break;
+#endif
+ default:
+ strcpy( buf, "Unknown" );
+ break;
+ }
+}
+
+
+static void code_arraydump( PVal *pv )
+{
+ // variable array dump
+ //
+ char t[512];
+ PDAT *src;
+ char *p;
+ int ofs;
+ int amax;
+ int ok;
+
+ amax = pv->len[1];
+ if ( amax <= 1 ) return;
+ if ( amax > 16 ) {
+ sbStrAdd( &dbgbuf, "(配列の一部だけを表示)\r\n" );
+ amax = 16;
+ }
+
+ for(ofs=0;ofsflag, HSPVAR_FLAG_STR, src );
+ } catch(...) {
+ char tmpbuf[256];
+ code_dbgvarinf_ext( pv, src, tmpbuf );
+ sprintf( t,"(%d)=%s\r\n", ofs, tmpbuf );
+ ok = 0;
+ }
+ if ( ok ) {
+ if ( strlen(p) > 63 ) {
+ strncpy( hspctx->stmp, p, 63 );
+ hspctx->stmp[64]=0;
+ p = hspctx->stmp;
+ }
+ sprintf( t,"(%d)=%s\r\n", ofs, p );
+ }
+ sbStrAdd( &dbgbuf, t );
+ }
+}
+
+
+char *code_dbgvarinf( char *target, int option )
+{
+ // 変数情報取得
+ // option
+ // bit0 : sort ( 受け側で処理 )
+ // bit1 : module
+ // bit2 : array
+ // bit3 : dump
+ //
+ int i,id,max;
+ char *name;
+ HspVarProc *proc;
+ PVal *pv;
+ PDAT *src;
+ char *p;
+ char *padr;
+ char tmp[256];
+ int size;
+ int orgsize;
+
+ code_inidbg();
+ max = hspctx->hsphed->max_val;
+
+ if ( target == NULL ) {
+ for(i=0;i= max ) break;
+ name = code_getdebug_varname(id);
+ if ( strcmp( name, target ) == 0 ) break;
+ id++;
+ }
+
+ pv = &hspctx->mem_var[id];
+ proc = HspVarCoreGetProc(pv->flag);
+ code_adddbg2( "変数名", name );
+ code_adddbg2( "型", proc->vartype_name );
+ sprintf( tmp, "(%d,%d,%d,%d)",pv->len[1],pv->len[2],pv->len[3],pv->len[4] );
+ code_adddbg2( "配列", tmp );
+ code_adddbg2( "モード", pv->mode );
+ code_adddbg2( "使用サイズ", pv->size );
+
+ HspVarCoreReset( pv );
+ src = proc->GetPtr( pv );
+ padr = (char *)proc->GetBlockSize( pv, src, &size );
+ code_adddbg2( "バッファサイズ", size );
+
+ switch( pv->flag ) {
+ case HSPVAR_FLAG_STR:
+ case HSPVAR_FLAG_DOUBLE:
+ case HSPVAR_FLAG_INT:
+ if ( pv->flag != HSPVAR_FLAG_STR ) {
+ p = (char *)HspVarCoreCnv( pv->flag, HSPVAR_FLAG_STR, src );
+ } else {
+ p = padr;
+ }
+ orgsize = (int)strlen(p);
+ if ( orgsize >= 1024 ) {
+ strncpy( hspctx->stmp, p, 1023 );
+ p = hspctx->stmp; p[1023] = 0;
+ sprintf( tmp, "(内容%dbytesの一部を表示しています)\r\n",orgsize );
+ sbStrAdd( &dbgbuf, tmp );
+ }
+ code_adddbg( "内容:", p );
+ break;
+ case HSPVAR_FLAG_LABEL:
+ default:
+ {
+ char tmpbuf[256];
+ code_dbgvarinf_ext( pv, src, tmpbuf );
+ code_adddbg( "内容:", tmpbuf );
+ break;
+ }
+ }
+
+ if ( option & 4 ) {
+ code_arraydump( pv );
+ }
+ if ( option & 8 ) {
+ if ( size > 0x1000 ) size = 0x1000;
+ code_dbgdump( padr, size );
+ }
+
+
+ return dbgbuf;
+}
+
+
+void code_dbgcurinf( void )
+{
+ unsigned short *bak;
+ bak = mcsbak;
+ mcsbak = mcs;
+ dbginfo.line = code_getdebug_line();
+ dbginfo.fname = code_getdebug_name();
+ mcsbak = bak;
+}
+
+
+void code_dbgclose( char *buf )
+{
+ sbFree( dbgbuf );
+}
+
+
+HSP3DEBUG *code_getdbg( void )
+{
+ return &dbginfo;
+}
+
+
+char *code_dbgvalue( int type )
+{
+ // ダミー用関数
+ return code_inidbg();
+}
+
+
+int code_dbgset( int id )
+{
+ // デバッグモード設定
+ //
+ switch( hspctx->runmode ) {
+ case RUNMODE_STOP:
+ if ( id != HSPDEBUG_STOP ) {
+ hspctx->runmode = RUNMODE_RUN;
+ if ( id == HSPDEBUG_RUN ) {
+ dbgmode = HSPDEBUG_NONE;
+ } else {
+ dbgmode = id;
+ }
+ return 0;
+ }
+ break;
+ case RUNMODE_WAIT:
+ case RUNMODE_AWAIT:
+ if ( id == HSPDEBUG_STOP ) {
+ hspctx->runmode = RUNMODE_STOP;
+ dbgmode = HSPDEBUG_NONE;
+ return 0;
+ }
+ break;
+ }
+ return -1;
+}
+
+char *code_dbgcallstack( void )
+{
+ STMDATA* it;
+ HSPROUTINE* routine;
+ int line;
+
+ char tmp[HSP_MAX_PATH + 5 + 1];
+
+ code_inidbg();
+
+ for (it = mem_stm; it != stm_cur; it++)
+ {
+ if (it->type == TYPE_EX_SUBROUTINE ||
+ it->type == TYPE_EX_CUSTOMFUNC)
+ {
+ routine = (HSPROUTINE *)STM_GETPTR(it);
+
+ line = code_getdebug_line(routine->mcsret);
+ sprintf(tmp, "%s:%4d\r\n", code_getdebug_name(), line);
+ sbStrAdd(&dbgbuf, tmp);
+ }
+ }
+
+ return dbgbuf;
+}
+
+void code_dbgtrace( void )
+{
+ // トレース処理
+ //
+ int i;
+ i = dbginfo.line;
+ code_dbgcurinf();
+ if ( i != dbginfo.line ) {
+ hspctx->runmode = RUNMODE_STOP;
+ hspctx->msgfunc( hspctx );
+ }
+}
+
+#endif
+
+
diff --git a/src/hsp3/hsp3code.h b/src/hsp3/hsp3code.h
new file mode 100644
index 0000000000000000000000000000000000000000..007c592674af5464e0c8212aef12c9b1431a2ce8
--- /dev/null
+++ b/src/hsp3/hsp3code.h
@@ -0,0 +1,117 @@
+
+//
+// hsp3code.cpp header
+//
+#ifndef HSP3OCDE_H
+#define HSP3CODE_H
+
+#include "hsp3debug.h"
+#include "hsp3struct.h"
+
+extern PVal *mpval;
+
+void code_init( void );
+void code_bye( void );
+void code_termfunc( void );
+void code_setctx( HSPCTX *ctx );
+void code_resetctx( HSPCTX *ctx );
+HSPCTX *code_getctx( void );
+void code_setpc( const unsigned short *pc );
+void code_setpci( const unsigned short *pc );
+void code_call( const unsigned short *pc );
+void cmdfunc_return( void );
+unsigned short *code_getpcbak( void );
+
+int code_execcmd( void );
+int code_execcmd2( void );
+int code_exec_wait( int tick );
+int code_exec_await( int tick );
+
+HSPERROR code_geterror( void );
+void code_puterror( HSPERROR error );
+
+void code_next( void );
+int code_get( void );
+int code_getexflg( void );
+
+char *code_gets( void );
+char *code_getds( const char *defval );
+char *code_getdsi( const char *defval );
+int code_geti( void );
+int code_getdi( const int defval );
+double code_getd( void );
+double code_getdd( const double defval );
+PVal *code_getpval( void );
+char *code_getvptr( PVal **pval, int *size );
+
+APTR code_getva( PVal **pval );
+void code_setva( PVal *pval, APTR aptr, int type, const void *ptr );
+//PDAT *code_getv( PVal **pval );
+//void code_setv( PVal *pval, PDAT *dat, int type, void *ptr );
+
+unsigned short *code_getlb( void );
+unsigned short *code_getlb2( void );
+
+STRUCTDAT *code_getstruct( void );
+STRUCTPRM *code_getstprm( void );
+STRUCTDAT *code_getcomst( void );
+char *code_get_proxyvar( char *ptr, int *mptype );
+APTR code_getv_proxy( PVal **pval, MPVarData *var, int mptype );
+
+#define CODE_EXPANDSTRUCT_OPT_NONE 0
+#define CODE_EXPANDSTRUCT_OPT_LOCALVAR 1
+
+void code_expandstruct( char *p, STRUCTDAT *st, int option );
+void code_setvs( PVal *pval, APTR aptr, int type, void *ptr, int size, int subid );
+
+char *code_stmpstr( char *src );
+char *code_stmp( int size );
+char *code_getsptr( int *type );
+
+int code_debug_init( void );
+int code_getdebug_line( void );
+int code_getdebug_line( unsigned short *pt );
+char *code_getdebug_name( void );
+int code_getdebug_seekvar( const char *name );
+char *code_getdebug_varname( int val_id );
+
+int code_event( int event, int prm1, int prm2, void *prm3 );
+void code_bload( char *fname, int ofs, int size, void *ptr );
+void code_bsave( char *fname, int ofs, int size, void *ptr );
+
+IRQDAT *code_getirq( int id );
+IRQDAT *code_seekirq( int actid, int custom );
+IRQDAT *code_addirq( void );
+int code_isirq( int id );
+int code_isuserirq( void );
+int code_sendirq( int id, int iparam, int wparam, int lparam );
+int code_checkirq( int id, int message, int wparam, int lparam );
+void code_execirq( IRQDAT *irq, int wparam, int lparam );
+void code_setirq( int id, int opt, int custom, unsigned short *ptr );
+int code_irqresult( int *value );
+void code_enableirq( int id, int sw );
+
+HSP3TYPEINFO *code_gettypeinfo( int type );
+void code_enable_typeinfo( HSP3TYPEINFO *info );
+
+int code_getdbgmode( void );
+HSP3DEBUG *code_getdbg( void );
+char *code_inidbg( void );
+void code_adddbg( char *name, int val );
+void code_adddbg( char *name, char *str );
+
+void code_dbg_global( void );
+char *code_dbgvalue( int type );
+char *code_dbgvarinf( char *target, int option );
+void code_dbgcurinf( void );
+void code_dbgclose( char *buf );
+int code_dbgset( int id );
+char *code_dbgcallstack( void );
+void code_dbgtrace( void );
+
+void code_delstruct( PVal *in_pval, APTR in_aptr );
+void code_delstruct_all( PVal *pval );
+
+#define fpconv( fp ) ( reinterpret_cast< void * >(fp) )
+
+#endif
diff --git a/src/hsp3/hsp3config.h b/src/hsp3/hsp3config.h
new file mode 100644
index 0000000000000000000000000000000000000000..33d77af8150fcfa5facea624511e4a6fcb52de69
--- /dev/null
+++ b/src/hsp3/hsp3config.h
@@ -0,0 +1,105 @@
+
+//
+// Configure for HSP3
+//
+#ifndef __hsp3config_h
+#define __hsp3config_h
+
+// システム関連ラベル
+//
+#define HSPTITLE "Hot Soup Processor ver."
+#define hspver "3.5"
+#define mvscode 7 // minor version code
+#define vercode 0x3507 // version code
+
+#define HSPERR_HANDLE // HSPエラー例外を有効にします
+#define SYSERR_HANDLE // システムエラー例外を有効にします
+
+
+//
+// 移植用のラベル
+//
+//#define JPN // IME use flag
+//#define JPNMSG // japanese message flag
+
+//
+// Debug mode functions
+//
+#define HSPDEBUGLOG // Debug Log Version
+
+// Debug Window Message Buffer Size
+//
+#define dbsel_size 0x10000
+#define dbmes_size 0x10000
+
+//
+// 環境フラグ:以下のラベルはコンパイルオプションで設定されます
+//
+//#define HSPWIN // Windows(WIN32) version flag
+//#define HSPMAC // Macintosh version flag
+//#define HSPLINUX // Linux(CLI) version flag
+//#define HSPIOS // iOS version flag
+//#define HSPNDK // android NDK version flag
+//#define HSPDISH // HSP3Dish flag
+//#define HSPDISHGP // HSP3Dish(HGIMG4) flag
+//#define HSPEMBED // HSP3 Embed runtime flag
+//#define HSPEMSCRIPTEN // EMSCRIPTEN version flag
+//#define HSP64 // 64bit compile flag
+//#define HSPUTF8 // UTF8使用フラグ
+
+//
+// 環境フラグに付加されるオプション
+//
+//#define HSPWINGUI // Windows/GUI (WIN32) version flag
+//#define HSPWINDISH // Windows/DISH (WIN32) version flag
+//#define HSPLINUXGUI // Linux(GUI) version flag
+
+//#define HSPDEBUG // Debug version flag
+
+// HSPが使用する実数型
+//
+#define HSPREAL double
+
+// HSPが使用する64bit整数値型
+//
+#ifdef HSP64
+#define HSPLPTR long
+#else
+#define HSPLPTR int
+#endif
+
+
+//
+// gcc使用のチェック
+//
+#if defined(HSPMAC)|defined(HSPIOS)|defined(HSPNDK)|defined(HSPLINUX)|defined(HSPEMSCRIPTEN)
+#define HSPGCC // GCC使用フラグ
+#define HSPUTF8 // UTF8使用フラグ
+#endif
+
+#if defined(HSPEMSCRIPTEN)
+#define HSPRANDMT // Use std::mt19937
+#endif
+
+#if defined(HSPLINUX)|defined(HSPEMSCRIPTEN)
+#define HSP_ALIGN_DOUBLE __attribute__ ((aligned (8)))
+#else
+#define HSP_ALIGN_DOUBLE
+#endif
+
+//
+// 移植用の定数
+//
+#ifdef HSPWIN
+#define HSP_MAX_PATH 260
+#define HSP_PATH_SEPARATOR '\\'
+#endif
+#ifdef HSPGCC
+#define HSP_MAX_PATH 256
+#define HSP_PATH_SEPARATOR '/'
+#endif
+#ifdef HSPLINUX
+#undef JPNMSG
+#endif
+
+#endif
diff --git a/src/hsp3/hsp3debug.cpp b/src/hsp3/hsp3debug.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f11696930b4e899e0896558ce6658974b09e7176
--- /dev/null
+++ b/src/hsp3/hsp3debug.cpp
@@ -0,0 +1,145 @@
+
+//
+// HSP3 debug support
+// (エラー処理およびデバッグ支援)
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+#include "hsp3config.h"
+#include "hsp3debug.h"
+#include "supio.h"
+
+/*------------------------------------------------------------*/
+/*
+ system data
+*/
+/*------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+#ifdef HSPDEBUG
+#ifdef JPNMSG
+static char *err[]={
+ "", // 0
+ "システムエラーが発生しました", // 1
+ "文法が間違っています", // 2
+ "パラメータの値が異常です", // 3
+ "計算式でエラーが発生しました", // 4
+ "パラメータの省略はできません", // 5
+ "パラメータの型が違います", // 6
+ "配列の要素が無効です", // 7
+ "有効なラベルが指定されていません", // 8
+ "サブルーチンやループのネストが深すぎます", // 9
+ "サブルーチン外のreturnは無効です", // 10
+ "repeat外でのloopは無効です", // 11
+ "ファイルが見つからないか無効な名前です", // 12
+ "画像ファイルがありません", // 13
+ "外部ファイル呼び出し中のエラーです", // 14
+ "計算式でカッコの記述が違います", // 15
+ "パラメータの数が多すぎます", // 16
+ "文字列式で扱える文字数を越えました", // 17
+ "代入できない変数名を指定しています", // 18
+ "0で除算しました", // 19
+ "バッファオーバーフローが発生しました", // 20
+ "サポートされない機能を選択しました", // 21
+ "計算式のカッコが深すぎます", // 22
+ "変数名が指定されていません", // 23
+ "整数以外が指定されています", // 24
+ "配列の要素書式が間違っています", // 25
+ "メモリの確保ができませんでした", // 26
+ "タイプの初期化に失敗しました", // 27
+ "関数に引数が設定されていません", // 28
+ "スタック領域のオーバーフローです", // 29
+ "無効な名前がパラメーターに指定されています", // 30
+ "異なる型を持つ配列変数に代入しました", // 31
+ "関数のパラメーター記述が不正です", // 32
+ "オブジェクト数が多すぎます", // 33
+ "配列・関数として使用できない型です", // 34
+ "モジュール変数が指定されていません", // 35
+ "モジュール変数の指定が無効です", // 36
+ "変数型の変換に失敗しました", // 37
+ "外部DLLの呼び出しに失敗しました", // 38
+ "外部オブジェクトの呼び出しに失敗しました", // 39
+ "関数の戻り値が設定されていません。", // 40
+ "関数を命令として記述しています。\n(HSP2から関数化された名前を使用している可能性があります)", // 41
+ "*"
+};
+#else
+static char *err[]={
+ "", // 0
+ "Unknown system error", // 1
+ "Syntax error", // 2
+ "Illegal function call", // 3
+ "Wrong expression", // 4
+ "Default parameter not allowed", // 5
+ "Type mismatch", // 6
+ "Array overflow", // 7
+ "Not a label object", // 8
+ "Too many nesting", // 9
+ "Return without gosub", // 10
+ "Loop without repeat", // 11
+ "File I/O error", // 12
+ "Picture file missing", // 13
+ "External execute error", // 14
+ "Priority error", // 15
+ "Too many parameters", // 16
+ "Temporary buffer overflow", // 17
+ "Wrong valiable name", // 18
+ "Divided by zero", // 19
+ "Buffer Overflow", // 20
+ "Unsupported function", // 21
+ "Expression too complex", // 22
+ "Variable required", // 23
+ "Integer value required", // 24
+ "Bad array expression", // 25
+ "Out of memory", // 26
+ "Type initalization failed", // 27
+ "No Function parameters", // 28
+ "Stack overflow", // 29
+ "Invalid parameter name", // 30
+ "Invalid type of array", // 31
+ "Invalid function parameter", // 32
+ "Too many window objects", // 33
+ "Invalid Array/Function", // 34
+ "Structure required", // 35
+ "Illegal structure call", // 36
+ "Invalid type of variable", // 37
+ "DLL call failed", // 38
+ "External COM call failed", // 39
+ "No function result", // 40
+ "Invalid syntax for function", // 41
+ "*"
+};
+#endif
+
+char *hspd_geterror( HSPERROR error )
+{
+ if ((error<0)||(error>=HSPERR_MAX)) return err[0];
+ return err[error];
+}
+
+#else
+
+static char errmsg[256];
+
+char *hspd_geterror( HSPERROR error )
+{
+#ifdef JPNMSG
+ sprintf( errmsg, "内部エラーが発生しました(%d)", (int)error );
+#else
+ sprintf( errmsg, "Internal Error(%d)", (int)error );
+#endif
+ return errmsg;
+}
+
+#endif
+
+
+
diff --git a/src/hsp3/hsp3debug.h b/src/hsp3/hsp3debug.h
new file mode 100644
index 0000000000000000000000000000000000000000..3259fb299379081a2e2c1bc690fe0eeb9f9fbcf9
--- /dev/null
+++ b/src/hsp3/hsp3debug.h
@@ -0,0 +1,117 @@
+
+//
+// hsp3debug.cpp header
+//
+#ifndef __hsp3debug_h
+#define __hsp3debug_h
+
+// エラーコード
+typedef enum {
+
+HSPERR_NONE = 0, // スクリプト終了時
+HSPERR_UNKNOWN_CODE,
+HSPERR_SYNTAX,
+HSPERR_ILLEGAL_FUNCTION,
+HSPERR_WRONG_EXPRESSION,
+HSPERR_NO_DEFAULT,
+HSPERR_TYPE_MISMATCH,
+HSPERR_ARRAY_OVERFLOW,
+HSPERR_LABEL_REQUIRED,
+HSPERR_TOO_MANY_NEST,
+HSPERR_RETURN_WITHOUT_GOSUB,
+HSPERR_LOOP_WITHOUT_REPEAT,
+HSPERR_FILE_IO,
+HSPERR_PICTURE_MISSING,
+HSPERR_EXTERNAL_EXECUTE,
+HSPERR_PRIORITY,
+HSPERR_TOO_MANY_PARAMETERS,
+HSPERR_TEMP_BUFFER_OVERFLOW,
+HSPERR_WRONG_NAME,
+HSPERR_DIVIDED_BY_ZERO,
+HSPERR_BUFFER_OVERFLOW,
+HSPERR_UNSUPPORTED_FUNCTION,
+HSPERR_EXPRESSION_COMPLEX,
+HSPERR_VARIABLE_REQUIRED,
+HSPERR_INTEGER_REQUIRED,
+HSPERR_BAD_ARRAY_EXPRESSION,
+HSPERR_OUT_OF_MEMORY,
+HSPERR_TYPE_INITALIZATION_FAILED,
+HSPERR_NO_FUNCTION_PARAMETERS,
+HSPERR_STACK_OVERFLOW,
+HSPERR_INVALID_PARAMETER,
+HSPERR_INVALID_ARRAYSTORE,
+HSPERR_INVALID_FUNCPARAM,
+HSPERR_WINDOW_OBJECT_FULL,
+HSPERR_INVALID_ARRAY,
+HSPERR_STRUCT_REQUIRED,
+HSPERR_INVALID_STRUCT_SOURCE,
+HSPERR_INVALID_TYPE,
+HSPERR_DLL_ERROR,
+HSPERR_COMDLL_ERROR,
+HSPERR_NORETVAL,
+HSPERR_FUNCTION_SYNTAX,
+
+HSPERR_INTJUMP, // 割り込みジャンプ時
+HSPERR_EXITRUN, // 外部ファイル実行
+HSPERR_MAX
+
+} HSPERROR;
+
+char *hspd_geterror( HSPERROR error );
+
+
+// Debug Info ID
+enum
+{
+DEBUGINFO_GENERAL = 0,
+DEBUGINFO_VARNAME,
+DEBUGINFO_INTINFO,
+DEBUGINFO_GRINFO,
+DEBUGINFO_MMINFO,
+DEBUGINFO_MAX
+};
+
+// Debug Flag ID
+enum
+{
+HSPDEBUG_NONE = 0,
+HSPDEBUG_RUN,
+HSPDEBUG_STOP,
+HSPDEBUG_STEPIN,
+HSPDEBUG_STEPOVER,
+HSPDEBUG_MAX
+};
+
+typedef struct HSP3DEBUG
+{
+ // [in/out] tranfer value
+ // (システムとの通信用)
+ //
+ int flag; // Flag ID
+ int line; // 行番号情報
+ char *fname; // ファイル名情報
+ void *dbgwin; // Debug WindowのHandle
+ char *dbgval; // debug情報取得バッファ
+
+ // [in] system value
+ // (初期化後に設定されます)
+ //
+ struct HSPCTX *hspctx;
+ //
+ char * (* get_value) (int); // debug情報取得コールバック
+ char * (* get_varinf) (char *,int); // 変数情報取得コールバック
+ void (* dbg_close) (char *); // debug情報取得終了
+ void (* dbg_curinf)( void ); // 現在行・ファイル名の取得
+ int (* dbg_set) (int); // debugモード設定
+ char * (* dbg_callstack) ( void ); // コールスタックの取得
+
+} HSP3DEBUG;
+
+// Debug Module
+
+#define HSP3DEBUG_MODULE "hsp3debug"
+#define HSP3DEBUG_INIT "debugini"
+#define HSP3DEBUG_NOTICE "debug_notice"
+
+
+#endif
diff --git a/src/hsp3/hsp3ext.h b/src/hsp3/hsp3ext.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ebf5392d038724f31366df21869b8d49780395c
--- /dev/null
+++ b/src/hsp3/hsp3ext.h
@@ -0,0 +1,29 @@
+
+//
+// hsp3ext.cpp header
+//
+#ifndef __hsp3ext_h
+#define __hsp3ext_h
+
+#ifdef HSPWIN
+#include "win32gui/hsp3ext_win.h"
+#endif
+
+#ifdef HSPIOS
+#include "ios/hsp3ext_ios.h"
+#endif
+
+#ifdef HSPNDK
+#include "ndk/hsp3ext_ndk.h"
+#endif
+
+#ifdef HSPLINUX
+#include "linux/hsp3ext_linux.h"
+#endif
+
+#ifdef HSPEMSCRIPTEN
+#include "emscripten/hsp3ext_emscripten.h"
+#endif
+
+
+#endif
diff --git a/src/hsp3/hsp3gr.h b/src/hsp3/hsp3gr.h
new file mode 100644
index 0000000000000000000000000000000000000000..5eb28322425579760a38068d3fcb53eaa87938f4
--- /dev/null
+++ b/src/hsp3/hsp3gr.h
@@ -0,0 +1,37 @@
+
+//
+// hsp3gr.cpp header
+//
+#ifndef __hsp3gr_h
+#define __hsp3gr_h
+
+#ifdef HSPWIN
+#ifdef HSPWINGUI
+#include "win32gui/hsp3gr_wingui.h"
+#else
+#ifdef HSPDISH
+#include "win32dish/hsp3gr_dish.h"
+#else
+#include "win32/hsp3gr_win.h"
+#endif
+#endif
+#endif
+
+#ifdef HSPIOS
+#include "ios/hsp3gr_ios.h"
+#endif
+
+#ifdef HSPNDK
+#include "ndk/hsp3gr_ndk.h"
+#endif
+
+#ifdef HSPLINUX
+#include "linux/hsp3gr_linux.h"
+#endif
+
+#ifdef HSPEMSCRIPTEN
+#include "emscripten/hsp3gr_emscripten.h"
+#endif
+
+
+#endif
diff --git a/src/hsp3/hsp3int.cpp b/src/hsp3/hsp3int.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..36a315b8255353a2cba9e3a26a25e0bdfe244ced
--- /dev/null
+++ b/src/hsp3/hsp3int.cpp
@@ -0,0 +1,1788 @@
+
+//
+// HSP3 internal command
+// (内蔵コマンド・関数処理)
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "hsp3config.h"
+
+#ifdef HSPRANDMT
+#include
+#endif
+
+#ifdef HSPWIN
+#include
+#include
+#endif
+
+#include "hspwnd.h"
+#include "supio.h"
+#include "dpmread.h"
+#include "strbuf.h"
+#include "strnote.h"
+
+#include "hsp3int.h"
+#include "hsp3code.h"
+
+static const double DBLINF = std::numeric_limits::infinity();
+
+/*------------------------------------------------------------*/
+/*
+ system data
+*/
+/*------------------------------------------------------------*/
+
+static int *type;
+static int *val;
+static HSPCTX *ctx; // Current Context
+static HSPEXINFO *exinfo; // Info for Plugins
+static CStrNote note;
+#ifdef HSPRANDMT
+static std::mt19937 mt;
+#endif
+
+
+
+/*------------------------------------------------------------*/
+/*
+ Sort Routines
+*/
+/*------------------------------------------------------------*/
+
+static int qsort_order;
+
+typedef struct {
+ union {
+ int ikey;
+ double dkey;
+ char *skey;
+ } as;
+ int info; // ソートの前にこの要素があった位置
+} DATA;
+
+static bool less_int_1(DATA const& lhs, DATA const& rhs)
+{
+ int cmp = (lhs.as.ikey - rhs.as.ikey);
+ return (cmp < 0)
+ || (cmp == 0 && lhs.info < rhs.info);
+}
+
+static bool less_int_0(DATA const& lhs, DATA const& rhs)
+{
+ int cmp = (lhs.as.ikey - rhs.as.ikey);
+ return (cmp > 0)
+ || (cmp == 0 && lhs.info < rhs.info);
+}
+
+static bool less_double_1(DATA const& lhs, DATA const& rhs)
+{
+ int cmp = (lhs.as.dkey < rhs.as.dkey ? -1 : (lhs.as.dkey > rhs.as.dkey ? 1 : 0));
+ return (cmp < 0)
+ || (cmp == 0 && lhs.info < rhs.info);
+}
+
+static bool less_double_0(DATA const& lhs, DATA const& rhs)
+{
+ int cmp = (lhs.as.dkey < rhs.as.dkey ? -1 : (lhs.as.dkey > rhs.as.dkey ? 1 : 0));
+ return (cmp > 0)
+ || (cmp == 0 && lhs.info < rhs.info);
+}
+
+static bool less_str_1(DATA const& lhs, DATA const& rhs)
+{
+ int cmp = (strcmp(lhs.as.skey, rhs.as.skey));
+ return (cmp < 0)
+ || (cmp == 0 && lhs.info < rhs.info);
+}
+
+static bool less_str_0(DATA const& lhs, DATA const& rhs)
+{
+ int cmp = (strcmp(lhs.as.skey, rhs.as.skey));
+ return (cmp > 0)
+ || (cmp == 0 && lhs.info < rhs.info);
+}
+
+
+static int NoteToData( char *adr, DATA *data )
+{
+ char *p = adr;
+ int line = 0;
+ while (*p != '\0') {
+ data[line].as.skey=p;
+ data[line].info=line;
+ while (*p != '\0') {
+ char c = *p;
+ if (c == '\n' || c == '\r') {
+ *p = '\0';
+ }
+ p ++;
+ if (c == '\n') break;
+ if (c == '\r') {
+ if (*p == '\n') p++;
+ break;
+ }
+ }
+ line ++;
+ }
+ return line;
+}
+
+
+static int GetNoteLines( char *adr )
+{
+ int line = 0;
+ char *p = adr;
+ while (*p != '\0') {
+ while (*p != '\0') {
+ char c = *p++;
+ if (c == '\n') break;
+ if (c == '\r') {
+ if (*p == '\n') p ++;
+ break;
+ }
+ }
+ line ++;
+ }
+ return line;
+}
+
+
+static size_t DataToNoteLen( DATA *data, int num )
+{
+ size_t len = 0;
+ int i;
+ for (i = 0; i < num; i++) {
+ char *s = data[i].as.skey;
+ len += strlen(s) + 2; // strlen("\r\n")
+ }
+ return len;
+}
+
+
+static void DataToNote( DATA *data, char *adr, int num )
+{
+ int a;
+ char *p;
+ char *s;
+ p=adr;
+ for(a=0;a new_size) {
+ new_size *= 2;
+ }
+ dtmp = (DATA *)realloc( dtmp, sizeof(DATA)*new_size );
+ memset( dtmp + dtmp_size, 0, sizeof(DATA)*(new_size - dtmp_size) );
+ dtmp_size = new_size;
+}
+
+
+static void DataInc( int n )
+{
+ DataExpand( n + 1 );
+ dtmp[n].info ++;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ Easing Function
+*/
+/*------------------------------------------------------------*/
+
+static int ease_type;
+static int ease_reverse;
+static HSPREAL ease_start;
+static HSPREAL ease_diff;
+static HSPREAL ease_4096;
+static HSPREAL ease_start_org;
+static HSPREAL ease_diff_org;
+
+#define EASE_LINEAR 0
+#define EASE_QUAD_IN 1
+#define EASE_QUAD_OUT 2
+#define EASE_QUAD_INOUT 3
+#define EASE_CUBIC_IN 4
+#define EASE_CUBIC_OUT 5
+#define EASE_CUBIC_INOUT 6
+#define EASE_QUARTIC_IN 7
+#define EASE_QUARTIC_OUT 8
+#define EASE_QUARTIC_INOUT 9
+#define EASE_BOUNCE_IN 10
+#define EASE_BOUNCE_OUT 11
+#define EASE_BOUNCE_INOUT 12
+#define EASE_SHAKE_IN 13
+#define EASE_SHAKE_OUT 14
+#define EASE_SHAKE_INOUT 15
+#define EASE_LOOP 4096
+
+/*------------------------------------------------------------*/
+
+static HSPREAL _ease_linear( HSPREAL t )
+{
+ return ease_diff * t + ease_start;
+}
+
+static HSPREAL _ease_quad_in( HSPREAL t )
+{
+ return ease_diff * t * t + ease_start;
+}
+
+static HSPREAL _ease_quad_out( HSPREAL t )
+{
+ return -ease_diff * t * (t - 2) + ease_start;
+}
+
+static HSPREAL _ease_quad_inout( HSPREAL t )
+{
+ HSPREAL tt;
+ tt = t * 2;
+ if ( tt < 1 ) {
+ return ease_diff * 0.5 * tt * tt + ease_start;
+ }
+ tt = tt - 1;
+ return -ease_diff * 0.5 * (tt * (tt - 2) - 1) + ease_start;
+}
+
+static HSPREAL _ease_cubic_in( HSPREAL t )
+{
+ return ease_diff * t * t * t + ease_start;
+}
+
+static HSPREAL _ease_cubic_out( HSPREAL t )
+{
+ HSPREAL tt;
+ tt = t - 1;
+ return ease_diff*(tt*tt*tt + 1) + ease_start;
+}
+
+static HSPREAL _ease_cubic_inout( HSPREAL t )
+{
+ HSPREAL tt;
+ tt = t * 2;
+ if ( tt < 1 ) {
+ return ease_diff * 0.5 *tt*tt*tt + ease_start;
+ }
+ tt = tt - 2;
+ return ease_diff * 0.5 * (tt*tt*tt + 2) + ease_start;
+}
+
+static HSPREAL _ease_quartic_in( HSPREAL t )
+{
+ return ease_diff * t * t * t * t + ease_start;
+}
+
+static HSPREAL _ease_quartic_out( HSPREAL t )
+{
+ HSPREAL tt;
+ tt = t - 1;
+ return -ease_diff*(tt*tt*tt*tt - 1) + ease_start;
+}
+
+static HSPREAL _ease_quartic_inout( HSPREAL t )
+{
+ HSPREAL tt;
+ tt = t * 2;
+ if ( tt < 1 ) {
+ return ease_diff * 0.5 *tt*tt*tt*tt + ease_start;
+ }
+ tt = tt - 2;
+ return -ease_diff * 0.5 * (tt*tt*tt*tt - 2) + ease_start;
+}
+
+static HSPREAL _ease_bounce( HSPREAL t )
+{
+ if ( t < (1/2.75)) {
+ return ease_diff*(7.5625*t*t);
+ } else if (t < (2/2.75)) {
+ return ease_diff*(7.5625*(t-=(1.5/2.75))*t + .75);
+ } else if (t < (2.5/2.75)) {
+ return ease_diff*(7.5625*(t-=(2.25/2.75))*t + .9375);
+ } else {
+ return ease_diff*(7.5625*(t-=(2.625/2.75))*t + .984375);
+ }
+}
+
+static HSPREAL _ease_bounce_in( HSPREAL t )
+{
+ HSPREAL tt;
+ tt = (HSPREAL)1 - t;
+ return ease_diff - _ease_bounce( tt ) + ease_start;
+}
+
+static HSPREAL _ease_bounce_out( HSPREAL t )
+{
+ return _ease_bounce(t) + ease_start;
+}
+
+static HSPREAL _ease_bounce_inout( HSPREAL t )
+{
+ HSPREAL tt;
+ if (t < 0.5) {
+ tt = (HSPREAL)1 - (t * 2);
+ return ( ease_diff - _ease_bounce( tt )) * 0.5 + ease_start;
+ }
+ return _ease_bounce( t*2 - 1 ) * 0.5 + ease_diff*0.5 + ease_start;
+}
+
+static HSPREAL _ease_shake( HSPREAL t )
+{
+ int pulse;
+ HSPREAL tt;
+ tt = t * t * 8;
+ pulse = (int)tt;
+ tt -= (HSPREAL)pulse;
+ if ( pulse & 1 ) {
+ return ( (HSPREAL)1 - tt );
+ }
+ return tt;
+}
+static HSPREAL _ease_shake_in( HSPREAL t )
+{
+ HSPREAL tt;
+ tt = (HSPREAL)1 - t;
+ return ( ease_diff * _ease_shake(tt) ) * tt - ease_diff * 0.5 * tt + ease_start;
+}
+
+static HSPREAL _ease_shake_out( HSPREAL t )
+{
+ return ( ease_diff * _ease_shake(t) ) * t - ease_diff * 0.5 * t + ease_start;
+}
+
+static HSPREAL _ease_shake_inout( HSPREAL t )
+{
+ HSPREAL tt;
+ tt = t * 2;
+ if ( tt < 1 ) {
+ return _ease_shake_in( tt );
+ }
+ tt = tt - 1;
+ return _ease_shake_out( tt );
+}
+
+/*------------------------------------------------------------*/
+
+static void initEase( void )
+{
+ ease_4096 = (HSPREAL)1.0 / (HSPREAL)4096.0;
+}
+
+static void setEase( int type, HSPREAL value_start, HSPREAL value_end )
+{
+ ease_type = type;
+ ease_reverse = 0;
+ ease_start_org = ease_start = value_start;
+ ease_diff_org = ease_diff = value_end - value_start;
+}
+
+static HSPREAL getEase( HSPREAL value )
+{
+ int type;
+ int reverse;
+ HSPREAL t;
+ t = value;
+ type = ease_type & ( EASE_LOOP - 1 );
+ reverse = 0;
+ if ( ease_type & EASE_LOOP ) {
+ int ival;
+ HSPREAL dval;
+ t = modf( t, &dval );
+ ival = (int)dval;
+ reverse = ival & 1;
+ } else {
+ if ( t < 0 ) t = (HSPREAL)0;
+ if ( t > 1 ) t = (HSPREAL)1;
+ }
+
+ if ( ease_reverse != reverse ) {
+ ease_reverse = reverse; // リバース時の動作
+ if ( ease_reverse ) {
+ ease_start = ease_start_org + ease_diff_org;
+ ease_diff = -ease_diff_org;
+ } else {
+ ease_start = ease_start_org;
+ ease_diff = ease_diff_org;
+ }
+ }
+
+ switch( type ) {
+ case EASE_QUAD_IN:
+ return _ease_quad_in( t );
+ case EASE_QUAD_OUT:
+ return _ease_quad_out( t );
+ case EASE_QUAD_INOUT:
+ return _ease_quad_inout( t );
+
+ case EASE_CUBIC_IN:
+ return _ease_cubic_in( t );
+ case EASE_CUBIC_OUT:
+ return _ease_cubic_out( t );
+ case EASE_CUBIC_INOUT:
+ return _ease_cubic_inout( t );
+
+ case EASE_QUARTIC_IN:
+ return _ease_quartic_in( t );
+ case EASE_QUARTIC_OUT:
+ return _ease_quartic_out( t );
+ case EASE_QUARTIC_INOUT:
+ return _ease_quartic_inout( t );
+
+ case EASE_BOUNCE_IN:
+ return _ease_bounce_in( t );
+ case EASE_BOUNCE_OUT:
+ return _ease_bounce_out( t );
+ case EASE_BOUNCE_INOUT:
+ return _ease_bounce_inout( t );
+
+ case EASE_SHAKE_IN:
+ return _ease_shake_in( t );
+ case EASE_SHAKE_OUT:
+ return _ease_shake_out( t );
+ case EASE_SHAKE_INOUT:
+ return _ease_shake_inout( t );
+
+ case EASE_LINEAR:
+ default:
+ break;
+ }
+ return _ease_linear( t );
+}
+
+static HSPREAL getEase( HSPREAL value, HSPREAL maxvalue )
+{
+ if ( maxvalue == 0 ) return (HSPREAL)0;
+ return getEase( value / maxvalue );
+}
+
+static int getEaseInt( int i_value, int i_maxvalue )
+{
+ int i;
+ HSPREAL value;
+ if ( i_maxvalue > 0 ) {
+ value = (HSPREAL)i_value / (HSPREAL)i_maxvalue;
+ } else {
+ value = ease_4096 * i_value;
+ }
+ i = (int)getEase(value);
+ return i;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+static char *note_update( void )
+{
+ char *p;
+ if ( ctx->note_pval == NULL ) throw HSPERR_ILLEGAL_FUNCTION;
+ p = (char *)HspVarCorePtrAPTR( ctx->note_pval, ctx->note_aptr );
+ note.Select( p );
+ return p;
+}
+
+// デストラクタで自動的に sbFree を呼ぶ
+class CAutoSbFree {
+public:
+ CAutoSbFree(char **pptr);
+ ~CAutoSbFree();
+
+private:
+ // uncopyable;
+ CAutoSbFree( CAutoSbFree const & );
+ CAutoSbFree const & operator =( CAutoSbFree const & );
+
+private:
+ char **pptr_;
+};
+
+CAutoSbFree::CAutoSbFree(char **pptr)
+ : pptr_(pptr)
+{}
+
+CAutoSbFree::~CAutoSbFree() {
+ sbFree(*pptr_);
+}
+
+static void cnvformat_expand( char **p, int *capacity, int len, int n )
+{
+ int needed_size = len + n + 1;
+ int capa = *capacity;
+ if ( needed_size > capa ) {
+ while ( needed_size > capa ) {
+ capa *= 2;
+ }
+ *p = sbExpand( *p, capa );
+ *capacity = capa;
+ }
+}
+
+static char *cnvformat( void )
+{
+ // フォーマット付き文字列を作成する
+ //
+#if ( WIN32 || _WIN32 ) && ! __CYGWIN__
+#define SNPRINTF _snprintf
+#else
+#define SNPRINTF snprintf
+#endif
+
+ char fstr[1024];
+ char *fp;
+ int capacity;
+ int len;
+ char *p;
+
+ strncpy( fstr, code_gets(), sizeof fstr );
+ fstr[sizeof(fstr)-1] = '\0';
+ fp = fstr;
+ capacity = 1024;
+ p = sbAlloc(capacity);
+ len = 0;
+
+ CAutoSbFree autofree(&p);
+
+ while (1) {
+ char fmt[32];
+ int i;
+ int val_type;
+ void *val_ptr;
+
+ // '%' までをコピー
+ i = 0;
+ while( fp[i] != '\0' && fp[i] != '%' ) {
+ i ++;
+ }
+ cnvformat_expand( &p, &capacity, len, i );
+ memcpy( p + len, fp, i );
+ len += i;
+ fp += i;
+ if ( *fp == '\0' ) break;
+
+ // 変換指定を読み fmt にコピー
+ i = (int)strspn( fp + 1, " #+-.0123456789" ) + 1;
+ strncpy( fmt, fp, sizeof fmt );
+ fmt[sizeof(fmt)-1] = '\0';
+ if ( i + 1 < (int)(sizeof fmt) ) fmt[i+1] = '\0';
+ fp += i;
+
+ char specifier = *fp;
+ fp ++;
+
+#if ( WIN32 || _WIN32 ) && ! __CYGWIN__
+ if ( specifier == 'I' ) { // I64 prefix対応(VC++のみ)
+ if ((fp[0]=='6')&&(fp[1]='4')) {
+ memcpy( fmt+i+1, fp, 3 );
+ fmt[i+4] = 0;
+ specifier = 'f';
+ fp += 3;
+ }
+ }
+#endif
+
+ if ( specifier == '\0' ) break;
+ if ( specifier == '%' ) {
+ cnvformat_expand( &p, &capacity, len, 1 );
+ p[len++] = '%';
+ continue;
+ }
+
+ // 引数を取得
+ if ( code_get() <= PARAM_END ) throw HSPERR_INVALID_FUNCPARAM;
+ switch (specifier) {
+ case 'd': case 'i': case 'c': case 'o': case 'x': case 'X': case 'u': case 'p':
+ val_type = HSPVAR_FLAG_INT;
+ val_ptr = HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_INT );
+ break;
+ case 'f': case 'e': case 'E': case 'g': case 'G':
+ val_type = HSPVAR_FLAG_DOUBLE;
+ val_ptr = HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_DOUBLE );
+ break;
+ case 's':
+ val_type = HSPVAR_FLAG_STR;
+ val_ptr = HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_STR );
+ break;
+ default:
+ throw HSPERR_INVALID_FUNCPARAM;
+ }
+
+ // snprintf が成功するまでバッファを広げていき、変換を行う
+ while (1) {
+ int n;
+ int space = capacity - len - 1;
+ if ( val_type == HSPVAR_FLAG_INT ) {
+ n = SNPRINTF( p + len, space, fmt, *(int *)val_ptr );
+ } else if ( val_type == HSPVAR_FLAG_DOUBLE ) {
+ n = SNPRINTF( p + len, space, fmt, *(HSPREAL *)val_ptr );
+ } else {
+ n = SNPRINTF( p + len, space, fmt, (char *)val_ptr );
+ }
+
+ if ( n >= 0 && n < space ) {
+ len += n;
+ break;
+ }
+ if ( n >= 0 ) {
+ space = n + 1;
+ } else {
+ space *= 2;
+ if ( space < 32 ) space = 32;
+ }
+ cnvformat_expand( &p, &capacity, len, space );
+ }
+ }
+ p[len] = '\0';
+
+ char *result = code_stmp(len + 1);
+ strcpy(result, p);
+ return result;
+}
+
+
+static void var_set_str_len( PVal *pval, APTR aptr, char *str, int len )
+{
+ // 変数にstrからlenバイトの文字列を代入する
+ //
+ HspVarProc *proc = HspVarCoreGetProc( HSPVAR_FLAG_STR );
+ if ( pval->flag != HSPVAR_FLAG_STR ) {
+ if ( aptr != 0 ) throw HSPERR_INVALID_ARRAYSTORE;
+ HspVarCoreClear( pval, HSPVAR_FLAG_STR );
+ }
+ pval->offset = aptr;
+ HspVarCoreAllocBlock( pval, proc->GetPtr( pval ), len + 1 );
+ char *ptr = (char *)proc->GetPtr( pval );
+ memcpy( ptr, str, len );
+ ptr[len] = '\0';
+}
+
+
+
+static int cmdfunc_intcmd( int cmd )
+{
+ // cmdfunc : TYPE_INTCMD
+ // (内蔵コマンド)
+ //
+ int p1,p2,p3;
+ //
+ code_next(); // 次のコードを取得(最初に必ず必要です)
+
+ switch( cmd ) { // サブコマンドごとの分岐
+
+ case 0x00: // onexit
+ case 0x01: // onerror
+ case 0x02: // onkey
+ case 0x03: // onclick
+ case 0x04: // oncmd
+ {
+
+/*
+ rev 45
+ 不具合 : (onxxx系命令) (ラベル型変数) 形式の書式でエラー
+ に対処
+*/
+
+ int tval = *type;
+ int opt = IRQ_OPT_GOTO;
+ int cust;
+ int actid;
+ IRQDAT *irq;
+ unsigned short *sbr;
+
+ if ( tval == TYPE_VAR ) {
+ if ( ( ctx->mem_var + *val )->flag == HSPVAR_FLAG_LABEL )
+ tval = TYPE_LABEL;
+ }
+
+ if (( tval != TYPE_PROGCMD )&&( tval != TYPE_LABEL )) { // ON/OFF切り替え
+ int i = code_geti();
+ code_enableirq( cmd, i );
+ break;
+ }
+
+ if ( tval == TYPE_PROGCMD ) { // ジャンプ方法指定
+ opt = *val;
+ if ( opt >= 2 ) throw HSPERR_SYNTAX;
+ code_next();
+ }
+
+ sbr = code_getlb2();
+ if ( cmd != 0x04 ) {
+ code_setirq( cmd, opt, -1, sbr );
+ break;
+ }
+ cust = code_geti();
+ actid = *(exinfo->actscr);
+ irq = code_seekirq( actid, cust );
+ if ( irq == NULL ) irq = code_addirq();
+ irq->flag = IRQ_FLAG_ENABLE;
+ irq->opt = opt;
+ irq->ptr = sbr;
+ irq->custom = cust;
+ irq->custom2 = actid;
+ break;
+ }
+
+ case 0x11: // exist
+ case 0x12: // delete
+ case 0x13: // mkdir
+ case 0x14: // chdir
+ code_event( HSPEVENT_FNAME, 0, 0, code_gets() );
+ code_event( HSPEVENT_FEXIST + (cmd - 0x11), 0, 0, NULL );
+ break;
+
+ case 0x15: // dirlist
+ {
+ PVal *pval;
+ APTR aptr;
+ char *ptr;
+ aptr = code_getva( &pval );
+ code_event( HSPEVENT_FNAME, 0, 0, code_gets() );
+ p1=code_getdi(0);
+ code_event( HSPEVENT_FDIRLIST1, p1, 0, &ptr );
+ code_setva( pval, aptr, TYPE_STRING, ptr );
+ code_event( HSPEVENT_FDIRLIST2, 0, 0, NULL );
+ break;
+ }
+ case 0x16: // bload
+ case 0x17: // bsave
+ {
+ PVal *pval;
+ char *ptr;
+ int size;
+ int tmpsize;
+ code_event( HSPEVENT_FNAME, 0, 0, code_gets() );
+ ptr = code_getvptr( &pval, &size );
+ p1 = code_getdi( -1 );
+ p2 = code_getdi( -1 );
+ if (( p1 < 0 )||( p1 > size )) p1 = size;
+ if ( cmd == 0x16 ) {
+ tmpsize = p2;if ( tmpsize<0 ) tmpsize = 0;
+ code_event( HSPEVENT_FREAD, tmpsize, p1, ptr );
+ } else {
+ code_event( HSPEVENT_FWRITE, p2, p1, ptr );
+ }
+ break;
+ }
+ case 0x18: // bcopy
+ code_event( HSPEVENT_FNAME, 0, 0, code_gets() );
+ code_event( HSPEVENT_FCOPY, 0, 0, code_gets() );
+ break;
+ case 0x19: // memfile
+ {
+ PVal *pval;
+ char *ptr;
+ int size;
+ ptr = code_getvptr( &pval, &size );
+ p1=code_getdi( 0 );
+ p2=code_getdi( 0 );
+ if ( p2==0 ) p2 = size - p1;
+ dpm_memfile( ptr+p1, p2 );
+ break;
+ }
+
+ case 0x1a: // poke
+ case 0x1b: // wpoke
+ case 0x1c: // lpoke
+ {
+ PVal *pval;
+ char *ptr;
+ int size;
+ int fl;
+ int len;
+ char *bp;
+ ptr = code_getvptr( &pval, &size );
+ p1 = code_getdi( 0 );
+ if ( p1<0 ) throw HSPERR_BUFFER_OVERFLOW;
+ ptr += p1;
+
+ if ( code_get() <= PARAM_END ) {
+ fl = HSPVAR_FLAG_INT;
+ bp = (char *)&p2; p2 = 0;
+ } else {
+ fl = mpval->flag;
+ bp = mpval->pt;
+ }
+
+ if ( cmd == 0x1a ) {
+ switch( fl ) {
+ case HSPVAR_FLAG_INT:
+ if ( p1 >= size ) throw HSPERR_BUFFER_OVERFLOW;
+ *ptr = *bp;
+ break;
+ case HSPVAR_FLAG_STR:
+ len = (int)strlen( bp );
+ ctx->strsize = len;
+ len++;
+ if ( (p1+len)>size ) throw HSPERR_BUFFER_OVERFLOW;
+ strcpy( ptr, bp );
+ break;
+ default:
+ throw HSPERR_TYPE_MISMATCH;
+ }
+ break;
+ }
+
+ if ( fl != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH;
+ if ( cmd == 0x1b ) {
+ if ( (p1+2)>size ) throw HSPERR_BUFFER_OVERFLOW;
+ *(short *)ptr = (short)(*(short *)bp);
+ } else {
+ if ( (p1+4)>size ) throw HSPERR_BUFFER_OVERFLOW;
+ *(int *)ptr = (*(int *)bp);
+ }
+ break;
+ }
+
+ case 0x1d: // getstr
+ {
+ PVal *pval2;
+ PVal *pval;
+ APTR aptr;
+ char *ptr;
+ char *p;
+ int size;
+ aptr = code_getva( &pval );
+ ptr = code_getvptr( &pval2, &size );
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 1024 );
+ if ( p1 >= size ) throw HSPERR_BUFFER_OVERFLOW;
+ ptr += p1;
+ p = code_stmp( p3 + 1 );
+ strsp_ini();
+ ctx->stat = strsp_get( ptr, p, p2, p3 );
+ ctx->strsize = strsp_getptr();
+ code_setva( pval, aptr, HSPVAR_FLAG_STR, p );
+ break;
+ }
+ case 0x1e: // chdpm
+ code_event( HSPEVENT_FNAME, 0, 0, code_gets() );
+ p1 = code_getdi( -1 );
+ dpm_bye();
+ p2 = dpm_ini( ctx->fnbuffer, 0, -1, p1 );
+ if ( p2 ) throw HSPERR_FILE_IO;
+#ifndef HSP3IMP
+#ifdef HSPWIN
+ Sleep( 1000 );
+#endif
+#endif
+ break;
+ case 0x1f: // memexpand
+ {
+ PVal *pval;
+ APTR aptr;
+ PDAT *ptr;
+ aptr = code_getva( &pval );
+ ptr = HspVarCorePtrAPTR( pval, aptr );
+ if (( pval->support & HSPVAR_SUPPORT_FLEXSTORAGE ) == 0 ) throw HSPERR_TYPE_MISMATCH;
+ p1 = code_getdi( 0 );
+ if ( p1 < 64 ) p1 = 64;
+ HspVarCoreAllocBlock( pval, ptr, p1 );
+ break;
+ }
+
+ case 0x20: // memcpy
+ {
+ PVal *pval;
+ char *sptr;
+ char *tptr;
+ int bufsize_t,bufsize_s;
+
+ tptr = code_getvptr( &pval, &bufsize_t );
+ sptr = code_getvptr( &pval, &bufsize_s );
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ if( p2 < 0 || p3 < 0 ) throw HSPERR_BUFFER_OVERFLOW;
+
+ tptr += p2;
+ sptr += p3;
+ if ( (p1+p2)>bufsize_t ) throw HSPERR_BUFFER_OVERFLOW;
+ if ( (p1+p3)>bufsize_s ) throw HSPERR_BUFFER_OVERFLOW;
+ if ( p1>0 ) {
+ memmove( tptr, sptr, p1 );
+ }
+ break;
+ }
+ case 0x21: // memset
+ {
+ PVal *pval;
+ char *ptr;
+ int size;
+ ptr = code_getvptr( &pval, &size );
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ if ( p3 < 0 ) throw HSPERR_BUFFER_OVERFLOW;
+ ptr += p3;
+ if ( (p3+p2)>size ) throw HSPERR_BUFFER_OVERFLOW;
+ if ( p2>0 ) {
+ memset( ptr, p1, p2 );
+ }
+ break;
+ }
+
+ case 0x22: // notesel
+ ctx->notep_aptr = ctx->note_aptr;
+ ctx->notep_pval = ctx->note_pval;
+ ctx->note_aptr = code_getva( &ctx->note_pval );
+ if ( ctx->note_pval->flag != HSPVAR_FLAG_STR ) {
+ code_setva( ctx->note_pval, ctx->note_aptr, TYPE_STRING, "" );
+ }
+ break;
+ case 0x23: // noteadd
+ {
+ char *np;
+ char *ps;
+ char *tmp;
+ int size;
+ np = note_update();
+ ps = code_gets();
+ size = (int)strlen( ps ) + 8;
+ HspVarCoreAllocBlock( ctx->note_pval, (PDAT *)np, (int)strlen(np) + size );
+
+ tmp = code_stmpstr( ps );
+
+ p1 = code_getdi( -1 );
+ p2 = code_getdi( 0 );
+ np = note_update();
+ note.PutLine( tmp, p1, p2 );
+ break;
+ }
+ case 0x24: // notedel
+ p1 = code_getdi( 0 );
+ note_update();
+ note.PutLine( NULL, p1, 1 );
+ break;
+ case 0x25: // noteload
+ {
+ int size;
+ char *ptr;
+ char *pdat;
+
+ code_event( HSPEVENT_FNAME, 0, 0, code_gets() );
+ p1 = code_getdi( -1 );
+ code_event( HSPEVENT_FEXIST, 0, 0, NULL );
+ size = ctx->strsize;
+ if ( size < 0 ) throw HSPERR_FILE_IO;
+ if ( p1>=0 ) if ( size >= p1 ) { ctx->strsize = size = p1; }
+
+ pdat = note_update();
+ HspVarCoreAllocBlock( ctx->note_pval, (PDAT *)pdat, size+1 );
+ ptr = (char *)note_update();
+ code_event( HSPEVENT_FREAD, 0, size, ptr );
+ ptr[size] = 0;
+ break;
+ }
+ case 0x26: // notesave
+ {
+ char *pdat;
+ int size;
+ code_event( HSPEVENT_FNAME, 0, 0, code_gets() );
+ pdat = note_update();
+ size = (int)strlen( pdat );
+ code_event( HSPEVENT_FWRITE, -1, size, pdat );
+ break;
+ }
+ case 0x27: // randomize
+#ifdef HSPWIN
+ p2 = (int)GetTickCount(); // Windowsの場合はtickをシード値とする
+#else
+ p2 = (int)time(0); // Windows以外のランダムシード値
+#endif
+ p1 = code_getdi( p2 );
+#ifdef HSPRANDMT
+ mt.seed( p1 );
+#else
+ srand( p1 );
+#endif
+ break;
+ case 0x28: // noteunsel
+ ctx->note_aptr = ctx->notep_aptr;
+ ctx->note_pval = ctx->notep_pval;
+ break;
+ case 0x29: // noteget
+ {
+ PVal *pval;
+ APTR aptr;
+ char *p;
+ note_update();
+ aptr = code_getva( &pval );
+ p1 = code_getdi( 0 );
+ p = note.GetLineDirect( p1 );
+ code_setva( pval, aptr, TYPE_STRING, p );
+ note.ResumeLineDirect();
+ break;
+ }
+ case 0x2a: // split
+ {
+ // 指定した文字列で分割された要素を代入する(fujidig)
+ PVal *pval = NULL;
+ int aptr = 0;
+ char *sptr;
+ char *sep;
+ char *newsptr;
+ int size;
+ int sep_len;
+ int n = 0;
+ int is_last = 0;
+
+ sptr = code_getvptr( &pval, &size );
+ if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ sep = code_gets();
+ sep_len = (int)strlen( sep );
+
+ while (1) {
+ newsptr = strstr2( sptr, sep );
+ if ( !is_last && *exinfo->npexflg & EXFLG_1 ) {
+ // 分割結果の数が格納する変数より多ければ最後の変数に配列で格納していく
+ // ただし最後の要素が a.2 のように要素指定があればそれ以降は全く格納しない
+ if ( aptr != 0 ) pval = NULL;
+ is_last = 1;
+ aptr = 0;
+ }
+ if ( is_last ) {
+ aptr ++;
+ if ( pval != NULL && aptr >= pval->len[1] ) {
+ if ( pval->len[2] != 0 ) throw HSPVAR_ERROR_ARRAYOVER;
+ HspVarCoreReDim( pval, 1, aptr+1 );
+ }
+ } else {
+ aptr = code_getva( &pval );
+ }
+ if ( pval != NULL ) {
+ if ( newsptr == NULL ) {
+ code_setva( pval, aptr, HSPVAR_FLAG_STR, sptr );
+ } else {
+ var_set_str_len( pval, aptr, sptr, (int)(newsptr - sptr) );
+ }
+ }
+ n ++;
+ if ( newsptr == NULL ) {
+ // 格納する変数の数が分割できた数より多ければ残った変数それぞれに空文字列を格納する
+ while( ( *exinfo->npexflg & EXFLG_1 ) == 0 ) {
+ aptr = code_getva( &pval );
+ code_setva( pval, aptr, HSPVAR_FLAG_STR, "" );
+ }
+ break;
+ }
+ sptr = newsptr + sep_len;
+ }
+ ctx->stat = n;
+ break;
+ }
+
+ case 0x02b: // strrep
+ {
+ PVal *pval;
+ APTR aptr;
+ char *ss;
+ char *s_rep;
+ char *s_buffer;
+ char *s_match;
+ char *s_result;
+ int len_match;
+ int len_result;
+ int len_buffer;
+
+ aptr = code_getva( &pval );
+ if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ s_buffer = (char *)HspVarCorePtrAPTR( pval, aptr );
+
+ ss = code_gets();
+ if ( *ss == 0 ) throw HSPERR_ILLEGAL_FUNCTION;
+ len_match = (int)strlen( ss );
+ s_match = sbAlloc( len_match + 1 );
+ memcpy( s_match, ss, len_match + 1 );
+
+ len_buffer = (int)strlen( s_buffer );
+ len_result = len_buffer + 0x4000;
+ if ( len_result < 0x8000 ) len_result = 0x8000;
+ s_result = sbAlloc( len_result );
+ *s_result = 0;
+
+ s_rep = code_gets();
+
+ ReplaceSetMatch( s_buffer, s_match, s_result, len_buffer, len_match, len_result );
+ ReplaceStr( s_rep );
+
+ code_setva( pval, aptr, TYPE_STRING, s_result );
+ ctx->stat = ReplaceDone();
+ sbFree( s_match );
+ sbFree( s_result );
+ break;
+ }
+
+ case 0x02c: // setease
+ {
+ HSPREAL dval;
+ HSPREAL dval2;
+ dval = code_getd();
+ dval2 = code_getd();
+ p1 = code_getdi( ease_type );
+ setEase( p1, dval, dval2 );
+ break;
+ }
+
+ case 0x02d: // sortval
+ {
+ int a,i;
+ PVal *p1;
+ APTR ap;
+ int order;
+
+ ap = code_getva( &p1 ); // パラメータ1:変数
+ order = code_getdi( 0 ); // パラメータ2:数値
+
+ i=p1->len[1];
+ if (i<=0) throw HSPERR_ILLEGAL_FUNCTION;
+ switch(p1->flag) {
+ case HSPVAR_FLAG_DOUBLE:
+ {
+ double *dp;
+ dp=(double *)p1->pt;
+ DataIni( i );
+ for(a=0;apt;
+ DataIni( i );
+ for(a=0;aflag != 2 ) throw HSPERR_TYPE_MISMATCH;
+ if (( pv->len[2] != 0 )||( ap != 0 )) throw HSPERR_ILLEGAL_FUNCTION;
+
+ proc = HspVarCoreGetProc( pv->flag );
+
+ len = pv->len[1];
+ DataIni( len );
+
+ for(i=0;imaster); // 変数に直接sbポインタを書き戻す
+ for(i=0;ipt = dtmp[i].as.skey;
+ sbSetOption(pv->pt, &pv->pt);
+ } else {
+ pvstr[i] = dtmp[i].as.skey;
+ sbSetOption(pvstr[i], &pvstr[i]);
+ }
+ }
+ break;
+ }
+
+ case 0x02f: // sortnote
+ {
+ int i,sflag;
+ char *p;
+ char *stmp;
+ PVal *pv;
+ APTR ap;
+
+ ap = code_getva( &pv ); // パラメータ1:変数
+ sflag = code_getdi( 0 ); // パラメータ2:数値
+
+ p = (char *)HspVarCorePtrAPTR( pv, ap );
+ i = GetNoteLines(p);
+ if ( i <= 0 ) throw HSPERR_ILLEGAL_FUNCTION;
+
+ DataIni( i );
+
+ NoteToData( p, dtmp );
+ if (sflag == 0) {
+ std::sort(dtmp, dtmp + i, less_str_1);
+ }
+ else {
+ std::sort(dtmp, dtmp + i, less_str_0);
+ }
+
+ stmp = code_stmp( (int)DataToNoteLen( dtmp, i ) + 1 );
+ DataToNote( dtmp, stmp, i );
+
+ code_setva( pv, ap, HSPVAR_FLAG_STR, stmp ); // 変数に値を代入
+
+ break;
+ }
+
+ case 0x030: // sortget
+ {
+ PVal *pv;
+ APTR ap;
+ int result;
+ int n;
+
+ ap = code_getva( &pv );
+ n = code_getdi( 0 );
+
+ if ( dtmp == NULL ) throw HSPERR_ILLEGAL_FUNCTION;
+ if (0 <= n && n < dtmp_size ) {
+ result=dtmp[n].info;
+ } else {
+ result=0;
+ }
+ code_setva( pv, ap, HSPVAR_FLAG_INT, &result );
+ break;
+ }
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ return RUNMODE_RUN;
+}
+
+static int reffunc_intfunc_ivalue;
+static HSPREAL reffunc_intfunc_value;
+
+static void *reffunc_intfunc( int *type_res, int arg )
+{
+ // reffunc : TYPE_INTFUNC
+ // (内蔵関数)
+ //
+ void *ptr;
+ int chk;
+ HSPREAL dval;
+ HSPREAL dval2;
+ int ival;
+ char *sval;
+ int p1,p2,p3;
+
+ // '('で始まるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( *val != '(' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ // 返値のタイプをargをもとに設定する
+ // 0~255 : int
+ // 256~383 : string
+ // 384~511 : double(HSPREAL)
+ //
+ switch( arg>>7 ) {
+ case 2: // 返値がstr
+ *type_res = HSPVAR_FLAG_STR; // 返値のタイプを指定する
+ ptr = NULL; // 返値のポインタ
+ break;
+ case 3: // 返値がdouble
+ *type_res = HSPVAR_FLAG_DOUBLE; // 返値のタイプを指定する
+ ptr = &reffunc_intfunc_value; // 返値のポインタ
+ break;
+ default: // 返値がint
+ *type_res = HSPVAR_FLAG_INT; // 返値のタイプを指定する
+ ptr = &reffunc_intfunc_ivalue; // 返値のポインタ
+ break;
+ }
+
+ switch( arg ) {
+
+ // int function
+ case 0x000: // int
+ {
+ int *ip;
+ chk = code_get();
+ if ( chk <= PARAM_END ) { throw HSPERR_INVALID_FUNCPARAM; }
+ ip = (int *)HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_INT );
+ reffunc_intfunc_ivalue = *ip;
+ break;
+ }
+ case 0x001: // rnd
+ ival = code_geti();
+ if ( ival == 0 ) throw HSPERR_DIVIDED_BY_ZERO;
+#ifdef HSPRANDMT
+ {
+ std::uniform_int_distribution dist( 0, ival - 1 );
+ reffunc_intfunc_ivalue = dist( mt );
+ }
+#else
+ reffunc_intfunc_ivalue = rand()%ival;
+#endif
+ break;
+ case 0x002: // strlen
+ sval = code_gets();
+ reffunc_intfunc_ivalue = (int) STRLEN( sval );
+ break;
+
+ case 0x003: // length(3.0)
+ case 0x004: // length2(3.0)
+ case 0x005: // length3(3.0)
+ case 0x006: // length4(3.0)
+ {
+ PVal *pv;
+ pv = code_getpval();
+ reffunc_intfunc_ivalue = pv->len[ arg - 0x002 ];
+ break;
+ }
+
+ case 0x007: // vartype(3.0)
+ {
+ PVal *pv;
+ HspVarProc *proc;
+ if ( *type == TYPE_STRING ) {
+ sval = code_gets();
+ proc = HspVarCoreSeekProc( sval );
+ if ( proc == NULL ) throw HSPERR_ILLEGAL_FUNCTION;
+ reffunc_intfunc_ivalue = proc->flag;
+ } else {
+ code_getva( &pv );
+ reffunc_intfunc_ivalue = pv->flag;
+ }
+ break;
+ }
+
+ case 0x008: // gettime
+ ival = code_geti();
+ reffunc_intfunc_ivalue = gettime( ival );
+ break;
+
+ case 0x009: // peek
+ case 0x00a: // wpeek
+ case 0x00b: // lpeek
+ {
+ PVal *pval;
+ char *ptr;
+ int size;
+ ptr = code_getvptr( &pval, &size );
+ p1 = code_getdi( 0 );
+ if ( p1<0 ) throw HSPERR_ILLEGAL_FUNCTION;
+ ptr += p1;
+ if ( arg == 0x09 ) {
+ if ( (p1+1)>size ) throw HSPERR_ILLEGAL_FUNCTION;
+ reffunc_intfunc_ivalue = ((int)(*ptr)) & 0xff;
+ } else if ( arg == 0x0a ) {
+ if ( (p1+2)>size ) throw HSPERR_ILLEGAL_FUNCTION;
+ reffunc_intfunc_ivalue = ((int)(*(short *)ptr)) & 0xffff;
+ } else {
+ if ( (p1+4)>size ) throw HSPERR_ILLEGAL_FUNCTION;
+ reffunc_intfunc_ivalue = *(int *)ptr;
+ }
+ break;
+ }
+ case 0x00c: // varptr
+ {
+ PVal *pval;
+ APTR aptr;
+ PDAT *pdat;
+ STRUCTDAT *st;
+ if ( *type == TYPE_DLLFUNC ) {
+ st = &(ctx->mem_finfo[ *val ]);
+ reffunc_intfunc_ivalue = (int)(size_t)(st->proc);
+ code_next();
+ break;
+ }
+ aptr = code_getva( &pval );
+ pdat = HspVarCorePtrAPTR( pval, aptr );
+ reffunc_intfunc_ivalue = (int)(size_t)(pdat);
+ HspVarCoreGetBlockSize(pval, pdat, &ctx->strsize);
+ break;
+ }
+ case 0x00d: // varuse
+ {
+ PVal *pval;
+ APTR aptr;
+ PDAT *pdat;
+ aptr = code_getva( &pval );
+ if ( pval->support & HSPVAR_SUPPORT_VARUSE ) {
+ pdat = HspVarCorePtrAPTR( pval, aptr );
+ reffunc_intfunc_ivalue = HspVarCoreGetUsing( pval, pdat );
+ } else throw HSPERR_TYPE_MISMATCH;
+ break;
+ }
+ case 0x00e: // noteinfo
+ ival = code_getdi(0);
+ note_update();
+ switch( ival ) {
+ case 0:
+ reffunc_intfunc_ivalue = note.GetMaxLine();
+ break;
+ case 1:
+ reffunc_intfunc_ivalue = note.GetSize();
+ break;
+ default:
+ throw HSPERR_ILLEGAL_FUNCTION;
+ }
+ break;
+
+ case 0x00f: // instr
+ {
+ PVal *pval;
+ char *ptr;
+ char *ps;
+ char *ps2;
+ int size;
+ int p1;
+ ptr = code_getvptr( &pval, &size );
+ if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ p1 = code_getdi(0);
+ if ( p1 >= size ) throw HSPERR_BUFFER_OVERFLOW;
+ ps = code_gets();
+ if ( p1 >= 0 ) {
+ ptr += p1;
+ ps2 = strstr2( ptr, ps );
+ } else {
+ ps2 = NULL;
+ }
+ if ( ps2 == NULL ) {
+ reffunc_intfunc_ivalue = -1;
+ } else {
+ reffunc_intfunc_ivalue = (int)(ps2 - ptr);
+ }
+ break;
+ }
+
+ case 0x010: // abs
+ reffunc_intfunc_ivalue = code_geti();
+ if ( reffunc_intfunc_ivalue < 0 ) reffunc_intfunc_ivalue = -reffunc_intfunc_ivalue;
+ break;
+
+ case 0x011: // limit
+ p1 = code_geti();
+ p2 = code_getdi(INT_MIN);
+ p3 = code_getdi(INT_MAX);
+ reffunc_intfunc_ivalue = GetLimit( p1, p2, p3 );
+ break;
+
+ case 0x012: // getease
+ p1 = code_geti();
+ p2 = code_getdi(-1);
+ reffunc_intfunc_ivalue = getEaseInt( p1, p2 );
+ break;
+
+ case 0x013: // notefind
+ {
+ char *ps;
+ char *p;
+ int findopt;
+ ps = code_gets();
+ p = code_stmpstr( ps );
+ findopt = code_getdi(0);
+ note_update();
+ reffunc_intfunc_ivalue = note.FindLine( p, findopt );
+ break;
+ }
+
+ case 0x014: // varsize
+ {
+ PVal *pval;
+ APTR aptr;
+ PDAT *pdat;
+ STRUCTDAT *st;
+ if ( *type == TYPE_DLLFUNC ) {
+ st = &(ctx->mem_finfo[ *val ]);
+ reffunc_intfunc_ivalue = (int)(st->size);
+ code_next();
+ break;
+ }
+ aptr = code_getva( &pval );
+ pdat = HspVarCorePtrAPTR( pval, aptr );
+ HspVarCoreGetBlockSize(pval, pdat, &reffunc_intfunc_ivalue);
+ break;
+ }
+
+
+ // str function
+ case 0x100: // str
+ {
+ char *sp;
+ chk = code_get();
+ if ( chk <= PARAM_END ) { throw HSPERR_INVALID_FUNCPARAM; }
+ sp = (char *)HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_STR );
+ ptr = (void *)sp;
+ break;
+ }
+ case 0x101: // strmid
+ {
+ PVal *pval;
+ char *sptr;
+ char *p;
+ char chrtmp;
+ int size;
+ int i;
+ int slen;
+ sptr = code_getvptr( &pval, &size );
+ if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ p1 = code_geti();
+ p2 = code_geti();
+
+ slen=(int)strlen( sptr );
+ if ( p1 < 0 ) {
+ p1=slen - p2;
+ if ( p1 < 0 ) p1 = 0;
+ }
+ if ( p1 >= slen )
+ p2 = 0;
+ if ( p2 > slen ) p2 = slen;
+ sptr += p1;
+ ptr = p = code_stmp( p2 + 1 );
+ for(i=0;istmp;
+ strncpy( pathname, code_gets(), HSP_MAX_PATH-1 );
+ p1=code_geti();
+ getpath( pathname, p, p1 );
+ ptr = p;
+ break;
+ }
+ case 0x105: // strtrim
+ {
+ PVal *pval;
+ char *sptr;
+ char *p;
+ int size;
+ sptr = code_getvptr( &pval, &size );
+ if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ p1 = code_getdi(0);
+ p2 = code_getdi(32);
+ ptr = p = code_stmp( size + 1 );
+ strcpy( p, sptr );
+ switch( p1 ) {
+ case 0:
+ TrimCodeL( p, p2 );
+ TrimCodeR( p, p2 );
+ break;
+ case 1:
+ TrimCodeL( p, p2 );
+ break;
+ case 2:
+ TrimCodeR( p, p2 );
+ break;
+ case 3:
+ TrimCode( p, p2 );
+ break;
+ }
+ break;
+ }
+
+ // double function
+ case 0x180: // sin
+ dval = code_getd();
+ reffunc_intfunc_value = sin( dval );
+ break;
+ case 0x181: // cos
+ dval = code_getd();
+ reffunc_intfunc_value = cos( dval );
+ break;
+ case 0x182: // tan
+ dval = code_getd();
+ reffunc_intfunc_value = tan( dval );
+ break;
+ case 0x183: // atan
+ dval = code_getd();
+ dval2 = code_getdd( 1.0 );
+ reffunc_intfunc_value = atan2( dval, dval2 );
+ break;
+ case 0x184: // sqrt
+ dval = code_getd();
+ reffunc_intfunc_value = sqrt( dval );
+ break;
+ case 0x185: // double
+ {
+ HSPREAL *dp;
+ chk = code_get();
+ if ( chk <= PARAM_END ) { throw HSPERR_INVALID_FUNCPARAM; }
+ dp = (HSPREAL *)HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_DOUBLE );
+ reffunc_intfunc_value = *dp;
+ break;
+ }
+ case 0x186: // absf
+ reffunc_intfunc_value = code_getd();
+ if ( reffunc_intfunc_value < 0 ) reffunc_intfunc_value = -reffunc_intfunc_value;
+ break;
+ case 0x187: // expf
+ dval = code_getd();
+ reffunc_intfunc_value = exp( dval );
+ break;
+ case 0x188: // logf
+ dval = code_getd();
+ reffunc_intfunc_value = log( dval );
+ break;
+ case 0x189: // limitf
+ {
+ HSPREAL d1,d2,d3;
+ d1 = code_getd();
+ d2 = code_getdd(-DBLINF);
+ d3 = code_getdd(DBLINF);
+ if ( d1 < d2 ) d1 = d2;
+ if ( d1 > d3 ) d1 = d3;
+ reffunc_intfunc_value = d1;
+ break;
+ }
+ case 0x18a: // powf
+ dval = code_getd();
+ dval2 = code_getd();
+ reffunc_intfunc_value = pow( dval, dval2 );
+ break;
+ case 0x18b: // geteasef
+ dval = code_getd();
+ dval2 = code_getdd(1.0);
+ if ( dval2 == 1.0 ) {
+ reffunc_intfunc_value = getEase( dval );
+ } else {
+ reffunc_intfunc_value = getEase( dval, dval2 );
+ }
+ break;
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+
+ // ')'で終わるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( *val != ')' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ return ptr;
+}
+
+
+
+
+/*------------------------------------------------------------*/
+/*
+ controller
+*/
+/*------------------------------------------------------------*/
+
+static int termfunc_intcmd( int option )
+{
+ // termfunc : TYPE_INTCMD
+ // (内蔵)
+ //
+ return 0;
+}
+
+void hsp3typeinit_intcmd( HSP3TYPEINFO *info )
+{
+ ctx = info->hspctx;
+ exinfo = info->hspexinfo;
+ type = exinfo->nptype;
+ val = exinfo->npval;
+ initEase();
+
+ info->cmdfunc = cmdfunc_intcmd;
+ info->termfunc = termfunc_intcmd;
+}
+
+void hsp3typeinit_intfunc( HSP3TYPEINFO *info )
+{
+ info->reffunc = reffunc_intfunc;
+}
+
+
diff --git a/src/hsp3/hsp3int.h b/src/hsp3/hsp3int.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c0f73a46553375e4680b53995ca4bb58759bc39
--- /dev/null
+++ b/src/hsp3/hsp3int.h
@@ -0,0 +1,13 @@
+
+//
+// hsp3int.cpp header
+//
+#ifndef __hsp3int_h
+#define __hsp3int_h
+
+#include "hsp3struct.h"
+
+void hsp3typeinit_intcmd( HSP3TYPEINFO *info );
+void hsp3typeinit_intfunc( HSP3TYPEINFO *info );
+
+#endif
diff --git a/src/hsp3/hsp3struct.h b/src/hsp3/hsp3struct.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd05398dba045e92fdd8f417ae23bd4bdfe5c0fe
--- /dev/null
+++ b/src/hsp3/hsp3struct.h
@@ -0,0 +1,681 @@
+
+//
+// Structure for HSP
+//
+#ifndef __hsp3struct_h
+#define __hsp3struct_h
+
+#include "hspvar_core.h"
+
+/*
+ rev 43
+ mingw : error : HSPERROR が未定義
+ に対処
+*/
+#include "hsp3debug.h"
+
+#ifdef _WIN64
+#define PTR64BIT // ポインタは64bit
+#else
+#define PTR32BIT // ポインタは32bit
+#endif
+
+// command type
+#define TYPE_MARK 0
+#define TYPE_VAR 1
+#define TYPE_STRING 2
+#define TYPE_DNUM 3
+#define TYPE_INUM 4
+#define TYPE_STRUCT 5
+#define TYPE_XLABEL 6
+#define TYPE_LABEL 7
+#define TYPE_INTCMD 8
+#define TYPE_EXTCMD 9
+#define TYPE_EXTSYSVAR 10
+#define TYPE_CMPCMD 11
+#define TYPE_MODCMD 12
+#define TYPE_INTFUNC 13
+#define TYPE_SYSVAR 14
+#define TYPE_PROGCMD 15
+#define TYPE_DLLFUNC 16
+#define TYPE_DLLCTRL 17
+#define TYPE_USERDEF 18
+
+#define TYPE_ERROR -1
+#define TYPE_CALCERROR -2
+
+#define PARAM_OK 0
+#define PARAM_SPLIT -1
+#define PARAM_END -2
+#define PARAM_DEFAULT -3
+#define PARAM_ENDSPLIT -4
+
+#define HSP3_FUNC_MAX 18
+#define HSP3_TYPE_USER 18
+
+#define EXFLG_0 0x1000
+#define EXFLG_1 0x2000
+#define EXFLG_2 0x4000
+#define EXFLG_3 0x8000
+#define CSTYPE 0x0fff
+
+typedef struct HSPHED
+{
+ // HSP3.0 header structure
+ //
+
+ char h1; // magic code1
+ char h2; // magic code2
+ char h3; // magic code3
+ char h4; // magic code4
+ int version; // version number info
+ int max_val; // max count of VAL Object
+ int allsize; // total file size
+
+ int pt_cs; // ptr to Code Segment
+ int max_cs; // size of CS
+ int pt_ds; // ptr to Data Segment
+ int max_ds; // size of DS
+
+ int pt_ot; // ptr to Object Temp
+ int max_ot; // size of OT
+ int pt_dinfo; // ptr to Debug Info
+ int max_dinfo; // size of DI
+
+ int pt_linfo; // ptr to LibInfo(2.3)
+ int max_linfo; // size of LibInfo(2.3)
+ int pt_finfo; // ptr to FuncInfo(2.3)
+ int max_finfo; // size of FuncInfo(2.3)
+
+ int pt_minfo; // ptr to ModInfo(2.5)
+ int max_minfo; // size of ModInfo(2.5)
+ int pt_finfo2; // ptr to FuncInfo2(2.5)
+ int max_finfo2; // size of FuncInfo2(2.5)
+
+ int pt_hpidat; // ptr to HPIDAT(3.0)
+ short max_hpi; // size of HPIDAT(3.0)
+ short max_varhpi; // Num of Vartype Plugins(3.0)
+ int bootoption; // bootup options
+ int runtime; // ptr to runtime name
+
+ // HSP3.5 extra header structure
+ //
+ int pt_sr; // ptr to Option Segment
+ int max_sr; // size of Option Segment
+ int opt1; // option (reserved)
+ int opt2; // option (reserved)
+
+} HSPHED;
+
+#define HSPHED_BOOTOPT_DEBUGWIN 1 // 起動時デバッグウインドゥ表示
+#define HSPHED_BOOTOPT_WINHIDE 2 // 起動時ウインドゥ非表示
+#define HSPHED_BOOTOPT_DIRSAVE 4 // 起動時カレントディレクトリ変更なし
+#define HSPHED_BOOTOPT_SAVER 0x100 // スクリーンセーバー
+
+#define HSPHED_BOOTOPT_RUNTIME 0x1000 // 動的ランタイムを有効にする
+#define HSPHED_BOOTOPT_NOMMTIMER 0x2000 // マルチメディアタイマーを無効にする
+#define HSPHED_BOOTOPT_NOGDIP 0x4000 // GDI+による描画を無効にする
+#define HSPHED_BOOTOPT_FLOAT32 0x8000 // 実数を32bit floatとして処理する
+#define HSPHED_BOOTOPT_ORGRND 0x10000 // 標準の乱数発生を使用する
+#define HSPHED_BOOTOPT_UTF8 0x20000 // UTF8ランタイムを使用する(コード識別用)
+#define HSPHED_BOOTOPT_HSP64 0x40000 // 64bitランタイムを使用する(コード識別用)
+#define HSPHED_BOOTOPT_IORESUME 0x80000 // ファイルI/Oエラーを無視して処理を続行する
+
+
+#define HPIDAT_FLAG_TYPEFUNC 0
+#define HPIDAT_FLAG_SELFFUNC -1
+#define HPIDAT_FLAG_VARFUNC 1
+#define HPIDAT_FLAG_DLLFUNC 2
+
+typedef struct MEM_HPIDAT { // native HPIDAT
+
+ short flag; // flag info
+ short option;
+ int libname; // lib name index (DS)
+ int funcname; // function name index (DS)
+ void *libptr; // lib handle
+
+} MEM_HPIDAT;
+
+#ifdef PTR64BIT
+typedef struct HPIDAT {
+
+ short flag; // flag info
+ short option;
+ int libname; // lib name index (DS)
+ int funcname; // function name index (DS)
+ int p_libptr; // lib handle
+
+} HPIDAT;
+#else
+typedef MEM_HPIDAT HPIDAT;
+#endif
+
+
+#define LIBDAT_FLAG_NONE 0
+#define LIBDAT_FLAG_DLL 1
+#define LIBDAT_FLAG_DLLINIT 2
+#define LIBDAT_FLAG_MODULE 3
+#define LIBDAT_FLAG_COMOBJ 4
+
+typedef struct LIBDAT {
+
+ int flag; // initalize flag
+ int nameidx; // function name index (DS)
+ // Interface IID ( Com Object )
+ void *hlib; // Lib handle
+ int clsid; // CLSID (DS) ( Com Object )
+
+} LIBDAT;
+
+#ifdef PTR64BIT
+typedef struct HED_LIBDAT {
+
+ int flag; // initalize flag
+ int nameidx; // function name index (DS)
+ // Interface IID ( Com Object )
+ int p_hlib; // Lib handle
+ int clsid; // CLSID (DS) ( Com Object )
+
+} HED_LIBDAT;
+#else
+typedef LIBDAT HED_LIBDAT;
+#endif
+
+
+// multi parameter type
+#define MPTYPE_NONE 0
+#define MPTYPE_VAR 1
+#define MPTYPE_STRING 2
+#define MPTYPE_DNUM 3
+#define MPTYPE_INUM 4
+#define MPTYPE_STRUCT 5
+#define MPTYPE_LABEL 7
+
+#define MPTYPE_LOCALVAR -1
+#define MPTYPE_ARRAYVAR -2
+#define MPTYPE_SINGLEVAR -3
+#define MPTYPE_FLOAT -4
+#define MPTYPE_STRUCTTAG -5
+#define MPTYPE_LOCALSTRING -6
+#define MPTYPE_MODULEVAR -7
+#define MPTYPE_PPVAL -8
+#define MPTYPE_PBMSCR -9
+#define MPTYPE_PVARPTR -10
+#define MPTYPE_IMODULEVAR -11
+
+#define MPTYPE_IOBJECTVAR -12
+#define MPTYPE_LOCALWSTR -13
+#define MPTYPE_FLEXSPTR -14
+#define MPTYPE_FLEXWPTR -15
+#define MPTYPE_PTR_REFSTR -16
+#define MPTYPE_PTR_EXINFO -17
+#define MPTYPE_PTR_DPMINFO -18
+#define MPTYPE_NULLPTR -19
+#define MPTYPE_TMODULEVAR -20
+
+//#define MPTYPE_PTR_HWND -14
+//#define MPTYPE_PTR_HDC -15
+//#define MPTYPE_PTR_HINST -16
+
+#define STRUCTPRM_SUBID_STACK -1
+#define STRUCTPRM_SUBID_STID -2
+#define STRUCTPRM_SUBID_DLL -3
+#define STRUCTPRM_SUBID_DLLINIT -4
+#define STRUCTPRM_SUBID_OLDDLL -5
+#define STRUCTPRM_SUBID_OLDDLLINIT -6
+#define STRUCTPRM_SUBID_COMOBJ -7
+
+#define STRUCTCODE_THISMOD -1
+
+#define TYPE_OFFSET_COMOBJ 0x1000
+
+typedef struct STRUCTPRM {
+ short mptype; // Parameter type
+ short subid; // struct index
+ int offset; // offset from top
+} STRUCTPRM;
+
+// DLL function flags
+#define STRUCTDAT_OT_NONE 0
+#define STRUCTDAT_OT_CLEANUP 1
+#define STRUCTDAT_OT_STATEMENT 2
+#define STRUCTDAT_OT_FUNCTION 4
+
+// Module function flags
+#define STRUCTDAT_INDEX_FUNC -1
+#define STRUCTDAT_INDEX_CFUNC -2
+#define STRUCTDAT_INDEX_STRUCT -3
+#define STRUCTDAT_FUNCFLAG_CLEANUP 0x10000
+
+// function,module specific data
+
+#ifdef PTR64BIT
+typedef struct STRUCTDAT {
+ short index; // base LIBDAT index
+ short subid; // struct index
+ int prmindex; // STRUCTPRM index(MINFO)
+ int prmmax; // number of STRUCTPRM
+ int nameidx; // name index (DS)
+ int size; // struct size (stack)
+ int otindex; // OT index(Module) / cleanup flag(Dll)
+ void *proc; // proc address
+ int funcflag; // function flags(Module)
+} STRUCTDAT;
+
+typedef struct HED_STRUCTDAT {
+ short index; // base LIBDAT index
+ short subid; // struct index
+ int prmindex; // STRUCTPRM index(MINFO)
+ int prmmax; // number of STRUCTPRM
+ int nameidx; // name index (DS)
+ int size; // struct size (stack)
+ int otindex; // OT index(Module) / cleanup flag(Dll)
+ int funcflag; // function flags(Module)
+} HED_STRUCTDAT;
+
+#else
+typedef struct STRUCTDAT {
+ short index; // base LIBDAT index
+ short subid; // struct index
+ int prmindex; // STRUCTPRM index(MINFO)
+ int prmmax; // number of STRUCTPRM
+ int nameidx; // name index (DS)
+ int size; // struct size (stack)
+ int otindex; // OT index(Module) / cleanup flag(Dll)
+ union {
+ void *proc; // proc address
+ int funcflag; // function flags(Module)
+ };
+} STRUCTDAT;
+typedef STRUCTDAT HED_STRUCTDAT;
+#endif
+
+
+// Var Data for Multi Parameter
+typedef struct MPVarData {
+ PVal *pval;
+ APTR aptr;
+} MPVarData;
+
+// Var Data for Module Function
+typedef struct MPModVarData {
+ short subid;
+ short magic;
+ PVal *pval;
+ APTR aptr;
+} MPModVarData;
+#define MODVAR_MAGICCODE 0x55aa
+
+#define IRQ_FLAG_NONE 0
+#define IRQ_FLAG_DISABLE 1
+#define IRQ_FLAG_ENABLE 2
+#define IRQ_OPT_GOTO 0
+#define IRQ_OPT_GOSUB 1
+#define IRQ_OPT_CALLBACK 2
+
+
+typedef struct IRQDAT {
+ short flag; // flag
+ short opt; // option value
+ int custom; // custom message value
+ int custom2; // custom message value2
+ int iparam; // iparam option
+ unsigned short *ptr; // jump ptr
+ void (*callback)(struct IRQDAT *,int,int); // IRQ callback function
+} IRQDAT;
+
+typedef struct HSPCTX HSPCTX;
+
+// Plugin info data (3.0 compatible)
+typedef struct HSPEXINFO30
+{
+ // HSP internal info data (2.6)
+ //
+ short ver; // Version Code
+ short min; // Minor Version
+ //
+ int *er; // Not Use
+ char *pstr; // String Buffer (master)
+ char *stmp; // String Buffer (sub)
+ PVal **mpval; // Master PVAL
+ //
+ int *actscr; // Active Window ID
+ int *nptype; // Next Parameter Type
+ int *npval; // Next Parameter Value
+ int *strsize; // StrSize Buffer
+ char *refstr; // RefStr Buffer
+ //
+ void *(*HspFunc_prm_getv)( void );
+ int (*HspFunc_prm_geti)( void );
+ int (*HspFunc_prm_getdi)( const int defval );
+ char *(*HspFunc_prm_gets)( void );
+ char *(*HspFunc_prm_getds)( const char *defstr );
+ int (*HspFunc_val_realloc)( PVal *pv, int size, int mode );
+ int (*HspFunc_fread)( char *fname, void *readmem, int rlen, int seekofs );
+ int (*HspFunc_fsize)( char *fname );
+ void *(*HspFunc_getbmscr)( int wid );
+ int (*HspFunc_getobj)( int wid, int id, void *inf );
+ int (*HspFunc_setobj)( int wid, int id, const void *inf );
+
+ // HSP internal info data (3.0)
+ //
+ int *npexflg; // Next Parameter ExFlg
+ HSPCTX *hspctx; // HSP context ptr
+
+ // Enhanced data (3.0)
+ //
+ int (*HspFunc_addobj)( int wid );
+ void (*HspFunc_puterror)( HSPERROR error );
+ HspVarProc *(*HspFunc_getproc)( int type );
+ HspVarProc *(*HspFunc_seekproc)( const char *name );
+
+ void (*HspFunc_prm_next)( void );
+ int (*HspFunc_prm_get)( void );
+ double (*HspFunc_prm_getd)( void );
+ double (*HspFunc_prm_getdd)( double defval );
+ unsigned short *(*HspFunc_prm_getlb)( void );
+ PVal *(*HspFunc_prm_getpval)( void );
+ APTR (*HspFunc_prm_getva)( PVal **pval );
+ void (*HspFunc_prm_setva)( PVal *pval, APTR aptr, int type, const void *ptr );
+ char *(*HspFunc_malloc)( int size );
+ void (*HspFunc_free)( void *ptr );
+ char *(*HspFunc_expand)( char *ptr, int size );
+ IRQDAT *(*HspFunc_addirq)( void );
+ int (*HspFunc_hspevent)( int event, int prm1, int prm2, void *prm3 );
+ void (*HspFunc_registvar)( int flag, HSPVAR_COREFUNC func );
+ void (*HspFunc_setpc)( const unsigned short *pc );
+ void (*HspFunc_call)( const unsigned short *pc );
+ void (*HspFunc_mref)( PVal *pval, int prm );
+
+ void (*HspFunc_dim)( PVal *pval, int flag, int len0, int len1, int len2, int len3, int len4 );
+ void (*HspFunc_redim)( PVal *pval, int lenid, int len );
+ void (*HspFunc_array)( PVal *pval, int offset );
+
+} HSPEXINFO30;
+
+
+
+// Plugin info data (3.1 or later)
+typedef struct HSPEXINFO
+{
+ // HSP internal info data (2.6)
+ //
+ short ver; // Version Code
+ short min; // Minor Version
+ //
+ int *er; // Not Use
+ char *pstr; // String Buffer (master)
+ char *stmp; // String Buffer (sub)
+ PVal **mpval; // Master PVAL
+ //
+ int *actscr; // Active Window ID
+ int *nptype; // Next Parameter Type
+ int *npval; // Next Parameter Value
+ int *strsize; // StrSize Buffer
+ char *refstr; // RefStr Buffer
+ //
+ void *(*HspFunc_prm_getv)( void );
+ int (*HspFunc_prm_geti)( void );
+ int (*HspFunc_prm_getdi)( const int defval );
+ char *(*HspFunc_prm_gets)( void );
+ char *(*HspFunc_prm_getds)( const char *defstr );
+ int (*HspFunc_val_realloc)( PVal *pv, int size, int mode );
+ int (*HspFunc_fread)( char *fname, void *readmem, int rlen, int seekofs );
+ int (*HspFunc_fsize)( char *fname );
+ void *(*HspFunc_getbmscr)( int wid );
+ int (*HspFunc_getobj)( int wid, int id, void *inf );
+ int (*HspFunc_setobj)( int wid, int id, const void *inf );
+
+ // HSP internal info data (3.0)
+ //
+ int *npexflg; // Next Parameter ExFlg
+ HSPCTX *hspctx; // HSP context ptr
+
+ // Enhanced data (3.0)
+ //
+ int (*HspFunc_addobj)( int wid );
+ void (*HspFunc_puterror)( HSPERROR error );
+ HspVarProc *(*HspFunc_getproc)( int type );
+ HspVarProc *(*HspFunc_seekproc)( const char *name );
+
+ void (*HspFunc_prm_next)( void );
+ int (*HspFunc_prm_get)( void );
+ double (*HspFunc_prm_getd)( void );
+ double (*HspFunc_prm_getdd)( double defval );
+ unsigned short *(*HspFunc_prm_getlb)( void );
+ PVal *(*HspFunc_prm_getpval)( void );
+ APTR (*HspFunc_prm_getva)( PVal **pval );
+ void (*HspFunc_prm_setva)( PVal *pval, APTR aptr, int type, const void *ptr );
+ char *(*HspFunc_malloc)( int size );
+ void (*HspFunc_free)( void *ptr );
+ char *(*HspFunc_expand)( char *ptr, int size );
+ IRQDAT *(*HspFunc_addirq)( void );
+ int (*HspFunc_hspevent)( int event, int prm1, int prm2, void *prm3 );
+ void (*HspFunc_registvar)( int flag, HSPVAR_COREFUNC func );
+ void (*HspFunc_setpc)( const unsigned short *pc );
+ void (*HspFunc_call)( const unsigned short *pc );
+ void (*HspFunc_mref)( PVal *pval, int prm );
+
+ void (*HspFunc_dim)( PVal *pval, int flag, int len0, int len1, int len2, int len3, int len4 );
+ void (*HspFunc_redim)( PVal *pval, int lenid, int len );
+ void (*HspFunc_array)( PVal *pval, int offset );
+
+ // Enhanced data (3.1)
+ //
+ char *(*HspFunc_varname)( int id );
+ int (*HspFunc_seekvar)( const char *name );
+
+ // Enhanced data (3.5)
+ //
+ char *(*HspFunc_prm_getns)(void);
+ char *(*HspFunc_prm_getnds)(const char *defstr);
+
+} HSPEXINFO;
+
+
+#define HSP3_REPEAT_MAX 32
+typedef struct LOOPDAT {
+ int time; // loop times left
+ int cnt; // count
+ int step; // count add value
+ unsigned short *pt; // loop start ptr
+} LOOPDAT;
+
+
+// 実行モード
+enum
+{
+RUNMODE_RUN = 0,
+RUNMODE_WAIT,
+RUNMODE_AWAIT,
+RUNMODE_STOP,
+RUNMODE_END,
+RUNMODE_ERROR,
+RUNMODE_RETURN,
+RUNMODE_INTJUMP,
+RUNMODE_ASSERT,
+RUNMODE_LOGMES,
+RUNMODE_EXITRUN,
+RUNMODE_MAX
+};
+
+
+struct HSPCTX
+{
+ // HSP Context
+ //
+ HSPHED *hsphed; // HSP object file header
+ unsigned short *mcs; // current code segment ptr
+ unsigned short *mem_mcs; // code segment ptr
+ char *mem_mds; // data segment ptr
+ unsigned char *mem_di; // Debug info ptr
+ int *mem_ot; // object temp segment ptr
+
+ IRQDAT *mem_irq; // IRQ data ptr
+ int irqmax; // IRQ data count
+ int iparam; // IRQ Info data1
+ int wparam; // IRQ Info data2
+ int lparam; // IRQ Info data3
+
+ PVal *mem_var; // var storage index
+ HSPEXINFO30 exinfo; // HSP function data(3.0)
+ int runmode; // HSP execute mode
+ int waitcount; // counter for wait
+ int waitbase; // wait sleep base
+ int waittick; // next tick for await
+ int lasttick; // previous tick
+ int sublev; // subroutine level
+ LOOPDAT mem_loop[HSP3_REPEAT_MAX]; // repeat loop info
+ int looplev; // repeat loop level
+ HSPERROR err; // error code
+ int hspstat; // HSP status
+ int stat; // sysvar 'stat'
+ int strsize; // sysvar 'strsize'
+ char *refstr; // RefStr Buffer
+ char *fnbuffer; // buffer for FILENAME
+ void *instance; // Instance Handle (windows)
+ int intwnd_id; // Window ID (interrupt)
+ PVal *note_pval; // MemNote pval
+ APTR note_aptr; // MemNote aptr
+ PVal *notep_pval; // MemNote pval (previous)
+ APTR notep_aptr; // MemNote aptr (previous)
+ char *stmp; // String temporary buffer
+
+ void *prmstack; // Current parameter stack area
+ LIBDAT *mem_linfo; // Library info
+ STRUCTPRM *mem_minfo; // Parameter info
+ STRUCTDAT *mem_finfo; // Function/Struct info
+ int retval_level; // subroutine level (return code)
+ int endcode; // End result code
+ void (*msgfunc) (HSPCTX *); // Message Callback Proc.
+ void *wnd_parent; // Parent Window Handle
+ double refdval; // sysvar 'refdval'
+ char *cmdline; // Command Line Parameters
+
+ HSPEXINFO *exinfo2; // HSP function data(3.1)
+
+ int prmstack_max; // Parameter Stack Max(hsp3cnv) (3.3)
+};
+
+#define HSPCTX_REFSTR_MAX 4096
+#define HSPCTX_CMDLINE_MAX 1024
+
+#define HSPSTAT_NORMAL 0
+#define HSPSTAT_DEBUG 1
+#define HSPSTAT_SSAVER 2
+#define HSPSTAT_CONSOLE 0x10
+#define HSPSTAT_MAC 0x80
+#define HSPSTAT_DISH 0x100
+#define HSPSTAT_LINUX 0x1000
+#define HSPSTAT_UTF8 0x20000
+#define HSPSTAT_HSP64 0x40000
+
+#define TYPE_EX_SUBROUTINE 0x100 // gosub用のスタックタイプ
+#define TYPE_EX_CUSTOMFUNC 0x101 // deffunc呼び出し用のスタックタイプ
+#define TYPE_EX_ENDOFPARAM 0x200 // パラメーター終端(HSPtoC)
+#define TYPE_EX_ARRAY_VARS 0x201 // 配列要素付き変数用スタックタイプ(HSPtoC)
+#define TYPE_EX_LOCAL_VARS 0x202 // ローカル変数用スタックタイプ(HSPtoC)
+
+typedef struct
+{
+ // Subroutine Context
+ //
+ int stacklev; // サブルーチン開始時のスタックレベル
+ unsigned short *mcsret; // 呼び出し元PCポインタ(復帰用)
+ STRUCTDAT *param; // 引数パラメーターリスト
+ void *oldtack; // 以前のスタックアドレス
+ int oldlev; // 以前のスタックレベル
+
+} HSPROUTINE;
+
+
+
+// コールバックのオプション
+//
+#define HSPEVENT_ENABLE_COMMAND 1 // 1ステップ実行時
+#define HSPEVENT_ENABLE_HSPIRQ 2 // HSP内での割り込み発生時
+#define HSPEVENT_ENABLE_GETKEY 4 // キーチェック時
+#define HSPEVENT_ENABLE_FILE 8 // ファイル入出力時
+#define HSPEVENT_ENABLE_MEDIA 16 // メディア入出力時
+#define HSPEVENT_ENABLE_PICLOAD 32 // picload命令実行時
+
+
+// ファンクション型
+//
+typedef int (* HSP3_CMDFUNC) (int);
+typedef void *(* HSP3_REFFUNC) (int *,int);
+typedef int (* HSP3_TERMFUNC) (int);
+typedef int (* HSP3_MSGFUNC) (int,int,int);
+typedef int (* HSP3_EVENTFUNC) (int,int,int,void *);
+
+
+typedef struct {
+ // 型ごとの情報
+ // (*の項目は、親アプリケーションで設定されます)
+ //
+ short type; // *型タイプ値
+ short option; // *オプション情報
+ HSPCTX *hspctx; // *HSP Context構造体へのポインタ
+ HSPEXINFO *hspexinfo; // *HSPEXINFO構造体へのポインタ
+
+ // ファンクション情報
+ //
+ int (* cmdfunc) (int); // コマンド受け取りファンクション
+ void *(* reffunc) (int *,int); // 参照受け取りファンクション
+ int (* termfunc) (int); // 終了受け取りファンクション
+
+ // イベントコールバックファンクション
+ //
+ int (* msgfunc) (int,int,int); // Windowメッセージコールバック
+ int (* eventfunc) (int,int,int,void *); // HSPイベントコールバック
+
+} HSP3TYPEINFO;
+
+
+// HSP割り込みID
+enum
+{
+HSPIRQ_ONEXIT = 0,
+HSPIRQ_ONERROR,
+HSPIRQ_ONKEY,
+HSPIRQ_ONCLICK,
+HSPIRQ_USERDEF,
+HSPIRQ_MAX
+};
+
+// HSPイベントID
+enum
+{
+HSPEVENT_NONE = 0,
+HSPEVENT_COMMAND,
+HSPEVENT_HSPIRQ,
+HSPEVENT_GETKEY,
+HSPEVENT_STICK,
+HSPEVENT_FNAME,
+HSPEVENT_FREAD,
+HSPEVENT_FWRITE,
+HSPEVENT_FEXIST,
+HSPEVENT_FDELETE,
+HSPEVENT_FMKDIR,
+HSPEVENT_FCHDIR,
+HSPEVENT_FCOPY,
+HSPEVENT_FDIRLIST1,
+HSPEVENT_FDIRLIST2,
+HSPEVENT_GETPICSIZE,
+HSPEVENT_PICLOAD,
+HSPEVENT_MAX
+};
+
+// ginfo拡張用フィーメド
+#define GINFO_EXINFO_MAX 16
+#define GINFO_EXINFO_BASE 0x100
+#define GINFO_EXINFO_ACCEL_X (GINFO_EXINFO_BASE+0)
+#define GINFO_EXINFO_ACCEL_Y (GINFO_EXINFO_BASE+1)
+#define GINFO_EXINFO_ACCEL_Z (GINFO_EXINFO_BASE+2)
+#define GINFO_EXINFO_GYRO_X (GINFO_EXINFO_BASE+3)
+#define GINFO_EXINFO_GYRO_Y (GINFO_EXINFO_BASE+4)
+#define GINFO_EXINFO_GYRO_Z (GINFO_EXINFO_BASE+5)
+
+
+#endif
diff --git a/src/hsp3/hspvar_core.cpp b/src/hsp3/hspvar_core.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2175df69ba770558d6eb30d3649d88cc4130050f
--- /dev/null
+++ b/src/hsp3/hspvar_core.cpp
@@ -0,0 +1,378 @@
+
+//
+// HSPVAR manager
+// onion software/onitama 2003/4
+//
+#include
+#include
+#include "hspvar_core.h"
+#include "hspvar_label.h"
+#include "hsp3debug.h"
+
+/*
+ rev 43
+ たぶんシステムヘッダ。それともカスタムヘッダを使うのか? (naznyark)
+*/
+#include "string.h"
+#include "strbuf.h"
+#include "supio.h"
+
+PVal *mem_pval;
+
+extern void HspVarInt_Init( HspVarProc *p );
+extern void HspVarStr_Init( HspVarProc *p );
+extern void HspVarDouble_Init( HspVarProc *p );
+extern void HspVarStruct_Init( HspVarProc *p );
+
+/*------------------------------------------------------------*/
+/*
+ master pointer
+*/
+/*------------------------------------------------------------*/
+
+HspVarProc *hspvarproc;
+int hspvartype_max;
+int hspvartype_limit;
+
+void HspVarCoreInit( void )
+{
+ int i;
+ hspvarproc = (HspVarProc *)sbAlloc( sizeof(HspVarProc) * HSPVAR_FLAG_MAX );
+ hspvartype_max = HSPVAR_FLAG_MAX;
+ for(i=0;imode = HSPVAR_MODE_NONE;
+ pval->flag = HSPVAR_FLAG_INT; // 仮の型
+ }
+}
+
+void HspVarCoreBye( void )
+{
+ int i;
+ for(i=0;i= 0 ) {
+ hspvarproc = (HspVarProc *)sbExpand( (char *)hspvarproc, sizeof(HspVarProc) * hspvartype_limit );
+ mem_pval = (PVal *)sbExpand( (char *)mem_pval, sizeof(PVal) * hspvartype_limit );
+ }
+
+ // 標準の型を登録する
+ //
+ HspVarCoreRegisterType( HSPVAR_FLAG_INT, (HSPVAR_COREFUNC)HspVarInt_Init );
+ HspVarCoreRegisterType( HSPVAR_FLAG_STR, (HSPVAR_COREFUNC)HspVarStr_Init );
+ HspVarCoreRegisterType( HSPVAR_FLAG_DOUBLE, (HSPVAR_COREFUNC)HspVarDouble_Init );
+ HspVarCoreRegisterType( HSPVAR_FLAG_STRUCT, (HSPVAR_COREFUNC)HspVarStruct_Init );
+ HspVarCoreRegisterType( HSPVAR_FLAG_LABEL, (HSPVAR_COREFUNC)HspVarLabel_Init ); // ラベル型(3.1)
+}
+
+
+int HspVarCoreAddType()
+{
+ int id;
+ PVal *pval;
+ if ( hspvartype_max >= hspvartype_limit ) return -1;
+ id = hspvartype_max++;
+ //hspvarproc = (HspVarProc *)sbExpand( (char *)hspvarproc, sizeof(HspVarProc) * hspvartype_max );
+ hspvarproc[id].flag = 0;
+ //mem_pval = (PVal *)sbExpand( (char *)mem_pval, sizeof(PVal) * hspvartype_max );
+ pval = &mem_pval[id];
+ pval->mode = HSPVAR_MODE_NONE;
+ pval->flag = HSPVAR_FLAG_INT; // 仮の型
+ return id;
+}
+
+
+static void PutInvalid( void )
+{
+ throw( HSPERR_UNSUPPORTED_FUNCTION );
+}
+
+
+void HspVarCoreRegisterType( int flag, HSPVAR_COREFUNC func )
+{
+ int id;
+ void **procs;
+ HspVarProc *p;
+
+ id = flag;
+ if ( id < 0 ) {
+ id = HspVarCoreAddType();
+ if ( id < 0 ) return;
+ }
+ p = &hspvarproc[ id ];
+ p->flag = p->aftertype = id;
+
+ procs = (void **)(&p->Cnv);
+ while(1) {
+ *procs = (void *)(PutInvalid);
+ if ( procs == (void **)(&p->LrI) ) break;
+ procs++;
+ }
+
+ // 初期化関数の呼び出し
+
+ func( p );
+}
+
+
+/*------------------------------------------------------------*/
+
+void HspVarCoreDupPtr( PVal *pval, int flag, void *ptr, int size )
+{
+ // 指定されたポインタからのクローンになる
+ //
+ PDAT *buf;
+ HspVarProc *p;
+ p = &hspvarproc[ flag ];
+ buf = (PDAT *)ptr;
+
+ HspVarCoreDispose( pval );
+ pval->pt = (char *)buf;
+ pval->flag = flag;
+ pval->size = size;
+ pval->mode = HSPVAR_MODE_CLONE;
+ pval->len[0] = 1;
+
+ if ( p->basesize < 0 ) {
+ pval->len[1] = 1;
+ } else {
+ pval->len[1] = size / p->basesize;
+ }
+ pval->len[2] = 0;
+ pval->len[3] = 0;
+ pval->len[4] = 0;
+ pval->offset = 0;
+ pval->arraycnt = 0;
+ pval->support = HSPVAR_SUPPORT_STORAGE;
+}
+
+
+void HspVarCoreDup( PVal *pval, PVal *arg, APTR aptr )
+{
+ // 指定された変数のクローンになる
+ //
+ int size;
+ PDAT *buf;
+ HspVarProc *p;
+ p = &hspvarproc[ arg->flag ];
+ buf = HspVarCorePtrAPTR( arg, aptr );
+ HspVarCoreGetBlockSize( arg, buf, &size );
+ HspVarCoreDupPtr( pval, arg->flag, buf, size );
+}
+
+
+void HspVarCoreDim( PVal *pval, int flag, int len1, int len2, int len3, int len4 )
+{
+ // 配列を確保する
+ // (len1~len4は、4byte単位なので注意)
+ //
+ HspVarProc *p;
+ p = &hspvarproc[ flag ];
+ if ((len1<0)||(len2<0)||(len3<0)||(len4<0)) throw HSPVAR_ERROR_ILLEGALPRM;
+
+ HspVarCoreDispose( pval );
+
+ pval->flag = flag;
+ pval->len[0] = 1;
+ pval->offset = 0;
+ pval->arraycnt = 0;
+ pval->support = p->support;
+ pval->len[1] = len1;
+ pval->len[2] = len2;
+ pval->len[3] = len3;
+ pval->len[4] = len4;
+ p->Alloc( pval, NULL );
+}
+
+
+void HspVarCoreDimFlex( PVal *pval, int flag, int len0, int len1, int len2, int len3, int len4 )
+{
+ // 配列を確保する(可変長配列用)
+ // (len1~len4は、4byte単位なので注意)
+ //
+ HspVarProc *p;
+ p = &hspvarproc[ flag ];
+ if ((len1<0)||(len2<0)||(len3<0)||(len4<0)) throw HSPVAR_ERROR_ILLEGALPRM;
+ HspVarCoreDispose( pval );
+ pval->flag = flag;
+ pval->len[0] = len0;
+ pval->offset = 0;
+ pval->arraycnt = 0;
+ pval->support = p->support;
+ pval->len[1] = len1;
+ pval->len[2] = len2;
+ pval->len[3] = len3;
+ pval->len[4] = len4;
+ p->Alloc( pval, NULL );
+ pval->len[0] = 1;
+}
+
+
+void HspVarCoreReDim( PVal *pval, int lenid, int len )
+{
+ // 配列を拡張する
+ //
+ HspVarProc *p;
+ p = &hspvarproc[ pval->flag ];
+ pval->len[lenid] = len;
+ p->Alloc( pval, pval );
+}
+
+
+void HspVarCoreClear( PVal *pval, int flag )
+{
+ // 指定タイプの変数を最小メモリで初期化する
+ //
+ HspVarCoreDim( pval, flag, 1, 0, 0, 0 ); // 最小サイズのメモリを確保
+}
+
+
+void HspVarCoreClearTemp( PVal *pval, int flag )
+{
+ // 指定タイプの変数を最小メモリで初期化する(テンポラリ用)
+ //
+ HspVarCoreDim( pval, flag, 1, 0, 0, 0 ); // 最小サイズのメモリを確保
+ pval->support |= HSPVAR_SUPPORT_TEMPVAR;
+}
+
+
+void *HspVarCoreCnvPtr( PVal *pval, int flag )
+{
+ // 指定されたtypeフラグに変換された値のポインタを得る
+ //
+ if ( pval->flag == flag ) {
+ return hspvarproc[ flag ].GetPtr( pval );
+ }
+ // 型変換をする
+ void *buf;
+ buf = hspvarproc[ pval->flag ].GetPtr( pval );
+ if ( pval->flag >= HSPVAR_FLAG_USERDEF ) {
+ return ( hspvarproc[ pval->flag ].CnvCustom( buf, flag ) );
+ }
+ return ( hspvarproc[ flag ].Cnv( buf, pval->flag ) );
+}
+
+
+#if 0
+PDAT *HspVarCorePtrAPTR( PVal *pv, APTR ofs )
+{
+ // 変数データの実態ポインタを得る
+ // (APTRとpvalから実態を求める)
+ //
+ pv->offset=ofs;
+ return hspvarproc[(pv)->flag].GetPtr(pv);
+}
+#endif
+
+
+HspVarProc *HspVarCoreSeekProc( const char *name )
+{
+ int i;
+ HspVarProc *p;
+ for(i=0;iflag ) {
+ if ( strcmp( p->vartype_name, name )==0 ) {
+ return p;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+void HspVarCoreArray( PVal *pval, int offset )
+{
+ // 配列要素の指定 (index)
+ // ( Reset後に次元数だけ連続で呼ばれます )
+ //
+ if ( pval->arraycnt >= 5 ) throw HSPVAR_ERROR_ARRAYOVER;
+ if ( pval->arraycnt == 0 ) {
+ pval->arraymul = 1; // 最初の値
+ } else {
+ pval->arraymul *= pval->len[ pval->arraycnt ];
+ }
+ pval->arraycnt++;
+ if ( offset < 0 ) throw HSPVAR_ERROR_ARRAYOVER;
+ if ( offset >= (pval->len[ pval->arraycnt ]) ) {
+ throw HSPVAR_ERROR_ARRAYOVER;
+ }
+ pval->offset += offset * pval->arraymul;
+}
+
+
+int HspVarCoreCountElems( PVal *pval )
+{
+ int k = pval->len[1];
+ if ( pval->len[2] ) k *= pval->len[2];
+ if ( pval->len[3] ) k *= pval->len[3];
+ if ( pval->len[4] ) k *= pval->len[4];
+ return k;
+}
+
+
+void HspVarCoreAllocPODArray( PVal *pval, const PVal *pval2, int basesize )
+{
+ // pval変数が必要とするサイズを確保する。
+ // (pvalがすでに確保されているメモリ解放は呼び出し側が行なう)
+ // (flagの設定は呼び出し側が行なう)
+ // (pval2がNULLの場合は、新規データ)
+ // (pval2が指定されている場合は、pval2の内容を継承して再確保)
+ //
+
+ // 配列を最低1は確保する
+ if ( pval->len[1] < 1 ) pval->len[1] = 1;
+
+ int size = HspVarCoreCountElems(pval) * basesize;
+ int old_size = (pval2 ? pval2->size : 0);
+
+ char *pt;
+ if ( pval == pval2 ) {
+ if ( size > STRBUF_BLOCKSIZE ) {
+ size = (size > old_size ? size + size / 8 : old_size);
+ }
+ pt = sbExpand(pval->pt, size);
+ } else {
+ pt = sbAlloc(size);
+
+ if ( pval2 != NULL ) {
+ memcpy(pt, pval2->pt, pval2->size);
+ sbFree(pval->pt);
+ }
+ }
+
+ // 新規要素を0埋め
+ if ( size > old_size ) {
+ memset(pt + old_size, 0, (size - old_size));
+ }
+
+ pval->pt = pt;
+ pval->size = size;
+ pval->mode = HSPVAR_MODE_MALLOC;
+}
+
+/*------------------------------------------------------------*/
+
+
diff --git a/src/hsp3/hspvar_core.h b/src/hsp3/hspvar_core.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d6ea14c951d50d777864543d204c6fbc3ab0421
--- /dev/null
+++ b/src/hsp3/hspvar_core.h
@@ -0,0 +1,254 @@
+
+//
+// hspvar.cpp header
+//
+#ifndef __hspvar_core_h
+#define __hspvar_core_h
+
+#define HSPVAR_FLAG_NONE 0
+#define HSPVAR_FLAG_LABEL 1
+#define HSPVAR_FLAG_STR 2
+#define HSPVAR_FLAG_DOUBLE 3
+#define HSPVAR_FLAG_INT 4
+#define HSPVAR_FLAG_STRUCT 5
+#define HSPVAR_FLAG_COMSTRUCT 6
+
+// 7はVARIANTで予約済み
+
+#define HSPVAR_FLAG_USERDEF 8
+#define HSPVAR_FLAG_MAX 8
+
+#define HSPVAR_MODE_NONE -1
+#define HSPVAR_MODE_MALLOC 1
+#define HSPVAR_MODE_CLONE 2
+
+#define HSPVAR_ERROR_INVALID HSPERR_WRONG_EXPRESSION
+#define HSPVAR_ERROR_DIVZERO HSPERR_DIVIDED_BY_ZERO
+#define HSPVAR_ERROR_TYPEMISS HSPERR_TYPE_MISMATCH
+#define HSPVAR_ERROR_ARRAYOVER HSPERR_ARRAY_OVERFLOW
+#define HSPVAR_ERROR_ILLEGALPRM HSPERR_ILLEGAL_FUNCTION
+
+#define HSPVAR_SUPPORT_STORAGE 1 // 固定長ストレージサポート
+#define HSPVAR_SUPPORT_FLEXSTORAGE 2 // 可変長ストレージサポート
+#define HSPVAR_SUPPORT_FIXEDARRAY 4 // 配列サポート
+#define HSPVAR_SUPPORT_FLEXARRAY 8 // 可変長配列サポート
+#define HSPVAR_SUPPORT_ARRAYOBJ 16 // 連想配列サポート
+#define HSPVAR_SUPPORT_FLEXSIZE 32 // 要素ごとのデータが可変長
+#define HSPVAR_SUPPORT_NOCONVERT 64 // 代入時の型変換を無効にする
+#define HSPVAR_SUPPORT_VARUSE 128 // varuse関数のチェックを有効にする
+#define HSPVAR_SUPPORT_TEMPVAR 256 // テンポラリ変数として使用する
+#define HSPVAR_SUPPORT_USER1 0x4000 // ユーザーフラグ1
+#define HSPVAR_SUPPORT_USER2 0x8000 // ユーザーフラグ2
+
+#define HSPVAR_SUPPORT_MISCTYPE (HSPVAR_SUPPORT_ARRAYOBJ)
+
+typedef void * PDAT; // データの実態へのポインタ
+typedef int APTR; // 配列データへのオフセット値
+
+enum
+{
+CALCCODE_ADD = 0,
+CALCCODE_SUB,
+CALCCODE_MUL,
+CALCCODE_DIV,
+CALCCODE_MOD,
+CALCCODE_AND,
+CALCCODE_OR,
+CALCCODE_XOR,
+CALCCODE_EQ,
+CALCCODE_NE,
+CALCCODE_GT,
+CALCCODE_LT,
+CALCCODE_GTEQ,
+CALCCODE_LTEQ,
+CALCCODE_RR,
+CALCCODE_LR,
+CALCCODE_MAX
+};
+
+// PVAL structure
+//
+typedef struct
+{
+ // Memory Data structure (2.5 compatible)
+ //
+ short flag; // type of val
+ short mode; // mode (0=normal/1=clone/2=alloced)
+ int len[5]; // length of array 4byte align (dim)
+ int size; // size of Val
+ char *pt; // ptr to array
+
+ // Memory Data structure (3.0 compatible)
+ //
+ void *master; // Master pointer for data
+ unsigned short support; // Support Flag
+ short arraycnt; // Array Set Count
+ int offset; // Array Data Offset
+ int arraymul; // Array Multiple Value
+
+} PVal;
+
+
+// command execute core function
+//
+typedef struct
+{
+ // データフィールド
+ //
+ short flag; // 型タイプ値 (親アプリケーションで設定されます)
+ short aftertype; // 演算後のタイプ値
+ short version; // 型タイプランタイムバージョン(0x100 = 1.0)
+ unsigned short support; // サポート状況フラグ(HSPVAR_SUPPORT_*)
+ short basesize; // 1つのデータが使用するサイズ(byte) / 可変長の時は-1
+ short opt; // (未使用)
+
+ char *vartype_name; // 型タイプ名文字列へのポインタ
+ char *user; // ユーザーデータ(未使用)
+
+ // システム参照・型変換用
+ //
+ void *(*Cnv)( const void *buffer, int flag );
+ void *(*CnvCustom)( const void *buffer, int flag );
+ PDAT *(*GetPtr)( PVal *pval );
+
+ void *(*ArrayObjectRead)( PVal *pval, int *mptype );// 配列要素の指定 (連想配列/読み出し)
+ void (*ArrayObject)( PVal *pval ); // 配列要素の指定 (連想配列/書き込み準備)
+ void (*ObjectWrite)( PVal *pval, void *data, int type ); // HSPVAR_SUPPORT_NOCONVERT指定時の代入
+ void (*ObjectMethod)( PVal *pval ); // 変数に対するメソッドの指定
+
+ void (*Alloc)( PVal *pval, const PVal *pval2 ); // 変数メモリを確保する
+ void (*Free)( PVal *pval ); // 変数メモリを解放する
+
+ int (*GetSize)( const PDAT *pdat ); // 要素が使用するメモリサイズを返す(可変長のため)
+ int (*GetUsing)( const PDAT *pdat ); // 要素が使用中であるかを返す(varuse関数用)
+
+ // 変数バッファ(バイナリ)のポインタとサイズを返す
+ // (要素が可変長(str)の場合は該当する1配列バイナリのみ)
+ // (要素が固定長(int,double)の場合は全配列バイナリ)
+ // (サイズはメモリ確保サイズを返す)
+ void *(*GetBlockSize)( PVal *pval, PDAT *pdat, int *size );
+
+ // バイナリデータ用にメモリブロックを確保する
+ // (要素が可変長(str)の場合にブロックサイズを強制的に確保する)
+ // (固定長の場合は何もしない)
+ void (*AllocBlock)( PVal *pval, PDAT *pdat, int size );
+
+ // 代入用関数(型の一致が保障されます)
+ //
+ void (*Set)( PVal *pval, PDAT *pdat, const void *in );
+
+ // 演算用関数(型の一致が保障されます)
+ //
+ void (*AddI)( PDAT *pval, const void *val );
+ void (*SubI)( PDAT *pval, const void *val );
+ void (*MulI)( PDAT *pval, const void *val );
+ void (*DivI)( PDAT *pval, const void *val );
+ void (*ModI)( PDAT *pval, const void *val );
+
+ void (*AndI)( PDAT *pval, const void *val );
+ void (*OrI)( PDAT *pval, const void *val );
+ void (*XorI)( PDAT *pval, const void *val );
+
+ void (*EqI)( PDAT *pval, const void *val );
+ void (*NeI)( PDAT *pval, const void *val );
+ void (*GtI)( PDAT *pval, const void *val );
+ void (*LtI)( PDAT *pval, const void *val );
+ void (*GtEqI)( PDAT *pval, const void *val );
+ void (*LtEqI)( PDAT *pval, const void *val );
+
+ void (*RrI)( PDAT *pval, const void *val );
+ void (*LrI)( PDAT *pval, const void *val );
+} HspVarProc;
+
+extern HspVarProc *hspvarproc;
+extern int hspvartype_max;
+
+typedef void (* HSPVAR_COREFUNC) (HspVarProc *);
+
+extern PVal *mem_pval;
+#define HspVarCoreGetPVal( flag ) (&mem_pval[flag])
+
+
+// flex value define
+//
+#define FLEXVAL_TYPE_NONE 0
+#define FLEXVAL_TYPE_ALLOC 1
+#define FLEXVAL_TYPE_CLONE 2
+typedef struct
+{
+ short type; // typeID
+ short myid; // 固有ID(未使用)
+ short customid; // structure ID
+ short clonetype; // typeID for clone
+ int size; // data size
+ void *ptr; // data ptr
+} FlexValue;
+
+
+/*
+ typefunc
+
+ 基本タイプ HSPVAR_FLAG_STR ~ HSPVAR_FLAG_DOUBLE
+ 拡張タイプ HSPVAR_FLAG_USERDEF 以降
+
+ 式の評価でpval->ptを参照するため、常に配列0のポイントはpval->ptが指し示す必要がある。
+*/
+
+
+// Core System Main Function
+//
+void HspVarCoreInit( void );
+void HspVarCoreBye( void );
+void HspVarCoreResetVartype( int expand );
+int HspVarCoreAddType();
+void HspVarCoreRegisterType( int flag, HSPVAR_COREFUNC func );
+HspVarProc *HspVarCoreSeekProc( const char *name );
+
+// low level support functions
+//
+void HspVarCoreDup( PVal *pval, PVal *arg, APTR aptr );
+void HspVarCoreDupPtr( PVal *pval, int flag, void *ptr, int size );
+void HspVarCoreClear( PVal *pval, int flag );
+void HspVarCoreClearTemp( PVal *pval, int flag );
+void HspVarCoreDim( PVal *pval, int flag, int len1, int len2, int len3, int len4 );
+void HspVarCoreDimFlex( PVal *pval, int flag, int len0, int len1, int len2, int len3, int len4 );
+void HspVarCoreReDim( PVal *pval, int lenid, int len );
+void *HspVarCoreCnvPtr( PVal *pval, int flag );
+PDAT *HspVarCorePtrAPTR( PVal *pv, APTR ofs );
+void HspVarCoreArray( PVal *pval, int offset );
+int HspVarCoreCountElems( PVal *pval );
+void HspVarCoreAllocPODArray( PVal *pval, const PVal *pval2, int basesize );
+
+// macro for PVal
+//
+#define HspVarCoreGetProc( flag ) (&hspvarproc[flag])
+#define HspVarCoreDispose( pv ) hspvarproc[(pv)->flag].Free(pv)
+#define HspVarCoreReset( pv ) ((pv)->offset=0,(pv)->arraycnt=0)
+#define HspVarCorePtr( pv ) (hspvarproc[(pv)->flag].GetPtr(pv))
+#define HspVarCoreArrayObject( pv,in ) (hspvarproc[(pv)->flag].ArrayObject(pv,in)) // 配列の要素を指定する(最初にResetを呼んでおくこと)
+
+#define HspVarCoreSet( pv,in ) hspvarproc[(pv)->flag].Set( pv, in )
+#define HspVarCoreCnv( in1,in2,in3 ) hspvarproc[in2].Cnv( in3,in1 ) // in1->in2の型にin3ポインタを変換する
+
+#define HspVarCoreGetBlockSize( pv,in1,out ) hspvarproc[(pv)->flag].GetBlockSize( pv,in1,out )
+#define HspVarCoreAllocBlock( pv,in1,in2 ) hspvarproc[(pv)->flag].AllocBlock( pv,in1,in2 )
+#define HspVarCoreGetUsing( pv,in1 ) hspvarproc[(pv)->flag].GetUsing( in1 )
+
+#define HspVarCoreGetAPTR( pv ) ((pv)->offset)
+
+#define HspVarCoreCopyArrayInfo( pv, src ) (pv)->arraycnt = (src)->arraycnt;(pv)->offset = (src)->offset;(pv)->arraymul = (src)->arraymul;
+
+
+inline PDAT *HspVarCorePtrAPTR( PVal *pv, APTR ofs )
+{
+ // 変数データの実態ポインタを得る
+ // (APTRとpvalから実態を求める)
+ //
+ pv->offset=ofs;
+ return hspvarproc[(pv)->flag].GetPtr(pv);
+}
+
+
+
+
+#endif
diff --git a/src/hsp3/hspvar_double.cpp b/src/hsp3/hspvar_double.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..50c6ca692b958c8666a3bba091168441e7eaf554
--- /dev/null
+++ b/src/hsp3/hspvar_double.cpp
@@ -0,0 +1,260 @@
+
+//
+// HSPVAR core module
+// onion software/onitama 2003/4
+//
+#include
+#include
+#include
+#include
+#include "hspvar_core.h"
+#include "hsp3debug.h"
+#include "strbuf.h"
+
+/*------------------------------------------------------------*/
+/*
+ HSPVAR core interface (double)
+*/
+/*------------------------------------------------------------*/
+
+#define GetPtr(pval) ((double *)pval)
+
+static double conv;
+static short *aftertype;
+
+// Core
+static PDAT *HspVarDouble_GetPtr( PVal *pval )
+{
+ return (PDAT *)(( (double *)(pval->pt))+pval->offset);
+}
+
+static void *HspVarDouble_Cnv( const void *buffer, int flag )
+{
+ // リクエストされた型 -> 自分の型への変換を行なう
+ // (組み込み型にのみ対応でOK)
+ // (参照元のデータを破壊しないこと)
+ //
+ switch( flag ) {
+ case HSPVAR_FLAG_STR:
+ conv = (double)atof( (char *)buffer );
+ return &conv;
+ case HSPVAR_FLAG_INT:
+ conv = (double)( *(int *)buffer );
+ return &conv;
+ case HSPVAR_FLAG_DOUBLE:
+ break;
+ default:
+ throw HSPVAR_ERROR_TYPEMISS;
+ }
+ return (void *)buffer;
+}
+
+/*
+static void *HspVarDouble_CnvCustom( const void *buffer, int flag )
+{
+ // (カスタムタイプのみ)
+ // 自分の型 -> リクエストされた型 への変換を行なう
+ // (組み込み型に対応させる)
+ // (参照元のデータを破壊しないこと)
+ //
+ return buffer;
+}
+*/
+
+static int GetVarSize( PVal *pval )
+{
+ // PVALポインタの変数が必要とするサイズを取得する
+ // (sizeフィールドに設定される)
+ //
+ return HspVarCoreCountElems(pval) * sizeof(double);
+}
+
+
+static void HspVarDouble_Free( PVal *pval )
+{
+ // PVALポインタの変数メモリを解放する
+ //
+ if ( pval->mode == HSPVAR_MODE_MALLOC ) { sbFree( pval->pt ); }
+ pval->pt = NULL;
+ pval->mode = HSPVAR_MODE_NONE;
+}
+
+
+static void HspVarDouble_Alloc( PVal *pval, const PVal *pval2 )
+{
+ HspVarCoreAllocPODArray(pval, pval2, sizeof(double));
+}
+
+/*
+static void *HspVarDouble_ArrayObject( PVal *pval, int *mptype )
+{
+ // 配列要素の指定 (文字列/連想配列用)
+ //
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ return NULL;
+}
+*/
+
+// Size
+static int HspVarDouble_GetSize( const PDAT *pval )
+{
+ return sizeof(double);
+}
+
+// Set
+static void HspVarDouble_Set( PVal *pval, PDAT *pdat, const void *in )
+{
+ //*GetPtr(pdat) = *((double *)(in));
+ memcpy(pdat, in, sizeof(double));
+}
+
+// Add
+static void HspVarDouble_AddI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) += *((double *)(val));
+ *aftertype = HSPVAR_FLAG_DOUBLE;
+}
+
+// Sub
+static void HspVarDouble_SubI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) -= *((double *)(val));
+ *aftertype = HSPVAR_FLAG_DOUBLE;
+}
+
+// Mul
+static void HspVarDouble_MulI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) *= *((double *)(val));
+ *aftertype = HSPVAR_FLAG_DOUBLE;
+}
+
+// Div
+static void HspVarDouble_DivI( PDAT *pval, const void *val )
+{
+ double p = *((double *)(val));
+ if ( p == 0.0 ) throw( HSPVAR_ERROR_DIVZERO );
+ *GetPtr(pval) /= p;
+ *aftertype = HSPVAR_FLAG_DOUBLE;
+}
+
+// Mod
+static void HspVarDouble_ModI( PDAT *pval, const void *val )
+{
+ double p = *((double *)(val));
+ double dval;
+ if ( p == 0.0 ) throw( HSPVAR_ERROR_DIVZERO );
+ dval = *GetPtr(pval);
+ *GetPtr(pval) = fmod( dval, p );
+ *aftertype = HSPVAR_FLAG_DOUBLE;
+}
+
+
+// Eq
+static void HspVarDouble_EqI( PDAT *pval, const void *val )
+{
+ *((int *)pval) = ( *GetPtr(pval) == *((double *)(val)) );
+ *aftertype = HSPVAR_FLAG_INT;
+}
+
+// Ne
+static void HspVarDouble_NeI( PDAT *pval, const void *val )
+{
+ *((int *)pval) = ( *GetPtr(pval) != *((double *)(val)) );
+ *aftertype = HSPVAR_FLAG_INT;
+}
+
+// Gt
+static void HspVarDouble_GtI( PDAT *pval, const void *val )
+{
+ *((int *)pval) = ( *GetPtr(pval) > *((double *)(val)) );
+ *aftertype = HSPVAR_FLAG_INT;
+}
+
+// Lt
+static void HspVarDouble_LtI( PDAT *pval, const void *val )
+{
+ *((int *)pval) = ( *GetPtr(pval) < *((double *)(val)) );
+ *aftertype = HSPVAR_FLAG_INT;
+}
+
+// GtEq
+static void HspVarDouble_GtEqI( PDAT *pval, const void *val )
+{
+ *((int *)pval) = ( *GetPtr(pval) >= *((double *)(val)) );
+ *aftertype = HSPVAR_FLAG_INT;
+}
+
+// LtEq
+static void HspVarDouble_LtEqI( PDAT *pval, const void *val )
+{
+ *((int *)pval) = ( *GetPtr(pval) <= *((double *)(val)) );
+ *aftertype = HSPVAR_FLAG_INT;
+}
+
+/*
+// INVALID
+static void HspVarDouble_Invalid( PDAT *pval, const void *val )
+{
+ throw( HSPVAR_ERROR_INVALID );
+}
+*/
+
+static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size )
+{
+ *size = pval->size - ( ((char *)pdat) - pval->pt );
+ return (pdat);
+}
+
+static void AllocBlock( PVal *pval, PDAT *pdat, int size )
+{
+}
+
+
+/*------------------------------------------------------------*/
+
+void HspVarDouble_Init( HspVarProc *p )
+{
+ aftertype = &p->aftertype;
+
+ p->Set = HspVarDouble_Set;
+ p->Cnv = HspVarDouble_Cnv;
+ p->GetPtr = HspVarDouble_GetPtr;
+// p->CnvCustom = HspVarDouble_CnvCustom;
+ p->GetSize = HspVarDouble_GetSize;
+ p->GetBlockSize = GetBlockSize;
+ p->AllocBlock = AllocBlock;
+
+// p->ArrayObject = HspVarDouble_ArrayObject;
+ p->Alloc = HspVarDouble_Alloc;
+ p->Free = HspVarDouble_Free;
+
+ p->AddI = HspVarDouble_AddI;
+ p->SubI = HspVarDouble_SubI;
+ p->MulI = HspVarDouble_MulI;
+ p->DivI = HspVarDouble_DivI;
+ p->ModI = HspVarDouble_ModI;
+
+// p->AndI = HspVarDouble_Invalid;
+// p->OrI = HspVarDouble_Invalid;
+// p->XorI = HspVarDouble_Invalid;
+
+ p->EqI = HspVarDouble_EqI;
+ p->NeI = HspVarDouble_NeI;
+ p->GtI = HspVarDouble_GtI;
+ p->LtI = HspVarDouble_LtI;
+ p->GtEqI = HspVarDouble_GtEqI;
+ p->LtEqI = HspVarDouble_LtEqI;
+
+// p->RrI = HspVarDouble_Invalid;
+// p->LrI = HspVarDouble_Invalid;
+
+ p->vartype_name = "double"; // タイプ名
+ p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0)
+ p->support = HSPVAR_SUPPORT_STORAGE|HSPVAR_SUPPORT_FLEXARRAY;
+ // サポート状況フラグ(HSPVAR_SUPPORT_*)
+ p->basesize = sizeof(double); // 1つのデータが使用するサイズ(byte) / 可変長の時は-1
+}
+
+/*------------------------------------------------------------*/
+
diff --git a/src/hsp3/hspvar_int.cpp b/src/hsp3/hspvar_int.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c75db4756341d267ed4da307a92186636fa8b23b
--- /dev/null
+++ b/src/hsp3/hspvar_int.cpp
@@ -0,0 +1,281 @@
+
+//
+// HSPVAR core module
+// onion software/onitama 2003/4
+//
+#include
+#include
+#include
+
+#include "hsp3config.h"
+
+#include "hspvar_core.h"
+#include "hsp3debug.h"
+#include "strbuf.h"
+#include "supio.h"
+
+/*------------------------------------------------------------*/
+/*
+ HSPVAR core interface (int)
+*/
+/*------------------------------------------------------------*/
+
+#define GetPtr(pval) ((int *)pval)
+
+static int conv;
+
+
+// Core
+static PDAT *HspVarInt_GetPtr( PVal *pval )
+{
+ return (PDAT *)(( (int *)(pval->pt))+pval->offset);
+}
+
+static void *HspVarInt_Cnv( const void *buffer, int flag )
+{
+ // リクエストされた型 -> 自分の型への変換を行なう
+ // (組み込み型にのみ対応でOK)
+ // (参照元のデータを破壊しないこと)
+ //
+ switch( flag ) {
+ case HSPVAR_FLAG_STR:
+ if ( *(char *)buffer == '$' ) { // 16->10進数
+ conv = htoi( (char *)buffer );
+ } else {
+ conv = atoi( (char *)buffer );
+ }
+ return &conv;
+ case HSPVAR_FLAG_INT:
+ break;
+ case HSPVAR_FLAG_DOUBLE:
+ conv = (int)( *(double *)buffer );
+ return &conv;
+ default:
+ throw HSPVAR_ERROR_TYPEMISS;
+ }
+ return (void *)buffer;
+}
+
+/*
+static void *HspVarInt_CnvCustom( const void *buffer, int flag )
+{
+ // (カスタムタイプのみ)
+ // 自分の型 -> リクエストされた型 への変換を行なう
+ // (組み込み型に対応させる)
+ // (参照元のデータを破壊しないこと)
+ //
+ return buffer;
+}
+*/
+
+static int GetVarSize( PVal *pval )
+{
+ // PVALポインタの変数が必要とするサイズを取得する
+ // (sizeフィールドに設定される)
+ //
+ return HspVarCoreCountElems(pval) * sizeof(int);
+}
+
+
+static void HspVarInt_Free( PVal *pval )
+{
+ // PVALポインタの変数メモリを解放する
+ //
+ if ( pval->mode == HSPVAR_MODE_MALLOC ) { sbFree( pval->pt ); }
+ pval->pt = NULL;
+ pval->mode = HSPVAR_MODE_NONE;
+}
+
+
+static void HspVarInt_Alloc( PVal *pval, const PVal *pval2 )
+{
+ // pval変数が必要とするサイズを確保する。
+ // (pvalがすでに確保されているメモリ解放は呼び出し側が行なう)
+ // (pval2がNULLの場合は、新規データ)
+ // (pval2が指定されている場合は、pval2の内容を継承して再確保)
+ //
+ HspVarCoreAllocPODArray(pval, pval2, sizeof(int));
+}
+
+/*
+static void *HspVarInt_ArrayObject( PVal *pval, int *mptype )
+{
+ // 配列要素の指定 (文字列/連想配列用)
+ //
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ return NULL;
+}
+*/
+
+// Size
+static int HspVarInt_GetSize( const PDAT *pval )
+{
+ return sizeof(int);
+}
+
+// Set
+static void HspVarInt_Set( PVal *pval, PDAT *pdat, const void *in )
+{
+ *GetPtr(pdat) = *((int *)(in));
+}
+
+// Add
+static void HspVarInt_AddI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) += *((int *)(val));
+}
+
+
+// Sub
+static void HspVarInt_SubI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) -= *((int *)(val));
+}
+
+// Mul
+static void HspVarInt_MulI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) *= *((int *)(val));
+}
+
+// Div
+static void HspVarInt_DivI( PDAT *pval, const void *val )
+{
+ int p = *((int *)(val));
+ if ( p == 0 ) throw( HSPVAR_ERROR_DIVZERO );
+ *GetPtr(pval) /= p;
+}
+
+// Mod
+static void HspVarInt_ModI( PDAT *pval, const void *val )
+{
+ int p = *((int *)(val));
+ if ( p == 0 ) throw( HSPVAR_ERROR_DIVZERO );
+ *GetPtr(pval) %= p;
+}
+
+
+// And
+static void HspVarInt_AndI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) &= *((int *)(val));
+}
+
+// Or
+static void HspVarInt_OrI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) |= *((int *)(val));
+}
+
+// Xor
+static void HspVarInt_XorI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) ^= *((int *)(val));
+}
+
+
+// Eq
+static void HspVarInt_EqI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) = ( *GetPtr(pval) == *((int *)(val)) );
+}
+
+// Ne
+static void HspVarInt_NeI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) = ( *GetPtr(pval) != *((int *)(val)) );
+}
+
+// Gt
+static void HspVarInt_GtI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) = ( *GetPtr(pval) > *((int *)(val)) );
+}
+
+// Lt
+static void HspVarInt_LtI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) = ( *GetPtr(pval) < *((int *)(val)) );
+}
+
+// GtEq
+static void HspVarInt_GtEqI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) = ( *GetPtr(pval) >= *((int *)(val)) );
+}
+
+// LtEq
+static void HspVarInt_LtEqI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) = ( *GetPtr(pval) <= *((int *)(val)) );
+}
+
+// Rr
+static void HspVarInt_RrI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) >>= *((int *)(val));
+}
+
+// Lr
+static void HspVarInt_LrI( PDAT *pval, const void *val )
+{
+ *GetPtr(pval) <<= *((int *)(val));
+}
+
+
+static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size )
+{
+ *size = pval->size - ( ((char *)pdat) - pval->pt );
+ return (pdat);
+}
+
+static void AllocBlock( PVal *pval, PDAT *pdat, int size )
+{
+}
+
+
+/*------------------------------------------------------------*/
+
+void HspVarInt_Init( HspVarProc *p )
+{
+ p->Set = HspVarInt_Set;
+ p->Cnv = HspVarInt_Cnv;
+ p->GetPtr = HspVarInt_GetPtr;
+// p->CnvCustom = HspVarInt_CnvCustom;
+ p->GetSize = HspVarInt_GetSize;
+ p->GetBlockSize = GetBlockSize;
+ p->AllocBlock = AllocBlock;
+
+// p->ArrayObject = HspVarInt_ArrayObject;
+ p->Alloc = HspVarInt_Alloc;
+ p->Free = HspVarInt_Free;
+
+ p->AddI = HspVarInt_AddI;
+ p->SubI = HspVarInt_SubI;
+ p->MulI = HspVarInt_MulI;
+ p->DivI = HspVarInt_DivI;
+ p->ModI = HspVarInt_ModI;
+
+ p->AndI = HspVarInt_AndI;
+ p->OrI = HspVarInt_OrI;
+ p->XorI = HspVarInt_XorI;
+
+ p->EqI = HspVarInt_EqI;
+ p->NeI = HspVarInt_NeI;
+ p->GtI = HspVarInt_GtI;
+ p->LtI = HspVarInt_LtI;
+ p->GtEqI = HspVarInt_GtEqI;
+ p->LtEqI = HspVarInt_LtEqI;
+
+ p->RrI = HspVarInt_RrI;
+ p->LrI = HspVarInt_LrI;
+
+ p->vartype_name = "int"; // タイプ名
+ p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0)
+ p->support = HSPVAR_SUPPORT_STORAGE | HSPVAR_SUPPORT_FLEXARRAY;
+ // サポート状況フラグ(HSPVAR_SUPPORT_*)
+ p->basesize = sizeof(int); // 1つのデータが使用するサイズ(byte) / 可変長の時は-1
+}
+
+/*------------------------------------------------------------*/
+
diff --git a/src/hsp3/hspvar_label.cpp b/src/hsp3/hspvar_label.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d48d79ae4e7c82f4adfed8d28f548a05dc4cbaf8
--- /dev/null
+++ b/src/hsp3/hspvar_label.cpp
@@ -0,0 +1,114 @@
+
+//
+// HSPVAR core module
+// onion software/onitama 2007/1
+//
+#include
+#include
+#include
+#include "hsp3code.h"
+#include "hspvar_core.h"
+#include "hsp3debug.h"
+#include "hspvar_label.h"
+
+#include "strbuf.h"
+#include "supio.h"
+
+/*------------------------------------------------------------*/
+/*
+ HSPVAR core interface (label)
+*/
+/*------------------------------------------------------------*/
+
+#define GetPtr(pval) ((HSPVAR_LABEL *)pval)
+
+// Core
+static PDAT *HspVarLabel_GetPtr( PVal *pval )
+{
+ return (PDAT *)(( (HSPVAR_LABEL *)(pval->pt))+pval->offset);
+}
+
+
+static int GetVarSize( PVal *pval )
+{
+ // PVALポインタの変数が必要とするサイズを取得する
+ // (sizeフィールドに設定される)
+ //
+ return HspVarCoreCountElems(pval) * sizeof(HSPVAR_LABEL);
+}
+
+
+static void HspVarLabel_Free( PVal *pval )
+{
+ // PVALポインタの変数メモリを解放する
+ //
+ if ( pval->mode == HSPVAR_MODE_MALLOC ) { sbFree( pval->pt ); }
+ pval->pt = NULL;
+ pval->mode = HSPVAR_MODE_NONE;
+}
+
+
+static void HspVarLabel_Alloc( PVal *pval, const PVal *pval2 )
+{
+ // pval変数が必要とするサイズを確保する。
+ // (pvalがすでに確保されているメモリ解放は呼び出し側が行なう)
+ // (flagの設定は呼び出し側が行なう)
+ // (pval2がNULLの場合は、新規データ)
+ // (pval2が指定されている場合は、pval2の内容を継承して再確保)
+ //
+ HspVarCoreAllocPODArray(pval, pval2, sizeof(HSPVAR_LABEL));
+}
+
+// Size
+static int HspVarLabel_GetSize( const PDAT *pval )
+{
+ return sizeof(HSPVAR_LABEL);
+}
+
+// Using
+static int HspVarLabel_GetUsing( const PDAT *pdat )
+{
+ // (実態のポインタが渡されます)
+ return ( *pdat != NULL );
+}
+
+// Set
+static void HspVarLabel_Set( PVal *pval, PDAT *pdat, const void *in )
+{
+ *GetPtr(pdat) = *((HSPVAR_LABEL *)(in));
+}
+
+static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size )
+{
+ *size = pval->size - ( ((char *)pdat) - pval->pt );
+ return (pdat);
+}
+
+static void AllocBlock( PVal *pval, PDAT *pdat, int size )
+{
+}
+
+
+/*------------------------------------------------------------*/
+
+void HspVarLabel_Init( HspVarProc *p )
+{
+ p->Set = HspVarLabel_Set;
+ p->GetPtr = HspVarLabel_GetPtr;
+ p->GetSize = HspVarLabel_GetSize;
+ p->GetUsing = HspVarLabel_GetUsing;
+ p->GetBlockSize = GetBlockSize;
+ p->AllocBlock = AllocBlock;
+
+ p->Alloc = HspVarLabel_Alloc;
+ p->Free = HspVarLabel_Free;
+
+ p->vartype_name = "label"; // タイプ名
+ p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0)
+ p->support = HSPVAR_SUPPORT_STORAGE | HSPVAR_SUPPORT_FLEXARRAY | HSPVAR_SUPPORT_VARUSE;
+ // サポート状況フラグ(HSPVAR_SUPPORT_*)
+ p->basesize = sizeof(HSPVAR_LABEL); // 1つのデータが使用するサイズ(byte) / 可変長の時は-1
+}
+
+/*------------------------------------------------------------*/
+
diff --git a/src/hsp3/hspvar_label.h b/src/hsp3/hspvar_label.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ad681865fac30c42a22256c9ad07ed2c74e0733
--- /dev/null
+++ b/src/hsp3/hspvar_label.h
@@ -0,0 +1,21 @@
+
+//
+// hspvar_label.cpp header
+//
+#ifndef __hspvar_label_h
+#define __hspvar_label_h
+
+#include "hspvar_core.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned short *HSPVAR_LABEL;
+void HspVarLabel_Init( HspVarProc *p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/hsp3/hspvar_str.cpp b/src/hsp3/hspvar_str.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..94d7787303176ffcc8f23803de2a09a94beb31e7
--- /dev/null
+++ b/src/hsp3/hspvar_str.cpp
@@ -0,0 +1,307 @@
+
+//
+// HSPVAR core module
+// onion software/onitama 2003/4
+//
+#include
+#include
+#include
+#include "hspvar_core.h"
+#include "hsp3debug.h"
+
+#include "strbuf.h"
+#include "supio.h"
+
+/*------------------------------------------------------------*/
+/*
+ HSPVAR core interface (str)
+*/
+/*------------------------------------------------------------*/
+
+#define GetPtr(pval) ((char *)pval)
+
+static char conv[400];
+static HspVarProc *myproc;
+
+static char **GetFlexBufPtr( PVal *pval, int num )
+{
+ // 可変長バッファのポインタを得る
+ //
+ char **pp;
+ if ( num == 0 ) return &(pval->pt); // ID#0は、ptがポインタとなる
+ pp = (char **)(pval->master);
+ return &pp[num];
+}
+
+
+
+// Core
+static PDAT *HspVarStr_GetPtr( PVal *pval )
+{
+ char **pp;
+ pp = GetFlexBufPtr( pval, pval->offset );
+ return (PDAT *)( *pp );
+}
+
+static void *HspVarStr_Cnv( const void *buffer, int flag )
+{
+ // リクエストされた型 -> 自分の型への変換を行なう
+ // (組み込み型にのみ対応でOK)
+ // (参照元のデータを破壊しないこと)
+ //
+ switch( flag ) {
+ case HSPVAR_FLAG_INT:
+#ifdef HSPWIN
+ _itoa( *(int *)buffer, conv, 10 );
+#else
+ sprintf( conv, "%d", *(int*)buffer);
+#endif
+ return conv;
+ case HSPVAR_FLAG_STR:
+ break;
+ case HSPVAR_FLAG_DOUBLE:
+ //_gcvt( *(double *)buffer, 32, conv );
+ sprintf( conv,"%f", *(double *)buffer );
+ return conv;
+ default:
+ throw HSPVAR_ERROR_TYPEMISS;
+ }
+ return (void *)buffer;
+}
+
+/*
+static void *HspVarStr_CnvCustom( const void *buffer, int flag )
+{
+ // (カスタムタイプのみ)
+ // 自分の型 -> リクエストされた型 への変換を行なう
+ // (組み込み型に対応させる)
+ // (参照元のデータを破壊しないこと)
+ //
+ return buffer;
+}
+*/
+
+static int GetVarSize( PVal *pval )
+{
+ // PVALポインタの変数が必要とするサイズを取得する
+ //
+ return HspVarCoreCountElems(pval) * sizeof(char *);
+}
+
+static void HspVarStr_Free( PVal *pval )
+{
+ // PVALポインタの変数メモリを解放する
+ //
+ char **pp;
+ int i,size;
+ if ( pval->mode == HSPVAR_MODE_MALLOC ) {
+ size = GetVarSize( pval );
+ pval->size = size;
+ for(i=0;i<(int)(size/sizeof(char *));i++) {
+ pp = GetFlexBufPtr( pval, i );
+ sbFree( *pp );
+ }
+ free( pval->master );
+ }
+ pval->mode = HSPVAR_MODE_NONE;
+}
+
+
+static void HspVarStr_Alloc( PVal *pval, const PVal *pval2 )
+{
+ // pval変数が必要とするサイズを確保する。
+ // (pvalがすでに確保されているメモリ解放は呼び出し側が行なう)
+ // (pval2がNULLの場合は、新規データ。len[0]に確保バイト数が代入される)
+ // (pval2が指定されている場合は、pval2の内容を継承して再確保)
+ //
+ char **pp;
+ int i, i2, size, bsize;
+ PVal oldvar;
+ if ( pval->len[1] < 1 ) pval->len[1] = 1; // 配列を最低1は確保する
+ if ( pval2 != NULL ) oldvar = *pval2; // 拡張時は以前の情報を保存する
+
+ size = GetVarSize( pval );
+
+ if ( pval == pval2 && size <= oldvar.size ) {
+ size = oldvar.size;
+ pval->master = oldvar.master;
+ } else {
+ if ( size > STRBUF_BLOCKSIZE ) {
+ size += size / 8;
+ }
+ pval->master = malloc(size);
+ }
+ if ( pval->master == NULL ) throw HSPERR_OUT_OF_MEMORY;
+
+ pval->size = size;
+ pval->mode = HSPVAR_MODE_MALLOC;
+
+ if ( pval2 == NULL ) { // 配列拡張なし
+ bsize = pval->len[0];
+ if ( bsize < STRBUF_BLOCKSIZE ) { bsize = STRBUF_BLOCKSIZE; }
+ for(i=0;i<(int)(size/sizeof(char *));i++) {
+ pp = GetFlexBufPtr( pval, i );
+ *pp = sbAllocClear( bsize );
+ sbSetOption( *pp, (void *)pp );
+ }
+ return;
+ }
+
+ i = 0;
+ i2 = oldvar.size / sizeof(char *);
+
+ // バッファを使い回す場合、既存要素を更新する必要はない
+ if ( pval->master == oldvar.master ) {
+ i = i2;
+ }
+
+ for(;i<(int)(size/sizeof(char *));i++) {
+ pp = GetFlexBufPtr( pval, i );
+ if ( i>=i2 ) {
+ *pp = sbAllocClear(STRBUF_BLOCKSIZE); // 新規確保分
+ } else {
+ *pp = *GetFlexBufPtr( &oldvar, i ); // 確保済みバッファ
+ }
+ sbSetOption( *pp, (void *)pp );
+ }
+
+ if ( pval->master != pval2->master ) {
+ free(oldvar.master);
+ }
+}
+
+/*
+static void *HspVarStr_ArrayObject( PVal *pval, int *arg )
+{
+ // 配列要素の指定 (文字列/連想配列用)
+ // ( Reset後に次元数だけ連続で呼ばれます )
+ //
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+}
+*/
+
+// Size
+static int HspVarStr_GetSize( const PDAT *pval )
+{
+ return (int)(strlen( (char *)pval ) + 1 );
+}
+
+// Set
+static void HspVarStr_Set( PVal *pval, PDAT *pdat, const void *in )
+{
+ char **pp;
+ if ( pval->mode == HSPVAR_MODE_CLONE ) {
+ strncpy( (char *)pdat, (char *)in, pval->size );
+ return;
+ }
+ pp = (char **)sbGetOption( (char *)pdat );
+ sbStrCopy( pp, (char *)in );
+ //strcpy( GetPtr(pval), (char *)in );
+}
+
+// Add
+static void HspVarStr_AddI( PDAT *pval, const void *val )
+{
+ char **pp;
+ pp = (char **)sbGetOption( (char *)pval );
+ sbStrAdd( pp, (char *)val );
+ //strcat( GetPtr(pval), (char *)val );
+ myproc->aftertype = HSPVAR_FLAG_STR;
+}
+
+// Eq
+static void HspVarStr_EqI( PDAT *pdat, const void *val )
+{
+ if ( strcmp( (char *)pdat, (char *)val ) ) {
+ *(int *)pdat = 0;
+ } else {
+ *(int *)pdat = 1;
+ }
+ myproc->aftertype = HSPVAR_FLAG_INT;
+}
+
+// Ne
+static void HspVarStr_NeI( PDAT *pdat, const void *val )
+{
+ int i;
+ i = strcmp( (char *)pdat, (char *)val );
+ *(int *)pdat = i;
+ myproc->aftertype = HSPVAR_FLAG_INT;
+}
+
+/*
+// INVALID
+static void HspVarStr_Invalid( PDAT *pval, const void *val )
+{
+ throw( HSPERR_UNSUPPORTED_FUNCTION );
+}
+*/
+
+static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size )
+{
+ STRINF *inf;
+ if ( pval->mode == HSPVAR_MODE_CLONE ) {
+ *size = pval->size;
+ return pdat;
+ }
+ inf = sbGetSTRINF( (char *)pdat );
+ *size = inf->size;
+ return pdat;
+}
+
+static void AllocBlock( PVal *pval, PDAT *pdat, int size )
+{
+ char **pp;
+ if ( pval->mode == HSPVAR_MODE_CLONE ) return;
+ pp = (char **)sbGetOption( (char *)pdat );
+ *pp = sbExpand( *pp, size );
+}
+
+
+/*------------------------------------------------------------*/
+
+void HspVarStr_Init( HspVarProc *p )
+{
+ myproc = p;
+
+ p->Set = HspVarStr_Set;
+ p->Cnv = HspVarStr_Cnv;
+ p->GetPtr = HspVarStr_GetPtr;
+// p->CnvCustom = HspVarStr_CnvCustom;
+ p->GetSize = HspVarStr_GetSize;
+ p->GetBlockSize = GetBlockSize;
+ p->AllocBlock = AllocBlock;
+
+// p->ArrayObject = HspVarStr_ArrayObject;
+ p->Alloc = HspVarStr_Alloc;
+ p->Free = HspVarStr_Free;
+
+ p->AddI = HspVarStr_AddI;
+// p->SubI = HspVarStr_Invalid;
+// p->MulI = HspVarStr_Invalid;
+// p->DivI = HspVarStr_Invalid;
+// p->ModI = HspVarStr_Invalid;
+
+// p->AndI = HspVarStr_Invalid;
+// p->OrI = HspVarStr_Invalid;
+// p->XorI = HspVarStr_Invalid;
+
+ p->EqI = HspVarStr_EqI;
+ p->NeI = HspVarStr_NeI;
+// p->GtI = HspVarStr_Invalid;
+// p->LtI = HspVarStr_Invalid;
+// p->GtEqI = HspVarStr_Invalid;
+// p->LtEqI = HspVarStr_Invalid;
+
+// p->RrI = HspVarStr_Invalid;
+// p->LrI = HspVarStr_Invalid;
+
+ p->vartype_name = "str"; // タイプ名
+ p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0)
+ p->support = HSPVAR_SUPPORT_FLEXSTORAGE | HSPVAR_SUPPORT_FLEXARRAY;
+ // サポート状況フラグ(HSPVAR_SUPPORT_*)
+ p->basesize = -1; // 1つのデータが使用するサイズ(byte) / 可変長の時は-1
+}
+
+/*------------------------------------------------------------*/
+
diff --git a/src/hsp3/hspvar_struct.cpp b/src/hsp3/hspvar_struct.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7e33fb0199463a7222e0cccfd43b51cf86faf97f
--- /dev/null
+++ b/src/hsp3/hspvar_struct.cpp
@@ -0,0 +1,191 @@
+
+//
+// HSPVAR core module
+// onion software/onitama 2003/4
+//
+#include
+#include
+#include
+#include "hsp3code.h"
+#include "hspvar_core.h"
+#include "hsp3debug.h"
+
+#include "strbuf.h"
+#include "supio.h"
+
+/*------------------------------------------------------------*/
+/*
+ HSPVAR core interface (struct)
+*/
+/*------------------------------------------------------------*/
+
+
+// Core
+static PDAT *HspVarStruct_GetPtr( PVal *pval )
+{
+ return (PDAT *)(( (FlexValue *)(pval->pt))+pval->offset);
+}
+
+/*
+static void *HspVarStruct_Cnv( const void *buffer, int flag )
+{
+ // リクエストされた型 -> 自分の型への変換を行なう
+ // (組み込み型にのみ対応でOK)
+ // (参照元のデータを破壊しないこと)
+ //
+ throw HSPERR_INVALID_TYPE;
+ return buffer;
+}
+
+
+static void *HspVarStruct_CnvCustom( const void *buffer, int flag )
+{
+ // (カスタムタイプのみ)
+ // 自分の型 -> リクエストされた型 への変換を行なう
+ // (組み込み型に対応させる)
+ // (参照元のデータを破壊しないこと)
+ //
+ throw HSPERR_INVALID_TYPE;
+ return buffer;
+}
+*/
+
+static void HspVarStruct_Free( PVal *pval )
+{
+ // PVALポインタの変数メモリを解放する
+ //
+ int i;
+ FlexValue *fv;
+ if ( pval->mode == HSPVAR_MODE_MALLOC ) {
+
+ code_delstruct_all( pval ); // デストラクタがあれば呼び出す
+
+ fv = (FlexValue *)pval->pt;
+ for(i=0;ilen[1];i++) {
+ if ( fv->type == FLEXVAL_TYPE_ALLOC ) sbFree( fv->ptr );
+ fv++;
+ }
+ sbFree( pval->pt );
+ }
+ pval->mode = HSPVAR_MODE_NONE;
+}
+
+
+static void HspVarStruct_Alloc( PVal *pval, const PVal *pval2 )
+{
+ // pval変数が必要とするサイズを確保する。
+ // (pvalがすでに確保されているメモリ解放は呼び出し側が行なう)
+ // (pval2がNULLの場合は、新規データ)
+ // (pval2が指定されている場合は、pval2の内容を継承して再確保)
+ //
+
+ // FLEXVAL_TYPE_NONE == 0 なので、0埋め初期化で問題ない
+ HspVarCoreAllocPODArray(pval, pval2, sizeof(FlexValue));
+}
+
+/*
+static void *HspVarStruct_ArrayObject( PVal *pval, int *mptype )
+{
+ // 配列要素の指定 (文字列/連想配列用)
+ //
+ throw( HSPERR_UNSUPPORTED_FUNCTION );
+ return NULL;
+}
+*/
+
+// Size
+static int HspVarStruct_GetSize( const PDAT *pdat )
+{
+ // (実態のポインタが渡されます)
+ return sizeof(FlexValue);
+}
+
+// Using
+static int HspVarStruct_GetUsing( const PDAT *pdat )
+{
+ // (実態のポインタが渡されます)
+ FlexValue *fv;
+ fv = (FlexValue *)pdat;
+ return fv->type;
+}
+
+// Set
+static void HspVarStruct_Set( PVal *pval, PDAT *pdat, const void *in )
+{
+ FlexValue *fv;
+ FlexValue *fv_src;
+ fv = (FlexValue *)in;
+ fv->type = FLEXVAL_TYPE_CLONE;
+ fv_src = (FlexValue *)pdat;
+ if ( fv_src->type == FLEXVAL_TYPE_ALLOC ) { sbFree( fv_src->ptr ); }
+ memcpy( pdat, fv, sizeof(FlexValue) );
+ //sbCopy( (char **)pdat, (char *)fv->ptr, fv->size );
+}
+
+/*
+// INVALID
+static void HspVarStruct_Invalid( PDAT *pval, const void *val )
+{
+ throw( HSPERR_UNSUPPORTED_FUNCTION );
+}
+*/
+
+static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size )
+{
+ FlexValue *fv;
+ fv = (FlexValue *)pdat;
+ *size = fv->size;
+ return (void *)(fv->ptr);
+}
+
+static void AllocBlock( PVal *pval, PDAT *pdat, int size )
+{
+}
+
+
+/*------------------------------------------------------------*/
+
+void HspVarStruct_Init( HspVarProc *p )
+{
+ p->Set = HspVarStruct_Set;
+ p->GetPtr = HspVarStruct_GetPtr;
+// p->Cnv = HspVarStruct_Cnv;
+// p->CnvCustom = HspVarStruct_CnvCustom;
+ p->GetSize = HspVarStruct_GetSize;
+ p->GetUsing = HspVarStruct_GetUsing;
+ p->GetBlockSize = GetBlockSize;
+ p->AllocBlock = AllocBlock;
+
+// p->ArrayObject = HspVarStruct_ArrayObject;
+ p->Alloc = HspVarStruct_Alloc;
+ p->Free = HspVarStruct_Free;
+/*
+ p->AddI = HspVarStruct_Invalid;
+ p->SubI = HspVarStruct_Invalid;
+ p->MulI = HspVarStruct_Invalid;
+ p->DivI = HspVarStruct_Invalid;
+ p->ModI = HspVarStruct_Invalid;
+
+ p->AndI = HspVarStruct_Invalid;
+ p->OrI = HspVarStruct_Invalid;
+ p->XorI = HspVarStruct_Invalid;
+
+ p->EqI = HspVarStruct_Invalid;
+ p->NeI = HspVarStruct_Invalid;
+ p->GtI = HspVarStruct_Invalid;
+ p->LtI = HspVarStruct_Invalid;
+ p->GtEqI = HspVarStruct_Invalid;
+ p->LtEqI = HspVarStruct_Invalid;
+
+ p->RrI = HspVarStruct_Invalid;
+ p->LrI = HspVarStruct_Invalid;
+*/
+ p->vartype_name = "struct"; // タイプ名
+ p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0)
+ p->support = HSPVAR_SUPPORT_STORAGE | HSPVAR_SUPPORT_FLEXARRAY | HSPVAR_SUPPORT_VARUSE;
+ // サポート状況フラグ(HSPVAR_SUPPORT_*)
+ p->basesize = sizeof(FlexValue); // 1つのデータが使用するサイズ(byte) / 可変長の時は-1
+}
+
+/*------------------------------------------------------------*/
+
diff --git a/src/hsp3/hspwnd.h b/src/hsp3/hspwnd.h
new file mode 100644
index 0000000000000000000000000000000000000000..b421cf68e8ae2c984fd865f55f2829acb74107a7
--- /dev/null
+++ b/src/hsp3/hspwnd.h
@@ -0,0 +1,34 @@
+
+//
+// HspWnd,Bmscr(BMSCR) struct define
+//
+#ifndef __hspwnd_h
+#define __hspwnd_h
+
+#ifdef HSPDISH
+#include "../hsp3dish/hspwnd.h"
+#else
+
+#ifdef HSPWIN
+#include "win32gui/hspwnd_win.h"
+#endif
+
+#ifdef HSPIOS
+#include "ios/hspwnd_ios.h"
+#endif
+
+#ifdef HSPNDK
+#include "ndk/hspwnd_ndk.h"
+#endif
+
+#ifdef HSPLINUX
+#include "linux/hspwnd_linux.h"
+#endif
+
+#ifdef HSPEMSCRIPTEN
+#include "emscripten/hspwnd_emscripten.h"
+#endif
+
+#endif
+
+#endif
diff --git a/src/hsp3/linux/hsp3cl.cpp b/src/hsp3/linux/hsp3cl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f2298bc90f89633bab6d4a8789d91c7ea58a7fb3
--- /dev/null
+++ b/src/hsp3/linux/hsp3cl.cpp
@@ -0,0 +1,227 @@
+/*--------------------------------------------------------
+ HSP3 main (Console Version)
+ 2004/8 onitama
+ --------------------------------------------------------*/
+
+#include
+#include
+#include
+
+#include "../strbuf.h"
+#include "../hsp3.h"
+#include "../hsp3config.h"
+#include "../supio.h"
+#include "../hsp3gr.h"
+
+/*----------------------------------------------------------*/
+
+static Hsp3 *hsp;
+static HSPCTX *ctx;
+
+static char fpas[]={ 'H'-48,'S'-48,'P'-48,'H'-48,
+ 'E'-48,'D'-48,'~'-48,'~'-48 };
+static char optmes[] = "HSPHED~~\0_1_________2_________3______";
+
+static int hsp_wd;
+
+/*----------------------------------------------------------*/
+
+void hsp3win_dialog( char *mes )
+{
+ printf( "%s\n", mes );
+}
+
+
+void hsp3cl_msgfunc( HSPCTX *hspctx )
+{
+ while(1) {
+
+ switch( hspctx->runmode ) {
+ case RUNMODE_STOP:
+ // stop命令
+ hsp3win_dialog( "[STOP] Press any key..." );
+ getchar();
+ throw HSPERR_NONE;
+
+ case RUNMODE_WAIT:
+ // wait命令による時間待ち
+ // (実際はcode_exec_waitにtick countを渡す)
+ hspctx->runmode = RUNMODE_RUN;
+ //hspctx->runmode = code_exec_wait( tick );
+ break;
+
+ case RUNMODE_AWAIT:
+ // await命令による時間待ち
+ // (実際はcode_exec_awaitにtick countを渡す)
+ hspctx->runmode = RUNMODE_RUN;
+ //hspctx->runmode = code_exec_await( tick );
+ break;
+
+ case RUNMODE_END:
+ // end命令
+#if 0
+ hsp3win_dialog( "[END] Press any key..." );
+ getchar();
+#endif
+ throw HSPERR_NONE;
+
+ case RUNMODE_RETURN:
+ throw HSPERR_RETURN_WITHOUT_GOSUB;
+
+ case RUNMODE_ASSERT:
+ // assertで中断
+ hspctx->runmode = RUNMODE_STOP;
+ break;
+
+ case RUNMODE_LOGMES:
+ // logmes命令
+ hspctx->runmode = RUNMODE_RUN;
+ break;
+
+ default:
+ return;
+ }
+ }
+}
+
+
+int hsp3cl_init( char *startfile )
+{
+ // システム関連の初期化
+ // ( mode:0=debug/1=release )
+ //
+ int a,orgexe, mode;
+ int hsp_sum, hsp_dec;
+ char a1;
+ char *ss;
+
+ // HSP関連の初期化
+ //
+ hsp = new Hsp3();
+
+#ifdef HSPDEBUG
+
+ if ( *startfile == 0 ) {
+ printf( "OpenHSP CL ver%s / onion software 1997-2017\n", hspver );
+ return -1;
+ }
+ hsp->SetFileName( startfile );
+#else
+ if ( startfile != NULL ) {
+ hsp->SetFileName( startfile );
+ }
+#endif
+
+ // 実行ファイルかデバッグ中かを調べる
+ //
+ mode = 0;
+ orgexe = 0;
+ hsp_wd = 0;
+ for( a=0 ; a<8; a++) {
+ a1=optmes[a]-48;if (a1==fpas[a]) orgexe++;
+ }
+ if ( orgexe == 0 ) {
+ mode = atoi(optmes+9) + 0x10000;
+ hsp_wd=( *(short *)(optmes+26) );
+ hsp_sum=*(unsigned short *)(optmes+29);
+ hsp_dec=*(int *)(optmes+32);
+ hsp->SetPackValue( hsp_sum, hsp_dec );
+ }
+
+ if ( hsp->Reset( mode ) ) {
+ hsp3win_dialog( "Startup failed." );
+ return -1;
+ }
+
+ ctx = &hsp->hspctx;
+
+ // コマンドライン関連
+ ss = ""; // コマンドラインパラメーターを入れる
+ sbStrCopy( &ctx->cmdline, ss ); // コマンドラインパラメーターを保存
+
+ // Register Type
+ //
+ ctx->msgfunc = hsp3cl_msgfunc;
+ ctx->hspstat |= 16;
+
+ hsp3typeinit_dllcmd( code_gettypeinfo( TYPE_DLLFUNC ) );
+ hsp3typeinit_dllctrl( code_gettypeinfo( TYPE_DLLCTRL ) );
+
+ hsp3typeinit_cl_extcmd( code_gettypeinfo( TYPE_EXTCMD ) );
+ hsp3typeinit_cl_extfunc( code_gettypeinfo( TYPE_EXTSYSVAR ) );
+
+ return 0;
+}
+
+
+static void hsp3cl_bye( void )
+{
+ // HSP関連の解放
+ //
+ delete hsp;
+}
+
+
+void hsp3cl_error( void )
+{
+ char errmsg[1024];
+ char *msg;
+ char *fname;
+ HSPERROR err;
+ int ln;
+ err = code_geterror();
+ ln = code_getdebug_line();
+ msg = hspd_geterror(err);
+ fname = code_getdebug_name();
+
+ if ( ln < 0 ) {
+ sprintf( errmsg, "#Error %d\n-->%s\n",(int)err,msg );
+ fname = NULL;
+ } else {
+ sprintf( errmsg, "#Error %d in line %d (%s)\n-->%s\n",(int)err, ln, fname, msg );
+ }
+
+ hsp3win_dialog( errmsg );
+ hsp3win_dialog( "[ERROR] Press any key..." );
+ getchar();
+}
+
+
+int hsp3cl_exec( void )
+{
+ // 実行メインを呼び出す
+ //
+ int runmode;
+ int endcode;
+rerun:
+
+ // 実行の開始
+ //
+ runmode = code_execcmd();
+ if ( runmode == RUNMODE_ERROR ) {
+ try {
+ hsp3cl_error();
+ }
+ catch( ... ) {
+ }
+ return -1;
+ }
+ if ( runmode == RUNMODE_EXITRUN ) {
+ char fname[HSP_MAX_PATH];
+ char cmd[1024];
+ int res;
+ strncpy( fname, ctx->refstr, HSP_MAX_PATH-1 );
+ strncpy( cmd, ctx->stmp, 1023 );
+
+ hsp3cl_bye();
+ res = hsp3cl_init( fname );
+ if ( res ) return res;
+
+ strncpy( ctx->cmdline, cmd, 1023 );
+ ctx->runmode = RUNMODE_RUN;
+ goto rerun;
+ }
+ endcode = ctx->endcode;
+ hsp3cl_bye();
+ return endcode;
+}
diff --git a/src/hsp3/linux/hsp3cl.h b/src/hsp3/linux/hsp3cl.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d41005eb600b98d07c98bf72c3f5ed89c0ddf3e
--- /dev/null
+++ b/src/hsp3/linux/hsp3cl.h
@@ -0,0 +1,12 @@
+
+//
+// hsp3cl.cpp header
+//
+#ifndef __hsp3cl_h
+#define __hsp3cl_h
+
+int hsp3cl_exec( void );
+int hsp3cl_init( char *startfile );
+void hsp3win_dialog( char *mes );
+
+#endif
diff --git a/src/hsp3/linux/hsp3ext_linux.cpp b/src/hsp3/linux/hsp3ext_linux.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..04e90aa196259a0992c63a9336d733d2b3ba37ce
--- /dev/null
+++ b/src/hsp3/linux/hsp3ext_linux.cpp
@@ -0,0 +1,19 @@
+
+//
+// HSP3 External program manager (dummy)
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+
+#include "hsp3ext_linux.h"
+
+void hsp3typeinit_dllcmd( HSP3TYPEINFO *info )
+{
+}
+
+void hsp3typeinit_dllctrl( HSP3TYPEINFO *info )
+{
+}
+
diff --git a/src/hsp3/linux/hsp3ext_linux.h b/src/hsp3/linux/hsp3ext_linux.h
new file mode 100644
index 0000000000000000000000000000000000000000..ade3bae4add604db90c334c61c951bca992fe9c9
--- /dev/null
+++ b/src/hsp3/linux/hsp3ext_linux.h
@@ -0,0 +1,13 @@
+
+//
+// hsp3ext.cpp header
+//
+#ifndef __hsp3ext_linux_h
+#define __hsp3ext_linux_h
+
+#include "../hsp3code.h"
+
+void hsp3typeinit_dllcmd( HSP3TYPEINFO *info );
+void hsp3typeinit_dllctrl( HSP3TYPEINFO *info );
+
+#endif
diff --git a/src/hsp3/linux/hsp3gr_linux.cpp b/src/hsp3/linux/hsp3gr_linux.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ce2117ee907de793c7059a4e41a24f6b53c5436
--- /dev/null
+++ b/src/hsp3/linux/hsp3gr_linux.cpp
@@ -0,0 +1,569 @@
+
+//
+// HSP3 graphics command
+// (GUI関連コマンド・関数処理)
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "../hsp3config.h"
+#include "../hsp3code.h"
+#include "../hsp3debug.h"
+#include "../supio.h"
+#include "../strbuf.h"
+
+#include "hsp3gr_linux.h"
+
+/*------------------------------------------------------------*/
+/*
+ system data
+*/
+/*------------------------------------------------------------*/
+
+static HSPCTX *ctx;
+static int *type;
+static int *val;
+static int cur_window;
+static int p1,p2,p3,p4,p5,p6;
+static int ckey,cklast,cktrg;
+static int msact;
+static int dispflg;
+
+extern int resY0, resY1;
+
+/*----------------------------------------------------------*/
+// HSP system support
+/*----------------------------------------------------------*/
+
+static void ExecFile( char *stmp, char *ps, int mode )
+{
+ // 外部ファイル実行
+ system(stmp);
+}
+
+static char *getdir( int id )
+{
+ // dirinfo命令の内容をstmpに設定する
+ //
+ char *p;
+ char *ss;
+ char fname[HSP_MAX_PATH+1];
+ p = ctx->stmp;
+
+ *p = 0;
+
+ switch( id ) {
+ case 0: // カレント(現在の)ディレクトリ
+ break;
+ case 1: // HSPの実行ファイルがあるディレクトリ
+ break;
+ case 2: // Windowsディレクトリ
+ break;
+ case 3: // Windowsのシステムディレクトリ
+ break;
+ case 4: // コマンドライン文字列
+ break;
+ default:
+ throw HSPERR_ILLEGAL_FUNCTION;
+ }
+
+ return p;
+}
+
+
+static int sysinfo( int p2 )
+{
+ // System strings get
+ //
+ int fl;
+ char *p1;
+
+ fl = HSPVAR_FLAG_INT;
+ p1 = ctx->stmp;
+ *p1 = 0;
+
+ return fl;
+}
+
+
+void *ex_getbmscr( int wid )
+{
+ return NULL;
+}
+
+void ex_mref( PVal *pval, int prm )
+{
+ int t,size;
+ void *ptr;
+ const int GETBM=0x60;
+ t = HSPVAR_FLAG_INT;
+ size = 4;
+ if ( prm >= GETBM ) {
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ } else {
+ switch( prm ) {
+ case 0x40:
+ ptr = &ctx->stat;
+ break;
+ case 0x41:
+ ptr = ctx->refstr;
+ t = HSPVAR_FLAG_STR;
+ size = 1024;
+ break;
+ case 0x44:
+ ptr = ctx; size = sizeof(HSPCTX);
+ break;
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ }
+ HspVarCoreDupPtr( pval, t, ptr, size );
+}
+
+
+/*----------------------------------------------------------*/
+// GPIOデバイスコントロール関連
+/*----------------------------------------------------------*/
+
+#ifdef HSPRASPBIAN
+
+#define GPIO_TYPE_NONE 0
+#define GPIO_TYPE_OUT 1
+#define GPIO_TYPE_IN 2
+#define GPIO_MAX 32
+
+#define GPIO_CLASS "/sys/class/gpio/"
+
+static int gpio_type[GPIO_MAX];
+static int gpio_value[GPIO_MAX];
+
+static int echo_file( char *name, char *value )
+{
+ // echo value > name を行なう
+ //printf( "[%s]<-%s\n",name,value );
+ int fd;
+ fd = open( name, O_WRONLY );
+ if (fd < 0) {
+ return -1;
+ }
+ write( fd, value, strlen(value)+1 );
+ close(fd);
+ return 0;
+}
+
+static int echo_file2( char *name, int value )
+{
+ char vstr[64];
+ sprintf( vstr, "%d", value );
+ return echo_file( name, vstr );
+}
+
+static int gpio_delport( int port )
+{
+ if ((port<0)||(port>=GPIO_MAX)) return -1;
+
+ if ( gpio_type[port]==GPIO_TYPE_NONE ) return 0;
+ echo_file2( GPIO_CLASS "unexport", port );
+ usleep(100000); //0.1秒待つ(念のため)
+ gpio_type[port]=GPIO_TYPE_NONE;
+ return 0;
+}
+
+static int gpio_setport( int port, int type )
+{
+ if ((port<0)||(port>=GPIO_MAX)) return -1;
+
+ if ( gpio_type[port]==GPIO_TYPE_NONE ) {
+ echo_file2( GPIO_CLASS "export", port );
+ usleep(100000); //0.1秒待つ(念のため)
+ }
+
+ if ( gpio_type[port] == type ) return 0;
+
+ int res = 0;
+ char vstr[256];
+ sprintf( vstr, GPIO_CLASS "gpio%d/direction", port );
+
+ switch( type ) {
+ case GPIO_TYPE_OUT:
+ res = echo_file( vstr, "out" );
+ break;
+ case GPIO_TYPE_IN:
+ res = echo_file( vstr, "in" );
+ break;
+ }
+
+ if ( res ) {
+ gpio_type[port] = GPIO_TYPE_NONE;
+ return res;
+ }
+
+ gpio_type[port] = type;
+ gpio_value[port] = 0;
+ return 0;
+}
+
+static int gpio_out( int port, int value )
+{
+ if ((port<0)||(port>=GPIO_MAX)) return -1;
+ if ( gpio_type[port]!=GPIO_TYPE_OUT ) {
+ int res = gpio_setport( port, GPIO_TYPE_OUT );
+ if ( res ) return res;
+ }
+
+ char vstr[256];
+ sprintf( vstr, GPIO_CLASS "gpio%d/value", port );
+ if ( value == 0 ) {
+ gpio_value[port] = 0;
+ return echo_file( vstr, "0" );
+ }
+ gpio_value[port] = 1;
+ return echo_file( vstr, "1" );
+}
+
+static int gpio_in( int port, int *value )
+{
+ if ((port<0)||(port>=GPIO_MAX)) return -1;
+ if ( gpio_type[port]!=GPIO_TYPE_IN ) {
+ int res = gpio_setport( port, GPIO_TYPE_IN );
+ if ( res ) return res;
+ }
+
+ int fd,rd,i;
+ char vstr[256];
+ char ev[256];
+ char a1;
+ sprintf( vstr, GPIO_CLASS "gpio%d/value", port );
+
+ fd = open( vstr, O_RDONLY | O_NONBLOCK );
+ if (fd < 0) {
+ return -1;
+ }
+ rd = read(fd,ev,255);
+ if(rd > 0) {
+ i = 0;
+ while(1) {
+ if ( i >= rd ) break;
+ a1 = ev[i++];
+ if ( a1 == '0' ) gpio_value[port] = 0;
+ if ( a1 == '1' ) gpio_value[port] = 1;
+ }
+ }
+ close(fd);
+
+ *value = gpio_value[port];
+ return 0;
+}
+
+static void gpio_init( void )
+{
+ int i;
+ for(i=0;iflag != HSPVAR_FLAG_STR ) {
+ ptr = (char *)HspVarCoreCnv( mpval->flag, HSPVAR_FLAG_STR, ptr ); // 型が一致しない場合は変換
+ }
+ printf( "%s\n",ptr );
+ //strsp_ini();
+ //while(1) {
+ // chk = strsp_get( ptr, stmp, 0, 1022 );
+ // printf( "%s\n",stmp );
+ // if ( chk == 0 ) break;
+ //}
+ break;
+ }
+
+ case 0x27: // input (console)
+ {
+ PVal *pval;
+ APTR aptr;
+ char *pp2;
+ char *vptr;
+ int strsize;
+ int a;
+ strsize = 0;
+ aptr = code_getva( &pval );
+ //pp2 = code_getvptr( &pval, &size );
+ p2 = code_getdi( 0x4000 );
+ p3 = code_getdi( 0 );
+
+ if ( p2 < 64 ) p2 = 64;
+ pp2 = code_stmp( p2+1 );
+
+ switch( p3 & 15 ) {
+ case 0:
+ while(1) {
+ if ( p2<=0 ) break;
+ a = getchar();
+ if ( a==EOF ) break;
+ *pp2++ = a;
+ p2--;
+ strsize++;
+ }
+ break;
+ case 1:
+ while(1) {
+ if ( p2<=0 ) break;
+ a = getchar();
+ if (( a==EOF )||( a=='\n' )) break;
+ *pp2++ = a;
+ p2--;
+ strsize++;
+ }
+ break;
+ case 2:
+ while(1) {
+ if ( p2<=0 ) break;
+ a = getchar();
+ if ( a == '\r' ) {
+ int c = getchar();
+ if( c != '\n' ) {
+ ungetc(c, stdin);
+ }
+ break;
+ }
+ if (( a==EOF )||( a=='\n' )) break;
+ *pp2++ = a;
+ p2--;
+ strsize++;
+ }
+ break;
+ }
+
+ *pp2 = 0;
+ ctx->strsize = strsize + 1;
+
+ if ( p3 & 16 ) {
+ if (( pval->support & HSPVAR_SUPPORT_FLEXSTORAGE ) == 0 ) throw HSPERR_TYPE_MISMATCH;
+ //HspVarCoreAllocBlock( pval, (PDAT *)vptr, strsize );
+ vptr = (char *)HspVarCorePtrAPTR( pval, aptr );
+ memcpy( vptr, ctx->stmp, strsize );
+ } else {
+ code_setva( pval, aptr, TYPE_STRING, ctx->stmp );
+ }
+ break;
+ }
+
+#ifdef HSPRASPBIAN
+
+ case 0x49: // devprm
+ {
+ char *ps;
+ char prmname[256];
+ int p_res;
+ strncpy( prmname, code_gets(), 255 );
+ ps = code_gets();
+ p_res = devprm( prmname, ps );
+ ctx->stat = p_res;
+ break;
+ }
+ case 0x4a: // devcontrol
+ {
+ char *cname;
+ int p_res;
+ cname = code_stmpstr( code_gets() );
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ p_res = devcontrol( cname, p1, p2, p3 );
+ ctx->stat = p_res;
+ break;
+ }
+
+#endif
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ return RUNMODE_RUN;
+}
+
+
+static int reffunc_intfunc_ivalue;
+
+static void *reffunc_function( int *type_res, int arg )
+{
+ void *ptr;
+
+ // 返値のタイプを設定する
+ //
+ *type_res = HSPVAR_FLAG_INT; // 返値のタイプを指定する
+ ptr = &reffunc_intfunc_ivalue; // 返値のポインタ
+
+ // '('で始まるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( *val != '(' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ switch( arg & 0xff ) {
+
+ // int function
+
+ case 0x002: // dirinfo
+ p1 = code_geti();
+ ptr = getdir( p1 );
+ *type_res = HSPVAR_FLAG_STR;
+ break;
+
+ case 0x003: // sysinfo
+ p1 = code_geti();
+ *type_res = sysinfo( p1 );
+ ptr = ctx->stmp;
+ break;
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+
+ // ')'で終わるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( *val != ')' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ return ptr;
+}
+
+
+static int termfunc_extcmd( int option )
+{
+ // termfunc : TYPE_EXTCMD
+ // (内蔵GUI)
+ //
+
+#ifdef HSPRASPBIAN
+ gpio_bye();
+#endif
+ return 0;
+}
+
+void hsp3typeinit_cl_extcmd( HSP3TYPEINFO *info )
+{
+ HSPEXINFO *exinfo; // Info for Plugins
+
+ ctx = info->hspctx;
+ exinfo = info->hspexinfo;
+ type = exinfo->nptype;
+ val = exinfo->npval;
+
+ // function register
+ //
+ info->cmdfunc = cmdfunc_extcmd;
+ info->termfunc = termfunc_extcmd;
+
+ // HSPEXINFOに関数を登録する
+ //
+ exinfo->actscr = &cur_window; // Active Window ID
+ exinfo->HspFunc_getbmscr = ex_getbmscr;
+ exinfo->HspFunc_mref = ex_mref;
+
+ // バイナリモードを設定
+ //
+ //_setmode( _fileno(stdin), _O_BINARY );
+}
+
+void hsp3typeinit_cl_extfunc( HSP3TYPEINFO *info )
+{
+ info->reffunc = reffunc_function;
+
+#ifdef HSPRASPBIAN
+ gpio_init();
+#endif
+}
+
diff --git a/src/hsp3/linux/hsp3gr_linux.h b/src/hsp3/linux/hsp3gr_linux.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ee0b821c51c7d93d9cf003f716db14657e5842b
--- /dev/null
+++ b/src/hsp3/linux/hsp3gr_linux.h
@@ -0,0 +1,15 @@
+
+//
+// hsp3gr_linux.cpp header
+//
+#ifndef __hsp3gr_linux_h
+#define __hsp3gr_linux_h
+
+#include "../hsp3struct.h"
+
+void hsp3typeinit_cl_extcmd( HSP3TYPEINFO *info );
+void hsp3typeinit_cl_extfunc( HSP3TYPEINFO *info );
+
+void hsp3gr_dbg_gui( void );
+
+#endif
diff --git a/src/hsp3/linux/hspwnd_linux.h b/src/hsp3/linux/hspwnd_linux.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1c316fd9ba2340b9acb3226d54d0374269d756d
--- /dev/null
+++ b/src/hsp3/linux/hspwnd_linux.h
@@ -0,0 +1,75 @@
+
+//
+// hspwnd.cpp header
+//
+#ifndef __hspwnd_linux_h
+#define __hspwnd_linux_h
+
+#include "../hsp3code.h"
+
+// Bmscr structure (same as Bmscr)
+//
+typedef struct BMSCR
+{
+ //
+ // Window data structure
+ //
+ int flag; // used flag
+ int sx; // X-size
+ int sy; // Y-size
+ int palmode; // palmode
+ void *hdc; // buffer HDC
+ void *pBit; // bitmap pointer
+ void *pbi; // infoheader
+ void *dib; // bitmap handle(DIB)
+ void *old; // bitmap handle(OLD)
+ void *pal; // palette table
+ void *hpal; // palette handle
+ void *holdpal; // palette handle (old)
+ int pals; // palette entries
+ void *hwnd; // window handle
+ void *hInst; // Instance of program
+ int infsize; // *pbi alloc memory size
+ int bmpsize; // *pBit alloc memory size
+
+ // Window object setting
+ //
+ int type; // setting type
+ int wid; // window ID
+ short fl_dispw; // display window flag
+ short fl_udraw; // update draw window
+ int wx,wy,wchg; // actual window size x,y
+ int viewx,viewy; // buffer view point x,y
+ int lx,ly; // buffer view size x,y
+ int cx,cy; // object cursor x,y
+ int ox,oy,py; // object size x,y,py
+ int texty; // text Y-axis size
+ int gx,gy,gmode; // gcopy size
+ void *hbr; // BRUSH handle
+ void *hpn; // PEN handle
+ void *hfont; // FONT handle
+ void *holdfon; // FONT handle (old)
+ int color; // text color code
+ int textspeed; // slow text speed
+ int cx2,cy2; // slow text cursor x,y
+ int tex,tey; // slow text limit x,y
+ char *prtmes; // slow message ptr
+ int focflg; // focus set flag
+ int objmode; // object set mode
+// LOGFONT logfont; // logical font
+ int style; // extra window style
+ int gfrate; // halftone copy rate
+ int tabmove; // object TAB move mode
+ int sx2; // actual bitmap X size
+// SIZE printsize; // print,mes extent size
+
+ // Class depend data
+ //
+ int objstyle; // objects style
+// HSPOBJINFO *mem_obj; // Window objects
+ int objmax; // Max number of obj
+ int objlimit; // Limit number of obj
+// void *master_hspwnd; // Parent hspwnd class
+} BMSCR;
+
+#endif
diff --git a/src/hsp3/linux/main.cpp b/src/hsp3/linux/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a8af2f09fd80646fb75c75caf01f8bf79b55c744
--- /dev/null
+++ b/src/hsp3/linux/main.cpp
@@ -0,0 +1,35 @@
+/*--------------------------------------------------------
+ HSP3 interpreter main
+ 1995/10 onitama
+ 1997/7 onitama
+ 1999/8 onitama
+ 2003/4 onitama
+ --------------------------------------------------------*/
+
+#include
+#include
+#include "hsp3cl.h"
+#include "../hsp3config.h"
+
+/*----------------------------------------------------------*/
+
+int main( int argc, char *argv[] )
+{
+ int res;
+ char *p;
+
+#ifdef HSPDEBUG
+ if ( argc > 1 ) p = argv[ 1 ]; else p = "";
+#else
+ p = NULL;
+#endif
+
+ res = hsp3cl_init( p );
+ if ( res ) return res;
+ res = hsp3cl_exec();
+
+ return res;
+}
+
+
+
diff --git a/src/hsp3/linux/supio_linux.cpp b/src/hsp3/linux/supio_linux.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..24c763da9bb4eb1c2944b31ca810161e19c6bd72
--- /dev/null
+++ b/src/hsp3/linux/supio_linux.cpp
@@ -0,0 +1,855 @@
+
+//
+// supio.cpp functions (for Linux)
+// Linux用のsupio.cppを別ファイルとして作成しました。
+//
+// Special thanks to Charlotte at HSP開発wiki
+// http://hspdev-wiki.net/?OpenHSP%2FLinux%2Fhsp3
+//
+//
+#include "../hsp3config.h"
+
+#include
+#include
+#include
+#include
+#include
+
+// gettime
+#include
+#include
+// mkdir stat
+#include
+#include
+// changedir delfile get_current_dir_name stat
+#include
+// dirlist
+#include
+
+#include "supio_linux.h"
+
+#include "../dpmread.h"
+#include "../strbuf.h"
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 256
+#endif
+#ifndef _MAX_DIR
+#define _MAX_DIR 256
+#endif
+#ifndef _MAX_EXT
+#define _MAX_EXT 256
+#endif
+#ifndef _MAX_FNAME
+#define _MAX_FNAME 256
+#endif
+
+HSPAPICHAR *chartoapichar( const char *orig,HSPAPICHAR **pphac)
+{
+ *pphac = (HSPAPICHAR*)orig;
+ return (HSPAPICHAR*)orig;
+}
+
+void freehac(HSPAPICHAR **pphac)
+{
+ *pphac = 0;
+ return;
+}
+
+HSPCHAR *apichartohspchar( const HSPAPICHAR *orig,HSPCHAR **pphc)
+{
+ *pphc = (HSPAPICHAR*)orig;
+ return (HSPCHAR*)orig;
+}
+
+void freehc(HSPCHAR **pphc)
+{
+ *pphc = 0;
+ return;
+}
+
+HSPAPICHAR *ansichartoapichar(const char *orig, HSPAPICHAR **pphac)
+{
+ *pphac = (HSPAPICHAR*)orig;
+ return (HSPAPICHAR*)orig;
+}
+
+char *apichartoansichar(const HSPAPICHAR *orig, char **ppc)
+{
+ *ppc = (char*)orig;
+ return (char*)orig;
+}
+
+void freeac(char **ppc)
+{
+ *ppc = 0;
+ return;
+}
+
+//
+// Internal function support (without Windows API)
+//
+static void _splitpath( char *path, char *p_drive, char *dir, char *fname, char *ext )
+{
+ // Linux用ファイルパス切り出し
+ //
+ char *p, pathtmp[256];
+
+ p_drive[0] = 0;
+ strcpy( pathtmp, path );
+
+ p = strchr2( pathtmp, '.' );
+ if ( p == NULL ) {
+ ext[0] = 0;
+ } else {
+ strcpy( ext, p );
+ *p = 0;
+ }
+ p = strchr2( pathtmp, '/' );
+ if ( p == NULL ) {
+ dir[0] = 0;
+ strcpy( fname, pathtmp );
+ } else {
+ strcpy( fname, p+1 );
+ p[1] = 0;
+ strcpy( dir, pathtmp );
+ }
+}
+
+static int wildcard( char *text, char *wc )
+{
+ // textに対してワイルドカード処理を適応
+ // return value: yes 1, no 0
+ //
+ if ( wc[0]=='\0' && *text=='\0' ) {
+ return 1;
+ }
+ if ( wc[0]=='*' ) {
+ if ( *text=='\0' && wc[1]=='\0' ) {
+ return 1;
+ } else if ( *text=='\0' ) {
+ return 0;
+ }
+ if ( wc[1]==*text | wc[1]=='*' ) {
+ if (wildcard( text, wc+1 )) {
+ return 1;
+ }
+ }
+ if ( *text!='\0' ) {
+ return wildcard( text+1, wc );
+ }
+ }
+ if ( (*text!='\0')&&(wc[0]==*text) ) {
+ return wildcard( text+1, wc+1 );
+ }
+ return 0;
+}
+
+
+//
+// basic C I/O support
+//
+static FILE *fp;
+
+char *mem_ini( int size ) {
+ return (char *)calloc(size,1);
+}
+
+void mem_bye( void *ptr ) {
+ free(ptr);
+}
+
+
+int mem_save( char *fname, void *mem, int msize, int seekofs )
+{
+ FILE *fp;
+ int flen;
+
+ if (seekofs<0) {
+ fp=fopen(fname,"wb");
+ }
+ else {
+ fp=fopen(fname,"r+b");
+ }
+ if (fp==NULL) return -1;
+ if ( seekofs>=0 ) fseek( fp, seekofs, SEEK_SET );
+ flen = (int)fwrite( mem, 1, msize, fp );
+ fclose(fp);
+ return flen;
+}
+
+
+size_t utf8strlen( const char *target )
+{
+ // UTF8文字列の長さを得る
+ //
+ unsigned char *p;
+ unsigned char *base;
+ unsigned char a1;
+ p = (unsigned char *)target;
+ base = p;
+ while(1) {
+ a1=*p;if ( a1==0 ) break;
+ p++; // 検索位置を移動
+ if (a1>=128) { // 多バイト文字チェック
+ if (a1>=192) p++;
+ if (a1>=224) p++;
+ if (a1>=240) p++;
+ if (a1>=248) p++;
+ if (a1>=252) p++;
+ }
+ }
+ return (size_t)(p-base);
+}
+
+
+void strcase( char *target )
+{
+ // strをすべて小文字に(utf8対応版)
+ //
+ unsigned char *p;
+ unsigned char a1;
+ p=(unsigned char *)target;
+ while(1) {
+ a1=*p;if ( a1==0 ) break;
+ *p=tolower(a1);
+ p++; // 検索位置を移動
+ if (a1>=128) { // 多バイト文字チェック
+ if (a1>=192) p++;
+ if (a1>=224) p++;
+ if (a1>=240) p++;
+ if (a1>=248) p++;
+ if (a1>=252) p++;
+ }
+ }
+}
+
+int strcpy2( char *str1, char *str2 )
+{
+ // string copy (ret:length)
+ //
+ char *p;
+ char *src;
+ char a1;
+ src = str2;
+ p = str1;
+ while(1) {
+ a1=*src++;if (a1==0) break;
+ *p++=a1;
+ }
+ *p++=0;
+ return (int)(p-str1);
+}
+
+
+int strcat2( char *str1, char *str2 )
+{
+ // string cat (ret:length)
+ //
+ char *src;
+ char a1;
+ int i;
+ src = str1;
+ while(1) {
+ a1=*src;if (a1==0) break;
+ src++;
+ }
+ i = (int)(src-str1);
+ return (strcpy2(src,str2)+i);
+}
+
+
+char *strstr2( char *target, char *src )
+{
+ // strstr関数のutf8対応版
+ //
+ unsigned char *p;
+ unsigned char *s;
+ unsigned char *p2;
+ unsigned char a1;
+ unsigned char a2;
+ unsigned char a3;
+ p=(unsigned char *)target;
+ if (( *src==0 )||( *target==0 )) return NULL;
+ while(1) {
+ a1=*p;if ( a1==0 ) break;
+ p2 = p;
+ s=(unsigned char *)src;
+ while(1) {
+ a2=*s++;if (a2==0) return (char *)p;
+ a3=*p2++;if (a3==0) break;
+ if (a2!=a3) break;
+ }
+ p++; // 検索位置を移動
+ if (a1>=128) { // 多バイト文字チェック
+ if (a1>=192) p++;
+ if (a1>=224) p++;
+ if (a1>=240) p++;
+ if (a1>=248) p++;
+ if (a1>=252) p++;
+ }
+ }
+ return NULL;
+}
+
+
+char *strchr2( char *target, char code )
+{
+ // str中最後のcode位置を探す(utf8対応版)
+ //
+ unsigned char *p;
+ unsigned char a1;
+ char *res;
+ p=(unsigned char *)target;
+ res = NULL;
+ while(1) {
+ a1=*p;if ( a1==0 ) break;
+ if ( a1==code ) res=(char *)p;
+ p++; // 検索位置を移動
+ if (a1>=128) { // 多バイト文字チェック
+ if (a1>=192) p++;
+ if (a1>=224) p++;
+ if (a1>=240) p++;
+ if (a1>=248) p++;
+ if (a1>=252) p++;
+ }
+ }
+ return res;
+}
+
+
+void getpath( char *stmp, char *outbuf, int p2 )
+{
+ char *p;
+ char tmp[_MAX_PATH];
+ char p_drive[_MAX_PATH];
+ char p_dir[_MAX_DIR];
+ char p_fname[_MAX_FNAME];
+ char p_ext[_MAX_EXT];
+
+ p = outbuf;
+ if (p2&16) strcase( stmp );
+ _splitpath( stmp, p_drive, p_dir, p_fname, p_ext );
+
+ strcat( p_drive, p_dir );
+ if ( p2&8 ) {
+ strcpy( tmp, p_fname ); strcat( tmp, p_ext );
+ } else if ( p2&32 ) {
+ strcpy( tmp, p_drive );
+ } else {
+ strcpy( tmp, stmp );
+ }
+ switch( p2&7 ) {
+ case 1: // Name only ( without ext )
+ stmp[ strlen(tmp)-strlen(p_ext) ] = 0;
+ strcpy( p, tmp );
+ break;
+ case 2: // Ext only
+ strcpy( p, p_ext );
+ break;
+ default: // Direct Copy
+ strcpy( p, tmp );
+ break;
+ }
+}
+
+
+int makedir( char *name )
+{
+ return mkdir( name, 0755 );
+}
+
+
+int changedir( char *name )
+{
+ return chdir( name );
+}
+
+
+int delfile( char *name )
+{
+ return unlink( name );
+ //return remove( name ); // ディレクトリにもファイルにも対応
+}
+
+
+int dirlist( char *fname, char **target, int p3 )
+{
+ // Linux System
+ //
+ enum { MASK = 3 }; // mode 3までのビット反転用
+ char *p;
+ unsigned int fl;
+ unsigned int stat_main;
+ unsigned int fmask;
+ DIR *sh;
+ struct dirent *fd;
+ struct stat st;
+ char curdir[_MAX_PATH+1];
+
+ stat_main=0;
+
+ //sh = opendir( get_current_dir_name() );
+ getcwd( curdir, _MAX_PATH );
+ sh = opendir( curdir ); // get_current_dir_nameはMinGWで通らなかったのでとりあえず
+
+ fd = readdir( sh );
+ while( fd != NULL ) {
+ p = fd->d_name; fl = 1;
+ if ( *p==0 ) fl=0; // 空行を除外
+ if ( *p=='.') { // '.','..'を除外
+ if ( p[1]==0 ) fl=0;
+ if ((p[1]=='.')&&(p[2]==0)) fl=0;
+ }
+ // 表示/非表示のマスク
+ // Linux用なのでシステム属性は考慮しない
+ if (p3!=0 && fl==1) {
+ stat( p, &st );
+ fmask=0;
+ if (p3&4) { // 条件反転
+ if (S_ISREG( st.st_mode )&&( *p!='.' )) {
+ fl=0;
+ } else {
+ fmask=MASK;
+ }
+ }
+ if ( fl==1 ) {
+ if ((p3^fmask)&1 && S_ISDIR( st.st_mode )) fl=0; //ディレクトリ
+ if ((p3^fmask)&2 && ( *p=='.' )) fl=0; //隠しファイル
+ }
+ }
+ // ワイルドカード処理
+ //
+ if (fl) {
+ fl=wildcard( p, fname );
+ }
+
+ if (fl) {
+ stat_main++;
+ sbStrAdd( target, p );
+ sbStrAdd( target, "\n" );
+ }
+ fd = readdir( sh );
+ }
+ closedir( sh );
+ return stat_main;
+}
+
+
+int gettime( int index )
+{
+/*
+ Get system time entries
+ index :
+ 0 wYear
+ 1 wMonth
+ 2 wDayOfWeek
+ 3 wDay
+ 4 wHour
+ 5 wMinute
+ 6 wSecond
+ 7 wMilliseconds
+ 8 wMicroseconds
+*/
+ struct timeval tv;
+ struct tm *lt;
+
+ gettimeofday( &tv, NULL ); // MinGWだとVerによって通りません
+ lt = localtime( &tv.tv_sec );
+
+ switch( index ) {
+ case 0:
+ return lt->tm_year+1900;
+ case 1:
+ return lt->tm_mon+1;
+ case 2:
+ return lt->tm_wday;
+ case 3:
+ return lt->tm_mday;
+ case 4:
+ return lt->tm_hour;
+ case 5:
+ return lt->tm_min;
+ case 6:
+ return lt->tm_sec;
+ case 7:
+ return (int)tv.tv_usec/10000;
+ case 8:
+ /* 一応マイクロ秒まで取れる */
+ return (int)tv.tv_usec%10000;
+ }
+ return 0;
+}
+
+
+static int splc; // split pointer
+
+void strsp_ini( void )
+{
+ splc=0;
+}
+
+int strsp_getptr( void )
+{
+ return splc;
+}
+
+int strsp_get( char *srcstr, char *dststr, char splitchr, int len )
+{
+ // split string with parameters
+ //
+
+/*
+ rev 44
+ mingw : warning : 比較は常に偽
+ に対処
+*/
+ unsigned char a1;
+ unsigned char a2;
+ int a;
+ int utf8cnt;
+ a=0;utf8cnt=0;
+ while(1) {
+ utf8cnt=0;
+ a1=srcstr[splc];
+ if (a1==0) break;
+ splc++;
+ if (a1>=128) { // 多バイト文字チェック
+ if (a1>=192) utf8cnt++;
+ if (a1>=224) utf8cnt++;
+ if (a1>=240) utf8cnt++;
+ if (a1>=248) utf8cnt++;
+ if (a1>=252) utf8cnt++;
+ }
+
+ if (a1==splitchr) break;
+ if (a1==13) {
+ a2=srcstr[splc];
+ if (a2==10) splc++;
+ break;
+ }
+#ifdef HSPLINUX
+ if (a1==10) {
+ a2=srcstr[splc];
+ break;
+ }
+#endif
+ dststr[a++]=a1;
+ if (utf8cnt>0) {
+ while(utf8cnt>0){
+ dststr[a++]=srcstr[splc++];
+ utf8cnt--;
+ }
+ }
+ if ( a>=len ) break;
+ }
+ dststr[a]=0;
+ return (int)a1;
+}
+
+
+char *strsp_cmds( char *srcstr )
+{
+ // Skip 1parameter from command line
+ //
+ int spmode;
+ char a1;
+ char *cmdchk;
+ cmdchk = srcstr;
+ spmode=0;
+ while(1) {
+ a1=*cmdchk;
+ if (a1==0) break;
+ cmdchk++;
+ if (a1==32) if (spmode==0) break;
+ if (a1==0x22) spmode^=1;
+ }
+ return cmdchk;
+}
+
+
+int GetLimit( int num, int min, int max )
+{
+ if ( num > max ) return max;
+ if ( num < min ) return min;
+ return num;
+}
+
+
+void CutLastChr( char *p, char code )
+{
+ // 最後の'\\'を取り除く
+ //
+ char *ss;
+ char *ss2;
+ int i;
+ ss = strchr2( p, '\\' );
+ if ( ss != NULL ) {
+ i = (int)strlen( p ); ss2 = p + i -1;
+ if (( i > 3 )&&( ss == ss2 )) *ss = 0;
+ }
+}
+
+
+static int htoi_sub( char hstr )
+{
+ // exchange hex to int
+
+ char a1;
+ a1=tolower(hstr);
+ if ((a1>='0')&&(a1<='9')) return a1-'0';
+ if ((a1>='a')&&(a1<='f')) return a1-'a'+10;
+ return 0;
+}
+
+
+int htoi( char *str )
+{
+ char a1;
+ int d;
+ int conv;
+ conv = 0;
+ d = 0;
+ while(1) {
+ a1=str[d++];if ( a1 == 0 ) break;
+ conv=(conv<<4) + htoi_sub(a1);
+ }
+ return conv;
+}
+
+
+/*----------------------------------------------------------*/
+// HSP string trim support
+/*----------------------------------------------------------*/
+
+char *strchr3( char *target, int code, int sw, char **findptr )
+{
+ // 文字列中のcode位置を探す(2バイトコード、utf8-4バイト分対応版)
+ // sw = 0 : findptr = 最後に見つかったcode位置
+ // sw = 1 : findptr = 最初に見つかったcode位置
+ // sw = 2 : findptr = 最初に見つかったcode位置(最初の文字のみ検索)
+ // 戻り値 : 次の文字にあたる位置
+ //
+ unsigned char *p;
+ unsigned char a1;
+ unsigned char code1;
+ unsigned char code2;
+ unsigned char code3;
+ unsigned char code4;
+ char *res;
+ char *pres;
+
+ p=(unsigned char *)target;
+ code1 = (unsigned char)(code&0xff);
+ code2 = (unsigned char)(code>>8);
+ code3 = (unsigned char)(code>>16);
+ code4 = (unsigned char)(code>>24);
+
+ res = NULL;
+ pres = NULL;
+ *findptr = NULL;
+
+ while(1) {
+ a1=*p;if ( a1==0 ) break;
+ if ( a1==code1 ) {
+ if ( a1 <128 ) {
+ res=(char *)p;
+ } else {
+ if (a1>=128) {
+ if (a1>=192) {
+ if ( p[1]==code2 ) {
+ if (a1>=224) {
+ if ( p[2]==code3 ) {
+ if (a1>=240) {
+ if ( p[3]==code4 ) {
+ res=(char *)p;
+ }
+ }else{
+ res=(char *)p;
+ }
+ }
+ }else{
+ res=(char *)p;
+ }
+ }
+ }else{
+ res=(char *)p;
+ }
+ } else {
+ res=(char *)p;
+ }
+ }
+ }
+ p++; // 検索位置を移動
+ if (a1>=128) { // 多バイト文字チェック
+ if (a1>=192) p++;
+ if (a1>=224) p++;
+ if (a1>=240) p++;
+ if (a1>=248) p++;
+ if (a1>=252) p++;
+ }
+ if ( res != NULL ) { *findptr = res; pres = (char *)p; res = NULL; }
+
+ switch( sw ) {
+ case 1:
+ if ( *findptr != NULL ) return (char *)p;
+ break;
+ case 2:
+ return (char *)p;
+ }
+ }
+ return pres;
+}
+
+
+void TrimCodeR( char *p, int code )
+{
+ // 最後のcodeを取り除く
+ //
+ char *ss;
+ char *ss2;
+ char *sslast;
+ int i;
+ while(1) {
+ i = (int)strlen( p );
+ sslast = p + i;
+ ss = strchr3( p, code, 0, &ss2 );
+ if ( ss2 == NULL ) break;
+ if ( ss != sslast ) break;
+ *ss2 = 0;
+ }
+}
+
+
+void TrimCode( char *p, int code )
+{
+ // すべてのcodeを取り除く
+ //
+ char *ss;
+ char *ss2;
+ while(1) {
+ ss = strchr3( p, code, 1, &ss2 );
+ if ( ss2 == NULL ) break;
+ strcpy( ss2, ss );
+ }
+}
+
+
+void TrimCodeL( char *p, int code )
+{
+ // 最初のcodeを取り除く
+ //
+ char *ss;
+ char *ss2;
+ while(1) {
+ ss = strchr3( p, code, 2, &ss2 );
+ if ( ss2 == NULL ) break;
+ strcpy( ss2, ss );
+ }
+}
+
+//
+// 文字列置き換え
+//
+static char *s_match;
+static int len_match;
+static char *s_rep;
+static int len_rep;
+static char *s_buffer;
+static int len_buffer;
+static char *s_result;
+static int len_result;
+static int reptime;
+
+void ReplaceSetMatch(char *src, char *match, char *result, int in_src, int in_match, int in_result)
+{
+ // 置き換え元、置き換え対象のセット
+ // (あらかじめメモリバッファの確保が必要)
+ //
+ s_buffer = src;
+ s_match = match;
+ s_result = result;
+ len_buffer = in_src;
+ len_match = in_match;
+ len_result = in_result;
+}
+
+char *ReplaceStr( char *repstr )
+{
+ // 置き換え実行
+ //
+ char *p;
+ unsigned char a1;
+ unsigned char a2;
+ int psize, csize, cursize, i;
+ int utf8cnt;
+
+ s_rep = repstr;
+ len_rep = (int)strlen( s_rep );
+ reptime = 0;
+
+ // replace
+ //
+ cursize = 0;
+ p = s_buffer;
+ a2 = (unsigned char)s_match[0];
+ while(1) {
+ a1 = (unsigned char)*p;
+ if ( a1 == 0 ) break;
+
+ utf8cnt=0;
+ if (a1>=128) { // 多バイト文字チェック
+ if (a1>=192) utf8cnt++;
+ if (a1>=224) utf8cnt++;
+ if (a1>=240) utf8cnt++;
+ if (a1>=248) utf8cnt++;
+ if (a1>=252) utf8cnt++;
+ }
+
+ // 比較する
+ psize = 0; csize = 1;
+ if ( a1 == a2 ) {
+ if ( memcmp( p, s_match, len_match ) == 0 ) {
+ psize = len_match;
+ csize = len_rep;
+ }
+ }
+
+ // バッファチェック
+ i = cursize + csize;
+ if ( i >= len_result ) {
+ len_result += 0x8000;
+ s_result = sbExpand( s_result, len_result );
+ }
+
+ if ( psize ) { // 置き換え
+
+ memcpy( s_result+cursize, s_rep, csize );
+ p += psize;
+ cursize += csize;
+ reptime++;
+
+ } else { // 置き換えなし
+ s_result[cursize++] = a1;
+ p++;
+ if ( utf8cnt>0 ) {
+ while (utf8cnt>0){
+ s_result[cursize++] = *p++;
+ utf8cnt--;
+ }
+ }
+ }
+
+ }
+ s_result[cursize] = 0;
+ return s_result;
+}
+
+int ReplaceDone( void )
+{
+ // 置き換えの後処理
+ //
+ return reptime;
+}
+
+
diff --git a/src/hsp3/linux/supio_linux.h b/src/hsp3/linux/supio_linux.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab49fddd48151b1195d46bd166294436ce21bac3
--- /dev/null
+++ b/src/hsp3/linux/supio_linux.h
@@ -0,0 +1,56 @@
+
+//
+// supio.cpp functions (linux)
+//
+
+#define HSPAPICHAR char
+#define HSPCHAR char
+
+size_t utf8strlen(const char *target);
+
+char *mem_ini( int size );
+void mem_bye( void *ptr );
+int mem_save( char *fname, void *mem, int msize, int seekofs );
+void strcase( char *str );
+int strcpy2( char *str1, char *str2 );
+int strcat2( char *str1, char *str2 );
+char *strstr2( char *target, char *src );
+char *strchr2( char *target, char code );
+void getpath( char *stmp, char *outbuf, int p2 );
+int makedir( char *name );
+int changedir( char *name );
+int delfile( char *name );
+int dirlist( char *fname, char **target, int p3 );
+int gettime( int index );
+void strsp_ini( void );
+int strsp_getptr( void );
+int strsp_get( char *srcstr, char *dststr, char splitchr, int len );
+int GetLimit( int num, int min, int max );
+void CutLastChr( char *p, char code );
+char *strsp_cmds( char *srcstr );
+int htoi( char *str );
+
+int SecurityCheck( char *name );
+
+char *strchr3( char *target, int code, int sw, char **findptr );
+void TrimCode( char *p, int code );
+void TrimCodeL( char *p, int code );
+void TrimCodeR( char *p, int code );
+
+void ReplaceSetMatch( char *src, char *match, char *result, int in_src, int in_match, int in_result );
+char *ReplaceStr( char *repstr );
+int ReplaceDone( void );
+
+void Alert( char *mes );
+void AlertV( char *mes, int val );
+void Alertf( char *format, ... );
+
+HSPAPICHAR *chartoapichar( const HSPCHAR*,HSPAPICHAR** );
+void freehac( HSPAPICHAR** );
+HSPCHAR *apichartohspchar( const HSPAPICHAR*,HSPCHAR** );
+void freehc( HSPCHAR** );
+HSPAPICHAR *ansichartoapichar(const char *, HSPAPICHAR **);
+char *apichartoansichar(const HSPAPICHAR *, char **);
+void freeac(char **);
+
+
diff --git a/src/hsp3/makefile b/src/hsp3/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..aa975eae7662607d1399104d947560772e613be9
--- /dev/null
+++ b/src/hsp3/makefile
@@ -0,0 +1,617 @@
+#/*-------------------------------------------------------------------------*/
+#
+# HSPランタイムのビルド。(mingw用)
+#
+# GNU make 用メイクファイル
+#
+# (使い方)
+# make ( [ ... ] [ release ] [ all ] ) | ( clean ) | cleanall
+#
+# は
+# linux
+# win32_mingw
+# win32gui_mingw
+# win64gui_mingw
+# のどれか。
+# makeにall, cleanを渡す場合もPLATFORMは必要です。
+#
+# にファイルを指定すると指定したファイルのみをビルド対象にする。
+# 指定しなかった場合は に対応した実行ファイルを対象にする。
+#
+# release を指定するとリリースビルド、そうでなければデバッグビルドを作成できます。
+#
+# all を指定すると に関係したオブジェクトファイル・実行ファイル全てのリビルド。
+# clean を指定すると に関係したオブジェクトファイル・実行ファイルの削除。
+# cleanallを指定するとオブジェクトファイルと実行ファイルの削除。
+#
+# HSPランタイムはWindows 2000以降用です
+#
+#
+#
+#/*-------------------------------------------------------------------------*/
+
+#/*-----------------------------------------------------------*/
+#
+# 追加インクルードパス (オプション)
+
+includedir =
+libdir =
+
+#/*-----------------------------------------------------------*/
+#
+# C++のバージョン
+
+CXXVER = -std=gnu++11
+
+#/*-----------------------------------------------------------*/
+#
+# 環境フラグ
+# それぞれのフラグはお互いと使用可能です
+#
+
+ENVFLAGS =
+
+#コンパクト版ランタイム (win64gui_mingwの場合、これを使用しなければならない)
+#ENVFLAGS = -DHSP_COMPACT -DHSP_COM_UNSUPPORTED
+
+#ユニコード版ランタイム (win32gui_mingw、win64gui_mingw用)
+#ENVFLAGS = -DHSPUTF8 -DUNICODE -D_UNICODE
+
+#/*-----------------------------------------------------------*/
+#
+# 削除コマンド
+#
+
+LINUXRM = rm -rf
+WINRM = del /Q /F
+
+#/*-----------------------------------------------------------*/
+#
+# プラットフォーム判定
+#
+
+PLATFORM =
+
+#/*------------------------------------------*/
+
+ifneq ($(filter linux,$(MAKECMDGOALS)),)
+ PLATFORM := $(PLATFORM) linux
+endif
+
+ifneq ($(filter win32_mingw,$(MAKECMDGOALS)),)
+ PLATFORM := $(PLATFORM) win32_mingw
+endif
+
+ifneq ($(filter win32gui_mingw,$(MAKECMDGOALS)),)
+ PLATFORM := $(PLATFORM) win32gui_mingw
+endif
+
+ifneq ($(filter win64gui_mingw,$(MAKECMDGOALS)),)
+ PLATFORM := $(PLATFORM) win64gui_mingw
+endif
+
+#/*------------------------------------------*/
+
+ifneq ($(words $(PLATFORM)),1)
+ PLATFORM =
+endif
+
+#/*------------------------------------------*/
+
+#/*-----------------------------------------------------------*/
+#
+# プラットフォームごとの設定
+#
+
+#/*------------------------------------------*/
+#
+# gcc で linux 版ランタイムをビルド。
+#
+# 動作未確認。問題があれば makefile.linux の内容を参照してください。
+#
+
+ifneq ($(filter linux,$(PLATFORM)),)
+
+ includedir := $(includedir)
+ libdir := $(libdir)
+
+ vpath
+ vpath %.c ./linux
+ vpath %.cpp ./linux
+ vpath %.h ./linux
+ vpath %.hpp ./linux
+
+ RM = $(LINUXRM)
+
+ CC = gcc
+ ENVFLAGS += -DHSPLINUX -DHSPUTF8
+ CFLAGS_B = -Wall -finput-charset=cp932 -fexec-charset=cp932 \
+ $(ENVFLAGS) $(addprefix -I,$(includedir))
+ CFLAGS_D = $(CFLAGS_B) -DHSPDEBUG
+ CFLAGS_R = $(CFLAGS_B) -O3 -DNDEBUG
+
+ CXX = $(CC)
+ CXXFLAGS_B = $(CFLAGS_B) $(CXXVER)
+ CXXFLAGS_D = $(CFLAGS_D) $(CXXVER)
+ CXXFLAGS_R = $(CFLAGS_R) $(CXXVER)
+
+ AS = nasm
+ ASFLAGS = $(ASMOPTS) -i$(asmdir) -f elf32 -o
+
+ LD = $(CC)
+ LDFLAGS_B = $(LINKOPTS) -s $(addprefix -L,$(libdir)) $(addprefix -l,$(LIBS))
+ LDFLAGS_D = $(LDFLAGS_B)
+ LDFLAGS_R = $(LDFLAGS_B)
+
+ PF_TARGET_D = hsp3
+ PF_TARGET_R = $(PF_TARGET_D)
+
+ OBJS = linux/main.o hsp3.o hsp3code.o hsp3debug.o hsp3int.o \
+ hspvar_core.o hspvar_double.o hspvar_int.o hspvar_label.o \
+ hspvar_str.o hspvar_struct.o stack.o strbuf.o strnote.o \
+ dpmread.o linux/supio_linux.o linux/hsp3cl.o \
+ linux/hsp3ext_linux.o linux/hsp3gr_linux.o
+ RESES =
+ LIBS = m stdc++
+
+endif
+
+#/*------------------------------------------*/
+
+#/*------------------------------------------*/
+#
+# mingw で Windows コンソール版ランタイムをビルド。
+#
+# TDM-GCC (GCC 5.10) でこれは確認
+
+ifneq ($(filter win32_mingw,$(PLATFORM)),)
+
+ includedir := $(includedir)
+ libdir := $(libdir)
+
+ asmdir := ./win32gui/
+
+ vpath
+ vpath %.c ./win32 ./win32gui
+ vpath %.cpp ./win32 ./win32gui
+ vpath %.h ./win32 ./win32gui $(asmdir)
+ vpath %.hpp ./win32 ./win32gui
+ vpath %.rc ./win32 ./win32gui
+ vpath %.mac $(asmdir)
+ vpath %.asm $(asmdir)
+
+ RM = $(WINRM)
+
+ CC = gcc
+ ENVFLAGS += -DWINVER=0x0500 -D_WIN32_IE=0x0500 -DHSPWIN -DHSPCL_WIN
+ CFLAGS_B = -m32 -Wall -Wno-unused -fexceptions -fsigned-char -finput-charset=cp932 -fexec-charset=cp932 -mwindows -mconsole -Os \
+ $(ENVFLAGS) $(addprefix -I,$(includedir))
+ CFLAGS_D = $(CFLAGS_B) -DHSPDEBUG
+ CFLAGS_R = $(CFLAGS_B) -DNDEBUG
+
+ CXX = g++
+ CXXFLAGS_B = $(CFLAGS_B) $(CXXVER)
+ CXXFLAGS_D = $(CFLAGS_D) $(CXXVER)
+ CXXFLAGS_R = $(CFLAGS_R) $(CXXVER)
+
+ AS = nasm
+ ASFLAGS = -i$(asmdir) -f win32 -o
+
+ LD = g++
+ LDFLAGS_B = -m32 -s -mwindows -mconsole \
+ $(addprefix -L,$(libdir)) $(addprefix -l,$(LIBS))
+ LDFLAGS_D = $(LDFLAGS_B)
+ LDFLAGS_R = $(LDFLAGS_B)
+
+ PF_TARGET_D = hsp3cl.exe
+ PF_TARGET_R = $(PF_TARGET_D)
+
+ RESES =
+ ASMOBJS =
+
+ OBJS := dpmread.o hsp3.o hsp3code.o hsp3debug.o hsp3int.o hspvar_core.o \
+ hspvar_double.o hspvar_int.o hspvar_label.o hspvar_str.o \
+ hspvar_struct.o stack.o strbuf.o strnote.o \
+ win32/hsp3cl.o win32/hsp3gr_win.o win32/main.o \
+ win32gui/comobj.o win32gui/comobj_event.o win32gui/filedlg.o win32gui/hsp3ext_win.o win32gui/hsp3extlib.o \
+ win32gui/hspvar_comobj.o win32gui/hspvar_variant.o win32gui/supio_win.o win32gui/supio_win_unicode.o \
+ $(RESES) $(ASMOBJS)
+
+ asmdir = ./win32asm/
+ LIBS = comctl32 ole32 oleaut32 uuid
+
+endif
+
+#/*------------------------------------------*/
+
+#/*------------------------------------------*/
+#
+# mingw で Windows GUI 版ランタイムをビルド。
+#
+# TDM-GCC (GCC 5.10) でこれは確認。
+#
+
+ifneq ($(filter win32gui_mingw,$(PLATFORM)),)
+
+ includedir := $(includedir)
+ libdir := $(libdir)
+
+ asmdir := ./win32gui/
+
+ vpath
+ vpath %.c ./win32gui
+ vpath %.cpp ./win32gui
+ vpath %.h ./win32gui $(asmdir)
+ vpath %.hpp ./win32gui
+ vpath %.rc ./win32gui
+ vpath %.mac $(asmdir)
+ vpath %.asm $(asmdir)
+
+ RM = $(WINRM)
+
+ CC = gcc
+ ENVFLAGS += -DWINVER=0x0500 -D_WIN32_IE=0x0500 -D_WIN32_WINNT=0x0500 -DHSPWIN -DHSPWINGUI
+ CFLAGS_B = -m32 -Wall -Wno-unused -fexceptions -fsigned-char -finput-charset=cp932 -fexec-charset=cp932 -mwindows -Os \
+ $(ENVFLAGS) $(addprefix -I,$(includedir))
+ CFLAGS_D = $(CFLAGS_B) -DHSPDEBUG
+ CFLAGS_R = $(CFLAGS_B) -DNDEBUG
+
+ CXX = g++
+ CXXFLAGS_B = $(CFLAGS_B) $(CXXVER)
+ CXXFLAGS_D = $(CFLAGS_D) $(CXXVER)
+ CXXFLAGS_R = $(CFLAGS_R) $(CXXVER)
+
+ AS = nasm
+ ASFLAGS = -i$(asmdir) -f win32 -o
+
+ WINDRES = windres
+ RCFLAGS = -J rc -O coff -F pe-i386
+
+ LD = g++
+ LDFLAGS_B = -m32 -s -mwindows $(addprefix -L,$(libdir)) $(addprefix -l,$(LIBS))
+ LDFLAGS_D = $(LDFLAGS_B)
+ LDFLAGS_R = $(LDFLAGS_B)
+
+ PF_TARGET_D = hsp3.exe
+ PF_TARGET_R = hsprt.exe
+
+ RESES = hsp3.res
+ ASMOBJS =
+
+ OBJS := dpmread.o hsp3.o hsp3code.o hsp3debug.o hsp3int.o hspvar_core.o \
+ hspvar_double.o hspvar_int.o hspvar_label.o hspvar_str.o \
+ hspvar_struct.o stack.o strbuf.o strnote.o \
+ win32gui/comobj.o win32gui/comobj_event.o win32gui/fcpoly.o win32gui/filedlg.o win32gui/hsp3ext_win.o \
+ win32gui/hsp3extlib.o win32gui/hsp3gr_wingui.o win32gui/hsp3win.o win32gui/hspvar_comobj.o \
+ win32gui/hspvar_variant.o win32gui/hspwnd_obj.o win32gui/hspwnd_win.o win32gui/main.o win32gui/mmman.o win32gui/supio_win.o win32gui/supio_win_unicode.o win32gui/stb_image.o \
+ $(RESES) $(ASMOBJS)
+
+ asmdir = ./win32asm/
+ LIBS = comctl32 ole32 oleaut32 uuid winmm msimg32
+
+endif
+
+#/*------------------------------------------*/
+
+#/*------------------------------------------*/
+#
+# mingw で Windows GUI 版ランタイムをビルド。
+# Win64ランタイム
+#
+# TDM-GCC (GCC 5.10) でこれは確認。(コンパクト版のみ確認)
+#
+
+ifneq ($(filter win64gui_mingw,$(PLATFORM)),)
+
+ includedir := $(includedir)
+ libdir := $(libdir)
+
+ asmdir := ./win32gui/
+
+ vpath
+ vpath %.c ./win32gui
+ vpath %.cpp ./win32gui
+ vpath %.h ./win32gui $(asmdir)
+ vpath %.hpp ./win32gui
+ vpath %.rc ./win32gui
+ vpath %.mac $(asmdir)
+ vpath %.asm $(asmdir)
+
+ RM = $(WINRM)
+
+ CC = gcc
+ ENVFLAGS += -DHSP64 -DHSPWIN -DHSPWINGUI
+ CFLAGS_B = -m64 -Wall -Wno-unused -fexceptions -fsigned-char -finput-charset=cp932 -fexec-charset=cp932 -mwindows -Os \
+ $(ENVFLAGS) $(addprefix -I,$(includedir))
+ CFLAGS_D = $(CFLAGS_B) -DHSPDEBUG
+ CFLAGS_R = $(CFLAGS_B) -DNDEBUG
+
+ CXX = g++
+ CXXFLAGS_B = $(CFLAGS_B) $(CXXVER)
+ CXXFLAGS_D = $(CFLAGS_D) $(CXXVER)
+ CXXFLAGS_R = $(CFLAGS_R) $(CXXVER)
+
+ AS = nasm
+ ASFLAGS = -i$(asmdir) -f win64 -o
+
+ WINDRES = windres
+ RCFLAGS = -J rc -O coff
+
+ LD = g++
+ LDFLAGS_B = -m64 -s -mwindows $(addprefix -L,$(libdir)) $(addprefix -l,$(LIBS))
+ LDFLAGS_D = $(LDFLAGS_B)
+ LDFLAGS_R = $(LDFLAGS_B)
+
+ PF_TARGET_D = hsp3_64.exe
+ PF_TARGET_R = hsprt.exe
+
+ RESES = hsp3.res
+ ASMOBJS = win32gui/callex64_nasm.o
+
+ OBJS := dpmread.o hsp3.o hsp3code.o hsp3debug.o hsp3int.o hspvar_core.o \
+ hspvar_double.o hspvar_int.o hspvar_label.o hspvar_str.o \
+ hspvar_struct.o stack.o strbuf.o strnote.o \
+ win32gui/comobj.o win32gui/comobj_event.o win32gui/fcpoly.o win32gui/filedlg.o win32gui/hsp3ext_win.o \
+ win32gui/hsp3extlib.o win32gui/hsp3gr_wingui.o win32gui/hsp3win.o win32gui/hspvar_comobj.o \
+ win32gui/hspvar_variant.o win32gui/hspwnd_obj.o win32gui/hspwnd_win.o win32gui/main.o win32gui/mmman.o win32gui/supio_win.o win32gui/supio_win_unicode.o win32gui/stb_image.o \
+ $(RESES) $(ASMOBJS)
+
+ LIBS = comctl32 ole32 oleaut32 uuid winmm msimg32
+
+endif
+
+#/*------------------------------------------*/
+
+#/*-----------------------------------------------------------*/
+
+#/*------------------------------------------*/
+#
+# リリース・デバッグの切り替え。
+#
+
+ifneq ($(filter release,$(MAKECMDGOALS)),)
+ CFLAGS = $(CFLAGS_R)
+ CXXFLAGS = $(CXXFLAGS_R)
+ LDFLAGS = $(LDFLAGS_R)
+ PF_TARGET = $(PF_TARGET_R)
+else
+ CFLAGS = $(CFLAGS_D)
+ CXXFLAGS = $(CXXFLAGS_D)
+ LDFLAGS = $(LDFLAGS_D)
+ PF_TARGET = $(PF_TARGET_D)
+endif
+
+#/*------------------------------------------*/
+
+TARGET = $(filter *.o *.exe *.dll,$(MAKECMDGOALS))
+
+ifeq ($(words $(TARGET)),0)
+ TARGET = $(PF_TARGET)
+endif
+
+#/*-----------------------------------------------------------*/
+
+EXECMODE =
+FILESRM =
+
+ifeq ($(words $(PLATFORM)),1)
+ EXECMODE = exec_target
+endif
+
+ifneq ($(filter cleanall,$(MAKECMDGOALS)),)
+ EXECMODE = exec_clean
+ FILESRM = $(TARGET)
+ MAKECMDGOALS := $(patsubst cleanall,clean,$(MAKECMDGOALS))
+endif
+
+ifneq ($(filter clean,$(MAKECMDGOALS)),)
+ EXECMODE = exec_clean
+ FILESRM += $(OBJS)
+ ifneq "$(PLATFORM)" "linux"
+ FILESRM := $(subst /,\,$(FILESRM))
+ endif
+endif
+
+ifneq ($(filter all,$(MAKECMDGOALS)),)
+ EXECMODE = exec_alltarget
+endif
+
+ifneq ($(words $(PLATFORM)),1)
+ EXECMODE = exec_error_platform
+endif
+
+#/*-----------------------------------------------------------*/
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .h .hpp .mac .asm .o .rc .res
+
+.PHONY: all clean cleanall release \
+ linux win32_mingw win32gui_mingw win64gui_mingw \
+ exec_alltarget exec_clean exec_error_platform exec_pre_alltarget exec_target
+
+#/*-----------------------------------------------------------*/
+
+linux win32_mingw win32gui_mingw win64gui_mingw all clean cleanall release: $(EXECMODE)
+ @echo -n
+
+#/*-------------------------------------------*/
+
+exec_error_platform:
+ @echo Only one platform must be specified.
+ @exit 1
+
+exec_clean:
+ $(RM) $(FILESRM)
+
+exec_target: $(TARGET)
+ @echo -n
+
+exec_alltarget: exec_pre_alltarget $(TARGET)
+ @echo -n
+
+exec_pre_alltarget:
+ $(RM) $(OBJS) $(TARGET)
+
+#/*-------------------------------------------*/
+
+$(TARGET): $(OBJS)
+ $(LD) $(OBJS) $(LDFLAGS) -o $@
+
+.c.o:
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.cpp.o:
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+.asm.o:
+ $(AS) $(ASFLAGS) $@ $<
+
+.rc.res:
+ $(WINDRES) $(RCFLAGS) -i $< -o $@ -I $(
+#include
+#include
+#include "hsp3config.h"
+#include "stack.h"
+#include "supio.h"
+
+/*------------------------------------------------------------*/
+/*
+ system data
+*/
+/*------------------------------------------------------------*/
+
+int stm_max;
+STMDATA *mem_stm;
+STMDATA *stm_cur;
+STMDATA *stm_maxptr;
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+void StackInit( void )
+{
+ int i;
+ STMDATA *stm;
+
+ stm_max = STM_MAX_DEFAULT;
+ mem_stm = (STMDATA *)malloc( sizeof( STMDATA ) * stm_max );
+ stm_maxptr = mem_stm + stm_max;
+ stm_cur = mem_stm;
+ stm = mem_stm;
+ for(i=0;itype = HSPVAR_FLAG_INT;
+ stm->mode = STMMODE_SELF;
+ stm->ptr = (char *)&(stm->ival);
+ stm++;
+ }
+}
+
+void StackTerm( void )
+{
+ StackReset();
+ free( mem_stm );
+}
+
+
+static inline void StackAlloc( STMDATA *stm, int size )
+{
+ if ( size <= STM_STRSIZE_DEFAULT ) {
+// stm->mode = STMMODE_SELF;
+// stm->ptr = (char *)&(stm->ival);
+ return;
+ }
+ stm->mode = STMMODE_ALLOC;
+ stm->ptr = (char *)malloc( size );
+}
+
+void StackReset( void )
+{
+ while(1) {
+ if ( stm_cur == mem_stm ) break;
+ StackPop();
+ }
+}
+
+void StackPush( int type, char *data, int size )
+{
+ STMDATA *stm;
+ double *dptr;
+ if ( stm_cur >= stm_maxptr ) throw HSPERR_STACK_OVERFLOW;
+ stm = stm_cur;
+ stm->type = type;
+ switch( type ) {
+ case HSPVAR_FLAG_LABEL:
+ case HSPVAR_FLAG_INT:
+// stm->mode = STMMODE_SELF;
+ stm->ival = *(int *)data;
+// stm->ptr = (char *)&(stm->ival);
+ stm_cur++;
+ return;
+ case HSPVAR_FLAG_DOUBLE:
+ //dptr = (double *)&stm->ival;
+ //*dptr = *(double *)data;
+ memcpy(&stm->ival, data, sizeof(double));
+// stm->mode = STMMODE_SELF;
+// stm->ptr = (char *)dptr;
+ stm_cur++;
+ return;
+ default:
+ break;
+ }
+ StackAlloc( stm, size );
+ memcpy( stm->ptr, data, size );
+ stm_cur++;
+}
+
+void StackPush( int type, char *str )
+{
+ StackPush( type, str, (int)STRLEN(str)+1 );
+}
+
+void *StackPushSize( int type, int size )
+{
+ STMDATA *stm;
+ if ( stm_cur >= stm_maxptr ) throw HSPERR_STACK_OVERFLOW;
+ stm = stm_cur;
+ stm->type = type;
+ StackAlloc( stm, size );
+ stm_cur++;
+ return (void *)stm->ptr;
+}
+
+void StackPushStr( char *str )
+{
+ StackPush( HSPVAR_FLAG_STR, str, (int)strlen(str)+1 );
+}
+
+void StackPushTypeVal( int type, int val, int val2 )
+{
+ STMDATA *stm;
+ int *iptr;
+// if ( stm_cur >= stm_maxptr ) throw HSPERR_STACK_OVERFLOW;
+ stm = stm_cur;
+ stm->type = type;
+// stm->mode = STMMODE_SELF;
+ stm->ival = val;
+ iptr = (int *)stm->itemp;
+ *iptr = val2;
+ stm_cur++;
+}
+
+void StackPushVar( void *pval, int aptr )
+{
+ STMDATA *stm;
+ // if ( stm_cur >= stm_maxptr ) throw HSPERR_STACK_OVERFLOW;
+ stm = stm_cur;
+ stm->type = -1; // HSPVAR_FLAG_VAR
+ // stm->mode = STMMODE_SELF;
+ stm->pval = pval;
+ stm->ival = aptr;
+ stm_cur++;
+}
+
+void StackPushType( int type )
+{
+ StackPushTypeVal( type, 0, 0 );
+}
+
+void StackPopFree( void )
+{
+ free( stm_cur->ptr );
+ stm_cur->mode = STMMODE_SELF;
+ stm_cur->ptr = (char *)&(stm_cur->ival);
+}
diff --git a/src/hsp3/stack.h b/src/hsp3/stack.h
new file mode 100644
index 0000000000000000000000000000000000000000..4051694ccbc65f75b8159bd36e8f93e28ba9bee7
--- /dev/null
+++ b/src/hsp3/stack.h
@@ -0,0 +1,96 @@
+
+//
+// stack.cpp header
+//
+#ifndef __stack_h
+#define __stack_h
+
+#include "hsp3config.h"
+
+#define STM_MAX_DEFAULT 512
+#define STM_STRSIZE_DEFAULT 64
+
+#define STMMODE_SELF 0
+#define STMMODE_ALLOC 1
+
+#include "hspvar_core.h"
+#include "hsp3debug.h"
+
+// STMDATA structure
+//
+typedef struct
+{
+ // Memory Data structure
+ //
+ short type;
+ short mode;
+ char *ptr;
+ void *pval;
+ int ival HSP_ALIGN_DOUBLE;
+ char itemp[STM_STRSIZE_DEFAULT-4]; // data area padding
+} STMDATA;
+
+void StackInit( void );
+void StackTerm( void );
+void StackReset( void );
+void StackPush( int type, char *data, int size );
+void StackPush( int type, char *str );
+void *StackPushSize( int type, int size );
+void StackPushi( int val );
+void StackPushStr( char *str );
+void StackPushType( int type );
+void StackPushTypeVal( int type, int val, int val2 );
+void StackPushVar( void *pval, int aptr );
+void StackPop( void );
+void StackPopFree( void );
+
+extern int stm_max;
+extern STMDATA *mem_stm;
+extern STMDATA *stm_cur;
+extern STMDATA *stm_maxptr;
+
+#define STM_GETPTR( pp ) ( pp->ptr )
+
+#define StackPeek (stm_cur-1)
+#define StackPeek2 (stm_cur-2)
+#define PeekPtr ((void *)(stm_cur-1)->ptr)
+
+#define StackGetLevel (stm_cur-mem_stm)
+#define StackDecLevel stm_cur--
+
+inline void StackPushi( int val )
+{
+// if ( stm_cur >= stm_maxptr ) throw HSPERR_STACK_OVERFLOW;
+ stm_cur->type = HSPVAR_FLAG_INT;
+ stm_cur->ival = val;
+ stm_cur++;
+}
+
+inline void StackPushl( int val )
+{
+// if ( stm_cur >= stm_maxptr ) throw HSPERR_STACK_OVERFLOW;
+ stm_cur->type = HSPVAR_FLAG_LABEL;
+ stm_cur->ival = val;
+ stm_cur++;
+}
+
+inline void StackPushd( double val )
+{
+ double *dptr;
+// if ( stm_cur >= stm_maxptr ) throw HSPERR_STACK_OVERFLOW;
+ stm_cur->type = HSPVAR_FLAG_DOUBLE;
+ dptr = (double *)&stm_cur->ival;
+ *dptr = val;
+ stm_cur++;
+}
+
+inline void StackPop( void )
+{
+// if ( stm_cur <= mem_stm ) throw HSPERR_UNKNOWN_CODE;
+ stm_cur--;
+ if ( stm_cur->mode ) {
+ StackPopFree();
+ }
+}
+
+#endif
diff --git a/src/hsp3/strbuf.cpp b/src/hsp3/strbuf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f744370d6e1f98111f788f93df31b2e8b48983cb
--- /dev/null
+++ b/src/hsp3/strbuf.cpp
@@ -0,0 +1,317 @@
+
+//
+// HSP3 string support
+// (おおらかなメモリ管理をするバッファマネージャー)
+// (sbAllocでSTRBUF_BLOCKSIZEのバッファを確保します)
+// (あとはsbCopy,sbAddで自動的にバッファの再確保を行ないます)
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+#include "supio.h"
+#include "strbuf.h"
+
+#include "hsp3debug.h"
+
+#define REALLOC realloc
+#define MALLOC malloc
+#define FREE free
+
+/*------------------------------------------------------------*/
+/*
+ system data
+*/
+/*------------------------------------------------------------*/
+
+typedef struct {
+ STRBUF *mem;
+ int len;
+} SLOT;
+
+static SLOT *mem_sb;
+static int str_blockcur;
+static int slot_len;
+
+static STRBUF *freelist;
+
+// STRINF_FLAG_NONE のとき STRINF::extptr を free list の次のポインタに使う
+#define STRINF_NEXT(inf) ((inf).extptr)
+#define STRBUF_NEXT(buf) STRINF_NEXT((buf)->inf)
+
+#define GET_INTINF(buf) (&((buf)->inf.intptr->inf))
+
+/*------------------------------------------------------------*/
+/*
+ internal function
+*/
+/*------------------------------------------------------------*/
+
+static void BlockPtrPrepare( void )
+{
+ STRBUF *sb;
+
+ if ( str_blockcur == 0 ) {
+ mem_sb = (SLOT *)MALLOC( sizeof(SLOT) );
+ } else {
+ mem_sb = (SLOT *)REALLOC( mem_sb, sizeof(SLOT) * ( str_blockcur + 1 ) );
+ }
+
+ sb = (STRBUF *)MALLOC( sizeof(STRBUF) * slot_len );
+ if ( sb == NULL ) throw HSPERR_OUT_OF_MEMORY;
+ STRBUF *p = sb;
+ STRBUF *pend = p + slot_len;
+ mem_sb[ str_blockcur ].mem = sb;
+ mem_sb[ str_blockcur ].len = slot_len;
+ str_blockcur++;
+ slot_len = (int)(slot_len * 1.8);
+
+ while ( p < pend ) {
+ p->inf.intptr = p;
+ p->inf.flag = STRINF_FLAG_NONE;
+ STRBUF_NEXT(p) = freelist;
+ freelist = p;
+ p ++;
+ }
+}
+
+
+static STRBUF *BlockEntry( void )
+{
+ // 空きエントリーブロックを探す
+ //
+ if ( freelist == NULL ) {
+ BlockPtrPrepare();
+ }
+ STRBUF *buf = freelist;
+ freelist = STRBUF_NEXT(freelist);
+ return buf;
+}
+
+static char *BlockAlloc( int size )
+{
+ int *p;
+ STRBUF *st;
+ STRBUF *st2;
+ STRINF *inf;
+ st = BlockEntry();
+ inf = &(st->inf);
+ if ( size <= STRBUF_BLOCKSIZE ) {
+ inf->flag = STRINF_FLAG_USEINT;
+ inf->size = STRBUF_BLOCKSIZE;
+ p = (int *)st->data;
+ inf->ptr = (char *)p;
+ } else {
+ inf->flag = STRINF_FLAG_USEEXT;
+ inf->size = size;
+ st2 = (STRBUF *)MALLOC( size + sizeof(STRINF) );
+ p = (int *)(st2->data);
+ inf->extptr = st2;
+ inf->ptr = (char *)p;
+ st2->inf = *inf;
+ }
+ *p = 0;
+ //return inf->ptr;
+ return (char *)p;
+}
+
+static void FreeExtPtr( STRINF *inf )
+{
+ if ( inf->flag == STRINF_FLAG_USEEXT ) {
+ FREE( inf->extptr );
+ }
+}
+
+static void BlockFree( STRINF *inf )
+{
+ FreeExtPtr( inf );
+ STRINF_NEXT(*inf) = freelist;
+ freelist = (STRBUF *)inf;
+ inf->flag = STRINF_FLAG_NONE;
+}
+
+static char *BlockRealloc( STRBUF *st, int size )
+{
+ char *p;
+ STRINF *inf;
+ STRBUF *newst;
+ inf = GET_INTINF(st);
+ if ( size <= inf->size ) return inf->ptr;
+
+ newst = (STRBUF *)MALLOC( size + sizeof(STRINF) );
+ p = newst->data;
+ memcpy( p, inf->ptr, inf->size );
+ FreeExtPtr( inf );
+ inf->size = size;
+ inf->flag = STRINF_FLAG_USEEXT;
+ inf->ptr = p;
+ inf->extptr = newst;
+
+ newst->inf = *inf;
+ return p;
+}
+
+void BlockInfo( STRINF *inf )
+{
+ STRBUF *newst;
+ if ( inf->flag == STRINF_FLAG_USEEXT ) {
+ newst = (STRBUF *)inf->extptr;
+ }
+}
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+void sbInit( void )
+{
+ str_blockcur = 0;
+ freelist = NULL;
+ slot_len = STRBUF_BLOCK_DEFAULT;
+ BlockPtrPrepare();
+}
+
+
+void sbBye( void )
+{
+ int i;
+ for( i=0; iinf );
+ p ++;
+ }
+ FREE( mem );
+ }
+ FREE( mem_sb );
+}
+
+
+STRINF *sbGetSTRINF( char *ptr )
+{
+ return (STRINF *)( ptr - sizeof(STRINF) );
+}
+
+
+char *sbAlloc( int size )
+{
+ int sz;
+ sz = size; if ( size < STRBUF_BLOCKSIZE ) sz = STRBUF_BLOCKSIZE;
+ return BlockAlloc( sz );
+}
+
+
+char *sbAllocClear( int size )
+{
+ char *p;
+ p = sbAlloc( size );
+ memset( p, 0, size );
+ return p;
+}
+
+
+void sbFree( void *ptr )
+{
+ char *p;
+ STRBUF *st;
+ STRINF *inf;
+ p = (char *)ptr;
+ st = (STRBUF *)( p - sizeof(STRINF) );
+ inf = GET_INTINF(st);
+ if ( p != (inf->ptr) ) return;
+ BlockFree( inf );
+}
+
+
+char *sbExpand( char *ptr, int size )
+{
+ STRBUF *st;
+ st = (STRBUF *)( ptr - sizeof(STRINF) );
+ return BlockRealloc( st, size );
+}
+
+
+void sbCopy( char **pptr, char *data, int size )
+{
+ int sz;
+ char *ptr;
+ char *p;
+ STRBUF *st;
+ ptr = *pptr;
+ st = (STRBUF *)( ptr - sizeof(STRINF) );
+ sz = st->inf.size;
+ p = st->inf.ptr;
+ if ( size > sz ) { p = BlockRealloc( st, size ); *pptr = p; }
+ memcpy( p, data, size );
+}
+
+
+void sbAdd( char **pptr, char *data, int size, int mode )
+{
+ // mode:0=normal/1=string
+ int sz,newsize;
+ STRBUF *st;
+ char *ptr;
+ char *p;
+ ptr = *pptr;
+ st = (STRBUF *)( ptr - sizeof(STRINF) );
+ p = st->inf.ptr;
+ if ( mode ) {
+ sz = (int)strlen( p ); // 文字列データ
+ } else {
+ sz = st->inf.size; // 通常データ
+ }
+ newsize = sz + size;
+ if ( newsize > (st->inf.size) ) {
+ newsize = ( newsize + 0xfff ) & 0xfffff000; // 8K単位で確保
+ //Alertf( "#Alloc%d",newsize );
+ p = BlockRealloc( st, newsize );
+ *pptr = p;
+ }
+ memcpy( p+sz, data, size );
+}
+
+
+void sbStrCopy( char **ptr, char *str )
+{
+ sbCopy( ptr, str, (int)strlen(str)+1 );
+}
+
+
+void sbStrAdd( char **ptr, char *str )
+{
+ sbAdd( ptr, str, (int)strlen(str)+1, 1 );
+}
+
+
+void *sbGetOption( char *ptr )
+{
+ STRBUF *st;
+ st = (STRBUF *)( ptr - sizeof(STRINF) );
+ return st->inf.opt;
+}
+
+
+void sbSetOption( char *ptr, void *option )
+{
+ STRBUF *st;
+ STRINF *inf;
+ st = (STRBUF *)( ptr - sizeof(STRINF) );
+ st->inf.opt = option;
+ inf = GET_INTINF(st);
+ inf->opt = option;
+}
+
+/*
+void sbInfo( char *ptr )
+{
+ STRBUF *st;
+ st = (STRBUF *)( ptr - sizeof(STRINF) );
+ Alertf( "size:%d (%x)",st->inf.size, st->inf.ptr );
+}
+*/
+
diff --git a/src/hsp3/strbuf.h b/src/hsp3/strbuf.h
new file mode 100644
index 0000000000000000000000000000000000000000..e31f353e2bc6ccd2e5c924ce389f32b6f0441f25
--- /dev/null
+++ b/src/hsp3/strbuf.h
@@ -0,0 +1,63 @@
+
+//
+// strbuf.cpp header
+//
+#ifndef __strbuf_h
+#define __strbuf_h
+
+#include "hsp3config.h"
+
+#define STRBUF_BLOCKSIZE 64
+#define STRBUF_BLOCK_DEFAULT 0x400
+#define STRBUF_SEGMENT_DEFAULT 0x1000
+
+#define STRINF_FLAG_NONE 0
+#define STRINF_FLAG_USEINT 1
+#define STRINF_FLAG_USEEXT 2
+
+
+// STRBUF structure
+//
+
+typedef struct STRBUF STRBUF;
+
+typedef struct
+{
+ // String Data structure
+ //
+ short flag; // 使用フラグ(0=none/other=busy)
+ short exflag; // 拡張フラグ(未使用)
+ STRBUF *intptr; // 自身のアドレス
+ int size; // 確保サイズ
+ char *ptr; // バッファポインタ
+ STRBUF *extptr; // 外部バッファポインタ(STRINF)
+ void *opt; // オプション(ユーザー定義用)
+} STRINF;
+
+struct STRBUF
+{
+ // String Data structure
+ //
+ STRINF inf; // バッファ情報
+ char data[STRBUF_BLOCKSIZE] HSP_ALIGN_DOUBLE; // 内部バッファ
+};
+
+void sbInit( void );
+void sbBye( void );
+
+char *sbAlloc( int size );
+char *sbAllocClear( int size );
+void sbFree( void *ptr );
+char *sbExpand( char *ptr, int size );
+STRINF *sbGetSTRINF( char *ptr );
+
+void sbCopy( char **ptr, char *data, int size );
+void sbStrCopy( char **ptr, char *str );
+void sbAdd( char **ptr, char *data, int size, int offset );
+void sbStrAdd( char **ptr, char *str );
+
+void *sbGetOption( char *ptr );
+void sbSetOption( char *ptr, void *option );
+void sbInfo( char *ptr );
+
+#endif
diff --git a/src/hsp3/strnote.cpp b/src/hsp3/strnote.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9dbc6307fee924ae413bf1d3d65079e5e37c0955
--- /dev/null
+++ b/src/hsp3/strnote.cpp
@@ -0,0 +1,345 @@
+
+/*----------------------------------------------------------------*/
+// notepad object related routines
+// (CR/LFだけでなくLFにも対応した版)
+/*----------------------------------------------------------------*/
+
+#include
+#include "hsp3config.h"
+#include "strnote.h"
+#include "supio.h"
+
+#if defined(HSPLINUX) || defined(HSPMAC) || defined(HSPIOS) || defined(HSPNDK) || defined(HSPEMSCRIPTEN)
+// LFを改行として扱う
+#define MATCH_LF
+#define CRSTR "\n"
+#else
+// CR/LFを改行として扱う
+#define CRSTR "\r\n"
+#endif
+
+//-------------------------------------------------------------
+// Interfaces
+//-------------------------------------------------------------
+
+CStrNote::CStrNote()
+{
+ base = NULL;
+ nulltmp[0] = 0;
+}
+
+
+CStrNote::~CStrNote()
+{
+}
+
+
+void CStrNote::Select( char *str )
+{
+ base = str;
+}
+
+
+int CStrNote::GetSize( void )
+{
+ return (int)strlen( base );
+}
+
+
+//-------------------------------------------------------------
+// Routines
+//-------------------------------------------------------------
+
+int CStrNote::nnget( char *nbase, int line )
+{
+ // 指定した行の先頭ポインタを求める
+ // nn = 先頭ポインタ
+ // lastcr : CR/LFで終了している
+ // line : line number(-1=最終行)
+ // result:0=ok/1=no line
+ //
+ int a,i;
+ char a1;
+ a=0;
+ lastcr=0;
+ nn=nbase;
+ if (line<0) {
+ i=(int)strlen(nbase);if (i==0) return 0;
+ nn+=i;a1=*(nn-1);
+ if ((a1==10)||(a1==13)) lastcr++;
+ return 0;
+ }
+ if (line) {
+ while(1) {
+ a1=*nn;if (a1==0) return 1;
+ nn++;
+#ifdef MATCH_LF
+ if (a1==10) {
+ a++;if (a==line) break;
+ }
+#endif
+ if (a1==13) {
+ if (*nn==10) nn++;
+ a++;if (a==line) break;
+ }
+ }
+ }
+ lastcr++;
+ return 0;
+}
+
+
+int CStrNote::GetLine( char *nres, int line )
+{
+ // Get specified line from note
+ // result:0=ok/1=no line
+ //
+ char a1;
+ char *pp;
+ pp=nres;
+ if ( nnget( base,line ) ) return 1;
+ if (*nn==0) return 1;
+ while(1) {
+ a1=*nn++;
+ if ((a1==0)||(a1==13)) break;
+#ifdef MATCH_LF
+ if (a1==10) break;
+#endif
+ *pp++=a1;
+ }
+ *pp=0;
+ return 0;
+}
+
+
+int CStrNote::GetLine( char *nres, int line, int max )
+{
+ // Get specified line from note
+ // result:0=ok/1=no line
+ //
+ char a1;
+ char *pp;
+ int cnt;
+ pp=nres;
+ cnt = 0;
+ if ( nnget( base,line ) ) return 1;
+ if (*nn==0) return 1;
+ while(1) {
+ if ( cnt>=max ) break;
+ a1=*nn++;
+ if ((a1==0)||(a1==13)) break;
+#ifdef MATCH_LF
+ if (a1==10) break;
+#endif
+ *pp++=a1;
+ cnt++;
+ }
+ *pp=0;
+ return 0;
+}
+
+
+char *CStrNote::GetLineDirect( int line )
+{
+ // Get specified line from note
+ //
+ char a1;
+ if ( nnget( base,line ) ) nn = nulltmp;
+ lastnn = nn;
+ while(1) {
+ a1=*lastnn;
+ if ((a1==0)||(a1==13)) break;
+#ifdef MATCH_LF
+ if (a1==10) break;
+#endif
+ lastnn++;
+ }
+ lastcode = a1;
+ *lastnn = 0;
+ return nn;
+}
+
+
+void CStrNote::ResumeLineDirect( void )
+{
+ // Resume last GetLineDirect function
+ //
+ *lastnn = lastcode;
+}
+
+
+int CStrNote::GetMaxLine( void )
+{
+ // Get total lines
+ //
+ int a,b;
+ char a1;
+ a=1;b=0;
+ nn=base;
+ while(1) {
+ a1=*nn++;if (a1==0) break;
+#ifdef MATCH_LF
+ if ((a1==13)||(a1==10)) {
+ if (a1=13&&*nn==10) nn++;
+#else
+ if (a1==13) {
+ if (*nn==10) nn++;
+#endif
+ a++;b=0;
+ }
+ else b++;
+ }
+ if (b==0) a--;
+ return a;
+}
+
+
+int CStrNote::PutLine( char *nstr2, int line, int ovr )
+{
+ // Pet specified line to note
+ // result:0=ok/1=no line
+ //
+ int a = 0,ln,la,lw;
+ char a1;
+ char *pp;
+ char *p1;
+ char *p2;
+ char *nstr;
+ if ( nnget( base,line ) ) return 1;
+ if (lastcr==0) {
+ if ( nn != base ) {
+ strcat( base, CRSTR );nn+=2;
+ }
+ }
+ nstr = nstr2;
+ if ( nstr == NULL ) { nstr=""; }
+
+ pp=nstr;
+ if ( nstr2 != NULL ) strcat(nstr, CRSTR );
+ ln=(int)strlen(nstr); // base new str + cr/lf
+ la=(int)strlen(base);
+ lw=la-(int)(nn-base)+1;
+ //
+ if (ovr) { // when overwrite mode
+ p1=nn;a=0;
+ while(1) {
+ a1=*p1++;if (a1==0) break;
+ a++;
+#ifdef MATCH_LF
+ if ((a1==13)||(a1==10)) {
+ if (a1=13&&*p1==10) { p1++;a++; }
+#else
+ if (a1==13) {
+ if (*p1==10) { p1++;a++; }
+#endif
+ break;
+ }
+ }
+ ln=ln-a;
+ lw=lw-a;if (lw<1) lw=1;
+ }
+ //
+ if (ln>=0) {
+ p1=base+la+ln; p2=base+la;
+ for(a=0;a
+#include
+#include
+#include
+
+#if defined( _MSC_VER )
+#pragma comment(lib, "comctl32.lib")
+#endif
+
+#include
+#include
+
+#include "hsp3gr_win.h"
+
+#include "../hsp3config.h"
+
+#include "../strbuf.h"
+#include "../hsp3.h"
+#include "../hsp3gr.h"
+#include "../supio.h"
+
+#include "../win32gui/hsp3ext_win.h"
+#include "../win32gui/hsp3extlib.h"
+#include "../win32gui/hspvar_comobj.h"
+#include "../win32gui/hspvar_variant.h"
+
+typedef BOOL (CALLBACK *HSP3DBGFUNC)(HSP3DEBUG *,int,int,int);
+
+/*----------------------------------------------------------*/
+
+static Hsp3 *hsp;
+static HSPCTX *ctx;
+
+static char fpas[]={ 'H'-48,'S'-48,'P'-48,'H'-48,
+ 'E'-48,'D'-48,'~'-48,'~'-48 };
+static char optmes[] = "HSPHED~~\0_1_________2_________3______";
+
+static int hsp_wd;
+
+#ifdef HSPDEBUG
+static HSP3DBGFUNC dbgwin;
+static HSP3DBGFUNC dbgnotice;
+static HINSTANCE h_dbgwin;
+static HWND dbgwnd;
+static HSP3DEBUG *dbginfo;
+#endif
+
+/*----------------------------------------------------------*/
+
+void hsp3win_dialog( char *mes )
+{
+ printf( "%s\n", mes );
+}
+
+
+#ifdef HSPCL_WIN
+#ifdef HSPDEBUG
+
+char *hsp3win_debug( int type )
+{
+ // デバッグ情報取得
+ //
+ char *p;
+ p = code_inidbg();
+
+ switch( type ) {
+ case DEBUGINFO_GENERAL:
+ hsp3gr_dbg_gui();
+ code_dbg_global();
+ break;
+ case DEBUGINFO_VARNAME:
+ break;
+ case DEBUGINFO_INTINFO:
+ break;
+ case DEBUGINFO_GRINFO:
+ break;
+ case DEBUGINFO_MMINFO:
+ break;
+ }
+ return p;
+}
+
+#endif
+#endif
+
+
+int hsp3win_debugopen( void )
+{
+ // デバッグウインドゥ表示
+ //
+#ifdef HSPDEBUG
+ if ( h_dbgwin != NULL ) return 0;
+ h_dbgwin = LoadLibrary( "hsp3debug.dll" );
+ if ( h_dbgwin != NULL ) {
+ dbgwin = (HSP3DBGFUNC)GetProcAddress( h_dbgwin, "_debugini@16" );
+ dbgnotice = (HSP3DBGFUNC)GetProcAddress( h_dbgwin, "_debug_notice@16" );
+ if (( dbgwin == NULL )||( dbgnotice == NULL )) h_dbgwin = NULL;
+ }
+ if ( h_dbgwin == NULL ) {
+ hsp3win_dialog( "No debug module." );
+ return -1;
+ }
+ dbginfo->get_value = hsp3win_debug;
+ dbgwin( dbginfo, 0, 0, 0 );
+ dbgwnd = (HWND)( dbginfo->dbgwin );
+#endif
+ return 0;
+}
+
+
+#ifdef HSPCL_WIN
+static void hsp3win_dispatch( MSG *msg )
+{
+ TranslateMessage( msg );
+ DispatchMessage( msg );
+}
+
+static void hsp3cl_stop( HSPCTX *hspctx )
+{
+ MSG msg;
+
+#ifdef HSPDEBUG
+ if ( h_dbgwin != NULL ) dbgnotice( dbginfo, 0, 0, 0 ); // Debug Window Notice
+#endif
+ while(1) {
+ GetMessage( &msg, NULL, 0, 0 );
+ if ( msg.message == WM_QUIT ) throw HSPERR_NONE;
+ hsp3win_dispatch( &msg );
+ if ( hspctx->runmode != RUNMODE_STOP ) break;
+ }
+}
+#endif
+
+
+void hsp3cl_msgfunc( HSPCTX *hspctx )
+{
+ while(1) {
+
+#ifdef HSPCL_WIN
+ MSG msg;
+ int tick;
+ if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
+ if (msg.message == WM_QUIT ) throw HSPERR_NONE;
+ hsp3win_dispatch( &msg );
+ continue;
+ }
+#endif
+
+ switch( hspctx->runmode ) {
+ case RUNMODE_STOP:
+#ifdef HSPDEBUG
+#ifdef HSPCL_WIN
+ if ( h_dbgwin != NULL ) {
+ hsp3cl_stop( hspctx );
+ break;
+ } else {
+ hsp3win_dialog( "[STOP] Press any key..." );
+ _getch();
+ }
+#else
+ hsp3win_dialog( "[STOP] Press any key..." );
+ _getch();
+#endif
+#endif
+ throw HSPERR_NONE;
+ case RUNMODE_WAIT:
+#ifdef HSPCL_WIN
+ tick = GetTickCount();
+ hspctx->runmode = code_exec_wait( tick );
+#endif
+ case RUNMODE_AWAIT:
+#ifdef HSPCL_WIN
+ tick = GetTickCount();
+ if ( code_exec_await( tick ) != RUNMODE_RUN ) {
+ MsgWaitForMultipleObjects(0, NULL, FALSE, hspctx->waittick - tick, QS_ALLINPUT );
+ }
+#endif
+ break;
+ case RUNMODE_END:
+#if 0
+ if ( h_dbgwin != NULL ) {
+ hsp3cl_stop( hspctx );
+ } else {
+ hsp3win_dialog( "[END] Press any key..." );
+ _getch();
+ }
+#endif
+ throw HSPERR_NONE;
+ case RUNMODE_RETURN:
+ throw HSPERR_RETURN_WITHOUT_GOSUB;
+
+
+#ifdef HSPCL_WIN
+ case RUNMODE_ASSERT:
+ hspctx->runmode = RUNMODE_STOP;
+#ifdef HSPDEBUG
+ hsp3win_debugopen();
+#endif
+ break;
+ case RUNMODE_LOGMES:
+ hspctx->runmode = RUNMODE_RUN;
+#ifdef HSPDEBUG
+ if ( h_dbgwin != NULL ) dbgnotice( dbginfo, 1, 0, 0 ); // Debug Window Notice
+#endif
+ return;
+#endif
+
+ default:
+ return;
+ }
+ }
+}
+
+
+int hsp3cl_init( char *startfile )
+{
+ // システム関連の初期化
+ // ( mode:0=debug/1=release )
+ //
+ int a,orgexe, mode;
+ int hsp_sum, hsp_dec;
+ char a1;
+ char *ss;
+#ifdef HSPDEBUG
+ char fname[_MAX_PATH+1];
+ int i;
+#endif
+
+#ifdef HSPCL_WIN
+#ifndef HSP_COM_UNSUPPORTED
+ if ( FAILED( CoInitializeEx( NULL, COINIT_APARTMENTTHREADED) ) ) {
+ return -1;
+ }
+ OleInitialize( NULL );
+#endif
+ InitCommonControls();
+#endif
+
+ // HSP関連の初期化
+ //
+ hsp = new Hsp3();
+#ifdef HSPCL_WIN
+ hsp->hspctx.instance = (HINSTANCE)GetModuleHandle(NULL);
+#endif
+
+#ifdef HSPDEBUG
+ h_dbgwin = NULL;
+ dbgwnd = NULL;
+
+ ss = strsp_cmds( startfile );
+ i = (int)( ss - startfile );
+ ss = startfile;
+ if ( ss[i-1] == 32 ) i--;
+ if ( *ss == 0x22 ) {
+ ss++;i-=2;
+ }
+ strncpy( fname, ss, i );
+ fname[i] = 0;
+ hsp->SetFileName( fname );
+
+ if ( i == 0 ) {
+ printf( "OpenHSP CL ver%s / onion software 1997-2009\n", hspver );
+ return -1;
+ }
+#else
+ if ( startfile != NULL ) {
+ hsp->SetFileName( startfile );
+ }
+#endif
+
+ // 実行ファイルかデバッグ中かを調べる
+ //
+ mode = 0;
+ orgexe = 0;
+ hsp_wd = 0;
+ for( a=0 ; a<8; a++) {
+ a1=optmes[a]-48;if (a1==fpas[a]) orgexe++;
+ }
+ if ( orgexe == 0 ) {
+ mode = atoi(optmes+9) + 0x10000;
+ hsp_wd=( *(short *)(optmes+26) );
+ hsp_sum=*(unsigned short *)(optmes+29);
+ hsp_dec=*(int *)(optmes+32);
+ hsp->SetPackValue( hsp_sum, hsp_dec );
+ }
+
+ // 起動ファイルのディレクトリをカレントにする
+ //
+#ifndef HSPDEBUG
+ if (( hsp_wd & 2 ) == 0 ) {
+ char fname[_MAX_PATH+1];
+ GetModuleFileName( NULL, fname, _MAX_PATH );
+ getpath( fname, fname, 32 );
+ changedir( fname );
+ }
+#endif
+
+ if ( hsp->Reset( mode ) ) {
+ hsp3win_dialog( "Startup failed." );
+ return -1;
+ }
+
+ ctx = &hsp->hspctx;
+
+ {
+ // コマンドライン関連
+ ss = GetCommandLine();
+ ss = strsp_cmds( ss );
+#ifdef HSPDEBUG
+ ss = strsp_cmds( ss );
+#endif
+ sbStrCopy( &ctx->cmdline, ss ); // コマンドラインパラメーターを保存
+ }
+
+ // Register Type
+ //
+ ctx->msgfunc = hsp3cl_msgfunc;
+ ctx->hspstat |= 16;
+
+#ifdef HSPCL_WIN
+#ifndef HSP_COM_UNSUPPORTED
+ HspVarCoreRegisterType( TYPE_COMOBJ, HspVarComobj_Init );
+ HspVarCoreRegisterType( TYPE_VARIANT, HspVarVariant_Init );
+#endif
+ hsp3typeinit_dllcmd( code_gettypeinfo( TYPE_DLLFUNC ) );
+ hsp3typeinit_dllctrl( code_gettypeinfo( TYPE_DLLCTRL ) );
+#endif
+ hsp3typeinit_cl_extcmd( code_gettypeinfo( TYPE_EXTCMD ) );
+ hsp3typeinit_cl_extfunc( code_gettypeinfo( TYPE_EXTSYSVAR ) );
+
+#ifdef HSPCL_WIN
+#ifdef HSPDEBUG
+ dbginfo = code_getdbg();
+#endif
+#endif
+ return 0;
+}
+
+
+static void hsp3cl_bye( void )
+{
+ // HSP関連の解放
+ //
+ delete hsp;
+
+ DllManager().free_all_library();
+
+ // システム関連の解放
+ //
+#ifdef HSPCL_WIN
+#ifndef HSP_COM_UNSUPPORTED
+ OleUninitialize();
+ CoUninitialize();
+#endif
+#endif
+}
+
+
+void hsp3cl_error( void )
+{
+ char errmsg[1024];
+ char *msg;
+ char *fname;
+ HSPERROR err;
+ int ln;
+ err = code_geterror();
+ ln = code_getdebug_line();
+ msg = hspd_geterror(err);
+ fname = code_getdebug_name();
+
+ if ( ln < 0 ) {
+ sprintf( errmsg, "#Error %d\n-->%s\n",(int)err,msg );
+ fname = NULL;
+ } else {
+ sprintf( errmsg, "#Error %d in line %d (%s)\n-->%s\n",(int)err, ln, fname, msg );
+ }
+
+#ifdef HSPCL_WIN
+#ifdef HSPDEBUG
+ hsp3win_debugopen();
+ hsp3win_dialog( errmsg );
+ MessageBox( NULL, errmsg, "Error",MB_ICONEXCLAMATION | MB_OK );
+#else
+ hsp3win_dialog( errmsg );
+#endif
+#else
+ hsp3win_dialog( errmsg );
+ hsp3win_dialog( "[ERROR] Press any key..." );
+ _getch();
+#endif
+}
+
+
+int hsp3cl_exec( void )
+{
+ // 実行メインを呼び出す
+ //
+ int runmode;
+ int endcode;
+rerun:
+
+ // デバッグウインドゥ用
+ //
+#ifdef HSPDEBUG
+ if ( ctx->hsphed->bootoption & HSPHED_BOOTOPT_DEBUGWIN ) {
+ if ( hsp3win_debugopen() ) return -1;
+ }
+#endif
+
+ // 実行の開始
+ //
+ runmode = code_execcmd();
+ if ( runmode == RUNMODE_ERROR ) {
+ try {
+ hsp3cl_error();
+ }
+ catch( ... ) {
+ }
+ return -1;
+ }
+ if ( runmode == RUNMODE_EXITRUN ) {
+ char fname[_MAX_PATH];
+ char cmd[1024];
+ int res;
+ strncpy( fname, ctx->refstr, _MAX_PATH-1 );
+ strncpy( cmd, ctx->stmp, 1023 );
+
+ hsp3cl_bye();
+ res = hsp3cl_init( fname );
+ if ( res ) return res;
+
+ strncpy( ctx->cmdline, cmd, 1023 );
+ ctx->runmode = RUNMODE_RUN;
+ goto rerun;
+ }
+ endcode = ctx->endcode;
+ hsp3cl_bye();
+ return endcode;
+}
diff --git a/src/hsp3/win32/hsp3cl.h b/src/hsp3/win32/hsp3cl.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d41005eb600b98d07c98bf72c3f5ed89c0ddf3e
--- /dev/null
+++ b/src/hsp3/win32/hsp3cl.h
@@ -0,0 +1,12 @@
+
+//
+// hsp3cl.cpp header
+//
+#ifndef __hsp3cl_h
+#define __hsp3cl_h
+
+int hsp3cl_exec( void );
+int hsp3cl_init( char *startfile );
+void hsp3win_dialog( char *mes );
+
+#endif
diff --git a/src/hsp3/win32/hsp3cl.vcproj b/src/hsp3/win32/hsp3cl.vcproj
new file mode 100644
index 0000000000000000000000000000000000000000..56b63c914d48b53d92487246495cc5f150d1d6f9
--- /dev/null
+++ b/src/hsp3/win32/hsp3cl.vcproj
@@ -0,0 +1,489 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/hsp3/win32/hsp3cl_vc2008.vcproj b/src/hsp3/win32/hsp3cl_vc2008.vcproj
new file mode 100644
index 0000000000000000000000000000000000000000..22f8e542105c33ed9f406606243b73ed92415a6a
--- /dev/null
+++ b/src/hsp3/win32/hsp3cl_vc2008.vcproj
@@ -0,0 +1,487 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/hsp3/win32/hsp3gr_win.cpp b/src/hsp3/win32/hsp3gr_win.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..13a814f97dcc97c19fd729ae0dcf4141644975ce
--- /dev/null
+++ b/src/hsp3/win32/hsp3gr_win.cpp
@@ -0,0 +1,509 @@
+
+//
+// HSP3 graphics command
+// (GUI関連コマンド・関数処理)
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "../hsp3code.h"
+#include "../hsp3debug.h"
+#include "../supio.h"
+#include "../strbuf.h"
+
+#include "../win32gui/filedlg.h"
+
+#include "hsp3gr_win.h"
+
+/*------------------------------------------------------------*/
+/*
+ system data
+*/
+/*------------------------------------------------------------*/
+
+static HSPCTX *ctx;
+static int *type;
+static int *val;
+static int cur_window;
+static int p1,p2,p3,p4,p5,p6;
+static int ckey,cklast,cktrg;
+static int msact;
+static int dispflg;
+
+extern int resY0, resY1;
+
+/*----------------------------------------------------------*/
+// HSP system support
+/*----------------------------------------------------------*/
+
+void ExecFile( char *stmp, char *ps, int mode )
+{
+ int i,j;
+ j=SW_SHOWDEFAULT;if (p1&2) j=SW_SHOWMINIMIZED;
+
+ if ( *ps != 0 ) {
+ SHELLEXECUTEINFO exinfo;
+ memset( &exinfo, 0, sizeof(SHELLEXECUTEINFO) );
+ exinfo.cbSize = sizeof(SHELLEXECUTEINFO);
+ exinfo.fMask = SEE_MASK_INVOKEIDLIST;
+ exinfo.hwnd = NULL;
+ exinfo.lpVerb = ps;
+ exinfo.lpFile = stmp;
+ exinfo.nShow = SW_SHOWNORMAL;
+ if ( ShellExecuteEx( &exinfo ) == false ) throw HSPERR_EXTERNAL_EXECUTE;
+ return;
+ }
+
+ if ( mode&16 ) {
+ i = (int)((INT_PTR)ShellExecute( NULL,NULL,stmp,"","",j ));
+ }
+ else if ( mode&32 ) {
+ i = (int)((INT_PTR)ShellExecute( NULL,"print",stmp,"","",j ));
+ }
+ else {
+ i=WinExec( stmp,j );
+ }
+ if (i<32) throw HSPERR_EXTERNAL_EXECUTE;
+}
+
+
+/*
+#define CSIDL_DESKTOP 0x0000
+#define CSIDL_INTERNET 0x0001
+#define CSIDL_PROGRAMS 0x0002
+#define CSIDL_CONTROLS 0x0003
+#define CSIDL_PRINTERS 0x0004
+#define CSIDL_PERSONAL 0x0005
+#define CSIDL_FAVORITES 0x0006
+#define CSIDL_STARTUP 0x0007
+#define CSIDL_RECENT 0x0008
+#define CSIDL_SENDTO 0x0009
+#define CSIDL_BITBUCKET 0x000a
+#define CSIDL_STARTMENU 0x000b
+#define CSIDL_DESKTOPDIRECTORY 0x0010
+#define CSIDL_DRIVES 0x0011
+#define CSIDL_NETWORK 0x0012
+#define CSIDL_NETHOOD 0x0013
+#define CSIDL_FONTS 0x0014
+#define CSIDL_TEMPLATES 0x0015
+#define CSIDL_COMMON_STARTMENU 0x0016
+#define CSIDL_COMMON_PROGRAMS 0X0017
+#define CSIDL_COMMON_STARTUP 0x0018
+#define CSIDL_COMMON_DESKTOPDIRECTORY 0x0019
+#define CSIDL_APPDATA 0x001a
+#define CSIDL_PRINTHOOD 0x001b
+#define CSIDL_ALTSTARTUP 0x001d // DBCS
+#define CSIDL_COMMON_ALTSTARTUP 0x001e // DBCS
+#define CSIDL_COMMON_FAVORITES 0x001f
+#define CSIDL_INTERNET_CACHE 0x0020
+#define CSIDL_COOKIES 0x0021
+#define CSIDL_HISTORY 0x0022
+*/
+
+static char *getdir( int id )
+{
+ // dirinfo命令の内容をstmpに設定する
+ //
+ char *p;
+ char *ss;
+ char fname[_MAX_PATH+1];
+ p = ctx->stmp;
+
+ switch( id ) {
+ case 0: // カレント(現在の)ディレクトリ
+ _getcwd( p, _MAX_PATH );
+ break;
+ case 1: // HSPの実行ファイルがあるディレクトリ
+ GetModuleFileName( NULL,fname,_MAX_PATH );
+ getpath( fname, p, 32 );
+ break;
+ case 2: // Windowsディレクトリ
+ GetWindowsDirectory( p, _MAX_PATH );
+ break;
+ case 3: // Windowsのシステムディレクトリ
+ GetSystemDirectory( p, _MAX_PATH );
+ break;
+ case 4: // コマンドライン文字列
+ ss = GetCommandLine();
+ ss = strsp_cmds( ss );
+#ifdef HSPDEBUG
+ ss = strsp_cmds( ss );
+#endif
+ sbStrCopy( &(ctx->stmp), ss );
+ p = ctx->stmp;
+ return p;
+ case 5: // HSPTV素材があるディレクトリ
+#if defined(HSPDEBUG)||defined(HSP3IMP)
+ GetModuleFileName( NULL,fname,_MAX_PATH );
+ getpath( fname, p, 32 );
+ CutLastChr( p, '\\' );
+ strcat( p, "\\hsptv\\" );
+ return p;
+#else
+ *p = 0;
+ return p;
+#endif
+ break;
+ default:
+ if ( id & 0x10000 ) {
+ SHGetSpecialFolderPath( NULL, p, id & 0xffff, FALSE );
+ break;
+ }
+ throw HSPERR_ILLEGAL_FUNCTION;
+ }
+
+ // 最後の'\\'を取り除く
+ //
+ CutLastChr( p, '\\' );
+ return p;
+}
+
+
+static int sysinfo( int p2 )
+{
+ // System strings get
+ //
+ int fl;
+ char pp[128];
+ char *p1;
+ BOOL success;
+ DWORD version;
+ DWORD size;
+ DWORD *mss;
+ SYSTEM_INFO si;
+ MEMORYSTATUS ms;
+
+ fl = HSPVAR_FLAG_INT;
+ p1 = ctx->stmp;
+ size = _MAX_PATH;
+
+ if (p2&16) {
+ GetSystemInfo(&si);
+ }
+ if (p2&32) {
+ GlobalMemoryStatus(&ms);
+ mss=(DWORD *)&ms;
+ *(int *)p1 = (int)mss[p2&15];
+ return fl;
+ }
+
+ switch(p2) {
+ case 0:
+ strcpy(p1,"Windows");
+ version = GetVersion();
+ if ((version & 0x80000000) == 0) strcat(p1,"NT");
+ else strcat(p1,"9X");
+/*
+ rev 43
+ mingw : warning : 仮引数int 実引数long unsigned
+ に対処
+*/
+ sprintf( pp," ver%d.%d", static_cast< int >( version&0xff ), static_cast< int >( (version&0xff00)>>8 ) );
+ strcat( p1, pp );
+ fl=HSPVAR_FLAG_STR;
+ break;
+ case 1:
+ success = GetUserName( p1,&size );
+ fl = HSPVAR_FLAG_STR;
+ break;
+ case 2:
+ success = GetComputerName(p1, &size );
+ fl = HSPVAR_FLAG_STR;
+ break;
+ case 16:
+ *(int *)p1 = (int)si.dwProcessorType;
+ break;
+ case 17:
+ *(int *)p1 = (int)si.dwNumberOfProcessors;
+ break;
+ default:
+ throw HSPERR_ILLEGAL_FUNCTION;
+ }
+ return fl;
+}
+
+
+void *ex_getbmscr( int wid )
+{
+ return NULL;
+}
+
+void ex_mref( PVal *pval, int prm )
+{
+ int t,size;
+ void *ptr;
+ const int GETBM=0x60;
+ t = HSPVAR_FLAG_INT;
+ size = 4;
+ if ( prm >= GETBM ) {
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ } else {
+ switch( prm ) {
+ case 0x40:
+ ptr = &ctx->stat;
+ break;
+ case 0x41:
+ ptr = ctx->refstr;
+ t = HSPVAR_FLAG_STR;
+ size = 1024;
+ break;
+ case 0x44:
+ ptr = ctx; size = sizeof(HSPCTX);
+ break;
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ }
+ HspVarCoreDupPtr( pval, t, ptr, size );
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+static void cmdfunc_dialog( void )
+{
+ // dialog
+ int i;
+ char *ptr;
+ char *ps;
+ char stmp[0x4000];
+ ptr = code_getdsi( "" );
+ strncpy( stmp, ptr, 0x4000-1 );
+ p1 = code_getdi( 0 );
+ ps = code_getds("");
+
+ if (p1&16) {
+ ctx->stat = fd_dialog( NULL, p1&3, stmp, ps );
+ if ( ctx->stat == 0 ) {
+ ctx->refstr[0] = 0;
+ } else {
+ strncpy( ctx->refstr, fd_getfname(), HSPCTX_REFSTR_MAX-1 );
+ }
+ }
+ else {
+ i=0;
+ if (p1&1) i|=MB_ICONEXCLAMATION; else i|=MB_ICONINFORMATION;
+ if (p1&2) i|=MB_YESNO; else i|=MB_OK;
+ ctx->stat = MessageBox( NULL, stmp, ps, i );
+ }
+}
+
+
+static int cmdfunc_extcmd( int cmd )
+{
+ // cmdfunc : TYPE_EXTCMD
+ // (内蔵GUIコマンド)
+ //
+ code_next(); // 次のコードを取得(最初に必ず必要です)
+ switch( cmd ) { // サブコマンドごとの分岐
+
+ case 0x02: // exec
+ {
+ char *ps;
+ char fname[_MAX_PATH];
+ strncpy( fname, code_gets(), _MAX_PATH-1 );
+ p1 = code_getdi( 0 );
+ ps = code_getds( "" );
+ ExecFile( fname, ps, p1 );
+ break;
+ }
+
+ case 0x03: // dialog
+ cmdfunc_dialog();
+ break;
+
+ case 0x0f: // mes,print
+ {
+ char *ptr;
+ ptr = code_getdsi( "" );
+ fputs(ptr, stdout);
+ if (code_getdi(0) == 0) fputs("\n", stdout);
+ break;
+ }
+
+ case 0x27: // input (console)
+ {
+ PVal *pval;
+ APTR aptr;
+ char *pp2;
+ char *vptr;
+ int strsize;
+ int a;
+ strsize = 0;
+ aptr = code_getva( &pval );
+ //pp2 = code_getvptr( &pval, &size );
+ p2 = code_getdi( 0x4000 );
+ p3 = code_getdi( 0 );
+
+ if ( p2 < 64 ) p2 = 64;
+ pp2 = code_stmp( p2+1 );
+
+ switch( p3 & 15 ) {
+ case 0:
+ while(1) {
+ if ( p2<=0 ) break;
+ a = getchar();
+ if ( a==EOF ) break;
+ *pp2++ = a;
+ p2--;
+ strsize++;
+ }
+ break;
+ case 1:
+ while(1) {
+ if ( p2<=0 ) break;
+ a = getchar();
+ if (( a==EOF )||( a=='\n' )) break;
+ *pp2++ = a;
+ p2--;
+ strsize++;
+ }
+ break;
+ case 2:
+ while(1) {
+ if ( p2<=0 ) break;
+ a = getchar();
+ if ( a == '\r' ) {
+ int c = getchar();
+ if( c != '\n' ) {
+ ungetc(c, stdin);
+ }
+ break;
+ }
+ if (( a==EOF )||( a=='\n' )) break;
+ *pp2++ = a;
+ p2--;
+ strsize++;
+ }
+ break;
+ }
+
+ *pp2 = 0;
+ ctx->strsize = strsize + 1;
+
+ if ( p3 & 16 ) {
+ if (( pval->support & HSPVAR_SUPPORT_FLEXSTORAGE ) == 0 ) throw HSPERR_TYPE_MISMATCH;
+ //HspVarCoreAllocBlock( pval, (PDAT *)vptr, strsize );
+ vptr = (char *)HspVarCorePtrAPTR( pval, aptr );
+ memcpy( vptr, ctx->stmp, strsize );
+ } else {
+ code_setva( pval, aptr, TYPE_STRING, ctx->stmp );
+ }
+ break;
+ }
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ return RUNMODE_RUN;
+}
+
+
+static int reffunc_intfunc_ivalue;
+
+static void *reffunc_function( int *type_res, int arg )
+{
+ void *ptr;
+
+ // 返値のタイプを設定する
+ //
+ *type_res = HSPVAR_FLAG_INT; // 返値のタイプを指定する
+ ptr = &reffunc_intfunc_ivalue; // 返値のポインタ
+
+ // '('で始まるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( *val != '(' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ switch( arg & 0xff ) {
+
+ // int function
+
+ case 0x002: // dirinfo
+ p1 = code_geti();
+ ptr = getdir( p1 );
+ *type_res = HSPVAR_FLAG_STR;
+ break;
+
+ case 0x003: // sysinfo
+ p1 = code_geti();
+ *type_res = sysinfo( p1 );
+ ptr = ctx->stmp;
+ break;
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+
+ // ')'で終わるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( *val != ')' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ return ptr;
+}
+
+
+static int termfunc_extcmd( int option )
+{
+ // termfunc : TYPE_EXTCMD
+ // (内蔵GUI)
+ //
+ return 0;
+}
+
+void hsp3typeinit_cl_extcmd( HSP3TYPEINFO *info )
+{
+ HSPEXINFO *exinfo; // Info for Plugins
+
+ ctx = info->hspctx;
+ exinfo = info->hspexinfo;
+ type = exinfo->nptype;
+ val = exinfo->npval;
+
+ // function register
+ //
+ info->cmdfunc = cmdfunc_extcmd;
+ info->termfunc = termfunc_extcmd;
+
+ // HSPEXINFOに関数を登録する
+ //
+ exinfo->actscr = &cur_window; // Active Window ID
+ exinfo->HspFunc_getbmscr = ex_getbmscr;
+ exinfo->HspFunc_mref = ex_mref;
+
+ // バイナリモードを設定
+ //
+ _setmode( _fileno(stdin), _O_BINARY );
+}
+
+void hsp3typeinit_cl_extfunc( HSP3TYPEINFO *info )
+{
+ info->reffunc = reffunc_function;
+}
+
+
+#ifdef HSPDEBUG
+void hsp3gr_dbg_gui( void )
+{
+ // デバッグウインドゥ用情報
+ //
+ code_adddbg( "ディレクトリ", getdir(0) );
+ code_adddbg( "コマンドライン", getdir(4) );
+}
+#endif
diff --git a/src/hsp3/win32/hsp3gr_win.h b/src/hsp3/win32/hsp3gr_win.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ad933fc725c84d2a7557c2109874598bcdc2c13
--- /dev/null
+++ b/src/hsp3/win32/hsp3gr_win.h
@@ -0,0 +1,15 @@
+
+//
+// hsp3gr.cpp header
+//
+#ifndef __hsp3gr_win_h
+#define __hsp3gr_win_h
+
+#include "../hsp3struct.h"
+
+void hsp3typeinit_cl_extcmd( HSP3TYPEINFO *info );
+void hsp3typeinit_cl_extfunc( HSP3TYPEINFO *info );
+
+void hsp3gr_dbg_gui( void );
+
+#endif
diff --git a/src/hsp3/win32/main.cpp b/src/hsp3/win32/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..de18264e04b377327bbdba78e5aa29b1163a455c
--- /dev/null
+++ b/src/hsp3/win32/main.cpp
@@ -0,0 +1,34 @@
+/*--------------------------------------------------------
+ HSP3 interpreter main
+ 1995/10 onitama
+ 1997/7 onitama
+ 1999/8 onitama
+ 2003/4 onitama
+ --------------------------------------------------------*/
+
+#include
+#include
+#include "hsp3cl.h"
+
+/*----------------------------------------------------------*/
+
+int main( int argc, char *argv[] )
+{
+ int res;
+ char *p;
+
+#ifdef HSPDEBUG
+ if ( argc > 1 ) p = argv[ 1 ]; else p = "";
+#else
+ p = NULL;
+#endif
+
+ res = hsp3cl_init( p );
+ if ( res ) return res;
+ res = hsp3cl_exec();
+
+ return res;
+}
+
+
+
diff --git a/src/hsp3/win32gui/XPStyle.xml b/src/hsp3/win32gui/XPStyle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3bfd3bc06acc9d15565a782f3de932d4ef12b44e
--- /dev/null
+++ b/src/hsp3/win32gui/XPStyle.xml
@@ -0,0 +1,24 @@
+
+
+
+XPStyle
+
+
+
+
+
+
+
+
diff --git a/src/hsp3/win32gui/callex64_nasm.asm b/src/hsp3/win32gui/callex64_nasm.asm
new file mode 100644
index 0000000000000000000000000000000000000000..301c86a754f316be504e9dc77d6dd1a802041622
--- /dev/null
+++ b/src/hsp3/win32gui/callex64_nasm.asm
@@ -0,0 +1,121 @@
+; 64-bit 'CallFunc'
+;
+; Kurogoma 08/26/2016
+;
+; This NASM script is in the pulbic domain.
+
+bits 64
+
+%include "sehhdr64_nasm.h"
+
+global CallFunc64
+
+section .text
+
+
+; CallFunc64(INT_PTR * arguments, FARPROC externalFunction, int numberOfArguments)
+; This function calls a external function.
+; arguments: Argument or arguments to pass to the function of 'externalFunction'
+; externalFunction: Function to call
+; numberOfArguments: Number of the argument or arguments of 'arguments'
+CallFunc64:
+
+ push rbp
+ .pushRBP:
+
+ mov rbp, rsp
+ .setFrame:
+
+ .endPrologue:
+
+ mov r10, rdx
+
+ ; Put the 'arguments' on the stack
+
+ mov eax, r8d
+ sal eax, 3
+ .@IfLabel00:
+ jle .@EndIfLabel00
+ xor eax, eax
+ .@EndIfLabel00:
+
+ sub rax, 8*4
+ .@IfLabel10:
+ jge .@IfLabel10_Else
+
+ add rsp, rax
+ jmp .@EndIfLabel10
+
+ .@IfLabel10_Else:
+
+ and eax, 8
+ sub rsp, rax
+
+ .@EndIfLabel10:
+
+ jmp .@00
+ .@DoLabel_00:
+
+ push qword [rcx + r8*8]
+
+ .@00:
+ dec r8d
+ jge .@DoLabel_00
+
+ .@UntilLabel_00:
+
+ ; Put the first 4 arguments into registers
+
+ pop rcx
+ pop rdx
+ pop r8
+ pop r9
+
+ sub rsp, 8*4
+
+ movq xmm0, rcx
+ movq xmm1, rdx
+ movq xmm2, r8
+ movq xmm3, r9
+
+ call r10
+
+ leave
+ ret
+ .endFunc:
+
+
+section .pdata
+
+ ; Funciton table for exception handling
+ TableOfSEHRuntimeFunctionStructs:
+
+ .CallFunc64:
+ dd CallFunc64
+ dd CallFunc64.endFunc
+ dd TableOfSEHUnwindInfoStructs.CallFunc64
+
+
+section .xdata
+
+ ; Unwind data information
+ TableOfSEHUnwindInfoStructs:
+
+ .CallFunc64:
+
+ db UNWIND_VERSION | (UNW_FLAG_NHANDLER << 3)
+ db CallFunc64.endPrologue - CallFunc64 ; Size of the Prologue
+ db (TableOfSEHUnwindInfoStructs.CallFunc64_unwindCodesTo - TableOfSEHUnwindInfoStructs.CallFunc64_unwindCodesFrom)/2 ; Length of the unwind code array
+ db OPINFO_RBP | (0 << 4) ; Info of the stack frame (lea rbp, [rsp + 0*16])
+
+ ; Unwind code arrray
+
+ .CallFunc64_unwindCodesFrom:
+
+ db CallFunc64.setFrame - CallFunc64
+ db UWOP_SET_FPREG
+
+ db CallFunc64.pushRBP - CallFunc64
+ db UWOP_PUSH_NONVOL + (OPINFO_RBP << 4)
+
+ .CallFunc64_unwindCodesTo:
\ No newline at end of file
diff --git a/src/hsp3/win32gui/comobj.cpp b/src/hsp3/win32gui/comobj.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f57ce38007a3e505c46b1c5787e9a8152269a75a
--- /dev/null
+++ b/src/hsp3/win32gui/comobj.cpp
@@ -0,0 +1,590 @@
+/*------------------------------------------------------------*/
+/*
+ comdata.cpp
+*/
+/*------------------------------------------------------------*/
+
+
+#ifndef HSP_COM_UNSUPPORTED //(COM サポートなし版のビルド時はファイル全体を無視)
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include
+#include
+#include
+#include
+
+#include
+
+#include "../hsp3code.h"
+
+#include "comobj.h"
+#include "comobj_event.h"
+
+#include "../hsp3ext.h"
+#include "../strbuf.h"
+
+/*-----------------------------------------------------------------------------------*/
+/*
+ ComObj interface
+*/
+/*-----------------------------------------------------------------------------------*/
+
+#ifdef HSP_COMOBJ_DEBUG
+FILE *fpComDbg;
+
+void COM_DBG_MSG( const char *sz, ... )
+{
+ va_list args;
+ va_start(args, sz);
+ vfprintf(fpComDbg, sz, args);
+ va_end(args);
+ fflush(fpComDbg);
+}
+#endif
+
+// オブジェクト解放
+void ReleaseComPtr( IUnknown** ppunk )
+{
+ HRESULT hr;
+ IEventHandler *event;
+
+ if ( ! IsVaridComPtr(ppunk) ) return;
+
+ hr = (*ppunk)->QueryInterface( IID_IEventHandler, (void**)&event );
+ if ( SUCCEEDED(hr) && event != NULL ) {
+ // イベントオブジェクトの場合は内部カウンタをデクリメント
+ event->DecInnerRef();
+ event->Release();
+ }
+ UINT ref = (*ppunk)->Release();
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "ReleaseComPtr() : pObj=0x%p is released. : m_ref=%d\n", *ppunk, ref );
+#endif
+ *ppunk = NULL;
+}
+
+// QueryInterface
+void QueryComPtr( IUnknown **ppunkDest, IUnknown *punkSrc, const IID *iid )
+{
+ IEventHandler *event;
+ IUnknown *punkNew;
+ HRESULT hr;
+ if ( punkSrc == NULL ) {
+ ReleaseComPtr( ppunkDest );
+ return;
+ }
+ if ( iid != NULL ) {
+ // iid が有効ポインタの場合は QueryInterface()
+ hr = punkSrc->QueryInterface( *iid, (void**)&punkNew );
+ ReleaseComPtr( ppunkDest );
+ *ppunkDest = ( SUCCEEDED(hr) ? punkNew : NULL );
+ } else {
+ // iid が NULL の場合は単なるコピー
+ punkSrc->AddRef(); // 先に AddRef() しておく(querycom に同じ変数を指定した場合に備えて)
+ ReleaseComPtr( ppunkDest );
+ *ppunkDest = punkNew = punkSrc;
+ }
+ // イベントオブジェクトの場合は内部カウンタをインクリメント
+ if ( punkNew ) {
+ hr = punkNew->QueryInterface( IID_IEventHandler, (void**)&event );
+ if ( SUCCEEDED(hr) && event != NULL ) {
+ event->IncInnerRef();
+ event->Release();
+ }
+ }
+#ifdef HSP_COMOBJ_DEBUG
+ if ( punkNew ) {
+ punkNew->AddRef();
+ UINT ref = (short)punkNew->Release();
+ COM_DBG_MSG( "Query/CopyComPtr() : pObj=%p : &pObj=%p : m_ref=%d\n", punkNew, ppunkDest, ref);
+ }
+#endif
+}
+
+// COMイベントを設定
+void SetComEvent( IUnknown **ppEv, IUnknown **ppunk, const IID *pCPGuid, unsigned short *callback )
+{
+ IEventHandler *event;
+ ReleaseComPtr( ppEv );
+ if ( ! IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR );
+ event = CreateEventHandler( *ppunk, pCPGuid, callback );
+ if ( event == NULL ) throw ( HSPERR_COMDLL_ERROR );
+ event->IncInnerRef();
+ *ppEv = static_cast(event);
+}
+
+// COMイベントの設定を解除(現在はこの関数を使用していない)
+void ReleaseComEvent( IUnknown **ppEv )
+{
+ IEventHandler *event;
+ HRESULT hr;
+ if ( ! IsVaridComPtr(ppEv) ) throw ( HSPERR_COMDLL_ERROR );
+ hr = (*ppEv)->QueryInterface( IID_IEventHandler, (void**)&event );
+ if ( FAILED(hr) || event == NULL ) throw ( HSPERR_COMDLL_ERROR );
+ event->Reset();
+ event->Release();
+ ReleaseComPtr( ppEv );
+}
+
+// 同一オブジェクトかどうか
+BOOL IsSameComObject( IUnknown **ppunk1, IUnknown **ppunk2 )
+{
+ IUnknown *punk1, *punk2;
+ BOOL result = FALSE;
+ if ( IsVaridComPtr(ppunk1) && IsVaridComPtr(ppunk2) ) {
+ (*ppunk1)->QueryInterface( IID_IUnknown, (void**)&punk1 );
+ (*ppunk2)->QueryInterface( IID_IUnknown, (void**)&punk2 );
+ if ( punk1 == punk2 ) result = TRUE;
+ punk1->Release();
+ punk2->Release();
+ } else if ( *ppunk1 == NULL && *ppunk2 == NULL ) {
+ result = TRUE;
+ }
+ return result;
+}
+
+
+
+
+/*-----------------------------------------------------------------------------------*/
+/*
+ オートメーション(IDispatch)関連
+*/
+/*-----------------------------------------------------------------------------------*/
+
+
+static void get_prm_for_method( ComDispParams *data );
+static void get_prm_for_prop( ComDispParams *data );
+static void free_dispparams( ComDispParams *data );
+static void set_prm_for_invoke( ComDispParams *data, int chk );
+
+
+HRESULT CallDispMethod( IUnknown* punk, DISPID dispid, VARIANT *result )
+{
+ // メソッド呼び出し (スクリプトからパラメータの取得を行いつつ)
+ //
+ HRESULT hr;
+ ComDispParams DispData = { 0 };
+
+ DispData.disp = (IDispatch *)punk;
+ punk->AddRef();
+
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "CallDispMethod() : pObj=0x%p, dispid=%d\n", punk, dispid);
+#endif
+ // VARIANT と IDispatch の確実な解放のための例外処理
+ try {
+ get_prm_for_method( &DispData );
+ hr = DispData.disp->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT,
+ DISPATCH_METHOD, &DispData.params,
+ result, NULL, NULL );
+ }
+ catch (...) {
+ free_dispparams( &DispData );
+ throw;
+ }
+ free_dispparams( &DispData );
+ return hr;
+}
+
+HRESULT GetDispProp( IUnknown* punk, DISPID dispid, VARIANT *result )
+{
+ // プロパティ取得 (スクリプトからパラメータの取得を行いつつ)
+ //
+ HRESULT hr;
+ ComDispParams DispData = { 0 };
+
+ DispData.disp = (IDispatch *)punk;
+ punk->AddRef();
+
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG("GetDispProp() : pObj=0x%p, dispid=%d\n", punk, dispid);
+#endif
+ // VARIANT と IDispatch の確実な解放のための例外処理
+ try {
+ get_prm_for_prop( &DispData );
+ hr = DispData.disp->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT,
+ DISPATCH_METHOD | DISPATCH_PROPERTYGET,
+ &DispData.params,result, NULL, NULL );
+ }
+ catch (...) {
+ free_dispparams( &DispData );
+ throw;
+ }
+ free_dispparams( &DispData );
+ return hr;
+}
+
+ComDispParams *PrepForPutDispProp( IUnknown *punk, DISPID dispid )
+{
+ // プロパティ設定のための準備 (スクリプトからパラメータの取得を行いつつ)
+ //
+ // 返される ComDispParams 構造体は後で PutDispProp() に渡す
+ // それまでは PVal の master メンバに保存しておく
+ //
+ ComDispParams *data = (ComDispParams *)sbAlloc( sizeof(ComDispParams) );;
+
+ data->disp = (IDispatch *)punk;
+ punk->AddRef();
+
+ data->dispid = dispid;
+ data->flag = DISPATCH_PROPERTYPUT;
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "PrepForPutDispProp() : pObj=0x%p, dispid=%d\n", punk, dispid);
+#endif
+ try {
+ get_prm_for_prop( data );
+ }
+ catch (...) {
+ free_dispparams( data );
+ sbFree( data );
+ throw;
+ }
+ return data;
+}
+
+HRESULT PutDispProp( ComDispParams *data, void *setdata, int settype )
+{
+ // プロパティ設定
+ //
+ VARIANT *var;
+ HRESULT hr;
+ DISPID DispIdNamed[] = { DISPID_PROPERTYPUT };
+ if ( data->flag != DISPATCH_PROPERTYPUT ) throw ( HSPERR_COMDLL_ERROR );
+ data->params.rgdispidNamedArgs = DispIdNamed;
+ data->params.cNamedArgs = 1;
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "PutDispProp() : pdispObj=0x%p, dispid=%d\n", data->disp, data->dispid);
+#endif
+ // VARIANT と IDispatch の確実な解放のための例外処理
+ try {
+ // 設定するデータをパラメータとして設定
+ if ( data->params.cArgs >= TMP_VARIANT_MAX ) {
+ throw ( HSPERR_TOO_MANY_PARAMETERS );
+ }
+ var = &data->prms[ TMP_VARIANT_MAX - 1 - data->params.cArgs ];
+ VariantInit( var );
+ comset_variant( var, setdata, settype );
+ data->params.rgvarg = var;
+ data->params.cArgs++;
+ hr = data->disp->Invoke( data->dispid, IID_NULL, LOCALE_USER_DEFAULT,
+ DISPATCH_PROPERTYPUT, &data->params, NULL, NULL, NULL );
+ }
+ catch (...) {
+ free_dispparams( data );
+ throw;
+ }
+ free_dispparams( data );
+ return hr;
+}
+static void free_dispparams( ComDispParams *data )
+{
+ // パラメータが格納された VARIANT 配列の解放
+ //
+ VARIANT *var;
+ int count = data->params.cArgs;
+ if ( count > 0 ) {
+ var = data->params.rgvarg;
+ for (int i=0; iparams.cArgs = 0;
+ }
+ if (data->disp) {
+ data->disp->Release();
+ data->disp = NULL;
+ }
+}
+
+void FreeDispParams( ComDispParams* data )
+{
+ // PrepForPutDispProp() が返した ComDispParams 構造体を解放
+ //
+ if ( data == NULL ) return;
+ free_dispparams( data );
+ sbFree( data );
+}
+
+static void get_prm_for_prop( ComDispParams *data )
+{
+ // invoke 呼び出しパラメータを取得(プロパティ用)
+ //
+ int chk;
+
+ data->params.rgvarg = NULL;
+ data->params.cArgs = 0;
+ while (1) {
+ chk = code_get();
+ switch ( chk ) {
+ case PARAM_OK:
+ case PARAM_SPLIT:
+ case PARAM_DEFAULT:
+ set_prm_for_invoke( data, chk );
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "get_prm_for_prop() : %d 個目のパラメータ : chk=%2d, flag=%d\n", data->params.cArgs, chk, mpval->flag);
+#endif
+ break;
+ case PARAM_ENDSPLIT: // パラメータ終端
+ return;
+ default:
+ throw ( HSPERR_BAD_ARRAY_EXPRESSION );
+ }
+ }
+}
+
+static void get_prm_for_method( ComDispParams *data )
+{
+ // invoke 呼び出しパラメータを取得(メソッド呼び出し用)
+ //
+ int chk;
+
+ data->params.rgvarg = NULL;
+ data->params.cArgs = 0;
+ while (1) {
+ chk = code_get();
+ switch ( chk ) {
+
+ case PARAM_OK: // パラメータ取得時
+ case PARAM_DEFAULT: // パラメータ省略時
+ set_prm_for_invoke( data, chk );
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "get_prm_for_method() : %d 個目のパラメータ : chk=%2d, flag=%d\n", data->params.cArgs, chk, mpval->flag);
+#endif
+ break;
+
+ case PARAM_END: // パラメータ終端
+ return;
+
+ default:
+ throw ( HSPERR_SYNTAX );
+ }
+ }
+}
+static void set_prm_for_invoke( ComDispParams *data, int chk )
+{
+ VARIANT *var;
+ if (data->params.cArgs >= TMP_VARIANT_MAX) {
+ throw ( HSPERR_TOO_MANY_PARAMETERS );
+ }
+ var = &data->prms[ TMP_VARIANT_MAX - 1 - data->params.cArgs ];
+ VariantInit( var );
+ if ( chk == PARAM_DEFAULT ) {
+ var->vt = VT_ERROR; // デフォルト値をセット
+ var->scode = DISP_E_PARAMNOTFOUND;
+ } else {
+ comset_variant( var, mpval->pt, mpval->flag ); // データ → VARIANT
+ }
+ data->params.rgvarg = var;
+ data->params.cArgs++;
+}
+
+
+/*-----------------------------------------------------------------------------------*/
+/*
+ SafeArray 関連
+*/
+/*-----------------------------------------------------------------------------------*/
+
+void ConvSafeArray2Var( PVal *pval, SAFEARRAY *psa, VARTYPE vt )
+{
+ // SafeArray から配列変数に変換
+ //
+ int i, dimcount, totalcount, elemcount[4]={0,0,0,0};
+ void *pSrc, *pDst;
+
+ dimcount = SafeArrayGetDim( psa );
+ if ( dimcount > 4 ) throw ( HSPERR_UNSUPPORTED_FUNCTION );
+ totalcount = 1;
+ for ( i=0; irgsabound[i].cElements;
+ totalcount *= elemcount[i];
+ }
+ SafeArrayAccessData( psa, &pSrc );
+ switch ( vt ) {
+ case VT_NULL:
+ case VT_EMPTY:
+ HspVarCoreDim( pval, HSPVAR_FLAG_INT, 1,0,0,0 );
+ break;
+ case VT_I4:
+ case VT_UI4:
+ case VT_INT:
+ case VT_UINT:
+ case VT_ERROR:
+ case VT_I2:
+ case VT_UI2:
+ case VT_I1:
+ case VT_UI1:
+ HspVarCoreDim( pval, HSPVAR_FLAG_INT, elemcount[0],elemcount[1],elemcount[2],elemcount[3] );
+ pDst = pval->pt;
+ switch ( vt ) {
+ case VT_I4:
+ case VT_UI4:
+ case VT_INT:
+ case VT_UINT:
+ case VT_ERROR:
+ memcpy( pDst, pSrc, totalcount * sizeof(long) );
+ break;
+ case VT_I2:
+ for (i=0; ipt;
+ switch ( vt ) {
+ case VT_R8:
+ memcpy( pDst, pSrc, totalcount * sizeof(double) );
+ break;
+ case VT_R4:
+ for (i=0; iflag ) {
+ case HSPVAR_FLAG_STR:
+ vt = VT_BSTR;
+ break;
+ case HSPVAR_FLAG_DOUBLE:
+ vt = VT_R8;
+ break;
+ case HSPVAR_FLAG_INT:
+ vt = VT_I4;
+ break;
+ case HSPVAR_FLAG_COMSTRUCT:
+ vt = VT_UNKNOWN;
+ break;
+ default:
+ throw HSPERR_INVALID_TYPE;
+ }
+ if ( bVariant ) vt = VT_VARIANT;
+
+ // 配列変数の次元数・要素数を調べる
+ dimcount = 0;
+ totalcount = 1;
+ for (i=0; i<4; i++) {
+ sabound[i].cElements = pval->len[i+1];
+ if ( sabound[i].cElements == 0 ) break;
+ totalcount *= sabound[i].cElements;
+ sabound[i].lLbound = 0;
+ dimcount++;
+ }
+
+ // SafeArray 作成・データコピー
+ psa = SafeArrayCreate( vt, dimcount, sabound );
+ if ( psa == NULL ) throw ( HSPERR_OUT_OF_MEMORY );
+ SafeArrayAccessData( psa, &pDst );
+ pSrc = pval->pt;
+ switch ( pval->flag ) {
+ case HSPVAR_FLAG_STR:
+ for (i=0; ioffset = i;
+ pszSrc = (char *)HspVarCorePtr( pval );
+ *pbstrDst = comget_bstr( pszSrc );
+ }
+ break;
+ case HSPVAR_FLAG_DOUBLE:
+ if ( bVariant ) {
+ for ( i=0; iAddRef();
+ }
+ }
+ break;
+ }
+ SafeArrayUnaccessData( psa );
+ *vtRet = vt;
+ return psa;
+}
+
+SAFEARRAY *CreateBinarySafeArray( void *data, int size, VARTYPE *vt )
+{
+ SAFEARRAY *psa;
+ SAFEARRAYBOUND rgsabound[1];
+ void *ptr;
+
+ if ( size <= 0 ) throw HSPERR_ILLEGAL_FUNCTION;
+
+ rgsabound[0].lLbound = 0;
+ rgsabound[0].cElements = size;
+ psa = SafeArrayCreate( VT_UI1, 1, rgsabound );
+ if ( psa == NULL ) throw HSPERR_OUT_OF_MEMORY;
+ SafeArrayAccessData( psa, &ptr );
+ memcpy( ptr, data, size );
+ SafeArrayUnaccessData( psa );
+ *vt = VT_UI1;
+ return psa;
+}
+
+void GetBinarySafeArray( void *ptr, int size, SAFEARRAY *psa )
+{
+ void *data;
+ HRESULT hr;
+
+ hr = SafeArrayAccessData( psa, &data );
+ if ( FAILED(hr) ) throw HSPERR_ARRAY_OVERFLOW;
+ memcpy( ptr, data, size );
+ SafeArrayUnaccessData( psa );
+}
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
diff --git a/src/hsp3/win32gui/comobj.h b/src/hsp3/win32gui/comobj.h
new file mode 100644
index 0000000000000000000000000000000000000000..75d653065361e98711154aea349bef20f54c5ea1
--- /dev/null
+++ b/src/hsp3/win32gui/comobj.h
@@ -0,0 +1,78 @@
+
+//
+// comstruct.cpp header
+//
+// COM オブジェクト情報を格納する構造体
+//
+#ifndef __comobj_h
+#define __comobj_h
+
+
+#ifndef HSP_COM_UNSUPPORTED //(COM サポートなし版のビルド時はファイル全体を無視)
+
+/*
+ rev 43
+ mingw ; error : IDispatchが宣言されていない、他
+ に対処
+*/
+#if defined( __GNUC__ )
+#define COM_NO_WINDOWS_H
+#include
+#endif
+
+// デバッグ用に作成する場合に定義
+// #define HSP_COMOBJ_DEBUG
+
+#ifdef HSP_COMOBJ_DEBUG
+extern FILE *fpComDbg;
+void COM_DBG_MSG( const char *sz, ... );
+#endif
+
+
+void ReleaseComPtr( IUnknown** );
+void QueryComPtr( IUnknown**, IUnknown*, const IID* );
+
+void SetComEvent( IUnknown **, IUnknown **, const IID *, unsigned short * );
+void ReleaseComEvent( IUnknown ** );
+BOOL IsSameComObject( IUnknown **, IUnknown ** );
+
+// 以下の2つはマクロ(インライン関数)として定義
+//BOOL IsVaridComPtr( IUnknown** );
+// void CopyComPtr( IUnknown**, IUnknown* );
+#ifdef __cplusplus
+inline BOOL IsVaridComPtr( IUnknown** ppunk ) { return ( *ppunk != NULL ); }
+inline void CopyComPtr( IUnknown** ppDest, IUnknown* pSrc ){ QueryComPtr( ppDest, pSrc, NULL );}
+#else
+#define IsVaridComPtr( ppunk ) ( *(ppunk) != NULL )
+#define CopyComPtr( ppDest, pSrc ) QueryComPtr( ppDest, pSrc, NULL )
+#endif
+
+
+/*------------------------------------------------------*/
+
+
+#define TMP_VARIANT_MAX 16
+
+typedef struct ComDispParams {
+ IDispatch *disp;
+ DISPID dispid;
+ WORD flag;
+ DISPPARAMS params;
+ VARIANT prms[TMP_VARIANT_MAX];
+} ComDispParams;
+
+HRESULT CallDispMethod( IUnknown* punk, DISPID dispid, VARIANT *result );
+HRESULT GetDispProp( IUnknown* punk, DISPID dispid, VARIANT *result );
+ComDispParams *PrepForPutDispProp( IUnknown *punk, DISPID dispid );
+HRESULT PutDispProp( ComDispParams *pDispData, void *setdata, int settype );
+void FreeDispParams( ComDispParams* data );
+
+void ConvSafeArray2Var( PVal *pval, SAFEARRAY *psa, VARTYPE vt );
+SAFEARRAY *ConvVar2SafeArray( PVal *pval, BOOL bVariant, VARTYPE *vtRet );
+SAFEARRAY *CreateBinarySafeArray( void *ptr, int size, VARTYPE *vt );
+void GetBinarySafeArray( void *ptr, int size, SAFEARRAY *psa );
+
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
+#endif // __comobj_h
diff --git a/src/hsp3/win32gui/comobj_event.cpp b/src/hsp3/win32gui/comobj_event.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4ca548cf0d28b0dfee3a95da43c03bde76659aa0
--- /dev/null
+++ b/src/hsp3/win32gui/comobj_event.cpp
@@ -0,0 +1,512 @@
+/*------------------------------------------------------------*/
+/*
+ event handler
+*/
+/*------------------------------------------------------------*/
+/*
+ (for HSP 3.0)
+ COM オブジェクトのイベントハンドラオブジェクト
+
+ COM オブジェクトのイベントを受け取るオブジェクトです。
+
+ イベントハンドラオブジェクトは、イベント取得に必要となる
+ IDispatch インターフェースを提供します。
+
+ イベントハンドラインターフェースポインタ (IID_IEventHandler)
+ のメンバ関数は以下の通り。
+
+ HRESULT IEventHandler::Set(IUnknown *pObj, IID* iid, USHORT* callback);
+ void IEventHandler::Reset();
+ void IEventHandler::IncInnerRef();
+ void IEventHandler::DecInnerRef();
+
+ Set() はイベントハンドラの設定を変更します。以前の設定は
+ 上書きされます。
+
+ Reset() は既存のハンドラ設定を解除します。
+
+ IncInnerRef(), DecInnerRef() はHSPのCOM型変数からの参照
+ カウントを管理するため使用されます。
+
+ 関数
+
+ DISPID GetEventDispID( void* iptr );
+
+ イベント割り込み処理中に、指定されたオブジェクトから通知
+ されたイベントの DISPID を取得します。多重割り込み処理中
+ に iptr に NULL を指定した場合には、もっとも新しいイベン
+ トを発生させたオブジェクトが対象になります。
+
+ VARIANT* GetEventArg( void* iptr, int idx );
+
+ イベント割り込み処理中に、指定されたオブジェクトから通知
+ されたイベントの指定インデックスの引数を表す VARIANT 構
+ 造体へのポインタを返します。多重割り込み処理中に iptr に
+ NULL を指定した場合には、もっとも新しいイベントを発生さ
+ せたオブジェクトが対象になります。
+
+*/
+
+
+#ifndef HSP_COM_UNSUPPORTED //(COM サポートなし版のビルド時はファイル全体を無視)
+
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include
+#include
+#include
+#include
+
+#include
+
+/*
+ rev 43
+ mingw : error : GUIDKIND_DEFAULT_SOURCE_DISP_IIDが未定義
+ に対処
+*/
+#if defined( __GNUC__ )
+#include
+#endif
+
+#include "../hsp3code.h"
+#include "comobj_event.h"
+#include "hspvar_comobj.h"
+
+
+#ifdef HSP_COMEVENT_DEBUG
+/* for Debug */
+/* GUID を文字列形式に変換 */
+static int sprintGuid( char *szguid, REFGUID rguid )
+{
+ if ( rguid == IID_IUnknown ) return sprintf( szguid, "IID_IUnknown" );
+ if ( rguid == IID_IDispatch ) return sprintf( szguid, "IID_IDispatch" );
+ if ( rguid == IID_IEventHandler ) return sprintf( szguid, "IID_IEventHandler" );
+
+ return sprintf( szguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ rguid.Data1, rguid.Data2, rguid.Data3, rguid.Data4[0], rguid.Data4[1],
+ rguid.Data4[2], rguid.Data4[3], rguid.Data4[4], rguid.Data4[5],
+ rguid.Data4[6], rguid.Data4[7]);
+}
+
+static DWORD g_dwThreadId;
+
+#endif // HSP_COMEVENT_DEBUG
+
+// IID_IEventHandler の実体
+IID IID_IEventHandler = {
+ 0x4c7f4354, 0x8a07, 0x4d51, {0xb9, 0xf0, 0x47, 0xba, 0x5c, 0xbe, 0xfe, 0xd7}
+};
+
+struct ComEventData;
+
+// Enevnt Handler object
+
+/*
+ rev 43
+ mingw : warning : ComEventHandler のデストラクタが仮想でない。
+ 問題ないのか?わかりません。(naznyark)
+*/
+class ComEventHandler : public IEventHandler {
+ ULONG m_ref; // イベントオブジェクト参照カウンタ
+ int m_refInner; // HSP COMオブジェクト変数からの参照カウンタ
+ IUnknown* m_punkObj; // オブジェクトのIUnknownインターフェースポインタ
+ IConnectionPoint* m_pCP; // IConnectionPoint インターフェースポインタ
+ DWORD m_cookie; // Cookie 値( Advise() より返される)
+ IID m_CPGuid; // コネクションポイントIID
+ unsigned short* m_callback; // HSPサブルーチン(コールバック用)
+
+#ifdef HSP_COMEVENT_DEBUG
+ /* For Debug */
+ FILE *fpDebug;
+#endif
+
+public:
+ ComEventHandler();
+ ~ComEventHandler();
+
+ // IDispatch methods (イベント処理用)
+ STDMETHOD(QueryInterface)(REFIID, void**);
+ STDMETHOD_(ULONG, AddRef)();
+ STDMETHOD_(ULONG, Release)();
+ STDMETHOD(GetTypeInfoCount)(UINT*);
+ STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo**);
+ STDMETHOD(GetIDsOfNames)(REFIID, OLECHAR**, UINT, LCID, DISPID*);
+ STDMETHOD(Invoke)(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
+ STDMETHOD_(void, IncInnerRef)();
+ STDMETHOD_(void, DecInnerRef)();
+ STDMETHOD(Set)(IUnknown*, const IID*, unsigned short* );
+ STDMETHOD_(void,Reset)();
+
+/*
+ rev 43
+ mingw : error : friend static修飾は不正
+ に対処
+*/
+#if defined(__GNUC__)
+ friend ComEventData* SearchEventData( void *iptr );
+#else
+ friend static ComEventData* SearchEventData( void *iptr );
+#endif
+
+};
+
+
+/*-----------------------------------------------------------------------------------*/
+
+// Event Data structure (defined as class object)
+//
+// note: エラー時に例外が throw された場合でもポインタのつなぎ替えが
+// 正常に行われるようにクラスオブジェクトとして定義してあります
+//
+
+struct ComEventData {
+ ComEventHandler* handler;
+ DISPID dispid;
+ DISPPARAMS* params;
+ VARIANT* result;
+
+ // (多重割り込みに備えて)
+ ComEventData* prev; // 1つ前のイベント
+ static ComEventData* now; // 現在処理中 (ない場合 NULL )
+ // static UINT count; // 多重割り込みイベント数 (未使用)
+
+ ComEventData(ComEventHandler*, DISPID, DISPPARAMS*, VARIANT*);
+ ~ComEventData();
+};
+
+// UINT ComEventData::count = 0;
+ComEventData* ComEventData::now = NULL;
+
+ComEventData::ComEventData(
+ ComEventHandler *handler_s,
+ DISPID dispid_s,
+ DISPPARAMS *params_s,
+ VARIANT *result_s )
+ : handler(handler_s),dispid(dispid_s),params(params_s),result(result_s)
+{
+ if (handler) { handler->AddRef(); }
+
+ prev = now;
+ now = this;
+// count++;
+}
+
+ComEventData::~ComEventData()
+{
+ if (handler) { handler->Release(); }
+ now = prev;
+// count--;
+}
+
+/*-----------------------------------------------------------------------------------*/
+
+/*
+ rev 43
+ mingw : warning : メンバの宣言順と初期化子リストの並び順が異なる
+ に対処
+*/
+ComEventHandler::ComEventHandler()
+ : m_ref(0), m_refInner(0), m_punkObj(NULL), m_pCP(NULL), m_cookie(0), m_CPGuid( IID_NULL ), m_callback(0)
+{
+ // 参照カウンタ 0 の状態で作成
+
+#ifdef HSP_COMEVENT_DEBUG
+ char fname[64];
+ sprintf( fname, "dbg_evnt_%p.txt", this );
+ fpDebug = fopen( fname, "w" );
+ fprintf( fpDebug, "An event handler is created. : this = %p\n", this );
+#endif // HSP_COMEVENT_DEBUG
+}
+
+ComEventHandler::~ComEventHandler()
+{
+ Reset();
+
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "This handler object is deleted.\n" );
+ fclose( fpDebug );
+#endif
+}
+
+
+// initialize connection of event handler object
+HRESULT STDMETHODCALLTYPE ComEventHandler::Set( IUnknown *pObj, const IID* pCPGuid, unsigned short* callback )
+{
+ IProvideClassInfo2* pPCI;
+ IConnectionPointContainer* pCPC;
+ HRESULT hr;
+
+ Reset();
+
+ // connection point IID preparation
+ if ( pCPGuid ) {
+ m_CPGuid = *pCPGuid;
+ } else {
+ // search for a default connection point IID.
+ hr = pObj->QueryInterface(IID_IProvideClassInfo2, reinterpret_cast(&pPCI) );
+ if ( SUCCEEDED(hr) ) {
+ hr = pPCI->GetGUID( GUIDKIND_DEFAULT_SOURCE_DISP_IID, &m_CPGuid );
+ pPCI->Release();
+ }
+ if ( FAILED(hr) ) return hr;
+ }
+
+ // 内部では IUnknown インターフェースを保持
+ pObj->QueryInterface( IID_IUnknown, reinterpret_cast(&m_punkObj) );
+ m_callback = callback;
+
+ // IConnectionPointContainer から IConnectionPoint を取得
+ hr = pObj->QueryInterface( IID_IConnectionPointContainer, reinterpret_cast(&pCPC) );
+ if ( SUCCEEDED(hr) ) {
+ hr = pCPC->FindConnectionPoint( m_CPGuid, &m_pCP );
+ if ( SUCCEEDED(hr) ) {
+ hr = m_pCP->Advise( static_cast(this), &m_cookie );
+ }
+ pCPC->Release();
+ }
+ if ( FAILED(hr) ) Reset();
+
+#ifdef HSP_COMEVENT_DEBUG
+ char guid[64];
+ sprintGuid( guid, *pCPGuid );
+ fprintf( fpDebug, "Set() : pObj=%p, Connection Point IID = %s : ", pObj, guid );
+ if ( SUCCEEDED(hr) ) {
+ fprintf( fpDebug, "Initialized. m_ref=%d\n", m_ref );
+ } else {
+ fprintf( fpDebug, "Initialization is failed.\n" );
+ }
+#endif // HSP_COMEVENT_DEBUG
+
+ return hr;
+}
+
+void STDMETHODCALLTYPE ComEventHandler::Reset()
+{
+ if ( m_pCP ) {
+ if ( m_cookie != 0 ) {
+ m_pCP->Unadvise( m_cookie );
+ m_cookie = 0;
+ }
+ m_pCP->Release();
+ m_pCP = NULL;
+ }
+ if ( m_punkObj ) {
+ m_punkObj->Release();
+ m_punkObj = NULL;
+ }
+ m_CPGuid = IID_NULL;
+ m_callback = NULL;
+
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "Reset() : All Setting is reset.\n" );
+#endif
+}
+
+void STDMETHODCALLTYPE ComEventHandler::IncInnerRef()
+{
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "IncInnerRef() : m_refInner=%d :: ", m_refInner+1);
+#endif
+
+ // HSP COM変数からの参照カウンタをインクリメント
+ AddRef();
+ m_refInner++;
+}
+
+void STDMETHODCALLTYPE ComEventHandler::DecInnerRef()
+{
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "DecInnerRef() : m_refInner=%d :: ", m_refInner-1);
+#endif
+
+ // HSP COM変数からの参照カウンタをデクリメント
+ if ( (--m_refInner) <= 0 ) {
+ // もうどのCOMオブジェクト変数からも参照されていない場合
+ Reset();
+ }
+ // この Release() でオブジェクト自身 (this) が破棄される可能性もある
+ // (この Release() 以降で自身のメンバを参照しないこと)
+ Release();
+}
+
+HRESULT STDMETHODCALLTYPE ComEventHandler::QueryInterface (
+ REFIID riid,
+ void** ppv )
+{
+#ifdef HSP_COMEVENT_DEBUG
+ char guid[64];
+ sprintGuid( guid, riid );
+ fprintf( fpDebug, "QueryInterface( %s ) : ", guid );
+#endif
+
+ if ( ppv == NULL ) return E_POINTER;
+
+ if ( riid == IID_IEventHandler ||
+ riid == m_CPGuid ||
+ riid == IID_IUnknown ||
+ riid == IID_IDispatch )
+ {
+ *ppv = static_cast(this);
+ AddRef();
+ return S_OK;
+ }
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "Error (m_ref=%d)\n", m_ref);
+#endif
+
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+ULONG STDMETHODCALLTYPE ComEventHandler::AddRef ()
+{
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "AddRef() : m_ref=%d\n", m_ref+1 );
+#endif
+
+ return ++m_ref;
+}
+
+ULONG STDMETHODCALLTYPE ComEventHandler::Release ()
+{
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "Release() : m_ref=%d\n", m_ref-1 );
+#endif
+
+ if ( --m_ref ) return m_ref;
+ delete this;
+ return 0;
+}
+
+HRESULT STDMETHODCALLTYPE ComEventHandler::GetTypeInfoCount (UINT* pctinfo)
+{
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "GetTypeInfoCount()\n");
+#endif
+
+ if ( pctinfo == NULL )
+ return E_INVALIDARG;
+ *pctinfo = 0;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE ComEventHandler::GetTypeInfo (UINT, LCID, ITypeInfo** ppTInfo)
+{
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "GetTypeInfo()\n");
+#endif
+
+ if ( ppTInfo == NULL )
+ return E_INVALIDARG;
+ *ppTInfo = NULL;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE ComEventHandler::GetIDsOfNames (
+ REFIID, OLECHAR**, UINT, LCID, DISPID* )
+{
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "GetIDsOfNames()\n");
+#endif
+
+ return DISP_E_UNKNOWNNAME;
+}
+
+HRESULT STDMETHODCALLTYPE ComEventHandler::Invoke (
+ DISPID dispid, REFIID, LCID, WORD wFlags,
+ DISPPARAMS *dispparams, VARIANT* result, EXCEPINFO*, UINT*)
+{
+#ifdef HSP_COMEVENT_DEBUG
+ fprintf( fpDebug, "Invoke() : DISPID=%d wFlags=0x%04x\n", dispid, wFlags);
+#endif
+ if ( wFlags != DISPATCH_METHOD )
+ return DISP_E_MEMBERNOTFOUND;
+ if ( dispparams->cNamedArgs )
+ return DISP_E_NONAMEDARGS;
+
+ ComEventData eventdata( this, dispid, dispparams, result);
+ code_call( m_callback );
+ return S_OK;
+}
+
+
+static ComEventData* SearchEventData( IUnknown* punkEvent )
+{
+ ComEventData *p, *ret;
+// IEventHandler *event;
+// HRESULT hr;
+
+ if ( punkEvent == NULL ) return ComEventData::now;
+
+ ret = NULL;
+ /*
+ hr = punkEvent->QueryInterface( IID_IEventHandler, (void**)&event );
+ if ( SUCCEEDED(hr) && event != NULL ) {
+ for ( p=ComEventData::now; p!=NULL; p=p->prev) {
+ if ( p->handler == static_cast(event) ) {
+ ret = p;
+ break;
+ }
+ }
+ event->Release();
+ }
+ */
+ for ( p=ComEventData::now; p!=NULL; p=p->prev) {
+ if ( p->handler == static_cast(punkEvent) ) {
+ ret = p;
+ break;
+ }
+ }
+ return ret;
+}
+
+
+DISPID GetEventDispID( IUnknown* punkEvent )
+{
+ ComEventData *pData = SearchEventData( punkEvent );
+ if ( pData ) {
+ return pData->dispid;
+ }
+ return DISPID_UNKNOWN;
+}
+
+VARIANT* GetEventArg( IUnknown* punkEvent , int idx )
+{
+#ifdef HSP_COMOBJ_DEBUG
+ fprintf(fpComDbg, "GetEventArg() : pEvent=%p : index=%d\n", punkEvent, idx);
+#endif
+
+ VARIANT *varArg = NULL;
+ ComEventData *pData = SearchEventData( punkEvent );
+ if ( pData ) {
+ int cArgs = pData->params->cArgs;
+ if ( idx >= 0 && idx < cArgs ) {
+ varArg = &pData->params->rgvarg[cArgs - idx - 1];
+#ifdef HSP_COMOBJ_DEBUG
+ fprintf(fpComDbg, "cArgs=%d, index=%d\n", cArgs, idx);
+#endif
+ }
+ }
+ return varArg;
+}
+
+IEventHandler* CreateEventHandler( IUnknown* obj, const IID* iid, unsigned short* subr )
+{
+ IEventHandler *event;
+ HRESULT hr;
+ event = new ComEventHandler;
+ event->AddRef();
+ hr = event->Set( obj, iid, subr );
+ if ( FAILED(hr) ) {
+ delete event;
+ event = NULL;
+ }
+ return event;
+}
+
+
+
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
diff --git a/src/hsp3/win32gui/comobj_event.h b/src/hsp3/win32gui/comobj_event.h
new file mode 100644
index 0000000000000000000000000000000000000000..215913e010fa3ec2e626ca65dc59a7fb6e5e5a05
--- /dev/null
+++ b/src/hsp3/win32gui/comobj_event.h
@@ -0,0 +1,60 @@
+
+//
+// comobj_event.cpp header
+//
+#ifndef __comobj_event_h
+#define __comobj_event_h
+
+// デバッグ用の場合に定義
+// #define HSP_COMEVENT_DEBUG
+
+
+#ifndef HSP_COM_UNSUPPORTED //(COM サポートなし版のビルド時はファイル全体を無視)
+
+/*-----------------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+struct IEventHandler;
+#endif
+
+// IID_IEventHandler = {4c7f4354-8a07-4d51-b9f0-47ba5cbefed7};
+extern IID IID_IEventHandler;
+
+#undef INTERFACE
+#define INTERFACE IEventHandler
+
+DECLARE_INTERFACE_(IEventHandler, IDispatch)
+{
+ // IUnknown methods
+ STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // IDispatch methods
+ STDMETHOD(GetTypeInfoCount)(THIS_ UINT*) PURE;
+ STDMETHOD(GetTypeInfo)(THIS_ UINT, LCID, ITypeInfo**) PURE;
+ STDMETHOD(GetIDsOfNames)(THIS_ REFIID, OLECHAR**, UINT, LCID, DISPID*) PURE;
+ STDMETHOD(Invoke)(THIS_ DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) PURE;
+
+ // IEventHandler methods
+ STDMETHOD_(void, IncInnerRef) (THIS) PURE;
+ STDMETHOD_(void, DecInnerRef) (THIS) PURE;
+ STDMETHOD(Set) (THIS_ IUnknown*, const IID*, unsigned short* ) PURE;
+ STDMETHOD_(void,Reset) (THIS) PURE;
+};
+
+DISPID GetEventDispID( IUnknown* );
+VARIANT* GetEventArg( IUnknown*, int );
+IEventHandler* CreateEventHandler( IUnknown*, const IID*, unsigned short* );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
+
+#endif // __comobj_event_h
diff --git a/src/hsp3/win32gui/fcpoly.cpp b/src/hsp3/win32gui/fcpoly.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4aba1517aa80306da2a1917df079bcb078e0f8aa
--- /dev/null
+++ b/src/hsp3/win32gui/fcpoly.cpp
@@ -0,0 +1,1107 @@
+//
+// Polygon draw lib (full color)
+// onion software/onitama 2001/6
+//
+
+// hsp3cでは全体を無視
+#ifndef HSP_COMPACT
+
+#include
+#include
+#include
+#include "fcpoly.h"
+#include "../supio.h"
+
+// Settings
+//
+int resY0, resY1; // 書き換え範囲(高さ)min,max
+
+static SCANDATA *scanData;
+static char *lpDest; // 描画画面のバッファ
+static int nDestWByte; // 描画座標幅byte数
+static int nDestWidth; // 描画座標幅
+static int nDestWidth2; // 描画座標幅(VRAM用)
+static int nDestHeight; // 描画座標高さ
+static int DestSize; // 描画画面バッファのサイズ
+static int maxysize; // SCANDATAの最大高さ
+
+static char *lpTex; // テクスチャのバッファ
+static int curtex; // current texID
+static int nTexWidth; // テクスチャ幅
+static int nTexWByte; // テクスチャ幅byte数
+static int nTexHeight; // テクスチャ高さ
+
+static unsigned char ck1; // カラーキー1
+static unsigned char ck2; // カラーキー2
+static unsigned char ck3; // カラーキー3
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+void SetupScanData( int ysize )
+{
+ if ( maxysize < ysize ) {
+ if ( scanData != NULL ) { free( scanData ); }
+ scanData = (SCANDATA *)malloc( sizeof( SCANDATA ) * ysize );
+ maxysize = ysize;
+ }
+}
+
+void hgiof_init( void )
+{
+ // Setup system valiables
+ //
+ HDC hdc;
+ int dispy;
+ hdc=GetDC(NULL);
+ dispy = GetSystemMetrics( SM_CYSCREEN );
+ ReleaseDC(NULL,hdc);
+
+ // バッファ初期化
+ //
+ lpDest = NULL;
+ lpTex = NULL;
+ maxysize = 0;
+ scanData = NULL;
+ SetupScanData( dispy );
+
+ // カラーキー初期化
+ //
+ ck1 = 0; ck2 = 0; ck3 = 0;
+
+ // テクスチャ情報初期化
+ //
+ TexInit();
+}
+
+void hgiof_term( void )
+{
+ if ( scanData != NULL ) { free( scanData ); scanData = NULL; }
+ lpDest = NULL;
+ TexTerm();
+}
+
+
+void SetPolyDest( void *dest, int sx, int sy )
+{
+ lpDest = (char *)dest;
+ nDestWidth = sx;
+ nDestWByte = ((sx*3)+3)&~3;
+ nDestWidth2 = ((sx)+3)&~3;
+ nDestHeight = sy;
+ DestSize = nDestWByte * sy * 3;
+}
+
+
+void SetPolyColorKey( int color )
+{
+ ck1 = (unsigned char)(color>>16);
+ ck2 = (unsigned char)(color>>8);
+ ck3 = (unsigned char)(color);
+}
+
+/*------------------------------------------------------------*/
+/*
+ Polygon Draw Routines
+*/
+/*------------------------------------------------------------*/
+
+//-----------------------------------------------------
+// Calc Polygon ScanLine Data
+//
+static void ScanLine(POLY4 *lpPolyData, // ポリゴンデータ
+ int nScrWidth, // 描画画面幅
+ int nScrHeight, // 描画画面高さ
+ int *lpnStartY, // 描画を開始する Y 座標(out)
+ int *lpnEndY // 描画を終了する Y 座標(out)
+ )
+{
+ int i,y,v1y,v2y,endY;
+ IAXIS2 *fv1;
+ IAXIS2 *fv2;
+ IAXIS2 *ftmp;
+ SCANDATA *lpScanData;
+
+ double x,dx; // 描画座標計算用
+ double dd;
+ double tx,ty,tdx,tdy; // テクスチャ座標計算用
+
+ // 描画開始位置、終了位置初期化
+ *lpnStartY = nScrHeight;
+ *lpnEndY = -1;
+
+ // スキャンデータ初期化
+ SetupScanData( nScrHeight );
+ lpScanData = scanData;
+
+ for(i=0;i< nScrHeight;i++){
+ lpScanData[i].minX = nScrWidth;
+ lpScanData[i].maxX = -1;
+ }
+
+ // ポリゴンの各辺毎にスキャンする
+ for(i=0;i< POLY4N;i++){
+
+ // 頂点番号セット
+ fv1 = &lpPolyData->v[i];
+ if ( (i+1)v[0]; }
+
+ // 頂点 V1 と V2 の y 軸が同じ時(水平線の時)
+ if( fv1->y == fv2->y ){
+
+ y = fv1->y;
+
+ // 範囲外の時はチェックしない
+ if((y < nScrHeight )&&( y >= 0)){
+
+ // スタート位置計算
+ *lpnStartY = min(y,*lpnStartY);
+ *lpnEndY = max(y,*lpnEndY);
+
+ // 頂点 V1 の方が左になるようにする
+ if( fv1->x > fv2->x ){
+ ftmp = fv1;
+ fv1 = fv2;
+ fv2 = ftmp;
+ }
+
+ // Max と Min の計算
+ if((y >=0 )&&( y < nScrHeight)){
+
+ if( fv1->x < lpScanData[y].minX){
+ lpScanData[y].minX = fv1->x;
+ lpScanData[y].minTx = fv1->tx;
+ lpScanData[y].minTy = fv1->ty;
+ }
+
+ if( fv2->x > lpScanData[y].maxX){
+ lpScanData[y].maxX = fv2->x;
+ lpScanData[y].maxTx = fv2->tx;
+ lpScanData[y].maxTy = fv2->ty;
+ }
+ }
+
+ }
+ }
+ else{ // 頂点 v1 と v2 の y 座標が異なる場合
+
+ // 頂点 V1 の方が上になるようにする
+ if( fv1->y > fv2->y ) {
+ ftmp = fv1;
+ fv1 = fv2;
+ fv2 = ftmp;
+ }
+
+ v1y = fv1->y;
+ v2y = fv2->y;
+
+ // 範囲外の時はチェックしない
+ if((v1y < nScrHeight )||( v2y >= 0)){
+
+ // スタート位置計算
+ *lpnStartY = min(v1y,*lpnStartY);
+ *lpnEndY = max(v2y,*lpnEndY);
+
+ // y が 1 増加した時の描画座標での x の変位と
+ // テクスチャ座標での x と y の変位を計算
+
+ //x 方向の変位計算
+ dd = 1.0f / (double)(v2y-v1y);
+ dx = (double)( fv2->x - fv1->x )*dd;
+ // テクスチャ座標の変位計算
+ tdx = (double)(fv2->tx - fv1->tx)*dd;
+ tdy = (double)(fv2->ty - fv1->ty)*dd;
+
+ // 初期描画座標セット
+ x = (double)fv1->x;
+
+ // 初期テクスチャ座標セット
+ tx = (double)fv1->tx;
+ ty = (double)fv1->ty;
+
+ // サーチ範囲計算
+ endY = min(nScrHeight-1,v2y);
+
+ // 上から順にサーチ開始
+ for(y = v1y; y <= endY; y++){
+
+ // Max と Min の計算
+ //if((y >=0 )&&( y < nScrHeight)){
+ if(y>=0){
+
+ if( x < lpScanData[y].minX){
+ lpScanData[y].minX = (int)x;
+ lpScanData[y].minTx = (int)tx;
+ lpScanData[y].minTy = (int)ty;
+ }
+
+ if( x > lpScanData[y].maxX){
+ lpScanData[y].maxX = (int)x;
+ lpScanData[y].maxTx = (int)tx;
+ lpScanData[y].maxTy = (int)ty;
+ }
+
+ }
+
+ // 座標移動
+ x += dx;
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+ }
+ }
+
+ // スタート位置計算
+ *lpnStartY = max(0,*lpnStartY);
+ *lpnEndY = min(nScrHeight,*lpnEndY);
+}
+
+
+void DrawPolygonF4( POLY4 *lpPolyData )
+{
+ int x,y; // ループ用
+ int nStartY,nEndY; // 描画開始を開始する Y 座標、終了座標
+ int maxX,minX; // エッジ座標の最大最小値
+// char *p;
+ short color1;
+ unsigned char color2;
+
+ DWORD dwScanData,dwDest; // エッジの座標データと転送先のベースアドレス
+// int x0,x1,x2,y0,y1,y2;
+
+ short alpha,alphaop,ialpha;
+ short cc1,cc2,cc3,a1,a2,a3;
+ unsigned char *up;
+
+ // 裏表判定
+/*
+ x0 = lpPolyData->v[0].x;
+ x1 = lpPolyData->v[1].x;
+ x2 = lpPolyData->v[2].x;
+ y0 = lpPolyData->v[0].y;
+ y1 = lpPolyData->v[1].y;
+ y2 = lpPolyData->v[2].y;
+ if ( (x0 - x1) * (y1 - y2) - (x1 - x2) * (y0 - y1) >= 0 ) return;
+*/
+ // エッジの座標のスキャン
+ ScanLine(lpPolyData, nDestWidth,nDestHeight,&nStartY,&nEndY);
+
+ // 範囲外なら描画しない
+ if(nStartY >= nDestHeight || nEndY < 0) { resY0 = resY1 = -1; return; }
+
+ resY0 = nStartY;
+ resY1 = nEndY;
+
+ // Fill Color
+ color1 = (short)(lpPolyData->color & 0xffff);
+ color2 = (unsigned char)((lpPolyData->color & 0xff0000 ) >>16 );
+
+ // 転送先バッファとスキャンデータのベースアドレスセット
+ // 転送先バッファ(DIB)は上下が反転しているのに注意((nDestHeight-1-nStartY)の所)
+
+ dwDest = (DWORD)lpDest + (DWORD)((nDestHeight-1-nStartY)*nDestWByte);
+ dwScanData = (DWORD)scanData + (DWORD)(nStartY*sizeof(SCANDATA));
+
+ // 透明設定を判定
+ //
+ if ( lpPolyData->alpha != 0x100 ) {
+ alphaop = lpPolyData->alpha>>8;
+ alpha = ( lpPolyData->alpha & 255 ) + 1;
+ cc1 = ((color1 & 0xff) * alpha )>>8;
+ cc2 = (((color1>>8)&0xff) * alpha )>>8;
+ cc3 = ((short)(color2) * alpha )>>8;
+
+ if ( alphaop == 0 ) goto f4_blend;
+ if ( alphaop == 2 ) goto f4_modulate;
+ if ( alphaop == 3 ) goto f4_substract;
+ }
+
+ // nStartY から nEndY まで上から順に描画
+ for(y = nStartY; y < nEndY; y++){
+
+ // エッジの(転送先画像(dwDest)上での)座標セット
+ minX = *(int *)(dwScanData);
+ maxX = *(int *)(dwScanData+4);
+
+ if(minX < 0) minX = 0;
+ if(maxX >= 0){
+
+ // 左から右に横に描画していく
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)dwDest + minX*3;
+ for(x = minX; x < maxX; x++){
+
+ // コピー
+ *(short *)up = color1;
+ up[2] = color2; up+=3;
+
+ }
+ }
+ // バッファとスキャンデータのベースアドレス更新
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+
+f4_blend:
+ ialpha = 0x100 - alpha;
+ for(y = nStartY; y < nEndY; y++){
+ minX = *(int *)(dwScanData);
+ maxX = *(int *)(dwScanData+4);
+ if(minX < 0) minX = 0;
+ if(maxX >= 0){
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)dwDest + minX*3;
+ for(x = minX; x < maxX; x++){
+ a1=((((short)up[0])*ialpha)>>8)+cc1;
+ a2=((((short)up[1])*ialpha)>>8)+cc2;
+ a3=((((short)up[2])*ialpha)>>8)+cc3;
+ up[0]=(unsigned char)a1;
+ up[1]=(unsigned char)a2;
+ up[2]=(unsigned char)a3;
+ up+=3;
+ }
+ }
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+
+f4_modulate:
+ for(y = nStartY; y < nEndY; y++){
+ minX = *(int *)(dwScanData);
+ maxX = *(int *)(dwScanData+4);
+ if(minX < 0) minX = 0;
+ if(maxX >= 0){
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)dwDest + minX*3;
+ for(x = minX; x < maxX; x++){
+ a1=cc1+(short)up[0];if (a1>255) a1=255;
+ a2=cc2+(short)up[1];if (a2>255) a2=255;
+ a3=cc3+(short)up[2];if (a3>255) a3=255;
+ up[0]=(unsigned char)a1;
+ up[1]=(unsigned char)a2;
+ up[2]=(unsigned char)a3;
+ up+=3;
+ }
+ }
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+f4_substract:
+ for(y = nStartY; y < nEndY; y++){
+ minX = *(int *)(dwScanData);
+ maxX = *(int *)(dwScanData+4);
+ if(minX < 0) minX = 0;
+ if(maxX >= 0){
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)dwDest + minX*3;
+ for(x = minX; x < maxX; x++){
+ a1=(short)up[0]-cc1;if (a1<0) a1=0;
+ a2=(short)up[1]-cc2;if (a2<0) a2=0;
+ a3=(short)up[2]-cc3;if (a3<0) a3=0;
+ up[0]=(unsigned char)a1;
+ up[1]=(unsigned char)a2;
+ up[2]=(unsigned char)a3;
+ up+=3;
+ }
+ }
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+
+
+}
+
+
+void DrawPolygonTex( POLY4 *lpPolyData )
+{
+ int i2,x,y; // ループ用
+ int nStartY,nEndY; // 描画開始を開始する Y 座標、終了座標
+ int maxX,minX; // エッジ座標の最大最小値
+// int x0,x1,x2,y0,y1,y2;
+ char *p;
+ char *srcp;
+ char d1,d2,d3;
+ DWORD tx,ty,tdx,tdy;
+
+ short alpha,alphaop,ialpha,a1,a2,a3;
+ unsigned char *up;
+ unsigned char *usrcp;
+
+ DWORD dwTexSize; // テクスチャのサイズ
+ DWORD dwScanData,dwDest; // エッジの座標データと転送先のベースアドレス
+
+ // Texture select
+ //if ( lpPolyData->tex != curtex ) ChangeTex( lpPolyData->tex );
+
+ // 裏表判定
+/*
+ x0 = lpPolyData->v[0].x;
+ x1 = lpPolyData->v[1].x;
+ x2 = lpPolyData->v[3].x;
+ y0 = lpPolyData->v[0].y;
+ y1 = lpPolyData->v[1].y;
+ y2 = lpPolyData->v[3].y;
+ if ( (x0 - x1) * (y1 - y2) - (x1 - x2) * (y0 - y1) >= 0 ) return;
+*/
+ // エッジの座標のスキャン
+ dwTexSize = (DWORD)(nTexHeight*nTexWByte);
+ ScanLine( lpPolyData, nDestWidth, nDestHeight, &nStartY, &nEndY );
+
+ // 範囲外なら描画しない
+ if(nStartY >= nDestHeight || nEndY < 0) { resY0 = resY1 = -1; return; }
+
+ resY0 = nStartY;
+ resY1 = nEndY;
+
+ // 転送先バッファとスキャンデータのベースアドレスセット
+ // 転送先バッファ(DIB)は上下が反転しているのに注意((nDestHeight-1-nStartY)の所)
+ p = (char *)lpDest + ((nDestHeight-1-nStartY)*nDestWByte);
+ dwDest = (DWORD)p;
+ dwScanData = (DWORD)scanData + (DWORD)(nStartY*sizeof(SCANDATA));
+
+ // 透明設定を判定
+ //
+ if ( lpPolyData->alpha != 0x100 ) {
+ alphaop = lpPolyData->alpha>>8;
+ alpha = ( lpPolyData->alpha & 255 ) + 1;
+ if ( alphaop == 0 ) goto p4_blend;
+ if ( alphaop == 2 ) goto p4_modulate;
+ if ( alphaop == 3 ) goto p4_substract;
+ }
+ if ( lpPolyData->attr & NODE_ATTR_COLKEY ) goto p4trans;
+
+ //
+ // 透明色なし描画
+ //
+ //
+ // nStartY から nEndY まで上から順に描画
+ for(y = nStartY; y < nEndY; y++){
+
+ // エッジの(転送先画像(dwDest)上での)座標セット
+ minX = *(LPLONG)(dwScanData);
+ maxX = *(LPLONG)(dwScanData+4);
+
+ if(maxX >= 0){
+
+ // テクスチャ座標計算用変数(16 bit 固定少数)
+
+ tx = *(LPLONG)(dwScanData+8);
+ ty = *(LPLONG)(dwScanData+12);
+ tx <<= 16;
+ ty <<= 16;
+
+ // 描画座標で x が 1 増加した時のテクスチャ座標での
+ // x と y の変位を計算
+ if(maxX != minX){
+
+ i2 = 0x10000 / (maxX-minX); // DWORD -> WORD 変換
+ tdx = ((*(LPLONG)(dwScanData+16)-*(LPLONG)(dwScanData+8)))*i2;
+ tdy = ((*(LPLONG)(dwScanData+20)-*(LPLONG)(dwScanData+12)))*i2;
+
+ }
+ else { // 一点の時
+ tdx = 0;
+ tdy = 0;
+ }
+
+ // 左側エッジ(minX)が 0 より小さいなら 0 になるまで回す
+
+ while(minX < 0){
+ minX++;
+ tx += tdx;
+ ty += tdy;
+ }
+
+ // 左から右に横に描画していく
+ maxX = min(nDestWidth,maxX);
+ p = (char *)(dwDest) + minX*3;
+ for(x = minX; x < maxX; x++){
+
+ // テクスチャデータを読み込む点を計算
+ //dwReadPoint = (DWORD)(nTexHeight-1-(ty>>5))*nTexWidth+(tx>>5);
+ //dwReadPoint = (DWORD)(nTexHeight-1-(ty>>16))*nTexWidth+(tx>>16);
+ //dwReadPoint = (DWORD)((ty>>16))*nTexWByte+((tx>>16)*3);
+// i2 = ((tx>>16)*3);
+ i2 = ((ty>>16)*nTexWByte)+((tx>>16)*3);
+
+ // コピー
+ if( i2 < (int)dwTexSize) {
+ srcp = (char *)lpTex + i2;
+ *(short *)p = *(short *)srcp; p+=2; srcp+=2;
+ *p++ = *srcp++;
+ }
+
+ // テクスチャ座標移動
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+
+ // バッファとスキャンデータのベースアドレス更新
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+
+ return;
+
+p4trans:
+ //
+ // 透明色あり描画
+ //
+ //
+ // nStartY から nEndY まで上から順に描画
+ for(y = nStartY; y < nEndY; y++){
+
+ // エッジの(転送先画像(dwDest)上での)座標セット
+ minX = *(LPLONG)(dwScanData);
+ maxX = *(LPLONG)(dwScanData+4);
+
+ if(maxX >= 0){
+
+ // テクスチャ座標計算用変数(16 bit 固定少数)
+
+ tx = *(LPLONG)(dwScanData+8);
+ ty = *(LPLONG)(dwScanData+12);
+ tx <<= 16;
+ ty <<= 16;
+
+ // 描画座標で x が 1 増加した時のテクスチャ座標での
+ // x と y の変位を計算
+ if(maxX != minX){
+
+ i2 = 0x10000 / (maxX-minX); // DWORD -> WORD 変換
+ tdx = ((*(LPLONG)(dwScanData+16)-*(LPLONG)(dwScanData+8)))*i2;
+ tdy = ((*(LPLONG)(dwScanData+20)-*(LPLONG)(dwScanData+12)))*i2;
+
+ }
+ else { // 一点の時
+ tdx = 0;
+ tdy = 0;
+ }
+
+ // 左側エッジ(minX)が 0 より小さいなら 0 になるまで回す
+
+ while(minX < 0){
+ minX++;
+ tx += tdx;
+ ty += tdy;
+ }
+
+ // 左から右に横に描画していく
+ maxX = min(nDestWidth,maxX);
+ p = (char *)(dwDest + minX*3);
+ for(x = minX; x < maxX; x++) {
+
+ // テクスチャデータを読み込む点を計算
+ i2 = ((ty>>16)*nTexWByte)+((tx>>16)*3);
+
+ // コピー
+ if( i2 < (int)dwTexSize) {
+ srcp = (char *)lpTex + i2;
+ d1=*srcp++;
+ d2=*srcp++;
+ d3=*srcp++;
+ if ( d1|d2|d3 ) {
+ p[0] = d1;
+ p[1] = d2;
+ p[2] = d3;
+ }
+ p+=3;
+ }
+
+ // テクスチャ座標移動
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+
+ // バッファとスキャンデータのベースアドレス更新
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+
+p4_blend:
+ //
+ // 描画(BLEND)
+ //
+ //
+ if ( lpPolyData->attr & NODE_ATTR_COLKEY ) goto p4_tblend;
+
+ ialpha = 0x100 - alpha;
+ for(y = nStartY; y < nEndY; y++){
+ minX = *(LPLONG)(dwScanData);
+ maxX = *(LPLONG)(dwScanData+4);
+ if(maxX >= 0){
+ tx = *(LPLONG)(dwScanData+8);
+ ty = *(LPLONG)(dwScanData+12);
+ tx <<= 16;
+ ty <<= 16;
+ if(maxX != minX){
+ i2 = 0x10000 / (maxX-minX); // DWORD -> WORD 変換
+ tdx = ((*(LPLONG)(dwScanData+16)-*(LPLONG)(dwScanData+8)))*i2;
+ tdy = ((*(LPLONG)(dwScanData+20)-*(LPLONG)(dwScanData+12)))*i2;
+ }
+ else {
+ tdx = 0;
+ tdy = 0;
+ }
+ while(minX < 0){
+ minX++;
+ tx += tdx;
+ ty += tdy;
+ }
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)(dwDest + minX*3);
+ for(x = minX; x < maxX; x++) {
+ i2 = ((ty>>16)*nTexWByte)+((tx>>16)*3);
+ if( i2 < (int)dwTexSize) {
+ usrcp = (unsigned char *)lpTex + i2;
+ a1=((((short)usrcp[0])*alpha)+(((short)up[0])*ialpha))>>8;
+ a2=((((short)usrcp[1])*alpha)+(((short)up[1])*ialpha))>>8;
+ a3=((((short)usrcp[2])*alpha)+(((short)up[2])*ialpha))>>8;
+ *up++=(unsigned char)a1;*up++=(unsigned char)a2;*up++=(unsigned char)a3;
+ }
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+
+p4_tblend:
+ //
+ // 透明色あり描画(BLEND)
+ //
+ //
+ ialpha = 0x100 - alpha;
+ for(y = nStartY; y < nEndY; y++){
+ minX = *(LPLONG)(dwScanData);
+ maxX = *(LPLONG)(dwScanData+4);
+ if(maxX >= 0){
+ tx = *(LPLONG)(dwScanData+8);
+ ty = *(LPLONG)(dwScanData+12);
+ tx <<= 16;
+ ty <<= 16;
+ if(maxX != minX){
+ i2 = 0x10000 / (maxX-minX); // DWORD -> WORD 変換
+ tdx = ((*(LPLONG)(dwScanData+16)-*(LPLONG)(dwScanData+8)))*i2;
+ tdy = ((*(LPLONG)(dwScanData+20)-*(LPLONG)(dwScanData+12)))*i2;
+ }
+ else {
+ tdx = 0;
+ tdy = 0;
+ }
+ while(minX < 0){
+ minX++;
+ tx += tdx;
+ ty += tdy;
+ }
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)(dwDest + minX*3);
+ for(x = minX; x < maxX; x++) {
+ i2 = ((ty>>16)*nTexWByte)+((tx>>16)*3);
+ if( i2 < (int)dwTexSize) {
+ usrcp = (unsigned char *)lpTex + i2;
+ if (( usrcp[0]==ck1 )&&( usrcp[1]==ck2 )&&( usrcp[2]==ck3 )) {
+ up+=3;
+ } else {
+ a1=((((short)usrcp[0])*alpha)+(((short)up[0])*ialpha))>>8;
+ a2=((((short)usrcp[1])*alpha)+(((short)up[1])*ialpha))>>8;
+ a3=((((short)usrcp[2])*alpha)+(((short)up[2])*ialpha))>>8;
+ *up++=(unsigned char)a1;*up++=(unsigned char)a2;*up++=(unsigned char)a3;
+ }
+ }
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+
+p4_modulate:
+ //
+ // 描画(MODULATE)
+ //
+ //
+ for(y = nStartY; y < nEndY; y++){
+ minX = *(LPLONG)(dwScanData);
+ maxX = *(LPLONG)(dwScanData+4);
+ if(maxX >= 0){
+ tx = *(LPLONG)(dwScanData+8);
+ ty = *(LPLONG)(dwScanData+12);
+ tx <<= 16;
+ ty <<= 16;
+ if(maxX != minX){
+ i2 = 0x10000 / (maxX-minX); // DWORD -> WORD 変換
+ tdx = ((*(LPLONG)(dwScanData+16)-*(LPLONG)(dwScanData+8)))*i2;
+ tdy = ((*(LPLONG)(dwScanData+20)-*(LPLONG)(dwScanData+12)))*i2;
+ }
+ else {
+ tdx = 0;
+ tdy = 0;
+ }
+ while(minX < 0){
+ minX++;
+ tx += tdx;
+ ty += tdy;
+ }
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)(dwDest + minX*3);
+ for(x = minX; x < maxX; x++) {
+ i2 = ((ty>>16)*nTexWByte)+((tx>>16)*3);
+ if( i2 < (int)dwTexSize) {
+ usrcp = (unsigned char *)lpTex + i2;
+ a1=((((short)usrcp[0])*alpha)>>8)+(short)up[0];
+ if (a1>255) a1=255;
+ a2=((((short)usrcp[1])*alpha)>>8)+(short)up[1];
+ if (a2>255) a2=255;
+ a3=((((short)usrcp[2])*alpha)>>8)+(short)up[2];
+ if (a3>255) a3=255;
+ *up++=(unsigned char)a1;*up++=(unsigned char)a2;*up++=(unsigned char)a3;
+ }
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+
+p4_substract:
+ //
+ // 描画(MODULATE)
+ //
+ //
+ for(y = nStartY; y < nEndY; y++){
+ minX = *(LPLONG)(dwScanData);
+ maxX = *(LPLONG)(dwScanData+4);
+ if(maxX >= 0){
+ tx = *(LPLONG)(dwScanData+8);
+ ty = *(LPLONG)(dwScanData+12);
+ tx <<= 16;
+ ty <<= 16;
+ if(maxX != minX){
+ i2 = 0x10000 / (maxX-minX); // DWORD -> WORD 変換
+ tdx = ((*(LPLONG)(dwScanData+16)-*(LPLONG)(dwScanData+8)))*i2;
+ tdy = ((*(LPLONG)(dwScanData+20)-*(LPLONG)(dwScanData+12)))*i2;
+ }
+ else {
+ tdx = 0;
+ tdy = 0;
+ }
+ while(minX < 0){
+ minX++;
+ tx += tdx;
+ ty += tdy;
+ }
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)(dwDest + minX*3);
+ for(x = minX; x < maxX; x++) {
+ i2 = ((ty>>16)*nTexWByte)+((tx>>16)*3);
+ if( i2 < (int)dwTexSize) {
+ usrcp = (unsigned char *)lpTex + i2;
+ a1=(short)up[0]-((((short)usrcp[0])*alpha)>>8);
+ if (a1<0) a1=0;
+ a2=(short)up[1]-((((short)usrcp[1])*alpha)>>8);
+ if (a2<0) a2=0;
+ a3=(short)up[2]-((((short)usrcp[2])*alpha)>>8);
+ if (a3<0) a3=0;
+ *up++=(unsigned char)a1;*up++=(unsigned char)a2;*up++=(unsigned char)a3;
+ }
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+ dwDest -= nDestWByte;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ palette mode process
+*/
+/*------------------------------------------------------------*/
+
+void DrawPolygonF4P( POLY4 *lpPolyData )
+{
+ int x,y; // ループ用
+ int nStartY,nEndY; // 描画開始を開始する Y 座標、終了座標
+ int maxX,minX; // エッジ座標の最大最小値
+// char *p;
+ unsigned char color1;
+
+ DWORD dwScanData,dwDest; // エッジの座標データと転送先のベースアドレス
+// int x0,x1,x2,y0,y1,y2;
+
+// short alpha,alphaop,ialpha;
+// short cc1,cc2,cc3,a1,a2,a3;
+ unsigned char *up;
+
+ // エッジの座標のスキャン
+ ScanLine(lpPolyData, nDestWidth,nDestHeight,&nStartY,&nEndY);
+
+ // 範囲外なら描画しない
+ if(nStartY >= nDestHeight || nEndY < 0) { resY0 = resY1 = -1; return; }
+
+ resY0 = nStartY;
+ resY1 = nEndY;
+
+ // Fill Color
+ color1 = (unsigned char)( lpPolyData->color & 0xff );
+
+ // 転送先バッファとスキャンデータのベースアドレスセット
+ // 転送先バッファ(DIB)は上下が反転しているのに注意((nDestHeight-1-nStartY)の所)
+
+ dwDest = (DWORD)lpDest + (DWORD)((nDestHeight-1-nStartY)*nDestWidth2);
+ dwScanData = (DWORD)scanData + (DWORD)(nStartY*sizeof(SCANDATA));
+
+ // nStartY から nEndY まで上から順に描画
+ for(y = nStartY; y < nEndY; y++){
+
+ // エッジの(転送先画像(dwDest)上での)座標セット
+ minX = *(int *)(dwScanData);
+ maxX = *(int *)(dwScanData+4);
+
+ if(minX < 0) minX = 0;
+ if(maxX >= 0){
+
+ // 左から右に横に描画していく
+ maxX = min(nDestWidth,maxX);
+ up = (unsigned char *)dwDest + minX;
+ for(x = minX; x < maxX; x++){
+
+ // コピー
+ *up++ = color1;
+
+ }
+ }
+ // バッファとスキャンデータのベースアドレス更新
+ dwDest -= nDestWidth2;
+ dwScanData += sizeof(SCANDATA);
+ }
+}
+
+
+void DrawPolygonTexP( POLY4 *lpPolyData )
+{
+ int i2,x,y; // ループ用
+ int nStartY,nEndY; // 描画開始を開始する Y 座標、終了座標
+ int maxX,minX; // エッジ座標の最大最小値
+ char *p;
+ char d1;
+ DWORD tx,ty,tdx,tdy;
+
+ DWORD dwTexSize; // テクスチャのサイズ
+ DWORD dwScanData,dwDest; // エッジの座標データと転送先のベースアドレス
+
+ // エッジの座標のスキャン
+ dwTexSize = (DWORD)(nTexHeight*nTexWidth);
+ ScanLine( lpPolyData, nDestWidth, nDestHeight, &nStartY, &nEndY );
+
+ // 範囲外なら描画しない
+ if(nStartY >= nDestHeight || nEndY < 0) { resY0 = resY1 = -1; return; }
+
+ resY0 = nStartY;
+ resY1 = nEndY;
+
+ // 転送先バッファとスキャンデータのベースアドレスセット
+ // 転送先バッファ(DIB)は上下が反転しているのに注意((nDestHeight-1-nStartY)の所)
+ p = (char *)lpDest + ((nDestHeight-1-nStartY)*nDestWidth2);
+ dwDest = (DWORD)p;
+ dwScanData = (DWORD)scanData + (DWORD)(nStartY*sizeof(SCANDATA));
+
+ // 透明設定を判定
+ //
+ if ( lpPolyData->attr & NODE_ATTR_COLKEY ) goto p4transp;
+
+ //
+ // 透明色なし描画
+ //
+ //
+ // nStartY から nEndY まで上から順に描画
+ for(y = nStartY; y < nEndY; y++){
+
+ // エッジの(転送先画像(dwDest)上での)座標セット
+ minX = *(LPLONG)(dwScanData);
+ maxX = *(LPLONG)(dwScanData+4);
+
+ if(maxX >= 0){
+
+ // テクスチャ座標計算用変数(16 bit 固定少数)
+
+ tx = *(LPLONG)(dwScanData+8);
+ ty = *(LPLONG)(dwScanData+12);
+ tx <<= 16;
+ ty <<= 16;
+
+ // 描画座標で x が 1 増加した時のテクスチャ座標での
+ // x と y の変位を計算
+ if(maxX != minX){
+
+ i2 = 0x10000 / (maxX-minX); // DWORD -> WORD 変換
+ tdx = ((*(LPLONG)(dwScanData+16)-*(LPLONG)(dwScanData+8)))*i2;
+ tdy = ((*(LPLONG)(dwScanData+20)-*(LPLONG)(dwScanData+12)))*i2;
+
+ }
+ else { // 一点の時
+ tdx = 0;
+ tdy = 0;
+ }
+
+ // 左側エッジ(minX)が 0 より小さいなら 0 になるまで回す
+
+ while(minX < 0){
+ minX++;
+ tx += tdx;
+ ty += tdy;
+ }
+
+ // 左から右に横に描画していく
+ maxX = min(nDestWidth,maxX);
+ p = (char *)(dwDest) + minX;
+ for(x = minX; x < maxX; x++){
+
+ // テクスチャデータを読み込む点を計算
+ i2 = ((ty>>16)*nTexWidth)+(tx>>16);
+
+ // コピー
+ if( i2 < (int)dwTexSize) {
+ *p++ = lpTex[i2];
+ }
+
+ // テクスチャ座標移動
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+
+ // バッファとスキャンデータのベースアドレス更新
+ dwDest -= nDestWidth2;
+ dwScanData += sizeof(SCANDATA);
+ }
+
+ return;
+
+p4transp:
+ //
+ // 透明色あり描画
+ //
+ //
+ // nStartY から nEndY まで上から順に描画
+ for(y = nStartY; y < nEndY; y++){
+
+ // エッジの(転送先画像(dwDest)上での)座標セット
+ minX = *(LPLONG)(dwScanData);
+ maxX = *(LPLONG)(dwScanData+4);
+
+ if(maxX >= 0){
+
+ // テクスチャ座標計算用変数(16 bit 固定少数)
+
+ tx = *(LPLONG)(dwScanData+8);
+ ty = *(LPLONG)(dwScanData+12);
+ tx <<= 16;
+ ty <<= 16;
+
+ // 描画座標で x が 1 増加した時のテクスチャ座標での
+ // x と y の変位を計算
+ if(maxX != minX){
+
+ i2 = 0x10000 / (maxX-minX); // DWORD -> WORD 変換
+ tdx = ((*(LPLONG)(dwScanData+16)-*(LPLONG)(dwScanData+8)))*i2;
+ tdy = ((*(LPLONG)(dwScanData+20)-*(LPLONG)(dwScanData+12)))*i2;
+
+ }
+ else { // 一点の時
+ tdx = 0;
+ tdy = 0;
+ }
+
+ // 左側エッジ(minX)が 0 より小さいなら 0 になるまで回す
+
+ while(minX < 0){
+ minX++;
+ tx += tdx;
+ ty += tdy;
+ }
+
+ // 左から右に横に描画していく
+ maxX = min(nDestWidth,maxX);
+ p = (char *)(dwDest + minX);
+ for(x = minX; x < maxX; x++) {
+
+ // テクスチャデータを読み込む点を計算
+ i2 = ((ty>>16)*nTexWidth)+(tx>>16);
+
+ // コピー
+ if( i2 < (int)dwTexSize) {
+ d1 = lpTex[i2];
+ if ( d1 ) *p=d1;
+ p++;
+ }
+
+ // テクスチャ座標移動
+ tx += tdx;
+ ty += tdy;
+ }
+ }
+
+ // バッファとスキャンデータのベースアドレス更新
+ dwDest -= nDestWidth2;
+ dwScanData += sizeof(SCANDATA);
+ }
+ return;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ texture process
+*/
+/*------------------------------------------------------------*/
+
+/*
+ rev 43
+ mingw : error : 宣言と修飾が異なる
+ に対処
+*/
+
+void TexInit( void )
+{
+ lpTex = NULL;
+}
+
+
+void TexTerm( void )
+{
+}
+
+
+void SetPolySource( void *src, int sx, int sy )
+{
+ lpTex = (char *)src;
+ nTexWidth = sx;
+ nTexWByte = ((nTexWidth*3)+3)&~3;
+ nTexHeight = sy;
+}
+
+
+
+#endif
diff --git a/src/hsp3/win32gui/fcpoly.h b/src/hsp3/win32gui/fcpoly.h
new file mode 100644
index 0000000000000000000000000000000000000000..fdd448272bb5b10cec02d1f257198d1f2a7e9658
--- /dev/null
+++ b/src/hsp3/win32gui/fcpoly.h
@@ -0,0 +1,65 @@
+//
+// fcpoly system structures
+//
+#ifndef __fcpoly_h
+#define __fcpoly_h
+
+#define PI 3.14159265358979f
+#define PI2 6.28318530717958f
+#define HPI 1.570796326794895f
+
+// 整数AXIS2型(UV付き)
+typedef struct {
+short x,y,tx,ty;
+} IAXIS2;
+
+#define setIAXIS( a,b,c ) a.x=(int)b;a.y=(int)c;
+#define setIAXIS2( a,b,c,d,e ) a.x=(int)b;a.y=(int)c;a.tx=(int)d;a.ty=(int)e;
+
+// 四角形ポリゴンprimitive
+#define POLY4N 4
+typedef struct
+{
+short code; // primitive code
+short attr; // attr SW
+short tex; // texture ID
+short npoly; // Num of polygon
+IAXIS2 v[POLY4N]; // XY&UV Vertices
+int color; // color code
+short alpha; // alpha blend value (opt)
+short specular; // specular value (opt)
+} POLY4;
+
+
+// attrコード
+//
+#define NODE_ATTR_COLKEY 0x8000
+
+// スキャンライン情報
+typedef struct
+{
+int minX, maxX; // left,right edge
+int minTx, minTy; // Tex UV of (minX,y)
+int maxTx, maxTy; // Tex UV of (maxX,y)
+} SCANDATA;
+
+
+//
+// function prototypes
+//
+void hgiof_init( void );
+void hgiof_term( void );
+void SetPolyDest( void *dest, int sx, int sy );
+void SetPolySource( void *src, int sx, int sy );
+void SetPolyColorKey( int color );
+void DrawPolygonF4( POLY4 *lpPolyData );
+void DrawPolygonF4P( POLY4 *lpPolyData );
+void DrawPolygonTex( POLY4 *lpPolyData );
+void DrawPolygonTexP( POLY4 *lpPolyData );
+
+void TexInit( void );
+void TexTerm( void );
+
+
+
+#endif
diff --git a/src/hsp3/win32gui/filedlg.cpp b/src/hsp3/win32gui/filedlg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..794bbd3bdf6826ac6babd68187165cdecb84aa88
--- /dev/null
+++ b/src/hsp3/win32gui/filedlg.cpp
@@ -0,0 +1,307 @@
+/*------------------------------------------
+ File Load/Save common dialog routines
+ ------------------------------------------*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "../hsp3debug.h"
+#include "../supio.h"
+
+#ifndef min
+#define min(prm0, prm1) (((prm0) > (prm1)) ? (prm1) : (prm0))
+#endif
+
+static HWND hwbak;
+static OPENFILENAME ofn ;
+static TCHAR szFileName[_MAX_PATH + 1] ;
+static TCHAR szTitleName[_MAX_PATH + 1] ;
+static char FileName8[(_MAX_PATH + 1)*6] ;
+//static char szFilter[128];
+
+
+void PopFileInitialize (HWND hwnd)
+ {
+ ofn.lStructSize = sizeof (OPENFILENAME) ;
+ ofn.hwndOwner = hwnd ;
+ ofn.hInstance = NULL ;
+// ofn.lpstrFilter = szFilter ;
+ ofn.lpstrCustomFilter = NULL ;
+ ofn.nMaxCustFilter = 0 ;
+ ofn.nFilterIndex = 1 ;
+ ofn.nMaxFile = _MAX_PATH ;
+ ofn.lpstrFile = szFileName ;
+ ofn.nMaxFileTitle = _MAX_PATH ;
+ ofn.lpstrFileTitle = szTitleName ;
+ ofn.lpstrInitialDir = NULL ;
+ ofn.lpstrTitle = NULL ;
+ ofn.Flags = 0 ; // Set in Open and Close functions
+ ofn.nFileOffset = 0 ;
+ ofn.nFileExtension = 0 ;
+ ofn.lpstrDefExt = NULL ;
+ ofn.lCustData = 0L ;
+ ofn.lpfnHook = NULL ;
+ ofn.lpTemplateName = NULL ;
+ }
+
+// SJISの1バイト目か調べる
+#define is_sjis1(c) ( ( (unsigned char)(c) >= 0x81 && (unsigned char)(c) <= 0x9F ) || ( (unsigned char)(c) >= 0xE0 && (unsigned char)(c) <= 0xFC ) )
+
+void fd_ini( HWND hwnd, char *extname, char *extinfo )
+{
+ // dialog p1,16,p3/dialog p1,17,p3 と OpenFileDialog/SaveFileDialogに渡すデータの
+ // p1(extname) p3(extinfo) フィルタ用データ
+ // "txt" "テキストファイル" "*.txt\0テキストファイル(*.txt)\0\0"
+ // "txt;*.text" "テキストファイル" "*.txt;*.text\0テキストファイル(*.txt;*.text)\0\0"
+ // "txt;*.text|log" "テキストファイル|ログファイル" "*.txt;*.text\0テキストファイル(*.txt;*.text)\0*.log\0ログファイル(*.log)\0\0"
+ // ";a*.txt" "テキストファイル" "a*.txt\0テキストファイル(a*.txt)\0\0"
+
+ // Shark++
+ // ※ MSも全角を推奨していたし(メニュー文字列だったけど)もう半角捨ててもいいよね...
+ // ってことで"ファイル" は "ファイル" にしました。
+
+#define realloc_filter_buffer() \
+ pszFilterPtr = (LPTSTR)realloc(pszFilter, (nFilterLen + 1)*sizeof(TCHAR)); \
+ if( NULL == pszFilterPtr ) goto out_of_memory; \
+ pszFilter = pszFilterPtr
+
+ // 区切り文字
+ // "|"区切り
+ static const TCHAR DELIMITER_PIPE[] = TEXT("|");
+ static const int DELIMITER_PIPE_LEN= 1;
+ // "\n"区切り
+ static const TCHAR DELIMITER_CR[] = TEXT("\r\n");
+ static const int DELIMITER_CR_LEN = 2;
+ static const TCHAR DEFAULT_DESC[] = TEXT("ファイル");
+ static const TCHAR ALL_FILE_FILTER[] = TEXT("すべてのファイル (*.*)");
+
+ LPTSTR pszFilter = NULL, pszFilterPtr;
+ int nFilterLen;
+ int nFilterSeek;
+ LPTSTR fext_bak = NULL,fext = NULL, fext_next;
+ LPTSTR finf_bak = NULL,finf = NULL, finf_next;
+ int fext_len;
+ int finf_len;
+ bool no_aster;
+ int nFilterIndex;
+
+ szFileName[0]=0;
+ szTitleName[0]=0;
+
+ chartoapichar(extname,&fext_bak);
+ chartoapichar(extinfo,&finf_bak);
+ fext = fext_bak;
+ finf = finf_bak;
+
+ nFilterLen = 0;
+ nFilterSeek = 0;
+
+ for(nFilterIndex = 0;;
+ fext = fext_next + (*DELIMITER_CR == *fext_next && DELIMITER_CR[1] == fext_next[1] ? DELIMITER_CR_LEN : DELIMITER_PIPE_LEN),
+ finf = finf_next + (*DELIMITER_CR == *finf_next && DELIMITER_CR[1] == finf_next[1] ? DELIMITER_CR_LEN : DELIMITER_PIPE_LEN),
+ nFilterIndex++)
+ {
+ // 区切り文字で分割
+ for(fext_next = fext; *fext_next &&
+ *DELIMITER_PIPE != *fext_next && *DELIMITER_CR != *fext_next;
+ fext_next++) {
+#ifndef HSPUTF8
+ // SJISの1バイト目チェック&2文字目を飛ばすときの'\0'チェック
+ if( is_sjis1(*fext_next) && fext_next[1] )
+ fext_next++;
+#endif
+ }
+ for(finf_next = finf; *finf_next &&
+ *DELIMITER_PIPE != *finf_next && *DELIMITER_CR != *finf_next;
+ finf_next++) {
+#ifndef HSPUTF8
+ // SJISの1バイト目チェック&2文字目を飛ばすときの'\0'チェック
+ if( is_sjis1(*finf_next) && finf_next[1] )
+ finf_next++;
+#endif
+ }
+ if( fext_next == fext && finf_next == finf ) {
+ break;
+ }
+
+ fext_len = (int)(fext_next - fext);
+ finf_len = (int)(finf_next - finf);
+
+ if( !*fext_next )
+ fext_next -= DELIMITER_PIPE_LEN;
+ if( !*finf_next )
+ finf_next -= DELIMITER_PIPE_LEN;
+
+ // 拡張子の先頭に';'があった場合は"*."を先頭につけないモードにする
+ no_aster = (TEXT(';') == *fext);
+ if( no_aster ) {
+ fext++;
+ fext_len--;
+ }
+
+ if( 0 == fext_len ||
+ (TEXT('*') == *fext && 1 == fext_len) )
+ {
+ // 拡張子指定が空文字 or "*" の場合はフィルタに登録をしない
+ continue;
+ }
+
+ // デフォルトファイル名指定
+ if( 0 == nFilterIndex ) {
+ if( !no_aster )
+ _tcscat(szFileName, TEXT("*."));
+ _tcsncat(szFileName, fext, min((size_t)fext_len, sizeof(szFileName)/sizeof(szFileName[0]) - 3/* strlen("*.")+sizeof('\0') */));
+ }
+
+ // finf + "(" + "*." + fext + ")" + "\0" + "*." + fext + "\0"
+ nFilterSeek = nFilterLen;
+ nFilterLen += finf_len + 1 + 2 + fext_len + 1 + 1 + 2 + fext_len + 1 + (no_aster ? -4 : 0);
+ if( 0 == finf_len ) {
+ // ファイルの説明が空文字の場合は拡張子+"ファイル"に
+ nFilterLen += fext_len;
+ nFilterLen += (int)_tcslen(DEFAULT_DESC); // ※
+ }
+ realloc_filter_buffer();
+
+ pszFilterPtr = pszFilter + nFilterSeek;
+ *pszFilterPtr = TEXT('\0');
+
+ // フィルタ説明
+ if( 0 == finf_len ) {
+ _tcsncat(pszFilterPtr, fext, (size_t)fext_len);
+ _tcscat(pszFilterPtr, DEFAULT_DESC); // ※
+ } else {
+ _tcsncat(pszFilterPtr, finf, (size_t)finf_len);
+ }
+
+ _tcscat(pszFilterPtr, no_aster ? TEXT("(") : TEXT("(*."));
+ _tcsncat(pszFilterPtr, fext, (size_t)fext_len);
+ _tcscat(pszFilterPtr, TEXT(")"));
+ _tcscat(pszFilterPtr, DELIMITER_PIPE);
+
+ // フィルタ拡張子
+ if( !no_aster )
+ _tcscat(pszFilterPtr, TEXT("*."));
+ _tcsncat(pszFilterPtr, fext, (size_t)fext_len);
+ _tcscat(pszFilterPtr, DELIMITER_PIPE);
+ }
+
+ // "すべてのファイル (*.*)" + "\0" + "*.*" + "\0" + "\0"
+ nFilterSeek = nFilterLen;
+ nFilterLen += (int)_tcslen(ALL_FILE_FILTER) + 1 + (int)_tcslen(TEXT("*.*")) + 1 + 1;
+ realloc_filter_buffer();
+
+ pszFilterPtr = pszFilter + nFilterSeek;
+ *pszFilterPtr = TEXT('\0');
+
+ // フィルタ説明
+ _tcscat(pszFilterPtr, ALL_FILE_FILTER); // ※
+ _tcscat(pszFilterPtr, DELIMITER_PIPE);
+
+ // フィルタ拡張子
+ _tcscat(pszFilterPtr, TEXT("*.*"));
+ _tcscat(pszFilterPtr, DELIMITER_PIPE);
+ _tcscat(pszFilterPtr, DELIMITER_PIPE);
+
+// for(int i = 0; i < nFilterLen-1; i++) if('\0'==pszFilter[i]) pszFilter[i] = '|';
+// MessageBox(NULL,pszFilter,"",0);
+
+ // 区切り文字を'\0'に変換
+ pszFilterPtr = pszFilter;
+ for(nFilterSeek = 0; nFilterSeek < nFilterLen; pszFilterPtr++, nFilterSeek++) {
+#ifndef HSPUTF8
+ if( is_sjis1(*pszFilterPtr) )
+ pszFilterPtr++, nFilterSeek++;
+ else if( *DELIMITER_PIPE == *pszFilterPtr )
+ *pszFilterPtr = TEXT('\0');
+#else
+ if (*DELIMITER_PIPE == *pszFilterPtr )
+ *pszFilterPtr = TEXT('\0');
+#endif
+ }
+
+ PopFileInitialize(hwnd);
+ ofn.lpstrFilter = pszFilter;
+
+ freehac(&fext_bak);
+ freehac(&finf_bak);
+
+#undef realloc_filter_buffer
+
+ return;
+
+out_of_memory:
+ free(pszFilter);
+ throw HSPERR_OUT_OF_MEMORY;
+}
+
+char *fd_getfname( void )
+{
+ HSPCHAR *hctmp1 = 0;
+ int hclen;
+ apichartohspchar(szFileName,&hctmp1);
+ hclen = strlen(hctmp1);
+ memcpy(FileName8,hctmp1,hclen);
+ FileName8[hclen] = '\0';
+ freehc(&hctmp1);
+ return FileName8;
+}
+
+BOOL fd_dialog( HWND hwnd, int mode, char *fext, char *finf )
+{
+ BOOL bResult = FALSE;
+ switch(mode) {
+ case 0:
+ fd_ini( hwnd, fext, finf );
+ ofn.Flags = OFN_HIDEREADONLY | OFN_CREATEPROMPT ;
+ bResult = GetOpenFileName (&ofn) ;
+ free((void*)ofn.lpstrFilter);
+ ofn.lpstrFilter = NULL;
+ break;
+ case 1:
+ fd_ini(hwnd, fext, finf);
+ ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
+ bResult = GetSaveFileName (&ofn) ;
+ free((void*)ofn.lpstrFilter);
+ ofn.lpstrFilter = NULL;
+ break;
+ }
+ return bResult;
+}
+
+
+DWORD fd_selcolor( HWND hwnd, int mode )
+ {
+ BOOL res;
+ static CHOOSECOLOR cc ;
+ static COLORREF crCustColors[16] ;
+
+ cc.lStructSize = sizeof (CHOOSECOLOR) ;
+ cc.hwndOwner = hwnd ;
+ cc.hInstance = NULL ;
+ cc.rgbResult = RGB (0x80, 0x80, 0x80) ;
+ cc.lpCustColors = crCustColors ;
+
+ if (mode)
+ cc.Flags = CC_RGBINIT | CC_FULLOPEN ;
+ else
+ cc.Flags = CC_RGBINIT;
+
+ cc.lCustData = 0L ;
+ cc.lpfnHook = NULL ;
+ cc.lpTemplateName = NULL ;
+
+ res=ChooseColor(&cc) ;
+ if (res) {
+ return (DWORD)cc.rgbResult;
+ }
+/*
+ rev 43
+ mingw : warning : DWORD型の戻り値に-1を返している
+ に対処
+*/
+ return static_cast< DWORD >( -1 );
+ }
diff --git a/src/hsp3/win32gui/filedlg.h b/src/hsp3/win32gui/filedlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa6822480c80f67d72d6b6d227ad571414cc48d0
--- /dev/null
+++ b/src/hsp3/win32gui/filedlg.h
@@ -0,0 +1,7 @@
+
+// in filedlg.cpp functions
+
+BOOL fd_dialog( HWND hwnd, int mode, char *fext, char *finf );
+char *fd_getfname( void );
+DWORD fd_selcolor( HWND hwnd, int mode );
+
diff --git a/src/hsp3/win32gui/hsp3.ico b/src/hsp3/win32gui/hsp3.ico
new file mode 100644
index 0000000000000000000000000000000000000000..709fb4b1f02747aac3f2b58c3773c6aa7fdd3532
Binary files /dev/null and b/src/hsp3/win32gui/hsp3.ico differ
diff --git a/src/hsp3/win32gui/hsp3.rc b/src/hsp3/win32gui/hsp3.rc
new file mode 100644
index 0000000000000000000000000000000000000000..17a4fa1550341610a96b3007f32258afb975c283
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3.rc
@@ -0,0 +1,13 @@
+
+#include "windows.h"
+
+#define IDR_MAIN 128
+
+// RT_MANIFEST
+//
+1 RT_MANIFEST "XPStyle.xml"
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAIN ICON DISCARDABLE "hsp3.ico"
+
diff --git a/src/hsp3/win32gui/hsp3.vcproj b/src/hsp3/win32gui/hsp3.vcproj
new file mode 100644
index 0000000000000000000000000000000000000000..e9ec64178e6aa47bbf9244fbba39b46c29a8fa27
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3.vcproj
@@ -0,0 +1,535 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/hsp3/win32gui/hsp3_vc2008.vcproj b/src/hsp3/win32gui/hsp3_vc2008.vcproj
new file mode 100644
index 0000000000000000000000000000000000000000..a31ac870172b415f0e07a92dd5cc2384ced490a2
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3_vc2008.vcproj
@@ -0,0 +1,541 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/hsp3/win32gui/hsp3_vc2013.vcxproj b/src/hsp3/win32gui/hsp3_vc2013.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..fb6cba22f5fae5a121fc69e5720f039b2b93b0b4
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3_vc2013.vcxproj
@@ -0,0 +1,366 @@
+
+
+
+
+ Debug-unicode
+ Win32
+
+
+ Debug
+ Win32
+
+
+ hsprt-unicode
+ Win32
+
+
+ hsprt
+ Win32
+
+
+ Release-unicode
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ hsp3
+ {05713FB6-5219-4BB5-B965-F30E5040BA7C}
+ hsp3
+ Win32Proj
+
+
+
+ Application
+ v120_xp
+ Unicode
+
+
+ Application
+ v120_xp
+ Unicode
+
+
+ Application
+ v120_xp
+ Unicode
+
+
+ Application
+ v120
+ MultiByte
+
+
+ Application
+ v120
+ MultiByte
+
+
+ Application
+ v120
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>12.0.30501.0
+
+
+ Debug\
+ Debug\
+ true
+ false
+
+
+ Release\
+ Release\
+ false
+ false
+
+
+ $(Configuration)\
+ $(Configuration)\
+ false
+ false
+
+
+ $(Configuration)\
+ $(Configuration)\
+ false
+ false
+ $(ProjectName)utf
+ .hrt
+
+
+ $(Configuration)\
+ $(Configuration)\
+ false
+ false
+ $(ProjectName)utf
+
+
+ $(Configuration)\
+ $(Configuration)\
+ true
+ false
+ $(ProjectName)w
+
+
+
+ Disabled
+ WIN32;HSPWIN;HSPWINGUI;HSPDEBUG;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebug
+
+ Level3
+ EditAndContinue
+
+
+ comctl32.lib;%(AdditionalDependencies)
+ $(OutDir)hsprt.exe
+ true
+ $(OutDir)hsprt.pdb
+ Windows
+ false
+
+ MachineX86
+
+
+
+
+ WIN32;HSPWIN;HSPWINGUI;HSPDEBUG;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ MultiThreaded
+ false
+
+ Level3
+ ProgramDatabase
+
+
+ comctl32.lib;%(AdditionalDependencies)
+ $(OutDir)$(ProjectName).exe
+ true
+ Windows
+ true
+ true
+ false
+
+ MachineX86
+
+
+
+
+
+
+
+ WIN32;HSPWIN;HSPWINGUI;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ MultiThreaded
+ false
+
+ Level3
+ ProgramDatabase
+
+
+ comctl32.lib;%(AdditionalDependencies)
+ $(OutDir)$(ProjectName).exe
+ true
+ Windows
+ true
+ true
+ false
+
+ MachineX86
+
+
+
+
+
+
+
+ WIN32;HSPWIN;HSPWINGUI;HSPUTF8;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ MultiThreaded
+ false
+
+ Level3
+ None
+ Disabled
+
+
+ comctl32.lib;%(AdditionalDependencies)
+ $(OutDir)$(ProjectName)utf$(TargetExt)
+ false
+ Windows
+ true
+ true
+ false
+
+ MachineX86
+
+
+
+
+
+
+
+ WIN32;HSPWIN;HSPWINGUI;HSPDEBUG;HSPUTF8;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ MultiThreaded
+ false
+
+ Level3
+ None
+
+
+ comctl32.lib;%(AdditionalDependencies)
+ $(OutDir)$(ProjectName)utf.exe
+ false
+ Windows
+ true
+ true
+ false
+
+ MachineX86
+
+
+
+
+
+
+
+ Disabled
+ WIN32;HSPWIN;HSPWINGUI;HSPDEBUG;HSPUTF8;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebug
+
+ Level3
+ EditAndContinue
+
+
+ comctl32.lib;%(AdditionalDependencies)
+ $(OutDir)hsprtw.exe
+ true
+ $(OutDir)hsprt.pdb
+ Windows
+ false
+
+ MachineX86
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/hsp3/win32gui/hsp3ext_win.cpp b/src/hsp3/win32gui/hsp3ext_win.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d8082d222d6812a861341af827102e972eafbc8a
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3ext_win.cpp
@@ -0,0 +1,1258 @@
+
+//
+// HSP3 External DLL manager
+// onion software/onitama 2004/6
+//
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include
+#include
+#include
+#include
+
+#include
+
+// Atlのヘッダ
+//#include
+//#include
+//#include
+
+// AtlをDLLからリンクする場合
+#if 0
+#pragma comment(lib, "atl.lib")
+#include
+#define _ATL_DLL_IMPL
+#include
+#endif
+
+#include "../supio.h"
+#include "../hsp3ext.h"
+#include "hsp3extlib.h"
+#include "../hspwnd.h"
+
+#ifdef HSPDISH
+#include "../../hsp3/strbuf.h"
+#else
+#include "../strbuf.h"
+#include "hsp3win.h"
+#endif
+
+
+static HSPCTX *hspctx; // Current Context
+static HSPEXINFO *exinfo; // Info for Plugins
+static int *type;
+static int *val;
+static int *exflg;
+static int reffunc_intfunc_ivalue;
+//static PVal **pmpval;
+
+
+#ifndef HSP_COM_UNSUPPORTED
+
+#include "hspvar_comobj.h"
+#include "hspvar_variant.h"
+#include "comobj_event.h"
+
+static PVal *comres_pval;
+static APTR comres_aptr;
+
+typedef void (CALLBACK *_ATXDLL_INIT)(void);
+typedef HRESULT (CALLBACK *_ATXDLL_GETCTRL)( HWND, void **res );
+static _ATXDLL_INIT fn_atxinit = NULL;
+static _ATXDLL_GETCTRL fn_atxgetctrl = NULL;
+static HINSTANCE hinst_atxdll = NULL;
+static LPTSTR atxwndclass = NULL;
+
+#endif // !defined(HSP_COM_UNSUPPORTED)
+
+
+#define GetPRM(id) (&hspctx->mem_finfo[id])
+#define strp(dsptr) &hspctx->mem_mds[dsptr]
+
+/*------------------------------------------------------------*/
+/*
+ ATL initialization / unitialization routines
+*/
+/*------------------------------------------------------------*/
+
+#ifndef HSP_COM_UNSUPPORTED
+
+
+static void InitAtxDll( void )
+{
+ if ( hinst_atxdll != NULL ) return;
+
+ hinst_atxdll = LoadLibrary( TEXT("Atl71.dll") );
+ if ( hinst_atxdll ) {
+ atxwndclass = TEXT("AtlAxWin71");
+ } else {
+ hinst_atxdll = LoadLibrary( TEXT("Atl.dll") );
+ if ( hinst_atxdll == NULL ) return;
+ atxwndclass = TEXT("AtlAxWin");
+ }
+
+ fn_atxinit = (_ATXDLL_INIT)GetProcAddress( hinst_atxdll, "AtlAxWinInit" );
+ fn_atxgetctrl = (_ATXDLL_GETCTRL)GetProcAddress( hinst_atxdll, "AtlAxGetControl" );
+ if ( fn_atxinit != NULL) fn_atxinit();
+}
+
+static void TermAtxDll( void )
+{
+ // Atl.dll の解放
+ //
+ // ここで解放すると強制終了する場合があるかも
+ // (変数のクリーンアップより先に実行されるのが原因?)
+ //
+ if ( hinst_atxdll == NULL ) return;
+ FreeLibrary( hinst_atxdll );
+ hinst_atxdll = NULL;
+}
+
+#endif // !defined(HSP_COM_UNSUPPORTED)
+
+
+/*------------------------------------------------------------*/
+/*
+ window object support
+*/
+/*------------------------------------------------------------*/
+
+#ifndef HSPDISH
+
+static BMSCR *GetBMSCR( void )
+{
+ HSPEXINFO *exinfo;
+ exinfo = hspctx->exinfo2;
+ return (BMSCR *)exinfo->HspFunc_getbmscr( *(exinfo->actscr) );
+}
+
+
+static void Object_WindowDelete( HSPOBJINFO *info )
+{
+ DestroyWindow( info->hCld );
+ info->hCld = NULL;
+}
+
+
+// static int AddHSPObject( HWND handle, int mode, int addy, PVal *pv, APTR aptr )
+static int AddHSPObject( HWND handle, int mode, int addy )
+{
+ // ウインドゥオブジェクトを追加する
+ //
+ HSPEXINFO *exinfo;
+ HSPOBJINFO obj;
+ BMSCR *bm;
+ int wid, entry, ppy;
+
+ entry = -1;
+
+ if ( handle != NULL ) {
+
+ exinfo = hspctx->exinfo2;
+ wid = *(exinfo->actscr); // アクティブなウインドゥID
+ entry = exinfo->HspFunc_addobj( wid ); // エントリーIDを得る
+ bm = GetBMSCR();
+
+ obj.hCld = handle;
+ obj.owmode = mode;
+ obj.option = 0;
+ obj.bm = bm;
+ obj.func_notice = NULL;
+ obj.func_objprm = NULL;
+ obj.func_delete = Object_WindowDelete;
+
+ exinfo->HspFunc_setobj( wid, entry, &obj );
+
+ ppy = addy; if ( ppy < bm->py ) ppy = bm->py;
+ bm->cy += ppy;
+ }
+
+ hspctx->stat = entry; // システム変数statにIDを入れる
+ return entry;
+}
+
+#endif
+
+/*------------------------------------------------------------*/
+/*
+ COM Object interface
+*/
+/*------------------------------------------------------------*/
+
+#ifndef HSP_COM_UNSUPPORTED
+
+// 一時領域として使用する VARIANT
+static VARIANT comconv_var;
+
+void *comget_variant( VARIANT *var, int *restype, BOOL fvariantret /* = FALSE*/ )
+{
+ // VARIANT型→HSPの型に変換する
+ //
+ int size;
+ BSTR bstr;
+/*
+ rev 43
+ mingw : warning : 定数へのポインタを非定数へのポインタに代入
+ に対処
+*/
+ void const *ptr;
+ if ( fvariantret ) {
+ VariantCopy( &comconv_var, var );
+ *restype = HSPVAR_FLAG_VARIANT;
+ return &comconv_var;
+ }
+
+ VariantCopyInd( &comconv_var, var );
+ switch ( comconv_var.vt ) {
+
+ case VT_R4:
+ VariantChangeType( &comconv_var, &comconv_var, VARIANT_NOVALUEPROP, VT_R8 );
+ case VT_R8:
+ *restype = HSPVAR_FLAG_DOUBLE;
+ return &comconv_var.dblVal;
+
+ case VT_BSTR:
+ // 文字列全体を返すため、ANSI文字列をバイナリデータBSTRとして格納
+ ptr = comconv_var.bstrVal;
+ if ( ptr == NULL ) ptr = L"";
+#ifndef HSPUTF8
+ size = cnvsjis( NULL, (char *)ptr, 0 );
+#else
+ size = cnvu8( NULL, (HSPAPICHAR *)ptr, 0);
+#endif
+ bstr = SysAllocStringByteLen( NULL, size );
+ if ( bstr == NULL ) throw HSPERR_OUT_OF_MEMORY;
+#ifndef HSPUTF8
+ cnvsjis( (char *)bstr, (char *)ptr, size );
+#else
+ cnvu8( (char *)bstr, (HSPAPICHAR *)ptr, size);
+#endif
+ SysFreeString( comconv_var.bstrVal );
+ comconv_var.bstrVal = bstr;
+ *restype = HSPVAR_FLAG_STR;
+ return comconv_var.bstrVal;
+
+ case VT_DISPATCH:
+ case VT_UNKNOWN:
+ *restype = HSPVAR_FLAG_COMSTRUCT;
+ return &comconv_var.punkVal;
+
+ case VT_I2:
+ case VT_UI2:
+ case VT_I1:
+ case VT_UI1:
+ case VT_I8:
+ case VT_UI8:
+ case VT_BOOL:
+ VariantChangeType( &comconv_var, &comconv_var, VARIANT_NOVALUEPROP, VT_I4 );
+ case VT_I4:
+ case VT_UI4:
+ case VT_ERROR:
+ case VT_INT:
+ case VT_UINT:
+ *restype = HSPVAR_FLAG_INT;
+ return &comconv_var.lVal;
+
+ default:
+ if ( comconv_var.vt & VT_ARRAY ) {
+ *restype = HSPVAR_FLAG_VARIANT; // SafeArray は Variant 型変数で扱う
+ return &comconv_var;
+ }
+ throw HSPERR_INVALID_TYPE;
+ }
+}
+
+void comset_variant( VARIANT *var, void *data, int vtype )
+{
+ // HSPの型→VARIANT 型に変換する
+ //
+ IUnknown *punk;
+
+ VariantClear( var );
+ switch( vtype ) {
+ case HSPVAR_FLAG_INT:
+ var->vt = VT_I4;
+ var->lVal = *(int *)data;
+ break;
+ case HSPVAR_FLAG_DOUBLE:
+ var->vt = VT_R8;
+ var->dblVal = *(double *)data;
+ break;
+ case HSPVAR_FLAG_STR:
+ var->vt = VT_BSTR;
+ var->bstrVal = comget_bstr( (char *)data );
+ break;
+ case HSPVAR_FLAG_COMSTRUCT:
+ var->vt = VT_UNKNOWN;
+ var->punkVal = NULL;
+ punk = *(IUnknown **)data;
+ if ( punk == NULL ) break;
+ punk->QueryInterface( IID_IDispatch, (void**)&var->pdispVal );
+ if ( var->pdispVal != NULL ) {
+ var->vt = VT_DISPATCH;
+ } else {
+ var->punkVal = punk;
+ punk->AddRef();
+ }
+ break;
+ case HSPVAR_FLAG_VARIANT:
+ VariantCopy( var, (VARIANT *)data );
+ break;
+ default:
+ throw HSPERR_INVALID_TYPE;
+ }
+}
+
+void comget_variantres( VARIANT *var, HRESULT hr, BOOL noconv )
+{
+ // 返値のVARIANTを変数に反映させる
+ //
+ void *ptr;
+ int restype;
+ hspctx->stat = (int)hr;
+ if ( comres_pval == NULL ) return;
+ if ( noconv ) {
+ // Variant のまま返す
+ code_setva( comres_pval, comres_aptr, HSPVAR_FLAG_VARIANT, var );
+ } else {
+ // 変数を対応する型に変換
+ if ( var->vt != VT_EMPTY ) {
+ ptr = comget_variant( var, &restype );
+ code_setva( comres_pval, comres_aptr, restype, ptr );
+ }
+ }
+}
+
+DISPID get_dispid( IUnknown* punk, char *propname, BOOL *bVariant )
+{
+ // IDispatch の DISPID を取得する
+ //
+ HRESULT hr;
+ IDispatch *disp;
+ DISPID dispid;
+ char *name = propname;
+ LPOLESTR list[]={ (LPOLESTR)(hspctx->stmp) };
+
+ if ( name[0] == '\0' ) return DISPID_VALUE;
+
+ if ( bVariant != NULL ) *bVariant = ( name[0] == '.' );
+ if ( name[0] == '.' ) name++;
+
+ disp = (IDispatch *)punk;
+ cnvwstr( hspctx->stmp, name, HSPCTX_REFSTR_MAX/sizeof(WCHAR)-1 );
+ hr = disp->GetIDsOfNames( IID_NULL, list, 1, LOCALE_SYSTEM_DEFAULT, &dispid );
+
+ if ( FAILED(hr) || dispid == DISPID_UNKNOWN ) throw HSPERR_INVALID_PARAMETER;
+ return dispid;
+}
+
+BSTR comget_bstr( char *ps )
+{
+ int size;
+ BSTR bstr;
+ void *temp;
+ size = cnvwstr( NULL, ps, 0 ) + 1;
+ if ( size * sizeof(WCHAR) > HSPCTX_REFSTR_MAX ) {
+ temp = sbAlloc( size * sizeof(WCHAR) );
+ cnvwstr( temp, ps, size );
+ bstr = SysAllocString( (LPOLESTR)temp );
+ sbFree( temp );
+ } else {
+ cnvwstr( hspctx->stmp, ps, size );
+ bstr = SysAllocString( (LPOLESTR)hspctx->stmp );
+ }
+ return bstr;
+}
+
+
+int call_method( void *iptr, int index, int *prm, int count )
+{
+ int *proc;
+ proc = (*(int **)iptr);
+ proc += index;
+ //Alertf( "%x:%x:%d",proc,*proc,index );
+ return call_extfunc( (void*)*proc, prm, count );
+}
+
+int call_method2( char *prmbuf, const STRUCTDAT *st )
+{
+ // 指定 IID を取得してメソッド呼び出し
+ // (code_expand_next() から呼ばれる)
+ //
+ const LIBDAT *lib;
+ const IID *piid;
+ IUnknown *punk, *punk2;
+ int result;
+ HRESULT hr;
+ // IID 情報を取ってくる
+ lib = &hspctx->mem_linfo[ st->index ];
+ piid = (IID *)strp( lib->nameidx );
+ punk = *(IUnknown **)prmbuf;
+ if ( st->otindex < 0 || punk == NULL ) throw ( HSPERR_COMDLL_ERROR );
+ hr = punk->QueryInterface( *piid, (void**)&punk2 );
+ if ( FAILED(hr) || punk2 == NULL ) throw ( HSPERR_COMDLL_ERROR );
+ *(IUnknown **)prmbuf = punk2;
+ result = call_method( punk2, st->otindex, (int*)prmbuf, st->size / 4 );
+ punk2->Release();
+ return result;
+}
+
+static BOOL GetIIDFromString( IID *iid, char *ps, bool fClsid = false )
+{
+ // SJIS文字列 IID から IID 構造体を得る
+ //
+ // fClsid が真のとき、ProgID からの CLSID 取得を試みる
+ // ProgID の変換に失敗した場合は FALSE を返す
+ // (それ以外のエラーはエラーを throw)
+ //
+ HRESULT hr;
+ cnvwstr( hspctx->stmp, ps, HSPCTX_REFSTR_MAX/sizeof(WCHAR)-1 );
+ if ( *ps == '{' ) {
+ // GUID 文字列 → GUID 構造体
+ hr = IIDFromString( (LPOLESTR)hspctx->stmp, iid );
+ if ( SUCCEEDED(hr) ) return TRUE;
+ }
+ if ( fClsid ) {
+ // ProgID 文字列 → GUID 構造体
+ hr = CLSIDFromProgID( (LPOLESTR)hspctx->stmp, iid );
+ if ( SUCCEEDED(hr) ) return TRUE;
+ return FALSE;
+ }
+ throw ( HSPERR_ILLEGAL_FUNCTION );
+ return FALSE;
+}
+
+#endif // !defined(HSP_COM_UNSUPPORTED)
+
+
+/*------------------------------------------------------------*/
+/*
+ type function
+*/
+/*------------------------------------------------------------*/
+
+static int cmdfunc_ctrlcmd( int cmd )
+{
+ // cmdfunc : TYPE_DLLCTRL
+ // (拡張DLLコントロールコマンド)
+ //
+ code_next(); // 次のコードを取得(最初に必ず必要です)
+
+ if ( cmd >= TYPE_OFFSET_COMOBJ ) {
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ // COM インターフェースメソッドの呼び出し
+ STRUCTDAT *st;
+ st = GetPRM( cmd - TYPE_OFFSET_COMOBJ );
+ hspctx->stat = code_expand_and_call( st );
+ return RUNMODE_RUN;
+#endif
+ }
+
+ switch( cmd ) { // サブコマンドごとの分岐
+
+
+ case 0x00: // newcom
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ {
+ PVal *pval;
+ APTR aptr;
+ IUnknown **ppunkNew, *punkDef;
+ CLSID clsid;
+ char *clsid_name;
+ const IID *piid, *piid2;
+ void *iptr;
+ LIBDAT *lib;
+ STRUCTDAT *st;
+ int inimode;
+
+ // 第1パラメータ:新しいインターフェースポインタを格納する変数
+ // (変数にNULLポインタを格納)
+ aptr = code_getva( &pval );
+ iptr = NULL;
+ code_setva( pval, aptr, TYPE_COMOBJ, &iptr );
+ ppunkNew = (IUnknown **)HspVarCorePtrAPTR( pval, aptr );
+
+ // CLSID / IID 情報を取得
+ if ( !code_getexflg() && *type == TYPE_DLLCTRL ) {
+ // 第2パラメータ:#usecom 登録情報
+ st = code_getcomst();
+ if ( st->otindex != -1 ) throw HSPERR_TYPE_MISMATCH;
+ lib = &hspctx->mem_linfo[ st->index ];
+ if ( lib->clsid == -1 ) throw HSPERR_INVALID_PARAMETER;
+ clsid_name = strp(lib->clsid);
+ piid = (IID *)strp( lib->nameidx );
+ piid2 = NULL;
+ } else {
+ // 第2パラメータ:文字列 CLSID
+ // (IID はデフォルトで IID_IDispatch, サポートされていなければ IID_IUnknown )
+ clsid_name = code_getds("");
+ piid = &IID_IDispatch;
+ piid2 = &IID_IUnknown;
+ }
+ inimode = code_getdi(0); // 初期化モード
+ punkDef = (IUnknown *)code_getdi(0); // デフォルトオブジェクト
+
+ // 新規CLSIDからインスタンスを作成
+ hspctx->stat = 0;
+ switch ( inimode ) {
+ case 0:
+ // 新規にロード
+ if ( clsid_name[0]!='\0' ) {
+ if ( GetIIDFromString(&clsid,clsid_name,true) != FALSE &&
+ SUCCEEDED( CoCreateInstance( clsid, NULL, CLSCTX_SERVER, *piid, (void**)ppunkNew )) &&
+ *ppunkNew != NULL )
+ {
+ break;
+ }
+ if ( piid2 != NULL &&
+ SUCCEEDED( CoCreateInstance( clsid, NULL, CLSCTX_SERVER, *piid2, (void**)ppunkNew )) &&
+ *ppunkNew != NULL )
+ {
+ break;
+ }
+ hspctx->stat = 1;
+ }
+ break;
+ case -2:
+ // オブジェクトを明示的に指定する場合 ( AddRef() あり)
+ if ( punkDef != NULL ) punkDef->AddRef();
+ case -1:
+ // オブジェクトを明示的に指定する場合 ( AddRef() なし)
+ *ppunkNew = punkDef;
+ break;
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ #ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "newcom : pObj=%p : &pObj=%p\n", *ppunkNew, ppunkNew);
+ #endif
+ break;
+ }
+#endif // HSP_COM_UNSUPPORTED
+
+ case 0x01: // querycom
+#ifdef HSP_COM_UNSUPPORTED
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+#else
+ {
+ PVal *pval, *pvalNew;
+ APTR aptr, aptrNew;
+ IUnknown **ppunkDst, **ppunkSrc;
+ IID iid;
+ const IID *piid;
+ void *iptr;
+ STRUCTDAT *st;
+ LIBDAT *lib;
+
+ // 第1パラメータ:新しいインターフェースポインタを格納する変数
+ aptrNew = code_getva( &pvalNew );
+
+ // 第2パラメータ:既存のCOMオブジェクト
+ aptr = code_getva( &pval );
+ if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH );
+ ppunkSrc = (IUnknown **)HspVarCorePtrAPTR( pval, aptr );
+ if ( ! IsVaridComPtr(ppunkSrc) ) throw ( HSPERR_COMDLL_ERROR );
+
+ // IID 情報を取得
+ if ( *type == TYPE_DLLCTRL ) {
+ // 第3パラメータ:#usecom 登録情報
+ st = code_getcomst();
+ if ( st->otindex != -1 ) throw ( HSPERR_TYPE_MISMATCH );
+ lib = &hspctx->mem_linfo[ st->index ];
+ piid = (IID *)strp( lib->nameidx );
+ } else {
+ // 第3パラメータ:文字列 IID
+ GetIIDFromString( &iid, code_gets() );
+ piid = &iid;
+ }
+
+ if ( pvalNew->flag != TYPE_COMOBJ ) {
+ // 代入により型変換
+ iptr = NULL;
+ code_setva( pvalNew, aptrNew, TYPE_COMOBJ, &iptr );
+ }
+ ppunkDst = (IUnknown **)HspVarCorePtrAPTR( pvalNew, aptrNew );
+
+ // query によりインスタンスを得る
+ QueryComPtr( ppunkDst, *ppunkSrc, piid );
+ if ( IsVaridComPtr(ppunkSrc) )
+ hspctx->stat = 0;
+ else
+ hspctx->stat = 1;
+ break;
+ }
+#endif // HSP_COM_UNSUPPORTED
+
+ case 0x02: // delcom
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ {
+ PVal *pval;
+ APTR aptr;
+ IUnknown **ppunk;
+ VARIANT *var;
+ void *ptr;
+
+ // 第1パラメータ:解放するCOMオブジェクト変数
+ aptr = code_getva( &pval );
+ ptr = HspVarCorePtrAPTR( pval, aptr );
+ switch ( pval->flag ) {
+ case TYPE_COMOBJ:
+ ppunk = (IUnknown **)ptr;
+ ReleaseComPtr( ppunk );
+ break;
+ case TYPE_VARIANT:
+ var = (VARIANT *)ptr;
+ VariantClear( var );
+ break;
+ default:
+ throw HSPERR_TYPE_MISMATCH;
+ }
+
+ // このタイミングで一時オブジェクトも削除しちゃう
+ if ( comconv_var.vt != VT_EMPTY ) VariantClear( &comconv_var );
+ break;
+ }
+#endif // HSP_COM_UNSUPPORTED
+
+ case 0x03: // cnvstow
+ {
+#ifndef HSPUTF8
+ PVal *pval;
+ char *ptr;
+ char *ps;
+ int size;
+ ptr = code_getvptr( &pval, &size );
+ ps = code_gets();
+ cnvwstr( ptr, ps, size/2 );
+ break;
+#else
+ PVal *pval;
+ char *ptr;
+ char *ps;
+ int size;
+ int sizew;
+ HSPAPICHAR *hactmp1 = 0;
+ ptr = code_getvptr(&pval, &size);
+ ps = code_gets();
+ chartoapichar(ps, &hactmp1);
+ sizew = wcslen(hactmp1) + 1;
+ if (size <= sizew*(int)sizeof(HSPAPICHAR)){
+ memcpy(ptr, hactmp1, size);
+ ((HSPAPICHAR*)ptr)[size - 1] = TEXT('\0');
+ hspctx->stat = -sizew*sizeof(HSPAPICHAR);
+ }
+ else{
+ memcpy(ptr, hactmp1, (sizew - 1)*sizeof(HSPAPICHAR));
+ ((HSPAPICHAR*)ptr)[sizew - 1] = TEXT('\0');
+ hspctx->stat = sizew*sizeof(HSPAPICHAR);
+ }
+ freehac(&hactmp1);
+ break;
+#endif
+ }
+
+ case 0x04: // comres
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ if ( code_getexflg() ) {
+ comres_pval = NULL;
+ comres_aptr = 0;
+ } else {
+ comres_aptr = code_getva( &comres_pval );
+ }
+ break;
+#endif // HSP_COM_UNSUPPORTED
+
+ case 0x05: // axobj
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ {
+ PVal *pval;
+ APTR aptr;
+ const IID *piid;
+ void *iptr;
+ BMSCR *bm;
+ HWND hwnd;
+ int id,sx,sy;
+ char clsid_name8[1024];
+ HSPAPICHAR *clsid_name = 0;
+ IUnknown **ppunk, *punkObj, *punkObj2;
+ STRUCTDAT *st;
+ LIBDAT *lib;
+ HRESULT hr;
+
+ bm = GetBMSCR();
+
+ // 第1パラメータ:新しいインターフェースポインタを格納する変数
+ // (あらかじめ変数にNULLを格納)
+ aptr = code_getva( &pval );
+ iptr = NULL;
+ code_setva( pval, aptr, TYPE_COMOBJ, &iptr );
+ ppunk = (IUnknown **)HspVarCorePtrAPTR( pval, aptr );
+
+ // オブジェクトの CLSID, ProgID, etc.
+ if ( *type == TYPE_DLLCTRL ) {
+ // 第2パラメータ:#usecom 登録情報から取得
+ st = code_getcomst();
+ if ( st->otindex != -1 ) throw ( HSPERR_TYPE_MISMATCH );
+ lib = &hspctx->mem_linfo[ st->index ];
+ piid = (IID *)strp( lib->nameidx );
+ if ( lib->clsid == -1 ) throw ( HSPERR_INVALID_PARAMETER );
+ strncpy( clsid_name8, strp(lib->clsid), sizeof(clsid_name8)-1 );
+ } else {
+ // 第2パラメータ:文字列 CLSID or ProgID を取得 (IID は IDispatch)
+ piid = &IID_IDispatch;
+ strncpy( clsid_name8, code_gets(), sizeof(clsid_name8)-1 );
+ }
+
+ // コントロールのサイズ
+ sx = code_getdi( bm->sx );
+ sy = code_getdi( bm->sy );
+
+ // ActiveXとしてロード
+ //
+ if ( fn_atxinit == NULL ) throw ( HSPERR_UNSUPPORTED_FUNCTION );
+ hwnd = CreateWindow( atxwndclass, chartoapichar(clsid_name8,&clsid_name),
+ WS_CHILD, // 最初は WS_VISIBLE なし (後で ShowWindow() )
+ bm->cx, bm->cy, sx, sy,
+ bm->hwnd, (HMENU)0, (HINSTANCE)hspctx->instance, NULL );
+ freehac(&clsid_name);
+
+ punkObj2 = NULL;
+ if ( hwnd ) {
+ punkObj = NULL;
+ fn_atxgetctrl( hwnd, (void**)&punkObj );
+ if ( punkObj ) {
+ // 指定 IID が存在するかどうか
+ hr = punkObj->QueryInterface( *piid, (void**)&punkObj2 );
+ punkObj->Release();
+ }
+ }
+ if ( punkObj2 == NULL ) {
+ // 目的オブジェクトではないときコントロールを削除
+ if (hwnd) { DestroyWindow( hwnd ); }
+ hspctx->stat = -1;
+ break;
+ }
+ // COM 型変数に格納
+ *ppunk = punkObj2;
+
+ // HSPのウインドゥオブジェクトとして登録する
+ ShowWindow( hwnd, SW_SHOW );
+ id = AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, sy );
+#ifdef HSP_COMOBJ_DEBUG
+ Alertf( "axobj : pObj=%p : &pObj=%p\n", *ppunk, ppunk);
+ #endif
+ break;
+ }
+#endif // HSP_COM_UNSUPPORTED
+
+ case 0x06: // winobj
+ {
+#ifdef HSPDISH
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ char clsname8[1024];
+ HSPAPICHAR *clsname = 0;
+ char winname8[1024];
+ HSPAPICHAR *winname = 0;
+ HWND hwnd;
+ char *ps;
+ BMSCR *bm;
+ int i;
+ int prm[6];
+
+ ps = code_gets(); strncpy( clsname8, ps, 1023 );
+ ps = code_gets(); strncpy( winname8, ps, 1023 );
+
+ bm = GetBMSCR();
+ for(i=0;i<6;i++) {
+ prm[i] = code_getdi(0);
+ }
+ if ( prm[2] <= 0 ) prm[2] = bm->ox;
+ if ( prm[3] <= 0 ) prm[3] = bm->oy;
+
+ hwnd = CreateWindowEx(
+ (DWORD) prm[0], // 拡張ウィンドウスタイル
+ chartoapichar(clsname8,&clsname), // ウィンドウクラス名
+ chartoapichar(winname8,&winname), // ウィンドウ名
+ (DWORD) prm[1], // ウィンドウスタイル
+ bm->cx, bm->cy, prm[2], prm[3], // X,Y,SIZEX,SIZEY
+ bm->hwnd, // 親ウィンドウのハンドル
+ (HMENU) prm[4], // メニューハンドルまたは子ウィンドウID
+ bm->hInst, // インスタンスハンドル
+ (PVOID) prm[5] // ウィンドウ作成データ
+ );
+ freehac(&clsname);
+ freehac(&winname);
+
+ // AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, prm[3], NULL, 0 ); // HSPのウインドゥオブジェクトとして登録する
+ AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, prm[3] );
+ break;
+#endif // HSPDISH
+ }
+
+ case 0x07: // sendmsg
+ {
+ int p1;
+ WPARAM p2;
+ LPARAM p3;
+ HWND hw;
+ int fl;
+ char *vptr;
+ HSPAPICHAR *hactmp1 = 0;
+ HSPAPICHAR *hactmp2 = 0;
+ hw = (HWND)code_getdi(0);
+ p1 = code_getdi(0);
+
+ vptr = code_getsptr( &fl );
+ if ( fl == TYPE_STRING ) {
+ p2 = (WPARAM)chartoapichar(vptr,&hactmp2);
+ } else {
+ p2 = *(WPARAM *)vptr;
+ }
+
+ vptr = code_getsptr( &fl );
+ if ( fl == TYPE_STRING ) {
+ p3 = (LPARAM)chartoapichar(vptr,&hactmp2);
+ } else {
+ p3 = *(LPARAM *)vptr;
+ }
+
+ //Alertf( "SEND[%x][%x][%x]",p1,p2,p3 );
+ hspctx->stat = (int)SendMessage( hw, p1, p2, p3 );
+ freehac(&hactmp1);
+ freehac(&hactmp2);
+ break;
+ }
+
+ case 0x08: // comevent
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ {
+ PVal *pval;
+ APTR aptr;
+ void* iptr;
+ char *ps;
+ IID iid, *piid;
+ unsigned short *subr;
+ IUnknown **ppunk, **ppunkEvent;
+
+ // 第1パラメータ:イベントハンドラオブジェクト (IEventHandler) を格納する変数
+ // (あらかじめ NULL で初期化)
+ aptr = code_getva( &pval );
+ iptr = NULL;
+ code_setva( pval, aptr, TYPE_COMOBJ, &iptr );
+ ppunkEvent = (IUnknown **)HspVarCorePtrAPTR( pval, aptr );
+
+ // 第2パラメータ:COMオブジェクトを格納した変数
+ aptr = code_getva( &pval );
+ if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH );
+ ppunk = (IUnknown **)HspVarCorePtrAPTR( pval, aptr );
+ if ( ! IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR );
+
+ // 第3パラメータ:コネクションポイントIID (文字列形式)
+ ps = code_getds("");
+ if ( ps[0] != '\0' ) {
+ piid = &iid;
+ GetIIDFromString( piid, ps );
+ } else {
+ piid = NULL; // NULL のときデフォルトIID が自動的に取得される
+ }
+
+ // 第4パラメータ:コールバック用のサブルーチンラベル
+ subr = code_getlb2();
+
+ // イベントハンドラ作成・接続
+ SetComEvent( ppunkEvent, ppunk, piid, subr );
+ #ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "comevent : pEvent=%p : pObj=%p\n", *ppunkEvent, *ppunk);
+ #endif
+ break;
+ }
+#endif // HSP_COM_UNSUPPORTED
+
+ case 0x09: // comevarg
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ {
+ PVal *pval, *pval2;
+ APTR aptr, aptr2;
+ VARIANT *v;
+ void *ptr;
+ int p1,p2;
+ int res;
+ IUnknown **ppunk;
+ VARIANT varTemp;
+
+ // 第1パラメータ:イベントのパラメータを格納する変数
+ aptr = code_getva( &pval );
+
+ // 第2パラメータ:イベントハンドラオブジェクト変数
+ aptr2 = code_getva( &pval2 );
+ if ( pval2->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH );
+ ppunk = (IUnknown **)HspVarCorePtrAPTR( pval2, aptr2 );
+ if ( ! IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR );
+
+ // 第3パラメータ:パラメータインデックス
+ p1 = code_getdi(0);
+
+ // 第4パラメータ:文字列変換フラグ
+ p2 = code_getdi(0);
+
+ // イベントのパラメータ取得
+ v = GetEventArg( *ppunk, p1 );
+ if ( v == NULL ) throw ( HSPERR_ILLEGAL_FUNCTION );
+ switch ( p2 ) {
+ case 0:
+ VariantInit( &varTemp );
+ VariantCopyInd( &varTemp, v );
+ ptr = comget_variant( &varTemp, &res );
+ VariantClear( &varTemp );
+ break;
+ case 1:
+ VariantInit( &varTemp );
+ if FAILED( VariantChangeType( &varTemp, v, VARIANT_ALPHABOOL, VT_BSTR ) )
+ throw ( HSPERR_TYPE_INITALIZATION_FAILED );
+ ptr = comget_variant( &varTemp, &res );
+ VariantClear( &varTemp );
+ break;
+ case 2:
+ ptr = v;
+ res = HSPVAR_FLAG_VARIANT;
+ break;
+ default:
+ throw ( HSPERR_ILLEGAL_FUNCTION );
+ }
+ code_setva( pval, aptr, res, ptr );
+ hspctx->stat = res;
+ break;
+ }
+#endif // HSP_COM_UNSUPPORTED
+
+ case 0x0a: // sarrayconv
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ {
+ PVal *pval1, *pval2;
+ APTR aptr1, aptr2;
+ int convdir, size;
+ VARIANT *variant, varTemp;
+ VARTYPE vt;
+ SAFEARRAY *psa;
+ long lbound, ubound;
+ HRESULT hr;
+
+ aptr1 = code_getva( &pval1 );
+ aptr2 = code_getva( &pval2 );
+ convdir = code_getdi(0);
+ size = code_getdi(0);
+
+ switch ( convdir ) {
+ case 0:
+ case 2:
+ case 4:
+ // 配列変数から SafeArray に変換
+ VariantInit( &varTemp );
+ code_setva( pval1, aptr1, HSPVAR_FLAG_VARIANT, &varTemp );
+ variant = (VARIANT *)HspVarCorePtrAPTR( pval1, aptr1 );
+ VariantClear( variant ); // 一応
+ if ( convdir == 2 ) {
+ // バイナリデータ(一次元のみ)
+ void *ptr = HspVarCorePtrAPTR( pval2, aptr2 );
+ psa = CreateBinarySafeArray( ptr, size, &vt );
+ } else {
+ BOOL bVariant = ( convdir == 4 );
+ psa = ConvVar2SafeArray( pval2, bVariant, &vt );
+ }
+ variant->vt = vt | VT_ARRAY;
+ variant->parray = psa;
+ break;
+ case 1:
+ case 3:
+ // SafeArray から配列変数に変換
+ if ( pval2->flag != HSPVAR_FLAG_VARIANT ) throw HSPERR_INVALID_TYPE;
+ variant = (VARIANT *)HspVarCorePtrAPTR( pval2, aptr2 );
+ if ( (variant->vt & VT_ARRAY) == 0 ) throw HSPERR_INVALID_TYPE;
+ psa = variant->parray;
+ if ( psa == NULL ) throw HSPERR_ARRAY_OVERFLOW;
+ vt = variant->vt & VT_TYPEMASK;
+ if ( vt == VT_EMPTY ) {
+ hr = SafeArrayGetVartype( psa, &vt );
+ if ( FAILED(hr) || vt == VT_EMPTY ) throw HSPERR_INVALID_ARRAYSTORE;
+ }
+ if ( convdir == 1 ) {
+ ConvSafeArray2Var( pval1, psa, vt );
+ } else {
+ // バイナリデータ(一次元のみ)
+ int varsize;
+ void *ptr = HspVarCorePtrAPTR( pval1, aptr1 ); if ( vt != VT_UI1 && vt != VT_I1 ) throw HSPERR_INVALID_TYPE;
+ SafeArrayGetLBound( psa, 1, &lbound );
+ hr = SafeArrayGetUBound( psa, 1, &ubound );
+ if ( FAILED(hr) ) throw HSPERR_ARRAY_OVERFLOW;
+ size = ubound - lbound + 1;
+ HspVarCoreGetBlockSize( pval1, (PDAT*)ptr, &varsize );
+ if ( varsize < size ) throw HSPERR_BUFFER_OVERFLOW;
+ GetBinarySafeArray( ptr, size, psa );
+ }
+ break;
+ default:
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+ }
+ break;
+ }
+#endif // HSP_COM_UNSUPPORTED
+ case 0x0c: // cnvstoa
+#ifndef HSPUTF8
+ throw (HSPERR_UNSUPPORTED_FUNCTION);
+#else
+ {
+ PVal *pval;
+ char *ptr;
+ char *ps;
+ int size;
+ int sizea;
+ HSPAPICHAR *hactmp1 = 0;
+ char *actmp1 = 0;
+ ptr = code_getvptr(&pval, &size);
+ ps = code_gets();
+ chartoapichar(ps, &hactmp1);
+ apichartoansichar(hactmp1, &actmp1);
+ sizea = strlen(actmp1) + 1;
+ if (size <= sizea){
+ memcpy(ptr, actmp1, size - 1);
+ ((char*)ptr)[size - 1] = '\0';
+ hspctx->stat = -sizea;
+ }
+ else{
+ memcpy(ptr, actmp1, sizea - 1);
+ ((char*)ptr)[sizea - 1] = '\0';
+ hspctx->stat = sizea;
+ }
+ freeac(&actmp1);
+ freehac(&hactmp1);
+ break;
+ }
+#endif
+ default:
+ throw ( HSPERR_SYNTAX );
+ }
+ return RUNMODE_RUN;
+}
+
+
+static void *reffunc_ctrlfunc( int *type_res, int arg )
+{
+ // reffunc : TYPE_DLLCTRL
+ // (拡張DLLコントロール関数)
+ //
+ void *ptr;
+ int p1,p2;
+
+ // '('で始まるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM );
+ if ( *val != '(' ) throw ( HSPERR_INVALID_FUNCPARAM );
+ code_next();
+
+ ptr = &reffunc_intfunc_ivalue;
+ *type_res = HSPVAR_FLAG_INT;
+
+ switch( arg ) { // サブコマンドごとの分岐
+ case 0x100: // callfunc
+ {
+ PVal *pval;
+ PDAT *p;
+ pval = code_getpval();
+ p = HspVarCorePtrAPTR( pval, 0 );
+ p1 = code_geti();
+ p2 = code_geti();
+ reffunc_intfunc_ivalue = call_extfunc( (void *)p1, (int *)p, p2 );
+ break;
+ }
+ case 0x101: // cnvwtos
+ {
+#ifndef HSPUTF8
+ PVal *pval;
+ char *sptr;
+ int size;
+ sptr = code_getvptr( &pval, &size );
+ hspctx->stmp = sbExpand( hspctx->stmp, size );
+ ptr = hspctx->stmp;
+ cnvsjis( ptr, sptr, size );
+ *type_res = HSPVAR_FLAG_STR;
+ break;
+#else
+ PVal *pval;
+ wchar_t *sptr;
+ int size;
+ int len;
+ sptr = (wchar_t*)code_getvptr(&pval, &size);
+ len = lstrlen(sptr) * 6 + 1;
+ hspctx->stmp = sbExpand(hspctx->stmp, len);
+ ptr = hspctx->stmp;
+ cnvu8(ptr, sptr, len);
+ *type_res = HSPVAR_FLAG_STR;
+ break;
+#endif
+ }
+
+ case 0x102: // comevdisp
+#ifdef HSP_COM_UNSUPPORTED
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+#else
+ {
+ PVal *pval;
+ APTR aptr;
+ IUnknown **ppunk;
+ // 第1パラメータ:COMオブジェクト変数
+ aptr = code_getva( &pval );
+ if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH );
+ ppunk = (IUnknown **)HspVarCorePtrAPTR( pval, aptr );
+ if ( !IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR );
+
+ // イベントの DISPID 取得
+ reffunc_intfunc_ivalue = GetEventDispID( *ppunk );
+ break;
+ }
+#endif // HSP_COM_UNSUPPORTED
+
+ case 0x103: // libptr
+ {
+ //LIBDAT *lib;
+ STRUCTDAT *st;
+ switch( *type ) {
+ case TYPE_DLLFUNC:
+ case TYPE_MODCMD:
+ p1 = *val;
+ break;
+ case TYPE_DLLCTRL:
+ p1 = *val;
+ if ( p1 >= TYPE_OFFSET_COMOBJ ) {
+ p1 -= TYPE_OFFSET_COMOBJ;
+ break;
+ }
+ default:
+ throw ( HSPERR_TYPE_MISMATCH );
+ }
+ code_next();
+ st = GetPRM( p1 );
+ //lib = &hspctx->mem_linfo[ st->index ];
+ reffunc_intfunc_ivalue = (int)((INT_PTR)st);
+ break;
+ }
+
+ case 0x104: // cnvatos
+#ifndef HSPUTF8
+ throw (HSPERR_UNSUPPORTED_FUNCTION);
+#else
+ {
+ PVal *pval;
+ char *sptr;
+ int size;
+ HSPAPICHAR *hactmp1 = 0;
+ int len;
+ sptr = code_getvptr(&pval, &size);
+ ansichartoapichar(sptr, &hactmp1);
+ len = lstrlen(hactmp1) * 6 + 1;
+ hspctx->stmp = sbExpand(hspctx->stmp, len);
+ ptr = hspctx->stmp;
+ cnvu8(ptr, hactmp1, len);
+ freehac(&hactmp1);
+ *type_res = HSPVAR_FLAG_STR;
+ break;
+ }
+#endif
+
+ default:
+ throw ( HSPERR_SYNTAX );
+ }
+
+ // ')'で終わるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM );
+ if ( *val != ')' ) throw ( HSPERR_INVALID_FUNCPARAM );
+ code_next();
+
+ return ptr;
+}
+
+
+static void *reffunc_dllcmd( int *type_res, int arg )
+{
+ // reffunc : TYPE_DLLFUNC
+ // (拡張DLL関数)
+ //
+
+ // '('で始まるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM );
+ if ( *val != '(' ) throw ( HSPERR_INVALID_FUNCPARAM );
+
+ *type_res = HSPVAR_FLAG_INT;
+ exec_dllcmd( arg, STRUCTDAT_OT_FUNCTION );
+ reffunc_intfunc_ivalue = hspctx->stat;
+
+ // ')'で終わるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM );
+ if ( *val != ')' ) throw ( HSPERR_INVALID_FUNCPARAM );
+ code_next();
+
+ return &reffunc_intfunc_ivalue;
+}
+
+
+static int termfunc_dllcmd( int option )
+{
+ // termfunc : TYPE_DLLCMD
+ //
+#ifndef HSP_COM_UNSUPPORTED
+ VariantClear( &comconv_var );
+ // TermAtxDll();
+#endif
+
+ Hsp3ExtLibTerm();
+ return 0;
+}
+
+void hsp3typeinit_dllcmd( HSP3TYPEINFO *info )
+{
+#ifndef HSP_COM_UNSUPPORTED
+#ifdef HSP_COMOBJ_DEBUG
+ if (fpComDbg == NULL) fpComDbg = fopen( "comobj_dbg.txt", "w");
+#endif
+ InitAtxDll();
+ VariantInit( &comconv_var );
+ comres_pval = NULL;
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
+ hspctx = info->hspctx;
+ exinfo = info->hspexinfo;
+ type = exinfo->nptype;
+ val = exinfo->npval;
+ exflg = exinfo->npexflg;
+
+ info->cmdfunc = cmdfunc_dllcmd;
+ info->reffunc = reffunc_dllcmd;
+ info->termfunc = termfunc_dllcmd;
+
+ Hsp3ExtLibInit( info );
+}
+
+void hsp3typeinit_dllctrl( HSP3TYPEINFO *info )
+{
+ info->cmdfunc = cmdfunc_ctrlcmd;
+ info->reffunc = reffunc_ctrlfunc;
+}
+
diff --git a/src/hsp3/win32gui/hsp3ext_win.h b/src/hsp3/win32gui/hsp3ext_win.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab9719d553494310d890c774cfe1895f5a10d578
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3ext_win.h
@@ -0,0 +1,32 @@
+
+//
+// hsp3ext.cpp header
+//
+#ifndef __hsp3ext_win_h
+#define __hsp3ext_win_h
+
+#include "../hsp3code.h"
+#include "hspvar_comobj.h"
+
+void hsp3typeinit_dllcmd( HSP3TYPEINFO *info );
+void hsp3typeinit_dllctrl( HSP3TYPEINFO *info );
+
+void DeleteHSPObject( int wid, int objid );
+
+#ifndef HSP_COM_UNSUPPORTED
+
+int call_method( void *iptr, int index, int *prm, int prms );
+int call_method2( char *prmbuf, const STRUCTDAT *st );
+
+DISPID get_dispid( IUnknown *punk, char *name, BOOL *bVariant );
+void comset_variant( VARIANT *var, void *data, int vtype );
+void *comget_variant( VARIANT *var, int *restype, BOOL variantret = FALSE );
+BSTR comget_bstr( char *ps );
+
+void comget_variantres( VARIANT *var, HRESULT hr, BOOL noconvret );
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
+
+
+#endif
diff --git a/src/hsp3/win32gui/hsp3extlib.cpp b/src/hsp3/win32gui/hsp3extlib.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..85607713beede4d09793e54ddf66afdcf107afc9
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3extlib.cpp
@@ -0,0 +1,764 @@
+
+//
+// HSP3 External COM manager
+// onion software/onitama 2004/6
+// chokuto 2005/3
+//
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "../hsp3config.h"
+
+#include "../supio.h"
+#include "../hsp3ext.h"
+#include "hsp3extlib.h"
+
+#ifdef HSPDISH
+#include "../../hsp3dish/hspwnd.h"
+#include "../../hsp3/dpmread.h"
+#include "../../hsp3/strbuf.h"
+#else
+#include "../hspwnd.h"
+//#include "hspvar_comobj.h"
+//#include "hsp3win.h"
+#include "../dpmread.h"
+#include "../strbuf.h"
+#endif
+
+static HSPCTX *hspctx; // Current Context
+static HSPEXINFO *exinfo; // Info for Plugins
+static PVal **pmpval;
+
+static int libmax, prmmax, hpimax;
+static MEM_HPIDAT *hpidat;
+
+#define GetPRM(id) (&hspctx->mem_finfo[id])
+#define GetLIB(id) (&hspctx->mem_linfo[id])
+#define strp(dsptr) &hspctx->mem_mds[dsptr]
+
+typedef void (CALLBACK *DLLFUNC)(HSP3TYPEINFO *);
+static DLLFUNC func;
+
+//------------------------------------------------------------//
+
+namespace hsp3 {
+
+//------------------------------------------------------------//
+/*
+ CDllManager
+*/
+//------------------------------------------------------------//
+
+CDllManager::CDllManager()
+ : mModules(), mError( NULL )
+{}
+
+
+CDllManager::~CDllManager()
+{
+ typedef holder_type::iterator Iter;
+ for ( Iter i = mModules.begin(); i != mModules.end(); ++i ) {
+ FreeLibrary( *i );
+ }
+}
+
+
+HMODULE CDllManager::load_library( const char *lpFileName )
+{
+ mError = NULL;
+ HMODULE h;
+
+#ifdef HSPUTF8
+ HSPAPICHAR *hactmp1 = 0;
+ chartoapichar( lpFileName, &hactmp1);
+ h = LoadLibrary(hactmp1);
+ freehac(&hactmp1);
+#else
+ h = LoadLibrary( lpFileName );
+#endif
+
+ try {
+ if ( h != NULL ) mModules.push_front( h );
+ }
+ catch ( ... ) {
+ if ( !FreeLibrary( h ) ) mError = h;
+ h = NULL;
+ }
+ return h;
+}
+
+
+BOOL CDllManager::free_library( HMODULE hModule )
+{
+ typedef holder_type::iterator Iter;
+ mError = NULL;
+ Iter i = std::find( mModules.begin(), mModules.end(), hModule );
+ if ( i == mModules.end() ) return FALSE;
+ BOOL res = FreeLibrary( hModule );
+ if ( res ) {
+ mModules.erase( i );
+ } else {
+ mError = hModule;
+ }
+ return res;
+}
+
+
+BOOL CDllManager::free_all_library()
+{
+ typedef holder_type::iterator Iter;
+ for ( Iter i = mModules.begin(); i != mModules.end(); ++i ) {
+ if ( FreeLibrary( *i ) ) *i = NULL;
+ }
+ mModules.erase( std::remove( mModules.begin(), mModules.end(),
+ static_cast< HMODULE >( NULL ) ), mModules.end() );
+ return ( mModules.empty() ? TRUE : FALSE );
+}
+
+
+HMODULE CDllManager::get_error() const
+{
+ return mError;
+}
+
+//------------------------------------------------------------//
+
+}; //namespace hsp3 {
+
+//------------------------------------------------------------//
+
+hsp3::CDllManager & DllManager()
+{
+ static hsp3::CDllManager dm;
+ return dm;
+}
+
+/*------------------------------------------------------------*/
+/*
+ routines
+*/
+/*------------------------------------------------------------*/
+
+static void BindLIB( LIBDAT *lib, char *name )
+{
+ // ライブラリのバインドを行なう
+ // (name:後から与える時のライブラリ名)
+ //
+ int i;
+ char *n;
+ HINSTANCE hd;
+ if ( lib->flag != LIBDAT_FLAG_DLL ) return;
+ i = lib->nameidx;
+ if ( i < 0 ) {
+ if ( name == NULL ) return;
+ n = name;
+ } else {
+ n = strp(i);
+ }
+ hd = DllManager().load_library( n );
+ if ( hd == NULL ) return;
+ lib->hlib = (void *)hd;
+ lib->flag = LIBDAT_FLAG_DLLINIT;
+}
+
+
+static int BindFUNC( STRUCTDAT *st, char *name )
+{
+ // ファンクションのバインドを行なう
+ // (name:後から与える時のファンクション名)
+ //
+ int i;
+ char *n;
+ LIBDAT *lib;
+ HINSTANCE hd;
+ if (( st->subid != STRUCTPRM_SUBID_DLL )&&( st->subid != STRUCTPRM_SUBID_OLDDLL )) return 4;
+ i = st->nameidx;
+ if ( i < 0 ) {
+ if ( name == NULL ) return 3;
+ n = name;
+ } else {
+ n = strp(i);
+ }
+ lib = GetLIB( st->index );
+ if ( lib->flag != LIBDAT_FLAG_DLLINIT ) {
+ BindLIB( lib, NULL );
+ if ( lib->flag != LIBDAT_FLAG_DLLINIT ) return 2;
+ }
+ hd = (HINSTANCE)(lib->hlib);
+ if ( hd == NULL ) return 1;
+#ifdef HSPUTF8
+ HSPAPICHAR *hactmp1 = 0;
+ char tmp1[512];
+ chartoapichar(n,&hactmp1);
+ cnvsjis(tmp1,(char*)hactmp1,512);
+ st->proc = (void *)GetProcAddress( hd, tmp1 );
+ freehac(&hactmp1);
+#else
+ st->proc = (void *)GetProcAddress( hd, n );
+#endif
+ if ( st->proc == NULL ) return 1;
+ st->subid--;
+ return 0;
+}
+
+
+static void ExitFunc( STRUCTDAT *st )
+{
+ // 終了時関数の呼び出し
+ //
+ int p[16];
+ FARPROC pFn;
+ BindFUNC( st, NULL );
+ pFn = (FARPROC)st->proc;
+ if ( pFn == NULL ) return;
+ p[0] = p[1] = p[2] = p[3] = 0;
+#ifdef HSP64
+ p[4] = p[5] = p[6] = p[7] = 0;
+#endif
+ call_extfunc(fpconv(pFn), p, st->size / 4);
+}
+
+
+static int Hsp3ExtAddPlugin( void )
+{
+ // プラグインの登録
+ //
+ int i;
+ HSPHED *hed;
+ char *ptr;
+ char *libname;
+ char *funcname;
+ HPIDAT *org_hpi;
+ MEM_HPIDAT *hpi;
+ HSP3TYPEINFO *info;
+ HINSTANCE hd;
+ TCHAR tmp[512];
+
+ hed = hspctx->hsphed; ptr = (char *)hed;
+ org_hpi = (HPIDAT *)(ptr + hed->pt_hpidat);
+ hpimax = hed->max_hpi / sizeof(HPIDAT);
+
+ if ( hpimax == 0 ) return 0;
+ hpidat = (MEM_HPIDAT *)malloc(hpimax * sizeof(MEM_HPIDAT));
+ hpi = hpidat;
+
+ for ( i=0;iflag = org_hpi->flag;
+ hpi->option = org_hpi->option;
+ hpi->libname = org_hpi->libname;
+ hpi->funcname = org_hpi->funcname;
+ hpi->libptr = NULL;
+
+ libname = strp(hpi->libname);
+ funcname = strp(hpi->funcname);
+ info = code_gettypeinfo(-1);
+
+ if ( hpi->flag == HPIDAT_FLAG_TYPEFUNC ) {
+ hd = DllManager().load_library( libname );
+ if ( hd == NULL ) {
+#ifdef HSPUTF8
+ TCHAR tmp[512];
+ HSPAPICHAR *haclibname = 0;
+ chartoapichar(libname, &haclibname);
+ _stprintf(tmp, TEXT("No DLL:%s"), haclibname);
+ freehac(&haclibname);
+ AlertW(tmp);
+#else
+ Alertf( "No DLL:%s", libname );
+#endif
+ return 1;
+ }
+ hpi->libptr = (void *)hd;
+#ifdef HSPUTF8
+ HSPAPICHAR *hacfuncname = 0;
+ char tmp2[512];
+ chartoapichar(funcname,&hacfuncname);
+ cnvsjis(tmp2,(char*)hacfuncname,512);
+ func = (DLLFUNC)GetProcAddress( hd, tmp2 );
+#else
+ func = (DLLFUNC)GetProcAddress( hd, funcname );
+#endif
+ if ( func == NULL ) {
+#ifdef HSPUTF8
+ TCHAR tmp[512];
+ HSPAPICHAR *haclibname = 0;
+ chartoapichar(libname, &haclibname);
+ _stprintf(tmp, TEXT("No DLL:%s:%s"), haclibname, hacfuncname);
+ freehac(&haclibname);
+ AlertW(tmp);
+ freehac(&hacfuncname);
+#else
+ Alertf("No DLL:%s:%s", libname, funcname);
+#endif
+ return 1;
+ }
+ func( info );
+ code_enable_typeinfo( info );
+ //Alertf( "%d_%d [%s][%s]", i, info->type, libname, funcname );
+#ifdef HSPUTF8
+ freehac(&hacfuncname);
+#endif
+ }
+ hpi++;
+ org_hpi++;
+ }
+ return 0;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ window object support
+*/
+/*------------------------------------------------------------*/
+
+static BMSCR *GetBMSCR( void )
+{
+ HSPEXINFO *exinfo;
+ exinfo = hspctx->exinfo2;
+ return (BMSCR *)exinfo->HspFunc_getbmscr( *(exinfo->actscr) );
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+int Hsp3ExtLibInit( HSP3TYPEINFO *info )
+{
+ int i;
+ STRUCTDAT *st;
+ char tmp[1024];
+
+ hspctx = info->hspctx;
+ exinfo = info->hspexinfo;
+ pmpval = exinfo->mpval;
+
+ libmax = hspctx->hsphed->max_linfo / sizeof(LIBDAT);
+ prmmax = hspctx->hsphed->max_finfo / sizeof(STRUCTDAT);
+
+ hpidat = NULL;
+
+ if ( Hsp3ExtAddPlugin() ) return 1;
+
+ for(i=0;iindex >= 0 ) {
+ if ( st->otindex & STRUCTDAT_OT_CLEANUP ) {
+ ExitFunc( st ); // クリーンアップ関数を呼び出す
+ }
+ }
+ }
+
+ // HPIDATの解放
+ if (hpidat != NULL) { free( hpidat); hpidat = NULL; }
+
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ code expand function
+*/
+/*------------------------------------------------------------*/
+
+/*
+ rev 43
+ mingw(gcc) 用のコード追加
+*/
+
+#ifndef HSP64
+
+#ifdef _MSC_VER
+
+__declspec( naked ) int __cdecl call_extfunc( void *proc, int *prm, int prms )
+{
+ // 外部関数呼び出し(VC++ のインラインアセンブラを使用)
+ //
+ __asm {
+ push ebp
+ mov ebp,esp
+
+ ;# ebp+8 : 関数のポインタ
+ ;# ebp+12 : 引数が入ったINTの配列
+ ;# ebp+16 : 引数の数(pushする回数)
+
+ ;# パラメータをnp個pushする
+ mov eax, dword ptr [ebp+12]
+ mov ecx, dword ptr [ebp+16]
+ jmp _$push_chk
+
+ _$push:
+ push dword ptr [eax+ecx*4]
+
+ _$push_chk:
+ dec ecx
+ jge _$push
+
+ ;# 関数呼び出し
+ call dword ptr [ebp+8]
+
+ ;# 戻り値は eax に入るのでそのままリターン
+ leave
+ ret
+ }
+}
+
+#elif defined( __GNUC__ )
+
+int __cdecl call_extfunc( void * proc, int * prm, int prms )
+{
+ // 外部関数呼び出し(GCC の拡張インラインアセンブラを使用)
+ int ret = 0;
+ __asm__ volatile (
+ "pushl %%ebp;"
+ "movl %%esp, %%ebp;"
+ "jmp _push_chk;"
+
+ // パラメータをprms個pushする
+ "_push:"
+ "pushl ( %2, %3, 4 );"
+
+ "_push_chk:"
+ "decl %3;"
+ "jge _push;"
+
+ "calll *%1;"
+ "leave;"
+
+ : "=a" ( ret )
+ : "r" ( proc ) , "r" ( prm ), "r" ( prms )
+ );
+ return ret;
+}
+
+#else
+
+int __cdecl call_extfunc( void * proc, int * prm, int prms )
+{
+ return 0;
+}
+
+#endif
+
+#endif
+
+
+int cnvwstr( void *out, char *in, int bufsize )
+{
+ // hspchar->unicode に変換
+ //
+#ifndef HSPUTF8
+ return MultiByteToWideChar( CP_ACP, 0, in, -1, (LPWSTR)out, bufsize );
+#else
+ return MultiByteToWideChar(CP_UTF8, 0, in, -1, (LPWSTR)out, bufsize);
+#endif
+}
+
+
+int cnvsjis( void *out, char *in, int bufsize )
+{
+ // unicode->sjis に変換
+ //
+ return WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)in, -1, (LPSTR)out, bufsize, NULL, NULL);
+}
+
+int cnvu8(void *out, wchar_t *in, int bufsize)
+{
+ // unicode->utf8に変換
+ //
+ return WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)in, -1, (LPSTR)out, bufsize, NULL, NULL);
+}
+
+
+static char *prepare_localstr( char *src, int mode )
+{
+ // DLL 渡しのための文字列を準備する
+ // mode:0=ansi/1=unicode
+ //
+ // 使用後は sbFree() で解放すること
+ //
+ int srcsize;
+ char *dst;
+
+#ifndef HSPUTF8
+
+ if ( mode ) {
+ dst = sbAlloc( (srcsize = cnvwstr(NULL, src, 0)) * sizeof(wchar_t) );
+ cnvwstr( dst, src, srcsize );
+ } else {
+ dst = sbAlloc( (int)strlen(src)+1 );
+ strcpy( dst, src );
+ }
+
+#else
+
+ dst = sbAlloc( (srcsize = cnvwstr(NULL, src, 0)) * sizeof(wchar_t) );
+ cnvwstr( dst, src, srcsize );
+
+ if (mode == 0) {
+ int bufferSize;
+ char * buffer;
+
+ buffer = sbAlloc(bufferSize = cnvsjis(NULL, dst, 0));
+ cnvsjis(buffer, dst, bufferSize);
+
+ sbFree(dst);
+ dst = buffer;
+ }
+
+#endif
+
+ return dst;
+}
+
+static int code_expand_next( char *, const STRUCTDAT *, int );
+
+int code_expand_and_call( const STRUCTDAT *st )
+{
+ // パラメータの取得および関数呼び出し(再帰処理による)
+ //
+ // 通常の DLL 関数呼び出しか COM メソッド呼び出しかどうかは
+ // STRUCTDAT の内容から判断します。
+ //
+ // DLL 関数呼び出し時は st->proc に関数アドレスをセットして
+ // おかなければなりません( BindFUNC() により)。
+ //
+ int result;
+
+#ifdef HSP64
+ char *prmbuf = sbAlloc(st->prmmax * sizeof(INT_PTR));
+#else
+ char *prmbuf = sbAlloc(st->size);
+#endif
+
+ try {
+ result = code_expand_next( prmbuf, st, 0 );
+ }
+ catch (...) {
+ sbFree( prmbuf );
+ throw;
+ }
+ sbFree( prmbuf );
+ return result;
+}
+
+static int code_expand_next( char *prmbuf, const STRUCTDAT *st, int index )
+{
+ // 次のパラメータを取得(および関数呼び出し)(再帰処理)
+ //
+ int result;
+ HSPAPICHAR *hactmp1 = 0;
+ if ( index == st->prmmax ) {
+ // 関数(またはメソッド)の呼び出し
+ //if ( !code_getexflg() ) throw HSPERR_TOO_MANY_PARAMETERS;
+ switch ( st->subid ) {
+ case STRUCTPRM_SUBID_DLL:
+ case STRUCTPRM_SUBID_DLLINIT:
+ case STRUCTPRM_SUBID_OLDDLL:
+ case STRUCTPRM_SUBID_OLDDLLINIT:
+ // 外部 DLL 関数の呼び出し
+#ifdef HSP64
+ result = call_extfunc(st->proc, (INT_PTR *)prmbuf, st->prmmax);
+#else
+ result = call_extfunc(st->proc, (INT_PTR *)prmbuf, st->size / sizeof(INT_PTR));
+#endif
+ break;
+#ifndef HSP_COM_UNSUPPORTED
+ case STRUCTPRM_SUBID_COMOBJ:
+ // COM メソッドの呼び出し
+ result = call_method2( prmbuf, st );
+ break;
+#endif
+ default:
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+ }
+ return result;
+ }
+
+ STRUCTPRM *prm = &hspctx->mem_minfo[ st->prmindex + index ];
+ void *out;
+#ifdef HSP64
+ out = &((INT_PTR *)prmbuf)[index];
+#else
+ out = prmbuf + prm->offset;
+#endif
+
+ int srcsize;
+ PVal *pval_dst, *mpval;
+ APTR aptr;
+ PVal *pval;
+ int chk;
+ // 以下のポインタ(またはオブジェクト)は呼出し後に解放
+ void *localbuf = NULL;
+ IUnknown *punklocal = NULL;
+
+ switch ( prm->mptype ) {
+
+ case MPTYPE_INUM:
+ *(UINT_PTR *)out = (UINT_PTR)code_getdi(0);
+ break;
+ case MPTYPE_PVARPTR:
+ aptr = code_getva( &pval );
+ *(void **)out = HspVarCorePtrAPTR( pval, aptr );
+ break;
+ case MPTYPE_LOCALSTRING:
+ case MPTYPE_LOCALWSTR:
+ *(void **)out = localbuf = prepare_localstr( code_gets(), prm->mptype == MPTYPE_LOCALWSTR );
+ break;
+ case MPTYPE_DNUM:
+ *(double *)out = code_getdd(0.0);
+ break;
+ case MPTYPE_FLOAT:
+ *(float *)out = (float)code_getdd(0.0);
+ break;
+ case MPTYPE_PPVAL:
+ aptr = code_getva( &pval );
+ localbuf = sbAlloc( sizeof(PVal) );
+ pval_dst = (PVal *)localbuf;
+ *pval_dst = *pval;
+ if ( pval->flag & HSPVAR_SUPPORT_FLEXSTORAGE ) { // ver2.5互換のための変換
+ HspVarCoreGetBlockSize( pval, HspVarCorePtrAPTR( pval, aptr ), &srcsize );
+ pval_dst->len[1] = (srcsize+3)/4;
+ pval_dst->len[2] = 1;
+ pval_dst->len[3] = 0;
+ pval_dst->len[4] = 0;
+ }
+ *(void **)out = pval_dst;
+ break;
+ case MPTYPE_PBMSCR:
+ *(void **)out = GetBMSCR();
+ break;
+ case MPTYPE_FLEXSPTR:
+ case MPTYPE_FLEXWPTR:
+ chk = code_get();
+ if ( chk<=PARAM_END ) throw ( HSPERR_NO_DEFAULT );
+ mpval = *pmpval;
+ switch( mpval->flag ) {
+ case HSPVAR_FLAG_INT:
+ *(UINT_PTR *)out = (UINT_PTR)(*(int *)(mpval->pt));
+ break;
+ case HSPVAR_FLAG_STR:
+ *(void ** )out = localbuf = prepare_localstr( mpval->pt, prm->mptype == MPTYPE_FLEXWPTR );
+ break;
+ default:
+ throw ( HSPERR_TYPE_MISMATCH );
+ }
+ break;
+ case MPTYPE_PTR_REFSTR:
+ *(void **)out = hspctx->refstr;
+ break;
+ case MPTYPE_PTR_EXINFO:
+ *(void **)out = exinfo;
+ break;
+ case MPTYPE_PTR_DPMINFO:
+ dpm_getinf( hspctx->refstr );
+ *(void **)out = hspctx->refstr;
+ break;
+ case MPTYPE_NULLPTR:
+ *(void **)out = NULL;
+ break;
+#ifndef HSP_COM_UNSUPPORTED
+ case MPTYPE_IOBJECTVAR:
+ aptr = code_getva( &pval );
+ if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH );
+ punklocal = *(IUnknown **)HspVarCorePtrAPTR( pval, aptr );
+ if ( punklocal ) punklocal->AddRef(); // 呼出し後に解放する
+ *(void **)out = (void *)punklocal;
+ break;
+#endif
+ default:
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+ }
+
+ // 次のパラメータの取り出し(再帰的に処理)
+ // (例外処理により動的確保したオブジェクトを確実に解放する)
+ try {
+ result = code_expand_next( prmbuf, st, index + 1 );
+ }
+ catch (...) {
+ if ( localbuf ) sbFree( localbuf );
+ if ( punklocal ) punklocal->Release();
+ throw;
+ }
+ if ( localbuf ) sbFree( localbuf );
+ if ( punklocal ) punklocal->Release();
+ return result;
+}
+
+int exec_dllcmd( int cmd, int mask )
+{
+ STRUCTDAT *st;
+ FARPROC pFn;
+ int result;
+
+ code_next(); // 次のコードを取得(最初に必ず必要です)
+
+ if ( cmd >= prmmax ) {
+ throw ( HSPERR_UNSUPPORTED_FUNCTION );
+ }
+
+ st = GetPRM(cmd);
+ pFn = (FARPROC)st->proc;
+ if ( pFn == NULL ) {
+ if ( BindFUNC( st, NULL ) ) throw ( HSPERR_DLL_ERROR );
+ pFn = (FARPROC)st->proc;
+ }
+ if (( st->otindex & mask ) == 0 ) throw ( HSPERR_SYNTAX );
+
+ result = code_expand_and_call( st );
+
+ if ( st->subid == STRUCTPRM_SUBID_OLDDLLINIT ) {
+ if ( result > 0 ) {
+ if ( result & 0x20000 ) {
+ result &= 0x1ffff;
+ } else if ( result & 0x10000 ) {
+ result = ( result & 0xffff ) * 10;
+ } else {
+ throw ( HSPERR_DLL_ERROR );
+ }
+ hspctx->waitcount = result;
+ hspctx->waittick = -1;
+ hspctx->runmode = RUNMODE_AWAIT;
+ return RUNMODE_AWAIT;
+ }
+ hspctx->stat = -result;
+ } else {
+ hspctx->stat = result;
+ }
+
+ return RUNMODE_RUN;
+}
+
+int cmdfunc_dllcmd( int cmd )
+{
+ // cmdfunc : TYPE_DLLCMD
+ // (拡張DLLコマンド)
+ //
+ return exec_dllcmd( cmd, STRUCTDAT_OT_STATEMENT );
+}
+
diff --git a/src/hsp3/win32gui/hsp3extlib.h b/src/hsp3/win32gui/hsp3extlib.h
new file mode 100644
index 0000000000000000000000000000000000000000..31a52ed49be783bd4b8954876b05196f9380d75c
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3extlib.h
@@ -0,0 +1,85 @@
+
+//
+// hsp3extlib.cpp header
+//
+#ifndef __hsp3extlib_h
+#define __hsp3extlib_h
+
+#include "../hsp3code.h"
+
+#include
+#include
+
+//------------------------------------------------------------//
+
+namespace hsp3 {
+
+//------------------------------------------------------------//
+/*
+ 拡張プラグイン・dllの管理クラス。
+*/
+//------------------------------------------------------------//
+
+class CDllManager
+{
+ typedef std::deque< HMODULE > holder_type;
+
+ //............................//
+
+public:
+ CDllManager();
+ ~CDllManager();
+
+ HMODULE load_library( const char *lpFileName );
+ BOOL free_library( HMODULE hModule );
+ BOOL free_all_library();
+ HMODULE get_error() const;
+
+private:
+ // uncopyable;
+ CDllManager( CDllManager const & );
+ CDllManager const & operator =( CDllManager const & );
+
+ //............................//
+
+private:
+ holder_type mModules;
+ HMODULE mError;
+};
+
+//------------------------------------------------------------//
+
+}; //namespace hsp3 {
+
+//------------------------------------------------------------//
+
+hsp3::CDllManager & DllManager();
+
+int Hsp3ExtLibInit( HSP3TYPEINFO *info );
+void Hsp3ExtLibTerm( void );
+
+int cmdfunc_dllcmd( int cmd );
+int exec_dllcmd( int cmd, int mask );
+int code_expand_and_call( const STRUCTDAT *st );
+
+#ifdef HSP64
+
+extern "C" INT_PTR CallFunc64(INT_PTR *, FARPROC, int);
+#define call_extfunc(externalFunction, arguments, numberOfArguments) CallFunc64((INT_PTR *)arguments, (FARPROC)externalFunction, numberOfArguments)
+
+#else
+
+#if defined( __GNUC__ )
+int __cdecl call_extfunc( void *proc, int *prm, int prms ) __attribute__(( noinline ));
+#else
+int __cdecl call_extfunc( void *proc, int *prm, int prms );
+#endif
+
+#endif
+
+
+int cnvwstr( void *out, char *in, int bufsize );
+int cnvsjis( void *out, char *in, int bufsize );
+int cnvu8( void *out, wchar_t *in, int bufsize);
+
+#endif
diff --git a/src/hsp3/win32gui/hsp3gr_wingui.cpp b/src/hsp3/win32gui/hsp3gr_wingui.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..320c819276b033461c85a5e0abf862c16d923fe5
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3gr_wingui.cpp
@@ -0,0 +1,1867 @@
+
+//
+// HSP3 graphics command
+// (GUI関連コマンド・関数処理)
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../hspwnd.h"
+#include "mmman.h"
+#include "filedlg.h"
+#include "../supio.h"
+#include "../dpmread.h"
+#include "../stack.h"
+#include "../strbuf.h"
+#include "fcpoly.h"
+
+#include "../hsp3gr.h"
+#include "../hsp3code.h"
+#include "../hsp3debug.h"
+
+#ifdef HSPUTF8
+#pragma execution_character_set("utf-8")
+#endif
+
+/*------------------------------------------------------------*/
+/*
+ system data
+*/
+/*------------------------------------------------------------*/
+
+static HspWnd *wnd;
+static MMMan *mmman;
+static Bmscr *bmscr;
+static HSPCTX *ctx;
+static int *type;
+static int *val;
+static int cur_window;
+static int ckey,cklast,cktrg;
+static int msact;
+static int dispflg;
+
+extern int resY0, resY1; // "fcpoly.h"のパラメーター
+
+#define GSQUARE_MODE_TEXTURE 0
+#define GSQUARE_MODE_COLORFILL 1
+#define GSQUARE_MODE_GRADFILL 2
+
+/*----------------------------------------------------------*/
+// HSP system support
+/*----------------------------------------------------------*/
+
+void ExecFile( char *stmp, char *ps, int mode )
+{
+ int i,j;
+ HSPAPICHAR *hactmp1 = 0;
+ HSPAPICHAR *hactmp2 = 0;
+ char *p;
+ j=SW_SHOWDEFAULT;if (mode&2) j=SW_SHOWMINIMIZED;
+
+ if ( *ps != 0 ) {
+ SHELLEXECUTEINFO exinfo;
+ memset( &exinfo, 0, sizeof(SHELLEXECUTEINFO) );
+ exinfo.cbSize = sizeof(SHELLEXECUTEINFO);
+ exinfo.fMask = SEE_MASK_INVOKEIDLIST;
+ exinfo.hwnd = bmscr->hwnd;
+ exinfo.lpVerb = chartoapichar(ps,&hactmp1);
+ exinfo.lpFile = chartoapichar(stmp,&hactmp2);
+ exinfo.nShow = SW_SHOWNORMAL;
+ if ( ShellExecuteEx( &exinfo ) == false ) {
+ freehac(&hactmp1);
+ freehac(&hactmp2);
+ throw HSPERR_EXTERNAL_EXECUTE;
+ }
+ freehac(&hactmp1);
+ freehac(&hactmp2);
+ return;
+ }
+
+ if ( mode&16 ) {
+ i = (int)(INT_PTR)ShellExecute( NULL,NULL,chartoapichar(stmp,&hactmp1),TEXT(""),TEXT(""),j );
+ freehac(&hactmp1);
+ }
+ else if ( mode&32 ) {
+ i = (int)(INT_PTR)ShellExecute( NULL,TEXT("print"),chartoapichar(stmp,&hactmp1),TEXT(""),TEXT(""),j );
+ freehac(&hactmp1);
+ }
+ else {
+ apichartohspchar(chartoapichar(stmp,&hactmp1),&p);
+ freehac(&hactmp1);
+ i=WinExec( p,j );
+ freehc(&p);
+
+ }
+ if (i<32) throw HSPERR_EXTERNAL_EXECUTE;
+}
+
+
+
+/*
+#define CSIDL_DESKTOP 0x0000
+#define CSIDL_INTERNET 0x0001
+#define CSIDL_PROGRAMS 0x0002
+#define CSIDL_CONTROLS 0x0003
+#define CSIDL_PRINTERS 0x0004
+#define CSIDL_PERSONAL 0x0005
+#define CSIDL_FAVORITES 0x0006
+#define CSIDL_STARTUP 0x0007
+#define CSIDL_RECENT 0x0008
+#define CSIDL_SENDTO 0x0009
+#define CSIDL_BITBUCKET 0x000a
+#define CSIDL_STARTMENU 0x000b
+#define CSIDL_DESKTOPDIRECTORY 0x0010
+#define CSIDL_DRIVES 0x0011
+#define CSIDL_NETWORK 0x0012
+#define CSIDL_NETHOOD 0x0013
+#define CSIDL_FONTS 0x0014
+#define CSIDL_TEMPLATES 0x0015
+#define CSIDL_COMMON_STARTMENU 0x0016
+#define CSIDL_COMMON_PROGRAMS 0X0017
+#define CSIDL_COMMON_STARTUP 0x0018
+#define CSIDL_COMMON_DESKTOPDIRECTORY 0x0019
+#define CSIDL_APPDATA 0x001a
+#define CSIDL_PRINTHOOD 0x001b
+#define CSIDL_ALTSTARTUP 0x001d // DBCS
+#define CSIDL_COMMON_ALTSTARTUP 0x001e // DBCS
+#define CSIDL_COMMON_FAVORITES 0x001f
+#define CSIDL_INTERNET_CACHE 0x0020
+#define CSIDL_COOKIES 0x0021
+#define CSIDL_HISTORY 0x0022
+*/
+
+static char *getdir( int id )
+{
+ // dirinfo命令の内容をstmpに設定する
+ //
+ char *p;
+ TCHAR pw[_MAX_PATH+1];
+ char *ss;
+ TCHAR fname[_MAX_PATH+1];
+ char *resp8;
+ p = ctx->stmp;
+
+ switch( id ) {
+ case 0: // カレント(現在の)ディレクトリ
+ _tgetcwd( pw, _MAX_PATH );
+ break;
+ case 1: // HSPの実行ファイルがあるディレクトリ
+ GetModuleFileName( NULL,fname,_MAX_PATH );
+ getpathW( fname, pw, 32 );
+ break;
+ case 2: // Windowsディレクトリ
+ GetWindowsDirectory( pw, _MAX_PATH );
+ break;
+ case 3: // Windowsのシステムディレクトリ
+ GetSystemDirectory( pw, _MAX_PATH );
+ break;
+ case 4: // コマンドライン文字列
+ ss = ctx->cmdline;
+ sbStrCopy( &(ctx->stmp), ss );
+ p = ctx->stmp;
+ return p;
+ case 5: // HSPTV素材があるディレクトリ
+#if defined(HSPDEBUG)||defined(HSP3IMP)
+ GetModuleFileName( NULL,fname,_MAX_PATH );
+ apichartohspchar(fname,&resp8);
+ getpath( resp8, p, 32 );
+ freehc(&resp8);
+ CutLastChr( p, '\\' );
+ strcat( p, "\\hsptv\\" );
+ return p;
+#else
+ p[0] = '\0';
+ return p;
+#endif
+ break;
+ default:
+ if ( id & 0x10000 ) {
+ SHGetSpecialFolderPath( NULL, pw, id & 0xffff, FALSE );
+ break;
+ }
+ throw HSPERR_ILLEGAL_FUNCTION;
+ }
+ apichartohspchar(pw,&resp8);
+ sbStrCopy( &(ctx->stmp),resp8);
+ freehc(&resp8);
+ p=ctx->stmp;
+ // 最後の'\\'を取り除く
+ //
+ CutLastChr( p, '\\' );
+ return p;
+}
+
+
+static int sysinfo( int p2 )
+{
+ // System strings get
+ //
+ int fl;
+ TCHAR pp[128];
+ char *p3;
+ BOOL success;
+ DWORD version;
+ DWORD size;
+ DWORD *mss;
+ SYSTEM_INFO si;
+ MEMORYSTATUS ms;
+ int plen;
+ char *p;
+
+ fl = HSPVAR_FLAG_INT;
+ p3 = ctx->stmp;
+ size = _MAX_PATH;
+
+ if (p2&16) {
+ GetSystemInfo(&si);
+ }
+ if (p2&32) {
+ GlobalMemoryStatus(&ms);
+ mss=(DWORD *)&ms;
+ *(int *)p3 = (int)mss[p2&15];
+ return fl;
+ }
+
+ switch(p2) {
+ case 0:
+ _tcscpy((TCHAR*)p3,TEXT("Windows"));
+ version = GetVersion();
+ if ((version & 0x80000000) == 0) _tcscat((TCHAR*)p3,TEXT("NT"));
+ else _tcscat((TCHAR*)p3,TEXT("9X"));
+/*
+ rev 43
+ mingw : warning : 仮引数int 実引数long unsigned
+ に対処
+*/
+ _stprintf( pp,TEXT(" ver%d.%d"), static_cast< int >( version&0xff ), static_cast< int >( (version&0xff00)>>8 ) );
+ _tcscat( (TCHAR*)p3, pp );
+ apichartohspchar((TCHAR*)p3,&p);
+ plen = strlen(p);
+ if (p3 != p){
+ memcpy(p3, p, plen);
+ p3[plen] = '\0';
+ }
+ freehc(&p);
+ fl=HSPVAR_FLAG_STR;
+ break;
+ case 1:
+ success = GetUserName( (TCHAR*)p3,&size );
+ apichartohspchar((TCHAR*)p3,&p);
+ plen = strlen(p);
+ if (p3 != p){
+ memcpy(p3, p, plen);
+ p3[plen] = '\0';
+ }
+ freehc(&p);
+ fl = HSPVAR_FLAG_STR;
+ break;
+ case 2:
+ success = GetComputerName((TCHAR*)p3, &size );
+ apichartohspchar((TCHAR*)p3,&p);
+ plen = strlen(p);
+ if (p3 != p){
+ memcpy(p3, p, plen);
+ p3[plen] = '\0';
+ }
+ freehc(&p);
+ fl = HSPVAR_FLAG_STR;
+ break;
+ case 16:
+ *(int *)p3 = (int)si.dwProcessorType;
+ break;
+ case 17:
+ *(int *)p3 = (int)si.dwNumberOfProcessors;
+ break;
+ default:
+ throw HSPERR_ILLEGAL_FUNCTION;
+ }
+ return fl;
+}
+
+
+static int chgdisp( int mode, int sx, int sy )
+{
+ // change display setting
+ // mode : 0=return to original
+ // 1=640x480 full-color mode
+ // 2=640x480 pal-mode
+ DEVMODE dev;
+ int a,c,f,sc,sel,res;
+ int maxcol;
+ if (mode) {
+ sc=mode-1;
+ } else {
+ if (dispflg==0) return 1;
+ ChangeDisplaySettings( NULL, 0 );
+ dispflg = 0;
+ return 0;
+ }
+ a=0;sel=-1;maxcol=0;
+ while(1) {
+ f=EnumDisplaySettings( NULL,a,&dev );
+ if (f==0) break;
+/*
+ rev 43
+ mingw : warning : 有符号型と無符号型の比較
+ に対処
+*/
+ if ( static_cast< int >( dev.dmPelsWidth ) == sx )
+ if ( static_cast< int >( dev.dmPelsHeight ) == sy ) {
+ c=(int)dev.dmBitsPerPel;
+ if (sc) {
+ if (c==8) sel=a;
+ } else {
+ if (c!=8) {
+ if ( c>maxcol ) { maxcol=c;sel=a; }
+ }
+ }
+ }
+ a++;
+ }
+ if (sel==-1) return 1;
+ EnumDisplaySettings( NULL,sel,&dev );
+ dev.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
+ ctx->stat = 0;
+
+ res=ChangeDisplaySettings( &dev,CDS_TEST );
+ if ( res == DISP_CHANGE_SUCCESSFUL ) {
+ res=ChangeDisplaySettings( &dev, CDS_FULLSCREEN );
+ } else {
+ ctx->stat = 2;
+ return 0;
+ }
+ dispflg++;
+ return 0;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ for polygon process interface
+*/
+/*------------------------------------------------------------*/
+
+#ifndef HSP_COMPACT
+
+static POLY4 mem_poly4;
+
+static void SetPolyAxis( POLY4 *poly, int num, int x, int y, int tx, int ty )
+{
+ IAXIS2 *iv;
+ iv = &poly->v[num];
+ iv->x = x;
+ iv->y = y;
+ iv->tx = tx;
+ iv->ty = ty;
+}
+
+
+static void DrawSquareEx( int mode, int color, int attr, int alpha, int *x, int *y, int *texx, int *texy )
+{
+ // 自由変形スプライト
+ // mode : 0=fullcolor/1=palette
+ //
+ POLY4 *poly;
+ int i,xx,yy,tx,ty;
+
+ poly = (POLY4 *)&mem_poly4;
+ for(i=0;i<4;i++) {
+ xx = x[i]; yy = y[i];
+ tx = texx[i];
+ ty = texy[i];
+ SetPolyAxis( poly, i, xx, yy, tx, ty );
+ }
+ poly->tex = 0;
+ poly->attr = attr;
+ poly->npoly = 1;
+ poly->alpha = alpha;
+ if ( color == -1 ) {
+ poly->color = 0xffffff;
+ if ( mode ) {
+ DrawPolygonTexP( poly );
+ } else {
+ DrawPolygonTex( poly );
+ }
+ } else {
+ poly->color = color;
+ if ( mode ) {
+ DrawPolygonF4P( poly );
+ } else {
+ DrawPolygonF4( poly );
+ }
+ }
+}
+
+
+static void DrawSpriteEx( int mode, int attr, int alpha, int x, int y, int sx, int sy, double ang, int tx0, int ty0, int tx1, int ty1, int opx, int opy )
+{
+ // 拡大回転スプライト
+ // mode : 0=fullcolor/1=palette
+ // (x,y)基点座標 / (sx,sy)サイズ / (opx,opy)オフセット / ang=角度
+ //
+ POLY4 *poly;
+ IAXIS2 *iv;
+ double xx,yy,x0,y0,x1,y1,ofsx,ofsy,mx0,mx1,my0,my1;
+
+ poly = (POLY4 *)&mem_poly4;
+
+ mx0=-(double)sin( ang );
+ my0=(double)cos( ang );
+ mx1 = -my0;
+ my1 = mx0;
+
+ ofsx = (double)-opx;
+ ofsy = (double)-opy;
+ x0 = mx0 * ofsy;
+ y0 = my0 * ofsy;
+ x1 = mx1 * ofsx;
+ y1 = my1 * ofsx;
+
+ // 基点の算出
+ xx = ( (double)x - (-x0+x1) );
+ yy = ( (double)y - (-y0+y1) );
+
+ /*-------------------------------*/
+
+ // 回転座標の算出
+ ofsx = (double)-sx;
+ ofsy = (double)-sy;
+ x0 = mx0 * ofsy;
+ y0 = my0 * ofsy;
+ x1 = mx1 * ofsx;
+ y1 = my1 * ofsx;
+
+ /*-------------------------------*/
+
+ iv = &poly->v[0];
+ iv->x = (short)((-x0+x1) + xx);
+ iv->y = (short)((-y0+y1) + yy);
+ iv->tx = tx1;
+ iv->ty = ty0;
+
+ /*-------------------------------*/
+
+ iv = &poly->v[1];
+ iv->x = (short)((x1) + xx);
+ iv->y = (short)((y1) + yy);
+ iv->tx = tx1;
+ iv->ty = ty1;
+
+ /*-------------------------------*/
+
+ iv = &poly->v[2];
+ iv->x = (short)(xx);
+ iv->y = (short)(yy);
+ iv->tx = tx0;
+ iv->ty = ty1;
+
+ /*-------------------------------*/
+
+ iv = &poly->v[3];
+ iv->x = (short)((-x0) + xx);
+ iv->y = (short)((-y0) + yy);
+ iv->tx = tx0;
+ iv->ty = ty0;
+
+ /*-------------------------------*/
+
+ poly->tex = 0;
+ poly->attr = attr;
+ poly->npoly = 1;
+ poly->color = 0xffffff;
+ poly->alpha = alpha;
+
+ if ( mode ) {
+ DrawPolygonTexP( poly );
+ } else {
+ DrawPolygonTex( poly );
+ }
+}
+
+
+static void DrawRectEx( int mode, int color, int alpha, int x, int y, int sx, int sy, double ang )
+{
+ // 回転fill
+ // mode : 0=fullcolor/1=palette
+ // (x,y)中心座標 / ang=角度
+ //
+ POLY4 *poly;
+ IAXIS2 *iv;
+ double x0,y0,x1,y1,ofsx,ofsy;
+ short xx,yy,tx0,ty0,tx1,ty1;
+
+ poly = (POLY4 *)&mem_poly4;
+ xx = (short)x;
+ yy = (short)y;
+
+ tx0 = 0;
+ ty0 = 0;
+ tx1 = sx-1; if ( tx1 < 0 ) tx1=0;
+ ty1 = sy-1; if ( ty1 < 0 ) ty1=0;
+ ofsx = (double)( tx1 - tx0 + 1 );
+ ofsy = (double)( ty1 - ty0 + 1 );
+ x0=-(double)sin( ang );
+ y0=(double)cos( ang );
+ x1 = -y0;
+ y1 = x0;
+
+ ofsx *= -0.5f;
+ ofsy *= -0.5f;
+ x0 *= ofsy;
+ y0 *= ofsy;
+ x1 *= ofsx;
+ y1 *= ofsx;
+
+ iv = &poly->v[0];
+ iv->x = (short)(-x0+x1) + xx;
+ iv->y = (short)(-y0+y1) + yy;
+ iv->tx = tx1;
+ iv->ty = ty1;
+
+ iv = &poly->v[1];
+ iv->x = (short)(x0+x1) + xx;
+ iv->y = (short)(y0+y1) + yy;
+ iv->tx = tx1;
+ iv->ty = ty0;
+
+ iv = &poly->v[2];
+ iv->x = (short)(x0-x1) + xx;
+ iv->y = (short)(y0-y1) + yy;
+ iv->tx = tx0;
+ iv->ty = ty0;
+
+ iv = &poly->v[3];
+ iv->x = (short)(-x0-x1) + xx;
+ iv->y = (short)(-y0-y1) + yy;
+ iv->tx = tx0;
+ iv->ty = ty1;
+
+ poly->tex = 0;
+ poly->attr = 0;
+ poly->npoly = 1;
+ poly->alpha = alpha;
+ poly->color = color;
+
+ if ( mode ) {
+ DrawPolygonF4P( poly );
+ } else {
+ DrawPolygonF4( poly );
+ }
+}
+
+
+static int CnvRGB( int color )
+{
+ int res=0;
+ res = color & 0x00ff00;
+ res |= (color>>16) & 0xff;
+ res |= (color & 0xff)<<16;
+ return res;
+}
+
+
+static int GetAttrOperation( void )
+{
+ // gmodeのモードをHGIMG互換のattr値に変換する
+ //
+ int attr;
+ attr = 0;
+ if ( bmscr->gmode == 2 ) { attr = NODE_ATTR_COLKEY; }
+ if ( bmscr->gmode == 4 ) { attr = NODE_ATTR_COLKEY; SetPolyColorKey( bmscr->color ); }
+ return attr;
+}
+
+
+static void GRotateSub( Bmscr *bm2, int x, int y, int sx, int sy, int sizex, int sizey, double rot, int opx, int opy )
+{
+ int tx0,ty0,tx1,ty1;
+ int attr;
+
+ SetPolyDest( bmscr->pBit, bmscr->sx, bmscr->sy );
+ SetPolySource( bm2->pBit, bm2->sx, bm2->sy );
+
+ tx0 = GetLimit( x, 0, bm2->sx );
+ ty0 = GetLimit( y, 0, bm2->sy );
+ tx1 = GetLimit( tx0 + sx - 1, 0, bm2->sx );
+ ty1 = GetLimit( ty0 + sy - 1, 0, bm2->sy );
+ ty0 = bm2->sy - 1 - ty0;
+ ty1 = bm2->sy - 1 - ty1;
+ attr = GetAttrOperation();
+ DrawSpriteEx( bmscr->palmode, attr, bmscr->GetAlphaOperation(), bmscr->cx, bmscr->cy, sizex, sizey, rot, tx0, ty1, tx1, ty0, opx, opy );
+ if ( resY0 >= 0 ) {
+ bmscr->Send( 0, resY0, bmscr->sx, resY1-resY0+1 );
+ }
+}
+
+
+static int *code_getiv( void )
+{
+ // 変数パラメーターを取得(PDATポインタ)
+ //
+ PVal *pval;
+ pval = code_getpval();
+ if ( pval->flag != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH;
+ return (int *)HspVarCorePtrAPTR( pval, 0 );
+}
+
+#endif
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+static void cmdfunc_dialog( void )
+{
+ // dialog
+ int i;
+ int p1,p2;
+ char *ptr;
+ char *ps;
+ char stmp[0x4000];
+ HSPAPICHAR *hactmp1 = 0;
+ HSPAPICHAR *hactmp2 = 0;
+ ptr = code_getdsi( "" );
+ strncpy( stmp, ptr, 0x4000-1 );
+ p1 = code_getdi( 0 );
+ ps = code_getds("");
+ p2 = code_getdi( 0 );
+
+ if ( p1 >= 64 ) {
+ return;
+ }
+ if (p1&16) {
+ ctx->stat = fd_dialog( bmscr->hwnd, p1&3, stmp, ps );
+ if ( ctx->stat == 0 ) {
+ ctx->refstr[0] = 0;
+ } else {
+ strncpy( ctx->refstr, fd_getfname(), HSPCTX_REFSTR_MAX-1 );
+ }
+ }
+ else if (p1&32) {
+ i = (int)fd_selcolor( bmscr->hwnd,p1&1 );
+ if ( i == -1 ) ctx->stat = 0;
+ else {
+ bmscr->color = i;
+ ctx->stat = 1;
+ }
+ }
+ else {
+ i=0;
+ if (p1&1) i|=MB_ICONEXCLAMATION; else i|=MB_ICONINFORMATION;
+ if (p1&2) i|=MB_YESNO; else i|=MB_OK;
+ ctx->stat = MessageBox( bmscr->hwnd,
+ chartoapichar(stmp,&hactmp1), chartoapichar(ps,&hactmp2), i );
+ freehac(&hactmp1);
+ freehac(&hactmp2);
+ }
+}
+
+
+static int cmdfunc_extcmd( int cmd )
+{
+ // cmdfunc : TYPE_EXTCMD
+ // (内蔵GUIコマンド)
+ //
+ int p1,p2,p3,p4,p5,p6;
+
+ code_next(); // 次のコードを取得(最初に必ず必要です)
+ switch( cmd ) { // サブコマンドごとの分岐
+
+ case 0x00: // button
+ {
+ int i;
+ char btnname[256];
+ unsigned short *sbr;
+ Bmscr *bmsrc;
+
+#ifndef HSPEMBED
+ i = 0;
+ if ( *type == TYPE_PROGCMD ) {
+ i = *val;
+ if ( i >= 2 ) throw HSPERR_SYNTAX;
+ code_next();
+ }
+#else
+ i = code_geti();
+#endif
+ strncpy( btnname, code_gets(), 255 );
+ sbr = code_getlb();
+ code_next();
+ ctx->stat = bmscr->AddHSPObjectButton( btnname, i, (void *)sbr );
+ p1 = bmscr->imgbtn;
+ if ( p1 >= 0 ) {
+ bmsrc = wnd->GetBmscrSafe( p1 );
+ bmscr->SetButtonImage( ctx->stat, p1, bmscr->btn_x1, bmscr->btn_y1, bmscr->btn_x2, bmscr->btn_y2, bmscr->btn_x3, bmscr->btn_y3 );
+ }
+ break;
+ }
+
+ case 0x01: // chgdisp
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 640 );
+ p3 = code_getdi( 480 );
+ ctx->stat = chgdisp( p1, p2, p3 );
+ break;
+
+ case 0x02: // exec
+ {
+ char *ps;
+ char *fname;
+ fname = code_stmpstr( code_gets() );
+ p1 = code_getdi( 0 );
+ ps = code_getds( "" );
+ ExecFile( fname, ps, p1 );
+ break;
+ }
+
+ case 0x03: // dialog
+ cmdfunc_dialog();
+ break;
+
+ case 0x08: // mmload
+ {
+ int i;
+ char fname[_MAX_PATH];
+ strncpy( fname, code_gets(), _MAX_PATH-1 );
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ i = mmman->Load( fname, p1, p2 );
+ if (i) throw HSPERR_FILE_IO;
+ break;
+ }
+ case 0x09: // mmplay
+ p1 = code_getdi( 0 );
+// if ( p1 < 0 ) {
+// ctx->stat = mmman->GetBusy();
+// } else {
+ mmman->SetWindow( bmscr->hwnd, bmscr->cx, bmscr->cy, bmscr->sx, bmscr->sy );
+ mmman->Play( p1 );
+// }
+ break;
+
+ case 0x0a: // mmstop
+ mmman->Stop();
+ break;
+
+ case 0x0b: // mci
+ ctx->stat = mmman->SendMCI( code_gets() );
+ strncpy( ctx->refstr, mmman->GetMCIResult(), HSPCTX_REFSTR_MAX-1 );
+ break;
+
+ case 0x0c: // pset
+ p1 = code_getdi( bmscr->cx );
+ p2 = code_getdi( bmscr->cy );
+ bmscr->Pset( p1, p2 );
+ break;
+
+ case 0x0d: // pget
+ p1 = code_getdi( bmscr->cx );
+ p2 = code_getdi( bmscr->cy );
+ bmscr->Pget( p1, p2 );
+ break;
+
+ case 0x0e: // syscolor
+ p1 = code_getdi( 0 );
+ bmscr->SetSystemcolor( p1 );
+ break;
+
+ case 0x0f: // mes,print
+ {
+ int chk;
+ int sw,x,y;
+ char *ptr;
+ ptr = code_getdsi( "" );
+ sw = code_getdi(0);
+ strsp_ini();
+ while(1) {
+ chk = strsp_get( ptr, ctx->stmp, 0, 1022 );
+ x = bmscr->cx; y = bmscr->cy;
+ bmscr->Print( ctx->stmp );
+ if ( chk == 0 ) break;
+ }
+ if ( sw ) { // 改行しない
+ bmscr->cx = x + bmscr->printsize.cx;
+ bmscr->cy = y;
+ }
+ break;
+ }
+ case 0x10: // title
+ {
+ char *p;
+ p = code_gets();
+ bmscr->Title( p );
+ break;
+ }
+ case 0x11: // pos
+ bmscr->cx = code_getdi( bmscr->cx );
+ bmscr->cy = code_getdi( bmscr->cy );
+ break;
+ case 0x12: // circle
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( bmscr->sx );
+ p4 = code_getdi( bmscr->sy );
+ p5 = code_getdi( 1 );
+ bmscr->Circle( p1,p2,p3,p4,p5 );
+ break;
+ case 0x13: // cls
+ p1 = code_getdi( 0 );
+ bmscr->Cls( p1 );
+ break;
+ case 0x14: // font
+ {
+ char fontname[256];
+ strncpy( fontname, code_gets(), 255 );
+ p1 = code_getdi( 12 );
+ p2 = code_getdi( 0 );
+ ctx->stat = bmscr->Newfont( fontname, p1, p2, 0 );
+ break;
+ }
+ case 0x15: // sysfont
+ p1 = code_getdi( 0 );
+ bmscr->Sysfont( p1 );
+ break;
+ case 0x16: // objsize
+ p1 = code_getdi( 64 );
+ p2 = code_getdi( 24 );
+ p3 = code_getdi( 0 );
+ bmscr->ox=p1;bmscr->oy=p2;bmscr->py=p3;
+ break;
+
+ case 0x17: // picload
+ {
+ int i,wid;
+ char fname[_MAX_PATH];
+ strncpy( fname, code_gets(), _MAX_PATH-1 );
+ p1 = code_getdi( 0 );
+ wid = bmscr->wid;
+ i = wnd->Picload( wid, fname, p1 );
+ if ( i ) throw HSPERR_PICTURE_MISSING;
+ bmscr = wnd->GetBmscr( wid );
+ //cur_window = wid;
+ break;
+ }
+ case 0x18: // color
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ bmscr->Setcolor(p1,p2,p3);
+ break;
+ case 0x19: // palcolor
+ p1 = code_getdi( 0 );
+ bmscr->SetPalcolor( p1 );
+ break;
+ case 0x1a: // palette
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ p4 = code_getdi( 0 );
+ p5 = code_getdi( 0 );
+ if ( p1 >= 0 ) {
+ bmscr->SetPalette( p1, p2, p3, p4 );
+ }
+ if ( p5 ) bmscr->UpdatePalette();
+ break;
+
+ break;
+ case 0x1b: // redraw
+ p1 = code_getdi( 1 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ p4 = code_getdi( 0 );
+ p5 = code_getdi( 0 );
+ if (p1==0) p1=2;
+ if (p1<2) {
+ bmscr->fl_udraw=1;
+ if ((p4==0)||(p5==0)) bmscr->Update();
+ else {
+ bmscr->Send( p2, p3, p4, p5 );
+ }
+ }
+ bmscr->fl_udraw=p1&1;
+ break;
+
+ case 0x1c: // width
+ p1 = code_getdi( -1 );
+ p2 = code_getdi( -1 );
+ p3 = code_getdi( -1 );
+ p4 = code_getdi( -1 );
+ bmscr->Width( p1, p2, p3, p4, 1 );
+ break;
+
+ case 0x1d: // gsel
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+
+ bmscr = wnd->GetBmscrSafe( p1 );
+ cur_window = p1;
+
+ if (p2<0) {
+ ShowWindow( bmscr->hwnd, SW_HIDE );
+ }
+ else if (p2>0) {
+ HWND i;
+ if (p2==1) i=HWND_NOTOPMOST; else i=HWND_TOPMOST;
+ ShowWindow( bmscr->hwnd, SW_SHOW );
+ SetActiveWindow( bmscr->hwnd );
+ SetWindowPos( bmscr->hwnd, i, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
+ }
+ break;
+
+ case 0x1e: // gcopy
+ {
+ Bmscr *src;
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ p4 = code_getdi( bmscr->gx );
+ p5 = code_getdi( bmscr->gy );
+ src = wnd->GetBmscrSafe( p1 );
+ if ( bmscr->Copy( src, p2, p3, p4, p5 ) ) throw HSPERR_UNSUPPORTED_FUNCTION;
+ break;
+ }
+
+ case 0x1f: // gzoom
+ {
+ int p7,p8;
+ Bmscr *src;
+ p1 = code_getdi( bmscr->sx );
+ p2 = code_getdi( bmscr->sy );
+ p3 = code_getdi( 0 );
+ p4 = code_getdi( 0 );
+ p5 = code_getdi( 0 );
+ p6 = code_getdi( bmscr->gx );
+ p7 = code_getdi( bmscr->gy );
+ p8 = code_getdi( 0 );
+ src = wnd->GetBmscrSafe( p3 );
+ if ( bmscr->Zoom( p1, p2, src, p4, p5, p6, p7, p8 ) ) throw HSPERR_UNSUPPORTED_FUNCTION;
+ break;
+ }
+
+ case 0x20: // gmode
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 32 );
+ p3 = code_getdi( 32 );
+ p4 = code_getdi( 0 );
+ bmscr->gmode = p1;
+ bmscr->gx = p2;
+ bmscr->gy = p3;
+ bmscr->gfrate = p4;
+ break;
+
+
+ case 0x21: // bmpsave
+ if ( bmscr->BmpSave( code_gets() ) ) throw HSPERR_FILE_IO;
+ break;
+
+ case 0x22: // hsvcolor
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( 0 );
+ bmscr->SetHSVColor( p1, p2, p3 );
+ break;
+
+ case 0x23: // getkey
+ {
+ PVal *pval;
+ APTR aptr;
+ aptr = code_getva( &pval );
+ p1=code_getdi(1);
+
+ if ( p1 == VK_LBUTTON || p1 == VK_RBUTTON ) {
+ if ( GetSystemMetrics(SM_SWAPBUTTON) ) { p1 ^= VK_LBUTTON | VK_RBUTTON; }
+ }
+
+ if ( code_event( HSPEVENT_GETKEY, p1, 0, &p2 ) == 0 ) {
+ if ( GetAsyncKeyState(p1)&0x8000 ) p2=1; else p2=0;
+ }
+ code_setva( pval, aptr, TYPE_INUM, &p2 );
+ break;
+ }
+
+ case 0x25: // chkbox
+ {
+ char name[256];
+ PVal *pval;
+ APTR aptr;
+ strncpy( name, code_gets(), 255 );
+ aptr = code_getva( &pval );
+ if ( pval->flag != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH;
+ ctx->stat = bmscr->AddHSPObjectCheckBox( name, pval, aptr );
+ break;
+ }
+
+ case 0x24: // listbox
+ case 0x26: // combox
+ {
+ PVal *pval;
+ APTR aptr;
+ char *p;
+ aptr = code_getva( &pval );
+ if ( pval->flag != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH;
+ p1 = code_getdi( 100 );
+ p = code_gets();
+ ctx->stat = bmscr->AddHSPObjectMultiBox( pval, aptr, p1, p, cmd==0x26 );
+ break;
+ }
+
+ case 0x27: // input
+ {
+ PVal *pval;
+ APTR aptr;
+ char *ptr;
+ int type,size;
+ aptr = code_getva( &pval );
+
+ p1 = code_getdi( bmscr->ox );
+ p2 = code_getdi( bmscr->oy );
+ size = 32;
+ type = pval->flag;
+ ptr = (char *)HspVarCorePtrAPTR( pval, aptr );
+ if ( type == TYPE_STRING ) {
+ ptr = (char *)HspVarCoreGetBlockSize( pval, (PDAT *)ptr, &size );
+ } else {
+ ptr = (char *)HspVarCoreCnv( pval->flag, HSPVAR_FLAG_STR, ptr ); // 文字列に変換
+ }
+ p3 = code_getdi( size );
+ ctx->stat = bmscr->AddHSPObjectInput( pval, aptr, p1, p2, ptr, p3, type );
+ break;
+ }
+
+ case 0x28: // mesbox
+ {
+ PVal *pval;
+ APTR aptr;
+ char *ptr;
+ int i;
+ int size;
+
+ aptr = code_getva( &pval );
+ if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ ptr = (char *)HspVarCoreGetBlockSize( pval, HspVarCorePtrAPTR( pval, aptr ), &size );
+ p1=code_getdi(bmscr->ox);
+ p2=code_getdi(bmscr->oy);
+ p3=code_getdi( 1 );
+ p4=code_getdi( -1 );
+ i = HSPOBJ_INPUT_MULTILINE;
+ if ((p3&1)==0) i |= HSPOBJ_INPUT_READONLY;
+ if (p3&4) i |= HSPOBJ_INPUT_HSCROLL;
+ if ( p4 < 0 ) p4 = size-1;
+ ctx->stat = bmscr->AddHSPObjectInput( pval, aptr, p1, p2, ptr, p4, (pval->flag)|i );
+ break;
+ }
+
+ case 0x29: // buffer
+ case 0x2a: // screen
+ case 0x2b: // bgscr
+ {
+ int p7,p8,t;
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 640 );
+ p3 = code_getdi( 480 );
+ p4 = code_getdi( 0 );
+ p5 = code_getdi( -1 );
+ p6 = code_getdi( -1 );
+ p7 = code_getdi( p2 );
+ p8 = code_getdi( p3 );
+
+#ifdef HSP3IMP
+ if ( p1 == 0 ) {
+ bmscr = wnd->GetBmscr( p1 );
+ cur_window = p1;
+ break;
+ }
+#endif
+ if ( cmd == 0x29 ) {
+ t = HSPWND_TYPE_BUFFER;
+ } else if ( cmd == 0x2b ) {
+ t = HSPWND_TYPE_BGSCR;
+ } else {
+ t = HSPWND_TYPE_MAIN;
+ }
+ wnd->MakeBmscr( p1, t, p5, p6, p7, p8, p2, p3, p4 );
+ bmscr = wnd->GetBmscr( p1 );
+ bmscr->Width( p7, p8, p5, p6, 1 );
+
+ cur_window = p1;
+
+ if ( bmscr->type == HSPWND_TYPE_BUFFER ) break;
+
+ ctx->waitcount = 0;
+ ctx->waittick = -1;
+ ctx->runmode = RUNMODE_AWAIT;
+ return RUNMODE_AWAIT;
+ }
+
+ case 0x2c: // mouse
+ {
+ POINT pt;
+ GetCursorPos(&pt);
+ p1 = code_getdi( pt.x );
+ p2 = code_getdi( pt.y );
+ if ((p1<0)||(p2<0)) {
+ msact = ShowCursor(0);
+ break;
+ }
+ SetCursorPos( p1, p2 );
+ if ( msact < 0 ) { msact = ShowCursor(1); }
+ break;
+ }
+
+ case 0x2d: // objsel
+ p1 = code_getdi( 0 );
+ ctx->stat = bmscr->ActivateHSPObject( p1 );
+ break;
+
+ case 0x2e: // groll
+ p1=code_getdi(0);
+ p2=code_getdi(0);
+ bmscr->SetScroll( p1, p2 );
+ break;
+
+ case 0x2f: // line
+ p1=code_getdi(0);
+ p2=code_getdi(0);
+ bmscr->cx=code_getdi(bmscr->cx);
+ bmscr->cy=code_getdi(bmscr->cy);
+ bmscr->Line( p1, p2 );
+ break;
+
+ case 0x30: // clrobj
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( -1 );
+ p4 = bmscr->objmax-1;
+ if ( p4 < 0 ) break;
+ if (( p1<0 )|( p2>p4 )|( p1>p4 )) throw HSPERR_ILLEGAL_FUNCTION;
+ if ( p2<0 ) p2 = p4;
+ for( p3=p1; p3<=p2; p3++ ) {
+ bmscr->DeleteHSPObject( p3 );
+ }
+ break;
+
+ case 0x31: // boxf
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( bmscr->sx );
+ p4 = code_getdi( bmscr->sy );
+ bmscr->Boxfill( p1, p2, p3, p4 );
+ break;
+
+ case 0x32: // objprm
+ p1=code_getdi(0);
+ if ( code_get() <= PARAM_END ) throw HSPERR_NO_DEFAULT;
+ bmscr->UpdateHSPObject( p1, mpval->flag, mpval->pt );
+ break;
+ case 0x33: // objmode (ver2.5 enhanced )
+ p1=code_getdi(0);
+ p2=code_getdi( bmscr->tabmove );
+ bmscr->objmode = p1;
+ bmscr->tabmove = p2;
+ break;
+
+ case 0x34: // stick
+ {
+ PVal *pval;
+ APTR aptr;
+ int res;
+ aptr = code_getva( &pval );
+ p1 = code_getdi(0);
+ p2 = code_getdi(1);
+
+ ckey = 0; res = 0;
+ if (p2) {
+ if ( wnd->GetActive() < 0 ) {
+ code_setva( pval, aptr, TYPE_INUM, &res );
+ break;
+ }
+ }
+ static int stick_keys[] = {
+ VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_SPACE, VK_RETURN,
+ VK_CONTROL, VK_ESCAPE,
+ (GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON),
+ (GetSystemMetrics(SM_SWAPBUTTON) ? VK_LBUTTON : VK_RBUTTON),
+ VK_TAB
+ };
+
+ for ( size_t i = 0; i < sizeof(stick_keys) / sizeof(int); i++ ) {
+ if ( GetAsyncKeyState(stick_keys[i]) & 0x8000 ) { ckey |= 1 << i; }
+ }
+ cktrg = (ckey^cklast)&ckey;
+ cklast = ckey;
+ res = cktrg|(ckey&p1);
+ code_setva( pval, aptr, TYPE_INUM, &res );
+ break;
+ }
+
+#ifndef HSP_COMPACT
+ case 0x35: // grect
+ {
+ double rot;
+ p1 = code_getdi(0); // パラメータ1:数値
+ p2 = code_getdi(0); // パラメータ2:数値
+ rot = code_getdd(0.0); // パラメータ5:数値
+ p3 = code_getdi(bmscr->gx); // パラメータ3:数値
+ p4 = code_getdi(bmscr->gy); // パラメータ4:数値
+ SetPolyDest( bmscr->pBit, bmscr->sx, bmscr->sy );
+ if ( bmscr->palmode ) p6 = bmscr->palcolor; else p6 = CnvRGB( bmscr->color );
+ DrawRectEx( bmscr->palmode, p6, bmscr->GetAlphaOperation(), p1, p2, p3, p4, rot );
+ if ( resY0 >= 0 ) {
+ bmscr->Send( 0, resY0, bmscr->sx, resY1-resY0+1 );
+ }
+ break;
+ }
+ case 0x36: // grotate
+ {
+ Bmscr *bm2;
+ double rot;
+
+ p1 = code_getdi(0); // パラメータ1:数値
+ p2 = code_getdi(0); // パラメータ2:数値
+ p3 = code_getdi(0); // パラメータ3:数値
+ rot = code_getdd(0.0); // パラメータ6:数値
+ p4 = code_getdi(bmscr->gx); // パラメータ4:数値
+ p5 = code_getdi(bmscr->gy); // パラメータ5:数値
+
+ bm2 = wnd->GetBmscrSafe( p1 ); // 転送元のBMSCRを取得
+ if ( bmscr->palmode != bm2->palmode ) throw HSPERR_ILLEGAL_FUNCTION;
+#if 0
+ int tx0,ty0,tx1,ty1;
+ int attr;
+ SetPolyDest( bmscr->pBit, bmscr->sx, bmscr->sy );
+ SetPolySource( bm2->pBit, bm2->sx, bm2->sy );
+
+ tx0 = GetLimit( p2, 0, bm2->sx );
+ ty0 = GetLimit( p3, 0, bm2->sy );
+ tx1 = GetLimit( tx0+bmscr->gx-1, 0, bm2->sx );
+ ty1 = GetLimit( ty0+bmscr->gy-1, 0, bm2->sy );
+ ty0 = bm2->sy - 1 - ty0;
+ ty1 = bm2->sy - 1 - ty1;
+ attr = GetAttrOperation();
+ DrawSpriteEx( bmscr->palmode, attr, bmscr->GetAlphaOperation(), bmscr->cx, bmscr->cy, p4, p5, rot, tx0, ty1, tx1, ty0, p4, p5 );
+ if ( resY0 >= 0 ) {
+ bmscr->Send( 0, resY0, bmscr->sx, resY1-resY0+1 );
+ }
+#else
+ GRotateSub( bm2, p2, p3, bmscr->gx, bmscr->gy, p4, p5, rot, p4/2, p5/2 );
+#endif
+ break;
+ }
+ case 0x37: // gsquare
+ {
+ Bmscr *bm2;
+ int ep1,i;
+ int attr;
+ int tmp_x[4], tmp_y[4], tmp_tx[4], tmp_ty[4];
+ int color;
+ int *px;
+ int *py;
+ int *ptx;
+ int *pty;
+ int sqmode;
+
+ bm2 = NULL;
+ ep1 = code_getdi(0); // パラメータ1:数値
+ px = code_getiv();
+ py = code_getiv();
+
+ sqmode = GSQUARE_MODE_TEXTURE;
+
+ if ( ep1 >= 0 ) {
+ bm2 = wnd->GetBmscrSafe( ep1 ); // 転送元のBMSCRを取得
+ if ( bmscr->palmode != bm2->palmode ) throw HSPERR_ILLEGAL_FUNCTION;
+ SetPolySource( bm2->pBit, bm2->sx, bm2->sy );
+ color = -1;
+ ptx = code_getiv();
+ pty = code_getiv();
+ } else {
+ if ( ep1 <= -257 ) { // グラデーションモード
+ ptx = code_getiv();
+ bmscr->GradFillEx( px, py, ptx );
+ break;
+ } else {
+ if ( bmscr->palmode ) { color = (- ep1 ) - 1; } else { color = CnvRGB( bmscr->color ); }
+ sqmode = GSQUARE_MODE_COLORFILL;
+ }
+ }
+
+ SetPolyDest( bmscr->pBit, bmscr->sx, bmscr->sy );
+
+ for(i=0;i<4;i++) {
+ tmp_x[i] = px[i];
+ tmp_y[i] = py[i];
+ switch( sqmode ) {
+ case GSQUARE_MODE_TEXTURE:
+ tmp_tx[i] = GetLimit( ptx[i], 0, bm2->sx );
+ tmp_ty[i] = bm2->sy - 1 - GetLimit( pty[i], 0, bm2->sy ); // UVの上下逆にする
+ break;
+ case GSQUARE_MODE_COLORFILL:
+ tmp_tx[i] = 0;
+ tmp_ty[i] = 0;
+ break;
+ }
+ }
+
+ attr = GetAttrOperation();
+ DrawSquareEx( bmscr->palmode, color, attr, bmscr->GetAlphaOperation(), tmp_x, tmp_y, tmp_tx, tmp_ty );
+
+ if ( resY0 >= 0 ) {
+ bmscr->Send( 0, resY0, bmscr->sx, resY1-resY0+1 );
+ }
+ break;
+ }
+
+ case 0x38: // gradf
+ {
+ int gradmode;
+ int col;
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = code_getdi( bmscr->sx );
+ p4 = code_getdi( bmscr->sy );
+ gradmode = code_getdi( 0 );
+ col = CnvRGB( bmscr->color );
+ p5 = code_getdi( col );
+ p6 = code_getdi( col );
+ bmscr->GradFill( p1, p2, p3, p4, gradmode, p5, p6 );
+ break;
+ }
+#endif
+
+ case 0x39: // objimage
+ p1 = code_getdi( -1 );
+ bmscr->imgbtn = p1;
+ bmscr->btn_x1 = (short)code_getdi( 0 );
+ bmscr->btn_y1 = (short)code_getdi( 0 );
+ bmscr->btn_x2 = (short)code_getdi( 0 );
+ bmscr->btn_y2 = (short)code_getdi( 0 );
+ bmscr->btn_x3 = (short)code_getdi( bmscr->btn_x1 );
+ bmscr->btn_y3 = (short)code_getdi( bmscr->btn_y1 );
+ break;
+
+ case 0x3a: // objskip
+ {
+ p1=code_getdi(0);
+ p2=code_getdi(2);
+ bmscr->SetObjectMode( p1, p2 );
+ break;
+ }
+
+ case 0x3b: // objenable
+ {
+ p1=code_getdi(0);
+ p2=code_getdi(1);
+ bmscr->EnableObject( p1, p2 );
+ break;
+ }
+
+#ifndef HSP_COMPACT
+ case 0x3c: // celload
+ {
+ int i;
+ char fname[_MAX_PATH];
+ strncpy( fname, code_gets(), _MAX_PATH-1 );
+ p1 = code_getdi( -1 );
+ p2 = code_getdi( 0 );
+ if ( p1 < 0 ) p1 = wnd->GetEmptyBufferId();
+
+ wnd->MakeBmscrOff( p1, 32, 32, p2 );
+ i = wnd->Picload( p1, fname, 2 );
+ if ( i ) throw HSPERR_PICTURE_MISSING;
+
+ ctx->stat = p1;
+ break;
+ }
+ case 0x3d: // celdiv
+ {
+ Bmscr *bm2;
+ p1=code_getdi(1);
+ p2=code_getdi(0);
+ p3=code_getdi(0);
+ p4=code_getdi(0);
+ p5=code_getdi(0);
+ bm2 = wnd->GetBmscrSafe( p1 );
+ bm2->SetCelDivideSize( p2, p3, p4, p5 );
+ break;
+ }
+ case 0x3e: // celput
+ {
+ Bmscr *bm2;
+ double zx,zy,rot;
+ int x,y,srcsx,srcsy,putsx,putsy,centerx,centery;
+
+ p1=code_getdi(1);
+ p2=code_getdi(0);
+ zx = code_getdd(1.0);
+ zy = code_getdd(1.0);
+ rot = code_getdd(0.0);
+ bm2 = wnd->GetBmscrSafe( p1 ); // 転送元のBMSCRを取得
+
+ if (( rot == 0.0 )&&( zx == 1.0 )&&( zy == 1.0 )) {
+ // 変形なし
+ if ( bmscr->CelPut( bm2, p2 ) ) throw HSPERR_UNSUPPORTED_FUNCTION;
+ break;
+ }
+
+ // 変形あり
+ if ( bmscr->palmode != bm2->palmode ) throw HSPERR_ILLEGAL_FUNCTION;
+
+ srcsx = bm2->divsx;
+ srcsy = bm2->divsy;
+ x = ( p2 % bm2->divx ) * srcsx;
+ y = ( p2 / bm2->divx ) * srcsy;
+ putsx = (int)((double)srcsx * zx );
+ putsy = (int)((double)srcsy * zy );
+ centerx = (int)((double)bm2->celofsx * zx );
+ centery = (int)((double)bm2->celofsy * zy );
+ GRotateSub( bm2, x, y, srcsx, srcsy, putsx, putsy, rot, centerx, centery );
+ bmscr->cx += putsx;
+ break;
+ }
+#endif
+
+ case 0x3f: // gfilter
+ case 0x40: // setreq
+ case 0x41: // getreq
+ // HSP3Dish用の機能
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ break;
+
+ case 0x42: // mmvol
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ mmman->SetVol( p1, p2 );
+ break;
+ case 0x43: // mmpan
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ mmman->SetPan( p1, p2 );
+ break;
+ case 0x44: // mmstat
+ {
+ PVal *p_pval;
+ APTR p_aptr;
+ p_aptr = code_getva( &p_pval );
+ p1 = code_getdi( 0 );
+ p2 = code_getdi( 0 );
+ p3 = mmman->GetStatus( p1, p2 );
+ code_setva( p_pval, p_aptr, HSPVAR_FLAG_INT, &p3 );
+ break;
+ }
+ case 0x45: // mtlist
+ case 0x46: // mtinfo
+ case 0x47: // devinfo
+ case 0x48: // devinfoi
+ case 0x49: // devprm
+ case 0x4a: // devcontrol
+ // HSP3Dish用の機能
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ break;
+
+
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ return RUNMODE_RUN;
+}
+
+
+static int get_ginfo( int arg )
+{
+ HDC hdc;
+ RECT rect;
+ POINT pt;
+ int i,j;
+
+ if (( arg>=4 )&&( arg<=11 )) GetWindowRect( bmscr->hwnd, &rect);
+
+ switch( arg ) {
+ case 0:
+ GetCursorPos(&pt);
+ return pt.x;
+ case 1:
+ GetCursorPos(&pt);
+ return pt.y;
+ case 2:
+ return wnd->GetActive();
+ case 3:
+ return cur_window;
+ case 4:
+ return rect.left;
+ case 5:
+ return rect.top;
+ case 6:
+ return rect.right;
+ case 7:
+ return rect.bottom;
+ case 8:
+ return bmscr->viewx;
+ case 9:
+ return bmscr->viewy;
+ case 10:
+ return rect.right - rect.left;
+ case 11:
+ return rect.bottom - rect.top;
+ case 12:
+ if ( bmscr->type != HSPWND_TYPE_BUFFER ) {
+ bmscr->GetClientSize( &i, &j );
+ return i;
+ }
+ case 26:
+ return bmscr->sx;
+ case 13:
+ if ( bmscr->type != HSPWND_TYPE_BUFFER ) {
+ bmscr->GetClientSize( &i, &j );
+ return j;
+ }
+ case 27:
+ return bmscr->sy;
+ case 14:
+ return bmscr->printsize.cx;
+ case 15:
+ return bmscr->printsize.cy;
+ case 16:
+ return GetRValue( bmscr->color );
+ case 17:
+ return GetGValue( bmscr->color );
+ case 18:
+ return GetBValue( bmscr->color );
+ case 19:
+ hdc=GetDC(NULL);
+ i = 0;
+ if ( GetDeviceCaps( hdc,RASTERCAPS ) & RC_PALETTE ) i = 1;
+ ReleaseDC( NULL, hdc );
+ return i;
+ case 20:
+ return GetSystemMetrics( SM_CXSCREEN );
+ case 21:
+ return GetSystemMetrics( SM_CYSCREEN );
+ case 22:
+ return bmscr->cx;
+ case 23:
+ return bmscr->cy;
+ case 24:
+ return ctx->intwnd_id;
+ case 25:
+ return wnd->GetEmptyBufferId();
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ return 0;
+}
+
+
+static int reffunc_intfunc_ivalue;
+
+static void *reffunc_function( int *type_res, int arg )
+{
+ void *ptr;
+ int p1,p2;
+
+ // 返値のタイプを設定する
+ //
+ *type_res = HSPVAR_FLAG_INT; // 返値のタイプを指定する
+ ptr = &reffunc_intfunc_ivalue; // 返値のポインタ
+
+ // '('で始まるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( *val != '(' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ switch( arg & 0xff ) {
+
+ // int function
+ case 0x000: // ginfo
+ reffunc_intfunc_ivalue = get_ginfo( code_geti() );
+ break;
+
+ case 0x001: // objinfo
+ {
+ int *iptr;
+ p1 = code_geti();
+ p2 = code_geti();
+ if (( p1 < 0 )||( p1 >= bmscr->objmax )) throw HSPERR_ILLEGAL_FUNCTION;
+ iptr = (int *)bmscr->GetHSPObject( p1 );
+ reffunc_intfunc_ivalue = iptr[p2];
+ break;
+ }
+
+ case 0x002: // dirinfo
+ p1 = code_geti();
+ ptr = getdir( p1 );
+ *type_res = HSPVAR_FLAG_STR;
+ break;
+
+ case 0x003: // sysinfo
+ p1 = code_geti();
+ *type_res = sysinfo( p1 );
+ ptr = ctx->stmp;
+ break;
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+
+ // ')'で終わるかを調べる
+ //
+ if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM;
+ if ( *val != ')' ) throw HSPERR_INVALID_FUNCPARAM;
+ code_next();
+
+ return ptr;
+}
+
+
+static void *reffunc_sysvar( int *type_res, int arg )
+{
+ // reffunc : TYPE_EXTSYSVAR
+ // (拡張システム変数)
+ //
+ void *ptr;
+ if ( arg & 0x100 ) return reffunc_function( type_res, arg );
+
+ // 返値のタイプを設定する
+ //
+ *type_res = HSPVAR_FLAG_INT; // 返値のタイプを指定する
+ ptr = &reffunc_intfunc_ivalue; // 返値のポインタ
+
+ switch( arg ) {
+
+ // int function
+ case 0x000: // mousex
+ reffunc_intfunc_ivalue = bmscr->savepos[ BMSCR_SAVEPOS_MOSUEX ];
+ break;
+ case 0x001: // mousey
+ reffunc_intfunc_ivalue = bmscr->savepos[ BMSCR_SAVEPOS_MOSUEY ];
+ break;
+ case 0x002: // mousew
+ reffunc_intfunc_ivalue = bmscr->savepos[ BMSCR_SAVEPOS_MOSUEW ];
+ bmscr->savepos[ BMSCR_SAVEPOS_MOSUEW ] = 0;
+ break;
+ case 0x003: // hwnd
+ ptr = (void *)(&(bmscr->hwnd));
+ break;
+ case 0x004: // hinstance
+ ptr = (void *)(&(bmscr->hInst));
+ break;
+ case 0x005: // hdc
+ ptr = (void *)(&(bmscr->hdc));
+ break;
+
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ return ptr;
+}
+
+
+static void mmnfunc( void *hwnd )
+{
+ // マルチメディアコールバック
+ //
+ mmman->Notify();
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ controller
+*/
+/*------------------------------------------------------------*/
+
+void *ex_getbmscr( int wid )
+{
+ Bmscr *bm;
+ bm = wnd->GetBmscr( wid );
+ return bm->GetBMSCR();
+}
+
+int ex_getobj( int wid, int id, void *inf )
+{
+ Bmscr *bm;
+ HSPOBJINFO *obj;
+ bm = wnd->GetBmscrSafe( wid );
+ obj = bm->GetHSPObject( id );
+ memcpy( inf, obj, sizeof(HSPOBJINFO) );
+ return 0;
+}
+
+int ex_setobj( int wid, int id, const void *inf )
+{
+ Bmscr *bm;
+ HSPOBJINFO *obj;
+ bm = wnd->GetBmscrSafe( wid );
+ obj = bm->GetHSPObject( id );
+ memcpy( obj, inf, sizeof(HSPOBJINFO) );
+ return 0;
+}
+
+int ex_addobj( int wid )
+{
+ Bmscr *bm;
+ bm = wnd->GetBmscrSafe( wid );
+ return bm->NewHSPObject();
+}
+
+
+void ex_mref( PVal *pval, int prm )
+{
+ int t,size;
+ void *ptr;
+ const int GETBM=0x60;
+ t = HSPVAR_FLAG_INT;
+ size = sizeof( Bmscr );
+ if ( prm >= GETBM ) {
+ ptr = ex_getbmscr( prm - GETBM );
+ } else {
+ switch( prm ) {
+ case 0x40:
+ size = sizeof(int);
+ ptr = &ctx->stat;
+ break;
+ case 0x41:
+ ptr = ctx->refstr;
+ t = HSPVAR_FLAG_STR;
+ size = 1024;
+ break;
+ case 0x42:
+ size = bmscr->bmpsize;
+ ptr = bmscr->pBit;
+ break;
+ case 0x43:
+ ptr = bmscr;
+ break;
+ case 0x44:
+ ptr = ctx; size = sizeof(HSPCTX);
+ break;
+ case 0x45:
+ size = 0x300;
+ ptr = wnd->pstpt;
+ break;
+ default:
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+ }
+ HspVarCoreDupPtr( pval, t, ptr, size );
+}
+
+
+static int termfunc_extcmd( int option )
+{
+ // termfunc : TYPE_EXTCMD
+ // (内蔵GUI)
+ //
+#ifndef HSP_COMPACT
+ hgiof_term();
+#endif
+ delete wnd;
+ chgdisp( 0, 0, 0 );
+ delete mmman;
+ return 0;
+}
+
+void hsp3typeinit_extcmd( HSP3TYPEINFO *info, int sx, int sy, int wd, int xx, int yy )
+{
+ HINSTANCE hInstance;
+ HSPEXINFO *exinfo; // Info for Plugins
+ char cname[32];
+ int flag;
+
+ ctx = info->hspctx;
+ exinfo = info->hspexinfo;
+ type = exinfo->nptype;
+ val = exinfo->npval;
+ hInstance = (HINSTANCE)ctx->instance;
+
+#ifdef HSP3IMP
+ strcpy( cname, "hspwndi" );
+#else
+ strcpy( cname, "hspwnd0" );
+#endif
+ if ( ctx->hspstat & HSPSTAT_SSAVER ) cname[6]='p';
+
+ mmman = new MMMan;
+ wnd = new HspWnd( hInstance, cname );
+
+ flag = wd & 0x100; // スクリーンセーバープレビューフラグ
+ if ( flag ) wnd->SetParentWindow( ctx->wnd_parent );
+ if ( wd & 1 ) flag |= 2; // 非表示フラグ
+
+ wnd->MakeBmscr( 0,HSPWND_TYPE_MAIN, xx, yy, sx, sy, sx, sy, flag );
+
+/*
+ rev 43
+ mingw : error : 関数ポインタから非関数ポインタへの変換
+ に対処
+*/
+ wnd->SetNotifyFunc( fpconv( mmnfunc ) );
+ wnd->SetEventNoticePtr( &ctx->stat );
+ cur_window = 0;
+ msact = 1;
+ dispflg = 0;
+ bmscr = wnd->GetBmscr( 0 );
+ mmman->Reset( bmscr->hwnd );
+#ifndef HSP_COMPACT
+ hgiof_init();
+#endif
+
+ // function register
+ //
+ info->cmdfunc = cmdfunc_extcmd;
+ info->termfunc = termfunc_extcmd;
+
+ // HSPEXINFOに関数を登録する
+ //
+ exinfo->actscr = &cur_window; // Active Window ID
+ exinfo->HspFunc_getbmscr = ex_getbmscr;
+ exinfo->HspFunc_getobj = ex_getobj;
+ exinfo->HspFunc_setobj = ex_setobj;
+ exinfo->HspFunc_addobj = ex_addobj;
+ exinfo->HspFunc_mref = ex_mref;
+}
+
+void hsp3typeinit_extfunc( HSP3TYPEINFO *info )
+{
+ info->reffunc = reffunc_sysvar;
+}
+
+
+void hsp3gr_nextobj( void )
+{
+ // [TAB]を押して次のobjectを選択
+ //
+ Bmscr *bm;
+ int id, plus;
+ id = wnd->GetActive();
+ if ( id<0 ) return;
+ plus = 1;
+ if ( GetAsyncKeyState(VK_SHIFT)&0x8000 ) plus=-1; // [shift]
+ bm = wnd->GetBmscr( id );
+ if ( bm->tabmove ) {
+ bm->NextObject( plus );
+ }
+}
+
+
+#ifdef HSPDEBUG
+void hsp3gr_dbg_gui( void )
+{
+ // デバッグウインドゥ用情報
+ //
+ code_adddbg( "ディレクトリ", getdir(0) );
+ code_adddbg( "コマンドライン", getdir(4) );
+ code_adddbg( "ウインドゥ最大", wnd->GetBmscrMax() );
+ code_adddbg( "カレントウインドゥ", cur_window );
+}
+#endif
diff --git a/src/hsp3/win32gui/hsp3gr_wingui.h b/src/hsp3/win32gui/hsp3gr_wingui.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce240f10ef1876e9f111fb9e1385d3fa54dbe64c
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3gr_wingui.h
@@ -0,0 +1,17 @@
+
+//
+// hsp3gr.cpp header
+//
+#ifndef HSP3GR_WINGUI_H
+#define HSP3GR_WINGUI_H
+
+#include "../hsp3struct.h"
+
+void hsp3typeinit_extcmd( HSP3TYPEINFO *info, int sx, int sy, int wd, int xx, int yy );
+void hsp3typeinit_extfunc( HSP3TYPEINFO *info );
+void hsp3gui_mref( PVal *pval, int prm );
+void hsp3gr_nextobj( void );
+
+void hsp3gr_dbg_gui( void );
+
+#endif
diff --git a/src/hsp3/win32gui/hsp3win.cpp b/src/hsp3/win32gui/hsp3win.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..11fbd7e73a299553ed5240f30a9c7d5f869e802a
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3win.cpp
@@ -0,0 +1,547 @@
+/*--------------------------------------------------------
+ HSP3 main (Windows GUI)
+ 2004/8 onitama
+ --------------------------------------------------------*/
+
+#define _WIN32_DCOM
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if defined( __GNUC__ )
+#include
+#endif
+
+#include "hsp3win.h"
+#include "../strbuf.h"
+#include "../hsp3.h"
+#include "../hsp3ext.h"
+#include "../hsp3gr.h"
+
+#include "hsp3extlib.h"
+#include "hspvar_comobj.h"
+#include "hspvar_variant.h"
+#include "../supio.h"
+
+typedef BOOL (CALLBACK *HSP3DBGFUNC)(HSP3DEBUG *,int,int,int);
+
+/*----------------------------------------------------------*/
+
+static Hsp3 *hsp = NULL;
+static HSPCTX *ctx;
+
+static char fpas[]={ 'H'-48,'S'-48,'P'-48,'H'-48,
+ 'E'-48,'D'-48,'~'-48,'~'-48 };
+static char optmes[] = "HSPHED~~\0_1_________2_________3______";
+
+static int hsp_wx, hsp_wy, hsp_wd, hsp_ss;
+
+#ifndef HSPDEBUG
+static int hsp_sscnt, hsp_ssx, hsp_ssy;
+#endif
+
+#ifdef HSPDEBUG
+static HSP3DBGFUNC dbgwin;
+static HSP3DBGFUNC dbgnotice;
+static HINSTANCE h_dbgwin;
+static HWND dbgwnd;
+static HSP3DEBUG *dbginfo;
+#endif
+
+//-------------------------------------------------------------
+// Sync Timer Routines
+//-------------------------------------------------------------
+
+static int timer_period = -1;
+static int timerid = 0;
+
+/*----------------------------------------------------------*/
+
+void hsp3win_dialog( char *mes )
+{
+ HSPAPICHAR *hactmp1 = 0;
+ MessageBox( NULL, chartoapichar(mes,&hactmp1), TEXT("Error"),MB_ICONEXCLAMATION | MB_OK );
+ freehac(&hactmp1);
+}
+
+
+#ifdef HSPDEBUG
+char *hsp3win_debug( int type )
+{
+ // デバッグ情報取得
+ //
+ char *p;
+ p = code_inidbg();
+
+ switch( type ) {
+ case DEBUGINFO_GENERAL:
+ hsp3gr_dbg_gui();
+ code_dbg_global();
+ break;
+ case DEBUGINFO_VARNAME:
+ break;
+ case DEBUGINFO_INTINFO:
+ break;
+ case DEBUGINFO_GRINFO:
+ break;
+ case DEBUGINFO_MMINFO:
+ break;
+ }
+ return p;
+}
+#endif
+
+
+int hsp3win_debugopen( void )
+{
+ // デバッグウインドゥ表示
+ //
+#ifdef HSPDEBUG
+ if ( h_dbgwin != NULL ) return 0;
+#ifdef HSP64
+ h_dbgwin = LoadLibrary( HSP3DEBUG_MODULE "_64.dll" );
+#else
+#ifndef HSPUTF8
+ h_dbgwin = LoadLibrary(TEXT( HSP3DEBUG_MODULE ".dll" ));
+#else
+ h_dbgwin = LoadLibrary(TEXT( HSP3DEBUG_MODULE ) TEXT("_u8.dll") );
+#endif
+#endif
+ if ( h_dbgwin != NULL ) {
+#ifdef HSP64
+ dbgwin = (HSP3DBGFUNC)GetProcAddress(h_dbgwin, HSP3DEBUG_INIT );
+ dbgnotice = (HSP3DBGFUNC)GetProcAddress( h_dbgwin, HSP3DEBUG_NOTICE );
+#else
+ dbgwin = (HSP3DBGFUNC)GetProcAddress(h_dbgwin, "_" HSP3DEBUG_INIT "@16");
+ dbgnotice = (HSP3DBGFUNC)GetProcAddress(h_dbgwin, "_" HSP3DEBUG_NOTICE "@16");
+#endif
+ if ((dbgwin == NULL) || (dbgnotice == NULL)) h_dbgwin = NULL;
+ }
+ if ( h_dbgwin == NULL ) {
+ hsp3win_dialog( "No debug module." );
+ return -1;
+ }
+ dbginfo->get_value = hsp3win_debug;
+ dbgwin( dbginfo, 0, 0, 0 );
+ dbgwnd = (HWND)( dbginfo->dbgwin );
+#endif
+ return 0;
+}
+
+
+static void hsp3win_dispatch( MSG *msg )
+{
+ TranslateMessage( msg );
+ DispatchMessage( msg );
+
+#ifndef HSPDEBUG
+ // スクリーンセーバー終了チェック
+ //
+ if ( ctx->hspstat & HSPSTAT_SSAVER ) {
+ int x,y;
+ if ( msg->message==WM_MOUSEMOVE ) {
+ x = LOWORD(msg->lParam);
+ y = HIWORD(msg->lParam);
+ if ( hsp_sscnt == 0 ) {
+ if (( hsp_ssx != x )||( hsp_ssy != y )) throw HSPERR_NONE;
+ } else {
+ hsp_ssx = x;
+ hsp_ssy = y;
+ }
+ }
+ if ( msg->message==WM_KEYDOWN ) {
+ if ( hsp_sscnt == 0 ) throw HSPERR_NONE;
+ }
+ }
+#endif
+
+ if ( msg->message==WM_KEYDOWN ) { // ocheck onkey
+ if ( msg->wParam == 9 ) {
+ hsp3gr_nextobj();
+ }
+ if ( code_isirq( HSPIRQ_ONKEY ) ) {
+ code_sendirq( HSPIRQ_ONKEY, (int)MapVirtualKey( msg->wParam, 2 ), (int)msg->wParam, (int)msg->lParam );
+ }
+ }
+}
+
+
+void hsp3win_msgfunc( HSPCTX *hspctx )
+{
+ MSG msg;
+ int tick;
+
+ while(1) {
+ // logmes なら先に処理する
+ if ( hspctx->runmode == RUNMODE_LOGMES ) {
+ hspctx->runmode = RUNMODE_RUN;
+#ifdef HSPDEBUG
+ if ( h_dbgwin != NULL ) dbgnotice( dbginfo, 1, 0, 0 ); // Debug Window Notice
+#endif
+ return;
+ }
+
+ if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
+ if (msg.message == WM_QUIT ) throw HSPERR_NONE;
+ hsp3win_dispatch( &msg );
+ continue;
+ }
+
+ switch( hspctx->runmode ) {
+ case RUNMODE_STOP:
+#ifdef HSPDEBUG
+ if ( h_dbgwin != NULL ) dbgnotice( dbginfo, 0, 0, 0 ); // Debug Window Notice
+#endif
+ while(1) {
+ GetMessage( &msg, NULL, 0, 0 );
+ if ( msg.message == WM_QUIT ) throw HSPERR_NONE;
+ hsp3win_dispatch( &msg );
+ if ( hspctx->runmode != RUNMODE_STOP ) break;
+ }
+
+ MsgWaitForMultipleObjects(0, NULL, FALSE, 1000, QS_ALLINPUT );
+ break;
+ case RUNMODE_WAIT:
+ if ( timer_period == -1 ) {
+ // 通常のタイマー
+ tick = GetTickCount();
+ } else {
+ // 高精度タイマー
+ tick = timeGetTime();
+ }
+ hspctx->runmode = code_exec_wait( tick );
+ case RUNMODE_AWAIT:
+ if ( timer_period == -1 ) {
+
+ // 通常のタイマー
+ tick = GetTickCount();
+ if ( code_exec_await( tick ) != RUNMODE_RUN ) {
+ MsgWaitForMultipleObjects(0, NULL, FALSE, hspctx->waittick - tick, QS_ALLINPUT );
+ } else {
+#ifndef HSPDEBUG
+ if ( ctx->hspstat & HSPSTAT_SSAVER ) {
+ if ( hsp_sscnt ) hsp_sscnt--;
+ }
+#endif
+ }
+ } else {
+ // 高精度タイマー
+ tick = timeGetTime()+5; // すこし早めに抜けるようにする
+ if ( code_exec_await( tick ) != RUNMODE_RUN ) {
+ MsgWaitForMultipleObjects(0, NULL, FALSE, hspctx->waittick - tick, QS_ALLINPUT );
+ } else {
+ tick = timeGetTime();
+ while( tick < hspctx->waittick ) { // 細かいwaitを取る
+ Sleep(1);
+ tick = timeGetTime();
+ }
+ hspctx->lasttick = tick;
+ hspctx->runmode = RUNMODE_RUN;
+#ifndef HSPDEBUG
+ if ( ctx->hspstat & HSPSTAT_SSAVER ) {
+ if ( hsp_sscnt ) hsp_sscnt--;
+ }
+#endif
+ }
+ }
+ break;
+// case RUNMODE_END:
+// throw HSPERR_NONE;
+ case RUNMODE_RETURN:
+ throw HSPERR_RETURN_WITHOUT_GOSUB;
+ case RUNMODE_INTJUMP:
+ throw HSPERR_INTJUMP;
+ case RUNMODE_ASSERT:
+ hspctx->runmode = RUNMODE_STOP;
+#ifdef HSPDEBUG
+ hsp3win_debugopen();
+#endif
+ break;
+ // case RUNMODE_LOGMES:
+ default:
+ return;
+ }
+
+ }
+}
+
+
+int hsp3win_init( HINSTANCE hInstance, char *startfile )
+{
+ // システム関連の初期化
+ // ( mode:0=debug/1=release )
+ //
+ int a,orgexe, mode;
+ int hsp_sum, hsp_dec;
+ char a1;
+#ifdef HSPDEBUG
+ char fname[_MAX_PATH + 1];
+#endif
+#ifndef HSPDEBUG
+ TCHAR fnamew[_MAX_PATH+1];
+ TCHAR fnamew2[_MAX_PATH + 1];
+#endif
+ char *ss;
+ LPTSTR cl;
+#ifdef HSPDEBUG
+ int i;
+#endif
+
+#ifndef HSP_COM_UNSUPPORTED
+ if ( FAILED( CoInitializeEx( NULL, COINIT_APARTMENTTHREADED) ) ) {
+ return 1;
+ }
+ OleInitialize( NULL );
+#endif
+ InitCommonControls();
+
+ // HSP関連の初期化
+ //
+ hsp = new Hsp3();
+ hsp->hspctx.instance = (void *)hInstance;
+#ifdef HSPDEBUG
+ h_dbgwin = NULL;
+ dbgwnd = NULL;
+
+ ss = strsp_cmds( startfile );
+ i = (int)( ss - startfile );
+ ss = startfile;
+ if ( ss[i-1] == 32 ) i--;
+ if ( *ss == 0x22 ) {
+ ss++;i-=2;
+ }
+ if ( i > 0 ) {
+ strncpy( fname, ss, i );
+ fname[i] = 0;
+ hsp->SetFileName( fname );
+ }
+#else
+ if (startfile != NULL) {
+ hsp->SetFileName(startfile);
+ }
+#endif
+
+
+ // 実行ファイルかデバッグ中かを調べる
+ //
+ mode = 0;
+ orgexe=0;
+ hsp_wx = 640;
+ hsp_wy = 480;
+ hsp_wd = 0;
+ hsp_ss = 0;
+
+ for( a=0 ; a<8; a++) {
+ a1=optmes[a]-48;if (a1==fpas[a]) orgexe++;
+ }
+ if ( orgexe == 0 ) {
+ mode = atoi(optmes+9) + 0x10000;
+ a1=*(optmes+17);
+ if ( a1 == 's' ) hsp_ss = HSPSTAT_SSAVER;
+ hsp_wx=*(short *)(optmes+20);
+ hsp_wy=*(short *)(optmes+23);
+ hsp_wd=( *(short *)(optmes+26) );
+ hsp_sum=*(unsigned short *)(optmes+29);
+ hsp_dec=*(int *)(optmes+32);
+ hsp->SetPackValue( hsp_sum, hsp_dec );
+ }
+#ifndef HSPWINGUIDLL
+ // 起動ファイルのディレクトリをカレントにする
+ //
+#ifndef HSPDEBUG
+ if (( hsp_wd & 2 ) == 0 ) {
+ GetModuleFileName( NULL, fnamew, _MAX_PATH );
+ getpathW( fnamew, fnamew2, 32 );
+ changedirW( fnamew2 );
+ }
+#endif
+#endif
+ if ( hsp->Reset( mode ) ) {
+ hsp3win_dialog( "Startup failed." );
+ return 1;
+ }
+
+ ctx = &hsp->hspctx;
+
+ {
+ // コマンドライン関連
+ cl = GetCommandLine();
+ cl = strsp_cmdsW( cl );
+#ifdef HSPDEBUG
+ cl = strsp_cmdsW( cl );
+#endif
+ apichartohspchar(cl,&ss);
+ sbStrCopy( &ctx->cmdline, ss ); // コマンドラインパラメーターを保存
+ }
+
+ // SSaver proc
+ //
+#ifndef HSPDEBUG
+ if ( hsp_ss ) {
+ cl = GetCommandLine();
+ cl = strsp_cmdsW( cl );
+ hsp_sscnt = 30;
+ a1=tolower(*(cl+1));
+ if (FindWindow(TEXT("oniwndp"), NULL) != NULL) {
+ freehc(&ss);
+ return 2;
+ }
+ if (a1==TEXT('p')) {
+ HWND s_hwnd;
+ RECT rPic;
+ s_hwnd = (HWND)_tstoi( cl+3 );
+ GetWindowRect( s_hwnd, &rPic );
+ hsp_wx = rPic.right-rPic.left;
+ hsp_wy = rPic.bottom-rPic.top;
+ hsp_wd = 0x100;
+ ctx->wnd_parent = s_hwnd;
+ }
+ if (a1==TEXT('s')) {
+ ShowCursor(FALSE);
+ } else {
+ hsp_ss = 0; // スクリーンセーバー時以外はモードOFF
+ }
+ ctx->hspstat |= hsp_ss;
+ }
+#endif
+ freehc(&ss);
+ // Register Type
+ //
+ ctx->msgfunc = hsp3win_msgfunc;
+
+#ifndef HSP_COM_UNSUPPORTED
+ HspVarCoreRegisterType( TYPE_COMOBJ, HspVarComobj_Init );
+ HspVarCoreRegisterType( TYPE_VARIANT, HspVarVariant_Init );
+#endif
+
+
+ // timerGetTime関数による精度アップ(μ秒単位)
+ timer_period = -1;
+ if (( ctx->hsphed->bootoption & HSPHED_BOOTOPT_NOMMTIMER ) == 0 ) {
+ TIMECAPS caps;
+ if ( timeGetDevCaps(&caps,sizeof(TIMECAPS)) == TIMERR_NOERROR ){
+ // マルチメディアタイマーのサービス精度を最大に
+ timer_period = caps.wPeriodMin;
+ timeBeginPeriod( timer_period );
+ }
+ }
+
+ // Initalize GUI System
+ //
+ hsp3typeinit_dllcmd( code_gettypeinfo( TYPE_DLLFUNC ) );
+ hsp3typeinit_dllctrl( code_gettypeinfo( TYPE_DLLCTRL ) );
+ hsp3typeinit_extcmd( code_gettypeinfo( TYPE_EXTCMD ), hsp_wx, hsp_wy, hsp_wd, -1, -1 );
+ hsp3typeinit_extfunc( code_gettypeinfo( TYPE_EXTSYSVAR ) );
+
+#ifdef HSPDEBUG
+ dbginfo = code_getdbg();
+#endif
+ return 0;
+}
+
+void hsp3win_bye( void )
+{
+ // HSP関連の解放
+ //
+ if ( hsp != NULL ) { delete hsp; hsp = NULL; }
+
+ // タイマーの開放
+ //
+ if ( timer_period != -1 ) {
+ timeEndPeriod( timer_period );
+ timer_period = -1;
+ }
+
+#ifdef HSPDEBUG
+ // デバッグウインドゥの解放
+ //
+ if ( h_dbgwin != NULL ) { FreeLibrary( h_dbgwin ); h_dbgwin = NULL; }
+#endif
+
+ DllManager().free_all_library();
+
+ // システム関連の解放
+ //
+#ifndef HSP_COM_UNSUPPORTED
+ OleUninitialize();
+ CoUninitialize();
+#endif
+}
+
+
+void hsp3win_error( void )
+{
+ char errmsg[1024];
+ char *msg;
+ char *fname;
+ HSPERROR err;
+ int ln;
+ err = code_geterror();
+ ln = code_getdebug_line();
+ msg = hspd_geterror(err);
+ fname = code_getdebug_name();
+
+ if ( ln < 0 ) {
+ sprintf( errmsg, "#Error %d\n-->%s\n",(int)err,msg );
+ fname = NULL;
+ } else {
+ sprintf( errmsg, "#Error %d in line %d (%s)\n-->%s\n",(int)err, ln, fname, msg );
+ }
+ hsp3win_debugopen();
+ hsp3win_dialog( errmsg );
+}
+
+
+int hsp3win_exec( void )
+{
+ // 実行メインを呼び出す
+ //
+ int runmode;
+ int endcode;
+rerun:
+ hsp3win_msgfunc( ctx );
+
+ // デバッグウインドゥ用
+ //
+#ifdef HSPDEBUG
+ if ( ctx->hsphed->bootoption & HSPHED_BOOTOPT_DEBUGWIN ) {
+ if ( hsp3win_debugopen() ) return -1;
+ }
+#endif
+
+ // 実行の開始
+ //
+ runmode = code_execcmd();
+ if ( runmode == RUNMODE_ERROR ) {
+ try {
+ hsp3win_error();
+ }
+ catch( ... ) {
+ }
+ return -1;
+ }
+ if ( runmode == RUNMODE_EXITRUN ) {
+ char fname[_MAX_PATH];
+ char cmd[1024];
+ HINSTANCE inst;
+ int res;
+ strncpy( fname, ctx->refstr, _MAX_PATH-1 );
+ strncpy( cmd, ctx->stmp, 1023 );
+ inst = (HINSTANCE)ctx->instance;
+
+ hsp3win_bye();
+ res = hsp3win_init( inst, fname );
+ if ( res ) return res;
+
+ strncpy( ctx->cmdline, cmd, 1023 );
+ goto rerun;
+ }
+ endcode = ctx->endcode;
+ hsp3win_bye();
+ return endcode;
+}
+
diff --git a/src/hsp3/win32gui/hsp3win.h b/src/hsp3/win32gui/hsp3win.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6f8605f45269bbaecc7d97dff611d5abea86dbe
--- /dev/null
+++ b/src/hsp3/win32gui/hsp3win.h
@@ -0,0 +1,13 @@
+
+//
+// hsp3win.cpp header
+//
+#ifndef __hsp3win_h
+#define __hsp3win_h
+
+int hsp3win_exec( void );
+int hsp3win_init( HINSTANCE hInstance, char *startfile );
+void hsp3win_dialog( char *mes );
+void hsp3win_bye( void );
+
+#endif
diff --git a/src/hsp3/win32gui/hspvar_comobj.cpp b/src/hsp3/win32gui/hspvar_comobj.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..730e6ae23186e0c6f26f5bcc95ce8975ce787e8a
--- /dev/null
+++ b/src/hsp3/win32gui/hspvar_comobj.cpp
@@ -0,0 +1,425 @@
+
+//
+// HSPVAR core module
+// onion software/onitama 2004/10
+//
+
+#ifndef HSP_COM_UNSUPPORTED //(COM サポートなし版のビルド時はファイル全体を無視)
+
+#include
+#include
+#include
+
+#include
+
+#include "../hsp3code.h"
+#include "../hsp3struct.h"
+#include "../hsp3ext.h"
+#include "../hspvar_core.h"
+#include "comobj.h"
+#include "hspvar_comobj.h"
+#include "comobj_event.h"
+#include "../strbuf.h"
+#include "../supio.h"
+
+/*------------------------------------------------------------*/
+/*
+ HSPVAR core interface (COM Object)
+*/
+/*------------------------------------------------------------*/
+
+static HspVarProc *myproc;
+
+// Core
+static PDAT *HspVarComobj_GetPtr( PVal *pval )
+{
+ return (PDAT *)(( (IUnknown **)(pval->pt))+pval->offset);
+}
+
+static void *HspVarComobj_Cnv( const void *buffer, int flag )
+{
+ // リクエストされた型 -> 自分の型への変換を行なう
+ // (組み込み型にのみ対応でOK)
+ // (参照元のデータを破壊しないこと)
+ //
+ throw HSPERR_INVALID_TYPE;
+ return (void *)buffer;
+}
+
+
+static void *HspVarComobj_CnvCustom( const void *buffer, int flag )
+{
+ // (カスタムタイプのみ)
+ // 自分の型 -> リクエストされた型 への変換を行なう
+ // (組み込み型に対応させる)
+ // (参照元のデータを破壊しないこと)
+ //
+ throw HSPERR_INVALID_TYPE;
+ return (void *)buffer;
+}
+
+static void HspVarComobj_Free( PVal *pval )
+{
+ // PVALポインタの変数メモリを解放する
+ //
+ IUnknown** ppunk;
+ if ( pval->master ) {
+ FreeDispParams( (ComDispParams *)pval->master );
+ }
+ if ( pval->mode == HSPVAR_MODE_MALLOC ) {
+ // (一時変数に含まれるオブジェクトは Release しない)
+ if ( (pval->support & HSPVAR_SUPPORT_TEMPVAR) == 0 ) {
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "HspVarComobj_Free()\n" );
+#endif
+ int count = HspVarCoreCountElems( pval );
+ ppunk = (IUnknown **)pval->pt;
+ for (int i=0; ipt );
+ }
+ pval->pt = NULL;
+ pval->flag = HSPVAR_MODE_NONE;
+}
+
+
+static void HspVarComobj_Alloc( PVal *pval, const PVal *pval2 )
+{
+ // pval変数が必要とするサイズを確保する。
+ // (pvalがすでに確保されているメモリ解放は呼び出し側が行なう)
+ // (pval2がNULLの場合は、新規データ)
+ // (pval2が指定されている場合は、pval2の内容を継承して再確保)
+ //
+ int count,size;
+ IUnknown **ppunk;
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "HspVarComobj_Alloc()\n" );
+#endif
+ if ( pval->len[1] < 1 ) pval->len[1] = 1; // 配列を最低 1 は確保する
+ count = HspVarCoreCountElems(pval);
+ size = count * sizeof( IUnknown* );
+ ppunk = (IUnknown **)sbAlloc( size );
+ pval->mode = HSPVAR_MODE_MALLOC;
+ for (int i=0; ipt, pval->size );
+ sbFree( pval->pt );
+ if ( pval->master ) sbFree( pval->master );
+ }
+ pval->master = NULL; // ComDispParams 用
+ pval->pt = (char *)ppunk;
+ pval->size = size;
+
+}
+
+static void HspVarComobj_ObjectMethod( PVal *pval )
+{
+ // メソッドの実行
+ //
+ VARIANT vres;
+ HRESULT hr;
+ char *ps;
+ DISPID dispid;
+ IUnknown** ppunk;
+ BOOL bVariantRet;
+
+// ppunk = (IUnknown**)HspVarCorePtrAPTR( pval, pval->offset );
+ ppunk = (IUnknown **)pval->pt;
+ if ( ! IsVaridComPtr(ppunk) ) throw HSPERR_COMDLL_ERROR;
+
+ // メソッド名から DISPID を取得
+ ps = code_gets();
+ dispid = get_dispid( *ppunk, ps, &bVariantRet );
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "ObjectMethod() : pObj=0x%p : PropName=\"%s\" (DISPID=%d)\n", *ppunk, ps, dispid);
+#endif
+ // メソッドパラメータの取得・メソッド実行
+ VariantInit( &vres );
+ hr = CallDispMethod( *ppunk, dispid, &vres );
+ comget_variantres( &vres, hr, bVariantRet ); // 返値を取得
+ VariantClear( &vres );
+}
+
+static int code_get_element( PVal *pval )
+{
+ // 変数の配列要素の取得
+ //
+ PVal pvalTemp;
+ int chk, idx;
+ HspVarCoreReset(pval);
+ while (1) {
+ HspVarCoreCopyArrayInfo( &pvalTemp, pval ); // 状態を保存
+ chk = code_get();
+ HspVarCoreCopyArrayInfo( pval, &pvalTemp ); // 状態を復帰
+ if ( chk == PARAM_ENDSPLIT ) {
+ if ( pval->arraycnt == 0 ) throw HSPERR_BAD_ARRAY_EXPRESSION; // a() 表記はエラー
+ break;
+ }
+ if ( chk != PARAM_OK && chk != PARAM_SPLIT ) throw HSPERR_ARRAY_OVERFLOW;
+ if ( mpval->flag != HSPVAR_FLAG_INT ) break;
+ idx = *(int *)(mpval->pt);
+ HspVarCoreArray( pval, idx );
+ }
+ return chk;
+}
+
+static void HspVarComobj_ArrayObject( PVal *pval )
+{
+ // 配列要素の指定 (連想配列用)
+ //
+ IUnknown** ppunk;
+ int chk;
+ DISPID dispid;
+ ComDispParams *paramdata;
+
+ // 配列要素の取得
+ chk = code_get_element( pval );
+ if ( chk == PARAM_ENDSPLIT ) return; // 配列要素が指定された場合はそのまま
+
+ // プロパティ設定時
+ ppunk = (IUnknown **)HspVarComobj_GetPtr( pval );
+ if ( ! IsVaridComPtr(ppunk) ) throw HSPERR_COMDLL_ERROR;
+ // プロパティ名から DISPID を取得
+ if ( mpval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ dispid = get_dispid( *ppunk, (char *)(mpval->pt), NULL );
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "ArrayObject() : pObj=0x%p : PropName=\"%s\" (DISPID=%d)\n", *ppunk, mpval->pt, dispid);
+#endif
+ // パラメータ取得し保持しておく
+ paramdata = PrepForPutDispProp( *ppunk, dispid );
+ if ( pval->master ) FreeDispParams( (ComDispParams *)pval->master );
+ pval->master = paramdata;
+}
+
+static void HspVarComobj_ObjectWrite( PVal *pval, void *data, int vtype )
+{
+ // 可変型の代入
+ //
+ ComDispParams *paramdata;
+ HRESULT hr;
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "ObjectWrite()\n" );
+#endif
+ // プロパティ設定時
+ paramdata = (ComDispParams *)pval->master;
+ if ( paramdata == NULL ) throw ( HSPERR_COMDLL_ERROR );
+ hr = PutDispProp( paramdata, data, vtype );
+ FreeDispParams( paramdata );
+ pval->master = NULL;
+
+ if ( FAILED(hr) ) throw ( HSPERR_COMDLL_ERROR );
+}
+
+
+static void get_coclassname( IUnknown *punk, VARIANT *vres )
+{
+ HRESULT hr;
+ IProvideClassInfo *pPCI;
+ ITypeInfo *pTI;
+ BSTR bstr = NULL;
+ hr = punk->QueryInterface( IID_IProvideClassInfo, (void **)&pPCI );
+ if ( SUCCEEDED(hr) && pPCI != NULL ) {
+ hr = pPCI->GetClassInfo( &pTI );
+ if ( SUCCEEDED(hr) && pTI != NULL ) {
+ hr = pTI->GetDocumentation( MEMBERID_NIL, &bstr, NULL, NULL, NULL );
+ pTI->Release();
+ }
+ pPCI->Release();
+ }
+ if ( bstr == NULL ) {
+ bstr = SysAllocString( L"" );
+ }
+ vres->bstrVal = bstr;
+ vres->vt = VT_BSTR;
+}
+static void get_interfacename( IUnknown *punk, VARIANT *vres )
+{
+ HRESULT hr;
+ IDispatch *pDisp;
+ ITypeInfo *pTI;
+ BSTR bstr = NULL;
+ hr = punk->QueryInterface( IID_IDispatch, (void **)&pDisp );
+ if ( SUCCEEDED(hr) && pDisp != NULL ) {
+ hr = pDisp->GetTypeInfo( 0, LOCALE_USER_DEFAULT, &pTI );
+ if ( SUCCEEDED(hr) && pTI != NULL ) {
+ hr = pTI->GetDocumentation( MEMBERID_NIL, &bstr, NULL, NULL, NULL );
+ pTI->Release();
+ }
+ pDisp->Release();
+ }
+ if ( bstr == NULL ) {
+ bstr = SysAllocString( L"" );
+ }
+ vres->bstrVal = bstr;
+ vres->vt = VT_BSTR;
+}
+
+static void *HspVarComobj_ArrayObjectRead( PVal *pval, int *mptype )
+{
+ // 配列要素の指定 (連想配列/読み出し)
+ //
+ void *ptr;
+ IUnknown **ppunk;
+ int chk;
+ DISPID dispid;
+ VARIANT vres;
+ BOOL noconvret;
+ char *propname;
+ HRESULT hr = S_OK;
+
+ // 配列要素の取得
+ chk = code_get_element( pval );
+ ppunk = (IUnknown **)HspVarComobj_GetPtr( pval );
+ if ( chk == PARAM_ENDSPLIT ) return ppunk; // 配列要素が指定された場合はそのまま
+
+ // プロパティ取得時
+ // プロパティ名から DISPID を取得
+ if ( ! IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR );
+ if ( mpval->flag != HSPVAR_FLAG_STR ) throw ( HSPERR_TYPE_MISMATCH );
+ propname = (char *)(mpval->pt);
+ VariantInit( &vres );
+ if ( propname[0] == '$' ) {
+ noconvret = FALSE;
+ if ( stricmp( propname, "$coclass" ) == 0 ) {
+ get_coclassname( *ppunk, &vres );
+ } else if ( stricmp( propname, "$interface" ) == 0 ) {
+ get_interfacename( *ppunk, &vres );
+ } else {
+ throw HSPERR_INVALID_PARAMETER;
+ }
+ } else {
+ dispid = get_dispid( *ppunk, propname, &noconvret );
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "ArrayObjectRead() : pObj=0x%p : PropName=\"%s\" (DISPID=%d)\n", *ppunk, mpval->pt, dispid);
+#endif
+ // パラメータを取得・プロパティ取得
+ hr = GetDispProp( *ppunk, dispid, &vres );
+ }
+ ptr = comget_variant( &vres, mptype, noconvret );
+ VariantClear( &vres );
+ if ( FAILED(hr) ) throw ( HSPERR_COMDLL_ERROR );
+ return ptr;
+}
+
+
+// Size
+static int HspVarComobj_GetSize( const PDAT *pdatl )
+{
+ // (実態のポインタが渡されます)
+ return sizeof(IUnknown*);
+}
+
+// Using
+static int HspVarComobj_GetUsing( const PDAT *pdat )
+{
+ // (実態のポインタが渡されます)
+ return IsVaridComPtr((IUnknown**)pdat);
+}
+
+// Set
+static void HspVarComobj_Set( PVal *pval, PDAT *pdat, const void *in )
+{
+ IUnknown **ppunkSrc, **ppunkDst;
+
+ ppunkDst = (IUnknown **)pdat;
+ ppunkSrc = (IUnknown **)in;
+ if ( pval->support & HSPVAR_SUPPORT_TEMPVAR ) {
+ // 代入先が一時変数の場合は AddRef() しない
+ *ppunkDst = *ppunkSrc;
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "ppunkDst is Temporary objedct.\n");
+#endif
+ } else {
+ CopyComPtr( ppunkDst, *ppunkSrc );
+ }
+}
+
+
+static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size )
+{
+ *size = pval->size - ( ((char *)pdat) - pval->pt );
+ return (pdat);
+}
+
+static void AllocBlock( PVal *pval, PDAT *pdat, int size )
+{
+}
+
+// Eq
+static void HspVarComobj_EqI( PDAT *pdat, const void *val )
+{
+ *(int *)pdat = IsSameComObject( (IUnknown **)pdat, (IUnknown **)val );
+ myproc->aftertype = HSPVAR_FLAG_INT;
+}
+
+// Ne
+static void HspVarComobj_NeI( PDAT *pdat, const void *val )
+{
+ *(int *)pdat = !IsSameComObject( (IUnknown **)pdat, (IUnknown **)val );
+ myproc->aftertype = HSPVAR_FLAG_INT;
+}
+
+
+/*------------------------------------------------------------*/
+
+void HspVarComobj_Init( HspVarProc *p )
+{
+ myproc = p;
+
+ p->Set = HspVarComobj_Set;
+ p->Cnv = HspVarComobj_Cnv;
+ p->GetPtr = HspVarComobj_GetPtr;
+ p->CnvCustom = HspVarComobj_CnvCustom;
+ p->GetSize = HspVarComobj_GetSize;
+ p->GetUsing = HspVarComobj_GetUsing;
+ p->GetBlockSize = GetBlockSize;
+ p->AllocBlock = AllocBlock;
+
+ p->ArrayObject = HspVarComobj_ArrayObject;
+ p->ArrayObjectRead = HspVarComobj_ArrayObjectRead;
+ p->ObjectWrite = HspVarComobj_ObjectWrite;
+ p->ObjectMethod = HspVarComobj_ObjectMethod;
+
+ p->Alloc = HspVarComobj_Alloc;
+ p->Free = HspVarComobj_Free;
+ p->EqI = HspVarComobj_EqI;
+ p->NeI = HspVarComobj_NeI;
+
+/*
+ p->AddI = HspVarComobj_Invalid;
+ p->SubI = HspVarComobj_Invalid;
+ p->MulI = HspVarComobj_Invalid;
+ p->DivI = HspVarComobj_Invalid;
+ p->ModI = HspVarComobj_Invalid;
+
+ p->AndI = HspVarComobj_Invalid;
+ p->OrI = HspVarComobj_Invalid;
+ p->XorI = HspVarComobj_Invalid;
+
+ p->EqI = HspVarComobj_Invalid;
+ p->NeI = HspVarComobj_Invalid;
+ p->GtI = HspVarComobj_Invalid;
+ p->LtI = HspVarComobj_Invalid;
+ p->GtEqI = HspVarComobj_Invalid;
+ p->LtEqI = HspVarComobj_Invalid;
+
+ p->RrI = HspVarComobj_Invalid;
+ p->LrI = HspVarComobj_Invalid;
+*/
+ p->vartype_name = "comobj"; // タイプ名
+ p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0)
+ p->support = HSPVAR_SUPPORT_STORAGE | HSPVAR_SUPPORT_ARRAYOBJ | HSPVAR_SUPPORT_NOCONVERT | HSPVAR_SUPPORT_VARUSE;
+ // サポート状況フラグ(HSPVAR_SUPPORT_*)
+ p->basesize = sizeof(void*); // 1つのデータが使用するサイズ(byte) / 可変長の時は-1
+}
+
+/*------------------------------------------------------------*/
+
+
+
+
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
diff --git a/src/hsp3/win32gui/hspvar_comobj.h b/src/hsp3/win32gui/hspvar_comobj.h
new file mode 100644
index 0000000000000000000000000000000000000000..3971986268bf5a9a40b84f60a18e8e04eb3ebdf8
--- /dev/null
+++ b/src/hsp3/win32gui/hspvar_comobj.h
@@ -0,0 +1,35 @@
+
+//
+// hspvar_comobj.cpp header
+//
+#ifndef __hspvar_comobj_h
+#define __hspvar_comobj_h
+
+
+#ifndef HSP_COM_UNSUPPORTED //(COM サポートなし版のビルド時はファイル全体を無視)
+
+
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include
+#include
+#include "comobj.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TYPE_COMOBJ 6
+
+
+void HspVarComobj_Init( HspVarProc *p );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
+
+#endif // __hspvar_comobj_h
diff --git a/src/hsp3/win32gui/hspvar_variant.cpp b/src/hsp3/win32gui/hspvar_variant.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1746f4ed603218fa89edccf2573efe1a7a46377d
--- /dev/null
+++ b/src/hsp3/win32gui/hspvar_variant.cpp
@@ -0,0 +1,745 @@
+
+//
+// HSPVAR core module
+// onion software/onitama 2004/10
+//
+
+#ifndef HSP_COM_UNSUPPORTED //(COM サポートなし版のビルド時はファイル全体を無視)
+
+#include
+#include
+#include
+
+#include
+
+#include "../hsp3code.h"
+#include "../hsp3struct.h"
+#include "../hsp3ext.h"
+#include "../hspvar_core.h"
+#include "comobj.h"
+#include "hspvar_comobj.h"
+#include "hspvar_variant.h"
+#include "comobj_event.h"
+#include "../strbuf.h"
+#include "../supio.h"
+
+
+/*------------------------------------------------------------*/
+/*
+ HSPVAR core interface (COM Object)
+*/
+/*------------------------------------------------------------*/
+
+static HspVarProc *myproc;
+
+// Core
+static PDAT *HspVarVariant_GetPtr( PVal *pval )
+{
+ return (PDAT *)(( (VARIANT *)(pval->pt))+pval->offset);
+}
+
+static void *HspVarVariant_Cnv( const void *buffer, int flag )
+{
+ // リクエストされた型 -> 自分の型への変換を行なう
+ // (組み込み型にのみ対応でOK)
+ // (参照元のデータを破壊しないこと)
+ //
+ throw HSPERR_INVALID_TYPE;
+ return (void *)buffer;
+}
+
+
+static void *HspVarVariant_CnvCustom( const void *buffer, int flag )
+{
+ // (カスタムタイプのみ)
+ // 自分の型 -> リクエストされた型 への変換を行なう
+ // (組み込み型に対応させる)
+ // (参照元のデータを破壊しないこと)
+ //
+ throw HSPERR_INVALID_TYPE;
+ return (void *)buffer;
+}
+
+
+static void HspVarVariant_Free( PVal *pval )
+{
+ // PVALポインタの変数メモリを解放する
+ //
+ VARIANT *var;
+
+#ifdef HSP_COMOBJ_DEBUG
+ if ( pval->support & HSPVAR_SUPPORT_TEMPVAR ) {
+ COM_DBG_MSG( "HspVarVariant_Free() : * HSPVAR_SUPPORT_TEMPVAR *\n" );
+ } else {
+ COM_DBG_MSG( "HspVarVariant_Free()\n" );
+ }
+#endif
+
+ if ( pval->mode == HSPVAR_MODE_MALLOC ) {
+ if ( (pval->support & HSPVAR_SUPPORT_TEMPVAR) == 0 ) {
+ int count = HspVarCoreCountElems(pval);
+ var = (VARIANT *)pval->pt;
+ for (int i=0; ipt );
+ }
+ if ( pval->master ) sbFree( pval->master );
+ pval->master = NULL;
+ pval->pt = NULL;
+ pval->flag = HSPVAR_MODE_NONE;
+}
+
+static void HspVarVariant_Alloc( PVal *pval, const PVal *pval2 )
+{
+ // pval変数が必要とするサイズを確保する。
+ // (pvalがすでに確保されているメモリ解放は呼び出し側が行なう)
+ // (pval2がNULLの場合は、新規データ)
+ // (pval2が指定されている場合は、pval2の内容を継承して再確保)
+ //
+ int count,size;
+ VARIANT *var;
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "HspVarVariant_Alloc()\n" );
+#endif
+ if ( pval->len[1] < 1 ) pval->len[1] = 1; // 配列を最低 1 は確保する
+ count = HspVarCoreCountElems(pval);
+ size = count * sizeof( VARIANT );
+ var = (VARIANT *)sbAlloc( size );
+ pval->mode = HSPVAR_MODE_MALLOC;
+ for (int i=0; ipt, pval->size );
+ sbFree( pval->pt );
+ } else {
+ pval->master = sbAlloc( sizeof(VariantParam) );
+ }
+ ((VariantParam *)pval->master)->id = 0;
+ pval->pt = (char *)var;
+ pval->size = size;
+}
+
+static int getMethodID( char *name )
+{
+ // メソッド名からメソッドIDを取得
+ //
+ return HSPVAR_VARIANT_UNKNOWN;
+}
+
+static int getPropertyID( char *name )
+{
+ // プロパティ名からメソッドIDを取得
+ //
+ if ( name[0] == '\0' || stricmp(name,"val") == 0 || stricmp(name,"value") == 0 ) return HSPVAR_VARIANT_VALUE;
+ if ( stricmp(name,"vt") == 0 || stricmp(name,"vartype") == 0 ) return HSPVAR_VARIANT_VARTYPE;
+ if ( stricmp(name,"vtmask") == 0 ) return HSPVAR_VARIANT_VARTYPE_MASKED;
+ if ( stricmp(name,"isbyref") == 0 ) return HSPVAR_VARIANT_IS_BYREF;
+ if ( stricmp(name,"isarray") == 0 ) return HSPVAR_VARIANT_IS_ARRAY;
+ if ( stricmp(name,"refptr") == 0 ) return HSPVAR_VARIANT_REFPTR;
+ if ( stricmp(name,"arrayptr") == 0 ) return HSPVAR_VARIANT_ARRAY_PTR;
+ if ( stricmp(name,"arraylbound") == 0 ) return HSPVAR_VARIANT_ARRAY_LBOUND;
+ if ( stricmp(name,"arrayubound") == 0 ) return HSPVAR_VARIANT_ARRAY_UBOUND;
+ if ( stricmp(name,"arraycount") == 0 ) return HSPVAR_VARIANT_ARRAY_COUNT;
+ if ( stricmp(name,"bstrptr") == 0 ) return HSPVAR_VARIANT_BSTR_PTR;
+ return HSPVAR_VARIANT_UNKNOWN;
+}
+
+static void HspVarVariant_ObjectMethod( PVal *pval )
+{
+ // メソッドの実行
+ //
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+/*
+ VARIANT *var;
+ char *ps;
+ int id;
+
+ var = (VARIANT *)pval->pt;
+
+ // メソッド名から DISPID を取得
+ ps = code_gets();
+ id = getMethodID( ps );
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "HspVarVariant_ObjectMethod() : Method Name=\"%s\" (Method Id=%d)\n", ps, id);
+#endif
+ switch ( id ) {
+ default:
+ throw HSPERR_INVALID_PARAMETER;
+ }
+*/
+}
+
+static int code_get_element( PVal *pval )
+{
+ // 変数の配列要素の取得
+ //
+ PVal pvalTemp;
+ int chk, idx;
+ HspVarCoreReset(pval);
+ while (1) {
+ HspVarCoreCopyArrayInfo( &pvalTemp, pval ); // 状態を保存
+ chk = code_get();
+ HspVarCoreCopyArrayInfo( pval, &pvalTemp ); // 状態を復帰
+ if ( chk == PARAM_ENDSPLIT ) {
+ if ( pval->arraycnt == 0 ) throw HSPERR_BAD_ARRAY_EXPRESSION; // a() 表記はエラー
+ break;
+ }
+ if ( chk != PARAM_OK && chk != PARAM_SPLIT ) throw HSPERR_ARRAY_OVERFLOW;
+ if ( mpval->flag != HSPVAR_FLAG_INT ) break;
+ idx = *(int *)(mpval->pt);
+ HspVarCoreArray( pval, idx );
+ }
+ return chk;
+}
+
+static void code_get_safearray( SAFEARRAY *psa, VariantParam *vprm )
+{
+ // SafeArray の配列要素を取得
+ //
+ int i, chk;
+ if ( psa == NULL ) throw HSPERR_ARRAY_OVERFLOW;
+ vprm->dimcount = psa->cDims;
+ for ( i=0; idimcount; i++ ) {
+ chk = code_get();
+ switch ( chk ) {
+ case PARAM_OK:
+ case PARAM_SPLIT:
+ if ( mpval->flag != HSPVAR_FLAG_INT ) throw HSPERR_BAD_ARRAY_EXPRESSION;
+ vprm->index[i] = *(int *)(mpval->pt);
+ break;
+ default:
+ throw HSPERR_ARRAY_OVERFLOW;
+ }
+ }
+}
+
+static void HspVarVariant_ArrayObject( PVal *pval )
+{
+ // 配列要素の指定 (連想配列用)
+ //
+ VARIANT* var;
+ int chk, id;
+ VariantParam *vprm;
+ // 配列要素の取得
+ chk = code_get_element( pval );
+ if ( chk == PARAM_ENDSPLIT ) return; // 配列要素が指定された場合はそのまま
+
+ // プロパティ設定時
+ var = (VARIANT *)HspVarVariant_GetPtr( pval );
+ // プロパティ名からプロパティ ID 取得
+ if ( mpval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ id = getPropertyID( (char *)(mpval->pt) );
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "HspVarVariant_ArrayObject() : Property Name=\"%s\" (Property ID=%d)\n", mpval->pt, id);
+#endif
+ vprm = (VariantParam *)pval->master;
+ vprm->var = var;
+ vprm->id = id;
+ switch ( id ) {
+ case HSPVAR_VARIANT_VALUE:
+ if ( (var->vt & VT_ARRAY) && (chk != PARAM_SPLIT) ) {
+ // SafeArray の要素を取りに行く
+ SAFEARRAY *psa;
+ if ( var->vt & VT_BYREF ) {
+ psa = *var->pparray;
+ } else {
+ psa = var->parray;
+ }
+ code_get_safearray( psa, vprm );
+ vprm->id = HSPVAR_VARIANT_ARRAY_ELEMENT;
+ }
+ break;
+ case HSPVAR_VARIANT_VARTYPE:
+ case HSPVAR_VARIANT_ARRAY_PTR:
+ case HSPVAR_VARIANT_BSTR_PTR:
+ break;
+ default:
+ throw HSPERR_INVALID_PARAMETER;
+ }
+ // ')' で閉じているか(これ以降にパラメータがないか)
+ if ( code_get() != PARAM_ENDSPLIT ) throw HSPERR_BAD_ARRAY_EXPRESSION;
+}
+
+void comcheck_variant_conv( VARTYPE vt, int vtype )
+{
+ // HSP変数 <=> Variant 間の型チェック
+ //
+ switch ( vtype ) {
+ case HSPVAR_FLAG_STR:
+ if ( vt == VT_BSTR ) return;
+ break;
+ case HSPVAR_FLAG_DOUBLE:
+ if ( vt == VT_R4 && vt == VT_R8 ) return;
+ break;
+ case HSPVAR_FLAG_INT:
+ switch ( vt ) {
+ case VT_I4:
+ case VT_UI4:
+ case VT_I1:
+ case VT_UI1:
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ case VT_ERROR:
+ case VT_I8:
+ case VT_UI8:
+ return;
+ }
+ break;
+ case HSPVAR_FLAG_COMSTRUCT:
+ if ( vt == VT_DISPATCH || vt == VT_UNKNOWN ) return;
+ break;
+ case HSPVAR_FLAG_VARIANT:
+ if ( vt == VT_VARIANT || (vt & VT_ARRAY) ) return;
+ break;
+ default:
+ throw HSPERR_INVALID_TYPE;
+ }
+}
+
+static void copy_ref_data( VARIANT *var, void *data )
+{
+ // 参照 (ByRef) Variant へのデータコピー
+ // data -> variant
+ //
+ VARTYPE vt;
+ void *pDst, *pSrc;
+
+ vt = var->vt & VT_TYPEMASK;
+ pDst = var->byref;
+ pSrc = data;
+
+ switch ( vt ) {
+ case VT_I4: // データサイズ 4 バイト
+ case VT_R4:
+ case VT_ERROR:
+ case VT_UI4:
+ case VT_INT:
+ case VT_UINT:
+ *(long *)pDst = *(long *)pSrc;
+ break;
+ case VT_I2: // データサイズ 2 バイト
+ case VT_UI2:
+ case VT_BOOL:
+ *(short *)pDst = *(short *)pSrc;
+ break;
+ case VT_I1: // データサイズ 1 バイト
+ case VT_UI1:
+ *(char *)pDst = *(char *)pSrc;
+ break;
+ case VT_R8: // データサイズ 8 バイト
+ case VT_CY:
+ case VT_DATE:
+ case VT_I8:
+ case VT_UI8:
+ *(double *)pDst = *(double *)pSrc;
+ break;
+ case VT_BSTR:
+ *(BSTR *)pDst = SysAllocString( *(BSTR *)pSrc );
+ break;
+ case VT_DISPATCH:
+ *(IDispatch **)pDst = NULL;
+ if ( *(IUnknown **)pSrc ) {
+ (*(IUnknown **)pSrc)->QueryInterface( IID_IDispatch, (void**)pDst );
+ if ( *(void**)pDst == NULL ) throw HSPERR_INVALID_TYPE;
+ }
+ break;
+ case VT_UNKNOWN:
+ *(IUnknown **)pDst = *(IUnknown **)pSrc;
+ if ( *(IUnknown **)pDst ) (*(IUnknown **)pDst)->AddRef();
+ break;
+ case VT_DECIMAL:
+ *(DECIMAL *)pDst = *(DECIMAL *)pSrc;
+ break;
+ case VT_VARIANT:
+ VariantCopy( (VARIANT *)pDst, (VARIANT *)pSrc );
+ break;
+ case VT_SAFEARRAY:
+ SafeArrayCopy( *(SAFEARRAY **)pSrc, (SAFEARRAY **)pDst );
+ break;
+ }
+}
+
+void comset_variant_byref( VARIANT *var, void *data, int vtype )
+{
+ // HSP変数データを Variant (ByRef) に代入する
+ //
+ VARIANT varTemp;
+ VARTYPE vt;
+ void *ptr;
+ HRESULT hr;
+
+ // 代入可能かどうか型チェック
+ if ( (var->vt & VT_BYREF) == 0 ) throw HSPERR_INVALID_PARAMETER;
+ vt = var->vt & ( VT_TYPEMASK | VT_ARRAY );
+ comcheck_variant_conv( vt, vtype );
+
+ // いったん一時 VARIANT を作成してから型変換
+ VariantInit( &varTemp );
+ comset_variant( &varTemp, data, vtype );
+ if ( vtype != HSPVAR_FLAG_VARIANT ) {
+ hr = VariantChangeType( &varTemp, &varTemp, VARIANT_NOVALUEPROP, vt );
+ if ( FAILED(hr) ) throw HSPERR_INVALID_TYPE;
+ }
+
+ // 元データのポインタ取得し代入
+ ptr = &varTemp.lVal;
+ if ( vt == VT_VARIANT ) ptr = &varTemp;
+ if ( vt == VT_DECIMAL ) ptr = &varTemp.decVal;
+ copy_ref_data( var, ptr );
+ VariantClear( &varTemp );
+}
+
+
+static void HspVarVariant_ObjectWrite( PVal *pval, void *data, int vtype )
+{
+ // 可変型の代入
+ //
+ int id;
+ void *ptr;
+ VARTYPE vt;
+ VARIANT varTemp, *var;
+ SAFEARRAY *psa;
+ VariantParam *vprm;
+ HRESULT hr;
+ BSTR bstr;
+
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "HspVarVariant_ObjectWrite()\n");
+#endif
+
+ vprm = (VariantParam *)pval->master;
+ var = vprm->var;
+ id = vprm->id;
+ switch ( id ) {
+
+ case HSPVAR_VARIANT_VALUE:
+ if ( var->vt & VT_BYREF ) {
+ // 参照 VARIANT への代入
+ comset_variant_byref( var, data, vtype );
+ } else {
+ // 値 Variant への代入
+ comset_variant( var, data, vtype );
+ }
+ break;
+
+ case HSPVAR_VARIANT_ARRAY_ELEMENT:
+ // SafeArray の要素へ代入(代入先の VARTYPE は変更できない)
+ // 代入可能かどうか型チェック
+ if ( (var->vt & VT_ARRAY) == 0 ) throw HSPERR_INVALID_ARRAYSTORE;
+ if ( var->vt & VT_BYREF ) {
+ psa = *var->pparray;
+ } else {
+ psa = var->parray;
+ }
+ vt = var->vt & VT_TYPEMASK;
+ if ( vt == VT_EMPTY ) {
+ hr = SafeArrayGetVartype( psa, &vt );
+ if ( FAILED(hr) || vt == VT_EMPTY ) throw HSPERR_INVALID_ARRAYSTORE;
+ }
+ comcheck_variant_conv( vt, vtype );
+ // いったん一時 VARIANT を作成してから型変換
+ VariantInit( &varTemp );
+ comset_variant( &varTemp, data, vtype );
+ if ( vtype != HSPVAR_FLAG_VARIANT ) {
+ hr = VariantChangeType( &varTemp, &varTemp, VARIANT_NOVALUEPROP, vt );
+ if ( FAILED(hr) ) throw HSPERR_INVALID_TYPE;
+ }
+ // 元データのポインタ取得し代入
+ ptr = &varTemp.lVal;
+ if ( vt == VT_VARIANT ) ptr = &varTemp;
+ if ( vt == VT_DECIMAL ) ptr = &varTemp.decVal;
+ hr = SafeArrayPutElement( psa, vprm->index, ptr );
+ VariantClear( &varTemp );
+ if ( FAILED(hr) ) throw HSPERR_ARRAY_OVERFLOW;
+ break;
+
+ case HSPVAR_VARIANT_VARTYPE:
+ // VARIANT の型 (VARTYPE) を変更
+ if ( vtype != HSPVAR_FLAG_INT ) throw HSPERR_INTEGER_REQUIRED;
+ vt = (VARTYPE)( *(int*)data );
+ hr = VariantChangeType( var, var, VARIANT_NOVALUEPROP, vt );
+ if ( FAILED(hr) ) throw HSPERR_INVALID_TYPE;
+ break;
+
+ case HSPVAR_VARIANT_ARRAY_PTR:
+ // 渡された整数が SafeArray であるとして代入
+ if ( vtype != HSPVAR_FLAG_INT ) throw HSPERR_INVALID_ARRAYSTORE;
+ psa = (SAFEARRAY *)( *(int*)data );
+ if ( psa == NULL ) throw HSPERR_ILLEGAL_FUNCTION;
+ hr = SafeArrayGetVartype( psa, &vt );
+ if ( FAILED(hr) ) throw HSPERR_INVALID_ARRAYSTORE;
+ VariantClear( var );
+ var->vt = vt | VT_ARRAY;
+ var->parray = psa;
+ break;
+
+ case HSPVAR_VARIANT_BSTR_PTR:
+ // 渡された整数がBSTRであるとして代入
+ if ( vtype != HSPVAR_FLAG_INT ) throw HSPERR_INVALID_ARRAYSTORE;
+ bstr = (BSTR)( *(int*)data );
+ VariantClear( var );
+ var->vt = VT_BSTR;
+ var->bstrVal = bstr;
+ break;
+
+ default:
+ throw HSPERR_INVALID_PARAMETER;
+ }
+}
+
+
+static void *HspVarVariant_ArrayObjectRead( PVal *pval, int *mptype )
+{
+ // 配列要素の指定 (連想配列/読み出し)
+ //
+ VARIANT* var;
+ int chk, id;
+ void *ptr;
+ static int vRet;
+ SAFEARRAY *psa;
+ long dimension, lbound, ubound;
+ VariantParam *vprm;
+ VARIANT varTemp;
+ VARTYPE vt;
+ HRESULT hr;
+
+ // 配列要素の取得
+ chk = code_get_element( pval );
+ var = (VARIANT *)HspVarVariant_GetPtr( pval );
+ if ( chk == PARAM_ENDSPLIT ) return var; // 配列要素が指定された場合はそのまま
+
+ // プロパティ取得時
+ if ( mpval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+ id = getPropertyID( (char *)(mpval->pt) );
+
+#ifdef HSP_COMOBJ_DEBUG
+ COM_DBG_MSG( "HspVarVariant_ArrayObjectRead() : Property Name=\"%s\" (Property ID=%d)\n", mpval->pt, id);
+#endif
+ // (デフォルト)
+ ptr = &vRet;
+ *mptype = HSPVAR_FLAG_INT;
+
+ // パラメータを取得・プロパティ取得
+ switch ( id ) {
+
+ case HSPVAR_VARIANT_VARTYPE:
+ case HSPVAR_VARIANT_VARTYPE_MASKED:
+ if ( id == HSPVAR_VARIANT_VARTYPE_MASKED ) {
+ vRet = var->vt & VT_TYPEMASK;
+ } else {
+ vRet = var->vt;
+ }
+ break;
+
+ case HSPVAR_VARIANT_VALUE:
+ if ( (var->vt & VT_ARRAY) && (chk != PARAM_SPLIT) ) {
+ // SafeArray の要素を取りに行く
+ if ( var->vt & VT_BYREF ) {
+ psa = *var->pparray;
+ } else {
+ psa = var->parray;
+ }
+ vprm = (VariantParam *)pval->master;
+ code_get_safearray( psa, vprm );
+ // 代入可能かどうか型チェック
+ vt = var->vt & VT_TYPEMASK;
+ if ( vt == VT_EMPTY ) {
+ hr = SafeArrayGetVartype( psa, &vt );
+ if ( FAILED(hr) || vt == VT_EMPTY ) throw HSPERR_INVALID_TYPE;
+ }
+ comcheck_variant_conv( vt, *mptype );
+ // いったん一時 VARIANT に格納してから型変換
+ VariantInit( &varTemp );
+ ptr = &varTemp.lVal;
+ if ( vt == VT_VARIANT ) ptr = &varTemp;
+ if ( vt == VT_DECIMAL ) ptr = &varTemp.decVal;
+ hr = SafeArrayGetElement( psa, vprm->index, ptr );
+ try {
+ if ( FAILED(hr) ) throw HSPERR_ARRAY_OVERFLOW;
+ varTemp.vt = vt;
+ ptr = comget_variant( &varTemp, mptype );
+ }
+ catch (...) {
+ VariantClear( &varTemp );
+ throw;
+ }
+ VariantClear( &varTemp );
+ } else {
+ // SafeArray 配列要素以外の値
+ ptr = comget_variant( var, mptype );
+ }
+ break;
+
+ case HSPVAR_VARIANT_IS_BYREF:
+ vRet = 0;
+ if ( var->vt & VT_BYREF ) vRet = 1;
+ break;
+
+ case HSPVAR_VARIANT_IS_ARRAY:
+ vRet = 0;
+ vt = var->vt;
+ if ( var->vt & VT_ARRAY ) vRet = 1;
+ break;
+
+ case HSPVAR_VARIANT_ARRAY_PTR:
+ case HSPVAR_VARIANT_ARRAY_LBOUND:
+ case HSPVAR_VARIANT_ARRAY_UBOUND:
+ case HSPVAR_VARIANT_ARRAY_COUNT:
+ if ( (var->vt & VT_ARRAY) == 0 ) throw HSPERR_INVALID_PARAMETER;
+ if ( var->vt & VT_BYREF ) {
+ psa = *var->pparray;
+ } else {
+ psa = var->parray;
+ }
+ if ( psa == NULL ) throw HSPERR_ARRAY_OVERFLOW;
+ if ( id == HSPVAR_VARIANT_ARRAY_PTR ) {
+ vRet = (int)psa;
+ break;
+ }
+ dimension = code_getdi(1);
+ switch ( id ) {
+ case HSPVAR_VARIANT_ARRAY_LBOUND:
+ hr = SafeArrayGetLBound( psa, dimension, &lbound );
+ vRet = lbound;
+ break;
+ case HSPVAR_VARIANT_ARRAY_UBOUND:
+ hr = SafeArrayGetUBound( psa, dimension, &ubound );
+ vRet = ubound;
+ break;
+ case HSPVAR_VARIANT_ARRAY_COUNT:
+ hr = SafeArrayGetLBound( psa, dimension, &lbound );
+ hr = SafeArrayGetUBound( psa, dimension, &ubound );
+ vRet = ubound - lbound + 1;
+ break;
+ }
+ if ( FAILED(hr) ) throw HSPERR_ILLEGAL_FUNCTION;
+ break;
+
+ case HSPVAR_VARIANT_BSTR_PTR:
+ if ( var->vt != VT_BSTR ) throw HSPERR_INVALID_PARAMETER;
+ vRet = (int)var->bstrVal;
+ break;
+
+ case HSPVAR_VARIANT_REFPTR:
+ if ( (var->vt & VT_BYREF) == 0 ) throw HSPERR_INVALID_PARAMETER;
+ vRet = (int)var->byref;
+ break;
+
+ default:
+ throw HSPERR_INVALID_PARAMETER;
+ }
+
+ // ')' で閉じているか(以降にパラメータがないか)
+ if ( code_get() != PARAM_ENDSPLIT ) throw HSPERR_BAD_ARRAY_EXPRESSION;
+
+ return ptr;
+}
+
+// Size
+static int HspVarVariant_GetSize( const PDAT *pdatl )
+{
+ // (実態のポインタが渡されます)
+ return sizeof(VARIANT);
+}
+
+// Using
+static int HspVarVariant_GetUsing( const PDAT *pdat )
+{
+ // (実態のポインタが渡されます)
+ VARIANT *var = (VARIANT *)pdat;
+ return ( var->vt != VT_EMPTY );
+}
+
+// Set
+static void HspVarVariant_Set( PVal *pval, PDAT *pdat, const void *in )
+{
+ VARIANT *varSrc, *varDst;
+
+ varDst = (VARIANT *)pdat;
+ varSrc = (VARIANT *)in;
+ if ( pval->support & HSPVAR_SUPPORT_TEMPVAR ) {
+ // 一時変数の場合は単なるメモリブロックコピー
+ *varDst = *varSrc;
+ } else {
+ VariantCopy( varDst, varSrc );
+ }
+#ifdef HSP_COMOBJ_DEBUG
+ if ( pval->support & HSPVAR_SUPPORT_TEMPVAR ) {
+ COM_DBG_MSG( "HspVarVariant_Set() : * HSPVAR_SUPPORT_TEMPVAR *\n" );
+ } else {
+ COM_DBG_MSG( "HspVarVariant_Set()\n" );
+ }
+#endif
+}
+
+static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size )
+{
+ *size = pval->size - ( ((char *)pdat) - pval->pt );
+ return (pdat);
+}
+
+static void AllocBlock( PVal *pval, PDAT *pdat, int size )
+{
+}
+
+
+/*------------------------------------------------------------*/
+
+void HspVarVariant_Init( HspVarProc *p )
+{
+ myproc = p;
+
+ p->Set = HspVarVariant_Set;
+ p->GetPtr = HspVarVariant_GetPtr;
+// p->Cnv = HspVarVariant_Cnv;
+// p->CnvCustom = HspVarVariant_CnvCustom;
+ p->GetSize = HspVarVariant_GetSize;
+ p->GetUsing = HspVarVariant_GetUsing;
+ p->GetBlockSize = GetBlockSize;
+ p->AllocBlock = AllocBlock;
+
+ p->ArrayObject = HspVarVariant_ArrayObject;
+ p->ArrayObjectRead = HspVarVariant_ArrayObjectRead;
+ p->ObjectWrite = HspVarVariant_ObjectWrite;
+ p->ObjectMethod = HspVarVariant_ObjectMethod;
+
+ p->Alloc = HspVarVariant_Alloc;
+ p->Free = HspVarVariant_Free;
+/*
+ p->EqI = HspVarVariant_EqI;
+ p->NeI = HspVarVariant_NeI;
+
+ p->AddI = HspVarVariant_Invalid;
+ p->SubI = HspVarVariant_Invalid;
+ p->MulI = HspVarVariant_Invalid;
+ p->DivI = HspVarVariant_Invalid;
+ p->ModI = HspVarVariant_Invalid;
+
+ p->AndI = HspVarVariant_Invalid;
+ p->OrI = HspVarVariant_Invalid;
+ p->XorI = HspVarVariant_Invalid;
+
+ p->EqI = HspVarVariant_Invalid;
+ p->NeI = HspVarVariant_Invalid;
+ p->GtI = HspVarVariant_Invalid;
+ p->LtI = HspVarVariant_Invalid;
+ p->GtEqI = HspVarVariant_Invalid;
+ p->LtEqI = HspVarVariant_Invalid;
+
+ p->RrI = HspVarVariant_Invalid;
+ p->LrI = HspVarVariant_Invalid;
+*/
+ p->vartype_name = "variant"; // タイプ名
+ p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0)
+ p->support = HSPVAR_SUPPORT_STORAGE | HSPVAR_SUPPORT_ARRAYOBJ | HSPVAR_SUPPORT_NOCONVERT | HSPVAR_SUPPORT_VARUSE;
+ // サポート状況フラグ(HSPVAR_SUPPORT_*)
+ p->basesize = sizeof(VARIANT); // 1つのデータが使用するサイズ(byte) / 可変長の時は-1
+}
+
+/*------------------------------------------------------------*/
+
+
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
diff --git a/src/hsp3/win32gui/hspvar_variant.h b/src/hsp3/win32gui/hspvar_variant.h
new file mode 100644
index 0000000000000000000000000000000000000000..c9d1f63fa03ec0eaaede0f339f241ed0456a6846
--- /dev/null
+++ b/src/hsp3/win32gui/hspvar_variant.h
@@ -0,0 +1,59 @@
+
+//
+// hspvar_comobj.cpp header
+//
+#ifndef __hspvar_variant_h
+#define __hspvar_variant_h
+
+
+#ifndef HSP_COM_UNSUPPORTED //(COM サポートなし版のビルド時はファイル全体を無視)
+
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include
+#include
+#include "comobj.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define TYPE_VARIANT 7
+#define HSPVAR_FLAG_VARIANT 7
+
+// use as property ID
+enum {
+ HSPVAR_VARIANT_UNKNOWN = 0,
+ HSPVAR_VARIANT_VARTYPE,
+ HSPVAR_VARIANT_VARTYPE_MASKED,
+ HSPVAR_VARIANT_VALUE,
+ HSPVAR_VARIANT_REFPTR,
+ HSPVAR_VARIANT_IS_ARRAY,
+ HSPVAR_VARIANT_IS_BYREF,
+ HSPVAR_VARIANT_ARRAY_ELEMENT,
+ HSPVAR_VARIANT_ARRAY_PTR,
+ HSPVAR_VARIANT_ARRAY_LBOUND,
+ HSPVAR_VARIANT_ARRAY_UBOUND,
+ HSPVAR_VARIANT_ARRAY_COUNT,
+ HSPVAR_VARIANT_BSTR_PTR
+};
+
+#define HSPVAR_VARIANT_PARAM_MAX 12
+
+typedef struct {
+ VARIANT *var; // 変数の配列要素 (VARIANT)
+ int id; // プロパティID
+ int dimcount; // SafeArray 次元数
+ long index[HSPVAR_VARIANT_PARAM_MAX]; // SafeArray インデックス
+} VariantParam;
+
+void HspVarVariant_Init( HspVarProc *p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !defined( HSP_COM_UNSUPPORTED )
+
+#endif // __hspvar_variant_h
diff --git a/src/hsp3/win32gui/hspwnd_obj.cpp b/src/hsp3/win32gui/hspwnd_obj.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..97a42ea24558443e18ffacbf69ed19bec363396a
--- /dev/null
+++ b/src/hsp3/win32gui/hspwnd_obj.cpp
@@ -0,0 +1,903 @@
+
+//
+// HSP3 window manager
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+#include
+
+#include "../hsp3config.h"
+#include "../hsp3debug.h"
+#include "../hspwnd.h"
+#include "../dpmread.h"
+#include "../strbuf.h"
+#include "../strnote.h"
+#include "../supio.h"
+
+#include
+
+
+#ifndef _tstof
+#ifdef HSPUTF8
+#define _tstof(prm) _wtof(prm)
+#else
+#define _tstof(prm) atof(prm)
+#endif
+#endif
+
+
+/*------------------------------------------------------------*/
+/*
+ Object callback interface
+*/
+/*------------------------------------------------------------*/
+
+static int *notice_ptr;
+static int bmscr_obj_ival;
+static double bmscr_obj_dval;
+static WNDPROC DefEditProc;
+static WNDPROC DefButtonProc;
+
+extern HspWnd *curwnd;
+
+LRESULT CALLBACK MyEditProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp ) {
+ if ( msg==WM_CHAR ) {
+ if (( wp==13 )||( wp==9 )) {
+ return 0;
+ }
+ }
+ return CallWindowProc( DefEditProc , hwnd , msg , wp , lp);
+}
+
+static void UpdateCustomButton( HWND hwnd, int flag )
+{
+ int id;
+ HDC disthdc;
+ HWND hw;
+ Bmscr *bm;
+ HSPOBJINFO *obj;
+
+ hw = (HWND)GetWindowLongPtr( hwnd , GWLP_HWNDPARENT );
+ id = (int)GetWindowLongPtr( hw, GWLP_USERDATA );
+ bm = curwnd->GetBmscrSafe( id );
+
+ id = (int)GetWindowLongPtr( hwnd, GWLP_USERDATA );
+ obj = bm->GetHSPObjectSafe( id );
+ if ( obj->owmode == HSPOBJ_NONE ) return;
+ if ( hwnd != obj->hCld ) return;
+
+ if ( flag ) {
+ if ( obj->option & 0x100 ) return;
+
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ _TrackMouseEvent(&tme);
+
+ obj->option |= 0x100;
+ } else {
+ if (( obj->option & 0x100 ) == 0 ) return;
+ obj->option &= ~0x100;
+ }
+
+ disthdc=GetDC( hwnd );
+ bm->DrawHSPCustomButton( obj, disthdc, flag );
+ ReleaseDC( hwnd, disthdc );
+}
+
+LRESULT CALLBACK MyButtonProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp ) {
+ switch( msg ) {
+ case WM_MOUSEMOVE:
+ UpdateCustomButton( hwnd, 1 );
+ break;
+ case WM_MOUSELEAVE:
+ UpdateCustomButton( hwnd, 0 );
+ break;
+ }
+ return CallWindowProc( DefButtonProc , hwnd , msg , wp , lp);
+}
+
+void SetObjectEventNoticePtr( int *ptr )
+{
+ // イベント時の値ポインタを設定
+ //
+ notice_ptr = ptr;
+}
+
+static void Object_WindowDelete( HSPOBJINFO *info )
+{
+ DestroyWindow( info->hCld );
+ info->hCld = NULL;
+}
+
+static void Object_JumpEvent( HSPOBJINFO *info, int wparam )
+{
+ *notice_ptr = info->owsize;
+ if ( info->option & 1 ) {
+ code_call( (unsigned short *)info->varset.ptr );
+ } else {
+ code_setpci( (unsigned short *)info->varset.ptr );
+ }
+}
+
+static void Object_SendSetVar( HSPOBJINFO *obj )
+{
+ code_setva( obj->varset.pval, obj->varset.aptr, obj->varset.type, obj->varset.ptr );
+}
+
+static void Object_CheckBox( HSPOBJINFO *info, int wparam )
+{
+ HWND hwnd;
+ BMSCR *bm;
+ int val, cid;
+
+ bm = (BMSCR *)info->bm;
+ hwnd = bm->hwnd;
+ cid = GetDlgCtrlID( info->hCld );
+ val = IsDlgButtonChecked( hwnd, cid );
+ bmscr_obj_ival = val;
+ Object_SendSetVar( info );
+}
+
+static void Object_IntInput( HSPOBJINFO *info, int wparam )
+{
+ HWND hwnd;
+ BMSCR *bm;
+ TCHAR minp[64];
+ int val, cid, notify;
+
+ bm = (BMSCR *)info->bm;
+ hwnd = bm->hwnd;
+ notify = wparam>>16;
+ if ( notify != EN_UPDATE ) return;
+ cid = GetDlgCtrlID( info->hCld );
+ val = GetDlgItemText( hwnd, cid, minp, 63 );
+ if ( val == 0 ) {
+ bmscr_obj_ival = 0;
+ } else {
+ bmscr_obj_ival = _ttoi( minp );
+ }
+ info->varset.ptr = (void *)&bmscr_obj_ival;
+ Object_SendSetVar( info );
+}
+
+static void Object_DoubleInput( HSPOBJINFO *info, int wparam )
+{
+ HWND hwnd;
+ BMSCR *bm;
+ TCHAR minp[64];
+ int val, cid, notify;
+
+ bm = (BMSCR *)info->bm;
+ hwnd = bm->hwnd;
+ notify = wparam>>16;
+ if ( notify != EN_UPDATE ) return;
+ cid = GetDlgCtrlID( info->hCld );
+ val = GetDlgItemText( hwnd, cid, minp, 63 );
+ if ( val == 0 ) {
+ bmscr_obj_dval = 0.0;
+ } else {
+ bmscr_obj_dval = _tstof( minp );
+ }
+ info->varset.ptr = (void *)&bmscr_obj_dval;
+ Object_SendSetVar( info );
+}
+
+static void Object_StrInput( HSPOBJINFO *info, int wparam )
+{
+ HWND hwnd;
+ BMSCR *bm;
+ TCHAR minp[0x8000];
+ TCHAR *bigbuf;
+ int val, cid, notify, size;
+ HSPCHAR *hctmp1 = 0;
+
+ bm = (BMSCR *)info->bm;
+ hwnd = bm->hwnd;
+ notify = wparam>>16;
+ if ( notify != EN_UPDATE ) return;
+
+ size = (int)SendMessage( info->hCld, WM_GETTEXTLENGTH,0,0L );
+ cid = GetDlgCtrlID( info->hCld );
+
+ if ( size < 0x8000 ) {
+ bigbuf = minp;
+ val = GetDlgItemText( hwnd, cid, minp, 0x7fff );
+ } else {
+ bigbuf = (HSPAPICHAR*)sbAlloc( size+1 );
+ val = GetDlgItemText( hwnd, cid, bigbuf, size );
+ }
+
+ if ( val == 0 ) {
+ bmscr_obj_ival = 0;
+ info->varset.ptr = (void *)&bmscr_obj_ival;
+ } else {
+ apichartohspchar(bigbuf,&hctmp1);
+ info->varset.ptr = hctmp1;
+ }
+ Object_SendSetVar( info );
+
+ if ( size >= 0x8000 ) sbFree( bigbuf );
+ freehc(&hctmp1);
+}
+
+static void Object_ComboBox( HSPOBJINFO *info, int wparam )
+{
+ int notify;
+ notify = wparam>>16;
+ if ( notify != CBN_SELENDOK ) return;
+ bmscr_obj_ival = (int)SendMessage( info->hCld, CB_GETCURSEL,0,0L );
+ Object_SendSetVar( info );
+}
+
+static void Object_ListBox( HSPOBJINFO *info, int wparam )
+{
+ bmscr_obj_ival = (int)SendMessage( info->hCld, LB_GETCURSEL,0,0L );
+ Object_SendSetVar( info );
+}
+
+static void Object_SetMultiBox( HSPOBJINFO *info, int type, void *ptr )
+{
+ int i,max;
+ char res[256];
+ UINT m_ini,m_add;
+ HWND hw;
+ CStrNote note;
+ HSPAPICHAR *hactmp1 = 0;
+
+ hw = info->hCld;
+
+ switch( type ) {
+ case TYPE_STRING:
+ if ( info->owid ) {
+ m_ini=CB_RESETCONTENT;
+ m_add=CB_ADDSTRING;
+ } else {
+ m_ini=LB_RESETCONTENT;
+ m_add=LB_ADDSTRING;
+ }
+ note.Select( (HSPCHAR*)ptr );
+ max = note.GetMaxLine();
+ SendMessage( hw, m_ini, 0, 0L );
+ for( i=0;iowid ) {
+ m_ini=CB_SETCURSEL;
+ } else {
+ m_ini=LB_SETCURSEL;
+ }
+ bmscr_obj_ival = *(int *)ptr;
+ SendMessage( hw, m_ini, bmscr_obj_ival, 0L );
+ Object_SendSetVar( info );
+ break;
+ default:
+ throw HSPERR_TYPE_MISMATCH;
+ }
+}
+
+
+static void Object_SetInputBox( HSPOBJINFO *info, int type, void *ptr )
+{
+ HWND hw;
+ HSPAPICHAR *hactmp1 = 0;
+ hw = info->hCld;
+ switch( type ) {
+ case TYPE_STRING:
+ SetWindowText( hw, chartoapichar((char*)ptr,&hactmp1) );
+ freehac(&hactmp1);
+ break;
+ case TYPE_INUM:
+ case TYPE_DNUM:
+ SetWindowText( hw, chartoapichar((char *)HspVarCoreCnv( type, TYPE_STRING, ptr ),&hactmp1) );
+ freehac(&hactmp1);
+ break;
+ default:
+ throw HSPERR_TYPE_MISMATCH;
+ }
+}
+
+
+static void Object_SetInputMesBox( HSPOBJINFO *info, int type, void *ptr )
+{
+ HWND hw;
+ hw = info->hCld;
+ Object_SetInputBox( info, type, ptr );
+ Object_StrInput( info, EN_UPDATE<<16 ); // 即時反映させる
+}
+
+
+static void Object_SetCheckBox( HSPOBJINFO *info, int type, void *ptr )
+{
+ HWND const hw = info->hCld;
+ HSPAPICHAR *hactmp1 = 0;
+ switch ( type ) {
+ case HSPVAR_FLAG_STR:
+ SetWindowText( hw,
+ chartoapichar(static_cast< char * >( ptr ),&hactmp1) );
+ break;
+ case HSPVAR_FLAG_INT:
+ SendMessage( hw, BM_SETCHECK,
+ ( *static_cast< int * >( ptr ) ? 1 : 0 ), 0 );
+ Object_CheckBox( info, 0 );
+ break;
+ default:
+ throw HSPERR_TYPE_MISMATCH;
+ }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void Bmscr::ResetHSPObject( void )
+{
+ // すべてのObjectをリセットする
+ //
+ int i;
+ if ( mem_obj != NULL ) {
+ for( i=0;i=0) {
+ obj = GetHSPObjectSafe( id );
+ ow = obj->hCld;
+ if ( ow == NULL ) return -2;
+
+ if ( obj->owmode & HSPOBJ_TAB_SELALLTEXT ) {
+ SendMessage( ow, EM_SETSEL, 0, -1);
+ }
+ SetFocus( ow );
+ return 0;
+ }
+ cid = -1;
+ ow = GetFocus();
+ if ( ow != NULL) {
+ for( a=0; aowmode == HSPOBJ_NONE ) throw HSPERR_ILLEGAL_FUNCTION;
+ EnableWindow( obj->hCld, sw!=0 );
+}
+
+
+void Bmscr::SetObjectMode( int id, int owmode )
+{
+ HSPOBJINFO *obj;
+ obj = GetHSPObjectSafe( id );
+ if ( obj->owmode == HSPOBJ_NONE ) throw HSPERR_ILLEGAL_FUNCTION;
+ if ( owmode <= 0 ) throw HSPERR_ILLEGAL_FUNCTION;
+ obj->owmode = owmode;
+}
+
+
+void Bmscr::NextObject( int plus )
+{
+ // [TAB]を押して次のobjectを選択
+ //
+ HWND hw;
+ HSPOBJINFO *obj;
+ int a,cid,ts;
+
+ cid = ActivateHSPObject(-1);
+ obj = &mem_obj[ cid ];
+ if ( cid>=0 ) if ( ( obj->owmode & 3 ) == HSPOBJ_TAB_DISABLE ) return;
+
+ for( a=0; a=objmax ) cid = 0;
+ if ( cid<0 ) cid = objmax - 1;
+ obj = &mem_obj[ cid ];
+ hw = obj->hCld;
+ if ( hw != NULL ) {
+ ts = obj->owmode & 3;
+ if ( ts != HSPOBJ_TAB_SKIP ) {
+ if ( IsWindowEnabled( hw ) ) {
+ if ( obj->owmode & HSPOBJ_TAB_SELALLTEXT ) {
+ SendMessage( hw, EM_SETSEL, 0, -1);
+ }
+ SetFocus( hw );
+ return;
+ }
+ }
+ }
+ }
+}
+
+
+
+int Bmscr::NewHSPObject( void )
+{
+ // 空きIDを探す
+ //
+ int i,id;
+ id = 0;
+ if ( mem_obj == NULL ) {
+ mem_obj = (HSPOBJINFO *) sbAlloc( sizeof(HSPOBJINFO) );
+ objmax++;
+ } else {
+ if ( objmax ) {
+ for( i=0; i= objlimit ) throw HSPERR_WINDOW_OBJECT_FULL;
+ id = objmax++;
+ mem_obj = (HSPOBJINFO *) sbExpand( (char *)mem_obj, sizeof(HSPOBJINFO) * objmax );
+ }
+ return id;
+}
+
+
+HSPOBJINFO *Bmscr::AddHSPObject( int id, HWND handle, int mode )
+{
+ HSPOBJINFO *obj;
+ obj = &mem_obj[id];
+ obj->hCld = handle;
+ obj->owmode = mode;
+ obj->option = 0;
+ obj->bm = GetBMSCR();
+ obj->func_notice = NULL;
+ obj->func_objprm = NULL;
+ obj->func_delete = NULL;
+ obj->owid = 0;
+ obj->owsize = 0;
+ SetHSPObjectFont( id );
+ return obj;
+}
+
+
+HSPOBJINFO *Bmscr::AddHSPJumpEventObject( int id, HWND handle, int mode, int val, void *ptr )
+{
+ HSPOBJINFO *obj;
+ obj = AddHSPObject( id, handle, mode );
+ obj->owid = -1;
+ obj->owsize = id;
+ obj->option = val;
+ obj->varset.ptr = ptr;
+ obj->func_notice = Object_JumpEvent;
+
+ SetWindowLongPtr( handle, GWLP_USERDATA, id );
+
+ return obj;
+}
+
+
+void Bmscr::SetButtonImage( int id, int bufid, int x1, int y1, int x2, int y2, int x3, int y3 )
+{
+ HSPOBJINFO *obj;
+ HSP3BTNSET *bset;
+
+ obj = GetHSPObjectSafe( id );
+
+ if ( obj->func_notice != Object_JumpEvent ) throw HSPERR_UNSUPPORTED_FUNCTION;
+
+ obj->owid = bufid;
+ SetWindowLong( obj->hCld, GWL_STYLE, GetWindowLong( obj->hCld, GWL_STYLE ) | BS_OWNERDRAW );
+
+ DefButtonProc = (WNDPROC)GetWindowLongPtr( obj->hCld , GWLP_WNDPROC );
+
+ if ( DefButtonProc != MyButtonProc ) {
+ SetWindowLongPtr( obj->hCld , GWLP_WNDPROC , (LONG_PTR)MyButtonProc );
+ }
+
+ bset = (HSP3BTNSET *)(&obj->varset);
+ bset->normal_x = x1;
+ bset->normal_y = y1;
+ bset->push_x = x2;
+ bset->push_y = y2;
+ bset->focus_x = x3;
+ bset->focus_y = y3;
+}
+
+
+HSPOBJINFO *Bmscr::AddHSPVarEventObject( int id, HWND handle, int mode, PVal *pval, APTR aptr, int type, void *ptr )
+{
+ HSPOBJINFO *obj;
+ obj = AddHSPObject( id, handle, mode );
+ obj->varset.pval = pval;
+ obj->varset.aptr = aptr;
+ obj->varset.type = type;
+ obj->varset.ptr = ptr;
+ return obj;
+}
+
+
+HSPOBJINFO *Bmscr::GetHSPObject( int id )
+{
+ return &mem_obj[id];
+}
+
+
+HSPOBJINFO *Bmscr::GetHSPObjectSafe( int id )
+{
+ if (( id < 0 )||( id >= objmax )) throw HSPERR_ILLEGAL_FUNCTION;
+ return &mem_obj[id];
+}
+
+
+void Bmscr::DeleteHSPObject( int id )
+{
+ // オブジェクト削除
+ //
+ HFONT hf;
+ HSPOBJINFO *obj;
+
+ obj = GetHSPObjectSafe( id );
+
+ if ( obj->owmode == HSPOBJ_NONE ) return;
+ if ( obj->hCld != NULL ) {
+ if ( obj->owmode & HSPOBJ_OPTION_SETFONT ) {
+ hf=(HFONT)SendMessage( obj->hCld, WM_GETFONT, 0, 0 );
+ if (hf!=NULL) DeleteObject( hf );
+ }
+ if ( obj->func_delete != NULL ) obj->func_delete( obj );
+ }
+ obj->owmode = HSPOBJ_NONE;
+}
+
+
+void Bmscr::UpdateHSPObject( int id, int type, void *ptr )
+{
+ // オブジェクトに値を設定する
+ //
+ HSPOBJINFO *obj;
+ obj = GetHSPObjectSafe( id );
+ if ( obj->func_objprm != NULL ) {
+ obj->func_objprm( obj, type, ptr );
+ } else {
+ throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+}
+
+
+void Bmscr::SetHSPObjectFont( int id )
+{
+ int a;
+ HWND hw;
+ HFONT hf;
+ PLOGFONT plf;
+ HSPOBJINFO *obj;
+
+ obj = GetHSPObjectSafe( id );
+ if ( obj->owmode == HSPOBJ_NONE ) return;
+ if (( obj->owmode & HSPOBJ_OPTION_SETFONT ) == 0 ) return;
+
+ a = objmode;
+ if (a) {
+ hw = obj->hCld;
+ if ( hw == NULL ) return;
+ if (a==1) hf=(HFONT)GetStockObject(17);
+ else {
+ plf=(PLOGFONT) &logfont;
+ hf=CreateFontIndirect( plf );
+ }
+ PostMessage( hw,WM_SETFONT,(WPARAM)hf,TRUE );
+ }
+}
+
+
+void Bmscr::SendHSPObjectNotice( int wparam )
+{
+ // オブジェクトの通知処理
+ //
+ int id;
+ HWND hw;
+ HSPOBJINFO *obj;
+ id = wparam & (MESSAGE_HSPOBJ-1);
+ obj = GetHSPObjectSafe( id );
+ if ( obj->owmode == HSPOBJ_NONE ) return;
+ hw = obj->hCld;
+ if ( hw == NULL ) return;
+
+ if ( obj->func_notice != NULL ) {
+ obj->func_notice( obj, wparam );
+ }
+}
+
+
+void Bmscr::DrawHSPCustomButton( HSPOBJINFO *obj, HDC drawhdc, int flag )
+{
+ // オーナードローの描画処理
+ // (flag:0=通常、1=フォーカス、2=押下)
+ //
+ int xx,yy;
+ Bmscr *src;
+ HspWnd *wnd;
+ HSP3BTNSET *bset;
+ RECT rect;
+ HFONT hFont;
+ COLORREF col;
+ HSPAPICHAR *hactmp1 = 0;
+
+ char msgtmp[256];
+
+ GetClientRect( obj->hCld, &rect );
+ if ( obj->owid < 0 ) {
+
+ } else {
+ bset = (HSP3BTNSET *)(&obj->varset);
+ wnd = (HspWnd *)master_hspwnd;
+ src = wnd->GetBmscrSafe( obj->owid );
+ switch( flag ) {
+ case 1:
+ xx = bset->focus_x;
+ yy = bset->focus_y;
+ break;
+ case 2:
+ xx = bset->push_x;
+ yy = bset->push_y;
+ break;
+ default:
+ xx = bset->normal_x;
+ yy = bset->normal_y;
+ break;
+ }
+ BitBlt( drawhdc, rect.left, rect.top, rect.right, rect.bottom, src->hdc, xx, yy, SRCCOPY );
+ }
+
+ if ( obj->option & 0x200 ) { // キーボードフォーカスあり
+ InflateRect( &rect, -3, -3 );
+ DrawFocusRect( drawhdc, &rect );
+ GetClientRect( obj->hCld, &rect );
+ }
+
+ SendMessage( obj->hCld, WM_GETTEXT, 255, (LPARAM)msgtmp );
+ hFont = (HFONT)SelectObject(drawhdc, (HGDIOBJ)SendMessage( obj->hCld, WM_GETFONT, 0, 0));
+ col = RGB(0,0,0);
+ SetBkMode( drawhdc,TRANSPARENT );
+ SetTextColor( drawhdc, col );
+ DrawText( drawhdc, chartoapichar(msgtmp,&hactmp1), -1, &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE );
+ freehac(&hactmp1);
+ SelectObject( drawhdc, hFont );
+}
+
+
+void Bmscr::SendHSPObjectDraw( int wparam, LPDRAWITEMSTRUCT lparam )
+{
+ // オーナードローの描画処理を呼び出す(wparam,lparam処理)
+ //
+ int id,flag;
+ HWND hw;
+ HSPOBJINFO *obj;
+ id = wparam & (MESSAGE_HSPOBJ-1);
+ obj = GetHSPObjectSafe( id );
+ if ( obj->owmode == HSPOBJ_NONE ) return;
+ hw = obj->hCld;
+ if ( hw != lparam->hwndItem ) return;
+
+ if ( lparam->itemState & ODS_FOCUS ) {
+ obj->option |= 0x200;
+ } else {
+ obj->option &= ~0x200;
+ }
+
+ flag = 0;
+ if ( obj->option & 0x100 ) flag = 1;
+ if ( lparam->itemState & ODS_SELECTED ) flag = 2;
+ DrawHSPCustomButton( obj, lparam->hDC, flag );
+}
+
+
+int Bmscr::AddHSPObjectButton( char *name, int flag, void *callptr )
+{
+ // create push button
+ //
+ HWND hw;
+ int id,ws;
+ HSPOBJINFO *obj;
+ HSPAPICHAR *hactmp1 = 0;
+
+ id = NewHSPObject();
+ ws = objstyle | BS_PUSHBUTTON;
+/*
+ rev 43
+ mingw : warning : 変数型から大きさの異なるポインタ型への変換
+ に対処
+ 以降4ヶ所も同様。
+*/
+ hw = CreateWindow( TEXT("button"), chartoapichar(name,&hactmp1), ws,
+ cx, cy, ox, oy, hwnd,
+ reinterpret_cast< HMENU >( static_cast< WORD >( MESSAGE_HSPOBJ + id ) ), hInst, NULL );
+ freehac(&hactmp1);
+
+ // ダブルクリックの受付を抑制
+ SetClassLong( hw, GCL_STYLE, GetClassLong(hw, GCL_STYLE) & ~CS_DBLCLKS );
+
+ obj = AddHSPJumpEventObject( id, hw, HSPOBJ_TAB_ENABLE|HSPOBJ_OPTION_SETFONT, flag, callptr );
+ obj->func_delete = Object_WindowDelete;
+ obj->func_objprm = Object_SetInputBox;
+ Posinc( oy );
+ return id;
+}
+
+
+int Bmscr::AddHSPObjectCheckBox( char *name, PVal *pval, APTR aptr )
+{
+ // create push button
+ //
+ HWND hw;
+ int id,ws;
+ int *iptr;
+ HSPOBJINFO *obj;
+ HSPAPICHAR *hactmp1 = 0;
+
+ id = NewHSPObject();
+ ws = objstyle | BS_AUTOCHECKBOX;
+ hw = CreateWindow( TEXT("button"), chartoapichar(name,&hactmp1), ws,
+ cx, cy, ox, oy, hwnd,
+ reinterpret_cast< HMENU >( static_cast< WORD >( MESSAGE_HSPOBJ + id ) ), hInst, NULL );
+ freehac(&hactmp1);
+
+ obj = AddHSPVarEventObject( id, hw, HSPOBJ_TAB_ENABLE|HSPOBJ_OPTION_SETFONT, pval, aptr, TYPE_INUM, (void *)&bmscr_obj_ival );
+ obj->func_notice = Object_CheckBox;
+ obj->func_objprm = Object_SetCheckBox;
+ obj->func_delete = Object_WindowDelete;
+ Posinc( oy );
+
+ iptr = (int *)HspVarCorePtrAPTR( pval, aptr );
+ if ( *iptr ) SendMessage( hw, BM_SETCHECK, 1, 0 );
+
+ return id;
+}
+
+
+int Bmscr::AddHSPObjectInput( PVal *pval, APTR aptr, int sizex, int sizey, char *defval, int limit, int mode )
+{
+ // create input box
+ //
+ HWND hwedit;
+ int id,ws,ws2,max,tabstop,type,subcl;
+ HSPOBJINFO *obj;
+ HSPAPICHAR *hactmp1 = 0;
+
+ id = NewHSPObject();
+ ws = objstyle;
+ ws2 = WS_EX_CLIENTEDGE;
+ max = 16;
+ subcl = 0;
+ tabstop = HSPOBJ_TAB_ENABLE;
+ type = mode & 15;
+ if ( type == HSPOBJ_INPUT_STR ) max = limit;
+
+ if ( mode & HSPOBJ_INPUT_HSCROLL ) ws|=WS_HSCROLL;
+ if ( mode & HSPOBJ_INPUT_MULTILINE ) {
+ ws|=ES_LEFT|ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL|ES_AUTOVSCROLL;
+ //tabstop = HSPOBJ_TAB_DISABLE;
+ tabstop = HSPOBJ_TAB_SKIP;
+ max = 0;
+ }
+ else {
+ //if ( bm->objmode & 32 ) ws2=WS_EX_WINDOWEDGE;
+ ws|=ES_AUTOHSCROLL;
+ tabstop |= HSPOBJ_TAB_SELALLTEXT;
+ subcl = 1;
+ }
+
+ if ( mode & HSPOBJ_INPUT_READONLY ) {
+ ws|=ES_READONLY;
+ tabstop = HSPOBJ_TAB_SKIP;
+ }
+ else {
+ ws|=WS_TABSTOP;
+ }
+
+ hwedit = CreateWindowEx( ws2, TEXT("edit"), NULL, ws,
+ cx, cy, sizex, sizey,
+ hwnd, reinterpret_cast< HMENU >( static_cast< WORD >( MESSAGE_HSPOBJ + id ) ), hInst, NULL );
+
+ if ( subcl ) {
+ DefEditProc = (WNDPROC)GetWindowLongPtr( hwedit , GWLP_WNDPROC );
+ SetWindowLongPtr(hwedit, GWLP_WNDPROC, (LONG_PTR)MyEditProc);
+ }
+
+ obj = AddHSPVarEventObject( id, hwedit, tabstop|HSPOBJ_OPTION_SETFONT, pval, aptr, type, (void *)&bmscr_obj_ival );
+ switch( type ) {
+ case HSPOBJ_INPUT_STR:
+ obj->func_notice = Object_StrInput;
+ break;
+ case HSPOBJ_INPUT_DOUBLE:
+ obj->func_notice = Object_DoubleInput;
+ break;
+ case HSPOBJ_INPUT_INT:
+ obj->func_notice = Object_IntInput;
+ break;
+ default:
+ throw HSPERR_TYPE_MISMATCH;
+ }
+
+ obj->func_delete = Object_WindowDelete;
+ obj->func_objprm = Object_SetInputBox;
+
+ if ( !subcl ) { // mesbox用のobjprm更新を追加(2011/1/6)
+ obj->func_objprm = Object_SetInputMesBox;
+ }
+
+ Posinc( sizey );
+
+ SendMessage( hwedit, EM_LIMITTEXT, limit, 0L );
+ SetWindowText( hwedit,chartoapichar(defval,&hactmp1) );
+ freehac(&hactmp1);
+ if ( focflg == 0 ) {
+ ActivateHSPObject( id );
+ }
+ focflg++;
+
+ return id;
+}
+
+
+int Bmscr::AddHSPObjectMultiBox( PVal *pval, APTR aptr, int psize, char *defval, int mode )
+{
+ // create combo/list box
+ //
+ HWND hw;
+ HSPOBJINFO *obj;
+ int id,sizex,sizey;
+ int *iptr;
+
+ id = NewHSPObject();
+ sizex = ox; sizey = oy;
+ iptr = (int *)HspVarCorePtrAPTR( pval, aptr );
+
+ if ( mode ) {
+ hw = CreateWindowEx( WS_EX_CLIENTEDGE, TEXT("combobox"), TEXT(""),
+ objstyle|WS_VSCROLL|CBS_DROPDOWNLIST,
+ cx, cy, sizex, sizey + psize, hwnd,
+ reinterpret_cast< HMENU >( static_cast< WORD >( MESSAGE_HSPOBJ + id ) ), hInst, NULL );
+ } else {
+ sizey += psize;
+ hw = CreateWindowEx( WS_EX_CLIENTEDGE, TEXT("listbox"), TEXT(""),
+ objstyle|WS_VSCROLL|LBS_NOTIFY,
+ cx, cy, sizex, sizey, hwnd,
+ reinterpret_cast< HMENU >( static_cast< WORD >( MESSAGE_HSPOBJ + id ) ), hInst, NULL );
+ }
+
+ obj = AddHSPVarEventObject( id, hw, HSPOBJ_TAB_ENABLE|HSPOBJ_OPTION_SETFONT, pval, aptr, TYPE_INUM, (void *)&bmscr_obj_ival );
+ obj->owid = mode;
+
+ if ( mode ) {
+ obj->func_notice = Object_ComboBox;
+ } else {
+ obj->func_notice = Object_ListBox;
+ }
+ obj->func_objprm = Object_SetMultiBox;
+ obj->func_delete = Object_WindowDelete;
+ Posinc( sizey );
+ Object_SetMultiBox( obj, TYPE_STRING, defval );
+ Object_SetMultiBox( obj, TYPE_INUM, iptr );
+ return id;
+}
+
diff --git a/src/hsp3/win32gui/hspwnd_win.cpp b/src/hsp3/win32gui/hspwnd_win.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2555568ad1dbd400d88e7a2ced8f803e9c01b40d
--- /dev/null
+++ b/src/hsp3/win32gui/hspwnd_win.cpp
@@ -0,0 +1,1902 @@
+
+//
+// HSP3 window manager
+// onion software/onitama 2004/6
+//
+#include
+#include
+#include
+#include
+
+#include "../hsp3config.h"
+#include "../hsp3debug.h"
+#include "../hspwnd.h"
+#include "../dpmread.h"
+#include "../strbuf.h"
+#include "../strnote.h"
+#include "../supio.h"
+
+#ifndef HSP_COMPACT
+#include "fcpoly.h"
+#define USE_STBIMAGE
+#endif
+
+#ifdef USE_STBIMAGE
+#include "stb_image.h"
+#endif
+
+#include
+#include
+
+#define HIMETRIC_INCH 2540
+#define MAP_LOGHIM_TO_PIX(x,ppli) ( ((ppli)*(x) + HIMETRIC_INCH/2) / HIMETRIC_INCH )
+
+
+/*
+ rev 43
+ mingw : warning : WM_MOUSEWHEELの再定義
+ に対処
+*/
+
+/*
+* WM_MOUSEWHEELはWindows NT 4.0以降で有効で、Windows 95で有効でない。
+*/
+
+#if !defined( WM_MOUSEWHEEL )
+#define WM_MOUSEWHEEL 0x020A
+#endif
+
+
+#if !defined(HSP_COMPACT)
+#if defined( _MSC_VER )
+#pragma comment(lib,"msimg32.lib")
+#endif
+#endif
+
+HspWnd *curwnd;
+static MM_NOTIFY_FUNC notifyfunc;
+
+#if !defined(HSP_COMPACT)
+extern int resY0, resY1; // "fcpoly.h"のパラメーター
+#endif
+
+/*------------------------------------------------------------*/
+/*
+ constructor
+*/
+/*------------------------------------------------------------*/
+
+HspWnd::HspWnd()
+{
+ // 初期化
+ //
+ Reset( NULL, "hspwnd0" );
+}
+
+HspWnd::HspWnd( HANDLE instance, char *wndcls )
+{
+ // 初期化
+ //
+ Reset( instance, wndcls );
+}
+
+HspWnd::~HspWnd()
+{
+ // すべて破棄
+ //
+ Dispose();
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ Window interface in C
+*/
+/*------------------------------------------------------------*/
+
+Bmscr *TrackBmscr( HWND hwnd )
+{
+ int id;
+ id = (int)GetWindowLongPtr( hwnd, GWLP_USERDATA );
+ if ( id < 0 ) return NULL;
+ return curwnd->GetBmscr( id );
+}
+
+
+void WM_Paint( HWND hwnd, Bmscr *bm )
+{
+ // WM_PAINT process
+ //
+ PAINTSTRUCT ps;
+ HDC hdc;
+ if ( bm->flag == BMSCR_FLAG_NOUSE ) return;
+ hdc = BeginPaint ( hwnd, &ps );
+ bm->Bmspnt( hdc );
+ EndPaint ( hwnd, &ps );
+}
+
+
+LRESULT CALLBACK WndProc( HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam )
+{
+ int id;
+ int retval;
+ Bmscr *bm;
+
+ if ( code_isuserirq() ) {
+ if ( code_checkirq( (int)GetWindowLongPtr( hwnd, GWLP_USERDATA ), (int)uMessage, (int)wParam, (int)lParam ) ) {
+ if ( code_irqresult( &retval ) ) return retval;
+ }
+ }
+
+ switch (uMessage)
+ {
+ case WM_CREATE:
+ SetWindowLongPtr( hwnd, GWLP_USERDATA, -1 );
+ return 0;
+
+ case WM_PALETTECHANGED:
+ if ( wParam == (WPARAM)hwnd ) break;
+ case WM_QUERYNEWPALETTE:
+ bm = TrackBmscr( hwnd );
+ if ( bm == NULL ) break;
+ if (bm->hpal != NULL) { // パレット変更時にもマッチングさせる
+ int a;
+ HDC hdc;
+ HPALETTE opal;
+ hdc=GetDC( hwnd );
+ opal=SelectPalette( hdc, bm->hpal, 0 );
+ a=RealizePalette( hdc );
+ SelectPalette( hdc, opal, 0 );
+ ReleaseDC( hwnd, hdc );
+ if ( a > 0) InvalidateRect( hwnd, NULL, TRUE );
+ return a;
+ }
+ break;
+
+ case WM_PAINT:
+ // Display 全描画
+ //
+ bm = TrackBmscr( hwnd );
+ if ( bm != NULL ) WM_Paint( hwnd, bm );
+ return 0 ;
+
+ case WM_GETMINMAXINFO:
+ {
+ LPMINMAXINFO lpmm;
+ bm = TrackBmscr( hwnd );
+ if ( bm != NULL ) {
+ lpmm = (LPMINMAXINFO)lParam;
+ lpmm->ptMaxTrackSize.x = bm->sx + bm->framesx;
+ lpmm->ptMaxTrackSize.y = bm->sy + bm->framesy;
+ }
+ break;
+ }
+
+ case WM_SIZE:
+ bm = TrackBmscr( hwnd );
+ if ( bm != NULL ) {
+ bm->wx = lParam & 0xFFFF; // xサイズ
+ bm->wy = (lParam >> 16) & 0xFFFF; // yサイズ
+ bm->SetScroll( bm->viewx, bm->viewy );
+ }
+ break;
+
+ case WM_MOUSEWHEEL:
+ bm = TrackBmscr( hwnd );
+ if ( bm != NULL ) {
+ bm->savepos[BMSCR_SAVEPOS_MOSUEZ] = LOWORD(wParam);
+ bm->savepos[BMSCR_SAVEPOS_MOSUEW] = HIWORD(wParam);
+ }
+ return 0;
+
+ case WM_MOUSEMOVE:
+ bm = TrackBmscr( hwnd );
+ if ( bm != NULL ) {
+ bm->savepos[BMSCR_SAVEPOS_MOSUEX] = LOWORD(lParam);
+ bm->savepos[BMSCR_SAVEPOS_MOSUEY] = HIWORD(lParam);
+ }
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ if ( code_isirq( HSPIRQ_ONCLICK ) ) {
+ code_sendirq( HSPIRQ_ONCLICK, (int)uMessage - (int)WM_LBUTTONDOWN, (int)wParam, (int)lParam );
+ }
+ break;
+ case WM_COMMAND:
+ if ( wParam & MESSAGE_HSPOBJ ) {
+ id = (int)GetWindowLongPtr( hwnd, GWLP_USERDATA );
+ bm =curwnd->GetBmscr( id );
+ //Alertf( "%d,%x,%x (%d)",id,wParam,lParam , ( wParam & (MESSAGE_HSPOBJ-1)) );
+ bm->SendHSPObjectNotice( (int)wParam );
+ }
+ return 0;
+
+ case MM_MCINOTIFY:
+ if ( wParam == MCI_NOTIFY_SUCCESSFUL ) {
+ if ( notifyfunc != NULL ) notifyfunc( hwnd );
+ }
+ return 0;
+
+#ifdef HSPWINGUIDLL
+ case WM_QUERYENDSESSION:
+ return TRUE;
+ case WM_CLOSE:
+ return 0;
+#else
+ case WM_QUERYENDSESSION:
+ case WM_CLOSE:
+ id = (int)GetWindowLongPtr( hwnd, GWLP_USERDATA );
+ if ( code_isirq( HSPIRQ_ONEXIT ) ) {
+ int iparam = 0;
+ if ( uMessage == WM_QUERYENDSESSION ) iparam++;
+ retval = code_sendirq( HSPIRQ_ONEXIT, iparam, id, 0 );
+ if ( retval == RUNMODE_INTJUMP ) retval = code_execcmd2(); // onexit goto時は実行してみる
+ if ( retval != RUNMODE_END ) return 0;
+ }
+ code_puterror( HSPERR_NONE );
+ PostQuitMessage(0);
+ return (uMessage == WM_QUERYENDSESSION) ? true : false;
+#endif
+
+ case WM_DRAWITEM:
+ if ( wParam & MESSAGE_HSPOBJ ) {
+ id = (int)GetWindowLongPtr( hwnd, GWLP_USERDATA );
+ bm =curwnd->GetBmscr( id );
+ bm->SendHSPObjectDraw( (int)wParam, (LPDRAWITEMSTRUCT)lParam );
+ }
+ break;
+
+ }
+
+ return DefWindowProc (hwnd, uMessage, wParam, lParam) ;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ interface
+*/
+/*------------------------------------------------------------*/
+
+void HspWnd::Dispose( void )
+{
+ // 破棄
+ //
+ int i;
+ HWND hwnd;
+ Bmscr *bm;
+ for(i=0;ihwnd;
+ if ( hwnd != NULL ) DestroyWindow( hwnd );
+ delete bm;
+ }
+ }
+ free( mem_bm );
+ UnregisterClass( defcls, hInst );
+}
+
+
+int HspWnd::GetActive( void )
+{
+ //
+ // detect active window
+ int i;
+ HWND hwnd;
+ Bmscr *bm;
+
+ hwnd = GetActiveWindow();
+
+ for(i=0;ihwnd != NULL ) if ( bm->hwnd == hwnd ) return i;
+ }
+ }
+ if (( wnd_parent != NULL )&&( wnd_parent == hwnd )) return 0;
+
+ return -1;
+}
+
+
+void HspWnd::ExpandScreen( int id )
+{
+ int i;
+ int idmax;
+ Bmscr **new_bm;
+
+ //Alertf("Expand:%d:%d",idmax,bmscr_max);
+ idmax = id + 1;
+ if ( idmax <= bmscr_max ) return;
+ new_bm = (Bmscr **)malloc( sizeof( Bmscr * ) * idmax );
+
+ for(i=0;i= bmscr_max )||( bmscr_max == 0 )) {
+ new_bm[i] = NULL;
+ } else {
+ //if ( mem_bm[i] != NULL )
+ new_bm[i] = mem_bm[i];
+ }
+ }
+ if ( mem_bm != NULL ) free( mem_bm );
+
+ bmscr_max = idmax;
+ mem_bm = new_bm;
+}
+
+
+void HspWnd::Reset( HANDLE instance, char *wndcls )
+{
+ // all window initalize
+ //
+ int i;
+ WNDCLASS wndclass ;
+ HSPAPICHAR *hactmp1 = 0;
+ hInst=(HINSTANCE)instance;
+ _tcscpy( defcls, chartoapichar(wndcls,&hactmp1) );
+ freehac(&hactmp1);
+
+ // alloc Bmscr
+ //
+ bmscr_max = 0;
+ mem_bm = NULL;
+ ExpandScreen( 31 ); // とりあえず
+
+ // global vals
+ //
+ wfy=GetSystemMetrics( SM_CYCAPTION )+GetSystemMetrics( SM_CYFRAME )*2;
+ wfx=GetSystemMetrics( SM_CXFRAME )*2;
+ wbx=GetSystemMetrics( SM_CXHTHUMB );
+ wby=GetSystemMetrics( SM_CYVTHUMB );
+ mwfy=GetSystemMetrics( SM_CYCAPTION )+GetSystemMetrics( SM_CYFIXEDFRAME )*2;
+ mwfx=GetSystemMetrics( SM_CXFIXEDFRAME )*2;
+
+ // main window class
+ //
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = (WNDPROC) WndProc ;
+ wndclass.cbClsExtra = 0 ;
+ wndclass.cbWndExtra = 0 ;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(128) );
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = defcls;
+ RegisterClass (&wndclass);
+
+ // Reset palette
+ //
+ for(i=0;i<256*3;i++) {
+ pstpt[i] = i/3; // グレースケールパレットを作成
+ }
+
+ // save pointer for C
+ //
+ SetNotifyFunc( NULL );
+ SetEventNoticePtr( &bmscr_res );
+ SetParentWindow( NULL );
+ curwnd = this;
+}
+
+
+void HspWnd::SetEventNoticePtr( int *ptr )
+{
+ resptr = ptr;
+ SetObjectEventNoticePtr( resptr );
+}
+
+
+void HspWnd::SetNotifyFunc( void *func )
+{
+ notifyfunc = (MM_NOTIFY_FUNC)func;
+}
+
+
+void HspWnd::MakeBmscrOff( int id, int sx, int sy, int mode )
+{
+ // Bmscr(オフスクリーン)生成
+ //
+ ExpandScreen( id );
+
+ HWND hwnd = NULL;
+
+ if ( mem_bm[ id ] != NULL ) {
+ hwnd = mem_bm[ id ]->hwnd;
+ delete mem_bm[ id ];
+ mem_bm[ id ] = NULL;
+
+ ShowWindow( hwnd, SW_HIDE );
+ }
+
+ Bmscr * bm = new Bmscr;
+ mem_bm[ id ] = bm;
+
+ bm->wid = id;
+ bm->master_hspwnd = static_cast< void * >( this );
+ bm->type = HSPWND_TYPE_BUFFER;
+
+ bm->Init( hInst, hwnd, sx, sy,
+ ( mode & 0x01 ? BMSCR_PALMODE_PALETTECOLOR : BMSCR_PALMODE_FULLCOLOR ) );
+
+ bm->wx = 0;
+ bm->wy = 0;
+ bm->wchg = 0;
+ bm->viewx=0;
+ bm->viewy=0;
+}
+
+
+void HspWnd::MakeBmscrWnd( int id, int type, int xx, int yy, int wx, int wy, int sx, int sy, int mode )
+{
+ HSPAPICHAR *hactmp1 = 0;
+ // Bmscr(ウィンドウ)生成
+ //
+ ExpandScreen( id );
+
+ int wndtype = type, style = 0, exstyle = 0;
+ HWND par_hwnd = NULL;
+
+ // スクリーンタイプごとのウィンドウスタイルの設定。
+ if ( wndtype == HSPWND_TYPE_BGSCR ) {
+ style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+
+ } else {
+ if ( mode & 0x100 ) {
+ wndtype = HSPWND_TYPE_SSPREVIEW;
+ style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+ par_hwnd = static_cast< HWND >( wnd_parent );
+
+ } else {
+ style = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX
+ | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+ if ( id > 0 && !( mode & 0x04 ) ) { // サイズ可変。
+ style |= WS_THICKFRAME;
+ }
+ if ( mode & 0x08 ) { // ツールウィンドウ。
+ exstyle |= WS_EX_TOOLWINDOW;
+ }
+ if ( mode & 0x10 ) { // 縁が深い。
+ exstyle |= WS_EX_OVERLAPPEDWINDOW;
+ }
+ }
+ }
+
+ HWND hwnd = NULL;
+
+ // ウィンドウの生成・再設定。
+ if ( mem_bm[ id ] == NULL ) {
+
+#ifdef HSPDEBUG
+ char const * const pc = HSPTITLE hspver;
+#else
+ char const * const pc = NULL;
+#endif
+
+ hwnd = CreateWindowEx( exstyle, // extra window style
+ defcls, // window class name
+ chartoapichar(pc,&hactmp1), // window caption
+ style, // window style
+ ( xx != -1 ? xx : CW_USEDEFAULT ),
+ // initial x position
+ ( yy != -1 ? yy : CW_USEDEFAULT ),
+ // initial y position
+ wx, // initial x size
+ wy, // initial y size
+ par_hwnd, // parent window handle
+ NULL, // window menu handle
+ hInst, // program instance handle
+ NULL ); // creation parameters
+ freehac(&hactmp1);
+
+ } else {
+ hwnd = mem_bm[ id ]->hwnd;
+ delete mem_bm[ id ];
+ mem_bm[ id ] = NULL;
+
+ RECT rc;
+ GetWindowRect( hwnd, &rc );
+ SetWindowPos( hwnd, NULL,
+ ( xx != -1 ? xx : rc.left ), ( yy != -1 ? yy : rc.top ), wx, wy,
+ SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
+ SetWindowLong( hwnd, GWL_STYLE, style );
+ SetWindowLong( hwnd, GWL_EXSTYLE, exstyle );
+ }
+
+ SetWindowLongPtr( hwnd, GWLP_USERDATA, id );
+
+ Bmscr * bm = new Bmscr;
+ mem_bm[ id ] = bm;
+
+ bm->wid = id;
+ bm->master_hspwnd = static_cast< void * >( this );
+ bm->type = wndtype;
+
+ bm->Init( hInst, hwnd, sx, sy,
+ ( mode & 0x01 ? BMSCR_PALMODE_PALETTECOLOR : BMSCR_PALMODE_FULLCOLOR ) );
+
+ bm->wchg = 0;
+ bm->viewx = 0;
+ bm->viewy = 0;
+
+ RECT rc;
+ rc.left = 0;
+ rc.top = 0;
+ rc.right = wx;
+ rc.bottom = wy;
+ if ( AdjustWindowRectEx( &rc, style, FALSE, exstyle ) ) {
+ bm->framesx = rc.right - rc.left - wx;
+ bm->framesy = rc.bottom - rc.top - wy;
+ } else {
+ bm->framesx = wfx;
+ bm->framesy = wfy;
+ }
+
+ bm->Width( wx, wy, -1, -1, 1 );
+
+ SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
+ ( mode & 2 ? SWP_NOACTIVATE | SWP_NOZORDER : SWP_SHOWWINDOW ) |
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE );
+
+ bm->Update();
+}
+
+
+void HspWnd::MakeBmscr( int id, int type, int xx, int yy, int wx, int wy, int sx, int sy, int mode )
+{
+ // Bmscr生成
+ //
+ if ( id < 0 ) throw HSPERR_ILLEGAL_FUNCTION;
+
+ Bmscr const * const pbm = ( id < bmscr_max ? mem_bm[ id ] : NULL );
+
+ if ( type == HSPWND_TYPE_BUFFER ) {
+ MakeBmscrOff( id, sx, sy, mode );
+
+ } else if ( pbm == NULL || pbm->type != HSPWND_TYPE_BUFFER ) {
+ MakeBmscrWnd( id, type, xx, yy, wx, wy, sx, sy, mode );
+
+ } else {
+ MakeBmscrOff( id, sx, sy, mode );
+ //throw HSPERR_UNSUPPORTED_FUNCTION;
+ }
+}
+
+
+int HspWnd::Picload( int id, char *fname, int mode )
+{
+ // picload
+ // ( mode:0=resize/1=overwrite )
+ //
+ Bmscr *bm;
+ void *pBuf;
+ HGLOBAL h;
+ RECT rc;
+ int i,size,x,y,psx,psy;
+ HRESULT hr;
+ long hmWidth, hmHeight;
+ LPPICTURE gpPicture; // IPicture
+ LPSTREAM pstm = NULL; // IStreamを取得する
+ char fext[8];
+ int stbmode;
+
+ bm = GetBmscr( id );
+ if ( bm == NULL ) return 1;
+ if ( bm->flag == BMSCR_FLAG_NOUSE ) return 1;
+
+ // ファイルサイズを取得
+ size = dpm_exist( fname );
+ if ( size <= 0 ) return 1;
+
+ // グローバル領域を確保
+ h = GlobalAlloc( GMEM_MOVEABLE, size );
+ if( h == NULL) return 2;
+ pBuf = GlobalLock( h );
+ if( pBuf == NULL ) return 2;
+ i = dpm_read( fname, pBuf, size, 0 );
+ if ( i <= 0 ) return 1;
+
+#ifdef USE_STBIMAGE
+ stbmode = 0;
+ getpath(fname,fext,16+2); // 拡張子を小文字で取り出す
+
+ if (!strcmp(fext,".png")) stbmode++; // ".png"の時
+ if (!strcmp(fext,".psd")) stbmode++; // ".psd"の時
+ if (!strcmp(fext,".tga")) stbmode++; // ".tga"の時
+
+ if ( stbmode ) { // stb_imageを使用して読み込む
+ int components;
+ unsigned char *sp_image;
+ sp_image = stbi_load_from_memory( (unsigned char *)pBuf, size, &psx, &psy, &components, 4 );
+ if ( sp_image == NULL ) return 3;
+
+ if (( mode == 0 )||( mode == 2 )) {
+ int palsw,type;
+ type = bm->type; palsw = bm->palmode;
+ MakeBmscr( id, type, -1, -1, psx, psy, psx, psy, palsw );
+ bm = GetBmscr( id );
+ if ( mode == 2 ) bm->Cls( 4 ); // 黒色でクリアしておく
+ }
+
+ x = bm->cx; y = bm->cy;
+ bm->RenderAlphaBitmap( psx, psy, components, sp_image );
+ bm->Send( x, y, psx, psy );
+
+ stbi_image_free(sp_image);
+ GlobalUnlock( h );
+ GlobalFree(h);
+ return 0;
+ }
+#endif
+
+ GlobalUnlock( h );
+
+ hr = CreateStreamOnHGlobal( h, TRUE, &pstm ); // グローバル領域からIStreamを作成
+ if( !SUCCEEDED(hr) ) return 3;
+ hr = OleLoadPicture( pstm, size, FALSE, IID_IPicture, (LPVOID *)&gpPicture ); // IPictureのオブジェクトのアドレスを取得
+ pstm->Release(); // IStreamオブジェクトを開放
+ if( SUCCEEDED( hr ) == FALSE || gpPicture == NULL ) {
+ return 3;
+ }
+
+ // get width and height of picture
+ gpPicture->get_Width(&hmWidth);
+ gpPicture->get_Height(&hmHeight);
+ // convert himetric to pixels
+ psx = MulDiv( hmWidth, GetDeviceCaps( bm->hdc, LOGPIXELSX ), HIMETRIC_INCH );
+ psy = MulDiv( hmHeight, GetDeviceCaps( bm->hdc, LOGPIXELSY ), HIMETRIC_INCH );
+
+ if (( mode == 0 )||( mode == 2 )) {
+ int palsw,type;
+ type = bm->type; palsw = bm->palmode;
+ MakeBmscr( id, type, -1, -1, psx, psy, psx, psy, palsw );
+ bm = GetBmscr( id );
+ if ( mode == 2 ) bm->Cls( 4 ); // 黒色でクリアしておく
+ }
+
+ // setup initial position
+ x = bm->cx; y = bm->cy;
+ GetClientRect( bm->hwnd, &rc );
+ // display picture using IPicture::Render
+ gpPicture->Render( bm->hdc, x, y, psx, psy, 0, hmHeight, hmWidth, -hmHeight, &rc );
+ bm->Send( x, y, psx, psy );
+
+ gpPicture->Release();
+ GlobalFree(h);
+ return 0;
+}
+
+
+Bmscr *HspWnd::GetBmscrSafe( int id )
+{
+ // 安全なbmscr取得
+ //
+ Bmscr *bm;
+ if (( id < 0 )||( id >= bmscr_max )) throw HSPERR_ILLEGAL_FUNCTION;
+ bm = GetBmscr( id );
+ if ( bm == NULL ) throw HSPERR_ILLEGAL_FUNCTION;
+ if ( bm->flag == BMSCR_FLAG_NOUSE ) throw HSPERR_ILLEGAL_FUNCTION;
+ return bm;
+}
+
+
+int HspWnd::GetEmptyBufferId( void )
+{
+ // 空きIDを取得
+ //
+ int i;
+ Bmscr *bm;
+ for(i=0;iflag == BMSCR_FLAG_NOUSE ) return i;
+ }
+ return bmscr_max;
+}
+
+
+/*------------------------------------------------------------*/
+/*
+ Bmscr interface
+*/
+/*------------------------------------------------------------*/
+
+Bmscr::Bmscr()
+{
+ // bmscr初期化
+ //
+ flag = BMSCR_FLAG_NOUSE;
+}
+
+Bmscr::~Bmscr()
+{
+ // Bmscr破棄
+ //
+ if ( flag == BMSCR_FLAG_INUSE ) {
+
+ // object remove
+ //
+ ResetHSPObject();
+
+ // resource remove
+ //
+ Delfont();
+
+ // remove HBRUSH
+ //
+ if ( hbr != NULL ) {
+ DeleteObject( hbr );
+ }
+
+ // remove HPEN
+ //
+ if ( hpn != NULL ) {
+ DeleteObject( hpn );
+ }
+
+ // remove HPALETTE
+ //
+ if ( hpal != NULL ) {
+ SelectPalette( hdc, holdpal, TRUE );
+ DeleteObject( hpal );
+ }
+
+ // remove DIB section
+ //
+ SelectObject( hdc, old );
+ DeleteObject( dib );
+ DeleteDC( hdc );
+ GlobalFree( pbi );
+ }
+}
+
+/*----------------------------------------------------------------*/
+// font&text related routines
+/*----------------------------------------------------------------*/
+
+void Bmscr::Init( HANDLE instance, HWND p_hwnd, int p_sx, int p_sy, int palsw )
+{
+ // bitmap buffer make
+ //
+ HDC srchdc;
+ HBITMAP hbDib,hbOld;
+ int msize,bsize;
+
+ hwnd = p_hwnd;
+ hInst= (HINSTANCE)instance;
+
+ flag = BMSCR_FLAG_INUSE;
+ objmax = 0;
+ mem_obj = NULL;
+ sx = p_sx; sy = p_sy;
+
+ palmode = palsw;
+ bsize = sx;
+
+ if ( palmode == BMSCR_PALMODE_FULLCOLOR ) {
+ msize=sizeof(BITMAPINFOHEADER);
+ pbi=(LPBITMAPINFOHEADER)GlobalAlloc( GPTR, msize );
+ pbi->biBitCount = 24;
+ bsize*=3;
+ } else {
+ msize=sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD);
+ pbi=(LPBITMAPINFOHEADER)GlobalAlloc( GPTR, msize );
+ pbi->biBitCount = 8;
+ }
+ bsize = ( bsize + 3 )&~3;
+ sx2 = bsize;
+ bsize *= sy;
+
+ infsize = msize;
+ bmpsize = bsize;
+
+ pbi->biSize = sizeof(BITMAPINFOHEADER);
+ pbi->biWidth = sx;
+ pbi->biHeight = sy;
+ pbi->biPlanes = 1;
+
+ srchdc = GetDC(hwnd);
+ hbDib=CreateDIBSection( srchdc,(BITMAPINFO *)pbi,DIB_RGB_COLORS,
+ (void **)&pBit, NULL, 0 );
+ hdc=CreateCompatibleDC(srchdc);
+ hbOld = (HBITMAP)SelectObject( hdc, hbDib );
+ ReleaseDC( hwnd, srchdc );
+
+ dib = hbDib;
+ old = hbOld;
+ pal = (RGBQUAD *)(pbi+1);
+ hpal = NULL;
+ hbr = NULL;
+ hpn = NULL;
+ focflg = 0;
+ objmode = 1;
+ tabmove = 1;
+ hfont=NULL;
+ fl_dispw = 0;
+ imgbtn = -1;
+
+ Cls( 0 );
+
+ fl_dispw = 1;
+ fl_udraw = 1;
+}
+
+
+void Bmscr::Cls( int mode )
+{
+ // screen setting reset
+ //
+ int i;
+ HBRUSH hbr, hbrOld;
+
+ // Font initalize
+ //
+ Sysfont(0);
+
+ // object initalize
+ //
+ ResetHSPObject();
+
+ // text setting initalize
+ //
+ cx=0;cy=0;
+ Setcolor(0,0,0);
+
+ // palette initalize
+ //
+ UpdatePalette();
+
+ // screen clear
+ //
+ hbr = (HBRUSH)GetStockObject( mode );
+ hbrOld = (HBRUSH)SelectObject( hdc, hbr );
+ Rectangle( hdc, -1, -1, sx+1, sy+1);
+ SelectObject( hdc, hbrOld );
+
+ // vals initalize
+ //
+ textspeed=0;
+ ox=64;oy=24;py=0;
+ gx=32;gy=32;gmode=0;
+ objstyle = WS_CHILD|WS_VISIBLE;
+ for(i=0;i 0 ) {
+ wx = x; if ( x > sx ) wx = sx;
+ }
+ if ( y > 0 ) {
+ wy = y; if ( y > sy ) wy = sy;
+ }
+
+ if (( type < HSPWND_TYPE_MAIN )||( type == HSPWND_TYPE_SSPREVIEW )) return;
+
+ sizex = wx + framesx;
+ sizey = wy + framesy;
+ GetWindowRect( hwnd,&rw );
+ if ( wposx >= 0 ) rw.left = wposx;
+ if ( wposy >= 0 ) rw.top = wposy;
+ MoveWindow( hwnd, rw.left, rw.top, sizex, sizey, (mode>0) );
+}
+
+
+void Bmscr::Send( int x, int y, int p_sx, int p_sy )
+{
+ HDC dhdc;
+ HPALETTE opal;
+ if ( fl_udraw == 0 ) return;
+ if ( type < HSPWND_TYPE_MAIN ) return;
+ dhdc=GetDC( hwnd );
+ if ( hpal != NULL ) {
+ opal=SelectPalette( dhdc, hpal, 0 );
+ RealizePalette( dhdc );
+ }
+ BitBlt( dhdc, x-viewx, y-viewy, p_sx, p_sy, hdc,x,y, SRCCOPY );
+ if ( hpal != NULL ) {
+ SelectPalette( dhdc, opal, 0 );
+ }
+ ReleaseDC( hwnd, dhdc );
+}
+
+
+void Bmscr::Posinc( int pp )
+{
+ if ( pplfFaceName, chartoapichar(fonname,&hactmp1) );
+ freehac(&hactmp1);
+ pLogFont->lfHeight = -fpts;
+ pLogFont->lfWidth = 0;
+ pLogFont->lfOutPrecision = 0 ;
+ pLogFont->lfClipPrecision = 0 ;
+
+ if (fopt&4) {
+ pLogFont->lfUnderline = TRUE;
+ } else {
+ pLogFont->lfUnderline = FALSE;
+ }
+
+ if (fopt&8) {
+ pLogFont->lfStrikeOut = TRUE;
+ } else {
+ pLogFont->lfStrikeOut = FALSE;
+ }
+
+ if ( fopt & 16 ) {
+ pLogFont->lfQuality = ANTIALIASED_QUALITY ;
+ } else {
+ pLogFont->lfQuality = DEFAULT_QUALITY;
+ }
+
+ pLogFont->lfPitchAndFamily = 0 ;
+ pLogFont->lfEscapement = angle ;
+ pLogFont->lfOrientation = 0 ;
+
+ b=DEFAULT_CHARSET;
+ a=0;while(1) {
+ chk=fonname[a++];
+ if (chk==0) break;
+ if (chk>=0x80) { b=SHIFTJIS_CHARSET;break; }
+ }
+ pLogFont->lfCharSet = b;
+
+ if (fopt&1) {
+ pLogFont->lfWeight = FW_BOLD;
+ } else {
+ pLogFont->lfWeight = FW_NORMAL;
+ }
+
+ if (fopt&2) {
+ pLogFont->lfItalic = TRUE;
+ } else {
+ pLogFont->lfItalic = FALSE;
+ }
+
+ hf_new = CreateFontIndirect( pLogFont );
+ if ( hf_new == NULL ) return -1;
+
+ Delfont();
+ hfont = hf_new;
+ Fontupdate();
+ return 0;
+}
+
+
+void Bmscr::Sysfont( int p1 )
+{
+ /*
+ Reserved Font List
+ #define OEM_FIXED_FONT 10
+ #define ANSI_FIXED_FONT 11
+ #define ANSI_VAR_FONT 12
+ #define SYSTEM_FONT 13
+ #define DEVICE_DEFAULT_FONT 14
+ #define DEFAULT_PALETTE 15
+ #define SYSTEM_FIXED_FONT 16
+ #define DEFAULT_GUI_FONT 17
+ */
+ HFONT hf;
+ Delfont();
+ if (p1) {
+ hf=(HFONT)GetStockObject(p1);
+ if (hf!=NULL) {
+ hfont=hf;
+ Fontupdate();
+ return;
+ }
+ }
+ Newfont( "FixedSys", 14,0,0 );
+}
+
+
+void Bmscr::Setcolor( int a1, int a2, int a3 )
+{
+ COLORREF c;
+ if (a1==-1) c = PALETTEINDEX(a2);
+ else c = color = RGB(a1,a2,a3);
+ SetBkMode( hdc,TRANSPARENT );
+ SetTextColor( hdc, c );
+ if ( hbr != NULL ) DeleteObject( hbr );
+ hbr = CreateSolidBrush( c );
+ if ( hpn != NULL ) DeleteObject( hpn );
+ hpn = CreatePen( PS_SOLID,0,c );
+}
+
+
+void Bmscr::Setcolor( COLORREF rgbcolor )
+{
+ Setcolor( GetRValue(rgbcolor), GetGValue(rgbcolor), GetBValue(rgbcolor) );
+}
+
+
+void Bmscr::SetSystemcolor( int id )
+{
+ Setcolor( (COLORREF)GetSysColor( id ) );
+}
+
+
+void Bmscr::UpdatePalette( void )
+{
+ // set palette to DIB & HPALETTE
+ // *rgbptr : R,G,B order palette entry
+ //
+ int a,colors;
+ BYTE *pt;
+ RGBQUAD *bpal;
+ LOGPALETTE *lpPal;
+ HPALETTE hGetPal;
+ HspWnd *wnd;
+ void *rgbptr;
+ //FILE *fp;
+
+ wnd = (HspWnd *)master_hspwnd;
+ rgbptr = wnd->pstpt;
+ colors = 256;
+
+ if ( palmode == 0 ) return;
+
+ if ( hpal != NULL ) {
+ SelectPalette( hdc, holdpal, TRUE );
+ DeleteObject( hpal );
+ }
+
+ bpal = pal;
+ pt=(BYTE *)rgbptr;
+ for(a=0;apalVersion = 0x300;
+ lpPal->palNumEntries = (WORD) colors;
+ pt=(BYTE *)rgbptr;
+ for( a=0; apalPalEntry[a].peRed = pt[0];
+ lpPal->palPalEntry[a].peGreen = pt[1];
+ lpPal->palPalEntry[a].peBlue = pt[2];
+ lpPal->palPalEntry[a].peFlags = PC_NOCOLLAPSE;
+ pt+=3;
+ }
+ hGetPal = CreatePalette( lpPal );
+ hpal = hGetPal;
+ holdpal = SelectPalette( hdc, hGetPal, TRUE );
+ free( lpPal );
+ pals = colors;
+}
+
+
+void Bmscr::SetPalette( int palno, int rv, int gv, int bv )
+{
+ int a;
+ BYTE a1,a2,a3;
+ HspWnd *wnd;
+ BYTE *pstpt;
+
+ if ( palmode == 0 ) return;
+
+ wnd = (HspWnd *)master_hspwnd;
+ pstpt = wnd->pstpt;
+
+ a=palno*3;
+ a1=rv;a2=gv;a3=bv;
+ pstpt[a++]=a1; pstpt[a++]=a2; pstpt[a++]=a3;
+ //UpdatePalette();
+}
+
+
+void Bmscr::SetPalcolor( int palno )
+{
+ RGBQUAD *p;
+ p=&pal[ palno ];
+ color = RGB( p->rgbRed, p->rgbGreen, p->rgbBlue );
+ Setcolor( -1, palno, 0 );
+ palcolor = palno;
+}
+
+
+void Bmscr::Print( char *mes )
+{
+ int a;
+ long res;
+ SIZE *size;
+ HSPAPICHAR *hactmp1 = 0;
+ size = &printsize;
+ a=(int)strlen(mes);
+ if (a) {
+
+ //GetTextExtentPoint32( hdc, mes, a, size );
+ //HDC hdcwnd = GetDC( hwnd );
+ //HFONT holdfontwnd = (HFONT)SelectObject( hdcwnd, hfont );
+
+ //TextOut( hdc, cx, cy , mes, a );
+ chartoapichar(mes,&hactmp1);
+
+ res = TabbedTextOut( hdc, cx, cy, hactmp1 , _tcslen(hactmp1), 0, NULL, 0 );
+ freehac(&hactmp1);
+ size->cx = res & 0xffff;
+ size->cy = res>>16;
+
+ //SelectObject( hdcwnd, holdfontwnd );
+ //ReleaseDC( hwnd, hdcwnd );
+
+ Send( cx, cy, size->cx, size->cy );
+ } else {
+ GetTextExtentPoint32( hdc, TEXT(" "), 1, size );
+ }
+ Posinc( size->cy );
+}
+
+
+void Bmscr::Boxfill( int x1,int y1,int x2,int y2 )
+{
+ // boxf
+ RECT bx;
+ bx.left=x1;bx.top=y1;bx.right=x2+1;bx.bottom=y2+1;
+ FillRect( hdc, &bx, hbr );
+ Send( x1,y1,x2-x1+1,y2-y1+1 );
+}
+
+
+COLORREF Bmscr::Pget( int xx, int yy )
+{
+ // pget
+ //
+ COLORREF c;
+ c = GetPixel( hdc, xx, yy );
+ Setcolor( c );
+ return c;
+}
+
+
+void Bmscr::Pset( int xx,int yy )
+{
+ // pset
+ //
+ SetPixel( hdc,xx,yy,color );
+ Send( xx,yy,1,1 );
+}
+
+
+void Bmscr::Line( int xx,int yy )
+{
+ // line
+ //
+ HPEN oldpen;
+ int x,y,x1,y1,x2,y2;
+ x=cx;y=cy;
+ MoveToEx( hdc,x,y,NULL );
+ if (cxsx; ssy = src->sy; ssx2 = src->sx2;
+
+ cx=this->cx;sx=asx;bsx=this->sx;
+ if (xx<0) { sx+=xx;cx-=xx;xx=0; }
+ if ((xx+sx)>=ssx) sx-=(xx+sx)-ssx;
+ if (cx>bsx) return;
+ if (cx<0) {
+ sx=cx+sx;
+ if (sx<=0) return;
+ xx-=cx;cx=0;
+ }
+ vv=bsx-sx;
+ if (cx>vv) { sx-=cx-vv; }
+
+ cy=this->cy;sy=asy;bsy=this->sy;
+ if (yy<0) { sy+=yy;cy-=yy;yy=0; }
+ if ((yy+sy)>=ssy) sy-=(yy+sy)-ssy;
+ if (cy>bsy) return;
+ if (cy<0) {
+ sy=cy+sy;
+ if (sy<=0) return;
+ yy-=cy;cy=0;
+ }
+ vv=bsy-sy;
+ if (cy>vv) { sy-=cy-vv; }
+
+ p=(BYTE *)this->pBit;
+ p+=(bsy-cy-1) * this->sx2;
+ p2=(BYTE *)(src->pBit);
+ p2+=(ssy-yy-1)*ssx2;
+
+ if (!palmode) goto blt24;
+
+ p+=cx; p2+=xx;
+ tofs = this->sx2 + sx;
+ sofs = ssx2 + sx;
+
+ if (mode==2) goto tblt;
+
+ for(b=0;bpal;pand=0xffffff;
+ for(b=0;bsx2 + (sx*3);
+ sofs = ssx2 + (sx*3);
+
+ switch( mode ) {
+ case 1:
+ break;
+ case 2:
+ // FC trans copy
+ for(b=0;b