@@ -143,6 +143,8 @@ TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
143
143
PCHAR_INFO
144
144
ConioCoordToPointer (PTEXTMODE_SCREEN_BUFFER Buff , ULONG X , ULONG Y )
145
145
{
146
+ ASSERT (X < Buff -> ScreenBufferSize .X );
147
+ ASSERT (Y < Buff -> ScreenBufferSize .Y );
146
148
return & Buff -> Buffer [((Y + Buff -> VirtualY ) % Buff -> ScreenBufferSize .Y ) * Buff -> ScreenBufferSize .X + X ];
147
149
}
148
150
@@ -185,78 +187,166 @@ ConioComputeUpdateRect(IN PTEXTMODE_SCREEN_BUFFER Buff,
185
187
}
186
188
187
189
/*
188
- * Move from one rectangle to another. We must be careful about the order that
189
- * this is done , to avoid overwriting parts of the source before they are moved .
190
+ * Copy from one rectangle to another. We must be careful about the order of
191
+ * operations , to avoid overwriting parts of the source before they are copied .
190
192
*/
191
193
static VOID
192
- ConioMoveRegion (PTEXTMODE_SCREEN_BUFFER ScreenBuffer ,
193
- PSMALL_RECT SrcRegion ,
194
- PSMALL_RECT DstRegion ,
195
- PSMALL_RECT ClipRegion ,
196
- CHAR_INFO FillChar )
194
+ ConioCopyRegion (
195
+ IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer ,
196
+ IN PSMALL_RECT SrcRegion ,
197
+ IN PCOORD DstOrigin )
197
198
{
198
- UINT Width = ConioRectWidth (SrcRegion );
199
- UINT Height = ConioRectHeight (SrcRegion );
200
- INT SXOrg , SX , SY ;
201
- INT DXOrg , DX , DY ;
202
- INT XDelta , YDelta ;
199
+ UINT Width , Height ;
200
+ SHORT SY , DY ;
201
+ SHORT YDelta ;
202
+ PCHAR_INFO PtrSrc , PtrDst ;
203
+ #if 0
204
+ SHORT SXOrg , DXOrg ;
205
+ SHORT SX , DX ;
206
+ SHORT XDelta ;
203
207
UINT i , j ;
204
- CHAR_INFO Cell ;
205
- PCHAR_INFO SRow , DRow ;
208
+ #endif
209
+
210
+ if (ConioIsRectEmpty (SrcRegion ))
211
+ return ;
212
+
213
+ #if 0
214
+ ASSERT (SrcRegion -> Left >= 0 && SrcRegion -> Left < ScreenBuffer -> ScreenBufferSize .X );
215
+ ASSERT (SrcRegion -> Right >= 0 && SrcRegion -> Right < ScreenBuffer -> ScreenBufferSize .X );
216
+ ASSERT (SrcRegion -> Top >= 0 && SrcRegion -> Top < ScreenBuffer -> ScreenBufferSize .Y );
217
+ ASSERT (SrcRegion -> Bottom >= 0 && SrcRegion -> Bottom < ScreenBuffer -> ScreenBufferSize .Y );
218
+ // ASSERT(DstOrigin->X >= 0 && DstOrigin->X < ScreenBuffer->ScreenBufferSize.X);
219
+ // ASSERT(DstOrigin->Y >= 0 && DstOrigin->Y < ScreenBuffer->ScreenBufferSize.Y);
220
+ #endif
221
+
222
+ /* If the source and destination regions are the same, just bail out */
223
+ if ((SrcRegion -> Left == DstOrigin -> X ) && (SrcRegion -> Top == DstOrigin -> Y ))
224
+ return ;
206
225
207
226
SY = SrcRegion -> Top ;
208
- DY = DstRegion -> Top ;
227
+ DY = DstOrigin -> Y ;
209
228
YDelta = 1 ;
210
229
if (SY < DY )
211
230
{
212
231
/* Moving down: work from bottom up */
213
232
SY = SrcRegion -> Bottom ;
214
- DY = DstRegion -> Bottom ;
233
+ DY = DstOrigin -> Y + ( SrcRegion -> Bottom - SrcRegion -> Top ) ;
215
234
YDelta = -1 ;
216
235
}
217
236
237
+ #if 0
218
238
SXOrg = SrcRegion -> Left ;
219
- DXOrg = DstRegion -> Left ;
239
+ DXOrg = DstOrigin -> X ;
220
240
XDelta = 1 ;
221
241
if (SXOrg < DXOrg )
222
242
{
223
243
/* Moving right: work from right to left */
224
244
SXOrg = SrcRegion -> Right ;
225
- DXOrg = DstRegion -> Right ;
245
+ DXOrg = DstOrigin -> X + ( SrcRegion -> Right - SrcRegion -> Left ) ;
226
246
XDelta = -1 ;
227
247
}
248
+ #endif
228
249
229
- for (i = 0 ; i < Height ; i ++ )
250
+ /* Loop through the source region */
251
+ Width = ConioRectWidth (SrcRegion );
252
+ Height = ConioRectHeight (SrcRegion );
253
+ #if 0
254
+ for (i = 0 ; i < Height ; ++ i , SY += YDelta , DY += YDelta )
255
+ #else
256
+ for (; Height -- > 0 ; SY += YDelta , DY += YDelta )
257
+ #endif
230
258
{
231
- SRow = ConioCoordToPointer (ScreenBuffer , 0 , SY );
232
- DRow = ConioCoordToPointer (ScreenBuffer , 0 , DY );
233
-
259
+ #if 0
234
260
SX = SXOrg ;
235
261
DX = DXOrg ;
236
262
237
- // TODO: Correctly support "moving" full-width characters.
263
+ PtrSrc = ConioCoordToPointer (ScreenBuffer , SX , SY );
264
+ PtrDst = ConioCoordToPointer (ScreenBuffer , DX , DY );
265
+ #else
266
+ PtrSrc = ConioCoordToPointer (ScreenBuffer , SrcRegion -> Left , SY );
267
+ PtrDst = ConioCoordToPointer (ScreenBuffer , DstOrigin -> X , DY );
268
+ #endif
238
269
239
- for (j = 0 ; j < Width ; j ++ )
270
+ // TODO: Correctly support copying full-width characters.
271
+ // By construction the source region is supposed to contain valid
272
+ // (possibly fullwidth) characters, so for these after the copy
273
+ // we need to check the characters at the borders and adjust the
274
+ // attributes accordingly.
275
+
276
+ #if 0
277
+ for (j = 0 ; j < Width ; ++ j , SX += XDelta , DX += XDelta )
240
278
{
241
- Cell = SRow [SX ];
242
- if (SX >= ClipRegion -> Left && SX <= ClipRegion -> Right &&
243
- SY >= ClipRegion -> Top && SY <= ClipRegion -> Bottom )
244
- {
245
- SRow [SX ] = FillChar ;
246
- }
247
- if (DX >= ClipRegion -> Left && DX <= ClipRegion -> Right &&
248
- DY >= ClipRegion -> Top && DY <= ClipRegion -> Bottom )
279
+ * PtrDst = * PtrSrc ;
280
+ PtrSrc += XDelta ;
281
+ PtrDst += XDelta ;
282
+ }
283
+ #else
284
+ /* RtlMoveMemory() takes into account for the direction of the copy */
285
+ RtlMoveMemory (PtrDst , PtrSrc , Width * sizeof (CHAR_INFO ));
286
+ #endif
287
+ }
288
+ }
289
+
290
+ static VOID
291
+ ConioFillRegion (
292
+ IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer ,
293
+ IN PSMALL_RECT Region ,
294
+ IN PSMALL_RECT ExcludeRegion OPTIONAL ,
295
+ IN CHAR_INFO FillChar )
296
+ {
297
+ SHORT X , Y ;
298
+ PCHAR_INFO Ptr ;
299
+ // BOOLEAN bFullwidth;
300
+
301
+ /* Bail out if the region to fill is empty */
302
+ if (ConioIsRectEmpty (Region ))
303
+ return ;
304
+
305
+ /* Sanitize the exclusion region: if it's empty, ignore the region */
306
+ if (ExcludeRegion && ConioIsRectEmpty (ExcludeRegion ))
307
+ ExcludeRegion = NULL ;
308
+
309
+ #if 0
310
+ ASSERT (Region -> Left >= 0 && Region -> Left < ScreenBuffer -> ScreenBufferSize .X );
311
+ ASSERT (Region -> Right >= 0 && Region -> Right < ScreenBuffer -> ScreenBufferSize .X );
312
+ ASSERT (Region -> Top >= 0 && Region -> Top < ScreenBuffer -> ScreenBufferSize .Y );
313
+ ASSERT (Region -> Bottom >= 0 && Region -> Bottom < ScreenBuffer -> ScreenBufferSize .Y );
314
+
315
+ if (ExcludeRegion )
316
+ {
317
+ ASSERT (ExcludeRegion -> Left >= 0 && ExcludeRegion -> Left < ScreenBuffer -> ScreenBufferSize .X );
318
+ ASSERT (ExcludeRegion -> Right >= 0 && ExcludeRegion -> Right < ScreenBuffer -> ScreenBufferSize .X );
319
+ ASSERT (ExcludeRegion -> Top >= 0 && ExcludeRegion -> Top < ScreenBuffer -> ScreenBufferSize .Y );
320
+ ASSERT (ExcludeRegion -> Bottom >= 0 && ExcludeRegion -> Bottom < ScreenBuffer -> ScreenBufferSize .Y );
321
+ }
322
+ #endif
323
+
324
+ // bFullwidth = (ScreenBuffer->Header.Console->IsCJK && IS_FULL_WIDTH(FillChar.Char.UnicodeChar));
325
+
326
+ /* Loop through the destination region */
327
+ for (Y = Region -> Top ; Y <= Region -> Bottom ; ++ Y )
328
+ {
329
+ Ptr = ConioCoordToPointer (ScreenBuffer , Region -> Left , Y );
330
+ for (X = Region -> Left ; X <= Region -> Right ; ++ X )
331
+ {
332
+ // TODO: Correctly support filling with full-width characters.
333
+
334
+ if (!ExcludeRegion ||
335
+ !(X >= ExcludeRegion -> Left && X <= ExcludeRegion -> Right &&
336
+ Y >= ExcludeRegion -> Top && Y <= ExcludeRegion -> Bottom ))
249
337
{
250
- DRow [DX ] = Cell ;
338
+ /* We are outside the excluded region, fill the destination */
339
+ * Ptr = FillChar ;
340
+ // Ptr->Attributes &= ~COMMON_LVB_SBCSDBCS;
251
341
}
252
- SX += XDelta ;
253
- DX += XDelta ;
342
+
343
+ ++ Ptr ;
254
344
}
255
- SY += YDelta ;
256
- DY += YDelta ;
257
345
}
258
346
}
259
347
348
+
349
+
260
350
// FIXME!
261
351
NTSTATUS NTAPI
262
352
ConDrvWriteConsoleInput (IN PCONSOLE Console ,
@@ -1366,24 +1456,25 @@ ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console,
1366
1456
}
1367
1457
1368
1458
NTSTATUS NTAPI
1369
- ConDrvScrollConsoleScreenBuffer (IN PCONSOLE Console ,
1370
- IN PTEXTMODE_SCREEN_BUFFER Buffer ,
1371
- IN BOOLEAN Unicode ,
1372
- IN PSMALL_RECT ScrollRectangle ,
1373
- IN BOOLEAN UseClipRectangle ,
1374
- IN PSMALL_RECT ClipRectangle OPTIONAL ,
1375
- IN PCOORD DestinationOrigin ,
1376
- IN CHAR_INFO FillChar )
1459
+ ConDrvScrollConsoleScreenBuffer (
1460
+ IN PCONSOLE Console ,
1461
+ IN PTEXTMODE_SCREEN_BUFFER Buffer ,
1462
+ IN BOOLEAN Unicode ,
1463
+ IN PSMALL_RECT ScrollRectangle ,
1464
+ IN BOOLEAN UseClipRectangle ,
1465
+ IN PSMALL_RECT ClipRectangle OPTIONAL ,
1466
+ IN PCOORD DestinationOrigin ,
1467
+ IN CHAR_INFO FillChar )
1377
1468
{
1378
1469
COORD CapturedDestinationOrigin ;
1379
1470
SMALL_RECT ScreenBuffer ;
1471
+ SMALL_RECT CapturedClipRectangle ;
1380
1472
SMALL_RECT SrcRegion ;
1381
1473
SMALL_RECT DstRegion ;
1382
1474
SMALL_RECT UpdateRegion ;
1383
- SMALL_RECT CapturedClipRectangle ;
1384
1475
1385
1476
if (Console == NULL || Buffer == NULL || ScrollRectangle == NULL ||
1386
- (UseClipRectangle ? ClipRectangle == NULL : FALSE ) || DestinationOrigin == NULL )
1477
+ (UseClipRectangle && ( ClipRectangle == NULL ) ) || DestinationOrigin == NULL )
1387
1478
{
1388
1479
return STATUS_INVALID_PARAMETER ;
1389
1480
}
@@ -1404,14 +1495,14 @@ ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console,
1404
1495
1405
1496
/* If the source was clipped on the left or top, adjust the destination accordingly */
1406
1497
if (ScrollRectangle -> Left < 0 )
1407
- {
1408
1498
CapturedDestinationOrigin .X -= ScrollRectangle -> Left ;
1409
- }
1410
1499
if (ScrollRectangle -> Top < 0 )
1411
- {
1412
1500
CapturedDestinationOrigin .Y -= ScrollRectangle -> Top ;
1413
- }
1414
1501
1502
+ /*
1503
+ * If a clip rectangle is provided, clip it to the screen buffer,
1504
+ * otherwise use the latter one as the clip rectangle.
1505
+ */
1415
1506
if (UseClipRectangle )
1416
1507
{
1417
1508
CapturedClipRectangle = * ClipRectangle ;
@@ -1425,26 +1516,60 @@ ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console,
1425
1516
CapturedClipRectangle = ScreenBuffer ;
1426
1517
}
1427
1518
1519
+ /*
1520
+ * Windows compatibility: Do nothing if the intersection of the source region
1521
+ * with the clip rectangle is empty, even if the intersection of destination
1522
+ * region with the clip rectangle is NOT empty and therefore it would have
1523
+ * been possible to copy contents to it...
1524
+ */
1525
+ if (!ConioGetIntersection (& UpdateRegion , & SrcRegion , & CapturedClipRectangle ))
1526
+ {
1527
+ return STATUS_SUCCESS ;
1528
+ }
1529
+
1530
+ /* Initialize the destination rectangle, of same size as the source rectangle */
1428
1531
ConioInitRect (& DstRegion ,
1429
1532
CapturedDestinationOrigin .Y ,
1430
1533
CapturedDestinationOrigin .X ,
1431
1534
CapturedDestinationOrigin .Y + ConioRectHeight (& SrcRegion ) - 1 ,
1432
1535
CapturedDestinationOrigin .X + ConioRectWidth (& SrcRegion ) - 1 );
1433
1536
1537
+ if (ConioGetIntersection (& DstRegion , & DstRegion , & CapturedClipRectangle ))
1538
+ {
1539
+ /*
1540
+ * Build the region image, within the source region,
1541
+ * of the destination region we should copy into.
1542
+ */
1543
+ SrcRegion .Left += DstRegion .Left - CapturedDestinationOrigin .X ;
1544
+ SrcRegion .Top += DstRegion .Top - CapturedDestinationOrigin .Y ;
1545
+ SrcRegion .Right = SrcRegion .Left + (DstRegion .Right - DstRegion .Left );
1546
+ SrcRegion .Bottom = SrcRegion .Top + (DstRegion .Bottom - DstRegion .Top );
1547
+
1548
+ /* Do the copy */
1549
+ CapturedDestinationOrigin .X = DstRegion .Left ;
1550
+ CapturedDestinationOrigin .Y = DstRegion .Top ;
1551
+ ConioCopyRegion (Buffer , & SrcRegion , & CapturedDestinationOrigin );
1552
+ }
1553
+
1434
1554
if (!Unicode )
1435
1555
{
1556
+ /* Conversion from the ASCII char to the UNICODE char */
1436
1557
WCHAR tmp ;
1437
1558
ConsoleOutputAnsiToUnicodeChar (Console , & tmp , & FillChar .Char .AsciiChar );
1438
1559
FillChar .Char .UnicodeChar = tmp ;
1439
1560
}
1440
1561
/* Sanitize the attribute */
1441
1562
FillChar .Attributes &= ~COMMON_LVB_SBCSDBCS ;
1442
1563
1443
- ConioMoveRegion (Buffer , & SrcRegion , & DstRegion , & CapturedClipRectangle , FillChar );
1564
+ /*
1565
+ * Fill the intersection (== UpdateRegion) of the source region with the
1566
+ * clip rectangle, excluding the destination region.
1567
+ */
1568
+ ConioFillRegion (Buffer , & UpdateRegion , & DstRegion , FillChar );
1444
1569
1445
1570
if ((PCONSOLE_SCREEN_BUFFER )Buffer == Console -> ActiveBuffer )
1446
1571
{
1447
- ConioGetUnion (& UpdateRegion , & SrcRegion , & DstRegion );
1572
+ ConioGetUnion (& UpdateRegion , & UpdateRegion , & DstRegion );
1448
1573
if (ConioGetIntersection (& UpdateRegion , & UpdateRegion , & CapturedClipRectangle ))
1449
1574
{
1450
1575
/* Draw update region */
0 commit comments