Annotation of mstools/samples/console/readout.c, revision 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.