From 9672ebd079a15048edbbb3fb633f3f5fea4c063a Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Sun, 25 Feb 2024 18:59:39 +0800 Subject: [PATCH] fix: font style not correct when painting --- RedPandaIDE/RedPandaIDE.pro | 6 +- RedPandaIDE/translations/RedPandaIDE_pt_BR.ts | 10 +- RedPandaIDE/translations/RedPandaIDE_zh_CN.ts | 772 +++++++++--------- RedPandaIDE/translations/RedPandaIDE_zh_TW.ts | 10 +- Red_Panda_CPP.pro | 2 - libs/qsynedit/qsynedit/document.cpp | 173 +++- libs/qsynedit/qsynedit/document.h | 34 +- libs/qsynedit/qsynedit/painter.cpp | 393 +++++---- libs/qsynedit/qsynedit/painter.h | 34 +- libs/qsynedit/qsynedit_zh_CN.ts | 14 +- 10 files changed, 849 insertions(+), 599 deletions(-) diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index f1fecf1b..0a6ee8ee 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -17,6 +17,8 @@ APP_NAME = RedPandaCPP APP_VERSION = 2.27 +APP_VERSION_SUFFIX = alpha + # TEST_VERSION = beta2 system(git rev-list HEAD --count): TEST_VERSION = $$system(git rev-list HEAD --count) @@ -57,9 +59,9 @@ DEFINES += PREFIX=\\\"$${PREFIX}\\\" DEFINES += LIBEXECDIR=\\\"$${LIBEXECDIR}\\\" DEFINES += APP_NAME=\\\"$${APP_NAME}\\\" isEmpty(TEST_VERSION) { - DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}\\\" + DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}$${APP_VERSION_SUFFIX}\\\" } else { - DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}.$${TEST_VERSION}\\\" + DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}$${APP_VERSION_SUFFIX}.$${TEST_VERSION}\\\" } win32 { _WINDOWS_PREFER_OPENCONSOLE = $$(WINDOWS_PREFER_OPENCONSOLE) diff --git a/RedPandaIDE/translations/RedPandaIDE_pt_BR.ts b/RedPandaIDE/translations/RedPandaIDE_pt_BR.ts index c1f9e754..d33fb003 100644 --- a/RedPandaIDE/translations/RedPandaIDE_pt_BR.ts +++ b/RedPandaIDE/translations/RedPandaIDE_pt_BR.ts @@ -5159,10 +5159,6 @@ Toggle Readonly - - Line: %1 Col: %2 Lines: %3 - - Newline @@ -5420,7 +5416,11 @@ - Line: %1 Col: %2 Sel:%3 Lines: %4 + Line: %1 Char: %2 Sel:%3 Lines: %4 + + + + Line: %1 Char: %2 Lines: %3 diff --git a/RedPandaIDE/translations/RedPandaIDE_zh_CN.ts b/RedPandaIDE/translations/RedPandaIDE_zh_CN.ts index 28d86d1d..40673f19 100644 --- a/RedPandaIDE/translations/RedPandaIDE_zh_CN.ts +++ b/RedPandaIDE/translations/RedPandaIDE_zh_CN.ts @@ -1607,24 +1607,24 @@ p, li { white-space: pre-wrap; } 要剪切的内容超过了字符数限制! - + hex: %1 16进制: %1 - + dec: %1 十进制: %1 - + Print Document 打印文档 - - - + + + Ctrl+click for more info Ctrl+单击以获取更多信息 @@ -1633,27 +1633,27 @@ p, li { white-space: pre-wrap; } 未找到符号'%1'! - + astyle not found 找不到astyle程序 - + Can't find astyle in "%1". 找不到astyle程序"%1". - + Break point condition 断点条件 - + Enter the condition of the breakpoint: 输入当前断点的生效条件: - + Readonly 只读 @@ -2506,12 +2506,12 @@ p, li { white-space: pre-wrap; } 表单 - + Theme: 主题: - + Use custom theme 使用自定义主题 @@ -2521,12 +2521,12 @@ p, li { white-space: pre-wrap; } 图标集: - + Use custom icon set 使用自定义图标 - + Icon Zoom: 图标缩放: @@ -2536,17 +2536,17 @@ p, li { white-space: pre-wrap; } 字体: - + Language: 语言: - + *Needs restart *需要重启之后生效 - + Font Size: 大小: @@ -4472,18 +4472,18 @@ p, li { white-space: pre-wrap; } MainWindow - + Red Panda C++ 小熊猫C++ - - - + + + Issues 编译器 @@ -4557,7 +4557,7 @@ p, li { white-space: pre-wrap; } - + Debug Console 调试主控台 @@ -4633,7 +4633,7 @@ p, li { white-space: pre-wrap; } 工具栏2 - + New 新建 @@ -4766,9 +4766,9 @@ p, li { white-space: pre-wrap; } - - - + + + Copy 复制 @@ -4779,7 +4779,7 @@ p, li { white-space: pre-wrap; } - + Paste 粘贴 @@ -4790,8 +4790,8 @@ p, li { white-space: pre-wrap; } - - + + Select All 选择全部 @@ -4915,38 +4915,38 @@ p, li { white-space: pre-wrap; } - - + + New Problem Set 新建试题集 - + Add Problem 添加试题 - + Remove Problem 删除试题 - - + + Save Problem Set 保存试题集 - - + + Load Problem Set 载入试题集 @@ -4994,7 +4994,7 @@ p, li { white-space: pre-wrap; } - + Remove Problem Case Remove Problem Set 删除试题案例 @@ -5002,21 +5002,21 @@ p, li { white-space: pre-wrap; } - + Open Anwser Source File 打开答案源代码文件 - + Run All Cases Run Current Case 运行所有案例 - + Problem Cases Validation Options 测试案例验证选项 @@ -5076,15 +5076,15 @@ p, li { white-space: pre-wrap; } - - + + Import FPS Problem Set 导入FPS试题集 - - + + Export FPS Problem Set 导出FPS试题集 @@ -5335,7 +5335,7 @@ p, li { white-space: pre-wrap; } - + Clear all breakpoints 删除所有断点 @@ -5699,7 +5699,7 @@ p, li { white-space: pre-wrap; } 保存为模板... - + New File 新建文件 @@ -5740,7 +5740,7 @@ p, li { white-space: pre-wrap; } - + Rename Symbol 重命名符号 @@ -5761,13 +5761,13 @@ p, li { white-space: pre-wrap; } - + Export As RTF 导出为RTF - + Export As HTML 导出为HTML @@ -6036,42 +6036,42 @@ p, li { white-space: pre-wrap; } 运行参数... - + File Encoding 文件编码 - + Recent Files 文件历史 - - - - - - + + + + + + Debugging 正在调试 - - - - - - + + + + + + Running 正在运行 - - - - - - + + + + + + Compiling 正在编译 @@ -6085,17 +6085,17 @@ p, li { white-space: pre-wrap; } 行: %1 列: %2 已选择 :%3 总行数: %4 总长度: %5 - + Read Only 只读 - + Insert 插入 - + Overwrite 覆写 @@ -6112,7 +6112,7 @@ p, li { white-space: pre-wrap; } 确认 - + Source file is not compiled. 源文件尚未编译。 @@ -6129,39 +6129,39 @@ p, li { white-space: pre-wrap; } 重新编译? - - - + + + Wrong Compiler Settings 错误的编译器设置 - - - + + + Compiler is set not to generate executable. 编译器被设置为不生成可执行文件。 - - + + We need the executabe to run problem case. 我们需要可执行文件来运行试题案例。 - + No compiler set 无编译器设置 - + No compiler set is configured. 没有配置编译器设置。 - + Can't start debugging. 无法启动调试器 @@ -6182,33 +6182,33 @@ p, li { white-space: pre-wrap; } 项目尚未构建。是否构建? - + Host applcation missing 宿主程序不存在 - + DLL project needs a host application to run. 动态链接库(DLL)需要一个宿主程序来运行。 - + But it's missing. 但它不存在。 - + Host application not exists 宿主程序不存在 - + Host application file '%1' doesn't exist. 宿主程序'%1'不存在。 - - + + Please correct this before start debugging 请在调试前改正设置。 @@ -6217,8 +6217,8 @@ p, li { white-space: pre-wrap; } 重新编译? - - + + Save last open info error 保存上次打开信息失败 @@ -6227,37 +6227,37 @@ p, li { white-space: pre-wrap; } 无法删除旧上次打开信息文件'%1' - + Can't save last open info file '%1' 无法保存上次打开信息文件'%1' - - + + Load last open info error 载入上次打开信息失败 - - + + Can't load last open info file '%1' 无法载入上次打开信息文件'%1' - + Open Source File 打开源代码文件 - - - + + + Correct compile settings for debug 纠正调试用编译设置 - - + + The generated executable won't have debug symbol infos, and can't be debugged. 生成的可执行文件中会缺少调试符号信息,因此无法编译。 @@ -6266,81 +6266,81 @@ p, li { white-space: pre-wrap; } 如果你正在使用Release版的编译器设置集,请在工具栏中将其改为Debug版本。 - - - + + + Or you can manually change the following settings in the options dialog's compiler set page: 您也可以手动在选项对话框的编译器设置页中修正下列选项: - - - + + + - Turned on the "Generate debug info (-g3)" option. - 打开“生成调试信息(-g3)"选项. - - - + + + - Turned off the "Strip executable (-s)" option. - 关闭"剥除附加信息(-s)"选项. - - - + + + - Turned off the "Optimization level (-O)" option or set it to "Debug (-Og)". - 关闭"优化级别(-O)选项,或将其设置为"调试(-Og)"级别. - - - - + + + + You should recompile after change the compiler set or it's settings. 在更换编译器设置集或修改其设置后,需要重新编译. - - - + + + Do you want to mannually change the compiler set settings now? 您现在就要手动修改编译器设置集的设置吗? - - + + Batch Set Cases 批量设置案例 - + Show detail debug logs 显示详细调试器日志 - + Copy all 全部复制 - + Go to Line 跳转到行 - + Line - + Template Exists 模板已存在 - + Template %1 already exists. Do you want to overwrite? 模板%1已存在。是否覆盖? @@ -6348,25 +6348,25 @@ p, li { white-space: pre-wrap; } - - - + + + Clear 清除 - + Export 导出 - + Insert Snippet 插入代码段 - - + + Problem Set %1 试题集%1 @@ -6395,56 +6395,66 @@ p, li { white-space: pre-wrap; } 项目已经被修改过,是否需要重新构建? - + Auto Save Error 自动保存出错 - + Auto save "%1" to "%2" failed:%3 自动保存"%1"到"%2"失败:%3 - + Properties... 试题属性... - + Set Problem Set Name 设置试题集名称 - + Problem Set Name: 试题集名称: - + Remove 删除 - + + Line: %1 Char: %2 Sel:%3 Lines: %4 + + + + + Line: %1 Char: %2 Lines: %3 + + + + Remove All Bookmarks 删除全部书签 - + Modify Description 修改描述 - - - + + + Bookmark Description 书签描述 - - - + + + Description: 描述: @@ -6453,70 +6463,69 @@ p, li { white-space: pre-wrap; } 在调试主控台中显示调试器输出 - + Remove this search 清除这次搜索 - + Clear all searches 删除所有搜索 - + Breakpoint condition... 断点条件... - + Break point condition 断点条件 - + Enter the condition of the breakpoint: 输入当前断点的生效条件: - + Remove All Breakpoints Remove all breakpoints 删除所有断点 - Line: %1 Col: %2 Sel:%3 Lines: %4 - 行: %1 列: %2 选中:%3 总行数: %4 + 行: %1 列: %2 选中:%3 总行数: %4 - + Remove Breakpoint 删除当前断点 - + Rename File 重命名文件 - - + + Add Folder 添加文件夹 - - + + New folder 新文件夹 - + Folder name: 文件夹: - + Rename Folder 重命名 @@ -6529,24 +6538,23 @@ p, li { white-space: pre-wrap; } 要现在去修改设置吗? - + Rename Problem Set 修改试题集名称 - + Can't open last open information file '%1' for write! 无法写入配置文件'%1'。 - + Rename Problem 修改试题名称 - Line: %1 Col: %2 Lines: %3 - 行: %1 列: %2 总行数: %3 + 行: %1 列: %2 总行数: %3 Correct compiler setting @@ -6569,12 +6577,12 @@ p, li { white-space: pre-wrap; } 是否现在去改正? - + Missing Project Files 项目文件缺失 - + The following files is missing, can't build the project: 下列项目文件缺失,无法构建项目: @@ -6591,202 +6599,202 @@ p, li { white-space: pre-wrap; } 请取消该设置,重新编译然后重新启动调试。 - + Goto Url 跳转到试题网址 - + Add Problem Case 添加试题案例 - + Run Current Case 运行当前案例 - + Remove Folder 删除文件夹 - + Switch to normal view 切换为普通视图 - + Switch to custom view 切换为自定义视图 - + Sort By Type 按类型排序 - + Sort alphabetically 按名称排序 - + Show inherited members 显示继承的成员 - + Goto declaration 跳转到声明处 - + Goto definition 跳转到定义处 - + In current file 仅当前文件 - + In current project 整个项目 - - + + New Folder 新建文件夹 - + Rename 重命名 - - + - - + + + Delete 删除 - + Open in Editor 在编辑器中打开 - + Open in External Program 使用外部程序打开 - + Open in Terminal 在终端中打开 - + Open in Windows Explorer 在文件资源管理器中打开 - + Character sets 字符集 - + Convert to %1 转换为%1编码 - + Newline 换行符 - + %1 files autosaved 已自动保存%1个文件 - + Set answer to... 设置答案源代码... - + select other file... 选择其他文件... - + Select Answer Source File 选择答案源代码文件 - + Watchpoint hitted 变量断点被触发 - + Value of "%1" has changed: "%1"的值发生了变化: - + New value: %1 新值: %1 - + Project folder removed. 项目文件夹被删除 - + Folder for project '%1' was removed. 项目"%1"的文件夹已被外部程序删除. - + It will be closed. 项目将被关闭. - + Save settings failed! 保存设置失败 - + Folder Not Empty 文件夹非空 - + The project folder is not empty, existing files may be overwritten. 项目文件夹不是空的,已有的文件可能会被覆盖。 - + Do you want to proceed? 您确定要继续吗? - + Watchpoint variable name 被监控的变量 - + Stop execution when the following variable is modified (it must be visible from the currect scope): 当下面的变量被修改时暂停执行(该变量必须可以从当前程序处访问): @@ -6795,17 +6803,17 @@ p, li { white-space: pre-wrap; } 中止 - + FPS Problem Set Files (*.fps;*.xml) FPS试题集文件(*.fps;*.xml) - + FPS Problem Set Files (*.fps) FPS试题集文件(*.fps) - + Export Error 导出时出错 @@ -6815,7 +6823,7 @@ p, li { white-space: pre-wrap; } C/C++源代码文件 (*.c *.cpp *.cc *.cxx) - + New Folder %1 新建文件夹%1 @@ -6828,13 +6836,13 @@ p, li { white-space: pre-wrap; } 无标题%1 - + Do you really want to delete %1? 你真的要删除%1吗? - + Do you really want to delete %1 files? 你真的要删除%1个文件吗? @@ -6847,7 +6855,7 @@ p, li { white-space: pre-wrap; } 变量"%1"有改动: - + Old value: %1 旧值: %1 @@ -6856,63 +6864,63 @@ p, li { white-space: pre-wrap; } 新值: %1 - + Save project 保存项目 - + The project '%1' has modifications. 项目'%1'有改动。 - - + + Do you want to save it? 需要保存吗? - - + + File Changed 文件已发生变化 - - - + + + New Project File? 新建项目文件? - - - + + + Do you want to add the new file to the project? 您是否要将新建的文件加入项目? - - - - - + + + + + Save Error 保存失败 - + Change Project Compiler Set 改变项目编译器配置集 - + Change the project's compiler set will lose all custom compiler set options. 改变项目的编译器配置集会导致所有的自定义编译器选项被重置。 - - + + Do you really want to do that? 你真的想要那么做吗? @@ -6921,12 +6929,12 @@ p, li { white-space: pre-wrap; } 批量设置案例 - + Choose input files 选择输入数据文件 - + Input data files (*.in) 输入数据文件 (*.in) @@ -6935,78 +6943,78 @@ p, li { white-space: pre-wrap; } 无标题%1 - + Modify Watch 修改监视表达式 - + Watch Expression 监视表达式 - + Do you really want to clear all breakpoints in this file? 您真的要清除该文件的所有断点吗? - + New project 新建项目 - + Close %1 and start new project? 关闭'%1'以打开新项目? - + Folder not exist 文件夹不存在 - + Folder '%1' doesn't exist. Create it now? 文件夹'%1'不存在。是否创建? - + Can't create folder 无法创建文件夹 - + Failed to create folder '%1'. 创建文件夹'%1'失败。 - + Save new project as - + Folder %1 is not empty. 文件夹%1不是空的。 - + Do you really want to delete it? 你真的要删除它吗? - + Change working folder 改变工作文件夹 - + File '%1' is not in the current working folder. File '%1' is not in the current working folder 文件'%1'不在当前工作文件夹中。 - + Do you want to change working folder to '%1'? 是否将工作文件夹改设为'%1'? @@ -7015,28 +7023,28 @@ p, li { white-space: pre-wrap; } 正在删除试题... - + Can't Commit 无法提交 - + Git needs user info to commit. Git需要用信息进行提交。 - + Choose Input Data File 选择输入数据文件 - - + + All files (*.*) 所有文件 (*.*) - + Choose Expected Output Data File Choose Expected Input Data File 选择期望输出文件 @@ -7048,59 +7056,59 @@ p, li { white-space: pre-wrap; } - + Choose Working Folder 选择工作文件夹 - - + + Header Exists 头文件已存在 - - + + Header file "%1" already exists! 头文件"%1"已存在! - + Source Exists 源文件已存在! - + Source file "%1" already exists! 源文件"%1"已存在! - + Can't commit! 无法提交! - + The following files are in conflicting: 下列文件处于冲突状态,请解决后重新添加和提交: - + Commit Message 提交信息 - + Commit Message: 提交信息: - + Commit Failed 提交失败 - + Commit message shouldn't be empty! 提交信息不能为空! @@ -7109,22 +7117,22 @@ p, li { white-space: pre-wrap; } 小熊猫Dev-C++项目文件 (*.dev) - + New project fail 新建项目失败 - + Can't assign project template 无法使用模板创建项目 - + Remove file 删除文件 - + Remove the file from disk? 同时从硬盘上删除文件? @@ -7133,27 +7141,27 @@ p, li { white-space: pre-wrap; } 无标题 - + New Project File Name 新的项目文件名 - + File Name: 文件名: - + File Already Exists! 文件已存在! - + File '%1' already exists! 文件'%1'已经存在! - + Add to project 添加到项目 @@ -7170,12 +7178,12 @@ p, li { white-space: pre-wrap; } 请在工具栏中选择Debug编译器配置集,或者在“编译器配置集”设置的“编译/链接选项”页中<b>启用</b>“生成调试信息(-g3)”、<b>禁用</b>“剥除附件信息(-3)”。 - + C/C++ Source Files (*.c *.cpp *.cc *.cxx) C/C++源代码文件 (*.c *.cpp *.cc *.cxx) - + This operation will remove all cases for the current problem. 本操作会删除此试题的所有案例。 @@ -7184,7 +7192,7 @@ p, li { white-space: pre-wrap; } 调试失败 - + The executable doesn't have symbol table, and can't be debugged. 可执行文件中没有符号表信息,无法调试。 @@ -7209,123 +7217,123 @@ p, li { white-space: pre-wrap; } 您也可以删除所有断点,打开“CPU信息窗口”,然后调试汇编代码。 - + Failed to generate the executable. 未能生成可执行文件。 - + Please check detail info in "Tools Output" panel. 请查看“工具输出”面板中的详细信息。 - + Red Panda C++ project file (*.dev) 小熊猫C++项目文件(*.dev) - + Rename Error 重命名出错 - + Symbol '%1' is defined in system header. 符号'%1'在系统头文件中定义,无法修改。 - + New Name 新名称 - - - - + + + + Replace Error 替换出错 - + Can't open file '%1' for replace! 无法打开文件'%1'进行替换! - + Contents has changed since last search! 内容和上次查找时不一致。 - + Rich Text Format Files (*.rtf) RTF格式文件 (*.rtf) - + HTML Files (*.html) HTML文件 (*.html) - + The current problem set is not empty. 当前的试题集不是空的。 - + Problem %1 试题%1 - - + + Problem Set Files (*.pbs) 试题集文件 (*.pbs) - - + + Load Error 载入失败 - - + + Problem Case %1 试题案例%1 - - - - - - - - - - - - - - + + + + + + + + + + + + + + Error 错误 - + Recent Projects 项目历史 - - + + Load Theme Error 载入主题失败 - - + + Clear History 清除历史 @@ -7334,8 +7342,8 @@ p, li { white-space: pre-wrap; } 编译生成的可执行文件中没有符号表,无法被调试。 - - + + Version Control 版本控制 @@ -7344,61 +7352,61 @@ p, li { white-space: pre-wrap; } 请在工具栏中选用Debug编译器配置集,或者在选项对话框的编辑器配置集页中勾选“生成调试信息(-g3)"选项。 - + File '%1' was changed. 磁盘文件'%1'已被修改。 - + Reload its content from disk? 是否重新读取它的内容? - + File '%1' was removed. 磁盘文件'%1'已被删除。 - + Keep it open? 是否保持它在小熊猫C++中打开的编辑窗口? - + Open 打开 - - + + Compile Failed 编译失败 - + Run Failed 运行失败 - - - - + + + + Confirm Convertion 确认转换 - + Exact 完全一致 - + Ignore leading/trailing spaces 忽略行首/行尾空格 - + Ignore spaces 忽略多余空格 @@ -7407,43 +7415,43 @@ p, li { white-space: pre-wrap; } 行: %1 列: %2 (%3个字符) 总行数: %4 - - - + + + If you are using the Release compiler set, please use choose the Debug version from toolbar. 如果你正在使用Release版的编译器设置集,请在工具栏中将其改为Debug版本。 - - - - + + + + The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue? 当前编辑器中的文件将会使用%1编码保存。<br />这项操作无法被撤回。<br />你确定要继续吗? - + New Watch Expression 新监视表达式 - + Enter Watch Expression (it is recommended to use 'this->' for class members): 输入监视表达式 - + Parsing file %1 of %2: "%3" (%1/%2)正在解析文件"%3" - - + + Done parsing %1 files in %2 seconds 完成%1个文件的解析,用时%2秒 - + (%1 files per second) (每秒%1个文件) @@ -8847,7 +8855,7 @@ p, li { white-space: pre-wrap; } QFileSystemModel - + <b>The name "%1" cannot be used.</b><p>Try using another name, with fewer characters or no punctuation marks. <b>文件名 "%1" 无法被使用!</b><p>可能是重名、过长、为空或者是使用了不能出现在文件名里的符号。 @@ -8856,13 +8864,13 @@ p, li { white-space: pre-wrap; } QObject - + Save 保存 - + Save changes to %1? 将修改保存到"%1"? @@ -10870,18 +10878,18 @@ p, li { white-space: pre-wrap; } 性能 - - - - + + + + Compiler Set 编译器配置集 - - + + Compiler @@ -10893,7 +10901,7 @@ p, li { white-space: pre-wrap; } 自动链接 - + @@ -10969,15 +10977,15 @@ p, li { white-space: pre-wrap; } 杂项 - - + + Program Runner 程序运行 - + Problem Set 试题集 @@ -11036,8 +11044,8 @@ p, li { white-space: pre-wrap; } 项目选项 - - + + diff --git a/RedPandaIDE/translations/RedPandaIDE_zh_TW.ts b/RedPandaIDE/translations/RedPandaIDE_zh_TW.ts index 571ddac6..b8a8b616 100644 --- a/RedPandaIDE/translations/RedPandaIDE_zh_TW.ts +++ b/RedPandaIDE/translations/RedPandaIDE_zh_TW.ts @@ -4868,10 +4868,6 @@ Toggle Readonly - - Line: %1 Col: %2 Lines: %3 - - Newline @@ -5133,7 +5129,11 @@ - Line: %1 Col: %2 Sel:%3 Lines: %4 + Line: %1 Char: %2 Sel:%3 Lines: %4 + + + + Line: %1 Char: %2 Lines: %3 diff --git a/Red_Panda_CPP.pro b/Red_Panda_CPP.pro index 6ae1fd32..43919b7d 100644 --- a/Red_Panda_CPP.pro +++ b/Red_Panda_CPP.pro @@ -21,8 +21,6 @@ qsynedit.depends = redpanda_qt_utils APP_NAME = RedPandaCPP -APP_VERSION = 2.27 - win32: { SUBDIRS += \ redpanda-win-git-askpass diff --git a/libs/qsynedit/qsynedit/document.cpp b/libs/qsynedit/qsynedit/document.cpp index 4b027ae4..8d01a4e6 100644 --- a/libs/qsynedit/qsynedit/document.cpp +++ b/libs/qsynedit/qsynedit/document.cpp @@ -895,6 +895,14 @@ int Document::stringWidth(const QString &str, int left) const return right - left; } +int Document::stringWidth(const QString &str, int left, const QFontMetrics &asciFontMetrics, const QFontMetrics &nonAsciiFontMetrics) +{ + QList glyphStartCharList = calcGlyphStartCharList(str); + int right; + calcGlyphPositionList(str, glyphStartCharList, asciFontMetrics, nonAsciiFontMetrics, left, right); + return right - left; +} + int Document::glyphCount(int line) { QMutexLocker locker(&mMutex); @@ -929,20 +937,7 @@ int Document::glyphWidth(int line, int glyphIdx) int Document::glyphWidth(const QString &glyph, int left) const { - int glyphWidth; - if (glyph.length()==1 && glyph[0].unicode()<0xFF) { - QChar ch = glyph[0]; - if (ch == '\t') { - glyphWidth = tabWidth() - left % tabWidth(); - } else { - glyphWidth = mFontMetrics.horizontalAdvance(ch); - //qDebug()< Document::calcLineWidth(const QString &lineText, const QList &gl return calcGlyphPositionList(lineText,glyphStartCharList,0,width); } +QList Document::calcGlyphPositionList(const QString &lineText, const QList &glyphStartCharList, const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics, int left, int &right) const +{ + right = std::max(0,left); + int start,end; + QList glyphPostionList; + for (int i=0;i=count()) return 0; - QList glyphPositionList = mLines[line]->glyphPositionList(); + QList glyphPositionList = mLines[line]->glyphStartPositionList(); return xposToGlyphIndex(mLines[line]->width(), glyphPositionList, xpos); } @@ -1010,7 +1026,7 @@ int Document::xposToGlyphStartChar(int line, int xpos) QMutexLocker locker(&mMutex); if (line<0 || line>=count()) return 0; - QList glyphPositionList = mLines[line]->glyphPositionList(); + QList glyphPositionList = mLines[line]->glyphStartPositionList(); int glyphIdx = xposToGlyphIndex(mLines[line]->width(), glyphPositionList, xpos); return mLines[line]->glyphStartChar(glyphIdx); } @@ -1040,7 +1056,7 @@ int Document::xposToGlyphStartChar(int line, const QString newStr, int xpos) QList glyphPositionList; int width; if (mLines[line]->lineText() == newStr) { - glyphPositionList = mLines[line]->glyphPositionList(); + glyphPositionList = mLines[line]->glyphStartPositionList(); width = mLines[line]->width(); } else { glyphPositionList = calcGlyphPositionList(mLines[line]->lineText(), width); @@ -1124,24 +1140,24 @@ void Document::internalClear() } } +void Document::setLineWidth(int line, const QString &lineText, int newWidth, const QList glyphStartPositionList) +{ + QMutexLocker locker(&mMutex); + if (line<0 || line>=count()) + return ; + if (lineText != mLines[line]->lineText()) + return; + mLines[line]->mWidth = newWidth; + mLines[line]->mGlyphStartPositionList = glyphStartPositionList; + Q_ASSERT(mLines[line]->mGlyphStartPositionList.length() == mLines[line]->mGlyphStartCharList.length()); +} + QList Document::calcGlyphPositionList(const QString &lineText, const QList &glyphStartCharList, int left, int &right) const { - right = std::max(0,left); - int start,end; - QList glyphPostionList; - for (int i=0;i Document::calcGlyphPositionList(const QString &lineText, int &width) return calcGlyphPositionList(lineText,glyphStartCharList,0,width); } +QList Document::getGlyphStartCharList(int line, const QString &lineText) +{ + if (line<0 || line>=count() || mLines[line]->lineText()!=lineText) + return calcGlyphStartCharList(lineText); + return mLines[line]->glyphStartCharList(); +} + +QList Document::getGlyphStartPositionList(int line, const QString &lineText, int &lineWidth) +{ + if (line<0 || line>=count() || mLines[line]->lineText()!=lineText) + return calcGlyphPositionList(lineText,lineWidth); + lineWidth = mLines[line]->width(); + return mLines[line]->glyphStartPositionList(); +} + NewlineType Document::getNewlineType() { QMutexLocker locker(&mMutex); @@ -1212,21 +1243,21 @@ int DocumentLine::glyphStartPosition(int i) return 0; if (mWidth<0) updateWidth(); - if (i>=mGlyphPositionList.length()) + if (i>=mGlyphStartPositionList.length()) return mWidth; - return mGlyphPositionList[i]; + return mGlyphStartPositionList[i]; } int DocumentLine::glyphWidth(int i) { - if (i<0 || i>=mGlyphPositionList.length()) + if (i<0 || i>=mGlyphStartPositionList.length()) return 0; if( mWidth <0) updateWidth(); int start = glyphStartPosition(i); int end; - if (i+1 &DocumentLine::glyphPositionList() +const QList &DocumentLine::glyphStartPositionList() { if(mWidth<0) updateWidth(); - return mGlyphPositionList; + return mGlyphStartPositionList; } int DocumentLine::glyphStartChar(int i) const @@ -1703,4 +1734,64 @@ int searchForSegmentIdx(const QList segList, int minVal, int maxVal, int va return -1; } +int Document::updateGlyphStartPositionList( + const QString &lineText, + const QList &glyphStartCharList, int startChar, int endChar, + const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics, + QList &glyphStartPositionList, int left, int &right, int &startGlyph, int &endGlyph) const +{ + right = std::max(0,left); + startGlyph = searchForSegmentIdx(glyphStartCharList,0,lineText.length(),startChar); + endGlyph = searchForSegmentIdx(glyphStartCharList,0,lineText.length(),endChar); + for (int i=startGlyph;i glyphStartCharList) +{ + QList addedList = calcGlyphStartCharList(strAdded); + for (int i=0;i segList, int maxVal, int idx) +{ + if (idx<0 || idx>=segList.length()) + return 0; + if (idx == segList.length()-1) + return maxVal - segList[idx]; + return segList[idx+1]-segList[idx]; +} + } diff --git a/libs/qsynedit/qsynedit/document.h b/libs/qsynedit/qsynedit/document.h index b771d38f..1f64b652 100644 --- a/libs/qsynedit/qsynedit/document.h +++ b/libs/qsynedit/qsynedit/document.h @@ -31,8 +31,9 @@ namespace QSynedit { int searchForSegmentIdx(const QList segList, int minVal, int maxVal, int value); - +int calcSegmentInterval(const QList segList, int maxVal, int idx); QList calcGlyphStartCharList(const QString &text); +void expandGlyphStartCharList(const QString& strAdded, int oldStrLen, QList glyphStartCharList); class Document; @@ -83,7 +84,7 @@ private: * @brief get list of start position of the glyphs in the line text * @return start positions of the glyph (in pixel) */ - const QList& glyphPositionList(); + const QList& glyphStartPositionList(); /** * @brief get start index of the chars representing the specified glyph. @@ -145,7 +146,7 @@ private: void setLineText(const QString &newLineText); void updateWidth(); - void invalidateWidth() { mWidth = -1; mGlyphPositionList.clear(); } + void invalidateWidth() { mWidth = -1; mGlyphStartPositionList.clear(); } private: QString mLineText; /* the unicode code points of the text */ /** @@ -160,11 +161,11 @@ private: * @brief start columns of the glyphs * * A glyph may occupy more than one columns in the screen. - * Each elements of mGlyphPositionList is the columns occupied by the glyph. + * Each elements of mGlyphStartPositionList is the columns occupied by the glyph. * The width of a glyph is affected by the font used to display, * so it must be recalculated each time the font is changed. */ - QList mGlyphPositionList; + QList mGlyphStartPositionList; /** * @brief state of the syntax highlighter after this line is parsed * @@ -441,6 +442,8 @@ public: */ int stringWidth(const QString &str, int left) const; + int stringWidth(const QString &str, int left, const QFontMetrics &asciFontMetrics, const QFontMetrics &nonAsciiFontMetrics); + int glyphCount(int line); /** * @brief get start index of the chars representing the specified glyph in the specified line. @@ -515,6 +518,14 @@ public: int charToGlyphStartPosition(int line, const QString newStr, int charPos); int xposToGlyphStartChar(int line, const QString newStr, int xpos); + int updateGlyphStartPositionList( + const QString& lineText, + const QList &glyphStartCharList, + int startChar, int endChar, + const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics, + QList &glyphStartPositionList, + int left, int &right, int &startGlyph, int &endGlyph) const; + bool getAppendNewLineAtEOF(); void setAppendNewLineAtEOF(bool appendNewLineAtEOF); @@ -554,11 +565,22 @@ protected: void putTextStr(const QString& text); void internalClear(); private: + void setLineWidth(int line, const QString& lineText, int newWidth, const QList glyphStartPositionList); + + int glyphWidth(const QString& glyph, int left, + const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics) const; + int xposToGlyphIndex(int strWidth, QList glyphPositionList, int xpos) const; int charToGlyphIndex(const QString& str, QList glyphStartCharList, int charPos) const; QList calcLineWidth(const QString& lineText, const QList &glyphStartCharList, int &width); + QList calcGlyphPositionList(const QString& lineText, const QList &glyphStartCharList, + const QFontMetrics &fontMetrics, + const QFontMetrics &nonAsciiFontMetrics, + int left, int &right) const; QList calcGlyphPositionList(const QString& lineText, const QList &glyphStartCharList, int left, int &right) const; QList calcGlyphPositionList(const QString& lineText, int &width) const; + QList getGlyphStartCharList(int line, const QString &lineText); + QList getGlyphStartPositionList(int line, const QString &lineText, int &lineWidth); bool tryLoadFileByEncoding(QByteArray encodingName, QFile& file); void loadUTF16BOMFile(QFile& file); void loadUTF32BOMFile(QFile& file); @@ -588,6 +610,8 @@ private: #else QMutex mMutex; #endif + + friend class QSynEditPainter; }; enum class ChangeReason { diff --git a/libs/qsynedit/qsynedit/painter.cpp b/libs/qsynedit/qsynedit/painter.cpp index c79a993b..c085453f 100644 --- a/libs/qsynedit/qsynedit/painter.cpp +++ b/libs/qsynedit/qsynedit/painter.cpp @@ -354,7 +354,12 @@ int QSynEditPainter::fixXValue(int xpos) } void QSynEditPainter::paintToken( - const QString &token, int tokenWidth, int tokenLeft, + const QString& lineText, + const QList &glyphStartCharList, + const QList &glyphStartPositionList, + int startGlyph, + int endGlyph, + int tokenWidth, int tokenLeft, int first, int last, bool /*isSelection*/, const QFont& font, const QFont& fontForNonAscii, bool showGlyphs) { @@ -362,8 +367,12 @@ void QSynEditPainter::paintToken( int nX; bool lastGlyphAscii = false; bool fontInited = false; + int tokenRight = tokenWidth+tokenLeft; -// qDebug()<<"Paint token"<= first && rcToken.right() > rcToken.left()) { nX = fixXValue(first); @@ -375,14 +384,12 @@ void QSynEditPainter::paintToken( } else { int tokenWidth=0; startPaint = false; - QList glyphStartCharList = calcGlyphStartCharList(token); -// qDebug()<<"painting:"<document()->glyphWidth(glyph, tokenLeft+tokenWidth); -// qDebug()<first) { if (!startPaint ) { nX-= (first - tokenWidth - 1) ; @@ -410,8 +417,8 @@ void QSynEditPainter::paintToken( QString textToPaint = glyph; while(i+1document()->glyphWidth(glyph2,0); + glyphWidth += calcSegmentInterval(glyphStartPositionList, tokenLeft+tokenWidth, i); textToPaint+=glyph2; if (tokenWidth + glyphWidth > last ) break; @@ -544,7 +551,10 @@ void QSynEditPainter::paintEditAreas(const EditingAreaList &areaList) } } -void QSynEditPainter::paintHighlightToken(bool bFillToEOL) +void QSynEditPainter::paintHighlightToken(const QString& lineText, + const QList &glyphStartCharList, + const QList &glyphStartPositionsList, + bool bFillToEOL) { bool isComplexToken; int nC1, nC2, nC1Sel, nC2Sel; @@ -578,16 +588,7 @@ void QSynEditPainter::paintHighlightToken(bool bFillToEOL) // if (bSpecialLine && mEdit->mOptions.testFlag(eoSpecialLineDefaultFg)) // colFG = TokenAccu.FG; - QFont font = mEdit->font(); - font.setBold(mTokenAccu.style & FontStyle::fsBold); - font.setItalic(mTokenAccu.style & FontStyle::fsItalic); - font.setStrikeOut(mTokenAccu.style & FontStyle::fsStrikeOut); - font.setUnderline(mTokenAccu.style & FontStyle::fsUnderline); - QFont nonAsciiFont = mEdit->fontForNonAscii(); - nonAsciiFont.setBold(mTokenAccu.style & FontStyle::fsBold); - nonAsciiFont.setItalic(mTokenAccu.style & FontStyle::fsItalic); - nonAsciiFont.setStrikeOut(mTokenAccu.style & FontStyle::fsStrikeOut); - nonAsciiFont.setUnderline(mTokenAccu.style & FontStyle::fsUnderline); + // Paint the chars if (isComplexToken) { @@ -596,24 +597,47 @@ void QSynEditPainter::paintHighlightToken(bool bFillToEOL) setDrawingColors(false); rcToken.setRight(fixXValue(mLineSelStart)); paintToken( - mTokenAccu.s,mTokenAccu.width,mTokenAccu.left,nC1,mLineSelStart,false,font,nonAsciiFont, mTokenAccu.showSpecialGlyphs); + lineText, + glyphStartCharList, + glyphStartPositionsList, + mTokenAccu.startGlyph, + mTokenAccu.endGlyph, + mTokenAccu.width,mTokenAccu.left,nC1,mLineSelStart,false,mTokenAccu.font,mTokenAccu.nonAsciiFont, mTokenAccu.showSpecialGlyphs); } // selected part of the token setDrawingColors(true); nC1Sel = std::max(mLineSelStart, nC1); nC2Sel = std::min(mLineSelEnd, nC2); rcToken.setRight(fixXValue(nC2Sel)); - paintToken(mTokenAccu.s, mTokenAccu.width, mTokenAccu.left, nC1Sel, nC2Sel,true,font,nonAsciiFont, mTokenAccu.showSpecialGlyphs); + paintToken( + lineText, + glyphStartCharList, + glyphStartPositionsList, + mTokenAccu.startGlyph, + mTokenAccu.endGlyph, + mTokenAccu.width, mTokenAccu.left, nC1Sel, nC2Sel,true,mTokenAccu.font,mTokenAccu.nonAsciiFont, mTokenAccu.showSpecialGlyphs); // second unselected part of the token if (bU2) { setDrawingColors(false); rcToken.setRight(fixXValue(nC2)); - paintToken(mTokenAccu.s, mTokenAccu.width, mTokenAccu.left, mLineSelEnd, nC2,false,font,nonAsciiFont, mTokenAccu.showSpecialGlyphs); + paintToken( + lineText, + glyphStartCharList, + glyphStartPositionsList, + mTokenAccu.startGlyph, + mTokenAccu.endGlyph, + mTokenAccu.width, mTokenAccu.left, mLineSelEnd, nC2,false,mTokenAccu.font,mTokenAccu.nonAsciiFont, mTokenAccu.showSpecialGlyphs); } } else { setDrawingColors(bSel); rcToken.setRight(fixXValue(nC2)); - paintToken(mTokenAccu.s, mTokenAccu.width, mTokenAccu.left, nC1, nC2,bSel,font,nonAsciiFont, mTokenAccu.showSpecialGlyphs); + paintToken( + lineText, + glyphStartCharList, + glyphStartPositionsList, + mTokenAccu.startGlyph, + mTokenAccu.endGlyph, + mTokenAccu.width, mTokenAccu.left, nC1, nC2,bSel,mTokenAccu.font,mTokenAccu.nonAsciiFont, mTokenAccu.showSpecialGlyphs); } } @@ -658,9 +682,15 @@ void QSynEditPainter::paintHighlightToken(bool bFillToEOL) // Store the token chars with the attributes in the TokenAccu // record. This will paint any chars already stored if there is // a (visible) change in the attributes. -void QSynEditPainter::addHighlightToken(const QString &token, int tokenLeft, - int tokenWidth, int line, PTokenAttribute attri, - bool showGlyphs) +void QSynEditPainter::addHighlightToken( + const QString& lineText, + const QString& token, int tokenLeft, + int line, PTokenAttribute attri, bool showGlyphs, + const QList glyphStartCharList, + int tokenStartChar, + int tokenEndChar, + QList &glyphStartPositionList, + int &tokenWidth) { bool bCanAppend; QColor foreground, background; @@ -706,20 +736,52 @@ void QSynEditPainter::addHighlightToken(const QString &token, int tokenLeft, } // If we can't append it, then we have to paint the old token chars first. if (!bCanAppend) - paintHighlightToken(false); + paintHighlightToken(lineText, glyphStartCharList, glyphStartPositionList, false); } - // Don't use AppendStr because it's more expensive. - if (bCanAppend) { - mTokenAccu.s.append(token); - mTokenAccu.width+=tokenWidth; - } else { - mTokenAccu.width = tokenWidth; - mTokenAccu.s = token; - mTokenAccu.left = tokenLeft; - mTokenAccu.foreground = foreground; - mTokenAccu.background = background; - mTokenAccu.style = style; - mTokenAccu.showSpecialGlyphs = showGlyphs; + if (!bCanAppend) { + mTokenAccu.font = mEdit->font(); + mTokenAccu.font.setBold(style & FontStyle::fsBold); + mTokenAccu.font.setItalic(style & FontStyle::fsItalic); + mTokenAccu.font.setStrikeOut(style & FontStyle::fsStrikeOut); + mTokenAccu.font.setUnderline(style & FontStyle::fsUnderline); + mTokenAccu.nonAsciiFont = mEdit->fontForNonAscii(); + mTokenAccu.nonAsciiFont.setBold(style & FontStyle::fsBold); + mTokenAccu.nonAsciiFont.setItalic(style & FontStyle::fsItalic); + mTokenAccu.nonAsciiFont.setStrikeOut(style & FontStyle::fsStrikeOut); + mTokenAccu.nonAsciiFont.setUnderline(style & FontStyle::fsUnderline); + } + //calculate width of the token ( and update it's glyph start positions ) + int tokenRight; + int startGlyph, endGlyph; + tokenWidth = mEdit->mDocument->updateGlyphStartPositionList( + lineText, + glyphStartCharList, + tokenStartChar, + tokenEndChar, + QFontMetrics(mTokenAccu.font), + QFontMetrics(mTokenAccu.nonAsciiFont), + glyphStartPositionList, + tokenLeft, + tokenRight, + startGlyph, + endGlyph); + + // Only accumulate tokens if it's visible. + if (tokenLeft < mRight) { + if (bCanAppend) { + mTokenAccu.width += tokenWidth; + Q_ASSERT(startGlyph == mTokenAccu.endGlyph); + mTokenAccu.endGlyph = endGlyph; + } else { + mTokenAccu.width = tokenWidth; + mTokenAccu.left = tokenLeft; + mTokenAccu.startGlyph = startGlyph; + mTokenAccu.endGlyph = endGlyph; + mTokenAccu.foreground = foreground; + mTokenAccu.background = background; + mTokenAccu.style = style; + mTokenAccu.showSpecialGlyphs = showGlyphs; + } } } @@ -864,8 +926,6 @@ void QSynEditPainter::paintLines() EditingAreaList areaList; PCodeFoldingRange foldRange; PTokenAttribute preeditAttr; - int nFold; - QString sFold; // Initialize rcLine for drawing. Note that Top and Bottom are updated // inside the loop. Get only the starting point for this. @@ -950,32 +1010,60 @@ void QSynEditPainter::paintLines() mIsLineSelected = (!mIsComplexLine) && (mLineSelStart > 0); rcToken = rcLine; + + int lineWidth; + QList glyphStartCharList = mEdit->mDocument->getGlyphStartCharList(vLine-1,sLine); + QList glyphStartPositionsList = mEdit->mDocument->getGlyphStartPositionList(vLine-1,sLine, lineWidth); + if (!mEdit->mSyntaxer || !mEdit->mSyntaxer->enabled()) { sToken = sLine; - if (mIsCurrentLine) { - tokenWidth = mEdit->document()->lineWidth(vLine-1, sLine); - } else { - tokenWidth = mEdit->document()->lineWidth(vLine-1); - } + tokenWidth = lineWidth; if (mEdit->mOptions.testFlag(eoShowLineBreaks) && (!mIsLineSelected) && (!mIsSpecialLine) && (tokenWidth <= mLeft)) { - sToken = sToken + LineBreakGlyph; - tokenWidth += mEdit->document()->glyphWidth(LineBreakGlyph,0); + expandGlyphStartCharList(LineBreakGlyph, sLine.length(), glyphStartCharList); + int width = mEdit->document()->glyphWidth(LineBreakGlyph,0); + glyphStartPositionsList.append(tokenWidth); + sLine+=LineBreakGlyph; + tokenWidth += width; } if (mIsComplexLine) { setDrawingColors(true); rcToken.setLeft(std::max(rcLine.left(), fixXValue(mLineSelStart))); rcToken.setRight(std::min(rcLine.right(), fixXValue(mLineSelEnd))); - paintToken(sToken, tokenWidth, 0, mLineSelStart, mLineSelEnd,false,mEdit->font(),mEdit->fontForNonAscii(),false); + paintToken( + sLine, + glyphStartCharList, + glyphStartPositionsList, + 0, + glyphStartCharList.length(), + tokenWidth, 0, mLineSelStart, mLineSelEnd,false,mEdit->font(),mEdit->fontForNonAscii(),false); setDrawingColors(false); rcToken.setLeft(std::max(rcLine.left(), fixXValue(mLeft))); rcToken.setRight(std::min(rcLine.right(), fixXValue(mLineSelStart))); - paintToken(sToken, tokenWidth, 0, mLeft, mLineSelStart,false,mEdit->font(),mEdit->fontForNonAscii(),false); + paintToken( + sLine, + glyphStartCharList, + glyphStartPositionsList, + 0, + glyphStartCharList.length(), + tokenWidth, 0, mLeft, mLineSelStart,false,mEdit->font(),mEdit->fontForNonAscii(),false); rcToken.setLeft(std::max(rcLine.left(), fixXValue(mLineSelEnd))); rcToken.setRight(std::min(rcLine.right(), fixXValue(mRight))); - paintToken(sToken, tokenWidth, 0, mLineSelEnd, mRight,true, mEdit->font(), mEdit->fontForNonAscii(),false); + paintToken( + sLine, + glyphStartCharList, + glyphStartPositionsList, + 0, + glyphStartCharList.length(), + tokenWidth, 0, mLineSelEnd, mRight,true, mEdit->font(), mEdit->fontForNonAscii(),false); } else { setDrawingColors(mIsLineSelected); - paintToken(sToken, tokenWidth, 0, mLeft, mRight, mIsLineSelected,mEdit->font(),mEdit->fontForNonAscii(),false); + paintToken( + sLine, + glyphStartCharList, + glyphStartPositionsList, + 0, + glyphStartCharList.length(), + tokenWidth, 0, mLeft, mRight, mIsLineSelected,mEdit->font(),mEdit->fontForNonAscii(),false); } //Paint editingAreaBorders if (mIsCurrentLine && mEdit->mInputPreeditString.length()>0) { @@ -1007,105 +1095,124 @@ void QSynEditPainter::paintLines() // Test first whether anything of this token is visible. while (!mEdit->mSyntaxer->eol()) { sToken = mEdit->mSyntaxer->getToken(); - // Work-around buggy highlighters which return empty tokens. if (sToken.isEmpty()) { - mEdit->mSyntaxer->next(); - if (mEdit->mSyntaxer->eol()) - break; - sToken = mEdit->mSyntaxer->getToken(); - // Maybe should also test whether GetTokenPos changed... - if (sToken.isEmpty()) { - //qDebug()<mSyntaxer->next(); + // if (mEdit->mSyntaxer->eol()) + // break; + // sToken = mEdit->mSyntaxer->getToken(); + // // Maybe should also test whether GetTokenPos changed... + // if (sToken.isEmpty()) { + // //qDebug()<charToColumn(sLine,edit->mHighlighter->getTokenPos()+1)-1; - tokenWidth = mEdit->stringWidth(sToken, tokenLeft); - if ( tokenLeft + tokenWidth >= mLeft) { - if (tokenLeft + tokenWidth >= mRight) { - if (tokenLeft >= mRight) - break; //*** BREAK *** - tokenWidth = mRight - tokenLeft; - } - // It's at least partially visible. Get the token attributes now. - attr = mEdit->mSyntaxer->getTokenAttribute(); + int tokenStartChar = mEdit->mSyntaxer->getTokenPos(); + int tokenEndChar = tokenStartChar + sToken.length(); - //rainbow parenthesis - if (sToken == "[" - || sToken == "(" - || sToken == "{" - ) { - SyntaxState rangeState = mEdit->mSyntaxer->getState(); - getBraceColorAttr(rangeState.bracketLevel - +rangeState.braceLevel - +rangeState.parenthesisLevel - ,attr); - } else if (sToken == "]" - || sToken == ")" - || sToken == "}" - ){ - SyntaxState rangeState = mEdit->mSyntaxer->getState(); - getBraceColorAttr(rangeState.bracketLevel - +rangeState.braceLevel - +rangeState.parenthesisLevel+1, - attr); - } - //input method - if (mIsCurrentLine && mEdit->mInputPreeditString.length()>0) { - int startPos = mEdit->mSyntaxer->getTokenPos()+1; - int endPos = mEdit->mSyntaxer->getTokenPos() + sToken.length(); - //qDebug()<mCaretX<<":"<mCaretX+edit->mInputPreeditString.length(); - if (!(endPos < mEdit->mCaretX - || startPos >= mEdit->mCaretX+mEdit->mInputPreeditString.length())) { - if (!preeditAttr) { - preeditAttr = attr; - } else { - attr = preeditAttr; - } - } - } - bool showGlyph=false; - if (attr && attr->tokenType() == TokenType::Space) { - int pos = mEdit->mSyntaxer->getTokenPos(); - if (pos==0) { - showGlyph = mEdit->mOptions.testFlag(eoShowLeadingSpaces); - } else if (pos+sToken.length()==sLine.length()) { - showGlyph = mEdit->mOptions.testFlag(eoShowTrailingSpaces); - } else { - showGlyph = mEdit->mOptions.testFlag(eoShowInnerSpaces); - } - } - addHighlightToken(sToken, tokenLeft, - tokenWidth, vLine,attr, showGlyph); + // It's at least partially visible. Get the token attributes now. + attr = mEdit->mSyntaxer->getTokenAttribute(); + + //rainbow parenthesis + if (sToken == "[" + || sToken == "(" + || sToken == "{" + ) { + SyntaxState rangeState = mEdit->mSyntaxer->getState(); + getBraceColorAttr(rangeState.bracketLevel + +rangeState.braceLevel + +rangeState.parenthesisLevel + ,attr); + } else if (sToken == "]" + || sToken == ")" + || sToken == "}" + ){ + SyntaxState rangeState = mEdit->mSyntaxer->getState(); + getBraceColorAttr(rangeState.bracketLevel + +rangeState.braceLevel + +rangeState.parenthesisLevel+1, + attr); } + //input method + if (mIsCurrentLine && mEdit->mInputPreeditString.length()>0) { + int startPos = mEdit->mSyntaxer->getTokenPos()+1; + int endPos = mEdit->mSyntaxer->getTokenPos() + sToken.length(); + //qDebug()<mCaretX<<":"<mCaretX+edit->mInputPreeditString.length(); + if (!(endPos < mEdit->mCaretX + || startPos >= mEdit->mCaretX+mEdit->mInputPreeditString.length())) { + if (!preeditAttr) { + preeditAttr = attr; + } else { + attr = preeditAttr; + } + } + } + bool showGlyph=false; + if (attr && attr->tokenType() == TokenType::Space) { + int pos = mEdit->mSyntaxer->getTokenPos(); + if (pos==0) { + showGlyph = mEdit->mOptions.testFlag(eoShowLeadingSpaces); + } else if (pos+sToken.length()==sLine.length()) { + showGlyph = mEdit->mOptions.testFlag(eoShowTrailingSpaces); + } else { + showGlyph = mEdit->mOptions.testFlag(eoShowInnerSpaces); + } + } + addHighlightToken( + sLine, + sToken, + tokenLeft, + vLine, attr,showGlyph, + glyphStartCharList, + tokenStartChar, + tokenEndChar, + glyphStartPositionsList, + tokenWidth); tokenLeft+=tokenWidth; // Let the highlighter scan the next token. mEdit->mSyntaxer->next(); } - // Paint folding - foldRange = mEdit->foldStartAtLine(vLine); - if ((foldRange) && foldRange->collapsed) { - sFold = mEdit->syntaxer()->foldString(sLine); - nFold = mEdit->stringWidth(sFold,mEdit->mDocument->lineWidth(vLine-1)); - attr = mEdit->mSyntaxer->symbolAttribute(); - getBraceColorAttr(mEdit->mSyntaxer->getState().braceLevel,attr); - addHighlightToken( - sFold, mEdit->mDocument->lineWidth(vLine-1) - , nFold, vLine, attr,false); - } else { - // Draw LineBreak glyph. - if (mEdit->mOptions.testFlag(eoShowLineBreaks) - && (!mIsLineSelected) - && (!mIsSpecialLine) - && (mEdit->mDocument->lineWidth(vLine-1) < mRight)) { - addHighlightToken(LineBreakGlyph, - mEdit->mDocument->lineWidth(vLine-1), - mEdit->mDocument->glyphWidth(LineBreakGlyph,0),vLine, mEdit->mSyntaxer->whitespaceAttribute(),false); + mEdit->mDocument->setLineWidth(vLine-1, sLine, tokenLeft, glyphStartPositionsList); + if (tokenLeftfoldStartAtLine(vLine); + if ((foldRange) && foldRange->collapsed) { + addOnStr = mEdit->syntaxer()->foldString(sLine); + } else { + // Draw LineBreak glyph. + if (mEdit->mOptions.testFlag(eoShowLineBreaks) + && (!mIsLineSelected) + && (!mIsSpecialLine) + && (mEdit->mDocument->lineWidth(vLine-1) < mRight)) { + addOnStr = LineBreakGlyph; + } + } + if (!addOnStr.isEmpty()) { + expandGlyphStartCharList(addOnStr, sLine.length(), glyphStartCharList); + for (int i=0;imSyntaxer->symbolAttribute(); + getBraceColorAttr(mEdit->mSyntaxer->getState().braceLevel,attr); + int oldLen = sLine.length(); + sLine += addOnStr; + addHighlightToken( + sLine, + addOnStr, + tokenLeft, + vLine, attr, false, + glyphStartCharList, + oldLen, + sLine.length(), + glyphStartPositionsList, + tokenWidth); } } // Draw anything that's left in the TokenAccu record. Fill to the end // of the invalid area with the correct colors. - paintHighlightToken(true); + paintHighlightToken(sLine, glyphStartCharList, glyphStartPositionsList, true); //Paint editingAreaBorders foreach (const PEditingArea& area, areaList) { diff --git a/libs/qsynedit/qsynedit/painter.h b/libs/qsynedit/qsynedit/painter.h index 0688ce0e..e7ceeb7c 100644 --- a/libs/qsynedit/qsynedit/painter.h +++ b/libs/qsynedit/qsynedit/painter.h @@ -31,10 +31,14 @@ class QSynEditPainter struct SynTokenAccu { int width; int left; - QString s; + int startGlyph; + int endGlyph; +// QString s; QColor foreground; QColor background; FontStyles style; + QFont font; + QFont nonAsciiFont; bool showSpecialGlyphs; }; @@ -54,13 +58,29 @@ private: void computeSelectionInfo(); void setDrawingColors(bool selected); int fixXValue(int xpos); - void paintToken(const QString& token, int tokenWidth, int tokenLeft, - int first, int last, bool isSelection, const QFont& font, - const QFont& fontForNonAscii, bool showGlyphs); + void paintToken( + const QString& lineText, + const QList &glyphStartCharList, + const QList &glyphStartPositionList, + int startGlyph, + int endGlyph, + int tokenWidth, int tokenLeft, + int first, int last, bool isSelection, const QFont& font, + const QFont& fontForNonAscii, bool showGlyphs); void paintEditAreas(const EditingAreaList& areaList); - void paintHighlightToken(bool bFillToEOL); - void addHighlightToken(const QString& token, int tokenLeft, int tokenWidth, - int line, PTokenAttribute p_Attri, bool showGlyphs); + void paintHighlightToken(const QString& lineText, + const QList &glyphStartCharList, + const QList &glyphStartPositionsList, bool bFillToEOL); + void addHighlightToken( + const QString& lineText, + const QString& token, int tokenLeft, + int line, PTokenAttribute p_Attri, bool showGlyphs, + const QList glyphStartCharList, + int tokenStartChar, + int tokenEndChar, + QList &glyphStartPositionList, + int &tokenWidth + ); void paintFoldAttributes(); void getBraceColorAttr(int level, PTokenAttribute &attr); diff --git a/libs/qsynedit/qsynedit_zh_CN.ts b/libs/qsynedit/qsynedit_zh_CN.ts index a985e592..8496a87c 100644 --- a/libs/qsynedit/qsynedit_zh_CN.ts +++ b/libs/qsynedit/qsynedit_zh_CN.ts @@ -4288,29 +4288,29 @@ QSynedit::Document - + Can't open file '%1' for read! 无法读取文件"%1". - - + + Can't load codec '%1'! 无法加载字符编码"%1"! - + '%1' is a binaray File! This is a binaray File! '%1'是二进制文件! - + Can't open file '%1' for save! 无法保存文件"%1"! - + Data not correctly writed to file '%1'. 数据未能正确写入文件"%1"。 @@ -4318,7 +4318,7 @@ QSynedit::QSynEdit - + The syntaxer seems to be in an infinite loop The highlighter seems to be in an infinite loop 代码分析器似乎死循环了。