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

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

unix.superglobalmegacorp.com

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