ReactOS 0.4.17-dev-470-gf9e3448
text.c
Go to the documentation of this file.
1/*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19/*
20 * PROJECT: ReactOS user32.dll
21 * FILE: win32ss/user/rtl/text.c
22 * PURPOSE: Draw Text
23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
24 * UPDATE HISTORY:
25 * 09-05-2001 CSH Created
26 */
27
28/* INCLUDES ******************************************************************/
29
30#ifdef _WIN32K_
31#include <win32k.h>
32DBG_DEFAULT_CHANNEL(UserMenu);
33#else
34#include <user32.h>
35#include <wine/debug.h>
37#endif
38
39/* FUNCTIONS *****************************************************************/
40
41#ifndef NDEBUG
42
43#ifdef assert
44#undef assert
45#endif
46
47#define assert(e) ((e) ? (void)0 : _font_assert(#e, __FILE__, __LINE__))
48
49#else
50#include <assert.h>
51
52#endif
53
54void _font_assert(const char *msg, const char *file, int line)
55{
56 /* Assertion failed at foo.c line 45: x<y */
57 DbgPrint("Assertion failed at %s line %d: %s\n", file, line, msg);
58#ifdef _WIN32K_
60#else
61 ExitProcess(3);
62 for(;;); /* eliminate warning by mingw */
63#endif
64}
65
66/*********************************************************************
67 *
68 * DrawText functions
69 *
70 * Copied from Wine.
71 * Copyright 1993, 1994 Alexandre Julliard
72 * Copyright 2002 Bill Medland
73 *
74 * Design issues
75 * How many buffers to use
76 * While processing in DrawText there are potentially three different forms
77 * of the text that need to be held. How are they best held?
78 * 1. The original text is needed, of course, to see what to display.
79 * 2. The text that will be returned to the user if the DT_MODIFYSTRING is
80 * in effect.
81 * 3. The buffered text that is about to be displayed e.g. the current line.
82 * Typically this will exclude the ampersands used for prefixing etc.
83 *
84 * Complications.
85 * a. If the buffered text to be displayed includes the ampersands then
86 * we will need special measurement and draw functions that will ignore
87 * the ampersands (e.g. by copying to a buffer without the prefix and
88 * then using the normal forms). This may involve less space but may
89 * require more processing. e.g. since a line containing tabs may
90 * contain several underlined characters either we need to carry around
91 * a list of prefix locations or we may need to locate them several
92 * times.
93 * b. If we actually directly modify the "original text" as we go then we
94 * will need some special "caching" to handle the fact that when we
95 * ellipsify the text the ellipsis may modify the next line of text,
96 * which we have not yet processed. (e.g. ellipsification of a W at the
97 * end of a line will overwrite the W, the \n and the first character of
98 * the next line, and a \0 will overwrite the second. Try it!!)
99 *
100 * Option 1. Three separate storages. (To be implemented)
101 * If DT_MODIFYSTRING is in effect then allocate an extra buffer to hold
102 * the edited string in some form, either as the string itself or as some
103 * sort of "edit list" to be applied just before returning.
104 * Use a buffer that holds the ellipsified current line sans ampersands
105 * and accept the need occasionally to recalculate the prefixes (if
106 * DT_EXPANDTABS and not DT_NOPREFIX and not DT_HIDEPREFIX)
107 */
108
109#define TAB 9
110#define LF 10
111#define CR 13
112#define SPACE 32
113#define PREFIX 38
114#define ALPHA_PREFIX 30 /* Win16: Alphabet prefix */
115#define KANA_PREFIX 31 /* Win16: Katakana prefix */
116
117#define FORWARD_SLASH '/'
118#define BACK_SLASH '\\'
119
120static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
121
122typedef struct tag_ellipsis_data
123{
125 int len;
126 int under;
127 int after;
129
130/*********************************************************************
131 * TEXT_Ellipsify (static)
132 *
133 * Add an ellipsis to the end of the given string whilst ensuring it fits.
134 *
135 * If the ellipsis alone doesn't fit then it will be returned anyway.
136 *
137 * See Also TEXT_PathEllipsify
138 *
139 * Arguments
140 * hdc [in] The handle to the DC that defines the font.
141 * str [in/out] The string that needs to be modified.
142 * max_str [in] The dimension of str (number of WCHAR).
143 * len_str [in/out] The number of characters in str
144 * width [in] The maximum width permitted (in logical coordinates)
145 * size [out] The dimensions of the text
146 * modstr [out] The modified form of the string, to be returned to the
147 * calling program. It is assumed that the caller has
148 * made sufficient space available so we don't need to
149 * know the size of the space. This pointer may be NULL if
150 * the modified string is not required.
151 * len_before [out] The number of characters before the ellipsis.
152 * len_ellip [out] The number of characters in the ellipsis.
153 *
154 * See for example Microsoft article Q249678.
155 *
156 * For now we will simply use three dots rather than worrying about whether
157 * the font contains an explicit ellipsis character.
158 */
159static void TEXT_Ellipsify (HDC hdc, WCHAR *str, unsigned int max_len,
160 unsigned int *len_str, int width, SIZE *size,
161 WCHAR *modstr,
162 int *len_before, int *len_ellip)
163{
164 unsigned int len_ellipsis;
165 unsigned int lo, mid, hi;
166 len_ellipsis = strlenW (ELLIPSISW);
167 if (len_ellipsis > max_len) len_ellipsis = max_len;
168 if (*len_str > max_len - len_ellipsis)
169 *len_str = max_len - len_ellipsis;
170
171 /* First do a quick binary search to get an upper bound for *len_str. */
172 if (*len_str > 0 &&
173#ifdef _WIN32K_
174 GreGetTextExtentExW(hdc, str, *len_str, width, NULL, NULL, size, 0) &&
175#else
176 GetTextExtentExPointW(hdc, str, *len_str, width, NULL, NULL, size) &&
177#endif
178 size->cx > width)
179 {
180 for (lo = 0, hi = *len_str; lo < hi; )
181 {
182 mid = (lo + hi) / 2;
183#ifdef _WIN32K_
184 if (!GreGetTextExtentExW(hdc, str, mid, width, NULL, NULL, size, 0))
185#else
187#endif
188 break;
189 if (size->cx > width)
190 hi = mid;
191 else
192 lo = mid + 1;
193 }
194 *len_str = hi;
195 }
196 /* Now this should take only a couple iterations at most. */
197 for ( ; ; )
198 {
199 memcpy(str + *len_str, ELLIPSISW, len_ellipsis*sizeof(WCHAR));
200#ifdef _WIN32K_
201 if (!GreGetTextExtentExW (hdc, str, *len_str + len_ellipsis, width,
202 NULL, NULL, size, 0)) break;
203#else
204 if (!GetTextExtentExPointW (hdc, str, *len_str + len_ellipsis, width,
205 NULL, NULL, size)) break;
206#endif
207 if (!*len_str || size->cx <= width) break;
208
209 (*len_str)--;
210 }
211 *len_ellip = len_ellipsis;
212 *len_before = *len_str;
213 *len_str += len_ellipsis;
214
215 if (modstr)
216 {
217 memcpy (modstr, str, *len_str * sizeof(WCHAR));
218 modstr[*len_str] = '\0';
219 }
220}
221
222/*********************************************************************
223 * TEXT_PathEllipsify (static)
224 *
225 * Add an ellipsis to the provided string in order to make it fit within
226 * the width. The ellipsis is added as specified for the DT_PATH_ELLIPSIS
227 * flag.
228 *
229 * See Also TEXT_Ellipsify
230 *
231 * Arguments
232 * hdc [in] The handle to the DC that defines the font.
233 * str [in/out] The string that needs to be modified
234 * max_str [in] The dimension of str (number of WCHAR).
235 * len_str [in/out] The number of characters in str
236 * width [in] The maximum width permitted (in logical coordinates)
237 * size [out] The dimensions of the text
238 * modstr [out] The modified form of the string, to be returned to the
239 * calling program. It is assumed that the caller has
240 * made sufficient space available so we don't need to
241 * know the size of the space. This pointer may be NULL if
242 * the modified string is not required.
243 * pellip [out] The ellipsification results
244 *
245 * For now we will simply use three dots rather than worrying about whether
246 * the font contains an explicit ellipsis character.
247 *
248 * The following applies, I think to Win95. We will need to extend it for
249 * Win98 which can have both path and end ellipsis at the same time (e.g.
250 * C:\MyLongFileName.Txt becomes ...\MyLongFileN...)
251 *
252 * The resulting string consists of as much as possible of the following:
253 * 1. The ellipsis itself
254 * 2. The last \ or / of the string (if any)
255 * 3. Everything after the last \ or / of the string (if any) or the whole
256 * string if there is no / or \. I believe that under Win95 this would
257 * include everything even though some might be clipped off the end whereas
258 * under Win98 that might be ellipsified too.
259 * Yet to be investigated is whether this would include wordbreaking if the
260 * filename is more than 1 word and splitting if DT_EDITCONTROL was in
261 * effect. (If DT_EDITCONTROL is in effect then on occasions text will be
262 * broken within words).
263 * 4. All the stuff before the / or \, which is placed before the ellipsis.
264 */
265static void TEXT_PathEllipsify (HDC hdc, WCHAR *str, unsigned int max_len,
266 unsigned int *len_str, int width, SIZE *size,
267 WCHAR *modstr, ellipsis_data *pellip)
268{
269 int len_ellipsis;
270 int len_trailing;
271 int len_under;
272 WCHAR *lastBkSlash, *lastFwdSlash, *lastSlash;
273 len_ellipsis = strlenW (ELLIPSISW);
274 if (!max_len) return;
275 if (len_ellipsis >= max_len) len_ellipsis = max_len - 1;
276 if (*len_str + len_ellipsis >= max_len)
277 *len_str = max_len - len_ellipsis-1;
278 /* Hopefully this will never happen, otherwise it would probably lose
279 * the wrong character
280 */
281 str[*len_str] = '\0'; /* to simplify things */
282#ifdef _WIN32K_
283 lastBkSlash = wcsrchr (str, BACK_SLASH);
284 lastFwdSlash = wcsrchr (str, FORWARD_SLASH);
285#else
286 lastBkSlash = strrchrW (str, BACK_SLASH);
287 lastFwdSlash = strrchrW (str, FORWARD_SLASH);
288#endif
289 lastSlash = lastBkSlash > lastFwdSlash ? lastBkSlash : lastFwdSlash;
290#ifdef __REACTOS__
291 if (!lastSlash) lastSlash = str + *len_str;
292#else
293 if (!lastSlash) lastSlash = str;
294#endif
295 len_trailing = *len_str - (lastSlash - str);
296
297 /* overlap-safe movement to the right */
298 memmove (lastSlash+len_ellipsis, lastSlash, len_trailing * sizeof(WCHAR));
299 memcpy (lastSlash, ELLIPSISW, len_ellipsis*sizeof(WCHAR));
300 len_trailing += len_ellipsis;
301 /* From this point on lastSlash actually points to the ellipsis in front
302 * of the last slash and len_trailing includes the ellipsis
303 */
304
305 len_under = 0;
306 for ( ; ; )
307 {
308#ifdef _WIN32K_
309 if (!GreGetTextExtentExW (hdc, str, *len_str + len_ellipsis, width,
310 NULL, NULL, size, 0)) break;
311#else
312 if (!GetTextExtentExPointW (hdc, str, *len_str + len_ellipsis, width,
313 NULL, NULL, size)) break;
314#endif
315 if (lastSlash == str || size->cx <= width) break;
316
317 /* overlap-safe movement to the left */
318 memmove (lastSlash-1, lastSlash, len_trailing * sizeof(WCHAR));
319 lastSlash--;
320 len_under++;
321
322 assert (*len_str);
323 (*len_str)--;
324 }
325 pellip->before = lastSlash-str;
326 pellip->len = len_ellipsis;
327 pellip->under = len_under;
328 pellip->after = len_trailing - len_ellipsis;
329 *len_str += len_ellipsis;
330
331 if (modstr)
332 {
333 memcpy(modstr, str, *len_str * sizeof(WCHAR));
334 modstr[*len_str] = '\0';
335 }
336}
337
338/* Check the character is Chinese, Japanese, Korean and/or Thai */
340{
341 if (0x0E00 <= wch && wch <= 0x0E7F)
342 return TRUE; /* Thai */
343
344 if (0x3000 <= wch && wch <= 0x9FFF)
345 return TRUE; /* CJK */
346
347 if (0xAC00 <= wch && wch <= 0xD7FF)
348 return TRUE; /* Korean */
349
350 if (0xFF00 <= wch && wch <= 0xFFEF)
351 return TRUE; /* CJK */
352
353 return FALSE;
354}
355
356/* See http://en.wikipedia.org/wiki/Kinsoku_shori */
357static const WCHAR KinsokuClassA[] =
358{
359 0x2010, 0x2013, 0x2019, 0x201D, 0x203C, 0x2047, 0x2048, 0x2049, 0x3001,
360 0x3002, 0x3005, 0x3009, 0x300B, 0x300D, 0x300F, 0x3011, 0x3015, 0x3017,
361 0x3019, 0x301C, 0x301F, 0x303B, 0x3041, 0x3043, 0x3045, 0x3047, 0x3049,
362 0x3063, 0x3083, 0x3085, 0x3087, 0x308E, 0x3095, 0x3096, 0x30A0, 0x30A1,
363 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30C3, 0x30E3, 0x30E5, 0x30E7, 0x30EE,
364 0x30F5, 0x30F6, 0x30FB, 0x30FC, 0x30FD, 0x30FE, 0x31F0, 0x31F1, 0x31F2,
365 0x31F3, 0x31F4, 0x31F5, 0x31F6, 0x31F7, 0x31F8, 0x31F9, 0x31FA, 0x31FB,
366 0x31FC, 0x31FD, 0x31FE, 0x31FF, 0xFF01, 0xFF09, 0xFF0C, 0xFF0E, 0xFF1A,
367 0xFF1B, 0xFF1F, 0xFF3D, 0xFF5D, 0xFF60, 0
368};
369
370/*********************************************************************
371 * TEXT_WordBreak (static)
372 *
373 * Perform wordbreak processing on the given string
374 *
375 * Assumes that DT_WORDBREAK has been specified and not all the characters
376 * fit. Note that this function should even be called when the first character
377 * that doesn't fit is known to be a space or tab, so that it can swallow them.
378 *
379 * Note that the Windows processing has some strange properties.
380 * 1. If the text is left-justified and there is room for some of the spaces
381 * that follow the last word on the line then those that fit are included on
382 * the line.
383 * 2. If the text is centred or right-justified and there is room for some of
384 * the spaces that follow the last word on the line then all but one of those
385 * that fit are included on the line.
386 * 3. (Reasonable behaviour) If the word breaking causes a space to be the first
387 * character of a new line it will be skipped.
388 *
389 * Arguments
390 * hdc [in] The handle to the DC that defines the font.
391 * str [in/out] The string that needs to be broken.
392 * max_str [in] The dimension of str (number of WCHAR).
393 * len_str [in/out] The number of characters in str
394 * width [in] The maximum width permitted
395 * format [in] The format flags in effect
396 * chars_fit [in] The maximum number of characters of str that are already
397 * known to fit; chars_fit+1 is known not to fit.
398 * chars_used [out] The number of characters of str that have been "used" and
399 * do not need to be included in later text. For example this will
400 * include any spaces that have been discarded from the start of
401 * the next line.
402 * size [out] The size of the returned text in logical coordinates
403 *
404 * Pedantic assumption - Assumes that the text length is monotonically
405 * increasing with number of characters (i.e. no weird kernings)
406 *
407 * Algorithm
408 *
409 * Work back from the last character that did fit to either a space or the last
410 * character of a word, whichever is met first.
411 * If there was one or the first character didn't fit then
412 * If the text is centred or right justified and that one character was a
413 * space then break the line before that character
414 * Otherwise break the line after that character
415 * and if the next character is a space then discard it.
416 * Suppose there was none (and the first character did fit).
417 * If Break Within Word is permitted
418 * break the word after the last character that fits (there must be
419 * at least one; none is caught earlier).
420 * Otherwise
421 * discard any trailing space.
422 * include the whole word; it may be ellipsified later
423 *
424 * Break Within Word is permitted under a set of circumstances that are not
425 * totally clear yet. Currently our best guess is:
426 * If DT_EDITCONTROL is in effect and neither DT_WORD_ELLIPSIS nor
427 * DT_PATH_ELLIPSIS is
428 */
429
430static void TEXT_WordBreak (HDC hdc, WCHAR *str, unsigned int max_str,
431 unsigned int *len_str,
432 int width, int format, unsigned int chars_fit,
433 unsigned int *chars_used, SIZE *size)
434{
435 WCHAR *p;
436 int word_fits;
438 assert (chars_fit < *len_str);
439
440 /* Work back from the last character that did fit to either a space or the
441 * last character of a word, whichever is met first.
442 */
443 p = str + chars_fit; /* The character that doesn't fit */
444 word_fits = TRUE;
445 if (!chars_fit)
446 word_fits = FALSE;
447 else if (*p == SPACE) /* chars_fit < *len_str so this is valid */
448 p--; /* the word just fitted */
449 else
450 {
451 while (p > str && *(--p) != SPACE && (!IsCJKT(p[1]) ||
452 p[1] == L'\0' || wcschr(KinsokuClassA, p[1]) != NULL))
453 ;
454 word_fits = (p != str || *p == SPACE || IsCJKT(p[1]));
455 }
456 /* If there was one. */
457 if (word_fits)
458 {
459 int next_is_space;
460 /* break the line before/after that character */
461 if (!(format & (DT_RIGHT | DT_CENTER)) || *p != SPACE)
462 p++;
463 next_is_space = (unsigned int) (p - str) < *len_str && *p == SPACE;
464 *len_str = p - str;
465 /* and if the next character is a space then discard it. */
466 *chars_used = *len_str;
467 if (next_is_space)
468 (*chars_used)++;
469 }
470 /* Suppose there was none. */
471 else
472 {
475 {
476 /* break the word after the last character that fits (there must be
477 * at least one). */
478 if (!chars_fit)
479 ++chars_fit;
480 *len_str = chars_fit;
481 *chars_used = chars_fit;
482
483 /* FIXME - possible error. Since the next character is now removed
484 * this could make the text longer so that it no longer fits, and
485 * so we need a loop to test and shrink.
486 */
487 }
488 /* Otherwise */
489 else
490 {
491 /* discard any trailing space. */
492 const WCHAR *e = str + *len_str;
493 p = str + chars_fit;
494 while (p < e && *p != SPACE)
495 p++;
496 *chars_used = p - str;
497 if (p < e) /* i.e. loop failed because *p == SPACE */
498 (*chars_used)++;
499
500 /* include the whole word; it may be ellipsified later */
501 *len_str = p - str;
502 /* Possible optimisation; if DT_WORD_ELLIPSIS only use chars_fit+1
503 * so that it will be too long
504 */
505 }
506 }
507 /* Remeasure the string */
508#ifdef _WIN32K_
509 GreGetTextExtentExW (hdc, str, *len_str, 0, NULL, NULL, size, 0);
510#else
511 GetTextExtentExPointW (hdc, str, *len_str, 0, NULL, NULL, size);
512#endif
513}
514
515/*********************************************************************
516 * TEXT_SkipChars
517 *
518 * Skip over the given number of characters, bearing in mind prefix
519 * substitution and the fact that a character may take more than one
520 * WCHAR (Unicode surrogates are two words long) (and there may have been
521 * a trailing &)
522 *
523 * Parameters
524 * new_count [out] The updated count
525 * new_str [out] The updated pointer
526 * start_count [in] The count of remaining characters corresponding to the
527 * start of the string
528 * start_str [in] The starting point of the string
529 * max [in] The number of characters actually in this segment of the
530 * string (the & counts)
531 * n [in] The number of characters to skip (if prefix then
532 * &c counts as one)
533 * prefix [in] Apply prefix substitution
534 *
535 * Return Values
536 * none
537 *
538 * Remarks
539 * There must be at least n characters in the string
540 * We need max because the "line" may have ended with a & followed by a tab
541 * or newline etc. which we don't want to swallow
542 */
543
544static void TEXT_SkipChars (int *new_count, const WCHAR **new_str,
545 int start_count, const WCHAR *start_str,
546 int max, int n, int prefix)
547{
548 /* This is specific to wide characters, MSDN doesn't say anything much
549 * about Unicode surrogates yet and it isn't clear if _wcsinc will
550 * correctly handle them so we'll just do this the easy way for now
551 */
552
553 if (prefix)
554 {
555 const WCHAR *str_on_entry = start_str;
556 assert (max >= n);
557 max -= n;
558 while (n--)
559 {
560 if ((*start_str == PREFIX || *start_str == ALPHA_PREFIX) && max--)
561 start_str++;
562 start_str++;
563 }
564 start_count -= (start_str - str_on_entry);
565 }
566 else
567 {
568 start_str += n;
569 start_count -= n;
570 }
571 *new_str = start_str;
572 *new_count = start_count;
573}
574
575/*********************************************************************
576 * TEXT_Reprefix
577 *
578 * Reanalyse the text to find the prefixed character. This is called when
579 * wordbreaking or ellipsification has shortened the string such that the
580 * previously noted prefixed character is no longer visible.
581 *
582 * Parameters
583 * str [in] The original string segment (including all characters)
584 * ns [in] The number of characters in str (including prefixes)
585 * pe [in] The ellipsification data
586 *
587 * Return Values
588 * The prefix offset within the new string segment (the one that contains the
589 * ellipses and does not contain the prefix characters) (-1 if none)
590 */
591
592static int TEXT_Reprefix (const WCHAR *str, unsigned int ns,
593 const ellipsis_data *pe)
594{
595 int result = -1;
596 unsigned int i;
597 unsigned int n = pe->before + pe->under + pe->after;
598 assert (n <= ns);
599 for (i = 0; i < n; i++, str++)
600 {
601 if (i == (unsigned int) pe->before)
602 {
603 /* Reached the path ellipsis; jump over it */
604 if (ns < (unsigned int) pe->under) break;
605 str += pe->under;
606 ns -= pe->under;
607 i += pe->under;
608 if (!pe->after) break; /* Nothing after the path ellipsis */
609 }
610 if (!ns) break;
611 ns--;
612 if (*str++ == PREFIX || *str == ALPHA_PREFIX)
613 {
614 str++;
615 if (!ns) break;
616 if (*str != PREFIX)
617 result = (i < (unsigned int) pe->before || pe->under == 0) ? i : i - pe->under + pe->len;
618 /* pe->len may be non-zero while pe_under is zero */
619 ns--;
620 }
621 }
622 return result;
623}
624
625/*********************************************************************
626 * Returns true if and only if the remainder of the line is a single
627 * newline representation or nothing
628 */
629
630static int remainder_is_none_or_newline (int num_chars, const WCHAR *str)
631{
632 if (!num_chars) return TRUE;
633 if (*str != LF && *str != CR) return FALSE;
634 if (!--num_chars) return TRUE;
635 if (*str == *(str+1)) return FALSE;
636 str++;
637 if (*str != CR && *str != LF) return FALSE;
638 if (--num_chars) return FALSE;
639 return TRUE;
640}
641
642/*********************************************************************
643 * Return next line of text from a string.
644 *
645 * hdc - handle to DC.
646 * str - string to parse into lines.
647 * count - length of str.
648 * dest - destination in which to return line.
649 * len - dest buffer size in chars on input, copied length into dest on output.
650 * width - maximum width of line in pixels.
651 * format - format type passed to DrawText.
652 * retsize - returned size of the line in pixels.
653 * last_line - TRUE if is the last line that will be processed
654 * p_retstr - If DT_MODIFYSTRING this points to a cursor in the buffer in which
655 * the return string is built.
656 * tabwidth - The width of a tab in logical coordinates
657 * pprefix_offset - Here is where we return the offset within dest of the first
658 * prefixed (underlined) character. -1 is returned if there
659 * are none. Note that there may be more; the calling code
660 * will need to use TEXT_Reprefix to find any later ones.
661 * pellip - Here is where we return the information about any ellipsification
662 * that was carried out. Note that if tabs are being expanded then
663 * this data will correspond to the last text segment actually
664 * returned in dest; by definition there would not have been any
665 * ellipsification in earlier text segments of the line.
666 *
667 * Returns pointer to next char in str after end of the line
668 * or NULL if end of str reached.
669 */
670static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
671 WCHAR *dest, int *len, int width, DWORD format,
672 SIZE *retsize, int last_line, WCHAR **p_retstr,
673 int tabwidth, int *pprefix_offset,
674 ellipsis_data *pellip)
675{
676 int i = 0, j = 0;
677 int plen = 0;
678 SIZE size = {0, 0};
679 int maxl = *len;
680 int seg_i, seg_count, seg_j;
681 int max_seg_width;
682 int num_fit;
683 int word_broken;
684 int line_fits;
685 unsigned int j_in_seg;
686 int ellipsified;
687 *pprefix_offset = -1;
688
689 /* For each text segment in the line */
690
691 retsize->cy = 0;
692 while (*count)
693 {
694
695 /* Skip any leading tabs */
696
697 if (str[i] == TAB && (format & DT_EXPANDTABS))
698 {
699 plen = ((plen/tabwidth)+1)*tabwidth;
700 (*count)--; if (j < maxl) dest[j++] = str[i++]; else i++;
701 while (*count && str[i] == TAB)
702 {
703 plen += tabwidth;
704 (*count)--; if (j < maxl) dest[j++] = str[i++]; else i++;
705 }
706 }
707
708
709 /* Now copy as far as the next tab or cr/lf or eos */
710
711 seg_i = i;
712 seg_count = *count;
713 seg_j = j;
714
715 while (*count &&
716 (str[i] != TAB || !(format & DT_EXPANDTABS)) &&
717 ((str[i] != CR && str[i] != LF) || (format & DT_SINGLELINE)))
718 {
719 if ((format & DT_NOPREFIX) || *count <= 1)
720 {
721 (*count)--; if (j < maxl) dest[j++] = str[i++]; else i++;
722 continue;
723 }
724
725 if (str[i] == PREFIX || str[i] == ALPHA_PREFIX) {
726 (*count)--, i++; /* Throw away the prefix itself */
727 if (str[i] == PREFIX)
728 {
729 /* Swallow it before we see it again */
730 (*count)--; if (j < maxl) dest[j++] = str[i++]; else i++;
731 }
732 else if (*pprefix_offset == -1 || *pprefix_offset >= seg_j)
733 {
734 *pprefix_offset = j;
735 }
736 /* else the previous prefix was in an earlier segment of the
737 * line; we will leave it to the drawing code to catch this
738 * one.
739 */
740 }
741 else if (str[i] == KANA_PREFIX)
742 {
743 /* Throw away katakana access keys */
744 (*count)--, i++; /* skip the prefix */
745 (*count)--, i++; /* skip the letter */
746 }
747 else
748 {
749 (*count)--; if (j < maxl) dest[j++] = str[i++]; else i++;
750 }
751 }
752
753
754 /* Measure the whole text segment and possibly WordBreak and
755 * ellipsify it
756 */
757
758 j_in_seg = j - seg_j;
759 max_seg_width = width - plen;
760#ifdef _WIN32K_
761 GreGetTextExtentExW (hdc, dest + seg_j, j_in_seg, max_seg_width, (PULONG)&num_fit, NULL, &size, 0);
762#else
763 GetTextExtentExPointW (hdc, dest + seg_j, j_in_seg, max_seg_width, &num_fit, NULL, &size);
764#endif
765
766 /* The Microsoft handling of various combinations of formats is weird.
767 * The following may very easily be incorrect if several formats are
768 * combined, and may differ between versions (to say nothing of the
769 * several bugs in the Microsoft versions).
770 */
771 word_broken = 0;
772 line_fits = (num_fit >= j_in_seg);
773 if (!line_fits && (format & DT_WORDBREAK))
774 {
775 const WCHAR *s;
776 unsigned int chars_used;
777 TEXT_WordBreak (hdc, dest+seg_j, maxl-seg_j, &j_in_seg,
778 max_seg_width, format, num_fit, &chars_used, &size);
779 line_fits = (size.cx <= max_seg_width);
780 /* and correct the counts */
781 TEXT_SkipChars (count, &s, seg_count, str+seg_i, i-seg_i,
782 chars_used, !(format & DT_NOPREFIX));
783 i = s - str;
784 word_broken = 1;
785 }
786 pellip->before = j_in_seg;
787 pellip->under = 0;
788 pellip->after = 0;
789 pellip->len = 0;
790 ellipsified = 0;
791 if (!line_fits && (format & DT_PATH_ELLIPSIS))
792 {
793 TEXT_PathEllipsify (hdc, dest + seg_j, maxl-seg_j, &j_in_seg,
794 max_seg_width, &size, *p_retstr, pellip);
795 line_fits = (size.cx <= max_seg_width);
796 ellipsified = 1;
797 }
798 /* NB we may end up ellipsifying a word-broken or path_ellipsified
799 * string */
800 if ((!line_fits && (format & DT_WORD_ELLIPSIS)) ||
801 ((format & DT_END_ELLIPSIS) &&
802 ((last_line && *count) ||
803 (remainder_is_none_or_newline (*count, &str[i]) && !line_fits))))
804 {
805 int before, len_ellipsis;
806 TEXT_Ellipsify (hdc, dest + seg_j, maxl-seg_j, &j_in_seg,
807 max_seg_width, &size, *p_retstr, &before, &len_ellipsis);
808 if (before > pellip->before)
809 {
810 /* We must have done a path ellipsis too */
811 pellip->after = before - pellip->before - pellip->len;
812 /* Leave the len as the length of the first ellipsis */
813 }
814 else
815 {
816 /* If we are here after a path ellipsification it must be
817 * because even the ellipsis itself didn't fit.
818 */
819 assert (pellip->under == 0 && pellip->after == 0);
820 pellip->before = before;
821 pellip->len = len_ellipsis;
822 /* pellip->after remains as zero as does
823 * pellip->under
824 */
825 }
826 line_fits = (size.cx <= max_seg_width);
827 ellipsified = 1;
828 }
829 /* As an optimisation if we have ellipsified and we are expanding
830 * tabs and we haven't reached the end of the line we can skip to it
831 * now rather than going around the loop again.
832 */
833 if ((format & DT_EXPANDTABS) && ellipsified)
834 {
835 if (format & DT_SINGLELINE)
836 *count = 0;
837 else
838 {
839 while ((*count) && str[i] != CR && str[i] != LF)
840 {
841 (*count)--, i++;
842 }
843 }
844 }
845
846 j = seg_j + j_in_seg;
847 if (*pprefix_offset >= seg_j + pellip->before)
848 {
849 *pprefix_offset = TEXT_Reprefix (str + seg_i, i - seg_i, pellip);
850 if (*pprefix_offset != -1)
851 *pprefix_offset += seg_j;
852 }
853
854 plen += size.cx;
855 if (size.cy > retsize->cy)
856 retsize->cy = size.cy;
857
858 if (word_broken)
859 break;
860 else if (!*count)
861 break;
862 else if (str[i] == CR || str[i] == LF)
863 {
864 (*count)--, i++;
865 if (*count && (str[i] == CR || str[i] == LF) && str[i] != str[i-1])
866 {
867 (*count)--, i++;
868 }
869 break;
870 }
871 /* else it was a Tab and we go around again */
872 }
873
874 retsize->cx = plen;
875 *len = j;
876 if (*count)
877 return (&str[i]);
878 else
879 return NULL;
880}
881
882
883/***********************************************************************
884 * TEXT_DrawUnderscore
885 *
886 * Draw the underline under the prefixed character
887 *
888 * Parameters
889 * hdc [in] The handle of the DC for drawing
890 * x [in] The x location of the line segment (logical coordinates)
891 * y [in] The y location of where the underscore should appear
892 * (logical coordinates)
893 * str [in] The text of the line segment
894 * offset [in] The offset of the underscored character within str
895 * rect [in] Clipping rectangle (if not NULL)
896 */
897/* Synced with wine 1.1.32 */
898static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int offset, const RECT *rect)
899{
900 int prefix_x;
901 int prefix_end;
902 SIZE size;
903 HPEN hpen;
904 HPEN oldPen;
905#ifdef _WIN32K_
907#else
909#endif
910 prefix_x = x + size.cx;
911#ifdef _WIN32K_
913#else
915#endif
916 prefix_end = x + size.cx - 1;
917 /* The above method may eventually be slightly wrong due to kerning etc. */
918
919 /* Check for clipping */
920 if (rect)
921 {
922 if (prefix_x > rect->right || prefix_end < rect->left ||
923 y < rect->top || y > rect->bottom)
924 return; /* Completely outside */
925 /* Partially outside */
926 if (prefix_x < rect->left ) prefix_x = rect->left;
927 if (prefix_end > rect->right) prefix_end = rect->right;
928 }
929#ifdef _WIN32K_
931 oldPen = NtGdiSelectPen (hdc, hpen);
932 GreMoveTo (hdc, prefix_x, y, NULL);
933 NtGdiLineTo (hdc, prefix_end, y);
934 NtGdiSelectPen (hdc, oldPen);
936#else
938 oldPen = SelectObject (hdc, hpen);
939 MoveToEx (hdc, prefix_x, y, NULL);
940 LineTo (hdc, prefix_end, y);
941 SelectObject (hdc, oldPen);
943#endif
944}
945
946#ifdef _WIN32K_
947/***********************************************************************
948 * UserExtTextOutW
949 *
950 * Callback to usermode to use ExtTextOut, which will apply complex
951 * script processing if needed and then draw it
952 *
953 * Parameters
954 * hdc [in] The handle of the DC for drawing
955 * x [in] The x location of the string
956 * y [in] The y location of the string
957 * flags [in] ExtTextOut flags
958 * lprc [in] Clipping rectangle (if not NULL)
959 * lpString [in] String to be drawn
960 * count [in] String length
961 */
963 INT x,
964 INT y,
965 UINT flags,
966 PRECTL lprc,
967 LPCWSTR lpString,
968 UINT count)
969{
970 PVOID ResultPointer;
972 ULONG ArgumentLength;
973 ULONG_PTR pStringBuffer;
976 BOOL bResult;
977
978 ArgumentLength = sizeof(LPK_CALLBACK_ARGUMENTS);
979
980 pStringBuffer = ArgumentLength;
981 ArgumentLength += sizeof(WCHAR) * (count + 2);
982
983 Argument = IntCbAllocateMemory(ArgumentLength);
984
985 if (!Argument)
986 {
987 goto fallback;
988 }
989
990 /* Initialize struct members */
991 Argument->hdc = hdc;
992 Argument->x = x;
993 Argument->y = y;
994 Argument->flags = flags;
995 Argument->count = count;
996
997 if (lprc)
998 {
999 Argument->rect = *lprc;
1000 Argument->bRect = TRUE;
1001 }
1002 else
1003 {
1004 Argument->bRect = FALSE;
1005 }
1006
1007 /* Align lpString
1008 mimicks code from co_IntClientLoadLibrary */
1009 Argument->lpString = (LPWSTR)pStringBuffer;
1010 pStringBuffer += (ULONG_PTR)Argument;
1011
1012 Status = RtlStringCchCopyNW((LPWSTR)pStringBuffer, count + 1, lpString, count);
1013
1014 if (!NT_SUCCESS(Status))
1015 {
1016 IntCbFreeMemory(Argument);
1017 goto fallback;
1018 }
1019
1020 UserLeaveCo();
1021
1022 Status = KeUserModeCallback(USER32_CALLBACK_LPK,
1023 Argument,
1024 ArgumentLength,
1025 &ResultPointer,
1026 &ResultLength);
1027
1028 UserEnterCo();
1029
1030 IntCbFreeMemory(Argument);
1031
1032 if (NT_SUCCESS(Status))
1033 {
1034 _SEH2_TRY
1035 {
1036 ProbeForRead(ResultPointer, sizeof(BOOL), 1);
1037 bResult = *(LPBOOL)ResultPointer;
1038 }
1040 {
1041 ERR("Failed to copy result from user mode!\n");
1043 }
1044 _SEH2_END;
1045 }
1046
1047 if (!NT_SUCCESS(Status))
1048 {
1049 goto fallback;
1050 }
1051
1052 return bResult;
1053
1054fallback:
1055 return GreExtTextOutW(hdc, x, y, flags, lprc, lpString, count, NULL, 0);
1056}
1057#endif
1058
1059/***********************************************************************
1060 * DrawTextExW (USER32.@)
1061 *
1062 * The documentation on the extra space required for DT_MODIFYSTRING at MSDN
1063 * is not quite complete, especially with regard to \0. We will assume that
1064 * the returned string could have a length of up to i_count+3 and also have
1065 * a trailing \0 (which would be 4 more than a not-null-terminated string but
1066 * 3 more than a null-terminated string). If this is not so then increase
1067 * the allowance in DrawTextExA.
1068 */
1069#define MAX_BUFFER 1024
1070/*
1071 * DrawTextExW
1072 *
1073 * Synced with Wine Staging 1.7.37
1074 */
1076 LPWSTR str,
1077 INT i_count,
1078 LPRECT rect,
1079 UINT flags,
1080 LPDRAWTEXTPARAMS dtp )
1081{
1082 SIZE size;
1083 const WCHAR *strPtr;
1084 WCHAR *retstr, *p_retstr;
1085 size_t size_retstr;
1087 int len, lh, count=i_count;
1089 int lmargin = 0, rmargin = 0;
1090 int x = rect->left, y = rect->top;
1091 int width = rect->right - rect->left;
1092 int max_width = 0;
1093 int last_line;
1094 int tabwidth /* to keep gcc happy */ = 0;
1095 int prefix_offset;
1096 ellipsis_data ellip;
1097 BOOL invert_y=FALSE;
1098
1099 HRGN hrgn = 0;
1100
1101#ifdef _WIN32K_
1102 TRACE("%S, %d, %08x\n", str, count, flags);
1103#else
1104 TRACE("%s, %d, [%s] %08x\n", debugstr_wn (str, count), count,
1106#endif
1107 if (dtp) TRACE("Params: iTabLength=%d, iLeftMargin=%d, iRightMargin=%d\n",
1108 dtp->iTabLength, dtp->iLeftMargin, dtp->iRightMargin);
1109
1110 if (!str) return 0;
1111
1112 strPtr = str;
1113
1114 if (flags & DT_SINGLELINE)
1115 flags &= ~DT_WORDBREAK;
1116#ifdef _WIN32K_
1118#else
1120#endif
1122 lh = tm.tmHeight + tm.tmExternalLeading;
1123 else
1124 lh = tm.tmHeight;
1125
1126 if (str[0] && count == 0)
1127 return lh;
1128
1129 if (dtp && dtp->cbSize != sizeof(DRAWTEXTPARAMS))
1130 return 0;
1131#ifdef _WIN32K_
1133 {
1134 SIZE window_ext, viewport_ext;
1135 GreGetWindowExtEx(hdc, &window_ext);
1136 GreGetViewportExtEx(hdc, &viewport_ext);
1137 if ((window_ext.cy > 0) != (viewport_ext.cy > 0))
1138 invert_y = TRUE;
1139 }
1140#else
1142 {
1143 SIZE window_ext, viewport_ext;
1144 GetWindowExtEx(hdc, &window_ext);
1145 GetViewportExtEx(hdc, &viewport_ext);
1146 if ((window_ext.cy > 0) != (viewport_ext.cy > 0))
1147 invert_y = TRUE;
1148 }
1149#endif
1150 if (count == -1)
1151 {
1152#ifdef _WIN32K_
1153 count = wcslen(str);
1154#else
1155 count = strlenW(str);
1156#endif
1157 if (count == 0)
1158 {
1159 if( flags & DT_CALCRECT)
1160 {
1161 rect->right = rect->left;
1162 if( flags & DT_SINGLELINE)
1163 rect->bottom = rect->top + (invert_y ? -lh : lh);
1164 else
1165 rect->bottom = rect->top;
1166 }
1167 return lh;
1168 }
1169 }
1170
1171 if (dtp)
1172 {
1173 lmargin = dtp->iLeftMargin;
1174 rmargin = dtp->iRightMargin;
1175 if (!(flags & (DT_CENTER | DT_RIGHT)))
1176 x += lmargin;
1177 dtp->uiLengthDrawn = 0; /* This param RECEIVES number of chars processed */
1178 }
1179
1180 if (flags & DT_EXPANDTABS)
1181 {
1182 int tabstop = ((flags & DT_TABSTOP) && dtp && dtp->iTabLength) ? dtp->iTabLength : 8;
1183 tabwidth = tm.tmAveCharWidth * tabstop;
1184 }
1185
1186 if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
1187#ifndef _WIN32K_
1188 if (!(flags & DT_NOCLIP) )
1189 {
1190 int hasClip;
1191 hrgn = CreateRectRgn(0,0,0,0);
1192 if (hrgn)
1193 {
1194 hasClip = GetClipRgn(hdc, hrgn);
1195 // If the region to be retrieved is NULL, the return value is 0.
1196 if (hasClip != 1)
1197 {
1199 hrgn = NULL;
1200 }
1202 }
1203 }
1204#else
1205 if (!(flags & DT_NOCLIP) )
1206 {
1207 int hasClip;
1208 hrgn = NtGdiCreateRectRgn(0,0,0,0);
1209 if (hrgn)
1210 {
1211 hasClip = NtGdiGetRandomRgn(hdc, hrgn, CLIPRGN);
1212 if (hasClip != 1)
1213 {
1215 hrgn = NULL;
1216 }
1218 }
1219 }
1220#endif
1221 if (flags & DT_MODIFYSTRING)
1222 {
1223 size_retstr = (count + 4) * sizeof (WCHAR);
1224#ifdef _WIN32K_
1225 retstr = ExAllocatePoolWithTag(PagedPool, size_retstr, USERTAG_RTL);
1226#else
1227 retstr = HeapAlloc(GetProcessHeap(), 0, size_retstr);
1228#endif
1229 if (!retstr) return 0;
1230 memcpy (retstr, str, size_retstr);
1231 }
1232 else
1233 {
1234 size_retstr = 0;
1235 retstr = NULL;
1236 }
1237 p_retstr = retstr;
1238
1239 do
1240 {
1241 len = sizeof(line)/sizeof(line[0]);
1242 if (invert_y)
1243 last_line = !(flags & DT_NOCLIP) && y - ((flags & DT_EDITCONTROL) ? 2*lh-1 : lh) < rect->bottom;
1244 else
1245 last_line = !(flags & DT_NOCLIP) && y + ((flags & DT_EDITCONTROL) ? 2*lh-1 : lh) > rect->bottom;
1246 strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags, &size, last_line, &p_retstr, tabwidth, &prefix_offset, &ellip);
1247
1248#ifdef __REACTOS__
1249 if (flags & DT_CENTER)
1250 {
1251 if (((rect->right - rect->left) < size.cx) && (flags & DT_CALCRECT))
1252 {
1253 x = rect->left + size.cx;
1254 }
1255 else
1256 {
1257 x = (rect->left + rect->right - size.cx) / 2;
1258 }
1259 }
1260#else
1261 if (flags & DT_CENTER) x = (rect->left + rect->right -
1262 size.cx) / 2;
1263#endif
1264 else if (flags & DT_RIGHT) x = rect->right - size.cx;
1265
1266 if (flags & DT_SINGLELINE)
1267 {
1268#ifdef __REACTOS__
1269 if (flags & DT_VCENTER) y = rect->top +
1270 (rect->bottom - rect->top + (invert_y ? size.cy : -size.cy)) / 2;
1271 else if (flags & DT_BOTTOM)
1272 y = rect->bottom + (invert_y ? size.cy : -size.cy);
1273#else
1274 if (flags & DT_VCENTER) y = rect->top +
1275 (rect->bottom - rect->top) / 2 - size.cy / 2;
1276 else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
1277#endif
1278 }
1279
1280 if (!(flags & DT_CALCRECT))
1281 {
1282 const WCHAR *str = line;
1283 int xseg = x;
1284 while (len)
1285 {
1286 int len_seg;
1287 SIZE size;
1288 if ((flags & DT_EXPANDTABS))
1289 {
1290 const WCHAR *p;
1291 p = str; while (p < str+len && *p != TAB) p++;
1292 len_seg = p - str;
1293 if (len_seg != len &&
1294#ifdef _WIN32K_
1295 !GreGetTextExtentW(hdc, str, len_seg, &size, 0))
1296#else
1297 !GetTextExtentPointW(hdc, str, len_seg, &size))
1298#endif
1299 {
1300#ifdef _WIN32K_
1302#else
1303 HeapFree (GetProcessHeap(), 0, retstr);
1304#endif
1305 return 0;
1306 }
1307 }
1308 else
1309 len_seg = len;
1310#ifdef _WIN32K_
1311 if (!UserExtTextOutW( hdc, xseg, y,
1312 ((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
1313 ((flags & DT_RTLREADING) ? ETO_RTLREADING : 0),
1314 rect, str, len_seg))
1315#else
1316 if (!ExtTextOutW( hdc, xseg, y,
1317 ((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
1318 ((flags & DT_RTLREADING) ? ETO_RTLREADING : 0),
1319 rect, str, len_seg, NULL ))
1320#endif
1321 {
1322#ifdef _WIN32K_
1324#else
1325 HeapFree (GetProcessHeap(), 0, retstr);
1326#endif
1327 return 0;
1328 }
1329 if (prefix_offset != -1 && prefix_offset < len_seg)
1330 {
1331 TEXT_DrawUnderscore (hdc, xseg, y + tm.tmAscent + 1, str, prefix_offset, (flags & DT_NOCLIP) ? NULL : rect);
1332 }
1333 len -= len_seg;
1334 str += len_seg;
1335 if (len)
1336 {
1337 assert ((flags & DT_EXPANDTABS) && *str == TAB);
1338 len--; str++;
1339 xseg += ((size.cx/tabwidth)+1)*tabwidth;
1340 if (prefix_offset != -1)
1341 {
1342 if (prefix_offset < len_seg)
1343 {
1344 /* We have just drawn an underscore; we ought to
1345 * figure out where the next one is. I am going
1346 * to leave it for now until I have a better model
1347 * for the line, which will make reprefixing easier.
1348 * This is where ellip would be used.
1349 */
1350 prefix_offset = -1;
1351 }
1352 else
1353 prefix_offset -= len_seg;
1354 }
1355 }
1356 }
1357 }
1358 else if (size.cx > max_width)
1359 max_width = size.cx;
1360
1361 y += invert_y ? -lh : lh;
1362 if (dtp)
1363 dtp->uiLengthDrawn += len;
1364 }
1365 while (strPtr && !last_line);
1366
1367#ifndef _WIN32K_
1368 if (!(flags & DT_NOCLIP) )
1369 {
1370 SelectClipRgn(hdc, hrgn); // This should be NtGdiExtSelectClipRgn, but due to ReactOS build rules this option is next:
1371 GdiFlush(); // Flush the batch and level up! See CORE-16498.
1372 if (hrgn)
1373 {
1375 }
1376 }
1377#else
1378 if (!(flags & DT_NOCLIP) )
1379 {
1381 if (hrgn)
1382 {
1384 }
1385 }
1386#endif
1387
1388 if (flags & DT_CALCRECT)
1389 {
1390 rect->right = rect->left + max_width;
1391 rect->bottom = y;
1392 if (dtp)
1393 rect->right += lmargin + rmargin;
1394 }
1395 if (retstr)
1396 {
1397 memcpy (str, retstr, size_retstr);
1398#ifdef _WIN32K_
1400#else
1401 HeapFree (GetProcessHeap(), 0, retstr);
1402#endif
1403 }
1404 return y - rect->top;
1405}
1406
static HRGN hrgn
static HPEN hpen
NTSTATUS NTAPI KeUserModeCallback(IN ULONG RoutineIndex, IN PVOID Argument, IN ULONG ArgumentLength, OUT PVOID *Result, OUT PULONG ResultLength)
Definition: usercall.c:235
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
static long long start_count
Definition: clock.cpp:18
RECT rect
Definition: combotst.c:67
COLORREF FASTCALL GreGetTextColor(HDC)
Definition: dcutil.c:80
int FASTCALL GreGetGraphicsMode(HDC)
Definition: dcutil.c:306
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define wcsrchr
Definition: compat.h:16
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1330
const WCHAR * text
Definition: package.c:1794
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define L(x)
Definition: resources.c:13
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL APIENTRY GreExtTextOutW(_In_ HDC hDC, _In_ INT XStart, _In_ INT YStart, _In_ UINT fuOptions, _In_opt_ PRECTL lprc, _In_reads_opt_(Count) PCWCH String, _In_ INT Count, _In_opt_ const INT *Dx, _In_ DWORD dwCodePage)
Definition: freetype.c:7218
pKey DeleteObject()
Status
Definition: gdiplustypes.h:24
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble n
Definition: glext.h:7729
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLint left
Definition: glext.h:7726
GLbitfield flags
Definition: glext.h:7161
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define DbgPrint
Definition: hal.h:12
unsigned int UINT
Definition: sysinfo.c:13
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
BOOL FASTCALL GreMoveTo(HDC hdc, INT x, INT y, LPPOINT pptOut)
Definition: line.c:110
#define e
Definition: ke_i.h:82
#define debugstr_wn
Definition: kernel32.h:33
if(dx< 0)
Definition: linetemp.h:194
BOOL * LPBOOL
Definition: minwindef.h:138
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define CLIPRGN
Definition: precomp.h:18
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:88
static char * dest
Definition: rtl.c:149
BOOL WINAPI GreGetViewportExtEx(_In_ HDC hdc, _Out_ LPSIZE lpSize)
Definition: coord.c:1416
BOOL WINAPI GreGetWindowExtEx(_In_ HDC hdc, _Out_ LPSIZE lpSize)
Definition: coord.c:1407
NTSTRSAFEAPI RtlStringCchCopyNW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc, _In_ size_t cchToCopy)
Definition: ntstrsafe.h:363
short WCHAR
Definition: pedump.c:58
__kernel_entry W32KAPI HRGN APIENTRY NtGdiCreateRectRgn(_In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom)
__kernel_entry W32KAPI INT APIENTRY NtGdiExtSelectClipRgn(_In_ HDC hdc, _In_opt_ HRGN hrgn, _In_ INT iMode)
__kernel_entry W32KAPI INT APIENTRY NtGdiIntersectClipRect(_In_ HDC hdc, _In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom)
Definition: cliprgn.c:488
__kernel_entry W32KAPI INT APIENTRY NtGdiGetRandomRgn(_In_ HDC hdc, _In_ HRGN hrgn, _In_ INT iRgn)
__kernel_entry W32KAPI HPEN APIENTRY NtGdiCreatePen(_In_ INT iPenStyle, _In_ INT iPenWidth, _In_ COLORREF cr, _In_opt_ HBRUSH hbr)
__kernel_entry W32KAPI HPEN APIENTRY NtGdiSelectPen(_In_ HDC hdc, _In_ HPEN hpen)
__kernel_entry W32KAPI BOOL APIENTRY NtGdiLineTo(_In_ HDC hdc, _In_ INT x, _In_ INT y)
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
const WCHAR * str
#define TRACE(s)
Definition: solgame.cpp:4
int iRightMargin
Definition: winuser.h:3208
UINT uiLengthDrawn
Definition: winuser.h:3209
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
Definition: fci.c:127
Definition: format.c:58
Definition: parser.c:49
Definition: mxnamespace.c:38
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
#define max(a, b)
Definition: svc.c:63
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2390
Character const *const prefix
Definition: tempnam.cpp:195
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * LPCWSTR
Definition: typedefs.h:57
uint16_t * LPWSTR
Definition: typedefs.h:56
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define UserEnterCo
Definition: ntuser.h:3
#define UserLeaveCo
Definition: ntuser.h:4
BOOL UserExtTextOutW(HDC hdc, INT x, INT y, UINT flags, PRECTL lprc, LPCWSTR lpString, UINT count)
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3782
#define FORCEINLINE
Definition: wdftypes.h:67
BOOL WINAPI ExtTextOutW(_In_ HDC hdc, _In_ INT x, _In_ INT y, _In_ UINT fuOptions, _In_opt_ const RECT *lprc, _In_reads_opt_(cwc) LPCWSTR lpString, _In_ UINT cwc, _In_reads_opt_(cwc) const INT *lpDx)
Definition: text.c:491
BOOL WINAPI GetTextMetricsW(_In_ HDC hdc, _Out_ LPTEXTMETRICW lptm)
Definition: text.c:221
BOOL APIENTRY GetTextExtentPointW(_In_ HDC hdc, _In_reads_(cchString) LPCWSTR lpString, _In_ INT cchString, _Out_ LPSIZE lpsz)
Definition: text.c:269
BOOL WINAPI GetTextExtentExPointW(_In_ HDC hdc, _In_reads_(cchString) LPCWSTR lpszString, _In_ INT cchString, _In_ INT nMaxExtent, _Out_opt_ LPINT lpnFit, _Out_writes_to_opt_(cchString, *lpnFit) LPINT lpnDx, _Out_ LPSIZE lpSize)
Definition: text.c:284
COLORREF WINAPI GetTextColor(_In_ HDC hdc)
Definition: text.c:860
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1165
BOOL WINAPI GreGetTextMetricsW(_In_ HDC hdc, _Out_ LPTEXTMETRICW lptm)
Definition: text.c:191
BOOL FASTCALL GreGetTextExtentW(_In_ HDC hDC, _In_reads_(cwc) PCWCH lpwsz, _In_ INT cwc, _Out_ PSIZE psize, _In_ UINT flOpts)
Definition: text.c:77
BOOL FASTCALL GreGetTextExtentExW(_In_ HDC hDC, _In_ PCWCH String, _In_ ULONG Count, _In_ ULONG MaxExtent, _Out_opt_ PULONG Fit, _Out_writes_to_opt_(Count, *Fit) PULONG Dx, _Out_ PSIZE pSize, _In_ FLONG fl)
Definition: text.c:133
struct _LPK_CALLBACK_ARGUMENTS LPK_CALLBACK_ARGUMENTS
PVOID FASTCALL IntCbAllocateMemory(ULONG Size)
Definition: callback.c:27
VOID FASTCALL IntCbFreeMemory(PVOID Data)
Definition: callback.c:50
#define USERTAG_RTL
Definition: tags.h:270
void _font_assert(const char *msg, const char *file, int line)
Definition: text.c:54
#define MAX_BUFFER
Definition: text.c:1069
static void TEXT_DrawUnderscore(HDC hdc, int x, int y, const WCHAR *str, int offset, const RECT *rect)
Definition: text.c:898
#define BACK_SLASH
Definition: text.c:118
#define LF
Definition: text.c:110
static int remainder_is_none_or_newline(int num_chars, const WCHAR *str)
Definition: text.c:630
#define KANA_PREFIX
Definition: text.c:115
#define SPACE
Definition: text.c:112
struct tag_ellipsis_data ellipsis_data
static const WCHAR * TEXT_NextLineW(HDC hdc, const WCHAR *str, int *count, WCHAR *dest, int *len, int width, DWORD format, SIZE *retsize, int last_line, WCHAR **p_retstr, int tabwidth, int *pprefix_offset, ellipsis_data *pellip)
Definition: text.c:670
static void TEXT_Ellipsify(HDC hdc, WCHAR *str, unsigned int max_len, unsigned int *len_str, int width, SIZE *size, WCHAR *modstr, int *len_before, int *len_ellip)
Definition: text.c:159
FORCEINLINE BOOL IsCJKT(WCHAR wch)
Definition: text.c:339
#define CR
Definition: text.c:111
static const WCHAR KinsokuClassA[]
Definition: text.c:357
INT WINAPI DrawTextExWorker(HDC hdc, LPWSTR str, INT i_count, LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp)
Definition: text.c:1075
#define ALPHA_PREFIX
Definition: text.c:114
static int TEXT_Reprefix(const WCHAR *str, unsigned int ns, const ellipsis_data *pe)
Definition: text.c:592
static void TEXT_PathEllipsify(HDC hdc, WCHAR *str, unsigned int max_len, unsigned int *len_str, int width, SIZE *size, WCHAR *modstr, ellipsis_data *pellip)
Definition: text.c:265
#define FORWARD_SLASH
Definition: text.c:117
static void TEXT_WordBreak(HDC hdc, WCHAR *str, unsigned int max_str, unsigned int *len_str, int width, int format, unsigned int chars_fit, unsigned int *chars_used, SIZE *size)
Definition: text.c:430
#define TAB
Definition: text.c:109
#define PREFIX
Definition: text.c:113
static const WCHAR ELLIPSISW[]
Definition: text.c:120
static void TEXT_SkipChars(int *new_count, const WCHAR **new_str, int start_count, const WCHAR *start_str, int max, int n, int prefix)
Definition: text.c:544
#define WINAPI
Definition: msvc.h:6
#define strlenW(s)
Definition: unicode.h:28
#define strrchrW(s, c)
Definition: unicode.h:35
#define GM_COMPATIBLE
Definition: wingdi.h:864
HRGN WINAPI CreateRectRgn(_In_ int, _In_ int, _In_ int, _In_ int)
int WINAPI GetGraphicsMode(_In_ HDC)
int WINAPI IntersectClipRect(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
BOOL WINAPI GdiFlush(void)
Definition: misc.c:44
BOOL WINAPI MoveToEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
int WINAPI GetClipRgn(_In_ HDC, _In_ HRGN)
#define RGN_COPY
Definition: wingdi.h:357
#define ETO_CLIPPED
Definition: wingdi.h:648
BOOL WINAPI GetWindowExtEx(_In_ HDC, _Out_ LPSIZE)
Definition: coord.c:411
BOOL WINAPI GetViewportExtEx(_In_ HDC, _Out_ LPSIZE)
Definition: coord.c:351
HPEN WINAPI CreatePen(_In_ int, _In_ int, _In_ COLORREF)
int WINAPI SelectClipRgn(_In_ HDC, _In_opt_ HRGN)
BOOL WINAPI LineTo(_In_ HDC, _In_ int, _In_ int)
#define PS_SOLID
Definition: wingdi.h:586
#define DT_NOPREFIX
Definition: winuser.h:537
#define DT_EXTERNALLEADING
Definition: winuser.h:533
#define DT_CENTER
Definition: winuser.h:527
#define DT_END_ELLIPSIS
Definition: winuser.h:529
#define DT_SINGLELINE
Definition: winuser.h:540
#define DT_TABSTOP
Definition: winuser.h:541
#define DT_NOCLIP
Definition: winuser.h:536
#define DT_RTLREADING
Definition: winuser.h:539
#define DT_MODIFYSTRING
Definition: winuser.h:535
#define DT_WORDBREAK
Definition: winuser.h:544
#define DT_VCENTER
Definition: winuser.h:543
#define DT_BOTTOM
Definition: winuser.h:525
_In_ int _Inout_ LPRECT lprc
Definition: winuser.h:4620
#define DT_WORD_ELLIPSIS
Definition: winuser.h:531
#define DT_RIGHT
Definition: winuser.h:538
#define DT_EXPANDTABS
Definition: winuser.h:532
#define DT_CALCRECT
Definition: winuser.h:526
#define DT_EDITCONTROL
Definition: winuser.h:528
#define DT_PATH_ELLIPSIS
Definition: winuser.h:530