/*********************************************************************************
source of "nwriter", a basic text-editor for the Nspire; last modified 25.04.11
Copyright (C) 2011 Olivier Thill alias shrear
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
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 .
*********************************************************************************/
#include
#include "screen.h"
void update_buffer(char* store, char* font, int* font_meta, char* screen_buffer, int screen_color, int ycord_start, int xcord_start, int ycord_end, int xcord_end, int index_start, int index)
{
//local variables
int for_control, draw_control, cords_temp ;
int ycord = ycord_start ;
int xcord = xcord_start ;
int write_control = 1 ;
//reset buffer
memset(screen_buffer, screen_color, SCREEN_HEIGHT*SCREEN_WIDTH) ;
//write characters
for ( for_control = index_start ; store[for_control] ; for_control++ )
{
//write char
cords_temp = write_char(store[for_control], font, font_meta, screen_buffer, screen_color, xcord_start, ycord_end, xcord_end, xcord, ycord, write_control) ;
//check if end of page
if ( !cords_temp )
write_control = 0 ;
ycord = cords_temp/65536 ;
xcord = (cords_temp&0x0000FFFF) ;
//draw cursor
if ( for_control == index-1 && write_control )
for ( draw_control = font_meta[2] ; draw_control ; draw_control-- )
if ( screen_color )
screen_buffer[(ycord+draw_control)*SCREEN_WIDTH+xcord-1] = 0x0 ;
else
screen_buffer[(ycord+draw_control)*SCREEN_WIDTH+xcord-1] = 0xF ;
}
//draw cursor manualy if index-1 is never passed
if ( index == index_start )
for ( draw_control = font_meta[2] ; draw_control ; draw_control-- )
if ( screen_color )
screen_buffer[(ycord_start+draw_control)*SCREEN_WIDTH] = 0x0 ;
else
screen_buffer[(ycord_start+draw_control)*SCREEN_WIDTH] = 0xF ;
}
int update_index(char* store, char* font, int* font_meta, int xcord_start, int xcord_end, short* index_line, int line_number)
{
//local variables
int for_control ;
int xcord = 0 ;
int char_location, char_width ;
int line = 0 ;
int index_max = 0 ;
//reset index_line
memset(index_line, 0, line_number*2) ;
for ( for_control = 0 ; store[for_control] ; for_control++ )
{
char_location = store[for_control]*font_meta[4]+(font_meta[6]-1)*font_meta[7] ;
char_width = font[char_location+2]*0x100+font[char_location+3] ;
//check if newline
if ( store[for_control] == 0x0A )
{
line++ ;
index_line[line] = for_control+1 ;
xcord = 0 ;
}
//check if end of line
else if ( xcord+char_width > SCREEN_WIDTH-xcord_end-xcord_start )
{
line++ ;
index_line[line] = for_control+1 ;
xcord = char_width+1 ;
}
else
xcord += char_width+1 ;
//check if valid line number
if ( line+1 > line_number )
error(3) ;
index_max = for_control+1 ;
}
return index_max ;
}
int write_char(char character, char* font, int* font_meta, char* screen_buffer, int screen_color, int xcord_start, int ycord_end, int xcord_end, int xcord, int ycord, int write_control)
{
//local variables
int char_location = character*font_meta[4]+(font_meta[6]-1)*font_meta[7] ;
int char_height = font[char_location]*0x100+font[char_location+1] ;
int char_width = font[char_location+2]*0x100+font[char_location+3] ;
//if control charakter
if ( character < 0x20 )
{
//newline
if ( character == 0x0A )
{
ycord += char_height+1 ;
xcord = xcord_start ;
if ( ycord >= SCREEN_HEIGHT-char_height-ycord_end )
return 0 ;
}
//tab
if ( character == 0x09 )
{
xcord++ ;
while ( xcord%char_width )
xcord++ ;
}
}
//if display character
else
{
//local variables
int y, x, for_control ;
int char_index = 0 ;
int char_size = (font_meta[4]-font_meta[1]*2)*font_meta[0]+font_meta[1]*2 ;
char* char_buffer = (char*)malloc(char_size) ;
char_location += font_meta[1]*2 ;
//check if enough space
if ( xcord+char_width > SCREEN_WIDTH-xcord_end )
{
//increase ycord
ycord += char_height+1 ;
xcord = xcord_start ;
if ( ycord >= SCREEN_HEIGHT-char_height-ycord_end )
return 0 ;
}
//do only if char is to be displayed
if ( write_control )
{
//decommpress char
if ( font_meta[0] == 1 )
for ( for_control = 0 ; for_control < char_size ; for_control++ )
char_buffer[for_control] = font[for_control+char_location] ;
else if ( font_meta[0] == 2)
for ( for_control = 0 ; for_control < char_size ; for_control += 2 )
{
char_buffer[for_control] = (font[for_control/2+char_location]&0xF0)/0x10 ;
char_buffer[for_control+1] = (font[for_control/2+char_location]&0x0F) ;
}
else if ( font_meta[0] == 4)
for ( for_control = 0 ; for_control < char_size ; for_control += 4 )
{
char_buffer[for_control] = (font[for_control/4+char_location]&0xC0)/0x40*0x5 ;
char_buffer[for_control+1] = (font[for_control/4+char_location]&0x30)/0x10*0x5 ;
char_buffer[for_control+2] = (font[for_control/4+char_location]&0x0C)/0x04*0x5 ;
char_buffer[for_control+3] = (font[for_control/4+char_location]&0x03)*0x5 ;
}
else if ( font_meta[0] == 8)
for ( for_control = 0 ; for_control < char_size ; for_control += 8 )
{
char_buffer[for_control] = (font[for_control/8+char_location]&0x80)/0x80*0xF ;
char_buffer[for_control+1] = (font[for_control/8+char_location]&0x40)/0x40*0xF ;
char_buffer[for_control+2] = (font[for_control/8+char_location]&0x20)/0x20*0xF ;
char_buffer[for_control+3] = (font[for_control/8+char_location]&0x10)/0x10*0xF ;
char_buffer[for_control+4] = (font[for_control/8+char_location]&0x08)/0x08*0xF ;
char_buffer[for_control+5] = (font[for_control/8+char_location]&0x04)/0x04*0xF ;
char_buffer[for_control+6] = (font[for_control/8+char_location]&0x02)/0x02*0xF ;
char_buffer[for_control+7] = (font[for_control/8+char_location]&0x01)*0xF ;
}
//change buffer
for (y = ycord ; y < ycord+char_height ; y++ )
for (x = xcord ; x < xcord+char_width ; x++ )
{
if ( screen_color )
screen_buffer[y*SCREEN_WIDTH+x] = char_buffer[char_index] ;
else
screen_buffer[y*SCREEN_WIDTH+x] = 0xF-char_buffer[char_index] ;
char_index++ ;
}
}
//increase xcord
xcord += char_width+1 ;
//free char_buffer
free(char_buffer) ;
}
return ycord*0x10000+xcord ;
}
int write_string(char* string, char* font, int* font_meta, char* screen_buffer, int screen_color, int ycord_start, int xcord_start, int ycord_end, int xcord_end)
{
//local variables
int for_control ;
int ycord = ycord_start ;
int xcord = xcord_start ;
int temp_cords = ycord*0x10000+xcord ;
//write string
for ( for_control = 0 ; string[for_control] ; for_control++ )
{
temp_cords = write_char(string[for_control], font, font_meta, screen_buffer, screen_color, xcord_start, ycord_end, xcord_end, xcord, ycord, 1) ;
ycord = temp_cords/0x10000 ;
xcord = temp_cords-(ycord*0x10000) ;
}
return temp_cords ;
}
int get_offset(char* store, char* font, int* font_meta, int line_start, int index)
{
//local variables
int for_control ;
int offset_x = 0 ;
for ( for_control = line_start ; for_control < index ; for_control++ )
offset_x += font[store[for_control]*font_meta[4]+2]*0x100+font[store[for_control]*font_meta[4]+3] ;
offset_x += (font[store[index]*font_meta[4]+2]*0x100+font[store[index]*font_meta[4]+3])/2 ;
return offset_x ;
}
int get_index(char* store, char* font, int* font_meta, int offset_x, int line_start, int line_end)
{
//local variables
int for_control ;
//check if line_start can be else return 0 ;
if ( !store[line_start] )
return 0 ;
//check if line_end can be else change it
if ( !store[line_end] )
for ( for_control = line_start ; store[for_control] ; for_control++ )
line_end = for_control ;
for ( for_control = line_start ; for_control <= line_end ; for_control++ )
{
offset_x -= font[store[for_control]*font_meta[4]+2]*0x100+font[store[for_control]*font_meta[4]+3] ;
if ( offset_x < 0 )
return for_control ;
}
//return the line "end" if nothing found yet
return line_end ;
}
void display_buffer(char* screen_buffer)
{
//local variables
short ycord, xcord ;
//pass the values in the buffer to the screen "adresses"
for (ycord = 0 ; ycord < SCREEN_HEIGHT ; ycord++)
for ( xcord = 0 ; xcord < SCREEN_WIDTH ; xcord++ )
*(char*)((int)SCREEN_BASE_ADDRESS+((ycord*SCREEN_WIDTH/2)+xcord/2)) = screen_buffer[(ycord*SCREEN_WIDTH+xcord-1)]*16 + (screen_buffer[(ycord*SCREEN_WIDTH+xcord)]) ;
}
int error(int error_id)
{
//display the native textbox with the error message
if ( !error_id )
show_msgbox("Error", "This one shuld never be trigered...\nPlease make a bug report if possible.") ;
else if ( error_id == 1 )
show_msgbox("Error", "Can not load a font.\nMake sure nwriter.font.tns\nis in the same directory as nwriter.\nProgram will terminate.") ;
else if ( error_id == 2 )
show_msgbox("Error", "Invalid index.\nProgram should correct it.\nBut make still a bug report please.") ;
else if ( error_id == 3 )
show_msgbox("Warning", "Maximun number of lines reached.\nContinue on your own risk.") ;
else if ( error_id == 4 )
show_msgbox("Warning", "Maximun number of characters reached.\nContinue on your own risk.") ;
return 0 ;
}