Release 0.4.7
[wine/multimedia.git] / objects / text.c
blobbbb2740085d7436400cf5b3725008c12d1141658
1 /*
2 * text functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <X11/Intrinsic.h>
10 #include <X11/StringDefs.h>
11 #include <X11/Core.h>
12 #include <X11/Shell.h>
13 #include <X11/Xatom.h>
15 #include "message.h"
16 #include "callback.h"
17 #include "win.h"
18 #include "gdi.h"
20 #define TAB 9
21 #define LF 10
22 #define CR 13
23 #define SPACE 32
24 #define PREFIX 38
26 static int tabstop = 8;
27 static int tabwidth;
28 static int spacewidth;
29 static int prefix_offset;
32 static char *TEXT_NextLine(HDC hdc, char *str, int *count, char *dest,
33 int *len, int width, WORD format)
35 /* Return next line of text from a string.
37 * hdc - handle to DC.
38 * str - string to parse into lines.
39 * count - length of str.
40 * dest - destination in which to return line.
41 * len - length of resultant line in dest in chars.
42 * width - maximum width of line in pixels.
43 * format - format type passed to DrawText.
45 * Returns pointer to next char in str after end of the line
46 * or NULL if end of str reached.
49 int i = 0, j = 0, k;
50 int plen = 0;
51 int numspaces;
52 SIZE size;
53 int lasttab = 0;
54 int wb_i = 0, wb_j = 0, wb_count;
56 while (*count)
58 switch (str[i])
60 case CR:
61 case LF:
62 if (!(format & DT_SINGLELINE))
64 i++;
65 if (str[i] == CR || str[i] == LF)
66 i++;
67 *len = j;
68 return (&str[i]);
70 dest[j++] = str[i++];
71 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
73 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
74 return NULL;
75 plen += size.cx;
77 break;
79 case PREFIX:
80 if (!(format & DT_NOPREFIX))
82 prefix_offset = j + 1;
83 i++;
85 else
87 dest[j++] = str[i++];
88 if (!(format & DT_NOCLIP))
90 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
91 return NULL;
92 plen += size.cx;
95 break;
97 case TAB:
98 if (format & DT_EXPANDTABS)
100 wb_i = ++i;
101 wb_j = j;
102 wb_count = *count;
104 if (!GetTextExtentPoint(hdc, &dest[lasttab], j - lasttab,
105 &size))
106 return NULL;
108 numspaces = (tabwidth - size.cx) / spacewidth;
109 for (k = 0; k < numspaces; k++)
110 dest[j++] = SPACE;
111 plen += tabwidth - size.cx;
112 lasttab = wb_j + numspaces;
114 else
116 dest[j++] = str[i++];
117 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
119 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
120 return NULL;
121 plen += size.cx;
124 break;
126 case SPACE:
127 dest[j++] = str[i++];
128 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
130 wb_i = i;
131 wb_j = j - 1;
132 wb_count = *count;
133 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
134 return NULL;
135 plen += size.cx;
137 break;
139 default:
140 dest[j++] = str[i++];
141 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
143 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
144 return NULL;
145 plen += size.cx;
149 (*count)--;
150 if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
152 if (plen > width)
154 if (format & DT_WORDBREAK)
156 *len = wb_j;
157 *count = wb_count;
158 return (&str[wb_i]);
160 else
162 *len = j;
163 return (&str[i]);
169 *len = j;
170 return NULL;
174 /***********************************************************************
175 * DrawText (USER.85)
177 int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
179 SIZE size;
180 char *strPtr;
181 static char line[1024];
182 int len, lh, prefix_x, prefix_len;
183 TEXTMETRIC tm;
184 int x = rect->left, y = rect->top;
185 int width = rect->right - rect->left;
187 if (count == -1) count = strlen(str);
188 strPtr = str;
190 GetTextMetrics(hdc, &tm);
191 if (flags & DT_EXTERNALLEADING)
192 lh = tm.tmHeight + tm.tmExternalLeading;
193 else
194 lh = tm.tmHeight;
196 if (flags & DT_TABSTOP)
197 tabstop = flags >> 8;
199 if (flags & DT_EXPANDTABS)
201 GetTextExtentPoint(hdc, " ", 1, &size);
202 spacewidth = size.cx;
203 GetTextExtentPoint(hdc, "o", 1, &size);
204 tabwidth = size.cx * tabstop;
209 prefix_offset = -1;
210 strPtr = TEXT_NextLine(hdc, strPtr, &count, line, &len, width, flags);
212 if (prefix_offset != -1)
214 GetTextExtentPoint(hdc, line, prefix_offset - 1, &size);
215 prefix_x = size.cx;
216 GetTextExtentPoint(hdc, line + prefix_offset, 1, &size);
217 prefix_len = size.cx;
220 if (!GetTextExtentPoint(hdc, line, len, &size)) return 0;
221 if (flags & DT_CENTER) x = (rect->left + rect->right -
222 size.cx) / 2;
223 else if (flags & DT_RIGHT) x = rect->right - size.cx;
225 if (flags & DT_SINGLELINE)
227 if (flags & DT_VCENTER) y = (rect->top + rect->bottom -
228 size.cy) / 2;
229 else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
232 if (!TextOut(hdc, x, y, line, len)) return 0;
233 if (prefix_offset != -1)
235 MoveTo(hdc, x + prefix_x, y + size.cy);
236 LineTo(hdc, x + prefix_x + prefix_len, y + size.cy);
239 if (strPtr)
241 y += lh;
242 if (!(flags & DT_NOCLIP))
244 if (y > rect->bottom - lh)
245 break;
249 while (strPtr);
251 return 1;
255 /***********************************************************************
256 * TextOut (GDI.33)
258 BOOL TextOut( HDC hdc, short x, short y, LPSTR str, short count )
260 int dir, ascent, descent, i;
261 XCharStruct info;
262 XFontStruct *font;
264 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
265 if (!dc) return FALSE;
266 if (!DC_SetupGCForText( dc )) return TRUE;
267 font = dc->u.x.font.fstruct;
269 if (dc->w.textAlign & TA_UPDATECP)
271 x = dc->w.CursPosX;
272 y = dc->w.CursPosY;
274 #ifdef DEBUG_TEXT
275 printf( "TextOut: %d,%d '%s'\n", x, y, str );
276 #endif
277 x = XLPTODP( dc, x );
278 y = YLPTODP( dc, y );
280 XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
281 info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
283 /* Compute starting position */
285 switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
287 case TA_LEFT:
288 if (dc->w.textAlign & TA_UPDATECP)
289 dc->w.CursPosX = XDPTOLP( dc, x + info.width );
290 break;
291 case TA_RIGHT:
292 x -= info.width;
293 if (dc->w.textAlign & TA_UPDATECP) dc->w.CursPosX = XDPTOLP( dc, x );
294 break;
295 case TA_CENTER:
296 x -= info.width / 2;
297 break;
299 switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
301 case TA_TOP:
302 y += font->ascent;
303 break;
304 case TA_BOTTOM:
305 y -= font->descent;
306 break;
307 case TA_BASELINE:
308 break;
311 /* Draw text */
313 if (!dc->w.charExtra && !dc->w.breakExtra)
315 if (dc->w.backgroundMode == TRANSPARENT)
316 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
317 x, y, str, count );
318 else
319 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
320 x, y, str, count );
322 else
324 char * p = str;
325 int xchar = x;
326 for (i = 0; i < count; i++, p++)
328 XCharStruct * charStr;
329 unsigned char ch = *p;
330 int extraWidth;
332 if ((ch < font->min_char_or_byte2)||(ch > font->max_char_or_byte2))
333 ch = font->default_char;
334 if (!font->per_char) charStr = &font->min_bounds;
335 else charStr = font->per_char + ch - font->min_char_or_byte2;
337 extraWidth = dc->w.charExtra;
338 if (ch == dc->u.x.font.metrics.tmBreakChar)
339 extraWidth += dc->w.breakExtra;
341 if (dc->w.backgroundMode == TRANSPARENT)
342 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
343 xchar, y, p, 1 );
344 else
346 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
347 xchar, y, p, 1 );
348 XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel);
349 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
350 xchar + charStr->width, y - font->ascent,
351 extraWidth, font->ascent + font->descent );
352 XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
354 xchar += charStr->width + extraWidth;
358 /* Draw underline and strike-out if needed */
360 if (dc->u.x.font.metrics.tmUnderlined)
362 long linePos, lineWidth;
363 if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
364 linePos = font->descent-1;
365 if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
366 lineWidth = 0;
367 else if (lineWidth == 1) lineWidth = 0;
368 XSetLineAttributes( XT_display, dc->u.x.gc, lineWidth,
369 LineSolid, CapRound, JoinBevel );
370 XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
371 x, y + linePos, x + info.width, y + linePos );
373 if (dc->u.x.font.metrics.tmStruckOut)
375 long lineAscent, lineDescent;
376 if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
377 lineAscent = font->ascent / 3;
378 if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
379 lineDescent = -lineAscent;
380 XSetLineAttributes( XT_display, dc->u.x.gc, lineAscent + lineDescent,
381 LineSolid, CapRound, JoinBevel );
382 XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
383 x, y - lineAscent, x + info.width, y - lineAscent );
386 return TRUE;