diff -Nru tominote-1.0.0/debian/changelog tominote-1.0.0/debian/changelog --- tominote-1.0.0/debian/changelog 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/debian/changelog 2017-11-29 21:45:59.000000000 +0000 @@ -1,8 +1,8 @@ -tominote (1.0.0-0~201711232349~ubuntu17.04.1) zesty; urgency=low +tominote (1.0.0-0~201711292112~ubuntu17.04.1) zesty; urgency=low * Auto build. - -- Jiří Hajda Thu, 23 Nov 2017 23:54:40 +0000 + -- Jiří Hajda Wed, 29 Nov 2017 21:45:59 +0000 tominote (1.0.0-0) precise; urgency=low diff -Nru tominote-1.0.0/debian/git-build-recipe.manifest tominote-1.0.0/debian/git-build-recipe.manifest --- tominote-1.0.0/debian/git-build-recipe.manifest 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/debian/git-build-recipe.manifest 2017-11-29 21:45:59.000000000 +0000 @@ -1,3 +1,3 @@ -# git-build-recipe format 0.4 deb-version {debupstream}-0~201711232349 -lp:tominote git-commit:0a89a9f9972e306bd67a00f9ebaf944d9b838bdd -nest-part packaging lp:tominote install/deb/debian debian git-commit:0a89a9f9972e306bd67a00f9ebaf944d9b838bdd +# git-build-recipe format 0.4 deb-version {debupstream}-0~201711292112 +lp:tominote git-commit:cf4741c1efe9e8d7d6c3b09360850c96bd196e51 +nest-part packaging lp:tominote install/deb/debian debian git-commit:cf4741c1efe9e8d7d6c3b09360850c96bd196e51 diff -Nru tominote-1.0.0/install/deb/TomiNote.desktop tominote-1.0.0/install/deb/TomiNote.desktop --- tominote-1.0.0/install/deb/TomiNote.desktop 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/install/deb/TomiNote.desktop 2017-11-29 21:45:59.000000000 +0000 @@ -2,7 +2,7 @@ Encoding=UTF-8 Name=TomiNote Comment=A simple note collection tool. -Exec=TomiNote --config=~/.config/TomiNote/TomiNote.ini --lang=/usr/share/TomiNote/languages +Exec=TomiNote --config=~/.config/TomiNote --lang=/usr/share/TomiNote/languages Icon=TomiNote Terminal=false Type=Application diff -Nru tominote-1.0.0/install/win/build.bat tominote-1.0.0/install/win/build.bat --- tominote-1.0.0/install/win/build.bat 1970-01-01 00:00:00.000000000 +0000 +++ tominote-1.0.0/install/win/build.bat 2017-11-29 21:45:59.000000000 +0000 @@ -0,0 +1,9 @@ +if not defined LAZDIR ( + set LAZDIR=C:\lazarus +) +%LAZDIR%\lazbuild.exe --lazarusdir=%LAZDIR% --build-mode="Release" --cpu=i386 --os=win32 ../../src/TomiNote.lpr +copy ..\..\src\TomiNote.exe ..\..\src\lib\i386-win32 +%LAZDIR%\lazbuild.exe --lazarusdir=%LAZDIR% --build-mode="Release" --cpu=x86_64 --os=win64 ../../src/TomiNote.lpr +copy ..\..\src\TomiNote.exe ..\..\src\lib\x86_64-win64 + +"C:\Program Files (x86)\Inno Setup 5\iscc.exe" TomiNote.iss \ No newline at end of file diff -Nru tominote-1.0.0/install/win/sqlite3/win32-x86/sqlite3.def tominote-1.0.0/install/win/sqlite3/win32-x86/sqlite3.def --- tominote-1.0.0/install/win/sqlite3/win32-x86/sqlite3.def 1970-01-01 00:00:00.000000000 +0000 +++ tominote-1.0.0/install/win/sqlite3/win32-x86/sqlite3.def 2017-11-29 21:45:59.000000000 +0000 @@ -0,0 +1,241 @@ +EXPORTS +sqlite3_aggregate_context +sqlite3_aggregate_count +sqlite3_auto_extension +sqlite3_backup_finish +sqlite3_backup_init +sqlite3_backup_pagecount +sqlite3_backup_remaining +sqlite3_backup_step +sqlite3_bind_blob +sqlite3_bind_blob64 +sqlite3_bind_double +sqlite3_bind_int +sqlite3_bind_int64 +sqlite3_bind_null +sqlite3_bind_parameter_count +sqlite3_bind_parameter_index +sqlite3_bind_parameter_name +sqlite3_bind_pointer +sqlite3_bind_text +sqlite3_bind_text16 +sqlite3_bind_text64 +sqlite3_bind_value +sqlite3_bind_zeroblob +sqlite3_bind_zeroblob64 +sqlite3_blob_bytes +sqlite3_blob_close +sqlite3_blob_open +sqlite3_blob_read +sqlite3_blob_reopen +sqlite3_blob_write +sqlite3_busy_handler +sqlite3_busy_timeout +sqlite3_cancel_auto_extension +sqlite3_changes +sqlite3_clear_bindings +sqlite3_close +sqlite3_close_v2 +sqlite3_collation_needed +sqlite3_collation_needed16 +sqlite3_column_blob +sqlite3_column_bytes +sqlite3_column_bytes16 +sqlite3_column_count +sqlite3_column_database_name +sqlite3_column_database_name16 +sqlite3_column_decltype +sqlite3_column_decltype16 +sqlite3_column_double +sqlite3_column_int +sqlite3_column_int64 +sqlite3_column_name +sqlite3_column_name16 +sqlite3_column_origin_name +sqlite3_column_origin_name16 +sqlite3_column_table_name +sqlite3_column_table_name16 +sqlite3_column_text +sqlite3_column_text16 +sqlite3_column_type +sqlite3_column_value +sqlite3_commit_hook +sqlite3_compileoption_get +sqlite3_compileoption_used +sqlite3_complete +sqlite3_complete16 +sqlite3_config +sqlite3_context_db_handle +sqlite3_create_collation +sqlite3_create_collation16 +sqlite3_create_collation_v2 +sqlite3_create_function +sqlite3_create_function16 +sqlite3_create_function_v2 +sqlite3_create_module +sqlite3_create_module_v2 +sqlite3_data_count +sqlite3_db_cacheflush +sqlite3_db_config +sqlite3_db_filename +sqlite3_db_handle +sqlite3_db_mutex +sqlite3_db_readonly +sqlite3_db_release_memory +sqlite3_db_status +sqlite3_declare_vtab +sqlite3_enable_load_extension +sqlite3_enable_shared_cache +sqlite3_errcode +sqlite3_errmsg +sqlite3_errmsg16 +sqlite3_errstr +sqlite3_exec +sqlite3_expanded_sql +sqlite3_expired +sqlite3_extended_errcode +sqlite3_extended_result_codes +sqlite3_file_control +sqlite3_finalize +sqlite3_free +sqlite3_free_table +sqlite3_get_autocommit +sqlite3_get_auxdata +sqlite3_get_table +sqlite3_global_recover +sqlite3_initialize +sqlite3_interrupt +sqlite3_last_insert_rowid +sqlite3_libversion +sqlite3_libversion_number +sqlite3_limit +sqlite3_load_extension +sqlite3_log +sqlite3_malloc +sqlite3_malloc64 +sqlite3_memory_alarm +sqlite3_memory_highwater +sqlite3_memory_used +sqlite3_mprintf +sqlite3_msize +sqlite3_mutex_alloc +sqlite3_mutex_enter +sqlite3_mutex_free +sqlite3_mutex_leave +sqlite3_mutex_try +sqlite3_next_stmt +sqlite3_open +sqlite3_open16 +sqlite3_open_v2 +sqlite3_os_end +sqlite3_os_init +sqlite3_overload_function +sqlite3_prepare +sqlite3_prepare16 +sqlite3_prepare16_v2 +sqlite3_prepare16_v3 +sqlite3_prepare_v2 +sqlite3_prepare_v3 +sqlite3_profile +sqlite3_progress_handler +sqlite3_randomness +sqlite3_realloc +sqlite3_realloc64 +sqlite3_release_memory +sqlite3_reset +sqlite3_reset_auto_extension +sqlite3_result_blob +sqlite3_result_blob64 +sqlite3_result_double +sqlite3_result_error +sqlite3_result_error16 +sqlite3_result_error_code +sqlite3_result_error_nomem +sqlite3_result_error_toobig +sqlite3_result_int +sqlite3_result_int64 +sqlite3_result_null +sqlite3_result_pointer +sqlite3_result_subtype +sqlite3_result_text +sqlite3_result_text16 +sqlite3_result_text16be +sqlite3_result_text16le +sqlite3_result_text64 +sqlite3_result_value +sqlite3_result_zeroblob +sqlite3_result_zeroblob64 +sqlite3_rollback_hook +sqlite3_rtree_geometry_callback +sqlite3_rtree_query_callback +sqlite3_set_authorizer +sqlite3_set_auxdata +sqlite3_set_last_insert_rowid +sqlite3_shutdown +sqlite3_sleep +sqlite3_snprintf +sqlite3_soft_heap_limit +sqlite3_soft_heap_limit64 +sqlite3_sourceid +sqlite3_sql +sqlite3_status +sqlite3_status64 +sqlite3_step +sqlite3_stmt_busy +sqlite3_stmt_readonly +sqlite3_stmt_status +sqlite3_strglob +sqlite3_stricmp +sqlite3_strlike +sqlite3_strnicmp +sqlite3_system_errno +sqlite3_table_column_metadata +sqlite3_test_control +sqlite3_thread_cleanup +sqlite3_threadsafe +sqlite3_total_changes +sqlite3_trace +sqlite3_trace_v2 +sqlite3_transfer_bindings +sqlite3_update_hook +sqlite3_uri_boolean +sqlite3_uri_int64 +sqlite3_uri_parameter +sqlite3_user_data +sqlite3_value_blob +sqlite3_value_bytes +sqlite3_value_bytes16 +sqlite3_value_double +sqlite3_value_dup +sqlite3_value_free +sqlite3_value_int +sqlite3_value_int64 +sqlite3_value_numeric_type +sqlite3_value_pointer +sqlite3_value_subtype +sqlite3_value_text +sqlite3_value_text16 +sqlite3_value_text16be +sqlite3_value_text16le +sqlite3_value_type +sqlite3_vfs_find +sqlite3_vfs_register +sqlite3_vfs_unregister +sqlite3_vmprintf +sqlite3_vsnprintf +sqlite3_vtab_config +sqlite3_vtab_on_conflict +sqlite3_wal_autocheckpoint +sqlite3_wal_checkpoint +sqlite3_wal_checkpoint_v2 +sqlite3_wal_hook +sqlite3_win32_is_nt +sqlite3_win32_mbcs_to_utf8 +sqlite3_win32_mbcs_to_utf8_v2 +sqlite3_win32_set_directory +sqlite3_win32_sleep +sqlite3_win32_unicode_to_utf8 +sqlite3_win32_utf8_to_mbcs +sqlite3_win32_utf8_to_mbcs_v2 +sqlite3_win32_utf8_to_unicode +sqlite3_win32_write_debug Binary files /tmp/tmpccceFB/qgMXJ5RLrS/tominote-1.0.0/install/win/sqlite3/win32-x86/sqlite3.dll and /tmp/tmpccceFB/dFOi0tjz3Q/tominote-1.0.0/install/win/sqlite3/win32-x86/sqlite3.dll differ diff -Nru tominote-1.0.0/install/win/sqlite3/win64-x64/sqlite3.def tominote-1.0.0/install/win/sqlite3/win64-x64/sqlite3.def --- tominote-1.0.0/install/win/sqlite3/win64-x64/sqlite3.def 1970-01-01 00:00:00.000000000 +0000 +++ tominote-1.0.0/install/win/sqlite3/win64-x64/sqlite3.def 2017-11-29 21:45:59.000000000 +0000 @@ -0,0 +1,245 @@ +EXPORTS +sqlite3_aggregate_context +sqlite3_aggregate_count +sqlite3_auto_extension +sqlite3_backup_finish +sqlite3_backup_init +sqlite3_backup_pagecount +sqlite3_backup_remaining +sqlite3_backup_step +sqlite3_bind_blob +sqlite3_bind_blob64 +sqlite3_bind_double +sqlite3_bind_int +sqlite3_bind_int64 +sqlite3_bind_null +sqlite3_bind_parameter_count +sqlite3_bind_parameter_index +sqlite3_bind_parameter_name +sqlite3_bind_pointer +sqlite3_bind_text +sqlite3_bind_text16 +sqlite3_bind_text64 +sqlite3_bind_value +sqlite3_bind_zeroblob +sqlite3_bind_zeroblob64 +sqlite3_blob_bytes +sqlite3_blob_close +sqlite3_blob_open +sqlite3_blob_read +sqlite3_blob_reopen +sqlite3_blob_write +sqlite3_busy_handler +sqlite3_busy_timeout +sqlite3_cancel_auto_extension +sqlite3_changes +sqlite3_clear_bindings +sqlite3_close +sqlite3_close_v2 +sqlite3_collation_needed +sqlite3_collation_needed16 +sqlite3_column_blob +sqlite3_column_bytes +sqlite3_column_bytes16 +sqlite3_column_count +sqlite3_column_database_name +sqlite3_column_database_name16 +sqlite3_column_decltype +sqlite3_column_decltype16 +sqlite3_column_double +sqlite3_column_int +sqlite3_column_int64 +sqlite3_column_name +sqlite3_column_name16 +sqlite3_column_origin_name +sqlite3_column_origin_name16 +sqlite3_column_table_name +sqlite3_column_table_name16 +sqlite3_column_text +sqlite3_column_text16 +sqlite3_column_type +sqlite3_column_value +sqlite3_commit_hook +sqlite3_compileoption_get +sqlite3_compileoption_used +sqlite3_complete +sqlite3_complete16 +sqlite3_config +sqlite3_context_db_handle +sqlite3_create_collation +sqlite3_create_collation_v2 +sqlite3_create_collation16 +sqlite3_create_function +sqlite3_create_function_v2 +sqlite3_create_function16 +sqlite3_create_module +sqlite3_create_module_v2 +sqlite3_data_count +sqlite3_data_directory +sqlite3_db_cacheflush +sqlite3_db_config +sqlite3_db_filename +sqlite3_db_handle +sqlite3_db_mutex +sqlite3_db_readonly +sqlite3_db_release_memory +sqlite3_db_status +sqlite3_declare_vtab +sqlite3_enable_load_extension +sqlite3_enable_shared_cache +sqlite3_errcode +sqlite3_errmsg +sqlite3_errmsg16 +sqlite3_errstr +sqlite3_exec +sqlite3_expanded_sql +sqlite3_expired +sqlite3_extended_errcode +sqlite3_extended_result_codes +sqlite3_file_control +sqlite3_finalize +sqlite3_free +sqlite3_free_table +sqlite3_fts5_may_be_corrupt +sqlite3_get_autocommit +sqlite3_get_auxdata +sqlite3_get_table +sqlite3_global_recover +sqlite3_initialize +sqlite3_interrupt +sqlite3_last_insert_rowid +sqlite3_libversion +sqlite3_libversion_number +sqlite3_limit +sqlite3_load_extension +sqlite3_log +sqlite3_malloc +sqlite3_malloc64 +sqlite3_memory_alarm +sqlite3_memory_highwater +sqlite3_memory_used +sqlite3_mprintf +sqlite3_msize +sqlite3_mutex_alloc +sqlite3_mutex_enter +sqlite3_mutex_free +sqlite3_mutex_leave +sqlite3_mutex_try +sqlite3_next_stmt +sqlite3_open +sqlite3_open_v2 +sqlite3_open16 +sqlite3_os_end +sqlite3_os_init +sqlite3_overload_function +sqlite3_prepare +sqlite3_prepare_v2 +sqlite3_prepare_v3 +sqlite3_prepare16 +sqlite3_prepare16_v2 +sqlite3_prepare16_v3 +sqlite3_profile +sqlite3_progress_handler +sqlite3_randomness +sqlite3_realloc +sqlite3_realloc64 +sqlite3_release_memory +sqlite3_reset +sqlite3_reset_auto_extension +sqlite3_result_blob +sqlite3_result_blob64 +sqlite3_result_double +sqlite3_result_error +sqlite3_result_error_code +sqlite3_result_error_nomem +sqlite3_result_error_toobig +sqlite3_result_error16 +sqlite3_result_int +sqlite3_result_int64 +sqlite3_result_null +sqlite3_result_pointer +sqlite3_result_subtype +sqlite3_result_text +sqlite3_result_text16 +sqlite3_result_text16be +sqlite3_result_text16le +sqlite3_result_text64 +sqlite3_result_value +sqlite3_result_zeroblob +sqlite3_result_zeroblob64 +sqlite3_rollback_hook +sqlite3_rtree_geometry_callback +sqlite3_rtree_query_callback +sqlite3_set_authorizer +sqlite3_set_auxdata +sqlite3_set_last_insert_rowid +sqlite3_shutdown +sqlite3_sleep +sqlite3_snprintf +sqlite3_soft_heap_limit +sqlite3_soft_heap_limit64 +sqlite3_sourceid +sqlite3_sql +sqlite3_status +sqlite3_status64 +sqlite3_step +sqlite3_stmt_busy +sqlite3_stmt_readonly +sqlite3_stmt_status +sqlite3_strglob +sqlite3_stricmp +sqlite3_strlike +sqlite3_strnicmp +sqlite3_system_errno +sqlite3_table_column_metadata +sqlite3_temp_directory +sqlite3_test_control +sqlite3_thread_cleanup +sqlite3_threadsafe +sqlite3_total_changes +sqlite3_trace +sqlite3_trace_v2 +sqlite3_transfer_bindings +sqlite3_update_hook +sqlite3_uri_boolean +sqlite3_uri_int64 +sqlite3_uri_parameter +sqlite3_user_data +sqlite3_value_blob +sqlite3_value_bytes +sqlite3_value_bytes16 +sqlite3_value_double +sqlite3_value_dup +sqlite3_value_free +sqlite3_value_int +sqlite3_value_int64 +sqlite3_value_numeric_type +sqlite3_value_pointer +sqlite3_value_subtype +sqlite3_value_text +sqlite3_value_text16 +sqlite3_value_text16be +sqlite3_value_text16le +sqlite3_value_type +sqlite3_version +sqlite3_vfs_find +sqlite3_vfs_register +sqlite3_vfs_unregister +sqlite3_vmprintf +sqlite3_vsnprintf +sqlite3_vtab_config +sqlite3_vtab_on_conflict +sqlite3_wal_autocheckpoint +sqlite3_wal_checkpoint +sqlite3_wal_checkpoint_v2 +sqlite3_wal_hook +sqlite3_win32_is_nt +sqlite3_win32_mbcs_to_utf8 +sqlite3_win32_mbcs_to_utf8_v2 +sqlite3_win32_set_directory +sqlite3_win32_sleep +sqlite3_win32_unicode_to_utf8 +sqlite3_win32_utf8_to_mbcs +sqlite3_win32_utf8_to_mbcs_v2 +sqlite3_win32_utf8_to_unicode +sqlite3_win32_write_debug Binary files /tmp/tmpccceFB/qgMXJ5RLrS/tominote-1.0.0/install/win/sqlite3/win64-x64/sqlite3.dll and /tmp/tmpccceFB/dFOi0tjz3Q/tominote-1.0.0/install/win/sqlite3/win64-x64/sqlite3.dll differ diff -Nru tominote-1.0.0/install/win/TomiNote.iss tominote-1.0.0/install/win/TomiNote.iss --- tominote-1.0.0/install/win/TomiNote.iss 1970-01-01 00:00:00.000000000 +0000 +++ tominote-1.0.0/install/win/TomiNote.iss 2017-11-29 21:45:59.000000000 +0000 @@ -0,0 +1,69 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "TomiNote" +#define MyAppVersion "1.0.0" +#define MyAppPublisher "TomiTomy" +#define MyAppPublisherShort "TomiTomy" +#define MyAppURL "https://github.com/tomitomy/TomiNote" +#define MyAppExeName "TomiNote.exe" +#define MyAppDebugName "TomiNote.dbg" +#define MyAppSubDir "..\..\src" +#define MyAppParams "--config=%APPDATA%\TomiNote" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +; Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{F2E3E9BB-D992-46C4-AFB4-C42C0F2153F1} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={pf}\{#MyAppName} +DefaultGroupName={#MyAppName} +AllowNoIcons=yes +OutputDir=. +OutputBaseFilename=Install-{#MyAppName}-{#MyAppVersion} +Compression=lzma +SolidCompression=yes +ChangesAssociations=yes +; "ArchitecturesInstallIn64BitMode=x64" requests that the install be +; done in "64-bit mode" on x64, meaning it should use the native +; 64-bit Program Files directory and the 64-bit view of the registry. +; On all other architectures it will install in "32-bit mode". +ArchitecturesInstallIn64BitMode=x64 +; Note: We don't set ProcessorsAllowed because we want this +; installation to run on all architectures (including Itanium, +; since it's capable of running 32-bit code too). + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" +Name: "czech"; MessagesFile: "compiler:Languages\Czech.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: + +[Registry] +Root: HKCU; Subkey: "Software\TomiTomy\TomiNote"; Flags: uninsdeletekey + +[Files] +Source: "{#MyAppSubDir}\lib\x86_64-win64\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode; +Source: "{#MyAppSubDir}\lib\i386-win32\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode +Source: "sqlite3\win64-x64\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode +Source: "sqlite3\win32-x86\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode +Source: "{#MyAppSubDir}\Languages\*.po"; DestDir: "{app}\Languages"; Flags: ignoreversion +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + + +[Icons] +Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Parameters: {#MyAppParams} +Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" +Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon; Parameters: {#MyAppParams} + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, "&", "&&")}}"; Flags: nowait postinstall skipifsilent; Parameters: "--config={%APPDATA|C:\}\{#MyAppName}" + Binary files /tmp/tmpccceFB/qgMXJ5RLrS/tominote-1.0.0/release/TomiNote_v1.0_Beta2_GTK2.zip and /tmp/tmpccceFB/dFOi0tjz3Q/tominote-1.0.0/release/TomiNote_v1.0_Beta2_GTK2.zip differ diff -Nru tominote-1.0.0/src/Forms/fexport.pas tominote-1.0.0/src/Forms/fexport.pas --- tominote-1.0.0/src/Forms/fexport.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Forms/fexport.pas 2017-11-29 21:45:59.000000000 +0000 @@ -241,4 +241,4 @@ editSeparator.Enabled := chkbAddSeparator.Checked; end; -end. +end. diff -Nru tominote-1.0.0/src/Forms/fhelp.pas tominote-1.0.0/src/Forms/fhelp.pas --- tominote-1.0.0/src/Forms/fhelp.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Forms/fhelp.pas 2017-11-29 21:45:59.000000000 +0000 @@ -47,6 +47,10 @@ #10 + 'This program uses dynamic load node, when you open the database, it will not load all the nodes, only the first depth node is loaded, when you expand a node, it will load its next node, so you don''t have to worry about loading too much data too slow, but the count of nodes should not exceed 2147483640, which is determined by the type of integer used by the program, you can modify the source code to make it support more The number of nodes, but also consume more database space.'#10 + #10 + + 'You can use the command line parameter --c or --config to specify the directory of the configuration file, such as: TomiNote --config=~/.config/TomiNote'#10 + + #10 + + 'You can use the command line parameter --l or --lang to specify the directory of the language files, such as: TomiNote --lang=/usr/share/TomiNote/languages'#10 + + #10 + #10 + #10 + '[Move Node]'#10 + @@ -171,7 +175,7 @@ #10 + 'You can search for text in node name and node content. You can search for text in "Selected node" or "Selected node and its descendants" or "All nodes".'#10 + #10 + - 'Carriage returns and newline characters in search content and replacements will be converted to \r \n, tabs will be converted to \t, backslashes will be converted to \\, and if the search content or replacement contains With \r \n \t \\, the backslash in these symbols will not be converted.'#10 + + 'Carriage returns and newline characters in search content and replacements will be converted to \r \n, tabs will be converted to \t, the backslash will not be processed, only the special backslash will be converted to \\. For example: ''\a\\b''#10 will be converted to ''\a\\b\r'', ''\a\\b\''#10 will be converted to ''\a\\b\\\r''.'#10 + #10 + 'The search results will be listed in the InfoBar, which you can double-click to jump to the corresponding place of the search result.'#10 + #10 + @@ -183,6 +187,10 @@ #10 + 'Note: The nodes that executed the multi-node replace operation will lose their history.'#10 + #10 + + 'Note: The contents of the search and replace operations are taken from the database, and the line-ending character used in the database is \n, so you can never found the \r character.'#10 + + #10 + + 'Note: If the pasted content contains line-ending character that do not match the current system, you can convert the line-ending to the current system''s line-ending by "switching to other nodes and then switching back", the wrong line-ending will cause the search results to display incorrectly.'#10 + + #10 + #10 + #10 + '[Import And Export]'#10 + diff -Nru tominote-1.0.0/src/Forms/fimport.pas tominote-1.0.0/src/Forms/fimport.pas --- tominote-1.0.0/src/Forms/fimport.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Forms/fimport.pas 2017-11-29 21:45:59.000000000 +0000 @@ -181,4 +181,4 @@ chkbIncludeEntryDir.Enabled := radgImportFrom.ItemIndex = 1; end; -end. +end. diff -Nru tominote-1.0.0/src/Forms/fmain.lfm tominote-1.0.0/src/Forms/fmain.lfm --- tominote-1.0.0/src/Forms/fmain.lfm 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Forms/fmain.lfm 2017-11-29 21:45:59.000000000 +0000 @@ -143,13 +143,13 @@ Height = 30 Top = 336 Width = 600 - Panels = < + Panels = < item Width = 260 - end + end item Width = 320 - end + end item Width = 260 end> @@ -232,6 +232,7 @@ OnExit = editRenameExit OnKeyDown = editRenameKeyDown ParentColor = True + PopupMenu = menuEdit TabOrder = 3 Visible = False end @@ -1264,7 +1265,6 @@ Caption = 'Delete(&D)' ImageIndex = 28 OnExecute = actnDeleteExecute - ShortCut = 46 end object actnUndo: TAction Category = 'Note' @@ -7978,4 +7978,36 @@ left = 404 top = 113 end + object menuEdit: TPopupMenu + Images = imglMain + left = 320 + top = 240 + object pmiCut2: TMenuItem + Action = actnCut + end + object pmiCopy2: TMenuItem + Action = actnCopy + end + object pmiPaste2: TMenuItem + Action = actnPaste + end + object pmiSplitter41: TMenuItem + Caption = '-' + end + object pmiSelectAll2: TMenuItem + Action = actnSelectAll + end + object pmiDelete2: TMenuItem + Action = actnDelete + end + object pmiSplitter42: TMenuItem + Caption = '-' + end + object pmiUndo2: TMenuItem + Action = actnUndo + end + object pmiRedo2: TMenuItem + Action = actnRedo + end + end end diff -Nru tominote-1.0.0/src/Forms/fmain.pas tominote-1.0.0/src/Forms/fmain.pas --- tominote-1.0.0/src/Forms/fmain.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Forms/fmain.pas 2017-11-29 21:45:59.000000000 +0000 @@ -217,6 +217,17 @@ pmiSplitter32 : TMenuItem; pmiSplitter33 : TMenuItem; + menuEdit : TPopupMenu; + pmiCut2 : TMenuItem; + pmiCopy2 : TMenuItem; + pmiPaste2 : TMenuItem; + pmiSelectAll2 : TMenuItem; + pmiDelete2 : TMenuItem; + pmiUndo2 : TMenuItem; + pmiRedo2 : TMenuItem; + pmiSplitter41 : TMenuItem; + pmiSplitter42 : TMenuItem; + tbarMain : TToolBar; tbtnNew : TToolButton; tbtnOpen : TToolButton; @@ -328,6 +339,9 @@ private + FConfigDir : string; // 配置文件所在目录 + FLangDir : string; // 语言文件所在目录 + FTreeDB : TTreeDB; // 数据库管理器 FDBFullName : string; // 数据库完整文件名 FDBFileName : string; // 数据库文件名(去掉扩展名) @@ -446,7 +460,6 @@ procedure ReLoadNodeName; public - LangDir: string; procedure LoadControlState; function GetTotalHistorySize: integer; procedure DiscardHistory(KeepSelected: boolean); @@ -467,6 +480,8 @@ procedure ExportToDir(ToPath: string; Node: TTreeNode; Ext: string; Depth: integer); function ExportToDB(ToPath: string; Node: TTreeNode; Depth: integer): boolean; + property ConfigDir : string read FConfigDir; + property LangDir : string read FLangDir; property DBFullName: string read FDBFullName; property DBDirName : string read FDBFileDir; property DBFileName: string read FDBFileName; @@ -495,8 +510,8 @@ Res_BackupDBFail = 'Fail to backup database!'; Res_RecentFileNotExists = 'The file doesn''t exists, do you want to remove the Menu Item of this recent file?'; Res_DataChangedTip = 'The data has been changed. Do you want to save it?'; - Res_CoverFileTip = 'The file already exists. Do you want to cover it?'; - Res_CoverFileFail = 'Fail to cover file!'; + Res_OverwriteFileTip = 'The file already exists. Do you want to overwrite it?'; + Res_OverwriteFileFail = 'Fail to overwrite file!'; Res_DelNodeWarning = 'The node will not be restored after deleting, Are you sure to delete the node?'; Res_EmptyRecyWarning = 'The nodes will not be recovered after empty the recycler. Are you sure to empty the recycler?'; Res_UnnamedNode = 'Unnamed Node'; @@ -537,14 +552,18 @@ FTreeDB := TTreeDB.Create; FTreeDB.OnActiveChanged := @DBActiveChanged; - if Application.HasOption('l', 'lang') then LangDir := ExpandFileName(Application.GetOptionValue('l', 'lang')) - else LangDir := ConcatPaths([AppDir, DefLanguagesDir]); + if Application.HasOption('l', 'lang') then + FLangDir := ExpandFileName(Application.GetOptionValue('l', 'lang')) + else + FLangDir := ConcatPaths([AppDir, DefLanguagesDir]); + // TomiNote.ini 和 script.ini 都存放在 FConfigDir 目录中 if Application.HasOption('c', 'config') then - ConfigFileName := ExpandFileName(Application.GetOptionValue('c', 'config')) - else ConfigFileName := ChangeFileExt(ParamStr(0), '.ini'); - ForceDirectories(ExtractFileDir(ConfigFileName)); - Config := TConfig.Create(ConfigFileName); + FConfigDir := ExpandFileName(Application.GetOptionValue('c', 'config')) + else + FConfigDir := AppDir; + ForceDirectories(FConfigDir); + Config := TConfig.Create(ConcatPaths([FConfigDir, AppName + '.ini'])); FEditHistory := THistoryManager.Create(editRename); FEditHistory.CreateHistory(''); @@ -556,7 +575,7 @@ // 初始化窗口状态 if Config.Language <> '' then - SetDefaultLang(Config.Language, LangDir); + SetDefaultLang(Config.Language, FLangDir); actnTextUtils.Caption := actnNodeUtils.Caption; @@ -636,7 +655,10 @@ var Size: integer; begin - if editRename.Visible then editRename.Hide; + if editRename.Visible then begin + FEditHistory.Enabled := False; + editRename.Hide; + end; if not (ssCtrl in Shift) then Exit; @@ -1010,11 +1032,19 @@ procedure TformMain.actnPrevNodeExecute(Sender: TObject); begin + if editRename.Visible then begin + FEditHistory.Enabled := False; + editRename.Hide; + end; SelectPrevNode; end; procedure TformMain.actnNextNodeExecute(Sender: TObject); begin + if editRename.Visible then begin + FEditHistory.Enabled := False; + editRename.Hide; + end; SelectNextNode; end; @@ -1184,8 +1214,8 @@ if Key = VK_RETURN then begin editRename.OnExit(Sender); end else if Key = VK_ESCAPE then begin - editRename.Hide; FEditHistory.Enabled := False; + editRename.Hide; FLastNode.TreeView.SetFocus; end; end; @@ -1195,6 +1225,7 @@ // 需要检查重命名框是否可见,否则会出错 if not editRename.Visible then Exit; SubmitRename; + FEditHistory.Enabled := False; editRename.Hide; FLastNode.TreeView.SetFocus; FEditHistory.Enabled := False; @@ -1204,7 +1235,7 @@ var PSR: PSearchRecord; FixNum: Integer; - Str: string; + S: string; begin if lstbInfo.ItemIndex = -1 then Exit; @@ -1220,12 +1251,12 @@ // 是 #13#10,长度不同,所以需要修补才能得到正确的 SelStart FixNum := 0; if Length(LineEnding) > 1 then begin - Str := FTreeDB.GetNote(PSR^.ID); - Str := UTF8Copy(Str, 1, PSR^.UStart); - FixNum := Str.CountChar(#10); + S := FTreeDB.GetNote(PSR^.ID); + S := UTF8Copy(S, 1, PSR^.UStart); + FixNum := S.CountChar(#10); end; - memoNote.SelStart := PSR^.UStart - 1 + FixNum; + memoNote.SelStart := PSR^.UStart + FixNum; memoNote.SelLength := PSR^.ULength; end; end; @@ -1422,7 +1453,10 @@ UpdateDBControlState; - if editRename.Visible then editRename.Hide; + if editRename.Visible then begin + FEditHistory.Enabled := False; + editRename.Hide; + end; end; procedure TformMain.DataStateChanged(ADataChanged: Boolean); @@ -1433,17 +1467,17 @@ procedure TformMain.UpdateCaption(ADataChanged: Boolean); var - Str: string; + S: string; begin - Str := Format('%s %s', [AppTitle, Version]); + S := Format('%s %s', [AppTitle, Version]); if FTreeDB.Active then begin - Str := Str + ' [' + FDBFileName + ']'; + S := S + ' [' + FDBFileName + ']'; if ADataChanged then - Str := Str + ' *'; + S := S + ' *'; end; - Caption := Str; + Caption := S; end; // debug @@ -1584,7 +1618,7 @@ FMemoHistory.Enabled := True; memoNote.Lines.EndUpdate; - if APrevText.Length > Length(memoNote.Text) then + if Length(APrevText) > Length(memoNote.Text) then FMemoHistory.AddRecordSimply(APrevText); end; @@ -1848,19 +1882,20 @@ if DirectoryExists(Result) then Exit; Result := AppDir; + if FileIsReadOnly(Result) then Result := ''; end; -function CoverFileDialog(AFileName, ATitle: string): boolean; +function OverwriteFileDialog(AFileName, ATitle: string): boolean; begin Result := not FileExists(AFileName); if Result then Exit; - Result := Application.MessageBox(PChar(Res_CoverFileTip), PChar(ATitle), MB_YESNO + MB_ICONQUESTION) = idYes; + Result := Application.MessageBox(PChar(Res_OverwriteFileTip), PChar(ATitle), MB_YESNO + MB_ICONQUESTION) = idYes; if Result and not DeleteFile(AFileName) then begin Result := False; - Application.MessageBox(PChar(Res_CoverFileFail), PChar(ATitle), MB_OK + MB_ICONERROR); + Application.MessageBox(PChar(Res_OverwriteFileFail), PChar(ATitle), MB_OK + MB_ICONERROR); end; end; @@ -1980,7 +2015,7 @@ function TformMain.CreateDB(AFileName: string = ''): boolean; var - CoverFile: Boolean; + OverwriteFile: Boolean; begin Result := False; @@ -1994,17 +2029,17 @@ if not SaveDBDialog then Exit; - CoverFile := False; + OverwriteFile := False; if FileExists(AFileName) then begin - CoverFile := Application.MessageBox(PChar(Res_CoverFileTip), PChar(AppTitle), MB_YESNO + MB_ICONQUESTION) = idYes; - if not CoverFile then Exit; + OverwriteFile := Application.MessageBox(PChar(Res_OverwriteFileTip), PChar(AppTitle), MB_YESNO + MB_ICONQUESTION) = idYes; + if not OverwriteFile then Exit; end; if not CloseDB(False) then Exit; - if CoverFile and not DeleteFile(AFileName) then + if OverwriteFile and not DeleteFile(AFileName) then begin - Application.MessageBox(PChar(Res_CoverFileFail), PChar(AppTitle), MB_OK + MB_ICONERROR); + Application.MessageBox(PChar(Res_OverwriteFileFail), PChar(AppTitle), MB_OK + MB_ICONERROR); Exit; end; @@ -2094,7 +2129,7 @@ function TformMain.SaveDBAs(AFileName: String): boolean; var - CoverFile: Boolean; + OverwriteFile: Boolean; begin Result := False; @@ -2106,10 +2141,10 @@ AFileName := svdg1.FileName; end; - CoverFile := False; + OverwriteFile := False; if FileExists(AFileName) then begin - CoverFile := Application.MessageBox(PChar(Res_CoverFileTip), PChar(AppTitle), MB_YESNO + MB_ICONQUESTION) = idYes; - if not CoverFile then Exit; + OverwriteFile := Application.MessageBox(PChar(Res_OverwriteFileTip), PChar(AppTitle), MB_YESNO + MB_ICONQUESTION) = idYes; + if not OverwriteFile then Exit; end; Result := FTreeDB.ExportToDB(RootID, RootID, AFileName + '.tmp', AllDepth) and @@ -2120,12 +2155,12 @@ Exit; end; - if CoverFile then begin + if OverwriteFile then begin if AFileName = FDBFullName then CloseDB(False); if not DeleteFile(AFileName) then begin - Application.MessageBox(PChar(Res_CoverFileFail), PChar(AppTitle), MB_OK + MB_ICONERROR); + Application.MessageBox(PChar(Res_OverwriteFileFail), PChar(AppTitle), MB_OK + MB_ICONERROR); Exit; end; end; @@ -2134,7 +2169,7 @@ Result := RenameFile(AFileName + '.tmp', AFileName); if not Result then begin - Application.MessageBox(PChar(Res_CoverFileFail), PChar(AppTitle), MB_OK + MB_ICONERROR); + Application.MessageBox(PChar(Res_OverwriteFileFail), PChar(AppTitle), MB_OK + MB_ICONERROR); Exit; end; @@ -2863,11 +2898,11 @@ AChanged := False; for i := 0 to Strs.Count - 1 do begin Line := Strs[i]; - if Line.Length >= 4 then begin - case LowerCase(Line.Substring(0, 4)) of - 'sch=': Sch := Line.Substring(4); + if Length(Line) >= 4 then begin + case LowerCase(Copy(Line, 1, 4)) of + 'sch=': Sch := Copy(Line, 5, Length(Line) - 4); 'rep=': if Sch <> '' then begin - Rep := Line.Substring(4); + Rep := Copy(Line, 5, Length(Line) - 4); AText := ReplaceRegExpr(Sch, AText, Rep, True); AChanged := True; end; @@ -2877,7 +2912,7 @@ if AChanged then begin FMemoHistory.Enabled := False; if InSelection and (memoNote.SelLength <> 0) then begin - FMemoHistory.History.AddRecord(memoNote.SelStart, memoNote.SelLength, memoNote.SelText, memoNote.SelStart, UTF8Length(AText), AText); + FMemoHistory.History.AddRecord(memoNote.SelStart, memoNote.SelLength, memoNote.SelText, memoNote.SelStart, UTF8LengthFast(AText), AText); memoNote.SelText := AText end else begin memoNote.Text := AText; @@ -3036,7 +3071,7 @@ Sample := UTF8Copy(ANote, 1, PSR^.ULength + 10) else Sample := UTF8Copy(ANote, PSR^.UStart - 10, PSR^.ULength + 20); - Sample := Sample.Replace(#10, ' '); + Sample := Sample.Replace(#10, ' ', [rfReplaceAll]); lstbInfo.Items.Add(Format('[%s] %s | (%d %d)', [AName, Sample, PSR^.UStart, PSR^.ULength])); diff -Nru tominote-1.0.0/src/Forms/ftextutils.pas tominote-1.0.0/src/Forms/ftextutils.pas --- tominote-1.0.0/src/Forms/ftextutils.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Forms/ftextutils.pas 2017-11-29 21:45:59.000000000 +0000 @@ -12,20 +12,20 @@ { TformTextUtils } TformTextUtils = class(TForm) - pgctMain: TPageControl; - tabsScript: TTabSheet; - pnlScript: TPanel; - lstbScriptList: TListBox; - spltScript: TSplitter; - memoScript: TMemo; - editScriptName: TEdit; - bttnAddScript: TButton; - bttnDeleteScript: TButton; - bttnModifyScript: TButton; - chkbSearchInSelection: TCheckBox; + pgctMain : TPageControl; + tabsScript : TTabSheet; + pnlScript : TPanel; + lstbScriptList : TListBox; + spltScript : TSplitter; + memoScript : TMemo; + editScriptName : TEdit; + bttnAddScript : TButton; + bttnDeleteScript : TButton; + bttnModifyScript : TButton; + chkbSearchInSelection : TCheckBox; - bttnOK: TButton; - bttnCancel: TButton; + bttnOK : TButton; + bttnCancel : TButton; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); @@ -58,7 +58,7 @@ implementation uses - fmain, uconfig; + fmain, uconfig, ucommon; const ScriptFile = 'script.ini'; @@ -168,17 +168,24 @@ var Index: integer; begin - if lstbScriptList.ItemIndex = -1 then Exit; - if Application.MessageBox(PChar(Res_DelItemWarning), PChar(Caption), MB_YESNO + MB_ICONWARNING) <> ID_YES then Exit; + Index := lstbScriptList.ItemIndex; - FScripts.Delete(FScripts.IndexOfName(lstbScriptList.Items[lstbScriptList.ItemIndex])); + if Index = -1 then Exit; - Index := lstbScriptList.ItemIndex; + { + // hold Shift key to ignore warning + if (not IsKeyDown(VK_SHIFT)) and (Application.MessageBox(PChar(Res_DelItemWarning), PChar(Caption), MB_YESNO + MB_ICONWARNING) <> ID_YES) then Exit; + } + + // can't ignore warning + if Application.MessageBox(PChar(Res_DelItemWarning), PChar(Caption), MB_YESNO + MB_ICONWARNING) <> ID_YES then Exit; + + FScripts.Delete(FScripts.IndexOfName(lstbScriptList.Items[Index])); - if FLastScriptName = lstbScriptList.Items[lstbScriptList.ItemIndex] then + if FLastScriptName = lstbScriptList.Items[Index] then FLastScriptName := ''; - lstbScriptList.DeleteSelected; + lstbScriptList.Items.Delete(Index); if lstbScriptList.Count - 1 >= Index then lstbScriptList.ItemIndex := Index @@ -216,7 +223,7 @@ Line := ''; Title := ''; Content := ''; - ConfigFile := ConcatPaths([AppDir, ScriptFile]); + ConfigFile := ConcatPaths([formMain.ConfigDir, ScriptFile]); Strs := TStringList.Create; try @@ -230,7 +237,7 @@ lstbScriptList.Items.Add(Title); Content := ''; end; - Title := Line.Substring(1, Length(Line) - 2); + Title := Copy(Line, 2, Length(Line) - 2); end else if Content = '' then Content := Line else @@ -258,7 +265,7 @@ Strs: TStringList; i: integer; begin - ConfigFile := ConcatPaths([AppDir, ScriptFile]); + ConfigFile := ConcatPaths([formMain.ConfigDir, ScriptFile]); if FScripts.Count = 0 then begin if FileExists(ConfigFile) then DeleteFile(ConfigFile); diff -Nru tominote-1.0.0/src/languages/TomiNote.cs.po tominote-1.0.0/src/languages/TomiNote.cs.po --- tominote-1.0.0/src/languages/TomiNote.cs.po 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/languages/TomiNote.cs.po 2017-11-29 21:45:59.000000000 +0000 @@ -88,6 +88,10 @@ "\n" "This program uses dynamic load node, when you open the database, it will not load all the nodes, only the first depth node is loaded, when you expand a node, it will load its next node, so you don't have to worry about loading too much data too slow, but the count of nodes should not exceed 2147483640, which is determined by the type of integer used by the program, you can modify the source code to make it support more The number of nodes, but also consume more database space.\n" "\n" +"You can use the command line parameter --c or --config to specify the directory of the configuration file, such as: TomiNote --config=~/.config/TomiNote\n" +"\n" +"You can use the command line parameter --l or --lang to specify the directory of the language files, such as: TomiNote --lang=/usr/share/TomiNote/languages\n" +"\n" "\n" "\n" "[Move Node]\n" @@ -212,7 +216,7 @@ "\n" "You can search for text in node name and node content. You can search for text in \"Selected node\" or \"Selected node and its descendants\" or \"All nodes\".\n" "\n" -"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, backslashes will be converted to \\\\, and if the search content or replacement contains With \\r \\n \\t \\\\, the backslash in these symbols will not be converted.\n" +"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, the backslash will not be processed, only the special backslash will be converted to \\\\. For example: '\\a\\\\b'#10 will be converted to '\\a\\\\b\\r', '\\a\\\\b\\'#10 will be converted to '\\a\\\\b\\\\\\r'.\n" "\n" "The search results will be listed in the InfoBar, which you can double-click to jump to the corresponding place of the search result.\n" "\n" @@ -224,6 +228,10 @@ "\n" "Note: The nodes that executed the multi-node replace operation will lose their history.\n" "\n" +"Note: The contents of the search and replace operations are taken from the database, and the line-ending character used in the database is \\n, so you can never found the \\r character.\n" +"\n" +"Note: If the pasted content contains line-ending character that do not match the current system, you can convert the line-ending to the current system's line-ending by \"switching to other nodes and then switching back\", the wrong line-ending will cause the search results to display incorrectly.\n" +"\n" "\n" "\n" "[Import And Export]\n" @@ -546,14 +554,6 @@ msgid "Fail to close database!" msgstr "Zavření databáze selhalo!" -#: fmain.res_coverfilefail -msgid "Fail to cover file!" -msgstr "Chyba přepsání soubor!" - -#: fmain.res_coverfiletip -msgid "The file already exists. Do you want to cover it?" -msgstr "Soubor již existuje. Chcete jej přepsat?" - #: fmain.res_createdbfail msgid "Fail to create database!" msgstr "Chyba vytvoření databáze!" @@ -586,6 +586,14 @@ msgid "Fail to open database!" msgstr "Chyba otevření databáze!" +#: fmain.res_overwritefilefail +msgid "Fail to overwrite file!" +msgstr "Chyba přepsání soubor!" + +#: fmain.res_overwritefiletip +msgid "The file already exists. Do you want to overwrite it?" +msgstr "Soubor již existuje. Chcete jej přepsat?" + #: fmain.res_recentfilenotexists msgid "The file doesn't exists, do you want to remove the Menu Item of this recent file?" msgstr "Soubor neexistuje, chcete odebrat položku menu tohoto nedávného souboru?" @@ -655,7 +663,7 @@ "Theme\n" "Others\n" msgstr "" -"Obecný\n" +"Obecné\n" "Rozvržení\n" "Téma\n" "Jiné\n" @@ -1201,3 +1209,4 @@ #: uconfig.res_notactive msgid "NotActive" msgstr "Neaktivní" + diff -Nru tominote-1.0.0/src/languages/TomiNote.en.po tominote-1.0.0/src/languages/TomiNote.en.po --- tominote-1.0.0/src/languages/TomiNote.en.po 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/languages/TomiNote.en.po 2017-11-29 21:45:59.000000000 +0000 @@ -120,6 +120,10 @@ "\n" "This program uses dynamic load node, when you open the database, it will not load all the nodes, only the first depth node is loaded, when you expand a node, it will load its next node, so you don't have to worry about loading too much data too slow, but the count of nodes should not exceed 2147483640, which is determined by the type of integer used by the program, you can modify the source code to make it support more The number of nodes, but also consume more database space.\n" "\n" +"You can use the command line parameter --c or --config to specify the directory of the configuration file, such as: TomiNote --config=~/.config/TomiNote\n" +"\n" +"You can use the command line parameter --l or --lang to specify the directory of the language files, such as: TomiNote --lang=/usr/share/TomiNote/languages\n" +"\n" "\n" "\n" "[Move Node]\n" @@ -244,7 +248,7 @@ "\n" "You can search for text in node name and node content. You can search for text in \"Selected node\" or \"Selected node and its descendants\" or \"All nodes\".\n" "\n" -"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, backslashes will be converted to \\\\, and if the search content or replacement contains With \\r \\n \\t \\\\, the backslash in these symbols will not be converted.\n" +"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, the backslash will not be processed, only the special backslash will be converted to \\\\. For example: '\\a\\\\b'#10 will be converted to '\\a\\\\b\\r', '\\a\\\\b\\'#10 will be converted to '\\a\\\\b\\\\\\r'.\n" "\n" "The search results will be listed in the InfoBar, which you can double-click to jump to the corresponding place of the search result.\n" "\n" @@ -256,6 +260,10 @@ "\n" "Note: The nodes that executed the multi-node replace operation will lose their history.\n" "\n" +"Note: The contents of the search and replace operations are taken from the database, and the line-ending character used in the database is \\n, so you can never found the \\r character.\n" +"\n" +"Note: If the pasted content contains line-ending character that do not match the current system, you can convert the line-ending to the current system's line-ending by \"switching to other nodes and then switching back\", the wrong line-ending will cause the search results to display incorrectly.\n" +"\n" "\n" "\n" "[Import And Export]\n" @@ -546,6 +554,10 @@ "\n" "This program uses dynamic load node, when you open the database, it will not load all the nodes, only the first depth node is loaded, when you expand a node, it will load its next node, so you don't have to worry about loading too much data too slow, but the count of nodes should not exceed 2147483640, which is determined by the type of integer used by the program, you can modify the source code to make it support more The number of nodes, but also consume more database space.\n" "\n" +"You can use the command line parameter --c or --config to specify the directory of the configuration file, such as: TomiNote --config=~/.config/TomiNote\n" +"\n" +"You can use the command line parameter --l or --lang to specify the directory of the language files, such as: TomiNote --lang=/usr/share/TomiNote/languages\n" +"\n" "\n" "\n" "[Move Node]\n" @@ -670,7 +682,7 @@ "\n" "You can search for text in node name and node content. You can search for text in \"Selected node\" or \"Selected node and its descendants\" or \"All nodes\".\n" "\n" -"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, backslashes will be converted to \\\\, and if the search content or replacement contains With \\r \\n \\t \\\\, the backslash in these symbols will not be converted.\n" +"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, the backslash will not be processed, only the special backslash will be converted to \\\\. For example: '\\a\\\\b'#10 will be converted to '\\a\\\\b\\r', '\\a\\\\b\\'#10 will be converted to '\\a\\\\b\\\\\\r'.\n" "\n" "The search results will be listed in the InfoBar, which you can double-click to jump to the corresponding place of the search result.\n" "\n" @@ -682,6 +694,10 @@ "\n" "Note: The nodes that executed the multi-node replace operation will lose their history.\n" "\n" +"Note: The contents of the search and replace operations are taken from the database, and the line-ending character used in the database is \\n, so you can never found the \\r character.\n" +"\n" +"Note: If the pasted content contains line-ending character that do not match the current system, you can convert the line-ending to the current system's line-ending by \"switching to other nodes and then switching back\", the wrong line-ending will cause the search results to display incorrectly.\n" +"\n" "\n" "\n" "[Import And Export]\n" @@ -1003,14 +1019,6 @@ msgid "Fail to close database!" msgstr "Fail to close database!" -#: fmain.res_coverfilefail -msgid "Fail to cover file!" -msgstr "Fail to cover file!" - -#: fmain.res_coverfiletip -msgid "The file already exists. Do you want to cover it?" -msgstr "The file already exists. Do you want to cover it?" - #: fmain.res_createdbfail msgid "Fail to create database!" msgstr "Fail to create database!" @@ -1043,6 +1051,14 @@ msgid "Fail to open database!" msgstr "Fail to open database!" +#: fmain.res_overwritefilefail +msgid "Fail to overwrite file!" +msgstr "Fail to overwrite file!" + +#: fmain.res_overwritefiletip +msgid "The file already exists. Do you want to overwrite it?" +msgstr "The file already exists. Do you want to overwrite it?" + #: fmain.res_recentfilenotexists msgid "The file doesn't exists, do you want to remove the Menu Item of this recent file?" msgstr "The file doesn't exists, do you want to remove the Menu Item of this recent file?" @@ -1169,239 +1185,239 @@ #: tformmain.actnabout.caption msgid "About(&A)" -msgstr "About(&A)" +msgstr "&About" #: tformmain.actnaddchild.caption msgid "Add To Child Last(&L)" -msgstr "Add To Child Last(&L)" +msgstr "Add To Child &Last" #: tformmain.actnaddchildfirst.caption msgid "Add To Child First(&F)" -msgstr "Add To Child First(&F)" +msgstr "Add To Child &First" #: tformmain.actnbrighttheme.caption msgid "Bright Theme(&L)" -msgstr "Bright Theme(&L)" +msgstr "&Bright Theme" #: tformmain.actnclose.caption msgid "Close(&C)" -msgstr "Close(&C)" +msgstr "&Close" #: tformmain.actncollapse.caption msgid "Collapse(&C)" -msgstr "Collapse(&C)" +msgstr "&Collapse" #: tformmain.actncopy.caption msgid "Copy(&C)" -msgstr "Copy(&C)" +msgstr "&Copy" #: tformmain.actncut.caption msgid "Cut(&T)" -msgstr "Cut(&T)" +msgstr "Cu&t" #: tformmain.actndarktheme.caption msgid "Dark Theme(&D)" -msgstr "Dark Theme(&D)" +msgstr "&Dark Theme" #: tformmain.actndelete.caption msgid "Delete(&D)" -msgstr "Delete(&D)" +msgstr "&Delete" #: tformmain.actndeletenode.caption msgid "Delete Node(&D)" -msgstr "Delete Node(&D)" +msgstr "&Delete Node" #: tformmain.actnemptyrecycler.caption msgid "Empty Recycler(&T)" -msgstr "Empty Recycler(&T)" +msgstr "Emp&ty Recycler" #: tformmain.actnexit.caption msgid "Exit(&X)" -msgstr "Exit(&X)" +msgstr "E&xit" #: tformmain.actnexpand.caption msgid "Expand(&X)" -msgstr "Expand(&X)" +msgstr "E&xpand" #: tformmain.actnexport.caption msgid "Export(&E) ..." -msgstr "Export(&E) ..." +msgstr "&Export ..." #: tformmain.actnfullscreen.caption msgid "Full Screen(&F)" -msgstr "Full Screen(&F)" +msgstr "&Full Screen" #: tformmain.actnfullwindow.caption msgid "Full Window(&W)" -msgstr "Full Window(&W)" +msgstr "Full &Window" #: tformmain.actnhelp.caption msgid "Help Content(&H)" -msgstr "Help Content(&H)" +msgstr "&Help Content" #: tformmain.actnimport.caption msgid "Import(&I) ..." -msgstr "Import(&I) ..." +msgstr "&Import ..." #: tformmain.actninsert.caption msgid "Add To Front(&G)" -msgstr "Add To Front(&G)" +msgstr "Add To Front" #: tformmain.actninsertbehind.caption msgid "Add To Behind(&H)" -msgstr "Add To Behind(&H)" +msgstr "Add To Be&hind" #: tformmain.actnmovedown.caption msgid "Move Down(&N)" -msgstr "Move Down(&N)" +msgstr "Move Dow&n" #: tformmain.actnmoveup.caption msgid "Move Up(&U)" -msgstr "Move Up(&U)" +msgstr "Move &Up" #: tformmain.actnnew.caption msgid "New(&N) ..." -msgstr "New(&N) ..." +msgstr "&New ..." #: tformmain.actnnextnode.caption msgid "Next Node(&N)" -msgstr "Next Node(&N)" +msgstr "&Next Node" #: tformmain.actnnodeutils.caption msgid "Utils(&U) ..." -msgstr "Utils(&U) ..." +msgstr "&Utils ..." #: tformmain.actnopen.caption msgid "Open(&O) ..." -msgstr "Open(&O) ..." +msgstr "&Open ..." #: tformmain.actnoptions.caption msgid "Options(&O) ..." -msgstr "Options(&O) ..." +msgstr "&Options ..." #: tformmain.actnpaste.caption msgid "Paste(&P)" -msgstr "Paste(&P)" +msgstr "&Paste" #: tformmain.actnprevnode.caption msgid "Prev Node(&P)" -msgstr "Prev Node(&P)" +msgstr "&Prev Node" #: tformmain.actnrecyclenode.caption msgid "Recycle Node(&V)" -msgstr "Recycle Node(&V)" +msgstr "Recycle Node" #: tformmain.actnredo.caption msgid "Redo(&R)" -msgstr "Redo(&R)" +msgstr "&Redo" #: tformmain.actnregexprhelp.caption msgid "Regular expression(&R)" -msgstr "Regular expression(&R)" +msgstr "&Regular expression" #: tformmain.actnrename.caption msgid "Rename(&R)" -msgstr "Rename(&R)" +msgstr "&Rename" #: tformmain.actnrestorenode.caption msgid "Restore Node(&R)" -msgstr "Restore Node(&R)" +msgstr "&Restore Node" #: tformmain.actnsave.caption msgid "Save(&S)" -msgstr "Save(&S)" +msgstr "&Save" #: tformmain.actnsaveas.caption msgid "Save As(&A) ..." -msgstr "Save As(&A) ..." +msgstr "Save &As ..." #: tformmain.actnsearch.caption msgid "Search(&S) ..." -msgstr "Search(&S) ..." +msgstr "&Search ..." #: tformmain.actnselectall.caption msgid "Select All(&A)" -msgstr "Select All(&A)" +msgstr "Select &All" #: tformmain.actnstriptailspace.caption msgid "Strip Trailing Spaces(&S)" -msgstr "Strip Trailing Spaces(&S)" +msgstr "&Strip Trailing Spaces" #: tformmain.actntoggleinfobar.caption msgid "InfoBar(&I)" -msgstr "InfoBar(&I)" +msgstr "&InfoBar" #: tformmain.actntogglemenubar.caption msgid "MenuBar(&M)" -msgstr "MenuBar(&M)" +msgstr "&MenuBar" #: tformmain.actntogglerecybar.caption msgid "RecyBar(&R)" -msgstr "RecyBar(&R)" +msgstr "&RecyBar" #: tformmain.actntogglestatbar.caption msgid "StatBar(&S)" -msgstr "StatBar(&S)" +msgstr "&StatBar" #: tformmain.actntoggletheme.caption msgid "Toggle Theme(&T)" -msgstr "Toggle Theme(&T)" +msgstr "&Toggle Theme" #: tformmain.actntoggletoolbar.caption msgid "ToolBar(&T)" -msgstr "ToolBar(&T)" +msgstr "&ToolBar" #: tformmain.actntoggletreebar.caption msgid "TreeBar(&D)" -msgstr "TreeBar(&D)" +msgstr "TreeBar" #: tformmain.actnundo.caption msgid "Undo(&U)" -msgstr "Undo(&U)" +msgstr "&Undo" #: tformmain.actnwordwrap.caption msgid "Line Wrapping(&W)" -msgstr "Line Wrapping(&W)" +msgstr "Line &Wrapping" #: tformmain.mmiclearrecentfiles.caption msgid "Clear Recent Files(&C)" -msgstr "Clear Recent Files(&C)" +msgstr "&Clear Recent Files" #: tformmain.mmiedit.caption msgid "Edit(&E)" -msgstr "Edit(&E)" +msgstr "&Edit" #: tformmain.mmifile.caption msgid "File(&F)" -msgstr "File(&F)" +msgstr "&File" #: tformmain.mmihelp.caption msgid "Help(&H)" -msgstr "Help(&H)" +msgstr "&Help" #: tformmain.mmilayout.caption msgid "Layout(&L)" -msgstr "Layout(&L)" +msgstr "&Layout" #: tformmain.mminode.caption msgid "Node(&N)" -msgstr "Node(&N)" +msgstr "&Node" #: tformmain.mminote.caption msgid "Text(&T)" -msgstr "Text(&T)" +msgstr "&Text" #: tformmain.mmirecentfiles.caption msgid "Recent Files(&R)" -msgstr "Recent Files(&R)" +msgstr "&Recent Files" #: tformmain.mmitheme.caption msgid "Theme(&T)" -msgstr "Theme(&T)" +msgstr "&Theme" #: tformmain.mmiview.caption msgid "View(&V)" -msgstr "View(&V)" +msgstr "&View" #: tformnodeutils.caption msgid "Node Utils" @@ -1605,7 +1621,7 @@ #: tformtextutils.chkbsearchinselection.caption msgid "Search in selected text (&S)" -msgstr "Search in selected text (&S)" +msgstr "&Search in selected text" #: tformtextutils.tabsscript.caption msgid "Script" @@ -1617,31 +1633,33 @@ #: uconfig.res_captioncancel msgid "Cancel(&C)" -msgstr "Cancel(&C)" +msgstr "&Cancel" #: uconfig.res_captionexecute msgid "Execute(&E)" -msgstr "Execute(&E)" +msgstr "&Execute" #: uconfig.res_captionexport msgid "Export(&E)" -msgstr "Export(&E)" +msgstr "&Export" #: uconfig.res_captionimport msgid "Import(&I)" -msgstr "Import(&I)" +msgstr "&Import" #: uconfig.res_captionok msgid "OK(&O)" -msgstr "OK(&O)" +msgstr "&OK" #: uconfig.res_captionreplace +#, fuzzy +#| msgid "&Replace(&R)" msgid "Replace(&R)" -msgstr "Replace(&R)" +msgstr "&Replace" #: uconfig.res_captionsearch msgid "Search(&S)" -msgstr "Search(&S)" +msgstr "&Search" #: uconfig.res_ignorecase msgid "Ignore case" @@ -1658,3 +1676,4 @@ #: uconfig.res_notactive msgid "NotActive" msgstr "NotActive" + diff -Nru tominote-1.0.0/src/languages/TomiNote.po tominote-1.0.0/src/languages/TomiNote.po --- tominote-1.0.0/src/languages/TomiNote.po 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/languages/TomiNote.po 2017-11-29 21:45:59.000000000 +0000 @@ -72,6 +72,10 @@ "\n" "This program uses dynamic load node, when you open the database, it will not load all the nodes, only the first depth node is loaded, when you expand a node, it will load its next node, so you don't have to worry about loading too much data too slow, but the count of nodes should not exceed 2147483640, which is determined by the type of integer used by the program, you can modify the source code to make it support more The number of nodes, but also consume more database space.\n" "\n" +"You can use the command line parameter --c or --config to specify the directory of the configuration file, such as: TomiNote --config=~/.config/TomiNote\n" +"\n" +"You can use the command line parameter --l or --lang to specify the directory of the language files, such as: TomiNote --lang=/usr/share/TomiNote/languages\n" +"\n" "\n" "\n" "[Move Node]\n" @@ -196,7 +200,7 @@ "\n" "You can search for text in node name and node content. You can search for text in \"Selected node\" or \"Selected node and its descendants\" or \"All nodes\".\n" "\n" -"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, backslashes will be converted to \\\\, and if the search content or replacement contains With \\r \\n \\t \\\\, the backslash in these symbols will not be converted.\n" +"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, the backslash will not be processed, only the special backslash will be converted to \\\\. For example: '\\a\\\\b'#10 will be converted to '\\a\\\\b\\r', '\\a\\\\b\\'#10 will be converted to '\\a\\\\b\\\\\\r'.\n" "\n" "The search results will be listed in the InfoBar, which you can double-click to jump to the corresponding place of the search result.\n" "\n" @@ -208,6 +212,10 @@ "\n" "Note: The nodes that executed the multi-node replace operation will lose their history.\n" "\n" +"Note: The contents of the search and replace operations are taken from the database, and the line-ending character used in the database is \\n, so you can never found the \\r character.\n" +"\n" +"Note: If the pasted content contains line-ending character that do not match the current system, you can convert the line-ending to the current system's line-ending by \"switching to other nodes and then switching back\", the wrong line-ending will cause the search results to display incorrectly.\n" +"\n" "\n" "\n" "[Import And Export]\n" @@ -521,14 +529,6 @@ msgid "Fail to close database!" msgstr "" -#: fmain.res_coverfilefail -msgid "Fail to cover file!" -msgstr "" - -#: fmain.res_coverfiletip -msgid "The file already exists. Do you want to cover it?" -msgstr "" - #: fmain.res_createdbfail msgid "Fail to create database!" msgstr "" @@ -561,6 +561,14 @@ msgid "Fail to open database!" msgstr "" +#: fmain.res_overwritefilefail +msgid "Fail to overwrite file!" +msgstr "" + +#: fmain.res_overwritefiletip +msgid "The file already exists. Do you want to overwrite it?" +msgstr "" + #: fmain.res_recentfilenotexists msgid "The file doesn't exists, do you want to remove the Menu Item of this recent file?" msgstr "" diff -Nru tominote-1.0.0/src/languages/TomiNote.zh_cn.po tominote-1.0.0/src/languages/TomiNote.zh_cn.po --- tominote-1.0.0/src/languages/TomiNote.zh_cn.po 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/languages/TomiNote.zh_cn.po 2017-11-29 21:45:59.000000000 +0000 @@ -122,6 +122,10 @@ "\n" "This program uses dynamic load node, when you open the database, it will not load all the nodes, only the first depth node is loaded, when you expand a node, it will load its next node, so you don't have to worry about loading too much data too slow, but the count of nodes should not exceed 2147483640, which is determined by the type of integer used by the program, you can modify the source code to make it support more The number of nodes, but also consume more database space.\n" "\n" +"You can use the command line parameter --c or --config to specify the directory of the configuration file, such as: TomiNote --config=~/.config/TomiNote\n" +"\n" +"You can use the command line parameter --l or --lang to specify the directory of the language files, such as: TomiNote --lang=/usr/share/TomiNote/languages\n" +"\n" "\n" "\n" "[Move Node]\n" @@ -246,7 +250,7 @@ "\n" "You can search for text in node name and node content. You can search for text in \"Selected node\" or \"Selected node and its descendants\" or \"All nodes\".\n" "\n" -"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, backslashes will be converted to \\\\, and if the search content or replacement contains With \\r \\n \\t \\\\, the backslash in these symbols will not be converted.\n" +"Carriage returns and newline characters in search content and replacements will be converted to \\r \\n, tabs will be converted to \\t, the backslash will not be processed, only the special backslash will be converted to \\\\. For example: '\\a\\\\b'#10 will be converted to '\\a\\\\b\\r', '\\a\\\\b\\'#10 will be converted to '\\a\\\\b\\\\\\r'.\n" "\n" "The search results will be listed in the InfoBar, which you can double-click to jump to the corresponding place of the search result.\n" "\n" @@ -258,6 +262,10 @@ "\n" "Note: The nodes that executed the multi-node replace operation will lose their history.\n" "\n" +"Note: The contents of the search and replace operations are taken from the database, and the line-ending character used in the database is \\n, so you can never found the \\r character.\n" +"\n" +"Note: If the pasted content contains line-ending character that do not match the current system, you can convert the line-ending to the current system's line-ending by \"switching to other nodes and then switching back\", the wrong line-ending will cause the search results to display incorrectly.\n" +"\n" "\n" "\n" "[Import And Export]\n" @@ -548,6 +556,10 @@ "\n" "本程序使用动态载入节点的方式,当打开数据库时,并不会载入所有节点,只会载入第一层节点,当你展开某个节点时,才会载入它的下一级节点,所以你不必担心数据太多造成加载太慢,但是你的节点数量不应该超过 2147483640 个,这是本程序所使用的整数类型所决定的,你可以修改本程序源代码使它支持更多的节点数量,但同时也会占用更多的数据库空间。\n" "\n" +"你可以使用命令行参数 --c 或 --config 来指定配置文件的存放目录,例如:--config=~/.config/TomiNote\n" +"\n" +"你可以使用命令行参数 --l 或 --lang 来指定语言文件的存放目录,例如:--lang=/usr/share/TomiNote/languages\n" +"\n" "\n" "\n" "[移动节点]\n" @@ -672,7 +684,7 @@ "\n" "你可以在“节点名称”和“节点内容”中搜索文本。你可在“所选节点”或“所选节点及其子孙节点”或“所有节点”中搜索文本。\n" "\n" -"搜索内容和替换内容中的回车符和换行符将被转换为 \\r \\n,制表符将被转换为 \\t,反斜线将被转换为 \\\\,如果搜索内容或替换内容中包含有 \\r \\n \\t \\\\,则这些符号中的反斜线不会被转换。\n" +"搜索内容和替换内容中的回车符和换行符将被转换为 \\r \\n,制表符将被转换为 \\t,反斜线不会被处理,只有特殊的反斜线会被转换为 \\\\。例如 '\\a\\\\b'#10 会被转换为 '\\a\\\\b\\r','\\a\\\\b\\'#10 会被转换为 '\\a\\\\b\\\\\\r'\n" "\n" "搜索结果将在信息栏列出,你可以双击信息栏中的条目以跳转到搜索结果的相应位置。\n" "\n" @@ -684,6 +696,10 @@ "\n" "注意:执行了多节点替换操作的节点将丢失其历史记录。\n" "\n" +"注意:搜索和替换操作是从数据库中获取内容进行处理的,数据库中使用的行尾符是 \\n,所以你永远也搜索不到 \\r 字符。\n" +"\n" +"注意:如果粘贴的内容中含有与当前系统不匹配的行尾符,可以通过“切换到其它节点再切换回来”的方式将行尾符转换为当前系统的行尾符。错误的行尾符会导致搜索结果显示错误。\n" +"\n" "\n" "\n" "[导入和导出]\n" @@ -1205,14 +1221,6 @@ msgid "Fail to close database!" msgstr "关闭数据库失败!" -#: fmain.res_coverfilefail -msgid "Fail to cover file!" -msgstr "覆盖文件失败!" - -#: fmain.res_coverfiletip -msgid "The file already exists. Do you want to cover it?" -msgstr "文件已经存在,是否覆盖?" - #: fmain.res_createdbfail msgid "Fail to create database!" msgstr "创建数据库失败!" @@ -1245,6 +1253,14 @@ msgid "Fail to open database!" msgstr "打开数据库失败!" +#: fmain.res_overwritefilefail +msgid "Fail to overwrite file!" +msgstr "覆盖文件失败!" + +#: fmain.res_overwritefiletip +msgid "The file already exists. Do you want to overwrite it?" +msgstr "文件已经存在,是否将其覆盖?" + #: fmain.res_recentfilenotexists msgid "The file doesn't exists, do you want to remove the Menu Item of this recent file?" msgstr "文件不存在,是否删除该菜单项?" @@ -1860,3 +1876,4 @@ #: uconfig.res_notactive msgid "NotActive" msgstr "未激活" + diff -Nru tominote-1.0.0/src/TomiNote.lpi tominote-1.0.0/src/TomiNote.lpi --- tominote-1.0.0/src/TomiNote.lpi 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/TomiNote.lpi 2017-11-29 21:45:59.000000000 +0000 @@ -98,7 +98,6 @@ - @@ -208,6 +207,9 @@ + + + diff -Nru tominote-1.0.0/src/Units/regexpr.pas tominote-1.0.0/src/Units/regexpr.pas --- tominote-1.0.0/src/Units/regexpr.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Units/regexpr.pas 2017-11-29 21:45:59.000000000 +0000 @@ -82,6 +82,7 @@ {$ENDIF} // ======== Define options for TRegExpr engine +// 我只修改了这里,以支持 Unicode {$DEFINE UniCode} // Unicode support {$ifdef FPC_OS_UNICODE} {$define UNICODE} diff -Nru tominote-1.0.0/src/Units/ucommon.pas tominote-1.0.0/src/Units/ucommon.pas --- tominote-1.0.0/src/Units/ucommon.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Units/ucommon.pas 2017-11-29 21:45:59.000000000 +0000 @@ -5,7 +5,7 @@ interface uses - Classes, SysUtils, LCLIntf, lazUTF8; + Classes, SysUtils, LCLIntf, StrUtils; type @@ -17,8 +17,6 @@ ULength : SizeInt; // UTF8 Length end; - PSearchResult = ^TSearchResult; - TSearchResult = class private FList: TList; @@ -37,35 +35,42 @@ function IsKeyDown(AKey: integer): boolean; inline; -function StartsWith(Str, SubStr: string; StartPos: SizeInt):boolean; -function EndsWith(Str, SubStr: string; EndPos: SizeInt):boolean; -function UTF8TrimLeft(Str: string; SubStrs: array of string): string; -function UTF8TrimRight(Str: string; SubStrs: array of string): string; -function UTF8TrimString(Str: string; SubStrs: array of string): string; -function UTF8TrimSpace(Str: string): string; - -function UTF8Search(ID: integer; const AText, ASearchText: string; - IgnoreCase: boolean; Rst: TSearchResult; StartUPos: SizeInt = 1; - SearchULen: SizeInt = 0; SearchCount: integer = 0): PtrInt; - -function UTF8Replace(ID: integer; const AText, ASearchText, AReplaceText: string; - IgnoreCase: boolean; Rst: TSearchResult; StartUPos: SizeInt = 1; - SearchULen: SizeInt = 0; SearchCount: integer = 0): string; - -function UTF8DiffBytePos(Str1, Str2: string; var Start1, Start2: SizeInt; Reverse: boolean = False): boolean; -function UTF8Diff(Str1, Str2: string; var Start1, Start2: SizeInt; Reverse: boolean = False): boolean; - -function ToLF(Str: string): string; -function ToLineEnding(Str: string): string; - -function Escape(Str: string): string; -function UnEscape(Str: string): string; +function StartsWith(S, SubStr: string; StartPos: SizeInt):boolean; +function EndsWith(S, SubStr: string; EndPos: SizeInt):boolean; +function UTF8TrimLeft(S: string; SubStrs: array of string): string; +function UTF8TrimRight(S: string; SubStrs: array of string): string; +function UTF8TrimString(S: string; SubStrs: array of string): string; +function UTF8TrimSpace(S: string): string; + +function UTF8LengthFast(S: PChar; SSize: SizeInt): SizeInt; +function UTF8LengthFast(S: string): SizeInt; + +function UTF8Pos(const S,OldPattern: String; const IgnoreCase: Boolean = False): SizeInt; + +procedure UTF8FindMatches(const S,OldPattern: String; out aMatches: SizeIntArray; + const aMatchAll: Boolean = False; const IgnoreCase: Boolean = False); +function UTF8ReplaceMatches(const S, OldPattern, NewPattern: string; out aMatches: SizeIntArray; + const aMatchAll: Boolean = False; const IgnoreCase: Boolean = False): string; + +procedure UTF8SearchSpecial(ID: integer; const AText, ASearchText: string; + IgnoreCase: boolean; Rst: TSearchResult); +function UTF8ReplaceSpecial(ID: integer; const AText, ASearchText, AReplaceText: string; + IgnoreCase: boolean; Rst: TSearchResult): string; + +function UTF8DiffBytePos(S1, S2: string; var Start1, Start2: SizeInt; Reverse: boolean = False): boolean; + +function ToLF(S: string): string; +function ToLineEnding(S: string): string; + +// function Escape_Abandoned(S: string): string; +function Escape(S: string): string; +function UnEscape(S: string): string; function ReadFile(FileName: string): string; procedure WriteFile(FileName: string; Text: string); function FixFileName(FileName: string): string; -function GetNotExistsPath(ToDir, FileName, FileExt: string; LenSuffix: integer): string; +function GetNonExistsPath(ToDir, FileName, FileExt: string; LenSuffix: integer): string; procedure FindFiles(APath: string; Rst: TStringList); implementation @@ -140,18 +145,18 @@ Result := GetKeyState(AKey) < 0; end; -// 判断 SubStr 是否在 Str 中,并且开始于 StartPos 位置 -function StartsWith(Str, SubStr: string; StartPos: SizeInt):boolean; +// 判断 SubStr 是否在 S 中,并且开始于 StartPos 位置 +function StartsWith(S, SubStr: string; StartPos: SizeInt):boolean; var c: Char; begin - if Str.Length - StartPos + 1 < SubStr.Length then begin + if Length(S) - StartPos + 1 < Length(SubStr) then begin Result := False; Exit; end; for c in SubStr do begin - if c = Str[StartPos] then + if c = S[StartPos] then Inc(StartPos) else begin Result := False; @@ -161,19 +166,19 @@ Result := True; end; -// 判断 SubStr 是否在 Str 中,并且结束于 EndPos 位置 -function EndsWith(Str, SubStr: string; EndPos: SizeInt):boolean; +// 判断 SubStr 是否在 S 中,并且结束于 EndPos 位置 +function EndsWith(S, SubStr: string; EndPos: SizeInt):boolean; var c: Char; begin - if EndPos < SubStr.Length then begin + if EndPos < Length(SubStr) then begin Result := False; Exit; end; - EndPos := EndPos - SubStr.Length + 1; + EndPos := EndPos - Length(SubStr) + 1; for c in SubStr do begin - if c = Str[EndPos] then + if c = S[EndPos] then Inc(EndPos) else begin Result := False; @@ -184,9 +189,9 @@ end; // 删除 UTF8 字符串左边的指定子字符串 -function UTF8TrimLeft(Str: string; SubStrs: array of string): string; +function UTF8TrimLeft(S: string; SubStrs: array of string): string; var - s: string; + SS: string; NotFound: boolean; StartPos: SizeInt; begin @@ -194,34 +199,34 @@ StartPos := 1; repeat NotFound := True; - for s in SubStrs do begin - if StartsWith(Str, s, StartPos) then begin - Inc(StartPos, s.Length); + for SS in SubStrs do begin + if StartsWith(S, SS, StartPos) then begin + Inc(StartPos, Length(SS)); NotFound := False; end; end; until NotFound; - if StartPos > Str.Length then + if StartPos > Length(S) then Result := '' else - Result := Str.Substring(StartPos - 1, Str.Length - StartPos + 1); + Result := Copy(S, StartPos, Length(S) - StartPos + 1); end; // 删除 UTF8 字符串右边的指定子字符串 -function UTF8TrimRight(Str: string; SubStrs: array of string): string; +function UTF8TrimRight(S: string; SubStrs: array of string): string; var - s: string; + SS: string; NotFound: boolean; EndPos: SizeInt; begin Result := ''; - EndPos := Str.Length; + EndPos := Length(S); repeat NotFound := True; - for s in SubStrs do begin - if EndsWith(Str, s, EndPos) then begin - Dec(EndPos, s.Length); + for SS in SubStrs do begin + if EndsWith(S, SS, EndPos) then begin + Dec(EndPos, Length(SS)); NotFound := False; end; end; @@ -230,24 +235,24 @@ if EndPos < 1 then Result := '' else - Result := Str.Substring(0, EndPos); + Result := Copy(S, 1, EndPos); end; // 删除 UTF8 字符串首尾的指定子字符串 -function UTF8TrimString(Str: string; SubStrs: array of string): string; +function UTF8TrimString(S: string; SubStrs: array of string): string; var - s: string; + SS: string; NotFound: boolean; StartPos, EndPos: SizeInt; begin Result := ''; StartPos := 1; - EndPos := Str.Length; + EndPos := Length(S); repeat NotFound := True; - for s in SubStrs do begin - if StartsWith(Str, s, StartPos) then begin - Inc(StartPos, s.Length); + for SS in SubStrs do begin + if StartsWith(S, SS, StartPos) then begin + Inc(StartPos, Length(SS)); NotFound := False; end; end; @@ -255,9 +260,9 @@ repeat NotFound := True; - for s in SubStrs do begin - if EndsWith(Str, s, EndPos) then begin - Dec(EndPos, s.Length); + for SS in SubStrs do begin + if EndsWith(S, SS, EndPos) then begin + Dec(EndPos, Length(SS)); NotFound := False; end; end; @@ -266,197 +271,270 @@ if EndPos < StartPos then Result := '' else - Result := Str.Substring(StartPos - 1, EndPos - StartPos + 1); + Result := Copy(S, StartPos, EndPos - StartPos + 1); end; // 删除 UTF8 字符串首尾的空白字符 -function UTF8TrimSpace(Str: string): string; +function UTF8TrimSpace(S: string): string; begin - Result := UTF8TrimString(Str, [' ', ' ', #13, #10, #9]); + Result := UTF8TrimString(S, [' ', ' ', #13, #10, #9]); end; -// 查找字符串,如果去掉参数 ID 就是一个通用函数 -// AText :要在其中进行搜索的源字符串 -// ASearchText:要搜索的内容 -// IgnoreCase :忽略大小写 -// Rst :用来存放搜索结果的 TSearchResult 对象(如果 为 nil 则不记录搜索结果) -// StartUPos :搜索的起始字符位置(从 1 开始,不是字节位置) -// SearchULen :搜索的长度,从 StartUPos 开始,到达此长度则停止搜索,0表示无限制 -// SearchCount:搜索的次数,匹配指定次数后则停止搜索,0表示无限制 -// 返回值:最后一个查找结果的起始位置 -function UTF8Search(ID: integer; const AText, ASearchText: string; - IgnoreCase: boolean; Rst: TSearchResult; - StartUPos: SizeInt = 1; SearchULen: SizeInt = 0; SearchCount: integer = 0): PtrInt; -var - b1, b2: byte; - BPos, SubBPos: SizeInt; - UPos, UStart, ULength: SizeInt; -begin - Result := 0; - - // 安全检查 - if (StartUPos <= 0) or (AText.Length < ASearchText.Length) then Exit; - - BPos := 1; - SubBPos := 1; - UStart := 1; - UPos := 0; - - // 在这里处理起始位置(跳过指定个数的 UTF8 字符) - while BPos <= AText.Length do begin - b1 := Ord(AText[BPos]) shr 6; - if (b1 = 3) or (b1 shr 1 = 0) then Inc(UPos); - - if UPos = StartUPos then break; - Inc(BPos); - end; - - // 安全检查 - if BPos > AText.Length then Exit; - - Dec(UPos); - ULength := UTF8Length(ASearchText); - - // 按字节遍历 - for BPos := BPos to AText.Length do begin - b1 := Ord(AText[BPos]); - b2 := Ord(ASearchText[SubBPos]); - // 遇到一个 UTF8 字符 - if (b1 shr 6 = 3) or (b1 shr 7 = 0) then begin - Inc(UPos); - Dec(SearchULen); - end; - - if (b1 = b2) or IgnoreCase and ((b1 >= 97) and (b1 <= 122) and (b1 - b2 = 32) or (b1 >= 65) and (b1 <= 90) and (b2 - b1 = 32)) then begin - // 首字节匹配 - if SubBPos = 1 then UStart := UPos; - // 完全匹配 - if SubBPos = ASearchText.Length then begin - Result := UStart; - SubBPos := 0; - if Rst <> nil then Rst.Add(ID, UStart, ULength); - // 这里处理次数限制 - Dec(SearchCount); - if SearchCount = 0 then Exit; - end; - Inc(SubBPos); - end else - SubBPos := 1; - // 在这里处理长度限制 - if SearchULen = 0 then break; +// 比 lazUTF8.UTF8LengthFast 慢,但比 lazUTF8.UTF8Length 快 +// lazUTF8.UTF8LengthFast 不能用在这里,会得到错误的值。 +function UTF8LengthFast(S: PChar; SSize: SizeInt): SizeInt; +var + Pos: Integer; +begin + Result := 0; + Pos := 0; + while Pos < SSize do begin + case S[Pos] of + #0 ..#127: Inc(Pos); + #192..#223: Inc(Pos, 2); + #224..#239: Inc(Pos, 3); + #240..#247: Inc(Pos, 4); + else begin Inc(Pos); continue; end; + end; + Inc(Result); + end; +end; + +function UTF8LengthFast(S: string): SizeInt; +begin + if S = '' then + Result := 0 + else + Result := UTF8LengthFast(@S[1], Length(S)); +end; + +// 索引从 0 开始 +procedure FindMatches(const S,OldPattern: String; out aMatches: SizeIntArray; + const aMatchAll: Boolean = False; const IgnoreCase: Boolean = False); +begin + if IgnoreCase then begin + FindMatchesBoyerMooreCaseINSensitive(@S[1],@OldPattern[1],Length(S),Length(OldPattern),aMatches, aMatchAll); + end else begin + FindMatchesBoyerMooreCaseSensitive(@S[1],@OldPattern[1],Length(S),Length(OldPattern),aMatches, aMatchAll); end; end; -// 替换字符串,如果去掉参数 ID 就是一个通用函数 -// AText :要在其中进行搜索的源字符串 -// ASearchText :要搜索的内容 -// AReplaceText:用来替换的内容 -// IgnoreCase :忽略大小写 -// Rst :用来存放搜索结果的 TSearchResult 对象(如果 为 nil 则不记录搜索结果) -// StartUPos :搜索的起始字符位置(从 1 开始,不是字节位置) -// SearchULen :搜索的长度,从 StartUPos 开始,到达此长度则停止搜索,0表示无限制 -// SearchCount :搜索的次数,匹配指定次数后则停止搜索,0表示无限制 -// 返回值:最后一个查找结果的起始位置 -function UTF8Replace(ID: integer; const AText, ASearchText, AReplaceText: string; - IgnoreCase: boolean; Rst: TSearchResult; - StartUPos: SizeInt = 1; SearchULen: SizeInt = 0; SearchCount: integer = 0): string; -var - b1, b2: byte; - BPos, SubBPos, BStart, LastBStart: SizeInt; - UPos, UStart, ULength, ULengthFix: SizeInt; - Count: integer; -begin - Result := AText; - - // 安全检查 - if (StartUPos <= 0) or (AText.Length < ASearchText.Length) then Exit; - - BPos := 1; - SubBPos := 1; - UStart := 1; - UPos := 0; - - // 跳过指定个数的 UTF8 字符 - while BPos <= AText.Length do begin - b1 := Ord(AText[BPos]) shr 6; - if (b1 = 3) or (b1 shr 1 = 0) then Inc(UPos); +// 索引从 0 开始 +function ReplaceMatches(const S, OldPattern, NewPattern: string; out aMatches: SizeIntArray; + const aMatchAll: Boolean = False; const IgnoreCase: Boolean = False): string; +var + OldPatternSize: SizeInt; + NewPatternSize: SizeInt; + MatchesCount: SizeInt; + MatchIndex: SizeInt; + MatchTarget: SizeInt; + MatchInternal: SizeInt; + AdvanceIndex: SizeInt; +begin + OldPatternSize:=Length(OldPattern); + NewPatternSize:=Length(NewPattern); + if (OldPattern='') or (Length(OldPattern)>Length(S)) then begin + Result:=S; + exit; + end; - if UPos = StartUPos then break; - Inc(BPos); + if IgnoreCase then begin + FindMatchesBoyerMooreCaseINSensitive(@S[1],@OldPattern[1],Length(S),Length(OldPattern),aMatches, aMatchAll); + end else begin + FindMatchesBoyerMooreCaseSensitive(@S[1],@OldPattern[1],Length(S),Length(OldPattern),aMatches, aMatchAll); end; - // 安全检查 - if BPos > AText.Length then Exit; + MatchesCount:=Length(aMatches); - Dec(UPos); - Result := ''; - Count := 0; - LastBStart := 1; - ULength := UTF8Length(AReplaceText); - ULengthFix := UTF8Length(AReplaceText) - UTF8Length(ASearchText); - - // 按字节遍历 - for BPos := BPos to AText.Length do begin - b1 := Ord(AText[BPos]); - b2 := Ord(ASearchText[SubBPos]); - // 遇到一个 UTF8 字符 - if (b1 shr 6 = 3) or (b1 shr 7 = 0) then begin - Inc(UPos); - Dec(SearchULen); - end; - - if (b1 = b2) or IgnoreCase and ((b1 >= 97) and (b1 <= 122) and (b1 - b2 = 32) or (b1 >= 65) and (b1 <= 90) and (b2 - b1 = 32)) then begin - // 首字节匹配 - if SubBPos = 1 then begin - BStart := BPos; - UStart := UPos + ULengthFix * Count; - end; - // 完全匹配 - if SubBPos = ASearchText.Length then begin - Result := Result + AText.Substring(LastBStart - 1, BStart - LastBStart) + AReplaceText; - LastBStart := BPos + 1; - SubBPos := 0; - if Rst <> nil then Rst.Add(ID, UStart, ULength); - Inc(Count); - // 这里处理次数限制 - if Count = SearchCount then break; - end; - Inc(SubBPos); - end else - SubBPos := 1; - // 在这里处理长度限制 - if SearchULen = 0 then break; + //Create room enougth for the result string + SetLength(Result,Length(S)-OldPatternSize*MatchesCount+NewPatternSize*MatchesCount); + MatchIndex:=1; + MatchTarget:=1; + //aMatches[x] are 0 based offsets + for MatchInternal := 0 to Pred(MatchesCount) do begin + //Copy information up to next match + AdvanceIndex:=aMatches[MatchInternal]+1-MatchIndex; + if AdvanceIndex>0 then begin + move(S[MatchIndex],Result[MatchTarget],AdvanceIndex); + inc(MatchTarget,AdvanceIndex); + inc(MatchIndex,AdvanceIndex); + aMatches[MatchInternal] := MatchTarget - 1; + end; + //Copy the new replace information string + if NewPatternSize>0 then begin + move(NewPattern[1],Result[MatchTarget],NewPatternSize); + inc(MatchTarget,NewPatternSize); + end; + inc(MatchIndex,OldPatternSize); + end; + if MatchTarget<=Length(Result) then begin + //Add remain data at the end of source. + move(S[MatchIndex],Result[MatchTarget],Length(Result)-MatchTarget+1); end; - if LastBStart < AText.Length then - Result := Result + AText.Substring(LastBStart - 1); end; -// 查找 Str1 和 Str2 的不同之处,参数和返回值的索引都是从 1 开始,到 Length(Str) 结束。 -// Start1 表示 Str1 的起始查找位置,查找结果也通过该参数返回。 -// Start2 表示 Str2 的起始查找位置,查找结果也通过该参数返回。 +// 索引从 0 开始 +procedure UTF8FindMatches(const S,OldPattern: String; out aMatches: SizeIntArray; + const aMatchAll: Boolean = False; const IgnoreCase: Boolean = False); +var + OldPatternSize: SizeInt; + MatchesCount: SizeInt; + MatchIndex: SizeInt; + MatchInternal: SizeInt; + AdvanceIndex: SizeInt; + MarchIndexU: SizeInt; + OldPatternSizeU: SizeInt; +begin + if IgnoreCase then begin + FindMatchesBoyerMooreCaseINSensitive(@S[1],@OldPattern[1],Length(S),Length(OldPattern),aMatches, aMatchAll); + end else begin + FindMatchesBoyerMooreCaseSensitive(@S[1],@OldPattern[1],Length(S),Length(OldPattern),aMatches, aMatchAll); + end; + + MatchesCount:=Length(aMatches); + + //Create room enougth for the result string + MatchIndex:=1; + MarchIndexU:=0; + OldPatternSize:=Length(OldPattern); + OldPatternSizeU:=UTF8LengthFast(PChar(OldPattern), Length(OldPattern)); + //aMatches[x] are 0 based offsets + for MatchInternal := 0 to Pred(MatchesCount) do begin + AdvanceIndex:=aMatches[MatchInternal]+1-MatchIndex; + Inc(MarchIndexU, UTF8LengthFast(@S[MatchIndex], AdvanceIndex)); + inc(MatchIndex,AdvanceIndex); + aMatches[MatchInternal] := MarchIndexU; + Inc(MarchIndexU, OldPatternSizeU); + inc(MatchIndex,OldPatternSize); + end; +end; + +// 索引从 0 开始 +function UTF8ReplaceMatches(const S, OldPattern, NewPattern: string; out aMatches: SizeIntArray; + const aMatchAll: Boolean = False; const IgnoreCase: Boolean = False): string; +var + OldPatternSize: SizeInt; + NewPatternSize: SizeInt; + MatchesCount: SizeInt; + MatchIndex: SizeInt; + MatchTarget: SizeInt; + MatchInternal: SizeInt; + AdvanceIndex: SizeInt; + MarchTargetU: SizeInt; + NewPatternSizeU: SizeInt; +begin + OldPatternSize:=Length(OldPattern); + NewPatternSize:=Length(NewPattern); + if (OldPattern='') or (Length(OldPattern)>Length(S)) then begin + Result:=S; + exit; + end; + + if IgnoreCase then begin + FindMatchesBoyerMooreCaseINSensitive(@S[1],@OldPattern[1],Length(S),Length(OldPattern),aMatches, aMatchAll); + end else begin + FindMatchesBoyerMooreCaseSensitive(@S[1],@OldPattern[1],Length(S),Length(OldPattern),aMatches, aMatchAll); + end; + + MatchesCount:=Length(aMatches); + + //Create room enougth for the result string + SetLength(Result,Length(S)-OldPatternSize*MatchesCount+NewPatternSize*MatchesCount); + MatchIndex:=1; + MatchTarget:=1; + MarchTargetU:=0; + NewPatternSizeU:=UTF8LengthFast(PChar(NewPattern), Length(NewPattern)); + //aMatches[x] are 0 based offsets + for MatchInternal := 0 to Pred(MatchesCount) do begin + //Copy information up to next match + AdvanceIndex:=aMatches[MatchInternal]+1-MatchIndex; + if AdvanceIndex>0 then begin + move(S[MatchIndex],Result[MatchTarget],AdvanceIndex); + Inc(MarchTargetU, UTF8LengthFast(@S[MatchIndex], AdvanceIndex)); + inc(MatchTarget,AdvanceIndex); + inc(MatchIndex,AdvanceIndex); + end; + aMatches[MatchInternal] := MarchTargetU; + Inc(MarchTargetU, NewPatternSizeU); + //Copy the new replace information string + if NewPatternSize>0 then begin + move(NewPattern[1],Result[MatchTarget],NewPatternSize); + inc(MatchTarget,NewPatternSize); + end; + inc(MatchIndex,OldPatternSize); + end; + if MatchTarget<=Length(Result) then begin + //Add remain data at the end of source. + move(S[MatchIndex],Result[MatchTarget],Length(Result)-MatchTarget+1); + end; +end; + +// 索引从 1 开始 +function UTF8Pos(const S,OldPattern: String; const IgnoreCase: Boolean = False): SizeInt; +var + Matches: SizeIntArray; +begin + UTF8FindMatches(S, OldPattern, Matches, False, IgnoreCase); + if Length(Matches) > 0 then + Result := Matches[Length(Matches) - 1] + 1 + else + Result := 1; +end; + +// 索引从 0 开始 +procedure UTF8SearchSpecial(ID: integer; const AText, ASearchText: string; + IgnoreCase: boolean; Rst: TSearchResult); +var + i: Integer; + Matches: SizeIntArray; + SearchTextLen: Integer; +begin + SearchTextLen := UTF8LengthFast(ASearchText); + UTF8FindMatches(AText, ASearchText, Matches, True, IgnoreCase); + for i := 0 to High(Matches) do + Rst.Add(ID, Matches[i], SearchTextLen); +end; + +// 索引从 0 开始 +function UTF8ReplaceSpecial(ID: integer; const AText, ASearchText, AReplaceText: string; + IgnoreCase: boolean; Rst: TSearchResult): string; +var + i: Integer; + Matches: SizeIntArray; + ReplaceTextLen: Integer; +begin + ReplaceTextLen := UTF8LengthFast(AReplaceText); + Result := UTF8ReplaceMatches(AText, ASearchText, AReplaceText, Matches, True, IgnoreCase); + for i := 0 to High(Matches) do + Rst.Add(ID, Matches[i], ReplaceTextLen); +end; + +// 查找 S1 和 S2 的不同之处,参数和返回值的索引都是从 1 开始,到 Length(S) 结束。 +// Start1 表示 S1 的起始查找位置,查找结果也通过该参数返回。 +// Start2 表示 S2 的起始查找位置,查找结果也通过该参数返回。 // Reverse 为 True 表示向头查找,False 表示向尾查找。 // 返回值:True 表示找到,False 表示没找到。 -// 如果没找到,则向头查找时,某一 Start 返回 0,向尾查找时某一 Start 返回 UTF8Length(Str)+1。 -function UTF8DiffBytePos(Str1, Str2: string; var Start1, Start2: SizeInt; Reverse: boolean = False): boolean; +// 如果没找到,则向头查找时,某一 Start 返回 0,向尾查找时某一 Start 返回 UTF8Length(S)+1。 +function UTF8DiffBytePos(S1, S2: string; var Start1, Start2: SizeInt; Reverse: boolean = False): boolean; - procedure GoToCpStartStr1; + procedure GoToCpStartS1; var b: byte; - begin // 回到 Str1 中字符码点的起始位置 + begin // 回到 S1 中字符码点的起始位置 while Start1 > 0 do begin // 如果 UTF8 编码不正确,则 Start1 可能小于等于 0。 - b := Ord(Str1[Start1]) shr 6; + b := Ord(S1[Start1]) shr 6; if (b = 3) or (b shr 1 = 0) then break; Dec(Start1); end; end; - procedure GoToCpStartStr2; + procedure GoToCpStartS2; var b: byte; - begin // 回到 Str2 中字符码点的起始位置 + begin // 回到 S2 中字符码点的起始位置 while Start2 > 0 do begin // 如果 UTF8 编码不正确,则 Start2 可能小于等于 0。 - b := Ord(Str2[Start2]) shr 6; + b := Ord(S2[Start2]) shr 6; if (b = 3) or (b shr 1 = 0) then break; Dec(Start2); @@ -465,127 +543,88 @@ begin Result := False; - if (Start1 <= 0) or (Start2 <= 0) or (Start1 > Str1.Length) or (Start2 > Str2.Length) then Exit; + if (Start1 <= 0) or (Start2 <= 0) or (Start1 > Length(S1)) or (Start2 > Length(S2)) then Exit; if Reverse then begin - while (Start1 >= 1) and (Start2 >= 1) and (Str1[Start1] = Str2[Start2]) do begin + while (Start1 >= 1) and (Start2 >= 1) and (S1[Start1] = S2[Start2]) do begin Dec(Start1); Dec(Start2); end; if Start1 > 1 then - GoToCpStartStr1; + GoToCpStartS1; if Start2 > 1 then - GoToCpStartStr2; + GoToCpStartS2; Result := (Start1 > 0) and (Start2 > 0); end else begin - while (Start1 <= Str1.Length) and (Start2 <= Str2.Length) and (Str1[Start1] = Str2[Start2]) do begin + while (Start1 <= Length(S1)) and (Start2 <= Length(S2)) and (S1[Start1] = S2[Start2]) do begin Inc(Start1); Inc(Start2); end; - if Start1 <= Str1.Length then - GoToCpStartStr1; - if Start2 <= Str2.Length then - GoToCpStartStr2; - Result := (Start1 <= Str1.Length) and (Start2 <= Str2.Length); + if Start1 <= Length(S1) then + GoToCpStartS1; + if Start2 <= Length(S2) then + GoToCpStartS2; + Result := (Start1 <= Length(S1)) and (Start2 <= Length(S2)); end; end; -// 查找 Str1 和 Str2 的不同之处,参数和返回值的索引都是从 1 开始,到 UTF8Length(Str) 结束。 -// Start1 表示 Str1 的起始查找位置,查找结果也通过该参数返回。 -// Start2 表示 Str2 的起始查找位置,查找结果也通过该参数返回。 -// Reverse 为 True 表示向头查找,False 表示向尾查找。 -// 返回值:True 表示找到,False 表示没找到。 -// 如果没找到,则向头查找时,某一 Start 返回 0,向尾查找时某一 Start 返回 UTF8Length(Str)+1。 -function UTF8Diff(Str1, Str2: string; var Start1, Start2: SizeInt; Reverse: boolean = False): boolean; -begin - if not Reverse then begin - Dec(Start1); - Dec(Start2); - end; - - Start1 := UTF8CharToByteIndex(PChar(Str1), Str1.Length, Start1); - Start2 := UTF8CharToByteIndex(PChar(Str2), Str2.Length, Start2); - - if not Reverse then begin - Inc(Start1); - Inc(Start2); - end; - - Result := UTF8DiffBytePos(Str1, Str2, Start1, Start2, Reverse); - - if Start1 > 0 then Start1 := UTF8Length(PChar(Str1), Start1 - 1) + 1; - if Start2 > 0 then Start2 := UTF8Length(PChar(Str2), Start2 - 1) + 1; -end; - // 将 \r\n 或 \r 转换为 \n -function ToLF(Str: string): string; +function ToLF(S: string): string; var - iStart, iEnd: SizeInt; - Stream: TStringStream; -begin - iStart := 0; - Stream := TStringStream.Create(''); - try - iEnd := Str.IndexOf(#13, iStart); - while iEnd <> -1 do begin - Stream.WriteString(Str.Substring(iStart, iEnd - iStart)); - if (iEnd = Str.Length - 1) or (Str[iEnd + 2] <> #10) then - Stream.WriteString(#10); - iStart := iEnd + 1; - iEnd := Str.IndexOf(#13, iStart); - end; - if (iEnd < Str.Length - 1) then - Stream.WriteString(Str.Substring(iStart)); - Result := Stream.DataString; - finally - Stream.Free; + Index: integer; + LastIndex: integer; + ResultIndex: integer; +begin + if S = '' then Exit; + + Index := 1; + LastIndex := 1; + ResultIndex := 1; + SetLength(Result, Length(S)); + while Index < Length(S) do begin + if S[Index] = #13 then begin + move(S[LastIndex], Result[ResultIndex], Index - LastIndex); + Inc(ResultIndex, Index - LastIndex); + Inc(Index); + LastIndex := Index; + if S[Index] = #10 then continue; + Result[ResultIndex] := #10; + Inc(ResultIndex); + end else + Inc(Index); end; + move(S[LastIndex], Result[ResultIndex], Length(S) - LastIndex); + Inc(ResultIndex, Length(S) - LastIndex); + if S[Length(S)] = #13 then + Result[ResultIndex] := #10 + else + Result[ResultIndex] := S[Length(S)]; + SetLength(Result, ResultIndex); end; // 将 \n 转换为系统默认的换行符 -function ToLineEnding(Str: string): string; -var - StartPos, EndPos: integer; - Stream: TStringStream; +function ToLineEnding(S: string): string; begin - if LineEnding = #10 then begin - Result := Str; - Exit; - end; - - StartPos := 0; - Stream := TStringStream.Create(''); - try - EndPos := Str.IndexOf(#10, StartPos); - while EndPos <> -1 do begin - Stream.WriteString(Str.Substring(StartPos, EndPos - StartPos)); - Stream.WriteString(LineEnding); - StartPos := EndPos + 1; - EndPos := Str.IndexOf(#10, StartPos); - end; - if (EndPos < Str.Length - 1) then - Stream.WriteString(Str.Substring(StartPos)); - Result := Stream.DataString; - finally - Stream.Free; - end; + Result := StringReplace(S, #10, LineEnding, [rfReplaceAll], sraBoyerMoore); end; +{ // 将特殊字符(#13 #10 #9 \)转换为转义字符(\r \n \t \\) // 字符串中原有的 \r \n \t \\ 不会进行处理 -function Escape(Str: string): string; +// 这个转换函数会影响正则表达式字符串,所以弃用 +function Escape_Abandoned(S: string): string; var - Start : SizeInt; + StartPos : SizeInt; i : SizeInt; c : Char; MeetSlash : boolean; begin - Start := 1; - Result := ''; + StartPos := 1; + Result := ''; MeetSlash := False; - for i := 1 to Str.Length do begin - c := Str[i]; + for i := 1 to Length(S) do begin + c := S[i]; if MeetSlash then begin MeetSlash := False; case c of @@ -600,15 +639,61 @@ else continue; end; end; - Result := Result + Str.SubString(Start - 1, i - Start) + '\' + c; - Start := i + 1; + Result := Result + Copy(S, StartPos, i - StartPos) + '\' + c; + StartPos := i + 1; + end; + + if StartPos <= Length(S) then + Result := Result + Copy(S, StartPos, Length(S) - StartPos + 1); +end; +} + +// 将特殊字符(#13 #10 #9)转换为转义字符(\r \n \t) +// 这个转换函数不会处理 \ 字符,所以可以用于正则表达式字符串 +function Escape(S: string): string; +var + StartPos : SizeInt; + i : SizeInt; + c : Char; + SS : string; + MeetSlash : Boolean; +begin + StartPos := 1; + Result := ''; + SS := ''; + MeetSlash := False; + + for i := 1 to Length(S) do begin + c := S[i]; + if MeetSlash then begin + MeetSlash := False; + case c of + #13: SS := '\\r'; + #10: SS := '\\n'; + #9 : SS := '\\t'; + else continue; + end; + end else begin + case c of + '\': begin MeetSlash := True; continue; end; + #13: SS := '\r'; + #10: SS := '\n'; + #9 : SS := '\t'; + else continue; + end; + end; + Result := Result + Copy(S, StartPos, i - StartPos) + SS; + StartPos := i + 1; end; - Result := Result + Str.SubString(Start - 1, Str.Length - Start + 1); - if MeetSlash then Result := Result + '\'; + + if StartPos <= Length(S) then + Result := Result + Copy(S, StartPos, Length(S) - StartPos + 1); end; // 将转义字符(\r \n \t \\)转换为特殊字符(#13 #10 #9 \) -function UnEscape(Str: string): string; +// 其它地方单独的 \ 字符会被保留 +// 与 Escape 函数配合使用 +function UnEscape(S: string): string; var Start : SizeInt; i : SizeInt; @@ -619,8 +704,8 @@ Result := ''; MeetSlash := False; - for i := 1 to Str.Length do begin - c := Str[i]; + for i := 1 to Length(S) do begin + c := S[i]; if MeetSlash then begin MeetSlash := False; case c of @@ -628,15 +713,17 @@ 'r': Result := Result + #13; 'n': Result := Result + #10; 't': Result := Result + #9; - else Result := Result + c; + else Result := Result + '\' + c; end; end else if c = '\' then begin MeetSlash := True; - Result := Result + Str.SubString(Start - 1, i - Start); + Result := Result + Copy(S, Start, i - Start); Start := i + 2; end; end; - Result := Result + Str.SubString(Start - 1, Str.Length - Start + 1); + + if Start <= Length(S) then + Result := Result + Copy(S, Start, Length(S) - Start + 1); end; // 读取文本文件内容,同时将换行符统一为 #10 @@ -662,7 +749,7 @@ AStream := TFileStream.Create(FileName, fmCreate); try Text := ToLineEnding(Text); - AStream.WriteBuffer(Text[1], Text.Length); + AStream.WriteBuffer(Text[1], Length(Text)); finally AStream.Free; end; @@ -680,7 +767,7 @@ end; // 获取一个不存在的文件名(避免与现有文件重名) -function GetNotExistsPath(ToDir, FileName, FileExt: string; LenSuffix: integer): string; +function GetNonExistsPath(ToDir, FileName, FileExt: string; LenSuffix: integer): string; var i: integer; Suffix: string; diff -Nru tominote-1.0.0/src/Units/uconfig.pas tominote-1.0.0/src/Units/uconfig.pas --- tominote-1.0.0/src/Units/uconfig.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Units/uconfig.pas 2017-11-29 21:45:59.000000000 +0000 @@ -208,7 +208,7 @@ const AppTitle = 'TomiNote'; - Version = 'v1.0 Beta2'; + Version = 'v1.0 Beta3'; AllDepth = 0; @@ -767,7 +767,7 @@ initialization -AppDir := ExtractFileDir(ParamStrUTF8(0)); +AppDir := ExtractFileDir(ParamStrUTF8(0)); AppName := ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), ''); end. diff -Nru tominote-1.0.0/src/Units/uhistory.pas tominote-1.0.0/src/Units/uhistory.pas --- tominote-1.0.0/src/Units/uhistory.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Units/uhistory.pas 2017-11-29 21:45:59.000000000 +0000 @@ -249,8 +249,8 @@ function THistory.GetRecordSize(Idx: integer): integer; begin Result := - Items[Idx]^.PrevSelText.Length + - Items[Idx]^.SelText.Length + + Length(Items[Idx]^.PrevSelText) + + Length(Items[Idx]^.SelText) + Sizeof(THistoryRecord); end; @@ -357,8 +357,8 @@ procedure THistoryManager.AddRecordSimply(APrevText: string); begin FHistory.AddRecord( - 0, UTF8Length(APrevText), APrevText, - 0, UTF8Length(FEdit.Text), FEdit.Text); + 0, UTF8LengthFast(APrevText), APrevText, + 0, UTF8LengthFast(FEdit.Text), FEdit.Text); end; // 记录 OnChange 之前的 SelStart @@ -419,10 +419,10 @@ // Len < PrevLen 表示编辑框中删除了内容,此时 SelStart 应该在被删除的内容之前。 // Len = PrevLen 不可能存在 if Len > PrevLen then begin - // 计算出增加了什么内容(Substring 的参数是从索引 0 开始计数的) - SelText := string(FEdit.Text).Substring(BSelStart - (Len - PrevLen), (Len - PrevLen)); + // 计算出增加了什么内容(Copy 的参数是从索引 1 开始计数的) + SelText := Copy(FEdit.Text, BSelStart - (Len - PrevLen) + 1, (Len - PrevLen)); // 计算出增加了多少字符 - SelLength := UTF8Length(SelText); + SelLength := UTF8LengthFast(SelText); PHR^.PrevSelStart := FEdit.SelStart - SelLength; PHR^.PrevSelLength := 0; @@ -432,10 +432,10 @@ PHR^.SelLength := SelLength; PHR^.SelText := SelText; end else if Len < PrevLen then begin - // 计算出删除了什么内容(Substring 的参数是从索引 0 开始计数的) - SelText := FPrevText.Substring(BSelStart, (PrevLen - Len)); + // 计算出删除了什么内容(Copy 的参数是从索引 1 开始计数的) + SelText := Copy(FPrevText, BSelStart + 1, (PrevLen - Len)); // 计算出删除了多少字符 - SelLength := UTF8Length(SelText); + SelLength := UTF8LengthFast(SelText); PHR^.PrevSelStart := FEdit.SelStart; PHR^.PrevSelLength := SelLength; @@ -489,28 +489,26 @@ begin // 获取 PrevSelStart 的字节索引。 // UTF8CharToByteIndex 的参数和结果是从索引 0 开始计数的。 - BPrevSelStart := UTF8CharToByteIndex(PChar(FPrevText), FPrevText.Length, FPrevSelStart); + BPrevSelStart := UTF8CharToByteIndex(PChar(FPrevText), Length(FPrevText), FPrevSelStart); // 获取新增内容的字节长度 - BSelLength := Length(FEdit.Text) - FPrevText.Length; - PrevSelText := FPrevText.Substring(BPrevSelStart, BSelLength); + BSelLength := Length(FEdit.Text) - Length(FPrevText); + PrevSelText := Copy(FPrevText, BPrevSelStart + 1, BSelLength); // 准备查找的起始位置(索引从 1 开始,跳过已选择的部分)。 BSelStartFix := BPrevSelStart + BSelLength + 1; BSelStartFix2 := BSelStartFix; // 向尾查找不同之处(即新内容的插入位置,返回值索引从 1 开始)。 // 如果没有不同之处,则说明新内容被插入到文本的尾部。 UTF8DiffBytePos(FEdit.Text, FPrevText, BSelStartFix, BSelStartFix2); - // 将索引恢复到从 0 开始。BSelStartFix2 和 BSelStartFix 相同,用不上。 - Dec(BSelStartFix); // 获取新增加的内容(新增加的内容不一定就是之前选择的内容,比如 a++b++c++, // 当把 +b+ 拖到 c+ 之后,就会出现这种情况)。 - // Substring 的参数是从索引 0 开始计数的。 - SelText := string(FEdit.Text).Substring(BSelStartFix, BSelLength); + // Copy 的参数是从索引 1 开始计数的。 + SelText := Copy(FEdit.Text, BSelStartFix, BSelLength); while PrevSelText <> SelText do begin Dec(BSelStartFix); - SelText := string(FEdit.Text).Substring(BSelStartFix, BSelLength); + SelText := Copy(FEdit.Text, BSelStartFix, BSelLength); end; // 计算正确的 SelStart。 - SelStart := FPrevSelStart + UTF8Length(PChar(FPrevText) + BPrevSelStart, BSelStartFix - BPrevSelStart); + SelStart := FPrevSelStart + UTF8LengthFast(PChar(FPrevText) + BPrevSelStart, BSelStartFix - BPrevSelStart - 1); end else if FEdit.SelStart > FPrevSelStart then // SelStart 发生了偏移,执行的是向头拖拽,接下来要从 SelStart 处开始向头比 @@ -518,10 +516,10 @@ begin // 获取 PrevSelStart 的字节索引。 // UTF8CharToByteIndex 的参数和结果是从索引 0 开始计数的。 - BPrevSelStart := UTF8CharToByteIndex(PChar(FPrevText), FPrevText.Length, FPrevSelStart); + BPrevSelStart := UTF8CharToByteIndex(PChar(FPrevText), Length(FPrevText), FPrevSelStart); // 获取新增内容的字节长度 - BSelLength := Length(FEdit.Text) - FPrevText.Length; - PrevSelText := FPrevText.Substring(BPrevSelStart, BSelLength); + BSelLength := Length(FEdit.Text) - Length(FPrevText); + PrevSelText := Copy(FPrevText, BPrevSelStart + 1, BSelLength); // 准备查找的起始位置(索引从 1 开始,跳过已选择的部分)。 BSelStartFix := BPrevSelStart + BSelLength + 1; // FEdit.Text 偏移后的 SelStart BSelStartFix2 := BPrevSelStart + 1; // FPrevSelStart @@ -534,25 +532,23 @@ SelText := PrevSelText; end else begin - // 将索引恢复到从 0 开始。 - Dec(BSelStartFix); // 跳过找到的不同的字符 - BSelStartFix := BSelStartFix + UTF8CharacterLength(PChar(FEdit.Text) + BSelStartFix); + BSelStartFix := BSelStartFix + UTF8CharacterLength(PChar(FEdit.Text) + BSelStartFix - 1); // 获取新增加的内容(新增加的内容不一定就是之前选择的内容,比如 a++b++c++, // 当把 +c+ 拖到 b+ 之前,就会出现这种情况)。 - // Substring 的参数是从索引 0 开始计数的。 - if BSelStartFix < BSelLength then BSelStartFix := BSelLength; + // Copy 的参数是从索引 1 开始计数的。 + if BSelStartFix <= BSelLength then BSelStartFix := BSelLength + 1; // 将 BSelStartFix 定位到新添加文本的开头位置 Dec(BSelStartFix, BSelLength); // 获取新添加的文本 - SelText := string(FEdit.Text).Substring(BSelStartFix, BSelLength); + SelText := Copy(FEdit.Text, BSelStartFix, BSelLength); // 修补错误的结果 while (PrevSelText <> SelText) do begin Inc(BSelStartFix); - SelText := string(FEdit.Text).Substring(BSelStartFix, BSelLength); + SelText := Copy(FEdit.Text, BSelStartFix, BSelLength); end; // 计算正确的 SelStart - SelStart := FPrevSelStart - UTF8Length(PChar(FPrevText) + BSelStartFix, BPrevSelStart - BSelStartFix); + SelStart := FPrevSelStart - UTF8LengthFast(PChar(FPrevText) + BSelStartFix - 1, BPrevSelStart - BSelStartFix + 1); end; end else begin ShowMessage('CalcRecordGTK2Memo: History Record Error !'); @@ -565,7 +561,7 @@ PHR^.SelStart := PHR^.PrevSelStart; PHR^.SelText := SelText; - PHR^.SelLength := UTF8Length(SelText); + PHR^.SelLength := UTF8LengthFast(SelText); {$ifdef DEBUG} // 太长的内容会导致输出信息时间过长 @@ -576,7 +572,7 @@ writeln('CalcRecordGTK2Memo: AddOrDel: ', SelText.Replace(#10, '_'), ' | ', SelStart, ' ', PHR^.SelLength); writeln('------------------------------') {$endif} - end else if (FEdit.SelStart = FPrevSelStart) and (Length(FEdit.Text) > FPrevText.Length) then + end else if (FEdit.SelStart = FPrevSelStart) and (Length(FEdit.Text) > Length(FPrevText)) then CalcRecordHard(PHR) else if FEdit.SelStart - FPrevSelStart > 1 then // 粘贴的情况已经在之前被拦截了 CalcRecordHard(PHR) @@ -601,9 +597,9 @@ if Len > PrevLen then begin // Add content to FEdit Dec(SelStart); - SelText := string(FEdit.Text).Substring(SelStart, (Len - PrevLen)); - SelLength := UTF8Length(SelText); - SelStart := UTF8Length(PChar(FEdit.Text), SelStart); + SelText := Copy(FEdit.Text, SelStart + 1, (Len - PrevLen)); + SelLength := UTF8LengthFast(SelText); + SelStart := UTF8LengthFast(PChar(FEdit.Text), SelStart); PHR^.PrevSelStart := SelStart; PHR^.PrevSelLength := 0; @@ -614,9 +610,9 @@ PHR^.SelText := SelText; end else if Len < PrevLen then begin Dec(PrevSelStart); - SelText := FPrevText.Substring(PrevSelStart, (PrevLen - Len)); - SelLength := UTF8Length(SelText); - SelStart := UTF8Length(PChar(FPrevText), PrevSelStart); + SelText := Copy(FPrevText, PrevSelStart + 1, (PrevLen - Len)); + SelLength := UTF8LengthFast(SelText); + SelStart := UTF8LengthFast(PChar(FPrevText), PrevSelStart); PHR^.PrevSelStart := SelStart; PHR^.PrevSelLength := SelLength; @@ -629,7 +625,7 @@ ShowMessage('CalcRecordHard: History Record Error !'); Exit; end; - if (FEdit.SelLength > 0) and (Length(FEdit.Text) > FPrevText.Length) then begin + if (FEdit.SelLength > 0) and (Length(FEdit.Text) > Length(FPrevText)) then begin PHR^.HalfRecord := hrFirstHalf; FHalfRecord := True; end else if FHalfRecord then begin @@ -731,11 +727,12 @@ SelStart := FEdit.SelStart; SelLength := FEdit.SelLength; SelText := FEdit.SelText; - ClipBoardText := ToLF(ClipBoard.AsText);; + ClipBoardText := ClipBoard.AsText; Enabled := False; - FEdit.SelText := ClipBoardText; - FHistory.AddRecord(SelStart, SelLength, SelText, SelStart, UTF8Length(ClipBoardText), ClipBoardText); + FEdit.PasteFromClipboard; + // FEdit.SelText := ClipBoardText; + FHistory.AddRecord(SelStart, SelLength, SelText, SelStart, UTF8LengthFast(ClipBoardText), ClipBoardText); FPrevText := FEdit.Text; Enabled := True; end; @@ -783,7 +780,7 @@ function THistoryManager.GetTotalSize: integer; begin - Result := FTotalSize + Size + FPrevText.Length; + Result := FTotalSize + Size + Length(FPrevText); end; procedure THistoryManager.SetEnabled(AValue: boolean); diff -Nru tominote-1.0.0/src/Units/utreedb.pas tominote-1.0.0/src/Units/utreedb.pas --- tominote-1.0.0/src/Units/utreedb.pas 2017-11-23 23:54:40.000000000 +0000 +++ tominote-1.0.0/src/Units/utreedb.pas 2017-11-29 21:45:59.000000000 +0000 @@ -1016,7 +1016,7 @@ if Assigned(Children) and (Depth <> 0) then begin // 将节点导出为目录 - ToDir := GetNotExistsPath(ToDir, Name, '', 3); + ToDir := GetNonExistsPath(ToDir, Name, '', 3); ForceDirectories(ToDir); // 保存节点的内容到文本文件 @@ -1029,7 +1029,7 @@ else begin // 将节点导出为文本文件 - WriteFile(GetNotExistsPath(ToDir, Name, Ext, 3), Note); + WriteFile(GetNonExistsPath(ToDir, Name, Ext, 3), Note); end; end; @@ -1157,12 +1157,12 @@ Dec(Depth); // 在节点名称中搜索 - if IncludeName and (UTF8Search(ID, GetName(ID), ASearchText, IgnoreCase, nil, 1, 1) > 0) then + if IncludeName and (UTF8Pos(GetName(ID), ASearchText, IgnoreCase) > 0) then Rst.Add(ID, 0, 0); // 在节点内容中搜索 if IncludeNote then - UTF8Search(ID, GetNote(ID), ASearchText, IgnoreCase, Rst); + UTF8SearchSpecial(ID, GetNote(ID), ASearchText, IgnoreCase, Rst); if Depth = 0 then Exit; for Child in GetChildren(ID) do @@ -1205,14 +1205,14 @@ if IncludeName then begin Count := Rst.Count; - NewName := UTF8Replace(ID, GetName(ID), ASearchText, AReplaceText, IgnoreCase, Rst); + NewName := UTF8ReplaceSpecial(ID, GetName(ID), ASearchText, AReplaceText, IgnoreCase, Rst); if Count < Rst.Count then SetName(ID, NewName); end; if IncludeNote then begin Count := Rst.Count; - NewNote := UTF8Replace(ID, GetNote(ID), ASearchText, AReplaceText, IgnoreCase, Rst); + NewNote := UTF8ReplaceSpecial(ID, GetNote(ID), ASearchText, AReplaceText, IgnoreCase, Rst); if Count < Rst.Count then SetNote(ID, NewNote); end; @@ -1334,9 +1334,9 @@ // 获取单个替换结果 ReplacedOne := ReplaceRegExpr(ASearchText, Expr.Match[0], AReplaceText, True); - ReplacedLength := UTF8Length(ReplacedOne); + ReplacedLength := UTF8LengthFast(ReplacedOne); - ReplacedStart := ReplacedStart + UTF8Length(MiddleString); + ReplacedStart := ReplacedStart + UTF8LengthFast(MiddleString); Rst.Add(ID, ReplacedStart, ReplacedLength); Result := Result + MiddleString + ReplacedOne; @@ -1406,5 +1406,6 @@ // 为 SQLite3 控件指定一个动态链接库文件,如果未指定,则使用系统默认的动态链接库文件 if FileExists(LibFile) then SQLiteDefaultLibrary := LibFile; + end.