4 * Copyright 1993 Alexandre Julliard
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
20 static int tabstop = 8;
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.
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.
48 int wb_i = 0, wb_j = 0, wb_count;
56 if (!(format & DT_SINGLELINE))
59 if (str[i] == CR || str[i] == LF)
65 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
67 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
74 if (!(format & DT_NOPREFIX))
76 prefix_offset = j + 1;
82 if (!(format & DT_NOCLIP))
84 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
92 if (format & DT_EXPANDTABS)
98 if (!GetTextExtentPoint(hdc, &dest[lasttab], j - lasttab,
102 numspaces = (tabwidth - size.cx) / spacewidth;
103 for (k = 0; k < numspaces; k++)
105 plen += tabwidth - size.cx;
106 lasttab = wb_j + numspaces;
110 dest[j++] = str[i++];
111 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
113 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
121 dest[j++] = str[i++];
122 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
127 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
134 dest[j++] = str[i++];
135 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX))
137 if (!GetTextExtentPoint(hdc, &dest[j-1], 1, &size))
144 if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
148 if (format & DT_WORDBREAK)
168 /***********************************************************************
171 int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
175 static char line[1024];
176 int len, lh, prefix_x, prefix_len;
178 int x = rect->left, y = rect->top;
179 int width = rect->right - rect->left;
181 if (count == -1) count = strlen(str);
184 GetTextMetrics(hdc, &tm);
185 if (flags & DT_EXTERNALLEADING)
186 lh = tm.tmHeight + tm.tmExternalLeading;
190 if (flags & DT_TABSTOP)
191 tabstop = flags >> 8;
193 if (flags & DT_EXPANDTABS)
195 GetTextExtentPoint(hdc, " ", 1, &size);
196 spacewidth = size.cx;
197 GetTextExtentPoint(hdc, "o", 1, &size);
198 tabwidth = size.cx * tabstop;
204 strPtr = TEXT_NextLine(hdc, strPtr, &count, line, &len, width, flags);
206 if (prefix_offset != -1)
208 GetTextExtentPoint(hdc, line, prefix_offset - 1, &size);
210 GetTextExtentPoint(hdc, line + prefix_offset, 1, &size);
211 prefix_len = size.cx;
214 if (!GetTextExtentPoint(hdc, line, len, &size)) return 0;
215 if (flags & DT_CENTER) x = (rect->left + rect->right -
217 else if (flags & DT_RIGHT) x = rect->right - size.cx;
219 if (flags & DT_SINGLELINE)
221 if (flags & DT_VCENTER) y = rect->top +
222 (rect->bottom - rect->top) / 2 - size.cy / 2;
223 else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
225 if (!(flags & DT_CALCRECT))
226 if (!TextOut(hdc, x, y, line, len)) return 0;
227 if (prefix_offset != -1)
229 MoveTo(hdc, x + prefix_x, y + size.cy);
230 LineTo(hdc, x + prefix_x + prefix_len, y + size.cy);
236 if (!(flags & DT_NOCLIP))
238 if (y > rect->bottom - lh)
244 if (flags & DT_CALCRECT) rect->bottom = y;
249 /***********************************************************************
252 BOOL TextOut( HDC hdc, short x, short y, LPSTR str, short count )
254 int dir, ascent, descent, i;
258 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
261 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
262 if (!dc) return FALSE;
263 MF_TextOut(dc, x, y, str, count);
267 if (!DC_SetupGCForText( dc )) return TRUE;
268 font = dc->u.x.font.fstruct;
270 if (dc->w.textAlign & TA_UPDATECP)
276 printf( "TextOut: %d,%d '%s', %d\n", x, y, str, count );
278 x = XLPTODP( dc, x );
279 y = YLPTODP( dc, y );
281 XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
282 info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
284 /* Compute starting position */
286 switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
289 if (dc->w.textAlign & TA_UPDATECP)
290 dc->w.CursPosX = XDPTOLP( dc, x + info.width );
294 if (dc->w.textAlign & TA_UPDATECP) dc->w.CursPosX = XDPTOLP( dc, x );
300 switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
314 if (!dc->w.charExtra && !dc->w.breakExtra)
316 if (dc->w.backgroundMode == TRANSPARENT)
317 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
318 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
320 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
321 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
327 for (i = 0; i < count; i++, p++)
329 XCharStruct * charStr;
330 unsigned char ch = *p;
333 if ((ch < font->min_char_or_byte2)||(ch > font->max_char_or_byte2))
334 ch = font->default_char;
335 if (!font->per_char) charStr = &font->min_bounds;
336 else charStr = font->per_char + ch - font->min_char_or_byte2;
338 extraWidth = dc->w.charExtra;
339 if (ch == dc->u.x.font.metrics.tmBreakChar)
340 extraWidth += dc->w.breakExtra;
342 if (dc->w.backgroundMode == TRANSPARENT)
343 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
344 dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
347 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
348 dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
349 XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel);
350 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
351 dc->w.DCOrgX + xchar + charStr->width,
352 dc->w.DCOrgY + y - font->ascent,
353 extraWidth, font->ascent + font->descent );
354 XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
356 xchar += charStr->width + extraWidth;
360 /* Draw underline and strike-out if needed */
362 if (dc->u.x.font.metrics.tmUnderlined)
364 long linePos, lineWidth;
365 if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
366 linePos = font->descent-1;
367 if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
369 else if (lineWidth == 1) lineWidth = 0;
370 XSetLineAttributes( XT_display, dc->u.x.gc, lineWidth,
371 LineSolid, CapRound, JoinBevel );
372 XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
373 dc->w.DCOrgX + x, dc->w.DCOrgY + y + linePos,
374 dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y + linePos );
376 if (dc->u.x.font.metrics.tmStruckOut)
378 long lineAscent, lineDescent;
379 if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
380 lineAscent = font->ascent / 3;
381 if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
382 lineDescent = -lineAscent;
383 XSetLineAttributes( XT_display, dc->u.x.gc, lineAscent + lineDescent,
384 LineSolid, CapRound, JoinBevel );
385 XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
386 dc->w.DCOrgX + x, dc->w.DCOrgY + y - lineAscent,
387 dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y - lineAscent );
393 /***********************************************************************
394 * GrayString (USER.185)
396 BOOL GrayString(HDC hdc, HBRUSH hbr, FARPROC gsprc, LPARAM lParam,
397 INT cch, INT x, INT y, INT cx, INT cy)
399 int s, current_color;
402 return CallGrayStringProc(gsprc, hdc, lParam,
403 cch ? cch : lstrlen((LPCSTR) lParam) );
405 current_color = GetTextColor(hdc);
406 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT) );
407 s = TextOut(hdc, x, y, (LPSTR) lParam,
408 cch ? cch : lstrlen((LPCSTR) lParam) );
409 SetTextColor(hdc, current_color);
415 /***********************************************************************
416 * ExtTextOut [GDI.351]
418 BOOL ExtTextOut(HDC hDC, short x, short y, WORD wOptions, LPRECT lprect,
419 LPSTR str, WORD count, LPINT lpDx)
421 printf("EMPTY STUB !!! ExtTextOut(); ! call TextOut() for now !\n");
422 TextOut(hDC, x, y, str, count);