Release 940714
[wine/multimedia.git] / objects / text.c
blob0cb0686f3e96e218c14f0347e9eb1326283f96d6
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"
12 #include "metafile.h"
14 #define TAB 9
15 #define LF 10
16 #define CR 13
17 #define SPACE 32
18 #define PREFIX 38
20 static int tabstop = 8;
21 static int tabwidth;
22 static int spacewidth;
23 static int prefix_offset;
26 static char *TEXT_NextLine(HDC hdc, char *str, int *count, char *dest,
27 int *len, int width, WORD format)
29 /* Return next line of text from a string.
31 * hdc - handle to DC.
32 * str - string to parse into lines.
33 * count - length of str.
34 * dest - destination in which to return line.
35 * len - length of resultant line in dest in chars.
36 * width - maximum width of line in pixels.
37 * format - format type passed to DrawText.
39 * Returns pointer to next char in str after end of the line
40 * or NULL if end of str reached.
43 int i = 0, j = 0, k;
44 int plen = 0;
45 int numspaces;
46 SIZE size;
47 int lasttab = 0;
48 int wb_i = 0, wb_j = 0, wb_count;
50 while (*count)
52 switch (str[i])
54 case CR:
55 case LF:
56 if (!(format & DT_SINGLELINE))
58 i++;
59 if (str[i] == CR || str[i] == LF)
60 i++;
61 *len = j;
62 return (&str[i]);
64 dest[j++] = str[i++];
65 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
66 (format & DT_WORDBREAK))
68 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
69 return NULL;
70 plen += size.cx;
72 break;
74 case PREFIX:
75 if (!(format & DT_NOPREFIX))
77 prefix_offset = j;
78 i++;
80 else
82 dest[j++] = str[i++];
83 if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
85 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
86 return NULL;
87 plen += size.cx;
90 break;
92 case TAB:
93 if (format & DT_EXPANDTABS)
95 wb_i = ++i;
96 wb_j = j;
97 wb_count = *count;
99 if (!GetTextExtentPoint(hdc, &dest[lasttab], j - lasttab,
100 &size))
101 return NULL;
103 numspaces = (tabwidth - size.cx) / spacewidth;
104 for (k = 0; k < numspaces; k++)
105 dest[j++] = SPACE;
106 plen += tabwidth - size.cx;
107 lasttab = wb_j + numspaces;
109 else
111 dest[j++] = str[i++];
112 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
113 (format & DT_WORDBREAK))
115 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
116 return NULL;
117 plen += size.cx;
120 break;
122 case SPACE:
123 dest[j++] = str[i++];
124 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
125 (format & DT_WORDBREAK))
127 wb_i = i;
128 wb_j = j - 1;
129 wb_count = *count;
130 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
131 return NULL;
132 plen += size.cx;
134 break;
136 default:
137 dest[j++] = str[i++];
138 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
139 (format & DT_WORDBREAK))
141 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
142 return NULL;
143 plen += size.cx;
147 (*count)--;
148 if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
150 if (plen > width)
152 if (format & DT_WORDBREAK)
154 *len = wb_j;
155 *count = wb_count - 1;
156 return (&str[wb_i]);
158 else
160 *len = j;
161 return (&str[i]);
167 *len = j;
168 return NULL;
172 /***********************************************************************
173 * DrawText (USER.85)
175 int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
177 SIZE size;
178 char *strPtr;
179 static char line[1024];
180 int len, lh, prefix_x, prefix_end;
181 TEXTMETRIC tm;
182 int x = rect->left, y = rect->top;
183 int width = rect->right - rect->left;
185 #ifdef DEBUG_TEXT
186 printf( "DrawText: '%s', %d , [(%d,%d),(%d,%d)]\n", str, count,
187 rect->left, rect->top, rect->right, rect->bottom);
188 #endif
190 if (count == -1) count = strlen(str);
191 strPtr = str;
193 GetTextMetrics(hdc, &tm);
194 if (flags & DT_EXTERNALLEADING)
195 lh = tm.tmHeight + tm.tmExternalLeading;
196 else
197 lh = tm.tmHeight;
199 if (flags & DT_TABSTOP)
200 tabstop = flags >> 8;
202 if (flags & DT_EXPANDTABS)
204 GetTextExtentPoint(hdc, " ", 1, &size);
205 spacewidth = size.cx;
206 GetTextExtentPoint(hdc, "o", 1, &size);
207 tabwidth = size.cx * tabstop;
212 prefix_offset = -1;
213 strPtr = TEXT_NextLine(hdc, strPtr, &count, line, &len, width, flags);
215 if (prefix_offset != -1)
217 GetTextExtentPoint(hdc, line, prefix_offset, &size);
218 prefix_x = size.cx;
219 GetTextExtentPoint(hdc, line, prefix_offset + 1, &size);
220 prefix_end = size.cx - 1;
223 if (!GetTextExtentPoint(hdc, line, len, &size)) return 0;
224 if (flags & DT_CENTER) x = (rect->left + rect->right -
225 size.cx) / 2;
226 else if (flags & DT_RIGHT) x = rect->right - size.cx;
228 if (flags & DT_SINGLELINE)
230 if (flags & DT_VCENTER) y = rect->top +
231 (rect->bottom - rect->top) / 2 - size.cy / 2;
232 else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
234 if (!(flags & DT_CALCRECT))
235 if (!TextOut(hdc, x, y, line, len)) return 0;
236 if (prefix_offset != -1)
238 MoveTo(hdc, x + prefix_x, y + tm.tmAscent + 1 );
239 LineTo(hdc, x + prefix_end, y + tm.tmAscent + 1 );
242 if (strPtr)
244 y += lh;
245 if (!(flags & DT_NOCLIP))
247 if (y > rect->bottom - lh)
248 break;
252 while (strPtr);
253 if (flags & DT_CALCRECT) rect->bottom = y;
254 return 1;
258 /***********************************************************************
259 * TextOut (GDI.33)
261 BOOL TextOut( HDC hdc, short x, short y, LPSTR str, short count )
263 int dir, ascent, descent, i;
264 XCharStruct info;
265 XFontStruct *font;
267 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
268 if (!dc)
270 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
271 if (!dc) return FALSE;
272 MF_TextOut(dc, x, y, str, count);
273 return TRUE;
276 if (!DC_SetupGCForText( dc )) return TRUE;
277 font = dc->u.x.font.fstruct;
279 if (dc->w.textAlign & TA_UPDATECP)
281 x = dc->w.CursPosX;
282 y = dc->w.CursPosY;
284 #ifdef DEBUG_TEXT
285 printf( "TextOut: %d,%d '%s', %d\n", x, y, str, count );
286 #endif
287 x = XLPTODP( dc, x );
288 y = YLPTODP( dc, y );
290 XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
291 info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
293 /* Compute starting position */
295 switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
297 case TA_LEFT:
298 if (dc->w.textAlign & TA_UPDATECP)
299 dc->w.CursPosX = XDPTOLP( dc, x + info.width );
300 break;
301 case TA_RIGHT:
302 x -= info.width;
303 if (dc->w.textAlign & TA_UPDATECP) dc->w.CursPosX = XDPTOLP( dc, x );
304 break;
305 case TA_CENTER:
306 x -= info.width / 2;
307 break;
309 switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
311 case TA_TOP:
312 y += font->ascent;
313 break;
314 case TA_BOTTOM:
315 y -= font->descent;
316 break;
317 case TA_BASELINE:
318 break;
321 /* Draw text */
323 if (!dc->w.charExtra && !dc->w.breakExtra)
325 if (dc->w.backgroundMode == TRANSPARENT)
326 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
327 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
328 else
329 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
330 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
332 else
334 char * p = str;
335 int xchar = x;
336 for (i = 0; i < count; i++, p++)
338 XCharStruct * charStr;
339 unsigned char ch = *p;
340 int extraWidth;
342 if ((ch < font->min_char_or_byte2)||(ch > font->max_char_or_byte2))
343 ch = font->default_char;
344 if (!font->per_char) charStr = &font->min_bounds;
345 else charStr = font->per_char + ch - font->min_char_or_byte2;
347 extraWidth = dc->w.charExtra;
348 if (ch == dc->u.x.font.metrics.tmBreakChar)
349 extraWidth += dc->w.breakExtra;
351 if (dc->w.backgroundMode == TRANSPARENT)
352 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
353 dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
354 else
356 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
357 dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
358 XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel);
359 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
360 dc->w.DCOrgX + xchar + charStr->width,
361 dc->w.DCOrgY + y - font->ascent,
362 extraWidth, font->ascent + font->descent );
363 XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
365 xchar += charStr->width + extraWidth;
369 /* Draw underline and strike-out if needed */
371 if (dc->u.x.font.metrics.tmUnderlined)
373 long linePos, lineWidth;
374 if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
375 linePos = font->descent-1;
376 if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
377 lineWidth = 0;
378 else if (lineWidth == 1) lineWidth = 0;
379 XSetLineAttributes( XT_display, dc->u.x.gc, lineWidth,
380 LineSolid, CapRound, JoinBevel );
381 XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
382 dc->w.DCOrgX + x, dc->w.DCOrgY + y + linePos,
383 dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y + linePos );
385 if (dc->u.x.font.metrics.tmStruckOut)
387 long lineAscent, lineDescent;
388 if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
389 lineAscent = font->ascent / 3;
390 if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
391 lineDescent = -lineAscent;
392 XSetLineAttributes( XT_display, dc->u.x.gc, lineAscent + lineDescent,
393 LineSolid, CapRound, JoinBevel );
394 XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
395 dc->w.DCOrgX + x, dc->w.DCOrgY + y - lineAscent,
396 dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y - lineAscent );
399 return TRUE;
402 /***********************************************************************
403 * GrayString (USER.185)
405 BOOL GrayString(HDC hdc, HBRUSH hbr, FARPROC gsprc, LPARAM lParam,
406 INT cch, INT x, INT y, INT cx, INT cy)
408 int s, current_color;
410 if (gsprc) {
411 return CallGrayStringProc(gsprc, hdc, lParam,
412 cch ? cch : lstrlen((LPCSTR) lParam) );
413 } else {
414 current_color = GetTextColor(hdc);
415 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT) );
416 s = TextOut(hdc, x, y, (LPSTR) lParam,
417 cch ? cch : lstrlen((LPCSTR) lParam) );
418 SetTextColor(hdc, current_color);
420 return s;
424 /***********************************************************************
425 * TabbedTextOut [USER.196]
427 LONG TabbedTextOut(HDC hDC, short x, short y, LPSTR lpStr, short nCount,
428 short nTabCount, LPINT lpTabPos, short nTabOrg)
430 WORD width, height;
431 printf("EMPTY STUB !!! TabbedTextOut(); ! call TextOut() for now !\n");
432 height = HIWORD(GetTextExtent(hDC, lpStr, nCount));
433 width = LOWORD(GetTextExtent(hDC, lpStr, nCount));
434 TextOut(hDC, x, y, lpStr, nCount);
435 return MAKELONG(width, height);
439 /***********************************************************************
440 * ExtTextOut [GDI.351]
442 BOOL ExtTextOut(HDC hDC, short x, short y, WORD wOptions, LPRECT lprect,
443 LPSTR str, WORD count, LPINT lpDx)
445 printf("EMPTY STUB !!! ExtTextOut(); ! call TextOut() for now !\n");
446 TextOut(hDC, x, y, str, count);
447 return FALSE;