Avoid excessive heap memory reallocation when generating EMF
[wine] / dlls / ttydrv / graphics.c
1 /*
2  * TTY DC graphics
3  *
4  * Copyright 1999 Patrik Stridvall
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnls.h"
28 #include "gdi.h"
29 #include "wine/debug.h"
30 #include "ttydrv.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(ttydrv);
33
34 /***********************************************************************
35  *              TTYDRV_DC_Arc
36  */
37 BOOL TTYDRV_DC_Arc(TTYDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
38                    INT xstart, INT ystart, INT xend, INT yend)
39 {
40   FIXME("(%p, %d, %d, %d, %d, %d, %d, %d, %d): stub\n",
41         physDev->hdc, left, top, right, bottom, xstart, ystart, xend, yend);
42   return TRUE;
43 }
44
45 /***********************************************************************
46  *              TTYDRV_DC_Chord
47  */
48 BOOL TTYDRV_DC_Chord(TTYDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
49                      INT xstart, INT ystart, INT xend, INT yend)
50 {
51   FIXME("(%p, %d, %d, %d, %d, %d, %d, %d, %d): stub\n",
52         physDev->hdc, left, top, right, bottom, xstart, ystart, xend, yend);
53   return TRUE;
54 }
55
56 /***********************************************************************
57  *              TTYDRV_DC_Ellipse
58  */
59 BOOL TTYDRV_DC_Ellipse(TTYDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom)
60 {
61   FIXME("(%p, %d, %d, %d, %d): stub\n", physDev->hdc, left, top, right, bottom);
62   return TRUE;
63 }
64
65 /***********************************************************************
66  *              TTYDRV_DC_ExtFloodFill
67  */
68 BOOL TTYDRV_DC_ExtFloodFill(TTYDRV_PDEVICE *physDev, INT x, INT y,
69                             COLORREF color, UINT fillType)
70 {
71   FIXME("(%p, %d, %d, 0x%08lx, %u): stub\n", physDev->hdc, x, y, color, fillType);
72   return TRUE;
73 }
74
75 /***********************************************************************
76  *              TTYDRV_DC_GetPixel
77  */
78 COLORREF TTYDRV_DC_GetPixel(TTYDRV_PDEVICE *physDev, INT x, INT y)
79 {
80   FIXME("(%p, %d, %d): stub\n", physDev->hdc, x, y);
81   return RGB(0,0,0); /* FIXME: Always returns black */
82 }
83
84 /***********************************************************************
85  *              TTYDRV_DC_LineTo
86  */
87 BOOL TTYDRV_DC_LineTo(TTYDRV_PDEVICE *physDev, INT x, INT y)
88 {
89 #ifdef WINE_CURSES
90   INT row1, col1, row2, col2;
91   POINT pt[2];
92
93   TRACE("(%p, %d, %d)\n", physDev->hdc, x, y);
94
95   if(!physDev->window)
96     return FALSE;
97
98   GetCurrentPositionEx( physDev->hdc, &pt[0] );
99   pt[1].x = x;
100   pt[1].y = y;
101   LPtoDP( physDev->hdc, pt, 2 );
102
103   row1 = (physDev->org.y + pt[0].y) / physDev->cellHeight;
104   col1 = (physDev->org.x + pt[0].x) / physDev->cellWidth;
105   row2 = (physDev->org.y + pt[1].y) / physDev->cellHeight;
106   col2 = (physDev->org.x + pt[1].x) / physDev->cellWidth;
107
108   if(row1 > row2) {
109     INT tmp = row1;
110     row1 = row2;
111     row2 = tmp;
112   }
113
114   if(col1 > col2) {
115     INT tmp = col1;
116     col1 = col2;
117     col2 = tmp;
118   }
119
120   wmove(physDev->window, row1, col1);
121   if(col1 == col2) {
122     wvline(physDev->window, ACS_VLINE, row2-row1);
123   } else if(row1 == row2) {
124     whline(physDev->window, ACS_HLINE, col2-col1);
125   } else {
126     FIXME("Diagonal line drawing not yet supported\n");
127   }
128   wrefresh(physDev->window);
129
130   return TRUE;
131 #else /* defined(WINE_CURSES) */
132   FIXME("(%x, %d, %d): stub\n", physDev->hdc, x, y);
133
134   return TRUE;
135 #endif /* defined(WINE_CURSES) */
136 }
137
138 /***********************************************************************
139  *              TTYDRV_DC_PaintRgn
140  */
141 BOOL TTYDRV_DC_PaintRgn(TTYDRV_PDEVICE *physDev, HRGN hrgn)
142 {
143   FIXME("(%p, %p): stub\n", physDev->hdc, hrgn);
144   return TRUE;
145 }
146
147 /***********************************************************************
148  *              TTYDRV_DC_Pie
149  */
150 BOOL TTYDRV_DC_Pie(TTYDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
151                    INT xstart, INT ystart, INT xend, INT yend)
152 {
153   FIXME("(%p, %d, %d, %d, %d, %d, %d, %d, %d): stub\n",
154         physDev->hdc, left, top, right, bottom, xstart, ystart, xend, yend);
155   return TRUE;
156 }
157
158 /***********************************************************************
159  *              TTYDRV_DC_Polygon
160  */
161 BOOL TTYDRV_DC_Polygon(TTYDRV_PDEVICE *physDev, const POINT* pt, INT count)
162 {
163   FIXME("(%p, %p, %d): stub\n", physDev->hdc, pt, count);
164   return TRUE;
165 }
166
167 /***********************************************************************
168  *              TTYDRV_DC_Polyline
169  */
170 BOOL TTYDRV_DC_Polyline(TTYDRV_PDEVICE *physDev, const POINT* pt, INT count)
171 {
172   FIXME("(%p, %p, %d): stub\n", physDev->hdc, pt, count);
173   return TRUE;
174 }
175
176 /***********************************************************************
177  *              TTYDRV_DC_PolyPolygon
178  */
179 BOOL TTYDRV_DC_PolyPolygon(TTYDRV_PDEVICE *physDev, const POINT* pt, const INT* counts, UINT polygons)
180 {
181   FIXME("(%p, %p, %p, %u): stub\n", physDev->hdc, pt, counts, polygons);
182   return TRUE;
183 }
184
185 /***********************************************************************
186  *              TTYDRV_DC_PolyPolyline
187  */
188 BOOL TTYDRV_DC_PolyPolyline(TTYDRV_PDEVICE *physDev, const POINT* pt, const DWORD* counts, DWORD polylines)
189 {
190   FIXME("(%p, %p, %p, %lu): stub\n", physDev->hdc, pt, counts, polylines);
191
192   return TRUE;
193 }
194
195 /***********************************************************************
196  *              TTYDRV_DC_Rectangle
197  */
198 BOOL TTYDRV_DC_Rectangle(TTYDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom)
199 {
200 #ifdef WINE_CURSES
201   INT row1, col1, row2, col2;
202   RECT rect;
203
204   TRACE("(%p, %d, %d, %d, %d)\n", physDev->hdc, left, top, right, bottom);
205
206   if(!physDev->window)
207     return FALSE;
208
209   rect.left   = left;
210   rect.top    = top;
211   rect.right  = right;
212   rect.bottom = bottom;
213   LPtoDP( physDev->hdc, (POINT *)&rect, 2 );
214   row1 = (physDev->org.y + rect.top) / physDev->cellHeight;
215   col1 = (physDev->org.x + rect.left) / physDev->cellWidth;
216   row2 = (physDev->org.y + rect.bottom) / physDev->cellHeight;
217   col2 = (physDev->org.x + rect.right) / physDev->cellWidth;
218
219   if(row1 > row2) {
220     INT tmp = row1;
221     row1 = row2;
222     row2 = tmp;
223   }
224   if(col1 > col2) {
225     INT tmp = col1;
226     col1 = col2;
227     col2 = tmp;
228   }
229
230   wmove(physDev->window, row1, col1);
231   whline(physDev->window, ACS_HLINE, col2-col1);
232
233   wmove(physDev->window, row1, col2);
234   wvline(physDev->window, ACS_VLINE, row2-row1);
235
236   wmove(physDev->window, row2, col1);
237   whline(physDev->window, ACS_HLINE, col2-col1);
238
239   wmove(physDev->window, row1, col1);
240   wvline(physDev->window, ACS_VLINE, row2-row1);
241
242   mvwaddch(physDev->window, row1, col1, ACS_ULCORNER);
243   mvwaddch(physDev->window, row1, col2, ACS_URCORNER);
244   mvwaddch(physDev->window, row2, col2, ACS_LRCORNER);
245   mvwaddch(physDev->window, row2, col1, ACS_LLCORNER);
246
247   wrefresh(physDev->window);
248
249   return TRUE;
250 #else /* defined(WINE_CURSES) */
251   FIXME("(%x, %d, %d, %d, %d): stub\n", physDev->hdc, left, top, right, bottom);
252
253   return TRUE;
254 #endif /* defined(WINE_CURSES) */
255 }
256
257 /***********************************************************************
258  *              TTYDRV_DC_RoundRect
259  */
260 BOOL TTYDRV_DC_RoundRect(TTYDRV_PDEVICE *physDev, INT left, INT top, INT right,
261                          INT bottom, INT ell_width, INT ell_height)
262 {
263   FIXME("(%p, %d, %d, %d, %d, %d, %d): stub\n",
264         physDev->hdc, left, top, right, bottom, ell_width, ell_height);
265
266   return TRUE;
267 }
268
269 /***********************************************************************
270  *              TTYDRV_DC_SetPixel
271  */
272 COLORREF TTYDRV_DC_SetPixel(TTYDRV_PDEVICE *physDev, INT x, INT y, COLORREF color)
273 {
274 #ifdef WINE_CURSES
275   INT row, col;
276   POINT pt;
277
278   TRACE("(%p, %d, %d, 0x%08lx)\n", physDev->hdc, x, y, color);
279
280   if(!physDev->window)
281     return FALSE;
282
283   pt.x = x;
284   pt.y = y;
285   LPtoDP( physDev->hdc, &pt, 1 );
286   row = (physDev->org.y + pt.y) / physDev->cellHeight;
287   col = (physDev->org.x + pt.x) / physDev->cellWidth;
288
289   mvwaddch(physDev->window, row, col, ACS_BULLET);
290   wrefresh(physDev->window);
291
292   return RGB(0,0,0); /* FIXME: Always returns black */
293 #else /* defined(WINE_CURSES) */
294   FIXME("(%x, %d, %d, 0x%08lx): stub\n", physDev->hdc, x, y, color);
295
296   return RGB(0,0,0); /* FIXME: Always returns black */
297 #endif /* defined(WINE_CURSES) */
298 }
299
300 /***********************************************************************
301  *              TTYDRV_DC_BitBlt
302  */
303 BOOL TTYDRV_DC_BitBlt(TTYDRV_PDEVICE *physDevDst, INT xDst, INT yDst,
304                       INT width, INT height, TTYDRV_PDEVICE *physDevSrc,
305                       INT xSrc, INT ySrc, DWORD rop)
306 {
307   FIXME("(%p, %d, %d, %d, %d, %p, %d, %d, %lu): stub\n",
308         physDevDst->hdc, xDst, yDst, width, height, physDevSrc->hdc, xSrc, ySrc, rop );
309   return TRUE;
310 }
311
312 /***********************************************************************
313  *              TTYDRV_DC_PatBlt
314  */
315 BOOL TTYDRV_DC_PatBlt(TTYDRV_PDEVICE *physDev, INT left, INT top,
316                       INT width, INT height, DWORD rop)
317 {
318   FIXME("(%p, %d, %d, %d, %d, %lu): stub\n", physDev->hdc, left, top, width, height, rop );
319   return TRUE;
320 }
321
322 /***********************************************************************
323  *              TTYDRV_DC_StretchBlt
324  */
325 BOOL TTYDRV_DC_StretchBlt(TTYDRV_PDEVICE *physDevDst, INT xDst, INT yDst,
326                           INT widthDst, INT heightDst,
327                           TTYDRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
328                           INT widthSrc, INT heightSrc, DWORD rop)
329 {
330   FIXME("(%p, %d, %d, %d, %d, %p, %d, %d, %d, %d, %lu): stub\n",
331         physDevDst->hdc, xDst, yDst, widthDst, heightDst,
332         physDevSrc->hdc, xSrc, ySrc, widthSrc, heightSrc, rop );
333
334   return TRUE;
335 }
336
337 /***********************************************************************
338  *              TTYDRV_DC_ExtTextOut
339  */
340 BOOL TTYDRV_DC_ExtTextOut(TTYDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
341                           const RECT *lpRect, LPCWSTR str, UINT count,
342                           const INT *lpDx)
343 {
344 #ifdef WINE_CURSES
345   INT row, col;
346   LPSTR ascii;
347   DWORD len;
348   POINT pt;
349   UINT text_align = GetTextAlign( physDev->hdc );
350
351   TRACE("(%p, %d, %d, 0x%08x, %p, %s, %d, %p)\n",
352         physDev->hdc, x, y, flags, lpRect, debugstr_wn(str, count), count, lpDx);
353
354   if(!physDev->window)
355     return FALSE;
356
357   pt.x = x;
358   pt.y = y;
359   /* FIXME: Is this really correct? */
360   if(text_align & TA_UPDATECP) GetCurrentPositionEx( physDev->hdc, &pt );
361
362   LPtoDP( physDev->hdc, &pt, 1 );
363   row = (physDev->org.y + pt.y) / physDev->cellHeight;
364   col = (physDev->org.x + pt.x) / physDev->cellWidth;
365   len = WideCharToMultiByte( CP_ACP, 0, str, count, NULL, 0, NULL, NULL );
366   ascii = HeapAlloc( GetProcessHeap(), 0, len );
367   WideCharToMultiByte( CP_ACP, 0, str, count, ascii, len, NULL, NULL );
368   mvwaddnstr(physDev->window, row, col, ascii, len);
369   HeapFree( GetProcessHeap(), 0, ascii );
370   wrefresh(physDev->window);
371
372   if(text_align & TA_UPDATECP)
373   {
374       pt.x += count * physDev->cellWidth;
375       pt.y += physDev->cellHeight;
376       DPtoLP( physDev->hdc, &pt, 1 );
377       MoveToEx( physDev->hdc, pt.x, pt.y, NULL );
378   }
379
380   return TRUE;
381 #else /* defined(WINE_CURSES) */
382   FIXME("(%x, %d, %d, 0x%08x, %p, %s, %d, %p): stub\n",
383         physDev->hdc, x, y, flags, lpRect, debugstr_wn(str,count), count, lpDx);
384
385   return TRUE;
386 #endif /* defined(WINE_CURSES) */
387 }
388
389 /***********************************************************************
390  *              TTYDRV_DC_GetCharWidth
391  */
392 BOOL TTYDRV_DC_GetCharWidth(TTYDRV_PDEVICE *physDev, UINT firstChar, UINT lastChar,
393                             LPINT buffer)
394 {
395   UINT c;
396
397   FIXME("(%p, %u, %u, %p): semistub\n", physDev->hdc, firstChar, lastChar, buffer);
398
399   for(c=firstChar; c<=lastChar; c++) {
400     buffer[c-firstChar] = physDev->cellWidth;
401   }
402
403   return TRUE;
404 }
405
406 /***********************************************************************
407  *              TTYDRV_DC_GetTextExtentPoint
408  */
409 BOOL TTYDRV_DC_GetTextExtentPoint(TTYDRV_PDEVICE *physDev, LPCWSTR str, INT count,
410                                   LPSIZE size)
411 {
412   TRACE("(%p, %s, %d, %p)\n", physDev->hdc, debugstr_wn(str, count), count, size);
413
414   size->cx = count * physDev->cellWidth;
415   size->cy = physDev->cellHeight;
416
417   return TRUE;
418 }
419
420 /***********************************************************************
421  *              TTYDRV_DC_GetTextMetrics
422  */
423 BOOL TTYDRV_DC_GetTextMetrics(TTYDRV_PDEVICE *physDev, LPTEXTMETRICW lptm)
424 {
425   TRACE("(%p, %p)\n", physDev->hdc, lptm);
426
427   lptm->tmHeight = physDev->cellHeight;
428   lptm->tmAscent = 0;
429   lptm->tmDescent = 0;
430   lptm->tmInternalLeading = 0;
431   lptm->tmExternalLeading = 0;
432   lptm->tmAveCharWidth = physDev->cellWidth;
433   lptm->tmMaxCharWidth = physDev->cellWidth;
434   lptm->tmWeight = FW_MEDIUM;
435   lptm->tmOverhang = 0;
436   lptm->tmDigitizedAspectX = physDev->cellWidth;
437   lptm->tmDigitizedAspectY = physDev->cellHeight;
438   lptm->tmFirstChar = 32;
439   lptm->tmLastChar = 255;
440   lptm->tmDefaultChar = 0;
441   lptm->tmBreakChar = 32;
442   lptm->tmItalic = FALSE;
443   lptm->tmUnderlined = FALSE;
444   lptm->tmStruckOut = FALSE;
445   lptm->tmPitchAndFamily = TMPF_FIXED_PITCH|TMPF_DEVICE;
446   lptm->tmCharSet = ANSI_CHARSET;
447
448   return TRUE;
449 }