欢迎下载打包后的版本!

欢迎大佬们转移成Linux版本的代码,发评论区就行,Thanks!!!!!

本开源版本需要自行建立Language_XXX.ini文件,建议去评论区复制粘贴现成的中文,当然也可以自己照着写。

// 文本编辑器模版.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
#include <iostream>
#include <windows.h>
#include <conio.h>
#include <commdlg.h>
#include <map>
#include <cstdlib>
#include <fstream>
#include <unordered_map>
#include <string>
using namespace std;

map <int, string> ERRORT = { {1, "Openfile ERROR"}, {2, "Languagefile ERROR"}, {3, "Systemtype ERROR"}};

string CONSTPLEASE = "请输入";
string CONSTOPEN = "打开";
string CONSTNEW = "新建";
string CONSTWAIT = "按任意键以继续";
string CONSTLEFT = "左";
string CONSTRIGHT = "右";
string CONSTUP = "上";
string CONSTDOWN = "下";
string CONSTQUIT = "退出";
string CONSTOPENPATH;

COORD GetCursorPos()
{
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO bInfo;
	GetConsoleScreenBufferInfo(hOut, &bInfo);
	return bInfo.dwCursorPosition;
}

unordered_map<string, string> readLanguageFile(const string& filename) {
	unordered_map<string, string> languageMap;
	ifstream file(filename);
	string line;

	if (!file.is_open()) {
		cerr << "Error opening file: " << filename << endl;
		return languageMap; // 返回一个空的map
	}

	while (getline(file, line)) {
		// 查找等号的位置
		size_t equalPos = line.find('=');
		if (equalPos != string::npos) {
			// 提取键和值
			string key = line.substr(0, equalPos);
			string value = line.substr(equalPos + 1, line.length() - equalPos - 1);
			// 去除键和值两侧的引号(如果有的话)
			if (key.front() == '"' && key.back() == '"') {
				key = key.substr(1, key.length() - 2);
			}
			if (value.front() == '"' && value.back() == '"') {
				value = value.substr(1, value.length() - 2);
			}
			// 存储到map中
			languageMap[key] = value;
		}
	}

	file.close();
	return languageMap;
}

string OpenFileDialog(string filePath, int size) {
	cout << CONSTPLEASE << CONSTOPENPATH << endl;
	cin >> filePath;
	return filePath;
}


void gotoxy(int x, int y)
{
	HANDLE hout;
	COORD pos;
	pos.X = x;
	pos.Y = y;
	hout = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hout, pos);
}

void gotoU(char n)
{
	int x = 0, y = 0;
	COORD cursorPos;
	cursorPos = GetCursorPos();

	int xCoord = cursorPos.X; // 获取x坐标
	int yCoord = cursorPos.Y; // 获取y坐标
	if (n == 'W') {
		if ((xCoord - 1) < 0) {
			return;
		}
		x = xCoord - 1;
	}
	else if (n == 'S') {
		if ((xCoord + 1) > 28) {
			return;
		}
		x = xCoord + 1;
	}
	else if (n == 'A') {
		if ((yCoord - 1) < 0) {
			return;
		}
		y = yCoord - 1;
	}
	else if (n == 'D') {
		if ((yCoord + 1) > 100) {
			return;
		}
		y = yCoord + 1;
	}
	HANDLE hout;
	COORD pos;
	pos.X = x;
	pos.Y = y;
	hout = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hout, pos);
}

void engret(int ERRORTYPE) {
	if (ERRORTYPE == 1) {
		cout << ERRORT[1];
		cout << CONSTWAIT;
		_getch();
		exit(1);
	}
	else if (ERRORTYPE == 2) {
		cout << ERRORT[2];
		cout << CONSTWAIT;
		_getch();
		exit(2);
	}
	else if (ERRORTYPE == 3) {
		cout << ERRORT[3];
		cout << CONSTWAIT;
		_getch();
		exit(3);
	}
}

void print_Str(string s, int t = 60) {
	for (int i = 0; i <= s.size(); i++) {
		cout << s[i];
		Sleep(t);
	}
}

void wel() {
	string osname;
	system("cls");
	printf("~SLSI_CodeNotepad\n");
	printf("~(c) SLSI 2024\n");
	Sleep(200);
	printf("~Detecting the language...\n");
	// 打开文件
	ifstream file("Language.txt");
	if (!file.is_open()) {
		engret(2);
	}
	string language_name;
	std::unordered_map<std::string, std::string> languageMap = readLanguageFile("Language.txt");
	for (const auto& pair : languageMap) {
		std::cout << "~" << pair.first << " = " << pair.second << std::endl;
		string key = pair.first;
		if (key == "CONSTOPEN") {
			CONSTOPEN = pair.second;
		}
		else if (key == "CONSTNEW") {
			CONSTNEW = pair.second;
		}
		else if (key == "CONSTWAIT") {
			CONSTWAIT = pair.second;
		}
		else if (key == "CONSTLEFT") {
			CONSTLEFT = pair.second;
		}
		else if (key == "CONSTRIGHT") {
			CONSTRIGHT = pair.second;
		}
		else if (key == "CONSTUP") {
			CONSTUP = pair.second;
		}
		else if (key == "CONSTDOWN") {
			CONSTDOWN = pair.second;
		}
		else if (key == "CONSTQUIT") {
			CONSTQUIT = pair.second;
		}
		else if (key == "CONSTPLEASE") {
			CONSTPLEASE = pair.second;
		}
		else if (key == "CONSTOPENPATH") {
			CONSTOPENPATH = pair.second;
		}
		else {
			engret(2);
		}
	}
	Sleep(1000);
	string s = "/";
	CONSTOPENPATH = "打开文件路径(使用" + s + "以代替\\)";
	printf("~Detecting the system type...\n");
	char* os_name = nullptr;
	size_t len = 0;
	errno_t err = _dupenv_s(&os_name, &len, "OS");
	if (err || os_name == nullptr) {
		engret(3);
	}
	osname = os_name;
	if (!(osname.substr(0, 7) == "Windows")) {
		engret(3);
	}
	free(os_name);
	printf("~System type: %s is true\n", osname.c_str());
	Sleep(1000);
	system("cls");
	
	return;
}

void setsize(int col, int row) {
    char cmdd[64] = {};
    snprintf(cmdd, 40, "mode con cols=%d lines=%d\0", col, row);
    system(cmdd);
    return;
}

void open() {
	system("cls");
	gotoxy(0, 0);
	string filepath;
	OpenFileDialog(filepath, 260);
label:
	system("cls");
	ifstream file;
	file.open(filepath);
	if (!file.is_open()) {
		engret(1);
	}
	string line;
	while (getline(file, line)) {
		cout << line << endl;
	}
	cout << "[W-" << CONSTUP << "] [S-" << CONSTDOWN << "] [A-" << CONSTLEFT << "] [D-" << CONSTRIGHT << "] [Q-" << CONSTQUIT << "]\n";
	char move = _getch();
	switch (move) {
	case 'W':gotoU('W'); break;
	case 'S':gotoU('S'); break;
	case 'A':gotoU('A'); break;
	case 'D':gotoU('D'); break;
	case 'Q':return;
	default:break;
	}
	file.close();
	system("cls");
	goto label;
}


void newfile() {

}

void text() {
	while (true) {
		setsize(100, 30);
		system("cls");
		for (int i = 1; i <= 28; i++) {
			cout << "~\n";
		}
		cout << "~[1-" << CONSTOPEN << "]" << "[2-" << CONSTNEW << "]" ;
		char gn = _getch();
		switch (gn) {
			case '1':open(); break;
			case '2':newfile(); break;
		}
	}
}

int main()
{
	SetConsoleTitle(L"SLSI_CodeNotepad");
	wel();
	text();
}
*/
#include <iostream>
#include <windows.h>
#include <conio.h>
#include <commdlg.h>
#include <map>
#include <cstdlib>
#include <fstream>
#include <unordered_map>
#include <string>
#include <vector>
#include <algorithm>
#include <shlobj.h>
#include <sstream>
using namespace std;

map <int, string> ERRORT = { {1, "Openfile ERROR"}, {2, "Languagefile ERROR"}, {3, "Systemtype ERROR"}, {4, "Savefile ERROR"} };

// 所有文本都将从语言文件读取
string CONSTPLEASE;
string CONSTOPEN;
string CONSTNEW;
string CONSTSAVE;
string CONSTWAIT;
string CONSTLEFT;
string CONSTRIGHT;
string CONSTUP;
string CONSTDOWN;
string CONSTQUIT;
string CONSTOPENPATH;
string CONSTSAVEPATH;
string CONSTEDIT;
string CONSTEXITEDIT;
string CONSTVERSION;
string CONSTCOMPANY;
string CONSTCOPYRIGHT;
string CONSTVIEWMODE;
string CONSTEDITMODE;
string CONSTBACK;
string CONSTSETTINGS;
string CONSTLANGUAGE;
string CONSTAUTOEXT;
string CONSTYES;
string CONSTNO;
string CONSTSAVECHANGES;
string CONSTCANCEL;
string CONSTABOUT;
string CONSTDESCRIPTION;
string CONSTAUTHOR;
string CONSTCONFIRM;
string CONSTSELECT;
string CONSTOK;
string CONSTSAVEAS;
string CONSTSAVEASPROMPT;
string CONSTEXTENSION;
string CONSTENABLED;
string CONSTDISABLED;

// 全局设置
string currentLanguage = "Chinese";
string autoExtension = ".txt";
bool autoExtEnabled = true;

// 菜单选项结构
struct MenuItem {
    string text;
    int id;
};

// 语言信息结构
struct LanguageInfo {
    string name;
    string code;
    string displayName;
};

// 可用语言列表
vector<LanguageInfo> availableLanguages;

// 转换为大写字符
char toUpperChar(char c) {
    if (c >= 'a' && c <= 'z') {
        return c - 'a' + 'A';
    }
    return c;
}

// 转换为小写字符
char toLowerChar(char c) {
    if (c >= 'A' && c <= 'Z') {
        return c - 'A' + 'a';
    }
    return c;
}

COORD GetCursorPos()
{
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO bInfo;
    GetConsoleScreenBufferInfo(hOut, &bInfo);
    return bInfo.dwCursorPosition;
}

// 读取INI文件
unordered_map<string, unordered_map<string, string>> readINIFile(const string& filename) {
    unordered_map<string, unordered_map<string, string>> iniData;
    ifstream file(filename);
    string line;
    string currentSection;

    if (!file.is_open()) {
        cerr << "Error opening file: " << filename << endl;
        return iniData;
    }

    while (getline(file, line)) {
        // 移除行首尾的空白字符
        line.erase(0, line.find_first_not_of(" \t"));
        line.erase(line.find_last_not_of(" \t") + 1);

        // 跳过空行和注释
        if (line.empty() || line[0] == ';' || line[0] == '#') {
            continue;
        }

        // 检查是否是节(section)
        if (line[0] == '[' && line[line.length() - 1] == ']') {
            currentSection = line.substr(1, line.length() - 2);
            continue;
        }

        // 解析键值对
        size_t equalPos = line.find('=');
        if (equalPos != string::npos && !currentSection.empty()) {
            string key = line.substr(0, equalPos);
            string value = line.substr(equalPos + 1);

            // 移除键值首尾的空白字符
            key.erase(0, key.find_first_not_of(" \t"));
            key.erase(key.find_last_not_of(" \t") + 1);
            value.erase(0, value.find_first_not_of(" \t"));
            value.erase(value.find_last_not_of(" \t") + 1);

            // 移除值的引号(如果有)
            if (value.length() >= 2 && value[0] == '"' && value[value.length() - 1] == '"') {
                value = value.substr(1, value.length() - 2);
            }

            iniData[currentSection][key] = value;
        }
    }

    file.close();
    return iniData;
}

// 检测可用语言
void detectAvailableLanguages() {
    availableLanguages.clear();

    // 查找语言文件
    vector<string> languageFiles;
    WIN32_FIND_DATAA findFileData;
    HANDLE hFind = FindFirstFileA("Language_*.ini", &findFileData);

    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
                string filename = findFileData.cFileName;
                languageFiles.push_back(filename);
            }
        } while (FindNextFileA(hFind, &findFileData) != 0);
        FindClose(hFind);
    }

    // 读取每个语言文件的信息
    for (const auto& filename : languageFiles) {
        auto iniData = readINIFile(filename);
        if (iniData.count("LanguageInfo") > 0) {
            LanguageInfo info;
            info.code = filename.substr(9, filename.find('.') - 9); // 从 "Language_" 后面开始到 ".ini" 之前
            info.name = iniData["LanguageInfo"].count("Name") ? iniData["LanguageInfo"]["Name"] : info.code;
            info.displayName = iniData["LanguageInfo"].count("DisplayName") ? iniData["LanguageInfo"]["DisplayName"] : info.name;
            availableLanguages.push_back(info);
        }
    }

    // 如果没有找到任何语言文件,使用默认设置
    if (availableLanguages.empty()) {
        LanguageInfo defaultLang;
        defaultLang.code = "Chinese";
        defaultLang.name = "Chinese";
        defaultLang.displayName = "中文";
        availableLanguages.push_back(defaultLang);
    }
}

string OpenFileDialog() {
    char filePath[MAX_PATH] = { 0 };
    cout << CONSTPLEASE << CONSTOPENPATH << ": ";
    cin.getline(filePath, MAX_PATH);

    // 检查文件是否存在
    ifstream testFile(filePath);
    if (!testFile.is_open()) {
        // 如果文件不存在且启用了自动扩展名,尝试添加扩展名
        if (autoExtEnabled && string(filePath).find('.') == string::npos) {
            string newPath = string(filePath) + autoExtension;
            testFile.open(newPath);
            if (testFile.is_open()) {
                testFile.close();
                return newPath;
            }
        }
        testFile.close();
    }
    else {
        testFile.close();
        return string(filePath);
    }

    return string(filePath);
}

string SaveFileDialog() {
    char filePath[MAX_PATH] = { 0 };
    cout << CONSTPLEASE << CONSTSAVEPATH << ": ";
    cin.getline(filePath, MAX_PATH);

    // 如果启用了自动扩展名且没有扩展名,添加扩展名
    if (autoExtEnabled && string(filePath).find('.') == string::npos) {
        return string(filePath) + autoExtension;
    }

    return string(filePath);
}

void gotoxy(int x, int y)
{
    HANDLE hout;
    COORD pos;
    pos.X = x;
    pos.Y = y;
    hout = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hout, pos);
}

void moveCursor(char direction)
{
    COORD cursorPos = GetCursorPos();
    int x = cursorPos.X;
    int y = cursorPos.Y;

    // 转换为大写以确保一致性
    direction = toUpperChar(direction);

    switch (direction) {
    case 'W': if (y > 0) gotoxy(x, y - 1); break;
    case 'S': gotoxy(x, y + 1); break;
    case 'A': if (x > 0) gotoxy(x - 1, y); break;
    case 'D': gotoxy(x + 1, y); break;
    }
}

void engret(int ERRORTYPE) {
    system("cls");
    cout << ERRORT[ERRORTYPE] << endl;
    cout << CONSTWAIT;
    _getch();
    exit(ERRORTYPE);
}

void print_Str(string s, int t = 60) {
    for (size_t i = 0; i < s.size(); i++) {
        cout << s[i];
        Sleep(t);
    }
}

// 显示菜单并返回选中的项目ID
int showMenu(const vector<MenuItem>& items, int startX, int startY) {
    int selected = 0;
    bool selectedConfirmed = false;

    while (!selectedConfirmed) {
        // 显示菜单项
        for (int i = 0; i < items.size(); i++) {
            gotoxy(startX, startY + i);
            if (i == selected) {
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_BLUE | BACKGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
                cout << "> " << items[i].text;
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
            }
            else {
                cout << "  " << items[i].text;
            }

            // 清除该行剩余部分
            int spaces = 50 - items[i].text.length();
            for (int j = 0; j < spaces; j++) {
                cout << " ";
            }
        }

        // 处理键盘输入
        int ch = _getch();
        if (ch == 0 || ch == 0xE0) { // 扩展键
            ch = _getch();
            switch (ch) {
            case 72: // 上箭头
                if (selected > 0) selected--;
                break;
            case 80: // 下箭头
                if (selected < items.size() - 1) selected++;
                break;
            }
        }
        else if (ch == 13) { // 回车键
            selectedConfirmed = true;
        }
        else if (ch == 27) { // ESC键
            return -1;
        }
    }

    return items[selected].id;
}

void loadLanguage(const string& langCode) {
    string filename = "Language_" + langCode + ".ini";
    ifstream testFile(filename);

    // 如果指定的语言文件不存在,使用默认语言
    if (!testFile.is_open()) {
        filename = "Language.ini";
        testFile.open(filename);
        if (!testFile.is_open()) {
            engret(2);
        }
    }
    testFile.close();

    auto languageMap = readINIFile(filename);

    // 加载所有文本常量
    CONSTPLEASE = languageMap.count("Text") && languageMap["Text"].count("Please") ? languageMap["Text"]["Please"] : "请输入";
    CONSTOPEN = languageMap.count("Text") && languageMap["Text"].count("Open") ? languageMap["Text"]["Open"] : "打开";
    CONSTNEW = languageMap.count("Text") && languageMap["Text"].count("New") ? languageMap["Text"]["New"] : "新建";
    CONSTSAVE = languageMap.count("Text") && languageMap["Text"].count("Save") ? languageMap["Text"]["Save"] : "保存";
    CONSTWAIT = languageMap.count("Text") && languageMap["Text"].count("Wait") ? languageMap["Text"]["Wait"] : "按任意键以继续";
    CONSTLEFT = languageMap.count("Text") && languageMap["Text"].count("Left") ? languageMap["Text"]["Left"] : "左";
    CONSTRIGHT = languageMap.count("Text") && languageMap["Text"].count("Right") ? languageMap["Text"]["Right"] : "右";
    CONSTUP = languageMap.count("Text") && languageMap["Text"].count("Up") ? languageMap["Text"]["Up"] : "上";
    CONSTDOWN = languageMap.count("Text") && languageMap["Text"].count("Down") ? languageMap["Text"]["Down"] : "下";
    CONSTQUIT = languageMap.count("Text") && languageMap["Text"].count("Quit") ? languageMap["Text"]["Quit"] : "退出";
    CONSTOPENPATH = languageMap.count("Text") && languageMap["Text"].count("OpenPath") ? languageMap["Text"]["OpenPath"] : "打开路径";
    CONSTSAVEPATH = languageMap.count("Text") && languageMap["Text"].count("SavePath") ? languageMap["Text"]["SavePath"] : "保存路径";
    CONSTEDIT = languageMap.count("Text") && languageMap["Text"].count("Edit") ? languageMap["Text"]["Edit"] : "编辑模式";
    CONSTEXITEDIT = languageMap.count("Text") && languageMap["Text"].count("ExitEdit") ? languageMap["Text"]["ExitEdit"] : "退出编辑模式";
    CONSTVERSION = languageMap.count("Text") && languageMap["Text"].count("Version") ? languageMap["Text"]["Version"] : "版本号";
    CONSTCOMPANY = languageMap.count("Text") && languageMap["Text"].count("Company") ? languageMap["Text"]["Company"] : "TengYve Technology, Inc.";
    CONSTCOPYRIGHT = languageMap.count("Text") && languageMap["Text"].count("Copyright") ? languageMap["Text"]["Copyright"] : "版权所有";
    CONSTVIEWMODE = languageMap.count("Text") && languageMap["Text"].count("ViewMode") ? languageMap["Text"]["ViewMode"] : "查看模式";
    CONSTEDITMODE = languageMap.count("Text") && languageMap["Text"].count("EditMode") ? languageMap["Text"]["EditMode"] : "编辑模式";
    CONSTBACK = languageMap.count("Text") && languageMap["Text"].count("Back") ? languageMap["Text"]["Back"] : "返回主菜单";
    CONSTSETTINGS = languageMap.count("Text") && languageMap["Text"].count("Settings") ? languageMap["Text"]["Settings"] : "设置";
    CONSTLANGUAGE = languageMap.count("Text") && languageMap["Text"].count("Language") ? languageMap["Text"]["Language"] : "语言";
    CONSTAUTOEXT = languageMap.count("Text") && languageMap["Text"].count("AutoExt") ? languageMap["Text"]["AutoExt"] : "自动补全扩展名";
    CONSTYES = languageMap.count("Text") && languageMap["Text"].count("Yes") ? languageMap["Text"]["Yes"] : "是";
    CONSTNO = languageMap.count("Text") && languageMap["Text"].count("No") ? languageMap["Text"]["No"] : "否";
    CONSTSAVECHANGES = languageMap.count("Text") && languageMap["Text"].count("SaveChanges") ? languageMap["Text"]["SaveChanges"] : "是否保存更改?";
    CONSTCANCEL = languageMap.count("Text") && languageMap["Text"].count("Cancel") ? languageMap["Text"]["Cancel"] : "取消";
    CONSTABOUT = languageMap.count("Text") && languageMap["Text"].count("About") ? languageMap["Text"]["About"] : "关于";
    CONSTDESCRIPTION = languageMap.count("Text") && languageMap["Text"].count("Description") ? languageMap["Text"]["Description"] : "描述";
    CONSTAUTHOR = languageMap.count("Text") && languageMap["Text"].count("Author") ? languageMap["Text"]["Author"] : "作者";
    CONSTCONFIRM = languageMap.count("Text") && languageMap["Text"].count("Confirm") ? languageMap["Text"]["Confirm"] : "确认";
    CONSTSELECT = languageMap.count("Text") && languageMap["Text"].count("Select") ? languageMap["Text"]["Select"] : "选择";
    CONSTOK = languageMap.count("Text") && languageMap["Text"].count("OK") ? languageMap["Text"]["OK"] : "确定";
    CONSTSAVEAS = languageMap.count("Text") && languageMap["Text"].count("SaveAs") ? languageMap["Text"]["SaveAs"] : "另存为";
    CONSTSAVEASPROMPT = languageMap.count("Text") && languageMap["Text"].count("SaveAsPrompt") ? languageMap["Text"]["SaveAsPrompt"] : "请输入保存路径";
    CONSTEXTENSION = languageMap.count("Text") && languageMap["Text"].count("Extension") ? languageMap["Text"]["Extension"] : "扩展名";
    CONSTENABLED = languageMap.count("Text") && languageMap["Text"].count("Enabled") ? languageMap["Text"]["Enabled"] : "启用";
    CONSTDISABLED = languageMap.count("Text") && languageMap["Text"].count("Disabled") ? languageMap["Text"]["Disabled"] : "禁用";

    currentLanguage = langCode;
}

void wel() {
    string osname;
    system("cls");
    printf("~TengYve cmd Notepad\n");
    printf("~(c) TengYve Technology, Inc. 2024\n");
    Sleep(200);
    printf("~Detecting the language...\n");

    // 检测可用语言
    detectAvailableLanguages();

    // 加载设置
    ifstream configFile("config.ini");
    if (configFile.is_open()) {
        auto configData = readINIFile("config.ini");
        if (configData.count("Settings")) {
            if (configData["Settings"].count("language")) {
                loadLanguage(configData["Settings"]["language"]);
            }
            if (configData["Settings"].count("auto_extension")) {
                autoExtension = configData["Settings"]["auto_extension"];
            }
            if (configData["Settings"].count("auto_ext_enabled")) {
                autoExtEnabled = (configData["Settings"]["auto_ext_enabled"] == "1");
            }
        }
        configFile.close();
    }
    else {
        // 默认加载第一个可用语言
        if (!availableLanguages.empty()) {
            loadLanguage(availableLanguages[0].code);
        }
        else {
            loadLanguage("Chinese");
        }
    }

    Sleep(1000);
    printf("~Detecting the system type...\n");
    char* os_name = nullptr;
    size_t len = 0;
    errno_t err = _dupenv_s(&os_name, &len, "OS");
    if (err || os_name == nullptr) {
        engret(3);
    }
    osname = os_name;
    if (osname.find("Windows") == string::npos) {
        engret(3);
    }
    free(os_name);
    printf("~System type: %s is true\n", osname.c_str());
    Sleep(1000);
}

void saveConfig() {
    ofstream configFile("config.ini");
    if (configFile.is_open()) {
        configFile << "[Settings]" << endl;
        configFile << "language=" << currentLanguage << endl;
        configFile << "auto_extension=" << autoExtension << endl;
        configFile << "auto_ext_enabled=" << (autoExtEnabled ? "1" : "0") << endl;
        configFile.close();
    }
}

void about() {
    system("cls");
    cout << "~TengYve cmd Notepad v1.0" << endl;
    cout << "~" << CONSTDESCRIPTION << ": A simple text editor" << endl;
    cout << "~" << CONSTAUTHOR << ": TengYve" << endl;
    cout << "~" << CONSTCOMPANY << endl;
    cout << "~" << CONSTCOPYRIGHT << " 2024" << endl;
    cout << endl;
    cout << CONSTWAIT;
    _getch();
}

void settings() {
    vector<MenuItem> settingsItems = {
        {CONSTLANGUAGE + " (" + currentLanguage + ")", 1},
        {CONSTAUTOEXT + " (" + (autoExtEnabled ? CONSTENABLED : CONSTDISABLED) + ")", 2},
        {CONSTABOUT, 3},
        {CONSTBACK, 4}
    };

    if (autoExtEnabled) {
        settingsItems.insert(settingsItems.begin() + 2, { CONSTEXTENSION + ": " + autoExtension, 5 });
    }

    while (true) {
        system("cls");
        cout << "~" << CONSTSETTINGS << endl;

        int choice = showMenu(settingsItems, 2, 2);

        switch (choice) {
        case 1: { // 语言设置
            vector<MenuItem> langItems;
            for (size_t i = 0; i < availableLanguages.size(); i++) {
                langItems.push_back({ availableLanguages[i].displayName + (availableLanguages[i].code == currentLanguage ? " ✓" : ""), static_cast<int>(i + 1) });
            }
            langItems.push_back({ CONSTBACK, static_cast<int>(availableLanguages.size() + 1) });

            system("cls");
            cout << CONSTLANGUAGE << ":" << endl;

            int langChoice = showMenu(langItems, 2, 2);
            if (langChoice > 0 && langChoice <= static_cast<int>(availableLanguages.size())) {
                loadLanguage(availableLanguages[langChoice - 1].code);
                saveConfig();

                // 更新设置菜单项文本
                settingsItems[0].text = CONSTLANGUAGE + " (" + currentLanguage + ")";
                settingsItems[1].text = CONSTAUTOEXT + " (" + (autoExtEnabled ? CONSTENABLED : CONSTDISABLED) + ")";

                // 重新检测语言文件,因为语言可能已更改
                detectAvailableLanguages();
            }
            break;
        }
        case 2: { // 自动扩展名开关
            autoExtEnabled = !autoExtEnabled;
            saveConfig();

            // 更新菜单项
            settingsItems[1].text = CONSTAUTOEXT + " (" + (autoExtEnabled ? CONSTENABLED : CONSTDISABLED) + ")";
            if (autoExtEnabled) {
                settingsItems.insert(settingsItems.begin() + 2, { CONSTEXTENSION + ": " + autoExtension, 5 });
            }
            else {
                // 找到扩展名设置项并移除
                for (auto it = settingsItems.begin(); it != settingsItems.end(); ++it) {
                    if (it->id == 5) {
                        settingsItems.erase(it);
                        break;
                    }
                }
            }
            break;
        }
        case 3: // 关于
            about();
            break;
        case 4: // 返回
            return;
        case 5: { // 扩展名设置
            system("cls");
            cout << CONSTPLEASE << CONSTEXTENSION << " (例如 .txt): ";
            cin >> autoExtension;
            saveConfig();

            // 更新菜单项
            for (auto& item : settingsItems) {
                if (item.id == 5) {
                    item.text = CONSTEXTENSION + ": " + autoExtension;
                    break;
                }
            }
            break;
        }
        }
    }
}

void setsize(int col, int row) {
    char cmdd[64] = {};
    snprintf(cmdd, sizeof(cmdd), "mode con cols=%d lines=%d", col, row);
    system(cmdd);
}

// 另存为功能
bool saveAs(vector<string>& lines) {
    system("cls");
    cout << CONSTSAVEASPROMPT << ": ";

    char filePath[MAX_PATH] = { 0 };
    cin.getline(filePath, MAX_PATH);

    // 如果启用了自动扩展名且没有扩展名,添加扩展名
    string savePath = filePath;
    if (autoExtEnabled && savePath.find('.') == string::npos) {
        savePath += autoExtension;
    }

    ofstream outFile(savePath);
    if (!outFile.is_open()) {
        cout << "保存失败!" << endl;
        cout << CONSTWAIT;
        _getch();
        return false;
    }

    for (const auto& l : lines) {
        outFile << l << endl;
    }
    outFile.close();

    cout << CONSTSAVE << CONSTOK << "!" << endl;
    cout << CONSTWAIT;
    _getch();
    return true;
}

bool editMode(const string& filepath, bool isNewFile = false) {
    system("cls");

    // 读取文件内容
    ifstream inFile(filepath);
    vector<string> lines;
    string line;
    bool modified = false;
    bool hasBeenSaved = !isNewFile; // 新建文件时初始为未保存状态

    if (isNewFile) {
        lines.push_back(""); // 新建文件时添加一个空行
    }
    else {
        while (getline(inFile, line)) {
            lines.push_back(line);
        }
        inFile.close();

        // 如果文件为空,添加一个空行
        if (lines.empty()) {
            lines.push_back("");
        }
    }

    // 显示文件内容
    for (size_t i = 0; i < lines.size(); i++) {
        cout << lines[i] << endl;
    }

    // 进入编辑模式 - 根据文件类型显示不同的提示信息
    if (isNewFile) {
        cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVEAS << ": Ctrl+A]\n";
    }
    else {
        cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
    }

    int currentLine = 0;
    int currentPos = 0;
    gotoxy(currentPos, currentLine);

    bool editing = true;
    while (editing) {
        if (_kbhit()) {
            int ch = _getch();

            // 检查控制键
            if (ch == 0 || ch == 0xE0) {
                ch = _getch(); // 获取扩展键码
                switch (ch) {
                case 72: // 上箭头
                    if (currentLine > 0) {
                        currentLine--;
                        currentPos = min(currentPos, (int)lines[currentLine].length());
                        gotoxy(currentPos, currentLine);
                    }
                    break;
                case 80: // 下箭头
                    if (currentLine < (int)lines.size() - 1) {
                        currentLine++;
                        currentPos = min(currentPos, (int)lines[currentLine].length());
                        gotoxy(currentPos, currentLine);
                    }
                    break;
                case 75: // 左箭头
                    if (currentPos > 0) {
                        currentPos--;
                        gotoxy(currentPos, currentLine);
                    }
                    else if (currentLine > 0) {
                        currentLine--;
                        currentPos = lines[currentLine].length();
                        gotoxy(currentPos, currentLine);
                    }
                    break;
                case 77: // 右箭头
                    if (currentPos < (int)lines[currentLine].length()) {
                        currentPos++;
                        gotoxy(currentPos, currentLine);
                    }
                    else if (currentLine < (int)lines.size() - 1) {
                        currentLine++;
                        currentPos = 0;
                        gotoxy(currentPos, currentLine);
                    }
                    break;
                }
            }
            else if (ch == 19 && !isNewFile) { // Ctrl+S 保存 (仅对已存在文件有效)
                ofstream outFile(filepath);
                for (const auto& l : lines) {
                    outFile << l << endl;
                }
                outFile.close();
                cout << "\n" << CONSTSAVE << CONSTOK << "!";
                modified = false;
                hasBeenSaved = true;
                Sleep(1000);
                system("cls");
                for (size_t i = 0; i < lines.size(); i++) {
                    cout << lines[i] << endl;
                }
                cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                gotoxy(currentPos, currentLine);
            }
            else if (ch == 1) { // Ctrl+A 另存为 (对所有文件有效)
                bool saveResult = saveAs(lines);
                if (saveResult) {
                    modified = false;
                    hasBeenSaved = true;
                    // 如果是新建文件且第一次保存,可以启用常规保存功能
                    if (isNewFile && hasBeenSaved) {
                        isNewFile = false;
                    }
                }
                system("cls");
                for (size_t i = 0; i < lines.size(); i++) {
                    cout << lines[i] << endl;
                }
                if (isNewFile) {
                    cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                }
                else {
                    cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                }
                gotoxy(currentPos, currentLine);
            }
            else if (ch == 17) { // Ctrl+Q 退出编辑
                if (modified) {
                    system("cls");
                    cout << CONSTSAVECHANGES << "?" << endl;

                    vector<MenuItem> saveItems = {
                        {CONSTYES, 1},
                        {CONSTNO, 2},
                        {CONSTCANCEL, 3}
                    };

                    int saveChoice = showMenu(saveItems, 2, 2);
                    if (saveChoice == 1) {
                        // 如果是新建文件且未保存过,需要先另存为
                        if (isNewFile && !hasBeenSaved) {
                            bool saveResult = saveAs(lines);
                            if (!saveResult) {
                                system("cls");
                                for (size_t i = 0; i < lines.size(); i++) {
                                    cout << lines[i] << endl;
                                }
                                if (isNewFile) {
                                    cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                                }
                                else {
                                    cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                                }
                                gotoxy(currentPos, currentLine);
                                continue;
                            }
                        }
                        else {
                            ofstream outFile(filepath);
                            for (const auto& l : lines) {
                                outFile << l << endl;
                            }
                            outFile.close();
                        }
                    }
                    else if (saveChoice == 3) {
                        system("cls");
                        for (size_t i = 0; i < lines.size(); i++) {
                            cout << lines[i] << endl;
                        }
                        if (isNewFile) {
                            cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                        }
                        else {
                            cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                        }
                        gotoxy(currentPos, currentLine);
                        continue;
                    }
                }
                editing = false;
            }
            else if (ch == 13) { // 回车键
                string newLine = lines[currentLine].substr(currentPos);
                lines[currentLine] = lines[currentLine].substr(0, currentPos);
                lines.insert(lines.begin() + currentLine + 1, newLine);
                currentLine++;
                currentPos = 0;
                modified = true;
                system("cls");
                for (size_t i = 0; i < lines.size(); i++) {
                    cout << lines[i] << endl;
                }
                if (isNewFile) {
                    cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                }
                else {
                    cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                }
                gotoxy(currentPos, currentLine);
            }
            else if (ch == 8) { // 退格键
                if (currentPos > 0) {
                    lines[currentLine].erase(currentPos - 1, 1);
                    currentPos--;
                    modified = true;
                    system("cls");
                    for (size_t i = 0; i < lines.size(); i++) {
                        cout << lines[i] << endl;
                    }
                    if (isNewFile) {
                        cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                    }
                    else {
                        cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                    }
                    gotoxy(currentPos, currentLine);
                }
                else if (currentLine > 0) {
                    string currentLineText = lines[currentLine];
                    lines.erase(lines.begin() + currentLine);
                    currentLine--;
                    currentPos = lines[currentLine].length();
                    lines[currentLine] += currentLineText;
                    modified = true;
                    system("cls");
                    for (size_t i = 0; i < lines.size(); i++) {
                        cout << lines[i] << endl;
                    }
                    if (isNewFile) {
                        cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                    }
                    else {
                        cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                    }
                    gotoxy(currentPos, currentLine);
                }
            }
            else {
                // 普通字符输入
                lines[currentLine].insert(currentPos, 1, (char)ch);
                currentPos++;
                modified = true;
                system("cls");
                for (size_t i = 0; i < lines.size(); i++) {
                    cout << lines[i] << endl;
                }
                if (isNewFile) {
                    cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                }
                else {
                    cout << "\n[" << CONSTEXITEDIT << ": Ctrl+Q] [" << CONSTSAVE << ": Ctrl+S] [" << CONSTSAVEAS << ": Ctrl+A]\n";
                }
                gotoxy(currentPos, currentLine);
            }
        }
        Sleep(10);
    }

    return modified;
}

void open() {
    system("cls");
    string filepath = OpenFileDialog();

    ifstream file;
    file.open(filepath);
    if (!file.is_open()) {
        engret(1);
    }
    file.close();

    // 进入查看/编辑模式选择
    system("cls");
    cout << CONSTSELECT << ":" << endl;

    vector<MenuItem> modeItems = {
        {CONSTVIEWMODE, 1},
        {CONSTEDITMODE, 2},
        {CONSTBACK, 3}
    };

    int mode = showMenu(modeItems, 2, 2);

    if (mode == 2) {
        editMode(filepath, false);
    }
    else if (mode == 1) {
        system("cls");
        ifstream viewFile(filepath);
        string line;
        while (getline(viewFile, line)) {
            cout << line << endl;
        }
        viewFile.close();

        cout << "\n[W-" << CONSTUP << "] [S-" << CONSTDOWN << "] [A-" << CONSTLEFT << "] [D-" << CONSTRIGHT << "] [Q-" << CONSTQUIT << "]\n";

        while (true) {
            char move = toUpperChar(_getch());
            switch (move) {
            case 'W': moveCursor('W'); break;
            case 'S': moveCursor('S'); break;
            case 'A': moveCursor('A'); break;
            case 'D': moveCursor('D'); break;
            case 'Q': return;
            default: break;
            }
        }
    }
}

void newfile() {
    system("cls");
    string filepath = "Untitled.txt"; // 临时文件名,实际保存时会要求用户输入

    editMode(filepath, true); // 传入 true 表示是新建文件
}
void text() {
    vector<MenuItem> mainItems = {
        {CONSTOPEN, 1},
        {CONSTNEW, 2},
        {CONSTSETTINGS, 3},
        {CONSTQUIT, 4}
    };

    while (true) {
        setsize(100, 30);
        system("cls");
        cout << "~TengYve cmd Notepad v1.0\n";
        cout << "~" << CONSTCOPYRIGHT << " " << CONSTCOMPANY << " 2024\n";

        int choice = showMenu(mainItems, 2, 4);

        switch (choice) {
        case 1: open(); break;
        case 2: newfile(); break;
        case 3: settings(); break;
        case 4: return;
        default: break;
        }
    }
}

int main()
{
    SetConsoleTitle(L"TengYve cmd Notepad");
    wel();
    text();
    return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
//   WIN平台版本

本程序使用CC-BY-NC-SA开源协议.二次发布、转发必须署名(即TengYve Technology ,Inc.),禁止用作商业用途,二次修改/发布必须使用同样的CC-BY-NC-SA开源协议,以及不得增设法律条款或技术措施(如DRM数字版权管理)来限制他人做本许可协议允许的事.

下面是开源协议链接:

https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.zh-hans

站内副本:https://www.17noi.cn/discuss/68a816948e14e43430cd1dee

Copyright (c) 2025 TengYve Technology. All rights reserved.

2 条评论

  • @ 2025-8-22 15:05:33
    • @ 2025-8-22 14:45:27

      文件名:Language_Chinese.ini

      内容:

      [LanguageInfo]
      Name=Chinese
      DisplayName=中文
      
      [Text]
      Please=请输入
      Open=打开
      New=新建
      Save=保存
      Wait=按任意键以继续
      Left=左
      Right=右
      Up=上
      Down=下
      Quit=退出
      OpenPath=打开路径
      SavePath=保存路径
      Edit=编辑模式
      ExitEdit=退出编辑模式
      Version=版本号
      Company=TengYve Technology, Inc.
      Copyright=版权所有
      ViewMode=查看模式
      EditMode=编辑模式
      Back=返回主菜单
      Settings=设置
      Language=语言
      AutoExt=自动补全扩展名
      Yes=是
      No=否
      SaveChanges=是否保存更改?
      Cancel=取消
      About=关于
      Description=描述
      Author=作者
      Confirm=确认
      Select=选择
      OK=确定
      SaveAs=另存为
      SaveAsPrompt=请输入保存路径
      Extension=扩展名
      Enabled=启用
      Disabled=禁用
      
      • 1