//
//  lcd_vcd.h	Part of Graphic LCD module I/O library, Character display emulation
//  Copyright(C)2013-2017 Toyohiko Togashi tog001@nifty.com
//
//
//  This program is free software; you can redistribute it and/or modify it under the terms of the
//  GNU General Public License as published by the Free Software Foundation; either version 3
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//  See the GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License along with this program.
//  If not, see <http://www.gnu.org/licenses/>
//
//
//    Update history
//    ---------- ----- -------------------------------------------
//    2013.01.22 v0.0  First cording
//    2014.03.15 v0.2  Rename source file: s95160_3.c -> lcd_vcd.c
//    2017.04.15 v0.3  Supported a System Workbench for STM32
//

#include "lcd_vcd.h"					//
#include "lcd_draw.h"					//

#ifdef VCD_USE_STDIO
#include <stdio.h>						// libc
#include <sys/unistd.h>					// libc
#include <errno.h>						// libc
#endif


//
//	Default view port
//
vcd_desc vcd_stdout = {
	0,
	0,
	LCD_SCREEN_WIDTH,
	LCD_SCREEN_HEIGHT,
	0,
	0,
//	LCD_COLOR_GREEN,
//	LCD_COLOR_LIME,
	LCD_COLOR_WHITE,
	LCD_COLOR_BLACK,
	1
};
unsigned char	vcd_openFlag = 0;


//
// Cursor move
//
void vcd_position(
	vcd_desc	*p,						// Control table pointer
	short		column,					//
	short		row						//
) {
	if (vcd_openFlag == 0) {
		lcd_drawOpen();
	    vcd_openFlag = 1;
	}

	if (p->cursor) {
		lcd_drawRect(p->x1 + p->x, p->y1 + p->y, LCD_FONT_WIDTH, LCD_FONT_HEIGHT, p->bcolor);
	}

	p->x = column * VCD_FONT_WIDTH;
	p->y = row    * VCD_FONT_HEIGHT;

	if (p->cursor) {
		lcd_drawRect(p->x1 + p->x, p->y1 + p->y, LCD_FONT_WIDTH, LCD_FONT_HEIGHT, p->fcolor);
	}
	return;
}

//
// Special display function
//
void vcd_control(
	vcd_desc		*p,						// Control table pointer
	unsigned char	cmd						// Command code
) {
	if (vcd_openFlag == 0) {
		lcd_drawOpen();
	    vcd_openFlag = 1;
	}

	if (p->cursor) {
		lcd_drawRect(p->x1 + p->x, p->y1 + p->y, LCD_FONT_WIDTH, LCD_FONT_HEIGHT, p->bcolor);
	}

	switch(cmd) {
	case LCD_DISP_BLANK:
		lcd_drawRect(p->x1, p->y1, p->w, p->h, p->bcolor);
		break;
	case LCD_DISP_CLEAR_HOME:
		lcd_drawRect(p->x1, p->y1, p->w, p->h, p->bcolor);
		p->x = 0;
		p->y = 0;
		break;
	case LCD_CURSOR_HOME:
		p->x = 0;
		p->y = 0;
		break;
	case LCD_CURSOR_LEFT:
		p->x -= VCD_FONT_WIDTH;
		if (p->x < 0) {
			p->x = 0;
		}
		break;
	case LCD_CURSOR_RIGHT:
		if (p->x < (p->w - VCD_FONT_WIDTH)) {
			p->x += VCD_FONT_WIDTH;
		}
		break;
	case LCD_CURSOR_ON:
		p->cursor = 1;
		break;
	case LCD_CURSOR_OFF:
		p->cursor = 0;
		break;
	default:
		break;
	}

	if (p->cursor) {
		lcd_drawRect(p->x1 + p->x, p->y1 + p->y, LCD_FONT_WIDTH, LCD_FONT_HEIGHT, p->fcolor);
	}
	return;
}

//
// Display text string
//
#ifdef DELETE							// DEL START 2017.04.15
void vcd_print(
	vcd_desc	*p,						// Control table pointer
	char		*str					// Text string
) {
	char	c;

	if (vcd_openFlag == 0) {
		lcd_drawOpen();
	    vcd_openFlag = 1;
	}

	while((c = *str++) != '\0') {

		c &= 0b01111111;

		// Visual char
		if (c >= ' ') {
			lcd_drawChar(p->x1 + p->x, p->y1 + p->y, p->fcolor, p->bcolor, c);
			p->x += VCD_FONT_WIDTH;

		// LF
		} else if (c == '\n') {
			lcd_drawRect(p->x1 + p->x, p->y1 + p->y, ((p->w)-(p->x)), LCD_FONT_HEIGHT, p->bcolor);
			p->x = 0;
			p->y += VCD_FONT_HEIGHT;

		// CR
		} else if (c == '\r') {
			p->x = 0;

		// FF (Clear home)
		} else if (c == '\f') {
			vcd_control(p, LCD_DISP_CLEAR_HOME);

		// VT (Home)
		} else if (c == '\v') {
			vcd_control(p, LCD_CURSOR_HOME);
		}

		// View range out
		if ((p->x) > (p->w - VCD_FONT_WIDTH)) {	// X over
			p->x = 0;					// Next line
			p->y += VCD_FONT_HEIGHT;
		}
		if ((p->y) > (p->h - VCD_FONT_HEIGHT)) {	// Y over
			p->y = 0;					// Top line
		}
	}

#ifdef VCD_SPLIT_LINE
	if (p->x == 0) {
		lcd_drawRect(p->x1, p->y1 + p->y, p->w, VCD_FONT_HEIGHT, VCD_SPLIT_LINE);
	}
#endif

	// Cursor
	if (p->cursor) {
		lcd_drawRect(p->x1 + p->x, p->y1 + p->y, LCD_FONT_WIDTH, LCD_FONT_HEIGHT, p->fcolor);
	}

	return;
}
#else									//  DEL END - ADD START 2017.04.15
void vcd_char(
	vcd_desc	*p,						// Control table pointer
	char		c						// Character
) {
	if (vcd_openFlag == 0) {
		lcd_drawOpen();
	    vcd_openFlag = 1;
	}

	c &= 0b01111111;

	// Visual char
	if (c >= ' ') {
		lcd_drawChar(p->x1 + p->x, p->y1 + p->y, p->fcolor, p->bcolor, c);
		p->x += VCD_FONT_WIDTH;

	// LF
	} else if (c == '\n') {
		lcd_drawRect(p->x1 + p->x, p->y1 + p->y, ((p->w)-(p->x)), LCD_FONT_HEIGHT, p->bcolor);
		p->x = 0;
		p->y += VCD_FONT_HEIGHT;

	// CR
	} else if (c == '\r') {
		p->x = 0;

	// FF (Clear home)
	} else if (c == '\f') {
		vcd_control(p, LCD_DISP_CLEAR_HOME);

	// VT (Home)
	} else if (c == '\v') {
		vcd_control(p, LCD_CURSOR_HOME);
	}

	// View range out
	if ((p->x) > (p->w - VCD_FONT_WIDTH)) {	// X over
		p->x = 0;					// Next line
		p->y += VCD_FONT_HEIGHT;
	}
	if ((p->y) > (p->h - VCD_FONT_HEIGHT)) {	// Y over
		p->y = 0;					// Top line
	}

#ifdef VCD_SPLIT_LINE
	if (p->x == 0) {
		lcd_drawRect(p->x1, p->y1 + p->y, p->w, VCD_FONT_HEIGHT, VCD_SPLIT_LINE);
	}
#endif

	// Cursor
	if (p->cursor) {
		lcd_drawRect(p->x1 + p->x, p->y1 + p->y, LCD_FONT_WIDTH, LCD_FONT_HEIGHT, p->fcolor);
	}

	return;
}

void vcd_print(
	vcd_desc	*p,						// Control table pointer
	char		*str					// Text string
) {
	char	c;

	while((c = *str++) != '\0') {
		vcd_char(p, c);
	}
	return;
}
#endif


//
// "stdio.h" relation
//
#ifdef VCD_USE_STDIO					// "system call" is taken over
#ifdef STM32							// ADD START 2017.04.15  IDE=="System Workbench for STM32"
int __io_putchar(int ch) {
	lcd_char(ch);
	return(ch);
}
#else									// ADD END 2017.04.15
int _write(int file, char *ptr, int len) {
	char	buf[16];
	char	*p;
	int		l;
	int		i;

	switch (file) {
	case STDOUT_FILENO:
	case STDERR_FILENO:
		l = len;
		while(l > 0) {
    		p = buf;
			for(i = 0; i < (sizeof(buf)-1); i++) {
				if (l <= 0) {
					break;
				}
				*p++ = *ptr++;
				--l;
			}
			*p = '\0';
			lcd_print(buf);
		}
		break;
	default:
		errno = EBADF;
        len = -1;
        break;
	}

	return(len);
}
#endif	// STM32						// ADD 2017.04.15
#endif	// VCD_USE_STDIO
