云计算百科
云计算领域专业知识百科平台

《玄》IDE v3.6.3重磅发布:全功能修复与性能飞跃

// ============================================================
// 《玄》IDE v3.6.3 — 完整版
// v3.6.3 新增/修复:
// – pattern 补:无符号短整数/整数/长整数,超长/长/短整数及指针/列表
// – 修复嵌套 "重复" 生成同名计数器 _i_rep_0(改用独立递增 id)
// v3.6.2 修复:
// – BUG-1: 则/则␣ 前边界保护(不误伤 原则/规则/法则)
// – BUG-2: 检测到 卦 时自动注入 srand((unsigned)time(0))
// v3.6.1 修复:
// – P0: 卦 A/B 扫描、对于X从A到B B 扫描加全角标点终止
// 链接库:-lgdi32 -lcomctl32 -lcomdlg32 -static-libstdc++ -static-libgcc
// ============================================================

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <process.h>
#include <atomic>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cctype>

using namespace std;

#define IDM_FILE_NEW 1001
#define IDM_FILE_OPEN 1002
#define IDM_FILE_SAVE 1003
#define IDM_FILE_SAVEAS 1004
#define IDM_FILE_EXIT 1005
#define IDM_EDIT_CUT 1011
#define IDM_EDIT_COPY 1012
#define IDM_EDIT_PASTE 1013
#define IDM_RUN_COMPILE 1021
#define IDM_RUN_RUN 1022
#define IDM_RUN_STOP 1023
#define IDM_HELP_MANUAL 1031
#define IDM_HELP_ABOUT 1032
#define IDB_SAVE 201
#define IDB_COMPILE 202
#define IDB_RUN 203
#define IDB_STOP 204
#define IDB_CLEAR 205

#define WM_UPDATE_OUTPUT (WM_USER + 100)
#define WM_COMPILE_FINISHED (WM_USER + 101)

HWND g_hMainWnd=NULL, g_hEdit=NULL, g_hOutput=NULL, g_hStatusBar=NULL;
HWND g_hBtnSave=NULL, g_hBtnCompile=NULL, g_hBtnRun=NULL, g_hBtnStop=NULL, g_hBtnClear=NULL;
HWND g_hHelpWnd=NULL, g_hHelpEdit=NULL;
HFONT g_hFont=NULL, g_hOutFont=NULL, g_hHelpFont=NULL;
HINSTANCE g_hInst=NULL;
string g_currentFilePath = "";
string g_currentFileName;
string g_tempDir = ".";
bool g_isRunning=false, g_isCompiling=false;

static std::atomic<HANDLE> g_hGppProcess{NULL};
static std::atomic<HANDLE> g_hOutputProcess{NULL};
static std::atomic<bool> g_stopRequested{false};

// ============================================================
// 编码转换
// ============================================================
static bool cpp_is_utf8() {
static const int flag = (sizeof("中") == 4) ? 1 : 0;
return flag == 1;
}

static string to_ansi(const char* s) {
if (!s || !*s) return string();
if (!cpp_is_utf8()) return string(s);
int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s, -1, NULL, 0);
if (wlen <= 0) return string(s);
vector<wchar_t> wbuf(wlen);
MultiByteToWideChar(CP_UTF8, 0, s, -1, &wbuf[0], wlen);
int alen = WideCharToMultiByte(CP_ACP, 0, &wbuf[0], -1, NULL, 0, NULL, NULL);
if (alen <= 0) return string(s);
vector<char> abuf(alen);
WideCharToMultiByte(CP_ACP, 0, &wbuf[0], -1, &abuf[0], alen, NULL, NULL);
return string(&abuf[0], alen – 1);
}

static string to_ansi_n(const char* s, size_t len) {
if (!s || len == 0) return string();
if (!cpp_is_utf8()) return string(s, len);
int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s, (int)len, NULL, 0);
if (wlen <= 0) return string(s, len);
vector<wchar_t> wbuf(wlen);
MultiByteToWideChar(CP_UTF8, 0, s, (int)len, &wbuf[0], wlen);
int alen = WideCharToMultiByte(CP_ACP, 0, &wbuf[0], wlen, NULL, 0, NULL, NULL);
if (alen <= 0) return string(s, len);
vector<char> abuf(alen);
WideCharToMultiByte(CP_ACP, 0, &wbuf[0], wlen, &abuf[0], alen, NULL, NULL);
return string(&abuf[0], alen);
}

static bool looks_like_utf8(const string& s) {
if (s.size() >= 3 &&
(unsigned char)s[0] == 0xEF &&
(unsigned char)s[1] == 0xBB &&
(unsigned char)s[2] == 0xBF) return true;
size_t cjk3 = 0;
for (size_t k = 0; k + 2 < s.size(); ++k) {
unsigned char c0 = (unsigned char)s[k];
unsigned char c1 = (unsigned char)s[k+1];
unsigned char c2 = (unsigned char)s[k+2];
if (c0 >= 0xE4 && c0 <= 0xE9 &&
(c1 & 0xC0) == 0x80 && (c2 & 0xC0) == 0x80) {
if (++cjk3 >= 3) return true;
}
}
return false;
}

static string utf8_to_ansi(const string& s) {
size_t start = 0;
if (s.size() >= 3 &&
(unsigned char)s[0] == 0xEF &&
(unsigned char)s[1] == 0xBB &&
(unsigned char)s[2] == 0xBF) start = 3;
if (start >= s.size()) return string();
int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
s.c_str() + start, (int)(s.size() – start), NULL, 0);
if (wlen <= 0) return s;
vector<wchar_t> wbuf(wlen);
MultiByteToWideChar(CP_UTF8, 0, s.c_str() + start,
(int)(s.size() – start), &wbuf[0], wlen);
int alen = WideCharToMultiByte(CP_ACP, 0, &wbuf[0], wlen, NULL, 0, NULL, NULL);
if (alen <= 0) return s;
vector<char> abuf(alen);
WideCharToMultiByte(CP_ACP, 0, &wbuf[0], wlen, &abuf[0], alen, NULL, NULL);
return string(&abuf[0], alen);
}

#define XA(s) (to_ansi(s).c_str())

// ============================================================
// 辅助
// ============================================================
static bool is_ascii_ident(unsigned char c) {
return (c>='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') || c=='_';
}

static size_t advance_one_char(const string& s, size_t pos) {
if (pos >= s.size()) return 1;
unsigned char c = (unsigned char)s[pos];
if (c < 0x80) return 1;
if ((c & 0xF8) == 0xF0 && pos + 3 < s.size() &&
((unsigned char)s[pos+1] & 0xC0) == 0x80 &&
((unsigned char)s[pos+2] & 0xC0) == 0x80 &&
((unsigned char)s[pos+3] & 0xC0) == 0x80) return 4;
if ((c & 0xF0) == 0xE0 && pos + 2 < s.size() &&
((unsigned char)s[pos+1] & 0xC0) == 0x80 &&
((unsigned char)s[pos+2] & 0xC0) == 0x80) return 3;
if ((c & 0xE0) == 0xC0 && pos + 1 < s.size() &&
((unsigned char)s[pos+1] & 0xC0) == 0x80) return 2;
return 2;
}

static bool ends_with_cjk_hanzi(const string& s) {
if (s.size() < 2) return false;
size_t p = s.size();
while (p > 0) { p–; if (((unsigned char)s[p] & 0xC0) != 0x80) break; }
unsigned char last = (unsigned char)s[p];
if (last >= 0x80) return true;
if (p > 0 && last >= 0x40 && last <= 0x7E) {
unsigned char lead = (unsigned char)s[p-1];
if (lead >= 0x81 && lead <= 0xFE) return true;
}
return false;
}

static bool is_fullwidth_punct_at(const string& s, size_t pos) {
if (pos >= s.size()) return false;
unsigned char c = (unsigned char)s[pos];
if (c < 0x80) return false;
if (c >= 0xA1 && c <= 0xA3) return true;
if (c == 0xEF) return true;
if (c == 0xE3 && pos + 1 < s.size() &&
(unsigned char)s[pos+1] == 0x80) return true;
return false;
}

// ============================================================
// 标点表
// ============================================================
static const vector<pair<string,string> >& get_punct_pairs() {
static vector<pair<string,string> > list;
static bool ready = false;
if (!ready) {
struct { const char* f; const char* t; } raw[] = {
{"(","("},{")",")"},{"「","["},{"」","]"},
{"【","{"},{"】","}"},{"《","{"},{"》","}"},
{",",","},{"、",","},{";",";"},{":"," << "}
};
for (size_t i = 0; i < sizeof(raw)/sizeof(raw[0]); ++i)
list.push_back(make_pair(to_ansi(raw[i].f), string(raw[i].t)));
ready = true;
}
return list;
}

static const vector<string>& get_punct_list() {
static vector<string> list;
static bool ready = false;
if (!ready) {
const char* raw[] = {";",":",",","。","、","!","?",
"(",")","【","】","「","」","《","》"," "};
for (size_t i = 0; i < sizeof(raw)/sizeof(raw[0]); ++i)
list.push_back(to_ansi(raw[i]));
ready = true;
}
return list;
}

static bool is_punct_pattern(const string& from) {
const vector<string>& L = get_punct_list();
for (size_t k = 0; k < L.size(); ++k) if (from == L[k]) return true;
return false;
}

static bool ends_with_any_punct(const string& s) {
const vector<string>& L = get_punct_list();
for (size_t k = 0; k < L.size(); ++k) {
size_t n = L[k].size();
if (s.size() >= n && s.compare(s.size()-n, n, L[k]) == 0) return true;
}
return false;
}

static bool is_cjk_terminator_at(const string& s, size_t pos) {
const vector<string>& L = get_punct_list();
for (size_t k = 0; k < L.size(); ++k) {
size_t n = L[k].size();
if (pos + n <= s.size() && s.compare(pos, n, L[k]) == 0)
return true;
}
return false;
}

static string translate_punct_only(const string& s) {
const vector<pair<string,string> >& subs = get_punct_pairs();
string r = s;
for (size_t k = 0; k < subs.size(); ++k) {
const string& from = subs[k].first;
const string& to = subs[k].second;
if (from.empty()) continue;
size_t flen = from.size(), tlen = to.size(), pos = 0;
while ((pos = r.find(from, pos)) != string::npos) {
r.replace(pos, flen, to);
pos += tlen;
}
}
return r;
}

static const char* GetFilterAnsi() {
static const char RAW[] = "玄源文件\\0*.玄\\0所有文件\\0*.*\\0";
static const string ANSI = to_ansi_n(RAW, sizeof(RAW) – 1);
return ANSI.c_str();
}

static const char* GetDefExtAnsi() {
static const string s = to_ansi("玄");
return s.c_str();
}

// ============================================================
// 用法大全
// ============================================================
const char* HELP_TEXT =
"================================================================\\n"
" 《玄》语言用法大全 v3.6.3\\n"
"================================================================\\n"
"\\n"
"【1 文件结构】\\n"
"头文件《标准IO》\\n"
"使用命名空间标准;\\n"
"主程序:\\n"
" 代码…\\n"
"。\\n"
"提示:关键字后建议跟空格或全角标点。\\n"
" 标识符中如包含关键字,可用 \\\\ 转义。\\n"
"\\n"
"【2 头文件】(35 个)\\n"
" 基础:标准IO / 字符串 / 向量 / 内存\\n"
" 算法:算法 / 数学 / 数值 / 随机数 / 随机\\n"
" 容器:映射 / 字典 / 集合 / 队列 / 栈 / 链表 / 数组 / 双端队列\\n"
" 工具:元组 / 对组 / 工具 / 函数 / 时间\\n"
" 并发:线程 / 互斥 / 互斥锁 / 原子 / 条件变量\\n"
" 输入:文件 / 文件流 / 字符串流 / 流格式 / 异常 / 迭代器\\n"
" 其他:位集 / 复数\\n"
"\\n"
"【3 命名空间】\\n"
"使用命名空间标准; -> using namespace std;\\n"
"使用命名空间 我的库; -> using namespace 我的库;\\n"
"\\n"
"【4 基本类型】\\n"
"整数 int / 浮点 float / 双精度 double / 字符 char\\n"
"布尔 bool / 文本 std::string / 字符串 std::string / 无 void\\n"
"真 true / 假 false / 定义 int\\n"
"短整数 short / 长整数 long long / 超长整数 long long\\n"
"无符号整数 unsigned int / 无符号短整数 unsigned short\\n"
"无符号长整数 unsigned long long\\n"
"\\n"
"【5 容器类型别名】\\n"
"整数映射 / 文本映射 / 整数集合 / 文本集合\\n"
"整数队列 / 文本队列 / 整数栈 / 文本栈\\n"
"整数对 / 文本对 / 整数双端队列\\n"
"整数列表 / 文本列表 / 浮点列表\\n"
"短整数列表 / 长整数列表 / 超长整数列表\\n"
"\\n"
"【6 输入输出】\\n"
"输出:\\"你好\\":换行;\\n"
"输入:a;\\n"
"全角冒号(:)翻译为 <<\\n"
"\\n"
"【7 运算符】\\n"
"比较:小于 < 大于 > 不大于 <= 不小于 >=\\n"
" 等于 == 不等于 != 比…小 < 比…大 >\\n"
" 比…小 允许跨行、紧凑写法(i比a小)\\n"
"逻辑:与/且 && 或/或者 || 非 !\\n"
"算术:加 + 减 – 乘 * 除 / 模 % 递增 ++ 递减 –\\n"
"大小:大小(T) / 字节数(T) -> sizeof(T)\\n"
"\\n"
"【8 控制流】\\n"
"如果(条件)《…》 否则如果《…》 否则《…》\\n"
"对于(整数 i=0;i 小于 10;i 递增)《…》\\n"
"只要(条件)《…》 / 当(条件)《…》\\n"
"跳出 break / 继续 continue / 返回 return\\n"
"\\n"
"【9 玄独有语法】\\n"
" ● 重复 N 次\\n"
" 重复 3 次 《 输出:\\"你好\\":换行; 》\\n"
"\\n"
" ● 对于 X 从 A 到 B(闭区间)\\n"
" 对于 i 从 1 到 5 《 输出:i:换行; 》\\n"
" 对于 i 从 3 到 1 递减 《 … 》\\n"
"\\n"
" ● 若 C 则 S;否则若 C 则 S;否则 S;\\n"
" 若 分数 大于 90 则 输出:\\"优\\":换行;\\n"
" 否则若 分数 大于 60 则 输出:\\"及格\\":换行;\\n"
" 否则 输出:\\"不及格\\":换行;\\n"
" 注意:\\"若\\"/\\"则\\"前后要有空格。\\n"
"\\n"
" ● 环 《…》 无限循环\\n"
"\\n"
" ● 卦 N / 卦 A 到 B 随机数(自动 srand)\\n"
" 卦 6 -> 范围 0..5\\n"
" 卦 1 到 6 -> 范围 1..6\\n"
"\\n"
" ● 承 继承\\n"
" ● 此 的 / 的 成员访问\\n"
"\\n"
"【10 类与结构】\\n"
"类 学生 《 公开: … 继承:类 大学生 承 学生 《 … 》\\n"
"\\n"
"【11 指针】\\n"
"整数指针 / 短整数指针 / 长整数指针 / 超长整数指针\\n"
"取地址 / 取内容 / 空指针 / 新建 / 释放\\n"
"\\n"
"【12 动态内存】\\n"
"新建 整数(100) / 新建数组 整数「10」 / 释放 p\\n"
"\\n"
"【13 容器初始化 / 索引】\\n"
"整数列表 v = 【1, 2, 3】; v「0」 -> v[0]\\n"
"\\n"
"【14 头文件对照表】\\n"
" 标准IO -> iostream + string + vector + memory + cstdlib\\n"
" 其余 34 个见源码\\n"
"\\n"
"【15 常见错误】\\n"
"1. 忘记写 头文件《标准IO》\\n"
"2. 忘记写 使用命名空间标准;\\n"
"3. 字符串用中文引号 “” —— 必须用英文引号 \\"\\"\\n"
"4. 缺少主程序结尾的句号 。\\n"
"5. 索引用 【】 会错 —— 索引用 「」,初始化用 【】\\n"
"6. 关键字与中文变量名粘连 —— 中间加空格或全角标点\\n"
"7. \\"若\\" / \\"则\\" / \\"否则若\\" / \\"此 的\\" / \\" 的 \\" 前后要空格\\n"
"\\n"
" 《玄》IDE v3.6.3\\n"
"================================================================\\n";

// ============================================================
// 文件工具
// ============================================================
string read_file(const string& path) {
ifstream f(path.c_str(), ios::binary);
if (!f) return "";
stringstream ss; ss << f.rdbuf();
return ss.str();
}
void write_file(const string& path, const string& content) {
ofstream f(path.c_str(), ios::binary);
f << content;
}

// ============================================================
// 构建 pattern
// ============================================================
static void build_patterns(vector<pair<string,string> >& patterns) {
patterns.push_back(make_pair(to_ansi("头文件《标准IO》"), string("#include <iostream>\\n#include <string>\\n#include <vector>\\n#include <memory>\\n#include <cstdlib>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《字符串》"), string("#include <string>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《向量》"), string("#include <vector>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《内存》"), string("#include <memory>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《算法》"), string("#include <algorithm>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《数学》"), string("#include <cmath>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《数值》"), string("#include <numeric>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《随机数》"), string("#include <random>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《随机》"), string("#include <random>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《映射》"), string("#include <map>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《字典》"), string("#include <map>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《集合》"), string("#include <set>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《队列》"), string("#include <queue>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《栈》"), string("#include <stack>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《链表》"), string("#include <list>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《数组》"), string("#include <array>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《双端队列》"),string("#include <deque>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《元组》"), string("#include <tuple>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《对组》"), string("#include <utility>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《工具》"), string("#include <utility>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《函数》"), string("#include <functional>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《时间》"), string("#include <chrono>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《线程》"), string("#include <thread>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《互斥锁》"), string("#include <mutex>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《互斥》"), string("#include <mutex>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《原子》"), string("#include <atomic>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《条件变量》"),string("#include <condition_variable>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《文件流》"), string("#include <fstream>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《文件》"), string("#include <fstream>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《字符串流》"),string("#include <sstream>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《流格式》"), string("#include <iomanip>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《异常》"), string("#include <stdexcept>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《迭代器》"), string("#include <iterator>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《位集》"), string("#include <bitset>\\n")));
patterns.push_back(make_pair(to_ansi("头文件《复数》"), string("#include <complex>\\n")));

patterns.push_back(make_pair(to_ansi("使用命名空间标准;"), string("using namespace std;")));
patterns.push_back(make_pair(to_ansi("使用命名空间标准"), string("using namespace std")));
patterns.push_back(make_pair(to_ansi("使用命名空间"), string("using namespace ")));
patterns.push_back(make_pair(to_ansi("命名空间"), string("namespace ")));
patterns.push_back(make_pair(to_ansi("主程序:"), string("int main() {")));

patterns.push_back(make_pair(to_ansi("输出:"), string("std::cout << ")));
patterns.push_back(make_pair(to_ansi("输出"), string("std::cout << ")));
patterns.push_back(make_pair(to_ansi("输入:"), string("std::cin >> ")));
patterns.push_back(make_pair(to_ansi("输入"), string("std::cin >> ")));
patterns.push_back(make_pair(to_ansi("换行"), string("std::endl")));

patterns.push_back(make_pair(to_ansi("整数双端队列"), string("std::deque<int>")));
patterns.push_back(make_pair(to_ansi("整数映射"), string("std::map<int,int>")));
patterns.push_back(make_pair(to_ansi("文本映射"), string("std::map<std::string,std::string>")));
patterns.push_back(make_pair(to_ansi("整数集合"), string("std::set<int>")));
patterns.push_back(make_pair(to_ansi("文本集合"), string("std::set<std::string>")));
patterns.push_back(make_pair(to_ansi("整数队列"), string("std::queue<int>")));
patterns.push_back(make_pair(to_ansi("文本队列"), string("std::queue<std::string>")));
patterns.push_back(make_pair(to_ansi("整数栈"), string("std::stack<int>")));
patterns.push_back(make_pair(to_ansi("文本栈"), string("std::stack<std::string>")));
patterns.push_back(make_pair(to_ansi("整数对"), string("std::pair<int,int>")));
patterns.push_back(make_pair(to_ansi("文本对"), string("std::pair<std::string,std::string>")));
patterns.push_back(make_pair(to_ansi("整数列表"), string("std::vector<int>")));
patterns.push_back(make_pair(to_ansi("文本列表"), string("std::vector<std::string>")));
patterns.push_back(make_pair(to_ansi("浮点列表"), string("std::vector<float>")));

// —- v3.6.3 补:长短整数、无符号 —-
patterns.push_back(make_pair(to_ansi("无符号长整数"), string("unsigned long long")));
patterns.push_back(make_pair(to_ansi("无符号短整数"), string("unsigned short")));
patterns.push_back(make_pair(to_ansi("无符号整数"), string("unsigned int")));
patterns.push_back(make_pair(to_ansi("超长整数指针"), string("long long*")));
patterns.push_back(make_pair(to_ansi("长整数指针"), string("long long*")));
patterns.push_back(make_pair(to_ansi("短整数指针"), string("short*")));
patterns.push_back(make_pair(to_ansi("超长整数列表"), string("std::vector<long long>")));
patterns.push_back(make_pair(to_ansi("长整数列表"), string("std::vector<long long>")));
patterns.push_back(make_pair(to_ansi("短整数列表"), string("std::vector<short>")));
patterns.push_back(make_pair(to_ansi("超长整数"), string("long long")));
patterns.push_back(make_pair(to_ansi("长整数"), string("long long")));
patterns.push_back(make_pair(to_ansi("短整数"), string("short")));

patterns.push_back(make_pair(to_ansi("整数指针"), string("int*")));
patterns.push_back(make_pair(to_ansi("文本指针"), string("std::string*")));
patterns.push_back(make_pair(to_ansi("浮点指针"), string("float*")));
patterns.push_back(make_pair(to_ansi("双精度指针"), string("double*")));
patterns.push_back(make_pair(to_ansi("字符指针"), string("char*")));
patterns.push_back(make_pair(to_ansi("布尔指针"), string("bool*")));

patterns.push_back(make_pair(to_ansi("整数"), string("int")));
patterns.push_back(make_pair(to_ansi("浮点"), string("float")));
patterns.push_back(make_pair(to_ansi("双精度"), string("double")));
patterns.push_back(make_pair(to_ansi("字符"), string("char")));
patterns.push_back(make_pair(to_ansi("布尔"), string("bool")));
patterns.push_back(make_pair(to_ansi("文本"), string("std::string")));
patterns.push_back(make_pair(to_ansi("字符串"), string("std::string")));
patterns.push_back(make_pair(to_ansi("无"), string("void")));
patterns.push_back(make_pair(to_ansi("定义"), string("int")));

patterns.push_back(make_pair(to_ansi("取地址"), string("&")));
patterns.push_back(make_pair(to_ansi("取址"), string("&")));
patterns.push_back(make_pair(to_ansi("取内容"), string("*")));
patterns.push_back(make_pair(to_ansi("解引用"), string("*")));
patterns.push_back(make_pair(to_ansi("空指针"), string("nullptr")));
patterns.push_back(make_pair(to_ansi("新建数组"), string("new ")));
patterns.push_back(make_pair(to_ansi("新建"), string("new ")));
patterns.push_back(make_pair(to_ansi("释放数组"), string("delete[] ")));
patterns.push_back(make_pair(to_ansi("释放"), string("delete ")));
patterns.push_back(make_pair(to_ansi("常量"), string("const ")));
patterns.push_back(make_pair(to_ansi("静态"), string("static ")));

patterns.push_back(make_pair(to_ansi("不大于"), string("<=")));
patterns.push_back(make_pair(to_ansi("不小于"), string(">=")));
patterns.push_back(make_pair(to_ansi("小于"), string("<")));
patterns.push_back(make_pair(to_ansi("大于"), string(">")));
patterns.push_back(make_pair(to_ansi("等于"), string("==")));
patterns.push_back(make_pair(to_ansi("不等于"), string("!=")));
patterns.push_back(make_pair(to_ansi("与"), string("&&")));
patterns.push_back(make_pair(to_ansi("且"), string("&&")));
patterns.push_back(make_pair(to_ansi("或者"), string("||")));
patterns.push_back(make_pair(to_ansi("或"), string("||")));
patterns.push_back(make_pair(to_ansi("非"), string("!")));

patterns.push_back(make_pair(to_ansi("递增"), string("++")));
patterns.push_back(make_pair(to_ansi("递减"), string("–")));
patterns.push_back(make_pair(to_ansi("加"), string("+")));
patterns.push_back(make_pair(to_ansi("减"), string("-")));
patterns.push_back(make_pair(to_ansi("乘"), string("*")));
patterns.push_back(make_pair(to_ansi("除"), string("/")));
patterns.push_back(make_pair(to_ansi("模"), string("%")));

patterns.push_back(make_pair(to_ansi("《"), string("{")));
patterns.push_back(make_pair(to_ansi("》"), string("}")));
patterns.push_back(make_pair(to_ansi("【"), string("{")));
patterns.push_back(make_pair(to_ansi("】"), string("}")));
patterns.push_back(make_pair(to_ansi("「"), string("[")));
patterns.push_back(make_pair(to_ansi("」"), string("]")));
patterns.push_back(make_pair(to_ansi("("), string("(")));
patterns.push_back(make_pair(to_ansi(")"), string(")")));
patterns.push_back(make_pair(to_ansi(";"), string(";")));
patterns.push_back(make_pair(to_ansi(":"), string(" << ")));
patterns.push_back(make_pair(to_ansi("。"), string("}")));
patterns.push_back(make_pair(to_ansi(","), string(",")));
patterns.push_back(make_pair(to_ansi("、"), string(",")));
patterns.push_back(make_pair(to_ansi("!"), string("!")));
patterns.push_back(make_pair(to_ansi("?"), string("?")));
patterns.push_back(make_pair(to_ansi(" "), string(" ")));

patterns.push_back(make_pair(to_ansi("否则如果"), string("else if ")));
patterns.push_back(make_pair(to_ansi("否则"), string("else ")));
patterns.push_back(make_pair(to_ansi("如果"), string("if ")));
patterns.push_back(make_pair(to_ansi("对于"), string("for ")));
patterns.push_back(make_pair(to_ansi("只要"), string("while ")));
patterns.push_back(make_pair(to_ansi("当"), string("while ")));
patterns.push_back(make_pair(to_ansi("跳出"), string("break")));
patterns.push_back(make_pair(to_ansi("继续"), string("continue")));
patterns.push_back(make_pair(to_ansi("返回"), string("return ")));

patterns.push_back(make_pair(to_ansi("类"), string("class ")));
patterns.push_back(make_pair(to_ansi("结构"), string("struct ")));
patterns.push_back(make_pair(to_ansi("枚举"), string("enum ")));
patterns.push_back(make_pair(to_ansi("继承"), string(": public ")));
patterns.push_back(make_pair(to_ansi("公开"), string("public:")));
patterns.push_back(make_pair(to_ansi("公有"), string("public:")));
patterns.push_back(make_pair(to_ansi("私有"), string("private:")));
patterns.push_back(make_pair(to_ansi("保护"), string("protected:")));
patterns.push_back(make_pair(to_ansi("虚函数"), string("virtual ")));

patterns.push_back(make_pair(to_ansi("真"), string("true")));
patterns.push_back(make_pair(to_ansi("假"), string("false")));

patterns.push_back(make_pair(to_ansi("否则若 "), string("else if (")));
patterns.push_back(make_pair(to_ansi("若 "), string("if (")));
patterns.push_back(make_pair(to_ansi("则 "), string(") ")));
patterns.push_back(make_pair(to_ansi("则"), string(")")));
patterns.push_back(make_pair(to_ansi("承"), string(": public ")));
patterns.push_back(make_pair(to_ansi("此 的 "), string("this->")));
patterns.push_back(make_pair(to_ansi(" 的 "), string(". ")));
patterns.push_back(make_pair(to_ansi("字节数("), string("sizeof(")));
patterns.push_back(make_pair(to_ansi("大小("), string("sizeof(")));

sort(patterns.begin(), patterns.end(),
[](const pair<string, string>& a, const pair<string, string>& b) {
return a.first.size() > b.first.size();
});
}

// ============================================================
// 转译核心
// ============================================================
string translate_xuan(const string& src) {
static vector<pair<string,string> > patterns;
static bool patterns_ready = false;
if (!patterns_ready) { build_patterns(patterns); patterns_ready = true; }

static string BI, XIAO, DA, ZUO, YOU, KUO_L, KUO_R;
static bool kw_ready = false;
if (!kw_ready) {
BI = to_ansi("比"); XIAO = to_ansi("小"); DA = to_ansi("大");
ZUO = to_ansi("("); YOU = to_ansi(")");
KUO_L = to_ansi("《"); KUO_R = to_ansi("》");
kw_ready = true;
}
const size_t BI_LEN = BI.size(), XIAO_LEN = XIAO.size(), DA_LEN = DA.size();
const size_t ZUO_LEN = ZUO.size(), YOU_LEN = YOU.size();
const size_t KUO_L_LEN = KUO_L.size(), KUO_R_LEN = KUO_R.size();

static string REPEAT_KW, TIMES_KW, FOR_KW, CONG_KW, DAO_KW, DEC_KW, GUA_KW, HUAN_KW;
static bool new_kw_ready = false;
if (!new_kw_ready) {
REPEAT_KW = to_ansi("重复");
TIMES_KW = to_ansi("次");
FOR_KW = to_ansi("对于");
CONG_KW = to_ansi("从");
DAO_KW = to_ansi("到");
DEC_KW = to_ansi("递减");
GUA_KW = to_ansi("卦");
HUAN_KW = to_ansi("环");
new_kw_ready = true;
}
const size_t REPEAT_LEN = REPEAT_KW.size(), TIMES_LEN = TIMES_KW.size();
const size_t FOR_KW_LEN = FOR_KW.size(), CONG_LEN = CONG_KW.size();
const size_t DAO_LEN = DAO_KW.size(), DEC_LEN = DEC_KW.size();
const size_t GUA_LEN = GUA_KW.size(), HUAN_LEN = HUAN_KW.size();

static string ZE_SPACE_KW, ZE_KW;
static bool ze_ready = false;
if (!ze_ready) {
ZE_SPACE_KW = to_ansi("则 ");
ZE_KW = to_ansi("则");
ze_ready = true;
}

vector<int> repeat_stack;
int next_rep_id = 0; // v3.6.3:独立递增计数器,避免嵌套同名

string out;
size_t i = 0;
const size_t N = src.size();
while (i < N) {
if (src[i] == '"') {
out += src[i++];
while (i < N) {
if (src[i] == '\\\\' && i+1 < N) { out += src[i++]; out += src[i++]; continue; }
if (src[i] == '"') break;
out += src[i++];
}
if (i < N) out += src[i++];
continue;
}
if (src[i] == '\\\\' && i + 1 < N) {
size_t clen = advance_one_char(src, i + 1);
if (i + 1 + clen <= N) { out += src.substr(i + 1, clen); i += 1 + clen; continue; }
}
if (src[i] == '/' && i+1 < N && src[i+1] == '/') {
while (i < N && src[i] != '\\n') out += src[i++];
continue;
}
if (src[i] == '/' && i+1 < N && src[i+1] == '*') {
out += src[i++]; out += src[i++];
while (i < N && !(src[i-1] == '*' && src[i] == '/')) out += src[i++];
if (i < N) out += src[i++];
continue;
}

bool matched = false;

// —- 重复 N 次 —-
if (!matched && REPEAT_LEN > 0 && i + REPEAT_LEN <= N &&
src.compare(i, REPEAT_LEN, REPEAT_KW) == 0) {
if (i == 0 || !is_ascii_ident((unsigned char)src[i-1])) {
int id = next_rep_id++; // v3.6.3:独立递增
repeat_stack.push_back(id);
out += "for (int _i_rep_" + to_string(id) + " = 0; _i_rep_"
+ to_string(id) + " < (";
i += REPEAT_LEN;
matched = true;
}
}
// —- 次 —-
if (!matched && !repeat_stack.empty() && TIMES_LEN > 0 &&
i + TIMES_LEN <= N && src.compare(i, TIMES_LEN, TIMES_KW) == 0) {
if (i == 0 || !is_ascii_ident((unsigned char)src[i-1])) {
size_t aft = i + TIMES_LEN;
unsigned char nx = (aft < N) ? (unsigned char)src[aft] : (unsigned char)0;
if (nx == 0 || isspace(nx) ||
(aft + KUO_L_LEN <= N &&
src.compare(aft, KUO_L_LEN, KUO_L) == 0)) {
int id = repeat_stack.back();
repeat_stack.pop_back();
out += "); _i_rep_" + to_string(id) + "++) ";
i = aft;
matched = true;
}
}
}
// —- 对于 X 从 A 到 B [递减] —-
if (!matched && FOR_KW_LEN > 0 && i + FOR_KW_LEN <= N &&
src.compare(i, FOR_KW_LEN, FOR_KW) == 0) {
if (i == 0 || !is_ascii_ident((unsigned char)src[i-1])) {
size_t j = i + FOR_KW_LEN;
while (j < N && isspace((unsigned char)src[j])) j++;
size_t vs = j;
while (j < N && !isspace((unsigned char)src[j]) &&
!(j + CONG_LEN <= N &&
src.compare(j, CONG_LEN, CONG_KW) == 0))
j += advance_one_char(src, j);
size_t ve = j;
while (j < N && isspace((unsigned char)src[j])) j++;
if (ve > vs && j + CONG_LEN <= N &&
src.compare(j, CONG_LEN, CONG_KW) == 0) {
string var = src.substr(vs, ve – vs);
j += CONG_LEN;
while (j < N && isspace((unsigned char)src[j])) j++;
size_t as = j;
while (j < N && !isspace((unsigned char)src[j]) &&
!(j + DAO_LEN <= N &&
src.compare(j, DAO_LEN, DAO_KW) == 0))
j += advance_one_char(src, j);
size_t ae = j;
while (j < N && isspace((unsigned char)src[j])) j++;
if (ae > as && j + DAO_LEN <= N &&
src.compare(j, DAO_LEN, DAO_KW) == 0) {
string A = src.substr(as, ae – as);
j += DAO_LEN;
while (j < N && isspace((unsigned char)src[j])) j++;
size_t bs = j;
while (j < N && !isspace((unsigned char)src[j]) &&
!(j + DEC_LEN <= N &&
src.compare(j, DEC_LEN, DEC_KW) == 0) &&
!(j + KUO_L_LEN <= N &&
src.compare(j, KUO_L_LEN, KUO_L) == 0)) {
if (is_cjk_terminator_at(src, j)) break;
j += advance_one_char(src, j);
}
size_t be = j;
if (be > bs) {
string B = src.substr(bs, be – bs);
while (j < N && isspace((unsigned char)src[j])) j++;
bool desc = false;
if (j + DEC_LEN <= N &&
src.compare(j, DEC_LEN, DEC_KW) == 0) {
desc = true; j += DEC_LEN;
}
out += "for (int " + var + " = " + A + "; " + var;
out += desc ? " >= " : " <= ";
out += B + "; " + var;
out += desc ? "–" : "++";
out += ") ";
i = j;
matched = true;
}
}
}
}
}
// —- 环 《 —-
if (!matched && HUAN_LEN > 0 && i + HUAN_LEN <= N &&
src.compare(i, HUAN_LEN, HUAN_KW) == 0) {
if (i == 0 || !is_ascii_ident((unsigned char)src[i-1])) {
size_t j = i + HUAN_LEN;
while (j < N && isspace((unsigned char)src[j])) j++;
if (j + KUO_L_LEN <= N &&
src.compare(j, KUO_L_LEN, KUO_L) == 0) {
out += "while (true) {";
i = j + KUO_L_LEN;
matched = true;
}
}
}
// —- 卦 N / 卦 A 到 B —-
if (!matched && GUA_LEN > 0 && i + GUA_LEN <= N &&
src.compare(i, GUA_LEN, GUA_KW) == 0) {
if (i == 0 || !is_ascii_ident((unsigned char)src[i-1])) {
size_t j = i + GUA_LEN;
while (j < N && isspace((unsigned char)src[j])) j++;
size_t as = j;
while (j < N && !isspace((unsigned char)src[j]) &&
src[j] != ';' && src[j] != ')' &&
src[j] != ',' && src[j] != '(' &&
src[j] != '{' && src[j] != '}') {
if (j + DAO_LEN <= N &&
src.compare(j, DAO_LEN, DAO_KW) == 0) break;
if (is_cjk_terminator_at(src, j)) break;
j += advance_one_char(src, j);
}
size_t ae = j;
if (ae > as) {
while (j < N && isspace((unsigned char)src[j])) j++;
if (j + DAO_LEN <= N &&
src.compare(j, DAO_LEN, DAO_KW) == 0) {
j += DAO_LEN;
while (j < N && isspace((unsigned char)src[j])) j++;
size_t bs = j;
while (j < N && !isspace((unsigned char)src[j]) &&
src[j] != ';' && src[j] != ')' &&
src[j] != ',' && src[j] != '(' &&
src[j] != '{' && src[j] != '}') {
if (is_cjk_terminator_at(src, j)) break;
j += advance_one_char(src, j);
}
size_t be = j;
if (be > bs) {
string A = src.substr(as, ae – as);
string B = src.substr(bs, be – bs);
out += "((rand() % ((" + B + ") – (" + A
+ ") + 1)) + (" + A + "))";
i = j;
matched = true;
}
} else {
string N_ = src.substr(as, ae – as);
out += "(rand() % (" + N_ + "))";
i = ae;
matched = true;
}
}
}
}

// —- "比" 结构 —-
if (!matched && BI_LEN > 0 && i + BI_LEN <= N && src.compare(i, BI_LEN, BI) == 0) {
bool boundary_ok = (i == 0) || !is_ascii_ident((unsigned char)src[i-1]);
if (!boundary_ok) {
size_t probe = i + BI_LEN;
if (probe < N) {
unsigned char p = (unsigned char)src[probe];
bool sp = isspace(p) != 0;
bool xa = (probe + XIAO_LEN <= N && src.compare(probe, XIAO_LEN, XIAO) == 0);
bool da = (probe + DA_LEN <= N && src.compare(probe, DA_LEN, DA) == 0);
boundary_ok = !sp && !xa && !da;
}
}
if (boundary_ok) {
size_t v1_end = i;
while (v1_end > 0 && isspace((unsigned char)src[v1_end-1])) v1_end–;
size_t v1_start = v1_end;
while (v1_start > 0 &&
!isspace((unsigned char)src[v1_start-1]) &&
src[v1_start-1] != '(' &&
!(v1_start >= ZUO_LEN && src.compare(v1_start – ZUO_LEN, ZUO_LEN, ZUO) == 0))
v1_start–;
size_t j = i + BI_LEN;
while (j < N && isspace((unsigned char)src[j])) j++;
size_t v2_start = j, v2_end = j;
int depth = 0;
const size_t MAX_SCAN = 4096;
while (v2_end < N && (v2_end – v2_start) < MAX_SCAN) {
unsigned char c = (unsigned char)src[v2_end];
if (c == '(') { depth++; v2_end++; continue; }
if (c == ')') { if (depth == 0) break; depth–; v2_end++; continue; }
if (v2_end + ZUO_LEN <= N && src.compare(v2_end, ZUO_LEN, ZUO) == 0) { depth++; v2_end += ZUO_LEN; continue; }
if (v2_end + YOU_LEN <= N && src.compare(v2_end, YOU_LEN, YOU) == 0) { if (depth == 0) break; depth–; v2_end += YOU_LEN; continue; }
if (depth == 0) {
if (isspace(c) || c == ';' || c == '{' || c == '}') break;
if (v2_end + KUO_L_LEN <= N && src.compare(v2_end, KUO_L_LEN, KUO_L) == 0) break;
if (v2_end + KUO_R_LEN <= N && src.compare(v2_end, KUO_R_LEN, KUO_R) == 0) break;
if (v2_end + XIAO_LEN <= N && src.compare(v2_end, XIAO_LEN, XIAO) == 0) break;
if (v2_end + DA_LEN <= N && src.compare(v2_end, DA_LEN, DA) == 0) break;
}
v2_end += advance_one_char(src, v2_end);
}
size_t after = v2_end;
while (after < N && isspace((unsigned char)src[after])) after++;
bool is_xiao = (after + XIAO_LEN <= N && src.compare(after, XIAO_LEN, XIAO) == 0);
bool is_da = (after + DA_LEN <= N && src.compare(after, DA_LEN, DA) == 0);
if (v1_end > v1_start && v2_end > v2_start && (is_xiao || is_da)) {
char op = is_xiao ? '<' : '>';
string var2 = src.substr(v2_start, v2_end – v2_start);
var2 = translate_punct_only(var2);
while (!out.empty() && isspace((unsigned char)out.back())) out.pop_back();
out += " "; out += op; out += " "; out += var2;
i = after + (is_xiao ? XIAO_LEN : DA_LEN);
matched = true;
}
}
}

// —- 常规 pattern —-
if (!matched) {
for (size_t k = 0; k < patterns.size(); ++k) {
const string& from = patterns[k].first;
const string& to = patterns[k].second;
if (from.empty() || i + from.size() > N) continue;
if (src.compare(i, from.size(), from) != 0) continue;

// 则 / 则␣ 前边界保护
if ((from == ZE_SPACE_KW || from == ZE_KW) &&
i > 0 && (unsigned char)src[i-1] >= 0x80)
continue;

if (!is_punct_pattern(from) &&
i > 0 && is_ascii_ident((unsigned char)src[i-1])) continue;
if (ends_with_cjk_hanzi(from) && !ends_with_any_punct(from)) {
size_t end = i + from.size();
if (end < N) {
unsigned char next = (unsigned char)src[end];
if (is_ascii_ident(next)) continue;
if (next >= 0x80 && !is_fullwidth_punct_at(src, end)) continue;
}
}
out += to;
i += from.size();
matched = true;
break;
}
}

if (!matched) out += src[i++];
}
return out;
}

// ============================================================
// 后台任务
// ============================================================
struct CompileJob { string src; bool runAfter; };

static void FinishByStop() {
g_stopRequested.store(false);
if (g_hMainWnd) PostMessage(g_hMainWnd, WM_COMPILE_FINISHED, 0, 0);
}

static bool RunAndCapture(const string& cmdline,
std::atomic<HANDLE>* pSlot,
string& output) {
SECURITY_ATTRIBUTES sa = {};
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;

HANDLE hRead = NULL, hWrite = NULL;
if (!CreatePipe(&hRead, &hWrite, &sa, 0)) return false;
SetHandleInformation(hRead, HANDLE_FLAG_INHERIT, 0);

HANDLE hNul = CreateFileA("NUL", GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hNul == INVALID_HANDLE_VALUE) hNul = NULL;

STARTUPINFOA si = { sizeof(si) };
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdOutput = hWrite;
si.hStdError = hWrite;
si.hStdInput = hNul;

PROCESS_INFORMATION pi = {};
vector<char> cmdbuf(cmdline.begin(), cmdline.end());
cmdbuf.push_back('\\0');

BOOL ok = CreateProcessA(NULL, &cmdbuf[0], NULL, NULL, TRUE,
CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
CloseHandle(hWrite);
if (hNul) CloseHandle(hNul);
if (!ok) { CloseHandle(hRead); return false; }

if (pSlot) pSlot->store(pi.hProcess);
CloseHandle(pi.hThread);

char buf[1024];
DWORD rd = 0;
while (ReadFile(hRead, buf, sizeof(buf) – 1, &rd, NULL) && rd > 0)
output.append(buf, rd);
CloseHandle(hRead);

WaitForSingleObject(pi.hProcess, INFINITE);
DWORD ec = 1;
GetExitCodeProcess(pi.hProcess, &ec);

if (pSlot) pSlot->store(NULL);
CloseHandle(pi.hProcess);
return (ec == 0);
}

void CompileAndRunTask(const string& src, bool runAfter) {
if (g_stopRequested.load()) { FinishByStop(); return; }

string cppPath = g_tempDir + "\\\\output.cpp";
string exePath = g_tempDir + "\\\\output.exe";

string cpp = translate_xuan(src);

{
static const string GUA_NEEDLE = to_ansi("卦");
if (cpp.find(GUA_NEEDLE) != string::npos ||
src.find(GUA_NEEDLE) != string::npos) {
string inject =
"// 玄 v3.6.3:检测到 卦,自动注入随机种子\\n"
"#include <cstdlib>\\n"
"#include <ctime>\\n"
"namespace { struct _xuan_srand_init {"
" _xuan_srand_init(){ srand((unsigned)time(0)); }"
" } _xuan_srand_instance; }\\n";
cpp = inject + cpp;
}
}

write_file(cppPath, cpp);

string buildLog;
string gppCmd = "g++ \\"" + cppPath + "\\" -o \\"" + exePath + "\\" "
"-std=c++11 -finput-charset=GBK -fexec-charset=GBK";
bool compileOK = RunAndCapture(gppCmd, &g_hGppProcess, buildLog);

if (g_stopRequested.load()) { FinishByStop(); return; }

if (!compileOK) {
string* pMsg = new string(
to_ansi("❌ 编译失败:\\n") + buildLog
+ to_ansi("\\n提示:转译后的 C++ 源码在 ") + cppPath + "\\n");
if (g_hMainWnd) PostMessage(g_hMainWnd, WM_UPDATE_OUTPUT, 0, (LPARAM)pMsg);
else delete pMsg;
if (g_hMainWnd) PostMessage(g_hMainWnd, WM_COMPILE_FINISHED, 0, 0);
return;
}

string* pMsg = new string(to_ansi("✅ 编译成功!\\n") + buildLog);
if (g_hMainWnd) PostMessage(g_hMainWnd, WM_UPDATE_OUTPUT, 0, (LPARAM)pMsg);
else delete pMsg;

if (runAfter) {
if (g_stopRequested.load()) { FinishByStop(); return; }

string outputLog;
string runCmd = "\\"" + exePath + "\\"";
RunAndCapture(runCmd, &g_hOutputProcess, outputLog);

if (g_stopRequested.load()) { FinishByStop(); return; }

if (looks_like_utf8(outputLog)) outputLog = utf8_to_ansi(outputLog);

string* pRun = new string(to_ansi("\\n▶ 程序输出:\\n——————–\\n")
+ outputLog
+ to_ansi("\\n——————–\\n"));
if (g_hMainWnd) PostMessage(g_hMainWnd, WM_UPDATE_OUTPUT, 1, (LPARAM)pRun);
else delete pRun;
}

if (g_hMainWnd) PostMessage(g_hMainWnd, WM_COMPILE_FINISHED, 0, 0);
}

unsigned __stdcall CompileThreadProc(void* lpParam) {
CompileJob* pJob = (CompileJob*)lpParam;
if (!pJob) return 0;
CompileAndRunTask(pJob->src, pJob->runAfter);
delete pJob;
return 0;
}

// ============================================================
// 停止
// ============================================================
void KillOutputExe() {
HANDLE hGpp = g_hGppProcess.load();
if (hGpp) TerminateProcess(hGpp, 1);

HANDLE hOut = g_hOutputProcess.load();
if (hOut) TerminateProcess(hOut, 1);
}

// ============================================================
// 帮助窗口
// ============================================================
static const string& GetHelpAnsi() {
static const string s = to_ansi(HELP_TEXT);
return s;
}

LRESULT CALLBACK HelpWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
g_hHelpEdit = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT",
GetHelpAnsi().c_str(),
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY |
ES_AUTOVSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | WS_HSCROLL,
10, 10, 100, 100, hWnd, NULL, g_hInst, NULL);
g_hHelpFont = CreateFont(16, 0, 0, 0, FW_NORMAL, 0, 0, 0,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, XA("新宋体"));
SendMessage(g_hHelpEdit, WM_SETFONT, (WPARAM)g_hHelpFont, TRUE);
return 0;
}
case WM_SIZE: {
if (g_hHelpEdit)
SetWindowPos(g_hHelpEdit, NULL, 10, 10,
LOWORD(lParam) – 20, HIWORD(lParam) – 20, SWP_NOZORDER);
return 0;
}
case WM_CLOSE: DestroyWindow(hWnd); return 0;
case WM_DESTROY:
if (g_hHelpFont) { DeleteObject(g_hHelpFont); g_hHelpFont = NULL; }
g_hHelpWnd = NULL; g_hHelpEdit = NULL;
return 0;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}

void ShowHelp() {
if (g_hHelpWnd && IsWindow(g_hHelpWnd)) {
SetForegroundWindow(g_hHelpWnd);
return;
}
WNDCLASSA wcCheck = {};
if (!GetClassInfoA(g_hInst, "XuanHelpWnd", &wcCheck)) {
WNDCLASSA wc = {};
wc.lpfnWndProc = HelpWndProc;
wc.hInstance = g_hInst;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszClassName = "XuanHelpWnd";
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_INFORMATION);
RegisterClassA(&wc);
}
g_hHelpWnd = CreateWindowExA(0, "XuanHelpWnd", XA("《玄》语言用法大全"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 700,
g_hMainWnd, NULL, g_hInst, NULL);
if (!g_hHelpWnd) return;
ShowWindow(g_hHelpWnd, SW_SHOW);
UpdateWindow(g_hHelpWnd);
EnableWindow(g_hMainWnd, FALSE);
MSG msg;
while (g_hHelpWnd && IsWindow(g_hHelpWnd) && GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
EnableWindow(g_hMainWnd, TRUE);
SetForegroundWindow(g_hMainWnd);
}

// ============================================================
// 文件操作
// ============================================================
void SetStatusText(const string& text) {
SendMessageA(g_hStatusBar, SB_SETTEXTA, 0, (LPARAM)text.c_str());
}

static bool IsDirty() {
if (!g_hEdit) return false;
return SendMessage(g_hEdit, EM_GETMODIFY, 0, 0) != 0;
}
static void ClearDirty() {
if (g_hEdit) SendMessage(g_hEdit, EM_SETMODIFY, FALSE, 0);
}

bool SaveFile(const string& content, bool saveAs=false) {
if (saveAs || g_currentFilePath.empty()) {
OPENFILENAMEA ofn = {};
char fileName[MAX_PATH] = "";
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = g_hMainWnd;
ofn.lpstrFilter = GetFilterAnsi();
ofn.lpstrFile = fileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = GetDefExtAnsi();
ofn.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
if (!GetSaveFileNameA(&ofn)) return false;
g_currentFilePath = fileName;
}
write_file(g_currentFilePath, content);
ClearDirty();
size_t pos = g_currentFilePath.find_last_of("/\\\\");
g_currentFileName = (pos == string::npos) ? g_currentFilePath : g_currentFilePath.substr(pos+1);
SetStatusText(g_currentFileName);
return true;
}

bool OpenFile() {
OPENFILENAMEA ofn = {};
char fileName[MAX_PATH] = "";
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = g_hMainWnd;
ofn.lpstrFilter = GetFilterAnsi();
ofn.lpstrFile = fileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if (!GetOpenFileNameA(&ofn)) return false;
g_currentFilePath = fileName;
string content = read_file(g_currentFilePath);
if (looks_like_utf8(content)) content = utf8_to_ansi(content);
SetWindowTextA(g_hEdit, content.c_str());
ClearDirty();
size_t pos = g_currentFilePath.find_last_of("/\\\\");
g_currentFileName = (pos == string::npos) ? g_currentFilePath : g_currentFilePath.substr(pos+1);
SetStatusText(g_currentFileName);
return true;
}

string GetEditContent() {
int len = GetWindowTextLength(g_hEdit) + 1;
if (len <= 1) return "";
char* buf = new char[len];
GetWindowTextA(g_hEdit, buf, len);
string s = buf;
delete[] buf;
return s;
}

static bool ConfirmDiscardOrSave(HWND hWnd, const char* prompt) {
if (!IsDirty()) return true;
int r = MessageBoxA(hWnd, XA(prompt), XA("确认"),
MB_YESNOCANCEL | MB_ICONQUESTION);
if (r == IDCANCEL) return false;
if (r == IDNO) return true;
if (!SaveFile(GetEditContent(), false)) return false;
return true;
}

// ============================================================
// 主窗口过程
// ============================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
HMENU hMenuBar = CreateMenu();
HMENU hFileMenu = CreatePopupMenu();
HMENU hEditMenu = CreatePopupMenu();
HMENU hRunMenu = CreatePopupMenu();
HMENU hHelpMenu = CreatePopupMenu();

AppendMenuA(hFileMenu, MF_STRING, IDM_FILE_NEW, XA("新建(&N)"));
AppendMenuA(hFileMenu, MF_STRING, IDM_FILE_OPEN, XA("打开(&O)…"));
AppendMenuA(hFileMenu, MF_STRING, IDM_FILE_SAVE, XA("保存(&S)"));
AppendMenuA(hFileMenu, MF_STRING, IDM_FILE_SAVEAS, XA("另存为(&A)…"));
AppendMenuA(hFileMenu, MF_SEPARATOR, 0, NULL);
AppendMenuA(hFileMenu, MF_STRING, IDM_FILE_EXIT, XA("退出(&X)"));
AppendMenuA(hEditMenu, MF_STRING, IDM_EDIT_CUT, XA("剪切(&T)"));
AppendMenuA(hEditMenu, MF_STRING, IDM_EDIT_COPY, XA("复制(&C)"));
AppendMenuA(hEditMenu, MF_STRING, IDM_EDIT_PASTE, XA("粘贴(&P)"));
AppendMenuA(hRunMenu, MF_STRING, IDM_RUN_COMPILE, XA("编译(&B)"));
AppendMenuA(hRunMenu, MF_STRING, IDM_RUN_RUN, XA("运行(&R)"));
AppendMenuA(hRunMenu, MF_STRING, IDM_RUN_STOP, XA("停止(&S)"));
AppendMenuA(hHelpMenu, MF_STRING, IDM_HELP_MANUAL, XA("用法大全(&H)"));
AppendMenuA(hHelpMenu, MF_STRING, IDM_HELP_ABOUT, XA("关于(&A)"));

AppendMenuA(hMenuBar, MF_POPUP, (UINT_PTR)hFileMenu, XA("文件(&F)"));
AppendMenuA(hMenuBar, MF_POPUP, (UINT_PTR)hEditMenu, XA("编辑(&E)"));
AppendMenuA(hMenuBar, MF_POPUP, (UINT_PTR)hRunMenu, XA("运行(&R)"));
AppendMenuA(hMenuBar, MF_POPUP, (UINT_PTR)hHelpMenu, XA("帮助(&H)"));
SetMenu(hWnd, hMenuBar);

g_hEdit = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL |
ES_AUTOHSCROLL | WS_HSCROLL,
0, 0, 0, 0, hWnd, (HMENU)101, g_hInst, NULL);
SendMessage(g_hEdit, WM_SETFONT, (WPARAM)g_hFont, TRUE);

g_hOutput = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL |
ES_AUTOHSCROLL | WS_HSCROLL | ES_READONLY,
0, 0, 0, 0, hWnd, (HMENU)102, g_hInst, NULL);
SendMessage(g_hOutput, WM_SETFONT, (WPARAM)g_hOutFont, TRUE);

g_hBtnSave = CreateWindowA("BUTTON", XA("保存"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 5,5,70,28, hWnd,(HMENU)IDB_SAVE,g_hInst,NULL);
g_hBtnCompile = CreateWindowA("BUTTON", XA("编译"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 80,5,70,28, hWnd,(HMENU)IDB_COMPILE,g_hInst,NULL);
g_hBtnRun = CreateWindowA("BUTTON", XA("运行"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 155,5,70,28, hWnd,(HMENU)IDB_RUN,g_hInst,NULL);
g_hBtnStop = CreateWindowA("BUTTON", XA("停止"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 230,5,70,28, hWnd,(HMENU)IDB_STOP,g_hInst,NULL);
EnableWindow(g_hBtnStop, FALSE);
g_hBtnClear = CreateWindowA("BUTTON", XA("清空"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 305,5,70,28, hWnd,(HMENU)IDB_CLEAR,g_hInst,NULL);

g_hStatusBar = CreateWindowA(STATUSCLASSNAMEA, XA("未命名.玄"),
WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hWnd, (HMENU)301, g_hInst, NULL);

const char* demo =
"头文件《标准IO》\\n"
"使用命名空间标准;\\n"
"\\n"
"整数 求和(整数 x,整数 y)《\\n"
" 返回 x 加 y;\\n"
"》\\n"
"\\n"
"主程序:\\n"
" 重复 3 次 《\\n"
" 输出:\\"你好\\":换行;\\n"
" 》\\n"
"\\n"
" 对于 i 从 1 到 5 《\\n"
" 输出:\\"i=\\":i:换行;\\n"
" 》\\n"
"\\n"
" 对于 k 从 3 到 1 递减 《\\n"
" 输出:\\"k=\\":k:换行;\\n"
" 》\\n"
"\\n"
" 整数 分数 = 85;\\n"
" 若 分数 大于 90 则 输出:\\"优\\":换行;\\n"
" 否则若 分数 大于 60 则 输出:\\"及格\\":换行;\\n"
" 否则 输出:\\"不及格\\":换行;\\n"
"\\n"
" 输出:\\"骰子=\\":卦 1 到 6:换行;\\n"
" 输出:\\"sizeof(int)=\\":大小(整数):换行;\\n"
" 输出:\\"sizeof(short)=\\":大小(短整数):换行;\\n"
" 输出:\\"sizeof(long long)=\\":大小(长整数):换行;\\n"
"\\n"
" 整数 n = 0;\\n"
" 环 《\\n"
" n 递增;\\n"
" 若 n 大于 3 则 跳出;\\n"
" 》\\n"
" 输出:\\"n=\\":n:换行;\\n"
"\\n"
" 整数 a = 10;\\n"
" 整数 b = 0;\\n"
" 对于(整数 i = 0; i 比 a 小; i 递增)《\\n"
" b = 求和(b,i);\\n"
" 》\\n"
" 输出:\\"总和=\\":b:换行;\\n"
"\\n"
" 整数列表 v = 【10, 20, 30】;\\n"
" 对于(整数 i = 0; i 比 v.size() 小; i 递增)《\\n"
" 输出:v「i」:换行;\\n"
" 》\\n"
"\\n"
" 整数 总比 = 100;\\n"
" 输出:\\"总比=\\":总比:换行;\\n"
"\\n"
" 整数 原则 = 7;\\n"
" 输出:\\"原则=\\":原则:换行;\\n"
"\\n"
" 返回 0;\\n"
"。\\n";
SetWindowTextA(g_hEdit, to_ansi(demo).c_str());
ClearDirty();
return 0;
}

case WM_SIZE: {
RECT rc; GetClientRect(hWnd, &rc);
int w = rc.right – rc.left, h = rc.bottom – rc.top;
int toolbarH = 40, outH = 140, statusH = 25;
int editH = h – toolbarH – outH – statusH – 15;
if (editH < 50) editH = 50;
SetWindowPos(g_hEdit, NULL, 5, toolbarH+5, w-10, editH, SWP_NOZORDER);
SetWindowPos(g_hOutput, NULL, 5, toolbarH+10+editH, w-10, outH-5, SWP_NOZORDER);
SendMessage(g_hStatusBar, WM_SIZE, 0, 0);
return 0;
}

case WM_COMMAND: {
int id = LOWORD(wParam);
if (id == IDM_FILE_NEW) {
if (!ConfirmDiscardOrSave(hWnd, "当前代码已修改,是否保存?")) break;
SetWindowTextA(g_hEdit, "");
g_currentFilePath = "";
g_currentFileName = to_ansi("未命名.玄");
SetStatusText(g_currentFileName);
ClearDirty();
}
else if (id == IDM_FILE_OPEN) {
if (!ConfirmDiscardOrSave(hWnd, "当前代码已修改,是否保存?")) break;
OpenFile();
}
else if (id == IDM_FILE_SAVE) SaveFile(GetEditContent(), false);
else if (id == IDM_FILE_SAVEAS) SaveFile(GetEditContent(), true);
else if (id == IDM_FILE_EXIT) PostMessage(hWnd, WM_CLOSE, 0, 0);
else if (id == IDM_EDIT_CUT) SendMessage(g_hEdit, WM_CUT, 0, 0);
else if (id == IDM_EDIT_COPY) SendMessage(g_hEdit, WM_COPY, 0, 0);
else if (id == IDM_EDIT_PASTE) SendMessage(g_hEdit, WM_PASTE, 0, 0);
else if (id == IDM_RUN_COMPILE || id == IDB_COMPILE) {
if (g_isCompiling || g_isRunning) break;
string src = GetEditContent();
if (!g_currentFilePath.empty()) write_file(g_currentFilePath, src);
SetWindowTextA(g_hOutput, XA("正在编译…\\n"));
EnableWindow(g_hBtnCompile, FALSE);
EnableWindow(g_hBtnRun, FALSE);
g_isCompiling = true;
g_stopRequested.store(false);
CompileJob* pJob = new CompileJob();
pJob->src = src; pJob->runAfter = false;
uintptr_t th = _beginthreadex(NULL, 0, CompileThreadProc, pJob, 0, NULL);
if (th) {
CloseHandle((HANDLE)(intptr_t)th);
} else {
delete pJob;
g_isCompiling = false;
EnableWindow(g_hBtnCompile, TRUE);
EnableWindow(g_hBtnRun, TRUE);
SetWindowTextA(g_hOutput, XA("线程创建失败\\n"));
}
}
else if (id == IDM_RUN_RUN || id == IDB_RUN) {
if (g_isCompiling || g_isRunning) break;
string src = GetEditContent();
if (!g_currentFilePath.empty()) write_file(g_currentFilePath, src);
SetWindowTextA(g_hOutput, XA("正在编译并运行…\\n"));
EnableWindow(g_hBtnCompile, FALSE);
EnableWindow(g_hBtnRun, FALSE);
EnableWindow(g_hBtnStop, TRUE);
g_isRunning = true;
g_stopRequested.store(false);
CompileJob* pJob = new CompileJob();
pJob->src = src; pJob->runAfter = true;
uintptr_t th = _beginthreadex(NULL, 0, CompileThreadProc, pJob, 0, NULL);
if (th) {
CloseHandle((HANDLE)(intptr_t)th);
} else {
delete pJob;
g_isRunning = false;
EnableWindow(g_hBtnCompile, TRUE);
EnableWindow(g_hBtnRun, TRUE);
EnableWindow(g_hBtnStop, FALSE);
SetWindowTextA(g_hOutput, XA("线程创建失败\\n"));
}
}
else if (id == IDM_RUN_STOP || id == IDB_STOP) {
g_stopRequested.store(true);
KillOutputExe();
EnableWindow(g_hBtnStop, FALSE);
EnableWindow(g_hBtnCompile, FALSE);
EnableWindow(g_hBtnRun, FALSE);
SetWindowTextA(g_hOutput, XA("正在停止…\\n"));
}
else if (id == IDB_SAVE) SaveFile(GetEditContent(), false);
else if (id == IDB_CLEAR) SetWindowTextA(g_hOutput, "");
else if (id == IDM_HELP_MANUAL) ShowHelp();
else if (id == IDM_HELP_ABOUT) {
MessageBoxA(hWnd,
XA("《玄》IDE v3.6.3\\n\\n一个用中文编写程序的 IDE\\n\\n"
"新增:无符号/短/长/超长整数及指针/列表\\n"
"修复:嵌套 重复 计数器同名遮蔽"),
XA("关于"), MB_OK|MB_ICONINFORMATION);
}
return 0;
}

case WM_UPDATE_OUTPUT: {
string* pMsg = (string*)lParam;
if (pMsg) {
if (wParam == 0) SetWindowTextA(g_hOutput, pMsg->c_str());
else {
int len = GetWindowTextLengthA(g_hOutput);
char* cur = new char[len+1];
GetWindowTextA(g_hOutput, cur, len+1);
string nt = string(cur) + *pMsg;
delete[] cur;
SetWindowTextA(g_hOutput, nt.c_str());
}
delete pMsg;
}
return 0;
}

case WM_COMPILE_FINISHED: {
g_isCompiling = false;
g_isRunning = false;
g_stopRequested.store(false);
EnableWindow(g_hBtnCompile, TRUE);
EnableWindow(g_hBtnRun, TRUE);
EnableWindow(g_hBtnStop, FALSE);
return 0;
}

case WM_CLOSE:
if (!ConfirmDiscardOrSave(hWnd, "退出前是否保存修改?")) return 0;
DestroyWindow(hWnd);
return 0;

case WM_DESTROY: {
g_hMainWnd = NULL;

KillOutputExe();

if (g_tempDir != ".") {
string cppPath = g_tempDir + "\\\\output.cpp";
string exePath = g_tempDir + "\\\\output.exe";
DeleteFileA(cppPath.c_str());
DeleteFileA(exePath.c_str());
RemoveDirectoryA(g_tempDir.c_str());
}

PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}

// ============================================================
// 入口
// ============================================================
static void InitTempDir() {
char tempPath[MAX_PATH];
DWORD len = GetTempPathA(MAX_PATH, tempPath);
if (len > 0 && len < MAX_PATH) {
char pidStr[32];
snprintf(pidStr, sizeof(pidStr), "xuan_ide_%lu",
(unsigned long)GetCurrentProcessId());
string dir = string(tempPath) + pidStr;
CreateDirectoryA(dir.c_str(), NULL);
DWORD attr = GetFileAttributesA(dir.c_str());
if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
g_tempDir = dir;
}
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
(void)hPrevInstance; (void)lpCmdLine;

{
typedef BOOL (WINAPI *PFN_DPIAWARE)();
HMODULE hU = GetModuleHandleA("user32.dll");
if (hU) {
PFN_DPIAWARE pFn = (PFN_DPIAWARE)GetProcAddress(hU, "SetProcessDPIAware");
if (pFn) pFn();
}
}

g_hInst = hInstance;
g_currentFileName = to_ansi("未命名.玄");
InitTempDir();

INITCOMMONCONTROLSEX icex = {sizeof(icex), ICC_WIN95_CLASSES};
InitCommonControlsEx(&icex);

g_hFont = CreateFontA(18,0,0,0,FW_NORMAL,0,0,0, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE, XA("宋体"));
g_hOutFont = CreateFontA(16,0,0,0,FW_NORMAL,0,0,0, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE, XA("宋体"));

WNDCLASSA wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = "XuanIDE";
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassA(&wc)) return 1;

g_hMainWnd = CreateWindowExA(0, "XuanIDE", XA("《玄》IDE v3.6.3"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1000, 720,
NULL, NULL, hInstance, NULL);
if (!g_hMainWnd) return 1;

ShowWindow(g_hMainWnd, nCmdShow);
UpdateWindow(g_hMainWnd);

MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (g_hFont) DeleteObject(g_hFont);
if (g_hOutFont) DeleteObject(g_hOutFont);
return 0;
}

哈哈哈!《玄》,果然玄!这才是给中国人用的语言!


赞(0)
未经允许不得转载:网硕互联帮助中心 » 《玄》IDE v3.6.3重磅发布:全功能修复与性能飞跃
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!