Displays simple html web pages using the uVGA-II.

Dependents:   uVGAII_WebBrowser

BasicWeb.cpp

Committer:
yaolu23
Date:
2013-03-06
Revision:
3:5f688bcc92b9
Parent:
2:ff57d9a43c7d

File content as of revision 3:5f688bcc92b9:

#include "BasicWeb.h"

// table used to convert keyboard scan codes to ASCII
const unsigned char BasicWeb::table[] = {
//  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,'~',  0,      // 0
    0,  0,  0,  0,  0,'q','1',  0,  0,  0,'z','s','a','w','2',  0,      // 1
    0,'c','x','d','e','4','3',  0,  0,' ','v','f','t','r','5',  0,      // 2
    0,'n','b','h','g','y','6',  0,  0,  0,'m','j','u','7','8',  0,      // 3
    0,  0,'k','i','o','0','9',  0,  0,'.','/','l',':','p','_',  0,      // 4
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,      // 5
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,      // 6
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,'-',  0,  0,  0,  0,      // 7
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,      // 8
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0};      // 9

BasicWeb::BasicWeb(PinName tx, PinName rx, PinName reset)
    :vga(tx, rx, reset),
    urlStr("http://www.batw.net/htmllessons/example_page.html"),
    urlIndex(49), str(NULL), bold(false), font(0), color(0x000000), index(0), title(false) {
    
    // initialize uVGA
    vga.baudrate(115200);
    vga.display_control(0x0c, 0x01);      // Set display to VGA 640x480
}

void BasicWeb::browser(){
    // draw browser
    vga.background_color(WHITE);
    vga.rectangle(0, 0, 640, 38, 0xBBBBBB);
    vga.rectangle(30, 20, 636, 34, WHITE);
    displayUrl();
    
    // connect to internet and display IP
    eth.init();
    eth.connect();
    vga.text_string("IP address is:", 50, 1, 1, 0x000000);
    vga.text_string(eth.getIPAddress(), 65, 1, 1, 0x000000);
}

void BasicWeb::displayUrl(){
    vga.rectangle(30, 20, 636, 34, WHITE);      // clear url
    vga.text_string(urlStr, 4, 3, 1, 0x000000);
}

// process new key
void BasicWeb::newKey(char scancode){
    char c = table[scancode];
    if(c != 0){                                 // if a alpha numeric
        urlStr[urlIndex] = c;
        char s[] = {c, 0};
        vga.text_string(s, 4 + urlIndex, 3, 1, 0x000000);
        urlIndex += 1;
        urlStr[urlIndex] = '\0';
    }else{
        if(scancode == 0x66){                   // backspace
            if(urlIndex != 0){
                urlIndex -= 1;
                urlStr[urlIndex] = '\0';
                vga.rectangle(31 + urlIndex*8, 20, 39 + urlIndex*8, 34, WHITE);
            }
        }else if(scancode == 0x5A){             // enter
            int ret = http.get(urlStr, text, 10240);
            if(!ret){
                removeRL(text, 10240);
                index = 0;
                lineIndex = 40;
                vga.rectangle(0, 0, 640, 19, 0xBBBBBB);         // clear title
                vga.rectangle(0, 39, 640, 480, 0xFFFFFF);       // clear page
                displayPage();
            }else{
                vga.graphic_string("Could not fetch page", 21, 0, 1, color, 1, 1);
            }
        }
    }
}

void BasicWeb::modKey(char scancode1, char scancode2){
    if(scancode1 == 0xE0){
        if(scancode2 == 0x72 || scancode2 == 0x74){             // up and right arrow
            vga.rectangle(0, 39, 640, 480, 0xFFFFFF);           // clear page
            lineIndex = 40;
            displayPage();
        }
    }
}

void BasicWeb::displayPage(){
    parseStr();
    while(printText(str)){
        parseStr();
        if(title){
            title = false;
            vga.rectangle(0, 0, 640, 19, 0xBBBBBB);
            vga.text_string(titleStr, 1, 1, 1, 0x000000);
        }
    }
}

/* processes tags up until a string to display is found */
void BasicWeb::parseStr(){
    bool cont = true;
    while(cont){
        while(text[index] == ' ') index++;       // skip white space
        if(text[index] == '\0'){
            str = NULL;
            return;
        }
        if(text[index] == '<'){
            cont = applyTag();
        }else{
            cont = extractStr();
        }
    }
}

/* processes the tag and increment index past it */
bool BasicWeb::applyTag(){
    index++;
    
    // skip comments
    bool comment = true;
    if(text[index] == '!'){
        if(text[index+1] == '-' && text[index+2] == '-'){
            index += 3;
            while(comment){                     // while still in comment body
            
                // check for ending sequence
                if(text[index] == '-'){
                    index += 1;
                    if(text[index] == '-'){
                        index += 1;
                        if(text[index] == '>'){
                            comment = false;    // break out of comment
                        }
                    }
                }else{
                    index++;
                }
            }
            comment = true;                     // reset comment flag
        }
        while(text[index] != '>') index++;
        index++;
        return true;
    }
    
    // process tag
    int i = 0;
    if(compareTag(text + index, "title")){
        index += 6;
        title = true;
        while(text[index+i] != '<' && text[index+i] != '\0'){
            i++;
        }
        if(i < 30){
            copyStr(text + index, titleStr, i);
        }else{
            copyStr(text + index, titleStr, 30);
        }
        index += i;
    }else if(compareTag(text + index, "script")){               // skip script
        index += 7;
        while(text[index] != '\0'){
            if(text[index] == '<'){
                index++;
                if(compareTag(text + index, "/script")){
                    index += 8;
                    break;
                }
            }
            index++;
        }
    }else if(compareTag(text + index, "style")){                // skip style
        index += 6;
        while(text[index] != '\0'){
            if(text[index] == '<'){
                index++;
                if(compareTag(text + index, "/style")){
                    index += 7;
                    break;
                }
            }
            index++;
        }
    }else if(compareTag(text + index, "br")){
        index += 3;
        lineIndex += 10;
    }else if(compareTag(text + index, "/br")){
        index += 3;
        lineIndex += 10;
    }else if(compareTag(text + index, "b")){
        index += 2;
        font += 1;
    }else if(compareTag(text + index, "/b")){
        index += 3;
        font -= 1;
    }else if(compareTag(text + index, "h1")){
        index += 3;
        font = 3;
    }else if(compareTag(text + index, "/h1")){
        index += 4;
        font = 0;
    }else if(compareTag(text + index, "h2")){
        index += 3;
        font = 2;
    }else if(compareTag(text + index, "/h2")){
        index += 4;
        font = 0;
    }else if(compareTag(text + index, "h3")){
        index += 3;
        font = 1;
    }else if(compareTag(text + index, "/h3")){
        index += 4;
        font = 0;
    }else{
        while(text[index+i] != '>') i++;
        index += i + 1;
    }
    
    return true;
}

/* checks string against given tag */
bool BasicWeb::compareTag(char* s, char* tag){
    int i = 0;
    while(s[i] != '>' && s[i] != '\0'){
        if(s[i] != tag[i]) return false;
        i++;
    }
    if(tag[i] != '\0'){
        return false;
    }else{
        return true;
    }
}

/* stores string up to the start of the next tag into str variable */
bool BasicWeb::extractStr(){

    // skip white space
    int i = 0;
    while(text[index+i] == ' ') i++;
    index += i;
    
    if(text[index+1] == '<'){
        index++;
        return true;
    }
    
    i = 0;
    while(text[index+i] != '<' && text[index+i] != '\0'){
        i++;
    }
    delete[] str;
    str = new char[i + 1];
    copyStr(text + index, str, i);
    index += i;
    strSize = i;
    return false;
}

/* copies s1 into s2 upto given size */
void BasicWeb::copyStr(char* s1, char* s2, int size){
    int i;
    for(i = 0; i < size; i++){
        s2[i] = s1[i];
        if(s1[i] == '\0') return;
    }
    s2[i] = '\0';
}

/* removes CR and LR because they causes problems for vga print function */
void BasicWeb::removeRL(char* s, int size){
    for(int i = 0; i < size; i++){
        if(s[i] == '\r' || s[i] == '\n') s[i] = ' ';
    }
}

/* prints text one line at a time, returning false if at end of screen */
bool BasicWeb::printText(char* s){

    if(s == NULL){
        index = 0;
        return false;
    }

    int maxChar;
    switch(font){
        case 0:
            maxChar = 105;
            break;
        case 1:
            maxChar = 70;
            break;
        case 2:
            maxChar = 65;
            break;
        case 3:
            maxChar = 50;
            break;
        default:
            maxChar = 100;
    }
    
    char* temp;
    int i = strSize;
    int lineNum = 0;
    
    if(i < maxChar){
        vga.graphic_string(s, 0, lineIndex, font, color, 1, 1);
        if(font == 3){
            lineIndex += 20;
        }else{
            lineIndex += 10;
        }
        if(lineIndex < 480){
            return true;
        }else{
            return false;
        }
    }else{
        temp = new char[maxChar + 1];
        while(i > 0){
            if(i > maxChar){
                copyStr(s + lineNum * maxChar, temp, maxChar);
                i -= maxChar;
            }else{
                copyStr(s + lineNum * maxChar, temp, i);
                i = 0;
            }
            vga.graphic_string(temp, 0, lineIndex, font, color, 1, 1);
            lineNum++;
            if(font == 3){
                lineIndex += 20;
            }else{
                lineIndex += 10;
            }
            if(lineIndex >= 480){
                delete[] temp;
                return false;
            }
        }
        delete[] temp;
    }
    return true;
}