#define SCROLLTEXT_C #define _XOPEN_SOURCE 600 #include #include #include #include #include "../config.h" #include "scrolltext.h" #include "../pixel.h" #include "../util.h" #include "font_arial8.h" // #include "font_small6.h" // #include "font_uni53.h" #ifdef __CYGWIN__ #define strtok_r(a, b, c) strtok((a), (b)) #endif #define MAX_FONTS 1 font fonts[MAX_FONTS]; #define MAX_SPECIALCOLORS 3 unsigned char PROGMEM colorTable[MAX_SPECIALCOLORS*NUM_ROWS] = {1, 1, 2, 3, 3, 2, 1, 1, 3, 3, 2, 1, 1, 2, 3, 3, 3, 3, 2, 2, 3, 3, 2, 2 }; char default_text[] PROGMEM = SCROLLTEXT_TEXT; char scrolltext_text[SCROLLTEXT_BUFFER_SIZE]; /* Konzept ======= Text wird in Token unterteilt, jeder Token bekommt einen Command-String. z.B. #bstr; unsigned char tmp[200], x=0; while(*str){ tmp[x++] = (*str++) + ' ' -1; } tmp[x] = 0; printf("this:\t%x\n",blob); printf("last:\t%x\n",blob->last); printf("next:\t%x\n",blob->next); printf("str:\t%s\n",tmp); printf("cmd:\t%s\n",blob->commands); printf("sizex\t%d\n",blob->sizex); printf("posx\t%d\n",blob->posx); printf("posy\t%d\n",blob->posy); printf("tox\t%d\n",blob->tox); printf("toy\t%d\n",blob->toy); printf("delayy_rld\t%d\n",blob->delayx_rld); printf("delayx_rld\t%d\n",blob->delayy_rld); printf("timer\t%d\n",blob->timer); printf("\n"); } */ #define PW(a) pgm_read_word(&(a)) #define PB(a) pgm_read_byte(&(a)) unsigned int getLen(blob_t *blob) { unsigned char glyph; unsigned int strLen = 0; unsigned char * str = (unsigned char*)blob->str; uint8_t space = blob->space * blob->font_storebytes; while ((glyph = *str++)) { glyph -= 1; strLen += PW(blob->fontIndex[glyph+1]) - PW(blob->fontIndex[glyph]); strLen += space; } return strLen/blob->font_storebytes; } unsigned int getnum(blob_t * blob){ unsigned int num=0; unsigned char gotnum = 0; while( (*blob->commands >= '0') && (*blob->commands <='9') ){ gotnum = 1; num *= 10; num += *blob->commands - '0'; blob->commands++; } if(gotnum){ return num; }else{ return 0xffff; } } unsigned char blobNextCommand(blob_t * blob){ unsigned int tmp; unsigned char retval = 0; while(*blob->commands != 0){ switch (*blob->commands++){ case '<': blob->direction &= ~DIRECTION_RIGHT; if((tmp = getnum(blob)) != 0xFFFF){ blob->delayx_rld = tmp; }else{ blob->delayx_rld = SCROLL_X_SPEED; } blob->delayx = blob->delayx_rld; break; case '>': blob->direction |= DIRECTION_RIGHT; if((tmp = getnum(blob)) != 0xFFFF){ blob->delayx_rld = tmp; }else{ blob->delayx_rld = SCROLL_X_SPEED; } blob->delayx = blob->delayx_rld; break; case 'd': blob->direction |= DIRECTION_DOWN; if((tmp = getnum(blob)) != 0xFFFF){ blob->delayy_rld = tmp; }else{ blob->delayy_rld = SCROLL_Y_SPEED; } blob->delayy = blob->delayy_rld; break; case 'u': blob->direction &= ~DIRECTION_DOWN; if((tmp = getnum(blob)) != 0xFFFF){ blob->delayy_rld = tmp; }else{ blob->delayy_rld = SCROLL_Y_SPEED; } blob->delayy = blob->delayy_rld; break; case 'x'://Place string at this x Position if((tmp = getnum(blob)) != 0xFFFF){ blob->posx = tmp; }else{ blob->posx = NUM_COLS/2 + blob->sizex/2; } break; case 'y'://Place string at this y Position if((tmp = getnum(blob)) != 0xFFFF){ blob->posy = tmp - blob->sizey; } break; case 'b'://blink blob if((tmp = getnum(blob)) != 0xFFFF){ blob->delayb_rld = tmp; }else{ blob->delayb_rld = 50; } blob->delayb = blob->delayb_rld; break; case '|': if((tmp = getnum(blob)) != 0xFFFF){ blob->tox = tmp; }else{ blob->tox = (NUM_COLS - 2 + blob->sizex)/2; } blob->waitfor = wait_posx; return retval; break; case '-': if((tmp = getnum(blob)) != 0xFFFF){ blob->toy = tmp; }else{ blob->toy = (NUM_ROWS-blob->sizey) / 2; } blob->waitfor = wait_posy; return retval; break; case 'p': blob->delayx_rld = 0; blob->delayy_rld = 0; if((tmp = getnum(blob)) != 0xFFFF){ blob->timer = tmp*64; }else{ blob->timer = 30*64; } blob->waitfor = wait_timer; return retval; break; case '/': blob->waitfor = wait_out; return retval; break; case ';': blob->waitfor = wait_col_l; return (retval); break; case ':': blob->waitfor = wait_col_r; return (retval); break; case '+': retval = 2; break; } } return 1;//this blob is finished, and can be deleted. } blob_t * setupBlob(char * str){ static unsigned char chop_cnt; static char *last; static char delim[] = "#"; static char *lastcommands; unsigned int tmp; blob_t *blob = malloc(sizeof (blob_t)); if(str){ #ifndef AVR // on non-AVR archs strtok_r fails for some reason if it operates on a // string which is located on another stack frame, so we need our own copy memcpy (blob->scrolltextBuffer, str, SCROLLTEXT_BUFFER_SIZE); str = blob->scrolltextBuffer; #endif chop_cnt = 0; } if(!chop_cnt){ blob->commands = strtok_r (str, delim, &last); if( blob->commands == 0) goto fail; if((tmp = getnum(blob)) != 0xFFFF){ chop_cnt = tmp; lastcommands = blob->commands; } } if(chop_cnt){ chop_cnt--; blob->commands = lastcommands; } blob->str = strtok_r (NULL, delim, &last); if ( blob->str == 0) goto fail; blob->fontIndex = fonts[0].fontIndex; blob->fontData = fonts[0].fontData; blob->font_storebytes = fonts[0].storebytes; unsigned char tmp1, *strg = (unsigned char*)blob->str; unsigned char glyph_beg = fonts[0].glyph_beg; unsigned char glyph_end = fonts[0].glyph_end; //translate the string: subtract 1 to get offset in Table while((tmp1 = *strg)){ if((tmp1>=glyph_beg) && (tmp1space = 1; blob->sizey = fonts[0].fontHeight; blob->sizex = getLen(blob); if(*blob->commands == '<'){ blob->posx = 0; blob->posy = (NUM_ROWS-blob->sizey)/2; }else if(*blob->commands == '>'){ blob->posx = NUM_COLS+blob->sizex; blob->posy = (NUM_ROWS-blob->sizey)/2; }else if(*blob->commands == 'd'){ blob->posy = -blob->sizey; blob->posx = (NUM_COLS - 2 + blob->sizex)/2; }else if(*blob->commands == 'u'){ blob->posy = blob->sizey; blob->posx = (NUM_COLS - 2 + blob->sizex)/2; }else if(*blob->commands == 'x'){ blob->posy = (NUM_ROWS-blob->sizey)/2; }else if(*blob->commands == 'y'){ blob->posx = (NUM_COLS - 2 + blob->sizex)/2; } blob->delayx_rld = 0; blob->delayy_rld = 0; blob->delayb_rld = 0; blob->waitfor = wait_new; return blob; fail: free(blob); return 0;//no more blobs to parse } unsigned char updateBlob(blob_t * blob){ if(blob->delayx_rld && (!(blob->delayx--))){ blob->delayx = blob->delayx_rld; (blob->direction & DIRECTION_RIGHT)?blob->posx--:blob->posx++; } if(blob->delayy_rld && (!(blob->delayy--))){ blob->delayy = blob->delayy_rld; (blob->direction & DIRECTION_DOWN)?blob->posy++:blob->posy--; } if(blob->delayb_rld){ if(!(blob->delayb--)){ blob->delayb = blob->delayb_rld; blob->visible ^= 1; } }else{ blob->visible = 1; } unsigned char done=0; switch (blob->waitfor){ case wait_posy: if (blob->posy == blob->toy)done = 1; break; case wait_posx: if (blob->posx == blob->tox)done = 1; break; case wait_out: if((blob->posx - blob->sizex) > NUM_COLS || blob->posx < 0) done = 1; if((blob->posy) > NUM_ROWS || (blob->posy + blob->sizey) <0 ) done = 1; break; case wait_timer: if(0 == blob->timer--){ done = 1; } break; case wait_col_l: if(blob->last){ if((blob->last->posx - blob->last->sizex) == blob->posx){ done=1; } }else{ done = 1; } break; case wait_col_r: if(blob->next){ if(blob->next->posx == (blob->posx - blob->sizex)){ done=1; } }else{ done = 1; } break; default: done = 1; break; } if(done){ return (blobNextCommand(blob)); } return 0; } void drawBlob(blob_t *blob) { char x, y; unsigned char byte=0, glyph, storebytes; unsigned int charPos, charEnd; unsigned int posx; unsigned char posy, toy; if(!blob->visible) return; unsigned char * str = (unsigned char*)blob->str; posx = blob->posx; posy = blob->posy; toy = posy + blob->sizey; storebytes = blob->font_storebytes; glyph = (*blob->str)-1; charPos = PW(blob->fontIndex[glyph]); charEnd = PW(blob->fontIndex[glyph+1]); while (posx >= NUM_COLS) { charPos += storebytes; if (charPos < charEnd) { posx--; }else{ posx -= blob->space + 1; if (!(glyph = *++str)) return; glyph -= 1; charPos = PW(blob->fontIndex[glyph]); charEnd = PW(blob->fontIndex[glyph+1]); } } for (x = posx; x >= 0; x-- ) { unsigned char mask = 0; unsigned int datpos; datpos = charPos; for (y = posy; (y < NUM_ROWS) && (y < toy); y++) { if((mask<<=1) == 0){ mask = 0x01; byte = PB(blob->fontData[datpos++]); } if ((byte & mask) && y >= 0 ) { text_setpixel((pixel){x, y},1); } } charPos += storebytes; if (charPos < charEnd) { }else{ x -= blob->space; if (!(glyph = *++str)) return; glyph -= 1; charPos = PW(blob->fontIndex[glyph]); charEnd = PW(blob->fontIndex[glyph+1]); } } } extern jmp_buf newmode_jmpbuf; void scrolltext(char *str) { jmp_buf tmp_jmpbuf; char tmp_str[SCROLLTEXT_BUFFER_SIZE]; int ljmp_retval; fonts[0] = SCROLLTEXT_FONT; text_pixmap = malloc(NUM_ROWS * LINEBYTES); if(scrolltext_text[0] == 0){ strcpy_P(scrolltext_text, default_text); } memcpy(tmp_str, str, SCROLLTEXT_BUFFER_SIZE); blob_t *startblob=0, *aktblob, *nextblob=0; memcpy (tmp_jmpbuf, newmode_jmpbuf, sizeof(jmp_buf)); if((ljmp_retval = setjmp(newmode_jmpbuf))){ while(startblob){ aktblob = startblob; startblob = aktblob->next; free(aktblob); } free(text_pixmap); memcpy (newmode_jmpbuf, tmp_jmpbuf, sizeof(jmp_buf)); longjmp(newmode_jmpbuf, ljmp_retval); } if (!(startblob = setupBlob(tmp_str))){ goto exit; } unsigned char retval; do{ startblob->next = 0; startblob->last = 0; while(startblob){ aktblob = startblob; while(aktblob){ retval = updateBlob(aktblob); if(!retval){ nextblob = aktblob->next; }else if(retval == 1){ if(aktblob == startblob){ startblob = aktblob->next; }else{ aktblob->last->next = aktblob->next; } if(aktblob->next){ aktblob->next->last = aktblob->last; } nextblob = aktblob->next; free(aktblob); }else if(retval == 2){ blob_t * newblob = setupBlob(0); if (newblob){ newblob->last = aktblob; newblob->next = aktblob->next; if(aktblob->next){ aktblob->next->last = newblob; } aktblob->next = newblob; } nextblob = aktblob->next; } aktblob = nextblob; } aktblob = startblob; clear_text_pixmap(0); while(aktblob){ drawBlob(aktblob); aktblob = aktblob->next; } update_pixmap(); wait(2); }; startblob = setupBlob(0); //showBlob(startblob); }while(startblob); exit: free(text_pixmap); memcpy (newmode_jmpbuf, tmp_jmpbuf, sizeof(jmp_buf)); }