Added a set of tests for the console API.
[wine] / dlls / kernel / tests / console.c
1 /*
2  * Unit tests for console API
3  *
4  * Copyright (c) 2003 Eric Pouech
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 "wine/test.h"
22 #include <windows.h>
23 #include <stdio.h>
24
25 /* DEFAULT_ATTRIB is used for all initial filling of the console.
26  * all modifications are made with TEST_ATTRIB so that we could check 
27  * what has to be modified or not 
28  */
29 #define TEST_ATTRIB    (BACKGROUND_BLUE | FOREGROUND_GREEN)
30 #define DEFAULT_ATTRIB (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED)
31 /* when filling the screen with non-blank chars, this macro defines 
32  * what character should be at position 'c'
33  */
34 #define CONTENT(c)    ('A' + (((c).Y * 17 + (c).X) % 23))
35
36 #define okCURSOR(hCon, c) do { \
37   CONSOLE_SCREEN_BUFFER_INFO __sbi; \
38   BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
39                 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
40   ok(expect, "Expected cursor at (%d,%d), got (%d,%d)", \
41      (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
42 } while (0)
43
44 #define okCHAR(hCon, c, ch, attr) do { \
45   char __ch; WORD __attr; DWORD __len; BOOL expect; \
46   expect = ReadConsoleOutputCharacter((hCon), &__ch, 1, (c), &__len) == 1 && __len == 1 && __ch == (ch); \
47   ok(expect, "At (%d,%d): expecting char '%c'/%02x got '%c'/%02x", (c).X, (c).Y, (ch), (ch), __ch, __ch); \
48   expect = ReadConsoleOutputAttribute((hCon), &__attr, 1, (c), &__len) == 1 && __len == 1 && __attr == (attr); \
49   ok(expect, "At (%d,%d): expecting attr %04x got %04x", (c).X, (c).Y, (attr), __attr); \
50 } while (0)
51
52 /* FIXME: this could be optimized on a speed point of view */
53 static void resetContent(HANDLE hCon, COORD sbSize, BOOL content)
54 {
55     COORD       c;
56     WORD        attr = DEFAULT_ATTRIB;
57     char        ch;
58     DWORD       len;
59     
60     for (c.X = 0; c.X < sbSize.X; c.X++)
61     {
62         for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
63         {
64             ch = (content) ? CONTENT(c) : ' ';
65             WriteConsoleOutputAttribute(hCon, &attr, 1, c, &len);
66             WriteConsoleOutputCharacterA(hCon, &ch, 1, c, &len);
67         }
68     }
69 }
70
71 static void testCursor(HANDLE hCon, COORD sbSize)
72 {
73     COORD               c;
74     
75     ok(SetConsoleCursorPosition(0, c) == 0, "No handle");
76     ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %lu",
77        ERROR_INVALID_HANDLE, GetLastError());
78     
79     c.X = c.Y = 0;
80     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left");
81     okCURSOR(hCon, c);
82     
83     c.X = sbSize.X - 1;
84     c.Y = sbSize.Y - 1;
85     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in lower-right");
86     okCURSOR(hCon, c);
87     
88     c.X = sbSize.X;
89     c.Y = sbSize.Y - 1;
90     ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside");
91     ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu",
92        ERROR_INVALID_PARAMETER, GetLastError());
93     
94     c.X = sbSize.X - 1;
95     c.Y = sbSize.Y;
96     ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside");
97     ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu",
98        ERROR_INVALID_PARAMETER, GetLastError());
99
100     c.X = -1;
101     c.Y = 0;
102     ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside");
103     ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu",
104        ERROR_INVALID_PARAMETER, GetLastError());
105
106     c.X = 0;
107     c.Y = -1;
108     ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside");
109     ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu",
110        ERROR_INVALID_PARAMETER, GetLastError());
111 }
112
113 static void testWriteSimple(HANDLE hCon, COORD sbSize)
114 {
115     COORD               c;
116     DWORD               len;
117     const char*         mytest = "abcdefg";
118     const size_t        mylen = strlen(mytest);
119     
120     /* single line write */
121     c.X = c.Y = 0;
122     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left");
123     
124     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
125     c.Y = 0;
126     for (c.X = 0; c.X < mylen; c.X++)
127     {
128         okCHAR(hCon, c, mytest[c.X], TEST_ATTRIB);
129     }
130     
131     okCURSOR(hCon, c);
132     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
133 }
134
135 static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize)
136 {
137     COORD               c;
138     DWORD               len, mode;
139     const char*         mytest = "abcd\nf\tg";
140     const size_t        mylen = strlen(mytest);
141     int                 p;
142     
143     ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode & ~(ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT)), 
144        "clearing wrap at EOL & processed output");
145     
146     /* write line, wrapping disabled, buffer exceeds sb width */
147     c.X = sbSize.X - 3; c.Y = 0;
148     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3");
149     
150     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
151     c.Y = 0;
152     for (p = mylen - 3; p < mylen; p++)
153     {
154         c.X = sbSize.X - 3 + p % 3;
155         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
156     }
157
158     c.X = 0; c.Y = 1;
159     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
160     
161     p = sbSize.X - 3 + mylen % 3;
162     c.X = p; c.Y = 0;
163     okCURSOR(hCon, c);
164     
165     /* write line, wrapping disabled, strings end on end of line */
166     c.X = sbSize.X - mylen; c.Y = 0;
167     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3");
168     
169     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
170     c.Y = 0;
171     for (p = 0; p < mylen; p++)
172     {
173         c.X = sbSize.X - mylen + p;
174         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
175     }
176     
177     c.X = 0; c.Y = 1;
178     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
179     
180     p = sbSize.X - mylen;
181     c.X = p; c.Y = 0;
182     okCURSOR(hCon, c);
183 }
184
185 static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
186 {
187     COORD               c;
188     DWORD               len, mode;
189     const char*         mytest = "abcd\nf\tg";
190     const size_t        mylen = strlen(mytest);
191     const size_t        mylen2 = strchr(mytest, '\n') - mytest;
192     int                 p;
193     
194     ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, (mode | ENABLE_PROCESSED_OUTPUT) & ~ENABLE_WRAP_AT_EOL_OUTPUT), 
195        "clearing wrap at EOL & setting processed output");
196     
197     /* write line, wrapping disabled, buffer exceeds sb width */
198     c.X = sbSize.X - 5; c.Y = 0;
199     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-5");
200     
201     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
202     c.Y = 0;
203     for (c.X = sbSize.X - 5; c.X < sbSize.X - 1; c.X++)
204     {
205         okCHAR(hCon, c, mytest[c.X - sbSize.X + 5], TEST_ATTRIB);
206     }
207     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
208     
209     c.X = 0; c.Y++;
210     okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
211     for (c.X = 1; c.X < 8; c.X++)
212         okCHAR(hCon, c, ' ', TEST_ATTRIB);
213     okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
214     c.X++;
215     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
216     
217     okCURSOR(hCon, c);
218     
219     /* write line, wrapping disabled, strings end on end of line */
220     c.X = sbSize.X - 4; c.Y = 0;
221     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4");
222     
223     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
224     c.Y = 0;
225     for (c.X = sbSize.X - 4; c.X < sbSize.X; c.X++)
226     {
227         okCHAR(hCon, c, mytest[c.X - sbSize.X + 4], TEST_ATTRIB);
228     }
229     c.X = 0; c.Y++;
230     okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
231     for (c.X = 1; c.X < 8; c.X++)
232         okCHAR(hCon, c, ' ', TEST_ATTRIB);
233     okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
234     c.X++;
235     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
236     
237     okCURSOR(hCon, c);
238     
239     /* write line, wrapping disabled, strings end after end of line */
240     c.X = sbSize.X - 3; c.Y = 0;
241     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4");
242     
243     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
244     c.Y = 0;
245     for (p = mylen2 - 3; p < mylen2; p++)
246     {
247         c.X = sbSize.X - 3 + p % 3;
248         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
249     }
250     c.X = 0; c.Y = 1;
251     okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
252     for (c.X = 1; c.X < 8; c.X++)
253         okCHAR(hCon, c, ' ', TEST_ATTRIB);
254     okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
255     c.X++;
256     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
257     
258     okCURSOR(hCon, c);
259 }
260
261 static void testWriteWrappedNotProcessed(HANDLE hCon, COORD sbSize)
262 {
263     COORD               c;
264     DWORD               len, mode;
265     const char*         mytest = "abcd\nf\tg";
266     const size_t        mylen = strlen(mytest);
267     int                 p;
268     
269     ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon,(mode | ENABLE_WRAP_AT_EOL_OUTPUT) & ~(ENABLE_PROCESSED_OUTPUT)), 
270        "setting wrap at EOL & clearing processed output");
271     
272     /* write line, wrapping enabled, buffer doesn't exceed sb width */
273     c.X = sbSize.X - 9; c.Y = 0;
274     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9");
275     
276     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
277     c.Y = 0;
278     for (p = 0; p < mylen; p++)
279     {
280         c.X = sbSize.X - 9 + p;
281         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
282     }
283     c.X = sbSize.X - 9 + mylen;
284     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
285     c.X = 0; c.Y = 1;
286     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
287     
288     /* write line, wrapping enabled, buffer does exceed sb width */
289     c.X = sbSize.X - 3; c.Y = 0;
290     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3");
291     
292     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
293     c.Y = 0;
294     for (p = 0; p < 3; p++)
295     {
296         c.X = sbSize.X - 3 + p;
297         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
298     }
299     
300     c.Y = 1;
301     for (p = 0; p < mylen - 3; p++)
302     {
303         c.X = p;
304         okCHAR(hCon, c, mytest[p + 3], TEST_ATTRIB);
305     }
306     c.X = mylen - 3;
307     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
308     
309     okCURSOR(hCon, c);
310 }
311
312 static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize)
313 {
314     COORD               c;
315     DWORD               len, mode;
316     const char*         mytest = "abcd\nf\tg";
317     const size_t        mylen = strlen(mytest);
318     int                 p;
319     
320     ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode | (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)), 
321        "setting wrap at EOL & processed output");
322     
323     /* write line, wrapping enabled, buffer doesn't exceed sb width */
324     c.X = sbSize.X - 9; c.Y = 0;
325     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9");
326     
327     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
328     for (p = 0; p < 4; p++)
329     {
330         c.X = sbSize.X - 9 + p;
331         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
332     }
333     c.X = sbSize.X - 9 + p;
334     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
335     c.X = 0; c.Y++;
336     okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
337     for (c.X = 1; c.X < 8; c.X++)
338         okCHAR(hCon, c, ' ', TEST_ATTRIB);
339     okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
340     c.X++;
341     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
342     okCURSOR(hCon, c);
343
344     /* write line, wrapping enabled, buffer does exceed sb width */
345     c.X = sbSize.X - 3; c.Y = 2;
346     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3");
347     
348     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole");
349     for (p = 0; p < 3; p++)
350     {
351         c.X = sbSize.X - 3 + p;
352         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
353     }
354     c.X = 0; c.Y++;
355     okCHAR(hCon, c, mytest[3], TEST_ATTRIB);
356     c.X++;
357     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
358
359     c.X = 0; c.Y++;
360     okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
361     for (c.X = 1; c.X < 8; c.X++)
362         okCHAR(hCon, c, ' ', TEST_ATTRIB);
363     okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
364     c.X++;
365     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
366     okCURSOR(hCon, c);
367 }
368
369 static void testWrite(HANDLE hCon, COORD sbSize)
370 {
371     /* FIXME: should in fact insure that the sb is at least 10 character wide */
372     ok(SetConsoleTextAttribute(hCon, TEST_ATTRIB), "Setting default text color");
373     resetContent(hCon, sbSize, FALSE);
374     testWriteSimple(hCon, sbSize);
375     resetContent(hCon, sbSize, FALSE);
376     testWriteNotWrappedNotProcessed(hCon, sbSize);
377     resetContent(hCon, sbSize, FALSE);
378     testWriteNotWrappedProcessed(hCon, sbSize);
379     resetContent(hCon, sbSize, FALSE);
380     testWriteWrappedNotProcessed(hCon, sbSize);
381     resetContent(hCon, sbSize, FALSE);
382     testWriteWrappedProcessed(hCon, sbSize);
383 }
384
385 #if 0
386 static void testScroll(HANDLE hCon, COORD sbSize)
387 {
388     SMALL_RECT  scroll, clip;
389     COORD       dst, c, tc;
390     CHAR_INFO   ci;
391
392 #define W 11
393 #define H 7
394
395     /* no clipping, src & dst rect don't overlap */
396     resetContent(hCon, sbSize, TRUE);
397     
398 #define IN_SRECT(r,c) ((r).Left <= (c).X && (c).X <= (r).Right && (r).Top <= (c).Y && (c).Y <= (r).Bottom)
399 #define IN_SRECT2(r,d,c) ((d).X <= (c).X && (c).X <= (d).X + (r).Right - (r).Left && (d).Y <= (c).Y && (c).Y <= (d).Y + (r).Bottom - (r).Top)
400
401     scroll.Left = 0;
402     scroll.Right = W - 1;
403     scroll.Top = 0;
404     scroll.Bottom = H - 1;
405     dst.X = W + 3;
406     dst.Y = H + 3;
407     ci.Char.UnicodeChar = '#';
408     ci.Attributes = TEST_ATTRIB;
409
410     clip.Left = 0;
411     clip.Right = sbSize.X - 1;
412     clip.Top = 0;
413     clip.Bottom = sbSize.Y - 1;
414
415     ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB");
416
417     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
418     {
419         for (c.X = 0; c.X < sbSize.X; c.X++)
420         {
421             if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
422             {
423                 tc.X = c.X - dst.X;
424                 tc.Y = c.Y - dst.Y;
425                 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
426             }
427             else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c)) 
428                 okCHAR(hCon, c, '#', TEST_ATTRIB);
429             else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
430         }
431     }
432
433     /* no clipping, src & dst rect do overlap */
434     resetContent(hCon, sbSize, TRUE);
435
436     scroll.Left = 0;
437     scroll.Right = W - 1;
438     scroll.Top = 0;
439     scroll.Bottom = H - 1;
440     dst.X = W /2;
441     dst.Y = H / 2;
442     ci.Char.UnicodeChar = '#';
443     ci.Attributes = TEST_ATTRIB;
444
445     clip.Left = 0;
446     clip.Right = sbSize.X - 1;
447     clip.Top = 0;
448     clip.Bottom = sbSize.Y - 1;
449
450     ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB");
451
452     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
453     {
454         for (c.X = 0; c.X < sbSize.X; c.X++)
455         {
456             if (dst.X <= c.X && c.X < dst.X + W && dst.Y <= c.Y && c.Y < dst.Y + H)
457             {
458                 tc.X = c.X - dst.X;
459                 tc.Y = c.Y - dst.Y;
460                 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
461             }
462             else if (c.X < W && c.Y < H) okCHAR(hCon, c, '#', TEST_ATTRIB);
463             else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
464         }
465     }
466
467     /* clipping, src & dst rect don't overlap */
468     resetContent(hCon, sbSize, TRUE);
469     
470     scroll.Left = 0;
471     scroll.Right = W - 1;
472     scroll.Top = 0;
473     scroll.Bottom = H - 1;
474     dst.X = W + 3;
475     dst.Y = H + 3;
476     ci.Char.UnicodeChar = '#';
477     ci.Attributes = TEST_ATTRIB;
478
479     clip.Left = W / 2;
480     clip.Right = min(W + W / 2, sbSize.X - 1);
481     clip.Top = H / 2;
482     clip.Bottom = min(H + H / 2, sbSize.Y - 1);
483
484     ok(ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci), "Scrolling SB");
485
486     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
487     {
488         for (c.X = 0; c.X < sbSize.X; c.X++)
489         {
490             if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
491             {
492                 tc.X = c.X - dst.X;
493                 tc.Y = c.Y - dst.Y;
494                 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
495             }
496             else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c)) 
497                 okCHAR(hCon, c, '#', TEST_ATTRIB);
498             else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
499         }
500     }
501
502     /* clipping, src & dst rect do overlap */
503     resetContent(hCon, sbSize, TRUE);
504     
505     scroll.Left = 0;
506     scroll.Right = W - 1;
507     scroll.Top = 0;
508     scroll.Bottom = H - 1;
509     dst.X = W / 2 - 3;
510     dst.Y = H / 2 - 3;
511     ci.Char.UnicodeChar = '#';
512     ci.Attributes = TEST_ATTRIB;
513
514     clip.Left = W / 2;
515     clip.Right = min(W + W / 2, sbSize.X - 1);
516     clip.Top = H / 2;
517     clip.Bottom = min(H + H / 2, sbSize.Y - 1);
518
519     ok(ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci), "Scrolling SB");
520
521     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
522     {
523         for (c.X = 0; c.X < sbSize.X; c.X++)
524         {
525             if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
526             {
527                 tc.X = c.X - dst.X;
528                 tc.Y = c.Y - dst.Y;
529                 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
530             }
531             else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c)) 
532                 okCHAR(hCon, c, '#', TEST_ATTRIB);
533             else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
534         }
535     }
536 }
537 #endif
538
539 START_TEST(console)
540 {
541     HANDLE hCon;
542     BOOL ret;
543     CONSOLE_SCREEN_BUFFER_INFO  sbi;
544
545     /* be sure we have a clean console (and that's our own) 
546      * FIXME: this will make the test fail (currently) if we don't run
547      * under X11
548      * Another solution would be to rerun the test under wineconsole with
549      * the curses backend
550      */
551     FreeConsole();
552     AllocConsole();
553     hCon = GetStdHandle(STD_OUTPUT_HANDLE);
554     ok(ret = GetConsoleScreenBufferInfo(hCon, &sbi), "Getting sb info");
555     if (!ret) return;
556
557     /* Non interactive tests */
558     testCursor(hCon, sbi.dwSize);
559     /* will test wrapped (on/off) & processed (on/off) strings output */
560     testWrite(hCon, sbi.dwSize);
561     /* will test line scrolling at the bottom of the screen */
562     /* testBottomScroll(); */
563     /* will test all the scrolling operations */
564     /* this one is disabled for now, Wine's result are way too bad */
565     /* testScroll(hCon, sbi.dwSize); */
566     /* will test sb creation / modification... */
567     /* testScreenBuffer() */
568
569     /* still to be done: events generation, access rights & access on objects */
570 }