Advertisement
Guest User

conio2.cpp

a guest
Oct 17th, 2015
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.38 KB | None | 0 0
  1. #include<stdio.h>
  2. #include<malloc.h>
  3. #include<string.h>
  4. #include<windows.h>
  5. #include"conio2.h"
  6. #ifdef __GNUC__
  7. #include<stdlib.h>
  8. #endif
  9.  
  10. #ifdef __cplusplus
  11. #define EXTERNC extern "C"
  12. #else
  13. #define EXTERNC
  14. #endif
  15.  
  16. int _wscroll;
  17.  
  18.  
  19. struct Conio2ThreadData {
  20.     int attrib;
  21.     int charCount;
  22.     int charValue;
  23.     int charFlag;
  24.     int ungetCount;
  25.     int ungetBuf[16];
  26.     int _wscroll;
  27.     int width;
  28.     int height;
  29.     int origwidth;
  30.     int origheight;
  31.     int origdepth;
  32.     int lastmode;
  33.     HANDLE output;
  34.     HANDLE input;
  35.     DWORD prevOutputMode;
  36.     DWORD prevInputMode;
  37.     };
  38.  
  39.  
  40. Conio2ThreadData thData;
  41.  
  42.  
  43. static void UpdateWScroll() {
  44.     if(_wscroll != thData._wscroll) {
  45.         if(_wscroll) SetConsoleMode(thData.output, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
  46.         else SetConsoleMode(thData.output, ENABLE_PROCESSED_OUTPUT);
  47.         thData._wscroll = _wscroll;
  48.         };
  49.     };
  50.  
  51.  
  52. static WORD ToWinAttribs(int attrib) {
  53.     WORD rv = 0;
  54.     if(attrib & 1) rv |= FOREGROUND_BLUE;
  55.     if(attrib & 2) rv |= FOREGROUND_GREEN;
  56.     if(attrib & 4) rv |= FOREGROUND_RED;
  57.     if(attrib & 8) rv |= FOREGROUND_INTENSITY;
  58.     if(attrib & 16) rv |= BACKGROUND_BLUE;
  59.     if(attrib & 32) rv |= BACKGROUND_GREEN;
  60.     if(attrib & 64) rv |= BACKGROUND_RED;
  61.     if(attrib & 128) rv |= BACKGROUND_INTENSITY;
  62.     return rv;
  63.     };
  64.  
  65.  
  66. static int FromWinAttribs(WORD attrib) {
  67.     int rv = 0;
  68.     if(attrib & FOREGROUND_BLUE) rv |= 1;
  69.     if(attrib & FOREGROUND_GREEN) rv |= 2;
  70.     if(attrib & FOREGROUND_RED) rv |= 4;
  71.     if(attrib & FOREGROUND_INTENSITY) rv |= 8;
  72.     if(attrib & BACKGROUND_BLUE) rv |= 16;
  73.     if(attrib & BACKGROUND_GREEN) rv |= 32;
  74.     if(attrib & BACKGROUND_RED) rv |= 64;
  75.     if(attrib & BACKGROUND_INTENSITY) rv |= 128;
  76.     return rv;
  77.     };
  78.  
  79.  
  80. static void GetCP(int *x, int *y) {
  81.     CONSOLE_SCREEN_BUFFER_INFO info;
  82.     GetConsoleScreenBufferInfo(thData.output, &info);
  83.     if(x) *x = info.dwCursorPosition.X + 1;
  84.     if(y) *y = info.dwCursorPosition.Y + 1;
  85.     };
  86.  
  87.  
  88. static bool HandleKeyEvent(INPUT_RECORD *buf) {
  89.     int ch;
  90.     ch = (int)(buf->Event.KeyEvent.uChar.AsciiChar) & 255;
  91.     if(ch == 0) ch = 0x8000 + buf->Event.KeyEvent.wVirtualKeyCode;
  92.     if(ch == 0x8010 || ch==0x8011 || ch==0x8012 || ch==0x8014
  93.        || ch==0x8090 || ch==0x8091) return false;
  94.     thData.charCount = buf->Event.KeyEvent.wRepeatCount;
  95.     thData.charFlag = ch & 0x8000 ? 1 : 0;
  96.     if(thData.charFlag) thData.charCount *= 2;
  97.     switch(ch) {
  98.         case 0x8000 + 33:   ch = 0x8000 + 73; break;
  99.         case 0x8000 + 34:   ch = 0x8000 + 81; break;
  100.         case 0x8000 + 35:   ch = 0x8000 + 79; break;
  101.         case 0x8000 + 36:   ch = 0x8000 + 71; break;
  102.         case 0x8000 + 37:   ch = 0x8000 + 75; break;
  103.         case 0x8000 + 38:   ch = 0x8000 + 72; break;
  104.         case 0x8000 + 39:   ch = 0x8000 + 77; break;
  105.         case 0x8000 + 40:   ch = 0x8000 + 80; break;
  106.         case 0x8000 + 46:   ch = 0x8000 + 83; break;
  107.         case 0x8000 + 112:  ch = 0x8000 + 59; break;
  108.         case 0x8000 + 113:  ch = 0x8000 + 60; break;
  109.         case 0x8000 + 114:  ch = 0x8000 + 61; break;
  110.         case 0x8000 + 115:  ch = 0x8000 + 62; break;
  111.         case 0x8000 + 116:  ch = 0x8000 + 63; break;
  112.         case 0x8000 + 117:  ch = 0x8000 + 64; break;
  113.         case 0x8000 + 118:  ch = 0x8000 + 65; break;
  114.         case 0x8000 + 119:  ch = 0x8000 + 66; break;
  115.         case 0x8000 + 120:  ch = 0x8000 + 67; break;
  116.         case 0x8000 + 121:  ch = 0x8000 + 68; break;
  117.         case 0x8000 + 122:  ch = 0x8000 + 133; break;
  118.         case 0x8000 + 123:  ch = 0x8000 + 134; break;
  119.         };
  120.     thData.charValue = ch & 0x7fff;
  121.     // TODO: translate proper keys (eg. arrows) to 0, xxx
  122.     return true;
  123.     };
  124.  
  125.  
  126. static void ResizeConsole(HANDLE con, int w, int h, int d) {
  127.     int cw, ch;
  128.     COORD s;
  129.     SMALL_RECT r;
  130.     CONSOLE_SCREEN_BUFFER_INFO info;
  131.  
  132.     bool res = GetConsoleScreenBufferInfo(con, &info);
  133.     cw = info.srWindow.Right - info.srWindow.Left + 1;
  134.     ch = info.srWindow.Bottom - info.srWindow.Top + 1;
  135.  
  136.     if(w < cw || h < ch) {
  137.         r.Top = 0;
  138.         r.Left = 0;
  139.         r.Right = (SHORT)(min(w, cw) - 1);
  140.         r.Bottom = (SHORT)(min(h, ch) - 1);
  141.         SetConsoleWindowInfo(con, TRUE, &r);
  142.         };
  143.  
  144.     if(d < h) d = h;
  145.     s.X = (SHORT)w;
  146.     s.Y = (SHORT)d;
  147.     SetConsoleScreenBufferSize(con, s);
  148.     r.Top = 0;
  149.     r.Left = 0;
  150.     r.Right = (SHORT)(w - 1);
  151.     r.Bottom = (SHORT)(h - 1);
  152.     SetConsoleWindowInfo(con, TRUE, &r);
  153.     };
  154.  
  155.  
  156. static void InitConio2(Conio2ThreadData *data) {
  157.     data->output = GetStdHandle(STD_OUTPUT_HANDLE);
  158.     data->input = GetStdHandle(STD_INPUT_HANDLE);
  159.     data->ungetCount = 0;
  160.     data->charCount = 0;
  161.    
  162.     CONSOLE_SCREEN_BUFFER_INFO info;
  163.     bool rc = GetConsoleScreenBufferInfo(data->output, &info);
  164.     if(rc) {
  165.         data->origwidth = info.srWindow.Right - info.srWindow.Left + 1;
  166.         data->origheight = info.srWindow.Bottom - info.srWindow.Top + 1;
  167.         data->origdepth = info.dwSize.Y;
  168.     } else {
  169.         data->origwidth = 80;
  170.         data->origheight = 25;
  171.         data->origdepth = 25;
  172.         }
  173.  
  174.     data->width = data->origwidth;
  175.     data->height = data->origheight;
  176.  
  177.     data->attrib = 0x07;
  178.     data->lastmode = C80;
  179.     data->_wscroll = -1;
  180.     SetConsoleTextAttribute(thData.output, ToWinAttribs(thData.attrib));
  181.     GetConsoleMode(data->input, &(data->prevInputMode));
  182.     GetConsoleMode(data->output, &(data->prevOutputMode));
  183.     SetConsoleMode(data->input, ENABLE_PROCESSED_INPUT);
  184.     UpdateWScroll();
  185. //  SetConsoleOutputCP();
  186.     //SetConsoleMode(data->output, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
  187.     };
  188.  
  189.  
  190. static void ExitConio2(Conio2ThreadData *data) {
  191.     ResizeConsole(data->output, data->origwidth, data->origheight, data->origdepth);
  192.     SetConsoleMode(data->input, data->prevInputMode);
  193.     SetConsoleMode(data->output, data->prevOutputMode);
  194. //  SetConsoleOutputCP();
  195.     };
  196.  
  197.  
  198. EXTERNC
  199. void gotoxy(int x, int y) {
  200.     COORD pos;
  201.     pos.X = x - 1;
  202.     pos.Y = y - 1;
  203.     SetConsoleCursorPosition(thData.output, pos);
  204.     };
  205.  
  206.  
  207. EXTERNC
  208. int wherex() {
  209.     int x;
  210.     GetCP(&x, NULL);
  211.     return x;
  212.     };
  213.  
  214.  
  215. EXTERNC
  216. int wherey() { 
  217.     int y;
  218.     GetCP(NULL, &y);
  219.     return y;
  220.     };
  221.  
  222.  
  223. EXTERNC
  224. void _setcursortype(int cur_t) {
  225.     CONSOLE_CURSOR_INFO inf;
  226.     GetConsoleCursorInfo(thData.output, &inf);
  227.     if(cur_t == _NOCURSOR) {
  228.         inf.bVisible = FALSE;
  229.     } else if(cur_t == _NORMALCURSOR) {
  230.         inf.bVisible = TRUE;
  231.         inf.dwSize = 13;
  232.     } else if(cur_t == _SOLIDCURSOR) {
  233.         inf.bVisible = TRUE;
  234.         inf.dwSize = 100;
  235.     } else return;
  236.     SetConsoleCursorInfo(thData.output, &inf);
  237.     };
  238.  
  239.  
  240. EXTERNC
  241. void textattr(int newattr) {
  242.     thData.attrib = newattr;
  243.     SetConsoleTextAttribute(thData.output, ToWinAttribs(thData.attrib));
  244.     };
  245.  
  246.  
  247. EXTERNC
  248. void textbackground(int newcolor) {
  249.     thData.attrib = (thData.attrib & 0x0f) | ((newcolor & 15) << 4);
  250.     SetConsoleTextAttribute(thData.output, ToWinAttribs(thData.attrib));
  251.     };
  252.  
  253.  
  254. EXTERNC
  255. void textcolor(int newcolor) {
  256.     thData.attrib = (thData.attrib & 0xf0) | (newcolor & 15);
  257.     SetConsoleTextAttribute(thData.output, ToWinAttribs(thData.attrib));
  258.     };
  259.  
  260.  
  261. EXTERNC
  262. void clreol() {
  263.     int cx, cy, n;
  264.     const char *spaces = "                                                                                ";
  265.     GetCP(&cx, &cy);
  266.     // TODO: different window sizes
  267.     cputs(spaces + 80 - cx);
  268.     //TODO: test wrapping at eol
  269.     gotoxy(cx, cy);
  270.     };
  271.  
  272.  
  273. EXTERNC
  274. void clrscr() {
  275.     COORD pos, size;
  276.     SMALL_RECT trg;
  277.     CHAR_INFO *buf;
  278.  
  279.     buf = (CHAR_INFO *)alloca(sizeof(CHAR_INFO) * thData.width * thData.height);
  280.     for(int i = 0; i < thData.width * thData.height; i++) {
  281.         buf[i].Char.AsciiChar = ' ';
  282.         buf[i].Attributes = thData.attrib;
  283.         };
  284.  
  285.     pos.X = 0; pos.Y = 0;
  286.     size.X = thData.width; size.Y = thData.height;
  287.     trg.Left = 0; trg.Top = 0;
  288.     trg.Right = 79; trg.Bottom = thData.height - 1;
  289.     WriteConsoleOutput(thData.output, buf, size, pos, &trg);
  290.     };
  291.  
  292.  
  293. EXTERNC
  294. void delline() {
  295.     int y;
  296.     y = wherey();
  297.     movetext(1, y + 1, thData.width, thData.height, 1, y);
  298.     };
  299.  
  300.  
  301. EXTERNC
  302. void insline() {
  303.     int y;
  304.     y = wherey();
  305.     movetext(1, y, thData.width, thData.height - 1, 1, y + 1);
  306.     };
  307.  
  308.  
  309. EXTERNC
  310. int getch() {
  311.     int ch;
  312.     BOOL rv;
  313.     DWORD n;
  314.     INPUT_RECORD buf;
  315.  
  316.     if(thData.ungetCount > 0) {
  317.         thData.ungetCount--;
  318.         return thData.ungetBuf[thData.ungetCount];
  319.         };
  320.  
  321.     if(thData.charCount > 0) {
  322.         thData.charCount--;
  323.         if(thData.charCount & 1 && thData.charFlag) return 0;
  324.         else return thData.charValue;
  325.         };
  326.  
  327.     while(true) {
  328.         rv = ReadConsoleInput(thData.input, &buf, 1, &n);
  329.         if(rv == false) continue;
  330.         if(buf.EventType != KEY_EVENT) continue;
  331.         if(buf.Event.KeyEvent.bKeyDown == false) continue;
  332.         if(HandleKeyEvent(&buf)) break;
  333.         };
  334.  
  335.     thData.charCount--;
  336.     if(thData.charCount & 1 && thData.charFlag) return 0;
  337.     else return thData.charValue;
  338.     };
  339.  
  340.  
  341. EXTERNC
  342. int getche() {
  343.     int ch;
  344.     ch = getch();
  345.     putch(ch);
  346.     return ch;
  347.     };
  348.  
  349.  
  350. EXTERNC
  351. int kbhit() {
  352.     int ch;
  353.     BOOL rv;
  354.     DWORD n;
  355.     INPUT_RECORD buf;
  356.  
  357.     if(thData.ungetCount > 0) return 1;
  358.     if(thData.charCount > 0) return 1;
  359.  
  360.     rv = PeekConsoleInput(thData.input, &buf, 1, &n);
  361.     if(!rv) return 0;
  362.     if(n == 0) return 0;
  363.     rv = ReadConsoleInput(thData.input, &buf, 1, &n);
  364.     if(rv == false) return 0;
  365.     if(buf.EventType != KEY_EVENT) return 0;
  366.     if(buf.Event.KeyEvent.bKeyDown == false) return 0;
  367.     return HandleKeyEvent(&buf) ? 1 : 0;
  368.     };
  369.  
  370.  
  371. EXTERNC
  372. int ungetch(int ch) {
  373.     if(thData.ungetCount >= 15) return EOF;
  374.     thData.ungetBuf[thData.ungetCount++] = ch;
  375.     return ch;
  376.     };
  377.  
  378.  
  379. EXTERNC
  380. int cputs(const char *str) {
  381.     DWORD count;
  382.     if(str == NULL) return EOF;
  383.     UpdateWScroll();
  384.     if(WriteConsole(thData.output, str, strlen(str), &count, NULL)) return count;
  385.     else return EOF;
  386.     };
  387.  
  388.  
  389. EXTERNC
  390. int putch(int c) {
  391.     DWORD count;
  392.     UpdateWScroll();
  393.     if(WriteConsole(thData.output, &c, 1, &count, NULL)) return c;
  394.     else return EOF;
  395.     };
  396.  
  397.  
  398. EXTERNC
  399. int gettext(int left, int top, int right, int bottom, void *dest) {
  400.     SMALL_RECT trg;
  401.     COORD pos, size;
  402.     CHAR_INFO *buf;
  403.     buf = (CHAR_INFO *)alloca((right - left + 1) * (bottom - top + 1) * sizeof(CHAR_INFO));
  404.  
  405.     pos.X = 0; pos.Y = 0;
  406.     size.X = right - left + 1; size.Y = bottom - top + 1;
  407.     trg.Left = left - 1; trg.Top = top - 1;
  408.     trg.Right = right - 1; trg.Bottom = bottom - 1;
  409.     ReadConsoleOutput(buf, buf, size, pos, &trg);
  410.     for(int i = 0; i < (right - left + 1) * (bottom - top + 1); i++) {
  411.         ((char *)dest)[i * 2] = buf[i].Char.AsciiChar;
  412.         ((char *)dest)[i * 2 + 1] = FromWinAttribs(buf[i].Attributes);
  413.         };
  414.     // TODO: check return values
  415.     return 1;
  416.     };
  417.  
  418.  
  419. EXTERNC
  420. int movetext(int left, int top, int right, int bottom, int destleft, int desttop) {
  421.     char *buf;
  422.     buf = (char *)alloca((right - left + 1) * (bottom - top + 1) * 2);
  423.     gettext(left, top, right, bottom, buf);
  424.     puttext(destleft, desttop, destleft + right - left, desttop + bottom - top, buf);
  425.     // TODO: check return values
  426.     return 1;
  427.     };
  428.  
  429.  
  430. EXTERNC
  431. int puttext(int left, int top, int right, int bottom, void *source) {
  432.     SMALL_RECT trg;
  433.     COORD pos, size;
  434.     CHAR_INFO *buf;
  435.     buf = (CHAR_INFO *)alloca((right - left + 1) * (bottom - top + 1) * sizeof(CHAR_INFO));
  436.     for(int i = 0; i < (right - left + 1) * (bottom - top + 1); i++) {
  437.         buf[i].Char.AsciiChar = ((char *)source)[i * 2];
  438.         buf[i].Attributes = ToWinAttribs(((char *)source)[i * 2 + 1]);
  439.         };
  440.     pos.X = 0; pos.Y = 0;
  441.     size.X = right - left + 1; size.Y = bottom - top + 1;
  442.     trg.Left = left - 1; trg.Top = top - 1;
  443.     trg.Right = right - 1; trg.Bottom = bottom - 1;
  444.     WriteConsoleOutput(buf, buf, size, pos, &trg);
  445.     // TODO: check return values
  446.     return 1;
  447.     };
  448.  
  449.  
  450. EXTERNC
  451. void settitle(const char *title) {
  452.     //linia poniżej generuje błąd w VS2013
  453.     SetConsoleTitleA(title);
  454.     };
  455.  
  456.  
  457. void gettextinfo(struct text_info *info) {
  458.     info->curx = wherex();
  459.     info->cury = wherey();
  460.     info->attribute = thData.attrib;
  461.     info->normattr = 0x07;
  462.     info->screenwidth = thData.width;
  463.     info->screenheight = thData.height;
  464.     };
  465.  
  466.  
  467. void textmode(int mode) {
  468.     int fs = mode & FULLSCREEN;
  469.     mode = mode & (~FULLSCREEN);
  470.     if(mode == C80) {
  471.         thData.width = 80;
  472.         thData.height = 25;
  473.         ResizeConsole(thData.output, 80, 25, 25);
  474.     } else if(mode == C4350) {
  475.         thData.width = 80;
  476.         thData.height = 50;
  477.         ResizeConsole(thData.output, 80, 50, 50);
  478.     } else if(mode == LASTMODE) {
  479.         textmode(thData.lastmode);
  480.         };
  481.     };
  482.  
  483.  
  484. #ifdef _MSC_VER
  485. static int Conio2_Init(void) {
  486.     InitConio2(&thData);
  487.     return 0;
  488.     };
  489.  
  490. static int Conio2_Exit(void) {
  491.     ExitConio2(&thData);
  492.     return 0;
  493.     };
  494.  
  495. typedef int cb(void);
  496.  
  497. #pragma data_seg(".CRT$XIU")
  498. static cb *autostart[] = { Conio2_Init };
  499.  
  500. #pragma data_seg(".CRT$XPU")
  501. static cb *autoexit[] = { Conio2_Exit};
  502.    
  503. #pragma data_seg() /* reset data-segment */
  504. #endif
  505.  
  506. #ifdef __GNUC__
  507. static void Conio2_Exit(void) {
  508.     ExitConio2(&thData);
  509.     };
  510.  
  511. static int Conio2_Init(void) {
  512.     InitConio2(&thData);
  513.     atexit(Conio2_Exit);
  514.     return 0;
  515.     };
  516.  
  517. static int conio2_init = Conio2_Init();
  518. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement