📄 dvdsynth.cpp
字号:
/***********************************************************************
Copyright 2002 Ben Rudiak-Gould.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
or visit <http://www.gnu.org/copyleft/gpl.html>.
***********************************************************************/
#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <shellapi.h>
#include <commctrl.h>
#include <process.h>
#include <time.h>
#include "/p/lib/myvector.h"
#include "/p/lib/mystring.h"
#include "resource.h"
#include "../include/dvdsynth-plugin.h"
/*******************************************************************\
\*******************************************************************/
union Value {
int i;
unsigned u;
const char* s;
};
static inline const char* FormatValue(Value v, char type) {
if (type == 's') {
return v.s;
} else {
switch (type) {
case 'i': case 'd': case 'u': case 'X': case 'c':
{
static char buf[3*sizeof(int)];
static char fmt_str[] = "%_";
fmt_str[1] = type;
wsprintf(buf, fmt_str, v.i);
return buf;
}
default:
return "???";
}
}
}
int Sprint(char* buf, int space, const char* fmt, const char* types, ...) {
if (types == 0) {
types = "sssssssss";
}
int num_types = lstrlen(types);
const char* p = fmt;
char* q = buf;
char* q_end = buf + space - 1;
for (;;) {
if (*p == '%' && *(p+1) >= '1' && *(p+1) <= '9') {
va_list val;
va_start(val, types);
Value value;
int arg_number = *(p+1) - '0';
char type;
for (int i=0; i<arg_number; ++i) {
type = types[i];
if (type == 's') {
value.s = va_arg(val, const char*);
} else {
value.i = va_arg(val, int);
}
}
va_end(val);
const char* insert = FormatValue(value, type);
if (insert == 0) {
insert = "(null)";
}
int insert_len = lstrlen(insert);
memcpy(q, insert, min(insert_len, q_end - q));
q += insert_len;
p += 2;
} else if (*p != 0) {
if (q < q_end) {
*q = *p;
}
++q; ++p;
} else {
break;
}
}
*min(q, q_end) = 0;
return q - buf;
}
/*******************************************************************\
\*******************************************************************/
class PopupMenu : public DvsMenu {
class Callback {
void (*callback)(void*, int);
void* p;
int i;
public:
Callback(void (*_callback)(void*, int), void* _p, int _i) {
callback = _callback; p = _p; i = _i;
}
void Invoke() {
if (callback)
callback(p,i);
}
};
Vector<Callback> callbacks;
Vector<HMENU> menu_stack;
HMENU top_level_popup;
int base_submenu_level;
bool add_separator;
bool menu_empty;
void InternalAddItem(UINT flags, UINT id, LPCTSTR text);
public:
PopupMenu() {
static DvsMenu_vtable vt = {
StaticAddSeparator,
StaticAddItem,
StaticAddDisabledItem,
StaticBeginSubmenu,
StaticEndSubmenu,
};
vtable = &vt;
top_level_popup = CreatePopupMenu();
menu_stack.push_back(top_level_popup);
base_submenu_level = 1;
add_separator = false;
menu_empty = true;
}
HMENU GetPopup() {
return top_level_popup;
}
void InvokeCallback(int index) {
if (index > 0 && index <= callbacks.size()) {
callbacks[index-1].Invoke();
}
}
~PopupMenu() {
DestroyMenu(top_level_popup);
}
// The purpose of the lock/unlock stuff is to prevent buggy plugins
// from screwing up the whole menu structure.
void LockSubmenuLevel() {
base_submenu_level = menu_stack.size();
}
void UnlockSubmenuLevel() {
// assert(menu_stack.size() == base_submenu_level);
while (menu_stack.size() > base_submenu_level) {
EndSubmenu();
}
base_submenu_level = 1;
}
void AddSeparator() {
add_separator = true;
}
void AddItem(const char* text, int checked, void (*callback)(void*, int), void* p, int i) {
callbacks.push_back(Callback(callback, p, i));
InternalAddItem(!!checked*MF_CHECKED, callbacks.size(), text);
}
void AddDisabledItem(const char* text, int checked) {
InternalAddItem(MF_GRAYED + !!checked*MF_CHECKED, (UINT)-1, text);
}
void BeginSubmenu(const char* text, int disabled) {
HMENU submenu = CreatePopupMenu();
InternalAddItem(MF_POPUP + !!disabled*MF_GRAYED, (UINT)submenu, text);
menu_stack.push_back(submenu);
menu_empty = true;
}
void EndSubmenu() {
// assert(menu_stack.size() > base_submenu_level);
if (menu_stack.size() > base_submenu_level) {
if (menu_empty) {
InternalAddItem(MF_GRAYED, 0, "(empty)");
}
menu_stack.pop_back();
add_separator = false;
//menu_empty = false;
}
}
static void StaticAddSeparator(DvsMenu* self) {
reinterpret_cast<PopupMenu*>(self)->AddSeparator();
}
static void StaticAddItem(DvsMenu* self, const char* text, int checked, void (*callback)(void*, int), void* p, int i) {
reinterpret_cast<PopupMenu*>(self)->AddItem(text, checked, callback, p, i);
}
static void StaticAddDisabledItem(DvsMenu* self, const char* text, int checked) {
reinterpret_cast<PopupMenu*>(self)->AddDisabledItem(text, checked);
}
static void StaticBeginSubmenu(DvsMenu* self, const char* text, int disabled) {
reinterpret_cast<PopupMenu*>(self)->BeginSubmenu(text, disabled);
}
static void StaticEndSubmenu(DvsMenu* self) {
reinterpret_cast<PopupMenu*>(self)->EndSubmenu();
}
};
void PopupMenu::InternalAddItem(UINT flags, UINT id, LPCTSTR text) {
if (add_separator && !menu_empty) {
AppendMenu(menu_stack.back(), MF_SEPARATOR, 0, 0);
}
AppendMenu(menu_stack.back(), flags, id, text);
add_separator = false;
menu_empty = false;
}
/*******************************************************************\
\*******************************************************************/
char g_dvdsynth_directory[MAX_PATH+1];
void ExtractDvdsynthDirectory(const char* exe_name) {
char* filepart;
if (GetFullPathName(exe_name, MAX_PATH, g_dvdsynth_directory, &filepart)) {
if (filepart > g_dvdsynth_directory && (filepart[-1] == '\\' || filepart[-1] == '/')) {
filepart[0] = 0;
} else {
filepart[0] = '\\';
filepart[1] = 0;
}
} else {
lstrcpy(g_dvdsynth_directory, ".\\");
}
}
// returns 0 on failure, # bytes copied on success
const char* GetDvdsynthDirectory() {
return g_dvdsynth_directory;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -