添加文件
This commit is contained in:
parent
bdcb0b66ea
commit
73a5ea2cce
|
@ -0,0 +1,886 @@
|
|||
// DlgInput.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "hgjson.h"
|
||||
#include "DlgTwain.h"
|
||||
#include "afxdialogex.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <file/file_util.h>
|
||||
#include <coding/coding.h>
|
||||
|
||||
|
||||
namespace util
|
||||
{
|
||||
enum
|
||||
{
|
||||
BOM_ANSI,
|
||||
BOM_UTF8,
|
||||
BOM_UNICODE,
|
||||
};
|
||||
static INTER_MODULE_CALLBACK(got_str)
|
||||
{
|
||||
*(std::string*)param += std::string(data, len);
|
||||
|
||||
return inter_module_data::SET_RESULT_CONTINUE;
|
||||
}
|
||||
static INTER_MODULE_CALLBACK(got_wstr)
|
||||
{
|
||||
*(std::wstring*)param += std::wstring((const wchar_t*)data, len / 2);
|
||||
|
||||
return inter_module_data::SET_RESULT_CONTINUE;
|
||||
}
|
||||
|
||||
static bool is_space(wchar_t ch)
|
||||
{
|
||||
return ch == L' ' || ch == L'\t' || ch == L'\r' || ch == L'\n';
|
||||
}
|
||||
static bool is_var_char(wchar_t ch, bool allow_num)
|
||||
{
|
||||
return ch == L'_' ||
|
||||
(ch >= L'0' && ch <= L'9' && allow_num) ||
|
||||
(ch >= L'a' && ch <= L'z') ||
|
||||
(ch >= L'A' && ch <= L'Z');
|
||||
}
|
||||
static bool skip_space(const wchar_t** str)
|
||||
{
|
||||
const wchar_t* bgn = *str;
|
||||
|
||||
while (is_space(str[0][0]))
|
||||
(*str)++;
|
||||
|
||||
return *str > bgn;
|
||||
}
|
||||
static void to_line_head(const wchar_t** str)
|
||||
{
|
||||
while (str[0][0] != L'\n')
|
||||
(*str)--;
|
||||
}
|
||||
static void erase_multiline_comment(std::wstring& cont)
|
||||
{
|
||||
for (int i = 0; i < cont.length(); ++i)
|
||||
{
|
||||
if (cont[i] == L'/')
|
||||
{
|
||||
if (cont[i + 1] == L'/')
|
||||
{
|
||||
std::wstring val(L"");
|
||||
int next = 0;
|
||||
coding_util::pick_line(cont.c_str() + i, got_wstr, &val, &next);
|
||||
i += next;
|
||||
}
|
||||
else if (cont[i + 1] == L'*')
|
||||
{
|
||||
size_t pos = cont.find(L"*/", i + 2);
|
||||
if (pos++ == std::wstring::npos)
|
||||
{
|
||||
cont.erase(i);
|
||||
break;
|
||||
}
|
||||
else
|
||||
cont.erase(i, pos - i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static void transform_hz(std::wstring& hz)
|
||||
{
|
||||
int prev = -1;
|
||||
std::string inner("");
|
||||
for (int i = 0; i < hz.length() - 3; ++i)
|
||||
{
|
||||
if (hz[i] == L'\\')
|
||||
{
|
||||
if (hz[i + 1] == L'u')
|
||||
{
|
||||
|
||||
}
|
||||
else if (hz[i + 1] == L'x')
|
||||
{
|
||||
|
||||
}
|
||||
else if (hz[i + 1] >= L'0' && hz[i + 1] <= L'7')
|
||||
{
|
||||
if (hz[i + 2] >= L'0' && hz[i + 2] <= L'7' &&
|
||||
hz[i + 3] >= L'0' && hz[i + 3] <= L'7')
|
||||
{
|
||||
if (prev == -1)
|
||||
prev = i;
|
||||
char ch = (hz[i + 1] - L'0') * 64 + (hz[i + 2] - L'0') * 8 + hz[i + 3] - L'0';
|
||||
inner.append(1, ch);
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inner.length())
|
||||
{
|
||||
std::wstring trans(L"");
|
||||
coding_util::utf8_2_unicode(inner.c_str(), got_wstr, &trans);
|
||||
hz.replace(prev, i - prev, trans);
|
||||
i = prev + trans.length();
|
||||
}
|
||||
prev = -1;
|
||||
inner = "";
|
||||
}
|
||||
}
|
||||
if (inner.length())
|
||||
{
|
||||
std::wstring trans(L"");
|
||||
coding_util::utf8_2_unicode(inner.c_str(), got_wstr, &trans);
|
||||
hz.replace(prev, hz.length() - prev, trans);
|
||||
}
|
||||
}
|
||||
static std::wstring now(void)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
tm* pt = localtime(&t);
|
||||
wchar_t buf[40] = { 0 };
|
||||
|
||||
swprintf_s(buf, _countof(buf) - 1, L"%04d-%02d-%02d %02d:%02d:%02d",
|
||||
pt->tm_year + 1900, pt->tm_mon + 1, pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec);
|
||||
|
||||
return buf;
|
||||
}
|
||||
static std::wstring get_text(HWND wnd)
|
||||
{
|
||||
int len = GetWindowTextLengthW(wnd);
|
||||
wchar_t * buf = new wchar_t[len + 128];
|
||||
std::wstring ret(L"");
|
||||
|
||||
len = ::GetWindowTextW(wnd, buf, len + 20);
|
||||
buf[len] = 0;
|
||||
ret = buf;
|
||||
delete[] buf;
|
||||
|
||||
return std::move(ret);
|
||||
}
|
||||
static void append_log(const wchar_t* log, HWND edit, bool scroll_last)
|
||||
{
|
||||
std::wstring text(std::move(get_text(edit))), cur(now() + L": "), str(log), space(L"");
|
||||
size_t pos = str.find(L"\r\n");
|
||||
|
||||
space.append(cur.length() * 2, L' ');
|
||||
while (pos != std::wstring::npos && pos < str.length() - 2)
|
||||
{
|
||||
str.insert(pos + 2, space);
|
||||
pos = str.find(L"\r\n", pos + space.length() + 2);
|
||||
}
|
||||
text += cur + str;
|
||||
::SetWindowTextW(edit, text.c_str());
|
||||
if (scroll_last)
|
||||
::SendMessage(edit, EM_LINESCROLL, 0, ::SendMessageW(edit, EM_GETLINECOUNT, 0, 0));
|
||||
else
|
||||
::SendMessageW(edit, EM_LINESCROLL, 0, (LPARAM)::GetPropW(edit, L"stop_line"));
|
||||
}
|
||||
static std::wstring load_file(const wchar_t* file, int *bom)
|
||||
{
|
||||
std::wstring cont(L"");
|
||||
std::string raw("");
|
||||
|
||||
file_util::load_file(file, got_str, &raw);
|
||||
if (raw.empty())
|
||||
return false;
|
||||
if (bom)
|
||||
*bom = coding_util::bom::is_unicode(raw.c_str(), NULL) ? BOM_UNICODE : (coding_util::bom::is_utf8(raw.c_str()) ? BOM_UTF8 : BOM_ANSI);
|
||||
coding_util::bom::to_unicode(raw.c_str(), raw.length(), got_wstr, &cont);
|
||||
|
||||
return std::move(cont);
|
||||
}
|
||||
static bool save_file(const wchar_t* file, const wchar_t* cont, int bom, std::wstring* bak = NULL)
|
||||
{
|
||||
std::string raw("");
|
||||
if (bom == BOM_UNICODE)
|
||||
coding_util::bom::from_unicode(cont, lstrlenW(cont) * 2, got_str, &raw);
|
||||
else if (bom == BOM_UTF8)
|
||||
{
|
||||
std::string utf8("");
|
||||
coding_util::unicode_2_utf8(cont, got_str, &utf8);
|
||||
coding_util::bom::from_utf8(utf8.c_str(), utf8.length(), got_str, &raw);
|
||||
}
|
||||
else
|
||||
coding_util::unicode_2_ansi(cont, got_str, &raw);
|
||||
|
||||
if (bak)
|
||||
{
|
||||
*bak = file;
|
||||
*bak += L".bak";
|
||||
file_util::force_copy_file(file, bak->c_str());
|
||||
}
|
||||
|
||||
return file_util::save_2_file(raw.c_str(), raw.length(), file) == 0;
|
||||
}
|
||||
std::string u2a(const wchar_t* u, bool to_utf8 = false)
|
||||
{
|
||||
std::string a("");
|
||||
|
||||
if (to_utf8)
|
||||
coding_util::unicode_2_utf8(u, got_str, &a);
|
||||
else
|
||||
coding_util::unicode_2_ansi(u, got_str, &a);
|
||||
|
||||
return std::move(a);
|
||||
}
|
||||
std::wstring a2u(const char* a, bool from_utf8 = false)
|
||||
{
|
||||
std::wstring u(L"");
|
||||
|
||||
if (from_utf8)
|
||||
coding_util::utf8_2_unicode(a, got_wstr, &u);
|
||||
else
|
||||
coding_util::ansi_2_unicode(a, got_wstr, &u);
|
||||
|
||||
return std::move(u);
|
||||
}
|
||||
|
||||
static std::wstring get_sane_opt_title(const wchar_t* key, const std::wstring& cont)
|
||||
{
|
||||
size_t pos = cont.find(key);
|
||||
std::wstring title(L"");
|
||||
|
||||
while (pos != std::wstring::npos)
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
int check = pos - 1;
|
||||
if (cont[check] == L' ' || cont[check] == L'\t')
|
||||
{
|
||||
const wchar_t* l = cont.c_str() + check;
|
||||
to_line_head(&l);
|
||||
skip_space(&l);
|
||||
if (wcsstr(l, L"#define") == l)
|
||||
{
|
||||
l += 7;
|
||||
skip_space(&l);
|
||||
if (wcsstr(l, key) == l)
|
||||
{
|
||||
l += lstrlenW(key);
|
||||
if (skip_space(&l) && *l++ == L'\"')
|
||||
{
|
||||
while (*l != L'\r' && *l != L'\n' && *l != L'\"' && *l != 0)
|
||||
title.append(1, *l++);
|
||||
transform_hz(title);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pos += lstrlenW(key);
|
||||
pos = cont.find(key, pos);
|
||||
}
|
||||
|
||||
return std::move(title);
|
||||
}
|
||||
static void get_sane_opts(const wchar_t* file, std::vector<SANEOPT>& opts)
|
||||
{
|
||||
std::wstring tf(file), name(L"\r\n"), title(L"\r\n")
|
||||
, pre_n(L"SANE_STD_OPT_NAME_"), pre_t(L"OPTION_TITLE_"), define(L"#define")
|
||||
, line(L""), val(L"");
|
||||
std::string bom("");
|
||||
SANEOPT opt;
|
||||
int off = 0, next = 0;
|
||||
|
||||
STR_PARENT_FOLDER(tf);
|
||||
tf += L"\\sane_option_definitions.h";
|
||||
STR_TO_ABSOLUTE_PATH(tf);
|
||||
|
||||
file_util::load_file(file, got_str, &bom);
|
||||
if (bom.empty())
|
||||
return;
|
||||
coding_util::bom::to_unicode(bom.c_str(), bom.length(), got_wstr, &name);
|
||||
erase_multiline_comment(name);
|
||||
|
||||
bom = "";
|
||||
file_util::load_file(tf.c_str(), got_str, &bom);
|
||||
if (bom.empty())
|
||||
return;
|
||||
coding_util::bom::to_unicode(bom.c_str(), bom.length(), got_wstr, &title);
|
||||
bom = "";
|
||||
erase_multiline_comment(title);
|
||||
|
||||
// search ...
|
||||
coding_util::pick_line(name.c_str(), got_wstr, &line, &next);
|
||||
while (line.length() || next)
|
||||
{
|
||||
size_t pos = line.find(define);
|
||||
if (pos == 0 && line.length() > define.length() && is_space(line[define.length()]))
|
||||
{
|
||||
const wchar_t* str = line.c_str() + define.length(), * bgn = NULL;;
|
||||
util::skip_space(&str);
|
||||
if (wcsstr(str, pre_n.c_str()) == str)
|
||||
{
|
||||
bgn = str;
|
||||
str += pre_n.length();
|
||||
while (is_var_char(*str, true))
|
||||
str++;
|
||||
opt.name_key = std::wstring(bgn, str - bgn);
|
||||
if (util::skip_space(&str) && *str++ == L'\"')
|
||||
{
|
||||
bgn = str;
|
||||
while (*str != L'\"')
|
||||
str++;
|
||||
opt.name = std::wstring(bgn, str - bgn);
|
||||
str++;
|
||||
util::skip_space(&str);
|
||||
if (wcsstr(str, L"//") == str)
|
||||
{
|
||||
str += 2;
|
||||
util::skip_space(&str);
|
||||
if (wcsstr(str, pre_t.c_str()) == str)
|
||||
{
|
||||
bgn = str;
|
||||
str += pre_t.length();
|
||||
while (is_var_char(*str, true))
|
||||
str++;
|
||||
opt.title_key = std::wstring(bgn, str - bgn);
|
||||
opt.title = std::move(get_sane_opt_title(opt.title_key.c_str(), title));
|
||||
opts.push_back(opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
off += next;
|
||||
line = L"";
|
||||
coding_util::pick_line(name.c_str() + off, got_wstr, &line, &next);
|
||||
}
|
||||
}
|
||||
|
||||
static bool pick_option_id_function(std::wstring& code, int* off = NULL, const wchar_t* api_decl = L"scanner::init_options_id(void)", const wchar_t* ret = L"int")
|
||||
{
|
||||
std::wstring api(api_decl);
|
||||
size_t pos = code.find(api);
|
||||
const wchar_t* l = NULL;
|
||||
|
||||
while (pos != std::wstring::npos)
|
||||
{
|
||||
l = code.c_str() + pos;
|
||||
to_line_head(&l);
|
||||
skip_space(&l);
|
||||
if (wcsstr(l, ret) == l)
|
||||
{
|
||||
l += lstrlenW(ret);
|
||||
if (skip_space(&l))
|
||||
{
|
||||
if (wcsstr(l, api.c_str()) == l)
|
||||
{
|
||||
int bgn = 0, end = 0;
|
||||
|
||||
coding_util::pick_value(l, L"{", L"}", &bgn, &end);
|
||||
if (end > bgn)
|
||||
{
|
||||
api = std::wstring(l + bgn, end - bgn + 1);
|
||||
if (off)
|
||||
*off = l + bgn - code.c_str();
|
||||
code = std::move(api);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pos += api.length();
|
||||
pos = code.find(api, pos);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static bool pick_twain_ex_enum(std::wstring& code, int* start = NULL)
|
||||
{
|
||||
// enum CapTypeEx : unsigned short {
|
||||
size_t pos = code.find(L"enum");
|
||||
|
||||
while (pos != std::wstring::npos)
|
||||
{
|
||||
const wchar_t* l = code.c_str() + pos;
|
||||
to_line_head(&l);
|
||||
skip_space(&l);
|
||||
if (wcsstr(l, L"enum") == l)
|
||||
{
|
||||
l += 4;
|
||||
if (skip_space(&l))
|
||||
{
|
||||
if (wcsstr(l, L"CapTypeEx") == l)
|
||||
{
|
||||
int bgn = 0, end = 0;
|
||||
coding_util::pick_value(l, L"{", L"}", &bgn, &end);
|
||||
if (start)
|
||||
*start = l + bgn - code.c_str();
|
||||
code = std::move(std::wstring(l + bgn, end - bgn + 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
pos = code.find(L"enum", pos + 4);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static bool get_twain_id(const std::wstring& idtext, std::vector<OPTUSED>& used)
|
||||
{
|
||||
std::wstring pre(L"CAP_EX_SANE_"), line(L""), key(L"");
|
||||
OPTUSED ou;
|
||||
int off = 0, next = 0, id = 0x8801;
|
||||
|
||||
coding_util::pick_line(idtext.c_str(), got_wstr, &line, &next);
|
||||
while (!line.empty() || next)
|
||||
{
|
||||
const wchar_t* bgn = line.c_str(), * l = bgn;
|
||||
skip_space(&l);
|
||||
if (wcsstr(l, pre.c_str()) == l)
|
||||
{
|
||||
l += pre.length();
|
||||
bgn = l;
|
||||
while (is_var_char(*l, true))
|
||||
l++;
|
||||
key = std::wstring(bgn, l - bgn);
|
||||
ou.id_key = "";
|
||||
coding_util::unicode_2_ansi(key.c_str(), got_str, &ou.id_key);
|
||||
ou.id = id++;
|
||||
used.push_back(ou);
|
||||
}
|
||||
|
||||
off += next;
|
||||
line.clear();
|
||||
coding_util::pick_line(idtext.c_str() + off, got_wstr, &line, &next);
|
||||
}
|
||||
std::sort(used.begin(), used.end());
|
||||
|
||||
return true;
|
||||
}
|
||||
static void get_used_opts(const wchar_t* file, std::vector<OPTUSED>& used)
|
||||
{
|
||||
std::wstring key(L""), id(L""), idf(file), line(L""), pre_nk(L"SANE_STD_OPT_NAME_"), pre_ik(L"CAP_EX_SANE_"), setoid(L"SET_OPT_ID(");
|
||||
std::string bom("");
|
||||
OPTUSED ou;
|
||||
int off = 0, next = 0;
|
||||
|
||||
STR_PARENT_FOLDER(idf);
|
||||
idf += L"\\..\\..\\code_twain\\twain\\twain\\huagaods.cpp";
|
||||
STR_TO_ABSOLUTE_PATH(idf);
|
||||
|
||||
file_util::load_file(file, got_str, &bom);
|
||||
if (bom.empty())
|
||||
return;
|
||||
coding_util::bom::to_unicode(bom.c_str(), bom.length(), got_wstr, &key);
|
||||
erase_multiline_comment(key);
|
||||
|
||||
bom = "";
|
||||
file_util::load_file(idf.c_str(), got_str, &bom);
|
||||
if (bom.empty())
|
||||
return;
|
||||
coding_util::bom::to_unicode(bom.c_str(), bom.length(), got_wstr, &id);
|
||||
erase_multiline_comment(id);
|
||||
get_twain_id(id, used);
|
||||
|
||||
if (!pick_option_id_function(key) || !pick_twain_ex_enum(id))
|
||||
return;
|
||||
|
||||
bom = "";
|
||||
coding_util::pick_line(key.c_str(), got_wstr, &line, &next);
|
||||
while (!line.empty() || next > 0)
|
||||
{
|
||||
const wchar_t* l = line.c_str(), * bgn = NULL;
|
||||
skip_space(&l);
|
||||
if (wcsstr(l, L"else") == l)
|
||||
{
|
||||
l += 4;
|
||||
skip_space(&l);
|
||||
}
|
||||
if (wcsstr(l, setoid.c_str()) == l)
|
||||
{
|
||||
l += setoid.length();
|
||||
bgn = l;
|
||||
if (is_var_char(*l++, false))
|
||||
{
|
||||
while (is_var_char(*l, true))
|
||||
l++;
|
||||
ou.id_key = "";
|
||||
coding_util::unicode_2_ansi(std::wstring(bgn, l - bgn).c_str(), got_str, &ou.id_key);
|
||||
skip_space(&l);
|
||||
if (*l++ == L',')
|
||||
{
|
||||
skip_space(&l);
|
||||
bgn = l;
|
||||
if (is_var_char(*l++, false))
|
||||
{
|
||||
while (is_var_char(*l, true))
|
||||
l++;
|
||||
ou.name_key = std::wstring(bgn, l - bgn);
|
||||
|
||||
std::vector<OPTUSED>::iterator it = std::find(used.begin(), used.end(), ou.id_key.c_str());
|
||||
if (it != used.end())
|
||||
it->name_key = std::move(L"SANE_STD_OPT_NAME_" + ou.name_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
off += next;
|
||||
line = L"";
|
||||
coding_util::pick_line(key.c_str() + off, got_wstr, &line, &next);
|
||||
}
|
||||
}
|
||||
|
||||
static bool add_2_huagaods_cpp(const wchar_t* file, const SANEOPT& sane, const OPTUSED& twain, std::wstring* msg)
|
||||
{
|
||||
int off = 0, next = 0, bom = BOM_ANSI;
|
||||
std::wstring cont(std::move(load_file(file, &bom))), line(L""), lead(L"CAP_EX_SANE_");
|
||||
|
||||
if (cont.empty())
|
||||
{
|
||||
if (msg)
|
||||
*msg = L"File 'huagaods.cpp' is not found or empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
line = cont;
|
||||
if (pick_twain_ex_enum(line, &off))
|
||||
{
|
||||
size_t pos = line.rfind(L',');
|
||||
const wchar_t* l = line.c_str() + pos, * bgn = NULL;
|
||||
|
||||
to_line_head(&l);
|
||||
bgn = ++l;
|
||||
skip_space(&l);
|
||||
|
||||
std::wstring en(bgn, l - bgn);
|
||||
|
||||
en += lead + a2u(twain.id_key.c_str()) + L",\t\t// " + now() + L" " + sane.title;
|
||||
lead = line;
|
||||
lead.insert(pos + 1, L"\r\n" + en);
|
||||
cont.replace(off, line.length(), lead);
|
||||
|
||||
line = cont;
|
||||
if (pick_option_id_function(line, &off, L"huagao_ds::init_support_caps_ex(void)", L"void"))
|
||||
{
|
||||
pos = line.rfind(L';');
|
||||
l = line.c_str() + pos;
|
||||
to_line_head(&l);
|
||||
l++;
|
||||
bgn = l;
|
||||
skip_space(&l);
|
||||
en = std::wstring(bgn, l - bgn);
|
||||
en += L"ADD_SANE_CAP(";
|
||||
en += a2u(twain.id_key.c_str());
|
||||
en += L");\r\n";
|
||||
lead = line + en;
|
||||
cont.replace(off, line.length(), lead);
|
||||
|
||||
if (save_file(file, cont.c_str(), bom, &line))
|
||||
{
|
||||
if (msg)
|
||||
*msg += std::wstring(L"Changed: ") + file + L"\r\n";
|
||||
return true;
|
||||
}
|
||||
else if (msg)
|
||||
*msg = L"Failed to save changes into file 'huagaods.cpp'.";
|
||||
|
||||
if (file_util::is_file_existing(line.c_str()))
|
||||
file_util::force_move_file(line.c_str(), file);
|
||||
}
|
||||
else if (msg)
|
||||
{
|
||||
*msg = L"Failed to find function 'huagao_ds::init_support_caps_ex(void)' in huagaods.cpp.";
|
||||
}
|
||||
}
|
||||
else if (msg)
|
||||
{
|
||||
*msg = L"Failed to find 'enum CapTypeEx' in huagaods.cpp.";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static bool add_2_scanner_codes(const wchar_t* cpp, const SANEOPT& sane, const OPTUSED& twain, std::wstring* msg)
|
||||
{
|
||||
int bom_c = BOM_ANSI, bom_h = BOM_ANSI;
|
||||
std::wstring hf(cpp), code_c(load_file(cpp, &bom_c)), code_h(L""), tag(L"// SANE options ID ..."), val(L""), hbak(L""), cbak(L"");
|
||||
size_t pos = hf.rfind(L'.');
|
||||
const wchar_t *l = NULL, *bgn = NULL;
|
||||
|
||||
if (code_c.empty())
|
||||
{
|
||||
if (msg)
|
||||
*msg = std::wstring(L"File '") + cpp + L"' is not found or empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
hf.erase(pos);
|
||||
hf += L".h";
|
||||
code_h = std::move(load_file(hf.c_str(), &bom_h));
|
||||
if (code_h.empty())
|
||||
{
|
||||
if (msg)
|
||||
*msg = std::wstring(L"File '") + hf + L"' is not found or empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
pos = code_h.find(tag);
|
||||
if (pos == std::wstring::npos)
|
||||
{
|
||||
if (msg)
|
||||
*msg = L"Cannot find tag '" + tag + L"' in file " + hf;
|
||||
return false;
|
||||
}
|
||||
|
||||
bgn = l = code_h.c_str() + pos;
|
||||
to_line_head(&bgn);
|
||||
bgn++;
|
||||
val = L"\r\n" + std::wstring(bgn, l - bgn) + L"SANE_OPTION_ID(" + a2u(twain.id_key.c_str()) + L");";
|
||||
code_h.insert(pos + tag.length(), val + L"\t\t// " + now() + L" " + sane.title);
|
||||
if (save_file(hf.c_str(), code_h.c_str(), bom_h, &hbak))
|
||||
{
|
||||
code_h.clear();
|
||||
|
||||
pos = code_c.find(L"SANE_OPTION_ID_IMPLEMENT(");
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
int off = 0;
|
||||
|
||||
val = L"SANE_OPTION_ID_IMPLEMENT(" + a2u(twain.id_key.c_str()) + L")\r\n";
|
||||
code_c.insert(pos, val);
|
||||
code_h = code_c;
|
||||
if (pick_option_id_function(code_h, &off))
|
||||
{
|
||||
pos = code_h.find(L"op_id++;");
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
l = bgn = code_h.c_str() + pos;
|
||||
to_line_head(&bgn);
|
||||
bgn++;
|
||||
tag = sane.name_key;
|
||||
if (tag.find(L"SANE_STD_OPT_NAME_") == 0)
|
||||
tag.erase(0, lstrlenW(L"SANE_STD_OPT_NAME_"));
|
||||
val = std::wstring(bgn, l - bgn) + L"else SET_OPT_ID(" + a2u(twain.id_key.c_str()) + L", " + tag + L", extension_none)\r\n";
|
||||
off += bgn - code_h.c_str();
|
||||
code_c.insert(off, val);
|
||||
if (save_file(cpp, code_c.c_str(), bom_c, &cbak))
|
||||
{
|
||||
std::wstring s2t(hf);
|
||||
|
||||
STR_PARENT_FOLDER(s2t);
|
||||
s2t += L"\\s2t_api.h";
|
||||
code_h = std::move(load_file(s2t.c_str(), &bom_h));
|
||||
if (!code_h.empty())
|
||||
{
|
||||
tag = L"// SANE options ID ...";
|
||||
pos = code_h.find(tag);
|
||||
if (pos == std::wstring::npos)
|
||||
{
|
||||
if (msg)
|
||||
*msg = L"Cannot find tag '// SANE options ID ...' in file " + s2t;
|
||||
return false;
|
||||
}
|
||||
bgn = l = code_h.c_str() + pos;
|
||||
to_line_head(&bgn);
|
||||
bgn++;
|
||||
val = L"\r\n" + std::wstring(bgn, l - bgn) + L"SANE_OPTION_ID_API(" + a2u(twain.id_key.c_str()) + L");";
|
||||
code_h.insert(pos + tag.length(), val + L"\t\t// " + now() + L" " + sane.title);
|
||||
|
||||
if (save_file(s2t.c_str(), code_h.c_str(), bom_h, &val))
|
||||
{
|
||||
if (msg)
|
||||
*msg += std::wstring(L"Changed: ") + hf + L"\r\n" + L"Changed: " + cpp + L"\r\nChanged: " + s2t + L"\r\n";
|
||||
return true;
|
||||
}
|
||||
else if (msg)
|
||||
*msg = L"Failed to save changes into file: " + s2t;
|
||||
if (file_util::is_file_existing(val.c_str()))
|
||||
file_util::force_move_file(val.c_str(), s2t.c_str());
|
||||
}
|
||||
else if (msg)
|
||||
*msg = std::wstring(L"File '") + s2t + L"' is not found or empty.";
|
||||
}
|
||||
else if (msg)
|
||||
{
|
||||
*msg = L"Failed to save changes into file: " + std::wstring(cpp);
|
||||
}
|
||||
|
||||
if (file_util::is_file_existing(cbak.c_str()))
|
||||
file_util::force_move_file(cbak.c_str(), cpp);
|
||||
}
|
||||
else if (msg)
|
||||
{
|
||||
*msg = L"Failed to find function 'scanner::init_options_id(void) - op_id++' in file: " + std::wstring(cpp);
|
||||
}
|
||||
}
|
||||
else if (msg)
|
||||
{
|
||||
*msg = L"Failed to find function 'scanner::init_options_id(void)' in file: " + std::wstring(cpp);
|
||||
}
|
||||
}
|
||||
else if (msg)
|
||||
{
|
||||
*msg = L"Failed to find 'SANE_OPTION_ID_IMPLEMENT' in file: " + std::wstring(cpp);
|
||||
}
|
||||
}
|
||||
else if (msg)
|
||||
{
|
||||
*msg = L"Failed to save changes into file: " + hf;
|
||||
}
|
||||
|
||||
if (file_util::is_file_existing(hbak.c_str()))
|
||||
file_util::force_move_file(hbak.c_str(), hf.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// CDlgTwain dialog
|
||||
|
||||
IMPLEMENT_DYNAMIC(CDlgTwain, CDialogEx)
|
||||
|
||||
CDlgTwain::CDlgTwain(CWnd* pParent /*=NULL*/)
|
||||
: CDialogEx(CDlgTwain::IDD, pParent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CDlgTwain::~CDlgTwain()
|
||||
{
|
||||
}
|
||||
|
||||
void CDlgTwain::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialogEx::DoDataExchange(pDX);
|
||||
DDX_Control(pDX, IDC_COMBO1, sane_);
|
||||
}
|
||||
BOOL CDlgTwain::OnInitDialog()
|
||||
{
|
||||
CDialogEx::OnInitDialog();
|
||||
|
||||
// Set the icon for this dialog. The framework does this automatically
|
||||
// when the application's main window is not a dialog
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
}
|
||||
void CDlgTwain::on_sln_path_changed(void)
|
||||
{
|
||||
GetDlgItem(IDC_BUTTON_BROWSE)->EnableWindow(FALSE);
|
||||
GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(FALSE);
|
||||
GetDlgItem(IDC_COMBO1)->EnableWindow(FALSE);
|
||||
|
||||
util::append_log(L"parsing SANE attributes ...\r\n", GetDlgItem(IDC_EDIT2)->m_hWnd, true);
|
||||
sane_.ResetContent();
|
||||
|
||||
std::wstring path(util::get_text(GetDlgItem(IDC_EDIT1)->m_hWnd));
|
||||
|
||||
opts_.clear();
|
||||
used_.clear();
|
||||
|
||||
STR_PARENT_FOLDER(path);
|
||||
path += L"\\..\\..\\";
|
||||
STR_TO_ABSOLUTE_PATH(path);
|
||||
root_ = path;
|
||||
util::get_sane_opts((path + L"sdk\\include\\sane\\sane_ex.h").c_str(), opts_);
|
||||
if (opts_.size() == 0)
|
||||
{
|
||||
::MessageBoxW(m_hWnd, L"没有找到SANE属性定义。", L"错误", MB_OK | MB_ICONSTOP);
|
||||
return;
|
||||
}
|
||||
for (auto& v : opts_)
|
||||
sane_.AddString((v.title + L" (" + v.name + L")").c_str());
|
||||
|
||||
GetDlgItem(IDC_BUTTON_BROWSE)->EnableWindow(TRUE);
|
||||
GetDlgItem(IDC_COMBO1)->EnableWindow(TRUE);
|
||||
GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(TRUE);
|
||||
util::append_log((L"Found " + std::to_wstring(opts_.size()) + L" options\r\n").c_str(), GetDlgItem(IDC_EDIT2)->m_hWnd, true);
|
||||
|
||||
// find used ...
|
||||
util::get_used_opts((path + L"code_twain\\sane\\scanner.cpp").c_str(), used_);
|
||||
}
|
||||
void CDlgTwain::synchronize_opt(const SANEOPT& opt)
|
||||
{
|
||||
OPTUSED ou;
|
||||
std::wstring pre(L"SANE_STD_OPT_NAME_"), key(L""), msg(L"");
|
||||
|
||||
if (used_.size())
|
||||
ou.id = used_[used_.size() - 1].id + 1;
|
||||
else
|
||||
ou.id = 0x8801;
|
||||
|
||||
ou.name_key = opt.name_key;
|
||||
if (ou.name_key.find(pre) == 0)
|
||||
key = ou.name_key.substr(pre.length());
|
||||
else
|
||||
key = ou.name_key;
|
||||
std::transform(key.begin(), key.end(), key.begin(), tolower);
|
||||
coding_util::unicode_2_ansi(key.c_str(), util::got_str, &ou.id_key);
|
||||
|
||||
std::vector<OPTUSED>::iterator it = std::find(used_.begin(), used_.end(), ou.id_key.c_str());
|
||||
if (it != used_.end())
|
||||
{
|
||||
::MessageBoxW(m_hWnd, (opt.title + L" already synchronized into TWAIN.").c_str(), L"Error", MB_OK | MB_ICONINFORMATION);
|
||||
return;
|
||||
}
|
||||
|
||||
if (util::add_2_huagaods_cpp((root_ + L"code_twain\\twain\\twain\\huagaods.cpp").c_str(), opt, ou, &msg) &&
|
||||
util::add_2_scanner_codes((root_ + L"code_twain\\sane\\scanner.cpp").c_str(), opt, ou, &msg))
|
||||
{
|
||||
used_.push_back(ou);
|
||||
|
||||
std::wstring tips(L"Added New TWAIN extended ATTR: CAP_EX_SANE_");
|
||||
wchar_t hex[40] = { 0 };
|
||||
|
||||
coding_util::ansi_2_unicode(ou.id_key.c_str(), util::got_wstr, &tips);
|
||||
swprintf_s(hex, _countof(hex) - 1, L" (ID: 0x%04x) - ", ou.id);
|
||||
tips += hex + opt.title + L"\r\n";
|
||||
util::append_log(tips.c_str(), GetDlgItem(IDC_EDIT2)->m_hWnd, true);
|
||||
}
|
||||
util::append_log(msg.c_str(), GetDlgItem(IDC_EDIT2)->m_hWnd, true);
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(CDlgTwain, CDialogEx)
|
||||
ON_BN_CLICKED(IDC_BUTTON_BROWSE, &CDlgTwain::OnBnClickedButtonBrowse)
|
||||
ON_BN_CLICKED(IDC_BUTTON_ADD, &CDlgTwain::OnBnClickedButtonAdd)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
// CDlgTwain message handlers
|
||||
|
||||
|
||||
|
||||
void CDlgTwain::OnBnClickedButtonBrowse()
|
||||
{
|
||||
// TODO: 在此添加控件通知处理程序代码
|
||||
file_util::PATHFILE path = { 0 };
|
||||
|
||||
if (file_util::browser_file(m_hWnd, &path, L"Solution File(*.sln)\0\0"))
|
||||
{
|
||||
::SetDlgItemTextW(m_hWnd, IDC_EDIT1, path.path);
|
||||
on_sln_path_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CDlgTwain::OnBnClickedButtonAdd()
|
||||
{
|
||||
// TODO: 在此添加控件通知处理程序代码
|
||||
std::wstring text(util::get_text(sane_.m_hWnd));
|
||||
std::string ansi("");
|
||||
size_t pos = text.rfind(L'(');
|
||||
|
||||
if (pos++ == std::wstring::npos)
|
||||
{
|
||||
::MessageBoxW(m_hWnd, L"Invalid option name! (lost '()')", L"Error", MB_OK | MB_ICONSTOP);
|
||||
return;
|
||||
}
|
||||
text.erase(0, pos);
|
||||
pos = text.find(L")");
|
||||
if (pos != std::wstring::npos)
|
||||
text.erase(pos);
|
||||
if (text.empty())
|
||||
{
|
||||
::MessageBoxW(m_hWnd, L"Invalid option name! (empty)", L"Error", MB_OK | MB_ICONSTOP);
|
||||
return;
|
||||
}
|
||||
|
||||
coding_util::unicode_2_ansi(text.c_str(), util::got_str, &ansi);
|
||||
|
||||
pos = sane_.GetCurSel();
|
||||
synchronize_opt(opts_[pos]);
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
// CDlgTwain dialog
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
typedef struct _san_opt
|
||||
{
|
||||
std::wstring name_key;
|
||||
std::wstring name;
|
||||
std::wstring title_key;
|
||||
std::wstring title;
|
||||
}SANEOPT;
|
||||
typedef struct _opt_used
|
||||
{
|
||||
std::wstring name_key; // same as SANEOPT::name_key
|
||||
std::string id_key;
|
||||
int id; // ID of CAP_SANE_EX_xxx
|
||||
|
||||
bool operator==(const wchar_t* key)
|
||||
{
|
||||
return name_key == key;
|
||||
}
|
||||
bool operator==(const char* key)
|
||||
{
|
||||
return id_key == key;
|
||||
}
|
||||
bool operator==(const int eid)
|
||||
{
|
||||
return eid == id;
|
||||
}
|
||||
bool operator<(const struct _opt_used& r)
|
||||
{
|
||||
return id < r.id;
|
||||
}
|
||||
}OPTUSED;
|
||||
|
||||
class CDlgTwain : public CDialogEx
|
||||
{
|
||||
DECLARE_DYNAMIC(CDlgTwain)
|
||||
|
||||
public:
|
||||
CDlgTwain(CWnd* pParent = NULL); // standard constructor
|
||||
virtual ~CDlgTwain();
|
||||
|
||||
// Dialog Data
|
||||
enum { IDD = IDD_ADD_TWAIN_ATTR };
|
||||
|
||||
std::vector<SANEOPT> opts_;
|
||||
std::vector<OPTUSED> used_;
|
||||
std::wstring root_;
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual BOOL OnInitDialog();
|
||||
void on_sln_path_changed(void);
|
||||
void synchronize_opt(const SANEOPT& opt);
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
public:
|
||||
afx_msg void OnBnClickedButtonBrowse();
|
||||
afx_msg void OnBnClickedButtonAdd();
|
||||
CComboBox sane_;
|
||||
};
|
Loading…
Reference in New Issue