- 编程
文本编辑器开源锚点
- 2025-8-22 14:44:24 @
欢迎下载打包后的版本!
欢迎大佬们转移成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 条评论
-
方均宸 LV 9 @ 2025-8-22 15:05:33
站内的CC-BY-NC-SA副本:https://www.17noi.cn/discuss/68a816948e14e43430cd1dee
-
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