URI:
       tcursesport.c - vaccinewars - be a doctor and try to vaccinate the world
  HTML git clone git://src.adamsgaard.dk/vaccinewars
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tcursesport.c (7418B)
       ---
            1 /************************************************************************
            2  * cursesport.c   Portability functions to enable curses applications   *
            3  *                     to be built on Win32 systems                     *
            4  * Copyright (C)  1998-2021  Ben Webb                                   *
            5  *                Email: benwebb@users.sf.net                           *
            6  *                WWW: https://dopewars.sourceforge.io/                 *
            7  *                                                                      *
            8  * This program is free software; you can redistribute it and/or        *
            9  * modify it under the terms of the GNU General Public License          *
           10  * as published by the Free Software Foundation; either version 2       *
           11  * of the License, or (at your option) any later version.               *
           12  *                                                                      *
           13  * This program is distributed in the hope that it will be useful,      *
           14  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
           15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
           16  * GNU General Public License for more details.                         *
           17  *                                                                      *
           18  * You should have received a copy of the GNU General Public License    *
           19  * along with this program; if not, write to the Free Software          *
           20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,               *
           21  *                   MA  02111-1307, USA.                               *
           22  ************************************************************************/
           23 
           24 #ifdef HAVE_CONFIG_H
           25 #include <config.h>
           26 #endif
           27 
           28 #include "cursesport.h"
           29 #include "dopewars.h"
           30 #include <glib.h>
           31 
           32 #ifdef CYGWIN                   /* Code for native Win32 build under Cygwin */
           33 
           34 int COLS, LINES;
           35 
           36 static int Width, Depth;
           37 static CHAR_INFO RealScreen[25][80], VirtualScreen[25][80];
           38 static HANDLE hOut, hIn;
           39 static int CurAttr = 0;
           40 static int CurX, CurY;
           41 static WORD Attr[10];
           42 
           43 void refresh(void)
           44 {
           45   int y;
           46   COORD size, offset;
           47   SMALL_RECT screenpos;
           48 
           49   move(CurY, CurX);
           50   for (y = 0; y < Depth; y++) {
           51     if (memcmp(&RealScreen[y][0], &VirtualScreen[y][0],
           52                sizeof(CHAR_INFO) * Width) != 0) {
           53       memcpy(&RealScreen[y][0], &VirtualScreen[y][0],
           54              Width * sizeof(CHAR_INFO));
           55       size.X = Width;
           56       size.Y = 1;
           57       offset.X = offset.Y = 0;
           58       screenpos.Left = 0;
           59       screenpos.Top = y;
           60       screenpos.Right = Width - 1;
           61       screenpos.Bottom = y;
           62       WriteConsoleOutputW(hOut, &VirtualScreen[y][0], size,
           63                           offset, &screenpos);
           64     }
           65   }
           66 }
           67 
           68 static HANDLE WINAPI GetConHandle(TCHAR *pszName)
           69 {
           70   SECURITY_ATTRIBUTES sa;
           71 
           72   sa.nLength = sizeof(sa);
           73   sa.lpSecurityDescriptor = NULL;
           74   sa.bInheritHandle = TRUE;
           75   return CreateFile(pszName, GENERIC_READ | GENERIC_WRITE,
           76                     FILE_SHARE_READ | FILE_SHARE_WRITE,
           77                     &sa, OPEN_EXISTING, (DWORD)0, (HANDLE)0);
           78 }
           79 
           80 SCREEN *newterm(void *a, void *b, void *c)
           81 {
           82   int i;
           83 
           84   Width = COLS = 80;
           85   Depth = LINES = 25;
           86   CurAttr = 1 << 16;
           87   CurX = 0;
           88   CurY = 0;
           89   for (i = 0; i < 10; i++)
           90     Attr[i] = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
           91   hOut = GetConHandle("CONOUT$");
           92   hIn = GetConHandle("CONIN$");
           93   SetConsoleMode(hIn, 0);
           94   SetConsoleMode(hOut, 0);
           95   return NULL;
           96 }
           97 
           98 void start_color(void)
           99 {
          100 }
          101 
          102 void init_pair(int index, WORD fg, WORD bg)
          103 {
          104   if (index >= 0 && index < 10) {
          105     Attr[index] = 0;
          106     switch (fg) {
          107     case COLOR_MAGENTA:
          108       Attr[index] |= (FOREGROUND_RED + FOREGROUND_BLUE);
          109       break;
          110     case COLOR_BLUE:
          111       Attr[index] |= FOREGROUND_BLUE;
          112       break;
          113     case COLOR_RED:
          114       Attr[index] |= FOREGROUND_RED;
          115       break;
          116     case COLOR_WHITE:
          117       Attr[index] |= (FOREGROUND_RED + FOREGROUND_BLUE + FOREGROUND_GREEN);
          118       break;
          119     }
          120     switch (bg) {
          121     case COLOR_MAGENTA:
          122       Attr[index] |= (BACKGROUND_RED + BACKGROUND_BLUE);
          123       break;
          124     case COLOR_BLUE:
          125       Attr[index] |= BACKGROUND_BLUE;
          126       break;
          127     case COLOR_RED:
          128       Attr[index] |= BACKGROUND_RED;
          129       break;
          130     case COLOR_WHITE:
          131       Attr[index] |= (BACKGROUND_RED + BACKGROUND_BLUE + BACKGROUND_GREEN);
          132       break;
          133     }
          134   }
          135 }
          136 
          137 void cbreak(void)
          138 {
          139 }
          140 
          141 void noecho(void)
          142 {
          143 }
          144 
          145 void nodelay(void *a, char b)
          146 {
          147 }
          148 
          149 void keypad(void *a, char b)
          150 {
          151 }
          152 
          153 void curs_set(BOOL visible)
          154 {
          155   CONSOLE_CURSOR_INFO ConCurInfo;
          156 
          157   ConCurInfo.dwSize = 10;
          158   ConCurInfo.bVisible = visible;
          159   SetConsoleCursorInfo(hOut, &ConCurInfo);
          160 }
          161 
          162 void endwin(void)
          163 {
          164   CurAttr = 0;
          165   refresh();
          166   curs_set(1);
          167 }
          168 
          169 void move(int y, int x)
          170 {
          171   COORD coord;
          172 
          173   if (x >= Width) {
          174     x = 0;
          175   }
          176   if (y >= Depth) {
          177     y = 0;
          178   }
          179   CurX = x;
          180   CurY = y;
          181   coord.X = x;
          182   coord.Y = y;
          183   SetConsoleCursorPosition(hOut, coord);
          184 }
          185 
          186 void attrset(int newAttr)
          187 {
          188   CurAttr = newAttr;
          189 }
          190 
          191 void addstr(const char *str)
          192 {
          193   int i;
          194   for (i = 0; i < strlen(str); i++)
          195     addch((guchar)str[i]);
          196 }
          197 
          198 void addch(unsigned ch_and_attr)
          199 {
          200   int attr;
          201   unsigned int ch;
          202   gunichar gch;
          203   /* Keep track of a UTF-8-encoded character */
          204   static char utf8_str[4];
          205   static int utf8_width = 0;
          206   static int utf8_pos = 0;
          207 
          208   ch = ch_and_attr & 0xFFFF;
          209 
          210   if (ch > 0xFF || ch <= 0x7F) {
          211     /* Already Unicode (e.g. box-drawing character), or ASCII */
          212     VirtualScreen[CurY][CurX].Char.UnicodeChar = ch;
          213   } else if (ch & 64) {
          214     /* UTF-8 encoded; first byte (get the width) */
          215     utf8_width = ch & 16 ? 4 : ch & 32 ? 3 : 2;
          216     utf8_pos = 0;
          217     utf8_str[utf8_pos++] = ch;
          218     return;
          219   } else {
          220     /* UTF-8 encoded; intermediate or last byte */
          221     utf8_str[utf8_pos++] = ch;
          222     if (utf8_pos < utf8_width) return;
          223     gch = g_utf8_get_char(utf8_str);
          224     /* Windows console can only handle 2-byte Unicode */
          225     VirtualScreen[CurY][CurX].Char.UnicodeChar = gch > 0xFFFF ? '?' : gch;
          226   }
          227 
          228   attr = ch_and_attr >> 16;
          229   if (attr > 0)
          230     VirtualScreen[CurY][CurX].Attributes = Attr[attr];
          231   else
          232     VirtualScreen[CurY][CurX].Attributes = Attr[CurAttr >> 16];
          233   if (++CurX >= Width) {
          234     CurX = 0;
          235     if (++CurY >= Depth)
          236       CurY = 0;
          237   }
          238 }
          239 
          240 void mvaddstr(int y, int x, const char *str)
          241 {
          242   move(y, x);
          243   addstr(str);
          244 }
          245 
          246 void mvaddch(int y, int x, int ch)
          247 {
          248   move(y, x);
          249   addch(ch);
          250 }
          251 
          252 /* 
          253  * Waits for the user to press a key.
          254  */
          255 gunichar bgetch(void)
          256 {
          257   DWORD NumRead;
          258   WCHAR Buffer[10];
          259 
          260   refresh();
          261   ReadConsoleW(hIn, Buffer, 1, &NumRead, NULL);
          262   return (int)(Buffer[0]);
          263 }
          264 
          265 void standout(void)
          266 {
          267 }
          268 
          269 void standend(void)
          270 {
          271 }
          272 
          273 #else /* Code for Unix build */
          274 
          275 /* 
          276  * Calls the curses getch() function; if the key pressed is Ctrl-L
          277  * then automatically clears and redraws the screen, otherwise just
          278  * passes the key back to the calling routine.
          279  */
          280 gunichar bgetch()
          281 {
          282   int c;
          283 
          284   c = getch();
          285   while (c == '\f') {
          286     wrefresh(curscr);
          287     c = getch();
          288   }
          289   /* Ignore special keys (e.g arrow keys) so we don't confuse them with
          290    * Unicode characters */
          291   if (c > 255) {
          292     return 0;
          293   }
          294   /* In UTF-8 locales we may need to read multiple bytes to assemble a
          295      complete Unicode character */
          296   if (LocaleIsUTF8 && (c & 192) == 192) {   /* First UTF-8 byte */
          297     char utf8_str[10];
          298     int i, utf8_width = c & 16 ? 4 : c & 32 ? 3 : 2;
          299     utf8_str[0] = (guchar)c;
          300     for (i = 1; i < utf8_width; ++i) {
          301       utf8_str[i] = (guchar)getch();
          302     }
          303     return g_utf8_get_char(utf8_str);
          304   }
          305   return c;
          306 }
          307 
          308 #endif /* CYGWIN */