// binclock.c
// displays system time in binary, hex, and decimal

#include <stdio.h>
#include <dos.h>
#include <conio.h>

void draw_frame(void);
void border(void);
void calc_bits(int value, char* bits);
void show_bits(char* bits);
void show_big(char* bits);
int ctrlbrk_handler(void);

struct text_info screen;

int main(void)
{
	int cursorx, cursory;
	struct time t;
	struct time newt;
	char hourbits[9], minbits[9], secbits[9];
	char hit;
	int formatflag = 1;
	int loopcontrol = 1;

	cursorx = 37;
	cursory = 21;
	ctrlbrk(ctrlbrk_handler);
	gettextinfo(&screen);
	_setcursortype(_NOCURSOR);
	textbackground(BLUE);
	highvideo();
	clrscr();
	draw_frame();
	gettime(&t);
	calc_bits(t.ti_hour, hourbits);
	calc_bits(t.ti_min, minbits);
	calc_bits(t.ti_sec, secbits);
	gotoxy(6, 2);
	show_big(hourbits);
	gotoxy(6, 10);
	show_big(minbits);
	gotoxy(6, 18);
	show_big(secbits);
	while (loopcontrol)
	{
		do
		{
			gettime(&newt);
		} while (newt.ti_sec == t.ti_sec && !kbhit());
		t = newt;
		calc_bits(t.ti_hour, hourbits);
		calc_bits(t.ti_min, minbits);
		calc_bits(t.ti_sec, secbits);
		if (kbhit())
		{
			hit = getch();
			if (hit == '\0') hit = getch(); // for extended scancode
			if (hit == ';') // for the F1 key
			{
				clrscr();
				if (formatflag == 0)
				{
					formatflag = 1;
					draw_frame();
				}
				else
				{
					formatflag = 0;
					border();
				}
			}
			else loopcontrol = 0;
		}
		if (formatflag == 0)
		{
			gotoxy(14, 2);
			show_bits(hourbits);
			gotoxy(14, 8);
			show_bits(minbits);
			gotoxy(14, 14);
			show_bits(secbits);
			gotoxy(cursorx, cursory + 3);
			cprintf("%s %s %s", hourbits, minbits, secbits);
				gotoxy(cursorx, cursory);
			cprintf("   %2d       %2d       %2d",
					t.ti_hour, t.ti_min, t.ti_sec);
			gotoxy(cursorx, cursory + 1);
			cprintf("   %2X       %2X       %2X",
				t.ti_hour, t.ti_min, t.ti_sec);
			gotoxy(cursorx, cursory + 2);
			cprintf("   %2o       %2o       %2o",
				t.ti_hour, t.ti_min, t.ti_sec);
		}
		else
		{
			gotoxy(6, 2);
			show_big(hourbits);
			gotoxy(6, 10);
			show_big(minbits);
			gotoxy(6, 18);
			show_big(secbits);
		}
	}
	_setcursortype(_NORMALCURSOR);
	textmode(screen.currmode);
	normvideo();
	clrscr();
	return 0;
}

void calc_bits(int value, char* bits)
{
	int filter = 1;
	int bit;
	bits[8] = '\0';
	for (bit = 0; bit < 8; bit++)
	{
		if (value & filter)
			bits[7 - bit] = '1';
		else
			bits[7 - bit] = '0';
		filter *= 2;
	}
	return;
}

void draw_frame(void)
{
	int i, cursory;
	// É is 201
	// Í is 205
	// » is 187
	// È is 200
	// ¼ is 188
	// º is 186
	textcolor(WHITE);
	gotoxy(2, 1);
	putch(201);
	for (i = 0; i < 31; i++)
		putch(205);
	cputs(" Binary Clock ");
	for (i = 45; i < 76; i++)
		putch(205);
	putch(187);
	for (cursory = 2; cursory < 25; cursory++)
	{
		gotoxy(2, cursory);
		putch(186);
		gotoxy(79, cursory);
		putch(186);
	}
	gotoxy(2, 25);
	putch(200);
	for (i = 0; i < 32; i++)
		putch(205);
	cputs(" F1 = Zoom ");
	for (i = 43; i < 76; i++)
		putch(205);
	putch(188);
	textcolor(YELLOW);
	return;
}

void border(void)
{
	// Ä is 196
	// Ç is 199
	// ¶ is 182
	int i;
	draw_frame();
	textcolor(WHITE);
	gotoxy(2, 19);
	putch(199);
	gotoxy(79, 19);
	putch(182);
	gotoxy(3, 19);
	for (i = 0; i < 76; i++)
		putch(196);
	gotoxy(18, 20);
	cputs("                     Hours  Minutes  Seconds");
	gotoxy(18, 21);
	cputs("Decimal time     : ");
	gotoxy(18, 22);
	cputs("Hexadecimal time : ");
	gotoxy(18, 23);
	cputs("Octal time       : ");
	gotoxy(18, 24);
	cputs("Binary time      : ");
	textcolor(YELLOW);
	return;
}

void show_bits(char* bits)
{
	// Û is 219 or xDB
	// ° is 176 or xB0
	int i, j;
	int cursorx = wherex();
	int cursory = wherey();
	for (i = 0; i < 5; i++)
	{
		gotoxy(cursorx, cursory);
		for (j = 0; j < 8; j++)
			if (bits[j] == '1')
			{
				cputs("\xDB\xDB\xDB\xDB\xDB\  ");
			}
			else
			{
				textcolor(WHITE);
				cputs("\xB0\xB0\xB0\xB0\xB0\  ");
				textcolor(YELLOW);
			}
		cursory++;
	}
	return;
}

void show_big(char* bits)
{
	int i, j;
	int cursorx = wherex();
	int cursory = wherey();
	for (i = 0; i < 7; i++)
	{
		gotoxy(cursorx, cursory);
		for (j = 0; j < 8; j++)
			if (bits[j] == '1')
			{
				cputs("\xDB\xDB\xDB\xDB\xDB\xDB\xDB\  ");
			}
			else
			{
				textcolor(WHITE);
				cputs("\xB0\xB0\xB0\xB0\xB0\xB0\xB0\  ");
				textcolor(YELLOW);
			}
		cursory++;
	}
	return;
}

int ctrlbrk_handler(void)
{
	_setcursortype(_NORMALCURSOR);
	textmode(screen.currmode);
	normvideo();
	clrscr();
	return 0;
}