/*
* This file is part of the uHex project.
* Copyright (C) 2015 Alexey Voskov
*
* Win32 API I/O driver that allows to port uHex to Windows NT platform
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*/
#include "io.h"
#include <windows.h>
static HANDLE hStdin = NULL, hStdout = NULL;
static int currentX = 0, currentY = 0;
static int screenWidth = 0, screenHeight = 0;
static COORD originalBufferSize;
void io_init(void) {
CONSOLE_SCREEN_BUFFER_INFO cinfo;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (GetConsoleScreenBufferInfo(hStdout, &cinfo)) {
currentX = cinfo.dwCursorPosition.X;
currentY = cinfo.dwCursorPosition.Y;
screenWidth = cinfo.dwSize.X;
screenHeight = cinfo.dwSize.Y;
originalBufferSize = cinfo.dwSize;
if (screenHeight > 50) {
cinfo.dwSize.Y = 50;
screenHeight = 50;
SetConsoleScreenBufferSize(hStdout, cinfo.dwSize);
}
}
ShowCursor(FALSE);
}
void io_close(void) {
cls(0);
SetConsoleScreenBufferSize(hStdout, originalBufferSize);
}
void cursor_hide(void) {
ShowCursor(FALSE);
}
void cursor_show(void) {
ShowCursor(TRUE);
}
void locate(int row, int column) {
COORD pos;
pos.Y = row; currentY = row;
pos.X = column; currentX = column;
SetConsoleCursorPosition(hStdout, pos);
}
static void printbufferyx(int y, int x, CHAR_INFO *buf, int len) {
COORD bufferSize, bufferCoord = {0, 0};
SMALL_RECT writeRegion;
bufferSize.X = len;
bufferSize.Y = 1;
writeRegion.Top = y;
writeRegion.Left = x;
writeRegion.Bottom = y;
writeRegion.Right = x + len - 1;
WriteConsoleOutput(hStdout, buf, bufferSize, bufferCoord, &writeRegion);
}
void printchar(char c, int attr) {
CHAR_INFO buf;
if ((unsigned char)c < 32) {
buf.Char.AsciiChar = '.';
} else {
buf.Char.AsciiChar = c;
}
buf.Attributes = attr;
printbufferyx(currentY, currentX, &buf, 1);
}
void printattrstringyx(int y, int x, char *sym, int *attr, int len) {
CHAR_INFO *buf;
int i;
buf = LocalAlloc(0, len*sizeof(CHAR_INFO));
for (i = 0; i < len; i++) {
if ((unsigned char)sym[i] < 32) {
buf[i].Char.AsciiChar = '.';
} else {
buf[i].Char.AsciiChar = sym[i];
}
buf[i].Attributes = attr[i];
}
printbufferyx(y, x, buf, len);
LocalFree(buf);
}
int getkey(void) {
INPUT_RECORD rec;
DWORD nEventsRead;
int scan, ascii;
do {
WaitForSingleObject(hStdin, INFINITE);
ReadConsoleInput(hStdin, &rec, 1, &nEventsRead);
} while (!(rec.EventType == KEY_EVENT &&
rec.Event.KeyEvent.bKeyDown &&
rec.Event.KeyEvent.wVirtualKeyCode != VK_MENU));
FlushConsoleInputBuffer(hStdin);
ascii = rec.Event.KeyEvent.uChar.AsciiChar;
scan = rec.Event.KeyEvent.wVirtualScanCode;
if (ascii == 0) return (0x100 | scan);
DWORD ctrlstate = rec.Event.KeyEvent.dwControlKeyState;
if (ctrlstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
switch (ascii) {
case 'f': return(0x121);
case 'h': return(0x123);
case 'j': return(0x124);
case 's': return(0x11F);
case 'u': return(0x116);
default: return ascii;
}
} else {
return(ascii);
}
}
void cls(int colattr) {
char *str;
int i, *attr;
str = LocalAlloc(0, screenWidth);
attr = LocalAlloc(0, screenWidth * sizeof(int));
memset(str, ' ', screenWidth);
/* Create attribute string:
pos 0-79 - colattr, 80-screenWidth - 0 */
for (i = 0; i < 80; i++) {
attr[i] = colattr;
}
for (i = 80; i < screenWidth; i++) {
attr[i] = 0;
}
for (i = 0; i < screenHeight; i++) {
printattrstringyx(i, 0, str, attr, screenWidth);
}
locate(0, 0);
LocalFree(str);
LocalFree(attr);
}
int computecolor(int doscol) {
return(doscol);
}
void getcurvideomode(int *termwidth, int *termheight, int *colorflag) {
*termwidth = screenWidth;
*termheight = screenHeight;
*colorflag = 1; /* No monochrome mode in Win32 */
}