/********************************************************************************* 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 ; }