diff options
-rw-r--r-- | indra/llcommon/llmd5.cpp | 551 | ||||
-rw-r--r-- | indra/llcommon/llmd5.h | 82 | ||||
-rw-r--r-- | indra/llrender/llfontvertexbuffer.cpp | 2 | ||||
-rw-r--r-- | indra/llui/lllineeditor.cpp | 60 | ||||
-rw-r--r-- | indra/llui/lllineeditor.h | 5 | ||||
-rw-r--r-- | indra/llui/lltextbase.cpp | 172 | ||||
-rw-r--r-- | indra/llui/lltextbase.h | 9 | ||||
-rw-r--r-- | indra/llui/llviewmodel.cpp | 10 | ||||
-rw-r--r-- | indra/llui/llviewmodel.h | 4 | ||||
-rw-r--r-- | indra/newview/llpanelmaininventory.cpp | 102 | ||||
-rw-r--r-- | indra/newview/llpanelmaininventory.h | 5 | ||||
-rw-r--r-- | indra/newview/skins/default/textures/map_avatar_you_32.tga | bin | 3395 -> 4140 bytes |
12 files changed, 578 insertions, 424 deletions
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index f64f54c262..e999b8f597 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -68,10 +68,6 @@ documentation and/or software. */ - - - - #include "linden_common.h" #include "llmd5.h" @@ -81,232 +77,203 @@ documentation and/or software. // how many bytes to grab at a time when checking files const int LLMD5::BLOCK_LEN = 4096; - // LLMD5 simple initialization method - LLMD5::LLMD5() { - init(); + init(); } - - - // MD5 block update operation. Continues an MD5 message-digest // operation, processing another message block, and updating the // context. +void LLMD5::update(const uint8_t* input, const size_t input_length) +{ + size_t input_index, buffer_index; + size_t buffer_space; // how much space is left in buffer -void LLMD5::update (const uint8_t *input, const size_t input_length) { - - size_t input_index, buffer_index; - size_t buffer_space; // how much space is left in buffer - - if (finalized){ // so we can't update! - std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl; - return; - } - - // Compute number of bytes mod 64 - buffer_index = size_t((count >> 3) & 0x3F); + if (finalized) + { // so we can't update! + std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl; + return; + } - // Update number of bits - count += input_length << 3; + // Compute number of bytes mod 64 + buffer_index = size_t((count >> 3) & 0x3F); - buffer_space = 64 - buffer_index; // how much space is left in buffer + // Update number of bits + count += input_length << 3; - // now, transform each 64-byte piece of the input, bypassing the buffer - if (input == NULL || input_length == 0){ - std::cerr << "LLMD5::update: Invalid input!" << std::endl; - return; - } + buffer_space = 64 - buffer_index; // how much space is left in buffer - // Transform as many times as possible. - if (input_length >= buffer_space) { // ie. we have enough to fill the buffer - // fill the rest of the buffer and transform - memcpy( /* Flawfinder: ignore */ - buffer + buffer_index, - input, - buffer_space); - transform (buffer); + // now, transform each 64-byte piece of the input, bypassing the buffer + if (input == NULL || input_length == 0) + { + std::cerr << "LLMD5::update: Invalid input!" << std::endl; + return; + } - for (input_index = buffer_space; input_index + 63 < input_length; - input_index += 64) - transform (input+input_index); + // Transform as many times as possible. + if (input_length >= buffer_space) // ie. we have enough to fill the buffer + { + // fill the rest of the buffer and transform + memcpy(/* Flawfinder: ignore */ + buffer + buffer_index, + input, + buffer_space); + transform(buffer); - buffer_index = 0; // so we can buffer remaining - } - else - input_index=0; // so we can buffer the whole input + for (input_index = buffer_space; input_index + 63 < input_length; input_index += 64) + transform(input + input_index); + buffer_index = 0; // so we can buffer remaining + } + else + input_index = 0; // so we can buffer the whole input - // and here we do the buffering: - memcpy(buffer+buffer_index, input+input_index, input_length-input_index); /* Flawfinder: ignore */ + // and here we do the buffering: + memcpy(buffer + buffer_index, input + input_index, input_length - input_index); /* Flawfinder: ignore */ } - - // MD5 update for files. // Like above, except that it works on files (and uses above as a primitive.) +void LLMD5::update(FILE* file) +{ + unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ + int len; -void LLMD5::update(FILE* file){ - - unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ - int len; - - while ( (len=(int)fread(buffer, 1, BLOCK_LEN, file)) ) - update(buffer, len); - - fclose (file); + while ((len = (int)fread(buffer, 1, BLOCK_LEN, file))) + update(buffer, len); + fclose(file); } // MD5 update for istreams. // Like update for files; see above. +void LLMD5::update(std::istream& stream) +{ + unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ + int len; -void LLMD5::update(std::istream& stream){ - - unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ - int len; - - while (stream.good()){ - stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable. - len=(int)stream.gcount(); - update(buffer, len); - } - + while (stream.good()) + { + stream.read((char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable. + len = (int)stream.gcount(); + update(buffer, len); + } } -void LLMD5::update(const std::string& s) +void LLMD5::update(const std::string& s) { - update((unsigned char *)s.c_str(),s.length()); + update((unsigned char*)s.c_str(), s.length()); } // MD5 finalization. Ends an MD5 message-digest operation, writing the // the message digest and zeroizing the context. - - -void LLMD5::finalize (){ - - unsigned char bits[8]; /* Flawfinder: ignore */ - size_t index, padLen; - static uint8_t PADDING[64]={ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +void LLMD5::finalize() +{ + unsigned char bits[8]; /* Flawfinder: ignore */ + size_t index, padLen; + static uint8_t PADDING[64] = + { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - if (finalized){ - std::cerr << "LLMD5::finalize: Already finalized this digest!" << std::endl; - return; - } - - // Save number of bits. - // Treat count, a uint64_t, as uint32_t[2]. - encode (bits, reinterpret_cast<uint32_t*>(&count), 8); + if (finalized) + { + std::cerr << "LLMD5::finalize: Already finalized this digest!" << std::endl; + return; + } - // Pad out to 56 mod 64. - index = size_t((count >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - update (PADDING, padLen); + // Save number of bits. + // Treat count, a uint64_t, as uint32_t[2]. + encode(bits, reinterpret_cast<uint32_t*>(&count), 8); - // Append length (before padding) - update (bits, 8); + // Pad out to 56 mod 64. + index = size_t((count >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + update(PADDING, padLen); - // Store state in digest - encode (digest, state, 16); + // Append length (before padding) + update(bits, 8); - // Zeroize sensitive information - memset (buffer, 0, sizeof(*buffer)); + // Store state in digest + encode(digest, state, 16); - finalized=1; + // Zeroize sensitive information + memset(buffer, 0, sizeof(buffer)); + finalized = true; } - - - -LLMD5::LLMD5(FILE *file){ - - init(); // must be called be all constructors - update(file); - finalize (); +LLMD5::LLMD5(FILE* file) +{ + init(); // must be called be all constructors + update(file); + finalize(); } - - - -LLMD5::LLMD5(std::istream& stream){ - - init(); // must called by all constructors - update (stream); - finalize(); +LLMD5::LLMD5(std::istream& stream) +{ + init(); // must called by all constructors + update(stream); + finalize(); } // Digest a string of the format ("%s:%i" % (s, number)) -LLMD5::LLMD5(const unsigned char *string, const unsigned int number) +LLMD5::LLMD5(const unsigned char* string, const unsigned int number) { - const char *colon = ":"; - char tbuf[16]; /* Flawfinder: ignore */ + const char* colon = ":"; + char tbuf[16]; /* Flawfinder: ignore */ init(); - update(string, (U32)strlen((const char *) string)); /* Flawfinder: ignore */ - update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */ - snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */ - update((const unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */ + update(string, (U32)strlen((const char*)string)); /* Flawfinder: ignore */ + update((const unsigned char*)colon, (U32)strlen(colon)); /* Flawfinder: ignore */ + snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */ + update((const unsigned char*)tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */ finalize(); } // Digest a string -LLMD5::LLMD5(const unsigned char *s) +LLMD5::LLMD5(const unsigned char* s) { init(); - update(s, (U32)strlen((const char *) s)); /* Flawfinder: ignore */ + update(s, (U32)strlen((const char*)s)); /* Flawfinder: ignore */ finalize(); } -void LLMD5::raw_digest(unsigned char *s) const +void LLMD5::raw_digest(unsigned char* s) const { if (!finalized) { - std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't "<< - "finalized the digest!" << std::endl; + std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't " + << "finalized the digest!" << std::endl; s[0] = '\0'; return; } - memcpy(s, digest, 16); /* Flawfinder: ignore */ - return; + memcpy(s, digest, 16); /* Flawfinder: ignore */ } - - -void LLMD5::hex_digest(char *s) const +void LLMD5::hex_digest(char* s) const { - int i; - if (!finalized) { - std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't "<< - "finalized the digest!" <<std::endl; + std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't " + << "finalized the digest!" << std::endl; s[0] = '\0'; return; } - for (i=0; i<16; i++) + for (int i = 0; i < 16; i++) { - sprintf(s+i*2, "%02x", digest[i]); /* Flawfinder: ignore */ + sprintf(s + i * 2, "%02x", digest[i]); /* Flawfinder: ignore */ } - s[32]='\0'; - - return; + s[32] = '\0'; } - - - - - -std::ostream& operator<<(std::ostream &stream, LLMD5 context) +std::ostream& operator<<(std::ostream& stream, const LLMD5& context) { char s[33]; /* Flawfinder: ignore */ context.hex_digest(s); @@ -320,7 +287,7 @@ bool operator==(const LLMD5& a, const LLMD5& b) unsigned char b_guts[16]; a.raw_digest(a_guts); b.raw_digest(b_guts); - if (memcmp(a_guts,b_guts,16)==0) + if (memcmp(a_guts, b_guts, 16) == 0) return true; else return false; @@ -328,30 +295,27 @@ bool operator==(const LLMD5& a, const LLMD5& b) bool operator!=(const LLMD5& a, const LLMD5& b) { - return !(a==b); + return !(a == b); } // PRIVATE METHODS: +void LLMD5::init() +{ + finalized = false; // we just started! -void LLMD5::init(){ - finalized=0; // we just started! - - // Nothing counted, so count=0 - count = 0; + // Nothing counted, so count=0 + count = 0; - // Load magic initialization constants. - state[0] = 0x67452301; - state[1] = 0xefcdab89; - state[2] = 0x98badcfe; - state[3] = 0x10325476; + // Load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; } - - // Constants for MD5Transform routine. // Although we could use C++ style constants, defines are actually better, // since they let us easily evade scope clashes. - #define S11 7 #define S12 12 #define S13 17 @@ -381,153 +345,144 @@ void LLMD5::init(){ /* ROTATE_LEFT rotates x left n bits. */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ -#define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - - +#define FF(a, b, c, d, x, s, ac) \ + { \ + (a) += F((b), (c), (d)) + (x) + (U32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + { \ + (a) += G((b), (c), (d)) + (x) + (U32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + { \ + (a) += H((b), (c), (d)) + (x) + (U32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + { \ + (a) += I((b), (c), (d)) + (x) + (U32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } // LLMD5 basic transformation. Transforms state based on block. -void LLMD5::transform (const U8 block[64]){ - - uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - decode (x, block, 64); - - assert(!finalized); // not just a user error, since the method is private - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - // Zeroize sensitive information. - memset ( (uint8_t *) x, 0, sizeof(x)); - +void LLMD5::transform(const U8 block[64]) +{ + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + decode(x, block, 64); + + assert(!finalized); // not just a user error, since the method is private + + /* Round 1 */ + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof(x)); } - - // Encodes input (uint32_t) into output (unsigned char). Assumes len is // a multiple of 4. -void LLMD5::encode (uint8_t *output, const uint32_t *input, const size_t len) { - - size_t i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (uint8_t) (input[i] & 0xff); - output[j+1] = (uint8_t) ((input[i] >> 8) & 0xff); - output[j+2] = (uint8_t) ((input[i] >> 16) & 0xff); - output[j+3] = (uint8_t) ((input[i] >> 24) & 0xff); - } +void LLMD5::encode(uint8_t* output, const uint32_t* input, const size_t len) +{ + for (size_t i = 0, j = 0; j < len; i++, j += 4) + { + output[j] = (uint8_t)(input[i] & 0xff); + output[j + 1] = (uint8_t)((input[i] >> 8) & 0xff); + output[j + 2] = (uint8_t)((input[i] >> 16) & 0xff); + output[j + 3] = (uint8_t)((input[i] >> 24) & 0xff); + } } - - - // Decodes input (unsigned char) into output (uint32_t). Assumes len is // a multiple of 4. -void LLMD5::decode (uint32_t *output, const uint8_t *input, const size_t len){ - - size_t i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | - (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24); +void LLMD5::decode(uint32_t* output, const uint8_t* input, const size_t len) +{ + for (size_t i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | + (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24); } - - diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index 46c79cf5a2..ad063fda46 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -67,59 +67,57 @@ documentation and/or software. */ -#include <cstdint> // uint32_t et al. +#include <cstdint> // uint32_t et al. // use for the raw digest output const int MD5RAW_BYTES = 16; // use for outputting hex digests -const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null +const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null const int MD5HEX_STR_BYTES = 32; // message system fixed size -class LL_COMMON_API LLMD5 { -// how many bytes to grab at a time when checking files - static const int BLOCK_LEN; +class LL_COMMON_API LLMD5 +{ + // how many bytes to grab at a time when checking files + static const int BLOCK_LEN; public: -// methods for controlled operation: - LLMD5 (); // simple initializer - void update (const uint8_t *input, const size_t input_length); - void update (std::istream& stream); - void update (FILE *file); - void update (const std::string& str); - void finalize (); - -// constructors for special circumstances. All these constructors finalize -// the MD5 context. - LLMD5 (const unsigned char *string); // digest string, finalize - LLMD5 (std::istream& stream); // digest stream, finalize - LLMD5 (FILE *file); // digest file, close, finalize - LLMD5 (const unsigned char *string, const unsigned int number); - -// methods to acquire finalized result - void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data - void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string - - friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 context); + // methods for controlled operation: + LLMD5(); // simple initializer + void update(const uint8_t* input, const size_t input_length); + void update(std::istream& stream); + void update(FILE* file); + void update(const std::string& str); + void finalize(); + + // constructors for special circumstances. All these constructors finalize + // the MD5 context. + LLMD5(const unsigned char* string); // digest string, finalize + LLMD5(std::istream& stream); // digest stream, finalize + LLMD5(FILE* file); // digest file, close, finalize + LLMD5(const unsigned char* string, const unsigned int number); + + // methods to acquire finalized result + void raw_digest(unsigned char* array) const; // provide 16-byte array for binary data + void hex_digest(char* string) const; // provide 33-byte array for ascii-hex string + + friend LL_COMMON_API std::ostream& operator<<(std::ostream&, const LLMD5& context); private: - - -// next, the private data: - uint32_t state[4]; - uint64_t count; // number of *bits*, mod 2^64 - uint8_t buffer[64]; // input buffer - uint8_t digest[16]; - uint8_t finalized; - -// last, the private methods, mostly static: - void init (); // called by all constructors - void transform (const uint8_t *buffer); // does the real update work. Note - // that length is implied to be 64. - - static void encode (uint8_t *dest, const uint32_t *src, const size_t length); - static void decode (uint32_t *dest, const uint8_t *src, const size_t length); - + // next, the private data: + uint32_t state[4]; + uint64_t count; // number of *bits*, mod 2^64 + uint8_t buffer[64]; // input buffer + uint8_t digest[16]; + bool finalized; + + // last, the private methods, mostly static: + void init(); // called by all constructors + void transform(const uint8_t* buffer); // does the real update work. Note + // that length is implied to be 64. + + static void encode(uint8_t* dest, const uint32_t* src, const size_t length); + static void decode(uint32_t* dest, const uint8_t* src, const size_t length); }; LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b); diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index 96ec94fe0f..392f235aad 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -42,6 +42,8 @@ LLFontVertexBuffer::~LLFontVertexBuffer() void LLFontVertexBuffer::reset() { + // Todo: some form of debug only frequecy check&assert to see if this is happening too often. + // Regenerating this list is expensive mBufferList.clear(); } diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 60b6115b34..66b274c33f 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -436,6 +436,9 @@ void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit { mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars)); } + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); if (all_selected) { @@ -617,6 +620,10 @@ void LLLineEditor::replaceWithSuggestion(U32 index) mText.insert(it->first, suggestion); setCursor(it->first + (S32)suggestion.length()); + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); + break; } } @@ -969,6 +976,10 @@ void LLLineEditor::removeChar() mText.erase(getCursor() - 1, 1); setCursor(getCursor() - 1); + + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); } else { @@ -992,6 +1003,10 @@ void LLLineEditor::addChar(const llwchar uni_char) return; mText.erase(getCursor(), 1); + + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); } S32 cur_bytes = static_cast<S32>(mText.getString().size()); @@ -1022,6 +1037,10 @@ void LLLineEditor::addChar(const llwchar uni_char) mText.insert(getCursor(), w_buf); setCursor(getCursor() + 1); + + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); } else { @@ -1186,6 +1205,10 @@ void LLLineEditor::deleteSelection() mText.erase(left_pos, selection_length); deselect(); setCursor(left_pos); + + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); } } @@ -1346,6 +1369,10 @@ void LLLineEditor::pasteHelper(bool is_primary) setCursor( getCursor() + (S32)clean_string.length() ); deselect(); + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); + // Validate new string and rollback the if needed. bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); if (need_to_rollback) @@ -1506,6 +1533,10 @@ bool LLLineEditor::handleSpecialKey(KEY key, MASK mask) { mText.assign(*(--mCurrentHistoryLine)); setCursorToEnd(); + + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); } else { @@ -1523,6 +1554,10 @@ bool LLLineEditor::handleSpecialKey(KEY key, MASK mask) { mText.assign( *(++mCurrentHistoryLine) ); setCursorToEnd(); + + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); } else { @@ -1897,7 +1932,8 @@ void LLLineEditor::draw() if( select_left > mScrollHPos ) { // unselected, left side - rendered_text = mGLFont->render( + rendered_text = mFontBufferPreSelection.render( + mGLFont, mText, mScrollHPos, rendered_pixels_right, text_bottom, text_color, @@ -1919,7 +1955,8 @@ void LLLineEditor::draw() gl_rect_2d(ll_round(rendered_pixels_right), cursor_top, ll_round(rendered_pixels_right)+width, cursor_bottom, color); LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ); - rendered_text += mGLFont->render( + rendered_text += mFontBufferSelection.render( + mGLFont, mText, mScrollHPos + rendered_text, rendered_pixels_right, text_bottom, tmp_color, @@ -1934,7 +1971,8 @@ void LLLineEditor::draw() if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) { // unselected, right side - rendered_text += mGLFont->render( + rendered_text += mFontBufferPostSelection.render( + mGLFont, mText, mScrollHPos + rendered_text, rendered_pixels_right, text_bottom, text_color, @@ -1948,7 +1986,8 @@ void LLLineEditor::draw() } else { - rendered_text = mGLFont->render( + rendered_text = mFontBufferPreSelection.render( + mGLFont, mText, mScrollHPos, rendered_pixels_right, text_bottom, text_color, @@ -2108,7 +2147,8 @@ void LLLineEditor::draw() //to give indication that it is not text you typed in if (0 == mText.length() && (mReadOnly || mShowLabelFocused)) { - mGLFont->render(mLabel.getWString(), 0, + mFontBufferLabel.render(mGLFont, + mLabel.getWString(), 0, (F32)mTextLeftEdge, (F32)text_bottom, label_color, LLFontGL::LEFT, @@ -2133,7 +2173,8 @@ void LLLineEditor::draw() // draw label if no text provided if (0 == mText.length()) { - mGLFont->render(mLabel.getWString(), 0, + mFontBufferLabel.render(mGLFont, + mLabel.getWString(), 0, (F32)mTextLeftEdge, (F32)text_bottom, label_color, LLFontGL::LEFT, @@ -2404,12 +2445,16 @@ void LLLineEditor::setKeystrokeCallback(callback_t callback, void* user_data) bool LLLineEditor::setTextArg( const std::string& key, const LLStringExplicit& text ) { mText.setArg(key, text); + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); return true; } bool LLLineEditor::setLabelArg( const std::string& key, const LLStringExplicit& text ) { mLabel.setArg(key, text); + mFontBufferLabel.reset(); return true; } @@ -2508,6 +2553,9 @@ void LLLineEditor::updatePreedit(const LLWString &preedit_string, mPreeditOverwrittenWString.clear(); } mText.insert(insert_preedit_at, mPreeditWString); + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); mPreeditStandouts = preedit_standouts; diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index cdd22413e7..12fe800acb 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -40,6 +40,7 @@ #include "llframetimer.h" #include "lleditmenuhandler.h" +#include "llfontvertexbuffer.h" #include "llspellcheckmenuhandler.h" #include "lluictrl.h" #include "lluiimage.h" @@ -344,6 +345,10 @@ protected: LLViewBorder* mBorder; const LLFontGL* mGLFont; + LLFontVertexBuffer mFontBufferPreSelection; + LLFontVertexBuffer mFontBufferSelection; + LLFontVertexBuffer mFontBufferPostSelection; + LLFontVertexBuffer mFontBufferLabel; S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes S32 mMaxLengthChars; // Maximum number of characters in the string S32 mCursorPos; // I-beam is just after the mCursorPos-th character. diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 0aebf7543c..615619d244 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -948,7 +948,6 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) { - beforeValueChange(); segment_set_t::iterator seg_iter = getSegIterContaining(pos); while(seg_iter != mSegments.end()) @@ -1325,6 +1324,7 @@ void LLTextBase::reshape(S32 width, S32 height, bool called_from_parent) //virtual void LLTextBase::draw() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; // reflow if needed, on demand reflow(); @@ -2586,6 +2586,11 @@ const LLWString& LLTextBase::getWText() const return getViewModel()->getDisplay(); } +S32 LLTextBase::getTextGeneration() const +{ + return getViewModel()->getDisplayGeneration(); +} + // If round is true, if the position is on the right half of a character, the cursor // will be put to its right. If round is false, the cursor will always be put to the // character's left. @@ -3280,7 +3285,8 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e : LLTextSegment(start, end), mStyle( style ), mToken(NULL), - mEditor(editor) + mEditor(editor), + mLastGeneration(-1) { mFontHeight = mStyle->getFont()->getLineHeight(); @@ -3294,7 +3300,8 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e LLNormalTextSegment::LLNormalTextSegment( const LLUIColor& color, S32 start, S32 end, LLTextBase& editor, bool is_visible) : LLTextSegment(start, end), mToken(NULL), - mEditor(editor) + mEditor(editor), + mLastGeneration(-1) { mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color)); @@ -3313,25 +3320,42 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec { return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect); } + else + { + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); + } return draw_rect.mLeft; } // Draws a single text segment, reversing the color for selection if needed. F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRectf rect) { - F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha; - - const LLWString &text = getWText(); - F32 right_x = rect.mLeft; if (!mStyle->isVisible()) { return right_x; } + F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha; + + const LLWString& text = getWText(); + S32 text_gen = mEditor.getTextGeneration(); + bool is_text_read_only = mEditor.getReadOnly(); + + if (text_gen != mLastGeneration) + { + mLastGeneration = text_gen; + + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); + } + const LLFontGL* font = mStyle->getFont(); - LLColor4 color = (mEditor.getReadOnly() ? mStyle->getReadOnlyColor() : mStyle->getColor()) % (alpha * mStyle->getAlpha()); + LLColor4 color = (is_text_read_only ? mStyle->getReadOnlyColor() : mStyle->getColor()) % (alpha * mStyle->getAlpha()); if( selection_start > seg_start ) { @@ -3339,16 +3363,40 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 start = seg_start; S32 end = llmin( selection_start, seg_end ); S32 length = end - start; - font->render(text, start, - rect, - color, - LLFontGL::LEFT, mEditor.mTextVAlign, - LLFontGL::NORMAL, - mStyle->getShadowType(), - length, - &right_x, - mEditor.getUseEllipses(), - mEditor.getUseColor()); + if (is_text_read_only) + { + mFontBufferPreSelection.render( + font, + text, start, + rect, + color, + LLFontGL::LEFT, mEditor.mTextVAlign, + LLFontGL::NORMAL, + mStyle->getShadowType(), + length, + &right_x, + mEditor.getUseEllipses(), + mEditor.getUseColor()); + } + else + { + // Font buffer doesn't do well with changes and huge notecard with a bunch + // of segments will see a lot of buffer updates, so instead use derect + // rendering to cache. + // Todo: instead of mLastGeneration make buffer invalidation more fine grained + // like string hash of a given segment. + font->render( + text, start, + rect, + color, + LLFontGL::LEFT, mEditor.mTextVAlign, + LLFontGL::NORMAL, + mStyle->getShadowType(), + length, + &right_x, + mEditor.getUseEllipses(), + mEditor.getUseColor()); + } } rect.mLeft = right_x; @@ -3359,16 +3407,35 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 end = llmin( selection_end, seg_end ); S32 length = end - start; - font->render(text, start, - rect, - mStyle->getSelectedColor().get(), - LLFontGL::LEFT, mEditor.mTextVAlign, - LLFontGL::NORMAL, - LLFontGL::NO_SHADOW, - length, - &right_x, - mEditor.getUseEllipses(), - mEditor.getUseColor()); + if (is_text_read_only) + { + mFontBufferSelection.render( + font, + text, start, + rect, + mStyle->getSelectedColor().get(), + LLFontGL::LEFT, mEditor.mTextVAlign, + LLFontGL::NORMAL, + LLFontGL::NO_SHADOW, + length, + &right_x, + mEditor.getUseEllipses(), + mEditor.getUseColor()); + } + else + { + font->render( + text, start, + rect, + mStyle->getSelectedColor().get(), + LLFontGL::LEFT, mEditor.mTextVAlign, + LLFontGL::NORMAL, + LLFontGL::NO_SHADOW, + length, + &right_x, + mEditor.getUseEllipses(), + mEditor.getUseColor()); + } } rect.mLeft = right_x; if( selection_end < seg_end ) @@ -3377,16 +3444,36 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 start = llmax( selection_end, seg_start ); S32 end = seg_end; S32 length = end - start; - font->render(text, start, - rect, - color, - LLFontGL::LEFT, mEditor.mTextVAlign, - LLFontGL::NORMAL, - mStyle->getShadowType(), - length, - &right_x, - mEditor.getUseEllipses(), - mEditor.getUseColor()); + if (is_text_read_only) + { + mFontBufferPostSelection.render( + font, + text, start, + rect, + color, + LLFontGL::LEFT, mEditor.mTextVAlign, + LLFontGL::NORMAL, + mStyle->getShadowType(), + length, + &right_x, + mEditor.getUseEllipses(), + mEditor.getUseColor()); + } + else + { + font->render( + text, start, + rect, + color, + LLFontGL::LEFT, mEditor.mTextVAlign, + LLFontGL::NORMAL, + mStyle->getShadowType(), + length, + &right_x, + mEditor.getUseEllipses(), + mEditor.getUseColor()); + + } } return right_x; } @@ -3573,6 +3660,15 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin return num_chars; } +void LLNormalTextSegment::updateLayout(const class LLTextBase& editor) +{ + LLTextSegment::updateLayout(editor); + + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); +} + void LLNormalTextSegment::dump() const { LL_INFOS() << "Segment [" << diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 00cf66b134..e2981c2637 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -30,6 +30,7 @@ #include "v4color.h" #include "lleditmenuhandler.h" +#include "llfontvertexbuffer.h" #include "llspellcheckmenuhandler.h" #include "llstyle.h" #include "llkeywords.h" @@ -131,6 +132,7 @@ public: /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const; /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const; + /*virtual*/ void updateLayout(const class LLTextBase& editor); /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); /*virtual*/ bool canEdit() const { return true; } /*virtual*/ const LLUIColor& getColor() const { return mStyle->getColor(); } @@ -161,6 +163,12 @@ protected: LLKeywordToken* mToken; std::string mTooltip; boost::signals2::connection mImageLoadedConnection; + + // font rendering + LLFontVertexBuffer mFontBufferPreSelection; + LLFontVertexBuffer mFontBufferSelection; + LLFontVertexBuffer mFontBufferPostSelection; + S32 mLastGeneration = -1; }; // This text segment is the same as LLNormalTextSegment, the only difference @@ -432,6 +440,7 @@ public: // wide-char versions void setWText(const LLWString& text); const LLWString& getWText() const; + S32 getTextGeneration() const; void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params()); diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp index 93106b344f..35963c2b99 100644 --- a/indra/llui/llviewmodel.cpp +++ b/indra/llui/llviewmodel.cpp @@ -82,11 +82,20 @@ void LLTextViewModel::setValue(const LLSD& value) // approximate LLSD storage usage LLViewModel::setValue(value); mDisplay = utf8str_to_wstring(mStringValue = value.asString()); + mDisplayGeneration++; // mDisplay and mValue agree mUpdateFromDisplay = false; } +LLWString& LLTextViewModel::getEditableDisplay() +{ + mDirty = true; + mDisplayGeneration++; + mUpdateFromDisplay = true; + return mDisplay; +} + void LLTextViewModel::setDisplay(const LLWString& value) { // This is the strange way to alter the value. Normally we'd setValue() @@ -94,6 +103,7 @@ void LLTextViewModel::setDisplay(const LLWString& value) // value. But a text editor might want to edit the display string // directly, then convert back to UTF8 on commit. mDisplay = value; + mDisplayGeneration++; mDirty = true; // Don't immediately convert to UTF8 -- do it lazily -- we expect many // more setDisplay() calls than getValue() calls. Just flag that it needs diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index 6cf2200a81..16b0800ce2 100644 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -105,7 +105,8 @@ public: // New functions /// Get the stored value in string form const LLWString& getDisplay() const { return mDisplay; } - LLWString& getEditableDisplay() { mDirty = true; mUpdateFromDisplay = true; return mDisplay; } + S32 getDisplayGeneration() const { return mDisplayGeneration; } + LLWString& getEditableDisplay(); /** * Set the display string directly (see LLTextEditor). What the user is @@ -120,6 +121,7 @@ private: /// To avoid converting every widget's stored value from LLSD to LLWString /// every frame, cache the converted value LLWString mDisplay; + S32 mDisplayGeneration = -1; /// As the user edits individual characters (setDisplay()), defer /// LLWString-to-UTF8 conversions until s/he's done. diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 2466ee5973..0c068ff993 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -963,59 +963,87 @@ void LLPanelMainInventory::draw() void LLPanelMainInventory::updateItemcountText() { - if(mItemCount != gInventory.getItemCount()) - { - mItemCount = gInventory.getItemCount(); - mItemCountString = ""; - LLLocale locale(LLLocale::USER_LOCALE); - LLResMgr::getInstance()->getIntegerString(mItemCountString, mItemCount); - } - - if(mCategoryCount != gInventory.getCategoryCount()) + bool update = false; + if (mSingleFolderMode) { - mCategoryCount = gInventory.getCategoryCount(); - mCategoryCountString = ""; - LLLocale locale(LLLocale::USER_LOCALE); - LLResMgr::getInstance()->getIntegerString(mCategoryCountString, mCategoryCount); - } - - LLStringUtil::format_map_t string_args; - string_args["[ITEM_COUNT]"] = mItemCountString; - string_args["[CATEGORY_COUNT]"] = mCategoryCountString; - string_args["[FILTER]"] = getFilterText(); + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; - std::string text = ""; + gInventory.getDirectDescendentsOf(getCurrentSFVRoot(), cats, items); + S32 item_count = items ? (S32)items->size() : 0; + S32 cat_count = cats ? (S32)cats->size() : 0; - if (LLInventoryModelBackgroundFetch::instance().folderFetchActive()) - { - text = getString("ItemcountFetching", string_args); + if (mItemCount != item_count) + { + mItemCount = item_count; + update = true; + } + if (mCategoryCount != cat_count) + { + mCategoryCount = cat_count; + update = true; + } } - else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) + else { - text = getString("ItemcountCompleted", string_args); + if (mItemCount != gInventory.getItemCount()) + { + mItemCount = gInventory.getItemCount(); + update = true; + } + + if (mCategoryCount != gInventory.getCategoryCount()) + { + mCategoryCount = gInventory.getCategoryCount(); + update = true; + } } - else + + if (mLastFilterText != getFilterText()) { - text = getString("ItemcountUnknown", string_args); + mLastFilterText = getFilterText(); + update = true; } - if (mSingleFolderMode) + if (update) { - LLInventoryModel::cat_array_t *cats; - LLInventoryModel::item_array_t *items; + mItemCountString = ""; + LLLocale locale(LLLocale::USER_LOCALE); + LLResMgr::getInstance()->getIntegerString(mItemCountString, mItemCount); - gInventory.getDirectDescendentsOf(getCurrentSFVRoot(), cats, items); + mCategoryCountString = ""; + LLResMgr::getInstance()->getIntegerString(mCategoryCountString, mCategoryCount); - if (items && cats) + LLStringUtil::format_map_t string_args; + string_args["[ITEM_COUNT]"] = mItemCountString; + string_args["[CATEGORY_COUNT]"] = mCategoryCountString; + string_args["[FILTER]"] = mLastFilterText; + + std::string text = ""; + + if (mSingleFolderMode) { - string_args["[ITEM_COUNT]"] = llformat("%d", items->size()); - string_args["[CATEGORY_COUNT]"] = llformat("%d", cats->size()); text = getString("ItemcountCompleted", string_args); } - } + else + { + if (LLInventoryModelBackgroundFetch::instance().folderFetchActive()) + { + text = getString("ItemcountFetching", string_args); + } + else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) + { + text = getString("ItemcountCompleted", string_args); + } + else + { + text = getString("ItemcountUnknown", string_args); + } + } - mCounterCtrl->setValue(text); - mCounterCtrl->setToolTip(text); + mCounterCtrl->setValue(text); + mCounterCtrl->setToolTip(text); + } } void LLPanelMainInventory::onFocusReceived() diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 3347ab904b..d28daddd73 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -196,9 +196,10 @@ private: LLSaveFolderState* mSavedFolderState; std::string mFilterText; std::string mFilterSubString; - S32 mItemCount; + S32 mItemCount = 0; + std::string mLastFilterText; std::string mItemCountString; - S32 mCategoryCount; + S32 mCategoryCount = 0; std::string mCategoryCountString; LLComboBox* mSearchTypeCombo; diff --git a/indra/newview/skins/default/textures/map_avatar_you_32.tga b/indra/newview/skins/default/textures/map_avatar_you_32.tga Binary files differindex 782207efd6..84b57aceaf 100644 --- a/indra/newview/skins/default/textures/map_avatar_you_32.tga +++ b/indra/newview/skins/default/textures/map_avatar_you_32.tga |