diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/util | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/util')
-rw-r--r-- | Src/Wasabi/api/util/savefile.cpp | 228 | ||||
-rw-r--r-- | Src/Wasabi/api/util/savefile.h | 31 | ||||
-rw-r--r-- | Src/Wasabi/api/util/selectfile.cpp | 111 | ||||
-rw-r--r-- | Src/Wasabi/api/util/selectfile.h | 41 | ||||
-rw-r--r-- | Src/Wasabi/api/util/systray.cpp | 93 | ||||
-rw-r--r-- | Src/Wasabi/api/util/systray.h | 23 | ||||
-rw-r--r-- | Src/Wasabi/api/util/varmgr.cpp | 111 | ||||
-rw-r--r-- | Src/Wasabi/api/util/varmgr.h | 17 |
8 files changed, 655 insertions, 0 deletions
diff --git a/Src/Wasabi/api/util/savefile.cpp b/Src/Wasabi/api/util/savefile.cpp new file mode 100644 index 00000000..f7766fa7 --- /dev/null +++ b/Src/Wasabi/api/util/savefile.cpp @@ -0,0 +1,228 @@ +#include "precomp.h" +//NONPORTABLE + +#include <windows.h> +#include <commdlg.h> +#include "savefile.h" + +#include "../bfc/basewnd.h" + +#include "../studio/api.h" +#include "../studio/assert.h" + +#include "../bfc/encodedstr.h" +#include "../studio/services/svc_stringconverter.h" + +SaveFileWnd::SaveFileWnd(const char *ident) : identifier(ident), + force_initial_dir(0) {} + +void SaveFileWnd::setInitialDir(const char *dir, int force) { + initial_dir = dir; + force_initial_dir = force; +} + +int SaveFileWnd::getSaveFile(api_window *parent, const char *ext, const char *suggext) { + int retcode, failed = 0; + if (ext == NULL) return 0; + + if (Std::encodingSupportedByOS(SvcStrCnv::UTF16)) { + int ret = getSaveFileW(parent, ext, suggext); + // If ret returns -1, the service is not available, we will call our own + // OSNative translation failure routines below: + if (ret != -1) { + return ret; + } + } + + char savedir[WA_MAX_PATH]; + Std::getCurDir(savedir, WA_MAX_PATH); + + char filenamebuf[MAX_PATH]=""; + filename = NULL; + + OPENFILENAME ofn; + ofn.lStructSize = sizeof ofn; + ofn.hwndOwner = parent->gethWnd(); + ofn.hInstance = NULL; + ofn.lpstrFilter = ext; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 0; + ofn.lpstrFile = filenamebuf; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + + ofn.lpstrInitialDir = NULL; + const char *initDir8 = NULL; + + // Figure out the initial directory in UTF8 + char dir[WA_MAX_PATH]=""; + String tname; + if (identifier != NULL) { + tname.printf("Recent directories/SaveFile/%s", identifier.getValue()); + if (force_initial_dir) + initial_dir.strncpyTo(dir, sizeof(dir)); + else + WASABI_API_CONFIG->getStringPublic(tname, dir, WA_MAX_PATH, initial_dir); + if (*dir) initDir8 = dir; + } + + // And then convert it when you're done to OSNATIVE. + EncodedStr initDirOSenc; + retcode = initDirOSenc.convertFromUTF8(SvcStrCnv::OSNATIVE, String(initDir8)); + if (retcode == SvcStrCnv::ERROR_UNAVAILABLE) { + failed = 1; + ofn.lpstrInitialDir = initDir8; + } else { + ofn.lpstrInitialDir = static_cast<char *>(initDirOSenc.getEncodedBuffer()); + } + + ofn.lpstrTitle = NULL; + ofn.Flags = OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY; + ofn.nFileOffset = 0; + ofn.nFileExtension = 0; + ofn.lpstrDefExt = suggext; + ofn.lCustData = 0; + ofn.lpfnHook = NULL; + ofn.lpTemplateName = NULL; + api->pushModalWnd(); + int ret = GetSaveFileName(&ofn); + api->popModalWnd(); + + if (failed) { + if (ret) + filename = filenamebuf; + } else { + // Okay, at this point we have the string in OSNATIVE format. + // Now we downconvert everything to UTF8 and pass our information to the engine API's + if (ret) { + EncodedStr bufOSstr(SvcStrCnv::OSNATIVE, filenamebuf, STRLEN(filenamebuf)+1, 0/*no delete*/); + bufOSstr.convertToUTF8(filename); + } + } + + // get new cur dir & save it off + if ((identifier != NULL) && ret) { + char newdir[WA_MAX_PATH]; + Std::getCurDir(newdir, WA_MAX_PATH); + + WASABI_API_CONFIG->setStringPublic(tname, newdir); + } + // put back old one + Std::setCurDir(savedir); + + return ret; +} + +int SaveFileWnd::getSaveFileW(api_window *parent, const char *ext, const char *suggext) { + + // The ultimate top level retrohack. (sigh). + // Test to see if the service is available. If not, return -1. + // The OSNATIVE codepath will include the proper failure handling. + StringConverterEnum myServiceEnum(SvcStrCnv::UTF16); // _ASSUME_ that there is a converter for U16 (we should, but still...) + svc_stringConverter *myConv = myServiceEnum.getFirst(); + if (myConv != NULL) { + myServiceEnum.release(myConv); + } else { + return -1; + } + + char savedir[WA_MAX_PATH]; + Std::getCurDir(savedir, WA_MAX_PATH); + + WCHAR filenamebufW[MAX_PATH] = L""; + filename = NULL; + + // convert multi const char* ext to U16 (Ascii7 assumptive) + int thisz = 0, lastz = 0; + const char *px; + WCHAR *pr, *ext16 = static_cast<WCHAR *>(MALLOC(WA_MAX_PATH)); + for (px = ext, pr = ext16; *px | (lastz); px++, pr++) { + lastz = (thisz)?1:0; + *pr = (*px) & 0xFF; + thisz = (*pr)?1:0; + } + *pr = *px; // the last 0 + + EncodedStr suggext16; + suggext16.convertFromUTF8(SvcStrCnv::UTF16, String(suggext)); + + OPENFILENAMEW ofnW; + ofnW.lStructSize = sizeof ofnW; + ofnW.hwndOwner = parent->gethWnd(); + ofnW.hInstance = NULL; + ofnW.lpstrFilter = ext16; + ofnW.lpstrCustomFilter = NULL; + ofnW.nMaxCustFilter = 0; + ofnW.nFilterIndex = 0; + ofnW.lpstrFile = filenamebufW; + ofnW.nMaxFile = MAX_PATH; + ofnW.lpstrFileTitle = NULL; + ofnW.nMaxFileTitle = 0; + + ofnW.lpstrInitialDir = NULL; + + char dir[WA_MAX_PATH]=""; + String tname; + + // Figure out the initial directory in UTF8 + const char *initDir8 = NULL; + if (identifier != NULL) { + tname.printf("Recent directories/SaveFile/%s", identifier.getValue()); + if (force_initial_dir) + initial_dir.strncpyTo(dir, sizeof(dir)); + else + WASABI_API_CONFIG->getStringPublic(tname, dir, WA_MAX_PATH, ""); + if (*dir) initDir8 = dir; + } + + // And then convert it when you're done to UTF16. + WCHAR *initDir16 = NULL; + EncodedStr initDir16enc; + if (initDir8 != NULL) { + int written = initDir16enc.convertFromUTF8(SvcStrCnv::UTF16, String(initDir8)); + if (written > 0) { + initDir16 = static_cast<WCHAR *>(initDir16enc.getEncodedBuffer()); + } else { + return -1; + } + } + + // And then stuff it here. Phew! + ofnW.lpstrInitialDir = initDir16; + + ofnW.lpstrTitle = NULL; + ofnW.Flags = OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY; + ofnW.nFileOffset = 0; + ofnW.nFileExtension = 0; + ofnW.lpstrDefExt = static_cast<WCHAR *>(suggext16.getEncodedBuffer()); + ofnW.lCustData = 0; + ofnW.lpfnHook = NULL; + ofnW.lpTemplateName = NULL; + api->pushModalWnd(); + int ret = GetSaveFileNameW(&ofnW); + api->popModalWnd(); + + // Okay, at this point we have the string in UTF16 widechar format. + // Now we downconvert everything to UTF8 and pass our information to the engine API's + if (ret) { + EncodedStr buf16str(SvcStrCnv::UTF16, filenamebufW, (WSTRLEN(filenamebufW)+1)*2, 0/*no delete*/); + buf16str.convertToUTF8(filename); + } + + // get new cur dir & save it off + if ((identifier != NULL) && ret) { + char newdir[WA_MAX_PATH]; + Std::getCurDir(newdir, WA_MAX_PATH); + + WASABI_API_CONFIG->setStringPublic(tname, newdir); + } + + FREE(ext16); + + // put back old one + Std::setCurDir(savedir); + + return ret; +} diff --git a/Src/Wasabi/api/util/savefile.h b/Src/Wasabi/api/util/savefile.h new file mode 100644 index 00000000..3df65287 --- /dev/null +++ b/Src/Wasabi/api/util/savefile.h @@ -0,0 +1,31 @@ +#ifndef _SAVEFILE_H +#define _SAVEFILE_H + +#include "common.h" + +#include "modal.h" +#include "../bfc/string.h" + +class ifc_window; + +class SaveFileWnd : public Modal { +public: + SaveFileWnd(const char *ident=NULL); +/** + Sets the initial directory for the picker. If force is FALSE, this directory + will only be used if no previous directory has been saved for the indent. + If TRUE, it will always be used. +*/ + void setInitialDir(const char *dir, int force=FALSE); + int getSaveFile(ifc_window *parent, const char *ext, const char *suggext); + int getSaveFileW(ifc_window *parent, const char *ext, const char *suggext); + const char *getFilename() { return filename; } + +private: + String identifier; + String filename; + String initial_dir; + int force_initial_dir; +}; + +#endif diff --git a/Src/Wasabi/api/util/selectfile.cpp b/Src/Wasabi/api/util/selectfile.cpp new file mode 100644 index 00000000..08e70314 --- /dev/null +++ b/Src/Wasabi/api/util/selectfile.cpp @@ -0,0 +1,111 @@ +#include <precomp.h> + +#include "selectfile.h" + +#include <api/wnd/popup.h> +#include <api/service/svcs/svc_filesel.h> + +SelectFile::SelectFile(ifc_window *parent, const wchar_t *menu_prefix, const wchar_t *menu_suffix) + : parentWnd(parent), + prefix_str(menu_prefix), + suffix_str(menu_suffix) +{ + svc = NULL; + ASSERT(parent != NULL); + xpos = ypos = 0; + pos_set = 0; +} + +SelectFile::~SelectFile() +{ + if (svc) WASABI_API_SVC->service_release(svc); + types.deleteAll(); +} + +void SelectFile::setDefaultDir(const wchar_t *dir) +{ + default_dir = dir; +} + +const wchar_t *SelectFile::getDirectory() +{ + if (svc) return svc->getDirectory(); + return NULL; +} + +void SelectFile::setIdent(const wchar_t *id) +{ + ident = id; +} + +void SelectFile::setPopPosition(int x, int y) +{ + xpos = x; + ypos = y; + pos_set = 1; +} + +int SelectFile::runSelector(const wchar_t *type, int allow_multiple, const wchar_t *extlist) +{ + if (svc) WASABI_API_SVC->service_release(svc); svc = NULL; + types.deleteAll(); + if (type == NULL) + { + int pos = 0; + for (;;) + { + waServiceFactory *wasvc = WASABI_API_SVC->service_enumService(WaSvc::FILESELECTOR, pos++); + if (wasvc == NULL) break; + svc_fileSelector *sfs = castService<svc_fileSelector>(wasvc); + const wchar_t *pref = sfs->getPrefix(); + if (pref != NULL) + types.addItem(new StringW(pref)); + WASABI_API_SVC->service_release(sfs); + } + if (types.getNumItems() <= 0) return 0; // none?! + + PopupMenu *pop = new PopupMenu(parentWnd); + for (int i = 0; i < types.getNumItems(); i++) + { + StringW str; + str += prefix_str; + str += types[i]->getValue(); + str += suffix_str; + pop->addCommand(str, i); + } + int cmd = pos_set ? pop->popAtXY(xpos, ypos) : pop->popAtMouse(); + StringW *s = types[cmd]; + if (s == NULL) return 0; + type = *s; + } + ASSERT(type != NULL); + + saved_type = type; + + svc = FileSelectorEnum(type).getFirst(); + ASSERT(svc != NULL); // we just enumed it + if (extlist != NULL) svc->setExtList(extlist); + //FUCKO : need to set open vs. save as + WASABI_API_WND->pushModalWnd(); + int r = svc->runSelector(parentWnd, FileSel::OPEN, allow_multiple, + ident.isempty() ? type : ident.getValue(), + default_dir); + WASABI_API_WND->popModalWnd(); + ASSERT(svc != NULL); // we just enumed it + return r; +} + +const wchar_t *SelectFile::getType() +{ + return saved_type; +} + +int SelectFile::getNumFiles() +{ + return svc ? svc->getNumFilesSelected() : 0; +} + +const wchar_t *SelectFile::enumFilename(int n) +{ + return svc ? svc->enumFilename(n) : NULL; +} diff --git a/Src/Wasabi/api/util/selectfile.h b/Src/Wasabi/api/util/selectfile.h new file mode 100644 index 00000000..5dc378a7 --- /dev/null +++ b/Src/Wasabi/api/util/selectfile.h @@ -0,0 +1,41 @@ +#ifndef _SELECTFILE_H +#define _SELECTFILE_H + +#include <bfc/common.h> + +#include <bfc/ptrlist.h> +#include <bfc/string/StringW.h> + +class svc_fileSelector; +class ifc_window; + +class SelectFile +{ +public: + SelectFile(ifc_window *parent, const wchar_t *menu_prefix = NULL, const wchar_t *menu_suffix = NULL); + ~SelectFile(); + + void setDefaultDir(const wchar_t *dir); // default dir to use + const wchar_t *getDirectory(); // return base directory after ok clicked + void setIdent(const wchar_t *id); // unless you saved one under this id + + void setPopPosition(int x, int y); // in screen coords + + int runSelector(const wchar_t *type = NULL, int allow_multiple = FALSE, const wchar_t *extlist = NULL); // if NULL, generate popup + const wchar_t *getType(); + + int getNumFiles(); + const wchar_t *enumFilename(int n); + +private: + int xpos, ypos; + int pos_set; + ifc_window *parentWnd; + svc_fileSelector *svc; + PtrList<StringW> types; + StringW prefix_str, suffix_str; + StringW default_dir, ident; + StringW saved_type; +}; + +#endif diff --git a/Src/Wasabi/api/util/systray.cpp b/Src/Wasabi/api/util/systray.cpp new file mode 100644 index 00000000..921d21d7 --- /dev/null +++ b/Src/Wasabi/api/util/systray.cpp @@ -0,0 +1,93 @@ +#include <precomp.h> +#ifdef WIN32 +#include <windows.h> +#include <shellapi.h> +#endif +#include "systray.h" +#include <bfc/assert.h> +#include <bfc/wasabi_std.h> + +Systray::Systray(HWND wnd, int uid, int msg, HICON smallicon) +{ + id = uid; + hwnd = wnd; + message = msg; + icon = smallicon; + /*int r = */addIcon(); + // always asserts with desktop with no systray support (litestep, WINE, etc...) + // ASSERT(r == TRUE); +} + +Systray::~Systray() +{ + /*int r = */deleteIcon(); + // always asserts with desktop with no systray support (litestep, WINE, etc...) + // ASSERT(r == TRUE); +} + +void Systray::setTip(const wchar_t *_tip) +{ + tip = _tip; + tip.trunc(64); + if (!tip.isempty()) + { + /*int r = */setTip(); + // always asserts with desktop with no systray support (litestep, WINE, etc...) + // ASSERT(r == TRUE); + } +} + +bool Systray::addIcon() +{ +#ifdef WIN32 + NOTIFYICONDATAW tnid = {0}; + tnid.cbSize = sizeof(NOTIFYICONDATAW); + tnid.uID = id; + tnid.hWnd = hwnd; + tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + tnid.uCallbackMessage = message; + tnid.hIcon = icon; + if (tip) + WCSCPYN(tnid.szTip, tip, sizeof(tnid.szTip)/sizeof(wchar_t)); + + return !!Shell_NotifyIconW(NIM_ADD, &tnid); +#else + DebugString("portme Systray::addIcon\n"); + return 1; +#endif +} + +bool Systray::setTip() +{ +#ifdef WIN32 + NOTIFYICONDATAW tnid = {0}; + tnid.cbSize = sizeof(NOTIFYICONDATAW); + tnid.uFlags = NIF_TIP; + tnid.uID = id; + tnid.hWnd = hwnd; + if (tip) + WCSCPYN(tnid.szTip, tip, sizeof(tnid.szTip)/sizeof(wchar_t)); + + return !!Shell_NotifyIconW(NIM_MODIFY, &tnid); +#else + DebugString("portme Systray::setTip\n"); + return 1; +#endif +} + + +bool Systray::deleteIcon() +{ +#ifdef WIN32 + NOTIFYICONDATA tnid = {0}; + tnid.cbSize = sizeof(NOTIFYICONDATAW); + tnid.hWnd = hwnd; + tnid.uID = id; + + return !!Shell_NotifyIcon(NIM_DELETE, &tnid); +#else + DebugString("portme Systray::deleteIcon\n"); + return 1; +#endif +} + diff --git a/Src/Wasabi/api/util/systray.h b/Src/Wasabi/api/util/systray.h new file mode 100644 index 00000000..3e4f6d93 --- /dev/null +++ b/Src/Wasabi/api/util/systray.h @@ -0,0 +1,23 @@ +#ifndef __SYSTRAY_H +#define __SYSTRAY_H + +#include <bfc/string/StringW.h> + +class Systray +{ +public: + Systray(HWND wnd, int uid, int msg, HICON smallicon); + ~Systray(); + void setTip(const wchar_t *tip); +private: + bool addIcon(); + bool deleteIcon(); + bool setTip(); + int id, message; + HWND hwnd; + HICON icon; + StringW tip; +}; + + +#endif diff --git a/Src/Wasabi/api/util/varmgr.cpp b/Src/Wasabi/api/util/varmgr.cpp new file mode 100644 index 00000000..d8a4e54f --- /dev/null +++ b/Src/Wasabi/api/util/varmgr.cpp @@ -0,0 +1,111 @@ +#include <precomp.h> +#include "varmgr.h" +#include <api/script/objects/guiobj.h> +#include <api/skin/widgets/group.h> +#include <api/skin/skinparse.h> +#include <api/wac/wac.h> +#include <bfc/parse/pathparse.h> + +// for now only translates special text like :componentname etc but in the future +// this will translate xml variables + +StringW *PublicVarManager::translate_nocontext(const wchar_t *str) +{ + return translate(str, NULL, NULL); +} + +//Martin> TODO: Split this method for <include/>, <bitmap/>,... and <text/> objects +StringW *PublicVarManager::translate(const wchar_t *str, GuiObject *o, Container *c) +{ + if (str == NULL) return NULL; + //test if @ or : is present + { + const wchar_t *p=str; + int found=0; + while(p && *p && !found) { + wchar_t a=*p++; + if(a==':' || a=='@') found=1; + } + if(!found) + return NULL; + } + + // lone> this needs to be a service, but it may slow shit down if we enum too often since this is called for all xml values, so carfull when you add this, lone + #ifdef CUSTOM_VARS + const wchar_t *rpl=NULL; + CUSTOM_VARS(str, rpl); + if (rpl != NULL) return new StringW(rpl); + #endif + + const wchar_t *skinname = NULL; + if (WASABI_API_SKIN != NULL) + skinname=WASABI_API_SKIN->getSkinName(); + + static int in=0; + if (in) + return NULL; + in = 1; + + StringW *ret = new StringW(str); + + if (skinname) + { + StringW colorThemePath = WASABI_API_APP->path_getAppPath(); + colorThemePath.AppendPath(L"ColorThemes"); + colorThemePath.AppendPath(skinname); + + ret->replace(L"@COLORTHEMESPATH@", colorThemePath); + ret->replace(L"@SKINPATH@", WASABI_API_SKIN->getSkinPath()); + ret->replace(L"@SKINSPATH@", WASABI_API_SKIN->getSkinsPath()); + ret->replace(L"@APPDATAPATH@", WASABI_API_APP->path_getUserSettingsPath()); + //ret->replace(L"@DEFAULTSKINPATH@", StringPathCombine(WASABI_API_SKIN->getSkinsPath(), L"Default")); //Martin> doesn't exist in winamp5, so cut to speed loading + ret->replace(L"@WINAMPPATH@", StringPrintfW(L"%s\\", WASABI_API_APP->path_getAppPath())); + } +#ifdef WASABI_COMPILE_COMPONENTS + ret->replace("@WACDATAPATH@", WASABI_API_APP->path_getComponentDataPath()); +#endif + + if (!o && !c) { in = 0; return ret; } + +//CUT wtf? if (!str) return NULL; + + const wchar_t *containerid = NULL; + const wchar_t *groupid = NULL; + const wchar_t *componentName = NULL; + + if (o && o->guiobject_getParentGroup()) + { + groupid = o->guiobject_getParentGroup()->getGuiObject()->guiobject_getId(); + if (o->guiobject_getParentGroup()->getParentContainer()) + { + containerid = o->guiobject_getParentGroup()->getParentContainer()->getId(); + componentName = o->guiobject_getParentGroup()->getParentContainer()->getName(); + } + } + else { + groupid = SkinParser::getCurrentGroupId(); + if (c) { + containerid = c->getId(); + componentName = /*c->hasComponent() ? api->getComponentName(c->getGUID()) : */c->getName(); + } else { + containerid = SkinParser::getCurrentContainerId(); + componentName = NULL; + } + } + + if (componentName != NULL) { + ret->replace(L":componentname", componentName); // DEPRECATED + ret->replace(L"@COMPONENTNAME@", componentName); + } + if (containerid != NULL) { + ret->replace(L":containerid", containerid); // DEPRECATED + ret->replace(L"@CONTAINERID@", containerid); + } + if (groupid != NULL) { + ret->replace(L":groupid", groupid); // DEPRECATED + ret->replace(L"@GROUPID@",groupid); + } + + in = 0; + return ret; +} diff --git a/Src/Wasabi/api/util/varmgr.h b/Src/Wasabi/api/util/varmgr.h new file mode 100644 index 00000000..8759cddf --- /dev/null +++ b/Src/Wasabi/api/util/varmgr.h @@ -0,0 +1,17 @@ +#ifndef __VARMGR_H +#define __VARMGR_H + +#include <bfc/wasabi_std.h> + +class GuiObject; +class Container; +class WaComponent; + + +class PublicVarManager { +public: + static StringW *translate_nocontext(const wchar_t *str); + static StringW *translate(const wchar_t *str, GuiObject *o=NULL, Container *c=NULL); +}; + +#endif |