//--------------------------------------------------------------------------- static TStringList * TVPGetConfigFileOptions(AnsiString filename) { // load .cf file AnsiString errmsg; if(!FileExists(filename)) errmsg = "file not found."; TStringList * ret = new TStringList(); if(errmsg == "") { try { ret->LoadFromFile(filename); } catch(Exception & e) { errmsg = e.Message; } catch(...) { delete ret; throw; } } if(errmsg != "") TVPAddImportantLog(ttstr("(info) Loading configuration file \"") + filename.c_str() + "\" failed (ignoring) : " + errmsg.c_str()); else TVPAddImportantLog(ttstr("(info) Loading configuration file \"") + filename.c_str() + "\" succeeded."); return ret; }
//--------------------------------------------------------------------------- // utilities //--------------------------------------------------------------------------- ttstr TVPStringFromBMPUnicode(const tjs_uint16 *src, tjs_int maxlen) { // convert to ttstr from BMP unicode if(sizeof(tjs_char) == 2) { // sizeof(tjs_char) is 2 (windows native) if(maxlen == -1) return ttstr((const tjs_char*)src); else return ttstr((const tjs_char*)src, maxlen); } else if(sizeof(tjs_char) == 4) { // sizeof(tjs_char) is 4 (UCS32) // FIXME: NOT TESTED CODE tjs_int len = 0; const tjs_uint16 *p = src; while(*p) len++, p++; if(maxlen != -1 && len > maxlen) len = maxlen; ttstr ret((tTJSStringBufferLength)(len)); tjs_char *dest = ret.Independ(); p = src; while(len && *p) { *dest = *p; dest++; p++; len --; } *dest = 0; ret.FixLen(); return ret; } return TJS_W("sizeof(tjs_char) must be 2 or 4."); }
/** * レイヤーカンプ */ tTJSVariant PSD::getLayerComp() { if (!isLoaded) TVPThrowExceptionMessage(L"no data"); tTJSVariant result; ncbDictionaryAccessor dict; ncbArrayAccessor arr; int compNum = layerComps.size(); if (compNum > 0) { if (dict.IsValid()) { dict.SetValue(L"last_applied_id", lastAppliedCompId); if (arr.IsValid()) { for (int i = 0; i < compNum; i++) { ncbDictionaryAccessor tmp; if (tmp.IsValid()) { psd::LayerComp &comp = layerComps[i]; tmp.SetValue(L"id", comp.id); tmp.SetValue(L"record_visibility", comp.isRecordVisibility); tmp.SetValue(L"record_position", comp.isRecordPosition); tmp.SetValue(L"record_appearance", comp.isRecordAppearance); tmp.SetValue(L"name", ttstr(comp.name.c_str())); tmp.SetValue(L"comment", ttstr(comp.comment.c_str())); arr.SetValue((tjs_int32)i, tmp.GetDispatch()); } } dict.SetValue(L"comps", arr.GetDispatch()); } result = dict; } } return result; }
//--------------------------------------------------------------------------- // TVPInitializeBaseSystems //--------------------------------------------------------------------------- void TVPInitializeBaseSystems() { // set system archive delimiter tTJSVariant v; if(TVPGetCommandLine(TJS_W("-arcdelim"), &v)) TVPArchiveDelimiter = ttstr(v)[0]; // set default current directory { char drive[MAXDRIVE]; char dir[MAXDIR]; fnsplit(_argv[0], drive, dir, NULL, NULL); ttstr curdir(ttstr(drive) + ttstr(dir)); if(curdir.GetLastChar() != TJS_W('\\')) curdir += TJS_W('\\'); TVPSetCurrentDirectory(curdir); } // load message map file bool load_msgmap = GetSystemSecurityOption("disablemsgmap") == 0; if(load_msgmap) { const tjs_char name_msgmap [] = TJS_W("msgmap.tjs"); if(TVPIsExistentStorage(name_msgmap)) TVPExecuteStorage(name_msgmap, NULL, false, TJS_W("")); } }
tjs_error TJS_INTF_METHOD StartTransition( /*in*/iTVPSimpleOptionProvider *options, // option provider /*in*/iTVPSimpleImageProvider *imagepro, // image provider /*in*/tTVPLayerType layertype, // destination layer type /*in*/tjs_uint src1w, tjs_uint src1h, // source 1 size /*in*/tjs_uint src2w, tjs_uint src2h, // source 2 size /*out*/tTVPTransType *type, // transition type /*out*/tTVPTransUpdateType * updatetype, // update typwe /*out*/iTVPBaseTransHandler ** handler // transition handler ) { if(type) *type = ttExchange; // transition type : exchange if(updatetype) *updatetype = tutDivisibleFade; // update type : divisible fade if(!handler) return TJS_E_FAIL; if(!options) return TJS_E_FAIL; if(src1w != src2w || src1h != src2h) TVPThrowExceptionMessage(TVPTransitionLayerSizeMismatch, ttstr((tjs_int)src2w) + TJS_W("x") + ttstr((tjs_int)src2h), ttstr((tjs_int)src1w) + TJS_W("x") + ttstr((tjs_int)src1h) ); *handler = GetTransitionObject(options, imagepro, layertype, src1w, src1h, src2w, src2h); return TJS_S_OK; }
// urldecode処理 static tjs_error TJS_INTF_METHOD urldecode(tTJSVariant *result, tjs_int numparams, tTJSVariant **param, iTJSDispatch2 *objthis) { if (numparams > 0 && result) { bool utf8 = !(numparams> 1 && (int)*param[1] == 0); ttstr str = *param[0]; tjs_int len = str.length(); std::string os; for (int i=0;i<len;i++) { int ch = str[i]; if (ch > 0xff) { return TJS_E_INVALIDPARAM; } if (ch == '%') { if (i + 2 >= len) { return TJS_E_INVALIDPARAM; } char buf[3]; buf[0] = (char)str[i+1]; buf[1] = (char)str[i+2]; buf[2] = '\0'; long n = strtol(buf, NULL, 16); if (errno == ERANGE) { return TJS_E_INVALIDPARAM; } os += (char)n; i+=2; } else { os += (char)ch; } } if (utf8) { const char *s = os.c_str(); tjs_int len = TVPUtf8ToWideCharString(s, NULL); if (len > 0) { tjs_char *dat = new tjs_char[len+1]; try { TVPUtf8ToWideCharString(s, dat); dat[len] = TJS_W('\0'); } catch(...) { delete [] dat; throw; } *result = ttstr(dat); delete [] dat; } } else { *result = ttstr(os.c_str()); } } return TJS_S_OK; }
//--------------------------------------------------------------------------- ttstr tTJSScriptBlock::GetNameInfo() const { if(LineOffset == 0) { return ttstr(Name); } else { return ttstr(Name) + TJS_W("(line +") + ttstr(LineOffset) + TJS_W(")"); } }
/** * 名前の取得 * @param layレイヤ情報 */ ttstr PSD::layname(psd::LayerInfo &lay) { ttstr ret; if (!lay.layerNameUnicode.empty()) { ret = ttstr(lay.layerNameUnicode.c_str()); } else { ret = ttstr(lay.layerName.c_str()); } return ret; }
/** * tTJSVariant を XMLノードに変換 * @param var 変換元の値 * @param doc XMLドキュメント * @return 作成したノード */ static xml_node * createNodeFromVariant(tTJSVariant &var, xml_document &doc) { switch(var.Type()) { case tvtObject: { iTJSDispatch2 *obj = var.AsObjectNoAddRef(); if (obj == NULL) { // NULL return doc.allocate_node(rapidxml::node_element, L"null"); } else if (obj->IsInstanceOf(TJS_IGNOREPROP,NULL,NULL,L"Array",obj) == TJS_S_TRUE) { // 配列 xml_node *node = doc.allocate_node(rapidxml::node_element, L"array"); tjs_int count = 0; { tTJSVariant result; if (TJS_SUCCEEDED(obj->PropGet(0, L"count", NULL, &result, obj))) { count = result; } } for (tjs_int i=0; i<count; i++) { tTJSVariant result; if (obj->PropGetByNum(TJS_IGNOREPROP, i, &result, obj) == TJS_S_OK) { xml_node *prop = doc.allocate_node(rapidxml::node_element, L"property"); prop->append_attribute(doc.allocate_attribute(L"id", ttstr(i).c_str())); prop->append_node(createNodeFromVariant(result, doc)); node->append_node(prop); } } return node; } else { // 辞書 xml_node *node = doc.allocate_node(rapidxml::node_element, L"object"); DictMemberDispCaller *caller = new DictMemberDispCaller(doc, node); tTJSVariantClosure closure(caller); obj->EnumMembers(TJS_IGNOREPROP, &closure, obj); caller->Release(); return node; } } break; case tvtString: return doc.allocate_node(rapidxml::node_element, L"string", var.GetString()); case tvtInteger: case tvtReal: return doc.allocate_node(rapidxml::node_element, L"number", ttstr(var).c_str()); case tvtVoid: return doc.allocate_node(rapidxml::node_element, L"undefined"); default: return doc.allocate_node(rapidxml::node_element, L"null"); } }
//--------------------------------------------------------------------------- void tTJSScriptBlock::Dump() const { std::list<tTJSInterCodeContext *>::const_iterator i = InterCodeContextList.begin(); while(i != InterCodeContextList.end()) { ConsoleOutput(TJS_W(""), (void*)this); tjs_char ptr[256]; TJS_sprintf(ptr, TJS_W(" 0x%p"), (*i)); ConsoleOutput((ttstr(TJS_W("(")) + ttstr((*i)->GetContextTypeName()) + TJS_W(") ") + ttstr((*i)->GetName()) + ptr).c_str(), (void*)this); (*i)->Disassemble(ConsoleOutput, (void*)this); i++; } }
//--------------------------------------------------------------------------- void tTVPLayerManager::PrimaryMouseDown(tjs_int x, tjs_int y, tTVPMouseButton mb, tjs_uint32 flags) { PrimaryMouseMove(x, y, flags); tTJSNI_BaseLayer * l = CaptureOwner ? CaptureOwner : GetMostFrontChildAt(x, y); if(l) { l->FromPrimaryCoordinates(x, y); ReleaseCaptureCalled = false; l->FireMouseDown(x, y, mb, flags); bool no_capture = ReleaseCaptureCalled; if(CaptureOwner != l) { ReleaseCapture(); if(!no_capture) { CaptureOwner = l; if(CaptureOwner->Owner) CaptureOwner->Owner->AddRef(); // addref TJS object } } SetHint(NULL,ttstr()); } else { ReleaseCapture(); } }
/* * 指定したパスにあるファイル名一覧の取得 * @param pathname パス名 * @param lister リスト取得用インターフェース */ void PSD::GetListAt(const ttstr &pathname, iTVPStorageLister *lister) { startStorage(); // ID一覧から名前を生成 if (pathname == "id/") { LayerIdIdxMap::const_iterator it = layerIdIdxMap.begin(); while (it != layerIdIdxMap.end()) { ttstr name = ttstr(it->first); lister->Add(name + BMPEXT); it++; } return; } // パス登録情報から名前を生成 PathMap::const_iterator n = pathMap.find(pathname); if (n != pathMap.end()) { const NameIdxMap &names = n->second; NameIdxMap::const_iterator it = names.begin(); while (it != names.end()) { ttstr name = it->first; lister->Add(name + BMPEXT); it++; } } }
//--------------------------------------------------------------------------- void __fastcall TTVPMainForm::ShowScriptEditorButtonClick(TObject *Sender) { if(TVPGetDebugSupportShowable()) { if(TVPMainPadForm && TVPMainPadForm->Visible) { if(CanHideAnyWindow()) { TVPMainPadForm->Visible = false; ShowScriptEditorButton->Down = false; } } else { if(!TVPMainPadForm) { TVPMainPadForm = new TTVPPadForm(Application, true); TVPMainPadForm->Caption = ttstr(TVPMainCDPName).AsAnsiString(); } TVPMainPadForm->Visible = true; ShowScriptEditorButton->Down = true; TVPMainPadForm->BringToFront(); } } }
HWND createMessageWindow(LPCWSTR className, LPCWSTR windowName) { HINSTANCE hinst = ::GetModuleHandle(NULL); if (!MessageWindowClass()) { WNDCLASSEXW wcex = { /*size*/sizeof(WNDCLASSEX), /*style*/0, /*proc*/&MsgWndProc, /*extra*/0L,0L, /*hinst*/hinst, /*icon*/NULL, /*cursor*/NULL, /*brush*/NULL, /*menu*/NULL, /*class*/className, /*smicon*/NULL }; if (!(MessageWindowClass(false, ::RegisterClassExW(&wcex)))) TVPThrowExceptionMessage((ttstr(TJS_W("register window class failed: "))+className).c_str()); } HWND hwnd = ::CreateWindowExW(0, (LPCWSTR)MAKELONG(MessageWindowClass(), 0), windowName, 0, 0, 0, 1, 1, HWND_MESSAGE, NULL, hinst, NULL); if (!hwnd) TVPThrowExceptionMessage((ttstr(TJS_W("create message window failed: "))+windowName).c_str()); ::SetWindowLong(hwnd, GWL_USERDATA, (LONG)this); return hwnd; }
static ttstr TVPParseCommandLineOne(const ttstr &i) { // value is specified const tjs_char *p, *o; p = o = i.c_str(); p = TJS_strchr(p, '='); if(p == NULL) { return i + TJS_W("=yes"); } p++; ttstr optname(o, p - o); if(*p == TJS_W('\'') || *p == TJS_W('\"')) { // as an escaped string tTJSVariant v; TJSParseString(v, &p); return optname + ttstr(v); } else { // as a string return optname + p; } }
/** * octet の MD5ハッシュ値の取得 * @param octet 対象オクテット * @return ハッシュ値(32文字の16進数ハッシュ文字列(小文字)) */ tjs_error TJS_INTF_METHOD ScriptsAdd::getMD5HashString(tTJSVariant *result, tjs_int numparams, tTJSVariant **param, iTJSDispatch2 *objthis) { if (numparams < 1) return TJS_E_BADPARAMCOUNT; tTJSVariantOctet *octet = param[0]->AsOctetNoAddRef(); TVP_md5_state_t st; TVP_md5_init(&st); TVP_md5_append(&st, octet->GetData(), (int)octet->GetLength()); tjs_uint8 buffer[16]; TVP_md5_finish(&st, buffer); tjs_char ret[32+1], *hex = TJS_W("0123456789abcdef"); for (tjs_int i=0; i<16; i++) { ret[i*2 ] = hex[(buffer[i] >> 4) & 0xF]; ret[i*2+1] = hex[(buffer[i] ) & 0xF]; } ret[32] = 0; if (result) *result = ttstr(ret); return TJS_S_OK; }
//--------------------------------------------------------------------------- tTJSString TJSInt32ToHex(tjs_uint32 num, int zeropad) { // convert given number to HEX string. // zeros are padded when the output string's length is smaller than "zeropad". // "zeropad" cannot be larger than 8. if(zeropad > 8) zeropad = 8; tjs_char buf[12]; tjs_char buf2[12]; tjs_char *p = buf; tjs_char *d = buf2; do { *(p++) = (TJS_W("0123456789ABCDEF"))[num % 16]; num /= 16; zeropad --; } while(zeropad || num); p--; while(buf <= p) *(d++) = *(p--); *d = 0; return ttstr(buf2); }
//--------------------------------------------------------------------------- tTJSBinaryStream * TVPCreateBinaryStreamForWrite(const ttstr & name, const ttstr & modestr) { tTJSBinaryStream* stream; // check o mode const tjs_char * o_ofs; o_ofs = TJS_strchr(modestr.c_str(), TJS_W('o')); if(o_ofs != NULL) { // seek to offset o_ofs++; tjs_char buf[256]; int i; for(i = 0; i < 255; i++) { if(o_ofs[i] >= TJS_W('0') && o_ofs[i] <= TJS_W('9')) buf[i] = o_ofs[i]; else break; } buf[i] = 0; tjs_uint64 ofs = ttstr(buf).AsInteger(); stream = TVPCreateStream(name, TJS_BS_UPDATE); stream->SetPosition(ofs); } else { stream = TVPCreateStream(name, TJS_BS_WRITE); } return stream; }
bool start(ttstr const &target, const tjs_char *param=0, const tjs_char *folder=0) { if (hasError()) return false; ttstr cmd(L"\""); // 吉里吉里サーチパス上にある場合はそちらを優先 if (TVPIsExistentStorage(target)) { ttstr tmp = TVPGetPlacedPath(target); TVPGetLocalName(tmp); /**/cmd += tmp + L"\""; } else cmd += target + L"\""; if (param && wcslen(param) > 0) cmd += L" " + ttstr(param); LPWSTR cmdline = (LPWSTR)cmd.c_str(); // 子プロセス作成 STARTUPINFO si; ::ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdOutput = hOW; si.hStdInput = hIR; si.hStdError = hEW; si.wShowWindow = SW_HIDE; if (!::CreateProcessW(0, cmdline, 0, 0, TRUE, CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, 0, folder, &si, &pi)) { error = ERR_PROC; return false; } return true; }
//--------------------------------------------------------------------------- // tTJSNativeClass //--------------------------------------------------------------------------- tTJSNativeClass::tTJSNativeClass(const ttstr &name) { CallFinalize = false; ClassName = TJSMapGlobalStringMap(name); if(TJSObjectHashMapEnabled()) TJSObjectHashSetType(this, ttstr(TJS_W("(native class) ")) + ClassName); }
/** * 吉里吉里に対して例外通知 */ void JSEXCEPTION(Isolate* isolate, TryCatch *try_catch) { HandleScope handle_scope(isolate); //HandleScope handle_scope; String::Value exception(try_catch->Exception()); Local<Message> message = try_catch->Message(); if (!message.IsEmpty()) { // 例外表示 String::Value filename(message->GetScriptResourceName()); ttstr msg; msg += *filename; msg += ":"; msg += tTJSVariant(message->GetLineNumber()); msg += ":"; msg += *exception; TVPAddLog(msg); // Print (filename):(line number): (message). String::Value sourceline(message->GetSourceLine()); TVPAddLog(ttstr(*sourceline)); // エラー行表示 ttstr wavy; int start = message->GetStartColumn(); for (int i = 0; i < start; i++) { wavy += " "; } int end = message->GetEndColumn(); for (int i = start; i < end; i++) { wavy +="^"; } TVPAddLog(wavy); // スタックトレース表示 String::Value stack_trace(try_catch->StackTrace()); if (stack_trace.length() > 0) { TVPAddLog(ttstr(*stack_trace)); } } TVPThrowExceptionMessage(*exception); }
/** * コマンドライン呼び出し */ tjs_error TJS_INTF_METHOD commandExecute( tTJSVariant *result, tjs_int numparams, tTJSVariant **param, iTJSDispatch2 *objthis) { tTJSVariant vStdOut; // パラメータチェック if (numparams == 0) return TJS_E_BADPARAMCOUNT; if (param[0]->Type() != tvtString) return TJS_E_INVALIDPARAM; // コマンドライン/タイムアウト取得 int timeout = 0; ttstr target(param[0]->GetString()); const tjs_char *cmdprm = 0; if (numparams > 1) cmdprm = param[1]->GetString(); if (numparams > 2) timeout = (tjs_int)*param[2]; DWORD exit = ~0L; bool haserr = true, timeouted = false; LPCWSTR errmes = 0; iTJSDispatch2 *array = TJSCreateArrayObject(); if (array != 0) { CommandExecute exec; if (exec.start(target, cmdprm)) exec.wait(cmdExecLineCallback, array, timeout); exit = exec.getExitCode(&haserr, &timeouted, &errmes); vStdOut.SetObject(array, array); array->Release(); } ncbDictionaryAccessor ret; if (ret.IsValid()) { ret.SetValue(L"stdout", vStdOut); if (haserr && errmes != 0) { ret.SetValue(L"status", ttstr(timeouted ? L"timeout" : L"error")); ret.SetValue(L"message", ttstr(errmes)); } else { ret.SetValue(L"status", ttstr(haserr ? L"failed" : L"ok")); ret.SetValue(L"exitcode", (tjs_int)exit); } } if (result != NULL) *result = ret; return TJS_S_OK; }
//--------------------------------------------------------------------------- // tTJSNativeFunction //--------------------------------------------------------------------------- tTJSNativeFunction::tTJSNativeFunction(const tjs_char *name) { if(TJSObjectHashMapEnabled()) { TJSAddObjectHashRecord(this); if(name) TJSObjectHashSetType(this, ttstr(TJS_W("(native function) ")) + name); } }
void FontSystem::ConstructDefaultFont() { if( !DefaultLOGFONTCreated ) { DefaultLOGFONTCreated = true; DefaultFont.Height = -12; DefaultFont.Flags = 0; DefaultFont.Angle = 0; DefaultFont.Face = ttstr(TVPGetDefaultFontName()); } }
//--------------------------------------------------------------------------- ttstr TVPGetVersionString() { TVPGetVersion(); tjs_char verstr[100]; TJS_snprintf(verstr, sizeof(verstr)/sizeof(tjs_char), TJS_W("%d.%d.%d.%d"), TVPVersionMajor, TVPVersionMinor, TVPVersionRelease, TVPVersionBuild); return ttstr(verstr); }
//--------------------------------------------------------------------------- ttstr tTJSScriptBlock::GetLineDescriptionString(tjs_int pos) const { // get short description, like "mainwindow.tjs(321)" // pos is in character count from the first of the script tjs_int line =SrcPosToLine(pos)+1; ttstr name; if(Name) { name = Name; } else { tjs_char ptr[128]; TJS_sprintf(ptr, TJS_W("0x%p"), this); name = ttstr(TJS_W("anonymous@")) + ptr; } return name + TJS_W("(") + ttstr(line) + TJS_W(")"); }
/** * サンプル値の取得(新方式) * getVisBuffer(buf, sampleCount, 1, sampleAhead)でサンプルを取得し, * (value/32768)^2の最大値を取得します。(0〜1の実数で返ります) * ※このプロパティを読み出すと暗黙でuseVisBuffer=trueに設定されます */ double getSampleValue() { memset(buf, 0, counts*sizeof(short)); tTJSVariant result; tjs_error r = objthis->FuncCall(0, TJS_W("getVisBuffer"), &hint, &result, 4, params, objthis); if (r != TJS_S_OK) TVPAddLog(ttstr(TJS_W("getVisBuffer failed: "))+ttstr(r)); int cnt = (int)result.AsInteger(); if (cnt > counts || cnt < 0) cnt = counts; // サンプルの二乗中の最大値を返す double max = 0; for (int i=cnt-1;i>=0;i--) { double s = ((double)buf[i]) / +32768.0; s *= s; if (max < s) max = s; } return max; }
//--------------------------------------------------------------------------- static void PushConfigFileOptions(TStringList * options) { if(!options) return; for(int j = 0; j < options->Count; j++) { if(options->Strings[j].c_str()[0] != ';') // unless comment TVPProgramArguments.push_back( TVPParseCommandLineOne(TJS_W("-") + ttstr(options->Strings[j]))); } }
// レイヤのパス名を返す ttstr PSD::pathname(psd::LayerInfo &lay) { ttstr name = ""; psd::LayerInfo *p = lay.parent; while (p) { name = path_layname(*p) + "/" + name; p = p->parent; } return ttstr("root/") + name; }
//--------------------------------------------------------------------------- tTJSBinaryStream * tTVPSusieArchivePlugin::CreateStream(std::wstring localname, unsigned long pos, unsigned long size) { HLOCAL memhandle = NULL; int errorcode = 0xff & GetFile(const_cast<LPSTR>(ttstr(localname).AsNarrowStdString().c_str()), pos, (LPSTR)(void*)&memhandle, 0x0100, (FARPROC)ProgressCallback, 0); if(errorcode || memhandle == NULL) { TVPThrowExceptionMessage(TVPSusiePluginError, ttstr(TJS_W("tTVPSusieArchivePlugin::GetFile failed, errorcode = ")) + ttstr((tjs_int)errorcode)); } tTVPMemoryStream *memstream = new tTVPMemoryStream; void *memblock = NULL; try { memblock = LocalLock(memhandle); if(memblock == NULL) { TVPThrowExceptionMessage(TVPSusiePluginError, ttstr(TJS_W("tTVPSusieArchivePlugin::GetFile failed : invalid memory block."))); } // write to on-memory stream memstream->WriteBuffer(memblock, size); memstream->SetPosition(0); } catch(...) { if(memblock) LocalUnlock(memhandle); LocalFree(memhandle); delete memstream; throw; } if(memblock) LocalUnlock(memhandle); LocalFree(memhandle); return memstream; }