Annotation of mstools/samples/console/readout.c, revision 1.1.1.3

1.1.1.3 ! root        1: 
        !             2: /******************************************************************************\
        !             3: *       This is a part of the Microsoft Source Code Samples. 
        !             4: *       Copyright (C) 1993 Microsoft Corporation.
        !             5: *       All rights reserved. 
        !             6: *       This source code is only intended as a supplement to 
        !             7: *       Microsoft Development Tools and/or WinHelp documentation.
        !             8: *       See these sources for detailed information regarding the 
        !             9: *       Microsoft samples programs.
        !            10: \******************************************************************************/
        !            11: 
1.1       root       12: #include <windows.h>
                     13: #include <string.h>
                     14: #include <malloc.h>
                     15: #include "console.h"
                     16: 
                     17: /********************************************************************
                     18: * FUNCTION: invertRectangle(HANDLE hConOut, COORD coordStart,       *
                     19: *                           COORD coordCur)                         *
                     20: *                                                                   *
                     21: * PURPOSE: invert the attributes of the rectangle defined as the    *
                     22: *          area between two input COORD parameters                  *
                     23: *                                                                   *
                     24: * INPUT: the output handle of the console to make the changes to,   *
                     25: *        and two sets of COORD structures defining the rectangle to *
                     26: *        invert                                                     *
                     27: ********************************************************************/
                     28: 
                     29: void invertRectangle(HANDLE hConOut, COORD coordStart, COORD coordCur)
                     30: {
                     31:   WORD *awLineAttr;
                     32:   unsigned i;
                     33:   DWORD dwBoxWidth;
                     34:   WORD top, left, right, bottom;
                     35:   BOOL bSuccess;
                     36:   DWORD dwNumAttrsRead;
                     37: 
                     38:   /* convert coordSart to upper left & coordCur to lower right */
                     39:   top = min(coordStart.Y, coordCur.Y);
                     40:   bottom = max(coordStart.Y, coordCur.Y);
                     41:   left = min(coordStart.X, coordCur.X);
                     42:   right = max(coordStart.X, coordCur.X);
                     43:   coordStart.X = left;
                     44:   coordStart.Y = top;
                     45:   coordCur.X = right;
                     46:   coordCur.Y = bottom;
                     47:   /* get the width of the selected area */
                     48:   dwBoxWidth = right - left + 1;
                     49:   /* allocate a buffer for the attributes read from the console */
1.1.1.3 ! root       50:   awLineAttr = (PWORD) malloc(getConX(hConOut) * sizeof(DWORD));
1.1       root       51:   PERR(awLineAttr, "malloc");
                     52:   /* for each line in the selected area */
                     53:   while (coordStart.Y <= coordCur.Y)
                     54:     {
                     55:     /* read the attributes on that line */
                     56:     bSuccess = ReadConsoleOutputAttribute(hConOut, awLineAttr,
                     57:         dwBoxWidth, coordStart, &dwNumAttrsRead);
                     58:     PERR(bSuccess, "ReadConsoleOutputAttribute");
                     59:     /* for each attribute in the line, invert the color */
                     60:     for (i = 0; i < dwBoxWidth; i++)
                     61:       awLineAttr[i] = ~awLineAttr[i];
                     62:     /* put the inverted color back on the line */
                     63:     bSuccess = WriteConsoleOutputAttribute(hConOut, awLineAttr, dwBoxWidth,
                     64:         coordStart, &dwNumAttrsRead);
                     65:     PERR(bSuccess, "WriteConsoleOutputAttribute");
                     66:     coordStart.Y++; /* go to the next line */
                     67:     }
                     68:   free(awLineAttr); /* free allocated attribute buffer */
                     69:   return;
                     70: }
                     71: 
                     72: 
                     73: /********************************************************************
                     74: * FUNCTION: demoReadConOut(HANDLE hConOut)                          *
                     75: *                                                                   *
                     76: * PURPOSE: demonstrate ReadConsoleOutput, WriteConsoleOutput,       *
                     77: *          ReadConsoleOutputAttribute, and                          *
                     78: *          WriteConsoleOutputAttribute. Implement a cut and past    *
                     79: *          function; as the user clicks and drags the mouse, invert *
                     80: *          the selection rectangle to show the area selected. When  *
                     81: *          the mouse button is released, copy the selected area and *
                     82: *          paste it to the console                                  *
                     83: *                                                                   *
                     84: * INPUT: the output handle to read from and write to                *
                     85: ********************************************************************/
                     86: 
                     87: void demoReadConOut(HANDLE hConOut)
                     88: {
                     89:   BOOL bSuccess;
                     90:   INPUT_RECORD inputBuffer;
                     91:   DWORD dwStdInMode;
                     92:   HANDLE hStdIn;
                     93:   DWORD dwInputEvents;
                     94:   COORD coordStart, coordEnd, coordDest = {0, 0};
                     95:   BOOL bDragMode = FALSE; /* mode flag - selecting (dragging) or not? */
                     96:   COORD coordPrev; /* coordinates of the start of the selected area */
                     97:   CHAR_INFO *pCharInfo; /* buffer to store info from ReadConsoleOutput */
                     98:   COORD coordBufSize; /* the size of the buffer to read into */
                     99:   SMALL_RECT srReadRegion; /* source rectangle to read from */
                    100:   WORD top, left, right, bottom; /* sides of the source rectangle */
                    101:   CONSOLE_SCREEN_BUFFER_INFO csbi; /* used to get cursor position */
                    102: 
                    103:   setConTitle(__FILE__);
                    104:   myPuts(hConOut, "Let's implement a simple cut & paste with the left mouse\n"
                    105:                   "button. Click and drag to select an area of the screen\n"
                    106:                   "to copy. We will read, invert, then write the screen attributes\n"
                    107:                   "of the area you are dragging over to show the current\n"
                    108:                   "selection. Release the mouse button and I will read the\n"
                    109:                   "screen contained in the output area and print the contents\n"
                    110:                   "of the buffer to the screen at the current cursor location.\n"
                    111:                   "Hit ESC to return.\n\n");
                    112:   hStdIn = GetStdHandle(STD_INPUT_HANDLE);
1.1.1.2   root      113:   PERR(hStdIn != INVALID_HANDLE_VALUE, "GetStdHandle");
1.1       root      114:   /* save the console mode */
                    115:   bSuccess = GetConsoleMode(hStdIn, &dwStdInMode);
                    116:   PERR(bSuccess, "GetConsoleMode");
                    117:   /* enable mouse input */
                    118:   bSuccess = SetConsoleMode(hStdIn, dwStdInMode | ENABLE_MOUSE_INPUT);
                    119:   PERR(bSuccess, "SetConsoleMode");
                    120:   for(;;)
                    121:     {
                    122:     /* get an input event */
                    123:     bSuccess = ReadConsoleInput(hStdIn, &inputBuffer, 1, &dwInputEvents);
                    124:     PERR(bSuccess, "ReadConsoleInput");
                    125:     switch (inputBuffer.EventType)
                    126:       {
                    127:       case KEY_EVENT:
                    128:         /* is it an ESC character? */
                    129:         if (inputBuffer.Event.KeyEvent.bKeyDown &&
                    130:             inputBuffer.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
                    131:           {
                    132:           /* set input mode back to what it was originally and return */
                    133:           bSuccess = SetConsoleMode(hStdIn, dwStdInMode);
                    134:           PERR(bSuccess, "SetConsoleMode");
                    135:           return;
                    136:           }
                    137:         break;
                    138:       case MOUSE_EVENT:
                    139:         /* was this was a click event? */
                    140:         if (inputBuffer.Event.MouseEvent.dwEventFlags != MOUSE_MOVED)
                    141:           /* is only leftmost button down? */
                    142:           {
                    143:           if(inputBuffer.Event.MouseEvent.dwButtonState ==
                    144:               FROM_LEFT_1ST_BUTTON_PRESSED)
                    145:             {
                    146:             /* save the starting coordinates of the selected area */
                    147:             coordStart = coordPrev =
                    148:                 inputBuffer.Event.MouseEvent.dwMousePosition;
                    149:             /* invert the single char attribute the cursor is on */
                    150:             invertRectangle(hConOut, coordStart, coordStart);
                    151:             bDragMode = TRUE; /* we are now in 'drag' mode */
                    152:             }
                    153:           else /* button #1 has just been released */
                    154:             {
                    155:             /* if we're not in drag mode, break; we might get a mouse */
                    156:             /* button release when gaining the focus */
                    157:             if (!bDragMode)
                    158:               break;
                    159:             /* save the coordinates of the mouse release */
                    160:             coordEnd = inputBuffer.Event.MouseEvent.dwMousePosition;
                    161:             bDragMode = FALSE; /* we're not in 'drag' mode anymore */
                    162:             /* invert the rectangle back to normal */
                    163:             invertRectangle(hConOut, coordStart, coordEnd);
                    164:             /* copy the buffer in the rectangle and output it. First convert */
                    165:             /* coordSart to upper left & coordCur to lower right */
                    166:             top = min(coordStart.Y, coordEnd.Y);
                    167:             left = min(coordStart.X, coordEnd.X);
                    168:             bottom = max(coordStart.Y, coordEnd.Y);
                    169:             right = max(coordStart.X, coordEnd.X);
                    170:             coordStart.X = srReadRegion.Left = left;
                    171:             coordStart.Y = srReadRegion.Top = top;
                    172:             coordEnd.X = srReadRegion.Right = right;
                    173:             coordEnd.Y = srReadRegion.Bottom = bottom;
                    174:             /* get the size of the selected rectangle */
                    175:             coordBufSize.X = coordEnd.X - coordStart.X + (SHORT) 1;
                    176:             coordBufSize.Y = coordEnd.Y - coordStart.Y + (SHORT) 1;
                    177:             /* allocate a buffer for the screen rectangle */
                    178:             pCharInfo = malloc(coordBufSize.X * coordBufSize.Y *
                    179:                 sizeof(CHAR_INFO));
                    180:             PERR(pCharInfo, "malloc");
                    181:             /* read the screen rectangle into the buffer */
                    182:             bSuccess = ReadConsoleOutput(hConOut, /* output buffer */
                    183:                 pCharInfo, /* buffer that receives data */
                    184:                 coordBufSize, /* col/row size of destination buffer */
                    185:                 coordDest, /* upper-left cell to write data to in dest */
                    186:                 &srReadRegion); /* screen buffer rectangle to read from */
                    187:             PERR(bSuccess, "ReadConsoleOutput");
                    188:             /* get current cursor position */
                    189:             bSuccess = GetConsoleScreenBufferInfo(hConOut, &csbi);
                    190:             PERR(bSuccess, "GetConsoleScreenBufferInfo");
                    191:             /* set up an output destination rectangle for the buffer. */
                    192:             /* Put it just below the current cursor position. */
                    193:             srReadRegion.Top = csbi.dwCursorPosition.Y;
                    194:             srReadRegion.Bottom = csbi.dwCursorPosition.Y + (bottom - top);
                    195:             srReadRegion.Left = 0;
                    196:             srReadRegion.Right = right - left;
                    197:             bSuccess = WriteConsoleOutput(hConOut, /* output buffer */
                    198:                 pCharInfo, /* buffer with data to write */
                    199:                 coordBufSize, /* col/row size of source buffer */
                    200:                 coordDest, /* upper-left cell to write data from in src */
                    201:                 &srReadRegion); /* screen buffer rect to write data to */
                    202:             PERR(bSuccess, "WriteConsoleOutput");
                    203:             free(pCharInfo);
                    204:             }
                    205:           }
                    206:         /* is it a mouse movement while we are in drag mode? */
                    207:         if (inputBuffer.Event.MouseEvent.dwEventFlags == MOUSE_MOVED &&
                    208:             bDragMode)
                    209:           {
                    210:           /* if the cursor moves from the rectangle it was previously in, */
                    211:           /* invert the old rectangle then invert the new rectangle. */
                    212:           /* Compare the current coordinates with the previous coordinates */
                    213:           if (memcmp(&inputBuffer.Event.MouseEvent.dwMousePosition,
                    214:               &coordPrev, sizeof(COORD)))
                    215:             {
                    216:             /* You could be clever and only invert what needs to be */
                    217:             /* inverted rather than the entire two rectangles... */
                    218:             /* Invert the old rectangle */
                    219:             invertRectangle(hConOut, coordStart, coordPrev);
                    220:             /* and invert the new rectangle */
                    221:             invertRectangle(hConOut, coordStart,
                    222:                 inputBuffer.Event.MouseEvent.dwMousePosition);
                    223:             /* save the current mouse position to the previous position */
                    224:             memcpy(&coordPrev,
                    225:                 &inputBuffer.Event.MouseEvent.dwMousePosition,
                    226:                 sizeof(COORD));
                    227:             }
                    228:           }
                    229:         break;
                    230:       } /* switch */
                    231:     } /* while */
                    232: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.