Release 940420
[wine/testsucceed.git] / objects / text.c
blobae01b208841b45df4627062c915f97f0052e268f
1 /*
2 * text functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <X11/Xatom.h>
10 #include "windows.h"
11 #include "gdi.h"
13 #define TAB 9
14 #define LF 10
15 #define CR 13
16 #define SPACE 32
17 #define PREFIX 38
19 static int tabstop = 8;
20 static int tabwidth;
21 static int spacewidth;
22 static int prefix_offset;
25 static char *TEXT_NextLine(HDC hdc, char *str, int *count, char *dest,
26 int *len, int width, WORD format)
28 /* Return next line of text from a string.
30 * hdc - handle to DC.
31 * str - string to parse into lines.
32 * count - length of str.
33 * dest - destination in which to return line.
34 * len - length of resultant line in dest in chars.
35 * width - maximum width of line in pixels.
36 * format - format type passed to DrawText.
38 * Returns pointer to next char in str after end of the line
39 * or NULL if end of str reached.
42 int i = 0, j = 0, k;
43 int plen = 0;
44 int numspaces;
45 SIZE size;
46 int lasttab = 0;
47 int wb_i = 0, wb_j = 0, wb_count;
49 while (*count)
51 switch (str[i])
53 case CR:
54 case LF:
55 if (!(format & DT_SINGLELINE))
57 i++;
58 if (str[i] == CR || str[i] == LF)
59 i++;
60 *len = j;
61 return (&str[i]);
63 dest[j++] = str[i++];
64 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
66 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
67 return NULL;
68 plen += size.cx;
70 break;
72 case PREFIX:
73 if (!(format & DT_NOPREFIX))
75 prefix_offset = j + 1;
76 i++;
78 else
80 dest[j++] = str[i++];
81 if (!(format & DT_NOCLIP))
83 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
84 return NULL;
85 plen += size.cx;
88 break;
90 case TAB:
91 if (format & DT_EXPANDTABS)
93 wb_i = ++i;
94 wb_j = j;
95 wb_count = *count;
97 if (!GetTextExtentPoint(hdc, &dest[lasttab], j - lasttab,
98 &size))
99 return NULL;
101 numspaces = (tabwidth - size.cx) / spacewidth;
102 for (k = 0; k < numspaces; k++)
103 dest[j++] = SPACE;
104 plen += tabwidth - size.cx;
105 lasttab = wb_j + numspaces;
107 else
109 dest[j++] = str[i++];
110 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
112 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
113 return NULL;
114 plen += size.cx;
117 break;
119 case SPACE:
120 dest[j++] = str[i++];
121 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
123 wb_i = i;
124 wb_j = j - 1;
125 wb_count = *count;
126 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
127 return NULL;
128 plen += size.cx;
130 break;
132 default:
133 dest[j++] = str[i++];
134 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
136 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
137 return NULL;
138 plen += size.cx;
142 (*count)--;
143 if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
145 if (plen > width)
147 if (format & DT_WORDBREAK)
149 *len = wb_j;
150 *count = wb_count;
151 return (&str[wb_i]);
153 else
155 *len = j;
156 return (&str[i]);
162 *len = j;
163 return NULL;
167 /***********************************************************************
168 * DrawText (USER.85)
170 int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
172 SIZE size;
173 char *strPtr;
174 static char line[1024];
175 int len, lh, prefix_x, prefix_len;
176 TEXTMETRIC tm;
177 int x = rect->left, y = rect->top;
178 int width = rect->right - rect->left;
180 if (count == -1) count = strlen(str);
181 strPtr = str;
183 GetTextMetrics(hdc, &tm);
184 if (flags & DT_EXTERNALLEADING)
185 lh = tm.tmHeight + tm.tmExternalLeading;
186 else
187 lh = tm.tmHeight;
189 if (flags & DT_TABSTOP)
190 tabstop = flags >> 8;
192 if (flags & DT_EXPANDTABS)
194 GetTextExtentPoint(hdc, " ", 1, &size);
195 spacewidth = size.cx;
196 GetTextExtentPoint(hdc, "o", 1, &size);
197 tabwidth = size.cx * tabstop;
202 prefix_offset = -1;
203 strPtr = TEXT_NextLine(hdc, strPtr, &count, line, &len, width, flags);
205 if (prefix_offset != -1)
207 GetTextExtentPoint(hdc, line, prefix_offset - 1, &size);
208 prefix_x = size.cx;
209 GetTextExtentPoint(hdc, line + prefix_offset, 1, &size);
210 prefix_len = size.cx;
213 if (!GetTextExtentPoint(hdc, line, len, &size)) return 0;
214 if (flags & DT_CENTER) x = (rect->left + rect->right -
215 size.cx) / 2;
216 else if (flags & DT_RIGHT) x = rect->right - size.cx;
218 if (flags & DT_SINGLELINE)
220 if (flags & DT_VCENTER) y = rect->top +
221 (rect->bottom - rect->top) / 2 - size.cy / 2;
222 else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
224 if (!(flags & DT_CALCRECT))
225 if (!TextOut(hdc, x, y, line, len)) return 0;
226 if (prefix_offset != -1)
228 MoveTo(hdc, x + prefix_x, y + size.cy);
229 LineTo(hdc, x + prefix_x + prefix_len, y + size.cy);
232 if (strPtr)
234 y += lh;
235 if (!(flags & DT_NOCLIP))
237 if (y > rect->bottom - lh)
238 break;
242 while (strPtr);
243 if (flags & DT_CALCRECT) rect->bottom = y;
244 return 1;
248 /***********************************************************************
249 * TextOut (GDI.33)
251 BOOL TextOut( HDC hdc, short x, short y, LPSTR str, short count )
253 int dir, ascent, descent, i;
254 XCharStruct info;
255 XFontStruct *font;
257 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
258 if (!dc) return FALSE;
259 if (!DC_SetupGCForText( dc )) return TRUE;
260 font = dc->u.x.font.fstruct;
262 if (dc->w.textAlign & TA_UPDATECP)
264 x = dc->w.CursPosX;
265 y = dc->w.CursPosY;
267 #ifdef DEBUG_TEXT
268 printf( "TextOut: %d,%d '%s', %d\n", x, y, str, count );
269 #endif
270 x = XLPTODP( dc, x );
271 y = YLPTODP( dc, y );
273 XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
274 info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
276 /* Compute starting position */
278 switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
280 case TA_LEFT:
281 if (dc->w.textAlign & TA_UPDATECP)
282 dc->w.CursPosX = XDPTOLP( dc, x + info.width );
283 break;
284 case TA_RIGHT:
285 x -= info.width;
286 if (dc->w.textAlign & TA_UPDATECP) dc->w.CursPosX = XDPTOLP( dc, x );
287 break;
288 case TA_CENTER:
289 x -= info.width / 2;
290 break;
292 switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
294 case TA_TOP:
295 y += font->ascent;
296 break;
297 case TA_BOTTOM:
298 y -= font->descent;
299 break;
300 case TA_BASELINE:
301 break;
304 /* Draw text */
306 if (!dc->w.charExtra && !dc->w.breakExtra)
308 if (dc->w.backgroundMode == TRANSPARENT)
309 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
310 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
311 else
312 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
313 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
315 else
317 char * p = str;
318 int xchar = x;
319 for (i = 0; i < count; i++, p++)
321 XCharStruct * charStr;
322 unsigned char ch = *p;
323 int extraWidth;
325 if ((ch < font->min_char_or_byte2)||(ch > font->max_char_or_byte2))
326 ch = font->default_char;
327 if (!font->per_char) charStr = &font->min_bounds;
328 else charStr = font->per_char + ch - font->min_char_or_byte2;
330 extraWidth = dc->w.charExtra;
331 if (ch == dc->u.x.font.metrics.tmBreakChar)
332 extraWidth += dc->w.breakExtra;
334 if (dc->w.backgroundMode == TRANSPARENT)
335 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
336 dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
337 else
339 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
340 dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
341 XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel);
342 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
343 dc->w.DCOrgX + xchar + charStr->width,
344 dc->w.DCOrgY + y - font->ascent,
345 extraWidth, font->ascent + font->descent );
346 XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
348 xchar += charStr->width + extraWidth;
352 /* Draw underline and strike-out if needed */
354 if (dc->u.x.font.metrics.tmUnderlined)
356 long linePos, lineWidth;
357 if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
358 linePos = font->descent-1;
359 if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
360 lineWidth = 0;
361 else if (lineWidth == 1) lineWidth = 0;
362 XSetLineAttributes( XT_display, dc->u.x.gc, lineWidth,
363 LineSolid, CapRound, JoinBevel );
364 XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
365 dc->w.DCOrgX + x, dc->w.DCOrgY + y + linePos,
366 dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y + linePos );
368 if (dc->u.x.font.metrics.tmStruckOut)
370 long lineAscent, lineDescent;
371 if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
372 lineAscent = font->ascent / 3;
373 if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
374 lineDescent = -lineAscent;
375 XSetLineAttributes( XT_display, dc->u.x.gc, lineAscent + lineDescent,
376 LineSolid, CapRound, JoinBevel );
377 XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
378 dc->w.DCOrgX + x, dc->w.DCOrgY + y - lineAscent,
379 dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y - lineAscent );
382 return TRUE;
385 /***********************************************************************
386 * GrayString (USER.185)
388 BOOL GrayString(HDC hdc, HBRUSH hbr, FARPROC gsprc, LPARAM lParam,
389 INT cch, INT x, INT y, INT cx, INT cy)
391 int s, current_color;
393 if (gsprc) {
394 return CallGrayStringProc(gsprc, hdc, lParam,
395 cch ? cch : lstrlen((LPCSTR) lParam) );
396 } else {
397 current_color = GetTextColor(hdc);
398 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT) );
399 s = TextOut(hdc, x, y, (LPSTR) lParam,
400 cch ? cch : lstrlen((LPCSTR) lParam) );
401 SetTextColor(hdc, current_color);
403 return s;