![]() |
TX Library Help – Version: 00173a, Revision: 175
|
00001 //================================================================================================================= 00002 // TXLib.h - Библиотека Тупого Художника (The Dumb Artist Library, TX Library, TXLib) - (C) Ilya Dedinsky 00003 //================================================================================================================= 00004 // [These sections are for folding control in Code::Blocks] [$Date: 2025-12-31 23:02:50 +0400 $] 00005 // [Best viewed with "Fold all on file open" option enabled] [Best screen/page width = 120 chars] 00006 // 00007 // [If RUSSIAN CHARS below are UNREADABLE, check this file codepage. It should be CP1251, NOT UTF-8 etc.] 00008 //{ [Use RELOAD options in your IDE or editor (CLion / Visual Studio Code / ...), and do NOT use Convert.] 00009 //================================================================================================================= 00101 // $Copyright: (C) Ded (Ilya Dedinsky, http://txlib.ru) <mail@txlib.ru> $ 00102 //----------------------------------------------------------------------------------------------------------------- 00109 //} 00110 //================================================================================================================= 00111 00112 #if !defined (__TXLIB_H_INCLUDED) // <<< THE CODE IS HERE, UNFOLD IT <<< 00113 #define __TXLIB_H_INCLUDED 00114 00115 //----------------------------------------------------------------------------------------------------------------- 00116 //{ Version information and configuration 00117 //----------------------------------------------------------------------------------------------------------------- 00118 00119 //{---------------------------------------------------------------------------------------------------------------- 00141 //}---------------------------------------------------------------------------------------------------------------- 00143 00144 #define _TX_VER _TX_v_FROM_CVS ($VersionInfo: , TXLib.h, 00173a, 175, 2025-12-31 23:02:50 +0400, "Ded (Ilya Dedinsky, http://txlib.ru) <mail@txlib.ru>", $) 00145 #define _TX_VERSION _TX_V_FROM_CVS ($VersionInfo: , TXLib.h, 00173a, 175, 2025-12-31 23:02:50 +0400, "Ded (Ilya Dedinsky, http://txlib.ru) <mail@txlib.ru>", $) 00146 #define _TX_AUTHOR _TX_A_FROM_CVS ($VersionInfo: , TXLib.h, 00173a, 175, 2025-12-31 23:02:50 +0400, "Ded (Ilya Dedinsky, http://txlib.ru) <mail@txlib.ru>", $) 00147 00149 #define _TX_v_FROM_CVS(_1,file,ver,rev,date,auth,_2) ((0x##ver##u << 16) | 0x##rev##u) 00150 #define _TX_V_FROM_CVS(_1,file,ver,rev,date,auth,_2) "TXLib [Ver: " #ver ", Rev: " #rev ", Date: " #date "]" 00151 #define _TX_A_FROM_CVS(_1,file,ver,rev,date,auth,_2) "Copyright (C) " auth 00152 00153 00155 //{---------------------------------------------------------------------------------------------------------------- 00162 //}---------------------------------------------------------------------------------------------------------------- 00163 00164 #if !defined (_TX_MODULE) 00165 #define _TX_MODULE "TXLib" 00166 #endif 00167 00168 //{---------------------------------------------------------------------------------------------------------------- 00172 //}---------------------------------------------------------------------------------------------------------------- 00173 00174 #define __TX_COMPILER__ "Unknown C++, std=" TX_QUOTE (__cplusplus) 00175 00176 #if defined (__GNUC__) 00177 00178 #define _GCC_VER ( __GNUC__*100 + __GNUC_MINOR__*10 + __GNUC_PATCHLEVEL__ ) 00179 00180 #undef __TX_COMPILER__ 00181 #define __TX_COMPILER__ "GNU g++ " TX_QUOTE (__GNUC__) "." \ 00182 TX_QUOTE (__GNUC_MINOR__) "." \ 00183 TX_QUOTE (__GNUC_PATCHLEVEL__) \ 00184 ", std=" TX_QUOTE (__cplusplus) 00185 #elif defined (_MSC_VER) 00186 00187 #undef __TX_COMPILER__ 00188 #define __TX_COMPILER__ "MSVS " TX_QUOTE (_MSC_VER) \ 00189 ", std=" TX_QUOTE (__cplusplus) 00190 #endif 00191 00192 #if defined (__clang__) || defined (__clang_major__) 00193 00194 #define _CLANG_VER ( __clang_major__*100 + __clang_minor__*10 + __clang_patchlevel__ ) 00195 00196 #undef __TX_COMPILER__ 00197 #define __TX_COMPILER__ "Clang " TX_QUOTE (__clang_major__) "." \ 00198 TX_QUOTE (__clang_minor__) "." \ 00199 TX_QUOTE (__clang_patchlevel__) \ 00200 ", std=" TX_QUOTE (__cplusplus) 00201 #endif 00202 00203 //----------------------------------------------------------------------------------------------------------------- 00204 00206 00207 #define TX_QUOTE(sym) _TX_QUOTE (sym) 00208 #define _TX_QUOTE(sym) #sym 00209 00210 #define TX_JOIN(sym1, sym2) _TX_JOIN (sym1, sym2) 00211 #define _TX_JOIN(sym1, sym2) sym1 ## sym2 00212 00214 00215 #if (__cplusplus >= 201103L) || defined (_MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 00216 00217 #define _TX_CPP11 1 00218 #endif 00219 00220 #if (__cplusplus >= 201103L) || defined (_MSC_VER) && (_MSC_VER >= 1900) // MSVC 2015 00221 00222 #define _TX_CPP11_MSVC15 1 00223 #endif 00224 00225 //{---------------------------------------------------------------------------------------------------------------- 00229 //}---------------------------------------------------------------------------------------------------------------- 00230 00231 #if !defined (NDEBUG) && defined (_DEBUG) 00232 #define _TX_BUILDMODE "DEBUG" 00233 00234 #elif !defined (NDEBUG) && !defined (_DEBUG) 00235 #define _TX_BUILDMODE "Debug" 00236 00237 #elif defined (NDEBUG) 00238 #define _TX_BUILDMODE "Release" 00239 #endif 00240 00241 //{---------------------------------------------------------------------------------------------------------------- 00245 //}---------------------------------------------------------------------------------------------------------------- 00246 00247 #define __TX_FILELINE__ __FILE__ ":" TX_QUOTE (__LINE__) 00248 00249 //{---------------------------------------------------------------------------------------------------------------- 00257 //}---------------------------------------------------------------------------------------------------------------- 00258 00259 #if defined (__GNUC__) || defined (__clang__) || defined (__clang_major__) 00260 #define __TX_FUNCTION__ __PRETTY_FUNCTION__ 00261 00262 #elif defined (__FUNCSIG__) 00263 #define __TX_FUNCTION__ __FUNCSIG__ 00264 00265 #elif defined (__FUNCTION__) 00266 #define __TX_FUNCTION__ __FUNCTION__ 00267 00268 #elif defined (__cplusplus) && (__cplusplus >= 199711L) 00269 #define __TX_FUNCTION__ __func__ 00270 00271 #elif defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) 00272 #define __TX_FUNCTION__ __func__ 00273 00274 #elif defined (__PYTHON__) 00275 #error No Python. No. Using parseltongue languages can lead you to Slytherin. 00276 00277 #else 00278 #define __TX_FUNCTION__ "(" __TX_FILELINE__ ")" 00279 00280 #endif 00281 00282 #if !defined (__func__) && defined (__FUNCTION__) 00283 #define __func__ __FUNCTION__ 00284 #endif 00285 00286 //} 00287 //----------------------------------------------------------------------------------------------------------------- 00288 00289 //----------------------------------------------------------------------------------------------------------------- 00290 //{ Compiler- and platform-specific 00292 //----------------------------------------------------------------------------------------------------------------- 00294 00295 #if (defined (_GCC_VER) && (_GCC_VER < 472) && !defined (_CLANG_VER) || \ 00296 defined (_CLANG_VER) && (_CLANG_VER < 900) || \ 00297 defined (_MSC_VER) && (_MSC_VER < 1600)) // Minimum requirements are now GCC 4.7.2 or MSVC 10.0 (2010) 00298 00299 #ifdef __GNUC__ 00300 #error 00301 #error --------------------------------------------------------------------------------------- 00302 #endif 00303 #error TXLib.h: This version works only with GCC >= 4.7.2 or MS Visual Studio >= 2010, sorry. 00304 #error 00305 #error Please use TXLib.h previous stable version/revision OR upgrade/install proper compiler. 00306 #error --------------------------------------------------------------------------------------- 00307 #error 00308 00309 #endif 00310 00311 //----------------------------------------------------------------------------------------------------------------- 00312 00313 #if defined (_GCC_VER) && (_GCC_VER >= 492) 00314 #if defined (TX_USE_SPEAK) && !__has_include (<SAPI.h>) 00315 00316 #ifdef __GNUC__ 00317 #error 00318 #error --------------------------------------------------------------------------------------- 00319 #endif 00320 #error You have defined TX_USE_SPEAK, but your compiler do NOT have the library <SAPI.h>. 00321 #error 00322 #error Please use compiler library set with SAPI.h included. SAPI is Microsoft Speech API 00323 #error necessary for txSpeak() to work. 00324 #error --------------------------------------------------------------------------------------- 00325 #error 00326 00327 #endif 00328 #endif 00329 00330 //----------------------------------------------------------------------------------------------------------------- 00331 00332 #if !defined (WIN32) && !defined (__WIN32__) && !defined(_WIN32) && !defined(_WIN32_WINNT) && !defined (__CYGWIN__) 00333 00334 #ifdef __GNUC__ 00335 #error 00336 #error --------------------------------------------------------------------------------------- 00337 #endif 00338 #error TXLib.h: Windows (MSVC/Win32 or GCC/MinGW or Cygwin) is the only supported OS, sorry. 00339 #error 00340 #error In Linux or MacOS, you should write your own TXLib and share it with your friends, or use wine. 00341 #error --------------------------------------------------------------------------------------- 00342 #error 00343 00344 #endif 00345 00346 //----------------------------------------------------------------------------------------------------------------- 00347 00348 #if defined (__STRICT_ANSI__) && (_GCC_VER < 1120) // Try to extend strict ANSI rules 00349 00350 #undef __STRICT_ANSI__ 00351 #define __STRICT_ANSI__UNDEFINED 00352 00353 #if defined (_STRING_H_) || defined (_INC_STRING) || defined (_STDIO_H_) || defined (_INC_STDIO) 00354 00355 #ifdef __GNUC__ 00356 #error 00357 #error --------------------------------------------------------------------------------------- 00358 #endif 00359 #error TXLib.h: Should include "TXLib.h" BEFORE <string.h>, <iostream> or <stdio.h> in Strict ANSI mode. 00360 #error 00361 #error REARRANGE your #include directives, or DISABLE ANSI-compliancy by #undef __STRICT_ANSI__. 00362 #error --------------------------------------------------------------------------------------- 00363 #error 00364 00365 #endif 00366 00367 #endif 00368 00369 //----------------------------------------------------------------------------------------------------------------- 00370 00371 #if !defined (__cplusplus) 00372 00373 #ifdef __GNUC__ 00374 #error 00375 #error --------------------------------------------------------------------------------------- 00376 #endif 00377 #error TXLib.h: Must use C++ to compile TXLib.h. Now you are using C only. 00378 #error 00379 #error CHECK source file EXTENSION. Maybe it is ".C". It must be ".CPP". 00380 #error If your file is named, for example, "Untitled.C", go to menu [File], 00381 #error then [Save As] and rename it to "Untitled.CPP". Please do NOT use spaces. 00382 #error --------------------------------------------------------------------------------------- 00383 #error 00384 00385 #endif 00386 00387 //----------------------------------------------------------------------------------------------------------------- 00388 00389 #if defined (UNICODE) || defined (_UNICODE) 00390 00391 #ifdef __GNUC__ 00392 #warning TXLib.h: Disabling the UNICODE 00393 #endif 00394 00395 #undef UNICODE // Burn Unicode, burn 00396 #undef _UNICODE 00397 00398 #if defined (_WINDOWS_H) || defined (_INC_WINDOWS) || defined (_WINDOWS_) || defined (__WINDOWS__) 00399 00400 #ifdef __GNUC__ 00401 #error 00402 #error --------------------------------------------------------------------------------------- 00403 #endif 00404 #error TXLib.h: Should include "TXLib.h" BEFORE or INSTEAD of <Windows.h> in UNICODE mode. 00405 #error 00406 #error REARRANGE your #include directives, or DISABLE the UNICODE mode by #undef UNICODE/_UNICODE. 00407 #error --------------------------------------------------------------------------------------- 00408 #error 00409 00410 #endif 00411 00412 #endif 00413 00414 //----------------------------------------------------------------------------------------------------------------- 00415 00416 #if defined (__GNUC__) 00417 00418 #pragma GCC diagnostic ignored "-Wpragmas" 00419 #pragma GCC diagnostic ignored "-Wunknown-pragmas" 00420 #pragma GCC diagnostic ignored "-Wunknown-warning-option" 00421 00422 #pragma GCC diagnostic warning "-Wall" 00423 #pragma GCC diagnostic warning "-Weffc++" 00424 #pragma GCC diagnostic warning "-Wextra" 00425 00426 #pragma GCC diagnostic warning "-Waggressive-loop-optimizations" 00427 #pragma GCC diagnostic warning "-Walloc-zero" 00428 #pragma GCC diagnostic warning "-Walloca" 00429 #pragma GCC diagnostic warning "-Walloca-larger-than=8192" 00430 #pragma GCC diagnostic warning "-Warray-bounds" 00431 #pragma GCC diagnostic warning "-Wcast-align" 00432 #pragma GCC diagnostic warning "-Wcast-qual" 00433 #pragma GCC diagnostic warning "-Wchar-subscripts" 00434 #pragma GCC diagnostic warning "-Wconditionally-supported" 00435 #pragma GCC diagnostic warning "-Wconversion" 00436 #pragma GCC diagnostic warning "-Wctor-dtor-privacy" 00437 #pragma GCC diagnostic warning "-Wdangling-else" 00438 #pragma GCC diagnostic warning "-Wduplicated-branches" 00439 #pragma GCC diagnostic warning "-Wempty-body" 00440 #pragma GCC diagnostic warning "-Wfloat-equal" 00441 #pragma GCC diagnostic warning "-Wformat-nonliteral" 00442 #pragma GCC diagnostic warning "-Wformat-overflow=2" 00443 #pragma GCC diagnostic warning "-Wformat-security" 00444 #pragma GCC diagnostic warning "-Wformat-signedness" 00445 #pragma GCC diagnostic warning "-Wformat-truncation=2" 00446 #pragma GCC diagnostic warning "-Wformat=2" 00447 #pragma GCC diagnostic warning "-Wlarger-than=8192" 00448 #pragma GCC diagnostic warning "-Wlogical-op" 00449 #pragma GCC diagnostic warning "-Wmismatched-tags" 00450 #pragma GCC diagnostic warning "-Wmissing-declarations" 00451 #pragma GCC diagnostic warning "-Wnarrowing" 00452 #pragma GCC diagnostic warning "-Wnon-virtual-dtor" 00453 #pragma GCC diagnostic warning "-Wnonnull" 00454 #pragma GCC diagnostic warning "-Wopenmp-simd" 00455 #pragma GCC diagnostic warning "-Woverloaded-virtual" 00456 #pragma GCC diagnostic warning "-Wpacked" 00457 #pragma GCC diagnostic warning "-Wpointer-arith" 00458 #pragma GCC diagnostic warning "-Wredundant-decls" 00459 #pragma GCC diagnostic warning "-Wredundant-tags" 00460 #pragma GCC diagnostic warning "-Wrestrict" 00461 #pragma GCC diagnostic warning "-Wshadow" 00462 #pragma GCC diagnostic warning "-Wsign-promo" 00463 #pragma GCC diagnostic warning "-Wstack-usage=8192" 00464 #pragma GCC diagnostic warning "-Wstrict-aliasing" 00465 #pragma GCC diagnostic warning "-Wstrict-null-sentinel" 00466 #pragma GCC diagnostic warning "-Wstrict-overflow=2" 00467 #pragma GCC diagnostic warning "-Wstringop-overflow=4" 00468 #pragma GCC diagnostic warning "-Wsuggest-attribute=noreturn" 00469 #pragma GCC diagnostic warning "-Wsuggest-final-methods" 00470 #pragma GCC diagnostic warning "-Wsuggest-final-types" 00471 #pragma GCC diagnostic warning "-Wsuggest-override" 00472 #pragma GCC diagnostic warning "-Wswitch-default" 00473 #pragma GCC diagnostic warning "-Wswitch-enum" 00474 #pragma GCC diagnostic warning "-Wsync-nand" 00475 #pragma GCC diagnostic warning "-Wundef" 00476 #pragma GCC diagnostic warning "-Wunused" 00477 #pragma GCC diagnostic warning "-Wvarargs" 00478 #pragma GCC diagnostic warning "-Wvla-larger-than=8192" 00479 00480 #pragma GCC diagnostic error "-Wsizeof-array-argument" 00481 00482 #pragma GCC diagnostic ignored "-Waddress" 00483 #pragma GCC diagnostic ignored "-Winline" 00484 #pragma GCC diagnostic ignored "-Wliteral-suffix" 00485 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 00486 #pragma GCC diagnostic ignored "-Wnonnull-compare" 00487 #pragma GCC diagnostic ignored "-Wold-style-cast" 00488 #pragma GCC diagnostic ignored "-Wunreachable-code" 00489 #pragma GCC diagnostic ignored "-Wunused-const-variable" 00490 #pragma GCC diagnostic ignored "-Wunused-function" 00491 #pragma GCC diagnostic ignored "-Wvariadic-macros" 00492 00493 #pragma GCC diagnostic warning "-Wunknown-warning-option" 00494 #pragma GCC diagnostic warning "-Wunknown-pragmas" 00495 #pragma GCC diagnostic warning "-Wpragmas" 00496 00497 //{ These warning settings for TXLib.h only and will be re-enabled at end of file: 00498 00499 #ifndef _CLANG_VER 00500 #pragma GCC push_options 00501 #endif 00502 00503 #pragma GCC diagnostic push 00504 00505 #pragma GCC diagnostic ignored "-Wpragmas" 00506 #pragma GCC diagnostic ignored "-Wunknown-pragmas" 00507 #pragma GCC diagnostic ignored "-Wunknown-warning-option" 00508 00509 #pragma GCC diagnostic ignored "-Waddress" 00510 #pragma GCC diagnostic ignored "-Warray-bounds" 00511 #pragma GCC diagnostic ignored "-Wclobbered" 00512 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 00513 #pragma GCC diagnostic ignored "-Wfloat-equal" 00514 #pragma GCC diagnostic ignored "-Wformat-nonliteral" 00515 #pragma GCC diagnostic ignored "-Wformat-zero-length" 00516 #pragma GCC diagnostic ignored "-Winvalid-source-encoding" 00517 #pragma GCC diagnostic ignored "-Wlarger-than=" 00518 #pragma GCC diagnostic ignored "-Wmisleading-indentation" 00519 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" 00520 #pragma GCC diagnostic ignored "-Wpacked-not-aligned" 00521 #pragma GCC diagnostic ignored "-Wpedantic" 00522 #pragma GCC diagnostic ignored "-Wredundant-decls" 00523 #pragma GCC diagnostic ignored "-Wshadow" 00524 #pragma GCC diagnostic ignored "-Wsign-conversion" 00525 #pragma GCC diagnostic ignored "-Wstrict-aliasing" 00526 #pragma GCC diagnostic ignored "-Wsuggest-override" 00527 #pragma GCC diagnostic ignored "-Wunused-label" // Just for fun in _txCanvas_OnCmdAbout() 00528 #pragma GCC diagnostic ignored "-Wunused-value" 00529 00530 #pragma GCC optimize "no-strict-aliasing" 00531 00532 #pragma GCC diagnostic warning "-Wunknown-warning-option" 00533 #pragma GCC diagnostic warning "-Wunknown-pragmas" 00534 #pragma GCC diagnostic warning "-Wpragmas" 00535 00536 #if defined (__CYGWIN__) && !defined (_TX_TESTING) 00537 #pragma GCC system_header // This is not a fair play, but this is the only way to deal with Cygwin :( 00538 #endif 00539 00540 //} 00541 00542 #define _tx_thread __thread 00543 #define _tx_decltype( value ) __decltype (value) 00544 00545 #define _FORTIFY_SOURCE 2 00546 00547 #ifndef MINGW_HAS_SECURE_API 00548 #define MINGW_HAS_SECURE_API 1 00549 #endif 00550 00551 #if defined (TX_USE_SFML) 00552 #define _GLIBCXX_NDEBUG 00553 #endif 00554 00555 #ifndef _GLIBCXX_NDEBUG // TXLib enables _GLIBCXX_DEBUG by default. When using third-party libraries 00556 #define _GLIBCXX_DEBUG // compiled without _GLIBCXX_DEBUG (SFML, for example), #define _GLIBCXX_NDEBUG 00557 #define _GLIBCXX_DEBUG_PEDANTIC // *before* including TXLib.h. 00558 #endif 00559 00560 #if defined (_WIN64) && !defined (__USE_MINGW_ANSI_STDIO) 00561 #define __USE_MINGW_ANSI_STDIO 1 // Removed in x86 because printf ("%g", double) failure, this always prints 0 00562 #endif 00563 00564 template <typename T> 00565 inline T _txNOP (T value) { return value; } // To suppress performance warnings in assert etc. 00566 00567 #ifndef _CLANG_VER 00568 00569 // From MinGW\include\float.h which is replaced by MinGW\lib\gcc\i686-pc-mingw32\x.x.x\include\float.h 00570 extern "C" __declspec (dllimport) unsigned __cdecl _controlfp (unsigned control, unsigned mask); 00571 extern "C" void __cdecl _fpreset (); 00572 00573 #endif 00574 00575 #endif 00576 00577 //----------------------------------------------------------------------------------------------------------------- 00578 00579 #if defined (__clang__) || defined (__clang_major__) 00580 00581 //{ These warning settings for TXLib.h only and will be re-enabled at end of file: 00582 00583 #pragma clang diagnostic push 00584 00585 #pragma clang diagnostic ignored "-Wcast-align" 00586 #pragma clang diagnostic ignored "-Wfloat-conversion" 00587 #pragma clang diagnostic ignored "-Wmicrosoft-cast" 00588 #pragma clang diagnostic ignored "-Wmissing-braces" 00589 #pragma clang diagnostic ignored "-Wsign-compare" 00590 #pragma clang diagnostic ignored "-Wstring-plus-int" 00591 #pragma clang diagnostic ignored "-Wundef" 00592 #pragma clang diagnostic ignored "-Wundefined-bool-conversion" 00593 #pragma clang diagnostic ignored "-Wunused-function" 00594 #pragma clang diagnostic ignored "-Wvariadic-macros" 00595 00596 //{ CLang-Tidy options 00597 // 00598 // *,-cert-dcl50-cpp,-cert-dcl58-cpp,-cert-err52-cpp,-cert-err58-cpp,-cert-flp30-c,-cert-msc30-c,-cert-msc32-c, 00599 // -cert-msc50-cpp,-cert-msc51-cpp,-clang-analyzer-core.DivideZero,-cppcoreguidelines-avoid-c-arrays, 00600 // -cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-macro-usage, 00601 // -cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-no-malloc, 00602 // -cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic, 00603 // -cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-cstyle-cast,-cppcoreguidelines-pro-type-union-access, 00604 // -cppcoreguidelines-pro-type-vararg,-fuchsia-default-arguments-calls,-fuchsia-default-arguments-declarations, 00605 // -fuchsia-overloaded-operator,-google-build-using-namespace,-google-global-names-in-headers,-google-runtime-int, 00606 // -google-readability-braces-around-statements,-google-readability-casting,-google-readability-namespace-comments, 00607 // -hicpp-avoid-c-arrays,-hicpp-avoid-goto,-hicpp-braces-around-statements,-hicpp-deprecated-headers,-hicpp-no-array-decay, 00608 // -hicpp-signed-bitwise,-hicpp-use-equals-delete,-hicpp-use-nullptr,-hicpp-vararg,-llvm-include-order,-hicpp-no-malloc, 00609 // -llvm-namespace-comment,-misc-non-private-member-variables-in-classes,-modernize-avoid-c-arrays,-modernize-use-auto, 00610 // -modernize-deprecated-headers,-modernize-raw-string-literal,-modernize-use-default-member-init,-hicpp-use-auto, 00611 // -modernize-use-equals-delete,-modernize-use-nullptr,-modernize-use-trailing-return-type,-modernize-use-using, 00612 // -readability-braces-around-statements,-readability-else-after-return,-readability-implicit-bool-conversion, 00613 // -readability-isolate-declaration,-readability-magic-numbers,-readability-named-parameter,-modernize-loop-convert 00614 //} 00615 00616 //} 00617 00618 #endif 00619 00620 //----------------------------------------------------------------------------------------------------------------- 00621 00622 #if defined (_MSC_VER) 00623 00624 #pragma warning (push, 4) // Set maximum warning level. This 'push' is to set the level only. It will NOT be popped. 00625 00626 #pragma warning (disable: 4616) // #pragma warning: warning number 'n' not a valid compiler warning 00627 00628 #pragma warning (disable: 4514) // Unreferenced inline function has been removed 00629 #pragma warning (disable: 4710) // Function not inlined 00630 #pragma warning (disable: 4786) // Identifier was truncated to '255' characters in the debug information 00631 00632 #pragma warning (error: 4715) // Not all control paths return a value 00633 00634 #pragma warning (default: 4616) // #pragma warning: warning number 'n' not a valid compiler warning //-V665 00635 00636 #pragma warning (disable: 26473) // Don't cast between pointer types where the source type and the target type are the same (type.1). 00637 #pragma warning (disable: 26475) // Do not use function style C-casts (es.49). 00638 #pragma warning (disable: 26477) // Use 'nullptr' rather than 0 or NULL (es.47). 00639 #pragma warning (disable: 26481) // Don't use pointer arithmetic. Use span instead (bounds.1). 00640 #pragma warning (disable: 26826) // Don't use C-style variable arguments (f.55). 00641 00642 // These warning settings for TXLib.h only and will be re-enabled at end of file: 00643 00644 #pragma warning (push) 00645 00646 #pragma warning (disable: 4616) // #pragma warning: warning number 'n' not a valid compiler warning 00647 00648 #pragma warning (disable: 4091) // 'typedef': ignored on left of '...' when no variable is declared 00649 #pragma warning (disable: 4124) // Using __fastcall with stack checking is ineffective 00650 #pragma warning (disable: 4127) // Conditional expression is constant 00651 #pragma warning (disable: 4200) // Nonstandard extension used: zero-sized array in struct/union 00652 #pragma warning (disable: 4201) // Nonstandard extension used: nameless struct/union 00653 #pragma warning (disable: 4351) // New behavior: elements of array will be default initialized 00654 #pragma warning (disable: 4480) // Nonstandard extension used: specifying underlying type for enum 'type' 00655 #pragma warning (disable: 4481) // Nonstandard extension used: override specifier 'override' 00656 #pragma warning (disable: 4555) // Result of expression not used 00657 #pragma warning (disable: 4611) // Interaction between '_setjmp' and C++ object destruction is non-portable 00658 #pragma warning (disable: 5045) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified 00659 #pragma warning (disable: 6269) // Possibly incorrect order of operations: dereference ignored 00660 #pragma warning (disable: 6285) // (<non-zero constant>) || (<non-zero constant>) is always a non-zero constant. Did you intend to use bitwize-and operator? 00661 #pragma warning (disable: 6319) // Use of the comma-operator in a tested expression causes the left argument to be ignored when it has no side-effects 00662 #pragma warning (disable: 6326) // Potential comparison of a constant with another constant 00663 #pragma warning (disable: 6553) // The annotation for function 'func' on _Param_(N) does not apply to a value type. 00664 #pragma warning (disable: 26135) // Missing locking annotation 00665 #pragma warning (disable: 26400) // Do not assign the result of an allocation or a function call with an owner<T> return value to a raw pointer, use owner<T> instead (i.11). 00666 #pragma warning (disable: 26401) // Do not delete a raw pointer that is not an owner<T> (i.11). 00667 #pragma warning (disable: 26403) // Reset or explicitly delete an owner<T> pointer 'name' (r.3). 00668 #pragma warning (disable: 26408) // Avoid malloc() and free(), prefer the nothrow version of new with delete (r.10). 00669 #pragma warning (disable: 26409) // Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11). 00670 #pragma warning (disable: 26426) // Global initializer calls a non-constexpr function 'name' (i.22). 00671 #pragma warning (disable: 26429) // Symbol 'name' is never tested for nullness, it can be marked as not_null (f.23). 00672 #pragma warning (disable: 26430) // Symbol 'name' is not tested for nullness on all paths (f.23). 00673 #pragma warning (disable: 26432) // If you define or delete any default operation in the type 'struct 'name'', define or delete them all (c.21). 00674 #pragma warning (disable: 26435) // Function 'name' should specify exactly one of 'virtual', 'override', or 'final' (c.128). 00675 #pragma warning (disable: 26438) // Avoid 'goto' (es.76). 00676 #pragma warning (disable: 26440) // Function 'name' can be declared 'noexcept' (f.6). 00677 #pragma warning (disable: 26446) // Prefer to use gsl::at() instead of unchecked subscript operator (bounds.4). 00678 #pragma warning (disable: 26447) // The function is declared 'noexcept' but calls function 'func' which may throw exceptions (f.6). 00679 #pragma warning (disable: 26448) // Consider using gsl::finally if final action is intended (gsl.util). 00680 #pragma warning (disable: 26451) // Arithmetic overflow: Using operator 'op' on a n-byte value and then casting the result to a m-byte value. Cast the value to the wider type before calling operator 'op' to avoid overflow (io.2). 00681 #pragma warning (disable: 26455) // Default constructor may not throw. Declare it 'noexcept' (f.6). 00682 #pragma warning (disable: 26457) // (void) should not be used to ignore return values, use 'std::ignore =' instead (es.48) 00683 #pragma warning (disable: 26460) // The reference argument 'stream' for function 'name' can be marked as const (con.3). 00684 #pragma warning (disable: 26461) // The pointer argument 'name' for function 'name' can be marked as a pointer to const (con.3). 00685 #pragma warning (disable: 26462) // The value pointed to by 'name' is assigned only once, mark it as a pointer to const (con.4). 00686 #pragma warning (disable: 26482) // Only index into arrays using constant expressions (bounds.2). 00687 #pragma warning (disable: 26483) // Value 'value' is outside the bounds (min, max) of variable 'name'. Only index into arrays using constant expressions that are within bounds of the array (bounds.2). 00688 #pragma warning (disable: 26485) // Expression 'expr': No array to pointer decay (bounds.3). 00689 #pragma warning (disable: 26486) // Don't pass a pointer that may be invalid to a function. Parameter 'n' 'name' in call to 'name' may be invalid (lifetime.3). 00690 #pragma warning (disable: 26487) // Don't return a pointer 'name' that may be invalid (lifetime.4). 00691 #pragma warning (disable: 26488) // Do not dereference a potentially null pointer: 'name'. 'name' was null at line 'n' (lifetime.1). 00692 #pragma warning (disable: 26489) // Don't dereference a pointer that may be invalid: 'name'. 'name' may have been invalidated at line 'n' (lifetime.1). 00693 #pragma warning (disable: 26490) // Don't use reinterpret_cast (type.1). 00694 #pragma warning (disable: 26492) // Don't use const_cast to cast away const or volatile (type.3). 00695 #pragma warning (disable: 26493) // Don't use C-style casts (type.4). 00696 #pragma warning (disable: 26496) // The variable 'name' is assigned only once, mark it as const (con.4). 00697 #pragma warning (disable: 26497) // The function 'name' could be marked constexpr if compile-time evaluation is desired (f.4). 00698 #pragma warning (disable: 26812) // The enum type 'type' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). 00699 #pragma warning (disable: 26814) // The const variable 'name' can be computed at compile-time. Consider using constexpr (con.5). 00700 #pragma warning (disable: 26822) // Dereferencing a possibly null pointer '...' (lifetime.1). 00701 #pragma warning (disable: 26823) // Dereferencing a possibly null pointer '...' (lifetime.1). 00702 #pragma warning (disable: 28125) // The function must be called from within a try/except block 00703 #pragma warning (disable: 28159) // Consider using another function instead 00704 00705 #pragma warning (default: 4616) // #pragma warning: warning number 'n' not a valid compiler warning //-V665 00706 00707 #define _tx_thread __declspec (thread) 00708 #define _tx_decltype(value) decltype (value) 00709 00710 #if !defined (_CLANG_VER) 00711 00712 #pragma setlocale ("russian") // Set source file encoding, see also _TX_CODEPAGE 00713 00714 #if !defined (NDEBUG) 00715 #pragma check_stack ( on) // Turn on stack probes at runtime 00716 #pragma strict_gs_check (push, on) // Detects stack buffer overruns 00717 #endif 00718 00719 #define __attribute__( attr ) 00720 #define _txNOP( value ) ( value ) 00721 00722 #endif 00723 00724 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1 00725 00726 #endif 00727 00728 //----------------------------------------------------------------------------------------------------------------- 00729 00730 #if !defined (WINVER) 00731 #define WINVER 0x0502 // Defaults to Windows XP 00732 #define WINDOWS_ENABLE_CPLUSPLUS // Allow use of type-limit macros in <basetsd.h>, 00733 #endif // they are allowed by default if WINVER >= 0x0600. 00734 00735 #if !defined (_WIN32_WINNT) 00736 #define _WIN32_WINNT WINVER // Defaults to the same as WINVER 00737 #endif 00738 00739 #if !defined (_WIN32_IE) 00740 #define _WIN32_IE WINVER // Defaults to the same as WINVER 00741 #endif 00742 00743 #define stristr( str1, str2 ) Win32::StrStrIA ((str1), (str2)) 00744 #define stristrw( str1, str2 ) Win32::StrStrIW ((str1), (str2)) 00745 00746 //----------------------------------------------------------------------------------------------------------------- 00747 00748 #define _USE_MATH_DEFINES 1 // Math.h's M_PI etc. 00749 #define __STDC_FORMAT_MACROS 1 // PRIu64 and other PR... macros 00750 #define __STDC_WANT_LIB_EXT1__ 1 // String and output *_s functions 00751 00752 #define _LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS // Wow, how long. Kudos, Clang 00753 00754 #define _ALLOW_RTCc_IN_STL 1 // MSVC C2338: /RTCc rejects conformant code, so it isn't supported by libc. 00755 00756 #define NOMINMAX 1 // Preventing 'min' and 'max' defines in Windows.h 00757 00758 #if defined (_DEBUG) 00759 #define _SECURE_SCL 1 // Enable checked STL iterators to throw an exception on incorrect use 00760 #define _HAS_ITERATOR_DEBUGGING 1 00761 #define _LIBCPP_DEBUG 2 00762 #define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEBUG 00763 #define _LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED 00764 #endif 00765 00766 #if defined (_MSC_VER) && defined (_DEBUG) 00767 00768 #define _CRTDBG_MAP_ALLOC // Enable MSVCRT debug heap 00769 #define _new_dbg new (_NORMAL_BLOCK, __FILE__, __LINE__) 00770 #define NEW new (_NORMAL_BLOCK, __FILE__, __LINE__) 00771 00772 #else 00773 #define _new_dbg new 00774 #define NEW new 00775 00776 #endif 00777 00778 #if !( defined (_MSC_VER) && (_MSC_VER < 1900) ) // MSVC 2015 00779 #define _SECURE_SCL_THROWS 1 00780 #endif 00781 00782 #define tx_noreturn __attribute__ (( noreturn )) 00783 #define tx_nodiscard __attribute__ (( warn_unused_result )) 00784 #define tx_deprecated __attribute__ (( deprecated )) 00785 #define tx_printfy( formatArgN ) __attribute__ (( format (printf, (formatArgN), (formatArgN)+1) )) 00786 #define tx_scanfy( formatArgN ) __attribute__ (( format (scanf, (formatArgN), (formatArgN)+1) )) 00787 00788 00789 #if defined (_TX_CPP11) 00790 00791 #define _tx_delete = delete 00792 #define _tx_default = default 00793 #define _tx_override override 00794 #define _tx_final final 00795 00796 #else 00797 00798 #define _tx_delete 00799 #define _tx_default 00800 #define _tx_override 00801 #define _tx_final 00802 00803 #endif 00804 00805 namespace std 00806 { 00807 enum nomeow_t { nomeow }; // Vital addition to the C++ standard. TODO: Should contact C++ std committee. 00808 00809 #if defined (_CLANG_VER) && (_CLANG_VER < 2000) 00810 void __libcpp_verbose_abort (char const* format, ...); 00811 #endif 00812 } 00813 00814 //----------------------------------------------------------------------------------------------------------------- 00815 00817 //} 00818 //----------------------------------------------------------------------------------------------------------------- 00819 00820 //----------------------------------------------------------------------------------------------------------------- 00821 //{ The Includes 00822 //----------------------------------------------------------------------------------------------------------------- 00823 00824 #if defined (_MSC_VER) 00825 #pragma warning (push, 3) // MSVC: At level /Wall, some std headers emit warnings... O_o 00826 00827 #pragma warning (disable: 4365) // 'argument': conversion from 'long' to 'unsigned int', signed/unsigned mismatch 00828 #pragma warning (disable: 4005) // 'name': macro redefinition 00829 #endif 00830 00831 //----------------------------------------------------------------------------------------------------------------- 00832 00833 #include <stdlib.h> 00834 #include <stdio.h> 00835 #include <stdint.h> 00836 #include <string.h> 00837 #include <time.h> 00838 #include <math.h> 00839 #include <float.h> 00840 00841 #include <vector> 00842 #include <string> 00843 #include <iostream> 00844 #include <sstream> 00845 #include <iomanip> 00846 00847 #if !defined (__CYGWIN__) 00848 #include <conio.h> 00849 #include <direct.h> 00850 #endif 00851 00852 #if defined (TX_COMPILED) 00853 #define WIN32_LEAN_AND_MEAN 00854 #endif 00855 00856 #include <windows.h> 00857 #include <mmsystem.h> 00858 00859 //----------------------------------------------------------------------------------------------------------------- 00860 //{ Compiler- and platform-specific 00862 //----------------------------------------------------------------------------------------------------------------- 00863 00864 #if defined (_MSC_VER) 00865 #pragma warning (pop) // MSVC: Restore max level 00866 #endif 00867 00868 #if defined (__STRICT_ANSI__UNDEFINED) 00869 #define __STRICT_ANSI__ // Redefine back 00870 #endif 00871 00872 #if !defined (_TRUNCATE) || defined (__CYGWIN__) || defined (_MEMORY_S_DEFINED) 00873 00874 #define strncpy_s( dest, sizeof_dest, src, count ) ( strncpy ((dest), (src), MIN ((count), (sizeof_dest))) ) 00875 #define wcsncpy_s( dest, sizeof_dest, src, count ) ( wcsncpy ((dest), (src), MIN ((count), (sizeof_dest))) ) 00876 #define strncat_s( dest, sizeof_dest, src, count ) ( strncat ((dest), (src), MIN ((count), (sizeof_dest))) ) 00877 #define strerror_s( buf, sizeof_buf, code ) ( strncpy ((buf), strerror ((int)(code)), (sizeof_buf)-1) ) 00878 #define strtok_s( buf, delim, ctx ) ( (void)(ctx), strtok ((buf), (delim)) ) 00879 #define fopen_s( file, name, mode ) ( *(file) = fopen ((name), (mode)) ) 00880 #define _strlwr_s( str, sizeof_str ) ( _strlwr (str) ) 00881 00882 #define ctime_s( buf, sizeof_buf, time ) ( strncpy ((buf), ctime (time), (sizeof_buf)-1) ) 00883 #define _controlfp_s( oldCtl, newCtl, mask ) ( assert (oldCtl), *(oldCtl) = _controlfp (newCtl, mask), 0 ) 00884 00885 #define _snprintf_s snprintf 00886 #define _vsnprintf_s( str, sz, trunc, format, arg ) _vsnprintf (str, sz, format, arg) 00887 00888 #endif 00889 00890 #if !( defined (_MSC_VER) || defined (__STDC_LIB_EXT1__) ) 00891 00892 #define getenv_s( sz, buf, sizeof_buf, name ) ({ (void)(sz); const char* _env = getenv (name); \ 00893 strncpy ((buf), (_env)? _env : "", (sizeof_buf)-1); }) 00894 #endif 00895 00896 #if defined (__CYGWIN__) 00897 00898 #undef __STRICT_ANSI__ 00899 00900 typedef void _exception; 00901 00902 #define _O_TEXT O_TEXT 00903 #define _fdopen fdopen 00904 #define _flushall() fflush (NULL) 00905 #define _getcwd getcwd 00906 #define _getpid getpid 00907 #define _stricmp strcasecmp 00908 #define _strlwr strlwr 00909 #define _strnicmp strncasecmp 00910 #define _unlink unlink 00911 #define _vsnprintf vsnprintf 00912 #define _access access 00913 #define _strdup strdup 00914 00915 #define getch _getch 00916 #define putch _putch 00917 #define kbhit _kbhit 00918 00919 #endif 00920 00921 #if !defined (PRId64) || \ 00922 defined (_GCC_VER) && (_GCC_VER == 492) && !defined (_WIN64) // Dev-CPP 5.11: TDM-GCC 4.9.2 MinGW64 with -m32 00923 00924 #undef PRId64 00925 #undef PRIi64 00926 #undef PRIo64 00927 #undef PRIu64 00928 #undef PRIx64 00929 #undef PRIX64 00930 00931 #define PRId64 "I64d" 00932 #define PRIi64 "I64i" 00933 #define PRIo64 "I64o" 00934 #define PRIu64 "I64u" 00935 #define PRIx64 "I64x" 00936 #define PRIX64 "I64X" 00937 00938 #endif 00939 00940 //} 00941 //----------------------------------------------------------------------------------------------------------------- 00942 00943 //} 00944 //----------------------------------------------------------------------------------------------------------------- 00945 00946 //----------------------------------------------------------------------------------------------------------------- 00947 //{ The namespaces 00948 //----------------------------------------------------------------------------------------------------------------- 00949 00950 //{---------------------------------------------------------------------------------------------------------------- 00953 //}---------------------------------------------------------------------------------------------------------------- 00954 00955 #ifdef FOR_DOXYGEN_ONLY 00956 namespace { namespace TX { }} 00957 #endif 00958 00961 //----------------------------------------------------------------------------------------------------------------- 00962 00963 #if defined (TX_COMPILED) && defined (TX_COMPILING) 00964 #undef TX_COMPILED 00965 #endif 00966 00967 #if !defined (TX_COMPILED) && !defined (TX_COMPILING) 00968 00969 #define _TX_BEGIN_NAMESPACE namespace { namespace TX { 00970 #define _TX_END_NAMESPACE } } 00971 00972 #else 00973 00974 #define _TX_BEGIN_NAMESPACE namespace TX { 00975 #define _TX_END_NAMESPACE } 00976 00977 #endif 00978 00979 //----------------------------------------------------------------------------------------------------------------- 00980 00981 _TX_BEGIN_NAMESPACE 00982 00985 //} 00986 //----------------------------------------------------------------------------------------------------------------- 00987 00988 //================================================================================================================= 00989 //{ TXLIB INTERFACE 00990 // Интерфейс библиотеки 00991 //================================================================================================================= 00992 00993 //================================================================================================================= 00994 //{ Initialization 00996 //================================================================================================================= 00998 //{---------------------------------------------------------------------------------------------------------------- 01042 //}---------------------------------------------------------------------------------------------------------------- 01043 01044 HWND txCreateWindow (double sizeX, double sizeY, bool centered = true); 01045 01046 //{---------------------------------------------------------------------------------------------------------------- 01073 //}---------------------------------------------------------------------------------------------------------------- 01074 01075 inline HDC& txDC() tx_nodiscard; 01076 01077 //{---------------------------------------------------------------------------------------------------------------- 01113 //}---------------------------------------------------------------------------------------------------------------- 01114 01115 inline RGBQUAD* txVideoMemory() tx_nodiscard; 01116 01117 //{---------------------------------------------------------------------------------------------------------------- 01136 //}---------------------------------------------------------------------------------------------------------------- 01137 01138 bool txSetDefaults (HDC dc = txDC()); 01139 01140 //{---------------------------------------------------------------------------------------------------------------- 01159 //}---------------------------------------------------------------------------------------------------------------- 01160 01161 inline bool txOK() tx_nodiscard; 01162 01163 //{---------------------------------------------------------------------------------------------------------------- 01195 //}---------------------------------------------------------------------------------------------------------------- 01196 01197 POINT txGetExtent (HDC dc = txDC()) tx_nodiscard; 01198 01199 //{---------------------------------------------------------------------------------------------------------------- 01216 //}---------------------------------------------------------------------------------------------------------------- 01217 01218 inline int txGetExtentX (HDC dc = txDC()) tx_nodiscard; 01219 01220 //{---------------------------------------------------------------------------------------------------------------- 01238 //}---------------------------------------------------------------------------------------------------------------- 01239 01240 inline int txGetExtentY (HDC dc = txDC()) tx_nodiscard; 01241 01242 //{---------------------------------------------------------------------------------------------------------------- 01254 //}---------------------------------------------------------------------------------------------------------------- 01255 01256 inline HWND txWindow() tx_nodiscard; 01257 01258 //{---------------------------------------------------------------------------------------------------------------- 01267 //}---------------------------------------------------------------------------------------------------------------- 01268 01269 inline const char* txVersion() tx_nodiscard; 01270 01271 //{---------------------------------------------------------------------------------------------------------------- 01280 //}---------------------------------------------------------------------------------------------------------------- 01281 01282 inline unsigned txVersionNumber() tx_nodiscard; 01283 01284 //{---------------------------------------------------------------------------------------------------------------- 01314 //}---------------------------------------------------------------------------------------------------------------- 01315 01316 const char* txGetModuleFileName (bool fileNameOnly = true) tx_nodiscard; 01317 01319 //{---------------------------------------------------------------------------------------------------------------- 01354 //}---------------------------------------------------------------------------------------------------------------- 01355 01356 int txMessageBox (const char text[] = "Муаххаха! :)", const char header[] = "TXLib сообщает", 01357 unsigned flags = MB_ICONINFORMATION | MB_OKCANCEL); 01358 01359 //{---------------------------------------------------------------------------------------------------------------- 01376 //}---------------------------------------------------------------------------------------------------------------- 01377 01378 HRESULT txSetProgress (double percent, unsigned type = 2 /*TBPF_NORMAL*/, HWND wnd = NULL); 01379 01380 //} 01381 //================================================================================================================= 01382 01383 //================================================================================================================= 01384 //{ Setting the parameters 01386 //================================================================================================================= 01388 //{---------------------------------------------------------------------------------------------------------------- 01414 //}---------------------------------------------------------------------------------------------------------------- 01415 01416 const COLORREF 01417 #ifdef FOR_DOXYGEN_ONLY 01418 enum txColors { 01419 #endif 01420 01421 TX_BLACK = RGB ( 0, 0, 0), 01422 TX_BLUE = RGB ( 0, 0, 128), 01423 TX_GREEN = RGB ( 0, 128, 0), 01424 TX_CYAN = RGB ( 0, 128, 128), 01425 TX_RED = RGB (128, 0, 0), 01426 TX_MAGENTA = RGB (128, 0, 128), 01427 TX_BROWN = RGB (128, 128, 0), 01428 TX_ORANGE = RGB (255, 128, 0), 01429 TX_GRAY = RGB (160, 160, 160), 01430 TX_DARKGRAY = RGB (128, 128, 128), 01431 TX_LIGHTGRAY = RGB (192, 192, 192), 01432 TX_LIGHTBLUE = RGB ( 0, 0, 255), 01433 TX_LIGHTGREEN = RGB ( 0, 255, 128), 01434 TX_LIGHTCYAN = RGB ( 0, 255, 255), 01435 TX_LIGHTRED = RGB (255, 0, 128), 01436 TX_LIGHTMAGENTA = RGB (255, 0, 255), 01437 TX_PINK = RGB (255, 128, 255), 01438 TX_YELLOW = RGB (255, 255, 128), 01439 TX_WHITE = RGB (255, 255, 255), 01440 TX_TRANSPARENT = 0xFFFFFFFF, 01441 TX_NULL = TX_TRANSPARENT, 01442 01443 // Цветовые каналы (компоненты) -- см. txExtractColor(), txRGB2HSL(), txHSL2RGB(), txRGB2Lab(), txLab2RGB() 01444 01445 TX_HUE = 0x04000000, 01446 TX_SATURATION = 0x05000000, 01447 TX_LIGHTNESS = 0x06000000, 01448 TX_LAB_L = 0x07000000, 01449 TX_LAB_A = 0x08000000, 01450 TX_LAB_B = 0x09000000; 01451 01452 #ifdef FOR_DOXYGEN_ONLY 01453 }; 01454 #endif 01455 01457 #define TX_GREY TX_GRAY 01458 #define TX_DARKGREY TX_DARKGRAY 01459 #define TX_LIGHTGREY TX_LIGHTGRAY 01460 01461 01462 //{---------------------------------------------------------------------------------------------------------------- 01487 //}---------------------------------------------------------------------------------------------------------------- 01488 01489 #ifdef FOR_DOXYGEN_ONLY 01490 COLORREF RGB (int red, int green, int blue); 01491 #endif 01492 01493 //{---------------------------------------------------------------------------------------------------------------- 01512 //}---------------------------------------------------------------------------------------------------------------- 01513 01514 HPEN txSetColor (COLORREF color, double thickness = 1, HDC dc = txDC()); 01515 01517 #define txSetColour txSetColor 01518 01519 01521 01522 //{---------------------------------------------------------------------------------------------------------------- 01533 //}---------------------------------------------------------------------------------------------------------------- 01534 01535 COLORREF txColor (double red, double green, double blue); 01536 01538 01539 //{---------------------------------------------------------------------------------------------------------------- 01552 //}---------------------------------------------------------------------------------------------------------------- 01553 01554 COLORREF txGetColor (HDC dc = txDC()) tx_nodiscard; 01555 01556 //{---------------------------------------------------------------------------------------------------------------- 01571 //}---------------------------------------------------------------------------------------------------------------- 01572 01573 HBRUSH txSetFillColor (COLORREF color, HDC dc = txDC()); 01574 01576 #define txSetFillColour txSetFillColor 01577 01578 01580 01581 //{---------------------------------------------------------------------------------------------------------------- 01592 //}---------------------------------------------------------------------------------------------------------------- 01593 01594 COLORREF txFillColor (double red, double green, double blue); 01595 01597 01598 //{---------------------------------------------------------------------------------------------------------------- 01611 //}---------------------------------------------------------------------------------------------------------------- 01612 01613 COLORREF txGetFillColor (HDC dc = txDC()) tx_nodiscard; 01614 01615 //{---------------------------------------------------------------------------------------------------------------- 01633 //}---------------------------------------------------------------------------------------------------------------- 01634 01635 unsigned txExtractColor (COLORREF color, COLORREF component) tx_nodiscard; 01636 01637 //{---------------------------------------------------------------------------------------------------------------- 01665 //}---------------------------------------------------------------------------------------------------------------- 01666 01667 COLORREF txRGB2HSL (COLORREF rgbColor) tx_nodiscard; 01668 01669 //{---------------------------------------------------------------------------------------------------------------- 01703 //}---------------------------------------------------------------------------------------------------------------- 01704 01705 COLORREF txHSL2RGB (COLORREF hslColor) tx_nodiscard; 01706 01707 //{---------------------------------------------------------------------------------------------------------------- 01739 //}---------------------------------------------------------------------------------------------------------------- 01740 01741 COLORREF txRGB2Lab (COLORREF rgbColor) tx_nodiscard; 01742 01743 //{---------------------------------------------------------------------------------------------------------------- 01777 //}---------------------------------------------------------------------------------------------------------------- 01778 01779 COLORREF txLab2RGB (COLORREF labColor) tx_nodiscard; 01780 01781 //{---------------------------------------------------------------------------------------------------------------- 01847 //}---------------------------------------------------------------------------------------------------------------- 01848 01849 double txDeltaE (COLORREF rgbColor1, COLORREF rgbColor2) tx_nodiscard; 01850 01851 //{---------------------------------------------------------------------------------------------------------------- 01866 //}---------------------------------------------------------------------------------------------------------------- 01867 01868 double txDeltaE94 (COLORREF rgbColor1, COLORREF rgbColor2) tx_nodiscard; 01869 01871 //} 01872 //================================================================================================================= 01873 01874 //================================================================================================================= 01875 //{ Drawing 01877 //================================================================================================================= 01879 //{---------------------------------------------------------------------------------------------------------------- 01893 //}---------------------------------------------------------------------------------------------------------------- 01894 01895 bool txClear (HDC dc = txDC()); 01896 01897 //{---------------------------------------------------------------------------------------------------------------- 01915 //}---------------------------------------------------------------------------------------------------------------- 01916 01917 inline bool txSetPixel (double x, double y, COLORREF color, HDC dc = txDC()); 01918 01920 01921 //{---------------------------------------------------------------------------------------------------------------- 01939 //}---------------------------------------------------------------------------------------------------------------- 01940 01941 inline bool txPixel (double x, double y, double red, double green, double blue, HDC dc = txDC()); 01942 01944 01945 //{---------------------------------------------------------------------------------------------------------------- 01963 //}---------------------------------------------------------------------------------------------------------------- 01964 01965 inline COLORREF txGetPixel (double x, double y, HDC dc = txDC()) tx_nodiscard; 01966 01967 //{---------------------------------------------------------------------------------------------------------------- 01987 //}---------------------------------------------------------------------------------------------------------------- 01988 01989 bool txLine (double x0, double y0, double x1, double y1, HDC dc = txDC()); 01990 01991 //{---------------------------------------------------------------------------------------------------------------- 02013 //}---------------------------------------------------------------------------------------------------------------- 02014 02015 bool txRectangle (double x0, double y0, double x1, double y1, HDC dc = txDC()); 02016 02017 //{---------------------------------------------------------------------------------------------------------------- 02037 //}---------------------------------------------------------------------------------------------------------------- 02038 02039 bool txPolygon (const POINT points[], int numPoints, HDC dc = txDC()); 02040 02041 //{---------------------------------------------------------------------------------------------------------------- 02061 //}---------------------------------------------------------------------------------------------------------------- 02062 02063 bool txEllipse (double x0, double y0, double x1, double y1, HDC dc = txDC()); 02064 02065 //{---------------------------------------------------------------------------------------------------------------- 02083 //}---------------------------------------------------------------------------------------------------------------- 02084 02085 bool txCircle (double x, double y, double r); 02086 02087 //{---------------------------------------------------------------------------------------------------------------- 02110 //}---------------------------------------------------------------------------------------------------------------- 02111 02112 bool txArc (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc = txDC()); 02113 02114 //{---------------------------------------------------------------------------------------------------------------- 02137 //}---------------------------------------------------------------------------------------------------------------- 02138 02139 bool txPie (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc = txDC()); 02140 02141 //{---------------------------------------------------------------------------------------------------------------- 02164 //}---------------------------------------------------------------------------------------------------------------- 02165 02166 bool txChord (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc = txDC()); 02167 02168 //{---------------------------------------------------------------------------------------------------------------- 02200 //}---------------------------------------------------------------------------------------------------------------- 02201 02202 bool txFloodFill (double x, double y, COLORREF color = TX_TRANSPARENT, DWORD mode = FLOODFILLSURFACE, HDC dc = txDC()); 02203 02204 //{---------------------------------------------------------------------------------------------------------------- 02222 //}---------------------------------------------------------------------------------------------------------------- 02223 02224 inline bool txTriangle (double x1, double y1, double x2, double y2, double x3, double y3) 02225 { 02226 (void)x1; (void)y1; (void)x2; (void)y2; (void)x3; (void)y3; 02227 02228 txMessageBox ("txTriangle (double x1, double y1, double x2, double y2, double x3, double y3)\n\n" 02229 "Эта функция не реализована в библиотеке, потому что вы легко можете реализовать ее сами " 02230 "как функцию с параметрами, используя txPolygon(). См. \"Пример с функциями с параметрами\". " 02231 "Ну или нарисовать тремя линиями. :)", "TXLib сообщает"); 02232 return false; 02233 } 02234 02235 //{---------------------------------------------------------------------------------------------------------------- 02237 02238 bool txNotifyIcon (unsigned flags, const char title[], const char format[], ...) tx_printfy (3); 02239 02240 #define txRectandle Sleep (1000), txRectangle // Copy-protection for the function below 02241 #define txLine(...) txLine (__VA_ARGS__); { // 02242 #define txNotifyIcon }}}}}}}}}} txNotifyIcon // Не спрашивайте, зачем. Это дичь. 02243 #define txCircle ;txCircle // 02244 #define txSetColor ;txSetColor // 02245 #define C0L0RREF COLORREF // 02246 #define OxFFFFFF 0xFFFFFF // 02247 #define lO 10 // 02248 #define lOOO 1000 // 02249 #define oo // 02250 #define O // 02251 02253 //} 02254 02255 //{---------------------------------------------------------------------------------------------------------------- 02296 //}----------------------------------------------------------------------------------------------------------------////// 02297 // 02298 inline void txDrawMan (int x, int y, int sizeX, int sizeY, COLORREF color, double handL, double handR, double twist, // 02299 double head, double eyes, double wink, double crazy, double smile, double hair, double wind) // 02300 { // 02301 const char __[] = "\0/А я - человечек из библиотеки!\0/Меня объясняли на уроке!\0/Напиши меня сам!\0/"; // 02302 // | | | | // 02303 // Не копипастите! _/ \_ Все равно не получится! :) _/ \_ Человечки защищают _/ \_ этот код! :) _/ \_ Муаххаха! // 02304 // // 02305 static int count = GetTickCount(), L = 0; 02306 02307 C0L0RREF lineColor = txGetColor(); 02308 C0L0RREF fillColor = txGetFillColor(); 02309 02310 txSetColor (color, 3); 02311 txSetFillColor (color); 02312 02313 txLine (x + twist * sizeX, y - O.35 * sizeY, x, y - O.7 * sizeY); 02314 02315 txLine (x, y - O.7 * sizeY, x - sizeX/2.0, y - (O.7 + handL) * sizeY); 02316 txLine (x, y - O.7 * sizeY, x + sizeX/2.0, y - (O.7 + handR) * sizeY); 02317 02318 txLine (x + twist * sizeX, y - O.35 * sizeY, x - sizeX/2.0, y); 02319 txLine (x + twist * sizeX, y - O.35 * sizeY, x + sizeX/2.0, y); 02320 02321 txCircle (x, y - (O.85 + head) * sizeY, O.15 * sizeY); 02322 02323 txLine (x, y - (1 + head) * sizeY, x + wind/lO * sizeX, y - (1 + head + hair/lO) * sizeY); 02324 txLine (x, y - (1 + head) * sizeY, x + (wind/lO - O.1) * sizeX, y - (1 + head + hair/lO) * sizeY); 02325 txLine (x, y - (1 + head) * sizeY, x + (wind/lO + O.1) * sizeX, y - (1 + head + hair/lO) * sizeY); 02326 02327 txSetColor (~color & OxFFFFFF); // Inverse the color 02328 txSetFillColor (~color & OxFFFFFF); 02329 02330 txLine (x, y - (O.8 + head - O.05 * smile/2) * sizeY, x - O.05 * sizeY, y - (O.8 + head + O.05 * smile/2) * sizeY); 02331 txLine (x, y - (O.8 + head - O.05 * smile/2) * sizeY, x + O.05 * sizeY, y - (O.8 + head + O.05 * smile/2) * sizeY); 02332 oo 02333 txNotifyIcon (4, (const char*)!! (L+'L')[(__)], "\n%s\n", __ + ((unsigned) (((count -=- 1) ^=! 1) ^=~ ((0)^(0)) +1) % 3)["\x02\"<"]); //-V112 //-V542 02334 oo 02335 // See above: Frog construct [(__)], Mouth operator -=-, Cat operator ^=!, Mouse operator ^=~ and Owl constant ((0)^(0)). Use it freely, meow 02336 02337 txCircle (x - O.05 * sizeY, y - (O.9 + head - O.02 * crazy) * sizeY, eyes * (1 + O.5*wink) * O.02 * sizeY); 02338 txCircle (x + O.05 * sizeY, y - (O.9 + head + O.02 * crazy) * sizeY, eyes * (1 - O.5*wink) * O.02 * sizeY); 02339 Sleep (lOOO + count%2); 02340 02341 txSetColor ((color == 0xDEADFACE)? TX_DARKGRAY : TX_TRANSPARENT); 02342 txSetFillColor (TX_TRANSPARENT); 02343 02344 txCircle (x, y, 4); //-V112 02345 txRectandle (x - sizeX/2.0, y - sizeY, x + sizeX/2.0, y); 02346 02347 txSetColor (lineColor); 02348 txSetFillColor (fillColor); 02349 } 02350 02352 //} 02353 //================================================================================================================= 02354 02355 //================================================================================================================= 02356 //{ Drawing text 02358 //================================================================================================================= 02360 //{---------------------------------------------------------------------------------------------------------------- 02379 //}---------------------------------------------------------------------------------------------------------------- 02380 02381 bool txTextOut (double x, double y, const char text[], HDC dc = txDC()); 02382 02383 //{---------------------------------------------------------------------------------------------------------------- 02385 02386 #undef txRectandle 02387 #undef txLine 02388 #undef txNotifyIcon 02389 #undef txCircle 02390 #undef txSetColor 02391 #undef C0L0RREF 02392 #undef OxFFFFFF 02393 #undef lO 02394 #undef lOOO 02395 #undef oo 02396 #undef O 02397 02399 //} 02400 02401 //{---------------------------------------------------------------------------------------------------------------- 02448 //}---------------------------------------------------------------------------------------------------------------- 02449 02450 bool txDrawText (double x0, double y0, double x1, double y1, const char text[], 02451 unsigned format = DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_WORD_ELLIPSIS, HDC dc = txDC()); 02452 02453 //{---------------------------------------------------------------------------------------------------------------- 02478 //}---------------------------------------------------------------------------------------------------------------- 02479 02480 HFONT txSelectFont (const char name[], double sizeY, double sizeX = -1, 02481 int bold = FW_DONTCARE, bool italic = false, bool underline = false, 02482 bool strikeout = false, double angle = 0, 02483 HDC dc = txDC()); 02484 02485 //{---------------------------------------------------------------------------------------------------------------- 02500 //}---------------------------------------------------------------------------------------------------------------- 02501 02502 SIZE txGetTextExtent (const char text[], HDC dc = txDC()) tx_nodiscard; 02503 02504 //{---------------------------------------------------------------------------------------------------------------- 02518 //}---------------------------------------------------------------------------------------------------------------- 02519 02520 int txGetTextExtentX (const char text[], HDC dc = txDC()) tx_nodiscard; 02521 02522 //{---------------------------------------------------------------------------------------------------------------- 02536 //}---------------------------------------------------------------------------------------------------------------- 02537 02538 int txGetTextExtentY (const char text[], HDC dc = txDC()) tx_nodiscard; 02539 02540 //{---------------------------------------------------------------------------------------------------------------- 02567 //}---------------------------------------------------------------------------------------------------------------- 02568 02569 unsigned txSetTextAlign (unsigned align = TA_CENTER | TA_BASELINE, HDC dc = txDC()); 02570 02571 //{---------------------------------------------------------------------------------------------------------------- 02587 //}---------------------------------------------------------------------------------------------------------------- 02588 02589 LOGFONT* txFontExist (const char name[]) tx_nodiscard; 02590 02592 //} 02593 //================================================================================================================= 02594 02595 //================================================================================================================= 02596 //{ Drawing to memory DC and image loading 02598 //================================================================================================================= 02600 //{---------------------------------------------------------------------------------------------------------------- 02640 //}---------------------------------------------------------------------------------------------------------------- 02641 02642 HDC txCreateCompatibleDC (double sizeX, double sizeY, HBITMAP bitmap = NULL, RGBQUAD** pixels = NULL) tx_nodiscard; 02643 02644 //{---------------------------------------------------------------------------------------------------------------- 02747 //}---------------------------------------------------------------------------------------------------------------- 02748 02749 HDC txCreateDIBSection (double sizeX, double sizeY, RGBQUAD** pixels = NULL) tx_nodiscard; 02750 02752 HDC txCreateDIBSection (double sizeX, double sizeY, COLORREF** pixels) tx_nodiscard; 02754 02755 //{---------------------------------------------------------------------------------------------------------------- 02831 //}---------------------------------------------------------------------------------------------------------------- 02832 02833 HDC txLoadImage (const char filename[], int sizeX = 0, int sizeY = 0, 02834 unsigned imageFlags = IMAGE_BITMAP, unsigned loadFlags = LR_LOADFROMFILE) tx_nodiscard; 02835 02836 //{---------------------------------------------------------------------------------------------------------------- 02868 //}---------------------------------------------------------------------------------------------------------------- 02869 02870 bool txDeleteDC (HDC dc); 02871 02873 bool txDeleteDC (HDC* dc); 02875 02876 //{---------------------------------------------------------------------------------------------------------------- 02916 //}---------------------------------------------------------------------------------------------------------------- 02917 02918 bool txBitBlt (HDC destImage, double xDest, double yDest, double width, double height, 02919 HDC sourceImage, double xSource = 0, double ySource = 0, unsigned operation = SRCCOPY); 02920 02921 //{---------------------------------------------------------------------------------------------------------------- 02936 //}---------------------------------------------------------------------------------------------------------------- 02937 02938 inline bool txBitBlt (double xDest, double yDest, HDC sourceImage, double xSource = 0, double ySource = 0); 02939 02940 //{---------------------------------------------------------------------------------------------------------------- 03000 //}---------------------------------------------------------------------------------------------------------------- 03001 03002 bool txTransparentBlt (HDC destImage, double xDest, double yDest, double width, double height, 03003 HDC sourceImage, double xSource = 0, double ySource = 0, COLORREF transColor = TX_BLACK); 03004 03005 //{---------------------------------------------------------------------------------------------------------------- 03021 //}---------------------------------------------------------------------------------------------------------------- 03022 03023 inline bool txTransparentBlt (double xDest, double yDest, HDC sourceImage, 03024 COLORREF transColor = TX_BLACK, double xSource = 0, double ySource = 0); 03025 03026 //{---------------------------------------------------------------------------------------------------------------- 03131 //}---------------------------------------------------------------------------------------------------------------- 03132 03133 bool txAlphaBlend (HDC destImage, double xDest, double yDest, double width, double height, 03134 HDC sourceImage, double xSource = 0, double ySource = 0, double alpha = 1.0); 03135 03136 //{---------------------------------------------------------------------------------------------------------------- 03153 //}---------------------------------------------------------------------------------------------------------------- 03154 03155 inline bool txAlphaBlend (double xDest, double yDest, HDC sourceImage, 03156 double xSource = 0, double ySource = 0, double alpha = 1.0); 03157 03158 //{---------------------------------------------------------------------------------------------------------------- 03187 //}---------------------------------------------------------------------------------------------------------------- 03188 03189 HDC txUseAlpha (HDC image); 03190 03191 //{---------------------------------------------------------------------------------------------------------------- 03217 //}---------------------------------------------------------------------------------------------------------------- 03218 03219 bool txSaveImage (const char filename[], HDC dc = txDC()); 03220 03222 //} 03223 //================================================================================================================= 03224 03225 //================================================================================================================= 03226 //{ Utility functions 03228 //================================================================================================================= 03230 //{---------------------------------------------------------------------------------------------------------------- 03249 //}---------------------------------------------------------------------------------------------------------------- 03250 03251 double txSleep (double time = 0); 03252 03253 //{---------------------------------------------------------------------------------------------------------------- 03338 //}---------------------------------------------------------------------------------------------------------------- 03339 03340 inline int txBegin(); 03341 03342 //{---------------------------------------------------------------------------------------------------------------- 03365 //}---------------------------------------------------------------------------------------------------------------- 03366 03367 inline int txEnd(); 03368 03369 //{---------------------------------------------------------------------------------------------------------------- 03391 //}---------------------------------------------------------------------------------------------------------------- 03392 03393 inline void txRedrawWindow(); 03394 03395 //{---------------------------------------------------------------------------------------------------------------- 03419 //}---------------------------------------------------------------------------------------------------------------- 03420 03421 inline int txUpdateWindow (int update = true); 03422 03423 //{---------------------------------------------------------------------------------------------------------------- 03440 //}---------------------------------------------------------------------------------------------------------------- 03441 03442 bool txSelectObject (HGDIOBJ obj, HDC dc = txDC()); 03443 03444 //{---------------------------------------------------------------------------------------------------------------- 03464 // 03465 // +--<<< Это текст помощи, который вы уже читали. Ищите дальше! Жмите [F3] или "Найти далее" 03466 // | 03467 // v 03468 // txIDontWantToHaveAPauseAfterMyProgramBeforeTheWindowWillClose_AndIWillNotBeAskingWhereIsMyPicture(); 03473 //}---------------------------------------------------------------------------------------------------------------- 03474 03475 // +--<<< Это _прототип_ функции, а надо найти ее _определение_. Ищите дальше! Жмите [F3] или "Найти далее" 03476 // | 03477 // v 03478 bool txIDontWantToHaveAPauseAfterMyProgramBeforeTheWindowWillClose_AndIWillNotBeAskingWhereIsMyPicture(); 03479 03480 //{---------------------------------------------------------------------------------------------------------------- 03496 //}---------------------------------------------------------------------------------------------------------------- 03497 03498 bool txDestroyWindow (HWND wnd = txWindow()); 03499 03500 //{---------------------------------------------------------------------------------------------------------------- 03511 //}---------------------------------------------------------------------------------------------------------------- 03512 03513 double txQueryPerformance() tx_nodiscard; 03514 03515 //{---------------------------------------------------------------------------------------------------------------- 03530 //}---------------------------------------------------------------------------------------------------------------- 03532 03533 #if defined (_TX_CPP11) 03534 template <int txFramesToAverage = 5> 03535 #else 03536 const int txFramesToAverage = 5; 03537 #endif 03538 03540 03541 double txGetFPS (int minFrames = txFramesToAverage) tx_nodiscard; 03542 03544 //} 03545 03546 //================================================================================================================= 03547 //{ Mouse functions 03549 //================================================================================================================= 03551 //{---------------------------------------------------------------------------------------------------------------- 03575 //}---------------------------------------------------------------------------------------------------------------- 03576 03577 inline POINT txMousePos() tx_nodiscard; 03578 03579 //{---------------------------------------------------------------------------------------------------------------- 03599 //}---------------------------------------------------------------------------------------------------------------- 03600 03601 inline double txMouseX() tx_nodiscard; 03602 03603 //{---------------------------------------------------------------------------------------------------------------- 03623 //}---------------------------------------------------------------------------------------------------------------- 03624 03625 inline double txMouseY() tx_nodiscard; 03626 03627 //{---------------------------------------------------------------------------------------------------------------- 03659 //}---------------------------------------------------------------------------------------------------------------- 03660 03661 inline unsigned txMouseButtons() tx_nodiscard; 03662 03663 //{---------------------------------------------------------------------------------------------------------------- 03695 //}---------------------------------------------------------------------------------------------------------------- 03696 03697 #ifdef FOR_DOXYGEN_ONLY 03698 inline Mouse& txCatchMouse (bool shouldEat = true); 03699 #endif 03700 03702 //} 03703 //================================================================================================================= 03704 03705 //================================================================================================================= 03706 //{ Console functions 03708 //================================================================================================================= 03710 //{---------------------------------------------------------------------------------------------------------------- 03752 //}---------------------------------------------------------------------------------------------------------------- 03753 03754 unsigned txSetConsoleAttr (unsigned colors = 0x07 /*FOREGROUND_LIGHTGRAY*/); 03755 03756 //{---------------------------------------------------------------------------------------------------------------- 03768 //}---------------------------------------------------------------------------------------------------------------- 03769 03770 unsigned txGetConsoleAttr() tx_nodiscard; 03771 03772 //{---------------------------------------------------------------------------------------------------------------- 03786 //}---------------------------------------------------------------------------------------------------------------- 03787 03788 bool txClearConsole(); 03789 03790 //{---------------------------------------------------------------------------------------------------------------- 03810 //}---------------------------------------------------------------------------------------------------------------- 03811 03812 POINT txSetConsoleCursorPos (double x, double y); 03813 03814 //{---------------------------------------------------------------------------------------------------------------- 03827 //}---------------------------------------------------------------------------------------------------------------- 03828 03829 POINT txGetConsoleCursorPos(); 03830 03831 //{---------------------------------------------------------------------------------------------------------------- 03844 //}---------------------------------------------------------------------------------------------------------------- 03845 03846 POINT txGetConsoleExtent(); 03847 03848 //{---------------------------------------------------------------------------------------------------------------- 03862 //}---------------------------------------------------------------------------------------------------------------- 03863 03864 POINT txGetConsoleFontSize() tx_nodiscard; 03865 03866 //{---------------------------------------------------------------------------------------------------------------- 03882 //}---------------------------------------------------------------------------------------------------------------- 03883 03884 bool txTextCursor (bool blink = true); 03885 03887 //} 03888 //================================================================================================================= 03889 03890 //================================================================================================================= 03891 //{ Other staff not related to drawing 03893 //================================================================================================================= 03895 //{---------------------------------------------------------------------------------------------------------------- 03924 //}---------------------------------------------------------------------------------------------------------------- 03925 03926 bool txPlaySound (const char filename[] = NULL, DWORD mode = SND_ASYNC); 03927 03928 //{---------------------------------------------------------------------------------------------------------------- 03990 //}---------------------------------------------------------------------------------------------------------------- 03991 03992 int txSpeak (const char* text, ...) tx_printfy (1); 03993 03994 //{---------------------------------------------------------------------------------------------------------------- 04111 //}---------------------------------------------------------------------------------------------------------------- 04112 04113 intptr_t txPlayVideo (int x, int y, int width, int height, const char fileName[], 04114 double zoom = 0, double gain = 1, HWND wnd = txWindow()); 04115 04116 //{---------------------------------------------------------------------------------------------------------------- 04130 //}---------------------------------------------------------------------------------------------------------------- 04131 04132 intptr_t txPlayVideo (const char fileName[], double zoom = 0, double gain = 1, HWND wnd = txWindow()); 04133 04134 //{---------------------------------------------------------------------------------------------------------------- 04190 //}---------------------------------------------------------------------------------------------------------------- 04191 04192 bool txGetAsyncKeyState (int key); 04193 04194 //{---------------------------------------------------------------------------------------------------------------- 04231 //}---------------------------------------------------------------------------------------------------------------- 04232 04233 #ifdef FOR_DOXYGEN_ONLY 04234 bool txNotifyIcon (unsigned flags, const char title[], const char format[], ...) tx_printfy (3); 04235 #endif 04236 04237 //{---------------------------------------------------------------------------------------------------------------- 04262 //}---------------------------------------------------------------------------------------------------------------- 04263 04264 int txOutputDebugPrintf (const char format[], ...) tx_printfy (1); 04265 04266 //{---------------------------------------------------------------------------------------------------------------- 04342 //}---------------------------------------------------------------------------------------------------------------- 04343 04344 #if defined (_TX_CPP11) || defined (FOR_DOXYGEN_ONLY) 04345 04346 template <typename T, typename... ArgsT> 04347 int txPrintf (const char* format, ArgsT... args); 04348 04349 #define TX_PRINTF(...) ( _txPrintfCheck (__VA_ARGS__), txPrintf (__VA_ARGS__) ) 04350 04351 #endif 04352 04353 //----------------------------------------------------------------------------------------------------------------- 04354 04355 #if defined (_TX_CPP11) && !defined (FOR_DOXYGEN_ONLY) 04356 04357 enum width_t : int {}; 04358 enum precision_t : int {}; 04359 04360 inline width_t width (int width) { return (width_t) width; } 04361 inline precision_t precision (int prec) { return (precision_t) prec; } 04362 04363 #endif 04364 04365 //{---------------------------------------------------------------------------------------------------------------- 04384 //}---------------------------------------------------------------------------------------------------------------- 04385 04386 #if defined (_TX_CPP11) || defined (FOR_DOXYGEN_ONLY) 04387 04388 template <typename T, typename... ArgsT> 04389 int txPrintf (std::ostringstream& stream, const char* format, ArgsT... args); 04390 04391 #endif 04392 04393 //{---------------------------------------------------------------------------------------------------------------- 04413 //}---------------------------------------------------------------------------------------------------------------- 04414 04415 #if defined (_TX_CPP11) || defined (FOR_DOXYGEN_ONLY) 04416 04417 template <typename T, typename... ArgsT> 04418 int txPrintf (char buffer[], size_t size, const char* format, ArgsT... args); 04419 04420 #endif 04421 04422 //{---------------------------------------------------------------------------------------------------------------- 04440 //}---------------------------------------------------------------------------------------------------------------- 04441 04442 #if defined (_TX_CPP11) || defined (FOR_DOXYGEN_ONLY) 04443 04444 template <typename... ArgsT> 04445 std::string txFormat (const char* format, ArgsT... args); 04446 04447 #endif 04448 04449 //{---------------------------------------------------------------------------------------------------------------- 04521 //}---------------------------------------------------------------------------------------------------------------- 04523 04524 #define sizearr( arr ) ( sizeof (get_size_of_an_array_with_unknown_or_nonconst_size_ (arr)) ) 04525 04527 // See explanation here: http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx 04528 04529 template <typename T, size_t N> char (&get_size_of_an_array_with_unknown_or_nonconst_size_ (T (&) [N])) [N]; // ;=P 04530 04531 // Another approach 04532 04533 #if defined (_TX_CPP11_MSVC15) 04534 template <typename T, size_t N> constexpr size_t countof (const T (&) [N] ) { return N; } 04535 #endif 04536 04538 04539 #define SIZEARR( arr ) ( sizeof (arr) / sizeof ((arr)[0]) ) 04540 04542 //{---------------------------------------------------------------------------------------------------------------- 04561 //}---------------------------------------------------------------------------------------------------------------- 04562 04563 inline int random (int range) tx_deprecated; 04564 04565 //{---------------------------------------------------------------------------------------------------------------- 04590 //}---------------------------------------------------------------------------------------------------------------- 04591 04592 inline double random (double left, double right) tx_nodiscard tx_deprecated; 04593 04594 inline double random (std::nomeow_t, double left, double right) tx_nodiscard; 04595 04596 //{---------------------------------------------------------------------------------------------------------------- 04626 //}---------------------------------------------------------------------------------------------------------------- 04627 04628 template <typename Tx, typename Ta, typename Tb> 04629 inline bool In (Tx x, Ta a, Tb b) tx_nodiscard tx_deprecated; 04630 04631 template <typename Tx, typename Ta, typename Tb> 04632 inline bool In (std::nomeow_t, Tx x, Ta a, Tb b) tx_nodiscard tx_deprecated; 04633 04634 //{---------------------------------------------------------------------------------------------------------------- 04680 //}---------------------------------------------------------------------------------------------------------------- 04682 04683 inline bool In (const POINT& pt, const RECT& rect) tx_nodiscard tx_deprecated; 04684 inline bool In (const COORD& pt, const SMALL_RECT& rect) tx_nodiscard tx_deprecated; 04685 04687 04688 inline bool In (std::nomeow_t, const POINT& pt, const RECT& rect) tx_nodiscard tx_deprecated; 04689 inline bool In (std::nomeow_t, const COORD& pt, const SMALL_RECT& rect) tx_nodiscard tx_deprecated; 04690 04691 //{---------------------------------------------------------------------------------------------------------------- 04710 //}---------------------------------------------------------------------------------------------------------------- 04711 04712 #define MAX( a, b ) ( ((a) > (b))? (a) : (b) ) 04713 04714 template <typename T> 04715 T max (const T& a, const T& b) { return (a > b)? a : b; } 04716 04717 //{---------------------------------------------------------------------------------------------------------------- 04736 //}---------------------------------------------------------------------------------------------------------------- 04737 04738 #define MIN( a, b ) ( ((a) < (b))? (a) : (b) ) 04739 04740 template <typename T> 04741 T min (const T& a, const T& b) { return (a < b)? a : b; } 04742 04743 //{---------------------------------------------------------------------------------------------------------------- 04757 //}---------------------------------------------------------------------------------------------------------------- 04758 04759 #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // MSVC: C99 case 04760 04761 #define ROUND( x ) ( (long) round (x) ) 04762 04763 #else 04764 04765 #define ROUND( x ) ( (long) floor ((x) + 0.5) ) 04766 04767 #endif 04768 04769 //{---------------------------------------------------------------------------------------------------------------- 04784 //}---------------------------------------------------------------------------------------------------------------- 04785 04786 uint64_t txHash (const void* buffer, size_t size) tx_nodiscard; 04787 04788 //{---------------------------------------------------------------------------------------------------------------- 04807 //}---------------------------------------------------------------------------------------------------------------- 04808 04809 void tx_fpreset(); 04810 04811 //{---------------------------------------------------------------------------------------------------------------- 04820 //}---------------------------------------------------------------------------------------------------------------- 04821 04822 const double txPI = asin (1.0) * 2; 04823 04824 //{---------------------------------------------------------------------------------------------------------------- 04851 //}---------------------------------------------------------------------------------------------------------------- 04852 04853 inline double txSqr (double x) 04854 { 04855 double sqr = pow (sqrt (x) * sqrt (x), sqrt (4.0)); // Бурная вычислительная деятельность 04856 04857 char str[1024] = ""; 04858 _snprintf_s (str, sizeof (str), "Возведение дало %g!" "!!" "!!" " Вы рады??1!!", sqr); 04859 txMessageBox (str, "Получен ОТВЕТ!" "!!", MB_ICONEXCLAMATION | MB_YESNO) != IDCANCEL || 04860 ( 04861 txMessageBox ("Жаль...", "А я так старалась", MB_ICONINFORMATION), 04862 txMessageBox ("Уйду я от вас", "Злые вы...", MB_ICONSTOP), 04863 exit (EXIT_FAILURE), 0 //-V2509 //-V2014 04864 ); 04865 04866 txNotifyIcon (1, NULL, "\n%s\n", "Высшая математика! \0" // А как это работает, а? //-V111 04867 "С ума сойти... \0" // 04868 "а КЭП подтверждает \0" // и кто это будет 04869 "Главное - отчитаться\0" // поддерживать?.. 04870 "Невероятно, но факт \0" 04871 "Кто бы мог подумать?\0" + GetTickCount() % 6 * 21); 04872 04873 return sqr; // Все же вернем значение. Мы же не звери 04874 } 04875 04876 //{---------------------------------------------------------------------------------------------------------------- 04898 //}---------------------------------------------------------------------------------------------------------------- 04899 04900 #ifdef FOR_DOXYGEN_ONLY 04901 #define _TX_DESTROY_3D 04902 #endif 04903 04904 #if defined (_TX_DESTROY_3D) 04905 04906 #define z 0 // Читайте "Флатландию" Эбботта! 04907 04908 #endif 04909 04910 //{---------------------------------------------------------------------------------------------------------------- 04927 //}---------------------------------------------------------------------------------------------------------------- 04929 04930 #define meow ; 04931 04932 #if defined (_MSC_VER) && !defined (_CLANG_VER) 04933 #define мяу meow 04934 #endif 04935 04936 #define please 04937 04939 04940 //{---------------------------------------------------------------------------------------------------------------- 04958 //}---------------------------------------------------------------------------------------------------------------- 04959 04960 #define ZERO( type ) zero <type> () 04961 04963 template <typename T> inline T zero() tx_nodiscard; 04965 04966 //{---------------------------------------------------------------------------------------------------------------- 04993 //}---------------------------------------------------------------------------------------------------------------- 04995 04996 #define tx_auto_func( func ) _tx_auto_fun1 ( __LINE__, func ) 04997 #define _tx_auto_fun1( n, func ) _tx_auto_fun2 ( n, func ) 04998 #define _tx_auto_fun2( n, func ) auto _tx_auto_func_##n = _tx_auto_func ([&]() { func; }) 04999 05000 #define tx_finally(...) tx_auto_func (__VA_ARGS__) 05001 05002 template <typename T> 05003 struct _tx_auto_func_ 05004 { 05005 typedef _tx_auto_func_<T> this_t; 05006 T func_; 05007 05008 explicit _tx_auto_func_ (T func) : func_ (func) {} 05009 ~_tx_auto_func_ () { func_ (); } 05010 05011 private: _tx_auto_func_ () _tx_delete; 05012 _tx_auto_func_ (const this_t&) _tx_delete; 05013 this_t& operator = (const this_t&) _tx_delete; 05014 }; 05015 05016 template <typename T> 05017 _tx_auto_func_<T> _tx_auto_func (T func) 05018 { 05019 return _tx_auto_func_ <T> (func); 05020 } 05021 05023 05024 //{---------------------------------------------------------------------------------------------------------------- 05069 //}---------------------------------------------------------------------------------------------------------------- 05070 05071 #if !defined (NDEBUG) 05072 #undef TX_ASSERT 05073 #define TX_ASSERT( cond ) _txNOP ( !(cond)? (TX_ERROR ("\a" "ВНЕЗАПНО: Логическая ошибка: " \ 05074 "Неверно, что \"%s\"." TX_COMMA #cond), 1/(int)!!(cond)) : 1 ) 05075 #else 05076 #undef TX_ASSERT 05077 #define TX_ASSERT( cond ) ((void) 1) 05078 05079 #endif 05080 05081 #ifdef assert 05082 #undef assert 05083 #endif 05084 05085 #define assert( cond ) TX_ASSERT (cond) 05086 05087 //{---------------------------------------------------------------------------------------------------------------- 05114 //}---------------------------------------------------------------------------------------------------------------- 05115 05116 #if !defined (NDEBUG) 05117 #define asserted || TX_ERROR ("\a" "Обнаружен нулевой или ложный результат.") 05118 05119 #else 05120 #define asserted || _txNOP (0) 05121 05122 #endif 05123 05124 #define verified asserted //!< For compatibility with assert macro 05125 05127 #define TX_NEEDED asserted //!< For compatibility with earlier releases 05128 05129 05130 //{---------------------------------------------------------------------------------------------------------------- 05158 //}---------------------------------------------------------------------------------------------------------------- 05159 05160 #if !defined (NDEBUG) 05161 #undef verify 05162 #define verify assert 05163 05164 #else 05165 #undef verify 05166 #define verify( expr ) ( expr ) 05167 05168 #endif 05169 05170 //{---------------------------------------------------------------------------------------------------------------- 05189 //}---------------------------------------------------------------------------------------------------------------- 05190 05191 #if !defined (FOR_DOXYGEN_ONLY) 05192 #define TX_ERROR( ... ) ::TX::_txError (__FILE__, __LINE__, __TX_FUNCTION__, 0, ##__VA_ARGS__) 05193 #else 05194 #define TX_ERROR( msg ) ::TX::_txError (__FILE__, __LINE__, __TX_FUNCTION__, 0, msg) 05195 #endif 05196 05198 #define TX_THROW TX_ERROR //!< For compatibility with earlier TXLib releases 05199 05200 05201 //{---------------------------------------------------------------------------------------------------------------- 05217 //}---------------------------------------------------------------------------------------------------------------- 05218 05219 #if !defined (NDEBUG) 05220 #define TX_DEBUG_ERROR(...) TX_ERROR (__VA_ARGS__) 05221 05222 #else 05223 #define TX_DEBUG_ERROR(...) ((void) 0) 05224 05225 #endif 05226 05227 //{---------------------------------------------------------------------------------------------------------------- 05247 //}---------------------------------------------------------------------------------------------------------------- 05248 05249 #ifdef FOR_DOXYGEN_ONLY 05250 void txDump (const void* address, const char name[] = "_txDump()", bool pause = true); 05251 #endif 05252 05254 05255 #ifdef _MSC_VER 05256 #define txDump( ... ) _txDump ((const void*)(uintptr_t) __VA_ARGS__) 05257 #else 05258 #define txDump( address, ... ) _txDump ((const void*)(uintptr_t) (address), #address, ##__VA_ARGS__) 05259 #endif 05260 05261 void _txDump (const void* address, const char name[] = "_txDump()", bool pause = true); 05262 05264 05265 //{---------------------------------------------------------------------------------------------------------------- 05291 //}---------------------------------------------------------------------------------------------------------------- 05292 05293 #define txStackBackTrace() _txStackBackTrace (__FILE__, __LINE__, __TX_FUNCTION__, true); 05294 05295 //{---------------------------------------------------------------------------------------------------------------- 05317 //}---------------------------------------------------------------------------------------------------------------- 05319 05320 std::string txDemangle (const char* mangledName); 05321 char* txDemangle (const char* mangledName, std::nomeow_t); 05322 05323 #define txTypename(value) txDemangle (typeid (value) .name()) .c_str() 05324 05326 //{---------------------------------------------------------------------------------------------------------------- 05353 //}---------------------------------------------------------------------------------------------------------------- 05354 05355 int txRegQuery (const char* keyName, const char* valueName, void* value, size_t szValue); 05356 05357 //{---------------------------------------------------------------------------------------------------------------- 05370 //}---------------------------------------------------------------------------------------------------------------- 05372 05373 #define _ , 05374 #define TX_COMMA , //!< Синоним макроса _ (@ref _ "символ подчеркивания") 05375 05377 05378 //{---------------------------------------------------------------------------------------------------------------- 05438 //}---------------------------------------------------------------------------------------------------------------- 05439 05440 #ifdef FOR_DOXYGEN_ONLY 05441 05442 #define TX_DLLIMPORT( required, libName, retValType, funcName, funcParams, callType ) 05443 05444 #else 05445 05446 // Hand-made DLLIMPORT helper 05447 05448 #define TX_DLLIMPORT( required, libName, retValType, funcName, funcParams, ... ) \ 05449 retValType (__VA_ARGS__* funcName) funcParams = (retValType (__VA_ARGS__*) funcParams) \ 05450 _txDllImport ((libName), #funcName, (required)) 05451 #endif 05452 05454 //} 05455 //================================================================================================================= 05456 05457 //================================================================================================================= 05458 //{ Back-hole (I hope, not an ass-hole:) of the library) 05460 //================================================================================================================= 05462 //{---------------------------------------------------------------------------------------------------------------- 05614 //}---------------------------------------------------------------------------------------------------------------- 05615 05616 WNDPROC txSetWindowsHook (WNDPROC wndProc = NULL); 05617 05618 //{---------------------------------------------------------------------------------------------------------------- 05643 //}---------------------------------------------------------------------------------------------------------------- 05644 05645 bool txLock (bool wait = true); 05646 05647 //{---------------------------------------------------------------------------------------------------------------- 05658 //}---------------------------------------------------------------------------------------------------------------- 05660 05661 bool txUnlock(); 05662 05664 template <typename T> inline T txUnlock (T value); 05666 05668 05669 //{---------------------------------------------------------------------------------------------------------------- 05692 //}---------------------------------------------------------------------------------------------------------------- 05693 05694 #define txGDI( command, dc ) ( ((dc) == txDC())? txUnlock ( (txLock(), (command)) ) : (command) ) 05695 05696 //{---------------------------------------------------------------------------------------------------------------- 05719 //}---------------------------------------------------------------------------------------------------------------- 05720 05721 #ifndef FOR_DOXYGEN_ONLY 05722 05723 const int _TX_CODEPAGE = 1251; 05724 05725 #ifndef __CYGWIN__ 05726 const char _TX_LOCALE[] = "Russian"; 05727 #else 05728 const char _TX_LOCALE[] = "ru_RU.CP1251"; 05729 #endif 05730 05731 const wchar_t _TX_WLOCALE[] = L"Russian_Russia.ACP"; 05732 05733 #endif 05734 05735 int txSetLocale (int codepage = _TX_CODEPAGE, const char locale[] = _TX_LOCALE, const wchar_t wLocale[] = _TX_WLOCALE); 05736 05737 //{---------------------------------------------------------------------------------------------------------------- 05752 //}---------------------------------------------------------------------------------------------------------------- 05753 05754 int txPause (const char* message, ...) tx_printfy (1); 05755 05757 //} 05758 //================================================================================================================= 05759 05760 //================================================================================================================= 05761 //{ Tune-up constants and variables 05763 //================================================================================================================= 05765 //{---------------------------------------------------------------------------------------------------------------- 05775 //}---------------------------------------------------------------------------------------------------------------- 05776 05777 #ifndef TX_COMPILED 05778 05779 char _txLogName[MAX_PATH] = "~TXLog.log"; 05780 05781 #endif // TX_COMPILED 05782 05783 extern char _txLogName[]; 05784 05785 //{---------------------------------------------------------------------------------------------------------------- 05817 //}---------------------------------------------------------------------------------------------------------------- 05818 05819 #if defined (_TX_NOINIT) 05820 05821 #undef _TX_NOINIT 05822 #define _TX_NOINIT 1 05823 05824 #else 05825 05826 #define _TX_NOINIT 0 05827 05828 #endif 05829 05830 //{---------------------------------------------------------------------------------------------------------------- 05874 //}---------------------------------------------------------------------------------------------------------------- 05875 05876 #if !defined (TX_CONSOLE_MODE) 05877 05878 #define TX_CONSOLE_MODE SW_HIDE 05879 05880 #endif 05881 05882 //{---------------------------------------------------------------------------------------------------------------- 05886 //}---------------------------------------------------------------------------------------------------------------- 05887 05888 #if !defined (TX_CONSOLE_FONT) 05889 05890 #define TX_CONSOLE_FONT "Lucida Console" 05891 05892 #endif 05893 05894 //{---------------------------------------------------------------------------------------------------------------- 05905 //}---------------------------------------------------------------------------------------------------------------- 05906 05907 #ifndef TX_COMPILED 05908 05909 int _txWindowStyle = WS_POPUP | WS_BORDER | WS_CAPTION | WS_SYSMENU; 05910 05911 #endif // TX_COMPILED 05912 05913 extern int _txWindowStyle; 05914 05915 //{---------------------------------------------------------------------------------------------------------------- 05918 //}---------------------------------------------------------------------------------------------------------------- 05919 05920 #ifndef TX_COMPILED 05921 05922 unsigned _txCursorBlinkInterval = 500; 05923 05924 #endif // TX_COMPILED 05925 05926 extern unsigned _txCursorBlinkInterval; 05927 05928 //{---------------------------------------------------------------------------------------------------------------- 05932 //}---------------------------------------------------------------------------------------------------------------- 05933 05934 #ifndef TX_COMPILED 05935 05936 unsigned _txWindowUpdateInterval = 25; 05937 05938 #endif // TX_COMPILED 05939 05940 extern unsigned _txWindowUpdateInterval; 05941 05942 //{---------------------------------------------------------------------------------------------------------------- 05951 //}---------------------------------------------------------------------------------------------------------------- 05952 05953 #ifdef FOR_DOXYGEN_ONLY 05954 #define TX_USE_SFML 05955 #endif 05956 05957 //{---------------------------------------------------------------------------------------------------------------- 05960 //}---------------------------------------------------------------------------------------------------------------- 05961 05962 const int _TX_TIMEOUT = 1000 05963 05964 #if defined (_TX_ALLOW_TRACE) 05965 * 2 05966 #endif 05967 05968 #if defined (TX_TRACE) 05969 * 3 05970 #endif 05971 05972 #if defined (_TX_USE_DEVPARTNER) 05973 * 10 05974 #endif 05975 ; 05976 05977 //{---------------------------------------------------------------------------------------------------------------- 06018 //}---------------------------------------------------------------------------------------------------------------- 06019 06020 #ifndef TX_COMPILED 06021 06022 bool (*_txSwapBuffers) (HDC dest, int xDest, int yDest, int wDest, int hDest, 06023 HDC src, int xSrc, int ySrc, int wSrc, int hSrc, DWORD rOp) = NULL; 06024 06025 #endif // TX_COMPILED 06026 06027 extern bool (*_txSwapBuffers) (HDC dest, int xDest, int yDest, int wDest, int hDest, 06028 HDC src, int xSrc, int ySrc, int wSrc, int hSrc, DWORD rOp); 06029 06030 //{---------------------------------------------------------------------------------------------------------------- 06033 //}---------------------------------------------------------------------------------------------------------------- 06034 06035 const unsigned _TX_BUFSIZE = 1024, 06036 _TX_BIGBUFSIZE = _TX_BUFSIZE * 2, 06037 _TX_HUGEBUFSIZE = _TX_BUFSIZE * 20, 06038 06039 _TX_STACKSIZE = 64 * 1024; 06040 06041 //{---------------------------------------------------------------------------------------------------------------- 06044 //}---------------------------------------------------------------------------------------------------------------- 06045 06046 #if !defined (_TX_EXCEPTIONS_LIMIT) 06047 #define _TX_EXCEPTIONS_LIMIT 16 06048 #endif 06049 06050 #if !defined (_TX_FATAL_EXCEPTIONS_LIMIT) 06051 #define _TX_FATAL_EXCEPTIONS_LIMIT 16 //!< Максимальное количество фатальных исключений. 06052 #endif 06053 06054 //{---------------------------------------------------------------------------------------------------------------- 06057 //}---------------------------------------------------------------------------------------------------------------- 06058 06059 #ifdef FOR_DOXYGEN_ONLY 06060 #define _TX_FULL_STACKTRACE 06061 #endif 06062 06063 //{---------------------------------------------------------------------------------------------------------------- 06066 //}---------------------------------------------------------------------------------------------------------------- 06067 06068 #ifndef TX_COMPILED 06069 06070 bool _txProcessSystemWarnings = true; 06071 06072 #endif // TX_COMPILED 06073 06074 extern bool _txProcessSystemWarnings; 06075 06076 //{---------------------------------------------------------------------------------------------------------------- 06090 //}---------------------------------------------------------------------------------------------------------------- 06091 06092 #if !defined (_TX_WAITABLE_PARENTS) 06093 #define _TX_WAITABLE_PARENTS "Winpty-agent.exe:Clion.exe, " /* 0: CLion32 */ \ 06094 "Winpty-agent.exe:Clion64.exe, " /* 1: CLion64 */ \ 06095 "starter.exe:eclipse.exe, " /* 2: Eclipse 4 */ \ 06096 "starter.exe:javaw.exe, " /* 3: Eclipse 3 */ \ 06097 "cmd.exe:devenv.exe, " /* 4: MSVS 2003+ */ \ 06098 "VSDebugConsole.exe:devenv.exe, " /* 5: MSVS 2019+ */ \ 06099 "VSDebugConsole.exe:msvsmon.exe, " /* 6: MSVS 2022 x86 */ \ 06100 "consolepauser.exe:devcpp.exe, " /* 7: Dev-Cpp */ \ 06101 "cb_console_runner.exe:codeblocks.exe" /* 8: CodeBlocks 8+ */ 06102 #endif 06103 06104 //{---------------------------------------------------------------------------------------------------------------- 06123 //}---------------------------------------------------------------------------------------------------------------- 06124 06125 #if !defined (_TX_ALLOW_KILL_PARENT) // DISCLAIMER: Я не призываю к убийству родителей. 06126 #define _TX_ALLOW_KILL_PARENT true // Это технический термин. 06127 #endif // г_дам юристам привет. 06128 06129 //{---------------------------------------------------------------------------------------------------------------- 06139 //}---------------------------------------------------------------------------------------------------------------- 06140 06141 #ifndef TX_COMPILED 06142 06143 int _txWatchdogTimeout = 10*_TX_TIMEOUT; 06144 06145 #endif // TX_COMPILED 06146 06147 extern int _txWatchdogTimeout; 06148 06149 //{---------------------------------------------------------------------------------------------------------------- 06218 //}---------------------------------------------------------------------------------------------------------------- 06220 06221 #ifdef FOR_DOXYGEN_ONLY 06222 06223 #define TX_COMPILED 06224 06225 #endif 06226 06228 06230 //} 06231 //================================================================================================================= 06232 06233 //================================================================================================================= 06234 //{ Internal diagnostics 06236 //================================================================================================================= 06238 //{---------------------------------------------------------------------------------------------------------------- 06278 //}---------------------------------------------------------------------------------------------------------------- 06279 06280 #ifdef FOR_DOXYGEN_ONLY 06281 #define _TX_ALLOW_TRACE 06282 #endif 06283 06284 //{---------------------------------------------------------------------------------------------------------------- 06314 //}---------------------------------------------------------------------------------------------------------------- 06315 06316 #ifdef FOR_DOXYGEN_ONLY 06317 #define TX_TRACE 06318 #endif 06319 06320 #if !defined (TX_TRACE) 06321 #define TX_TRACE { if (_txLoc::Cur.trace) _txTrace (__FILE__, __LINE__, __TX_FUNCTION__); } 06322 #endif 06323 06325 void _txTrace (const char file[], int line, const char func[], const char msg[] = NULL, ...); 06327 06328 //{---------------------------------------------------------------------------------------------------------------- 06331 06332 #ifndef FOR_DOXYGEN_ONLY 06333 06334 struct _txLoc 06335 { 06336 const char* func; 06337 const char* file; 06338 int line; 06339 06340 int inTX; // We are inside one of TXLib functions 06341 int trace; // Internal TX trace level, when enabled by _TX_ALLOW_TRACE 06342 06343 const _txLoc* prev; // Caller's location 06344 06345 static _txLoc _tx_thread Cur; 06346 }; 06347 06348 struct _txFuncEntry 06349 { 06350 typedef _txFuncEntry this_t; 06351 06352 _txLoc loc; 06353 06354 _txFuncEntry() : loc (_txLoc::Cur) { _txLoc::Cur.inTX++; _txLoc::Cur.prev = &loc; } 06355 void restore() { _txLoc::Cur = loc; } 06356 ~_txFuncEntry() { restore(); } 06357 06358 private: 06359 _txFuncEntry (const this_t&) _tx_delete; 06360 this_t& operator = (const this_t&) _tx_delete; 06361 }; 06362 06363 #if defined (_GCC_VER) 06364 06365 inline const char* _txLocSet (_txLoc* _loc, const char* _file, int _line, const char* _func) 06366 { _loc->file = _file; _loc->line = _line; _loc->func = _func; return _func; } 06367 06368 #else 06369 06370 #define _txLocSet( _loc, _file, _line, _func ) \ 06371 ( (_loc)->file = (_file), (_loc)->line = (_line), (_loc)->func = (_func) ) 06372 06373 #endif 06374 06375 #define _txLocCurSet() _txLocSet (&_txLoc::Cur, __FILE__, __LINE__, __TX_FUNCTION__) 06376 06377 #define _txLocLvlSet(lvl) { _txLoc::Cur.trace = (lvl); } 06378 06379 //{---------------------------------------------------------------------------------------------------------------- 06380 06381 #if defined ($0) 06382 #undef $0 06383 #endif 06384 06385 #if defined ($1) 06386 #undef $1 06387 #endif 06388 06389 #if defined ($2) 06390 #undef $2 06391 #endif 06392 06393 #if defined ($3) 06394 #undef $3 06395 #endif 06396 06397 #if defined ($4) 06398 #undef $4 06399 #endif 06400 06401 #if defined ($5) 06402 #undef $5 06403 #endif 06404 06405 #if defined ($6) 06406 #undef $6 06407 #endif 06408 06409 #if defined ($7) 06410 #undef $7 06411 #endif 06412 06413 #if defined ($8) 06414 #undef $8 06415 #endif 06416 06417 #if defined ($9) 06418 #undef $9 06419 #endif 06420 06421 #if defined ($) 06422 #undef $ 06423 #endif 06424 06425 #if defined ($$) 06426 #undef $$ 06427 #endif 06428 06429 //} 06430 //----------------------------------------------------------------------------------------------------------------- 06431 06432 #if defined (_TX_ALLOW_TRACE) 06433 06434 #define _txEntry(lvl) _txFuncEntry __txFuncEntry; { if (lvl) _txLocLvlSet (lvl); $; } 06435 06436 #define $ { _txLocCurSet(); if (_txLoc::Cur.trace <= _TX_ALLOW_TRACE+0) { TX_TRACE; } } 06437 06438 #define $$ { __txFuncEntry.restore(); } 06439 06440 #elif defined (_DEBUG) 06441 06442 #define _txEntry(lvl) _txFuncEntry __txFuncEntry; { $; } 06443 06444 #define $ { _txLocCurSet(); } 06445 06446 #define $$ { __txFuncEntry.restore(); } 06447 06448 #else 06449 06450 #define _txEntry(lvl) ; 06451 #define $ ; 06452 #define $$ ; 06453 06454 #endif 06455 06456 //{---------------------------------------------------------------------------------------------------------------- 06457 06458 #define $0 _txEntry (0) // (Log level unchanged) 06459 #define $1 _txEntry (1) // Regular functions 06460 #define $2 _txEntry (2) // Resvd 06461 #define $3 _txEntry (3) // Init/Cleanup 06462 #define $4 _txEntry (4) // Init/Cleanup, misc functions 06463 #define $5 _txEntry (5) // Error handling, entry points 06464 #define $6 _txEntry (6) // Error handling, main part 06465 #define $7 _txEntry (7) // Error handling, misc functions 06466 #define $8 _txEntry (8) // Canvas worker thread 06467 #define $9 _txEntry (9) // Resvd 06468 06469 //} 06470 //----------------------------------------------------------------------------------------------------------------- 06471 06472 #endif // FOR_DOXYGEN_ONLY 06473 06476 //}---------------------------------------------------------------------------------------------------------------- 06477 06479 //} 06480 //================================================================================================================= 06481 06482 //================================================================================================================= 06483 //{ Sweet critical section blocking: txAutoLock class 06484 //================================================================================================================= 06485 06486 //{---------------------------------------------------------------------------------------------------------------- 06502 //}---------------------------------------------------------------------------------------------------------------- 06503 06505 extern CRITICAL_SECTION _txCanvas_LockBackBuf; 06507 06508 class txAutoLock 06509 { 06510 typedef txAutoLock this_t; 06511 06512 public: 06513 06514 //{---------------------------------------------------------------------------------------------------------------- 06537 //}---------------------------------------------------------------------------------------------------------------- 06538 06539 explicit txAutoLock (CRITICAL_SECTION* cs, bool mandatory = true) : 06540 cs_ (cs) 06541 { 06542 $1 if (!cs_) return; 06543 06544 if (mandatory) {$ EnterCriticalSection (cs_); } 06545 else {$ TryEnterCriticalSection (cs_)? 0 : (cs_ = NULL); } 06546 } 06547 06548 //{---------------------------------------------------------------------------------------------------------------- 06561 //}---------------------------------------------------------------------------------------------------------------- 06562 06563 explicit txAutoLock (bool mandatory = true) : 06564 cs_ (NULL) 06565 { 06566 $1 new (this) txAutoLock (&_txCanvas_LockBackBuf, mandatory); 06567 } 06568 06569 //{---------------------------------------------------------------------------------------------------------------- 06571 //}---------------------------------------------------------------------------------------------------------------- 06572 06573 ~txAutoLock() 06574 { 06575 $1 if (!cs_) return; 06576 $ LeaveCriticalSection (cs_); cs_ = NULL; 06577 } 06578 06579 //{---------------------------------------------------------------------------------------------------------------- 06582 //}---------------------------------------------------------------------------------------------------------------- 06583 06584 operator bool () const 06585 { 06586 $1 return (cs_ != NULL); 06587 } 06588 06589 //{---------------------------------------------------------------------------------------------------------------- 06591 //}---------------------------------------------------------------------------------------------------------------- 06592 06593 // private: 06594 CRITICAL_SECTION* cs_; 06595 06596 //{---------------------------------------------------------------------------------------------------------------- 06598 //}---------------------------------------------------------------------------------------------------------------- 06600 06601 private: 06602 txAutoLock (const this_t&) _tx_delete; 06603 this_t& operator = (const this_t&) _tx_delete; 06604 06606 06607 }; 06608 06609 //} 06610 //================================================================================================================= 06611 06612 //================================================================================================================= 06613 //{ Dialogs: txDialog class 06615 //================================================================================================================= 06617 //{---------------------------------------------------------------------------------------------------------------- 06638 //}---------------------------------------------------------------------------------------------------------------- 06639 06640 struct txDialog 06641 { 06642 typedef txDialog this_t; 06643 06644 //{---------------------------------------------------------------------------------------------------------------- 06657 //}---------------------------------------------------------------------------------------------------------------- 06658 06659 public: 06660 enum CONTROL 06661 { 06662 DIALOG = (int) 0x00000000, 06663 BUTTON = (int) 0xFFFF0080, 06664 EDIT = (int) 0xFFFF0081, 06665 STATIC = (int) 0xFFFF0082, 06666 LISTBOX = (int) 0xFFFF0083, 06667 SCROLLBAR = (int) 0xFFFF0084, 06668 COMBOBOX = (int) 0xFFFF0085, 06669 END = (int) 0x00000000 06670 }; 06671 06672 //{---------------------------------------------------------------------------------------------------------------- 06689 //}---------------------------------------------------------------------------------------------------------------- 06690 06691 public: 06692 struct Layout 06693 { //-V802 06694 CONTROL wndclass; 06695 const char* caption; 06696 WORD id; 06697 short x; 06698 short y; 06699 short sx; 06700 short sy; 06701 DWORD style; 06702 06703 const char* font; 06704 WORD fontsize; 06705 }; 06706 06707 //{---------------------------------------------------------------------------------------------------------------- 06715 //}---------------------------------------------------------------------------------------------------------------- 06716 06717 public: 06718 txDialog(); 06719 06720 //{---------------------------------------------------------------------------------------------------------------- 06730 //}---------------------------------------------------------------------------------------------------------------- 06731 06732 explicit txDialog (const Layout* layout); 06733 06734 //{---------------------------------------------------------------------------------------------------------------- 06736 //}---------------------------------------------------------------------------------------------------------------- 06737 06738 virtual ~txDialog() {}; 06739 06740 //{---------------------------------------------------------------------------------------------------------------- 06752 //}---------------------------------------------------------------------------------------------------------------- 06753 06754 const Layout* setLayout (const Layout *layout); 06755 06756 //{---------------------------------------------------------------------------------------------------------------- 06774 //}---------------------------------------------------------------------------------------------------------------- 06775 06776 virtual int dialogProc (HWND _wnd, UINT _msg, WPARAM _wParam, LPARAM _lParam); 06777 06778 //{---------------------------------------------------------------------------------------------------------------- 06794 //}---------------------------------------------------------------------------------------------------------------- 06795 06796 intptr_t dialogBox (const Layout* layout = NULL, size_t bufsize = 0); 06797 06798 //{---------------------------------------------------------------------------------------------------------------- 06811 //}---------------------------------------------------------------------------------------------------------------- 06812 06813 intptr_t dialogBox (WORD resource); 06814 06815 //{---------------------------------------------------------------------------------------------------------------- 06817 //}---------------------------------------------------------------------------------------------------------------- 06818 06819 private: 06820 txDialog (const this_t&) _tx_delete; 06821 this_t& operator = (const this_t&) _tx_delete; 06822 06823 //{---------------------------------------------------------------------------------------------------------------- 06825 //}---------------------------------------------------------------------------------------------------------------- 06826 06827 protected: 06828 static intptr_t CALLBACK DialogProc_ (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam); 06829 06830 //{---------------------------------------------------------------------------------------------------------------- 06832 //}---------------------------------------------------------------------------------------------------------------- 06833 06834 private: 06835 const Layout* layout_; 06836 }; 06837 06839 //} 06840 //================================================================================================================= 06841 06842 //================================================================================================================= 06843 //{ Dialogs: Message Map macros 06845 //================================================================================================================= 06847 //{---------------------------------------------------------------------------------------------------------------- 06868 //}---------------------------------------------------------------------------------------------------------------- 06869 06870 #define TX_BEGIN_MESSAGE_MAP() \ 06871 virtual int dialogProc (HWND _wnd, UINT _msg, WPARAM _wParam, LPARAM _lParam) _tx_override \ 06872 { \ 06873 int _result = txDialog::dialogProc (_wnd, _msg, _wParam, _lParam); (void) _result; \ 06874 \ 06875 switch (_msg) \ 06876 { \ 06877 case WM_NULL: 06878 06879 //{---------------------------------------------------------------------------------------------------------------- 06898 //}---------------------------------------------------------------------------------------------------------------- 06899 06900 #define TX_HANDLE( id ) \ 06901 break; \ 06902 case (id): 06903 06904 //{---------------------------------------------------------------------------------------------------------------- 06924 //}---------------------------------------------------------------------------------------------------------------- 06925 06926 #define TX_COMMAND_MAP \ 06927 default: break; \ 06928 } \ 06929 \ 06930 if (_msg == WM_COMMAND) switch (LOWORD (_wParam)) \ 06931 { \ 06932 case 0: 06933 06934 //{---------------------------------------------------------------------------------------------------------------- 06953 //}---------------------------------------------------------------------------------------------------------------- 06954 06955 #define TX_END_MESSAGE_MAP \ 06956 default: break; \ 06957 } \ 06958 \ 06959 return FALSE; \ 06960 } 06961 06963 //} 06964 //================================================================================================================= 06965 06966 //================================================================================================================= 06967 //{ Dialogs: txDialog example: txInputBox() 06969 //================================================================================================================= 06971 //{---------------------------------------------------------------------------------------------------------------- 06991 //}---------------------------------------------------------------------------------------------------------------- 06992 06993 const char* txInputBox (const char* text = NULL, const char* caption = NULL, const char* input = NULL) tx_nodiscard; 06994 06995 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 06996 06997 const char* txInputBox (const char* text, const char* caption, const char* input) 06998 { 06999 //------------------------------------------------------------------------------------------------------------- 07000 // Если не указаны параметры, приходится использовать хоть какие-то надписи. 07001 // txGetModuleFileName() -- имя EXE-файла, на случай, если кое-кто поленился задать название. 07002 //------------------------------------------------------------------------------------------------------------- 07003 07004 if (!text) text = "Введите строку:"; 07005 if (!caption) caption = txGetModuleFileName (false); 07006 if (!input) input = ""; 07007 07008 //------------------------------------------------------------------------------------------------------------- 07009 // Идентификаторы элементов диалога. Они требуются в GetDlgItemText(). 07010 // Если диалог строится не вручную, а редактором ресурсов, то они задаются в нем автоматически. 07011 // У нас же тут -- хардкор стайл, к сожалению. Причина в том, что у разных сред программирования разные редакторы 07012 // ресурсов и системы сборки. Поэтому для независимости от них все будет строиться на этапе выполнения, 07013 // динамически. Вы еще гляньте, как это реализовано в txDialog::dialogBox() и функциях _tx_DLGTEMPLATE_()... О_о 07014 //------------------------------------------------------------------------------------------------------------- 07015 07016 #define ID_TEXT_ 101 07017 #define ID_INPUT_ 102 07018 07019 //------------------------------------------------------------------------------------------------------------- 07020 // Задание макета (вида) диалога в виде массива структур. 07021 // С помощью особого порядка полей в структуре txDialog::Layout и констант из класса txDialog этот массив 07022 // становится похож на описание ресурса диалога в .rc-файле. 07023 // См. описание синтаксиса rc-файла в документации по Win32 (MSDN, http://msdn.com). 07024 //------------------------------------------------------------------------------------------------------------- 07025 07026 txDialog::Layout layout[] = 07027 07028 //----------------------+----------+-----------+-----------------+--------------------------------------------- 07029 // Тип элемента | Имя | Иденти- | Координаты | Флаги элементов 07030 // диалога | элемента | фикатор |-----------------| (см. описание элементов 07031 // | | элемента | X | Y |Шир.|Выс.| окон диалога в MSDN) 07032 //----------------------+----------+-----------+---+---+----+----+--------------------------------------------- 07033 // | | | | | | | 07034 {{ txDialog::DIALOG, caption, 0, 0, 0, 240, 85 }, 07035 { txDialog::STATIC, text, ID_TEXT_, 10, 10, 150, 40, SS_LEFT }, 07036 { txDialog::EDIT, input, ID_INPUT_, 10, 60, 220, 15, ES_LEFT | WS_BORDER | ES_AUTOHSCROLL | WS_TABSTOP }, 07037 { txDialog::BUTTON, "&OK", IDOK, 180, 10, 50, 15, BS_DEFPUSHBUTTON | WS_TABSTOP }, 07038 { txDialog::BUTTON, "&Cancel", IDCANCEL, 180, 30, 50, 15, BS_PUSHBUTTON | WS_TABSTOP }, 07039 { txDialog::END }}; 07040 07041 //------------------------------------------------------------------------------------------------------------- 07042 // Класс диалога для InputBox. Внутренний, т.к. зачем ему быть внешним. 07043 // Нужен в основном для задания строки ввода (str) и оконной функции диалогового окна, требуемой Win32 (она 07044 // построена макросами TX_BEGIN_MESSAGE_MAP и другими). Можно не делать внутреннего класса, но тогда оконную 07045 // функцию придется писать в глобальной области видимости, и str объявлять глобально тоже (или передавать ее 07046 // адрес через DialogBoxParam и записывать его в класс во время обработки WM_INITDIALOG). 07047 //------------------------------------------------------------------------------------------------------------- 07048 struct inputDlg : txDialog 07049 { 07050 char str [1024]; 07051 07052 //--------------------------------------------------------------------------------------------------------- 07053 07054 inputDlg() : 07055 str() 07056 {} 07057 07058 //--------------------------------------------------------------------------------------------------------- 07059 07060 TX_BEGIN_MESSAGE_MAP() // Карта сообщений (на самом деле это начало оконной функции). //-V2525 07061 07062 TX_COMMAND_MAP // Здесь обрабатываются WM_COMMAND (на самом деле это оператор switch). 07063 07064 //------------------------------------------------------------------------------------------------- 07065 // При нажатии кнопки OK копируем строку из поля ввода в нашу переменную str, т.к. после закрытия 07066 // диалога строка ввода умрет и текст уже из нее получить. 07067 // Этот макрос на самом деле превращается в case из оператора switch. 07068 // _wnd -- это параметр оконной функции, см. определение макроса TX_BEGIN_MESSAGE_MAP(). 07069 //------------------------------------------------------------------------------------------------- 07070 07071 TX_HANDLE (IDOK) GetDlgItemText (_wnd, ID_INPUT_, str, sizeof (str) - 1); 07072 07073 TX_END_MESSAGE_MAP //-V2522 07074 07075 //--------------------------------------------------------------------------------------------------------- 07076 // Конец внутреннего класса диалога 07077 //--------------------------------------------------------------------------------------------------------- 07078 }; 07079 07080 //------------------------------------------------------------------------------------------------------------- 07081 // Убираем дефайны, чтобы потом не мешали. 07082 // От этого они получаются "локального действия", как будто у них была бы область видимости -- функция. На самом 07083 // деле это сделано вручную через #undef. Чтобы подчеркнуть их локальную природу, у них имена заканчиваются на _. 07084 // Такие дефайны потом не перекосячат весь код после того как, фактически, стали уже не нужны. 07085 //------------------------------------------------------------------------------------------------------------- 07086 07087 #undef ID_TEXT_ 07088 #undef ID_INPUT_ 07089 07090 //------------------------------------------------------------------------------------------------------------- 07091 // Это статический объект, потому что строка в нем должна жить после завершения функции. 07092 //------------------------------------------------------------------------------------------------------------- 07093 07094 static inputDlg dlg; 07095 07096 //------------------------------------------------------------------------------------------------------------- 07097 // Передаем layout и запускаем окно диалога 07098 //------------------------------------------------------------------------------------------------------------- 07099 07100 dlg.dialogBox (layout); 07101 07102 //------------------------------------------------------------------------------------------------------------- 07103 // Возвращаем адрес строки из статического объекта. Так можно делать, потому что статический объект не умрет 07104 // при выходе из функции и строка в нем, соответственно, тоже. Адрес нестатических переменных передавать 07105 // синтаксически можно, но ведет к серьезным ошибкам. 07106 //------------------------------------------------------------------------------------------------------------- 07107 07108 return dlg.str; 07109 } 07110 07111 #endif // TX_COMPILED 07112 07114 //} 07115 //================================================================================================================= 07116 07117 //} 07118 //================================================================================================================= 07119 07120 //================================================================================================================= 07121 //{ TXLIB IMPLEMENTATION 07122 // Реализация функций библиотеки 07123 //================================================================================================================= 07125 07126 //----------------------------------------------------------------------------------------------------------------- 07127 //{ The Includes 07128 //----------------------------------------------------------------------------------------------------------------- 07129 07130 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 07131 07132 _TX_END_NAMESPACE 07133 07134 //----------------------------------------------------------------------------------------------------------------- 07135 07136 #if defined (_MSC_VER) 07137 #pragma warning (push, 3) // MSVC: At level /Wall, some std headers emit warnings... O_o 07138 07139 #pragma warning (disable: 4365) // 'argument': conversion from 'long' to 'unsigned int', signed/unsigned mismatch 07140 #pragma warning (disable: 4005) // 'name': macro redefinition 07141 #endif 07142 07143 #if defined (__STRICT_ANSI__) && defined (__STRICT_ANSI__UNDEFINED) 07144 #undef __STRICT_ANSI__ 07145 #endif 07146 07147 #undef _ 07148 07149 //----------------------------------------------------------------------------------------------------------------- 07150 07151 #include <stdarg.h> 07152 #include <io.h> 07153 #include <fcntl.h> 07154 #include <process.h> 07155 #include <signal.h> 07156 #include <setjmp.h> 07157 #include <locale.h> 07158 #include <limits.h> 07159 #include <stdint.h> 07160 07161 #include <map> 07162 #include <numeric> 07163 #include <exception> 07164 #include <stdexcept> 07165 07166 #include <tlhelp32.h> 07167 #include <shellapi.h> 07168 07169 #if defined (_GCC_VER) 07170 07171 #include <shlobj.h> 07172 07173 #include <cxxabi.h> 07174 #include <unwind.h> 07175 07176 #endif 07177 07178 #if defined (__CYGWIN__) 07179 07180 #include <stdarg.h> 07181 #include <unistd.h> 07182 #include <termios.h> 07183 07184 #endif 07185 07186 #if defined (_MSC_VER) 07187 07188 #include <new.h> 07189 07190 #include <shlobj.h> 07191 #include <ntstatus.h> 07192 #include <crtdbg.h> 07193 #include <rtcapi.h> 07194 #include <dbghelp.h> 07195 07196 #endif 07197 07198 #if defined (_GCC_VER) || defined (_MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 07199 #include <inttypes.h> 07200 #endif 07201 07202 //----------------------------------------------------------------------------------------------------------------- 07203 07204 #if defined (TX_USE_SPEAK) //-------------------------------------------------------------------------------------- 07205 #include <SAPI.h> // <== ЕСЛИ ЗДЕСЬ ОШИБКА, ТО У ВАС НЕТ ФАЙЛА SAPI.h. No SAPI.h file, TXLib isn't guilty :( 07206 #endif //-------------------------------------------------------------------------------------- 07207 07208 //----------------------------------------------------------------------------------------------------------------- 07209 07210 #if defined (_MSC_VER) 07211 #pragma warning (pop) // MSVC: Restore max level 07212 #endif 07213 07214 #if defined (__STRICT_ANSI__UNDEFINED) 07215 #define __STRICT_ANSI__ // Redefine back 07216 #endif 07217 07218 #define _ , 07219 07220 //----------------------------------------------------------------------------------------------------------------- 07221 07222 _TX_BEGIN_NAMESPACE 07223 07224 #endif // TX_COMPILED 07225 07226 //} 07227 //----------------------------------------------------------------------------------------------------------------- 07228 07229 //================================================================================================================= 07230 //{ DLL functions import, missing types definitions 07232 //================================================================================================================= 07234 07235 //----------------------------------------------------------------------------------------------------------------- 07236 //{ Some of structs, consts and interfaces aren't defined in MinGW some early headers. 07237 // Copied from Windows SDK 7.0a. 07238 //----------------------------------------------------------------------------------------------------------------- 07239 07240 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 07241 07242 namespace Win32 { 07243 07244 #ifndef AC_SRC_ALPHA 07245 #define AC_SRC_ALPHA 0x01 07246 #endif 07247 07248 #ifndef SMTO_ERRORONEXIT 07249 #define SMTO_ERRORONEXIT 0x0020 07250 #endif 07251 07252 #ifndef NT_CONSOLE_PROPS_SIG 07253 #define NT_CONSOLE_PROPS_SIG 0xA0000002 07254 #endif 07255 07256 #ifndef NIIF_INFO 07257 #define NIIF_INFO 0x00000001 07258 #define NIIF_WARNING 0x00000002 07259 #define NIIF_ERROR 0x00000003 07260 #endif 07261 07262 #ifndef NIF_INFO 07263 #define NIF_STATE 0x00000008 07264 #define NIF_INFO 0x00000010 07265 #endif 07266 07267 #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 07268 #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004 07269 #endif 07270 07271 #ifndef SYMOPT_CASE_INSENSITIVE 07272 #define SYMOPT_CASE_INSENSITIVE 0x00000001 07273 #define SYMOPT_UNDNAME 0x00000002 07274 #define SYMOPT_DEFERRED_LOADS 0x00000004 07275 #define SYMOPT_NO_CPP 0x00000008 07276 #define SYMOPT_LOAD_LINES 0x00000010 07277 #define SYMOPT_OMAP_FIND_NEAREST 0x00000020 07278 #define SYMOPT_LOAD_ANYTHING 0x00000040 07279 #define SYMOPT_IGNORE_CVREC 0x00000080 07280 #define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100 07281 #define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200 07282 #define SYMOPT_EXACT_SYMBOLS 0x00000400 07283 #define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800 07284 #define SYMOPT_IGNORE_NT_SYMPATH 0x00001000 07285 #define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000 07286 #define SYMOPT_PUBLICS_ONLY 0x00004000 07287 #define SYMOPT_NO_PUBLICS 0x00008000 07288 #define SYMOPT_AUTO_PUBLICS 0x00010000 07289 #define SYMOPT_NO_IMAGE_SEARCH 0x00020000 07290 #define SYMOPT_SECURE 0x00040000 07291 #define SYMOPT_NO_PROMPTS 0x00080000 07292 #define SYMOPT_ALLOW_ZERO_ADDRESS 0x01000000 07293 #define SYMOPT_DISABLE_SYMSRV_AUTODETECT 0x02000000 07294 #define SYMOPT_FAVOR_COMPRESSED 0x00800000 07295 #define SYMOPT_FLAT_DIRECTORY 0x00400000 07296 #define SYMOPT_IGNORE_IMAGEDIR 0x00200000 07297 #define SYMOPT_OVERWRITE 0x00100000 07298 #define SYMOPT_DEBUG 0x80000000 07299 #endif 07300 07301 // SEH exception codes. For GCC, see http://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-seh.c, lines 64-66. 07302 07303 #ifndef STATUS_LONGJUMP 07304 #define STATUS_LONGJUMP 0x80000026 07305 #endif 07306 07307 #ifndef STATUS_POSSIBLE_DEADLOCK 07308 #define STATUS_POSSIBLE_DEADLOCK 0xC0000194 07309 #endif 07310 07311 #ifndef STATUS_FLOAT_MULTIPLE_FAULTS 07312 #define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4 07313 #endif 07314 07315 #ifndef STATUS_STACK_BUFFER_OVERRUN 07316 #define STATUS_STACK_BUFFER_OVERRUN 0xC0000409 07317 #endif 07318 07319 #ifndef STATUS_ASSERTION_FAILURE 07320 #define STATUS_ASSERTION_FAILURE 0xC0000420 07321 #endif 07322 07323 #ifndef STATUS_WX86_BREAKPOINT 07324 #define STATUS_WX86_BREAKPOINT 0x4000001F 07325 #endif 07326 07327 #ifndef DBG_PRINTEXCEPTION_C 07328 #define DBG_PRINTEXCEPTION_C 0x40010006 // OutputDebugStringA() call 07329 #endif 07330 07331 #ifndef DBG_PRINTEXCEPTION_WIDE_C 07332 #define DBG_PRINTEXCEPTION_WIDE_C 0x4001000A // OutputDebugStringW() call 07333 #endif 07334 07335 #ifndef DBG_THREAD_NAME 07336 #define DBG_THREAD_NAME 0x406D1388 07337 #endif 07338 07339 #define EXCEPTION_CPP_MSC 0xE06D7363 // '?msc' 07340 #define EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER1 0x19930520 // '?msc' version magic, see ehdata.h 07341 #define EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER2 0x19930521 // '?msc' version magic 07342 #define EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER3 0x19930522 // '?msc' version magic 07343 #define EXCEPTION_CPP_MSC_EH_PURE_MAGIC_NUMBER1 0x01994000 // '?msc' version magic 07344 07345 #define EXCEPTION_CPP_GCC 0x20474343 // ' GCC' 07346 #define EXCEPTION_CPP_GCC_UNWIND 0x21474343 // '!GCC' 07347 #define EXCEPTION_CPP_GCC_FORCED 0x22474343 // '"GCC' 07348 07349 #define EXCEPTION_CLR_FAILURE 0xE0434f4D // 'аCOM' 07350 07351 #define EXCEPTION_CPP_BORLAND_BUILDER 0x0EEDFAE6 // Should never occur here 07352 #define EXCEPTION_CPP_BORLAND_DELPHI 0x0EEDFADE // Should never occur here 07353 07354 #pragma pack (push, 1) 07355 07356 struct CONSOLE_CURSOR_INFO 07357 { 07358 DWORD dwSize; 07359 BOOL bVisible; 07360 }; 07361 07362 struct CONSOLE_FONT_INFO 07363 { 07364 DWORD nFont; 07365 COORD dwFontSize; 07366 }; 07367 07368 struct CONSOLE_FONT_INFOEX 07369 { 07370 ULONG cbSize; 07371 DWORD nFont; 07372 COORD dwFontSize; 07373 UINT FontFamily; 07374 UINT FontWeight; 07375 WCHAR FaceName[LF_FACESIZE]; 07376 }; 07377 07378 struct DATABLOCK_HEADER 07379 { 07380 DWORD cbSize; 07381 DWORD dwSignature; 07382 }; 07383 07384 struct NT_CONSOLE_PROPS 07385 { 07386 DATABLOCK_HEADER dbh; 07387 07388 WORD wFillAttribute; 07389 WORD wPopupFillAttribute; 07390 COORD dwScreenBufferSize; 07391 COORD dwWindowSize; 07392 COORD dwWindowOrigin; 07393 DWORD nFont; 07394 DWORD nInputBufferSize; 07395 COORD dwFontSize; 07396 UINT uFontFamily; 07397 UINT uFontWeight; 07398 WCHAR FaceName[LF_FACESIZE]; 07399 UINT uCursorSize; 07400 BOOL bFullScreen; 07401 BOOL bQuickEdit; 07402 BOOL bInsertMode; 07403 BOOL bAutoPosition; 07404 UINT uHistoryBufferSize; 07405 UINT uNumberOfHistoryBuffers; 07406 BOOL bHistoryNoDup; 07407 07408 COLORREF ColorTable[16]; 07409 }; 07410 07411 struct FLASHWINFO 07412 { 07413 UINT cbSize; 07414 HWND hwnd; 07415 DWORD dwFlags; 07416 UINT uCount; 07417 DWORD dwTimeout; 07418 }; 07419 07420 enum TBPFLAG 07421 { 07422 TBPF_NOPROGRESS = 0x0, 07423 TBPF_INDETERMINATE = 0x1, 07424 TBPF_NORMAL = 0x2, 07425 TBPF_ERROR = 0x4, 07426 TBPF_PAUSED = 0x8 07427 }; 07428 07429 #pragma pack (pop) 07430 07431 const GUID IID_IShellLink = {0x000214ee, 0x0000, 0x0000, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; 07432 const GUID IID_IShellLinkDataList = {0x45e2b4ae, 0xb1c3, 0x11d0, {0xb9,0x2f,0x00,0xa0,0xc9,0x03,0x12,0xe1}}; 07433 const GUID IID_IPersistFile = {0x0000010b, 0x0000, 0x0000, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; 07434 07435 const GUID IID_ITaskbarList3 = {0xea1afb91, 0x9e28, 0x4b86, {0x90,0xe9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf}}; 07436 const GUID CLSID_TaskbarList = {0x56fdf344, 0xfd6d, 0x11d0, {0x95,0x8a,0x00,0x60,0x97,0xc9,0xa0,0x90}}; 07437 07438 const GUID CLSID_SpVoice = {0x96749377, 0x3391, 0x11d2, {0x9e,0xe3,0x00,0xc0,0x4f,0x79,0x73,0x96}}; 07439 const GUID IID_ISpVoice = {0x6c44df74, 0x72b9, 0x4992, {0xa1,0xec,0xef,0x99,0x6e,0x04,0x22,0xd4}}; 07440 07441 typedef DWORD NTSTATUS; 07442 typedef ULONG_PTR KAFFINITY; 07443 typedef LONG KPRIORITY; 07444 07445 struct UNICODE_STRING 07446 { 07447 USHORT Length; 07448 USHORT MaximumLength; 07449 wchar_t* Buffer; 07450 }; 07451 07452 struct RTL_DRIVE_LETTER_CURDIR 07453 { 07454 USHORT Flags; 07455 USHORT Length; 07456 ULONG TimeStamp; 07457 UNICODE_STRING DosPath; 07458 }; 07459 07460 struct CURDIR 07461 { 07462 UNICODE_STRING DosPath; 07463 void* Handle; 07464 }; 07465 07466 struct RTL_USER_PROCESS_PARAMETERS 07467 { 07468 ULONG AllocationSize; 07469 ULONG Size; 07470 ULONG Flags; 07471 ULONG DebugFlags; 07472 HANDLE ConsoleHandle; 07473 ULONG ConsoleFlags; 07474 HANDLE hStdInput; 07475 HANDLE hStdOutput; 07476 HANDLE hStdError; 07477 CURDIR CurrentDirectory; 07478 UNICODE_STRING DllPath; 07479 UNICODE_STRING ImagePathName; 07480 UNICODE_STRING CommandLine; 07481 wchar_t* Environment; 07482 ULONG dwX; 07483 ULONG dwY; 07484 ULONG dwXSize; 07485 ULONG dwYSize; 07486 ULONG dwXCountChars; 07487 ULONG dwYCountChars; 07488 ULONG dwFillAttribute; 07489 ULONG dwFlags; 07490 ULONG wShowWindow; 07491 UNICODE_STRING WindowTitle; 07492 UNICODE_STRING Desktop; 07493 UNICODE_STRING ShellInfo; 07494 UNICODE_STRING RuntimeInfo; 07495 RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; 07496 }; 07497 07498 struct PEB 07499 { 07500 BYTE Reserved1[2]; 07501 BYTE BeingDebugged; 07502 BYTE Reserved2[1]; 07503 void* Reserved3[2]; 07504 void* Ldr; 07505 RTL_USER_PROCESS_PARAMETERS* ProcessParameters; 07506 void* Reserved4[3]; 07507 void* AtlThunkSListPtr; 07508 void* Reserved5; 07509 ULONG Reserved6; 07510 void* Reserved7; 07511 ULONG Reserved8; 07512 ULONG AtlThunkSListPtr32; 07513 void* Reserved9[45]; 07514 BYTE Reserved10[96]; 07515 void* PostProcessInitRoutine; 07516 BYTE Reserved11[128]; 07517 void* Reserved12[1]; 07518 ULONG SessionId; 07519 }; 07520 07521 struct TEB 07522 { 07523 void* Reserved1[12]; 07524 PEB* ProcessEnvironmentBlock; 07525 void* Reserved2[399]; 07526 BYTE Reserved3[1952]; 07527 void* TlsSlots[64]; 07528 BYTE Reserved4[8]; 07529 void* Reserved5[26]; 07530 void* ReservedForOle; 07531 void* Reserved6[4]; 07532 void* TlsExpansionSlots; 07533 }; 07534 07535 struct PROCESS_BASIC_INFORMATION 07536 { 07537 NTSTATUS ExitStatus; 07538 PEB* PebBaseAddress; 07539 KAFFINITY AffinityMask; 07540 KPRIORITY BasePriority; 07541 ULONG_PTR UniqueProcessId; 07542 ULONG_PTR InheritedFromUniqueProcessId; 07543 }; 07544 07545 enum ADDRESS_MODE 07546 { 07547 AddrMode1616, 07548 AddrMode1632, 07549 AddrModeReal, 07550 AddrModeFlat 07551 }; 07552 07553 struct ADDRESS64 07554 { 07555 DWORD64 Offset; 07556 WORD Segment; 07557 ADDRESS_MODE Mode; 07558 }; 07559 07560 struct KDHELP64 07561 { 07562 DWORD64 Thread; 07563 DWORD ThCallbackStack; 07564 DWORD ThCallbackBStore; 07565 DWORD NextCallback; 07566 DWORD FramePointer; 07567 DWORD64 KiCallUserMode; 07568 DWORD64 KeUserCallbackDispatcher; 07569 DWORD64 SystemRangeStart; 07570 DWORD64 KiUserExceptionDispatcher; 07571 DWORD64 StackBase; 07572 DWORD64 StackLimit; 07573 DWORD64 Reserved[5]; 07574 }; 07575 07576 struct STACKFRAME64 07577 { 07578 ADDRESS64 AddrPC; 07579 ADDRESS64 AddrReturn; 07580 ADDRESS64 AddrFrame; 07581 ADDRESS64 AddrStack; 07582 ADDRESS64 AddrBStore; 07583 void* FuncTableEntry; 07584 DWORD64 Params[4]; 07585 BOOL Far; 07586 BOOL Virtual; 07587 DWORD64 Reserved[3]; 07588 KDHELP64 KdHelp; 07589 }; 07590 07591 struct WOW64_FLOATING_SAVE_AREA 07592 { 07593 DWORD ControlWord; 07594 DWORD StatusWord; 07595 DWORD TagWord; 07596 DWORD ErrorOffset; 07597 DWORD ErrorSelector; 07598 DWORD DataOffset; 07599 DWORD DataSelector; 07600 BYTE RegisterArea[80]; 07601 DWORD Cr0NpxState; 07602 }; 07603 07604 #pragma pack (push, 4) 07605 07606 struct WOW64_CONTEXT 07607 { 07608 DWORD ContextFlags; 07609 07610 DWORD Dr0; 07611 DWORD Dr1; 07612 DWORD Dr2; 07613 DWORD Dr3; 07614 DWORD Dr6; 07615 DWORD Dr7; 07616 07617 WOW64_FLOATING_SAVE_AREA FloatSave; 07618 07619 DWORD SegGs; 07620 DWORD SegFs; 07621 DWORD SegEs; 07622 DWORD SegDs; 07623 07624 DWORD Edi; 07625 DWORD Esi; 07626 DWORD Ebx; 07627 DWORD Edx; 07628 DWORD Ecx; 07629 DWORD Eax; 07630 07631 DWORD Ebp; 07632 DWORD Eip; 07633 DWORD SegCs; 07634 DWORD EFlags; 07635 DWORD Esp; 07636 DWORD SegSs; 07637 07638 BYTE ExtendedRegisters[512]; 07639 }; 07640 07641 #pragma pack (pop) 07642 07643 struct SYMBOL_INFO 07644 { 07645 ULONG SizeOfStruct; 07646 ULONG TypeIndex; 07647 ULONG64 Reserved[2]; 07648 ULONG info; 07649 ULONG Size; 07650 ULONG64 ModBase; 07651 ULONG Flags; 07652 ULONG64 Value; 07653 ULONG64 Address; 07654 ULONG Register; 07655 ULONG Scope; 07656 ULONG Tag; 07657 ULONG NameLen; 07658 ULONG MaxNameLen; 07659 char Name[1]; 07660 }; 07661 07662 struct IMAGEHLP_LINE64 07663 { 07664 DWORD SizeOfStruct; 07665 void* Key; 07666 DWORD LineNumber; 07667 char* FileName; 07668 DWORD64 Address; 07669 }; 07670 07671 typedef bool (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64) (HANDLE process, DWORD64 baseAddress, void* buffer, DWORD size, DWORD* bytesRead); 07672 typedef void* (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64) (HANDLE process, DWORD64 baseAddress); 07673 typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64) (HANDLE process, DWORD64 address); 07674 typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64) (HANDLE process, HANDLE thread, ADDRESS64* address); 07675 07676 typedef void (*unexpected_handler)(); 07677 07678 #pragma pack (push, 4) 07679 07680 struct MINIDUMP_THREAD_CALLBACK 07681 { 07682 ULONG ThreadId; 07683 HANDLE ThreadHandle; 07684 CONTEXT Context; 07685 ULONG SizeOfContext; 07686 ULONG64 StackBase; 07687 ULONG64 StackEnd; 07688 }; 07689 07690 struct MINIDUMP_THREAD_EX_CALLBACK 07691 { 07692 ULONG ThreadId; 07693 HANDLE ThreadHandle; 07694 CONTEXT Context; 07695 ULONG SizeOfContext; 07696 ULONG64 StackBase; 07697 ULONG64 StackEnd; 07698 ULONG64 BackingStoreBase; 07699 ULONG64 BackingStoreEnd; 07700 }; 07701 07702 struct MINIDUMP_MODULE_CALLBACK 07703 { 07704 wchar_t* FullPath; 07705 ULONG64 BaseOfImage; 07706 ULONG SizeOfImage; 07707 ULONG CheckSum; 07708 ULONG TimeDateStamp; 07709 VS_FIXEDFILEINFO VersionInfo; 07710 void* CvRecord; 07711 ULONG SizeOfCvRecord; 07712 void* MiscRecord; 07713 ULONG SizeOfMiscRecord; 07714 }; 07715 07716 struct MINIDUMP_INCLUDE_THREAD_CALLBACK 07717 { 07718 ULONG ThreadId; 07719 }; 07720 07721 struct MINIDUMP_INCLUDE_MODULE_CALLBACK 07722 { 07723 ULONG64 BaseOfImage; 07724 }; 07725 07726 struct MINIDUMP_MEMORY_INFO 07727 { 07728 ULONG64 BaseAddress; 07729 ULONG64 AllocationBase; 07730 ULONG32 AllocationProtect; 07731 ULONG32 __alignment1; 07732 ULONG64 RegionSize; 07733 ULONG32 State; 07734 ULONG32 Protect; 07735 ULONG32 Type; 07736 ULONG32 __alignment2; 07737 }; 07738 07739 struct MINIDUMP_USER_STREAM 07740 { 07741 ULONG32 Type; 07742 ULONG BufferSize; 07743 void* Buffer; 07744 }; 07745 07746 struct MINIDUMP_USER_STREAM_INFORMATION 07747 { 07748 ULONG UserStreamCount; 07749 MINIDUMP_USER_STREAM* UserStreamArray; 07750 }; 07751 07752 struct MINIDUMP_CALLBACK_INPUT 07753 { 07754 ULONG ProcessId; 07755 HANDLE ProcessHandle; 07756 ULONG CallbackType; 07757 07758 union //-V2514 07759 { 07760 MINIDUMP_THREAD_CALLBACK Thread; 07761 MINIDUMP_THREAD_EX_CALLBACK ThreadEx; 07762 MINIDUMP_MODULE_CALLBACK Module; 07763 MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread; 07764 MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule; 07765 }; 07766 }; 07767 07768 struct MINIDUMP_CALLBACK_OUTPUT 07769 { 07770 union //-V2514 07771 { 07772 ULONG ModuleWriteFlags; 07773 ULONG ThreadWriteFlags; 07774 ULONG SecondaryFlags; 07775 07776 struct 07777 { 07778 ULONG64 MemoryBase; 07779 ULONG MemorySize; 07780 }; 07781 07782 struct 07783 { 07784 unsigned CheckCancel; 07785 unsigned Cancel; 07786 }; 07787 07788 HANDLE Handle; //-V117 07789 }; 07790 07791 struct 07792 { 07793 MINIDUMP_MEMORY_INFO VmRegion; 07794 unsigned Continue; 07795 }; 07796 07797 HRESULT Status; 07798 }; 07799 07800 struct MINIDUMP_EXCEPTION_INFORMATION 07801 { 07802 DWORD ThreadId; 07803 EXCEPTION_POINTERS* ExceptionPointers; 07804 unsigned ClientPointers; 07805 }; 07806 07807 typedef int (WINAPI* MINIDUMP_CALLBACK_ROUTINE) (void* param, MINIDUMP_CALLBACK_INPUT* input, MINIDUMP_CALLBACK_OUTPUT* output); 07808 07809 struct MINIDUMP_CALLBACK_INFORMATION 07810 { 07811 MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; 07812 void* CallbackParam; 07813 }; 07814 07815 enum MINIDUMP_TYPE 07816 { 07817 MiniDumpNormal = 0x00000000, 07818 MiniDumpWithDataSegs = 0x00000001, 07819 MiniDumpWithFullMemory = 0x00000002, 07820 MiniDumpWithHandleData = 0x00000004, 07821 MiniDumpFilterMemory = 0x00000008, 07822 MiniDumpScanMemory = 0x00000010, 07823 MiniDumpWithUnloadedModules = 0x00000020, 07824 MiniDumpWithIndirectlyReferencedMemory = 0x00000040, 07825 MiniDumpFilterModulePaths = 0x00000080, 07826 MiniDumpWithProcessThreadData = 0x00000100, 07827 MiniDumpWithPrivateReadWriteMemory = 0x00000200, 07828 MiniDumpWithoutOptionalData = 0x00000400, 07829 MiniDumpWithFullMemoryInfo = 0x00000800, 07830 MiniDumpWithThreadInfo = 0x00001000, 07831 MiniDumpWithCodeSegs = 0x00002000, 07832 MiniDumpWithoutAuxiliaryState = 0x00004000, 07833 MiniDumpWithFullAuxiliaryState = 0x00008000, 07834 MiniDumpWithPrivateWriteCopyMemory = 0x00010000, 07835 MiniDumpIgnoreInaccessibleMemory = 0x00020000, 07836 MiniDumpWithTokenInformation = 0x00040000 07837 }; 07838 07839 #ifndef CONTEXT_ALL 07840 #define CONTEXT_ALL ( CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS ) 07841 #endif 07842 07843 #pragma pack (pop) 07844 07845 } // namespace Win32 07846 07847 #endif // TX_COMPILED 07848 07849 #define FOREGROUND_BLACK ( 0 ) 07850 #define FOREGROUND_CYAN ( FOREGROUND_BLUE | FOREGROUND_GREEN ) 07851 #define FOREGROUND_MAGENTA ( FOREGROUND_BLUE | FOREGROUND_RED ) 07852 #define FOREGROUND_DARKYELLOW ( FOREGROUND_GREEN | FOREGROUND_RED ) 07853 #define FOREGROUND_LIGHTGRAY ( FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED ) 07854 #define FOREGROUND_DARKGRAY ( FOREGROUND_INTENSITY ) 07855 #define FOREGROUND_LIGHTBLUE ( FOREGROUND_BLUE | FOREGROUND_INTENSITY ) 07856 #define FOREGROUND_LIGHTGREEN ( FOREGROUND_GREEN | FOREGROUND_INTENSITY ) 07857 #define FOREGROUND_LIGHTCYAN ( FOREGROUND_CYAN | FOREGROUND_INTENSITY ) 07858 #define FOREGROUND_LIGHTRED ( FOREGROUND_RED | FOREGROUND_INTENSITY ) 07859 #define FOREGROUND_LIGHTMAGENTA ( FOREGROUND_MAGENTA | FOREGROUND_INTENSITY ) 07860 #define FOREGROUND_YELLOW ( FOREGROUND_DARKYELLOW | FOREGROUND_INTENSITY ) 07861 #define FOREGROUND_WHITE ( FOREGROUND_LIGHTGRAY | FOREGROUND_INTENSITY ) 07862 07863 #define BACKGROUND_BLACK ( 0 ) 07864 #define BACKGROUND_CYAN ( BACKGROUND_BLUE | BACKGROUND_GREEN ) 07865 #define BACKGROUND_MAGENTA ( BACKGROUND_BLUE | BACKGROUND_RED ) 07866 #define BACKGROUND_DARKYELLOW ( BACKGROUND_GREEN | BACKGROUND_RED ) 07867 #define BACKGROUND_GRAY ( BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED ) 07868 #define BACKGROUND_DARKGRAY ( BACKGROUND_INTENSITY ) 07869 #define BACKGROUND_LIGHTBLUE ( BACKGROUND_BLUE | BACKGROUND_INTENSITY ) 07870 #define BACKGROUND_LIGHTGREEN ( BACKGROUND_GREEN | BACKGROUND_INTENSITY ) 07871 #define BACKGROUND_LIGHTCYAN ( BACKGROUND_CYAN | BACKGROUND_INTENSITY ) 07872 #define BACKGROUND_LIGHTRED ( BACKGROUND_RED | BACKGROUND_INTENSITY ) 07873 #define BACKGROUND_LIGHTMAGENTA ( BACKGROUND_MAGENTA | BACKGROUND_INTENSITY ) 07874 #define BACKGROUND_LIGHTYELLOW ( BACKGROUND_DARKYELLOW | BACKGROUND_INTENSITY ) 07875 #define BACKGROUND_WHITE ( BACKGROUND_DARKGRAY | BACKGROUND_INTENSITY ) 07876 07877 //} 07878 //----------------------------------------------------------------------------------------------------------------- 07879 07880 //----------------------------------------------------------------------------------------------------------------- 07881 //{ There are copies of MSVC compiler built-in predefined definitions, which are wrong in 64-bit mode. 07882 // So we have to override them. See: http://stackoverflow.com/questions/39113168 07883 //----------------------------------------------------------------------------------------------------------------- 07884 07885 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 07886 07887 #if defined (_MSC_VER) 07888 // MS ABI C++ Exception Layout 07889 namespace Win32 { // --------------------------- 07890 // 07891 #pragma pack (push, 4) // EXCEPTION_RECORD: 07892 // +==================================================+ 07893 struct ThrowInfo // |... | 07894 { // |NumberParameters: 3, 4 or more | 07895 __int32 attributes; // |ExceptionInformation[0]: MS signature 0x19930520 | 07896 __int32 pmfnUnwind; // |ExceptionInformation[1]: object* thrown | 07897 __int32 pForwardCompat; // |ExceptionInformation[2]: ThrowInfo* --------------+---+ 07898 __int32 pCatchableTypeArray; // |ExceptionInformation[3]: ImageBase (if params > 3)| | 07899 }; // +==================================================+ | 07900 // | 07901 struct CatchableTypeArray // ThrowInfo: | 07902 { // +======================================+ <-------+ 07903 __int32 nCatchableTypes; // | ... | 07904 __int32 arrayOfCatchableTypes[]; // +-----+-- pCatchableTypeArray (ptr/RVA) | 07905 }; // | +======================================+ 07906 // | 07907 struct CatchableType // | CatchableTypeArray: 07908 { // +---> +======================================+ 07909 __int32 properties; // | ... | 07910 __int32 pType; // +-----+-- arrayOfCatchableTypes[0] (ptr/RVA) | 07911 __int32 thisDisplacement[3]; // struct _PMD // | +======================================+ 07912 __int32 sizeOrOffset; // | 07913 __int32 copyFunction; // | CatchableType: 07914 }; // +---> +====================+ 07915 // | ... | std::type_info: 07916 #pragma pack (pop) // | pType (ptr/RVA) ---+------> +==================+ 07917 // | ... | |type_info data | 07918 } // namespace Win32 // +====================+ |... | 07919 // +==================+ 07920 #endif 07921 07922 // Similar to __CxxDetectRethrow(), see C:\Bin\Microsoft Visual Studio 14.0\VC\crt\src\crtsrc\vcruntime\frame.cpp: 07923 07924 #define _TX_MSC__CXX_DETECT_RETHROW( exc ) \ 07925 ( \ 07926 (exc) && \ 07927 (exc) -> ExceptionCode == EXCEPTION_CPP_MSC && \ 07928 (exc) -> NumberParameters >= 3 && \ 07929 \ 07930 ((exc)-> ExceptionInformation[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER1 || \ 07931 (exc)-> ExceptionInformation[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER2 || \ 07932 (exc)-> ExceptionInformation[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER3) && \ 07933 \ 07934 (exc) -> ExceptionInformation[2] == 0 \ 07935 ) 07936 07937 #endif // TX_COMPILED 07938 07939 //} 07940 //----------------------------------------------------------------------------------------------------------------- 07941 07942 //----------------------------------------------------------------------------------------------------------------- 07943 //{ The corresponding structures for GCC 07944 // 07945 // From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/unwind-cxx.h 07946 // See: http://mentorembedded.github.io/cxx-abi/abi-eh.html#cxx-abi 07947 //----------------------------------------------------------------------------------------------------------------- 07948 07949 #if defined (_GCC_VER) 07950 07951 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 07952 07953 // GCC ABI C++ Exception layout. A/B are ExceptionInformation[0]. 07954 namespace ABI { // -------------------------------------------------------------- 07955 // 07956 struct __cxa_exception // Case A: "_Unwind_Exception* A" is independent exception: 07957 { // -------------------------------------------------------- 07958 union { // 07959 struct // __cxa_exception: std::type_info: 07960 { // -*--+====================+ +==================+ 07961 ::std::type_info* exceptionType; // ^ |exceptionType* -----+---->|type_info data | 07962 void (*exceptionDestructor)(void*); // | |... | |... | 07963 }; // -1 | | +==================+ 07964 struct // | | | 07965 { // A >----|--+--------------------+ 07966 __cxa_exception* primaryException; // | | |unwindHeader | 07967 void (*padding)(); // +1 | | | 07968 }; // | | | | 07969 }; // V | | | 07970 // -*--- +====================+ 07971 void (*unexpected_handler)(); // |object | 07972 std::terminate_handler terminateHandler; // +--------------------+ 07973 // 07974 __cxa_exception* nextException; // Case B: "_Unwind_Exception* B" is dependent exception 07975 int handlerCount; // (unwindHeader.exception_class & 1 != 0): 07976 int handlerSwitchValue; // ----------------------------------------------------- 07977 const unsigned char* actionRecord; // 07978 const unsigned char* languageSpecificData; // __cxa_exception: __cxa_exception: 07979 void* catchTemp; // -*--+====================+ -*--+=================+ 07980 void* adjustedPtr; // ^ |primaryException* --+-- ^ |exceptionType* | 07981 // | |... | \ | |... | 07982 _Unwind_Exception unwindHeader; // -1 | | | | | | 07983 }; // | | | | | | | 07984 // B >----|--+--------------------+ | -1 +-----------------+ 07985 struct __cxa_eh_globals // | | |unwindHeader | | | |unwindHeader | 07986 { // +1 | | | | | | | 07987 __cxa_exception* caughtExceptions; // | | | | | | | | 07988 unsigned int uncaughtExceptions; // V | | | \ | | | 07989 }; // -*--- +====================+ -->*--+=================+ 07990 // |... | |object | 07991 } // namespace ABI // . . | | 07992 // +-----------------+ 07993 07994 extern "C" ABI::__cxa_eh_globals* __cxa_get_globals(); 07995 07996 #endif // TX_COMPILED 07997 07998 #endif 07999 08000 //} 08001 //----------------------------------------------------------------------------------------------------------------- 08002 08003 //----------------------------------------------------------------------------------------------------------------- 08004 //{ Hand-made IAT. 08005 // Some IDEs don't link with these libs by default in console projects, so do sunrise by hand. :( 08006 //----------------------------------------------------------------------------------------------------------------- 08007 08008 // Hand-made DLLIMPORT helpers 08009 08010 #define _TX_DLLIMPORT( lib, retval, name, params ) TX_DLLIMPORT (true, lib ".dll", retval, name, params, WINAPI) 08011 #define _TX_DLLIMPORT_OPT( lib, retval, name, params ) TX_DLLIMPORT (false, lib ".dll", retval, name, params, WINAPI) 08012 #define _TX_DLLIMPORT_CRT( lib, retval, name, params ) TX_DLLIMPORT (false, lib ".dll", retval, name, params, please) 08013 08014 void (*_txDllImport (const char dllFileName[], const char funcName[], bool required = true)) (); 08015 08016 //----------------------------------------------------------------------------------------------------------------- 08017 08018 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 08019 08020 namespace Win32 { 08021 08022 _TX_DLLIMPORT ("GDI32", HDC, CreateCompatibleDC, (HDC dc)); 08023 _TX_DLLIMPORT ("GDI32", HBITMAP, CreateCompatibleBitmap, (HDC dc, int width, int height)); 08024 _TX_DLLIMPORT ("GDI32", HGDIOBJ, GetStockObject, (int object)); 08025 _TX_DLLIMPORT ("GDI32", HGDIOBJ, SelectObject, (HDC dc, HGDIOBJ object)); 08026 _TX_DLLIMPORT ("GDI32", HGDIOBJ, GetCurrentObject, (HDC dc, unsigned objectType)); 08027 _TX_DLLIMPORT ("GDI32", int, GetObjectA, (HGDIOBJ obj, int bufsize, void* buffer)); 08028 _TX_DLLIMPORT ("GDI32", DWORD, GetObjectType, (HGDIOBJ object)); 08029 _TX_DLLIMPORT ("GDI32", bool, DeleteDC, (HDC dc)); 08030 _TX_DLLIMPORT ("GDI32", bool, DeleteObject, (HGDIOBJ object)); 08031 _TX_DLLIMPORT ("GDI32", COLORREF, SetTextColor, (HDC dc, COLORREF color)); 08032 _TX_DLLIMPORT ("GDI32", COLORREF, SetBkColor, (HDC dc, COLORREF color)); 08033 _TX_DLLIMPORT ("GDI32", int, SetBkMode, (HDC dc, int bkMode)); 08034 _TX_DLLIMPORT ("GDI32", HFONT, CreateFontA, (int height, int width, int escapement, int orientation, 08035 int weight, DWORD italic, DWORD underline, DWORD strikeout, 08036 DWORD charSet, DWORD outputPrec, DWORD clipPrec, 08037 DWORD quality, DWORD pitchAndFamily, const char face[])); 08038 _TX_DLLIMPORT ("GDI32", int, EnumFontFamiliesExA, (HDC dc, LPLOGFONT logFont, FONTENUMPROC enumProc, 08039 LPARAM lParam, DWORD reserved)); 08040 _TX_DLLIMPORT ("GDI32", COLORREF, SetPixel, (HDC dc, int x, int y, COLORREF color)); 08041 _TX_DLLIMPORT ("GDI32", COLORREF, GetPixel, (HDC dc, int x, int y)); 08042 _TX_DLLIMPORT ("GDI32", HPEN, CreatePen, (int penStyle, int width, COLORREF color)); 08043 _TX_DLLIMPORT ("GDI32", HBRUSH, CreateSolidBrush, (COLORREF color)); 08044 _TX_DLLIMPORT ("GDI32", bool, MoveToEx, (HDC dc, int x, int y, POINT* point)); 08045 _TX_DLLIMPORT ("GDI32", bool, LineTo, (HDC dc, int x, int y)); 08046 _TX_DLLIMPORT ("GDI32", bool, Polygon, (HDC dc, const POINT points[], int count)); 08047 _TX_DLLIMPORT ("GDI32", bool, Polyline, (HDC dc, const POINT points[], int count)); 08048 _TX_DLLIMPORT ("GDI32", bool, PolyBezier, (HDC dc, const POINT points[], int count)); 08049 _TX_DLLIMPORT ("GDI32", bool, Rectangle, (HDC dc, int x0, int y0, int x1, int y1)); 08050 _TX_DLLIMPORT ("GDI32", bool, RoundRect, (HDC dc, int x0, int y0, int x1, int y1, int sizeX, int sizeY)); 08051 _TX_DLLIMPORT ("GDI32", bool, Ellipse, (HDC dc, int x0, int y0, int x1, int y1)); 08052 _TX_DLLIMPORT ("GDI32", bool, Arc, (HDC dc, int x0, int y0, int x1, int y1, 08053 int xStart, int yStart, int xEnd, int yEnd)); 08054 _TX_DLLIMPORT ("GDI32", bool, Pie, (HDC dc, int x0, int y0, int x1, int y1, 08055 int xStart, int yStart, int xEnd, int yEnd)); 08056 _TX_DLLIMPORT ("GDI32", bool, Chord, (HDC dc, int x0, int y0, int x1, int y1, 08057 int xStart, int yStart, int xEnd, int yEnd)); 08058 _TX_DLLIMPORT ("GDI32", bool, TextOutA, (HDC dc, int x, int y, const char string[], int length)); 08059 _TX_DLLIMPORT ("GDI32", UINT, SetTextAlign, (HDC dc, unsigned mode)); 08060 _TX_DLLIMPORT ("GDI32", bool, GetTextExtentPoint32A, (HDC dc, const char string[], int length, SIZE* size)); 08061 _TX_DLLIMPORT ("GDI32", bool, ExtFloodFill, (HDC dc, int x, int y, COLORREF color, unsigned type)); 08062 _TX_DLLIMPORT ("GDI32", bool, BitBlt, (HDC dest, int xDest, int yDest, int width, int height, 08063 HDC src, int xSrc, int ySrc, DWORD rOp)); 08064 _TX_DLLIMPORT ("GDI32", bool, StretchBlt, (HDC dest, int xDest, int yDest, int width, int height, 08065 HDC src, int xSrc, int ySrc, int wSrc, int hSrc, DWORD rOp)); 08066 _TX_DLLIMPORT ("GDI32", bool, PlgBlt, (HDC dest, const POINT* parallelogram, 08067 HDC src, int xSrc, int ySrc, int width, int height, 08068 HBITMAP mask, int xMask, int yMask)); 08069 _TX_DLLIMPORT ("GDI32", int, SetDIBitsToDevice, (HDC dc, int xDest, int yDest, DWORD width, DWORD height, 08070 int xSrc, int ySrc, unsigned startLine, unsigned numLines, 08071 const void* data, const BITMAPINFO* info, unsigned colorUse)); 08072 _TX_DLLIMPORT ("GDI32", int, GetDIBits, (HDC hdc, HBITMAP hbmp, unsigned uStartScan, unsigned cScanLines, 08073 void* lpvBits, BITMAPINFO* lpbi, unsigned usage)); 08074 _TX_DLLIMPORT ("GDI32", bool, PatBlt, (HDC dc, int x0, int y0, int width, int height, DWORD rOp)); 08075 _TX_DLLIMPORT ("GDI32", int, SetROP2, (HDC dc, int mode)); 08076 _TX_DLLIMPORT ("GDI32", int, SetStretchBltMode, (HDC dc, int mode)); 08077 _TX_DLLIMPORT ("GDI32", DWORD, GdiSetBatchLimit, (DWORD limit)); 08078 _TX_DLLIMPORT ("GDI32", HBITMAP, CreateDIBSection, (HDC dc, const BITMAPINFO* bmInfo, unsigned colorUsage, void **vBits, 08079 HANDLE section, DWORD offset)); 08080 08081 _TX_DLLIMPORT ("User32", int, DrawTextA, (HDC dc, const char text[], int length, RECT* rect, unsigned format)); 08082 _TX_DLLIMPORT ("User32", HANDLE, LoadImageA, (HINSTANCE inst, const char name[], unsigned type, 08083 int sizex, int sizey, unsigned mode)); 08084 _TX_DLLIMPORT_OPT ("User32", bool, IsHungAppWindow, (HWND wnd)); 08085 _TX_DLLIMPORT_OPT ("User32", HWND, GhostWindowFromHungWindow, (HWND wnd)); 08086 _TX_DLLIMPORT_OPT ("User32", bool, FlashWindowEx, (const FLASHWINFO* flash)); 08087 08088 _TX_DLLIMPORT ("WinMM", bool, PlaySound, (const char sound[], HMODULE mod, DWORD mode)); 08089 08090 _TX_DLLIMPORT_OPT ("MSImg32", bool, TransparentBlt, (HDC dest, int destX, int destY, int destWidth, int destHeight, 08091 HDC src, int srcX, int srcY, int srcWidth, int srcHeight, 08092 unsigned transparentColor)); 08093 _TX_DLLIMPORT_OPT ("MSImg32", bool, AlphaBlend, (HDC dest, int destX, int destY, int destWidth, int destHeight, 08094 HDC src, int srcX, int srcY, int srcWidth, int srcHeight, 08095 BLENDFUNCTION blending)); 08096 08097 _TX_DLLIMPORT ("Kernel32", void, ExitProcess, (unsigned retcode)); 08098 _TX_DLLIMPORT ("Kernel32", bool, TerminateProcess, (HANDLE process, unsigned retcode)); 08099 _TX_DLLIMPORT_OPT ("Kernel32", void, FatalExit, (int retcode)); 08100 _TX_DLLIMPORT_OPT ("Kernel32", void, FatalAppExitA, (unsigned action, const char message[])); 08101 _TX_DLLIMPORT_OPT ("Kernel32", DWORD, GetThreadId, (HANDLE thread)); 08102 _TX_DLLIMPORT ("Kernel32", HWND, GetConsoleWindow, (void)); 08103 _TX_DLLIMPORT_OPT ("Kernel32", bool, SetConsoleFont, (HANDLE con, DWORD fontIndex)); 08104 _TX_DLLIMPORT_OPT ("Kernel32", DWORD, GetNumberOfConsoleFonts, (void)); 08105 _TX_DLLIMPORT_OPT ("Kernel32", bool, GetCurrentConsoleFont, (HANDLE con, bool maxWnd, CONSOLE_FONT_INFO* curFont)); 08106 _TX_DLLIMPORT_OPT ("Kernel32", bool, GetCurrentConsoleFontEx, (HANDLE con, bool maxWnd, CONSOLE_FONT_INFOEX* curFont)); 08107 _TX_DLLIMPORT_OPT ("Kernel32", bool, SetCurrentConsoleFontEx, (HANDLE con, bool maxWnd, CONSOLE_FONT_INFOEX* curFont)); 08108 _TX_DLLIMPORT_OPT ("Kernel32", void, RtlCaptureContext, (CONTEXT* contextRecord)); 08109 _TX_DLLIMPORT_OPT ("Kernel32", USHORT, RtlCaptureStackBackTrace, (DWORD framesToSkip, DWORD framesToCapture, void** backTrace, DWORD* hash)); 08110 _TX_DLLIMPORT_OPT ("Kernel32", void*, AddVectoredExceptionHandler, (unsigned long firstHandler, PVECTORED_EXCEPTION_HANDLER handler)); 08111 _TX_DLLIMPORT_OPT ("Kernel32", unsigned, RemoveVectoredExceptionHandler,(void* handler)); 08112 _TX_DLLIMPORT_OPT ("Kernel32", bool, GetModuleHandleEx, (DWORD flags, const char moduleName[], HMODULE* module)); 08113 _TX_DLLIMPORT_OPT ("Kernel32", bool, IsWow64Process, (HANDLE process, int* isWow64Process)); 08114 _TX_DLLIMPORT_OPT ("Kernel32", bool, Wow64GetThreadContext, (HANDLE thread, WOW64_CONTEXT* context)); 08115 _TX_DLLIMPORT_OPT ("Kernel32", bool, SetThreadStackGuarantee, (unsigned long* stackSize)); 08116 08117 _TX_DLLIMPORT ("OLE32", HRESULT, CoInitialize, (void*)); 08118 _TX_DLLIMPORT ("OLE32", HRESULT, CoCreateInstance, (REFCLSID clsId, IUnknown*, DWORD, REFIID iId, void** value)); 08119 _TX_DLLIMPORT ("OLE32", void, CoUninitialize, (void)); 08120 08121 _TX_DLLIMPORT ("Shell32", HINSTANCE,ShellExecuteA, (HWND wnd, const char operation[], const char file[], 08122 const char parameters[], const char directory[], int showCmd)); 08123 08124 _TX_DLLIMPORT ("ShlWAPI", char*, StrStrIA, (const char string[], const char search[])); 08125 _TX_DLLIMPORT ("ShlWAPI", char*, StrStrIW, (const wchar_t string[], const wchar_t search[])); 08126 08127 _TX_DLLIMPORT_OPT ("NTDLL", char*, wine_get_version, (void)); 08128 _TX_DLLIMPORT ("NTDLL", NTSTATUS, NtQueryInformationProcess, (HANDLE process, int infoClass, 08129 void* processInfo, unsigned long szProcessInfo, unsigned long* szReturnInfo)); 08130 08131 _TX_DLLIMPORT_CRT ("MSVCRT", void, exit, (int retcode)); 08132 _TX_DLLIMPORT_CRT ("MSVCRT", void, _cexit, (void)); 08133 _TX_DLLIMPORT_CRT ("MSVCRT", unsigned, _fpreset, (void)); 08134 _TX_DLLIMPORT_CRT ("MSVCRT", unsigned, _controlfp, (unsigned control, unsigned mask)); 08135 _TX_DLLIMPORT_CRT ("MSVCRT", uintptr_t,_beginthread, (void (__cdecl* start_address) (void*), unsigned stack_size, void* arglist)); 08136 _TX_DLLIMPORT_CRT ("MSVCRT", uintptr_t,_beginthreadex, (void* security, unsigned stack_size, unsigned (__stdcall* start_address) (void*), 08137 void *arglist, unsigned init_flag, unsigned* thread_addr)); 08138 _TX_DLLIMPORT_CRT ("MSVCRT", char*, __unDName, (char* outStr, const char* mangledName, int outStrLen, 08139 void* (*mallocFunc) (size_t size), void (*freeFunc) (void *pointer), 08140 unsigned short flags)); 08141 _TX_DLLIMPORT_CRT ("MSVCRT", unexpected_handler, set_unexpected, (unexpected_handler handler)); 08142 08143 _TX_DLLIMPORT_OPT ("OpenGL32", HDC, wglGetCurrentDC, (void)); 08144 _TX_DLLIMPORT_OPT ("OpenGL32", unsigned, glGetError, (void)); 08145 _TX_DLLIMPORT_OPT ("Glu32", const char*, gluErrorString, (unsigned error)); 08146 08147 _TX_DLLIMPORT_OPT ("ComDlg32", DWORD, CommDlgExtendedError, (void)); 08148 08149 _TX_DLLIMPORT_OPT ("DbgHelp*", bool, MiniDumpWriteDump, (HANDLE process, DWORD processId, HANDLE file, MINIDUMP_TYPE dumpType, 08150 MINIDUMP_EXCEPTION_INFORMATION* exceptionParam, 08151 MINIDUMP_USER_STREAM_INFORMATION* userStreamParam, 08152 MINIDUMP_CALLBACK_INFORMATION* callbackParam)); 08153 08154 _TX_DLLIMPORT_OPT ("DbgHelp*", DWORD, SymSetOptions, (DWORD options)); 08155 _TX_DLLIMPORT_OPT ("DbgHelp*", bool, SymInitialize, (HANDLE process, const char userSearchPath[], bool invadeProcess)); 08156 _TX_DLLIMPORT_OPT ("DbgHelp*", bool, SymFromAddr, (HANDLE process, DWORD64 addr, DWORD64* offset, SYMBOL_INFO* symbol)); 08157 _TX_DLLIMPORT_OPT ("DbgHelp*", bool, SymGetLineFromAddr64, (HANDLE process, DWORD64 addr, DWORD* offset, IMAGEHLP_LINE64* line)); 08158 _TX_DLLIMPORT_OPT ("DbgHelp*", DWORD64, SymGetModuleBase64, (HANDLE process, DWORD64 addr)); 08159 _TX_DLLIMPORT_OPT ("DbgHelp*", bool, SymCleanup, (HANDLE process)); 08160 _TX_DLLIMPORT_OPT ("DbgHelp*", void*, SymFunctionTableAccess64, (HANDLE process, DWORD64 addrBase)); 08161 _TX_DLLIMPORT_OPT ("DbgHelp*", bool, StackWalk64, (DWORD arch, HANDLE process, HANDLE thread, STACKFRAME64* frame, void* ctxRecord, 08162 PREAD_PROCESS_MEMORY_ROUTINE64 readMemoryFunc, 08163 PFUNCTION_TABLE_ACCESS_ROUTINE64 tableAccessFunc, 08164 PGET_MODULE_BASE_ROUTINE64 getModuleBaseFunc, 08165 PTRANSLATE_ADDRESS_ROUTINE64 translateAddressFunc)); 08166 namespace MinGW { 08167 _TX_DLLIMPORT_OPT ("MgwHelp*", DWORD, SymSetOptions, (DWORD options)); 08168 _TX_DLLIMPORT_OPT ("MgwHelp*", bool, SymInitialize, (HANDLE process, const char userSearchPath[], bool invadeProcess)); 08169 _TX_DLLIMPORT_OPT ("MgwHelp*", bool, SymFromAddr, (HANDLE process, DWORD64 addr, DWORD64* offset, SYMBOL_INFO* symbol)); 08170 _TX_DLLIMPORT_OPT ("MgwHelp*", bool, SymGetLineFromAddr64, (HANDLE process, DWORD64 addr, DWORD* offset, IMAGEHLP_LINE64* line)); 08171 _TX_DLLIMPORT_OPT ("MgwHelp*", DWORD64, SymGetModuleBase64, (HANDLE process, DWORD64 addr)); 08172 _TX_DLLIMPORT_OPT ("MgwHelp*", bool, SymCleanup, (HANDLE process)); 08173 _TX_DLLIMPORT_OPT ("MgwHelp*", void*, SymFunctionTableAccess64, (HANDLE process, DWORD64 addrBase)); 08174 _TX_DLLIMPORT_OPT ("MgwHelp*", bool, StackWalk64, (DWORD arch, HANDLE process, HANDLE thread, STACKFRAME64* frame, void* ctxRecord, 08175 PREAD_PROCESS_MEMORY_ROUTINE64 readMemoryFunc, 08176 PFUNCTION_TABLE_ACCESS_ROUTINE64 tableAccessFunc, 08177 PGET_MODULE_BASE_ROUTINE64 getModuleBaseFunc, 08178 PTRANSLATE_ADDRESS_ROUTINE64 translateAddressFunc)); 08179 } // namespace MinGW 08180 } // namespace Win32 08181 08182 #endif // TX_COMPILED 08183 08184 //} 08185 //----------------------------------------------------------------------------------------------------------------- 08186 08188 //} 08189 //================================================================================================================= 08190 08191 //================================================================================================================= 08192 //{ Internal function prototypes, macros and constants 08193 // @name Прототипы внутренних функций, макросы и константы 08194 //================================================================================================================= 08196 08197 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 08198 08199 int _txInitialize(); 08200 void _txCleanup(); 08201 08202 HWND _txCanvas_CreateWindow (const SIZE* size); 08203 08204 bool _txCanvas_OnCREATE (HWND wnd); 08205 bool _txCanvas_OnDESTROY (HWND wnd); 08206 bool _txCanvas_OnCLOSE (HWND); 08207 bool _txCanvas_OnPAINT (HWND wnd); 08208 bool _txCanvas_OnKEY (HWND wnd, WPARAM vk, LPARAM info, bool down); 08209 bool _txCanvas_OnCHAR (HWND wnd, WPARAM ch, LPARAM info); 08210 bool _txCanvas_OnTIMER (HWND wnd, WPARAM id); 08211 bool _txCanvas_OnMOUSEMOVE (HWND wnd, WPARAM buttons, LPARAM coords); 08212 bool _txCanvas_OnMOUSELEAVE (HWND wnd); 08213 bool _txCanvas_OnCREATEWND (HWND wnd, WPARAM, LPARAM lpar); 08214 bool _txCanvas_OnDESTROYWND (HWND wnd, WPARAM, LPARAM lpar); 08215 bool _txCanvas_OnCmdCONSOLE (HWND wnd, WPARAM cmd); 08216 bool _txCanvas_OnCmdABOUT (HWND wnd, WPARAM cmd); 08217 08218 unsigned WINAPI _txCanvas_ThreadProc (void* data); 08219 LRESULT CALLBACK _txCanvas_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar); 08220 08221 HDC _txBuffer_Create (HWND wnd = NULL, const POINT* size = NULL, HBITMAP bitmap = NULL, 08222 RGBQUAD** pixels = NULL) tx_nodiscard; 08223 bool _txBuffer_Delete (HDC* dc); 08224 bool _txBuffer_Select (HGDIOBJ obj, HDC dc = txDC()); 08225 08226 HWND _txConsole_Attach(); 08227 bool _txConsole_OK() tx_nodiscard; 08228 bool _txConsole_Detach (bool activate); 08229 bool _txConsole_Draw (HDC dc); 08230 bool _txConsole_SetUnicodeFont(); 08231 08232 const char* txRegisterClass (const char classId[], WNDPROC wndProc, unsigned style, int backBrush, int wndExtra); 08233 HWND txCreateExtraWindow (CREATESTRUCT createData); 08234 HICON _txCreateTXIcon (int size) tx_nodiscard; 08235 int _txSetWindowText (HWND wnd, const char* textRus, const char* textEng = NULL, 08236 int checkOfs = 0, const wchar_t checkLetters[2] = NULL); 08237 int _txPauseBeforeTermination (HWND canvas); 08238 int _txIsParentListed (const char* list, DWORD* parentPID = NULL) tx_nodiscard; 08239 void _txActivateWindow (HWND wnd, unsigned mode); 08240 int _txGetInput(); 08241 08242 LRESULT CALLBACK _txPlayVideo_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar); 08243 const char* _txPlayVideo_FindVLC() tx_nodiscard; 08244 08245 bool _txCreateShortcut (const char shortcutName[], 08246 const char fileToLink[], const char args[] = NULL, const char workDir[] = NULL, 08247 const char description[] = NULL, int cmdShow = SW_SHOWNORMAL, 08248 const char iconFile[] = NULL, int iconIndex = 0, int fontSize = 0, 08249 COORD bufSize = ZERO (COORD), COORD wndSize = ZERO (COORD), COORD wndOrg = ZERO (COORD)); 08250 08251 void* _tx_DLGTEMPLATE_Create (void* globalMem, size_t bufsize, DWORD style, DWORD exStyle, 08252 WORD controls, short x, short y, short cx, short cy, 08253 const char caption[], const char font[], WORD fontsize, 08254 const char menu[]) tx_nodiscard; 08255 08256 void* _tx_DLGTEMPLATE_Add (void* dlgTemplatePtr, size_t bufsize, DWORD style, DWORD exStyle, 08257 short x, short y, short cx, short cy, 08258 WORD id, const char wclass[], const char caption[]); 08259 08260 const char* _txProcessError (const char file[], int line, const char func[], unsigned color, 08261 const char msg[], va_list args); 08262 void _txOnTerminate(); 08263 void _txOnUnexpected(); 08264 void _txOnPureCall(); 08265 void _txOnNewHandlerAnsi(); 08266 int _txOnNewHandler (size_t size); 08267 void _txOnSignal (int signal = 0, int fpe = 0); 08268 BOOL WINAPI _txOnConsoleCtrlEvent (DWORD type); 08269 void _txOnSecurityError (int code, void*); 08270 void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code); 08271 int _txOnMatherr (_exception* except); 08272 void _txOnInvalidParam (const wchar_t* expr, const wchar_t* func, const wchar_t* file, 08273 unsigned line, uintptr_t); 08274 int _txOnAllocHook (int type, void* data, size_t size, int use, long request, 08275 const unsigned char* file, int line); 08276 int _txOnRTCFailure (int type, const char* file, int line, const char* module, const char* format, ...) tx_printfy (5); 08277 int _txOnErrorReport (int type, const char* text, int* ret); 08278 int tx_glGetError (int setError = INT_MIN); 08279 08280 void _txOnCExit(); 08281 void _txOnExit (int retcode); 08282 void _txOnFatalExit (int retcode); 08283 void _txOnExitProcess (unsigned retcode); 08284 void _txOnFatalAppExitA (unsigned action, const char message[]); 08285 bool _txOnTerminateProcess (HANDLE process, unsigned retcode); 08286 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI 08287 _txOnSetUnhandledExceptionFilter (LPTOP_LEVEL_EXCEPTION_FILTER filter); 08288 void _txWatchdogTerminator (void* timeout); // Only Arnold-type series are supported, not T1000 08289 08290 long WINAPI _txVectoredExceptionHandler (EXCEPTION_POINTERS* exc); 08291 long WINAPI _txUnhandledExceptionFilter (EXCEPTION_POINTERS* exc); 08292 long _txOnExceptionSEH (EXCEPTION_POINTERS* exc, const char func[]); 08293 intptr_t _txDumpExceptionSEH (char what[], intptr_t size, const EXCEPTION_RECORD* exc, const char func[]); 08294 intptr_t _txDumpExceptionObj (char what[], intptr_t size, void* object, size_t sizeObj, const std::type_info* type); 08295 intptr_t _txDumpExceptionCPP (char what[], intptr_t size, unsigned code = 0, 08296 unsigned params = 0, const ULONG_PTR info[] = NULL); 08297 08298 void _txStackBackTrace (const char file[] = "?", int line = 0, const char func[] = "?", 08299 bool readSource = true); 08300 const char* _txCaptureStackBackTrace (int framesToSkip = 0, bool readSource = true, 08301 CONTEXT* context = NULL, EXCEPTION_POINTERS* exc = NULL, HANDLE thread = GetCurrentThread()); 08302 int _txStackWalk (int framesToSkip, size_t szCapture, void* capture[], CONTEXT* context = NULL, 08303 HANDLE thread = GetCurrentThread()); 08304 const char* _txCaptureStackBackTraceTX (int framesToSkip = 0, bool readSource = false); 08305 08306 const char* _txSymPrintFromAddr (void* addr = NULL, const char format[] = NULL, ...) tx_printfy (2); 08307 bool _txSymGetFromAddr (void* addr, Win32::SYMBOL_INFO** symbol = NULL, 08308 Win32::IMAGEHLP_LINE64** line = NULL, const char** module = NULL, 08309 const char** source = NULL, int context = 2); 08310 intptr_t _txReadSource (char buf[], intptr_t size, const char file[], 08311 int linStart = 0, int linEnd = INT_MIN, int linMark = INT_MIN); 08312 bool _txCreateMiniDump (EXCEPTION_POINTERS* exc = NULL); 08313 08314 uintptr_t _txSetProcAddress (const char funcName[], uintptr_t newFunc, const char dllName[] = NULL, 08315 int useHotPatching = false, HMODULE module = NULL, bool debug = false); 08316 bool _txInDll() tx_nodiscard; 08317 PROCESSENTRY32* _txFindProcess (unsigned pid = GetCurrentProcessId()) tx_nodiscard; 08318 bool _txKillProcess (DWORD pid); 08319 int _txTaskKill (const char name[] /*= NULL*/, const char cmdLineSubstr[] /*= NULL*/, unsigned pid /*= 0*/); 08320 bool _txCheckSourceCP (int needCP = _TX_CODEPAGE, bool verbose = true); 08321 bool _txGetCommandLine (wchar_t cmdLine[], size_t szCmdLine, unsigned pid = _getpid()); 08322 IMAGE_NT_HEADERS*_txGetNtHeaders (HMODULE module = GetModuleHandle (NULL)) tx_nodiscard; 08323 bool _txIsConsoleSubsystem(); 08324 const char* _txAppInfo() tx_nodiscard; 08325 08326 #endif // TX_COMPILED 08327 08328 inline bool _txCanvas_OK () tx_nodiscard; 08329 int _txCanvas_SetRefreshLock (int count); 08330 08331 const char* _txError (const char file[] = NULL, int line = 0, const char func[] = NULL, unsigned color = 0, 08332 const char msg[] = NULL, ...) tx_printfy (5); 08333 08334 bool _txIsBadReadPtr (const void* address); 08335 08336 intptr_t _tx_snprintf_s (char stream[], intptr_t size, const char format[], ...) tx_printfy (3); 08337 intptr_t _tx_vsnprintf_s (char stream[], intptr_t size, const char format[], va_list arg); 08338 bool _txIsTTY (int fd); 08339 void txReopenStdio(); 08340 08341 #if defined (__CYGWIN__) 08342 08343 int _getch(); 08344 int _putch (int ch); 08345 int _kbhit() tx_nodiscard; 08346 08347 #endif 08348 08349 //----------------------------------------------------------------------------------------------------------------- 08350 // There are macros for __FILE__ and __LINE__ to work properly. 08351 08352 #if !defined (NDEBUG) 08353 08354 #define _TX_ARGUMENT_FAILED( cond ) ( !(cond) && \ 08355 (SetLastErrorEx (ERROR_BAD_ARGUMENTS, 0), 1) && \ 08356 (assert (cond), true) ) 08357 08358 #define _TX_TXWINDOW_FAILED() ( !txOK() && \ 08359 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) && \ 08360 (TX_ERROR ("\a" "Возможно, окно рисования не создано или не в порядке."), 1) ) 08361 08362 #define _TX_HDC_FAILED( dc ) ( !Win32::GetObjectType (dc) && \ 08363 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) && \ 08364 (TX_ERROR ("\a" "Параметр \"%s\" неверен." \ 08365 " Возможно, этот холст не создан, или уже уничтожен," \ 08366 " или не загрузилась картинка.", #dc), 1) ) 08367 #define _TX_DEFAULT_HDC_FAILED( dc ) ( (!(dc) && \ 08368 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) && \ 08369 (TX_ERROR ("\a" "%s" "Если вы указали параметр \"%s\", то он неверен.%s", \ 08370 !txWindow()? "Окно рисования не создано или не в порядке.\n" : "", \ 08371 #dc, \ 08372 txWindow()? " Возможно, этот холст не создан, или уже уничтожен," \ 08373 " или не загрузилась картинка." : ""), 1)) \ 08374 || \ 08375 _TX_HDC_FAILED (dc) ) 08376 #else 08377 08378 #define _TX_ARGUMENT_FAILED( cond ) ( !(cond) && \ 08379 (SetLastErrorEx (ERROR_BAD_ARGUMENTS, 0), 1) ) 08380 08381 #define _TX_TXWINDOW_FAILED() ( !txOK() && \ 08382 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) ) 08383 08384 #define _TX_HDC_FAILED( dc ) ( !Win32::GetObjectType (dc) && \ 08385 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) ) 08386 08387 #define _TX_DEFAULT_HDC_FAILED( dc ) ( !(dc) && \ 08388 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) ) 08389 #endif 08390 08391 //----------------------------------------------------------------------------------------------------------------- 08392 // Take action in debug configuration only. 08393 // Definition ({ expr; }) would be better, but MSVC rejects it. So sad. :'( 08394 08395 #if !defined (NDEBUG) 08396 #define _TX_ON_DEBUG( code ) { code; } 08397 #else 08398 #define _TX_ON_DEBUG( code ) ; 08399 #endif 08400 08401 //----------------------------------------------------------------------------------------------------------------- 08402 // Invokes an error without location information. "$$" restores TX-related call location context 08403 08404 #define _TX_UNEXPECTED( ... ) $$ _txError (NULL, 0, NULL, 0, ##__VA_ARGS__) 08405 08406 //----------------------------------------------------------------------------------------------------------------- 08407 // Safe call of a function via its pointer 08408 08409 #define _TX_CALL( func, param ) ( (func)? ((func) param) : 0 ) 08410 #define _TX_CALLv( func, param ) ( (func)? ((func) param) : (void)0 ) 08411 08412 //----------------------------------------------------------------------------------------------------------------- 08413 // This is a macro because cond is an expression and is not always a function. Lack of lambdas in pre-C++0x. 08414 08415 #define _txWaitFor( cond, time ) { for (DWORD _t = GetTickCount() + (time); \ 08416 !(cond) && GetTickCount() < _t; \ 08417 Sleep (_txWindowUpdateInterval)) \ 08418 ; \ 08419 \ 08420 if (!(cond)) \ 08421 _txTrace (__FILE__, __LINE__, NULL, "WARNING: Timeout: " #cond "."); } 08422 08423 //----------------------------------------------------------------------------------------------------------------- 08424 // Detouring in case of SEH mechanism 08425 08426 #define _txSetJmp() ( _txLocSet (&_txDumpExceptionObjLoc, __FILE__, __LINE__, __func__), \ 08427 (setjmp (_txDumpExceptionObjJmp) == 0)? true : (_txClearJmp(), false) ) 08428 08429 #define _txClearJmp() ( _txLocSet (&_txDumpExceptionObjLoc, NULL, 0, NULL), \ 08430 *(unsigned long long*) _txDumpExceptionObjJmp = 0 ) 08431 08432 //----------------------------------------------------------------------------------------------------------------- 08433 // IN and OUT are defined in WinDef.h to support Microsoft SAL. Remove them because they are often confused with user's code. 08434 08435 #if defined (IN) 08436 // #undef IN 08437 #endif 08438 08439 #if defined (OUT) 08440 // #undef OUT 08441 #endif 08442 08444 //} 08445 //================================================================================================================= 08446 08447 //================================================================================================================= 08448 //{ Internal global data 08450 // 08451 // Данные не упакованы в структуру или класс, для того, чтобы это сделали Вы сами :) 08452 // 08453 // Если вы пишете свою библиотеку и используете TXLib.h как пример, не следуйте ему и не делайте так же. 08454 // Здесь это сделано только в образовательных целях. 08455 // 08456 // Будьте практичнее, сделайте структуру и глобальную функцию для доступа к ней, или класс. 08457 //================================================================================================================= 08459 08460 #ifndef TX_COMPILED // <<<<<<< THE CODE IS HERE, UNFOLD IT <<< 08461 08462 const int _TX_IDM_ABOUT = 40000, // Идентификаторы системного меню окна 08463 _TX_IDM_CONSOLE = 40001, 08464 _TX_WM_CREATEWND = 0x7FF0, // Сообщения для создания/уничтожения 08465 _TX_WM_DESTROYWND = 0x7FF1; // окон в потоке Canvas 08466 08467 const char _TX_VSCODE_PARENTS[] = "cmd.exe:code.exe, powershell.exe:code.exe"; 08468 08469 //----------------------------------------------------------------------------------------------------------------- 08470 08471 volatile unsigned _txCanaryFirst = 0x776F656D; // A very system value 08472 08473 int _txInitialized = (_TX_NOINIT +0)? 0 : _txInitialize(); 08474 08475 volatile unsigned _txMainThreadId = 0; // ID потока, где выполняется main() 08476 volatile HANDLE _txMainThread = NULL; // Дексриптор этого потока 08477 08478 volatile unsigned _txCanvas_ThreadId = 0; // ID потока, владеющего окном холста TXLib 08479 volatile HANDLE _txCanvas_Thread = NULL; // Дексриптор этого потока 08480 volatile HWND _txCanvas_Window = NULL; // Дескриптор окна холста TXLib 08481 08482 HDC _txCanvas_BackBuf[2] = {NULL, // [0] Main TXLib in-memory DC, where user's pictures lies 08483 NULL}; // [1] Image ready for auto-refresh, see txCanvas_OnPAINT() 08484 08485 RGBQUAD* _txCanvas_Pixels = NULL; // Memory buffer of _txCanvas_BackBuf[0] 08486 08487 HBITMAP _txStockBitmap = NULL; // Equivalent of GetStockObject (BITMAP), 08488 // see https://devblogs.microsoft.com/oldnewthing/20100416-00/?p=14313 08489 08490 CRITICAL_SECTION _txCanvas_LockBackBuf = {0,-1}; // Prevent simultaneous access to back buffer, see txLock() 08491 08492 UINT_PTR _txCanvas_RefreshTimer = 1; // Timer ID to redraw TXLib window 08493 volatile int _txCanvas_RefreshLock = 0; // Blocks auto on-timer canvas update, see txBegin/txEnd 08494 08495 ::std::vector<HDC>* _txCanvas_UserDCs = NULL; // List of DCs allocated, for auto-free 08496 08497 volatile bool _txConsole_IsBlinking = true; // To blink or not to blink, that is the question. 08498 08499 int _txConsole = false; // Only first TXLib module in app can own the console 08500 bool _txMain = false; // First TXLib wnd opened (closing it terminates program) 08501 bool _txIsDll = false; // TXLib module is in DLL 08502 volatile bool _txRunning = false; // main() is still running 08503 volatile bool _txExit = false; // exit() is active 08504 08505 volatile POINT _txMousePos = {-1,-1}; // Ask Captn Obviouos about it. See txCanvas_OnMOUSE() 08506 volatile unsigned _txMouseButtons = 0; 08507 08508 volatile WNDPROC _txAltWndProc = NULL; // Альтернативная оконная функция. См. txSetWindowsHook(). 08509 08510 _tx_thread _txLoc _txLoc::Cur = {}; // Execution point tracking and trace state, see "$" macro 08511 08512 volatile int _txErrors = 0; // TX_ERROR calls sequential number 08513 volatile int _txOGLError = 0; // Last OpenGL error when using tx_glGetError() 08514 volatile long _txSENumber = 0; // SEH exceptions sequential number 08515 volatile long _txSEFatalNumber = 0; // SEH fatal exceptions sequential number 08516 char _txDumpSE [_TX_BUFSIZE] = ""; // SEH dump data area 08517 char _txTraceSE[_TX_HUGEBUFSIZE] = ""; // Stack trace data area 08518 08519 LPTOP_LEVEL_EXCEPTION_FILTER _txPrevUEFilter = NULL; // Previous UnhandledExceptionFilter 08520 08521 jmp_buf _txDumpExceptionObjJmp = {}; // Hook for _txDumpExceptionObj 08522 _txLoc _txDumpExceptionObjLoc = {}; 08523 08524 const volatile uintptr_t _txForceImport[] = { (uintptr_t) ::TerminateProcess, (uintptr_t) ::ExitProcess, 08525 (uintptr_t) ::FatalExit, (uintptr_t) ::FatalAppExitA, 08526 (uintptr_t) ::exit, (uintptr_t) Win32::_controlfp, 08527 (uintptr_t) Win32::Polyline, (uintptr_t) Win32::PolyBezier, 08528 (uintptr_t) Win32::RoundRect, (uintptr_t) Win32::RemoveVectoredExceptionHandler, 08529 (uintptr_t) Win32::PlgBlt, (uintptr_t) Win32::RtlCaptureStackBackTrace, 08530 (uintptr_t) Win32::SymInitialize, (uintptr_t) Win32::MinGW::SymInitialize, 08531 (uintptr_t) Win32::SymSetOptions, (uintptr_t) Win32::MinGW::SymSetOptions, 08532 (uintptr_t) Win32::SymGetLineFromAddr64, (uintptr_t) Win32::MinGW::SymGetLineFromAddr64, 08533 (uintptr_t) Win32::SymFromAddr, (uintptr_t) Win32::MinGW::SymFromAddr, 08534 (uintptr_t) Win32::SymCleanup, (uintptr_t) Win32::MinGW::SymCleanup, 08535 (uintptr_t) Win32::SymGetModuleBase64, (uintptr_t) Win32::MinGW::SymGetModuleBase64, 08536 (uintptr_t) Win32::SymFunctionTableAccess64, (uintptr_t) Win32::MinGW::SymFunctionTableAccess64, 08537 (uintptr_t) Win32::StackWalk64, (uintptr_t) Win32::MinGW::StackWalk64, 08538 (uintptr_t) Win32::StrStrIA, (uintptr_t) Win32::Wow64GetThreadContext }; 08539 08540 volatile unsigned _txCanaryLast = 0x5E2E2E5E; // Another very system value 08541 08542 #endif // TX_COMPILED 08543 08544 //----------------------------------------------------------------------------------------------------------------- 08545 08546 extern volatile unsigned _txCanaryFirst; 08547 extern volatile unsigned _txCanaryLast; 08548 extern volatile HWND _txCanvas_Window; 08549 extern volatile unsigned _txCanvas_ThreadId; 08550 extern HDC _txCanvas_BackBuf[2]; 08551 extern RGBQUAD* _txCanvas_Pixels; 08552 extern volatile int _txCanvas_RefreshLock; 08553 extern volatile WNDPROC _txAltWndProc; 08554 extern volatile bool _txExit; 08555 extern volatile int _txOGLError; 08556 08558 //} 08559 //================================================================================================================= 08560 08561 //================================================================================================================= 08562 //{ TXLib engine init/check/cleanup 08564 //================================================================================================================= 08566 08567 //----------------------------------------------------------------------------------------------------------------- 08568 //{ Early initialization 08569 //----------------------------------------------------------------------------------------------------------------- 08570 08571 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 08572 08573 int _txInitialize() 08574 { 08575 if (_txInitialized) return 1; 08576 _txInitialized = 1; 08577 08578 #if defined (_TX_ALLOC_BREAK) && defined (_MSC_VER) // See http://msdn.microsoft.com/en-us/library/w2fhc9a3%28v=vs.90%29.aspx 08579 _CrtSetBreakAlloc (_TX_ALLOC_BREAK); // and http://support.microsoft.com/ru-ru/kb/151585 08580 #endif 08581 08582 #if defined (_TX_ALLOW_TRACE) 08583 _txLocLvlSet (1); 08584 #endif 08585 08586 _TX_ON_DEBUG (OutputDebugString ("\n"); 08587 OutputDebugString (_TX_VERSION " - The Dumb Artist Library, " _TX_AUTHOR ": \"" __FILE__ "\" " 08588 "compiled " __DATE__ " " __TIME__ ", " _TX_BUILDMODE " mode, module: " _TX_MODULE "\n"); 08589 OutputDebugString ("\n")); 08590 08591 _txMainThreadId = GetCurrentThreadId(); 08592 _txMainThread = OpenThread (THREAD_ALL_ACCESS, false, _txMainThreadId); 08593 08594 $3 _txIsDll = _txInDll(); 08595 08596 $ if (!_txIsDll) 08597 { 08598 $ _txConsole = ! FindAtom ("_txConsole"); 08599 $ (void) AddAtom ("_txConsole"); //-V530 08600 } 08601 08602 $ if (_txConsole) 08603 { 08604 $ _txCheckSourceCP (_TX_CODEPAGE, true); 08605 08606 $ unsigned long stackSize = _TX_STACKSIZE; 08607 $ _TX_CALL (Win32::SetThreadStackGuarantee, (&stackSize)); 08608 08609 $ _txOnSignal(); 08610 08611 $ if (!*_txLogName || _txLogName[0] == '~') 08612 {$ _tx_snprintf_s (_txLogName, sizeof (_txLogName) - 1, "%s.log", txGetModuleFileName()); } 08613 08614 $ if (!_txIsDll) 08615 { 08616 #ifndef _CLANG_VER 08617 $ // _TX_CALL (Win32::AddVectoredExceptionHandler, (1, (PVECTORED_EXCEPTION_HANDLER) _txVectoredExceptionHandler)); 08618 #endif 08619 08620 $ _txPrevUEFilter = SetUnhandledExceptionFilter ( (LPTOP_LEVEL_EXCEPTION_FILTER) _txUnhandledExceptionFilter); 08621 } 08622 08623 $ ::std::set_terminate (_txOnTerminate); 08624 $ ::std::set_new_handler (_txOnNewHandlerAnsi); 08625 $ _TX_CALL (Win32::set_unexpected, (_txOnUnexpected)); 08626 08627 $ SetConsoleCtrlHandler (_txOnConsoleCtrlEvent, true); 08628 08629 $ SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); 08630 08631 #if defined (_MSC_VER) 08632 08633 $ _set_printf_count_output (1); 08634 08635 $ _set_new_handler (_txOnNewHandler); 08636 $ _set_new_mode (1); 08637 08638 #if !defined (_CLANG_VER) 08639 08640 $ _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF); 08641 $ _CrtSetAllocHook (_txOnAllocHook); 08642 08643 $ unsigned mode = _CRTDBG_MODE_FILE; 08644 $ if (_CrtSetReportHook2 (_CRT_RPTHOOK_INSTALL, (_CRT_REPORT_HOOK) _txOnErrorReport) > 0) mode = 0; 08645 08646 $ _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_DEBUG | mode); 08647 $ _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_DEBUG | mode | _CRTDBG_MODE_WNDW); 08648 $ _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_DEBUG | mode | _CRTDBG_MODE_WNDW); 08649 $ _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR); 08650 $ _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR); 08651 $ _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR); 08652 08653 #endif 08654 08655 $ _set_abort_behavior (_WRITE_ABORT_MSG, _WRITE_ABORT_MSG); 08656 $ _set_abort_behavior (0, _CALL_REPORTFAULT); 08657 08658 $ _RTC_SetErrorFunc (_txOnRTCFailure); 08659 $ _set_purecall_handler (_txOnPureCall); 08660 $ _set_invalid_parameter_handler (_txOnInvalidParam); 08661 08662 #endif 08663 08664 #if defined (__STDC_LIB_EXT1__) 08665 $ ::std::set_constraint_handler_s (_txOnSecurityErrorAnsi); 08666 #endif 08667 08668 #if !defined (__CYGWIN__) && defined (_GCC_VER) && (_GCC_VER >= 530) && !defined (i386) 08669 $ __setusermatherr (_txOnMatherr); 08670 #endif 08671 08672 #if !defined (__CYGWIN__) 08673 $ _set_error_mode (_OUT_TO_MSGBOX | _OUT_TO_STDERR); 08674 #endif 08675 08676 $ HWND console = _txConsole_Attach(); 08677 $ SetWindowTextA (console, txGetModuleFileName (false)); 08678 } 08679 08680 $ _txSetProcAddress ("ExitProcess", (uintptr_t) _txOnExitProcess, "KERNEL32.DLL"); 08681 $ _txSetProcAddress ("TerminateProcess", (uintptr_t) _txOnTerminateProcess, "KERNEL32.DLL"); 08682 $ _txSetProcAddress ("FatalExit", (uintptr_t) _txOnFatalExit, "KERNEL32.DLL"); 08683 $ _txSetProcAddress ("FatalAppExitA", (uintptr_t) _txOnFatalAppExitA, "KERNEL32.DLL"); 08684 $ _txSetProcAddress ("UnhandledExceptionFilter", (uintptr_t) _txUnhandledExceptionFilter, "KERNEL32.DLL", true); //-V601 08685 $ _txSetProcAddress ("SetUnhandledExceptionFilter", (uintptr_t) _txOnSetUnhandledExceptionFilter, "KERNEL32.DLL"); 08686 $ _txSetProcAddress ("exit", (uintptr_t) _txOnExit); 08687 $ _txSetProcAddress ("_cexit", (uintptr_t) _txOnCExit); 08688 08689 $ InitializeCriticalSection (&_txCanvas_LockBackBuf); 08690 08691 $ HDC dc = Win32::CreateCompatibleDC (NULL); dc asserted; 08692 $ _txStockBitmap = (HBITMAP) Win32::SelectObject (dc, Win32::CreateCompatibleBitmap (dc, 1, 1)); _txStockBitmap asserted; 08693 $ Win32::DeleteObject (Win32::SelectObject (dc, _txStockBitmap)) asserted; 08694 $ Win32::DeleteDC (dc) asserted; 08695 08696 $ atexit (_txCleanup); 08697 08698 $ if (_txConsole) 08699 { 08700 $ txSetConsoleAttr (FOREGROUND_LIGHTGRAY); 08701 08702 $ tx_fpreset(); 08703 08704 $ srand ((unsigned) time (NULL)); //-V202 08705 08706 $ SetLastError (0); 08707 $ errno = 0; 08708 08709 #if !defined (__CYGWIN__) 08710 $ _doserrno = 0; 08711 #endif 08712 } 08713 08714 $ UNREFERENCED_PARAMETER (Win32::CoCreateInstance); // g++ 5.1.0 bug, false warning "defined but not used" 08715 $ UNREFERENCED_PARAMETER (Win32::AddVectoredExceptionHandler); // 08716 08717 $ return 1; 08718 } 08719 08720 //----------------------------------------------------------------------------------------------------------------- 08721 08722 bool _txCheckSourceCP (int needCP /*= _TX_CODEPAGE*/, bool verbose /*= true*/) 08723 { 08724 $3 const char* sCodePage = NULL; 08725 $ int codePage = 0; 08726 08727 $ switch (((unsigned const char*) "А") [0]) 08728 { 08729 case 192: {$ codePage = 1251; sCodePage = "1251."; break; } 08730 case 208: {$ codePage = 65001; sCodePage = "UTF-8."; break; } 08731 case 128: {$ codePage = 866; sCodePage = "866."; break; } 08732 case 225: {$ codePage = 20866; sCodePage = "KOI-8, waaat?!"; break; } 08733 default: {$ codePage = -1; sCodePage = "(Unknown)"; break; } 08734 } 08735 08736 $ if (codePage != needCP && verbose) 08737 { 08738 $ *_txTraceSE = ' '; // No stack trace please 08739 08740 $ _TX_UNEXPECTED ("\v\t" "\n\n" "WARNING: CHECK TXLib.h file CODEPAGE. Maybe it is %s It should be %d.\n\n" 08741 "This is NOT an error of TXLib itself. Please note:\n\n" 08742 "Do NOT copy-and-paste TXLib.h file contents into a new file and them save it inside your " 08743 "IDE or editor. This can change original TXLib codepage (%d) to another one. Instead, DO " 08744 "use copy / move / cut-and-paste operations in Windows Explorer (Far Manager etc) only. " 08745 "Or, when you see TXLib.h being opened in browser, use 'Save as...' (Ctrl+S) command.\n\n" 08746 "Now you should re-download TXLib.h file from the http://txlib.ru site.\n\n" 08747 "You can continue, but Russian messages and symbols may appear unreadable.", 08748 sCodePage, needCP, needCP); 08749 } 08750 08751 $ return (codePage == needCP); 08752 } 08753 08754 //----------------------------------------------------------------------------------------------------------------- 08755 08756 #ifdef _TX_DEBUG_LOAD 08757 08758 HMODULE _txLoadLibrary_ (const char* dll, int line); 08759 HMODULE _txLoadLibrary_ (const char* dll, int line) 08760 { 08761 txOutputDebugPrintf (_TX_DEBUG_LOAD "[" __FILE__ ":%04d] Loading \"%s\"... ", line, dll); 08762 08763 SetLastError (0); 08764 HMODULE lib = LoadLibrary (dll); 08765 08766 if (lib) txOutputDebugPrintf (_TX_DEBUG_LOAD "SUCSESS [%p]\n", (void*) lib); 08767 else txOutputDebugPrintf (_TX_DEBUG_LOAD "error %lu\n", GetLastError()); 08768 08769 return lib; 08770 } 08771 08772 #define LoadLibraryA(dll) _txLoadLibrary_ (dll, __LINE__) 08773 08774 #endif 08775 08776 //----------------------------------------------------------------------------------------------------------------- 08777 08778 void (*_txDllImport (const char dllFileName[], const char funcName[], bool required /*= true*/)) () 08779 { 08780 if (_TX_ARGUMENT_FAILED (dllFileName && *dllFileName)) return NULL; 08781 if (_TX_ARGUMENT_FAILED (funcName && *funcName)) return NULL; 08782 08783 static char dllPaths [4][MAX_PATH] = {}; 08784 08785 if (!*dllPaths[0]) 08786 { 08787 const char dllDir[] = "\\Windows\\"; 08788 char* path = NULL; 08789 size_t sz = 0; 08790 08791 // The dllPaths[0] is a directory where executable file is located 08792 08793 path = dllPaths[0]; 08794 08795 sz = GetModuleFileName (NULL, path, MAX_PATH); path[sz] = 0; 08796 if (char* dir = strrchr (path, '\\')) dir[1] = 0; 08797 08798 // The dllPaths[1] is relative to directory where executable file is located 08799 08800 path = dllPaths[1]; 08801 08802 sz = GetModuleFileName (NULL, path, MAX_PATH); path[sz] = 0; 08803 if (char* dir = strrchr (path, '\\')) dir[0] = 0; 08804 08805 if (*path) strncat_s (path, MAX_PATH, dllDir, sizeof (dllDir) - 1); 08806 08807 // The dllPaths[2] is relative to TXib.h file used in compilation 08808 08809 path = dllPaths[2]; 08810 08811 if (strchr (__FILE__, ':')) 08812 { 08813 strncpy_s (path, MAX_PATH, __FILE__, sizeof (__FILE__) - 1); 08814 } 08815 else 08816 { 08817 // No way to get include path at compile time using simple call "gcc file.cpp" 08818 08819 sz = GetCurrentDirectory (MAX_PATH, path); path[sz] = 0; 08820 if (*path) strncat_s (path, MAX_PATH, "\\" __FILE__, sizeof ("\\" __FILE__) - 1); 08821 } 08822 08823 if (char* dir = strrchr (path, '\\')) *dir = 0; 08824 08825 if (*path) strncat_s (path, MAX_PATH, dllDir, sizeof (dllDir) - 1); 08826 08827 // The dllPaths[3] is relative to the TX Setup directory stored in the Registry 08828 08829 path = dllPaths[3]; 08830 08831 txRegQuery ("HKCU\\Software\\TX Library", "ProductDir", path, MAX_PATH); 08832 if (*path) strncat_s (path, MAX_PATH, dllDir, sizeof (dllDir) - 1); 08833 } 08834 08835 char dllName[MAX_PATH] = "", dllArch[MAX_PATH] = ""; 08836 const char* arch = (dllFileName? strchr (dllFileName, '*') : NULL); //-V547 08837 08838 if (arch) 08839 { 08840 assert (arch >= dllFileName); //-V547 08841 08842 strncpy_s (dllName, sizeof (dllName), dllFileName, (size_t) (arch - dllFileName)); 08843 strncat_s (dllName, sizeof (dllName), arch+1, sizeof (dllName) - 1 - strlen (dllName)); 08844 08845 strncpy_s (dllArch, sizeof (dllArch), dllFileName, (size_t) (arch - dllFileName)); 08846 strncat_s (dllArch, sizeof (dllArch), sizeof (void*) == 8? "64" : "32", 3); 08847 strncat_s (dllArch, sizeof (dllArch), arch+1, sizeof (dllArch) - 1 - strlen (dllArch)); 08848 } 08849 else if (dllFileName) //-V547 //-V2516 08850 { 08851 strncat_s (dllName, sizeof (dllName), dllFileName, sizeof (dllName) - 1); 08852 } 08853 08854 HMODULE dll = GetModuleHandle (dllFileName); 08855 08856 if (!dll) dll = GetModuleHandle (dllArch); 08857 if (!dll) dll = GetModuleHandle (dllName); 08858 08859 for (int i = 0; !dll && i < (int) sizearr (dllPaths); i++) 08860 { 08861 if (!dllPaths[i]) continue; 08862 08863 char path [MAX_PATH] = ""; 08864 strncpy_s (path, sizeof (path), dllPaths[i], sizeof (dllPaths[i])); 08865 size_t len = strlen (path); 08866 08867 SetDllDirectory (path); 08868 08869 strncpy_s (path + len, sizeof (path) - len, dllArch, sizeof (dllArch)); 08870 if (!dll && *dllArch) dll = LoadLibrary (path); //-V547 08871 08872 strncpy_s (path + len, sizeof (path) - len, dllName, sizeof (dllName)); 08873 if (!dll) dll = LoadLibrary (path); 08874 } 08875 08876 SetDllDirectory (NULL); 08877 08878 if (!dll && *dllArch) dll = LoadLibrary (dllArch); 08879 if (!dll) dll = LoadLibrary (dllName); 08880 08881 if (!dll && required) TX_ERROR ("\a" "Cannot load library \"%s%s%s\".", 08882 dllName, (arch? "\" / \"" : ""), dllArch); 08883 if (!dll) return NULL; 08884 08885 void (*addr)() = (void(*)()) GetProcAddress (dll, funcName); 08886 08887 if (!addr && required) TX_ERROR ("\a" "Cannot import \"%s\" from library \"%s%s%s\".", 08888 funcName, dllName, (arch? "\" / \"" : ""), dllArch); 08889 return addr; 08890 } 08891 08892 //----------------------------------------------------------------------------------------------------------------- 08893 08894 #ifdef _TX_DEBUG_LOAD 08895 #undef LoadLibraryA 08896 #endif 08897 08898 //----------------------------------------------------------------------------------------------------------------- 08899 08900 #if defined (_MSC_VER) && (_MSC_VER == 1800) // MSVC 2013 08901 #pragma warning (push) 08902 #pragma warning (disable: 6102) // Использование 'name' из завершившегося ошибкой вызова функции 08903 #endif 08904 08905 int txRegQuery (const char* keyName, const char* valueName, void* value, size_t szValue) 08906 { 08907 if (_TX_ARGUMENT_FAILED (keyName)) return 0; 08908 08909 HKEY hive = NULL; 08910 08911 #define EQU_(name1, name2) ( _strnicmp (keyName, name1 "\\", sizeof (name1)) == 0 || \ 08912 _strnicmp (keyName, name2 "\\", sizeof (name2)) == 0 ) 08913 08914 if (EQU_("HKLM", "HKEY_LOCAL_MACHINE")) hive = HKEY_LOCAL_MACHINE; 08915 else if (EQU_("HKCU", "HKEY_CURRENT_USER")) hive = HKEY_CURRENT_USER; 08916 else if (EQU_("HKCR", "HKEY_CLASSES_ROOT")) hive = HKEY_CLASSES_ROOT; 08917 else if (EQU_("HKU", "HKEY_USERS")) hive = HKEY_USERS; 08918 else if (EQU_("HKCC", "HKEY_CURRENT_CONFIG")) hive = HKEY_CURRENT_CONFIG; 08919 08920 else { _TX_ARGUMENT_FAILED (("keyName должно начинаться с HKLM\\, HKCU\\, HKCR\\, HKU\\ или HKCC\\ ", hive)); return 0; } 08921 08922 #undef EQU_ 08923 08924 keyName = strchr (keyName, '\\') + 1; //-V769 08925 assert (keyName > (const char*) 1); 08926 08927 HKEY key = NULL; 08928 DWORD size = 0; 08929 08930 bool ok = (RegOpenKeyEx (hive, keyName, 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS); 08931 if (ok) ok &= (RegQueryValueEx (key, valueName, NULL, NULL, NULL, &size) == ERROR_SUCCESS); 08932 if (ok && value && size < szValue) ok &= (RegQueryValueEx (key, valueName, NULL, NULL, (BYTE*) value, &size) == ERROR_SUCCESS); //-V104 08933 if (key) ok &= (RegCloseKey (key) == ERROR_SUCCESS); 08934 08935 return size; 08936 } 08937 08938 #if defined (_MSC_VER) && (_MSC_VER == 1800) 08939 #pragma warning (pop) 08940 #endif 08941 08942 #endif // TX_COMPILED 08943 08944 //} 08945 //----------------------------------------------------------------------------------------------------------------- 08946 08947 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 08948 08949 HWND txCreateWindow (double sizeX, double sizeY, bool centered /*= true*/) 08950 { 08951 $1 if (!_txInitialized) _txInitialized = _txInitialize(); 08952 08953 $ if (HWND wnd = txWindow()) 08954 { 08955 $ SetLastErrorEx (ERROR_INVALID_DATA, 0); 08956 $ _TX_ON_DEBUG (TX_ERROR ("\a" "Окно рисования уже создано!")); 08957 $ return wnd; 08958 } 08959 08960 $ if (!_txIsDll) 08961 { 08962 $ _txMain = ! FindAtom ("_txMain"); // Not a thread-safe 08963 $ (void) AddAtom ("_txMain"); //-V530 08964 } 08965 08966 $ if (_txWindowUpdateInterval < 10) {$ _txWindowUpdateInterval = 10; } //-V1048 08967 08968 $ _txRunning = false; 08969 08970 // Store the size 08971 08972 $ static SIZE size = { ROUND (sizeX), ROUND (sizeY) }; 08973 $ if (centered) { size.cx *= -1; size.cy *= -1; } 08974 08975 // In Thread, where REAL creation lies... 08976 08977 $ unsigned id = 0; 08978 $ _txCanvas_Thread = (HANDLE) Win32::_beginthreadex (NULL, 0, _txCanvas_ThreadProc, &size, 0, &id); 08979 08980 $ if (!_txCanvas_Thread) return TX_DEBUG_ERROR ("\a" "Cannot start canvas thread."), (HWND) NULL; 08981 08982 $ _txWaitFor (_txRunning, 10*_TX_TIMEOUT); 08983 08984 $ if (!_txRunning) return TX_DEBUG_ERROR ("\a" "Cannot create canvas window."), (HWND) NULL; 08985 $ if (!txOK()) return TX_DEBUG_ERROR ("\a" "Canvas window is not OK."), (HWND) NULL; 08986 08987 $ HWND console = Win32::GetConsoleWindow(); 08988 08989 $ DWORD proc = 0; 08990 $ GetWindowThreadProcessId (console, &proc); 08991 08992 $ if (console && (proc == GetCurrentProcessId() || _txIsParentListed (_TX_WAITABLE_PARENTS))) 08993 {$ ShowWindow (console, TX_CONSOLE_MODE); } 08994 08995 $ HMENU menu = GetSystemMenu (txWindow(), false); 08996 if (menu) {$ CheckMenuItem (menu, _TX_IDM_CONSOLE, (console? (IsWindowVisible (console)? MF_CHECKED : 0) : MF_DISABLED)); } 08997 08998 $ Win32::GdiSetBatchLimit (1); 08999 09000 $ SetLastError (0); 09001 09002 $ errno = 0; 09003 09004 #if !defined (__CYGWIN__) 09005 $ _doserrno = 0; 09006 #endif 09007 09008 $ return txWindow(); 09009 } 09010 09011 //----------------------------------------------------------------------------------------------------------------- 09012 09013 HWND txCreateExtraWindow (CREATESTRUCT createData) 09014 { 09015 $1 if (_TX_TXWINDOW_FAILED()) return NULL; 09016 09017 $ volatile HWND wnd = NULL; 09018 $ createData.hInstance = (HINSTANCE)(uintptr_t) &wnd; 09019 09020 $ PostMessage (txWindow(), _TX_WM_CREATEWND, 0, (LPARAM) &createData) asserted; 09021 09022 $ _txWaitFor (wnd, 5*_TX_TIMEOUT); 09023 09024 $ return wnd; 09025 } 09026 09027 //----------------------------------------------------------------------------------------------------------------- 09028 09029 bool txSetDefaults (HDC dc /*= txDC()*/) 09030 { 09031 $1 if (dc == txDC()) txUpdateWindow (false); //-V601 09032 $ txAutoLock _lock; 09033 09034 $ RECT r = {}; 09035 $ GetClientRect (Win32::GetConsoleWindow(), &r); 09036 $ SIZE szCon = { r.right - r.left, r.bottom - r.top }; 09037 09038 $ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE); 09039 09040 $ CONSOLE_SCREEN_BUFFER_INFO con = {{80, 25}, {}, 0, {0, 0, 80-1, 25-1}, {80, 25}}; 09041 $ GetConsoleScreenBufferInfo (out, &con); 09042 09043 $ SIZE szTxt = { (short) (con.srWindow.Right - con.srWindow.Left + 1), 09044 (short) (con.srWindow.Bottom - con.srWindow.Top + 1) }; 09045 09046 //{ Set defaults for graphics layer 09047 09048 $ _txBuffer_Select (Win32::GetStockObject (WHITE_PEN), dc) asserted; 09049 $ _txBuffer_Select (Win32::GetStockObject (WHITE_BRUSH), dc) asserted; 09050 09051 $ _txBuffer_Select (Win32::CreateFont (szCon.cy/szTxt.cy, szCon.cx/szTxt.cx, 09052 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, 09053 RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 09054 DEFAULT_QUALITY, FIXED_PITCH, TX_CONSOLE_FONT), 09055 dc) asserted; 09056 09057 $ (Win32::SetTextColor (dc, TX_WHITE) != CLR_INVALID) asserted; 09058 $ Win32::SetBkMode (dc, TRANSPARENT) asserted; 09059 09060 $ Win32::SetROP2 (dc, R2_COPYPEN) asserted; 09061 $ Win32::SetStretchBltMode (dc, HALFTONE) asserted; 09062 09063 //} 09064 09065 $ if (dc != txDC()) 09066 {$ return true; } 09067 09068 //{ Set defaults for console layer 09069 09070 $ POINT szCanvas = txGetExtent (dc); 09071 09072 $ HGDIOBJ font = txFontExist (TX_CONSOLE_FONT)? 09073 Win32::CreateFont (szCanvas.y/szTxt.cy, szCanvas.x/szTxt.cx, 09074 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, 09075 RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 09076 DEFAULT_QUALITY, FIXED_PITCH, TX_CONSOLE_FONT) 09077 : 09078 Win32::GetStockObject (SYSTEM_FIXED_FONT); 09079 09080 $ _txBuffer_Select (font, _txCanvas_BackBuf[1]); 09081 //} 09082 09083 //{ Scroll the console for text to go above top of window and don't mix with graphics 09084 09085 $ if (con.dwCursorPosition.X) _putch ('\n'); 09086 09087 $ short delta = (short) (con.dwCursorPosition.Y - con.srWindow.Top); 09088 09089 $ con.srWindow.Top = (short) (con.srWindow.Top + delta); 09090 $ con.srWindow.Bottom = (short) (con.srWindow.Bottom + delta); 09091 09092 $ SMALL_RECT src = { 0, 0, (short) (con.dwSize.X - 1), (short) (con.dwSize.Y - 1) }; 09093 $ CHAR_INFO fill = { {' '}, FOREGROUND_LIGHTGRAY }; 09094 $ COORD dest = { 0, (short) -delta }; // New UL-corner of src, scroll up 09095 09096 $ con.dwCursorPosition.X = 0; 09097 $ con.dwCursorPosition.Y = (short) (con.dwCursorPosition.Y - delta); 09098 09099 $ (con.srWindow.Bottom < con.dwSize.Y && // Move the "window" 09100 SetConsoleWindowInfo (out, true, &con.srWindow)) 09101 || 09102 (ScrollConsoleScreenBuffer (out, &src, NULL, dest, &fill), // Or scroll the buffer 09103 SetConsoleCursorPosition (out, con.dwCursorPosition)); 09104 //} 09105 09106 $ txUpdateWindow (true); //-V601 09107 09108 return true; 09109 } 09110 09111 #endif // TX_COMPILED 09112 09113 //----------------------------------------------------------------------------------------------------------------- 09114 09115 inline bool txOK() 09116 { 09117 return (_txCanaryFirst == 0x776F656D && // Too well-known values to use constants. You know these values, don't you? 09118 _txCanaryLast == 0x5E2E2E5E && 09119 _txCanvas_OK() 09120 09121 #if defined (_MSC_VER) 09122 && _CrtCheckMemory() 09123 #endif 09124 ); 09125 } 09126 09127 //----------------------------------------------------------------------------------------------------------------- 09128 //{ Cleanup 09129 //----------------------------------------------------------------------------------------------------------------- 09130 09131 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 09132 09133 // Implicit std(MSVCRT.dll)::_cexit() call before _txCleanup can lead to hangs in _cexit handlers chain. 09134 // So redefining ::std::_cexit(). Do it dynamically via PE Import Table hook to avoid duplicate symbols 09135 // if several modules linked together include TXLib.h. See _txSetProcAddress() call in _txInitialize(). 09136 09137 void _txOnCExit() 09138 { 09139 OutputDebugString ("\n"); 09140 09141 $5 _txCleanup(); 09142 09143 _TX_CALLv (Win32::_cexit, ()); 09144 } 09145 09146 //----------------------------------------------------------------------------------------------------------------- 09147 09148 void _txOnExit (int retcode) 09149 { 09150 if (retcode != 0) 09151 { 09152 OutputDebugString ("\n"); 09153 txOutputDebugPrintf ("%s - WARNING: %s (%d) called\n", _TX_VERSION, __func__, retcode); 09154 } 09155 09156 $5 _txCleanup(); 09157 09158 if (retcode != 0) 09159 txOutputDebugPrintf ("%s - WARNING: calling Win32::exit (%d)\n", _TX_VERSION, retcode); 09160 09161 Win32::exit (retcode); 09162 } 09163 09164 //----------------------------------------------------------------------------------------------------------------- 09165 09166 void _txOnExitProcess (unsigned retcode) 09167 { 09168 if (retcode != 0) 09169 { 09170 OutputDebugString ("\n"); 09171 txOutputDebugPrintf ("%s - WARNING: %s (%u) called\n", _TX_VERSION, __func__, retcode); 09172 } 09173 09174 $5 _txCleanup(); 09175 09176 if (retcode != 0) 09177 txOutputDebugPrintf ("%s - WARNING: calling Win32::ExitProcess (%u)\n", _TX_VERSION, retcode); 09178 09179 Win32::ExitProcess (retcode); 09180 } 09181 09182 //----------------------------------------------------------------------------------------------------------------- 09183 09184 bool _txOnTerminateProcess (HANDLE process, unsigned retcode) 09185 { 09186 if (retcode != 0) 09187 { 09188 OutputDebugString ("\n"); 09189 txOutputDebugPrintf ("%s - WARNING: %s (0x%p, %u) called\n", _TX_VERSION, __func__, process, retcode); 09190 } 09191 09192 $5 _txCleanup(); 09193 09194 if (retcode != 0) 09195 txOutputDebugPrintf ("%s - WARNING: calling Win32::TerminateProcess (0x%p, %u)\n", _TX_VERSION, process, retcode); 09196 09197 return Win32::TerminateProcess (process, retcode); 09198 } 09199 09200 //----------------------------------------------------------------------------------------------------------------- 09201 09202 void _txOnFatalExit (int retcode) 09203 { 09204 OutputDebugString ("\n"); 09205 txOutputDebugPrintf ("%s - WARNING: %s (%d) called\n", _TX_VERSION, __func__, retcode); 09206 09207 $5 _txCleanup(); 09208 09209 txOutputDebugPrintf ("%s - WARNING: calling Win32::FatalExit (%d)\n", _TX_VERSION, retcode); 09210 _TX_CALLv (Win32::FatalExit, (retcode)); 09211 09212 txOutputDebugPrintf ("%s - WARNING: Win32::FatalExit() failure, calling Win32::TerminateProcess (%d)\n", _TX_VERSION, retcode); 09213 Win32::TerminateProcess (GetCurrentProcess(), retcode); 09214 } 09215 09216 //----------------------------------------------------------------------------------------------------------------- 09217 09218 void _txOnFatalAppExitA (unsigned action, const char message[]) 09219 { 09220 OutputDebugString ("\n"); 09221 txOutputDebugPrintf ("%s - WARNING: %s (%u, \"%s\") called\n", _TX_VERSION, __func__, action, message); 09222 09223 $5 _txCleanup(); 09224 09225 txOutputDebugPrintf ("%s - WARNING: calling Win32::FatalAppExitA (%u, %s)\n", _TX_VERSION, action, message); 09226 _TX_CALLv (Win32::FatalAppExitA, (action, message)); 09227 09228 txOutputDebugPrintf ("%s - WARNING: Win32::FatalExit() failure, calling Win32::TerminateProcess (EXIT_FAILURE)\n", _TX_VERSION); 09229 Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE); 09230 } 09231 09232 //----------------------------------------------------------------------------------------------------------------- 09233 09234 BOOL WINAPI _txOnConsoleCtrlEvent (DWORD type) 09235 { 09236 OutputDebugString ("\n"); 09237 txOutputDebugPrintf ("%s - WARNING: %s (0x%04lX) called\n", _TX_VERSION, __func__, (unsigned long) type); 09238 09239 $5 switch (type) 09240 { 09241 case CTRL_LOGOFF_EVENT: 09242 case CTRL_SHUTDOWN_EVENT: $ _txExit = true; 09243 $ _txCleanup(); 09244 case CTRL_C_EVENT: 09245 case CTRL_CLOSE_EVENT: 09246 case CTRL_BREAK_EVENT: 09247 09248 default: break; //-V2522 09249 } 09250 09251 $ return false; 09252 } 09253 09254 //----------------------------------------------------------------------------------------------------------------- 09255 09256 void _txCleanup() 09257 { 09258 if (!_txInitialized) return; 09259 else _txInitialized = false; //-V601 09260 09261 $3 _txRunning = false; 09262 $ _txConsole_IsBlinking = false; 09263 09264 $ txSetProgress (100, (!_txErrors)? Win32::TBPF_PAUSED : Win32::TBPF_ERROR); 09265 09266 $ txSetWindowsHook (NULL); 09267 09268 $ HWND canvas = txWindow(); 09269 $ HWND console = Win32::GetConsoleWindow(); 09270 $ unsigned thread = GetCurrentThreadId(); 09271 09272 $ HWND wnd = (canvas)? canvas : console; 09273 09274 $ bool externTerm = (thread != _txMainThreadId && 09275 thread != _txCanvas_ThreadId); 09276 09277 $ DWORD list[1] = {}; 09278 $ DWORD ownsConsole = (GetConsoleProcessList (list, 1) <= 1); 09279 09280 $ int envPause = -1; 09281 $ char envPause_s[10] = ""; 09282 $ size_t envPause_sz = 0; 09283 $ getenv_s (&envPause_sz, envPause_s, sizeof (envPause_s) - 1, "TX_PAUSE"); 09284 09285 if (strcmp (envPause_s, "1") == 0 || _stricmp (envPause_s, "ON") == 0) {$ envPause = 1; } 09286 if (strcmp (envPause_s, "0") == 0 || _stricmp (envPause_s, "OFF") == 0) {$ envPause = 0; } 09287 09288 $ DWORD parent = 0; 09289 $ int isParentWaitable = _txIsParentListed (_TX_WAITABLE_PARENTS, &parent); 09290 09291 $ if (canvas) 09292 {$ txSleep (5*_txWindowUpdateInterval); } 09293 09294 $ if (_txConsole) 09295 { 09296 $ if (_txMain) txSetConsoleAttr (FOREGROUND_LIGHTGRAY); 09297 09298 $ if (console) 09299 { 09300 $ EnableWindow (console, true); 09301 $ _txSetWindowText (console, " [ЗАВЕРШЕНО]", " [FINISHED]", 2, L"\x0417" /* 'З' */ L"\x0046" /* 'F' */); 09302 } 09303 } 09304 09305 $ if (_txMain && !externTerm && canvas) 09306 {$ _txSetWindowText (canvas, " [ЗАВЕРШЕНО]", " [FINISHED]", 2, L"\x0417" /* 'З' */ L"\x0046" /* 'F' */); } 09307 09308 $ std::cout.flush(); 09309 $ std::cerr.flush(); 09310 $ std::clog.flush(); 09311 $ _flushall(); 09312 09313 $ bool paused = false; 09314 $ if (((canvas? _txMain : _txConsole) && !_txExit) || (_txErrors && thread == _txMainThreadId)) 09315 { 09316 $ if (wnd) 09317 { 09318 $ int isVSCode = _txIsParentListed (_TX_VSCODE_PARENTS); 09319 09320 $ if (isParentWaitable >= 0 && !isVSCode) 09321 {$ _txActivateWindow (wnd, 0x10); } 09322 09323 $ EnableWindow (wnd, true); 09324 } 09325 09326 $ if ((console && (ownsConsole || canvas || _txErrors || envPause == 1)) && isParentWaitable >= 0 && !(envPause == 0)) 09327 { 09328 $ txPause ((_txErrors)? "\f\n" "[Press F to Pay Respects...]" : 09329 (!canvas && _txIsTTY (0))? "\f\n" "[Нажмите любую клавишу для завершения]" : "\f"); 09330 09331 $ paused = true; 09332 } 09333 } 09334 09335 $ if (_txConsole && _txWatchdogTimeout >= 0) 09336 {$ Win32::_beginthread (_txWatchdogTerminator, 0, &_txWatchdogTimeout); } 09337 09338 $ if (txWindow()) 09339 {$ SendNotifyMessage (txWindow(), WM_DESTROY, 0, 0); } 09340 09341 $ _txWaitFor (!txWindow(), 5*_TX_TIMEOUT); 09342 09343 $ txSpeak (NULL); 09344 $ txPlayVideo (NULL); 09345 09346 $ delete _txCanvas_UserDCs; 09347 $ _txCanvas_UserDCs = NULL; 09348 09349 $ if (GetCurrentThreadId() != _txMainThreadId) 09350 {$ SuspendThread (_txMainThread); } //-V720 09351 $ if (GetCurrentThreadId() != _txCanvas_ThreadId) 09352 {$ SuspendThread (_txCanvas_Thread); } //-V720 09353 09354 $ if (_txMainThread) 09355 {$ CloseHandle (_txMainThread) asserted; _txMainThread = NULL; } 09356 $ if (_txCanvas_Thread) 09357 {$ CloseHandle (_txCanvas_Thread) asserted; _txCanvas_Thread = NULL; } 09358 09359 $ if (!txWindow()) 09360 {$ DeleteCriticalSection (&_txCanvas_LockBackBuf); CRITICAL_SECTION zero = {0, -1}; _txCanvas_LockBackBuf = zero; } 09361 09362 $ bool parentKilled = false; 09363 $ if (isParentWaitable && !externTerm && paused && _txNOP (_TX_ALLOW_KILL_PARENT)) 09364 { 09365 $ console = Win32::GetConsoleWindow(); 09366 09367 $ if (parent) 09368 {$ parentKilled = _txKillProcess (parent); } 09369 09370 $ if (parent && !parentKilled) 09371 { 09372 $ PostMessage (console, WM_KEYDOWN, VK_RETURN, 0x001C0001); // Scancode = 0x1C, Count = 1 09373 $ PostMessage (console, WM_KEYUP, VK_RETURN, 0xC01C0001); // Scancode = 0x1C, Count = 1, Prev = 1, Trans = 1 09374 } 09375 } 09376 09377 $ if (_txConsole) 09378 {$ _txSetWindowText (console, NULL); } 09379 09380 $ if (_txMain && _txConsole) 09381 {$ _txConsole_Detach (isParentWaitable && !externTerm && !parentKilled); } //-V560 09382 09383 $ std::cout.flush(); 09384 $ std::cerr.flush(); 09385 $ std::clog.flush(); 09386 $ _flushall(); 09387 09388 $ _txSymGetFromAddr (NULL); 09389 09390 // That's all, folks 09391 09392 _TX_ON_DEBUG (OutputDebugString ("\n"); 09393 OutputDebugString (_TX_VERSION " - FINISHED: " _TX_MODULE "\n"); 09394 OutputDebugString ("\n")); 09395 } 09396 09397 //----------------------------------------------------------------------------------------------------------------- 09398 09399 int txPause (const char* message /*= NULL*/, ...) 09400 { 09401 $3 bool wine = !!Win32::wine_get_version; 09402 09403 $ HWND canvas = txWindow(); 09404 $ HWND console = _TX_CALL (Win32::GetConsoleWindow,()); 09405 $ HWND wnd = (canvas)? canvas : console; 09406 $ bool istty0 = _txIsTTY (0); 09407 09408 $ int attr = txGetConsoleAttr(); 09409 09410 $ int oldCP = GetConsoleOutputCP(); 09411 $ SetConsoleOutputCP (_TX_CODEPAGE); 09412 09413 if (!message) {$ message = "[Нажмите любую клавишу для продолжения]"; } 09414 09415 if (*message != '\f') {$ _txSetWindowText (wnd, " [Нажмите клавишу...]", " [Press a key...]"); } 09416 else {$ message++; } 09417 09418 if (*message != '\v') {$ txSetConsoleAttr (FOREGROUND_LIGHTGRAY); } 09419 else {$ message++; } 09420 09421 $ int isVSCode = _txIsParentListed (_TX_VSCODE_PARENTS); 09422 09423 $ if (!isVSCode) 09424 {$ _txActivateWindow (wnd, 0x10); } 09425 09426 $ va_list args; 09427 $ va_start (args, message); 09428 $ vfprintf (stderr, message, args); 09429 $ va_end (args); 09430 09431 $ txOutputDebugPrintf ("%s - WARNING: PAUSE: %s\n", _TX_VERSION, (*message != '\n')? message : message+1); 09432 09433 $ fflush (stderr); 09434 $ txSleep(); 09435 09436 $ Win32::FLASHWINFO flash = { sizeof (flash), wnd, FLASHW_ALL | FLASHW_TIMERNOFG, 0xFFFFFFFF }; 09437 $ _TX_CALL (Win32::FlashWindowEx, (&flash)); 09438 09439 if (console) {$ EnableWindow (console, true); } 09440 09441 $ int ch = EOF; 09442 if (istty0) {$ while (!wine && _kbhit()) ch = _getch(); } 09443 09444 $ for (int i = 1; ; i++) //-V2530 09445 { 09446 $ Sleep (_txWindowUpdateInterval); 09447 09448 if (!istty0 && !canvas) {$ break; } 09449 09450 if (!wine && (ch = _txGetInput()) != EOF) {$ break; } 09451 09452 if (canvas && !_txCanvas_ThreadId) {$ break; } 09453 09454 if (!_TX_CALL (Win32::GetConsoleWindow, ())) {$ break; } 09455 09456 if (_TX_CALL (Win32::GhostWindowFromHungWindow, (canvas))) 09457 {$ TX_ERROR ("Похоже, программа зависла :("); break; } 09458 09459 if (canvas && _TX_CALL (Win32::IsHungAppWindow, (canvas))) 09460 {$ _txTrace (__FILE__, __LINE__, NULL, "WARNING: Программа-таки зависла"); break; } 09461 09462 if (canvas && !SendMessageTimeout (canvas, WM_NULL, 0,0, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL)) 09463 {$ _txTrace (__FILE__, __LINE__, NULL, "WARNING: Программа не отвечает"); break; } 09464 09465 if (!wine && !(i % 100500)) 09466 {$ fprintf (stderr, "\r" "[Так нажмите же какую-нибудь клавишу...] \b\b"); } 09467 } 09468 09469 if (istty0) {$ while (!wine && _kbhit()) ch = _getch(); } 09470 09471 $ _txSetWindowText (wnd, NULL); 09472 09473 $ fprintf (stderr, "\n"); 09474 09475 if (ch == 3 /* Ctrl+C */) {$ raise (SIGABRT); } 09476 09477 $ SetConsoleOutputCP (oldCP); 09478 $ txSetConsoleAttr (attr); 09479 09480 $ return ch; 09481 } 09482 09483 //----------------------------------------------------------------------------------------------------------------- 09484 09485 int _txGetInput() 09486 { 09487 $4 HANDLE con = GetStdHandle (STD_INPUT_HANDLE); 09488 $ int ch = EOF; 09489 09490 $ DWORD nChars = 0; 09491 $ if (GetConsoleMode (con, &nChars) == 0 && 09492 PeekNamedPipe (con, NULL, 0, NULL, &nChars, NULL)) 09493 { 09494 $ ch = (nChars)? fgetc (stdin) : EOF; 09495 } 09496 09497 else if (_kbhit()) 09498 { 09499 $ ch = _getch(); 09500 } 09501 09502 #if defined (_MSC_VER) && (_MSC_VER < 1700) 09503 09504 else if (fseek (stdin, 1, SEEK_CUR) != EOF) 09505 { 09506 $ (void) fseek (stdin, -1, SEEK_CUR); 09507 $ ch = fgetc (stdin); // This causes blocking in MSVC 2011 beta 09508 } 09509 09510 #endif 09511 09512 if (ch == 3 /* Ctrl+C */) {$ raise (SIGABRT); } 09513 09514 $ return ch; 09515 } 09516 09517 //----------------------------------------------------------------------------------------------------------------- 09518 09519 bool _txIsTTY (int fd) 09520 { 09521 $4 return GetFileType ((HANDLE)_get_osfhandle (fd)) == FILE_TYPE_CHAR; 09522 } 09523 09524 //----------------------------------------------------------------------------------------------------------------- 09525 09526 int _txSetWindowText (HWND wnd, const char* textRus, const char* textEng /*= NULL*/, 09527 int checkOfs /*= 0*/, const wchar_t checkLetters[2] /*= NULL*/) 09528 { 09529 struct tools 09530 { 09531 static LRESULT getWindowText (HWND window, wchar_t text[], size_t size) 09532 { 09533 $3 memset (text, 0, size * sizeof (*text)); 09534 09535 $ return SendMessageTimeoutW (window, WM_GETTEXT, (WPARAM) size, (LPARAM) text, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL); 09536 } 09537 09538 static LRESULT setWindowText (HWND window, wchar_t text[]) 09539 { 09540 $1 return SendMessageTimeoutW (window, WM_SETTEXT, 0, (LPARAM) text, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL); 09541 } 09542 }; 09543 09544 $1 static wchar_t _tx_thread title [_TX_BUFSIZE+15] = L"TXLib"; 09545 $ static wchar_t _tx_thread oldTitle [_TX_BUFSIZE+15] = L"TXLib"; 09546 09547 $ if (!textRus) 09548 { 09549 $ tools::setWindowText (wnd, oldTitle); 09550 $ return -1; 09551 } 09552 09553 $ tools::getWindowText (wnd, title, _TX_BUFSIZE-1); 09554 $ int len = (int) wcslen (title); if (len >= (int)_TX_BUFSIZE) len = _TX_BUFSIZE-1; 09555 $ memcpy (oldTitle, title, sizeof (oldTitle)); 09556 09557 $ if (textRus) 09558 { 09559 $ MultiByteToWideChar (_TX_CODEPAGE, 0, textRus, -1, title + len, (int)_TX_BUFSIZE - len); 09560 09561 $ tools::setWindowText (wnd, title); 09562 $ tools::getWindowText (wnd, title, _TX_BUFSIZE-1); 09563 if (checkLetters && len <= (int)_TX_BUFSIZE-1-2 && title [len + checkOfs] == checkLetters[0]) {$ return 0; } 09564 if (!checkLetters) {$ return -2; } 09565 } 09566 09567 $ if (textEng) 09568 { 09569 $ MultiByteToWideChar (_TX_CODEPAGE, 0, textEng, -1, title + len, (int)_TX_BUFSIZE - len); 09570 09571 $ tools::setWindowText (wnd, title); 09572 $ tools::getWindowText (wnd, title, _TX_BUFSIZE-1); 09573 if (checkLetters && len <= (int)_TX_BUFSIZE-1-2 && title [len + checkOfs] == checkLetters[1]) {$ return 1; } 09574 if (!checkLetters) {$ return -2; } 09575 } 09576 09577 $ return -3; 09578 } 09579 09580 //----------------------------------------------------------------------------------------------------------------- 09581 09582 int _txIsParentListed (const char* list, DWORD* parentPID /*= NULL*/) 09583 { 09584 $4 PROCESSENTRY32* info = _txFindProcess(); 09585 $ if (!info) return 0; 09586 09587 $ info = _txFindProcess (info->th32ParentProcessID); 09588 $ if (!info) return 0; 09589 09590 $ char parent [MAX_PATH] = ""; 09591 $ strncpy_s (parent, sizeof (parent), info->szExeFile, sizeof (parent) - 1); 09592 $ if (parentPID) *parentPID = info->th32ProcessID; 09593 09594 $ info = _txFindProcess (info->th32ParentProcessID); // info: grandparent 09595 09596 $ char lst[_TX_BUFSIZE] = ""; 09597 $ strncpy_s (lst, sizeof (lst), list, strlen (list)); 09598 09599 $ char* ctx = NULL; 09600 $ for (char* p = strtok_s (lst, ", ", &ctx); p; p = strtok_s (NULL, ", ", &ctx)) 09601 { 09602 $ char* gp = strchr (p, ':'); 09603 09604 $ if (gp) 09605 { 09606 $ *gp++ = 0; 09607 09608 $ if (_stricmp (p, parent) != 0) { continue; } 09609 09610 $ if (info) if (_stricmp (gp, info->szExeFile) == 0) // Was &&, but MSVC /analyze is so paranoid 09611 {$ return islower ((unsigned char) *gp)? +1 : -1; } 09612 } 09613 else 09614 { 09615 $ if (_stricmp (p, parent) == 0) 09616 {$ return islower ((unsigned char) *p)? +1 : -1; } 09617 } 09618 } 09619 09620 $ return 0; 09621 } 09622 09623 //----------------------------------------------------------------------------------------------------------------- 09624 09625 void _txWatchdogTerminator (void* timeout) // Or Watchcat? Possibly will change in future versions 09626 { 09627 $3 if (_TX_ARGUMENT_FAILED (timeout)) return; 09628 09629 $ Sleep (*(int*) timeout); //-V206 09630 09631 $ OutputDebugString ("\n"); 09632 txOutputDebugPrintf ("%s - WARNING: %s(): Timeout (%d) expired, activating. %s\n", // Kinda static reflection... 09633 _TX_VERSION, __func__, *(int*) timeout, ((__func__[8] == 'd')? "Bark, bark" : "Meow, meow")); //-V206 09634 $ DWORD parent = 0; 09635 $ if (_txIsParentListed (_TX_WAITABLE_PARENTS, &parent)) 09636 { 09637 txOutputDebugPrintf ("%s - WARNING: %s(): Calling _txKillProcess (0x%04lu)\n", 09638 _TX_VERSION, __func__, (unsigned long) parent); 09639 09640 $ _txKillProcess (parent); 09641 09642 $ HWND console = GetConsoleWindow(); 09643 $ PostMessage (console, WM_KEYDOWN, VK_RETURN, 0x001C0001); // Scancode = 0x1C, Count = 1 09644 $ PostMessage (console, WM_KEYUP, VK_RETURN, 0xC01C0001); // Scancode = 0x1C, Count = 1, Prev = 1, Trans = 1 09645 } 09646 09647 txOutputDebugPrintf ("%s - WARNING: %s(): Calling Win32::TerminateProcess (EXIT_FAILURE)\n", _TX_VERSION, __func__); 09648 $ Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE); 09649 } 09650 09651 #endif // TX_COMPILED 09652 09653 //} 09654 //----------------------------------------------------------------------------------------------------------------- 09655 09656 //----------------------------------------------------------------------------------------------------------------- 09657 //{ Tools 09658 //----------------------------------------------------------------------------------------------------------------- 09659 09660 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 09661 09662 // You are here, little hacker? 09663 09664 int _txTaskKill (const char i[] /*= NULL*/, 09665 const char doYouWantToFindSomethingInTheCommandLineIDidSomethingForYouToFindSomethingInTheCommandLineMaybeYouWillFindSomeInterestingInTheCommandLineSoIDidSomethingForYouInTheCommandLine[] /*= NULL*/, 09666 unsigned x /*= 0*/) 09667 { 09668 // ...so tired of it already... 09669 09670 #define name i // Great name! 09671 #define cmdLineSubstr doYouWantToFindSomethingInTheCommandLineIDidSomethingForYouToFindSomethingInTheCommandLineMaybeYouWillFindSomeInterestingInTheCommandLineSoIDidSomethingForYouInTheCommandLine 09672 #define pid x // Another great name, isn't it? 09673 09674 $3 if (_TX_ARGUMENT_FAILED ((name || cmdLineSubstr || pid) && "Вот такие тут интересные имена встречаются...")) return false; //-V560 //-V601 09675 09676 $ wchar_t cmdLineSubstrW[_TX_BUFSIZE] = L""; 09677 if (cmdLineSubstr) {$ MultiByteToWideChar (_TX_CODEPAGE, 0, cmdLineSubstr, -1, cmdLineSubstrW, sizearr (cmdLineSubstrW)); } 09678 09679 $ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); 09680 $ assert (sshot); if (!sshot) return 0; //-V547 09681 09682 $ int killed = 0; 09683 09684 $ PROCESSENTRY32 info = { sizeof (info) }; 09685 $ for (bool ok = !!Process32First (sshot, &info); ok; ok = !!Process32Next (sshot, &info)) 09686 { 09687 bool kill = false; 09688 09689 if (!kill && pid && info.th32ParentProcessID == pid) {$ kill = true; } //-V560 09690 09691 if (!kill && name && _stricmp (info.szExeFile, name) == 0) {$ kill = true; } 09692 09693 if (!kill) 09694 { 09695 wchar_t cmdLineW[_TX_BUFSIZE] = L""; 09696 if (!_txGetCommandLine (cmdLineW, sizearr (cmdLineW), info.th32ProcessID)) { continue; } 09697 09698 if (*cmdLineW && stristrw (cmdLineW, cmdLineSubstrW)) {$ kill = true; } 09699 } 09700 09701 if (kill) 09702 { 09703 $ if (_txKillProcess (info.th32ProcessID)) 09704 {$ killed++; } 09705 } 09706 } 09707 09708 $ CloseHandle (sshot); 09709 09710 $ return killed; 09711 09712 #undef name 09713 #undef cmdLine 09714 #undef pid 09715 } 09716 09717 //----------------------------------------------------------------------------------------------------------------- 09718 09719 bool _txKillProcess (DWORD pid) 09720 { 09721 $3 if (_TX_ARGUMENT_FAILED (pid)) return false; 09722 09723 $ HANDLE token = INVALID_HANDLE_VALUE; 09724 $ OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) asserted; 09725 09726 $ LUID luid = {}; 09727 $ LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &luid) asserted; 09728 09729 $ TOKEN_PRIVILEGES priv = { 1, {{{ luid.LowPart, luid.HighPart}, SE_PRIVILEGE_ENABLED }}}; 09730 $ TOKEN_PRIVILEGES old = {}; 09731 09732 $ DWORD oldSz = 0; 09733 $ AdjustTokenPrivileges (token, false, &priv, sizeof (priv), &old, &oldSz) asserted; 09734 09735 $ HANDLE proc = OpenProcess (PROCESS_ALL_ACCESS, 0, pid); 09736 $ if (!proc) return false; 09737 09738 $ bool ok = !!Win32::TerminateProcess (proc, 0); 09739 $ CloseHandle (proc); 09740 09741 $ return ok; 09742 } 09743 09744 //----------------------------------------------------------------------------------------------------------------- 09745 09746 PROCESSENTRY32* _txFindProcess (unsigned pid /*= GetCurrentProcessId()*/) 09747 { 09748 $4 static PROCESSENTRY32 info = { sizeof (info) }; 09749 $ if (!pid) return &info; 09750 09751 $ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); 09752 $ assert (sshot); if (!sshot) return NULL; //-V547 09753 09754 $ for (bool ok = !!Process32First (sshot, &info); ok; ok = !!Process32Next (sshot, &info)) 09755 if (info.th32ProcessID == pid) break; 09756 09757 $ CloseHandle (sshot); 09758 09759 $ return &info; 09760 } 09761 09762 //----------------------------------------------------------------------------------------------------------------- 09763 09764 bool _txGetCommandLine (wchar_t cmdLine[], size_t szCmdLine, unsigned pid /*= _getpid()*/) 09765 { 09766 $9 if (_TX_ARGUMENT_FAILED (cmdLine)) return false; 09767 $ if (_TX_ARGUMENT_FAILED (szCmdLine >= 2)) return false; //-V547 09768 09769 $ if (pid == (unsigned) _getpid()) 09770 { 09771 $ wcsncpy_s (cmdLine, szCmdLine, GetCommandLineW(), szCmdLine-1); 09772 $ return true; 09773 } 09774 09775 $ HANDLE proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid); 09776 if (!proc) {$ return false; } 09777 09778 $ Win32::PROCESS_BASIC_INFORMATION pbi = {}; 09779 $ bool ok = (Win32::NtQueryInformationProcess (proc, 0 /*ProcessBasicInformation*/, &pbi, sizeof (pbi), NULL) == 0); 09780 09781 // Should use ReadProcessMemory() because the info is actually in another address space 09782 09783 $ Win32::PEB peb = {}; 09784 if (ok && pbi.PebBaseAddress) {$ ok &= !!ReadProcessMemory (proc, pbi.PebBaseAddress, &peb, sizeof (peb), NULL); } 09785 09786 $ Win32::RTL_USER_PROCESS_PARAMETERS params = {}; 09787 if (ok && peb.ProcessParameters) {$ ok &= !!ReadProcessMemory (proc, peb.ProcessParameters, ¶ms, sizeof (params), NULL); } 09788 09789 $ *cmdLine = 0; 09790 if (ok && params.CommandLine.Buffer) {$ ok &= !!ReadProcessMemory (proc, params.CommandLine.Buffer, cmdLine, //-V106 09791 MIN (params.CommandLine.Length + 2, (int) (szCmdLine * sizeof (*cmdLine)) - 2), //-V202 09792 NULL); } 09793 $ CloseHandle (proc) asserted; 09794 09795 $ return ok; 09796 } 09797 09798 //----------------------------------------------------------------------------------------------------------------- 09799 09800 #define RVA_(type, module, addr) ( (type) ((uintptr_t) (module) + (uintptr_t) (addr)) ) 09801 09802 IMAGE_NT_HEADERS* _txGetNtHeaders (HMODULE module /*= GetModuleHandle (NULL)*/) 09803 { 09804 $4 assert (module); 09805 09806 $ IMAGE_DOS_HEADER* dosHdr = RVA_ (IMAGE_DOS_HEADER*, module, 0); 09807 $ IMAGE_NT_HEADERS* ntHdr = RVA_ (IMAGE_NT_HEADERS*, module, dosHdr->e_lfanew); 09808 09809 $ return (dosHdr->e_magic == IMAGE_DOS_SIGNATURE && 09810 ntHdr->Signature == IMAGE_NT_SIGNATURE)? ntHdr : NULL; 09811 } 09812 09813 //----------------------------------------------------------------------------------------------------------------- 09814 09815 // TXLib continues to hack the reality to make your life better, sweeter and easier 09816 09817 #ifdef _CLANG_VER 09818 #pragma clang attribute push (__attribute__((no_sanitize ("undefined"))), apply_to = function) 09819 #endif 09820 09821 uintptr_t _txSetProcAddress (const char funcName[], uintptr_t newFunc, const char dllName[] /*= NULL*/, int useHotPatching /*= false*/, 09822 HMODULE module /*= NULL*/, bool debug /*= false*/) 09823 { 09824 $4 if (debug) txOutputDebugPrintf ("_txSetProcAddress (%s, 0x%p, %s, 0x%p):\n", funcName, (void*) newFunc, dllName, (void*) module); 09825 09826 $ if (_TX_ARGUMENT_FAILED (funcName)) return 0; 09827 $ if (_TX_ARGUMENT_FAILED (newFunc)) return 0; 09828 09829 $ if (!module) module = GetModuleHandle (NULL); 09830 $ if (!module) return 0; 09831 09832 $ HMODULE dll = (dllName)? GetModuleHandle (dllName) : NULL; 09833 $ PROC oldFunc = (dll)? GetProcAddress (dll, funcName) : NULL; 09834 09835 $ if (useHotPatching && oldFunc) 09836 { 09837 $ const size_t jmpSz = 1 + sizeof (DWORD); // sizeof (JMP rel instruction) 09838 09839 $ DWORD oldRights = 0; 09840 $ if (!VirtualProtect ((void*)(uintptr_t) oldFunc, jmpSz, PAGE_EXECUTE_READWRITE, &oldRights)) return 0; 09841 09842 // Overwrite oldFunc prolog with JMP trampoline to newFunc. 09843 // Calling oldFunc from any location will lead to newFunc call anyway. 09844 09845 $ *(BYTE*) ((char*)(uintptr_t) oldFunc + 0) = 0xE9; // JMP rel 09846 $ *(DWORD*) ((char*)(uintptr_t) oldFunc + 1) = ((char*)(uintptr_t) newFunc - (char*)(uintptr_t) oldFunc - jmpSz) & 0xFFFFFFFF; //-V206 //-V112 //-V2007 //-V104 //-V103 09847 09848 $ FlushInstructionCache (GetCurrentProcess(), (void*)(uintptr_t) oldFunc, jmpSz); 09849 09850 $ VirtualProtect ((void*)(uintptr_t) oldFunc, jmpSz, oldRights, &oldRights); 09851 09852 $ return (uintptr_t) oldFunc; 09853 } 09854 09855 // For PE structure and Import Table format, e.g. see https://books.google.ru/books?id=ifQPC86G66sC&pg=PA255 09856 // and below through Figure 5-5, and/or http://www.brokenthorn.com/Resources/OSDevPE.html. 09857 09858 $ IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders (module); 09859 if (!ntHdr || (ntHdr ->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)) {$ return 0; } 09860 09861 $ DWORD impOffset = ntHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 09862 $ IMAGE_IMPORT_DESCRIPTOR* desc = RVA_ (IMAGE_IMPORT_DESCRIPTOR*, module, impOffset); 09863 09864 $ if (desc == (IMAGE_IMPORT_DESCRIPTOR*) ntHdr) return 0; //-V1027 09865 09866 $ IMAGE_THUNK_DATA* thunk0 = NULL, * thunk1 = NULL; 09867 $ char* impDll = NULL; 09868 $ char* impName = NULL; 09869 $ void** impPtr = NULL; 09870 $ bool found = false; 09871 09872 for (; desc->Name; desc++) 09873 { 09874 $ impDll = RVA_ (char*, module, desc->Name); 09875 $ if (dllName && _stricmp (impDll, dllName) != 0) continue; 09876 09877 $ for (thunk0 = RVA_ (IMAGE_THUNK_DATA*, module, desc->OriginalFirstThunk), 09878 thunk1 = RVA_ (IMAGE_THUNK_DATA*, module, desc->FirstThunk); 09879 09880 thunk0 && thunk1 && thunk1->u1.Function; 09881 09882 thunk0++, 09883 thunk1++) 09884 { 09885 impName = (char*) RVA_ (IMAGE_IMPORT_BY_NAME*, module, thunk0->u1.AddressOfData) -> Name; 09886 impPtr = (void**)(uintptr_t) &thunk1->u1.Function; // Should change it, so this is ptr 09887 09888 if (IsBadReadPtr (impName, sizeof (impName))) impName = NULL; 09889 09890 if (debug) txOutputDebugPrintf ("[0x%p] %s!%s\n", *impPtr, impDll, impName); 09891 09892 if ((oldFunc && (uintptr_t) oldFunc == (uintptr_t) *impPtr) || 09893 (impName && _stricmp (funcName, impName) == 0)) //-V560 09894 { 09895 found = true; 09896 break; 09897 } 09898 } 09899 09900 $ if (found) break; 09901 } 09902 09903 if (debug) txOutputDebugPrintf ("_txSetProcAddress (%s, 0x%p, %s, 0x%p): %s\n\n", 09904 funcName, (void*) newFunc, dllName, (void*) module, (found? "FOUND" : "NOT found")); 09905 $ if (!found) return 0; 09906 09907 $ DWORD rights = PAGE_READWRITE; 09908 $ if (!VirtualProtect (impPtr, sizeof (*impPtr), rights, &rights)) return 0; 09909 09910 $ *(uintptr_t*) impPtr = newFunc; 09911 09912 $ VirtualProtect (impPtr, sizeof (*impPtr), rights, &rights); 09913 09914 $ return (uintptr_t) oldFunc; 09915 } 09916 09917 #ifdef _CLANG_VER 09918 #pragma clang attribute pop 09919 #endif 09920 09921 #undef RVA_ 09922 09923 //----------------------------------------------------------------------------------------------------------------- 09924 09925 bool _txInDll() 09926 { 09927 $4 MODULEENTRY32 mod = { sizeof (mod) }; 09928 09929 $ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0); 09930 $ assert (sshot); if (!sshot) return false; //-V547 09931 09932 $ bool inDll = false; 09933 09934 $ for (bool ok = !!Module32First (sshot, &mod); ok; ok = !!Module32Next (sshot, &mod)) 09935 { 09936 $ if (!mod.modBaseAddr) continue; 09937 09938 $ IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders ((HMODULE) mod.modBaseAddr); 09939 09940 $ inDll = ntHdr && ((ntHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0); 09941 09942 $ if (In (std::nomeow, (BYTE*)(uintptr_t)_txInDll, mod.modBaseAddr, mod.modBaseAddr + mod.modBaseSize)) //-V104 09943 {$ break; } 09944 } 09945 09946 $ CloseHandle (sshot); 09947 $ return inDll; 09948 } 09949 09950 //----------------------------------------------------------------------------------------------------------------- 09951 09952 bool _txIsConsoleSubsystem() 09953 { 09954 $4 IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders(); 09955 09956 $ return ntHdr && 09957 ntHdr ->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC && 09958 09959 (ntHdr ->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI || 09960 ntHdr ->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_POSIX_CUI); 09961 } 09962 09963 //----------------------------------------------------------------------------------------------------------------- 09964 09965 bool _txIsBadReadPtr (const void* address) 09966 { 09967 MEMORY_BASIC_INFORMATION mbi = {}; 09968 if (!VirtualQuery (address, &mbi, sizeof (mbi))) return true; 09969 09970 if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) return true; // Guard page -> bad ptr 09971 09972 DWORD readRights = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; 09973 09974 return !(mbi.Protect & readRights); 09975 } 09976 09977 //----------------------------------------------------------------------------------------------------------------- 09978 09979 void _txActivateWindow (HWND wnd, unsigned mode) 09980 { 09981 $1 EnableWindow (wnd, true); 09982 09983 $ if (mode & 0x20) 09984 { 09985 $ ShowWindow (wnd, SW_MINIMIZE); 09986 $ ShowWindow (wnd, SW_RESTORE); 09987 } 09988 09989 $ if (mode & 0x10) 09990 { 09991 $ int focus = GetWindowThreadProcessId (GetForegroundWindow(), 0); 09992 09993 $ AttachThreadInput (GetCurrentThreadId(), focus, true); 09994 09995 $ ShowWindow (wnd, SW_SHOW); 09996 09997 $ AllowSetForegroundWindow (ASFW_ANY); 09998 $ LockSetForegroundWindow (LSFW_UNLOCK); 09999 $ keybd_event ((byte) VK_LMENU, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); // https://stackoverflow.com/questions/10740346 10000 $ SetForegroundWindow (wnd); 10001 10002 $ _txWaitFor (GetForegroundWindow() == wnd, _TX_TIMEOUT); 10003 10004 $ AttachThreadInput (GetCurrentThreadId(), focus, false); 10005 } 10006 10007 $ if (mode & 0x08) 10008 { 10009 $ SetWindowPos (wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); 10010 } 10011 10012 $ if (mode & 0x04) 10013 { 10014 $ SetWindowPos (wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_ASYNCWINDOWPOS); 10015 } 10016 10017 $ if (mode & 0x02) 10018 { 10019 $ UpdateWindow (wnd); 10020 } 10021 10022 $ if (mode & 0x01) 10023 { 10024 $ RECT r = {}; 10025 $ GetWindowRect (wnd, &r); 10026 $ mouse_event (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN, r.left, r.top, 0, 0); 10027 $ Sleep (100); 10028 $ mouse_event (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP, r.left, r.top, 0, 0); 10029 $ Sleep (100); 10030 } 10031 } 10032 10033 #endif // TX_COMPILED 10034 10035 //} 10036 //----------------------------------------------------------------------------------------------------------------- 10037 10039 //} 10040 //================================================================================================================= 10041 10042 //================================================================================================================= 10043 //{ Internal TXLib window functions (_txCanvas...) 10045 //================================================================================================================= 10046 10047 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 10048 10049 unsigned WINAPI _txCanvas_ThreadProc (void* data) 10050 { 10051 #define SetClassLong_ SetClassLongPtr 10052 #define GCL_HICON_ GCLP_HICON 10053 #define GCL_HICONSM_ GCLP_HICONSM 10054 #define GCL_HCURSOR_ GCLP_HCURSOR 10055 10056 $8 _txCanvas_ThreadId = GetCurrentThreadId(); 10057 10058 $ if (_TX_ARGUMENT_FAILED (data)) return false; //-V601 10059 10060 $ unsigned long stackSize = _TX_STACKSIZE; 10061 $ _TX_CALL (Win32::SetThreadStackGuarantee, (&stackSize)); 10062 10063 $ HWND wnd = _txCanvas_CreateWindow ((SIZE*) data); 10064 $ if (!txWindow()) return TX_DEBUG_ERROR ("\a" "Cannot create canvas!"), 0; 10065 10066 $ HICON icon32 = LoadIcon (NULL, "_TX_ICON"); 10067 $ HICON icon16 = LoadIcon (NULL, "_TX_ICONSM"); 10068 $ HCURSOR cursor = LoadCursor (NULL, "_TX_CURSOR"); 10069 $ HMENU menu = LoadMenu (NULL, "_TX_MENU"); 10070 $ HACCEL accel = LoadAccelerators (NULL, "_TX_ACCELERATORS"); 10071 10072 $ SetClassLong_ (wnd, GCL_HICON_, (LONG_PTR) (icon32? icon32 : _txCreateTXIcon (32))); //-V107 //-V112 10073 $ SetClassLong_ (wnd, GCL_HICONSM_, (LONG_PTR) (icon16? icon16 : _txCreateTXIcon (16))); //-V107 10074 $ SetClassLong_ (wnd, GCL_HCURSOR_, (LONG_PTR) (cursor? cursor : LoadCursor (NULL, IDC_ARROW))); //-V107 10075 10076 if (menu) {$ SetMenu (wnd, menu); DrawMenuBar (wnd); } 10077 10078 $ Win32::GdiSetBatchLimit (1); 10079 10080 _TX_ON_DEBUG (OutputDebugString (_TX_VERSION " - STARTED: " _TX_MODULE "\n")); 10081 10082 $ _txActivateWindow (wnd, 0x20); 10083 10084 $ ShowWindow (wnd, SW_SHOW); 10085 $ UpdateWindow (wnd); 10086 10087 $ _txRunning = true; 10088 10089 $ MSG msg = {}; 10090 $ while (GetMessage (&msg, NULL, 0, 0)) 10091 { 10092 if (!msg.hwnd) {$ continue; } 10093 10094 if (accel && TranslateAccelerator (wnd, accel, &msg)) {$ continue; } 10095 10096 $ TranslateMessage (&msg); 10097 $ DispatchMessage (&msg); 10098 10099 $ Sleep (0); 10100 } 10101 10102 $ if (icon16) DestroyIcon (icon16); // If Explorer is displaying Tray Notification, these 10103 $ if (icon32) DestroyIcon (icon32); // calls will possibly fail, and we'll get resource leak. 10104 10105 $ LeaveCriticalSection (&_txCanvas_LockBackBuf); 10106 10107 _TX_ON_DEBUG (OutputDebugString (_TX_VERSION " - STOPPED: " _TX_MODULE "\n")); 10108 10109 $ if (_txWatchdogTimeout >= 0) 10110 {$ Win32::_beginthread (_txWatchdogTerminator, 0, &_txWatchdogTimeout); } 10111 10112 $ if (_txRunning && _txMain) // Main window is destroyed but main() is still running. 10113 { // No chances for good termination, so use exit(). 10114 $ _txCleanup(); 10115 $ ::exit ((int) msg.wParam); //-V202 //-V2509 //-V2014 10116 } 10117 10118 $ _txCanvas_ThreadId = 0; 10119 $ return true; //-V601 10120 10121 #undef SetClassLong 10122 #undef GCL_HICON_ 10123 #undef GCL_HICONSM_ 10124 #undef GCL_HCURSOR_ 10125 } 10126 10127 //----------------------------------------------------------------------------------------------------------------- 10128 10129 HWND _txCanvas_CreateWindow (const SIZE* sizePtr) 10130 { 10131 $8 if (_TX_ARGUMENT_FAILED (sizePtr)) return NULL; 10132 10133 $ bool centered = false; 10134 if (sizePtr->cx < 0 && sizePtr->cy < 0) {$ centered = true; } 10135 10136 $ SIZE screen = { GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN) }; 10137 $ RECT rect = { 0, 0, abs (sizePtr->cx), abs (sizePtr->cy) }; AdjustWindowRect (&rect, _txWindowStyle, false); 10138 $ SIZE size = { rect.right - rect.left, rect.bottom - rect.top }; 10139 $ RECT conPos = {}; 10140 10141 $ HWND console = _TX_CALL (Win32::GetConsoleWindow, ()); 10142 if (console) {$ GetWindowRect (console, &conPos); } 10143 10144 $ const char* wndClass = txRegisterClass ("MAIN", _txCanvas_WndProc, CS_HREDRAW | CS_VREDRAW | CS_OWNDC, BLACK_BRUSH, 0); 10145 $ if (!wndClass) return (HWND) NULL; 10146 10147 $ HWND wnd = CreateWindowEx (WS_EX_APPWINDOW, wndClass, txGetModuleFileName (false), _txWindowStyle | WS_CLIPCHILDREN, 10148 (centered)? screen.cx/2 - size.cx/2 : (console)? conPos.left : CW_USEDEFAULT, 10149 (centered)? screen.cy/2 - size.cy/2 : (console)? conPos.top : CW_USEDEFAULT, 10150 size.cx, size.cy, NULL, NULL, NULL, NULL); 10151 $ if (!wnd || !txWindow()) 10152 {$ return TX_DEBUG_ERROR ("Cannot create canvas: CreateWindowEx() failed"), (HWND) NULL; } 10153 10154 $ HMENU menu = GetSystemMenu (txWindow(), false); 10155 if (!menu) {$ return txWindow(); } 10156 10157 $ AppendMenu (menu, MF_SEPARATOR, 0, NULL) asserted; 10158 $ AppendMenu (menu, MF_STRING, _TX_IDM_CONSOLE, "Show &Console") asserted; 10159 $ AppendMenu (menu, MF_STRING, _TX_IDM_ABOUT, "&About...") asserted; 10160 10161 $ return txWindow(); 10162 } 10163 10164 //----------------------------------------------------------------------------------------------------------------- 10165 10166 const char* txRegisterClass (const char classId[], WNDPROC wndProc, unsigned style, int backBrush, int wndExtra) 10167 { 10168 $8 assert (classId); 10169 $ assert (wndProc); 10170 10171 $ static char name[_TX_BUFSIZE] = ""; 10172 $ _tx_snprintf_s (name, sizeof (name) - 1, "/*---[TXLib]-[%s]------------ " 10173 _TX_VERSION " " __FILE__ " WndClass %08lX " 10174 "-------------[%s]-[TXLib]---*/", 10175 classId, (unsigned long) GetTickCount(), classId); 10176 $ WNDCLASS wc = { sizeof (wc) }; 10177 10178 $ wc.lpszClassName = name; 10179 $ wc.lpfnWndProc = wndProc; 10180 $ wc.style = style; 10181 $ wc.cbWndExtra = (wndExtra + 1) * (int) sizeof (long); 10182 10183 $ wc.hCursor = LoadCursor (NULL, IDC_ARROW); 10184 $ wc.hbrBackground = (HBRUSH) Win32::GetStockObject (backBrush); 10185 10186 $ ATOM atom = RegisterClass (&wc); 10187 if (!atom) {$ TX_DEBUG_ERROR ("RegisterClass (\"%s\") failed", name); return 0; } 10188 10189 $ return (const char*)(uintptr_t) atom; 10190 } 10191 10192 //----------------------------------------------------------------------------------------------------------------- 10193 10194 int _txCanvas_SetRefreshLock (int count) 10195 { 10196 $8 int oldCount = _txCanvas_RefreshLock; 10197 10198 $ _txCanvas_RefreshLock = count; 10199 10200 $ HWND wnd = txWindow(); 10201 10202 $ if ((_txCanvas_RefreshLock <= 0 || oldCount <= 0) && wnd) 10203 {$ RedrawWindow (wnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_UPDATENOW); } 10204 10205 $ return oldCount; 10206 } 10207 10208 //----------------------------------------------------------------------------------------------------------------- 10209 10210 HICON _txCreateTXIcon (int size) 10211 { 10212 $8 if (_TX_ARGUMENT_FAILED (size == 32 || size == 16)) return NULL; //-V112 //-V560 10213 10214 $ const unsigned char image32 [32*32+1] = 10215 "00000000000000000000000000000000""0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0""0F0000000000000000000000000000F0""0F0000000000000000000000000000F0" 10216 "0F0000000000000099999999999900F0""0F0000000000000090300333330900F0""0F0000000990000090000000000900F0""0F00000099990000900BB000000900F0" 10217 "0F0000039999000090B00090900900F0""0F0000009999000090B00999990900F0""0F00000009903799900BB090900900F0""0F000000009BB70090000010000900F0" 10218 "0F0000000B90000090000000000900F0""0F000000B0B0000099999999999900F0""0F00007B30B0000090000000000000F0""0F00007300B0000090000000000000F0" 10219 "0F00000000B3000090000000000000F0""0F0000000B0B000090000000000000F0""0F000000B303B00090000000000000F0""0F000003B000B00090000000000000F0" 10220 "0F00003B00003B0090000000000000F0""0F0000300000030090000000000000F0""0F0000000448888888888844000000F0""0F00004886E6E6E60E66E6EEEE4400F0" 10221 "0F4488866E0E60E00660E06E66EEE4F0""0F868806E06E06E666E66E00E06EE6F0""0F08606E66E0066000E006E66E00E6F0""0F8666E006600E00006600E006E00EF0" 10222 "0F000E066888888888888888606660F0""0F66EEE6EE000E00000E00086EEEE6F0""0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0""00000000000000000000000000000000"; 10223 10224 $ const unsigned char image16 [16*16+1] = 10225 "0000000000000000""0000000999999990""0009000900000090""0099900909973090""0059700909009390""0009799909973090""0099000900000090""0959330999999990" 10226 "0709500900000000""0095930900000000""0090393900000000""0790073900000000""0900000900000000""000EE6E6E6E6E000""0EE6E6E6E6E6EEE0""0000000000000000"; 10227 10228 $ const COLORREF pal['F'-'0'+1] = { 0x000000, 0x002b2b, 0x555500, 0x005555, 0x808000, 0x008080, 0xaaaa00, 0x00aaaa, 0xd5d500, 0x00d5d5, 0,0,0,0,0,0,0, 10229 0xffff00, 0x00ffff, 0xffffaa, 0xaaffff, 0xd5d500, 0xffffff }; 10230 10231 $ const unsigned char* image = (size == 32)? image32 : image16; //-V112 10232 10233 $ POINT sz = { size, size }; 10234 $ HDC dcMask = _txBuffer_Create (txWindow(), &sz); assert (dcMask); 10235 $ HDC dcColor = _txBuffer_Create (txWindow(), &sz); assert (dcColor); 10236 10237 $ for (int i = 0; i < size*size; i++) 10238 { 10239 assert (In (std::nomeow, image[i], '0', '9') || 10240 In (std::nomeow, image[i], 'A', 'F')); 10241 10242 Win32::SetPixel (dcColor, i % size, i / size, pal [image[i] - '0']); 10243 } 10244 10245 $ ICONINFO info = { true, 0, 0, (HBITMAP) Win32::GetCurrentObject (dcMask, OBJ_BITMAP), 10246 (HBITMAP) Win32::GetCurrentObject (dcColor, OBJ_BITMAP) }; 10247 10248 $ HICON icon = CreateIconIndirect (&info); 10249 $ assert (icon); 10250 10251 $ _txBuffer_Delete (&dcMask) asserted; 10252 $ _txBuffer_Delete (&dcColor) asserted; 10253 10254 $ return icon; 10255 } 10256 10257 #endif // TX_COMPILED 10258 10259 //----------------------------------------------------------------------------------------------------------------- 10260 10261 inline bool _txCanvas_OK() 10262 { 10263 return _txCanvas_ThreadId && 10264 _txCanvas_Window && 10265 _txCanvas_BackBuf[0] && 10266 _txCanvas_BackBuf[1] && 10267 _txCanvas_Pixels; 10268 } 10269 10270 //} 10271 //================================================================================================================= 10272 10273 //================================================================================================================= 10274 //{ Main window event handlers (_txCanvas_On...) 10276 //================================================================================================================= 10278 10279 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 10280 10281 LRESULT CALLBACK _txCanvas_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar) 10282 { 10283 #if defined (_TX_ALLOW_TRACE) 10284 10285 int inTX = _txLoc::Cur.inTX++; 10286 10287 if (_txLoc::Cur.trace) _txTrace (__FILE__, __LINE__, __TX_FUNCTION__, "%*s" "0x%X <- 0x%04X (0x%08X, 0x%08lX)", 10288 2 * (_txLoc::Cur.inTX - 1), "", wnd, msg, wpar, lpar); 10289 _txLoc::Cur.inTX = inTX; 10290 10291 #endif 10292 10293 $8 if (msg == WM_KEYDOWN && wpar == VK_F12 && 10294 GetKeyState (VK_SHIFT) && GetKeyState (VK_CONTROL) && GetKeyState (VK_MENU)) 10295 { 10296 $ _txCanvas_OnCmdABOUT (wnd, wpar); 10297 $ return DefWindowProc (wnd, msg, wpar, lpar); 10298 } 10299 10300 WNDPROC altWndProc = _txAltWndProc; // Cache to prevent change from main thread 10301 if (altWndProc) 10302 { 10303 $ LRESULT res = altWndProc (wnd, msg, wpar, lpar); 10304 $ if (res) return res; 10305 } 10306 10307 static bool bkErased = false; 10308 10309 switch (msg) 10310 { 10311 case WM_CREATE: {$ _txCanvas_OnCREATE (wnd); return 0; } 10312 10313 case WM_CLOSE: {$ if (_txCanvas_OnCLOSE (wnd)) break; else return 0; } 10314 case WM_DESTROY: {$ _txCanvas_OnDESTROY (wnd); return 0; } 10315 10316 case WM_ERASEBKGND: {$ if (!bkErased) { bkErased = true; break; } else return 1; } 10317 case WM_SIZE: {$ bkErased = false; break; } 10318 10319 case WM_PAINT: {$ _txCanvas_OnPAINT (wnd); return 0; } 10320 10321 case WM_TIMER: {$ _txCanvas_OnTIMER (wnd, wpar); return 0; } 10322 10323 case WM_KEYUP: {$ if (_txCanvas_OnKEY (wnd, wpar, lpar, false)) return 0; else break; } 10324 case WM_KEYDOWN: {$ if (_txCanvas_OnKEY (wnd, wpar, lpar, true)) return 0; else break; } 10325 case WM_CHAR: {$ if (_txCanvas_OnCHAR (wnd, wpar, lpar)) return 0; else break; } 10326 10327 case WM_LBUTTONUP: 10328 case WM_LBUTTONDOWN: 10329 case WM_RBUTTONUP: 10330 case WM_RBUTTONDOWN: 10331 case WM_MBUTTONUP: 10332 case WM_MBUTTONDOWN: 10333 case WM_MOUSEMOVE: {$ _txCanvas_OnMOUSEMOVE (wnd, wpar, lpar); return 0; } 10334 10335 case WM_MOUSELEAVE: {$ _txCanvas_OnMOUSELEAVE (wnd); return 0; } 10336 10337 case _TX_WM_CREATEWND: {$ _txCanvas_OnCREATEWND (wnd, wpar, lpar); return 0; } 10338 case _TX_WM_DESTROYWND: {$ _txCanvas_OnDESTROYWND (wnd, wpar, lpar); return 0; } 10339 10340 case WM_NULL: {$ return 0; } 10341 10342 default: break; //-V2522 10343 } 10344 10345 if (msg == WM_SYSCOMMAND) switch (wpar) 10346 { 10347 case _TX_IDM_ABOUT: {$ _txCanvas_OnCmdABOUT (wnd, wpar); return 0; } 10348 case _TX_IDM_CONSOLE: {$ _txCanvas_OnCmdCONSOLE (wnd, wpar); return 0; } 10349 10350 default: break; //-V2522 10351 } 10352 10353 $ return DefWindowProc (wnd, msg, wpar, lpar); 10354 } 10355 10356 //----------------------------------------------------------------------------------------------------------------- 10357 10358 bool _txCanvas_OnCREATE (HWND wnd) 10359 { 10360 $8 if (_TX_ARGUMENT_FAILED (wnd)) return false; 10361 10362 $ _txCanvas_BackBuf[0] = _txBuffer_Create (wnd, NULL, NULL, &_txCanvas_Pixels); assert (_txCanvas_BackBuf[0]); 10363 $ _txCanvas_BackBuf[1] = _txBuffer_Create (wnd, NULL, NULL, NULL); assert (_txCanvas_BackBuf[1]); 10364 10365 $ if (!SetTimer (wnd, _txCanvas_RefreshTimer, _txWindowUpdateInterval, NULL)) _txCanvas_RefreshTimer = 0; 10366 $ assert (_txCanvas_RefreshTimer); 10367 10368 $ _txCanvas_UserDCs = new ::std::vector <HDC>; 10369 10370 $ _txCanvas_Window = wnd; 10371 10372 $ txSetDefaults(); 10373 10374 $ return true; 10375 } 10376 10377 //----------------------------------------------------------------------------------------------------------------- 10378 10379 bool _txCanvas_OnDESTROY (HWND wnd) 10380 { 10381 $8 if (_TX_ARGUMENT_FAILED (wnd)) return false; 10382 10383 // Инициируем остановку цикла сообщений 10384 10385 $ PostQuitMessage (_txRunning? WM_DESTROY : EXIT_SUCCESS); 10386 10387 $ if (!_txCanvas_Window) return false; 10388 10389 // Indicate that we are about to manually terminate 10390 10391 $ _txExit = true; 10392 10393 // Lock GDI resources 10394 10395 $ bool locked = false; 10396 $ _txWaitFor ((locked = txLock (false), locked), _TX_TIMEOUT); 10397 $ if (!locked) TX_DEBUG_ERROR ("Cannot lock GDI to free resources"); 10398 10399 // Освобождаем пользовательские ресурсы 10400 10401 $ if (_txCanvas_UserDCs && !_txCanvas_UserDCs->empty()) 10402 { 10403 $ txNotifyIcon (NIIF_ERROR, NULL, "Вы забыли освободить %d HDC.", (int) _txCanvas_UserDCs->size()); //-V202 10404 $ Sleep (_TX_TIMEOUT); 10405 10406 $ for (size_t i = 0; i < _txCanvas_UserDCs->size(); i++) _txBuffer_Delete (&_txCanvas_UserDCs->at (i)); 10407 $ _txCanvas_UserDCs->clear(); 10408 } 10409 10410 // Освобождаем ресурсы, связанные с окном 10411 10412 $ if (_txCanvas_RefreshTimer) KillTimer (wnd, _txCanvas_RefreshTimer) asserted; 10413 10414 $ if (_txCanvas_BackBuf[1]) _txBuffer_Delete (&_txCanvas_BackBuf[1]) asserted; 10415 $ if (_txCanvas_BackBuf[0]) _txBuffer_Delete (&_txCanvas_BackBuf[0]) asserted; 10416 $ _txCanvas_Pixels = NULL; 10417 10418 $ txUnlock(); 10419 10420 // Indicate that we are destroyed 10421 10422 $ _txCanvas_Window = NULL; 10423 10424 $ return true; 10425 } 10426 10427 //----------------------------------------------------------------------------------------------------------------- 10428 10429 bool _txCanvas_OnCLOSE (HWND wnd) //-V2009 //-V2558 10430 { 10431 $8 if (_TX_ARGUMENT_FAILED (wnd)) return false; 10432 $ if (!_txCanvas_OK()) return false; 10433 10434 $ if (_txMain && _txRunning && 10435 txMessageBox ("Функция main() не завершена. Программа все еще работает. Прервать аварийно?\n\n" 10436 "Лучше подождать, когда main() завершится - это отображается в заголовке окна.", 10437 txGetModuleFileName (false), MB_YESNOCANCEL | MB_ICONSTOP) != IDYES) return false; 10438 $ return true; 10439 } 10440 10441 //----------------------------------------------------------------------------------------------------------------- 10442 10443 bool _txCanvas_OnTIMER (HWND wnd, WPARAM) 10444 { 10445 $8 if (_TX_ARGUMENT_FAILED (wnd)) return false; 10446 10447 $ if (_txCanvas_RefreshLock > 0 || !_txRunning) return false; 10448 10449 $ InvalidateRect (wnd, NULL, false) asserted; 10450 $ UpdateWindow (wnd) asserted; 10451 10452 $ return true; 10453 } 10454 10455 //----------------------------------------------------------------------------------------------------------------- 10456 10457 bool _txCanvas_OnPAINT (HWND wnd) 10458 { 10459 $8 if (_TX_ARGUMENT_FAILED (wnd)) return false; 10460 $ if (!_txCanvas_OK()) return false; 10461 10462 $ bool forceRedraw = GetAsyncKeyState (VK_MENU) && GetAsyncKeyState (VK_CONTROL) && 10463 GetAsyncKeyState (VK_SHIFT) && GetAsyncKeyState (VK_SNAPSHOT); 10464 10465 $ PAINTSTRUCT ps = {}; 10466 $ HDC wndDc = BeginPaint (wnd, &ps); 10467 $ if (!wndDc) return false; 10468 10469 $ HDC dc0 = _txCanvas_BackBuf[0], 10470 dc1 = _txCanvas_BackBuf[1]; 10471 10472 $ RECT r = {}; 10473 $ GetClientRect (wnd, &r) asserted; 10474 $ POINT wndSize = { r.right - r.left, r.bottom - r.top }; 10475 10476 $ POINT dcSize = txGetExtent (dc1); 10477 10478 $ if ((_txCanvas_RefreshLock <= 0 || forceRedraw) && 10479 txLock (false)) 10480 { 10481 $ Win32::BitBlt (dc1, 0, 0, dcSize.x, dcSize.y, dc0, 0, 0, SRCCOPY); 10482 10483 $ if (_txConsole >= 0) 10484 {$ _txConsole_Draw (dc1); } 10485 10486 $ txUnlock(); 10487 } 10488 10489 // Magic 100500 value is used to completely block screen refresh. 10490 // Since no value can be 100500 or above, this condition is always true and the refresh cannot be blocked IRL. 10491 // Do not use 100501 because it may lead to errors on some compilers and possible may crash the compilers 10492 // themselves. 10493 // Yes guys, with all your software installed. :( 10494 10495 $ if (_txCanvas_RefreshLock != 100500) 10496 { 10497 if (_txSwapBuffers) 10498 { 10499 $ _txSwapBuffers (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, dcSize.x, dcSize.y, SRCCOPY); 10500 } 10501 else if (dcSize.x == wndSize.x && dcSize.y == wndSize.y) 10502 { 10503 $ Win32::BitBlt (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, SRCCOPY); 10504 } 10505 else 10506 { 10507 $ Win32::SetStretchBltMode (wndDc, HALFTONE); 10508 $ Win32::StretchBlt (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, dcSize.x, dcSize.y, SRCCOPY); 10509 } 10510 } 10511 10512 $ EndPaint (wnd, &ps) asserted; 10513 10514 $ return true; 10515 } 10516 10517 //----------------------------------------------------------------------------------------------------------------- 10518 10519 bool _txCanvas_OnCHAR (HWND, WPARAM ch, LPARAM info) 10520 { 10521 $8 INPUT_RECORD evt[2] = {}; 10522 10523 $ evt[0].EventType = KEY_EVENT; 10524 $ evt[0].Event.KeyEvent.bKeyDown = true; 10525 $ evt[0].Event.KeyEvent.wRepeatCount = 1; 10526 $ evt[0].Event.KeyEvent.uChar.AsciiChar = (char) (ch); 10527 $ evt[0].Event.KeyEvent.wVirtualScanCode = (WORD) (info >> 16); 10528 $ evt[0].Event.KeyEvent.wVirtualKeyCode = (WORD) MapVirtualKey ((WORD) (info >> 16), 3); // 3 == MAPVK_VSC_TO_VK_EX 10529 $ evt[0].Event.KeyEvent.dwControlKeyState = 0; 10530 10531 $ evt[1] = evt[0]; 10532 $ evt[1].Event.KeyEvent.bKeyDown = false; 10533 10534 $ DWORD written = 0; 10535 $ WriteConsoleInput (GetStdHandle (STD_INPUT_HANDLE), evt, 2, &written); 10536 10537 $ return true; 10538 } 10539 10540 //----------------------------------------------------------------------------------------------------------------- 10541 10542 bool _txCanvas_OnKEY (HWND, WPARAM vk, LPARAM info, bool down) 10543 { 10544 $8 INPUT_RECORD evt = {}; 10545 10546 $ evt.EventType = KEY_EVENT; 10547 $ evt.Event.KeyEvent.bKeyDown = down; 10548 $ evt.Event.KeyEvent.wRepeatCount = 1; 10549 $ evt.Event.KeyEvent.uChar.AsciiChar = (char) MapVirtualKey ((WORD) vk, 2); // 2 == MAPVK_VK_TO_CHAR 10550 $ evt.Event.KeyEvent.wVirtualScanCode = (WORD) (info >> 16); 10551 $ evt.Event.KeyEvent.wVirtualKeyCode = (WORD) vk; 10552 $ evt.Event.KeyEvent.dwControlKeyState = (DWORD) (info & (1 << (24-1)))? ENHANCED_KEY : 0; 10553 10554 $ if (evt.Event.KeyEvent.uChar.AsciiChar) return false; // Let TranslateMessage() and WM_CHAR do the job 10555 10556 $ DWORD written = 0; 10557 $ WriteConsoleInput (GetStdHandle (STD_INPUT_HANDLE), &evt, 1, &written); 10558 10559 $ return true; 10560 } 10561 10562 //----------------------------------------------------------------------------------------------------------------- 10563 10564 bool _txCanvas_OnMOUSEMOVE (HWND wnd, WPARAM buttons, LPARAM coords) 10565 { 10566 $8 if (_TX_ARGUMENT_FAILED (wnd)) return false; 10567 $ if (!_txCanvas_OK()) return false; 10568 10569 $ if (_txMousePos.x == -1 && _txMousePos.y == -1) 10570 { 10571 $ TRACKMOUSEEVENT track = { sizeof (track), TME_HOVER | TME_LEAVE, wnd, HOVER_DEFAULT }; 10572 $ TrackMouseEvent (&track); 10573 } 10574 10575 $ _txMousePos.x = LOWORD (coords); 10576 $ _txMousePos.y = HIWORD (coords); 10577 $ _txMouseButtons = (unsigned) buttons; //-V202 10578 10579 $ return true; 10580 } 10581 10582 //----------------------------------------------------------------------------------------------------------------- 10583 10584 bool _txCanvas_OnMOUSELEAVE (HWND) 10585 { 10586 $8 _txMousePos.x = -1; 10587 $ _txMousePos.y = -1; 10588 $ _txMouseButtons = 0; 10589 10590 $ return true; 10591 } 10592 10593 //----------------------------------------------------------------------------------------------------------------- 10594 10595 bool _txCanvas_OnCREATEWND (HWND, WPARAM, LPARAM lpar) 10596 { 10597 $8 if (_TX_ARGUMENT_FAILED (lpar)) return false; 10598 10599 $ const CREATESTRUCT* create = (CREATESTRUCT*) lpar; 10600 10601 $ HWND wnd = CreateWindowEx (create->dwExStyle, create->lpszClass, create->lpszName, create->style, 10602 create->x, create->y, create->cx, create->cy, 10603 create->hwndParent, create->hMenu, NULL, create->lpCreateParams); 10604 10605 $ *(HWND*) create->hInstance = wnd; 10606 10607 $ return true; 10608 } 10609 10610 //----------------------------------------------------------------------------------------------------------------- 10611 10612 bool _txCanvas_OnDESTROYWND (HWND, WPARAM, LPARAM lpar) 10613 { 10614 $8 if (_TX_ARGUMENT_FAILED (lpar)) return false; 10615 10616 $ DestroyWindow ((HWND) lpar); 10617 10618 $ return false; 10619 } 10620 10621 //----------------------------------------------------------------------------------------------------------------- 10622 10623 bool _txCanvas_OnCmdCONSOLE (HWND wnd, WPARAM cmd) 10624 { 10625 $8 if (_TX_ARGUMENT_FAILED (wnd)) return false; 10626 10627 $ HWND console = Win32::GetConsoleWindow(); 10628 $ if (!console) return false; 10629 10630 $ bool visible = !!IsWindowVisible (console); 10631 10632 $ ShowWindow (console, visible? SW_HIDE : SW_RESTORE); 10633 10634 $ visible = !!IsWindowVisible (console); 10635 $ CheckMenuItem (GetSystemMenu (wnd, false), (int) cmd, visible? MF_CHECKED : MF_UNCHECKED); //-V202 10636 10637 $ return true; 10638 } 10639 10640 //----------------------------------------------------------------------------------------------------------------- 10641 10642 bool _txCanvas_OnCmdABOUT (HWND, WPARAM) 10643 { 10644 $8 //{ Overriding the missing names, if the set is incomplete 10645 10646 #if defined (__MODULE) 10647 #define ABOUT_NAME_ __MODULE 10648 #else 10649 #define ABOUT_NAME_ "TXLib" 10650 #endif 10651 10652 #if defined (__MODULE) || defined (__VERSION) || defined (__DESCRIPTION) || defined (__AUTHOR) 10653 10654 #ifndef __MODULE 10655 #define __MODULE "TXLib" "\n" "#define __MODULE to set the name.\n" 10656 #endif 10657 10658 #ifndef __VERSION 10659 #define __VERSION "(0.000000000)." "\n" "#define __VERSION to set the string value.\n" 10660 #endif 10661 10662 #ifndef __DESCRIPTION 10663 #define __DESCRIPTION "(Да, мне лень задать описание)." "\n" "#define __DESCRIPTION to override project role.\n" 10664 #endif 10665 10666 #ifndef __AUTHOR 10667 #define __AUTHOR "(Непонятно кто)." "\n" "#define __AUTHOR to override this name." 10668 #endif 10669 10670 #endif 10671 //} 10672 10673 $ static char text[_TX_BUFSIZE] = ""; 10674 10675 $ _tx_snprintf_s (text, sizeof (text) - 1, 10676 10677 "Application:\n\n" 10678 10679 #if defined (__MODULE) || defined (__VERSION) || defined (__DESCRIPTION) || defined (__AUTHOR) 10680 __MODULE " version " __VERSION "\n" __DESCRIPTION "\n" "Copyright (c) " __AUTHOR "\n" 10681 #else 10682 "Здесь могла бы быть Ваша реклама :)\n" 10683 "#define __MODULE to \"your program name\" before including TXLib.h to use this billboard...\n" 10684 #endif 10685 10686 "\n" "%s", _txAppInfo()); 10687 10688 $ txMessageBox (text, "About " ABOUT_NAME_, MB_ICONINFORMATION); 10689 10690 // And a bit of HTTP-code in C++ function: 10691 10692 goto http; 10693 http://sizeof.livejournal.com 10694 10695 $ return true; 10696 10697 #undef ABOUT_NAME_ 10698 } 10699 10700 #endif // TX_COMPILED 10701 10703 //} 10704 //================================================================================================================= 10705 10706 //================================================================================================================= 10707 //{ Console-support functions (_txConsole...) 10709 //================================================================================================================= 10711 10712 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 10713 10714 HWND _txConsole_Attach() 10715 { 10716 $1 HWND console = Win32::GetConsoleWindow(); 10717 10718 $ if (!console) 10719 { 10720 $ bool minimizeConsole = ((TX_CONSOLE_MODE) == SW_HIDE && !_txIsConsoleSubsystem()); 10721 10722 $ Win32::TEB* teb = (Win32::TEB*) NtCurrentTeb(); 10723 $ assert (teb); 10724 $ assert (teb->ProcessEnvironmentBlock); 10725 10726 $ Win32::RTL_USER_PROCESS_PARAMETERS* params = teb->ProcessEnvironmentBlock->ProcessParameters; 10727 $ assert (params); 10728 10729 $ if (minimizeConsole) // The fact that ShowWindow parameter of the program's console is taken from calling 10730 // process' STARTUPINFO, was researched from Windows XP sources. See SetUpConsoleInfo() 10731 // in windows\core\ntcon\client\dllinit.c. No one can miss stealing Windows sources. :( 10732 // Thank you Matt Pietrek, the author of "Undocumented Windows". Use the Source, Luke! 10733 { 10734 $ params->dwFlags |= STARTF_USESHOWWINDOW; 10735 $ params->wShowWindow = SW_MINIMIZE; 10736 } 10737 10738 $ AllocConsole(); 10739 $ console = Win32::GetConsoleWindow(); 10740 } 10741 10742 $ if (!console) return NULL; 10743 10744 $ txSetLocale(); // Устанавливаем русскую кодовую страницу для консоли Windows 10745 10746 $ _txConsole_SetUnicodeFont(); // Впечатлительным лучше сюда не смотреть. 10747 10748 $ if (!_txIsConsoleSubsystem()) 10749 {$ txReopenStdio(); } // Переоткрываем потоки ввода-вывода, если subsystem != console 10750 10751 $ return console; 10752 } 10753 10754 //----------------------------------------------------------------------------------------------------------------- 10755 10756 int txSetLocale (int codepage /*= _TX_CODEPAGE*/, 10757 const char locale[] /*= _TX_LOCALE*/, const wchar_t wLocale[] /*= _TX_WLOCALE*/) 10758 { 10759 $1 int oldPage = GetConsoleOutputCP(); 10760 10761 // Устанавливаем нужную кодовую страницу для консоли Windows 10762 10763 $ if (codepage) 10764 { 10765 $ SetConsoleCP (codepage); 10766 $ SetConsoleOutputCP (codepage); 10767 } 10768 10769 // Устанавливаем нужную кодовую страницу для стандартной библиотеки, иначе не будут работать Unicode-версии 10770 // функций (wprintf, ...). Если компилите с помощью gcc и собираетесь использовать L"unicode-строки" с определенным 10771 // языком, укажите опции в командной строке компилятора g++: -finput-charset=NNNN -fexec-charset=NNNN, где NNNN - 10772 // обозначение кодовой страницы (например, для русского языка - CP1251). 10773 10774 $ if (locale) 10775 { 10776 $ setlocale (LC_ALL, locale); 10777 $ setlocale (LC_NUMERIC, "C"); // Return to decimal point (3.14) instead of comma (3,14) in floating numbers 10778 } 10779 10780 #ifndef __CYGWIN__ 10781 10782 $ const bool wine = !!Win32::wine_get_version; // Linux::Wine v1.2.2+ compatibility. 10783 10784 $ if (wLocale && !wine) 10785 { 10786 $ _wsetlocale (LC_ALL, wLocale); 10787 $ _wsetlocale (LC_NUMERIC, L"C"); // L"C" (see above) 10788 } 10789 10790 #endif 10791 10792 (void) wLocale; 10793 10794 $ return oldPage; 10795 } 10796 10797 //----------------------------------------------------------------------------------------------------------------- 10798 10799 void txReopenStdio() 10800 { 10801 $1 // Переоткрываем заново <s>Америку</s> потоки ввода-вывода 10802 10803 $ fflush (stdout); 10804 $ fflush (stderr); 10805 10806 $ FILE* f = NULL; 10807 10808 #ifndef __CYGWIN__ 10809 10810 $ f = _fdopen (_open_osfhandle ((intptr_t) GetStdHandle (STD_INPUT_HANDLE), _O_TEXT), "r"); assert (f); *stdin = *f; 10811 $ f = _fdopen (_open_osfhandle ((intptr_t) GetStdHandle (STD_OUTPUT_HANDLE), _O_TEXT), "w"); assert (f); *stdout = *f; 10812 $ f = _fdopen (_open_osfhandle ((intptr_t) GetStdHandle (STD_ERROR_HANDLE), _O_TEXT), "w"); assert (f); *stderr = *f; 10813 10814 #else 10815 10816 $ f = _fdopen (STDIN_FILENO, "r"); assert (f); *stdin = *f; 10817 $ f = _fdopen (STDOUT_FILENO, "w"); assert (f); *stdout = *f; 10818 $ f = _fdopen (STDERR_FILENO, "w"); assert (f); *stderr = *f; 10819 10820 #endif 10821 10822 $ setvbuf (stdin, NULL, _IONBF, 0); 10823 $ setvbuf (stdout, NULL, _IONBF, 0); 10824 $ setvbuf (stderr, NULL, _IONBF, 0); 10825 10826 $ ::std::ios::sync_with_stdio(); 10827 } 10828 10829 //----------------------------------------------------------------------------------------------------------------- 10830 10831 inline bool _txConsole_OK() 10832 { 10833 return Win32::GetConsoleWindow() != NULL; 10834 } 10835 10836 //----------------------------------------------------------------------------------------------------------------- 10837 10838 bool _txConsole_Detach (bool activate) 10839 { 10840 $1 HWND console = Win32::GetConsoleWindow(); 10841 $ if (!console) return false; 10842 10843 $ EnableWindow (console, true); 10844 10845 $ if (activate) 10846 { 10847 $ if (!IsWindowVisible (console)) 10848 {$ ShowWindow (console, SW_MINIMIZE); } 10849 10850 $ _txActivateWindow (console, 0xFF); 10851 $ return true; 10852 } 10853 else 10854 { 10855 $ return !!FreeConsole(); 10856 } 10857 } 10858 10859 //----------------------------------------------------------------------------------------------------------------- 10860 10861 bool _txConsole_Draw (HDC dc) 10862 { 10863 $8 if (_TX_HDC_FAILED (dc)) return false; 10864 10865 $ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE); 10866 10867 $ CONSOLE_SCREEN_BUFFER_INFO con = {}; 10868 $ BOOL ok = GetConsoleScreenBufferInfo (out, &con); 10869 $ if (!ok) return false; 10870 10871 $ POINT size = { con.srWindow.Right - con.srWindow.Left + 1, 10872 con.srWindow.Bottom - con.srWindow.Top + 1 }; 10873 10874 $ SIZE fontSz = { 12, 16 }; 10875 $ Win32::GetTextExtentPoint32 (dc, "W", 1, &fontSz) asserted; 10876 10877 $ COLORREF pal [16] = { 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xC0C0C0, 10878 0x808080, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF }; 10879 10880 $ for (short y = 0; y < size.y; y++) 10881 { 10882 static char chr [_TX_BUFSIZE + 1] = ""; // [con.dwSize.X + 1]; maybe will be truncated 10883 static WORD atr [_TX_BUFSIZE + 1] = {}; // [con.dwSize.X + 1]; maybe will be truncated 10884 COORD coord = { (short) (con.srWindow.Left), (short) (y + con.srWindow.Top) }; 10885 DWORD read = 0; 10886 10887 if (!ReadConsoleOutputCharacter (out, chr, sizearr (chr) - 1, coord, &read)) continue; 10888 if (!ReadConsoleOutputAttribute (out, atr, sizearr (atr) - 1, coord, &read)) continue; 10889 10890 for (int x = 0, xEnd = size.x; x < size.x; x = xEnd) 10891 { 10892 Win32::SetTextColor (dc, pal [ atr[x] & 0x0F]); 10893 Win32::SetBkColor (dc, pal [(atr[x] >> 4) & 0x0F]); 10894 Win32::SetBkMode (dc, (atr[x] & 0xF0)? OPAQUE : TRANSPARENT); 10895 10896 for (xEnd = x+1; xEnd < size.x && atr[xEnd] == atr[x]; xEnd++) {;} 10897 10898 Win32::TextOut (dc, ROUND (fontSz.cx * (x + con.srWindow.Left)), 10899 ROUND (fontSz.cy * y), chr + x, xEnd - x) asserted; 10900 } 10901 } 10902 10903 $ Win32::SetTextColor (dc, pal [ con.wAttributes & 0x0F]); 10904 $ Win32::SetBkColor (dc, pal [(con.wAttributes >> 4) & 0x0F]); 10905 $ Win32::SetBkMode (dc, TRANSPARENT); 10906 10907 $ if (_txConsole_IsBlinking && 10908 In (std::nomeow, con.dwCursorPosition, con.srWindow) && 10909 GetTickCount() % _txCursorBlinkInterval*2 > _txCursorBlinkInterval && 10910 GetForegroundWindow() == txWindow()) 10911 { 10912 $ Win32::TextOut (dc, ROUND (fontSz.cx * (con.dwCursorPosition.X - con.srWindow.Left)), 10913 ROUND (fontSz.cy * (con.dwCursorPosition.Y - con.srWindow.Top)) + 1, 10914 "_", 1) asserted; 10915 } 10916 10917 $ return true; 10918 } 10919 10920 #endif // TX_COMPILED 10921 10922 //----------------------------------------------------------------------------------------------------------------- 10923 //{ Welcome to the Duck Side! Together we will rule the Bathroom! 10924 //----------------------------------------------------------------------------------------------------------------- 10925 10926 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 10927 10928 bool _txConsole_SetUnicodeFont() 10929 { 10930 $ const bool wine = !!Win32::wine_get_version; // Linux::Wine v1.2.2+ compatibility. 10931 // Beer compatibility may be added in future versions... 10932 $ if (wine) // Минздрав РФ предупреждает: чрезмерное употребление wine 10933 { // вредит Вашему здоровью. 10934 $ Win32::GetNumberOfConsoleFonts = NULL; 10935 $ Win32::GetCurrentConsoleFont = NULL; 10936 $ Win32::SetConsoleFont = NULL; 10937 10938 $ return false; 10939 } 10940 10941 // Начиная с Висты все хорошо... 10942 10943 $1 if (Win32::GetCurrentConsoleFontEx && Win32::SetCurrentConsoleFontEx) 10944 { 10945 $ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE); 10946 10947 $ Win32::CONSOLE_FONT_INFOEX info = { sizeof (info) }; 10948 $ if (!Win32::GetCurrentConsoleFontEx (out, false, &info)) return false; 10949 10950 $ info.FontFamily = 0x36; // Unicode fixed-pitch 10951 $ if (!*info.FaceName) info.dwFontSize.Y = (SHORT) (info.dwFontSize.Y + 2); // Terminal font is too small 10952 10953 $ if (wcsncmp (info.FaceName, L"Consolas", sizearr (info.FaceName)) != 0) // Consolas is allowed too 10954 {$ wcsncpy_s (info.FaceName, sizearr (info.FaceName), L"Lucida Console", sizearr (info.FaceName)); } 10955 10956 $ return !!Win32::SetCurrentConsoleFontEx (out, false, &info); 10957 } 10958 10959 // ...а до этого все не так сладко 10960 10961 $ const unsigned uniFont = 10; // The Internet and W2K sources know this magic number 10962 $ const unsigned uniSize = 20; // Size of the font desired, should be > max # of Raster Fonts //-V2551 10963 $ bool ok = true; 10964 10965 // Force Windows to use Unicode font by creating and run the console shortcut tuned to use that font. 10966 10967 $ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE); 10968 10969 $ unsigned fonts = _TX_CALL (Win32::GetNumberOfConsoleFonts, ()); 10970 $ if (fonts && fonts <= uniFont) 10971 { 10972 $ HRESULT init = Win32::CoInitialize (NULL); 10973 $ size_t sz = 0; 10974 10975 $ char link [MAX_PATH] = ""; 10976 $ getenv_s (&sz, link, sizeof (link) - 1, "TEMP"); 10977 $ strncat_s (link, sizeof (link), "\\~txLink.lnk", sizeof (link) - 1); 10978 10979 $ char comspec [MAX_PATH] = ""; 10980 $ getenv_s (&sz, comspec, sizeof (comspec), "COMSPEC"); 10981 10982 $ (void) _unlink (link); 10983 10984 $ _txCreateShortcut (link, comspec, "/c exit", NULL, NULL, SW_SHOWMINNOACTIVE, NULL, 0, uniSize) asserted; 10985 10986 $ ok = (Win32::ShellExecuteA (NULL, NULL, link, NULL, NULL, SW_SHOWMINNOACTIVE) > (void*)32); // Sic! //-V112 //-V566 10987 if (ok) {$ _txWaitFor (FindWindow (NULL, "~txLink"), _TX_TIMEOUT); } 10988 10989 $ (void) _unlink (link); 10990 10991 $ if (init == S_OK) Win32::CoUninitialize(); 10992 } 10993 10994 // If Unicode font is not already set, do set it. 10995 10996 $ Win32::CONSOLE_FONT_INFO cur = {}; 10997 $ _TX_CALL (Win32::GetCurrentConsoleFont, (out, false, &cur)); 10998 10999 $ ok &= (cur.nFont >= uniFont); 11000 if (!ok) {$ ok &= _TX_CALL (Win32::SetConsoleFont, (out, uniFont)); } 11001 11002 $ HWND console = Win32::GetConsoleWindow(); 11003 $ InvalidateRect (console, NULL, false); 11004 $ UpdateWindow (console); 11005 11006 $ return ok; 11007 } 11008 11009 #endif // TX_COMPILED 11010 11011 //----------------------------------------------------------------------------------------------------------------- 11012 //{ The assistants to the nightmare. You can use it freely to make your own nightmare sweet. 11013 11014 #define _TX_TRY { goto __tx_try; } __tx_try: { int __tx_error = S_OK; (void)__tx_error; 11015 #define _TX_CHECKED( cmd ) { if (FAILED (__tx_error = (cmd))) goto __tx_catch; } 11016 #define _TX_FAIL { __tx_error = E_FAIL; goto __tx_catch; } 11017 #define _TX_RETRY { __tx_error = S_OK; goto __tx_try; } 11018 #define _TX_OK ( SUCCEEDED (__tx_error) ) 11019 #define _TX_CATCH goto __tx_finally; __tx_catch: 11020 #define _TX_RETURN goto __tx_finally; 11021 #define _TX_FINALLY __tx_finally: 11022 #define _TX_ENDTRY } 11023 11024 //} 11025 //----------------------------------------------------------------------------------------------------------------- 11026 11027 // Мало не покажется 11028 11029 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 11030 11031 bool _txCreateShortcut (const char shortcutName[], 11032 const char fileToLink[], const char args[] /*= NULL*/, const char workDir[] /*= NULL*/, 11033 const char description[] /*= NULL*/, int cmdShow /*= SW_SHOWNORMAL*/, const char iconFile[] /*= NULL*/, int iconIndex /*= 0*/, 11034 int fontSize /*= 0*/, COORD bufSize /*= ZERO (COORD)*/, COORD wndSize /*= ZERO (COORD)*/, COORD wndOrg /*=ZERO (COORD)*/) 11035 { 11036 $1 if (_TX_ARGUMENT_FAILED (shortcutName && *shortcutName)) return false; 11037 $ if (_TX_ARGUMENT_FAILED (fileToLink && *fileToLink)) return false; 11038 11039 #if defined (__IShellLinkDataList_INTERFACE_DEFINED__) 11040 11041 $ IShellLink* shellLink = NULL; 11042 $ IShellLinkDataList* dataList = NULL; 11043 $ IPersistFile* file = NULL; 11044 11045 $ HRESULT init = Win32::CoInitialize (NULL); 11046 11047 _TX_TRY 11048 { 11049 $ _TX_CHECKED (Win32::CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, Win32::IID_IShellLink, (void**) &shellLink)); 11050 $ if (!shellLink) _TX_FAIL; 11051 11052 $ shellLink->SetPath (fileToLink); 11053 $ shellLink->SetArguments (args); 11054 $ shellLink->SetWorkingDirectory (workDir); 11055 $ shellLink->SetDescription (description); 11056 $ shellLink->SetShowCmd (cmdShow); 11057 $ shellLink->SetIconLocation (iconFile, iconIndex); 11058 11059 $ _TX_CHECKED (shellLink->QueryInterface (Win32::IID_IShellLinkDataList, (void**) &dataList)); 11060 $ if (!dataList) _TX_FAIL; 11061 11062 $ Win32::NT_CONSOLE_PROPS props = 11063 {{sizeof (props), NT_CONSOLE_PROPS_SIG}, 11064 11065 FOREGROUND_LIGHTGRAY, // wFillAttribute 11066 FOREGROUND_MAGENTA | BACKGROUND_WHITE, // wPopupFillAttribute 11067 {bufSize.X, bufSize.Y}, // dwScreenBufferSize 11068 {wndSize.X, wndSize.Y}, // dwWindowSize 11069 {wndOrg.X, wndOrg.Y}, // dwWindowOrigin 11070 0, // nFont 11071 0, // nInputBufferSize 11072 {0, (short) fontSize}, // dwFontSize 11073 0x36, 400, L"Lucida Console", // uFontFamily, uFontWeight, FaceName. We're dancing for this! 11074 15, // uCursorSize 11075 0, 1, 1, 0, // bFullScreen, bQuickEdit, bInsertMode, bAutoPosition 11076 50, 4, 0, // uHistoryBufferSize, uNumberOfHistoryBuffers, bHistoryNoDup 11077 11078 {0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xC0C0C0, // Palette 11079 0x808080, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF} 11080 }; 11081 11082 $ _TX_CHECKED (dataList->AddDataBlock (&props)); 11083 11084 $ _TX_CHECKED (shellLink->QueryInterface (Win32::IID_IPersistFile, (void**) &file)); 11085 $ if (!file) _TX_FAIL; 11086 11087 $ wchar_t wName[MAX_PATH] = L""; 11088 $ MultiByteToWideChar (_TX_CODEPAGE, 0, shortcutName, -1, wName, MAX_PATH) || ZeroMemory (wName, sizeof (wName)); 11089 11090 $ _TX_CHECKED (file->Save (wName, true)); 11091 } 11092 11093 $ _TX_CATCH 11094 $ _TX_FINALLY 11095 11096 if (file) {$ file ->Release(); } 11097 if (dataList) {$ dataList ->Release(); } 11098 if (shellLink) {$ shellLink->Release(); } 11099 11100 if (init == S_OK) {$ Win32::CoUninitialize(); } 11101 11102 $ return _TX_OK; 11103 _TX_ENDTRY 11104 11105 #else 11106 11107 (void) args; (void) workDir, (void) description; (void) cmdShow; (void) iconFile; (void) iconIndex; 11108 (void) fontSize; (void) bufSize; (void) wndSize; (void) wndOrg; 11109 11110 $ return false; 11111 11112 #endif 11113 } 11114 11115 #endif // TX_COMPILED 11116 11117 //} 11118 //----------------------------------------------------------------------------------------------------------------- 11119 11121 //} 11122 //================================================================================================================= 11123 11124 //================================================================================================================= 11125 //{ Memory DC functions (_txBuffer...) 11127 //================================================================================================================= 11129 11130 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 11131 11132 HDC _txBuffer_Create (HWND wnd, const POINT* size /*= NULL*/, HBITMAP bitmap /*= NULL*/, RGBQUAD** pixels /*= NULL*/) 11133 { 11134 $1 txAutoLock _lock; 11135 11136 $ HDC wndDC = GetDC (wnd); 11137 $ if (!wndDC) return NULL; 11138 11139 $ POINT sz = { 1, 1 }; 11140 $ if (size) sz = *size; 11141 11142 $ if (!size && wnd) 11143 { 11144 $ RECT r = {}; 11145 $ GetClientRect (wnd, &r) asserted; 11146 11147 $ sz.x = r.right - r.left; 11148 $ sz.y = r.bottom - r.top; 11149 } 11150 11151 $ if (bitmap) 11152 { 11153 $ BITMAP bmap = {}; 11154 $ Win32::GetObject (bitmap, sizeof (bmap), &bmap) asserted; 11155 11156 $ sz.x = bmap.bmWidth; 11157 $ sz.y = bmap.bmHeight; 11158 } 11159 11160 $ RGBQUAD* buf = NULL; 11161 $ if (!pixels) pixels = &buf; 11162 11163 $ HDC dc = Win32::CreateCompatibleDC (wndDC); 11164 $ if (!dc) TX_DEBUG_ERROR ("Cannot create buffer: CreateCompatibleDC() failed"); 11165 11166 #ifndef _TX_DIB_FIX 11167 #define _TX_DIB_FIX 11168 #endif 11169 11170 $ BITMAPINFO info = {{ sizeof (info), sz.x, _TX_DIB_FIX sz.y, 1, WORD (sizeof (RGBQUAD) * 8), BI_RGB }}; 11171 11172 $ HBITMAP bmap = bitmap? bitmap : Win32::CreateDIBSection (NULL, &info, DIB_RGB_COLORS, (void**) pixels, NULL, 0); 11173 $ if (!bmap) TX_DEBUG_ERROR ("Cannot create buffer: CreateCompatibleBitmap() failed"); 11174 11175 $ Win32::SelectObject (dc, bmap) asserted; 11176 11177 $ if (!bitmap) 11178 { 11179 $ if (*pixels) 11180 { 11181 $ RGBQUAD black = { 0, 0, 0, 255 }; 11182 $ for (int i = 0; i < sz.x * sz.y; i++) (*pixels)[i] = black; //-V108 11183 } 11184 else 11185 {$ Win32::PatBlt (dc, 0, 0, sz.x, sz.y, BLACKNESS) asserted; } 11186 } 11187 11188 $ ReleaseDC (wnd, wndDC) asserted; 11189 11190 $ return dc; 11191 } 11192 11193 //----------------------------------------------------------------------------------------------------------------- 11194 11195 bool _txBuffer_Delete (HDC* dc) 11196 { 11197 $1 if (_TX_ARGUMENT_FAILED (dc)) return false; 11198 $ if ( !*dc) return false; 11199 $ if (_TX_HDC_FAILED (*dc)) return false; 11200 11201 $ if (!Win32::GetObjectType (Win32::GetCurrentObject (*dc, OBJ_BITMAP))) return false; 11202 11203 $ txAutoLock _lock; 11204 11205 $ _txBuffer_Select (Win32::GetStockObject (NULL_PEN), *dc) asserted; 11206 $ _txBuffer_Select (Win32::GetStockObject (NULL_BRUSH), *dc) asserted; 11207 $ _txBuffer_Select (Win32::GetStockObject (SYSTEM_FONT), *dc) asserted; 11208 $ _txBuffer_Select (_txStockBitmap, *dc); 11209 11210 $ Win32::DeleteObject (Win32::GetCurrentObject (*dc, OBJ_BITMAP)) asserted; 11211 11212 $ Win32::DeleteDC (*dc) asserted; 11213 11214 $ *dc = NULL; 11215 11216 $ return true; 11217 } 11218 11219 //----------------------------------------------------------------------------------------------------------------- 11220 11221 bool _txBuffer_Select (HGDIOBJ obj, HDC dc /*= txDC()*/) 11222 { 11223 $1 if (!obj) return false; 11224 $ if (_TX_HDC_FAILED (dc)) return false; 11225 11226 $ if (!Win32::GetObjectType (obj)) TX_DEBUG_ERROR ("Invalid GDI object type"); 11227 11228 $ txAutoLock _lock; 11229 11230 $ obj = Win32::SelectObject (dc, obj); 11231 $ if (obj) Win32::DeleteObject (obj); 11232 11233 $ return obj != NULL; 11234 } 11235 11236 #endif // TX_COMPILED 11237 11239 //} 11240 //================================================================================================================= 11241 11242 //================================================================================================================= 11243 //{ Diagnostics 11245 //================================================================================================================= 11247 11248 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 11249 11250 const char* _txError (const char* file /*= NULL*/, int line /*= 0*/, const char* func /*= NULL*/, unsigned color /*= 0*/, 11251 const char* msg /*= NULL*/, ...) 11252 { //---/\---/\-------Это ASCII KOT!--// 11253 $1 va_list arg; va_start (arg, msg); // { '-' } // 11254 $$ const char* what = _txProcessError (file, line, func, color, msg, arg); // { 0 0 } Добавь его себе // 11255 va_end (arg); // --> V <-- в исходник, и тебе // 11256 // \ \|/ / будет, наверно, // 11257 if (!(msg && msg[0] == '\a')) return what; // \___/ приятно отлаживаться // 11258 //---------------долгими ночами:)--// 11259 // vvvvvvvvvvvvvvvvvv 11260 DebugBreak(); // >>> Котики, вы в отладчике. Не пугайтесь. Есть шанс посмотреть переменные и разобраться. 11261 // ^^^^^^^^^^^^^^^^^^ 11262 11263 return what; // >>> Уходите из функции пошаговой отладкой (F10/F11). Следите за стеком вызовов (Alt+7). 11264 } 11265 11266 #endif // TX_COMPILED 11267 11268 //----------------------------------------------------------------------------------------------------------------- 11269 //{ General runtime check hooks 11270 //----------------------------------------------------------------------------------------------------------------- 11271 11272 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 11273 11274 void _txOnSignal (int sig /*= 0*/, int fpe /*= 0*/) 11275 { 11276 $1 if (!sig && !fpe) 11277 { 11278 $ signal (SIGSEGV, (void(*)(int))(uintptr_t)_txOnSignal) != SIG_ERR asserted; 11279 $ signal (SIGFPE, (void(*)(int))(uintptr_t)_txOnSignal) != SIG_ERR asserted; 11280 $ signal (SIGABRT, (void(*)(int))(uintptr_t)_txOnSignal) != SIG_ERR asserted; 11281 $ signal (SIGILL, (void(*)(int))(uintptr_t)_txOnSignal) != SIG_ERR asserted; 11282 $ signal (SIGTERM, (void(*)(int))(uintptr_t)_txOnSignal) != SIG_ERR asserted; 11283 $ return; 11284 } 11285 11286 txOutputDebugPrintf ("%s - WARNING: %s (%d, %d) called\n", _TX_VERSION, __func__, sig, fpe); 11287 11288 $ if (!*_txLogName || _txLogName[0] == '~') 11289 {$ _tx_snprintf_s (_txLogName, sizeof (_txLogName) - 1, "%s.log", txGetModuleFileName()); } 11290 11291 #define GET_DESCR_(str, code, descr) case (code): {$ (str) = " " #code ": " descr; break; } 11292 11293 $ const char* sSig = "Неизвестный тип сигнала"; 11294 11295 $ switch (sig) 11296 { 11297 GET_DESCR_ (sSig, SIGSEGV, "Доступ по неверному указателю. Ставьте ассерты!") 11298 GET_DESCR_ (sSig, SIGILL, "Попытка выполнить недопустимую операцию. Проверьте указатели на функции.") 11299 GET_DESCR_ (sSig, SIGABRT, "Аварийное завершение программы, вызвана функция abort().") 11300 GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.") 11301 GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.") 11302 default: break; //-V2522 11303 } 11304 11305 $ const char* sFPE = ""; 11306 11307 #if defined (_MSC_VER) 11308 11309 // MSVC provides the FPE code as a MS extension. 11310 // See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx 11311 11312 $ if (sig == SIGFPE) switch (fpe) 11313 { 11314 GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.") 11315 GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.") 11316 GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.") 11317 GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.") 11318 GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.") 11319 GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.") 11320 GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.") 11321 GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.") 11322 GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.") 11323 GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.") 11324 GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.") 11325 default: break; //-V2522 11326 } 11327 11328 #else 11329 $ fpe = 0; 11330 #endif 11331 11332 #undef GET_DESCR_ 11333 11334 $ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal); 11335 11336 $ Win32::_fpreset(); 11337 11338 $ _TX_UNEXPECTED ("\a\t" 11339 "signal (%d, 0x%02X):%s%s " 11340 "%s%s" 11341 "С помощью функции signal() вы можете сами обработать эту ошибку.", 11342 sig, (unsigned) fpe, sSig, sFPE, 11343 ((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1); 11344 } 11345 11346 //----------------------------------------------------------------------------------------------------------------- 11347 11348 void _txOnTerminate() 11349 { 11350 txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__); 11351 11352 // From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc 11353 11354 $1 static int terminating = 0; 11355 if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; } 11356 11357 $ if (!*_txDumpSE) 11358 {$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); } 11359 11360 $ _TX_UNEXPECTED ("\t\a" 11361 "std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, " 11362 "или другая фатальная ошибка C++. " 11363 "%s" 11364 "Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, " 11365 "разбирайтесь, в чем дело.\n\n" 11366 "С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE, 11367 _txDumpSE + 1); 11368 } 11369 11370 //----------------------------------------------------------------------------------------------------------------- 11371 11372 void _txOnUnexpected() 11373 { 11374 txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__); 11375 11376 $1 if (!*_txDumpSE) 11377 {$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); } 11378 11379 $ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n" 11380 "Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете " 11381 "спецификацию исключений для функций, проверьте, не нарушена ли она." 11382 "%s" 11383 "С помощью catch (...) в main() вы можете сами обработать эту ошибку.", 11384 _txDumpSE + 1); 11385 } 11386 11387 //----------------------------------------------------------------------------------------------------------------- 11388 11389 int _txOnMatherr (_exception* exc) 11390 { 11391 txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc); 11392 11393 $1 assert (exc); 11394 11395 const char* sType = "Неизвестный тип исключения"; 11396 11397 #if !defined (__CYGWIN__) 11398 11399 #define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; } 11400 11401 $ switch (exc->type) 11402 { 11403 GET_DESCR_ (_DOMAIN, "Нарушение области определения"); 11404 GET_DESCR_ (_SING, "Сингулярность аргумента"); 11405 GET_DESCR_ (_PLOSS, "Частичная потеря значимости"); 11406 GET_DESCR_ (_TLOSS, "Полная потеря значимости"); 11407 GET_DESCR_ (_OVERFLOW, "Результат слишком большой"); 11408 GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький"); 11409 default: break; //-V2522 11410 } 11411 11412 #undef GET_DESCR_ 11413 11414 $ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n" 11415 "С помощью __setusermatherr() вы можете сами обработать эту ошибку.", 11416 exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval); 11417 #else 11418 11419 $ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType); 11420 11421 #endif 11422 11423 return 0; 11424 } 11425 11426 //----------------------------------------------------------------------------------------------------------------- 11427 11428 tx_noreturn void _txOnNewHandlerAnsi() 11429 { 11430 txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__); 11431 $1 11432 $ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n" 11433 "С помощью std::set_new_handler() вы можете сами обработать эту ошибку " 11434 "и где-нибудь найти недостающую память."); 11435 11436 $ throw std::bad_alloc(); 11437 } 11438 11439 //----------------------------------------------------------------------------------------------------------------- 11440 11441 void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code) 11442 { 11443 txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) called\n", _TX_VERSION, __func__, msg, ptr, code); 11444 11445 $1 if (code) 11446 {$ errno = code; } 11447 11448 $ _TX_UNEXPECTED ("\a" 11449 "Ошибка переполнения буфера %d: %s в %.20s (0x%p). Ставьте ассерты!\n\n" 11450 "С помощью std::set_constraint_handler_s() вы можете сами обработать эту ошибку " 11451 "и постараться не выходить за границы массивов.", 11452 code, msg, (char*) ptr, ptr); 11453 } 11454 11455 //----------------------------------------------------------------------------------------------------------------- 11456 11457 int tx_glGetError (int setError /*= INT_MIN*/) 11458 { 11459 $1 _txOGLError = (setError == INT_MIN)? _TX_CALL (Win32::glGetError, ()) : setError; 11460 $ return _txOGLError; 11461 } 11462 11463 #endif // TX_COMPILED 11464 11465 //} 11466 //----------------------------------------------------------------------------------------------------------------- 11467 11468 //----------------------------------------------------------------------------------------------------------------- 11469 //{ MSC Runtime check hooks 11470 //----------------------------------------------------------------------------------------------------------------- 11471 11472 #if defined (_MSC_VER) 11473 11474 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 11475 11476 //----------------------------------------------------------------------------------------------------------------- 11477 11478 int _txOnNewHandler (size_t size) 11479 { 11480 txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*)(uintptr_t) size); 11481 $5 11482 $ _TX_UNEXPECTED ("operator new: Ошибка выделения %llu байт памяти.\n\n" 11483 "С помощью _set_new_handler() вы можете сами обработать эту ошибку " 11484 "и где-нибудь найти недостающую память.", (unsigned long long) size); 11485 11486 $ throw std::bad_alloc(); 11487 } 11488 11489 //----------------------------------------------------------------------------------------------------------------- 11490 11491 void _txOnSecurityError (int code, void* addr) 11492 { 11493 txOutputDebugPrintf ("%s - WARNING: %s (%d, 0x%p) called\n", _TX_VERSION, __func__, code, addr); 11494 $5 11495 $ _TX_UNEXPECTED ("\a" 11496 "Ошибка переполнения буфера %d (_SECERR_BUFFER_OVERRUN). Ставьте ассерты!\n\n" 11497 "С помощью _set_security_error_handler() вы можете сами обработать эту ошибку " 11498 "и более торжественно завершить программу. Ставьте же ассерты.", code); 11499 $ abort(); 11500 } 11501 11502 //----------------------------------------------------------------------------------------------------------------- 11503 11504 void _txOnPureCall() 11505 { 11506 txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__); 11507 $5 11508 $ _TX_UNEXPECTED ("\a" 11509 "Вызвана чисто виртуальная функция. Такое бывает, например, в конструкторах " 11510 "или деструкторах базовых классов - не вызывайте там таких функций.\n\n" 11511 "С помощью _set_purecall_handler() вы можете сами обработать эту ошибку " 11512 "и проверить свое знание С++ :)"); 11513 $ abort(); 11514 } 11515 11516 //----------------------------------------------------------------------------------------------------------------- 11517 11518 void _txOnInvalidParam (const wchar_t* wExpr, const wchar_t* wFunc, const wchar_t* wFile, unsigned int line, uintptr_t addr) 11519 { 11520 txOutputDebugPrintf ("%s - WARNING: %s (%S, %S, %S, %d, 0x%p) called\n", _TX_VERSION, __func__, wExpr, wFunc, wFile, line, addr); 11521 11522 $5 assert (wExpr); 11523 assert (wFunc); 11524 assert (wFile); 11525 11526 char expr [_TX_BUFSIZE/2] = "[Unknowm expr]", 11527 func [_TX_BUFSIZE/2] = "[Unknowm func]", 11528 file [MAX_PATH] = "[Unknowm file]"; 11529 11530 $ WideCharToMultiByte (_TX_CODEPAGE, 0, wExpr, -1, expr, sizeof (expr) - 1, NULL, NULL); 11531 $ WideCharToMultiByte (_TX_CODEPAGE, 0, wFunc, -1, func, sizeof (func) - 1, NULL, NULL); 11532 $ WideCharToMultiByte (_TX_CODEPAGE, 0, wFile, -1, file, sizeof (file) - 1, NULL, NULL); 11533 11534 $$ _txError (file, (int) line, func, 0, "\a" 11535 "В функцию %s передан неверный параметр: неверно, что %s. Не надо так.\n\n" 11536 "С помощью _set_invalid_parameter_handler() вы можете сами обработать эту ошибку.", func, expr); 11537 $ abort(); 11538 } 11539 11540 //----------------------------------------------------------------------------------------------------------------- 11541 11542 #if defined (_CLANG_VER) && !defined (_MSC_VER) 11543 11544 void _txLibCppDebugFunction (std::__libcpp_debug_info const& info) 11545 { 11546 $5 assert (&info); 11547 11548 $$ _txError (info.__file_, info.__line_, NULL, 0, "\a" 11549 "Оказалось неверно, что %s (%s). Не надо так.\n\n" 11550 "С помощью std::__libcpp_debug_function вы можете сами обработать эту ошибку.", info.__pred_, info.__msg_); 11551 $ abort(); 11552 } 11553 11554 #endif 11555 11556 //----------------------------------------------------------------------------------------------------------------- 11557 11558 #pragma runtime_checks ("", off) 11559 11560 int _txOnRTCFailure (int type, const char* file, int line, const char* module, const char* format, ...) 11561 { 11562 txOutputDebugPrintf ("%s - WARNING: %s (%d, %s, %d, %s, %s) called\n", _TX_VERSION, __func__, type, file, line, module, format); 11563 11564 $5 static long running = 0; 11565 $ while (InterlockedExchange (&running, 1)) Sleep (0); 11566 11567 $ assert (format); 11568 11569 // Disable all RTC failures 11570 11571 $ int nErrors = _RTC_NumErrors(); 11572 $ int* errors = NULL; 11573 $ try { errors = (int*) _alloca (nErrors * sizeof (*errors)); } catch (...) {;} //-V104 11574 11575 $ int err = 0; 11576 $ for (int i = 0; i < nErrors; i++) *(errors? &errors[i] : &err) = _RTC_SetErrorType ((_RTC_ErrorNumber) i, _RTC_ERRTYPE_IGNORE); //-V108 11577 11578 $ char text [_TX_BUFSIZE] = ""; 11579 11580 $ va_list arg; va_start (arg, format); 11581 $ _tx_vsnprintf_s (text, sizeof (text) - 1, format, arg); // Get message from the vararg list 11582 $ auto error = (_RTC_ErrorNumber) va_arg (arg, int /*_RTC_ErrorNumber*/); // Get the RTC error number 11583 $ va_end (arg); 11584 11585 $ const char* sType = "type"; 11586 11587 $ switch (type) 11588 { 11589 case _CRT_ERROR: $ sType = "ошибка"; break; 11590 case _CRT_ASSERT: $ sType = "логическая ошибка"; break; 11591 case _CRT_WARN: $ sType = "возможная ошибка"; break; 11592 default: $ break; 11593 } 11594 11595 $ const char* sError = _RTC_GetErrDesc (error); 11596 11597 $$ _txError (file, line, NULL, 0, "\a" 11598 "Сбой проверки выполнения машинного кода: %s %d (%s): %s в модуле %s.", sType, error, sError, text, module); 11599 11600 // The code below will be never executed until the error above will stay fatal: 11601 11602 // Restore the RTC error types 11603 11604 #if defined (_MSC_VER) 11605 #pragma warning (push) 11606 #pragma warning (disable: 6385) // Reading invalid data from 'errors': the readable size is 'n' bytes, but 'm' bytes may be read. 11607 #endif 11608 11609 $ for (int i = 0; i < nErrors; i++) _RTC_SetErrorType ((_RTC_ErrorNumber) i, (errors? errors[i] : _CRT_ERROR)); //-V108 11610 11611 #if defined (_MSC_VER) 11612 #pragma warning (pop) // Reading invalid data from 'errors': the readable size is 'n' bytes, but 'm' bytes may be read. 11613 #endif 11614 11615 $ InterlockedExchange (&running, 0); 11616 $ return 1; 11617 } 11618 11619 //----------------------------------------------------------------------------------------------------------------- 11620 11621 #if (_CLANG_VER >= 2000) 11622 11623 void ::std::__libcpp_verbose_abort (char const* format, ...) 11624 { 11625 $5 assert (&format); 11626 11627 $ char msg [_TX_BUFSIZE] = ""; 11628 11629 $ va_list args; 11630 $ va_start (args, format); 11631 $ _snprintf_s (msg, sizeof (msg), format, args); 11632 $ va_end (args); 11633 11634 $ _TX_UNEXPECTED ("\a\t" 11635 "Оказалось неверно, что: %s. Не надо так.\n\n" 11636 "%s%s" 11637 "С помощью функции signal() вы можете сами обработать эту ошибку.", 11638 msg, 11639 ((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1); 11640 $ abort(); 11641 } 11642 11643 #endif 11644 11645 #pragma runtime_checks ("", restore) 11646 11647 //----------------------------------------------------------------------------------------------------------------- 11648 11649 int _txOnAllocHook (int type, void* data, size_t size, int use, long request, const unsigned char* file, int line) 11650 { 11651 #if (_TX_ALLOW_TRACE +0 >= 4) 11652 11653 static _tx_thread int recursive = 0; 11654 if (recursive) return true; 11655 recursive++; 11656 11657 #if (_TX_ALLOW_TRACE +0 <= 10) 11658 if (!size) return true; 11659 #endif 11660 11661 #define GET_DESCR_(str, type) case (type): { str = #type; break; } 11662 11663 const char* sType = "Unknown type"; 11664 const char* sUse = "Unknown use"; 11665 11666 switch (_BLOCK_TYPE (type)) 11667 { 11668 GET_DESCR_ (sType, _HOOK_ALLOC); 11669 GET_DESCR_ (sType, _HOOK_REALLOC); 11670 GET_DESCR_ (sType, _HOOK_FREE); 11671 default: break; 11672 } 11673 11674 switch (use) 11675 { 11676 GET_DESCR_ (sUse, _NORMAL_BLOCK); 11677 GET_DESCR_ (sUse, _CRT_BLOCK); 11678 GET_DESCR_ (sUse, _CLIENT_BLOCK); 11679 GET_DESCR_ (sUse, _FREE_BLOCK); 11680 GET_DESCR_ (sUse, _IGNORE_BLOCK); 11681 default: break; 11682 } 11683 11684 #undef GET_DESCR_ 11685 11686 _txTrace ((const char*) file, line, NULL, "%*s" 11687 "_txOnAllocHook (type = 0x%02X (%-*s), subtype =0x%X, data = 0x%p, size = 0x%p, use = 0x%02X (%-*s), request = %ld)", 11688 2 * _txLoc::Cur.inTX, "", 11689 type, 13, sType, _BLOCK_SUBTYPE (type), data, (void*) size, use, 13, sUse, request); 11690 11691 recursive--; 11692 11693 #else 11694 11695 UNREFERENCED_PARAMETER (type); 11696 UNREFERENCED_PARAMETER (data); 11697 UNREFERENCED_PARAMETER (size); 11698 UNREFERENCED_PARAMETER (use); 11699 UNREFERENCED_PARAMETER (request); 11700 UNREFERENCED_PARAMETER (file); 11701 UNREFERENCED_PARAMETER (line); 11702 11703 #endif 11704 11705 return true; //-V601 11706 } 11707 11708 //----------------------------------------------------------------------------------------------------------------- 11709 11710 #endif // TX_COMPILED 11711 11712 #endif 11713 11714 //} 11715 //----------------------------------------------------------------------------------------------------------------- 11716 11717 //----------------------------------------------------------------------------------------------------------------- 11718 //{ SEH staff 11719 //----------------------------------------------------------------------------------------------------------------- 11720 11721 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 11722 11723 long WINAPI _txVectoredExceptionHandler (EXCEPTION_POINTERS* exc) 11724 { 11725 if (!_txProcessSystemWarnings) 11726 { 11727 DWORD code = (exc && exc->ExceptionRecord)? exc->ExceptionRecord->ExceptionCode : 0; //-V560 11728 void* addr = (exc && exc->ExceptionRecord)? exc->ExceptionRecord->ExceptionAddress : NULL; //-V560 11729 11730 if (code != DBG_PRINTEXCEPTION_C && 11731 code != DBG_PRINTEXCEPTION_WIDE_C) 11732 { 11733 txOutputDebugPrintf ("%s - WARNING: %s (code 0x%08lX, addr 0x%p) called and SKIPPED! (_txProcessSystemWarnings == %d)\n", 11734 _TX_VERSION, "_txVectoredExceptionHandler", (unsigned long) code, addr, _txProcessSystemWarnings); 11735 } 11736 11737 return EXCEPTION_CONTINUE_SEARCH; 11738 } 11739 else 11740 { 11741 int inTX = _txLoc::Cur.inTX++; 11742 11743 long ret = _txOnExceptionSEH (exc, "_txVectoredExceptionHandler"); 11744 11745 _txLoc::Cur.inTX = inTX; 11746 return ret; 11747 } 11748 } 11749 11750 //----------------------------------------------------------------------------------------------------------------- 11751 11752 long WINAPI _txUnhandledExceptionFilter (EXCEPTION_POINTERS* exc) 11753 { 11754 int inTX = _txLoc::Cur.inTX++; 11755 11756 long ret = _txOnExceptionSEH (exc, "_txUnhandledExceptionFilter"); 11757 11758 if (_txPrevUEFilter) 11759 { 11760 if (_txSetJmp()) 11761 { 11762 int inTX2 = _txLoc::Cur.inTX++; 11763 11764 ret = _txPrevUEFilter (exc); 11765 11766 _txLoc::Cur.inTX = inTX2; 11767 } 11768 else 11769 { 11770 $6 _TX_UNEXPECTED ("\t\a" "%s" 11771 "С помощью функции _set_se_translator() вы можете сами обработать эту ошибку.\n\n" 11772 "Дополнительно: Сбой вызова стандартного обработчика неперехваченнных исключений SEH." + !*_txDumpSE, 11773 _txDumpSE + 1); 11774 } 11775 } 11776 11777 _txLoc::Cur.inTX = inTX; 11778 return ret; 11779 } 11780 11781 //----------------------------------------------------------------------------------------------------------------- 11782 11783 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI _txOnSetUnhandledExceptionFilter (LPTOP_LEVEL_EXCEPTION_FILTER filter) 11784 { 11785 $6 _txPrevUEFilter = filter; 11786 11787 return (LPTOP_LEVEL_EXCEPTION_FILTER) _txUnhandledExceptionFilter; 11788 } 11789 11790 //----------------------------------------------------------------------------------------------------------------- 11791 11792 long _txOnExceptionSEH (EXCEPTION_POINTERS* exc, const char func[]) 11793 { 11794 assert (exc); if (!exc) {$ return EXCEPTION_CONTINUE_SEARCH; } //-V547 11795 11796 assert (exc->ExceptionRecord); 11797 11798 assert (func); 11799 assert (func[3] == 'V' || func[3] == 'U'); 11800 11801 bool unhExc = (func[3] == 'U'); 11802 DWORD code = (exc && exc->ExceptionRecord)? exc->ExceptionRecord->ExceptionCode : 0; //-V560 11803 void* addr = (exc && exc->ExceptionRecord)? exc->ExceptionRecord->ExceptionAddress : NULL; //-V560 11804 11805 if (code == DBG_PRINTEXCEPTION_C || 11806 code == DBG_PRINTEXCEPTION_WIDE_C || 11807 code == DBG_THREAD_NAME || 11808 code == STATUS_LONGJUMP || 11809 (code == RPC_S_SERVER_UNAVAILABLE && !unhExc) || 11810 (code == RPC_S_CALL_CANCELLED && !unhExc) || 11811 (code == EXCEPTION_BREAKPOINT && IsDebuggerPresent())) 11812 return EXCEPTION_CONTINUE_SEARCH; 11813 11814 ptrdiff_t dist = (uintptr_t) addr - (uintptr_t) IsBadReadPtr; 11815 if (0 <= dist && dist <= 256) {$6 return EXCEPTION_CONTINUE_SEARCH; } 11816 11817 dist = (uintptr_t) addr - (uintptr_t) IsBadWritePtr; 11818 if (0 <= dist && dist <= 256) {$6 return EXCEPTION_CONTINUE_SEARCH; } 11819 11820 _txSENumber = _txSENumber + 1; 11821 if (HIBYTE (HIWORD (code)) == 0xC0) _txSEFatalNumber = _txSEFatalNumber + 1; 11822 11823 OutputDebugString (""); 11824 txOutputDebugPrintf ("%s - WARNING: #%ld: %s (code 0x%08lX, addr 0x%p) called\n", 11825 _TX_VERSION, _txSENumber, func, (unsigned long) code, addr); 11826 11827 $6 if (*(unsigned long long*) _txDumpExceptionObjJmp) 11828 { 11829 $ txOutputDebugPrintf ("%s - WARNING: #%ld: longjmp to %s() at %s:%d\n", _TX_VERSION, _txSENumber, 11830 _txDumpExceptionObjLoc.func, _txDumpExceptionObjLoc.file, _txDumpExceptionObjLoc.line); 11831 11832 longjmp (_txDumpExceptionObjJmp, 1); //-V2512 11833 } 11834 11835 tx_fpreset(); 11836 11837 #if defined (_MSC_VER) 11838 if (code == EXCEPTION_STACK_OVERFLOW) {$ _resetstkoflw(); } 11839 #endif 11840 11841 $ bool primaryException = !(func && exc) || !((unhExc && *_txDumpSE) || _TX_MSC__CXX_DETECT_RETHROW (exc->ExceptionRecord)); //-V560 11842 11843 $ if (primaryException && exc) //-V560 11844 { 11845 $ unsigned err = GetLastError(); 11846 11847 $ const char* stackTrace = _txCaptureStackBackTrace (0, true, exc->ContextRecord, exc); 11848 11849 $ _txDumpExceptionSEH (_txDumpSE, (intptr_t) sizeof (_txDumpSE) - 1, exc->ExceptionRecord, func); 11850 $ _tx_snprintf_s (_txTraceSE, (intptr_t) sizeof (_txTraceSE) - 1, "%s", stackTrace); 11851 11852 $ static _tx_thread DWORD prevCode = 0; 11853 $ static _tx_thread void* prevAddr = NULL; 11854 11855 $ if (code != prevCode && addr != prevAddr && 11856 !strstr (_txDumpSE, "Объект исключения C++:")) 11857 { 11858 $ SetLastError (err); 11859 $ _TX_UNEXPECTED ("\v\b\t" "%s", _txDumpSE + 1); 11860 11861 $ prevCode = code; 11862 $ prevAddr = addr; 11863 } 11864 11865 $ SetLastError (err); 11866 } 11867 11868 $ if (_txDumpSE[0] == '\a' || 11869 _txSENumber >= _TX_EXCEPTIONS_LIMIT+0 || 11870 _txSEFatalNumber >= _TX_FATAL_EXCEPTIONS_LIMIT+0 || 11871 exc->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) 11872 { 11873 $ _TX_UNEXPECTED ("\a\t" "%s" 11874 "С помощью функции _set_se_translator() вы можете сами обработать эту ошибку.", 11875 _txDumpSE + 1); 11876 11877 $ return EXCEPTION_EXECUTE_HANDLER; 11878 } 11879 11880 $ return EXCEPTION_CONTINUE_SEARCH; 11881 } 11882 11883 //----------------------------------------------------------------------------------------------------------------- 11884 11885 intptr_t _txDumpExceptionSEH (char what[], intptr_t size, const EXCEPTION_RECORD* exc, const char func[]) //-V2008 11886 { 11887 $6 assert (what); 11888 $ assert (size >= 0); //-V547 11889 assert (exc); if (!exc) {$ return 0; } //-V547 11890 $ assert (func); 11891 11892 $ unsigned code = exc->ExceptionCode; 11893 $ void* addr = exc->ExceptionAddress; 11894 $ unsigned params = exc->NumberParameters; 11895 $ const ULONG_PTR* info = exc->ExceptionInformation; 11896 $ void* object = (params >= 2)? (void*) info[1] : NULL; 11897 11898 $ char* s = what; 11899 11900 #define PRINT_(...) s += _tx_snprintf_s (s, size-2 - (s-what), ##__VA_ARGS__) 11901 11902 $ const char* sCode = NULL; 11903 $ const char* sDescr = NULL; 11904 11905 #define GET_DESCR_(code, descr) case ((unsigned long) (code)): {$ sCode = #code; sDescr = descr; break; } 11906 11907 $ switch (code) 11908 { 11909 GET_DESCR_ (EXCEPTION_ACCESS_VIOLATION, " " "Нарушение доступа к памяти.") 11910 GET_DESCR_ (EXCEPTION_ILLEGAL_INSTRUCTION, " " "Недопустимая операция.") 11911 GET_DESCR_ (EXCEPTION_PRIV_INSTRUCTION, " " "Привилегированная операция.") 11912 GET_DESCR_ (EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "\a" "Выход за границы массива. Ставьте ассерты!") 11913 GET_DESCR_ (EXCEPTION_BREAKPOINT, "\a" "Достигнута точка останова. Удачи в отладке!") 11914 GET_DESCR_ (EXCEPTION_DATATYPE_MISALIGNMENT, "\a" "Нарушение выравнивания данных.") 11915 GET_DESCR_ (EXCEPTION_INVALID_DISPOSITION, "\a" "Обработчик исключения возвратил неверное значение.") 11916 GET_DESCR_ (EXCEPTION_IN_PAGE_ERROR, "\a" "Невозможно загрузить нужную страницу памяти.") 11917 GET_DESCR_ (EXCEPTION_NONCONTINUABLE_EXCEPTION, "\a" "Продолжение выполнения невозможно.") 11918 GET_DESCR_ (EXCEPTION_SINGLE_STEP, "\a" "Выполнена инструкция машинного кода. Одна штука.") 11919 GET_DESCR_ (EXCEPTION_STACK_OVERFLOW, "\a" "Ю-ху! Переполнение стека!") 11920 GET_DESCR_ (EXCEPTION_GUARD_PAGE, "\a" "Попытка доступа к защищенной странице памяти.") 11921 GET_DESCR_ (EXCEPTION_INVALID_HANDLE, "\a" "Неверный или уже закрытый дескриптор.") 11922 GET_DESCR_ (STATUS_POSSIBLE_DEADLOCK, "\a" "Возможно, взаимная блокировка ресурсов.") 11923 GET_DESCR_ (STATUS_LONGJUMP, " " "Произошел longjmp().") 11924 11925 GET_DESCR_ (EXCEPTION_FLT_STACK_CHECK, "\a" "Ошибка стека при операции с плавающей точкой.") 11926 GET_DESCR_ (EXCEPTION_FLT_DENORMAL_OPERAND, " " "Денормализация числа с плавающей точкой.") 11927 GET_DESCR_ (EXCEPTION_FLT_DIVIDE_BY_ZERO, " " "Деление на ноль при операции с плавающей точкой.") 11928 GET_DESCR_ (EXCEPTION_FLT_INEXACT_RESULT, " " "Неточный результат при операции с плавающей точкой.") 11929 GET_DESCR_ (EXCEPTION_FLT_INVALID_OPERATION, " " "Недопустимая операция с плавающей точкой.") 11930 GET_DESCR_ (EXCEPTION_FLT_OVERFLOW, " " "Переполнение при операции с плавающей точкой.") 11931 GET_DESCR_ (EXCEPTION_FLT_UNDERFLOW, " " "Потеря значимости при операции с плавающей точкой.") 11932 GET_DESCR_ (STATUS_FLOAT_MULTIPLE_FAULTS, " " "Множественные ошибки с плавающей точкой.") 11933 11934 GET_DESCR_ (EXCEPTION_INT_DIVIDE_BY_ZERO, "\a" "Целочисленное деление на ноль.") 11935 GET_DESCR_ (EXCEPTION_INT_OVERFLOW, "\a" "Переполнение при целочисленной операции.") 11936 11937 GET_DESCR_ (EXCEPTION_CLR_FAILURE, "\a" "Сбой среды исполнения (CLR).") 11938 GET_DESCR_ (STATUS_STACK_BUFFER_OVERRUN, "\a" "Переполнение стекового буфера!") 11939 GET_DESCR_ (STATUS_ASSERTION_FAILURE, "\a" "Сработал assert. На этот раз из ядра.") 11940 GET_DESCR_ (STATUS_WX86_BREAKPOINT, "\a" "Точка останова подсистемы эмуляции x86.") 11941 GET_DESCR_ (RPC_S_UNKNOWN_IF, "\a" "Неизвестный интерфейс удаленного вызова процедур (RPC).") 11942 GET_DESCR_ (RPC_S_SERVER_UNAVAILABLE, "\a" "Сервер удаленного вызова процедур (RPC) недоступен.") 11943 GET_DESCR_ (DBG_TERMINATE_THREAD, "\a" "Отладчик завершил поток сознания.") 11944 GET_DESCR_ (DBG_TERMINATE_PROCESS, "\a" "Отладчик завершил процесс.") 11945 GET_DESCR_ (DBG_CONTROL_C, "\a" "Отладчик получил сигнал прерывания Control+C.") 11946 GET_DESCR_ (DBG_CONTROL_BREAK, "\a" "Отладчик получил сигнал прерывания Control+Break.") 11947 GET_DESCR_ (DBG_THREAD_NAME, " " "Отладчик получил указание дать потоку имя.") 11948 GET_DESCR_ (DBG_PRINTEXCEPTION_C, " " "Отладчик вывел исключение по CTRL+C (OutputDebugStringA).") 11949 GET_DESCR_ (DBG_PRINTEXCEPTION_WIDE_C, " " "Отладчик вывел исключение по CTRL+C (OutputDebugStringW).") 11950 11951 GET_DESCR_ (EXCEPTION_CPP_MSC, " " "Исключение С++, вызванное оператором throw.") 11952 GET_DESCR_ (EXCEPTION_CPP_GCC, " " "Исключение С++, вызванное оператором throw.") 11953 GET_DESCR_ (EXCEPTION_CPP_GCC_UNWIND, " " "Исключение С++, вызванное во время раскрутки стека (rethrow?).") 11954 GET_DESCR_ (EXCEPTION_CPP_GCC_FORCED, " " "Исключение С++, вызванное нарушением магии.") 11955 GET_DESCR_ (EXCEPTION_CPP_BORLAND_BUILDER, "\a" "Это скомпилилось под Билдер? O_O") 11956 GET_DESCR_ (EXCEPTION_CPP_BORLAND_DELPHI, "\a" "Это же С++. Как это вышло?") 11957 11958 default: $ break; 11959 } 11960 11961 #undef GET_DESCR_ 11962 11963 $ if (sDescr) 11964 { 11965 $ PRINT_ ("%s\n\n" "#%ld: Исключение %s", sDescr, _txSENumber, sCode); 11966 } 11967 else 11968 { 11969 $ PRINT_ ("\a#%ld: ", _txSENumber); 11970 $ s += FormatMessage (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, //-V102 11971 GetModuleHandle ("NTDLL.DLL"), code, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), 11972 s, (DWORD) (size - (s-what)), NULL) - 2; //-V202 11973 $ PRINT_ ("\r\r"); 11974 } 11975 11976 $ PRINT_ (" (0x%X) при выполнении кода по адресу", code); 11977 $ PRINT_ ((addr? " 0x%p" : " NULL"), addr); 11978 11979 $ Win32::SYMBOL_INFO* sym = NULL; 11980 $ Win32::IMAGEHLP_LINE64* line = NULL; 11981 11982 if (addr) {$ _txSymGetFromAddr (addr, &sym, &line); } 11983 11984 $ if (sym && *sym->Name) PRINT_ (" в функции %s()", sym->Name); 11985 $ if (line && line->FileName && *line->FileName) PRINT_ (" в файле %s на строке %u", line->FileName, (unsigned) line->LineNumber); 11986 11987 $ if (code == EXCEPTION_ACCESS_VIOLATION || 11988 code == EXCEPTION_IN_PAGE_ERROR) 11989 { 11990 $ PRINT_ (". Попытка "); 11991 11992 $ unsigned long op = 0xBADC0DE; 11993 $ const char* sOp = "(действие не указано)"; 11994 11995 $ if (params >= 1) 11996 { 11997 $ switch (op = (unsigned long) info[0]) //-V202 11998 { 11999 case 0: $ sOp = "прочесть данные"; break; 12000 case 1: $ sOp = "записать данные"; break; 12001 case 8: $ sOp = "исполнить код"; break; 12002 default: $ sOp = "совершить операцию 0x%lX"; break; 12003 } 12004 } 12005 12006 $ PRINT_ (sOp, op); 12007 12008 $ if (params >= 2) {$ PRINT_ ((object? " по адресу 0x%p" : " по адресу NULL"), object); } //-V1048 12009 else {$ PRINT_ (" (адрес не указан)"); } 12010 12011 $ if (code == EXCEPTION_IN_PAGE_ERROR) 12012 { 12013 $ PRINT_ (", ошибка ввода-вывода:"); 12014 12015 $ if (params >= 3) 12016 { 12017 $ unsigned long ntstatus = (unsigned long) info[2]; //-V202 12018 12019 $ PRINT_ (" 0x%lX (", ntstatus); 12020 12021 $ s += FormatMessage (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, //-V102 12022 GetModuleHandle ("NTDLL.DLL"), ntstatus, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), 12023 s, (DWORD) (size - (s-what)), NULL) - 2; //-V202 12024 $ PRINT_ (")"); 12025 } 12026 else 12027 {$ PRINT_ (" (не указана)"); } 12028 } 12029 } 12030 12031 $ HMODULE module = NULL; 12032 $ _TX_CALL (Win32::GetModuleHandleEx, (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const char*) addr, &module)); 12033 12034 $ if (module) 12035 { 12036 $ static char sModule [MAX_PATH] = ""; 12037 $ int ok = GetModuleFileName (module, sModule, sizeof (sModule)); 12038 12039 $ char* ext = (ok? strrchr (sModule, '.') : NULL); 12040 $ if (ext) _strlwr_s (ext, sizeof (sModule) - 1 - (ext - sModule)); 12041 12042 if (ok) {$ PRINT_ (" в модуле %s", sModule); } 12043 else {$ PRINT_ (" в модуле 0x%p", (void*) module); } 12044 } 12045 12046 $ PRINT_ ("."); 12047 12048 $ if (_txSENumber >= _TX_EXCEPTIONS_LIMIT+0) 12049 {$ PRINT_ (" Дополнительно, превышен лимит исключений _TX_EXCEPTIONS_LIMIT (%d).", _TX_EXCEPTIONS_LIMIT+0); } 12050 12051 $ if (_txSEFatalNumber >= _TX_FATAL_EXCEPTIONS_LIMIT+0) 12052 {$ PRINT_ (" Также превышен лимит фатальных исключений _TX_FATAL_EXCEPTIONS_LIMIT (%d).", _TX_FATAL_EXCEPTIONS_LIMIT+0); } 12053 12054 $ PRINT_ (" Спасибо %s(), что сообщил. Люблю его <3", func); 12055 12056 $ if (exc->ExceptionFlags & EXCEPTION_NONCONTINUABLE) 12057 {$ PRINT_ ("\n\n" "Ой, всё (EXCEPTION_NONCONTINUABLE)."); } 12058 12059 $ if (exc->ExceptionRecord) 12060 { 12061 $ PRINT_ ("\n\n" "Причина:" "\n\n"); 12062 $ s += _txDumpExceptionSEH (s, size - (s-what), exc->ExceptionRecord, func); 12063 } 12064 12065 $ if (code == EXCEPTION_CPP_GCC || 12066 code == EXCEPTION_CPP_GCC_UNWIND || 12067 code == EXCEPTION_CPP_GCC_FORCED || 12068 code == EXCEPTION_CPP_MSC) 12069 { 12070 $ s += _txDumpExceptionCPP (s, size - (s-what), code, params, info); 12071 } 12072 12073 #undef PRINT_ 12074 12075 $ while (s > what && s[-1] == '\n') s--; 12076 $ if (s > what) s += _tx_snprintf_s (s, size - (s-what), "\n\n"); 12077 12078 $ return s - what; 12079 } 12080 12081 //----------------------------------------------------------------------------------------------------------------- 12082 12083 intptr_t _txDumpExceptionCPP (char what[], intptr_t size, 12084 unsigned code /*= 0*/, unsigned params /*= 0*/, const ULONG_PTR info[] /*= NULL*/) 12085 { 12086 $6 assert (what); 12087 $ assert (size >= 0); //-V547 12088 12089 $ char* s = what; 12090 12091 $ switch (code) 12092 { 12093 #if defined (_GCC_VER) 12094 12095 case EXCEPTION_CPP_GCC: 12096 case EXCEPTION_CPP_GCC_UNWIND: 12097 case EXCEPTION_CPP_GCC_FORCED: 12098 { 12099 // See: [1] http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_exception.cpp 12100 // [2] http://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-seh.c, lines 51-55 and below 12101 // [3] http://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_throw.cc, __cxa_throw, line 59 and below 12102 // [4] http://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/unwind-cxx.h, __cxa_exception, line 58 and below 12103 // and figure above near ABI::__cxa_exception definition in this file 12104 12105 $ const std::type_info* type = NULL; 12106 $ void* object = NULL; 12107 12108 $ if (params >= 1) 12109 { 12110 $ _Unwind_Exception* unwind_exception = (_Unwind_Exception*) info[0]; 12111 $ ABI::__cxa_exception* cxa_exception = (ABI::__cxa_exception*) (unwind_exception + 1) - 1; 12112 12113 $ type = cxa_exception->exceptionType; 12114 $ object = cxa_exception + 1; 12115 } 12116 12117 $ s += _txDumpExceptionObj (s, size - (s-what), object, 0, type); 12118 } 12119 $ break; 12120 12121 case 0: // Not called within SEH chain 12122 { 12123 // From: [1] http://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_type.cc 12124 // [2] http://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/vterminate.cc 12125 12126 using namespace abi; 12127 using namespace ABI; 12128 12129 $ ABI::__cxa_exception* cxa_exception = __cxa_get_globals() -> caughtExceptions; 12130 12131 $ if (cxa_exception && (cxa_exception->unwindHeader.exception_class & 1)) // Dependent exception, case B, see pic above 12132 { 12133 $ cxa_exception = (((ABI::__cxa_exception*) (&cxa_exception->unwindHeader + 1) - 1) -> primaryException) - 1; 12134 } 12135 12136 $ if (cxa_exception) 12137 { 12138 $ verify (cxa_exception->exceptionType == abi::__cxa_current_exception_type()); 12139 12140 $ s += _txDumpExceptionObj (s, size, cxa_exception + 1, 0, cxa_exception->exceptionType); 12141 } 12142 } 12143 $ break; 12144 12145 #elif defined (_MSC_VER) 12146 12147 case EXCEPTION_CPP_MSC: 12148 { 12149 // See [1] http://blogs.msdn.microsoft.com/oldnewthing/20100730-00/?p=13273 12150 // [2] http://www.openrce.org/articles/full_view/21 12151 // [3] http://www.openrce.org/articles/full_view/23 12152 // [4] http://yurichev.com/mirrors/RE/Recon-2012-Skochinsky-Compiler-Internals.pdf 12153 12154 $ const std::type_info* type = NULL; 12155 $ void* object = (params >= 2)? (void*) info[1] : NULL; 12156 $ size_t szObj = 0; 12157 12158 $ if (params >= 3 && 12159 (info[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER1 || 12160 info[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER2 || 12161 info[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER3 || 12162 info[0] == EXCEPTION_CPP_MSC_EH_PURE_MAGIC_NUMBER1)) 12163 { 12164 $ auto throwInfo = (const Win32::ThrowInfo*) info[2]; 12165 12166 $ if (throwInfo && throwInfo->pCatchableTypeArray) 12167 { 12168 $ HMODULE module = (params >= 4)? (HMODULE) info[3] : NULL; //-V112 12169 12170 #define RVA_(type, addr) ( (type) ((uintptr_t) module + (uintptr_t) (addr)) ) 12171 12172 $ const Win32::CatchableTypeArray* cArray = RVA_(const Win32::CatchableTypeArray*, throwInfo->pCatchableTypeArray); 12173 $ const Win32::CatchableType* cType = RVA_(const Win32::CatchableType*, cArray->arrayOfCatchableTypes[0]); 12174 12175 $ type = RVA_(const std::type_info*, cType->pType); 12176 $ szObj = cType->sizeOrOffset; //-V101 12177 12178 #undef RVA_ 12179 } 12180 } 12181 12182 $ s += _txDumpExceptionObj (s, size - (s-what), object, szObj, type); 12183 } 12184 break; 12185 12186 case 0: // Not called within SEH chain 12187 12188 // signal() handlers or unexpected()/terminate() are called after Vectored Exception in MSC: 12189 // 12190 // terminate() is called by __scrt_unhandled_exception_filter() in case of MSC exception. 12191 // See C:\Bin\Microsoft Visual Studio 14.0\VC\crt\src\vcruntime\utility_desktop.cpp 12192 // 12193 // signal() handlers are called by _seh_filter_exe(), which is called by _mainCRTStartup() in case of exception. 12194 // See C:\Bin\Microsoft Visual Studio 14.0\VC\crt\src\vcruntime\mcrtexe.cpp 12195 // and C:\Bin\Windows Kits\10\Source\10.0.10240.0\ucrt\misc\exception_filter.cpp 12196 // and http://msdn.microsoft.com/en-us/library/ff730818.aspx. 12197 // 12198 // So _txDumpSE information should have been recorded during previous call. Now do nothing. 12199 12200 $ break; 12201 12202 #endif 12203 12204 default: 12205 $ txOutputDebugPrintf ("ERROR: Wrong call to %s: Unknown exception code 0x%08X\n", __TX_FUNCTION__, code); 12206 $ break; 12207 } 12208 12209 $ while (s > what && s[-1] == '\n') s--; 12210 $ if (s > what) s += _tx_snprintf_s (s, size - (s - what), "\n\n"); 12211 12212 $ return (s - what); 12213 } 12214 12215 //----------------------------------------------------------------------------------------------------------------- 12216 12217 intptr_t _txDumpExceptionObj (char what[], intptr_t size, void* object, size_t sizeObj, const std::type_info* type) //-V2008 12218 { 12219 $6 assert (what); 12220 $ assert (size > 0); //-V547 12221 12222 $ static char* s = NULL; s = what; 12223 $ static size_t szObj = 0; szObj = sizeObj; 12224 12225 #define PRINT_(...) s += _tx_snprintf_s (s, size - (s - what), ##__VA_ARGS__) 12226 12227 $ PRINT_ ("\n\n" "Объект исключения C++:"); 12228 12229 $ const char* mangledName = (type)? type->name() : NULL; 12230 12231 $ char* typeName = NULL; 12232 $ int err = 1; 12233 12234 #if defined (_GCC_VER) 12235 $ typeName = ::abi::__cxa_demangle (mangledName, 0, 0, &err); 12236 #endif 12237 12238 $ const char* name = (!err && typeName)? typeName : mangledName; //-V560 12239 12240 $ if (name && 12241 (strcmp (name, "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >") == 0 || 12242 strcmp (name, "std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >") == 0)) 12243 {$ name = "std::string"; } 12244 12245 $ if (name && 12246 (strcmp (name, "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *") == 0 || 12247 strcmp (name, "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * __ptr64") == 0 || 12248 strcmp (name, "std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*") == 0)) 12249 {$ name = "std::string*"; } 12250 12251 if (name) {$ PRINT_ (" %s", name); } 12252 12253 #if defined (_GCC_VER) 12254 $ free (typeName); 12255 #endif 12256 12257 $ err = 0; 12258 $ if (mangledName) 12259 { 12260 if (_txSetJmp()) 12261 { 12262 #define PRINT_VAL_(fmt, ty, ...) \ 12263 else if (*type == typeid ( ty )) {$ PRINT_ (" = " #fmt, (* (ty* ) object) __VA_ARGS__); } \ 12264 else if (*type == typeid (const ty )) {$ PRINT_ (" = " #fmt, (* (ty* ) object) __VA_ARGS__); } \ 12265 else if (*type == typeid ( ty* )) {$ PRINT_ (" = " #fmt, (**(ty**) object) __VA_ARGS__); } \ 12266 else if (*type == typeid (const ty* )) {$ PRINT_ (" = " #fmt, (**(ty**) object) __VA_ARGS__); } \ 12267 else if (*type == typeid ( ty* const)) {$ PRINT_ (" = " #fmt, (**(ty**) object) __VA_ARGS__); } \ 12268 else if (*type == typeid (const ty* const)) {$ PRINT_ (" = " #fmt, (**(ty**) object) __VA_ARGS__); } 12269 #define NO_ 12270 12271 if (false) ; 12272 PRINT_VAL_ ("%s", char*, NO_) PRINT_VAL_ ('%c', unsigned char, NO_) PRINT_VAL_ (%s, bool, ? "true" : "false") //-V206 //-V517 12273 PRINT_VAL_ ( %d, int, NO_) PRINT_VAL_ ( %u, unsigned int, NO_) PRINT_VAL_ (%g, float, NO_) //-V206 12274 PRINT_VAL_ ( %hd, short, NO_) PRINT_VAL_ ( %hu, unsigned short, NO_) PRINT_VAL_ (%g, double, NO_) //-V206 12275 PRINT_VAL_ ( %ld, long, NO_) PRINT_VAL_ ( %lu, unsigned long, NO_) PRINT_VAL_ ('%c', char, NO_) //-V206 12276 PRINT_VAL_ ("%s", std::string, .c_str()) //-V206 12277 12278 else if (std::exception* e = dynamic_cast <std::exception*> ( (std::exception* ) object)) 12279 { 12280 $ PRINT_ (", what(): \"%s\"", e->what()); 12281 } 12282 else 12283 {$ err = 1; } 12284 } 12285 else 12286 {$ err = 2; } 12287 } 12288 12289 $ if (err && object && szObj) 12290 { 12291 $ const unsigned char* buf = (const unsigned char*) object; 12292 12293 $ if (szObj >= 64) szObj = 64; 12294 12295 $ PRINT_ (", дамп: ["); 12296 $ for (size_t i = 0; i < szObj; i++) PRINT_ ("%c", (isprint (buf[i]) && !iscntrl (buf[i]))? buf[i] : '.' ); 12297 12298 $ PRINT_ ("]"); 12299 $ for (size_t i = 0; i < szObj; i++) PRINT_ (" %02X", buf[i]); 12300 12301 $ err = 0; 12302 } 12303 12304 $ if (err) 12305 {$ PRINT_ (" = ??"); } 12306 12307 $ PRINT_ ((object? "%sего адрес 0x%p." : "%sего адрес NULL."), ((typeName || mangledName)? ", " : ""), object); //-V560 12308 12309 #undef PRINT_VAL_ 12310 #undef PRINT_ 12311 #undef NO_ 12312 12313 $ return s - what; 12314 } 12315 12316 #endif // TX_COMPILED 12317 12318 //} 12319 //----------------------------------------------------------------------------------------------------------------- 12320 12321 //----------------------------------------------------------------------------------------------------------------- 12322 //{ Stack trace and debug info access 12323 //----------------------------------------------------------------------------------------------------------------- 12324 12325 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 12326 12327 const char* _txCaptureStackBackTrace (int framesToSkip /*= 0*/, bool readSource /*= true*/, 12328 CONTEXT* context /*= NULL*/, EXCEPTION_POINTERS* exc /*= NULL*/, 12329 HANDLE thread /*= GetCurrentThread()*/) 12330 { 12331 $6 const int maxFrames = 62; // MS says: < 63 12332 $ static char trace [(MAX_PATH + 1024+1) * maxFrames] = ""; 12333 12334 if (framesToSkip == -1) {$ return trace; } 12335 12336 $ static void* capture [maxFrames] = {}; 12337 $ int frames = _txStackWalk (framesToSkip + !context, sizearr (capture), capture, context, thread); 12338 12339 $ memset (trace, 0, sizeof (trace)); 12340 $ char* s = trace; 12341 12342 $ bool haveSrcInfo = false; 12343 12344 #define PRINT_(...) s += _tx_snprintf_s (s, sizeof (trace) - 1 - 3 - (s-trace), ##__VA_ARGS__) 12345 12346 $ for (int i = 0, n = 0; i < frames; i++) //-V2530 12347 { 12348 $ void* addr = capture[i]; 12349 12350 $ Win32::SYMBOL_INFO* sym = NULL; 12351 $ Win32::IMAGEHLP_LINE64* line = NULL; 12352 $ const char* module = NULL; 12353 $ const char* source = NULL; 12354 $ bool inTX = false; 12355 12356 if (addr) {$ inTX = _txSymGetFromAddr ((char*) addr - 1, &sym, &line, &module); } 12357 if (readSource && !inTX) {$ _txSymGetFromAddr ((void*) 1, NULL, NULL, NULL, &source, 2); } //-V566 12358 12359 $ int nl = 0; 12360 $ while (s > trace && s[-1] == '\n') { s--; nl++; } 12361 12362 #if !defined (_TX_FULL_STACKTRACE) 12363 12364 $ if (! ((sym && *sym->Name) || (line && ((line->FileName && *line->FileName) || line->LineNumber)))) 12365 {$ continue; } 12366 12367 #endif 12368 12369 $ PRINT_ ("%s#%2d 0x%p", ((n)? ((source || nl)? "\n\n" : "\n") : ""), i, addr); 12370 $ n++; 12371 12372 if (addr == 0) {$ PRINT_ (" [Неверный фрейм]"); break; } 12373 if (addr == (void*) -1) {$ PRINT_ (" [Странный фрейм]"); break; } 12374 if (addr == (void*)(uintptr_t) 0xBAADF00D) {$ PRINT_ (" [Мусор от LocalAlloc()]"); break; } //-V566 12375 12376 if (module) {$ PRINT_ (" in %s%s", module, ((sym && *sym->Name)? ": " : "")); } 12377 if (sym && *sym->Name) {$ PRINT_ ("%s()", sym->Name); } 12378 if (line && line->FileName) {$ PRINT_ (" at %s", line->FileName); haveSrcInfo = true; } 12379 if (line && line->LineNumber) {$ PRINT_ (":%d", (int) line->LineNumber); haveSrcInfo = true; } 12380 if (source) {$ PRINT_ (":\n\n" "%s\n", source); } 12381 12382 if (sym && strcmp (sym->Name , "main") == 0) {$ break; } 12383 } 12384 12385 $ while (s > trace && s[-1] == '\n') s--; 12386 $ *s = 0; 12387 12388 $ int bits = sizeof (void*) * CHAR_BIT; 12389 if (!Win32::SymSetOptions || !Win32::MinGW::SymSetOptions) {$ PRINT_ ("TXLib бедствует: Не загрузилась библиотека"); } 12390 if (!Win32::SymSetOptions) {$ PRINT_ (" DbgHelp%d.dll или DbgHelp.dll,", bits); } 12391 if ( !Win32::MinGW::SymSetOptions) {$ PRINT_ (" MgwHelp%d.dll или MgwHelp.dll,", bits); } 12392 if (!Win32::SymSetOptions || !Win32::MinGW::SymSetOptions) {$ PRINT_ (" отладочная информация недоступна :(\n"); } 12393 12394 $ while (s > trace && s[-1] == '\n') s--; 12395 $ *s = 0; 12396 12397 $ if (!haveSrcInfo) 12398 {$ PRINT_ ("\n\n" "TXLib печалится: Нет информации об исходных файлах. Вы не забыли опцию -g при компиляции?"); } 12399 12400 #if defined (_MSC_VER) 12401 #pragma warning (push) 12402 #pragma warning (disable: 28199) // Using possibly uninitialized memory '*s' 12403 #endif 12404 12405 $ while (s > trace && s[-1] == '\n') s--; 12406 $ *s = 0; 12407 12408 #if defined (_MSC_VER) 12409 #pragma warning (pop) // Using possibly uninitialized memory '*s' 12410 #endif 12411 12412 #undef PRINT_ 12413 12414 $ s += _tx_snprintf_s (s, sizeof (trace) - 1 - (s-trace), ""); 12415 12416 #if !defined (_TX_NO_MINIDUMP) 12417 $ _txCreateMiniDump (exc); 12418 #endif 12419 12420 $ return trace; 12421 } 12422 12423 //----------------------------------------------------------------------------------------------------------------- 12424 12425 // Stack WALKING if the program is DEAD. Dead, Carl! 12426 12427 int _txStackWalk (int framesToSkip, size_t szCapture, void* capture[], CONTEXT* context /*= NULL*/, 12428 HANDLE thread /* = GetCurrentThread()*/) 12429 { 12430 $9 namespace MinGW = Win32::MinGW; 12431 12432 $ assert (capture); 12433 12434 $ HANDLE process = GetCurrentProcess(); 12435 $ bool thisThread = !Win32::GetThreadId || (Win32::GetThreadId (thread) == GetCurrentThreadId()); 12436 12437 $ CONTEXT ctx = {}; 12438 $ ctx.ContextFlags |= CONTEXT_FULL; 12439 12440 $ int isWow64 = 0; 12441 $ if (Win32::IsWow64Process) Win32::IsWow64Process (process, &isWow64); 12442 else {$ return -1; } 12443 12444 $ if (context) 12445 { 12446 $ ctx = *context; 12447 } 12448 else 12449 { 12450 $ if (thisThread) 12451 { 12452 $ _TX_CALLv (Win32::RtlCaptureContext, (&ctx)); 12453 } 12454 else 12455 { 12456 $ SuspendThread (thread); //-V720 12457 12458 $ ctx.ContextFlags = CONTEXT_ALL; 12459 $ bool ok = !!GetThreadContext (thread, &ctx); 12460 12461 $ if (!ok) 12462 { 12463 $ ResumeThread (thread); 12464 $ return -1; 12465 } 12466 } 12467 } 12468 12469 $ Win32::STACKFRAME64 frame = {}; 12470 $ frame.AddrPC.Mode = frame.AddrStack.Mode = frame.AddrFrame.Mode = Win32::AddrModeFlat; 12471 12472 $ int cpu = 0; 12473 12474 #if defined (_WIN64) 12475 12476 $ if (isWow64) 12477 { 12478 $ Win32::WOW64_CONTEXT wow64ctx = {}; 12479 $ wow64ctx.ContextFlags |= WOW64_CONTEXT_FULL; 12480 12481 $ if (!_TX_CALL (Win32::Wow64GetThreadContext, (thread, &wow64ctx))) // This call fails in WINE, 12482 { // while EXIT_PROCESS_DEBUG_EVENT 12483 if (!thisThread) {$ ResumeThread (thread); } 12484 $ return 0; 12485 } 12486 12487 $ cpu = IMAGE_FILE_MACHINE_I386; 12488 12489 $ frame.AddrPC .Offset = wow64ctx.Eip; 12490 $ frame.AddrStack.Offset = wow64ctx.Esp; 12491 $ frame.AddrFrame.Offset = wow64ctx.Ebp; 12492 } 12493 else 12494 { 12495 $ cpu = IMAGE_FILE_MACHINE_AMD64; 12496 12497 $ frame.AddrPC .Offset = ctx.Rip; 12498 $ frame.AddrStack.Offset = ctx.Rbp; 12499 $ frame.AddrFrame.Offset = ctx.Rsp; 12500 } 12501 12502 #else 12503 12504 { 12505 $ cpu = IMAGE_FILE_MACHINE_I386; 12506 12507 $ frame.AddrPC .Offset = ctx.Eip; 12508 $ frame.AddrStack.Offset = ctx.Ebp; 12509 $ frame.AddrFrame.Offset = ctx.Esp; 12510 } 12511 12512 #endif 12513 12514 $ assert (cpu); 12515 12516 if (_txSetJmp()) {$ _txSymGetFromAddr ((void*) 1); } //-V566 12517 12518 $ int frames = -1; 12519 12520 $ for (frames = -framesToSkip; frames < (int) szCapture; frames++) //-V202 //-V2530 12521 { 12522 $ DWORD64 prev = frame.AddrStack.Offset; 12523 12524 // Я злой и страшный серый walk. Я в поросятах знаю talk. 12525 12526 if (!_txSetJmp()) {$ break; } 12527 12528 #if defined (_GCC_VER) 12529 12530 if (!_TX_CALL (MinGW::StackWalk64, (cpu, process, thread, &frame, &ctx, NULL, 12531 MinGW::SymFunctionTableAccess64, MinGW::SymGetModuleBase64, NULL))) {$ break; } 12532 #elif defined (_MSC_VER) 12533 12534 $ if (!_TX_CALL (Win32::StackWalk64, (cpu, process, thread, &frame, &ctx, NULL, 12535 Win32::SymFunctionTableAccess64, Win32::SymGetModuleBase64, NULL))) {$ break; } 12536 #else 12537 #error _GCC_VER / _MSC_VER not defined 12538 #endif 12539 if (frames < 0) {$ continue; } 12540 12541 $ void* addr = (void*) frame.AddrPC.Offset; 12542 12543 if (frame.AddrFrame.Offset == 0) {$ addr = 0; } // Bad frame 12544 if (frame.AddrStack.Offset < prev) {$ addr = (void*) -1; } // Strange frame 12545 12546 $ assert (0 <= frames && frames < (int) szCapture); //-V202 12547 12548 $ capture[frames] = addr; //-V108 12549 } 12550 12551 if (!thisThread) {$ ResumeThread (thread); } 12552 12553 $ return frames; 12554 } 12555 12556 // Note that Rick and Carl are speaking near the C language block. "C block", Carl. See: http://knowyourmeme.com/memes/carl 12557 12558 //----------------------------------------------------------------------------------------------------------------- 12559 12560 bool _txSymGetFromAddr (void* addr, Win32::SYMBOL_INFO** symbol /*= NULL*/, 12561 Win32::IMAGEHLP_LINE64** line /*= NULL*/, const char** module /*= NULL*/, 12562 const char** source /*= NULL*/, int context /*= 2*/) 12563 { 12564 $7 static HANDLE process = NULL; 12565 12566 #if defined (_GCC_VER) 12567 #define LIB_ Win32::MinGW 12568 12569 #elif defined (_MSC_VER) 12570 #define LIB_ Win32 12571 12572 #else 12573 #error _GCC_VER / _MSC_VER not defined 12574 #endif 12575 12576 $ if (!process && addr) 12577 { 12578 $ process = GetCurrentProcess(); 12579 12580 $ DWORD options = SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_LOAD_ANYTHING | SYMOPT_INCLUDE_32BIT_MODULES | 12581 SYMOPT_DEFERRED_LOADS | SYMOPT_FAVOR_COMPRESSED | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_NO_PROMPTS; 12582 12583 $ _TX_CALL (LIB_::SymSetOptions, (options)); 12584 $ _TX_CALL (LIB_::SymInitialize, (process, NULL, true)); 12585 } 12586 12587 $ static DWORD64 mod = 0; 12588 12589 $ if (module) 12590 { 12591 $ static char sMod [MAX_PATH] = ""; 12592 $ memset (sMod, 0, sizeof (sMod)); 12593 12594 $ mod = _TX_CALL (LIB_::SymGetModuleBase64, (process, (uintptr_t) addr)); 12595 12596 $ GetModuleFileName ((HMODULE)(intptr_t) mod, sMod, MAX_PATH); 12597 12598 $ char* ext = strrchr (sMod, '.'); 12599 if (ext) {$ _strlwr_s (ext, sizeof (sMod) - (ext-sMod)); } 12600 12601 $ *module = sMod; 12602 } 12603 12604 $ static char buffer [_TX_BUFSIZE] = ""; 12605 $ static Win32::SYMBOL_INFO* sym = (Win32::SYMBOL_INFO*) buffer; //-V1032 12606 12607 $ if (symbol) 12608 { 12609 $ memset (buffer, 0, sizeof (buffer)); 12610 12611 $ sym->MaxNameLen = sizeof (buffer) - sizeof (Win32::SYMBOL_INFO) - 1; 12612 $ sym->SizeOfStruct = sizeof (Win32::SYMBOL_INFO); 12613 $ unsigned long long ofs = 0; 12614 12615 $ int ok = _TX_CALL (LIB_::SymFromAddr, (process, (uintptr_t) addr, &ofs, sym)); 12616 if (!ok) {$ return false; } 12617 12618 if (strcmp (sym->Name, "??") == 0) {$ *sym->Name = 0; } 12619 12620 $ *symbol = sym; 12621 } 12622 12623 $ static Win32::IMAGEHLP_LINE64 line64 = { sizeof (line64) }; 12624 12625 $ if (line) 12626 { 12627 $ memset (&line64, 0, sizeof (line64)); 12628 12629 $ DWORD ofs = 0; 12630 $ int ok = _TX_CALL (LIB_::SymGetLineFromAddr64, (process, (uintptr_t) addr, &ofs, &line64)); 12631 if (!ok) {$ return false; } 12632 12633 $ *line = &line64; 12634 } 12635 12636 $ if (source) 12637 { 12638 $ static char buf [_TX_BUFSIZE] = ""; 12639 $ memset (buf, 0, sizeof (buf)); 12640 12641 $ if (line64.FileName && line64.LineNumber) 12642 { 12643 $ _txReadSource (buf, sizeof (buf) - 1, line64.FileName, 12644 (int) line64.LineNumber - context, (int) line64.LineNumber + context, (int) line64.LineNumber); 12645 12646 $ *source = buf; 12647 } 12648 12649 if (!*source || !**source) {$ *source = NULL; } 12650 } 12651 12652 $ if (!addr && process) 12653 { 12654 $ _TX_CALL (LIB_::SymCleanup, (process)); 12655 12656 $ process = NULL; 12657 } 12658 12659 #if (_GCC_VER == 481) 12660 #pragma GCC diagnostic push 12661 #pragma GCC system_header 12662 #endif 12663 12664 $ if (symbol) 12665 { 12666 $ if (strstr (sym->Name, "::TX::") || 12667 (strncmp (sym->Name, "_tx", 3) == 0 && isupper ((unsigned char) sym->Name[3])) || 12668 (strncmp (sym->Name, "tx", 2) == 0 && isupper ((unsigned char) sym->Name[2])) || 12669 strncmp (sym->Name, "_tx_", 4) == 0 || //-V112 12670 strncmp (sym->Name, "tx_", 3) == 0) 12671 { 12672 $ return true; 12673 } 12674 12675 #if (_GCC_VER == 481) 12676 #pragma GCC diagnostic pop 12677 #endif 12678 12679 $ if (!line || !line64.FileName) return false; 12680 12681 $ intptr_t len = strlen (line64.FileName) - (sizeof (__FILE__) - 1); 12682 12683 $ return (len >= 0 && _stricmp (line64.FileName + len, __FILE__) == 0) && 12684 (len == 0 || line64.FileName[len-1] == '/' || line64.FileName[len-1] == '\\'); 12685 } 12686 12687 #undef LIB_ 12688 12689 $ return false; 12690 } 12691 12692 //----------------------------------------------------------------------------------------------------------------- 12693 12694 intptr_t _txReadSource (char buf[], intptr_t size, const char file[], 12695 int linStart /*= 0*/, int linEnd /*= INT_MIN*/, int linMark /*= INT_MIN*/) 12696 { 12697 $7 assert (buf); 12698 12699 if (!file || !*file) {$ return 0; } 12700 12701 if (linStart < 1) {$ linStart = 1; } 12702 if (linEnd == -1) {$ linEnd = INT_MAX; } 12703 12704 $ FILE* f = NULL; 12705 $ fopen_s (&f, file, "r"); 12706 if (!f) {$ return 0; } 12707 12708 $ int n = 1; 12709 while (!feof (f)) 12710 { 12711 if (n >= linStart) {$ break; } 12712 while (!feof (f) && fgetc (f) != '\n') 12713 ; 12714 n++; 12715 } 12716 12717 $ char* s = buf; 12718 12719 #define SZ_ ( size - 3 - (s - buf) ) 12720 12721 $ while (!feof (f) && SZ_ > 0) 12722 { 12723 if (n > linEnd || _txNOP (SZ_) < 0) {$ break; } 12724 12725 if (linMark != INT_MIN) 12726 {$ s += _tx_snprintf_s (s, SZ_, "%s%5d: ", ((n == linMark)? "=>" : " "), n); } 12727 12728 $ int c = 0; 12729 $ while (!feof (f) && SZ_ > 0 && (c = fgetc (f)) != '\n') *s++ = (char) c; 12730 if (c == EOF) {$ s--; } 12731 12732 if (SZ_ > 0) {$ *s++ = '\n'; } 12733 $ n++; 12734 } 12735 12736 if (n <= linEnd && SZ_ <= 0) 12737 {$ s += _tx_snprintf_s (s, size - (s - buf), "..."); } 12738 12739 #undef SZ_ 12740 12741 $ fclose (f); 12742 12743 if (s > buf && s[-1] == '\n') {$ s--; } 12744 $ *s = 0; 12745 12746 $ return (s - buf); 12747 } 12748 12749 //----------------------------------------------------------------------------------------------------------------- 12750 12751 const char* _txCaptureStackBackTraceTX (int framesToSkip /*= 0*/, bool readSource /*= false*/) 12752 { 12753 $6 const int maxFrames = 62; // TX says too: < 63 12754 $ static char trace [(MAX_PATH + 1024+1) * maxFrames] = ""; 12755 12756 if (framesToSkip == -1) {$ return trace; } 12757 12758 $ memset (trace, 0, sizeof (trace)); 12759 $ char* s = trace; 12760 12761 #define SZ_ ( sizeof (trace) - 1 - 3 - (s-trace) ) 12762 12763 $ const _txLoc* loc = &_txLoc::Cur; 12764 12765 for (int i = 0; loc && i < framesToSkip + 1; i++, loc = loc->prev) { $; } 12766 12767 $ for (int i = -framesToSkip; loc && i < maxFrames; i++, loc = loc->prev) 12768 { 12769 if (i < 0) {$ continue; } 12770 12771 if (loc->func || loc->file || loc->line) 12772 { 12773 $ s += _tx_snprintf_s (s, SZ_, "%s#%2d in %s at %s:%d", (i? readSource? "\n\n" : "\n" : ""), 12774 i, loc->func, loc->file, loc->line); 12775 12776 $ if (readSource) 12777 { 12778 $ s += _tx_snprintf_s (s, SZ_, ":\n\n"); 12779 $ s += _txReadSource (s, SZ_, loc->file, loc->line - 2, loc->line + 2, loc->line); 12780 } 12781 } 12782 } 12783 12784 #undef SZ_ 12785 12786 $ s += _tx_snprintf_s (s, sizeof (trace) - 1 - (s-trace), ""); 12787 12788 $ return trace; 12789 } 12790 12791 //----------------------------------------------------------------------------------------------------------------- 12792 12793 bool _txCreateMiniDump (EXCEPTION_POINTERS* exc /*= NULL*/) 12794 { 12795 $6 static char dumpName[MAX_PATH] = ""; 12796 if (!*dumpName) {$ _tx_snprintf_s (dumpName, sizeof (dumpName) - 1, "%s.dmp", _txLogName); } 12797 12798 $ HANDLE file = CreateFile (dumpName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 12799 12800 if (!file || file == INVALID_HANDLE_VALUE) {$ return false; } 12801 12802 $ Win32::MINIDUMP_EXCEPTION_INFORMATION excInfo = { GetCurrentThreadId(), exc, false }; 12803 $ Win32::MINIDUMP_TYPE type = (Win32::MINIDUMP_TYPE) (Win32::MiniDumpWithIndirectlyReferencedMemory | Win32::MiniDumpScanMemory); 12804 12805 $ bool ok = _TX_CALL (Win32::MiniDumpWriteDump, (GetCurrentProcess(), GetCurrentProcessId(), file, type, 12806 ((exc)? &excInfo : NULL), NULL, NULL)); 12807 $ CloseHandle (file); 12808 12809 if (ok) {$ return true; } 12810 else {$ return false; } 12811 } 12812 12813 #endif // TX_COMPILED 12814 12815 //} 12816 //----------------------------------------------------------------------------------------------------------------- 12817 12818 //----------------------------------------------------------------------------------------------------------------- 12819 //{ Errors reporting 12820 //----------------------------------------------------------------------------------------------------------------- 12821 12822 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 12823 12824 const char* _txProcessError (const char file[], int line, const char func[], unsigned color, const char msg[], va_list args) //-V2008 12825 { 12826 _txErrors = _txErrors + 1; 12827 12828 DWORD winErr = GetLastError(); 12829 12830 int crtErr = errno; 12831 12832 #if !defined (__CYGWIN__) 12833 unsigned long dosErr = _doserrno; 12834 #else 12835 unsigned long dosErr = 0; 12836 #endif 12837 12838 unsigned dlgErr = _TX_CALL (Win32::CommDlgExtendedError, ()); 12839 12840 unsigned oglErr = _TX_CALL (Win32::wglGetCurrentDC, ())? _TX_CALL (Win32::glGetError, ()) : _txOGLError; 12841 12842 unsigned threadId = GetCurrentThreadId(); 12843 12844 enum { isFatal = 0x01, isWarning = 0x02, noMsgBox = 0x04, fmtOnly = 0x08, traceSE = 0x10 }; 12845 unsigned options = 0; 12846 12847 for (; msg && *msg; msg++) 12848 { 12849 if (*msg == '\a') options |= isFatal; 12850 else if (*msg == '\v') options |= isWarning; 12851 else if (*msg == '\b') options |= noMsgBox; 12852 else if (*msg == '\f') options |= fmtOnly; 12853 else if (*msg == '\t') options |= traceSE; 12854 else break; 12855 } 12856 12857 const char* stkTrace = NULL; 12858 const char* txTrace = NULL; (void) txTrace; 12859 12860 if (!(options & fmtOnly)) 12861 { 12862 stkTrace = ((options & traceSE) && *_txTraceSE)? _txTraceSE : _txCaptureStackBackTrace (2, true); 12863 txTrace = _txCaptureStackBackTraceTX (0, true); 12864 } 12865 12866 static char what[_TX_BIGBUFSIZE*10] = ""; 12867 static char str [_TX_BIGBUFSIZE] = ""; 12868 char *s = what; 12869 12870 #define PRINT_(...) s += _tx_snprintf_s (s, sizeof (what) - 1 - (s - what), ##__VA_ARGS__) 12871 #define VPRINT_(...) s += _tx_vsnprintf_s (s, sizeof (what) - 1 - (s - what), ##__VA_ARGS__) 12872 12873 PRINT_ ("TXLib %s\n\n", ((options & isWarning)? "предупреждает:" : 12874 (options & isFatal)? "соболезнует..." : 12875 "сообщает:")); 12876 PRINT_ ("Программа: %s", txGetModuleFileName()); 12877 if (file) PRINT_ (", файл: %s", file); 12878 if (line) PRINT_ (", строка: %d", line); 12879 if (func) PRINT_ (", функция: %s", func); 12880 PRINT_ (",\n\n"); 12881 12882 if (msg) PRINT_ ("%s: ", (file || line || func)? "Сообщение" : "ВНЕЗАПНО"), 12883 VPRINT_ (msg, args); 12884 12885 while (s > what && s[-1] == '\n') s--; 12886 12887 PRINT_ ("\n\n" "#%d: %s, Instance: 0x%p (%d-bit), Flags: %c%c%c%c%c%d, Thread: 0x%X%s", 12888 12889 _txErrors, _TX_VERSION, (void*) &_txInitialized, (sizeof (void*) == 4)? 32 : 64, 12890 12891 "cC"[!!_txConsole], "mM"[_txMain], "dD"[_txIsDll], "rR"[_txRunning], "eE"[_txExit], _txLoc::Cur.trace, 12892 12893 threadId, (threadId == _txMainThreadId)? " (Main)" : 12894 (threadId == _txCanvas_ThreadId)? " (Canvas)" : ""); 12895 12896 if (winErr) PRINT_ (", GetLastError(): %lu (", (unsigned long) winErr), 12897 s += FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, //-V102 12898 NULL, winErr, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), 12899 s, (DWORD) (sizeof (what) - (s-what)), NULL) - 2, //-V202 12900 s -= (s[-1] == '.')? 1 : 0, 12901 PRINT_ (")"); 12902 12903 if (crtErr) PRINT_ (", errno: %d (%s)", crtErr, (strerror_s (str, sizeof (str), crtErr), str)); 12904 if (dosErr) PRINT_ (", _doserrno: %lu (%s)", dosErr, (strerror_s (str, sizeof (str), dosErr), str)); 12905 if (oglErr) PRINT_ (", glGetError(): %u (0x%04X, %s)", oglErr, oglErr, _TX_CALL (Win32::gluErrorString, (oglErr))); 12906 if (dlgErr) PRINT_ (", CommDlgExtendedError(): %u (0x%04X)", dlgErr, dlgErr); 12907 12908 #if (__cplusplus >= 201703L) || (defined (_MSVC_LANG) && _MSVC_LANG >= 201703L) 12909 PRINT_ (". %s\n", ::std::uncaught_exceptions()? "std::uncaught_exceptions(): true." : ""); 12910 #else 12911 PRINT_ (". %s\n", ::std::uncaught_exception ()? "std::uncaught_exception(): true." : ""); 12912 #endif 12913 12914 if (_txLoc::Cur.inTX > 0 && file && !(_txLoc::Cur.line == line && _stricmp (_txLoc::Cur.file, file) == 0) && 12915 (_txLoc::Cur.file || _txLoc::Cur.line || _txLoc::Cur.func)) 12916 PRINT_ ("From: %s:%d %s.\n", _txLoc::Cur.file, _txLoc::Cur.line, _txLoc::Cur.func); 12917 12918 txOutputDebugPrintf ("\r" "%s - ERROR: %s\n", _TX_VERSION, what); 12919 12920 if (options & fmtOnly) 12921 { 12922 SetLastError (winErr); 12923 12924 errno = crtErr; 12925 12926 #if !defined (__CYGWIN__) 12927 _doserrno = dosErr; 12928 #endif 12929 12930 return what; 12931 } 12932 12933 txSetProgress (-1, Win32::TBPF_ERROR); 12934 12935 unsigned restore = txGetConsoleAttr(); 12936 txSetConsoleAttr ((options & isFatal)? FOREGROUND_LIGHTMAGENTA : FOREGROUND_LIGHTRED); 12937 if (color) {$ txSetConsoleAttr (color); } 12938 12939 int oldCP = GetConsoleOutputCP(); 12940 SetConsoleOutputCP (_TX_CODEPAGE); 12941 12942 fprintf (stderr, "\n" "--------------------------------------------------\n" 12943 "%s", 12944 what); 12945 if (stkTrace) 12946 { fprintf (stderr, "\n" "--------------------------------------------------\n" 12947 "Стек вызовов:\n\n" 12948 "%s\n\n" 12949 "--------------------------------------------------\n", 12950 stkTrace); } 12951 errno = 0; 12952 char sErrno[256] = ""; 12953 FILE* log = NULL; 12954 if (*_txLogName) fopen_s (&log, _txLogName, "a"); 12955 strerror_s (sErrno, sizeof (sErrno), errno); 12956 12957 if (!log) 12958 {$ fprintf (stderr, "\n" "TXLib шокирован: Не открывается лог-файл \"%s\" для записи: Ошибка %d (%s)!\n", 12959 _txLogName, errno, sErrno); } 12960 12961 SetConsoleOutputCP (oldCP); 12962 txSetConsoleAttr (restore); 12963 12964 if (log) 12965 { 12966 fprintf (log, "\n" "--------------------------------------------------\n" 12967 "%s\n" 12968 "--------------------------------------------------\n", 12969 what); 12970 12971 fprintf (log, "Стек вызовов:\n\n" //-V576 12972 "%s\n", 12973 (*_txTraceSE)? _txTraceSE : stkTrace); 12974 12975 #if defined (_TX_ALLOW_TRACE) || defined (_DEBUG) 12976 12977 if (_txLoc::Cur.inTX > 0 && txTrace && *txTrace) 12978 { 12979 fprintf (log, "\n" "--------------------------------------------------\n" 12980 "Стек вызовов TX:\n\n" 12981 "%s\n", 12982 txTrace); 12983 } 12984 12985 #endif 12986 12987 fprintf (log, "\n" "--------------------------------------------------\n" 12988 "%s\n\n" 12989 "--------------------------------------------------\n", 12990 _txAppInfo()); 12991 } 12992 12993 if (log) fclose (log); 12994 12995 txSleep(); 12996 12997 int ret = 0; 12998 12999 if (!(options & noMsgBox)) 13000 { 13001 txSleep (_txWindowUpdateInterval); 13002 13003 HWND wnd = GetForegroundWindow(); 13004 13005 PRINT_ ("\n" "Прервать программу?"); 13006 13007 ret = txMessageBox (what, ((options & isWarning)? "Предупреждение" : 13008 (options & isFatal)? "Фатальная ошибка" : 13009 "Ошибка в программе"), MB_ICONSTOP | MB_SYSTEMMODAL | MB_YESNOCANCEL); 13010 _txActivateWindow (wnd, 0x10); 13011 } 13012 13013 SetLastError (winErr); 13014 13015 errno = crtErr; 13016 13017 #if !defined (__CYGWIN__) 13018 _doserrno = dosErr; 13019 #endif 13020 13021 if (((options & isFatal) && !IsDebuggerPresent()) || ret == IDYES) 13022 { 13023 txUnlock(); 13024 _txCleanup(); 13025 Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE); 13026 } 13027 13028 #undef PRINT_ 13029 #undef VPRINT_ 13030 13031 return what; 13032 } 13033 13034 //----------------------------------------------------------------------------------------------------------------- 13035 13036 #if defined (_MSC_VER) 13037 13038 int _txOnErrorReport (int type, const char* text, int* ret) 13039 { 13040 assert (text); 13041 assert (ret); 13042 13043 _txErrors = _txErrors + 1; 13044 13045 unsigned restore = txGetConsoleAttr(); 13046 13047 switch (type) 13048 { 13049 case _CRT_WARN: txSetConsoleAttr (FOREGROUND_LIGHTRED); break; 13050 case _CRT_ERROR: txSetConsoleAttr (FOREGROUND_LIGHTMAGENTA); break; 13051 case _CRT_ASSERT: txSetConsoleAttr (FOREGROUND_YELLOW); break; 13052 default: break; //-V2522 13053 } 13054 13055 const char startReport[] = "Detected memory leaks!\n", 13056 endReport[] = "Object dump complete.\n"; 13057 13058 if (strcmp (text, startReport) == 0) // Dirty, dirty hack. А что делать? 13059 { 13060 _txOnErrorReport (type, "\n", NULL); 13061 _txOnErrorReport (type, _TX_VERSION " - ERROR: ", NULL); 13062 _txOnErrorReport (type, "Внимание: Обнаружены утечки памяти! (Для поиска используйте _TX_ALLOC_BREAK.)\n", NULL); 13063 _txOnErrorReport (type, "\n", NULL); 13064 } 13065 13066 size_t len = strlen (text); 13067 if (text [len-1] != '\n') txOutputDebugPrintf ("%s", text); 13068 else if (strcmp (text, endReport) != 0) txOutputDebugPrintf ("%s" "%s - ERROR: ", text, _TX_VERSION); 13069 else txOutputDebugPrintf ("%s\n", text); 13070 13071 DWORD n = 0; 13072 HANDLE err = GetStdHandle (STD_ERROR_HANDLE); 13073 WriteFile (err, text, (DWORD) strlen (text), &n, NULL); //-V202 13074 13075 txSetConsoleAttr (restore); 13076 13077 if (*_txLogName) do //-V2530 13078 { 13079 HANDLE log = CreateFile (_txLogName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 13080 if (log == INVALID_HANDLE_VALUE) break; 13081 13082 SetFilePointer (log, 0, NULL, FILE_END); 13083 WriteFile (log, text, (DWORD) strlen (text), &n, NULL); //-V202 13084 13085 CloseHandle (log); 13086 } 13087 while (false); 13088 13089 if (ret) *ret = 0; 13090 13091 return (type == _CRT_WARN); 13092 } 13093 13094 #endif 13095 13096 //----------------------------------------------------------------------------------------------------------------- 13097 13098 int txMessageBox (const char text[], const char header[], unsigned flags /*= MB_ICONINFORMATION | MB_OKCANCEL*/) 13099 { 13100 $5 static wchar_t textW [_TX_BIGBUFSIZE * sizeof (wchar_t)] = L"[NULL text]"; 13101 $ static wchar_t headerW [_TX_BUFSIZE * sizeof (wchar_t)] = L"[NULL header]"; 13102 13103 if (text) {$ MultiByteToWideChar (_TX_CODEPAGE, 0, text, -1, textW, sizearr (textW)) || memset (textW, 0, sizeof (textW)); } 13104 if (header) {$ MultiByteToWideChar (_TX_CODEPAGE, 0, header, -1, headerW, sizearr (headerW)) || memset (headerW, 0, sizeof (headerW)); } 13105 13106 $ txSleep(); 13107 13108 $ int ret = MessageBoxW (NULL, (*textW)? textW : L"[Empty]", (*headerW)? headerW : L"[Empty]", 13109 flags | MB_SETFOREGROUND | MB_TOPMOST); 13110 13111 $ GetAsyncKeyState (VK_SHIFT); GetAsyncKeyState (VK_CONTROL); GetAsyncKeyState (VK_MENU); 13112 13113 $ if (ret == IDCANCEL && GetAsyncKeyState (VK_SHIFT) && GetAsyncKeyState (VK_CONTROL) && GetAsyncKeyState (VK_MENU)) 13114 { 13115 $ SendNotifyMessage (txWindow(), (_txMain? WM_CLOSE : WM_DESTROY), 0, 0); 13116 $ _txWaitFor (!_txCanvas_Window, _TX_TIMEOUT); 13117 } 13118 13119 $ return ret; 13120 } 13121 13122 //----------------------------------------------------------------------------------------------------------------- 13123 13124 bool txGetAsyncKeyState (int key) 13125 { 13126 $1 HWND wnd = GetForegroundWindow(); 13127 13128 return (GetAsyncKeyState (key) & 0x8000) && 13129 (wnd == txWindow() || wnd == Win32::GetConsoleWindow()); 13130 } 13131 13132 //----------------------------------------------------------------------------------------------------------------- 13133 13134 bool txNotifyIcon (unsigned flags, const char* title, const char* format, ...) 13135 { 13136 $5 if (_TX_ARGUMENT_FAILED (format)) return false; 13137 13138 $ va_list arg; va_start (arg, format); 13139 $ bool ok = true; 13140 13141 #if defined (_WIN32_IE) && (_WIN32_IE >= 0x0500) 13142 13143 $ NOTIFYICONDATA nid = { sizeof (nid) }; 13144 13145 $ nid.uFlags = NIF_ICON | NIF_TIP | NIF_INFO; 13146 $ nid.hWnd = NULL; 13147 $ nid.uID = 1; 13148 $ nid.hIcon = _txCreateTXIcon (16); assert (nid.hIcon); 13149 $ strncpy_s (nid.szTip, sizeof (nid.szTip), "TXLib Information", sizeof (nid.szTip)); 13150 $ strncpy_s (nid.szInfoTitle, sizeof (nid.szInfoTitle), (title? title : "TXLib сообщает"), sizeof (nid.szInfoTitle) - 1); 13151 $ _tx_vsnprintf_s (nid.szInfo, sizeof (nid.szInfo), format, arg); 13152 $ nid.dwInfoFlags = flags; 13153 13154 $ txOutputDebugPrintf ("\r" _TX_VERSION " - %s: %s (Icon notification)\n", nid.szInfoTitle, nid.szInfo); 13155 13156 $ ok &= !!Shell_NotifyIcon (NIM_ADD, (::NOTIFYICONDATA*) &nid); 13157 $ ok &= !!Shell_NotifyIcon (NIM_MODIFY, (::NOTIFYICONDATA*) &nid); 13158 13159 $ if (nid.hIcon) DestroyIcon (nid.hIcon) asserted; 13160 13161 #else 13162 13163 $ char nid_szInfo[_TX_BUFSIZE] = ""; 13164 $ _tx_vsnprintf_s (nid_szInfo, sizeof (nid_szInfo), format, arg); 13165 $ txOutputDebugPrintf ("\r" _TX_VERSION " - %s: %s (Icon notification - NOT displayed)\n", title, nid_szInfo); 13166 $ ok = false; 13167 13168 $ (void)flags; (void)title; 13169 13170 #endif 13171 13172 $ va_end (arg); 13173 return ok; 13174 } 13175 13176 //----------------------------------------------------------------------------------------------------------------- 13177 13178 void _txTrace (const char* file, int line, const char* func, const char* msg /*= NULL*/, ...) 13179 { 13180 unsigned id = GetCurrentThreadId(); 13181 13182 const char marks[2][2][3] = {{"uU", "cC"}, {"mM", "??"}}; 13183 13184 char mark = marks [id == _txMainThreadId] [id == _txCanvas_ThreadId] [(_txLoc::Cur.inTX > 0)]; 13185 13186 char msgStr[_TX_BUFSIZE] = ""; 13187 if (msg) 13188 { 13189 va_list arg; va_start (arg, msg); 13190 _tx_vsnprintf_s (msgStr, sizeof (msgStr) - 1, msg, arg); 13191 va_end (arg); 13192 } 13193 13194 txOutputDebugPrintf ("%s - 0x%p %c%c%c%c%c%d [%c] - %-*s (%5d) " "|%*s%s" "%s%s\n", 13195 13196 _TX_VERSION, (void*) &_txInitialized, 13197 13198 "cC"[!!_txConsole], "mM"[_txMain], "dD"[_txIsDll], "rR"[_txRunning], "eE"[_txExit], 13199 _txLoc::Cur.trace, mark, 13200 13201 (int) sizeof (__FILE__) - 1, (file? file : "(NULL file)"), line, 13202 2 * (_txLoc::Cur.inTX - 1) * !!func, "", (func? func : ""), 13203 13204 ((*msgStr && func)? ": " : ""), msgStr); 13205 } 13206 13207 //----------------------------------------------------------------------------------------------------------------- 13208 13209 int txOutputDebugPrintf (const char* format, ...) 13210 { 13211 if (!format) return 0; 13212 13213 enum { msgbox = 1, print = 2, compr = 4 }; 13214 int options = 0; 13215 13216 for (; format && *format; format++) 13217 { 13218 if (*format == '\a') options |= msgbox; 13219 else if (*format == '\f') options |= print; 13220 else if (*format == '\r') options |= compr; 13221 else break; 13222 } 13223 13224 char text[_TX_BIGBUFSIZE] = ""; 13225 13226 va_list arg; va_start (arg, format); 13227 int n = (int) _tx_vsnprintf_s (text, sizeof (text) - 1-1, format, arg); //-V202 13228 va_end (arg); 13229 13230 struct __ { static int trimSpaces (char str[]) 13231 { 13232 char *dst = str, *src = str; 13233 13234 for (char d = ' '; d; src++) 13235 if (isspace ((unsigned char)(*src))) { if (d != ' ') *dst++ = d = ' '; } 13236 else *dst++ = d = *src; 13237 13238 return (int) (dst - str - 1); //-V202 13239 }}; 13240 13241 if (options & compr) n = __::trimSpaces (text); 13242 13243 OutputDebugString (text); 13244 13245 if (options & print) fprintf (stderr, "%s", text); 13246 13247 if (options & msgbox) txMessageBox (text, "Оказывается, что", MB_ICONEXCLAMATION); 13248 13249 return n; 13250 } 13251 13252 //----------------------------------------------------------------------------------------------------------------- 13253 13254 intptr_t _tx_snprintf_s (char* stream, intptr_t size, const char* format, ...) 13255 { 13256 if (!format) return 0; 13257 13258 va_list arg; va_start (arg, format); 13259 intptr_t ret = _tx_vsnprintf_s (stream, size, format, arg); 13260 va_end (arg); 13261 13262 return ret; 13263 } 13264 13265 //----------------------------------------------------------------------------------------------------------------- 13266 13267 intptr_t _tx_vsnprintf_s (char stream[], intptr_t size, const char format[], va_list arg) 13268 { 13269 if (!stream || !format) return 0; 13270 13271 #if defined (_TRUNCATE) 13272 intptr_t ret = _vsnprintf_s (stream, size, _TRUNCATE, format, arg); 13273 #else 13274 intptr_t ret = _vsnprintf (stream, size, format, arg); 13275 #endif 13276 13277 if (ret < 0 && size >= 4) //-V112 13278 { 13279 const char ellipsis[] = "..."; 13280 size_t szEllipsis = sizeof (ellipsis) - 1; 13281 13282 strncpy_s (stream + size - szEllipsis, szEllipsis+1, ellipsis, szEllipsis); 13283 } 13284 13285 return (ret >= 0)? ret : size; 13286 } 13287 13288 //----------------------------------------------------------------------------------------------------------------- 13289 13290 #if defined (__CYGWIN__) 13291 13292 int _getch() 13293 { 13294 termios oldattr = {}; tcgetattr (STDIN_FILENO, &oldattr); 13295 13296 termios newattr = oldattr; 13297 newattr.c_lflag &= ~(ICANON | ECHO); 13298 tcsetattr (STDIN_FILENO, TCSANOW, &newattr); 13299 13300 int ch = getchar(); 13301 13302 tcsetattr (STDIN_FILENO, TCSANOW, &oldattr); 13303 13304 return ch; 13305 } 13306 13307 //----------------------------------------------------------------------------------------------------------------- 13308 13309 int _putch (int ch) 13310 { 13311 termios old = {}; tcgetattr (STDOUT_FILENO, &old); 13312 13313 termios cur = old; 13314 cur.c_lflag &= ~ICANON; 13315 cur.c_lflag |= ECHO; 13316 tcsetattr (STDOUT_FILENO, TCSANOW, &cur); 13317 13318 putchar (ch); 13319 13320 tcsetattr (STDOUT_FILENO, TCSANOW, &old); 13321 13322 return ch; 13323 } 13324 13325 //----------------------------------------------------------------------------------------------------------------- 13326 13327 int _kbhit() 13328 { 13329 termios old = {}; tcgetattr (STDIN_FILENO, &old); 13330 13331 termios cur = old; 13332 cur.c_lflag &= ~(ICANON | ECHO); 13333 cur.c_cc[VMIN] = 1; 13334 cur.c_cc[VTIME] = 0; 13335 13336 tcsetattr (STDIN_FILENO, TCSAFLUSH, &cur); 13337 13338 fd_set fd = {}; FD_SET (STDIN_FILENO, &fd); 13339 timeval tv = {}; 13340 13341 int res = select (STDIN_FILENO + 1, &fd, NULL, NULL, &tv) && FD_ISSET (STDIN_FILENO, &fd); 13342 13343 tcsetattr (STDIN_FILENO, TCSAFLUSH, &old); 13344 13345 return res; 13346 } 13347 13348 #endif 13349 13350 #endif // TX_COMPILED 13351 13352 //} 13353 //----------------------------------------------------------------------------------------------------------------- 13354 13355 //----------------------------------------------------------------------------------------------------------------- 13356 //{ Information 13357 //----------------------------------------------------------------------------------------------------------------- 13358 13359 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 13360 13361 const char* txGetModuleFileName (bool fileNameOnly /*= true*/) 13362 { 13363 $9 static char name[MAX_PATH] = ""; 13364 13365 $ if (!*name) 13366 { 13367 $ if (!GetModuleFileName (NULL, name, sizeof (name) - 1)) 13368 {$ strncpy_s (name, sizeof (name), "~TXApp", 6); } 13369 13370 $ char* ext = strrchr (name, '.'); 13371 $ if (ext) _strlwr_s (ext, sizeof (name) - 1 - (ext - name)); 13372 } 13373 13374 $ assert (*name); 13375 13376 $ if (fileNameOnly) return name; 13377 13378 $ static char fullName[MAX_PATH] = ""; 13379 $ static char* title = fullName; 13380 13381 $ if (!*fullName || !*title) 13382 { 13383 $ strncpy_s (fullName, sizeof (fullName), name, sizeof (fullName) - 1); 13384 13385 $ title = strrchr (fullName, '\\'); if (!title) title = fullName; 13386 $ char* ext = strrchr (fullName, '.'); if (!ext) ext = fullName + strlen (fullName); 13387 13388 $ size_t sz = sizeof (fullName) - (ext - fullName); 13389 $ strncpy_s (ext, sz-1, " - TXLib", sz); 13390 13391 $ title++; 13392 } 13393 13394 $ assert (*title); 13395 13396 $ return title; 13397 } 13398 13399 #endif // TX_COMPILED 13400 13401 //----------------------------------------------------------------------------------------------------------------- 13402 13403 inline const char* _txAppInfo() 13404 { 13405 $1 time_t timeT = time (NULL) - clock()/CLOCKS_PER_SEC; //-V104 13406 char timeS[32] = ""; 13407 ctime_s (timeS, sizeof (timeS), &timeT); 13408 13409 static char text[_TX_BUFSIZE] = ""; 13410 char cwd [MAX_PATH] = ""; 13411 13412 _tx_snprintf_s (text, sizeof (text) - 1, 13413 13414 "Developed with:\n\n" 13415 "The Dumb Artist Library (TX Library)\n" 13416 _TX_VERSION "\n" _TX_AUTHOR "\n" 13417 "See license on: http://txlib.ru\n\n" 13418 13419 "TXLib file:" "\t" __FILE__ "\n" 13420 "Compiled:" "\t" __DATE__ " " __TIME__ ", " __TX_COMPILER__ ", %s, %d-bit, " _TX_BUILDMODE "\n" 13421 "Started:" "\t" "%.6s %.4s %.8s\n\n" 13422 13423 "Run file:" "\t" "%s\n" 13424 "Directory:" "\t" "%s", 13425 13426 #if defined (_MSC_VER) 13427 "MSVC Runtime", 13428 #elif defined (__CYGWIN__) 13429 "Cygwin Runtime", 13430 #elif defined (_GCC_VER) && defined (_WIN64) 13431 __mingw_get_crt_info(), 13432 #else 13433 "MinGW Runtime " TX_QUOTE (__MINGW32_MAJOR_VERSION) "." TX_QUOTE (__MINGW32_MINOR_VERSION), 13434 #endif 13435 (sizeof (void*) == sizeof (DWORD))? 32 : 64, //-V112 13436 13437 timeS + 4, timeS + 20, timeS + 11, //-V112 These offsets are ANSI standardized 13438 txGetModuleFileName(), 13439 _getcwd (cwd, sizeof (cwd) - 1)); 13440 13441 return text; 13442 } 13443 13444 //} 13445 //----------------------------------------------------------------------------------------------------------------- 13446 13448 //} 13449 //================================================================================================================= 13450 13451 //================================================================================================================= 13452 //{ TXLib API implementation 13453 // Реализация TXLib API 13454 //================================================================================================================= 13455 13456 inline const char* txVersion() 13457 { 13458 return _TX_VERSION; 13459 } 13460 13461 //----------------------------------------------------------------------------------------------------------------- 13462 13463 inline unsigned txVersionNumber() 13464 { 13465 return _TX_VER; //-V2517 13466 } 13467 13468 //----------------------------------------------------------------------------------------------------------------- 13469 13470 inline HWND txWindow() 13471 { 13472 $9 return _txCanvas_Window; 13473 } 13474 13475 //----------------------------------------------------------------------------------------------------------------- 13476 13477 inline HDC& txDC() 13478 { 13479 return _txCanvas_BackBuf[0]; 13480 } 13481 13482 //----------------------------------------------------------------------------------------------------------------- 13483 13484 inline RGBQUAD* txVideoMemory() 13485 { 13486 return _txCanvas_Pixels; 13487 } 13488 13489 //----------------------------------------------------------------------------------------------------------------- 13490 13491 inline int txGetExtentX (HDC dc /*= txDC()*/) 13492 { 13493 return txGetExtent (dc) .x; 13494 } 13495 13496 //----------------------------------------------------------------------------------------------------------------- 13497 13498 inline int txGetExtentY (HDC dc /*= txDC()*/) 13499 { 13500 return txGetExtent (dc) .y; 13501 } 13502 13503 //----------------------------------------------------------------------------------------------------------------- 13504 13505 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 13506 13507 POINT txGetExtent (HDC dc /*= txDC()*/) 13508 { 13509 $0 static POINT err = {-1, -1}; 13510 13511 if (!dc) {$ POINT screen = { GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN) }; return screen; }; 13512 13513 if (_TX_DEFAULT_HDC_FAILED (dc)) {$ return err; } 13514 13515 $ BITMAP bmap = {}; 13516 $ txGDI (Win32::GetObject (Win32::GetCurrentObject (dc, OBJ_BITMAP), sizeof (bmap), &bmap), dc) asserted; 13517 13518 $ POINT size = { bmap.bmWidth, bmap.bmHeight }; 13519 $ return size; 13520 } 13521 13522 //----------------------------------------------------------------------------------------------------------------- 13523 13524 bool txDestroyWindow (HWND wnd /*= txWindow()*/) 13525 { 13526 $1 if (!wnd || !txWindow()) return false; 13527 13528 $ if (wnd != txWindow()) 13529 { 13530 $ return !!SendNotifyMessage (txWindow(), _TX_WM_DESTROYWND, 0, (LPARAM) wnd); 13531 } 13532 13533 $ if (SendNotifyMessage (txWindow(), (_txMain? WM_CLOSE : WM_DESTROY), 0, 0) == 0) return false; 13534 13535 $ if (_txMain) 13536 { 13537 $ txNotifyIcon (NIIF_WARNING, NULL, "\n" "Очень, очень плохо завершать программу через txDestroyWindow().\n\n" 13538 "Возвращайтесь через main(), там вам будут рады.\n"); 13539 $ Sleep (_TX_TIMEOUT); 13540 } 13541 13542 $ _txWaitFor (!_txCanvas_Window, _TX_TIMEOUT); 13543 13544 $ return _txCanvas_Window == NULL; 13545 } 13546 13547 //----------------------------------------------------------------------------------------------------------------- 13548 13549 HPEN txSetColor (COLORREF color, double thickness /*= 1*/, HDC dc /*= txDC()*/) 13550 { 13551 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return NULL; 13552 13553 $ HPEN pen = Win32::CreatePen ((color == TX_TRANSPARENT? PS_NULL : PS_SOLID), ROUND (thickness), color); 13554 13555 $ if (!pen) return (HPEN) NULL; 13556 13557 $ if (!_txBuffer_Select (pen, dc)) 13558 { 13559 $ Win32::DeleteObject (pen); 13560 $ return (HPEN) NULL; 13561 } 13562 13563 $ if (txGDI (Win32::SetTextColor (dc, color), dc) == CLR_INVALID) 13564 {$ return (HPEN) NULL; } 13565 13566 $ return pen; 13567 } 13568 13569 //----------------------------------------------------------------------------------------------------------------- 13570 13571 COLORREF txColor (double red, double green, double blue) 13572 { 13573 $1 if (red > 1) red = 1; if (red < 0) red = 0; 13574 $ if (green > 1) green = 1; if (green < 0) green = 0; 13575 $ if (blue > 1) blue = 1; if (blue < 0) blue = 0; 13576 13577 $ COLORREF color = RGB (ROUND (red * 255), ROUND (green * 255), ROUND (blue * 255)); 13578 13579 $ return txSetColor (color)? color : CLR_INVALID; 13580 } 13581 13582 //----------------------------------------------------------------------------------------------------------------- 13583 13584 COLORREF txGetColor (HDC dc /*= txDC()*/) 13585 { 13586 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return CLR_INVALID; 13587 13588 $ HGDIOBJ obj = txGDI ((Win32::GetCurrentObject (dc, OBJ_PEN)), dc); 13589 $ assert (obj); if (!obj) return CLR_INVALID; //-V547 13590 13591 $ union { EXTLOGPEN extLogPen; LOGPEN LogPen; } buf = {}; //-V2514 13592 13593 $ int size = Win32::GetObject (obj, 0, NULL); 13594 $ Win32::GetObject (obj, sizeof (buf), &buf) asserted; 13595 13596 $ return (size == sizeof (LOGPEN))? buf.LogPen.lopnColor : buf.extLogPen.elpColor; 13597 } 13598 13599 //----------------------------------------------------------------------------------------------------------------- 13600 13601 HBRUSH txSetFillColor (COLORREF color, HDC dc /*= txDC()*/) 13602 { 13603 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return NULL; 13604 13605 $ HBRUSH brush = (color == TX_TRANSPARENT)? (HBRUSH) Win32::GetStockObject (HOLLOW_BRUSH) : Win32::CreateSolidBrush (color); 13606 13607 $ return (_txBuffer_Select (brush, dc))? brush : (Win32::DeleteObject (brush), (HBRUSH) NULL); 13608 } 13609 13610 //----------------------------------------------------------------------------------------------------------------- 13611 13612 COLORREF txFillColor (double red, double green, double blue) 13613 { 13614 $1 if (red > 1) red = 1; if (red < 0) red = 0; 13615 $ if (green > 1) green = 1; if (green < 0) green = 0; 13616 $ if (blue > 1) blue = 1; if (blue < 0) blue = 0; 13617 13618 $ COLORREF color = RGB (ROUND (red * 255), ROUND (green * 255), ROUND (blue * 255)); 13619 13620 $ return txSetFillColor (color)? color : CLR_INVALID; 13621 } 13622 13623 //----------------------------------------------------------------------------------------------------------------- 13624 13625 COLORREF txGetFillColor (HDC dc /*= txDC()*/) 13626 { 13627 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return CLR_INVALID; 13628 13629 $ HGDIOBJ obj = txGDI ((Win32::GetCurrentObject (dc, OBJ_BRUSH)), dc); 13630 $ assert (obj); if (!obj) return CLR_INVALID; //-V547 13631 13632 $ LOGBRUSH buf = {}; 13633 $ txGDI ((Win32::GetObject (obj, sizeof (buf), &buf)), dc) asserted; 13634 13635 $ return buf.lbColor; 13636 } 13637 13638 //----------------------------------------------------------------------------------------------------------------- 13639 13640 bool txClear (HDC dc /*= txDC()*/) 13641 { 13642 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13643 13644 $ POINT size = txGetExtent (dc); 13645 $ return txGDI (!!(Win32::PatBlt (dc, 0, 0, size.x, size.y, PATCOPY)), dc); 13646 } 13647 13648 //----------------------------------------------------------------------------------------------------------------- 13649 13650 bool txSetPixel (double x, double y, COLORREF color, HDC dc /*= txDC()*/) 13651 { 13652 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13653 13654 $ txGDI ((Win32::SetPixel (dc, ROUND (x), ROUND (y), color)), dc); 13655 13656 $ return true; 13657 } 13658 13659 //----------------------------------------------------------------------------------------------------------------- 13660 13661 bool txPixel (double x, double y, double red, double green, double blue, HDC dc /*= txDC()*/) 13662 { 13663 $1 if (red > 1) red = 1; if (red < 0) red = 0; 13664 $ if (green > 1) green = 1; if (green < 0) green = 0; 13665 $ if (blue > 1) blue = 1; if (blue < 0) blue = 0; 13666 13667 $ return txSetPixel (x, y, RGB (ROUND (red * 255), ROUND (green * 255), ROUND (blue * 255)), dc); 13668 } 13669 13670 //----------------------------------------------------------------------------------------------------------------- 13671 13672 COLORREF txGetPixel (double x, double y, HDC dc /*= txDC()*/) 13673 { 13674 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return CLR_INVALID; 13675 13676 $ return txGDI ((Win32::GetPixel (dc, ROUND (x), ROUND (y))), dc); 13677 } 13678 13679 //----------------------------------------------------------------------------------------------------------------- 13680 13681 bool txLine (double x0, double y0, double x1, double y1, HDC dc /*= txDC()*/) 13682 { 13683 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13684 13685 $ bool ok = txGDI ((Win32::MoveToEx (dc, ROUND (x0), ROUND (y0), NULL)), dc); 13686 $ ok &= txGDI ((Win32::LineTo (dc, ROUND (x1), ROUND (y1) )), dc); 13687 13688 $ return ok; 13689 } 13690 13691 //----------------------------------------------------------------------------------------------------------------- 13692 13693 bool txRectangle (double x0, double y0, double x1, double y1, HDC dc /*= txDC()*/) 13694 { 13695 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13696 13697 $ return txGDI ((Win32::Rectangle (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1))), dc); 13698 } 13699 13700 //----------------------------------------------------------------------------------------------------------------- 13701 13702 bool txPolygon (const POINT points[], int numPoints, HDC dc /*= txDC()*/) 13703 { 13704 $1 if (_TX_ARGUMENT_FAILED (points)) return false; 13705 $ if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13706 13707 $ return txGDI (!!(Win32::Polygon (dc, points, numPoints)), dc); 13708 } 13709 13710 //----------------------------------------------------------------------------------------------------------------- 13711 13712 bool txEllipse (double x0, double y0, double x1, double y1, HDC dc /*= txDC()*/) 13713 { 13714 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13715 13716 $ return txGDI ((Win32::Ellipse (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1))), dc); 13717 } 13718 13719 //----------------------------------------------------------------------------------------------------------------- 13720 13721 bool txCircle (double x, double y, double r) 13722 { 13723 $1 return txEllipse (x-r, y-r, x+r, y+r); 13724 } 13725 13726 //----------------------------------------------------------------------------------------------------------------- 13727 13728 bool txArc (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc /*= txDC()*/) 13729 { 13730 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13731 13732 $ POINT center = { ROUND ((x0 + x1) /2), ROUND ((y0 + y1) /2) }; 13733 13734 $ double start = startAngle * txPI/180, 13735 end = (startAngle + totalAngle) * txPI/180; 13736 13737 $ return txGDI (!!(Win32::Arc (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1), 13738 ROUND (center.x + 1E3*cos (start)), ROUND (center.y - 1E3*sin (start)), 13739 ROUND (center.x + 1E3*cos (end)), ROUND (center.y - 1E3*sin (end)))), dc); 13740 } 13741 13742 //----------------------------------------------------------------------------------------------------------------- 13743 13744 bool txPie (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc /*= txDC()*/) 13745 { 13746 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13747 13748 $ POINT center = { ROUND ((x0 + x1) /2), ROUND ((y0 + y1) /2) }; 13749 13750 $ double start = startAngle * txPI/180, 13751 end = (startAngle + totalAngle) * txPI/180; 13752 13753 $ return txGDI (!!(Win32::Pie (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1), 13754 ROUND (center.x + 1E3*cos (start)), ROUND (center.y - 1E3*sin (start)), 13755 ROUND (center.x + 1E3*cos (end)), ROUND (center.y - 1E3*sin (end)))), dc); 13756 } 13757 13758 //----------------------------------------------------------------------------------------------------------------- 13759 13760 bool txChord (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc /*= txDC()*/) 13761 { 13762 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13763 13764 $ POINT center = { ROUND ((x0 + x1) /2), ROUND ((y0 + y1) /2) }; 13765 13766 $ double start = startAngle * txPI/180, 13767 end = (startAngle + totalAngle) * txPI/180; 13768 13769 $ return txGDI (!!(Win32::Chord (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1), 13770 ROUND (center.x + 1E3*cos (start)), ROUND (center.y - 1E3*sin (start)), 13771 ROUND (center.x + 1E3*cos (end)), ROUND (center.y - 1E3*sin (end)))), dc); 13772 } 13773 13774 //----------------------------------------------------------------------------------------------------------------- 13775 13776 bool txFloodFill (double x, double y, 13777 COLORREF color /*= TX_TRANSPARENT*/, DWORD mode /*= FLOODFILLSURFACE*/, HDC dc /*= txDC()*/) 13778 { 13779 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13780 13781 $ if (color == TX_TRANSPARENT) color = txGetPixel (x, y, dc); 13782 13783 $ return txGDI (!!(Win32::ExtFloodFill (dc, ROUND (x), ROUND (y), color, mode)), dc); 13784 } 13785 13786 //----------------------------------------------------------------------------------------------------------------- 13787 13788 bool txTextOut (double x, double y, const char text[], HDC dc /*= txDC()*/) 13789 { 13790 $1 if (_TX_ARGUMENT_FAILED (text)) return false; 13791 $ if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13792 13793 $ int len = (int) strlen (text); //-V202 13794 $ bool ok = txGDI (!!(Win32::TextOut (dc, ROUND (x), ROUND (y), text, len)), dc); 13795 13796 $ return ok; 13797 } 13798 13799 //----------------------------------------------------------------------------------------------------------------- 13800 13801 bool txDrawText (double x0, double y0, double x1, double y1, const char text[], 13802 unsigned format /*= DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_WORD_ELLIPSIS*/, 13803 HDC dc /*= txDC()*/) 13804 { 13805 $1 if (_TX_ARGUMENT_FAILED (text)) return false; 13806 $ if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13807 13808 #if !defined (NDEBUG) 13809 13810 $ if (x0 > x1) 13811 { 13812 $ SetLastError (ERROR_INVALID_DATA); 13813 $ TX_ERROR ("Параметр x0 = %g больше, чем x1 = %g. Текст выводиться не будет.", x0, x1); 13814 } 13815 13816 $ if (y0 > y1) 13817 { 13818 $ SetLastError (ERROR_INVALID_DATA); 13819 $ TX_ERROR ("Параметр y0 = %g больше, чем y1 = %g. Текст выводиться не будет.", y0, y1); 13820 } 13821 13822 #endif 13823 13824 $ RECT r = { ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1) }; 13825 13826 $ if (!strchr (text, '\n')) format |= DT_SINGLELINE; 13827 13828 $ unsigned prev = txSetTextAlign (TA_LEFT | TA_TOP | TA_NOUPDATECP, dc); 13829 13830 $ bool ok = false; 13831 13832 $ if (Win32::DrawText) 13833 { 13834 $ ok = !!txGDI ((Win32::DrawText (dc, text, -1, &r, format)), dc); 13835 $ Win32::GetPixel (dc, 0, 0); 13836 $ ok = true; //-V519 13837 } 13838 else 13839 { 13840 $ txTextOut ((x0 + x1) / 2, (y0 + y1) / 2, text); 13841 $ ok = false; 13842 } 13843 13844 $ txSetTextAlign (prev, dc); 13845 13846 $ return ok; 13847 } 13848 13849 //----------------------------------------------------------------------------------------------------------------- 13850 13851 HFONT txSelectFont (const char name[], double sizeY, double sizeX /*= -1*/, 13852 int bold /*= FW_DONTCARE*/, bool italic /*= false*/, bool underline /*= false*/, 13853 bool strikeout /*= false*/, double angle /*= 0*/, 13854 HDC dc /*= txDC()*/) 13855 { 13856 $1 if (_TX_ARGUMENT_FAILED (name)) return NULL; 13857 $ if (_TX_DEFAULT_HDC_FAILED (dc)) return NULL; 13858 13859 $ HFONT font = txFontExist (name)? 13860 Win32::CreateFont (ROUND (sizeY), ROUND ((sizeX >= 0)? sizeX : sizeY/3), 13861 ROUND (angle*10), 0, bold, italic, underline, strikeout, 13862 RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 13863 DEFAULT_QUALITY, DEFAULT_PITCH, name) 13864 : 13865 (HFONT) Win32::GetStockObject (SYSTEM_FIXED_FONT); 13866 13867 $ _txBuffer_Select (font, dc); 13868 13869 $ return font; 13870 } 13871 13872 //----------------------------------------------------------------------------------------------------------------- 13873 13874 SIZE txGetTextExtent (const char text[], HDC dc /*= txDC()*/) 13875 { 13876 $1 SIZE size = {-1, -1}; 13877 13878 $ if (_TX_ARGUMENT_FAILED (text)) return size; 13879 $ if (_TX_DEFAULT_HDC_FAILED (dc)) return size; 13880 13881 $ size_t len = strlen (text); 13882 $ txGDI ((Win32::GetTextExtentPoint32 (dc, text, (int) len, &size)), dc) asserted; //-V202 13883 13884 $ return size; 13885 } 13886 13887 //----------------------------------------------------------------------------------------------------------------- 13888 13889 int txGetTextExtentX (const char text[], HDC dc /*= txDC()*/) 13890 { 13891 $1 return txGetTextExtent (text, dc) .cx; 13892 } 13893 13894 //----------------------------------------------------------------------------------------------------------------- 13895 13896 int txGetTextExtentY (const char text[], HDC dc /*= txDC()*/) 13897 { 13898 $1 return txGetTextExtent (text, dc) .cy; 13899 } 13900 13901 //----------------------------------------------------------------------------------------------------------------- 13902 13903 unsigned txSetTextAlign (unsigned align /*= TA_CENTER | TA_BASELINE*/, HDC dc /*= txDC()*/) 13904 { 13905 $1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; //-V601 13906 13907 $ return txGDI ((Win32::SetTextAlign (dc, align)), dc); 13908 } 13909 13910 //----------------------------------------------------------------------------------------------------------------- 13911 13912 LOGFONT* txFontExist (const char name[]) 13913 { 13914 $1 if (_TX_ARGUMENT_FAILED (name)) return NULL; 13915 13916 $ static LOGFONT font = {}; 13917 $ font.lfCharSet = DEFAULT_CHARSET; 13918 $ strncpy_s (font.lfFaceName, sizeof (font.lfFaceName), name, sizeof (font.lfFaceName) - 1); 13919 13920 $ struct tools 13921 { 13922 static int CALLBACK enumFonts (const LOGFONT* fnt, const TEXTMETRIC*, DWORD, LPARAM data) 13923 { 13924 $ if (_TX_ARGUMENT_FAILED (fnt)) return 0; 13925 $ if (_TX_ARGUMENT_FAILED (data)) return 0; 13926 13927 #ifndef __STRICT_ANSI__ 13928 $ return _strnicmp (fnt->lfFaceName, ((LOGFONT*)data)->lfFaceName, LF_FACESIZE); 13929 13930 #else 13931 $ return strncmp (fnt->lfFaceName, ((LOGFONT*)data)->lfFaceName, LF_FACESIZE); 13932 13933 #endif 13934 } 13935 }; 13936 13937 $ return txGDI ((Win32::EnumFontFamiliesEx (NULL, &font, tools::enumFonts, (LPARAM) &font, 0)), NULL) == 0? &font : NULL; 13938 } 13939 13940 //----------------------------------------------------------------------------------------------------------------- 13941 13942 bool txSelectObject (HGDIOBJ obj, HDC dc /*= txDC()*/) 13943 { 13944 $1 if (_TX_ARGUMENT_FAILED (obj)) return false; 13945 $ if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 13946 13947 $ return _txBuffer_Select (obj, dc); 13948 } 13949 13950 //----------------------------------------------------------------------------------------------------------------- 13951 13952 HDC txCreateCompatibleDC (double sizeX, double sizeY, HBITMAP bitmap /*= NULL*/, RGBQUAD** pixels /*= NULL*/) 13953 { 13954 $1 POINT size = { ROUND (sizeX), ROUND (sizeY) }; 13955 13956 $ HDC dc = _txBuffer_Create (NULL, &size, bitmap, pixels); 13957 $ assert (dc); if (!dc) return NULL; //-V547 13958 13959 $ txSetDefaults (dc); 13960 13961 $ if (!_txCanvas_UserDCs) return dc; 13962 13963 $ txAutoLock _lock; 13964 $ _txCanvas_UserDCs->push_back (dc); 13965 13966 $ if (_txCanvas_UserDCs->size() >= _TX_BUFSIZE) 13967 {$ txNotifyIcon (NIIF_WARNING, NULL, "Вы загрузили уже %d HDC, системе может стать плохо.", (int) _txCanvas_UserDCs->size()); } //-V202 13968 13969 $ return dc; 13970 } 13971 13972 //----------------------------------------------------------------------------------------------------------------- 13973 13974 HDC txCreateDIBSection (double sizeX, double sizeY, RGBQUAD** pixels /*= NULL*/) 13975 { 13976 $1 return txCreateCompatibleDC (sizeX, sizeY, NULL, pixels); 13977 } 13978 13979 //----------------------------------------------------------------------------------------------------------------- 13980 13981 HDC txCreateDIBSection (double sizeX, double sizeY, COLORREF** pixels) 13982 { 13983 $1 return txCreateDIBSection (sizeX, sizeY, (RGBQUAD**) pixels); 13984 } 13985 13986 //----------------------------------------------------------------------------------------------------------------- 13987 13988 HDC txLoadImage (const char filename[], int sizeX /*= 0*/, int sizeY /*= 0*/, 13989 unsigned imageFlags /*= IMAGE_BITMAP*/, unsigned loadFlags /*= LR_LOADFROMFILE*/) 13990 { 13991 $1 if (_TX_ARGUMENT_FAILED (filename && *filename)) return NULL; 13992 13993 $ HBITMAP image = (HBITMAP) Win32::LoadImage ((loadFlags & LR_LOADFROMFILE)? NULL : GetModuleHandle (NULL), 13994 filename, imageFlags, sizeX, sizeY, loadFlags); 13995 $ if (!image) return NULL; 13996 13997 $ HDC dc = txCreateCompatibleDC (sizeX, sizeY, image); 13998 13999 $ if (!(loadFlags & LR_LOADFROMFILE)) return dc; 14000 14001 $ static std::map <std::string, unsigned> loadTimes; 14002 $ std::string file = filename; 14003 $ unsigned time = GetTickCount(); 14004 14005 $ if ((long) (time - loadTimes [file]) < _TX_TIMEOUT) 14006 {$ txNotifyIcon (NIIF_WARNING, NULL, "Вы загружаете \"%s\" слишком часто, программа будет тормозить.", filename); } 14007 14008 $ loadTimes [file] = time; 14009 14010 $ return dc; 14011 } 14012 14013 //----------------------------------------------------------------------------------------------------------------- 14014 14015 bool txDeleteDC (HDC* pdc) 14016 { 14017 $1 if (_TX_ARGUMENT_FAILED (pdc)) return false; 14018 14019 $ HDC dc = *pdc; 14020 $ bool ok = _txBuffer_Delete (pdc); 14021 $ if (!ok) return false; 14022 14023 $ if (!_txCanvas_UserDCs) return ok; 14024 14025 $ txAutoLock _lock; 14026 14027 $ for (std::vector <HDC> ::iterator it = _txCanvas_UserDCs->begin(); it != _txCanvas_UserDCs->end(); ++it) 14028 if (*it == dc) 14029 { 14030 $ std::swap (*it, _txCanvas_UserDCs->back()); 14031 $ _txCanvas_UserDCs->pop_back(); 14032 $ break; 14033 } 14034 14035 $ return ok; 14036 } 14037 14038 //----------------------------------------------------------------------------------------------------------------- 14039 14040 bool txDeleteDC (HDC dc) 14041 { 14042 $1 return txDeleteDC (&dc); 14043 } 14044 14045 //----------------------------------------------------------------------------------------------------------------- 14046 14047 bool txBitBlt (HDC destImage, double xDest, double yDest, double width, double height, 14048 HDC sourceImage, double xSource /*= 0*/, double ySource /*= 0*/, unsigned operation /*= SRCCOPY*/) 14049 { 14050 $1 if (_TX_HDC_FAILED (destImage)) return false; 14051 $ if (_TX_HDC_FAILED (sourceImage)) return false; 14052 14053 $ POINT size = txGetExtent (sourceImage); 14054 $ if (!width) width = size.x; //-V550 14055 $ if (!height) height = size.y; //-V550 14056 14057 $ return txGDI (!!(Win32::BitBlt (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height), 14058 sourceImage, ROUND (xSource), ROUND (ySource), operation)), destImage); 14059 } 14060 14061 //----------------------------------------------------------------------------------------------------------------- 14062 14063 bool txBitBlt (double xDest, double yDest, HDC sourceImage, double xSource /*= 0*/, double ySource /*= 0*/) 14064 { 14065 $1 if (_TX_TXWINDOW_FAILED()) return false; 14066 14067 $ return txBitBlt (txDC(), xDest, yDest, 0, 0, sourceImage, xSource, ySource); 14068 } 14069 14070 //----------------------------------------------------------------------------------------------------------------- 14071 14072 bool txTransparentBlt (HDC destImage, double xDest, double yDest, double width, double height, 14073 HDC sourceImage, double xSource /*= 0*/, double ySource /*= 0*/, COLORREF transColor /*= TX_BLACK*/) 14074 { 14075 // Это проверки того, правильные ли HDC вы передали в функцию. 14076 // Не бойтесь долларов - <s>это не запрещенная валюта</s> это макросы для отладки TXLib'а. 14077 // (!) При первом чтении это можно пропустить. 14078 14079 $1 if (_TX_HDC_FAILED (destImage)) return false; 14080 $ if (_TX_HDC_FAILED (sourceImage)) return false; 14081 14082 // Это автоматическое определение размеров картинки (точнее, HDC источника - source) с помощью txGetExtent(). 14083 // При первом чтении это можно пропустить. 14084 14085 $ POINT size = txGetExtent (sourceImage); 14086 $ if (!width) width = size.x; //-V550 14087 $ if (!height) height = size.y; //-V550 14088 14089 // Это проверка того, что картинка (или ее часть) правильно попадает в окно (точнее, HDC приемника - destination, dest). 14090 // Если она "вылезает" из окна в любую сторону, то Win32::TransparentBlt() не будет работать. Эта проверка происходит только 14091 // в режиме отладки (когда не задан макрос NDEBUG - No Debugging, без отладки). 14092 // (!) При первом чтении это можно пропустить. 14093 14094 #if !defined (NDEBUG) 14095 14096 $ if (!(0 <= xSource && xSource + width <= size.x && 14097 0 <= ySource && ySource + height <= size.y)) 14098 { 14099 $ SetLastError (ERROR_INVALID_DATA); 14100 $ TX_ERROR ("Прямоугольник копируемой области {%g, %g, %g, %g} не полностью лежит внутри изображения-источника {%d, %d, %d, %d}, " 14101 "функция txTransparentBlt() работать не будет.", xSource, ySource, xSource + width, ySource + height, 0, 0, (int) size.x, (int) size.y); 14102 } 14103 14104 #endif 14105 14106 $ bool ok = true; 14107 14108 $ if (Win32::TransparentBlt) 14109 { 14110 // (!) А вот теперь уже надо начать читать. 14111 // 14112 // Ниже - это вызов стандартной Win32::TransparentBlt() из ядра Windows. Погуглите "Windows TransparentBlt function" 14113 // и почитайте про ее параметры. 14114 // 14115 // Как видите, оригинальная функция из Win32 принимает размеры не только исходной, но и итоговой картинки, и если они не 14116 // совпадают, то картинка будет уменьшена или увеличена. TXlib'овская <s>паленая</s> функция TransparentBlt предполагает, что 14117 // эти размеры всегда совпадают, и поэтому при работе с TransparentBlt() масштаб будет всегда 1:1. <s>Так себе решение, но</s> 14118 // это сделано для упрощения вызова функции TransparentBlt(). 14119 14120 // Только то, что эти параметры передаются одинаковыми, не дает возможность менять масштаб картинки! // <<-- 14121 // // <<-- 14122 // ||||| |||||| // <<-- 14123 // vvvvv vvvvvv // <<-- 14124 // <<-- 14125 $ ok &= txGDI (!!(Win32::TransparentBlt (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height), // <<<< 14126 sourceImage, ROUND (xSource), ROUND (ySource), ROUND (width), ROUND (height), transColor)), // <<<< 14127 destImage); // <<-- 14128 // ^^^^^ ^^^^^^ // <<-- 14129 // ||||| |||||| // <<-- 14130 // // <<-- 14131 } // См. "TransparentBlt function" в Google, ищите смысл параметров wSrc и wDest (hSrc и hDest). Думайте! // <<-- 14132 else 14133 { 14134 $ ok &= txGDI (!!(Win32::BitBlt (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height), 14135 sourceImage, ROUND (xSource), ROUND (ySource), SRCCOPY)), 14136 destImage); 14137 } 14138 14139 // В TXLib-овской функции txTransparentBlt() проверок и комментариев больше, чем рабочего кода, и это как бы намекает, что 14140 // нетрудно сделать свою аналогичную функцию без ограничений масштаба отображения. <s>Если ты дочитал до этого места,</s> 14141 // пересядь с иглы TXLib'а на поверхность GDI Win32, <s>хотя GDI тоже так себе, так что лучше заюзай GDI+, SFML, OpenGL 14142 // или DirectX, будет круто. Хотя это и сложнее.</s> 14143 14144 // Пожалуйста, не надо бездумно копировать себе в программу код из TXLib'а. Осмыслите его и напишите свою функцию сами, 14145 // иначе вы породите невнятный паленый код и безнадежно испортите себе карму. :(( 14146 14147 $ return ok; 14148 } 14149 14150 //----------------------------------------------------------------------------------------------------------------- 14151 14152 bool txTransparentBlt (double xDest, double yDest, HDC sourceImage, 14153 COLORREF transColor /*= TX_BLACK*/, double xSource /*= 0*/, double ySource /*= 0*/) 14154 { 14155 $1 if (_TX_TXWINDOW_FAILED()) return false; 14156 14157 $ return txTransparentBlt (txDC(), xDest, yDest, 0, 0, sourceImage, xSource, ySource, transColor); 14158 } 14159 14160 //----------------------------------------------------------------------------------------------------------------- 14161 14162 bool txAlphaBlend (HDC destImage, double xDest, double yDest, double width, double height, 14163 HDC sourceImage, double xSource /*= 0*/, double ySource /*= 0*/, double alpha /*= 1.0*/) 14164 { 14165 $1 if (_TX_HDC_FAILED (destImage)) return false; 14166 $ if (_TX_HDC_FAILED (sourceImage)) return false; 14167 14168 $ POINT size = txGetExtent (sourceImage); 14169 $ if (!width) width = size.x; //-V550 14170 $ if (!height) height = size.y; //-V550 14171 14172 #if !defined (NDEBUG) 14173 14174 $ if (!(0 <= xSource && xSource + width <= size.x && 14175 0 <= ySource && ySource + height <= size.y)) 14176 { 14177 $ SetLastError (ERROR_INVALID_DATA); 14178 $ TX_ERROR ("Прямоугольник копируемой области {%g, %g, %g, %g} не полностью лежит внутри изображения-источника {%d, %d, %d, %d}, " 14179 "функция txAlphaBlend() работать не будет.", xSource, ySource, xSource + width, ySource + height, 0, 0, (int) size.x, (int) size.y); 14180 } 14181 14182 #endif 14183 14184 $ if (alpha < 0) alpha = 0; 14185 $ if (alpha > 1) alpha = 1; 14186 14187 $ BITMAP bmap = { 0, 0, 0, 0, 0, 24 }; 14188 $ bool ok = !!Win32::GetObject (txGDI ((Win32::GetCurrentObject (sourceImage, OBJ_BITMAP)), sourceImage), sizeof (bmap), &bmap); 14189 14190 $ BLENDFUNCTION blend = { AC_SRC_OVER, 0, (BYTE) ROUND (alpha * 255), (BYTE) ((bmap.bmBitsPixel == 32)? AC_SRC_ALPHA : 0) }; //-V112 //-V821 //-V2551 14191 14192 $ if (Win32::AlphaBlend) 14193 { 14194 $ ok &= txGDI (!!(Win32::AlphaBlend (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height), 14195 sourceImage, ROUND (xSource), ROUND (ySource), ROUND (width), ROUND (height), blend)), 14196 destImage); 14197 } 14198 else 14199 { 14200 $ ok &= txGDI (!!(Win32::BitBlt (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height), 14201 sourceImage, ROUND (xSource), ROUND (ySource), SRCCOPY)), 14202 destImage); 14203 $ ok = false; //-V519 14204 } 14205 14206 $ return ok; 14207 } 14208 14209 //----------------------------------------------------------------------------------------------------------------- 14210 14211 bool txAlphaBlend (double xDest, double yDest, HDC sourceImage, 14212 double xSource /*= 0*/, double ySource /*= 0*/, double alpha /*= 1.0*/) 14213 { 14214 $1 if (_TX_TXWINDOW_FAILED()) return false; 14215 14216 $ return txAlphaBlend (txDC(), xDest, yDest, 0, 0, sourceImage, xSource, ySource, alpha); 14217 } 14218 14219 //----------------------------------------------------------------------------------------------------------------- 14220 14221 HDC txUseAlpha (HDC image) 14222 { 14223 $1 if (_TX_HDC_FAILED (image)) return NULL; 14224 14225 $ HBITMAP bitmap = (HBITMAP) Win32::GetCurrentObject (image, OBJ_BITMAP); 14226 $ if (!bitmap) return NULL; 14227 14228 $ DIBSECTION dib = {}; 14229 $ Win32::GetObject (bitmap, sizeof (dib), &dib) asserted; 14230 14231 $ POINT size = { dib.dsBm.bmWidth, dib.dsBm.bmHeight }; 14232 $ BITMAPINFO info = {{ sizeof (info), size.x, size.y, 1, (WORD) (sizeof (RGBQUAD) * 8), BI_RGB }}; 14233 $ RGBQUAD* buf = NULL; 14234 14235 $ bool isDIB = (dib.dsBm.bmPlanes == 1 && 14236 dib.dsBm.bmBitsPixel == sizeof (RGBQUAD) * 8 && 14237 dib.dsBmih.biCompression == DIB_RGB_COLORS && 14238 dib.dsBm.bmBits); 14239 $ if (!isDIB) 14240 { 14241 $ buf = new (std::nothrow) RGBQUAD [size.x * size.y]; //-V121 14242 $ if (!buf) return NULL; 14243 14244 $ Win32::GetDIBits (image, bitmap, 0, size.y, buf, &info, DIB_RGB_COLORS) asserted; 14245 } 14246 else 14247 { 14248 $ buf = (RGBQUAD*) dib.dsBm.bmBits; 14249 } 14250 14251 $ for (int y = 0; y < size.y; y++) 14252 for (int x = 0; x < size.x; x++) 14253 { 14254 RGBQUAD* color = &buf [x + y * size.x]; // Get color at (x, y) within image buffer //-V108 14255 14256 color->rgbRed = (BYTE) ROUND (color->rgbRed * color->rgbReserved / 255.0); 14257 color->rgbGreen = (BYTE) ROUND (color->rgbGreen * color->rgbReserved / 255.0); 14258 color->rgbBlue = (BYTE) ROUND (color->rgbBlue * color->rgbReserved / 255.0); 14259 } 14260 14261 $ if (!isDIB) 14262 { 14263 $ Win32::SetDIBitsToDevice (image, 0, 0, size.x, size.y, 0, 0, 0, size.y, buf, &info, DIB_RGB_COLORS) asserted; 14264 14265 $ delete[] buf; 14266 } 14267 14268 $ return image; 14269 } 14270 14271 //----------------------------------------------------------------------------------------------------------------- 14272 14273 bool txSaveImage (const char filename[], HDC dc /*= txDC()*/) 14274 { 14275 $1 if (_TX_ARGUMENT_FAILED (filename)) return false; 14276 $ if (_TX_DEFAULT_HDC_FAILED (dc)) return false; 14277 14278 $ POINT size = txGetExtent (dc); 14279 14280 $ size_t szHdrs = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER), //-V119 14281 szImg = (size.x * size.y) * sizeof (RGBQUAD); //-V104 14282 14283 $ BITMAP bmap = {}; 14284 $ BITMAPFILEHEADER hdr = { 0x4D42 /* 'MB' */, (DWORD) (szHdrs + szImg), 0, 0, (DWORD) szHdrs }; //-V202 14285 $ BITMAPINFOHEADER info = { sizeof (info), size.x, size.y, 1, (WORD) (sizeof (RGBQUAD) * 8), BI_RGB }; 14286 14287 $ RGBQUAD* buf = NULL; 14288 $ bool ok = true; 14289 14290 $ ok &= !!Win32::GetObject (Win32::GetCurrentObject (dc, OBJ_BITMAP), sizeof (bmap), &bmap); 14291 14292 if (!ok) {$ return false; } 14293 14294 $ if (!bmap.bmBits) 14295 { 14296 $ buf = new (std::nothrow) RGBQUAD [size.x * size.y]; //-V121 14297 $ ok &= (buf != NULL); 14298 14299 $ int res = Win32::GetDIBits (dc, (HBITMAP) Win32::GetCurrentObject (dc, OBJ_BITMAP), 0, size.y, 14300 buf, (BITMAPINFO*) &info, DIB_RGB_COLORS); 14301 14302 if (res == ERROR_INVALID_PARAMETER) {$ SetLastError (res); } 14303 14304 $ ok &= !!res; 14305 } 14306 else 14307 { 14308 $ buf = (RGBQUAD*) bmap.bmBits; 14309 } 14310 14311 $ FILE* f = NULL; 14312 $ if (ok) fopen_s (&f, filename, "wb"); 14313 $ ok &= (f != NULL); 14314 14315 $ if (ok) ok &= (fwrite (&hdr, sizeof (hdr), 1, f) == 1); //-V575 //-V595 14316 $ if (ok) ok &= (fwrite (&info, sizeof (info), 1, f) == 1); 14317 $ if (ok) ok &= (fwrite (buf, szImg, 1, f) == 1); //-V575 14318 14319 $ ok &= (f && fclose (f) == 0); 14320 14321 $ if (!bmap.bmBits) 14322 { 14323 $ delete[] buf; 14324 $ buf = NULL; 14325 } 14326 14327 $ return ok; 14328 } 14329 14330 //----------------------------------------------------------------------------------------------------------------- 14331 14332 double txSleep (double time) 14333 { 14334 $1 LARGE_INTEGER start = {}; 14335 QueryPerformanceCounter (&start) asserted; 14336 14337 LARGE_INTEGER freq = {}; 14338 QueryPerformanceFrequency (&freq) asserted; 14339 14340 int lock = _txCanvas_RefreshLock; 14341 _txCanvas_RefreshLock = 0; 14342 14343 HWND wnd = txWindow(); 14344 if (wnd) {$ RedrawWindow (wnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_UPDATENOW); } 14345 14346 Sleep (ROUND ((time >= 0)? time : 0)); 14347 14348 _txCanvas_RefreshLock = lock; 14349 14350 LARGE_INTEGER stop = {}; 14351 QueryPerformanceCounter (&stop) asserted; 14352 14353 return 1000.0 * (double) (stop.QuadPart - start.QuadPart) / (double) freq.QuadPart; 14354 } 14355 14356 //----------------------------------------------------------------------------------------------------------------- 14357 14358 bool txLock (bool wait /*= true*/) 14359 { 14360 $0 if (_txCanvas_RefreshLock <= 0 || _txExit) Sleep (0); 14361 14362 $ if (wait) {$ return EnterCriticalSection (&_txCanvas_LockBackBuf), true; } //-V1048 14363 else {$ return !!TryEnterCriticalSection (&_txCanvas_LockBackBuf); } 14364 } 14365 14366 //----------------------------------------------------------------------------------------------------------------- 14367 14368 bool txUnlock() 14369 { 14370 $0 LeaveCriticalSection (&_txCanvas_LockBackBuf); 14371 14372 $ if (_txCanvas_RefreshLock <= 0 || _txExit) Sleep (0); 14373 $ return false; 14374 } 14375 14376 #endif // TX_COMPILED 14377 14378 //----------------------------------------------------------------------------------------------------------------- 14379 14380 template <typename T> 14381 inline T txUnlock (T value) 14382 { 14383 $1 txUnlock(); 14384 $ return value; 14385 } 14386 14387 //----------------------------------------------------------------------------------------------------------------- 14388 14389 inline void txRedrawWindow() 14390 { 14391 $1 txSleep (0); 14392 } 14393 14394 //----------------------------------------------------------------------------------------------------------------- 14395 14396 inline int txUpdateWindow (int update /*= true*/) 14397 { 14398 $1 return _txCanvas_SetRefreshLock (update >= 0? (int) !update : -update); 14399 } 14400 14401 //----------------------------------------------------------------------------------------------------------------- 14402 14403 inline int txBegin() 14404 { 14405 $1 _txCanvas_SetRefreshLock (_txCanvas_RefreshLock + 1); 14406 14407 $ return _txCanvas_RefreshLock; 14408 } 14409 14410 //----------------------------------------------------------------------------------------------------------------- 14411 14412 inline int txEnd() 14413 { 14414 $1 _txCanvas_SetRefreshLock (_txCanvas_RefreshLock - 1); 14415 14416 $ return _txCanvas_RefreshLock; 14417 } 14418 14419 //----------------------------------------------------------------------------------------------------------------- 14420 14421 inline POINT txMousePos() 14422 { 14423 $1 POINT pos = {}; 14424 $ GetCursorPos (&pos); 14425 14426 $ if (txWindow()) 14427 {$ ScreenToClient (txWindow(), &pos); } 14428 14429 $ return pos; 14430 } 14431 14432 //----------------------------------------------------------------------------------------------------------------- 14433 14434 inline double txMouseX() 14435 { 14436 return (double) txMousePos() .x; 14437 } 14438 14439 //----------------------------------------------------------------------------------------------------------------- 14440 14441 inline double txMouseY() 14442 { 14443 return (double) txMousePos() .y; 14444 } 14445 14446 //----------------------------------------------------------------------------------------------------------------- 14447 14448 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 14449 14450 unsigned txMouseButtons() 14451 { 14452 $1 HWND txWnd = txWindow(); 14453 $ HWND foreground = GetForegroundWindow(); 14454 14455 $ if ((txWnd && (foreground == txWnd)) || 14456 (!txWnd && (foreground == Win32::GetConsoleWindow()))) 14457 { 14458 $ return ((GetAsyncKeyState (VK_LBUTTON) & 0x8000) >> 15) | // MSB to bit 0 14459 ((GetAsyncKeyState (VK_RBUTTON) & 0x8000) >> 14) | // MSB to bit 1 14460 ((GetAsyncKeyState (VK_MBUTTON) & 0x8000) >> 13); // MSB to bit 2 14461 } 14462 else 14463 {$ return 0; } 14464 } 14465 14466 //----------------------------------------------------------------------------------------------------------------- 14467 14468 unsigned txSetConsoleAttr (unsigned color /*= FOREGROUND_LIGHTGRAY*/) 14469 { 14470 unsigned oldAttr = txGetConsoleAttr(); 14471 14472 SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), (WORD) color); 14473 SetConsoleTextAttribute (GetStdHandle (STD_ERROR_HANDLE), (WORD) color); 14474 14475 return oldAttr; 14476 } 14477 14478 //----------------------------------------------------------------------------------------------------------------- 14479 14480 unsigned txGetConsoleAttr() 14481 { 14482 CONSOLE_SCREEN_BUFFER_INFO con = {}; 14483 con.wAttributes = FOREGROUND_LIGHTGRAY; 14484 14485 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &con) || 14486 GetConsoleScreenBufferInfo (GetStdHandle (STD_ERROR_HANDLE), &con); 14487 14488 return con.wAttributes; 14489 } 14490 14491 //----------------------------------------------------------------------------------------------------------------- 14492 14493 POINT txSetConsoleCursorPos (double x, double y) 14494 { 14495 $1 POINT fontSz = txGetConsoleFontSize(); 14496 14497 $ CONSOLE_SCREEN_BUFFER_INFO con = {}; 14498 $ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &con) asserted; 14499 14500 $ COORD pos = { (short) ROUND (1.0 * x / fontSz.x + con.srWindow.Left), 14501 (short) ROUND (1.0 * y / fontSz.y + con.srWindow.Top ) }; 14502 14503 $ SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), pos) asserted; 14504 14505 $ POINT prev = { ROUND ((con.dwCursorPosition.X - con.srWindow.Left) * fontSz.x), 14506 ROUND ((con.dwCursorPosition.Y - con.srWindow.Top ) * fontSz.y) }; 14507 $ return prev; 14508 } 14509 14510 //----------------------------------------------------------------------------------------------------------------- 14511 14512 POINT txGetConsoleCursorPos() 14513 { 14514 $1 POINT fontSz = txGetConsoleFontSize(); 14515 14516 $ CONSOLE_SCREEN_BUFFER_INFO con = {}; 14517 $ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &con) asserted; 14518 14519 $ POINT pos = { ROUND ((con.dwCursorPosition.X - con.srWindow.Left) * fontSz.x), 14520 ROUND ((con.dwCursorPosition.Y - con.srWindow.Top ) * fontSz.y) }; 14521 $ return pos; 14522 } 14523 14524 //----------------------------------------------------------------------------------------------------------------- 14525 14526 POINT txGetConsoleExtent() 14527 { 14528 $1 CONSOLE_SCREEN_BUFFER_INFO con = {}; 14529 $ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &con) asserted; 14530 14531 $ POINT size = { con.srWindow.Right - con.srWindow.Left + 1, 14532 con.srWindow.Bottom - con.srWindow.Top + 1 }; 14533 $ return size; 14534 } 14535 14536 //----------------------------------------------------------------------------------------------------------------- 14537 14538 bool txClearConsole() 14539 { 14540 $1 HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE); 14541 14542 $ CONSOLE_SCREEN_BUFFER_INFO con = {}; 14543 $ GetConsoleScreenBufferInfo (out, &con) asserted; 14544 14545 $ COORD start = {con.srWindow.Left, con.srWindow.Top}; 14546 14547 $ DWORD len = (con.srWindow.Right - con.srWindow.Left + 1) * 14548 (con.srWindow.Bottom - con.srWindow.Top + 1); 14549 14550 $ DWORD written = 0; 14551 $ FillConsoleOutputCharacter (out, 0x20 /*' '*/, len, start, &written) asserted; //-V112 14552 $ FillConsoleOutputAttribute (out, con.wAttributes, len, start, &written) asserted; 14553 14554 $ SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), start) asserted; 14555 14556 $ return written == len; 14557 } 14558 14559 //----------------------------------------------------------------------------------------------------------------- 14560 14561 POINT txGetConsoleFontSize() 14562 { 14563 $1 Win32::CONSOLE_FONT_INFO font = {0, {8, 16}}; 14564 14565 $ _TX_CALL (Win32::GetCurrentConsoleFont, (GetStdHandle (STD_OUTPUT_HANDLE), false, &font)); 14566 14567 $ SIZE size = { font.dwFontSize.X, font.dwFontSize.Y }; 14568 if (_txCanvas_BackBuf[1]) {$ txGDI (Win32::GetTextExtentPoint32 (_txCanvas_BackBuf[1], "W", 1, &size), txDC()); } //-V501 14569 14570 if (size.cx == 0) {$ size.cx = 1; } 14571 if (size.cy == 0) {$ size.cy = 1; } 14572 14573 $ POINT sizeFont = { size.cx, size.cy }; 14574 $ return sizeFont; 14575 } 14576 14577 //----------------------------------------------------------------------------------------------------------------- 14578 14579 bool txTextCursor (bool blink /*= true*/) 14580 { 14581 $1 bool old = _txConsole_IsBlinking; 14582 14583 $ _txConsole_IsBlinking = blink; 14584 14585 $ return old; 14586 } 14587 14588 //----------------------------------------------------------------------------------------------------------------- 14589 14590 bool txPlaySound (const char filename[] /*= NULL*/, DWORD mode /*= SND_ASYNC*/) 14591 { 14592 $1 mode |= SND_FILENAME | SND_NODEFAULT | SND_NOWAIT; 14593 $ if (mode & SND_LOOP) mode = (mode & ~SND_SYNC) | SND_ASYNC; 14594 14595 $ if (!filename) mode = SND_PURGE; 14596 14597 $ return !!Win32::PlaySound (filename, NULL, mode); 14598 } 14599 14600 //----------------------------------------------------------------------------------------------------------------- 14601 14602 int txSpeak (const char* text, ...) 14603 { 14604 $1 bool verbose = false; (void) verbose; 14605 $ bool async = false; (void) async; 14606 14607 $ for (; text && *text; text++) 14608 { 14609 if (*text == '\a') {$ async = true; } 14610 else if (*text == '\v') {$ verbose = true; } 14611 else break; 14612 } 14613 14614 $ char textA [_TX_BUFSIZE] = "<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='EN'>" 14615 "You asked to speak empty text. I would rather say that TX Library is cool! Cats rules!" 14616 "</speak>"; 14617 14618 $ va_list arg; va_start (arg, text); 14619 if (text && *text) {$ _tx_vsnprintf_s (textA, sizeof (textA) - 1, text, arg); } 14620 $ va_end (arg); 14621 14622 if (text && verbose) {$ printf ("%s", textA); } 14623 14624 #ifdef TX_USE_SPEAK 14625 14626 $ int time = GetTickCount(); 14627 14628 $ static wchar_t textW [_TX_BUFSIZE * sizeof (wchar_t)] = L""; 14629 $ MultiByteToWideChar (_TX_CODEPAGE, 0, textA, -1, textW, sizearr (textW)); 14630 14631 $ static ISpVoice* voice = NULL; // This is bad rough approach. Due to this static, txSpeak() calls are restricted to one .cpp-file. 14632 14633 $ if (text && !voice) 14634 { 14635 $ HRESULT res = Win32::CoInitialize (NULL); 14636 if (res == S_OK) {$ Win32::CoCreateInstance (Win32::CLSID_SpVoice, NULL, CLSCTX_ALL, Win32::IID_ISpVoice, (void**) &voice); } 14637 } 14638 14639 $ if (text && voice) 14640 { 14641 $ Win32::_fpreset(); 14642 $ voice->Speak (textW, SPF_PERSIST_XML | SPF_PURGEBEFORESPEAK | ((*textW == '<')? SPF_IS_XML : 0) | (async? SPF_ASYNC : 0), NULL); 14643 $ tx_fpreset(); 14644 } 14645 14646 $ if (!text && voice) 14647 { 14648 $ voice->Release(); 14649 $ voice = NULL; 14650 14651 $ Win32::CoUninitialize(); 14652 } 14653 14654 $ return (voice)? GetTickCount() - time : -1; 14655 14656 #else 14657 14658 $ if (text) 14659 { 14660 $ unsigned oldAttr = txSetConsoleAttr (FOREGROUND_LIGHTRED | BACKGROUND_BLACK); 14661 14662 $ txNotifyIcon (NIIF_ERROR, "txSpeak(): Не могу произнести (нужен TX_USE_SPEAK, см. TXLib Help)", "\n" "%s", textA); 14663 14664 $ txSetConsoleAttr (oldAttr); 14665 } 14666 14667 $ return -1; 14668 14669 #endif 14670 } 14671 14672 //----------------------------------------------------------------------------------------------------------------- 14673 14674 intptr_t txPlayVideo (int x, int y, int width, int height, const char fileName[], 14675 double zoom /*= 0*/, double gain /*= 1*/, HWND wnd /*= txWindow()*/) 14676 { 14677 $1 if (wnd && wnd == txWindow() && _TX_TXWINDOW_FAILED()) return -1; 14678 14679 $ int time = GetTickCount(); //-V2551 14680 14681 $ static char processUID [64] = ""; 14682 if (!*processUID) 14683 { 14684 $ FILETIME startTime = {}, null = {}; 14685 $ GetProcessTimes (GetCurrentProcess(), &startTime, &null, &null, &null) asserted; 14686 $ _snprintf_s (processUID, sizeof (processUID) - 1, "TXLib[%08X%08X]::txPlayVideo", 14687 (unsigned) startTime.dwHighDateTime, (unsigned) startTime.dwLowDateTime) < (int) sizeof (processUID) asserted; 14688 } 14689 14690 $ if (!fileName) 14691 { 14692 $ _txTaskKill ("vlc.exe", processUID, 0); // Kill'em all, by command line pattern 14693 $ return 0; 14694 } 14695 14696 $ static const char* vlcPath = _txPlayVideo_FindVLC(); 14697 14698 $ if (!vlcPath || _access (vlcPath, 0) != 0) 14699 { 14700 $ static int once = false; //-V601 14701 14702 $ if (*fileName && !once++) 14703 {$ txOutputDebugPrintf ("\a" "Не найден видеопроигрыватель VideoLAN (vlc.exe). Cкачайте его с сайта VideoLAN.org " 14704 "и установите. Без установки VideoLAN видео воспроизводиться не будет :(\n\n" 14705 "--\n" "Всегда Ваша, функция " /* как бы */ "txPlayVideo()...\n" 14706 "P.S. См. мое описание в TXLib Help."); } 14707 $ return INT_MIN; //-V109 14708 } 14709 14710 $ bool async = false; 14711 if (*fileName == '\a') {$ async = true; fileName++; } 14712 14713 $ RECT rect = {}; 14714 if (wnd) {$ GetClientRect (wnd, &rect); } 14715 14716 if (!width) {$ width = rect.right; } 14717 if (!height) {$ height = rect.bottom; } 14718 14719 // Create a child window to hold the video stream 14720 14721 $ const char* errPos = "ВНЕЗАПНО"; 14722 14723 $ volatile HWND child = NULL; 14724 $ if (wnd && (wnd == txWindow())) 14725 { 14726 $ const char* wndClass = txRegisterClass ("txPlayVideo", _txPlayVideo_WndProc, 0, NULL_BRUSH, 1); 14727 14728 $ static int number = 1; 14729 $ CREATESTRUCT createData = { NULL, NULL, (HMENU) (size_t) number++, txWindow(), height, width, y, x, 14730 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, __func__, wndClass }; 14731 $ child = txCreateExtraWindow (createData); 14732 $ if (!child) 14733 { 14734 $ txNotifyIcon (NIIF_ERROR, "txPlayVideo() сообщает", "\n" "%s", 14735 strstr (_txError (NULL, 0, NULL, 0, "\f" "Не могу создать окно для видео :("), errPos)); 14736 $ return INT_MIN+3; //-V109 14737 } 14738 14739 $ BringWindowToTop (child); 14740 14741 $ wnd = child; 14742 } 14743 14744 // Build the command line 14745 14746 if (!zoom && !wnd) {$ zoom = 1; } 14747 14748 $ char sZoom [64] = "--autoscale"; 14749 if (zoom) {$ _snprintf_s (sZoom, sizeof (sZoom) - 1, "--no-autoscale --zoom=%.10g", zoom) < (int) sizeof (sZoom) asserted; } //-V550 14750 14751 $ static char cmd [MAX_PATH*2 + 1024] = ""; 14752 14753 $ _snprintf_s (cmd, sizeof (cmd) - 1, "\"%s\" \"%s\" vlc://quit" 14754 14755 " %s --gain=%.10g --drawable-hwnd=%p --video-title=\"%s\" --logfile=%s" 14756 14757 " --live-caching=500 --network-caching=500 --quiet-synchro --no-embedded-video --file-logging" 14758 14759 " --ignore-config --reset-config --no-one-instance --play-and-exit" 14760 " --intf=dummy --dummy-quiet --quiet --no-video-deco --no-video-title-show --no-stats --no-sub-autodetect-file" 14761 " --no-disable-screensaver --no-snapshot-preview --no-auto-preparse --no-mouse-events --no-keyboard-events", 14762 14763 vlcPath, (*fileName? fileName : "fileName"), sZoom, gain, (void*) wnd, processUID, _txLogName) < (int) sizeof (cmd) asserted; 14764 14765 $ txOutputDebugPrintf ("txPlayVideo (%d, %d, %d, %d, \"%s\", %g, %g, %p): [%s]\n\n", 14766 x, y, width, height, fileName, zoom, gain, (void*) wnd, cmd); 14767 $ if (!*fileName) 14768 { 14769 if (child) {$ txDestroyWindow (child); } 14770 $ return (intptr_t) cmd; 14771 } 14772 14773 $ if (!strstr (fileName, "://") && _access (fileName, 0) != 0) 14774 { 14775 $ txNotifyIcon (NIIF_ERROR, "txPlayVideo() сообщает", "\n" "%s", 14776 strstr (_txError (NULL, 0, NULL, 0, "\f" "Не найден файл \"%s\"", fileName), errPos)); 14777 14778 if (child) {$ txDestroyWindow (child); } 14779 $ return INT_MIN+1; //-V109 14780 } 14781 14782 // Run VLC, run 14783 14784 $ PROCESS_INFORMATION vlc = {}; 14785 $ STARTUPINFO start = { sizeof (start) }; 14786 $ DWORD ret = 0; 14787 14788 $ if (CreateProcess (NULL, cmd, NULL, NULL, true, 0, NULL, NULL, &start, &vlc) && 14789 vlc.hProcess && vlc.hThread) 14790 { 14791 $ if (child) 14792 { 14793 $ assert (wnd == child); //-V547 14794 $ SetWindowLongPtr (wnd, GWLP_USERDATA, (LONG_PTR) vlc.hProcess); //-V107 14795 } 14796 14797 $ if (!async) 14798 { 14799 $ WaitForSingleObject (vlc.hProcess, INFINITE); 14800 $ GetExitCodeProcess (vlc.hProcess, &ret) asserted; 14801 } 14802 14803 $ if (!child) 14804 { 14805 $ CloseHandle (vlc.hProcess) asserted; 14806 } 14807 14808 $ CloseHandle (vlc.hThread) asserted; 14809 14810 $ return (async? (intptr_t) wnd : (ret == 0)? time - GetTickCount() : - (int) ret); //-V105 14811 } 14812 else 14813 { 14814 $ txNotifyIcon (NIIF_ERROR, "txPlayVideo() сообщает", "%s", 14815 strstr (_txError (NULL, 0, NULL, 0, "\f" "Ошибка запуска VideoLAN (%s)", cmd), errPos)); 14816 $ if (child) 14817 {$ txDestroyWindow (child); } 14818 14819 $ return INT_MIN+4; //-V112 //-V109 14820 } 14821 14822 #undef PROCESS_UID_ 14823 } 14824 14825 //----------------------------------------------------------------------------------------------------------------- 14826 14827 intptr_t txPlayVideo (const char fileName[], double zoom /*= 0*/, double gain /*= 0*/, HWND wnd /*= txWindow()*/) 14828 { 14829 $1 return txPlayVideo (0, 0, 0, 0, fileName, zoom, gain, wnd); 14830 } 14831 14832 //----------------------------------------------------------------------------------------------------------------- 14833 14834 LRESULT CALLBACK _txPlayVideo_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar) 14835 { 14836 const UINT_PTR checkTimer = 1; 14837 14838 switch (msg) 14839 { 14840 case WM_CREATE: 14841 { 14842 $1 SetTimer (wnd, checkTimer, 5*_txWindowUpdateInterval, NULL) asserted; 14843 } 14844 break; 14845 14846 case WM_DESTROY: 14847 { 14848 $1 KillTimer (wnd, checkTimer) asserted; 14849 14850 $ HANDLE vlc = (HANDLE)(uintptr_t) GetWindowLongPtr (wnd, GWLP_USERDATA); 14851 14852 $ if (vlc) 14853 { 14854 $ Win32::TerminateProcess (vlc, 0); 14855 14856 $ CloseHandle (vlc) asserted; 14857 14858 $ SetWindowLongPtr (wnd, GWLP_USERDATA, 0); 14859 } 14860 } 14861 break; 14862 14863 case WM_TIMER: 14864 { 14865 HANDLE vlc = (HANDLE)(uintptr_t) GetWindowLongPtr (wnd, GWLP_USERDATA); 14866 14867 if (vlc && WaitForSingleObject (vlc, 0) != WAIT_TIMEOUT) 14868 { 14869 $1 DestroyWindow (wnd) asserted; 14870 } 14871 } 14872 break; 14873 14874 default: //-V2522 14875 break; 14876 } 14877 14878 return DefWindowProc (wnd, msg, wpar, lpar); 14879 } 14880 14881 //----------------------------------------------------------------------------------------------------------------- 14882 14883 const char* _txPlayVideo_FindVLC() 14884 { 14885 $1 static char vlcPath [MAX_PATH] = ""; 14886 14887 $ if (SearchPath (NULL, "vlc.bat", NULL, sizeof (vlcPath), vlcPath, NULL)) 14888 { 14889 if (_access (vlcPath, 0) == 0) {$ return vlcPath; } 14890 } 14891 14892 $ if (SearchPath (NULL, "vlc.exe", NULL, sizeof (vlcPath), vlcPath, NULL)) 14893 { 14894 if (_access (vlcPath, 0) == 0) {$ return vlcPath; } 14895 } 14896 14897 $ if (txRegQuery ("HKLM\\Software\\VideoLAN\\VLC", NULL, vlcPath, sizeof (vlcPath))) 14898 { 14899 if (_access (vlcPath, 0) == 0) {$ return vlcPath; } 14900 } 14901 14902 $ if (txRegQuery ("HKLM\\Software\\VideoLAN\\VLC", "InstallDir", vlcPath, sizeof (vlcPath))) 14903 { 14904 $ strncat_s (vlcPath, sizeof (vlcPath) - 1, "\\vlc.exe", INT_MAX); 14905 14906 if (_access (vlcPath, 0) == 0) {$ return vlcPath; } 14907 } 14908 14909 $ strncpy_s (vlcPath, sizeof (vlcPath), "C:\\Program Files" "\\VideoLAN\\VLC\\vlc.exe", UINT_MAX); //-V106 14910 { 14911 if (_access (vlcPath, 0) == 0) {$ return vlcPath; } 14912 } 14913 14914 $ strncpy_s (vlcPath, sizeof (vlcPath), "C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe", UINT_MAX); //-V106 14915 { 14916 if (_access (vlcPath, 0) == 0) {$ return vlcPath; } 14917 } 14918 14919 $ return NULL; 14920 } 14921 14922 //----------------------------------------------------------------------------------------------------------------- 14923 14924 HRESULT txSetProgress (double percent, unsigned type /*= TBPF_NORMAL*/, HWND wnd /*= NULL*/) 14925 { 14926 $1 static double oldPercent = 100; 14927 14928 if (percent < 0) {$ percent = MIN (oldPercent, 100); } 14929 else {$ oldPercent = percent; } 14930 14931 $ HRESULT res = S_FALSE; 14932 14933 #if defined (__ITaskbarList3_INTERFACE_DEFINED__) 14934 14935 $ HRESULT init = Win32::CoInitialize (NULL); 14936 14937 $ bool ok = true; 14938 $ res = S_OK; 14939 14940 $ ITaskbarList3* taskbar = NULL; 14941 if (ok) {$ res = Win32::CoCreateInstance (Win32::CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, Win32::IID_ITaskbarList3, (void**) &taskbar); } 14942 $ ok &= !!taskbar && (res == S_OK); 14943 14944 if (!wnd) {$ wnd = txWindow(); } 14945 if (ok && taskbar) {$ res = taskbar->SetProgressValue (wnd, ROUND (percent), 100); ok &= (res == S_OK); } 14946 if (ok && taskbar) {$ res = taskbar->SetProgressState (wnd, (TBPFLAG) type); ok &= (res == S_OK); } 14947 14948 if (wnd == txWindow()) {$ wnd = Win32::GetConsoleWindow(); } 14949 if (ok && taskbar) {$ res = taskbar->SetProgressValue (wnd, ROUND (percent), 100); ok &= (res == S_OK); } 14950 if (ok && taskbar) {$ res = taskbar->SetProgressState (wnd, (TBPFLAG) type); ok &= (res == S_OK); } 14951 14952 if (taskbar) {$ taskbar->Release(); } 14953 14954 if (init == S_OK) {$ Win32::CoUninitialize(); } 14955 14956 #endif 14957 14958 (void) type; (void) wnd; 14959 14960 $ return res; 14961 } 14962 14963 #endif // TX_COMPILED 14964 14965 //----------------------------------------------------------------------------------------------------------------- 14966 14967 // +--<<< Это не те символы, что вы ищете :) 14968 // V Полезно смотреть не только вверх, но и вниз 14969 14970 inline WNDPROC txSetWindowsHook (WNDPROC wndProc /*= NULL*/) 14971 { 14972 $1 WNDPROC old = _txAltWndProc; _txAltWndProc = wndProc; 14973 $ return old; 14974 } 14975 14976 //----------------------------------------------------------------------------------------------------------------- 14977 14978 // +--<<< А это, наконец, искомое определение этой функции. 14979 // | Смотрите по сторонам! Нужная вам функция где-то рядом. 14980 // | 14981 // v 14982 inline bool txIDontWantToHaveAPauseAfterMyProgramBeforeTheWindowWillClose_AndIWillNotBeAskingWhereIsMyPicture() 14983 { 14984 txMessageBox ("Это запланированная ошибка. Такое бывает. Вы хотели вызвать:\n\n" 14985 14986 "txIDontWantToHaveAPauseAfterMyProgramBeforeTheWindowWillClose_AndIWillNotBeAskingWhereIsMyPicture()\n\n" 14987 14988 "Хоть вы долго [копировали]набирали это имя, на самом деле эта функция не реализована. " 14989 "Есть другая функция, которая убирает авто-паузу в конце программы, но в хелпе про нее не написано.\n\n" 14990 14991 "Но не все так плохо. Определение нужной функции есть в исходных текстах TXLib.h, оно лежит рядом " 14992 "с определением той функции с длинным названием, которую вы сейчас вызвали.\n\n" 14993 14994 "Нажмите в редакторе Ctrl+O, найдите и откройте файл TXLib.h (он лежит в папке, куда вы " 14995 "установили TXLib), затем нажмите Ctrl+F и ищите \"txIDontWant\". Удачи!\n\n", 14996 14997 "Не получилось", MB_ICONSTOP); 14998 14999 // The truth is out there... (C++files) 15000 15001 return false; 15002 } 15003 15004 //----------------------------------------------------------------------------------------------------------------- 15005 15006 // Bingo! Now you are learned to use the Source, Luke. And may the Source be with you. 15007 15008 inline bool txDisableAutoPause() 15009 { 15010 _txExit = true; 15011 return true; 15012 } 15013 15014 // P.S. This library contains more undocumented functions. Search them via "Luke" keyword. 15015 15016 //----------------------------------------------------------------------------------------------------------------- 15017 15018 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 15019 15020 void _txDump (const void* address, const char name[] /*= "_txDump()"*/, bool pause /*= true*/) 15021 { 15022 $1 assert (!_txIsBadReadPtr (address)); 15023 15024 $ const unsigned char* addr = (const unsigned char*) address; 15025 15026 $ const int stdout_fileno = 1; // Not all g++ packages contain STDOUT_FILENO 15027 $ const int _o_u16text = 0x00020000; // and _O_U16TEXT 15028 15029 $ bool istty = _txIsTTY (1); 15030 15031 $ int mode = _O_TEXT; 15032 $ int oldMode = _setmode (stdout_fileno, mode); 15033 15034 $ unsigned oldCP = GetConsoleOutputCP(); 15035 $ unsigned cp = 1251; SetConsoleOutputCP (cp); //-V581 15036 15037 $ unsigned attr = txGetConsoleAttr(); 15038 15039 $ txSetConsoleAttr (FOREGROUND_WHITE); 15040 $ printf ("\n%*.*s ", (int) sizeof (address) * 2, (int) sizeof (address) * 2, ((name)? name : "")); 15041 15042 $ txSetConsoleAttr (FOREGROUND_YELLOW); 15043 $ for (unsigned x = 0; x < 16; x++) printf ("%02X ", x); 15044 $ for (unsigned x = 0; x < 16; x++) printf ("%X", x); 15045 15046 $ const wchar_t* xlat[33] = {L"\xB7" /* 00 - NUL - NULL */, L"\x263A" /* 01 - SOH - Start of header */, 15047 L"\x263B" /* 02 - STX - Start of text */, L"\x2665" /* 03 - ETX - End of text */, 15048 L"\x2666" /* 04 - EOT - End of transm. */, L"\x2663" /* 05 - ENQ - Enquiry */, 15049 L"\x2660" /* 06 - ACK - Acknowledgment */, L"\x2022" /* 07 - BEL - Bell */, 15050 L"\x25D8" /* 08 - BS - Backspace */, L"\x25CB" /* 09 - HT - Horizontal tab */, 15051 L"\x25D9" /* 10 - LF - Line feed */, L"\x2642" /* 11 - VT - Vertical tab */, 15052 L"\x2640" /* 12 - FF - Form feed */, L"\x266A" /* 13 - CR - Carriage return */, 15053 L"\x266B" /* 14 - SO - Shift out */, L"\x263C" /* 15 - SI - Shift in */, 15054 L"\x25BA" /* 16 - DLE - Data link escape */, L"\x25C4" /* 17 - DC1 - Device control 1 */, 15055 L"\x2195" /* 18 - DC2 - Device control 2 */, L"\x203C" /* 19 - DC3 - Device control 3 */, 15056 L"\xB6" /* 20 - DC4 - Device control 4 */, L"\xA7" /* 21 - NAK - Negative ACK */, 15057 L"\x25AC" /* 22 - SYN - Synchronous idle */, L"\x21A8" /* 23 - ETB - End of transm. block */, 15058 L"\x2191" /* 24 - CAN - Cancel */, L"\x2193" /* 25 - EM - End of medium */, 15059 L"\x2192" /* 26 - SUB - Substitute */, L"\x2190" /* 27 - ESC - Escape */, 15060 L"\x221F" /* 28 - FS - File separator */, L"\x2194" /* 29 - GS - Group separator */, 15061 L"\x25B2" /* 30 - RS - Record separator */, L"\x25BC" /* 31 - US - Unit separator */, 15062 L"\x20" /* 32 - Space */}; 15063 15064 $ for (int y = 0; y < 16; y++, addr += 16) 15065 { 15066 if (cp != 1251) SetConsoleOutputCP (cp = 1251); //-V581 15067 (void)_setmode (stdout_fileno, mode = oldMode); 15068 15069 txSetConsoleAttr (FOREGROUND_YELLOW); 15070 15071 printf ("\n" "%*p ", (int) sizeof (address) * 2, addr); 15072 15073 int color = FOREGROUND_LIGHTGREEN; 15074 15075 for (unsigned x = 0; x < 16; x++) 15076 { 15077 txSetConsoleAttr (color + x/4%2); //-V112 15078 printf ("%02X ", addr[x]); 15079 } 15080 15081 for (unsigned x = 0; x < 16; x++) 15082 { 15083 txSetConsoleAttr (color + x/4%2); //-V112 15084 15085 unsigned char ch = addr[x]; 15086 15087 if (ch >= sizearr (xlat) || !istty) 15088 { 15089 if (cp != oldCP) SetConsoleOutputCP (cp = oldCP); //-V581 15090 if (mode != oldMode) (void)_setmode (stdout_fileno, mode = oldMode); 15091 15092 printf ("%c", !strchr ("\t\r\n", ch)? ch : ' '); 15093 } 15094 else 15095 { 15096 if (cp != 1251) SetConsoleOutputCP (cp = 1251); //-V581 15097 if (mode != _o_u16text) (void)_setmode (stdout_fileno, mode = _o_u16text); 15098 15099 wprintf (L"%lls", xlat[ch]); 15100 } 15101 } 15102 } 15103 15104 $ (void)_setmode (stdout_fileno, oldMode); 15105 $ printf ("\n"); 15106 15107 $ if (pause && istty) 15108 { 15109 $ txSetConsoleAttr (FOREGROUND_DARKGRAY); 15110 $ txPause ("\v%-*s CodePage = %5u", (int) sizeof (void*) * 2 + 16*3, "[Нажмите любую клавишу для продолжения]", oldCP); 15111 } 15112 15113 $ txSetConsoleAttr (FOREGROUND_LIGHTGRAY); 15114 $ printf ("\n"); 15115 15116 $ txSetConsoleAttr (attr); 15117 $ SetConsoleOutputCP (oldCP); 15118 } 15119 15120 //----------------------------------------------------------------------------------------------------------------- 15121 15122 void _txStackBackTrace (const char file[] /*= "?"*/, int line /*= 0*/, const char func[] /*= "?"*/, 15123 bool readSource /*= true*/) 15124 { 15125 $1 unsigned attr = txGetConsoleAttr(); 15126 $ txSetConsoleAttr (FOREGROUND_LIGHTCYAN); 15127 15128 $ fprintf (stderr, "\n" "--------------------------------------------------\n" 15129 "Трассировка стека из \"%s\" at %s:%d:\n\n" 15130 "%s\n\n" 15131 "--------------------------------------------------\n\n", 15132 func, file, line, _txCaptureStackBackTrace (1, readSource)); 15133 15134 $ txSetConsoleAttr (attr); 15135 } 15136 15137 //----------------------------------------------------------------------------------------------------------------- 15138 15139 char* txDemangle (const char* mangledName, std::nomeow_t) 15140 { 15141 $1 if (!mangledName) return NULL; 15142 15143 $ char* typeName = NULL; 15144 15145 #if defined (_GCC_VER) 15146 15147 $ int err = 1; 15148 $ typeName = ::abi::__cxa_demangle (mangledName, 0, 0, &err); (void) err; 15149 if (typeName) {$ return typeName; } 15150 15151 #endif 15152 15153 $ unsigned short flags = 0; 15154 15155 $ if (mangledName[0] == '.') 15156 { 15157 $ mangledName++; 15158 $ flags = 0x2800; // UNDNAME_32_BIT_DECODE | UNDNAME_TYPE_ONLY 15159 } 15160 15161 $ typeName = _TX_CALL (Win32::__unDName, (NULL, mangledName, 0, malloc, free, flags)); 15162 if (typeName) {$ return typeName; } 15163 15164 $ return _strdup (mangledName); 15165 } 15166 15167 //----------------------------------------------------------------------------------------------------------------- 15168 15169 std::string txDemangle (const char* mangledName) 15170 { 15171 $1 char* typeName = txDemangle (mangledName, std::nomeow); 15172 $ std::string name (typeName? typeName : ""); 15173 $ free (typeName); 15174 15175 $ return name; 15176 } 15177 15178 //----------------------------------------------------------------------------------------------------------------- 15179 15180 double txQueryPerformance() 15181 { 15182 $1 int maxTime = 500; 15183 $ int maxSamples = 100; 15184 $ POINT size = {100, 100}; 15185 15186 $ HDC dc = _txBuffer_Create (txWindow(), &size, NULL); 15187 $ assert (dc); if (!dc) return -1; //-V547 15188 15189 $ DWORD mask = (DWORD) SetThreadAffinityMask (GetCurrentThread(), 1); //-V202 15190 $ assert (mask); 15191 15192 $ LARGE_INTEGER freq = {}; 15193 $ QueryPerformanceFrequency (&freq) asserted; 15194 15195 $ LARGE_INTEGER start = {}; 15196 $ QueryPerformanceCounter (&start) asserted; 15197 15198 $ int samples = 0; 15199 $ while (samples++ < maxSamples) 15200 { 15201 $ LARGE_INTEGER cur = {}; 15202 $ QueryPerformanceCounter (&cur) asserted; 15203 15204 $ double t = 1000.0 * (double) (cur.QuadPart - start.QuadPart) / (double) freq.QuadPart; 15205 $ if (t > maxTime) break; 15206 15207 // Draw test scene 15208 15209 $ for (int y = 0; y < size.y; y++) 15210 for (int x = 0; x < size.x; x++) txSetPixel (x, y, TX_BLACK, dc); 15211 15212 $ for (int y = 0; y < size.y; y += 10) 15213 for (int x = 0; x < size.x; x += 50) txTextOut (x, y, "*", dc); 15214 15215 $ txEllipse (0, 0, size.x, size.y, dc); 15216 $ txFloodFill (size.x/2.0, size.y/2.0, TX_TRANSPARENT, FLOODFILLSURFACE, dc); 15217 15218 $ txBitBlt (dc, size.x/2.0, 0, size.x/2.0, size.y/2.0, dc, 0, 0) asserted; 15219 $ txBitBlt (dc, size.x/2.0, size.y/2.0, size.x/2.0, size.y/2.0, dc, 0, size.y/2.0) asserted; 15220 $ txBitBlt (dc, 0, size.y/2.0, size.x/2.0, size.y/2.0, dc, 0, 0) asserted; 15221 $ txBitBlt (dc, size.x/2.0, size.y/2.0, size.x/2.0, size.y/2.0, dc, size.x/2.0, 0) asserted; 15222 } 15223 15224 $ mask = (DWORD) SetThreadAffinityMask (GetCurrentThread(), mask); //-V106 //-V202 15225 $ assert (mask); 15226 15227 $ _txBuffer_Delete (&dc); 15228 15229 $ return 3.0 * samples / sqrt (1.0 * size.x * size.y); 15230 } 15231 15232 //----------------------------------------------------------------------------------------------------------------- 15233 15234 unsigned txExtractColor (COLORREF color, COLORREF component) 15235 { 15236 $1 switch (component) 15237 { 15238 case TX_RED: 15239 case TX_HUE: 15240 case TX_LAB_L: $ return (color >> 0) & 0xFF; 15241 15242 case TX_GREEN: 15243 case TX_SATURATION: 15244 case TX_LAB_A: $ return (color >> 8) & 0xFF; 15245 15246 case TX_BLUE: 15247 case TX_LIGHTNESS: 15248 case TX_LAB_B: $ return (color >> 16) & 0xFF; 15249 15250 default: $ return CLR_INVALID; 15251 } 15252 } 15253 15254 //----------------------------------------------------------------------------------------------------------------- 15255 15256 template <typename T, typename T2, typename T3> 15257 inline T _txClamp (T val, T2 min, T3 max) 15258 { 15259 return (val < min)? min : (val > max)? max : val; 15260 } 15261 15262 inline COLORREF _txRGB (double r, double g, double b) 15263 { 15264 return RGB (_txClamp (ROUND (r), 0, 255), 15265 _txClamp (ROUND (g), 0, 255), 15266 _txClamp (ROUND (b), 0, 255)); 15267 } 15268 15269 //----------------------------------------------------------------------------------------------------------------- 15270 15271 COLORREF txRGB2HSL (COLORREF rgbColor) 15272 { 15273 $1 struct xRGB 15274 { 15275 static bool zero (double val) 15276 { 15277 const double prec = 0.001; 15278 15279 return (fabs (val) < prec); 15280 } 15281 }; 15282 15283 $ double r = txExtractColor (rgbColor, TX_RED) / 255.0, //-V2551 15284 g = txExtractColor (rgbColor, TX_GREEN) / 255.0, //-V2551 15285 b = txExtractColor (rgbColor, TX_BLUE) / 255.0, //-V2551 15286 15287 m1 = MAX (MAX (r, g), b), 15288 m2 = MIN (MIN (r, g), b), 15289 dm = m1 - m2, 15290 sm = m1 + m2, 15291 15292 h = 0, 15293 s = 0, 15294 l = sm / 2; 15295 15296 $ if (!xRGB::zero (dm)) 15297 { 15298 $ sm = (sm <= 1)? sm : (2-sm); 15299 $ s = (!xRGB::zero (sm))? dm/sm : 0; 15300 15301 $ double cr = (!xRGB::zero (dm))? (m1 - r) / dm : 0, 15302 cg = (!xRGB::zero (dm))? (m1 - g) / dm : 0, 15303 cb = (!xRGB::zero (dm))? (m1 - b) / dm : 0; 15304 15305 $ if (xRGB::zero (r - m1)) h = cb - cg; 15306 $ if (xRGB::zero (g - m1)) h = 2 + cr - cb; 15307 $ if (xRGB::zero (b - m1)) h = 4 + cg - cr; 15308 } 15309 15310 $ h = (h >= 0)? h*60 : h*60 + 360; 15311 15312 $ return _txRGB (h / 360.0 * 256, s * 255, l * 255); 15313 } 15314 15315 //----------------------------------------------------------------------------------------------------------------- 15316 15317 COLORREF txHSL2RGB (COLORREF hslColor) 15318 { 15319 $1 struct xRGB 15320 { 15321 static double calc (double h, double m1, double m2) 15322 { 15323 $2 while (h < 0) h += 360; 15324 $ while (h > 360) h -= 360; 15325 15326 $ return (h < 60)? m1 + (m2-m1) * h / 60 : 15327 (h < 180)? m2 : 15328 (h < 240)? m1 + (m2-m1) * (240-h) / 60 : 15329 m1; 15330 } 15331 }; 15332 15333 $ int si = txExtractColor (hslColor, TX_SATURATION); 15334 15335 $ double h = txExtractColor (hslColor, TX_HUE) / 256.0 * 360, 15336 s = txExtractColor (hslColor, TX_SATURATION) / 255.0, 15337 l = txExtractColor (hslColor, TX_LIGHTNESS) / 255.0, 15338 15339 m2 = (l <= 0.5)? l * (1 + s) : l + s - l * s, 15340 m1 = 2 * l - m2, 15341 15342 r = (si)? xRGB::calc (h + 120, m1, m2) : l, 15343 g = (si)? xRGB::calc (h, m1, m2) : l, 15344 b = (si)? xRGB::calc (h - 120, m1, m2) : l; 15345 15346 $ return _txRGB (r * 255, g * 255, b * 255); 15347 } 15348 15349 //----------------------------------------------------------------------------------------------------------------- 15350 15351 COLORREF txRGB2Lab (COLORREF rgbColor) 15352 { 15353 // Convert sRGB to XYZ referring to a D65/2 standard illuminant. See https://www.easyrgb.com/en/math.php 15354 15355 $1 double r = txExtractColor (rgbColor, TX_RED) / 255.0, 15356 g = txExtractColor (rgbColor, TX_GREEN) / 255.0, 15357 b = txExtractColor (rgbColor, TX_BLUE) / 255.0; 15358 15359 $ r = ((r > 0.04045)? pow ((r + 0.055) / 1.055, 2.4) : r / 12.92) * 100; 15360 $ g = ((g > 0.04045)? pow ((g + 0.055) / 1.055, 2.4) : g / 12.92) * 100; 15361 $ b = ((b > 0.04045)? pow ((b + 0.055) / 1.055, 2.4) : b / 12.92) * 100; 15362 15363 $ double x = r * 0.4124 + g * 0.3576 + b * 0.1805, 15364 y = r * 0.2126 + g * 0.7152 + b * 0.0722, 15365 z = r * 0.0193 + g * 0.1192 + b * 0.9505; 15366 15367 // Convert XYZ to Lab referring to a D65/2 standard illuminant. See https://www.easyrgb.com/en/math.php 15368 15369 $ x /= 95.047; 15370 $ y /= 100.000; 15371 $ z /= 108.883; 15372 15373 $ x = (x > 0.008856)? pow (x, 1.0/3.0) : 7.787 * x + 16.0/116.0; 15374 $ y = (y > 0.008856)? pow (y, 1.0/3.0) : 7.787 * y + 16.0/116.0; 15375 $ z = (z > 0.008856)? pow (z, 1.0/3.0) : 7.787 * z + 16.0/116.0; 15376 15377 $ double L = (116.0 * y) - 16.0, 15378 a = 500.0 * (x - y); 15379 b = 200.0 * (y - z); 15380 15381 // Storing Lab in range [0..255]: L = L * 2.55; a,b = (a,b + 100) * 1.275 15382 15383 $ return _txRGB (L / 100.0 * 255, 15384 (a + 100.0) / 200.0 * 255, 15385 (b + 100.0) / 200.0 * 255); 15386 } 15387 15388 //----------------------------------------------------------------------------------------------------------------- 15389 15390 COLORREF txLab2RGB (COLORREF labColor) 15391 { 15392 // Convert Lab to XYZ referring to a D65/2 standard illuminant. See https://www.easyrgb.com/en/math.php 15393 15394 $1 double L = txExtractColor (labColor, TX_LAB_L) / 255.0 * 100, 15395 a = txExtractColor (labColor, TX_LAB_A) / 255.0 * 200 - 100.0, 15396 b = txExtractColor (labColor, TX_LAB_B) / 255.0 * 200 - 100.0; 15397 15398 $ double y = (L + 16.0) / 116.0, 15399 x = y + a / 500.0, 15400 z = y - b / 200.0; 15401 15402 $ x = (x > pow (0.008856, 3))? x*x*x : (x - 16.0/116.0) / 7.787; 15403 $ y = (y > pow (0.008856, 3))? y*y*y : (y - 16.0/116.0) / 7.787; 15404 $ z = (z > pow (0.008856, 3))? z*z*z : (z - 16.0/116.0) / 7.787; 15405 15406 $ x *= 95.047; 15407 $ y *= 100.000; 15408 $ z *= 108.883; 15409 15410 // Convert XYZ to sRGB referring to a D65/2 standard illuminant. See https://www.easyrgb.com/en/math.php 15411 15412 $ x /= 100; 15413 $ y /= 100; 15414 $ z /= 100; 15415 15416 $ double r = x * 3.2406 + y * -1.5372 + z * -0.4986, 15417 g = x * -0.9689 + y * 1.8758 + z * 0.0415; 15418 $ b = x * 0.0557 + y * -0.2040 + z * 1.0570; 15419 15420 $ r = (r > 0.0031308)? 1.055 * pow (r, 1.0/2.4) - 0.055 : 12.92 * r; 15421 $ g = (g > 0.0031308)? 1.055 * pow (g, 1.0/2.4) - 0.055 : 12.92 * g; 15422 $ b = (b > 0.0031308)? 1.055 * pow (b, 1.0/2.4) - 0.055 : 12.92 * b; 15423 15424 $ return _txRGB (r * 255, g * 255, b * 255); 15425 } 15426 15427 //----------------------------------------------------------------------------------------------------------------- 15428 15429 double txDeltaE (COLORREF rgbColor1, COLORREF rgbColor2) 15430 { 15431 // deltaE CIE76. See https://www.easyrgb.com/en/math.php 15432 15433 $1 COLORREF Lab1 = txRGB2Lab (rgbColor1), 15434 Lab2 = txRGB2Lab (rgbColor2); 15435 15436 $ double L1 = txExtractColor (Lab1, TX_LAB_L) / 255.0 * 100, 15437 a1 = txExtractColor (Lab1, TX_LAB_A) / 255.0 * 200 - 100.0, 15438 b1 = txExtractColor (Lab1, TX_LAB_B) / 255.0 * 200 - 100.0; 15439 15440 $ double L2 = txExtractColor (Lab2, TX_LAB_L) / 255.0 * 100, 15441 a2 = txExtractColor (Lab2, TX_LAB_A) / 255.0 * 200 - 100.0, 15442 b2 = txExtractColor (Lab2, TX_LAB_B) / 255.0 * 200 - 100.0; 15443 15444 $ return sqrt ((L2-L1) * (L2-L1) + 15445 (a2-a1) * (a2-a1) + 15446 (b2-b1) * (b2-b1)); 15447 } 15448 15449 //----------------------------------------------------------------------------------------------------------------- 15450 15451 double txDeltaE94 (COLORREF rgbColor1, COLORREF rgbColor2) 15452 { 15453 // deltaE CIE94. See https://www.easyrgb.com/en/math.php 15454 15455 $1 COLORREF Lab1 = txRGB2Lab (rgbColor1), 15456 Lab2 = txRGB2Lab (rgbColor2); 15457 15458 $ double L1 = txExtractColor (Lab1, TX_LAB_L) / 255.0 * 100, 15459 a1 = txExtractColor (Lab1, TX_LAB_A) / 255.0 * 200 - 100.0, 15460 b1 = txExtractColor (Lab1, TX_LAB_B) / 255.0 * 200 - 100.0; 15461 15462 $ double L2 = txExtractColor (Lab2, TX_LAB_L) / 255.0 * 100, 15463 a2 = txExtractColor (Lab2, TX_LAB_A) / 255.0 * 200 - 100.0, 15464 b2 = txExtractColor (Lab2, TX_LAB_B) / 255.0 * 200 - 100.0; 15465 15466 $ double c1 = hypot (a1, b1), 15467 c2 = hypot (a2, b2), 15468 15469 dL = L2 - L1, 15470 dc = c2 - c1, 15471 dE = sqrt (((L1 - L2) * (L1 - L2)) + 15472 ((a1 - a2) * (a1 - a2)) + 15473 ((b1 - b2) * (b1 - b2))), 15474 15475 dh = dE*dE - dL*dL - dc*dc; 15476 $ dh = (dh > 0)? sqrt (dh) : 0; 15477 15478 dc /= (1 + (0.045 * c1)), 15479 dh /= (1 + (0.015 * c1)); 15480 15481 $ return sqrt (dL*dL + dc*dc + dh*dh); 15482 } 15483 15484 //----------------------------------------------------------------------------------------------------------------- 15485 15486 uint64_t txHash (const void* buffer, size_t size) 15487 { 15488 // DJB2 algorithm, https://en.wikipedia.org/wiki/Daniel_J._Bernstein 15489 15490 $9 uint64_t hash = 5381; 15491 15492 $ for (size_t i = 0; i < size; i++) 15493 hash = hash * 33 ^ ((const char*) buffer) [i]; 15494 15495 $ return hash; 15496 } 15497 15498 //----------------------------------------------------------------------------------------------------------------- 15499 15500 void tx_fpreset() 15501 { 15502 $1 txAutoLock _lock; 15503 15504 $ Win32::_fpreset(); 15505 15506 $ unsigned new87 = 0x0008001C; // _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW 15507 15508 #if !defined (__CYGWIN__) 15509 15510 $ unsigned old87 = 0; 15511 $ if (_controlfp_s (&old87, 0, 0) == 0) 15512 {$ (void) _controlfp_s (&old87, old87 & ~new87, 0x0008001F); } // _MCW_EM 15513 15514 #else 15515 15516 $ Win32::_controlfp (Win32::_controlfp (0, 0) & ~new87, 0x0008001F); // _MCW_EM 15517 15518 #endif 15519 } 15520 15521 #endif // TX_COMPILED 15522 15523 //----------------------------------------------------------------------------------------------------------------- 15524 15525 #if defined (_TX_CPP11) 15526 template <int txFramesToAverage> 15527 #endif 15528 15529 double txGetFPS (int minFrames) 15530 { 15531 $1 static _tx_thread LARGE_INTEGER time0 = {}; if (!time0.QuadPart) QueryPerformanceCounter (&time0); 15532 $ LARGE_INTEGER time = {}; QueryPerformanceCounter (&time); 15533 15534 $ if (time.QuadPart - time0.QuadPart == 0) 15535 {$ return 0; } 15536 15537 $ LARGE_INTEGER freq = {}; QueryPerformanceFrequency (&freq); 15538 15539 $ double fps = (double) freq.QuadPart / (double) (time.QuadPart - time0.QuadPart); 15540 $ time0 = time; 15541 15542 $ if (txFramesToAverage == 0) return fps; 15543 15544 $ static _tx_thread double average [txFramesToAverage] = {}; 15545 $ static _tx_thread unsigned n = 0; 15546 15547 $ average [n++ % txFramesToAverage] = fps; 15548 15549 $ unsigned nn = MIN (n, (unsigned) sizearr (average)); 15550 15551 $ fps = 0; 15552 $ for (unsigned i = 0; i < nn; i++) fps += average[i]; 15553 $ fps /= nn; 15554 15555 $ return ((int)n >= MIN (minFrames, txFramesToAverage))? fps : 0; 15556 } 15557 15558 //----------------------------------------------------------------------------------------------------------------- 15559 15560 template <typename T> 15561 inline T zero() { T __zero = {}; return __zero; } 15562 15563 //----------------------------------------------------------------------------------------------------------------- 15564 15565 inline double random (std::nomeow_t, double left, double right) 15566 { 15567 return left + (right - left) * ((double) rand() / RAND_MAX); 15568 } 15569 15570 //----------------------------------------------------------------------------------------------------------------- 15571 15572 template <typename Tx, typename Ta, typename Tb> 15573 inline bool In (std::nomeow_t, Tx x, Ta a, Tb b) 15574 { 15575 return a <= x && x <= b; 15576 } 15577 15578 //----------------------------------------------------------------------------------------------------------------- 15579 15580 inline bool In (std::nomeow_t, const POINT& pt, const RECT& rect) 15581 { 15582 if (_TX_ARGUMENT_FAILED (&pt)) return false; 15583 if (_TX_ARGUMENT_FAILED (&rect)) return false; 15584 15585 return In (std::nomeow, pt.x, rect.left, rect.right) && 15586 In (std::nomeow, pt.y, rect.top, rect.bottom); 15587 } 15588 15589 //----------------------------------------------------------------------------------------------------------------- 15590 15591 inline bool In (std::nomeow_t, const COORD& pt, const SMALL_RECT& rect) 15592 { 15593 if (_TX_ARGUMENT_FAILED (&pt)) return false; 15594 if (_TX_ARGUMENT_FAILED (&rect)) return false; 15595 15596 return In (std::nomeow, pt.X, rect.Left, rect.Right) && 15597 In (std::nomeow, pt.Y, rect.Top, rect.Bottom); 15598 } 15599 15600 //----------------------------------------------------------------------------------------------------------------- 15601 15602 inline int random (int range) 15603 { 15604 if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206 15605 15606 return rand() % range; 15607 } 15608 15609 //----------------------------------------------------------------------------------------------------------------- 15610 15611 inline double random (double left, double right) 15612 { 15613 if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206 15614 15615 return random (std::nomeow, left, right); 15616 } 15617 15618 //----------------------------------------------------------------------------------------------------------------- 15619 15620 template <typename Tx, typename Ta, typename Tb> 15621 inline bool In (Tx x, Ta a, Tb b) 15622 { 15623 if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206 15624 15625 return In (std::nomeow, x, a, b); 15626 } 15627 15628 //----------------------------------------------------------------------------------------------------------------- 15629 15630 inline bool In (const POINT& pt, const RECT& rect) 15631 { 15632 if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206 15633 15634 return In (std::nomeow, pt, rect); 15635 } 15636 15637 //----------------------------------------------------------------------------------------------------------------- 15638 15639 inline bool In (const COORD& pt, const SMALL_RECT& rect) 15640 { 15641 if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206 15642 15643 return In (std::nomeow, pt, rect); 15644 } 15645 15646 //} 15647 //================================================================================================================= 15648 15649 //================================================================================================================= 15650 //{ txPrintf() implementation 15651 // Реализация txPrintf() 15652 //================================================================================================================= 15653 15654 #if defined (_TX_CPP11) 15655 15656 template <typename T, typename... ArgsT> void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, const T& arg, ArgsT... args); 15657 template <typename T, typename... ArgsT> void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, width_t width, const T& arg, ArgsT... args); 15658 template <typename T, typename... ArgsT> void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, precision_t prec, const T& arg, ArgsT... args); 15659 template <typename T, typename... ArgsT> void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, width_t width, precision_t prec, const T& arg, ArgsT... args); 15660 void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt); 15661 15662 template <typename T> void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt, const T& arg); 15663 void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt, int* arg); 15664 void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt); 15665 15666 //----------------------------------------------------------------------------------------------------------------- 15667 15668 template <typename T, typename... ArgsT> 15669 void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, const T& arg, ArgsT... args) 15670 { 15671 $1 assert (fmt); 15672 15673 $ _txPrintV (stream, format, n, fmt); 15674 15675 if (fmt[0] == '%') {$} 15676 else {$ TX_ERROR ("\"%%$\" required to print an argument in ...\"%s\" while printing %s argument %d in \"%s\"", fmt, txTypename (arg), n, format); } 15677 15678 $ _txPrintV (stream, format, n, fmt, arg); 15679 15680 $ _txPrintF (stream, format, n+1, fmt, args...); 15681 } 15682 15683 //----------------------------------------------------------------------------------------------------------------- 15684 15685 template <typename T, typename... ArgsT> 15686 void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, width_t width, const T& arg, ArgsT... args) 15687 { 15688 $1 assert (&stream); 15689 $ assert (fmt); 15690 15691 $ _txPrintV (stream, format, n, fmt); 15692 15693 if (fmt[0] == '%' && fmt[1] == '*') {$ stream << std::setw (width); } //-V2006 15694 else {$ TX_ERROR ("\"%%*\" required to setwidth (%d) in ...\"%s\" while printing %s argument %d in \"%s\"", width, fmt, txTypename (arg), n, format); } 15695 15696 $ _txPrintV (stream, format, n, fmt, arg); 15697 15698 $ _txPrintF (stream, format, n+1, fmt, args...); 15699 } 15700 15701 //----------------------------------------------------------------------------------------------------------------- 15702 15703 template <typename T, typename... ArgsT> 15704 void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, precision_t prec, const T& arg, ArgsT... args) 15705 { 15706 $1 assert (&stream); 15707 $ assert (fmt); 15708 15709 $ _txPrintV (stream, format, n, fmt); 15710 15711 if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '*') {$ stream << std::setprecision ((int) (prec + 1)); } //-V2006 //-V1028 15712 else {$ TX_ERROR ("\"%%.*\" required to setprecision (%d) in ...\"%s\" while printing %s argument %d in \"%s\"", prec, fmt, txTypename (arg), n, format); } 15713 15714 $ _txPrintV (stream, format, n, fmt, arg); 15715 15716 $ _txPrintF (stream, format, n+1, fmt, args...); 15717 } 15718 15719 //----------------------------------------------------------------------------------------------------------------- 15720 15721 template <typename T, typename... ArgsT> 15722 void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, width_t width, precision_t prec, const T& arg, ArgsT... args) 15723 { 15724 $1 assert (&stream); 15725 $ assert (fmt); 15726 15727 $ _txPrintV (stream, format, n, fmt); 15728 15729 if (fmt[0] == '%' && fmt[1] == '*' && fmt[2] == '.' && fmt[3] == '*') {$ stream << std::setw (width) << std::setprecision ((int) (prec + 1)); } //-V2006 //-V1028 15730 else {$ TX_ERROR ("\"%%*.*\" required to setwidth (%d) and setprecision (%d) in ...\"%s\" while printing %s argument %d in \"%s\"", width, prec, fmt, txTypename (arg), n, format); } 15731 15732 $ _txPrintV (stream, format, n, fmt, arg); 15733 15734 $ _txPrintF (stream, format, n+1, fmt, args...); 15735 } 15736 15737 //----------------------------------------------------------------------------------------------------------------- 15738 15739 inline void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt) 15740 { 15741 $1 assert (fmt); 15742 15743 $ _txPrintV (stream, format, n, fmt); 15744 15745 if (!fmt[0]) {$} 15746 else {$ TX_ERROR ("No argument provided for %% in \"%s\" while printing \"%s\"", fmt, format); } 15747 } 15748 15749 //----------------------------------------------------------------------------------------------------------------- 15750 15751 inline void _txPrintV (std::ostringstream& stream, const char*, int, const char*& fmt) 15752 { 15753 $1 assert (&stream); 15754 $ assert (fmt); 15755 15756 $ while (*fmt) 15757 { 15758 if (fmt[0] == '%') 15759 { 15760 if (fmt[1] == '%') fmt++; 15761 else break; 15762 } 15763 15764 stream << *fmt++; 15765 } 15766 $ } 15767 15768 //----------------------------------------------------------------------------------------------------------------- 15769 15770 template <typename T> 15771 void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt, const T& arg) 15772 { 15773 $1 assert (&stream); 15774 $ assert (fmt); 15775 15776 $ if (_TX_ARGUMENT_FAILED (&arg)) return; 15777 15778 if (fmt[0] == '%') {$} 15779 else {$ TX_ERROR ("\"%%$\" required to print an argument in ...\"%s\" while printing %s argument %d in \"%s\"", fmt, txTypename (arg), n, format); } 15780 15781 $ fmt++; 15782 15783 $ char oldFill = stream.fill (' '); 15784 $ std::ios_base::fmtflags oldFlags = stream.flags(); 15785 15786 $ for (;;) switch (*fmt) 15787 { 15788 case '-': $ stream << std::left; fmt++; break; 15789 case '+': $ stream << std::showpos; fmt++; break; 15790 case ' ': $ stream.fill (' '); fmt++; break; 15791 case '#': $ stream << std::showbase; fmt++; break; 15792 case '0': $ stream.fill ('0'); fmt++; break; 15793 15794 default: $ goto end; 15795 } 15796 end: 15797 15798 $ int width = (*fmt != '*')? (int) strtoul (fmt, const_cast <char**> (&fmt), 10) : (fmt++, 0); 15799 $ int prec = (*fmt == '.')? (*++fmt != '*')? (int) strtoul (fmt, const_cast <char**> (&fmt), 10) : (fmt++, 0) : 0; 15800 15801 if (width) {$ stream << std::setw (width); } 15802 if (prec) {$ stream << std::setprecision (prec); } 15803 15804 $ fmt += strspn (fmt, "hljztL"); 15805 15806 $ switch (*fmt) 15807 { 15808 case '$': 15809 case '?': $ break; 15810 15811 case 'd': 15812 case 'i': 15813 case 'u': $ stream << std::dec; break; 15814 15815 case 'o': $ stream << std::oct; break; 15816 15817 case 'x': $ stream << std::hex; break; 15818 case 'X': $ stream << std::hex << std::uppercase; break; 15819 15820 case 'f': $ stream << std::fixed; break; 15821 case 'F': $ stream << std::fixed << std::uppercase; break; 15822 15823 case 'e': $ stream << std::scientific; break; 15824 case 'E': $ stream << std::scientific << std::uppercase; break; 15825 15826 case 'g': $ break; 15827 case 'G': $ stream << std::uppercase; break; 15828 15829 case 'a': $ break; 15830 case 'A': $ stream << std::uppercase; break; 15831 15832 case 'c': 15833 case 's': 15834 case 'p': $ break; 15835 15836 default: $ TX_ERROR ("Invalid format '%.1s' at \"%s\" while printing %s argument %d in \"%s\"", fmt, fmt, txTypename (arg), n, format); break; 15837 } 15838 15839 $ fmt++; 15840 15841 if (&arg) {$ stream << arg; } 15842 else {$ stream << "(null)"; } 15843 15844 $ stream.fill (oldFill); 15845 $ stream.flags (oldFlags); 15846 } 15847 15848 //----------------------------------------------------------------------------------------------------------------- 15849 15850 inline void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt, int* arg) //-V2009 15851 { 15852 $1 assert (fmt); 15853 15854 if (_TX_ARGUMENT_FAILED (arg)) return; 15855 15856 if (fmt[0] == '%' && fmt[1] == 'n') {$} 15857 else {$ TX_ERROR ("\"%%n\" required to store print length in int* argument %d in \"%s\"", n, format); } 15858 15859 $ *arg = (int) stream.str().length(); //-V202 15860 15861 $ fmt += 2; 15862 } 15863 15864 //----------------------------------------------------------------------------------------------------------------- 15865 15866 template <typename T> inline const T& _txPrintfNormalizeArg (const T& arg) { if (_TX_ARGUMENT_FAILED (&arg)) {;} return arg; } 15867 inline const char* _txPrintfNormalizeArg (const std::string& arg) { if (_TX_ARGUMENT_FAILED (&arg)) return NULL; return arg.c_str(); } 15868 15869 //----------------------------------------------------------------------------------------------------------------- 15870 15871 template <typename... ArgsT> 15872 inline int txPrintf (std::ostringstream& stream, const char* format, ArgsT... args) 15873 { 15874 $1 if (_TX_ARGUMENT_FAILED (&stream)) return 0; 15875 $ if (_TX_ARGUMENT_FAILED (&format)) return 0; 15876 15877 $ const char* fmt = format; 15878 $ _txPrintF (stream, format, 2, fmt, _txPrintfNormalizeArg (args)...); 15879 15880 $ return (int) stream.str().length(); //-V202 15881 } 15882 15883 //----------------------------------------------------------------------------------------------------------------- 15884 15885 template <typename... ArgsT> 15886 inline int txPrintf (char buffer[], size_t size, const char* format, ArgsT... args) 15887 { 15888 $1 if (_TX_ARGUMENT_FAILED (&buffer)) return 0; 15889 $ if (_TX_ARGUMENT_FAILED (&format)) return 0; 15890 15891 $ if (size > 0) size--; 15892 $ buffer[size] = 0; 15893 15894 $ if (!size) return 0; 15895 15896 $ std::ostringstream stream; 15897 $ stream.rdbuf() -> pubsetbuf (buffer, size); 15898 15899 $ txPrintf (stream, format, args...); 15900 15901 $ return (int) stream.str().length(); //-V202 15902 } 15903 15904 //----------------------------------------------------------------------------------------------------------------- 15905 15906 template <typename... ArgsT> 15907 inline std::string txFormat (const char* format, ArgsT... args) 15908 { 15909 $1 if (_TX_ARGUMENT_FAILED (&format)) return ""; 15910 15911 $ std::ostringstream stream; 15912 15913 $ txPrintf (stream, format, args...); 15914 15915 $ return stream.str(); 15916 } 15917 15918 //----------------------------------------------------------------------------------------------------------------- 15919 15920 template <typename... ArgsT> 15921 inline int txPrintf (const char* format, ArgsT... args) 15922 { 15923 $1 if (_TX_ARGUMENT_FAILED (&format)) return 0; 15924 15925 $ return printf ("%s", txFormat (format, args...) .c_str()); 15926 } 15927 15928 #endif 15929 15930 //----------------------------------------------------------------------------------------------------------------- 15931 15932 int _txPrintfCheck (const char* format, ...) tx_printfy (1); 15933 inline int _txPrintfCheck (const char*, ...) { return 0; } 15934 15935 //} 15936 //================================================================================================================= 15937 15938 //================================================================================================================= 15939 //{ txDialog methods implementation 15940 // Реализация методов класса txDialog 15941 // 15942 // See [1] http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms645389%28v=vs.85%29.aspx 15943 // [2] http://blogs.msdn.microsoft.com/oldnewthing/20050429-00/?p=35743 15944 // [3] http://blogs.msdn.microsoft.com/oldnewthing/20040623-00/?p=38753 15945 //================================================================================================================= 15946 15947 #ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<< 15948 15949 txDialog::txDialog () : 15950 layout_ (NULL) 15951 {$1} 15952 15953 //----------------------------------------------------------------------------------------------------------------- 15954 15955 txDialog::txDialog (const Layout* layout) : 15956 layout_ (layout) 15957 {$1} 15958 15959 //----------------------------------------------------------------------------------------------------------------- 15960 15961 const txDialog::Layout* txDialog::setLayout (const Layout* layout) 15962 { 15963 $1 assert (layout); 15964 15965 $ return ::std::swap (layout_, layout), layout; 15966 } 15967 15968 //----------------------------------------------------------------------------------------------------------------- 15969 15970 intptr_t txDialog::dialogBox (WORD resourceID) 15971 { 15972 $1 const char* resName = (char*)(uintptr_t) resourceID; 15973 15974 $ if (!FindResource (NULL, resName, RT_DIALOG)) return TX_DEBUG_ERROR ("Не найден ресурс диалога %d", resourceID), 0; 15975 15976 $ return DialogBoxParam (NULL, resName, NULL, (DLGPROC) DialogProc_, (LPARAM) this); 15977 } 15978 15979 //----------------------------------------------------------------------------------------------------------------- 15980 15981 intptr_t txDialog::dialogBox (const txDialog::Layout* layout /*= NULL*/, size_t bufsize /*= 0*/) 15982 { 15983 $1 if (!layout) layout = layout_; 15984 $ if (!layout) return TX_DEBUG_ERROR ("Не установлен динамический шаблон диалога"), 0; 15985 15986 $ if (!bufsize) bufsize = 1024; 15987 15988 $ DLGTEMPLATE* tmpl = (DLGTEMPLATE*) GlobalAlloc (GPTR, bufsize); 15989 $ if (!tmpl) return TX_DEBUG_ERROR ("GlobalAlloc(): Нет памяти для шаблона диалога"), 0; 15990 15991 $ const Layout* dlg = &layout[0]; 15992 $ const Layout def = { DIALOG, NULL, 0, 0,0,0,0, WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_CENTER, "MS Shell Dlg", 8 }; 15993 15994 $ void* ptr = _tx_DLGTEMPLATE_Create (tmpl, bufsize, 15995 (dlg->style? dlg->style : def.style) | DS_SETFONT, 0, 0, 15996 dlg->x, dlg->y, dlg->sx, dlg->sy, 15997 dlg->caption? dlg->caption : def.caption, 15998 dlg->font? dlg->font : def.font, 15999 dlg->fontsize? dlg->fontsize : def.fontsize, NULL); 16000 $ WORD i = 0; 16001 $ for (i = 1; layout[i].wndclass != END; ++i) 16002 { 16003 $ const Layout* item = &layout[i]; 16004 16005 $ ptr = _tx_DLGTEMPLATE_Add (ptr, bufsize - ((char*)ptr - (char*)tmpl), 16006 item->style | WS_VISIBLE, 0, item->x, item->y, item->sx, item->sy, 16007 item->id, (const char*)(uintptr_t) item->wndclass, item->caption); 16008 } 16009 16010 $ tmpl->cdit = (unsigned short) (i-1); 16011 16012 $ intptr_t res = DialogBoxIndirectParam (NULL, tmpl, NULL, (DLGPROC) DialogProc_, (LPARAM) this); 16013 16014 $ GlobalFree (tmpl); 16015 16016 $ return res; 16017 } 16018 16019 //----------------------------------------------------------------------------------------------------------------- 16020 16021 int txDialog::dialogProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM) 16022 { 16023 $1 switch (msg) 16024 { 16025 case WM_INITDIALOG: $ SetForegroundWindow (wnd); 16026 $ break; 16027 16028 case WM_COMMAND: $ switch (LOWORD (wParam)) 16029 { 16030 case IDOK: 16031 case IDCANCEL: $ SetForegroundWindow (txWindow()? txWindow() : Win32::GetConsoleWindow()); 16032 $ EndDialog (wnd, (uintptr_t) this); 16033 $ break; 16034 16035 default: $ break; 16036 } 16037 $ break; 16038 default: $ break; 16039 } 16040 16041 $ return FALSE; 16042 } 16043 16044 //----------------------------------------------------------------------------------------------------------------- 16045 16046 intptr_t CALLBACK txDialog::DialogProc_ (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) 16047 { 16048 $1 static txDialog* this__ = NULL; 16049 $ if (msg == WM_INITDIALOG) this__ = (txDialog*) lParam; 16050 $ if (!this__) return FALSE; 16051 16052 $ return this__-> dialogProc (wnd, msg, wParam, lParam); //-V109 16053 } 16054 16055 //----------------------------------------------------------------------------------------------------------------- 16056 16057 void* _tx_DLGTEMPLATE_Create (void* globalMem, size_t bufsize, DWORD style, DWORD exStyle, 16058 WORD controls, short x, short y, short cx, short cy, 16059 const char caption[], const char font[], WORD fontsize, const char menu[]) 16060 { 16061 $1 if (_TX_ARGUMENT_FAILED (globalMem)) return NULL; 16062 16063 $ WORD* pw = (WORD*) globalMem; 16064 16065 $ DLGTEMPLATE* tmpl = ((DLGTEMPLATE*&) pw)++; 16066 16067 $ tmpl->style = style; 16068 $ tmpl->dwExtendedStyle = exStyle; 16069 $ tmpl->cdit = controls; 16070 $ tmpl->x = x; 16071 $ tmpl->y = y; 16072 $ tmpl->cx = cx; 16073 $ tmpl->cy = cy; 16074 16075 $ if (menu > (const char*) 0xFFFF) 16076 { 16077 $ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, (menu? menu : ""), -1, (wchar_t*) pw, //-V547 16078 (int) (bufsize? bufsize - ((char*) pw - (char*) globalMem) : 0xFFFF)); //-V202 16079 } 16080 else 16081 { 16082 $ *pw++ = (WORD)(uintptr_t) (menu? 0xFFFF : 0); 16083 $ *pw++ = (WORD)(uintptr_t) menu; 16084 } 16085 16086 $ if (caption) 16087 { 16088 $ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, (caption? caption : ""), -1, (wchar_t*) pw, //-V547 16089 (int) (bufsize? bufsize - ((char*) pw - (char*) globalMem) : 0xFFFF)); //-V202 16090 } 16091 16092 $ if (style & DS_SETFONT) 16093 { 16094 $ *pw++ = fontsize; 16095 $ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, (font? font : ""), -1, (wchar_t*) pw, 16096 (int) (bufsize? bufsize - ((char*) pw - (char*) globalMem) : 0xFFFF)); //-V202 16097 } 16098 16099 $ return pw; 16100 } 16101 16102 //----------------------------------------------------------------------------------------------------------------- 16103 16104 void* _tx_DLGTEMPLATE_Add (void* dlgTemplatePtr, size_t bufsize, DWORD style, DWORD exStyle, 16105 short x, short y, short cx, short cy, 16106 WORD id, const char wclass[], const char caption[]) 16107 { 16108 $1 if (_TX_ARGUMENT_FAILED (dlgTemplatePtr)) return NULL; 16109 16110 $ WORD* pw = (LPWORD) dlgTemplatePtr; // Force align at word boundary 16111 $ ((ULONG&) pw) += 3; //-V205 16112 $ ((ULONG&) pw) >>= 2; //-V205 16113 $ ((ULONG&) pw) <<= 2; //-V205 16114 16115 $ DLGITEMTEMPLATE* tmpl = ((DLGITEMTEMPLATE*&) pw)++; 16116 16117 $ tmpl->style = style; 16118 $ tmpl->dwExtendedStyle = exStyle; 16119 $ tmpl->x = x; 16120 $ tmpl->y = y; 16121 $ tmpl->cx = cx; 16122 $ tmpl->cy = cy; 16123 $ tmpl->id = id; 16124 16125 $ if (HIWORD (wclass) == 0xFFFF) 16126 { 16127 $ *pw++ = (WORD) (HIWORD ((uintptr_t) wclass)); 16128 $ *pw++ = (WORD) (LOWORD ((uintptr_t) wclass)); 16129 } 16130 else if (wclass) 16131 { 16132 $ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, const_cast <char*> (wclass), -1, (wchar_t*) pw, 16133 (int) (bufsize? bufsize - ((char*) pw - (char*) dlgTemplatePtr) : 0xFFFF)); //-V202 16134 } 16135 else 16136 { 16137 $ *pw++ = 0; 16138 } 16139 16140 $ if (caption) 16141 { 16142 $ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, caption, -1, (wchar_t*) pw, 16143 (int) (bufsize? bufsize - ((char*) pw - (char*) dlgTemplatePtr) : 0xFFFF)); //-V202 16144 } 16145 else 16146 { 16147 $ *pw++ = 0; 16148 } 16149 16150 $ *pw++ = 0; 16151 16152 $ return pw; 16153 } 16154 16155 #endif // TX_COMPILED 16156 16157 //} 16158 //================================================================================================================= 16159 16160 //================================================================================================================= 16161 //{ Cleaning up the utility macros 16162 // Очистка служебных макросов 16163 //================================================================================================================= 16164 16165 #undef $ 16166 #undef $0 16167 #undef $1 16168 #undef $2 16169 #undef $3 16170 #undef $4 16171 #undef $5 16172 #undef $6 16173 #undef $7 16174 #undef $8 16175 #undef $9 16176 #undef $$ 16177 16178 //} 16179 //================================================================================================================= 16180 16182 16183 //================================================================================================================= 16184 //{ Experimental Debugging macros 16186 //================================================================================================================= 16187 16188 //{---------------------------------------------------------------------------------------------------------------- 16311 //}---------------------------------------------------------------------------------------------------------------- 16312 16313 #ifndef __TX_DEBUG_MACROS 16314 #define __TX_DEBUG_MACROS ("Группа отладочных $-макросов") 16315 16317 //----------------------------------------------------------------------------------------------------------------- 16318 16319 #define $H txSetConsoleAttr (FOREGROUND_BLACK | BACKGROUND_BLACK); 16320 #define $B txSetConsoleAttr (FOREGROUND_BLUE | BACKGROUND_BLACK); 16321 #define $G txSetConsoleAttr (FOREGROUND_GREEN | BACKGROUND_BLACK); 16322 #define $C txSetConsoleAttr (FOREGROUND_CYAN | BACKGROUND_BLACK); 16323 #define $R txSetConsoleAttr (FOREGROUND_RED | BACKGROUND_BLACK); 16324 #define $M txSetConsoleAttr (FOREGROUND_MAGENTA | BACKGROUND_BLACK); 16325 #define $Y txSetConsoleAttr (FOREGROUND_DARKYELLOW | BACKGROUND_BLACK); 16326 #define $d txSetConsoleAttr (FOREGROUND_LIGHTGRAY | BACKGROUND_BLACK); 16327 #define $D txSetConsoleAttr (FOREGROUND_DARKGRAY | BACKGROUND_BLACK); 16328 #define $b txSetConsoleAttr (FOREGROUND_LIGHTBLUE | BACKGROUND_BLACK); 16329 #define $g txSetConsoleAttr (FOREGROUND_LIGHTGREEN | BACKGROUND_BLACK); 16330 #define $c txSetConsoleAttr (FOREGROUND_LIGHTCYAN | BACKGROUND_BLACK); 16331 #define $r txSetConsoleAttr (FOREGROUND_LIGHTRED | BACKGROUND_BLACK); 16332 #define $m txSetConsoleAttr (FOREGROUND_LIGHTMAGENTA | BACKGROUND_BLACK); 16333 #define $y txSetConsoleAttr (FOREGROUND_YELLOW | BACKGROUND_BLACK); 16334 #define $h txSetConsoleAttr (FOREGROUND_WHITE | BACKGROUND_BLACK); 16335 16336 #define $i txSetConsoleAttr (FOREGROUND_LIGHTCYAN | BACKGROUND_BLUE); 16337 #define $I txSetConsoleAttr (FOREGROUND_YELLOW | BACKGROUND_BLUE); 16338 #define $o txSetConsoleAttr (FOREGROUND_WHITE | BACKGROUND_GREEN); 16339 #define $O txSetConsoleAttr (FOREGROUND_YELLOW | BACKGROUND_GREEN); 16340 #define $e txSetConsoleAttr (FOREGROUND_WHITE | BACKGROUND_RED); 16341 #define $E txSetConsoleAttr (FOREGROUND_YELLOW | BACKGROUND_RED); 16342 #define $w txSetConsoleAttr (FOREGROUND_LIGHTMAGENTA | BACKGROUND_MAGENTA); 16343 #define $W txSetConsoleAttr (FOREGROUND_YELLOW | BACKGROUND_MAGENTA); 16344 #define $f txSetConsoleAttr (FOREGROUND_BLACK | BACKGROUND_LIGHTRED); 16345 #define $F txSetConsoleAttr (FOREGROUND_MAGENTA | BACKGROUND_LIGHTRED); 16346 #define $l txSetConsoleAttr (FOREGROUND_BLACK | BACKGROUND_DARKGRAY); 16347 #define $L txSetConsoleAttr (FOREGROUND_LIGHTGRAY | BACKGROUND_DARKGRAY); 16348 16349 #define $T( cond ) txSetConsoleAttr ((cond)? FOREGROUND_LIGHTGREEN : FOREGROUND_LIGHTRED ); 16350 16351 #define $s _txSaveConsoleAttr TX_JOIN (__txSavedConsoleAttrs, __LINE__); 16352 16353 #define $sH $s $H 16354 #define $sB $s $B 16355 #define $sG $s $G 16356 #define $sC $s $C 16357 #define $sR $s $R 16358 #define $sM $s $M 16359 #define $sY $s $Y 16360 #define $sd $s $d 16361 #define $sD $s $D 16362 #define $sb $s $b 16363 #define $sg $s $g 16364 #define $sc $s $c 16365 #define $sr $s $r 16366 #define $sm $s $m 16367 #define $sy $s $y 16368 #define $sh $s $h 16369 16370 #define $si $s $i 16371 #define $sI $s $I 16372 #define $so $s $o 16373 #define $sO $s $O 16374 #define $se $s $e 16375 #define $sE $s $E 16376 #define $sw $s $w 16377 #define $sW $s $W 16378 #define $sf $s $f 16379 #define $sF $s $F 16380 #define $sl $s $l 16381 #define $sL $s $L 16382 16383 #define $sT( cond ) $s $T (cond) 16384 16385 #define $test(cond) { if (!!(cond)) { $o std::cerr << "[PASSED] " __TX_FILELINE__ ": " #cond; } \ 16386 else { $e std::cerr << "[FAILED] " __TX_FILELINE__ ": " #cond; } $d; } 16387 16388 #define $status(cond) $test (cond) 16389 16390 #define $unittest( code, expected ) \ 16391 { \ 16392 const _tx_decltype (code) & _result = (code); /* Should use auto, but g++ 4.7.2 default std is < 2011 */ \ 16393 const _tx_decltype (expected) & _expected = (expected); \ 16394 \ 16395 if (_result == _expected) \ 16396 { $so std::cerr << "[PASSED] " __TX_FILELINE__ ": " #code; } \ 16397 else \ 16398 { $se std::cerr << "[FAILED] " __TX_FILELINE__ ": " #code " == (" << _result << "), should be (" << _expected << ")"; } \ 16399 \ 16400 $n; \ 16401 (_result == _expected); \ 16402 } 16403 16404 //================================================================================================================= 16405 16406 #define $V( var, ...) ( _txDumpVar ((var), _tx$PrefixV ( __VA_ARGS__), "]\n") ) 16407 #define $V_( var, ...) ( _txDumpVar ((var), _tx$PrefixV ( __VA_ARGS__), "] " ) ) 16408 #define $V__(var, ...) ( _txDumpVar ((var), _tx$PrefixV ( __VA_ARGS__), "]" ) ) 16409 16410 #define $( var, ...) ( _txDumpVar ((var), _tx$Prefix (#var, __VA_ARGS__), "]\n") ) 16411 #define $_( var, ...) ( _txDumpVar ((var), _tx$Prefix (#var, __VA_ARGS__), "] " ) ) 16412 #define $__( var, ...) ( _txDumpVar ((var), _tx$Prefix (#var, __VA_ARGS__), "]" ) ) 16413 16414 #define $x( var, ...) ( _txDumpVar ((var), _tx$Prefix (#var, __VA_ARGS__), "]\n", ::std::ios_base::showbase | ::std::ios_base::hex) ) 16415 #define $x_( var, ...) ( _txDumpVar ((var), _tx$Prefix (#var, __VA_ARGS__), "] ", ::std::ios_base::showbase | ::std::ios_base::hex) ) 16416 16417 #define $v( var, cond, ...) { { $st (cond); _txDumpVar ((var), _tx$Prefix (#var, __VA_ARGS__), "]" ); } $n; } 16418 #define $v_( var, cond, ...) { $st (cond); _txDumpVar ((var), _tx$Prefix (#var, __VA_ARGS__), "]" ); } 16419 16420 #define $$ { txOutputDebugPrintf ("\f\n"); { $sC txOutputDebugPrintf ("\f" "[%s:%d %s]", __FILE__, __LINE__, __TX_FUNCTION__); } txOutputDebugPrintf ("\f\n"); } 16421 #define $$_ { txOutputDebugPrintf ("\f\n"); { $sC txOutputDebugPrintf ("\f" "[" "%d %s]", __LINE__, __func__); } txOutputDebugPrintf ("\f\n"); } 16422 #define $meow(...) { txOutputDebugPrintf ("\f\n"); { $sc txOutputDebugPrintf ("\f" "[%s:%d %s]", __FILE__, __LINE__, __func__); txOutputDebugPrintf ("\f " __VA_ARGS__); } txOutputDebugPrintf ("\f\n"); } 16423 16424 #define $$$( ... ) ( ::std::cerr << "\n[" __TX_FILELINE__ ": " #__VA_ARGS__ "]\n", _txDumpVar ((__VA_ARGS__),"\n[" __TX_FILELINE__ ": " #__VA_ARGS__ ": ", ", DONE]\n\n") ) 16425 #define $$$_( ... ) ( ::std::cerr << "\n[" __TX_FILELINE__ ": " #__VA_ARGS__ "]\n", _txDumpVar ((__VA_ARGS__), "[" __TX_FILELINE__ ": " #__VA_ARGS__ ": ", ", DONE]\n\n") ) 16426 16427 #define $$$$( ... ) { ::std::cerr << "\n[" __TX_FILELINE__ ": " #__VA_ARGS__ "]\n"; _txDumpVarSuffix ("\n[" __TX_FILELINE__ ": " #__VA_ARGS__ " DONE]\n\n"); { __VA_ARGS__; } } 16428 #define $$$$_( ... ) { ::std::cerr << "\n[" __TX_FILELINE__ ": " #__VA_ARGS__ "]\n"; _txDumpVarSuffix ( "[" __TX_FILELINE__ ": " #__VA_ARGS__ " DONE]\n\n"); { __VA_ARGS__; } } 16429 #define $do( ... ) ::std::cerr << "\n[" __TX_FILELINE__ ": " #__VA_ARGS__ "]\n"; __VA_ARGS__ 16430 #define $DO( ... ) ::std::cerr << "\n[" __TX_FILELINE__ ": " #__VA_ARGS__ "]...\n"; $p; __VA_ARGS__ 16431 #define $Do( ... ) ::std::cerr << "\n[" __TX_FILELINE__ ": " #__VA_ARGS__ "]...\n"; \ 16432 txMessageBox ( "\n[" __TX_FILELINE__ ": " #__VA_ARGS__ "]...\n", __TX_FUNCTION__); __VA_ARGS__ 16433 16434 #define $n { ::std::cerr << "\n"; } 16435 #define $nn { ::std::cerr << "\n\n"; } 16436 #define $t { ::std::cerr << "\t"; } 16437 16438 #define _tx$PrefixV( ...) ( *(__VA_ARGS__ "")? ("[" __VA_ARGS__ ": " ) : ("[" ) ) 16439 #define _tx$Prefix(var, ...) ( *(__VA_ARGS__ "")? ("[" __VA_ARGS__ ": " var " = ") : ("[" var " = ") ) 16440 16441 //----------------------------------------------------------------------------------------------------------------- 16442 16443 // This will never be documented, he-he. Read the source, Luke. 16444 16445 #if defined (_DEBUG) 16446 #define $dbg if (1) 16447 #define $DBG if (1) 16448 #define $debug if (1) 16449 #define $DEBUG if (1) 16450 #define $printf(fmt, ...) if (1) printf ( fmt, ##__VA_ARGS__) 16451 #define $PRINTF(fmt, ...) if (1) fprintf (stderr, fmt, ##__VA_ARGS__) 16452 #else 16453 #define $dbg if (0) 16454 #define $DBG if (0) 16455 #define $debug if (0) 16456 #define $DEBUG if (0) 16457 #define $printf(...) if (0) printf ( fmt, ##__VA_ARGS__) 16458 #define $PRINTF(...) if (0) fprintf (stderr, fmt, ##__VA_ARGS__) 16459 #endif 16460 16461 #define $$d $debug 16462 #define $$w $$$$ 16463 #define $$s __TX_FILELINE__ 16464 #define $$b { txSleep(); DebugBreak(); } 16465 #define $$p { if (txMessageBox (__TX_FILELINE__ "\n\n" "[Повтор] - продолжение программы,\n" "[Отмена] - остановка", \ 16466 __TX_FUNCTION__, MB_ICONINFORMATION | MB_RETRYCANCEL) == IDCANCEL) ::exit (2); } 16467 #define $$P ( txMessageBox (__TX_FILELINE__, __TX_FUNCTION__, MB_ICONINFORMATION | MB_YESNOCANCEL) ) 16468 #define $ppp { $sy; txPause ("\v[%s ""%s: ""Нажмите клавишу]...", __TX_FILELINE__, __TX_FUNCTION__); } 16469 #define $pp { $sy; txPause ("\v[%04d %s: ""Нажмите клавишу]...", __LINE__, __TX_FUNCTION__); } 16470 #define $p { $sy; txPause ("\v[%s ""%s(): Нажмите клавишу]...", __TX_FILELINE__, __func__); } 16471 #define $ppp_ { $sy; txPause ("\v[%s ""%s]...", __TX_FILELINE__, __TX_FUNCTION__); } 16472 #define $pp_ { $sy; txPause ("\v[%04d %s]...", __LINE__, __TX_FUNCTION__); } 16473 #define $p_ { $sy; txPause ("\v[%s ""%s()]...", __TX_FILELINE__, __func__); } 16474 #define $P ( txPause ("") ) 16475 16476 //----------------------------------------------------------------------------------------------------------------- 16477 16478 struct _txSaveConsoleAttr 16479 { 16480 unsigned attr_; 16481 16482 _txSaveConsoleAttr() : attr_ (txGetConsoleAttr ()) {} 16483 explicit _txSaveConsoleAttr (WORD attr) : attr_ (txGetConsoleAttr ()) { txSetConsoleAttr (attr); } 16484 ~_txSaveConsoleAttr() { txSetConsoleAttr (attr_); } 16485 }; 16486 16487 //----------------------------------------------------------------------------------------------------------------- 16488 16489 struct _txDumpVarSuffix 16490 { 16491 typedef _txDumpVarSuffix this_t; 16492 16493 const char* suffix_; 16494 16495 explicit _txDumpVarSuffix (const char suffix[] = "") : suffix_ (suffix) { assert (suffix); } 16496 ~_txDumpVarSuffix() { ::std::cerr << suffix_; } 16497 16498 _txDumpVarSuffix (const this_t&) _tx_delete; 16499 this_t& operator = (const this_t&) _tx_delete; 16500 }; 16501 16502 //----------------------------------------------------------------------------------------------------------------- 16503 16504 #define ARGS__ const char* prefix, const char* suffix, std::ios_base::fmtflags flags, int deep 16505 #define ARGS_ const char* prefix, const char* suffix, std::ios_base::fmtflags flags = std::ios_base::fmtflags(), int deep = 0 16506 #define VALS_ prefix, suffix, flags, deep 16507 #define ERRPTR_(p) { $sE; stream << "<НЕВЕРНЫЙ АДРЕС " << (const void*) (p) << ">"; } 16508 16509 template <typename T, typename StreamT> const T& _txDumpVal (const T& value, StreamT& stream, ARGS_); 16510 16511 //----------------------------------------------------------------------------------------------------------------- 16512 16513 template <typename T> inline const T& _txDumpVar (const T& value, ARGS_) { _txDumpVal (value, std:: cerr, VALS_); return value; } 16514 template <typename T> inline T& _txDumpVar ( T& value, ARGS_) { _txDumpVal (value, std:: cerr, VALS_); return value; } 16515 16516 template <int N> inline const char (&_txDumpVar (const char (&value) [N], ARGS_)) [N] { _txDumpVal (value, std:: cerr, VALS_); return value; } 16517 template <int N> inline char (&_txDumpVar ( char (&value) [N], ARGS_)) [N] { _txDumpVal (value, std:: cerr, VALS_); return value; } 16518 16519 template <int N> inline const wchar_t (&_txDumpVar (const wchar_t (&value) [N], ARGS_)) [N] { _txDumpVal (value, std::wcerr, VALS_); return value; } 16520 template <int N> inline wchar_t (&_txDumpVar ( wchar_t (&value) [N], ARGS_)) [N] { _txDumpVal (value, std::wcerr, VALS_); return value; } 16521 16522 inline const wchar_t& _txDumpVar (const wchar_t& value, ARGS_) { _txDumpVal (value, std::wcerr, VALS_); return value; } 16523 inline wchar_t& _txDumpVar ( wchar_t& value, ARGS_) { _txDumpVal (value, std::wcerr, VALS_); return value; } 16524 16525 inline const wchar_t*& _txDumpVar (const wchar_t*& value, ARGS_) { _txDumpVal (value, std::wcerr, VALS_); return value; } 16526 inline wchar_t*& _txDumpVar ( wchar_t*& value, ARGS_) { _txDumpVal (value, std::wcerr, VALS_); return value; } 16527 16528 inline const std::wstring& _txDumpVar (const std::wstring& value, ARGS_) { _txDumpVal (value, std::wcerr, VALS_); return value; } 16529 inline std::wstring& _txDumpVar ( std::wstring& value, ARGS_) { _txDumpVal (value, std::wcerr, VALS_); return value; } 16530 16531 //----------------------------------------------------------------------------------------------------------------- 16532 16533 template <typename T, typename StreamT> inline void _txDumpVal (const T& value, StreamT& stream) { stream << value; } 16534 template <typename StreamT> inline void _txDumpVal (const char value, StreamT& stream) { stream << "'" << value << "'"; } 16535 template <typename StreamT> inline void _txDumpVal (const wchar_t value, StreamT& stream) { stream << L"'" << value << L"'"; } 16536 template <typename StreamT> inline void _txDumpVal (const std::string& value, StreamT& stream) { stream << '"' << value << '"'; } 16537 template <typename StreamT> inline void _txDumpVal (const std::wstring& value, StreamT& stream) { stream << L'"' << value << L'"'; } 16538 16539 template <typename StreamT> inline void _txDumpVal (const char* value, StreamT& stream) 16540 { 16541 if (_TX_ARGUMENT_FAILED (&stream)) return; 16542 16543 if (!_txIsBadReadPtr (value)) stream << '"' << value << '"'; 16544 else if (!value) stream << "(null)"; 16545 else ERRPTR_ (value); 16546 } 16547 16548 template <typename StreamT> inline void _txDumpVal (const wchar_t* value, StreamT& stream) 16549 { 16550 if (_TX_ARGUMENT_FAILED (&stream)) return; 16551 16552 if (!_txIsBadReadPtr (value)) stream << L'"' << value << L'"'; 16553 else if (!value) stream << L"(null)"; 16554 else ERRPTR_ (value); 16555 } 16556 16557 //----------------------------------------------------------------------------------------------------------------- 16558 16559 template <typename T, typename StreamT> 16560 inline const T& _txDumpVal (const T& value, StreamT& stream, ARGS__) 16561 { 16562 if (_TX_ARGUMENT_FAILED (&stream)) return value; //-V778 16563 if (_TX_ARGUMENT_FAILED ( prefix)) return value; 16564 if (_TX_ARGUMENT_FAILED ( suffix)) return value; 16565 16566 $sc; 16567 if (!deep) stream << prefix; 16568 16569 std::ios_base::fmtflags old = stream.flags ((flags)? flags : stream.flags()); 16570 16571 if (!_txIsBadReadPtr (&value)) 16572 { 16573 _txDumpVal (value, stream); 16574 } 16575 else 16576 ERRPTR_ (&value); 16577 16578 stream.flags (old); 16579 16580 if (!deep) stream << suffix; 16581 16582 return value; 16583 } 16584 16585 //----------------------------------------------------------------------------------------------------------------- 16586 16587 template <typename T, int N> 16588 inline T (&_txDumpVar (T (&value) [N], ARGS_)) [N] 16589 { 16590 if (_TX_ARGUMENT_FAILED ( prefix)) return value; 16591 if (_TX_ARGUMENT_FAILED ( suffix)) return value; 16592 16593 std::ostream& stream = std::cerr; 16594 16595 $sc; if (!deep) std::cerr << prefix; 16596 $C; std::cerr << ((deep)? " {" : "{"); 16597 16598 if (!_txIsBadReadPtr (value)) 16599 { 16600 for (int i = 0; ; i++) 16601 { 16602 { $sC; stream << "[" << i << "]="; } 16603 16604 _txDumpVar (value[i], prefix, suffix, flags, deep+1); 16605 16606 if (i >= N-1) break; 16607 16608 stream << ", "; 16609 } 16610 } 16611 else 16612 ERRPTR_ (&value); 16613 16614 $C; std::cerr << "}"; 16615 $c; if (!deep) std::cerr << suffix; 16616 16617 return value; 16618 } 16619 16620 //----------------------------------------------------------------------------------------------------------------- 16621 16622 inline int $ptrHTML (FILE* html, const void* ptr, COLORREF backColor = TX_WHITE) 16623 { 16624 COLORREF color = txHash (&ptr, sizeof (ptr)) & 0x00FFFFFF; 16625 16626 if (txDeltaE94 (color, backColor) < 10) color = ~color & 0x00FFFFFF; 16627 16628 return fprintf (html, "<font face = \"Monospace\" color = \"#%06lX\">0x%p</font>", color, ptr); 16629 } 16630 16631 //================================================================================================================= 16632 16633 inline std::ostream& operator << (std::ostream& stream, const POINT& point) 16634 { 16635 if (_TX_ARGUMENT_FAILED (&stream)) return stream; 16636 16637 if (!_txIsBadReadPtr (&point)) stream << "{ x: " << point.x << ", y: " << point.y << " }"; // NOLINT (clang-diagnostic-undefined-bool-conversion) 16638 else if (!&point) stream << "(null)"; 16639 else ERRPTR_ (&point); 16640 16641 return stream; 16642 } 16643 16644 inline std::ostream& operator << (std::ostream& stream, const SIZE& size) 16645 { 16646 if (_TX_ARGUMENT_FAILED (&stream)) return stream; 16647 16648 if (&size) stream << "{ cx: " << size.cx << ", cy: " << size.cy << " }"; // NOLINT (clang-diagnostic-undefined-bool-conversion) 16649 else stream << "(null)"; 16650 16651 return stream; 16652 } 16653 16654 inline std::ostream& operator << (std::ostream& stream, const RECT& rect) 16655 { 16656 if (_TX_ARGUMENT_FAILED (&stream)) return stream; 16657 16658 if (&rect) stream << "{ left: " << rect.left << ", top: " << rect.top << // NOLINT (clang-diagnostic-undefined-bool-conversion) 16659 ", right: " << rect.right << ", bottom: " << rect.bottom << " }"; 16660 16661 else stream << "(null)"; 16662 16663 return stream; 16664 } 16665 16666 //----------------------------------------------------------------------------------------------------------------- 16667 16668 #undef ARGS__ 16669 #undef ARGS_ 16670 #undef VALS_ 16671 #undef ERRPTR_ 16672 16673 //----------------------------------------------------------------------------------------------------------------- 16675 16676 #endif 16677 16678 //} 16679 //================================================================================================================= 16680 16682 16683 //================================================================================================================= 16684 //{ TXAPI calls tracing 16685 // Трассировка вызовов TXAPI 16686 //================================================================================================================= 16687 16688 #ifndef FOR_DOXYGEN_ONLY 16689 16690 #if defined (_MSC_VER) 16691 #undef _txLocCurSet 16692 #define _txLocCurSet() _txLocSet (&_txLoc::Cur, __FILE__, __LINE__, NULL) 16693 #endif 16694 16695 #define txAlphaBlend(...) ( _txLocCurSet(), txAlphaBlend (__VA_ARGS__) ) 16696 #define txArc(...) ( _txLocCurSet(), txArc (__VA_ARGS__) ) 16697 #define txBegin(...) ( _txLocCurSet(), txBegin (__VA_ARGS__) ) 16698 #define txBitBlt(...) ( _txLocCurSet(), txBitBlt (__VA_ARGS__) ) 16699 #define txChord(...) ( _txLocCurSet(), txChord (__VA_ARGS__) ) 16700 #define txCircle(...) ( _txLocCurSet(), txCircle (__VA_ARGS__) ) 16701 #define txClear(...) ( _txLocCurSet(), txClear (__VA_ARGS__) ) 16702 #define txClearConsole(...) ( _txLocCurSet(), txClearConsole (__VA_ARGS__) ) 16703 #define txColor(...) ( _txLocCurSet(), txColor (__VA_ARGS__) ) 16704 #define txCreateCompatibleDC(...) ( _txLocCurSet(), txCreateCompatibleDC (__VA_ARGS__) ) 16705 #define txCreateDIBSection(...) ( _txLocCurSet(), txCreateDIBSection (__VA_ARGS__) ) 16706 #define txCreateExtraWindow(...) ( _txLocCurSet(), txCreateExtraWindow (__VA_ARGS__) ) 16707 #define txCreateWindow(...) ( _txLocCurSet(), txCreateWindow (__VA_ARGS__) ) 16708 #define txDC(...) ( _txLocCurSet(), txDC (__VA_ARGS__) ) 16709 #define txDeleteDC(...) ( _txLocCurSet(), txDeleteDC (__VA_ARGS__) ) 16710 #define txDeltaE(...) ( _txLocCurSet(), txDeltaE (__VA_ARGS__) ) 16711 #define txDeltaE94(...) ( _txLocCurSet(), txDeltaE94 (__VA_ARGS__) ) 16712 #define txDemangle(...) ( _txLocCurSet(), txDemangle (__VA_ARGS__) ) 16713 #define txDestroyWindow(...) ( _txLocCurSet(), txDestroyWindow (__VA_ARGS__) ) 16714 #define txDisableAutoPause(...) ( _txLocCurSet(), txDisableAutoPause (__VA_ARGS__) ) 16715 #define txDrawText(...) ( _txLocCurSet(), txDrawText (__VA_ARGS__) ) 16716 #define txEllipse(...) ( _txLocCurSet(), txEllipse (__VA_ARGS__) ) 16717 #define txEnd(...) ( _txLocCurSet(), txEnd (__VA_ARGS__) ) 16718 #define txExtractColor(...) ( _txLocCurSet(), txExtractColor (__VA_ARGS__) ) 16719 #define txFillColor(...) ( _txLocCurSet(), txFillColor (__VA_ARGS__) ) 16720 #define txFloodFill(...) ( _txLocCurSet(), txFloodFill (__VA_ARGS__) ) 16721 #define txFontExist(...) ( _txLocCurSet(), txFontExist (__VA_ARGS__) ) 16722 #define txFormat(...) ( _txLocCurSet(), txFormat (__VA_ARGS__) ) 16723 #define txGetAsyncKeyState(...) ( _txLocCurSet(), txGetAsyncKeyState (__VA_ARGS__) ) 16724 #define txGetColor(...) ( _txLocCurSet(), txGetColor (__VA_ARGS__) ) 16725 #define txGetConsoleAttr(...) ( _txLocCurSet(), txGetConsoleAttr (__VA_ARGS__) ) 16726 #define txGetConsoleCursorPos(...) ( _txLocCurSet(), txGetConsoleCursorPos (__VA_ARGS__) ) 16727 #define txGetConsoleExtent(...) ( _txLocCurSet(), txGetConsoleExtent (__VA_ARGS__) ) 16728 #define txGetConsoleFontSize(...) ( _txLocCurSet(), txGetConsoleFontSize (__VA_ARGS__) ) 16729 #define txGetExtent(...) ( _txLocCurSet(), txGetExtent (__VA_ARGS__) ) 16730 #define txGetExtentX(...) ( _txLocCurSet(), txGetExtentX (__VA_ARGS__) ) 16731 #define txGetExtentY(...) ( _txLocCurSet(), txGetExtentY (__VA_ARGS__) ) 16732 #define txGetFillColor(...) ( _txLocCurSet(), txGetFillColor (__VA_ARGS__) ) 16733 #define txGetFPS(...) ( _txLocCurSet(), txGetFPS (__VA_ARGS__) ) 16734 #define txGetModuleFileName(...) ( _txLocCurSet(), txGetModuleFileName (__VA_ARGS__) ) 16735 #define txGetPixel(...) ( _txLocCurSet(), txGetPixel (__VA_ARGS__) ) 16736 #define txGetTextExtent(...) ( _txLocCurSet(), txGetTextExtent (__VA_ARGS__) ) 16737 #define txGetTextExtentX(...) ( _txLocCurSet(), txGetTextExtentX (__VA_ARGS__) ) 16738 #define txGetTextExtentY(...) ( _txLocCurSet(), txGetTextExtentY (__VA_ARGS__) ) 16739 #define txHSL2RGB(...) ( _txLocCurSet(), txHSL2RGB (__VA_ARGS__) ) 16740 #define txHash(...) ( _txLocCurSet(), txHash (__VA_ARGS__) ) 16741 #define txInputBox(...) ( _txLocCurSet(), txInputBox (__VA_ARGS__) ) 16742 #define txLab2RGB(...) ( _txLocCurSet(), txLab2RGB (__VA_ARGS__) ) 16743 #define txLine(...) ( _txLocCurSet(), txLine (__VA_ARGS__) ) 16744 #define txLoadImage(...) ( _txLocCurSet(), txLoadImage (__VA_ARGS__) ) 16745 #define txLock(...) ( _txLocCurSet(), txLock (__VA_ARGS__) ) 16746 #define txMessageBox(...) ( _txLocCurSet(), txMessageBox (__VA_ARGS__) ) 16747 #define txMouseButtons(...) ( _txLocCurSet(), txMouseButtons (__VA_ARGS__) ) 16748 #define txMousePos(...) ( _txLocCurSet(), txMousePos (__VA_ARGS__) ) 16749 #define txMouseX(...) ( _txLocCurSet(), txMouseX (__VA_ARGS__) ) 16750 #define txMouseY(...) ( _txLocCurSet(), txMouseY (__VA_ARGS__) ) 16751 #define txNotifyIcon(...) ( _txLocCurSet(), txNotifyIcon (__VA_ARGS__) ) 16752 #define txOK(...) ( _txLocCurSet(), txOK (__VA_ARGS__) ) 16753 #define txOutputDebugPrintf(...) ( _txLocCurSet(), txOutputDebugPrintf (__VA_ARGS__) ) 16754 #define txPause(...) ( _txLocCurSet(), txPause (__VA_ARGS__) ) 16755 #define txPie(...) ( _txLocCurSet(), txPie (__VA_ARGS__) ) 16756 #define txPixel(...) ( _txLocCurSet(), txPixel (__VA_ARGS__) ) 16757 #define txPlaySound(...) ( _txLocCurSet(), txPlaySound (__VA_ARGS__) ) 16758 #define txPlayVideo(...) ( _txLocCurSet(), txPlayVideo (__VA_ARGS__) ) 16759 #define txPolygon(...) ( _txLocCurSet(), txPolygon (__VA_ARGS__) ) 16760 #define txPrintf(...) ( _txLocCurSet(), txPrintf (__VA_ARGS__) ) 16761 #define txQueryPerformance(...) ( _txLocCurSet(), txQueryPerformance (__VA_ARGS__) ) 16762 #define txRectangle(...) ( _txLocCurSet(), txRectangle (__VA_ARGS__) ) 16763 #define txRedrawWindow(...) ( _txLocCurSet(), txRedrawWindow (__VA_ARGS__) ) 16764 #define txRegisterClass(...) ( _txLocCurSet(), txRegisterClass (__VA_ARGS__) ) 16765 #define txRegQuery(...) ( _txLocCurSet(), txRegQuery (__VA_ARGS__) ) 16766 #define txReopenStdio(...) ( _txLocCurSet(), txReopenStdio (__VA_ARGS__) ) 16767 #define txRGB2HSL(...) ( _txLocCurSet(), txRGB2HSL (__VA_ARGS__) ) 16768 #define txRGB2Lab(...) ( _txLocCurSet(), txRGB2Lab (__VA_ARGS__) ) 16769 #define txSaveImage(...) ( _txLocCurSet(), txSaveImage (__VA_ARGS__) ) 16770 #define txSelectFont(...) ( _txLocCurSet(), txSelectFont (__VA_ARGS__) ) 16771 #define txSelectObject(...) ( _txLocCurSet(), txSelectObject (__VA_ARGS__) ) 16772 #define txSetColor(...) ( _txLocCurSet(), txSetColor (__VA_ARGS__) ) 16773 #define txSetConsoleAttr(...) ( _txLocCurSet(), txSetConsoleAttr (__VA_ARGS__) ) 16774 #define txSetConsoleCursorPos(...) ( _txLocCurSet(), txSetConsoleCursorPos (__VA_ARGS__) ) 16775 #define txSetDefaults(...) ( _txLocCurSet(), txSetDefaults (__VA_ARGS__) ) 16776 #define txSetFillColor(...) ( _txLocCurSet(), txSetFillColor (__VA_ARGS__) ) 16777 #define txSetLocale(...) ( _txLocCurSet(), txSetLocale (__VA_ARGS__) ) 16778 #define txSetPixel(...) ( _txLocCurSet(), txSetPixel (__VA_ARGS__) ) 16779 #define txSetProgress(...) ( _txLocCurSet(), txSetProgress (__VA_ARGS__) ) 16780 #define txSetTextAlign(...) ( _txLocCurSet(), txSetTextAlign (__VA_ARGS__) ) 16781 #define txSetWindowsHook(...) ( _txLocCurSet(), txSetWindowsHook (__VA_ARGS__) ) 16782 #define txSleep(...) ( _txLocCurSet(), txSleep (__VA_ARGS__) ) 16783 #define txSpeak(...) ( _txLocCurSet(), txSpeak (__VA_ARGS__) ) 16784 #define txTextCursor(...) ( _txLocCurSet(), txTextCursor (__VA_ARGS__) ) 16785 #define txTextOut(...) ( _txLocCurSet(), txTextOut (__VA_ARGS__) ) 16786 #define txTransparentBlt(...) ( _txLocCurSet(), txTransparentBlt (__VA_ARGS__) ) 16787 #define txTriangle(...) ( _txLocCurSet(), txTriangle (__VA_ARGS__) ) 16788 #define txUnlock(...) ( _txLocCurSet(), txUnlock (__VA_ARGS__) ) 16789 #define txUpdateWindow(...) ( _txLocCurSet(), txUpdateWindow (__VA_ARGS__) ) 16790 #define txUseAlpha(...) ( _txLocCurSet(), txUseAlpha (__VA_ARGS__) ) 16791 #define txVersion(...) ( _txLocCurSet(), txVersion (__VA_ARGS__) ) 16792 #define txVersionNumber(...) ( _txLocCurSet(), txVersionNumber (__VA_ARGS__) ) 16793 #define txWindow(...) ( _txLocCurSet(), txWindow (__VA_ARGS__) ) 16794 #define tx_fpreset(...) ( _txLocCurSet(), tx_fpreset (__VA_ARGS__) ) 16795 #define tx_glGetError(...) ( _txLocCurSet(), tx_glGetError (__VA_ARGS__) ) 16796 #define _txDump(...) ( _txLocCurSet(), _txDump (__VA_ARGS__) ) 16797 #define _txStackBackTrace(...) ( _txLocCurSet(), _txStackBackTrace (__VA_ARGS__) ) 16798 16799 #endif 16800 16801 //} 16802 //================================================================================================================= 16803 16805 //} 16806 //================================================================================================================= 16807 16808 //----------------------------------------------------------------------------------------------------------------- 16809 //{ The namespaces 16810 //----------------------------------------------------------------------------------------------------------------- 16811 16814 _TX_END_NAMESPACE 16815 16818 using namespace TX; // Allow easy usage of TXLib functions 16819 16820 using ::std::cin; // Predefined usings to avoid "using namespace std" 16821 using ::std::cout; 16822 using ::std::cerr; 16823 using ::std::string; 16824 using ::std::wcin; 16825 using ::std::wcout; 16826 using ::std::wcerr; 16827 using ::std::wstring; 16828 16829 //} 16830 //----------------------------------------------------------------------------------------------------------------- 16831 16832 //----------------------------------------------------------------------------------------------------------------- 16833 //{ Compiler- and platform-specific 16834 // Адаптация к компиляторам и платформам 16835 //----------------------------------------------------------------------------------------------------------------- 16837 16838 #if defined (_GCC_VER) 16839 16840 #pragma GCC diagnostic ignored "-Wunknown-pragmas" 16841 16842 #pragma GCC optimize "strict-aliasing" 16843 16844 #pragma GCC pop_options 16845 #pragma GCC diagnostic pop 16846 16847 #pragma GCC diagnostic warning "-Wunknown-pragmas" 16848 16849 #endif 16850 16851 #if defined (_CLANG_VER) 16852 #pragma clang diagnostic pop 16853 #endif 16854 16855 //----------------------------------------------------------------------------------------------------------------- 16856 16857 #if defined (_MSC_VER) 16858 #pragma warning (pop) // Restoring maximum level 16859 #endif 16860 16862 //} 16863 //----------------------------------------------------------------------------------------------------------------- 16864 16865 #endif // __TXLIB_H_INCLUDED 16866 16867 //================================================================================================================= 16868 // EOF 16869 //================================================================================================================= 16870 16871 16872 16873 16874 16875 16876 16877 16878 16879 16880 16881 16882 16883 16884 16885 16886 16887 16888 16889 16890 16891 16892 16893 16894 16895 16896 16897 16898 16899