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

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

unix.superglobalmegacorp.com

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