From 2b81b7f01e12c1ad3f0442bace31a82eac00b01f Mon Sep 17 00:00:00 2001 From: DrKLO Date: Fri, 22 May 2015 00:27:27 +0300 Subject: [PATCH] update to 2.9.1 --- TMessagesProj/build.gradle | 6 +- TMessagesProj/jni/sqlite/sqlite3.c | 6662 +++++++++++------ TMessagesProj/jni/sqlite/sqlite3.h | 698 +- .../libs/armeabi-v7a/libtmessages.8.so | Bin 1569668 -> 1577868 bytes TMessagesProj/libs/armeabi/libtmessages.8.so | Bin 1114980 -> 1119076 bytes TMessagesProj/libs/x86/libtmessages.8.so | Bin 1877932 -> 1886124 bytes TMessagesProj/src/main/AndroidManifest.xml | 14 + .../telegram/PhoneFormat/CallingCodeInfo.java | 12 +- .../telegram/android/AndroidUtilities.java | 319 +- .../android/AutoMessageHeardReceiver.java | 26 + .../android/AutoMessageReplyReceiver.java | 37 + .../main/java/org/telegram/android/Emoji.java | 6 +- .../org/telegram/android/ImageLoader.java | 299 +- .../org/telegram/android/ImageReceiver.java | 100 +- .../telegram/android/LocaleController.java | 113 +- .../java/org/telegram/android/LruCache.java | 3 - .../org/telegram/android/MediaController.java | 77 +- .../org/telegram/android/MessageObject.java | 63 +- .../telegram/android/MessagesController.java | 316 +- .../org/telegram/android/MessagesStorage.java | 42 +- .../telegram/android/NotificationCenter.java | 147 +- .../android/NotificationsController.java | 243 +- .../org/telegram/android/ScreenReceiver.java | 1 + .../telegram/android/SecretChatHelper.java | 97 +- .../telegram/android/SendMessagesHelper.java | 316 +- .../org/telegram/android/SmsListener.java | 9 +- .../org/telegram/android/VideoEditedInfo.java | 51 + .../telegram/android/query/StickersQuery.java | 285 +- .../android/support/widget/RecyclerView.java | 2 + .../telegram/messenger/AbsSerializedData.java | 4 +- .../java/org/telegram/messenger/Action.java | 4 +- .../telegram/messenger/ApplicationLoader.java | 5 +- .../telegram/messenger/BuffersStorage.java | 16 +- .../org/telegram/messenger/BuildVars.java | 2 +- .../ByteArrayOutputStreamExpand.java | 2 +- .../telegram/messenger/ByteBufferDesc.java | 4 +- .../telegram/messenger/ConnectionContext.java | 4 +- .../messenger/ConnectionsManager.java | 130 +- .../org/telegram/messenger/Datacenter.java | 279 +- .../org/telegram/messenger/DispatchQueue.java | 4 +- .../messenger/ExportAuthorizationAction.java | 4 +- .../telegram/messenger/FileLoadOperation.java | 19 +- .../org/telegram/messenger/FileLoader.java | 181 +- .../java/org/telegram/messenger/FileLog.java | 13 +- .../messenger/FileUploadOperation.java | 25 +- .../telegram/messenger/HandshakeAction.java | 4 +- .../telegram/messenger/MessageKeyData.java | 58 +- .../telegram/messenger/NetworkMessage.java | 4 +- .../org/telegram/messenger/RPCRequest.java | 4 +- .../telegram/messenger/SerializedData.java | 4 +- .../org/telegram/messenger/ServerSalt.java | 4 +- .../org/telegram/messenger/TLClassStore.java | 26 +- .../java/org/telegram/messenger/TLObject.java | 9 +- .../java/org/telegram/messenger/TLRPC.java | 4507 ++++++----- .../org/telegram/messenger/TcpConnection.java | 66 +- .../org/telegram/messenger/UserConfig.java | 50 +- .../org/telegram/messenger/Utilities.java | 375 +- .../org/telegram/ui/ActionBar/ActionBar.java | 4 +- .../ui/ActionBar/ActionBarLayout.java | 7 +- .../telegram/ui/ActionBar/ActionBarMenu.java | 9 - .../ui/ActionBar/ActionBarMenuItem.java | 87 +- .../ui/ActionBar/ActionBarPopupWindow.java | 32 +- .../telegram/ui/ActionBar/BaseFragment.java | 20 +- .../telegram/ui/ActionBar/BottomSheet.java | 301 + .../Adapters/BaseSearchAdapterRecycler.java | 210 + .../ui/Adapters/ChatActivityAdapter.java | 2 +- .../telegram/ui/Adapters/DialogsAdapter.java | 96 +- .../ui/Adapters/DialogsSearchAdapter.java | 220 +- .../telegram/ui/Adapters/SearchAdapter.java | 4 +- .../telegram/ui/Adapters/StickersAdapter.java | 180 +- .../org/telegram/ui/BlockedUsersActivity.java | 28 +- .../org/telegram/ui/Cells/ChatActionCell.java | 8 +- .../org/telegram/ui/Cells/ChatAudioCell.java | 7 +- .../org/telegram/ui/Cells/ChatBaseCell.java | 10 +- .../telegram/ui/Cells/ChatContactCell.java | 2 +- .../org/telegram/ui/Cells/ChatMediaCell.java | 28 +- .../telegram/ui/Cells/ChatMessageCell.java | 114 +- .../org/telegram/ui/Cells/DialogCell.java | 48 +- .../telegram/ui/Cells/DrawerActionCell.java | 9 +- .../telegram/ui/Cells/DrawerProfileCell.java | 43 +- .../telegram/ui/Cells/GreySectionCell.java | 11 +- .../telegram/ui/Cells/HashtagSearchCell.java | 15 + .../org/telegram/ui/Cells/HeaderCell.java | 35 +- .../telegram/ui/Cells/LetterSectionCell.java | 6 +- .../org/telegram/ui/Cells/LoadingCell.java | 9 +- .../org/telegram/ui/Cells/MentionCell.java | 24 +- .../telegram/ui/Cells/PhotoEditToolCell.java | 25 +- .../ui/Cells/PhotoPickerAlbumsCell.java | 35 +- .../ui/Cells/PhotoPickerPhotoCell.java | 22 +- .../ui/Cells/PhotoPickerSearchCell.java | 33 +- .../telegram/ui/Cells/ProfileSearchCell.java | 32 +- .../org/telegram/ui/Cells/SessionCell.java | 57 +- .../ui/Cells/ShadowBottomSectionCell.java | 22 +- .../telegram/ui/Cells/ShadowSectionCell.java | 22 +- .../telegram/ui/Cells/SharedDocumentCell.java | 87 +- .../ui/Cells/SharedMediaSectionCell.java | 9 +- .../ui/Cells/SharedPhotoVideoCell.java | 10 +- .../org/telegram/ui/Cells/StickerCell.java | 13 +- .../telegram/ui/Cells/StickerEmojiCell.java | 36 +- .../org/telegram/ui/Cells/StickerSetCell.java | 144 + .../java/org/telegram/ui/Cells/TextCell.java | 36 +- .../org/telegram/ui/Cells/TextCheckCell.java | 18 +- .../org/telegram/ui/Cells/TextColorCell.java | 19 +- .../org/telegram/ui/Cells/TextDetailCell.java | 29 +- .../ui/Cells/TextDetailSettingsCell.java | 20 +- .../org/telegram/ui/Cells/TextInfoCell.java | 9 +- .../ui/Cells/TextInfoPrivacyCell.java | 14 +- .../telegram/ui/Cells/TextSettingsCell.java | 28 +- .../org/telegram/ui/Cells/WallpaperCell.java | 75 + .../telegram/ui/ChangeChatNameActivity.java | 12 +- .../org/telegram/ui/ChangeNameActivity.java | 21 +- .../org/telegram/ui/ChangePhoneActivity.java | 43 +- .../telegram/ui/ChangePhoneHelpActivity.java | 2 +- .../telegram/ui/ChangeUsernameActivity.java | 2 +- .../java/org/telegram/ui/ChatActivity.java | 410 +- .../telegram/ui/Components/AvatarUpdater.java | 49 +- .../ui/Components/BackupImageView.java | 20 +- .../ui/Components/ChatActivityEnterView.java | 83 +- .../org/telegram/ui/Components/EmojiView.java | 171 +- .../ui/Components/EmptyTextProgressView.java | 103 + .../ui/Components/ForegroundDetector.java | 2 + .../ui/Components/HorizontalListView.java | 389 - .../telegram/ui/Components/LayoutHelper.java | 10 +- .../telegram/ui/Components/PasscodeView.java | 17 +- .../ui/Components/PhotoFilterView.java | 38 +- .../ui/Components/RecyclerExListView.java | 292 - .../ui/Components/RecyclerListView.java | 109 - .../Components/SizeNotifierFrameLayout.java | 111 + .../ui/Components/StaticLayoutEx.java | 8 +- .../telegram/ui/Components/StickersAlert.java | 138 + .../ui/Components/URLSpanNoUnderlineBold.java | 26 + .../ui/Components/WebFrameLayout.java | 232 + .../org/telegram/ui/ContactsActivity.java | 4 +- .../telegram/ui/DocumentSelectActivity.java | 15 +- .../org/telegram/ui/GroupCreateActivity.java | 9 +- .../telegram/ui/GroupCreateFinalActivity.java | 35 +- .../org/telegram/ui/GroupInviteActivity.java | 4 +- .../java/org/telegram/ui/IntroActivity.java | 11 +- .../telegram/ui/LanguageSelectActivity.java | 2 +- .../org/telegram/ui/LastSeenActivity.java | 6 +- .../telegram/ui/LastSeenUsersActivity.java | 2 +- .../java/org/telegram/ui/LaunchActivity.java | 117 +- .../java/org/telegram/ui/LoginActivity.java | 41 +- .../java/org/telegram/ui/MediaActivity.java | 6 +- .../org/telegram/ui/MessagesActivity.java | 432 +- .../ui/NotificationsSettingsActivity.java | 23 +- .../org/telegram/ui/PasscodeActivity.java | 20 +- .../telegram/ui/PhotoAlbumPickerActivity.java | 2 +- .../org/telegram/ui/PhotoPickerActivity.java | 28 +- .../java/org/telegram/ui/PhotoViewer.java | 17 +- .../ui/PopupNotificationActivity.java | 6 +- .../telegram/ui/PrivacySettingsActivity.java | 10 +- .../java/org/telegram/ui/ProfileActivity.java | 18 +- .../ui/ProfileNotificationsActivity.java | 19 +- .../org/telegram/ui/SecretPhotoViewer.java | 4 +- .../org/telegram/ui/SessionsActivity.java | 10 +- .../org/telegram/ui/SettingsActivity.java | 133 +- .../org/telegram/ui/StickersActivity.java | 316 + .../ui/TwoStepVerificationActivity.java | 16 +- .../org/telegram/ui/VideoEditorActivity.java | 17 +- .../org/telegram/ui/WallpapersActivity.java | 256 +- .../res/drawable-v21/bar_selector_grey.xml | 4 + .../main/res/drawable/bar_selector_grey.xml | 19 + .../src/main/res/layout/messages_list.xml | 95 - .../src/main/res/layout/recycler_view.xml | 5 - .../layout/settings_color_dialog_layout.xml | 14 - .../res/layout/settings_wallpapers_layout.xml | 30 - .../res/layout/settings_wallpapers_my_row.xml | 20 - .../layout/settings_wallpapers_other_row.xml | 19 - TMessagesProj/src/main/res/raw/sound_in.wav | Bin 12590 -> 12590 bytes .../src/main/res/values-ar/strings.xml | 31 +- .../src/main/res/values-de/strings.xml | 33 +- .../src/main/res/values-es/strings.xml | 31 +- .../src/main/res/values-it/strings.xml | 63 +- .../src/main/res/values-ko/strings.xml | 29 +- .../src/main/res/values-nl/strings.xml | 31 +- .../src/main/res/values-pt-rBR/strings.xml | 31 +- .../src/main/res/values-pt-rPT/strings.xml | 31 +- TMessagesProj/src/main/res/values/strings.xml | 29 +- .../src/main/res/xml/automotive_app_desc.xml | 4 + 180 files changed, 13675 insertions(+), 8826 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/android/AutoMessageHeardReceiver.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/AutoMessageReplyReceiver.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/VideoEditedInfo.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapterRecycler.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerExListView.java delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderlineBold.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java create mode 100644 TMessagesProj/src/main/res/drawable-v21/bar_selector_grey.xml create mode 100644 TMessagesProj/src/main/res/drawable/bar_selector_grey.xml delete mode 100644 TMessagesProj/src/main/res/layout/messages_list.xml delete mode 100644 TMessagesProj/src/main/res/layout/recycler_view.xml delete mode 100644 TMessagesProj/src/main/res/layout/settings_color_dialog_layout.xml delete mode 100644 TMessagesProj/src/main/res/layout/settings_wallpapers_layout.xml delete mode 100644 TMessagesProj/src/main/res/layout/settings_wallpapers_my_row.xml delete mode 100644 TMessagesProj/src/main/res/layout/settings_wallpapers_other_row.xml create mode 100644 TMessagesProj/src/main/res/xml/automotive_app_desc.xml diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 446dfeae5..1b53792de 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:1.1.3' + classpath 'com.android.tools.build:gradle:1.2.3' } } apply plugin: 'com.android.application' @@ -81,7 +81,7 @@ android { defaultConfig { minSdkVersion 8 targetSdkVersion 22 - versionCode 521 - versionName "2.8.1" + versionCode 541 + versionName "2.9.1" } } diff --git a/TMessagesProj/jni/sqlite/sqlite3.c b/TMessagesProj/jni/sqlite/sqlite3.c index cae0c4ad2..a09cf7178 100644 --- a/TMessagesProj/jni/sqlite/sqlite3.c +++ b/TMessagesProj/jni/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.8.8.1. By combining all the individual C code files into this +** version 3.8.10. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -22,9 +22,6 @@ #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif -#ifndef SQLITE_API -# define SQLITE_API -#endif /************** Begin file sqliteInt.h ***************************************/ /* ** 2001 September 15 @@ -73,6 +70,7 @@ #pragma warning(disable : 4055) #pragma warning(disable : 4100) #pragma warning(disable : 4127) +#pragma warning(disable : 4130) #pragma warning(disable : 4152) #pragma warning(disable : 4189) #pragma warning(disable : 4206) @@ -90,6 +88,44 @@ /************** End of msvc.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ +/* +** Special setup for VxWorks +*/ +/************** Include vxworks.h in the middle of sqliteInt.h ***************/ +/************** Begin file vxworks.h *****************************************/ +/* +** 2015-03-02 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains code that is specific to Wind River's VxWorks +*/ +#if defined(__RTP__) || defined(_WRS_KERNEL) +/* This is VxWorks. Set up things specially for that OS +*/ +#include +#include /* amalgamator: dontcache */ +#define OS_VXWORKS 1 +#define SQLITE_OS_OTHER 0 +#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1 +#define SQLITE_OMIT_LOAD_EXTENSION 1 +#define SQLITE_ENABLE_LOCKING_STYLE 0 +#define HAVE_UTIME 1 +#else +/* This is not VxWorks. */ +#define OS_VXWORKS 0 +#endif /* defined(_WRS_KERNEL) */ + +/************** End of vxworks.h *********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + /* ** These #defines should enable >2GB file support on POSIX if the ** underlying operating system supports it. If the OS lacks @@ -214,16 +250,20 @@ extern "C" { /* -** Add the ability to override 'extern' +** Provide the ability to override linkage features of the interface. */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif - #ifndef SQLITE_API # define SQLITE_API #endif - +#ifndef SQLITE_CDECL +# define SQLITE_CDECL +#endif +#ifndef SQLITE_STDCALL +# define SQLITE_STDCALL +#endif /* ** These no-op macros are used in front of interfaces to mark those @@ -278,9 +318,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.8.8.1" -#define SQLITE_VERSION_NUMBER 3008008 -#define SQLITE_SOURCE_ID "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55" +#define SQLITE_VERSION "3.8.10" +#define SQLITE_VERSION_NUMBER 3008010 +#define SQLITE_SOURCE_ID "2015-05-07 11:53:08 cf975957b9ae671f34bb65f049acf351e650d437" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -313,9 +353,9 @@ extern "C" { ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; -SQLITE_API const char *sqlite3_libversion(void); -SQLITE_API const char *sqlite3_sourceid(void); -SQLITE_API int sqlite3_libversion_number(void); +SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void); +SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void); +SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics @@ -340,8 +380,8 @@ SQLITE_API int sqlite3_libversion_number(void); ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_API int sqlite3_compileoption_used(const char *zOptName); -SQLITE_API const char *sqlite3_compileoption_get(int N); +SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); #endif /* @@ -380,7 +420,7 @@ SQLITE_API const char *sqlite3_compileoption_get(int N); ** ** See the [threading mode] documentation for additional information. */ -SQLITE_API int sqlite3_threadsafe(void); +SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle @@ -437,6 +477,7 @@ typedef sqlite_uint64 sqlite3_uint64; /* ** CAPI3REF: Closing A Database Connection +** DESTRUCTOR: sqlite3 ** ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors ** for the [sqlite3] object. @@ -476,8 +517,8 @@ typedef sqlite_uint64 sqlite3_uint64; ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ -SQLITE_API int sqlite3_close(sqlite3*); -SQLITE_API int sqlite3_close_v2(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*); /* ** The type for a callback function. @@ -488,6 +529,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); /* ** CAPI3REF: One-Step Query Execution Interface +** METHOD: sqlite3 ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], @@ -547,7 +589,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. ** */ -SQLITE_API int sqlite3_exec( +SQLITE_API int SQLITE_STDCALL sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ @@ -927,14 +969,16 @@ struct sqlite3_io_methods { ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] ** interface. ** +**
    +**
  • [[SQLITE_FCNTL_LOCKSTATE]] ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This ** opcode causes the xFileControl method to write the current state of ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) ** into an integer that the pArg argument points to. This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -**
      +** is used during testing and is only available when the SQLITE_TEST +** compile-time option is used. +** **
    • [[SQLITE_FCNTL_SIZE_HINT]] ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS ** layer a hint of how large the database file will grow to be during the @@ -1059,7 +1103,9 @@ struct sqlite3_io_methods { ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] ** file control returns [SQLITE_OK], then the parser assumes that the ** VFS has handled the PRAGMA itself and the parser generates a no-op -** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** prepared statement if result string is NULL, or that returns a copy +** of the result string if the string is non-NULL. +** ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] @@ -1117,12 +1163,19 @@ struct sqlite3_io_methods { ** pointed to by the pArg argument. This capability is used during testing ** and only needs to be supported when SQLITE_TEST is defined. ** +**
    • [[SQLITE_FCNTL_WAL_BLOCK]] +** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might +** be advantageous to block on the next WAL lock if the lock is not immediately +** available. The WAL subsystem issues this signal during rare +** circumstances in order to fix a problem with priority inversion. +** Applications should not use this file-control. +** **
    */ #define SQLITE_FCNTL_LOCKSTATE 1 -#define SQLITE_GET_LOCKPROXYFILE 2 -#define SQLITE_SET_LOCKPROXYFILE 3 -#define SQLITE_LAST_ERRNO 4 +#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 +#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 +#define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 @@ -1141,6 +1194,13 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 +#define SQLITE_FCNTL_WAL_BLOCK 24 + +/* deprecated names */ +#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE +#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO + /* ** CAPI3REF: Mutex Handle @@ -1489,10 +1549,10 @@ struct sqlite3_vfs { ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ -SQLITE_API int sqlite3_initialize(void); -SQLITE_API int sqlite3_shutdown(void); -SQLITE_API int sqlite3_os_init(void); -SQLITE_API int sqlite3_os_end(void); +SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void); +SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void); +SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void); +SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library @@ -1523,10 +1583,11 @@ SQLITE_API int sqlite3_os_end(void); ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ -SQLITE_API int sqlite3_config(int, ...); +SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections +** METHOD: sqlite3 ** ** The sqlite3_db_config() interface is used to make configuration ** changes to a [database connection]. The interface is similar to @@ -1541,7 +1602,7 @@ SQLITE_API int sqlite3_config(int, ...); ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. */ -SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); +SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines @@ -1701,7 +1762,7 @@ struct sqlite3_mem_methods { **
  • [sqlite3_memory_used()] **
  • [sqlite3_memory_highwater()] **
  • [sqlite3_soft_heap_limit64()] -**
  • [sqlite3_status()] +**
  • [sqlite3_status64()] **
)^ ** ^Memory allocation statistics are enabled by default unless SQLite is ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory @@ -1912,7 +1973,6 @@ struct sqlite3_mem_methods { ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value ** that specifies the maximum size of the created heap. -** ** ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] **
SQLITE_CONFIG_PCACHE_HDRSZ @@ -2025,15 +2085,17 @@ struct sqlite3_mem_methods { /* ** CAPI3REF: Enable Or Disable Extended Result Codes +** METHOD: sqlite3 ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ -SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); +SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid +** METHOD: sqlite3 ** ** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables) ** has a unique 64-bit signed @@ -2081,10 +2143,11 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ -SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified +** METHOD: sqlite3 ** ** ^This function returns the number of rows modified, inserted or ** deleted by the most recently completed INSERT, UPDATE or DELETE @@ -2133,10 +2196,11 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ -SQLITE_API int sqlite3_changes(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified +** METHOD: sqlite3 ** ** ^This function returns the total number of rows inserted, modified or ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed @@ -2156,10 +2220,11 @@ SQLITE_API int sqlite3_changes(sqlite3*); ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ -SQLITE_API int sqlite3_total_changes(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query +** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically @@ -2195,7 +2260,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*); ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ -SQLITE_API void sqlite3_interrupt(sqlite3*); +SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete @@ -2230,12 +2295,13 @@ SQLITE_API void sqlite3_interrupt(sqlite3*); ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ -SQLITE_API int sqlite3_complete(const char *sql); -SQLITE_API int sqlite3_complete16(const void *sql); +SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql); +SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors ** KEYWORDS: {busy-handler callback} {busy handler} +** METHOD: sqlite3 ** ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X ** that might be invoked with argument P whenever @@ -2291,10 +2357,11 @@ SQLITE_API int sqlite3_complete16(const void *sql); ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ -SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); +SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); /* ** CAPI3REF: Set A Busy Timeout +** METHOD: sqlite3 ** ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps ** for a specified amount of time when a table is locked. ^The handler @@ -2313,10 +2380,11 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); ** ** See also: [PRAGMA busy_timeout] */ -SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); +SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries +** METHOD: sqlite3 ** ** This is a legacy interface that is preserved for backwards compatibility. ** Use of this interface is not recommended. @@ -2387,7 +2455,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ -SQLITE_API int sqlite3_get_table( +SQLITE_API int SQLITE_STDCALL sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ @@ -2395,13 +2463,17 @@ SQLITE_API int sqlite3_get_table( int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); -SQLITE_API void sqlite3_free_table(char **result); +SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. +** These routines understand most of the common K&R formatting options, +** plus some additional non-standard formats, detailed below. +** Note that some of the more obscure formatting options from recent +** C-library standards are omitted from this implementation. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their ** results into memory obtained from [sqlite3_malloc()]. @@ -2434,7 +2506,7 @@ SQLITE_API void sqlite3_free_table(char **result); ** These routines all implement some additional formatting ** options that are useful for constructing SQL statements. ** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. +** is are "%q", "%Q", "%w" and "%z" options. ** ** ^(The %q option works like %s in that it substitutes a nul-terminated ** string from the argument list. But %q also doubles every '\'' character. @@ -2487,14 +2559,20 @@ SQLITE_API void sqlite3_free_table(char **result); ** The code above will render a correct SQL statement in the zSQL ** variable even if the zText variable is a NULL pointer. ** +** ^(The "%w" formatting option is like "%q" except that it expects to +** be contained within double-quotes instead of single quotes, and it +** escapes the double-quote character instead of the single-quote +** character.)^ The "%w" formatting option is intended for safely inserting +** table and column names into a constructed SQL statement. +** ** ^(The "%z" formatting option works like "%s" but with the ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ -SQLITE_API char *sqlite3_mprintf(const char*,...); -SQLITE_API char *sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); +SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); +SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem @@ -2584,12 +2662,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ -SQLITE_API void *sqlite3_malloc(int); -SQLITE_API void *sqlite3_malloc64(sqlite3_uint64); -SQLITE_API void *sqlite3_realloc(void*, int); -SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64); -SQLITE_API void sqlite3_free(void*); -SQLITE_API sqlite3_uint64 sqlite3_msize(void*); +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int); +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64); +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int); +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64); +SQLITE_API void SQLITE_STDCALL sqlite3_free(void*); +SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); /* ** CAPI3REF: Memory Allocator Statistics @@ -2614,8 +2692,8 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void*); ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ -SQLITE_API sqlite3_int64 sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator @@ -2638,10 +2716,11 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ -SQLITE_API void sqlite3_randomness(int N, void *P); +SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks +** METHOD: sqlite3 ** ** ^This routine registers an authorizer callback with a particular ** [database connection], supplied in the first argument. @@ -2720,7 +2799,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P); ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ -SQLITE_API int sqlite3_set_authorizer( +SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData @@ -2798,6 +2877,7 @@ SQLITE_API int sqlite3_set_authorizer( /* ** CAPI3REF: Tracing And Profiling Functions +** METHOD: sqlite3 ** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. @@ -2824,12 +2904,13 @@ SQLITE_API int sqlite3_set_authorizer( ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ -SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, +SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); /* ** CAPI3REF: Query Progress Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to @@ -2859,10 +2940,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, ** database connections for the meaning of "modify" in this paragraph. ** */ -SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection +** CONSTRUCTOR: sqlite3 ** ** ^These routines open an SQLite database file as specified by the ** filename argument. ^The filename argument is interpreted as UTF-8 for @@ -3087,15 +3169,15 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** ** See also: [sqlite3_temp_directory] */ -SQLITE_API int sqlite3_open( +SQLITE_API int SQLITE_STDCALL sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int sqlite3_open16( +SQLITE_API int SQLITE_STDCALL sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int sqlite3_open_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -3141,19 +3223,22 @@ SQLITE_API int sqlite3_open_v2( ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ -SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); -SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); +SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* ** CAPI3REF: Error Codes And Messages +** METHOD: sqlite3 ** -** ^The sqlite3_errcode() interface returns the numeric [result code] or -** [extended result code] for the most recent failed sqlite3_* API call -** associated with a [database connection]. If a prior API call failed -** but the most recent API call succeeded, the return value from -** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() +** ^If the most recent sqlite3_* API call associated with +** [database connection] D failed, then the sqlite3_errcode(D) interface +** returns the numeric [result code] or [extended result code] for that +** API call. +** If the most recent API call was successful, +** then the return value from sqlite3_errcode() is undefined. +** ^The sqlite3_extended_errcode() ** interface is the same except that it always returns the ** [extended result code] even when extended result codes are ** disabled. @@ -3184,40 +3269,41 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ -SQLITE_API int sqlite3_errcode(sqlite3 *db); -SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *sqlite3_errmsg(sqlite3*); -SQLITE_API const void *sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *sqlite3_errstr(int); +SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db); +SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int); /* -** CAPI3REF: SQL Statement Object +** CAPI3REF: Prepared Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** -** An instance of this object represents a single SQL statement. -** This object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". +** An instance of this object represents a single SQL statement that +** has been compiled into binary form and is ready to be evaluated. ** -** The life of a statement object goes something like this: +** Think of each SQL statement as a separate computer program. The +** original SQL text is source code. A prepared statement object +** is the compiled object code. All SQL must be converted into a +** prepared statement before it can be run. +** +** The life-cycle of a prepared statement object usually goes like this: ** **
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to [host parameters] using the sqlite3_bind_*() +**
  3. Create the prepared statement object using [sqlite3_prepare_v2()]. +**
  4. Bind values to [parameters] using the sqlite3_bind_*() ** interfaces. **
  5. Run the SQL by calling [sqlite3_step()] one or more times. -**
  6. Reset the statement using [sqlite3_reset()] then go back +**
  7. Reset the prepared statement using [sqlite3_reset()] then go back ** to step 2. Do this zero or more times. **
  8. Destroy the object using [sqlite3_finalize()]. **
-** -** Refer to documentation on individual methods above for additional -** information. */ typedef struct sqlite3_stmt sqlite3_stmt; /* ** CAPI3REF: Run-time Limits +** METHOD: sqlite3 ** ** ^(This interface allows the size of various constructs to be limited ** on a connection by connection basis. The first parameter is the @@ -3255,7 +3341,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** ** New run-time limit categories may be added in future releases. */ -SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); +SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories @@ -3329,6 +3415,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_stmt ** ** To execute an SQL query, it must first be compiled into a byte-code ** program using one of these routines. @@ -3342,16 +3430,14 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() ** use UTF-16. ** -** ^If the nByte argument is less than zero, then zSql is read up to the -** first zero terminator. ^If nByte is non-negative, then it is the maximum -** number of bytes read from zSql. ^When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** the nByte-th byte, whichever comes first. If the caller knows -** that the supplied string is nul-terminated, then there is a small -** performance advantage to be gained by passing an nByte parameter that -** is equal to the number of bytes in the input string including -** the nul-terminator bytes as this saves SQLite from having to -** make a copy of the input string. +** ^If the nByte argument is negative, then zSql is read up to the +** first zero terminator. ^If nByte is positive, then it is the +** number of bytes read from zSql. ^If nByte is zero, then no prepared +** statement is generated. +** If the caller knows that the supplied string is nul-terminated, then +** there is a small performance advantage to passing an nByte parameter that +** is the number of bytes in the input string including +** the nul-terminator. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte ** past the end of the first SQL statement in zSql. These routines only @@ -3407,28 +3493,28 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ** */ -SQLITE_API int sqlite3_prepare( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int sqlite3_prepare_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int sqlite3_prepare16( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int sqlite3_prepare16_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -3438,15 +3524,17 @@ SQLITE_API int sqlite3_prepare16_v2( /* ** CAPI3REF: Retrieving Statement SQL +** METHOD: sqlite3_stmt ** ** ^This interface can be used to retrieve a saved copy of the original ** SQL text used to create a [prepared statement] if that statement was ** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. */ -SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database +** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to @@ -3474,10 +3562,11 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. */ -SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset +** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the ** [prepared statement] S has been stepped at least once using @@ -3493,7 +3582,7 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ -SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); /* ** CAPI3REF: Dynamically Typed Value Object @@ -3552,6 +3641,7 @@ typedef struct sqlite3_context sqlite3_context; ** CAPI3REF: Binding Values To Prepared Statements ** KEYWORDS: {host parameter} {host parameters} {host parameter name} ** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** METHOD: sqlite3_stmt ** ** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, ** literals may be replaced by a [parameter] that matches one of following @@ -3654,22 +3744,23 @@ typedef struct sqlite3_context sqlite3_context; ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ -SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, void(*)(void*)); -SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, +SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); /* ** CAPI3REF: Number Of SQL Parameters +** METHOD: sqlite3_stmt ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the @@ -3686,10 +3777,11 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); ** [sqlite3_bind_parameter_name()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter +** METHOD: sqlite3_stmt ** ** ^The sqlite3_bind_parameter_name(P,N) interface returns ** the name of the N-th [SQL parameter] in the [prepared statement] P. @@ -3713,10 +3805,11 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name +** METHOD: sqlite3_stmt ** ** ^Return the index of an SQL parameter given its name. ^The ** index value returned is suitable for use as the second @@ -3729,19 +3822,21 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement +** METHOD: sqlite3_stmt ** ** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ -SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); +SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set +** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL @@ -3749,10 +3844,11 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); ** ** See also: [sqlite3_data_count()] */ -SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set +** METHOD: sqlite3_stmt ** ** ^These routines return the name assigned to a particular column ** in the result set of a [SELECT] statement. ^The sqlite3_column_name() @@ -3777,11 +3873,12 @@ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ -SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result +** METHOD: sqlite3_stmt ** ** ^These routines provide a means to determine the database, table, and ** table column that is the origin of a particular result column in @@ -3825,15 +3922,16 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ -SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result +** METHOD: sqlite3_stmt ** ** ^(The first parameter is a [prepared statement]. ** If this statement is a [SELECT] statement and the Nth column of the @@ -3861,11 +3959,12 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); ** is associated with individual values, not with the containers ** used to hold those values. */ -SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement +** METHOD: sqlite3_stmt ** ** After a [prepared statement] has been prepared using either ** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy @@ -3941,10 +4040,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ -SQLITE_API int sqlite3_step(sqlite3_stmt*); +SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set +** METHOD: sqlite3_stmt ** ** ^The sqlite3_data_count(P) interface returns the number of columns in the ** current row of the result set of [prepared statement] P. @@ -3961,7 +4061,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt*); ** ** See also: [sqlite3_column_count()] */ -SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes @@ -3998,6 +4098,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Result Values From A Query ** KEYWORDS: {column access functions} +** METHOD: sqlite3_stmt ** ** These routines form the "result set" interface. ** @@ -4157,19 +4258,20 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ -SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object +** DESTRUCTOR: sqlite3_stmt ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors @@ -4193,10 +4295,11 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ -SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object +** METHOD: sqlite3_stmt ** ** The sqlite3_reset() function is called to reset a [prepared statement] ** object back to its initial state, ready to be re-executed. @@ -4219,13 +4322,14 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ -SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} ** KEYWORDS: {application-defined SQL functions} +** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior @@ -4318,7 +4422,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ -SQLITE_API int sqlite3_create_function( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4328,7 +4432,7 @@ SQLITE_API int sqlite3_create_function( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int sqlite3_create_function16( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -4338,7 +4442,7 @@ SQLITE_API int sqlite3_create_function16( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int sqlite3_create_function_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4380,21 +4484,22 @@ SQLITE_API int sqlite3_create_function_v2( ** These functions are [deprecated]. In order to maintain ** backwards compatibility with older code, these functions continue ** to be supported. However, new applications should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you what they do. +** the use of these functions. To encourage programmers to avoid +** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif /* ** CAPI3REF: Obtaining SQL Function Parameter Values +** METHOD: sqlite3_value ** ** The C-language implementation of SQL functions and aggregates uses ** this set of interface routines to access the parameter values on @@ -4438,21 +4543,22 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ -SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API double sqlite3_value_double(sqlite3_value*); -SQLITE_API int sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int sqlite3_value_type(sqlite3_value*); -SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context +** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. @@ -4493,10 +4599,11 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ -SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); +SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions +** METHOD: sqlite3_context ** ** ^The sqlite3_user_data() interface returns a copy of ** the pointer that was the pUserData parameter (the 5th parameter) @@ -4507,10 +4614,11 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); ** This routine must be called from the same thread in which ** the application-defined function is running. */ -SQLITE_API void *sqlite3_user_data(sqlite3_context*); +SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions +** METHOD: sqlite3_context ** ** ^The sqlite3_context_db_handle() interface returns a copy of ** the pointer to the [database connection] (the 1st parameter) @@ -4518,10 +4626,11 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context*); ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ -SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data +** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to ** associate metadata with argument values. If the same value is passed to @@ -4570,8 +4679,8 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** These routines must be called from the same thread in which ** the SQL function is running. */ -SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* @@ -4594,6 +4703,7 @@ typedef void (*sqlite3_destructor_type)(void*); /* ** CAPI3REF: Setting The Result Of An SQL Function +** METHOD: sqlite3_context ** ** These routines are used by the xFunc or xFinal callbacks that ** implement SQL functions and aggregates. See @@ -4706,29 +4816,30 @@ typedef void (*sqlite3_destructor_type)(void*); ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ -SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*, sqlite3_uint64,void(*)(void*)); -SQLITE_API void sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void sqlite3_result_null(sqlite3_context*); -SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, +SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); /* ** CAPI3REF: Define New Collating Sequences +** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. @@ -4806,14 +4917,14 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ -SQLITE_API int sqlite3_create_collation( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); -SQLITE_API int sqlite3_create_collation_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, @@ -4821,7 +4932,7 @@ SQLITE_API int sqlite3_create_collation_v2( int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); -SQLITE_API int sqlite3_create_collation16( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, @@ -4831,6 +4942,7 @@ SQLITE_API int sqlite3_create_collation16( /* ** CAPI3REF: Collation Needed Callbacks +** METHOD: sqlite3 ** ** ^To avoid having to register all collation sequences before a database ** can be used, a single callback function may be registered with the @@ -4855,12 +4967,12 @@ SQLITE_API int sqlite3_create_collation16( ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ -SQLITE_API int sqlite3_collation_needed( +SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); -SQLITE_API int sqlite3_collation_needed16( +SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) @@ -4874,11 +4986,11 @@ SQLITE_API int sqlite3_collation_needed16( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int sqlite3_key( +SQLITE_API int SQLITE_STDCALL sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); -SQLITE_API int sqlite3_key_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The key */ @@ -4892,11 +5004,11 @@ SQLITE_API int sqlite3_key_v2( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int sqlite3_rekey( +SQLITE_API int SQLITE_STDCALL sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); -SQLITE_API int sqlite3_rekey_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The new key */ @@ -4906,7 +5018,7 @@ SQLITE_API int sqlite3_rekey_v2( ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ -SQLITE_API void sqlite3_activate_see( +SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -4916,7 +5028,7 @@ SQLITE_API void sqlite3_activate_see( ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ -SQLITE_API void sqlite3_activate_cerod( +SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -4938,7 +5050,7 @@ SQLITE_API void sqlite3_activate_cerod( ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ -SQLITE_API int sqlite3_sleep(int); +SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -5038,6 +5150,7 @@ SQLITE_API char *sqlite3_data_directory; /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} +** METHOD: sqlite3 ** ** ^The sqlite3_get_autocommit() interface returns non-zero or ** zero if the given database connection is or is not in autocommit mode, @@ -5056,10 +5169,11 @@ SQLITE_API char *sqlite3_data_directory; ** connection while this routine is running, then the return value ** is undefined. */ -SQLITE_API int sqlite3_get_autocommit(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement +** METHOD: sqlite3_stmt ** ** ^The sqlite3_db_handle interface returns the [database connection] handle ** to which a [prepared statement] belongs. ^The [database connection] @@ -5068,10 +5182,11 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*); ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ -SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection +** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename ** associated with database N of connection D. ^The main database file @@ -5084,19 +5199,21 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ -SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only +** METHOD: sqlite3 ** ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ -SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); +SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement +** METHOD: sqlite3 ** ** ^This interface returns a pointer to the next [prepared statement] after ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL @@ -5108,10 +5225,11 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ -SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); +SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_commit_hook() interface registers a callback ** function to be invoked whenever a transaction is [COMMIT | committed]. @@ -5156,11 +5274,12 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); ** ** See also the [sqlite3_update_hook()] interface. */ -SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument @@ -5207,7 +5326,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] ** interfaces. */ -SQLITE_API void *sqlite3_update_hook( +SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* @@ -5237,12 +5356,17 @@ SQLITE_API void *sqlite3_update_hook( ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. ** +** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 +** and will always return SQLITE_MISUSE. On those systems, +** shared cache mode should be enabled per-database connection via +** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. +** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** ** See Also: [SQLite Shared-Cache Mode] */ -SQLITE_API int sqlite3_enable_shared_cache(int); +SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory @@ -5258,10 +5382,11 @@ SQLITE_API int sqlite3_enable_shared_cache(int); ** ** See also: [sqlite3_db_release_memory()] */ -SQLITE_API int sqlite3_release_memory(int); +SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection +** METHOD: sqlite3 ** ** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap ** memory as possible from database connection D. Unlike the @@ -5271,7 +5396,7 @@ SQLITE_API int sqlite3_release_memory(int); ** ** See also: [sqlite3_release_memory()] */ -SQLITE_API int sqlite3_db_release_memory(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size @@ -5323,7 +5448,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*); ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ -SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface @@ -5334,11 +5459,12 @@ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ -SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); +SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); /* ** CAPI3REF: Extract Metadata About A Column Of A Table +** METHOD: sqlite3 ** ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns ** information about column C of table T in database D @@ -5403,7 +5529,7 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ -SQLITE_API int sqlite3_table_column_metadata( +SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -5417,6 +5543,7 @@ SQLITE_API int sqlite3_table_column_metadata( /* ** CAPI3REF: Load An Extension +** METHOD: sqlite3 ** ** ^This interface loads an SQLite extension library from the named file. ** @@ -5449,7 +5576,7 @@ SQLITE_API int sqlite3_table_column_metadata( ** ** See also the [load_extension() SQL function]. */ -SQLITE_API int sqlite3_load_extension( +SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ @@ -5458,6 +5585,7 @@ SQLITE_API int sqlite3_load_extension( /* ** CAPI3REF: Enable Or Disable Extension Loading +** METHOD: sqlite3 ** ** ^So as not to open security holes in older applications that are ** unprepared to deal with [extension loading], and as a means of disabling @@ -5469,7 +5597,7 @@ SQLITE_API int sqlite3_load_extension( ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. */ -SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); +SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions @@ -5507,7 +5635,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ -SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); +SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Cancel Automatic Extension Loading @@ -5519,7 +5647,7 @@ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ -SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); +SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading @@ -5527,7 +5655,7 @@ SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ -SQLITE_API void sqlite3_reset_auto_extension(void); +SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void); /* ** The interface to the virtual-table mechanism is currently considered @@ -5707,6 +5835,7 @@ struct sqlite3_index_info { /* ** CAPI3REF: Register A Virtual Table Implementation +** METHOD: sqlite3 ** ** ^These routines are used to register a new [virtual table module] name. ** ^Module names must be registered before @@ -5730,13 +5859,13 @@ struct sqlite3_index_info { ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. */ -SQLITE_API int sqlite3_create_module( +SQLITE_API int SQLITE_STDCALL sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData /* Client data for xCreate/xConnect */ ); -SQLITE_API int sqlite3_create_module_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ @@ -5764,7 +5893,7 @@ SQLITE_API int sqlite3_create_module_v2( */ struct sqlite3_vtab { const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* NO LONGER USED */ + int nRef; /* Number of open cursors */ char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; @@ -5799,10 +5928,11 @@ struct sqlite3_vtab_cursor { ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. */ -SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); +SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table +** METHOD: sqlite3 ** ** ^(Virtual tables can provide alternative implementations of functions ** using the [xFindFunction] method of the [virtual table module]. @@ -5817,7 +5947,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ -SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); +SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up @@ -5845,6 +5975,8 @@ typedef struct sqlite3_blob sqlite3_blob; /* ** CAPI3REF: Open A BLOB For Incremental I/O +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_blob ** ** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located ** in row iRow, column zColumn, table zTable in database zDb; @@ -5914,7 +6046,7 @@ typedef struct sqlite3_blob sqlite3_blob; ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ -SQLITE_API int sqlite3_blob_open( +SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, @@ -5926,6 +6058,7 @@ SQLITE_API int sqlite3_blob_open( /* ** CAPI3REF: Move a BLOB Handle to a New Row +** METHOD: sqlite3_blob ** ** ^This function is used to move an existing blob handle so that it points ** to a different row of the same database table. ^The new row is identified @@ -5946,10 +6079,11 @@ SQLITE_API int sqlite3_blob_open( ** ** ^This function sets the database handle error code and message. */ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); +SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle +** DESTRUCTOR: sqlite3_blob ** ** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed ** unconditionally. Even if this routine returns an error code, the @@ -5968,10 +6102,11 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_i ** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ -SQLITE_API int sqlite3_blob_close(sqlite3_blob *); +SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB +** METHOD: sqlite3_blob ** ** ^Returns the size in bytes of the BLOB accessible via the ** successfully opened [BLOB handle] in its only argument. ^The @@ -5983,10 +6118,11 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *); ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. */ -SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); +SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally +** METHOD: sqlite3_blob ** ** ^(This function is used to read data from an open [BLOB handle] into a ** caller-supplied buffer. N bytes of data are copied into buffer Z @@ -6011,10 +6147,11 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); ** ** See also: [sqlite3_blob_write()]. */ -SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); +SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally +** METHOD: sqlite3_blob ** ** ^(This function is used to write data into an open [BLOB handle] from a ** caller-supplied buffer. N bytes of data are copied from the buffer Z @@ -6052,7 +6189,7 @@ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); ** ** See also: [sqlite3_blob_read()]. */ -SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); +SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); /* ** CAPI3REF: Virtual File System Objects @@ -6083,9 +6220,9 @@ SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOff ** ^(If the default VFS is unregistered, another VFS is chosen as ** the default. The choice for the new VFS is arbitrary.)^ */ -SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); +SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); /* ** CAPI3REF: Mutexes @@ -6198,11 +6335,11 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ -SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); -SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); -SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); -SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); -SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*); /* ** CAPI3REF: Mutex Methods Object @@ -6312,8 +6449,8 @@ struct sqlite3_mutex_methods { ** interface should also return 1 when given a NULL pointer. */ #ifndef NDEBUG -SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); -SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); #endif /* @@ -6342,6 +6479,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); /* ** CAPI3REF: Retrieve the mutex for a database connection +** METHOD: sqlite3 ** ** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument @@ -6349,10 +6487,11 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ -SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files +** METHOD: sqlite3 ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated @@ -6383,7 +6522,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ -SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); +SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface @@ -6402,7 +6541,7 @@ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void* ** Unlike most of the SQLite API, this function is not guaranteed to ** operate consistently from one release to the next. */ -SQLITE_API int sqlite3_test_control(int op, ...); +SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); /* ** CAPI3REF: Testing Interface Operation Codes @@ -6436,12 +6575,13 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 -#define SQLITE_TESTCTRL_LAST 24 +#define SQLITE_TESTCTRL_IMPOSTER 25 +#define SQLITE_TESTCTRL_LAST 25 /* ** CAPI3REF: SQLite Runtime Status ** -** ^This interface is used to retrieve runtime status information +** ^These interfaces are used to retrieve runtime status information ** about the performance of SQLite, and optionally to reset various ** highwater marks. ^The first argument is an integer code for ** the specific parameter to measure. ^(Recognized integer codes @@ -6455,19 +6595,22 @@ SQLITE_API int sqlite3_test_control(int op, ...); ** ^(Other parameters record only the highwater mark and not the current ** value. For these latter parameters nothing is written into *pCurrent.)^ ** -** ^The sqlite3_status() routine returns SQLITE_OK on success and a -** non-zero [error code] on failure. +** ^The sqlite3_status() and sqlite3_status64() routines return +** SQLITE_OK on success and a non-zero [error code] on failure. ** -** This routine is threadsafe but is not atomic. This routine can be -** called while other threads are running the same or different SQLite -** interfaces. However the values returned in *pCurrent and -** *pHighwater reflect the status of SQLite at different points in time -** and it is possible that another thread might change the parameter -** in between the times when *pCurrent and *pHighwater are written. +** If either the current value or the highwater mark is too large to +** be represented by a 32-bit integer, then the values returned by +** sqlite3_status() are undefined. ** ** See also: [sqlite3_db_status()] */ -SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API int SQLITE_STDCALL sqlite3_status64( + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag +); /* @@ -6565,6 +6708,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF /* ** CAPI3REF: Database Connection Status +** METHOD: sqlite3 ** ** ^This interface is used to retrieve runtime status information ** about a single [database connection]. ^The first argument is the @@ -6585,7 +6729,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF ** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ -SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); +SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Status Parameters for database connections @@ -6693,6 +6837,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r /* ** CAPI3REF: Prepared Statement Status +** METHOD: sqlite3_stmt ** ** ^(Each prepared statement maintains various ** [SQLITE_STMTSTATUS counters] that measure the number @@ -6714,7 +6859,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ -SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements @@ -7137,20 +7282,20 @@ typedef struct sqlite3_backup sqlite3_backup; ** is not a permanent error and does not affect the return value of ** sqlite3_backup_finish(). ** -** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] +** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]] ** sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** -** ^Each call to sqlite3_backup_step() sets two values inside -** the [sqlite3_backup] object: the number of pages still to be backed -** up and the total number of pages in the source database file. -** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces -** retrieve these two values, respectively. -** -** ^The values returned by these functions are only updated by -** sqlite3_backup_step(). ^If the source database is modified during a backup -** operation, then the values are not updated to account for any extra -** pages that need to be updated or the size of the source database file -** changing. +** ^The sqlite3_backup_remaining() routine returns the number of pages still +** to be backed up at the conclusion of the most recent sqlite3_backup_step(). +** ^The sqlite3_backup_pagecount() routine returns the total number of pages +** in the source database at the conclusion of the most recent +** sqlite3_backup_step(). +** ^(The values returned by these functions are only updated by +** sqlite3_backup_step(). If the source database is modified in a way that +** changes the size of the source database or the number of pages remaining, +** those changes are not reflected in the output of sqlite3_backup_pagecount() +** and sqlite3_backup_remaining() until after the next +** sqlite3_backup_step().)^ ** ** Concurrent Usage of Database Handles ** @@ -7183,19 +7328,20 @@ typedef struct sqlite3_backup sqlite3_backup; ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ -SQLITE_API sqlite3_backup *sqlite3_backup_init( +SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); -SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification +** METHOD: sqlite3 ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or @@ -7308,7 +7454,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ -SQLITE_API int sqlite3_unlock_notify( +SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ @@ -7323,8 +7469,8 @@ SQLITE_API int sqlite3_unlock_notify( ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int sqlite3_stricmp(const char *, const char *); -SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); +SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *); +SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: String Globbing @@ -7339,7 +7485,7 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); ** Note that this routine returns zero on a match and non-zero if the strings ** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. */ -SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); +SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr); /* ** CAPI3REF: Error Logging Interface @@ -7362,10 +7508,11 @@ SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); ** a few hundred characters, it will be truncated to the length of the ** buffer. */ -SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); +SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook +** METHOD: sqlite3 ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that ** is invoked each time data is committed to a database in wal mode. @@ -7397,7 +7544,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** those overwrite any prior [sqlite3_wal_hook()] settings. */ -SQLITE_API void *sqlite3_wal_hook( +SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* @@ -7405,6 +7552,7 @@ SQLITE_API void *sqlite3_wal_hook( /* ** CAPI3REF: Configure an auto-checkpoint +** METHOD: sqlite3 ** ** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around ** [sqlite3_wal_hook()] that causes any database on [database connection] D @@ -7431,10 +7579,11 @@ SQLITE_API void *sqlite3_wal_hook( ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ -SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); +SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to ** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ @@ -7452,10 +7601,11 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); ** start a callback but which do not need the full power (and corresponding ** complication) of [sqlite3_wal_checkpoint_v2()]. */ -SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); +SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint ** operation on database X of [database connection] D in mode M. Status @@ -7545,7 +7695,7 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ -SQLITE_API int sqlite3_wal_checkpoint_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -7581,7 +7731,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ -SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); +SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options @@ -7634,7 +7784,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ -SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); +SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Conflict resolution modes @@ -7710,6 +7860,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Prepared Statement Scan Status +** METHOD: sqlite3_stmt ** ** This interface returns information about the predicted and measured ** performance for pStmt. Advanced applications can use this @@ -7738,7 +7889,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( +SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ @@ -7747,13 +7898,14 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( /* ** CAPI3REF: Zero Scan-Status Counters +** METHOD: sqlite3_stmt ** ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ -SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); +SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* @@ -7808,7 +7960,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; ** ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ -SQLITE_API int sqlite3_rtree_geometry_callback( +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), @@ -7834,7 +7986,7 @@ struct sqlite3_rtree_geometry { ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ -SQLITE_API int sqlite3_rtree_query_callback( +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( sqlite3 *db, const char *zQueryFunc, int (*xQueryFunc)(sqlite3_rtree_query_info*), @@ -7998,15 +8150,17 @@ struct sqlite3_rtree_query_info { #endif /* -** The maximum number of in-memory pages to use for the main database -** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE +** The suggested maximum number of in-memory pages to use for +** the main database table and for temporary tables. +** +** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size +** is 2000 pages. +** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be +** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options. */ #ifndef SQLITE_DEFAULT_CACHE_SIZE # define SQLITE_DEFAULT_CACHE_SIZE 2000 #endif -#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE -# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 -#endif /* ** The default number of frames to accumulate in the log file before @@ -8355,6 +8509,32 @@ SQLITE_PRIVATE void sqlite3Coverage(int); # define NEVER(X) (X) #endif +/* +** Declarations used for tracing the operating system interfaces. +*/ +#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \ + (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) + extern int sqlite3OSTrace; +# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X +# define SQLITE_HAVE_OS_TRACE +#else +# define OSTRACE(X) +# undef SQLITE_HAVE_OS_TRACE +#endif + +/* +** Is the sqlite3ErrName() function needed in the build? Currently, +** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when +** OSTRACE is enabled), and by several "test*.c" files (which are +** compiled using SQLITE_TEST). +*/ +#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \ + (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) +# define SQLITE_NEED_ERR_NAME +#else +# undef SQLITE_NEED_ERR_NAME +#endif + /* ** Return true (non-zero) if the input is an integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() @@ -8850,6 +9030,20 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */ */ typedef INT16_TYPE LogEst; +/* +** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer +*/ +#ifndef SQLITE_PTRSIZE +# if defined(__SIZEOF_POINTER__) +# define SQLITE_PTRSIZE __SIZEOF_POINTER__ +# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(_M_ARM) || defined(__arm__) || defined(__x86) +# define SQLITE_PTRSIZE 4 +# else +# define SQLITE_PTRSIZE 8 +# endif +#endif + /* ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. @@ -9062,8 +9256,8 @@ struct BusyHandler { #define SQLITE_WSD const #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) -SQLITE_API int sqlite3_wsd_init(int N, int J); -SQLITE_API void *sqlite3_wsd_find(void *K, int L); +SQLITE_API int SQLITE_STDCALL sqlite3_wsd_init(int N, int J); +SQLITE_API void *SQLITE_STDCALL sqlite3_wsd_find(void *K, int L); #else #define SQLITE_WSD #define GLOBAL(t,v) v @@ -9221,10 +9415,8 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); -SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); -#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG) +SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree*); SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p); -#endif SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); @@ -9302,8 +9494,18 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); /* ** Values that may be OR'd together to form the second argument of an ** sqlite3BtreeCursorHints() call. +** +** The BTREE_BULKLOAD flag is set on index cursors when the index is going +** to be filled with content that is already in sorted order. +** +** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or +** OP_SeekLE opcodes for a range search, but where the range of entries +** selected will all have the same key. In other words, the cursor will +** be used only for equality key searches. +** */ -#define BTREE_BULKLOAD 0x00000001 +#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */ +#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */ SQLITE_PRIVATE int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ @@ -9349,6 +9551,9 @@ SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); +#endif SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt); SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void); @@ -9715,23 +9920,25 @@ typedef struct VdbeOpList VdbeOpList; #define OP_MemMax 136 /* synopsis: r[P1]=max(r[P1],r[P2]) */ #define OP_IfPos 137 /* synopsis: if r[P1]>0 goto P2 */ #define OP_IfNeg 138 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2 */ -#define OP_IfZero 139 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */ -#define OP_AggFinal 140 /* synopsis: accum=r[P1] N=P2 */ -#define OP_IncrVacuum 141 -#define OP_Expire 142 -#define OP_TableLock 143 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 144 -#define OP_VCreate 145 -#define OP_VDestroy 146 -#define OP_VOpen 147 -#define OP_VColumn 148 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VNext 149 -#define OP_VRename 150 -#define OP_Pagecount 151 -#define OP_MaxPgcnt 152 -#define OP_Init 153 /* synopsis: Start at P2 */ -#define OP_Noop 154 -#define OP_Explain 155 +#define OP_IfNotZero 139 /* synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2 */ +#define OP_DecrJumpZero 140 /* synopsis: if (--r[P1])==0 goto P2 */ +#define OP_JumpZeroIncr 141 /* synopsis: if (r[P1]++)==0 ) goto P2 */ +#define OP_AggFinal 142 /* synopsis: accum=r[P1] N=P2 */ +#define OP_IncrVacuum 143 +#define OP_Expire 144 +#define OP_TableLock 145 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 146 +#define OP_VCreate 147 +#define OP_VDestroy 148 +#define OP_VOpen 149 +#define OP_VColumn 150 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VNext 151 +#define OP_VRename 152 +#define OP_Pagecount 153 +#define OP_MaxPgcnt 154 +#define OP_Init 155 /* synopsis: Start at P2 */ +#define OP_Noop 156 +#define OP_Explain 157 /* Properties such as "out2" or "jump" that are specified in @@ -9739,33 +9946,32 @@ typedef struct VdbeOpList VdbeOpList; ** are encoded into bitvectors as follows: */ #define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ -#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */ -#define OPFLG_IN1 0x0004 /* in1: P1 is an input */ -#define OPFLG_IN2 0x0008 /* in2: P2 is an input */ -#define OPFLG_IN3 0x0010 /* in3: P3 is an input */ -#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */ -#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */ +#define OPFLG_IN1 0x0002 /* in1: P1 is an input */ +#define OPFLG_IN2 0x0004 /* in2: P2 is an input */ +#define OPFLG_IN3 0x0008 /* in3: P3 is an input */ +#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */ +#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */ #define OPFLG_INITIALIZER {\ /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\ -/* 8 */ 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,\ -/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\ -/* 24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\ -/* 32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\ -/* 40 */ 0x04, 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00,\ -/* 48 */ 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00,\ -/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\ -/* 64 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x4c,\ -/* 72 */ 0x4c, 0x02, 0x02, 0x00, 0x05, 0x05, 0x15, 0x15,\ -/* 80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\ -/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\ -/* 96 */ 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\ -/* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x00,\ -/* 112 */ 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00,\ -/* 120 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 128 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x02, 0x00, 0x01,\ -/* 136 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x01, 0x00, 0x00,\ -/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,\ -/* 152 */ 0x02, 0x01, 0x00, 0x00,} +/* 8 */ 0x01, 0x01, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,\ +/* 16 */ 0x01, 0x01, 0x02, 0x12, 0x01, 0x02, 0x03, 0x08,\ +/* 24 */ 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10,\ +/* 32 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x03, 0x02,\ +/* 40 */ 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x00,\ +/* 48 */ 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,\ +/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09,\ +/* 64 */ 0x09, 0x09, 0x04, 0x09, 0x09, 0x09, 0x09, 0x26,\ +/* 72 */ 0x26, 0x10, 0x10, 0x00, 0x03, 0x03, 0x0b, 0x0b,\ +/* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x26, 0x26, 0x26,\ +/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\ +/* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ +/* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x00,\ +/* 112 */ 0x10, 0x01, 0x01, 0x01, 0x01, 0x10, 0x00, 0x00,\ +/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 128 */ 0x06, 0x23, 0x0b, 0x01, 0x10, 0x10, 0x00, 0x01,\ +/* 136 */ 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x01,\ +/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\ +/* 152 */ 0x00, 0x10, 0x10, 0x01, 0x00, 0x00,} /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -9824,6 +10030,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); @@ -10841,11 +11048,13 @@ struct sqlite3 { u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ + u8 imposterTable; /* Building an imposter table */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ int nVdbeWrite; /* Number of active VDBEs that read and write */ int nVdbeExec; /* Number of nested calls to VdbeExec() */ + int nVDestroy; /* Number of active OP_VDestroy operations */ int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ void (*xTrace)(void*,const char*); /* Trace function */ @@ -10959,6 +11168,7 @@ struct sqlite3 { #define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ #define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ #define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ +#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */ /* @@ -11289,34 +11499,8 @@ struct VTable { }; /* -** Each SQL table is represented in memory by an instance of the -** following structure. -** -** Table.zName is the name of the table. The case of the original -** CREATE TABLE statement is stored, but case is not significant for -** comparisons. -** -** Table.nCol is the number of columns in this table. Table.aCol is a -** pointer to an array of Column structures, one for each column. -** -** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of -** the column that is that key. Otherwise Table.iPKey is negative. Note -** that the datatype of the PRIMARY KEY must be INTEGER for this field to -** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of -** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid -** is generated for each row of the table. TF_HasPrimaryKey is set if -** the table has any PRIMARY KEY, INTEGER or otherwise. -** -** Table.tnum is the page number for the root BTree page of the table in the -** database file. If Table.iDb is the index of the database table backend -** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that -** holds temporary tables and indices. If TF_Ephemeral is set -** then the table is stored in a file that is automatically deleted -** when the VDBE cursor to the table is closed. In this case Table.tnum -** refers VDBE cursor number that holds the table open, not to the root -** page number. Transient tables are used to hold the results of a -** sub-query that appears instead of a real table name in the FROM clause -** of a SELECT statement. +** The schema for each SQL table and view is represented in memory +** by an instance of the following structure. */ struct Table { char *zName; /* Name of the table or view */ @@ -11328,11 +11512,11 @@ struct Table { #ifndef SQLITE_OMIT_CHECK ExprList *pCheck; /* All CHECK constraints */ #endif - LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ - int tnum; /* Root BTree node for this table (see note above) */ - i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ + int tnum; /* Root BTree page for this table */ + i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ + LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ #ifdef SQLITE_ENABLE_COSTMULT LogEst costMult; /* Cost multiplier for using this table */ @@ -11354,6 +11538,12 @@ struct Table { /* ** Allowed values for Table.tabFlags. +** +** TF_OOOHidden applies to virtual tables that have hidden columns that are +** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING +** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, +** the TF_OOOHidden attribute would apply in this case. Such tables require +** special handling during INSERT processing. */ #define TF_Readonly 0x01 /* Read-only system table */ #define TF_Ephemeral 0x02 /* An ephemeral table */ @@ -11361,6 +11551,7 @@ struct Table { #define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ #define TF_Virtual 0x10 /* Is a virtual table */ #define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */ +#define TF_OOOHidden 0x40 /* Out-of-Order hidden columns */ /* @@ -11797,8 +11988,14 @@ struct Expr { #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ -#define EP_Constant 0x080000 /* Node is a constant */ +#define EP_ConstFunc 0x080000 /* Node is a SQLITE_FUNC_CONSTANT function */ #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ +#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ + +/* +** Combinations of two or more EP_* flags +*/ +#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ /* ** These macros can be used to test, set, or clear bits in the @@ -11997,7 +12194,7 @@ struct SrcList { #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ #define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */ #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ - /* 0x0080 // not currently used */ +#define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */ #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */ #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */ #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */ @@ -12111,11 +12308,12 @@ struct Select { #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_Compound 0x0040 /* Part of a compound query */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ -#define SF_AllValues 0x0100 /* All terms of compound are VALUES */ +#define SF_MultiValue 0x0100 /* Single VALUES term with multiple rows */ #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ #define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */ #define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */ #define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */ +#define SF_Converted 0x2000 /* By convertCompoundSelectToSubquery() */ /* @@ -12434,7 +12632,8 @@ struct AuthContext { #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ -#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ +#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ +#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ /* @@ -12493,7 +12692,7 @@ struct Trigger { * orconf -> stores the ON CONFLICT algorithm * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then * this stores a pointer to the SELECT statement. Otherwise NULL. - * target -> A token holding the quoted name of the table to insert into. + * zTarget -> Dequoted name of the table to insert into. * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then * this stores values to be inserted. Otherwise NULL. * pIdList -> If this is an INSERT INTO ... () VALUES ... @@ -12501,12 +12700,12 @@ struct Trigger { * inserted into. * * (op == TK_DELETE) - * target -> A token holding the quoted name of the table to delete from. + * zTarget -> Dequoted name of the table to delete from. * pWhere -> The WHERE clause of the DELETE statement if one is specified. * Otherwise NULL. * * (op == TK_UPDATE) - * target -> A token holding the quoted name of the table to update rows of. + * zTarget -> Dequoted name of the table to update. * pWhere -> The WHERE clause of the UPDATE statement if one is specified. * Otherwise NULL. * pExprList -> A list of the columns to update and the expressions to update @@ -12518,8 +12717,8 @@ struct TriggerStep { u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ - Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */ - Token target; /* Target table for DELETE, UPDATE, INSERT */ + Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ + char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ ExprList *pExprList; /* SET clause for UPDATE. */ IdList *pIdList; /* Column names for INSERT */ @@ -12552,8 +12751,7 @@ struct StrAccum { char *zText; /* The string collected so far */ int nChar; /* Length of the string so far */ int nAlloc; /* Amount of space allocated in zText */ - int mxAlloc; /* Maximum allowed string length */ - u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */ + int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ }; #define STRACCUM_NOMEM 1 @@ -12838,10 +13036,15 @@ SQLITE_PRIVATE int sqlite3MutexInit(void); SQLITE_PRIVATE int sqlite3MutexEnd(void); #endif -SQLITE_PRIVATE int sqlite3StatusValue(int); -SQLITE_PRIVATE void sqlite3StatusAdd(int, int); +SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int); +SQLITE_PRIVATE void sqlite3StatusUp(int, int); +SQLITE_PRIVATE void sqlite3StatusDown(int, int); SQLITE_PRIVATE void sqlite3StatusSet(int, int); +/* Access to mutexes used by sqlite3_status() */ +SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); +SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void); + #ifndef SQLITE_OMIT_FLOATING_POINT SQLITE_PRIVATE int sqlite3IsNaN(double); #else @@ -12865,7 +13068,7 @@ SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...); SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...); -#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) @@ -12906,6 +13109,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); +SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); @@ -13211,7 +13415,7 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); -#if defined(SQLITE_TEST) +#if defined(SQLITE_NEED_ERR_NAME) SQLITE_PRIVATE const char *sqlite3ErrName(int); #endif @@ -13220,7 +13424,7 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*); +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); @@ -13305,7 +13509,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); -SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int); +SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char); @@ -13489,12 +13693,11 @@ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *); SQLITE_PRIVATE int sqlite3MemJournalSize(void); SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *); +SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); #if SQLITE_MAX_EXPR_DEPTH>0 -SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p); SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *); SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int); #else - #define sqlite3ExprSetHeight(x,y) #define sqlite3SelectExprHeight(x) 0 #define sqlite3ExprCheckHeight(x,y) #endif @@ -13524,7 +13727,7 @@ SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *); #ifdef SQLITE_ENABLE_IOTRACE # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); -void (*sqlite3IoTrace)(const char*,...); +SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...); #else # define IOTRACE(A) # define sqlite3VdbeIOTraceSql(X) @@ -13631,16 +13834,16 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */ - 96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */ - 112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */ + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */ + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */ - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */ + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */ 160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */ 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */ 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */ - 224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */ - 239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */ + 224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */ + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */ #endif }; @@ -14237,7 +14440,7 @@ static const char * const azCompileOpt[] = { ** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix ** is not required for a match. */ -SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ +SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){ int i, n; #if SQLITE_ENABLE_API_ARMOR @@ -14265,7 +14468,7 @@ SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ ** Return the N-th compile-time option string. If N is out of range, ** return a NULL pointer. */ -SQLITE_API const char *sqlite3_compileoption_get(int N){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N){ if( N>=0 && N4 + sqlite3_int64 nowValue[10]; /* Current value */ + sqlite3_int64 mxValue[10]; /* Maximum value */ +#else + u32 nowValue[10]; /* Current value */ + u32 mxValue[10]; /* Maximum value */ +#endif } sqlite3Stat = { {0,}, {0,} }; +/* +** Elements of sqlite3Stat[] are protected by either the memory allocator +** mutex, or by the pcache1 mutex. The following array determines which. +*/ +static const char statMutex[] = { + 0, /* SQLITE_STATUS_MEMORY_USED */ + 1, /* SQLITE_STATUS_PAGECACHE_USED */ + 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */ + 0, /* SQLITE_STATUS_SCRATCH_USED */ + 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */ + 0, /* SQLITE_STATUS_MALLOC_SIZE */ + 0, /* SQLITE_STATUS_PARSER_STACK */ + 1, /* SQLITE_STATUS_PAGECACHE_SIZE */ + 0, /* SQLITE_STATUS_SCRATCH_SIZE */ + 0, /* SQLITE_STATUS_MALLOC_COUNT */ +}; + /* The "wsdStat" macro will resolve to the status information ** state vector. If writable static data is unsupported on the target, @@ -14823,33 +15042,60 @@ static SQLITE_WSD struct sqlite3StatType { #endif /* -** Return the current value of a status parameter. +** Return the current value of a status parameter. The caller must +** be holding the appropriate mutex. */ -SQLITE_PRIVATE int sqlite3StatusValue(int op){ +SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int op){ wsdStatInit; assert( op>=0 && op=0 && op=0 && op=0 && opwsdStat.mxValue[op] ){ wsdStat.mxValue[op] = wsdStat.nowValue[op]; } } +SQLITE_PRIVATE void sqlite3StatusDown(int op, int N){ + wsdStatInit; + assert( N>=0 ); + assert( op>=0 && op=0 && op=0 && op=0 && opwsdStat.mxValue[op] ){ wsdStat.mxValue[op] = wsdStat.nowValue[op]; @@ -14858,12 +15104,14 @@ SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){ /* ** Query status information. -** -** This implementation assumes that reading or writing an aligned -** 32-bit integer is an atomic operation. If that assumption is not true, -** then this routine is not threadsafe. */ -SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ +SQLITE_API int SQLITE_STDCALL sqlite3_status64( + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag +){ + sqlite3_mutex *pMutex; wsdStatInit; if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ return SQLITE_MISUSE_BKPT; @@ -14871,18 +15119,35 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF #ifdef SQLITE_ENABLE_API_ARMOR if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; #endif + pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex(); + sqlite3_mutex_enter(pMutex); *pCurrent = wsdStat.nowValue[op]; *pHighwater = wsdStat.mxValue[op]; if( resetFlag ){ wsdStat.mxValue[op] = wsdStat.nowValue[op]; } + sqlite3_mutex_leave(pMutex); + (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */ return SQLITE_OK; } +SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ + sqlite3_int64 iCur, iHwtr; + int rc; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; +#endif + rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag); + if( rc==0 ){ + *pCurrent = (int)iCur; + *pHighwater = (int)iHwtr; + } + return rc; +} /* ** Query status information for a single database connection */ -SQLITE_API int sqlite3_db_status( +SQLITE_API int SQLITE_STDCALL sqlite3_db_status( sqlite3 *db, /* The database connection whose status is desired */ int op, /* Status verb */ int *pCurrent, /* Write current value here */ @@ -16506,7 +16771,7 @@ static sqlite3_vfs * SQLITE_WSD vfsList = 0; ** Locate a VFS by name. If no name is given, simply return the ** first VFS on the list. */ -SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ +SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfs){ sqlite3_vfs *pVfs = 0; #if SQLITE_THREADSAFE sqlite3_mutex *mutex; @@ -16552,7 +16817,7 @@ static void vfsUnlink(sqlite3_vfs *pVfs){ ** VFS multiple times. The new VFS becomes the default if makeDflt is ** true. */ -SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ MUTEX_LOGIC(sqlite3_mutex *mutex;) #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -16580,7 +16845,7 @@ SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ /* ** Unregister a VFS so that it is no longer accessible. */ -SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -18916,7 +19181,7 @@ SQLITE_PRIVATE int sqlite3MutexEnd(void){ /* ** Retrieve a pointer to a static mutex or allocate a new dynamic one. */ -SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){ +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int id){ #ifndef SQLITE_OMIT_AUTOINIT if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0; @@ -18935,7 +19200,7 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){ /* ** Free a dynamic mutex. */ -SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){ +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){ if( p ){ sqlite3GlobalConfig.mutex.xMutexFree(p); } @@ -18945,7 +19210,7 @@ SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){ ** Obtain the mutex p. If some other thread already has the mutex, block ** until it can be obtained. */ -SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){ +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){ if( p ){ sqlite3GlobalConfig.mutex.xMutexEnter(p); } @@ -18955,7 +19220,7 @@ SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){ ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. */ -SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){ +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){ int rc = SQLITE_OK; if( p ){ return sqlite3GlobalConfig.mutex.xMutexTry(p); @@ -18969,7 +19234,7 @@ SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){ ** is not currently entered. If a NULL pointer is passed as an argument ** this function is a no-op. */ -SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){ +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){ if( p ){ sqlite3GlobalConfig.mutex.xMutexLeave(p); } @@ -18980,10 +19245,10 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){ ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. */ -SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){ +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex *p){ return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); } -SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex *p){ return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); } #endif @@ -19113,8 +19378,12 @@ static sqlite3_mutex *debugMutexAlloc(int id){ break; } default: { - assert( id-2 >= 0 ); - assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) ); +#ifdef SQLITE_ENABLE_API_ARMOR + if( id-2<0 || id-2>=ArraySize(aStatic) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif pNew = &aStatic[id-2]; pNew->id = id; break; @@ -19129,8 +19398,13 @@ static sqlite3_mutex *debugMutexAlloc(int id){ static void debugMutexFree(sqlite3_mutex *pX){ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; assert( p->cnt==0 ); - assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); - sqlite3_free(p); + if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){ + sqlite3_free(p); + }else{ +#ifdef SQLITE_ENABLE_API_ARMOR + (void)SQLITE_MISUSE_BKPT; +#endif + } } /* @@ -19241,8 +19515,10 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ */ struct sqlite3_mutex { pthread_mutex_t mutex; /* Mutex controlling the lock */ -#if SQLITE_MUTEX_NREF +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) int id; /* Mutex type */ +#endif +#if SQLITE_MUTEX_NREF volatile int nRef; /* Number of entrances */ volatile pthread_t owner; /* Thread that is within this mutex */ int trace; /* True to trace changes */ @@ -19358,9 +19634,6 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&p->mutex, &recursiveAttr); pthread_mutexattr_destroy(&recursiveAttr); -#endif -#if SQLITE_MUTEX_NREF - p->id = iType; #endif } break; @@ -19368,9 +19641,6 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ case SQLITE_MUTEX_FAST: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ -#if SQLITE_MUTEX_NREF - p->id = iType; -#endif pthread_mutex_init(&p->mutex, 0); } break; @@ -19383,12 +19653,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ } #endif p = &staticMutexes[iType-2]; -#if SQLITE_MUTEX_NREF - p->id = iType; -#endif break; } } +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) + if( p ) p->id = iType; +#endif return p; } @@ -19400,9 +19670,18 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ */ static void pthreadMutexFree(sqlite3_mutex *p){ assert( p->nRef==0 ); - assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); - pthread_mutex_destroy(&p->mutex); - sqlite3_free(p); +#if SQLITE_ENABLE_API_ARMOR + if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) +#endif + { + pthread_mutex_destroy(&p->mutex); + sqlite3_free(p); + } +#ifdef SQLITE_ENABLE_API_ARMOR + else{ + (void)SQLITE_MISUSE_BKPT; + } +#endif } /* @@ -19614,16 +19893,6 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) -# ifndef SQLITE_DEBUG_OS_TRACE -# define SQLITE_DEBUG_OS_TRACE 0 -# endif - int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; -# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X -#else -# define OSTRACE(X) -#endif - /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. @@ -19872,6 +20141,17 @@ SQLITE_API int sqlite3_open_file_count = 0; # define SQLITE_WIN32_VOLATILE volatile #endif +/* +** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() +** functions are not available (e.g. those not using MSVC, Cygwin, etc). +*/ +#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ + SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) +# define SQLITE_OS_WIN_THREADS 1 +#else +# define SQLITE_OS_WIN_THREADS 0 +#endif + #endif /* _OS_WIN_H_ */ /************** End of os_win.h **********************************************/ @@ -19954,8 +20234,8 @@ static int winMutex_isNt = -1; /* <0 means "need to query" */ */ static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; -SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */ -SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ +SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void); /* os_win.c */ +SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ static int winMutexInit(void){ /* The first to increment to 1 does actual initialization */ @@ -20047,8 +20327,8 @@ static sqlite3_mutex *winMutexAlloc(int iType){ case SQLITE_MUTEX_RECURSIVE: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ -#ifdef SQLITE_DEBUG p->id = iType; +#ifdef SQLITE_DEBUG #ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC p->trace = 1; #endif @@ -20068,12 +20348,9 @@ static sqlite3_mutex *winMutexAlloc(int iType){ return 0; } #endif - assert( iType-2 >= 0 ); - assert( iType-2 < ArraySize(winMutex_staticMutexes) ); - assert( winMutex_isInit==1 ); p = &winMutex_staticMutexes[iType-2]; -#ifdef SQLITE_DEBUG p->id = iType; +#ifdef SQLITE_DEBUG #ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC p->trace = 1; #endif @@ -20092,13 +20369,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){ */ static void winMutexFree(sqlite3_mutex *p){ assert( p ); -#ifdef SQLITE_DEBUG assert( p->nRef==0 && p->owner==0 ); - assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){ + DeleteCriticalSection(&p->mutex); + sqlite3_free(p); + }else{ +#ifdef SQLITE_ENABLE_API_ARMOR + (void)SQLITE_MISUSE_BKPT; #endif - assert( winMutex_isInit==1 ); - DeleteCriticalSection(&p->mutex); - sqlite3_free(p); + } } /* @@ -20252,7 +20531,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** held by SQLite. An example of non-essential memory is memory used to ** cache database pages that are not currently in use. */ -SQLITE_API int sqlite3_release_memory(int n){ +SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT return sqlite3PcacheReleaseMemory(n); #else @@ -20307,6 +20586,13 @@ static SQLITE_WSD struct Mem0Global { #define mem0 GLOBAL(struct Mem0Global, mem0) +/* +** Return the memory allocator mutex. sqlite3_status() needs it. +*/ +SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){ + return mem0.mutex; +} + /* ** This routine runs when the memory allocator sees that the ** total memory allocation is about to exceed the soft heap @@ -20329,7 +20615,7 @@ static int sqlite3MemoryAlarm( void *pArg, sqlite3_int64 iThreshold ){ - int nUsed; + sqlite3_int64 nUsed; sqlite3_mutex_enter(mem0.mutex); mem0.alarmCallback = xCallback; mem0.alarmArg = pArg; @@ -20345,7 +20631,7 @@ static int sqlite3MemoryAlarm( ** Deprecated external interface. Internal/core SQLite code ** should call sqlite3MemoryAlarm. */ -SQLITE_API int sqlite3_memory_alarm( +SQLITE_API int SQLITE_STDCALL sqlite3_memory_alarm( void(*xCallback)(void *pArg, sqlite3_int64 used,int N), void *pArg, sqlite3_int64 iThreshold @@ -20358,7 +20644,7 @@ SQLITE_API int sqlite3_memory_alarm( ** Set the soft heap-size limit for the library. Passing a zero or ** negative value indicates no limit. */ -SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 n){ sqlite3_int64 priorLimit; sqlite3_int64 excess; #ifndef SQLITE_OMIT_AUTOINIT @@ -20378,7 +20664,7 @@ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); return priorLimit; } -SQLITE_API void sqlite3_soft_heap_limit(int n){ +SQLITE_API void SQLITE_STDCALL sqlite3_soft_heap_limit(int n){ if( n<0 ) n = 0; sqlite3_soft_heap_limit64(n); } @@ -20387,6 +20673,7 @@ SQLITE_API void sqlite3_soft_heap_limit(int n){ ** Initialize the memory allocation subsystem. */ SQLITE_PRIVATE int sqlite3MallocInit(void){ + int rc; if( sqlite3GlobalConfig.m.xMalloc==0 ){ sqlite3MemSetDefault(); } @@ -20422,7 +20709,9 @@ SQLITE_PRIVATE int sqlite3MallocInit(void){ sqlite3GlobalConfig.szPage = 0; sqlite3GlobalConfig.nPage = 0; } - return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); + rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); + if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0)); + return rc; } /* @@ -20447,7 +20736,7 @@ SQLITE_PRIVATE void sqlite3MallocEnd(void){ /* ** Return the amount of memory currently checked out. */ -SQLITE_API sqlite3_int64 sqlite3_memory_used(void){ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){ int n, mx; sqlite3_int64 res; sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0); @@ -20460,7 +20749,7 @@ SQLITE_API sqlite3_int64 sqlite3_memory_used(void){ ** checked out since either the beginning of this process ** or since the most recent reset. */ -SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag){ int n, mx; sqlite3_int64 res; sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag); @@ -20498,7 +20787,7 @@ static int mallocWithAlarm(int n, void **pp){ nFull = sqlite3GlobalConfig.m.xRoundup(n); sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n); if( mem0.alarmCallback!=0 ){ - int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); if( nUsed >= mem0.alarmThreshold - nFull ){ mem0.nearlyFull = 1; sqlite3MallocAlarm(nFull); @@ -20515,8 +20804,8 @@ static int mallocWithAlarm(int n, void **pp){ #endif if( p ){ nFull = sqlite3MallocSize(p); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull); - sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1); + sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull); + sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); } *pp = p; return nFull; @@ -20551,13 +20840,13 @@ SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ ** First make sure the memory subsystem is initialized, then do the ** allocation. */ -SQLITE_API void *sqlite3_malloc(int n){ +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif return n<=0 ? 0 : sqlite3Malloc(n); } -SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){ +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64 n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif @@ -20593,14 +20882,14 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){ p = mem0.pScratchFree; mem0.pScratchFree = mem0.pScratchFree->pNext; mem0.nScratchFree--; - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); + sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1); sqlite3_mutex_leave(mem0.mutex); }else{ sqlite3_mutex_leave(mem0.mutex); p = sqlite3Malloc(n); if( sqlite3GlobalConfig.bMemstat && p ){ sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); + sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); sqlite3_mutex_leave(mem0.mutex); } sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); @@ -20641,19 +20930,19 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){ mem0.pScratchFree = pSlot; mem0.nScratchFree++; assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch ); - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1); + sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1); sqlite3_mutex_leave(mem0.mutex); }else{ /* Release memory back to the heap */ assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) ); - assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); if( sqlite3GlobalConfig.bMemstat ){ int iSize = sqlite3MallocSize(p); sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize); - sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); + sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize); + sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize); + sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); sqlite3GlobalConfig.m.xFree(p); sqlite3_mutex_leave(mem0.mutex); }else{ @@ -20684,7 +20973,7 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){ } SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ if( db==0 ){ - assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); return sqlite3MallocSize(p); }else{ @@ -20693,13 +20982,13 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ return db->lookaside.sz; }else{ assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); return sqlite3GlobalConfig.m.xSize(p); } } } -SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){ - assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) ); +SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void *p){ + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p); } @@ -20707,14 +20996,14 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){ /* ** Free memory previously obtained from sqlite3Malloc(). */ -SQLITE_API void sqlite3_free(void *p){ +SQLITE_API void SQLITE_STDCALL sqlite3_free(void *p){ if( p==0 ) return; /* IMP: R-49053-54554 */ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p)); - sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); + sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p)); + sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); sqlite3GlobalConfig.m.xFree(p); sqlite3_mutex_leave(mem0.mutex); }else{ @@ -20755,7 +21044,7 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){ } } assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); sqlite3_free(p); @@ -20768,7 +21057,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ int nOld, nNew, nDiff; void *pNew; assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) ); - assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) ); if( pOld==0 ){ return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */ } @@ -20802,7 +21091,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ } if( pNew ){ nNew = sqlite3MallocSize(pNew); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld); + sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld); } sqlite3_mutex_leave(mem0.mutex); }else{ @@ -20816,14 +21105,14 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ ** The public interface to sqlite3Realloc. Make sure that the memory ** subsystem is initialized prior to invoking sqliteRealloc. */ -SQLITE_API void *sqlite3_realloc(void *pOld, int n){ +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void *pOld, int n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif if( n<0 ) n = 0; /* IMP: R-26507-47431 */ return sqlite3Realloc(pOld, n); } -SQLITE_API void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif @@ -20935,7 +21224,7 @@ SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ } }else{ assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); pNew = sqlite3_realloc64(p, n); if( !pNew ){ @@ -21188,6 +21477,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ ** Set the StrAccum object to an error mode. */ static void setStrAccumError(StrAccum *p, u8 eError){ + assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); p->accError = eError; p->nAlloc = 0; } @@ -21262,13 +21552,6 @@ SQLITE_PRIVATE void sqlite3VXPrintf( PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ -#ifdef SQLITE_ENABLE_API_ARMOR - if( ap==0 ){ - (void)SQLITE_MISUSE_BKPT; - sqlite3StrAccumReset(pAccum); - return; - } -#endif bufpt = 0; if( bFlags ){ if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ @@ -21309,7 +21592,6 @@ SQLITE_PRIVATE void sqlite3VXPrintf( } }while( !done && (c=(*++fmt))!=0 ); /* Get the field width */ - width = 0; if( c=='*' ){ if( bArgList ){ width = (int)getIntArg(pArgList); @@ -21318,18 +21600,21 @@ SQLITE_PRIVATE void sqlite3VXPrintf( } if( width<0 ){ flag_leftjustify = 1; - width = -width; + width = width >= -2147483647 ? -width : 0; } c = *++fmt; }else{ + unsigned wx = 0; while( c>='0' && c<='9' ){ - width = width*10 + c - '0'; + wx = wx*10 + c - '0'; c = *++fmt; } + testcase( wx>0x7fffffff ); + width = wx & 0x7fffffff; } + /* Get the precision */ if( c=='.' ){ - precision = 0; c = *++fmt; if( c=='*' ){ if( bArgList ){ @@ -21337,13 +21622,18 @@ SQLITE_PRIVATE void sqlite3VXPrintf( }else{ precision = va_arg(ap,int); } - if( precision<0 ) precision = -precision; c = *++fmt; + if( precision<0 ){ + precision = precision >= -2147483647 ? -precision : -1; + } }else{ + unsigned px = 0; while( c>='0' && c<='9' ){ - precision = precision*10 + c - '0'; + px = px*10 + c - '0'; c = *++fmt; } + testcase( px>0x7fffffff ); + precision = px & 0x7fffffff; } }else{ precision = -1; @@ -21507,7 +21797,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf( else prefix = 0; } if( xtype==etGENERIC && precision>0 ) precision--; - for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){} + testcase( precision>0xfff ); + for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} if( xtype==etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; @@ -21562,8 +21853,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf( }else{ e2 = exp; } - if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){ - bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 ); + if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){ + bufpt = zExtra + = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); if( bufpt==0 ){ setStrAccumError(pAccum, STRACCUM_NOMEM); return; @@ -21795,13 +22087,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf( */ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ char *zNew; - assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */ + assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ if( p->accError ){ testcase(p->accError==STRACCUM_TOOBIG); testcase(p->accError==STRACCUM_NOMEM); return 0; } - if( !p->useMalloc ){ + if( p->mxAlloc==0 ){ N = p->nAlloc - p->nChar - 1; setStrAccumError(p, STRACCUM_TOOBIG); return N; @@ -21821,10 +22113,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ }else{ p->nAlloc = (int)szNew; } - if( p->useMalloc==1 ){ + if( p->db ){ zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); }else{ - zNew = sqlite3_realloc(zOld, p->nAlloc); + zNew = sqlite3_realloc64(zOld, p->nAlloc); } if( zNew ){ assert( p->zText!=0 || p->nChar==0 ); @@ -21844,7 +22136,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ ** Append N copies of character c to the given string buffer. */ SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ - if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return; + testcase( p->nChar + (i64)N > 0x7fffffff ); + if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ + return; + } while( (N--)>0 ) p->zText[p->nChar++] = c; } @@ -21869,7 +22164,7 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ ** size of the memory allocation for StrAccum if necessary. */ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ - assert( z!=0 ); + assert( z!=0 || N==0 ); assert( p->zText!=0 || p->nChar==0 || p->accError ); assert( N>=0 ); assert( p->accError==0 || p->nAlloc==0 ); @@ -21898,12 +22193,8 @@ SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ p->zText[p->nChar] = 0; - if( p->useMalloc && p->zText==p->zBase ){ - if( p->useMalloc==1 ){ - p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); - }else{ - p->zText = sqlite3_malloc(p->nChar+1); - } + if( p->mxAlloc>0 && p->zText==p->zBase ){ + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); }else{ @@ -21919,25 +22210,31 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ */ SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ if( p->zText!=p->zBase ){ - if( p->useMalloc==1 ){ - sqlite3DbFree(p->db, p->zText); - }else{ - sqlite3_free(p->zText); - } + sqlite3DbFree(p->db, p->zText); } p->zText = 0; } /* -** Initialize a string accumulator +** Initialize a string accumulator. +** +** p: The accumulator to be initialized. +** db: Pointer to a database connection. May be NULL. Lookaside +** memory is used if not NULL. db->mallocFailed is set appropriately +** when not NULL. +** zBase: An initial buffer. May be NULL in which case the initial buffer +** is malloced. +** n: Size of zBase in bytes. If total space requirements never exceed +** n then no memory allocations ever occur. +** mx: Maximum number of bytes to accumulate. If mx==0 then no memory +** allocations will ever occur. */ -SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){ +SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ p->zText = p->zBase = zBase; - p->db = 0; + p->db = db; p->nChar = 0; p->nAlloc = n; p->mxAlloc = mx; - p->useMalloc = 1; p->accError = 0; } @@ -21950,9 +22247,8 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; assert( db!=0 ); - sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), + sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); - acc.db = db; sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); z = sqlite3StrAccumFinish(&acc); if( acc.accError==STRACCUM_NOMEM ){ @@ -21996,7 +22292,7 @@ SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zForma ** Print into memory obtained from sqlite3_malloc(). Omit the internal ** %-conversion extensions. */ -SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ +SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap){ char *z; char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; @@ -22010,8 +22306,7 @@ SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif - sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); - acc.useMalloc = 2; + sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); sqlite3VXPrintf(&acc, 0, zFormat, ap); z = sqlite3StrAccumFinish(&acc); return z; @@ -22021,7 +22316,7 @@ SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ ** Print into memory obtained from sqlite3_malloc()(). Omit the internal ** %-conversion extensions. */ -SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){ +SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){ va_list ap; char *z; #ifndef SQLITE_OMIT_AUTOINIT @@ -22046,22 +22341,21 @@ SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){ ** ** sqlite3_vsnprintf() is the varargs version. */ -SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ +SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ StrAccum acc; if( n<=0 ) return zBuf; #ifdef SQLITE_ENABLE_API_ARMOR if( zBuf==0 || zFormat==0 ) { (void)SQLITE_MISUSE_BKPT; - if( zBuf && n>0 ) zBuf[0] = 0; + if( zBuf ) zBuf[0] = 0; return zBuf; } #endif - sqlite3StrAccumInit(&acc, zBuf, n, 0); - acc.useMalloc = 0; + sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); sqlite3VXPrintf(&acc, 0, zFormat, ap); return sqlite3StrAccumFinish(&acc); } -SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ +SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ char *z; va_list ap; va_start(ap,zFormat); @@ -22083,8 +22377,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ StrAccum acc; /* String accumulator */ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ - sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); - acc.useMalloc = 0; + sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); sqlite3VXPrintf(&acc, 0, zFormat, ap); sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, sqlite3StrAccumFinish(&acc)); @@ -22093,7 +22386,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ /* ** Format and write a message to the log if logging is enabled. */ -SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ +SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...){ va_list ap; /* Vararg list */ if( sqlite3GlobalConfig.xLog ){ va_start(ap, zFormat); @@ -22102,7 +22395,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ } } -#if defined(SQLITE_DEBUG) +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) /* ** A version of printf() that understands %lld. Used for debugging. ** The printf() built into some versions of windows does not understand %lld @@ -22112,8 +22405,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ va_list ap; StrAccum acc; char zBuf[500]; - sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); - acc.useMalloc = 0; + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); va_start(ap,zFormat); sqlite3VXPrintf(&acc, 0, zFormat, ap); va_end(ap); @@ -22140,7 +22432,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ ** is not the last item in the tree. */ SQLITE_PRIVATE TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ if( p==0 ){ - p = sqlite3_malloc( sizeof(*p) ); + p = sqlite3_malloc64( sizeof(*p) ); if( p==0 ) return 0; memset(p, 0, sizeof(*p)); }else{ @@ -22163,8 +22455,7 @@ SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ int i; StrAccum acc; char zBuf[500]; - sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); - acc.useMalloc = 0; + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); if( p ){ for(i=0; iiLevel && ibLine)-1; i++){ sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); @@ -22229,7 +22520,7 @@ static SQLITE_WSD struct sqlite3PrngType { /* ** Return N random bytes. */ -SQLITE_API void sqlite3_randomness(int N, void *pBuf){ +SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *pBuf){ unsigned char t; unsigned char *zBuf = pBuf; @@ -22435,7 +22726,7 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ /********************************* Win32 Threads ****************************/ -#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0 +#if SQLITE_OS_WIN_THREADS #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ #include @@ -22528,7 +22819,7 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; } -#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */ +#endif /* SQLITE_OS_WIN_THREADS */ /******************************** End Win32 Threads *************************/ @@ -23381,7 +23672,7 @@ SQLITE_PRIVATE int sqlite3Dequote(char *z){ ** case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ +SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *zLeft, const char *zRight){ register unsigned char *a, *b; if( zLeft==0 ){ return zRight ? -1 : 0; @@ -23393,7 +23684,7 @@ SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } return UpperToLower[*a] - UpperToLower[*b]; } -SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ +SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ register unsigned char *a, *b; if( zLeft==0 ){ return zRight ? -1 : 0; @@ -23787,6 +24078,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){ } } #endif + while( zNum[0]=='0' ) zNum++; for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){ v = v*10 + c; } @@ -24924,23 +25216,25 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 136 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), /* 137 */ "IfPos" OpHelp("if r[P1]>0 goto P2"), /* 138 */ "IfNeg" OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"), - /* 139 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"), - /* 140 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 141 */ "IncrVacuum" OpHelp(""), - /* 142 */ "Expire" OpHelp(""), - /* 143 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 144 */ "VBegin" OpHelp(""), - /* 145 */ "VCreate" OpHelp(""), - /* 146 */ "VDestroy" OpHelp(""), - /* 147 */ "VOpen" OpHelp(""), - /* 148 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 149 */ "VNext" OpHelp(""), - /* 150 */ "VRename" OpHelp(""), - /* 151 */ "Pagecount" OpHelp(""), - /* 152 */ "MaxPgcnt" OpHelp(""), - /* 153 */ "Init" OpHelp("Start at P2"), - /* 154 */ "Noop" OpHelp(""), - /* 155 */ "Explain" OpHelp(""), + /* 139 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]+=P3, goto P2"), + /* 140 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), + /* 141 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), + /* 142 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 143 */ "IncrVacuum" OpHelp(""), + /* 144 */ "Expire" OpHelp(""), + /* 145 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 146 */ "VBegin" OpHelp(""), + /* 147 */ "VCreate" OpHelp(""), + /* 148 */ "VDestroy" OpHelp(""), + /* 149 */ "VOpen" OpHelp(""), + /* 150 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 151 */ "VNext" OpHelp(""), + /* 152 */ "VRename" OpHelp(""), + /* 153 */ "Pagecount" OpHelp(""), + /* 154 */ "MaxPgcnt" OpHelp(""), + /* 155 */ "Init" OpHelp("Start at P2"), + /* 156 */ "Noop" OpHelp(""), + /* 157 */ "Explain" OpHelp(""), }; return azName[i]; } @@ -25020,18 +25314,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ # endif #endif -/* -** Define the OS_VXWORKS pre-processor macro to 1 if building on -** vxworks, or 0 otherwise. -*/ -#ifndef OS_VXWORKS -# if defined(__RTP__) || defined(_WRS_KERNEL) -# define OS_VXWORKS 1 -# else -# define OS_VXWORKS 0 -# endif -#endif - /* ** standard include files. */ @@ -25046,18 +25328,30 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ # include #endif -#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS +#if SQLITE_ENABLE_LOCKING_STYLE # include -# if OS_VXWORKS -# include -# include -# else -# include -# include -# endif +# include +# include #endif /* SQLITE_ENABLE_LOCKING_STYLE */ -#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS) +#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ + (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) +# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ + && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0)) +# define HAVE_GETHOSTUUID 1 +# else +# warning "gethostuuid() is disabled." +# endif +#endif + + +#if OS_VXWORKS +/* # include */ +# include +# include +#endif /* OS_VXWORKS */ + +#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE # include #endif @@ -25098,6 +25392,10 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ */ #define MAX_PATHNAME 512 +/* Always cast the getpid() return type for compatibility with +** kernel modules in VxWorks. */ +#define osGetpid(X) (pid_t)getpid() + /* ** Only set the lastErrno if the error code is a real error and not ** a normal expected return code of SQLITE_BUSY or SQLITE_OK @@ -25186,7 +25484,7 @@ struct unixFile { ** method was called. If xOpen() is called from a different process id, ** indicating that a fork() has occurred, the PRNG will be reset. */ -static int randomnessPid = 0; +static pid_t randomnessPid = 0; /* ** Allowed values for the unixFile.ctrlFlags bitmask: @@ -25203,7 +25501,8 @@ static int randomnessPid = 0; #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ -#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */ +#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings issued */ +#define UNIXFILE_BLOCK 0x0200 /* Next SHM lock might block */ /* ** Include code that is common to all os_*.c files @@ -25241,16 +25540,6 @@ static int randomnessPid = 0; # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) -# ifndef SQLITE_DEBUG_OS_TRACE -# define SQLITE_DEBUG_OS_TRACE 0 -# endif - int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; -# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X -#else -# define OSTRACE(X) -#endif - /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. @@ -25542,7 +25831,7 @@ static struct unix_syscall { { "read", (sqlite3_syscall_ptr)read, 0 }, #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent) -#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS) +#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE { "pread", (sqlite3_syscall_ptr)pread, 0 }, #else { "pread", (sqlite3_syscall_ptr)0, 0 }, @@ -25559,7 +25848,7 @@ static struct unix_syscall { { "write", (sqlite3_syscall_ptr)write, 0 }, #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent) -#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS) +#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 }, #else { "pwrite", (sqlite3_syscall_ptr)0, 0 }, @@ -25793,7 +26082,7 @@ static int unixMutexHeld(void) { #endif -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) +#ifdef SQLITE_HAVE_OS_TRACE /* ** Helper function for printing out trace information from debugging ** binaries. This returns the string representation of the supplied @@ -25874,9 +26163,9 @@ static int lockTrace(int fd, int op, struct flock *p){ /* ** Retry ftruncate() calls that fail due to EINTR ** -** All calls to ftruncate() within this file should be made through this wrapper. -** On the Android platform, bypassing the logic below could lead to a corrupt -** database. +** All calls to ftruncate() within this file should be made through +** this wrapper. On the Android platform, bypassing the logic below +** could lead to a corrupt database. */ static int robust_ftruncate(int h, sqlite3_int64 sz){ int rc; @@ -26056,7 +26345,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ assert( zAbsoluteName[0]=='/' ); n = (int)strlen(zAbsoluteName); - pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) ); + pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) ); if( pNew==0 ) return 0; pNew->zCanonicalName = (char*)&pNew[1]; memcpy(pNew->zCanonicalName, zAbsoluteName, n+1); @@ -26335,6 +26624,14 @@ static void robust_close(unixFile *pFile, int h, int lineno){ } } +/* +** Set the pFile->lastErrno. Do this in a subroutine as that provides +** a convenient place to set a breakpoint. +*/ +static void storeLastErrno(unixFile *pFile, int error){ + pFile->lastErrno = error; +} + /* ** Close all file descriptors accumuated in the unixInodeInfo->pUnused list. */ @@ -26408,7 +26705,7 @@ static int findInodeInfo( fd = pFile->h; rc = osFstat(fd, &statbuf); if( rc!=0 ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); #ifdef EOVERFLOW if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; #endif @@ -26429,12 +26726,12 @@ static int findInodeInfo( if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){ do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR ); if( rc!=1 ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return SQLITE_IOERR; } rc = osFstat(fd, &statbuf); if( rc!=0 ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return SQLITE_IOERR; } } @@ -26452,7 +26749,7 @@ static int findInodeInfo( pInode = pInode->pNext; } if( pInode==0 ){ - pInode = sqlite3_malloc( sizeof(*pInode) ); + pInode = sqlite3_malloc64( sizeof(*pInode) ); if( pInode==0 ){ return SQLITE_NOMEM; } @@ -26557,7 +26854,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ lock.l_type = F_WRLCK; if( osFcntl(pFile->h, F_GETLK, &lock) ){ rc = SQLITE_IOERR_CHECKRESERVEDLOCK; - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); } else if( lock.l_type!=F_UNLCK ){ reserved = 1; } @@ -26690,7 +26987,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){ assert( pFile ); OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, azFileLock(eFileLock), azFileLock(pFile->eFileLock), - azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid())); + azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared, + osGetpid(0))); /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the end_lock: exit path, as @@ -26757,7 +27055,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( rc!=SQLITE_BUSY ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_lock; } @@ -26792,7 +27090,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ if( rc ){ if( rc!=SQLITE_BUSY ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_lock; }else{ @@ -26825,7 +27123,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( rc!=SQLITE_BUSY ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } } } @@ -26898,7 +27196,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock, pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, - getpid())); + osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ @@ -26932,7 +27230,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ ** 4: [RRRR.] */ if( eFileLock==SHARED_LOCK ){ - #if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE (void)handleNFSUnlock; assert( handleNFSUnlock==0 ); @@ -26950,7 +27247,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_unlock; } @@ -26962,7 +27259,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_unlock; } @@ -26974,7 +27271,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_unlock; } @@ -26993,7 +27290,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ ** SQLITE_BUSY would confuse the upper layer (in practice it causes ** an assert to fail). */ rc = SQLITE_IOERR_RDLOCK; - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); goto end_unlock; } } @@ -27006,7 +27303,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ pInode->eFileLock = SHARED_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); goto end_unlock; } } @@ -27024,7 +27321,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ pInode->eFileLock = NO_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); pInode->eFileLock = NO_LOCK; pFile->eFileLock = NO_LOCK; } @@ -27299,7 +27596,7 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) { } else { rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } } return rc; @@ -27326,7 +27623,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock, - pFile->eFileLock, getpid())); + pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -27353,7 +27650,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { rc = SQLITE_IOERR_UNLOCK; } if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } return rc; } @@ -27389,10 +27686,9 @@ static int dotlockClose(sqlite3_file *id) { ** still works when you do this, but concurrency is reduced since ** only a single process can be reading the database at a time. ** -** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if -** compiling for VXWORKS. +** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off */ -#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS +#if SQLITE_ENABLE_LOCKING_STYLE /* ** Retry flock() calls that fail with EINTR @@ -27440,7 +27736,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ /* unlock failed with an error */ lrc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(lrc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); rc = lrc; } } @@ -27450,7 +27746,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ /* someone else might have it reserved */ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(lrc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); rc = lrc; } } @@ -27516,7 +27812,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) { /* didn't get, must be busy */ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } } else { /* got it, set the type and return ok */ @@ -27545,7 +27841,7 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock, - pFile->eFileLock, getpid())); + pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -27606,7 +27902,7 @@ static int flockClose(sqlite3_file *id) { ** to a non-zero value otherwise *pResOut is set to zero. The return value ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ -static int semCheckReservedLock(sqlite3_file *id, int *pResOut) { +static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) { int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; @@ -27628,7 +27924,7 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) { int tErrno = errno; if( EAGAIN != tErrno ){ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK); - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } else { /* someone else has the lock when we are in NO_LOCK */ reserved = (pFile->eFileLock < SHARED_LOCK); @@ -27673,7 +27969,7 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) { ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ -static int semLock(sqlite3_file *id, int eFileLock) { +static int semXLock(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; sem_t *pSem = pFile->pInode->pSem; int rc = SQLITE_OK; @@ -27706,14 +28002,14 @@ static int semLock(sqlite3_file *id, int eFileLock) { ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ -static int semUnlock(sqlite3_file *id, int eFileLock) { +static int semXUnlock(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; sem_t *pSem = pFile->pInode->pSem; assert( pFile ); assert( pSem ); OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock, - pFile->eFileLock, getpid())); + pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -27732,7 +28028,7 @@ static int semUnlock(sqlite3_file *id, int eFileLock) { int rc, tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } return rc; } @@ -27743,10 +28039,10 @@ static int semUnlock(sqlite3_file *id, int eFileLock) { /* ** Close a file. */ -static int semClose(sqlite3_file *id) { +static int semXClose(sqlite3_file *id) { if( id ){ unixFile *pFile = (unixFile*)id; - semUnlock(id, NO_LOCK); + semXUnlock(id, NO_LOCK); assert( pFile ); unixEnterMutex(); releaseInodeInfo(pFile); @@ -27834,7 +28130,7 @@ static int afpSetLock( setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); #endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */ if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } return rc; } else { @@ -27927,7 +28223,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ assert( pFile ); OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, azFileLock(eFileLock), azFileLock(pFile->eFileLock), - azFileLock(pInode->eFileLock), pInode->nShared , getpid())); + azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0))); /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as @@ -28017,7 +28313,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); if( IS_LOCK_ERROR(lrc1) ) { - pFile->lastErrno = lrc1Errno; + storeLastErrno(pFile, lrc1Errno); rc = lrc1; goto afp_end_lock; } else if( IS_LOCK_ERROR(lrc2) ){ @@ -28113,7 +28409,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, - getpid())); + osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ @@ -28304,9 +28600,9 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ SimulateIOError( newOffset-- ); if( newOffset!=offset ){ if( newOffset == -1 ){ - ((unixFile*)id)->lastErrno = errno; + storeLastErrno((unixFile*)id, errno); }else{ - ((unixFile*)id)->lastErrno = 0; + storeLastErrno((unixFile*)id, 0); } return -1; } @@ -28316,7 +28612,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ if( got<0 ){ if( errno==EINTR ){ got = 1; continue; } prior = 0; - ((unixFile*)id)->lastErrno = errno; + storeLastErrno((unixFile*)id, errno); break; }else if( got>0 ){ cnt -= got; @@ -28381,7 +28677,7 @@ static int unixRead( /* lastErrno set by seekAndRead */ return SQLITE_IOERR_READ; }else{ - pFile->lastErrno = 0; /* not a system error */ + storeLastErrno(pFile, 0); /* not a system error */ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[got], 0, amt-got); return SQLITE_IOERR_SHORT_READ; @@ -28410,9 +28706,9 @@ static int seekAndWriteFd( TIMER_START; #if defined(USE_PREAD) - do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); + do{ rc = (int)osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); #elif defined(USE_PREAD64) - do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); + do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); #else do{ i64 iSeek = lseek(fd, iOff, SEEK_SET); @@ -28522,7 +28818,7 @@ static int unixWrite( /* lastErrno set by seekAndWrite */ return SQLITE_IOERR_WRITE; }else{ - pFile->lastErrno = 0; /* not a system error */ + storeLastErrno(pFile, 0); /* not a system error */ return SQLITE_FULL; } } @@ -28731,7 +29027,7 @@ static int unixSync(sqlite3_file *id, int flags){ rc = full_fsync(pFile->h, isFullsync, isDataOnly); SimulateIOError( rc=1 ); if( rc ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); } @@ -28775,7 +29071,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){ rc = robust_ftruncate(pFile->h, nByte); if( rc ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); }else{ #ifdef SQLITE_DEBUG @@ -28815,7 +29111,7 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){ rc = osFstat(((unixFile*)id)->h, &buf); SimulateIOError( rc=1 ); if( rc!=0 ){ - ((unixFile*)id)->lastErrno = errno; + storeLastErrno((unixFile*)id, errno); return SQLITE_IOERR_FSTAT; } *pSize = buf.st_size; @@ -28851,7 +29147,9 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ i64 nSize; /* Required file size */ struct stat buf; /* Used to hold return values of fstat() */ - if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT; + if( osFstat(pFile->h, &buf) ){ + return SQLITE_IOERR_FSTAT; + } nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; if( nSize>(i64)buf.st_size ){ @@ -28898,7 +29196,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ int rc; if( pFile->szChunk<=0 ){ if( robust_ftruncate(pFile->h, nByte) ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); } } @@ -28936,11 +29234,15 @@ static int unixGetTempname(int nBuf, char *zBuf); static int unixFileControl(sqlite3_file *id, int op, void *pArg){ unixFile *pFile = (unixFile*)id; switch( op ){ + case SQLITE_FCNTL_WAL_BLOCK: { + /* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */ + return SQLITE_OK; + } case SQLITE_FCNTL_LOCKSTATE: { *(int*)pArg = pFile->eFileLock; return SQLITE_OK; } - case SQLITE_LAST_ERRNO: { + case SQLITE_FCNTL_LAST_ERRNO: { *(int*)pArg = pFile->lastErrno; return SQLITE_OK; } @@ -28968,7 +29270,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ return SQLITE_OK; } case SQLITE_FCNTL_TEMPFILENAME: { - char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname ); + char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname ); if( zTFile ){ unixGetTempname(pFile->pVfs->mxPathname, zTFile); *(char**)pArg = zTFile; @@ -29009,8 +29311,8 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ } #endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - case SQLITE_SET_LOCKPROXYFILE: - case SQLITE_GET_LOCKPROXYFILE: { + case SQLITE_FCNTL_SET_LOCKPROXYFILE: + case SQLITE_FCNTL_GET_LOCKPROXYFILE: { return proxyFileControl(id,op,pArg); } #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ @@ -29150,7 +29452,9 @@ static int unixDeviceCharacteristics(sqlite3_file *id){ ** Instead, it should be called via macro osGetpagesize(). */ static int unixGetpagesize(void){ -#if defined(_BSD_SOURCE) +#if OS_VXWORKS + return 1024; +#elif defined(_BSD_SOURCE) return getpagesize(); #else return (int)sysconf(_SC_PAGESIZE); @@ -29243,15 +29547,17 @@ struct unixShm { ** otherwise. */ static int unixShmSystemLock( - unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */ + unixFile *pFile, /* Open connection to the WAL file */ int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ int ofst, /* First byte of the locking range */ int n /* Number of bytes to lock */ ){ - struct flock f; /* The posix advisory locking structure */ - int rc = SQLITE_OK; /* Result code form fcntl() */ + unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */ + struct flock f; /* The posix advisory locking structure */ + int rc = SQLITE_OK; /* Result code form fcntl() */ /* Access to the unixShmNode object is serialized by the caller */ + pShmNode = pFile->pInode->pShmNode; assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 ); /* Shared locks never span more than one byte */ @@ -29261,6 +29567,7 @@ static int unixShmSystemLock( assert( n>=1 && nh>=0 ){ + int lkType; /* Initialize the locking parameters */ memset(&f, 0, sizeof(f)); f.l_type = lockType; @@ -29268,8 +29575,10 @@ static int unixShmSystemLock( f.l_start = ofst; f.l_len = n; - rc = osFcntl(pShmNode->h, F_SETLK, &f); + lkType = (pFile->ctrlFlags & UNIXFILE_BLOCK)!=0 ? F_SETLKW : F_SETLK; + rc = osFcntl(pShmNode->h, lkType, &f); rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; + pFile->ctrlFlags &= ~UNIXFILE_BLOCK; } /* Update the global lock state and do debug tracing */ @@ -29402,7 +29711,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ int nShmFilename; /* Size of the SHM filename in bytes */ /* Allocate space for the new unixShm object. */ - p = sqlite3_malloc( sizeof(*p) ); + p = sqlite3_malloc64( sizeof(*p) ); if( p==0 ) return SQLITE_NOMEM; memset(p, 0, sizeof(*p)); assert( pDbFd->pShm==0 ); @@ -29415,6 +29724,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ pShmNode = pInode->pShmNode; if( pShmNode==0 ){ struct stat sStat; /* fstat() info for database file */ +#ifndef SQLITE_SHM_DIRECTORY + const char *zBasePath = pDbFd->zPath; +#endif /* Call fstat() to figure out the permissions on the database file. If ** a new *-shm file is created, an attempt will be made to create it @@ -29428,9 +29740,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ #ifdef SQLITE_SHM_DIRECTORY nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31; #else - nShmFilename = 6 + (int)strlen(pDbFd->zPath); + nShmFilename = 6 + (int)strlen(zBasePath); #endif - pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename ); + pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); if( pShmNode==0 ){ rc = SQLITE_NOMEM; goto shm_open_err; @@ -29442,7 +29754,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x", (u32)sStat.st_ino, (u32)sStat.st_dev); #else - sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath); + sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath); sqlite3FileSuffix3(pDbFd->zPath, zShmFilename); #endif pShmNode->h = -1; @@ -29476,13 +29788,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ ** If not, truncate the file to zero length. */ rc = SQLITE_OK; - if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ + if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ if( robust_ftruncate(pShmNode->h, 0) ){ rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename); } } if( rc==SQLITE_OK ){ - rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1); + rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); } if( rc ) goto shm_open_err; } @@ -29640,7 +29952,7 @@ static int unixShmMap( goto shmpage_out; } }else{ - pMem = sqlite3_malloc(szRegion); + pMem = sqlite3_malloc64(szRegion); if( pMem==0 ){ rc = SQLITE_NOMEM; goto shmpage_out; @@ -29714,7 +30026,7 @@ static int unixShmLock( /* Unlock the system-level locks */ if( (mask & allMask)==0 ){ - rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); }else{ rc = SQLITE_OK; } @@ -29742,7 +30054,7 @@ static int unixShmLock( /* Get shared locks at the system level, if necessary */ if( rc==SQLITE_OK ){ if( (allShared & mask)==0 ){ - rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); }else{ rc = SQLITE_OK; } @@ -29767,7 +30079,7 @@ static int unixShmLock( ** also mark the local connection as being locked. */ if( rc==SQLITE_OK ){ - rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n); if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); p->exclMask |= mask; @@ -29776,7 +30088,7 @@ static int unixShmLock( } sqlite3_mutex_leave(pShmNode->mutex); OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", - p->id, getpid(), p->sharedMask, p->exclMask)); + p->id, osGetpid(0), p->sharedMask, p->exclMask)); return rc; } @@ -29835,7 +30147,9 @@ static int unixShmUnmap( assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); + if( deleteFlag && pShmNode->h>=0 ){ + osUnlink(pShmNode->zFilename); + } unixShmPurge(pDbFd); } unixLeaveMutex(); @@ -30112,7 +30426,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ ** * An I/O method finder function called FINDER that returns a pointer ** to the METHOD object in the previous bullet. */ -#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK, SHMMAP) \ +#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP) \ static const sqlite3_io_methods METHOD = { \ VERSION, /* iVersion */ \ CLOSE, /* xClose */ \ @@ -30177,7 +30491,7 @@ IOMETHODS( 0 /* xShmMap method */ ) -#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS +#if SQLITE_ENABLE_LOCKING_STYLE IOMETHODS( flockIoFinder, /* Finder function name */ flockIoMethods, /* sqlite3_io_methods object name */ @@ -30195,10 +30509,10 @@ IOMETHODS( semIoFinder, /* Finder function name */ semIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ - semClose, /* xClose method */ - semLock, /* xLock method */ - semUnlock, /* xUnlock method */ - semCheckReservedLock, /* xCheckReservedLock method */ + semXClose, /* xClose method */ + semXLock, /* xLock method */ + semXUnlock, /* xUnlock method */ + semXCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #endif @@ -30322,15 +30636,13 @@ static const sqlite3_io_methods #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ -#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE -/* -** This "finder" function attempts to determine the best locking strategy -** for the database file "filePath". It then returns the sqlite3_io_methods -** object that implements that strategy. -** -** This is for VXWorks only. +#if OS_VXWORKS +/* +** This "finder" function for VxWorks checks to see if posix advisory +** locking works. If it does, then that is what is used. If it does not +** work, then fallback to named semaphore locking. */ -static const sqlite3_io_methods *autolockIoFinderImpl( +static const sqlite3_io_methods *vxworksIoFinderImpl( const char *filePath, /* name of the database file */ unixFile *pNew /* the open file object */ ){ @@ -30356,9 +30668,9 @@ static const sqlite3_io_methods *autolockIoFinderImpl( } } static const sqlite3_io_methods - *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl; + *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl; -#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */ +#endif /* OS_VXWORKS */ /* ** An abstract type for a pointer to an IO method finder function: @@ -30477,7 +30789,7 @@ static int fillInUnixFile( ** the afpLockingContext. */ afpLockingContext *pCtx; - pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) ); + pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) ); if( pCtx==0 ){ rc = SQLITE_NOMEM; }else{ @@ -30507,7 +30819,7 @@ static int fillInUnixFile( int nFilename; assert( zFilename!=0 ); nFilename = (int)strlen(zFilename) + 6; - zLockFile = (char *)sqlite3_malloc(nFilename); + zLockFile = (char *)sqlite3_malloc64(nFilename); if( zLockFile==0 ){ rc = SQLITE_NOMEM; }else{ @@ -30540,7 +30852,7 @@ static int fillInUnixFile( } #endif - pNew->lastErrno = 0; + storeLastErrno(pNew, 0); #if OS_VXWORKS if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); @@ -30871,8 +31183,8 @@ static int unixOpen( ** the same instant might all reset the PRNG. But multiple resets ** are harmless. */ - if( randomnessPid!=getpid() ){ - randomnessPid = getpid(); + if( randomnessPid!=osGetpid(0) ){ + randomnessPid = osGetpid(0); sqlite3_randomness(0,0); } @@ -30884,7 +31196,7 @@ static int unixOpen( if( pUnused ){ fd = pUnused->fd; }else{ - pUnused = sqlite3_malloc(sizeof(*pUnused)); + pUnused = sqlite3_malloc64(sizeof(*pUnused)); if( !pUnused ){ return SQLITE_NOMEM; } @@ -30988,13 +31300,16 @@ static int unixOpen( #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE if( fstatfs(fd, &fsInfo) == -1 ){ - ((unixFile*)pFile)->lastErrno = errno; + storeLastErrno(p, errno); robust_close(p, fd, __LINE__); return SQLITE_IOERR_ACCESS; } if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; } + if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) { + ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; + } #endif /* Set up appropriate ctrlFlags */ @@ -31017,19 +31332,6 @@ static int unixOpen( if( envforce!=NULL ){ useProxy = atoi(envforce)>0; }else{ - if( statfs(zPath, &fsInfo) == -1 ){ - /* In theory, the close(fd) call is sub-optimal. If the file opened - ** with fd is a database file, and there are other connections open - ** on that file that are currently holding advisory locks on it, - ** then the call to close() will cancel those locks. In practice, - ** we're assuming that statfs() doesn't fail very often. At least - ** not while other file descriptors opened by the same process on - ** the same file are working. */ - p->lastErrno = errno; - robust_close(p, fd, __LINE__); - rc = SQLITE_IOERR_ACCESS; - goto open_finished; - } useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ @@ -31273,8 +31575,8 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ ** tests repeatable. */ memset(zBuf, 0, nBuf); - randomnessPid = getpid(); -#if !defined(SQLITE_TEST) + randomnessPid = osGetpid(0); +#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) { int fd, got; fd = robust_open("/dev/urandom", O_RDONLY, 0); @@ -31455,9 +31757,10 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ ** ** C APIs ** -** sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE, +** sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE, ** | ":auto:"); -** sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &); +** sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE, +** &); ** ** ** SQL pragmas @@ -31550,7 +31853,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ ** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will ** force proxy locking to be used for every database file opened, and 0 ** will force automatic proxy locking to be disabled for all database -** files (explicitly calling the SQLITE_SET_LOCKPROXYFILE pragma or +** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or ** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING). */ @@ -31571,6 +31874,7 @@ struct proxyLockingContext { char *lockProxyPath; /* Name of the proxy lock file */ char *dbPath; /* Name of the open file */ int conchHeld; /* 1 if the conch is held, -1 if lockless */ + int nFails; /* Number of conch taking failures */ void *oldLockingContext; /* Original lockingcontext to restore on close */ sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ }; @@ -31592,7 +31896,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ { if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n", - lPath, errno, getpid())); + lPath, errno, osGetpid(0))); return SQLITE_IOERR_LOCK; } len = strlcat(lPath, "sqliteplocks", maxLen); @@ -31614,7 +31918,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ } lPath[i+len]='\0'; strlcat(lPath, ":auto:", maxLen); - OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid())); + OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid(0))); return SQLITE_OK; } @@ -31641,7 +31945,7 @@ static int proxyCreateLockPath(const char *lockPath){ if( err!=EEXIST ) { OSTRACE(("CREATELOCKPATH FAILED creating %s, " "'%s' proxy lock path=%s pid=%d\n", - buf, strerror(err), lockPath, getpid())); + buf, strerror(err), lockPath, osGetpid(0))); return err; } } @@ -31650,7 +31954,7 @@ static int proxyCreateLockPath(const char *lockPath){ } buf[i] = lockPath[i]; } - OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid())); + OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid(0))); return 0; } @@ -31684,7 +31988,7 @@ static int proxyCreateUnixFile( if( pUnused ){ fd = pUnused->fd; }else{ - pUnused = sqlite3_malloc(sizeof(*pUnused)); + pUnused = sqlite3_malloc64(sizeof(*pUnused)); if( !pUnused ){ return SQLITE_NOMEM; } @@ -31717,7 +32021,7 @@ static int proxyCreateUnixFile( } } - pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew)); + pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew)); if( pNew==NULL ){ rc = SQLITE_NOMEM; goto end_create_proxy; @@ -31750,8 +32054,10 @@ SQLITE_API int sqlite3_hostid_num = 0; #define PROXY_HOSTIDLEN 16 /* conch file host id length */ +#ifdef HAVE_GETHOSTUUID /* Not always defined in the headers as it ought to be */ extern int gethostuuid(uuid_t id, const struct timespec *wait); +#endif /* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN ** bytes of writable memory. @@ -31759,10 +32065,9 @@ extern int gethostuuid(uuid_t id, const struct timespec *wait); static int proxyGetHostID(unsigned char *pHostID, int *pError){ assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); memset(pHostID, 0, PROXY_HOSTIDLEN); -#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\ - && __MAC_OS_X_VERSION_MIN_REQUIRED<1050 +#ifdef HAVE_GETHOSTUUID { - static const struct timespec timeout = {1, 0}; /* 1 sec timeout */ + struct timespec timeout = {1, 0}; /* 1 sec timeout */ if( gethostuuid(pHostID, &timeout) ){ int err = errno; if( pError ){ @@ -31877,7 +32182,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ */ struct stat buf; if( osFstat(conchFile->h, &buf) ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return SQLITE_IOERR_LOCK; } @@ -31897,7 +32202,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ char tBuf[PROXY_MAXCONCHLEN]; int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); if( len<0 ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return SQLITE_IOERR_LOCK; } if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ @@ -31917,7 +32222,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ if( 0==proxyBreakConchLock(pFile, myHostID) ){ rc = SQLITE_OK; if( lockType==EXCLUSIVE_LOCK ){ - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); } if( !rc ){ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); @@ -31955,11 +32260,12 @@ static int proxyTakeConch(unixFile *pFile){ int forceNewLockPath = 0; OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h, - (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid())); + (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), + osGetpid(0))); rc = proxyGetHostID(myHostID, &pError); if( (rc&0xff)==SQLITE_IOERR ){ - pFile->lastErrno = pError; + storeLastErrno(pFile, pError); goto end_takeconch; } rc = proxyConchLock(pFile, myHostID, SHARED_LOCK); @@ -31970,7 +32276,7 @@ static int proxyTakeConch(unixFile *pFile){ readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN); if( readLen<0 ){ /* I/O error: lastErrno set by seekAndRead */ - pFile->lastErrno = conchFile->lastErrno; + storeLastErrno(pFile, conchFile->lastErrno); rc = SQLITE_IOERR_READ; goto end_takeconch; }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || @@ -32043,7 +32349,7 @@ static int proxyTakeConch(unixFile *pFile){ rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); } }else{ - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); + rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); } if( rc==SQLITE_OK ){ char writeBuffer[PROXY_MAXCONCHLEN]; @@ -32052,7 +32358,8 @@ static int proxyTakeConch(unixFile *pFile){ writeBuffer[0] = (char)PROXY_CONCHVERSION; memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); if( pCtx->lockProxyPath!=NULL ){ - strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN); + strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, + MAXPATHLEN); }else{ strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); } @@ -32164,7 +32471,7 @@ static int proxyReleaseConch(unixFile *pFile){ conchFile = pCtx->conchFile; OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h, (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), - getpid())); + osGetpid(0))); if( pCtx->conchHeld>0 ){ rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); } @@ -32176,7 +32483,7 @@ static int proxyReleaseConch(unixFile *pFile){ /* ** Given the name of a database file, compute the name of its conch file. -** Store the conch filename in memory obtained from sqlite3_malloc(). +** Store the conch filename in memory obtained from sqlite3_malloc64(). ** Make *pConchPath point to the new name. Return SQLITE_OK on success ** or SQLITE_NOMEM if unable to obtain memory. ** @@ -32192,7 +32499,7 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){ /* Allocate space for the conch filename and initialize the name to ** the name of the original database file. */ - *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8); + *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8); if( conchPath==0 ){ return SQLITE_NOMEM; } @@ -32264,7 +32571,8 @@ static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){ /* afp style keeps a reference to the db path in the filePath field ** of the struct */ assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); - strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN); + strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, + MAXPATHLEN); } else #endif if( pFile->pMethod == &dotlockIoMethods ){ @@ -32305,9 +32613,9 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { } OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h, - (lockPath ? lockPath : ":auto:"), getpid())); + (lockPath ? lockPath : ":auto:"), osGetpid(0))); - pCtx = sqlite3_malloc( sizeof(*pCtx) ); + pCtx = sqlite3_malloc64( sizeof(*pCtx) ); if( pCtx==0 ){ return SQLITE_NOMEM; } @@ -32377,7 +32685,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { */ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ switch( op ){ - case SQLITE_GET_LOCKPROXYFILE: { + case SQLITE_FCNTL_GET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; if( pFile->pMethod == &proxyIoMethods ){ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; @@ -32392,13 +32700,16 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ } return SQLITE_OK; } - case SQLITE_SET_LOCKPROXYFILE: { + case SQLITE_FCNTL_SET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; int rc = SQLITE_OK; int isProxyStyle = (pFile->pMethod == &proxyIoMethods); if( pArg==NULL || (const char *)pArg==0 ){ if( isProxyStyle ){ - /* turn off proxy locking - not supported */ + /* turn off proxy locking - not supported. If support is added for + ** switching proxy locking mode off then it will need to fail if + ** the journal mode is WAL mode. + */ rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/; }else{ /* turn off proxy locking - already off - NOOP */ @@ -32589,7 +32900,7 @@ static int proxyClose(sqlite3_file *id) { ** necessarily been initialized when this routine is called, and so they ** should not be used. */ -SQLITE_API int sqlite3_os_init(void){ +SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ /* ** The following macro defines an initializer for an sqlite3_vfs object. ** The name of the VFS is NAME. The pAppData is a pointer to a pointer @@ -32643,8 +32954,10 @@ SQLITE_API int sqlite3_os_init(void){ ** array cannot be const. */ static sqlite3_vfs aVfs[] = { -#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__)) +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) UNIXVFS("unix", autolockIoFinder ), +#elif OS_VXWORKS + UNIXVFS("unix", vxworksIoFinder ), #else UNIXVFS("unix", posixIoFinder ), #endif @@ -32654,11 +32967,11 @@ SQLITE_API int sqlite3_os_init(void){ #if OS_VXWORKS UNIXVFS("unix-namedsem", semIoFinder ), #endif -#if SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS UNIXVFS("unix-posix", posixIoFinder ), -#if !OS_VXWORKS - UNIXVFS("unix-flock", flockIoFinder ), #endif +#if SQLITE_ENABLE_LOCKING_STYLE + UNIXVFS("unix-flock", flockIoFinder ), #endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) UNIXVFS("unix-afp", afpIoFinder ), @@ -32686,7 +32999,7 @@ SQLITE_API int sqlite3_os_init(void){ ** to release dynamically allocated objects. But not on unix. ** This routine is a no-op for unix. */ -SQLITE_API int sqlite3_os_end(void){ +SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ return SQLITE_OK; } @@ -32746,16 +33059,6 @@ SQLITE_API int sqlite3_os_end(void){ # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) -# ifndef SQLITE_DEBUG_OS_TRACE -# define SQLITE_DEBUG_OS_TRACE 0 -# endif - int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; -# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X -#else -# define OSTRACE(X) -#endif - /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. @@ -33099,8 +33402,10 @@ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif /* SQLITE_OS_WINRT */ /* -** This file mapping API is common to both Win32 and WinRT. +** These file mapping APIs are common to both Win32 and WinRT. */ + +WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T); WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); #endif /* SQLITE_WIN32_FILEMAPPING_API */ @@ -33968,6 +34273,32 @@ static struct win_syscall { SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) #endif /* defined(InterlockedCompareExchange) */ +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + { "UuidCreate", (SYSCALL)UuidCreate, 0 }, +#else + { "UuidCreate", (SYSCALL)0, 0 }, +#endif + +#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, +#else + { "UuidCreateSequential", (SYSCALL)0, 0 }, +#endif + +#define osUuidCreateSequential \ + ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) + +#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 + { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, +#else + { "FlushViewOfFile", (SYSCALL)0, 0 }, +#endif + +#define osFlushViewOfFile \ + ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) + }; /* End of the overrideable system calls */ /* @@ -34061,7 +34392,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){ ** "pnLargest" argument, if non-zero, will be used to return the size of the ** largest committed free block in the heap, in bytes. */ -SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){ +SQLITE_API int SQLITE_STDCALL sqlite3_win32_compact_heap(LPUINT pnLargest){ int rc = SQLITE_OK; UINT nLargest = 0; HANDLE hHeap; @@ -34101,7 +34432,7 @@ SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){ ** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will ** be returned and no changes will be made to the Win32 native heap. */ -SQLITE_API int sqlite3_win32_reset_heap(){ +SQLITE_API int SQLITE_STDCALL sqlite3_win32_reset_heap(){ int rc; MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ @@ -34146,7 +34477,7 @@ SQLITE_API int sqlite3_win32_reset_heap(){ ** (if available). */ -SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ +SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int nBuf){ char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ @@ -34186,7 +34517,7 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ static HANDLE sleepObj = NULL; #endif -SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){ +SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds){ #if SQLITE_OS_WINRT if ( sleepObj==NULL ){ sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, @@ -34235,7 +34566,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ ** This function determines if the machine is running a version of Windows ** based on the NT kernel. */ -SQLITE_API int sqlite3_win32_is_nt(void){ +SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void){ #if SQLITE_OS_WINRT /* ** NOTE: The WinRT sub-platform is always assumed to be based on the NT @@ -34589,7 +34920,7 @@ static char *winUnicodeToMbcs(LPCWSTR zWideFilename){ ** Convert multibyte character string to UTF-8. Space to hold the ** returned string is obtained from sqlite3_malloc(). */ -SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zFilename){ char *zFilenameUtf8; LPWSTR zTmpWide; @@ -34606,7 +34937,7 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ ** Convert UTF-8 to multibyte character string. Space to hold the ** returned string is obtained from sqlite3_malloc(). */ -SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){ +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zFilename){ char *zFilenameMbcs; LPWSTR zTmpWide; @@ -34626,7 +34957,7 @@ SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){ ** argument is the name of the directory to use. The return value will be ** SQLITE_OK if successful. */ -SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ +SQLITE_API int SQLITE_STDCALL sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ char **ppDirectory = 0; #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -34851,11 +35182,11 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){ /* ** Log a I/O error retry episode. */ -static void winLogIoerr(int nRetry){ +static void winLogIoerr(int nRetry, int lineno){ if( nRetry ){ - sqlite3_log(SQLITE_IOERR, - "delayed %dms for lock/sharing conflict", - winIoerrRetryDelay*nRetry*(nRetry+1)/2 + sqlite3_log(SQLITE_NOTICE, + "delayed %dms for lock/sharing conflict at line %d", + winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno ); } } @@ -35335,7 +35666,8 @@ static int winClose(sqlite3_file *id){ assert( pFile->pShm==0 ); #endif assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); - OSTRACE(("CLOSE file=%p\n", pFile->h)); + OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n", + osGetCurrentProcessId(), pFile, pFile->h)); #if SQLITE_MAX_MMAP_SIZE>0 winUnmapfile(pFile); @@ -35364,7 +35696,8 @@ static int winClose(sqlite3_file *id){ pFile->h = NULL; } OpenCounter(-1); - OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed")); + OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n", + osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed")); return rc ? SQLITE_OK : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), "winClose", pFile->zPath); @@ -35392,7 +35725,8 @@ static int winRead( assert( amt>0 ); assert( offset>=0 ); SimulateIOError(return SQLITE_IOERR_READ); - OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n", + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " + "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, pFile->h, pBuf, amt, offset, pFile->locktype)); #if SQLITE_MAX_MMAP_SIZE>0 @@ -35401,7 +35735,8 @@ static int winRead( if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); - OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; }else{ int nCopy = (int)(pFile->mmapSize - offset); @@ -35415,7 +35750,8 @@ static int winRead( #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) if( winSeekFile(pFile, offset) ){ - OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_FULL; } while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ @@ -35429,19 +35765,22 @@ static int winRead( DWORD lastErrno; if( winRetryIoerr(&nRetry, &lastErrno) ) continue; pFile->lastErrno = lastErrno; - OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h)); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n", + osGetCurrentProcessId(), pFile, pFile->h)); return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, "winRead", pFile->zPath); } - winLogIoerr(nRetry); + winLogIoerr(nRetry, __LINE__); if( nRead<(DWORD)amt ){ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[nRead], 0, amt-nRead); - OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h)); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_IOERR_SHORT_READ; } - OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; } @@ -35464,7 +35803,8 @@ static int winWrite( SimulateIOError(return SQLITE_IOERR_WRITE); SimulateDiskfullError(return SQLITE_FULL); - OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n", + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " + "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, pFile->h, pBuf, amt, offset, pFile->locktype)); #if SQLITE_MAX_MMAP_SIZE>0 @@ -35473,7 +35813,8 @@ static int winWrite( if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); - OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; }else{ int nCopy = (int)(pFile->mmapSize - offset); @@ -35536,17 +35877,20 @@ static int winWrite( if( rc ){ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) || ( pFile->lastErrno==ERROR_DISK_FULL )){ - OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h)); + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", + osGetCurrentProcessId(), pFile, pFile->h)); return winLogError(SQLITE_FULL, pFile->lastErrno, "winWrite1", pFile->zPath); } - OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h)); + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n", + osGetCurrentProcessId(), pFile, pFile->h)); return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, "winWrite2", pFile->zPath); }else{ - winLogIoerr(nRetry); + winLogIoerr(nRetry, __LINE__); } - OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; } @@ -35560,8 +35904,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ assert( pFile ); SimulateIOError(return SQLITE_IOERR_TRUNCATE); - OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n", - pFile->h, nByte, pFile->locktype)); + OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n", + osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype)); /* If the user has configured a chunk-size for this file, truncate the ** file so that it consists of an integer number of chunks (i.e. the @@ -35593,7 +35937,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ } #endif - OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); + OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n", + osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc))); return rc; } @@ -35617,7 +35962,7 @@ static int winSync(sqlite3_file *id, int flags){ BOOL rc; #endif #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \ - (defined(SQLITE_TEST) && defined(SQLITE_DEBUG)) + defined(SQLITE_HAVE_OS_TRACE) /* ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or ** OSTRACE() macros. @@ -35638,8 +35983,9 @@ static int winSync(sqlite3_file *id, int flags){ */ SimulateDiskfullError( return SQLITE_FULL ); - OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n", - pFile->h, flags, pFile->locktype)); + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n", + osGetCurrentProcessId(), pFile, pFile->h, flags, + pFile->locktype)); #ifndef SQLITE_TEST UNUSED_PARAMETER(flags); @@ -35654,19 +36000,38 @@ static int winSync(sqlite3_file *id, int flags){ ** no-op */ #ifdef SQLITE_NO_SYNC - OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; #else +#if SQLITE_MAX_MMAP_SIZE>0 + if( pFile->pMapRegion ){ + if( osFlushViewOfFile(pFile->pMapRegion, 0) ){ + OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " + "rc=SQLITE_OK\n", osGetCurrentProcessId(), + pFile, pFile->pMapRegion)); + }else{ + pFile->lastErrno = osGetLastError(); + OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " + "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), + pFile, pFile->pMapRegion)); + return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, + "winSync1", pFile->zPath); + } + } +#endif rc = osFlushFileBuffers(pFile->h); SimulateIOError( rc=FALSE ); if( rc ){ - OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; }else{ pFile->lastErrno = osGetLastError(); - OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h)); + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n", + osGetCurrentProcessId(), pFile, pFile->h)); return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, - "winSync", pFile->zPath); + "winSync2", pFile->zPath); } #endif } @@ -36274,7 +36639,7 @@ struct winShmNode { int nRef; /* Number of winShm objects pointing to this */ winShm *pFirst; /* All winShm objects pointing to this */ winShmNode *pNext; /* Next in list of all winShmNode objects */ -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) u8 nextShmId; /* Next available winShm.id value */ #endif }; @@ -36305,7 +36670,7 @@ struct winShm { u8 hasMutex; /* True if holding the winShmNode mutex */ u16 sharedMask; /* Mask of shared locks held */ u16 exclMask; /* Mask of exclusive locks held */ -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) u8 id; /* Id of this connection with its winShmNode */ #endif }; @@ -36496,7 +36861,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ /* Make the new connection a child of the winShmNode */ p->pShmNode = pShmNode; -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) p->id = pShmNode->nextShmId++; #endif pShmNode->nRef++; @@ -36716,16 +37081,16 @@ static int winShmMap( void volatile **pp /* OUT: Mapped memory */ ){ winFile *pDbFd = (winFile*)fd; - winShm *p = pDbFd->pShm; + winShm *pShm = pDbFd->pShm; winShmNode *pShmNode; int rc = SQLITE_OK; - if( !p ){ + if( !pShm ){ rc = winOpenSharedMemory(pDbFd); if( rc!=SQLITE_OK ) return rc; - p = pDbFd->pShm; + pShm = pDbFd->pShm; } - pShmNode = p->pShmNode; + pShmNode = pShm->pShmNode; sqlite3_mutex_enter(pShmNode->mutex); assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); @@ -36765,7 +37130,7 @@ static int winShmMap( } /* Map the requested memory region into this processes address space. */ - apNew = (struct ShmRegion *)sqlite3_realloc( + apNew = (struct ShmRegion *)sqlite3_realloc64( pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) ); if( !apNew ){ @@ -37637,7 +38002,7 @@ static int winOpen( } } #endif - winLogIoerr(cnt); + winLogIoerr(cnt, __LINE__); OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name, dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); @@ -37821,7 +38186,7 @@ static int winDelete( if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); }else{ - winLogIoerr(cnt); + winLogIoerr(cnt, __LINE__); } sqlite3_free(zConverted); OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc))); @@ -37871,7 +38236,7 @@ static int winAccess( attr = sAttrData.dwFileAttributes; } }else{ - winLogIoerr(cnt); + winLogIoerr(cnt, __LINE__); if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ sqlite3_free(zConverted); return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", @@ -38212,7 +38577,7 @@ static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ int n = 0; UNUSED_PARAMETER(pVfs); -#if defined(SQLITE_TEST) +#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) n = nBuf; memset(zBuf, 0, nBuf); #else @@ -38246,7 +38611,23 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ memcpy(&zBuf[n], &i, sizeof(i)); n += sizeof(i); } +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + if( sizeof(UUID)<=nBuf-n ){ + UUID id; + memset(&id, 0, sizeof(UUID)); + osUuidCreate(&id); + memcpy(zBuf, &id, sizeof(UUID)); + n += sizeof(UUID); + } + if( sizeof(UUID)<=nBuf-n ){ + UUID id; + memset(&id, 0, sizeof(UUID)); + osUuidCreateSequential(&id); + memcpy(zBuf, &id, sizeof(UUID)); + n += sizeof(UUID); + } #endif +#endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */ return n; } @@ -38370,7 +38751,7 @@ static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ /* ** Initialize and deinitialize the operating system interface. */ -SQLITE_API int sqlite3_os_init(void){ +SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ static sqlite3_vfs winVfs = { 3, /* iVersion */ sizeof(winFile), /* szOsFile */ @@ -38424,7 +38805,7 @@ SQLITE_API int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==77 ); + assert( ArraySize(aSyscall)==80 ); /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); @@ -38445,7 +38826,7 @@ SQLITE_API int sqlite3_os_init(void){ return SQLITE_OK; } -SQLITE_API int sqlite3_os_end(void){ +SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ #if SQLITE_OS_WINRT if( sleepObj!=NULL ){ osCloseHandle(sleepObj); @@ -38801,7 +39182,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ ** bits to act as the reference */ pBitvec = sqlite3BitvecCreate( sz ); pV = sqlite3MallocZero( (sz+7)/8 + 1 ); - pTmpSpace = sqlite3_malloc(BITVEC_SZ); + pTmpSpace = sqlite3_malloc64(BITVEC_SZ); if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; /* NULL pBitvec tests */ @@ -38983,12 +39364,20 @@ static void pcacheUnpin(PgHdr *p){ } /* -** Compute the number of pages of cache requested. +** Compute the number of pages of cache requested. p->szCache is the +** cache size requested by the "PRAGMA cache_size" statement. +** +** */ static int numberOfCachePages(PCache *p){ if( p->szCache>=0 ){ + /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the + ** suggested cache size is set to N. */ return p->szCache; }else{ + /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then + ** the number of cache pages is adjusted to use approximately abs(N*1024) + ** bytes of memory. */ return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); } } @@ -39728,7 +40117,6 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ static void *pcache1Alloc(int nByte){ void *p = 0; assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); - sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); if( nByte<=pcache1.szSlot ){ sqlite3_mutex_enter(pcache1.mutex); p = (PgHdr1 *)pcache1.pFree; @@ -39737,7 +40125,8 @@ static void *pcache1Alloc(int nByte){ pcache1.nFreeSlot--; pcache1.bUnderPressure = pcache1.nFreeSlot=0 ); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); + sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1); } sqlite3_mutex_leave(pcache1.mutex); } @@ -39750,7 +40139,8 @@ static void *pcache1Alloc(int nByte){ if( p ){ int sz = sqlite3MallocSize(p); sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); + sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); sqlite3_mutex_leave(pcache1.mutex); } #endif @@ -39768,7 +40158,7 @@ static int pcache1Free(void *p){ if( p>=pcache1.pStart && ppNext = pcache1.pFree; pcache1.pFree = pSlot; @@ -39782,7 +40172,7 @@ static int pcache1Free(void *p){ nFreed = sqlite3MallocSize(p); #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed); + sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); sqlite3_mutex_leave(pcache1.mutex); #endif sqlite3_free(p); @@ -40519,6 +40909,14 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){ */ SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } +/* +** Return the global mutex used by this PCACHE implementation. The +** sqlite3_status() routine needs access to this mutex. +*/ +SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void){ + return pcache1.mutex; +} + #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* ** This function is called to free superfluous dynamically allocated memory @@ -44273,9 +44671,7 @@ static int pagerWalFrames( ){ int rc; /* Return code */ int nList; /* Number of pages in pList */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES) PgHdr *p; /* For looping over pages */ -#endif assert( pPager->pWal ); assert( pList ); @@ -44292,7 +44688,6 @@ static int pagerWalFrames( ** any pages with page numbers greater than nTruncate into the WAL file. ** They will never be read by any client. So remove them from the pDirty ** list here. */ - PgHdr *p; PgHdr **ppNext = &pList; nList = 0; for(p=pList; (*ppNext = p)!=0; p=p->pDirty){ @@ -44312,7 +44707,6 @@ static int pagerWalFrames( pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags ); if( rc==SQLITE_OK && pPager->pBackup ){ - PgHdr *p; for(p=pList; p; p=p->pDirty){ sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); } @@ -48243,6 +48637,8 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ } assert( state==pPager->eState ); } + }else if( eMode==PAGER_JOURNALMODE_OFF ){ + sqlite3OsClose(pPager->jfd); } } @@ -49025,7 +49421,7 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ if( pWal->nWiData<=iPage ){ int nByte = sizeof(u32*)*(iPage+1); volatile u32 **apNew; - apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte); + apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte); if( !apNew ){ *ppPage = 0; return SQLITE_NOMEM; @@ -49291,9 +49687,10 @@ static void walUnlockShared(Wal *pWal, int lockIdx){ SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); } -static int walLockExclusive(Wal *pWal, int lockIdx, int n){ +static int walLockExclusive(Wal *pWal, int lockIdx, int n, int fBlock){ int rc; if( pWal->exclusiveMode ) return SQLITE_OK; + if( fBlock ) sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_WAL_BLOCK, 0); rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, @@ -49579,7 +49976,7 @@ static int walIndexRecover(Wal *pWal){ assert( pWal->writeLock ); iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; nLock = SQLITE_SHM_NLOCK - iLock; - rc = walLockExclusive(pWal, iLock, nLock); + rc = walLockExclusive(pWal, iLock, nLock, 0); if( rc ){ return rc; } @@ -49649,7 +50046,7 @@ static int walIndexRecover(Wal *pWal){ /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; - aFrame = (u8 *)sqlite3_malloc(szFrame); + aFrame = (u8 *)sqlite3_malloc64(szFrame); if( !aFrame ){ rc = SQLITE_NOMEM; goto recovery_error; @@ -50042,7 +50439,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc(nByte); + p = (WalIterator *)sqlite3_malloc64(nByte); if( !p ){ return SQLITE_NOMEM; } @@ -50052,7 +50449,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ /* Allocate temporary space used by the merge-sort routine. This block ** of memory will be freed before this function returns. */ - aTmp = (ht_slot *)sqlite3_malloc( + aTmp = (ht_slot *)sqlite3_malloc64( sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) ); if( !aTmp ){ @@ -50113,7 +50510,7 @@ static int walBusyLock( ){ int rc; do { - rc = walLockExclusive(pWal, lockIdx, n); + rc = walLockExclusive(pWal, lockIdx, n, 0); }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) ); return rc; } @@ -50197,7 +50594,7 @@ static int walCheckpoint( int sync_flags, /* Flags for OsSync() (or 0) */ u8 *zBuf /* Temporary buffer to use */ ){ - int rc; /* Return code */ + int rc = SQLITE_OK; /* Return code */ int szPage; /* Database page-size */ WalIterator *pIter = 0; /* Wal iterator context */ u32 iDbpage = 0; /* Next database page to write */ @@ -50211,104 +50608,115 @@ static int walCheckpoint( testcase( szPage<=32768 ); testcase( szPage>=65536 ); pInfo = walCkptInfo(pWal); - if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK; + if( pInfo->nBackfillhdr.mxFrame ){ - /* Allocate the iterator */ - rc = walIteratorInit(pWal, &pIter); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pIter ); - - /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked - ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ - assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); - - /* Compute in mxSafeFrame the index of the last frame of the WAL that is - ** safe to write into the database. Frames beyond mxSafeFrame might - ** overwrite database pages that are in use by active readers and thus - ** cannot be backfilled from the WAL. - */ - mxSafeFrame = pWal->hdr.mxFrame; - mxPage = pWal->hdr.nPage; - for(i=1; iaReadMark[i]; - if( mxSafeFrame>y ){ - assert( y<=pWal->hdr.mxFrame ); - rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); - if( rc==SQLITE_OK ){ - pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED); - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - }else if( rc==SQLITE_BUSY ){ - mxSafeFrame = y; - xBusy = 0; - }else{ - goto walcheckpoint_out; - } + /* Allocate the iterator */ + rc = walIteratorInit(pWal, &pIter); + if( rc!=SQLITE_OK ){ + return rc; } - } + assert( pIter ); - if( pInfo->nBackfillnBackfill; + /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked + ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); - /* Sync the WAL to disk */ - if( sync_flags ){ - rc = sqlite3OsSync(pWal->pWalFd, sync_flags); - } - - /* If the database may grow as a result of this checkpoint, hint - ** about the eventual size of the db file to the VFS layer. + /* Compute in mxSafeFrame the index of the last frame of the WAL that is + ** safe to write into the database. Frames beyond mxSafeFrame might + ** overwrite database pages that are in use by active readers and thus + ** cannot be backfilled from the WAL. */ - if( rc==SQLITE_OK ){ - i64 nReq = ((i64)mxPage * szPage); - rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); - if( rc==SQLITE_OK && nSizepDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); - } - } - - - /* Iterate through the contents of the WAL, copying data to the db file. */ - while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ - i64 iOffset; - assert( walFramePgno(pWal, iFrame)==iDbpage ); - if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue; - iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; - /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ - rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - iOffset = (iDbpage-1)*(i64)szPage; - testcase( IS_BIG_INT(iOffset) ); - rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - } - - /* If work was actually accomplished... */ - if( rc==SQLITE_OK ){ - if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ - i64 szDb = pWal->hdr.nPage*(i64)szPage; - testcase( IS_BIG_INT(szDb) ); - rc = sqlite3OsTruncate(pWal->pDbFd, szDb); - if( rc==SQLITE_OK && sync_flags ){ - rc = sqlite3OsSync(pWal->pDbFd, sync_flags); + mxSafeFrame = pWal->hdr.mxFrame; + mxPage = pWal->hdr.nPage; + for(i=1; iaReadMark[i]; + if( mxSafeFrame>y ){ + assert( y<=pWal->hdr.mxFrame ); + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); + if( rc==SQLITE_OK ){ + pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED); + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + }else if( rc==SQLITE_BUSY ){ + mxSafeFrame = y; + xBusy = 0; + }else{ + goto walcheckpoint_out; } } - if( rc==SQLITE_OK ){ - pInfo->nBackfill = mxSafeFrame; - } } - /* Release the reader lock held while backfilling */ - walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); - } + if( pInfo->nBackfillnBackfill; - if( rc==SQLITE_BUSY ){ - /* Reset the return code so as not to report a checkpoint failure - ** just because there are active readers. */ - rc = SQLITE_OK; + /* Sync the WAL to disk */ + if( sync_flags ){ + rc = sqlite3OsSync(pWal->pWalFd, sync_flags); + } + + /* If the database may grow as a result of this checkpoint, hint + ** about the eventual size of the db file to the VFS layer. + */ + if( rc==SQLITE_OK ){ + i64 nReq = ((i64)mxPage * szPage); + rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); + if( rc==SQLITE_OK && nSizepDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); + } + } + + + /* Iterate through the contents of the WAL, copying data to the db file */ + while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ + i64 iOffset; + assert( walFramePgno(pWal, iFrame)==iDbpage ); + if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ + continue; + } + iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; + /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ + rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); + if( rc!=SQLITE_OK ) break; + iOffset = (iDbpage-1)*(i64)szPage; + testcase( IS_BIG_INT(iOffset) ); + rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); + if( rc!=SQLITE_OK ) break; + } + + /* If work was actually accomplished... */ + if( rc==SQLITE_OK ){ + if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ + i64 szDb = pWal->hdr.nPage*(i64)szPage; + testcase( IS_BIG_INT(szDb) ); + rc = sqlite3OsTruncate(pWal->pDbFd, szDb); + if( rc==SQLITE_OK && sync_flags ){ + rc = sqlite3OsSync(pWal->pDbFd, sync_flags); + } + } + if( rc==SQLITE_OK ){ + pInfo->nBackfill = mxSafeFrame; + } + } + + /* Release the reader lock held while backfilling */ + walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); + } + + if( rc==SQLITE_BUSY ){ + /* Reset the return code so as not to report a checkpoint failure + ** just because there are active readers. */ + rc = SQLITE_OK; + } } /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the @@ -50323,7 +50731,7 @@ static int walCheckpoint( }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ u32 salt1; sqlite3_randomness(4, &salt1); - assert( mxSafeFrame==pWal->hdr.mxFrame ); + assert( pInfo->nBackfill==pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); if( rc==SQLITE_OK ){ if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ @@ -50543,7 +50951,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ walUnlockShared(pWal, WAL_WRITE_LOCK); rc = SQLITE_READONLY_RECOVERY; } - }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){ + }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 1)) ){ pWal->writeLock = 1; if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ badHdr = walIndexTryHdr(pWal, pChanged); @@ -50749,7 +51157,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ && (mxReadMarkhdr.mxFrame || mxI==0) ){ for(i=1; iaReadMark[i] = pWal->hdr.mxFrame; mxI = i; @@ -51005,7 +51413,7 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){ /* Only one writer allowed at a time. Get the write lock. Return ** SQLITE_BUSY if unable. */ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); + rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 0); if( rc ){ return rc; } @@ -51150,7 +51558,7 @@ static int walRestartLog(Wal *pWal){ if( pInfo->nBackfill>0 ){ u32 salt1; sqlite3_randomness(4, &salt1); - rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1, 0); if( rc==SQLITE_OK ){ /* If all readers are using WAL_READ_LOCK(0) (in other words if no ** readers are currently using the WAL), then the transactions @@ -51475,7 +51883,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive ** "checkpoint" lock on the database file. */ - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); + rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1, 0); if( rc ){ /* EVIDENCE-OF: R-10421-19736 If any other process is running a ** checkpoint operation at the same time, the lock cannot be obtained and @@ -51950,6 +52358,7 @@ struct MemPage { u8 hdrOffset; /* 100 for page 1. 0 otherwise */ u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ u8 max1bytePayload; /* min(maxLocal,127) */ + u8 bBusy; /* Prevent endless loops on corrupt database files */ u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ @@ -52088,6 +52497,9 @@ struct BtShared { #endif u8 inTransaction; /* Transaction state */ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ +#ifdef SQLITE_HAS_CODEC + u8 optimalReserve; /* Desired amount of reserved space per page */ +#endif u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ @@ -52474,6 +52886,7 @@ static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ ** Exit the recursive mutex on a Btree. */ SQLITE_PRIVATE void sqlite3BtreeLeave(Btree *p){ + assert( sqlite3_mutex_held(p->db->mutex) ); if( p->sharable ){ assert( p->wantToLock>0 ); p->wantToLock--; @@ -52721,7 +53134,7 @@ static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; ** The shared cache setting effects only future calls to ** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). */ -SQLITE_API int sqlite3_enable_shared_cache(int enable){ +SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int enable){ sqlite3GlobalConfig.sharedCacheEnabled = enable; return SQLITE_OK; } @@ -52810,6 +53223,12 @@ static int hasSharedCacheTableLock( for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ Index *pIdx = (Index *)sqliteHashData(p); if( pIdx->tnum==(int)iRoot ){ + if( iTab ){ + /* Two or more indexes share the same root page. There must + ** be imposter tables. So just return true. The assert is not + ** useful in that case. */ + return 1; + } iTab = pIdx->pTable->tnum; } } @@ -53229,10 +53648,15 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){ static int saveCursorPosition(BtCursor *pCur){ int rc; - assert( CURSOR_VALID==pCur->eState ); + assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState ); assert( 0==pCur->pKey ); assert( cursorHoldsMutex(pCur) ); + if( pCur->eState==CURSOR_SKIPNEXT ){ + pCur->eState = CURSOR_VALID; + }else{ + pCur->skipNext = 0; + } rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ @@ -53303,7 +53727,7 @@ static int SQLITE_NOINLINE saveCursorsOnList( ){ do{ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ - if( p->eState==CURSOR_VALID ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; @@ -53375,17 +53799,19 @@ static int btreeMoveto( */ static int btreeRestoreCursorPosition(BtCursor *pCur){ int rc; + int skipNext; assert( cursorHoldsMutex(pCur) ); assert( pCur->eState>=CURSOR_REQUIRESEEK ); if( pCur->eState==CURSOR_FAULT ){ return pCur->skipNext; } pCur->eState = CURSOR_INVALID; - rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext); + rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); + pCur->skipNext |= skipNext; if( pCur->skipNext && pCur->eState==CURSOR_VALID ){ pCur->eState = CURSOR_SKIPNEXT; } @@ -53437,9 +53863,10 @@ SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow) *pDifferentRow = 1; return rc; } - if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){ + if( pCur->eState!=CURSOR_VALID ){ *pDifferentRow = 1; }else{ + assert( pCur->skipNext==0 ); *pDifferentRow = 0; } return SQLITE_OK; @@ -54580,16 +55007,18 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( */ if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){ if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ + int nFilename = sqlite3Strlen30(zFilename)+1; int nFullPathname = pVfs->mxPathname+1; - char *zFullPathname = sqlite3Malloc(nFullPathname); + char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename)); MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) + p->sharable = 1; if( !zFullPathname ){ sqlite3_free(p); return SQLITE_NOMEM; } if( isMemdb ){ - memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1); + memcpy(zFullPathname, zFilename, nFilename); }else{ rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); @@ -54646,8 +55075,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( ** the right size. This is to guard against size changes that result ** when compiling on a different architecture. */ - assert( sizeof(i64)==8 || sizeof(i64)==4 ); - assert( sizeof(u64)==8 || sizeof(u64)==4 ); + assert( sizeof(i64)==8 ); + assert( sizeof(u64)==8 ); assert( sizeof(u32)==4 ); assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); @@ -55034,6 +55463,9 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, BtShared *pBt = p->pBt; assert( nReserve>=-1 && nReserve<=255 ); sqlite3BtreeEnter(p); +#if SQLITE_HAS_CODEC + if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve; +#endif if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ sqlite3BtreeLeave(p); return SQLITE_READONLY; @@ -55045,7 +55477,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); - assert( !pBt->pPage1 && !pBt->pCursor ); + assert( !pBt->pCursor ); pBt->pageSize = (u32)pageSize; freeTempSpace(pBt); } @@ -55063,7 +55495,6 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){ return p->pBt->pageSize; } -#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG) /* ** This function is similar to sqlite3BtreeGetReserve(), except that it ** may only be called if it is guaranteed that the b-tree mutex is already @@ -55076,25 +55507,33 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){ ** database handle that owns *p, causing undefined behavior. */ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ + int n; assert( sqlite3_mutex_held(p->pBt->mutex) ); - return p->pBt->pageSize - p->pBt->usableSize; + n = p->pBt->pageSize - p->pBt->usableSize; + return n; } -#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */ -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) /* ** Return the number of bytes of space at the end of every page that ** are intentually left unused. This is the "reserved" space that is ** sometimes used by extensions. +** +** If SQLITE_HAS_MUTEX is defined then the number returned is the +** greater of the current reserved space and the maximum requested +** reserve space. */ -SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree *p){ +SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree *p){ int n; sqlite3BtreeEnter(p); - n = p->pBt->pageSize - p->pBt->usableSize; + n = sqlite3BtreeGetReserveNoMutex(p); +#ifdef SQLITE_HAS_CODEC + if( npBt->optimalReserve ) n = p->pBt->optimalReserve; +#endif sqlite3BtreeLeave(p); return n; } + /* ** Set the maximum page count for a database if mxPage is positive. ** No changes are made if mxPage is 0 or negative. @@ -55125,7 +55564,6 @@ SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ sqlite3BtreeLeave(p); return b; } -#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ /* ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' @@ -56245,7 +56683,7 @@ SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int wr for(p=pBtree->pBt->pCursor; p; p=p->pNext){ int i; if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ - if( p->eState==CURSOR_VALID ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ rc = saveCursorPosition(p); if( rc!=SQLITE_OK ){ (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); @@ -56651,6 +57089,8 @@ SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>=0 ); + assert( pCur->iPageapPage[pCur->iPage]->intKeyLeaf==1 ); getCellInfo(pCur); *pSize = pCur->info.nPayload; @@ -57059,13 +57499,18 @@ static const void *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ u32 *pAmt /* Write the number of available bytes here */ ){ + u32 amt; assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorHoldsMutex(pCur) ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); assert( pCur->info.nSize>0 ); - *pAmt = pCur->info.nLocal; + assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB ); + assert( pCur->info.pPayloadapPage[pCur->iPage]->aDataEnd ||CORRUPT_DB); + amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload); + if( pCur->info.nLocalinfo.nLocal; + *pAmt = amt; return (void*)pCur->info.pPayload; } @@ -57129,7 +57574,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ return SQLITE_OK; } -#if 0 +#if SQLITE_DEBUG /* ** Page pParent is an internal (non-leaf) tree page. This function ** asserts that page number iChild is the left-child if the iIdx'th @@ -57138,6 +57583,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ ** the page. */ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){ + if( CORRUPT_DB ) return; /* The conditions tested below might not be true + ** in a corrupt database */ assert( iIdx<=pParent->nCell ); if( iIdx==pParent->nCell ){ assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild ); @@ -57162,19 +57609,11 @@ static void moveToParent(BtCursor *pCur){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>0 ); assert( pCur->apPage[pCur->iPage] ); - - /* UPDATE: It is actually possible for the condition tested by the assert - ** below to be untrue if the database file is corrupt. This can occur if - ** one cursor has modified page pParent while a reference to it is held - ** by a second cursor. Which can only happen if a single page is linked - ** into more than one b-tree structure in a corrupt database. */ -#if 0 assertParentIndex( pCur->apPage[pCur->iPage-1], pCur->aiIdx[pCur->iPage-1], pCur->apPage[pCur->iPage]->pgno ); -#endif testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); releasePage(pCur->apPage[pCur->iPage]); @@ -59349,7 +59788,6 @@ static int balance_nonroot( }else if( iParentIdx==i ){ nxDiv = i-2+bBulk; }else{ - assert( bBulk==0 ); nxDiv = iParentIdx-1; } i = 2-bBulk; @@ -60100,7 +60538,8 @@ static int balance(BtCursor *pCur){ ** pSpace buffer passed to the latter call to balance_nonroot(). */ u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); - rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints); + rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, + pCur->hints&BTREE_BULKLOAD); if( pFree ){ /* If pFree is not NULL, it points to the pSpace buffer used ** by a previous call to balance_nonroot(). Its contents are @@ -60121,6 +60560,7 @@ static int balance(BtCursor *pCur){ /* The next iteration of the do-loop balances the parent page. */ releasePage(pPage); pCur->iPage--; + assert( pCur->iPage>=0 ); } }while( rc==SQLITE_OK ); @@ -60597,9 +61037,13 @@ static int clearDatabasePage( if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } - rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; + if( pPage->bBusy ){ + rc = SQLITE_CORRUPT_BKPT; + goto cleardatabasepage_out; + } + pPage->bBusy = 1; hdr = pPage->hdrOffset; for(i=0; inCell; i++){ pCell = findCell(pPage, i); @@ -60624,6 +61068,7 @@ static int clearDatabasePage( } cleardatabasepage_out: + pPage->bBusy = 0; releasePage(pPage); return rc; } @@ -61131,6 +61576,57 @@ static void checkList( } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ +/* +** An implementation of a min-heap. +** +** aHeap[0] is the number of elements on the heap. aHeap[1] is the +** root element. The daughter nodes of aHeap[N] are aHeap[N*2] +** and aHeap[N*2+1]. +** +** The heap property is this: Every node is less than or equal to both +** of its daughter nodes. A consequence of the heap property is that the +** root node aHeap[1] is always the minimum value currently in the heap. +** +** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto +** the heap, preserving the heap property. The btreeHeapPull() routine +** removes the root element from the heap (the minimum value in the heap) +** and then moves other nodes around as necessary to preserve the heap +** property. +** +** This heap is used for cell overlap and coverage testing. Each u32 +** entry represents the span of a cell or freeblock on a btree page. +** The upper 16 bits are the index of the first byte of a range and the +** lower 16 bits are the index of the last byte of that range. +*/ +static void btreeHeapInsert(u32 *aHeap, u32 x){ + u32 j, i = ++aHeap[0]; + aHeap[i] = x; + while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){ + x = aHeap[j]; + aHeap[j] = aHeap[i]; + aHeap[i] = x; + i = j; + } +} +static int btreeHeapPull(u32 *aHeap, u32 *pOut){ + u32 j, i, x; + if( (x = aHeap[0])==0 ) return 0; + *pOut = aHeap[1]; + aHeap[1] = aHeap[x]; + aHeap[x] = 0xffffffff; + aHeap[0]--; + i = 1; + while( (j = i*2)<=aHeap[0] ){ + if( aHeap[j]>aHeap[j+1] ) j++; + if( aHeap[i]zPfx; @@ -61308,15 +61805,15 @@ static int checkTreePage( */ data = pPage->aData; hdr = pPage->hdrOffset; - hit = sqlite3PageMalloc( pBt->pageSize ); + heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); pCheck->zPfx = 0; - if( hit==0 ){ + if( heap==0 ){ pCheck->mallocFailed = 1; }else{ int contentOffset = get2byteNotZero(&data[hdr+5]); assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ - memset(hit+contentOffset, 0, usableSize-contentOffset); - memset(hit, 1, contentOffset); + heap[0] = 0; + btreeHeapInsert(heap, contentOffset-1); /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the ** number of cells on the page. */ nCell = get2byte(&data[hdr+3]); @@ -61328,7 +61825,6 @@ static int checkTreePage( for(i=0; i=pc; j--) hit[j]++; + btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); } } /* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header @@ -61349,7 +61845,7 @@ static int checkTreePage( assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */ size = get2byte(&data[i+2]); assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */ - for(j=i+size-1; j>=i; j--) hit[j]++; + btreeHeapInsert(heap, (i<<16)|(i+size-1)); /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a ** big-endian integer which is the offset in the b-tree page of the next ** freeblock in the chain, or zero if the freeblock is the last on the @@ -61361,27 +61857,33 @@ static int checkTreePage( assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */ i = j; } - for(i=cnt=0; i1 ){ + cnt = 0; + assert( heap[0]>0 ); + assert( (heap[1]>>16)==0 ); + btreeHeapPull(heap,&prev); + while( btreeHeapPull(heap,&x) ){ + if( (prev&0xffff)+1>(x>>16) ){ checkAppendMsg(pCheck, - "Multiple uses for byte %d of page %d", i, iPage); + "Multiple uses for byte %u of page %d", x>>16, iPage); break; + }else{ + cnt += (x>>16) - (prev&0xffff) - 1; + prev = x; } } + cnt += usableSize - (prev&0xffff) - 1; /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments ** is stored in the fifth field of the b-tree page header. ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the ** number of fragmented free bytes within the cell content area. */ - if( cnt!=data[hdr+7] ){ + if( heap[0]==0 && cnt!=data[hdr+7] ){ checkAppendMsg(pCheck, "Fragmentation of %d bytes reported as %d on page %d", cnt, data[hdr+7], iPage); } } - sqlite3PageFree(hit); + sqlite3PageFree(heap); releasePage(pPage); end_of_check: @@ -61445,8 +61947,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); - sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); - sCheck.errMsg.useMalloc = 2; + sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); /* Check the integrity of the freelist */ @@ -61763,14 +62264,23 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ } /* -** set the mask of hint flags for cursor pCsr. Currently the only valid -** values are 0 and BTREE_BULKLOAD. +** set the mask of hint flags for cursor pCsr. */ SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ - assert( mask==BTREE_BULKLOAD || mask==0 ); + assert( mask==BTREE_BULKLOAD || mask==BTREE_SEEK_EQ || mask==0 ); pCsr->hints = mask; } +#ifdef SQLITE_DEBUG +/* +** Return true if the cursor has a hint specified. This routine is +** only used from within assert() statements +*/ +SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){ + return (pCsr->hints & mask)!=0; +} +#endif + /* ** Return true if the given Btree is read-only. */ @@ -61929,7 +62439,7 @@ static int checkReadTransaction(sqlite3 *db, Btree *p){ ** If an error occurs, NULL is returned and an error code and error message ** stored in database handle pDestDb. */ -SQLITE_API sqlite3_backup *sqlite3_backup_init( +SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( sqlite3* pDestDb, /* Database to write to */ const char *zDestDb, /* Name of database within pDestDb */ sqlite3* pSrcDb, /* Database connection to read from */ @@ -62032,7 +62542,7 @@ static int backupOnePage( ** guaranteed that the shared-mutex is held by this thread, handle ** p->pSrc may not actually be the owner. */ int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); - int nDestReserve = sqlite3BtreeGetReserve(p->pDest); + int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest); #endif int rc = SQLITE_OK; i64 iOff; @@ -62137,7 +62647,7 @@ static void attachBackupObject(sqlite3_backup *p){ /* ** Copy nPage pages from the source b-tree to the destination. */ -SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ +SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ int rc; int destMode; /* Destination journal mode */ int pgszSrc = 0; /* Source page size */ @@ -62382,7 +62892,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ /* ** Release all resources associated with an sqlite3_backup* handle. */ -SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ +SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ sqlite3_backup **pp; /* Ptr to head of pagers backup list */ sqlite3 *pSrcDb; /* Source database connection */ int rc; /* Value to return */ @@ -62434,7 +62944,7 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ ** Return the number of pages still to be backed up as of the most recent ** call to sqlite3_backup_step(). */ -SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){ +SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){ #ifdef SQLITE_ENABLE_API_ARMOR if( p==0 ){ (void)SQLITE_MISUSE_BKPT; @@ -62448,7 +62958,7 @@ SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){ ** Return the total number of pages in the source database as of the most ** recent call to sqlite3_backup_step(). */ -SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){ +SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p){ #ifdef SQLITE_ENABLE_API_ARMOR if( p==0 ){ (void)SQLITE_MISUSE_BKPT; @@ -62773,10 +63283,11 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ pMem->z[pMem->n] = 0; pMem->z[pMem->n+1] = 0; pMem->flags |= MEM_Term; -#ifdef SQLITE_DEBUG - pMem->pScopyFrom = 0; -#endif } + pMem->flags &= ~MEM_Ephem; +#ifdef SQLITE_DEBUG + pMem->pScopyFrom = 0; +#endif return SQLITE_OK; } @@ -63663,7 +64174,7 @@ struct ValueNewStat4Ctx { ** Otherwise, if the second argument is non-zero, then this function is ** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not ** already been allocated, allocate the UnpackedRecord structure that -** that function will return to its caller here. Then return a pointer +** that function will return to its caller here. Then return a pointer to ** an sqlite3_value within the UnpackedRecord.a[] array. */ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ @@ -63707,6 +64218,113 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ return sqlite3ValueNew(db); } +/* +** The expression object indicated by the second argument is guaranteed +** to be a scalar SQL function. If +** +** * all function arguments are SQL literals, +** * the SQLITE_FUNC_CONSTANT function flag is set, and +** * the SQLITE_FUNC_NEEDCOLL function flag is not set, +** +** then this routine attempts to invoke the SQL function. Assuming no +** error occurs, output parameter (*ppVal) is set to point to a value +** object containing the result before returning SQLITE_OK. +** +** Affinity aff is applied to the result of the function before returning. +** If the result is a text value, the sqlite3_value object uses encoding +** enc. +** +** If the conditions above are not met, this function returns SQLITE_OK +** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to +** NULL and an SQLite error code returned. +*/ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static int valueFromFunction( + sqlite3 *db, /* The database connection */ + Expr *p, /* The expression to evaluate */ + u8 enc, /* Encoding to use */ + u8 aff, /* Affinity to use */ + sqlite3_value **ppVal, /* Write the new value here */ + struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */ +){ + sqlite3_context ctx; /* Context object for function invocation */ + sqlite3_value **apVal = 0; /* Function arguments */ + int nVal = 0; /* Size of apVal[] array */ + FuncDef *pFunc = 0; /* Function definition */ + sqlite3_value *pVal = 0; /* New value */ + int rc = SQLITE_OK; /* Return code */ + int nName; /* Size of function name in bytes */ + ExprList *pList = 0; /* Function arguments */ + int i; /* Iterator variable */ + + assert( pCtx!=0 ); + assert( (p->flags & EP_TokenOnly)==0 ); + pList = p->x.pList; + if( pList ) nVal = pList->nExpr; + nName = sqlite3Strlen30(p->u.zToken); + pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0); + assert( pFunc ); + if( (pFunc->funcFlags & SQLITE_FUNC_CONSTANT)==0 + || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) + ){ + return SQLITE_OK; + } + + if( pList ){ + apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal); + if( apVal==0 ){ + rc = SQLITE_NOMEM; + goto value_from_function_out; + } + for(i=0; ia[i].pExpr, enc, aff, &apVal[i]); + if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out; + } + } + + pVal = valueNew(db, pCtx); + if( pVal==0 ){ + rc = SQLITE_NOMEM; + goto value_from_function_out; + } + + assert( pCtx->pParse->rc==SQLITE_OK ); + memset(&ctx, 0, sizeof(ctx)); + ctx.pOut = pVal; + ctx.pFunc = pFunc; + pFunc->xFunc(&ctx, nVal, apVal); + if( ctx.isError ){ + rc = ctx.isError; + sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal)); + }else{ + sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); + assert( rc==SQLITE_OK ); + rc = sqlite3VdbeChangeEncoding(pVal, enc); + if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){ + rc = SQLITE_TOOBIG; + pCtx->pParse->nErr++; + } + } + pCtx->pParse->rc = rc; + + value_from_function_out: + if( rc!=SQLITE_OK ){ + pVal = 0; + } + if( apVal ){ + for(i=0; iop)==TK_UPLUS ) pExpr = pExpr->pLeft; if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; + /* Compressed expressions only appear when parsing the DEFAULT clause + ** on a table column definition, and hence only when pCtx==0. This + ** check ensures that an EP_TokenOnly expression is never passed down + ** into valueFromFunction(). */ + assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 ); + if( op==TK_CAST ){ u8 aff = sqlite3AffinityType(pExpr->u.zToken,0); rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); @@ -63815,6 +64439,12 @@ static int valueFromExpr( } #endif +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + else if( op==TK_FUNCTION && pCtx!=0 ){ + rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); + } +#endif + *ppVal = pVal; return rc; @@ -64101,7 +64731,7 @@ SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ Mem *aMem = pRec->aMem; sqlite3 *db = aMem[0].db; for(i=0; ipKeyInfo); sqlite3DbFree(db, pRec); @@ -64204,7 +64834,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepa /* ** Return the SQL associated with a prepared statement */ -SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe *)pStmt; return (p && p->isPrepareV2) ? p->zSql : 0; } @@ -65267,7 +65897,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ #ifndef SQLITE_OMIT_VIRTUALTABLE case P4_VTAB: { sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; - sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); + sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab); break; } #endif @@ -65931,13 +66561,29 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ else if( pCx->pVtabCursor ){ sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; const sqlite3_module *pModule = pVtabCursor->pVtab->pModule; - p->inVtabMethod = 1; + assert( pVtabCursor->pVtab->nRef>0 ); + pVtabCursor->pVtab->nRef--; pModule->xClose(pVtabCursor); - p->inVtabMethod = 0; } #endif } +/* +** Close all cursors in the current frame. +*/ +static void closeCursorsInFrame(Vdbe *p){ + if( p->apCsr ){ + int i; + for(i=0; inCursor; i++){ + VdbeCursor *pC = p->apCsr[i]; + if( pC ){ + sqlite3VdbeFreeCursor(p, pC); + p->apCsr[i] = 0; + } + } + } +} + /* ** Copy the values stored in the VdbeFrame structure to its Vdbe. This ** is used, for example, when a trigger sub-program is halted to restore @@ -65945,6 +66591,7 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ */ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ Vdbe *v = pFrame->v; + closeCursorsInFrame(v); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS v->anExec = pFrame->anExec; #endif @@ -65979,17 +66626,7 @@ static void closeAllCursors(Vdbe *p){ p->nFrame = 0; } assert( p->nFrame==0 ); - - if( p->apCsr ){ - int i; - for(i=0; inCursor; i++){ - VdbeCursor *pC = p->apCsr[i]; - if( pC ){ - sqlite3VdbeFreeCursor(p, pC); - p->apCsr[i] = 0; - } - } - } + closeCursorsInFrame(p); if( p->aMem ){ releaseMemArray(&p->aMem[1], p->nMem); } @@ -66292,7 +66929,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ ** doing this the directory is synced again before any individual ** transaction files are deleted. */ - rc = sqlite3OsDelete(pVfs, zMaster, 1); + rc = sqlite3OsDelete(pVfs, zMaster, needSync); sqlite3DbFree(db, zMaster); zMaster = 0; if( rc ){ @@ -67522,7 +68159,8 @@ static void vdbeAssertFieldCountWithinLimits( if( CORRUPT_DB ) return; idx = getVarint32(aKey, szHdr); - assert( szHdr<=nKey ); + assert( nKey>=0 ); + assert( szHdr<=(u32)nKey ); while( idxerrCode is set to SQLITE_NOMEM and, if it is not NULL, the ** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db). */ -static int vdbeRecordCompareWithSkip( +SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2, /* Right key */ int bSkip /* If true, skip the first field */ @@ -67919,7 +68557,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ - return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); } @@ -68007,7 +68645,7 @@ static int vdbeRecordCompareInt( }else if( pPKey2->nField>1 ){ /* The first fields of the two keys are equal. Compare the trailing ** fields. */ - res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ /* The first fields of the two keys are equal and there are no trailing ** fields. Return pPKey2->default_rc in this case. */ @@ -68055,7 +68693,7 @@ static int vdbeRecordCompareString( res = nStr - pPKey2->aMem[0].n; if( res==0 ){ if( pPKey2->nField>1 ){ - res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ res = pPKey2->default_rc; } @@ -68359,7 +68997,7 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ ** collating sequences are registered or if an authorizer function is ** added or changed. */ -SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p==0 || p->expired; } @@ -68396,7 +69034,7 @@ static int vdbeSafetyNotNull(Vdbe *p){ ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ -SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL @@ -68422,7 +69060,7 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ -SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; @@ -68441,7 +69079,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ /* ** Set all the parameters in the compiled SQL statement to NULL. */ -SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; @@ -68465,7 +69103,7 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ ** The following routines extract information from a Mem or sqlite3_value ** structure. */ -SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ sqlite3VdbeMemExpandBlob(p); @@ -68475,36 +69113,40 @@ SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ return sqlite3_value_text(pVal); } } -SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){ +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value *pVal){ return sqlite3ValueBytes(pVal, SQLITE_UTF8); } -SQLITE_API int sqlite3_value_bytes16(sqlite3_value *pVal){ +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value *pVal){ return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); } -SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){ +SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value *pVal){ return sqlite3VdbeRealValue((Mem*)pVal); } -SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){ +SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value *pVal){ return (int)sqlite3VdbeIntValue((Mem*)pVal); } -SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ +SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } -SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_value_text16(sqlite3_value* pVal){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value* pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); } -SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *pVal){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16BE); } -SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16LE); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ +/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five +** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating +** point number string BLOB NULL +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){ static const u8 aType[] = { SQLITE_BLOB, /* 0x00 */ SQLITE_NULL, /* 0x01 */ @@ -68580,7 +69222,7 @@ static int invokeValueDestructor( if( pCtx ) sqlite3_result_error_toobig(pCtx); return SQLITE_TOOBIG; } -SQLITE_API void sqlite3_result_blob( +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, @@ -68590,7 +69232,7 @@ SQLITE_API void sqlite3_result_blob( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, 0, xDel); } -SQLITE_API void sqlite3_result_blob64( +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64( sqlite3_context *pCtx, const void *z, sqlite3_uint64 n, @@ -68604,37 +69246,37 @@ SQLITE_API void sqlite3_result_blob64( setResultStrOrError(pCtx, z, (int)n, 0, xDel); } } -SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context *pCtx, double rVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetDouble(pCtx->pOut, rVal); } -SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif -SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context *pCtx, int iVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal); } -SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); } -SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); } -SQLITE_API void sqlite3_result_text( +SQLITE_API void SQLITE_STDCALL sqlite3_result_text( sqlite3_context *pCtx, const char *z, int n, @@ -68643,7 +69285,7 @@ SQLITE_API void sqlite3_result_text( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); } -SQLITE_API void sqlite3_result_text64( +SQLITE_API void SQLITE_STDCALL sqlite3_result_text64( sqlite3_context *pCtx, const char *z, sqlite3_uint64 n, @@ -68660,7 +69302,7 @@ SQLITE_API void sqlite3_result_text64( } } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API void sqlite3_result_text16( +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16( sqlite3_context *pCtx, const void *z, int n, @@ -68669,7 +69311,7 @@ SQLITE_API void sqlite3_result_text16( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); } -SQLITE_API void sqlite3_result_text16be( +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be( sqlite3_context *pCtx, const void *z, int n, @@ -68678,7 +69320,7 @@ SQLITE_API void sqlite3_result_text16be( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); } -SQLITE_API void sqlite3_result_text16le( +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le( sqlite3_context *pCtx, const void *z, int n, @@ -68688,17 +69330,20 @@ SQLITE_API void sqlite3_result_text16le( setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemCopy(pCtx->pOut, pValue); } -SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); } -SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; pCtx->fErrorOrAux = 1; +#ifdef SQLITE_DEBUG + if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; +#endif if( pCtx->pOut->flags & MEM_Null ){ sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1, SQLITE_UTF8, SQLITE_STATIC); @@ -68706,7 +69351,7 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ } /* Force an SQLITE_TOOBIG error. */ -SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_TOOBIG; pCtx->fErrorOrAux = 1; @@ -68715,7 +69360,7 @@ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ } /* An SQLITE_NOMEM error. */ -SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); pCtx->isError = SQLITE_NOMEM; @@ -68779,7 +69424,7 @@ static int sqlite3Step(Vdbe *p){ ** or SQLITE_BUSY error. */ #ifdef SQLITE_OMIT_AUTORESET - if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){ + if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){ sqlite3_reset((sqlite3_stmt*)p); }else{ return SQLITE_MISUSE_BKPT; @@ -68825,6 +69470,9 @@ static int sqlite3Step(Vdbe *p){ if( p->bIsReader ) db->nVdbeRead++; p->pc = 0; } +#ifdef SQLITE_DEBUG + p->rcApp = SQLITE_OK; +#endif #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); @@ -68869,7 +69517,7 @@ end_of_step: assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR || rc==SQLITE_BUSY || rc==SQLITE_MISUSE ); - assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE ); + assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp ); if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ /* If this statement was prepared using sqlite3_prepare_v2(), and an ** error has occurred, then return the error code in p->rc to the @@ -68885,7 +69533,7 @@ end_of_step: ** sqlite3Step() to do most of the work. If a schema error occurs, ** call sqlite3Reprepare() and try again. */ -SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_OK; /* Result from sqlite3Step() */ int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ @@ -68936,7 +69584,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. */ -SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ +SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){ assert( p && p->pFunc ); return p->pFunc->pUserData; } @@ -68951,22 +69599,32 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ ** sqlite3_create_function16() routines that originally registered the ** application defined function. */ -SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context *p){ assert( p && p->pFunc ); return p->pOut->db; } /* -** Return the current time for a statement +** Return the current time for a statement. If the current time +** is requested more than once within the same run of a single prepared +** statement, the exact same time is returned for each invocation regardless +** of the amount of time that elapses between invocations. In other words, +** the time returned is always the time of the first call. */ SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ - Vdbe *v = p->pVdbe; int rc; - if( v->iCurrentTime==0 ){ - rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, &v->iCurrentTime); - if( rc ) v->iCurrentTime = 0; +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime; + assert( p->pVdbe!=0 ); +#else + sqlite3_int64 iTime = 0; + sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime; +#endif + if( *piTime==0 ){ + rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime); + if( rc ) *piTime = 0; } - return v->iCurrentTime; + return *piTime; } /* @@ -69017,7 +69675,7 @@ static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){ ** context is allocated on the first call. Subsequent calls return the ** same context that was returned on prior calls. */ -SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ +SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, int nByte){ assert( p && p->pFunc && p->pFunc->xStep ); assert( sqlite3_mutex_held(p->pOut->db->mutex) ); testcase( nByte<0 ); @@ -69032,10 +69690,15 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ ** Return the auxiliary data pointer, if any, for the iArg'th argument to ** the user-function defined by pCtx. */ -SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ +SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ AuxData *pAuxData; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +#if SQLITE_ENABLE_STAT3_OR_STAT4 + if( pCtx->pVdbe==0 ) return 0; +#else + assert( pCtx->pVdbe!=0 ); +#endif for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break; } @@ -69048,7 +69711,7 @@ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ ** argument to the user-function defined by pCtx. Any previous value is ** deleted by calling the delete function specified when it was set. */ -SQLITE_API void sqlite3_set_auxdata( +SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata( sqlite3_context *pCtx, int iArg, void *pAux, @@ -69059,6 +69722,11 @@ SQLITE_API void sqlite3_set_auxdata( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); if( iArg<0 ) goto failed; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( pVdbe==0 ) goto failed; +#else + assert( pVdbe!=0 ); +#endif for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break; @@ -69098,7 +69766,7 @@ failed: ** implementations should keep their own counts within their aggregate ** context. */ -SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ +SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){ assert( p && p->pMem && p->pFunc && p->pFunc->xStep ); return p->pMem->n; } @@ -69107,7 +69775,7 @@ SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ /* ** Return the number of columns in the result set for the statement pStmt. */ -SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; return pVm ? pVm->nResColumn : 0; } @@ -69116,7 +69784,7 @@ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ ** Return the number of values available from the current row of the ** currently executing statement pStmt. */ -SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; if( pVm==0 || pVm->pResultSet==0 ) return 0; return pVm->nResColumn; @@ -69218,7 +69886,7 @@ static void columnMallocFailure(sqlite3_stmt *pStmt) ** The following routines are used to access elements of the current row ** in the result set. */ -SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ const void *val; val = sqlite3_value_blob( columnMem(pStmt,i) ); /* Even though there is no encoding conversion, value_blob() might @@ -69228,37 +69896,37 @@ SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ columnMallocFailure(pStmt); return val; } -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ +SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt *pStmt, int i){ double val = sqlite3_value_double( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ +SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_int( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ +SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt *pStmt, int i){ const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ +SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStmt, int i){ Mem *pOut = columnMem(pStmt, i); if( pOut->flags&MEM_Static ){ pOut->flags &= ~MEM_Static; @@ -69268,13 +69936,13 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ return (sqlite3_value *)pOut; } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ +SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt *pStmt, int i){ int iType = sqlite3_value_type( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return iType; @@ -69338,12 +70006,12 @@ static const void *columnName( ** Return the name of the Nth column of the result set returned by SQL ** statement pStmt. */ -SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); } @@ -69363,12 +70031,12 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt. */ -SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); } @@ -69381,12 +70049,12 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); } @@ -69397,12 +70065,12 @@ SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); } @@ -69413,12 +70081,12 @@ SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ -SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); } @@ -69519,7 +70187,7 @@ static int bindText( /* ** Bind a blob value to an SQL statement variable. */ -SQLITE_API int sqlite3_bind_blob( +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob( sqlite3_stmt *pStmt, int i, const void *zData, @@ -69528,7 +70196,7 @@ SQLITE_API int sqlite3_bind_blob( ){ return bindText(pStmt, i, zData, nData, xDel, 0); } -SQLITE_API int sqlite3_bind_blob64( +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64( sqlite3_stmt *pStmt, int i, const void *zData, @@ -69542,7 +70210,7 @@ SQLITE_API int sqlite3_bind_blob64( return bindText(pStmt, i, zData, (int)nData, xDel, 0); } } -SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -69552,10 +70220,10 @@ SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ } return rc; } -SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ return sqlite3_bind_int64(p, i, (i64)iValue); } -SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -69565,7 +70233,7 @@ SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValu } return rc; } -SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ int rc; Vdbe *p = (Vdbe*)pStmt; rc = vdbeUnbind(p, i); @@ -69574,7 +70242,7 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ } return rc; } -SQLITE_API int sqlite3_bind_text( +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text( sqlite3_stmt *pStmt, int i, const char *zData, @@ -69583,7 +70251,7 @@ SQLITE_API int sqlite3_bind_text( ){ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); } -SQLITE_API int sqlite3_bind_text64( +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64( sqlite3_stmt *pStmt, int i, const char *zData, @@ -69600,7 +70268,7 @@ SQLITE_API int sqlite3_bind_text64( } } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API int sqlite3_bind_text16( +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16( sqlite3_stmt *pStmt, int i, const void *zData, @@ -69610,7 +70278,7 @@ SQLITE_API int sqlite3_bind_text16( return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; switch( sqlite3_value_type((sqlite3_value*)pValue) ){ case SQLITE_INTEGER: { @@ -69641,7 +70309,7 @@ SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_valu } return rc; } -SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -69656,7 +70324,7 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ ** Return the number of wildcards that can be potentially bound to. ** This routine is added to support DBD::SQLite. */ -SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p ? p->nVar : 0; } @@ -69667,7 +70335,7 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ ** ** The result is always UTF-8. */ -SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ Vdbe *p = (Vdbe*)pStmt; if( p==0 || i<1 || i>p->nzVar ){ return 0; @@ -69695,7 +70363,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa } return 0; } -SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); } @@ -69729,7 +70397,7 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt ** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise ** SQLITE_OK is returned. */ -SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; if( pFrom->nVar!=pTo->nVar ){ @@ -69751,7 +70419,7 @@ SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt * ** the first argument to the sqlite3_prepare() that was used to create ** the statement in the first place. */ -SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->db : 0; } @@ -69759,14 +70427,14 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ ** Return true if the prepared statement is guaranteed to not modify the ** database. */ -SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; } /* ** Return true if the prepared statement is in need of being reset. */ -SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){ Vdbe *v = (Vdbe*)pStmt; return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN; } @@ -69777,7 +70445,7 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ ** prepared statement for the database connection. Return NULL if there ** are no more. */ -SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ +SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ sqlite3_stmt *pNext; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(pDb) ){ @@ -69798,7 +70466,7 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ /* ** Return the value of a status counter for a prepared statement */ -SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ Vdbe *pVdbe = (Vdbe*)pStmt; u32 v; #ifdef SQLITE_ENABLE_API_ARMOR @@ -69816,7 +70484,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ /* ** Return status data for a single loop within query pStmt. */ -SQLITE_API int sqlite3_stmt_scanstatus( +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement being queried */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Which metric to return */ @@ -69875,7 +70543,7 @@ SQLITE_API int sqlite3_stmt_scanstatus( /* ** Zero all counters associated with the sqlite3_stmt_scanstatus() data. */ -SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ +SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; memset(p->anExec, 0, p->nOp * sizeof(i64)); } @@ -69967,9 +70635,8 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( char zBase[100]; /* Initial working space */ db = p->db; - sqlite3StrAccumInit(&out, zBase, sizeof(zBase), + sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); - out.db = db; if( db->nVdbeExec>1 ){ while( *zRawSql ){ const char *zStart = zRawSql; @@ -69978,6 +70645,8 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( assert( (zRawSql - zStart) > 0 ); sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); } + }else if( p->nVar==0 ){ + sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql)); }else{ while( zRawSql[0] ){ n = findNextHostParameter(zRawSql, &nToken); @@ -69994,10 +70663,12 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( idx = nextIndex; } }else{ - assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); + assert( zRawSql[0]==':' || zRawSql[0]=='$' || + zRawSql[0]=='@' || zRawSql[0]=='#' ); testcase( zRawSql[0]==':' ); testcase( zRawSql[0]=='$' ); testcase( zRawSql[0]=='@' ); + testcase( zRawSql[0]=='#' ); idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); assert( idx>0 ); } @@ -70374,7 +71045,7 @@ static void applyAffinity( ** is appropriate. But only do the conversion if it is possible without ** loss of information and return the revised type of the argument. */ -SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ +SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value *pVal){ int eType = sqlite3_value_type(pVal); if( eType==SQLITE_TEXT ){ Mem *pMem = (Mem*)pVal; @@ -70672,6 +71343,21 @@ static int checkSavepointCount(sqlite3 *db){ } #endif +/* +** Return the register of pOp->p2 after first preparing it to be +** overwritten with an integer value. +*/ +static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ + Mem *pOut; + assert( pOp->p2>0 ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); + pOut = &p->aMem[pOp->p2]; + memAboutToChange(p, pOut); + if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); + pOut->flags = MEM_Int; + return pOut; +} + /* ** Execute as much of a VDBE program as we can. @@ -70680,9 +71366,11 @@ static int checkSavepointCount(sqlite3 *db){ SQLITE_PRIVATE int sqlite3VdbeExec( Vdbe *p /* The VDBE */ ){ - int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ - Op *pOp; /* Current operation */ + Op *pOp = aOp; /* Current operation */ +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + Op *pOrigOp; /* Value of pOp at the top of the loop */ +#endif int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ @@ -70758,23 +71446,22 @@ SQLITE_PRIVATE int sqlite3VdbeExec( } sqlite3EndBenignMalloc(); #endif - for(pc=p->pc; rc==SQLITE_OK; pc++){ - assert( pc>=0 && pcnOp ); + for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ + assert( pOp>=aOp && pOp<&aOp[p->nOp]); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif nVmStep++; - pOp = &aOp[pc]; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS - if( p->anExec ) p->anExec[pc]++; + if( p->anExec ) p->anExec[(int)(pOp-aOp)]++; #endif /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ - sqlite3VdbePrintOp(stdout, pc, pOp); + sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp); } #endif @@ -70791,23 +71478,9 @@ SQLITE_PRIVATE int sqlite3VdbeExec( } #endif - /* On any opcode with the "out2-prerelease" tag, free any - ** external allocations out of mem[p2] and set mem[p2] to be - ** an undefined integer. Opcodes will either fill in the integer - ** value or convert mem[p2] to a different type. - */ - assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); - if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem-p->nCursor) ); - pOut = &aMem[pOp->p2]; - memAboutToChange(p, pOut); - if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); - pOut->flags = MEM_Int; - } - /* Sanity checking on other operands */ #ifdef SQLITE_DEBUG + assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); if( (pOp->opflags & OPFLG_IN1)!=0 ){ assert( pOp->p1>0 ); assert( pOp->p1<=(p->nMem-p->nCursor) ); @@ -70840,6 +71513,9 @@ SQLITE_PRIVATE int sqlite3VdbeExec( memAboutToChange(p, &aMem[pOp->p3]); } #endif +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + pOrigOp = pOp; +#endif switch( pOp->opcode ){ @@ -70863,7 +71539,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( ** ** Other keywords in the comment that follows each case are used to ** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[]. -** Keywords include: in1, in2, in3, out2_prerelease, out2, out3. See +** Keywords include: in1, in2, in3, out2, out3. See ** the mkopcodeh.awk script for additional information. ** ** Documentation about VDBE opcodes is generated by scanning this file @@ -70891,7 +71567,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec( ** to the current line should be indented for EXPLAIN output. */ case OP_Goto: { /* jump */ - pc = pOp->p2 - 1; +jump_to_p2_and_check_for_interrupt: + pOp = &aOp[pOp->p2 - 1]; /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon @@ -70936,9 +71613,13 @@ case OP_Gosub: { /* jump */ assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; - pIn1->u.i = pc; + pIn1->u.i = (int)(pOp-aOp); REGISTER_TRACE(pOp->p1, pIn1); - pc = pOp->p2 - 1; + + /* Most jump operations do a goto to this spot in order to update + ** the pOp pointer. */ +jump_to_p2: + pOp = &aOp[pOp->p2 - 1]; break; } @@ -70950,7 +71631,7 @@ case OP_Gosub: { /* jump */ case OP_Return: { /* in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags==MEM_Int ); - pc = (int)pIn1->u.i; + pOp = &aOp[pIn1->u.i]; pIn1->flags = MEM_Undefined; break; } @@ -70974,7 +71655,7 @@ case OP_InitCoroutine: { /* jump */ assert( !VdbeMemDynamic(pOut) ); pOut->u.i = pOp->p3 - 1; pOut->flags = MEM_Int; - if( pOp->p2 ) pc = pOp->p2 - 1; + if( pOp->p2 ) goto jump_to_p2; break; } @@ -70994,7 +71675,7 @@ case OP_EndCoroutine: { /* in1 */ pCaller = &aOp[pIn1->u.i]; assert( pCaller->opcode==OP_Yield ); assert( pCaller->p2>=0 && pCaller->p2nOp ); - pc = pCaller->p2 - 1; + pOp = &aOp[pCaller->p2 - 1]; pIn1->flags = MEM_Undefined; break; } @@ -71018,9 +71699,9 @@ case OP_Yield: { /* in1, jump */ assert( VdbeMemDynamic(pIn1)==0 ); pIn1->flags = MEM_Int; pcDest = (int)pIn1->u.i; - pIn1->u.i = pc; + pIn1->u.i = (int)(pOp - aOp); REGISTER_TRACE(pOp->p1, pIn1); - pc = pcDest; + pOp = &aOp[pcDest]; break; } @@ -71071,30 +71752,34 @@ case OP_HaltIfNull: { /* in3 */ case OP_Halt: { const char *zType; const char *zLogFmt; + VdbeFrame *pFrame; + int pcx; + pcx = (int)(pOp - aOp); if( pOp->p1==SQLITE_OK && p->pFrame ){ /* Halt the sub-program. Return control to the parent frame. */ - VdbeFrame *pFrame = p->pFrame; + pFrame = p->pFrame; p->pFrame = pFrame->pParent; p->nFrame--; sqlite3VdbeSetChanges(db, p->nChange); - pc = sqlite3VdbeFrameRestore(pFrame); + pcx = sqlite3VdbeFrameRestore(pFrame); lastRowid = db->lastRowid; if( pOp->p2==OE_Ignore ){ - /* Instruction pc is the OP_Program that invoked the sub-program + /* Instruction pcx is the OP_Program that invoked the sub-program ** currently being halted. If the p2 instruction of this OP_Halt ** instruction is set to OE_Ignore, then the sub-program is throwing ** an IGNORE exception. In this case jump to the address specified ** as the p2 of the calling OP_Program. */ - pc = p->aOp[pc].p2-1; + pcx = p->aOp[pcx].p2-1; } aOp = p->aOp; aMem = p->aMem; + pOp = &aOp[pcx]; break; } p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; - p->pc = pc; + p->pc = pcx; if( p->rc ){ if( pOp->p5 ){ static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", @@ -71118,7 +71803,7 @@ case OP_Halt: { }else{ sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType); } - sqlite3_log(pOp->p1, zLogFmt, pc, p->zSql, p->zErrMsg); + sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); @@ -71137,7 +71822,8 @@ case OP_Halt: { ** ** The 32-bit integer value P1 is written into register P2. */ -case OP_Integer: { /* out2-prerelease */ +case OP_Integer: { /* out2 */ + pOut = out2Prerelease(p, pOp); pOut->u.i = pOp->p1; break; } @@ -71148,7 +71834,8 @@ case OP_Integer: { /* out2-prerelease */ ** P4 is a pointer to a 64-bit integer value. ** Write that value into register P2. */ -case OP_Int64: { /* out2-prerelease */ +case OP_Int64: { /* out2 */ + pOut = out2Prerelease(p, pOp); assert( pOp->p4.pI64!=0 ); pOut->u.i = *pOp->p4.pI64; break; @@ -71161,7 +71848,8 @@ case OP_Int64: { /* out2-prerelease */ ** P4 is a pointer to a 64-bit floating point value. ** Write that value into register P2. */ -case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ +case OP_Real: { /* same as TK_FLOAT, out2 */ + pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Real; assert( !sqlite3IsNaN(*pOp->p4.pReal) ); pOut->u.r = *pOp->p4.pReal; @@ -71173,12 +71861,13 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ ** Synopsis: r[P2]='P4' ** ** P4 points to a nul terminated UTF-8 string. This opcode is transformed -** into a String before it is executed for the first time. During +** into a String opcode before it is executed for the first time. During ** this transformation, the length of string P4 is computed and stored ** as the P1 parameter. */ -case OP_String8: { /* same as TK_STRING, out2-prerelease */ +case OP_String8: { /* same as TK_STRING, out2 */ assert( pOp->p4.z!=0 ); + pOut = out2Prerelease(p, pOp); pOp->opcode = OP_String; pOp->p1 = sqlite3Strlen30(pOp->p4.z); @@ -71205,18 +71894,31 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ /* Fall through to the next case, OP_String */ } -/* Opcode: String P1 P2 * P4 * +/* Opcode: String P1 P2 P3 P4 P5 ** Synopsis: r[P2]='P4' (len=P1) ** ** The string value P4 of length P1 (bytes) is stored in register P2. +** +** If P5!=0 and the content of register P3 is greater than zero, then +** the datatype of the register P2 is converted to BLOB. The content is +** the same sequence of bytes, it is merely interpreted as a BLOB instead +** of a string, as if it had been CAST. */ -case OP_String: { /* out2-prerelease */ +case OP_String: { /* out2 */ assert( pOp->p4.z!=0 ); + pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = pOp->p4.z; pOut->n = pOp->p1; pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); + if( pOp->p5 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=(p->nMem-p->nCursor) ); + pIn3 = &aMem[pOp->p3]; + assert( pIn3->flags & MEM_Int ); + if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term; + } break; } @@ -71232,9 +71934,10 @@ case OP_String: { /* out2-prerelease */ ** NULL values will not compare equal even if SQLITE_NULLEQ is set on ** OP_Ne or OP_Eq. */ -case OP_Null: { /* out2-prerelease */ +case OP_Null: { /* out2 */ int cnt; u16 nullFlag; + pOut = out2Prerelease(p, pOp); cnt = pOp->p3-pOp->p2; assert( pOp->p3<=(p->nMem-p->nCursor) ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; @@ -71269,8 +71972,9 @@ case OP_SoftNull: { ** P4 points to a blob of data P1 bytes long. Store this ** blob in register P2. */ -case OP_Blob: { /* out2-prerelease */ +case OP_Blob: { /* out2 */ assert( pOp->p1 <= SQLITE_MAX_LENGTH ); + pOut = out2Prerelease(p, pOp); sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); @@ -71285,7 +71989,7 @@ case OP_Blob: { /* out2-prerelease */ ** If the parameter is named, then its name appears in P4. ** The P4 value is used by sqlite3_bind_parameter_name(). */ -case OP_Variable: { /* out2-prerelease */ +case OP_Variable: { /* out2 */ Mem *pVar; /* Value being transferred */ assert( pOp->p1>0 && pOp->p1<=p->nVar ); @@ -71294,6 +71998,7 @@ case OP_Variable: { /* out2-prerelease */ if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; } + pOut = out2Prerelease(p, pOp); sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); break; @@ -71328,10 +72033,11 @@ case OP_Move: { memAboutToChange(p, pOut); sqlite3VdbeMemMove(pOut, pIn1); #ifdef SQLITE_DEBUG - if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){ - pOut->pScopyFrom += p1 - pOp->p2; + if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrompScopyFrom += pOp->p2 - p1; } #endif + Deephemeralize(pOut); REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; @@ -71470,7 +72176,7 @@ case OP_ResultRow: { /* Return SQLITE_ROW */ - p->pc = pc + 1; + p->pc = (int)(pOp - aOp) + 1; rc = SQLITE_ROW; goto vdbe_return; } @@ -71663,7 +72369,7 @@ arithmetic_result_is_null: ** ** The interface used by the implementation of the aforementioned functions ** to retrieve the collation sequence set by this opcode is not available -** publicly, only to user functions defined in func.c. +** publicly. Only built-in functions have access to this feature. */ case OP_CollSeq: { assert( pOp->p4type==P4_COLLSEQ ); @@ -71716,7 +72422,7 @@ case OP_Function: { assert( pOp->p4type==P4_FUNCDEF ); ctx.pFunc = pOp->p4.pFunc; - ctx.iOp = pc; + ctx.iOp = (int)(pOp - aOp); ctx.pVdbe = p; MemSetTypeFlag(ctx.pOut, MEM_Null); ctx.fErrorOrAux = 0; @@ -71730,7 +72436,7 @@ case OP_Function: { sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(ctx.pOut)); rc = ctx.isError; } - sqlite3VdbeDeleteAuxData(p, pc, pOp->p1); + sqlite3VdbeDeleteAuxData(p, (int)(pOp - aOp), pOp->p1); } /* Copy the result of the function into register P3 */ @@ -71859,8 +72565,7 @@ case OP_MustBeInt: { /* jump, in1 */ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ - pc = pOp->p2 - 1; - break; + goto jump_to_p2; } } } @@ -72046,7 +72751,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ }else{ VdbeBranchTaken(2,3); if( pOp->p5 & SQLITE_JUMPIFNULL ){ - pc = pOp->p2-1; + goto jump_to_p2; } } break; @@ -72066,11 +72771,15 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_Real ); sqlite3VdbeMemStringify(pIn1, encoding, 1); + testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); + flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); } if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){ testcase( pIn3->flags & MEM_Int ); testcase( pIn3->flags & MEM_Real ); sqlite3VdbeMemStringify(pIn3, encoding, 1); + testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); + flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask); } } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); @@ -72094,6 +72803,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ default: res = res>=0; break; } + /* Undo any changes made by applyAffinity() to the input registers. */ + assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); + pIn1->flags = flags1; + assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) ); + pIn3->flags = flags3; + if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); @@ -72103,12 +72818,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ }else{ VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); if( res ){ - pc = pOp->p2-1; + goto jump_to_p2; } } - /* Undo any changes made by applyAffinity() to the input registers. */ - pIn1->flags = flags1; - pIn3->flags = flags3; break; } @@ -72203,11 +72915,11 @@ case OP_Compare: { */ case OP_Jump: { /* jump */ if( iCompare<0 ){ - pc = pOp->p1 - 1; VdbeBranchTaken(0,3); + VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1]; }else if( iCompare==0 ){ - pc = pOp->p2 - 1; VdbeBranchTaken(1,3); + VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1]; }else{ - pc = pOp->p3 - 1; VdbeBranchTaken(2,3); + VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1]; } break; } @@ -72317,7 +73029,7 @@ case OP_Once: { /* jump */ assert( pOp->p1nOnceFlag ); VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); if( p->aOnceFlag[pOp->p1] ){ - pc = pOp->p2-1; + goto jump_to_p2; }else{ p->aOnceFlag[pOp->p1] = 1; } @@ -72352,7 +73064,7 @@ case OP_IfNot: { /* jump, in1 */ } VdbeBranchTaken(c!=0, 2); if( c ){ - pc = pOp->p2-1; + goto jump_to_p2; } break; } @@ -72366,7 +73078,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2); if( (pIn1->flags & MEM_Null)!=0 ){ - pc = pOp->p2 - 1; + goto jump_to_p2; } break; } @@ -72380,7 +73092,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); if( (pIn1->flags & MEM_Null)==0 ){ - pc = pOp->p2 - 1; + goto jump_to_p2; } break; } @@ -72594,7 +73306,7 @@ case OP_Column: { } } - /* If after trying to extra new entries from the header, nHdrParsed is + /* If after trying to extract new entries from the header, nHdrParsed is ** still not up to p2, that means that the record has fewer than p2 ** columns. So the result will be either the default value or a NULL. */ @@ -72718,7 +73430,7 @@ case OP_MakeRecord: { u64 nData; /* Number of bytes of data space */ int nHdr; /* Number of bytes of header space */ i64 nByte; /* Data space required for this record */ - int nZero; /* Number of zero bytes at the end of the record */ + i64 nZero; /* Number of zero bytes at the end of the record */ int nVarint; /* Number of bytes in a varint */ u32 serial_type; /* Type field */ Mem *pData0; /* First field to be combined into the record */ @@ -72810,7 +73522,7 @@ case OP_MakeRecord: { if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ + if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } @@ -72861,7 +73573,7 @@ case OP_MakeRecord: { ** opened by cursor P1 in register P2 */ #ifndef SQLITE_OMIT_BTREECOUNT -case OP_Count: { /* out2-prerelease */ +case OP_Count: { /* out2 */ i64 nEntry; BtCursor *pCrsr; @@ -72869,6 +73581,7 @@ case OP_Count: { /* out2-prerelease */ assert( pCrsr ); nEntry = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3BtreeCount(pCrsr, &nEntry); + pOut = out2Prerelease(p, pOp); pOut->u.i = nEntry; break; } @@ -72982,7 +73695,7 @@ case OP_Savepoint: { } db->autoCommit = 1; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = pc; + p->pc = (int)(pOp - aOp); db->autoCommit = 0; p->rc = rc = SQLITE_BUSY; goto vdbe_return; @@ -73041,7 +73754,7 @@ case OP_Savepoint: { db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } - if( !isTransaction ){ + if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){ rc = sqlite3VtabSavepoint(db, p1, iSavepoint); if( rc!=SQLITE_OK ) goto abort_due_to_error; } @@ -73101,7 +73814,7 @@ case OP_AutoCommit: { }else{ db->autoCommit = (u8)desiredAutoCommit; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = pc; + p->pc = (int)(pOp - aOp); db->autoCommit = (u8)(1-desiredAutoCommit); p->rc = rc = SQLITE_BUSY; goto vdbe_return; @@ -73178,7 +73891,7 @@ case OP_Transaction: { if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ - p->pc = pc; + p->pc = (int)(pOp - aOp); p->rc = rc = SQLITE_BUSY; goto vdbe_return; } @@ -73208,7 +73921,12 @@ case OP_Transaction: { p->nStmtDefImmCons = db->nDeferredImmCons; } - /* Gather the schema version number for checking */ + /* Gather the schema version number for checking: + ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite + ** each time a query is executed to ensure that the internal cache of the + ** schema used when compiling the SQL query matches the schema of the + ** database against which the compiled query is actually executed. + */ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); iGen = db->aDb[pOp->p1].pSchema->iGeneration; }else{ @@ -73252,7 +73970,7 @@ case OP_Transaction: { ** must be started or there must be an open cursor) before ** executing this instruction. */ -case OP_ReadCookie: { /* out2-prerelease */ +case OP_ReadCookie: { /* out2 */ int iMeta; int iDb; int iCookie; @@ -73266,6 +73984,7 @@ case OP_ReadCookie: { /* out2-prerelease */ assert( DbMaskTest(p->btreeMask, iDb) ); sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta); + pOut = out2Prerelease(p, pOp); pOut->u.i = iMeta; break; } @@ -73376,20 +74095,6 @@ case OP_SetCookie: { /* in3 */ ** See also OpenRead. */ case OP_ReopenIdx: { - VdbeCursor *pCur; - - assert( pOp->p5==0 ); - assert( pOp->p4type==P4_KEYINFO ); - pCur = p->apCsr[pOp->p1]; - if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ - assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ - break; - } - /* If the cursor is not currently open or is open on a different - ** index, then fall through into OP_OpenRead to force a reopen */ -} -case OP_OpenRead: -case OP_OpenWrite: { int nField; KeyInfo *pKeyInfo; int p2; @@ -73399,8 +74104,20 @@ case OP_OpenWrite: { VdbeCursor *pCur; Db *pDb; - assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); - assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); + assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); + assert( pOp->p4type==P4_KEYINFO ); + pCur = p->apCsr[pOp->p1]; + if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ + assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ + goto open_cursor_set_hints; + } + /* If the cursor is not currently open or is open on a different + ** index, then fall through into OP_OpenRead to force a reopen */ +case OP_OpenRead: +case OP_OpenWrite: + + assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 ); + assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); assert( p->bIsReader ); assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx || p->readOnly==0 ); @@ -73463,14 +74180,17 @@ case OP_OpenWrite: { pCur->pgnoRoot = p2; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; - assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); - sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); - /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; + +open_cursor_set_hints: + assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); + assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ ); + sqlite3BtreeCursorHints(pCur->pCursor, + (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ))); break; } @@ -73586,7 +74306,7 @@ case OP_SequenceTest: { pC = p->apCsr[pOp->p1]; assert( pC->pSorter ); if( (pC->seqCount++)==0 ){ - pc = pOp->p2 - 1; + goto jump_to_p2; } break; } @@ -73731,6 +74451,22 @@ case OP_SeekGT: { /* jump, in3 */ #ifdef SQLITE_DEBUG pC->seekOp = pOp->opcode; #endif + + /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and + ** OP_SeekLE opcodes are allowed, and these must be immediately followed + ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key. + */ +#ifdef SQLITE_DEBUG + if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){ + assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); + assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); + assert( pOp[1].p1==pOp[0].p1 ); + assert( pOp[1].p2==pOp[0].p2 ); + assert( pOp[1].p3==pOp[0].p3 ); + assert( pOp[1].p4.i==pOp[0].p4.i ); + } +#endif + if( pC->isTable ){ /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do @@ -73747,7 +74483,7 @@ case OP_SeekGT: { /* jump, in3 */ if( (pIn3->flags & MEM_Real)==0 ){ /* If the P3 value cannot be converted into any kind of a number, ** then the seek is not possible, so jump to P2 */ - pc = pOp->p2 - 1; VdbeBranchTaken(1,2); + VdbeBranchTaken(1,2); goto jump_to_p2; break; } @@ -73838,7 +74574,7 @@ case OP_SeekGT: { /* jump, in3 */ assert( pOp->p2>0 ); VdbeBranchTaken(res!=0,2); if( res ){ - pc = pOp->p2 - 1; + goto jump_to_p2; } break; } @@ -73932,6 +74668,7 @@ case OP_NoConflict: /* jump, in3 */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int alreadyExists; + int takeJump; int ii; VdbeCursor *pC; int res; @@ -73954,7 +74691,7 @@ case OP_Found: { /* jump, in3 */ pIn3 = &aMem[pOp->p3]; assert( pC->pCursor!=0 ); assert( pC->isTable==0 ); - pFree = 0; /* Not needed. Only used to suppress a compiler warning. */ + pFree = 0; if( pOp->p4.i>0 ){ r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; @@ -73977,21 +74714,20 @@ case OP_Found: { /* jump, in3 */ sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } pIdxKey->default_rc = 0; + takeJump = 0; if( pOp->opcode==OP_NoConflict ){ /* For the OP_NoConflict opcode, take the jump if any of the ** input fields are NULL, since any key with a NULL will not ** conflict */ for(ii=0; iinField; ii++){ if( pIdxKey->aMem[ii].flags & MEM_Null ){ - pc = pOp->p2 - 1; VdbeBranchTaken(1,2); + takeJump = 1; break; } } } rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); - if( pOp->p4.i==0 ){ - sqlite3DbFree(db, pFree); - } + sqlite3DbFree(db, pFree); if( rc!=SQLITE_OK ){ break; } @@ -74002,10 +74738,10 @@ case OP_Found: { /* jump, in3 */ pC->cacheStatus = CACHE_STALE; if( pOp->opcode==OP_Found ){ VdbeBranchTaken(alreadyExists!=0,2); - if( alreadyExists ) pc = pOp->p2 - 1; + if( alreadyExists ) goto jump_to_p2; }else{ - VdbeBranchTaken(alreadyExists==0,2); - if( !alreadyExists ) pc = pOp->p2 - 1; + VdbeBranchTaken(takeJump||alreadyExists==0,2); + if( takeJump || !alreadyExists ) goto jump_to_p2; } break; } @@ -74054,10 +74790,8 @@ case OP_NotExists: { /* jump, in3 */ pC->cacheStatus = CACHE_STALE; pC->deferredMoveto = 0; VdbeBranchTaken(res!=0,2); - if( res!=0 ){ - pc = pOp->p2 - 1; - } pC->seekResult = res; + if( res!=0 ) goto jump_to_p2; break; } @@ -74069,9 +74803,10 @@ case OP_NotExists: { /* jump, in3 */ ** The sequence number on the cursor is incremented after this ** instruction. */ -case OP_Sequence: { /* out2-prerelease */ +case OP_Sequence: { /* out2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( p->apCsr[pOp->p1]!=0 ); + pOut = out2Prerelease(p, pOp); pOut->u.i = p->apCsr[pOp->p1]->seqCount++; break; } @@ -74092,7 +74827,7 @@ case OP_Sequence: { /* out2-prerelease */ ** generated record number. This P3 mechanism is used to help implement the ** AUTOINCREMENT feature. */ -case OP_NewRowid: { /* out2-prerelease */ +case OP_NewRowid: { /* out2 */ i64 v; /* The new rowid */ VdbeCursor *pC; /* Cursor of table to get the new rowid */ int res; /* Result of an sqlite3BtreeLast() */ @@ -74102,6 +74837,7 @@ case OP_NewRowid: { /* out2-prerelease */ v = 0; res = 0; + pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -74415,9 +75151,7 @@ case OP_SorterCompare: { res = 0; rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res); VdbeBranchTaken(res!=0,2); - if( res ){ - pc = pOp->p2-1; - } + if( res ) goto jump_to_p2; break; }; @@ -74546,12 +75280,13 @@ case OP_RowData: { ** be a separate OP_VRowid opcode for use with virtual tables, but this ** one opcode now works for both table types. */ -case OP_Rowid: { /* out2-prerelease */ +case OP_Rowid: { /* out2 */ VdbeCursor *pC; i64 v; sqlite3_vtab *pVtab; const sqlite3_module *pModule; + pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -74604,7 +75339,7 @@ case OP_NullRow: { break; } -/* Opcode: Last P1 P2 * * * +/* Opcode: Last P1 P2 P3 * * ** ** The next use of the Rowid or Column or Prev instruction for P1 ** will refer to the last entry in the database table or index. @@ -74631,12 +75366,13 @@ case OP_Last: { /* jump */ pC->nullRow = (u8)res; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; + pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG pC->seekOp = OP_Last; #endif if( pOp->p2>0 ){ VdbeBranchTaken(res!=0,2); - if( res ) pc = pOp->p2 - 1; + if( res ) goto jump_to_p2; } break; } @@ -74700,9 +75436,7 @@ case OP_Rewind: { /* jump */ pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2nOp ); VdbeBranchTaken(res!=0,2); - if( res ){ - pc = pOp->p2 - 1; - } + if( res ) goto jump_to_p2; break; } @@ -74813,11 +75547,11 @@ next_tail: VdbeBranchTaken(res==0,2); if( res==0 ){ pC->nullRow = 0; - pc = pOp->p2 - 1; p->aCounter[pOp->p5]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif + goto jump_to_p2_and_check_for_interrupt; }else{ pC->nullRow = 1; } @@ -74925,11 +75659,12 @@ case OP_IdxDelete: { ** ** See also: Rowid, MakeRecord. */ -case OP_IdxRowid: { /* out2-prerelease */ +case OP_IdxRowid: { /* out2 */ BtCursor *pCrsr; VdbeCursor *pC; i64 rowid; + pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -75042,9 +75777,7 @@ case OP_IdxGE: { /* jump */ res++; } VdbeBranchTaken(res>0,2); - if( res>0 ){ - pc = pOp->p2 - 1 ; - } + if( res>0 ) goto jump_to_p2; break; } @@ -75068,32 +75801,18 @@ case OP_IdxGE: { /* jump */ ** ** See also: Clear */ -case OP_Destroy: { /* out2-prerelease */ +case OP_Destroy: { /* out2 */ int iMoved; - int iCnt; - Vdbe *pVdbe; int iDb; assert( p->readOnly==0 ); -#ifndef SQLITE_OMIT_VIRTUALTABLE - iCnt = 0; - for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ - if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader - && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 - ){ - iCnt++; - } - } -#else - iCnt = db->nVdbeRead; -#endif + pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Null; - if( iCnt>1 ){ + if( db->nVdbeRead > db->nVDestroy+1 ){ rc = SQLITE_LOCKED; p->errorAction = OE_Abort; }else{ iDb = pOp->p3; - assert( iCnt==1 ); assert( DbMaskTest(p->btreeMask, iDb) ); iMoved = 0; /* Not needed. Only to silence a warning. */ rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); @@ -75196,12 +75915,13 @@ case OP_ResetSorter: { ** ** See documentation on OP_CreateTable for additional information. */ -case OP_CreateIndex: /* out2-prerelease */ -case OP_CreateTable: { /* out2-prerelease */ +case OP_CreateIndex: /* out2 */ +case OP_CreateTable: { /* out2 */ int pgno; int flags; Db *pDb; + pOut = out2Prerelease(p, pOp); pgno = 0; assert( pOp->p1>=0 && pOp->p1nDb ); assert( DbMaskTest(p->btreeMask, pOp->p1) ); @@ -75427,12 +76147,12 @@ case OP_RowSetRead: { /* jump, in1, out3 */ ){ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); - pc = pOp->p2 - 1; VdbeBranchTaken(1,2); + goto jump_to_p2_and_check_for_interrupt; }else{ /* A value was pulled from the index */ - sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); VdbeBranchTaken(0,2); + sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); } goto check_for_interrupt; } @@ -75483,10 +76203,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */ if( iSet ){ exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); VdbeBranchTaken(exists!=0,2); - if( exists ){ - pc = pOp->p2 - 1; - break; - } + if( exists ) goto jump_to_p2; } if( iSet>=0 ){ sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); @@ -75575,7 +76292,7 @@ case OP_Program: { /* jump */ pFrame->v = p; pFrame->nChildMem = nMem; pFrame->nChildCsr = pProgram->nCsr; - pFrame->pc = pc; + pFrame->pc = (int)(pOp - aOp); pFrame->aMem = p->aMem; pFrame->nMem = p->nMem; pFrame->apCsr = p->apCsr; @@ -75598,7 +76315,7 @@ case OP_Program: { /* jump */ pFrame = pRt->u.pFrame; assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem ); assert( pProgram->nCsr==pFrame->nChildCsr ); - assert( pc==pFrame->pc ); + assert( (int)(pOp - aOp)==pFrame->pc ); } p->nFrame++; @@ -75619,7 +76336,7 @@ case OP_Program: { /* jump */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = 0; #endif - pc = -1; + pOp = &aOp[-1]; memset(p->aOnceFlag, 0, p->nOnceFlag); break; @@ -75637,9 +76354,10 @@ case OP_Program: { /* jump */ ** the value of the P1 argument to the value of the P1 argument to the ** calling OP_Program instruction. */ -case OP_Param: { /* out2-prerelease */ +case OP_Param: { /* out2 */ VdbeFrame *pFrame; Mem *pIn; + pOut = out2Prerelease(p, pOp); pFrame = p->pFrame; pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); @@ -75683,10 +76401,10 @@ case OP_FkCounter: { case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); - if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; }else{ VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); - if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; } break; } @@ -75726,18 +76444,18 @@ case OP_MemMax: { /* in2 */ /* Opcode: IfPos P1 P2 * * * ** Synopsis: if r[P1]>0 goto P2 ** -** If the value of register P1 is 1 or greater, jump to P2. +** Register P1 must contain an integer. +** If the value of register P1 is 1 or greater, jump to P2 and +** add the literal value P3 to register P1. ** -** It is illegal to use this instruction on a register that does -** not contain an integer. An assertion fault will result if you try. +** If the initial value of register P1 is less than 1, then the +** value is unchanged and control passes through to the next instruction. */ case OP_IfPos: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); VdbeBranchTaken( pIn1->u.i>0, 2); - if( pIn1->u.i>0 ){ - pc = pOp->p2 - 1; - } + if( pIn1->u.i>0 ) goto jump_to_p2; break; } @@ -75752,26 +76470,56 @@ case OP_IfNeg: { /* jump, in1 */ assert( pIn1->flags&MEM_Int ); pIn1->u.i += pOp->p3; VdbeBranchTaken(pIn1->u.i<0, 2); - if( pIn1->u.i<0 ){ - pc = pOp->p2 - 1; + if( pIn1->u.i<0 ) goto jump_to_p2; + break; +} + +/* Opcode: IfNotZero P1 P2 P3 * * +** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2 +** +** Register P1 must contain an integer. If the content of register P1 is +** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is +** initially zero, leave it unchanged and fall through. +*/ +case OP_IfNotZero: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken(pIn1->u.i<0, 2); + if( pIn1->u.i ){ + pIn1->u.i += pOp->p3; + goto jump_to_p2; } break; } -/* Opcode: IfZero P1 P2 P3 * * -** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2 +/* Opcode: DecrJumpZero P1 P2 * * * +** Synopsis: if (--r[P1])==0 goto P2 ** -** The register P1 must contain an integer. Add literal P3 to the -** value in register P1. If the result is exactly 0, jump to P2. +** Register P1 must hold an integer. Decrement the value in register P1 +** then jump to P2 if the new value is exactly zero. */ -case OP_IfZero: { /* jump, in1 */ +case OP_DecrJumpZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); - pIn1->u.i += pOp->p3; + pIn1->u.i--; VdbeBranchTaken(pIn1->u.i==0, 2); - if( pIn1->u.i==0 ){ - pc = pOp->p2 - 1; - } + if( pIn1->u.i==0 ) goto jump_to_p2; + break; +} + + +/* Opcode: JumpZeroIncr P1 P2 * * * +** Synopsis: if (r[P1]++)==0 ) goto P2 +** +** The register P1 must contain an integer. If register P1 is initially +** zero, then jump to P2. Increment register P1 regardless of whether or +** not the jump is taken. +*/ +case OP_JumpZeroIncr: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken(pIn1->u.i==0, 2); + if( (pIn1->u.i++)==0 ) goto jump_to_p2; break; } @@ -75813,7 +76561,7 @@ case OP_AggStep: { ctx.pOut = &t; ctx.isError = 0; ctx.pVdbe = p; - ctx.iOp = pc; + ctx.iOp = (int)(pOp - aOp); ctx.skipFlag = 0; (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */ if( ctx.isError ){ @@ -75908,7 +76656,7 @@ case OP_Checkpoint: { ** ** Write a string containing the final journal-mode to register P2. */ -case OP_JournalMode: { /* out2-prerelease */ +case OP_JournalMode: { /* out2 */ Btree *pBt; /* Btree to change journal mode of */ Pager *pPager; /* Pager associated with pBt */ int eNew; /* New journal mode */ @@ -75917,6 +76665,7 @@ case OP_JournalMode: { /* out2-prerelease */ const char *zFilename; /* Name of database file for pPager */ #endif + pOut = out2Prerelease(p, pOp); eNew = pOp->p3; assert( eNew==PAGER_JOURNALMODE_DELETE || eNew==PAGER_JOURNALMODE_TRUNCATE @@ -75992,7 +76741,6 @@ case OP_JournalMode: { /* out2-prerelease */ } eNew = sqlite3PagerSetJournalMode(pPager, eNew); - pOut = &aMem[pOp->p2]; pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = (char *)sqlite3JournalModename(eNew); pOut->n = sqlite3Strlen30(pOut->z); @@ -76033,8 +76781,8 @@ case OP_IncrVacuum: { /* jump */ rc = sqlite3BtreeIncrVacuum(pBt); VdbeBranchTaken(rc==SQLITE_DONE,2); if( rc==SQLITE_DONE ){ - pc = pOp->p2 - 1; rc = SQLITE_OK; + goto jump_to_p2; } break; } @@ -76112,13 +76860,29 @@ case OP_VBegin: { #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VCreate P1 * * P4 * +/* Opcode: VCreate P1 P2 * * * ** -** P4 is the name of a virtual table in database P1. Call the xCreate method -** for that table. +** P2 is a register that holds the name of a virtual table in database +** P1. Call the xCreate method for that table. */ case OP_VCreate: { - rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg); + Mem sMem; /* For storing the record being decoded */ + const char *zTab; /* Name of the virtual table */ + + memset(&sMem, 0, sizeof(sMem)); + sMem.db = db; + /* Because P2 is always a static string, it is impossible for the + ** sqlite3VdbeMemCopy() to fail */ + assert( (aMem[pOp->p2].flags & MEM_Str)!=0 ); + assert( (aMem[pOp->p2].flags & MEM_Static)!=0 ); + rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]); + assert( rc==SQLITE_OK ); + zTab = (const char*)sqlite3_value_text(&sMem); + assert( zTab || db->mallocFailed ); + if( zTab ){ + rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg); + } + sqlite3VdbeMemRelease(&sMem); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -76130,9 +76894,9 @@ case OP_VCreate: { ** of that table. */ case OP_VDestroy: { - p->inVtabMethod = 2; + db->nVDestroy++; rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); - p->inVtabMethod = 0; + db->nVDestroy--; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -76148,14 +76912,17 @@ case OP_VOpen: { VdbeCursor *pCur; sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; - sqlite3_module *pModule; + const sqlite3_module *pModule; assert( p->bIsReader ); pCur = 0; pVtabCursor = 0; pVtab = pOp->p4.pVtab->pVtab; - pModule = (sqlite3_module *)pVtab->pModule; - assert(pVtab && pModule); + if( pVtab==0 || NEVER(pVtab->pModule==0) ){ + rc = SQLITE_LOCKED; + break; + } + pModule = pVtab->pModule; rc = pModule->xOpen(pVtab, &pVtabCursor); sqlite3VtabImportErrmsg(p, pVtab); if( SQLITE_OK==rc ){ @@ -76166,9 +76933,11 @@ case OP_VOpen: { pCur = allocateCursor(p, pOp->p1, 0, -1, 0); if( pCur ){ pCur->pVtabCursor = pVtabCursor; + pVtab->nRef++; }else{ - db->mallocFailed = 1; + assert( db->mallocFailed ); pModule->xClose(pVtabCursor); + goto no_mem; } } break; @@ -76224,27 +76993,19 @@ case OP_VFilter: { /* jump */ iQuery = (int)pQuery->u.i; /* Invoke the xFilter method */ - { - res = 0; - apArg = p->apArg; - for(i = 0; iinVtabMethod = 1; - rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); - p->inVtabMethod = 0; - sqlite3VtabImportErrmsg(p, pVtab); - if( rc==SQLITE_OK ){ - res = pModule->xEof(pVtabCursor); - } - VdbeBranchTaken(res!=0,2); - if( res ){ - pc = pOp->p2 - 1; - } + res = 0; + apArg = p->apArg; + for(i = 0; ixFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); + sqlite3VtabImportErrmsg(p, pVtab); + if( rc==SQLITE_OK ){ + res = pModule->xEof(pVtabCursor); } pCur->nullRow = 0; - + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -76323,9 +77084,7 @@ case OP_VNext: { /* jump */ ** data is available) and the error code returned when xColumn or ** some other method is next invoked on the save virtual table cursor. */ - p->inVtabMethod = 1; rc = pModule->xNext(pCur->pVtabCursor); - p->inVtabMethod = 0; sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK ){ res = pModule->xEof(pCur->pVtabCursor); @@ -76333,7 +77092,7 @@ case OP_VNext: { /* jump */ VdbeBranchTaken(!res,2); if( !res ){ /* If there is data, jump to P2 */ - pc = pOp->p2 - 1; + goto jump_to_p2_and_check_for_interrupt; } goto check_for_interrupt; } @@ -76400,7 +77159,7 @@ case OP_VRename: { */ case OP_VUpdate: { sqlite3_vtab *pVtab; - sqlite3_module *pModule; + const sqlite3_module *pModule; int nArg; int i; sqlite_int64 rowid; @@ -76412,7 +77171,11 @@ case OP_VUpdate: { ); assert( p->readOnly==0 ); pVtab = pOp->p4.pVtab->pVtab; - pModule = (sqlite3_module *)pVtab->pModule; + if( pVtab==0 || NEVER(pVtab->pModule==0) ){ + rc = SQLITE_LOCKED; + break; + } + pModule = pVtab->pModule; nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); if( ALWAYS(pModule->xUpdate) ){ @@ -76452,7 +77215,8 @@ case OP_VUpdate: { ** ** Write the current number of pages in database P1 to memory cell P2. */ -case OP_Pagecount: { /* out2-prerelease */ +case OP_Pagecount: { /* out2 */ + pOut = out2Prerelease(p, pOp); pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); break; } @@ -76468,10 +77232,11 @@ case OP_Pagecount: { /* out2-prerelease */ ** ** Store the maximum page count after the change in register P2. */ -case OP_MaxPgcnt: { /* out2-prerelease */ +case OP_MaxPgcnt: { /* out2 */ unsigned int newMax; Btree *pBt; + pOut = out2Prerelease(p, pOp); pBt = db->aDb[pOp->p1].pBt; newMax = 0; if( pOp->p3 ){ @@ -76500,9 +77265,6 @@ case OP_Init: { /* jump */ char *zTrace; char *z; - if( pOp->p2 ){ - pc = pOp->p2 - 1; - } #ifndef SQLITE_OMIT_TRACE if( db->xTrace && !p->doingRerun @@ -76530,6 +77292,7 @@ case OP_Init: { /* jump */ } #endif /* SQLITE_DEBUG */ #endif /* SQLITE_OMIT_TRACE */ + if( pOp->p2 ) goto jump_to_p2; break; } @@ -76561,8 +77324,8 @@ default: { /* This is really OP_Noop and OP_Explain */ #ifdef VDBE_PROFILE { u64 endTime = sqlite3Hwtime(); - if( endTime>start ) pOp->cycles += endTime - start; - pOp->cnt++; + if( endTime>start ) pOrigOp->cycles += endTime - start; + pOrigOp->cnt++; } #endif @@ -76572,16 +77335,16 @@ default: { /* This is really OP_Noop and OP_Explain */ ** the evaluator loop. So we can leave it out when NDEBUG is defined. */ #ifndef NDEBUG - assert( pc>=-1 && pcnOp ); + assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] ); #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ if( rc!=0 ) printf("rc=%d\n",rc); - if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){ - registerTrace(pOp->p2, &aMem[pOp->p2]); + if( pOrigOp->opflags & (OPFLG_OUT2) ){ + registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]); } - if( pOp->opflags & OPFLG_OUT3 ){ - registerTrace(pOp->p3, &aMem[pOp->p3]); + if( pOrigOp->opflags & OPFLG_OUT3 ){ + registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]); } } #endif /* SQLITE_DEBUG */ @@ -76596,7 +77359,7 @@ vdbe_error_halt: p->rc = rc; testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3_log(rc, "statement aborts at %d: [%s] %s", - pc, p->zSql, p->zErrMsg); + (int)(pOp - aOp), p->zSql, p->zErrMsg); sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; @@ -76759,7 +77522,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ /* ** Open a blob handle. */ -SQLITE_API int sqlite3_blob_open( +SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( sqlite3* db, /* The database connection */ const char *zDb, /* The attached database containing the blob */ const char *zTable, /* The table containing the blob */ @@ -76809,12 +77572,17 @@ SQLITE_API int sqlite3_blob_open( Incrblob *pBlob = 0; #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || ppBlob==0 || zTable==0 ){ + if( ppBlob==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + *ppBlob = 0; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif flags = !!flags; /* flags = (flags ? 1 : 0); */ - *ppBlob = 0; sqlite3_mutex_enter(db->mutex); @@ -76991,7 +77759,7 @@ blob_open_out: ** Close a blob handle that was previously created using ** sqlite3_blob_open(). */ -SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; int rc; sqlite3 *db; @@ -77028,7 +77796,7 @@ static int blobReadWrite( sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; - if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ + if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; }else if( v==0 ){ @@ -77060,14 +77828,14 @@ static int blobReadWrite( /* ** Read data from a blob handle. */ -SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData); } /* ** Write data to a blob handle. */ -SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); } @@ -77077,7 +77845,7 @@ SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int ** The Incrblob.nByte field is fixed for the lifetime of the Incrblob ** so no mutex is required for access. */ -SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; return (p && p->pStmt) ? p->nByte : 0; } @@ -77092,7 +77860,7 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ ** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) ** immediately return SQLITE_ABORT. */ -SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ +SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ int rc; Incrblob *p = (Incrblob *)pBlob; sqlite3 *db; @@ -77417,6 +78185,7 @@ struct MergeEngine { ** after the thread has finished are not dire. So we don't worry about ** memory barriers and such here. */ +typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int); struct SortSubtask { SQLiteThread *pThread; /* Background thread, if any */ int bDone; /* Set if thread is finished but not joined */ @@ -77424,10 +78193,12 @@ struct SortSubtask { UnpackedRecord *pUnpacked; /* Space to unpack a record */ SorterList list; /* List for thread to write to a PMA */ int nPMA; /* Number of PMAs currently in file */ + SorterCompare xCompare; /* Compare function to use */ SorterFile file; /* Temp file for level-0 PMAs */ SorterFile file2; /* Space for other PMAs */ }; + /* ** Main sorter structure. A single instance of this is allocated for each ** sorter cursor created by the VDBE. @@ -77454,9 +78225,13 @@ struct VdbeSorter { u8 bUseThreads; /* True to use background threads */ u8 iPrev; /* Previous thread used to flush PMA */ u8 nTask; /* Size of aTask[] array */ + u8 typeMask; SortSubtask aTask[1]; /* One or more subtasks */ }; +#define SORTER_TYPE_INTEGER 0x01 +#define SORTER_TYPE_TEXT 0x02 + /* ** An instance of the following object is used to read records out of a ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. @@ -77868,32 +78643,162 @@ static int vdbePmaReaderInit( return rc; } +/* +** A version of vdbeSorterCompare() that assumes that it has already been +** determined that the first field of key1 is equal to the first field of +** key2. +*/ +static int vdbeSorterCompareTail( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + UnpackedRecord *r2 = pTask->pUnpacked; + if( *pbKey2Cached==0 ){ + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; + } + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); +} /* ** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, ** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences ** used by the comparison. Return the result of the comparison. ** -** Before returning, object (pTask->pUnpacked) is populated with the -** unpacked version of key2. Or, if pKey2 is passed a NULL pointer, then it -** is assumed that the (pTask->pUnpacked) structure already contains the -** unpacked key to use as key2. +** If IN/OUT parameter *pbKey2Cached is true when this function is called, +** it is assumed that (pTask->pUnpacked) contains the unpacked version +** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked +** version of key2 and *pbKey2Cached set to true before returning. ** ** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set ** to SQLITE_NOMEM. */ static int vdbeSorterCompare( SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ const void *pKey1, int nKey1, /* Left side of comparison */ const void *pKey2, int nKey2 /* Right side of comparison */ ){ UnpackedRecord *r2 = pTask->pUnpacked; - if( pKey2 ){ + if( !*pbKey2Cached ){ sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; } return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); } +/* +** A specially optimized version of vdbeSorterCompare() that assumes that +** the first field of each key is a TEXT value and that the collation +** sequence to compare them with is BINARY. +*/ +static int vdbeSorterCompareText( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + const u8 * const p1 = (const u8 * const)pKey1; + const u8 * const p2 = (const u8 * const)pKey2; + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ + + int n1; + int n2; + int res; + + getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2; + getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2; + res = memcmp(v1, v2, MIN(n1, n2)); + if( res==0 ){ + res = n1 - n2; + } + + if( res==0 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); + } + }else{ + if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + res = res * -1; + } + } + + return res; +} + +/* +** A specially optimized version of vdbeSorterCompare() that assumes that +** the first field of each key is an INTEGER value. +*/ +static int vdbeSorterCompareInt( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + const u8 * const p1 = (const u8 * const)pKey1; + const u8 * const p2 = (const u8 * const)pKey2; + const int s1 = p1[1]; /* Left hand serial type */ + const int s2 = p2[1]; /* Right hand serial type */ + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ + int res; /* Return value */ + + assert( (s1>0 && s1<7) || s1==8 || s1==9 ); + assert( (s2>0 && s2<7) || s2==8 || s2==9 ); + + if( s1>7 && s2>7 ){ + res = s1 - s2; + }else{ + if( s1==s2 ){ + if( (*v1 ^ *v2) & 0x80 ){ + /* The two values have different signs */ + res = (*v1 & 0x80) ? -1 : +1; + }else{ + /* The two values have the same sign. Compare using memcmp(). */ + static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 }; + int i; + res = 0; + for(i=0; i7 ){ + res = +1; + }else if( s1>7 ){ + res = -1; + }else{ + res = s1 - s2; + } + assert( res!=0 ); + + if( res>0 ){ + if( *v1 & 0x80 ) res = -1; + }else{ + if( *v2 & 0x80 ) res = +1; + } + } + } + + if( res==0 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); + } + }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + res = res * -1; + } + + return res; +} + /* ** Initialize the temporary index cursor just opened as a sorter cursor. ** @@ -77961,9 +78866,13 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); pKeyInfo->db = 0; - if( nField && nWorker==0 ) pKeyInfo->nField = nField; + if( nField && nWorker==0 ){ + pKeyInfo->nXField += (pKeyInfo->nField - nField); + pKeyInfo->nField = nField; + } pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); pSorter->nTask = nWorker + 1; + pSorter->iPrev = nWorker-1; pSorter->bUseThreads = (pSorter->nTask>1); pSorter->db = db; for(i=0; inTask; i++){ @@ -77989,6 +78898,12 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM; } } + + if( (pKeyInfo->nField+pKeyInfo->nXField)<13 + && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) + ){ + pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; + } } return rc; @@ -78013,30 +78928,24 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){ */ static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){ sqlite3DbFree(db, pTask->pUnpacked); - pTask->pUnpacked = 0; #if SQLITE_MAX_WORKER_THREADS>0 /* pTask->list.aMemory can only be non-zero if it was handed memory ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */ if( pTask->list.aMemory ){ sqlite3_free(pTask->list.aMemory); - pTask->list.aMemory = 0; }else #endif { assert( pTask->list.aMemory==0 ); vdbeSorterRecordFree(0, pTask->list.pList); } - pTask->list.pList = 0; if( pTask->file.pFd ){ sqlite3OsCloseFree(pTask->file.pFd); - pTask->file.pFd = 0; - pTask->file.iEof = 0; } if( pTask->file2.pFd ){ sqlite3OsCloseFree(pTask->file2.pFd); - pTask->file2.pFd = 0; - pTask->file2.iEof = 0; } + memset(pTask, 0, sizeof(SortSubtask)); } #ifdef SQLITE_DEBUG_SORTER_THREADS @@ -78216,6 +79125,7 @@ SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){ for(i=0; inTask; i++){ SortSubtask *pTask = &pSorter->aTask[i]; vdbeSortSubtaskCleanup(db, pTask); + pTask->pSorter = pSorter; } if( pSorter->list.aMemory==0 ){ vdbeSorterRecordFree(0, pSorter->list.pList); @@ -78277,6 +79187,7 @@ static int vdbeSorterOpenTempFile( sqlite3_file **ppFd ){ int rc; + if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS; rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd, SQLITE_OPEN_TEMP_JOURNAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | @@ -78324,28 +79235,42 @@ static void vdbeSorterMerge( ){ SorterRecord *pFinal = 0; SorterRecord **pp = &pFinal; - void *pVal2 = p2 ? SRVAL(p2) : 0; + int bCached = 0; while( p1 && p2 ){ int res; - res = vdbeSorterCompare(pTask, SRVAL(p1), p1->nVal, pVal2, p2->nVal); + res = pTask->xCompare( + pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal + ); + if( res<=0 ){ *pp = p1; pp = &p1->u.pNext; p1 = p1->u.pNext; - pVal2 = 0; }else{ *pp = p2; - pp = &p2->u.pNext; + pp = &p2->u.pNext; p2 = p2->u.pNext; - if( p2==0 ) break; - pVal2 = SRVAL(p2); + bCached = 0; } } *pp = p1 ? p1 : p2; *ppOut = pFinal; } +/* +** Return the SorterCompare function to compare values collected by the +** sorter object passed as the only argument. +*/ +static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){ + if( p->typeMask==SORTER_TYPE_INTEGER ){ + return vdbeSorterCompareInt; + }else if( p->typeMask==SORTER_TYPE_TEXT ){ + return vdbeSorterCompareText; + } + return vdbeSorterCompare; +} + /* ** Sort the linked list of records headed at pTask->pList. Return ** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if @@ -78360,12 +79285,14 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ rc = vdbeSortAllocUnpacked(pTask); if( rc!=SQLITE_OK ) return rc; + p = pList->pList; + pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter); + aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); if( !aSlot ){ return SQLITE_NOMEM; } - p = pList->pList; while( p ){ SorterRecord *pNext; if( pList->aMemory ){ @@ -78579,13 +79506,12 @@ static int vdbeMergeEngineStep( int i; /* Index of aTree[] to recalculate */ PmaReader *pReadr1; /* First PmaReader to compare */ PmaReader *pReadr2; /* Second PmaReader to compare */ - u8 *pKey2; /* To pReadr2->aKey, or 0 if record cached */ + int bCached = 0; /* Find the first two PmaReaders to compare. The one that was just ** advanced (iPrev) and the one next to it in the array. */ pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)]; pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)]; - pKey2 = pReadr2->aKey; for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){ /* Compare pReadr1 and pReadr2. Store the result in variable iRes. */ @@ -78595,8 +79521,8 @@ static int vdbeMergeEngineStep( }else if( pReadr2->pFd==0 ){ iRes = -1; }else{ - iRes = vdbeSorterCompare(pTask, - pReadr1->aKey, pReadr1->nKey, pKey2, pReadr2->nKey + iRes = pTask->xCompare(pTask, &bCached, + pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey ); } @@ -78618,9 +79544,9 @@ static int vdbeMergeEngineStep( if( iRes<0 || (iRes==0 && pReadr1aTree[i] = (int)(pReadr1 - pMerger->aReadr); pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; - pKey2 = pReadr2->aKey; + bCached = 0; }else{ - if( pReadr1->pFd ) pKey2 = 0; + if( pReadr1->pFd ) bCached = 0; pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr); pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; } @@ -78727,6 +79653,16 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite( int bFlush; /* True to flush contents of memory to PMA */ int nReq; /* Bytes of memory required */ int nPMA; /* Bytes of PMA space required */ + int t; /* serial type of first record field */ + + getVarint32((const u8*)&pVal->z[1], t); + if( t>0 && t<10 && t!=7 ){ + pSorter->typeMask &= SORTER_TYPE_INTEGER; + }else if( t>10 && (t & 0x01) ){ + pSorter->typeMask &= SORTER_TYPE_TEXT; + }else{ + pSorter->typeMask = 0; + } assert( pSorter ); @@ -78992,10 +79928,12 @@ static void vdbeMergeEngineCompare( }else if( p2->pFd==0 ){ iRes = i1; }else{ + SortSubtask *pTask = pMerger->pTask; + int bCached = 0; int res; - assert( pMerger->pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ - res = vdbeSorterCompare( - pMerger->pTask, p1->aKey, p1->nKey, p2->aKey, p2->nKey + assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ + res = pTask->xCompare( + pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey ); if( res<=0 ){ iRes = i1; @@ -79019,11 +79957,12 @@ static void vdbeMergeEngineCompare( #define INCRINIT_TASK 1 #define INCRINIT_ROOT 2 -/* Forward reference. -** The vdbeIncrMergeInit() and vdbePmaReaderIncrMergeInit() routines call each -** other (when building a merge tree). +/* +** Forward reference required as the vdbeIncrMergeInit() and +** vdbePmaReaderIncrInit() routines are called mutually recursively when +** building a merge tree. */ -static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode); +static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode); /* ** Initialize the MergeEngine object passed as the second argument. Once this @@ -79070,7 +80009,7 @@ static int vdbeMergeEngineInit( ** better advantage of multi-processor hardware. */ rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]); }else{ - rc = vdbePmaReaderIncrMergeInit(&pMerger->aReadr[i], INCRINIT_NORMAL); + rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL); } if( rc!=SQLITE_OK ) return rc; } @@ -79082,17 +80021,15 @@ static int vdbeMergeEngineInit( } /* -** Initialize the IncrMerge field of a PmaReader. -** -** If the PmaReader passed as the first argument is not an incremental-reader -** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it serves -** to open and/or initialize the temp file related fields of the IncrMerge +** The PmaReader passed as the first argument is guaranteed to be an +** incremental-reader (pReadr->pIncr!=0). This function serves to open +** and/or initialize the temp file related fields of the IncrMerge ** object at (pReadr->pIncr). ** ** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders -** in the sub-tree headed by pReadr are also initialized. Data is then loaded -** into the buffers belonging to pReadr and it is set to -** point to the first key in its range. +** in the sub-tree headed by pReadr are also initialized. Data is then +** loaded into the buffers belonging to pReadr and it is set to point to +** the first key in its range. ** ** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed ** to be a multi-threaded PmaReader and this function is being called in a @@ -79119,59 +80056,62 @@ static int vdbeMergeEngineInit( static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ int rc = SQLITE_OK; IncrMerger *pIncr = pReadr->pIncr; + SortSubtask *pTask = pIncr->pTask; + sqlite3 *db = pTask->pSorter->db; /* eMode is always INCRINIT_NORMAL in single-threaded mode */ assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); - if( pIncr ){ - SortSubtask *pTask = pIncr->pTask; - sqlite3 *db = pTask->pSorter->db; + rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - - /* Set up the required files for pIncr. A multi-theaded IncrMerge object - ** requires two temp files to itself, whereas a single-threaded object - ** only requires a region of pTask->file2. */ - if( rc==SQLITE_OK ){ - int mxSz = pIncr->mxSz; + /* Set up the required files for pIncr. A multi-theaded IncrMerge object + ** requires two temp files to itself, whereas a single-threaded object + ** only requires a region of pTask->file2. */ + if( rc==SQLITE_OK ){ + int mxSz = pIncr->mxSz; #if SQLITE_MAX_WORKER_THREADS>0 - if( pIncr->bUseThread ){ - rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd); - if( rc==SQLITE_OK ){ - rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd); - } - }else + if( pIncr->bUseThread ){ + rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd); + if( rc==SQLITE_OK ){ + rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd); + } + }else #endif - /*if( !pIncr->bUseThread )*/{ - if( pTask->file2.pFd==0 ){ - assert( pTask->file2.iEof>0 ); - rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd); - pTask->file2.iEof = 0; - } - if( rc==SQLITE_OK ){ - pIncr->aFile[1].pFd = pTask->file2.pFd; - pIncr->iStartOff = pTask->file2.iEof; - pTask->file2.iEof += mxSz; - } + /*if( !pIncr->bUseThread )*/{ + if( pTask->file2.pFd==0 ){ + assert( pTask->file2.iEof>0 ); + rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd); + pTask->file2.iEof = 0; + } + if( rc==SQLITE_OK ){ + pIncr->aFile[1].pFd = pTask->file2.pFd; + pIncr->iStartOff = pTask->file2.iEof; + pTask->file2.iEof += mxSz; } } + } #if SQLITE_MAX_WORKER_THREADS>0 - if( rc==SQLITE_OK && pIncr->bUseThread ){ - /* Use the current thread to populate aFile[1], even though this - ** PmaReader is multi-threaded. The reason being that this function - ** is already running in background thread pIncr->pTask->thread. */ - assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK ); - rc = vdbeIncrPopulate(pIncr); - } + if( rc==SQLITE_OK && pIncr->bUseThread ){ + /* Use the current thread to populate aFile[1], even though this + ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object, + ** then this function is already running in background thread + ** pIncr->pTask->thread. + ** + ** If this is the INCRINIT_ROOT object, then it is running in the + ** main VDBE thread. But that is Ok, as that thread cannot return + ** control to the VDBE or proceed with anything useful until the + ** first results are ready from this merger object anyway. + */ + assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK ); + rc = vdbeIncrPopulate(pIncr); + } #endif - if( rc==SQLITE_OK - && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) - ){ - rc = vdbePmaReaderNext(pReadr); - } + if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){ + rc = vdbePmaReaderNext(pReadr); } + return rc; } @@ -79180,7 +80120,7 @@ static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ ** The main routine for vdbePmaReaderIncrMergeInit() operations run in ** background threads. */ -static void *vdbePmaReaderBgInit(void *pCtx){ +static void *vdbePmaReaderBgIncrInit(void *pCtx){ PmaReader *pReader = (PmaReader*)pCtx; void *pRet = SQLITE_INT_TO_PTR( vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK) @@ -79188,20 +80128,36 @@ static void *vdbePmaReaderBgInit(void *pCtx){ pReader->pIncr->pTask->bDone = 1; return pRet; } +#endif /* -** Use a background thread to invoke vdbePmaReaderIncrMergeInit(INCRINIT_TASK) -** on the PmaReader object passed as the first argument. -** -** This call will initialize the various fields of the pReadr->pIncr -** structure and, if it is a multi-threaded IncrMerger, launch a -** background thread to populate aFile[1]. +** If the PmaReader passed as the first argument is not an incremental-reader +** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes +** the vdbePmaReaderIncrMergeInit() function with the parameters passed to +** this routine to initialize the incremental merge. +** +** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1), +** then a background thread is launched to call vdbePmaReaderIncrMergeInit(). +** Or, if the IncrMerger is single threaded, the same function is called +** using the current thread. */ -static int vdbePmaReaderBgIncrInit(PmaReader *pReadr){ - void *pCtx = (void*)pReadr; - return vdbeSorterCreateThread(pReadr->pIncr->pTask, vdbePmaReaderBgInit, pCtx); -} +static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){ + IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */ + int rc = SQLITE_OK; /* Return code */ + if( pIncr ){ +#if SQLITE_MAX_WORKER_THREADS>0 + assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK ); + if( pIncr->bUseThread ){ + void *pCtx = (void*)pReadr; + rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx); + }else #endif + { + rc = vdbePmaReaderIncrMergeInit(pReadr, eMode); + } + } + return rc; +} /* ** Allocate a new MergeEngine object to merge the contents of nPMA level-0 @@ -79413,6 +80369,11 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ MergeEngine *pMain = 0; #if SQLITE_MAX_WORKER_THREADS sqlite3 *db = pTask0->pSorter->db; + int i; + SorterCompare xCompare = vdbeSorterGetCompare(pSorter); + for(i=0; inTask; i++){ + pSorter->aTask[i].xCompare = xCompare; + } #endif rc = vdbeSorterMergeTreeBuild(pSorter, &pMain); @@ -79441,15 +80402,21 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ } } for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ + /* Check that: + ** + ** a) The incremental merge object is configured to use the + ** right task, and + ** b) If it is using task (nTask-1), it is configured to run + ** in single-threaded mode. This is important, as the + ** root merge (INCRINIT_ROOT) will be using the same task + ** object. + */ PmaReader *p = &pMain->aReadr[iTask]; - assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] ); - if( p->pIncr ){ - if( iTask==pSorter->nTask-1 ){ - rc = vdbePmaReaderIncrMergeInit(p, INCRINIT_TASK); - }else{ - rc = vdbePmaReaderBgIncrInit(p); - } - } + assert( p->pIncr==0 || ( + (p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */ + && (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */ + )); + rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK); } } pMain = 0; @@ -80404,7 +81371,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){ ** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; ** ** The nSubquery parameter specifies how many levels of subquery the -** alias is removed from the original expression. The usually value is +** alias is removed from the original expression. The usual value is ** zero but it might be more if the alias is contained within a subquery ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION ** structures must be increased by the nSubquery amount. @@ -80424,7 +81391,6 @@ static void resolveAlias( assert( iCol>=0 && iColnExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); - assert( pOrig->flags & EP_Resolved ); db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); if( pDup==0 ) return; @@ -80572,9 +81538,10 @@ static int lookupName( testcase( pNC->ncFlags & NC_PartIdx ); testcase( pNC->ncFlags & NC_IsCheck ); if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){ - /* Silently ignore database qualifiers inside CHECK constraints and partial - ** indices. Do not raise errors because that might break legacy and - ** because it does not hurt anything to just ignore the database name. */ + /* Silently ignore database qualifiers inside CHECK constraints and + ** partial indices. Do not raise errors because that might break + ** legacy and because it does not hurt anything to just ignore the + ** database name. */ zDb = 0; }else{ for(i=0; inDb; i++){ @@ -80645,7 +81612,8 @@ static int lookupName( if( pMatch ){ pExpr->iTable = pMatch->iCursor; pExpr->pTab = pMatch->pTab; - assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */ + /* RIGHT JOIN not (yet) supported */ + assert( (pMatch->jointype & JT_RIGHT)==0 ); if( (pMatch->jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } @@ -80966,7 +81934,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->affinity = SQLITE_AFF_INTEGER; break; } -#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ +#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) + && !defined(SQLITE_OMIT_SUBQUERY) */ /* A lone identifier is the name of a column. */ @@ -81031,19 +82000,20 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ if( n==2 ){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ - sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a " - "constant between 0.0 and 1.0"); + sqlite3ErrorMsg(pParse, + "second argument to likelihood() must be a " + "constant between 0.0 and 1.0"); pNC->nErr++; } }else{ - /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to - ** likelihood(X, 0.0625). - ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for - ** likelihood(X,0.0625). - ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for - ** likelihood(X,0.9375). - ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to - ** likelihood(X,0.9375). */ + /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is + ** equivalent to likelihood(X, 0.0625). + ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is + ** short-hand for likelihood(X,0.0625). + ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand + ** for likelihood(X,0.9375). + ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent + ** to likelihood(X,0.9375). */ /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */ pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120; } @@ -81060,7 +82030,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ return WRC_Prune; } #endif - if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant); + if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ){ + ExprSetProperty(pExpr,EP_ConstFunc); + } } if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); @@ -81312,9 +82284,11 @@ static int resolveCompoundOrderBy( if( pItem->pExpr==pE ){ pItem->pExpr = pNew; }else{ - assert( pItem->pExpr->op==TK_COLLATE ); - assert( pItem->pExpr->pLeft==pE ); - pItem->pExpr->pLeft = pNew; + Expr *pParent = pItem->pExpr; + assert( pParent->op==TK_COLLATE ); + while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft; + assert( pParent->pLeft==pE ); + pParent->pLeft = pNew; } sqlite3ExprDelete(db, pE); pItem->u.x.iOrderByCol = (u16)iCol; @@ -81371,7 +82345,8 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy( resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); return 1; } - resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0); + resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, + zType,0); } } return 0; @@ -81504,6 +82479,20 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } + + /* If the SF_Converted flags is set, then this Select object was + ** was created by the convertCompoundSelectToSubquery() function. + ** In this case the ORDER BY clause (p->pOrderBy) should be resolved + ** as if it were part of the sub-query, not the parent. This block + ** moves the pOrderBy down to the sub-query. It will be moved back + ** after the names have been resolved. */ + if( p->selFlags & SF_Converted ){ + Select *pSub = p->pSrc->a[0].pSelect; + assert( p->pSrc->nSrc==1 && p->pOrderBy ); + assert( pSub->pPrior && pSub->pOrderBy==0 ); + pSub->pOrderBy = p->pOrderBy; + p->pOrderBy = 0; + } /* Recursively resolve names in all subqueries */ @@ -81586,12 +82575,30 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ sNC.pNext = 0; sNC.ncFlags |= NC_AllowAgg; + /* If this is a converted compound query, move the ORDER BY clause from + ** the sub-query back to the parent query. At this point each term + ** within the ORDER BY clause has been transformed to an integer value. + ** These integers will be replaced by copies of the corresponding result + ** set expressions by the call to resolveOrderGroupBy() below. */ + if( p->selFlags & SF_Converted ){ + Select *pSub = p->pSrc->a[0].pSelect; + p->pOrderBy = pSub->pOrderBy; + pSub->pOrderBy = 0; + } + /* Process the ORDER BY clause for singleton SELECT statements. ** The ORDER BY clause for compounds SELECT statements is handled ** below, after all of the result-sets for all of the elements of ** the compound have been resolved. + ** + ** If there is an ORDER BY clause on a term of a compound-select other + ** than the right-most term, then that is a syntax error. But the error + ** is not detected until much later, and so we need to go ahead and + ** resolve those symbols on the incorrect ORDER BY for consistency. */ - if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){ + if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */ + && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") + ){ return WRC_Abort; } if( db->mallocFailed ){ @@ -81861,10 +82868,11 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken( Parse *pParse, /* Parsing context */ Expr *pExpr, /* Add the "COLLATE" clause to this expression */ - const Token *pCollName /* Name of collating sequence */ + const Token *pCollName, /* Name of collating sequence */ + int dequote /* True to dequote pCollName */ ){ if( pCollName->n>0 ){ - Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote); if( pNew ){ pNew->pLeft = pExpr; pNew->flags |= EP_Collate|EP_Skip; @@ -81878,7 +82886,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, con assert( zC!=0 ); s.z = zC; s.n = sqlite3Strlen30(s.z); - return sqlite3ExprAddCollateToken(pParse, pExpr, &s); + return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); } /* @@ -81924,9 +82932,9 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); break; } - if( p->pTab!=0 - && (op==TK_AGG_COLUMN || op==TK_COLUMN + if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER) + && p->pTab!=0 ){ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ @@ -81938,10 +82946,25 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ break; } if( p->flags & EP_Collate ){ - if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ + if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ - p = p->pRight; + Expr *pNext = p->pRight; + /* The Expr.x union is never used at the same time as Expr.pRight */ + assert( p->x.pList==0 || p->pRight==0 ); + /* p->flags holds EP_Collate and p->pLeft->flags does not. And + ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at + ** least one EP_Collate. Thus the following two ALWAYS. */ + if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){ + int i; + for(i=0; ALWAYS(ix.pList->nExpr); i++){ + if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ + pNext = p->x.pList->a[i].pExpr; + break; + } + } + } + p = pNext; } }else{ break; @@ -82147,6 +83170,9 @@ static void heightOfSelect(Select *p, int *pnHeight){ ** Expr.pSelect member has a height of 1. Any other expression ** has a height equal to the maximum height of any other ** referenced Expr plus one. +** +** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, +** if appropriate. */ static void exprSetHeight(Expr *p){ int nHeight = 0; @@ -82154,8 +83180,9 @@ static void exprSetHeight(Expr *p){ heightOfExpr(p->pRight, &nHeight); if( ExprHasProperty(p, EP_xIsSelect) ){ heightOfSelect(p->x.pSelect, &nHeight); - }else{ + }else if( p->x.pList ){ heightOfExprList(p->x.pList, &nHeight); + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } p->nHeight = nHeight + 1; } @@ -82164,8 +83191,12 @@ static void exprSetHeight(Expr *p){ ** Set the Expr.nHeight variable using the exprSetHeight() function. If ** the height is greater than the maximum allowed expression depth, ** leave an error in pParse. +** +** Also propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. */ -SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){ +SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + if( pParse->nErr ) return; exprSetHeight(p); sqlite3ExprCheckHeight(pParse, p->nHeight); } @@ -82179,8 +83210,17 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){ heightOfSelect(p, &nHeight); return nHeight; } -#else - #define exprSetHeight(y) +#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ +/* +** Propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. +*/ +SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); + } +} +#define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ /* @@ -82282,11 +83322,11 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees( }else{ if( pRight ){ pRoot->pRight = pRight; - pRoot->flags |= EP_Collate & pRight->flags; + pRoot->flags |= EP_Propagate & pRight->flags; } if( pLeft ){ pRoot->pLeft = pLeft; - pRoot->flags |= EP_Collate & pLeft->flags; + pRoot->flags |= EP_Propagate & pLeft->flags; } exprSetHeight(pRoot); } @@ -82386,7 +83426,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token * } pNew->x.pList = pList; assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - sqlite3ExprSetHeight(pParse, pNew); + sqlite3ExprSetHeightAndFlags(pParse, pNew); return pNew; } @@ -83001,6 +84041,22 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ sqlite3DbFree(db, pList); } +/* +** Return the bitwise-OR of all Expr.flags fields in the given +** ExprList. +*/ +SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){ + int i; + u32 m = 0; + if( pList ){ + for(i=0; inExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + if( ALWAYS(pExpr) ) m |= pExpr->flags; + } + } + return m; +} + /* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The @@ -83041,7 +84097,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ ** and either pWalker->eCode==4 or 5 or the function has the ** SQLITE_FUNC_CONST flag. */ case TK_FUNCTION: - if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_Constant) ){ + if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){ return WRC_Continue; }else{ pWalker->eCode = 0; @@ -83435,7 +84491,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int ** ephemeral table. */ p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); - if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){ + if( pParse->nErr==0 && isCandidateForInOpt(p) ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table . */ Expr *pExpr; /* Expression */ @@ -83760,6 +84816,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[1]); pSel->iLimit = 0; + pSel->selFlags &= ~SF_MultiValue; if( sqlite3Select(pParse, pSel, &dest) ){ return 0; } @@ -84048,7 +85105,8 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int int idxLru; struct yColCache *p; - assert( iReg>0 ); /* Register numbers are always positive */ + /* Unless an error has occurred, register numbers are always positive. */ + assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed ); assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ /* The SQLITE_ColumnCache flag disables the column cache. This is used @@ -85124,7 +86182,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m break; } case TK_ID: { - sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken); + sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken); break; } #ifndef SQLITE_OMIT_CAST @@ -85759,7 +86817,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2; if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; - if( ALWAYS((combinedFlags & EP_Reduced)==0) ){ + if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ if( pA->iColumn!=pB->iColumn ) return 2; if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; @@ -86291,6 +87349,7 @@ static void renameParentFunc( n = sqlite3GetToken(z, &token); }while( token==TK_SPACE ); + if( token==TK_ILLEGAL ) break; zParent = sqlite3DbStrNDup(db, (const char *)z, n); if( zParent==0 ) break; sqlite3Dequote(zParent); @@ -86855,7 +87914,10 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ */ if( pDflt ){ sqlite3_value *pVal = 0; - if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){ + int rc; + rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + if( rc!=SQLITE_OK ){ db->mallocFailed = 1; return; } @@ -88514,14 +89576,17 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ z = argv[2]; if( pIndex ){ + tRowcnt *aiRowEst = 0; int nCol = pIndex->nKeyCol+1; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero( - sizeof(tRowcnt) * nCol - ); - if( aiRowEst==0 ) pInfo->db->mallocFailed = 1; -#else - tRowcnt * const aiRowEst = 0; + /* Index.aiRowEst may already be set here if there are duplicate + ** sqlite_stat1 entries for this index. In that case just clobber + ** the old data with the new instead of allocating a new array. */ + if( pIndex->aiRowEst==0 ){ + pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); + if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1; + } + aiRowEst = pIndex->aiRowEst; #endif pIndex->bUnordered = 0; decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); @@ -89077,7 +90142,7 @@ static void attachFunc( case SQLITE_NULL: /* No key specified. Use the key from the main database */ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){ + if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); } break; @@ -89184,7 +90249,7 @@ static void detachFunc( sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; - sqlite3ResetAllSchemasOfConnection(db); + sqlite3CollapseDatabaseArray(db); return; detach_error: @@ -89218,7 +90283,6 @@ static void codeAttach( SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) ){ - pParse->nErr++; goto attach_end; } @@ -89540,7 +90604,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( ** Setting the auth function to NULL disables this hook. The default ** setting of the auth function is NULL. */ -SQLITE_API int sqlite3_set_authorizer( +SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( sqlite3 *db, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pArg @@ -89877,9 +90941,11 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ assert( pParse->pToplevel==0 ); db = pParse->db; - if( db->mallocFailed ) return; if( pParse->nested ) return; - if( pParse->nErr ) return; + if( db->mallocFailed || pParse->nErr ){ + if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR; + return; + } /* Begin by generating some termination code at the end of the ** vdbe program @@ -89961,7 +91027,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ /* Get the VDBE program ready for execution */ - if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){ + if( v && pParse->nErr==0 && !db->mallocFailed ){ assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ /* A minimum of one cursor is required if autoincrement is used * See ticket [a696379c1f08866] */ @@ -90043,10 +91109,6 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha Table *p = 0; int i; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return 0; -#endif - /* All mutexes are required for schema access. Make sure we hold them. */ assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); #if SQLITE_USER_AUTHENTICATION @@ -90500,14 +91562,12 @@ SQLITE_PRIVATE int sqlite3TwoPartName( if( ALWAYS(pName2!=0) && pName2->n>0 ){ if( db->init.busy ) { sqlite3ErrorMsg(pParse, "corrupt database"); - pParse->nErr++; return -1; } *pUnqual = pName2; iDb = sqlite3FindDb(db, pName1); if( iDb<0 ){ sqlite3ErrorMsg(pParse, "unknown database %T", pName1); - pParse->nErr++; return -1; } }else{ @@ -90666,7 +91726,7 @@ SQLITE_PRIVATE void sqlite3StartTable( if( !noErr ){ sqlite3ErrorMsg(pParse, "table %T already exists", pName); }else{ - assert( !db->init.busy ); + assert( !db->init.busy || CORRUPT_DB ); sqlite3CodeVerifySchema(pParse, iDb); } goto begin_table_error; @@ -90955,7 +92015,8 @@ SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){ p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; pCol = &p->aCol[p->nCol-1]; - assert( pCol->zType==0 ); + assert( pCol->zType==0 || CORRUPT_DB ); + sqlite3DbFree(pParse->db, pCol->zType); pCol->zType = sqlite3NameFromToken(pParse->db, pType); pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); } @@ -91466,11 +92527,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ assert( pPk!=0 ); nPk = pPk->nKeyCol; - /* Make sure every column of the PRIMARY KEY is NOT NULL */ - for(i=0; iaCol[pPk->aiColumn[i]].notNull = 1; + /* Make sure every column of the PRIMARY KEY is NOT NULL. (Except, + ** do not enforce this for imposter tables.) */ + if( !db->init.imposterTable ){ + for(i=0; iaCol[pPk->aiColumn[i]].notNull = 1; + } + pPk->uniqNotNull = 1; } - pPk->uniqNotNull = 1; /* The root page of the PRIMARY KEY is the table root page */ pPk->tnum = pTab->tnum; @@ -92186,6 +93250,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, } assert( pParse->nErr==0 ); assert( pName->nSrc==1 ); + if( sqlite3ReadSchema(pParse) ) goto exit_drop_table; if( noErr ) db->suppressErr++; pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; @@ -92499,7 +93564,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); + sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); + sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); @@ -92592,8 +93658,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( char *zExtra = 0; /* Extra space after the Index object */ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ - assert( pParse->nErr==0 ); /* Never called with prior errors */ - if( db->mallocFailed || IN_DECLARE_VTAB ){ + if( db->mallocFailed || IN_DECLARE_VTAB || pParse->nErr>0 ){ goto exit_create_index; } if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ @@ -92919,6 +93984,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( pIdx->onError = pIndex->onError; } } + pRet = pIdx; goto exit_create_index; } } @@ -93511,7 +94577,6 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){ if( p ){ int i; - assert( p->a || p->nSrc==0 ); for(i=p->nSrc-1; i>0; i--){ p->a[i].jointype = p->a[i-1].jointype; } @@ -93758,8 +94823,7 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint( StrAccum errMsg; Table *pTab = pIdx->pTable; - sqlite3StrAccumInit(&errMsg, 0, 0, 200); - errMsg.db = pParse->db; + sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); for(j=0; jnKeyCol; j++){ char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); @@ -94705,7 +95769,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( pInClause->x.pSelect = pSelect; pInClause->flags |= EP_xIsSelect; - sqlite3ExprSetHeight(pParse, pInClause); + sqlite3ExprSetHeightAndFlags(pParse, pInClause); return pInClause; /* something went wrong. clean up anything allocated. */ @@ -95378,7 +96442,9 @@ SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ ** Return the collating function associated with a function. */ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ - VdbeOp *pOp = &context->pVdbe->aOp[context->iOp-1]; + VdbeOp *pOp; + assert( context->pVdbe!=0 ); + pOp = &context->pVdbe->aOp[context->iOp-1]; assert( pOp->opcode==OP_CollSeq ); assert( pOp->p4type==P4_COLLSEQ ); return pOp->p4.pColl; @@ -95586,13 +96652,13 @@ static void printfFunc( StrAccum str; const char *zFormat; int n; + sqlite3 *db = sqlite3_context_db_handle(context); if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ x.nArg = argc-1; x.nUsed = 0; x.apArg = argv+1; - sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH); - str.db = sqlite3_context_db_handle(context); + sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); n = str.nChar; sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, @@ -95647,6 +96713,14 @@ static void substrFunc( } } } +#ifdef SQLITE_SUBSTR_COMPATIBILITY + /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as + ** as substr(X,1,N) - it returns the first N characters of X. This + ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8] + ** from 2009-02-02 for compatibility of applications that exploited the + ** old buggy behavior. */ + if( p1==0 ) p1 = 1; /* */ +#endif if( argc==3 ){ p2 = sqlite3_value_int(argv[2]); if( p2<0 ){ @@ -95734,7 +96808,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ #endif /* -** Allocate nByte bytes of space using sqlite3_malloc(). If the +** Allocate nByte bytes of space using sqlite3Malloc(). If the ** allocation fails, call sqlite3_result_error_nomem() to notify ** the database handle that malloc() has failed and return NULL. ** If nByte is larger than the maximum string or blob length, then @@ -96108,7 +97182,7 @@ static int patternCompare( /* ** The sqlite3_strglob() interface. */ -SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ +SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlobPattern, const char *zString){ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0; } @@ -96403,7 +97477,7 @@ static void charFunc( ){ unsigned char *z, *zOut; int i; - zOut = z = sqlite3_malloc( argc*4+1 ); + zOut = z = sqlite3_malloc64( argc*4+1 ); if( z==0 ){ sqlite3_result_error_nomem(context); return; @@ -96551,7 +97625,7 @@ static void replaceFunc( return; } zOld = zOut; - zOut = sqlite3_realloc(zOut, (int)nOut); + zOut = sqlite3_realloc64(zOut, (int)nOut); if( zOut==0 ){ sqlite3_result_error_nomem(context); sqlite3_free(zOld); @@ -96913,8 +97987,7 @@ static void groupConcatStep( if( pAccum ){ sqlite3 *db = sqlite3_context_db_handle(context); - int firstTerm = pAccum->useMalloc==0; - pAccum->useMalloc = 2; + int firstTerm = pAccum->mxAlloc==0; pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; if( !firstTerm ){ if( argc==2 ){ @@ -96998,6 +98071,11 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive) ** then set aWc[0] through aWc[2] to the wildcard characters and ** return TRUE. If the function is not a LIKE-style function then ** return FALSE. +** +** *pIsNocase is set to true if uppercase and lowercase are equivalent for +** the function (default for LIKE). If the function makes the distinction +** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to +** false. */ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ FuncDef *pDef; @@ -98329,7 +99407,8 @@ static Trigger *fkActionTrigger( iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iFromCol>=0 ); - tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid"; + assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKeynCol) ); + tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; tToCol.n = sqlite3Strlen30(tToCol.z); @@ -98341,10 +99420,10 @@ static Trigger *fkActionTrigger( ** parent table are used for the comparison. */ pEq = sqlite3PExpr(pParse, TK_EQ, sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) + sqlite3ExprAlloc(db, TK_ID, &tOld, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) , 0), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol) + sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) , 0); pWhere = sqlite3ExprAnd(db, pWhere, pEq); @@ -98356,12 +99435,12 @@ static Trigger *fkActionTrigger( if( pChanges ){ pEq = sqlite3PExpr(pParse, TK_IS, sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), + sqlite3ExprAlloc(db, TK_ID, &tOld, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), 0), sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), + sqlite3ExprAlloc(db, TK_ID, &tNew, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), 0), 0); pWhen = sqlite3ExprAnd(db, pWhen, pEq); @@ -98371,8 +99450,8 @@ static Trigger *fkActionTrigger( Expr *pNew; if( action==OE_Cascade ){ pNew = sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) + sqlite3ExprAlloc(db, TK_ID, &tNew, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) , 0); }else if( action==OE_SetDflt ){ Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; @@ -98419,13 +99498,12 @@ static Trigger *fkActionTrigger( pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ sizeof(TriggerStep) + /* Single step in trigger program */ - nFrom + 1 /* Space for pStep->target.z */ + nFrom + 1 /* Space for pStep->zTarget */ ); if( pTrigger ){ pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; - pStep->target.z = (char *)&pStep[1]; - pStep->target.n = nFrom; - memcpy((char *)pStep->target.z, zFrom, nFrom); + pStep->zTarget = (char *)&pStep[1]; + memcpy((char *)pStep->zTarget, zFrom, nFrom); pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); @@ -98890,20 +99968,23 @@ static int xferOptimization( /* ** This routine is called to handle SQL of the following forms: ** -** insert into TABLE (IDLIST) values(EXPRLIST) +** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),... ** insert into TABLE (IDLIST) select +** insert into TABLE (IDLIST) default values ** ** The IDLIST following the table name is always optional. If omitted, -** then a list of all columns for the table is substituted. The IDLIST -** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted. +** then a list of all (non-hidden) columns for the table is substituted. +** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST +** is omitted. ** -** The pList parameter holds EXPRLIST in the first form of the INSERT -** statement above, and pSelect is NULL. For the second form, pList is -** NULL and pSelect is a pointer to the select statement used to generate -** data for the insert. +** For the pSelect parameter holds the values to be inserted for the +** first two forms shown above. A VALUES clause is really just short-hand +** for a SELECT statement that omits the FROM clause and everything else +** that follows. If the pSelect parameter is NULL, that means that the +** DEFAULT VALUES form of the INSERT statement is intended. ** ** The code generated follows one of four templates. For a simple -** insert with data coming from a VALUES clause, the code executes +** insert with data coming from a single-row VALUES clause, the code executes ** once straight down through. Pseudo-code follows (we call this ** the "1st template"): ** @@ -99010,7 +100091,7 @@ SQLITE_PRIVATE void sqlite3Insert( u8 useTempTable = 0; /* Store SELECT results in intermediate table */ u8 appendFlag = 0; /* True if the insert is likely to be an append */ u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ - u8 bIdListInOrder = 1; /* True if IDLIST is in table order */ + u8 bIdListInOrder; /* True if IDLIST is in table order */ ExprList *pList = 0; /* List of VALUES() to be inserted */ /* Register allocations */ @@ -99035,8 +100116,8 @@ SQLITE_PRIVATE void sqlite3Insert( } /* If the Select object is really just a simple VALUES() list with a - ** single row values (the common case) then keep that one row of values - ** and go ahead and discard the Select object + ** single row (the common case) then keep that one row of values + ** and discard the other (unused) parts of the pSelect object */ if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){ pList = pSelect->pEList; @@ -99144,6 +100225,7 @@ SQLITE_PRIVATE void sqlite3Insert( ** is appears in the original table. (The index of the INTEGER ** PRIMARY KEY in the original table is pTab->iPKey.) */ + bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0; if( pColumn ){ for(i=0; inId; i++){ pColumn->a[i].idx = -1; @@ -99179,7 +100261,8 @@ SQLITE_PRIVATE void sqlite3Insert( ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ - /* Data is coming from a SELECT. Generate a co-routine to run the SELECT */ + /* Data is coming from a SELECT or from a multi-row VALUES clause. + ** Generate a co-routine to run the SELECT. */ int regYield; /* Register holding co-routine entry-point */ int addrTop; /* Top of the co-routine */ int rc; /* Result code */ @@ -99192,8 +100275,7 @@ SQLITE_PRIVATE void sqlite3Insert( dest.nSdst = pTab->nCol; rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; - assert( pParse->nErr==0 || rc ); - if( rc || db->mallocFailed ) goto insert_cleanup; + if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); @@ -99241,8 +100323,8 @@ SQLITE_PRIVATE void sqlite3Insert( sqlite3ReleaseTempReg(pParse, regTempRowid); } }else{ - /* This is the case if the data for the INSERT is coming from a VALUES - ** clause + /* This is the case if the data for the INSERT is coming from a + ** single-row VALUES clause */ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); @@ -100313,6 +101395,7 @@ static int xferOptimization( int onError, /* How to handle constraint errors */ int iDbDest /* The database of pDest */ ){ + sqlite3 *db = pParse->db; ExprList *pEList; /* The result set of the SELECT */ Table *pSrc; /* The table in the FROM clause of SELECT */ Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ @@ -100460,11 +101543,11 @@ static int xferOptimization( ** the extra complication to make this rule less restrictive is probably ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ - if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ + if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ return 0; } #endif - if( (pParse->db->flags & SQLITE_CountRows)!=0 ){ + if( (db->flags & SQLITE_CountRows)!=0 ){ return 0; /* xfer opt does not play well with PRAGMA count_changes */ } @@ -100475,7 +101558,7 @@ static int xferOptimization( #ifdef SQLITE_TEST sqlite3_xferopt_count++; #endif - iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); + iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; @@ -100485,14 +101568,18 @@ static int xferOptimization( regRowid = sqlite3GetTempReg(pParse); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); assert( HasRowid(pDest) || destHasUniqueIdx ); - if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ + if( (db->flags & SQLITE_Vacuum)==0 && ( + (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ || destHasUniqueIdx /* (2) */ || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ - ){ + )){ /* In some circumstances, we are able to run the xfer optimization - ** only if the destination table is initially empty. This code makes - ** that determination. Conditions under which the destination must - ** be empty: + ** only if the destination table is initially empty. Unless the + ** SQLITE_Vacuum flag is set, this block generates code to make + ** that determination. If SQLITE_Vacuum is set, then the destination + ** table is always empty. + ** + ** Conditions under which the destination must be empty: ** ** (1) There is no INTEGER PRIMARY KEY but there are indices. ** (If the destination is not initially empty, the rowid fields @@ -100535,6 +101622,7 @@ static int xferOptimization( sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + u8 useSeekResult = 0; for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } @@ -100548,7 +101636,33 @@ static int xferOptimization( VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); + if( db->flags & SQLITE_Vacuum ){ + /* This INSERT command is part of a VACUUM operation, which guarantees + ** that the destination table is empty. If all indexed columns use + ** collation sequence BINARY, then it can also be assumed that the + ** index will be populated by inserting keys in strictly sorted + ** order. In this case, instead of seeking within the b-tree as part + ** of every OP_IdxInsert opcode, an OP_Last is added before the + ** OP_IdxInsert to seek to the point within the b-tree where each key + ** should be inserted. This is faster. + ** + ** If any of the indexed columns use a collation sequence other than + ** BINARY, this optimization is disabled. This is because the user + ** might change the definition of a collation sequence and then run + ** a VACUUM command. In that case keys may not be written in strictly + ** sorted order. */ + for(i=0; inColumn; i++){ + char *zColl = pSrcIdx->azColl[i]; + assert( zColl!=0 ); + if( sqlite3_stricmp("BINARY", zColl) ) break; + } + if( i==pSrcIdx->nColumn ){ + useSeekResult = OPFLAG_USESEEKRESULT; + sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + } + } sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); + sqlite3VdbeChangeP5(v, useSeekResult); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); @@ -100598,7 +101712,7 @@ static int xferOptimization( ** argument to xCallback(). If xCallback=NULL then no callback ** is invoked, even for queries. */ -SQLITE_API int sqlite3_exec( +SQLITE_API int SQLITE_STDCALL sqlite3_exec( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /* Invoke this callback routine */ @@ -101667,7 +102781,7 @@ static int sqlite3LoadExtension( const char *zEntry; char *zAltEntry = 0; void **aHandle; - int nMsg = 300 + sqlite3Strlen30(zFile); + u64 nMsg = 300 + sqlite3Strlen30(zFile); int ii; /* Shared library endings to try if zFile cannot be loaded as written */ @@ -101710,7 +102824,7 @@ static int sqlite3LoadExtension( #endif if( handle==0 ){ if( pzErrMsg ){ - *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); + *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "unable to open shared library [%s]", zFile); @@ -101736,7 +102850,7 @@ static int sqlite3LoadExtension( if( xInit==0 && zProc==0 ){ int iFile, iEntry, c; int ncFile = sqlite3Strlen30(zFile); - zAltEntry = sqlite3_malloc(ncFile+30); + zAltEntry = sqlite3_malloc64(ncFile+30); if( zAltEntry==0 ){ sqlite3OsDlClose(pVfs, handle); return SQLITE_NOMEM; @@ -101758,7 +102872,7 @@ static int sqlite3LoadExtension( if( xInit==0 ){ if( pzErrMsg ){ nMsg += sqlite3Strlen30(zEntry); - *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); + *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "no entry point [%s] in shared library [%s]", zEntry, zFile); @@ -101793,7 +102907,7 @@ static int sqlite3LoadExtension( db->aExtension[db->nExtension++] = handle; return SQLITE_OK; } -SQLITE_API int sqlite3_load_extension( +SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ @@ -101824,7 +102938,7 @@ SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){ ** Enable or disable extension loading. Extension loading is disabled by ** default so as not to open security holes in older applications. */ -SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ +SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff){ sqlite3_mutex_enter(db->mutex); if( onoff ){ db->flags |= SQLITE_LoadExtension; @@ -101857,7 +102971,7 @@ static const sqlite3_api_routines sqlite3Apis = { 0 }; */ typedef struct sqlite3AutoExtList sqlite3AutoExtList; static SQLITE_WSD struct sqlite3AutoExtList { - int nExt; /* Number of entries in aExt[] */ + u32 nExt; /* Number of entries in aExt[] */ void (**aExt)(void); /* Pointers to the extension init functions */ } sqlite3Autoext = { 0, 0 }; @@ -101881,7 +102995,7 @@ static SQLITE_WSD struct sqlite3AutoExtList { ** Register a statically linked extension that is automatically ** loaded by every new database connection. */ -SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){ +SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xInit)(void)){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); @@ -101890,7 +103004,7 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){ }else #endif { - int i; + u32 i; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -101900,9 +103014,9 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){ if( wsdAutoext.aExt[i]==xInit ) break; } if( i==wsdAutoext.nExt ){ - int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]); + u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]); void (**aNew)(void); - aNew = sqlite3_realloc(wsdAutoext.aExt, nByte); + aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte); if( aNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -101926,7 +103040,7 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){ ** Return 1 if xInit was found on the list and removed. Return 0 if xInit ** was not on the list. */ -SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){ +SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xInit)(void)){ #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -101934,7 +103048,7 @@ SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){ int n = 0; wsdAutoextInit; sqlite3_mutex_enter(mutex); - for(i=wsdAutoext.nExt-1; i>=0; i--){ + for(i=(int)wsdAutoext.nExt-1; i>=0; i--){ if( wsdAutoext.aExt[i]==xInit ){ wsdAutoext.nExt--; wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt]; @@ -101949,7 +103063,7 @@ SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){ /* ** Reset the automatic extension loading mechanism. */ -SQLITE_API void sqlite3_reset_auto_extension(void){ +SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize()==SQLITE_OK ) #endif @@ -101972,7 +103086,7 @@ SQLITE_API void sqlite3_reset_auto_extension(void){ ** If anything goes wrong, set an error in the database connection. */ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ - int i; + u32 i; int go = 1; int rc; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); @@ -102031,11 +103145,18 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ #endif /*************************************************************************** -** The next block of code, including the PragTyp_XXXX macro definitions and -** the aPragmaName[] object is composed of generated code. DO NOT EDIT. -** -** To add new pragmas, edit the code in ../tool/mkpragmatab.tcl and rerun -** that script. Then copy/paste the output in place of the following: +** The "pragma.h" include file is an automatically generated file that +** that includes the PragType_XXXX macro definitions and the aPragmaName[] +** object. This ensures that the aPragmaName[] table is arranged in +** lexicographical order to facility a binary search of the pragma name. +** Do not edit pragma.h directly. Edit and rerun the script in at +** ../tool/mkpragmatab.tcl. */ +/************** Include pragma.h in the middle of pragma.c *******************/ +/************** Begin file pragma.h ******************************************/ +/* DO NOT EDIT! +** This file is automatically generated by the script at +** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit +** that script and rerun it. */ #define PragTyp_HEADER_VALUE 0 #define PragTyp_AUTO_VACUUM 1 @@ -102270,6 +103391,10 @@ static const struct sPragmaNames { /* ePragTyp: */ PragTyp_INDEX_LIST, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, + { /* zName: */ "index_xinfo", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) { /* zName: */ "integrity_check", @@ -102486,9 +103611,10 @@ static const struct sPragmaNames { /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, #endif }; -/* Number of pragmas: 58 on by default, 71 total. */ -/* End of the automatically generated pragma table. -***************************************************************************/ +/* Number of pragmas: 59 on by default, 72 total. */ + +/************** End of pragma.h **********************************************/ +/************** Continuing where we left off in pragma.c *********************/ /* ** Interpret the given string as a safety level. Return 0 for OFF, @@ -102624,15 +103750,15 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){ */ static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){ Vdbe *v = sqlite3GetVdbe(pParse); - int mem = ++pParse->nMem; + int nMem = ++pParse->nMem; i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value)); if( pI64 ){ memcpy(pI64, &value, sizeof(value)); } - sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64); + sqlite3VdbeAddOp4(v, OP_Int64, 0, nMem, 0, (char*)pI64, P4_INT64); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1); } @@ -102741,6 +103867,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* The specific database being pragmaed */ Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ + const struct sPragmaNames *pPragma; if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); @@ -102776,6 +103903,17 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS ** connection. If it returns SQLITE_OK, then assume that the VFS ** handled the pragma and generate a no-op prepared statement. + ** + ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed, + ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file + ** object corresponding to the database file to which the pragma + ** statement refers. + ** + ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA + ** file control is an array of pointers to strings (char**) in which the + ** second element of the array is the name of the pragma and the third + ** element is the argument to the pragma or NULL if the pragma has no + ** argument. */ aFcntl[0] = 0; aFcntl[1] = zLeft; @@ -102785,11 +103923,11 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); if( rc==SQLITE_OK ){ if( aFcntl[0] ){ - int mem = ++pParse->nMem; - sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0); + int nMem = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, nMem, 0, aFcntl[0], 0); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1); sqlite3_free(aFcntl[0]); } goto pragma_out; @@ -102818,14 +103956,15 @@ SQLITE_PRIVATE void sqlite3Pragma( } } if( lwr>upr ) goto pragma_out; + pPragma = &aPragmaNames[mid]; /* Make sure the database schema is loaded if the pragma requires that */ - if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){ + if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; } /* Jump to the appropriate pragma handler */ - switch( aPragmaNames[mid].ePragTyp ){ + switch( pPragma->ePragTyp ){ #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* @@ -103393,7 +104532,9 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3ErrorMsg(pParse, "Safety level may not be changed inside a transaction"); }else{ - pDb->safety_level = getSafetyLevel(zRight,0,1)+1; + int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK; + if( iLevel==0 ) iLevel = 1; + pDb->safety_level = iLevel; setAllPagerFlags(db); } } @@ -103404,10 +104545,9 @@ SQLITE_PRIVATE void sqlite3Pragma( #ifndef SQLITE_OMIT_FLAG_PRAGMAS case PragTyp_FLAG: { if( zRight==0 ){ - returnSingleInt(pParse, aPragmaNames[mid].zName, - (db->flags & aPragmaNames[mid].iArg)!=0 ); + returnSingleInt(pParse, pPragma->zName, (db->flags & pPragma->iArg)!=0 ); }else{ - int mask = aPragmaNames[mid].iArg; /* Mask of bits to set or clear. */ + int mask = pPragma->iArg; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ /* Foreign key support may not be enabled or disabled while not ** in auto-commit mode. */ @@ -103489,7 +104629,7 @@ SQLITE_PRIVATE void sqlite3Pragma( }else if( pPk==0 ){ k = 1; }else{ - for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} + for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } sqlite3VdbeAddOp2(v, OP_Integer, k, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); @@ -103536,20 +104676,42 @@ SQLITE_PRIVATE void sqlite3Pragma( pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ int i; + int mx; + if( pPragma->iArg ){ + /* PRAGMA index_xinfo (newer version with more rows and columns) */ + mx = pIdx->nColumn; + pParse->nMem = 6; + }else{ + /* PRAGMA index_info (legacy version) */ + mx = pIdx->nKeyCol; + pParse->nMem = 3; + } pTab = pIdx->pTable; - sqlite3VdbeSetNumCols(v, 3); - pParse->nMem = 3; + sqlite3VdbeSetNumCols(v, pParse->nMem); sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC); - for(i=0; inKeyCol; i++){ + if( pPragma->iArg ){ + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC); + } + for(i=0; iaiColumn[i]; sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2); - assert( pTab->nCol>cnum ); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + if( cnum<0 ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, 3); + }else{ + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0); + } + if( pPragma->iArg ){ + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4); + sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0); + sqlite3VdbeAddOp2(v, OP_Integer, inKeyCol, 6); + } + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem); } } } @@ -103562,17 +104724,22 @@ SQLITE_PRIVATE void sqlite3Pragma( pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ v = sqlite3GetVdbe(pParse); - sqlite3VdbeSetNumCols(v, 3); - pParse->nMem = 3; + sqlite3VdbeSetNumCols(v, 5); + pParse->nMem = 5; sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "origin", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "partial", SQLITE_STATIC); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ + const char *azOrigin[] = { "c", "u", "pk" }; sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); sqlite3VdbeAddOp2(v, OP_Integer, IsUniqueIndex(pIdx), 3); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, azOrigin[pIdx->idxType], 0); + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->pPartIdxWhere!=0, 5); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); } } } @@ -104142,9 +105309,9 @@ SQLITE_PRIVATE void sqlite3Pragma( ** applications for any purpose. */ case PragTyp_HEADER_VALUE: { - int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */ + int iCookie = pPragma->iArg; /* Which cookie to read or write */ sqlite3VdbeUsesBtree(v, iDb); - if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){ + if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ /* Write the specified cookie value */ static const VdbeOpList setCookie[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ @@ -104246,8 +105413,9 @@ SQLITE_PRIVATE void sqlite3Pragma( /* ** PRAGMA shrink_memory ** - ** This pragma attempts to free as much memory as possible from the - ** current database connection. + ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database + ** connection on which it is invoked to free up as much memory as it + ** can, by calling sqlite3_db_release_memory(). */ case PragTyp_SHRINK_MEMORY: { sqlite3_db_release_memory(db); @@ -104264,7 +105432,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** disables the timeout. */ /*case PragTyp_BUSY_TIMEOUT*/ default: { - assert( aPragmaNames[mid].ePragTyp==PragTyp_BUSY_TIMEOUT ); + assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT ); if( zRight ){ sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); } @@ -104276,8 +105444,12 @@ SQLITE_PRIVATE void sqlite3Pragma( ** PRAGMA soft_heap_limit ** PRAGMA soft_heap_limit = N ** - ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted, - ** use -1. + ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the + ** sqlite3_soft_heap_limit64() interface with the argument N, if N is + ** specified and is a non-negative integer. + ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always + ** returns the same integer that would be returned by the + ** sqlite3_soft_heap_limit64(-1) C-language function. */ case PragTyp_SOFT_HEAP_LIMIT: { sqlite3_int64 N; @@ -104463,7 +105635,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 ){ corruptSchema(pData, argv[0], 0); - }else if( argv[2] && argv[2][0] ){ + }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data @@ -104494,8 +105666,8 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char } } sqlite3_finalize(pStmt); - }else if( argv[0]==0 ){ - corruptSchema(pData, 0, 0); + }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){ + corruptSchema(pData, argv[0], 0); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE @@ -105173,7 +106345,7 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){ ** and the statement is automatically recompiled if an schema change ** occurs. */ -SQLITE_API int sqlite3_prepare( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -105185,7 +106357,7 @@ SQLITE_API int sqlite3_prepare( assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } -SQLITE_API int sqlite3_prepare_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -105261,7 +106433,7 @@ static int sqlite3Prepare16( ** and the statement is automatically recompiled if an schema change ** occurs. */ -SQLITE_API int sqlite3_prepare16( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -105273,7 +106445,7 @@ SQLITE_API int sqlite3_prepare16( assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } -SQLITE_API int sqlite3_prepare16_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -105402,7 +106574,6 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( Select standin; sqlite3 *db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); - assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */ if( pNew==0 ){ assert( db->mallocFailed ); pNew = &standin; @@ -105422,7 +106593,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pNew->op = TK_SELECT; pNew->pLimit = pLimit; pNew->pOffset = pOffset; - assert( pOffset==0 || pLimit!=0 ); + assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 ); pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; if( db->mallocFailed ) { @@ -105854,20 +107025,17 @@ static void pushOntoSorter( } sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); if( pSelect->iLimit ){ - int addr1, addr2; + int addr; int iLimit; if( pSelect->iOffset ){ iLimit = pSelect->iOffset+1; }else{ iLimit = pSelect->iLimit; } - addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); - addr2 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, addr1); + addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); - sqlite3VdbeJumpHere(v, addr2); + sqlite3VdbeJumpHere(v, addr); } } @@ -106264,7 +107432,7 @@ static void selectInnerLoop( ** the output for us. */ if( pSort==0 && p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); } } @@ -106675,7 +107843,7 @@ static const char *columnTypeImpl( ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ - if( iCol>=0 && ALWAYS(iColpEList->nExpr) ){ + if( iCol>=0 && iColpEList->nExpr ){ /* If iCol is less than zero, then the expression requests the ** rowid of the sub-select or view. This expression is legal (see ** test case misc2.2.2) - it always evaluates to NULL. @@ -106995,12 +108163,14 @@ static void selectAddColumnTypeAndCollation( a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ p = a[i].pExpr; - pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst)); + if( pCol->zType==0 ){ + pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst)); + } szAll += pCol->szEst; pCol->affinity = sqlite3ExprAffinity(p); if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE; pColl = sqlite3ExprCollSeq(pParse, p); - if( pColl ){ + if( pColl && pCol->zColl==0 ){ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); } } @@ -107117,7 +108287,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3ExprCode(pParse, p->pLimit, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); VdbeComment((v, "LIMIT counter")); - sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); } if( p->pOffset ){ p->iOffset = iOffset = ++pParse->nMem; @@ -107336,7 +108506,7 @@ static void generateWithRecursiveQuery( selectInnerLoop(pParse, p, p->pEList, iCurrent, 0, 0, pDest, addrCont, addrBreak); if( regLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); VdbeCoverage(v); } sqlite3VdbeResolveLabel(v, addrCont); @@ -107402,8 +108572,7 @@ static int multiSelectValues( int nExpr = p->pEList->nExpr; int nRow = 1; int rc = 0; - assert( p->pNext==0 ); - assert( p->selFlags & SF_AllValues ); + assert( p->selFlags & SF_MultiValue ); do{ assert( p->selFlags & SF_Values ); assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); @@ -107512,7 +108681,7 @@ static int multiSelect( /* Special handling for a compound-select that originates as a VALUES clause. */ - if( p->selFlags & SF_AllValues ){ + if( p->selFlags & SF_MultiValue ){ rc = multiSelectValues(pParse, p, &dest); goto multi_select_end; } @@ -107561,7 +108730,7 @@ static int multiSelect( p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v); + addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); VdbeComment((v, "Jump ahead if LIMIT reached")); } explainSetInteger(iSub2, pParse->iNextSelectId); @@ -107897,7 +109066,7 @@ static int generateOutputSubroutine( */ case SRT_Set: { int r1; - assert( pIn->nSdst==1 ); + assert( pIn->nSdst==1 || pParse->nErr>0 ); pDest->affSdst = sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); r1 = sqlite3GetTempReg(pParse); @@ -107923,7 +109092,7 @@ static int generateOutputSubroutine( ** of the scan loop. */ case SRT_Mem: { - assert( pIn->nSdst==1 ); + assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 ); sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); /* The LIMIT clause will jump out of the loop for us */ break; @@ -107938,7 +109107,7 @@ static int generateOutputSubroutine( pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst); pDest->nSdst = pIn->nSdst; } - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst); + sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); break; } @@ -107962,7 +109131,7 @@ static int generateOutputSubroutine( /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); } /* Generate the subroutine return @@ -108154,8 +109323,10 @@ static int multiSelectOrderBy( if( aPermute ){ struct ExprList_item *pItem; for(i=0, pItem=pOrderBy->a; iu.x.iOrderByCol>0 - && pItem->u.x.iOrderByCol<=p->pEList->nExpr ); + assert( pItem->u.x.iOrderByCol>0 ); + /* assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ) is also true + ** but only for well-formed SELECT statements. */ + testcase( pItem->u.x.iOrderByCol > p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; } pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); @@ -108365,7 +109536,7 @@ static int multiSelectOrderBy( /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ explainComposite(pParse, p->op, iSub1, iSub2, 0); - return SQLITE_OK; + return pParse->nErr!=0; } #endif @@ -108485,7 +109656,10 @@ static void substSelect( ** ** (1) The subquery and the outer query do not both use aggregates. ** -** (2) The subquery is not an aggregate or the outer query is not a join. +** (2) The subquery is not an aggregate or (2a) the outer query is not a join +** and (2b) the outer query does not use subqueries other than the one +** FROM-clause subquery that is a candidate for flattening. (2b is +** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) ** ** (3) The subquery is not the right operand of a left outer join ** (Originally ticket #306. Strengthened by ticket #3300) @@ -108622,8 +109796,17 @@ static int flattenSubquery( iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); - if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ - if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ + if( subqueryIsAgg ){ + if( isAgg ) return 0; /* Restriction (1) */ + if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ + if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) + || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 + || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 + ){ + return 0; /* Restriction (2b) */ + } + } + pSubSrc = pSub->pSrc; assert( pSubSrc ); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, @@ -109165,7 +110348,10 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ pNew->pOrderBy = 0; p->pPrior = 0; p->pNext = 0; + p->pWith = 0; p->selFlags &= ~SF_Compound; + assert( (p->selFlags & SF_Converted)==0 ); + p->selFlags |= SF_Converted; assert( pNew->pPrior!=0 ); pNew->pPrior->pNext = pNew; pNew->pLimit = 0; @@ -109317,7 +110503,7 @@ static int withExpand( for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); pEList = pLeft->pEList; if( pCte->pCols ){ - if( pEList->nExpr!=pCte->pCols->nExpr ){ + if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){ sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", pCte->zName, pEList->nExpr, pCte->pCols->nExpr ); @@ -109444,7 +110630,7 @@ static int selectExpander(Walker *pWalker, Select *p){ /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); - sqlite3WalkSelect(pWalker, pSel); + if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; pTab->nRef = 1; @@ -109701,7 +110887,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; - if( (pSelect->selFlags & SF_AllValues)==0 ){ + if( (pSelect->selFlags & SF_MultiValue)==0 ){ w.xSelectCallback2 = selectPopWith; } sqlite3WalkSelect(&w, pSelect); @@ -109887,7 +111073,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ } if( pF->iDistinct>=0 ){ addrNext = sqlite3VdbeMakeLabel(v); - assert( nArg==1 ); + testcase( nArg==0 ); /* Error condition */ + testcase( nArg>1 ); /* Also an error */ codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); } if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ @@ -110043,6 +111230,13 @@ SQLITE_PRIVATE int sqlite3Select( } isAgg = (p->selFlags & SF_Aggregate)!=0; assert( pEList!=0 ); +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ + SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif + /* Begin generating code. */ @@ -110755,10 +111949,9 @@ SQLITE_PRIVATE int sqlite3Select( */ sqlite3VdbeResolveLabel(v, iEnd); - /* The SELECT was successfully coded. Set the return code to 0 - ** to indicate no errors. - */ - rc = 0; + /* The SELECT has been coded. If there is an error in the Parse structure, + ** set the return code to 1. Otherwise 0. */ + rc = (pParse->nErr>0); /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. @@ -110788,9 +111981,9 @@ select_end: SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; pView = sqlite3TreeViewPush(pView, moreToFollow); - sqlite3TreeViewLine(pView, "SELECT%s%s", + sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p)", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), - ((p->selFlags & SF_Aggregate) ? " agg_flag" : "") + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p ); if( p->pSrc && p->pSrc->nSrc ) n++; if( p->pWhere ) n++; @@ -110809,7 +112002,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m struct SrcList_item *pItem = &p->pSrc->a[i]; StrAccum x; char zLine[100]; - sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0); + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); if( pItem->zDatabase ){ sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); @@ -110968,7 +112161,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ z = 0; }else{ int n = sqlite3Strlen30(argv[i])+1; - z = sqlite3_malloc( n ); + z = sqlite3_malloc64( n ); if( z==0 ) goto malloc_failed; memcpy(z, argv[i], n); } @@ -110993,7 +112186,7 @@ malloc_failed: ** Instead, the entire table should be passed to sqlite3_free_table() when ** the calling procedure is finished using it. */ -SQLITE_API int sqlite3_get_table( +SQLITE_API int SQLITE_STDCALL sqlite3_get_table( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ char ***pazResult, /* Write the result table here */ @@ -111017,7 +112210,7 @@ SQLITE_API int sqlite3_get_table( res.nData = 1; res.nAlloc = 20; res.rc = SQLITE_OK; - res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc ); + res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc ); if( res.azResult==0 ){ db->errCode = SQLITE_NOMEM; return SQLITE_NOMEM; @@ -111045,7 +112238,7 @@ SQLITE_API int sqlite3_get_table( } if( res.nAlloc>res.nData ){ char **azNew; - azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData ); + azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData ); if( azNew==0 ){ sqlite3_free_table(&res.azResult[1]); db->errCode = SQLITE_NOMEM; @@ -111062,7 +112255,7 @@ SQLITE_API int sqlite3_get_table( /* ** This routine frees the space the sqlite3_get_table() malloced. */ -SQLITE_API void sqlite3_free_table( +SQLITE_API void SQLITE_STDCALL sqlite3_free_table( char **azResult /* Result returned from sqlite3_get_table() */ ){ if( azResult ){ @@ -111273,7 +112466,6 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); - pParse->nErr++; goto trigger_cleanup; } @@ -111453,12 +112645,12 @@ static TriggerStep *triggerStepAllocate( ){ TriggerStep *pTriggerStep; - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n); + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); if( pTriggerStep ){ char *z = (char*)&pTriggerStep[1]; memcpy(z, pName->z, pName->n); - pTriggerStep->target.z = z; - pTriggerStep->target.n = pName->n; + sqlite3Dequote(z); + pTriggerStep->zTarget = z; pTriggerStep->op = op; } return pTriggerStep; @@ -111741,7 +112933,7 @@ SQLITE_PRIVATE Trigger *sqlite3TriggersExist( } /* -** Convert the pStep->target token into a SrcList and return a pointer +** Convert the pStep->zTarget string into a SrcList and return a pointer ** to that SrcList. ** ** This routine adds a specific database name, if needed, to the target when @@ -111754,17 +112946,17 @@ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ + sqlite3 *db = pParse->db; int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ - pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); + pSrc = sqlite3SrcListAppend(db, 0, 0, 0); if( pSrc ){ assert( pSrc->nSrc>0 ); - assert( pSrc->a!=0 ); - iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); + pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); + iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); if( iDb==0 || iDb>=2 ){ - sqlite3 *db = pParse->db; - assert( iDbdb->nDb ); + assert( iDbnDb ); pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); } } @@ -111876,6 +113068,7 @@ static void transferParseError(Parse *pTo, Parse *pFrom){ if( pTo->nErr==0 ){ pTo->zErrMsg = pFrom->zErrMsg; pTo->nErr = pFrom->nErr; + pTo->rc = pFrom->rc; }else{ sqlite3DbFree(pFrom->db, pFrom->zErrMsg); } @@ -113160,7 +114353,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** cause problems for the call to BtreeSetPageSize() below. */ sqlite3BtreeCommit(pTemp); - nRes = sqlite3BtreeGetReserve(pMain); + nRes = sqlite3BtreeGetOptimalReserve(pMain); /* A VACUUM cannot change the pagesize of an encrypted database. */ #ifdef SQLITE_HAS_CODEC @@ -113226,6 +114419,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy ** the contents to the temporary database. */ + assert( (db->flags & SQLITE_Vacuum)==0 ); + db->flags |= SQLITE_Vacuum; rc = execExecSql(db, pzErrMsg, "SELECT 'INSERT INTO vacuum_db.' || quote(name) " "|| ' SELECT * FROM main.' || quote(name) || ';'" @@ -113233,6 +114428,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ "WHERE type = 'table' AND name!='sqlite_sequence' " " AND coalesce(rootpage,1)>0" ); + assert( (db->flags & SQLITE_Vacuum)!=0 ); + db->flags &= ~SQLITE_Vacuum; if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Copy over the sequence table @@ -113371,6 +114568,8 @@ end_of_vacuum: struct VtabCtx { VTable *pVTable; /* The virtual table being constructed */ Table *pTab; /* The Table object to which the virtual table belongs */ + VtabCtx *pPrior; /* Parent context (if any) */ + int bDeclared; /* True after sqlite3_declare_vtab() is called */ }; /* @@ -113422,7 +114621,7 @@ static int createModule( /* ** External API function used to create a new virtual-table module. */ -SQLITE_API int sqlite3_create_module( +SQLITE_API int SQLITE_STDCALL sqlite3_create_module( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ @@ -113437,7 +114636,7 @@ SQLITE_API int sqlite3_create_module( /* ** External API function used to create a new virtual-table module. */ -SQLITE_API int sqlite3_create_module_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ @@ -113736,6 +114935,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ char *zStmt; char *zWhere; int iDb; + int iReg; Vdbe *v; /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ @@ -113770,8 +114970,10 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); - sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, - pTab->zName, sqlite3Strlen30(pTab->zName) + 1); + + iReg = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, iReg, 0, pTab->zName, 0); + sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg); } /* If we are rereading the sqlite_master table create the in-memory @@ -113814,7 +115016,7 @@ SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse *pParse, Token *p){ pArg->z = p->z; pArg->n = p->n; }else{ - assert(pArg->z < p->z); + assert(pArg->z <= p->z); pArg->n = (int)(&p->z[p->n] - pArg->z); } } @@ -113831,15 +115033,27 @@ static int vtabCallConstructor( int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ - VtabCtx sCtx, *pPriorCtx; + VtabCtx sCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; - char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); + char *zModuleName; int iDb; + VtabCtx *pCtx; + /* Check that the virtual-table is not already being initialized */ + for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ + if( pCtx->pTab==pTab ){ + *pzErr = sqlite3MPrintf(db, + "vtable constructor called recursively: %s", pTab->zName + ); + return SQLITE_LOCKED; + } + } + + zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); if( !zModuleName ){ return SQLITE_NOMEM; } @@ -113860,11 +115074,13 @@ static int vtabCallConstructor( assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; - pPriorCtx = db->pVtabCtx; + sCtx.pPrior = db->pVtabCtx; + sCtx.bDeclared = 0; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - db->pVtabCtx = pPriorCtx; + db->pVtabCtx = sCtx.pPrior; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ if( zErr==0 ){ @@ -113880,13 +115096,14 @@ static int vtabCallConstructor( memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); pVTable->pVtab->pModule = pMod->pModule; pVTable->nRef = 1; - if( sCtx.pTab ){ + if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; + u8 oooHidden = 0; /* If everything went according to plan, link the new VTable structure ** into the linked list headed by pTab->pVTable. Then loop through the ** columns of the table to see if any of them contain the token "hidden". @@ -113899,7 +115116,10 @@ static int vtabCallConstructor( char *zType = pTab->aCol[iCol].zType; int nType; int i = 0; - if( !zType ) continue; + if( !zType ){ + pTab->tabFlags |= oooHidden; + continue; + } nType = sqlite3Strlen30(zType); if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ for(i=0; iaCol[iCol].colFlags |= COLFLAG_HIDDEN; + oooHidden = TF_OOOHidden; + }else{ + pTab->tabFlags |= oooHidden; } } } @@ -114049,22 +115272,26 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ -SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ +SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ + VtabCtx *pCtx; Parse *pParse; - int rc = SQLITE_OK; Table *pTab; char *zErr = 0; #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; + if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ + return SQLITE_MISUSE_BKPT; + } #endif sqlite3_mutex_enter(db->mutex); - if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){ + pCtx = db->pVtabCtx; + if( !pCtx || pCtx->bDeclared ){ sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } + pTab = pCtx->pTab; assert( (pTab->tabFlags & TF_Virtual)!=0 ); pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); @@ -114087,7 +115314,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } - db->pVtabCtx->pTab = 0; + pCtx->bDeclared = 1; }else{ sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); @@ -114122,11 +115349,15 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ - VTable *p = vtabDisconnectAll(db, pTab); - - assert( rc==SQLITE_OK ); + VTable *p; + for(p=pTab->pVTable; p; p=p->pNext){ + assert( p->pVtab ); + if( p->pVtab->nRef>0 ){ + return SQLITE_LOCKED; + } + } + p = vtabDisconnectAll(db, pTab); rc = p->pMod->pModule->xDestroy(p->pVtab); - /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ if( rc==SQLITE_OK ){ assert( pTab->pVTable==p && p->pNext==0 ); @@ -114277,7 +115508,7 @@ SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){ int rc = SQLITE_OK; assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN ); - assert( iSavepoint>=0 ); + assert( iSavepoint>=-1 ); if( db->aVTrans ){ int i; for(i=0; rc==SQLITE_OK && inVTrans; i++){ @@ -114395,7 +115626,7 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ if( pTab==pToplevel->apVtabLock[i] ) return; } n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); - apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n); + apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); if( apVtabLock ){ pToplevel->apVtabLock = apVtabLock; pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; @@ -114411,7 +115642,7 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ ** The results of this routine are undefined unless it is called from ** within an xUpdate method. */ -SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ +SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *db){ static const unsigned char aMap[] = { SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE }; @@ -114429,7 +115660,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ ** the SQLite core with additional information about the behavior ** of the virtual table being implemented. */ -SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ +SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){ va_list ap; int rc = SQLITE_OK; @@ -114555,6 +115786,8 @@ struct WhereLevel { int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ + int iLikeRepCntr; /* LIKE range processing counter register */ + int addrLikeRep; /* LIKE range processing address */ u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ int p1, p2; /* Operands of the opcode used to ends the loop */ @@ -114739,7 +115972,7 @@ struct WhereTerm { } u; LogEst truthProb; /* Probability of truth for this expression */ u16 eOperator; /* A WO_xx value describing */ - u8 wtFlags; /* TERM_xxx bit flags. See below */ + u16 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ @@ -114761,6 +115994,9 @@ struct WhereTerm { #else # define TERM_VNULL 0x00 /* Disabled if not using stat3 */ #endif +#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */ +#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */ +#define TERM_LIKE 0x400 /* The original LIKE operator */ /* ** An instance of the WhereScan object is used as an iterator for locating @@ -115136,7 +116372,7 @@ static void whereClauseClear(WhereClause *pWC){ ** calling this routine. Such pointers may be reinitialized by referencing ** the pWC->a[] array. */ -static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ +static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ WhereTerm *pTerm; int idx; testcase( wtFlags & TERM_VIRTUAL ); @@ -115189,13 +116425,14 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ ** all terms of the WHERE clause. */ static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ + Expr *pE2 = sqlite3ExprSkipCollate(pExpr); pWC->op = op; - if( pExpr==0 ) return; - if( pExpr->op!=op ){ + if( pE2==0 ) return; + if( pE2->op!=op ){ whereClauseInsert(pWC, pExpr, 0); }else{ - whereSplit(pWC, pExpr->pLeft, op); - whereSplit(pWC, pExpr->pRight, op); + whereSplit(pWC, pE2->pLeft, op); + whereSplit(pWC, pE2->pRight, op); } } @@ -115561,7 +116798,11 @@ static void exprAnalyzeAll( ** so and false if not. ** ** In order for the operator to be optimizible, the RHS must be a string -** literal that does not begin with a wildcard. +** literal that does not begin with a wildcard. The LHS must be a column +** that may only be NULL, a string, or a BLOB, never a number. (This means +** that virtual tables cannot participate in the LIKE optimization.) If the +** collating sequence for the column on the LHS must be appropriate for +** the operator. */ static int isLikeOrGlob( Parse *pParse, /* Parsing and code generating context */ @@ -115590,7 +116831,7 @@ static int isLikeOrGlob( pLeft = pList->a[1].pExpr; if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) + || IsVirtual(pLeft->pTab) /* Value might be numeric */ ){ /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must ** be the name of an indexed column with TEXT affinity. */ @@ -115700,6 +116941,79 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ pWC->a[iParent].nChild++; } +/* +** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not +** a conjunction, then return just pTerm when N==0. If N is exceeds +** the number of available subterms, return NULL. +*/ +static WhereTerm *whereNthSubterm(WhereTerm *pTerm, int N){ + if( pTerm->eOperator!=WO_AND ){ + return N==0 ? pTerm : 0; + } + if( Nu.pAndInfo->wc.nTerm ){ + return &pTerm->u.pAndInfo->wc.a[N]; + } + return 0; +} + +/* +** Subterms pOne and pTwo are contained within WHERE clause pWC. The +** two subterms are in disjunction - they are OR-ed together. +** +** If these two terms are both of the form: "A op B" with the same +** A and B values but different operators and if the operators are +** compatible (if one is = and the other is <, for example) then +** add a new virtual AND term to pWC that is the combination of the +** two. +** +** Some examples: +** +** x x<=y +** x=y OR x=y --> x=y +** x<=y OR x x<=y +** +** The following is NOT generated: +** +** xy --> x!=y +*/ +static void whereCombineDisjuncts( + SrcList *pSrc, /* the FROM clause */ + WhereClause *pWC, /* The complete WHERE clause */ + WhereTerm *pOne, /* First disjunct */ + WhereTerm *pTwo /* Second disjunct */ +){ + u16 eOp = pOne->eOperator | pTwo->eOperator; + sqlite3 *db; /* Database connection (for malloc) */ + Expr *pNew; /* New virtual expression */ + int op; /* Operator for the combined expression */ + int idxNew; /* Index in pWC of the next virtual term */ + + if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; + if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; + if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp + && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; + assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); + assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); + if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; + if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return; + /* If we reach this point, it means the two subterms can be combined */ + if( (eOp & (eOp-1))!=0 ){ + if( eOp & (WO_LT|WO_LE) ){ + eOp = WO_LE; + }else{ + assert( eOp & (WO_GT|WO_GE) ); + eOp = WO_GE; + } + } + db = pWC->pWInfo->pParse->db; + pNew = sqlite3ExprDup(db, pOne->pExpr, 0); + if( pNew==0 ) return; + for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( opop = op; + idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew); +} + #if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) /* ** Analyze a term that consists of two or more OR-connected @@ -115724,6 +117038,7 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) +** (F) x>A OR (x=A AND y>=B) ** ** CASE 1: ** @@ -115740,6 +117055,16 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ ** ** CASE 2: ** +** If there are exactly two disjuncts one side has x>A and the other side +** has x=A (for the same x and A) then add a new virtual conjunct term to the +** WHERE clause of the form "x>=A". Example: +** +** x>A OR (x=A AND y>B) adds: x>=A +** +** The added conjunct can sometimes be helpful in query planning. +** +** CASE 3: +** ** If all subterms are indexable by a single table T, then set ** ** WhereTerm.eOperator = WO_OR @@ -115866,12 +117191,26 @@ static void exprAnalyzeOrTerm( } /* - ** Record the set of tables that satisfy case 2. The set might be + ** Record the set of tables that satisfy case 3. The set might be ** empty. */ pOrInfo->indexable = indexable; pTerm->eOperator = indexable==0 ? 0 : WO_OR; + /* For a two-way OR, attempt to implementation case 2. + */ + if( indexable && pOrWc->nTerm==2 ){ + int iOne = 0; + WhereTerm *pOne; + while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){ + int iTwo = 0; + WhereTerm *pTwo; + while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){ + whereCombineDisjuncts(pSrc, pWC, pOne, pTwo); + } + } + } + /* ** chngToIN holds a set of tables that *might* satisfy case 1. But ** we have to do some additional checking to see if case 1 really @@ -116001,7 +117340,7 @@ static void exprAnalyzeOrTerm( }else{ sqlite3ExprListDelete(db, pList); } - pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ + pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */ } } } @@ -116039,7 +117378,7 @@ static void exprAnalyze( Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ - int noCase = 0; /* LIKE/GLOB distinguishes case */ + int noCase = 0; /* uppercase equivalent to lowercase */ int op; /* Top-level operator. pExpr->op */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection */ @@ -116177,12 +117516,15 @@ static void exprAnalyze( /* Add constraints to reduce the search space on a LIKE or GLOB ** operator. ** - ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints + ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints ** - ** x>='abc' AND x<'abd' AND x LIKE 'abc%' + ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%' ** ** The last character of the prefix "abc" is incremented to form the - ** termination condition "abd". + ** termination condition "abd". If case is not significant (the default + ** for LIKE) then the lower-bound is made all uppercase and the upper- + ** bound is made all lowercase so that the bounds also work when comparing + ** BLOBs. */ if( pWC->op==TK_AND && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase) @@ -116193,10 +117535,26 @@ static void exprAnalyze( Expr *pNewExpr2; int idxNew1; int idxNew2; - Token sCollSeqName; /* Name of collating sequence */ + const char *zCollSeqName; /* Name of collating sequence */ + const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC; pLeft = pExpr->x.pList->a[1].pExpr; pStr2 = sqlite3ExprDup(db, pStr1, 0); + + /* Convert the lower bound to upper-case and the upper bound to + ** lower-case (upper-case is less than lower-case in ASCII) so that + ** the range constraints also work for BLOBs + */ + if( noCase && !pParse->db->mallocFailed ){ + int i; + char c; + pTerm->wtFlags |= TERM_LIKE; + for(i=0; (c = pStr1->u.zToken[i])!=0; i++){ + pStr1->u.zToken[i] = sqlite3Toupper(c); + pStr2->u.zToken[i] = sqlite3Tolower(c); + } + } + if( !db->mallocFailed ){ u8 c, *pC; /* Last character before the first wildcard */ pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; @@ -116213,22 +117571,21 @@ static void exprAnalyze( } *pC = c + 1; } - sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; - sCollSeqName.n = 6; + zCollSeqName = noCase ? "NOCASE" : "BINARY"; pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); - pNewExpr1 = sqlite3PExpr(pParse, TK_GE, - sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), + pNewExpr1 = sqlite3PExpr(pParse, TK_GE, + sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), pStr1, 0); transferJoinMarkings(pNewExpr1, pExpr); - idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); + idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); testcase( idxNew1==0 ); exprAnalyze(pSrc, pWC, idxNew1); pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, - sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), + sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), pStr2, 0); transferJoinMarkings(pNewExpr2, pExpr); - idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); + idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); testcase( idxNew2==0 ); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; @@ -116346,7 +117703,7 @@ static int findIndexCol( && p->iTable==iBase ){ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); - if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ + if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){ return i; } } @@ -116546,11 +117903,16 @@ static void constructAutomaticIndex( pLoop = pLevel->pWLoop; idxCols = 0; for(pTerm=pWC->a; pTermpExpr; + assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */ + || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */ + || pLoop->prereq!=0 ); /* table of a LEFT JOIN */ if( pLoop->prereq==0 && (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsTableConstant(pTerm->pExpr, pSrc->iCursor) ){ + && !ExprHasProperty(pExpr, EP_FromJoin) + && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ pPartial = sqlite3ExprAnd(pParse->db, pPartial, - sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); + sqlite3ExprDup(pParse->db, pExpr, 0)); } if( termCanDriveIndex(pTerm, pSrc, notReady) ){ int iCol = pTerm->u.leftColumn; @@ -116615,7 +117977,7 @@ static void constructAutomaticIndex( idxCols |= cMask; pIdx->aiColumn[n] = pTerm->u.leftColumn; pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); - pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY"; + pIdx->azColl[n] = pColl ? pColl->zName : "BINARY"; n++; } } @@ -116837,11 +118199,14 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: ** -** aStat[0] Est. number of rows less than pVal -** aStat[1] Est. number of rows equal to pVal +** aStat[0] Est. number of rows less than pRec +** aStat[1] Est. number of rows equal to pRec ** ** Return the index of the sample that is the smallest sample that -** is greater than or equal to pRec. +** is greater than or equal to pRec. Note that this index is not an index +** into the aSample[] array - it is an index into a virtual set of samples +** based on the contents of aSample[] and the number of fields in record +** pRec. */ static int whereKeyStats( Parse *pParse, /* Database connection */ @@ -116852,67 +118217,158 @@ static int whereKeyStats( ){ IndexSample *aSample = pIdx->aSample; int iCol; /* Index of required stats in anEq[] etc. */ + int i; /* Index of first sample >= pRec */ + int iSample; /* Smallest sample larger than or equal to pRec */ int iMin = 0; /* Smallest sample not yet tested */ - int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ int iTest; /* Next sample to test */ int res; /* Result of comparison operation */ + int nField; /* Number of fields in pRec */ + tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */ #ifndef SQLITE_DEBUG UNUSED_PARAMETER( pParse ); #endif assert( pRec!=0 ); - iCol = pRec->nField - 1; assert( pIdx->nSample>0 ); - assert( pRec->nField>0 && iColnSampleCol ); + assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol ); + + /* Do a binary search to find the first sample greater than or equal + ** to pRec. If pRec contains a single field, the set of samples to search + ** is simply the aSample[] array. If the samples in aSample[] contain more + ** than one fields, all fields following the first are ignored. + ** + ** If pRec contains N fields, where N is more than one, then as well as the + ** samples in aSample[] (truncated to N fields), the search also has to + ** consider prefixes of those samples. For example, if the set of samples + ** in aSample is: + ** + ** aSample[0] = (a, 5) + ** aSample[1] = (a, 10) + ** aSample[2] = (b, 5) + ** aSample[3] = (c, 100) + ** aSample[4] = (c, 105) + ** + ** Then the search space should ideally be the samples above and the + ** unique prefixes [a], [b] and [c]. But since that is hard to organize, + ** the code actually searches this set: + ** + ** 0: (a) + ** 1: (a, 5) + ** 2: (a, 10) + ** 3: (a, 10) + ** 4: (b) + ** 5: (b, 5) + ** 6: (c) + ** 7: (c, 100) + ** 8: (c, 105) + ** 9: (c, 105) + ** + ** For each sample in the aSample[] array, N samples are present in the + ** effective sample array. In the above, samples 0 and 1 are based on + ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc. + ** + ** Often, sample i of each block of N effective samples has (i+1) fields. + ** Except, each sample may be extended to ensure that it is greater than or + ** equal to the previous sample in the array. For example, in the above, + ** sample 2 is the first sample of a block of N samples, so at first it + ** appears that it should be 1 field in size. However, that would make it + ** smaller than sample 1, so the binary search would not work. As a result, + ** it is extended to two fields. The duplicates that this creates do not + ** cause any problems. + */ + nField = pRec->nField; + iCol = 0; + iSample = pIdx->nSample * nField; do{ - iTest = (iMin+i)/2; - res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec); - if( res<0 ){ - iMin = iTest+1; + int iSamp; /* Index in aSample[] of test sample */ + int n; /* Number of fields in test sample */ + + iTest = (iMin+iSample)/2; + iSamp = iTest / nField; + if( iSamp>0 ){ + /* The proposed effective sample is a prefix of sample aSample[iSamp]. + ** Specifically, the shortest prefix of at least (1 + iTest%nField) + ** fields that is greater than the previous effective sample. */ + for(n=(iTest % nField) + 1; nnField = n; + res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec); + if( res<0 ){ + iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1]; + iMin = iTest+1; + }else if( res==0 && nnSample ); - assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) - || pParse->db->mallocFailed ); - }else{ - /* Otherwise, pRec must be smaller than sample $i and larger than - ** sample ($i-1). */ - assert( i==pIdx->nSample - || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 - || pParse->db->mallocFailed ); - assert( i==0 - || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 - || pParse->db->mallocFailed ); + if( pParse->db->mallocFailed==0 ){ + if( res==0 ){ + /* If (res==0) is true, then pRec must be equal to sample i. */ + assert( inSample ); + assert( iCol==nField-1 ); + pRec->nField = nField; + assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) + || pParse->db->mallocFailed + ); + }else{ + /* Unless i==pIdx->nSample, indicating that pRec is larger than + ** all samples in the aSample[] array, pRec must be smaller than the + ** (iCol+1) field prefix of sample i. */ + assert( i<=pIdx->nSample && i>=0 ); + pRec->nField = iCol+1; + assert( i==pIdx->nSample + || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 + || pParse->db->mallocFailed ); + + /* if i==0 and iCol==0, then record pRec is smaller than all samples + ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must + ** be greater than or equal to the (iCol) field prefix of sample i. + ** If (i>0), then pRec must also be greater than sample (i-1). */ + if( iCol>0 ){ + pRec->nField = iCol; + assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 + || pParse->db->mallocFailed ); + } + if( i>0 ){ + pRec->nField = nField; + assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 + || pParse->db->mallocFailed ); + } + } } #endif /* ifdef SQLITE_DEBUG */ - /* At this point, aSample[i] is the first sample that is greater than - ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less - ** than pVal. If aSample[i]==pVal, then res==0. - */ if( res==0 ){ + /* Record pRec is equal to sample i */ + assert( iCol==nField-1 ); aStat[0] = aSample[i].anLt[iCol]; aStat[1] = aSample[i].anEq[iCol]; }else{ - tRowcnt iLower, iUpper, iGap; - if( i==0 ){ - iLower = 0; - iUpper = aSample[0].anLt[iCol]; + /* At this point, the (iCol+1) field prefix of aSample[i] is the first + ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec + ** is larger than all samples in the array. */ + tRowcnt iUpper, iGap; + if( i>=pIdx->nSample ){ + iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); }else{ - i64 nRow0 = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); - iUpper = i>=pIdx->nSample ? nRow0 : aSample[i].anLt[iCol]; - iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol]; + iUpper = aSample[i].anLt[iCol]; } - aStat[1] = pIdx->aAvgEq[iCol]; + if( iLower>=iUpper ){ iGap = 0; }else{ @@ -116924,7 +118380,11 @@ static int whereKeyStats( iGap = iGap/3; } aStat[0] = iLower + iGap; + aStat[1] = pIdx->aAvgEq[iCol]; } + + /* Restore the pRec->nField value before returning. */ + pRec->nField = nField; return i; } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ @@ -117398,20 +118858,43 @@ static int whereInScanEst( ** but joins might run a little slower. The trick is to disable as much ** as we can without disabling too much. If we disabled in (1), we'd get ** the wrong answer. See ticket #813. +** +** If all the children of a term are disabled, then that term is also +** automatically disabled. In this way, terms get disabled if derived +** virtual terms are tested first. For example: +** +** x GLOB 'abc*' AND x>='abc' AND x<'acd' +** \___________/ \______/ \_____/ +** parent child1 child2 +** +** Only the parent term was in the original WHERE clause. The child1 +** and child2 terms were added by the LIKE optimization. If both of +** the virtual child terms are valid, then testing of the parent can be +** skipped. +** +** Usually the parent term is marked as TERM_CODED. But if the parent +** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead. +** The TERM_LIKECOND marking indicates that the term should be coded inside +** a conditional such that is only evaluated on the second pass of a +** LIKE-optimization loop, when scanning BLOBs instead of strings. */ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ - if( pTerm + int nLoop = 0; + while( pTerm && (pTerm->wtFlags & TERM_CODED)==0 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) && (pLevel->notReady & pTerm->prereqAll)==0 ){ - pTerm->wtFlags |= TERM_CODED; - if( pTerm->iParent>=0 ){ - WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent]; - if( (--pOther->nChild)==0 ){ - disableTerm(pLevel, pOther); - } + if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){ + pTerm->wtFlags |= TERM_LIKECOND; + }else{ + pTerm->wtFlags |= TERM_CODED; } + if( pTerm->iParent<0 ) break; + pTerm = &pTerm->pWC->a[pTerm->iParent]; + pTerm->nChild--; + if( pTerm->nChild!=0 ) break; + nLoop++; } } @@ -117790,8 +119273,7 @@ static int explainOneScan( || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); - sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - str.db = db; + sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); if( pItem->pSelect ){ sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId); @@ -117895,7 +119377,34 @@ static void addScanStatus( # define addScanStatus(a, b, c, d) ((void)d) #endif - +/* +** If the most recently coded instruction is a constant range contraint +** that originated from the LIKE optimization, then change the P3 to be +** pLoop->iLikeRepCntr and set P5. +** +** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range +** expression: "x>='ABC' AND x<'abd'". But this requires that the range +** scan loop run twice, once for strings and a second time for BLOBs. +** The OP_String opcodes on the second pass convert the upper and lower +** bound string contants to blobs. This routine makes the necessary changes +** to the OP_String opcodes for that to happen. +*/ +static void whereLikeOptimizationStringFixup( + Vdbe *v, /* prepared statement under construction */ + WhereLevel *pLevel, /* The loop that contains the LIKE operator */ + WhereTerm *pTerm /* The upper or lower bound just coded */ +){ + if( pTerm->wtFlags & TERM_LIKEOPT ){ + VdbeOp *pOp; + assert( pLevel->iLikeRepCntr>0 ); + pOp = sqlite3VdbeGetOp(v, -1); + assert( pOp!=0 ); + assert( pOp->opcode==OP_String8 + || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); + pOp->p3 = pLevel->iLikeRepCntr; + pOp->p5 = 1; + } +} /* ** Generate code for the start of the iLevel-th loop in the WHERE clause @@ -118225,10 +119734,25 @@ static Bitmask codeOneLoopStart( if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ pRangeStart = pLoop->aLTerm[j++]; nExtraReg = 1; + /* Like optimization range constraints always occur in pairs */ + assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || + (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 ); } if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; nExtraReg = 1; + if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){ + assert( pRangeStart!=0 ); /* LIKE opt constraints */ + assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */ + pLevel->iLikeRepCntr = ++pParse->nMem; + testcase( bRev ); + testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC ); + sqlite3VdbeAddOp2(v, OP_Integer, + bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC), + pLevel->iLikeRepCntr); + VdbeComment((v, "LIKE loop counter")); + pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v); + } if( pRangeStart==0 && (j = pIdx->aiColumn[nEq])>=0 && pIdx->pTable->aCol[j].notNull==0 @@ -118271,6 +119795,7 @@ static Bitmask codeOneLoopStart( if( pRangeStart ){ Expr *pRight = pRangeStart->pExpr->pRight; sqlite3ExprCode(pParse, pRight, regBase+nEq); + whereLikeOptimizationStringFixup(v, pLevel, pRangeStart); if( (pRangeStart->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ @@ -118316,6 +119841,7 @@ static Bitmask codeOneLoopStart( Expr *pRight = pRangeEnd->pExpr->pRight; sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); sqlite3ExprCode(pParse, pRight, regBase+nEq); + whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ @@ -118543,7 +120069,8 @@ static Bitmask codeOneLoopStart( */ wctrlFlags = WHERE_OMIT_OPEN_CLOSE | WHERE_FORCE_TABLE - | WHERE_ONETABLE_ONLY; + | WHERE_ONETABLE_ONLY + | WHERE_NO_AUTOINDEX; for(ii=0; iinTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ @@ -118705,6 +120232,7 @@ static Bitmask codeOneLoopStart( */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; + int skipLikeAddr = 0; testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; @@ -118719,7 +120247,13 @@ static Bitmask codeOneLoopStart( if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ continue; } + if( pTerm->wtFlags & TERM_LIKECOND ){ + assert( pLevel->iLikeRepCntr>0 ); + skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr); + VdbeCoverage(v); + } sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); + if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); pTerm->wtFlags |= TERM_CODED; } @@ -118938,6 +120472,13 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ */ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ if( ALWAYS(pWInfo) ){ + int i; + for(i=0; inLevel; i++){ + WhereLevel *pLevel = &pWInfo->a[i]; + if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ + sqlite3DbFree(db, pLevel->u.in.aInLoop); + } + } whereClauseClear(&pWInfo->sWC); while( pWInfo->pLoops ){ WhereLoop *p = pWInfo->pLoops; @@ -119384,6 +120925,10 @@ static int whereLoopAddBtreeIndex( } if( pTerm->prereqRight & pNew->maskSelf ) continue; + /* Do not allow the upper bound of a LIKE optimization range constraint + ** to mix with a lower range bound from some other source */ + if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; + pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->nLTerm = saved_nLTerm; @@ -119413,7 +120958,7 @@ static int whereLoopAddBtreeIndex( }else if( eOp & (WO_EQ) ){ pNew->wsFlags |= WHERE_COLUMN_EQ; if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){ - if( iCol>=0 && !IsUniqueIndex(pProbe) ){ + if( iCol>=0 && pProbe->uniqNotNull==0 ){ pNew->wsFlags |= WHERE_UNQ_WANTED; }else{ pNew->wsFlags |= WHERE_ONEROW; @@ -119427,6 +120972,17 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; pBtm = pTerm; pTop = 0; + if( pTerm->wtFlags & TERM_LIKEOPT ){ + /* Range contraints that come from the LIKE optimization are + ** always used in pairs. */ + pTop = &pTerm[1]; + assert( (pTop-(pTerm->pWC->a))pWC->nTerm ); + assert( pTop->wtFlags & TERM_LIKEOPT ); + assert( pTop->eOperator==WO_LT ); + if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ + pNew->aLTerm[pNew->nLTerm++] = pTop; + pNew->wsFlags |= WHERE_TOP_LIMIT; + } }else{ assert( eOp & (WO_LT|WO_LE) ); testcase( eOp & WO_LT ); @@ -119628,7 +121184,12 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ int i; WhereTerm *pTerm; for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - if( sqlite3ExprImpliesExpr(pTerm->pExpr, pWhere, iTab) ) return 1; + Expr *pExpr = pTerm->pExpr; + if( sqlite3ExprImpliesExpr(pExpr, pWhere, iTab) + && (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) + ){ + return 1; + } } return 0; } @@ -119732,6 +121293,7 @@ static int whereLoopAddBtree( #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet + && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && pSrc->pIndex==0 && !pSrc->viaCoroutine @@ -120615,10 +122177,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ /* Seed the search with a single WherePath containing zero WhereLoops. ** - ** TUNING: Do not let the number of iterations go above 25. If the cost - ** of computing an automatic index is not paid back within the first 25 + ** TUNING: Do not let the number of iterations go above 28. If the cost + ** of computing an automatic index is not paid back within the first 28 ** rows, then do not use the automatic index. */ - aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) ); + aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) ); nFrom = 1; assert( aFrom[0].isOrdered==0 ); if( nOrderBy ){ @@ -120856,7 +122418,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ pWInfo->revMask = pFrom->revLoop; } if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) - && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr + && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 ){ Bitmask revMask = 0; int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, @@ -121261,7 +122823,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } #ifdef WHERETRACE_ENABLED /* !=0 */ if( sqlite3WhereTrace ){ - int ii; sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); if( pWInfo->nOBSat>0 ){ sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); @@ -121416,6 +122977,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( op ){ sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIx); + if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0 + && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 + && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 + ){ + sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */ + } VdbeComment((v, "%s", pIx->zName)); } } @@ -121508,7 +123075,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } - sqlite3DbFree(db, pLevel->u.in.aInLoop); } sqlite3VdbeResolveLabel(v, pLevel->addrBrk); if( pLevel->addrSkip ){ @@ -121517,6 +123083,16 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeJumpHere(v, pLevel->addrSkip); sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); } + if( pLevel->addrLikeRep ){ + int op; + if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){ + op = OP_DecrJumpZero; + }else{ + op = OP_JumpZeroIncr; + } + sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep); + VdbeCoverage(v); + } if( pLevel->iLeftJoin ){ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 @@ -121710,6 +123286,28 @@ struct TrigEvent { int a; IdList * b; }; struct AttachKey { int type; Token key; }; + /* + ** For a compound SELECT statement, make sure p->pPrior->pNext==p for + ** all elements in the list. And make sure list length does not exceed + ** SQLITE_LIMIT_COMPOUND_SELECT. + */ + static void parserDoubleLinkSelect(Parse *pParse, Select *p){ + if( p->pPrior ){ + Select *pNext = 0, *pLoop; + int mxSelect, cnt = 0; + for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){ + pLoop->pNext = pNext; + pLoop->selFlags |= SF_Compound; + } + if( (p->selFlags & SF_MultiValue)==0 && + (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 && + cnt>mxSelect + ){ + sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); + } + } + } + /* This is a utility routine used to set the ExprSpan.zStart and ** ExprSpan.zEnd values of pOut so that the span covers the complete ** range of text beginning with pStart and going to the end of pEnd. @@ -124026,27 +125624,10 @@ static void yy_reduce( break; case 112: /* select ::= with selectnowith */ { - Select *p = yymsp[0].minor.yy3, *pNext, *pLoop; + Select *p = yymsp[0].minor.yy3; if( p ){ - int cnt = 0, mxSelect; p->pWith = yymsp[-1].minor.yy59; - if( p->pPrior ){ - u16 allValues = SF_Values; - pNext = 0; - for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){ - pLoop->pNext = pNext; - pLoop->selFlags |= SF_Compound; - allValues &= pLoop->selFlags; - } - if( allValues ){ - p->selFlags |= SF_AllValues; - }else if( - (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 - && cnt>mxSelect - ){ - sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); - } - } + parserDoubleLinkSelect(pParse, p); }else{ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy59); } @@ -124064,12 +125645,14 @@ static void yy_reduce( SrcList *pFrom; Token x; x.n = 0; + parserDoubleLinkSelect(pParse, pRhs); pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); } if( pRhs ){ pRhs->op = (u8)yymsp[-1].minor.yy328; pRhs->pPrior = yymsp[-2].minor.yy3; + pRhs->selFlags &= ~SF_MultiValue; if( yymsp[-1].minor.yy328!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy3); @@ -124116,13 +125699,16 @@ static void yy_reduce( break; case 121: /* values ::= values COMMA LP exprlist RP */ { - Select *pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0); + Select *pRight, *pLeft = yymsp[-4].minor.yy3; + pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); + if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; - pRight->pPrior = yymsp[-4].minor.yy3; + pLeft = yymsp[-4].minor.yy3; + pRight->pPrior = pLeft; yygotominor.yy3 = pRight; }else{ - yygotominor.yy3 = yymsp[-4].minor.yy3; + yygotominor.yy3 = pLeft; } } break; @@ -124407,7 +125993,7 @@ static void yy_reduce( break; case 193: /* expr ::= expr COLLATE ID|STRING */ { - yygotominor.yy346.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy346.pExpr, &yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy346.pExpr, &yymsp[0].minor.yy0, 1); yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart; yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } @@ -124570,7 +126156,7 @@ static void yy_reduce( yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0); if( yygotominor.yy346.pExpr ){ yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy14; - sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr); }else{ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); } @@ -124585,8 +126171,8 @@ static void yy_reduce( yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); if( yygotominor.yy346.pExpr ){ yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3; - ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr); }else{ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } @@ -124599,8 +126185,8 @@ static void yy_reduce( yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0); if( yygotominor.yy346.pExpr ){ yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3; - ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr); }else{ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } @@ -124615,8 +126201,8 @@ static void yy_reduce( yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy346.pExpr, 0, 0); if( yygotominor.yy346.pExpr ){ yygotominor.yy346.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } @@ -124630,8 +126216,8 @@ static void yy_reduce( Expr *p = yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ p->x.pSelect = yymsp[-1].minor.yy3; - ExprSetProperty(p, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, p); + ExprSetProperty(p, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, p); }else{ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } @@ -124644,7 +126230,7 @@ static void yy_reduce( yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy132, 0, 0); if( yygotominor.yy346.pExpr ){ yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy132 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy132) : yymsp[-2].minor.yy14; - sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr); }else{ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14); sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy132); @@ -124687,7 +126273,7 @@ static void yy_reduce( break; case 244: /* idxlist ::= idxlist COMMA nm collate sortorder */ { - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0, 1); yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, p); sqlite3ExprListSetName(pParse,yygotominor.yy14,&yymsp[-2].minor.yy0,1); sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index"); @@ -124696,7 +126282,7 @@ static void yy_reduce( break; case 245: /* idxlist ::= nm collate sortorder */ { - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0, 1); yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, p); sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index"); @@ -125886,10 +127472,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ - -#ifdef SQLITE_ENABLE_API_ARMOR - if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT; -#endif + assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( db->nVdbeActive==0 ){ db->u1.isInterrupted = 0; @@ -125929,10 +127512,8 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr break; } case TK_ILLEGAL: { - sqlite3DbFree(db, *pzErrMsg); - *pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"", + sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &pParse->sLastToken); - nErr++; goto abort_parse; } case TK_SEMI: { @@ -125950,17 +127531,22 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr } } abort_parse: - if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ + assert( nErr==0 ); + if( zSql[i]==0 && pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ if( lastTokenParsed!=TK_SEMI ){ sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); pParse->zTail = &zSql[i]; } - sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); + if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ + sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); + } } #ifdef YYTRACKMAXSTACKDEPTH + sqlite3_mutex_enter(sqlite3MallocMutex()); sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(pEngine) ); + sqlite3_mutex_leave(sqlite3MallocMutex()); #endif /* YYDEBUG */ sqlite3ParserFree(pEngine, sqlite3_free); db->lookaside.bEnabled = enableLookaside; @@ -126014,9 +127600,7 @@ abort_parse: pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(db, p); } - if( nErr>0 && pParse->rc==SQLITE_OK ){ - pParse->rc = SQLITE_ERROR; - } + assert( nErr==0 || pParse->rc!=SQLITE_OK ); return nErr; } @@ -126124,7 +127708,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[]; ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ -SQLITE_API int sqlite3_complete(const char *zSql){ +SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ @@ -126289,10 +127873,10 @@ SQLITE_API int sqlite3_complete(const char *zSql){ ** above, except that the parameter is required to be UTF-16 encoded, not ** UTF-8. */ -SQLITE_API int sqlite3_complete16(const void *zSql){ +SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *zSql){ sqlite3_value *pVal; char const *zSql8; - int rc = SQLITE_NOMEM; + int rc; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); @@ -126439,24 +128023,36 @@ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; /* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns ** a pointer to the to the sqlite3_version[] string constant. */ -SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } +SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void){ return sqlite3_version; } /* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a ** pointer to a string constant whose value is the same as the ** SQLITE_SOURCE_ID C preprocessor macro. */ -SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } +SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function ** returns an integer equal to SQLITE_VERSION_NUMBER. */ -SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } +SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } /* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns ** zero if and only if SQLite was compiled with mutexing code omitted due to ** the SQLITE_THREADSAFE compile-time option being set to 0. */ -SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } +SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } + +/* +** When compiling the test fixture or with debugging enabled (on Win32), +** this variable being set to non-zero will cause OSTRACE macros to emit +** extra diagnostic information. +*/ +#ifdef SQLITE_HAVE_OS_TRACE +# ifndef SQLITE_DEBUG_OS_TRACE +# define SQLITE_DEBUG_OS_TRACE 0 +# endif + int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; +#endif #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) /* @@ -126465,7 +128061,7 @@ SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } ** I/O active are written using this function. These messages ** are intended for debugging activity only. */ -/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0; +SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0; #endif /* @@ -126517,7 +128113,7 @@ SQLITE_API char *sqlite3_data_directory = 0; ** * Recursive calls to this routine from thread X return immediately ** without blocking. */ -SQLITE_API int sqlite3_initialize(void){ +SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ int rc; /* Result code */ #ifdef SQLITE_EXTRA_INIT @@ -126531,6 +128127,11 @@ SQLITE_API int sqlite3_initialize(void){ } #endif + /* If the following assert() fails on some obscure processor/compiler + ** combination, the work-around is to set the correct pointer + ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */ + assert( SQLITE_PTRSIZE==sizeof(char*) ); + /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end @@ -126673,7 +128274,7 @@ SQLITE_API int sqlite3_initialize(void){ ** on when SQLite is already shut down. If SQLite is already shut down ** when this routine is invoked, then this routine is a harmless no-op. */ -SQLITE_API int sqlite3_shutdown(void){ +SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void){ #ifdef SQLITE_OMIT_WSD int rc = sqlite3_wsd_init(4096, 24); if( rc!=SQLITE_OK ){ @@ -126727,7 +128328,7 @@ SQLITE_API int sqlite3_shutdown(void){ ** threadsafe. Failure to heed these warnings can lead to unpredictable ** behavior. */ -SQLITE_API int sqlite3_config(int op, ...){ +SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; @@ -126743,26 +128344,28 @@ SQLITE_API int sqlite3_config(int op, ...){ */ #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */ case SQLITE_CONFIG_SINGLETHREAD: { - /* Disable all mutexing */ - sqlite3GlobalConfig.bCoreMutex = 0; - sqlite3GlobalConfig.bFullMutex = 0; + /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to + ** Single-thread. */ + sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */ + sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */ case SQLITE_CONFIG_MULTITHREAD: { - /* Disable mutexing of database connections */ - /* Enable mutexing of core data structures */ - sqlite3GlobalConfig.bCoreMutex = 1; - sqlite3GlobalConfig.bFullMutex = 0; + /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to + ** Multi-thread. */ + sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ + sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */ case SQLITE_CONFIG_SERIALIZED: { - /* Enable all mutexing */ - sqlite3GlobalConfig.bCoreMutex = 1; - sqlite3GlobalConfig.bFullMutex = 1; + /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to + ** Serialized. */ + sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ + sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */ break; } #endif @@ -126874,7 +128477,8 @@ SQLITE_API int sqlite3_config(int op, ...){ case SQLITE_CONFIG_HEAP: { /* EVIDENCE-OF: R-19854-42126 There are three arguments to ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the - ** number of bytes in the memory buffer, and the minimum allocation size. */ + ** number of bytes in the memory buffer, and the minimum allocation size. + */ sqlite3GlobalConfig.pHeap = va_arg(ap, void*); sqlite3GlobalConfig.nHeap = va_arg(ap, int); sqlite3GlobalConfig.mnReq = va_arg(ap, int); @@ -126979,7 +128583,9 @@ SQLITE_API int sqlite3_config(int op, ...){ ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE ** compile-time option. */ - if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ) mxMmap = SQLITE_MAX_MMAP_SIZE; + if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){ + mxMmap = SQLITE_MAX_MMAP_SIZE; + } if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE; if( szMmap>mxMmap) szMmap = mxMmap; sqlite3GlobalConfig.mxMmap = mxMmap; @@ -127079,7 +128685,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ /* ** Return the mutex associated with a database connection. */ -SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -127093,7 +128699,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ ** Free up as much memory as we can from the given database ** connection. */ -SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){ +SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3 *db){ int i; #ifdef SQLITE_ENABLE_API_ARMOR @@ -127116,7 +128722,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){ /* ** Configuration settings for an individual database connection */ -SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ +SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; va_start(ap, op); @@ -127235,7 +128841,7 @@ static int nocaseCollatingFunc( /* ** Return the ROWID of the most recent insert */ -SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ +SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -127248,7 +128854,7 @@ SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ /* ** Return the number of changes in the most recent call to sqlite3_exec(). */ -SQLITE_API int sqlite3_changes(sqlite3 *db){ +SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -127261,7 +128867,7 @@ SQLITE_API int sqlite3_changes(sqlite3 *db){ /* ** Return the number of changes since the database handle was opened. */ -SQLITE_API int sqlite3_total_changes(sqlite3 *db){ +SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -127403,8 +129009,8 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ ** unclosed resources, and arranges for deallocation when the last ** prepare statement or sqlite3_backup closes. */ -SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } -SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } +SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } +SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } /* @@ -127587,7 +129193,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ ** Return a static string containing the name corresponding to the error code ** specified in the argument. */ -#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST) +#if defined(SQLITE_NEED_ERR_NAME) SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ const char *zName = 0; int i, origRc = rc; @@ -127811,13 +129417,13 @@ SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. */ -SQLITE_API int sqlite3_busy_handler( +SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler( sqlite3 *db, int (*xBusy)(void*,int), void *pArg ){ #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE; + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); db->busyHandler.xFunc = xBusy; @@ -127834,7 +129440,7 @@ SQLITE_API int sqlite3_busy_handler( ** given callback function with the given argument. The progress callback will ** be invoked every nOps opcodes. */ -SQLITE_API void sqlite3_progress_handler( +SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler( sqlite3 *db, int nOps, int (*xProgress)(void*), @@ -127865,7 +129471,7 @@ SQLITE_API void sqlite3_progress_handler( ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ -SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ +SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3 *db, int ms){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif @@ -127881,7 +129487,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ /* ** Cause any pending operation to stop at its earliest opportunity. */ -SQLITE_API void sqlite3_interrupt(sqlite3 *db){ +SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -127998,7 +129604,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc( /* ** Create new user functions. */ -SQLITE_API int sqlite3_create_function( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function( sqlite3 *db, const char *zFunc, int nArg, @@ -128012,7 +129618,7 @@ SQLITE_API int sqlite3_create_function( xFinal, 0); } -SQLITE_API int sqlite3_create_function_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( sqlite3 *db, const char *zFunc, int nArg, @@ -128055,7 +129661,7 @@ SQLITE_API int sqlite3_create_function_v2( } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API int sqlite3_create_function16( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -128095,7 +129701,7 @@ SQLITE_API int sqlite3_create_function16( ** A global function must exist in order for name resolution to work ** properly. */ -SQLITE_API int sqlite3_overload_function( +SQLITE_API int SQLITE_STDCALL sqlite3_overload_function( sqlite3 *db, const char *zName, int nArg @@ -128127,7 +129733,7 @@ SQLITE_API int sqlite3_overload_function( ** trace is a pointer to a function that is invoked at the start of each ** SQL statement. */ -SQLITE_API void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ +SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ void *pOld; #ifdef SQLITE_ENABLE_API_ARMOR @@ -128151,7 +129757,7 @@ SQLITE_API void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), v ** profile is a pointer to a function that is invoked at the conclusion of ** each SQL statement that is run. */ -SQLITE_API void *sqlite3_profile( +SQLITE_API void *SQLITE_STDCALL sqlite3_profile( sqlite3 *db, void (*xProfile)(void*,const char*,sqlite_uint64), void *pArg @@ -128178,7 +129784,7 @@ SQLITE_API void *sqlite3_profile( ** If the invoked function returns non-zero, then the commit becomes a ** rollback. */ -SQLITE_API void *sqlite3_commit_hook( +SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook( sqlite3 *db, /* Attach the hook to this database */ int (*xCallback)(void*), /* Function to invoke on each commit */ void *pArg /* Argument to the function */ @@ -128203,7 +129809,7 @@ SQLITE_API void *sqlite3_commit_hook( ** Register a callback to be invoked each time a row is updated, ** inserted or deleted using this database connection. */ -SQLITE_API void *sqlite3_update_hook( +SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), void *pArg /* Argument to the function */ @@ -128228,7 +129834,7 @@ SQLITE_API void *sqlite3_update_hook( ** Register a callback to be invoked each time a transaction is rolled ** back by this database connection. */ -SQLITE_API void *sqlite3_rollback_hook( +SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*), /* Callback function */ void *pArg /* Argument to the function */ @@ -128282,7 +129888,7 @@ SQLITE_PRIVATE int sqlite3WalDefaultHook( ** using sqlite3_wal_hook() disables the automatic checkpoint mechanism ** configured by this function. */ -SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ +SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ #ifdef SQLITE_OMIT_WAL UNUSED_PARAMETER(db); UNUSED_PARAMETER(nFrame); @@ -128303,7 +129909,7 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ ** Register a callback to be invoked each time a transaction is written ** into the write-ahead-log by this database connection. */ -SQLITE_API void *sqlite3_wal_hook( +SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( sqlite3 *db, /* Attach the hook to this db handle */ int(*xCallback)(void *, sqlite3*, const char*, int), void *pArg /* First argument passed to xCallback() */ @@ -128330,7 +129936,7 @@ SQLITE_API void *sqlite3_wal_hook( /* ** Checkpoint database zDb. */ -SQLITE_API int sqlite3_wal_checkpoint_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -128369,6 +129975,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( rc = SQLITE_ERROR; sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb); }else{ + db->busyHandler.nBusy = 0; rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); sqlite3Error(db, rc); } @@ -128384,7 +129991,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( ** to contains a zero-length string, all attached databases are ** checkpointed. */ -SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ +SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); @@ -128473,7 +130080,7 @@ SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){ ** Return UTF-8 encoded English language explanation of the most recent ** error. */ -SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); @@ -128501,7 +130108,7 @@ SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ ** Return UTF-16 encoded English language explanation of the most recent ** error. */ -SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ +SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){ static const u16 outOfMem[] = { 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0 }; @@ -128546,7 +130153,7 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ ** Return the most recent error code generated by an SQLite routine. If NULL is ** passed to this function, we assume a malloc() failed during sqlite3_open(). */ -SQLITE_API int sqlite3_errcode(sqlite3 *db){ +SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db){ if( db && !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -128555,7 +130162,7 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db){ } return db->errCode & db->errMask; } -SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ +SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db){ if( db && !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -128570,7 +130177,7 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ ** argument. For now, this simply calls the internal sqlite3ErrStr() ** function. */ -SQLITE_API const char *sqlite3_errstr(int rc){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int rc){ return sqlite3ErrStr(rc); } @@ -128718,7 +130325,7 @@ static const int aHardLimit[] = { ** It merely prevents new constructs that exceed the limit ** from forming. */ -SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ +SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ int oldLimit; #ifdef SQLITE_ENABLE_API_ARMOR @@ -128811,18 +130418,30 @@ SQLITE_PRIVATE int sqlite3ParseUri( int eState; /* Parser state when parsing URI */ int iIn; /* Input character index */ int iOut = 0; /* Output character index */ - int nByte = nUri+2; /* Bytes of space to allocate */ + u64 nByte = nUri+2; /* Bytes of space to allocate */ /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen ** method that there may be extra parameters following the file-name. */ flags |= SQLITE_OPEN_URI; for(iIn=0; iInmallocFailed && rc==SQLITE_OK){ + int sqlite3_dbstat_register(sqlite3*); + rc = sqlite3_dbstat_register(db); + } +#endif + /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. @@ -129262,7 +130891,8 @@ static int openDatabase( opendb_out: sqlite3_free(zOpen); if( db ){ - assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); + assert( db->mutex!=0 || isThreadsafe==0 + || sqlite3GlobalConfig.bFullMutex==0 ); sqlite3_mutex_leave(db->mutex); } rc = sqlite3_errcode(db); @@ -129287,14 +130917,14 @@ opendb_out: /* ** Open a new database handle. */ -SQLITE_API int sqlite3_open( +SQLITE_API int SQLITE_STDCALL sqlite3_open( const char *zFilename, sqlite3 **ppDb ){ return openDatabase(zFilename, ppDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); } -SQLITE_API int sqlite3_open_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -129307,7 +130937,7 @@ SQLITE_API int sqlite3_open_v2( /* ** Open a new database handle. */ -SQLITE_API int sqlite3_open16( +SQLITE_API int SQLITE_STDCALL sqlite3_open16( const void *zFilename, sqlite3 **ppDb ){ @@ -129346,7 +130976,7 @@ SQLITE_API int sqlite3_open16( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int sqlite3_create_collation( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( sqlite3* db, const char *zName, int enc, @@ -129359,7 +130989,7 @@ SQLITE_API int sqlite3_create_collation( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int sqlite3_create_collation_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( sqlite3* db, const char *zName, int enc, @@ -129384,7 +131014,7 @@ SQLITE_API int sqlite3_create_collation_v2( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int sqlite3_create_collation16( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( sqlite3* db, const void *zName, int enc, @@ -129414,7 +131044,7 @@ SQLITE_API int sqlite3_create_collation16( ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ -SQLITE_API int sqlite3_collation_needed( +SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) @@ -129435,7 +131065,7 @@ SQLITE_API int sqlite3_collation_needed( ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ -SQLITE_API int sqlite3_collation_needed16( +SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) @@ -129457,7 +131087,7 @@ SQLITE_API int sqlite3_collation_needed16( ** This function is now an anachronism. It used to be used to recover from a ** malloc() failure, but SQLite now does this automatically. */ -SQLITE_API int sqlite3_global_recover(void){ +SQLITE_API int SQLITE_STDCALL sqlite3_global_recover(void){ return SQLITE_OK; } #endif @@ -129468,7 +131098,7 @@ SQLITE_API int sqlite3_global_recover(void){ ** by default. Autocommit is disabled by a BEGIN statement and reenabled ** by the next COMMIT or ROLLBACK. */ -SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ +SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -129520,7 +131150,7 @@ SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ ** SQLite no longer uses thread-specific data so this routine is now a ** no-op. It is retained for historical compatibility. */ -SQLITE_API void sqlite3_thread_cleanup(void){ +SQLITE_API void SQLITE_STDCALL sqlite3_thread_cleanup(void){ } #endif @@ -129528,7 +131158,7 @@ SQLITE_API void sqlite3_thread_cleanup(void){ ** Return meta information about a specific column of a database table. ** See comment in sqlite3.h (sqlite.h.in) for details. */ -SQLITE_API int sqlite3_table_column_metadata( +SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -129544,13 +131174,19 @@ SQLITE_API int sqlite3_table_column_metadata( Table *pTab = 0; Column *pCol = 0; int iCol = 0; - char const *zDataType = 0; char const *zCollSeq = 0; int notnull = 0; int primarykey = 0; int autoinc = 0; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + /* Ensure the database schema has been loaded */ sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); @@ -129640,7 +131276,7 @@ error_out: /* ** Sleep for a little while. Return the amount of time slept. */ -SQLITE_API int sqlite3_sleep(int ms){ +SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int ms){ sqlite3_vfs *pVfs; int rc; pVfs = sqlite3_vfs_find(0); @@ -129656,7 +131292,7 @@ SQLITE_API int sqlite3_sleep(int ms){ /* ** Enable or disable the extended result codes. */ -SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ +SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3 *db, int onoff){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif @@ -129669,7 +131305,7 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ /* ** Invoke the xFileControl method on a particular database. */ -SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ +SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ int rc = SQLITE_ERROR; Btree *pBtree; @@ -129697,13 +131333,13 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo sqlite3BtreeLeave(pBtree); } sqlite3_mutex_leave(db->mutex); - return rc; + return rc; } /* ** Interface to the testing logic. */ -SQLITE_API int sqlite3_test_control(int op, ...){ +SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ int rc = 0; #ifndef SQLITE_OMIT_BUILTIN_TEST va_list ap; @@ -130000,6 +131636,35 @@ SQLITE_API int sqlite3_test_control(int op, ...){ if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR; break; } + + /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); + ** + ** This test control is used to create imposter tables. "db" is a pointer + ** to the database connection. dbName is the database name (ex: "main" or + ** "temp") which will receive the imposter. "onOff" turns imposter mode on + ** or off. "tnum" is the root page of the b-tree to which the imposter + ** table should connect. + ** + ** Enable imposter mode only when the schema has already been parsed. Then + ** run a single CREATE TABLE statement to construct the imposter table in + ** the parsed schema. Then turn imposter mode back off again. + ** + ** If onOff==0 and tnum>0 then reset the schema for all databases, causing + ** the schema to be reparsed the next time it is needed. This has the + ** effect of erasing all imposter tables. + */ + case SQLITE_TESTCTRL_IMPOSTER: { + sqlite3 *db = va_arg(ap, sqlite3*); + sqlite3_mutex_enter(db->mutex); + db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); + db->init.busy = db->init.imposterTable = va_arg(ap,int); + db->init.newTnum = va_arg(ap,int); + if( db->init.busy==0 && db->init.newTnum>0 ){ + sqlite3ResetAllSchemasOfConnection(db); + } + sqlite3_mutex_leave(db->mutex); + break; + } } va_end(ap); #endif /* SQLITE_OMIT_BUILTIN_TEST */ @@ -130017,7 +131682,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** parameter if it exists. If the parameter does not exist, this routine ** returns a NULL pointer. */ -SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam){ if( zFilename==0 || zParam==0 ) return 0; zFilename += sqlite3Strlen30(zFilename) + 1; while( zFilename[0] ){ @@ -130032,7 +131697,7 @@ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char * /* ** Return a boolean value for a query parameter. */ -SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ +SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ const char *z = sqlite3_uri_parameter(zFilename, zParam); bDflt = bDflt!=0; return z ? sqlite3GetBoolean(z, bDflt) : bDflt; @@ -130041,7 +131706,7 @@ SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, in /* ** Return a 64-bit integer value for a query parameter. */ -SQLITE_API sqlite3_int64 sqlite3_uri_int64( +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64( const char *zFilename, /* Filename as passed to xOpen */ const char *zParam, /* URI parameter sought */ sqlite3_int64 bDflt /* return if parameter is missing */ @@ -130073,7 +131738,7 @@ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ ** Return the filename of the database associated with a database ** connection. */ -SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ +SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName){ Btree *pBt; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ @@ -130089,7 +131754,7 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ ** Return 1 if database is read-only or 0 if read/write. Return -1 if ** no such database exists. */ -SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ +SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ Btree *pBt; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ @@ -130248,7 +131913,7 @@ static void leaveMutex(void){ ** on the same "db". If xNotify==0 then any prior callbacks are immediately ** cancelled. */ -SQLITE_API int sqlite3_unlock_notify( +SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( sqlite3 *db, void (*xNotify)(void **, int), void *pArg @@ -131142,6 +132807,11 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi #ifdef SQLITE_COVERAGE_TEST # define ALWAYS(x) (1) # define NEVER(X) (0) +#elif defined(SQLITE_DEBUG) +# define ALWAYS(x) sqlite3Fts3Always((x)!=0) +# define NEVER(x) sqlite3Fts3Never((x)!=0) +SQLITE_PRIVATE int sqlite3Fts3Always(int b); +SQLITE_PRIVATE int sqlite3Fts3Never(int b); #else # define ALWAYS(x) (x) # define NEVER(x) (x) @@ -131383,6 +133053,11 @@ struct Fts3Phrase { int bIncr; /* True if doclist is loaded incrementally */ int iDoclistToken; + /* Used by sqlite3Fts3EvalPhrasePoslist() if this is a descendent of an + ** OR condition. */ + char *pOrPoslist; + i64 iOrDocid; + /* Variables below this point are populated by fts3_expr.c when parsing ** a MATCH expression. Everything above is part of the evaluation phase. */ @@ -131537,6 +133212,7 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); ) /* fts3.c */ +SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...); SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); @@ -131626,6 +133302,13 @@ static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); +#ifndef SQLITE_AMALGAMATION +# if defined(SQLITE_DEBUG) +SQLITE_PRIVATE int sqlite3Fts3Always(int b) { assert( b ); return b; } +SQLITE_PRIVATE int sqlite3Fts3Never(int b) { assert( !b ); return b; } +# endif +#endif + /* ** Write a 64-bit variable-length integer to memory starting at p[0]. ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. @@ -131735,7 +133418,7 @@ SQLITE_PRIVATE void sqlite3Fts3Dequote(char *z){ /* If the first byte was a '[', then the close-quote character is a ']' */ if( quote=='[' ) quote = ']'; - while( ALWAYS(z[iIn]) ){ + while( z[iIn] ){ if( z[iIn]==quote ){ if( z[iIn+1]!=quote ) break; z[iOut++] = quote; @@ -131814,6 +133497,17 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ return SQLITE_OK; } +/* +** Write an error message into *pzErr +*/ +SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){ + va_list ap; + sqlite3_free(*pzErr); + va_start(ap, zFormat); + *pzErr = sqlite3_vmprintf(zFormat, ap); + va_end(ap); +} + /* ** Construct one or more SQL statements from the format string given ** and then evaluate those statements. The success code is written @@ -132223,11 +133917,16 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){ ** This function is used when parsing the "prefix=" FTS4 parameter. */ static int fts3GobbleInt(const char **pp, int *pnOut){ + const int MAX_NPREFIX = 10000000; const char *p; /* Iterator pointer */ int nInt = 0; /* Output value */ for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ nInt = nInt * 10 + (p[0] - '0'); + if( nInt>MAX_NPREFIX ){ + nInt = 0; + break; + } } if( p==*pp ) return SQLITE_ERROR; *pnOut = nInt; @@ -132270,7 +133969,6 @@ static int fts3PrefixParameter( aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); *apIndex = aIndex; - *pnIndex = nIndex; if( !aIndex ){ return SQLITE_NOMEM; } @@ -132280,13 +133978,20 @@ static int fts3PrefixParameter( const char *p = zParam; int i; for(i=1; i=0 ); + if( nPrefix==0 ){ + nIndex--; + i--; + }else{ + aIndex[i].nPrefix = nPrefix; + } p++; } } + *pnIndex = nIndex; return SQLITE_OK; } @@ -132321,7 +134026,8 @@ static int fts3ContentColumns( const char *zTbl, /* Name of content table */ const char ***pazCol, /* OUT: Malloc'd array of column names */ int *pnCol, /* OUT: Size of array *pazCol */ - int *pnStr /* OUT: Bytes of string content */ + int *pnStr, /* OUT: Bytes of string content */ + char **pzErr /* OUT: error message */ ){ int rc = SQLITE_OK; /* Return code */ char *zSql; /* "SELECT *" statement on zTbl */ @@ -132332,6 +134038,9 @@ static int fts3ContentColumns( rc = SQLITE_NOMEM; }else{ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db)); + } } sqlite3_free(zSql); @@ -132410,7 +134119,7 @@ static int fts3InitVtab( const char **aCol; /* Array of column names */ sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ - int nIndex; /* Size of aIndex[] array */ + int nIndex = 0; /* Size of aIndex[] array */ struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ /* The results of parsing supported FTS4 key=value options: */ @@ -132498,13 +134207,13 @@ static int fts3InitVtab( } } if( iOpt==SizeofArray(aFts4Opt) ){ - *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z); + sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); rc = SQLITE_ERROR; }else{ switch( iOpt ){ case 0: /* MATCHINFO */ if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ - *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal); + sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); rc = SQLITE_ERROR; } bNoDocsize = 1; @@ -132532,7 +134241,7 @@ static int fts3InitVtab( if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) ){ - *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal); + sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); rc = SQLITE_ERROR; } bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); @@ -132583,7 +134292,7 @@ static int fts3InitVtab( if( nCol==0 ){ sqlite3_free((void*)aCol); aCol = 0; - rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); + rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); /* If a languageid= option was specified, remove the language id ** column from the aCol[] array. */ @@ -132618,7 +134327,7 @@ static int fts3InitVtab( rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex); if( rc==SQLITE_ERROR ){ assert( zPrefix ); - *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix); + sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix); } if( rc!=SQLITE_OK ) goto fts3_init_out; @@ -132700,7 +134409,7 @@ static int fts3InitVtab( } for(i=0; izReadExprlist = fts3ReadExprList(p, zUncompress, &rc); p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); @@ -133804,26 +135513,33 @@ static int fts3DoclistOrMerge( ** ** The right-hand input doclist is overwritten by this function. */ -static void fts3DoclistPhraseMerge( +static int fts3DoclistPhraseMerge( int bDescDoclist, /* True if arguments are desc */ int nDist, /* Distance from left to right (1=adjacent) */ char *aLeft, int nLeft, /* Left doclist */ - char *aRight, int *pnRight /* IN/OUT: Right/output doclist */ + char **paRight, int *pnRight /* IN/OUT: Right/output doclist */ ){ sqlite3_int64 i1 = 0; sqlite3_int64 i2 = 0; sqlite3_int64 iPrev = 0; + char *aRight = *paRight; char *pEnd1 = &aLeft[nLeft]; char *pEnd2 = &aRight[*pnRight]; char *p1 = aLeft; char *p2 = aRight; char *p; int bFirstOut = 0; - char *aOut = aRight; + char *aOut; assert( nDist>0 ); - + if( bDescDoclist ){ + aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX); + if( aOut==0 ) return SQLITE_NOMEM; + }else{ + aOut = aRight; + } p = aOut; + fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); @@ -133852,6 +135568,12 @@ static void fts3DoclistPhraseMerge( } *pnRight = (int)(p - aOut); + if( bDescDoclist ){ + sqlite3_free(aRight); + *paRight = aOut; + } + + return SQLITE_OK; } /* @@ -133976,8 +135698,22 @@ static int fts3TermSelectMerge( ){ if( pTS->aaOutput[0]==0 ){ /* If this is the first term selected, copy the doclist to the output - ** buffer using memcpy(). */ - pTS->aaOutput[0] = sqlite3_malloc(nDoclist); + ** buffer using memcpy(). + ** + ** Add FTS3_VARINT_MAX bytes of unused space to the end of the + ** allocation. This is so as to ensure that the buffer is big enough + ** to hold the current doclist AND'd with any other doclist. If the + ** doclists are stored in order=ASC order, this padding would not be + ** required (since the size of [doclistA AND doclistB] is always less + ** than or equal to the size of [doclistA] in that case). But this is + ** not true for order=DESC. For example, a doclist containing (1, -1) + ** may be smaller than (-1), as in the first example the -1 may be stored + ** as a single-byte delta, whereas in the second it must be stored as a + ** FTS3_VARINT_MAX byte varint. + ** + ** Similar padding is added in the fts3DoclistOrMerge() function. + */ + pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); pTS->anOutput[0] = nDoclist; if( pTS->aaOutput[0] ){ memcpy(pTS->aaOutput[0], aDoclist, nDoclist); @@ -134074,7 +135810,7 @@ static int fts3SegReaderCursor( ** calls out here. */ if( iLevel<0 && p->aIndex ){ Fts3SegReader *pSeg = 0; - rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg); + rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg); if( rc==SQLITE_OK && pSeg ){ rc = fts3SegReaderCursorAppend(pCsr, pSeg); } @@ -134477,10 +136213,17 @@ static int fts3FilterMethod( ** row by docid. */ if( eSearch==FTS3_FULLSCAN_SEARCH ){ - zSql = sqlite3_mprintf( - "SELECT %s ORDER BY rowid %s", - p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") - ); + if( pDocidGe || pDocidLe ){ + zSql = sqlite3_mprintf( + "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s", + p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid, + (pCsr->bDesc ? "DESC" : "ASC") + ); + }else{ + zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", + p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") + ); + } if( zSql ){ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); sqlite3_free(zSql); @@ -134716,11 +136459,31 @@ static void fts3ReversePoslist(char *pStart, char **ppPoslist){ char *p = &(*ppPoslist)[-2]; char c = 0; + /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */ while( p>pStart && (c=*p--)==0 ); + + /* Search backwards for a varint with value zero (the end of the previous + ** poslist). This is an 0x00 byte preceded by some byte that does not + ** have the 0x80 bit set. */ while( p>pStart && (*p & 0x80) | c ){ c = *p--; } - if( p>pStart ){ p = &p[2]; } + assert( p==pStart || c==0 ); + + /* At this point p points to that preceding byte without the 0x80 bit + ** set. So to find the start of the poslist, skip forward 2 bytes then + ** over a varint. + ** + ** Normally. The other case is that p==pStart and the poslist to return + ** is the first in the doclist. In this case do not skip forward 2 bytes. + ** The second part of the if condition (c==0 && *ppPoslist>&p[2]) + ** is required for cases where the first byte of a doclist and the + ** doclist is empty. For example, if the first docid is 10, a doclist + ** that begins with: + ** + ** 0x0A 0x00 + */ + if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; } while( *p++&0x80 ); *ppPoslist = p; } @@ -134791,6 +136554,8 @@ static void fts3SnippetFunc( } if( !zEllipsis || !zEnd || !zStart ){ sqlite3_result_error_nomem(pContext); + }else if( nToken==0 ){ + sqlite3_result_text(pContext, "", -1, SQLITE_STATIC); }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); } @@ -135226,14 +136991,17 @@ static void fts3EvalAllocateReaders( ** This function assumes that pList points to a buffer allocated using ** sqlite3_malloc(). This function takes responsibility for eventually ** freeing the buffer. +** +** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs. */ -static void fts3EvalPhraseMergeToken( +static int fts3EvalPhraseMergeToken( Fts3Table *pTab, /* FTS Table pointer */ Fts3Phrase *p, /* Phrase to merge pList/nList into */ int iToken, /* Token pList/nList corresponds to */ char *pList, /* Pointer to doclist */ int nList /* Number of bytes in pList */ ){ + int rc = SQLITE_OK; assert( iToken!=p->iDoclistToken ); if( pList==0 ){ @@ -135272,13 +137040,16 @@ static void fts3EvalPhraseMergeToken( nDiff = p->iDoclistToken - iToken; } - fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight); + rc = fts3DoclistPhraseMerge( + pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight + ); sqlite3_free(pLeft); p->doclist.aAll = pRight; p->doclist.nAll = nRight; } if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; + return rc; } /* @@ -135304,7 +137075,7 @@ static int fts3EvalPhraseLoad( char *pThis = 0; rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); if( rc==SQLITE_OK ){ - fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); + rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); } } assert( pToken->pSegcsr==0 ); @@ -135846,12 +137617,14 @@ static void fts3EvalStartReaders( ){ if( pExpr && SQLITE_OK==*pRc ){ if( pExpr->eType==FTSQUERY_PHRASE ){ - int i; int nToken = pExpr->pPhrase->nToken; - for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; + if( nToken ){ + int i; + for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; + } + pExpr->bDeferred = (i==nToken); } - pExpr->bDeferred = (i==nToken); *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); }else{ fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); @@ -136106,9 +137879,13 @@ static int fts3EvalSelectDeferred( char *pList = 0; rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); assert( rc==SQLITE_OK || pList==0 ); + if( rc==SQLITE_OK ){ + rc = fts3EvalPhraseMergeToken( + pTab, pTC->pPhrase, pTC->iToken,pList,nList + ); + } if( rc==SQLITE_OK ){ int nCount; - fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList); nCount = fts3DoclistCountDocids( pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll ); @@ -136333,6 +138110,22 @@ static void fts3EvalNextRow( } pExpr->iDocid = pLeft->iDocid; pExpr->bEof = (pLeft->bEof || pRight->bEof); + if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){ + if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){ + Fts3Doclist *pDl = &pRight->pPhrase->doclist; + while( *pRc==SQLITE_OK && pRight->bEof==0 ){ + memset(pDl->pList, 0, pDl->nList); + fts3EvalNextRow(pCsr, pRight, pRc); + } + } + if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){ + Fts3Doclist *pDl = &pLeft->pPhrase->doclist; + while( *pRc==SQLITE_OK && pLeft->bEof==0 ){ + memset(pDl->pList, 0, pDl->nList); + fts3EvalNextRow(pCsr, pLeft, pRc); + } + } + } } break; } @@ -136705,6 +138498,7 @@ static void fts3EvalRestart( } pPhrase->doclist.pNextDocid = 0; pPhrase->doclist.iDocid = 0; + pPhrase->pOrPoslist = 0; } pExpr->iDocid = 0; @@ -136950,8 +138744,8 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( iDocid = pExpr->iDocid; pIter = pPhrase->doclist.pList; if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ + int rc = SQLITE_OK; int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ - int iMul; /* +1 if csr dir matches index dir, else -1 */ int bOr = 0; u8 bEof = 0; u8 bTreeEof = 0; @@ -136975,72 +138769,44 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( ** an incremental phrase. Load the entire doclist for the phrase ** into memory in this case. */ if( pPhrase->bIncr ){ - int rc = SQLITE_OK; - int bEofSave = pExpr->bEof; - fts3EvalRestart(pCsr, pExpr, &rc); - while( rc==SQLITE_OK && !pExpr->bEof ){ - fts3EvalNextRow(pCsr, pExpr, &rc); - if( bEofSave==0 && pExpr->iDocid==iDocid ) break; + int bEofSave = pNear->bEof; + fts3EvalRestart(pCsr, pNear, &rc); + while( rc==SQLITE_OK && !pNear->bEof ){ + fts3EvalNextRow(pCsr, pNear, &rc); + if( bEofSave==0 && pNear->iDocid==iDocid ) break; } - pIter = pPhrase->doclist.pList; assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); - if( rc!=SQLITE_OK ) return rc; } - - iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1); - while( bTreeEof==1 - && pNear->bEof==0 - && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0 - ){ - int rc = SQLITE_OK; - fts3EvalNextRow(pCsr, pExpr, &rc); - if( rc!=SQLITE_OK ) return rc; - iDocid = pExpr->iDocid; - pIter = pPhrase->doclist.pList; - } - - bEof = (pPhrase->doclist.nAll==0); - assert( bDescDoclist==0 || bDescDoclist==1 ); - assert( pCsr->bDesc==0 || pCsr->bDesc==1 ); - - if( bEof==0 ){ - if( pCsr->bDesc==bDescDoclist ){ - int dummy; - if( pNear->bEof ){ - /* This expression is already at EOF. So position it to point to the - ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable - ** iDocid is already set for this entry, so all that is required is - ** to set pIter to point to the first byte of the last position-list - ** in the doclist. - ** - ** It would also be correct to set pIter and iDocid to zero. In - ** this case, the first call to sqltie3Fts4DoclistPrev() below - ** would also move the iterator to point to the last entry in the - ** doclist. However, this is expensive, as to do so it has to - ** iterate through the entire doclist from start to finish (since - ** it does not know the docid for the last entry). */ - pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1]; - fts3ReversePoslist(pPhrase->doclist.aAll, &pIter); - } - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ - sqlite3Fts3DoclistPrev( - bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, - &pIter, &iDocid, &dummy, &bEof - ); - } - }else{ - if( pNear->bEof ){ - pIter = 0; - iDocid = 0; - } - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ - sqlite3Fts3DoclistNext( - bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, - &pIter, &iDocid, &bEof - ); - } + if( bTreeEof ){ + while( rc==SQLITE_OK && !pNear->bEof ){ + fts3EvalNextRow(pCsr, pNear, &rc); } } + if( rc!=SQLITE_OK ) return rc; + + pIter = pPhrase->pOrPoslist; + iDocid = pPhrase->iOrDocid; + if( pCsr->bDesc==bDescDoclist ){ + bEof = !pPhrase->doclist.nAll || + (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll)); + while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ + sqlite3Fts3DoclistNext( + bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, + &pIter, &iDocid, &bEof + ); + } + }else{ + bEof = !pPhrase->doclist.nAll || (pIter && pIter<=pPhrase->doclist.aAll); + while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ + int dummy; + sqlite3Fts3DoclistPrev( + bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, + &pIter, &iDocid, &dummy, &bEof + ); + } + } + pPhrase->pOrPoslist = pIter; + pPhrase->iOrDocid = iDocid; if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0; } @@ -137054,10 +138820,13 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( } while( iThisxCreate(iArg, aArg, ppTok); assert( rc!=SQLITE_OK || *ppTok ); if( rc!=SQLITE_OK ){ - *pzErr = sqlite3_mprintf("unknown tokenizer"); + sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer"); }else{ (*ppTok)->pModule = m; } @@ -140272,9 +142047,9 @@ static void testFunc( p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); if( !p ){ - char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); + char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName); + sqlite3_result_error(context, zErr2, -1); + sqlite3_free(zErr2); return; } @@ -140809,7 +142584,7 @@ static int fts3tokQueryTokenizer( p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); if( !p ){ - *pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName); + sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName); return SQLITE_ERROR; } @@ -141506,7 +143281,7 @@ static int fts3SqlStmt( /* 25 */ "", /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", -/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", +/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'", /* This statement is used to determine which level to read the input from ** when performing an incremental merge. It returns the absolute level number @@ -142805,7 +144580,10 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( ** an array of pending terms by term. This occurs as part of flushing ** the contents of the pending-terms hash table to the database. */ -static int fts3CompareElemByTerm(const void *lhs, const void *rhs){ +static int SQLITE_CDECL fts3CompareElemByTerm( + const void *lhs, + const void *rhs +){ char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); @@ -144621,7 +146399,8 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ int rc2; - sqlite3_bind_int(pAllLangid, 1, p->nIndex); + sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); + sqlite3_bind_int(pAllLangid, 2, p->nIndex); while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ int i; int iLangid = sqlite3_column_int(pAllLangid, 0); @@ -145953,7 +147732,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ pHint->n = i; i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); i += fts3GetVarint32(&pHint->a[i], pnInput); - if( i!=nHint ) return SQLITE_CORRUPT_VTAB; + if( i!=nHint ) return FTS_CORRUPT_VTAB; return SQLITE_OK; } @@ -146321,7 +148100,8 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ int rc2; - sqlite3_bind_int(pAllLangid, 1, p->nIndex); + sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); + sqlite3_bind_int(pAllLangid, 2, p->nIndex); while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ int iLangid = sqlite3_column_int(pAllLangid, 0); int i; @@ -146334,7 +148114,6 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ } /* This block calculates the checksum according to the %_content table */ - rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; sqlite3_stmt *pStmt = 0; @@ -146431,7 +148210,7 @@ static int fts3DoIntegrityCheck( int rc; int bOk = 0; rc = fts3IntegrityCheck(p, &bOk); - if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB; + if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; return rc; } @@ -146869,6 +148648,7 @@ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ #define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */ #define FTS3_MATCHINFO_LCS 's' /* nCol values */ #define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ +#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */ /* ** The default value for the second argument to matchinfo(). @@ -147284,37 +149064,39 @@ static int fts3BestSnippet( sIter.nSnippet = nSnippet; sIter.nPhrase = nList; sIter.iCurrent = -1; - (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); + rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); + if( rc==SQLITE_OK ){ - /* Set the *pmSeen output variable. */ - for(i=0; iiCol = iCol; - while( !fts3SnippetNextCandidate(&sIter) ){ - int iPos; - int iScore; - u64 mCover; - u64 mHighlight; - fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight); - assert( iScore>=0 ); - if( iScore>iBestScore ){ - pFragment->iPos = iPos; - pFragment->hlmask = mHighlight; - pFragment->covered = mCover; - iBestScore = iScore; + /* Loop through all candidate snippets. Store the best snippet in + ** *pFragment. Store its associated 'score' in iBestScore. + */ + pFragment->iCol = iCol; + while( !fts3SnippetNextCandidate(&sIter) ){ + int iPos; + int iScore; + u64 mCover; + u64 mHighlite; + fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover,&mHighlite); + assert( iScore>=0 ); + if( iScore>iBestScore ){ + pFragment->iPos = iPos; + pFragment->hlmask = mHighlite; + pFragment->covered = mCover; + iBestScore = iScore; + } } - } + *piScore = iBestScore; + } sqlite3_free(sIter.aPhrase); - *piScore = iBestScore; - return SQLITE_OK; + return rc; } @@ -147522,8 +149304,12 @@ static int fts3SnippetText( ** required. They are required if (a) this is not the first fragment, ** or (b) this fragment does not begin at position 0 of its column. */ - if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); + if( rc==SQLITE_OK ){ + if( iPos>0 || iFragment>0 ){ + rc = fts3StringAppend(pOut, zEllipsis, -1); + }else if( iBegin ){ + rc = fts3StringAppend(pOut, zDoc, iBegin); + } } if( rc!=SQLITE_OK || iCurrentpCursor->base.pVtab; + int rc = SQLITE_OK; + int iStart = iPhrase * p->nCol; + Fts3Expr *pEof; /* Ancestor node already at EOF */ + + /* This must be a phrase */ + assert( pExpr->pPhrase ); + + /* Initialize all output integers to zero. */ + memset(&p->aMatchinfo[iStart], 0, sizeof(u32) * p->nCol); + + /* Check if this or any parent node is at EOF. If so, then all output + ** values are zero. */ + for(pEof=pExpr; pEof && pEof->bEof==0; pEof=pEof->pParent); + + if( pEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){ + Fts3Phrase *pPhrase = pExpr->pPhrase; + char *pIter = pPhrase->doclist.pList; + int iCol = 0; + + while( 1 ){ + int nHit = fts3ColumnlistCount(&pIter); + if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){ + p->aMatchinfo[iStart + iCol] = (u32)nHit; + } + assert( *pIter==0x00 || *pIter==0x01 ); + if( *pIter!=0x01 ) break; + pIter++; + pIter += fts3GetVarint32(pIter, &iCol); + } + } + + return rc; +} + static int fts3MatchinfoCheck( Fts3Table *pTab, char cArg, @@ -147657,10 +149488,11 @@ static int fts3MatchinfoCheck( || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) || (cArg==FTS3_MATCHINFO_LCS) || (cArg==FTS3_MATCHINFO_HITS) + || (cArg==FTS3_MATCHINFO_LHITS) ){ return SQLITE_OK; } - *pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg); + sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg); return SQLITE_ERROR; } @@ -147680,6 +149512,10 @@ static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ nVal = pInfo->nCol; break; + case FTS3_MATCHINFO_LHITS: + nVal = pInfo->nCol * pInfo->nPhrase; + break; + default: assert( cArg==FTS3_MATCHINFO_HITS ); nVal = pInfo->nCol * pInfo->nPhrase * 3; @@ -147934,6 +149770,10 @@ static int fts3MatchinfoValues( } break; + case FTS3_MATCHINFO_LHITS: + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLHitsCb, (void*)pInfo); + break; + default: { Fts3Expr *pExpr; assert( zArg[i]==FTS3_MATCHINFO_HITS ); @@ -148089,7 +149929,7 @@ SQLITE_PRIVATE void sqlite3Fts3Snippet( */ for(iRead=0; iReadnColumn; iRead++){ SnippetFragment sF = {0, 0, 0, 0}; - int iS; + int iS = 0; if( iCol>=0 && iRead!=iCol ) continue; /* Find the best snippet of nFToken tokens in column iRead. */ @@ -151946,11 +153786,19 @@ static int rtreeUpdate( if( nData>1 ){ int ii; - /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ - assert( nData==(pRtree->nDim*2 + 3) ); + /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. + ** + ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared + ** with "column" that are interpreted as table constraints. + ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5)); + ** This problem was discovered after years of use, so we silently ignore + ** these kinds of misdeclared tables to avoid breaking any legacy. + */ + assert( nData<=(pRtree->nDim*2 + 3) ); + #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ + for(ii=0; iicell.aCoord[ii+1].f ){ @@ -151961,7 +153809,7 @@ static int rtreeUpdate( }else #endif { - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ + for(ii=0; iicell.aCoord[ii+1].i ){ @@ -152532,7 +154380,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ /* ** Register a new geometry function for use with the r-tree MATCH operator. */ -SQLITE_API int sqlite3_rtree_geometry_callback( +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( sqlite3 *db, /* Register SQL function on this connection */ const char *zGeom, /* Name of the new SQL function */ int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */ @@ -152556,7 +154404,7 @@ SQLITE_API int sqlite3_rtree_geometry_callback( ** Register a new 2nd-generation geometry function for use with the ** r-tree MATCH operator. */ -SQLITE_API int sqlite3_rtree_query_callback( +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( sqlite3 *db, /* Register SQL function on this connection */ const char *zQueryFunc, /* Name of new SQL function */ int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */ @@ -152581,7 +154429,7 @@ SQLITE_API int sqlite3_rtree_query_callback( #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int sqlite3_rtree_init( +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -153086,7 +154934,7 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int sqlite3_icu_init( +SQLITE_API int SQLITE_STDCALL sqlite3_icu_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -153361,3 +155209,631 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule( #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_icu.c ********************************************/ +/************** Begin file dbstat.c ******************************************/ +/* +** 2010 July 12 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains an implementation of the "dbstat" virtual table. +** +** The dbstat virtual table is used to extract low-level formatting +** information from an SQLite database in order to implement the +** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script +** for an example implementation. +*/ + +#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \ + && !defined(SQLITE_OMIT_VIRTUALTABLE) + +/* +** Page paths: +** +** The value of the 'path' column describes the path taken from the +** root-node of the b-tree structure to each page. The value of the +** root-node path is '/'. +** +** The value of the path for the left-most child page of the root of +** a b-tree is '/000/'. (Btrees store content ordered from left to right +** so the pages to the left have smaller keys than the pages to the right.) +** The next to left-most child of the root page is +** '/001', and so on, each sibling page identified by a 3-digit hex +** value. The children of the 451st left-most sibling have paths such +** as '/1c2/000/, '/1c2/001/' etc. +** +** Overflow pages are specified by appending a '+' character and a +** six-digit hexadecimal value to the path to the cell they are linked +** from. For example, the three overflow pages in a chain linked from +** the left-most cell of the 450th child of the root page are identified +** by the paths: +** +** '/1c2/000+000000' // First page in overflow chain +** '/1c2/000+000001' // Second page in overflow chain +** '/1c2/000+000002' // Third page in overflow chain +** +** If the paths are sorted using the BINARY collation sequence, then +** the overflow pages associated with a cell will appear earlier in the +** sort-order than its child page: +** +** '/1c2/000/' // Left-most child of 451st child of root +*/ +#define VTAB_SCHEMA \ + "CREATE TABLE xx( " \ + " name STRING, /* Name of table or index */" \ + " path INTEGER, /* Path to page from root */" \ + " pageno INTEGER, /* Page number */" \ + " pagetype STRING, /* 'internal', 'leaf' or 'overflow' */" \ + " ncell INTEGER, /* Cells on page (0 for overflow) */" \ + " payload INTEGER, /* Bytes of payload on this page */" \ + " unused INTEGER, /* Bytes of unused space on this page */" \ + " mx_payload INTEGER, /* Largest payload size of all cells */" \ + " pgoffset INTEGER, /* Offset of page in file */" \ + " pgsize INTEGER /* Size of the page */" \ + ");" + + +typedef struct StatTable StatTable; +typedef struct StatCursor StatCursor; +typedef struct StatPage StatPage; +typedef struct StatCell StatCell; + +struct StatCell { + int nLocal; /* Bytes of local payload */ + u32 iChildPg; /* Child node (or 0 if this is a leaf) */ + int nOvfl; /* Entries in aOvfl[] */ + u32 *aOvfl; /* Array of overflow page numbers */ + int nLastOvfl; /* Bytes of payload on final overflow page */ + int iOvfl; /* Iterates through aOvfl[] */ +}; + +struct StatPage { + u32 iPgno; + DbPage *pPg; + int iCell; + + char *zPath; /* Path to this page */ + + /* Variables populated by statDecodePage(): */ + u8 flags; /* Copy of flags byte */ + int nCell; /* Number of cells on page */ + int nUnused; /* Number of unused bytes on page */ + StatCell *aCell; /* Array of parsed cells */ + u32 iRightChildPg; /* Right-child page number (or 0) */ + int nMxPayload; /* Largest payload of any cell on this page */ +}; + +struct StatCursor { + sqlite3_vtab_cursor base; + sqlite3_stmt *pStmt; /* Iterates through set of root pages */ + int isEof; /* After pStmt has returned SQLITE_DONE */ + + StatPage aPage[32]; + int iPage; /* Current entry in aPage[] */ + + /* Values to return. */ + char *zName; /* Value of 'name' column */ + char *zPath; /* Value of 'path' column */ + u32 iPageno; /* Value of 'pageno' column */ + char *zPagetype; /* Value of 'pagetype' column */ + int nCell; /* Value of 'ncell' column */ + int nPayload; /* Value of 'payload' column */ + int nUnused; /* Value of 'unused' column */ + int nMxPayload; /* Value of 'mx_payload' column */ + i64 iOffset; /* Value of 'pgOffset' column */ + int szPage; /* Value of 'pgSize' column */ +}; + +struct StatTable { + sqlite3_vtab base; + sqlite3 *db; +}; + +#ifndef get2byte +# define get2byte(x) ((x)[0]<<8 | (x)[1]) +#endif + +/* +** Connect to or create a statvfs virtual table. +*/ +static int statConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + StatTable *pTab = 0; + int rc = SQLITE_OK; + + rc = sqlite3_declare_vtab(db, VTAB_SCHEMA); + if( rc==SQLITE_OK ){ + pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable)); + if( pTab==0 ) rc = SQLITE_NOMEM; + } + + assert( rc==SQLITE_OK || pTab==0 ); + if( rc==SQLITE_OK ){ + memset(pTab, 0, sizeof(StatTable)); + pTab->db = db; + } + + *ppVtab = (sqlite3_vtab*)pTab; + return rc; +} + +/* +** Disconnect from or destroy a statvfs virtual table. +*/ +static int statDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* +** There is no "best-index". This virtual table always does a linear +** scan of the binary VFS log file. +*/ +static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + + /* Records are always returned in ascending order of (name, path). + ** If this will satisfy the client, set the orderByConsumed flag so that + ** SQLite does not do an external sort. + */ + if( ( pIdxInfo->nOrderBy==1 + && pIdxInfo->aOrderBy[0].iColumn==0 + && pIdxInfo->aOrderBy[0].desc==0 + ) || + ( pIdxInfo->nOrderBy==2 + && pIdxInfo->aOrderBy[0].iColumn==0 + && pIdxInfo->aOrderBy[0].desc==0 + && pIdxInfo->aOrderBy[1].iColumn==1 + && pIdxInfo->aOrderBy[1].desc==0 + ) + ){ + pIdxInfo->orderByConsumed = 1; + } + + pIdxInfo->estimatedCost = 10.0; + return SQLITE_OK; +} + +/* +** Open a new statvfs cursor. +*/ +static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + StatTable *pTab = (StatTable *)pVTab; + StatCursor *pCsr; + int rc; + + pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor)); + if( pCsr==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pCsr, 0, sizeof(StatCursor)); + pCsr->base.pVtab = pVTab; + + rc = sqlite3_prepare_v2(pTab->db, + "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" + " UNION ALL " + "SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0" + " ORDER BY name", -1, + &pCsr->pStmt, 0 + ); + if( rc!=SQLITE_OK ){ + sqlite3_free(pCsr); + pCsr = 0; + } + } + + *ppCursor = (sqlite3_vtab_cursor *)pCsr; + return rc; +} + +static void statClearPage(StatPage *p){ + int i; + if( p->aCell ){ + for(i=0; inCell; i++){ + sqlite3_free(p->aCell[i].aOvfl); + } + sqlite3_free(p->aCell); + } + sqlite3PagerUnref(p->pPg); + sqlite3_free(p->zPath); + memset(p, 0, sizeof(StatPage)); +} + +static void statResetCsr(StatCursor *pCsr){ + int i; + sqlite3_reset(pCsr->pStmt); + for(i=0; iaPage); i++){ + statClearPage(&pCsr->aPage[i]); + } + pCsr->iPage = 0; + sqlite3_free(pCsr->zPath); + pCsr->zPath = 0; +} + +/* +** Close a statvfs cursor. +*/ +static int statClose(sqlite3_vtab_cursor *pCursor){ + StatCursor *pCsr = (StatCursor *)pCursor; + statResetCsr(pCsr); + sqlite3_finalize(pCsr->pStmt); + sqlite3_free(pCsr); + return SQLITE_OK; +} + +static void getLocalPayload( + int nUsable, /* Usable bytes per page */ + u8 flags, /* Page flags */ + int nTotal, /* Total record (payload) size */ + int *pnLocal /* OUT: Bytes stored locally */ +){ + int nLocal; + int nMinLocal; + int nMaxLocal; + + if( flags==0x0D ){ /* Table leaf node */ + nMinLocal = (nUsable - 12) * 32 / 255 - 23; + nMaxLocal = nUsable - 35; + }else{ /* Index interior and leaf nodes */ + nMinLocal = (nUsable - 12) * 32 / 255 - 23; + nMaxLocal = (nUsable - 12) * 64 / 255 - 23; + } + + nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4); + if( nLocal>nMaxLocal ) nLocal = nMinLocal; + *pnLocal = nLocal; +} + +static int statDecodePage(Btree *pBt, StatPage *p){ + int nUnused; + int iOff; + int nHdr; + int isLeaf; + int szPage; + + u8 *aData = sqlite3PagerGetData(p->pPg); + u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0]; + + p->flags = aHdr[0]; + p->nCell = get2byte(&aHdr[3]); + p->nMxPayload = 0; + + isLeaf = (p->flags==0x0A || p->flags==0x0D); + nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100; + + nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell; + nUnused += (int)aHdr[7]; + iOff = get2byte(&aHdr[1]); + while( iOff ){ + nUnused += get2byte(&aData[iOff+2]); + iOff = get2byte(&aData[iOff]); + } + p->nUnused = nUnused; + p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]); + szPage = sqlite3BtreeGetPageSize(pBt); + + if( p->nCell ){ + int i; /* Used to iterate through cells */ + int nUsable; /* Usable bytes per page */ + + sqlite3BtreeEnter(pBt); + nUsable = szPage - sqlite3BtreeGetReserveNoMutex(pBt); + sqlite3BtreeLeave(pBt); + p->aCell = sqlite3_malloc64((p->nCell+1) * sizeof(StatCell)); + if( p->aCell==0 ) return SQLITE_NOMEM; + memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell)); + + for(i=0; inCell; i++){ + StatCell *pCell = &p->aCell[i]; + + iOff = get2byte(&aData[nHdr+i*2]); + if( !isLeaf ){ + pCell->iChildPg = sqlite3Get4byte(&aData[iOff]); + iOff += 4; + } + if( p->flags==0x05 ){ + /* A table interior node. nPayload==0. */ + }else{ + u32 nPayload; /* Bytes of payload total (local+overflow) */ + int nLocal; /* Bytes of payload stored locally */ + iOff += getVarint32(&aData[iOff], nPayload); + if( p->flags==0x0D ){ + u64 dummy; + iOff += sqlite3GetVarint(&aData[iOff], &dummy); + } + if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload; + getLocalPayload(nUsable, p->flags, nPayload, &nLocal); + pCell->nLocal = nLocal; + assert( nLocal>=0 ); + assert( nPayload>=(u32)nLocal ); + assert( nLocal<=(nUsable-35) ); + if( nPayload>(u32)nLocal ){ + int j; + int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); + pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); + pCell->nOvfl = nOvfl; + pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); + if( pCell->aOvfl==0 ) return SQLITE_NOMEM; + pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]); + for(j=1; jaOvfl[j-1]; + DbPage *pPg = 0; + rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg); + if( rc!=SQLITE_OK ){ + assert( pPg==0 ); + return rc; + } + pCell->aOvfl[j] = sqlite3Get4byte(sqlite3PagerGetData(pPg)); + sqlite3PagerUnref(pPg); + } + } + } + } + } + + return SQLITE_OK; +} + +/* +** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on +** the current value of pCsr->iPageno. +*/ +static void statSizeAndOffset(StatCursor *pCsr){ + StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab; + Btree *pBt = pTab->db->aDb[0].pBt; + Pager *pPager = sqlite3BtreePager(pBt); + sqlite3_file *fd; + sqlite3_int64 x[2]; + + /* The default page size and offset */ + pCsr->szPage = sqlite3BtreeGetPageSize(pBt); + pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1); + + /* If connected to a ZIPVFS backend, override the page size and + ** offset with actual values obtained from ZIPVFS. + */ + fd = sqlite3PagerFile(pPager); + x[0] = pCsr->iPageno; + if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ + pCsr->iOffset = x[0]; + pCsr->szPage = (int)x[1]; + } +} + +/* +** Move a statvfs cursor to the next entry in the file. +*/ +static int statNext(sqlite3_vtab_cursor *pCursor){ + int rc; + int nPayload; + StatCursor *pCsr = (StatCursor *)pCursor; + StatTable *pTab = (StatTable *)pCursor->pVtab; + Btree *pBt = pTab->db->aDb[0].pBt; + Pager *pPager = sqlite3BtreePager(pBt); + + sqlite3_free(pCsr->zPath); + pCsr->zPath = 0; + +statNextRestart: + if( pCsr->aPage[0].pPg==0 ){ + rc = sqlite3_step(pCsr->pStmt); + if( rc==SQLITE_ROW ){ + int nPage; + u32 iRoot = (u32)sqlite3_column_int64(pCsr->pStmt, 1); + sqlite3PagerPagecount(pPager, &nPage); + if( nPage==0 ){ + pCsr->isEof = 1; + return sqlite3_reset(pCsr->pStmt); + } + rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg); + pCsr->aPage[0].iPgno = iRoot; + pCsr->aPage[0].iCell = 0; + pCsr->aPage[0].zPath = sqlite3_mprintf("/"); + pCsr->iPage = 0; + }else{ + pCsr->isEof = 1; + return sqlite3_reset(pCsr->pStmt); + } + }else{ + + /* Page p itself has already been visited. */ + StatPage *p = &pCsr->aPage[pCsr->iPage]; + + while( p->iCellnCell ){ + StatCell *pCell = &p->aCell[p->iCell]; + if( pCell->iOvflnOvfl ){ + int nUsable; + sqlite3BtreeEnter(pBt); + nUsable = sqlite3BtreeGetPageSize(pBt) - + sqlite3BtreeGetReserveNoMutex(pBt); + sqlite3BtreeLeave(pBt); + pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); + pCsr->iPageno = pCell->aOvfl[pCell->iOvfl]; + pCsr->zPagetype = "overflow"; + pCsr->nCell = 0; + pCsr->nMxPayload = 0; + pCsr->zPath = sqlite3_mprintf( + "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl + ); + if( pCell->iOvflnOvfl-1 ){ + pCsr->nUnused = 0; + pCsr->nPayload = nUsable - 4; + }else{ + pCsr->nPayload = pCell->nLastOvfl; + pCsr->nUnused = nUsable - 4 - pCsr->nPayload; + } + pCell->iOvfl++; + statSizeAndOffset(pCsr); + return SQLITE_OK; + } + if( p->iRightChildPg ) break; + p->iCell++; + } + + if( !p->iRightChildPg || p->iCell>p->nCell ){ + statClearPage(p); + if( pCsr->iPage==0 ) return statNext(pCursor); + pCsr->iPage--; + goto statNextRestart; /* Tail recursion */ + } + pCsr->iPage++; + assert( p==&pCsr->aPage[pCsr->iPage-1] ); + + if( p->iCell==p->nCell ){ + p[1].iPgno = p->iRightChildPg; + }else{ + p[1].iPgno = p->aCell[p->iCell].iChildPg; + } + rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg); + p[1].iCell = 0; + p[1].zPath = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); + p->iCell++; + } + + + /* Populate the StatCursor fields with the values to be returned + ** by the xColumn() and xRowid() methods. + */ + if( rc==SQLITE_OK ){ + int i; + StatPage *p = &pCsr->aPage[pCsr->iPage]; + pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); + pCsr->iPageno = p->iPgno; + + rc = statDecodePage(pBt, p); + if( rc==SQLITE_OK ){ + statSizeAndOffset(pCsr); + + switch( p->flags ){ + case 0x05: /* table internal */ + case 0x02: /* index internal */ + pCsr->zPagetype = "internal"; + break; + case 0x0D: /* table leaf */ + case 0x0A: /* index leaf */ + pCsr->zPagetype = "leaf"; + break; + default: + pCsr->zPagetype = "corrupted"; + break; + } + pCsr->nCell = p->nCell; + pCsr->nUnused = p->nUnused; + pCsr->nMxPayload = p->nMxPayload; + pCsr->zPath = sqlite3_mprintf("%s", p->zPath); + nPayload = 0; + for(i=0; inCell; i++){ + nPayload += p->aCell[i].nLocal; + } + pCsr->nPayload = nPayload; + } + } + + return rc; +} + +static int statEof(sqlite3_vtab_cursor *pCursor){ + StatCursor *pCsr = (StatCursor *)pCursor; + return pCsr->isEof; +} + +static int statFilter( + sqlite3_vtab_cursor *pCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + StatCursor *pCsr = (StatCursor *)pCursor; + + statResetCsr(pCsr); + return statNext(pCursor); +} + +static int statColumn( + sqlite3_vtab_cursor *pCursor, + sqlite3_context *ctx, + int i +){ + StatCursor *pCsr = (StatCursor *)pCursor; + switch( i ){ + case 0: /* name */ + sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_STATIC); + break; + case 1: /* path */ + sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); + break; + case 2: /* pageno */ + sqlite3_result_int64(ctx, pCsr->iPageno); + break; + case 3: /* pagetype */ + sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC); + break; + case 4: /* ncell */ + sqlite3_result_int(ctx, pCsr->nCell); + break; + case 5: /* payload */ + sqlite3_result_int(ctx, pCsr->nPayload); + break; + case 6: /* unused */ + sqlite3_result_int(ctx, pCsr->nUnused); + break; + case 7: /* mx_payload */ + sqlite3_result_int(ctx, pCsr->nMxPayload); + break; + case 8: /* pgoffset */ + sqlite3_result_int64(ctx, pCsr->iOffset); + break; + case 9: /* pgsize */ + sqlite3_result_int(ctx, pCsr->szPage); + break; + } + return SQLITE_OK; +} + +static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ + StatCursor *pCsr = (StatCursor *)pCursor; + *pRowid = pCsr->iPageno; + return SQLITE_OK; +} + +/* +** Invoke this routine to register the "dbstat" virtual table module +*/ +SQLITE_API int SQLITE_STDCALL sqlite3_dbstat_register(sqlite3 *db){ + static sqlite3_module dbstat_module = { + 0, /* iVersion */ + statConnect, /* xCreate */ + statConnect, /* xConnect */ + statBestIndex, /* xBestIndex */ + statDisconnect, /* xDisconnect */ + statDisconnect, /* xDestroy */ + statOpen, /* xOpen - open a cursor */ + statClose, /* xClose - close a cursor */ + statFilter, /* xFilter - configure scan constraints */ + statNext, /* xNext - advance a cursor */ + statEof, /* xEof - check for end of scan */ + statColumn, /* xColumn - read data */ + statRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + }; + return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); +} +#endif /* SQLITE_ENABLE_DBSTAT_VTAB */ + +/************** End of dbstat.c **********************************************/ diff --git a/TMessagesProj/jni/sqlite/sqlite3.h b/TMessagesProj/jni/sqlite/sqlite3.h index 07406477d..edb9e9c4b 100644 --- a/TMessagesProj/jni/sqlite/sqlite3.h +++ b/TMessagesProj/jni/sqlite/sqlite3.h @@ -43,16 +43,20 @@ extern "C" { /* -** Add the ability to override 'extern' +** Provide the ability to override linkage features of the interface. */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif - #ifndef SQLITE_API # define SQLITE_API #endif - +#ifndef SQLITE_CDECL +# define SQLITE_CDECL +#endif +#ifndef SQLITE_STDCALL +# define SQLITE_STDCALL +#endif /* ** These no-op macros are used in front of interfaces to mark those @@ -107,9 +111,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.8.8.1" -#define SQLITE_VERSION_NUMBER 3008008 -#define SQLITE_SOURCE_ID "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55" +#define SQLITE_VERSION "3.8.10" +#define SQLITE_VERSION_NUMBER 3008010 +#define SQLITE_SOURCE_ID "2015-05-07 11:53:08 cf975957b9ae671f34bb65f049acf351e650d437" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -142,9 +146,9 @@ extern "C" { ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; -SQLITE_API const char *sqlite3_libversion(void); -SQLITE_API const char *sqlite3_sourceid(void); -SQLITE_API int sqlite3_libversion_number(void); +SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void); +SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void); +SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics @@ -169,8 +173,8 @@ SQLITE_API int sqlite3_libversion_number(void); ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_API int sqlite3_compileoption_used(const char *zOptName); -SQLITE_API const char *sqlite3_compileoption_get(int N); +SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N); #endif /* @@ -209,7 +213,7 @@ SQLITE_API const char *sqlite3_compileoption_get(int N); ** ** See the [threading mode] documentation for additional information. */ -SQLITE_API int sqlite3_threadsafe(void); +SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle @@ -266,6 +270,7 @@ typedef sqlite_uint64 sqlite3_uint64; /* ** CAPI3REF: Closing A Database Connection +** DESTRUCTOR: sqlite3 ** ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors ** for the [sqlite3] object. @@ -305,8 +310,8 @@ typedef sqlite_uint64 sqlite3_uint64; ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ -SQLITE_API int sqlite3_close(sqlite3*); -SQLITE_API int sqlite3_close_v2(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*); /* ** The type for a callback function. @@ -317,6 +322,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); /* ** CAPI3REF: One-Step Query Execution Interface +** METHOD: sqlite3 ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], @@ -376,7 +382,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. ** */ -SQLITE_API int sqlite3_exec( +SQLITE_API int SQLITE_STDCALL sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ @@ -756,14 +762,16 @@ struct sqlite3_io_methods { ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] ** interface. ** +**
    +**
  • [[SQLITE_FCNTL_LOCKSTATE]] ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This ** opcode causes the xFileControl method to write the current state of ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) ** into an integer that the pArg argument points to. This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -**
      +** is used during testing and is only available when the SQLITE_TEST +** compile-time option is used. +** **
    • [[SQLITE_FCNTL_SIZE_HINT]] ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS ** layer a hint of how large the database file will grow to be during the @@ -888,7 +896,9 @@ struct sqlite3_io_methods { ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] ** file control returns [SQLITE_OK], then the parser assumes that the ** VFS has handled the PRAGMA itself and the parser generates a no-op -** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** prepared statement if result string is NULL, or that returns a copy +** of the result string if the string is non-NULL. +** ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] @@ -946,12 +956,19 @@ struct sqlite3_io_methods { ** pointed to by the pArg argument. This capability is used during testing ** and only needs to be supported when SQLITE_TEST is defined. ** +**
    • [[SQLITE_FCNTL_WAL_BLOCK]] +** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might +** be advantageous to block on the next WAL lock if the lock is not immediately +** available. The WAL subsystem issues this signal during rare +** circumstances in order to fix a problem with priority inversion. +** Applications should not use this file-control. +** **
    */ #define SQLITE_FCNTL_LOCKSTATE 1 -#define SQLITE_GET_LOCKPROXYFILE 2 -#define SQLITE_SET_LOCKPROXYFILE 3 -#define SQLITE_LAST_ERRNO 4 +#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 +#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 +#define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 @@ -970,6 +987,13 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 +#define SQLITE_FCNTL_WAL_BLOCK 24 + +/* deprecated names */ +#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE +#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO + /* ** CAPI3REF: Mutex Handle @@ -1318,10 +1342,10 @@ struct sqlite3_vfs { ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ -SQLITE_API int sqlite3_initialize(void); -SQLITE_API int sqlite3_shutdown(void); -SQLITE_API int sqlite3_os_init(void); -SQLITE_API int sqlite3_os_end(void); +SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void); +SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void); +SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void); +SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library @@ -1352,10 +1376,11 @@ SQLITE_API int sqlite3_os_end(void); ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ -SQLITE_API int sqlite3_config(int, ...); +SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections +** METHOD: sqlite3 ** ** The sqlite3_db_config() interface is used to make configuration ** changes to a [database connection]. The interface is similar to @@ -1370,7 +1395,7 @@ SQLITE_API int sqlite3_config(int, ...); ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. */ -SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); +SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines @@ -1530,7 +1555,7 @@ struct sqlite3_mem_methods { **
  • [sqlite3_memory_used()] **
  • [sqlite3_memory_highwater()] **
  • [sqlite3_soft_heap_limit64()] -**
  • [sqlite3_status()] +**
  • [sqlite3_status64()] **
)^ ** ^Memory allocation statistics are enabled by default unless SQLite is ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory @@ -1741,7 +1766,6 @@ struct sqlite3_mem_methods { ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value ** that specifies the maximum size of the created heap. -** ** ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] **
SQLITE_CONFIG_PCACHE_HDRSZ @@ -1854,15 +1878,17 @@ struct sqlite3_mem_methods { /* ** CAPI3REF: Enable Or Disable Extended Result Codes +** METHOD: sqlite3 ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ -SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); +SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid +** METHOD: sqlite3 ** ** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables) ** has a unique 64-bit signed @@ -1910,10 +1936,11 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ -SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified +** METHOD: sqlite3 ** ** ^This function returns the number of rows modified, inserted or ** deleted by the most recently completed INSERT, UPDATE or DELETE @@ -1962,10 +1989,11 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ -SQLITE_API int sqlite3_changes(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified +** METHOD: sqlite3 ** ** ^This function returns the total number of rows inserted, modified or ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed @@ -1985,10 +2013,11 @@ SQLITE_API int sqlite3_changes(sqlite3*); ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ -SQLITE_API int sqlite3_total_changes(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query +** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically @@ -2024,7 +2053,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*); ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ -SQLITE_API void sqlite3_interrupt(sqlite3*); +SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete @@ -2059,12 +2088,13 @@ SQLITE_API void sqlite3_interrupt(sqlite3*); ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ -SQLITE_API int sqlite3_complete(const char *sql); -SQLITE_API int sqlite3_complete16(const void *sql); +SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql); +SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors ** KEYWORDS: {busy-handler callback} {busy handler} +** METHOD: sqlite3 ** ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X ** that might be invoked with argument P whenever @@ -2120,10 +2150,11 @@ SQLITE_API int sqlite3_complete16(const void *sql); ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ -SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); +SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); /* ** CAPI3REF: Set A Busy Timeout +** METHOD: sqlite3 ** ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps ** for a specified amount of time when a table is locked. ^The handler @@ -2142,10 +2173,11 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); ** ** See also: [PRAGMA busy_timeout] */ -SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); +SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries +** METHOD: sqlite3 ** ** This is a legacy interface that is preserved for backwards compatibility. ** Use of this interface is not recommended. @@ -2216,7 +2248,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ -SQLITE_API int sqlite3_get_table( +SQLITE_API int SQLITE_STDCALL sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ @@ -2224,13 +2256,17 @@ SQLITE_API int sqlite3_get_table( int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); -SQLITE_API void sqlite3_free_table(char **result); +SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. +** These routines understand most of the common K&R formatting options, +** plus some additional non-standard formats, detailed below. +** Note that some of the more obscure formatting options from recent +** C-library standards are omitted from this implementation. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their ** results into memory obtained from [sqlite3_malloc()]. @@ -2263,7 +2299,7 @@ SQLITE_API void sqlite3_free_table(char **result); ** These routines all implement some additional formatting ** options that are useful for constructing SQL statements. ** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. +** is are "%q", "%Q", "%w" and "%z" options. ** ** ^(The %q option works like %s in that it substitutes a nul-terminated ** string from the argument list. But %q also doubles every '\'' character. @@ -2316,14 +2352,20 @@ SQLITE_API void sqlite3_free_table(char **result); ** The code above will render a correct SQL statement in the zSQL ** variable even if the zText variable is a NULL pointer. ** +** ^(The "%w" formatting option is like "%q" except that it expects to +** be contained within double-quotes instead of single quotes, and it +** escapes the double-quote character instead of the single-quote +** character.)^ The "%w" formatting option is intended for safely inserting +** table and column names into a constructed SQL statement. +** ** ^(The "%z" formatting option works like "%s" but with the ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ -SQLITE_API char *sqlite3_mprintf(const char*,...); -SQLITE_API char *sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); +SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); +SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem @@ -2413,12 +2455,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ -SQLITE_API void *sqlite3_malloc(int); -SQLITE_API void *sqlite3_malloc64(sqlite3_uint64); -SQLITE_API void *sqlite3_realloc(void*, int); -SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64); -SQLITE_API void sqlite3_free(void*); -SQLITE_API sqlite3_uint64 sqlite3_msize(void*); +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int); +SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64); +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int); +SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64); +SQLITE_API void SQLITE_STDCALL sqlite3_free(void*); +SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); /* ** CAPI3REF: Memory Allocator Statistics @@ -2443,8 +2485,8 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void*); ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ -SQLITE_API sqlite3_int64 sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator @@ -2467,10 +2509,11 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ -SQLITE_API void sqlite3_randomness(int N, void *P); +SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks +** METHOD: sqlite3 ** ** ^This routine registers an authorizer callback with a particular ** [database connection], supplied in the first argument. @@ -2549,7 +2592,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P); ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ -SQLITE_API int sqlite3_set_authorizer( +SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData @@ -2627,6 +2670,7 @@ SQLITE_API int sqlite3_set_authorizer( /* ** CAPI3REF: Tracing And Profiling Functions +** METHOD: sqlite3 ** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. @@ -2653,12 +2697,13 @@ SQLITE_API int sqlite3_set_authorizer( ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ -SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, +SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); /* ** CAPI3REF: Query Progress Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to @@ -2688,10 +2733,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, ** database connections for the meaning of "modify" in this paragraph. ** */ -SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection +** CONSTRUCTOR: sqlite3 ** ** ^These routines open an SQLite database file as specified by the ** filename argument. ^The filename argument is interpreted as UTF-8 for @@ -2916,15 +2962,15 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** ** See also: [sqlite3_temp_directory] */ -SQLITE_API int sqlite3_open( +SQLITE_API int SQLITE_STDCALL sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int sqlite3_open16( +SQLITE_API int SQLITE_STDCALL sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int sqlite3_open_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -2970,19 +3016,22 @@ SQLITE_API int sqlite3_open_v2( ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ -SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); -SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); +SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* ** CAPI3REF: Error Codes And Messages +** METHOD: sqlite3 ** -** ^The sqlite3_errcode() interface returns the numeric [result code] or -** [extended result code] for the most recent failed sqlite3_* API call -** associated with a [database connection]. If a prior API call failed -** but the most recent API call succeeded, the return value from -** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() +** ^If the most recent sqlite3_* API call associated with +** [database connection] D failed, then the sqlite3_errcode(D) interface +** returns the numeric [result code] or [extended result code] for that +** API call. +** If the most recent API call was successful, +** then the return value from sqlite3_errcode() is undefined. +** ^The sqlite3_extended_errcode() ** interface is the same except that it always returns the ** [extended result code] even when extended result codes are ** disabled. @@ -3013,40 +3062,41 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ -SQLITE_API int sqlite3_errcode(sqlite3 *db); -SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *sqlite3_errmsg(sqlite3*); -SQLITE_API const void *sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *sqlite3_errstr(int); +SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db); +SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int); /* -** CAPI3REF: SQL Statement Object +** CAPI3REF: Prepared Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** -** An instance of this object represents a single SQL statement. -** This object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". +** An instance of this object represents a single SQL statement that +** has been compiled into binary form and is ready to be evaluated. ** -** The life of a statement object goes something like this: +** Think of each SQL statement as a separate computer program. The +** original SQL text is source code. A prepared statement object +** is the compiled object code. All SQL must be converted into a +** prepared statement before it can be run. +** +** The life-cycle of a prepared statement object usually goes like this: ** **
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to [host parameters] using the sqlite3_bind_*() +**
  3. Create the prepared statement object using [sqlite3_prepare_v2()]. +**
  4. Bind values to [parameters] using the sqlite3_bind_*() ** interfaces. **
  5. Run the SQL by calling [sqlite3_step()] one or more times. -**
  6. Reset the statement using [sqlite3_reset()] then go back +**
  7. Reset the prepared statement using [sqlite3_reset()] then go back ** to step 2. Do this zero or more times. **
  8. Destroy the object using [sqlite3_finalize()]. **
-** -** Refer to documentation on individual methods above for additional -** information. */ typedef struct sqlite3_stmt sqlite3_stmt; /* ** CAPI3REF: Run-time Limits +** METHOD: sqlite3 ** ** ^(This interface allows the size of various constructs to be limited ** on a connection by connection basis. The first parameter is the @@ -3084,7 +3134,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** ** New run-time limit categories may be added in future releases. */ -SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); +SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories @@ -3158,6 +3208,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_stmt ** ** To execute an SQL query, it must first be compiled into a byte-code ** program using one of these routines. @@ -3171,16 +3223,14 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() ** use UTF-16. ** -** ^If the nByte argument is less than zero, then zSql is read up to the -** first zero terminator. ^If nByte is non-negative, then it is the maximum -** number of bytes read from zSql. ^When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** the nByte-th byte, whichever comes first. If the caller knows -** that the supplied string is nul-terminated, then there is a small -** performance advantage to be gained by passing an nByte parameter that -** is equal to the number of bytes in the input string including -** the nul-terminator bytes as this saves SQLite from having to -** make a copy of the input string. +** ^If the nByte argument is negative, then zSql is read up to the +** first zero terminator. ^If nByte is positive, then it is the +** number of bytes read from zSql. ^If nByte is zero, then no prepared +** statement is generated. +** If the caller knows that the supplied string is nul-terminated, then +** there is a small performance advantage to passing an nByte parameter that +** is the number of bytes in the input string including +** the nul-terminator. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte ** past the end of the first SQL statement in zSql. These routines only @@ -3236,28 +3286,28 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ** */ -SQLITE_API int sqlite3_prepare( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int sqlite3_prepare_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int sqlite3_prepare16( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int sqlite3_prepare16_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -3267,15 +3317,17 @@ SQLITE_API int sqlite3_prepare16_v2( /* ** CAPI3REF: Retrieving Statement SQL +** METHOD: sqlite3_stmt ** ** ^This interface can be used to retrieve a saved copy of the original ** SQL text used to create a [prepared statement] if that statement was ** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. */ -SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database +** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to @@ -3303,10 +3355,11 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. */ -SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset +** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the ** [prepared statement] S has been stepped at least once using @@ -3322,7 +3375,7 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ -SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); /* ** CAPI3REF: Dynamically Typed Value Object @@ -3381,6 +3434,7 @@ typedef struct sqlite3_context sqlite3_context; ** CAPI3REF: Binding Values To Prepared Statements ** KEYWORDS: {host parameter} {host parameters} {host parameter name} ** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** METHOD: sqlite3_stmt ** ** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, ** literals may be replaced by a [parameter] that matches one of following @@ -3483,22 +3537,23 @@ typedef struct sqlite3_context sqlite3_context; ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ -SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, void(*)(void*)); -SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, +SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); /* ** CAPI3REF: Number Of SQL Parameters +** METHOD: sqlite3_stmt ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the @@ -3515,10 +3570,11 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); ** [sqlite3_bind_parameter_name()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter +** METHOD: sqlite3_stmt ** ** ^The sqlite3_bind_parameter_name(P,N) interface returns ** the name of the N-th [SQL parameter] in the [prepared statement] P. @@ -3542,10 +3598,11 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name +** METHOD: sqlite3_stmt ** ** ^Return the index of an SQL parameter given its name. ^The ** index value returned is suitable for use as the second @@ -3558,19 +3615,21 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement +** METHOD: sqlite3_stmt ** ** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ -SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); +SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set +** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL @@ -3578,10 +3637,11 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); ** ** See also: [sqlite3_data_count()] */ -SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set +** METHOD: sqlite3_stmt ** ** ^These routines return the name assigned to a particular column ** in the result set of a [SELECT] statement. ^The sqlite3_column_name() @@ -3606,11 +3666,12 @@ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ -SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result +** METHOD: sqlite3_stmt ** ** ^These routines provide a means to determine the database, table, and ** table column that is the origin of a particular result column in @@ -3654,15 +3715,16 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ -SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result +** METHOD: sqlite3_stmt ** ** ^(The first parameter is a [prepared statement]. ** If this statement is a [SELECT] statement and the Nth column of the @@ -3690,11 +3752,12 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); ** is associated with individual values, not with the containers ** used to hold those values. */ -SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); +SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement +** METHOD: sqlite3_stmt ** ** After a [prepared statement] has been prepared using either ** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy @@ -3770,10 +3833,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ -SQLITE_API int sqlite3_step(sqlite3_stmt*); +SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set +** METHOD: sqlite3_stmt ** ** ^The sqlite3_data_count(P) interface returns the number of columns in the ** current row of the result set of [prepared statement] P. @@ -3790,7 +3854,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt*); ** ** See also: [sqlite3_column_count()] */ -SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes @@ -3827,6 +3891,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Result Values From A Query ** KEYWORDS: {column access functions} +** METHOD: sqlite3_stmt ** ** These routines form the "result set" interface. ** @@ -3986,19 +4051,20 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ -SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object +** DESTRUCTOR: sqlite3_stmt ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors @@ -4022,10 +4088,11 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ -SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object +** METHOD: sqlite3_stmt ** ** The sqlite3_reset() function is called to reset a [prepared statement] ** object back to its initial state, ready to be re-executed. @@ -4048,13 +4115,14 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ -SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); +SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} ** KEYWORDS: {application-defined SQL functions} +** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior @@ -4147,7 +4215,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ -SQLITE_API int sqlite3_create_function( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4157,7 +4225,7 @@ SQLITE_API int sqlite3_create_function( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int sqlite3_create_function16( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -4167,7 +4235,7 @@ SQLITE_API int sqlite3_create_function16( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int sqlite3_create_function_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4209,21 +4277,22 @@ SQLITE_API int sqlite3_create_function_v2( ** These functions are [deprecated]. In order to maintain ** backwards compatibility with older code, these functions continue ** to be supported. However, new applications should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you what they do. +** the use of these functions. To encourage programmers to avoid +** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif /* ** CAPI3REF: Obtaining SQL Function Parameter Values +** METHOD: sqlite3_value ** ** The C-language implementation of SQL functions and aggregates uses ** this set of interface routines to access the parameter values on @@ -4267,21 +4336,22 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ -SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API double sqlite3_value_double(sqlite3_value*); -SQLITE_API int sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int sqlite3_value_type(sqlite3_value*); -SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*); +SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context +** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. @@ -4322,10 +4392,11 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ -SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); +SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions +** METHOD: sqlite3_context ** ** ^The sqlite3_user_data() interface returns a copy of ** the pointer that was the pUserData parameter (the 5th parameter) @@ -4336,10 +4407,11 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); ** This routine must be called from the same thread in which ** the application-defined function is running. */ -SQLITE_API void *sqlite3_user_data(sqlite3_context*); +SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions +** METHOD: sqlite3_context ** ** ^The sqlite3_context_db_handle() interface returns a copy of ** the pointer to the [database connection] (the 1st parameter) @@ -4347,10 +4419,11 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context*); ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ -SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data +** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to ** associate metadata with argument values. If the same value is passed to @@ -4399,8 +4472,8 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** These routines must be called from the same thread in which ** the SQL function is running. */ -SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* @@ -4423,6 +4496,7 @@ typedef void (*sqlite3_destructor_type)(void*); /* ** CAPI3REF: Setting The Result Of An SQL Function +** METHOD: sqlite3_context ** ** These routines are used by the xFunc or xFinal callbacks that ** implement SQL functions and aggregates. See @@ -4535,29 +4609,30 @@ typedef void (*sqlite3_destructor_type)(void*); ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ -SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*, sqlite3_uint64,void(*)(void*)); -SQLITE_API void sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void sqlite3_result_null(sqlite3_context*); -SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, +SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); -SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); /* ** CAPI3REF: Define New Collating Sequences +** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. @@ -4635,14 +4710,14 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ -SQLITE_API int sqlite3_create_collation( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); -SQLITE_API int sqlite3_create_collation_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, @@ -4650,7 +4725,7 @@ SQLITE_API int sqlite3_create_collation_v2( int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); -SQLITE_API int sqlite3_create_collation16( +SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, @@ -4660,6 +4735,7 @@ SQLITE_API int sqlite3_create_collation16( /* ** CAPI3REF: Collation Needed Callbacks +** METHOD: sqlite3 ** ** ^To avoid having to register all collation sequences before a database ** can be used, a single callback function may be registered with the @@ -4684,12 +4760,12 @@ SQLITE_API int sqlite3_create_collation16( ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ -SQLITE_API int sqlite3_collation_needed( +SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); -SQLITE_API int sqlite3_collation_needed16( +SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) @@ -4703,11 +4779,11 @@ SQLITE_API int sqlite3_collation_needed16( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int sqlite3_key( +SQLITE_API int SQLITE_STDCALL sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); -SQLITE_API int sqlite3_key_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The key */ @@ -4721,11 +4797,11 @@ SQLITE_API int sqlite3_key_v2( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int sqlite3_rekey( +SQLITE_API int SQLITE_STDCALL sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); -SQLITE_API int sqlite3_rekey_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The new key */ @@ -4735,7 +4811,7 @@ SQLITE_API int sqlite3_rekey_v2( ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ -SQLITE_API void sqlite3_activate_see( +SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -4745,7 +4821,7 @@ SQLITE_API void sqlite3_activate_see( ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ -SQLITE_API void sqlite3_activate_cerod( +SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -4767,7 +4843,7 @@ SQLITE_API void sqlite3_activate_cerod( ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ -SQLITE_API int sqlite3_sleep(int); +SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -4867,6 +4943,7 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} +** METHOD: sqlite3 ** ** ^The sqlite3_get_autocommit() interface returns non-zero or ** zero if the given database connection is or is not in autocommit mode, @@ -4885,10 +4962,11 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; ** connection while this routine is running, then the return value ** is undefined. */ -SQLITE_API int sqlite3_get_autocommit(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement +** METHOD: sqlite3_stmt ** ** ^The sqlite3_db_handle interface returns the [database connection] handle ** to which a [prepared statement] belongs. ^The [database connection] @@ -4897,10 +4975,11 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*); ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ -SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); +SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection +** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename ** associated with database N of connection D. ^The main database file @@ -4913,19 +4992,21 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ -SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only +** METHOD: sqlite3 ** ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ -SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); +SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement +** METHOD: sqlite3 ** ** ^This interface returns a pointer to the next [prepared statement] after ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL @@ -4937,10 +5018,11 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ -SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); +SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_commit_hook() interface registers a callback ** function to be invoked whenever a transaction is [COMMIT | committed]. @@ -4985,11 +5067,12 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); ** ** See also the [sqlite3_update_hook()] interface. */ -SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument @@ -5036,7 +5119,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] ** interfaces. */ -SQLITE_API void *sqlite3_update_hook( +SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* @@ -5066,12 +5149,17 @@ SQLITE_API void *sqlite3_update_hook( ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. ** +** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 +** and will always return SQLITE_MISUSE. On those systems, +** shared cache mode should be enabled per-database connection via +** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. +** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** ** See Also: [SQLite Shared-Cache Mode] */ -SQLITE_API int sqlite3_enable_shared_cache(int); +SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory @@ -5087,10 +5175,11 @@ SQLITE_API int sqlite3_enable_shared_cache(int); ** ** See also: [sqlite3_db_release_memory()] */ -SQLITE_API int sqlite3_release_memory(int); +SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection +** METHOD: sqlite3 ** ** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap ** memory as possible from database connection D. Unlike the @@ -5100,7 +5189,7 @@ SQLITE_API int sqlite3_release_memory(int); ** ** See also: [sqlite3_release_memory()] */ -SQLITE_API int sqlite3_db_release_memory(sqlite3*); +SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size @@ -5152,7 +5241,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*); ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ -SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); +SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface @@ -5163,11 +5252,12 @@ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ -SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); +SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); /* ** CAPI3REF: Extract Metadata About A Column Of A Table +** METHOD: sqlite3 ** ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns ** information about column C of table T in database D @@ -5232,7 +5322,7 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ -SQLITE_API int sqlite3_table_column_metadata( +SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -5246,6 +5336,7 @@ SQLITE_API int sqlite3_table_column_metadata( /* ** CAPI3REF: Load An Extension +** METHOD: sqlite3 ** ** ^This interface loads an SQLite extension library from the named file. ** @@ -5278,7 +5369,7 @@ SQLITE_API int sqlite3_table_column_metadata( ** ** See also the [load_extension() SQL function]. */ -SQLITE_API int sqlite3_load_extension( +SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ @@ -5287,6 +5378,7 @@ SQLITE_API int sqlite3_load_extension( /* ** CAPI3REF: Enable Or Disable Extension Loading +** METHOD: sqlite3 ** ** ^So as not to open security holes in older applications that are ** unprepared to deal with [extension loading], and as a means of disabling @@ -5298,7 +5390,7 @@ SQLITE_API int sqlite3_load_extension( ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. */ -SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); +SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions @@ -5336,7 +5428,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ -SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); +SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Cancel Automatic Extension Loading @@ -5348,7 +5440,7 @@ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ -SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); +SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading @@ -5356,7 +5448,7 @@ SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ -SQLITE_API void sqlite3_reset_auto_extension(void); +SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void); /* ** The interface to the virtual-table mechanism is currently considered @@ -5536,6 +5628,7 @@ struct sqlite3_index_info { /* ** CAPI3REF: Register A Virtual Table Implementation +** METHOD: sqlite3 ** ** ^These routines are used to register a new [virtual table module] name. ** ^Module names must be registered before @@ -5559,13 +5652,13 @@ struct sqlite3_index_info { ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. */ -SQLITE_API int sqlite3_create_module( +SQLITE_API int SQLITE_STDCALL sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData /* Client data for xCreate/xConnect */ ); -SQLITE_API int sqlite3_create_module_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ @@ -5593,7 +5686,7 @@ SQLITE_API int sqlite3_create_module_v2( */ struct sqlite3_vtab { const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* NO LONGER USED */ + int nRef; /* Number of open cursors */ char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; @@ -5628,10 +5721,11 @@ struct sqlite3_vtab_cursor { ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. */ -SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); +SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table +** METHOD: sqlite3 ** ** ^(Virtual tables can provide alternative implementations of functions ** using the [xFindFunction] method of the [virtual table module]. @@ -5646,7 +5740,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ -SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); +SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up @@ -5674,6 +5768,8 @@ typedef struct sqlite3_blob sqlite3_blob; /* ** CAPI3REF: Open A BLOB For Incremental I/O +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_blob ** ** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located ** in row iRow, column zColumn, table zTable in database zDb; @@ -5743,7 +5839,7 @@ typedef struct sqlite3_blob sqlite3_blob; ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ -SQLITE_API int sqlite3_blob_open( +SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, @@ -5755,6 +5851,7 @@ SQLITE_API int sqlite3_blob_open( /* ** CAPI3REF: Move a BLOB Handle to a New Row +** METHOD: sqlite3_blob ** ** ^This function is used to move an existing blob handle so that it points ** to a different row of the same database table. ^The new row is identified @@ -5775,10 +5872,11 @@ SQLITE_API int sqlite3_blob_open( ** ** ^This function sets the database handle error code and message. */ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); +SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle +** DESTRUCTOR: sqlite3_blob ** ** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed ** unconditionally. Even if this routine returns an error code, the @@ -5797,10 +5895,11 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_i ** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ -SQLITE_API int sqlite3_blob_close(sqlite3_blob *); +SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB +** METHOD: sqlite3_blob ** ** ^Returns the size in bytes of the BLOB accessible via the ** successfully opened [BLOB handle] in its only argument. ^The @@ -5812,10 +5911,11 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *); ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. */ -SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); +SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally +** METHOD: sqlite3_blob ** ** ^(This function is used to read data from an open [BLOB handle] into a ** caller-supplied buffer. N bytes of data are copied into buffer Z @@ -5840,10 +5940,11 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); ** ** See also: [sqlite3_blob_write()]. */ -SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); +SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally +** METHOD: sqlite3_blob ** ** ^(This function is used to write data into an open [BLOB handle] from a ** caller-supplied buffer. N bytes of data are copied from the buffer Z @@ -5881,7 +5982,7 @@ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); ** ** See also: [sqlite3_blob_read()]. */ -SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); +SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); /* ** CAPI3REF: Virtual File System Objects @@ -5912,9 +6013,9 @@ SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOff ** ^(If the default VFS is unregistered, another VFS is chosen as ** the default. The choice for the new VFS is arbitrary.)^ */ -SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); +SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); /* ** CAPI3REF: Mutexes @@ -6027,11 +6128,11 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ -SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); -SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); -SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); -SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); -SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*); /* ** CAPI3REF: Mutex Methods Object @@ -6141,8 +6242,8 @@ struct sqlite3_mutex_methods { ** interface should also return 1 when given a NULL pointer. */ #ifndef NDEBUG -SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); -SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); #endif /* @@ -6171,6 +6272,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); /* ** CAPI3REF: Retrieve the mutex for a database connection +** METHOD: sqlite3 ** ** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument @@ -6178,10 +6280,11 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ -SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); +SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files +** METHOD: sqlite3 ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated @@ -6212,7 +6315,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ -SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); +SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface @@ -6231,7 +6334,7 @@ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void* ** Unlike most of the SQLite API, this function is not guaranteed to ** operate consistently from one release to the next. */ -SQLITE_API int sqlite3_test_control(int op, ...); +SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); /* ** CAPI3REF: Testing Interface Operation Codes @@ -6265,12 +6368,13 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 -#define SQLITE_TESTCTRL_LAST 24 +#define SQLITE_TESTCTRL_IMPOSTER 25 +#define SQLITE_TESTCTRL_LAST 25 /* ** CAPI3REF: SQLite Runtime Status ** -** ^This interface is used to retrieve runtime status information +** ^These interfaces are used to retrieve runtime status information ** about the performance of SQLite, and optionally to reset various ** highwater marks. ^The first argument is an integer code for ** the specific parameter to measure. ^(Recognized integer codes @@ -6284,19 +6388,22 @@ SQLITE_API int sqlite3_test_control(int op, ...); ** ^(Other parameters record only the highwater mark and not the current ** value. For these latter parameters nothing is written into *pCurrent.)^ ** -** ^The sqlite3_status() routine returns SQLITE_OK on success and a -** non-zero [error code] on failure. +** ^The sqlite3_status() and sqlite3_status64() routines return +** SQLITE_OK on success and a non-zero [error code] on failure. ** -** This routine is threadsafe but is not atomic. This routine can be -** called while other threads are running the same or different SQLite -** interfaces. However the values returned in *pCurrent and -** *pHighwater reflect the status of SQLite at different points in time -** and it is possible that another thread might change the parameter -** in between the times when *pCurrent and *pHighwater are written. +** If either the current value or the highwater mark is too large to +** be represented by a 32-bit integer, then the values returned by +** sqlite3_status() are undefined. ** ** See also: [sqlite3_db_status()] */ -SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API int SQLITE_STDCALL sqlite3_status64( + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag +); /* @@ -6394,6 +6501,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF /* ** CAPI3REF: Database Connection Status +** METHOD: sqlite3 ** ** ^This interface is used to retrieve runtime status information ** about a single [database connection]. ^The first argument is the @@ -6414,7 +6522,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF ** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ -SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); +SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Status Parameters for database connections @@ -6522,6 +6630,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r /* ** CAPI3REF: Prepared Statement Status +** METHOD: sqlite3_stmt ** ** ^(Each prepared statement maintains various ** [SQLITE_STMTSTATUS counters] that measure the number @@ -6543,7 +6652,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ -SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); +SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements @@ -6966,20 +7075,20 @@ typedef struct sqlite3_backup sqlite3_backup; ** is not a permanent error and does not affect the return value of ** sqlite3_backup_finish(). ** -** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] +** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]] ** sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** -** ^Each call to sqlite3_backup_step() sets two values inside -** the [sqlite3_backup] object: the number of pages still to be backed -** up and the total number of pages in the source database file. -** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces -** retrieve these two values, respectively. -** -** ^The values returned by these functions are only updated by -** sqlite3_backup_step(). ^If the source database is modified during a backup -** operation, then the values are not updated to account for any extra -** pages that need to be updated or the size of the source database file -** changing. +** ^The sqlite3_backup_remaining() routine returns the number of pages still +** to be backed up at the conclusion of the most recent sqlite3_backup_step(). +** ^The sqlite3_backup_pagecount() routine returns the total number of pages +** in the source database at the conclusion of the most recent +** sqlite3_backup_step(). +** ^(The values returned by these functions are only updated by +** sqlite3_backup_step(). If the source database is modified in a way that +** changes the size of the source database or the number of pages remaining, +** those changes are not reflected in the output of sqlite3_backup_pagecount() +** and sqlite3_backup_remaining() until after the next +** sqlite3_backup_step().)^ ** ** Concurrent Usage of Database Handles ** @@ -7012,19 +7121,20 @@ typedef struct sqlite3_backup sqlite3_backup; ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ -SQLITE_API sqlite3_backup *sqlite3_backup_init( +SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); -SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification +** METHOD: sqlite3 ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or @@ -7137,7 +7247,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ -SQLITE_API int sqlite3_unlock_notify( +SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ @@ -7152,8 +7262,8 @@ SQLITE_API int sqlite3_unlock_notify( ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int sqlite3_stricmp(const char *, const char *); -SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); +SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *); +SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: String Globbing @@ -7168,7 +7278,7 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); ** Note that this routine returns zero on a match and non-zero if the strings ** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. */ -SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); +SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr); /* ** CAPI3REF: Error Logging Interface @@ -7191,10 +7301,11 @@ SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); ** a few hundred characters, it will be truncated to the length of the ** buffer. */ -SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); +SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook +** METHOD: sqlite3 ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that ** is invoked each time data is committed to a database in wal mode. @@ -7226,7 +7337,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** those overwrite any prior [sqlite3_wal_hook()] settings. */ -SQLITE_API void *sqlite3_wal_hook( +SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* @@ -7234,6 +7345,7 @@ SQLITE_API void *sqlite3_wal_hook( /* ** CAPI3REF: Configure an auto-checkpoint +** METHOD: sqlite3 ** ** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around ** [sqlite3_wal_hook()] that causes any database on [database connection] D @@ -7260,10 +7372,11 @@ SQLITE_API void *sqlite3_wal_hook( ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ -SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); +SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to ** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ @@ -7281,10 +7394,11 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); ** start a callback but which do not need the full power (and corresponding ** complication) of [sqlite3_wal_checkpoint_v2()]. */ -SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); +SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint ** operation on database X of [database connection] D in mode M. Status @@ -7374,7 +7488,7 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ -SQLITE_API int sqlite3_wal_checkpoint_v2( +SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -7410,7 +7524,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ -SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); +SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options @@ -7463,7 +7577,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ -SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); +SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Conflict resolution modes @@ -7539,6 +7653,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Prepared Statement Scan Status +** METHOD: sqlite3_stmt ** ** This interface returns information about the predicted and measured ** performance for pStmt. Advanced applications can use this @@ -7567,7 +7682,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( +SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ @@ -7576,13 +7691,14 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( /* ** CAPI3REF: Zero Scan-Status Counters +** METHOD: sqlite3_stmt ** ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ -SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); +SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* @@ -7637,7 +7753,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; ** ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ -SQLITE_API int sqlite3_rtree_geometry_callback( +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), @@ -7663,7 +7779,7 @@ struct sqlite3_rtree_geometry { ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ -SQLITE_API int sqlite3_rtree_query_callback( +SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( sqlite3 *db, const char *zQueryFunc, int (*xQueryFunc)(sqlite3_rtree_query_info*), diff --git a/TMessagesProj/libs/armeabi-v7a/libtmessages.8.so b/TMessagesProj/libs/armeabi-v7a/libtmessages.8.so index 29c750d686bfd006da519bc9baaa91813dae9ebd..b73f401f35c8c469d5a1f408484f7aba4be7c688 100755 GIT binary patch delta 311494 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

H=+buf`r$J;%qW~K(AST%ayaNK&qw<( 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

49%{P)GPWV2fTJ|yv( zW$G~RJEzZ#i?664dX388BGKPLoemx$xn9(ek-lGL_AS8u6|YY-RX4%PFTmC^b-X+>wNX@0TTI}^RMHphDsDXO$qX+WG) zM9U-I4v(=g&sA%#S#@fBELE3gGYfqQ32Nsxt4T{aNYDMvl00h%o3BP1UV^l`o!ez%v7_k8_*x=jD90z-n7U4uMCF|=cs zMyAH2GPe-6T2X$r7jP(dXW_rC`rlyx#w@_G0-S2ZvR8wzQP41C%ubc2` z1^1@h#r&-KXP7lheHON!WLkDkE1luj{47W%^ZoHY>^**8AnW~am}2!q=)v)wJB_xC z@9LKu*3CB`J$HW_|GE4%^Dz+@`loN5>&Ju_bP=(w7V0`JbFsg@j!T;NsOtWwb@T8? zfK^AZxrqkf3O$rY)v0Wh?1hW-M5OVo+})u$N3WMhq<3E^&J#Mvx#G@5AGHL`0|Mzd z+`m~eeF<&V7k^qU@&KP^QKQq$7TlelD8<3HG#@4A{UPzbmu*J|y(4}HKz7bxa=!xl zi55eCOBqco%V_X_lu@5|x08l)5~|90nf!)&?k_8$4h(IaL9gLCQkGsaFsS(^1*`kE zsMUX24cnE{aLs$h!3>5Xp$28?r6a@Xz(&u+MM?K(InIn_x^|HF*`dePFMnB$YCI%W zFwSlt-hrxd1+HM}~?TPwhOTM-1-@W*+NQ7^l8YNVrP!Cy%6QDXR zfJAE$Jp%#GU?4l2`fgMl&uVSc?W# zIP29%)FR!^%oN8bnP3RfIvuGqKCbmRN3$r>nK+~QcAaw;R6k-IX$R>`&e+M1-y;zF z@Q-pJ#toQa<@9zL3+YzDH8#YQMYC6^6_blVe^)~Z4T+0%+X8=@097i;IyWrRQ4=ql z%1Nh#bC{gU*pcHnF^%V)wCO4CvYj#7>>aG``A<0nL~#PH%TVBfSq6^e1;&s#p30<< zQ9Q@c@;=;4+#GQDXOwp0O}EzEMQEFAJYS8{Ozs-Lckt}L5~ZE~gLhngxk@faIf4;d zihyWDP9R^D?L;XyI=)8yh zt~Gl@eeNg>%0_I73$j6yN?!cFI0ZJWyAvcpY@BHF&7yg=ck|p##8*a1mT)=FQn&z< z&K(v7+2q}zG&J?v0>5bZ_X=B3k{!HF@*(nya!B%KO1`|Dh+uWs2myLXXc>vb04)iG zBbDeUP6ZAL8SVnB0$LHY5;HsdiU4Xv=q>KDoVKS7KlY^XCkO%gfX)-vpM}VkYljKh-c>O zMZMA6ycm*&%B6j9-t-FKIOv+w5hG}LCEm*vbosa#g=pZddcR8QDH+BS;?I>R5m3-p(THR6w{n-y9>(I|B#Duc>fgXgLLm%c|l&c^f3jGXskp z1(YuE!~B-Xw`zQo6(!3ejwg1_EbrH~2_j!x^X{#qYx%bB{naV!H(A2GXv!#u&dv)+ zqD6JOKL5hij`dHdZC?tm z!r6X2%ZSNj7QDU=txIH-_lob2pcA7fp-MFE$=MR~KduC`l&tBJNO0#FoK$-^;t+X! z)tXnLgGj7`5)jU^K6g+tlSYWFn5|@pB&tE1$_hR7hADW44MTcR_-x%fRXx?SR_#0) zN5k_Fvu_)PuuA);`$3Mt>i-XPvz>8{2RQj2$+y6-WzP%W1%Nu_=f8ognmmHT(gOmp zOpr&0SCrokaBDp(&zU6=4rW@=Kq`1@s3386u(vEx9?_)@VC}_mh;MJ3xB?u$?u7r5 z=OUQkwUCClvu1^L&-CD0&#bU(RKdAS3fH}Jf`VkDdH(xEl8GRI+|2tFEibY<-r@W} zH^e;_?0lYk@x>@D9vWBrD<-nvxik7FF5%0>c&@}A4#fwRRXa1RV9 zu?=!S=3HOkt(B2k>89oP-YF49hB`D+0#UfsPqB6*{S{TCn%yXGxso}%Ds0m~Vp$OJ zHVTfpP)hJbw%uRBzsi~8*-%?bms*74%Di?|o^;n#j4$H9x9uAPHFTJ6@M@2DdbXP6PRF5CkJ!#)q=*glJfF% z{I02cLUQ<^NK-CB7^E)P{_rx<8knhLJ8G%9}4xk6pBL(5NNGy>gUK@sUFRQSS<$6*f6}WOD6^Q#=RjZ_{F|;^` zkIHi?&$98ye>6%v^0Vq$-A=XF_7D-!IWLJ3SrRUMOiiqAcZ%K?qn96zR$HpuE%l)K zp}O6@eT~i$(ReV`ORylBaeYu_RGHJFz{9bX#lejrRxAlOcub9sw>zcIrnpz4^>V{% zELsF7(5a{{{7#cNI{an)8|`GH^Uvy3yq%K%>UF_FKWll!s1n5ht%VbpI%QvZgJBhA zZ7-;l8g{C2bCK#M_qa~#ks9_2YgvRa)yPrv^~csy5+g_}myw72NV z;e*%9XLHIz?j@8+2B$M~t<_N^X{x1ZA25y{RDYTFh`0danoOoo4yw_X-Nm?=tk^Cw zp!Y%YPp)1NUPc4jR*uD&yvwhA=VKxl{N&d1xsTzx_$PMoMF`t+XB3+skJ6stK!(SD zP+e?0DK7!BL;qz#(IpU#Ia2m3*DqYCXrLTg*;uZhxPIhcB|xvotW6m!ciWEiQ&{rSX!dz z{qW7bs#~JnD!#RU6BT}-d8gqWG`_Z-&{)ZUdyB$p#%eU1iya*P{OW(;TA)TH+V%U* zW;2xO-R?5I(-SBmVMFWEfLK+X(|@$Z;lV{@fpCKtI^Gp=QEapm9Es(d;~Ry8zcf|C z48Gl3ElsprHtdFX%E7d~tgZb6P$*sayXILd0AWxF+i9YmPzRgTmR`iO5n3ecdS_O+ z4(1B=RY9#J)ws4@CpD4n$xZ23SPw_n6YGmOB?wtO(U?i$R@-XZ8KeGjFY}U8Fb^k7 zr8=ZiEB!jSg@zq$!e%{vKf^Ns3iY-BBX+SilR)ngZsL?Ic?T)$;u@!40_ikDgX^F{ zfhIh|REHX?dy?$>4|JSF5~>kDu-c$s2Q1betdwWHF%c2Ilwe-bS}2j&@slcxt3eS@ zTz6~7Ho<3q8KoWkk)SG9-CFRYD6Q!02%p{O%ss(ewKK_ns((DiYIi{kvljRVwHE75 zwlIfr(Yzm|L$WF%dlm*!AeU|zJ!ze)()W@rB+^6Ha6~Fb@disQ2sIcilOtU4&_gWeJyc zisc~CjGR97ozk>#7%*944jn+gFUfa2OS>!(2-wG$?Q^+Fo2a_hvlH$<|0?bkxrOvV zMDR$&r<+v-LHSuH3WFe|^vLj=VnX|+^GS#M1Sd#eG65{k+fVnF3tXI>3ENH!Oo;8a94m*z1``jYFLP4c`HbH(MM#v@%bw@GnC{r+6n6 zOV%{j#?V|EBHe{S#_=|D6uaJ8VOe)$fxblYwiP^Qj}7^RqigG3tcE7rHEO&8JQ^S6 zEB*EKLVp1R-TMG-DLz?N_fgv{O3{YrM$m%(T*37<>mn17(sdWZ#}eEHBPY;?kgrm1Ml3R0W=+W9<~2^`Hk;! z?!1Ea;0HPFI7<3QJAIUui0gh-`aiPj?c++k%xc7a?(eKttWuYL!SQMz>3Qz(t6MEd zvF8}?8!EYxJp~)`@<#S6#`%4!y@zGCZh<=NfrIehhP5$wIj8pE#7^%nyH7IXjprE+X{i z{o3qc$EVbRR2#EofAyE7T{}<>Xks5T%D+?@X?BXyd9Ui7W~al`j!(0X>$j=9o7#O6 zY+ZN6Sv@B|XzI(u^(!>>R#UsF9OTs0zQwqzscTK`l%!uYy}TLdmZl+=5Uo$nAb;^o z)iNFE_MBF4rrRTof3{J^O?JBRQ5%)Povn8LZ?fy;)y+by>x0+{!wH5ndE9c^Sq&L- zmhw+gmf@TVZ!Y4}LZlcRlRZ-x$<6?T!bOrsGpB|BU{ZF@#_o?~(*aOQ9Uawlf2lSH zmnKe51AU*Ptb=s$vaIFkJx_+OWFA*P-(>&0+7p!O zo9&Ut9rvsCHv@7zb@XPtN$rzhbriyS7LH(Ye7&qTKdBlStnRnGrP^n}=(ST1XV?q$ z&Fc3IyNwa(q%v-?_r`j2(X;0I0!y3Q-fAz)wrEdw@DbIqxm~}VxK+lK!q2fET@cU< zogPgew63gRHqXvxJf>pvN|p2LYGHGzz-skAH&-tP=j-Nn3%!fdTiD(6SP<69J_R9R ziJqm7ugb;z{ef;$F^G&hE>0$1Cs19Q0!PU9JzwC`A95P^ag-=R1_#Ri565v&;*w86 zEBNx`$`t24Jj1il}lhIB@<=+$0L>oGdkBH#kV?+7Q`X5HU|z zav$ulDJ&CVv8%a&PVOROJ%Nme)tAY@oJP5864eh`w9MizwPFo9#byh~VP9ldjV10~ zlQ6p8qI!<5NT=|#Of#7!Qb-KlpuAn}2J$bqhP*PESg*kb9Z}1>+K(D>eK{-G9%5|0 zTaD;uFEVOB!db!KH4d3mx`W40%uwk)?0!kxuSE#KZ$b!skxqTAk1Fh8KVn2@sb70A zaINs^yVKrFc(Hap?Vs&;3o6PV0eXQ_=H}|Ys{LIcP})1H@GkHn^J#Th?w+Sraxd_u z-qWgmFX-WB^>8oy(bOqJ1b0O%(LaP>n=EAG0-HtQsLD3)#@Bhby3h+q>%F3;+zr}o z>Y@(Z4LWtZtde`%W1}B<7~i8dYTQ!@5x(BGnSS3kVaa?UnG~k)AU!%FbkgUCUl|*Yl_cD!wMy?}FE#3J+w@rKzG@wb`7>OlUh?ql@k0S8Gn2eRoq=GRSohcUWFonO^o!|f#F ziFZ`e2x#T89%{u1drI;~6fHtd)(w!}#{-4J_7+ z;eGa&q?>Bh2=!bN=@u`|tk3UmOE!(TA5=Gzd#J((Ao6Q@DW~(CC|1TuyIaqrU5Hr(CmWHpS?GMN)vuXUk*mQruqZ;Peb!rDb07w=$ zC`xj?AD=K#u$j6$$F4s(_d1{8Cxk#nVSg6FAkxl4vdESb8TtmL1(?-WQA+_A{2KRX zD|Ht=yod|g+rvGyRpF&#N}#M<_3s?J$!#llv9%$a6&`>^&)y8c=JL*468YVk-@{5H z2X?=}dr8xQcTuH%RGm@wJr8)Pt1W03r{N|`A#Q@jY1%{n4i_~XnK9*Ypq6fagG&4O zIirMo=jj29BgXU&(?zxqRsWE?51Absb9E20pf^GbH3;7`YU?Qb)=|icXnO{SWMWFw z*=rQMLRVya=LN@Au*U%q;zdf$#n(Z)h%|DTU>e;cM^rb5H`~zqG`VxXDEP)^YWQfoyYWkZ_3CIA#;Y6DnbC~)3#!IL_HFtpb@xMd{Tj(sB!$V>}_{ zL-tMe!~`WxfN6{qO}&)Izc^F9|B#)Kw^!6av9mVJ>RR(jDKY>xl%SJP%D`v3U&dU-XvR8*Zh-TB+c*VS!f?Bu-hclmD; zn73mR%PsUb&xYgj_Y78zzpJ!QP&_fxd{mST|L(zC8qUvHJ3ZjWOsL2DUU$*BG=LYB zibE`TvjvI`Z@ypmc1J^SU!V_bpO_S5*e)!Mb$Ms{C7s4WZh2w_);-<7XOVRLB1B_N zlysua4GV-o|K`~Yo-g9?t81sj2CdYh76+UKnO-nFvXzMUZKnrZR7%HlpINGz|BtOV zkB_Rz9(ZqW*$A<7Z$d%{aKpX?>_F6jC=Esoir6e7Xw+8GLB}OJ=%9n9A?&0zDo|{} zcE>&NQ)CdC#(fYKL=YotFJ4eGqv)ukBIJF~?anxF-ut6J-CehC)u~gbPMxhzEsA1w zX?2)WtW+P@$VQy%L)y?KXBE9Shy&pda$8(2Fny6pypf%PlZ zwj1<8j@OlSgMLAmSCIH+H?of-vC~L~uhkRPxIZF4)DBZUZqz?__8F#5-l(5Ja-P#~ z(tX`8NrfsB{UE3I=R<*h!mUFH6%K;f8*b7^mtK-=#-ZnYz!!5s4TQZX&@_s{Cf%U$LN4_Rm1_JRx~Ic5+Jc z1%8Xa1W}RO9dn#E^MhEV>TxH#&*ARq0=@$Kh zz7dob;Z7amz&-rWLVA`nf-~*LE=gvpoww-5DHHs_5VTVv97P0F$y@Y_?hjxTZ)6U& z&`L|J3-65)xCL587H?Az^LNM<@K|_jazS8;KXFfV6R*pA)zpnlAo)8*6H1{f8Clg5zbNhw_@C=qXo~^nk_1q`~Gg- z5&HJ9I4#9LbmsR0Yanp}L&%UtAv3^CaBL(|jV3J5s(Du21f7G=s+KhvG6;P``7hNz zwR)PLTHV<*wetD#9-&Xk)CgM{Fh8EP;DPu|@LsGfuTRu^mnYmT_dURsvH=E?u8?Rl z)01~ITJh*e1`98B-cG}Q5ku2yT&Rc1ml64Su7d3S62 z-Nn4?rCz>l=6$9yA|P^j$HE-*<2DJFj!m?mP4aW^7`A{(aXc=|Oyt~xCL{o?cuw#2 zu`>jER=-dSTZqjNGqmtmUBF6)*8G)<+@_a0d-~Om+w?ByK0hNh=Q5pKhnuq={N{6E znXqQ4+n&%HXvN{XgH#z3c56Fw_ety51FpPxpX&N2y?@#Hyjl{BB&(U!uYaOhCO?-{ zF<(&b4H3A+IZ3^s9?-Jj?boqIe^I6-2{DUTlDof;cOgQ~r`BoOr`8$ZKqk(?ydu4D}tQ^W$UrtyRs7JNrBsr)L+WXXw5+tv*bCJA~nI zH6Yyi6ZPVP*2s$aVw*-Re6#(~*_($P=qPIOC+0f|Z)j;hymb?q*{J(;x?Vk-S#Hxp zt2f(kVauB$Us+M4(H5~<+zq|c}MirpKDUnbzizn+R34vANVgz zpFAgt+e|W!L4A{GQ!<_n0K-JGpeV{b=#JECsAT_2s-52Y>}_{68|nZTJ2^o0ZJyW91_ zj(1h}JFpnNpeEg+Kj~Pgez`;cb4IN*FS(9eNdF9HAEmm_!3I~U&YA-Yenj0q2P^!% zmz(G4e{mG{`Z0xw{=nM@7-ehUs)pR9|Do^wTaLF$k$^3dggh#=t6!YdkvFSh5i8YS z@6vnf+3Dg`H8REjsE*#H_bU7C2Q(0Nw9&4-q!wwkHieNBI;45Ry5^`Mf6*_3jo$qi z{f}Mq31YDGfUpKYI-4%LJ~-T{9CP&|$62cDTp)izjhU;T>Fje<-7^>4O89H_#9Xwg zIbW+^=VH^EswUm7cXNEDZn|6VpLZz$$eQU3KD=S|$lcWR{-}PsTYo>}PRibDRJ-oc zugEyW@8=rT(0aW`$^L(V5`Q4U6xuSlAf5y)WVQ{r8DPibvUGt z?RPsJ+F=>oGXIO#IXS3N<^;(}Fh!Xgb+&J#nmAAI(qroUlsavqN;{z$bd`kWhl>Rw z@k`EE^XH*ZUf1~YH}mxQjzO2cc)V>h>A`pSI35i`bF{^=`DR0GD&@jCgrRG!-{Z^G z+6Igor(diFEzpPc7~30zpl_WeyjR|ngXCvXCjTpXb3j+W!EuYS7U+XZj`eD9+Y5qa zcb2g70Rj(Ad%shI79u2kqb^>k_b&{xm5AxRIz9Q)(iiIfg?i7^9!0yAC3-(gQHtN2 zmio_m%95>RpT=cl#Q0;Uc1h5i{2oVAZjAf>3Z*a7$7XM%cmS;rP?s;#NB3Bk-8s33 zvlS-9+Xtys2$+rCCgA+<)wV@wN4=M;Ul%dt{WWUYV*NnIv%GWVGIiY&eRE0OVXbW= z=?qLFfn@qtrcDkv99F}YVynFJu)1QYKG{*m=~1@k!Rp7Q`gsnYI%^s0tCzZc879`w zht(6yu#2`^>hop#b$Q<$Yj692kqpbhG_h1oUJfC})t$=$cQ21*;Inz`ibmqid@s0@ z@Bu!#bJT(5`q>!F3mf%6I(r{h^BXZzp4_CKXoUE^ht>Oy`Ub~^>ZY)MiQ_}{W>`;l zDWt(vl-utM*LzIuxR-I?KUtl;SMTCTs>1v9-eX(86?>no@c?$du*FuNBP?ho3-(c> z_T`zBzeAZ&!hGCkuk+iP&Um*5Yw3M7`}c8b+kN`Y&S$?=gPQcyGYZ^!$t#zr>zW8F z*q|0R=@&V(zgGvE^ofHqCo{iZNsSV={>dE6d7AI(ZXn&+0u(H6L?;3jm#B&N>x-N_ zThxL3^(!1()M*dsk2TF<#2Lv zvATK%ChrOA@fC2t8ujK1{Q}30Du1Qkt*pRJIKa-Z<>yn4Nwd z&6Rrp`gf$^x6dew0{Yar(_ii6*pBY@FVtqL`&a2k*O~P1@GnYC_oFYP=em4X5s^7Leztmb zmEM1#-wXo|neU_Fgdfnxe9KC2iX?+Aq!+s?5}yh<8NtSwUv*Zn>6z*@rT@j*sZ4EF z@PR+8&y-%|9QlI!Nnu2LWr^yy8cz7R8o!!F^SGL~TED35byNH^SwOMN5~d=-0>VtH zF)cU{aTloXR%4M6rOY8`qP&shc8!cM0XA*|sU%ZO?D^wul^|z=)@&U_-kd1d@Y&ZOqy+@+%3HriOx2ux6Vyuz(WYlj2((n0Ry4s$-jvcW! z{i5XQ6A$0&x@IdNa3i!y9nlM}JsoBwfJ9|1coCy-SQB|qW>{!zd*%MPSRCY@hV7Ma z#;2+G)_}sD>c=&D&w-s0D$DbwW*{lV`7bC@Z1V#C5o}7u74mEfZsW7o>fK7#fdL1q zRk;J3jCY|O`)FcxUHQDaZ7sY*TclR4)o)`P%U(z5K~`ERlH-mb&XXC9xK>BQoXI2XoNgJEg|XM_NOIZy!DfKRd9_pn+d>NMLy@V zn)N=Vp@x`@HE&X5EH5g$*F1DIIE@TR-Q5hy$S8_A94{l$P$|TcH=ogX>CD79>BSD# z;;6Aha`U`XtUjRAPA+vOQ)f%Mj+;8J|EZHjo$=IpQ9CaM zwUbJY|Ec7rlAlVoCIo}AZ8HsuvF&LX!!<%kGQR=lmxXbcdM=`mc3$_K`X-|Lx_!cA zPO^6yc&>y}FKdLd-0=Q7HR54Nd^+!Ea3@F=AzwCen)74Ali%PHSz(l0$_~UgR~&#g zro@+@XfLUuo69IW?c@6G=M~AJa3OxZu=qqA9Hr z2&=)cnE#fGjW5{T#qvQ{mm>?~kx$NK04wM?sNx%RW5lc$vCo~8SP@}i_+(LptrizF z%GhOHqllKs*qz!1iCHn~`jO{YXt`?OL$Lo0b=5<9asB&n4JzdkU@t8DM$=`j2)HaE z@I$ceF&|*RkA$tfy2e;F9p%Lq#p1PFRs z6pX~@X_5HJo~I<+dtQ{>5?mK=(bl2(Ul(&k;b=Uscfuuw4QpW5NjeE>!0pSU;mMN0 zEJqrUhW^t?Q%57$$F$&lR(4}d79h95#m~jC?1)C}IQpzCv>!Ow1V0NC_oN4wDf&$% z|5s~rb|sv6;o0NPw)a){NA#X$b71&+AX-ktk7Gv0kY6K{|D|9~+L@*9d<=negWCC+ zZuG;6cvK){s3r5v|2Kr2&2{lD4AT`$iElb6f3nb`WkbM zO*88;7E}?Q;<+iDSPwI=1?{t2Y_v`;n)E66*2nCIy&@U39jlE~F+rb7#&E`uov z5R)Brl(*ShZ_*C2?P4%^9hHoO+;K);Z}kRfKO2?o7;-H7olrROeglq!C_xtNYmO!^ zYPbr=@6LrsvI7xZF0EE(#S*q|JEv=jTbmK@g>62&PLA1J68{`CsciAmj_kJf`)u`@ zI~UpSOI!X5h@Lj8wfYCG2{D8-HddJjT!1;!P-Pv$7R3FJKM+9$Agg0s8$kT3jLKt1 zk~Iiva`OLQ=pbWjjAmOa_QhL9%_M+SuB-{f&w+ZY!HPR}ue~${P`7WBRTF*C&TN+#U3A15 zz4u7RyPJJqN^-DPkqG3>cP8&=KoTNDNhlzI%58%=ZtrHMxi)@=c(~o!c}YJg7YuY} z)DH-?GKZDHur)GWF49!I0^N(}RpuJ??PGfP`d?-J2gx)8iiDv_)($c7%p{`X=*rmB%+{P8pL##6!m~M{V;CdyqE~SSz1AI zqiI+*z6Y${r4mH>CcERCR_|imf0e+?ZzpA)pzZ14CtI5~i&z+L-v&`{_`;jF`ofP? zkt;YCPAPX-RPo8OKl8019d!tIm(hTThkJNei20B|obX%@Fww9z3Z&%*A!d*%D=*Dy z)w(B`nNi)*TTF=0%iL2DjKyoBD{VrSkq9BrWF(9-mKB33c@bS`v=4Px5^~W&)PMO+ zPBjo-03x3Ph*1o{$9owS>yL%b2wKh=^zn^yP}n0@<(5cv3HP>`@m!$+q=A z25&#oYqhLq6L?rG_1a{Ym{r~0H!Olil5Q#YW8a09ZS)y7!lH6Fzl zF)vn|o+*j5v87@t;%0uo16=Zs$emUGm55I)Qf*p&ax*472P#)B19bV=Ga2MmrX0T6 zYRi^1Ft-jQ)WMab6KwHGWYX$j7*!0OMx#aFgvn-oZ)^p?$ptjSK?c(r_rT?g-iJGw z-270{7@KZCpB%5@xhxA!`$Mgryk{{Z+)id#VaTFWWx!xNuL1Cs-xNV>XhK2vfqW1wRHON>+3aGkp3B(xn6(UGa&nREAAUjf z)Z|HRh_+2Ceof(_5G;@xbp_B&eatw3$Sit5U{=#Y&cxrVE_zz;n=P1J0-CDT-A^Oi zeh4F4B;?41_)*m|f>*`nc|);fPve9}T4&;Hs>#6%;AX;>`j*GC%Nk>E@LonRh&IEn z7=u|v8xyrOE&nt4Ekd^JCAsG3M`p{n@AD%oskqxZ{@UE!7m>cBJlu&z%GNFD5z;mu`|9h&$A?v2e-WzQlX z$P_gCDFzBZP`F|I*F!pT{asT;s!vNcHmNI~)q72v16c}7&nM%PU{W%Qr0BR-GH;f= z5o8^JQMYf4O-DixLMK&TF1ry9R=3ycy)e#tkj6Rx2( z;X-pl?T1IH`=8T|&b7eq3cZdA;Eu)`}J{b_NAw98%wT)#u^F3Vxg zMc|7JFSlsQ86es1v z0>moc!5&uf%r5ta6VDJ=LQ$WGU?~? zr;fKxVDKIgoEwV77dI`BWj?$pHjHN?@6Bfm_whUsBtMWE^MYQ~uSYj>R=|^6PQmMq zWcGdtfmJ}`w`T|jX_ zYSBv^JCxOeqe55toAlm(j^d1zxHOGzy!mKqD#gUed7Kh2V~`M+3?d_h{@kWro|6}% zK4ZYrlT@Ki`YgwL>T4QvT%$T~){7^=${dhtH79E;0Y`0@my?}4CyVOUhL?y}eE&(c?Im76=Tmj~ zCCoX`JgIWF;3(RnMr_fiIG#}9Em+2j4y$cj@MSD|@_1Vo!w@H&SS-bwu_mu`^0j-^ z_gnOSL+{|ZJVVYon!$4kzQ{3&4W)buWfI0Dr#%;=vYawhjeA)il;?xD+Zp(oka1_J zRWB3hf5jm6;mdlji}w-;BGF$}bqhQmCR7Ml^u_1CYHxEf;o}*RMZ1}lM~1YwVR5l@ zt!TkX_5?cv5m})*PB=jpMp@zOxoZ4Y-83NwSWwOiTIzU$*~IQaB3bWMVQTfE){m63 z-`G6jUua-LMUd{BiZvHhqdS&r&D1f&NxC;QO0zO4@5n9oJ z_(yfsD=4{TY7I3UU#P#n0^$BmefA1#;xd)Jox<1E!0kA#mZ@{M<4|Z-OZnIRu`gLx zv?U9{W&&m^21@RJSfqAt$9vzcH8rGSNb+5VEsq`prL_?KctBx|#pT%n%C^^#SxPPr zXbB`75o}1INPGm~W&3dI(ghA;(q^o)vVsCS5fOEqplOO2h@d&*jPK5O4f}$_ZzL!y z8Sgug4TnqJk*sFEst<7dQH5W{qXUQIcAZGF6Q~?MGKEsPw7Cj1?uc^Ev(_!L#y7oX zRYw+CvWSH6Zcy=8IrH*5bMz02T)g&<^6UT`FR1Z5^qxI>92VO!`$W3I0$I-zZUT!) zj8Kbq=smjQ4z{W9Yi8Y32j#If$*EJx=^9i!cj(=m+L!9{9faCuf?Nj#If_RGn3lgO zS401Xzh=`2b=}|eyF4x*wkMT;gSSZi_BXxM^W+EtsCyKE-cVOXnJiPqOHVOWQ&e|% z*@lPzGwCQ8N$%!5I*EANN$Tk+?$_aJ(oS9J6M(z8X%%}Pw|v-rV)* z@wP8d_h>$1a_vI9+S5B4ua1Qh?iiw>pEPOFsHLg=w{@etMD|DwX%&p%i-8hU zwSq$|3v8W9_IxAjZmLNngcZ|Twol4TWC5w9+DCqb&Z_44QM z;JxO6PW~=P|L>||7xK-O>Z)D%2hNzQ?%Ji_TsX0S7%PZTiy)wK*oZ8p)+%*EYCg`j zbHtgt=eD=`;PcY{hBP0zQq6dmwe^g;`&}0J7`69Z{f~~<)LFarD;+CU^KN}{*N>9_ zUy!d>4+;Lnw=$L{=Yd})Y!?E`M!T>p`J zVh`-)zK>Mv9^6(}s_uK?4|CP{z4}FYm*Gwm1*zJPwl_yTu@{fZ3bl7H_?xW0+pCXu zj8zpM;!=J%q8|8=7_H(jRO^TOM8~6Q;68#sXQ*rUAw6CgQBUlHMt<9;-rq-OkC!Xw zM>s);lJ4dsTx?s_cONkcO?RrC{j7ziVQTDteOk^ekH+@uPxkz?dW8Q(+W)d&A6~yz z-xC*p?KGFfgpx!RX92`rO_8{1HgR3B=*naUsN>X5Xg;YU97#Ed?+q=mw))<{I)P9k zs~Cr$;7=$-%AGhZp1c}-*98*7%Vk&A!Mm^t2^{s91h)HDTrF41+H!{I$Wp;;uCU6^ zCKQs2p1RkL$bXNCU9Rpm0zgxpc62C#v(lhgKsy@M+4Dti5%a$Qlc5HFOk~B^>hg~< zw@p=#f2{YTMXpQrBnjBWXpJk|Oc+j3?e$lnK{|corl!qFIXL)f2fvyfeZ5%^&Him&ka>?eW9N}?D!t7O#l`M9B8^| z_W9fq>U>%tqgN-rGO0&5GD}TwxwYSVsj)FU=XY1A%`tsZNj>lH`LEcKm72$n9l3Ll znjA;&yLpegCyvKGo~L&3zsH78Qv2c%%yVc&M?3S~%=dl*4f1BIj0F4QOJdRw1QN2v zLu@FVSk{0~RE}+GOhP}iYb({i{gYHn-RqR=BTF+v%u8xzLa)z=mH};M)=xhpSmu|lMM)&nUGA5kPU`17oJ}97pT4AE@F%Lo())ES*h2## zy(*1Wq!Z#X!&XSmu=M--O?0zUa%_4CZ5QCg$R*drc*;ba=!hTTc7?pd`Z&i&>f*!t zMJ2BaUA6=guYp`R_kZT9Dxh{8hT)C-Kpj2|XlH+*GLFFb+TT|rk8pYii~F)8%;6&S z+z}3_7ek11z?~CHxJ7+^1VQ>&&Ix~|4;ymgQ+f~zXo=)s+Y)hILN$SZ><5&Gejkfa z$Y0g%U%`uKpQ;XgMW@w1_0w1S(~g_f!(Z#?6^>(qGfk+ONf1KGVOZa*6JP6p>2(^y z5glM7yDWJVNO>21@?T%1$^_f4Q`Op|dawLLL)+W#0suEd6XqEVGri%&owt+hH7%2t)0~R7>BZOf@H)lpjE{}Q~{n=22+3(zOIdO2}&lq=z^;(llB-BW<#ob24>f?L_!>BR%jkX|(Z ztqF&!_=j#}`+!}Pf==qff9O5WrNu(ix1Iz{4;BXbXueQk2YkLX1m$+f{FLOt^#8&9 zccZt-xJ`QWsh9qtpIUDsJNGf0t&mItGc6s31 zb5wxM*D_?r##T{Fgn0YfGJj(NA6cT$IJA~Y3u59JU&ykRbvWx%fR6?eH2_u#rab^v z&cNQKZ8_smLz`mTcI0r2aZaSSxTM_vMk}P9L+%23xh{}+B0cIkE#buMrf?z@3EP$< zd3gXeAn?ko$nj@o~lm#Q|~s=dD-s>Yy#(EfSM4a-?RZLSGyu!7lJa> zm~RjrYt)Qy^uc|l@f#sjC&sia&MGvR^J7&eHfc_|4B(lUDd?%5`bK|&8;56ns}C=m z$e84Oj3b5wON~6nIy*)S^fQN+iq&)9>ODObjHX!a{Z=16X<3){wrQscUpA6iU;zoO zq?kA7(2Be@+r$IFU_=|1Stw@(a2NVfnR3}VHJ-_`t>I*M1)J|)welDN8jE_OvTM!O z0=^wo70O76DF{nzE*>z>`t4eH)v{Qz`s^6d;*)>^FU`^7NV6q9PM{}$jM4kVO;j7N z(|5L8WhkQ3TksBG{@~WCFN6D-OvtuV<#1+FO^$ zW(K(|5yKaxK2oNhz%sent3<4k#i6hzsmX$nn*w@NIefR*+u_K<7i49# zle-*#7n0W0lwmFAGtLL^>Gvd(9m@$*Q34<}+q!#XE(XwodnaD&V zcu^Kk2ktYOgK|bMH@M4aWco5f2&I%EGv-J=0b1sXLD|=K2sVP|dK-h)04zrOrze08 zn=3N2OTU!?sX6j`SYOPDSs!UkatPqp)3IHJA;vp$M* z0}Hvj9%KPW3$P0(5R09B=P=u|O#Fsk#=ytHEMKwuc-s_t&Toe=B1cD$%C~eY-MjeR z0nR=F14J$bN8UKpLVt1&CD^jwNrZU!AN0~JQqs_Lg6t+g5NWhbUH^mLZL-HJ`Ax+Z zA~S{r&y0zXDQi<}BD(=T9IXyg!`UXzr%LG@RFo0agJ%^`i+WDTH3u9VH zefWc3Rfx|*(*_|(9o_6b7I&1bI6|&6)$>PkA#w3T0Ztc(c6$=L5a&PUB(=~Y3mU+| zav400_XJ(|d9evC6HbuD8Y!bZtB%Yqph1q*ENNQ5&>4!%%Wj$%Li;~zLrn5_&DUs8 zsnDRbBXsEHlMAtrl|JmkKqOhKUj0!onotM~F0deEbth=dr!5cUB72~aR1f~kB6Il0 zCq~6sKzO#Yz?Q7pg0g1o!3m6-1Cdq!6$zF5lU{t49K-NZQz8@W<;fcxY9t5fdID!s zZwanf*Y=J5w_q<@5L#%7+~;_oKw%Ox376OWwLLz*-WM8D`9Dz2^`#Uwr zwL3x$(yOfZ$LTLZe@M8=F0%Xe24P(U0F7Ogg?+<7wc#hdM-MH~WN+ipvEi|$=zzhx zGvH{h_LJ(0e`Bt24N_14TfZacrS2(l_W!!8K|iAh|4rTWvwlt9Q?uLK*!zywA=XrP zRiFQi06wR?>hcT1+-?2T`M)4u-ZDVl{0s4>|5o8&IAeZ$5A_p&>#Jx{(+HzMM3pV_ zdY}}YW@a&YQ;JASnw^rATy;b*U-XdmA`+8E(q$(E?)E=)#MIytXp7H6>|Vk&CBdb% zqxIxCSmdsRoZQkPk>UGRr4H6?CM545sAEG(9*l;&u=Mpa@A*KVwe1W&=oa1`e3F1SMq_9`X;PA{0AmAsR z#WSAaqVcBGaaNnX29PTvxV88U;8PVvl$7`BSnlRg>yJZ>OSSp2Y%LVa;qxfqh(%PS zk}O)5pq7K)#>CiD8xy;|ja=*3Xt|-x0Wo6h@bhMRcLM4atibs(kzA^IF2DWh?~Qz) z1_mpsZ#(^&3OQcr!sF$l-m_+7y_IcZS^%_jn3GC67g83oe$&a;@?7eor)OCjIT4Nu z^Rm>fqVA9(%j`w!MgYlRFajHXXFYK8!!hFtfG!N2Cu)Qo1$vI*hQ{ zlJ;ysG_~V5J!eL5+LL|*oz_}Y+gh!U1n=~fZ8m_Mh9fc`?iiK{`rek_*L@615Oj!o z_Hxu3ttOBJ>&xlL)qI_*IDyz?s_`fE-uXjuwhDUf5k>-u40ZPjy<7d4&phN|aN6!B zI5~48LZ%$QlFqWh*rAoj+XUlgWU1xkSpZ;)>9jQVcWY)$%n|T5^3q6MZ)~Y8WA%wH zwYr;sw+i@QV5ZvoqL1ikNN4{ALd>CER3hn)4>A%F&}>1Q&Kylz!qGGkPx@}CaJQxN z$>igzh$T<)?zZw`yRD3--PU@Twg+l=08}p@#v@H#cTyj8-Piq6(vKK~oG>bnZ?^|- zm6PgY5}`5h7vJte5hg^^j*fiDszH9082&eCQ;W{G4)%I0er&+*_>heDHX(c&pde@_ zNYEndt?)|q%}IP#*($qT@89oS7MD~z2>5=Q)0liOU`mtjAk>R)`eIZ~Zr6L&+v^B$ z-O=R?8G(u}bNS?@lU#18IFt{?8e1xM=TG;2X3a1^BT50vC1wN-DDEsjCt*_mWbR~% z16(GaMwh0?gJ~FQ1D{#6VcWmNJ48G2x!%vLyJMeO^}f$aEeB`P@1Y=%#vBC?3R8DE zz)8Mu_ez)1zkavfoyp?6<8*ig)N&Fm3kb43x&qh6`UD!G^OQfJ7nm)W0gq!ye!%hs z7;=-CGiM}!1|-4Ux)UeceyDoLZdd*bT4wip(3<^PgS~K{HhAiqVq;>wYBB8N# z=>0(;dvOm&Mf?r&?qu2%P8sr*CeAzAer1VRlFvslltSl{(!{kK$Px~g6(Y_gopSUY z@*J`N~tT-@N`*{?1GsB7~$69t9PgK@Rz+N>?vtIuWFH^l~Og zR&boutc!lxvk zS2wwhGl%~|k#Kk6>PL_`Y-RuxkSRbg%jtQdz3p#wC~2-d5tJr>v-*q6DDz0RuxaXH zmr+n3S#J5UcgbuB`S{Ic)}z0rW~GraNOZvjWH2XPh#WRR3tN+EQp()vGA$H|i%nBz z*bvIZS0PYVLj^9n6|xcgd=;xer1w#LWFK#4cC*F%clS_up&H{cdY>h!^=xVfcMh{W zVe=~F1I>i3m`+_(B;i-i09m;SB!$fs!qN*}fk^&Ss@Y?lQ6GYsWGfMT)-Z&1fJW80 zgKwFJb0|ahN#Zspn_jaumEp=fPEHT|OrA@<5quledz*Sf53=gBys5yj0&m!wXGY?$ zjV42S5!;bH3xOo)Io*;21@eM}3R)y;FUJ8s2r7~yC`q3#I)#?D5y5KWYt)zwqj%<6 zqA8NV{DU1vVf`5ZEZdQo{aUneVk4c8GMV03Bza@ZwCYD^CN<_G%jZwp8+eTUGt$I9 zkr$IaSNf@@-;Qk>xfy>D10b`L+=Cz*fG;gy%ds`P9`lCQC9AeRr6W&9-?DM?B3*|SlGIWNzIH1v0!etJ6oENXxto-;X*X~(}O7q zrGk3Gr-HCNp;sX+0tFx*$%8Z{S)-}>nMSvI@Z|K}Xs-mJA#jy+L;)$1k^?*BLW$v& zP2(4tRJs!oek=u4!0_;%$A`og2-`WP1osX*>>4ccTUJ@7mqYvDc9ir-WR0fX7^?)N zE(8WVT}5Z<&TV4e{hJz^WfaxZZaabQLKqVWPLuVKT7q~V5u(OK-tqv4>n8%>4+B?M zhTh55$(D)EBxRE=p|T+!A{ARl7nKo-b_`oDFrEQsv$YNQWjxpOJxXh~KA@e)NW~yi zQr|HrCFwa4JYoT~v%q%(zp?_xA}qLq|JdK!U*tiH*Q5Cyqvr8$)=s`*t9CF*H9**2LjDVY-DGh5ezaH($~8)Q==>Mtc_@=X#LsVU zV}m`~@`Fp8`NPXs=NdT<=fB(4&7F<0PTy>`xwFyB*?+b=(AgMv`rK!@)`1S>WscC= z7jV8G*LfZot31jR(gnkAFQ1n7HrYV!x*Wp#^dd`KwxnZV?@K;&$qurjRsEW0jB|eW>&s(L zF`N$P_F^^8%aqRHy(Mh|E9D)no= z(a(8GmFlG%S38&VP>XcqZ0GIIskd~aN8Zm*31Os$GHa#!UN;swe|$>aWdP#n=hOy+ zHugWOb{NJq=c&)DE(ONfU9V%lCLkGI&v#X5h1JJgZ8 z?!%>;&NCbEaV#Nwt^^QGPD%i+Y^XjQ^lXqY>Q&Z!laM|iCM-lHC&5h{CxbjBl}eoS zK5c=Am}(pY*@ebA&MTf$6AO)DmroMF!Kn=R>8zCB%XTLtYL)_!bcKx~r6JHBX&}Ud0Rpw08nhBNK;%uqpTd-6A-<0xn0Ez4WmMm#Ce!PFNfFOD%Nao+~<_> zs_oU*c)gS<6>czy*FRQ$yBNLmg*&nf$ESNS%=_8Z)r>Ci>#9168HWZ=?AwPzk=I8> zI4I^P!E%UmC&ODYC#|qd%;8lyQUbi{cz3sv`%WakoDa%KLZvWz#-xsn5vRhAnA;c+;kac53vUhPTkb0wd=B6ww z6tZ$#LTIULt&JO*4Q7Qwa6D>3LJn`beCoC$qX&m@?=LdWbY3`CyVT>Z9O-()v zUNS&gh94SGzZ4m#I>Y_dpkkv}{oi|QZ9n_4%pt5w_&|a8L!{h!$pY_dcI=w4au#{~ zJ$t*1B+vOGrEUc1T{HtR)QE^*1r(sZu#fNULPw`Uq{oOcfZr00s^MN0^l@mXRoa?v zO3c_M$|LICVx!`;>6*AhnyvGOXl*iQW3*OY2qb6FxD3;AX0AOCbJFv0tDsR;bT$4^ zRuf>Gptw4)AR)nDatFxNI>L{c-XPCv)nB_B-MW5?W2J^WE?l@{_?;7^RpE!V>YrVW z;n`9fh)JbAu!JR6uEv)b-OfGj9^t%!-(w`!gjTH;5 zo)RDcqx}z#cvh*NqQ$cY37SpN%rOc#0oXo#69wLVX;iihsKY>M2oxa(ThfKaVy zc@lc_xbk!}h6B`yZpKAr1<^1Dh_Lm{3Z%a%wE(cJ6YH17<*0BZ1L`TMjr*k=@_j}p zjqRIwTujQ}=BT__pDN9ml|E17q3>+N{vhF1renL^$O}n4Qq%K zPH>UVNzdXB6LKjMNkc9F=9YD{-y@VVb-%F0%jtjuG*K8|n97d4;@+sC}v z#;5{mi$mVpNTCwW+&dbQQ`SI&pErWT-;H=VocG zLcROcXWfmW^F$DmY%Mh{ICgx~Et`Ok9sH3s&OK|3Vp%PX32$&+`c~&j$(5Welx1Fk z%qes6WTqslTdzJiP*_o4PSU&rUUq7FvNBLC{@@Y`HjvRt9+^Q5%b9D)bs;(B=%A(O ztHPjM{2z`s<3eHy2MQ z;Tg=6ACJ;ZGs~K#p#amd#^5EPuZWPgH2i>&?o?5rx5<7bc zKzp9#AwiyW*I*!hz&+WrLjyoda zCWZ@Rbr4$^m&@&vXAa)?L9_?cZDeU7WS)8P+(`{bX!q*)TpAL`Xtl38Asj&(zy-W^ zkNI|dcA%OwnGeL7){>xas-+$K=tn2y(C#x5IQMf7f>059yoj9x5Sorf_iB~<%D?41M#=0;s`((fw1+FY`To!0S7z{IbS4C*~y0S zTh34yL$S^*1Fvw*VCOP^E_*wl)J|N{QDC{KE8Q0yoBE@$rQvx^us1w@}p5PX4E+^fX+@3zWCCozSdUxJ0uEXmD zX5@&}LmBK4lnK_VwMB`H80H`O&j6h&+{@_XSf$qVGWz7sd@r8CG-NUj$JF0@8H4+- z25Z|N2WuJ^E(9^<^Ic5FtCuMgxMh7WQC)i*XLdeFQQzo(IA1Agn6K(>^mkt8RLgoB z)2@O>J++_!8H9P|SZ;K2LgrTHcq*uv*~B?eXjZEUf93p*-axAy*_j%JPE)S?coXmX z5D_zXo@-y2AgZ&&cWxqg=lw_gYD^zU>5Z;h+gCy^F%p<-k+{j!3%`(oi(K5x270CK zjh5|Eny4X2OE{xs1DhFvf3u8a+q5Y_TVcI$7JCRY+QCQ0LN+GIy#`IPviKp(4-c0a zM(eDPmEN4%V?PzWn+GN*U350A$GqeUVJxQin#8dD#<<=)RTeQ>w}VJ6XvX3$U(CM9 z>fl)ZS8x!n#h#(003?99{jqp3gh4J4i<8744kg6@LY9hJ+8xu&o!mO?g16&aE8dRx zft&u6I21qVdMiE}_f1|jvT1ZQ@~A{1*d*h3$Bwy)mv31BwG}DXu!Pq<<`#F)S9H$zmc3$xq zcLr-*6ApR1)mf(+y=N?;NEVVD}-3;U&A3Cqbg7YKW(!3jWXR7Mz zGp=!tc}(5oGbZMcUZ+G_^7c^&e8$jW&9LgKO@e^Sk{ej!{;2$}O|Ij2O^}{}NEDRQ zy%E=G-iXotggQCM=;7%^^L|w}*f0t`{4C{+o*7+X8{IuvLu=Le!A8&g8+at=3`+xV zSV&zZUUfIcjx5zY*yvW_$$#*O-$lMtCaTzvmmI~XuWuJM(MA}tn3@Lommy26L6%r% zU8DZV+s-Y$RbIJ)pI!AWH+tF|SgG$a>!V|z{+NMyBo_69{tM!A|B%~sa(6GATJ!-q z@Kd6B$rwTFOK4eeFEM~VZ#PSHLw8gzsVKECNVtBlYyKi8_1OqKziwIL**bPj^-H-i++9jm4CNbQoF=T@7cF38 zDzI);w+=zTm<$PPUcz8)(QGgDVI*rM69qyH(RD`$EOY~@ODo;)(u(UbkS%y4kHca`mKxHav)t7viMu1J`s`Xh}9-n3@(tONhUVSm>OqCw7V#Jje{A zTz%W$=<4xvgGZg}JizE(e~8-`MVB?bdSU>@4(~#JeSp{?ZABrQzkwv^@Hm=^u!$CW zO+8U-hCL{FIX)!40dOZr#e*pNmn0=f?{db$J4unNYA^`Msp7d&vbWH8R^4iA>&`>m z+sPq$_Hxkxnxf&c*0$FU#5eM?98IplXd$v{5DudSS6eI0u=RdtL0Bq6`QbdSO`*XR zG$^NJWob@TKQfL>zlOqZWHE$HsFwwywaDhiYmc(tDDU_$lx;t!e2kO_Bk>h932y9n z|g__t?{XiUm>B@eKZ^DVsU>G28uJ|NA&omMehbdhOS924IC+|ty(hq)&RzV{h z=g7EpX0H^+=<}|(Jkdq5yr%n)XvN{LL=VJ(7We+rp$Ecy7_SBQ->B{$#438`5w&5E z(dFVl;_VW@wP5f7aEPFf%$Jkl{pg6e&}x04$KG79$?-qK`$i_uit2e!-Wg*?j12RQ zA~~@hy|7dA*hLp5|Ex}{07XkcQHIO_*mcvpM6F8`UHCtbXR-oiy_X}@JOdx9hK<2z z;BNC1)vWjVoT4AV0HQ9|IyS zy3Q&Ni0zE1*VqcHMqNA1xUx_fV^))BYBQ1}er?Yg5F+eTeKHKzcC-3rm~nx#?Oru* zxUr!tp+q?aO_FwYM)DOHkjRAtLe17U>cnuPcaCsk2_TphR)Z>ylFqxn`+YLJYEq>! zyl~nt7{ZuJsan*F?6?R%HR}FKqp0tLH24nCN~6LFLH9 zLmrk$7FhiEFkwH%l9opntxS((Ps7n_)z*bA(Pl7voNn~*TI(S^x$F?mHC@(*%Mpwi zA*$A@A!iufX0T+f%c-KVjAasL(rSipVayx6-!?&rST9WckwVS3U{~VEvV9BC%y}NI zM7BghtK1#r@g6!NR_;EWN0_RfJHsd%Gmh%^q7F6}juGzTd#gy6!QwjE@QEh9b#Y9V ziQToAuFV@ctW17YWXxbyPiv;~RKe6j-9EPFaS7P~pp$K^Tp&g+w_oFRA*tLtf%-v9 zMAFv@2asn1c_t(HLmK*Dj;Fx6-kmyqbBy4Ee-e8xD;)zfqlKHwZa-UVwl2Ln@pTnT|UC7C)@OABaGpB&$_u{(ffT| zGM+r?Ry{@@I1SWUx2E^hGz0!5Vi=pNZxXr(4Zne#Fhok z3TX?%VT191neA65GbYced1iDCSTk@gR1nw{N zGTQy3qaarbrMqr@;K(8V%a(*(l%I(&)>RkD|A4YD0q!3r2lx?^k7)n`0Ft&@u4WWH zwR4GP)9To7!---O6;Z<)CricQy*GxmXEQ<(vSxWFSvP<*cX|{;PRG!*|H0IVZ1Ftu zf{ak64FKY=vH~pqgo@VsB z@HBuHWBB&r`{GWf@FoC~0m`6kPbGi|s~s$ZqfHThru~NMMFyKGuwrK!iJ`ElA+*H$?o7sxA$S8lXsaE4{ZxbZrc9&Apwg+*E}nR!elp)XWvsUI2F{$T+9)h$A1lT zIvf*X=wXwbM0sJgNFF8ROri%IoecYEFFu1a;pC&#oeZmo7{w&`LKN5s=`Jf8wnj4~ zvCzHpvpPA-=u-YB-IhVPLW7%smSbv0a_FzAhgZV8MIw1q~^O;7Ufp4&Nb=d5B z^Yo`-2T&F{h4E|qu5#}IgfK^<-J72%Rp*W}dS5(?DP=tI&MX3xyN}fIS*Y&-lj6C!nf*$p zP4n|V5KFpRu!}Q&`BEnsN&3^|(UWyt?O!}LVXI1vr?w0(N#);US|T8v^@Eg~BU13i zJkwAG(P+_|&rP_SNPAncFxF79n6m^Y&Nhm&xd|=j=MW;f>OR^~*}p%1b+plKjHGpV z?cd^jo*FM^@Ep@y`wMd}rUW6=CN|B$P4xtDJ5^Gh(*~aj(9eP7< zbdl8;CLyn6fM4G!VA}9?BQI$Rd-)C<|N`-je`6&aO-R7m_T3x2rd%Ufbn6m@D6)i+kU3tI$f^k|H|B*|Wa`5+V%x$xCr)wF7($N1Gu zV33X{Q%6|5PQ4%vds{HXft9H(5{CJJtuNa9743Zjv2U{a5#yaqfKchJqf?GS(E{ZE^JjyA087)c&ax8&M8Rh? zwMSpW(u7+lMKF{Jyi&H@7PO$2b)2^eTN_w7!X9S&!-K2^j4&5LKsx-lSWp6yWF0Si zTCfiVm{b}OTO(@6dB#QcD18JFN3&ek$46{n2J?I1yzX zzA756<+L%zpnTDnSOQj^hV4H{O?Cem z<1&w|;ac_G7^8pQoF5ofdS5(JZo56fB6ea# z8*crE!un5XD3Fqw+zjE|GClAEhg3LBFV*cDH^AYZKir}tWlIF`p`!_4uQx`zp8sC z7`?jxo&ReQrGzjBfYgjSuB71q4g{q0)Ky~*Bj-GsTSl|{gxWE|=#n?&I!@whVe2ib z`DdyF7ZPf-V5S;5(HN^A!0MdIx)W(dbhIZ+)V&jp(>reiLu1lc#JsHbPDINYZQI^p zWP~t_XB|>)%^``SBx-z;W-4(HNnp!J5ye?t)91yGj0%M*o02?NA_!V=X8KXooA{!r`Z@2O>6)=W;M?W`1bIQz*Y~8z8LfG+n`Pf7y})P)rf%6 zzoZj0(-&{9s0$7=l+Yp~0xYz?)YM%8YE=jUrxmr2IyU3X)u{Mj2$AR5JYPg;c!x6JZ0%yM<@B*U!ts+E;qwXo3_ zUMNw9$2ejn^C#-@wbvjf_#??Zn-WVu-I-W?`1jt8zU%>B-PTu5rzMY-&?RP5~uso}7zp}kV+#-E^pWCe5Po<8BeF-=4 zr7Mo4Tw!Y3@5xEc`#|AIJgZ{f{!QIF)##ZmVYM|aY(Q$w zR5Y6m94SI0A-I#!&V#arv|xTrSF3EIY5;&)C|mp=6Eh`BraRGx|1vEOpF0uqy=R|x z96*@}&EV0Yn7_Fm<9c>HOK-c zTpLXZ5sKpg$Q&?>^Q+q1B7T?&3yc$)$s1_D4{a7he*Y)$K$EhQI5{9BSis8;$%U=Y z>09X9f#ZLk?>)~;$egm!9p3VU9nCFF+)FT;*8y=%awh9l{9?l(Ug*b*jow|>9RnqP zPTfJJ$DALr@!*Mds-e@2n+YXso@Vssi22TGhH>2jFZUOL#O@p zh+9GSO`&z^K(@6Tm;@=4K}a0pD4va5qq#eJ?2=c0|kzPU#YX1ylu*0t$mm0$d%6bqQ6O=-KhK8;t zjY;&H&1vAP7nA(tS9SfR#^CYYfJq*An1oKnLUoo11DU!{ksd@0wrBvKxgQ!|SmcSIXDyL?Mp zYJ7`cqU@#jNbw;ABM_FW_?1SfoFkYUVC_Xji4;8W0>2}&EaArU zmka;*;K2C_ouyoz79@;i&^mQR&=@qt$M6LaEmruiB&8ob|V7~Nf_k= zh+IN0h;j)zg9HZcs3Fl01iQk=Bz{%OZ=lU{k!%ja`DM=o1V_P%_O&|Y9g|lDcmuo- z)!V3-S&h^mZyQd9VjuaneD}pJ8QqZh5bU+Ee?^~lX?2gev?ULth;HKi1mBg)r5(7+ zrMdc3hs_&ZaFVga&Aft!Zyp#`b^ia~S+Wwtggapg+aw?&pbm?QNM%4&MATssqO~@*6w#taMMZ0!$-&#uV?Xn32 zf#gUhxPbj#_bkm0qbdFWN0NJthFav2)_fct*L=J4v9T?S9vge7`EIs-Qa@3RZ~VF* zlOl_9)Rv@~pZ0d~ynU@X?>Bb8qyD`%%hX?r?_`So;W(M+GNJMwOYv68(yV|Ky@UeOJ3cI2tgvm0T;Bsj`n$N?`7gyN7^n7Qg z{+9hA8)IhOZ=tZTl?66I$*|e-TSVaI5$65h+7JiGxq%mq0i*oF?n)&`vvMG{miAEKE0OPTCiG_GCW>F6w09Izu<$`ctK z`+IZJRd&BYn*SQV+gh_I*LLAeTIZu4m)v-FU(DQml|886M!KZ>cVYkjU+TW}7W3>? z_Ox#I_v!D}Cm2+AQN~nUjaK&HiRR3!?a3AIql&G9eM(zamo>c7q;~*^hIh_tv*~IU z|6INVIjhWtw5#sRAtFI4X9z1%+gGce2xa1l)X%x^Byb%=`=@UqZrYC#I(k3;$9y!! z0kjik7|)aUg|ZqoQ#_O^cl{ z*I2Fy*C;MIb5!@BZ%-s>4uB=##^RKSgcm#W!)Wn|#qfc}Am>F2nzC!yhBLk+55aQO zg;DYKI-8(1H-e%HAVQu$paeP_oGDa%Jn?jTCcv~Wc*qg|7xDj~j{gG?m_OdY{O5=z zev7z*Tnfk7JYu(03=H7YyKNq^HCB>C!|R7*xbZNT_4cA}B)JdNIz<(A7-M4j3HFaR zkZcRjHyGXEFG^~GUxv@bYHhQEi&QnbVr4WjO^P`VMQ?XPRV?x1$x~$Y5E@op16$s8 zEo=|_hVYePZ=H{x4T{wxPiRuwL&CSN^7LCv9h~2(PV6iMNLh`F>6hV9kN`uGg-Hvb zasaA`vZMn|buqVHOZeSiK!ld=CNYu=tcmF{H+}C?j!Y>%JBI%!QI!Vi6A&&Caze7) zv!ILy1Sy{aL7-f!nMhL;>D$Ycmw{TqyTT^I@B|7gM6RV#CEadY4A@y#$4{nI{J~@* zb62h(hv}m9Orn)!Adz_`=?|;|K~vpC-uc|SI5^Dok3-^Vc4hLtKf=0Tyxy&gWzAMm zh3k$$sbLY;cRLHCuEq~=T9h3Nfc|idtQq*gRQ-G(QBO`R z;7%fURR7I_hzhHq3Jj*;+))xTOP$9LS=w%T5B|{&jw47WWcc1$^`iT0O&Edd4?Q zFkK%+S2TX7vl6zH%lp@nN$wMCcU|OKET!(08I-&ji%jC${%I zAj)J6;kj89t^=jqo4;RgAI-s^sp}DlyXo21;pEc?b$c|nSRv1EK02j=MbBW81B4%bR%C4VgzcgEJu&4LCo;apF{+-g1X~a`~ zGhsEbit5D3Uj5C88!_*Hf1CN$jV!h}x0p>g+O^(Ex0#a`5PDP*Fuz)0|LXX4v>XKe zs#fDA&E?O76jZEOK021jdKt7p*XuU(zI?%%h5ZTo>sL5e=T4sqJqKP#R{ z9c!+<30-yh<)-+JlI|svzLLDEaRx00%&U6c|DY+p8QVN@i#h&gRM79fH{MJVoumyb?+qtz8)`4LVK^KZyP1#Sr zH!sDAczmIvH4ZKJ;Ha7)ox6^{WI^X73Ph4HiR!( zVGh^ZXL?qcGZxw>d%tNkw=TrVbe8$cLVLQm%OT@kM5&*xFhdsEWu<2Uk?`?7Or;Ya zv&@Byq*XVX8y49UO2_3{n8^Pdn`6w*Mc`vYqxoo&J-K9QqpWCc2h(w2iBw-Relf3O zjpm}oko^K`T5M17)R`w2z3LldD9K%m8DSTo(AJx#{Vxim@&)j34^+^ zvV1wc5^vFW#r&_Hek|?2<5|H`=H6v6i(sR9g>Sp{pbeFInKGj6Uo@ER%h67M2WYB8 zW2bTB`01OM^WD@U^T2Z2F1Wz#U2d=PK7OOQs)3$e)?`*S@cygi=Gg{DZL-Ecvb_BO4q!J!x+lT;A-g!LJer+4-OD+KnvMNU%T4!{_N`^rl=X+Q z`h}KeWg<(OP{Xcmu1_~CVZZW)C%yvbeS2n+U}Pt;O<>! zCa<<{<}jRXtL<_9W{s=qrYO{MGy|PKBAMt;n=p$<%S^=@`}m3h1gr_&Z=gAdl*FZl zW;G`R>&f-z+BNp{;W59P5L-F>JyBl6W3{SbRl%y+AuBZXtloo8$cC82l5~E=e6z-m z#E6KZQhbp)9>I@wRl}06;%nbR^>%CEOH5W5xGv%Bv0%gLSAJ+|@*r^(QqFEbrjn zUEsracpq$L{h3kL8nk?~q2@J@d797JB(3q!RNUo}<(xOT#_6&}3q|Xk@y)NfWsT{z z&OS9Zv6{1hsMg&V5lA92lbKS+FKD6Dg9G(_b9k4FTsiv=-hu=LgF^wM3m^q7GCA^n zs2Z9NElx|uJP24?Mmg%<%?iGe12VItyQ-)Fy@ zmCCzjaX3%k=^N?_h0Rk9fx=i%;uc(i$siQcDGw{y+QA_hSo85+$+F_L>J)G&6|M&K z6b8SK{;x`8#AH-fX1&6ognLhQT{kf;$&6p~t$y|HXv!*h)QV@v^WvrLF*lf4g;hXY zNtMm)=)8beBe*&m{w4LC z_EY^w39CP0$NaS+Q2Lu;9Xu(ZE`~e1rh)++ciDr+bVDon9!)!+LLzSY ziP-SBQNY}Nbo+r%L8YXs#=8^9t7+udi_Il>+Y_cu6OjL<17a}exE-j>Oan*(pb2&_ z9Uz(l$w{XHxO26q(@TBYV)NzQNcX{u&E$kVq2%BXS%ekvtq^vnxif)N_C51y!X9_j zPIQ^zh>j&1&bVeZyN9{-9(2opEiw<^!?3)x$h>e58b_}@^UXc>kcv%<{xbkM)Hk|M z`+@$zBh$$pm^?G#UimkBRsky&vsTFpw@xEJ$m^CENjUc394 z>-k1~>m(0<=nhA#w(g+vj^mbEtrn~x2FSy&mSJy3i~HdkbKZUS9Pfx6^Z0%AeOM1u zd_P+5ljef^F|@ADHLLDN@oHLQ9>3onQ#|q=P+py-;FoQ4n4;Z!eb14@|{_qzpTj z@5L0faW0pBNJ7VR%ta5PKwb_CA4EBwztE%~v`3U3tk3pe{nC<-;5ZW)KCd^&|Cu3F z$nl?nJymb!=>NCt&7wcsw|W=Vo7|1GUGFznZA2lwt=>Gak@sjwFKo0|^!o%Dv>qsO z_yPC1w1;z$kNSV?(dOF!u}>NCs!YELfS!FLbxOna%j)|vEQ?K#Cq`B>}g zc=lzjnb}NxJ?hMgX1HK(o!Q;Ycsx^UhCE`waMXpG8uaNH@R(zMe1u4nv8H^JJF~W+AGZ)f3wdUb6+j57{HU@9YVBthZt#Lh%99chR3h`QMY9=F)+d6cSutTEp_YMb-ACohS5un%{zJTaEehF_`^hHD<))_Jp$gJIeY6QzW~Y zR?8rF)tD8JlSpbk?>i-<+&EoOM*d-*d>puz*OHCD;qpu?NR7@Opr>FhE-}t|{g;o=ZOre?j1Qzd{8gtbX_MpD6P@{*MuJ8Ed zX8zZS9Y5f5$uo~UfgL^eRg=5ft}VG^Pu8NBRU&JNWE-39%ShbjdD0%&ONX2E0n=pY zcdVxMIKdkoMTYh?7d~nCiIFMemKLokq&EdAFr>FaE!j|Fx$|0h?`Pf8qS+!ih|rueZL9Nfpfm zTn$<2s4h<7rnU-ik$|DEzGfOHbYiS~&?>8Ze5l+>zR+c8-BVN8A8568X+kH;l!`%w zB%x*{lI(g;W)9uAGqvkp(p#{T#;2qT+@BMknLfYz%(T^VU0UyaEl(%)ogca_iYLrv zPuaz>d$*xcqN;LjD&Lms&g@htNp@1G&QIq4S?NAPohJI^Y4w+jTk zMf-(T9J{0@C4@9|aMeyY+bXuDG~`08JfJcg{o&h4nZtg>Tbl1IB?zIc&|FwoGPGR% z3y=t<)4cSPHdMuw>xrU{*Yx^3sU+Nt6g1nu(#q_j`Yt2`C=7YsEH_s8RmZbjd*r5P zuH-XSB_&14KK1Mq-P1j}j75P~GfRKeC5u_(r}6Z%XDkS~7g6@&j&ZK$y~jeusvd9t z@pn?Dx?>S|F0F$h7V)x*VAgzK*Fsu&m%RDWbb>JpQmGYETH9$Eor9|r(SuE_(T3gz zplKOQ@-i#2+HF|8<^!e(N^r_ko%o5k_VSEf`N_P1C+TTvO5rh%xhGv|X6vJ#K)twJ z+Ap&KS|15vK_n^JHcKbNH$*g)(>y$xaI;`wjT7OSb}h%*lw*xR;be1a+po5y`p^lT z9Gq{}IBnjyQ=7`SkfEl=2_mYMf!<$T%e`-nlW$&q+O|(2i%znX4J)#BN<+^%!6>g- z7kP`331V*KTXBeLn{%jQil&Uus>{pi-` zQhR!;Q7WT>Vbr0D7ga4vK8&+K_{{~UQp|m!nk1`=89x?_)MMeX$f`{$BSLezx#(HD zc;1otZ zFuo)68qAIm=Q|j)j>Rd0D!f>roy=F}t@4~rWKYDkiQ2Tk8G1k(Eof>aX&uKHMnrs8 zYp6+Upp0qL?Yw8(eJn(nCR@_@=Wncn-79-3Ot73MGBJG_J!pP`#A0oG54Jav*B$g< zQhkx*<^TLZp1XyVU0`K8eDjKU8K{kF!#xfdtvgnxFo#OSRIl-NN|nmght!dkD!*~1 zifL;hiEWQeAD&+o$kq{#-|5uA1cKFMAMLg{ncs992R2b}0EZ5l;Bwh$4HL0d_dh(; z9q$RbT$p+WcvW{^JX?2ed(BvuT1^2YO% zzNUg?8xJ;8aY561VaOG6hX(Gud}O!J`0sSpWYE(uSDB;>XE17yHz7pq^FS**!VqOl_W2?Q29*Mf;L9i)&40mtz9 zYsuH&OwPNwh`3VQ;mV4dj1#O@@Y;o$a!BH>K|51ndTdz$M5EP_M(2=!XKFt58s>=I z-)^=04N3H%{EWc0!H*5Mq3y=L_2SR zl%d~%dun!#)+JvOn$XVy#+ElDUUw+ zJW$vno*g+QJwjF!$cm3o_X0t^mVmIprRh_KFVVh*QLa)e6<-}3MW-|m`;nwu0#$JK z0d@&iaWh{6!P&gbv_EI}J@!a$FGv+d5Ja6vl4gS8ZLq+%o%7+T6{chxUV{R23O~Jc zW|T5$Ng;xW#6{f9>-KJ{tzvs> z7lcwoRKTH%?dD(G?2)nUsY^glK^2;O0$QvlG@Gs$Ff3M_VFv}8oa1=bB|up3Gs9s419x1 zlc_w3$ugITQdD(20WT;}RWs91aKcu8ga8;fZ~cr^gxx(sj#3d0CL$O(Cc^yv1-n=5 zPR*J?3H)hBN=VUSgg5Y;q>dfnVEUv^x{>DWsX8+qCP>9&-H;*gQ`y`A!~g`95w?N` zI7vr?9bm9Sr>9FW3noHq6M-}o`gOWwWC8#ho#7SB+~?}uu7PO1A#W@x-BZ~WKavzi zIu|iQXDX#8=<^eHH=5+3I}!~{V?uC37des8*39P6WVe@Lc5;g8_w`zn!=c{HknEu$ zEg={(%pQqO9drsd;6Z+(&u;fy38mz0-9edv6Q!vZ=9S6-Z) zM2CFLX>VZhzA4;WfjDQ;032Gl%TBFkrU*nqfF`}2mWgW2idrzYNK?z|Y@lVG^BI_! zD=am25M8{{`4i7Nv2q^wuKmcKpSRKOl>X=G0dJwP`%Z#36c8fA=Ul?bC2J-?7Zc!AXY>Cs zR!N3YHUQ>ezt|?ov?{OxA!qG0mN5R8{WbiIlA)7bF+sJ9sa6x?6vSAB5xta^A}f)w zLnO#%J6EAn2Y12R5EuS8Vf>waT?@OB*6p2ZZrEY>i>;?Gom3(VM)q?_7B?vmWnGeE zfO_&QpH&q}q>#D>u0L?K-`(7^MTvV&{Js2=xZBC&o>j!cNx-HP@m}ZNwe>{=)d>Hnx*}R{jw5Wj^|xj_BhYerY5nW!Mw`0;-d|pYBF+OpW zIro}J9+YFmR!Z#BGDqFgwM*6@_~{@RR9tAl7uvN?{SKA%cOoELwk>_~DF<^TwA*nL z4~JUzjom_ktC(NQ%H+f?{d4%W1bU}2kOSy(=rOk?k*VkR8o;g(i!V*jQ~@q!W3Cb; zdsfR)q7G%Gx%x~H7U0+~fY9vlhi(IQpBpsh57#)4j=&ZhvBed^;*6!G|6iNzbKK8I z;!(g%JpzDJT>xTgIJ*|v3BWY|KmY$H00)B|05A|TDDpt^zW^W@Mj-+5I^U=ZuBMCF z*&<_62IAuC#mU@QH+M9Wc?cg_nfjoMRhMLhlFcQ%Qq3jLrQB!IdIDJ6DBPt1tZm9^ zmG!4@0{F4?P5G;-=JF%HIl@9e6%I^iQ*ok3gz2-ov>%Ac6MN*t2|T=A&**^|o6OHP z_G{-?{{dF-#*ywuV!nn6^xV@Sv!`Ta?W^kD)8WO=6zD%6-r|9`XpCiL$cZRzNe$W^ zTIVB*eFPE(6@pA_AYV~4kw=7#IKkyy(+DcX?Zn|eo&8~`Xh(0)Lfd}ZW&!V}Vx zj6pVq0o=$YdqB7-RCi+Ma+Jnbjcg;kmnV_P91HM2P0+9===98PWQRwdqQrG+2zq4q z_G7Xpg(lhKcKd-7#GYF`OtVv6%L)oh~pM9s=9D5I@#N(ko zDbLg1w6d{lm4A*L4OpM7Hk;R8vwNKuJ|71$uxshU%K;hpQy|;fZ6#vPVIj#F`vC|&phg~ z53}xsO1`?#Ox?p8*Nkh;iao5uT-V1uu*bfn+bAj>%_v40af!6c9Mk;``&w`0O0(<@ zmfVJ2Y4*NBs8_|6#``9}J+CxF^jmzTnWkU=mF8ysemBqDtKYVHX8W7=H19j}Oux5? zdE)M@q6tN z$9;M$dmX8mWO5n2EDO;HQ-e8&U7EuPJS}SU`mhePou0YMH15TD-{mH=aW99&_;1QC z*J(9YEBjiqlWr)w`f-6t(+t^NbKbE>diO0bW8R_F_ZOH;-eIxftp)#SHPo`+-JJc7 zS^5sUg?8{twTbjqF~QC z*}BQx^{#zVPMq=+P5HaFZ9aL|4taiMj(U&GgjW-K=_0#jp))$#;A|cKCd@{85!g~| z5fg!Slt;BzB$3hNn+F(LHu)=^mf*RH0&+5F`_`11qP@)>Nqc6&7On82 z!`x`TO|lpB@*7RRls(4tCv#!SKH;QzSJr))(XtS=9eHd7Y6PdJLa@TGcJOus3f;?N zr~iv@G|#3u%A~=(mx7)~+-SZ_5%3VY(M(9Qq&kD*GD2XUg?=!iVYuqw=H@hMTfZ`Y zN!#apzqr91PBZh~yTP27vAbXK<_+v(gm04bsEpxAO_so8SV|zINC?Qlfrvx|wS%%E zo>4rXs8Qva)slVRr=`((p7$=ULjNIaeXIRV&)i^Mp}l@j98rgeQFUnlyUI1+;L`Yc z8!4mh<*I8wX&n;C0!8(YZMxIhjf{STS&;G>!>ZaO%wxfOV%bh6EVr8>$Fmpa+ zQYTI0hxR$gF2@CRTV4)SE=4dxriKB@1udzm!=sHtH^qUl-Cm4%KO zhSA()&i=^mKTz5)X6udWN=% zu+<;U!ygge`|0(j^&=KT`_r88BszQDT)NLbr&|G!)S4B~2H@Mp=GlEDu2Fhx&6%;h zOB!dNeasp6s>nwv*Ux*rV|MRRlczY{{yAvEvKZ}mW-Bp;cn`?b`0y}5S3 zeOk`tpU}E_ByAsK-ra8x^j>zo@qTQdmouGerkM*qwommmncF@l2gB*+j~}z|zZA#u z>*x)+p)6K9M^n@JmbXp%V|tsXlU5i$SRYRB>p5vWAoJh^3CcW3Rm_!wN|1|F;090NC#C^^Q zID`?;r9{Yi<`6(exe}JjbNKZz4anwM*X?1xlg*~@h{uY-+_Duu$P3Z)b^K1DVpR%< zm5sGmK`(05A0o>k{SZe%XUgcL2Vt`a;51r_6mbJ}LOSwMW!5@z)Wt|geKH;7rZ1wN zY`c84oZhLoOK8|1F{gzQ@BR|=#wW@G~az{ zSNv?tdF=;&FV!v%DyUX!p`g-~FQc4G{*go~Ntq3S#`LnFxL`D+rSPvz`De)Tiw?V0 z<=#hCPyS%`en$Mn=hw9#_&dsx2&U#oGvsshl5wTxuFvi6LoSa~MHK5(7-5k}GX0zn z&|HxQx(}eS`@5~)cjgD?{m;=2-l{d-+DM7@^_$t48DU$Z=>c`hxuYnxp*XwlZg2T=H1l_+ICd&x#y>zvs+XKsYKDAa4;gYhk}b-6 z^-LVgZ$;8kYmw8Cq8t*3bL-%=J{^({^>)gjq&A~5T|{zJ3qOMB*-`-x50{}(qcN{>ME z(|sEm&~oGWoW|?Svl(tK<381dPzJIgLFZC$ew0v4>Qnha?3nz@p3}WZQrcYd_-1U`xeC&I+b?GQF)%O+e&gI>s^hMvx?6lCo_k)L%5uf)n3}T#2gy$Hl zy~5Xnp>+^9j-HZL`xH{7^B+}C+2(L>KBamd46v(|b^?^u|KU^eGAEvRPG(AY(Ev_W zTjlKKrFQW=vgPoBkw5dYs=m${JML^1a8_>e`bFJ z&#EKGeJo^-V~~PXTEJZAEZ$-^eT^1(>lX9I*U-zPznQ{=Y*Bp#O;mf1@EE(nu@`+x z=P^^&DUUnIgk^qU&O2yN8&ko%7Z^klhXz$gGm1t%RSY_1SD%z6`)S#5p4_N1zd2;S%sj@ubF#rJms zK8COs_gh`?BU95>m3z8l{%GjLs#f&%1sQpOHHE}Lp2%%KFqpR9eE+Z;a_KTM(MVX4 zhxHC874l8gMVHzeb+~<+yGr_#kxM0d;oRQd8tN#_agzB~h=>V*sZ=rwwtANge{Nr8 z_yxA8u5u3z)$`JhXNSz6581P@hdkfHO~&*#W#2N5`&OC>-y)rgE6uIn+Cz%JX5AcT znY-(4!*=ty-p$!!zWml6QF8p?Y=SOL1&d|Rz2?O4?BDk5%47U;t^P=3dNwCN#+k9Q zCRHqduzB`7g8zOzru~4<@@Qn$$B&Z8rcRe?XBM>|&`!$-XOXuv-*1gB#wEw~`cXbB zO)C3_qfEv31fK0XU|#s%{#Eh8rvWdTory0WFem*$ez*+>4j$*`<@R97j;C_>tsbAH%pL@O2B)F40 zMZ7^-&JeJc4OM2y4kjDz$a{rjd1KGe-6uJD9hGZ@gb+_8k@*Y?m*;s{7oX)%9_JM8 zIyWsjhY|-)8=ZfcSAVpBo%?kUzqPA}8FQH6x7TKxYY*EMRj0mm_&{@2y|bB1+aE;y zS|J%2()~1dsS!%d6 zouLLcAlwOzPPslnG~HTypb?$QuZp_Z-vFS@o!{_zCEv)oEs^J?+{(3A28Vj)uDw0j zJD~a$t)+k`0lxP6;H21NT}a}?Xly`xReb#hqN7xhGZtDewDdv1os`lqb?&D6z({fM zeJ$7|I*Mm%^uCeJDR`LetxnkY!SHMP6ORah>zlJeb05r~_ZenZW?a=a()8EkPgvu1 z)|;iC;LuYRc9eTv<-(LC?CQbhSCd8ys5l)LEb}5ls)ECoYOijW^h1=4hCzN^YSf zgQa9}t*SK&f=GwQdOSOT=-@C0{pSb|y&FbrJ9y`-CMN*D_I*|+n#h(D=RCRDeC7?7 zdCoNjzToe?dk>jKzTo5DCq6c(`Ga?P4?bbu_Xqop$|sqS3ve9m4>JCEEkZjaDvV|p zGRQ&3N@h=h6?2jA5A3xz;hf;WZhi5~0f;*xgJ?uoer)FC1p6J^IrP)%)NFU+WG4?c zquWV~P8QOc>&#zrf&-3fp#cppF=B;JoA+{p#}pj%@!`)QJ~J zwKYZg!JefncpGFMTFo#i^3bXS-OVZa!QRLAc_KUYc%6f<4-~S!7{&JEy;*UqqF({z z>82(>X!rS)+n>=76?u;$eaN4yBBEH+oF5Dxl~RvzDu*HW1?JWK;OX5yT_bOLc8C4f z05*7px$5e!-A&a$y7^6{An5n*dEcB_5FB#!98~ALL?UwuzwVy<$l**-faXDWK;9u`GD++`Ca^?c! zX7fm4u($Vzedd+IVA=6D-Wa*NJuSBof|(fkC#ut&5zQa6cBWqGsJ)j&1wS;T5tB5g{(I)2s_8&}f$#;6Dx7M63 z(r5L=Mq>_YE)J*8O3rXnyTbzY&a{!qeabQw3f0<`q326|0cclKQ!M_V{8po1Zkb%7FV*u{!@bbrFXN3Stoce zNh-Cl?W_*9FhQ_vHB?Dit)w0gE%uD8MIBw^#8p0QQo%S|s~{S&41pzz+5%hGum0c7 zJz&NV-<-+N(T}#p&+OMes=Uymq!6(ZCXvSA_#EaSjdsXR3_|yyr`ZWPx^1 z#IZ7PI8jF2KN@b#k-)tL7XpezYA5v#n|g=yD2>iL?QRE(%1j}uVCROSjPmYW{L0C)t+YI0CSS=YLBaZ+c&kg}V_IOWF7#w=^Gx@wd+Gck_BSzep0ePl^;bLgFv zFYHZPF?!APbJIbrW9N|{ve+DcIc3G)a6HwM((BPz^1fKvw7Z+t`eMG-`g*R_dQ_g( zI*hA<>mIHI*Rx#DaBbllKslyTHCmO;L0P$knQ=cM{^D4 zs^ao-AWbiT=*e}C&uaaI3r)WDSbqESYzS9{$BMa-4W*K5puC!EGA}lA9is3B9hLo( z-%GfD!F3x~g6nRsySTP-rMQw@c~t&Rz-k@OwT|m9t_QgO$aO#0eO&i)-NQAStGa89 zM!QuBW-SFl29X;e&7eimMm(T*(#TdXQ^2&te*1mg8E_ z=en?C2!@q#Na#ZAz@vdi=LFbKA?zXt#<>!a);U$#!B}QBAyOhs(h+7*L3JV(=a(JK zt$rvTe!>RGb#9U%QGHPaM+L{q)G|xz9$B1Z%3|+d5KHaqMs^@#pa!F~Y5H`bF<1T% zK~8e;-*gz%=I}cyg`h~C(EF=OVOpq2cvuRjFs;=^WNJffkV}wLTSL2;y8%AA7e`&;oBbmXN>Ycb+Q8bb2M-SyjnL>l}X~;ud$9yfsgCPxxPA2ejl;7x<)tC^C0DW;LrU;>R z-Pt)GQDp0k%-ca&YsX?^7oJC~hV;NdLwaziA^pj0mqEdt2=IyuJJU10BHP^F=C`oY z-!vsHd8u<~o z!_Rw!M#-vacuLd&4O97)v}A!Af4Minj@SK+OcGiU8-A4G$;Ih|upJ{p7V4p^9uU?#~N}V z*sZytRcX|3yW8-s`+A4@i1C)es3Xjk^vfN;;fs@-!>^@eJPQ+J!Gy+FnA+KoT|{x> zCYTYLrjPa0qFs}-nb~qNMA(c-S2o1Wp(QbA2GPRN@G?g`A!hJWQdWGTT#9lT?puklS@7OOj$h zVa0G!v6PTb+ELHtOnI~k9zg>-H+^Og>kesrQfj75;2XS}hnZE18xu3in-Rj-T$;5T z9|Sc=GNTi5y6NLfza`=HSdRUKs^1|hP#jL2?Jb!!0IG&H1n;usB|s;dqfTLS2c-C6 zFRN@Kc$Bg!T}oa0BD5$4C4q~U)XS_k`5{%es|>7ve0{Qhyfoy+$xASsg^t%li&LJ^ zs^pe&_a(pP{@IRigqm!5)S2+>d}C*>FSQDv9qUW0zLRzOB9l0^sq+JHlKp_0-|>OK z-U!%!x~Y$T{?TC*O9e_}_jG;~?fht=`;q4qU-~-EW_FPsPk08DX5B;ifj6A`(4Edh z>^6B5yab>URVZa{1$7lwGijM{B3Eq~i2{9qXWx~`cT|~~WUc$SPhV^A?1q0kW=Jc7KQ+Pbqxh8cTu9H?jN>@L`zE2wYE`JAobrA|SRM}fuWix%W+#x; zcEIIH*#@q`?1?8uQU2=p_r*QSI96y`vUqM*oXN(R-AtWTsHK%uKDUWoDV8|(%nUur z5xTg#wM6bL6?foR$WkjZoBtb2FQAt#l$XfzH?4bYDoKpk9Sk(nJ|)N zYuPj@Ui^Tg{tZ(PNjhKzK&IZ3x_uL3`XEYWJkZPh2rHskM&7Bb;Rt)2UV&{)PCL^B zUZEaO);cj!Y-zv7bbg?5zbIG#OH|F<2&&@I^zB7f**Lhqo|oYk z8;b{O@Nig@t+kTrnUl+`r;r|H<0&($j0s22kLtjJz7apwvx#(abO?{<_*MIQ!RlP* z?x~9b-NNK=ovh!jj2CUb=Tn4dxWX0GyI4_AMk8oNT;B1k_YIzkC2`H-q*%=2YnCMQ zu`P9wPfjmu?{$IpkA675YbJ-?ob4x^pIJvwE3bhN!9Y%&Lkw9m-4rHzo-p4$%!0BL zP&e0cN};x}4Th+m2;aq0==9XF0Wv3gq*BD05n0sX0x9$nu!er*jrG*3?z|>b5|P`3HB(sJg5jIhS_||zp;z?*Fwfjf*l=(J?vm9 zAgi?Cb|Syw{X<`e`+`5-i&Y8CIvxGpyePSx@{%`O$7Q+07f_H?L9v)DcX>J0q%rwF zr0q?u-uG6;E6Ao*v9uMqFMY`SN~$gNa%v%kMb45f%C{_SNTJSSxfj*s+g6#6?h0QT zPui-Sfg-PiX z(J&04WsOq_+d8I);tel$myymUeo_%wTH6-?lvB|Emv;B00gaj1+CO7mvZ8n_R4@to zBE{v;ptTobUOoOUV3kSaYcd~4<%*1++`loc%2u)#ItqY8sDqoQy_=eXCs%XK&GQ5i zObpkrofxfOScwEzy*CtFW2Qjz68&mxEagiTbR4JhW>hseLZ)bVqf=>~`9-jItf(B0 z#CNTw*0M-|ImrD!?sdv|W&F;CQ>^-h6S+9%ap5H3R~vnMSVKC!UB!KgoVw=qls8(J zq`cGZ_{Q|>A*SF7mnHK`>XUh%_4~Z+*?Bb8-`U0UXs9M##B?i8u1um2#hkVzg;R-C z6a2lH{c09E%6hQvA$<111e_^?C7)mmV-r!!Ar`p)-G{ksB;A!;>jY)u&$Bn)jMX5k)A45z|S1Fl8FJH zWMX6&Qq$yHOEE_h&*|hBe;~f^O*j~*goDVE%!kbN9E-HmaL3W~YAgV2v|hw_8ln-6 z*jRva<1^5EiGyzqL?JoI&ea8|M`GAA&y)xAVlYAP-@k7!tgq6{#`Fp$QZ4M0@B|Jz zgOO)igJE5@Ow95T!bLRKG~55F0SW9z<0Yl2#FD~35H-HQ*1SJa&L2l=XsT7C2~nOj zK1u2RvIPastm-$NB{dB(SGCfDW^MVB^+y1>{=Wd| z9w(=H3wM{qsIEREEq?aU$o`JM1zV3n%&9_HBd}#LY3fymV~vhRe|>_{4scv%+nWbH zAbDu9)C%{vaMv*}rk*=LkxKBv{am{?YM=cOHv9}_e*Twi)5Qq-9yV#_pw#U7rDd42H;X= z%agZhX)>1$goD{4^AAqPoZEuA4n}T;ku){mN#{9aqlqkp#n#>(uv#}rCXmS7>r15W z%Op~DMR8o4HRL#;tPOxuGGoMA9trXt!{4Wz*#8D)2{8m#^%s(e^Px27|!w!Mu zwd9netf!=gR|Yu#FpyQAQXH5WAS^wGuEbEVkoe+S6f+hPFJOpf__lSomRXS(9Szg| zZT+1?mvqgv|MGk=&{*ck_qPC4Xv=OXY@`Sxc`yWBn5hGU#|(MsZ5Gw6&p+~nC#S7Q zJ=lcpCKo543|PzZ7?CXj3Ay#ox__B_2L>x*7j$h*f4Kc!GJdJU6PQG-t%P6MC-EsJ zGhh_Y$JV9FgG89X5Ve^I8D2IRK9CFc@>x-NwY`0aMkl}s&t=kyWVFRjwyr#co>S_& zY2-99`Jcr{m}_*oV?~z7N(;j;I}Z_)Bsn7zDbh@|_&7{s#6dm#brxw0nfdy#SGdKU ztv*PlHyk?k^mQ(K@v29-^YTi9!UDPk6xa{i)q+KPXp?jVP(xl?$7rQgQrIt*Tv+iHF!MQ%%lT=Jn&4%!TwP2j7hE(nJ*woJB5)hhEhp7n^k=Xxi2i z=dEILYE{RR;>Ufe*KJ`r_{dm=jB}F)WJmH1u zK-nCFp0IUUQMk5oEpok+VAUoIV^dE)H z)yI4-t5VX*pp0&^Q9dVZPGvRfq69CL;<4su{LSnpW-EjhUG3yl@8SI(CzcmUcmycF zHF*}Q19pi5r3Ct*~$nU(6TEHC-y zKEa#y^q4FLTZZ&^{dDr_i6*}NS^I%4U}qfIb`2~58x~oZ=2-B;HJU5@e^arwy=N8V z8c4Vfq{6{3WFD%%!|@KP%{&x{EprNo)@J5HY&}C9w~P8JB8yMmFiz{`ldkOj>oL(#C>R- zfAn^%X=XF$V=isR*&!Z7dz@QMZ`l~Rphdnm6sQP%2;y50k3uq~dR8xE>)|qI1}@Tv zqRX7iiL|P$%9a_2=R!maZ!Q#<*!Tsrif{b{pcQcmpliuF(F|8`l?`U2Sd8qLqU0Jp zR_Ms$MV@jDnHmn~-LiIHD8l)`a-W3gHM+Aq8={=P1s3K;Ny^XSH^x(Ddv^`l>FJ9@ zE7Ez@FJ@R|O5+}bK`W{tj-f>c0~V1k4tQa>UfeM?>?+-Tkj2vUeEwe$t%;?pxk>P1 z9>4$OcP_te{Lbe0%wN`|bNbe#tGHKs2CF2V%qx$iYj7NS%U2|$ff{C9JnawMDJ!3K%BYRxiPX{YkVFd=fRXyDa>A z$(EFCEvBYZsHqucYF3HMUyvzh#iDTkHDac-GXI4A!>}~%T6Q^cJ0PUN_gItt@T%N&1%sC^1N5{4{Wrf@XT-y3tnF6H+|HolB z!{zasizW0*P;@;?2G+F9gfivOKXne?%N?My3W;LW6!B zdCXOz#&dWt0T<2m&u6`vsUSc@OrK8Av*L`jyG|X^J1|nXJ{-$(6P7OaiaX6kKT*$e z@QQp5e%s1y*{}6X!YhImQiXw}SDwm2LjwR(tUic>Ay}bL_U% ztD$A7wjpHjL0uBS!cI>jjehD>j9wMNf&3vhvEX_WWRHEz=36izMM#MpfwWAb6n>t1 zn0M-t02mf9&UNgWd!Bqs`d{la&;ARwf$xSXO+9rWkQ`41D@zJq;c|WQ^jzi7Z$Eq> zre4e7t_;8Blt4Kl6q-u%2drTj)R4<{sAzNu%EbVeCZ<@;(H#P#dy!RmO2_@JP_$O# z|5C+HBm_=RI_3#qhu}zzbTzm*Ij$kZBcxu;^$BTA-$E%63zJ(WfA}%3qh7sM*o7iW zT(yu2gdr4X4kfA=JGF60mDWONa!d(>Q=0G|v}he|X;RA|^T4e1>3JmCSfEbP*{sOj zK-;5M?@K}Pu15>+sCw+OPOu^ZETY$S!^5{)RD$jE?Ow-WbWBNX?!8{LexRj7FRys0>@Wm6JE4o@`k>T%^ zxepZ77zlTF??H8ktNZ#kWdJOt(loV6S` zN%;V0Ccd@k_-q<`X?m_x4{8vXz4*)QPM6LJ$YA*Vz{5!A_(JTaj-aK&deCA^(N;~5 z6NBZkcM6%&cmaxFT(2E!FDyN+F)a%^C$xHBn~ZQqT(du4GaWJ;CB21?F8)b}o|+N) zbgrCA;!ck#upY z7EKI!6@D0Cr=|vn>s)!|OA4Ur$JPoL3(xQDhSlX4XU zj!fFuh11`O3AO3{S2(DInLx)b;m>&|TG!IgI93Lv0$@pFJ|%oJnFqgTI9&yup>&50 zYsR%~Vv$B?vUCZ!a|!70P1f>$qbzrUQv8gGlIb1V<_Pk_kR}^zfyou<9gXgolL9Zj zbravi^P(_eEsV+4ogbQ(_OKYX3L)DYPxCJTK$BV4O6Q#NMc!~?noME^`B8|7Szm-e z%$d3{spW=+QzRO7?u002b=rpT5k{sf(;ngvcIEdL|0kW9&`8O1Xs*3x#a@%@xFNcF&xWeHZTAyFmIKDNb=YffQFo^p@-&^^?IE}R zSk?l3^_wggzmOHtd@Mw%_&dJAG-t{PD<7dgicg98hQQWrdZSZgD+3#xQT#t1cJLdf z>(~2ftQ!cusf*1IOh8oi)9XCijUWcbwc z@E@u1`Bf-6VZ||`Ds%*IabGB>L?PdKqIGFGxunbHp|dc@GnK?0+>zoW++e! znvx71M*TSvk{wH94_vp2FlG$-Dt#Xn?Er8UQxHNH z<61a%5ytoW2Vg%wcwOj0@y(#TM`Ck|FcpVe6rr-o$I z%MnpGydkMziTd#kNg4RLQOKhz>(k2RyrxiqH9tC#8=@1<=8})P_Kr1souZ@{QB5{p z%j+r1oYb94I?L*6LPB-{zessf!mEnIn+PpFlaVP;I9bif_>&LF- zkn&>Yp8RM%TqEZdr<1a-W`Bo-3E7DYr4&ga>LL~yVohHYQfQe3DY-Fs!`JMqEw6W- z%|6yu@>^Ep@7k6;qA^)TmXsP_BytJGi#l|0 z7++aW>COe++(DYfAa&}~idB(LE!R~+2eadQ?|D=SMWu59;X2Houiwc={)$=p!Pn#` zvt3>g`MmoC21Mlw05w-j>Gd!!jea482NS(6o-&NEBKbpZIi>x;Elk5OkvUlr;bv;x zI|&O#eLDuBDX}3Sjsu8%yZ{!!X)#*wMV|6lNl11pDXl#*4YzG%YJGf-DLWq56=Fd#0X;N*O)5J~5s!qL%J{$7w3s+wC_XTT2U7;#Rh zD<)_~VuDUaoFIIMC||jqWW0?I6SW&nq|WV1Ue&7AuF*dEF-@*$=1LTy{E)V;P0L&% zCwF+2Ymen<+yTOhkTq>gR%zoCTthSFozro$c#)ZsPzia?aC9n!owth`#rkB<*a2(`!YxvEZtY5(RmMlr%ZN+!>RU$+-3(7q=E+lPniSvNi<>;L96+E_X!e8_roBksxuHg<|Mo0-C_l>4%t|dUxY{GMF7rh!S3f$X3Pbd2ly?BpOKdHN@k3&8s~PHIEP5AA-$lvQ8UoZiJhm$+g?AoMr;o|CxksU z$@0^?#p#tio5+2X`v&eK+%MpMDfeT!PjJ78`_bJ0llwaEM{(cAeVqF+_h)upoc=xc zT5!qvJuz7^9%40@X)!1Yboq$KylW<4CR{zdni$LurF{VyDZuQJ7gZd>U$w!Bohb*DSVn*|4wzx` zphPcaVS&PWJ_9{?SOjhI8tK0?QnO1iS21Jf@;i^KnrlAS_srJ&Jpc+FEO|LQTvi0W z<>7!D2zuU#{;nw=3MepYWisGd?L2dn<>lz&JI`ZrenYqZPGb1;W;9m(`hQ-nRVgPmr(LGr#$|e zGXOPwV9RSx@vz#|F+9s3T$?(Y=S82aNL94F7IOxHnf(1LQbhx6Q@&9vQty#JpMc@i zJSrUsr?2Yp6O_aKCqCDouu2x1TUgg^Lf>yfXNYH0s&|&d4_3%QBOl85K_2$Pk`8g0 z!@Y-Rh{e4ETDpoWHP&_{?4MVocz*a@pqJaLmzTg6l8MZ`6uo8WSu;qnGq6m-S{HB8 zP+pv=&9w?U8;)_GoX#P&kwoUhy8Z;9u1xM{QCfcK{P@ab8}Bp%O|TqddNO*yE1YO_ zUZ*G8vDL=Vt4HhkU`I2#J!Qop5u&-)9Rs8IGl6=E86OSWu`_P64y=cqG^%T@97c76 z6XBVc$ty~Lk7L{{^b)#~IuW=oz6UjvJ{0o*`MK7zDuraAFNoit!~079&x`ugo_Hd2 z|0D3!3s@~E-@Pv<)J=f}M0Cv1X45;C&?aESQUl=x8@ARaE8rBKcrEc;iBt#xn!;J2 z)?4{5sr436IN!5CO$DeWUNBE`tQqJ_=snCA0m1H=GJhz$Us~xp2aV-C9f0Z*0tl;{ zc2N~>?(pm8E1I)Yw-x)5Zd-@tEhQ|3^5v&uP2Q)`T|1wB{+0HCp`z03U7>BMS!}1x z|0?UP$v%6|U8MB!OuDX&6n`?ScsH}+Fbt_AsS^kw!ehg0lL{a84X=02a$k6b%LnVQ zyejZTefgyfj_eK(X+cLeK=2mg5+>}oGhOqf(TS(x5JX|Qm5rl1-B3PPcX&dpk}c!z z!+KkmdXMiq%f<@wvd&sLYJJI7D%@?)m;aBkHvyBPy5hd8yJuqH3_GI(f`tguZc&NR(HMfnr3Dm3&`|*qiS}X%GA>{c zQI!6E|Elgt@_g_6ygm+H%dNYfd-ii~uG&wgO81%JJ(JPxJwDWk8uN-_AG0%waDxET zT?Cz1;|DeUbR;M#iW!}H+Z5Lvt4>@34=7(IDc(H(m-R0)rlrR6LJym)b!noyQ%&Ku zJRg%TuKh5zC%o>37xFzWD7vN&AhMbcyGFbChay)m(!nR6QaJ!wva7U=1rx>l$gC)Q z^E1FTa3W)$uOT+;F+TkJLxm5+|NCLxVIS6|1Cd{6W3IljJX4ck$n{f+O4lkfhNq%S z#%87(*o-SfAEd8~VvGT%eu6>0jt;tdetBETPOs@{sMW)T%)(pgHR}&G-$?^fY=@v|WxZG)F|d-1u`Fekhvq_-K2l)?Hk1v|*{!Cpj&1CzS{eR$|f?*|Hj@ zIRUnAk;N~lr$_BHX9Dj>B#GMMnVcOWz{E(dC-6;UWG3P+-rPeig-lP$bjF&{*keoD z1sX)?Ar$JtGe6TQ16@GdC^{2bxxiV^yOEks-Uqo~%kT6N9G%OkrT&v2sMs8d>aqd~ zwp6bn1K?0>Mp((#@mD99N*ruyJkjn+rmO-$5}#CX{qy1aHxy2C zoc1-dB0%#R@Z@7P;JZx?%uIE{7-!Uyc#v5<1+4fA84$HQa8IiKdC=B$2Wxt!OK@st zYAiH8%jOp{(R1!o=I?t>8GQ~!<{0y~qzC+_W2n_h(t@W7$U2ux&dOGw00SOi@;bxciqr}jSHs~bj9PMv}-JVtcSZULjKRAqU@KZ(epT|53nGxxs9(%|qW|Y1*6bXbi?j)9rG45!N0~@AuNGh9M3Z0ez7~ zprCd2vCl<}s<(OCRS(Lkl#yr|^=<&~4)>HOQ-Bib%*Vm|Q|kxQP%Qvg2CveeXH2yO)Oi@_H9GfD zHE@8$bgB9$jIMY7)X{K7wla2sjJqm#{-#6C^CIpyvGnN&l*?p%HVzaQ?5szs*Q}Qc zH&m+vTq*U8J*_RN+0s->KrM(bGRCjf0V?@MN`CM}l!A29ohd*3d+*zpp6t_skN<9; zHw^dVCs-=Mi988Sh?9TFF;{4BrLP{xa@l* zbhKaTYxXRm2Z7`~duLx9$k={H^uCmO{t7fjaoB!ltxpIEQ(H4QBc)hwvRROdweC&z zd=7?wZQDUA8wC&X?&Jz%Ll5^}UR2XDH6&3CUX}7&@l*&SV-Xvo3~?wJBzhXm-TU-| z>>}6weumQ{TIc-CkcC6e`K^b7<-s0_)I0KEA40_i8C>BM+DXRnc{^RVeM4%R1+I6y z2;D_!^BN8vXr;%o-Z1jSNPu6>HAXmr4g~2G@7(>Xcdv8~pD;oqytbFGql#&AH|od7|~8W(?riOhkmD zAw-QuyfkAnHp_iiOWB8=D(8;BVY*z8OQJG$=VJIJYG>R|uTe`pz-Xr)!xU=Nn$GX7 z8J>D_z|52kBVu4516MrQwLVi)gBpW!Ta3wR`AqtZ2tHSDWIS_w#Mi#mnC&iGB$3Ub z@{nEjZxNOzh-}Xmmwh(oa>P_3HMCCB`}{F)%31-f>Y>2jh+OTa=#}7q+uq!U+w)5y z9HNoK&XdoA<&cv-2(Tj&W|EbLMy5Krq#8AQa^*wlxVHWt7^ESnNzO)H(rHgFw!0__ zIc8d1OIsKrHTpa_#n=NL2_MeHPD8$raTY5YFl}&gOxoDfM$f=$+&h2pe%`GNZb?g5t`3q3 zJFWHgLDbYi@eBq4HG;&nQW_ZXid0d&EHf#tz@_oo8&KCZ8EXN~tg6JUB_Qr{tgijEsKm;Zg*CwSRE7VtwyJfo{PYvpvo<2`A)l< z=b&b#GJ9tL=X=z>%fTfIwRxOhA)~fdyUb$9zsl-*9@iDM?EeZNQ_PCLR+$hkO6PnW zIuQMh8~bKhcVl`1nOHBT))xU6a9Q*AcuY$XdK57&LetuQ0nl#Hco-Ul^A>eho+bq2 zt+}2H=>!mZg@DR=7vx|TfOlfHjx{d{t=_2zB^FXuXf^v8uBdj7;~zRTTONML-QV-R z&9iU7icA{?JzQ`Z9Rq-cBed6%_^X?uo{JlP)AHZ6e>lzTijz#!>1)#)F$TBpHh<@y z@TT+$7$97$5a5K`x@rQ64Sito38A@FF99z9Wy@m`ezoPz#g?Z9$jA1xk_E8)9Dz=g zED#0s+FtgpU8yQYSQ4 zAfXrqW+ir^N_7NCFeXjle?^KgNZ=&E)$g(Af&bC zrS4DSy1+8LiM`$hAa?I6t_!s4IRHtRTO_0iSdsp{?xnZ0i8j1V_S^=w| zUEa-(-o1lAcIWQcR{mMdpXk+r^PyE2TtK=Eqy_|eL8x}8ND-3YPCpG9c!rB+4Ka|1 zQV%+7Y(BUb|k{d5@?N>u};=D?y)e%6O|Z>%QZvdcX|M40_sL~KI}~?oW4=r zv9;Z;3v5q+c7Tf*@zwDUNYS`l#3H^H%!D+ml7U=cg(x5RhET)z@J0Ieg6yX->}os^ zc^~Yp$iD_?-lLgAhBO6W`w;p-qi&acP&=^%s^cg+q8I@A30&9c(!E$l0ReItm>331 zYoULQOPz)WAQf?@z=|m6yDvO0^A)TmR6i>lSoN(rm-q(erQ8E0M0}aJtdcAV;4>!O6N5_xQvEiK?n@Q1H2(Y&Ra@*DxVk_PMjxY12}0UbaENHBZ-9~261XliY{jDRm8k%s zhQ4S598E+)l!$^@!>kXE`zE)&s1_MI;;Bz{5YNi!o9Vvf(UrG~$jjlxRYIJYst;h8 zF;ThPqTpp*&|~T+fbG5T?#XU=_XIlFkzFGg5K>d@q>!4_A~Ctji2o>LDJYAhFpenm z`Gwg{5KTp=X}W`Xxkw^P1zJRq5?uYv%y9&4YBVk7E(L%|QRCw*6_&63M}WMs-3NFM z$mhK>`@Lu)DiF!z^8J8?J;N!spxSI1k&d#;nRvv`#hSudI>C9)MPs~W*{KgfHoLw? zOBj3*fC5$!@Ff`nXg=FI+YH6(qKprBW*ymcy>cy6N{olg^#b0M%$^DLY|BDxf!oqW z5jcV7YUBg|$sPsOcO7u(P=WxTaYwd;1RB^jA1z7+5TuO?e$`eX5bx1%bFt+GuC{+< zW@h~{UW9o$bJsQk#30grH-H0vSqLqjFG!x97Q!0%K4Ih+S1gWLb-Vxs{ogpMC13x_ zQJn=4EMi(ZMq*psMPr`YF8DfEy}k>Z75##A3xW=fO6W@VbaBF|EikWa#BFS9ZD<^M zG8SrH@t!L88V-a)bDA{)$w-*iFwAN{R~(3Bej>;B5TDk~i#9A9jHlkEIM4`>;?TQz z5S4MACRA_35U!QhFJNG$B7{v*b%f;=zuDS;tQ}aW?i3F3q%uj@`VJ^beSXr13}~t( zvb0fY9Hqn2G}?*f1{f@y^|$wC?|mg34>Le!S?E&{qyiSv_;Z;VBaz5DFv?}LS(-?+ z%j`voexeVfCfeO#YA3PnF?htW*{ESx8P=2_%ui-YVltf9rCCLfeY`ifxFUQ`=7}%~ z`=}^)Y^gh&0XQ#A$Uc7}@xUg^tuE(z%7_! z3G5%PHCx4oFwM#-urkE)Pv8V*!@ue)jx?f>J2OnRRhDc1JF}x5G8x5-g(11>a?dJW zf~%tBi_?LnCnUAOi)q)j{YLM-tl7HP62XT#|9(i0&7#qWoN+Yyru)(OY=-TttyoPq z5g%bPL*v8}fyDWEppS#mIzn|6;C+TMCc6MauL`#C%?GTvEa37TM$eg+2Z(k??L2UN z>-x;NG=|GJP^L#dOe;&tYZHny1kq+!M%JXSA0FG}+!aHqF2%-_|WX$J-O}LwPoZ-R5l6|!uNl} zk>{{*1*!9Uvag&;T?&dm8$GU!2t9x{SLC1_36d_m`NGT?{H7P}?#s(lL->&J%1lYv z3$N_OCY0-D|5^g1kkg8569d>t=`(?Z9>`Qhc);~QN3Ua&`aos1I4dBea<*cXvt_BV zDI;`mrZuroQnP-KPPZUj1_s0sWosl!en8x($CLgM3DFO@De^dmgTA7S^{blK z|H&TLMB`GKHT7MaE*O~JX+F#Z7yZ@f^d@D6SEVv*&uoqlFLuP?xqR)g3vSF344YPR z2AM?zsVynrq1-AzYrhtxD#j%wZvoa+ozy`hQW&m4H@mTymt{dC@zMEjkIgmzgN`fy z4V77SV+o1z402xOj|AK6w-4RZrc*`!=r2{d(?0rIWS-~hOZ=gb<`7)hI)6~mo^aen1FqY@GAqhoF?EW@eoV* z!I`2DTj>C@gYu8 zbxyKtBArT#4~%5{aDNrUE#>_aLX>#~2Y* zli2WXrWl}eWoTV`DCH+iM%BS+MOH?vlV9EVwDjqdKpNl0Sm+%+mbpxjyO@kbkQik_ zqjaDwJdKUd$rs`2P7O5aRGh9RfZ)zKwmwr^iT_H7a}F+G_L%lk%C!dj>>>nA9_!+! zrGN>Bi!yR|&4ta(ouA{M2jW1VfCb8~iYZw_MJ;QXs;8j0mZbDX4OQ=ail8zyJVTfy zeIA_=VS9(TCT$zBjw0!8fVv(Gpg-zo4M6WSfD*nDWS+`EN+=`6N1{z4ZNV7*2{@C2 z1KM<1TJDuedQ-6eDly1P1GHFSz`Mt@@?I7jDIrCOU}bV`n(zfGgt2xb(-R-cPuph@ z)@dXLDxW68Dl$N#oxSG<(~L<2p}2dF`zlw|x!54F*ahkH_rw8hLp7&z%WpTlY;?3F z9nImXNY>J7|IkuLDwH+HCerKawQ%KXAo4&9srC}-HC!*^{kCqPGU_a|=EqXocqvKn zKtB#_<;5#WF{>8LX-#Td-%V-7ZzA4u|3*rkI8aJw_;?Z(8CExxW8IO_$MCx*b>OH? z>8DdPz;~^wLuEHIuM3QNN9~kR-g3Y5$~XCARM?A#5lR133D;_<$^BqHXoAjB;Sx)% zRDHzmm=;GdjY6u|LdX!q0}zGbVV7O;<+_?89E8bP49#uIzx zybrqa{X&YA*?$Z&5`#c@8km&wDx2pIq*C;He(TBj#w>Lnq0-OeoTSPPlOIwVYBW6b84A@5RO|k-(>X6VrpH^Sx{X$}}(o2+`>M zK3E}ROrS3#)V*N9ux^Ka%4RfULbhu7-Imfg0B!k3wS*e2zmmWFvgvSWu7R`nQ*Y2{ z0iJk93JliuhJ2%LBl(IO{vRrKJDRWfFNKQF_;oPjs8_OskxV==;ag;f#3H9PfEWxe za>^~}+|by;=JI4BeIabMQW&~XJ-iGUkMDvir^D`Z0uGCe4L+#*sciBivFQHCvJx7b zf!N}N%b^RPtg^BziAoZ}{STH?c+<7-1j(7Tvm7F~_;Q_z#%0o<)0TVhJR0bB&b+P<7;RJl) zL_0*S%AOF}NSO3Ak-Ch5Y&a6W=wxHF-m-j`Cc1BJ7zzIvnj}}k`d(VC8yofht+4MqmWQq8KGa1p}VyxUKw#KII=z!Z9j)=IojhnC@ruUuw@G-f=L43n8ieM$cA{L*86 zjBp~`_1@fBqEO6GB=hgDa@DUCZB0i*uYb|Snws%fK8U;7`*dzhwkz=G&tGq2cBh7> zr(WcY%h%R^$nKhue$Q{87B$bTzVA=20c&zGE$Q3@C%P8O0i0V1(2uyP|57WioSqBLn^NTz}w1DJYM%C1^eS1hymhtgZ^ zlG{;l{U+NcG$*65YlR8~8WS&&{B7;QS%an z(JM!Lkr}wu2w#Q=Kv)3p;p>dGN;* z>3zEnHM_)}aU<`gHTLg;tg@c@3Hg!n%d!)AAAJo(K$}*au%n+JRe_Xzjjq+*CTyNjI+dIg*;84 zd~oW5OP&2l@=csMaEI*r46@w#Rk>F8?V;u?>92T736hPWjcEaNAW8oytM(8Ks}yE8 zOL^A#_7S3v1f(Ca#u`VN<>A8~cr_NZ1J@rs)a-`kg&8wt8nJKT3qQhTGWF3dYY#R5 zc9(a+++R>bN;_4@Q6r~XDZ9yso@dD+QssdL4riiM zvL6`XMUKAv?2q1VkORQkdGDn^mlz|eLHjPKy9QQ^EP&QVwBK``iA<-Ekz#v`;)(QM zpTr-*3vT6P|_15h9&tWEbn1FeKAlJZ^=4W$5^_%4P2nVUk{%Ct5e!zYyT2qGsVdy)Dx7`&2G+4)6AX?IrPtW(OK4Way61Og z_Pa1FdMFu7m#{w9MPy)-KZ_Tl;evTmU_Pqtw7gDQy2cHFv~-O^hkFTxe_Amue5Y+? zu&p%M3fGeenU8x-N<-iOh2j~R_xk0UbF50a5u;IX;zE)ee4$JjRCWwY)|yI`BKK&# zxnx>V#Zt^1+Lx=o9Ej91_hFgagYadDx{gkXC)H73P2u(F&X}GjK{4T0(q{ooWl4GW zOvn!BTC*$DD;m=BNwE;#o>(=sM0J`~$J|^x@pAYr(`5G*UrUhDm%k ziP>3I^WlHqDePMLh*s6CQ*x7_8|~0JKG!X58V}fW?lQX+ML$fH+kd@_xC70sW^U2G z+;VNYwrnz2`w`!gdWSPzDzL-|<4ZH9_rGqGchaSleaYAYtVXgI|D<5CUrj(I;13^I zRy>Pst)t%gVd@J~&H7k0=u8?}UJ_ zwCuLOGuy^$fO`$%rJcA{;AHX@16JlMt@K#+gZ=OfmS1JCm0|rBK|vVpS$r!IB^<#N zpUL83A7{}7;@9D#Co)m+F}z^D>JX&|B6uh0cnWf-c=xUYR>#~xcez%GHj0qf)krBa z6x|}`s83d@5=!Sz0h5C=g;CV$FhXy{M}V(zCp@?vN`c@M$D=Ix)N@#$y$@{ zP=hc4QXg^S(y!0FXX)2x-RLPlR~*Py3(FXD=6o$UE{c+C$7r7wESE96O3K()ip$Yo zcwCt7&*xfbs4NKI1>pChlV^Vce9p1HQJ#;Hb3)&I#%~$F|I#nA*KppiKc*|nmzl2e zrJ%=*9hGZ73$*4cX+Q?MC?n;J%0V1ru7(Cenf)CFPodz@mOg+foc*MY2RKpIPcB)4 zj~TwXsW-r(a?74^+rpi)c>aB7Zo}uTy>HaWCcYEZVM)`Epqo}ylStwyT=OpG&|2kg zxj3|O8f{MX#bb#Fa59{RA%0JnP(ftaFvr>*YscGaB(1@?&z5DwzRdT624 zg!)jpZXa$2XY+xs6{y{ZwUvwi7|x>7mb_XY^X(4lrKw!YBt2GB-;HSi(oLbghwB|q z4*0S@GXGOT6NO=qxRJr=ni{ z#Ow)*zvT2njM}?RI;TBAO6X6@FRovKjL83GEnXYB~>7f z8)zwq9BfvCqFvM}{kbN1SbPICAI@sP;$kt7XNI^BP4({?FuOQ*FG+_wV7pM<%C6BQ zh9^45O*&NbW_mg^D4$bLzq$>s!|!q(0nuJMrDg8-wZ}XN#|XD5fU$T$U1}U&+)_m!yt^EK*gy6w3Y5P;vE9! z58__&6SG(w$@F2j2aQEBr`UqHGmZXHb=kk3aFCo*=vCvAwU;=>wQF{|zmcgaU+tST zxH0`Fw!DBnK?=2krE4RgplKe!tO@4Ea~iYA!7WOMoS&_P{cGmnPuTHK;4)BTjPn%n z!jh5-uI`&_zM2NaWk?K~O$9nxPirohsg5)tA7zcU95X~H59Ckc@?_9y`7saOXYZe4 z_KInVYQJFkBO&dhP*$vEv}f1B8O0OnZWa9X zAR(l&#_57PtrqVNf;+FK3*R`nKtQsU$WP(@T7wU))Xwo%z4JEyFuqW?OeuB11!jw* z(EbSAWZ2^l?kodxwME8%&Nl#p7E#A{4Fy@OyGN4$m5uq{-sqCg zQz#&~u2|2$;cqDP-1qx+S$(WcJ(%~UlXSh*>CNu|-ivWjCvL=*LJg+f%0EdDW*&;kwKD2G;5Dz|IEY-iK!*xq<2 zYO440L4wjb993McY=~QEYa3$Ky=}l!z@@0<9wIzNrJE3+6z%zMCQe`j6vSL$KL0re z2s!TkZz^FD{>%g@GhX00GUJ8Xff`A{7$ScS_VX6-w3=-n9TPKs24Va%iR#*lJ^<={ zzCbKkKc3NM%DU;22d%KV_hioD|H=P$hwQdebZ z;ih1H;E)9&J2F1I`02QuHgu$vS>6qdOCMW? z7;+Um+ZO|0y4yYO1zZ(jcqls!VJD8_2m8>ZFe(<{QNfZ*KA=$h!stZ=N*JZo{=&P; zL?r3sru{uK51*ZYPwnX5WVLa1MUfd!*d5@y^z@o( zDI+8d?3c3+Ca z4?~PH%25zZiDXm-+{sw{n$|ClVHh4kF!B6uJf@_=gshDOvkDEsu2o-vAXS0$uN5ij*i43s)SjFVyMgkk2M|Do0O*lY`5`iS#ou7+G;RCxTNnWgB|}v3Y0}2A2A= zPw$+o6}tmGBQ1xB-cxVWv0BzJN&pO~MBLPOvOqK4hjaBeJ>b#eui%zO18@a;x0@X{ zaqu$dM)?O;O2B1AV&@A&Zcp}T6&1d*A1@(%Tzuh~{@3V$Xo^1y7lTKUxEZ{pIE`5u zU4H%cF+8V2;A;T1Tvw@+4izIW>xGVK42@P_h^qBjDR(g-ew#?RM6RAJS$Ha z@m(X?Y8Ciuk3@&_ES!!JhUldd+2zt28y+?eph*^rUkfdgh6?Ikz5Ink&7MARhRc$z z8n7zJ`(~b!>1^;;AzYaWCx%wVf-h+#@b1Ld@XjU`3#p{Oo!JW zldeZ+;EQ`qevHbey$jTCG_e0M?J_oA2df>vYMC1_H}np8j@tWE z$g<9)TD(@G_ow<##T8-=e`E16jo+W@Ls@05P|}C%f}|Itd_&Z;Ek2!;cN{q%_|`zH zgJa^@EN+$MMF0_<$X4A_j}xl_YJ(D@a-SB6y~k`kt_2MT++;LYHZ9Np=@D4 z@&6z0*8nce5<-~z3*VJln|BTqYGxabqKvrVV#;-1;cjKlYV&afW|)r&h*t&_q1q`Z ze}|?BWFsS6aTs}&xJ8%J67CQJpo)w@CTb|~DUv;r`?6#p^T(v_CuGmy-X9EP$l=fZ z=_Ot+TtO74y1beBMldjt3Q@o#uegSGrlg; zXJ#ebTnxZbLGg~$n7YNh5Zxvp2m5?RMvlx!ZO09B@>1vTy!)W`zVx`7WhAJ9mRltH zAo^q_70=aoI>#y>4yJ4*{?H>kRqkmz@H}OvQbzd`=$yM;d#p`q4ovX~%u^J&hXT@- zT8z9Ro=88$z1L78I|)wfGCEjMD`E2@^tHzJrZC0@rnVuBOD0TDF{9JSi&)>X(1$y< zob%jKk9W~+6Xo2&GU!FrclLfnrpswWB1;hUb_JEFfZS^}WmEY0BHoWf?0yftP(%X} zDrtk6ttjLIY5&1!!&qP&~4E;SKwMv#onF-P#(HdUqJ^I$WP@=pdg+ zTA7+R(wVXpd~TFw38VK9Epb}I%t#~T?ti>mkTl_F;;f@8jZUS)H$bUlNQj{d-=M;6 zj{NIOZ+Fh=iqJ31}cI1Vnvc&IWh`oRk=;w&_+FWOe#voiGH~ zGemU-&x+wQH8#Bg`B1&AKt38Nxr}K%^$$>M0y?2{F8s9^B|_|ggfu5?#Rk-a76)h%ue{>6wQ#{PFcXS_`vC6@`KDsFj4$^+EWk(6Vp zq`U|rX6hRsG(pHnbi~CcF}RzaFb_HrPrf}WBtIXG7=q-hBSgki7kVB}QWsh<4jS1c zMy*k5gucj>%;BSalU;LWK6UqVEU$3NZ0znr!Q%B>ass?yD>j9P!|)8$i@rO&{NQ&% zc*Omj8Q;MEW{=00I4M{zkxZ#PUVPWE`5@=0f+pRxvIY!PShRoNTR|`PFg_ zvGDC+fO6{n6Jnn{6BLLqDZa&{hmLT81A`!kIwgEz7z`O^!ghMT*)P@)CB4iaviT_! z;w~t1!9~+xyEjC=^pC9~iR=N?6sIGkNm`5|6iJ0Mh%ual2r8~yT-=`SU0v>5D(Par z5dwX-N3Qu!R?b-t>33;F-Y~DiB8U&U<9UENNkvd(5yn3fM_7dB ztrOc@n@1w4R5$)0c^QZi-2Vq}mLEZ5TpCWKmr`F4a42LO;W#ckx4^9GSVb>8v>g3a z?R7{*6!b-)lF0?>MfTnXQZQWt6m;bEg}fGWm8{;DYfZ5DnX9ffnmgbLy&haB)C5D9 zJ>12k3+?K;kMf5<@4#~{md2*d83>Y?1g@Yc)SU&YbjA{B2_B9)Z@I>uNaim7lGcILJUkA?PcJbh<8?UIb@r2^-|xSV0R}XrQLj~oPDVE-4f9M-1*TewqUZvW zUoByTo^|TMw}f^eNzBfTZX!uBVTtr}JimgD6c}$hnZ?wBE4S^kCIWHE)w|I=M?zlR zU1E${0(L>T?geZ=S>7r;*$r<>q`QM|p1+kSqgyY?o|pV?|6rGY}bBp0yPc+iY2Xir(@Cuh{cfE>BaKY5^ z8u(1pI#PN(&`E0yh=qJGK9ui>vz70qWN;!GD}q`vWmU(sZXKIleaoSCzF^ga1_KE zYhXZtl_I4G)}#){3e94Foa1E%>CREKfjFj92CCQ*A-8b@VA6%5KLfF9F0X074La6)I9e`!ssnBDlp_WGy7&6lu92=Kn+|1}V!ng}m8N`PGkl%kq25 z>t6EGu{Y(KZ$@Y@Xb@%-Ip(WnxtKLyIFU^=%Z1pf*i_h)ZQYRY0KNj?{nRbjdfucNOO`jwI3jyaqb$Smq$pS6zgKQBi9bg21Z*5!lH zL6>U~)Sf7p4mu~~bf5%VJtGtpV~oodoU`SB?*&I|H~jkiaHs7rLC?MDw2`mt0cK4R zWn$6>#h9{lIl5Rvy^NBSEz6#3PpvQ1=}Ssal+gXJR{+DUzS2CtHhW8YN=-skyNp3^}$ zG7)(!=G2pV)~%chRe2XGxAMKDL7!w`*_BG^M8#xJ%KHd+K;eQScgj7zs-|D6&EJyS zL)=!$r!=(3${P9qzKS4w-5fA>;KV)dHouYJ@8{bP(w?}T3;zCihu>IogWqtCuW(*A zak!O{%}m#Y*^`+r3&bR7{v#eOg$^E@?_BB@uXCDub>skk8?aVmQzLXNd~SlVAq)URYE+O0yusHI?V?@^Y=^y?}2Es%rS%Sh|8nT_+~iTvM!( z@iD12jcQGI&0*8+<72_XG)?ztmAx>Fke^Sx#MIMab^fawSxd z%T-2m3p!HV0H&l}Upy8^WVqN3XO|-g4ZG)5_6T!$v~gBuCR{x(6q*yoyZBlYVp zIze@$HFK9|yTd2CF@vp>a5Yr8go?|II<)n5nO=l;Y0nP8rSMaj&@x7%GU9$D)M@{V zl{$)TR(RK&YY`e9JaD2clPu3OELkD@M2^G zAV~>VYnruoqbGQlocppE`2OeJIr(=pc-Qnl?@rIZi}P;R|GXQTfA{-rjD6VSzZ)E! ze|b9}cKDxn$K>DL$h#2l)Jb(#9X0arCi1Q^jChDE&PKMJ&H*=~n_aD-v>NZ?g`DW=6lS}w)nObTwr1y|$4*{?~IQ6^^t6_fO+7y+n2YvTS7w*`otd>EdaKIQX6%?IIOwW(S}y-lf= z{|Of|S@z9HBKsp8f{3p_7)xY7Im5#>$G}pE1yqA#o{!ISZ+=$s(d%=~pRvo$-oJX^ z38wF|a?SrjBpnsyw6*X=NplyrNQ%{K@?iIGbFEqnH zDm1frB0^P%f91+^J94{QGb0616Zwdwi70`8)lvv|Nu~j0{zDBG6Y^5PZ3Sv@i1O0O zXcmeAvp!G;jb6b_F|D&m!dECEI!0?0)qdbeSV5;TvWaYfcnt&!Uu144ole ztML9}A*e=N*9A>Vxu@f&E1?yC1IYzzA!H=+(R@D-5mebx(M8UH1m!ifP$E0QzWEum z(=jKV17*NjqL%7Q`P@fb$MDcw#k-iTmw({Ih#6%UH@am#$n`AiqQUlCG?L{yT>ryN23n}iq%l`dx zb71ja_}R_&3p}Z0#;Z++p!3w_89c{!mYe;~TSbXaz#4kjLA+oeJ)Dg}oi2;!9VA=K0n!S&Fk~O6~HvJ9o zI14dI&dxNp+u&l)QTF@Kn*FMZ_5cw;S_cDrCB@a1lkLjCn(Zq8&E_s+`r3C%WG{_P z$@H)X|JCe%w8eG^;I4BvrOSZaQfpM^16;hUpchau5ziXlr~P!evpwyv<~^-sr|!(| zEcKm{vFujQvE&_iq_&1f);N1;$g+n&XAY~ef}T#nqO|s=^bo$_l+38$OsD=(ZhHs& z(dW>&{!FR^O_=2EeaCwSvJSMb8l~vIlC$F97H(p~;^d0D3%#(`YB-Z6pZvxl8`AIN z4Lq}9vC|HJ{x<9>WlB5Vhhc=jAJN+kV#u2;A@-I}7ELpqn zh*=Z# z`I2)phV@{k2gNIHgHN^+?Znokh)U2J5lB|u!#=SQg4~{g2okg_J7B$+Dvil-c0rzW zRHbDkvLo<~fFpJp3X!4lKObtIiKAe^xFr1vizg&7il&r$!!3tql--}T0EzL@ZO+Bf z^v=6$IRG7NA_%fPU|oaLFW4ZMus>-uJKjiQirvAa*VuZ({Z&Z^7z;JFC%Gdn_1f|I zMv2PY9gKQq6Zx_#w*vpH&OmH`%IPfSJ#NQ7rain#nL7FE`9ibo-@eUxXgvN&>+tg--B=Z@JxVVF;Cmbf8IKnB))`N6sOtuk|YPkVtCl&Bt>{c(D!v+fISNA*E z+=G5-i2%Sr1Ei7L2x0X8p$iKLZ7n&C%^tPjlF0qIIjZDhZ zz;(*(@&|r}*ly#uMF@J+!1mON=0Q#E45GR+G092&A?@X>KJ9t#B@{b8g~FPqtDD2JcfeqAZRp1qf_$F`=|o2oYsm?Rw6D|8rIvzjHkGU zcLJ}Lhk+MX&~ky+t!K7rfAaNsXRXHd95YB%5SPeKLA6yEo$Y9=X=;RTda}I|#%xKi z*}nN*+0(9niK&umFMzJNF}T>dkRC0MZg3iJ-jE(&yUhvImSm(kFN!46*YGZk7oJ;Hc|(?4GK%HWtM(gORr_u@*BoH_hd6IeW@{P=k0v2r3g06chZMY0s84vRaGY`7)bSrq(Mnmv^c|OQ14c@@3Xi zMr~>v{&FaW0gnB%jE6ngGsQ`Ci~MSYC-JNUdZJzEj6UaYEq@LCEjrb2)M8WLbuOnJ zUF$dE{Dt{TUW2Xwd{j#OF1gxom=VgI#`RT{4f~Djc=r;&2Tniw%Rq#H?Klo&_TUv} zdvNc0E6h&*D?YMsSYcKlG3uCHv%$Q&x_;(ajKcGs?Zqq1qx?^Fw%=M|p5MBmGiAcm zf?Z(XM|QV=n715ZoZvS`U5U2=J=}H$J>fTgs{QAGnBDxz`Syl?nCG8UgOyp#NJVg| z^ZDQ4DjBKn{cwjKxA~y+kNF_LVEmZpU;fqaVT` zAUz=%C`@^U@sKlzI$BV#0mz{m&U9vLy_>OLTxp))t>!Fvx7tW%FxzsF;bEXqcxf?* zUX#+d-g#z;-R))bcwfDJ$;)PM|E#U{l$Xtm{CEG&-u|*#U47HmTyr_yR`oYC1o2P0 zo|Ca#uY%1RJl{TZ6+@0Mv2R#qUhZ%6oV{U{c}#4=5`_TQWsE(ad~Y?*;c%vwj+(!S z=YF1#$ls6QKEQoAe}6vrMcfa~-=D*MG516A_h)in!u_E9{b}5na$kn{9?CyEWyvA? z?thx+Ro__S%~z4}gdGX zwSD`m%=pw7?d7kUN0o2>4cmafXV0)debub45wBJ8IbLIR%N!-=krT(7Z|=+VZ>Y~0 zNz`@rk*}FUd}r7fy=IO%`*>PY%>t+Xp(e4N?fQq3RkCdRqw?&Rg({MLlUiHklR-@r zrVlppd~_Bzwq4MwubOJ_eGP{1pBNs&!pth&oh($I0L9 zQ(iak_W$^bz2bHAO8*7bc6HJ`)4$~f`^qGnZuJiPzNC3-s|L&ms_OPvh-0unPMV#L z8pWj^-9_!a(XSbekxV~Y>@Z*%J`BHc**YKhU#+vdykU0nZ|-QHs^14+urGgus^92n z&*rykMaNw8>(n6>uKI$k`$+rkH_U;jDiGiABY%r^Wm|tuDln1z#CHTSpUF{c%=VfWAZWrTg=n`S@%M+@w0 z-ZaneJu>WRZUpQ7AM(OJMGB4vXBZ92kSB#h&i>?0vu~$C6mH4OLA)#xaL2s@$55c_ zTV_?KJ`^atET(&f0^KNZ!CU6&-?XBDP^r7M!ensNJvB*0F~VML=TLhf|Gez5=bd@} z%P_C}xm>&N65cmI49nRE-!caTc5`v;Ikl+TOoo5mA@oAK>!I( zyi~s-oX=GWY2mjQC79AiRv58Irvdw*0?HqHz-KHkg8>o}-FqKd5y<-?Oe06smfh-7 zWes?-CzU5` zF!>1A)w*s2;^}b;#z0!Z6!k*5P*x-Y3NrfY>h|{jcg#Mg&nm76&8kux`#@GA$ZE@c zj1!FV6WmRcmuEqLW_(&(l`FPjFz7=+`-+XMbyg@)MPQwzSYq} zOvzBb5v&-fr6p{Rj7+P}l+fr%ocyp^Zs^a;;e_J~5C+(-HkrTmJ!Rj#$?Se)fVqf9 zJM#vc4%hp;ZKG?P(^ETbwQc`(lX*f(FT!VTd)?l>$vm!jD_dc|UGuKlsd57Y5}-vx z`g&}3lYQR1W>^2FPwiXYHM{vPx97cUw)6F}pM017aU$Me>ggb(-uVUpZW%ld+W&gj zY+wC7lh6SLl(5Ul_{@x=cGP5_*X`EtnJ4+@l-cLJXP)M}!>)hN?B~1Ae)&D~1m8A$ z?|WwZ6W6{?zC$E#xmwF>Y$f-~3*{ad$o;e2*OKDWvc_g6G$Q{|?k1iuvWGXpOV-(! zG?`u79mh~4Wr_thj3rL?+?+k9$(-!}(Py`QpTUIe0q>iq_jRXH#~d@<^8f=GD=(t^ zE39p4e?{BuSgyl>zCDa%*z#%Fx2 zhLReRoI3=LVnoJd=h^iiqU`vZwiUu+q!59E!itw?QFLsNgz0M|7$h+{BZ?3RLzAKy zCTn5KBiw_XgqcQyg<6B1w)~P?UIcd1zL(jTH2hq<*r{COk@WZ1xx{r@9yTdr{zitD zUPr?ZIQY_%=x;M#b?xK@Q(ncynPDk3D9m2eKK+v5fd1SU2>bG=l@G z4#aeed7=NFx9p3yn&&|L9^GoTJ7ob=Ah;+aq_I^#;n*+8S)eT)84z)Y~OL;9B%|);GHufE?vy{>@Dn*{&vkrX8X$iOkglM58tUJPJlh~ zpndj7=E=Sp_Oy@8ewAO~@~U7kQ55sIDb7s$jgQO|Zk~%dra0tv;U+4O8Tw+ARfsT& ztkxYOLTIC#nA|2LNIzvopj=7PAQL8&eIZ>G^1p_GjEP6IiR`)YZVS2U9qp&r5Wi8K*t^hPiDD>ZWx)dw4=IpSSBHeO+v=U(bh$9Qlj!oD)T=s=rB2~rKi!-Z?Ch*~=+H6EdT=L<#dyY~%0^My z2iV7?yK<$ThPm!`2r*^M?Z@=_sGoD&lgKKCRcT9~3}&(ieX77=Li!%5)V`-me~?T_ zJoi*#OB`A5T^axdIi2^aqn0Lp)UlQOn+~h@XY%;8);NLh+xTuA?+hz(F<}-SIP9Z9 z2?aLa{ZsCM^a1=e@)zeXG72`0zaW390q79U@f(Bqdm2{WMEpWb%S=I$_op>3=Z!=!F(Lgr_+rOx()jHdjibM0{$y^0>8?^NZ|Dx0_d< zaysmK5$^?fpMKz7ixsYAF7;f@+#s&M$}=$Qa!gtxk{Jlhjtv2>^pO|CVG`=0?*rWHi#k?P3Z-zXb1wpE*9xSV`W=iVOC%hGtd~_?c zX}>*rhuOQbea*qHn>Zj&n-#+`}PtCL1jsRJ{WYvS37IO|r zJahkj_HmyBl<&-(B?+6PtOYa+_(A-qL zGw01*^LnE`qj@@$b(Qt$ER2P~T-rP~aLtK1du-b5=|8T){zKY4DR3SS{*g9o+Ko6- z{-rEdGLaogh1VgFG^fqMf!vUs-92ND_CL|pzAIy%$vnQAF^}~ZpJsoPF|Q1K!TYgU z^RnVGeGbB+{5@-4Ts&r|xRuJ!&9Q+;d428Y=Gp#BSN`M0&sm0cCl2wH2R;zwTyiuU zp@-}nPp;}{hrTc?{6oI5PyNC?)&Hhp-}{AmJLBB@1;ZU`Pu^*cZFdqL%;NcgU%<+C z+MJoQckVQ6I`;V($qYCtyzrmN*yD*bJku_7U{w{b^~z&3Z0B1n&in1_cbTXAi{7%I z+hvaFnBa>M5!*SD>cwx!2WbRu0Q>EZUz(i)H=mHRPxz8?JoT_W0ErqMe)fes4?Ge^Yr4r?&aCL%}y;&g*FeRo&EOB zyUp%_nUsEDw|Pb2m*aEx54+6^13S66pxLbQfBvq0O|v;Bu#pG<@?KCsf zXP%_GhkpfQvd_NoD|4WK!*YA}S7x^(?ms@)%z-DnM|SWVcOH+R&EMuh_Uf<9YXUC? z47=ag=4FBLR5|Bsb6VhdF4}!#UJ~fa#jW3%Rh1q2z7J4TXLthSOnc!s=(*B!?bp6B zZ}-nS(LU~5^VCiyr{tQKfjq=HiNuY8u6IDS_T*q{{+4NI;^HsgnjHggbFuDQvuEIE zF24QN9N=%&#qPGpJT>qb53br{UgH0_xBc24bIi$q8=Pwv8kYiXf(2?0Q8{xh3L>e~ z>V~KuLM6+!q|e{7W^OquI(IMp<6kWM-MuI<_SV?n>@|;XJAew)>LmlxN1raUkN?g* zJ}{3DZvD>ecti&Z9M5cpDWDeQ26M(U_9Ne!)om(x*O!m=ydNK|`_3FtYy-vn?O(n_ zBbqtVuKqWb9pyLdvHv!YE^f~U`|WA}X20*V-}txLyZAS5>97B7b`AVvP|j|%kBNDn zi(|R)Us7YAzmN5u&x6PJF+p!~@eUWm?j3}-fO$AGKR(UD5Y|JCqlR%8?;CK6&>ZN# zC*_nAP<+s>s{VVk#(!Nmd(8J}8h_i(zUzDN;orL2&wXzm(`8ThgUzo(D>SULy8=;E zq*ydnblV5^Pv4teS`VUu?Ua!ZLZHFEu$@?zL*skG7CIB!6+dk-q zmUPaSiJ|3mf~QS)s#FN(tBeW3C(JoOqso;lUal@F&Ig_f;jdA>q=WhakwISj`CUP+{!74P)W+jMm zO)hr6B5Xq7UxsF&f>nBHzy{~(0XQ7+oL-i{0t=>*83?dqK>i>{4m!$8xj3uBSn3=H zy{iz-goO?U>xiamB4AF?$&A*;?e1FlJ@mcZedq zMG=F882TFFlwy&3r#owX3yqw^$2aji$ZZJgCB4=9&LS#ikmy;Gdth-$5-0S~CTDPR zlOvoN<_|P3HHYh*_POmTy`-v;AoL)eHL&^LP2I)Rt$GEfib05JDy{_3XAjIZTX7m? zG^bLi9Hoj6hX4WR-bfGhCtYD*aigzOtb$u51o9DNJe~v)!lr`3fchO`*_q&@ncy&?K>{a4?rNp& zP#{K_-!Q+!qXM;yac__)x0roE6Vy=_n(K_E$fWDs(^caZYuI!wwjWcb&nt!`NUVvtRQ}m0#JF47s%p&NaMq2Z3aw zhKp!G_eIgU?!8ev*ZG)l^{fM`g>}bi1rZe)XwW#S-ciFrYpK)axm>e+Lrg|1bW&l| z>%(#>E5kiO=^bwNS+N?%DE3Ia=wA;}5|uJ@f@rHF!02|8WP-fc-gR9KbR;0yY%25E zq4t5Qkx3FdT-&Ry(%B0xF1kL|{ylZcvhk8nxw}UApf^*Z^G7u2mbIXYY@k7o_>KiD zYfrBV3T;k)bytN2#$%Dvs(=bzdqg;q-b$DE3_toyBRo1&)^uLRh=VvHh@4SKX05V1 z8PzP-ZYz(bWi2U7ZU#+HaM5%NJb0wN5}H=gmSSGN%Gq7^n`3&7MK0Ei>HV|$Yc0_8j~!}WlBW+t zf3P3iZ+1E2AOgAN=qK}hf6Ws6&p(;n0v`{6Q2%6htf}S0kin$H6WM9d`cNE9 zne=v_pIPs37aueSw&@@G*wt|ihOP~T?d`g~s;hm?L9=aO{Ktpvdk#YTAE(O451Nzd zQqP~w-voXPj9UU(92U-u~&K=4;p(lCstGM6P?JJm10* zNYt9M(vXKRw%C{bg66Hi{kvbx-hs_jyX+V9l)z(LeD(|M$YL&XznFak_jA$jka=@} z{K@vihbVIu7oQw5dmeQOeON&oehV`_YquI?bn#-=HXg~W1DMn|pEWzR^$7c@oOyfK z<0uaeNNZ{|?-#-TTJ*1j@dz%caI-o1!XDKAQO>OQ&#qZ`P1W)K149-*QgxIbFMOw} zr~l{1h2K?mYh^JURdK_y5`k)bRRdcV9u1;`-}-`K#KWcOM#Y ze z()J(sN%{$xKOH;5p;Rt(wMZp=jSvduq-qu7Y@t-W^JK#&=Lwj?<@0mR&+_e^RH;?& z%PJ3tjh4W`pel7=1!57wDYfvAGVsx&JyzL~KFkU&?#0r}_ijSEqH=C%2oKTbgvvrw z26uqR5ol0oaMZrOw5n6=XP~AXP%|PSNFq=HWHy3D6-)n5EHUn4N2g{+MsYt5G3g1e z6EmgC%1Svf(qdXd=m`y`BMkAQFHiFfMmK$g`pGlB>&Ei|+~1imucH@@2I5KdvJ)@Q z$yZkX|M7L+fl(IQ-+y*Doq!w2LkT5Is8VD>ni^q2L`2k3q$q0eqT&@bDk@je4ZTPt z6d6#ERq=`)8+sLW1uHgGRK&KMbp;a(b}o9!`}sc4u0-zdy?;#d?97>&GiT16IdkUB z3>njzY~oK##XFK4qy&Ey@w{!25R2zFfX^jf?G2y?WzbgnALbS;4yM~rJPs@q7%o~B zo`k=3>vgPV<|Kcjr54YaOy+8e9w>4QheXJ{m}55!FN&h_s}8+#5{$g>3Hr8)P(N?` zqyX-->-{a9w-kP@;o3m93-)t?1+UG=G6D#uU?g!%94_=n;w`NA*b|xy?AUlqM$b-* z1NB(jv^}sW1Q8?RC+grJC|WRX?LtE01mRhfgp zcbGD!hOi1Khe*c)*Mqf>wh-_%&&z}pA(rC<5H-j~mXpiaS_nZ1$&ZP^i>dWJ8hCN9 zdT&!;K&opgR6X->&-%LQ7Wcgo#BwdI+mhE37l8%jwpU5~?FijpO>UlD93B>B)kwLX z$eeA6gXqA(q7O=gi#|Zsz09rFFRQ*`8Qh3ZQNsNobq@o+7j>(n#a&Vmb^d-a)mRnW z3PqZjVHjzG5hu+dtrhVWj-|tZO>tKfhr4bdQMe8?Pv+T!!^$^}DACoCkL-Gj4x;0# zvZ`dGvPgW`5rHnueXBEg&z-jy<9rxCVJze4} zz|lag)_HVxBXISRjz4~FhJS^*xRKpHyjn*Vkb|g0d3r%mkB2U2OFP{m=V5PEBN`H- zuY>dl48bKex;I6If5f(G=4Kx74GDS7-ZVml%%DOwsFB|l5gOJ_n`0+>Q4NbUPbg9H zDPuEN966k!4a0(byF-|}&Fg->>Jvxi5A%xv3!P0b!&&En$bKIO@CH^adbu>R=;d^M zk5gZo;W9PpM!1_g)ronG(y4UHfADb$;NiqupdGPuB>6nd+go4R>XgWphq&u54!V# zwrIoBPl=PMNgTI~Q8R=5Gf9&hdo~>qBFz_=&9y^ZyFr62%N3n-Q!P-Zw&ZYWwsl_o zHJGSCV$aXRD)kjDYDz)7)U0n}_sU(ua(ik-hS?9A*u_mmr(Gf)QPzvbdz3x2_d$5M zA}UlSvzX*`3TfUTRl;jxF;8G*O(k(+HFXnP$4A-4dAvPWS4p;k5p!@>LAz5`q}V^e zd;mA3{g$rJijsw1As#+WQebj*MqLFE??m>BTVORzFOW z7hD-<=~pDiSSP}xbTUNm7j`F7w2IB9xExe7bzftu9k>}3DiA%@5$B<@Mzl;GPlERb z7RDs&5AqO1VT9X3Di)e&{dU{%9T3uy*NDa!+3b>jCYkd*@A$6k?asK*>P=rN?m$5d z&BQE_5(04w(|-@~eYqq<4bow{A*qWdA0nU64-(|{L4$8faoGVWIiG)lh5w#E>ieT_ zvO^Tbu!Y6eV(eyHEB6|9mBcnW7G4?=Vb7MgauEuU;|4y!R286~&XbWhM){#gVm9AW zg2q(>E~_GVRJrrR0C64?RH zRPt(1hJR)9gAMNW2N^u?l*^WJ3wEH{N0kc@-qqmfBZG**(BK9ojB*ry!~Gm@h5_6y zz_LUacu>U9npPD=DO3YB7o8hDH(^C$&K9V&w`@$fqKg>nUOJ_)kJ}L&A?Pp&tPZ;K zkFX9^tVuSaz%2#4ldsC_4x-%-P+HKfQO|MUjl=a~c6%!7z`gXi3YR&_Vg}F|s#}0- z!?y~)nQz@et?xyA2UFkk`R@ z8R|*}(R#r^M6e**2X*dhL5uiHXe={U{93tEh7Hfhlf{?6O;J;GYf#9o!?yXfW|zIxF+beinh*M)Ud%go#XlkDvak)UR zkZpxCqJ)?G_WoI^P*o2YkkVqBCJ5~3eD6wj-O#6xBH`&4s?zRX>f^bKig z#ay4qG^vak?6PYYK@vC9zhZA8OOeMI8$u9oH42U-LW~(L7dg-of0&&IA?IU!S2 z+cjQv#j0=l^1U)+_+W2o<|1~6$_~wSrs(z>CQ&X)k@`I%v?%#1*XCJJJ|nm`S#HG= zZ9dihCH&9_igOR;ejs?&{M^LtiH*WE+oN`w2{pAOY6070?W zdn%hoXb)y!XnkfSH={j68aG*{NAmm3M@ITLG3luRJOc`8T@vEIrmM9QYN1HtJ^l}~kU+dI`wfi=i=00=mAK34 ztu5H(r;-dZOH`>P-Dyb~*h*A2)Us|!A@C~&c>*V4l=%LuW;nn|8tJuk@0Dxz-VDEb zSwHAjhGvMjEcANcoon{OtF@?u;rJV5ZYYja`9AG>(Xtq6n$PA@@pQstYDJ0ylI7E( zg7n@=Afh=jz=Sdn#HDs4uKohs30Tb+lC!4+{|9CF2$s2uKiprGmhV$E!eTC&WiW37 z>7}1Zsga&Dh|JfLS^Am!R#W~u3eNY(;>`0GwY0mP_;ir_+A6SygX9|WUE79(k-$pF z6oX2~lg_F)l{>WjotvR>21}J!YTjyTcPMZsTxGR?uX~>A1{zN*yLJ1C)Rd#<5+w_$ zN-amiXVYA%&s$Brh21*$AnyZ6JD6@VDa9m)<+A(=6IuU&qQJ(13i~}C6p)I zin6WB839}pM)(<*bh@?wz3?wSj0f_*8R1`)ob2}^`sX+R>A0E1DMR}Aj3a(m9PxYl z5x=J$@q6lDeuo#~>*7uBVHufS!2O5?JZ%qVBLc3Xt}!PgO-A6(BumX5F<3q?MdDxX zL)1nvR56x9Q0flS!~k5!lhD``)iiEb<|EGim=yfW_ddU#>v-rEHAr0R3kO761~n9z zjBpbv zZCX?Yv$@Hf$lPRpbguLCgqlCG@b|iNVXlS)wBbVY6tMs7_xh2wTl=`j{w55bTk{3Y z@L1^bya$W}AHq@!1_y3HQiV=YEik8nX?;Nojmwo6yny+LGXA_6ECuxc_x@&iWnvV z>=9ZVyy?7LCB1fxvs0~$e+mOqPR1m@WIF0vy#ho=J6j+xa#2treW?R?%YD9>kY@?Y zB1|@o<$Jr*7ZPb#N-P1_l79A6mge|(q4uM?**OwPz+7iLlKUq`&=g5<`PF>SZ_Q)6 zC{SIX)taO8l1beoCUHa*&HbcneO)su%BcW((lt&svxLk&ZD`+qZW#XF@6PoQvZ%0n zt#f`vOET#TU2$CP8TkZdjpbM*;+sm5XVSBU6(*@|wU&O-WOO1^MS_Y<3EC=~^)Gj- z-pxf5(x6*%Glw_3siRx?Q+eL~cYV01GSIZ<9e|X17<07>n}^sP7hu=iVpJ(3q5@mN z{eGQX+{UG_C>8k-8=;fuL9VdZR10zmA=ee;p2*~e+6*q6_29B%aYp2KueI|a7b026 zv}?I%X7lH~|EnfXMC8Du^Oec3VXAu7sE zRXe+TTiqTNX3dc%*bv7-+BGFiHQ%{1 zvMx@gtM(B{ik`rYh+ZCo#= z!5PL5*ni*Dd~5#*6+4%S5+Ow}K?`f>8rhq0&X(FNoK&v#grQvkct_cD+8uk~wAKs$a zBk{i;<*{fGrd%JC0O3I|v0?5{kT5XYRyK0Q^`m9;o-Y(9SJSZayGiQ5N zds?rI;HOk$DS)}qtv@&kH;qEwLcfW0)hz~V*{r@!_*x-mTj07PdJi0>>hcXxrUj&X zqLIYqN(VV1qIkiCNmC~vd|6Jz^gUXo8si)o?tnX^JwnWvi1I@m3I$HQB{b+CIMujWmR&6Sqt=*z0LE47W} zzP=oEZPE8dT$caEToZk(QDXl)XFAK2rH9Pr9qo3RDlZ?Y;ewIoQ!Yrm1zU z>uk`5#t8XFE6nko>>}^))nP+C%em#^2Wc{<%47%G_!CT(w131 zW@P==mfC}NvW;aiQech%$abV3y6uHjY{8ABu{}&dXZzTqi+Djrt9;?B+ew`46!qO| zb6#h=dAEltM&0U*d(*pLhe=#nARi4jRn>#w&?T+_z7r0PS-1|76H{!qj zf{T_k!MBO?r_#USJ~Y+}T+MP@^3H3_ubu4@U+?b^nbutpVcqx`(8WF#|H|22>|UAY zLLHnpyV!5EI(<2=l;Gmvu~`RTmL{iw&oHyLt9_~O)Xw!L`)K>jwN4wcwyfe0%J>Bf%!_ix@)8Wf3T8N9a z#Oc7r9y;psHhht$b^c~E0VJ9jj$_3EgFo3P^MmouCc~&=}sj%8QB~{N`q? zqAUpRJiM9(klZ2UFw*EM1VwaytSg)(Zd1h_*)M6v$Z0g@))r#YHbEGbyVM;M5^x=a zM0r__Y>c{WL6o=@O6kA)X&T>YSB%}o4c>c#das9ZK2zmV{Z!eTGvR(Pl(X|j> z74#CWbgaD+9Vu`TtzSyTZAe>GUX@%$sOEPD!$6+Odev(YNU8y-_jw~iYm=D)on5K= zdI}BE<#uw{&!OD#2p0Ak!ASfcofs!XcmO#2MG8V?Nm~qyX_?a01se1nfDv11_4x0O z^>vFN>rYVe1rX-)!bEG}7eOhhhM9ctYsdL~r)(~}W$X!lFYuw@+Tvt>8I}dKi4Ycr zM<}4BpZ!yi(Pb%CrFpog-8{T*kZVnliSjG_``EpxUHbM0XSo)tbk9WvDzR8@=CDFF zzZq~NLX=a@GA$H|2P0S-DyovDwJk|5>%3${YuD*VcJPay9LKM+VtZkUSo9U`3f{jX)URutn zNh%G2*syB$q(azdE7m8k($)*7**q*QKFY&efrh?xBB!mRyuU*O^ReGd>-RqHf$ohj zv7E3~%ZcdP^@J{&R_&)bT=T;Jt%O&&+2t3nRr?WfkMf_9S38;D1GYJrI8~5-456Cz zr+6oH5_$R)-cT9*{+jP;{Eq;00dY0_9>xDX{I&@TStraet$H!ji`~Rhd7C3X%{tHP z)$_K8PhMP_BAADb$oul$6$`eE#0$Kf?t@cC(7_G4Y6kfmK|gVy!+9abm^h1$n+#Wp z(_D^oST!6M+o_&Y0o#e%y6 zEJq=7nT*h^HYCD!2X4z`a&AWcX87WGE@#%tY*4-&|9G@hg;mwu`LN3tR9dvt3<+X7 zRXsv{=z>3|5VVq5Vi3P$Jn*JEC_f&>&qp|nrTkjNWE%fbP2BT)R_bitDG)D&J}eXP z&?eSxk<&PM6xy&?R|QF;Ir&nsR&ZW8^CNa-D;r_OhixruS*#L&V+&v2cN1hQsxT{%GpYK$ABx8R9~xb zBbOj@40_U>+uQCnTD{2-;xY(sOQ2IUr>gf=?qCVH2D0U2xIpm|Y&SN?zX&e-wa=&V zjF9H=v5D1OsZ?n`>uq=O+-x%Y*xh;Qn=X!0SqFp!&{L?%OD&3*Ql~}cDX~H{0S0>v z!4JEf5G-`y=mxX`o(vZ(W3v(N*D_7X_9ND63hc3gagJzo_JVn@SIc&IG~t0o)^w8QBLH)n7yH;Py48bEFgOlj)~v=ChHDJYaDNC=Fstr?-9iL)m74^hox!>?Ibc3Gi zctlUVa1$NH{(U>*sVmG%obgh&DtRxej~d^wn;yIFuidnOZhF4YF4${qq6r09^K^uw0~5;@Rd5sZ7d$xxnx?5nZGvxip;?M zQ@yEP5<)6$@r&#BIz2>ht_4ojsUUBK}Q@mB? ziZxxb-3eHAt4xXMJmH^7$RyL^bYiNo?}!gzh09=+=#?>Nq0z5XFefm-UrXXh>zCf+ ze6T@FyD}CuYI?#WjyNofIET|(mbFh_Ov@z-RbK`TMLZ2pjPNf>ekW@wB%zf)?v~G7 zLxF0M7oTgN4qniu=y4WukmDSYKiWB&qweLFqLdPu#gVg!>z zd`7e?Spvb*DoC1Wg1KLLL)=asr96tquvB!pP%6`j{Ie1zuwf?UWPsi;&udlSuV~y#n zu4P=R+aSBcqCuCU8q@o6m2@g0UB7joh?H7U{%g|GTvHapvJ3ZQu&69!&$Jm=*W8~% z&_|xWu%Ys#MoIraS#MM>n~qTplgWuY*cW)>0>~I*E=my8Wtcw+b{EqTFKN?;ZlVj}D&W~j=+4?u9zC(O(N_`LGJCgdAuS6ljSu@H8 z#^u0rj>uO;60KxA-T&b)Sr~-;)y>g4U8Vk#Y^(MjsQFJqe?o*1U|C$jI`+#jy8s!l zd9Bh{IU4-6#~Sg@q58>nyxB-tx{E8yws@>Qcd~{?MI84WH^0O@R*>O3el5TGUiT?$ zZNeJDJVJRY9QedzZT;9|RTJhBq92jQ^=3;S_gWRxII{d0SD5YcSm6=;Ik1`QhWP*U zRFL5Ds>lZ(>rI4VOMZX4(_`fjCKIMbkpWY@)4WTJvxoA@n$0X6WVg$zW)aw)W0b)7f_%I&$i{aC6D2^LGW%|jT@r4` zw-`tTs&H|%xcr|~qW+cRm98Yos9ckjf+hykNtKTD|9Cih1TCGa-HgYIlZ`eni%EHF znfl(qcZl?r{4eGIa{dqF|1$m$bYa4=)%?h*T+3=vGoA{cSCdu7jb&7j!S@K3%i00S z!? z`m)yA+J+u4{lTJ}EGh&E6)vHYm1}4iB4b>Fy|yK9b}V+tr$w7CP<;ECIW;_@S5wb!3+iS# zrHg92y0XR_t*j};+i*p&Loj3W+evC@S#onTP7;vGF&nAJ(I&J3A_)W-DEgvaVmJ*z}WcO|At_)M^Ry zXc9(|%adEloE-GmPQ`3XyLr{(cT+9i?zZ?Z4K8f@->o%+Pr@#>d2TYm9<4NWcJ1OE zYzXFu=JfNV3jXrh)Oh5^8SUzgh3q<@poSn+;sJVILtr__Wk%7Ubk`cV^hiA?7e6v} zxt1hSN6G?oli`MX$wp2PozS3=D=1`RXD9?RS~9AYQkpa#mv`zE6Ov*_QObMDOTHIV zhKU=-`q3@qn+PjY=6OzG?bsO31K`B$-|Jd~fUxvn{?KAa zzDH_R2AANg3#`!cR2#pOb%6`9O6oAD;tNt_Pu@yrGRvrO#$*nYG8WV^VR^ts9w z#YqhnDTvZ7_K$cgenHOfb^qqEI)|9xG}k4zqrh~J4saP-EYS<yP-XtFST>DNCrk6o zCv>@dL5-jPR%KNYCe^CsS=>=BAlSrJ^D5c6HSuBC$4(pV;Ph|}O zj+rH)G{Ik+^}Dq9#O7A+!yW4VD~X#%`vmhK=ZY@m+tK)eufGau1+!`DjPWX%R9?*6 z=8NIB-RWuuy+afbsDzEhjX6+W#1SVJVkE3ItxiGOHVU{Mwg#HAV2fW5O)cR~yhebC z?&t-?T}@i7fzbuqY2K_NMjbH1_u|W4iCYi7)15pP$?PfT_%v#{7c{)V$aaox?2$(A zE16>+KgAx<3O>RpuERJe$~!csvM6$B`3~b7VV~IgK1S(?bBdGdqx1+^%H2*(|E>x@ z{4*V6$mJ%OI|d+tzTelO(Lg+qOKdwZCgLo_CGR9r$gLCPcW}qgx&bWKg*fk`+>{ zg~W#%u>^0EB_wQKht)K3ZpakJlqJ}?u=B0O&UN{0T-fWNl8$6*0{yZFls7+|YTIoW zqrl8@CGF;zFN6d3H29~eVLt^=Jls#Oyx~f!sr1zh`a<;1O!4Rpcyutvni)=uaK;E# zeUR=`^_#Tf839*gzPGKr=F=&|c^oUM{uX7_ip3*Gp#romPU?QvatqJE822!UOE>i_ zPHqB`O#o`1c(5_EV{lnafTJQp1dF+!{cW{12 zaya!gyVWJrX&R@{lI}^hv*Pj&lYuOMP9#2xZ)P@5tYIi)Ea|kGyAeMJb(aI~a8`cx z%A~(sTIu-2Inqiia3_EPazd-|LD}W{pkTmVV&bRSU3?>`x6vrO6%N9kM%gFi_Mv*Y zi%m3_jN*_(M}Df->E_N+b~E2|zZ^18jk4QMS|BWGh6WnVfQ{T{G$H;xH{LNHrJI*S zyd;VwqVk9p)oicI`LneX;?qp;)9vo1AxLeNN1AQMOGsWr^6$vOb}D|+&gDJC_u%ZG z<4{9mILlFRA45h?@MiOwcA@W!HudI_)9qFTySZEXa1G<)LG$tH7$Qm^^ULTJT7s&>3N1--0CT!(iSIOsu>i5xG>K&7oK5vIDHez z*&1D`(mGL^WYAs2|61|^!x>pp5!vpmj%?2kMPB5F4zbma$!tbRptqzbo%Nl_9iKm& z52&$dX22b^nSO`bap~;g%2=W#V49q1ALF}$#tuHyZq<4Qb?794oQZUWNOo}L-ci>2 zWE1-B>ND;3tv>=l{on&ZA(ck*e39!+o5MT+sO?@lNS8YZz^ZgRYYae%Gwsnh1N4(x zke-5>)Bl`h*8bC#BOdJ@A-qoFu!y7cp! z7A|BvM8PboT~7Q!&`|Y4CB1Xi6I5PmfXa)!(V4Q@I3}BRQeD`AewO$gExE$*MGZ1j zHfJC78v68qZ#A4=q3M;EFH+}Is^GPpGVv6zilrU_%`RtO9z@hB4*x-Sr_73lv5#7l zU;WTv_kjLMDBVUy33hzVVYK1p2Kc>Qk*_EW_1Q*wwNgDeJHK=b+{H0_*XPn*JcOD3^1eOjrb!*3DQc%BaMdMin6lBzCSP zvrdzKQ-sxr3iEkI&DtD^>xhIbG?g(9Q3qTfBau*=Tt3Kns#%CtGDlIdrXMvbXN|j8 zlcU!S)M(<^*KFdnJewA(z***pv+QEu@lZ-qCG%G*9%y=xw~Gg#4@eF}SY#FPB zy?~UGH3!KgrAs0tgYq+?E>TranJ7Qrwg>G7*ovD6h(RuE-T+zNh%;J^>e|&3v3P!9K3lqWGxhy)uEf>!jrQc5B4pYZmWjZ5Pl|0#LA_IaZccm@o0%KW`#KnrYP_RUg zQ4Dew&`OC)@WY72>!vNm%Wfsc(0OGMU^Z}$oCn68Z(YqCp->}%k*#uKE)&VNq%zdk z!$eHdvMcr@k>ts5Zrj|fd01to387~QWU|ztlD5!w33Eod&LEFZoXG&246Mr5Q4f{P z8rd<}OIRhjx;{X;g2`ZyQVJfkb2t6w(tsET=3`tKfB=)jGe;L3Kgc=Zr1UgV`!XDz z`$jk;!b7?9ws4!*=4G)xD9`fDf1CfB^kl<{?S{z%%2SqT|4V&dHSpZz<1n$-U?Pe) z$S6e$L_umgI|+)<^y94=tg2B@Yg4~J1f0ccfM~sT}$7&OtfU zB@cW*Ijn5ylTOcoh^%zTzW8)1yO&DRilbECClN2RkXPfP%tX<}HB=Sh`?Xnn0zq%-84G z9Y&9UWixuO*qc$dL{qY}^4Ex$YN_eG8LFZrLZ*6+qQntm$x+~*!wtg~6eZTyRNoH| zrb=_}WV=;(O|lOORs{xPD(Hw7{4;h~2MGK!C_p~jDokfE&IUF=Wz%JsBTsCi3N%hs zS(+8gfD;Rd)si%rhefGt%L8jIHqiBp+E~lD3q9_M>qj)pIUX3D=_>X$CFyJ;StWlZ= z<{ha3*MZs$C?Q_TtAunB?m+Ia!D+n@IIWD{!A_WuWwbvYYHFdDTt1xhWdhVdU@d}l zzo2G$utO{#6P@BQkh1E*kSUL0jHWW8s!=(CxnVGlVG>`1=P;usHne6G6;6yTrIpKK zlb|Du--OUq(a-_VIE<0 z&3L{a0!utM1M^L4Cvx9a=W}l`h059!8?%AU0rZm<8uw7}?bpuT8-YL8Q_;DNYW z?>=+{TnTV*Hh}Y{;O;&Gt|f4r8o-HLRNh+P3J!$-8?#D)1+e^xg6{pbzGzy5g3^dB zJOXY#aKjqFr4hRkxYa0^Y5tZ^LuNP_N&LNKecdO>(87Yl4trCk$$>(K$1*gj7!x6T zlS}~YLM9F%r-x!S#<=SmbcxGAOghF(4492EWj80SA<3maKOJ-%c8-HEN<9=0i{xBE zT@)cvKn+Pgx&ffzCIdIC0bIIervP^r15>`rnj~a*k~)2%=l8llczpE04)#4?Wqa~< zkG1J}e2#g7Y2R}mYwGFVu(fL|`;Z*B${?ZgS&vn=-eaxe{|thkutvMC|6+6WX^%CK z?MC4HUHb(!gEh7 z{dW&#*Ove5mU^vKj{rlMMVN6rmq_!!^kI+XbWga!kk}P;EjvHUt-ZmB2=m_jH>5ez zy1|I3Jp%3;;QYN0!=<|?2HfQmtZ3pGt>Y3^n%VR&y_q&AsdSXvEDA3?mMFS@A69a0n&~n(+1#nFueR@ zT$AiLq-?`7Gc9&jyY_JlUF8&tLqbX#bzv}vNXtB8Xe>Dbt}Sp=8^EP$UwH&vGvF3A zfODi#7-@6u5rDY>KG*;-BPF(`9|2eY3(syhfJ4c0#M=c&!2JT;&kf+RQg9Q2+`c?3{@xGu-AGHU$n?gz$|y!T9N={8#MOfRA9f9M z*fo6Z2WIcGNMa-___x-1~NW`;GYs7=&eV-D@27yhS8qlYS=YG1VJgPWe{hD4)6XUde2~KaBNS`o8u!snf2M>q2+oUq=#YFe|Z!%@Hk+2l24uprq`vm9sXgz zOU@A@XJsUQH$q0U()}=7dM7T*YbR2s8)`P6ATTt}8;MM*g_Hr~j9?_*jIs>rt^%&O z!y3_c;?;dUR9^`9>Xs?hNs+Iyft{l>A53^!hszk)yZ&I^YakipE%y8vf+gy{N+pu$ zbehf?-N8ov^iFKhTWuUoo(44QK)z?lC#HPpKL_jDv}CK3a?$kvG}IQ=hY!|03Xm`r z0;K@STR?zi94Hn71r)Rim~o^DCKT9{RLcdEN7|jFDgJ;>i(trUOmO=BwD0%2e<7?E zu~(j1#<>I}yJq%V_q)${i#LkH|ARTU4*YKp-Lc)}P;sU#x#ChSFT^BMD9~9qM0qp} z^4zt=xU+VBHn_&Cu!g&~v}UroFZDy*sbv z&0s5V^OFMJ8hGQ;_HAd^Gzq-%^-s{2)!2{Z_P;j!oJKzmR!3p zv=ZaOrrTwl^;=_3zRWJ}GUJ`ebn@glm!#%N4c?FWG>4*uMNZ|M*sZsWsM+k_ZEn8I zp46VryxLa@QNlFB*Mw^JN0t$8A=H@6%el;SOTJaRi7=C>YW`o#|7!>w`KT=*`OYKl?|H-%%JMAp z&gJ%%o?6&$k)BDo1DIE6)HZ^L-xgsD-}e&M5dL7Rvx@%*`L8FoAL08q{`aMf zU-&v=ov;^}fAaqY!c&CD2%89XoXScN zY6#m1s|a5al7!)ezJv~hT*5?7ew{`rC7eJwo^V{4KLZH^2>l8D2tmRu!X$!@kimbo z@ALgELC4Kn6N(562r~&$kQ+$XEaUq*zWee0ck=wkF|&6GhA@k84{>V-m1uWQN_R)i93x%)Y=%$W>9YYhl^!*d^H?B&V54Gwjx_HoT3c7R#<) zHqVdFi7oZdjuo^WQj>40X4u!YOUaP9cHjet>UZcI=|IG2BWgV1Q&Vz{eN2;q+<271 zZ(fHhsZ1F zIkaZ0p9|1YWJRc)5I1^pLRaoa7SZ+SzPUrSs{9_*LL0`0P&) znV+t)`*}BhX1ZN#5BIM4%v^P?-M^?SQ@JLqjEYsx98sv#P32`Z@A%C&(!JAfG6%1< zi;AY8v|uA*{&P(d*99voolZx*_yr=qA@K}g_*ky&LsqPp2 zSNM0Vs$l+uK)Qf#CWkJ>RqBihpSXnc5kJ+9&vp_$$NVXv=p95?i&H9;k_o7kszqFkEXkk(t4?54KO~wlsnwpvRoa6d( z$V@AoK6sfrugtSyq4{Y9FikjUR2Y*l#d(RbjoD%LuVn@9K2mw6S^p1vu=kIA^Z7rR z<=!;^{s-3rY&UJM=if7Ci2gllF1+3@Zhqf4s28;OQV`Cm5W`PMtZHIzyWTEplH1gE zy=5gC|Mu@@+x2!y&&xqYvwes`vJ>Ay<<%R3YL!q6bJ8(=gWg(GaD&~t&)+@;3>BKr zh_AA$l8XRwz$sP)E`%`sf$5PN+B2J&^KM|@u|1x@DqeZIQibfgO$<|^nSPFKTzgBeQA6lgHwCq~tQCHU?WUOL}vMR+=P2LGoMIuge5gz)Z7 z*vTgFHW}|SzQ*@3!a!_gPp|V>9dE@nwbo;qvYYHe?;oF-i*B+@hQ6;c-he7EgFvY$ z1XYC4i~LSgNxz@tcaOj@-so~E|IR07$4z!;@5i5*A8)dcIpHD76XMf$LV15#&CfV# zst4{RUgqOf0d~n#b(T_&Ln+GLi=)mb^Xwtv-&$Bsmn{_#2|`W?+(gCcuAEO=PKsL) zOt8W*W>%3rl6Z$Z45UfxTlp)YaZ(glev~y|%(K^A zJI^jT@5294$s?&s#2>1p?0-};no7z_{!&RS{*_aQ_vHVW+veFt=T2l4YxKS`-)-da zYCK2_DW4j{2-nWUILU?v;~>USn*3OygM0?70@kB(Z}&Ng!WcUjjERoG_i)&!MLi2{pCm&g7C@Vzg~X#6AB6M z(e_nAc2R(rU=)mS5gx+fz#as#89m1?_BQ*(UL=ED2NRGNm8^3LC5MpoJ-eJcLULs|6D1$b~e0tkxe_j&wQ z4~jy{SFy*82{Zhz-(#*1+sE`dgZ#o%3uSGPuM245vvl7G;+l>t><)(KyCWTj87zV(jp;&0sj+edX*ln8(N|9WRJUZ8moMU%x+dI`+0~sy( zlDNnNtaT1@dFDTrTu;+sk13jM_b>Sa_gf|Z#1R~)F7Q3Q0X~iQn5$;nC7EB6&P#@~ z?Pgi4NdC{q=J`syf9{ubu(H2phRnCSG})eG?Z^talzQ`HbM1V)b1r&5*LmH}QxxCM zr{cFhHhBx|l6D&@FbCXRLF`_8k?y$f?l7;+x4W6(0=s2DuKdoUaWxpg;tQd&#?obK zV1$XdTC?BT36zDroJw4Ptlj)BOT1@pTwo7wG9OvE^-6bwY-^bv3+z7L`A3;U3+(3J z$9^%*7uwz0&&{=poz-l>eopho92t`cI`$3CkkAzv~mS$CoarLh_;Zbhka~5T*x&wthxPaurrcotu#G2Th+Pc2n<=Y%_cb*Enr4 z*DSG5@D9GjJhsFx$@}d?+C!E%8=23S*zJa1&mhQ2`2lc}F>heI!(DKXU_oazs7!X| zx6ug}Q+cIUA+)Q8sd=y?#|*mJzQ9+H%jDfR+dUgc8nmIre0H;aY~$(%QB6(TrFJjx z>>_i68A(^amZY@lzZnt$H6cU;z=Q_xW`T6R=?Uv1-I*_*l7v`lnTFdxBDoI z802@hn^jB_SXa=(7zjx@6ncXH_msaoRW-NzIocguaEy~_$N$LmMk>=AWWrUrisyhkw-nB525SM1sReUSE_~MK=$x3Gy%bBiv74On9{yDJscLspSA~=bz2urY2 z)tQm98l3Q-(O`%`;=MD8W7UHbJ_r0(Yp{gl%9uB2KozEUw1)*2 zJNL7^bTb!T5GVLEZ*=L8PtczX{&&9B7s?0I$FFPS4$`TLr*B-QFHDYy+-ihISeLAx za#hjY(_<4IsZ_1b=dw<9?szixfN1XO;MU{_-0X^%*_}=tK|-25C-bcuHT2ZcyVnc2(i4i^TA%1+Jd+05!a_?<>l#r)oYg*&Cv6tAB8xj|Yx(lVV9 z{#LRz-x<6hwkq&evL)Y>#V;*PpxSPed;Di^r{{<#I+$tIc44?%D((P=dBg}Ot~it* zq^IEmHE9OKEcggQllEWIzTEBYT+*|gJVtrP!QY#O ztV+N2Kz-h@0Fuv{Z^tA?Wtx%|_8?yMnzF)f(WM8bf`OF_c*NuWWFT6V{Ome+IWOKu zk~@ysi(#V;D{TAZxne|oy>dZg&Hn*-1L;}t$bKeeZ(ufCfPahq%)~s9kt2Q;KIfQ! zudqAxNbYjSLm4d)r#*4>Tk+HRwqmH=P_7Ae%PFri8cCQ@EA2MnCaF;{gPV(3b!BD* zqjqVq&{m<047+cz(uQ|4`EB=0(M8jO__;Sku(*>|WIyIW{T@$nNR6h(xm-UrxBZ-0 z5C1lY#$Cv#agxs0LHW3p-s3;X?7h|Q*SnceL|m$4%RqbkwQe&sH1kPQ2Wi;e(%K!$ z*=GGp``9M0HQX5E4{`-7`-*14MPKCJ>V? zltSM69E&w6(yV##Wm|28xXGu4AVdEiP#03#??;*8tL>Ybyd>Xy z`b&h`eV2J}wLQGsmJ2>|SpGrvYbCBiFxN@!yoEQ^f~sXdFIesd!%<~D>L#odyKd5>*kKz z@PzK!$d#GrvsWZ6JaD39aF<5)=AGMYyK(yzz*qo+=7-zt7R|qS&u!7?ydaVT1=YIe zb4|P3F@}Df>y|ed@GskMfZ*j>;10z^b{lipQJt)iT z$b1$(d|MH1L9-dhQ0;_|MpMo%=)2_C`VK{oddH7q5^@{?HYxEY`jrHbF8FM;$$WUb z-LCP!D11ojs;Ik+XPw=`v(B_yXP;288nd?UXv)BM)`v)3VJ=+9>U!1%X2CjpkZ)Tq zk29~c&kcXdp3;mt9;@#ectoA%u@>i$&>JY`iIBbObD^b z)R*+w4etLoJ}x32&vg_0j*Y{C37CmjdMuG`Tkn^XTBC?5?`L;58K%4=>90-l8-Mz!!kRcl`6<5ny zxbOng=MFA<=$NAY^;Gs{dzGayCUGs!##@@c7r!$4!dG%wzUr6yJuRb=L<=^=XP5fo z8RaV&QS)kirc z%rjryVdrvE=<7S|;`UEdj^I_<*B3Uz(#g*jL-{PCQhn z+ZM!*`_Q@tw#7WU!R}(WOVyb9)_l5j={}LPmHBpqUF<0^jU)WaH9h$k_5kP(#$h#0 zWj+D$5B7Bxr)D)y#r;N{1sOHeBy-a0gckSy_Yc)Y{8cp(gr8Fu!fhigt@o)n@&6C4 z;VJhk%Frq=6S5-V@+zAZw{tQ$+wag+E4EcUW_--MZiYSP>xkXDaTg@D@=LhxGzE8Z zBzKP1YV=TAmQ~1r2FP}*&@Drfr$R-Zh3Q4sHL3O8Gr)*5(0=~H8IyDV${B;FxX%B2 zrs~J~`e%;D(wpD2<2-&Z=!&4(!EW1PZdD6(4=E}S5?u{?t zN<(%1#q1()G56hNckot!XWqVx1<@A0RLF{di~060yEt<+NJUM--FAyJ*6lo0_dN~K z)yyK0GZX?#Yi7O%jbXWKI3GUD&ndB>SaWouy%vQWm{mo;X6a1wO8QkdvyYDdm}SQQ z(;gXKay5vc-=9U^EXvdhITTo*+<$?K;8&>N)y-X6AgX61>6*lp;sp=VeOlCzZ~atH)dB z4}hg6D8q*nTx2p?6aTprZoUgOlpL?x*_u4eb%Grz~&>&*qT~Z znwvJ;C1b|5K8(b%DI~rCc3Ok@o~ihciBG?_Z0H$LKX6KLQ$IW(s-w8E`O!r6a zwoPMqx#l*lm82YGU1iRGl)JV&<`0`=SB+t}4NA>uSL^=$=~C!3~}%Kkr^vmdv+HTxwK zjw~;$xgXWN4v7;SRBX)ScKedD29~qS-lkxK1x+eVyRjx)8xK5K@GSR#p zwU2Kyqxf(KcX-=0f6;E2cXhdRknxFj|1m|I*bZ&Vc+%vwmRl4;P=yp)XHp83hFz~5p%Pi4#t z+|Ig#bz7&**V{C;10IMZH1-=ka;AB8lUBEN%z^ug?A%t z3R&u$C<`%iO~ZkqRn(HW%TjTigDwh$v@{!+c!O)>1f$!V{=h1j&hsq-Of$NeMP(v1 z;_rh<2+hV9VLz=B4>*3S@fzoEuRByX=I8p!e@YmQv0sU7&n%n;a6WfnayMJTimc#G z)2d{M20YPygUc%s4i`cJtr|p~o!nI;M3T76it_kyHuG4Px%5RI1>BxW+)ZLy{pIes zyeu#j<9R4(B2NP`ym)M+Rb$cQEPOXO9iP#%Th?^ zlt(C1<{M z=qQI=ToRCZ9|hn1qZzb~McN3buU72Ugwc_VBD*rFvX(_I=_P~J`VtWQhcn{FC%%S1 z{%FM&?J%*BlAsVwD_}Hm3W6^uFLz+w$wXa!DP7$}DrOY-Y~Z`q*I!gyXszb_qn>9i zi~GtW1zF6d{W#f@fr>aQpo{q{Yko(aS6}A@t1;L_JRvlKKwv>KR6aLpl_LQwI5GeO zrhOs?(2WjNp|FsD*_?jA-J$!}S1=f3dY{tu#K@z^EpTZs-apPI@(7FcRvXOi_rpdQ zoC0%~%!f!pTSt(a2Tfx3lVYn4LN`VEO{Hyy9a9(S!v1YP-XU4ucD!Br&sq0&cCL4GE?gV8h!;U*kO3zON7lenJ?L=^d9AC zYK#XOB^7f#=l{Q4KHrgAPxpD28O!t_-~J)fRK(OI#}PJ-6(eP&JR`zwVp!f})NT&JE0s%|Y;7TzioB8@_$XKFvGq3UmC+ zb~~16lU}xY{1?~cAZpOlC9gZ8F39iJ6FFq<=*?sGqJYym8Y}ZzSp1HbwXwO&X~JqS zSMdBw932}s5a)Eb$$7<)`8Rs|;rTc5y(^|gynO$<hY9KJi1dJ{2eRcs3o*QI_-g?fzN>9hrWKSG+OOEF3TQ`GI>n?4WNLr)ym zZ$t8lm`;B#i){>4CG~uH-G^@HUiE!_k=iMx<&Rh0CWI^0usyz;1Tlfs_}N z9Oy*Koo^hfyMWewnTpq@o#K`LI%(&SCRB8&`(qeGd^GNRS1XnB_BY*z6fCQmUb)^b z``(m1h(`Os1T&of%_pbIoCW`@%zG*CxbMwP58BO->kYbnC|lZv(AGpSVM2XfPvSxq zECJzNKlu^YPTsa-sR!ln6!X@DcJYuH2Rl13WF&`nci3R_-@mIF;FYPRYo#lVrI3WF zwjfpPFeJ7-tOl5#4`CBqU`9WL#q36N*+X23KGEFz5UcvNz>5KRo7TBVVefZ5kHrx0 zjRE65m?DFE97+f1A<9?NP9x7}zEIM0#?iO8e8-`T_NLDx%u;=bUxl?!#229+XR-*>xSSFOJ`M6g7 z9+9#=w<5M3UE{@5uomU?LEGxRa&KvBMSCn0K|gTWG}IHeCXVKiVHuuXIDD5AM)BQ- zaNtbrdW4;qVcR1_u=x$+e~6I5_r9w<)=cbnGdOgZe*%XNFX2!lp(A17U~YrOIb7k* zX&x&;*m|+Y`r{N%RSu_2LO#EzpI6GC3n-KfqX<2wkO8CMWa6d~M%8k5^Bi2y&c@|z zABYgTQdwWZ&dFxMR=bZ~?Ps)OyzK3*uM-7izbBa)HCqNuKBvBQ zy@%YQ3cYMKJ!fCzGZ|ce@f^2a+z99!&)GdsOL(|0BIq9Rx5ThyQDMuYhCDe$D{?cS}&0N`XGv*dI-<0t@@J#X8shXddxx1%UEs4)b< z3j#PkRkcu2^{Q5e-M#>P|Ga&!_l#@I886r+t(yU;(JCg;i#BO%Z!1RR%`e!Un#Bwk zy3bikN~zDT zL_J`c`6-9-l$ITG*TIb{T=w*Bj>K<%-MwB-`J1x{V1v*R#Tp{grG`v)*gu?T%JE_q zVlnP_XgXj_o`+hiI03hT*A+L3xcq=FF&dL#=FS_JGQnBIX-r%}g=HvY15SvztAxR4 zI#zggAO*J?=kid#rmWPyYp%KHDXu{Jea|8D>Ql&* zfAb=z4ZpJ9ty7o3ZRXOb zj~d`5ks-YHO1*-ent)ecPKB(G6B3QgWl!5JdS1q|Bfr9Z>41C9iu7=_^WYebwaTiK z9eHoeQyGbm%CZvqrspd-5xpg+6)ZIGYN)W+V`-zy<^ALjK=07%t|!QN^N|##!vjd6}9>@~xHo#(z!Q*lE!LI92EekuRV@ zqu}nn`pvU5SkYzU;H4J6{iqN(EmL`86Paop<)};#OqI_RJCyQbSBB>$(+O~xlTb>6 zg*37%+?Joi`=iSE@ulMb50Zr`1P%sXPM)ty;l>N;5IUvVdHhaWq4b?YnmX%Z5D2A^ zn~JW|w0sxw;}iejj)=S*@2ccB3g6yakz*4V68B>2dm4p^GxinW%Dsm3C{r-=myfT> znjIO9bQ`(5w|)lTZ1-B5oDmGF3~qTfyZ{e0Wvw zdC4ytBy4_jRCPRX(!FpS-@>mN z0<8hJ>M8S*O9`u}PVrw7|2Nv6?v&NAo#G3jQ+MK5)YrFj7N-z^1?tO;Gq>T>u#x1H z&r5!3?t9(tGX4=}{7WhGIgUG_o9ODn+NR*7WUW|oeV-xUm-eh`N*!dX6tGS(0 zqg(Uc>o_Q_76xTyHIsnLB%T3UqfSJS)hUnS+Ctq}@6{}eFO2Dq`&jPTq9GTUhEQgJ-|1ToSU7v9S7#ftmHc66&tu{6HlaSj*Ko} z924B)JIuj1I1TmG1E$ZLcFC#DID#!)TCc`1!he}7cCkK7XPM|2g2k z8LH=2gX{7I$%oAPH|<_Wb*HJ55O(f2G$Da>gxKsulVl4daWsK)ZG7is!aWU2prXg!pGXYnu87Q z1I*WPt5sojmAUsVyTE(!X!Fcl92Lm=hpBxF2lunqn5J*rV}^D=rM?aeFINw)PoAU- z%Obi#uy!(qKFEK$4lolYE?Eo5Rz?zIh>LXRIZKu#)7!ANnPmR?wtY;=&3Yn{;p2E9 zA;4@pL__SrX>Q|pU1xrM+io|U=hV3R0-;y|D+8m(*Ivg62ljVh)!@Pu!Pn*GCRiLL zoZn|Yw{Phahnz)d=W28IJD8##F#mYR9@u6`&#%2S-wN>vIP+KzH>_CYkQA28H*dXT zw+^4~aL-wZQ&eGv76=m(=Za$j`W}<$!?zW9&-w1fcXjloWPT;ivaERXnak8Lv>9<& ze86HMyFR&;_vADaNUvB?@siVvIeyAx+e_-g}BXNnL9H4BE;B+Io2~-NS|0S9p`s%pkoq9V0C}~T|3KD zYF>VqXIfv0nnUl}XEg03W}z5WBig+1fI06yyAQq^%im*n|HaeHmiO#4iuz1<4X^?$ zliiIP^D!`Io@Uy;Z#U0t)X3$V)sLG&@7vqFS=)?vm)))D@S1~;$6I-TZX@rpHD=H* zyQu$X%(3FTT&mo|x6(Aw1=p86O_|(vky=wEIM$=uw!}^DZEo3RpWSrKVoMIBexjz&p@dP*~EW>i#EZlh+6kJ-lGNuq{EhDP#xzV7Sz`SksMe>@(C z=ly#KSSpsJ?c z(z)g@Oj4M(ok!8<`)x<_CD+LwbqYm2LmrQpSKmGv`unFTXWW#@RNc?=;ZuCrIs4Cy zuf=ZnvVFGQkMnmv*{1=GoN?H2X{Nr-oZRn7zN|$nY61R^ga??eDDP2m( z^GZinQFj*(zpq!CS4Y#xjkjr$6y66%jqp&@6w#hbZ2BJ~5lVj&Q^WV^(v`5eERB!u zggZ=q+*yH!U2l-Fj#yQkz)S=OiiE0;yPl)R&`CGu|N=zo= z$;@ihgV_^*SN5a^IqO4j^}+ucp3@aWfJZ%A>XsH8Vnk%qq)+;`{hm~Wi@Ft<>bxQp zkNsd+n+(_YsOaR@M=kj&ZuJrl<>pxKsxVtX^kME!&#@k1l=IEsI|f3g7t-|E?#{&v?D)GkHFojB~VHR5;z z=3e#gmLG77;_}OT(xNp`L&Z31;CO1_4d~Q0r@*6S^9JrVA{VkdJ??uoZDF*g-8?$# zBxXmqu8+2tO>Z3;$ih)@t}Tc^ajim9r2N=bL8-c`ww+9Y{1J1_=#E<-g8HRf2{w_pg7`w8e@1^GbuXc*^XOxtoJy$D{Tp4XXL+AebM)=)tg&1_ z)0uPWRJj(q{+8u^S6#+Dszr-}qMrHKIl2%hWmA$ltuqgu2AV|t-Ndm<^(LxyxJ~Pu zt_hR!7o`GD(!CZeV=;8!&Xkj8KSE4m{GDp8SYppK$lHP`JXxMH#X}d#z;HP9=}x{! z{}}CXc^~Q6Eid_u;O=&2>auyXgr-qK^_X+xAavE|Df82Df`=bO*Y-=46)kLP;5604 zR~bp(tV5wqpR-M0h?$Zpv&NH{-1GCXJ6*(UKeE`JUUVYw)MGa~To~i2z#$=0iS9_2gF(-v%2 z6E5nhQ`4vYXl=@MqDJSVtrZWt&n1nrmw~6tSj9gaUGbmJX|9+cXQcVCg{SDw?#wcF zaEe~;j1S@-|G2%?os;)epZTlp5A!hBx99X?8Gn}ZDBC$~_;)_KOJBh#2(r!7sr|x7 z`-=0HyLYkkiTTUiz;Yu;HCCi_p6-EHiFjU7_sv9B4cT85>N|CHg#B>_Hfxh-CQ_B`mL3c+&HqJ7xT}J z?m69pK|KzY)$)MmF|CN$27~tYTz%P7eYZ0cr>OLUjFZ4 zqeoq0X>_1XHo5~{()0T0XfmhwI#`p%kwsVaXic(tbTo8nC$B?q<-CNV=wUjlEXw6H zonocr=?06Zj4zv&E${n8wVGJH-YV;uD@eJ4+O+ft(n6!-RI08wM^Sv89}PK3HPYB zB^1?mRuc(DR>_q|Pe!-OXjX|H5~8eBB9x8EWM3opGq9^fY%3fcP^-=$GVZCBvd8*X z^9s$xZJeXf^2GYM$;{-uD`I3?8dlrBb2X zYdTii3` zAShp>8?j?UF~?1u?no6IytOlK=371Vr+8M_xe6TZ-H>D_d zf5EBi@>|&7s#C3JFQ6>kwVp`prOf&^jE9rnF( zgHQF%&H6O-_gM>5+SRe(JG4NuWE z^^={LI&N06pyTyUJ5v4A-M;?Kix|6jtF)@}*JS^}S^5Ut4SDlY-Q8WY zGK14d?Ug+jP;@@FywpW-7mz8@N3Q;ym{8z994$MSjLRiA;)|Ac<`(fuG`|Yqik@lM z4dUVbS@(CQlVab@yLY7p`KX@%`aX|8rqkztYnLK^&lyWQletmg&PIcu#y>jq?J;wM z@5ZYqh~W*!$z*```g|m06JNUU(TuW<3bdpr!b>gQ{!hxJDe;|TF~>$~mDNR$_idg0 zX=vAfQjR@kEU{q!w2QsBX%Aw!p>A1M5R1Vq9_^X=$gT-9?;%zzn2tUkI(=8lvFECT zi7zFONK)?^N;V%|!;?5ZPH;XvI$p$5w`3=ef|s4cbS0UgyLa(OXKA$4^s!%EVAK|_ z?omn#jOkm37q$_Hd-TrvH!rm#`eL{J*~3@TYX&y|nb_=l61##lAjrwdbk6 z;hB$;ix2mWoWWsap0Cp_mN*_#iwR!o^!*pbmaIim7X3Trtj6w(E|fG&P&*o7k)WRB z-M`Zv)^T15k5#cV@mw3&9%f_IiNp?$fw;%dS|0Cf$Bo-TwAg90zIC8GwMnY*=yJd1 z&HjFl6e@rMUiYaUTy;UG8+7AMjy3$|v zzDkfL%d)VDy$ALz$bo#`Kas}3ttp4bM7KZ9x`svVFS`@yx8s-X2E49Z@Y_$=kRLJ}x^qO{@ z{Zmd^8(u5LX{B?oz0jQljlJQ*?xQD|G`uxox0l&^T$wFSMJPyd%qL9ul`>^cxQCeS z)|i+S4J5%(!EpR!RIk9?AupZk&RrxGq3Vt5N9;qSo&;>h z4Ku}_ZRD^f(D_jP$^DN1etOBL`tF{&wA1f?!}>~9oR~H&MCR&oiwn9VbKmVcf*jNu zCCdhUGz-U*61ObzbP`Vx{+lsX5z!efHv!6S!erE;k?@Ge>2MSEXgF&@;S%V7MtOo4Rruo96{ughvJaZc99blH3( zjSBjM(8aq`W}a?qb8^|zzB@_2vP4rBZI5dVTcR_2#LRe>_x*;NyD9Y4ZoU-2rvu6! zW-IQIU5!7|F4?_(8oldChF86y=k30~;n~r7C4bZzDFCe>U` zuGHbpBmkYj^U`hy{U3D=20v!rb4Ayn%&BCmVDXvZSTS!W zz&XK=zBx=H6u}CzE|Dxu#GgbW>ZqXn+^kWo+=8Xb-oKSMqB3Qag;IHd<2hMveb-SA zTe~~tIXlXa_bsDx@bG5OcJ>=Lc<$~}SE{iio^j(R0 zvT&Np(Vqg|8?N6)oVMXkO71Z+o_F_oJlhwr_+s47Vhrv)Ka(Rlj9eXgF`hhrMNxWT zgrhtyc$P6K#?zY2;qv6r-}dmtNhZ6$-mKW}(V{8cw^9VEwR}~!Co?p2FHfW$3@zBp zLx~))+?#S@>}?l@mhMeiI^hXosl5{IlU)3DX!5?4c`@IHey}g)mXnt(KeBr>i_N1= z?7i2I@FHn)C(K$FhA~q|GUdY1j(sUJQuIByjjLO`P7SuY-+*1Z>YlF5(D*M?j+@ks zQ#QG{f50JccrbMCmuyn!bI_=gG1&{X8(GdevZm#!zDy#d_QV5$aUS;DHS5o12+XF- zN^jvCcnon1vUXzUs-Ei@(tB5FyuQAN2Ok;gt-dyEWlA=F1+yMV33}3c*z}y{K6yp1 z%wjIgw{ZMC8_f4AD6hXVdE=9H?yjYy4Kn#0PgT^IrG2ZQ+8s4fn<1w9@y$s2ovKar+z2u2u+l1wwuSo8$?s+ZtgDwqW@zluQ zaU6xuUpcOU9P4vEN0T#)=<5`*k8@UfPBM#Zc#dQ!Li+fM23bW`CztAmbW77ltPVS^ zEG1e$u&42~`pvhmb-n$@)`T8d5?E@dmPNG`ALIfEcK-MpjA+ww$c z*M4ro^@b)LNI84FP8xW!G*7*%r#N)ofs|8@{auXbgYx(P?5^4QN>yKJ^g4s<;?SxC zDJRZ8fd@?VDrPm)bCsBr?8-5oQcJ^{+WzjQ(7ppHb8ampgV=ZN(s3r`xXl0kYd!|d zz>`4+#PDF4-bEW1d}r6eS;WxIL|$0HIG`|cDdiP4f9|_6a!fuq*BJW6 z5Z}UnpoxVG5!P0!m)Va#$LO8)=q`r_vgB+#Hw<>F20YPcCOzF({pQo$VbT-4e5adW zlkvVJ^w%LiF~y0V0j&g-pZ{d3=C%Z`?;F7hwqb62;C5Ih_WKYC(J zPETb6#p`CftrSn=^!s&NkByW^w+D`TN$1GRP^a{8qi@N;fS9u}nDB9>H>9@*ugKYEo4?P;NM zkz=Z0I=<%hEOT?f+gab&az#5+w7>PKQJ&gK0T5YzV9l$qi)wc-nP2xI0xK)(zL>yR z9QV;u>E=6`8ojwoE8>l_KIq!YQ>b0V|#rBCQw`FItP@N(<#k9Fig726hh;hr4a$C?G*V_RxE-AxBs_KS`ocg zpHvsUz6U!;x94|jnpURX_!_P8IjhY%eQ`wGP&i3aSMr!>Ez&93yIBp zJaqPJ{cXf{bX98(f;ce}Hw~IRwyCWOk>0q8G?d)9J&M~hL_d&U#H#?nJ*(xVls zZUpK>S?l+Qy1z@geth-UqXX3(8Pd6e*wDpCc=}^`=od#)ro{L{%aCGkD-5kWk`iD9 zc;^VO^LT$S^q(UsGh$ELA4(WaS$KZl_ubR3D_TIyuwxo{QZMZb_T5Moi?4yy;r?G(6i@JI4W14y+WsJIt-XGaRJemmT#+CZy+o>uWMiob@&zxl}GU%J>70c-@k8V@l z68dpm;P`WU>1B>PZ5bW0-SKMR)U*3yE3H)wC)@EVnMY~-?p=o;x?Ut@)wv7YABEnD z3(TFgn2yLjF2GaE+M%lqjr9hObBgd;gSh&&grU&^-Pcqolgp^vM%{WzPd>h@)K!pg zFsD|8k7l+qUgt{w_9gc5>-+n1w-L*u(=XZCA-5hS(tRl%ONjQ+>06R#-^9kfHs#}a zvy=RmU3LE|%!l!R<{)^Wq?=zd*J=EMBOZ^B-(cRU zUnGU@jt@+AmYhcsoMBG~s?;=cd&@MnzNTj$*Y}=IFeK*g>+!m%sC!IVIPMhmZfB9V z%)N8V{nzfdxr^J#%W>uoQgcX%kMT$m-YcJJ3rYzi3dlRMO!BZln05yPm@Oie!Z&#{)>PQbk0pF*Gp3o^WfoOxvYxE@+~Pv>*! zRCL(M)@AdvtZ6{(^ zHB#;GviCy&^3kbW^j_$&FED4qkI$n@kR~0Ud-R6Tys?4vW5-_~x@#kwbzA?BnGBUJItNbR6nn>ML*PROn^E-+(q4M%#FSJzWsipS=PP(l)&`{H!&>L1Tu6Tbp} zPk-p~Ji>3wINnZvz~jl78M+L6fp>Ckja)@MR4Y{*pKK02fLZJ-6`_}s0(YE0aig`P z4*ugC|JU9iQ>LS}_F4Q<+>V~ZR6ioWJh*wKAawKiz$|vDmW>Zw5dZUY*=h;>b$sBs zn4!>Kfeobzf#WZH7{4`Jp-lSaR_Tl>3io{V4&h{}td{q^KsqydtyhrB&ao7hlTYt3kNXvKtH zo*1|wc2;TV@WjA0=X0zq^8C3^$ALYbhdQtNj@E-U4@<~6a_SSzHM1pzzKm!Kh?!(- z_btRixkGd({gWJ1jrY>KCoueuA=+}E&6C*L$~$T{dV?+TPtf(ojl_;-h5qCZ%)R;Z zFaNhAmEC_ejJgL<3dD#d?)ieJ<$Ptex>NtCAaV_vi)&ry4- zeX;)xoi-_O+T>TG;fx`-*r47$_ruT~lL9kteu?nt9TWqV)7PsQ-|jc5x+8SPQ~$|CDmy)tEVU4-92^2-QD4j z4-e=#Y5xCZK6S#~-A^BPclQd+dolNr9(BvO@A{l)&2%Tm7i1Ehmk8k&|IIRDt!DOf&`+_To>d0+}n+1K(wcVg!s zJH1rM#?Wt*0~e(5g(IFkN$$~6fh0eBalyFm$3h<^2adn(XLJ-QR&M7cdh$4PMNv1F z*kXMSYD3^9n#2Q&CCx;STJuT4Zhax#L(XXXP%X~4U}@jo@`Kc6kDl(P?hnzFDW_^e zH>L!pj$IV>rZV)0l)!Owv@%!!p&>9S@2S39qsH?2mjAg9_muIVQ4$k_#q&acO9=$V z*YRw#CC2+wk3JtDd*5!6_2w+ zw*>;zZwt_}R2!w*My6&eFbY9(AyZHfx7alEN}9=X_Iqa8-!n^PY@hMHNa|^*8alvZ z(EU^eMUT=KI(KSd`pmfRmD@!+=jh>WAy`YG{9{S~b)i2@4V*apyvupKA9aksh9eH) zuDhAts-3Cl){H^AC1s%xrUqur&?u!FNJ&Myzh2UH4a*0atL^`+ER>KMm~rl<*im2c zC%9yoTPg{B(~Dp8LDo|&KZ{|`*UTOH4Xf?ukt3W<(nRpY(2r7?KORp;sfl-F+dhh(&c&N(J<;)F(Ac=I^Y%p9uW+Rz=x1OhWQoO6Vi zO;K$<;hwpwrbWEi3NQ8?V3Fr}W%V(E$uXDAV}{5!s5?39&8qIxlOQ!%Sj4Y@UoO84 zeja``UotZ8jq$YXXM!;Ly`Bq?ujS##X@S7P;;Ts?U7%)>+LcrhX|qu!zk?w~$&2xa zdw#{FO!+V-kMv`AE(cGm^1kH#bv$8nZ|M5zfwN-gJQR9ldf=|uPp=M5P79nC`0^TV ziqK|NarbboN?p7zbPZ;SlYJ9=Vwl}NuqyOm8mqrgazg9U0taS1%y6NbHVIkWmkd(1 zA}sB3=Pg^__rQyxt;aICyXVEwj$;F}uly}`E0_R|#ja})J7a@(LZaU97nm>L##RF5 ztMn-@cM=cHu$Sc=8PFRH60xtPxWd?VW9Z5mOvd^Tg_h0;oSgW0L-qoS*VBq9w zA7NK*AP&1a?zx$=S6IQdq1iJ7Gp;Yf8b+}#}8BYP&?QLX`xeJ(gl-3Ps|LQe95!RZT+DxOj5hm zEGu1gj>^7DXYQzj@sf$3TL+2X(Rw)h(f_T7Z>|VUm=(Bk_7~MQ?%Ea6)FP>fNpsOd zo$vfm-OjRZO=-$r2rZozxc-MewrGZ5p19C6Gq7;O!K{7pGp2v$N#A(>lpPrh&pBq! z^bH5=zw~5`-Lc`| z_Ac}-oPf4%Z)o1}fwPS$>{zlCK%Hxd&3NUIWNa!BlXL11)iCU^EVtE+~-}m z_{Fgo|Ca0CeQ^s@U(8sz;-dJ4p3eA%L2Pc{m$5MC^_^|4v#@>*(Mx^9yRcz;S=xq!NqgfL7QA@I!daNi*c-}B4`f`SAQEOw z{VZm^=Y*_<=PbN@$lST%;J@~HGUCaa(tXOBxR3VlifNC}-?vMCmhR117}KdNS@6X1 z6;GTW)4t*0TYD~u48Hy!iry1?Ha&2$cf-N|>VN6#1M;i{Fw^tGQ zsy*20Ic>&g3&;`QtPKYvdl#h1^t8R9_Su11xShQxbZ~Yci%_@h9fPe62Ok&+%{eg; z#w=&xl}}F$bjNUc@9xl+lLB{gmAE@J=j1>kS10cdEj>AKGFKmb5sI7~2vWSyeKFpR zy624p37#vy;%8bs3tsDt@!ZVlwR$5>fL}AeSNQGXx0GK!6UMvv-Ou%(Hn2Y9mzOoh zbd=)OET4!?tkUh%)m9i*gt$2+L|4h7aRQKmBZPAk7E;yK4xI!m-lh# z)3aHvMm`7~IXkc;F^I1JBmF|%Ie~Stmwga=BYwpWhi17Z0D0HMQbeuNiV>ugOh7ej&jm`K-MWmlI6g1S=0s6cbG9WYK4` z0%E{1y~o%H6i#y$rZ70*tS8`p7+IfgiZjF{Q+kRRG+S~8xb@8X8b;Q{nBsF`Bw~z6 z1ncwR^Ip>mWp9gQ^yWhRz353(awReeZ5Cf}Volps1I`NsSW`UU@TCJM?^+D-Fuz0& z(@p6Oau9Fo;TFsnms;}{mrcfVqm`4O0`x}ZdXa#0Zn6n%fRQ!hO~tJP&T8|%>Ho=q zv)IAI)SnJGOJM!4u|UlBi0flb!Ea%t*`)t&z^TA|$z76Hn+gY#)u~4I{Km7)rmS`S zfK!OQ{1?%$8)JrH0dm1#JY%*zEZIO(; zIpD0j`+ZaWmJKlH6WMDrVV8|2_furDzFeeeJpT>XCYV8&UemGzxiQWZd`3=wGwRfI zx)F$&YAzIkB~U3$>Jl4Foy#UO3{@E`d(k(?nf$&1rv?v(ciD)TJ=Wt6k(6$S@^72u z=6KVv*Xkp%6nCvrxqYv)lB{m{dcg5id(AL>VZPtg92{_(=1(;JP?fIr8v>f2Wju$h z$HT+&u)(bScECx+!=b<)>`gEoQ}?(5x5Fg#_0z3f3)RZ@KvlxZksN6>Sy4Fy%3% zE9=iNq=+2PpsQGIvVLtXWp-#urqEi9>tox zBx^ATM%JHas!p_W1yuX4%&>AfjI0@Ba!$5#7F13Qo@(WOsG=x7&B}#P39UVy2&kP_ zb0H7Y&#)HKpkf}0%8gMuILDf&!btNZQ#jYk`EdRGSkrzkdb;eD^Wh6YQ=VtdOX2$Y z>89usD;L1X`b5)qnPU|#mq`(8Ixn|!2UOYRUbWZlc&dx7ehE|#nQN`Q7)By%Om>Nt zGokv06;Zhk%6{Q3);u3duKKZ+D;zGAa_>*%Fk(DVIWl~!l`Erixy-36D{d3x%+8<6 z{8>|8Y3-N7NaQ(F{4*;TLJhaocSzr8!chLMaOGx``E%(b#>wGA23b%$=q%&q(ga}{Hc|bpycdcD`&#>^O+Itva$!NE)?`zIS*!lw2bwncV9jIk8#9e$|g`faXpck;PCE>411}tf~Et6wjIwml2b* z*jmhjifQc=@@Rr-f7;3`*2;dPX&2W{Fy-rIo@i=cvgV5p?sFQy9Cexx?{k}P_*?7W z3MhLkN5sh{9P51P2C#G5m#&A&)2&=L?@MP99;BZ8rQ2opLRFfbP+6WdAJSixF0lGy zs1(&j6ge8>=sYZpvMTP3mIFt4z-C#IV`!vf0%C-rBE)D$=3l zuIzaBa3K%MAG8)qVPwr%lm9TJ@-#m#ImHw|WgU)eu=a*vWc@5-Hd%dVht+pLRo0z5 zt-iina;&NA5q-wfCnlMqU6}iv7tKyCWZ?e-QnqEgtw$wLFh}z~9+t+4 zUQ-u0=-R6vFFC<9`>lCq@}OI1(xHmD*k!~laY;_4pvT1I>H-U8B1@~bfMlA7*c4+5 zQmtG9)jSs;Gst8$*0ey`+v2jxbVlW!E?1fGG?}wrm~QQDbQv~jX;v`%A)4412n=LBSO zto#&6&$t5OFk%{|pmtVfS_cLu?-_N%QF)I`CZ{f&OypD>Krhq+qxp0zd$W+$4`f?^ zBG6sjo+-J>WJAeyuH0yv&va}G8={Jev#fe@}Y{Z6>1@qKHth-Cr=h5#^JmPnYv4C#A=|* zurn%mxN@_pE|mTmv*ZUhfEK6#yqC+p-{f6s^;J;w{G_YIX0uad7Mxcsdp_e7mTd zT8GP3rs|LAsZ>R^GN%iMNs4GxPFpU0vsvP@(X@z!xA8%_b8<}K)7D|Bs7Ybi%G+Hw znY>j|bEsyw*p*kAnyB0;nPq!BRBLIAnw!roO^j#NWcn$qWxiC|$9d?D79HN$l=X4_gw&Wwm_V@=I^h`XwYHLu`Xnw40+Kvo5mAlvjirMeltBT$4=2!((fMKsV!FUtIRMR|hzf*wy zx+#)ljY-+>8vP zAY+Dgmk-s^l*|;HO~EX&$rK!K-PNaCebsEMZ*>`QOiNU;I70@Frp_e}PqGd=p#toH zEB`a4|v3&9awZ zD$7N$$+%VYnZnzw{d}l8mIoD~X313Q(x2_u^gGV9SD|1$H+PC!#V)}hpoFos2uB$%1Mt{^D?M# zdmkajN@>|ExP{4k?9{wpAaXT)Tgb!4X&S` zWL7>WeUkA!FS0srhSZ5NXRQ>m#vidB`=Bb*h)9Q#wn3a|ayN-n%+6P3&N}}!Yd-iF zk!ku?tM7IBjLCUJG8+-1I-65P$BPLyZKEWhkFJ_x1u&|T4on)F{`VH1y8VqyKC+$WnCqqT3)VawjilMer zif^%UA@t+X#-CWZ8EQH1`@c@3Rhl4@mZ!w&fzT;fHJhRZs!e z!Sa8PI*n1eIcnY@nO0WvFr@OOJ}SmIW~F;E)^ya{+MD^9^(X^o;8C9B^~ok25`Cs+ zg_vOSpR{u0pKS!fP+6W97Mo1^DluZRpjyS2)yV1r*Bo$m{%h2!Zbn}3B$(p0x|m_M zMZ^gv<7MlhWs~)IGu(`WR;V26a2YW>p|Y~$73o==LS=QoE3Yy2uS)-n+4h>%w?gGu z#v3AcPFoH*m5yTaCJK7GMv)XQdh38whQ6|mtc2O`TMsg!T7?m@xBX)=)?{}`A7`@v z+sYevTl2zwR&Mypx?c(1qWexvGF9HMX#Zqo&A6{zkFq8}JSq|KxP7`vmd~(q#mukV z6qZ5P-7GQ5c+(*fD;BX|eWKM@pKRrgr&@VqmX#OJg{(1GK-Z(e0&8Jgkqw{~swk?j zxAGFGRdGRumGht?kb9eTm-cfp)}&Thx%wB7{vqd1xNfW&7S|@4qF>6KP3~WdJ~Mou zql*cq_DSn;HFTQ|TpRn6saz?U_WqPLPlBpM{?+0b)6gKsnBW>nnQnVtOf;QqMZf8I zN%Wbvmmw3CvQ3a2j)=$w&MQ{2LPU|Z*~&&lPJPwN6;PF{Ofr?NH7akBOagLV7nw)2 z%08P|P{aBb$>`JH6IoCE)tYY+(K`hnae;?LA{Od*i0p>-S__#2kjfbranShHS8lDZ z{zfwE_`}HTk_AVsx$z9S`l>jQd4*RDnA&kxpP3BFffjMS*D-sJ(FL>EdO>Yo1jS97M*U*JLgLOj2U*>U^230?ltXaLj0>e zOS0oL?enb1ZBSDy&wTM&vm_5vww`>+YfSz^E3YUJ<4ta%IL55F+Una&#PO!%hgQzI z*~b%A7?b_Em8<`4%`YU@? zuieVq3AHJmStKT!cCl%!DZ0X%7eM*ncr7H{oz8Vuk$ST@#?+LH<4ws=WFc%;xMZJS zl*0*1eL~nA-cSeou|`F(&zslAkd{wPJ&5U2gTBI?2zP4v`3MdBU1! zuawMO@o90aWBS8f&@L;V6`6)NL1LEr!q@JsH5Y39u7H}cY*}lwawAlG556qY^KB71 z2>pSWY=Z6L3=`=UXPIq>MW5O79V8)1Mm6$AQj3% zE>z!L4>dV8K5M=hYB1XAvdQF(Mdmcjpva7;BoPuotEgrBIIGW3vhH)C{I8G7wGfA4 z)53*37!jH8*G(j)SS+4|OxBG|6@8}j*n@6SWX_QNMpNLDgGDZzm?s=`nwaG_9EUk$ zMoCci)|tpmktLi<5$P zU|cquv}|N5U)tF=qRDV%JG0)X9ES2|BOFBE4&8{)BWJIF$#mRt(CI~=10-Vr%`CSot^U6I*sn=R7h_mMfiS1r=ohD7`y{7~flkM|$C zU>dz$vm7+zGHMi@wda>Xiq`b!_pd8BnFjQGL_sTw%dAFEq%D=Sc z)lki_T{2NKywX*17N{<`^lLdxGQPtihf`c~J3amzXMNdACTqes=o7i22no1B zT+4o8isVL959M!Wz{+_dYrx7>h`*gPzM=ioQM4at6_J_WxG8Of?s|Wg^&tCr$!ko9 z%LbF5j!fV0IYIh$rVy&XXmsVU$)9cg$%U#rNhgVH^SKP0da=Q8Do<7f=t|qTP^Bt7 zMO?g!oO_e>t4&eaH_o2+QD@67lAklf~@|yIV z?b>4Hq&LJ#Ca+zbVzzf!xwF&C)n8b-VZW9058Ku=0#(-O-&+6E;Ksj?I@`U&&Sr;; z@(IJv7FeG;?6kl|vxafN8V@Q$TO^Ysjb~eZgGhgnlOuVxX@j!Y;>zsvpCdiZ466NC z&l`4IMfVcn-3}!0VhqTtGM5a?F4-); z#5&A{YUdSD5%gU;?5zA7T`+Xr6e;%z%&``Rq89c< z9Y~gk$(KXMg5oQz2Zc~wZu3=EZh#7)QAEGxCeddae`L+WP!Zl1m0O{TV9Cvp9H?<_ zk>VMXS#Ay5L~>-?k0q}$=2misdqHIt*25CGe*S5u;SMXWgo;4+&xf7xUupNS0an6B zSO=S7GgL%|pzP;ViOuZ)>4GVg{};nf9TwAJJVpYwp#*F)Lg4Am-%{)oJq{r^^7FkAK4 z$^!TEL^_aRsQUr=%aPf!sD^G?N@kL}_(5y0L!_uSJ`AZVOCFINF|{tkCjC(xU`D<4 zoVI(+ns0j?GX9#pkX2-^umKc9c~I`M(KJNmPO&N8g#TpC+o76Y?-PcZ3z9hx&}<{r4kh=B)biYQl2@5FmupO9z2s+2OGND-4~sTg2h~s!YL3cVTs9j2 zE7m+2s_g2ba=ptY)4JK3dtbHYl~56=g7R-=RG;!%oZ+eNHAq@K~7L4zYUpk4U5!` z%y(>fx$h#A!v)TJx?l+ft3ROmMCBrAkjvYwxn+~7mrS!Nec$R!MCITI!_L2}xwG-1 z%vl49RO;kyvd2=*WyF+;tS|EaZi~vPZN#MYi}ErdFFrH9126VqLLlf{s>ggrF~}Y=R#!1)Nvt)OLkg|`JY?49xCR8 zP!9e7vgXY$n@#b*t=!u+?3BOH%%K_=3*=4M!D2 zyJXO4g8kOvBB(O;d|~B0sEBTh%GtZEM?0bP!2x7u(X)$XEj&~l-V!})$-a2 zaNTq>IPs8^j|H#)kW&CtVIjlleX}c5*(RZrrDKdRjyJ`G=gUcQ_G!fpxb6D&=|khn#Zsi=eVT z0?Uv)p$@Gsx)3@{EVgr@uC(GJIb3Hl3#@}JPyzTZvF6*M*6pc3u=dg}v+|Igv8! z7YSg?ZIFWnZMVz3*;G{8BJkZIxrtdYq~j|5Ic(-m%AGdg5-9T_@%d?{Ncw%&eyvku1I)PJDjJ~5$p3&GFb0SOoc>2E?{vvY=32?@ zhA$VJjCs(yYlo`kxer-=4V3J86!`_VaH0HPTrYFZ{}exN6)T}UDh!Ei9=W6shpL>5 zR#=ac{$$P5p&QXBq5(dMo*u94&sN_8m4KwMwO<4my~TuPmDTq{+&d<1wG=EMpf-^z zpOMT|3l`zP*I?xwmz?1g$&ui*)?GeSM9QLabyVIC({P{joOPe;vdL6M%XK(te|Ijmsu8C=&3JMq8`fp;EZy`KSz4wi{m%xvRd;Ca872fbe%o8N z$jsYT-w5SyyGS$M)(UAg!FSyDpI|m~Aq!RSiX54G&&GUFo7G2Lt}>l28KmB~djAJD zC6yma<~*RwCMKO$&T`2q8ka0UqO$+5hn!~i12XJFT&^?a-Bw;KKFvaT&O`Ldy704q{_OeFN(_v+L4!aRBF3HiD!%iXg zl47NAG}$i0#z5tO(=G)m^m?r#6)FYEFo?ru$(-$Mi?<#Oidujq9ClvdghbI8na?nb z#vXS22~VQz(T})XXL843j|h%HMIf9cM$Ag_g;>W_j<*&f(DittwNN6`^#=Wt*O_*g zO{R7dGPSpIGUU!ib}D2t>O1DJn-e>s0`g81xv}YT9Z$j72o9xLed@9B1bD1gfwEC>WZih5-yp{7#5NX%5Meglpi0Mo)AX&d?4y1Wy%{}Z4z0P@msEDk{ z7HOtXMU`{rVW$)G8tAV7H=e}> zE`sW+H%dOx5K%33JWr9*cxx(JyBW)wgMp`wc=PdDk85CO%! zlnYrby%YnAU{GY0+WZ5E$9qKd?U#v(W_yu1+f-jCCY#*bZOXkrmFzS5KZgWZP-P?N z{{=D;+6fg-_MMVhS>5T#L6XT>WG(hXkm8WC=8TA)nhh*Jy4Y> z{qbl7p^Bt%g_SFyvOM@Fs}DY5^|^4*U)WV^ME^pj85T+Lh}d+ZX?WhsPNObR6gF8! zu}F`$5pKqV(hbODY4Bw+!DMX`dE)66o0T0-p76;I<-c`7JMO}R%$H2=ex%2oGK;?!XK=7UB*0O)Hem8S-#Rs~QD+jq#Xe_7MVjX#(c%7m z`WP;7P&8IdGQn|>j-)yXssjtujhE_Ia3C?$TGo`P!RJGmpmAF zGO{WQ)D~>;6l-3QX&o*(6%s(>X(DICvLF%Y6p2vb8IWnWXRehuid5d>97s6cb0l-p zGS9IF^%saUOlzS{dF>A*bA0YHsLFM@)t499oXWhy$_-EfwG=~&GXH98zT_HY^`s?o z&!8nzbdA?Z=8oz0QN6>3YHiC6R*_XIHk(10%!0)xwpwod)+ydR>a;+WdEJjiZn4}B z$$_Gu+6ZO;O!hgje1|Q%5vb>fym!hzm2;6e%TzA@*74(?lWC-gH5E%mYWFfoEgcqV z*XcEo0Jezij5gPaK2uRICYzBb;5wceSp`XH<7(-XOiiPWK-u%sb7)1R2$I%ABIt`q z=KNphi&jzd5~OSzHbCBPQ@BwUe5Q31BtjifeRtAk$;~G1RhfHD^J`W=0;O;Jiw!ty z3o@0oLnLC0-mv<9=(d&?xZX)K-Zm~M!}j-W7B+u?Ol2zhP!`u2?_XunX9l-h^NLSw zfSymKPc-J=kdA1m6EZa`>XJUetn7xk&+d`zH+lV{&*Tn3hTq|RkalJ^4st;jZ4+_W z@s-Lf&6N5_TseQTNI(Hd#L}ihQq=fkNb}oRY3&vL3|Tqz3z6ONUlIXY#fs-0Db6$7 z+QrGH;Zrf)B!2;^JawX4#ekS(a`sud;Y%^m?EFehHcO7!fOBW?h-K1h!E$3qpJNRAaw zhLL8+_du-uWT6--J4}E6Ooibps5%HkymsS?tg9Wbqf*FbGy^E~JVW>LO0o4o( ze}$fA)eKd}Wxp2baF)oNIpH5hosJioltTGiw~PpEN3ntnMWD@PBZH6iIQw4dn~di^ z8(-yX`**%%%KvEXi!aR2F`in-Dw1o( zCSzQ(I)w#9Y-3dRE$3|CL>|wDiolYn9EQ!~Uoxc+q9-TwAF<}eaIHF+$81V-LRMb~ zB)+_!^#?rxM6qMb@Wi#l{I)l zgON*33^D9Et87FU-Lah1aW^D#3D$8r5;4swQDV@;gsYH*1dOPo!ALw}&0UCMGO;i> z8r&mFxv1!&-0#iwFs-+_+*Mtbuj^LFhCTyxIu-Mh~@wENJm z;JN4S+;i}py;mPRckiKd4p#3uxbt8zTyrRRZgqIi9wYvmuh|*ccUgUaGA`sNGfR&9 zt~Vx+`>Jd^j2DjkN+zmb_r+}n?<*>e+E1EDz3VHp6&|@c5;$^A;QB+? zAGzrZcl=8Kx^cTrztr&N>Gda{jl=Cnw;$y8OzZtUx(u(ogaovg_{a^$Umxdpjkh1&anq4o4u@4KRRQBmdHSa&w0u2iyCbNVIU|4B{<#|t zUVrHP?U&zig}x_$|Ni}Vd_})}V#Kbm*lpp7Z=S5b3pB|i@P{tocLNLTb|I>ufXe3O@dNZ`C?Yu2pT@LzE4BZ zjMWK!+Gu%DuPv$GxodaLp1tP;&)v8GqWS|Dlht^2Qor7lpNDG8%eQZ$IFX6F9@HPO z+5W*e@Q{9y?aqnY9@1l5^MgBfPI!K!A3QmhPnxcKe9{Z!_xofRx?%L6e9{6_==Kqx ztf0?99eOor5a3sMy*t9T#Rq&c0%2?pWE>fV#&jA@t~ukow%UL8$=WEk?;>Fw+P~|& zRw_|ezvq)>i2TGSozMrvFb*@Y0L!4Au1jLOF1?ky)Ssox>e;%CRO`~bTbHRCU7~w* zS%TnRT{@r-Mqqre@ts9|^PksWri*H@>X;}vq2*Ft>Kb)vhpv+(9Y6k@F5S=!6|jtt z9=f&t1DNP{ciNw+WAVy|67|RvbsrX zkS$=J@<|zlAPPe;1xZ+giidqt4=oUZ9+-hu@IK;`AauY8#9;wkkCGmuFbwfWeKA=? z(c)x)MhHU`dSM)9VFB!qQ6XrA2n@g!EP*^u9JD|;j6xii!Sz$0)IbQjVGI%=(>|%3 zj`^esr3=O&39cuo475Ne48k19&$y(Z9@?QB24D(i!Sy7*pc6(Q0ZZVYp#snVt0R_K9Yn1y9ILFC=U45cjxTgn$#cnNYzCinYu%h zrG8E3U-O9f4Ua6MhxQ?*SgPM~OArDBnzT-P_>h!a2KqFa{3_}H%9HlxihcdW&gRzK zl7wlnI#V?}ku&aoNqz0azItExNDUQCoxoS@M9!*SbW07iz2Xt=ut!!e^vD7vVIvUl z01f<51_7vqY*3YIZ1c$cUXKhN&}8*mkF;wZiGUeye|h!H*y^deILf%*2vx`iXoF4| z_#GEMa_%i|X=DOcz;PO5AJjt#`j2zbKg->P-VFl~hXq&#{}#qYaBb7m&#~FJeQDYJ zkj5BviAPp`qRGm?Q~8uzT;K&2R3lVqtk9Fb7FU!4j;1_&8nQg)*psDhNUyG(ao1wGIQ{V?c@ z=`xHm22(H%2}r^stbpjW2m(+Awa@@f5Q0`{gARy7H}t^(48sVF!X!+?EX+X?7GnHK z!6GcdGOU33X&q=#29;0+L8ymD2tg~fK?g*k8~R}gMqmskAr3Pz2T4f53dH0?T)p6j z08~OX1fdQZpcz`B9iq?!{V)WhFbUI;fFz_~306Qh;~%_G1{F{RL8#x%`ENuCK`XRD z1UjJ`dZ8bNU=+q-3P!l)R8UizN-jj3c_U0>&&)A3nL$?rs|vI0Jlo7P^JW@#zofQs z{?+_eg;g^`In}o6vMFulMnY$bln&MCs(>!2LstiC)M-LL*({(H{S;G=nCVGk>&fcG z)o=%?d06^MF+_yR%rK75mqycJCYynF&ZC=6lSR`WAk~_wGgTKyz-&Dc73gl$PY|7N zQKUmXx@PJFHqL*Md0-b^icQ^%UXn>KO=L)SX%~YG-B@bc!`OXh`X&WU}6&}M@5&@Ox=%t3!e^1hZZ8Xni-<#0aKsBQMsvCkU<4?T?}I1mOkQK zV&~g(=}?cJZl%K}lT=ih8yF>(Y(lEI7Noi`+tjh@&JNQMMXJzss&U@y`eyg+e`GtG zi}2LUa9#bo?1|xYa3^HL7|loQxJO!%{R<_sSRM07U?)?DK#|NJ z*2MmKO@cVh20IS?kUT>Z$A@tYN#d6+X|ick+ls{X$s*|`O$ZVn^+U} zxv?hUpJ_4#j@y_6;UgNudF8QES#(gd2Q{g@yhy5XlK4lj^t-6(>m?Fw@ksR{kA$e` z0=BN>nbX)p0U=tlbT*HBWSmET;23!ec!I*xc&Q9emdYUMywH2GCQWaa$UKksvPw-F zKcz`*?$gwYgEVD9HsVu0D&S2T%$(DGU)LVoClR!GtVwaoHb&eWvi zO6IfsNlQ6?q+F!Qm`cBc^B+E)^Fe~nAM21(3 z`PQRH#vzd?mMAl^vSV&(c!EOWq@y=_%D7ILrB!@clhMT@S>yBwjqtvlnWO8;XmikLHX?v$sIyjBvP`4#>VXLvC>6Ogbv9p0Ab=RjZ;6o=! zHF;CCm)KYwu)se{(nGg;h`qhOe&kByTW{(5)vMQ~KPDvK?qp+!sKLd|VEPG;)%|+V zl-HRuYRWH~@;0REj;|rrAnSjLK^3WrQG;>o%eryu+xlO`yg%TBEBEt3t!H`Ef1l;3 z+T=i=L8hSXe&(;pTI3Ki4tCNtjIc7DXF|mBJS>g*WKroqWMw(dG5Q!bFKI@RLF5c_ z3fR?_7LMzG#KM1?3`-EkSPNmCH^Cb8|A3`0acfj41zl9aMZt|Y>4kQvh0u?%O^_G* zf6USs*)Yj21acf1fL`c;C2YOG6jG+Y7xT#^g_d!!hHM}rii1w@HZk#G)NO3rBy)#1 z$;?9z3B(3iHMV}Ec;;uwWJHSxyj88kI>lLSzEn)wKQ~1vUr!>c%viy)!`bpSM1})Do3!D55bbbkK#2g`9(B^tj#6H$(k0hTcdI%wtc&Fm#Z=4O$@tQ=9xTNe~f-X_$do z7=8->&sfj%m&Z^xJSd0RE>gyv(;HL=4Udh z`pJ9K7?+*m_qppDa`_rcj4gI-s~^kRno2V1?4Qe3K4hk=VCI?)t)^}Htz6!4rf%-{ z+0tc%EM>HtdE*!7@P#rDsX23fNUvo^#e? z$wyC~Fkf$p@pOUeNQBe&ukFG;WXc6D29 zQ|~FFeB(lx9?n&NCf$6!&{DHR+T?R5SuAA3g4x|YmTp`zySBw*6L01;k6H4TWo(|N zi*m&Vy_r^E@iK+ahPs@2oFz*(G@Irck$#K0g$=}PuwIL3`wx&nCblW>>b7}gDjT@Z)&9Uw+>_)!GB)gzkf(C1= zPTm)MgN6SAk4&;QYed$A#)}gNa;%=U99td@$jC9?FR+FiJ3sSwrAd`yKDB!ByZop9 z#{SQa2XMUfryc(<{iQEENK=u^dKWW2LWE`snBi7ytI zrGetNXBl@E`L~>`R{!%)@&dtltjHfIV6(vgjPX*D|8%7Wo-y3T{?i>Vvp!;7YfnG? zjK*SrVF9M_bH-J~793+``)lLNDj|y_Szw`Le81Sg^(3{@3%#Nn&ldZ)=PPAhDSap( TEw6w6WMa5oyQ$rV8 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%0A(LO`FWy9 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 GEBWtRu@`>; delta 299304 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 -1un9sNa)5PH3N8ongR7>yX3);k^kxE>6D*f$oK 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%0D{^#ElmW)i>S@AuAUH*rZ8NbeqL7a%lV0eay_ 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

a(@L;yVXLTCvcMQCMHpK0VpW4ehUu6!#Uc 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 z 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

c24oyxj#U6M4;g_vL7HmuV4)!Or@SKM+K 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/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%0D(UFm4*qG52+oW}GTA?GOX;hVc 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 diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index dd3c5fc25..2009cf46a 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -123,6 +123,18 @@ android:windowSoftInputMode="adjustResize|stateHidden"> + + + + + + + + + + + + @@ -168,6 +180,8 @@ + + diff --git a/TMessagesProj/src/main/java/org/telegram/PhoneFormat/CallingCodeInfo.java b/TMessagesProj/src/main/java/org/telegram/PhoneFormat/CallingCodeInfo.java index 666d508a0..33a53fbf9 100644 --- a/TMessagesProj/src/main/java/org/telegram/PhoneFormat/CallingCodeInfo.java +++ b/TMessagesProj/src/main/java/org/telegram/PhoneFormat/CallingCodeInfo.java @@ -27,11 +27,11 @@ package org.telegram.PhoneFormat; import java.util.ArrayList; public class CallingCodeInfo { - public ArrayList countries = new ArrayList(); + public ArrayList countries = new ArrayList<>(); public String callingCode = ""; - public ArrayList trunkPrefixes = new ArrayList(); - public ArrayList intlPrefixes = new ArrayList(); - public ArrayList ruleSets = new ArrayList(); + public ArrayList trunkPrefixes = new ArrayList<>(); + public ArrayList intlPrefixes = new ArrayList<>(); + public ArrayList ruleSets = new ArrayList<>(); //public ArrayList formatStrings; String matchingAccessCode(String str) { @@ -107,14 +107,14 @@ public class CallingCodeInfo { for (RuleSet set : ruleSets) { boolean valid = set.isValid(str, intlPrefix, trunkPrefix, true); if (valid) { - return valid; + return true; } } for (RuleSet set : ruleSets) { boolean valid = set.isValid(str, intlPrefix, trunkPrefix, false); if (valid) { - return valid; + return true; } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java index 1e8111f08..17acc3426 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java @@ -8,19 +8,26 @@ package org.telegram.android; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; +import android.content.ContentUris; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.database.Cursor; import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Build; import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -39,6 +46,11 @@ import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; +import net.hockeyapp.android.CrashManager; +import net.hockeyapp.android.CrashManagerListener; +import net.hockeyapp.android.UpdateManager; + +import org.telegram.messenger.BuildVars; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; @@ -53,11 +65,20 @@ import org.telegram.ui.Components.ForegroundDetector; import org.telegram.ui.Components.NumberPicker; import org.telegram.ui.Components.TypefaceSpan; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.Hashtable; +import java.util.Locale; public class AndroidUtilities { @@ -159,7 +180,7 @@ public class AndroidUtilities { } public static boolean isWaitingForSms() { - boolean value = false; + boolean value; synchronized (smsLock) { value = waitingForSms; } @@ -575,11 +596,12 @@ public class AndroidUtilities { } } + @SuppressLint("NewApi") public static void clearDrawableAnimation(View view) { if (Build.VERSION.SDK_INT < 21 || view == null) { return; } - Drawable drawable = null; + Drawable drawable; if (view instanceof ListView) { drawable = ((ListView) view).getSelector(); if (drawable != null) { @@ -596,9 +618,9 @@ public class AndroidUtilities { public static Spannable replaceTags(String str) { try { - int start = -1; + int start; int startColor = -1; - int end = -1; + int end; StringBuilder stringBuilder = new StringBuilder(str); while ((start = stringBuilder.indexOf("
")) != -1) { stringBuilder.replace(start, start + 4, "\n"); @@ -608,7 +630,7 @@ public class AndroidUtilities { } ArrayList bolds = new ArrayList<>(); ArrayList colors = new ArrayList<>(); - while ((start = stringBuilder.indexOf("")) != -1 || (startColor = stringBuilder.indexOf("")) != -1 || (startColor = stringBuilder.indexOf(""); @@ -628,6 +650,7 @@ public class AndroidUtilities { colors.add(startColor); colors.add(end); colors.add(color); + startColor = -1; } } SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(stringBuilder); @@ -726,4 +749,290 @@ public class AndroidUtilities { window.clearFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); } }*/ + + public static void checkForCrashes(Activity context) { + CrashManager.register(context, BuildVars.HOCKEY_APP_HASH, new CrashManagerListener() { + @Override + public boolean includeDeviceData() { + return true; + } + }); + } + + public static void checkForUpdates(Activity context) { + if (BuildVars.DEBUG_VERSION) { + UpdateManager.register(context, BuildVars.HOCKEY_APP_HASH); + } + } + + public static void unregisterUpdates() { + if (BuildVars.DEBUG_VERSION) { + UpdateManager.unregister(); + } + } + + public static void addMediaToGallery(String fromPath) { + if (fromPath == null) { + return; + } + File f = new File(fromPath); + Uri contentUri = Uri.fromFile(f); + addMediaToGallery(contentUri); + } + + public static void addMediaToGallery(Uri uri) { + if (uri == null) { + return; + } + Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + mediaScanIntent.setData(uri); + ApplicationLoader.applicationContext.sendBroadcast(mediaScanIntent); + } + + private static File getAlbumDir() { + File storageDir = null; + if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { + storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Telegram"); + if (!storageDir.mkdirs()) { + if (!storageDir.exists()){ + FileLog.d("tmessages", "failed to create directory"); + return null; + } + } + } else { + FileLog.d("tmessages", "External storage is not mounted READ/WRITE."); + } + + return storageDir; + } + + @SuppressLint("NewApi") + public static String getPath(final Uri uri) { + try { + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + if (isKitKat && DocumentsContract.isDocumentUri(ApplicationLoader.applicationContext, uri)) { + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + } else if (isDownloadsDocument(uri)) { + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + return getDataColumn(ApplicationLoader.applicationContext, contentUri, null, null); + } else if (isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + switch (type) { + case "image": + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + break; + case "video": + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + break; + case "audio": + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + break; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[] { + split[1] + }; + + return getDataColumn(ApplicationLoader.applicationContext, contentUri, selection, selectionArgs); + } + } else if ("content".equalsIgnoreCase(uri.getScheme())) { + return getDataColumn(ApplicationLoader.applicationContext, uri, null, null); + } else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + return null; + } + + public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { + column + }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + if (cursor != null && cursor.moveToFirst()) { + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + public static File generatePicturePath() { + try { + File storageDir = getAlbumDir(); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()); + return new File(storageDir, "IMG_" + timeStamp + ".jpg"); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + return null; + } + + public static CharSequence generateSearchName(String name, String name2, String q) { + if (name == null && name2 == null) { + return ""; + } + SpannableStringBuilder builder = new SpannableStringBuilder(); + String wholeString = name; + if (wholeString == null || wholeString.length() == 0) { + wholeString = name2; + } else if (name2 != null && name2.length() != 0) { + wholeString += " " + name2; + } + wholeString = wholeString.trim(); + String lower = " " + wholeString.toLowerCase(); + + int index; + int lastIndex = 0; + while ((index = lower.indexOf(" " + q, lastIndex)) != -1) { + int idx = index - (index == 0 ? 0 : 1); + int end = q.length() + (index == 0 ? 0 : 1) + idx; + + if (lastIndex != 0 && lastIndex != idx + 1) { + builder.append(wholeString.substring(lastIndex, idx)); + } else if (lastIndex == 0 && idx != 0) { + builder.append(wholeString.substring(0, idx)); + } + + String query = wholeString.substring(idx, end); + if (query.startsWith(" ")) { + builder.append(" "); + } + query = query.trim(); + builder.append(AndroidUtilities.replaceTags("" + query + "")); + + lastIndex = end; + } + + if (lastIndex != -1 && lastIndex != wholeString.length()) { + builder.append(wholeString.substring(lastIndex, wholeString.length())); + } + + return builder; + } + + public static File generateVideoPath() { + try { + File storageDir = getAlbumDir(); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()); + return new File(storageDir, "VID_" + timeStamp + ".mp4"); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + return null; + } + + public static String formatFileSize(long size) { + if (size < 1024) { + return String.format("%d B", size); + } else if (size < 1024 * 1024) { + return String.format("%.1f KB", size / 1024.0f); + } else if (size < 1024 * 1024 * 1024) { + return String.format("%.1f MB", size / 1024.0f / 1024.0f); + } else { + return String.format("%.1f GB", size / 1024.0f / 1024.0f / 1024.0f); + } + } + + public static byte[] decodeQuotedPrintable(final byte[] bytes) { + if (bytes == null) { + return null; + } + final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + for (int i = 0; i < bytes.length; i++) { + final int b = bytes[i]; + if (b == '=') { + try { + final int u = Character.digit((char) bytes[++i], 16); + final int l = Character.digit((char) bytes[++i], 16); + buffer.write((char) ((u << 4) + l)); + } catch (Exception e) { + FileLog.e("tmessages", e); + return null; + } + } else { + buffer.write(b); + } + } + byte[] array = buffer.toByteArray(); + try { + buffer.close(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + return array; + } + + public static boolean copyFile(InputStream sourceFile, File destFile) throws IOException { + OutputStream out = new FileOutputStream(destFile); + byte[] buf = new byte[4096]; + int len; + while ((len = sourceFile.read(buf)) > 0) { + Thread.yield(); + out.write(buf, 0, len); + } + out.close(); + return true; + } + + public static boolean copyFile(File sourceFile, File destFile) throws IOException { + if (!destFile.exists()) { + destFile.createNewFile(); + } + FileInputStream source = null; + FileOutputStream destination = null; + try { + source = new FileInputStream(sourceFile); + destination = new FileOutputStream(destFile); + destination.getChannel().transferFrom(source.getChannel(), 0, source.getChannel().size()); + } catch (Exception e) { + FileLog.e("tmessages", e); + return false; + } finally { + if (source != null) { + source.close(); + } + if (destination != null) { + destination.close(); + } + } + return true; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/AutoMessageHeardReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/AutoMessageHeardReceiver.java new file mode 100644 index 000000000..825bcd565 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/AutoMessageHeardReceiver.java @@ -0,0 +1,26 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.android; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class AutoMessageHeardReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + long dialog_id = intent.getLongExtra("dialog_id", 0); + int max_id = intent.getIntExtra("max_id", 0); + if (dialog_id == 0 || max_id == 0) { + return; + } + MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, 0, true, false); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/AutoMessageReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/AutoMessageReplyReceiver.java new file mode 100644 index 000000000..c8411de73 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/AutoMessageReplyReceiver.java @@ -0,0 +1,37 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2014. + */ + +package org.telegram.android; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.RemoteInput; + +public class AutoMessageReplyReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); + if (remoteInput == null) { + return; + } + CharSequence text = remoteInput.getCharSequence(NotificationsController.EXTRA_VOICE_REPLY); + if (text == null || text.length() == 0) { + return; + } + long dialog_id = intent.getLongExtra("dialog_id", 0); + int max_id = intent.getIntExtra("max_id", 0); + if (dialog_id == 0 || max_id == 0) { + return; + } + SendMessagesHelper.getInstance().sendMessage(text.toString(), dialog_id, null, null, true); + MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, 0, true, false); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/Emoji.java b/TMessagesProj/src/main/java/org/telegram/android/Emoji.java index 312c78488..988a94b9e 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/android/Emoji.java @@ -221,7 +221,7 @@ public class Emoji { private static void loadEmoji(final int page) { try { - float scale = 1.0f; + float scale; int imageResize = 1; if (AndroidUtilities.density <= 1.0f) { scale = 2.0f; @@ -257,7 +257,7 @@ public class Emoji { imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); if (!imageFile.exists()) { InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + imageName); - Utilities.copyFile(is, imageFile); + AndroidUtilities.copyFile(is, imageFile); is.close(); } @@ -276,7 +276,7 @@ public class Emoji { imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); if (!imageFile.exists()) { InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + imageName); - Utilities.copyFile(is, imageFile); + AndroidUtilities.copyFile(is, imageFile); is.close(); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java index 2cc360353..9bbefe8e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java @@ -67,11 +67,12 @@ public class ImageLoader { private DispatchQueue cacheThumbOutQueue = new DispatchQueue("cacheThumbOutQueue"); private DispatchQueue thumbGeneratingQueue = new DispatchQueue("thumbGeneratingQueue"); private DispatchQueue imageLoadQueue = new DispatchQueue("imageLoadQueue"); - private DispatchQueue recycleQueue = new DispatchQueue("recycleQueue"); private ConcurrentHashMap fileProgresses = new ConcurrentHashMap<>(); private HashMap thumbGenerateTasks = new HashMap<>(); private static byte[] bytes; private static byte[] bytesThumb; + private static byte[] header = new byte[12]; + private static byte[] headerThumb = new byte[12]; private int currentHttpTasksCount = 0; private LinkedList httpFileLoadTasks = new LinkedList<>(); @@ -116,8 +117,24 @@ public class ImageLoader { try { URL downloadUrl = new URL(url); httpConnection = downloadUrl.openConnection(); + httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/_BuildID_) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36"); + httpConnection.addRequestProperty("Referer", "google.com"); httpConnection.setConnectTimeout(5000); httpConnection.setReadTimeout(5000); + if (httpConnection instanceof HttpURLConnection) { + HttpURLConnection httpURLConnection = (HttpURLConnection) httpConnection; + httpURLConnection.setInstanceFollowRedirects(true); + int status = httpURLConnection.getResponseCode(); + if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM || status == HttpURLConnection.HTTP_SEE_OTHER) { + String newUrl = httpURLConnection.getHeaderField("Location"); + String cookies = httpURLConnection.getHeaderField("Set-Cookie"); + downloadUrl = new URL(newUrl); + httpConnection = downloadUrl.openConnection(); + httpConnection.setRequestProperty("Cookie", cookies); + httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/_BuildID_) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36"); + httpConnection.addRequestProperty("Referer", "google.com"); + } + } httpConnection.connect(); httpConnectionStream = httpConnection.getInputStream(); @@ -137,29 +154,31 @@ public class ImageLoader { FileLog.e("tmessages", e); } - try { - byte[] data = new byte[1024 * 4]; - while (true) { - if (isCancelled()) { - break; - } - try { - int readed = httpConnectionStream.read(data); - if (readed > 0) { - fileOutputStream.write(data, 0, readed); - } else if (readed == -1) { - done = true; - break; - } else { + if (httpConnectionStream != null) { + try { + byte[] data = new byte[1024 * 4]; + while (true) { + if (isCancelled()) { + break; + } + try { + int read = httpConnectionStream.read(data); + if (read > 0) { + fileOutputStream.write(data, 0, read); + } else if (read == -1) { + done = true; + break; + } else { + break; + } + } catch (Exception e) { + FileLog.e("tmessages", e); break; } - } catch (Exception e) { - FileLog.e("tmessages", e); - break; } + } catch (Throwable e) { + FileLog.e("tmessages", e); } - } catch (Throwable e) { - FileLog.e("tmessages", e); } try { @@ -175,7 +194,6 @@ public class ImageLoader { if (httpConnectionStream != null) { httpConnectionStream.close(); } - httpConnectionStream = null; } catch (Throwable e) { FileLog.e("tmessages", e); } @@ -235,12 +253,16 @@ public class ImageLoader { try { URL downloadUrl = new URL(cacheImage.httpUrl); httpConnection = downloadUrl.openConnection(); + httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/_BuildID_) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36"); + httpConnection.addRequestProperty("Referer", "google.com"); httpConnection.setConnectTimeout(5000); httpConnection.setReadTimeout(5000); + if (httpConnection instanceof HttpURLConnection) { + ((HttpURLConnection) httpConnection).setInstanceFollowRedirects(true); + } if (!isCancelled()) { httpConnection.connect(); httpConnectionStream = httpConnection.getInputStream(); - fileOutputStream = new RandomAccessFile(cacheImage.tempFilePath, "rws"); } } catch (Throwable e) { @@ -260,37 +282,39 @@ public class ImageLoader { FileLog.e("tmessages", e); } - try { - byte[] data = new byte[1024 * 2]; - int totalLoaded = 0; - while (true) { - if (isCancelled()) { - break; - } - try { - int readed = httpConnectionStream.read(data); - if (readed > 0) { - totalLoaded += readed; - fileOutputStream.write(data, 0, readed); - if (imageSize != 0) { - reportProgress(totalLoaded / (float) imageSize); - } - } else if (readed == -1) { - done = true; - if (imageSize != 0) { - reportProgress(1.0f); - } - break; - } else { + if (httpConnectionStream != null) { + try { + byte[] data = new byte[1024 * 2]; + int totalLoaded = 0; + while (true) { + if (isCancelled()) { + break; + } + try { + int read = httpConnectionStream.read(data); + if (read > 0) { + totalLoaded += read; + fileOutputStream.write(data, 0, read); + if (imageSize != 0) { + reportProgress(totalLoaded / (float) imageSize); + } + } else if (read == -1) { + done = true; + if (imageSize != 0) { + reportProgress(1.0f); + } + break; + } else { + break; + } + } catch (Exception e) { + FileLog.e("tmessages", e); break; } - } catch (Exception e) { - FileLog.e("tmessages", e); - break; } + } catch (Throwable e) { + FileLog.e("tmessages", e); } - } catch (Throwable e) { - FileLog.e("tmessages", e); } } @@ -307,7 +331,6 @@ public class ImageLoader { if (httpConnectionStream != null) { httpConnectionStream.close(); } - httpConnectionStream = null; } catch (Throwable e) { FileLog.e("tmessages", e); } @@ -446,7 +469,6 @@ public class ImageLoader { Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, (int) (w / scaleFactor), (int) (h / scaleFactor), true); if (scaledBitmap != originalBitmap) { originalBitmap.recycle(); - callGC(); } originalBitmap = scaledBitmap; FileOutputStream stream = new FileOutputStream(thumbFile); @@ -513,14 +535,41 @@ public class ImageLoader { Bitmap image = null; File cacheFileFinal = cacheImage.finalFilePath; boolean canDeleteFile = true; - boolean isWebp = false; + boolean useNativeWebpLoaded = false; - if (cacheFileFinal.toString().endsWith("webp")) { - isWebp = true; + if (Build.VERSION.SDK_INT < 18) { + RandomAccessFile randomAccessFile = null; + try { + randomAccessFile = new RandomAccessFile(cacheFileFinal, "r"); + byte[] bytes; + if (cacheImage.thumb) { + bytes = headerThumb; + } else { + bytes = header; + } + randomAccessFile.readFully(bytes, 0, bytes.length); + String str = new String(bytes); + if (str != null) { + str = str.toLowerCase(); + if (str.startsWith("riff") && str.endsWith("webp")) { + useNativeWebpLoaded = true; + } + } + randomAccessFile.close(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } finally { + if (randomAccessFile != null) { + try { + randomAccessFile.close(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } } if (cacheImage.thumb) { - int blurType = 0; if (cacheImage.filter != null) { if (cacheImage.filter.contains("b2")) { @@ -543,11 +592,11 @@ public class ImageLoader { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 1; - if (!isWebp && Build.VERSION.SDK_INT > 10 && Build.VERSION.SDK_INT < 21) { + if (!useNativeWebpLoaded && Build.VERSION.SDK_INT > 10 && Build.VERSION.SDK_INT < 21) { opts.inPurgeable = true; } - if (isWebp) { + if (useNativeWebpLoaded) { RandomAccessFile file = new RandomAccessFile(cacheFileFinal, "r"); ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, cacheFileFinal.length()); image = Utilities.loadWebpImage(buffer, buffer.limit(), null); @@ -570,20 +619,18 @@ public class ImageLoader { } if (image == null) { - if (canDeleteFile && (cacheFileFinal.length() == 0 || cacheImage.filter == null)) { + if (cacheFileFinal.length() == 0 || cacheImage.filter == null) { cacheFileFinal.delete(); } } else { - if (image != null) { - if (blurType == 1) { - Utilities.blurBitmap(image, 3, opts.inPurgeable ? 0 : 1); - } else if (blurType == 2) { - Utilities.blurBitmap(image, 1, opts.inPurgeable ? 0 : 1); - } else if (blurType == 3) { - Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); - Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); - Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); - } + if (blurType == 1) { + Utilities.blurBitmap(image, 3, opts.inPurgeable ? 0 : 1); + } else if (blurType == 2) { + Utilities.blurBitmap(image, 1, opts.inPurgeable ? 0 : 1); + } else if (blurType == 3) { + Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); + Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); + Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); } if (blurType == 0 && opts.inPurgeable) { Utilities.pinBitmap(image); @@ -685,7 +732,7 @@ public class ImageLoader { } else { opts.inPreferredConfig = Bitmap.Config.RGB_565; } - if (!isWebp && Build.VERSION.SDK_INT > 10 && Build.VERSION.SDK_INT < 21) { + if (!useNativeWebpLoaded && Build.VERSION.SDK_INT > 10 && Build.VERSION.SDK_INT < 21) { opts.inPurgeable = true; } @@ -698,7 +745,7 @@ public class ImageLoader { } } if (image == null) { - if (isWebp) { + if (useNativeWebpLoaded) { RandomAccessFile file = new RandomAccessFile(cacheFileFinal, "r"); ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, cacheFileFinal.length()); image = Utilities.loadWebpImage(buffer, buffer.limit(), null); @@ -734,7 +781,6 @@ public class ImageLoader { Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, (int) w_filter, (int) (bitmapH / scaleFactor), true); if (image != scaledBitmap) { image.recycle(); - callGC(); image = scaledBitmap; } } @@ -746,7 +792,7 @@ public class ImageLoader { if (!blured && opts.inPurgeable) { Utilities.pinBitmap(image); } - if (runtimeHack != null) { + if (runtimeHack != null && image != null) { runtimeHack.trackFree(image.getRowBytes() * image.getHeight()); } } @@ -774,7 +820,6 @@ public class ImageLoader { runtimeHack.trackAlloc(image.getRowBytes() * image.getHeight()); } image.recycle(); - callGC(); } } final BitmapDrawable toSetFinal = toSet; @@ -853,6 +898,7 @@ public class ImageLoader { protected String key; protected String url; protected String filter; + protected String ext; protected TLObject location; protected File finalFilePath; @@ -897,7 +943,7 @@ public class ImageLoader { imageReceiverArray.clear(); if (location != null) { if (location instanceof TLRPC.FileLocation) { - FileLoader.getInstance().cancelLoadFile((TLRPC.FileLocation) location); + FileLoader.getInstance().cancelLoadFile((TLRPC.FileLocation) location, ext); } else if (location instanceof TLRPC.Document) { FileLoader.getInstance().cancelLoadFile((TLRPC.Document) location); } @@ -1019,11 +1065,16 @@ public class ImageLoader { } @Override - public void fileDidUploaded(final String location, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile) { + public void fileDidUploaded(final String location, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv) { Utilities.stageQueue.postRunnable(new Runnable() { @Override public void run() { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidUpload, location, inputFile, inputEncryptedFile); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidUpload, location, inputFile, inputEncryptedFile, key, iv); + } + }); fileProgresses.remove(location); } }); @@ -1034,7 +1085,12 @@ public class ImageLoader { Utilities.stageQueue.postRunnable(new Runnable() { @Override public void run() { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidFailUpload, location, isEncrypted); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidFailUpload, location, isEncrypted); + } + }); fileProgresses.remove(location); } }); @@ -1049,7 +1105,7 @@ public class ImageLoader { if (location != null) { if (MediaController.getInstance().canSaveToGallery() && telegramPath != null && finalFile != null && finalFile.exists() && (location.endsWith(".mp4") || location.endsWith(".jpg"))) { if (finalFile.toString().startsWith(telegramPath.toString())) { - Utilities.addMediaToGallery(finalFile.toString()); + AndroidUtilities.addMediaToGallery(finalFile.toString()); } } } @@ -1250,17 +1306,6 @@ public class ImageLoader { } } - public void callGC() { - if (Build.VERSION.SDK_INT > 13) { - recycleQueue.postRunnable(new Runnable() { - @Override - public void run() { - //System.gc(); - } - }); - } - } - public boolean decrementUseCount(String key) { Integer count = bitmapUseCounts.get(key); if (count == null) { @@ -1394,7 +1439,7 @@ public class ImageLoader { } } - private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiver, final String key, final String url, final TLObject imageLocation, final String httpLocation, final String filter, final int size, final boolean cacheOnly, final int thumb) { + private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiver, final String key, final String url, final String ext, final TLObject imageLocation, final String httpLocation, final String filter, final int size, final boolean cacheOnly, final int thumb) { if (imageReceiver == null || url == null || key == null) { return; } @@ -1510,6 +1555,7 @@ public class ImageLoader { img.key = key; img.filter = filter; img.httpUrl = httpLocation; + img.ext = ext; img.addImageReceiver(imageReceiver); if (onlyCache || cacheFile.exists()) { img.finalFilePath = cacheFile; @@ -1527,7 +1573,7 @@ public class ImageLoader { if (httpLocation == null) { if (imageLocation instanceof TLRPC.FileLocation) { TLRPC.FileLocation location = (TLRPC.FileLocation) imageLocation; - FileLoader.getInstance().loadFile(location, size, size == 0 || location.key != null || cacheOnly); + FileLoader.getInstance().loadFile(location, ext, size, size == 0 || location.key != null || cacheOnly); } else if (imageLocation instanceof TLRPC.Document) { FileLoader.getInstance().loadFile((TLRPC.Document) imageLocation, true, true); } @@ -1584,7 +1630,10 @@ public class ImageLoader { String thumbUrl = null; key = null; thumbKey = null; - String ext = null; + String ext = imageReceiver.getExt(); + if (ext == null) { + ext = "jpg"; + } if (httpLocation != null) { key = Utilities.MD5(httpLocation); url = key + "." + getHttpUrlExtension(httpLocation); @@ -1592,9 +1641,8 @@ public class ImageLoader { if (imageLocation instanceof TLRPC.FileLocation) { TLRPC.FileLocation location = (TLRPC.FileLocation) imageLocation; key = location.volume_id + "_" + location.local_id; - ext = "." + (location.ext != null ? location.ext : "jpg"); - url = key + ext; - if (location.ext != null || location.key != null || location.volume_id == Integer.MIN_VALUE && location.local_id < 0) { + url = key + "." + ext; + if (imageReceiver.getExt() != null || location.key != null || location.volume_id == Integer.MIN_VALUE && location.local_id < 0) { saveImageToCache = true; } } else if (imageLocation instanceof TLRPC.Document) { @@ -1603,10 +1651,19 @@ public class ImageLoader { return; } key = location.dc_id + "_" + location.id; - ext = ".webp"; - url = key + ext; + String docExt = FileLoader.getDocumentFileName(location); + int idx; + if (docExt == null || (idx = docExt.lastIndexOf(".")) == -1) { + docExt = ""; + } else { + docExt = docExt.substring(idx); + if (docExt.length() <= 1) { + docExt = ""; + } + } + url = key + docExt; if (thumbKey != null) { - thumbUrl = thumbKey + ext; + thumbUrl = thumbKey + "." + ext; } saveImageToCache = true; } @@ -1619,11 +1676,7 @@ public class ImageLoader { if (thumbLocation != null) { thumbKey = thumbLocation.volume_id + "_" + thumbLocation.local_id; - if (ext != null) { - thumbUrl = thumbKey + ext; - } else { - thumbUrl = thumbKey + "." + (thumbLocation.ext != null ? thumbLocation.ext : "jpg"); - } + thumbUrl = thumbKey + "." + ext; } String filter = imageReceiver.getFilter(); @@ -1636,10 +1689,10 @@ public class ImageLoader { } if (httpLocation != null) { - createLoadOperationForImageReceiver(imageReceiver, key, url, null, httpLocation, filter, 0, true, 0); + createLoadOperationForImageReceiver(imageReceiver, key, url, ext, null, httpLocation, filter, 0, true, 0); } else { - createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, thumbLocation, null, thumbFilter, 0, true, thumbSet ? 2 : 1); - createLoadOperationForImageReceiver(imageReceiver, key, url, imageLocation, null, filter, imageReceiver.getSize(), saveImageToCache || imageReceiver.getCacheOnly(), 0); + createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, ext, thumbLocation, null, thumbFilter, 0, true, thumbSet ? 2 : 1); + createLoadOperationForImageReceiver(imageReceiver, key, url, ext, imageLocation, null, filter, imageReceiver.getSize(), saveImageToCache || imageReceiver.getCacheOnly(), 0); } } @@ -1682,6 +1735,7 @@ public class ImageLoader { cacheImage.key = img.key; cacheImage.httpUrl = img.httpUrl; cacheImage.thumb = img.thumb; + cacheImage.ext = img.ext; cacheImage.cacheTask = task = new CacheOutTask(cacheImage); cacheImage.filter = img.filter; imageLoadingByKeys.put(cacheImage.key, cacheImage); @@ -1821,7 +1875,7 @@ public class ImageLoader { path = uri.getPath(); } else { try { - path = Utilities.getPath(uri); + path = AndroidUtilities.getPath(uri); } catch (Throwable e) { FileLog.e("tmessages", e); } @@ -1861,7 +1915,7 @@ public class ImageLoader { if (path != null) { exifPath = path; } else if (uri != null) { - exifPath = Utilities.getPath(uri); + exifPath = AndroidUtilities.getPath(uri); } Matrix matrix = null; @@ -1919,9 +1973,7 @@ public class ImageLoader { FileLog.e("tmessages", e); } finally { try { - if (parcelFD != null) { - parcelFD.close(); - } + parcelFD.close(); } catch (Throwable e) { FileLog.e("tmessages", e); } @@ -1931,8 +1983,25 @@ public class ImageLoader { return b; } + public static void fillPhotoSizeWithBytes(TLRPC.PhotoSize photoSize) { + if (photoSize == null || photoSize.bytes != null) { + return; + } + File file = FileLoader.getPathToAttach(photoSize, true); + try { + RandomAccessFile f = new RandomAccessFile(file, "r"); + int len = (int) f.length(); + if (len < 20000) { + photoSize.bytes = new byte[(int) f.length()]; + f.readFully(photoSize.bytes, 0, photoSize.bytes.length); + } + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + } + private static TLRPC.PhotoSize scaleAndSaveImageInternal(Bitmap bitmap, int w, int h, float photoW, float photoH, float scaleFactor, int quality, boolean cache, boolean scaleAnyway) throws Exception { - Bitmap scaledBitmap = null; + Bitmap scaledBitmap; if (scaleFactor > 1 || scaleAnyway) { scaledBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true); } else { @@ -2055,12 +2124,6 @@ public class ImageLoader { } else if (message.media instanceof TLRPC.TL_messageMediaDocument) { if (message.media.document.thumb instanceof TLRPC.TL_photoCachedSize) { photoSize = message.media.document.thumb; - for (TLRPC.DocumentAttribute attribute : message.media.document.attributes) { - if (attribute instanceof TLRPC.TL_documentAttributeSticker) { - photoSize.location.ext = "webp"; - break; - } - } } } else if (message.media instanceof TLRPC.TL_messageMediaWebPage) { if (message.media.webpage.photo != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java index 1d0eb8b4c..b73778a24 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java @@ -43,6 +43,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg public String thumbFilter; public int size; public boolean cacheOnly; + public String ext; } private View parentView; @@ -59,6 +60,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private String currentHttpUrl; private String currentFilter; private String currentThumbFilter; + private String currentExt; private TLRPC.FileLocation currentThumbLocation; private int currentSize; private boolean currentCacheOnly; @@ -68,6 +70,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private boolean needsQualityThumb; private boolean shouldGenerateQualityThumb; + private boolean invalidateAll; private int imageX, imageY, imageW, imageH; private Rect drawRegion = new Rect(); @@ -104,27 +107,27 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg canceledLoading = true; } - public void setImage(TLObject path, String filter, Drawable thumb, boolean cacheOnly) { - setImage(path, null, filter, thumb, null, null, 0, cacheOnly); + public void setImage(TLObject path, String filter, Drawable thumb, String ext, boolean cacheOnly) { + setImage(path, null, filter, thumb, null, null, 0, ext, cacheOnly); } - public void setImage(TLObject path, String filter, Drawable thumb, int size, boolean cacheOnly) { - setImage(path, null, filter, thumb, null, null, size, cacheOnly); + public void setImage(TLObject path, String filter, Drawable thumb, int size, String ext, boolean cacheOnly) { + setImage(path, null, filter, thumb, null, null, size, ext, cacheOnly); } - public void setImage(String httpUrl, String filter, Drawable thumb, int size) { - setImage(null, httpUrl, filter, thumb, null, null, size, true); + public void setImage(String httpUrl, String filter, Drawable thumb, String ext, int size) { + setImage(null, httpUrl, filter, thumb, null, null, size, ext, true); } - public void setImage(TLObject fileLocation, String filter, TLRPC.FileLocation thumbLocation, String thumbFilter, boolean cacheOnly) { - setImage(fileLocation, null, filter, null, thumbLocation, thumbFilter, 0, cacheOnly); + public void setImage(TLObject fileLocation, String filter, TLRPC.FileLocation thumbLocation, String thumbFilter, String ext, boolean cacheOnly) { + setImage(fileLocation, null, filter, null, thumbLocation, thumbFilter, 0, ext, cacheOnly); } - public void setImage(TLObject fileLocation, String filter, TLRPC.FileLocation thumbLocation, String thumbFilter, int size, boolean cacheOnly) { - setImage(fileLocation, null, filter, null, thumbLocation, thumbFilter, size, cacheOnly); + public void setImage(TLObject fileLocation, String filter, TLRPC.FileLocation thumbLocation, String thumbFilter, int size, String ext, boolean cacheOnly) { + setImage(fileLocation, null, filter, null, thumbLocation, thumbFilter, size, ext, cacheOnly); } - public void setImage(TLObject fileLocation, String httpUrl, String filter, Drawable thumb, TLRPC.FileLocation thumbLocation, String thumbFilter, int size, boolean cacheOnly) { + public void setImage(TLObject fileLocation, String httpUrl, String filter, Drawable thumb, TLRPC.FileLocation thumbLocation, String thumbFilter, int size, String ext, boolean cacheOnly) { if (setImageBackup != null) { setImageBackup.fileLocation = null; setImageBackup.httpUrl = null; @@ -139,6 +142,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg recycleBitmap(null, false); recycleBitmap(null, true); currentKey = null; + currentExt = ext; currentThumbKey = null; currentThumbFilter = null; currentImageLocation = null; @@ -153,7 +157,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg bitmapShader = null; ImageLoader.getInstance().cancelLoadingForImageReceiver(this, 0); if (parentView != null) { - parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } } if (delegate != null) { delegate.didSetImage(this, currentImage != null || currentThumb != null || staticThumb != null, currentImage == null); @@ -207,6 +215,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentThumbKey = thumbKey; currentKey = key; + currentExt = ext; currentImageLocation = fileLocation; currentHttpUrl = httpUrl; currentFilter = filter; @@ -224,7 +233,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ImageLoader.getInstance().loadImageForImageReceiver(this); if (parentView != null) { - parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } } } @@ -249,6 +262,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg centerRotation = center; } + public void setInvalidateAll(boolean value) { + invalidateAll = value; + } + public int getOrientation() { return orientation; } @@ -264,6 +281,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg staticThumb = bitmap; currentThumbLocation = null; currentKey = null; + currentExt = null; currentThumbKey = null; currentImage = null; currentThumbFilter = null; @@ -284,7 +302,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg delegate.didSetImage(this, currentImage != null || currentThumb != null || staticThumb != null, currentImage == null); } if (parentView != null) { - parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } } } @@ -309,6 +331,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg setImageBackup.thumbLocation = currentThumbLocation; setImageBackup.thumbFilter = currentThumbFilter; setImageBackup.size = currentSize; + setImageBackup.ext = currentExt; setImageBackup.cacheOnly = currentCacheOnly; } NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didReplacedPhotoInMemCache); @@ -318,7 +341,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg public boolean onAttachedToWindow() { NotificationCenter.getInstance().addObserver(this, NotificationCenter.didReplacedPhotoInMemCache); if (setImageBackup != null && (setImageBackup.fileLocation != null || setImageBackup.httpUrl != null || setImageBackup.thumbLocation != null || setImageBackup.thumb != null)) { - setImage(setImageBackup.fileLocation, setImageBackup.httpUrl, setImageBackup.filter, setImageBackup.thumb, setImageBackup.thumbLocation, setImageBackup.thumbFilter, setImageBackup.size, setImageBackup.cacheOnly); + setImage(setImageBackup.fileLocation, setImageBackup.httpUrl, setImageBackup.filter, setImageBackup.thumb, setImageBackup.thumbLocation, setImageBackup.thumbFilter, setImageBackup.size, setImageBackup.ext, setImageBackup.cacheOnly); return true; } return false; @@ -332,10 +355,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg boolean hasFilter = paint != null && paint.getColorFilter() != null; if (hasFilter && !isPressed) { bitmapDrawable.setColorFilter(null); - hasFilter = false; } else if (!hasFilter && isPressed) { bitmapDrawable.setColorFilter(new PorterDuffColorFilter(0xffdddddd, PorterDuff.Mode.MULTIPLY)); - hasFilter = true; } if (colorFilter != null) { bitmapDrawable.setColorFilter(colorFilter); @@ -353,8 +374,6 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } else { int bitmapW; int bitmapH; - int originalW = bitmapDrawable.getIntrinsicWidth(); - int originalH = bitmapDrawable.getIntrinsicHeight(); if (orientation == 90 || orientation == 270) { bitmapW = bitmapDrawable.getIntrinsicHeight(); bitmapH = bitmapDrawable.getIntrinsicWidth(); @@ -383,7 +402,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ImageLoader.getInstance().removeImage(currentThumbKey); currentThumbKey = null; } - setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentCacheOnly); + setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentCacheOnly); FileLog.e("tmessages", e); } canvas.restore(); @@ -402,11 +421,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (bitmapW / scaleH > imageW) { bitmapW /= scaleH; - originalW /= scaleH; drawRegion.set(imageX - (bitmapW - imageW) / 2, imageY, imageX + (bitmapW + imageW) / 2, imageY + imageH); } else { bitmapH /= scaleW; - originalH /= scaleW; drawRegion.set(imageX, imageY - (bitmapH - imageH) / 2, imageX + imageW, imageY + (bitmapH + imageH) / 2); } if (orientation == 90 || orientation == 270) { @@ -430,7 +447,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ImageLoader.getInstance().removeImage(currentThumbKey); currentThumbKey = null; } - setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentCacheOnly); + setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentCacheOnly); FileLog.e("tmessages", e); } } @@ -467,7 +484,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ImageLoader.getInstance().removeImage(currentThumbKey); currentThumbKey = null; } - setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentCacheOnly); + setImage(currentImageLocation, currentHttpUrl, currentFilter, currentThumb, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentCacheOnly); FileLog.e("tmessages", e); } } @@ -498,7 +515,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } lastUpdateAlphaTime = System.currentTimeMillis(); if (parentView != null) { - parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } } } } @@ -577,7 +598,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } isVisible = value; if (invalidate && parentView != null) { - parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } } } @@ -636,6 +661,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return imageH; } + public String getExt() { + return currentExt; + } + public boolean isInsideImage(float x, float y) { return x >= imageX && x <= imageX + imageW && y >= imageY && y <= imageY + imageH; } @@ -782,7 +811,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } if (parentView != null) { - parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } } } else if (currentThumb == null && (currentImage == null || forcePreview)) { if (currentThumbKey == null || !key.equals(currentThumbKey)) { @@ -801,7 +834,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } if (!(staticThumb instanceof BitmapDrawable) && parentView != null) { - parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } } } @@ -841,7 +878,6 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } if (canDelete) { bitmap.recycle(); - ImageLoader.getInstance().callGC(); } } if (thumb) { @@ -866,7 +902,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg staticThumb = null; } if (parentView != null) { - parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } } } } else if (id == NotificationCenter.didReplacedPhotoInMemCache) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/android/LocaleController.java index 5e82e4070..cf89fe20f 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/LocaleController.java @@ -23,7 +23,6 @@ import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; -import org.telegram.messenger.Utilities; import org.telegram.messenger.ApplicationLoader; import org.xmlpull.v1.XmlPullParser; @@ -359,7 +358,7 @@ public class LocaleController { } File finalFile = new File(ApplicationLoader.applicationContext.getFilesDir(), languageCode + ".xml"); - if (!Utilities.copyFile(file, finalFile)) { + if (!AndroidUtilities.copyFile(file, finalFile)) { return false; } @@ -494,7 +493,6 @@ public class LocaleController { try { if (stream != null) { stream.close(); - stream = null; } } catch (Exception e) { FileLog.e("tmessages", e); @@ -512,7 +510,7 @@ public class LocaleController { return; } try { - Locale newLocale = null; + Locale newLocale; if (localeInfo.shortName != null) { String[] args = localeInfo.shortName.split("_"); if (args.length == 1) { @@ -682,50 +680,60 @@ public class LocaleController { } public static String formatDate(long date) { - Calendar rightNow = Calendar.getInstance(); - int day = rightNow.get(Calendar.DAY_OF_YEAR); - int year = rightNow.get(Calendar.YEAR); - rightNow.setTimeInMillis(date * 1000); - int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); - int dateYear = rightNow.get(Calendar.YEAR); + try { + Calendar rightNow = Calendar.getInstance(); + int day = rightNow.get(Calendar.DAY_OF_YEAR); + int year = rightNow.get(Calendar.YEAR); + rightNow.setTimeInMillis(date * 1000); + int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); + int dateYear = rightNow.get(Calendar.YEAR); - if (dateDay == day && year == dateYear) { - return formatterDay.format(new Date(date * 1000)); - } else if (dateDay + 1 == day && year == dateYear) { - return getString("Yesterday", R.string.Yesterday); - } else if (year == dateYear) { - return formatterMonth.format(new Date(date * 1000)); - } else { - return formatterYear.format(new Date(date * 1000)); + if (dateDay == day && year == dateYear) { + return formatterDay.format(new Date(date * 1000)); + } else if (dateDay + 1 == day && year == dateYear) { + return getString("Yesterday", R.string.Yesterday); + } else if (year == dateYear) { + return formatterMonth.format(new Date(date * 1000)); + } else { + return formatterYear.format(new Date(date * 1000)); + } + } catch (Exception e) { + FileLog.e("tmessages", e); } + return "LOC_ERR"; } public static String formatDateOnline(long date) { - Calendar rightNow = Calendar.getInstance(); - int day = rightNow.get(Calendar.DAY_OF_YEAR); - int year = rightNow.get(Calendar.YEAR); - rightNow.setTimeInMillis(date * 1000); - int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); - int dateYear = rightNow.get(Calendar.YEAR); + try { + Calendar rightNow = Calendar.getInstance(); + int day = rightNow.get(Calendar.DAY_OF_YEAR); + int year = rightNow.get(Calendar.YEAR); + rightNow.setTimeInMillis(date * 1000); + int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); + int dateYear = rightNow.get(Calendar.YEAR); - if (dateDay == day && year == dateYear) { - return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("TodayAt", R.string.TodayAt), formatterDay.format(new Date(date * 1000))); - } else if (dateDay + 1 == day && year == dateYear) { - return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("YesterdayAt", R.string.YesterdayAt), formatterDay.format(new Date(date * 1000))); - } else if (year == dateYear) { - String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, formatterMonth.format(new Date(date * 1000)), formatterDay.format(new Date(date * 1000))); - return String.format("%s %s", LocaleController.getString("LastSeenDate", R.string.LastSeenDate), format); - } else { - String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, formatterYear.format(new Date(date * 1000)), formatterDay.format(new Date(date * 1000))); - return String.format("%s %s", LocaleController.getString("LastSeenDate", R.string.LastSeenDate), format); + if (dateDay == day && year == dateYear) { + return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("TodayAt", R.string.TodayAt), formatterDay.format(new Date(date * 1000))); + } else if (dateDay + 1 == day && year == dateYear) { + return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("YesterdayAt", R.string.YesterdayAt), formatterDay.format(new Date(date * 1000))); + } else if (year == dateYear) { + String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, formatterMonth.format(new Date(date * 1000)), formatterDay.format(new Date(date * 1000))); + return String.format("%s %s", LocaleController.getString("LastSeenDate", R.string.LastSeenDate), format); + } else { + String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, formatterYear.format(new Date(date * 1000)), formatterDay.format(new Date(date * 1000))); + return String.format("%s %s", LocaleController.getString("LastSeenDate", R.string.LastSeenDate), format); + } + } catch (Exception e) { + FileLog.e("tmessages", e); } + return "LOC_ERR"; } private FastDateFormat createFormatter(Locale locale, String format, String defaultFormat) { if (format == null || format.length() == 0) { format = defaultFormat; } - FastDateFormat formatter = null; + FastDateFormat formatter; try { formatter = FastDateFormat.getInstance(format, locale); } catch (Exception e) { @@ -758,25 +766,30 @@ public class LocaleController { } public static String stringForMessageListDate(long date) { - Calendar rightNow = Calendar.getInstance(); - int day = rightNow.get(Calendar.DAY_OF_YEAR); - int year = rightNow.get(Calendar.YEAR); - rightNow.setTimeInMillis(date * 1000); - int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); - int dateYear = rightNow.get(Calendar.YEAR); + try { + Calendar rightNow = Calendar.getInstance(); + int day = rightNow.get(Calendar.DAY_OF_YEAR); + int year = rightNow.get(Calendar.YEAR); + rightNow.setTimeInMillis(date * 1000); + int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); + int dateYear = rightNow.get(Calendar.YEAR); - if (year != dateYear) { - return formatterYear.format(new Date(date * 1000)); - } else { - int dayDiff = dateDay - day; - if(dayDiff == 0 || dayDiff == -1 && (int)(System.currentTimeMillis() / 1000) - date < 60 * 60 * 8) { - return formatterDay.format(new Date(date * 1000)); - } else if(dayDiff > -7 && dayDiff <= -1) { - return formatterWeek.format(new Date(date * 1000)); + if (year != dateYear) { + return formatterYear.format(new Date(date * 1000)); } else { - return formatterMonth.format(new Date(date * 1000)); + int dayDiff = dateDay - day; + if(dayDiff == 0 || dayDiff == -1 && (int)(System.currentTimeMillis() / 1000) - date < 60 * 60 * 8) { + return formatterDay.format(new Date(date * 1000)); + } else if(dayDiff > -7 && dayDiff <= -1) { + return formatterWeek.format(new Date(date * 1000)); + } else { + return formatterMonth.format(new Date(date * 1000)); + } } + } catch (Exception e) { + FileLog.e("tmessages", e); } + return "LOC_ERR"; } public static String formatUserStatus(TLRPC.User user) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/LruCache.java b/TMessagesProj/src/main/java/org/telegram/android/LruCache.java index 3ed7d3c64..d4870cc96 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/LruCache.java +++ b/TMessagesProj/src/main/java/org/telegram/android/LruCache.java @@ -107,7 +107,6 @@ public class LruCache { if (previous != null) { entryRemoved(false, key, previous, value); - ImageLoader.getInstance().callGC(); } trimToSize(maxSize, key); @@ -148,7 +147,6 @@ public class LruCache { entryRemoved(true, key, value, null); } - ImageLoader.getInstance().callGC(); } } @@ -183,7 +181,6 @@ public class LruCache { } entryRemoved(false, key, previous, null); - ImageLoader.getInstance().callGC(); } return previous; diff --git a/TMessagesProj/src/main/java/org/telegram/android/MediaController.java b/TMessagesProj/src/main/java/org/telegram/android/MediaController.java index 9a088bcd0..a0ff51259 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MediaController.java @@ -8,6 +8,7 @@ package org.telegram.android; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.ProgressDialog; @@ -243,6 +244,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel private Timer progressTimer = null; private final Object progressTimerSync = new Object(); private boolean useFrontSpeaker; + private int buffersWrited; private AudioRecord audioRecorder = null; private TLRPC.TL_audio recordingAudio = null; @@ -271,7 +273,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel @Override public void run() { if (audioRecorder != null) { - ByteBuffer buffer = null; + ByteBuffer buffer; if (!recordBuffers.isEmpty()) { buffer = recordBuffers.get(0); recordBuffers.remove(0); @@ -691,7 +693,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (downloadObject.object instanceof TLRPC.Audio) { FileLoader.getInstance().loadFile((TLRPC.Audio)downloadObject.object, false); } else if (downloadObject.object instanceof TLRPC.PhotoSize) { - FileLoader.getInstance().loadFile((TLRPC.PhotoSize)downloadObject.object, false); + FileLoader.getInstance().loadFile((TLRPC.PhotoSize)downloadObject.object, null, false); } else if (downloadObject.object instanceof TLRPC.Video) { FileLoader.getInstance().loadFile((TLRPC.Video)downloadObject.object, false); } else if (downloadObject.object instanceof TLRPC.Document) { @@ -727,7 +729,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (downloadObject != null) { downloadQueueKeys.remove(fileName); if (state == 0 || state == 2) { - MessagesStorage.getInstance().removeFromDownloadQueue(downloadObject.id, downloadObject.type, state != 0); + MessagesStorage.getInstance().removeFromDownloadQueue(downloadObject.id, downloadObject.type, false /*state != 0*/); } if (downloadObject.type == AUTODOWNLOAD_MASK_PHOTO) { photoDownloadQueue.remove(downloadObject); @@ -1106,10 +1108,12 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } catch (Exception e) { FileLog.e("tmessages", e); } + buffersWrited++; if (count > 0) { final long pcm = buffer.pcmOffset; - final int marker = buffer.finished == 1 ? buffer.size : -1; + final int marker = buffer.finished == 1 ? count : -1; + final int finalBuffersWrited = buffersWrited; AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { @@ -1118,6 +1122,9 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (audioTrackPlayer != null) { audioTrackPlayer.setNotificationMarkerPosition(1); } + if (finalBuffersWrited == 1) { + clenupPlayer(true); + } } } }); @@ -1140,12 +1147,17 @@ public class MediaController implements NotificationCenter.NotificationCenterDel }); } + private boolean isNearToSensor(float value) { + return value < 5.0f && value != proximitySensor.getMaximumRange(); + } + @Override public void onSensorChanged(SensorEvent event) { - if (proximitySensor != null && audioTrackPlayer == null && audioPlayer == null || isPaused || (useFrontSpeaker == (event.values[0] < proximitySensor.getMaximumRange() / 10))) { + FileLog.e("tmessages", "proximity changed to " + event.values[0]); + if (proximitySensor != null && audioTrackPlayer == null && audioPlayer == null || isPaused || (useFrontSpeaker == isNearToSensor(event.values[0]))) { return; } - boolean newValue = event.values[0] < proximitySensor.getMaximumRange() / 10; + boolean newValue = isNearToSensor(event.values[0]); try { if (newValue && NotificationsController.getInstance().audioManager.isWiredHeadsetOn()) { return; @@ -1230,6 +1242,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } stopProgressTimer(); lastProgress = 0; + buffersWrited = 0; isPaused = false; MessageObject lastFile = playingMessageObject; playingMessageObject.audioProgress = 0.0f; @@ -1464,6 +1477,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.getId() != messageObject.getId()) { return false; } + stopProgressTimer(); try { if (audioPlayer != null) { audioPlayer.pause(); @@ -1480,11 +1494,12 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } public boolean resumeAudio(MessageObject messageObject) { - startProximitySensor(); if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.getId() != messageObject.getId()) { return false; } + startProximitySensor(); try { + startProgressTimer(); if (audioPlayer != null) { audioPlayer.start(); } else if (audioTrackPlayer != null) { @@ -1706,9 +1721,9 @@ public class MediaController implements NotificationCenter.NotificationCenterDel try { File destFile = null; if (type == 0) { - destFile = Utilities.generatePicturePath(); + destFile = AndroidUtilities.generatePicturePath(); } else if (type == 1) { - destFile = Utilities.generateVideoPath(); + destFile = AndroidUtilities.generateVideoPath(); } else if (type == 2) { File f = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); destFile = new File(f, name); @@ -1725,8 +1740,8 @@ public class MediaController implements NotificationCenter.NotificationCenterDel source = new FileInputStream(sourceFile).getChannel(); destination = new FileOutputStream(destFile).getChannel(); long size = source.size(); - for (long a = 0; a < size; a += 1024) { - destination.transferFrom(source, a, Math.min(1024, size - a)); + for (long a = 0; a < size; a += 4096) { + destination.transferFrom(source, a, Math.min(4096, size - a)); if (finalProgress != null) { if (lastProgress <= System.currentTimeMillis() - 500) { lastProgress = System.currentTimeMillis(); @@ -1757,7 +1772,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } if (result && (type == 0 || type == 1)) { - Utilities.addMediaToGallery(Uri.fromFile(destFile)); + AndroidUtilities.addMediaToGallery(Uri.fromFile(destFile)); } } catch (Exception e) { FileLog.e("tmessages", e); @@ -2185,6 +2200,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } + @SuppressLint("NewApi") public static MediaCodecInfo selectCodec(String mimeType) { int numCodecs = MediaCodecList.getCodecCount(); MediaCodecInfo lastCodecInfo = null; @@ -2221,6 +2237,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } + @SuppressLint("NewApi") public static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) { MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType); int lastColorFormat = 0; @@ -2373,7 +2390,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } private void checkConversionCanceled() throws Exception { - boolean cancelConversion = false; + boolean cancelConversion; synchronized (videoConvertSync) { cancelConversion = cancelCurrentVideoConversion; } @@ -2384,15 +2401,15 @@ public class MediaController implements NotificationCenter.NotificationCenterDel @TargetApi(16) private boolean convertVideo(final MessageObject messageObject) { - String videoPath = messageObject.messageOwner.videoEditedInfo.originalPath; - long startTime = messageObject.messageOwner.videoEditedInfo.startTime; - long endTime = messageObject.messageOwner.videoEditedInfo.endTime; - int resultWidth = messageObject.messageOwner.videoEditedInfo.resultWidth; - int resultHeight = messageObject.messageOwner.videoEditedInfo.resultHeight; - int rotationValue = messageObject.messageOwner.videoEditedInfo.rotationValue; - int originalWidth = messageObject.messageOwner.videoEditedInfo.originalWidth; - int originalHeight = messageObject.messageOwner.videoEditedInfo.originalHeight; - int bitrate = messageObject.messageOwner.videoEditedInfo.bitrate; + String videoPath = messageObject.videoEditedInfo.originalPath; + long startTime = messageObject.videoEditedInfo.startTime; + long endTime = messageObject.videoEditedInfo.endTime; + int resultWidth = messageObject.videoEditedInfo.resultWidth; + int resultHeight = messageObject.videoEditedInfo.resultHeight; + int rotationValue = messageObject.videoEditedInfo.rotationValue; + int originalWidth = messageObject.videoEditedInfo.originalWidth; + int originalHeight = messageObject.videoEditedInfo.originalHeight; + int bitrate = messageObject.videoEditedInfo.bitrate; int rotateRender = 0; File cacheFile = new File(messageObject.messageOwner.attachPath); @@ -2455,7 +2472,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel checkConversionCanceled(); if (resultWidth != originalWidth || resultHeight != originalHeight) { - int videoIndex = -5; + int videoIndex; videoIndex = selectTrack(extractor, false); if (videoIndex >= 0) { MediaCodec decoder = null; @@ -2471,7 +2488,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel int swapUV = 0; int videoTrackIndex = -5; - int colorFormat = 0; + int colorFormat; int processorType = PROCESSOR_TYPE_OTHER; String manufacturer = Build.MANUFACTURER.toLowerCase(); if (Build.VERSION.SDK_INT < 18) { @@ -2590,7 +2607,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (index == videoIndex) { int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); if (inputBufIndex >= 0) { - ByteBuffer inputBuf = null; + ByteBuffer inputBuf; if (Build.VERSION.SDK_INT < 21) { inputBuf = decoderInputBuffers[inputBufIndex]; } else { @@ -2636,7 +2653,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } else if (encoderStatus < 0) { throw new RuntimeException("unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus); } else { - ByteBuffer encodedData = null; + ByteBuffer encodedData; if (Build.VERSION.SDK_INT < 21) { encodedData = encoderOutputBuffers[encoderStatus]; } else { @@ -2698,7 +2715,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } else if (decoderStatus < 0) { throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus); } else { - boolean doRender = false; + boolean doRender; if (Build.VERSION.SDK_INT >= 18) { doRender = info.size != 0; } else { @@ -2775,21 +2792,17 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (outputSurface != null) { outputSurface.release(); - outputSurface = null; } if (inputSurface != null) { inputSurface.release(); - inputSurface = null; } if (decoder != null) { decoder.stop(); decoder.release(); - decoder = null; } if (encoder != null) { encoder.stop(); encoder.release(); - encoder = null; } checkConversionCanceled(); @@ -2809,7 +2822,6 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } finally { if (extractor != null) { extractor.release(); - extractor = null; } if (mediaMuxer != null) { try { @@ -2817,7 +2829,6 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } catch (Exception e) { FileLog.e("tmessages", e); } - mediaMuxer = null; } FileLog.e("tmessages", "time = " + (System.currentTimeMillis() - time)); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java index 45673ea72..ed916003e 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java @@ -25,6 +25,7 @@ import org.telegram.messenger.TLRPC; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.ui.Components.URLSpanNoUnderline; +import org.telegram.ui.Components.URLSpanNoUnderlineBold; import java.util.AbstractMap; import java.util.ArrayList; @@ -48,10 +49,11 @@ public class MessageObject { public int contentType; public String dateKey; public String monthKey; - public boolean deleted = false; + public boolean deleted; public float audioProgress; public int audioProgressSec; public ArrayList photoThumbs; + public VideoEditedInfo videoEditedInfo; public static TextPaint textPaint; public int lastLineWidth; @@ -147,7 +149,7 @@ public class MessageObject { if (whoUser != null && fromUser != null) { if (whoUser.id == fromUser.id) { if (isOut()) { - messageText = LocaleController.getString("ActionAddUserSelf", R.string.ActionAddUserSelf).replace("un1", LocaleController.getString("FromYou", R.string.FromYou)); + messageText = LocaleController.getString("ActionAddUserSelfYou", R.string.ActionAddUserSelfYou); } else { messageText = replaceWithLink(LocaleController.getString("ActionAddUserSelf", R.string.ActionAddUserSelf), "un1", fromUser); } @@ -331,6 +333,9 @@ public class MessageObject { if (message instanceof TLRPC.TL_message || message instanceof TLRPC.TL_messageForwarded_old2) { if (isMediaEmpty()) { contentType = type = 0; + if (messageText.length() == 0) { + messageText = "Empty message"; + } } else if (message.media instanceof TLRPC.TL_messageMediaPhoto) { contentType = type = 1; } else if (message.media instanceof TLRPC.TL_messageMediaGeo || message.media instanceof TLRPC.TL_messageMediaVenue) { @@ -351,9 +356,6 @@ public class MessageObject { type = 8; } else if (message.media.document.mime_type.equals("image/webp") && isSticker()) { type = 13; - if (messageOwner.media.document.thumb != null && messageOwner.media.document.thumb.location != null) { - messageOwner.media.document.thumb.location.ext = "webp"; - } } else { type = 9; } @@ -393,6 +395,11 @@ public class MessageObject { monthKey = String.format("%d_%02d", dateYear, dateMonth); } + if (messageOwner.message != null && messageOwner.id < 0 && messageOwner.message.length() > 6 && messageOwner.media instanceof TLRPC.TL_messageMediaVideo) { + videoEditedInfo = new VideoEditedInfo(); + videoEditedInfo.parseString(messageOwner.message); + } + generateCaption(); if (generateLayout) { generateLayout(); @@ -458,7 +465,7 @@ public class MessageObject { if (messageOwner.media.webpage.photo != null) { if (!update || photoThumbs == null) { photoThumbs = new ArrayList<>(messageOwner.media.webpage.photo.sizes); - } else if (photoThumbs != null && !photoThumbs.isEmpty()) { + } else if (!photoThumbs.isEmpty()) { for (TLRPC.PhotoSize photoObject : photoThumbs) { for (TLRPC.PhotoSize size : messageOwner.media.webpage.photo.sizes) { if (size instanceof TLRPC.TL_photoSizeEmpty) { @@ -479,7 +486,7 @@ public class MessageObject { public CharSequence replaceWithLink(CharSequence source, String param, TLRPC.User user) { String name = ContactsController.formatName(user.first_name, user.last_name); int start = TextUtils.indexOf(source, param); - URLSpanNoUnderline span = new URLSpanNoUnderline("" + user.id); + URLSpanNoUnderlineBold span = new URLSpanNoUnderlineBold("" + user.id); SpannableStringBuilder builder = new SpannableStringBuilder(TextUtils.replace(source, new String[]{param}, new String[]{name})); builder.setSpan(span, start, start + name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); return builder; @@ -664,7 +671,7 @@ public class MessageObject { } } - StaticLayout textLayout = null; + StaticLayout textLayout; try { textLayout = new StaticLayout(messageText, textPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); @@ -783,7 +790,6 @@ public class MessageObject { if (a == blocksCount - 1) { lastLineWidth = lastLineWidthWithLeft; } - linesMaxWidth = linesMaxWidthWithLeft; } else if (a == blocksCount - 1) { lastLineWidth = linesMaxWidth; } @@ -939,6 +945,20 @@ public class MessageObject { return false; } + public static TLRPC.InputStickerSet getInputStickerSet(TLRPC.Message message) { + if (message.media != null && message.media.document != null) { + for (TLRPC.DocumentAttribute attribute : message.media.document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeSticker) { + if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetEmpty) { + return null; + } + return attribute.stickerset; + } + } + } + return null; + } + public String getStrickerChar() { if (messageOwner.media != null && messageOwner.media.document != null) { for (TLRPC.DocumentAttribute attribute : messageOwner.media.document.attributes) { @@ -991,8 +1011,8 @@ public class MessageObject { } return photoHeight + AndroidUtilities.dp(14); } else { - int photoHeight = 0; - int photoWidth = 0; + int photoHeight; + int photoWidth; if (AndroidUtilities.isTablet()) { photoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); @@ -1010,35 +1030,22 @@ public class MessageObject { if (currentPhotoObject != null) { float scale = (float) currentPhotoObject.w / (float) photoWidth; - int w = (int) (currentPhotoObject.w / scale); int h = (int) (currentPhotoObject.h / scale); - if (w == 0) { - w = AndroidUtilities.dp(100); - } if (h == 0) { h = AndroidUtilities.dp(100); } if (h > photoHeight) { - float scale2 = h; h = photoHeight; - scale2 /= h; - w = (int) (w / scale2); } else if (h < AndroidUtilities.dp(120)) { h = AndroidUtilities.dp(120); - float hScale = (float) currentPhotoObject.h / h; - if (currentPhotoObject.w / hScale < photoWidth) { - w = (int) (currentPhotoObject.w / hScale); - } } if (isSecretPhoto()) { if (AndroidUtilities.isTablet()) { - w = h = (int) (AndroidUtilities.getMinTabletSide() * 0.5f); + h = (int) (AndroidUtilities.getMinTabletSide() * 0.5f); } else { - w = h = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f); + h = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f); } } - - photoWidth = w; photoHeight = h; } return photoHeight + AndroidUtilities.dp(14); @@ -1049,6 +1056,10 @@ public class MessageObject { return isStickerMessage(messageOwner); } + public TLRPC.InputStickerSet getInputStickerSet() { + return getInputStickerSet(messageOwner); + } + public boolean isForwarded() { return (messageOwner.flags & TLRPC.MESSAGE_FLAG_FWD) != 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java index f4b2437b0..01b18bb9a 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java @@ -10,9 +10,12 @@ package org.telegram.android; import android.app.Activity; import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.os.Build; +import android.os.Bundle; import android.util.Base64; import android.util.SparseArray; @@ -28,6 +31,8 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.ProfileActivity; import java.util.ArrayList; import java.util.Collections; @@ -129,6 +134,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } private static volatile MessagesController Instance = null; + public static MessagesController getInstance() { MessagesController localInstance = Instance; if (localInstance == null) { @@ -200,7 +206,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter disabledFeature.serializeToStream(data); } String string = Base64.encodeToString(data.toByteArray(), Base64.DEFAULT); - if (string != null && string.length() != 0) { + if (string.length() != 0) { editor.putString("disabledFeatures", string); } } catch (Exception e) { @@ -223,7 +229,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter builder.setTitle("Oops!"); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(disabledFeature.description); - fragment.showAlertDialog(builder); + fragment.showDialog(builder.create()); } return false; } @@ -255,7 +261,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (user == null) { return null; } - TLRPC.InputUser inputUser = null; + TLRPC.InputUser inputUser; if (user.id == UserConfig.getClientUserId()) { inputUser = new TLRPC.TL_inputUserSelf(); } else if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) { @@ -272,9 +278,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter @Override public void didReceivedNotification(int id, Object... args) { if (id == NotificationCenter.FileDidUpload) { - final String location = (String)args[0]; - final TLRPC.InputFile file = (TLRPC.InputFile)args[1]; - final TLRPC.InputEncryptedFile encryptedFile = (TLRPC.InputEncryptedFile)args[2]; + final String location = (String) args[0]; + final TLRPC.InputFile file = (TLRPC.InputFile) args[1]; if (uploadingAvatar != null && uploadingAvatar.equals(location)) { TLRPC.TL_photos_uploadProfilePhoto req = new TLRPC.TL_photos_uploadProfilePhoto(); @@ -327,16 +332,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } else if (id == NotificationCenter.FileDidFailUpload) { final String location = (String) args[0]; - final boolean enc = (Boolean) args[1]; - if (uploadingAvatar != null && uploadingAvatar.equals(location)) { uploadingAvatar = null; } } else if (id == NotificationCenter.messageReceivedByServer) { - Integer msgId = (Integer)args[0]; + Integer msgId = (Integer) args[0]; MessageObject obj = dialogMessage.get(msgId); if (obj != null) { - Integer newMsgId = (Integer)args[1]; + Integer newMsgId = (Integer) args[1]; dialogMessage.remove(msgId); dialogMessage.put(newMsgId, obj); obj.messageOwner.id = newMsgId; @@ -360,9 +363,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter } NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); } - } else { - NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidLoaded); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailedLoad); } } @@ -431,7 +431,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter } public TLRPC.User getUser(String username) { - return usersByUsernames.get(username); + if (username == null || username.length() == 0) { + return null; + } + return usersByUsernames.get(username.toLowerCase()); } public ConcurrentHashMap getUsers() { @@ -458,8 +461,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter FileLog.e("tmessages", e); } if (result.size() == 2) { - chat = (TLRPC.EncryptedChat)result.get(0); - TLRPC.User user = (TLRPC.User)result.get(1); + chat = (TLRPC.EncryptedChat) result.get(0); + TLRPC.User user = (TLRPC.User) result.get(1); putEncryptedChat(chat, false); putUser(user, true); } @@ -471,10 +474,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter return exportedChats.get(chat_id); } - public void putExportedInvite(int chat_id, TLRPC.TL_chatInviteExported invite) { - exportedChats.put(chat_id, invite); - } - public boolean putUser(TLRPC.User user, boolean fromCache) { if (user == null) { return false; @@ -485,7 +484,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter usersByUsernames.remove(oldUser.username); } if (user.username != null && user.username.length() > 0) { - usersByUsernames.put(user.username, user); + usersByUsernames.put(user.username.toLowerCase(), user); } if (!fromCache) { users.put(user.id, user); @@ -637,7 +636,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter loadingFullUsers.remove((Integer) user.id); loadedFullUsers.add(user.id); String names = user.first_name + user.last_name + user.username; - TLRPC.TL_userFull userFull = (TLRPC.TL_userFull)response; + TLRPC.TL_userFull userFull = (TLRPC.TL_userFull) response; ArrayList users = new ArrayList<>(); users.add(userFull.user); putUsers(users, false); @@ -651,7 +650,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - loadingFullUsers.remove((Integer)user.id); + loadingFullUsers.remove((Integer) user.id); } }); } @@ -710,7 +709,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.lastPtsValue = pts; MessagesStorage.getInstance().saveDiffParams(MessagesStorage.lastSeqValue, MessagesStorage.lastPtsValue, MessagesStorage.lastDateValue, MessagesStorage.lastQtsValue); } else if (MessagesStorage.lastPtsValue != pts) { - if (gettingDifference || updatesStartWaitTimePts == 0 || updatesStartWaitTimePts != 0 && updatesStartWaitTimePts + 1500 > System.currentTimeMillis()) { + if (gettingDifference || updatesStartWaitTimePts == 0 || updatesStartWaitTimePts + 1500 > System.currentTimeMillis()) { FileLog.e("tmessages", "ADD UPDATE TO QUEUE pts = " + pts + " pts_count = " + pts_count); if (updatesStartWaitTimePts == 0) { updatesStartWaitTimePts = System.currentTimeMillis(); @@ -733,7 +732,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } MessagesStorage.getInstance().saveDiffParams(MessagesStorage.lastSeqValue, MessagesStorage.lastPtsValue, MessagesStorage.lastDateValue, MessagesStorage.lastQtsValue); } else if (MessagesStorage.lastSeqValue != seq) { - if (gettingDifference || updatesStartWaitTimeSeq == 0 || updatesStartWaitTimeSeq != 0 && updatesStartWaitTimeSeq + 1500 > System.currentTimeMillis()) { + if (gettingDifference || updatesStartWaitTimeSeq == 0 || updatesStartWaitTimeSeq + 1500 > System.currentTimeMillis()) { FileLog.e("tmessages", "ADD UPDATE TO QUEUE seq = " + seq); if (updatesStartWaitTimeSeq == 0) { updatesStartWaitTimeSeq = System.currentTimeMillis(); @@ -826,7 +825,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } }; int currentServerTime = ConnectionsManager.getInstance().getCurrentTime(); - Utilities.stageQueue.postRunnable(currentDeleteTaskRunnable, (long)Math.abs(currentServerTime - currentDeletingTaskTime) * 1000); + Utilities.stageQueue.postRunnable(currentDeleteTaskRunnable, (long) Math.abs(currentServerTime - currentDeletingTaskTime) * 1000); } } else { currentDeletingTaskTime = 0; @@ -847,14 +846,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter TLRPC.TL_photos_getUserPhotos req = new TLRPC.TL_photos_getUserPhotos(); req.limit = count; req.offset = offset; - req.max_id = (int)max_id; + req.max_id = (int) max_id; req.user_id = getInputUser(user); long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { @Override public void run(TLObject response, TLRPC.TL_error error) { if (error == null) { TLRPC.photos_Photos res = (TLRPC.photos_Photos) response; - processLoadedUserPhotos(res, uid, offset, count, max_id, fromCache, classGuid); + processLoadedUserPhotos(res, uid, offset, count, max_id, false, classGuid); } } }); @@ -917,7 +916,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter ArrayList blocked = new ArrayList<>(); ArrayList users = null; if (error == null) { - final TLRPC.contacts_Blocked res = (TLRPC.contacts_Blocked)response; + final TLRPC.contacts_Blocked res = (TLRPC.contacts_Blocked) response; for (TLRPC.TL_contactBlocked contactBlocked : res.blocked) { blocked.add(contactBlocked.user_id); } @@ -965,9 +964,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (user == null) { return; } - if (user != null) { - user.photo = UserConfig.getCurrentUser().photo; - } + user.photo = UserConfig.getCurrentUser().photo; NotificationCenter.getInstance().postNotificationName(NotificationCenter.mainUserInfoChanged); NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_ALL); ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { @@ -1077,8 +1074,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } public void deleteDialog(final long did, int offset, final boolean onlyHistory) { - int lower_part = (int)did; - int high_id = (int)(did >> 32); + int lower_part = (int) did; + int high_id = (int) (did >> 32); if (offset == 0) { TLRPC.TL_dialog dialog = dialogs_dict.get(did); @@ -1414,8 +1411,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter typings = new HashMap<>(); sendingTypings.put(action, typings); } - int lower_part = (int)dialog_id; - int high_id = (int)(dialog_id >> 32); + int lower_part = (int) dialog_id; + int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { if (high_id == 1) { return; @@ -1505,7 +1502,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, final int load_type, final int last_message_id, final int first_message_id, final boolean allowCache) { - int lower_part = (int)dialog_id; + int lower_part = (int) dialog_id; if (fromCache || lower_part == 0) { MessagesStorage.getInstance().getMessages(dialog_id, count, max_id, midDate, classGuid, load_type); } else { @@ -1515,6 +1512,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter req.peer.chat_id = -lower_part; } else { TLRPC.User user = getUser(lower_part); + if (user == null) { + return; + } if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) { req.peer = new TLRPC.TL_inputPeerForeign(); req.peer.user_id = user.id; @@ -1785,7 +1785,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - putUsers(dialogsRes.users, isCache); + putUsers(dialogsRes.users, true); loadingDialogs = false; if (resetEnd) { dialogsEndReached = false; @@ -1936,8 +1936,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (random_id == 0 || dialog_id == 0 || ttl <= 0) { return; } - int lower_part = (int)dialog_id; - int high_id = (int)(dialog_id >> 32); + int lower_part = (int) dialog_id; + int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { return; } @@ -1953,8 +1953,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } public void markDialogAsRead(final long dialog_id, final int max_id, final int max_positive_id, final int offset, final int max_date, final boolean was, final boolean popup) { - int lower_part = (int)dialog_id; - int high_id = (int)(dialog_id >> 32); + int lower_part = (int) dialog_id; + int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { if (max_positive_id == 0 && offset == 0 || high_id == 1) { @@ -2079,7 +2079,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter chat.title = title; chat.photo = new TLRPC.TL_chatPhotoEmpty(); chat.participants_count = selectedContacts.size(); - chat.date = (int)(System.currentTimeMillis() / 1000); + chat.date = (int) (System.currentTimeMillis() / 1000); chat.left = false; chat.version = 1; UserConfig.lastBroadcastId--; @@ -2096,7 +2096,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter TLRPC.TL_chatParticipant participant = new TLRPC.TL_chatParticipant(); participant.user_id = id; participant.inviter_id = UserConfig.getClientUserId(); - participant.date = (int)(System.currentTimeMillis() / 1000); + participant.date = (int) (System.currentTimeMillis() / 1000); participants.participants.add(participant); } MessagesStorage.getInstance().updateChatInfo(chat.id, participants, false); @@ -2246,20 +2246,18 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.getInstance().putUsersAndChats(null, chatArrayList, true, true); boolean changed = false; - if (info != null) { - for (int a = 0; a < info.participants.size(); a++) { - TLRPC.TL_chatParticipant p = info.participants.get(a); - if (p.user_id == user.id) { - info.participants.remove(a); - changed = true; - break; - } - } - if (changed) { - MessagesStorage.getInstance().updateChatInfo(info.chat_id, info, true); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatInfoDidLoaded, info.chat_id, info); + for (int a = 0; a < info.participants.size(); a++) { + TLRPC.TL_chatParticipant p = info.participants.get(a); + if (p.user_id == user.id) { + info.participants.remove(a); + changed = true; + break; } } + if (changed) { + MessagesStorage.getInstance().updateChatInfo(info.chat_id, info, true); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatInfoDidLoaded, info.chat_id, info); + } NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_CHAT_MEMBERS); } } @@ -2325,14 +2323,27 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - public void logOut() { - TLRPC.TL_auth_logOut req = new TLRPC.TL_auth_logOut(); - ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(TLObject response, TLRPC.TL_error error) { - ConnectionsManager.getInstance().cleanUp(); - } - }); + public void performLogout(boolean byUser) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + editor.clear().commit(); + if (byUser) { + unregistedPush(); + TLRPC.TL_auth_logOut req = new TLRPC.TL_auth_logOut(); + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + ConnectionsManager.getInstance().cleanUp(); + } + }); + } else { + ConnectionsManager.getInstance().cleanUp(); + } + UserConfig.clearConfig(); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.appDidLogout); + MessagesStorage.getInstance().cleanUp(false); + cleanUp(); + ContactsController.getInstance().deleteAllAppAccounts(); } public void generateUpdateMessage() { @@ -2343,6 +2354,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter String build = LocaleController.getString("updateBuild", R.string.updateBuild); if (build != null) { int version = Utilities.parseInt(build); + if (version == 0) { + version = 524; + } if (version <= UserConfig.lastUpdateVersion) { return; } @@ -2378,20 +2392,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter req.app_sandbox = false; try { req.lang_code = LocaleController.getLocaleString(LocaleController.getInstance().getSystemDefaultLocale()); - if (req.lang_code == null || req.lang_code.length() == 0) { + if (req.lang_code.length() == 0) { req.lang_code = "en"; } req.device_model = Build.MANUFACTURER + Build.MODEL; - if (req.device_model == null) { - req.device_model = "Android unknown"; - } req.system_version = "SDK " + Build.VERSION.SDK_INT; PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); req.app_version = pInfo.versionName + " (" + pInfo.versionCode + ")"; - if (req.app_version == null) { - req.app_version = "App version unknown"; - } - } catch (Exception e) { FileLog.e("tmessages", e); req.lang_code = "en"; @@ -2505,15 +2512,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (type == 1) { if (updates.pts <= MessagesStorage.lastPtsValue) { return 2; - } else if (MessagesStorage.lastPtsValue + updates.pts_count == updates.pts) { + } else if (MessagesStorage.lastPtsValue + updates.pts_count == updates.pts) { return 0; } else { return 1; } } else if (type == 2) { - if (updates.qts <= MessagesStorage.lastQtsValue) { + if (updates.pts <= MessagesStorage.lastQtsValue) { return 2; - } else if (MessagesStorage.lastQtsValue + updates.updates.size() == updates.qts) { + } else if (MessagesStorage.lastQtsValue + updates.updates.size() == updates.pts) { return 0; } else { return 1; @@ -2545,11 +2552,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter Collections.sort(updatesQueue, new Comparator() { @Override public int compare(TLRPC.Updates updates, TLRPC.Updates updates2) { - return AndroidUtilities.compare(updates.qts, updates2.qts); + return AndroidUtilities.compare(updates.pts, updates2.pts); } }); } - if (!updatesQueue.isEmpty()) { + if (updatesQueue != null && !updatesQueue.isEmpty()) { boolean anyProceed = false; if (state == 2) { TLRPC.Updates updates = updatesQueue.get(0); @@ -2557,8 +2564,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.lastSeqValue = getUpdateSeq(updates); } else if (type == 1) { MessagesStorage.lastPtsValue = updates.pts; - } else if (type == 2) { - MessagesStorage.lastQtsValue = updates.qts; + } else { + MessagesStorage.lastQtsValue = updates.pts; } } for (int a = 0; a < updatesQueue.size(); a++) { @@ -2707,15 +2714,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter for (TLRPC.Message message : res.new_messages) { MessageObject obj = new MessageObject(message, usersDict, true); - long dialog_id = obj.messageOwner.dialog_id; - if (dialog_id == 0) { - if (obj.messageOwner.to_id.chat_id != 0) { - dialog_id = -obj.messageOwner.to_id.chat_id; - } else { - dialog_id = obj.messageOwner.to_id.user_id; - } - } - if (!obj.isOut() && obj.isUnread()) { pushMessages.add(obj); } @@ -2773,7 +2771,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter SecretChatHelper.getInstance().processPendingEncMessages(); } - if (res != null && !res.other_updates.isEmpty()) { + if (!res.other_updates.isEmpty()) { processUpdateArray(res.other_updates, res.users, res.chats); } @@ -2886,7 +2884,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter needFwdUser = true; } - boolean missingData = false; + boolean missingData; if (updates instanceof TLRPC.TL_updateShortMessage) { missingData = user == null || needFwdUser && user2 == null; } else { @@ -2985,7 +2983,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); } else if (MessagesStorage.lastPtsValue != updates.pts) { FileLog.e("tmessages", "need get diff short message, pts: " + MessagesStorage.lastPtsValue + " " + updates.pts + " count = " + updates.pts_count); - if (gettingDifference || updatesStartWaitTimePts == 0 || updatesStartWaitTimePts != 0 && updatesStartWaitTimePts + 1500 > System.currentTimeMillis()) { + if (gettingDifference || updatesStartWaitTimePts == 0 || updatesStartWaitTimePts + 1500 > System.currentTimeMillis()) { if (updatesStartWaitTimePts == 0) { updatesStartWaitTimePts = System.currentTimeMillis(); } @@ -3054,24 +3052,24 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (getUpdateType(update) == 1) { TLRPC.TL_updates updatesNew = new TLRPC.TL_updates(); updatesNew.updates.add(update); - updatesNew.qts = update.qts; + updatesNew.pts = update.qts; for (int b = a + 1; b < updates.updates.size(); b++) { TLRPC.Update update2 = updates.updates.get(b); - if (getUpdateType(update2) == 1 && updatesNew.qts + 1 == update2.qts) { + if (getUpdateType(update2) == 1 && updatesNew.pts + 1 == update2.qts) { updatesNew.updates.add(update2); - updatesNew.qts = update2.qts; + updatesNew.pts = update2.qts; updates.updates.remove(b); b--; } else { break; } } - if (MessagesStorage.lastQtsValue == 0 || MessagesStorage.lastQtsValue + updatesNew.updates.size() == updatesNew.qts) { + if (MessagesStorage.lastQtsValue == 0 || MessagesStorage.lastQtsValue + updatesNew.updates.size() == updatesNew.pts) { processUpdateArray(updatesNew.updates, updates.users, updates.chats); - MessagesStorage.lastQtsValue = updatesNew.qts; + MessagesStorage.lastQtsValue = updatesNew.pts; needReceivedQueue = true; - } else if (MessagesStorage.lastPtsValue != updatesNew.qts) { - FileLog.e("tmessages", update + " need get diff, qts: " + MessagesStorage.lastQtsValue + " " + updatesNew.qts); + } else if (MessagesStorage.lastPtsValue != updatesNew.pts) { + FileLog.e("tmessages", update + " need get diff, qts: " + MessagesStorage.lastQtsValue + " " + updatesNew.pts); if (gettingDifference || updatesStartWaitTimeQts == 0 || updatesStartWaitTimeQts != 0 && updatesStartWaitTimeQts + 1500 > System.currentTimeMillis()) { if (updatesStartWaitTimeQts == 0) { updatesStartWaitTimeQts = System.currentTimeMillis(); @@ -3089,7 +3087,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter a--; } - boolean processUpdate = false; + boolean processUpdate; if (updates instanceof TLRPC.TL_updatesCombined) { processUpdate = MessagesStorage.lastSeqValue + 1 == updates.seq_start || MessagesStorage.lastSeqValue == updates.seq_start; } else { @@ -3110,7 +3108,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter FileLog.e("tmessages", "need get diff TL_updates, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq); } - if (gettingDifference || updatesStartWaitTimeSeq == 0 || updatesStartWaitTimeSeq != 0 && updatesStartWaitTimeSeq + 1500 > System.currentTimeMillis()) { + if (gettingDifference || updatesStartWaitTimeSeq == 0 || updatesStartWaitTimeSeq + 1500 > System.currentTimeMillis()) { if (updatesStartWaitTimeSeq == 0) { updatesStartWaitTimeSeq = System.currentTimeMillis(); } @@ -3142,7 +3140,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (a == 2) { updatesQueue = updatesQueueQts; } - if (!updatesQueue.isEmpty()) { + if (updatesQueue != null && !updatesQueue.isEmpty()) { processUpdatesQueue(a, 0); } } @@ -3226,7 +3224,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter for (TLRPC.Update update : updates) { if (update instanceof TLRPC.TL_updateNewMessage) { - TLRPC.TL_updateNewMessage upd = (TLRPC.TL_updateNewMessage)update; + TLRPC.TL_updateNewMessage upd = (TLRPC.TL_updateNewMessage) update; if (checkForUsers) { TLRPC.User user = getUser(upd.message.from_id); if (usersDict.get(upd.message.from_id) == null && user == null || upd.message.to_id.chat_id != 0 && chatsDict.get(upd.message.to_id.chat_id) == null && getChat(upd.message.to_id.chat_id) == null) { @@ -3419,7 +3417,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (update instanceof TLRPC.TL_updateNewEncryptedMessage) { ArrayList decryptedMessages = SecretChatHelper.getInstance().decryptMessage(((TLRPC.TL_updateNewEncryptedMessage) update).message); if (decryptedMessages != null && !decryptedMessages.isEmpty()) { - int cid = ((TLRPC.TL_updateNewEncryptedMessage)update).message.chat_id; + int cid = ((TLRPC.TL_updateNewEncryptedMessage) update).message.chat_id; long uid = ((long) cid) << 32; ArrayList arr = messages.get(uid); if (arr == null) { @@ -3475,7 +3473,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (update instanceof TLRPC.TL_updateEncryption) { SecretChatHelper.getInstance().processUpdateEncryption((TLRPC.TL_updateEncryption) update, usersDict); } else if (update instanceof TLRPC.TL_updateUserBlocked) { - final TLRPC.TL_updateUserBlocked finalUpdate = (TLRPC.TL_updateUserBlocked)update; + final TLRPC.TL_updateUserBlocked finalUpdate = (TLRPC.TL_updateUserBlocked) update; if (finalUpdate.blocked) { ArrayList ids = new ArrayList<>(); ids.add(finalUpdate.user_id); @@ -3514,7 +3512,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter newMessage.to_id.user_id = UserConfig.getClientUserId(); newMessage.dialog_id = 777000; newMessage.media = update.media; - newMessage.message = ((TLRPC.TL_updateServiceNotification)update).message; + newMessage.message = ((TLRPC.TL_updateServiceNotification) update).message; messagesArr.add(newMessage); MessageObject obj = new MessageObject(newMessage, usersDict, true); @@ -3575,7 +3573,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter public void run() { int updateMask = interfaceUpdateMaskFinal; - boolean avatarsUpdate = false; if (!updatesOnMainThread.isEmpty()) { ArrayList dbUsers = new ArrayList<>(); ArrayList dbUsersStatus = new ArrayList<>(); @@ -3627,7 +3624,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (currentUser != null) { currentUser.photo = update.photo; } - avatarsUpdate = true; toDbUser.photo = update.photo; dbUsers.add(toDbUser); } else if (update instanceof TLRPC.TL_updateUserPhone) { @@ -3643,14 +3639,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter toDbUser.phone = update.phone; dbUsers.add(toDbUser); } else if (update instanceof TLRPC.TL_updateNotifySettings) { - if (update.notify_settings instanceof TLRPC.TL_peerNotifySettings && update.peer instanceof TLRPC.TL_notifyPeer) { + TLRPC.TL_updateNotifySettings updateNotifySettings = (TLRPC.TL_updateNotifySettings) update; + if (update.notify_settings instanceof TLRPC.TL_peerNotifySettings && updateNotifySettings.peer instanceof TLRPC.TL_notifyPeer) { if (editor == null) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); editor = preferences.edit(); } - long dialog_id = update.peer.peer.user_id; + long dialog_id = updateNotifySettings.peer.peer.user_id; if (dialog_id == 0) { - dialog_id = -update.peer.peer.chat_id; + dialog_id = -updateNotifySettings.peer.peer.chat_id; } TLRPC.TL_dialog dialog = dialogs_dict.get(dialog_id); if (dialog != null) { @@ -3671,7 +3668,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialog.notify_settings.mute_until = until; } } - MessagesStorage.getInstance().setDialogFlags(dialog_id, ((long)until << 32) | 1); + MessagesStorage.getInstance().setDialogFlags(dialog_id, ((long) until << 32) | 1); } else { if (dialog != null) { dialog.notify_settings.mute_until = 0; @@ -3888,19 +3885,25 @@ public class MessagesController implements NotificationCenter.NotificationCenter } protected void updateInterfaceWithMessages(final long uid, final ArrayList messages, boolean isBroadcast) { + if (messages == null || messages.isEmpty()) { + return; + } + + boolean isEncryptedChat = ((int) uid) == 0; MessageObject lastMessage = null; - TLRPC.TL_dialog dialog = dialogs_dict.get(uid); - - boolean isEncryptedChat = ((int)uid) == 0; - - NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceivedNewMessages, uid, messages); - for (MessageObject message : messages) { if (lastMessage == null || (!isEncryptedChat && message.getId() > lastMessage.getId() || (isEncryptedChat || message.getId() < 0 && lastMessage.getId() < 0) && message.getId() < lastMessage.getId()) || message.messageOwner.date > lastMessage.messageOwner.date) { lastMessage = message; } } + TLRPC.TL_dialog dialog = dialogs_dict.get(uid); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceivedNewMessages, uid, messages); + + if (lastMessage == null) { + return; + } + boolean changed = false; if (dialog == null) { @@ -3958,13 +3961,88 @@ public class MessagesController implements NotificationCenter.NotificationCenter } }); for (TLRPC.TL_dialog d : dialogs) { - int high_id = (int)(d.id >> 32); - if ((int)d.id != 0 && high_id != 1) { + int high_id = (int) (d.id >> 32); + if ((int) d.id != 0 && high_id != 1) { dialogsServerOnly.add(d); } } } } + public static void openByUserName(String username, final BaseFragment fragment, final int type) { + if (username == null || fragment == null) { + return; + } + TLRPC.User user = MessagesController.getInstance().getUser(username); + if (user != null) { + Bundle args = new Bundle(); + args.putInt("user_id", user.id); + if (type == 0) { + fragment.presentFragment(new ProfileActivity(args)); + } else { + fragment.presentFragment(new ChatActivity(args)); + } + } else { + if (fragment.getParentActivity() == null) { + return; + } + final ProgressDialog progressDialog = new ProgressDialog(fragment.getParentActivity()); + progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.setCancelable(false); + TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); + req.username = username; + final long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + if (fragment != null) { + fragment.setVisibleDialog(null); + } + if (error == null) { + TLRPC.User user = (TLRPC.User) response; + MessagesController.getInstance().putUser(user, false); + ArrayList users = new ArrayList<>(); + users.add(user); + MessagesStorage.getInstance().putUsersAndChats(users, null, false, true); + Bundle args = new Bundle(); + args.putInt("user_id", user.id); + if (fragment != null) { + if (type == 0) { + fragment.presentFragment(new ProfileActivity(args)); + } else if (type == 1) { + fragment.presentFragment(new ChatActivity(args)); + } + } + } + } + }); + } + }); + progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ConnectionsManager.getInstance().cancelRpc(reqId, true); + try { + dialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + if (fragment != null) { + fragment.setVisibleDialog(null); + } + } + }); + fragment.setVisibleDialog(progressDialog); + progressDialog.show(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java index 9f445c515..7cde65697 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java @@ -282,7 +282,7 @@ public class MessagesStorage { database.executeFast("PRAGMA user_version = 4").stepThis().dispose(); version = 4; } - if (version == 4 && version < 6) { + if (version == 4) { database.executeFast("CREATE TABLE IF NOT EXISTS enc_tasks_v2(mid INTEGER PRIMARY KEY, date INTEGER)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_enc_tasks_v2 ON enc_tasks_v2(date);").stepThis().dispose(); database.beginTransaction(); @@ -290,7 +290,7 @@ public class MessagesStorage { SQLitePreparedStatement state = database.executeFast("REPLACE INTO enc_tasks_v2 VALUES(?, ?)"); if (cursor.next()) { int date = cursor.intValue(0); - int length = 0; + int length; ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(1)); if ((length = cursor.byteBufferValue(1, data.buffer)) != 0) { for (int a = 0; a < length / 4; a++) { @@ -313,7 +313,7 @@ public class MessagesStorage { database.executeFast("PRAGMA user_version = 6").stepThis().dispose(); version = 6; } - if (version == 6 && version < 7) { + if (version == 6) { database.executeFast("CREATE TABLE IF NOT EXISTS messages_seq(mid INTEGER PRIMARY KEY, seq_in INTEGER, seq_out INTEGER);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS seq_idx_messages_seq ON messages_seq(seq_in, seq_out);").stepThis().dispose(); database.executeFast("ALTER TABLE enc_chats ADD COLUMN layer INTEGER default 0").stepThis().dispose(); @@ -333,7 +333,7 @@ public class MessagesStorage { database.executeFast("PRAGMA user_version = 9").stepThis().dispose(); version = 9; }*/ - if ((version == 7 || version == 8 || version == 9) && version < 10) { + if (version == 7 || version == 8 || version == 9) { database.executeFast("ALTER TABLE enc_chats ADD COLUMN use_count INTEGER default 0").stepThis().dispose(); database.executeFast("ALTER TABLE enc_chats ADD COLUMN exchange_id INTEGER default 0").stepThis().dispose(); database.executeFast("ALTER TABLE enc_chats ADD COLUMN key_date INTEGER default 0").stepThis().dispose(); @@ -343,17 +343,17 @@ public class MessagesStorage { database.executeFast("PRAGMA user_version = 10").stepThis().dispose(); version = 10; } - if (version == 10 && version < 11) { + if (version == 10) { database.executeFast("CREATE TABLE IF NOT EXISTS web_recent_v3(id TEXT, type INTEGER, image_url TEXT, thumb_url TEXT, local_url TEXT, width INTEGER, height INTEGER, size INTEGER, date INTEGER, PRIMARY KEY (id, type));").stepThis().dispose(); database.executeFast("PRAGMA user_version = 11").stepThis().dispose(); version = 11; } - if (version == 11 && version < 12) { + if (version == 11) { database.executeFast("CREATE TABLE IF NOT EXISTS stickers(id INTEGER PRIMARY KEY, data BLOB, date INTEGER);").stepThis().dispose(); database.executeFast("PRAGMA user_version = 12").stepThis().dispose(); version = 12; } - if (version == 12 && version < 13) { + if (version == 12) { database.executeFast("DROP INDEX IF EXISTS uid_mid_idx_media;").stepThis().dispose(); database.executeFast("DROP INDEX IF EXISTS mid_idx_media;").stepThis().dispose(); database.executeFast("DROP INDEX IF EXISTS uid_date_mid_idx_media;").stepThis().dispose(); @@ -370,26 +370,26 @@ public class MessagesStorage { database.executeFast("PRAGMA user_version = 13").stepThis().dispose(); version = 13; } - if (version == 13 && version < 14) { + if (version == 13) { database.executeFast("ALTER TABLE messages ADD COLUMN replydata BLOB default NULL").stepThis().dispose(); database.executeFast("PRAGMA user_version = 14").stepThis().dispose(); version = 14; } - if (version == 14 && version < 15) { + if (version == 14) { database.executeFast("CREATE TABLE IF NOT EXISTS hashtag_recent_v2(id TEXT PRIMARY KEY, date INTEGER);").stepThis().dispose(); database.executeFast("PRAGMA user_version = 15").stepThis().dispose(); version = 15; } - if (version == 15 && version < 16) { + if (version == 15) { database.executeFast("CREATE TABLE IF NOT EXISTS webpage_pending(id INTEGER, mid INTEGER, PRIMARY KEY (id, mid));").stepThis().dispose(); database.executeFast("PRAGMA user_version = 16").stepThis().dispose(); version = 16; } - if (version == 16 && version < 17) { + if (version == 16) { database.executeFast("ALTER TABLE dialogs ADD COLUMN inbox_max INTEGER default 0").stepThis().dispose(); database.executeFast("ALTER TABLE dialogs ADD COLUMN outbox_max INTEGER default 0").stepThis().dispose(); database.executeFast("PRAGMA user_version = 17").stepThis().dispose(); - version = 17; + //version = 17; } } catch (Exception e) { FileLog.e("tmessages", e); @@ -764,7 +764,7 @@ public class MessagesStorage { public void run() { try { SQLiteCursor cursor = database.queryFinalized("SELECT data FROM wallpapers WHERE 1"); - ArrayList wallPapers = new ArrayList<>(); + final ArrayList wallPapers = new ArrayList<>(); while (cursor.next()) { ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0)); if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { @@ -774,7 +774,12 @@ public class MessagesStorage { buffersStorage.reuseFreeBuffer(data); } cursor.dispose(); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.wallpapersDidLoaded, wallPapers); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.wallpapersDidLoaded, wallPapers); + } + }); } catch (Exception e) { FileLog.e("tmessages", e); } @@ -1069,7 +1074,7 @@ public class MessagesStorage { int minDate = Integer.MAX_VALUE; SparseArray> messages = new SparseArray<>(); StringBuilder mids = new StringBuilder(); - SQLiteCursor cursor = null; + SQLiteCursor cursor; if (random_ids == null) { cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, ttl FROM messages WHERE uid = %d AND out = %d AND read_state != 0 AND ttl > 0 AND date <= %d AND send_state = 0 AND media != 1", ((long) chat_id) << 32, isOut, time)); } else { @@ -1763,7 +1768,7 @@ public class MessagesStorage { ArrayList replyMessages = new ArrayList<>(); HashMap> replyMessageOwners = new HashMap<>(); - SQLiteCursor cursor = null; + SQLiteCursor cursor; int lower_id = (int)dialog_id; if (lower_id != 0) { @@ -3241,7 +3246,6 @@ public class MessagesStorage { } finally { if (state != null) { state.dispose(); - state = null; } } @@ -3351,12 +3355,12 @@ public class MessagesStorage { try { if (inbox != null) { for (HashMap.Entry entry : inbox.entrySet()) { - database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = read_state | 1 WHERE uid = %d AND mid <= %d AND read_state IN(0,2) AND out = 0", entry.getKey(), entry.getValue())).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = read_state | 1 WHERE uid = %d AND mid > 0 AND mid <= %d AND read_state IN(0,2) AND out = 0", entry.getKey(), entry.getValue())).stepThis().dispose(); } } if (outbox != null) { for (HashMap.Entry entry : outbox.entrySet()) { - database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = read_state | 1 WHERE uid = %d AND mid <= %d AND read_state IN(0,2) AND out = 1", entry.getKey(), entry.getValue())).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = read_state | 1 WHERE uid = %d AND mid > 0 AND mid <= %d AND read_state IN(0,2) AND out = 1", entry.getKey(), entry.getValue())).stepThis().dispose(); } } if (encryptedMessages != null && !encryptedMessages.isEmpty()) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java index a75a4f64e..2092d378c 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java @@ -8,6 +8,10 @@ package org.telegram.android; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.FileLog; + import java.util.ArrayList; import java.util.HashMap; @@ -51,7 +55,6 @@ public class NotificationCenter { public static final int didSetPasscode = totalEvents++; public static final int didSetTwoStepPassword = totalEvents++; public static final int screenStateChanged = totalEvents++; - public static final int appSwitchedToForeground = totalEvents++; public static final int didLoadedReplyMessages = totalEvents++; public static final int newSessionReceived = totalEvents++; public static final int didReceivedWebpages = totalEvents++; @@ -94,14 +97,31 @@ public class NotificationCenter { public static final int audioDidStarted = totalEvents++; public static final int audioRouteChanged = totalEvents++; - final private HashMap> observers = new HashMap<>(); - - final private HashMap removeAfterBroadcast = new HashMap<>(); - final private HashMap addAfterBroadcast = new HashMap<>(); + private HashMap> observers = new HashMap<>(); + private HashMap removeAfterBroadcast = new HashMap<>(); + private HashMap addAfterBroadcast = new HashMap<>(); + private ArrayList delayedPosts = new ArrayList<>(10); private int broadcasting = 0; + private boolean animationInProgress; + + public interface NotificationCenterDelegate { + void didReceivedNotification(int id, Object... args); + } + + private class DelayedPost { + + private DelayedPost(int id, Object[] args) { + this.id = id; + this.args = args; + } + + private int id; + private Object[] args; + } private static volatile NotificationCenter Instance = null; + public static NotificationCenter getInstance() { NotificationCenter localInstance = Instance; if (localInstance == null) { @@ -115,66 +135,97 @@ public class NotificationCenter { return localInstance; } - public interface NotificationCenterDelegate { - void didReceivedNotification(int id, Object... args); + public void setAnimationInProgress(boolean value) { + animationInProgress = value; + if (!animationInProgress && !delayedPosts.isEmpty()) { + for (DelayedPost delayedPost : delayedPosts) { + postNotificationNameInternal(delayedPost.id, true, delayedPost.args); + } + delayedPosts.clear(); + } } public void postNotificationName(int id, Object... args) { - synchronized (observers) { - broadcasting++; - ArrayList objects = observers.get(id); - if (objects != null) { - for (Object obj : objects) { - ((NotificationCenterDelegate)obj).didReceivedNotification(id, args); - } + boolean allowDuringAnimation = false; + if (id == dialogsNeedReload || id == closeChats || id == messagesDidLoaded || id == mediaCountDidLoaded || id == mediaDidLoaded) { + allowDuringAnimation = true; + } + postNotificationNameInternal(id, allowDuringAnimation, args); + } + + public void postNotificationNameInternal(int id, boolean allowDuringAnimation, Object... args) { + if (BuildVars.DEBUG_VERSION) { + if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) { + throw new RuntimeException("postNotificationName allowed only from MAIN thread"); } - broadcasting--; - if (broadcasting == 0) { - if (!removeAfterBroadcast.isEmpty()) { - for (HashMap.Entry entry : removeAfterBroadcast.entrySet()) { - removeObserver(entry.getValue(), entry.getKey()); - } - removeAfterBroadcast.clear(); + } + if (!allowDuringAnimation && animationInProgress) { + DelayedPost delayedPost = new DelayedPost(id, args); + delayedPosts.add(delayedPost); + if (BuildVars.DEBUG_VERSION) { + FileLog.e("tmessages", "delay post notification " + id + " with args count = " + args.length); + } + return; + } + broadcasting++; + ArrayList objects = observers.get(id); + if (objects != null) { + for (Object obj : objects) { + ((NotificationCenterDelegate) obj).didReceivedNotification(id, args); + } + } + broadcasting--; + if (broadcasting == 0) { + if (!removeAfterBroadcast.isEmpty()) { + for (HashMap.Entry entry : removeAfterBroadcast.entrySet()) { + removeObserver(entry.getValue(), entry.getKey()); } - if (!addAfterBroadcast.isEmpty()) { - for (HashMap.Entry entry : addAfterBroadcast.entrySet()) { - addObserver(entry.getValue(), entry.getKey()); - } - addAfterBroadcast.clear(); + removeAfterBroadcast.clear(); + } + if (!addAfterBroadcast.isEmpty()) { + for (HashMap.Entry entry : addAfterBroadcast.entrySet()) { + addObserver(entry.getValue(), entry.getKey()); } + addAfterBroadcast.clear(); } } } public void addObserver(Object observer, int id) { - synchronized (observers) { - if (broadcasting != 0) { - addAfterBroadcast.put(id, observer); - return; + if (BuildVars.DEBUG_VERSION) { + if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) { + throw new RuntimeException("addObserver allowed only from MAIN thread"); } - ArrayList objects = observers.get(id); - if (objects == null) { - observers.put(id, (objects = new ArrayList<>())); - } - if (objects.contains(observer)) { - return; - } - objects.add(observer); } + if (broadcasting != 0) { + addAfterBroadcast.put(id, observer); + return; + } + ArrayList objects = observers.get(id); + if (objects == null) { + observers.put(id, (objects = new ArrayList<>())); + } + if (objects.contains(observer)) { + return; + } + objects.add(observer); } public void removeObserver(Object observer, int id) { - synchronized (observers) { - if (broadcasting != 0) { - removeAfterBroadcast.put(id, observer); - return; + if (BuildVars.DEBUG_VERSION) { + if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) { + throw new RuntimeException("removeObserver allowed only from MAIN thread"); } - ArrayList objects = observers.get(id); - if (objects != null) { - objects.remove(observer); - if (objects.size() == 0) { - observers.remove(id); - } + } + if (broadcasting != 0) { + removeAfterBroadcast.put(id, observer); + return; + } + ArrayList objects = observers.get(id); + if (objects != null) { + objects.remove(observer); + if (objects.size() == 0) { + observers.remove(id); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java index 2192b3663..67fb8fb3f 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java @@ -8,6 +8,7 @@ package org.telegram.android; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; @@ -59,9 +60,11 @@ public class NotificationsController { private HashMap smartNotificationsDialogs = new HashMap<>(); private NotificationManagerCompat notificationManager = null; private HashMap pushDialogs = new HashMap<>(); - private HashMap wearNoticationsIds = new HashMap<>(); + private HashMap wearNotificationsIds = new HashMap<>(); + private HashMap autoNotificationsIds = new HashMap<>(); private HashMap pushDialogsOverrideMention = new HashMap<>(); private int wearNotificationId = 10000; + private int autoNotificationId = 20000; public ArrayList popupMessages = new ArrayList<>(); private long openned_dialog_id = 0; private int total_unread_count = 0; @@ -70,10 +73,10 @@ public class NotificationsController { private int lastOnlineFromOtherDevice = 0; private boolean inChatSoundEnabled = true; private int lastBadgeCount; + private String launcherClassName; private long lastSoundPlay; - //private MediaPlayer mediaPlayerIn; - //private MediaPlayer mediaPlayerOut; + private long lastSoundOutPlay; private SoundPool soundPool; private int soundIn; private int soundOut; @@ -100,7 +103,6 @@ public class NotificationsController { try { audioManager = (AudioManager) ApplicationLoader.applicationContext.getSystemService(Context.AUDIO_SERVICE); - //mediaPlayer = new MediaPlayer(); } catch (Exception e) { FileLog.e("tmessages", e); } @@ -114,7 +116,8 @@ public class NotificationsController { pushMessagesDict.clear(); pushDialogs.clear(); popupMessages.clear(); - wearNoticationsIds.clear(); + wearNotificationsIds.clear(); + autoNotificationsIds.clear(); notifyCheck = false; lastBadgeCount = 0; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); @@ -376,13 +379,13 @@ public class NotificationsController { int needVibrate = 0; String choosenSoundPath = null; int ledColor = 0xff00ff00; - boolean inAppSounds = false; - boolean inAppVibrate = false; + boolean inAppSounds; + boolean inAppVibrate; boolean inAppPreview = false; - boolean inAppPriority = false; + boolean inAppPriority; int priority = 0; - int priorityOverride = 0; - int vibrateOverride = 0; + int priorityOverride; + int vibrateOverride; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); int notifyOverride = getNotifyOverride(preferences, override_dialog_id); @@ -517,7 +520,7 @@ public class NotificationsController { } PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_ONE_SHOT); - String name = null; + String name; boolean replace = true; if ((int)dialog_id == 0 || pushDialogs.size() > 1 || AndroidUtilities.needShowPasscode(false) || UserConfig.isWaitingForPasscodeEnter) { name = LocaleController.getString("AppName", R.string.AppName); @@ -530,7 +533,7 @@ public class NotificationsController { } } - String detailText = null; + String detailText; if (pushDialogs.size() == 1) { detailText = LocaleController.formatPluralString("NewMessages", total_unread_count); } else { @@ -547,12 +550,16 @@ public class NotificationsController { .setGroupSummary(true) .setColor(0xff2ca5e0); - if (priority == 0) { - mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT); - } else if (priority == 1) { - mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH); - } else if (priority == 2) { - mBuilder.setPriority(NotificationCompat.PRIORITY_MAX); + if (!notifyAboutLast) { + mBuilder.setPriority(NotificationCompat.PRIORITY_LOW); + } else { + if (priority == 0) { + mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT); + } else if (priority == 1) { + mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH); + } else if (priority == 2) { + mBuilder.setPriority(NotificationCompat.PRIORITY_MAX); + } } mBuilder.setCategory(NotificationCompat.CATEGORY_MESSAGE); @@ -649,18 +656,20 @@ public class NotificationsController { mBuilder.setVibrate(new long[]{0, 0}); } + showExtraNotifications(mBuilder, notifyAboutLast); notificationManager.notify(1, mBuilder.build()); if (preferences.getBoolean("EnablePebbleNotifications", false)) { sendAlertToPebble(lastMessageFull); } - showWearNotifications(notifyAboutLast); + scheduleNotificationRepeat(); } catch (Exception e) { FileLog.e("tmessages", e); } } - public void showWearNotifications(boolean notifyAboutLast) { + @SuppressLint("InlinedApi") + public void showExtraNotifications(NotificationCompat.Builder notificationBuilder, boolean notifyAboutLast) { if (Build.VERSION.SDK_INT < 19) { return; } @@ -681,16 +690,21 @@ public class NotificationsController { arrayList.add(messageObject); } - HashMap oldIds = new HashMap<>(); - oldIds.putAll(wearNoticationsIds); - wearNoticationsIds.clear(); + HashMap oldIdsWear = new HashMap<>(); + oldIdsWear.putAll(wearNotificationsIds); + wearNotificationsIds.clear(); + + HashMap oldIdsAuto = new HashMap<>(); + oldIdsAuto.putAll(autoNotificationsIds); + autoNotificationsIds.clear(); for (long dialog_id : sortedDialogs) { ArrayList messageObjects = messagesByDialogs.get(dialog_id); int max_id = messageObjects.get(0).getId(); + int max_date = messageObjects.get(0).messageOwner.date; TLRPC.Chat chat = null; TLRPC.User user = null; - String name = null; + String name; if (dialog_id > 0) { user = MessagesController.getInstance().getUser((int)dialog_id); if (user == null) { @@ -708,28 +722,56 @@ public class NotificationsController { name = ContactsController.formatName(user.first_name, user.last_name); } - Integer notificationId = oldIds.get(dialog_id); - if (notificationId == null) { - notificationId = wearNotificationId++; + Integer notificationIdWear = oldIdsWear.get(dialog_id); + if (notificationIdWear == null) { + notificationIdWear = wearNotificationId++; } else { - oldIds.remove(dialog_id); + oldIdsWear.remove(dialog_id); + } + + Integer notificationIdAuto = oldIdsAuto.get(dialog_id); + if (notificationIdAuto == null) { + notificationIdAuto = autoNotificationId++; + } else { + oldIdsAuto.remove(dialog_id); } Intent replyIntent = new Intent(ApplicationLoader.applicationContext, WearReplyReceiver.class); replyIntent.putExtra("dialog_id", dialog_id); replyIntent.putExtra("max_id", max_id); - PendingIntent replyPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, notificationId, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT); - RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY).setLabel(LocaleController.getString("Reply", R.string.Reply)).build(); + PendingIntent replyPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, notificationIdWear, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT); + RemoteInput remoteInputWear = new RemoteInput.Builder(EXTRA_VOICE_REPLY).setLabel(LocaleController.getString("Reply", R.string.Reply)).build(); String replyToString; if (chat != null) { replyToString = LocaleController.formatString("ReplyToGroup", R.string.ReplyToGroup, name); } else { replyToString = LocaleController.formatString("ReplyToUser", R.string.ReplyToUser, name); } - NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon, replyToString, replyPendingIntent).addRemoteInput(remoteInput).build(); + NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon, replyToString, replyPendingIntent).addRemoteInput(remoteInputWear).build(); + + Intent msgHeardIntent = new Intent(); + msgHeardIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + msgHeardIntent.setAction("org.telegram.messenger.ACTION_MESSAGE_HEARD"); + msgHeardIntent.putExtra("dialog_id", dialog_id); + msgHeardIntent.putExtra("max_id", max_id); + PendingIntent msgHeardPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, notificationIdAuto, msgHeardIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + Intent msgReplyIntent = new Intent(); + msgReplyIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + msgReplyIntent.setAction("org.telegram.messenger.ACTION_MESSAGE_REPLY"); + msgReplyIntent.putExtra("dialog_id", dialog_id); + msgReplyIntent.putExtra("max_id", max_id); + PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, notificationIdAuto, msgReplyIntent, PendingIntent.FLAG_UPDATE_CURRENT); + RemoteInput remoteInputAuto = new RemoteInput.Builder(NotificationsController.EXTRA_VOICE_REPLY).setLabel(LocaleController.getString("Reply", R.string.Reply)).build(); + + NotificationCompat.CarExtender.UnreadConversation.Builder unreadConvBuilder = new NotificationCompat.CarExtender.UnreadConversation.Builder(name) + .setReadPendingIntent(msgHeardPendingIntent) + .setReplyAction(msgReplyPendingIntent, remoteInputAuto) + .setLatestTimestamp((long) max_date * 1000); String text = ""; - for (MessageObject messageObject : messageObjects) { + for (int a = messageObjects.size() - 1; a >= 0; a--) { + MessageObject messageObject = messageObjects.get(a); String message = getStringForMessage(messageObject, false); if (message == null) { continue; @@ -743,8 +785,40 @@ public class NotificationsController { text += "\n\n"; } text += message; + + unreadConvBuilder.addMessage(message); } + + + TLRPC.FileLocation photoPath = null; + if (chat != null) { + if (chat.photo != null && chat.photo.photo_small != null && chat.photo.photo_small.volume_id != 0 && chat.photo.photo_small.local_id != 0) { + photoPath = chat.photo.photo_small; + } + } else { + if (user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) { + photoPath = user.photo.photo_small; + } + } + //notificationBuilder.extend(new NotificationCompat.CarExtender().setUnreadConversation(unreadConvBuilder.build())); + NotificationCompat.Builder builderAuto = new NotificationCompat.Builder(ApplicationLoader.applicationContext) + .setSmallIcon(R.drawable.notification) + .setColor(0xff2ca5e0) + .setGroup("messages") + .setLocalOnly(true) + //.setGroupSummary(false) + //.setCategory(NotificationCompat.CATEGORY_MESSAGE) + .extend(new NotificationCompat.CarExtender().setUnreadConversation(unreadConvBuilder.build())); + if (photoPath != null) { + BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(photoPath, null, "50_50"); + if (img != null) { + builderAuto.setLargeIcon(img.getBitmap()); + } + } + notificationManager.notify("android_auto", notificationIdAuto, builderAuto.build()); + autoNotificationsIds.put(dialog_id, notificationIdAuto); + Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class); intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE); intent.setFlags(32768); @@ -760,20 +834,30 @@ public class NotificationsController { .setSmallIcon(R.drawable.notification) .setGroup("messages") .setContentText(text) + .setColor(0xff2ca5e0) .setGroupSummary(false) .setContentIntent(contentIntent) .extend(new NotificationCompat.WearableExtender().addAction(action)) .setCategory(NotificationCompat.CATEGORY_MESSAGE); + if (photoPath != null) { + BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(photoPath, null, "50_50"); + if (img != null) { + builder.setLargeIcon(img.getBitmap()); + } + } if (chat == null && user != null && user.phone != null && user.phone.length() > 0) { builder.addPerson("tel:+" + user.phone); } - notificationManager.notify(notificationId, builder.build()); - wearNoticationsIds.put(dialog_id, notificationId); + notificationManager.notify(notificationIdWear, builder.build()); + wearNotificationsIds.put(dialog_id, notificationIdWear); } - for (HashMap.Entry entry : oldIds.entrySet()) { + for (HashMap.Entry entry : oldIdsAuto.entrySet()) { + notificationManager.cancel(entry.getValue()); + } + for (HashMap.Entry entry : oldIdsWear.entrySet()) { notificationManager.cancel(entry.getValue()); } } @@ -783,6 +867,14 @@ public class NotificationsController { notificationManager.cancel(1); pushMessages.clear(); pushMessagesDict.clear(); + for (HashMap.Entry entry : autoNotificationsIds.entrySet()) { + notificationManager.cancel(entry.getValue()); + } + autoNotificationsIds.clear(); + for (HashMap.Entry entry : wearNotificationsIds.entrySet()) { + notificationManager.cancel(entry.getValue()); + } + wearNotificationsIds.clear(); NotificationCenter.getInstance().postNotificationName(NotificationCenter.pushMessagesUpdated); } catch (Exception e) { FileLog.e("tmessages", e); @@ -893,29 +985,19 @@ public class NotificationsController { try { if (soundPool == null) { soundPool = new SoundPool(4, AudioManager.STREAM_SYSTEM, 0); + soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() { + @Override + public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { + if (status == 0) { + soundPool.play(sampleId, 1.0f, 1.0f, 1, 0, 1.0f); + } + } + }); } if (soundIn == 0) { soundIn = soundPool.load(ApplicationLoader.applicationContext, R.raw.sound_in, 1); } soundPool.play(soundIn, 1.0f, 1.0f, 1, 0, 1.0f); - /*if (mediaPlayerIn == null) { - AssetFileDescriptor assetFileDescriptor = ApplicationLoader.applicationContext.getResources().openRawResourceFd(R.raw.sound_in); - if (assetFileDescriptor != null) { - mediaPlayerIn = new MediaPlayer(); - mediaPlayerIn.setAudioStreamType(AudioManager.STREAM_SYSTEM); - mediaPlayerIn.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength()); - mediaPlayerIn.setLooping(false); - assetFileDescriptor.close(); - mediaPlayerIn.prepare(); - } - } - try { - mediaPlayerIn.pause(); - mediaPlayerIn.seekTo(0); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - mediaPlayerIn.start();*/ } catch (Exception e) { FileLog.e("tmessages", e); } @@ -941,31 +1023,25 @@ public class NotificationsController { @Override public void run() { try { + if (lastSoundOutPlay > System.currentTimeMillis() - 100) { + return; + } + lastSoundOutPlay = System.currentTimeMillis(); if (soundPool == null) { soundPool = new SoundPool(4, AudioManager.STREAM_SYSTEM, 0); + soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() { + @Override + public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { + if (status == 0) { + soundPool.play(sampleId, 1.0f, 1.0f, 1, 0, 1.0f); + } + } + }); } if (soundOut == 0) { soundOut = soundPool.load(ApplicationLoader.applicationContext, R.raw.sound_out, 1); } soundPool.play(soundOut, 1.0f, 1.0f, 1, 0, 1.0f); - /*if (mediaPlayerOut == null) { - AssetFileDescriptor assetFileDescriptor = ApplicationLoader.applicationContext.getResources().openRawResourceFd(R.raw.sound_out); - if (assetFileDescriptor != null) { - mediaPlayerOut = new MediaPlayer(); - mediaPlayerOut.setAudioStreamType(AudioManager.STREAM_SYSTEM); - mediaPlayerOut.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength()); - mediaPlayerOut.setLooping(false); - assetFileDescriptor.close(); - mediaPlayerOut.prepare(); - } - } - try { - mediaPlayerOut.pause(); - mediaPlayerOut.seekTo(0); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - mediaPlayerOut.start();*/ } catch (Exception e) { FileLog.e("tmessages", e); } @@ -1109,13 +1185,9 @@ public class NotificationsController { delayedPushMessages.clear(); showOrUpdateNotification(notifyCheck); } else { - showOrUpdateNotification(false); scheduleNotificationDelay(lastOnlineFromOtherDevice > ConnectionsManager.getInstance().getCurrentTime()); } } - /*if (old_unread_count != total_unread_count) { - showOrUpdateNotification(notifyCheck); - }*/ notifyCheck = false; if (preferences.getBoolean("badgeNumber", true)) { setBadge(ApplicationLoader.applicationContext, total_unread_count); @@ -1217,15 +1289,24 @@ public class NotificationsController { //ignore } try { - String launcherClassName = getLauncherClassName(context); + launcherClassName = getLauncherClassName(context); if (launcherClassName == null) { return; } - Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); - intent.putExtra("badge_count", count); - intent.putExtra("badge_count_package_name", context.getPackageName()); - intent.putExtra("badge_count_class_name", launcherClassName); - context.sendBroadcast(intent); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); + intent.putExtra("badge_count", count); + intent.putExtra("badge_count_package_name", context.getPackageName()); + intent.putExtra("badge_count_class_name", launcherClassName); + context.sendBroadcast(intent); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); } catch (Throwable e) { FileLog.e("tmessages", e); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/ScreenReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/ScreenReceiver.java index d7824f18b..90c1e2bf1 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ScreenReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ScreenReceiver.java @@ -17,6 +17,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.ApplicationLoader; public class ScreenReceiver extends BroadcastReceiver { + @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/android/SecretChatHelper.java index 2866763ac..5d793ea3d 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/android/SecretChatHelper.java @@ -48,6 +48,7 @@ public class SecretChatHelper { private boolean startingSecretChat = false; private static volatile SecretChatHelper Instance = null; + public static SecretChatHelper getInstance() { SecretChatHelper localInstance = Instance; if (localInstance == null) { @@ -87,7 +88,7 @@ public class SecretChatHelper { newMsg.local_id = newMsg.id = UserConfig.getNewMessageId(); newMsg.from_id = UserConfig.getClientUserId(); newMsg.flags = TLRPC.MESSAGE_FLAG_UNREAD | TLRPC.MESSAGE_FLAG_OUT; - newMsg.dialog_id = ((long)encryptedChat.id) << 32; + newMsg.dialog_id = ((long) encryptedChat.id) << 32; newMsg.to_id = new TLRPC.TL_peerUser(); newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; if (encryptedChat.participant_id == UserConfig.getClientUserId()) { @@ -114,7 +115,7 @@ public class SecretChatHelper { if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -123,7 +124,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -140,7 +141,7 @@ public class SecretChatHelper { protected void processUpdateEncryption(TLRPC.TL_updateEncryption update, ConcurrentHashMap usersDict) { final TLRPC.EncryptedChat newChat = update.chat; - long dialog_id = ((long)newChat.id) << 32; + long dialog_id = ((long) newChat.id) << 32; TLRPC.EncryptedChat existingChat = MessagesController.getInstance().getEncryptedChatDB(newChat.id); if (newChat instanceof TLRPC.TL_encryptedChatRequested && existingChat == null) { @@ -219,7 +220,7 @@ public class SecretChatHelper { if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -228,7 +229,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -247,7 +248,7 @@ public class SecretChatHelper { if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -256,7 +257,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -278,7 +279,7 @@ public class SecretChatHelper { return; } sendingNotifyLayer.add(encryptedChat.id); - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -287,7 +288,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -307,7 +308,7 @@ public class SecretChatHelper { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -316,7 +317,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -338,7 +339,7 @@ public class SecretChatHelper { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -347,7 +348,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -370,7 +371,7 @@ public class SecretChatHelper { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -379,7 +380,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -401,7 +402,7 @@ public class SecretChatHelper { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -410,7 +411,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -431,7 +432,7 @@ public class SecretChatHelper { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -440,7 +441,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -459,7 +460,7 @@ public class SecretChatHelper { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -468,7 +469,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -495,7 +496,7 @@ public class SecretChatHelper { return; } - TLRPC.TL_decryptedMessageService reqSend = null; + TLRPC.TL_decryptedMessageService reqSend; if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend = new TLRPC.TL_decryptedMessageService(); } else { @@ -504,7 +505,7 @@ public class SecretChatHelper { Utilities.random.nextBytes(reqSend.random_bytes); } - TLRPC.Message message = null; + TLRPC.Message message; if (resendMessage != null) { message = resendMessage; @@ -654,7 +655,7 @@ public class SecretChatHelper { Utilities.stageQueue.postRunnable(new Runnable() { @Override public void run() { - TLObject toEncryptObject = null; + TLObject toEncryptObject; if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 17) { TLRPC.TL_decryptedMessageLayer layer = new TLRPC.TL_decryptedMessageLayer(); int myLayer = Math.max(17, AndroidUtilities.getMyLayerVersion(chat.layer)); @@ -710,7 +711,7 @@ public class SecretChatHelper { byte[] messageKey = new byte[16]; System.arraycopy(messageKeyFull, messageKeyFull.length - 16, messageKey, 0, 16); - MessageKeyData keyData = Utilities.generateMessageKeyData(chat.auth_key, messageKey, false); + MessageKeyData keyData = MessageKeyData.generateMessageKeyData(chat.auth_key, messageKey, false); len = toEncrypt.length(); int extraLen = len % 16 != 0 ? 16 - len % 16 : 0; @@ -734,7 +735,7 @@ public class SecretChatHelper { BuffersStorage.getInstance().reuseFreeBuffer(dataForEncryption); data.position(0); - TLObject reqToSend = null; + TLObject reqToSend; if (encryptedFile == null) { if (req instanceof TLRPC.TL_decryptedMessageService) { @@ -770,7 +771,7 @@ public class SecretChatHelper { if (error == null) { if (req.action instanceof TLRPC.TL_decryptedMessageActionNotifyLayer) { TLRPC.EncryptedChat currentChat = MessagesController.getInstance().getEncryptedChat(chat.id); - sendingNotifyLayer.remove((Integer)currentChat.id); + sendingNotifyLayer.remove((Integer) currentChat.id); currentChat.layer = AndroidUtilities.setMyLayerVersion(currentChat.layer, CURRENT_SECRET_CHAT_LAYER); MessagesStorage.getInstance().updateEncryptedChatLayer(currentChat); } @@ -857,8 +858,8 @@ public class SecretChatHelper { } if (object instanceof TLRPC.TL_decryptedMessage) { - TLRPC.TL_decryptedMessage decryptedMessage = (TLRPC.TL_decryptedMessage)object; - TLRPC.TL_message newMessage = null; + TLRPC.TL_decryptedMessage decryptedMessage = (TLRPC.TL_decryptedMessage) object; + TLRPC.TL_message newMessage; if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 17) { newMessage = new TLRPC.TL_message_secret(); newMessage.ttl = decryptedMessage.ttl; @@ -875,7 +876,7 @@ public class SecretChatHelper { newMessage.random_id = random_id; newMessage.to_id.user_id = UserConfig.getClientUserId(); newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; - newMessage.dialog_id = ((long)chat.id) << 32; + newMessage.dialog_id = ((long) chat.id) << 32; if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) { newMessage.media = new TLRPC.TL_messageMediaEmpty(); } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaContact) { @@ -899,11 +900,12 @@ public class SecretChatHelper { newMessage.media.photo.user_id = newMessage.from_id; newMessage.media.photo.date = newMessage.date; newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty(); - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { + byte[] thumb = ((TLRPC.TL_decryptedMessageMediaPhoto) decryptedMessage.media).thumb; + if (thumb != null && thumb.length != 0 && thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize(); small.w = decryptedMessage.media.thumb_w; small.h = decryptedMessage.media.thumb_h; - small.bytes = decryptedMessage.media.thumb; + small.bytes = thumb; small.type = "s"; small.location = new TLRPC.TL_fileLocationUnavailable(); newMessage.media.photo.sizes.add(small); @@ -929,9 +931,10 @@ public class SecretChatHelper { newMessage.media = new TLRPC.TL_messageMediaVideo(); newMessage.media.caption = ""; newMessage.media.video = new TLRPC.TL_videoEncrypted(); - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { + byte[] thumb = ((TLRPC.TL_decryptedMessageMediaVideo) decryptedMessage.media).thumb; + if (thumb != null && thumb.length != 0 && thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize(); - newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb; + newMessage.media.video.thumb.bytes = thumb; newMessage.media.video.thumb.w = decryptedMessage.media.thumb_w; newMessage.media.video.thumb.h = decryptedMessage.media.thumb_h; newMessage.media.video.thumb.type = "s"; @@ -975,9 +978,10 @@ public class SecretChatHelper { newMessage.media.document.size = file.size; newMessage.media.document.key = decryptedMessage.media.key; newMessage.media.document.iv = decryptedMessage.media.iv; - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { + byte[] thumb = ((TLRPC.TL_decryptedMessageMediaDocument) decryptedMessage.media).thumb; + if (thumb != null && thumb.length != 0 && thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { newMessage.media.document.thumb = new TLRPC.TL_photoCachedSize(); - newMessage.media.document.thumb.bytes = decryptedMessage.media.thumb; + newMessage.media.document.thumb.bytes = thumb; newMessage.media.document.thumb.w = decryptedMessage.media.thumb_w; newMessage.media.document.thumb.h = decryptedMessage.media.thumb_h; newMessage.media.document.thumb.type = "s"; @@ -997,7 +1001,7 @@ public class SecretChatHelper { newMessage.media.document.mime_type = decryptedMessage.media.mime_type; newMessage.media.document.dc_id = decryptedMessage.media.dc_id; newMessage.media.document.size = decryptedMessage.media.size; - newMessage.media.document.thumb = decryptedMessage.media.thumbImage; + newMessage.media.document.thumb = ((TLRPC.TL_decryptedMessageMediaExternalDocument) decryptedMessage.media).thumb; } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaAudio) { if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { return null; @@ -1025,7 +1029,7 @@ public class SecretChatHelper { } return newMessage; } else if (object instanceof TLRPC.TL_decryptedMessageService) { - final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService)object; + final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService) object; if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL || serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) { TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService(); if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { @@ -1047,10 +1051,10 @@ public class SecretChatHelper { newMessage.from_id = from_id; newMessage.to_id = new TLRPC.TL_peerUser(); newMessage.to_id.user_id = UserConfig.getClientUserId(); - newMessage.dialog_id = ((long)chat.id) << 32; + newMessage.dialog_id = ((long) chat.id) << 32; return newMessage; } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionFlushHistory) { - final long did = ((long)chat.id) << 32; + final long did = ((long) chat.id) << 32; AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { @@ -1314,7 +1318,7 @@ public class SecretChatHelper { if (keyToDecrypt != null) { byte[] messageKey = is.readData(16, false); - MessageKeyData keyData = Utilities.generateMessageKeyData(keyToDecrypt, messageKey, false); + MessageKeyData keyData = MessageKeyData.generateMessageKeyData(keyToDecrypt, messageKey, false); Utilities.aesIgeEncryption(is.buffer, keyData.aesKey, keyData.aesIv, false, false, 24, is.limit() - 24); @@ -1327,19 +1331,14 @@ public class SecretChatHelper { return null; } - TLObject object = null; - try { - object = TLClassStore.Instance().TLdeserialize(is, is.readInt32(true), true); - } catch (Exception e) { - FileLog.e("tmessages", e); - } + TLObject object = TLClassStore.Instance().TLdeserialize(is, is.readInt32(false), false); BuffersStorage.getInstance().reuseFreeBuffer(is); if (!new_key_used && AndroidUtilities.getPeerLayerVersion(chat.layer) >= 20) { chat.key_use_count_in++; } if (object instanceof TLRPC.TL_decryptedMessageLayer) { - final TLRPC.TL_decryptedMessageLayer layer = (TLRPC.TL_decryptedMessageLayer)object; + final TLRPC.TL_decryptedMessageLayer layer = (TLRPC.TL_decryptedMessageLayer) object; if (chat.seq_in == 0 && chat.seq_out == 0) { if (chat.admin_id == UserConfig.getClientUserId()) { chat.seq_out = 1; diff --git a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java index 8cef20598..3aa324556 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java @@ -56,9 +56,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter public String httpLocation; public MessageObject obj; public TLRPC.EncryptedChat encryptedChat; + public VideoEditedInfo videoEditedInfo; } private static volatile SendMessagesHelper Instance = null; + public static SendMessagesHelper getInstance() { SendMessagesHelper localInstance = Instance; if (localInstance == null) { @@ -94,113 +96,100 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } @Override - public void didReceivedNotification(int id, Object... args) { + public void didReceivedNotification(int id, final Object... args) { if (id == NotificationCenter.FileDidUpload) { - final String location = (String)args[0]; - final TLRPC.InputFile file = (TLRPC.InputFile)args[1]; - final TLRPC.InputEncryptedFile encryptedFile = (TLRPC.InputEncryptedFile)args[2]; + final String location = (String) args[0]; + final TLRPC.InputFile file = (TLRPC.InputFile) args[1]; + final TLRPC.InputEncryptedFile encryptedFile = (TLRPC.InputEncryptedFile) args[2]; + ArrayList arr = delayedMessages.get(location); + if (arr != null) { + for (int a = 0; a < arr.size(); a++) { + DelayedMessage message = arr.get(a); + TLRPC.InputMedia media = null; + if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) { + media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media; + } else if (message.sendRequest instanceof TLRPC.TL_messages_sendBroadcast) { + media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media; + } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - ArrayList arr = delayedMessages.get(location); - if (arr != null) { - for (int a = 0; a < arr.size(); a++) { - DelayedMessage message = arr.get(a); - TLRPC.InputMedia media = null; - if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) { - media = ((TLRPC.TL_messages_sendMedia)message.sendRequest).media; - } else if (message.sendRequest instanceof TLRPC.TL_messages_sendBroadcast) { - media = ((TLRPC.TL_messages_sendBroadcast)message.sendRequest).media; - } - - if (file != null && media != null) { - if (message.type == 0) { - media.file = file; - performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); - } else if (message.type == 1) { - if (media.file == null) { - media.file = file; - if (media.thumb == null && message.location != null) { - performSendDelayedMessage(message); - } else { - performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); - } - } else { - media.thumb = file; - performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); - } - } else if (message.type == 2) { - if (media.file == null) { - media.file = file; - if (media.thumb == null && message.location != null) { - performSendDelayedMessage(message); - } else { - performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); - } - } else { - media.thumb = file; - performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); - } - } else if (message.type == 3) { - media.file = file; + if (file != null && media != null) { + if (message.type == 0) { + media.file = file; + performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); + } else if (message.type == 1) { + if (media.file == null) { + media.file = file; + if (media.thumb == null && message.location != null) { + performSendDelayedMessage(message); + } else { performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); } - arr.remove(a); - a--; - } else if (encryptedFile != null && message.sendEncryptedRequest != null) { - message.sendEncryptedRequest.media.key = encryptedFile.key; - message.sendEncryptedRequest.media.iv = encryptedFile.iv; - SecretChatHelper.getInstance().performSendEncryptedRequest(message.sendEncryptedRequest, message.obj.messageOwner, message.encryptedChat, encryptedFile, message.originalPath); - arr.remove(a); - a--; + } else { + media.thumb = file; + performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); } + } else if (message.type == 2) { + if (media.file == null) { + media.file = file; + if (media.thumb == null && message.location != null) { + performSendDelayedMessage(message); + } else { + performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); + } + } else { + media.thumb = file; + performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); + } + } else if (message.type == 3) { + media.file = file; + performSendMessageRequest(message.sendRequest, message.obj.messageOwner, message.originalPath); } - if (arr.isEmpty()) { - delayedMessages.remove(location); - } + arr.remove(a); + a--; + } else if (encryptedFile != null && message.sendEncryptedRequest != null) { + message.sendEncryptedRequest.media.key = (byte[]) args[3]; + message.sendEncryptedRequest.media.iv = (byte[]) args[4]; + SecretChatHelper.getInstance().performSendEncryptedRequest(message.sendEncryptedRequest, message.obj.messageOwner, message.encryptedChat, encryptedFile, message.originalPath); + arr.remove(a); + a--; } } - }); + if (arr.isEmpty()) { + delayedMessages.remove(location); + } + } } else if (id == NotificationCenter.FileDidFailUpload) { final String location = (String) args[0]; final boolean enc = (Boolean) args[1]; - - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - ArrayList arr = delayedMessages.get(location); - if (arr != null) { - for (int a = 0; a < arr.size(); a++) { - DelayedMessage obj = arr.get(a); - if (enc && obj.sendEncryptedRequest != null || !enc && obj.sendRequest != null) { - MessagesStorage.getInstance().markMessageAsSendError(obj.obj.getId()); - obj.obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; - arr.remove(a); - a--; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, obj.obj.getId()); - processSentMessage(obj.obj.getId()); - } - } - if (arr.isEmpty()) { - delayedMessages.remove(location); - } + ArrayList arr = delayedMessages.get(location); + if (arr != null) { + for (int a = 0; a < arr.size(); a++) { + DelayedMessage obj = arr.get(a); + if (enc && obj.sendEncryptedRequest != null || !enc && obj.sendRequest != null) { + MessagesStorage.getInstance().markMessageAsSendError(obj.obj.getId()); + obj.obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; + arr.remove(a); + a--; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, obj.obj.getId()); + processSentMessage(obj.obj.getId()); } } - }); + if (arr.isEmpty()) { + delayedMessages.remove(location); + } + } } else if (id == NotificationCenter.FilePreparingStarted) { - MessageObject messageObject = (MessageObject)args[0]; - String finalPath = (String)args[1]; + MessageObject messageObject = (MessageObject) args[0]; + String finalPath = (String) args[1]; ArrayList arr = delayedMessages.get(messageObject.messageOwner.attachPath); if (arr != null) { for (int a = 0; a < arr.size(); a++) { DelayedMessage message = arr.get(a); if (message.obj == messageObject) { - message.videoLocation.videoEditedInfo = null; + message.videoEditedInfo = null; performSendDelayedMessage(message); arr.remove(a); - a--; break; } } @@ -209,19 +198,19 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } } else if (id == NotificationCenter.FileNewChunkAvailable) { - MessageObject messageObject = (MessageObject)args[0]; - String finalPath = (String)args[1]; - long finalSize = (Long)args[2]; - boolean isEncrypted = ((int)messageObject.getDialogId()) == 0; + MessageObject messageObject = (MessageObject) args[0]; + String finalPath = (String) args[1]; + long finalSize = (Long) args[2]; + boolean isEncrypted = ((int) messageObject.getDialogId()) == 0; FileLoader.getInstance().checkUploadNewDataAvailable(finalPath, isEncrypted, finalSize); if (finalSize != 0) { ArrayList arr = delayedMessages.get(messageObject.messageOwner.attachPath); if (arr != null) { for (DelayedMessage message : arr) { if (message.obj == messageObject) { - message.obj.messageOwner.videoEditedInfo = null; + message.obj.videoEditedInfo = null; message.obj.messageOwner.message = "-1"; - message.obj.messageOwner.media.video.size = (int)finalSize; + message.obj.messageOwner.media.video.size = (int) finalSize; ArrayList messages = new ArrayList<>(); messages.add(message.obj.messageOwner); @@ -235,8 +224,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } } else if (id == NotificationCenter.FilePreparingFailed) { - MessageObject messageObject = (MessageObject)args[0]; - String finalPath = (String)args[1]; + MessageObject messageObject = (MessageObject) args[0]; + String finalPath = (String) args[1]; stopVideoService(messageObject.messageOwner.attachPath); ArrayList arr = delayedMessages.get(finalPath); @@ -257,8 +246,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } } else if (id == NotificationCenter.httpFileDidLoaded) { - String path = (String)args[0]; - String file = (String)args[1]; + String path = (String) args[0]; + String file = (String) args[1]; ArrayList arr = delayedMessages.get(path); if (arr != null) { for (final DelayedMessage message : arr) { @@ -334,7 +323,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessages.remove(path); } } else if (id == NotificationCenter.httpFileDidFailedLoad) { - String path = (String)args[0]; + String path = (String) args[0]; ArrayList arr = delayedMessages.get(path); if (arr != null) { @@ -454,8 +443,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter sendMessage((TLRPC.TL_audio) messageObject.messageOwner.media.audio, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject); } else if (messageObject.messageOwner.media.video instanceof TLRPC.TL_video) { TLRPC.TL_video video = (TLRPC.TL_video) messageObject.messageOwner.media.video; - video.videoEditedInfo = messageObject.messageOwner.videoEditedInfo; - sendMessage(video, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject); + sendMessage(video, messageObject.videoEditedInfo, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject); } else if (messageObject.messageOwner.media.document instanceof TLRPC.TL_document) { sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo) { @@ -527,7 +515,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } public void sendMessage(TLRPC.User user, long peer, MessageObject reply_to_msg) { - sendMessage(null, null, null, null, null, user, null, null, null, peer, false, null, reply_to_msg, null, true); + sendMessage(null, null, null, null, null, null, user, null, null, null, peer, false, null, reply_to_msg, null, true); } public void sendMessage(ArrayList messages, long peer) { @@ -703,38 +691,38 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } public void sendMessage(MessageObject message) { - sendMessage(null, null, null, null, message, null, null, null, null, message.getDialogId(), true, message.messageOwner.attachPath, null, null, true); + sendMessage(null, null, null, null, null, message, null, null, null, null, message.getDialogId(), true, message.messageOwner.attachPath, null, null, true); } public void sendMessage(MessageObject message, long peer) { - sendMessage(null, null, null, null, message, null, null, null, null, peer, false, message.messageOwner.attachPath, null, null, true); + sendMessage(null, null, null, null, null, message, null, null, null, null, peer, false, message.messageOwner.attachPath, null, null, true); } public void sendMessage(TLRPC.TL_document document, String originalPath, String path, long peer, MessageObject reply_to_msg) { - sendMessage(null, null, null, null, null, null, document, null, originalPath, peer, false, path, reply_to_msg, null, true); + sendMessage(null, null, null, null, null, null, null, document, null, originalPath, peer, false, path, reply_to_msg, null, true); } public void sendMessage(String message, long peer, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks) { - sendMessage(message, null, null, null, null, null, null, null, null, peer, false, null, reply_to_msg, webPage, searchLinks); + sendMessage(message, null, null, null, null, null, null, null, null, null, peer, false, null, reply_to_msg, webPage, searchLinks); } public void sendMessage(TLRPC.MessageMedia location, long peer, MessageObject reply_to_msg) { - sendMessage(null, location, null, null, null, null, null, null, null, peer, false, null, reply_to_msg, null, true); + sendMessage(null, location, null, null, null, null, null, null, null, null, peer, false, null, reply_to_msg, null, true); } public void sendMessage(TLRPC.TL_photo photo, String originalPath, String path, long peer, MessageObject reply_to_msg) { - sendMessage(null, null, photo, null, null, null, null, null, originalPath, peer, false, path, reply_to_msg, null, true); + sendMessage(null, null, photo, null, null, null, null, null, null, originalPath, peer, false, path, reply_to_msg, null, true); } - public void sendMessage(TLRPC.TL_video video, String originalPath, String path, long peer, MessageObject reply_to_msg) { - sendMessage(null, null, null, video, null, null, null, null, originalPath, peer, false, path, reply_to_msg, null, true); + public void sendMessage(TLRPC.TL_video video, VideoEditedInfo videoEditedInfo, String originalPath, String path, long peer, MessageObject reply_to_msg) { + sendMessage(null, null, null, video, videoEditedInfo, null, null, null, null, originalPath, peer, false, path, reply_to_msg, null, true); } public void sendMessage(TLRPC.TL_audio audio, String path, long peer, MessageObject reply_to_msg) { - sendMessage(null, null, null, null, null, null, null, audio, null, peer, false, path, reply_to_msg, null, true); + sendMessage(null, null, null, null, null, null, null, null, audio, null, peer, false, path, reply_to_msg, null, true); } - private void sendMessage(String message, TLRPC.MessageMedia location, TLRPC.TL_photo photo, TLRPC.TL_video video, MessageObject msgObj, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, boolean retry, String path, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks) { + private void sendMessage(String message, TLRPC.MessageMedia location, TLRPC.TL_photo photo, TLRPC.TL_video video, VideoEditedInfo videoEditedInfo, MessageObject msgObj, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, boolean retry, String path, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks) { if (peer == 0) { return; } @@ -776,7 +764,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else { type = 3; video = (TLRPC.TL_video) newMsg.media.video; - video.videoEditedInfo = newMsg.videoEditedInfo; } } else if (msgObj.type == 12) { user = new TLRPC.TL_userRequest(); @@ -842,12 +829,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter newMsg.media = new TLRPC.TL_messageMediaVideo(); newMsg.media.caption = video.caption != null ? video.caption : ""; newMsg.media.video = video; - newMsg.videoEditedInfo = video.videoEditedInfo; type = 3; - if (video.videoEditedInfo == null) { + if (videoEditedInfo == null) { newMsg.message = "-1"; } else { - newMsg.message = video.videoEditedInfo.getString(); + newMsg.message = videoEditedInfo.getString(); } newMsg.attachPath = path; } else if (msgObj != null) { @@ -1093,6 +1079,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.obj = newMsgObj; delayedMessage.location = video.thumb.location; delayedMessage.videoLocation = video; + delayedMessage.videoEditedInfo = videoEditedInfo; } else { TLRPC.TL_inputMediaVideo media = new TLRPC.TL_inputMediaVideo(); media.id = new TLRPC.TL_inputVideo(); @@ -1149,7 +1136,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } - TLObject reqSend = null; + TLObject reqSend; if (sendToPeers != null) { TLRPC.TL_messages_sendBroadcast request = new TLRPC.TL_messages_sendBroadcast(); @@ -1229,7 +1216,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.PhotoSize small = photo.sizes.get(0); TLRPC.PhotoSize big = photo.sizes.get(photo.sizes.size() - 1); reqSend.media = new TLRPC.TL_decryptedMessageMediaPhoto(); - reqSend.media.thumb = small.bytes; + ImageLoader.fillPhotoSizeWithBytes(small); + if (small.bytes != null) { + ((TLRPC.TL_decryptedMessageMediaPhoto) reqSend.media).thumb = small.bytes; + } else { + ((TLRPC.TL_decryptedMessageMediaPhoto) reqSend.media).thumb = new byte[0]; + } reqSend.media.thumb_h = small.h; reqSend.media.thumb_w = small.w; reqSend.media.w = big.w; @@ -1257,16 +1249,26 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter SecretChatHelper.getInstance().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, encryptedFile, null); } } else if (type == 3) { + ImageLoader.fillPhotoSizeWithBytes(video.thumb); if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { reqSend.media = new TLRPC.TL_decryptedMessageMediaVideo(); + if (video.thumb != null && video.thumb.bytes != null) { + ((TLRPC.TL_decryptedMessageMediaVideo) reqSend.media).thumb = video.thumb.bytes; + } else { + ((TLRPC.TL_decryptedMessageMediaVideo) reqSend.media).thumb = new byte[0]; + } } else { reqSend.media = new TLRPC.TL_decryptedMessageMediaVideo_old(); + if (video.thumb != null && video.thumb.bytes != null) { + ((TLRPC.TL_decryptedMessageMediaVideo_old) reqSend.media).thumb = video.thumb.bytes; + } else { + ((TLRPC.TL_decryptedMessageMediaVideo_old) reqSend.media).thumb = new byte[0]; + } } reqSend.media.duration = video.duration; reqSend.media.size = video.size; reqSend.media.w = video.w; reqSend.media.h = video.h; - reqSend.media.thumb = video.thumb.bytes; reqSend.media.thumb_h = video.thumb.h; reqSend.media.thumb_w = video.thumb.w; reqSend.media.mime_type = "video/mp4"; @@ -1278,6 +1280,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.obj = newMsgObj; delayedMessage.encryptedChat = encryptedChat; delayedMessage.videoLocation = video; + delayedMessage.videoEditedInfo = videoEditedInfo; performSendDelayedMessage(delayedMessage); } else { TLRPC.TL_inputEncryptedFile encryptedFile = new TLRPC.TL_inputEncryptedFile(); @@ -1305,21 +1308,27 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter reqSend.media = new TLRPC.TL_decryptedMessageMediaExternalDocument(); reqSend.media.id = document.id; reqSend.media.date = document.date; + reqSend.media.access_hash = document.access_hash; reqSend.media.mime_type = document.mime_type; reqSend.media.size = document.size; - ((TLRPC.TL_decryptedMessageMediaExternalDocument) reqSend.media).thumbImage = document.thumb; reqSend.media.dc_id = document.dc_id; reqSend.media.attributes = document.attributes; + if (document.thumb == null) { + ((TLRPC.TL_decryptedMessageMediaExternalDocument) reqSend.media).thumb = new TLRPC.TL_photoSizeEmpty(); + } else { + ((TLRPC.TL_decryptedMessageMediaExternalDocument) reqSend.media).thumb = document.thumb; + } SecretChatHelper.getInstance().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null); } else { + ImageLoader.fillPhotoSizeWithBytes(document.thumb); reqSend.media = new TLRPC.TL_decryptedMessageMediaDocument(); reqSend.media.size = document.size; - if (!(document.thumb instanceof TLRPC.TL_photoSizeEmpty)) { - reqSend.media.thumb = document.thumb.bytes; + if (document.thumb != null && document.thumb.bytes != null) { + ((TLRPC.TL_decryptedMessageMediaDocument) reqSend.media).thumb = document.thumb.bytes; reqSend.media.thumb_h = document.thumb.h; reqSend.media.thumb_w = document.thumb.w; } else { - reqSend.media.thumb = new byte[0]; + ((TLRPC.TL_decryptedMessageMediaDocument) reqSend.media).thumb = new byte[0]; reqSend.media.thumb_h = 0; reqSend.media.thumb_w = 0; } @@ -1401,7 +1410,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } } else if (message.type == 1) { - if (message.videoLocation.videoEditedInfo != null) { + if (message.videoEditedInfo != null) { String location = message.obj.messageOwner.attachPath; if (location == null) { location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.videoLocation.id + ".mp4"; @@ -1410,10 +1419,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter MediaController.getInstance().scheduleVideoConvert(message.obj); } else { if (message.sendRequest != null) { - TLRPC.InputMedia media = null; + TLRPC.InputMedia media; if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) { media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media; - } else if (message.sendRequest instanceof TLRPC.TL_messages_sendBroadcast) { + } else { media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media; } if (media.file == null) { @@ -1422,7 +1431,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.videoLocation.id + ".mp4"; } putToDelayedMessages(location, message); - if (message.obj.messageOwner.videoEditedInfo != null) { + if (message.obj.videoEditedInfo != null) { FileLoader.getInstance().uploadFile(location, false, false, message.videoLocation.size); } else { FileLoader.getInstance().uploadFile(location, false, false); @@ -1438,7 +1447,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.videoLocation.id + ".mp4"; } putToDelayedMessages(location, message); - if (message.obj.messageOwner.videoEditedInfo != null) { + if (message.obj.videoEditedInfo != null) { FileLoader.getInstance().uploadFile(location, true, false, message.videoLocation.size); } else { FileLoader.getInstance().uploadFile(location, true, false); @@ -1451,10 +1460,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ImageLoader.getInstance().loadHttpFile(message.httpLocation, "gif"); } else { if (message.sendRequest != null) { - TLRPC.InputMedia media = null; + TLRPC.InputMedia media; if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) { media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media; - } else if (message.sendRequest instanceof TLRPC.TL_messages_sendBroadcast) { + } else { media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media; } if (media.file == null) { @@ -1575,7 +1584,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ArrayList arr = new ArrayList<>(); MessageObject messageObject = new MessageObject(message, null, false); arr.add(messageObject); - MessagesController.getInstance().updateInterfaceWithMessages(messageObject.getDialogId(), arr, isBroadcast); + MessagesController.getInstance().updateInterfaceWithMessages(messageObject.getDialogId(), arr, true); } NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); } @@ -1632,18 +1641,21 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter MessagesStorage.getInstance().putSentFile(originalPath, sentMessage.media.photo, 0); for (TLRPC.PhotoSize size : sentMessage.media.photo.sizes) { - if (size instanceof TLRPC.TL_photoSizeEmpty) { + if (size == null || size instanceof TLRPC.TL_photoSizeEmpty || size.type == null) { continue; } for (TLRPC.PhotoSize size2 : newMsg.media.photo.sizes) { - if (size2.location != null && size2.location.volume_id == Integer.MIN_VALUE && size.type.equals(size2.type) || size.w == size2.w && size.h == size2.h) { + if (size2 == null || size2.location == null || size2.type == null) { + continue; + } + if (size2.location.volume_id == Integer.MIN_VALUE && size.type.equals(size2.type) || size.w == size2.w && size.h == size2.h) { String fileName = size2.location.volume_id + "_" + size2.location.local_id; String fileName2 = size.location.volume_id + "_" + size.location.local_id; if (fileName.equals(fileName2)) { break; } File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); - File cacheFile2 = null; + File cacheFile2; if (sentMessage.media.photo.sizes.size() == 1 || size.w > 90 || size.h > 90) { cacheFile2 = FileLoader.getPathToAttach(size); } else { @@ -1842,13 +1854,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter return false; } - boolean isEncrypted = (int)dialog_id == 0; + boolean isEncrypted = (int) dialog_id == 0; boolean allowSticker = !isEncrypted; String name = f.getName(); - if (name == null) { - name = "noname"; - } String ext = ""; int idx = path.lastIndexOf("."); if (idx != -1) { @@ -1872,7 +1881,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.TL_documentAttributeFilename fileName = new TLRPC.TL_documentAttributeFilename(); fileName.file_name = name; document.attributes.add(fileName); - document.size = (int)f.length(); + document.size = (int) f.length(); document.dc_id = 0; if (ext.length() != 0) { if (ext.toLowerCase().equals("webp")) { @@ -1911,12 +1920,13 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter FileLog.e("tmessages", e); } if (bmOptions.outWidth != 0 && bmOptions.outHeight != 0 && bmOptions.outWidth <= 800 && bmOptions.outHeight <= 800) { - TLRPC.TL_documentAttributeSticker attributeSticker = null; + TLRPC.TL_documentAttributeSticker attributeSticker; if (isEncrypted) { attributeSticker = new TLRPC.TL_documentAttributeSticker_old(); } else { attributeSticker = new TLRPC.TL_documentAttributeSticker(); attributeSticker.alt = ""; + attributeSticker.stickerset = new TLRPC.TL_inputStickerSetEmpty(); } document.attributes.add(attributeSticker); TLRPC.TL_documentAttributeImageSize attributeImageSize = new TLRPC.TL_documentAttributeImageSize(); @@ -2023,7 +2033,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter new Thread(new Runnable() { @Override public void run() { - boolean isEncrypted = (int)dialog_id == 0; + boolean isEncrypted = (int) dialog_id == 0; for (int a = 0; a < photos.size(); a++) { final MediaController.SearchImage searchImage = photos.get(a); if (searchImage.type == 1) { @@ -2034,7 +2044,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter String md5 = Utilities.MD5(searchImage.imageUrl) + "." + ImageLoader.getHttpUrlExtension(searchImage.imageUrl); File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), md5); if (document == null) { - File thumbFile = null; + File thumbFile; document = new TLRPC.TL_document(); document.id = 0; document.date = ConnectionsManager.getInstance().getCurrentTime(); @@ -2091,15 +2101,19 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (photo == null) { String md5 = Utilities.MD5(searchImage.imageUrl) + "." + ImageLoader.getHttpUrlExtension(searchImage.imageUrl); File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), md5); - if (cacheFile.exists()) { + if (cacheFile.exists() && cacheFile.length() != 0) { photo = SendMessagesHelper.getInstance().generatePhotoSizes(cacheFile.toString(), null); - needDownloadHttp = false; - } else { + if (photo != null) { + needDownloadHttp = false; + } + } + if (photo == null) { md5 = Utilities.MD5(searchImage.thumbUrl) + "." + ImageLoader.getHttpUrlExtension(searchImage.thumbUrl); cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), md5); if (cacheFile.exists()) { photo = SendMessagesHelper.getInstance().generatePhotoSizes(cacheFile.toString(), null); - } else { + } + if (photo == null) { photo = new TLRPC.TL_photo(); photo.user_id = UserConfig.getClientUserId(); photo.date = ConnectionsManager.getInstance().getCurrentTime(); @@ -2174,7 +2188,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter new Thread(new Runnable() { @Override public void run() { - boolean isEncrypted = (int)dialog_id == 0; + boolean isEncrypted = (int) dialog_id == 0; ArrayList sendAsDocuments = null; ArrayList sendAsDocumentsOriginal = null; @@ -2192,7 +2206,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter String originalPath = path; String tempPath = path; if (tempPath == null && uri != null) { - tempPath = Utilities.getPath(uri); + tempPath = AndroidUtilities.getPath(uri); originalPath = uri.toString(); } @@ -2236,7 +2250,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (!isEncrypted) { photo = (TLRPC.TL_photo) MessagesStorage.getInstance().getSentFile(originalPath, !isEncrypted ? 0 : 3); if (photo == null && uri != null) { - photo = (TLRPC.TL_photo) MessagesStorage.getInstance().getSentFile(Utilities.getPath(uri), !isEncrypted ? 0 : 3); + photo = (TLRPC.TL_photo) MessagesStorage.getInstance().getSentFile(AndroidUtilities.getPath(uri), !isEncrypted ? 0 : 3); } } if (photo == null) { @@ -2266,7 +2280,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter }).start(); } - public static void prepareSendingVideo(final String videoPath, final long estimatedSize, final long duration, final int width, final int height, final TLRPC.VideoEditedInfo videoEditedInfo, final long dialog_id, final MessageObject reply_to_msg) { + public static void prepareSendingVideo(final String videoPath, final long estimatedSize, final long duration, final int width, final int height, final VideoEditedInfo videoEditedInfo, final long dialog_id, final MessageObject reply_to_msg) { if (videoPath == null || videoPath.length() == 0) { return; } @@ -2274,7 +2288,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter @Override public void run() { - boolean isEncrypted = (int)dialog_id == 0; + boolean isEncrypted = (int) dialog_id == 0; if (videoEditedInfo != null || videoPath.endsWith("mp4")) { String path = videoPath; @@ -2316,14 +2330,13 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter video.h = height; } video.size = (int) estimatedSize; - video.videoEditedInfo = videoEditedInfo; String fileName = Integer.MIN_VALUE + "_" + UserConfig.lastLocalId + ".mp4"; UserConfig.lastLocalId--; File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); UserConfig.saveConfig(false); path = cacheFile.getAbsolutePath(); } else { - if (temp != null && temp.exists()) { + if (temp.exists()) { video.size = (int) temp.length(); } boolean infoObtained = false; @@ -2351,7 +2364,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter try { if (mediaMetadataRetriever != null) { mediaMetadataRetriever.release(); - mediaMetadataRetriever = null; } } catch (Exception e) { FileLog.e("tmessages", e); @@ -2379,7 +2391,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - SendMessagesHelper.getInstance().sendMessage(videoFinal, originalPathFinal, finalPath, dialog_id, reply_to_msg); + SendMessagesHelper.getInstance().sendMessage(videoFinal, videoEditedInfo, originalPathFinal, finalPath, dialog_id, reply_to_msg); } }); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/android/SmsListener.java b/TMessagesProj/src/main/java/org/telegram/android/SmsListener.java index 78e179605..0c1df4802 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/SmsListener.java +++ b/TMessagesProj/src/main/java/org/telegram/android/SmsListener.java @@ -44,11 +44,16 @@ public class SmsListener extends BroadcastReceiver { try { Pattern pattern = Pattern.compile("[0-9]+"); - Matcher matcher = pattern.matcher(wholeString); + final Matcher matcher = pattern.matcher(wholeString); if (matcher.find()) { String str = matcher.group(0); if (str.length() >= 3) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceiveSmsCode, matcher.group(0)); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceiveSmsCode, matcher.group(0)); + } + }); } } } catch (Throwable e) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/VideoEditedInfo.java b/TMessagesProj/src/main/java/org/telegram/android/VideoEditedInfo.java new file mode 100644 index 000000000..ef14750e3 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/VideoEditedInfo.java @@ -0,0 +1,51 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2014. + */ + +package org.telegram.android; + +import java.util.Locale; + +public class VideoEditedInfo { + public long startTime; + public long endTime; + public int rotationValue; + public int originalWidth; + public int originalHeight; + public int resultWidth; + public int resultHeight; + public int bitrate; + public String originalPath; + + public String getString() { + return String.format(Locale.US, "-1_%d_%d_%d_%d_%d_%d_%d_%d_%s", startTime, endTime, rotationValue, originalWidth, originalHeight, bitrate, resultWidth, resultHeight, originalPath); + } + + public void parseString(String string) { + if (string.length() < 6) { + return; + } + String args[] = string.split("_"); + if (args.length >= 10) { + startTime = Long.parseLong(args[1]); + endTime = Long.parseLong(args[2]); + rotationValue = Integer.parseInt(args[3]); + originalWidth = Integer.parseInt(args[4]); + originalHeight = Integer.parseInt(args[5]); + bitrate = Integer.parseInt(args[6]); + resultWidth = Integer.parseInt(args[7]); + resultHeight = Integer.parseInt(args[8]); + for (int a = 9; a < args.length; a++) { + if (originalPath == null) { + originalPath = args[a]; + } else { + originalPath += "_" + args[a]; + } + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/query/StickersQuery.java b/TMessagesProj/src/main/java/org/telegram/android/query/StickersQuery.java index 6c8c45288..9b247d8e8 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/query/StickersQuery.java +++ b/TMessagesProj/src/main/java/org/telegram/android/query/StickersQuery.java @@ -8,20 +8,33 @@ package org.telegram.android.query; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Message; +import android.widget.Toast; + import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLitePreparedStatement; import org.telegram.android.AndroidUtilities; +import org.telegram.android.LocaleController; import org.telegram.android.MessagesStorage; import org.telegram.android.NotificationCenter; import org.telegram.messenger.ByteBufferDesc; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; import org.telegram.messenger.RPCRequest; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Components.StickersAlert; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; public class StickersQuery { @@ -30,19 +43,54 @@ public class StickersQuery { private static int loadDate; private static ArrayList stickers = new ArrayList<>(); private static HashMap> allStickers = new HashMap<>(); + private static ArrayList stickerPacks = new ArrayList<>(); + private static ArrayList stickerSets = new ArrayList<>(); + private static HashMap> stickersBySets = new HashMap<>(); + private static HashMap stickersByEmoji = new HashMap<>(); private static boolean loadingStickers; + private static boolean stickersLoaded; + private static boolean hideMainStickersPack; public static void checkStickers() { - if (!loadingStickers && (allStickers.isEmpty() || loadDate < (System.currentTimeMillis() / 1000 - 60 * 60))) { - loadStickers(true); + if (!loadingStickers && (!stickersLoaded || loadDate < (System.currentTimeMillis() / 1000 - 60 * 60))) { + loadStickers(true, false); } } + public static boolean isLoadingStickers() { + return loadingStickers; + } + + public static HashMap> getAllStickers() { + return allStickers; + } + + public static ArrayList getStickersForSet(long id) { + return stickersBySets.get(id); + } + + public static ArrayList getStickerPacks() { + return stickerPacks; + } + public static ArrayList getStickers() { return stickers; } - private static void loadStickers(boolean cache) { + public static ArrayList getStickerSets() { + return stickerSets; + } + + public static boolean isStickerPackInstalled(long id) { + return stickersBySets.containsKey(id); + } + + public static String getEmojiForSticker(long id) { + String value = stickersByEmoji.get(id); + return value != null ? value : ""; + } + + public static void loadStickers(boolean cache, boolean force) { if (loadingStickers) { return; } @@ -54,7 +102,14 @@ public class StickersQuery { TLRPC.messages_AllStickers result = null; int date = 0; try { - SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT data, date FROM stickers WHERE 1"); + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT value FROM keyvalue WHERE id = 'hide_stickers'"); + if (cursor.next()) { + int value = Utilities.parseInt(cursor.stringValue(0)); + hideMainStickersPack = value == 1; + } + cursor.dispose(); + + cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT data, date FROM stickers WHERE 1"); ArrayList loadedUsers = new ArrayList<>(); if (cursor.next()) { ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); @@ -73,10 +128,7 @@ public class StickersQuery { }); } else { TLRPC.TL_messages_getAllStickers req = new TLRPC.TL_messages_getAllStickers(); - req.hash = hash; - if (req.hash == null) { - req.hash = ""; - } + req.hash = hash == null || force ? "" : hash; ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { @Override public void run(final TLObject response, final TLRPC.TL_error error) { @@ -113,11 +165,24 @@ public class StickersQuery { }); } + private static long getStickerSetId(TLRPC.Document document) { + for (TLRPC.DocumentAttribute attribute : document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeSticker) { + if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetID) { + return attribute.stickerset.id; + } + break; + } + } + return -1; + } + private static void processLoadedStickers(final TLRPC.messages_AllStickers res, final boolean cache, final int date) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { loadingStickers = false; + stickersLoaded = true; } }); Utilities.stageQueue.postRunnable(new Runnable() { @@ -127,7 +192,7 @@ public class StickersQuery { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - loadStickers(false); + loadStickers(false, false); } }); if (res == null) { @@ -135,18 +200,41 @@ public class StickersQuery { } } if (res instanceof TLRPC.TL_messages_allStickers) { - if (!cache) { - putStickersToCache((TLRPC.TL_messages_allStickers) res); - } HashMap documents = new HashMap<>(); + final HashMap> sets = new HashMap<>(); + final ArrayList allDocuments = new ArrayList<>(); + final HashMap stickersEmoji = new HashMap<>(); for (TLRPC.Document document : res.documents) { if (document == null) { continue; } + documents.put(document.id, document); - if (document.thumb != null && document.thumb.location != null) { - document.thumb.location.ext = "webp"; + long setId = getStickerSetId(document); + if (setId != -1 || setId == -1 && !hideMainStickersPack) { + allDocuments.add(document); } + ArrayList docs = sets.get(setId); + if (docs == null) { + docs = new ArrayList<>(); + sets.put(setId, docs); + if (setId == -1) { + boolean contain = false; + for (TLRPC.TL_stickerSet set : res.sets) { + if (set.id == setId) { + contain = true; + break; + } + } + if (!contain) { + TLRPC.TL_stickerSet set = new TLRPC.TL_stickerSet(); + set.title = set.short_name = ""; + set.id = -1; + res.sets.add(0, set); + } + } + } + docs.add(document); } final HashMap> result = new HashMap<>(); for (TLRPC.TL_stickerPack stickerPack : res.packs) { @@ -154,8 +242,16 @@ public class StickersQuery { stickerPack.emoticon = stickerPack.emoticon.replace("\uFE0F", ""); ArrayList arrayList = result.get(stickerPack.emoticon); for (Long id : stickerPack.documents) { + if (!stickersEmoji.containsKey(id)) { + stickersEmoji.put(id, stickerPack.emoticon); + } TLRPC.Document document = documents.get(id); if (document != null) { + long setId = getStickerSetId(document); + if (setId == -1 && hideMainStickersPack) { + continue; + } + if (arrayList == null) { arrayList = new ArrayList<>(); result.put(stickerPack.emoticon, arrayList); @@ -165,11 +261,30 @@ public class StickersQuery { } } } + Collections.sort(allDocuments, new Comparator() { + @Override + public int compare(TLRPC.Document lhs, TLRPC.Document rhs) { + long lid = getStickerSetId(lhs); + long rid = getStickerSetId(rhs); + if (lid < rid) { + return -1; + } else if (lid > rid) { + return 1; + } + return 0; + } + }); + if (!cache) { + putStickersToCache((TLRPC.TL_messages_allStickers) res); + } AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + stickerSets = res.sets; allStickers = result; - stickers = res.documents; + stickers = allDocuments; + stickersBySets = sets; + stickersByEmoji = stickersEmoji; hash = res.hash; loadDate = date; NotificationCenter.getInstance().postNotificationName(NotificationCenter.stickersDidLoaded); @@ -179,4 +294,144 @@ public class StickersQuery { } }); } + + public static void loadStickers(final BaseFragment fragment, final TLRPC.InputStickerSet stickerSet) { + if (fragment == null || stickerSet == null) { + return; + } + + final ProgressDialog progressDialog = new ProgressDialog(fragment.getParentActivity()); + progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.setCancelable(false); + + TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); + req.stickerset = stickerSet; + + final long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + if (fragment != null && fragment.getParentActivity() != null && !fragment.getParentActivity().isFinishing()) { + if (error == null) { + final TLRPC.TL_messages_stickerSet res = (TLRPC.TL_messages_stickerSet) response; + + StickersAlert alert = new StickersAlert(fragment.getParentActivity(), res.set, res.documents); + if (res.set == null || !StickersQuery.isStickerPackInstalled(res.set.id)) { + alert.setButton(AlertDialog.BUTTON_POSITIVE, LocaleController.getString("AddStickers", R.string.AddStickers), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + TLRPC.TL_messages_installStickerSet req = new TLRPC.TL_messages_installStickerSet(); + req.stickerset = stickerSet; + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (fragment != null && fragment.getParentActivity() != null) { + if (error == null) { + Toast.makeText(fragment.getParentActivity(), LocaleController.getString("AddStickersInstalled", R.string.AddStickersInstalled), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(fragment.getParentActivity(), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred), Toast.LENGTH_SHORT).show(); + } + } + loadStickers(false, true); + } + }); + } + }); + } + }); + } else { + alert.setButton(AlertDialog.BUTTON_NEUTRAL, LocaleController.getString("StickersRemove", R.string.StickersRemove), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + removeStickersSet(fragment.getParentActivity(), res.set); + } + }); + } + alert.setButton(AlertDialog.BUTTON_NEGATIVE, LocaleController.getString("Close", R.string.Close), (Message) null); + fragment.setVisibleDialog(alert); + alert.show(); + } else { + Toast.makeText(fragment.getParentActivity(), LocaleController.getString("AddStickersNotFound", R.string.AddStickersNotFound), Toast.LENGTH_SHORT).show(); + } + } + } + }); + } + }); + + progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ConnectionsManager.getInstance().cancelRpc(reqId, true); + try { + dialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + fragment.setVisibleDialog(progressDialog); + progressDialog.show(); + } + + public static void setHideMainStickersPack(final boolean value) { + hideMainStickersPack = value; + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO keyvalue VALUES(?, ?)"); + state.requery(); + state.bindString(1, "hide_stickers"); + state.bindString(2, value ? "1" : "0"); + state.step(); + state.dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + public static void removeStickersSet(final Context context, TLRPC.TL_stickerSet stickerSet) { + TLRPC.TL_messages_uninstallStickerSet req = new TLRPC.TL_messages_uninstallStickerSet(); + req.stickerset = new TLRPC.TL_inputStickerSetID(); + req.stickerset.access_hash = stickerSet.access_hash; + req.stickerset.id = stickerSet.id; + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + if (error == null) { + Toast.makeText(context, LocaleController.getString("StickersRemoved", R.string.StickersRemoved), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(context, LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred), Toast.LENGTH_SHORT).show(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + loadStickers(false, true); + } + }); + } + }); + } + + public static boolean getHideMainStickersPack() { + return hideMainStickersPack; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java index ebb4e89ba..c5a0fe725 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java @@ -58,6 +58,8 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.Interpolator; +import org.telegram.android.AndroidUtilities; + import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AbsSerializedData.java b/TMessagesProj/src/main/java/org/telegram/messenger/AbsSerializedData.java index 1e24cd4e1..ae3863940 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AbsSerializedData.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AbsSerializedData.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.x. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Action.java b/TMessagesProj/src/main/java/org/telegram/messenger/Action.java index 61ed9b70d..dc0c669a4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Action.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Action.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 70a9b6f1d..c7b0937a6 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -157,6 +157,7 @@ public class ApplicationLoader extends Application { } UserConfig.loadConfig(); + MessagesController.getInstance(); if (UserConfig.getCurrentUser() != null) { MessagesController.getInstance().putUser(UserConfig.getCurrentUser(), true); ConnectionsManager.getInstance().applyCountryPortNumber(UserConfig.getCurrentUser().phone); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuffersStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuffersStorage.java index db28c5c73..d6e733709 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuffersStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuffersStorage.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.x. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -37,12 +37,12 @@ public class BuffersStorage { public BuffersStorage(boolean threadSafe) { isThreadSafe = threadSafe; - freeBuffers128 = new ArrayList(); - freeBuffers1024 = new ArrayList(); - freeBuffers4096 = new ArrayList(); - freeBuffers16384 = new ArrayList(); - freeBuffers32768 = new ArrayList(); - freeBuffersBig = new ArrayList(); + freeBuffers128 = new ArrayList<>(); + freeBuffers1024 = new ArrayList<>(); + freeBuffers4096 = new ArrayList<>(); + freeBuffers16384 = new ArrayList<>(); + freeBuffers32768 = new ArrayList<>(); + freeBuffersBig = new ArrayList<>(); for (int a = 0; a < 5; a++) { freeBuffers128.add(new ByteBufferDesc(128)); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 9507d40e1..93df93753 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -10,7 +10,7 @@ package org.telegram.messenger; public class BuildVars { public static boolean DEBUG_VERSION = false; - public static int BUILD_VERSION = 521; + public static int BUILD_VERSION = 541; public static int APP_ID = 0; //obtain your own APP_ID at https://core.telegram.org/api/obtaining_api_id public static String APP_HASH = ""; //obtain your own APP_HASH at https://core.telegram.org/api/obtaining_api_id public static String HOCKEY_APP_HASH = "your-hockeyapp-api-key-here"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ByteArrayOutputStreamExpand.java b/TMessagesProj/src/main/java/org/telegram/messenger/ByteArrayOutputStreamExpand.java index b82131fef..a4dac2968 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ByteArrayOutputStreamExpand.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ByteArrayOutputStreamExpand.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ByteBufferDesc.java b/TMessagesProj/src/main/java/org/telegram/messenger/ByteBufferDesc.java index ca366b0b1..4a63cac25 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ByteBufferDesc.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ByteBufferDesc.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.x. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionContext.java b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionContext.java index b32127dbc..06e654576 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionContext.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionContext.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java index b0a32b642..e18873d8b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java @@ -1,13 +1,14 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; +import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageInfo; @@ -24,7 +25,13 @@ import org.telegram.android.MessagesController; import org.telegram.android.NotificationCenter; import java.io.File; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashMap; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; @@ -444,67 +451,117 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. if (isTestBackend == 0) { Datacenter datacenter = new Datacenter(); datacenter.datacenterId = 1; - datacenter.addAddressAndPort("149.154.175.50", 443); + datacenter.addAddressAndPort("149.154.175.50", 443, 0); + datacenter.addAddressAndPort("2001:b28:f23d:f001:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 2; - datacenter.addAddressAndPort("149.154.167.51", 443); + datacenter.addAddressAndPort("149.154.167.51", 443, 0); + datacenter.addAddressAndPort("2001:67c:4e8:f002:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 3; - datacenter.addAddressAndPort("149.154.175.100", 443); + datacenter.addAddressAndPort("149.154.175.100", 443, 0); + datacenter.addAddressAndPort("2001:b28:f23d:f003:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 4; - datacenter.addAddressAndPort("149.154.167.91", 443); + datacenter.addAddressAndPort("149.154.167.91", 443, 0); + datacenter.addAddressAndPort("2001:67c:4e8:f004:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 5; - datacenter.addAddressAndPort("149.154.171.5", 443); + datacenter.addAddressAndPort("149.154.171.5", 443, 0); + datacenter.addAddressAndPort("2001:b28:f23f:f005:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); } else { Datacenter datacenter = new Datacenter(); datacenter.datacenterId = 1; - datacenter.addAddressAndPort("149.154.175.10", 443); + datacenter.addAddressAndPort("149.154.175.10", 443, 0); + datacenter.addAddressAndPort("2001:b28:f23d:f001:0000:0000:0000:000e", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 2; - datacenter.addAddressAndPort("149.154.167.40", 443); + datacenter.addAddressAndPort("149.154.167.40", 443, 0); + datacenter.addAddressAndPort("2001:67c:4e8:f002:0000:0000:0000:000e", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 3; - datacenter.addAddressAndPort("149.154.175.117", 443); + datacenter.addAddressAndPort("149.154.175.117", 443, 0); + datacenter.addAddressAndPort("2001:b28:f23d:f003:0000:0000:0000:000e", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); } } else if (datacenters.size() == 1) { Datacenter datacenter = new Datacenter(); datacenter.datacenterId = 2; - datacenter.addAddressAndPort("149.154.167.51", 443); + datacenter.addAddressAndPort("149.154.167.51", 443, 0); + datacenter.addAddressAndPort("2001:67c:4e8:f002:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 3; - datacenter.addAddressAndPort("149.154.175.100", 443); + datacenter.addAddressAndPort("149.154.175.100", 443, 0); + datacenter.addAddressAndPort("2001:b28:f23d:f003:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 4; - datacenter.addAddressAndPort("149.154.167.91", 443); + datacenter.addAddressAndPort("149.154.167.91", 443, 0); + datacenter.addAddressAndPort("2001:67c:4e8:f004:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 5; - datacenter.addAddressAndPort("149.154.171.5", 443); + datacenter.addAddressAndPort("149.154.171.5", 443, 0); + datacenter.addAddressAndPort("2001:b28:f23f:f005:0000:0000:0000:000a", 443, 1); datacenters.put(datacenter.datacenterId, datacenter); } } + @SuppressLint("NewApi") + protected static boolean useIpv6Address() { + if (Build.VERSION.SDK_INT < 19) { + return false; + } + try { + NetworkInterface networkInterface; + + Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); + while (networkInterfaces.hasMoreElements()) { + networkInterface = networkInterfaces.nextElement(); + if (!networkInterface.isUp() || networkInterface.isLoopback()) { + continue; + } + boolean hasIpv4 = false; + boolean hasIpv6 = false; + for (InterfaceAddress address : networkInterface.getInterfaceAddresses()) { + InetAddress inetAddress = address.getAddress(); + if (inetAddress.isLinkLocalAddress() || inetAddress.isLoopbackAddress() || inetAddress.isMulticastAddress()) { + continue; + } + if (inetAddress instanceof Inet6Address) { + hasIpv6 = true; + } else if (inetAddress instanceof Inet4Address) { + hasIpv4 = true; + } + } + if (!hasIpv4 && hasIpv6) { + return true; + } + } + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + + return false; + } + private void saveSession() { Utilities.stageQueue.postRunnable(new Runnable() { @Override @@ -698,7 +755,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. HashMap ports = new HashMap<>(); addresses.add(ip_address); ports.put(ip_address, port); - exist.replaceAddressesAndPorts(addresses, ports); + exist.replaceAddressesAndPorts(addresses, ports, 0); exist.suspendConnections(); updateDcSettings(dc); } @@ -783,7 +840,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. datacentersArr.add(existing); datacenterMap.put(existing.datacenterId, existing); } - existing.addAddressAndPort(datacenterDesc.ip_address, datacenterDesc.port); + existing.addAddressAndPort(datacenterDesc.ip_address, datacenterDesc.port, datacenterDesc.flags); } if (!datacentersArr.isEmpty()) { @@ -792,7 +849,10 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. if (exist == null) { datacenters.put(datacenter.datacenterId, datacenter); } else { - exist.replaceAddressesAndPorts(datacenter.addresses, datacenter.ports); + exist.replaceAddressesAndPorts(datacenter.addressesIpv4, datacenter.ports, 0); + exist.replaceAddressesAndPorts(datacenter.addressesIpv6, datacenter.ports, 1); + exist.replaceAddressesAndPorts(datacenter.addressesIpv4Download, datacenter.ports, 2); + exist.replaceAddressesAndPorts(datacenter.addressesIpv6Download, datacenter.ports, 3); } if (datacenter.datacenterId == movingToDatacenterId) { movingToDatacenterId = DEFAULT_DATACENTER_ID; @@ -821,18 +881,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. invoke.api_id = BuildVars.APP_ID; try { invoke.lang_code = LocaleController.getLocaleString(LocaleController.getInstance().getSystemDefaultLocale()); - if (invoke.lang_code == null || invoke.lang_code.length() == 0) { + if (invoke.lang_code.length() == 0) { invoke.lang_code = "en"; } invoke.device_model = Build.MANUFACTURER + Build.MODEL; - if (invoke.device_model == null) { - invoke.device_model = "Android unknown"; - } PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); invoke.app_version = pInfo.versionName + " (" + pInfo.versionCode + ")"; - if (invoke.app_version == null) { - invoke.app_version = "App version unknown"; - } invoke.system_version = "SDK " + Build.VERSION.SDK_INT; } catch (Exception e) { FileLog.e("tmessages", e); @@ -1729,7 +1783,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. data.cleanup(); } - MessageKeyData keyData = Utilities.generateMessageKeyData(datacenter.authKey, messageKey, false); + MessageKeyData keyData = MessageKeyData.generateMessageKeyData(datacenter.authKey, messageKey, false); int zeroCount = 0; if (innerOs.limit() % 16 != 0) { @@ -1841,20 +1895,13 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. req.app_sandbox = false; try { req.lang_code = LocaleController.getLocaleString(LocaleController.getInstance().getSystemDefaultLocale()); - if (req.lang_code == null || req.lang_code.length() == 0) { + if (req.lang_code.length() == 0) { req.lang_code = "en"; } req.device_model = Build.MANUFACTURER + Build.MODEL; - if (req.device_model == null) { - req.device_model = "Android unknown"; - } req.system_version = "SDK " + Build.VERSION.SDK_INT; PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); req.app_version = pInfo.versionName + " (" + pInfo.versionCode + ")"; - if (req.app_version == null) { - req.app_version = "App version unknown"; - } - } catch (Exception e) { FileLog.e("tmessages", e); req.lang_code = "en"; @@ -2191,7 +2238,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.appDidLogout); + MessagesController.getInstance().performLogout(false); } }); } @@ -2428,13 +2475,13 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. } void generatePing(Datacenter datacenter, boolean push) { - TcpConnection connection = null; + TcpConnection connection; if (push) { connection = datacenter.pushConnection; } else { connection = datacenter.connection; } - if (connection != null && (push || !push && connection.channelToken != 0)) { + if (connection != null && (push || connection.channelToken != 0)) { ByteBufferDesc transportData = generatePingData(connection); if (transportData != null) { if (push) { @@ -2607,7 +2654,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. } byte[] messageKey = data.readData(16, false); - MessageKeyData keyData = Utilities.generateMessageKeyData(datacenter.authKey, messageKey, true); + MessageKeyData keyData = MessageKeyData.generateMessageKeyData(datacenter.authKey, messageKey, true); Utilities.aesIgeEncryption(data.buffer, keyData.aesKey, keyData.aesIv, false, false, data.position(), length - 24); @@ -2671,10 +2718,15 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. } protected TLObject deserialize(TLObject request, AbsSerializedData data, boolean exception) { - int constructor = data.readInt32(exception); + int constructor = 0; + try { + constructor = data.readInt32(exception); + } catch (Exception e) { + FileLog.e("tmessages", e); + } TLObject message = null; try { - message = TLClassStore.Instance().TLdeserialize(data, constructor, request, exception); + message = TLClassStore.Instance().TLdeserialize(data, constructor, exception); } catch (Exception e) { FileLog.e("tmessages", e); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Datacenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/Datacenter.java index 04ffccfab..cb28e751a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Datacenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Datacenter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -17,10 +17,13 @@ import java.util.Comparator; import java.util.HashMap; public class Datacenter { - private static final int DATA_VERSION = 4; + private static final int DATA_VERSION = 5; public int datacenterId; - public ArrayList addresses = new ArrayList<>(); + public ArrayList addressesIpv4 = new ArrayList<>(); + public ArrayList addressesIpv6 = new ArrayList<>(); + public ArrayList addressesIpv4Download = new ArrayList<>(); + public ArrayList addressesIpv6Download = new ArrayList<>(); public HashMap ports = new HashMap<>(); public int[] defaultPorts = new int[] {-1, 80, -1, 443, -1, 443, -1, 80, -1, 443, -1}; public int[] defaultPorts8888 = new int[] {-1, 8888, -1, 443, -1, 8888, -1, 80, -1, 8888, -1}; @@ -29,8 +32,15 @@ public class Datacenter { public long authKeyId; public int lastInitVersion = 0; public int overridePort = -1; - private volatile int currentPortNum = 0; - private volatile int currentAddressNum = 0; + + private volatile int currentPortNumIpv4 = 0; + private volatile int currentAddressNumIpv4 = 0; + private volatile int currentPortNumIpv6 = 0; + private volatile int currentAddressNumIpv6 = 0; + private volatile int currentPortNumIpv4Download = 0; + private volatile int currentAddressNumIpv4Download = 0; + private volatile int currentPortNumIpv6Download = 0; + private volatile int currentAddressNumIpv6Download = 0; public TcpConnection connection; private TcpConnection downloadConnection; @@ -47,7 +57,7 @@ public class Datacenter { if (version == 0) { datacenterId = data.readInt32(false); String address = data.readString(false); - addresses.add(address); + addressesIpv4.add(address); int port = data.readInt32(false); ports.put(address, port); int len = data.readInt32(false); @@ -72,7 +82,7 @@ public class Datacenter { } } else if (version == 1) { int currentVersion = data.readInt32(false); - if (currentVersion == 2 || currentVersion == 3 || currentVersion == 4) { + if (currentVersion >= 2 && currentVersion <= 5) { datacenterId = data.readInt32(false); if (currentVersion >= 3) { lastInitVersion = data.readInt32(false); @@ -80,15 +90,35 @@ public class Datacenter { int len = data.readInt32(false); for (int a = 0; a < len; a++) { String address = data.readString(false); - addresses.add(address); + addressesIpv4.add(address); ports.put(address, data.readInt32(false)); } + if (currentVersion >= 5) { + len = data.readInt32(false); + for (int a = 0; a < len; a++) { + String address = data.readString(false); + addressesIpv6.add(address); + ports.put(address, data.readInt32(false)); + } + len = data.readInt32(false); + for (int a = 0; a < len; a++) { + String address = data.readString(false); + addressesIpv4Download.add(address); + ports.put(address, data.readInt32(false)); + } + len = data.readInt32(false); + for (int a = 0; a < len; a++) { + String address = data.readString(false); + addressesIpv6Download.add(address); + ports.put(address, data.readInt32(false)); + } + } len = data.readInt32(false); if (len != 0) { authKey = data.readData(len, false); } - if (currentVersion == 4) { + if (currentVersion >= 4) { authKeyId = data.readInt64(false); } else { len = data.readInt32(false); @@ -116,26 +146,79 @@ public class Datacenter { } public void switchTo443Port() { - for (int a = 0; a < addresses.size(); a++) { - if (ports.get(addresses.get(a)) == 443) { - currentAddressNum = a; - currentPortNum = 0; + for (int a = 0; a < addressesIpv4.size(); a++) { + if (ports.get(addressesIpv4.get(a)) == 443) { + currentAddressNumIpv4 = a; + currentPortNumIpv4 = 0; + break; + } + } + for (int a = 0; a < addressesIpv6.size(); a++) { + if (ports.get(addressesIpv6.get(a)) == 443) { + currentAddressNumIpv6 = a; + currentPortNumIpv6 = 0; + break; + } + } + for (int a = 0; a < addressesIpv4Download.size(); a++) { + if (ports.get(addressesIpv4Download.get(a)) == 443) { + currentAddressNumIpv4Download = a; + currentPortNumIpv4Download = 0; + break; + } + } + for (int a = 0; a < addressesIpv6Download.size(); a++) { + if (ports.get(addressesIpv6Download.get(a)) == 443) { + currentAddressNumIpv6Download = a; + currentPortNumIpv6Download = 0; break; } } } - public String getCurrentAddress() { + public String getCurrentAddress(int flags) { + int currentAddressNum; + ArrayList addresses; + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + currentAddressNum = currentAddressNumIpv6Download; + addresses = addressesIpv6Download; + } else { + currentAddressNum = currentAddressNumIpv4Download; + addresses = addressesIpv4Download; + } + } else { + if ((flags & 1) != 0) { + currentAddressNum = currentAddressNumIpv6; + addresses = addressesIpv6; + } else { + currentAddressNum = currentAddressNumIpv4; + addresses = addressesIpv4; + } + } if (addresses.isEmpty()) { return null; } if (currentAddressNum >= addresses.size()) { currentAddressNum = 0; + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + currentAddressNumIpv6Download = currentAddressNum; + } else { + currentAddressNumIpv4Download = currentAddressNum; + } + } else { + if ((flags & 1) != 0) { + currentAddressNumIpv6 = currentAddressNum; + } else { + currentAddressNumIpv4 = currentAddressNum; + } + } } return addresses.get(currentAddressNum); } - public int getCurrentPort() { + public int getCurrentPort(int flags) { if (ports.isEmpty()) { return overridePort == -1 ? 443 : overridePort; } @@ -146,21 +229,64 @@ public class Datacenter { portsArray = defaultPorts8888; } + int currentPortNum; + ArrayList addresses; + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + currentPortNum = currentPortNumIpv6Download; + } else { + currentPortNum = currentPortNumIpv4Download; + } + } else { + if ((flags & 1) != 0) { + currentPortNum = currentPortNumIpv6; + } else { + currentPortNum = currentPortNumIpv4; + } + } + if (currentPortNum >= defaultPorts.length) { currentPortNum = 0; + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + currentPortNumIpv6Download = currentPortNum; + } else { + currentPortNumIpv4Download = currentPortNum; + } + } else { + if ((flags & 1) != 0) { + currentPortNumIpv6 = currentPortNum; + } else { + currentPortNumIpv4 = currentPortNum; + } + } } int port = portsArray[currentPortNum]; if (port == -1) { if (overridePort != -1) { return overridePort; } - String address = getCurrentAddress(); + String address = getCurrentAddress(flags); return ports.get(address); } return port; } - public void addAddressAndPort(String address, int port) { + public void addAddressAndPort(String address, int port, int flags) { + ArrayList addresses; + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + addresses = addressesIpv6Download; + } else { + addresses = addressesIpv4Download; + } + } else { + if ((flags & 1) != 0) { + addresses = addressesIpv6; + } else { + addresses = addressesIpv4; + } + } if (addresses.contains(address)) { return; } @@ -168,7 +294,31 @@ public class Datacenter { ports.put(address, port); } - public void nextAddressOrPort() { + public void nextAddressOrPort(int flags) { + int currentPortNum; + int currentAddressNum; + ArrayList addresses; + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + currentPortNum = currentPortNumIpv6Download; + currentAddressNum = currentAddressNumIpv6Download; + addresses = addressesIpv6Download; + } else { + currentPortNum = currentPortNumIpv4Download; + currentAddressNum = currentAddressNumIpv4Download; + addresses = addressesIpv4Download; + } + } else { + if ((flags & 1) != 0) { + currentPortNum = currentPortNumIpv6; + currentAddressNum = currentAddressNumIpv6; + addresses = addressesIpv6; + } else { + currentPortNum = currentPortNumIpv4; + currentAddressNum = currentAddressNumIpv4; + addresses = addressesIpv4; + } + } if (currentPortNum + 1 < defaultPorts.length) { currentPortNum++; } else { @@ -179,6 +329,23 @@ public class Datacenter { } currentPortNum = 0; } + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + currentPortNumIpv6Download = currentPortNum; + currentAddressNumIpv6Download = currentAddressNum; + } else { + currentPortNumIpv4Download = currentPortNum; + currentAddressNumIpv4Download = currentAddressNum; + } + } else { + if ((flags & 1) != 0) { + currentPortNumIpv6 = currentPortNum; + currentAddressNumIpv6 = currentAddressNum; + } else { + currentPortNumIpv4 = currentPortNum; + currentAddressNumIpv4 = currentAddressNum; + } + } } public void storeCurrentAddressAndPortNum() { @@ -187,8 +354,14 @@ public class Datacenter { public void run() { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("dataconfig", Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("dc" + datacenterId + "port", currentPortNum); - editor.putInt("dc" + datacenterId + "address", currentAddressNum); + editor.putInt("dc" + datacenterId + "port", currentPortNumIpv4); + editor.putInt("dc" + datacenterId + "address", currentAddressNumIpv4); + editor.putInt("dc" + datacenterId + "port6", currentPortNumIpv6); + editor.putInt("dc" + datacenterId + "address6", currentAddressNumIpv6); + editor.putInt("dc" + datacenterId + "portD", currentPortNumIpv4Download); + editor.putInt("dc" + datacenterId + "addressD", currentAddressNumIpv4Download); + editor.putInt("dc" + datacenterId + "port6D", currentPortNumIpv6Download); + editor.putInt("dc" + datacenterId + "address6D", currentAddressNumIpv6Download); editor.commit(); } }); @@ -196,21 +369,71 @@ public class Datacenter { private void readCurrentAddressAndPortNum() { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("dataconfig", Context.MODE_PRIVATE); - currentPortNum = preferences.getInt("dc" + datacenterId + "port", 0); - currentAddressNum = preferences.getInt("dc" + datacenterId + "address", 0); + currentPortNumIpv4 = preferences.getInt("dc" + datacenterId + "port", 0); + currentAddressNumIpv4 = preferences.getInt("dc" + datacenterId + "address", 0); + currentPortNumIpv6 = preferences.getInt("dc" + datacenterId + "port6", 0); + currentAddressNumIpv6 = preferences.getInt("dc" + datacenterId + "address6", 0); + currentPortNumIpv4Download = preferences.getInt("dc" + datacenterId + "portD", 0); + currentAddressNumIpv4Download = preferences.getInt("dc" + datacenterId + "addressD", 0); + currentPortNumIpv6Download = preferences.getInt("dc" + datacenterId + "port6D", 0); + currentAddressNumIpv6Download = preferences.getInt("dc" + datacenterId + "address6D", 0); } - public void replaceAddressesAndPorts(ArrayList newAddresses, HashMap newPorts) { - addresses = newAddresses; - ports = newPorts; + public void replaceAddressesAndPorts(ArrayList newAddresses, HashMap newPorts, int flags) { + ArrayList addresses; + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + addresses = addressesIpv6Download; + } else { + addresses = addressesIpv4Download; + } + } else { + if ((flags & 1) != 0) { + addresses = addressesIpv6; + } else { + addresses = addressesIpv4; + } + } + for (String address : addresses) { + ports.remove(address); + } + if ((flags & 2) != 0) { + if ((flags & 1) != 0) { + addressesIpv6Download = newAddresses; + } else { + addressesIpv4Download = newAddresses; + } + } else { + if ((flags & 1) != 0) { + addressesIpv6 = newAddresses; + } else { + addressesIpv4 = newAddresses; + } + } + ports.putAll(newPorts); } public void SerializeToStream(SerializedData stream) { stream.writeInt32(DATA_VERSION); stream.writeInt32(datacenterId); stream.writeInt32(lastInitVersion); - stream.writeInt32(addresses.size()); - for (String address : addresses) { + stream.writeInt32(addressesIpv4.size()); + for (String address : addressesIpv4) { + stream.writeString(address); + stream.writeInt32(ports.get(address)); + } + stream.writeInt32(addressesIpv6.size()); + for (String address : addressesIpv6) { + stream.writeString(address); + stream.writeInt32(ports.get(address)); + } + stream.writeInt32(addressesIpv4Download.size()); + for (String address : addressesIpv4Download) { + stream.writeString(address); + stream.writeInt32(ports.get(address)); + } + stream.writeInt32(addressesIpv6Download.size()); + for (String address : addressesIpv6Download) { stream.writeString(address); stream.writeInt32(ports.get(address)); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java index 2c68fdf6e..529cbdbc5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ExportAuthorizationAction.java b/TMessagesProj/src/main/java/org/telegram/messenger/ExportAuthorizationAction.java index 51367696d..603032c29 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ExportAuthorizationAction.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ExportAuthorizationAction.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 62f217442..2a006d37b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -60,7 +60,7 @@ public class FileLoadOperation { void didChangedLoadProgress(FileLoadOperation operation, float progress); } - public FileLoadOperation(TLRPC.FileLocation photoLocation, int size) { + public FileLoadOperation(TLRPC.FileLocation photoLocation, String extension, int size) { if (photoLocation instanceof TLRPC.TL_fileEncryptedLocation) { location = new TLRPC.TL_inputEncryptedFileLocation(); location.id = photoLocation.volume_id; @@ -79,10 +79,7 @@ public class FileLoadOperation { datacenter_id = photoLocation.dc_id; } totalBytesCount = size; - ext = photoLocation.ext; - if (ext == null) { - ext = "jpg"; - } + ext = extension != null ? extension : "jpg"; } public FileLoadOperation(TLRPC.Video videoLocation) { @@ -140,7 +137,7 @@ public class FileLoadOperation { } totalBytesCount = documentLocation.size; ext = FileLoader.getDocumentFileName(documentLocation); - int idx = -1; + int idx; if (ext == null || (idx = ext.lastIndexOf(".")) == -1) { ext = ""; } else { @@ -179,8 +176,8 @@ public class FileLoadOperation { return; } Long mediaId = null; - String fileNameFinal = null; - String fileNameTemp = null; + String fileNameFinal; + String fileNameTemp; String fileNameIv = null; if (location.volume_id != 0 && location.local_id != 0) { fileNameTemp = location.volume_id + "_" + location.local_id + "_temp." + ext; @@ -219,7 +216,6 @@ public class FileLoadOperation { cacheFileFinal = new File(storePath, fileNameFinal); boolean exist = cacheFileFinal.exists(); if (exist && totalBytesCount != 0 && totalBytesCount != cacheFileFinal.length()) { - exist = false; cacheFileFinal.delete(); } @@ -388,7 +384,6 @@ public class FileLoadOperation { processRequestResult(delayedRequestInfo, null); delayedRequestInfo.response.disableFree = false; delayedRequestInfo.response.freeResources(); - delayedRequestInfo = null; break; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 8dbed3e4c..2860c3cc9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -21,10 +21,15 @@ public class FileLoader { public interface FileLoaderDelegate { void fileUploadProgressChanged(String location, float progress, boolean isEncrypted); - void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile); + + void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv); + void fileDidFailedUpload(String location, boolean isEncrypted); + void fileDidLoaded(String location, File finalFile, int type); + void fileDidFailedLoad(String location, int state); + void fileLoadProgressChanged(String location, float progress); } @@ -56,6 +61,7 @@ public class FileLoader { private int currentUploadSmallOperationsCount = 0; private static volatile FileLoader Instance = null; + public static FileLoader getInstance() { FileLoader localInstance = Instance; if (localInstance == null) { @@ -92,7 +98,7 @@ public class FileLoader { fileLoaderQueue.postRunnable(new Runnable() { @Override public void run() { - FileUploadOperation operation = null; + FileUploadOperation operation; if (!enc) { operation = uploadOperationPaths.get(location); } else { @@ -112,7 +118,7 @@ public class FileLoader { fileLoaderQueue.postRunnable(new Runnable() { @Override public void run() { - FileUploadOperation operation = null; + FileUploadOperation operation; if (encrypted) { operation = uploadOperationPathsEnc.get(location); } else { @@ -163,7 +169,7 @@ public class FileLoader { } operation.delegate = new FileUploadOperation.FileUploadOperationDelegate() { @Override - public void didFinishUploadingFile(FileUploadOperation operation, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile) { + public void didFinishUploadingFile(FileUploadOperation operation, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv) { fileLoaderQueue.postRunnable(new Runnable() { @Override public void run() { @@ -192,7 +198,7 @@ public class FileLoader { } } if (delegate != null) { - delegate.fileDidUploaded(location, inputFile, inputEncryptedFile); + delegate.fileDidUploaded(location, inputFile, inputEncryptedFile, key, iv); } } }); @@ -261,26 +267,26 @@ public class FileLoader { } public void cancelLoadFile(TLRPC.Video video) { - cancelLoadFile(video, null, null, null); + cancelLoadFile(video, null, null, null, null); } public void cancelLoadFile(TLRPC.Document document) { - cancelLoadFile(null, document, null, null); + cancelLoadFile(null, document, null, null, null); } public void cancelLoadFile(TLRPC.Audio audio) { - cancelLoadFile(null, null, audio, null); + cancelLoadFile(null, null, audio, null, null); } public void cancelLoadFile(TLRPC.PhotoSize photo) { - cancelLoadFile(null, null, null, photo.location); + cancelLoadFile(null, null, null, photo.location, null); } - public void cancelLoadFile(TLRPC.FileLocation location) { - cancelLoadFile(null, null, null, location); + public void cancelLoadFile(TLRPC.FileLocation location, String ext) { + cancelLoadFile(null, null, null, location, ext); } - private void cancelLoadFile(final TLRPC.Video video, final TLRPC.Document document, final TLRPC.Audio audio, final TLRPC.FileLocation location) { + private void cancelLoadFile(final TLRPC.Video video, final TLRPC.Document document, final TLRPC.Audio audio, final TLRPC.FileLocation location, final String locationExt) { if (video == null && location == null && document == null && audio == null) { return; } @@ -291,7 +297,7 @@ public class FileLoader { if (video != null) { fileName = getAttachFileName(video); } else if (location != null) { - fileName = getAttachFileName(location); + fileName = getAttachFileName(location, locationExt); } else if (document != null) { fileName = getAttachFileName(document); } else if (audio != null) { @@ -335,26 +341,26 @@ public class FileLoader { } public void loadFile(TLRPC.Video video, boolean force) { - loadFile(video, null, null, null, 0, force, video != null && video.key != null); + loadFile(video, null, null, null, null, 0, force, video != null && video.key != null); } - public void loadFile(TLRPC.PhotoSize photo, boolean cacheOnly) { - loadFile(null, null, null, photo.location, photo.size, false, cacheOnly || (photo != null && photo.size == 0 || photo.location.key != null)); + public void loadFile(TLRPC.PhotoSize photo, String ext, boolean cacheOnly) { + loadFile(null, null, null, photo.location, ext, photo.size, false, cacheOnly || (photo != null && photo.size == 0 || photo.location.key != null)); } public void loadFile(TLRPC.Document document, boolean force, boolean cacheOnly) { - loadFile(null, document, null, null, 0, force, cacheOnly || document != null && document.key != null); + loadFile(null, document, null, null, null, 0, force, cacheOnly || document != null && document.key != null); } public void loadFile(TLRPC.Audio audio, boolean force) { - loadFile(null, null, audio, null, 0, false, audio != null && audio.key != null); + loadFile(null, null, audio, null, null, 0, false, audio != null && audio.key != null); } - public void loadFile(TLRPC.FileLocation location, int size, boolean cacheOnly) { - loadFile(null, null, null, location, size, true, cacheOnly || size == 0 || (location != null && location.key != null)); + public void loadFile(TLRPC.FileLocation location, String ext, int size, boolean cacheOnly) { + loadFile(null, null, null, location, ext, size, true, cacheOnly || size == 0 || (location != null && location.key != null)); } - private void loadFile(final TLRPC.Video video, final TLRPC.Document document, final TLRPC.Audio audio, final TLRPC.FileLocation location, final int locationSize, final boolean force, final boolean cacheOnly) { + private void loadFile(final TLRPC.Video video, final TLRPC.Document document, final TLRPC.Audio audio, final TLRPC.FileLocation location, final String locationExt, final int locationSize, final boolean force, final boolean cacheOnly) { fileLoaderQueue.postRunnable(new Runnable() { @Override public void run() { @@ -362,7 +368,7 @@ public class FileLoader { if (video != null) { fileName = getAttachFileName(video); } else if (location != null) { - fileName = getAttachFileName(location); + fileName = getAttachFileName(location, locationExt); } else if (document != null) { fileName = getAttachFileName(document); } else if (audio != null) { @@ -372,11 +378,11 @@ public class FileLoader { return; } - FileLoadOperation operation = null; + FileLoadOperation operation; operation = loadOperationPaths.get(fileName); if (operation != null) { if (force) { - LinkedList downloadQueue = null; + LinkedList downloadQueue; if (audio != null) { downloadQueue = audioLoadOperationQueue; } else if (location != null) { @@ -404,7 +410,7 @@ public class FileLoader { operation = new FileLoadOperation(video); type = MEDIA_DIR_VIDEO; } else if (location != null) { - operation = new FileLoadOperation(location, locationSize); + operation = new FileLoadOperation(location, locationExt, locationSize); type = MEDIA_DIR_IMAGE; } else if (document != null) { operation = new FileLoadOperation(document); @@ -489,7 +495,7 @@ public class FileLoader { @Override public void run() { loadOperationPaths.remove(arg1); - FileLoadOperation operation = null; + FileLoadOperation operation; if (audio != null) { currentAudioLoadOperationsCount--; if (!audioLoadOperationQueue.isEmpty()) { @@ -583,51 +589,59 @@ public class FileLoader { } public static File getPathToAttach(TLObject attach) { - return getPathToAttach(attach, false); + return getPathToAttach(attach, null, false); } public static File getPathToAttach(TLObject attach, boolean forceCache) { + return getPathToAttach(attach, null, forceCache); + } + + public static File getPathToAttach(TLObject attach, String ext, boolean forceCache) { File dir = null; - if (attach instanceof TLRPC.Video) { - TLRPC.Video video = (TLRPC.Video)attach; - if (forceCache || video.key != null) { - dir = getInstance().getDirectory(MEDIA_DIR_CACHE); - } else { - dir = getInstance().getDirectory(MEDIA_DIR_VIDEO); - } - } else if (attach instanceof TLRPC.Document) { - TLRPC.Document document = (TLRPC.Document)attach; - if (forceCache || document.key != null) { - dir = getInstance().getDirectory(MEDIA_DIR_CACHE); - } else { - dir = getInstance().getDirectory(MEDIA_DIR_DOCUMENT); - } - } else if (attach instanceof TLRPC.PhotoSize) { - TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize)attach; - if (forceCache || photoSize.location == null || photoSize.location.key != null || photoSize.location.volume_id == Integer.MIN_VALUE && photoSize.location.local_id < 0) { - dir = getInstance().getDirectory(MEDIA_DIR_CACHE); - } else { - dir = getInstance().getDirectory(MEDIA_DIR_IMAGE); - } - } else if (attach instanceof TLRPC.Audio) { - TLRPC.Audio audio = (TLRPC.Audio)attach; - if (forceCache || audio.key != null) { - dir = getInstance().getDirectory(MEDIA_DIR_CACHE); - } else { - dir = getInstance().getDirectory(MEDIA_DIR_AUDIO); - } - } else if (attach instanceof TLRPC.FileLocation) { - TLRPC.FileLocation fileLocation = (TLRPC.FileLocation)attach; - if (forceCache || fileLocation.key != null || fileLocation.volume_id == Integer.MIN_VALUE && fileLocation.local_id < 0) { - dir = getInstance().getDirectory(MEDIA_DIR_CACHE); - } else { - dir = getInstance().getDirectory(MEDIA_DIR_IMAGE); + if (forceCache) { + dir = getInstance().getDirectory(MEDIA_DIR_CACHE); + } else { + if (attach instanceof TLRPC.Video) { + TLRPC.Video video = (TLRPC.Video) attach; + if (video.key != null) { + dir = getInstance().getDirectory(MEDIA_DIR_CACHE); + } else { + dir = getInstance().getDirectory(MEDIA_DIR_VIDEO); + } + } else if (attach instanceof TLRPC.Document) { + TLRPC.Document document = (TLRPC.Document) attach; + if (document.key != null) { + dir = getInstance().getDirectory(MEDIA_DIR_CACHE); + } else { + dir = getInstance().getDirectory(MEDIA_DIR_DOCUMENT); + } + } else if (attach instanceof TLRPC.PhotoSize) { + TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) attach; + if (photoSize.location == null || photoSize.location.key != null || photoSize.location.volume_id == Integer.MIN_VALUE && photoSize.location.local_id < 0) { + dir = getInstance().getDirectory(MEDIA_DIR_CACHE); + } else { + dir = getInstance().getDirectory(MEDIA_DIR_IMAGE); + } + } else if (attach instanceof TLRPC.Audio) { + TLRPC.Audio audio = (TLRPC.Audio) attach; + if (audio.key != null) { + dir = getInstance().getDirectory(MEDIA_DIR_CACHE); + } else { + dir = getInstance().getDirectory(MEDIA_DIR_AUDIO); + } + } else if (attach instanceof TLRPC.FileLocation) { + TLRPC.FileLocation fileLocation = (TLRPC.FileLocation) attach; + if (fileLocation.key != null || fileLocation.volume_id == Integer.MIN_VALUE && fileLocation.local_id < 0) { + dir = getInstance().getDirectory(MEDIA_DIR_CACHE); + } else { + dir = getInstance().getDirectory(MEDIA_DIR_IMAGE); + } } } if (dir == null) { return new File(""); } - return new File(dir, getAttachFileName(attach)); + return new File(dir, getAttachFileName(attach, ext)); } public static TLRPC.PhotoSize getClosestPhotoSizeWithSize(ArrayList sizes, int side) { @@ -663,6 +677,9 @@ public class FileLoader { public static String getDocumentFileName(TLRPC.Document document) { if (document != null) { + if (document.file_name != null) { + return document.file_name; + } for (TLRPC.DocumentAttribute documentAttribute : document.attributes) { if (documentAttribute instanceof TLRPC.TL_documentAttributeFilename) { return documentAttribute.file_name; @@ -673,35 +690,39 @@ public class FileLoader { } public static String getAttachFileName(TLObject attach) { + return getAttachFileName(attach, null); + } + + public static String getAttachFileName(TLObject attach, String ext) { if (attach instanceof TLRPC.Video) { - TLRPC.Video video = (TLRPC.Video)attach; - return video.dc_id + "_" + video.id + ".mp4"; + TLRPC.Video video = (TLRPC.Video) attach; + return video.dc_id + "_" + video.id + "." + (ext != null ? ext : "mp4"); } else if (attach instanceof TLRPC.Document) { - TLRPC.Document document = (TLRPC.Document)attach; - String ext = getDocumentFileName(document); - int idx = -1; - if (ext == null || (idx = ext.lastIndexOf(".")) == -1) { - ext = ""; + TLRPC.Document document = (TLRPC.Document) attach; + String docExt = getDocumentFileName(document); + int idx; + if (docExt == null || (idx = docExt.lastIndexOf(".")) == -1) { + docExt = ""; } else { - ext = ext.substring(idx); + docExt = docExt.substring(idx); } - if (ext.length() > 1) { - return document.dc_id + "_" + document.id + ext; + if (docExt.length() > 1) { + return document.dc_id + "_" + document.id + docExt; } else { return document.dc_id + "_" + document.id; } } else if (attach instanceof TLRPC.PhotoSize) { - TLRPC.PhotoSize photo = (TLRPC.PhotoSize)attach; + TLRPC.PhotoSize photo = (TLRPC.PhotoSize) attach; if (photo.location == null) { return ""; } - return photo.location.volume_id + "_" + photo.location.local_id + "." + (photo.location.ext != null ? photo.location.ext : "jpg"); + return photo.location.volume_id + "_" + photo.location.local_id + "." + (ext != null ? ext : "jpg"); } else if (attach instanceof TLRPC.Audio) { - TLRPC.Audio audio = (TLRPC.Audio)attach; - return audio.dc_id + "_" + audio.id + ".ogg"; + TLRPC.Audio audio = (TLRPC.Audio) attach; + return audio.dc_id + "_" + audio.id + "." + (ext != null ? ext : "ogg"); } else if (attach instanceof TLRPC.FileLocation) { - TLRPC.FileLocation location = (TLRPC.FileLocation)attach; - return location.volume_id + "_" + location.local_id + "." + (location.ext != null ? location.ext : "jpg"); + TLRPC.FileLocation location = (TLRPC.FileLocation) attach; + return location.volume_id + "_" + location.local_id + "." + (ext != null ? ext : "jpg"); } return ""; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index e72408acc..b54bff7a4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -1,14 +1,13 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; -import android.net.Uri; import android.util.Log; import org.telegram.android.time.FastDateFormat; @@ -16,7 +15,6 @@ import org.telegram.android.time.FastDateFormat; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; -import java.util.ArrayList; import java.util.Locale; public class FileLog { @@ -50,14 +48,8 @@ public class FileLog { return; } File dir = new File(sdCard.getAbsolutePath() + "/logs"); - if (dir == null) { - return; - } dir.mkdirs(); currentFile = new File(dir, dateFormat.format(System.currentTimeMillis()) + ".txt"); - if (currentFile == null) { - return; - } } catch (Exception e) { e.printStackTrace(); } @@ -181,7 +173,6 @@ public class FileLog { } public static void cleanupLogs() { - ArrayList uris = new ArrayList<>(); File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null); File dir = new File (sdCard.getAbsolutePath() + "/logs"); File[] files = dir.listFiles(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index 788a202a4..1faeda79f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -46,7 +46,7 @@ public class FileUploadOperation { private boolean started = false; public interface FileUploadOperationDelegate { - void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile); + void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv); void didFailedUploadingFile(FileUploadOperation operation); void didChangedUploadProgress(FileUploadOperation operation, float progress); } @@ -190,8 +190,12 @@ public class FileUploadOperation { if (ivString != null && keyString != null) { key = Utilities.hexToBytes(keyString); iv = Utilities.hexToBytes(ivString); - ivChange = new byte[32]; - System.arraycopy(iv, 0, ivChange, 0, 32); + if (key != null && iv != null && key.length == 32 && iv.length == 32) { + ivChange = new byte[32]; + System.arraycopy(iv, 0, ivChange, 0, 32); + } else { + rewrite = true; + } } else { rewrite = true; } @@ -234,6 +238,11 @@ public class FileUploadOperation { String ivcString = preferences.getString(fileKey + "_ivc", null); if (ivcString != null) { ivChange = Utilities.hexToBytes(ivcString); + if (ivChange == null || ivChange.length != 32) { + rewrite = true; + currentUploaded = 0; + currentPartNum = 0; + } } else { rewrite = true; currentUploaded = 0; @@ -369,7 +378,7 @@ public class FileUploadOperation { result.parts = currentPartNum; result.id = currentFileId; result.name = uploadingFilePath.substring(uploadingFilePath.lastIndexOf("/") + 1); - delegate.didFinishUploadingFile(FileUploadOperation.this, result, null); + delegate.didFinishUploadingFile(FileUploadOperation.this, result, null, null, null); cleanup(); } else { TLRPC.InputEncryptedFile result; @@ -382,9 +391,7 @@ public class FileUploadOperation { result.parts = currentPartNum; result.id = currentFileId; result.key_fingerprint = fingerprint; - result.iv = iv; - result.key = key; - delegate.didFinishUploadingFile(FileUploadOperation.this, null, result); + delegate.didFinishUploadingFile(FileUploadOperation.this, null, result, key, iv); cleanup(); } } else { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java b/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java index cf64c98e0..eb225c09c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java index 6aef7a298..669f3a029 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java @@ -1,14 +1,68 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; public class MessageKeyData { + public byte[] aesKey; public byte[] aesIv; + + public static MessageKeyData generateMessageKeyData(byte[] authKey, byte[] messageKey, boolean incoming) { + MessageKeyData keyData = new MessageKeyData(); + if (authKey == null || authKey.length == 0) { + keyData.aesIv = null; + keyData.aesKey = null; + return keyData; + } + + int x = incoming ? 8 : 0; + + SerializedData data = new SerializedData(); + data.writeRaw(messageKey); + data.writeRaw(authKey, x, 32); + byte[] sha1_a = Utilities.computeSHA1(data.toByteArray()); + data.cleanup(); + + data = new SerializedData(); + data.writeRaw(authKey, 32 + x, 16); + data.writeRaw(messageKey); + data.writeRaw(authKey, 48 + x, 16); + byte[] sha1_b = Utilities.computeSHA1(data.toByteArray()); + data.cleanup(); + + data = new SerializedData(); + data.writeRaw(authKey, 64 + x, 32); + data.writeRaw(messageKey); + byte[] sha1_c = Utilities.computeSHA1(data.toByteArray()); + data.cleanup(); + + data = new SerializedData(); + data.writeRaw(messageKey); + data.writeRaw(authKey, 96 + x, 32); + byte[] sha1_d = Utilities.computeSHA1(data.toByteArray()); + data.cleanup(); + + data = new SerializedData(); + data.writeRaw(sha1_a, 0, 8); + data.writeRaw(sha1_b, 8, 12); + data.writeRaw(sha1_c, 4, 12); + keyData.aesKey = data.toByteArray(); + data.cleanup(); + + data = new SerializedData(); + data.writeRaw(sha1_a, 8, 12); + data.writeRaw(sha1_b, 0, 8); + data.writeRaw(sha1_c, 16, 4); + data.writeRaw(sha1_d, 0, 8); + keyData.aesIv = data.toByteArray(); + data.cleanup(); + + return keyData; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NetworkMessage.java b/TMessagesProj/src/main/java/org/telegram/messenger/NetworkMessage.java index a44ef7664..67cd93cf4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NetworkMessage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NetworkMessage.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/RPCRequest.java b/TMessagesProj/src/main/java/org/telegram/messenger/RPCRequest.java index 180c9446b..63dd660f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/RPCRequest.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/RPCRequest.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SerializedData.java b/TMessagesProj/src/main/java/org/telegram/messenger/SerializedData.java index f01309425..d23048322 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SerializedData.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SerializedData.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ServerSalt.java b/TMessagesProj/src/main/java/org/telegram/messenger/ServerSalt.java index 33ca53ea2..88aa01958 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ServerSalt.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ServerSalt.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java index 8b433f284..1c855859e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -13,7 +13,7 @@ import java.util.HashMap; public class TLClassStore { private HashMap classStore; - public TLClassStore () { + public TLClassStore() { classStore = new HashMap<>(); classStore.put(TLRPC.TL_futuresalts.constructor, TLRPC.TL_futuresalts.class); @@ -108,26 +108,18 @@ public class TLClassStore { } public TLObject TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - try { - return TLdeserialize(stream, constructor, null, exception); - } catch (Exception e) { - return null; - } - } - - public TLObject TLdeserialize(AbsSerializedData stream, int constructor, TLObject request, boolean exception) { Class objClass = classStore.get(constructor); if (objClass != null) { + TLObject response; try { - TLObject response = (TLObject)objClass.newInstance(); - response.readParams(stream, exception); - return response; + response = (TLObject) objClass.newInstance(); } catch (Throwable e) { - FileLog.e("tmessages", "can't create class"); + FileLog.e("tmessages", e); return null; } - } else { - return null; + response.readParams(stream, exception); + return response; } + return null; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLObject.java index 17c493070..12cb748fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLObject.java @@ -1,14 +1,15 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; public class TLObject { + public boolean disableFree = false; public TLObject() { @@ -19,10 +20,6 @@ public class TLObject { } - public byte[] serialize() { - return null; - } - public void serializeToStream(AbsSerializedData stream) { } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java index cd093459a..32d39df40 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java @@ -1,15 +1,14 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; import java.util.ArrayList; -import java.util.Locale; @SuppressWarnings("unchecked") public class TLRPC { @@ -20,7 +19,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_REPLY = 8; public static final int MESSAGE_FLAG_MENTION = 16; public static final int MESSAGE_FLAG_CONTENT_UNREAD = 32; - public static final int LAYER = 28; + public static final int LAYER = 30; public static class TL_inputEncryptedChat extends TLObject { public static int constructor = 0xf141b5e1; @@ -247,6 +246,39 @@ public class TLRPC { } } + public static class InputEncryptedFile extends TLObject { + public long id; + public long access_hash; + public int parts; + public int key_fingerprint; + public String md5_checksum; + + public static InputEncryptedFile TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + InputEncryptedFile result = null; + switch(constructor) { + case 0x5a17b5e5: + result = new TL_inputEncryptedFile(); + break; + case 0x2dc173c8: + result = new TL_inputEncryptedFileBigUploaded(); + break; + case 0x1837c364: + result = new TL_inputEncryptedFileEmpty(); + break; + case 0x64bd0306: + result = new TL_inputEncryptedFileUploaded(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in InputEncryptedFile", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_inputEncryptedFile extends InputEncryptedFile { public static int constructor = 0x5a17b5e5; @@ -482,9 +514,24 @@ public class TLRPC { } } + public static class TL_messageEmpty extends Message { + public static int constructor = 0x83e5de54; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + } + } + public static class TL_messageService extends Message { public static int constructor = 0x1d86f70e; + public void readParams(AbsSerializedData stream, boolean exception) { flags = stream.readInt32(exception); id = stream.readInt32(exception); @@ -505,17 +552,75 @@ public class TLRPC { } } - public static class TL_messageEmpty extends Message { - public static int constructor = 0x83e5de54; + public static class TL_messages_stickerSet extends TLObject { + public static int constructor = 0xb60a24a6; + public TL_stickerSet set; + public ArrayList packs = new ArrayList<>(); + public ArrayList documents = new ArrayList<>(); + + public static TL_messages_stickerSet TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + if (TL_messages_stickerSet.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messages_stickerSet", constructor)); + } else { + return null; + } + } + TL_messages_stickerSet result = new TL_messages_stickerSet(); + result.readParams(stream, exception); + return result; + } public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); + set = TL_stickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_stickerPack object = TL_stickerPack.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + packs.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Document object = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + documents.add(object); + } } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(id); + set.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = packs.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + packs.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = documents.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + documents.get(a).serializeToStream(stream); + } } } @@ -823,7 +928,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - attributes.add(DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception)); + DocumentAttribute object = DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + attributes.add(object); } } @@ -1029,7 +1138,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - attributes.add(DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception)); + DocumentAttribute object = DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + attributes.add(object); } } @@ -1095,7 +1208,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1106,7 +1223,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } seq = stream.readInt32(exception); } @@ -1171,7 +1292,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - dialogs.add(TL_dialog.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_dialog object = TL_dialog.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + dialogs.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1182,7 +1307,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - messages.add(Message.TLdeserialize(stream, stream.readInt32(exception), exception)); + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1193,7 +1322,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1204,7 +1337,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -1252,7 +1389,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - dialogs.add(TL_dialog.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_dialog object = TL_dialog.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + dialogs.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1263,7 +1404,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - messages.add(Message.TLdeserialize(stream, stream.readInt32(exception), exception)); + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1274,7 +1419,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1285,7 +1434,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -1411,7 +1564,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(InputUser.TLdeserialize(stream, stream.readInt32(exception), exception)); + InputUser object = InputUser.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -1476,7 +1633,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(InputUser.TLdeserialize(stream, stream.readInt32(exception), exception)); + InputUser object = InputUser.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -1564,7 +1725,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - photos.add(Photo.TLdeserialize(stream, stream.readInt32(exception), exception)); + Photo object = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + photos.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1575,7 +1740,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -1611,7 +1780,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - photos.add(Photo.TLdeserialize(stream, stream.readInt32(exception), exception)); + Photo object = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + photos.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -1622,7 +1795,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -1687,6 +1864,55 @@ public class TLRPC { } } + public static class UserStatus extends TLObject { + public int expires; + + public static UserStatus TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + UserStatus result = null; + switch(constructor) { + case 0x8c703f: + result = new TL_userStatusOffline(); + break; + case 0x7bf09fc: + result = new TL_userStatusLastWeek(); + break; + case 0x9d05049: + result = new TL_userStatusEmpty(); + break; + case 0x77ebc742: + result = new TL_userStatusLastMonth(); + break; + case 0xedb93949: + result = new TL_userStatusOnline(); + break; + case 0xe26f42f1: + result = new TL_userStatusRecently(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in UserStatus", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_userStatusOffline extends UserStatus { + public static int constructor = 0x8c703f; + + + public void readParams(AbsSerializedData stream, boolean exception) { + expires = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(expires); + } + } + public static class TL_userStatusLastWeek extends UserStatus { public static int constructor = 0x7bf09fc; @@ -2011,7 +2237,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - participants.add(TL_chatParticipant.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_chatParticipant object = TL_chatParticipant.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + participants.add(object); } version = stream.readInt32(exception); } @@ -2072,6 +2302,40 @@ public class TLRPC { } } + public static class DecryptedMessage extends TLObject { + public long random_id; + public DecryptedMessageAction action; + public byte[] random_bytes; + public String message; + public DecryptedMessageMedia media; + public int ttl; + + public static DecryptedMessage TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + DecryptedMessage result = null; + switch(constructor) { + case 0x73164160: + result = new TL_decryptedMessageService(); + break; + case 0x1f814f1f: + result = new TL_decryptedMessage_old(); + break; + case 0x204d3878: + result = new TL_decryptedMessage(); + break; + case 0xaa48327d: + result = new TL_decryptedMessageService_old(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in DecryptedMessage", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_decryptedMessageService extends DecryptedMessage { public static int constructor = 0x73164160; @@ -2088,6 +2352,26 @@ public class TLRPC { } } + public static class TL_decryptedMessage_old extends TL_decryptedMessage { + public static int constructor = 0x1f814f1f; + + + public void readParams(AbsSerializedData stream, boolean exception) { + random_id = stream.readInt64(exception); + random_bytes = stream.readByteArray(exception); + message = stream.readString(exception); + media = DecryptedMessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(random_id); + stream.writeByteArray(random_bytes); + stream.writeString(message); + media.serializeToStream(stream); + } + } + public static class TL_decryptedMessage extends DecryptedMessage { public static int constructor = 0x204d3878; @@ -2108,6 +2392,24 @@ public class TLRPC { } } + public static class TL_decryptedMessageService_old extends TL_decryptedMessageService { + public static int constructor = 0xaa48327d; + + + public void readParams(AbsSerializedData stream, boolean exception) { + random_id = stream.readInt64(exception); + random_bytes = stream.readByteArray(exception); + action = DecryptedMessageAction.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(random_id); + stream.writeByteArray(random_bytes); + action.serializeToStream(stream); + } + } + public static class messages_Messages extends TLObject { public ArrayList messages = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -2148,7 +2450,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - messages.add(Message.TLdeserialize(stream, stream.readInt32(exception), exception)); + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -2159,7 +2465,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -2170,7 +2480,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -2212,7 +2526,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - messages.add(Message.TLdeserialize(stream, stream.readInt32(exception), exception)); + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -2223,7 +2541,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -2234,7 +2556,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -2326,9 +2652,86 @@ public class TLRPC { } } + public static class DecryptedMessageMedia extends TLObject { + public int thumb_w; + public int thumb_h; + public String file_name; + public String mime_type; + public int size; + public byte[] key; + public byte[] iv; + public long id; + public long access_hash; + public int date; + public int dc_id; + public ArrayList attributes = new ArrayList<>(); + public int duration; + public double lat; + public double _long; + public int w; + public int h; + public String phone_number; + public String first_name; + public String last_name; + public int user_id; + + public static DecryptedMessageMedia TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + DecryptedMessageMedia result = null; + switch(constructor) { + case 0x89f5c4a: + result = new TL_decryptedMessageMediaEmpty(); + break; + case 0xb095434b: + result = new TL_decryptedMessageMediaDocument(); + break; + case 0xfa95b0dd: + result = new TL_decryptedMessageMediaExternalDocument(); + break; + case 0x6080758f: + result = new TL_decryptedMessageMediaAudio_old(); + break; + case 0x35480a59: + result = new TL_decryptedMessageMediaGeoPoint(); + break; + case 0x57e0a9cb: + result = new TL_decryptedMessageMediaAudio(); + break; + case 0x524a415d: + result = new TL_decryptedMessageMediaVideo(); + break; + case 0x588a0a97: + result = new TL_decryptedMessageMediaContact(); + break; + case 0x32798a8c: + result = new TL_decryptedMessageMediaPhoto(); + break; + case 0x4cee6ef3: + result = new TL_decryptedMessageMediaVideo_old(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in DecryptedMessageMedia", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_decryptedMessageMediaEmpty extends DecryptedMessageMedia { + public static int constructor = 0x89f5c4a; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_decryptedMessageMediaDocument extends DecryptedMessageMedia { public static int constructor = 0xb095434b; + public byte[] thumb; public void readParams(AbsSerializedData stream, boolean exception) { thumb = stream.readByteArray(exception); @@ -2354,6 +2757,74 @@ public class TLRPC { } } + public static class TL_decryptedMessageMediaExternalDocument extends DecryptedMessageMedia { + public static int constructor = 0xfa95b0dd; + + public PhotoSize thumb; + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + date = stream.readInt32(exception); + mime_type = stream.readString(exception); + size = stream.readInt32(exception); + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + DocumentAttribute object = DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + attributes.add(object); + } + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(date); + stream.writeString(mime_type); + stream.writeInt32(size); + thumb.serializeToStream(stream); + stream.writeInt32(dc_id); + stream.writeInt32(0x1cb5c415); + int count = attributes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + attributes.get(a).serializeToStream(stream); + } + } + } + + public static class TL_decryptedMessageMediaAudio_old extends TL_decryptedMessageMediaAudio { + public static int constructor = 0x6080758f; + + + public void readParams(AbsSerializedData stream, boolean exception) { + duration = stream.readInt32(exception); + size = stream.readInt32(exception); + key = stream.readByteArray(exception); + iv = stream.readByteArray(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(duration); + stream.writeInt32(size); + stream.writeByteArray(key); + stream.writeByteArray(iv); + } + } + public static class TL_decryptedMessageMediaGeoPoint extends DecryptedMessageMedia { public static int constructor = 0x35480a59; @@ -2395,6 +2866,7 @@ public class TLRPC { public static class TL_decryptedMessageMediaVideo extends DecryptedMessageMedia { public static int constructor = 0x524a415d; + public byte[] thumb; public void readParams(AbsSerializedData stream, boolean exception) { thumb = stream.readByteArray(exception); @@ -2444,18 +2916,10 @@ public class TLRPC { } } - public static class TL_decryptedMessageMediaEmpty extends DecryptedMessageMedia { - public static int constructor = 0x89f5c4a; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - public static class TL_decryptedMessageMediaPhoto extends DecryptedMessageMedia { public static int constructor = 0x32798a8c; + public byte[] thumb; public void readParams(AbsSerializedData stream, boolean exception) { thumb = stream.readByteArray(exception); @@ -2481,6 +2945,150 @@ public class TLRPC { } } + public static class TL_decryptedMessageMediaVideo_old extends TL_decryptedMessageMediaVideo { + public static int constructor = 0x4cee6ef3; + + public byte[] thumb; + + public void readParams(AbsSerializedData stream, boolean exception) { + thumb = stream.readByteArray(exception); + thumb_w = stream.readInt32(exception); + thumb_h = stream.readInt32(exception); + duration = stream.readInt32(exception); + w = stream.readInt32(exception); + h = stream.readInt32(exception); + size = stream.readInt32(exception); + key = stream.readByteArray(exception); + iv = stream.readByteArray(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeByteArray(thumb); + stream.writeInt32(thumb_w); + stream.writeInt32(thumb_h); + stream.writeInt32(duration); + stream.writeInt32(w); + stream.writeInt32(h); + stream.writeInt32(size); + stream.writeByteArray(key); + stream.writeByteArray(iv); + } + } + + public static class User extends TLObject { + public int id; + public String first_name; + public String last_name; + public long access_hash; + public String phone; + public UserProfilePhoto photo; + public UserStatus status; + public boolean inactive; + public String username; + + public static User TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + User result = null; + switch(constructor) { + case 0xf2fb8319: + result = new TL_userContact_old(); + break; + case 0x720535ec: + result = new TL_userSelf_old(); + break; + case 0xcab35e18: + result = new TL_userContact(); + break; + case 0x1c60e608: + result = new TL_userSelf(); + break; + case 0x75cf7a8: + result = new TL_userForeign(); + break; + case 0x200250ba: + result = new TL_userEmpty(); + break; + case 0x22e8ceb0: + result = new TL_userRequest_old(); + break; + case 0x5214c89d: + result = new TL_userForeign_old(); + break; + case 0xd9ccc4ef: + result = new TL_userRequest(); + break; + case 0x7007b451: + result = new TL_userSelf_old2(); + break; + case 0xb29ad7cc: + result = new TL_userDeleted_old(); + break; + case 0xd6016d7a: + result = new TL_userDeleted(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in User", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_userContact_old extends TL_userContact { + public static int constructor = 0xf2fb8319; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + first_name = stream.readString(exception); + last_name = stream.readString(exception); + access_hash = stream.readInt64(exception); + phone = stream.readString(exception); + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeString(first_name); + stream.writeString(last_name); + stream.writeInt64(access_hash); + stream.writeString(phone); + photo.serializeToStream(stream); + status.serializeToStream(stream); + } + } + + public static class TL_userSelf_old extends TL_userSelf { + public static int constructor = 0x720535ec; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + first_name = stream.readString(exception); + last_name = stream.readString(exception); + phone = stream.readString(exception); + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + inactive = stream.readBool(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeString(first_name); + stream.writeString(last_name); + stream.writeString(phone); + photo.serializeToStream(stream); + status.serializeToStream(stream); + stream.writeBool(inactive); + } + } + public static class TL_userContact extends User { public static int constructor = 0xcab35e18; @@ -2509,6 +3117,108 @@ public class TLRPC { } } + public static class TL_userSelf extends User { + public static int constructor = 0x1c60e608; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + first_name = stream.readString(exception); + last_name = stream.readString(exception); + username = stream.readString(exception); + phone = stream.readString(exception); + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeString(first_name); + stream.writeString(last_name); + stream.writeString(username); + stream.writeString(phone); + photo.serializeToStream(stream); + status.serializeToStream(stream); + } + } + + public static class TL_userForeign extends User { + public static int constructor = 0x75cf7a8; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + first_name = stream.readString(exception); + last_name = stream.readString(exception); + username = stream.readString(exception); + access_hash = stream.readInt64(exception); + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeString(first_name); + stream.writeString(last_name); + stream.writeString(username); + stream.writeInt64(access_hash); + photo.serializeToStream(stream); + status.serializeToStream(stream); + } + } + + public static class TL_userRequest_old extends TL_userRequest { + public static int constructor = 0x22e8ceb0; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + first_name = stream.readString(exception); + last_name = stream.readString(exception); + access_hash = stream.readInt64(exception); + phone = stream.readString(exception); + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeString(first_name); + stream.writeString(last_name); + stream.writeInt64(access_hash); + stream.writeString(phone); + photo.serializeToStream(stream); + status.serializeToStream(stream); + } + } + + public static class TL_userForeign_old extends TL_userForeign { + public static int constructor = 0x5214c89d; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + first_name = stream.readString(exception); + last_name = stream.readString(exception); + access_hash = stream.readInt64(exception); + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeString(first_name); + stream.writeString(last_name); + stream.writeInt64(access_hash); + photo.serializeToStream(stream); + status.serializeToStream(stream); + } + } + public static class TL_userRequest extends User { public static int constructor = 0xd9ccc4ef; @@ -2537,8 +3247,8 @@ public class TLRPC { } } - public static class TL_userForeign extends User { - public static int constructor = 0x75cf7a8; + public static class TL_userSelf_old2 extends TL_userSelf { + public static int constructor = 0x7007b451; public void readParams(AbsSerializedData stream, boolean exception) { @@ -2546,9 +3256,10 @@ public class TLRPC { first_name = stream.readString(exception); last_name = stream.readString(exception); username = stream.readString(exception); - access_hash = stream.readInt64(exception); + phone = stream.readString(exception); photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + inactive = stream.readBool(exception); } public void serializeToStream(AbsSerializedData stream) { @@ -2557,9 +3268,28 @@ public class TLRPC { stream.writeString(first_name); stream.writeString(last_name); stream.writeString(username); - stream.writeInt64(access_hash); + stream.writeString(phone); photo.serializeToStream(stream); status.serializeToStream(stream); + stream.writeBool(inactive); + } + } + + public static class TL_userDeleted_old extends TL_userDeleted { + public static int constructor = 0xb29ad7cc; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + first_name = stream.readString(exception); + last_name = stream.readString(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeString(first_name); + stream.writeString(last_name); } } @@ -2583,29 +3313,88 @@ public class TLRPC { } } - public static class TL_userSelf extends User { - public static int constructor = 0x1c60e608; + public static class MessageMedia extends TLObject { + public byte[] bytes; + public Video video; + public String caption; + public Photo photo; + public Audio audio; + public GeoPoint geo; + public String title; + public String address; + public String provider; + public String venue_id; + public Document document; + public String phone_number; + public String first_name; + public String last_name; + public int user_id; + public WebPage webpage; + + public static MessageMedia TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + MessageMedia result = null; + switch(constructor) { + case 0x29632a36: + result = new TL_messageMediaUnsupported_old(); + break; + case 0x5bcf1675: + result = new TL_messageMediaVideo(); + break; + case 0xc8c45a2a: + result = new TL_messageMediaPhoto_old(); + break; + case 0xc6b68300: + result = new TL_messageMediaAudio(); + break; + case 0x9f84f49e: + result = new TL_messageMediaUnsupported(); + break; + case 0x3ded6320: + result = new TL_messageMediaEmpty(); + break; + case 0x7912b71f: + result = new TL_messageMediaVenue(); + break; + case 0xa2d24290: + result = new TL_messageMediaVideo_old(); + break; + case 0x2fda2204: + result = new TL_messageMediaDocument(); + break; + case 0x5e7d2f39: + result = new TL_messageMediaContact(); + break; + case 0x3d8ce53d: + result = new TL_messageMediaPhoto(); + break; + case 0xa32dd600: + result = new TL_messageMediaWebPage(); + break; + case 0x56e0d474: + result = new TL_messageMediaGeo(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in MessageMedia", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_messageMediaUnsupported_old extends TL_messageMediaUnsupported { + public static int constructor = 0x29632a36; public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - first_name = stream.readString(exception); - last_name = stream.readString(exception); - username = stream.readString(exception); - phone = stream.readString(exception); - photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + bytes = stream.readByteArray(exception); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(id); - stream.writeString(first_name); - stream.writeString(last_name); - stream.writeString(username); - stream.writeString(phone); - photo.serializeToStream(stream); - status.serializeToStream(stream); + stream.writeByteArray(bytes); } } @@ -2625,6 +3414,122 @@ public class TLRPC { } } + public static class TL_messageMediaPhoto_old extends TL_messageMediaPhoto { + public static int constructor = 0xc8c45a2a; + + + public void readParams(AbsSerializedData stream, boolean exception) { + photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + photo.serializeToStream(stream); + } + } + + public static class TL_messageMediaAudio extends MessageMedia { + public static int constructor = 0xc6b68300; + + + public void readParams(AbsSerializedData stream, boolean exception) { + audio = Audio.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + audio.serializeToStream(stream); + } + } + + public static class TL_messageMediaUnsupported extends MessageMedia { + public static int constructor = 0x9f84f49e; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_messageMediaEmpty extends MessageMedia { + public static int constructor = 0x3ded6320; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_messageMediaVenue extends MessageMedia { + public static int constructor = 0x7912b71f; + + + public void readParams(AbsSerializedData stream, boolean exception) { + geo = GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); + title = stream.readString(exception); + address = stream.readString(exception); + provider = stream.readString(exception); + venue_id = stream.readString(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + geo.serializeToStream(stream); + stream.writeString(title); + stream.writeString(address); + stream.writeString(provider); + stream.writeString(venue_id); + } + } + + public static class TL_messageMediaVideo_old extends TL_messageMediaVideo { + public static int constructor = 0xa2d24290; + + + public void readParams(AbsSerializedData stream, boolean exception) { + video = Video.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + video.serializeToStream(stream); + } + } + + public static class TL_messageMediaDocument extends MessageMedia { + public static int constructor = 0x2fda2204; + + + public void readParams(AbsSerializedData stream, boolean exception) { + document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + document.serializeToStream(stream); + } + } + + public static class TL_messageMediaContact extends MessageMedia { + public static int constructor = 0x5e7d2f39; + + + public void readParams(AbsSerializedData stream, boolean exception) { + phone_number = stream.readString(exception); + first_name = stream.readString(exception); + last_name = stream.readString(exception); + user_id = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(phone_number); + stream.writeString(first_name); + stream.writeString(last_name); + stream.writeInt32(user_id); + } + } + public static class TL_messageMediaPhoto extends MessageMedia { public static int constructor = 0x3d8ce53d; @@ -2655,20 +3560,6 @@ public class TLRPC { } } - public static class TL_messageMediaDocument extends MessageMedia { - public static int constructor = 0x2fda2204; - - - public void readParams(AbsSerializedData stream, boolean exception) { - document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - document.serializeToStream(stream); - } - } - public static class TL_messageMediaGeo extends MessageMedia { public static int constructor = 0x56e0d474; @@ -2683,80 +3574,6 @@ public class TLRPC { } } - public static class TL_messageMediaEmpty extends MessageMedia { - public static int constructor = 0x3ded6320; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_messageMediaAudio extends MessageMedia { - public static int constructor = 0xc6b68300; - - - public void readParams(AbsSerializedData stream, boolean exception) { - audio = Audio.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - audio.serializeToStream(stream); - } - } - - public static class TL_messageMediaVenue extends MessageMedia { - public static int constructor = 0x7912b71f; - - - public void readParams(AbsSerializedData stream, boolean exception) { - geo = GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); - title = stream.readString(exception); - address = stream.readString(exception); - provider = stream.readString(exception); - venue_id = stream.readString(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - geo.serializeToStream(stream); - stream.writeString(title); - stream.writeString(address); - stream.writeString(provider); - stream.writeString(venue_id); - } - } - - public static class TL_messageMediaContact extends MessageMedia { - public static int constructor = 0x5e7d2f39; - - - public void readParams(AbsSerializedData stream, boolean exception) { - phone_number = stream.readString(exception); - first_name = stream.readString(exception); - last_name = stream.readString(exception); - user_id = stream.readInt32(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeString(phone_number); - stream.writeString(first_name); - stream.writeString(last_name); - stream.writeInt32(user_id); - } - } - - public static class TL_messageMediaUnsupported extends MessageMedia { - public static int constructor = 0x9f84f49e; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - public static class TL_nearestDc extends TLObject { public static int constructor = 0x8e1a1775; @@ -2882,7 +3699,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - results.add(TL_contactSuggested.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_contactSuggested object = TL_contactSuggested.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + results.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -2893,7 +3714,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -2957,7 +3782,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - sizes.add(PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception)); + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); } color = stream.readInt32(exception); } @@ -3201,7 +4030,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -3361,7 +4194,6 @@ public class TLRPC { public boolean previous; public int inviter_id; public UserStatus status; - public NotifyPeer peer; public static Update TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { Update result = null; @@ -3598,6 +4430,8 @@ public class TLRPC { public static class TL_updateNotifySettings extends Update { public static int constructor = 0xbec268ef; + public NotifyPeer peer; + public void readParams(AbsSerializedData stream, boolean exception) { peer = NotifyPeer.TLdeserialize(stream, stream.readInt32(exception), exception); notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -3730,7 +4564,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - dc_options.add(TL_dcOption.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_dcOption object = TL_dcOption.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + dc_options.add(object); } } @@ -3854,7 +4692,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - rules.add(PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception)); + PrivacyRule object = PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + rules.add(object); } } @@ -4074,7 +4916,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - dc_options.add(TL_dcOption.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_dcOption object = TL_dcOption.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + dc_options.add(object); } chat_size_max = stream.readInt32(exception); broadcast_size_max = stream.readInt32(exception); @@ -4097,7 +4943,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - disabled_features.add(TL_disabledFeature.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_disabledFeature object = TL_disabledFeature.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + disabled_features.add(object); } } @@ -4402,7 +5252,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - links.add(TL_contacts_link.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_contacts_link object = TL_contacts_link.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + links.add(object); } seq = stream.readInt32(exception); } @@ -4648,6 +5502,37 @@ public class TLRPC { } } + public static class FileLocation extends TLObject { + public int dc_id; + public long volume_id; + public int local_id; + public long secret; + public byte[] key; + public byte[] iv; + + public static FileLocation TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + FileLocation result = null; + switch(constructor) { + case 0x53d69076: + result = new TL_fileLocation(); + break; + case 0x55555554: + result = new TL_fileEncryptedLocation(); + break; + case 0x7c596b46: + result = new TL_fileLocationUnavailable(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in FileLocation", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_fileLocation extends FileLocation { public static int constructor = 0x53d69076; @@ -4668,6 +5553,30 @@ public class TLRPC { } } + public static class TL_fileEncryptedLocation extends FileLocation { + public static int constructor = 0x55555554; + + + public void readParams(AbsSerializedData stream, boolean exception) { + dc_id = stream.readInt32(exception); + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + secret = stream.readInt64(exception); + key = stream.readByteArray(exception); + iv = stream.readByteArray(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(dc_id); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + stream.writeInt64(secret); + stream.writeByteArray(key); + stream.writeByteArray(iv); + } + } + public static class TL_fileLocationUnavailable extends FileLocation { public static int constructor = 0x7c596b46; @@ -4686,6 +5595,43 @@ public class TLRPC { } } + public static class TL_stickerSet extends TLObject { + public static int constructor = 0xa7a43b17; + + public long id; + public long access_hash; + public String title; + public String short_name; + + public static TL_stickerSet TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + if (TL_stickerSet.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_stickerSet", constructor)); + } else { + return null; + } + } + TL_stickerSet result = new TL_stickerSet(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + title = stream.readString(exception); + short_name = stream.readString(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeString(title); + stream.writeString(short_name); + } + } + public static class TL_pong extends TLObject { public static int constructor = 0x347773c5; @@ -4785,7 +5731,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -4796,7 +5746,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -5166,10 +6120,10 @@ public class TLRPC { } public static class TL_dcOption extends TLObject { - public static int constructor = 0x2ec2a43c; + public static int constructor = 0x5d8c6cc; + public int flags; public int id; - public String hostname; public String ip_address; public int port; @@ -5187,16 +6141,16 @@ public class TLRPC { } public void readParams(AbsSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); id = stream.readInt32(exception); - hostname = stream.readString(exception); ip_address = stream.readString(exception); port = stream.readInt32(exception); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); stream.writeInt32(id); - stream.writeString(hostname); stream.writeString(ip_address); stream.writeInt32(port); } @@ -5521,7 +6475,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - rules.add(PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception)); + PrivacyRule object = PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + rules.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -5532,7 +6490,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -5791,6 +6753,52 @@ public class TLRPC { } } + public static class Photo extends TLObject { + public long id; + public long access_hash; + public int user_id; + public int date; + public GeoPoint geo; + public ArrayList sizes = new ArrayList<>(); + public String caption; + + public static Photo TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + Photo result = null; + switch(constructor) { + case 0x2331b22d: + result = new TL_photoEmpty(); + break; + case 0xc3838076: + result = new TL_photo(); + break; + case 0x22b56751: + result = new TL_photo_old(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in Photo", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_photoEmpty extends Photo { + public static int constructor = 0x2331b22d; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + } + } + public static class TL_photo extends Photo { public static int constructor = 0xc3838076; @@ -5810,7 +6818,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - sizes.add(PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception)); + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); } } @@ -5830,17 +6842,48 @@ public class TLRPC { } } - public static class TL_photoEmpty extends Photo { - public static int constructor = 0x2331b22d; + public static class TL_photo_old extends TL_photo { + public static int constructor = 0x22b56751; public void readParams(AbsSerializedData stream, boolean exception) { id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + caption = stream.readString(exception); + geo = GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); + } } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeString(caption); + geo.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = sizes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + sizes.get(a).serializeToStream(stream); + } } } @@ -6183,22 +7226,129 @@ public class TLRPC { } } - public static class TL_messageActionChatEditPhoto extends MessageAction { - public static int constructor = 0x7fcb13a8; + public static class MessageAction extends TLObject { + public String title; + public String address; + public int user_id; + public int inviter_id; + public DecryptedMessageAction encryptedAction; + public int ttl; + public UserProfilePhoto newUserPhoto; + public Photo photo; + public ArrayList users = new ArrayList<>(); + + public static MessageAction TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + MessageAction result = null; + switch(constructor) { + case 0xc7d53de: + result = new TL_messageActionGeoChatCheckin(); + break; + case 0x55555557: + result = new TL_messageActionCreatedBroadcastList(); + break; + case 0xb5a1ce5a: + result = new TL_messageActionChatEditTitle(); + break; + case 0x555555F5: + result = new TL_messageActionLoginUnknownLocation(); + break; + case 0x5e3cfc4b: + result = new TL_messageActionChatAddUser(); + break; + case 0xf89cf5e8: + result = new TL_messageActionChatJoinedByLink(); + break; + case 0x55555550: + result = new TL_messageActionUserJoined(); + break; + case 0x555555F7: + result = new TL_messageEncryptedAction(); + break; + case 0x55555552: + result = new TL_messageActionTTLChange(); + break; + case 0x55555551: + result = new TL_messageActionUserUpdatedPhoto(); + break; + case 0xb6aef7b0: + result = new TL_messageActionEmpty(); + break; + case 0x95e3fbef: + result = new TL_messageActionChatDeletePhoto(); + break; + case 0xb2ae9b0c: + result = new TL_messageActionChatDeleteUser(); + break; + case 0x7fcb13a8: + result = new TL_messageActionChatEditPhoto(); + break; + case 0xa6638b9a: + result = new TL_messageActionChatCreate(); + break; + case 0x6f038ebc: + result = new TL_messageActionGeoChatCreate(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in MessageAction", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_messageActionGeoChatCheckin extends MessageAction { + public static int constructor = 0xc7d53de; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_messageActionCreatedBroadcastList extends MessageAction { + public static int constructor = 0x55555557; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_messageActionChatEditTitle extends MessageAction { + public static int constructor = 0xb5a1ce5a; public void readParams(AbsSerializedData stream, boolean exception) { - photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + title = stream.readString(exception); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); - photo.serializeToStream(stream); + stream.writeString(title); } } - public static class TL_messageActionChatDeleteUser extends MessageAction { - public static int constructor = 0xb2ae9b0c; + public static class TL_messageActionLoginUnknownLocation extends MessageAction { + public static int constructor = 0x555555F5; + + + public void readParams(AbsSerializedData stream, boolean exception) { + title = stream.readString(exception); + address = stream.readString(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(title); + stream.writeString(address); + } + } + + public static class TL_messageActionChatAddUser extends MessageAction { + public static int constructor = 0x5e3cfc4b; public void readParams(AbsSerializedData stream, boolean exception) { @@ -6225,6 +7375,66 @@ public class TLRPC { } } + public static class TL_messageActionUserJoined extends MessageAction { + public static int constructor = 0x55555550; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_messageEncryptedAction extends MessageAction { + public static int constructor = 0x555555F7; + + + public void readParams(AbsSerializedData stream, boolean exception) { + encryptedAction = DecryptedMessageAction.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + encryptedAction.serializeToStream(stream); + } + } + + public static class TL_messageActionTTLChange extends MessageAction { + public static int constructor = 0x55555552; + + + public void readParams(AbsSerializedData stream, boolean exception) { + ttl = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(ttl); + } + } + + public static class TL_messageActionUserUpdatedPhoto extends MessageAction { + public static int constructor = 0x55555551; + + + public void readParams(AbsSerializedData stream, boolean exception) { + newUserPhoto = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + newUserPhoto.serializeToStream(stream); + } + } + + public static class TL_messageActionEmpty extends MessageAction { + public static int constructor = 0xb6aef7b0; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_messageActionChatDeletePhoto extends MessageAction { public static int constructor = 0x95e3fbef; @@ -6234,8 +7444,8 @@ public class TLRPC { } } - public static class TL_messageActionChatAddUser extends MessageAction { - public static int constructor = 0x5e3cfc4b; + public static class TL_messageActionChatDeleteUser extends MessageAction { + public static int constructor = 0xb2ae9b0c; public void readParams(AbsSerializedData stream, boolean exception) { @@ -6248,6 +7458,20 @@ public class TLRPC { } } + public static class TL_messageActionChatEditPhoto extends MessageAction { + public static int constructor = 0x7fcb13a8; + + + public void readParams(AbsSerializedData stream, boolean exception) { + photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + photo.serializeToStream(stream); + } + } + public static class TL_messageActionChatCreate extends MessageAction { public static int constructor = 0xa6638b9a; @@ -6279,29 +7503,6 @@ public class TLRPC { } } - public static class TL_messageActionEmpty extends MessageAction { - public static int constructor = 0xb6aef7b0; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_messageActionChatEditTitle extends MessageAction { - public static int constructor = 0xb5a1ce5a; - - - public void readParams(AbsSerializedData stream, boolean exception) { - title = stream.readString(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeString(title); - } - } - public static class TL_messageActionGeoChatCreate extends MessageAction { public static int constructor = 0x6f038ebc; @@ -6318,15 +7519,6 @@ public class TLRPC { } } - public static class TL_messageActionGeoChatCheckin extends MessageAction { - public static int constructor = 0xc7d53de; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - public static class DecryptedMessageAction extends TLObject { public int ttl_seconds; public int layer; @@ -6821,17 +8013,21 @@ public class TLRPC { public static class messages_AllStickers extends TLObject { public String hash; public ArrayList packs = new ArrayList<>(); + public ArrayList sets = new ArrayList<>(); public ArrayList documents = new ArrayList<>(); public static messages_AllStickers TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { messages_AllStickers result = null; switch(constructor) { - case 0xdcef3102: + case 0x5ce352ec: result = new TL_messages_allStickers(); break; case 0xe86602c3: result = new TL_messages_allStickersNotModified(); break; + case 0xdcef3102: + result = new TL_messages_allStickers_old(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in messages_AllStickers", constructor)); @@ -6844,6 +8040,92 @@ public class TLRPC { } public static class TL_messages_allStickers extends messages_AllStickers { + public static int constructor = 0x5ce352ec; + + + public void readParams(AbsSerializedData stream, boolean exception) { + hash = stream.readString(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_stickerPack object = TL_stickerPack.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + packs.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_stickerSet object = TL_stickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sets.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Document object = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + documents.add(object); + } + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(hash); + stream.writeInt32(0x1cb5c415); + int count = packs.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + packs.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = sets.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + sets.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = documents.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + documents.get(a).serializeToStream(stream); + } + } + } + + public static class TL_messages_allStickersNotModified extends messages_AllStickers { + public static int constructor = 0xe86602c3; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_messages_allStickers_old extends TL_messages_allStickers { public static int constructor = 0xdcef3102; @@ -6858,7 +8140,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - packs.add(TL_stickerPack.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_stickerPack object = TL_stickerPack.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + packs.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -6869,7 +8155,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - documents.add(Document.TLdeserialize(stream, stream.readInt32(exception), exception)); + Document object = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + documents.add(object); } } @@ -6891,15 +8181,6 @@ public class TLRPC { } } - public static class TL_messages_allStickersNotModified extends messages_AllStickers { - public static int constructor = 0xe86602c3; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - public static class TL_auth_checkedPhone extends TLObject { public static int constructor = 0x811ea28e; @@ -6928,6 +8209,34 @@ public class TLRPC { } } + public static class UserProfilePhoto extends TLObject { + public long photo_id; + public FileLocation photo_small; + public FileLocation photo_big; + + public static UserProfilePhoto TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + UserProfilePhoto result = null; + switch(constructor) { + case 0x4f11bae1: + result = new TL_userProfilePhotoEmpty(); + break; + case 0xd559d8c8: + result = new TL_userProfilePhoto(); + break; + case 0x990d1493: + result = new TL_userProfilePhoto_old(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in UserProfilePhoto", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_userProfilePhotoEmpty extends UserProfilePhoto { public static int constructor = 0x4f11bae1; @@ -6955,6 +8264,22 @@ public class TLRPC { } } + public static class TL_userProfilePhoto_old extends TL_userProfilePhoto { + public static int constructor = 0x990d1493; + + + public void readParams(AbsSerializedData stream, boolean exception) { + photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + photo_small.serializeToStream(stream); + photo_big.serializeToStream(stream); + } + } + public static class TL_authorization extends TLObject { public static int constructor = 0x7bf2e6f6; @@ -7149,7 +8474,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - results.add(TL_chatLocated.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_chatLocated object = TL_chatLocated.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + results.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7160,7 +8489,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - messages.add(GeoChatMessage.TLdeserialize(stream, stream.readInt32(exception), exception)); + GeoChatMessage object = GeoChatMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7171,7 +8504,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7182,7 +8519,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -7300,7 +8641,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - blocked.add(TL_contactBlocked.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_contactBlocked object = TL_contactBlocked.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + blocked.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7311,7 +8656,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -7347,7 +8696,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - blocked.add(TL_contactBlocked.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_contactBlocked object = TL_contactBlocked.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + blocked.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7358,7 +8711,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -7380,8 +8737,8 @@ public class TLRPC { } } - public static class TL_encryptedChatWaiting extends EncryptedChat { - public static int constructor = 0x3bf703dc; + public static class TL_encryptedChatRequested_old extends TL_encryptedChatRequested { + public static int constructor = 0xfda9a7b7; public void readParams(AbsSerializedData stream, boolean exception) { @@ -7390,6 +8747,8 @@ public class TLRPC { date = stream.readInt32(exception); admin_id = stream.readInt32(exception); participant_id = stream.readInt32(exception); + g_a = stream.readByteArray(exception); + nonce = stream.readByteArray(exception); } public void serializeToStream(AbsSerializedData stream) { @@ -7399,34 +8758,32 @@ public class TLRPC { stream.writeInt32(date); stream.writeInt32(admin_id); stream.writeInt32(participant_id); + stream.writeByteArray(g_a); + stream.writeByteArray(nonce); } } - public static class TL_encryptedChatEmpty extends EncryptedChat { - public static int constructor = 0xab7ec0a0; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(id); - } - } - - public static class TL_encryptedChatDiscarded extends EncryptedChat { - public static int constructor = 0x13d6dd27; + public static class TL_encryptedChatRequested extends EncryptedChat { + public static int constructor = 0xc878527e; public void readParams(AbsSerializedData stream, boolean exception) { id = stream.readInt32(exception); + access_hash = stream.readInt64(exception); + date = stream.readInt32(exception); + admin_id = stream.readInt32(exception); + participant_id = stream.readInt32(exception); + g_a = stream.readByteArray(exception); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); stream.writeInt32(id); + stream.writeInt64(access_hash); + stream.writeInt32(date); + stream.writeInt32(admin_id); + stream.writeInt32(participant_id); + stream.writeByteArray(g_a); } } @@ -7456,8 +8813,8 @@ public class TLRPC { } } - public static class TL_encryptedChatRequested extends EncryptedChat { - public static int constructor = 0xc878527e; + public static class TL_encryptedChat_old extends TL_encryptedChat { + public static int constructor = 0x6601d14f; public void readParams(AbsSerializedData stream, boolean exception) { @@ -7466,7 +8823,9 @@ public class TLRPC { date = stream.readInt32(exception); admin_id = stream.readInt32(exception); participant_id = stream.readInt32(exception); - g_a = stream.readByteArray(exception); + g_a_or_b = stream.readByteArray(exception); + nonce = stream.readByteArray(exception); + key_fingerprint = stream.readInt64(exception); } public void serializeToStream(AbsSerializedData stream) { @@ -7476,7 +8835,59 @@ public class TLRPC { stream.writeInt32(date); stream.writeInt32(admin_id); stream.writeInt32(participant_id); - stream.writeByteArray(g_a); + stream.writeByteArray(g_a_or_b); + stream.writeByteArray(nonce); + stream.writeInt64(key_fingerprint); + } + } + + public static class TL_encryptedChatEmpty extends EncryptedChat { + public static int constructor = 0xab7ec0a0; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + } + } + + public static class TL_encryptedChatWaiting extends EncryptedChat { + public static int constructor = 0x3bf703dc; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + access_hash = stream.readInt64(exception); + date = stream.readInt32(exception); + admin_id = stream.readInt32(exception); + participant_id = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeInt64(access_hash); + stream.writeInt32(date); + stream.writeInt32(admin_id); + stream.writeInt32(participant_id); + } + } + + public static class TL_encryptedChatDiscarded extends EncryptedChat { + public static int constructor = 0x13d6dd27; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); } } @@ -7583,7 +8994,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - stickers.add(Document.TLdeserialize(stream, stream.readInt32(exception), exception)); + Document object = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + stickers.add(object); } } @@ -7599,6 +9014,51 @@ public class TLRPC { } } + public static class Video extends TLObject { + public long id; + public long access_hash; + public int user_id; + public int date; + public int duration; + public int size; + public PhotoSize thumb; + public int dc_id; + public int w; + public int h; + public String caption; + public byte[] key; + public byte[] iv; + public String mime_type; + + public static Video TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + Video result = null; + switch(constructor) { + case 0xee9f4a4d: + result = new TL_video(); + break; + case 0x55555553: + result = new TL_videoEncrypted(); + break; + case 0x5a04a49f: + result = new TL_video_old(); + break; + case 0x388fa391: + result = new TL_video_old2(); + break; + case 0xc10658a8: + result = new TL_videoEmpty(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in Video", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_video extends Video { public static int constructor = 0xee9f4a4d; @@ -7631,6 +9091,114 @@ public class TLRPC { } } + public static class TL_videoEncrypted extends TL_video { + public static int constructor = 0x55555553; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + caption = stream.readString(exception); + duration = stream.readInt32(exception); + size = stream.readInt32(exception); + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + w = stream.readInt32(exception); + h = stream.readInt32(exception); + key = stream.readByteArray(exception); + iv = stream.readByteArray(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeString(caption); + stream.writeInt32(duration); + stream.writeInt32(size); + thumb.serializeToStream(stream); + stream.writeInt32(dc_id); + stream.writeInt32(w); + stream.writeInt32(h); + stream.writeByteArray(key); + stream.writeByteArray(iv); + } + } + + public static class TL_video_old extends TL_video { + public static int constructor = 0x5a04a49f; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + caption = stream.readString(exception); + duration = stream.readInt32(exception); + size = stream.readInt32(exception); + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + w = stream.readInt32(exception); + h = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeString(caption); + stream.writeInt32(duration); + stream.writeInt32(size); + thumb.serializeToStream(stream); + stream.writeInt32(dc_id); + stream.writeInt32(w); + stream.writeInt32(h); + } + } + + public static class TL_video_old2 extends TL_video { + public static int constructor = 0x388fa391; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + caption = stream.readString(exception); + duration = stream.readInt32(exception); + mime_type = stream.readString(exception); + size = stream.readInt32(exception); + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + w = stream.readInt32(exception); + h = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeString(caption); + stream.writeInt32(duration); + stream.writeString(mime_type); + stream.writeInt32(size); + thumb.serializeToStream(stream); + stream.writeInt32(dc_id); + stream.writeInt32(w); + stream.writeInt32(h); + } + } + public static class TL_videoEmpty extends Video { public static int constructor = 0xc10658a8; @@ -7717,7 +9285,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - messages.add(GeoChatMessage.TLdeserialize(stream, stream.readInt32(exception), exception)); + GeoChatMessage object = GeoChatMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7728,7 +9300,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7739,7 +9315,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -7781,7 +9361,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - messages.add(GeoChatMessage.TLdeserialize(stream, stream.readInt32(exception), exception)); + GeoChatMessage object = GeoChatMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7792,7 +9376,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -7803,7 +9391,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -7907,6 +9499,73 @@ public class TLRPC { } } + public static class InputStickerSet extends TLObject { + public long id; + public long access_hash; + public String short_name; + + public static InputStickerSet TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + InputStickerSet result = null; + switch(constructor) { + case 0xffb62b95: + result = new TL_inputStickerSetEmpty(); + break; + case 0x9de7a269: + result = new TL_inputStickerSetID(); + break; + case 0x861cc8a0: + result = new TL_inputStickerSetShortName(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in InputStickerSet", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_inputStickerSetEmpty extends InputStickerSet { + public static int constructor = 0xffb62b95; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_inputStickerSetID extends InputStickerSet { + public static int constructor = 0x9de7a269; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + } + } + + public static class TL_inputStickerSetShortName extends InputStickerSet { + public static int constructor = 0x861cc8a0; + + + public void readParams(AbsSerializedData stream, boolean exception) { + short_name = stream.readString(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(short_name); + } + } + public static class storage_FileType extends TLObject { public static storage_FileType TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { @@ -8071,7 +9730,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - authorizations.add(TL_authorization.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_authorization object = TL_authorization.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + authorizations.add(object); } } @@ -8225,7 +9888,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - contacts.add(TL_contact.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_contact object = TL_contact.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + contacts.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8236,7 +9903,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -8307,7 +9978,6 @@ public class TLRPC { public int user_id; public Update update; public int seq_start; - public int qts; public static Updates TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { Updates result = null; @@ -8401,7 +10071,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - updates.add(Update.TLdeserialize(stream, stream.readInt32(exception), exception)); + Update object = Update.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + updates.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8412,7 +10086,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8423,7 +10101,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } date = stream.readInt32(exception); seq = stream.readInt32(exception); @@ -8528,7 +10210,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - updates.add(Update.TLdeserialize(stream, stream.readInt32(exception), exception)); + Update object = Update.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + updates.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8539,7 +10225,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8550,7 +10240,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } date = stream.readInt32(exception); seq_start = stream.readInt32(exception); @@ -8727,7 +10421,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - new_messages.add(Message.TLdeserialize(stream, stream.readInt32(exception), exception)); + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + new_messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8738,7 +10436,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - new_encrypted_messages.add(EncryptedMessage.TLdeserialize(stream, stream.readInt32(exception), exception)); + EncryptedMessage object = EncryptedMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + new_encrypted_messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8749,7 +10451,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - other_updates.add(Update.TLdeserialize(stream, stream.readInt32(exception), exception)); + Update object = Update.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + other_updates.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8760,7 +10466,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8771,7 +10481,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } intermediate_state = TL_updates_state.TLdeserialize(stream, stream.readInt32(exception), exception); } @@ -8826,7 +10540,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - new_messages.add(Message.TLdeserialize(stream, stream.readInt32(exception), exception)); + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + new_messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8837,7 +10555,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - new_encrypted_messages.add(EncryptedMessage.TLdeserialize(stream, stream.readInt32(exception), exception)); + EncryptedMessage object = EncryptedMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + new_encrypted_messages.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8848,7 +10570,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - other_updates.add(Update.TLdeserialize(stream, stream.readInt32(exception), exception)); + Update object = Update.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + other_updates.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8859,7 +10585,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -8870,7 +10600,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } state = TL_updates_state.TLdeserialize(stream, stream.readInt32(exception), exception); } @@ -9000,17 +10734,67 @@ public class TLRPC { } } - public static class TL_audioEmpty extends Audio { - public static int constructor = 0x586988d8; + public static class Audio extends TLObject { + public long id; + public long access_hash; + public int user_id; + public int date; + public int duration; + public int size; + public int dc_id; + public String mime_type; + public byte[] key; + public byte[] iv; + + public static Audio TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + Audio result = null; + switch(constructor) { + case 0x427425e7: + result = new TL_audio_old(); + break; + case 0xc7ac6496: + result = new TL_audio(); + break; + case 0x555555F6: + result = new TL_audioEncrypted(); + break; + case 0x586988d8: + result = new TL_audioEmpty(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in Audio", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_audio_old extends TL_audio { + public static int constructor = 0x427425e7; public void readParams(AbsSerializedData stream, boolean exception) { id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + duration = stream.readInt32(exception); + size = stream.readInt32(exception); + dc_id = stream.readInt32(exception); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeInt32(duration); + stream.writeInt32(size); + stream.writeInt32(dc_id); } } @@ -9042,6 +10826,50 @@ public class TLRPC { } } + public static class TL_audioEncrypted extends TL_audio { + public static int constructor = 0x555555F6; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + duration = stream.readInt32(exception); + size = stream.readInt32(exception); + dc_id = stream.readInt32(exception); + key = stream.readByteArray(exception); + iv = stream.readByteArray(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeInt32(duration); + stream.writeInt32(size); + stream.writeInt32(dc_id); + stream.writeByteArray(key); + stream.writeByteArray(iv); + } + } + + public static class TL_audioEmpty extends Audio { + public static int constructor = 0x586988d8; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + } + } + public static class TL_contacts_found extends TLObject { public static int constructor = 0x566000e; @@ -9071,7 +10899,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - results.add(TL_contactFound.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_contactFound object = TL_contactFound.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + results.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -9082,7 +10914,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -9103,6 +10939,113 @@ public class TLRPC { } } + public static class Document extends TLObject { + public long id; + public long access_hash; + public int user_id; + public int date; + public String file_name; + public String mime_type; + public int size; + public PhotoSize thumb; + public int dc_id; + public byte[] key; + public byte[] iv; + public ArrayList attributes = new ArrayList<>(); + + public static Document TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + Document result = null; + switch(constructor) { + case 0x55555556: + result = new TL_documentEncrypted_old(); + break; + case 0x9efc6326: + result = new TL_document_old(); + break; + case 0x36f8c871: + result = new TL_documentEmpty(); + break; + case 0x55555558: + result = new TL_documentEncrypted(); + break; + case 0xf9a39f4f: + result = new TL_document(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in Document", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_documentEncrypted_old extends TL_document { + public static int constructor = 0x55555556; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + file_name = stream.readString(exception); + mime_type = stream.readString(exception); + size = stream.readInt32(exception); + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + key = stream.readByteArray(exception); + iv = stream.readByteArray(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeString(file_name); + stream.writeString(mime_type); + stream.writeInt32(size); + thumb.serializeToStream(stream); + stream.writeInt32(dc_id); + stream.writeByteArray(key); + stream.writeByteArray(iv); + } + } + + public static class TL_document_old extends TL_document { + public static int constructor = 0x9efc6326; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + file_name = stream.readString(exception); + mime_type = stream.readString(exception); + size = stream.readInt32(exception); + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeString(file_name); + stream.writeString(mime_type); + stream.writeInt32(size); + thumb.serializeToStream(stream); + stream.writeInt32(dc_id); + } + } + public static class TL_documentEmpty extends Document { public static int constructor = 0x36f8c871; @@ -9117,6 +11060,57 @@ public class TLRPC { } } + public static class TL_documentEncrypted extends Document { + public static int constructor = 0x55555558; + + + public void readParams(AbsSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + date = stream.readInt32(exception); + mime_type = stream.readString(exception); + size = stream.readInt32(exception); + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + DocumentAttribute object = DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + attributes.add(object); + } + key = stream.readByteArray(exception); + iv = stream.readByteArray(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(date); + stream.writeString(mime_type); + stream.writeInt32(size); + thumb.serializeToStream(stream); + stream.writeInt32(dc_id); + stream.writeInt32(0x1cb5c415); + int count = attributes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + attributes.get(a).serializeToStream(stream); + } + stream.writeByteArray(key); + stream.writeByteArray(iv); + } + } + public static class TL_document extends Document { public static int constructor = 0xf9a39f4f; @@ -9138,7 +11132,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - attributes.add(DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception)); + DocumentAttribute object = DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + attributes.add(object); } } @@ -9566,7 +11564,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - chats.add(Chat.TLdeserialize(stream, stream.readInt32(exception), exception)); + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } } @@ -9685,6 +11687,65 @@ public class TLRPC { } } + public static class SendMessageAction extends TLObject { + public int progress; + + public static SendMessageAction TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + SendMessageAction result = null; + switch(constructor) { + case 0xd52f73f7: + result = new TL_sendMessageRecordAudioAction(); + break; + case 0x92042ff7: + result = new TL_sendMessageUploadVideoAction_old(); + break; + case 0xe6ac8a6f: + result = new TL_sendMessageUploadAudioAction_old(); + break; + case 0xf351d7ab: + result = new TL_sendMessageUploadAudioAction(); + break; + case 0xd1d34a26: + result = new TL_sendMessageUploadPhotoAction(); + break; + case 0x8faee98e: + result = new TL_sendMessageUploadDocumentAction_old(); + break; + case 0xe9763aec: + result = new TL_sendMessageUploadVideoAction(); + break; + case 0xfd5ec8f5: + result = new TL_sendMessageCancelAction(); + break; + case 0x176f8ba1: + result = new TL_sendMessageGeoLocationAction(); + break; + case 0x628cbc6f: + result = new TL_sendMessageChooseContactAction(); + break; + case 0x16bf744e: + result = new TL_sendMessageTypingAction(); + break; + case 0x990a3c1a: + result = new TL_sendMessageUploadPhotoAction_old(); + break; + case 0xaa0cd9e4: + result = new TL_sendMessageUploadDocumentAction(); + break; + case 0xa187d66f: + result = new TL_sendMessageRecordVideoAction(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in SendMessageAction", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_sendMessageRecordAudioAction extends SendMessageAction { public static int constructor = 0xd52f73f7; @@ -9694,6 +11755,28 @@ public class TLRPC { } } + public static class TL_sendMessageUploadVideoAction_old extends TL_sendMessageUploadVideoAction { + public static int constructor = 0x92042ff7; + + public void readParams(AbsSerializedData stream, boolean exception) { + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_sendMessageUploadAudioAction_old extends TL_sendMessageUploadAudioAction { + public static int constructor = 0xe6ac8a6f; + + public void readParams(AbsSerializedData stream, boolean exception) { + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_sendMessageUploadAudioAction extends SendMessageAction { public static int constructor = 0xf351d7ab; @@ -9722,6 +11805,17 @@ public class TLRPC { } } + public static class TL_sendMessageUploadDocumentAction_old extends TL_sendMessageUploadDocumentAction { + public static int constructor = 0x8faee98e; + + public void readParams(AbsSerializedData stream, boolean exception) { + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_sendMessageUploadVideoAction extends SendMessageAction { public static int constructor = 0xe9763aec; @@ -9772,6 +11866,17 @@ public class TLRPC { } } + public static class TL_sendMessageUploadPhotoAction_old extends TL_sendMessageUploadPhotoAction { + public static int constructor = 0x990a3c1a; + + public void readParams(AbsSerializedData stream, boolean exception) { + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_sendMessageUploadDocumentAction extends SendMessageAction { public static int constructor = 0xaa0cd9e4; @@ -9919,6 +12024,52 @@ public class TLRPC { } } + public static class DocumentAttribute extends TLObject { + public int w; + public int h; + public String file_name; + public String alt; + public InputStickerSet stickerset; + public int duration; + + public static DocumentAttribute TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { + DocumentAttribute result = null; + switch(constructor) { + case 0x11b58939: + result = new TL_documentAttributeAnimated(); + break; + case 0xfb0a5727: + result = new TL_documentAttributeSticker_old(); + break; + case 0x6c37c15c: + result = new TL_documentAttributeImageSize(); + break; + case 0x15590068: + result = new TL_documentAttributeFilename(); + break; + case 0x3a556302: + result = new TL_documentAttributeSticker(); + break; + case 0x5910cccb: + result = new TL_documentAttributeVideo(); + break; + case 0x51448e5: + result = new TL_documentAttributeAudio(); + break; + case 0x994c9882: + result = new TL_documentAttributeSticker_old2(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in DocumentAttribute", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_documentAttributeAnimated extends DocumentAttribute { public static int constructor = 0x11b58939; @@ -9928,6 +12079,17 @@ public class TLRPC { } } + public static class TL_documentAttributeSticker_old extends TL_documentAttributeSticker { + public static int constructor = 0xfb0a5727; + + public void readParams(AbsSerializedData stream, boolean exception) { + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_documentAttributeImageSize extends DocumentAttribute { public static int constructor = 0x6c37c15c; @@ -9958,6 +12120,22 @@ public class TLRPC { } } + public static class TL_documentAttributeSticker extends DocumentAttribute { + public static int constructor = 0x3a556302; + + + public void readParams(AbsSerializedData stream, boolean exception) { + alt = stream.readString(exception); + stickerset = InputStickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(alt); + stickerset.serializeToStream(stream); + } + } + public static class TL_documentAttributeVideo extends DocumentAttribute { public static int constructor = 0x5910cccb; @@ -9976,20 +12154,6 @@ public class TLRPC { } } - public static class TL_documentAttributeSticker extends DocumentAttribute { - public static int constructor = 0x994c9882; - - - public void readParams(AbsSerializedData stream, boolean exception) { - alt = stream.readString(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeString(alt); - } - } - public static class TL_documentAttributeAudio extends DocumentAttribute { public static int constructor = 0x51448e5; @@ -10004,6 +12168,20 @@ public class TLRPC { } } + public static class TL_documentAttributeSticker_old2 extends TL_documentAttributeSticker { + public static int constructor = 0x994c9882; + + + public void readParams(AbsSerializedData stream, boolean exception) { + alt = stream.readString(exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(alt); + } + } + public static class TL_contacts_importedContacts extends TLObject { public static int constructor = 0xad524315; @@ -10034,7 +12212,11 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - imported.add(TL_importedContact.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_importedContact object = TL_importedContact.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + imported.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -10056,7 +12238,11 @@ public class TLRPC { } count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - users.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); } } @@ -10273,7 +12459,11 @@ public class TLRPC { public void readParams(AbsSerializedData stream, boolean exception) { int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - destroy_results.add(DestroySessionRes.TLdeserialize(stream, stream.readInt32(exception), exception)); + DestroySessionRes object = DestroySessionRes.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + destroy_results.add(object); } } @@ -10685,7 +12875,11 @@ public class TLRPC { Vector vector = new Vector(); int size = stream.readInt32(exception); for (int a = 0; a < size; a++) { - vector.objects.add(WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception)); + WallPaper object = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return vector; + } + vector.objects.add(object); } return vector; } @@ -10704,7 +12898,11 @@ public class TLRPC { Vector vector = new Vector(); int size = stream.readInt32(exception); for (int a = 0; a < size; a++) { - vector.objects.add(User.TLdeserialize(stream, stream.readInt32(exception), exception)); + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return vector; + } + vector.objects.add(object); } return vector; } @@ -10743,7 +12941,11 @@ public class TLRPC { Vector vector = new Vector(); int size = stream.readInt32(exception); for (int a = 0; a < size; a++) { - vector.objects.add(TL_contactStatus.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_contactStatus object = TL_contactStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return vector; + } + vector.objects.add(object); } return vector; } @@ -11079,7 +13281,11 @@ public class TLRPC { Vector vector = new Vector(); int size = stream.readInt32(exception); for (int a = 0; a < size; a++) { - vector.objects.add(TL_receivedNotifyMessage.TLdeserialize(stream, stream.readInt32(exception), exception)); + TL_receivedNotifyMessage object = TL_receivedNotifyMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return vector; + } + vector.objects.add(object); } return vector; } @@ -12381,76 +14587,52 @@ public class TLRPC { } } - //manually created + public static class TL_messages_getStickerSet extends TLObject { + public static int constructor = 0x2619a90e; - //Photo start - public static class Photo extends TLObject { - public long id; - public long access_hash; - public int user_id; - public int date; - public GeoPoint geo; - public ArrayList sizes = new ArrayList<>(); - public String caption; //custom + public InputStickerSet stickerset; - public static Photo TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - Photo result = null; - switch(constructor) { - case 0xc3838076: - result = new TL_photo(); - break; - case 0x2331b22d: - result = new TL_photoEmpty(); - break; - case 0x22b56751: - result = new TL_photo_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in Photo", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_photo_old extends TL_photo { - public static int constructor = 0x22b56751; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - user_id = stream.readInt32(exception); - date = stream.readInt32(exception); - caption = stream.readString(exception); - geo = GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); - stream.readInt32(exception); - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - sizes.add(PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception)); - } + public TLObject deserializeResponse(AbsSerializedData stream, int constructor, boolean exception) { + return TL_messages_stickerSet.TLdeserialize(stream, constructor, exception); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(user_id); - stream.writeInt32(date); - stream.writeString(caption); - geo.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = sizes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - sizes.get(a).serializeToStream(stream); - } + stickerset.serializeToStream(stream); } } - //Photo end + + public static class TL_messages_installStickerSet extends TLObject { + public static int constructor = 0xefbbfae9; + + public InputStickerSet stickerset; + + public TLObject deserializeResponse(AbsSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stickerset.serializeToStream(stream); + } + } + + public static class TL_messages_uninstallStickerSet extends TLObject { + public static int constructor = 0xf96e55de; + + public InputStickerSet stickerset; + + public TLObject deserializeResponse(AbsSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stickerset.serializeToStream(stream); + } + } + + //manually created //EncryptedChat start public static class EncryptedChat extends TLObject { @@ -12459,9 +14641,10 @@ public class TLRPC { public int date; public int admin_id; public int participant_id; + public byte[] g_a; + public byte[] nonce; public byte[] g_a_or_b; public long key_fingerprint; - public byte[] g_a; public byte[] a_or_b; //custom public byte[] auth_key; //custom public int user_id; //custom @@ -12480,26 +14663,26 @@ public class TLRPC { public static EncryptedChat TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { EncryptedChat result = null; switch(constructor) { - case 0x3bf703dc: - result = new TL_encryptedChatWaiting(); - break; - case 0xab7ec0a0: - result = new TL_encryptedChatEmpty(); - break; - case 0x13d6dd27: - result = new TL_encryptedChatDiscarded(); - break; - case 0xfa56ce36: - result = new TL_encryptedChat(); + case 0xfda9a7b7: + result = new TL_encryptedChatRequested_old(); break; case 0xc878527e: result = new TL_encryptedChatRequested(); break; - case 0x6601d14f: - result = new TL_encryptedChat_old(); //custom + case 0xfa56ce36: + result = new TL_encryptedChat(); break; - case 0xfda9a7b7: - result = new TL_encryptedChatRequested_old(); //custom + case 0x6601d14f: + result = new TL_encryptedChat_old(); + break; + case 0xab7ec0a0: + result = new TL_encryptedChatEmpty(); + break; + case 0x3bf703dc: + result = new TL_encryptedChatWaiting(); + break; + case 0x13d6dd27: + result = new TL_encryptedChatDiscarded(); break; } if (result == null && exception) { @@ -12511,58 +14694,6 @@ public class TLRPC { return result; } } - - public static class TL_encryptedChat_old extends TL_encryptedChat { - public static int constructor = 0x6601d14f; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - access_hash = stream.readInt64(exception); - date = stream.readInt32(exception); - admin_id = stream.readInt32(exception); - participant_id = stream.readInt32(exception); - g_a_or_b = stream.readByteArray(exception); - stream.readByteArray(exception); - key_fingerprint = stream.readInt64(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(TL_encryptedChat.constructor); - stream.writeInt32(id); - stream.writeInt64(access_hash); - stream.writeInt32(date); - stream.writeInt32(admin_id); - stream.writeInt32(participant_id); - stream.writeByteArray(g_a_or_b); - stream.writeInt64(key_fingerprint); - } - } - - public static class TL_encryptedChatRequested_old extends EncryptedChat { - public static int constructor = 0xfda9a7b7; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - access_hash = stream.readInt64(exception); - date = stream.readInt32(exception); - admin_id = stream.readInt32(exception); - participant_id = stream.readInt32(exception); - g_a = stream.readByteArray(exception); - stream.readByteArray(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(TL_encryptedChatRequested.constructor); - stream.writeInt32(id); - stream.writeInt64(access_hash); - stream.writeInt32(date); - stream.writeInt32(admin_id); - stream.writeInt32(participant_id); - stream.writeByteArray(g_a); - } - } //EncryptedChat end //Message start @@ -12590,7 +14721,6 @@ public class TLRPC { public int seq_in; //custom public int seq_out; //custom public TLRPC.Message replyMessage; //custom - public VideoEditedInfo videoEditedInfo = null; //custom public static Message TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { Message result = null; @@ -12654,10 +14784,6 @@ public class TLRPC { if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) { attachPath = stream.readString(exception); } - if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) { - videoEditedInfo = new VideoEditedInfo(); - videoEditedInfo.parseString(message); - } } public void serializeToStream(AbsSerializedData stream) { @@ -12701,10 +14827,6 @@ public class TLRPC { if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) { attachPath = stream.readString(exception); } - if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) { - videoEditedInfo = new VideoEditedInfo(); - videoEditedInfo.parseString(message); - } if ((flags & MESSAGE_FLAG_FWD) != 0 && id < 0) { fwd_msg_id = stream.readInt32(exception); } @@ -12750,10 +14872,6 @@ public class TLRPC { if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) { attachPath = stream.readString(exception); } - if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) { - videoEditedInfo = new VideoEditedInfo(); - videoEditedInfo.parseString(message); - } } public void serializeToStream(AbsSerializedData stream) { @@ -12817,10 +14935,6 @@ public class TLRPC { if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) { attachPath = stream.readString(exception); } - if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) { - videoEditedInfo = new VideoEditedInfo(); - videoEditedInfo.parseString(message); - } } public void serializeToStream(AbsSerializedData stream) { @@ -12857,10 +14971,6 @@ public class TLRPC { if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) { attachPath = stream.readString(exception); } - if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) { - videoEditedInfo = new VideoEditedInfo(); - videoEditedInfo.parseString(message); - } } public void serializeToStream(AbsSerializedData stream) { @@ -12892,10 +15002,6 @@ public class TLRPC { if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) { attachPath = stream.readString(exception); } - if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) { - videoEditedInfo = new VideoEditedInfo(); - videoEditedInfo.parseString(message); - } } public void serializeToStream(AbsSerializedData stream) { @@ -12913,246 +15019,6 @@ public class TLRPC { } //Message end - //MessageAction start - public static class MessageAction extends TLObject { - public Photo photo; - public int user_id; - public int inviter_id; - public String title; - public ArrayList users = new ArrayList<>(); - public String address; - public int ttl; - public DecryptedMessageAction encryptedAction; - public UserProfilePhoto newUserPhoto; - - public static MessageAction TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - MessageAction result = null; - switch(constructor) { - case 0x7fcb13a8: - result = new TL_messageActionChatEditPhoto(); - break; - case 0xb2ae9b0c: - result = new TL_messageActionChatDeleteUser(); - break; - case 0xf89cf5e8: - result = new TL_messageActionChatJoinedByLink(); - break; - case 0x95e3fbef: - result = new TL_messageActionChatDeletePhoto(); - break; - case 0x5e3cfc4b: - result = new TL_messageActionChatAddUser(); - break; - case 0xa6638b9a: - result = new TL_messageActionChatCreate(); - break; - case 0xb6aef7b0: - result = new TL_messageActionEmpty(); - break; - case 0xb5a1ce5a: - result = new TL_messageActionChatEditTitle(); - break; - case 0x6f038ebc: - result = new TL_messageActionGeoChatCreate(); - break; - case 0xc7d53de: - result = new TL_messageActionGeoChatCheckin(); - break; - case 0x55555552: - result = new TL_messageActionTTLChange(); //custom - break; - case 0x55555557: - result = new TL_messageActionCreatedBroadcastList(); //custom - break; - case 0x55555551: - result = new TL_messageActionUserUpdatedPhoto(); //custom - break; - case 0x55555550: - result = new TL_messageActionUserJoined(); //custom - break; - case 0x555555F5: - result = new TL_messageActionLoginUnknownLocation(); //custom - break; - case 0x555555F7: - result = new TL_messageEncryptedAction(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in MessageAction", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_messageActionTTLChange extends MessageAction { - public static int constructor = 0x55555552; - - public void readParams(AbsSerializedData stream, boolean exception) { - ttl = stream.readInt32(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(ttl); - } - } - - public static class TL_messageActionCreatedBroadcastList extends MessageAction { - public static int constructor = 0x55555557; - - public void readParams(AbsSerializedData stream, boolean exception) { - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_messageActionUserUpdatedPhoto extends MessageAction { - public static int constructor = 0x55555551; - - public void readParams(AbsSerializedData stream, boolean exception) { - newUserPhoto = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - newUserPhoto.serializeToStream(stream); - } - } - - public static class TL_messageActionUserJoined extends MessageAction { - public static int constructor = 0x55555550; - - public void readParams(AbsSerializedData stream, boolean exception) { - - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_messageActionLoginUnknownLocation extends MessageAction { - public static int constructor = 0x555555F5; - - public void readParams(AbsSerializedData stream, boolean exception) { - title = stream.readString(exception); - address = stream.readString(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeString(title); - stream.writeString(address); - } - } - - public static class TL_messageEncryptedAction extends MessageAction { - public static int constructor = 0x555555F7; - - public void readParams(AbsSerializedData stream, boolean exception) { - encryptedAction = DecryptedMessageAction.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - encryptedAction.serializeToStream(stream); - } - } - //MessageAction end - - //InputEncryptedFile start - public static class InputEncryptedFile extends TLObject { - public long id; - public long access_hash; - public int parts; - public int key_fingerprint; - public String md5_checksum; - public byte[] key; //custom - public byte[] iv; //custom - - public static InputEncryptedFile TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - InputEncryptedFile result = null; - switch(constructor) { - case 0x5a17b5e5: - result = new TL_inputEncryptedFile(); - break; - case 0x2dc173c8: - result = new TL_inputEncryptedFileBigUploaded(); - break; - case 0x1837c364: - result = new TL_inputEncryptedFileEmpty(); - break; - case 0x64bd0306: - result = new TL_inputEncryptedFileUploaded(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in InputEncryptedFile", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - //InputEncryptedFile end - - //UserStatus start - public static class UserStatus extends TLObject { - public int expires; - - public static UserStatus TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - UserStatus result = null; - switch(constructor) { - case 0x8c703f: - result = new TL_userStatusOffline(); - break; - case 0x7bf09fc: - result = new TL_userStatusLastWeek(); - break; - case 0x9d05049: - result = new TL_userStatusEmpty(); - break; - case 0x77ebc742: - result = new TL_userStatusLastMonth(); - break; - case 0xedb93949: - result = new TL_userStatusOnline(); - break; - case 0xe26f42f1: - result = new TL_userStatusRecently(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in UserStatus", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_userStatusOffline extends UserStatus { - public static int constructor = 0x8c703f; - - - public void readParams(AbsSerializedData stream, boolean exception) { - expires = stream.readInt32(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(expires); - } - } - //UserStatus end - //TL_dialog start public static class TL_dialog extends TLObject { public static int constructor = 0xc1dd804a; @@ -13199,66 +15065,6 @@ public class TLRPC { //TL_dialog end //User start - public static class User extends TLObject { - public int id; - public String first_name; - public String last_name; - public String username; - public long access_hash; - public String phone; - public UserProfilePhoto photo; - public UserStatus status; - - public static User TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - User result = null; - switch(constructor) { - case 0xcab35e18: - result = new TL_userContact(); - break; - case 0xd9ccc4ef: - result = new TL_userRequest(); - break; - case 0x75cf7a8: - result = new TL_userForeign(); - break; - case 0xd6016d7a: - result = new TL_userDeleted(); - break; - case 0x1c60e608: - result = new TL_userSelf(); - break; - case 0x200250ba: - result = new TL_userEmpty(); - break; - case 0xb29ad7cc: - result = new TL_userDeleted_old(); //custom - break; - case 0x5214c89d: - result = new TL_userForeign_old(); //custom - break; - case 0x22e8ceb0: - result = new TL_userRequest_old(); //custom - break; - case 0xf2fb8319: - result = new TL_userContact_old(); //custom - break; - case 0x7007b451: - result = new TL_userSelf_old2(); //custom - break; - case 0x720535ec: - result = new TL_userSelf_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in User", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - public static class TL_userEmpty extends User { public static int constructor = 0x200250ba; @@ -13277,971 +15083,8 @@ public class TLRPC { stream.writeInt32(id); } } - - public static class TL_userDeleted_old extends TL_userDeleted { - public static int constructor = 0xb29ad7cc; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - first_name = stream.readString(exception); - last_name = stream.readString(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(id); - stream.writeString(first_name); - stream.writeString(last_name); - } - } - - public static class TL_userForeign_old extends TL_userForeign { - public static int constructor = 0x5214c89d; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - first_name = stream.readString(exception); - last_name = stream.readString(exception); - access_hash = stream.readInt64(exception); - photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(id); - stream.writeString(first_name); - stream.writeString(last_name); - stream.writeInt64(access_hash); - photo.serializeToStream(stream); - status.serializeToStream(stream); - } - } - - public static class TL_userRequest_old extends TL_userRequest { - public static int constructor = 0x22e8ceb0; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - first_name = stream.readString(exception); - last_name = stream.readString(exception); - access_hash = stream.readInt64(exception); - phone = stream.readString(exception); - photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(id); - stream.writeString(first_name); - stream.writeString(last_name); - stream.writeInt64(access_hash); - stream.writeString(phone); - photo.serializeToStream(stream); - status.serializeToStream(stream); - } - } - - public static class TL_userContact_old extends TL_userContact { - public static int constructor = 0xf2fb8319; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - first_name = stream.readString(exception); - last_name = stream.readString(exception); - access_hash = stream.readInt64(exception); - phone = stream.readString(exception); - photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(id); - stream.writeString(first_name); - stream.writeString(last_name); - stream.writeInt64(access_hash); - stream.writeString(phone); - photo.serializeToStream(stream); - status.serializeToStream(stream); - } - } - - public static class TL_userSelf_old2 extends TL_userSelf { - public static int constructor = 0x7007b451; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - first_name = stream.readString(exception); - last_name = stream.readString(exception); - username = stream.readString(exception); - phone = stream.readString(exception); - photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); - stream.readBool(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(id); - stream.writeString(first_name); - stream.writeString(last_name); - stream.writeString(username); - stream.writeString(phone); - photo.serializeToStream(stream); - status.serializeToStream(stream); - stream.writeBool(false); - } - } - - public static class TL_userSelf_old extends TL_userSelf { - public static int constructor = 0x720535ec; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - first_name = stream.readString(exception); - last_name = stream.readString(exception); - phone = stream.readString(exception); - photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); - stream.readBool(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(id); - stream.writeString(first_name); - stream.writeString(last_name); - stream.writeString(phone); - photo.serializeToStream(stream); - status.serializeToStream(stream); - stream.writeBool(false); - } - } //User end - //Video start - public static class Video extends TLObject { - public long id; - public long access_hash; - public int user_id; - public int date; - public int duration; - public int size; - public PhotoSize thumb; - public int dc_id; - public int w; - public int h; - public String caption; - public String mime_type; - public byte[] key; //custom - public byte[] iv; //custom - public VideoEditedInfo videoEditedInfo = null; //custom - - public static Video TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - Video result = null; - switch(constructor) { - case 0xee9f4a4d: - result = new TL_video(); - break; - case 0xc10658a8: - result = new TL_videoEmpty(); - break; - case 0x5a04a49f: - result = new TL_video_old(); //custom - break; - case 0x55555553: - result = new TL_videoEncrypted(); //custom - break; - case 0x388fa391: - result = new TL_video_old2(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in Video", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_video_old extends TL_video { - public static int constructor = 0x5a04a49f; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - user_id = stream.readInt32(exception); - date = stream.readInt32(exception); - caption = stream.readString(exception); - duration = stream.readInt32(exception); - size = stream.readInt32(exception); - thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - dc_id = stream.readInt32(exception); - w = stream.readInt32(exception); - h = stream.readInt32(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(user_id); - stream.writeInt32(date); - stream.writeString(caption); - stream.writeInt32(duration); - stream.writeInt32(size); - thumb.serializeToStream(stream); - stream.writeInt32(dc_id); - stream.writeInt32(w); - stream.writeInt32(h); - } - } - - public static class TL_video_old2 extends TL_video { - public static int constructor = 0x388fa391; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - user_id = stream.readInt32(exception); - date = stream.readInt32(exception); - caption = stream.readString(exception); - duration = stream.readInt32(exception); - mime_type = stream.readString(exception); - size = stream.readInt32(exception); - thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - dc_id = stream.readInt32(exception); - w = stream.readInt32(exception); - h = stream.readInt32(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(user_id); - stream.writeInt32(date); - stream.writeString(caption); - stream.writeInt32(duration); - stream.writeString(mime_type); - stream.writeInt32(size); - thumb.serializeToStream(stream); - stream.writeInt32(dc_id); - stream.writeInt32(w); - stream.writeInt32(h); - } - } - - public static class TL_videoEncrypted extends TL_video { - public static int constructor = 0x55555553; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - user_id = stream.readInt32(exception); - date = stream.readInt32(exception); - caption = stream.readString(exception); - duration = stream.readInt32(exception); - size = stream.readInt32(exception); - thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - dc_id = stream.readInt32(exception); - w = stream.readInt32(exception); - h = stream.readInt32(exception); - key = stream.readByteArray(exception); - iv = stream.readByteArray(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(user_id); - stream.writeInt32(date); - stream.writeString(caption); - stream.writeInt32(duration); - stream.writeInt32(size); - thumb.serializeToStream(stream); - stream.writeInt32(dc_id); - stream.writeInt32(w); - stream.writeInt32(h); - stream.writeByteArray(key); - stream.writeByteArray(iv); - } - } - - public static class VideoEditedInfo { - public long startTime; - public long endTime; - public int rotationValue; - public int originalWidth; - public int originalHeight; - public int resultWidth; - public int resultHeight; - public int bitrate; - public String originalPath; - - public String getString() { - return String.format(Locale.US, "-1_%d_%d_%d_%d_%d_%d_%d_%d_%s", startTime, endTime, rotationValue, originalWidth, originalHeight, bitrate, resultWidth, resultHeight, originalPath); - } - - public void parseString(String string) { - if (string.length() < 6) { - return; - } - String args[] = string.split("_"); - if (args.length >= 10) { - startTime = Long.parseLong(args[1]); - endTime = Long.parseLong(args[2]); - rotationValue = Integer.parseInt(args[3]); - originalWidth = Integer.parseInt(args[4]); - originalHeight = Integer.parseInt(args[5]); - bitrate = Integer.parseInt(args[6]); - resultWidth = Integer.parseInt(args[7]); - resultHeight = Integer.parseInt(args[8]); - for (int a = 9; a < args.length; a++) { - if (originalPath == null) { - originalPath = args[a]; - } else { - originalPath += "_" + args[a]; - } - } - } - } - } - //Video end - - //Document start - public static class Document extends TLObject { - public long id; - public long access_hash; - public int date; - public String mime_type; - public int size; - public PhotoSize thumb; - public int dc_id; - public ArrayList attributes = new ArrayList<>(); - public byte[] key; //custom - public byte[] iv; //custom - - public static Document TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - Document result = null; - switch(constructor) { - case 0x36f8c871: - result = new TL_documentEmpty(); - break; - case 0xf9a39f4f: - result = new TL_document(); - break; - case 0x55555558: - result = new TL_documentEncrypted(); //custom - break; - case 0x55555556: - result = new TL_documentEncrypted_old(); //custom - break; - case 0x9efc6326: - result = new TL_document_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in Document", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_documentEncrypted extends TL_document { - public static int constructor = 0x55555558; - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - date = stream.readInt32(exception); - mime_type = stream.readString(exception); - size = stream.readInt32(exception); - thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - dc_id = stream.readInt32(exception); - stream.readInt32(exception); - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - attributes.add(DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception)); - } - key = stream.readByteArray(exception); - iv = stream.readByteArray(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(date); - stream.writeString(mime_type); - stream.writeInt32(size); - thumb.serializeToStream(stream); - stream.writeInt32(dc_id); - stream.writeInt32(0x1cb5c415); - int count = attributes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - attributes.get(a).serializeToStream(stream); - } - stream.writeByteArray(key); - stream.writeByteArray(iv); - } - } - - public static class TL_documentEncrypted_old extends TL_document { - public static int constructor = 0x55555556; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - stream.readInt32(exception); - date = stream.readInt32(exception); - TL_documentAttributeFilename fileName = new TL_documentAttributeFilename(); - fileName.file_name = stream.readString(exception); - attributes.add(fileName); - mime_type = stream.readString(exception); - size = stream.readInt32(exception); - thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - dc_id = stream.readInt32(exception); - key = stream.readByteArray(exception); - iv = stream.readByteArray(exception); - } - } - - public static class TL_document_old extends TL_document { - public static int constructor = 0x9efc6326; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - stream.readInt32(exception); - date = stream.readInt32(exception); - TL_documentAttributeFilename fileName = new TL_documentAttributeFilename(); - fileName.file_name = stream.readString(exception); - attributes.add(fileName); - mime_type = stream.readString(exception); - size = stream.readInt32(exception); - thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - dc_id = stream.readInt32(exception); - } - } - //Document end - - //Audio start - public static class Audio extends TLObject { - public long id; - public long access_hash; - public int user_id; - public int date; - public int duration; - public String mime_type; - public int size; - public int dc_id; - public byte[] key; - public byte[] iv; - - public static Audio TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - Audio result = null; - switch(constructor) { - case 0x586988d8: - result = new TL_audioEmpty(); - break; - case 0xc7ac6496: - result = new TL_audio(); - break; - case 0x555555F6: - result = new TL_audioEncrypted(); //custom - break; - case 0x427425e7: - result = new TL_audio_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in Audio", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_audioEncrypted extends TL_audio { - public static int constructor = 0x555555F6; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - user_id = stream.readInt32(exception); - date = stream.readInt32(exception); - duration = stream.readInt32(exception); - size = stream.readInt32(exception); - dc_id = stream.readInt32(exception); - key = stream.readByteArray(exception); - iv = stream.readByteArray(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(user_id); - stream.writeInt32(date); - stream.writeInt32(duration); - stream.writeInt32(size); - stream.writeInt32(dc_id); - stream.writeByteArray(key); - stream.writeByteArray(iv); - } - } - - public static class TL_audio_old extends TL_audio { - public static int constructor = 0x427425e7; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - user_id = stream.readInt32(exception); - date = stream.readInt32(exception); - duration = stream.readInt32(exception); - size = stream.readInt32(exception); - dc_id = stream.readInt32(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(user_id); - stream.writeInt32(date); - stream.writeInt32(duration); - stream.writeInt32(size); - stream.writeInt32(dc_id); - } - } - //Audio end - - //SendMessageAction start - public static class SendMessageAction extends TLObject { - public int progress; - - public static SendMessageAction TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - SendMessageAction result = null; - switch(constructor) { - case 0xd52f73f7: - result = new TL_sendMessageRecordAudioAction(); - break; - case 0xf351d7ab: - result = new TL_sendMessageUploadAudioAction(); - break; - case 0xd1d34a26: - result = new TL_sendMessageUploadPhotoAction(); - break; - case 0xe9763aec: - result = new TL_sendMessageUploadVideoAction(); - break; - case 0xfd5ec8f5: - result = new TL_sendMessageCancelAction(); - break; - case 0x176f8ba1: - result = new TL_sendMessageGeoLocationAction(); - break; - case 0x628cbc6f: - result = new TL_sendMessageChooseContactAction(); - break; - case 0x16bf744e: - result = new TL_sendMessageTypingAction(); - break; - case 0xaa0cd9e4: - result = new TL_sendMessageUploadDocumentAction(); - break; - case 0xa187d66f: - result = new TL_sendMessageRecordVideoAction(); - break; - case 0x92042ff7: - result = new TL_sendMessageUploadVideoAction_old(); //custom - break; - case 0xe6ac8a6f: - result = new TL_sendMessageUploadAudioAction_old(); //custom - break; - case 0x990a3c1a: - result = new TL_sendMessageUploadPhotoAction_old(); //custom - break; - case 0x8faee98e: - result = new TL_sendMessageUploadDocumentAction_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in SendMessageAction", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_sendMessageUploadDocumentAction_old extends TL_sendMessageUploadDocumentAction { - public static int constructor = 0x8faee98e; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_sendMessageUploadVideoAction_old extends TL_sendMessageUploadVideoAction { - public static int constructor = 0x92042ff7; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_sendMessageUploadPhotoAction_old extends TL_sendMessageUploadPhotoAction { - public static int constructor = 0x990a3c1a; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_sendMessageUploadAudioAction_old extends TL_sendMessageUploadAudioAction { - public static int constructor = 0xe6ac8a6f; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - //SendMessageAction end - - //FileLocation start - public static class FileLocation extends TLObject { - public int dc_id; - public long volume_id; - public int local_id; - public long secret; - public String ext; //custom - public byte[] key; //custom - public byte[] iv; //custom - - public static FileLocation TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - FileLocation result = null; - switch(constructor) { - case 0x53d69076: - result = new TL_fileLocation(); - break; - case 0x7c596b46: - result = new TL_fileLocationUnavailable(); - break; - case 0x55555554: - result = new TL_fileEncryptedLocation(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in FileLocation", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_fileEncryptedLocation extends FileLocation { - public static int constructor = 0x55555554; - - - public void readParams(AbsSerializedData stream, boolean exception) { - dc_id = stream.readInt32(exception); - volume_id = stream.readInt64(exception); - local_id = stream.readInt32(exception); - secret = stream.readInt64(exception); - key = stream.readByteArray(exception); - iv = stream.readByteArray(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(dc_id); - stream.writeInt64(volume_id); - stream.writeInt32(local_id); - stream.writeInt64(secret); - stream.writeByteArray(key); - stream.writeByteArray(iv); - } - } - //FileLocation end - - //DocumentAttribute start - public static class DocumentAttribute extends TLObject { - public int w; - public int h; - public String file_name; - public int duration; - public String alt; - - public static DocumentAttribute TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - DocumentAttribute result = null; - switch(constructor) { - case 0x11b58939: - result = new TL_documentAttributeAnimated(); - break; - case 0x6c37c15c: - result = new TL_documentAttributeImageSize(); - break; - case 0x15590068: - result = new TL_documentAttributeFilename(); - break; - case 0x5910cccb: - result = new TL_documentAttributeVideo(); - break; - case 0x994c9882: - result = new TL_documentAttributeSticker(); - break; - case 0x51448e5: - result = new TL_documentAttributeAudio(); - break; - case 0xfb0a5727: - result = new TL_documentAttributeSticker_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in DocumentAttribute", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_documentAttributeSticker_old extends TL_documentAttributeSticker { - public static int constructor = 0xfb0a5727; - - public void readParams(AbsSerializedData stream, boolean exception) { - - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - //DocumentAttribute end - - //MessageMedia start - public static class MessageMedia extends TLObject { - public Video video; - public String caption; - public Photo photo; - public WebPage webpage; - public Document document; - public GeoPoint geo; - public Audio audio; - public String title; - public String address; - public String provider; - public String venue_id; - public String phone_number; - public String first_name; - public String last_name; - public int user_id; - public byte[] bytes; //custom - - public static MessageMedia TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - MessageMedia result = null; - switch(constructor) { - case 0x5bcf1675: - result = new TL_messageMediaVideo(); - break; - case 0x3d8ce53d: - result = new TL_messageMediaPhoto(); - break; - case 0xa32dd600: - result = new TL_messageMediaWebPage(); - break; - case 0x2fda2204: - result = new TL_messageMediaDocument(); - break; - case 0x56e0d474: - result = new TL_messageMediaGeo(); - break; - case 0x3ded6320: - result = new TL_messageMediaEmpty(); - break; - case 0xc6b68300: - result = new TL_messageMediaAudio(); - break; - case 0x7912b71f: - result = new TL_messageMediaVenue(); - break; - case 0x5e7d2f39: - result = new TL_messageMediaContact(); - break; - case 0x9f84f49e: - result = new TL_messageMediaUnsupported(); - break; - case 0xa2d24290: - result = new TL_messageMediaVideo_old(); //custom - break; - case 0xc8c45a2a: - result = new TL_messageMediaPhoto_old(); //custom - break; - case 0x29632a36: - result = new TL_messageMediaUnsupported_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in MessageMedia", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_messageMediaUnsupported_old extends TL_messageMediaUnsupported { - public static int constructor = 0x29632a36; - - - public void readParams(AbsSerializedData stream, boolean exception) { - bytes = stream.readByteArray(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeByteArray(bytes); - } - } - - public static class TL_messageMediaPhoto_old extends TL_messageMediaPhoto { - public static int constructor = 0xc8c45a2a; - - - public void readParams(AbsSerializedData stream, boolean exception) { - photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - photo.serializeToStream(stream); - } - } - - public static class TL_messageMediaVideo_old extends TL_messageMediaVideo { - public static int constructor = 0xa2d24290; - - - public void readParams(AbsSerializedData stream, boolean exception) { - video = Video.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - video.serializeToStream(stream); - } - } - //MessageMedia end - - //DecryptedMessage start - public static class DecryptedMessage extends TLObject { - public long random_id; - public DecryptedMessageAction action; - public int ttl; - public String message; - public DecryptedMessageMedia media; - public byte[] random_bytes; //custom - - public static DecryptedMessage TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - DecryptedMessage result = null; - switch(constructor) { - case 0x73164160: - result = new TL_decryptedMessageService(); - break; - case 0x204d3878: - result = new TL_decryptedMessage(); - break; - case 0xaa48327d: - result = new TL_decryptedMessageService_old(); //custom - break; - case 0x1f814f1f: - result = new TL_decryptedMessage_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in DecryptedMessage", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_decryptedMessageService_old extends TL_decryptedMessageService { - public static int constructor = 0xaa48327d; - - - public void readParams(AbsSerializedData stream, boolean exception) { - random_id = stream.readInt64(exception); - random_bytes = stream.readByteArray(exception); - action = DecryptedMessageAction.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(random_id); - stream.writeByteArray(random_bytes); - action.serializeToStream(stream); - } - } - - public static class TL_decryptedMessage_old extends TL_decryptedMessage { - public static int constructor = 0x1f814f1f; - - - public void readParams(AbsSerializedData stream, boolean exception) { - random_id = stream.readInt64(exception); - random_bytes = stream.readByteArray(exception); - message = stream.readString(exception); - media = DecryptedMessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(random_id); - stream.writeByteArray(random_bytes); - stream.writeString(message); - media.serializeToStream(stream); - } - } - //DecryptedMessage end - //Chat start public static class TL_chatEmpty extends Chat { public static int constructor = 0x9ba2d800; @@ -14260,216 +15103,6 @@ public class TLRPC { } //Chat end - //UserProfilePhoto start - public static class UserProfilePhoto extends TLObject { - public long photo_id; - public FileLocation photo_small; - public FileLocation photo_big; - - public static UserProfilePhoto TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - UserProfilePhoto result = null; - switch(constructor) { - case 0x4f11bae1: - result = new TL_userProfilePhotoEmpty(); - break; - case 0xd559d8c8: - result = new TL_userProfilePhoto(); - break; - case 0x990d1493: - result = new TL_userProfilePhotoOld(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in UserProfilePhoto", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_userProfilePhotoOld extends UserProfilePhoto { - public static int constructor = 0x990d1493; - - - public void readParams(AbsSerializedData stream, boolean exception) { - photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - photo_small.serializeToStream(stream); - photo_big.serializeToStream(stream); - } - } - //UserProfilePhoto end - - //DecryptedMessageMedia start - public static class DecryptedMessageMedia extends TLObject { - public long id; - public long access_hash; - public int date; - public String mime_type; - public int size; - public int dc_id; - public ArrayList attributes = new ArrayList<>(); - public int thumb_w; - public int thumb_h; - public String file_name; - public byte[] key; - public byte[] iv; - public double lat; - public double _long; - public int duration; - public int w; - public int h; - public String phone_number; - public String first_name; - public String last_name; - public int user_id; - public byte[] thumb; //custom - public PhotoSize thumbImage; //custom - - public static DecryptedMessageMedia TLdeserialize(AbsSerializedData stream, int constructor, boolean exception) { - DecryptedMessageMedia result = null; - switch(constructor) { - case 0xfa95b0dd: - result = new TL_decryptedMessageMediaExternalDocument(); - break; - case 0xb095434b: - result = new TL_decryptedMessageMediaDocument(); - break; - case 0x35480a59: - result = new TL_decryptedMessageMediaGeoPoint(); - break; - case 0x57e0a9cb: - result = new TL_decryptedMessageMediaAudio(); - break; - case 0x524a415d: - result = new TL_decryptedMessageMediaVideo(); - break; - case 0x588a0a97: - result = new TL_decryptedMessageMediaContact(); - break; - case 0x89f5c4a: - result = new TL_decryptedMessageMediaEmpty(); - break; - case 0x32798a8c: - result = new TL_decryptedMessageMediaPhoto(); - break; - case 0x4cee6ef3: - result = new TL_decryptedMessageMediaVideo_old(); //custom - break; - case 0x6080758f: - result = new TL_decryptedMessageMediaAudio_old(); //custom - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in DecryptedMessageMedia", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_decryptedMessageMediaExternalDocument extends DecryptedMessageMedia { - public static int constructor = 0xfa95b0dd; - - - public void readParams(AbsSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - date = stream.readInt32(exception); - mime_type = stream.readString(exception); - size = stream.readInt32(exception); - thumbImage = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - dc_id = stream.readInt32(exception); - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - attributes.add(DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception)); - } - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(date); - stream.writeString(mime_type); - stream.writeInt32(size); - thumbImage.serializeToStream(stream); - stream.writeInt32(dc_id); - stream.writeInt32(0x1cb5c415); - int count = attributes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - attributes.get(a).serializeToStream(stream); - } - } - } - - public static class TL_decryptedMessageMediaVideo_old extends TL_decryptedMessageMediaVideo { - public static int constructor = 0x4cee6ef3; - - - public void readParams(AbsSerializedData stream, boolean exception) { - thumb = stream.readByteArray(exception); - thumb_w = stream.readInt32(exception); - thumb_h = stream.readInt32(exception); - duration = stream.readInt32(exception); - w = stream.readInt32(exception); - h = stream.readInt32(exception); - size = stream.readInt32(exception); - key = stream.readByteArray(exception); - iv = stream.readByteArray(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeByteArray(thumb); - stream.writeInt32(thumb_w); - stream.writeInt32(thumb_h); - stream.writeInt32(duration); - stream.writeInt32(w); - stream.writeInt32(h); - stream.writeInt32(size); - stream.writeByteArray(key); - stream.writeByteArray(iv); - } - } - - public static class TL_decryptedMessageMediaAudio_old extends TL_decryptedMessageMediaAudio { - public static int constructor = 0x6080758f; - - - public void readParams(AbsSerializedData stream, boolean exception) { - duration = stream.readInt32(exception); - size = stream.readInt32(exception); - key = stream.readByteArray(exception); - iv = stream.readByteArray(exception); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(duration); - stream.writeInt32(size); - stream.writeByteArray(key); - stream.writeByteArray(iv); - } - } - //DecryptedMessageMedia end - //functions memory optimize public static class TL_upload_saveFilePart extends TLObject { public static int constructor = 0xb304a621; @@ -14879,10 +15512,6 @@ public class TLRPC { return RpcDropAnswer.TLdeserialize(stream, constructor, exception); } - public void readParams(AbsSerializedData stream, boolean exception) { - req_msg_id = stream.readInt64(exception); - } - public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); stream.writeInt64(req_msg_id); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java b/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java index 3772ed52c..8901c1750 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -20,6 +20,7 @@ import jawnae.pyronet.PyroClient; import jawnae.pyronet.PyroSelector; public class TcpConnection extends ConnectionContext { + public enum TcpConnectionState { TcpConnectionStageIdle, TcpConnectionStageConnecting, @@ -30,8 +31,11 @@ public class TcpConnection extends ConnectionContext { public interface TcpConnectionDelegate { void tcpConnectionClosed(TcpConnection connection); + void tcpConnectionConnected(TcpConnection connection); + void tcpConnectionQuiackAckReceived(TcpConnection connection, int ack); + void tcpConnectionReceivedData(TcpConnection connection, ByteBufferDesc data, int length); } @@ -41,6 +45,7 @@ public class TcpConnection extends ConnectionContext { public volatile int channelToken = 0; private String hostAddress; private int hostPort; + private int currentAddressFlag; private int datacenterId; private int failedConnectionCount; public TcpConnectionDelegate delegate; @@ -62,13 +67,14 @@ public class TcpConnection extends ConnectionContext { if (selector == null) { selector = new PyroSelector(); selector.spawnNetworkThread("network thread"); - BuffersStorage storage = BuffersStorage.getInstance(); + BuffersStorage.getInstance(); } datacenterId = did; connectionState = TcpConnectionState.TcpConnectionStageIdle; } static volatile Integer nextChannelToken = 1; + static int generateChannelToken() { return nextChannelToken++; } @@ -101,8 +107,27 @@ public class TcpConnection extends ConnectionContext { connectionState = TcpConnectionState.TcpConnectionStageConnecting; try { Datacenter datacenter = ConnectionsManager.getInstance().datacenterWithId(datacenterId); - hostAddress = datacenter.getCurrentAddress(); - hostPort = datacenter.getCurrentPort(); + if (transportRequestClass == RPCRequest.RPCRequestClassDownloadMedia) { + currentAddressFlag = 2; + if (ConnectionsManager.useIpv6Address()) { + currentAddressFlag |= 1; + } + hostAddress = datacenter.getCurrentAddress(currentAddressFlag); + if (hostAddress == null) { + currentAddressFlag = 0; + if (ConnectionsManager.useIpv6Address()) { + currentAddressFlag |= 1; + } + hostAddress = datacenter.getCurrentAddress(currentAddressFlag); + } + } else { + currentAddressFlag = 0; + if (ConnectionsManager.useIpv6Address()) { + currentAddressFlag |= 1; + } + hostAddress = datacenter.getCurrentAddress(currentAddressFlag); + } + hostPort = datacenter.getCurrentPort(currentAddressFlag); try { synchronized (timerSync) { @@ -163,7 +188,7 @@ public class TcpConnection extends ConnectionContext { } catch (Exception e2) { FileLog.e("tmessages", e2); } - connectionState = TcpConnectionState.TcpConnectionStageReconnecting; + connectionState = TcpConnectionState.TcpConnectionStageReconnecting; if (delegate != null) { final TcpConnectionDelegate finalDelegate = delegate; Utilities.stageQueue.postRunnable(new Runnable() { @@ -186,7 +211,7 @@ public class TcpConnection extends ConnectionContext { isNextPort = true; if (failedConnectionCount > willRetryConnectCount) { Datacenter datacenter = ConnectionsManager.getInstance().datacenterWithId(datacenterId); - datacenter.nextAddressOrPort(); + datacenter.nextAddressOrPort(currentAddressFlag); failedConnectionCount = 0; } } @@ -319,7 +344,7 @@ public class TcpConnection extends ConnectionContext { ByteBufferDesc buffer = BuffersStorage.getInstance().getFreeBuffer(bufferLen); if (firstPacket) { - buffer.writeByte((byte)0xef); + buffer.writeByte((byte) 0xef); firstPacket = false; } if (packetLength < 0x7f) { @@ -354,12 +379,10 @@ public class TcpConnection extends ConnectionContext { ByteBuffer parseLaterBuffer = null; if (restOfTheData != null) { if (lastPacketLength == 0) { - //FileLog.e("tmessages", this + " write addition data to restOfTheData"); if (restOfTheData.capacity() - restOfTheData.position() >= buffer.limit()) { restOfTheData.limit(restOfTheData.position() + buffer.limit()); restOfTheData.put(buffer); buffer = restOfTheData.buffer; - //FileLog.e("tmessages", this + " no need to recreate buffer"); } else { ByteBufferDesc newBuffer = BuffersStorage.getInstance().getFreeBuffer(restOfTheData.limit() + buffer.limit()); restOfTheData.rewind(); @@ -368,30 +391,23 @@ public class TcpConnection extends ConnectionContext { buffer = newBuffer.buffer; BuffersStorage.getInstance().reuseFreeBuffer(restOfTheData); restOfTheData = newBuffer; - //FileLog.e("tmessages", this + " NEED to recreate buffer"); } } else { - //FileLog.e("tmessages", this + " write buffer to restOfTheData buffer of len = " + lastPacketLength); - int len = 0; + int len; if (lastPacketLength - restOfTheData.position() <= buffer.limit()) { len = lastPacketLength - restOfTheData.position(); - //FileLog.e("tmessages", this + " received buffer - OK!"); } else { len = buffer.limit(); - //FileLog.e("tmessages", this + " received buffer less than need"); } int oldLimit = buffer.limit(); buffer.limit(len); restOfTheData.put(buffer); buffer.limit(oldLimit); if (restOfTheData.position() != lastPacketLength) { - //FileLog.e("tmessages", this + " don't get much data to restOfTheData"); return; } else { - //FileLog.e("tmessages", this + " get much data to restOfTheData - OK!"); if (buffer.hasRemaining()) { parseLaterBuffer = buffer; - //FileLog.e("tmessages", this + " something remain in the received buffer"); } else { parseLaterBuffer = null; } @@ -427,10 +443,8 @@ public class TcpConnection extends ConnectionContext { restOfTheData.put(buffer); restOfTheData.limit(restOfTheData.position()); lastPacketLength = 0; - //FileLog.e("tmessages", this + " 1 - size less than 4 bytes - write to free buffer"); if (reuseLater != null) { BuffersStorage.getInstance().reuseFreeBuffer(reuseLater); - //FileLog.e("tmessages", this + " 1 - reuse later buffer1"); } break; } @@ -450,11 +464,10 @@ public class TcpConnection extends ConnectionContext { } if (fByte != 0x7f) { - currentPacketLength = ((int)fByte) * 4; + currentPacketLength = ((int) fByte) * 4; } else { buffer.reset(); if (buffer.remaining() < 4) { - //FileLog.e("tmessages", this + " 2 - size less than 4 bytes - write to free buffer"); if (restOfTheData == null || restOfTheData != null && restOfTheData.position() != 0) { ByteBufferDesc reuseLater = restOfTheData; restOfTheData = BuffersStorage.getInstance().getFreeBuffer(16384); @@ -463,7 +476,6 @@ public class TcpConnection extends ConnectionContext { lastPacketLength = 0; if (reuseLater != null) { BuffersStorage.getInstance().reuseFreeBuffer(reuseLater); - //FileLog.e("tmessages", this + " 2 - reuse later buffer1"); } } else { restOfTheData.position(restOfTheData.limit()); @@ -491,10 +503,8 @@ public class TcpConnection extends ConnectionContext { if (restOfTheData != null && restOfTheData.capacity() < len) { reuseLater = restOfTheData; restOfTheData = null; - //FileLog.e("tmessages", this + " not enough space for len, recreate buffer = " + len); } if (restOfTheData == null) { - //FileLog.e("tmessages", this + " write to restOfTheData, get buffer len = " + len); buffer.reset(); restOfTheData = BuffersStorage.getInstance().getFreeBuffer(len); restOfTheData.put(buffer); @@ -505,7 +515,6 @@ public class TcpConnection extends ConnectionContext { lastPacketLength = len; if (reuseLater != null) { BuffersStorage.getInstance().reuseFreeBuffer(reuseLater); - //FileLog.e("tmessages", this + " 3 - reuse later buffer1"); } return; } @@ -533,17 +542,14 @@ public class TcpConnection extends ConnectionContext { if (lastPacketLength != 0 && restOfTheData.position() == lastPacketLength || lastPacketLength == 0 && !restOfTheData.hasRemaining()) { BuffersStorage.getInstance().reuseFreeBuffer(restOfTheData); restOfTheData = null; - //FileLog.e("tmessages", this + " restOfTheData parsed null it"); } else { restOfTheData.compact(); restOfTheData.limit(restOfTheData.position()); restOfTheData.position(0); - //FileLog.e("tmessages", this + " restOfTheData NOT parsed, compact"); } } if (parseLaterBuffer != null) { - //FileLog.e("tmessages", this + " there is parseLaterBuffer"); buffer = parseLaterBuffer; parseLaterBuffer = null; } @@ -597,7 +603,7 @@ public class TcpConnection extends ConnectionContext { isNextPort = true; if (failedConnectionCount > willRetryConnectCount || switchToNextPort) { Datacenter datacenter = ConnectionsManager.getInstance().datacenterWithId(datacenterId); - datacenter.nextAddressOrPort(); + datacenter.nextAddressOrPort(currentAddressFlag); failedConnectionCount = 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index 2ae522fb4..31b0ffce5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -17,6 +17,7 @@ import org.telegram.android.MessagesStorage; import java.io.File; public class UserConfig { + private static TLRPC.User currentUser; public static boolean registeredForPush = false; public static boolean registeredForInternalPush = false; @@ -31,6 +32,7 @@ public class UserConfig { public static boolean saveIncomingPhotos = false; public static int contactsVersion = 1; public static String passcodeHash = ""; + public static byte[] passcodeSalt = new byte[0]; public static boolean appLocked = false; public static int passcodeType = 0; public static int autoLockIn = 60 * 60; @@ -68,6 +70,7 @@ public class UserConfig { editor.putBoolean("registeredForInternalPush", registeredForInternalPush); editor.putBoolean("blockedUsersLoaded", blockedUsersLoaded); editor.putString("passcodeHash1", passcodeHash); + editor.putString("passcodeSalt", passcodeSalt.length > 0 ? Base64.encodeToString(passcodeSalt, Base64.DEFAULT) : ""); editor.putBoolean("appLocked", appLocked); editor.putInt("passcodeType", passcodeType); editor.putInt("autoLockIn", autoLockIn); @@ -85,6 +88,7 @@ public class UserConfig { } else { editor.remove("user"); } + editor.commit(); if (oldFile != null) { oldFile.delete(); @@ -211,10 +215,51 @@ public class UserConfig { data.cleanup(); } } + String passcodeSaltString = preferences.getString("passcodeSalt", ""); + if (passcodeSaltString.length() > 0) { + passcodeSalt = Base64.decode(passcodeSaltString, Base64.DEFAULT); + } else { + passcodeSalt = new byte[0]; + } } } } + public static boolean checkPasscode(String passcode) { + if (passcodeSalt.length == 0) { + boolean result = Utilities.MD5(passcode).equals(passcodeHash); + if (result) { + try { + passcodeSalt = new byte[16]; + Utilities.random.nextBytes(passcodeSalt); + byte[] passcodeBytes = passcode.getBytes("UTF-8"); + byte[] bytes = new byte[32 + passcodeBytes.length]; + System.arraycopy(passcodeSalt, 0, bytes, 0, 16); + System.arraycopy(passcodeBytes, 0, bytes, 16, passcodeBytes.length); + System.arraycopy(passcodeSalt, 0, bytes, passcodeBytes.length + 16, 16); + passcodeHash = Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length)); + saveConfig(false); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + return result; + } else { + try { + byte[] passcodeBytes = passcode.getBytes("UTF-8"); + byte[] bytes = new byte[32 + passcodeBytes.length]; + System.arraycopy(passcodeSalt, 0, bytes, 0, 16); + System.arraycopy(passcodeBytes, 0, bytes, 16, passcodeBytes.length); + System.arraycopy(passcodeSalt, 0, bytes, passcodeBytes.length + 16, 16); + String hash = Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length)); + return passcodeHash.equals(hash); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + return false; + } + public static void clearConfig() { currentUser = null; registeredForInternalPush = false; @@ -229,6 +274,7 @@ public class UserConfig { appLocked = false; passcodeType = 0; passcodeHash = ""; + passcodeSalt = new byte[0]; autoLockIn = 60 * 60; lastPauseTime = 0; isWaitingForPasscodeEnter = false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index 2b1ac08eb..73326ac0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -1,43 +1,24 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 2.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; -import android.app.Activity; -import android.content.ContentUris; import android.content.Context; -import android.content.Intent; import android.content.SharedPreferences; -import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.text.SpannableStringBuilder; import android.util.Base64; -import net.hockeyapp.android.CrashManager; -import net.hockeyapp.android.CrashManagerListener; -import net.hockeyapp.android.UpdateManager; - -import org.telegram.android.AndroidUtilities; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.math.BigInteger; import java.nio.ByteBuffer; import java.security.KeyFactory; @@ -45,9 +26,7 @@ import java.security.MessageDigest; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.RSAPublicKeySpec; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; @@ -56,6 +35,7 @@ import java.util.zip.GZIPOutputStream; import javax.crypto.Cipher; public class Utilities { + public static Pattern pattern = Pattern.compile("[0-9]+"); public static SecureRandom random = new SecureRandom(); @@ -111,13 +91,19 @@ public class Utilities { } public native static long doPQNative(long _what); + public native static void loadBitmap(String path, Bitmap bitmap, int scale, int width, int height, int stride); + public native static int pinBitmap(Bitmap bitmap); + public native static void blurBitmap(Object bitmap, int radius, int unpin); + public native static void calcCDT(ByteBuffer hsvBuffer, int width, int height, ByteBuffer buffer); + public native static Bitmap loadWebpImage(ByteBuffer buffer, int len, BitmapFactory.Options options); - public native static Bitmap loadBpgImage(ByteBuffer buffer, int len, BitmapFactory.Options options); + public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap); + private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length); public static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, boolean changeIv, int offset, int length) { @@ -287,12 +273,13 @@ public class Utilities { if (arr1 == null || arr2 == null || arr1.length - offset1 != arr2.length - offset2 || arr1.length - offset1 < 0) { return false; } + boolean result = true; for (int a = offset1; a < arr1.length; a++) { if (arr1[a + offset1] != arr2[a + offset2]) { - return false; + result = false; } } - return true; + return result; } public static byte[] computeSHA1(byte[] convertme, int offset, int len) { @@ -321,7 +308,7 @@ public class Utilities { convertme.limit(oldl); convertme.position(oldp); } - return null; + return new byte[0]; } public static byte[] computeSHA1(ByteBuffer convertme) { @@ -362,59 +349,6 @@ public class Utilities { + (((long) bytes[3] & 0xFF) << 24) + (((long) bytes[2] & 0xFF) << 16) + (((long) bytes[1] & 0xFF) << 8) + ((long) bytes[0] & 0xFF); } - public static MessageKeyData generateMessageKeyData(byte[] authKey, byte[] messageKey, boolean incoming) { - MessageKeyData keyData = new MessageKeyData(); - if (authKey == null || authKey.length == 0) { - keyData.aesIv = null; - keyData.aesKey = null; - return keyData; - } - - int x = incoming ? 8 : 0; - - SerializedData data = new SerializedData(); - data.writeRaw(messageKey); - data.writeRaw(authKey, x, 32); - byte[] sha1_a = Utilities.computeSHA1(data.toByteArray()); - data.cleanup(); - - data = new SerializedData(); - data.writeRaw(authKey, 32 + x, 16); - data.writeRaw(messageKey); - data.writeRaw(authKey, 48 + x, 16); - byte[] sha1_b = Utilities.computeSHA1(data.toByteArray()); - data.cleanup(); - - data = new SerializedData(); - data.writeRaw(authKey, 64 + x, 32); - data.writeRaw(messageKey); - byte[] sha1_c = Utilities.computeSHA1(data.toByteArray()); - data.cleanup(); - - data = new SerializedData(); - data.writeRaw(messageKey); - data.writeRaw(authKey, 96 + x, 32); - byte[] sha1_d = Utilities.computeSHA1(data.toByteArray()); - data.cleanup(); - - data = new SerializedData(); - data.writeRaw(sha1_a, 0, 8); - data.writeRaw(sha1_b, 8, 12); - data.writeRaw(sha1_c, 4, 12); - keyData.aesKey = data.toByteArray(); - data.cleanup(); - - data = new SerializedData(); - data.writeRaw(sha1_a, 8, 12); - data.writeRaw(sha1_b, 0, 8); - data.writeRaw(sha1_c, 16, 4); - data.writeRaw(sha1_d, 0, 8); - keyData.aesIv = data.toByteArray(); - data.cleanup(); - - return keyData; - } - public static TLObject decompress(byte[] data, TLObject parentObject, boolean exception) { final int BUFFER_SIZE = 16384; ByteArrayInputStream is = new ByteArrayInputStream(data); @@ -477,42 +411,6 @@ public class Utilities { return packedData; } - public static boolean copyFile(InputStream sourceFile, File destFile) throws IOException { - OutputStream out = new FileOutputStream(destFile); - byte[] buf = new byte[4096]; - int len; - while ((len = sourceFile.read(buf)) > 0) { - Thread.yield(); - out.write(buf, 0, len); - } - out.close(); - return true; - } - - public static boolean copyFile(File sourceFile, File destFile) throws IOException { - if (!destFile.exists()) { - destFile.createNewFile(); - } - FileInputStream source = null; - FileOutputStream destination = null; - try { - source = new FileInputStream(sourceFile); - destination = new FileOutputStream(destFile); - destination.getChannel().transferFrom(source.getChannel(), 0, source.getChannel().size()); - } catch (Exception e) { - FileLog.e("tmessages", e); - return false; - } finally { - if (source != null) { - source.close(); - } - if (destination != null) { - destination.close(); - } - } - return true; - } - public static String MD5(String md5) { if (md5 == null) { return null; @@ -530,249 +428,4 @@ public class Utilities { } return null; } - - public static void addMediaToGallery(String fromPath) { - if (fromPath == null) { - return; - } - File f = new File(fromPath); - Uri contentUri = Uri.fromFile(f); - addMediaToGallery(contentUri); - } - - public static void addMediaToGallery(Uri uri) { - if (uri == null) { - return; - } - Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - mediaScanIntent.setData(uri); - ApplicationLoader.applicationContext.sendBroadcast(mediaScanIntent); - } - - private static File getAlbumDir() { - File storageDir = null; - if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { - storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Telegram"); - if (storageDir != null) { - if (!storageDir.mkdirs()) { - if (!storageDir.exists()){ - FileLog.d("tmessages", "failed to create directory"); - return null; - } - } - } - } else { - FileLog.d("tmessages", "External storage is not mounted READ/WRITE."); - } - - return storageDir; - } - - public static String getPath(final Uri uri) { - try { - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - if (isKitKat && DocumentsContract.isDocumentUri(ApplicationLoader.applicationContext, uri)) { - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - } else if (isDownloadsDocument(uri)) { - final String id = DocumentsContract.getDocumentId(uri); - final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); - return getDataColumn(ApplicationLoader.applicationContext, contentUri, null, null); - } else if (isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - switch (type) { - case "image": - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - break; - case "video": - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - break; - case "audio": - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - break; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[] { - split[1] - }; - - return getDataColumn(ApplicationLoader.applicationContext, contentUri, selection, selectionArgs); - } - } else if ("content".equalsIgnoreCase(uri.getScheme())) { - return getDataColumn(ApplicationLoader.applicationContext, uri, null, null); - } else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - } catch (Exception e) { - FileLog.e("tmessages", e); - } - return null; - } - - public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { - - Cursor cursor = null; - final String column = "_data"; - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); - if (cursor != null && cursor.moveToFirst()) { - final int column_index = cursor.getColumnIndexOrThrow(column); - return cursor.getString(column_index); - } - } catch (Exception e) { - FileLog.e("tmessages", e); - } finally { - if (cursor != null) { - cursor.close(); - } - } - return null; - } - - public static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - public static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - public static boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } - - public static File generatePicturePath() { - try { - File storageDir = getAlbumDir(); - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - return new File(storageDir, "IMG_" + timeStamp + ".jpg"); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - return null; - } - - public static CharSequence generateSearchName(String name, String name2, String q) { - if (name == null && name2 == null) { - return ""; - } - SpannableStringBuilder builder = new SpannableStringBuilder(); - String wholeString = name; - if (wholeString == null || wholeString.length() == 0) { - wholeString = name2; - } else if (name2 != null && name2.length() != 0) { - wholeString += " " + name2; - } - wholeString = wholeString.trim(); - String lower = " " + wholeString.toLowerCase(); - - int index = -1; - int lastIndex = 0; - while ((index = lower.indexOf(" " + q, lastIndex)) != -1) { - int idx = index - (index == 0 ? 0 : 1); - int end = q.length() + (index == 0 ? 0 : 1) + idx; - - if (lastIndex != 0 && lastIndex != idx + 1) { - builder.append(wholeString.substring(lastIndex, idx)); - } else if (lastIndex == 0 && idx != 0) { - builder.append(wholeString.substring(0, idx)); - } - - String query = wholeString.substring(idx, end); - if (query.startsWith(" ")) { - builder.append(" "); - } - query = query.trim(); - builder.append(AndroidUtilities.replaceTags("" + query + "")); - - lastIndex = end; - } - - if (lastIndex != -1 && lastIndex != wholeString.length()) { - builder.append(wholeString.substring(lastIndex, wholeString.length())); - } - - return builder; - } - - public static File generateVideoPath() { - try { - File storageDir = getAlbumDir(); - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - return new File(storageDir, "VID_" + timeStamp + ".mp4"); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - return null; - } - - public static String formatFileSize(long size) { - if (size < 1024) { - return String.format("%d B", size); - } else if (size < 1024 * 1024) { - return String.format("%.1f KB", size / 1024.0f); - } else if (size < 1024 * 1024 * 1024) { - return String.format("%.1f MB", size / 1024.0f / 1024.0f); - } else { - return String.format("%.1f GB", size / 1024.0f / 1024.0f / 1024.0f); - } - } - - public static byte[] decodeQuotedPrintable(final byte[] bytes) { - if (bytes == null) { - return null; - } - final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - for (int i = 0; i < bytes.length; i++) { - final int b = bytes[i]; - if (b == '=') { - try { - final int u = Character.digit((char) bytes[++i], 16); - final int l = Character.digit((char) bytes[++i], 16); - buffer.write((char) ((u << 4) + l)); - } catch (Exception e) { - FileLog.e("tmessages", e); - return null; - } - } else { - buffer.write(b); - } - } - byte[] array = buffer.toByteArray(); - try { - buffer.close(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - return array; - } - - public static void checkForCrashes(Activity context) { - CrashManager.register(context, BuildVars.HOCKEY_APP_HASH, new CrashManagerListener() { - @Override - public boolean includeDeviceData() { - return true; - } - }); - } - - public static void checkForUpdates(Activity context) { - if (BuildVars.DEBUG_VERSION) { - UpdateManager.register(context, BuildVars.HOCKEY_APP_HASH); - } - } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index 03942a068..7ddad2ce3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -88,7 +88,7 @@ public class ActionBar extends FrameLayout { } int maxTextWidth = 0; - LayoutParams layoutParams = null; + LayoutParams layoutParams; if (titleTextView != null && titleTextView.getVisibility() == VISIBLE) { if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { @@ -121,7 +121,7 @@ public class ActionBar extends FrameLayout { maxTextWidth = Math.max(maxTextWidth, subTitleTextView.getMeasuredWidth()); } - int x = 0; + int x; if (backButtonImageView != null && backButtonImageView.getVisibility() == VISIBLE) { x = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 80 : 72); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index 2a7f75c4f..b14f21bfe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -71,7 +71,7 @@ public class ActionBarLayout extends FrameLayout { if (view instanceof ActionBar && view.getVisibility() == VISIBLE) { if (((ActionBar) view).getCastShadows()) { actionBarHeight = view.getMeasuredHeight(); - wasActionBar = true; + //wasActionBar = true; } break; } @@ -424,7 +424,7 @@ public class ActionBarLayout extends FrameLayout { float velX = velocityTracker.getXVelocity(); float velY = velocityTracker.getYVelocity(); final boolean backAnimation = x < containerView.getMeasuredWidth() / 3.0f && (velX < 3500 || velX < velY); - float distToMove = 0; + float distToMove; if (!backAnimation) { distToMove = containerView.getMeasuredWidth() - x; animatorSet.playTogether( @@ -674,6 +674,7 @@ public class ActionBarLayout extends FrameLayout { animators.add(ObjectAnimatorProxy.ofFloat(backgroundView, "alpha", 0.0f, 1.0f)); } + fragment.onOpenAnimationStart(); currentAnimation = new AnimatorSetProxy(); currentAnimation.playTogether(animators); currentAnimation.setInterpolator(accelerateDecelerateInterpolator); @@ -703,6 +704,7 @@ public class ActionBarLayout extends FrameLayout { }; ViewProxy.setAlpha(containerView, 0.0f); ViewProxy.setTranslationX(containerView, 48.0f); + fragment.onOpenAnimationStart(); startLayoutAnimation(true, true); /*currentAnimation = new AnimatorSetProxy(); currentAnimation.playTogether( @@ -733,6 +735,7 @@ public class ActionBarLayout extends FrameLayout { ViewProxy.setAlpha(backgroundView, 1.0f); backgroundView.setVisibility(VISIBLE); } + fragment.onOpenAnimationStart(); fragment.onOpenAnimationEnd(); } return true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java index ef85bd22f..18ce670aa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -10,7 +10,6 @@ package org.telegram.ui.ActionBar; import android.content.Context; import android.graphics.drawable.Drawable; -import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; @@ -32,14 +31,6 @@ public class ActionBarMenu extends LinearLayout { super(context); } - public ActionBarMenu(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ActionBarMenu(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - public View addItemResource(int id, int resourceId) { LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = li.inflate(resourceId, null); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java index afbf6b807..6d152b6a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -42,10 +42,22 @@ import java.lang.reflect.Field; public class ActionBarMenuItem extends FrameLayoutFixed { public static class ActionBarMenuItemSearchListener { - public void onSearchExpand() { } - public boolean onSearchCollapse() { return true; } - public void onTextChanged(EditText editText) { } - public void onSearchPressed(EditText editText) { } + public void onSearchExpand() { + } + + public boolean onSearchCollapse() { + return true; + } + + public void onTextChanged(EditText editText) { + } + + public void onSearchPressed(EditText editText) { + } + } + + public interface ActionBarMenuItemDelegate { + void onItemClick(int id); } private ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout; @@ -63,8 +75,8 @@ public class ActionBarMenuItem extends FrameLayoutFixed { private Runnable showMenuRunnable; private boolean showFromBottom; private int menuHeight = AndroidUtilities.dp(16); - private boolean needOffset = Build.VERSION.SDK_INT >= 21; private int subMenuOpenSide = 0; + private ActionBarMenuItemDelegate delegate; public ActionBarMenuItem(Context context, ActionBarMenu menu, int background) { super(context); @@ -115,8 +127,8 @@ public class ActionBarMenuItem extends FrameLayoutFixed { for (int a = 0; a < popupLayout.getChildCount(); a++) { View child = popupLayout.getChildAt(a); child.getHitRect(rect); - if ((Integer)child.getTag() < 100) { - if (!rect.contains((int)x, (int)y)) { + if ((Integer) child.getTag() < 100) { + if (!rect.contains((int) x, (int) y)) { child.setPressed(false); child.setSelected(false); if (Build.VERSION.SDK_INT >= 21) { @@ -137,7 +149,11 @@ public class ActionBarMenuItem extends FrameLayoutFixed { } else if (popupWindow != null && popupWindow.isShowing() && event.getActionMasked() == MotionEvent.ACTION_UP) { if (selectedMenuView != null) { selectedMenuView.setSelected(false); - parentMenu.onItemClick((Integer) selectedMenuView.getTag()); + if (parentMenu != null) { + parentMenu.onItemClick((Integer) selectedMenuView.getTag()); + } else if (delegate != null) { + delegate.onItemClick((Integer) selectedMenuView.getTag()); + } } popupWindow.dismiss(); } else { @@ -149,12 +165,12 @@ public class ActionBarMenuItem extends FrameLayoutFixed { return super.onTouchEvent(event); } - public void setShowFromBottom(boolean value) { - showFromBottom = value; + public void setDelegate(ActionBarMenuItemDelegate delegate) { + this.delegate = delegate; } - public void setNeedOffset(boolean value) { - needOffset = Build.VERSION.SDK_INT >= 21 && value; + public void setShowFromBottom(boolean value) { + showFromBottom = value; } public void setSubMenuOpenSide(int side) { @@ -174,7 +190,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { if (popupWindow != null && popupWindow.isShowing()) { v.getHitRect(rect); - if (!rect.contains((int)event.getX(), (int)event.getY())) { + if (!rect.contains((int) event.getX(), (int) event.getY())) { popupWindow.dismiss(); } } @@ -213,7 +229,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed { } } popupLayout.addView(textView); - LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)textView.getLayoutParams(); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams(); if (LocaleController.isRTL) { layoutParams.gravity = Gravity.RIGHT; } @@ -223,7 +239,11 @@ public class ActionBarMenuItem extends FrameLayoutFixed { textView.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - parentMenu.onItemClick((Integer) view.getTag()); + if (parentMenu != null) { + parentMenu.onItemClick((Integer) view.getTag()); + } else if (delegate != null) { + delegate.onItemClick((Integer) view.getTag()); + } if (popupWindow != null && popupWindow.isShowing()) { popupWindow.dismiss(); } @@ -262,7 +282,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed { popupWindow.getContentView().setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0 && event.getAction() == KeyEvent.ACTION_UP && popupWindow != null && popupWindow.isShowing()) { + if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0 && event.getAction() == KeyEvent.ACTION_UP && popupWindow != null && popupWindow.isShowing()) { popupWindow.dismiss(); return true; } @@ -277,8 +297,14 @@ public class ActionBarMenuItem extends FrameLayoutFixed { popupWindow.showAsDropDown(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth(), getOffsetY()); popupWindow.update(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth(), getOffsetY(), -1, -1); } else { - popupWindow.showAsDropDown(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY()); - popupWindow.update(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY(), -1, -1); + if (parentMenu != null) { + popupWindow.showAsDropDown(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY()); + popupWindow.update(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY(), -1, -1); + } else if (getParent() != null) { + View parent = (View) getParent(); + popupWindow.showAsDropDown(this, parent.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parent.getLeft(), getOffsetY()); + popupWindow.update(this, parent.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parent.getLeft(), getOffsetY(), -1, -1); + } } } else { popupWindow.showAsDropDown(this, -AndroidUtilities.dp(8), getOffsetY()); @@ -289,7 +315,12 @@ public class ActionBarMenuItem extends FrameLayoutFixed { if (showFromBottom) { popupWindow.showAsDropDown(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth(), getOffsetY()); } else { - popupWindow.showAsDropDown(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY()); + if (parentMenu != null) { + popupWindow.showAsDropDown(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY()); + } else { + View parent = (View) getParent(); + popupWindow.showAsDropDown(this, parent.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parent.getLeft(), getOffsetY()); + } } } else { popupWindow.showAsDropDown(this, -AndroidUtilities.dp(8), getOffsetY()); @@ -305,14 +336,14 @@ public class ActionBarMenuItem extends FrameLayoutFixed { if (diff < 0) { y -= diff; } - return y - (needOffset ? AndroidUtilities.statusBarHeight : 0); + return y; } else { - return -getMeasuredHeight() - (needOffset ? AndroidUtilities.statusBarHeight : 0); + return -getMeasuredHeight(); } } public void openSearch() { - if (searchContainer == null || searchContainer.getVisibility() == VISIBLE) { + if (searchContainer == null || searchContainer.getVisibility() == VISIBLE || parentMenu == null) { return; } parentMenu.parentActionBar.onSearchFieldVisibilityChanged(toggleSearch()); @@ -357,10 +388,13 @@ public class ActionBarMenuItem extends FrameLayoutFixed { } public ActionBarMenuItem setIsSearchField(boolean value) { + if (parentMenu == null) { + return this; + } if (value && searchContainer == null) { searchContainer = new FrameLayout(getContext()); parentMenu.addView(searchContainer, 0); - LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)searchContainer.getLayoutParams(); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) searchContainer.getLayoutParams(); layoutParams.weight = 1; layoutParams.width = 0; layoutParams.height = LayoutHelper.MATCH_PARENT; @@ -491,7 +525,12 @@ public class ActionBarMenuItem extends FrameLayoutFixed { if (showFromBottom) { popupWindow.update(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth(), getOffsetY(), -1, -1); } else { - popupWindow.update(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY(), -1, -1); + if (parentMenu != null) { + popupWindow.update(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY(), -1, -1); + } else { + View parent = (View) getParent(); + popupWindow.update(this, parent.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parent.getLeft(), getOffsetY(), -1, -1); + } } } else { popupWindow.update(this, -AndroidUtilities.dp(8), getOffsetY(), -1, -1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index 479ab5512..759222d1c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -11,12 +11,9 @@ package org.telegram.ui.ActionBar; import android.content.Context; -import android.os.Build; -import android.util.AttributeSet; import android.view.KeyEvent; import android.view.View; import android.view.ViewTreeObserver; -import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.PopupWindow; @@ -60,14 +57,6 @@ public class ActionBarPopupWindow extends PopupWindow { super(context); } - public ActionBarPopupWindowLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ActionBarPopupWindowLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - public void setDispatchKeyEventListener(OnDispatchKeyEventListener listener) { mOnDispatchKeyEventListener = listener; } @@ -91,21 +80,6 @@ public class ActionBarPopupWindow extends PopupWindow { init(); } - public ActionBarPopupWindow(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public ActionBarPopupWindow(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - - public ActionBarPopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(); - } - public ActionBarPopupWindow(int width, int height) { super(width, height); init(); @@ -135,15 +109,15 @@ public class ActionBarPopupWindow extends PopupWindow { mSuperScrollListener = null; } } - if (Build.VERSION.SDK_INT >= 21) { + /*if (Build.VERSION.SDK_INT >= 21) { try { Field field = PopupWindow.class.getDeclaredField("mWindowLayoutType"); field.setAccessible(true); field.set(this, WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); } catch (Exception e) { - /* ignored */ + //ignored } - } + }*/ } private void unregisterListener() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java index 2388b7b48..c4414cc87 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -9,7 +9,7 @@ package org.telegram.ui.ActionBar; import android.app.Activity; -import android.app.AlertDialog; +import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -23,8 +23,9 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.R; public class BaseFragment { + private boolean isFinished = false; - protected AlertDialog visibleDialog = null; + protected Dialog visibleDialog = null; protected View fragmentView; protected ActionBarLayout parentLayout; @@ -191,7 +192,11 @@ public class BaseFragment { } } - public void onOpenAnimationEnd() { + protected void onOpenAnimationEnd() { + + } + + protected void onOpenAnimationStart() { } @@ -203,7 +208,7 @@ public class BaseFragment { return true; } - public AlertDialog showAlertDialog(AlertDialog.Builder builder) { + public Dialog showDialog(Dialog dialog) { if (parentLayout == null || parentLayout.animationInProgress || parentLayout.startedTracking || parentLayout.checkTransitionAnimation()) { return null; } @@ -216,7 +221,7 @@ public class BaseFragment { FileLog.e("tmessages", e); } try { - visibleDialog = builder.show(); + visibleDialog = dialog; visibleDialog.setCanceledOnTouchOutside(true); visibleDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override @@ -225,6 +230,7 @@ public class BaseFragment { onDialogDismiss(); } }); + visibleDialog.show(); return visibleDialog; } catch (Exception e) { FileLog.e("tmessages", e); @@ -235,4 +241,8 @@ public class BaseFragment { protected void onDialogDismiss() { } + + public void setVisibleDialog(Dialog dialog) { + visibleDialog = dialog; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java new file mode 100644 index 000000000..39ca1cf64 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -0,0 +1,301 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.ActionBar; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Build; +import android.os.Bundle; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.AnimationCompat.AnimatorListenerAdapterProxy; +import org.telegram.android.AnimationCompat.AnimatorSetProxy; +import org.telegram.android.AnimationCompat.ObjectAnimatorProxy; +import org.telegram.android.LocaleController; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; +import org.telegram.ui.Components.LayoutHelper; + +public class BottomSheet extends Dialog { + + private LinearLayout linearLayout; + private FrameLayout container; + private boolean dismissed; + + private DialogInterface.OnClickListener onClickListener; + + private CharSequence[] items; + private View customView; + private boolean overrideTabletWidth = true; + + private BottomSheetDelegate delegate; + + public interface BottomSheetDelegate { + void onOpenAnimationEnd(); + } + + private static class BottomSheetRow extends FrameLayout { + + private TextView textView; + + public BottomSheetRow(Context context) { + super(context); + + setBackgroundResource(R.drawable.list_selector); + setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + + textView = new TextView(context); + textView.setTextColor(0xff212121); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); + } + } + + public BottomSheet(Context context) { + super(context); + + container = new FrameLayout(getContext()); + container.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + dismiss(); + return false; + } + }); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + /* + @null + @null + fill_parent + @android:color/transparent + true + @null + true + @style/BottomSheet.Animation + #DD000000 + #8A000000 + #42000000 + */ + + Window window = getWindow(); + window.setBackgroundDrawableResource(R.drawable.transparent); + window.requestFeature(Window.FEATURE_NO_TITLE); + + setContentView(container); + + linearLayout = new LinearLayout(getContext()); + linearLayout.setOrientation(LinearLayout.VERTICAL); + if (AndroidUtilities.isTablet() && !overrideTabletWidth) { + container.addView(linearLayout, 0, LayoutHelper.createFrame(320, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL)); + } else { + container.addView(linearLayout, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); + } + + View shadow = new View(getContext()); + shadow.setBackgroundResource(R.drawable.header_shadow_reverse); + linearLayout.addView(shadow, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 3)); + + LinearLayout containerView = new LinearLayout(getContext()); + containerView.setBackgroundColor(0xffffffff); + containerView.setOrientation(LinearLayout.VERTICAL); + containerView.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + linearLayout.addView(containerView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + if (items != null) { + for (int a = 0; a < items.length; a++) { + CharSequence charSequence = items[a]; + BottomSheetRow row = new BottomSheetRow(getContext()); + row.textView.setText(charSequence); + containerView.addView(row, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + row.setTag(a); + row.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismissWithButtonClick((Integer) v.getTag()); + } + }); + } + } + if (customView != null) { + containerView.addView(customView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } + + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.height = ViewGroup.LayoutParams.MATCH_PARENT; + params.width = ViewGroup.LayoutParams.MATCH_PARENT; + params.gravity = Gravity.TOP | Gravity.LEFT; + params.dimAmount = 0.2f; + params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + if (Build.VERSION.SDK_INT >= 21) { + params.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; + params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; + } + getWindow().setAttributes(params); + + setOnShowListener(new OnShowListener() { + @Override + public void onShow(DialogInterface dialog) { + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", linearLayout.getHeight(), 0)); + animatorSetProxy.setDuration(180); + animatorSetProxy.setInterpolator(new DecelerateInterpolator()); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (delegate != null) { + delegate.onOpenAnimationEnd(); + } + } + }); + animatorSetProxy.start(); + } + }); + } + + public void setDelegate(BottomSheetDelegate delegate) { + this.delegate = delegate; + } + + public FrameLayout getContainer() { + return container; + } + + public LinearLayout getSheetContainer() { + return linearLayout; + } + + private void dismissWithButtonClick(final int item) { + if (dismissed) { + return; + } + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", linearLayout.getHeight() + AndroidUtilities.dp(10)) + ); + animatorSetProxy.setDuration(180); + animatorSetProxy.setInterpolator(new AccelerateInterpolator()); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (onClickListener != null) { + onClickListener.onClick(BottomSheet.this, item); + } + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + BottomSheet.super.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + @Override + public void onAnimationCancel(Object animation) { + onAnimationEnd(animation); + } + }); + animatorSetProxy.start(); + } + + @Override + public void dismiss() { + if (dismissed) { + return; + } + dismissed = true; + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", linearLayout.getHeight() + AndroidUtilities.dp(10)) + ); + animatorSetProxy.setDuration(180); + animatorSetProxy.setInterpolator(new AccelerateInterpolator()); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + BottomSheet.super.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + @Override + public void onAnimationCancel(Object animation) { + onAnimationEnd(animation); + } + }); + animatorSetProxy.start(); + } + + public static class Builder { + + private BottomSheet bottomSheet; + + public Builder(Context context) { + bottomSheet = new BottomSheet(context); + } + + public Builder setItems(CharSequence[] items, final OnClickListener onClickListener) { + bottomSheet.items = items; + bottomSheet.onClickListener = onClickListener; + return this; + } + + public Builder setCustomView(View view) { + bottomSheet.customView = view; + return this; + } + + public BottomSheet create() { + return bottomSheet; + } + + public BottomSheet show() { + bottomSheet.show(); + return bottomSheet; + } + + public BottomSheet setOverrideTabletWidth(boolean value) { + bottomSheet.overrideTabletWidth = value; + return bottomSheet; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapterRecycler.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapterRecycler.java new file mode 100644 index 000000000..4f24e7635 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapterRecycler.java @@ -0,0 +1,210 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Adapters; + +import org.telegram.SQLite.SQLiteCursor; +import org.telegram.SQLite.SQLitePreparedStatement; +import org.telegram.android.AndroidUtilities; +import org.telegram.android.MessagesStorage; +import org.telegram.android.support.widget.RecyclerView; +import org.telegram.messenger.ConnectionsManager; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.RPCRequest; +import org.telegram.messenger.TLObject; +import org.telegram.messenger.TLRPC; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class BaseSearchAdapterRecycler extends RecyclerView.Adapter { + + protected static class HashtagObject { + String hashtag; + int date; + } + + protected ArrayList globalSearch = new ArrayList<>(); + private long reqId = 0; + private int lastReqId; + protected String lastFoundUsername = null; + + protected ArrayList hashtags; + protected HashMap hashtagsByText; + protected boolean hashtagsLoadedFromDb = false; + + public void queryServerSearch(final String query) { + if (reqId != 0) { + ConnectionsManager.getInstance().cancelRpc(reqId, true); + reqId = 0; + } + if (query == null || query.length() < 5) { + globalSearch.clear(); + lastReqId = 0; + notifyDataSetChanged(); + return; + } + TLRPC.TL_contacts_search req = new TLRPC.TL_contacts_search(); + req.q = query; + req.limit = 50; + final int currentReqId = ++lastReqId; + reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (currentReqId == lastReqId) { + if (error == null) { + TLRPC.TL_contacts_found res = (TLRPC.TL_contacts_found) response; + globalSearch = res.users; + lastFoundUsername = query; + notifyDataSetChanged(); + } + } + reqId = 0; + } + }); + } + }, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors); + } + + public void loadRecentHashtags() { + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT id, date FROM hashtag_recent_v2 WHERE 1"); + final ArrayList arrayList = new ArrayList<>(); + final HashMap hashMap = new HashMap<>(); + while (cursor.next()) { + HashtagObject hashtagObject = new HashtagObject(); + hashtagObject.hashtag = cursor.stringValue(0); + hashtagObject.date = cursor.intValue(1); + arrayList.add(hashtagObject); + hashMap.put(hashtagObject.hashtag, hashtagObject); + } + cursor.dispose(); + Collections.sort(arrayList, new Comparator() { + @Override + public int compare(HashtagObject lhs, HashtagObject rhs) { + if (lhs.date < rhs.date) { + return 1; + } else if (lhs.date > rhs.date) { + return -1; + } else { + return 0; + } + } + }); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + setHashtags(arrayList, hashMap); + } + }); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + public void addHashtagsFromMessage(String message) { + if (message == null) { + return; + } + boolean changed = false; + Pattern pattern = Pattern.compile("(^|\\s)#[\\w@\\.]+"); + Matcher matcher = pattern.matcher(message); + while (matcher.find()) { + int start = matcher.start(); + int end = matcher.end(); + if (message.charAt(start) != '@' && message.charAt(start) != '#') { + start++; + } + String hashtag = message.substring(start, end); + if (hashtagsByText == null) { + hashtagsByText = new HashMap<>(); + hashtags = new ArrayList<>(); + } + HashtagObject hashtagObject = hashtagsByText.get(hashtag); + if (hashtagObject == null) { + hashtagObject = new HashtagObject(); + hashtagObject.hashtag = hashtag; + hashtagsByText.put(hashtagObject.hashtag, hashtagObject); + } else { + hashtags.remove(hashtagObject); + } + hashtagObject.date = (int) (System.currentTimeMillis() / 1000); + hashtags.add(0, hashtagObject); + changed = true; + } + if (changed) { + putRecentHashtags(hashtags); + } + } + + private void putRecentHashtags(final ArrayList arrayList) { + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + MessagesStorage.getInstance().getDatabase().beginTransaction(); + SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO hashtag_recent_v2 VALUES(?, ?)"); + for (int a = 0; a < arrayList.size(); a++) { + if (a == 100) { + break; + } + HashtagObject hashtagObject = arrayList.get(a); + state.requery(); + state.bindString(1, hashtagObject.hashtag); + state.bindInteger(2, hashtagObject.date); + state.step(); + } + state.dispose(); + MessagesStorage.getInstance().getDatabase().commitTransaction(); + if (arrayList.size() >= 100) { + MessagesStorage.getInstance().getDatabase().beginTransaction(); + for (int a = 100; a < arrayList.size(); a++) { + MessagesStorage.getInstance().getDatabase().executeFast("DELETE FROM hashtag_recent_v2 WHERE id = '" + arrayList.get(a).hashtag + "'").stepThis().dispose(); + } + MessagesStorage.getInstance().getDatabase().commitTransaction(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + public void clearRecentHashtags() { + hashtags = new ArrayList<>(); + hashtagsByText = new HashMap<>(); + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + MessagesStorage.getInstance().getDatabase().executeFast("DELETE FROM hashtag_recent_v2 WHERE 1").stepThis().dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + protected void setHashtags(ArrayList arrayList, HashMap hashMap) { + hashtags = arrayList; + hashtagsByText = hashMap; + hashtagsLoadedFromDb = true; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java index 0fd986614..afe18248d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java @@ -294,7 +294,7 @@ public class ChatActivityAdapter { } } ); - showAlertDialog(builder); + showDialog(builder.create()); } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index e8884689c..56508d07a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -14,17 +14,25 @@ import android.view.ViewGroup; import org.telegram.android.AndroidUtilities; import org.telegram.android.MessagesController; +import org.telegram.android.support.widget.RecyclerView; import org.telegram.messenger.TLRPC; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.LoadingCell; -public class DialogsAdapter extends BaseFragmentAdapter { +public class DialogsAdapter extends RecyclerView.Adapter { private Context mContext; private boolean serverOnly; private long openedDialogId; private int currentCount; + private class Holder extends RecyclerView.ViewHolder { + + public Holder(View itemView) { + super(itemView); + } + } + public DialogsAdapter(Context context, boolean onlyFromServer) { mContext = context; serverOnly = onlyFromServer; @@ -36,21 +44,11 @@ public class DialogsAdapter extends BaseFragmentAdapter { public boolean isDataSetChanged() { int current = currentCount; - return current != getCount(); + return current != getItemCount(); } @Override - public boolean areAllItemsEnabled() { - return true; - } - - @Override - public boolean isEnabled(int i) { - return true; - } - - @Override - public int getCount() { + public int getItemCount() { int count; if (serverOnly) { count = MessagesController.getInstance().dialogsServerOnly.size(); @@ -67,7 +65,6 @@ public class DialogsAdapter extends BaseFragmentAdapter { return count; } - @Override public TLRPC.TL_dialog getItem(int i) { if (serverOnly) { if (i < 0 || i >= MessagesController.getInstance().dialogsServerOnly.size()) { @@ -88,41 +85,32 @@ public class DialogsAdapter extends BaseFragmentAdapter { } @Override - public boolean hasStableIds() { - return true; + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View view = null; + if (viewType == 0) { + view = new DialogCell(mContext); + } else if (viewType == 1) { + view = new LoadingCell(mContext); + } + return new Holder(view); } @Override - public View getView(int i, View view, ViewGroup viewGroup) { - int type = getItemViewType(i); - if (type == 1) { - if (view == null) { - view = new LoadingCell(mContext); - } - } else if (type == 0) { - if (view == null) { - view = new DialogCell(mContext); - } - if (view instanceof DialogCell) { //TODO finally i need to find this crash - ((DialogCell) view).useSeparator = (i != getCount() - 1); - TLRPC.TL_dialog dialog = null; - if (serverOnly) { - dialog = MessagesController.getInstance().dialogsServerOnly.get(i); - } else { - dialog = MessagesController.getInstance().dialogs.get(i); - if (AndroidUtilities.isTablet()) { - if (dialog.id == openedDialogId) { - view.setBackgroundColor(0x0f000000); - } else { - view.setBackgroundColor(0); - } - } + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) { + if (viewHolder.getItemViewType() == 0) { + DialogCell cell = (DialogCell) viewHolder.itemView; + cell.useSeparator = (i != getItemCount() - 1); + TLRPC.TL_dialog dialog; + if (serverOnly) { + dialog = MessagesController.getInstance().dialogsServerOnly.get(i); + } else { + dialog = MessagesController.getInstance().dialogs.get(i); + if (AndroidUtilities.isTablet()) { + cell.setDialogSelected(dialog.id == openedDialogId); } - ((DialogCell) view).setDialog(dialog, i, serverOnly); } + cell.setDialog(dialog, i, serverOnly); } - - return view; } @Override @@ -132,26 +120,4 @@ public class DialogsAdapter extends BaseFragmentAdapter { } return 0; } - - @Override - public int getViewTypeCount() { - return 2; - } - - @Override - public boolean isEmpty() { - int count; - if (serverOnly) { - count = MessagesController.getInstance().dialogsServerOnly.size(); - } else { - count = MessagesController.getInstance().dialogs.size(); - } - if (count == 0 && MessagesController.getInstance().loadingDialogs) { - return true; - } - if (!MessagesController.getInstance().dialogsEndReached) { - count++; - } - return count == 0; - } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index 03497da97..0aae2b086 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -20,6 +20,7 @@ import org.telegram.android.LocaleController; import org.telegram.android.MessageObject; import org.telegram.android.MessagesController; import org.telegram.android.MessagesStorage; +import org.telegram.android.support.widget.RecyclerView; import org.telegram.messenger.ByteBufferDesc; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; @@ -27,7 +28,6 @@ import org.telegram.messenger.R; import org.telegram.messenger.RPCRequest; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; -import org.telegram.messenger.Utilities; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.GreySectionCell; import org.telegram.ui.Cells.HashtagSearchCell; @@ -42,7 +42,7 @@ import java.util.Locale; import java.util.Timer; import java.util.TimerTask; -public class DialogsSearchAdapter extends BaseSearchAdapter { +public class DialogsSearchAdapter extends BaseSearchAdapterRecycler { private Context mContext; private Timer searchTimer; @@ -59,6 +59,13 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { private String lastMessagesSearchString; private int lastSearchId = 0; + private class Holder extends RecyclerView.ViewHolder { + + public Holder(View itemView) { + super(itemView); + } + } + private class DialogSearchResult { public TLObject object; public int date; @@ -246,9 +253,9 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { user.status.expires = cursor.intValue(1); } if (found == 1) { - dialogSearchResult.name = Utilities.generateSearchName(user.first_name, user.last_name, q); + dialogSearchResult.name = AndroidUtilities.generateSearchName(user.first_name, user.last_name, q); } else { - dialogSearchResult.name = Utilities.generateSearchName("@" + user.username, null, "@" + q); + dialogSearchResult.name = AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q); } dialogSearchResult.object = user; resultCount++; @@ -281,7 +288,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { dialog_id = AndroidUtilities.makeBroadcastId(chat.id); } DialogSearchResult dialogSearchResult = dialogsResult.get(dialog_id); - dialogSearchResult.name = Utilities.generateSearchName(chat.title, null, q); + dialogSearchResult.name = AndroidUtilities.generateSearchName(chat.title, null, q); dialogSearchResult.object = chat; resultCount++; } @@ -345,7 +352,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { if (found == 1) { dialogSearchResult.name = AndroidUtilities.replaceTags("" + ContactsController.formatName(user.first_name, user.last_name) + ""); } else { - dialogSearchResult.name = Utilities.generateSearchName("@" + user.username, null, "@" + q); + dialogSearchResult.name = AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q); } dialogSearchResult.object = chat; encUsers.add(user); @@ -418,9 +425,9 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { user.status.expires = cursor.intValue(1); } if (found == 1) { - resultArrayNames.add(Utilities.generateSearchName(user.first_name, user.last_name, q)); + resultArrayNames.add(AndroidUtilities.generateSearchName(user.first_name, user.last_name, q)); } else { - resultArrayNames.add(Utilities.generateSearchName("@" + user.username, null, "@" + q)); + resultArrayNames.add(AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q)); } resultArray.add(user); } @@ -567,30 +574,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { } @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int i) { - if (!searchResultHashtags.isEmpty()) { - return i != 0; - } - int localCount = searchResult.size(); - int globalCount = globalSearch.isEmpty() ? 0 : globalSearch.size() + 1; - int messagesCount = searchResultMessages.isEmpty() ? 0 : searchResultMessages.size() + 1; - if (i >= 0 && i < localCount || i > localCount && i < globalCount + localCount) { - return true; - } else if (i > globalCount + localCount && i < globalCount + localCount + messagesCount) { - return true; - } else if (messagesCount != 0 && i == globalCount + localCount + messagesCount) { - return true; - } - return false; - } - - @Override - public int getCount() { + public int getItemCount() { if (!searchResultHashtags.isEmpty()) { return searchResultHashtags.size() + 1; } @@ -606,7 +590,6 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { return count; } - @Override public Object getItem(int i) { if (!searchResultHashtags.isEmpty()) { return searchResultHashtags.get(i - 1); @@ -630,96 +613,107 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { } @Override - public boolean hasStableIds() { - return true; + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = null; + switch (viewType) { + case 0: + view = new ProfileSearchCell(mContext); + view.setBackgroundResource(R.drawable.list_selector); + break; + case 1: + view = new GreySectionCell(mContext); + break; + case 2: + view = new DialogCell(mContext); + break; + case 3: + view = new LoadingCell(mContext); + break; + case 4: + view = new HashtagSearchCell(mContext); + break; + } + return new Holder(view); } @Override - public View getView(int i, View view, ViewGroup viewGroup) { - int type = getItemViewType(i); + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: { + ProfileSearchCell cell = (ProfileSearchCell) holder.itemView; - if (type == 1) { - if (view == null) { - view = new GreySectionCell(mContext); - } - if (!searchResultHashtags.isEmpty()) { - ((GreySectionCell) view).setText(LocaleController.getString("Hashtags", R.string.Hashtags).toUpperCase()); - } else if (!globalSearch.isEmpty() && i == searchResult.size()) { - ((GreySectionCell) view).setText(LocaleController.getString("GlobalSearch", R.string.GlobalSearch)); - } else { - ((GreySectionCell) view).setText(LocaleController.getString("SearchMessages", R.string.SearchMessages)); - } - } else if (type == 0) { - if (view == null) { - view = new ProfileSearchCell(mContext); - } + TLRPC.User user = null; + TLRPC.Chat chat = null; + TLRPC.EncryptedChat encryptedChat = null; - TLRPC.User user = null; - TLRPC.Chat chat = null; - TLRPC.EncryptedChat encryptedChat = null; + int localCount = searchResult.size(); + int globalCount = globalSearch.isEmpty() ? 0 : globalSearch.size() + 1; - int localCount = searchResult.size(); - int globalCount = globalSearch.isEmpty() ? 0 : globalSearch.size() + 1; - - ((ProfileSearchCell) view).useSeparator = (i != getCount() - 1 && i != localCount - 1 && i != localCount + globalCount - 1); - Object obj = getItem(i); - if (obj instanceof TLRPC.User) { - /*user = MessagesController.getInstance().getUser(((TLRPC.User) obj).id); - if (user == null) { + cell.useSeparator = (position != getItemCount() - 1 && position != localCount - 1 && position != localCount + globalCount - 1); + Object obj = getItem(position); + if (obj instanceof TLRPC.User) { user = (TLRPC.User) obj; - }*/ - user = (TLRPC.User) obj; - } else if (obj instanceof TLRPC.Chat) { - chat = MessagesController.getInstance().getChat(((TLRPC.Chat) obj).id); - } else if (obj instanceof TLRPC.EncryptedChat) { - encryptedChat = MessagesController.getInstance().getEncryptedChat(((TLRPC.EncryptedChat) obj).id); - user = MessagesController.getInstance().getUser(encryptedChat.user_id); - } + } else if (obj instanceof TLRPC.Chat) { + chat = MessagesController.getInstance().getChat(((TLRPC.Chat) obj).id); + } else if (obj instanceof TLRPC.EncryptedChat) { + encryptedChat = MessagesController.getInstance().getEncryptedChat(((TLRPC.EncryptedChat) obj).id); + user = MessagesController.getInstance().getUser(encryptedChat.user_id); + } - CharSequence username = null; - CharSequence name = null; - if (i < searchResult.size()) { - name = searchResultNames.get(i); - if (name != null && user != null && user.username != null && user.username.length() > 0) { - if (name.toString().startsWith("@" + user.username)) { - username = name; - name = null; + CharSequence username = null; + CharSequence name = null; + if (position < searchResult.size()) { + name = searchResultNames.get(position); + if (name != null && user != null && user.username != null && user.username.length() > 0) { + if (name.toString().startsWith("@" + user.username)) { + username = name; + name = null; + } + } + } else if (position > searchResult.size() && user != null && user.username != null) { + String foundUserName = lastFoundUsername; + if (foundUserName.startsWith("@")) { + foundUserName = foundUserName.substring(1); + } + try { + username = AndroidUtilities.replaceTags(String.format("@%s%s", user.username.substring(0, foundUserName.length()), user.username.substring(foundUserName.length()))); + } catch (Exception e) { + username = user.username; + FileLog.e("tmessages", e); } } - } else if (i > searchResult.size() && user != null && user.username != null) { - String foundUserName = lastFoundUsername; - if (foundUserName.startsWith("@")) { - foundUserName = foundUserName.substring(1); - } - try { - username = AndroidUtilities.replaceTags(String.format("@%s%s", user.username.substring(0, foundUserName.length()), user.username.substring(foundUserName.length()))); - } catch (Exception e) { - username = user.username; - FileLog.e("tmessages", e); - } - } - ((ProfileSearchCell) view).setData(user, chat, encryptedChat, name, username); - } else if (type == 2) { - if (view == null) { - view = new DialogCell(mContext); + cell.setData(user, chat, encryptedChat, name, username); + break; } - ((DialogCell) view).useSeparator = (i != getCount() - 1); - MessageObject messageObject = (MessageObject)getItem(i); - ((DialogCell) view).setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date); - } else if (type == 3) { - if (view == null) { - view = new LoadingCell(mContext); + case 1: { + GreySectionCell cell = (GreySectionCell) holder.itemView; + if (!searchResultHashtags.isEmpty()) { + cell.setText(LocaleController.getString("Hashtags", R.string.Hashtags).toUpperCase()); + } else if (!globalSearch.isEmpty() && position == searchResult.size()) { + cell.setText(LocaleController.getString("GlobalSearch", R.string.GlobalSearch)); + } else { + cell.setText(LocaleController.getString("SearchMessages", R.string.SearchMessages)); + } + break; } - } else if (type == 4) { - if (view == null) { - view = new HashtagSearchCell(mContext); + case 2: { + DialogCell cell = (DialogCell) holder.itemView; + cell.useSeparator = (position != getItemCount() - 1); + MessageObject messageObject = (MessageObject)getItem(position); + cell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date); + break; + } + case 3: { + break; + } + case 4: { + HashtagSearchCell cell = (HashtagSearchCell) holder.itemView; + cell.setText(searchResultHashtags.get(position - 1)); + cell.setNeedDivider(position != searchResultHashtags.size()); + break; } - ((HashtagSearchCell) view).setText(searchResultHashtags.get(i - 1)); - ((HashtagSearchCell) view).setNeedDivider(i != searchResultHashtags.size()); } - - return view; } @Override @@ -739,14 +733,4 @@ public class DialogsSearchAdapter extends BaseSearchAdapter { } return 1; } - - @Override - public int getViewTypeCount() { - return 5; - } - - @Override - public boolean isEmpty() { - return searchResult.isEmpty() && globalSearch.isEmpty() && searchResultMessages.isEmpty() && searchResultHashtags.isEmpty(); - } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java index cf7ce7c1f..9894b9592 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -138,9 +138,9 @@ public class SearchAdapter extends BaseSearchAdapter { if (found != 0) { if (found == 1) { - resultArrayNames.add(Utilities.generateSearchName(user.first_name, user.last_name, q)); + resultArrayNames.add(AndroidUtilities.generateSearchName(user.first_name, user.last_name, q)); } else { - resultArrayNames.add(Utilities.generateSearchName("@" + user.username, null, "@" + q)); + resultArrayNames.add(AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q)); } resultArray.add(user); break; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java index 2acda7a59..38bb738f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -12,20 +12,11 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; -import org.telegram.SQLite.SQLiteCursor; -import org.telegram.SQLite.SQLitePreparedStatement; -import org.telegram.android.AndroidUtilities; -import org.telegram.android.MessagesStorage; import org.telegram.android.NotificationCenter; +import org.telegram.android.query.StickersQuery; import org.telegram.android.support.widget.RecyclerView; -import org.telegram.messenger.ByteBufferDesc; -import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLoader; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.RPCRequest; -import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; -import org.telegram.messenger.Utilities; import org.telegram.ui.Cells.StickerCell; import java.io.File; @@ -34,11 +25,6 @@ import java.util.HashMap; public class StickersAdapter extends RecyclerView.Adapter implements NotificationCenter.NotificationCenterDelegate { - private static boolean loadingStickers; - private static String hash = ""; - private static int loadDate = 0; - private static HashMap> allStickers; - private Context mContext; private ArrayList stickers; private ArrayList stickersToLoad = new ArrayList<>(); @@ -60,9 +46,7 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio public StickersAdapter(Context context, StickersAdapterDelegate delegate) { mContext = context; this.delegate = delegate; - if (!loadingStickers && (allStickers == null || loadDate < (System.currentTimeMillis() / 1000 - 60 * 60))) { - loadStickers(true); - } + StickersQuery.checkStickers(); NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidLoaded); NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailedLoad); } @@ -75,64 +59,13 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio @Override public void didReceivedNotification(int id, final Object... args) { if (id == NotificationCenter.FileDidLoaded || id == NotificationCenter.FileDidFailedLoad) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (stickers != null && !stickers.isEmpty() && !stickersToLoad.isEmpty() && visible) { - String fileName = (String) args[0]; - stickersToLoad.remove(fileName); - if (stickersToLoad.isEmpty()) { - delegate.needChangePanelVisibility(stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty()); - } - } + if (stickers != null && !stickers.isEmpty() && !stickersToLoad.isEmpty() && visible) { + String fileName = (String) args[0]; + stickersToLoad.remove(fileName); + if (stickersToLoad.isEmpty()) { + delegate.needChangePanelVisibility(stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty()); } - }); - } - } - - private void loadStickers(boolean cache) { - if (loadingStickers) { - return; - } - loadingStickers = true; - if (cache) { - MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { - @Override - public void run() { - TLRPC.messages_AllStickers result = null; - int date = 0; - try { - SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT data, date FROM stickers WHERE 1"); - ArrayList loadedUsers = new ArrayList<>(); - if (cursor.next()) { - ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); - if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { - result = TLRPC.messages_AllStickers.TLdeserialize(data, data.readInt32(false), false); - } - date = cursor.intValue(1); - MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); - } - cursor.dispose(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - processLoadedStickers(result, true, date); - } - }); - } else { - TLRPC.TL_messages_getAllStickers req = new TLRPC.TL_messages_getAllStickers(); - req.hash = hash; - ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(final TLObject response, final TLRPC.TL_error error) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - processLoadedStickers((TLRPC.messages_AllStickers) response, false, (int)(System.currentTimeMillis() / 1000)); - } - }); - } - }); + } } } @@ -144,109 +77,20 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio int size = Math.min(10, stickers.size()); for (int a = 0; a < size; a++) { TLRPC.Document document = stickers.get(a); - File f = FileLoader.getPathToAttach(document.thumb, true); + File f = FileLoader.getPathToAttach(document.thumb, "webp", true); if (!f.exists()) { - stickersToLoad.add(FileLoader.getAttachFileName(document.thumb)); - FileLoader.getInstance().loadFile(document.thumb.location, 0, true); + stickersToLoad.add(FileLoader.getAttachFileName(document.thumb, "webp")); + FileLoader.getInstance().loadFile(document.thumb.location, "webp", 0, true); } } return stickersToLoad.isEmpty(); } - private void putStickersToCache(final TLRPC.TL_messages_allStickers stickers) { - MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { - @Override - public void run() { - try { - SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO stickers VALUES(?, ?, ?)"); - state.requery(); - ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(stickers.getObjectSize()); - stickers.serializeToStream(data); - state.bindInteger(1, 1); - state.bindByteBuffer(2, data.buffer); - state.bindInteger(3, (int) (System.currentTimeMillis() / 1000)); - state.step(); - MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); - state.dispose(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - }); - } - - private void processLoadedStickers(final TLRPC.messages_AllStickers res, final boolean cache, final int date) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - loadingStickers = false; - } - }); - Utilities.stageQueue.postRunnable(new Runnable() { - @Override - public void run() { - if ((res == null || date < (int) (System.currentTimeMillis() / 1000 - 60 * 60)) && cache) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - loadStickers(false); - } - }); - if (res == null) { - return; - } - } - if (res instanceof TLRPC.TL_messages_allStickers) { - if (!cache) { - putStickersToCache((TLRPC.TL_messages_allStickers) res); - } - HashMap documents = new HashMap<>(); - for (TLRPC.Document document : res.documents) { - if (document == null) { - continue; - } - documents.put(document.id, document); - if (document.thumb != null && document.thumb.location != null) { - document.thumb.location.ext = "webp"; - } - } - final HashMap> result = new HashMap<>(); - for (TLRPC.TL_stickerPack stickerPack : res.packs) { - if (stickerPack != null && stickerPack.emoticon != null) { - stickerPack.emoticon = stickerPack.emoticon.replace("\uFE0F", ""); - ArrayList arrayList = result.get(stickerPack.emoticon); - for (Long id : stickerPack.documents) { - TLRPC.Document document = documents.get(id); - if (document != null) { - if (arrayList == null) { - arrayList = new ArrayList<>(); - result.put(stickerPack.emoticon, arrayList); - } - arrayList.add(document); - } - } - } - } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - allStickers = result; - hash = res.hash; - loadDate = date; - if (lastSticker != null) { - loadStikersForEmoji(lastSticker); - } - } - }); - } - } - }); - } - public void loadStikersForEmoji(CharSequence emoji) { boolean search = emoji != null && emoji.length() != 0 && emoji.length() <= 2; if (search) { lastSticker = emoji.toString(); + HashMap> allStickers = StickersQuery.getAllStickers(); if (allStickers != null) { ArrayList newStickers = allStickers.get(lastSticker); if (stickers != null && newStickers == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java index b0c4d1434..1c1699d13 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java @@ -98,12 +98,7 @@ public class BlockedUsersActivity extends BaseFragment implements NotificationCe emptyTextView.setGravity(Gravity.CENTER); emptyTextView.setVisibility(View.INVISIBLE); emptyTextView.setText(LocaleController.getString("NoBlocked", R.string.NoBlocked)); - frameLayout.addView(emptyTextView); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) emptyTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.gravity = Gravity.TOP; - emptyTextView.setLayoutParams(layoutParams); + frameLayout.addView(emptyTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); emptyTextView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -112,19 +107,10 @@ public class BlockedUsersActivity extends BaseFragment implements NotificationCe }); progressView = new FrameLayout(context); - frameLayout.addView(progressView); - layoutParams = (FrameLayout.LayoutParams) progressView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - progressView.setLayoutParams(layoutParams); + frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); ProgressBar progressBar = new ProgressBar(context); - progressView.addView(progressBar); - layoutParams = (FrameLayout.LayoutParams) progressView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.CENTER; - progressView.setLayoutParams(layoutParams); + progressView.addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); listView = new ListView(context); listView.setEmptyView(emptyTextView); @@ -135,11 +121,7 @@ public class BlockedUsersActivity extends BaseFragment implements NotificationCe if (Build.VERSION.SDK_INT >= 11) { listView.setVerticalScrollbarPosition(LocaleController.isRTL ? ListView.SCROLLBAR_POSITION_LEFT : ListView.SCROLLBAR_POSITION_RIGHT); } - frameLayout.addView(listView); - layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - listView.setLayoutParams(layoutParams); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -170,7 +152,7 @@ public class BlockedUsersActivity extends BaseFragment implements NotificationCe } } }); - showAlertDialog(builder); + showDialog(builder.create()); return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index ce31697b2..12c749222 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -98,11 +98,11 @@ public class ChatActionCell extends BaseCell { } avatarDrawable.setInfo(id, null, null, false); if (currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { - imageReceiver.setImage(currentMessageObject.messageOwner.action.newUserPhoto.photo_small, "50_50", avatarDrawable, false); + imageReceiver.setImage(currentMessageObject.messageOwner.action.newUserPhoto.photo_small, "50_50", avatarDrawable, null, false); } else { TLRPC.PhotoSize photo = FileLoader.getClosestPhotoSizeWithSize(currentMessageObject.photoThumbs, AndroidUtilities.dp(64)); if (photo != null) { - imageReceiver.setImage(photo.location, "50_50", avatarDrawable, false); + imageReceiver.setImage(photo.location, "50_50", avatarDrawable, null, false); } else { imageReceiver.setImageBitmap(avatarDrawable); } @@ -225,7 +225,7 @@ public class ChatActionCell extends BaseCell { try { int linesCount = textLayout.getLineCount(); for (int a = 0; a < linesCount; a++) { - float lineWidth = 0; + float lineWidth; float lineLeft = 0; try { lineWidth = textLayout.getLineWidth(a); @@ -257,7 +257,7 @@ public class ChatActionCell extends BaseCell { return; } - Drawable backgroundDrawable = null; + Drawable backgroundDrawable; if (ApplicationLoader.isCustomTheme()) { backgroundDrawable = ResourceLoader.backgroundBlack; } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java index 09bc6fcd1..66862c623 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java @@ -165,7 +165,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega seekBar.setProgress(currentMessageObject.audioProgress); } - int duration = 0; + int duration; if (!MediaController.getInstance().isPlayingAudio(currentMessageObject)) { duration = currentMessageObject.messageOwner.media.audio.duration; } else { @@ -307,11 +307,6 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega backgroundWidth = Math.min(AndroidUtilities.displaySize.x - AndroidUtilities.dp(isChat ? 102 : 50), AndroidUtilities.dp(300)); } - int uid = messageObject.messageOwner.media.audio.user_id; - if (uid == 0) { - uid = messageObject.messageOwner.from_id; - } - if (messageObject.isOut()) { seekBar.type = 0; progressView.setProgressColors(0xffb4e396, 0xff6ac453); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java index 72589d5d0..5b8f96c46 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java @@ -47,6 +47,7 @@ public class ChatBaseCell extends BaseCell { void didLongPressed(ChatBaseCell cell); void didPressReplyMessage(ChatBaseCell cell, int id); void didPressUrl(String url); + void needOpenWebView(String url, String title, String originalUrl, int w, int h); boolean canPerformActions(); } @@ -196,6 +197,9 @@ public class ChatBaseCell extends BaseCell { replyTextPaint.linkColor = 0xff316f9f; replyLinePaint = new Paint(); + + urlPaint = new Paint(); + urlPaint.setColor(0x33316f9f); } avatarImage = new ImageReceiver(this); avatarImage.setRoundRadius(AndroidUtilities.dp(21)); @@ -347,7 +351,7 @@ public class ChatBaseCell extends BaseCell { currentPhoto = null; avatarDrawable.setInfo(messageObject.messageOwner.from_id, null, null, false); } - avatarImage.setImage(currentPhoto, "50_50", avatarDrawable, false); + avatarImage.setImage(currentPhoto, "50_50", avatarDrawable, null, false); } if (!media) { @@ -461,7 +465,7 @@ public class ChatBaseCell extends BaseCell { needReplyImage = false; } else { currentReplyPhoto = photoSize.location; - replyImageReceiver.setImage(photoSize.location, "50_50", null, true); + replyImageReceiver.setImage(photoSize.location, "50_50", null, null, true); needReplyImage = true; maxWidth -= AndroidUtilities.dp(44); } @@ -653,7 +657,7 @@ public class ChatBaseCell extends BaseCell { avatarImage.draw(canvas); } - Drawable currentBackgroundDrawable = null; + Drawable currentBackgroundDrawable; if (currentMessageObject.isOut()) { if (isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted) { if (!media) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java index 45907c708..129348b60 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java @@ -195,7 +195,7 @@ public class ChatContactCell extends ChatBaseCell { currentPhoto = null; avatarDrawable.setInfo(uid, null, null, false); } - avatarImage.setImage(currentPhoto, "50_50", avatarDrawable, false); + avatarImage.setImage(currentPhoto, "50_50", avatarDrawable, null, false); String currentNameString = ContactsController.formatName(messageObject.messageOwner.media.first_name, messageObject.messageOwner.media.last_name); int nameWidth = Math.min((int) Math.ceil(namePaint.measureText(currentNameString)), maxWidth); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java index 69cd4052c..df409c4b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java @@ -34,7 +34,6 @@ import org.telegram.android.MediaController; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; -import org.telegram.messenger.Utilities; import org.telegram.android.MessageObject; import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.Components.ResourceLoader; @@ -407,7 +406,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD cancelLoading = false; radialProgress.setProgress(0, false); if (currentMessageObject.type == 1) { - photoImage.setImage(currentPhotoObject.location, currentPhotoFilter, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, currentPhotoFilter, currentPhotoObject.size, false); + photoImage.setImage(currentPhotoObject.location, currentPhotoFilter, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, currentPhotoFilter, currentPhotoObject.size, null, false); } else if (currentMessageObject.type == 8 || currentMessageObject.type == 9) { FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true, false); lastDownloadedGifMessage = currentMessageObject; @@ -527,7 +526,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } ext = ext.toUpperCase(); - String str = Utilities.formatFileSize(messageObject.messageOwner.media.document.size) + " " + ext; + String str = AndroidUtilities.formatFileSize(messageObject.messageOwner.media.document.size) + " " + ext; if (currentInfoString == null || !currentInfoString.equals(str)) { currentInfoString = str; @@ -539,7 +538,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } else if (messageObject.type == 8) { gifDrawable = MediaController.getInstance().getGifDrawable(this, false); - String str = Utilities.formatFileSize(messageObject.messageOwner.media.document.size); + String str = AndroidUtilities.formatFileSize(messageObject.messageOwner.media.document.size); if (currentInfoString == null || !currentInfoString.equals(str)) { currentInfoString = str; infoOffset = 0; @@ -552,7 +551,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD int duration = messageObject.messageOwner.media.video.duration; int minutes = duration / 60; int seconds = duration - minutes * 60; - String str = String.format("%d:%02d, %s", minutes, seconds, Utilities.formatFileSize(messageObject.messageOwner.media.video.size)); + String str = String.format("%d:%02d, %s", minutes, seconds, AndroidUtilities.formatFileSize(messageObject.messageOwner.media.video.size)); if (currentInfoString == null || !currentInfoString.equals(str)) { currentInfoString = str; infoOffset = ResourceLoader.videoIconDrawable.getIntrinsicWidth() + AndroidUtilities.dp(4); @@ -578,7 +577,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD photoImage.setParentMessageObject(messageObject); if (currentPhotoObject != null) { currentPhotoFilter = String.format(Locale.US, "%d_%d_b", photoWidth, photoHeight); - photoImage.setImage(null, null, null, null, currentPhotoObject.location, currentPhotoFilter, 0, true); + photoImage.setImage(null, null, null, null, currentPhotoObject.location, currentPhotoFilter, 0, null, true); } else { photoImage.setImageBitmap((BitmapDrawable) null); } @@ -605,7 +604,6 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD maxWidth = (int) Math.max(maxWidth, nameLayout.getLineWidth(a) + AndroidUtilities.dp(16)); } if (infoLayout != null) { - lineCount = infoLayout.getLineCount(); for (int a = 0; a < infoLayout.getLineCount(); a++) { maxWidth = (int) Math.max(maxWidth, infoLayout.getLineWidth(a) + AndroidUtilities.dp(16)); } @@ -622,7 +620,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD photoImage.setNeedsQualityThumb(false); photoImage.setShouldGenerateQualityThumb(false); photoImage.setParentMessageObject(null); - photoImage.setImage(currentUrl, null, messageObject.isOut() ? ResourceLoader.geoOutDrawable : ResourceLoader.geoInDrawable, 0); + photoImage.setImage(currentUrl, null, messageObject.isOut() ? ResourceLoader.geoOutDrawable : ResourceLoader.geoInDrawable, null, 0); } else if (messageObject.type == 13) { //webp drawBackground = false; for (TLRPC.DocumentAttribute attribute : messageObject.messageOwner.media.document.attributes) { @@ -664,7 +662,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD null, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, "b1", - messageObject.messageOwner.media.document.size, true); + messageObject.messageOwner.media.document.size, "webp", true); } } else if (messageObject.messageOwner.media.document.id != 0) { photoImage.setImage(messageObject.messageOwner.media.document, null, @@ -672,7 +670,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD null, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, "b1", - messageObject.messageOwner.media.document.size, true); + messageObject.messageOwner.media.document.size, "webp", true); } } else { if (AndroidUtilities.isTablet()) { @@ -803,22 +801,22 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD if (photoExist || MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO) || FileLoader.getInstance().isLoadingFile(fileName)) { if (allowedToSetPhoto || ImageLoader.getInstance().getImageFromMemory(currentPhotoObject.location, null, currentPhotoFilter) != null) { allowedToSetPhoto = true; - photoImage.setImage(currentPhotoObject.location, currentPhotoFilter, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, currentPhotoFilter, noSize ? 0 : currentPhotoObject.size, false); + photoImage.setImage(currentPhotoObject.location, currentPhotoFilter, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, currentPhotoFilter, noSize ? 0 : currentPhotoObject.size, null, false); } else if (currentPhotoObjectThumb != null) { - photoImage.setImage(null, null, currentPhotoObjectThumb.location, currentPhotoFilter, 0, false); + photoImage.setImage(null, null, currentPhotoObjectThumb.location, currentPhotoFilter, 0, null, false); } else { photoImage.setImageBitmap((Drawable) null); } } else { photoNotSet = true; if (currentPhotoObjectThumb != null) { - photoImage.setImage(null, null, currentPhotoObjectThumb.location, currentPhotoFilter, 0, false); + photoImage.setImage(null, null, currentPhotoObjectThumb.location, currentPhotoFilter, 0, null, false); } else { photoImage.setImageBitmap((Drawable) null); } } } else { - photoImage.setImage(null, null, currentPhotoObject.location, currentPhotoFilter, 0, false); + photoImage.setImage(null, null, currentPhotoObject.location, currentPhotoFilter, 0, null, false); } } else { photoImage.setImageBitmap((Bitmap) null); @@ -998,7 +996,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD radialProgress.setHideCurrentDrawable(false); if (currentMessageObject.type == 9) { - Drawable menuDrawable = null; + Drawable menuDrawable; if (currentMessageObject.isOut()) { infoPaint.setColor(0xff70b15c); docBackPaint.setColor(0xffdaf5c3); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 00a9477a4..8e5924c37 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -14,6 +14,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Build; import android.provider.Browser; import android.text.Layout; import android.text.Spannable; @@ -36,6 +37,7 @@ import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.Components.StaticLayoutEx; import org.telegram.ui.Components.URLSpanNoUnderline; +import java.io.File; import java.util.Locale; public class ChatMessageCell extends ChatBaseCell { @@ -56,6 +58,9 @@ public class ChatMessageCell extends ChatBaseCell { private boolean isInstagram; private int descriptionY; private int durationWidth; + private int descriptionX; + private int titleX; + private int authorX; private StaticLayout siteNameLayout; private StaticLayout titleLayout; private StaticLayout descriptionLayout; @@ -69,10 +74,6 @@ public class ChatMessageCell extends ChatBaseCell { super(context); drawForwardedName = true; linkImageView = new ImageReceiver(this); - if (urlPaint == null) { - urlPaint = new Paint(); - urlPaint.setColor(0x33316f9f); - } } @Override @@ -152,7 +153,7 @@ public class ChatMessageCell extends ChatBaseCell { } else { if (descriptionLayout != null && y >= descriptionY) { try { - x -= textX + AndroidUtilities.dp(10); + x -= textX + AndroidUtilities.dp(10) + descriptionX; y -= descriptionY; final int line = descriptionLayout.getLineForVertical(y); final int off = descriptionLayout.getOffsetForHorizontal(line, x); @@ -191,10 +192,15 @@ public class ChatMessageCell extends ChatBaseCell { if (pressedLink != null) { pressedLink.onClick(this); } else { - Uri uri = Uri.parse(currentMessageObject.messageOwner.media.webpage.url); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName()); - getContext().startActivity(intent); + TLRPC.WebPage webPage = currentMessageObject.messageOwner.media.webpage; + if (Build.VERSION.SDK_INT >= 16 && webPage.embed_url != null && webPage.embed_url.length() != 0) { + delegate.needOpenWebView(webPage.embed_url, webPage.site_name, webPage.url, webPage.embed_width, webPage.embed_height); + } else { + Uri uri = Uri.parse(webPage.url); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + intent.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName()); + getContext().startActivity(intent); + } } } catch (Exception e) { FileLog.e("tmessages", e); @@ -260,6 +266,9 @@ public class ChatMessageCell extends ChatBaseCell { int addedChars = 0; StaticLayout layout = new StaticLayout(text, paint, smallWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); for (int a = 0; a < linesCount; a++) { + if (layout.getLineLeft(a) != 0) { + maxWidth = smallWidth; + } int pos = layout.getLineEnd(a); if (pos == text.length()) { break; @@ -348,6 +357,7 @@ public class ChatMessageCell extends ChatBaseCell { maxChildWidth = Math.max(maxChildWidth, forwardedNameWidth); maxChildWidth = Math.max(maxChildWidth, replyNameWidth); maxChildWidth = Math.max(maxChildWidth, replyTextWidth); + int maxWebWidth = 0; int timeMore = timeWidth + AndroidUtilities.dp(6); if (messageObject.isOut()) { @@ -387,9 +397,7 @@ public class ChatMessageCell extends ChatBaseCell { currentMessageObject.generateThumbs(true); } - if (MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)) { - isSmallImage = webPage.description != null && webPage.type != null && (webPage.type.equals("app") || webPage.type.equals("profile") || webPage.type.equals("article")) && currentMessageObject.photoThumbs != null; - } + isSmallImage = webPage.description != null && webPage.type != null && (webPage.type.equals("app") || webPage.type.equals("profile") || webPage.type.equals("article")) && currentMessageObject.photoThumbs != null; if (webPage.site_name != null) { try { @@ -399,35 +407,54 @@ public class ChatMessageCell extends ChatBaseCell { linkPreviewHeight += height; totalHeight += height; additionalHeight += height; + width = siteNameLayout.getWidth(); maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); + maxWebWidth = Math.max(maxWebWidth, width + additinalWidth); } catch (Exception e) { FileLog.e("tmessages", e); } } + boolean titleIsRTL = false; if (webPage.title != null) { try { + titleX = 0; if (linkPreviewHeight != 0) { linkPreviewHeight += AndroidUtilities.dp(2); totalHeight += AndroidUtilities.dp(2); } int restLines = 0; if (!isSmallImage || webPage.description == null) { - titleLayout = StaticLayoutEx.createStaticLayout(webPage.title, replyNamePaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, AndroidUtilities.dp(1), false, TextUtils.TruncateAt.END, linkPreviewMaxWidth, 2); + titleLayout = StaticLayoutEx.createStaticLayout(webPage.title, replyNamePaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, AndroidUtilities.dp(1), false, TextUtils.TruncateAt.END, linkPreviewMaxWidth, 4); } else { restLines = restLinesCount; - titleLayout = generateStaticLayout(webPage.title, replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - AndroidUtilities.dp(48 + 2), restLinesCount, 2); + titleLayout = generateStaticLayout(webPage.title, replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - AndroidUtilities.dp(48 + 2), restLinesCount, 4); restLinesCount -= titleLayout.getLineCount(); } int height = titleLayout.getLineBottom(titleLayout.getLineCount() - 1); linkPreviewHeight += height; totalHeight += height; for (int a = 0; a < titleLayout.getLineCount(); a++) { - int width = (int) Math.ceil(titleLayout.getLineWidth(a)); - if (a < restLines) { + int lineLeft = (int) titleLayout.getLineLeft(a); + if (lineLeft != 0) { + titleIsRTL = true; + if (titleX == 0) { + titleX = -lineLeft; + } else { + titleX = Math.max(titleX, -lineLeft); + } + } + int width; + if (lineLeft != 0) { + width = titleLayout.getWidth() - lineLeft; + } else { + width = (int) Math.ceil(titleLayout.getLineWidth(a)); + } + if (a < restLines || lineLeft != 0 && isSmallImage) { width += AndroidUtilities.dp(48 + 2); } maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); + maxWebWidth = Math.max(maxWebWidth, width + additinalWidth); } } catch (Exception e) { FileLog.e("tmessages", e); @@ -450,7 +477,10 @@ public class ChatMessageCell extends ChatBaseCell { int height = authorLayout.getLineBottom(authorLayout.getLineCount() - 1); linkPreviewHeight += height; totalHeight += height; + int lineLeft = (int) authorLayout.getLineLeft(0); + authorX = -lineLeft; maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); + maxWebWidth = Math.max(maxWebWidth, width + additinalWidth); } catch (Exception e) { FileLog.e("tmessages", e); } @@ -458,6 +488,7 @@ public class ChatMessageCell extends ChatBaseCell { if (webPage.description != null) { try { + descriptionX = 0; currentMessageObject.generateLinkDescription(); if (linkPreviewHeight != 0) { linkPreviewHeight += AndroidUtilities.dp(2); @@ -474,10 +505,28 @@ public class ChatMessageCell extends ChatBaseCell { linkPreviewHeight += height; totalHeight += height; for (int a = 0; a < descriptionLayout.getLineCount(); a++) { - int width = (int) Math.ceil(descriptionLayout.getLineWidth(a)); - if (a < restLines) { + int lineLeft = (int) Math.ceil(descriptionLayout.getLineLeft(a)); + if (descriptionX == 0) { + descriptionX = -lineLeft; + } else { + descriptionX = Math.max(descriptionX, -lineLeft); + } + + int width; + if (lineLeft != 0) { + width = descriptionLayout.getWidth() - lineLeft; + } else { + width = (int) Math.ceil(descriptionLayout.getLineWidth(a)); + } + if (a < restLines || lineLeft != 0 && isSmallImage) { width += AndroidUtilities.dp(48 + 2); } + if (maxWebWidth < width + additinalWidth) { + if (titleIsRTL) { + titleX += (width + additinalWidth - maxWebWidth); + } + maxWebWidth = width + additinalWidth; + } maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); } } catch (Exception e) { @@ -485,7 +534,7 @@ public class ChatMessageCell extends ChatBaseCell { } } - if (webPage.photo != null && MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)) { + if (webPage.photo != null) { boolean smallImage = webPage.type != null && (webPage.type.equals("app") || webPage.type.equals("profile") || webPage.type.equals("article")); if (smallImage && descriptionLayout != null && descriptionLayout.getLineCount() == 1) { smallImage = false; @@ -537,7 +586,26 @@ public class ChatMessageCell extends ChatBaseCell { } linkImageView.setImageCoords(0, 0, width, height); - linkImageView.setImage(currentPhotoObject.location, String.format(Locale.US, "%d_%d", width, height), currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, String.format(Locale.US, "%d_%d_b", width, height), 0, false); + + String fileName = FileLoader.getAttachFileName(currentPhotoObject); + + boolean photoExist = true; + File cacheFile = FileLoader.getPathToAttach(currentPhotoObject, true); + if (!cacheFile.exists()) { + photoExist = false; + } + + String filter = String.format(Locale.US, "%d_%d", width, height); + + if (photoExist || MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO) || FileLoader.getInstance().isLoadingFile(fileName)) { + linkImageView.setImage(currentPhotoObject.location, filter, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, String.format(Locale.US, "%d_%d_b", width, height), 0, null, false); + } else { + if (currentPhotoObjectThumb != null) { + linkImageView.setImage(null, null, currentPhotoObjectThumb.location, String.format(Locale.US, "%d_%d_b", width, height), 0, null, false); + } else { + linkImageView.setImageBitmap((Drawable) null); + } + } drawLinkImageView = true; if (webPage.site_name != null) { @@ -659,7 +727,7 @@ public class ChatMessageCell extends ChatBaseCell { replyNamePaint.setColor(0xff000000); smallImageStartY = linkPreviewY - AndroidUtilities.dp(1); canvas.save(); - canvas.translate(textX + AndroidUtilities.dp(10), linkPreviewY - AndroidUtilities.dp(3)); + canvas.translate(textX + AndroidUtilities.dp(10) + titleX, linkPreviewY - AndroidUtilities.dp(3)); titleLayout.draw(canvas); canvas.restore(); linkPreviewY += titleLayout.getLineBottom(titleLayout.getLineCount() - 1); @@ -674,7 +742,7 @@ public class ChatMessageCell extends ChatBaseCell { } replyNamePaint.setColor(0xff000000); canvas.save(); - canvas.translate(textX + AndroidUtilities.dp(10), linkPreviewY - AndroidUtilities.dp(3)); + canvas.translate(textX + AndroidUtilities.dp(10) + authorX, linkPreviewY - AndroidUtilities.dp(3)); authorLayout.draw(canvas); canvas.restore(); linkPreviewY += authorLayout.getLineBottom(authorLayout.getLineCount() - 1); @@ -690,7 +758,7 @@ public class ChatMessageCell extends ChatBaseCell { replyTextPaint.setColor(0xff000000); descriptionY = linkPreviewY - AndroidUtilities.dp(3); canvas.save(); - canvas.translate(textX + AndroidUtilities.dp(10), descriptionY); + canvas.translate(textX + AndroidUtilities.dp(10) + descriptionX, descriptionY); if (pressedLink != null && linkBlockNum == -10) { canvas.drawPath(urlPath, urlPaint); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index 10f96292c..41a469e9e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -12,10 +12,12 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; +import android.os.Build; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.view.MotionEvent; import org.telegram.android.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; @@ -52,6 +54,7 @@ public class DialogCell extends BaseCell { private static Drawable muteDrawable; private static Paint linePaint; + private static Paint backPaint; private long currentDialogId; private boolean isDialogCell; @@ -74,7 +77,6 @@ public class DialogCell extends BaseCell { public boolean useSeparator = false; - private int nameLeft; private StaticLayout nameLayout; private boolean drawNameLock; @@ -111,7 +113,11 @@ public class DialogCell extends BaseCell { private int avatarTop = AndroidUtilities.dp(10); - private void init() { + private boolean isSelected; + + public DialogCell(Context context) { + super(context); + if (namePaint == null) { namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); namePaint.setTextSize(AndroidUtilities.dp(17)); @@ -136,6 +142,9 @@ public class DialogCell extends BaseCell { linePaint = new Paint(); linePaint.setColor(0xffdcdcdc); + backPaint = new Paint(); + backPaint.setColor(0x0f000000); + messagePrintingPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); messagePrintingPaint.setTextSize(AndroidUtilities.dp(16)); messagePrintingPaint.setColor(0xff4d83b3); @@ -159,11 +168,9 @@ public class DialogCell extends BaseCell { broadcastDrawable = getResources().getDrawable(R.drawable.list_broadcast); muteDrawable = getResources().getDrawable(R.drawable.mute_grey); } - } - public DialogCell(Context context) { - super(context); - init(); + setBackgroundResource(R.drawable.list_selector); + avatarImage = new ImageReceiver(this); avatarImage.setRoundRadius(AndroidUtilities.dp(26)); avatarDrawable = new AvatarDrawable(); @@ -208,7 +215,7 @@ public class DialogCell extends BaseCell { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(72)); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(72) + (useSeparator ? 1 : 0)); } @Override @@ -222,6 +229,16 @@ public class DialogCell extends BaseCell { } } + @Override + public boolean onTouchEvent(MotionEvent event) { + if (Build.VERSION.SDK_INT >= 21 && getBackground() != null) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { + getBackground().setHotspot(event.getX(), event.getY()); + } + } + return super.onTouchEvent(event); + } + public void buildLayout() { String nameString = ""; String timeString = ""; @@ -568,8 +585,8 @@ public class DialogCell extends BaseCell { FileLog.e("tmessages", e); } - double widthpx = 0; - float left = 0; + double widthpx; + float left; if (LocaleController.isRTL) { if (nameLayout != null && nameLayout.getLineCount() > 0) { left = nameLayout.getLineLeft(0); @@ -617,6 +634,13 @@ public class DialogCell extends BaseCell { } } + public void setDialogSelected(boolean value) { + if (isSelected != value) { + invalidate(); + } + isSelected = value; + } + public void checkCurrentDialogIndex() { TLRPC.TL_dialog dialog = null; if (isServerOnly) { @@ -740,7 +764,7 @@ public class DialogCell extends BaseCell { } avatarDrawable.setInfo(chat); } - avatarImage.setImage(photo, "50_50", avatarDrawable, false); + avatarImage.setImage(photo, "50_50", avatarDrawable, null, false); if (getMeasuredWidth() != 0 || getMeasuredHeight() != 0) { buildLayout(); @@ -757,6 +781,10 @@ public class DialogCell extends BaseCell { return; } + if (isSelected) { + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backPaint); + } + if (drawNameLock) { setDrawableBounds(lockDrawable, nameLockLeft, nameLockTop); lockDrawable.draw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java index 3e127c02c..49c9c5514 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java @@ -33,14 +33,7 @@ public class DrawerActionCell extends FrameLayout { textView.setSingleLine(true); textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); textView.setCompoundDrawablePadding(AndroidUtilities.dp(34)); - addView(textView); - LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.gravity = Gravity.LEFT; - layoutParams.leftMargin = AndroidUtilities.dp(14); - layoutParams.rightMargin = AndroidUtilities.dp(16); - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 14, 0, 16, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index afe12f393..1d2692c6a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -27,6 +27,7 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.AndroidUtilities; import org.telegram.android.ContactsController; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.ui.Components.AvatarDrawable; @@ -51,23 +52,11 @@ public class DrawerProfileCell extends FrameLayout { shadowView.setVisibility(INVISIBLE); shadowView.setScaleType(ImageView.ScaleType.FIT_XY); shadowView.setImageResource(R.drawable.bottom_shadow); - addView(shadowView); - LayoutParams layoutParams = (FrameLayout.LayoutParams) shadowView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = AndroidUtilities.dp(70); - layoutParams.gravity = Gravity.LEFT | Gravity.BOTTOM; - shadowView.setLayoutParams(layoutParams); + addView(shadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 70, Gravity.LEFT | Gravity.BOTTOM)); avatarImageView = new BackupImageView(context); avatarImageView.getImageReceiver().setRoundRadius(AndroidUtilities.dp(32)); - addView(avatarImageView); - layoutParams = (LayoutParams) avatarImageView.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(64); - layoutParams.height = AndroidUtilities.dp(64); - layoutParams.gravity = Gravity.LEFT | Gravity.BOTTOM; - layoutParams.leftMargin = AndroidUtilities.dp(16); - layoutParams.bottomMargin = AndroidUtilities.dp(67); - avatarImageView.setLayoutParams(layoutParams); + addView(avatarImageView, LayoutHelper.createFrame(64, 64, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 0, 67)); nameTextView = new TextView(context); nameTextView.setTextColor(0xffffffff); @@ -77,15 +66,7 @@ public class DrawerProfileCell extends FrameLayout { nameTextView.setMaxLines(1); nameTextView.setSingleLine(true); nameTextView.setGravity(Gravity.LEFT); - addView(nameTextView); - layoutParams = (FrameLayout.LayoutParams) nameTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.LEFT | Gravity.BOTTOM; - layoutParams.leftMargin = AndroidUtilities.dp(16); - layoutParams.bottomMargin = AndroidUtilities.dp(28); - layoutParams.rightMargin = AndroidUtilities.dp(16); - nameTextView.setLayoutParams(layoutParams); + addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 16, 28)); phoneTextView = new TextView(context); phoneTextView.setTextColor(0xffc2e5ff); @@ -94,15 +75,7 @@ public class DrawerProfileCell extends FrameLayout { phoneTextView.setMaxLines(1); phoneTextView.setSingleLine(true); phoneTextView.setGravity(Gravity.LEFT); - addView(phoneTextView); - layoutParams = (FrameLayout.LayoutParams) phoneTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.LEFT | Gravity.BOTTOM; - layoutParams.leftMargin = AndroidUtilities.dp(16); - layoutParams.bottomMargin = AndroidUtilities.dp(9); - layoutParams.rightMargin = AndroidUtilities.dp(16); - phoneTextView.setLayoutParams(layoutParams); + addView(phoneTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 16, 9)); } @Override @@ -110,7 +83,11 @@ public class DrawerProfileCell extends FrameLayout { if (Build.VERSION.SDK_INT >= 21) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(148) + AndroidUtilities.statusBarHeight, MeasureSpec.EXACTLY)); } else { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(148), MeasureSpec.EXACTLY)); + try { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(148), MeasureSpec.EXACTLY)); + } catch (Exception e) { + FileLog.e("tmessages", e); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java index 43a5132e8..c38def2a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java @@ -31,19 +31,12 @@ public class GreySectionCell extends FrameLayout { textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextColor(0xff8a8a8a); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(textView); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(16); - layoutParams.rightMargin = AndroidUtilities.dp(16); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 16, 0, 16, 0)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY)); } public void setText(String text) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java index ccb8dbcef..6655015ef 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java @@ -11,11 +11,14 @@ package org.telegram.ui.Cells; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; +import android.os.Build; import android.util.TypedValue; import android.view.Gravity; +import android.view.MotionEvent; import android.widget.TextView; import org.telegram.android.AndroidUtilities; +import org.telegram.messenger.R; public class HashtagSearchCell extends TextView { @@ -32,6 +35,18 @@ public class HashtagSearchCell extends TextView { paint = new Paint(); paint.setColor(0xffdcdcdc); } + + setBackgroundResource(R.drawable.list_selector); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (Build.VERSION.SDK_INT >= 21 && getBackground() != null) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { + getBackground().setHotspot(event.getX(), event.getY()); + } + } + return super.onTouchEvent(event); } public void setNeedDivider(boolean value) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java index dd4a8eb20..bfc725fa0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java @@ -9,7 +9,6 @@ package org.telegram.ui.Cells; import android.content.Context; -import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; import android.widget.FrameLayout; @@ -23,41 +22,15 @@ public class HeaderCell extends FrameLayout { private TextView textView; - private void init() { + public HeaderCell(Context context) { + super(context); + textView = new TextView(getContext()); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextColor(0xff3e90cf); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(textView); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.topMargin = AndroidUtilities.dp(15); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); - } - - public HeaderCell(Context context) { - super(context); - init(); - } - - public HeaderCell(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public HeaderCell(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - public HeaderCell(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 15, 17, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java index 18ac212bb..4ff29231f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java @@ -31,11 +31,7 @@ public class LetterSectionCell extends FrameLayout { textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextColor(0xff808080); textView.setGravity(Gravity.CENTER); - addView(textView); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } public void setLetter(String letter) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java index aad139aa8..fe1f545c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java @@ -22,16 +22,11 @@ public class LoadingCell extends FrameLayout { super(context); ProgressBar progressBar = new ProgressBar(context); - addView(progressBar); - LayoutParams layoutParams = (FrameLayout.LayoutParams) progressBar.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.CENTER; - progressBar.setLayoutParams(layoutParams); + addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(54), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(54), MeasureSpec.EXACTLY)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java index 05cd5b6b9..7a477eafb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java @@ -39,13 +39,7 @@ public class MentionCell extends LinearLayout { imageView = new BackupImageView(context); imageView.setRoundRadius(AndroidUtilities.dp(14)); - addView(imageView); - LayoutParams layoutParams = (LayoutParams) imageView.getLayoutParams(); - layoutParams.leftMargin = AndroidUtilities.dp(12); - layoutParams.topMargin = AndroidUtilities.dp(4); - layoutParams.width = AndroidUtilities.dp(28); - layoutParams.height = AndroidUtilities.dp(28); - imageView.setLayoutParams(layoutParams); + addView(imageView, LayoutHelper.createLinear(28, 28, 12, 4, 0, 0)); nameTextView = new TextView(context); nameTextView.setTextColor(0xff000000); @@ -53,13 +47,7 @@ public class MentionCell extends LinearLayout { nameTextView.setSingleLine(true); nameTextView.setGravity(Gravity.LEFT); nameTextView.setEllipsize(TextUtils.TruncateAt.END); - addView(nameTextView); - layoutParams = (LayoutParams) nameTextView.getLayoutParams(); - layoutParams.leftMargin = AndroidUtilities.dp(12); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.CENTER_VERTICAL; - nameTextView.setLayoutParams(layoutParams); + addView(nameTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 12, 0, 0, 0)); usernameTextView = new TextView(context); usernameTextView.setTextColor(0xff999999); @@ -67,13 +55,7 @@ public class MentionCell extends LinearLayout { usernameTextView.setSingleLine(true); usernameTextView.setGravity(Gravity.LEFT); usernameTextView.setEllipsize(TextUtils.TruncateAt.END); - addView(usernameTextView); - layoutParams = (LayoutParams) usernameTextView.getLayoutParams(); - layoutParams.leftMargin = AndroidUtilities.dp(12); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.CENTER_VERTICAL; - usernameTextView.setLayoutParams(layoutParams); + addView(usernameTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 12, 0, 0, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java index f723a5371..55d39ec94 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java @@ -30,12 +30,7 @@ public class PhotoEditToolCell extends FrameLayoutFixed { iconImage = new ImageView(context); iconImage.setScaleType(ImageView.ScaleType.CENTER); - addView(iconImage); - LayoutParams layoutParams = (LayoutParams) iconImage.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.bottomMargin = AndroidUtilities.dp(12); - iconImage.setLayoutParams(layoutParams); + addView(iconImage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 12)); nameTextView = new TextView(context); nameTextView.setGravity(Gravity.CENTER); @@ -45,27 +40,13 @@ public class PhotoEditToolCell extends FrameLayoutFixed { nameTextView.setMaxLines(1); nameTextView.setSingleLine(true); nameTextView.setEllipsize(TextUtils.TruncateAt.END); - addView(nameTextView); - layoutParams = (LayoutParams) nameTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.LEFT | Gravity.BOTTOM; - layoutParams.leftMargin = AndroidUtilities.dp(4); - layoutParams.rightMargin = AndroidUtilities.dp(4); - nameTextView.setLayoutParams(layoutParams); + addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 4, 0, 4, 0)); valueTextView = new TextView(context); valueTextView.setTextColor(0xff6cc3ff); valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 11); valueTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - addView(valueTextView); - layoutParams = (LayoutParams) valueTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.LEFT | Gravity.TOP; - layoutParams.leftMargin = AndroidUtilities.dp(57); - layoutParams.topMargin = AndroidUtilities.dp(3); - valueTextView.setLayoutParams(layoutParams); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 57, 3, 0, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java index d469e9503..caff290ca 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java @@ -47,21 +47,12 @@ public class PhotoPickerAlbumsCell extends FrameLayoutFixed { super(context); imageView = new BackupImageView(context); - addView(imageView); - LayoutParams layoutParams = (LayoutParams) imageView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - imageView.setLayoutParams(layoutParams); + addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); linearLayout.setBackgroundColor(0x7f000000); - addView(linearLayout); - layoutParams = (LayoutParams) linearLayout.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = AndroidUtilities.dp(28); - layoutParams.gravity = Gravity.BOTTOM; - linearLayout.setLayoutParams(layoutParams); + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 28, Gravity.LEFT | Gravity.BOTTOM)); nameTextView = new TextView(context); nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); @@ -70,13 +61,7 @@ public class PhotoPickerAlbumsCell extends FrameLayoutFixed { nameTextView.setEllipsize(TextUtils.TruncateAt.END); nameTextView.setMaxLines(1); nameTextView.setGravity(Gravity.CENTER_VERTICAL); - linearLayout.addView(nameTextView); - LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams) nameTextView.getLayoutParams(); - layoutParams1.width = 0; - layoutParams1.height = LayoutHelper.MATCH_PARENT; - layoutParams1.leftMargin = AndroidUtilities.dp(8); - layoutParams1.weight = 1; - nameTextView.setLayoutParams(layoutParams1); + linearLayout.addView(nameTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 8, 0, 0, 0)); countTextView = new TextView(context); countTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); @@ -85,21 +70,11 @@ public class PhotoPickerAlbumsCell extends FrameLayoutFixed { countTextView.setEllipsize(TextUtils.TruncateAt.END); countTextView.setMaxLines(1); countTextView.setGravity(Gravity.CENTER_VERTICAL); - linearLayout.addView(countTextView); - layoutParams1 = (LinearLayout.LayoutParams) countTextView.getLayoutParams(); - layoutParams1.width = LayoutHelper.WRAP_CONTENT; - layoutParams1.height = LayoutHelper.MATCH_PARENT; - layoutParams1.leftMargin = AndroidUtilities.dp(4); - layoutParams1.rightMargin = AndroidUtilities.dp(4); - countTextView.setLayoutParams(layoutParams1); + linearLayout.addView(countTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, 4, 0, 4, 0)); selector = new View(context); selector.setBackgroundResource(R.drawable.list_selector); - addView(selector); - layoutParams = (LayoutParams) selector.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - selector.setLayoutParams(layoutParams); + addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java index 40005597d..94f85c207 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java @@ -29,33 +29,17 @@ public class PhotoPickerPhotoCell extends FrameLayout { super(context); photoImage = new BackupImageView(context); - addView(photoImage); - LayoutParams layoutParams = (LayoutParams) photoImage.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - photoImage.setLayoutParams(layoutParams); + addView(photoImage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); checkFrame = new FrameLayout(context); - addView(checkFrame); - layoutParams = (LayoutParams) checkFrame.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(42); - layoutParams.height = AndroidUtilities.dp(42); - layoutParams.gravity = Gravity.RIGHT | Gravity.TOP; - checkFrame.setLayoutParams(layoutParams); + addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.RIGHT | Gravity.TOP)); checkBox = new CheckBox(context, R.drawable.checkbig); checkBox.setSize(30); checkBox.setCheckOffset(AndroidUtilities.dp(1)); checkBox.setDrawBackground(true); checkBox.setColor(0xff3ccaef); - addView(checkBox); - layoutParams = (LayoutParams) checkBox.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(30); - layoutParams.height = AndroidUtilities.dp(30); - layoutParams.gravity = Gravity.RIGHT | Gravity.TOP; - layoutParams.topMargin = AndroidUtilities.dp(6); - layoutParams.rightMargin = AndroidUtilities.dp(6); - checkBox.setLayoutParams(layoutParams); + addView(checkBox, LayoutHelper.createFrame(30, 30, Gravity.RIGHT | Gravity.TOP, 0, 6, 6, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java index bc3ce4f10..81c007e45 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java @@ -45,20 +45,11 @@ public class PhotoPickerSearchCell extends LinearLayout { selector = new View(context); selector.setBackgroundResource(R.drawable.list_selector); - addView(selector); - FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) selector.getLayoutParams(); - layoutParams1.width = LayoutHelper.MATCH_PARENT; - layoutParams1.height = LayoutHelper.MATCH_PARENT; - selector.setLayoutParams(layoutParams1); + addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - addView(imageView); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) imageView.getLayoutParams(); - layoutParams.height = AndroidUtilities.dp(48); - layoutParams.width = AndroidUtilities.dp(48); - layoutParams1.gravity = Gravity.LEFT | Gravity.TOP; - imageView.setLayoutParams(layoutParams); + addView(imageView, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); textView1 = new TextView(context); textView1.setGravity(Gravity.CENTER_VERTICAL); @@ -67,15 +58,7 @@ public class PhotoPickerSearchCell extends LinearLayout { textView1.setTextColor(0xffffffff); textView1.setSingleLine(true); textView1.setEllipsize(TextUtils.TruncateAt.END); - addView(textView1); - layoutParams1 = (FrameLayout.LayoutParams) textView1.getLayoutParams(); - layoutParams1.width = LayoutHelper.MATCH_PARENT; - layoutParams1.height = LayoutHelper.WRAP_CONTENT; - layoutParams1.gravity = Gravity.TOP | Gravity.LEFT; - layoutParams1.rightMargin = AndroidUtilities.dp(4); - layoutParams1.leftMargin = AndroidUtilities.dp(51); - layoutParams1.topMargin = AndroidUtilities.dp(8); - textView1.setLayoutParams(layoutParams1); + addView(textView1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 51, 8, 4, 0)); textView2 = new TextView(context); textView2.setGravity(Gravity.CENTER_VERTICAL); @@ -84,15 +67,7 @@ public class PhotoPickerSearchCell extends LinearLayout { textView2.setTextColor(0xff666666); textView2.setSingleLine(true); textView2.setEllipsize(TextUtils.TruncateAt.END); - addView(textView2); - layoutParams1 = (FrameLayout.LayoutParams) textView2.getLayoutParams(); - layoutParams1.width = LayoutHelper.MATCH_PARENT; - layoutParams1.height = LayoutHelper.WRAP_CONTENT; - layoutParams1.gravity = Gravity.TOP | Gravity.LEFT; - layoutParams1.leftMargin = AndroidUtilities.dp(51); - layoutParams1.rightMargin = AndroidUtilities.dp(4); - layoutParams1.topMargin = AndroidUtilities.dp(26); - textView2.setLayoutParams(layoutParams1); + addView(textView2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 51, 26, 4, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java index 80bfa4f28..cc7537594 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -12,10 +12,12 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; +import android.os.Build; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.view.MotionEvent; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.AndroidUtilities; @@ -70,13 +72,7 @@ public class ProfileSearchCell extends BaseCell { public ProfileSearchCell(Context context) { super(context); - init(); - avatarImage = new ImageReceiver(this); - avatarImage.setRoundRadius(AndroidUtilities.dp(26)); - avatarDrawable = new AvatarDrawable(); - } - private void init() { if (namePaint == null) { namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); namePaint.setTextSize(AndroidUtilities.dp(17)); @@ -103,6 +99,20 @@ public class ProfileSearchCell extends BaseCell { lockDrawable = getResources().getDrawable(R.drawable.list_secret); groupDrawable = getResources().getDrawable(R.drawable.list_group); } + + avatarImage = new ImageReceiver(this); + avatarImage.setRoundRadius(AndroidUtilities.dp(26)); + avatarDrawable = new AvatarDrawable(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (Build.VERSION.SDK_INT >= 21 && getBackground() != null) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { + getBackground().setHotspot(event.getX(), event.getY()); + } + } + return super.onTouchEvent(event); } public void setData(TLRPC.User u, TLRPC.Chat c, TLRPC.EncryptedChat ec, CharSequence n, CharSequence s) { @@ -143,7 +153,7 @@ public class ProfileSearchCell extends BaseCell { } public void buildLayout() { - CharSequence nameString = ""; + CharSequence nameString; TextPaint currentNamePaint; drawNameBroadcast = false; @@ -235,7 +245,7 @@ public class ProfileSearchCell extends BaseCell { onlineLeft = AndroidUtilities.dp(11); } - CharSequence onlineString = ""; + CharSequence onlineString; TextPaint currentOnlinePaint = offlinePaint; if (subLabel != null) { @@ -265,8 +275,8 @@ public class ProfileSearchCell extends BaseCell { avatarImage.setImageCoords(avatarLeft, AndroidUtilities.dp(10), AndroidUtilities.dp(52), AndroidUtilities.dp(52)); - double widthpx = 0; - float left = 0; + double widthpx; + float left; if (LocaleController.isRTL) { if (nameLayout.getLineCount() > 0) { left = nameLayout.getLineLeft(0); @@ -370,7 +380,7 @@ public class ProfileSearchCell extends BaseCell { lastAvatar = photo; - avatarImage.setImage(photo, "50_50", avatarDrawable, false); + avatarImage.setImage(photo, "50_50", avatarDrawable, null, false); if (getMeasuredWidth() != 0 || getMeasuredHeight() != 0) { buildLayout(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java index a76d1e389..4555b276b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java @@ -47,15 +47,7 @@ public class SessionCell extends FrameLayout { LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); linearLayout.setWeightSum(1); - addView(linearLayout); - LayoutParams layoutParams = (LayoutParams) linearLayout.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = AndroidUtilities.dp(30); - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.topMargin = AndroidUtilities.dp(11); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - linearLayout.setLayoutParams(layoutParams); + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 11, 11, 0)); nameTextView = new TextView(context); nameTextView.setTextColor(0xff212121); @@ -72,32 +64,13 @@ public class SessionCell extends FrameLayout { onlineTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP); if (LocaleController.isRTL) { - linearLayout.addView(onlineTextView); - linearLayout.addView(nameTextView); + linearLayout.addView(onlineTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 2, 0, 0)); + linearLayout.addView(nameTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, Gravity.RIGHT | Gravity.TOP, 10, 0, 0, 0)); } else { - linearLayout.addView(nameTextView); - linearLayout.addView(onlineTextView); + linearLayout.addView(nameTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, Gravity.LEFT | Gravity.TOP, 0, 0, 10, 0)); + linearLayout.addView(onlineTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.TOP, 0, 2, 0, 0)); } - LinearLayout.LayoutParams layoutParams2 = (LinearLayout.LayoutParams) nameTextView.getLayoutParams(); - layoutParams2.width = 0; - layoutParams2.height = LayoutHelper.MATCH_PARENT; - layoutParams2.weight = 1; - if (LocaleController.isRTL) { - layoutParams2.leftMargin = AndroidUtilities.dp(10); - } else { - layoutParams2.rightMargin = AndroidUtilities.dp(10); - } - layoutParams2.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - nameTextView.setLayoutParams(layoutParams2); - - layoutParams2 = (LinearLayout.LayoutParams) onlineTextView.getLayoutParams(); - layoutParams2.width = LayoutHelper.WRAP_CONTENT; - layoutParams2.height = LayoutHelper.MATCH_PARENT; - layoutParams2.topMargin = AndroidUtilities.dp(2); - layoutParams2.gravity = (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP; - onlineTextView.setLayoutParams(layoutParams2); - detailTextView = new TextView(context); detailTextView.setTextColor(0xff212121); detailTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); @@ -106,15 +79,7 @@ public class SessionCell extends FrameLayout { detailTextView.setSingleLine(true); detailTextView.setEllipsize(TextUtils.TruncateAt.END); detailTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); - addView(detailTextView); - layoutParams = (LayoutParams) detailTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.topMargin = AndroidUtilities.dp(36); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP; - detailTextView.setLayoutParams(layoutParams); + addView(detailTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 36, 17, 0)); detailExTextView = new TextView(context); detailExTextView.setTextColor(0xff999999); @@ -124,15 +89,7 @@ public class SessionCell extends FrameLayout { detailExTextView.setSingleLine(true); detailExTextView.setEllipsize(TextUtils.TruncateAt.END); detailExTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); - addView(detailExTextView); - layoutParams = (LayoutParams) detailExTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.topMargin = AndroidUtilities.dp(59); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP; - detailExTextView.setLayoutParams(layoutParams); + addView(detailExTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 59, 17, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java index 39a4dfca2..ed0998b50 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java @@ -9,7 +9,6 @@ package org.telegram.ui.Cells; import android.content.Context; -import android.util.AttributeSet; import android.view.View; import org.telegram.android.AndroidUtilities; @@ -17,28 +16,9 @@ import org.telegram.messenger.R; public class ShadowBottomSectionCell extends View { - private void init() { - setBackgroundResource(R.drawable.greydivider_bottom); - } - public ShadowBottomSectionCell(Context context) { super(context); - init(); - } - - public ShadowBottomSectionCell(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public ShadowBottomSectionCell(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - public ShadowBottomSectionCell(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(); + setBackgroundResource(R.drawable.greydivider_bottom); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java index b8c7ce118..ad130f9bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java @@ -9,7 +9,6 @@ package org.telegram.ui.Cells; import android.content.Context; -import android.util.AttributeSet; import android.view.View; import org.telegram.android.AndroidUtilities; @@ -17,28 +16,9 @@ import org.telegram.messenger.R; public class ShadowSectionCell extends View { - private void init() { - setBackgroundResource(R.drawable.greydivider); - } - public ShadowSectionCell(Context context) { super(context); - init(); - } - - public ShadowSectionCell(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public ShadowSectionCell(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - public ShadowSectionCell(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(); + setBackgroundResource(R.drawable.greydivider); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index 92f83da3d..4c2e46a36 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -28,7 +28,6 @@ import org.telegram.android.MessageObject; import org.telegram.messenger.FileLoader; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; -import org.telegram.messenger.Utilities; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CheckBox; import org.telegram.ui.Components.LayoutHelper; @@ -77,15 +76,7 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F TAG = MediaController.getInstance().generateObserverTag(); placeholderImabeView = new ImageView(context); - addView(placeholderImabeView); - LayoutParams layoutParams = (LayoutParams) placeholderImabeView.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(40); - layoutParams.height = AndroidUtilities.dp(40); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(12); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(12) : 0; - layoutParams.topMargin = AndroidUtilities.dp(8); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - placeholderImabeView.setLayoutParams(layoutParams); + addView(placeholderImabeView, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 12, 8, LocaleController.isRTL ? 12 : 0, 0)); extTextView = new TextView(context); extTextView.setTextColor(0xffffffff); @@ -96,17 +87,10 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F extTextView.setSingleLine(true); extTextView.setGravity(Gravity.CENTER); extTextView.setEllipsize(TextUtils.TruncateAt.END); - addView(extTextView); - layoutParams = (LayoutParams) extTextView.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(32); - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.topMargin = AndroidUtilities.dp(22); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(16); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(16) : 0; - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - extTextView.setLayoutParams(layoutParams); + addView(extTextView, LayoutHelper.createFrame(32, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 16, 22, LocaleController.isRTL ? 16 : 0, 0)); thumbImageView = new BackupImageView(context); + addView(thumbImageView, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 12, 8, LocaleController.isRTL ? 12 : 0, 0)); thumbImageView.getImageReceiver().setDelegate(new ImageReceiver.ImageReceiverDelegate() { @Override public void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb) { @@ -114,15 +98,6 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F placeholderImabeView.setVisibility(set ? INVISIBLE : VISIBLE); } }); - addView(thumbImageView); - layoutParams = (LayoutParams) thumbImageView.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(40); - layoutParams.height = AndroidUtilities.dp(40); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(12); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(12) : 0; - layoutParams.topMargin = AndroidUtilities.dp(8); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - thumbImageView.setLayoutParams(layoutParams); nameTextView = new TextView(context); nameTextView.setTextColor(0xff222222); @@ -133,27 +108,11 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F nameTextView.setSingleLine(true); nameTextView.setEllipsize(TextUtils.TruncateAt.END); nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(nameTextView); - layoutParams = (LayoutParams) nameTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.topMargin = AndroidUtilities.dp(5); - layoutParams.leftMargin = LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(72); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(72) : AndroidUtilities.dp(8); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - nameTextView.setLayoutParams(layoutParams); + addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 5, LocaleController.isRTL ? 72 : 8, 0)); statusImageView = new ImageView(context); statusImageView.setVisibility(INVISIBLE); - addView(statusImageView); - layoutParams = (LayoutParams) statusImageView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.topMargin = AndroidUtilities.dp(35); - layoutParams.leftMargin = LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(72); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(72) : AndroidUtilities.dp(8); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - statusImageView.setLayoutParams(layoutParams); + addView(statusImageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 35, LocaleController.isRTL ? 72 : 8, 0)); dateTextView = new TextView(context); dateTextView.setTextColor(0xff999999); @@ -163,38 +122,14 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F dateTextView.setSingleLine(true); dateTextView.setEllipsize(TextUtils.TruncateAt.END); dateTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(dateTextView); - layoutParams = (LayoutParams) dateTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.topMargin = AndroidUtilities.dp(30); - layoutParams.leftMargin = LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(72); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(72) : AndroidUtilities.dp(8); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - dateTextView.setLayoutParams(layoutParams); + addView(dateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 30, LocaleController.isRTL ? 72 : 8, 0)); progressView = new LineProgressView(context); - addView(progressView); - layoutParams = (LayoutParams) progressView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = AndroidUtilities.dp(2); - layoutParams.topMargin = AndroidUtilities.dp(54); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(72); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(72) : 0; - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - progressView.setLayoutParams(layoutParams); + addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 72, 54, LocaleController.isRTL ? 72 : 0, 0)); checkBox = new CheckBox(context, R.drawable.round_check2); checkBox.setVisibility(INVISIBLE); - addView(checkBox); - layoutParams = (LayoutParams) checkBox.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(22); - layoutParams.height = AndroidUtilities.dp(22); - layoutParams.topMargin = AndroidUtilities.dp(30); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(34); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(34) : 0; - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - checkBox.setLayoutParams(layoutParams); + addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 34, 30, LocaleController.isRTL ? 34 : 0, 0)); } private int getThumbForNameOrMime(String name, String mime) { @@ -270,7 +205,7 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F loading = false; if (document != null && document.messageOwner.media != null) { - int idx = -1; + int idx; String name = FileLoader.getDocumentFileName(document.messageOwner.media.document); placeholderImabeView.setVisibility(VISIBLE); extTextView.setVisibility(VISIBLE); @@ -285,7 +220,7 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F thumbImageView.setImage(document.messageOwner.media.document.thumb.location, "40_40", (Drawable) null); } long date = (long) document.messageOwner.date * 1000; - dateTextView.setText(String.format("%s, %s", Utilities.formatFileSize(document.messageOwner.media.document.size), LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.formatterYear.format(new Date(date)), LocaleController.formatterDay.format(new Date(date))))); + dateTextView.setText(String.format("%s, %s", AndroidUtilities.formatFileSize(document.messageOwner.media.document.size), LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.formatterYear.format(new Date(date)), LocaleController.formatterDay.format(new Date(date))))); } else { nameTextView.setText(""); extTextView.setText(""); @@ -304,7 +239,7 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F public void updateFileExistIcon() { if (message != null && message.messageOwner.media != null) { String fileName = null; - File cacheFile = null; + File cacheFile; if (message.messageOwner.attachPath == null || message.messageOwner.attachPath.length() == 0 || !(new File(message.messageOwner.attachPath).exists())) { cacheFile = FileLoader.getPathToMessage(message.messageOwner); if (!cacheFile.exists()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java index 7c39b0bf8..1646b509b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java @@ -30,14 +30,7 @@ public class SharedMediaSectionCell extends FrameLayout { textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextColor(0xff222222); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(textView); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(13); - layoutParams.rightMargin = AndroidUtilities.dp(13); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 13, 0, 13, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java index 954632263..879043844 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java @@ -69,11 +69,7 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { ImageView imageView1 = new ImageView(context); imageView1.setImageResource(R.drawable.ic_video); - videoInfoContainer.addView(imageView1); - LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams) imageView1.getLayoutParams(); - layoutParams1.width = LayoutHelper.WRAP_CONTENT; - layoutParams1.height = LayoutHelper.WRAP_CONTENT; - imageView1.setLayoutParams(layoutParams1); + videoInfoContainer.addView(imageView1, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); videoTextView = new TextView(context); videoTextView.setTextColor(0xffffffff); @@ -186,14 +182,14 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { photoVideoView.videoTextView.setText(String.format("%d:%02d", minutes, seconds)); if (messageObject.messageOwner.media.video.thumb != null) { TLRPC.FileLocation location = messageObject.messageOwner.media.video.thumb.location; - photoVideoView.imageView.setImage(null, null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, location, "b", 0); + photoVideoView.imageView.setImage(null, null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, location, "b", null, 0); } else { photoVideoView.imageView.setImageResource(R.drawable.photo_placeholder_in); } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageObject.messageOwner.media.photo != null && !messageObject.photoThumbs.isEmpty()) { photoVideoView.videoInfoContainer.setVisibility(INVISIBLE); TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 80); - photoVideoView.imageView.setImage(null, null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, photoSize.location, "b", 0); + photoVideoView.imageView.setImage(null, null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, photoSize.location, "b", null, 0); } else { photoVideoView.videoInfoContainer.setVisibility(INVISIBLE); photoVideoView.imageView.setImageResource(R.drawable.photo_placeholder_in); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java index 34e04c69b..04e79938f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java @@ -9,7 +9,6 @@ package org.telegram.ui.Cells; import android.content.Context; -import android.graphics.drawable.Drawable; import android.view.Gravity; import org.telegram.android.AndroidUtilities; @@ -17,6 +16,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.FrameLayoutFixed; +import org.telegram.ui.Components.LayoutHelper; public class StickerCell extends FrameLayoutFixed { @@ -27,13 +27,7 @@ public class StickerCell extends FrameLayoutFixed { imageView = new BackupImageView(context); imageView.setAspectFit(true); - addView(imageView); - LayoutParams layoutParams = (LayoutParams) imageView.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(66); - layoutParams.height = AndroidUtilities.dp(66); - layoutParams.gravity = Gravity.CENTER_HORIZONTAL; - layoutParams.topMargin = AndroidUtilities.dp(5); - imageView.setLayoutParams(layoutParams); + addView(imageView, LayoutHelper.createFrame(66, 66, Gravity.CENTER_HORIZONTAL, 0, 5, 0, 0)); } @Override @@ -52,8 +46,7 @@ public class StickerCell extends FrameLayoutFixed { public void setSticker(TLRPC.Document document, int side) { if (document != null) { - document.thumb.location.ext = "webp"; - imageView.setImage(document.thumb.location, null, (Drawable) null); + imageView.setImage(document.thumb.location, null, "webp", null); } if (side == -1) { setBackgroundResource(R.drawable.stickers_back_left); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java index 72b8db653..ce803d315 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java @@ -9,10 +9,14 @@ package org.telegram.ui.Cells; import android.content.Context; -import android.graphics.drawable.Drawable; +import android.util.TypedValue; import android.view.Gravity; import android.widget.FrameLayout; +import android.widget.TextView; +import org.telegram.android.AndroidUtilities; +import org.telegram.android.Emoji; +import org.telegram.android.query.StickersQuery; import org.telegram.messenger.TLRPC; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.LayoutHelper; @@ -21,6 +25,7 @@ public class StickerEmojiCell extends FrameLayout { private BackupImageView imageView; private TLRPC.Document sticker; + private TextView emojiTextView; public StickerEmojiCell(Context context) { super(context); @@ -28,6 +33,10 @@ public class StickerEmojiCell extends FrameLayout { imageView = new BackupImageView(context); imageView.setAspectFit(true); addView(imageView, LayoutHelper.createFrame(66, 66, Gravity.CENTER)); + + emojiTextView = new TextView(context); + emojiTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + addView(emojiTextView, LayoutHelper.createFrame(28, 28, Gravity.BOTTOM | Gravity.RIGHT)); } @Override @@ -43,11 +52,30 @@ public class StickerEmojiCell extends FrameLayout { return sticker; } - public void setSticker(TLRPC.Document document) { + public void setSticker(TLRPC.Document document, boolean showEmoji) { if (document != null) { sticker = document; - document.thumb.location.ext = "webp"; - imageView.setImage(document.thumb.location, null, (Drawable) null); + imageView.setImage(document.thumb.location, null, "webp", null); + + + if (showEmoji) { + boolean set = false; + for (TLRPC.DocumentAttribute attribute : document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeSticker) { + if (attribute.alt != null && attribute.alt.length() > 0) { + emojiTextView.setText(Emoji.replaceEmoji(attribute.alt, emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16))); + set = true; + } + break; + } + } + if (!set) { + emojiTextView.setText(Emoji.replaceEmoji(StickersQuery.getEmojiForSticker(sticker.id), emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16))); + } + emojiTextView.setVisibility(VISIBLE); + } else { + emojiTextView.setVisibility(INVISIBLE); + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java new file mode 100644 index 000000000..03699a64a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java @@ -0,0 +1,144 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2014. + */ + +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.AnimationCompat.ViewProxy; +import org.telegram.android.LocaleController; +import org.telegram.android.query.StickersQuery; +import org.telegram.messenger.R; +import org.telegram.messenger.TLRPC; +import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.LayoutHelper; + +import java.util.ArrayList; + +public class StickerSetCell extends FrameLayout { + + private TextView textView; + private TextView valueTextView; + private BackupImageView imageView; + private boolean needDivider; + private ImageView optionsButton; + private TLRPC.TL_stickerSet stickersSet; + + private static Paint paint; + + public StickerSetCell(Context context) { + super(context); + + if (paint == null) { + paint = new Paint(); + paint.setColor(0xffd9d9d9); + } + + textView = new TextView(context); + textView.setTextColor(0xff212121); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setLines(1); + textView.setMaxLines(1); + textView.setSingleLine(true); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 40 : 71, 10, LocaleController.isRTL ? 40 : 71, 0)); + + valueTextView = new TextView(context); + valueTextView.setTextColor(0xff8a8a8a); + valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + valueTextView.setLines(1); + valueTextView.setMaxLines(1); + valueTextView.setSingleLine(true); + valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 40 : 71, 35, LocaleController.isRTL ? 40 : 71, 0)); + + imageView = new BackupImageView(context); + imageView.setAspectFit(true); + addView(imageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 12, 8, LocaleController.isRTL ? 12 : 0, 0)); + + optionsButton = new ImageView(context); + optionsButton.setBackgroundResource(R.drawable.bar_selector_grey); + optionsButton.setImageResource(R.drawable.doc_actions_b); + optionsButton.setScaleType(ImageView.ScaleType.CENTER); + addView(optionsButton, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP)); + + /*ActionBarMenuItem menuItem = new ActionBarMenuItem(context, null, R.drawable.bar_selector_grey); + menuItem.setIcon(R.drawable.doc_actions_b); + addView(menuItem, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 40 : 0, 0, LocaleController.isRTL ? 0 : 40, 0)); + menuItem.addSubItem(1, "test", 0); + menuItem.addSubItem(2, "test", 0); + menuItem.addSubItem(3, "test", 0); + menuItem.addSubItem(4, "test", 0); + menuItem.addSubItem(5, "test", 0); + menuItem.addSubItem(6, "test", 0); + menuItem.addSubItem(7, "test", 0);*/ + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); + } + + public void setStickersSet(TLRPC.TL_stickerSet set, boolean divider) { + needDivider = divider; + stickersSet = set; + + if (stickersSet.id == -1) { + textView.setText(LocaleController.getString("GeniusStickerPackName", R.string.GeniusStickerPackName)); + if (StickersQuery.getHideMainStickersPack()) { + ViewProxy.setAlpha(textView, 0.5f); + ViewProxy.setAlpha(valueTextView, 0.5f); + ViewProxy.setAlpha(imageView, 0.5f); + } else { + ViewProxy.setAlpha(textView, 1.0f); + ViewProxy.setAlpha(valueTextView, 1.0f); + ViewProxy.setAlpha(imageView, 1.0f); + } + } else { + textView.setText(stickersSet.title); + ViewProxy.setAlpha(textView, 1.0f); + ViewProxy.setAlpha(valueTextView, 1.0f); + ViewProxy.setAlpha(imageView, 1.0f); + } + ArrayList documents = StickersQuery.getStickersForSet(stickersSet.id); + if (documents != null) { + valueTextView.setText(LocaleController.formatPluralString("Stickers", documents.size())); + TLRPC.Document document = documents.get(0); + if (document.thumb != null && document.thumb.location != null) { + imageView.setImage(document.thumb.location, null, "webp", null); + } + } else { + valueTextView.setText(LocaleController.formatPluralString("Stickers", 0)); + } + } + + public void setOnOptionsClick(OnClickListener listener) { + optionsButton.setOnClickListener(listener); + } + + public TLRPC.TL_stickerSet getStickersSet() { + return stickersSet; + } + + @Override + protected void onDraw(Canvas canvas) { + if (needDivider) { + canvas.drawLine(0, getHeight() - 1, getWidth() - getPaddingRight(), getHeight() - 1, paint); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index e6dfa544b..d43cb7580 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -39,14 +39,7 @@ public class TextCell extends FrameLayout { textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(textView); - LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 71); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 71 : 16); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 16 : 71, 0, LocaleController.isRTL ? 71 : 16, 0)); valueTextView = new TextView(context); valueTextView.setTextColor(0xff2f8cc9); @@ -55,36 +48,15 @@ public class TextCell extends FrameLayout { valueTextView.setMaxLines(1); valueTextView.setSingleLine(true); valueTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL); - addView(valueTextView); - layoutParams = (LayoutParams) valueTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 24 : 0); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 0 : 24); - layoutParams.gravity = LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT; - valueTextView.setLayoutParams(layoutParams); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 24 : 0, 0, LocaleController.isRTL ? 0 : 24, 0)); imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - addView(imageView); - layoutParams = (LayoutParams) imageView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 0 : 16); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 0); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL; - imageView.setLayoutParams(layoutParams); + addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 0 : 16, 0, LocaleController.isRTL ? 16 : 0, 0)); valueImageView = new ImageView(context); valueImageView.setScaleType(ImageView.ScaleType.CENTER); - addView(valueImageView); - layoutParams = (LayoutParams) valueImageView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 24 : 0); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 0 : 24); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL; - valueImageView.setLayoutParams(layoutParams); + addView(valueImageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 24 : 0, 0, LocaleController.isRTL ? 0 : 24, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java index 6734071ec..a36f01ff0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java @@ -45,28 +45,14 @@ public class TextCheckCell extends FrameLayoutFixed { textView.setMaxLines(1); textView.setSingleLine(true); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(textView); - LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 0, 17, 0)); checkBox = new Switch(context); checkBox.setDuplicateParentStateEnabled(false); checkBox.setFocusable(false); checkBox.setFocusableInTouchMode(false); checkBox.setClickable(false); - addView(checkBox); - layoutParams = (LayoutParams) checkBox.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(14); - layoutParams.rightMargin = AndroidUtilities.dp(14); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL; - checkBox.setLayoutParams(layoutParams); + addView(checkBox, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 14, 0, 14, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java index 348e5b7b5..2fb0de5c6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java @@ -25,12 +25,14 @@ import org.telegram.messenger.R; import org.telegram.ui.Components.LayoutHelper; public class TextColorCell extends FrameLayout { + private TextView textView; - private Drawable colorDrawable; - private static Paint paint; private boolean needDivider; private int currentColor; + private static Drawable colorDrawable; + private static Paint paint; + public TextColorCell(Context context) { super(context); @@ -38,6 +40,8 @@ public class TextColorCell extends FrameLayout { paint = new Paint(); paint.setColor(0xffd9d9d9); paint.setStrokeWidth(1); + + colorDrawable = getResources().getDrawable(R.drawable.switch_to_on2); } textView = new TextView(context); @@ -47,16 +51,7 @@ public class TextColorCell extends FrameLayout { textView.setMaxLines(1); textView.setSingleLine(true); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(textView); - LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); - - colorDrawable = getResources().getDrawable(R.drawable.switch_to_on2); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 0, 17, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java index e44654ef0..7889b7803 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java @@ -36,15 +36,7 @@ public class TextDetailCell extends FrameLayout { textView.setMaxLines(1); textView.setSingleLine(true); textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(textView); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.topMargin = AndroidUtilities.dp(10); - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 71); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 71 : 16); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 10, LocaleController.isRTL ? 16 : 71, 0)); valueTextView = new TextView(context); valueTextView.setTextColor(0xff8a8a8a); @@ -53,26 +45,11 @@ public class TextDetailCell extends FrameLayout { valueTextView.setMaxLines(1); valueTextView.setSingleLine(true); valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(valueTextView); - layoutParams = (FrameLayout.LayoutParams) valueTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.topMargin = AndroidUtilities.dp(35); - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 71); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 71 : 16); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - valueTextView.setLayoutParams(layoutParams); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 35, LocaleController.isRTL ? 16 : 71, 0)); imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - addView(imageView); - layoutParams = (LayoutParams) imageView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 0 : 16); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 0); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL; - imageView.setLayoutParams(layoutParams); + addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 0 : 16, 0, LocaleController.isRTL ? 16 : 0, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java index 1ac52592a..1d9a9a062 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java @@ -44,15 +44,7 @@ public class TextDetailSettingsCell extends FrameLayoutFixed { textView.setMaxLines(1); textView.setSingleLine(true); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(textView); - LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.topMargin = AndroidUtilities.dp(10); - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 10, 17, 0)); valueTextView = new TextView(context); valueTextView.setTextColor(0xff8a8a8a); @@ -62,15 +54,7 @@ public class TextDetailSettingsCell extends FrameLayoutFixed { valueTextView.setMaxLines(1); valueTextView.setSingleLine(true); valueTextView.setPadding(0, 0, 0, 0); - addView(valueTextView); - layoutParams = (LayoutParams) valueTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.topMargin = AndroidUtilities.dp(35); - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - valueTextView.setLayoutParams(layoutParams); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 35, 17, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java index 236cff202..1e0f3ceec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java @@ -29,14 +29,7 @@ public class TextInfoCell extends FrameLayout { textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); textView.setGravity(Gravity.CENTER); textView.setPadding(0, AndroidUtilities.dp(19), 0, AndroidUtilities.dp(19)); - addView(textView); - LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.gravity = Gravity.CENTER; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 17, 0, 17, 0)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java index 8ba0f7232..579917310 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java @@ -9,6 +9,7 @@ package org.telegram.ui.Cells; import android.content.Context; +import android.text.method.LinkMovementMethod; import android.util.TypedValue; import android.view.Gravity; import android.widget.FrameLayout; @@ -27,17 +28,12 @@ public class TextInfoPrivacyCell extends FrameLayout { textView = new TextView(context); textView.setTextColor(0xff808080); + textView.setLinkTextColor(0xff316f9f); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); textView.setPadding(0, AndroidUtilities.dp(10), 0, AndroidUtilities.dp(17)); - addView(textView); - LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); + textView.setMovementMethod(LinkMovementMethod.getInstance()); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 0, 17, 0)); } @Override @@ -45,7 +41,7 @@ public class TextInfoPrivacyCell extends FrameLayout { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); } - public void setText(String text) { + public void setText(CharSequence text) { textView.setText(text); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java index b9b295e55..fdda610f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java @@ -47,14 +47,7 @@ public class TextSettingsCell extends FrameLayout { textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - addView(textView); - LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT; - textView.setLayoutParams(layoutParams); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 0, 17, 0)); valueTextView = new TextView(context); valueTextView.setTextColor(0xff2f8cc9); @@ -64,26 +57,12 @@ public class TextSettingsCell extends FrameLayout { valueTextView.setSingleLine(true); valueTextView.setEllipsize(TextUtils.TruncateAt.END); valueTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL); - addView(valueTextView); - layoutParams = (LayoutParams) valueTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.leftMargin = AndroidUtilities.dp(17); - layoutParams.rightMargin = AndroidUtilities.dp(17); - layoutParams.gravity = LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT; - valueTextView.setLayoutParams(layoutParams); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 17, 0, 17, 0)); valueImageView = new ImageView(context); valueImageView.setScaleType(ImageView.ScaleType.CENTER); valueImageView.setVisibility(INVISIBLE); - addView(valueImageView); - layoutParams = (LayoutParams) valueImageView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 17 : 0); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 0 : 17); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL; - valueImageView.setLayoutParams(layoutParams); + addView(valueImageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 17, 0, 17, 0)); } @Override @@ -127,6 +106,7 @@ public class TextSettingsCell extends FrameLayout { } needDivider = divider; setWillNotDraw(!divider); + requestLayout(); } public void setTextAndIcon(String text, int resId, boolean divider) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java new file mode 100644 index 000000000..5dce6aaf4 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java @@ -0,0 +1,75 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.R; +import org.telegram.messenger.TLRPC; +import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.LayoutHelper; + +public class WallpaperCell extends FrameLayout { + + private BackupImageView imageView; + private View selectionView; + private ImageView imageView2; + + public WallpaperCell(Context context) { + super(context); + + imageView = new BackupImageView(context); + addView(imageView, LayoutHelper.createFrame(100, 100, Gravity.LEFT | Gravity.BOTTOM)); + + imageView2 = new ImageView(context); + imageView2.setImageResource(R.drawable.ic_gallery_background); + imageView2.setScaleType(ImageView.ScaleType.CENTER); + addView(imageView2, LayoutHelper.createFrame(100, 100, Gravity.LEFT | Gravity.BOTTOM)); + + selectionView = new View(context); + selectionView.setBackgroundResource(R.drawable.wall_selection); + addView(selectionView, LayoutHelper.createFrame(100, 102)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(100), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(102), MeasureSpec.EXACTLY)); + } + + public void setWallpaper(TLRPC.WallPaper wallpaper, int selectedBackground) { + if (wallpaper == null) { + imageView.setVisibility(INVISIBLE); + imageView2.setVisibility(VISIBLE); + selectionView.setVisibility(selectedBackground == -1 ? View.VISIBLE : INVISIBLE); + imageView2.setBackgroundColor(selectedBackground == -1 || selectedBackground == 1000001 ? 0x5a475866 : 0x5a000000); + } else { + imageView.setVisibility(VISIBLE); + imageView2.setVisibility(INVISIBLE); + selectionView.setVisibility(selectedBackground == wallpaper.id ? View.VISIBLE : INVISIBLE); + + if (wallpaper instanceof TLRPC.TL_wallPaperSolid) { + imageView.setImageBitmap(null); + imageView.setBackgroundColor(0xff000000 | wallpaper.bg_color); + } else { + TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(wallpaper.sizes, AndroidUtilities.dp(100)); + if (size != null && size.location != null) { + imageView.setImage(size.location, "100_100", (Drawable) null); + } + imageView.setBackgroundColor(0x5a475866); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java index 66d3b748e..8eb72c7e1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java @@ -80,7 +80,8 @@ public class ChangeChatNameActivity extends BaseFragment { TLRPC.Chat currentChat = MessagesController.getInstance().getChat(chat_id); - fragmentView = new LinearLayout(context); + LinearLayout linearLayout = new LinearLayout(context); + fragmentView = linearLayout; fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL); fragmentView.setOnTouchListener(new View.OnTouchListener() { @@ -113,14 +114,7 @@ public class ChangeChatNameActivity extends BaseFragment { } }); - ((LinearLayout) fragmentView).addView(firstNameField); - LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) firstNameField.getLayoutParams(); - layoutParams.topMargin = AndroidUtilities.dp(24); - layoutParams.height = AndroidUtilities.dp(36); - layoutParams.leftMargin = AndroidUtilities.dp(24); - layoutParams.rightMargin = AndroidUtilities.dp(24); - layoutParams.width = LayoutHelper.MATCH_PARENT; - firstNameField.setLayoutParams(layoutParams); + linearLayout.addView(firstNameField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 24, 24, 24, 0)); if (chat_id > 0) { firstNameField.setHint(LocaleController.getString("GroupName", R.string.GroupName)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java index 490aa76dc..5c0088490 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java @@ -76,7 +76,8 @@ public class ChangeNameActivity extends BaseFragment { user = UserConfig.getCurrentUser(); } - fragmentView = new LinearLayout(context); + LinearLayout linearLayout = new LinearLayout(context); + fragmentView = linearLayout; fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL); fragmentView.setOnTouchListener(new View.OnTouchListener() { @@ -98,14 +99,7 @@ public class ChangeNameActivity extends BaseFragment { firstNameField.setImeOptions(EditorInfo.IME_ACTION_NEXT); firstNameField.setHint(LocaleController.getString("FirstName", R.string.FirstName)); AndroidUtilities.clearCursorDrawable(firstNameField); - ((LinearLayout) fragmentView).addView(firstNameField); - LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) firstNameField.getLayoutParams(); - layoutParams.topMargin = AndroidUtilities.dp(24); - layoutParams.height = AndroidUtilities.dp(36); - layoutParams.leftMargin = AndroidUtilities.dp(24); - layoutParams.rightMargin = AndroidUtilities.dp(24); - layoutParams.width = LayoutHelper.MATCH_PARENT; - firstNameField.setLayoutParams(layoutParams); + linearLayout.addView(firstNameField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 24, 24, 24, 0)); firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { @@ -130,14 +124,7 @@ public class ChangeNameActivity extends BaseFragment { lastNameField.setImeOptions(EditorInfo.IME_ACTION_DONE); lastNameField.setHint(LocaleController.getString("LastName", R.string.LastName)); AndroidUtilities.clearCursorDrawable(lastNameField); - ((LinearLayout) fragmentView).addView(lastNameField); - layoutParams = (LinearLayout.LayoutParams) lastNameField.getLayoutParams(); - layoutParams.topMargin = AndroidUtilities.dp(16); - layoutParams.height = AndroidUtilities.dp(36); - layoutParams.leftMargin = AndroidUtilities.dp(24); - layoutParams.rightMargin = AndroidUtilities.dp(24); - layoutParams.width = LayoutHelper.MATCH_PARENT; - lastNameField.setLayoutParams(layoutParams); + linearLayout.addView(lastNameField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 24, 16, 24, 0)); lastNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java index 0841e4a7c..1887a03b0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java @@ -8,6 +8,7 @@ package org.telegram.ui; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; @@ -132,27 +133,11 @@ public class ChangePhoneActivity extends BaseFragment { views[0] = new PhoneView(context); views[0].setVisibility(View.VISIBLE); - frameLayout.addView(views[0]); - FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) views[0].getLayoutParams(); - layoutParams1.width = LayoutHelper.MATCH_PARENT; - layoutParams1.height = LayoutHelper.WRAP_CONTENT; - layoutParams1.leftMargin = AndroidUtilities.dp(16); - layoutParams1.rightMargin = AndroidUtilities.dp(16); - layoutParams1.topMargin = AndroidUtilities.dp(30); - layoutParams1.gravity = Gravity.TOP | Gravity.LEFT; - views[0].setLayoutParams(layoutParams1); + frameLayout.addView(views[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 16, 30, 16, 0)); views[1] = new LoginActivitySmsView(context); views[1].setVisibility(View.GONE); - frameLayout.addView(views[1]); - layoutParams1 = (FrameLayout.LayoutParams) views[1].getLayoutParams(); - layoutParams1.width = LayoutHelper.MATCH_PARENT; - layoutParams1.height = LayoutHelper.MATCH_PARENT; - layoutParams1.leftMargin = AndroidUtilities.dp(16); - layoutParams1.rightMargin = AndroidUtilities.dp(16); - layoutParams1.topMargin = AndroidUtilities.dp(30); - layoutParams1.gravity = Gravity.TOP | Gravity.LEFT; - views[1].setLayoutParams(layoutParams1); + frameLayout.addView(views[1], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 16, 30, 16, 0)); try { if (views[0] == null || views[1] == null) { @@ -209,7 +194,7 @@ public class ChangePhoneActivity extends BaseFragment { builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(text); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showAlertDialog(builder); + showDialog(builder.create()); } public void needShowProgress() { @@ -258,6 +243,7 @@ public class ChangePhoneActivity extends BaseFragment { newView.setVisibility(View.VISIBLE); } + @SuppressLint("NewApi") @Override public void onAnimationEnd(Object animation) { outView.setVisibility(View.GONE); @@ -1066,18 +1052,13 @@ public class ChangePhoneActivity extends BaseFragment { @Override public void didReceivedNotification(int id, final Object... args) { if (id == NotificationCenter.didReceiveSmsCode) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (!waitingForSms) { - return; - } - if (codeField != null) { - codeField.setText("" + args[0]); - onNextPressed(); - } - } - }); + if (!waitingForSms) { + return; + } + if (codeField != null) { + codeField.setText("" + args[0]); + onNextPressed(); + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java index 362d91294..e4077ef3b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java @@ -148,7 +148,7 @@ public class ChangePhoneHelpActivity extends BaseFragment { } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java index 6e1d20ca8..0e40b1a41 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java @@ -215,7 +215,7 @@ public class ChangeUsernameActivity extends BaseFragment { break; } builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showAlertDialog(builder); + showDialog(builder.create()); } private boolean checkUserName(final String name, boolean alert) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 11eb1f3f1..133143686 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -10,7 +10,6 @@ package org.telegram.ui; import android.app.Activity; import android.app.AlertDialog; -import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -44,7 +43,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; -import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -57,7 +55,9 @@ import org.telegram.android.MessagesStorage; import org.telegram.android.NotificationsController; import org.telegram.android.SecretChatHelper; import org.telegram.android.SendMessagesHelper; +import org.telegram.android.VideoEditedInfo; import org.telegram.android.query.ReplyMessageQuery; +import org.telegram.android.query.StickersQuery; import org.telegram.android.support.widget.LinearLayoutManager; import org.telegram.android.support.widget.RecyclerView; import org.telegram.messenger.ApplicationLoader; @@ -74,7 +74,7 @@ import org.telegram.android.MessagesController; import org.telegram.android.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.Adapters.MentionsAdapter; import org.telegram.ui.Adapters.StickersAdapter; import org.telegram.android.AnimationCompat.AnimatorListenerAdapterProxy; @@ -98,13 +98,13 @@ import org.telegram.android.ImageReceiver; import org.telegram.ui.Components.FrameLayoutFixed; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecordStatusDrawable; -import org.telegram.ui.Components.RecyclerExListView; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.Components.SendingFileExDrawable; -import org.telegram.ui.Components.SizeNotifierRelativeLayout; +import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.TimerDrawable; import org.telegram.ui.Components.TypingDotsDrawable; +import org.telegram.ui.Components.WebFrameLayout; import java.io.File; import java.util.ArrayList; @@ -133,7 +133,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private ActionBarMenuItem attachItem; private ActionBarMenuItem headerItem; private TextView addContactItem; - private RecyclerExListView chatListView; + private RecyclerListView chatListView; private LinearLayoutManager chatLayoutManager; private ChatActivityAdapter chatAdapter; private BackupImageView avatarImageView; @@ -258,7 +258,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int id_chat_compose_panel = 1000; - RecyclerExListView.OnItemLongClickListener onItemLongClickListener = new RecyclerExListView.OnItemLongClickListener() { + RecyclerListView.OnItemLongClickListener onItemLongClickListener = new RecyclerListView.OnItemLongClickListener() { @Override public void onItemClick(View view, int position) { if (!actionBar.isActionModeShowed()) { @@ -267,7 +267,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }; - RecyclerExListView.OnItemClickListener onItemClickListener = new RecyclerExListView.OnItemClickListener() { + RecyclerListView.OnItemClickListener onItemClickListener = new RecyclerListView.OnItemClickListener() { @Override public void onItemClick(View view, int position) { if (actionBar.isActionModeShowed()) { @@ -543,7 +543,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onItemClick(final int id) { if (id == attach_photo || id == attach_gallery || id == attach_document || id == attach_video) { - String action = null; + String action; if (currentChat != null) { if (currentChat.participants_count > MessagesController.getInstance().groupBigSize) { if (id == attach_photo || id == attach_gallery) { @@ -582,7 +582,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (id == attach_photo) { try { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - File image = Utilities.generatePicturePath(); + File image = AndroidUtilities.generatePicturePath(); if (image != null) { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image)); currentPicturePath = image.getAbsolutePath(); @@ -635,7 +635,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (id == attach_video) { try { Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); - File video = Utilities.generateVideoPath(); + File video = AndroidUtilities.generateVideoPath(); if (video != null) { if (Build.VERSION.SDK_INT >= 18) { takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(video)); @@ -745,7 +745,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (id == forward) { Bundle args = new Bundle(); args.putBoolean("onlySelect", true); @@ -757,7 +757,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (getParentActivity() == null) { return; } - showAlertDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat)); + showDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat).create()); } else if (id == clear_history || id == delete_chat) { if (getParentActivity() == null) { return; @@ -779,7 +779,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onClick(DialogInterface dialogInterface, int i) { if (id != clear_history) { if (isChat) { - MessagesController.getInstance().deleteUserFromChat((int) -dialog_id, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), null); + if (currentChat.left || currentChat instanceof TLRPC.TL_chatForbidden) { + MessagesController.getInstance().deleteDialog(dialog_id, 0, false); + } else { + MessagesController.getInstance().deleteUserFromChat((int) -dialog_id, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), null); + } } else { MessagesController.getInstance().deleteDialog(dialog_id, 0, false); } @@ -790,7 +794,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (id == share_contact) { if (currentUser == null || getParentActivity() == null) { return; @@ -813,7 +817,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } } else if (id == mute) { boolean muted = MessagesController.getInstance().isDialogMuted(dialog_id); @@ -842,7 +846,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); - long flags = 0; + long flags; if (i == 3) { editor.putInt("notify2_" + dialog_id, 2); flags = 1; @@ -863,7 +867,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } ); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); @@ -942,7 +946,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (getParentActivity() == null) { return; } - showAlertDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat)); + showDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat).create()); } }); } @@ -1047,29 +1051,117 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } checkActionBarMenu(); - fragmentView = new SizeNotifierRelativeLayout(context); - - /* - { + fragmentView = new SizeNotifierFrameLayout(context) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (chatActivityEnterView chatActivityEnterView.isEmojiPopupShowing()) { - int height = MeasureSpec.getSize(heightMeasureSpec); - heightMeasureSpec = MeasureSpec.makeMeasureSpec(height - chatActivityEnterView.getEmojiHeight(), MeasureSpec.getMode(heightMeasureSpec)); + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); + heightSize -= getPaddingBottom(); + + int inputFieldHeight = 0; + + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child == chatActivityEnterView) { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + inputFieldHeight = child.getMeasuredHeight(); + break; + } } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child.getVisibility() == GONE || child == chatActivityEnterView) { + continue; + } + + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (child == chatListView) { + int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); + int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - inputFieldHeight + AndroidUtilities.dp(2)), MeasureSpec.EXACTLY); + child.measure(contentWidthSpec, contentHeightSpec); + } else { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int count = getChildCount(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) { + continue; + } + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + + int childLeft; + int childTop; + + int gravity = lp.gravity; + if (gravity == -1) { + gravity = Gravity.TOP | Gravity.LEFT; + } + + final int absoluteGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; + + switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + childLeft = (r - l - width) / 2 + lp.leftMargin - lp.rightMargin; + break; + case Gravity.RIGHT: + childLeft = r - width - lp.rightMargin; + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin; + } + + switch (verticalGravity) { + case Gravity.TOP: + childTop = lp.topMargin; + break; + case Gravity.CENTER_VERTICAL: + childTop = ((b - getPaddingBottom()) - t - height) / 2 + lp.topMargin - lp.bottomMargin; + break; + case Gravity.BOTTOM: + childTop = ((b - getPaddingBottom()) - t) - height - lp.bottomMargin; + break; + default: + childTop = lp.topMargin; + } + + if (child == mentionListView) { + childTop -= chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(2); + } else if (child == pagedownButton) { + childTop -= chatActivityEnterView.getMeasuredHeight(); + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + + notifyHeightChanged(); } }; - */ - SizeNotifierRelativeLayout contentView = (SizeNotifierRelativeLayout) fragmentView; + + SizeNotifierFrameLayout contentView = (SizeNotifierFrameLayout) fragmentView; contentView.setBackgroundImage(ApplicationLoader.getCachedWallpaper()); emptyViewContainer = new FrameLayout(context); emptyViewContainer.setPadding(0, 0, 0, AndroidUtilities.dp(48)); emptyViewContainer.setVisibility(View.INVISIBLE); - contentView.addView(emptyViewContainer, new RelativeLayout.LayoutParams(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + contentView.addView(emptyViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); emptyViewContainer.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -1079,7 +1171,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentEncryptedChat == null) { TextView emptyView = new TextView(context); - if (currentUser != null && currentUser.id != 777000 && (currentUser.id / 1000 == 333 || currentUser.id % 1000 == 0)) { + if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && (currentUser.id / 1000 == 333 || currentUser.id % 1000 == 0)) { emptyView.setText(LocaleController.getString("GotAQuestion", R.string.GotAQuestion)); } else { emptyView.setText(LocaleController.getString("NoMessages", R.string.NoMessages)); @@ -1164,7 +1256,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - chatListView = (RecyclerExListView) inflater.inflate(R.layout.recycler_view, null); + if (chatActivityEnterView != null) { + chatActivityEnterView.onDestroy(); + } + + chatListView = new RecyclerListView(context); + chatListView.setVerticalScrollBarEnabled(true); chatListView.setAdapter(chatAdapter = new ChatActivityAdapter(context)); chatListView.setClipToPadding(false); chatListView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(3)); @@ -1179,7 +1276,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); chatLayoutManager.setStackFromEnd(true); chatListView.setLayoutManager(chatLayoutManager); - contentView.addView(chatListView, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 0, -3, RelativeLayout.ABOVE, id_chat_compose_panel)); + contentView.addView(chatListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); chatListView.setOnItemLongClickListener(onItemLongClickListener); chatListView.setOnItemClickListener(onItemClickListener); chatListView.setOnScrollListener(new RecyclerView.OnScrollListener() { @@ -1271,7 +1368,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } }); - chatListView.setOnInterceptTouchListener(new RecyclerExListView.OnInterceptTouchListener() { + chatListView.setOnInterceptTouchListener(new RecyclerListView.OnInterceptTouchListener() { @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (actionBar.isActionModeShowed()) { @@ -1295,7 +1392,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } final ChatMediaCell cell = (ChatMediaCell) view; final MessageObject messageObject = cell.getMessageObject(); - if (messageObject == null || !messageObject.isSecretPhoto() || !cell.getPhotoImage().isInsideImage(x, y - top)) { + if (messageObject == null || messageObject.isSending() || !messageObject.isSecretPhoto() || !cell.getPhotoImage().isInsideImage(x, y - top)) { break; } File file = FileLoader.getPathToMessage(messageObject.messageOwner); @@ -1332,7 +1429,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not progressView = new FrameLayout(context); progressView.setVisibility(View.INVISIBLE); - contentView.addView(progressView, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 0, 48)); + contentView.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 48)); View view = new View(context); view.setBackgroundResource(ApplicationLoader.isCustomTheme() ? R.drawable.system_loader2 : R.drawable.system_loader1); @@ -1359,13 +1456,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (Build.VERSION.SDK_INT > 8) { mentionListView.setOverScrollMode(ListView.OVER_SCROLL_NEVER); } - contentView.addView(mentionListView, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, 110, 0, -108, 0, 0, RelativeLayout.ALIGN_TOP, id_chat_compose_panel)); + contentView.addView(mentionListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); mentionListView.setAdapter(mentionsAdapter = new MentionsAdapter(context, false, new MentionsAdapter.MentionsAdapterDelegate() { @Override public void needChangePanelVisibility(boolean show) { if (show) { - RelativeLayout.LayoutParams layoutParams3 = (RelativeLayout.LayoutParams) mentionListView.getLayoutParams(); + FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) mentionListView.getLayoutParams(); int height = 36 * Math.min(3, mentionsAdapter.getCount()) + (mentionsAdapter.getCount() > 3 ? 18 : 0); layoutParams3.height = AndroidUtilities.dp(2 + height); layoutParams3.topMargin = -AndroidUtilities.dp(height); @@ -1470,7 +1567,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); return true; } return false; @@ -1478,14 +1575,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); } - if (chatActivityEnterView != null) { - chatActivityEnterView.onDestroy(); - } chatActivityEnterView = new ChatActivityEnterView(getParentActivity(), contentView, this, true); chatActivityEnterView.setDialogId(dialog_id); chatActivityEnterView.addToAttachLayout(menuItem); chatActivityEnterView.setId(id_chat_compose_panel); - contentView.addView(chatActivityEnterView, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, RelativeLayout.ALIGN_PARENT_BOTTOM)); + contentView.addView(chatActivityEnterView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { @Override public void onMessageSend(String message) { @@ -1494,9 +1588,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionsAdapter != null) { mentionsAdapter.addHashtagsFromMessage(message); } - if (message != null) { - NotificationsController.getInstance().playOutChatSound(); - } } @Override @@ -1629,9 +1720,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stickersPanel = new FrameLayout(context); stickersPanel.setVisibility(View.GONE); - contentView.addView(stickersPanel, LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, 81.5f, 0, 0, 0, 38, RelativeLayout.ALIGN_BOTTOM, id_chat_compose_panel)); + contentView.addView(stickersPanel, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 81.5f, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 38)); stickersListView = new RecyclerListView(context); + stickersListView.setDisallowInterceptTouchEvents(true); LinearLayoutManager layoutManager = new LinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); stickersListView.setLayoutManager(layoutManager); @@ -1686,7 +1778,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } })); - stickersListView.addOnItemTouchListener(new RecyclerListView.RecyclerListViewItemClickListener(context, new RecyclerListView.OnItemClickListener() { + stickersListView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { @Override public void onItemClick(View view, int position) { TLRPC.Document document = stickersAdapter.getItem(position); @@ -1696,7 +1788,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatActivityEnterView.setFieldText(""); } - })); + }); } imageView = new ImageView(context); @@ -1709,7 +1801,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomOverlay.setFocusable(true); bottomOverlay.setFocusableInTouchMode(true); bottomOverlay.setClickable(true); - contentView.addView(bottomOverlay, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, 48, RelativeLayout.ALIGN_PARENT_BOTTOM)); + contentView.addView(bottomOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM)); bottomOverlayText = new TextView(context); bottomOverlayText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); @@ -1719,7 +1811,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomOverlayChat = new FrameLayout(context); bottomOverlayChat.setBackgroundColor(0xfffbfcfd); bottomOverlayChat.setVisibility(View.INVISIBLE); - contentView.addView(bottomOverlayChat, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, 48, RelativeLayout.ALIGN_PARENT_BOTTOM)); + contentView.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM)); bottomOverlayChat.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -1747,7 +1839,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); } builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } }); @@ -1759,7 +1851,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pagedownButton = new ImageView(context); pagedownButton.setVisibility(View.INVISIBLE); pagedownButton.setImageResource(R.drawable.pagedown); - contentView.addView(pagedownButton, LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 0, 6, 4, RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.ABOVE, id_chat_compose_panel)); + contentView.addView(pagedownButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 4)); pagedownButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -1786,6 +1878,33 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return fragmentView; } + private boolean searchForHttpInText(CharSequence string) { + int len = string.length(); + int seqLen = 0; + for (int a = 0; a < len; a++) { + char ch = string.charAt(a); + if (seqLen == 0 && (ch == 'h' || ch == 'H')) { + seqLen++; + } else if ((seqLen == 1 || seqLen == 2) && (ch == 't' || ch == 'T')) { + seqLen++; + } else if (seqLen == 3 && (ch == 'p' || ch == 'P')) { + seqLen++; + } else if (seqLen == 4 && (ch == 's' || ch == 'S')) { + seqLen++; + } else if ((seqLen == 4 || seqLen == 5) && ch == ':') { + seqLen++; + } else if ((seqLen == 5 || seqLen == 6 || seqLen == 7) && ch == '/') { + if (seqLen == 6 || seqLen == 7) { + return true; + } + seqLen++; + } else if (seqLen != 0) { + seqLen = 0; + } + } + return false; + } + private void searchLinks(CharSequence charSequence, boolean force) { if (currentEncryptedChat != null) { return; @@ -1814,7 +1933,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pendingLinkSearchString = null; showReplyPanel(false, null, null, foundWebPage, false, true); } - if (charSequence.length() < 13 || TextUtils.indexOf(charSequence, "http://") == -1 && TextUtils.indexOf(charSequence, "https://") == -1) { + if (charSequence.length() < 13 || !searchForHttpInText(charSequence)) { return; } final TLRPC.TL_messages_getWebPagePreview req = new TLRPC.TL_messages_getWebPagePreview(); @@ -1982,7 +2101,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedSticker", messageObjects.size())); } else if (type == 8 || type == 9) { if (messageObjects.size() == 1) { - String name = null; + String name; if ((name = FileLoader.getDocumentFileName(messageObjects.get(0).messageOwner.media.document)).length() != 0) { replyObjectTextView.setText(name); } @@ -2309,7 +2428,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!messageObject.isMediaEmpty()) { return 0; } else { - return 7; + return 20; } } else { return -1; @@ -2327,6 +2446,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVideo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + if (messageObject.isSticker()) { + TLRPC.InputStickerSet inputStickerSet = messageObject.getInputStickerSet(); + if (inputStickerSet != null && !StickersQuery.isStickerPackInstalled(inputStickerSet.id)) { + return 7; + } + } boolean canSave = false; if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() != 0) { File f = new File(messageObject.messageOwner.attachPath); @@ -2370,7 +2495,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!messageObject.isMediaEmpty()) { return 0; } else { - return 7; + return 20; } } else if (messageObject.type == 10 || messageObject.type == 11) { if (messageObject.getId() == 0 || messageObject.isSending()) { @@ -2383,6 +2508,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVideo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + if (messageObject.isSticker()) { + TLRPC.InputStickerSet inputStickerSet = messageObject.getInputStickerSet(); + if (inputStickerSet != null && !StickersQuery.isStickerPackInstalled(inputStickerSet.id)) { + return 7; + } + } boolean canSave = false; if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() != 0) { File f = new File(messageObject.messageOwner.attachPath); @@ -2449,7 +2580,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int type = getMessageType(message); - if (type < 2 || type == 7) { + if (type < 2 || type == 8) { return; } addToSelectedMessages(message); @@ -2651,7 +2782,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragment.setDelegate(new VideoEditorActivity.VideoEditorActivityDelegate() { @Override public void didFinishEditVideo(String videoPath, long startTime, long endTime, int resultWidth, int resultHeight, int rotationValue, int originalWidth, int originalHeight, int bitrate, long estimatedSize, long estimatedDuration) { - TLRPC.VideoEditedInfo videoEditedInfo = new TLRPC.VideoEditedInfo(); + VideoEditedInfo videoEditedInfo = new VideoEditedInfo(); videoEditedInfo.startTime = startTime; videoEditedInfo.endTime = endTime; videoEditedInfo.rotationValue = rotationValue; @@ -2722,7 +2853,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } }, this); - Utilities.addMediaToGallery(currentPicturePath); + AndroidUtilities.addMediaToGallery(currentPicturePath); currentPicturePath = null; } else if (requestCode == 1) { if (data == null || data.getData() == null) { @@ -2733,7 +2864,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (uri.toString().contains("video")) { String videoPath = null; try { - videoPath = Utilities.getPath(uri); + videoPath = AndroidUtilities.getPath(uri); } catch (Exception e) { FileLog.e("tmessages", e); } @@ -2763,7 +2894,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { videoPath = currentPicturePath; } - Utilities.addMediaToGallery(currentPicturePath); + AndroidUtilities.addMediaToGallery(currentPicturePath); currentPicturePath = null; } if (videoPath == null && currentPicturePath != null) { @@ -2788,7 +2919,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showAttachmentError(); return; } - String tempPath = Utilities.getPath(data.getData()); + String tempPath = AndroidUtilities.getPath(data.getData()); String originalPath = tempPath; if (tempPath == null) { originalPath = data.toString(); @@ -3157,7 +3288,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(LocaleController.formatString("CompatibilityChat", R.string.CompatibilityChat, currentUser.first_name, currentUser.first_name)); - showAlertDialog(builder); + showDialog(builder.create()); } } } @@ -3459,6 +3590,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mediaUpdated && chatLayoutManager.findLastVisibleItemPosition() >= messages.size() - 1) { moveScrollToLastMessage(); } + NotificationsController.getInstance().playOutChatSound(); } } else if (id == NotificationCenter.messageReceivedByAck) { Integer msgId = (Integer) args[0]; @@ -3692,7 +3824,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void onOpenAnimationEnd() { + protected void onOpenAnimationStart() { + NotificationCenter.getInstance().setAnimationInProgress(true); + } + + @Override + protected void onOpenAnimationEnd() { + NotificationCenter.getInstance().setAnimationInProgress(false); openAnimationEnded = true; int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { @@ -3985,7 +4123,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesIds.clear(); actionBar.hideActionMode(); - if (single || type < 2 || type == 7) { + if (single || type < 2 || type == 20) { if (type >= 0) { selectedObject = message; if (getParentActivity() == null) { @@ -4007,7 +4145,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not items = new CharSequence[]{LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{1}; } - } else if (type == 7) { + } else if (type == 20) { items = new CharSequence[]{LocaleController.getString("Retry", R.string.Retry), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{0, 3, 1}; } else { @@ -4021,17 +4159,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options = new int[]{8, 2, 3, 1}; } else if (type == 4) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { - items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 10, 4, 2, 1}; } else { items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 4, 2, 1}; } - options = new int[]{8, 4, 2, 1}; } else if (type == 5) { items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{8, 5, 4, 2, 1}; } else if (type == 6) { - items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; - options = new int[]{8, 7, 6, 2, 1}; + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 7, 10, 6, 2, 1}; + } else if (type == 7) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("AddToStickers", R.string.AddToStickers), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 2, 9, 1}; } } else { if (type == 2) { @@ -4042,17 +4184,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options = new int[]{2, 3, 1}; } else if (type == 4) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { - items = new CharSequence[]{LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + items = new CharSequence[]{LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{10, 4, 2, 1}; } else { items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{4, 2, 1}; } - options = new int[]{4, 2, 1}; } else if (type == 5) { items = new CharSequence[]{LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{5, 4, 2, 1}; } else if (type == 6) { - items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; - options = new int[]{7, 6, 2, 1}; + items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{7, 10, 6, 2, 1}; + } else if (type == 7) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("AddToStickers", R.string.AddToStickers), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 2, 9, 1}; } } } else { @@ -4064,14 +4210,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options = new int[]{3, 1}; } else if (type == 4) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { - items = new CharSequence[]{LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Delete", R.string.Delete)}; + items = new CharSequence[]{LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{10, 4, 1}; } else { items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{4, 1}; } - options = new int[]{4, 1}; } else if (type == 5) { items = new CharSequence[]{LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{5, 1}; + } else if (type == 7) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("AddToStickers", R.string.AddToStickers), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 2, 9, 1}; } } } @@ -4088,7 +4238,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); builder.setTitle(LocaleController.getString("Message", R.string.Message)); - showAlertDialog(builder); + showDialog(builder.create()); } return; } @@ -4144,7 +4294,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (option == 2) { forwaringMessage = selectedObject; Bundle args = new Bundle(); @@ -4209,7 +4359,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("IncorrectLocalization", R.string.IncorrectLocalization)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showAlertDialog(builder); + showDialog(builder.create()); } } } else if (option == 6 || option == 7) { @@ -4236,77 +4386,31 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (option == 8) { showReplyPanel(true, selectedObject, null, null, false, true); + } else if (option == 9) { + StickersQuery.loadStickers(this, selectedObject.getInputStickerSet()); + } else if (option == 10) { + String fileName = FileLoader.getDocumentFileName(selectedObject.messageOwner.media.document); + if (fileName == null || fileName.length() == 0) { + fileName = selectedObject.getFileName(); + } + String path = selectedObject.messageOwner.attachPath; + if (path != null && path.length() > 0) { + File temp = new File(path); + if (!temp.exists()) { + path = null; + } + } + if (path == null || path.length() == 0) { + path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + } + MediaController.saveFile(path, getParentActivity(), 2, fileName); } selectedObject = null; } - private void openProfileWithUsername(String username) { - TLRPC.User user = MessagesController.getInstance().getUser(username); - if (user != null) { - Bundle args = new Bundle(); - args.putInt("user_id", user.id); - presentFragment(new ProfileActivity(args)); - } else { - if (getParentActivity() == null) { - return; - } - final ProgressDialog progressDialog = new ProgressDialog(getParentActivity()); - progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); - progressDialog.setCanceledOnTouchOutside(false); - progressDialog.setCancelable(false); - - TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); - req.username = username; - final long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(final TLObject response, final TLRPC.TL_error error) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - try { - progressDialog.dismiss(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - visibleDialog = null; - if (error == null) { - TLRPC.User user = (TLRPC.User) response; - MessagesController.getInstance().putUser(user, false); - ArrayList users = new ArrayList<>(); - users.add(user); - MessagesStorage.getInstance().putUsersAndChats(users, null, false, true); - Bundle args = new Bundle(); - args.putInt("user_id", user.id); - presentFragment(new ProfileActivity(args)); - } - } - }); - } - }); - progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ConnectionsManager.getInstance().cancelRpc(reqId, true); - try { - dialog.dismiss(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - visibleDialog = null; - } - }); - visibleDialog = progressDialog; - progressDialog.show(); - } - } - @Override public void didSelectDialog(MessagesActivity activity, long did, boolean param) { if (dialog_id != 0 && (forwaringMessage != null || !selectedMessagesIds.isEmpty())) { - if (isBroadcast) { - param = true; - } - ArrayList fmessages = new ArrayList<>(); if (forwaringMessage != null) { fmessages.add(forwaringMessage); @@ -4404,7 +4508,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); return false; } } @@ -4452,7 +4556,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.messageOwner.media.document.mime_type)); } - showAlertDialog(builder); + showDialog(builder.create()); } @Override @@ -4569,7 +4673,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public long getItemId(int i) { - return RecyclerExListView.NO_ID; + return RecyclerListView.NO_ID; } @Override @@ -4640,7 +4744,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void didPressUrl(String url) { if (url.startsWith("@")) { - openProfileWithUsername(url.substring(1)); + MessagesController.openByUserName(url.substring(1), ChatActivity.this, 0); } else if (url.startsWith("#")) { MessagesActivity fragment = new MessagesActivity(null); fragment.setSearchString(url); @@ -4648,6 +4752,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + @Override + public void needOpenWebView(String url, String title, String originalUrl, int w, int h) { + BottomSheet.Builder builder = new BottomSheet.Builder(mContext); + builder.setCustomView(new WebFrameLayout(mContext, builder.create(), title, originalUrl, url, w, h)); + builder.setOverrideTabletWidth(true); + showDialog(builder.create()); + } + @Override public void didPressReplyMessage(ChatBaseCell cell, int id) { scrollToMessageId(id, cell.getMessageObject().getId(), true); @@ -4798,7 +4910,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } ); - showAlertDialog(builder); + showDialog(builder.create()); } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java index b8001641c..57e0b98a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java @@ -24,7 +24,6 @@ import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.android.NotificationCenter; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.Utilities; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoAlbumPickerActivity; import org.telegram.ui.PhotoCropActivity; @@ -62,7 +61,7 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg public void openCamera() { try { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - File image = Utilities.generatePicturePath(); + File image = AndroidUtilities.generatePicturePath(); if (image != null) { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image)); currentPicturePath = image.getAbsolutePath(); @@ -163,7 +162,7 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg processBitmap(bitmap); } }, null); - Utilities.addMediaToGallery(currentPicturePath); + AndroidUtilities.addMediaToGallery(currentPicturePath); currentPicturePath = null; } else if (requestCode == 14) { if (data == null || data.getData() == null) { @@ -205,37 +204,27 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg if (id == NotificationCenter.FileDidUpload) { String location = (String)args[0]; if (uploadingAvatar != null && location.equals(uploadingAvatar)) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationCenter.getInstance().removeObserver(AvatarUpdater.this, NotificationCenter.FileDidUpload); - NotificationCenter.getInstance().removeObserver(AvatarUpdater.this, NotificationCenter.FileDidFailUpload); - if (delegate != null) { - delegate.didUploadedPhoto((TLRPC.InputFile)args[1], smallPhoto, bigPhoto); - } - uploadingAvatar = null; - if (clearAfterUpdate) { - parentFragment = null; - delegate = null; - } - } - }); + NotificationCenter.getInstance().removeObserver(AvatarUpdater.this, NotificationCenter.FileDidUpload); + NotificationCenter.getInstance().removeObserver(AvatarUpdater.this, NotificationCenter.FileDidFailUpload); + if (delegate != null) { + delegate.didUploadedPhoto((TLRPC.InputFile)args[1], smallPhoto, bigPhoto); + } + uploadingAvatar = null; + if (clearAfterUpdate) { + parentFragment = null; + delegate = null; + } } } else if (id == NotificationCenter.FileDidFailUpload) { String location = (String)args[0]; if (uploadingAvatar != null && location.equals(uploadingAvatar)) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationCenter.getInstance().removeObserver(AvatarUpdater.this, NotificationCenter.FileDidUpload); - NotificationCenter.getInstance().removeObserver(AvatarUpdater.this, NotificationCenter.FileDidFailUpload); - uploadingAvatar = null; - if (clearAfterUpdate) { - parentFragment = null; - delegate = null; - } - } - }); + NotificationCenter.getInstance().removeObserver(AvatarUpdater.this, NotificationCenter.FileDidUpload); + NotificationCenter.getInstance().removeObserver(AvatarUpdater.this, NotificationCenter.FileDidFailUpload); + uploadingAvatar = null; + if (clearAfterUpdate) { + parentFragment = null; + delegate = null; + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index 3d991dde3..5fa640c07 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -45,39 +45,43 @@ public class BackupImageView extends View { imageReceiver = new ImageReceiver(this); } + public void setImage(TLObject path, String filter, String ext, Drawable thumb) { + setImage(path, null, filter, thumb, null, null, null, ext, 0); + } + public void setImage(TLObject path, String filter, Drawable thumb) { - setImage(path, null, filter, thumb, null, null, null, 0); + setImage(path, null, filter, thumb, null, null, null, null, 0); } public void setImage(TLObject path, String filter, Bitmap thumb) { - setImage(path, null, filter, null, thumb, null, null, 0); + setImage(path, null, filter, null, thumb, null, null, null, 0); } public void setImage(TLObject path, String filter, Drawable thumb, int size) { - setImage(path, null, filter, thumb, null, null, null, size); + setImage(path, null, filter, thumb, null, null, null, null, size); } public void setImage(TLObject path, String filter, Bitmap thumb, int size) { - setImage(path, null, filter, null, thumb, null, null, size); + setImage(path, null, filter, null, thumb, null, null, null, size); } public void setImage(TLObject path, String filter, TLRPC.FileLocation thumb, int size) { - setImage(path, null, filter, null, null, thumb, null, size); + setImage(path, null, filter, null, null, thumb, null, null, size); } public void setImage(String path, String filter, Drawable thumb) { - setImage(null, path, filter, thumb, null, null, null, 0); + setImage(null, path, filter, thumb, null, null, null, null, 0); } public void setOrientation(int angle, boolean center) { imageReceiver.setOrientation(angle, center); } - public void setImage(TLObject path, String httpUrl, String filter, Drawable thumb, Bitmap thumbBitmap, TLRPC.FileLocation thumbLocation, String thumbFilter, int size) { + public void setImage(TLObject path, String httpUrl, String filter, Drawable thumb, Bitmap thumbBitmap, TLRPC.FileLocation thumbLocation, String thumbFilter, String ext, int size) { if (thumbBitmap != null) { thumb = new BitmapDrawable(null, thumbBitmap); } - imageReceiver.setImage(path, httpUrl, filter, thumb, thumbLocation, thumbFilter, size, false); + imageReceiver.setImage(path, httpUrl, filter, thumb, thumbLocation, thumbFilter, size, ext, false); } public void setImageBitmap(Bitmap bitmap) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index 233374b32..4d6580a2e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -73,7 +73,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private ImageView audioSendButton; private FrameLayout recordPanel; private LinearLayout slideText; - private SizeNotifierRelativeLayout sizeNotifierRelativeLayout; + private View sizeNotifierLayout; private FrameLayout attachButton; private LinearLayout textFieldContainer; private View topView; @@ -118,7 +118,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private boolean allowShowTopView; private AnimatorSetProxy currentTopViewAnimation; - public ChatActivityEnterView(Activity context, SizeNotifierRelativeLayout parent, BaseFragment fragment, boolean isChat) { + public ChatActivityEnterView(Activity context, View parent, BaseFragment fragment, boolean isChat) { super(context); setBackgroundResource(R.drawable.compose_panel); setFocusable(true); @@ -135,8 +135,12 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioRouteChanged); parentActivity = context; parentFragment = fragment; - sizeNotifierRelativeLayout = parent; - sizeNotifierRelativeLayout.setDelegate(this); + sizeNotifierLayout = parent; + if (sizeNotifierLayout instanceof SizeNotifierRelativeLayout) { + ((SizeNotifierRelativeLayout) sizeNotifierLayout).setDelegate(this); + } else if (sizeNotifierLayout instanceof SizeNotifierFrameLayout) { + ((SizeNotifierFrameLayout) sizeNotifierLayout).setDelegate(this); + } SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); sendByEnter = preferences.getBoolean("send_by_enter", false); @@ -155,7 +159,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } else if (keyboardTransitionState == 2) { if (!keyboardVisible || framesDroped >= 60) { int currentHeight = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight; - sizeNotifierRelativeLayout.setPadding(0, 0, 0, currentHeight); + sizeNotifierLayout.setPadding(0, 0, 0, currentHeight); keyboardTransitionState = 0; } framesDroped++; @@ -433,8 +437,8 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat public boolean onTouch(View view, MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { if (parentFragment != null) { - String action = null; - TLRPC.Chat currentChat = null; + String action; + TLRPC.Chat currentChat; if ((int) dialog_id < 0) { currentChat = MessagesController.getInstance().getChat(-(int) dialog_id); if (currentChat != null && currentChat.participants_count > MessagesController.getInstance().groupBigSize) { @@ -535,14 +539,14 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } else if (state == 2) { int currentHeight = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight; - sizeNotifierRelativeLayout.setPadding(0, 0, 0, currentHeight); + sizeNotifierLayout.setPadding(0, 0, 0, currentHeight); keyboardTransitionState = 0; } } else { framesDroped = 0; keyboardTransitionState = state; if (state == 1) { - sizeNotifierRelativeLayout.setPadding(0, 0, 0, 0); + sizeNotifierLayout.setPadding(0, 0, 0, 0); } } } @@ -591,9 +595,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat topViewShowed = true; if (allowShowTopView) { topView.setVisibility(VISIBLE); - float resumeValue = 0.0f; if (currentTopViewAnimation != null) { - resumeValue = topViewAnimation; currentTopViewAnimation.cancel(); currentTopViewAnimation = null; } @@ -706,7 +708,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat NotificationCenter.getInstance().removeObserver(this, NotificationCenter.emojiDidLoaded); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.hideEmojiKeyboard); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioRouteChanged); - sizeNotifierRelativeLayout.getViewTreeObserver().removeOnPreDrawListener(onPreDrawListener); + sizeNotifierLayout.getViewTreeObserver().removeOnPreDrawListener(onPreDrawListener); if (mWakeLock != null) { try { mWakeLock.release(); @@ -715,8 +717,12 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat FileLog.e("tmessages", e); } } - if (sizeNotifierRelativeLayout != null) { - sizeNotifierRelativeLayout.setDelegate(null); + if (sizeNotifierLayout != null) { + if (sizeNotifierLayout instanceof SizeNotifierRelativeLayout) { + ((SizeNotifierRelativeLayout) sizeNotifierLayout).setDelegate(null); + } else if (sizeNotifierLayout instanceof SizeNotifierFrameLayout) { + ((SizeNotifierFrameLayout) sizeNotifierLayout).setDelegate(null); + } } } @@ -739,8 +745,8 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private void sendMessage() { if (parentFragment != null) { - String action = null; - TLRPC.Chat currentChat = null; + String action; + TLRPC.Chat currentChat; if ((int) dialog_id < 0) { currentChat = MessagesController.getInstance().getChat(-(int) dialog_id); if (currentChat != null && currentChat.participants_count > MessagesController.getInstance().groupBigSize) { @@ -1066,8 +1072,8 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat if (i < 0) { i = 0; } - try { - CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); + try {//TODO check + CharSequence localCharSequence = Emoji.replaceEmoji(symbol/* + "\uFE0F"*/, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); messageEditText.setText(messageEditText.getText().insert(i, localCharSequence)); int j = i + localCharSequence.length(); messageEditText.setSelection(j, j); @@ -1095,18 +1101,18 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat int currentHeight = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight; FileLog.e("tmessages", "show emoji with height = " + currentHeight); emojiPopup.setHeight(View.MeasureSpec.makeMeasureSpec(currentHeight, View.MeasureSpec.EXACTLY)); - if (sizeNotifierRelativeLayout != null) { + if (sizeNotifierLayout != null) { emojiPopup.setWidth(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.EXACTLY)); } emojiPopup.showAtLocation(parentActivity.getWindow().getDecorView(), Gravity.BOTTOM | Gravity.LEFT, 0, 0); if (!keyboardVisible) { - if (sizeNotifierRelativeLayout != null) { - sizeNotifierRelativeLayout.setPadding(0, 0, 0, currentHeight); + if (sizeNotifierLayout != null) { + sizeNotifierLayout.setPadding(0, 0, 0, currentHeight); emojiButton.setImageResource(R.drawable.ic_msg_panel_hide); showKeyboardOnEmojiButton = false; - onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); + onWindowSizeChanged(sizeNotifierLayout.getHeight() - sizeNotifierLayout.getPaddingBottom()); } return; } else { @@ -1129,19 +1135,19 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } } if (keyboardTransitionState == 0) { - if (sizeNotifierRelativeLayout != null) { + if (sizeNotifierLayout != null) { if (post) { - sizeNotifierRelativeLayout.post(new Runnable() { + sizeNotifierLayout.post(new Runnable() { public void run() { - if (sizeNotifierRelativeLayout != null) { - sizeNotifierRelativeLayout.setPadding(0, 0, 0, 0); - onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight()); + if (sizeNotifierLayout != null) { + sizeNotifierLayout.setPadding(0, 0, 0, 0); + onWindowSizeChanged(sizeNotifierLayout.getHeight()); } } }); } else { - sizeNotifierRelativeLayout.setPadding(0, 0, 0, 0); - onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight()); + sizeNotifierLayout.setPadding(0, 0, 0, 0); + onWindowSizeChanged(sizeNotifierLayout.getHeight()); } } } @@ -1262,12 +1268,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } if (emojiPopup != null && emojiPopup.isShowing()) { - int newHeight = 0; - if (isWidthGreater) { - newHeight = keyboardHeightLand; - } else { - newHeight = keyboardHeight; - } + int newHeight = isWidthGreater ? keyboardHeightLand : keyboardHeight; final WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) emojiPopup.getContentView().getLayoutParams(); FileLog.e("tmessages", "update emoji height to = " + newHeight); if (layoutParams.width != AndroidUtilities.displaySize.x || layoutParams.height != newHeight) { @@ -1277,10 +1278,10 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat if (wm != null) { wm.updateViewLayout(emojiPopup.getContentView(), layoutParams); if (!keyboardVisible) { - if (sizeNotifierRelativeLayout != null) { - sizeNotifierRelativeLayout.setPadding(0, 0, 0, layoutParams.height); - sizeNotifierRelativeLayout.requestLayout(); - onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); + if (sizeNotifierLayout != null) { + sizeNotifierLayout.setPadding(0, 0, 0, layoutParams.height); + sizeNotifierLayout.requestLayout(); + onWindowSizeChanged(sizeNotifierLayout.getHeight() - sizeNotifierLayout.getPaddingBottom()); } } } @@ -1289,13 +1290,13 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat boolean oldValue = keyboardVisible; keyboardVisible = height > 0; - if (keyboardVisible && (sizeNotifierRelativeLayout.getPaddingBottom() > 0 || keyboardTransitionState == 1)) { + if (keyboardVisible && (sizeNotifierLayout.getPaddingBottom() > 0 || keyboardTransitionState == 1)) { setKeyboardTransitionState(1); } else if (keyboardTransitionState != 2 && !keyboardVisible && keyboardVisible != oldValue && emojiPopup != null && emojiPopup.isShowing()) { showEmojiPopup(false, true); } if (keyboardTransitionState == 0) { - onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); + onWindowSizeChanged(sizeNotifierLayout.getHeight() - sizeNotifierLayout.getPaddingBottom()); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 2800d68a9..260b398c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -8,7 +8,9 @@ package org.telegram.ui.Components; +import android.app.Activity; import android.content.Context; +import android.content.SharedPreferences; import android.database.DataSetObserver; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; @@ -30,11 +32,15 @@ import org.telegram.android.Emoji; import org.telegram.android.LocaleController; import org.telegram.android.NotificationCenter; import org.telegram.android.query.StickersQuery; +import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.ui.Cells.StickerEmojiCell; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; public class EmojiView extends LinearLayout implements NotificationCenter.NotificationCenterDelegate { @@ -46,6 +52,9 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi private ArrayList adapters = new ArrayList<>(); private StickersGridAdapter stickersGridAdapter; + private HashMap stickersUseHistory = new HashMap<>(); + private ArrayList stickers; + private int[] icons = { R.drawable.ic_emoji_recent, R.drawable.ic_emoji_smile, @@ -58,15 +67,19 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi private Listener listener; private ViewPager pager; private FrameLayout recentsWrap; + private FrameLayout emojiWrap; private ArrayList views = new ArrayList<>(); private ImageView backspaceButton; private boolean backspacePressed; private boolean backspaceOnce; + private boolean showStickers; public EmojiView(boolean needStickers, Context context) { super(context); + showStickers = needStickers; + setOrientation(LinearLayout.VERTICAL); for (int i = 0; i < Emoji.data.length; i++) { GridView gridView = new GridView(context); @@ -84,7 +97,9 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi adapters.add(emojiGridAdapter); } - if (needStickers) { + if (showStickers) { + StickersQuery.checkStickers(); + stickers = StickersQuery.getStickers(); GridView gridView = new GridView(context); gridView.setColumnWidth(AndroidUtilities.dp(72)); gridView.setNumColumns(-1); @@ -157,6 +172,19 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi recentsWrap.addView(textView); views.get(0).setEmptyView(textView); + if (views.size() > 6) { + emojiWrap = new FrameLayout(context); + emojiWrap.addView(views.get(6)); + + textView = new TextView(context); + textView.setText(LocaleController.getString("NoStickers", R.string.NoStickers)); + textView.setTextSize(18); + textView.setTextColor(0xff888888); + textView.setGravity(Gravity.CENTER); + emojiWrap.addView(textView); + views.get(6).setEmptyView(textView); + } + addView(pager); loadRecents(); @@ -223,37 +251,103 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi } private void saveRecents() { - ArrayList localArrayList = new ArrayList<>(); - long[] arrayOfLong = Emoji.data[0]; - int i = arrayOfLong.length; - for (int j = 0; ; j++) { - if (j >= i) { - getContext().getSharedPreferences("emoji", 0).edit().putString("recents", TextUtils.join(",", localArrayList)).commit(); - return; - } - localArrayList.add(arrayOfLong[j]); + ArrayList arrayList = new ArrayList<>(Emoji.data[0].length); + for (int j = 0; j < Emoji.data[0].length; j++) { + arrayList.add(Emoji.data[0][j]); } + getContext().getSharedPreferences("emoji", 0).edit().putString("recents", TextUtils.join(",", arrayList)).commit(); + } + + private void saveRecentStickers() { + SharedPreferences preferences = getContext().getSharedPreferences("emoji", Activity.MODE_PRIVATE); + StringBuilder stringBuilder = new StringBuilder(); + for (HashMap.Entry entry : stickersUseHistory.entrySet()) { + if (stringBuilder.length() != 0) { + stringBuilder.append(","); + } + stringBuilder.append(entry.getKey()); + stringBuilder.append("="); + stringBuilder.append(entry.getValue()); + } + getContext().getSharedPreferences("emoji", 0).edit().putString("stickers", stringBuilder.toString()).commit(); + } + + private void sortStickers() { + HashMap hashMap = new HashMap<>(); + for (TLRPC.Document document : stickers) { + Integer count = stickersUseHistory.get(document.id); + if (count != null) { + hashMap.put(document.id, count); + stickersUseHistory.remove(document.id); + } + } + if (!stickersUseHistory.isEmpty()) { + stickersUseHistory = hashMap; + saveRecents(); + } else { + stickersUseHistory = hashMap; + } + Collections.sort(stickers, new Comparator() { + @Override + public int compare(TLRPC.Document lhs, TLRPC.Document rhs) { + Integer count1 = stickersUseHistory.get(lhs.id); + Integer count2 = stickersUseHistory.get(rhs.id); + if (count1 == null) { + count1 = 0; + } + if (count2 == null) { + count2 = 0; + } + if (count1 > count2) { + return -1; + } else if (count1 < count2) { + return 1; + } + return 0; + } + }); } public void loadRecents() { - String str = getContext().getSharedPreferences("emoji", 0).getString("recents", ""); - String[] arrayOfString = null; - if (str != null && str.length() > 0) { - arrayOfString = str.split(","); - Emoji.data[0] = new long[arrayOfString.length]; - for (int i = 0; i < arrayOfString.length; i++) { - Emoji.data[0][i] = Long.parseLong(arrayOfString[i]); + SharedPreferences preferences = getContext().getSharedPreferences("emoji", Activity.MODE_PRIVATE); + String str = preferences.getString("recents", ""); + try { + if (str != null && str.length() > 0) { + String[] args = str.split(","); + Emoji.data[0] = new long[args.length]; + for (int i = 0; i < args.length; i++) { + Emoji.data[0][i] = Long.parseLong(args[i]); + } + } else { + Emoji.data[0] = new long[]{0x00000000D83DDE02L, 0x00000000D83DDE18L, 0x0000000000002764L, 0x00000000D83DDE0DL, 0x00000000D83DDE0AL, 0x00000000D83DDE01L, + 0x00000000D83DDC4DL, 0x000000000000263AL, 0x00000000D83DDE14L, 0x00000000D83DDE04L, 0x00000000D83DDE2DL, 0x00000000D83DDC8BL, + 0x00000000D83DDE12L, 0x00000000D83DDE33L, 0x00000000D83DDE1CL, 0x00000000D83DDE48L, 0x00000000D83DDE09L, 0x00000000D83DDE03L, + 0x00000000D83DDE22L, 0x00000000D83DDE1DL, 0x00000000D83DDE31L, 0x00000000D83DDE21L, 0x00000000D83DDE0FL, 0x00000000D83DDE1EL, + 0x00000000D83DDE05L, 0x00000000D83DDE1AL, 0x00000000D83DDE4AL, 0x00000000D83DDE0CL, 0x00000000D83DDE00L, 0x00000000D83DDE0BL, + 0x00000000D83DDE06L, 0x00000000D83DDC4CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L}; + } + adapters.get(0).data = Emoji.data[0]; + adapters.get(0).notifyDataSetChanged(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + + if (showStickers) { + try { + stickersUseHistory.clear(); + str = preferences.getString("stickers", ""); + if (str != null && str.length() > 0) { + String[] args = str.split(","); + for (String arg : args) { + String[] args2 = arg.split("="); + stickersUseHistory.put(Long.parseLong(args2[0]), Integer.parseInt(args2[1])); + } + } + sortStickers(); + } catch (Exception e) { + FileLog.e("tmessages", e); } - } else { - Emoji.data[0] = new long[]{0x00000000D83DDE02L, 0x00000000D83DDE18L, 0x0000000000002764L, 0x00000000D83DDE0DL, 0x00000000D83DDE0AL, 0x00000000D83DDE01L, - 0x00000000D83DDC4DL, 0x000000000000263AL, 0x00000000D83DDE14L, 0x00000000D83DDE04L, 0x00000000D83DDE2DL, 0x00000000D83DDC8BL, - 0x00000000D83DDE12L, 0x00000000D83DDE33L, 0x00000000D83DDE1CL, 0x00000000D83DDE48L, 0x00000000D83DDE09L, 0x00000000D83DDE03L, - 0x00000000D83DDE22L, 0x00000000D83DDE1DL, 0x00000000D83DDE31L, 0x00000000D83DDE21L, 0x00000000D83DDE0FL, 0x00000000D83DDE1EL, - 0x00000000D83DDE05L, 0x00000000D83DDE1AL, 0x00000000D83DDE4AL, 0x00000000D83DDE0CL, 0x00000000D83DDE00L, 0x00000000D83DDE0BL, - 0x00000000D83DDE06L, 0x00000000D83DDC4CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L}; } - adapters.get(0).data = Emoji.data[0]; - adapters.get(0).notifyDataSetChanged(); } public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @@ -277,6 +371,9 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi super.onAttachedToWindow(); if (stickersGridAdapter != null) { NotificationCenter.getInstance().addObserver(this, NotificationCenter.stickersDidLoaded); + stickers = StickersQuery.getStickers(); + sortStickers(); + stickersGridAdapter.notifyDataSetChanged(); } } @@ -301,19 +398,18 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi public StickersGridAdapter(Context context) { this.context = context; - StickersQuery.checkStickers(); } public int getCount() { - return StickersQuery.getStickers().size(); + return stickers.size(); } public Object getItem(int i) { - return StickersQuery.getStickers().get(i); + return stickers.get(i); } public long getItemId(int i) { - return StickersQuery.getStickers().get(i).id; + return stickers.get(i).id; } public View getView(int i, View view, ViewGroup viewGroup) { @@ -327,12 +423,19 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi @Override public void onClick(View v) { if (listener != null) { - listener.onStickerSelected(((StickerEmojiCell) v).getSticker()); + TLRPC.Document document = ((StickerEmojiCell) v).getSticker(); + Integer count = stickersUseHistory.get(document.id); + if (count == null) { + count = 0; + } + stickersUseHistory.put(document.id, ++count); + saveRecentStickers(); + listener.onStickerSelected(document); } } }); } - ((StickerEmojiCell) view).setSticker(StickersQuery.getStickers().get(i)); + ((StickerEmojiCell) view).setSticker(stickers.get(i), false); return view; } @@ -401,6 +504,8 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi View localObject; if (paramInt == 0) { localObject = recentsWrap; + } else if (paramInt == 6) { + localObject = emojiWrap; } else { localObject = views.get(paramInt); } @@ -419,6 +524,8 @@ public class EmojiView extends LinearLayout implements NotificationCenter.Notifi View localObject; if (paramInt == 0) { localObject = recentsWrap; + } else if (paramInt == 6) { + localObject = emojiWrap; } else { localObject = views.get(paramInt); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java new file mode 100644 index 000000000..0e38769e6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java @@ -0,0 +1,103 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.content.Context; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import org.telegram.android.LocaleController; +import org.telegram.messenger.R; + +public class EmptyTextProgressView extends FrameLayout { + + private TextView textView; + private ProgressBar progressBar; + private boolean inLayout; + private boolean showAtCenter; + + public EmptyTextProgressView(Context context) { + super(context); + + progressBar = new ProgressBar(context); + progressBar.setVisibility(INVISIBLE); + addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + textView = new TextView(context); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + textView.setTextColor(0xff808080); + textView.setGravity(Gravity.CENTER); + textView.setVisibility(INVISIBLE); + textView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); + } + + public void showProgress() { + textView.setVisibility(INVISIBLE); + progressBar.setVisibility(VISIBLE); + } + + public void showTextView() { + textView.setVisibility(VISIBLE); + progressBar.setVisibility(INVISIBLE); + } + + public void setText(String text) { + textView.setText(text); + } + + public void setShowAtCenter(boolean value) { + showAtCenter = value; + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + inLayout = true; + int width = r - l; + int height = b - t; + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + + if (child.getVisibility() == GONE) { + continue; + } + + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + int x = (width - child.getMeasuredWidth()) / 2; + int y; + if (showAtCenter) { + y = (height / 2 - child.getMeasuredHeight()) / 2; + } else { + y = (height - child.getMeasuredHeight()) / 2; + } + child.layout(x, y, x + child.getMeasuredWidth(), y + child.getMeasuredHeight()); + } + inLayout = false; + } + + @Override + public void requestLayout() { + if (!inLayout) { + super.requestLayout(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java index a1f4cf2f6..26323f5e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java @@ -8,6 +8,7 @@ package org.telegram.ui.Components; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.Application; import android.os.Build; @@ -17,6 +18,7 @@ import org.telegram.messenger.FileLog; import java.util.concurrent.CopyOnWriteArrayList; +@SuppressLint("NewApi") public class ForegroundDetector implements Application.ActivityLifecycleCallbacks { public interface Listener { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java deleted file mode 100644 index 973a775a5..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 1.3.2. - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013. - */ -package org.telegram.ui.Components; - -import java.util.HashMap; -import java.util.LinkedList; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.database.DataSetObserver; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.GestureDetector.OnGestureListener; -import android.view.MotionEvent; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListAdapter; -import android.widget.Scroller; - -public class HorizontalListView extends AdapterView { - - public boolean mAlwaysOverrideTouch = true; - protected ListAdapter mAdapter; - private int mLeftViewIndex = -1; - private int mRightViewIndex = 0; - protected int mCurrentX; - protected int mNextX; - private int mMaxX = Integer.MAX_VALUE; - private int mDisplayOffset = 0; - protected Scroller mScroller; - private GestureDetector mGesture; - private HashMap> mRemovedViewQueue = new HashMap<>(); - private OnItemSelectedListener mOnItemSelected; - private OnItemClickListener mOnItemClicked; - private OnItemLongClickListener mOnItemLongClicked; - private boolean mDataChanged = false; - - public HorizontalListView(Context context, AttributeSet attrs) { - super(context, attrs); - initView(); - } - - private synchronized void initView() { - mLeftViewIndex = -1; - mRightViewIndex = 0; - mDisplayOffset = 0; - mCurrentX = 0; - mNextX = 0; - mMaxX = Integer.MAX_VALUE; - mScroller = new Scroller(getContext()); - mGesture = new GestureDetector(getContext(), mOnGesture); - } - - @Override - public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) { - mOnItemSelected = listener; - } - - @Override - public void setOnItemClickListener(AdapterView.OnItemClickListener listener) { - mOnItemClicked = listener; - } - - @Override - public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) { - mOnItemLongClicked = listener; - } - - private DataSetObserver mDataObserver = new DataSetObserver() { - @Override - public void onChanged() { - synchronized (HorizontalListView.this) { - mDataChanged = true; - } - invalidate(); - requestLayout(); - } - - @Override - public void onInvalidated() { - reset(); - invalidate(); - requestLayout(); - } - }; - - @Override - public ListAdapter getAdapter() { - return mAdapter; - } - - @Override - public View getSelectedView() { - - return null; - } - - @Override - public void setSelection(int position) { - - } - - @Override - public void setAdapter(ListAdapter adapter) { - if (mAdapter != null && mDataObserver != null) { - mAdapter.unregisterDataSetObserver(mDataObserver); - } - mAdapter = adapter; - mAdapter.registerDataSetObserver(mDataObserver); - reset(); - } - - private synchronized void reset() { - initView(); - mRemovedViewQueue.clear(); - removeAllViewsInLayout(); - requestLayout(); - } - - private void addAndMeasureChild(final View child, int viewPos) { - LayoutParams params = child.getLayoutParams(); - if (params == null) { - params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutHelper.MATCH_PARENT); - } - addViewInLayout(child, viewPos, params, true); - child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); - } - - - @SuppressLint("DrawAllocation") - @Override - protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - if (mAdapter == null) { - return; - } - - if (mDataChanged) { - int oldCurrentX = mCurrentX; - initView(); - removeAllViewsInLayout(); - mNextX = oldCurrentX; - mDataChanged = false; - } - - if (mScroller.computeScrollOffset()) { - mNextX = mScroller.getCurrX(); - } - - if (mNextX <= 0) { - mNextX = 0; - mScroller.forceFinished(true); - } - if (mNextX >= mMaxX) { - mNextX = mMaxX; - mScroller.forceFinished(true); - } - - int dx = mCurrentX - mNextX; - - removeNonVisibleItems(dx); - fillList(dx); - positionItems(dx); - - mCurrentX = mNextX; - - if (!mScroller.isFinished()) { - post(new Runnable() { - @Override - public void run() { - requestLayout(); - } - }); - } - } - - private void fillList(final int dx) { - int edge = 0; - View child = getChildAt(getChildCount() - 1); - if (child != null) { - edge = child.getRight(); - } - fillListRight(edge, dx); - - edge = 0; - child = getChildAt(0); - if (child != null) { - edge = child.getLeft(); - } - fillListLeft(edge, dx); - } - - private void fillListRight(int rightEdge, final int dx) { - while (rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) { - - View v = null; - int type = mAdapter.getItemViewType(mRightViewIndex); - LinkedList list = mRemovedViewQueue.get(type); - if (list != null) { - v = list.poll(); - } - View child = mAdapter.getView(mRightViewIndex, v, this); - child.setTag(type); - - addAndMeasureChild(child, -1); - rightEdge += child.getMeasuredWidth(); - child.invalidate(); - - if (mRightViewIndex == mAdapter.getCount() - 1) { - mMaxX = mCurrentX + rightEdge - getWidth() + getPaddingLeft(); - } - - if (mMaxX < 0) { - mMaxX = 0; - } - mRightViewIndex++; - } - - } - - private void fillListLeft(int leftEdge, final int dx) { - while (leftEdge + dx > 0 && mLeftViewIndex >= 0) { - View v = null; - int type = mAdapter.getItemViewType(mLeftViewIndex); - LinkedList list = mRemovedViewQueue.get(type); - if (list != null) { - v = list.poll(); - } - View child = mAdapter.getView(mLeftViewIndex, v, this); - child.setTag(type); - - addAndMeasureChild(child, 0); - leftEdge -= child.getMeasuredWidth(); - mLeftViewIndex--; - mDisplayOffset -= child.getMeasuredWidth(); - } - } - - private void removeNonVisibleItems(final int dx) { - View child = getChildAt(0); - while (child != null && child.getRight() + dx <= 0) { - mDisplayOffset += child.getMeasuredWidth(); - - int type = (Integer) child.getTag(); - LinkedList list = mRemovedViewQueue.get(type); - if (list == null) { - list = new LinkedList<>(); - mRemovedViewQueue.put(type, list); - } - list.add(child); - - removeViewInLayout(child); - mLeftViewIndex++; - child = getChildAt(0); - } - - child = getChildAt(getChildCount() - 1); - while (child != null && child.getLeft() + dx >= getWidth()) { - int type = (Integer) child.getTag(); - LinkedList list = mRemovedViewQueue.get(type); - if (list == null) { - list = new LinkedList<>(); - mRemovedViewQueue.put(type, list); - } - list.add(child); - - removeViewInLayout(child); - mRightViewIndex--; - child = getChildAt(getChildCount() - 1); - } - } - - private void positionItems(final int dx) { - if (getChildCount() > 0) { - mDisplayOffset += dx; - int left = mDisplayOffset; - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - int childWidth = child.getMeasuredWidth(); - child.layout(left + getPaddingLeft(), 0, left + childWidth + getPaddingLeft(), child.getMeasuredHeight()); - left += childWidth + child.getPaddingRight(); - } - } - } - - public synchronized void scrollTo(int x) { - mScroller.startScroll(mNextX, 0, x - mNextX, 0); - requestLayout(); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - boolean handled = super.dispatchTouchEvent(ev); - handled |= mGesture.onTouchEvent(ev); - return handled; - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - requestDisallowInterceptTouchEvent(true); - return super.onInterceptTouchEvent(ev); - } - - protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - synchronized (HorizontalListView.this) { - mScroller.fling(mNextX, 0, (int) -velocityX, 0, 0, mMaxX, 0, 0); - } - requestLayout(); - - return true; - } - - protected boolean onDown(MotionEvent e) { - mScroller.forceFinished(true); - return true; - } - - private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() { - - @Override - public boolean onDown(MotionEvent e) { - return HorizontalListView.this.onDown(e); - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY); - } - - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - synchronized (HorizontalListView.this) { - mNextX += (int) distanceX; - } - requestLayout(); - return true; - } - - @Override - public boolean onSingleTapUp(MotionEvent e) { - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - if (isEventWithinView(e, child)) { - if (mOnItemClicked != null) { - mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i)); - } - if (mOnItemSelected != null) { - mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i)); - } - break; - } - } - return true; - } - - @Override - public void onLongPress(MotionEvent e) { - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - if (isEventWithinView(e, child)) { - if (mOnItemLongClicked != null) { - mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i)); - } - break; - } - } - } - - private boolean isEventWithinView(MotionEvent e, View child) { - Rect viewRect = new Rect(); - int[] childPosition = new int[2]; - child.getLocationOnScreen(childPosition); - int left = childPosition[0]; - int right = left + child.getWidth(); - int top = childPosition[1]; - int bottom = top + child.getHeight(); - viewRect.set(left, top, right, bottom); - return viewRect.contains((int) e.getRawX(), (int) e.getRawY()); - } - }; -} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java index f449daf27..2446115da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java @@ -23,7 +23,7 @@ public class LayoutHelper { return (int) (size < 0 ? size : AndroidUtilities.dp(size)); } - public static FrameLayout.LayoutParams createFrame(int width, int height, int gravity, float leftMargin, float topMargin, float rightMargin, float bottomMargin) { + public static FrameLayout.LayoutParams createFrame(int width, float height, int gravity, float leftMargin, float topMargin, float rightMargin, float bottomMargin) { FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity); layoutParams.setMargins(AndroidUtilities.dp(leftMargin), AndroidUtilities.dp(topMargin), AndroidUtilities.dp(rightMargin), AndroidUtilities.dp(bottomMargin)); return layoutParams; @@ -33,7 +33,7 @@ public class LayoutHelper { return new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity); } - public static FrameLayout.LayoutParams createFrame(int width, int height) { + public static FrameLayout.LayoutParams createFrame(int width, float height) { return new FrameLayout.LayoutParams(getSize(width), getSize(height)); } @@ -87,6 +87,12 @@ public class LayoutHelper { return layoutParams; } + public static LinearLayout.LayoutParams createLinear(int width, int height, float weight, int leftMargin, int topMargin, int rightMargin, int bottomMargin) { + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(getSize(width), getSize(height), weight); + layoutParams.setMargins(AndroidUtilities.dp(leftMargin), AndroidUtilities.dp(topMargin), AndroidUtilities.dp(rightMargin), AndroidUtilities.dp(bottomMargin)); + return layoutParams; + } + public static LinearLayout.LayoutParams createLinear(int width, int height, int gravity, int leftMargin, int topMargin, int rightMargin, int bottomMargin) { LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(getSize(width), getSize(height)); layoutParams.setMargins(AndroidUtilities.dp(leftMargin), AndroidUtilities.dp(topMargin), AndroidUtilities.dp(rightMargin), AndroidUtilities.dp(bottomMargin)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java index b5898e18c..22f7a4326 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java @@ -47,7 +47,6 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.Utilities; import org.telegram.android.AnimationCompat.AnimatorListenerAdapterProxy; import org.telegram.android.AnimationCompat.AnimatorSetProxy; import org.telegram.android.AnimationCompat.ObjectAnimatorProxy; @@ -675,55 +674,42 @@ public class PasscodeView extends FrameLayout { int key = KeyEvent.KEYCODE_DEL; switch (tag) { case 0: - key = KeyEvent.KEYCODE_0; passwordEditText2.appendCharacter("0"); break; case 1: - key = KeyEvent.KEYCODE_1; passwordEditText2.appendCharacter("1"); break; case 2: - key = KeyEvent.KEYCODE_2; passwordEditText2.appendCharacter("2"); break; case 3: - key = KeyEvent.KEYCODE_3; passwordEditText2.appendCharacter("3"); break; case 4: - key = KeyEvent.KEYCODE_4; passwordEditText2.appendCharacter("4"); break; case 5: - key = KeyEvent.KEYCODE_5; passwordEditText2.appendCharacter("5"); break; case 6: - key = KeyEvent.KEYCODE_6; passwordEditText2.appendCharacter("6"); break; case 7: - key = KeyEvent.KEYCODE_7; passwordEditText2.appendCharacter("7"); break; case 8: - key = KeyEvent.KEYCODE_8; passwordEditText2.appendCharacter("8"); break; case 9: - key = KeyEvent.KEYCODE_9; passwordEditText2.appendCharacter("9"); break; case 10: - key = KeyEvent.KEYCODE_DEL; passwordEditText2.eraseLastCharacter(); break; } if (passwordEditText2.lenght() == 4) { processDone(); } - //passwordEditText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, key, 0)); - //passwordEditText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_UP, key, 0)); } }); numberFrameLayouts.add(frameLayout); @@ -754,7 +740,7 @@ public class PasscodeView extends FrameLayout { onPasscodeError(); return; } - if (!Utilities.MD5(password).equals(UserConfig.passcodeHash)) { + if (!UserConfig.checkPasscode(password)) { passwordEditText.setText(""); passwordEditText2.eraseAllCharacters(true); onPasscodeError(); @@ -866,7 +852,6 @@ public class PasscodeView extends FrameLayout { backgroundDrawable = ApplicationLoader.getCachedWallpaper(); if (backgroundDrawable != null) { backgroundFrameLayout.setBackgroundColor(0xbf000000); - customTheme = true; } else { backgroundFrameLayout.setBackgroundColor(0xff517c9e); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java index 319286ca5..ced235b6a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java @@ -8,6 +8,7 @@ package org.telegram.ui.Components; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -55,6 +56,7 @@ import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL; import javax.microedition.khronos.opengles.GL10; +@SuppressLint("NewApi") public class PhotoFilterView extends FrameLayout { private boolean showOriginal; @@ -1459,58 +1461,58 @@ public class PhotoFilterView extends FrameLayout { layoutParams.height = AndroidUtilities.dp(60); layoutParams.gravity = Gravity.LEFT | Gravity.TOP; recyclerListView.setLayoutParams(layoutParams); - recyclerListView.addOnItemTouchListener(new RecyclerListView.RecyclerListViewItemClickListener(context, new RecyclerListView.OnItemClickListener() { + recyclerListView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { @Override - public void onItemClick(View view, int i) { - selectedTool = i; - if (i == enhanceTool) { + public void onItemClick(View view, int position) { + selectedTool = position; + if (position == enhanceTool) { previousValue = enhanceValue; valueSeekBar.setMinMax(0, 100); paramTextView.setText(LocaleController.getString("Enhance", R.string.Enhance)); - } else if (i == highlightsTool) { + } else if (position == highlightsTool) { previousValue = highlightsValue; valueSeekBar.setMinMax(0, 100); paramTextView.setText(LocaleController.getString("Highlights", R.string.Highlights)); - } else if (i == contrastTool) { + } else if (position == contrastTool) { previousValue = contrastValue; valueSeekBar.setMinMax(-100, 100); paramTextView.setText(LocaleController.getString("Contrast", R.string.Contrast)); - } else if (i == exposureTool) { + } else if (position == exposureTool) { previousValue = exposureValue; valueSeekBar.setMinMax(-100, 100); paramTextView.setText(LocaleController.getString("Exposure", R.string.Exposure)); - } else if (i == warmthTool) { + } else if (position == warmthTool) { previousValue = warmthValue; valueSeekBar.setMinMax(-100, 100); paramTextView.setText(LocaleController.getString("Warmth", R.string.Warmth)); - } else if (i == saturationTool) { + } else if (position == saturationTool) { previousValue = saturationValue; valueSeekBar.setMinMax(-100, 100); paramTextView.setText(LocaleController.getString("Saturation", R.string.Saturation)); - } else if (i == vignetteTool) { + } else if (position == vignetteTool) { previousValue = vignetteValue; valueSeekBar.setMinMax(0, 100); paramTextView.setText(LocaleController.getString("Vignette", R.string.Vignette)); - } else if (i == shadowsTool) { + } else if (position == shadowsTool) { previousValue = shadowsValue; valueSeekBar.setMinMax(0, 100); paramTextView.setText(LocaleController.getString("Shadows", R.string.Shadows)); - } else if (i == grainTool) { + } else if (position == grainTool) { previousValue = grainValue; valueSeekBar.setMinMax(0, 100); paramTextView.setText(LocaleController.getString("Grain", R.string.Grain)); - } else if (i == sharpenTool) { + } else if (position == sharpenTool) { previousValue = sharpenValue; valueSeekBar.setMinMax(0, 100); paramTextView.setText(LocaleController.getString("Sharpen", R.string.Sharpen)); - } else if (i == blurTool) { + } else if (position == blurTool) { previousValue = blurType; } valueSeekBar.setProgress((int) previousValue, false); updateValueTextView(); switchToOrFromEditMode(); } - })); + }); editView = new FrameLayout(context); editView.setVisibility(GONE); @@ -1925,8 +1927,8 @@ public class PhotoFilterView extends FrameLayout { viewWidth -= AndroidUtilities.dp(28); viewHeight -= AndroidUtilities.dp(14 + 140); - float bitmapW = bitmapToEdit.getWidth(); - float bitmapH = bitmapToEdit.getHeight(); + float bitmapW; + float bitmapH; if (orientation == 90 || orientation == 270) { bitmapW = bitmapToEdit.getHeight(); bitmapH = bitmapToEdit.getWidth(); @@ -2020,7 +2022,7 @@ public class PhotoFilterView extends FrameLayout { if (parameterValue > 0) { parameterValue *= 1.05f; } - return parameterValue += 1; + return parameterValue + 1; } public FrameLayout getToolsView() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerExListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerExListView.java deleted file mode 100644 index 09e818588..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerExListView.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 2.x - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2015. - */ - -package org.telegram.ui.Components; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.HapticFeedbackConstants; -import android.view.MotionEvent; -import android.view.SoundEffectConstants; -import android.view.View; -import android.view.ViewConfiguration; - -import org.telegram.android.AndroidUtilities; -import org.telegram.android.support.widget.RecyclerView; - -public class RecyclerExListView extends RecyclerView { - - private OnItemClickListener onItemClickListener; - private OnItemLongClickListener onItemLongClickListener; - private RecyclerView.OnScrollListener onScrollListener; - private OnInterceptTouchListener onInterceptTouchListener; - private View emptyView; - private Runnable selectChildRunnable; - - private GestureDetector mGestureDetector; - private View currentChildView; - private int currentChildPosition; - private boolean interceptedByChild; - private boolean wasPressed; - - public interface OnItemClickListener { - void onItemClick(View view, int position); - } - - public interface OnItemLongClickListener { - void onItemClick(View view, int position); - } - - public interface OnInterceptTouchListener { - boolean onInterceptTouchEvent(MotionEvent event); - } - - private class RecyclerListViewItemClickListener implements RecyclerView.OnItemTouchListener { - - public RecyclerListViewItemClickListener(Context context) { - mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onSingleTapUp(MotionEvent e) { - if (currentChildView != null && onItemClickListener != null) { - currentChildView.playSoundEffect(SoundEffectConstants.CLICK); - onItemClickListener.onItemClick(currentChildView, currentChildPosition); - if (selectChildRunnable != null) { - currentChildView.setPressed(true); - final View view = currentChildView; - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (view != null) { - view.setPressed(false); - } - } - }, ViewConfiguration.getPressedStateDuration()); - AndroidUtilities.cancelRunOnUIThread(selectChildRunnable); - selectChildRunnable = null; - currentChildView = null; - interceptedByChild = false; - } - } - return true; - } - - @Override - public void onLongPress(MotionEvent e) { - if (currentChildView != null && onItemLongClickListener != null) { - currentChildView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - onItemLongClickListener.onItemClick(currentChildView, currentChildPosition); - } - } - }); - } - - @Override - public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { - int action = e.getActionMasked(); - boolean isScrollIdle = RecyclerExListView.this.getScrollState() == RecyclerExListView.SCROLL_STATE_IDLE; - - if ((action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) && currentChildView == null && isScrollIdle) { - currentChildView = view.findChildViewUnder(e.getX(), e.getY()); - currentChildPosition = -1; - if (currentChildView != null) { - currentChildPosition = view.getChildPosition(currentChildView); - MotionEvent childEvent = MotionEvent.obtain(0, 0, e.getActionMasked(), e.getX() - currentChildView.getLeft(), e.getY() - currentChildView.getTop(), 0); - if (currentChildView.onTouchEvent(childEvent)) { - interceptedByChild = true; - } - childEvent.recycle(); - } - } - - if (currentChildView != null && !interceptedByChild) { - mGestureDetector.onTouchEvent(e); - } - - if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) { - if (!interceptedByChild && currentChildView != null) { - selectChildRunnable = new Runnable() { - @Override - public void run() { - if (selectChildRunnable != null && currentChildView != null) { - currentChildView.setPressed(true); - selectChildRunnable = null; - } - } - }; - AndroidUtilities.runOnUIThread(selectChildRunnable, ViewConfiguration.getTapTimeout()); - } - } else if (currentChildView != null && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_CANCEL || !isScrollIdle)) { - if (selectChildRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(selectChildRunnable); - selectChildRunnable = null; - } - currentChildView.setPressed(false); - currentChildView = null; - interceptedByChild = false; - } - return false; - } - - @Override - public void onTouchEvent(RecyclerView view, MotionEvent e) { - - } - } - - private AdapterDataObserver observer = new AdapterDataObserver() { - @Override - public void onChanged() { - checkIfEmpty(); - } - - @Override - public void onItemRangeInserted(int positionStart, int itemCount) { - checkIfEmpty(); - } - - @Override - public void onItemRangeRemoved(int positionStart, int itemCount) { - checkIfEmpty(); - } - }; - - public void init(Context context) { - super.setOnScrollListener(new OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - if (newState != SCROLL_STATE_IDLE && currentChildView != null) { - if (selectChildRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(selectChildRunnable); - selectChildRunnable = null; - } - MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); - mGestureDetector.onTouchEvent(event); - currentChildView.onTouchEvent(event); - event.recycle(); - currentChildView.setPressed(false); - currentChildView = null; - interceptedByChild = false; - } - if (onScrollListener != null) { - onScrollListener.onScrollStateChanged(recyclerView, newState); - } - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - if (onScrollListener != null) { - onScrollListener.onScrolled(recyclerView, dx, dy); - } - } - }); - addOnItemTouchListener(new RecyclerListViewItemClickListener(context)); - } - - public RecyclerExListView(Context context) { - super(context); - - /*setVerticalScrollBarEnabled(true); - try { - TypedArray a = context.getTheme().obtainStyledAttributes(new int[0]); - Method initializeScrollbars = android.view.View.class.getDeclaredMethod("initializeScrollbars", TypedArray.class); - initializeScrollbars.invoke(this, a); - a.recycle(); - } catch (Throwable e) { - FileLog.e("tmessages", e); - }*/ - - init(context); - } - - public RecyclerExListView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - public RecyclerExListView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(context); - } - - public void setOnItemClickListener(OnItemClickListener listener) { - onItemClickListener = listener; - } - - public void setOnItemLongClickListener(OnItemLongClickListener listener) { - onItemLongClickListener = listener; - } - - public void setEmptyView(View view) { - if (emptyView == view) { - return; - } - emptyView = view; - checkIfEmpty(); - } - - public View getEmptyView() { - return emptyView; - } - - public void invalidateViews() { - int count = getChildCount(); - for (int a = 0; a < count; a++) { - getChildAt(a).invalidate(); - } - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent e) { - return onInterceptTouchListener != null && onInterceptTouchListener.onInterceptTouchEvent(e) || super.onInterceptTouchEvent(e); - } - - private void checkIfEmpty() { - if (emptyView == null || getAdapter() == null) { - return; - } - boolean emptyViewVisible = getAdapter().getItemCount() == 0; - emptyView.setVisibility(emptyViewVisible ? VISIBLE : INVISIBLE); - setVisibility(emptyViewVisible ? INVISIBLE : VISIBLE); - } - - @Override - public void setOnScrollListener(OnScrollListener listener) { - onScrollListener = listener; - } - - public void setOnInterceptTouchListener(OnInterceptTouchListener listener) { - onInterceptTouchListener = listener; - } - - @Override - public void setAdapter(Adapter adapter) { - final Adapter oldAdapter = getAdapter(); - if (oldAdapter != null) { - oldAdapter.unregisterAdapterDataObserver(observer); - } - super.setAdapter(adapter); - if (adapter != null) { - adapter.registerAdapterDataObserver(observer); - } - checkIfEmpty(); - } - - @Override - public void stopScroll() { - try { - super.stopScroll(); - } catch (NullPointerException exception) { - /** - * The mLayout has been disposed of before the - * RecyclerView and this stops the application - * from crashing. - */ - } - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java deleted file mode 100644 index 3f1e8f9ba..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 2.0.x. - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2014. - */ - -package org.telegram.ui.Components; - -import android.content.Context; -import org.telegram.android.support.widget.RecyclerView; - -import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.View; - -import org.telegram.messenger.FileLog; - -public class RecyclerListView extends RecyclerView { - - public interface OnItemClickListener { - void onItemClick(View view, int position); - } - - public static class RecyclerListViewItemClickListener implements RecyclerView.OnItemTouchListener { - private OnItemClickListener mListener; - - GestureDetector mGestureDetector; - - public RecyclerListViewItemClickListener(Context context, OnItemClickListener listener) { - mListener = listener; - mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onSingleTapUp(MotionEvent e) { - return true; - } - }); - } - - @Override - public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { - View childView = view.findChildViewUnder(e.getX(), e.getY()); - if (childView != null) { - if (mListener != null && mGestureDetector.onTouchEvent(e)) { - mListener.onItemClick(childView, view.getChildPosition(childView)); - } - /*int action = e.getAction(); - if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) { - childView.setPressed(true); - } else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { - childView.setPressed(false); - }*/ - } else { - /*int count = view.getChildCount(); - for (int a = 0; a < count; a++) { - view.getChildAt(a).setPressed(false); - }*/ - } - return false; - } - - @Override - public void onTouchEvent(RecyclerView view, MotionEvent e) { - - } - } - - public RecyclerListView(Context context) { - super(context); - } - - public RecyclerListView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public RecyclerListView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent e) { - requestDisallowInterceptTouchEvent(true); - return super.onInterceptTouchEvent(e); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - try { - super.onLayout(changed, l, t, r, b); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - - @Override - public void stopScroll() { - try { - super.stopScroll(); - } catch (NullPointerException exception) { - /** - * The mLayout has been disposed of before the - * RecyclerView and this stops the application - * from crashing. - */ - } - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java new file mode 100644 index 000000000..864e9e1ea --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java @@ -0,0 +1,111 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.FrameLayout; + +import org.telegram.android.AndroidUtilities; +import org.telegram.messenger.FileLog; + +public class SizeNotifierFrameLayout extends FrameLayout { + + private Rect rect = new Rect(); + private Drawable backgroundDrawable; + private int keyboardHeight; + private SizeNotifierRelativeLayout.SizeNotifierRelativeLayoutDelegate delegate; + + public SizeNotifierFrameLayout(Context context) { + super(context); + setWillNotDraw(false); + } + + public SizeNotifierFrameLayout(Context context, android.util.AttributeSet attrs) { + super(context, attrs); + setWillNotDraw(false); + } + + public SizeNotifierFrameLayout(Context context, android.util.AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setWillNotDraw(false); + } + + public void setBackgroundImage(int resourceId) { + try { + backgroundDrawable = getResources().getDrawable(resourceId); + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + } + + public void setBackgroundImage(Drawable bitmap) { + backgroundDrawable = bitmap; + } + + public Drawable getBackgroundImage() { + return backgroundDrawable; + } + + public void setDelegate(SizeNotifierRelativeLayout.SizeNotifierRelativeLayoutDelegate delegate) { + this.delegate = delegate; + } + + @SuppressLint("DrawAllocation") + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + notifyHeightChanged(); + } + + public void notifyHeightChanged() { + if (delegate != null) { + View rootView = this.getRootView(); + int usableViewHeight = rootView.getHeight() - AndroidUtilities.statusBarHeight - AndroidUtilities.getViewInset(rootView); + this.getWindowVisibleDisplayFrame(rect); + keyboardHeight = usableViewHeight - (rect.bottom - rect.top); + final boolean isWidthGreater = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y; + post(new Runnable() { + @Override + public void run() { + if (delegate != null) { + delegate.onSizeChanged(keyboardHeight, isWidthGreater); + } + } + }); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (backgroundDrawable != null) { + if (backgroundDrawable instanceof ColorDrawable) { + backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + backgroundDrawable.draw(canvas); + } else { + float scaleX = (float) getMeasuredWidth() / (float) backgroundDrawable.getIntrinsicWidth(); + float scaleY = (float) (getMeasuredHeight() + keyboardHeight) / (float) backgroundDrawable.getIntrinsicHeight(); + float scale = scaleX < scaleY ? scaleY : scaleX; + int width = (int) Math.ceil(backgroundDrawable.getIntrinsicWidth() * scale); + int height = (int) Math.ceil(backgroundDrawable.getIntrinsicHeight() * scale); + int x = (getMeasuredWidth() - width) / 2; + int y = (getMeasuredHeight() - height + keyboardHeight) / 2; + backgroundDrawable.setBounds(x, y, x + width, y + height); + backgroundDrawable.draw(canvas); + } + } else { + super.onDraw(canvas); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java index d904f7c00..f918c1b3c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java @@ -109,7 +109,13 @@ public class StaticLayoutEx { if (layout.getLineCount() <= maxLines) { return layout; } else { - int off = layout.getOffsetForHorizontal(maxLines - 1, layout.getLineWidth(maxLines - 1)); + int off; + float left = layout.getLineLeft(maxLines - 1); + if (left != 0) { + off = layout.getOffsetForHorizontal(maxLines - 1, left); + } else { + off = layout.getOffsetForHorizontal(maxLines - 1, layout.getLineWidth(maxLines - 1)); + } SpannableStringBuilder stringBuilder = new SpannableStringBuilder(source.subSequence(0, Math.max(0, off - 1))); stringBuilder.append("\u2026"); return new StaticLayout(stringBuilder, paint, outerWidth, align, spacingMult, spacingAdd, includePad); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java new file mode 100644 index 000000000..49ace5b72 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -0,0 +1,138 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.FrameLayout; +import android.widget.GridView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.LocaleController; +import org.telegram.android.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.TLRPC; +import org.telegram.ui.Cells.StickerEmojiCell; + +import java.util.ArrayList; + +public class StickersAlert extends AlertDialog implements NotificationCenter.NotificationCenterDelegate { + + private ArrayList stickers; + private GridView gridView; + + public StickersAlert(Context context, TLRPC.TL_stickerSet set, ArrayList arrayList) { + super(context); + stickers = arrayList; + + FrameLayout container = new FrameLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) Math.min(Math.ceil(stickers.size() / 4.0f) * AndroidUtilities.dp(82), AndroidUtilities.displaySize.y / 5 * 3), MeasureSpec.EXACTLY)); + } + }; + setView(container, AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + + gridView = new GridView(context); + gridView.setNumColumns(4); + gridView.setAdapter(new GridAdapter(context)); + gridView.setVerticalScrollBarEnabled(false); + container.addView(gridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + if (set.id == -1) { + setTitle(LocaleController.getString("GeniusStickerPackName", R.string.GeniusStickerPackName)); + } else { + setTitle(set.title); + } + + NotificationCenter.getInstance().addObserver(this, NotificationCenter.emojiDidLoaded); + + setOnShowListener(new OnShowListener() { + @Override + public void onShow(DialogInterface arg0) { + if (getButton(AlertDialog.BUTTON_NEUTRAL) != null) { + getButton(AlertDialog.BUTTON_NEUTRAL).setTextColor(0xffcd5a5a); + } + if (getButton(AlertDialog.BUTTON_POSITIVE) != null) { + getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(0xff37a919); + } + } + }); + } + + @Override + public void dismiss() { + super.dismiss(); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.emojiDidLoaded); + } + + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.emojiDidLoaded) { + if (gridView != null) { + gridView.invalidateViews(); + } + } + } + + private class GridAdapter extends BaseAdapter { + + Context context; + + public GridAdapter(Context context) { + this.context = context; + } + + public int getCount() { + return stickers.size(); + } + + public Object getItem(int i) { + return stickers.get(i); + } + + public long getItemId(int i) { + return stickers.get(i).id; + } + + @Override + public boolean areAllItemsEnabled() { + return false; + } + + @Override + public boolean isEnabled(int position) { + return false; + } + + public View getView(int i, View view, ViewGroup viewGroup) { + if (view == null) { + view = new StickerEmojiCell(context) { + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(82), MeasureSpec.EXACTLY)); + } + }; + } + ((StickerEmojiCell) view).setSticker(stickers.get(i), true); + return view; + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + if (observer != null) { + super.unregisterDataSetObserver(observer); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderlineBold.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderlineBold.java new file mode 100644 index 000000000..42f98f0e8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderlineBold.java @@ -0,0 +1,26 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.text.TextPaint; + +import org.telegram.android.AndroidUtilities; + +public class URLSpanNoUnderlineBold extends URLSpanNoUnderline { + public URLSpanNoUnderlineBold(String url) { + super(url); + } + + @Override + public void updateDrawState(TextPaint ds) { + super.updateDrawState(ds); + ds.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + ds.setUnderlineText(false); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java new file mode 100644 index 000000000..7d597cce6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java @@ -0,0 +1,232 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.provider.Browser; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.webkit.CookieManager; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.BottomSheet; + +import java.util.HashMap; + +public class WebFrameLayout extends FrameLayout { + + private WebView webView; + private BottomSheet dialog; + private View customView; + private FrameLayout fullscreenVideoContainer; + private WebChromeClient.CustomViewCallback customViewCallback; + private ProgressBar progressBar; + + private int width; + private int height; + private String openUrl; + + @SuppressLint("SetJavaScriptEnabled") + public WebFrameLayout(Context context, BottomSheet parentDialog, String title, String originalUrl, final String url, int w, int h) { + super(context); + + openUrl = originalUrl; + width = w; + height = h; + dialog = parentDialog; + + fullscreenVideoContainer = new FrameLayout(context); + fullscreenVideoContainer.setBackgroundColor(0xff000000); + dialog.getContainer().addView(fullscreenVideoContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + fullscreenVideoContainer.setVisibility(INVISIBLE); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.LEFT | Gravity.TOP)); + + TextView textView = new TextView(context); + textView.setTextColor(0xff666666); + textView.setText(title); + textView.setSingleLine(true); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setGravity(Gravity.CENTER_VERTICAL); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + linearLayout.addView(textView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 16, 0, 0, 0)); + + textView = new TextView(context); + textView.setTextColor(0xff999999); + textView.setText(LocaleController.getString("OpenInBrowser", R.string.OpenInBrowser)); + textView.setGravity(Gravity.CENTER_VERTICAL); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, 16, 0, 0, 0)); + textView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Uri uri = Uri.parse(openUrl); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + intent.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName()); + getContext().startActivity(intent); + if (dialog != null) { + dialog.dismiss(); + } + } + }); + + textView = new TextView(context); + textView.setTextColor(0xff999999); + textView.setText(LocaleController.getString("CopyUrl", R.string.CopyUrl)); + textView.setGravity(Gravity.CENTER_VERTICAL); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, 16, 0, 16, 0)); + textView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (Build.VERSION.SDK_INT < 11) { + android.text.ClipboardManager clipboard = (android.text.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setText(openUrl); + } else { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText("label", openUrl); + clipboard.setPrimaryClip(clip); + } + Toast.makeText(getContext(), LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_SHORT).show(); + if (dialog != null) { + dialog.dismiss(); + } + } + }); + + View lineView = new View(context); + lineView.setBackgroundColor(0xffcdcdcd); + addView(lineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.TOP | Gravity.LEFT, 0, 40, 0, 0)); + + webView = new WebView(context); + webView.getSettings().setJavaScriptEnabled(true); + String userAgent = webView.getSettings().getUserAgentString(); + if (userAgent != null) { + userAgent = userAgent.replace("Android", ""); + webView.getSettings().setUserAgentString(userAgent); + } + if (Build.VERSION.SDK_INT >= 21) { + webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); + CookieManager cookieManager = CookieManager.getInstance(); + cookieManager.setAcceptThirdPartyCookies(webView, true); + } + + webView.setWebChromeClient(new WebChromeClient() { + + @Override + public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) { + onShowCustomView(view, callback); + } + + @Override + public void onShowCustomView(View view, CustomViewCallback callback) { + if (customView != null) { + callback.onCustomViewHidden(); + return; + } + customView = view; + if (dialog != null) { + dialog.getSheetContainer().setVisibility(INVISIBLE); + fullscreenVideoContainer.setVisibility(VISIBLE); + fullscreenVideoContainer.addView(view, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + } + customViewCallback = callback; + } + + @Override + public void onHideCustomView() { + super.onHideCustomView(); + if (customView == null) { + return; + } + if (dialog != null) { + dialog.getSheetContainer().setVisibility(VISIBLE); + fullscreenVideoContainer.setVisibility(INVISIBLE); + fullscreenVideoContainer.removeView(customView); + } + if (customViewCallback != null && !customViewCallback.getClass().getName().contains(".chromium.")) { + customViewCallback.onCustomViewHidden(); + } + customView = null; + } + }); + + webView.setWebViewClient(new WebViewClient() { + @Override + public void onLoadResource(WebView view, String url) { + super.onLoadResource(view, url); + } + + + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + progressBar.setVisibility(INVISIBLE); + } + }); + + addView(webView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 8, 49, 8, 0)); + + progressBar = new ProgressBar(context); + addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 8, 24, 8, 0)); + + setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); + + parentDialog.setDelegate(new BottomSheet.BottomSheetDelegate() { + @Override + public void onOpenAnimationEnd() { + HashMap args = new HashMap<>(); + args.put("Referer", "http://youtube.com"); + webView.loadUrl(url, args); + } + }); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + webView.stopLoading(); + webView.loadUrl("about:blank"); + webView.destroy(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int parentWidth = MeasureSpec.getSize(widthMeasureSpec); + float scale = width / parentWidth; + int h = (int) Math.min(height / scale, AndroidUtilities.displaySize.y / 2); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h + AndroidUtilities.dp(49), MeasureSpec.EXACTLY)); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index 793629602..99a4b4475 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -376,7 +376,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } } } @@ -427,7 +427,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)editText.getLayoutParams(); if (layoutParams != null) { if (layoutParams instanceof FrameLayout.LayoutParams) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java index cf02ca29f..260092182 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java @@ -8,6 +8,7 @@ package org.telegram.ui; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; @@ -32,7 +33,6 @@ import org.telegram.android.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.android.LocaleController; import org.telegram.messenger.R; -import org.telegram.messenger.Utilities; import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -234,7 +234,7 @@ public class DocumentSelectActivity extends BaseFragment { } if (sizeLimit != 0) { if (file.length() > sizeLimit) { - showErrorBox(LocaleController.formatString("FileUploadLimit", R.string.FileUploadLimit, Utilities.formatFileSize(sizeLimit))); + showErrorBox(LocaleController.formatString("FileUploadLimit", R.string.FileUploadLimit, AndroidUtilities.formatFileSize(sizeLimit))); return false; } } @@ -298,7 +298,7 @@ public class DocumentSelectActivity extends BaseFragment { he.scrollItem = listView.getFirstVisiblePosition(); he.scrollOffset = listView.getChildAt(0).getTop(); he.dir = currentDir; - he.title = actionBar.getTitle().toString(); + he.title = actionBar.getTitle(); history.add(he); if (!listFiles(file)) { history.remove(he); @@ -313,7 +313,7 @@ public class DocumentSelectActivity extends BaseFragment { } if (sizeLimit != 0) { if (file.length() > sizeLimit) { - showErrorBox(LocaleController.formatString("FileUploadLimit", R.string.FileUploadLimit, Utilities.formatFileSize(sizeLimit))); + showErrorBox(LocaleController.formatString("FileUploadLimit", R.string.FileUploadLimit, AndroidUtilities.formatFileSize(sizeLimit))); return; } } @@ -404,7 +404,7 @@ public class DocumentSelectActivity extends BaseFragment { return false; } emptyView.setText(LocaleController.getString("NoFiles", R.string.NoFiles)); - File[] files = null; + File[] files; try { files = dir.listFiles(); } catch(Exception e) { @@ -449,7 +449,7 @@ public class DocumentSelectActivity extends BaseFragment { String fname = file.getName(); String[] sp = fname.split("\\."); item.ext = sp.length > 1 ? sp[sp.length - 1] : "?"; - item.subtitle = Utilities.formatFileSize(file.length()); + item.subtitle = AndroidUtilities.formatFileSize(file.length()); fname = fname.toLowerCase(); if (fname.endsWith(".jpg") || fname.endsWith(".png") || fname.endsWith(".gif") || fname.endsWith(".jpeg")) { item.thumb = file.getAbsolutePath(); @@ -485,6 +485,7 @@ public class DocumentSelectActivity extends BaseFragment { new AlertDialog.Builder(getParentActivity()).setTitle(LocaleController.getString("AppName", R.string.AppName)).setMessage(error).setPositiveButton(LocaleController.getString("OK", R.string.OK), null).show(); } + @SuppressLint("NewApi") private void listRoots() { currentDir = null; items.clear(); @@ -582,7 +583,7 @@ public class DocumentSelectActivity extends BaseFragment { if (total == 0) { return ""; } - return LocaleController.formatString("FreeOfTotal", R.string.FreeOfTotal, Utilities.formatFileSize(free), Utilities.formatFileSize(total)); + return LocaleController.formatString("FreeOfTotal", R.string.FreeOfTotal, AndroidUtilities.formatFileSize(free), AndroidUtilities.formatFileSize(total)); } private class ListAdapter extends BaseFragmentAdapter { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index ba5470f4b..d26744043 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -376,7 +376,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { - TLRPC.User user = null; + TLRPC.User user; if (searching && searchWas) { user = searchListViewAdapter.getItem(i); } else { @@ -482,12 +482,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen updateVisibleRows(mask); } } else if (id == NotificationCenter.chatDidCreated) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - removeSelfFromStack(); - } - }); + removeSelfFromStack(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index a0aecf567..93aaffa07 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -255,7 +255,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati } } }); - showAlertDialog(builder); + showDialog(builder.create()); } }); } @@ -393,26 +393,21 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati } donePressed = false; } else if (id == NotificationCenter.chatDidCreated) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (progressDialog != null) { - try { - progressDialog.dismiss(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - int chat_id = (Integer)args[0]; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); - Bundle args2 = new Bundle(); - args2.putInt("chat_id", chat_id); - presentFragment(new ChatActivity(args2), true); - if (uploadedAvatar != null) { - MessagesController.getInstance().changeChatAvatar(chat_id, uploadedAvatar); - } + if (progressDialog != null) { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); } - }); + } + int chat_id = (Integer)args[0]; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); + Bundle args2 = new Bundle(); + args2.putInt("chat_id", chat_id); + presentFragment(new ChatActivity(args2), true); + if (uploadedAvatar != null) { + MessagesController.getInstance().changeChatAvatar(chat_id, uploadedAvatar); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java index 7af61e6a9..1ea12de42 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java @@ -167,7 +167,7 @@ public class GroupInviteActivity extends BaseFragment implements NotificationCen } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } } }); @@ -225,7 +225,7 @@ public class GroupInviteActivity extends BaseFragment implements NotificationCen builder.setMessage(LocaleController.getString("RevokeAlertNewLink", R.string.RevokeAlertNewLink)); builder.setTitle(LocaleController.getString("RevokeLink", R.string.RevokeLink)); builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); - showAlertDialog(builder); + showDialog(builder.create()); } } loading = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java index 2d3599521..57766ebc6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java @@ -30,7 +30,6 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.messenger.R; -import org.telegram.messenger.Utilities; public class IntroActivity extends Activity { private ViewPager viewPager; @@ -236,8 +235,14 @@ public class IntroActivity extends Activity { } justCreated = false; } - Utilities.checkForCrashes(this); - Utilities.checkForUpdates(this); + AndroidUtilities.checkForCrashes(this); + AndroidUtilities.checkForUpdates(this); + } + + @Override + protected void onPause() { + super.onPause(); + AndroidUtilities.unregisterUpdates(); } private class IntroAdapter extends PagerAdapter { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index 0e17c33d2..f7f1bd2d1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -215,7 +215,7 @@ public class LanguageSelectActivity extends BaseFragment { } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); return true; } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java index fcc8ace2a..1b1f81c04 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java @@ -129,7 +129,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); return; } } @@ -179,7 +179,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter currentType = newType; updateRows(); } else if (i == neverShareRow || i == alwaysShareRow) { - ArrayList createFromArray = null; + ArrayList createFromArray; if (i == neverShareRow) { createFromArray = currentMinus; } else { @@ -323,7 +323,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("PrivacyFloodControlError", R.string.PrivacyFloodControlError)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showAlertDialog(builder); + showDialog(builder.create()); } private void checkPrivacy() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java index b4d4c93d0..b476860fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java @@ -186,7 +186,7 @@ public class LastSeenUsersActivity extends BaseFragment implements NotificationC } } }); - showAlertDialog(builder); + showDialog(builder.create()); return true; } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 6d517a28a..42abf382a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -45,6 +45,7 @@ import org.telegram.android.ContactsController; import org.telegram.android.MessagesController; import org.telegram.android.MessagesStorage; import org.telegram.android.SendMessagesHelper; +import org.telegram.android.query.StickersQuery; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; @@ -55,7 +56,6 @@ import org.telegram.messenger.RPCRequest; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.Utilities; import org.telegram.ui.Adapters.DrawerLayoutAdapter; import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.BaseFragment; @@ -131,6 +131,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa setTheme(R.style.Theme_TMessages); getWindow().setBackgroundDrawableResource(R.drawable.transparent); + super.onCreate(savedInstanceState); if (UserConfig.passcodeHash.length() != 0 && UserConfig.appLocked) { @@ -340,8 +341,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa NotificationCenter.getInstance().addObserver(this, NotificationCenter.didUpdatedConnectionState); if (Build.VERSION.SDK_INT < 14) { NotificationCenter.getInstance().addObserver(this, NotificationCenter.screenStateChanged); - } else { - NotificationCenter.getInstance().addObserver(this, NotificationCenter.appSwitchedToForeground); } if (actionBarLayout.fragmentsStack.isEmpty()) { @@ -402,11 +401,12 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa FileLog.e("tmessages", e); } } else { - boolean allowOpen = false; + boolean allowOpen = true; if (AndroidUtilities.isTablet()) { allowOpen = actionBarLayout.fragmentsStack.size() <= 1 && layersActionBarLayout.fragmentsStack.isEmpty(); - } else { - allowOpen = actionBarLayout.fragmentsStack.size() <= 1; + if (layersActionBarLayout.fragmentsStack.size() == 1 && layersActionBarLayout.fragmentsStack.get(0) instanceof LoginActivity) { + allowOpen = false; + } } if (actionBarLayout.fragmentsStack.size() == 1 && actionBarLayout.fragmentsStack.get(0) instanceof LoginActivity) { allowOpen = false; @@ -478,22 +478,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (Intent.ACTION_SEND.equals(intent.getAction())) { boolean error = false; String type = intent.getType(); - if (type != null && (type.equals("text/plain") || type.equals("message/rfc822")) && (intent.getStringExtra(Intent.EXTRA_TEXT) != null || intent.getCharSequenceExtra(Intent.EXTRA_TEXT) != null)) { - String text = intent.getStringExtra(Intent.EXTRA_TEXT); - if (text == null) { - text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT).toString(); - } - String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT); - - if (text != null && text.length() != 0) { - if ((text.startsWith("http://") || text.startsWith("https://")) && subject != null && subject.length() != 0) { - text = subject + "\n" + text; - } - sendingText = text; - } else { - error = true; - } - } else if (type != null && type.equals(ContactsContract.Contacts.CONTENT_VCARD_TYPE)) { + if (type != null && type.equals(ContactsContract.Contacts.CONTENT_VCARD_TYPE)) { try { Uri uri = (Uri) intent.getExtras().get(Intent.EXTRA_STREAM); if (uri != null) { @@ -505,7 +490,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa String nameCharset = null; ArrayList phones = new ArrayList<>(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, "UTF-8")); - String line = null; + String line; while ((line = bufferedReader.readLine()) != null) { String[] args = line.split(":"); if (args.length != 2) { @@ -534,7 +519,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } name += line; } - byte[] bytes = Utilities.decodeQuotedPrintable(name.getBytes()); + byte[] bytes = AndroidUtilities.decodeQuotedPrintable(name.getBytes()); if (bytes != null && bytes.length != 0) { String decodedName = new String(bytes, nameCharset); if (decodedName != null) { @@ -574,21 +559,40 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa error = true; } } else { + if (type != null && (type.equals("text/plain") || type.equals("message/rfc822")) && (intent.getStringExtra(Intent.EXTRA_TEXT) != null || intent.getCharSequenceExtra(Intent.EXTRA_TEXT) != null)) { + String text = intent.getStringExtra(Intent.EXTRA_TEXT); + if (text == null) { + text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT).toString(); + } + String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT); + + if (text != null && text.length() != 0) { + if ((text.startsWith("http://") || text.startsWith("https://")) && subject != null && subject.length() != 0) { + text = subject + "\n" + text; + } + sendingText = text; + if (sendingText.contains("WhatsApp")) { //who needs this sent from ...? + sendingText = null; + } + } else { + error = true; + } + } Parcelable parcelable = intent.getParcelableExtra(Intent.EXTRA_STREAM); if (parcelable != null) { - String path = null; + String path; if (!(parcelable instanceof Uri)) { parcelable = Uri.parse(parcelable.toString()); } Uri uri = (Uri) parcelable; - if (uri != null && type != null && type.startsWith("image/")) { - String tempPath = Utilities.getPath(uri); + if (uri != null && (type != null && type.startsWith("image/") || uri.toString().toLowerCase().endsWith(".jpg"))) { + String tempPath = AndroidUtilities.getPath(uri); if (photoPathsArray == null) { photoPathsArray = new ArrayList<>(); } photoPathsArray.add(uri); } else { - path = Utilities.getPath(uri); + path = AndroidUtilities.getPath(uri); if (path != null) { if (path.startsWith("file:")) { path = path.replace("file://", ""); @@ -611,12 +615,12 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa documentsMimeType = type; } } - } else { + } else if (sendingText == null) { error = true; } - if (error) { - Toast.makeText(this, "Unsupported content", Toast.LENGTH_SHORT).show(); - } + } + if (error) { + Toast.makeText(this, "Unsupported content", Toast.LENGTH_SHORT).show(); } } else if (intent.getAction().equals(Intent.ACTION_SEND_MULTIPLE)) { boolean error = false; @@ -640,7 +644,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (!(parcelable instanceof Uri)) { parcelable = Uri.parse(parcelable.toString()); } - String path = Utilities.getPath((Uri) parcelable); + String path = AndroidUtilities.getPath((Uri) parcelable); String originalPath = parcelable.toString(); if (originalPath == null) { originalPath = path; @@ -673,6 +677,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (data != null) { String username = null; String group = null; + String sticker = null; String scheme = data.getScheme(); if (scheme != null) { if ((scheme.equals("http") || scheme.equals("https"))) { @@ -683,6 +688,8 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa path = path.substring(1); if (path.startsWith("joinchat/")) { group = path.replace("joinchat/", ""); + } else if (path.startsWith("addstickers/")) { + sticker = path.replace("addstickers/", ""); } else { username = path; } @@ -698,11 +705,15 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa url = url.replace("tg:join", "tg://telegram.org").replace("tg://join", "tg://telegram.org"); data = Uri.parse(url); group = data.getQueryParameter("invite"); + } else if (url.startsWith("tg:addstickers") || url.startsWith("tg://addstickers")) { + url = url.replace("tg:addstickers", "tg://telegram.org").replace("tg://addstickers", "tg://telegram.org"); + data = Uri.parse(url); + sticker = data.getQueryParameter("set"); } } } - if (username != null || group != null) { - runLinkRequest(username, group, 0); + if (username != null || group != null || sticker != null) { + runLinkRequest(username, group, sticker, 0); } else { try { Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null); @@ -742,15 +753,11 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } if (push_user_id != 0) { - if (push_user_id == UserConfig.getClientUserId()) { - open_settings = 1; - } else { - Bundle args = new Bundle(); - args.putInt("user_id", push_user_id); - ChatActivity fragment = new ChatActivity(args); - if (actionBarLayout.presentFragment(fragment, false, true, true)) { - pushOpened = true; - } + Bundle args = new Bundle(); + args.putInt("user_id", push_user_id); + ChatActivity fragment = new ChatActivity(args); + if (actionBarLayout.presentFragment(fragment, false, true, true)) { + pushOpened = true; } } else if (push_chat_id != 0) { Bundle args = new Bundle(); @@ -790,7 +797,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa args.putString("selectAlertStringGroup", LocaleController.getString("SendMessagesToGroup", R.string.SendMessagesToGroup)); MessagesActivity fragment = new MessagesActivity(args); fragment.setDelegate(this); - boolean removeLast = false; + boolean removeLast; if (AndroidUtilities.isTablet()) { removeLast = layersActionBarLayout.fragmentsStack.size() > 0 && layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1) instanceof MessagesActivity; } else { @@ -858,7 +865,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa return false; } - private void runLinkRequest(final String username, final String group, final int state) { + private void runLinkRequest(final String username, final String group, final String sticker, final int state) { final ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); progressDialog.setCanceledOnTouchOutside(false); @@ -932,7 +939,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - runLinkRequest(username, group, 1); + runLinkRequest(username, group, sticker, 1); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -999,6 +1006,13 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } }); } + } else if (sticker != null) { + if (!mainFragmentsStack.isEmpty()) { + TLRPC.TL_inputStickerSetShortName stickerset = new TLRPC.TL_inputStickerSetShortName(); + stickerset.short_name = sticker; + StickersQuery.loadStickers(mainFragmentsStack.get(0), stickerset); + } + return; } final long reqId = requestId; @@ -1136,8 +1150,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didUpdatedConnectionState); if (Build.VERSION.SDK_INT < 14) { NotificationCenter.getInstance().removeObserver(this, NotificationCenter.screenStateChanged); - } else { - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.appSwitchedToForeground); } } @@ -1274,6 +1286,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } ApplicationLoader.mainInterfacePaused = true; ConnectionsManager.getInstance().setAppPaused(true, false); + AndroidUtilities.unregisterUpdates(); } @Override @@ -1305,8 +1318,8 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } else { passcodeView.onResume(); } - Utilities.checkForCrashes(this); - Utilities.checkForUpdates(this); + AndroidUtilities.checkForCrashes(this); + AndroidUtilities.checkForUpdates(this); ApplicationLoader.mainInterfacePaused = false; ConnectionsManager.getInstance().setAppPaused(false, false); updateCurrentConnectionState(); @@ -1369,8 +1382,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa onPasscodeResume(); } } - } else if (id == NotificationCenter.appSwitchedToForeground) { - onPasscodeResume(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index 7dd309e84..2ae84cf47 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -9,7 +9,9 @@ package org.telegram.ui; import android.animation.Animator; +import android.annotation.SuppressLint; import android.app.AlertDialog; +import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; @@ -269,7 +271,7 @@ public class LoginActivity extends BaseFragment { } else if (currentViewNum == 3) { views[currentViewNum].onBackPressed(); setPage(0, true, null, true); - } else if (currentViewNum == 4) { + } else if (currentViewNum == 4) { views[currentViewNum].onBackPressed(); setPage(3, true, null, true); } @@ -284,7 +286,7 @@ public class LoginActivity extends BaseFragment { builder.setTitle(title); builder.setMessage(text); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showAlertDialog(builder); + showDialog(builder.create()); } public void needShowProgress() { @@ -326,6 +328,7 @@ public class LoginActivity extends BaseFragment { public void onAnimationStart(Animator animator) { } + @SuppressLint("NewApi") @Override public void onAnimationEnd(Animator animator) { outView.setVisibility(View.GONE); @@ -770,6 +773,7 @@ public class LoginActivity extends BaseFragment { needShowAlert(LocaleController.getString("AppName", R.string.AppName), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); return; } + ConnectionsManager.getInstance().cleanUp(); TLRPC.TL_auth_sendCode req = new TLRPC.TL_auth_sendCode(); String phone = PhoneFormat.stripExceptNumbers("" + codeField.getText() + phoneField.getText()); ConnectionsManager.getInstance().applyCountryPortNumber(phone); @@ -1302,18 +1306,13 @@ public class LoginActivity extends BaseFragment { @Override public void didReceivedNotification(int id, final Object... args) { if (id == NotificationCenter.didReceiveSmsCode) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (!waitingForSms) { - return; - } - if (codeField != null) { - codeField.setText("" + args[0]); - onNextPressed(); - } - } - }); + if (!waitingForSms) { + return; + } + if (codeField != null) { + codeField.setText("" + args[0]); + onNextPressed(); + } } } @@ -1453,7 +1452,7 @@ public class LoginActivity extends BaseFragment { setPage(4, true, bundle, false); } }); - AlertDialog dialog = showAlertDialog(builder); + Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); @@ -1536,7 +1535,7 @@ public class LoginActivity extends BaseFragment { } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } }); @@ -1815,7 +1814,7 @@ public class LoginActivity extends BaseFragment { setPage(3, true, new Bundle(), true); } }); - AlertDialog dialog = showAlertDialog(builder); + Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); @@ -1874,12 +1873,6 @@ public class LoginActivity extends BaseFragment { return; } nextPressed = true; - byte[] oldPasswordBytes = null; - try { - oldPasswordBytes = oldPassword.getBytes("UTF-8"); - } catch (Exception e) { - FileLog.e("tmessages", e); - } String code = codeField.getText().toString(); if (code.length() == 0) { @@ -2084,7 +2077,7 @@ public class LoginActivity extends BaseFragment { } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index 3f92e3936..cc14a0e98 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -279,7 +279,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (id == forward) { Bundle args = new Bundle(); args.putBoolean("onlySelect", true); @@ -938,7 +938,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.messageOwner.media.document.mime_type)); - showAlertDialog(builder); + showDialog(builder.create()); } } } else if (!cell.isLoading()) { @@ -1140,7 +1140,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No MessageObject messageObject = messageObjects.get(0); ((SharedMediaSectionCell) convertView).setText(LocaleController.formatterMonthYear.format((long) messageObject.messageOwner.date * 1000).toUpperCase()); } else { - SharedPhotoVideoCell cell = null; + SharedPhotoVideoCell cell; if (convertView == null) { if (!cellCache.isEmpty()) { convertView = cellCache.get(0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java index 28bc4ca84..ed15ce845 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java @@ -10,6 +10,7 @@ package org.telegram.ui; import android.animation.ObjectAnimator; import android.animation.StateListAnimator; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -17,26 +18,27 @@ import android.content.res.Configuration; import android.graphics.Outline; import android.os.Build; import android.os.Bundle; +import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.animation.AccelerateDecelerateInterpolator; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.CheckBox; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.ListView; +import android.widget.ProgressBar; import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.android.MessageObject; +import org.telegram.android.support.widget.LinearLayoutManager; +import org.telegram.android.support.widget.RecyclerView; import org.telegram.messenger.FileLog; import org.telegram.messenger.TLRPC; import org.telegram.android.ContactsController; @@ -45,7 +47,7 @@ import org.telegram.android.MessagesStorage; import org.telegram.android.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.ui.Adapters.BaseFragmentAdapter; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.Adapters.DialogsAdapter; import org.telegram.ui.Adapters.DialogsSearchAdapter; import org.telegram.android.AnimationCompat.ObjectAnimatorProxy; @@ -57,19 +59,25 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.MenuDrawable; +import org.telegram.ui.Components.EmptyTextProgressView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ResourceLoader; import java.util.ArrayList; public class MessagesActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { - private ListView messagesListView; + + private RecyclerListView listView; + private LinearLayoutManager layoutManager; private DialogsAdapter dialogsAdapter; private DialogsSearchAdapter dialogsSearchAdapter; - private View searchEmptyView; - private View progressView; - private View emptyView; + private EmptyTextProgressView searchEmptyView; + private ProgressBar progressView; + private LinearLayout emptyView; private ActionBarMenuItem passcodeItem; private ImageView floatingButton; + private int prevPosition; private int prevTop; private boolean scrollUpdated; @@ -78,21 +86,18 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter private String selectAlertString; private String selectAlertStringGroup; - private boolean serverOnly = false; + private boolean serverOnly; - private static boolean dialogsLoaded = false; - private boolean searching = false; - private boolean searchWas = false; - private boolean onlySelect = false; + private static boolean dialogsLoaded; + private boolean searching; + private boolean searchWas; + private boolean onlySelect; private long selectedDialog; private String searchString; + private long openedDialogId; private MessagesActivityDelegate delegate; - private long openedDialogId = 0; - - private static final int passcode_menu_item = 1; - public interface MessagesActivityDelegate { void didSelectDialog(MessagesActivity fragment, long dialog_id, boolean param); } @@ -157,7 +162,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(final Context context, LayoutInflater inflater) { searching = false; searchWas = false; @@ -165,22 +170,19 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter ActionBarMenu menu = actionBar.createMenu(); if (!onlySelect && searchString == null) { - passcodeItem = menu.addItem(passcode_menu_item, R.drawable.lock_close); + passcodeItem = menu.addItem(1, R.drawable.lock_close); updatePasscodeButton(); } ActionBarMenuItem item = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override public void onSearchExpand() { searching = true; - if (messagesListView != null) { + if (listView != null) { if (searchString != null) { - messagesListView.setEmptyView(progressView); - searchEmptyView.setVisibility(View.INVISIBLE); - } else { - messagesListView.setEmptyView(searchEmptyView); + listView.setEmptyView(searchEmptyView); progressView.setVisibility(View.INVISIBLE); + emptyView.setVisibility(View.INVISIBLE); } - emptyView.setVisibility(View.INVISIBLE); if (!onlySelect) { floatingButton.setVisibility(View.GONE); } @@ -196,16 +198,14 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } searching = false; searchWas = false; - if (messagesListView != null) { + if (listView != null) { + searchEmptyView.setVisibility(View.INVISIBLE); if (MessagesController.getInstance().loadingDialogs && MessagesController.getInstance().dialogs.isEmpty()) { - searchEmptyView.setVisibility(View.INVISIBLE); emptyView.setVisibility(View.INVISIBLE); - progressView.setVisibility(View.VISIBLE); - messagesListView.setEmptyView(progressView); + listView.setEmptyView(progressView); } else { - messagesListView.setEmptyView(emptyView); - searchEmptyView.setVisibility(View.INVISIBLE); progressView.setVisibility(View.INVISIBLE); + listView.setEmptyView(emptyView); } if (!onlySelect) { floatingButton.setVisibility(View.VISIBLE); @@ -213,8 +213,8 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter ViewProxy.setTranslationY(floatingButton, AndroidUtilities.dp(100)); hideFloatingButton(false); } - if (messagesListView.getAdapter() != dialogsAdapter) { - messagesListView.setAdapter(dialogsAdapter); + if (listView.getAdapter() != dialogsAdapter) { + listView.setAdapter(dialogsAdapter); dialogsAdapter.notifyDataSetChanged(); } } @@ -231,13 +231,14 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter if (text.length() != 0) { searchWas = true; if (dialogsSearchAdapter != null) { - messagesListView.setAdapter(dialogsSearchAdapter); + listView.setAdapter(dialogsSearchAdapter); dialogsSearchAdapter.notifyDataSetChanged(); } - if (searchEmptyView != null && messagesListView.getEmptyView() == emptyView) { - messagesListView.setEmptyView(searchEmptyView); + if (searchEmptyView != null && listView.getEmptyView() != searchEmptyView) { emptyView.setVisibility(View.INVISIBLE); progressView.setVisibility(View.INVISIBLE); + searchEmptyView.showTextView(); + listView.setEmptyView(searchEmptyView); } } if (dialogsSearchAdapter != null) { @@ -268,7 +269,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } else if (parentLayout != null) { parentLayout.getDrawerLayoutContainer().openDrawer(false); } - } else if (id == passcode_menu_item) { + } else if (id == 1) { UserConfig.appLocked = !UserConfig.appLocked; UserConfig.saveConfig(false); updatePasscodeButton(); @@ -276,127 +277,47 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } }); - fragmentView = inflater.inflate(R.layout.messages_list, null, false); - if (searchString == null) { - dialogsAdapter = new DialogsAdapter(context, serverOnly); - if (AndroidUtilities.isTablet() && openedDialogId != 0) { - dialogsAdapter.setOpenedDialogId(openedDialogId); - } - } - int type = 0; - if (searchString != null) { - type = 2; - } else if (!onlySelect) { - type = 1; - } - dialogsSearchAdapter = new DialogsSearchAdapter(context, type); - dialogsSearchAdapter.setDelegate(new DialogsSearchAdapter.MessagesActivitySearchAdapterDelegate() { + FrameLayout frameLayout = new FrameLayout(context); + fragmentView = frameLayout; + + listView = new RecyclerListView(context); + listView.setVerticalScrollBarEnabled(true); + listView.setItemAnimator(null); + listView.setInstantClick(true); + listView.setLayoutAnimation(null); + layoutManager = new LinearLayoutManager(context) { @Override - public void searchStateChanged(boolean search) { - if (searching && searchWas && messagesListView != null) { - progressView.setVisibility(search ? View.VISIBLE : View.INVISIBLE); - searchEmptyView.setVisibility(search ? View.INVISIBLE : View.VISIBLE); - messagesListView.setEmptyView(search ? progressView : searchEmptyView); - } + public boolean supportsPredictiveItemAnimations() { + return false; } - }); - - messagesListView = (ListView) fragmentView.findViewById(R.id.messages_list_view); - if (dialogsAdapter != null) { - messagesListView.setAdapter(dialogsAdapter); - } + }; + layoutManager.setOrientation(LinearLayoutManager.VERTICAL); + listView.setLayoutManager(layoutManager); if (Build.VERSION.SDK_INT >= 11) { - messagesListView.setVerticalScrollbarPosition(LocaleController.isRTL ? ListView.SCROLLBAR_POSITION_LEFT : ListView.SCROLLBAR_POSITION_RIGHT); + listView.setVerticalScrollbarPosition(LocaleController.isRTL ? ListView.SCROLLBAR_POSITION_LEFT : ListView.SCROLLBAR_POSITION_RIGHT); } - - progressView = fragmentView.findViewById(R.id.progressLayout); - searchEmptyView = fragmentView.findViewById(R.id.search_empty_view); - searchEmptyView.setOnTouchListener(new View.OnTouchListener() { + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { @Override - public boolean onTouch(View v, MotionEvent event) { - return true; - } - }); - emptyView = fragmentView.findViewById(R.id.list_empty_view); - emptyView.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - return true; - } - }); - - - TextView textView = (TextView) fragmentView.findViewById(R.id.list_empty_view_text1); - textView.setText(LocaleController.getString("NoChats", R.string.NoChats)); - textView = (TextView) fragmentView.findViewById(R.id.list_empty_view_text2); - String help = LocaleController.getString("NoChatsHelp", R.string.NoChatsHelp); - if (AndroidUtilities.isTablet() && !AndroidUtilities.isSmallTablet()) { - help = help.replace("\n", " "); - } - textView.setText(help); - textView = (TextView) fragmentView.findViewById(R.id.search_empty_text); - textView.setText(LocaleController.getString("NoResult", R.string.NoResult)); - - floatingButton = (ImageView) fragmentView.findViewById(R.id.floating_button); - floatingButton.setVisibility(onlySelect ? View.GONE : View.VISIBLE); - floatingButton.setScaleType(ImageView.ScaleType.CENTER); - if (Build.VERSION.SDK_INT >= 21) { - StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(floatingButton, "translationZ", AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(floatingButton, "translationZ", AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); - floatingButton.setStateListAnimator(animator); - floatingButton.setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - outline.setOval(0, 0, AndroidUtilities.dp(56), AndroidUtilities.dp(56)); - } - }); - } - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) floatingButton.getLayoutParams(); - layoutParams.leftMargin = LocaleController.isRTL ? AndroidUtilities.dp(14) : 0; - layoutParams.rightMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(14); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM; - floatingButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Bundle args = new Bundle(); - args.putBoolean("destroyAfterSelect", true); - presentFragment(new ContactsActivity(args)); - } - }); - - if (MessagesController.getInstance().loadingDialogs && MessagesController.getInstance().dialogs.isEmpty()) { - searchEmptyView.setVisibility(View.INVISIBLE); - emptyView.setVisibility(View.INVISIBLE); - progressView.setVisibility(View.VISIBLE); - messagesListView.setEmptyView(progressView); - } else { - messagesListView.setEmptyView(emptyView); - searchEmptyView.setVisibility(View.INVISIBLE); - progressView.setVisibility(View.INVISIBLE); - } - - messagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { - if (messagesListView == null || messagesListView.getAdapter() == null) { + public void onItemClick(View view, int position) { + if (listView == null || listView.getAdapter() == null) { return; } long dialog_id = 0; int message_id = 0; - BaseFragmentAdapter adapter = (BaseFragmentAdapter) messagesListView.getAdapter(); + RecyclerView.Adapter adapter = listView.getAdapter(); if (adapter == dialogsAdapter) { - TLRPC.TL_dialog dialog = dialogsAdapter.getItem(i); + TLRPC.TL_dialog dialog = dialogsAdapter.getItem(position); if (dialog == null) { return; } dialog_id = dialog.id; } else if (adapter == dialogsSearchAdapter) { - Object obj = dialogsSearchAdapter.getItem(i); + Object obj = dialogsSearchAdapter.getItem(position); if (obj instanceof TLRPC.User) { dialog_id = ((TLRPC.User) obj).id; - if (dialogsSearchAdapter.isGlobalSearch(i)) { + if (dialogsSearchAdapter.isGlobalSearch(position)) { ArrayList users = new ArrayList<>(); users.add((TLRPC.User) obj); MessagesController.getInstance().putUsers(users, false); @@ -468,15 +389,14 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } } }); - - messagesListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + listView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() { @Override - public boolean onItemLongClick(AdapterView adapterView, View view, int i, long l) { + public void onItemClick(View view, int position) { if (onlySelect || searching && searchWas || getParentActivity() == null) { if (searchWas && searching) { - BaseFragmentAdapter adapter = (BaseFragmentAdapter) messagesListView.getAdapter(); + RecyclerView.Adapter adapter = listView.getAdapter(); if (adapter == dialogsSearchAdapter) { - Object item = adapter.getItem(i); + Object item = dialogsSearchAdapter.getItem(position); if (item instanceof String) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); @@ -488,30 +408,35 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); - return true; + showDialog(builder.create()); + return; } } } - return false; + return; } TLRPC.TL_dialog dialog; if (serverOnly) { - if (i >= MessagesController.getInstance().dialogsServerOnly.size()) { - return false; + if (position < 0 || position >= MessagesController.getInstance().dialogsServerOnly.size()) { + return; } - dialog = MessagesController.getInstance().dialogsServerOnly.get(i); + dialog = MessagesController.getInstance().dialogsServerOnly.get(position); } else { - if (i >= MessagesController.getInstance().dialogs.size()) { - return false; + if (position < 0 || position >= MessagesController.getInstance().dialogs.size()) { + return; } - dialog = MessagesController.getInstance().dialogs.get(i); + dialog = MessagesController.getInstance().dialogs.get(position); } selectedDialog = dialog.id; - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + /*AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create());*/ + + BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); int lower_id = (int) selectedDialog; int high_id = (int) (selectedDialog >> 32); @@ -536,7 +461,12 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter public void onClick(DialogInterface dialogInterface, int i) { if (which != 0) { if (isChat) { - MessagesController.getInstance().deleteUserFromChat((int) -selectedDialog, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), null); + TLRPC.Chat currentChat = MessagesController.getInstance().getChat((int) -selectedDialog); + if (currentChat != null && currentChat.left || currentChat instanceof TLRPC.TL_chatForbidden) { + MessagesController.getInstance().deleteDialog(selectedDialog, 0, false); + } else { + MessagesController.getInstance().deleteUserFromChat((int) -selectedDialog, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), null); + } } else { MessagesController.getInstance().deleteDialog(selectedDialog, 0, false); } @@ -549,39 +479,111 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); + } + }); + + searchEmptyView = new EmptyTextProgressView(context); + searchEmptyView.setVisibility(View.INVISIBLE); + searchEmptyView.setShowAtCenter(true); + searchEmptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + frameLayout.addView(searchEmptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + emptyView = new LinearLayout(context); + emptyView.setOrientation(LinearLayout.VERTICAL); + emptyView.setVisibility(View.INVISIBLE); + emptyView.setGravity(Gravity.CENTER); + frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + emptyView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { return true; } }); - messagesListView.setOnScrollListener(new AbsListView.OnScrollListener() { + TextView textView = new TextView(context); + textView.setText(LocaleController.getString("NoChats", R.string.NoChats)); + textView.setTextColor(0xff959595); + textView.setGravity(Gravity.CENTER); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + emptyView.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + textView = new TextView(context); + String help = LocaleController.getString("NoChatsHelp", R.string.NoChatsHelp); + if (AndroidUtilities.isTablet() && !AndroidUtilities.isSmallTablet()) { + help = help.replace("\n", " "); + } + textView.setText(help); + textView.setTextColor(0xff959595); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setGravity(Gravity.CENTER); + textView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(6), AndroidUtilities.dp(8), 0); + textView.setLineSpacing(AndroidUtilities.dp(2), 1); + emptyView.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + progressView = new ProgressBar(context); + progressView.setVisibility(View.INVISIBLE); + frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + + floatingButton = new ImageView(context); + floatingButton.setVisibility(onlySelect ? View.GONE : View.VISIBLE); + floatingButton.setScaleType(ImageView.ScaleType.CENTER); + floatingButton.setBackgroundResource(R.drawable.floating_states); + floatingButton.setImageResource(R.drawable.floating_pencil); + if (Build.VERSION.SDK_INT >= 21) { + StateListAnimator animator = new StateListAnimator(); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(floatingButton, "translationZ", AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(floatingButton, "translationZ", AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + floatingButton.setStateListAnimator(animator); + floatingButton.setOutlineProvider(new ViewOutlineProvider() { + @SuppressLint("NewApi") + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(56), AndroidUtilities.dp(56)); + } + }); + } + frameLayout.addView(floatingButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM, LocaleController.isRTL ? 14 : 0, 0, LocaleController.isRTL ? 0 : 14, 14)); + floatingButton.setOnClickListener(new View.OnClickListener() { @Override - public void onScrollStateChanged(AbsListView absListView, int i) { - if (i == SCROLL_STATE_TOUCH_SCROLL && searching && searchWas) { + public void onClick(View v) { + Bundle args = new Bundle(); + args.putBoolean("destroyAfterSelect", true); + presentFragment(new ContactsActivity(args)); + } + }); + + listView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING && searching && searchWas) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } } @Override - public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); + int visibleItemCount = Math.abs(layoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; + int totalItemCount = recyclerView.getAdapter().getItemCount(); + if (searching && searchWas) { - if (visibleItemCount > 0 && absListView.getLastVisiblePosition() == totalItemCount - 1 && !dialogsSearchAdapter.isMessagesSearchEndReached()) { + if (visibleItemCount > 0 && layoutManager.findLastVisibleItemPosition() == totalItemCount - 1 && !dialogsSearchAdapter.isMessagesSearchEndReached()) { dialogsSearchAdapter.loadMoreSearchMessages(); } return; } if (visibleItemCount > 0) { - if (absListView.getLastVisiblePosition() == MessagesController.getInstance().dialogs.size() && !serverOnly || absListView.getLastVisiblePosition() == MessagesController.getInstance().dialogsServerOnly.size() && serverOnly) { + if (layoutManager.findLastVisibleItemPosition() == MessagesController.getInstance().dialogs.size() && !serverOnly || layoutManager.findLastVisibleItemPosition() == MessagesController.getInstance().dialogsServerOnly.size() && serverOnly) { MessagesController.getInstance().loadDialogs(MessagesController.getInstance().dialogs.size(), MessagesController.getInstance().dialogsServerOnly.size(), 100, true); } } if (floatingButton.getVisibility() != View.GONE) { - final View topChild = absListView.getChildAt(0); + final View topChild = recyclerView.getChildAt(0); int firstViewTop = 0; if (topChild != null) { firstViewTop = topChild.getTop(); @@ -605,6 +607,42 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } }); + if (searchString == null) { + dialogsAdapter = new DialogsAdapter(context, serverOnly); + if (AndroidUtilities.isTablet() && openedDialogId != 0) { + dialogsAdapter.setOpenedDialogId(openedDialogId); + } + listView.setAdapter(dialogsAdapter); + } + int type = 0; + if (searchString != null) { + type = 2; + } else if (!onlySelect) { + type = 1; + } + dialogsSearchAdapter = new DialogsSearchAdapter(context, type); + dialogsSearchAdapter.setDelegate(new DialogsSearchAdapter.MessagesActivitySearchAdapterDelegate() { + @Override + public void searchStateChanged(boolean search) { + if (searching && searchWas && searchEmptyView != null) { + if (search) { + searchEmptyView.showProgress(); + } else { + searchEmptyView.showTextView(); + } + } + } + }); + + if (MessagesController.getInstance().loadingDialogs && MessagesController.getInstance().dialogs.isEmpty()) { + searchEmptyView.setVisibility(View.INVISIBLE); + emptyView.setVisibility(View.INVISIBLE); + listView.setEmptyView(progressView); + } else { + searchEmptyView.setVisibility(View.INVISIBLE); + progressView.setVisibility(View.INVISIBLE); + listView.setEmptyView(emptyView); + } if (searchString != null) { actionBar.openSearchField(searchString); } @@ -658,32 +696,32 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter if (dialogsSearchAdapter != null) { dialogsSearchAdapter.notifyDataSetChanged(); } - if (messagesListView != null) { + if (listView != null) { try { if (MessagesController.getInstance().loadingDialogs && MessagesController.getInstance().dialogs.isEmpty()) { searchEmptyView.setVisibility(View.INVISIBLE); emptyView.setVisibility(View.INVISIBLE); - messagesListView.setEmptyView(progressView); + listView.setEmptyView(progressView); } else { - if (searching && searchWas) { - messagesListView.setEmptyView(searchEmptyView); - emptyView.setVisibility(View.INVISIBLE); - } else { - messagesListView.setEmptyView(emptyView); - searchEmptyView.setVisibility(View.INVISIBLE); - } progressView.setVisibility(View.INVISIBLE); + if (searching && searchWas) { + emptyView.setVisibility(View.INVISIBLE); + listView.setEmptyView(searchEmptyView); + } else { + searchEmptyView.setVisibility(View.INVISIBLE); + listView.setEmptyView(emptyView); + } } } catch (Exception e) { FileLog.e("tmessages", e); //TODO fix it in other way? } } } else if (id == NotificationCenter.emojiDidLoaded) { - if (messagesListView != null) { + if (listView != null) { updateVisibleRows(0); } } else if (id == NotificationCenter.updateInterfaces) { - updateVisibleRows((Integer)args[0]); + updateVisibleRows((Integer) args[0]); } else if (id == NotificationCenter.appDidLogout) { dialogsLoaded = false; } else if (id == NotificationCenter.encryptedChatUpdated) { @@ -692,8 +730,8 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter updateVisibleRows(0); } else if (id == NotificationCenter.openedChatChanged) { if (!serverOnly && AndroidUtilities.isTablet()) { - boolean close = (Boolean)args[1]; - long dialog_id = (Long)args[0]; + boolean close = (Boolean) args[1]; + long dialog_id = (Long) args[0]; if (close) { if (dialog_id == openedDialogId) { openedDialogId = 0; @@ -743,22 +781,22 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } private void updateVisibleRows(int mask) { - if (messagesListView == null) { + if (listView == null) { return; } - int count = messagesListView.getChildCount(); + int count = listView.getChildCount(); for (int a = 0; a < count; a++) { - View child = messagesListView.getChildAt(a); + View child = listView.getChildAt(a); if (child instanceof DialogCell) { DialogCell cell = (DialogCell) child; if ((mask & MessagesController.UPDATE_MASK_NEW_MESSAGE) != 0) { cell.checkCurrentDialogIndex(); if (!serverOnly && AndroidUtilities.isTablet()) { - child.setBackgroundColor(cell.getDialogId() == openedDialogId ? 0x0f000000 : 0); + cell.setDialogSelected(cell.getDialogId() == openedDialogId); } } else if ((mask & MessagesController.UPDATE_MASK_SELECT_DIALOG) != 0) { if (!serverOnly && AndroidUtilities.isTablet()) { - child.setBackgroundColor(cell.getDialogId() == openedDialogId ? 0x0f000000 : 0); + cell.setDialogSelected(cell.getDialogId() == openedDialogId); } } else { cell.update(mask); @@ -788,8 +826,8 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - int lower_part = (int)dialog_id; - int high_id = (int)(dialog_id >> 32); + int lower_part = (int) dialog_id; + int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { if (high_id == 1) { TLRPC.Chat chat = MessagesController.getInstance().getChat(lower_part); @@ -820,29 +858,15 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } builder.setMessage(LocaleController.formatStringSimple(selectAlertString, ContactsController.formatName(user.first_name, user.last_name))); } - CheckBox checkBox = null; - /*if (delegate instanceof ChatActivity) { - checkBox = new CheckBox(getParentActivity()); - checkBox.setText(LocaleController.getString("ForwardFromMyName", R.string.ForwardFromMyName)); - checkBox.setChecked(false); - builder.setView(checkBox); - }*/ - final CheckBox checkBoxFinal = checkBox; + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - didSelectResult(dialog_id, false, checkBoxFinal != null && checkBoxFinal.isChecked()); + didSelectResult(dialog_id, false, false); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); - if (checkBox != null) { - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)checkBox.getLayoutParams(); - if (layoutParams != null) { - layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(10); - checkBox.setLayoutParams(layoutParams); - } - } + showDialog(builder.create()); } else { if (delegate != null) { delegate.didSelectDialog(MessagesActivity.this, dialog_id, param); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index 14868a899..a6d162c9a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -19,11 +19,13 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.provider.Settings; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.FrameLayout; +import android.widget.LinearLayout; import android.widget.ListView; import android.widget.Toast; @@ -356,16 +358,17 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } } else if (i == messageLedRow || i == groupLedRow) { if (getParentActivity() == null) { return; } - LayoutInflater li = (LayoutInflater) getParentActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = li.inflate(R.layout.settings_color_dialog_layout, null, false); - final ColorPickerView colorPickerView = (ColorPickerView) view.findViewById(R.id.color_picker); + LinearLayout linearLayout = new LinearLayout(getParentActivity()); + linearLayout.setOrientation(LinearLayout.VERTICAL); + final ColorPickerView colorPickerView = new ColorPickerView(getParentActivity()); + linearLayout.addView(colorPickerView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); if (i == messageLedRow) { @@ -376,7 +379,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("LedColor", R.string.LedColor)); - builder.setView(view); + builder.setView(linearLayout); builder.setPositiveButton(LocaleController.getString("Set", R.string.Set), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int which) { @@ -405,7 +408,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif listView.invalidateViews(); } }); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == messagePopupNotificationRow || i == groupPopupNotificationRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("PopupNotification", R.string.PopupNotification)); @@ -431,7 +434,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == messageVibrateRow || i == groupVibrateRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("Vibrate", R.string.Vibrate)); @@ -468,7 +471,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == messagePriorityRow || i == groupPriorityRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("NotificationsPriority", R.string.NotificationsPriority)); @@ -491,7 +494,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == repeatRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("RepeatNotifications", R.string.RepeatNotifications)); @@ -528,7 +531,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(!enabled); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java index 5cbf1d5ed..49333c45b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java @@ -37,7 +37,6 @@ import android.view.inputmethod.EditorInfo; import android.widget.AdapterView; import android.widget.EditText; import android.widget.FrameLayout; -import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; @@ -392,7 +391,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter UserConfig.saveConfig(false); } }); - showAlertDialog(builder); + showDialog(builder.create()); } } }); @@ -526,7 +525,20 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter passwordEditText.setText(""); return; } - UserConfig.passcodeHash = Utilities.MD5(firstPassword); + + try { + UserConfig.passcodeSalt = new byte[16]; + Utilities.random.nextBytes(UserConfig.passcodeSalt); + byte[] passcodeBytes = firstPassword.getBytes("UTF-8"); + byte[] bytes = new byte[32 + passcodeBytes.length]; + System.arraycopy(UserConfig.passcodeSalt, 0, bytes, 0, 16); + System.arraycopy(passcodeBytes, 0, bytes, 16, passcodeBytes.length); + System.arraycopy(UserConfig.passcodeSalt, 0, bytes, passcodeBytes.length + 16, 16); + UserConfig.passcodeHash = Utilities.bytesToHex(Utilities.computeSHA256(bytes, 0, bytes.length)); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + UserConfig.passcodeType = currentPasswordType; UserConfig.saveConfig(false); finishFragment(); @@ -534,7 +546,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter passwordEditText.clearFocus(); AndroidUtilities.hideKeyboard(passwordEditText); } else if (type == 2) { - if (!Utilities.MD5(passwordEditText.getText().toString()).equals(UserConfig.passcodeHash)) { + if (!UserConfig.checkPasscode(passwordEditText.getText().toString())) { passwordEditText.setText(""); onPasscodeError(); return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index 82c3db435..7b4922103 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -534,7 +534,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati public View getView(int i, View view, ViewGroup viewGroup) { int type = getItemViewType(i); if (type == 0) { - PhotoPickerAlbumsCell photoPickerAlbumsCell = null; + PhotoPickerAlbumsCell photoPickerAlbumsCell; if (view == null) { view = new PhotoPickerAlbumsCell(mContext); photoPickerAlbumsCell = (PhotoPickerAlbumsCell) view; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index ee45902c1..c737724f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -281,7 +281,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen finishFragment(); } } else { - ArrayList arrayList = null; + ArrayList arrayList; if (selectedAlbum != null) { arrayList = (ArrayList) selectedAlbum.photos; } else { @@ -319,7 +319,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); return true; } return false; @@ -471,7 +471,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen continue; } } else { - ArrayList array = null; + ArrayList array; if (searchResult.isEmpty() && lastSearchString == null) { array = recentImages; } else { @@ -527,7 +527,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen cell.photoImage.setImageResource(R.drawable.nophotos); } } else { - ArrayList array = null; + ArrayList array; if (searchResult.isEmpty() && lastSearchString == null) { array = recentImages; } else { @@ -569,7 +569,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen continue; } } else { - ArrayList array = null; + ArrayList array; if (searchResult.isEmpty() && lastSearchString == null) { array = recentImages; } else { @@ -598,7 +598,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (selectedAlbum != null) { return !(index < 0 || index >= selectedAlbum.photos.size()) && selectedPhotos.containsKey(selectedAlbum.photos.get(index).imageId); } else { - ArrayList array = null; + ArrayList array; if (searchResult.isEmpty() && lastSearchString == null) { array = recentImages; } else { @@ -623,8 +623,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen selectedPhotos.put(photoEntry.imageId, photoEntry); } } else { - MediaController.SearchImage photoEntry = null; - ArrayList array = null; + MediaController.SearchImage photoEntry; + ArrayList array; if (searchResult.isEmpty() && lastSearchString == null) { array = recentImages; } else { @@ -671,7 +671,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen selectedPhotos.put(photoEntry.imageId, photoEntry); } } else if (selectedPhotos.isEmpty()) { - ArrayList array = null; + ArrayList array; if (searchResult.isEmpty() && lastSearchString == null) { array = recentImages; } else { @@ -798,7 +798,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (nextSearchBingString != null) { url = nextSearchBingString; } else { - boolean adult = false; + boolean adult; String phone = UserConfig.getCurrentUser().phone; adult = phone.startsWith("44") || phone.startsWith("49") || phone.startsWith("43") || phone.startsWith("31") || phone.startsWith("1"); url = String.format(Locale.US, "https://api.datamarket.azure.com/Bing/Search/v1/Image?Query='%s'&$skip=%d&$top=%d&$format=json%s", URLEncoder.encode(query, "UTF-8"), offset, count, adult ? "" : "&Adult='Off'"); @@ -913,7 +913,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); int rotation = manager.getDefaultDisplay().getRotation(); - int columnsCount = 2; + int columnsCount; if (AndroidUtilities.isTablet()) { columnsCount = 3; } else { @@ -1017,7 +1017,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen ((PhotoPickerPhotoCell) v.getParent()).checkBox.setChecked(selectedPhotos.containsKey(photoEntry.imageId), true); } else { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); - MediaController.SearchImage photoEntry = null; + MediaController.SearchImage photoEntry; if (searchResult.isEmpty() && lastSearchString == null) { photoEntry = recentImages.get((Integer)((View)v.getParent()).getTag()); } else { @@ -1043,7 +1043,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen BackupImageView imageView = ((PhotoPickerPhotoCell) view).photoImage; imageView.setTag(i); view.setTag(i); - boolean showing = false; + boolean showing; imageView.setOrientation(0, true); if (selectedAlbum != null) { @@ -1063,7 +1063,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen cell.checkBox.setChecked(selectedPhotos.containsKey(photoEntry.imageId), false); showing = PhotoViewer.getInstance().isShowingImage(photoEntry.path); } else { - MediaController.SearchImage photoEntry = null; + MediaController.SearchImage photoEntry; if (searchResult.isEmpty() && lastSearchString == null) { photoEntry = recentImages.get(i); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 699433b21..270962eda 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -991,6 +991,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat checkImageView.setVisibility(View.GONE); captionDoneItem.setVisibility(View.VISIBLE); pickerView.setVisibility(View.GONE); + captionTextView.clearAnimation(); captionTextView.setVisibility(View.INVISIBLE); captionEditText.openKeyboard(); lastTitle = actionBar.getTitle(); @@ -1020,7 +1021,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ActionBarMenu menu = actionBar.createMenu(); menuItem = menu.addItem(0, R.drawable.ic_ab_other); - menuItem.setNeedOffset(false); menuItem.addSubItem(gallery_menu_showall, LocaleController.getString("ShowAllMedia", R.string.ShowAllMedia), 0); menuItem.addSubItem(gallery_menu_save, LocaleController.getString("SaveToGallery", R.string.SaveToGallery), 0); menuItem.addSubItem(gallery_menu_delete, LocaleController.getString("Delete", R.string.Delete), 0); @@ -1181,10 +1181,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat centerImage.setParentView(containerView); centerImage.setCrossfadeAlpha((byte) 2); + centerImage.setInvalidateAll(true); leftImage.setParentView(containerView); leftImage.setCrossfadeAlpha((byte) 2); + leftImage.setInvalidateAll(true); rightImage.setParentView(containerView); rightImage.setCrossfadeAlpha((byte) 2); + rightImage.setInvalidateAll(true); WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); int rotation = manager.getDefaultDisplay().getRotation(); @@ -2133,6 +2136,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat mentionListView.setVisibility(View.GONE); editorDoneLayout.setVisibility(View.GONE); captionTextView.setTag(null); + captionTextView.clearAnimation(); captionTextView.setVisibility(View.INVISIBLE); if (photoCropView != null) { photoCropView.clearAnimation(); @@ -2291,7 +2295,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat long date = (long) currentMessageObject.messageOwner.date * 1000; String dateString = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.formatterYear.format(new Date(date)), LocaleController.formatterDay.format(new Date(date))); if (currentFileNames[0] != null && currentFileNames[0].endsWith("mp4")) { - dateTextView.setText(String.format("%s (%s)", dateString, Utilities.formatFileSize(currentMessageObject.messageOwner.media.video.size))); + dateTextView.setText(String.format("%s (%s)", dateString, AndroidUtilities.formatFileSize(currentMessageObject.messageOwner.media.video.size))); } else { dateTextView.setText(dateString); } @@ -2474,6 +2478,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override public void run() { captionTextViewOld.setTag(null); + captionTextViewOld.clearAnimation(); captionTextViewOld.setVisibility(View.INVISIBLE); captionTextViewNew.setVisibility(bottomLayout.getVisibility() == View.VISIBLE || pickerView.getVisibility() == View.VISIBLE ? View.VISIBLE : View.INVISIBLE); } @@ -2602,7 +2607,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imageSize = ((MediaController.SearchImage) object).size; } } - imageReceiver.setImage(path, String.format(Locale.US, "%d_%d", size, size), placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, imageSize); + imageReceiver.setImage(path, String.format(Locale.US, "%d_%d", size, size), placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, null, imageSize); } else { imageReceiver.setImageBitmap((Bitmap) null); } @@ -2628,7 +2633,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeHolder = currentThumb; } TLRPC.PhotoSize thumbLocation = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 100); - imageReceiver.setImage(null, null, null, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, thumbLocation.location, "b", 0, true); + imageReceiver.setImage(null, null, null, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, thumbLocation.location, "b", 0, null, true); } else { imageReceiver.setImageBitmap(parentActivity.getResources().getDrawable(R.drawable.photoview_placeholder)); } @@ -2642,7 +2647,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat size[0] = -1; } TLRPC.PhotoSize thumbLocation = messageObject != null ? FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 100) : null; - imageReceiver.setImage(fileLocation, null, null, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, thumbLocation != null ? thumbLocation.location : null, "b", size[0], avatarsUserId != 0); + imageReceiver.setImage(fileLocation, null, null, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, thumbLocation != null ? thumbLocation.location : null, "b", size[0], null, avatarsUserId != 0); } } else { imageReceiver.setNeedsQualityThumb(false); @@ -2865,6 +2870,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + NotificationCenter.getInstance().setAnimationInProgress(false); if (animationEndRunnable != null) { animationEndRunnable.run(); animationEndRunnable = null; @@ -2882,6 +2888,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + NotificationCenter.getInstance().setAnimationInProgress(true); animatorSet.start(); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index 12515c1a5..d06f17a6d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -493,7 +493,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC } private void applyViewsLayoutParams(int xOffset) { - FrameLayout.LayoutParams layoutParams = null; + FrameLayout.LayoutParams layoutParams; int widht = AndroidUtilities.displaySize.x - AndroidUtilities.dp(24); if (leftView != null) { layoutParams = (FrameLayout.LayoutParams) leftView.getLayoutParams(); @@ -531,7 +531,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC } else if (num == NotificationsController.getInstance().popupMessages.size()) { num = 0; } - ViewGroup view = null; + ViewGroup view; MessageObject messageObject = NotificationsController.getInstance().popupMessages.get(num); if (messageObject.type == 1 || messageObject.type == 4) { if (imageViews.size() > 0) { @@ -595,7 +595,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC imageView.setImage(currentUrl, null, null); } } else if (messageObject.type == 2) { - PopupAudioView cell = null; + PopupAudioView cell; if (audioViews.size() > 0) { view = audioViews.get(0); audioViews.remove(0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 6fb67435a..6b6449365 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -12,7 +12,6 @@ import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -115,12 +114,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio listView.setDividerHeight(0); listView.setVerticalScrollBarEnabled(false); listView.setDrawSelectorOnTop(true); - frameLayout.addView(listView); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.gravity = Gravity.TOP; - listView.setLayoutParams(layoutParams); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -184,7 +178,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == lastSeenRow) { presentFragment(new LastSeenActivity()); } else if (i == passwordRow) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 84c5df504..980c185be 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -10,6 +10,7 @@ package org.telegram.ui; import android.animation.ObjectAnimator; import android.animation.StateListAnimator; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -261,7 +262,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (id == add_contact) { TLRPC.User user = MessagesController.getInstance().getUser(user_id); Bundle args = new Bundle(); @@ -295,7 +296,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (id == add_member) { openAddMember(); } else if (id == leave_group) { @@ -309,7 +310,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (id == edit_name) { Bundle args = new Bundle(); args.putInt("chat_id", chat_id); @@ -427,7 +428,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (getParentActivity() == null) { return; } - showAlertDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat)); + showDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat).create()); } else if (i == settingsNotificationsRow) { Bundle args = new Bundle(); if (user_id != 0) { @@ -448,7 +449,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == phoneRow) { final TLRPC.User user = MessagesController.getInstance().getUser(user_id); if (user == null || user.phone == null || user.phone.length() == 0 || getParentActivity() == null) { @@ -479,7 +480,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } }); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i > emptyRowChat2 && i < membersEndRow) { int user_id = info.participants.get(sortedUsers.get(i - emptyRowChat2 - 1)).user_id; if (user_id == UserConfig.getClientUserId()) { @@ -522,7 +523,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } }); - showAlertDialog(builder); + showDialog(builder.create()); return true; } @@ -555,6 +556,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. animator.addState(new int[]{}, ObjectAnimator.ofFloat(writeButton, "translationZ", AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); writeButton.setStateListAnimator(animator); writeButton.setOutlineProvider(new ViewOutlineProvider() { + @SuppressLint("NewApi") @Override public void getOutline(View view, Outline outline) { outline.setOval(0, 0, AndroidUtilities.dp(56), AndroidUtilities.dp(56)); @@ -607,7 +609,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } }); - showAlertDialog(builder); + showDialog(builder.create()); } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 9ed9efbf6..103ac0c18 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -160,7 +160,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == settingsNotificationsRow) { if (getParentActivity() == null) { return; @@ -193,7 +193,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == settingsSoundRow) { try { Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); @@ -228,9 +228,10 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi return; } - LayoutInflater li = (LayoutInflater) getParentActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = li.inflate(R.layout.settings_color_dialog_layout, null, false); - final ColorPickerView colorPickerView = (ColorPickerView) view.findViewById(R.id.color_picker); + LinearLayout linearLayout = new LinearLayout(getParentActivity()); + linearLayout.setOrientation(LinearLayout.VERTICAL); + final ColorPickerView colorPickerView = new ColorPickerView(getParentActivity()); + linearLayout.addView(colorPickerView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); if (preferences.contains("color_" + dialog_id)) { @@ -245,7 +246,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("LedColor", R.string.LedColor)); - builder.setView(view); + builder.setView(linearLayout); builder.setPositiveButton(LocaleController.getString("Set", R.string.Set), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int which) { @@ -276,7 +277,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi listView.invalidateViews(); } }); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == settingsPriorityRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("NotificationsPriority", R.string.NotificationsPriority)); @@ -301,7 +302,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == smartRow) { if (getParentActivity() == null) { return; @@ -416,7 +417,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } } }); - showAlertDialog(builder); + showDialog(builder.create()); } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java index 682d366bb..368898919 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java @@ -265,7 +265,7 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD BitmapDrawable drawable = ImageLoader.getInstance().getImageFromMemory(sizeFull.location, null, null); if (drawable == null) { File file = FileLoader.getPathToAttach(sizeFull); - Bitmap bitmap = null; + Bitmap bitmap; try { bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); } catch (Throwable e) { @@ -280,7 +280,7 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD if (drawable != null) { centerImage.setImageBitmap(drawable); } else { - centerImage.setImage(sizeFull.location, null, null, size, false); + centerImage.setImage(sizeFull.location, null, null, size, null, false); } currentMessageObject = messageObject; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index c27a0a4c4..a7185bc3d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -224,7 +224,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i >= otherSessionsStartRow && i < otherSessionsEndRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setMessage(LocaleController.getString("TerminateSessionQuestion", R.string.TerminateSessionQuestion)); @@ -266,7 +266,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } } }); @@ -336,7 +336,11 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter currentSessionSectionRow = -1; } if (sessions.isEmpty()) { - noOtherSessionsRow = -1; + if (currentSession != null) { + noOtherSessionsRow = rowCount++; + } else { + noOtherSessionsRow = -1; + } terminateAllSessionsRow = -1; terminateAllSessionsDetailRow = -1; otherSessionsSectionRow = -1; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index 99b5f9e5d..a5bdf3b00 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -10,6 +10,7 @@ package org.telegram.ui; import android.animation.ObjectAnimator; import android.animation.StateListAnimator; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; @@ -118,6 +119,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private int messagesSectionRow; private int messagesSectionRow2; private int textSizeRow; + private int stickersRow; private int sendByEnterRow; private int supportSectionRow; private int supportSectionRow2; @@ -176,7 +178,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter if (user == null) { return; } - TLRPC.TL_photos_photo photo = (TLRPC.TL_photos_photo)response; + TLRPC.TL_photos_photo photo = (TLRPC.TL_photos_photo) response; ArrayList sizes = photo.photo.sizes; TLRPC.PhotoSize smallSize = FileLoader.getClosestPhotoSizeWithSize(sizes, 100); TLRPC.PhotoSize bigSize = FileLoader.getClosestPhotoSizeWithSize(sizes, 1000); @@ -231,6 +233,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter messagesSectionRow = rowCount++; messagesSectionRow2 = rowCount++; textSizeRow = rowCount++; + stickersRow = rowCount++; sendByEnterRow = rowCount++; supportSectionRow = rowCount++; supportSectionRow2 = rowCount++; @@ -293,20 +296,11 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.clear().commit(); - MessagesController.getInstance().unregistedPush(); - MessagesController.getInstance().logOut(); - UserConfig.clearConfig(); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.appDidLogout); - MessagesStorage.getInstance().cleanUp(false); - MessagesController.getInstance().cleanUp(); - ContactsController.getInstance().deleteAllAppAccounts(); + MessagesController.getInstance().performLogout(true); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } } }); @@ -322,15 +316,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter avatarImage = new BackupImageView(context); avatarImage.setRoundRadius(AndroidUtilities.dp(30)); - actionBar.addView(avatarImage); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) avatarImage.getLayoutParams(); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM; - layoutParams.width = AndroidUtilities.dp(60); - layoutParams.height = AndroidUtilities.dp(60); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(17); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(17) : 0; - layoutParams.bottomMargin = AndroidUtilities.dp(22); - avatarImage.setLayoutParams(layoutParams); + actionBar.addView(avatarImage, LayoutHelper.createFrame(60, 60, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM, LocaleController.isRTL ? 0 : 17, 0, LocaleController.isRTL ? 17 : 0, 22)); avatarImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -351,15 +337,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter nameTextView.setEllipsize(TextUtils.TruncateAt.END); nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - actionBar.addView(nameTextView); - layoutParams = (FrameLayout.LayoutParams) nameTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 97); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 97 : 16); - layoutParams.bottomMargin = AndroidUtilities.dp(51); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM; - nameTextView.setLayoutParams(layoutParams); + actionBar.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM, LocaleController.isRTL ? 16 : 97, 0, LocaleController.isRTL ? 97 : 16, 51)); onlineTextView = new TextView(context); onlineTextView.setTextColor(AvatarDrawable.getProfileTextColorForId(5)); @@ -369,27 +347,14 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter onlineTextView.setSingleLine(true); onlineTextView.setEllipsize(TextUtils.TruncateAt.END); onlineTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - actionBar.addView(onlineTextView); - layoutParams = (FrameLayout.LayoutParams) onlineTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 97); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 97 : 16); - layoutParams.bottomMargin = AndroidUtilities.dp(30); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM; - onlineTextView.setLayoutParams(layoutParams); + actionBar.addView(onlineTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM, LocaleController.isRTL ? 16 : 97, 0, LocaleController.isRTL ? 97 : 16, 30)); listView = new ListView(context); listView.setDivider(null); listView.setDividerHeight(0); listView.setVerticalScrollBarEnabled(false); AndroidUtilities.setListViewEdgeEffectColor(listView, AvatarDrawable.getProfileBackColorForId(5)); - frameLayout.addView(listView); - layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.gravity = Gravity.TOP; - listView.setLayoutParams(layoutParams); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -418,7 +383,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } } }); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == enableAnimationsRow) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); boolean animations = preferences.getBoolean("view_animations", true); @@ -451,7 +416,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == sendLogsRow) { sendLogs(); } else if (i == clearLogsRow) { @@ -488,7 +453,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == telegramFaqRow) { try { Intent pickIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(LocaleController.getString("TelegramFaqUrl", R.string.TelegramFaqUrl))); @@ -521,7 +486,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == wifiDownloadRow || i == mobileDownloadRow || i == roamingDownloadRow) { if (getParentActivity() == null) { return; @@ -575,7 +540,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter if (i == mobileDownloadRow) { editor.putInt("mobileDataDownloadMask", mask); - mask = MediaController.getInstance().mobileDataDownloadMask = mask; + MediaController.getInstance().mobileDataDownloadMask = mask; } else if (i == wifiDownloadRow) { editor.putInt("wifiDownloadMask", mask); MediaController.getInstance().wifiDownloadMask = mask; @@ -590,11 +555,13 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }); builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); - showAlertDialog(builder); + showDialog(builder.create()); } else if (i == usernameRow) { presentFragment(new ChangeUsernameActivity()); } else if (i == numberRow) { presentFragment(new ChangePhoneHelpActivity()); + } else if (i == stickersRow) { + presentFragment(new StickersActivity()); } } }); @@ -611,20 +578,14 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter animator.addState(new int[]{}, ObjectAnimator.ofFloat(writeButton, "translationZ", AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); writeButton.setStateListAnimator(animator); writeButton.setOutlineProvider(new ViewOutlineProvider() { + @SuppressLint("NewApi") @Override public void getOutline(View view, Outline outline) { outline.setOval(0, 0, AndroidUtilities.dp(56), AndroidUtilities.dp(56)); } }); } - frameLayout.addView(writeButton); - layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 0); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 0 : 16); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT); - writeButton.setLayoutParams(layoutParams); + frameLayout.addView(writeButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 16 : 0, 0, LocaleController.isRTL ? 0 : 16, 0)); writeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -663,7 +624,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } } }); - showAlertDialog(builder); + showDialog(builder.create()); } }); @@ -737,7 +698,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } @Override - public void willSwitchFromPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { } + public void willSwitchFromPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { + } @Override public void willHidePhotoViewer() { @@ -745,19 +707,26 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } @Override - public boolean isPhotoChecked(int index) { return false; } + public boolean isPhotoChecked(int index) { + return false; + } @Override - public void setPhotoChecked(int index) { } + public void setPhotoChecked(int index) { + } @Override - public void cancelButtonPressed() { } + public void cancelButtonPressed() { + } @Override - public void sendButtonPressed(int index) { } + public void sendButtonPressed(int index) { + } @Override - public int getSelectedCount() { return 0; } + public int getSelectedCount() { + return 0; + } public void performAskAQuestion() { final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); @@ -797,7 +766,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter public void run(TLObject response, TLRPC.TL_error error) { if (error == null) { - final TLRPC.TL_help_support res = (TLRPC.TL_help_support)response; + final TLRPC.TL_help_support res = (TLRPC.TL_help_support) response; AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { @@ -866,7 +835,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter @Override public void didReceivedNotification(int id, Object... args) { if (id == NotificationCenter.updateInterfaces) { - int mask = (Integer)args[0]; + int mask = (Integer) args[0]; if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0 || (mask & MessagesController.UPDATE_MASK_NAME) != 0) { updateUserData(); } @@ -898,14 +867,14 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } if (avatarImage != null) { - float diff = actionBar.getExtraHeight() / (float)AndroidUtilities.dp(88); + float diff = actionBar.getExtraHeight() / (float) AndroidUtilities.dp(88); float diffm = 1.0f - diff; - int avatarSize = 42 + (int)(18 * diff); - int avatarX = 17 + (int)(47 * diffm); - int avatarY = AndroidUtilities.dp(22) - (int)((AndroidUtilities.dp(22) - (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff)); - int nameX = 97 + (int)(21 * diffm); - int nameEndX = 16 + (int)(32 * diffm); + int avatarSize = 42 + (int) (18 * diff); + int avatarX = 17 + (int) (47 * diffm); + int avatarY = AndroidUtilities.dp(22) - (int) ((AndroidUtilities.dp(22) - (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff)); + int nameX = 97 + (int) (21 * diffm); + int nameEndX = 16 + (int) (32 * diffm); int nameY = avatarY + AndroidUtilities.dp(29 - 13 * diffm); int statusY = avatarY + AndroidUtilities.dp(8 - 7 * diffm); float scale = 1.0f - 0.12f * diffm; @@ -987,7 +956,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter try { ArrayList uris = new ArrayList<>(); File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null); - File dir = new File (sdCard.getAbsolutePath() + "/logs"); + File dir = new File(sdCard.getAbsolutePath() + "/logs"); File[] files = dir.listFiles(); for (File file : files) { uris.add(Uri.fromFile(file)); @@ -997,7 +966,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter return; } Intent i = new Intent(Intent.ACTION_SEND_MULTIPLE); - i.setType("message/rfc822") ; + i.setType("message/rfc822"); i.putExtra(Intent.EXTRA_EMAIL, new String[]{BuildVars.SEND_LOGS_EMAIL}); i.putExtra(Intent.EXTRA_SUBJECT, "last logs"); i.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); @@ -1024,7 +993,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter return i == textSizeRow || i == enableAnimationsRow || i == notificationRow || i == backgroundRow || i == numberRow || i == askQuestionRow || i == sendLogsRow || i == sendByEnterRow || i == privacyRow || i == wifiDownloadRow || i == mobileDownloadRow || i == clearLogsRow || i == roamingDownloadRow || i == languageRow || i == usernameRow || - i == switchBackendButtonRow || i == telegramFaqRow || i == contactsSortRow || i == contactsReimportRow || i == saveToGalleryRow; + i == switchBackendButtonRow || i == telegramFaqRow || i == contactsSortRow || i == contactsReimportRow || i == saveToGalleryRow || + i == stickersRow; } @Override @@ -1104,6 +1074,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter textCell.setText(LocaleController.getString("TelegramFAQ", R.string.TelegramFaq), true); } else if (i == contactsReimportRow) { textCell.setText(LocaleController.getString("ImportContacts", R.string.ImportContacts), true); + } else if (i == stickersRow) { + textCell.setText(LocaleController.getString("Stickers", R.string.Stickers), true); } } else if (type == 3) { if (view == null) { @@ -1151,7 +1123,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter TextDetailSettingsCell textCell = (TextDetailSettingsCell) view; if (i == mobileDownloadRow || i == wifiDownloadRow || i == roamingDownloadRow) { - int mask = 0; + int mask; String value; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); if (i == mobileDownloadRow) { @@ -1217,11 +1189,12 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter public int getItemViewType(int i) { if (i == emptyRow || i == overscrollRow) { return 0; - } if (i == settingsSectionRow || i == supportSectionRow || i == messagesSectionRow || i == mediaDownloadSection || i == contactsSectionRow) { + } + if (i == settingsSectionRow || i == supportSectionRow || i == messagesSectionRow || i == mediaDownloadSection || i == contactsSectionRow) { return 1; } else if (i == enableAnimationsRow || i == sendByEnterRow || i == saveToGalleryRow) { return 3; - } else if (i == notificationRow || i == backgroundRow || i == askQuestionRow || i == sendLogsRow || i == privacyRow || i == clearLogsRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsReimportRow || i == textSizeRow || i == languageRow || i == contactsSortRow) { + } else if (i == notificationRow || i == backgroundRow || i == askQuestionRow || i == sendLogsRow || i == privacyRow || i == clearLogsRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsReimportRow || i == textSizeRow || i == languageRow || i == contactsSortRow || i == stickersRow) { return 2; } else if (i == versionRow) { return 5; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java new file mode 100644 index 000000000..ce76b2d02 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java @@ -0,0 +1,316 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2014. + */ + +package org.telegram.ui; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Build; +import android.os.Message; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.FrameLayout; +import android.widget.ListView; +import android.widget.Toast; + +import org.telegram.android.LocaleController; +import org.telegram.android.MessagesController; +import org.telegram.android.NotificationCenter; +import org.telegram.android.query.StickersQuery; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; +import org.telegram.messenger.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Adapters.BaseFragmentAdapter; +import org.telegram.ui.Cells.StickerSetCell; +import org.telegram.ui.Cells.TextInfoPrivacyCell; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.StickersAlert; +import org.telegram.ui.Components.URLSpanNoUnderline; + +import java.util.ArrayList; +import java.util.Locale; + +public class StickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + + private ListAdapter listAdapter; + + private int stickersStartRow; + private int stickersEndRow; + private int stickersInfoRow; + private int rowCount; + + @Override + public boolean onFragmentCreate() { + super.onFragmentCreate(); + StickersQuery.checkStickers(); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.stickersDidLoaded); + updateRows(); + return true; + } + + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.stickersDidLoaded); + } + + @Override + public View createView(Context context, LayoutInflater inflater) { + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setAllowOverlayTitle(true); + actionBar.setTitle(LocaleController.getString("Stickers", R.string.Stickers)); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + + listAdapter = new ListAdapter(context); + + fragmentView = new FrameLayout(context); + FrameLayout frameLayout = (FrameLayout) fragmentView; + frameLayout.setBackgroundColor(0xfff0f0f0); + + ListView listView = new ListView(context); + listView.setDivider(null); + listView.setDividerHeight(0); + listView.setVerticalScrollBarEnabled(false); + listView.setDrawSelectorOnTop(true); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + listView.setAdapter(listAdapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, final int i, long l) { + if (i >= stickersStartRow && i < stickersEndRow && getParentActivity() != null) { + final TLRPC.TL_stickerSet stickerSet = StickersQuery.getStickerSets().get(i); + ArrayList stickers = StickersQuery.getStickersForSet(stickerSet.id); + if (stickers == null) { + return; + } + StickersAlert alert = new StickersAlert(getParentActivity(), stickerSet, stickers); + alert.setButton(AlertDialog.BUTTON_NEGATIVE, LocaleController.getString("Close", R.string.Close), (Message) null); + if (stickerSet.id != -1) { + alert.setButton(AlertDialog.BUTTON_NEUTRAL, LocaleController.getString("StickersRemove", R.string.StickersRemove), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + StickersQuery.removeStickersSet(getParentActivity(), stickerSet); + } + }); + } + setVisibleDialog(alert); + alert.show(); + } + } + }); + + return fragmentView; + } + + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.stickersDidLoaded) { + updateRows(); + } + } + + private void updateRows() { + rowCount = 0; + ArrayList stickerSets = StickersQuery.getStickerSets(); + if (!stickerSets.isEmpty()) { + stickersStartRow = 0; + stickersEndRow = stickerSets.size(); + rowCount += stickerSets.size(); + } else { + stickersStartRow = -1; + stickersEndRow = -1; + } + stickersInfoRow = rowCount++; + if (listAdapter != null) { + listAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onResume() { + super.onResume(); + if (listAdapter != null) { + listAdapter.notifyDataSetChanged(); + } + } + + private class ListAdapter extends BaseFragmentAdapter { + private Context mContext; + + public ListAdapter(Context context) { + mContext = context; + } + + @Override + public boolean areAllItemsEnabled() { + return false; + } + + @Override + public boolean isEnabled(int i) { + return i >= stickersStartRow && i < stickersEndRow; + } + + @Override + public int getCount() { + return rowCount; + } + + @Override + public Object getItem(int i) { + return null; + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + int type = getItemViewType(i); + if (type == 0) { + if (view == null) { + view = new StickerSetCell(mContext); + view.setBackgroundColor(0xffffffff); + ((StickerSetCell) view).setOnOptionsClick(new View.OnClickListener() { + @Override + public void onClick(View v) { + StickerSetCell cell = (StickerSetCell) v.getParent(); + final TLRPC.TL_stickerSet stickerSet = cell.getStickersSet(); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + CharSequence[] items; + if (stickerSet.id == -1) { + builder.setTitle(LocaleController.getString("GeniusStickerPackName", R.string.GeniusStickerPackName)); + items = new CharSequence[]{ + StickersQuery.getHideMainStickersPack() ? LocaleController.getString("StickersShow", R.string.StickersShow) : LocaleController.getString("StickersHide", R.string.StickersHide) + }; + } else { + builder.setTitle(stickerSet.title); + items = new CharSequence[]{ + LocaleController.getString("StickersRemove", R.string.StickersRemove), + LocaleController.getString("StickersShare", R.string.StickersShare), + LocaleController.getString("StickersCopy", R.string.StickersCopy), + }; + } + builder.setItems(items, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == 0) { + if (stickerSet.id == -1) { + StickersQuery.setHideMainStickersPack(!StickersQuery.getHideMainStickersPack()); + listAdapter.notifyDataSetChanged(); + StickersQuery.loadStickers(true, false); + } else { + StickersQuery.removeStickersSet(getParentActivity(), stickerSet); + } + } else if (which == 1) { + try { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + intent.putExtra(Intent.EXTRA_TEXT, String.format(Locale.US, "https://telegram.me/addstickers/%s", stickerSet.short_name)); + getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("StickersShare", R.string.StickersShare)), 500); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } else if (which == 2) { + try { + if (Build.VERSION.SDK_INT < 11) { + android.text.ClipboardManager clipboard = (android.text.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setText(String.format(Locale.US, "https://telegram.me/addstickers/%s", stickerSet.short_name)); + } else { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText("label", String.format(Locale.US, "https://telegram.me/addstickers/%s", stickerSet.short_name)); + clipboard.setPrimaryClip(clip); + } + Toast.makeText(getParentActivity(), LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } + }); + //builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + } + }); + } + ArrayList arrayList = StickersQuery.getStickerSets(); + ((StickerSetCell) view).setStickersSet(arrayList.get(i), i != arrayList.size() - 1); + } else if (type == 1) { + if (view == null) { + view = new TextInfoPrivacyCell(mContext); + String text = LocaleController.getString("StickersInfo", R.string.StickersInfo); + String botName = "@stickers"; + int index = text.indexOf(botName); + if (index != -1) { + try { + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(text); + URLSpanNoUnderline spanNoUnderline = new URLSpanNoUnderline("@stickers") { + @Override + public void onClick(View widget) { + MessagesController.openByUserName("stickers", StickersActivity.this, 1); + } + }; + stringBuilder.setSpan(spanNoUnderline, index, index + botName.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + ((TextInfoPrivacyCell) view).setText(stringBuilder); + } catch (Exception e) { + FileLog.e("tmessages", e); + ((TextInfoPrivacyCell) view).setText(text); + } + } else { + ((TextInfoPrivacyCell) view).setText(text); + } + view.setBackgroundResource(R.drawable.greydivider_bottom); + } + } + return view; + } + + @Override + public int getItemViewType(int i) { + if (i >= stickersStartRow && i < stickersEndRow) { + return 0; + } else if (i == stickersInfoRow) { + return 1; + } + return 0; + } + + @Override + public int getViewTypeCount() { + return 2; + } + + @Override + public boolean isEmpty() { + return false; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java index b9c8aeb5f..079bf6926 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java @@ -9,6 +9,7 @@ package org.telegram.ui; import android.app.AlertDialog; +import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; @@ -314,7 +315,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific presentFragment(fragment); } }); - AlertDialog dialog = showAlertDialog(builder); + Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); @@ -355,7 +356,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } } } @@ -422,7 +423,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showAlertDialog(builder); + showDialog(builder.create()); } } }); @@ -696,7 +697,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setTitle(title); builder.setMessage(text); - showAlertDialog(builder); + showDialog(builder.create()); } private void setNewPassword(final boolean clear) { @@ -707,6 +708,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific if (waitingForEmail && currentPassword instanceof TLRPC.TL_account_noPassword) { req.new_settings.flags = 2; req.new_settings.email = ""; + req.current_password_hash = new byte[0]; } else { req.new_settings.flags = 3; req.new_settings.hint = ""; @@ -766,7 +768,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific }); builder.setMessage(LocaleController.getString("YourPasswordSuccessText", R.string.YourPasswordSuccessText)); builder.setTitle(LocaleController.getString("YourPasswordSuccess", R.string.YourPasswordSuccess)); - AlertDialog dialog = showAlertDialog(builder); + Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); @@ -784,7 +786,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific }); builder.setMessage(LocaleController.getString("YourEmailAlmostThereText", R.string.YourEmailAlmostThereText)); builder.setTitle(LocaleController.getString("YourEmailAlmostThere", R.string.YourEmailAlmostThere)); - AlertDialog dialog = showAlertDialog(builder); + Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); @@ -937,7 +939,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific }); builder.setMessage(LocaleController.getString("PasswordReset", R.string.PasswordReset)); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - AlertDialog dialog = showAlertDialog(builder); + Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java index 1c794ab99..37fa05bf4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java @@ -47,7 +47,6 @@ import org.telegram.android.NotificationCenter; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; -import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; @@ -105,7 +104,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur private Runnable progressRunnable = new Runnable() { @Override public void run() { - boolean playerCheck = false; + boolean playerCheck; while (true) { synchronized (sync) { @@ -491,7 +490,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur long duration = (long)Math.ceil(videoDuration); int minutes = (int)(duration / 1000 / 60); int seconds = (int) Math.ceil(duration / 1000) - minutes * 60; - String videoTimeSize = String.format("%d:%02d, %s", minutes, seconds, Utilities.formatFileSize(originalSize)); + String videoTimeSize = String.format("%d:%02d, %s", minutes, seconds, AndroidUtilities.formatFileSize(originalSize)); originalSizeTextView.setText(String.format("%s, %s", videoDimension, videoTimeSize)); } @@ -501,8 +500,8 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur } esimatedDuration = (long)Math.ceil((videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress()) * videoDuration); - int width = 0; - int height = 0; + int width; + int height; if (compressVideo.getVisibility() == View.GONE || compressVideo.getVisibility() == View.VISIBLE && !compressVideo.isChecked()) { width = rotationValue == 90 || rotationValue == 270 ? originalHeight : originalWidth; @@ -528,7 +527,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur String videoDimension = String.format("%dx%d", width, height); int minutes = (int)(esimatedDuration / 1000 / 60); int seconds = (int) Math.ceil(esimatedDuration / 1000) - minutes * 60; - String videoTimeSize = String.format("%d:%02d, ~%s", minutes, seconds, Utilities.formatFileSize(estimatedSize)); + String videoTimeSize = String.format("%d:%02d, ~%s", minutes, seconds, AndroidUtilities.formatFileSize(estimatedSize)); editedSizeTextView.setText(String.format("%s, %s", videoDimension, videoTimeSize)); } @@ -536,15 +535,15 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur if (fragmentView == null || getParentActivity() == null) { return; } - int viewHeight = 0; + int viewHeight; if (AndroidUtilities.isTablet()) { viewHeight = AndroidUtilities.dp(472); } else { viewHeight = AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - AndroidUtilities.getCurrentActionBarHeight(); } - int width = 0; - int height = 0; + int width; + int height; if (AndroidUtilities.isTablet()) { width = AndroidUtilities.dp(490); height = viewHeight - AndroidUtilities.dp(276 + (compressVideo.getVisibility() == View.VISIBLE ? 20 : 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java index ab3380f21..1689a0e62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java @@ -14,24 +14,26 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Point; -import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; +import android.view.Gravity; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.AdapterView; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; import org.telegram.android.AndroidUtilities; import org.telegram.android.ImageLoader; import org.telegram.android.LocaleController; +import org.telegram.android.support.widget.LinearLayoutManager; +import org.telegram.android.support.widget.RecyclerView; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; @@ -42,13 +44,13 @@ import org.telegram.android.MessagesStorage; import org.telegram.android.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.RPCRequest; -import org.telegram.messenger.Utilities; -import org.telegram.ui.Adapters.BaseFragmentAdapter; + import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; -import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Cells.WallpaperCell; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Components.HorizontalListView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RecyclerListView; import java.io.File; import java.io.FileOutputStream; @@ -57,7 +59,6 @@ import java.util.HashMap; public class WallpapersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { - private HorizontalListView listView; private ListAdapter listAdapter; private ImageView backgroundImage; private ProgressBar progressBar; @@ -126,7 +127,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent File f = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); File toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper.jpg"); try { - done = Utilities.copyFile(f, toFile); + done = AndroidUtilities.copyFile(f, toFile); } catch (Exception e) { done = false; FileLog.e("tmessages", e); @@ -157,17 +158,40 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent ActionBarMenu menu = actionBar.createMenu(); doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); - fragmentView = inflater.inflate(R.layout.settings_wallpapers_layout, null, false); - listAdapter = new ListAdapter(context); + FrameLayout frameLayout = new FrameLayout(context); + fragmentView = frameLayout; - progressBar = (ProgressBar) fragmentView.findViewById(R.id.action_progress); - backgroundImage = (ImageView) fragmentView.findViewById(R.id.background_image); - listView = (HorizontalListView) fragmentView.findViewById(R.id.listView); - listView.setAdapter(listAdapter); - listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + backgroundImage = new ImageView(context); + backgroundImage.setScaleType(ImageView.ScaleType.CENTER_CROP); + frameLayout.addView(backgroundImage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + backgroundImage.setOnTouchListener(new View.OnTouchListener() { @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { - if (i == 0) { + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); + + progressBar = new ProgressBar(context); + progressBar.setPadding(AndroidUtilities.dp(6), AndroidUtilities.dp(6), AndroidUtilities.dp(6), AndroidUtilities.dp(6)); + frameLayout.addView(progressBar, LayoutHelper.createFrame(60, 60, Gravity.CENTER, 0, 0, 0, 52)); + + RecyclerListView listView = new RecyclerListView(context); + listView.setClipToPadding(false); + listView.setPadding(AndroidUtilities.dp(40), 0, AndroidUtilities.dp(40), 0); + LinearLayoutManager layoutManager = new LinearLayoutManager(context); + layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + listView.setLayoutManager(layoutManager); + listView.setClipToPadding(false); + listView.setDisallowInterceptTouchEvents(true); + if (Build.VERSION.SDK_INT >= 9) { + listView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); + } + listView.setAdapter(listAdapter = new ListAdapter(context)); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 102, Gravity.LEFT | Gravity.BOTTOM)); + listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { + @Override + public void onItemClick(View view, int position) { + if (position == 0) { if (getParentActivity() == null) { return; } @@ -181,7 +205,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent try { if (i == 0) { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - File image = Utilities.generatePicturePath(); + File image = AndroidUtilities.generatePicturePath(); if (image != null) { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image)); currentPicturePath = image.getAbsolutePath(); @@ -197,9 +221,12 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent } } }); - showAlertDialog(builder); + showDialog(builder.create()); } else { - TLRPC.WallPaper wallPaper = wallPapers.get(i - 1); + if (position - 1 < 0 || position - 1 >= wallPapers.size()) { + return; + } + TLRPC.WallPaper wallPaper = wallPapers.get(position - 1); selectedBackground = wallPaper.id; listAdapter.notifyDataSetChanged(); processSelectedBackground(); @@ -216,7 +243,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent public void onActivityResultFragment(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { if (requestCode == 10) { - Utilities.addMediaToGallery(currentPicturePath); + AndroidUtilities.addMediaToGallery(currentPicturePath); FileOutputStream stream = null; try { Point screenSize = AndroidUtilities.getRealScreenSize(); @@ -292,7 +319,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent progressBar.setVisibility(View.VISIBLE); loadingSize = size; selectedColor = 0; - FileLoader.getInstance().loadFile(size, true); + FileLoader.getInstance().loadFile(size, null, true); backgroundImage.setBackgroundColor(0); } else { if (loadingFile != null) { @@ -352,7 +379,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent @Override public void didReceivedNotification(int id, final Object... args) { if (id == NotificationCenter.FileDidFailedLoad) { - String location = (String)args[0]; + String location = (String) args[0]; if (loadingFile != null && loadingFile.equals(location)) { loadingFileObject = null; loadingFile = null; @@ -361,7 +388,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent doneButton.setEnabled(false); } } else if (id == NotificationCenter.FileDidLoaded) { - String location = (String)args[0]; + String location = (String) args[0]; if (loadingFile != null && loadingFile.equals(location)) { backgroundImage.setImageURI(Uri.fromFile(loadingFileObject)); progressBar.setVisibility(View.GONE); @@ -372,38 +399,27 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent loadingSize = null; } } else if (id == NotificationCenter.FileLoadProgressChanged) { - String location = (String)args[0]; + String location = (String) args[0]; if (loadingFile != null && loadingFile.equals(location)) { - Float progress = (Float)args[1]; - progressBar.setProgress((int)(progress * 100)); + Float progress = (Float) args[1]; + progressBar.setProgress((int) (progress * 100)); } } else if (id == NotificationCenter.wallpapersDidLoaded) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - wallPapers = (ArrayList)args[0]; - wallpappersByIds.clear(); - for (TLRPC.WallPaper wallPaper : wallPapers) { - wallpappersByIds.put(wallPaper.id, wallPaper); - } - if (listAdapter != null) { - listAdapter.notifyDataSetChanged(); - } - if (!wallPapers.isEmpty() && backgroundImage != null) { - processSelectedBackground(); - } - loadWallpapers(); - } - }); + wallPapers = (ArrayList) args[0]; + wallpappersByIds.clear(); + for (TLRPC.WallPaper wallPaper : wallPapers) { + wallpappersByIds.put(wallPaper.id, wallPaper); + } + if (listAdapter != null) { + listAdapter.notifyDataSetChanged(); + } + if (!wallPapers.isEmpty() && backgroundImage != null) { + processSelectedBackground(); + } + loadWallpapers(); } } - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - fixLayout(); - } - private void loadWallpapers() { TLRPC.TL_account_getWallPapers req = new TLRPC.TL_account_getWallPapers(); long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { @@ -416,11 +432,11 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent @Override public void run() { wallPapers.clear(); - TLRPC.Vector res = (TLRPC.Vector)response; + TLRPC.Vector res = (TLRPC.Vector) response; wallpappersByIds.clear(); for (Object obj : res.objects) { - wallPapers.add((TLRPC.WallPaper)obj); - wallpappersByIds.put(((TLRPC.WallPaper)obj).id, (TLRPC.WallPaper)obj); + wallPapers.add((TLRPC.WallPaper) obj); + wallpappersByIds.put(((TLRPC.WallPaper) obj).id, (TLRPC.WallPaper) obj); } if (listAdapter != null) { listAdapter.notifyDataSetChanged(); @@ -436,28 +452,6 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid); } - private void fixLayout() { - ViewTreeObserver obs = fragmentView.getViewTreeObserver(); - obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - fragmentView.getViewTreeObserver().removeOnPreDrawListener(this); - if (listAdapter != null) { - listAdapter.notifyDataSetChanged(); - } - if (listView != null) { - listView.post(new Runnable() { - @Override - public void run() { - listView.scrollTo(0); - } - }); - } - return false; - } - }); - } - @Override public void onResume() { super.onResume(); @@ -465,10 +459,17 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent listAdapter.notifyDataSetChanged(); } processSelectedBackground(); - fixLayout(); } - private class ListAdapter extends BaseFragmentAdapter { + private class ListAdapter extends RecyclerView.Adapter { + + private class Holder extends RecyclerView.ViewHolder { + + public Holder(View itemView) { + super(itemView); + } + } + private Context mContext; public ListAdapter(Context context) { @@ -476,109 +477,24 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent } @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int i) { - return true; - } - - @Override - public int getCount() { + public int getItemCount() { return 1 + wallPapers.size(); } - @Override - public Object getItem(int i) { - return null; - } - @Override public long getItemId(int i) { return i; } @Override - public boolean hasStableIds() { - return true; + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + WallpaperCell view = new WallpaperCell(mContext); + return new Holder(view); } @Override - public View getView(int i, View view, ViewGroup viewGroup) { - int type = getItemViewType(i); - if (type == 0) { - if (view == null) { - LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = li.inflate(R.layout.settings_wallpapers_my_row, viewGroup, false); - } - View parentView = view.findViewById(R.id.parent); - ImageView imageView = (ImageView)view.findViewById(R.id.image); - View selection = view.findViewById(R.id.selection); - if (i == 0) { - if (selectedBackground == -1 || selectedColor != 0 || selectedBackground == 1000001) { - imageView.setBackgroundColor(0x5A475866); - } else { - imageView.setBackgroundColor(0x5A000000); - } - imageView.setImageResource(R.drawable.ic_gallery_background); - if (selectedBackground == -1) { - selection.setVisibility(View.VISIBLE); - } else { - selection.setVisibility(View.INVISIBLE); - } - } else { - imageView.setImageBitmap(null); - TLRPC.WallPaper wallPaper = wallPapers.get(i - 1); - imageView.setBackgroundColor(0xff000000 | wallPaper.bg_color); - if (wallPaper.id == selectedBackground) { - selection.setVisibility(View.VISIBLE); - } else { - selection.setVisibility(View.INVISIBLE); - } - } - } else if (type == 1) { - if (view == null) { - LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = li.inflate(R.layout.settings_wallpapers_other_row, viewGroup, false); - } - BackupImageView image = (BackupImageView)view.findViewById(R.id.image); - View selection = view.findViewById(R.id.selection); - TLRPC.WallPaper wallPaper = wallPapers.get(i - 1); - TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(wallPaper.sizes, AndroidUtilities.dp(100)); - if (size != null && size.location != null) { - image.setImage(size.location, "100_100", (Drawable)null); - } - if (wallPaper.id == selectedBackground) { - selection.setVisibility(View.VISIBLE); - } else { - selection.setVisibility(View.INVISIBLE); - } - } - return view; - } - - @Override - public int getItemViewType(int i) { - if (i == 0) { - return 0; - } - TLRPC.WallPaper wallPaper = wallPapers.get(i - 1); - if (wallPaper instanceof TLRPC.TL_wallPaperSolid) { - return 0; - } - return 1; - } - - @Override - public int getViewTypeCount() { - return 2; - } - - @Override - public boolean isEmpty() { - return false; + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) { + ((WallpaperCell) viewHolder.itemView).setWallpaper(i == 0 ? null : wallPapers.get(i - 1), selectedBackground); } } } diff --git a/TMessagesProj/src/main/res/drawable-v21/bar_selector_grey.xml b/TMessagesProj/src/main/res/drawable-v21/bar_selector_grey.xml new file mode 100644 index 000000000..fc4dddc7f --- /dev/null +++ b/TMessagesProj/src/main/res/drawable-v21/bar_selector_grey.xml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/bar_selector_grey.xml b/TMessagesProj/src/main/res/drawable/bar_selector_grey.xml new file mode 100644 index 000000000..f311824b8 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/bar_selector_grey.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/layout/messages_list.xml b/TMessagesProj/src/main/res/layout/messages_list.xml deleted file mode 100644 index 6f6381a86..000000000 --- a/TMessagesProj/src/main/res/layout/messages_list.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TMessagesProj/src/main/res/layout/recycler_view.xml b/TMessagesProj/src/main/res/layout/recycler_view.xml deleted file mode 100644 index 648ce2b19..000000000 --- a/TMessagesProj/src/main/res/layout/recycler_view.xml +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/TMessagesProj/src/main/res/layout/settings_color_dialog_layout.xml b/TMessagesProj/src/main/res/layout/settings_color_dialog_layout.xml deleted file mode 100644 index 981b72c3a..000000000 --- a/TMessagesProj/src/main/res/layout/settings_color_dialog_layout.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - \ No newline at end of file diff --git a/TMessagesProj/src/main/res/layout/settings_wallpapers_layout.xml b/TMessagesProj/src/main/res/layout/settings_wallpapers_layout.xml deleted file mode 100644 index 4f83f96d2..000000000 --- a/TMessagesProj/src/main/res/layout/settings_wallpapers_layout.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/TMessagesProj/src/main/res/layout/settings_wallpapers_my_row.xml b/TMessagesProj/src/main/res/layout/settings_wallpapers_my_row.xml deleted file mode 100644 index d0683c0b1..000000000 --- a/TMessagesProj/src/main/res/layout/settings_wallpapers_my_row.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/TMessagesProj/src/main/res/layout/settings_wallpapers_other_row.xml b/TMessagesProj/src/main/res/layout/settings_wallpapers_other_row.xml deleted file mode 100644 index 882ae732f..000000000 --- a/TMessagesProj/src/main/res/layout/settings_wallpapers_other_row.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/sound_in.wav b/TMessagesProj/src/main/res/raw/sound_in.wav index 262201668ac81a99daae5f71980f1f70dc425e6b..dd59215441841e4dcec313dd867dd9656dd66b7c 100644 GIT binary patch literal 12590 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 XCb*7xX(HJ7!sjBKlF>)-C+PnJO9BK^ literal 12590 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 OrF+C|Xw@(B#{UD_#Z7kr diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 0e70149ad..b3877943f 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -126,6 +126,8 @@ عداد التدمير الذاتي إشعارات الخدمة جاري جلب معلومات الرابط... + فتح في المتصفح + انسخ الرابط %1$s قام بتعيين عداد التدمير الذاتي إلى to %2$s لقد قمت بتعيين التدمير الذاتي إلى %1$s @@ -195,7 +197,7 @@ رابط دعوة هل أنت متأكد من رغبتك في إلغاء رابط الدعوة؟ إذا قمت بذلك، لن يستطيع أحد من استخدامه للدخول للمجموعة. رابط الدعوة السابق لا يعمل الآن. سيتم إنشاء رابط جديد. - إلغاء + إلغاء الرابط إلغاء الرابط نسخ الرابط شارك الرابط @@ -241,6 +243,21 @@ %1$s متاح. لا يوجد حدث خطأ. + + ملصقات + العقول العظيمة + الرسامون مرحب بهم ليصنعوا حزم ملصقات عن طريق مراسلة @stickers .\n\nيمكن إضافة هذه الحزم بالضغط مرتين على الملصق واختيار \"معلومات\" — \"إضافة الملصقات\". + إضافة ملصق + إضافة إلى الملصقات + لا يوجد ملصقات + تم حذف الملصقات + تم إضافة ملصقات جديدة + إخفاء + إظهار + مشاركة + نسخ الرابط + حذف + لا يوجد ملصقات بعد تم تعيين كافة الإشعارات افتراضيا حجم نص الرسائل @@ -517,6 +534,7 @@ تم فتح إلغاء + إغلاق إضافة تعديل إرسال @@ -551,6 +569,7 @@ un1 قام بإخراجك un1 قام بإضافتك un1 عاد إلى المجموعة + لقد عدت إلى المجموعة نسخة تيليجرام الموجودة لديك لا تدعم هذه الرسالة. الرجاء التحديث لأحدث نسخة: http://telegram.org/update صورة مقطع مرئي @@ -713,6 +732,12 @@ %1$d متر %1$d متر %1$d متر + %1$d ملصقات + %1$d ملصق + %1$d ملصق + %1$d ملصقات + %1$d ملصق + %1$d ملصق %1$d رسالة معاد توجيهها الرسالة المعاد توجيهها @@ -780,6 +805,6 @@ h:mm a %1$s الساعة %2$s - تم تحديث تيليجرام نسخة الأندرويد. الجديد في النسخة ٢.٨:\n\n- روابط الدعوة للمجموعات\n- الإشعارات الذكية\n- خيار الملصقات في قائمة الإموجي\n- التعليقات للصور\n- الأماكن في خدمة المواقع\n- وضعية \"مسموع\" في الرسائل الصوتية\n- شرح متطور لحالة الطرف الآخر: يرسل صورة، يسجل مقطع صوتي، إلخ\n- تطوير التحريك والحركات داخل التطبيق ليكون أسهل وأسرع - 516 + تيليجرام نسخة الـ Android تم تحديثه. الجديد في نسخة ٢.٩:\n\n- تنصيب ومشاركة الملصقات كهذه: https://telegram.me/addstickers/Animals\n- إذا كنت رسام، قم بصنع حزمة ملصقات عن طريق مراسلة @stickers .\n\n - استخدم تيليجرام مع أندرويد أوتو. + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index 37451fdb4..a044f7818 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -126,6 +126,8 @@ Selbstzerstörungs-Timer setzen Servicemeldungen Lade Linkvorschau... + Im Browser öffnen + URL kopieren %1$s hat den Selbstzerstörungs-Timer auf %2$s gesetzt Du hast den Selbstzerstörungs-Timer auf %1$s gesetzt @@ -241,6 +243,21 @@ %1$s ist verfügbar. Keiner Es ist ein Fehler aufgetreten. + + Sticker + Große Denker + Künstler können eigene Sticker-Pakete über unseren Sticker Bot (@stickers) einstellen.\n\nNutzer fügen neue Sticker durch doppeltes Antippen (\"Doppelklick\") eines Stickers und dann \"Info\" — \"Sticker hinzufügen\" hinzu. + Sticker hinzufügen + Sticker hinzufügen + Sticker nicht gefunden + Sticker entfernt + Neue Sticker hinzugefügt + Verstecken + Zeigen + Teilen + Link kopieren + Entfernen + Noch keine Sticker Alle Einstellungen für Mitteilungen zurücksetzen Textgröße für Nachrichten @@ -327,11 +344,11 @@ Deaktiviert Deaktiviert Aus - In-Chat Töne + In-Chat-Töne Standard Intelligente Benachrichtigungen Deaktiviert - Höchstens %1$s innerhalb %2$s + Höchstens %1$s innerhalb von %2$s Höchstens Mal innerhalb von @@ -517,6 +534,7 @@ Fertig Öffnen Abbrechen + Schließen Hinzufügen Bearbeiten Senden @@ -551,6 +569,7 @@ un1 hat dich aus der Gruppe entfernt un1 hat dich hinzugefügt un1 ist in die Gruppe zurückgekehrt + Du bist in die Gruppe zurückgekehrt Diese Nachricht wird von deiner Telegram-Version nicht unterstützt. Bitte aktualisiere die App um sie zu sehen: http://telegram.org/update Foto Video @@ -713,6 +732,12 @@ %1$d Meter %1$d Meter %1$d Meter + %1$d Sticker + %1$d Sticker + %1$d Sticker + %1$d Sticker + %1$d Sticker + %1$d Sticker %1$d angehängten Nachrichten Angehängte Nachricht @@ -780,6 +805,6 @@ h:mm a %1$s um %2$s - Telegram für Android wurde aktualisiert. Neu in 2.8:\n\n- Einladungslinks für Gruppenchats\n- Intelligente Benachrichtigungen\n- Sticker Tab im Emojimenü\n- Beschriftungen für Bilder\n- Orte in der Umgebung im Standortmenü\n- \'Angehört\'-Status Sprachnachrichten\n- Erweiterterte \'schreibt gerade\' Status: schickt Bild, nimmt Audio auf, etc.\n- Verbesserter Bildlauf und flüssige Animationen - 516 + Telegram für Android wurde aktualisiert. Neu in Version 2.9:\n\n- Installiere und teile benutzerdefinierte Sticker-Pakete, wie z.B. dieses: https://telegram.me/addstickers/Animals\n- Künstler können eigene Sticker-Pakete über unseren Sticker Bot (@stickers) einstellen.\n\n- Benutze Telegram mit Android Auto (siehe android.com/auto) + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index cc33630f4..02eb45317 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -126,6 +126,8 @@ Establecer autodestrucción Servicio de notificaciones Obteniendo información... + Abrir en el navegador + Copiar URL %1$s activó la autodestrucción en %2$s Activaste la autodestrucción en %1$s @@ -241,6 +243,21 @@ %1$s está disponible. Ninguno Ocurrió un error. + + Stickers + Grandes personajes + Los artistas pueden añadir sus propios packs de stickers usando el bot @stickers.\n\nLos usuarios pueden añadir stickers pulsando y eligiendo \"Añadir stickers\". + Añadir stickers + Añadir a stickers + Stickers no encontrados + Stickers eliminados + Nuevos stickers añadidos + Ocultar + Mostrar + Compartir + Copiar enlace + Quitar + Sin stickers aún Restablecer las notificaciones Tamaño del texto @@ -517,6 +534,7 @@ Hecho Abrir Cancelar + Cerrar Añadir Editar Enviar @@ -551,6 +569,7 @@ un1 te expulsó un1 te añadió un1 volvió al grupo + Volviste al grupo Este mensaje no lo admite tu versión de Telegram. Actualiza la app para verlo: http://telegram.org/update Foto Vídeo @@ -574,7 +593,7 @@ No tienes reproductor de vídeo. Por favor, instala uno para continuar. Por favor, envía un correo electrónico a sms@stel.com y cuéntanos tu problema. No tienes aplicaciones que puedan manejar el tipo de archivo \'%1$s\'. Por favor, instala una para continuar. - Este usuario no tiene Telegram aún. ¿Enviarle una invitación? + Este usuario aún no tiene Telegram. ¿Enviarle una invitación? ¿Quieres hacerlo? ¿Añadir a %1$s al grupo?\n\nNúmero de los últimos mensajes para reenviar: ¿Reenviar mensajes a %1$s? @@ -713,6 +732,12 @@ %1$d metros %1$d metros %1$d metros + %1$d stickers + %1$d sticker + %1$d stickers + %1$d stickers + %1$d stickers + %1$d stickers %1$d mensajes adjuntos Mensaje adjunto @@ -780,6 +805,6 @@ h:mm a %1$s a las %2$s - Telegram para Android ha sido actualizada. Novedades en la versión 2.8:\n\n- Enlaces de invitación para chats grupales\n- Notificaciones inteligentes\n- Pestaña de stickers en el menú de emojis\n- Comentarios en las fotos\n- Lugares y direcciones en las ubicaciones\n- Estado \'escuchado\' para los mensajes de voz\n- Estado \'escribiendo\' avanzado: enviando foto, grabando audio, etc.\n- Deslizamiento y animaciones mejoradas para una experiencia fluiiiiiiiiiiiiiiiiiida - 515 + Telegram para Android fue actualizada. Novedades en la versión 2.9:\n\n- Instala y comparte packs de stickers personalizados como este: https://telegram.me/addstickers/Animals\n- Si eres un artista, crea packs de stickers personalizados usando nuestro bot @stickers.\n\n- Usa Telegram con Android Auto. + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 0b0cd0f1f..2fd334137 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -39,7 +39,7 @@ Connessione… Aggiornamento… Nuova chat segreta - In attesa che %s si colleghi… + Aspettando che %s si colleghi… Chat segreta annullata Scambio delle chiavi di cifratura... %s si è unito alla tua chat segreta. @@ -70,7 +70,7 @@ Liberi %1$s di %2$s Errore sconosciuto Errore durante l\'accesso - Non ci sono ancora file... + Ancora nessun file... La dimensione del file non dovrebbe superare i %1$s Archiviazione non montata Trasferimento USB attivo @@ -99,7 +99,7 @@ Posizione Video File - Non ci sono ancora messaggi… + Ancora nessun messaggio qui… Messaggio inoltrato Da Nessuno recente @@ -114,7 +114,7 @@ Non lasciano traccia sui nostri server Hanno un timer di autodistruzione Non permettono l’inoltro - Sei stato espulso da questo gruppo + Sei stato rimosso da questo gruppo Hai lasciato il gruppo Elimina questo gruppo Elimina questa chat @@ -126,6 +126,8 @@ Timer di autodistruzione Notifiche di servizio Recupero le info del link... + Apri nel Browser + Copia URL %1$s ha impostato il timer di autodistruzione a %2$s Hai impostato il timer di autodistruzione a %1$s @@ -155,11 +157,11 @@ %1$s ha modificato la foto del gruppo %2$s %1$s ha invitato %3$s nel gruppo %2$s %1$s è rientrato nel gruppo %2$s - %1$s ha espulso %3$s dal gruppo %2$s - %1$s ti ha espulso dal gruppo %2$s + %1$s ha rimosso %3$s dal gruppo %2$s + %1$s ti ha rimosso dal gruppo %2$s %1$s ha lasciato il gruppo %2$s %1$s ha iniziato a usare Telegram! - %1$s,\nAbbiamo rilevato un accesso al tuo account da un nuovo dispositivo il %2$s\n\nDispositivo: %3$s\nPosizione: %4$s\n\nSe non sei stato tu, puoi andare su Impostazioni - Privacy e Sicurezza - Sessioni - Termina tutte le sessioni.\n\nSe pensi che qualcuno si sia collegato al tuo account contro il tuo volere, ti raccomandiamo di attivare la verifica in due passaggi nelle impostazioni di Privacy e Sicurezza.\n\nGrazie,\nil team di Telegram + %1$s,\nAbbiamo rilevato un accesso al tuo account da un nuovo dispositivo il %2$s\n\nDispositivo: %3$s\nPosizione: %4$s\n\nSe non sei stato tu, puoi andare su Impostazioni - Privacy e sicurezza - Sessioni - Termina tutte le sessioni.\n\nSe pensi che qualcuno si sia collegato al tuo account contro il tuo volere, ti raccomandiamo di attivare la verifica in due passaggi nelle impostazioni di Privacy e Sicurezza.\n\nGrazie,\nil team di Telegram %1$s ha aggiornato la foto del profilo %1$s si è unito al gruppo %2$s tramite link di invito Rispondi @@ -206,7 +208,7 @@ Aggiungi membro Elimina e lascia il gruppo Notifiche - Espelli dal gruppo + Rimuovi dal gruppo Condividi Aggiungi @@ -241,6 +243,21 @@ %1$s è disponibile. Nessuno Si è verificato un errore. + + Sticker + Grandi menti + Gli artisti sono invitati ad aggiungere i loro pacchetti di sticker usando il nostro bot @stickers.\n\nGli utenti possono aggiungere sticker premendo su di loro e scegliendo \"Aggiungi agli sticker\". + Aggiungi sticker + Aggiungi agli sticker + Sticker non trovati + Sticker rimossi + Nuovi sticker aggiunti + Nascondi + Mostra + Condividi + Copia link + Rimuovi + Ancora nessuno sticker Ripristina tutte le impostazioni di notifica predefinite Dimensione testo messaggi @@ -271,7 +288,7 @@ Solo se silenzioso Sfondo chat Messaggi - Spedisci con Invio + Spedisci con invio Termina le altre sessioni Eventi Un contatto ha iniziato a usare Telegram @@ -388,7 +405,7 @@ Tutte le foto Tutti i video Ancora nessuna foto - Nessun video + Ancora nessun video Scarica prima il file Nessuna foto recente Nessuna GIF recente @@ -517,6 +534,7 @@ Fatto Apri Annulla + Chiudi Aggiungi Modifica Invia @@ -534,23 +552,24 @@ Ti sei unito al gruppo tramite link di invito un1 si è unito al gruppo tramite link di invito - un1 ha espulso un2 + un1 ha rimosso un2 un1 ha lasciato il gruppo un1 ha aggiunto un2 un1 ha rimosso la foto del gruppo un1 ha cambiato la foto del gruppo un1 ha cambiato il nome del gruppo in un2 un1 ha creato il gruppo - Hai espulso un2 + Hai rimosso un2 Hai lasciato il gruppo Hai aggiunto un2 Hai rimosso la foto del gruppo Hai cambiato la foto del gruppo Hai cambiato il nome del gruppo in un2 Hai creato il gruppo - un1 ti ha espulso + un1 ti ha rimosso un1 ti ha aggiunto - un1 è ritentrato nel gruppo + un1 è rientrato nel gruppo + Sei rientrato nel gruppo Questo messaggio non è supportato sulla tua versione di Telegram. Aggiorna l\'applicazione per visualizzarlo: http://telegram.org/update Foto Video @@ -581,12 +600,12 @@ Inviare i messaggi a %1$s? Sei sicuro di volerti disconnettere?\n\nRicorda che puoi usare Telegram su tutti i tuoi device insieme.\n\nRicorda, disconnettersi elimina tutte le Chat Segrete. Terminare tutte le altre sessioni? - Eliminare il gruppo e uscire da esso? - Eliminare questa chat? + Sei sicuro di voler uscire ed eliminare il gruppo? + Sei sicuro di voler eliminare questa chat? Condividere le informazioni del proprio contatto? Bloccare questo contatto? Sbloccare questo contatto? - Eliminare questo contatto? + Sei sicuro di voler eliminare questo contatto? Iniziare una chat segreta? Sei sicuro di volere eliminare questa registrazione? Sei sicuro di volere eliminare la cronologia? @@ -713,6 +732,12 @@ %1$d metri %1$d metri %1$d metri + %1$d sticker + %1$d sticker + %1$d sticker + %1$d sticker + %1$d sticker + %1$d sticker %1$d messaggi inoltrati Messaggio inoltrato @@ -780,6 +805,6 @@ h:mm a %1$s alle %2$s - Telegram per Android si è aggiornato. Nuovo nella versione 2.8:\n\n- Invita nei gruppi tramite link\n- Notifiche intelligenti\n- Pannello degli sticker nella lista emoji\n- Luoghi e direzioni nelle posizioni\n- Stato \'ascoltato\' per i messaggi vocali\n- Stato di scrittura \'avanzato\': inviando una foto, registrando un audio, etc\n- Animazioni e scorrimento migliorati per un\'esperienza rapidissimaaaa - 516 + Telegram per Android è stato aggiornato. Nuovo nella versione 2.9:\n\n- Installa e condividi pacchetti di sticker personalizzati come questo: https://telegram.me/addstickers/Animals\n- Se sei un artista, crea pacchetti di sticker utilizzando il nostro bot @stickers.\n\n- Usa Telegram con Android Auto. + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 8429a7221..e642f9979 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -126,6 +126,8 @@ 자동삭제 타이머 설정 서비스 알림 링크 정보를 가져오는 중... + 브라우져에서 열기 + URL 복사 %1$s님이 자동삭제를 %2$s 후로 설정했습니다 자동삭제를 %1$s 후로 설정했습니다 @@ -241,6 +243,21 @@ %1$s: 사용 가능합니다. 없음 오류가 발생했습니다. + + 스티커 + Great Minds + \@stickers 봇을 통하여 누구든지 스스로 제작한 스티커를 등록 할 수 있습니다.\n\n스티커는 더블탭하여 \"스티커 추가\" 를 통하여 추가할 수 있습니다. + 스티커 추가 + 스티커 추가 + 스티커를 찾을 수 없음 + 스티커 제거됨 + 새로운 스티커가 추가되었습니다. + 숨김 + 보기 + 공유 + 링크 복사 + 삭제 + 스티커가 아직 없음 모든 알림 설정이 초기화되었습니다 채팅 글자 크기 @@ -517,6 +534,7 @@ 완료 열기 취소 + 닫기 추가 편집 보내기 @@ -551,6 +569,7 @@ un1님이 추방했습니다 un1님이 그룹에 초대했습니다 un1 님께서 그룹에 돌아오셨습니다 + 그룹에 돌아오셨습니다. 이 메시지는 사용 중인 텔레그램의 버전이 낮아 지원하지 않습니다. 앱을 업데이트 하세요: http://telegram.org/update 사진 동영상 @@ -713,6 +732,12 @@ %1$d 미터 %1$d 미터 %1$d 미터 + 스티커 %1$d개 + 스티커 %1$d개 + 스티커 %1$d개 + 스티커 %1$d개 + 스티커 %1$d개 + 스티커 %1$d개 %1$d 개의 전달된 메시지 전달된 메시지 @@ -780,6 +805,6 @@ a h:mm %1$s %2$s - 텔레그램 안드로이드가 업데이트 되었습니다. 새로운 버전 2.8:\n\n-그룹방 초대링크 기능\n-스마트 알림\n-이모티콘 스티커탭\n-사진 설명 기능\n-위치에 장소 및 안내 기능\n-음성 메시지 \'청취확인\' 기능\n-\'입력 중\' 확장 : 사진 보내는중, 녹음 중등\n-부드러운 스크롤링 및 애니메이션 향상 - 516 + 텔레그램 안드로이드 버전이 업데이트 되었습니다. 새로운 버전은 2.9 입니다:\n\n - 아래와 같은 커스텀 스티커 설치 및 공유 : https://telegram.me/addstickers/Animals\n - 커스텀 스티커를 신규로 생성하여 등록할 수 있는 @stickers 봇 활용\n\n - Android Auto와 텔레그램 호환 + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index 54ae2cf52..990c87af5 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -126,6 +126,8 @@ Zelfvernietigingstimer instellen Servicemeldingen Link-preview ophalen... + Openen in browser + Link kopiëren %1$s heeft de zelfvernietigingstimer ingesteld op %2$s Je hebt de zelfvernietigingstimer ingesteld op %1$s @@ -241,6 +243,23 @@ %1$s is beschikbaar. Geen Er is een fout opgetreden. + + Stickers + Grote geesten + Ontwerpers kunnen stickerbundels toevoegen via onze bot: @stickers. + +Gebruikers kunnen met een tik stickers toevoegen via \"Toevoegen aan stickers\". + Stickers toevoegen + Toevoegen aan stickers + Stickers niet gevonden + Stickers verwijderd + Nieuwe stickers toegevoegd + Verbergen + Weergeven + Delen + Link kopiëren + Verwijder + Nog geen stickers Meldingen gereset Tekstgrootte berichten @@ -517,6 +536,7 @@ Gereed Openen Annuleren + Sluit Toevoegen Wijzig Stuur @@ -551,6 +571,7 @@ un1 heeft je verwijderd un1 heeft je toegevoegd un1 is terug in de groep + Je keerde terug naar de groep Dit bericht wordt niet ondersteund door jouw versie van Telegram. Werk Telegram bij om dit bericht te bekijken: http://telegram.org/update Foto Video @@ -713,6 +734,12 @@ %1$d meter %1$d meter %1$d meter + %1$d stickers + %1$d sticker + %1$d stickers + %1$d stickers + %1$d stickers + %1$d stickers Bijlage: %1$d berichten Bijlage: 1 bericht @@ -780,6 +807,6 @@ h:mm a %1$s om %2$s - Telegram voor Android is geüpdatet. Nieuw in versie 2.8:\n\n- Uitnodigingslinks voor groepchats\n- Slimme meldingen\n- Stickerstab in emojimenu\n- Onderschriften voor foto\'s\n- Plekken en routebeschrijvingen op locaties\n- \'Beluistered\'-status voor spraakberichten\n- Geadvanceerde \'aan het typen\'-status: verstuurt een foto, audio opnemen, etc.\n- Scrollen en animaties verbeterd voor een soepele ervaring - 516 + Telegram voor Android is geüpdatet. Nieuw in versie 2.9:\n\n- Deel en installeer stickerbundels zoals deze: https://telegram.me/addstickers/Animals\n- Ben je een ontwerper? Maak stickerbundels met onze bot: @stickers.\n\n- Gebruik Telegram met Android Auto. + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index b7b5d2758..ea42ce566 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -126,6 +126,8 @@ Definir timer de autodestruição Notificações de serviço Obtendo informações... + Abrir no Navegador + Copiar URL %1$s estabeleceu o tempo de autodestruição para %2$s Você estabeleceu o tempo de autodestruição para %1$s @@ -241,6 +243,21 @@ %1$s está disponível. Nenhum Ocorreu um erro. + + Stickers + Grandes Mentes + Artistas são bem vindos a adicionar seus próprios pacotes de stickers usando o @stickers bot.\n\nUsuários podem adicionar stickers com um clique sobre eles e então escolher \"Adicionar aos Stickers\". + Adicionar Stickers + Adicionar aos Stickers + Stickers não encontrados + Stickers removidos + Novos stickers adicionados + Esconder + Mostrar + Compartilhar + Copiar link + Remover + Nenhum sticker Restaurar todas as configurações de notificação Tamanho do texto nas mensagens @@ -279,7 +296,7 @@ Idioma Por favor compreenda que o Suporte do Telegram é feito por voluntários. Tentamos responder o mais rápido possível, mas pode demorar um pouco.
]]>Por favor acesse o FAQ do Telegram]]>: temos respostas para algumas questões, assim como dicas importantes à resolução de problemas]]>.
Pergunte a um voluntário - FAQ do Telegram + Perguntas frequentes https://telegram.org/faq Apagar localização? Arquivo de localização incorreto @@ -517,6 +534,7 @@ Concluído Abrir Cancelar + Fechar Adicionar Editar Enviar @@ -551,6 +569,7 @@ un1 removeu você un1 adicionou você un1 retornou ao grupo + Você retornou ao grupo Esta mensagem não é suportada na sua versão do Telegram. Para visualiza-la atualize seu aplicativo em http://telegram.org/update Foto Vídeo @@ -713,6 +732,12 @@ %1$d metros %1$d metros %1$d metros + %1$d stickers + %1$d sticker + %1$d stickers + %1$d stickers + %1$d stickers + %1$d stickers %1$d mensagens encaminhadas Mensagem encaminhada @@ -780,6 +805,6 @@ h:mm a %1$s às %2$s - Telegram para Android atualizado: Novidades na versão 2.8:\n\n- Link de convite para chats em grupo\n- Notificações inteligentes\n- Botão para stickers no menu de emojis\n- Legendas para fotos\n- Lugares e direções nas localizações\n- Status \'ouvido\' para mensagens de voz\n- Status \'escrevendo\' avançado: enviando foto, gravando áudio, etc.\n- Melhorias nas animações de rolagem para uma leeeeeeeve experiência - 516 + Seu Telegram para Android acaba de ser atualizado. Novidades da versão 2.9:\n\n- Instale e compartilhe pacotes de stickers customizados como esse: https://telegram.me/addstickers/Animals\n- Se você é um artista, crie stickers customizados usando o @stickers bot.\n\n- Use Telegram com Android Auto. + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml index 2facbb7ac..06a50d418 100644 --- a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml @@ -126,6 +126,8 @@ Definir timer de autodestruição Notificações de serviço Obtendo informações... + Abrir no Navegador + Copiar URL %1$s estabeleceu o tempo de autodestruição para %2$s Você estabeleceu o tempo de autodestruição para %1$s @@ -241,6 +243,21 @@ %1$s está disponível. Nenhum Ocorreu um erro. + + Stickers + Grandes Mentes + Artistas são bem vindos a adicionar seus próprios pacotes de stickers usando o @stickers bot.\n\nUsuários podem adicionar stickers com um clique sobre eles e então escolher \"Adicionar aos Stickers\". + Adicionar Stickers + Adicionar aos Stickers + Stickers não encontrados + Stickers removidos + Novos stickers adicionados + Esconder + Mostrar + Compartilhar + Copiar link + Remover + Nenhum sticker Restaurar todas as configurações de notificação Tamanho do texto nas mensagens @@ -279,7 +296,7 @@ Idioma Por favor compreenda que o Suporte do Telegram é feito por voluntários. Tentamos responder o mais rápido possível, mas pode demorar um pouco.
]]>Por favor acesse o FAQ do Telegram]]>: temos respostas para algumas questões, assim como dicas importantes à resolução de problemas]]>.
Pergunte a um voluntário - FAQ do Telegram + Perguntas frequentes https://telegram.org/faq Apagar localização? Arquivo de localização incorreto @@ -517,6 +534,7 @@ Concluído Abrir Cancelar + Fechar Adicionar Editar Enviar @@ -551,6 +569,7 @@ un1 removeu você un1 adicionou você un1 retornou ao grupo + Você retornou ao grupo Esta mensagem não é suportada na sua versão do Telegram. Para visualiza-la atualize seu aplicativo em http://telegram.org/update Foto Vídeo @@ -713,6 +732,12 @@ %1$d metros %1$d metros %1$d metros + %1$d stickers + %1$d sticker + %1$d stickers + %1$d stickers + %1$d stickers + %1$d stickers %1$d mensagens encaminhadas Mensagem encaminhada @@ -780,6 +805,6 @@ h:mm a %1$s às %2$s - Telegram para Android atualizado: Novidades na versão 2.8:\n\n- Link de convite para chats em grupo\n- Notificações inteligentes\n- Botão para stickers no menu de emojis\n- Legendas para fotos\n- Lugares e direções nas localizações\n- Status \'ouvido\' para mensagens de voz\n- Status \'escrevendo\' avançado: enviando foto, gravando áudio, etc.\n- Melhorias nas animações de rolagem para uma leeeeeeeve experiência - 516 + Seu Telegram para Android acaba de ser atualizado. Novidades da versão 2.9:\n\n- Instale e compartilhe pacotes de stickers customizados como esse: https://telegram.me/addstickers/Animals\n- Se você é um artista, crie stickers customizados usando o @stickers bot.\n\n- Use Telegram com Android Auto. + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 33423ab8c..85ef4036e 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -126,6 +126,8 @@ Set self-destruct timer Service notifications Getting Link Info... + Open in Browser + Copy URL %1$s set the self-destruct timer to %2$s You set the self-destruct timer to %1$s @@ -241,6 +243,21 @@ %1$s is available. None An error occurred. + + Stickers + Great Minds + Artists are welcome to add their own sticker packs using our @stickers bot.\n\nUsers can add stickers by tapping on them and choosing \"Add to Stickers\". + Add Stickers + Add to Stickers + Stickers not found + Stickers removed + New stickers added + Hide + Show + Share + Copy link + Remove + No stickers yet Reset all notification settings to default Messages Text Size @@ -517,6 +534,7 @@ Done Open Cancel + Close Add Edit Send @@ -551,6 +569,7 @@ un1 removed you un1 added you un1 returned to the group + You returned to the group This message is not supported on your version of Telegram. Update the app to view: http://telegram.org/update Photo Video @@ -713,6 +732,12 @@ %1$d meters %1$d meters %1$d meters + %1$d stickers + %1$d sticker + %1$d stickers + %1$d stickers + %1$d stickers + %1$d stickers %1$d forwarded messages Forwarded message @@ -780,6 +805,6 @@ h:mm a %1$s at %2$s - Telegram for Android has been updated. New in version 2.8:\n\n- Places and directions in locations\n- Smart notifications\n- Invite links for group chats\n- Stickers tab in emoji menu\n- Captions for photos\n- \'Listened\' status for voice messages\n- Advanced \'typing\' status: sending photo, recording audio, etc.\n- Improved scrolling and animations for a smooooooooth experience - 516 + Telegram for Android has been updated. New in version 2.9:\n\n- Install and share custom sticker sets like this one: https://telegram.me/addstickers/Animals\n- If you\'re an artist, create custom sticker sets using our @stickers bot.\n\n- Use Telegram with Android Auto. + 536 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/xml/automotive_app_desc.xml b/TMessagesProj/src/main/res/xml/automotive_app_desc.xml new file mode 100644 index 000000000..b6df3b517 --- /dev/null +++ b/TMessagesProj/src/main/res/xml/automotive_app_desc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file