{
int F,R=rad,ssx=startx+_sx,ssy=starty+_sy,dxx=_ex-_sx,dyy=_ey-_sy,rx,ry,wx,wy,count;
- unsigned char *pos=(lbb+(ssx<<2)+fix_screeninfo.line_length*ssy);
- unsigned char *pos0, *pos1, *pos2, *pos3, *i;
- unsigned char pix[4]={bl[col],gn[col],rd[col],tr[col]};
+ uint32_t *pos = lbb + ssx + stride * ssy;
+ uint32_t *pos0, *pos1, *pos2, *pos3, *i;
+ uint32_t pix = bgra[col];
if (dxx<0)
{
- printf("[msgbox] RenderBox called with dx < 0 (%d)\n", dxx);
+ printf("msgbox RenderBox called with dx < 0 (%d)\n", dxx);
dxx=0;
}
rx=R-ssx;
ry=R-ssy;
- pos0=pos+((dyy-ry)*fix_screeninfo.line_length);
- pos1=pos+(ry*fix_screeninfo.line_length);
- pos2=pos+(rx*fix_screeninfo.line_length);
- pos3=pos+((dyy-rx)*fix_screeninfo.line_length);
+ pos0=pos+(dyy-ry)*stride;
+ pos1=pos+ry*stride;
+ pos2=pos+rx*stride;
+ pos3=pos+(dyy-rx)*stride;
+
while (ssx <= ssy)
{
rx=R-ssx;
wx=rx<<1;
wy=ry<<1;
- for(i=pos0+(rx<<2); i<pos0+((rx+dxx-wx)<<2);i+=4)
- memcpy(i, pix, 4);
- for(i=pos1+(rx<<2); i<pos1+((rx+dxx-wx)<<2);i+=4)
- memcpy(i, pix, 4);
- for(i=pos2+(ry<<2); i<pos2+((ry+dxx-wy)<<2);i+=4)
- memcpy(i, pix, 4);
- for(i=pos3+(ry<<2); i<pos3+((ry+dxx-wy)<<2);i+=4)
- memcpy(i, pix, 4);
+ for(i=pos0+rx; i<pos0+rx+dxx-wx;i++)
+ *i = pix;
+ for(i=pos1+rx; i<pos1+rx+dxx-wx;i++)
+ *i = pix;
+ for(i=pos2+ry; i<pos2+ry+dxx-wy;i++)
+ *i = pix;
+ for(i=pos3+ry; i<pos3+ry+dxx-wy;i++)
+ *i = pix;
ssx++;
- pos2-=fix_screeninfo.line_length;
- pos3+=fix_screeninfo.line_length;
+
+ pos2-=stride;
+ pos3+=stride;
+
if (F<0)
{
F+=(ssx<<1)-1;
{
F+=((ssx-ssy)<<1);
ssy--;
- pos0-=fix_screeninfo.line_length;
- pos1+=fix_screeninfo.line_length;
+
+ pos0-=stride;
+ pos1+=stride;
}
}
- pos+=R*fix_screeninfo.line_length;
+ pos+=R*stride;
}
for (count=R; count<(dyy-R); count++)
{
- for(i=pos; i<pos+(dxx<<2);i+=4)
- memcpy(i, pix, 4);
- pos+=fix_screeninfo.line_length;
+ for(i=pos; i<pos+dxx;i++)
+ *i = pix;
+ pos+=stride;
}
}
-
-
#ifndef __GFX_H__
-
#define __GFX_H__
void RenderBox(int sx, int sy, int ex, int ey, int mode, int color);
#include <errno.h>
#include <locale.h>
#include <fcntl.h>
-#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <linux/input.h>
-#include "msgbox.h"
-
+#include <poll.h>
+#include <stdint.h>
#include "io.h"
+#include "msgbox.h"
-#define RC_DEVICE "/dev/input/nevis_ir"
extern int instance;
struct input_event ev;
static unsigned short rccode=-1;
-static int rc = 0;
+static int rc;
int InitRC(void)
{
- rc = open(RC_DEVICE, O_RDONLY);
+ rc = open(RC_DEVICE, O_RDONLY | O_CLOEXEC);
if(rc == -1)
{
perror("msgbox <open remote control>");
return 0;
}
+void ClearRC(void)
+{
+ struct pollfd pfd;
+ pfd.fd = rc;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
-int GetRCCode(void)
+ do
+ poll(&pfd, 1, 300);
+ while(read(rc, &ev, sizeof(ev)) == sizeof(ev));
+}
+
+int GetRCCode(int timeout_in_ms)
{
- int rv;
-
- if(!RCKeyPressed() || (get_instance()>instance))
+ int rv = -1;
+
+ if (get_instance()>instance)
{
- return -1;
+ return rv;
}
- rv=rccode;
- while(RCKeyPressed());
-
- return rv;
-}
+ if (timeout_in_ms) {
+ struct pollfd pfd;
+ struct timeval tv;
+ uint64_t ms_now, ms_final;
+
+ pfd.fd = rc;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ gettimeofday( &tv, NULL );
+ ms_now = tv.tv_usec/1000 + tv.tv_sec * 1000;
+ if (timeout_in_ms > 0)
+ ms_final = ms_now + timeout_in_ms;
+ else
+ ms_final = UINT64_MAX;
+ while (ms_final > ms_now) {
+ switch(poll(&pfd, 1, timeout_in_ms)) {
+ case -1:
+ perror("GetRCCode: poll() failed");
+ case 0:
+ return -1;
+ default:
+ ;
+ }
+ if(RCKeyPressed()) {
+ rv = rccode;
+ while(RCKeyPressed());
+ return rv;
+ }
+ gettimeofday( &tv, NULL );
+ ms_now = tv.tv_usec/1000 + tv.tv_sec * 1000;
+ if (timeout_in_ms > 0)
+ timeout_in_ms = (int)(ms_final - ms_now);
+ }
+ } else if(RCKeyPressed()) {
+ rv = rccode;
+ while(RCKeyPressed());
+ }
+ return rv;
+}
#ifndef __IO_H__
-
#define __IO_H__
#define RC_DEVICE "/dev/input/nevis_ir"
int InitRC(void);
int CloseRC(void);
int RCKeyPressed(void);
-int GetRCCode(void);
+int GetRCCode(int);
+void ClearRC(void);
#endif
#include "gfx.h"
#include "txtform.h"
-#define M_VERSION 1.18
+#define M_VERSION 1.20
#define NCF_FILE "/var/tuxbox/config/neutrino.conf"
#define HDF_FILE "/tmp/.msgbox_hidden"
// if font is not in usual place, we look here:
#define FONT "/share/fonts/neutrino.ttf"
-FT_Error error;
-FT_Library library;
-FTC_Manager manager;
-FTC_SBitCache cache;
-FTC_SBit sbit;
-#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0
-FTC_Image_Desc desc;
-#else
-FTC_ImageTypeRec desc;
-#endif
-
-FT_Face face;
-FT_Bool use_kerning;
-FT_UInt prev_glyphindex;
-
-char *butmsg[MAX_BUTTONS];
-struct fb_fix_screeninfo fix_screeninfo;
-struct fb_var_screeninfo var_screeninfo;
-int startx, starty, sx, ex, sy, ey, debounce, rblock;
-int fb;
-
// CMCST, CMCS, CMCT, CMC, CMCIT, CMCI, CMHT, CMH
// WHITE, BLUE0, TRANSP, CMS, ORANGE, GREEN, YELLOW, RED
unsigned char tr[] = { 0xFF, 0xFF, 0xFF, 0xA0, 0xFF, 0xA0, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+uint32_t bgra[20];
+
void TrimString(char *strg);
// OSD stuff
char *line_buffer=NULL, *title=NULL;
int size=24, type=0, timeout=0, refresh=3, flash=0, selection=0, tbuttons=0, buttons=0, bpline=3, echo=0, absolute=0, mute=1, header=1, cyclic=1;
-int rbutt[16],hide=0,radius=10;
+char *butmsg[16];
+int rbutt[16],hide=0,radius=11;
// Misc
const char NOMEM[]="msgbox <Out of memory>\n";
char TMP_FILE[64]="/tmp/msgbox.tmp";
-unsigned char *lfb = 0, *lbb = 0, *obb = 0, *hbb = 0, *ibb = 0;
-unsigned char nstr[BUFSIZE]="";
-unsigned char *trstr;
-unsigned char sc[8]={'a','o','u','A','O','U','z','d'}, tc[8]={0xE4,0xF6,0xFC,0xC4,0xD6,0xDC,0xDF,0xB0};
-unsigned char rc = ' ';
+uint32_t *lfb = NULL, *lbb = NULL, *obb = NULL, *hbb = NULL, *ibb = NULL;
+char nstr[BUFSIZE]={0};
+char *trstr;
const char INST_FILE[]="/tmp/rc.locked";
int instance=0;
+int stride;
int get_instance(void)
{
void put_instance(int pval)
{
+FILE *fh;
+
if(pval)
{
- FILE *fh;
if((fh=fopen(INST_FILE,"w"))!=NULL)
{
fputc(pval,fh);
}
}
-static void quit_signal()
+static void quit_signal(int sig)
{
put_instance(get_instance()-1);
- printf("msgbox Version %.2f killed\n",M_VERSION);
+ printf("%s Version %.2f killed, signal %d\n", "msgbox", M_VERSION, sig);
exit(1);
}
int Read_Neutrino_Cfg(char *entry)
{
FILE *nfh;
+char tstr [512], *cfptr=NULL;
int rv=-1;
if((nfh=fopen(NCF_FILE,"r"))!=NULL)
{
- char tstr [512]={0}, *cfptr=NULL;
+ tstr[0]=0;
+
while((!feof(nfh)) && ((strstr(tstr,entry)==NULL) || ((cfptr=strchr(tstr,'='))==NULL)))
{
fgets(tstr,500,nfh);
if(strlen(pt2))
{
rbutt[btn]=tbuttons;
- butmsg[btn]=strdup(pt2);
+ size_t l = strlen(pt2);
+ char *t = (char *)alloca(l * 4 + 1);
+ memcpy(t, pt2, l + 1);
+ TranslateString(t, l * 4);
+ butmsg[btn]=strdup(t);
CatchTabs(butmsg[btn++]);
}
if(run)
int show_txt(int buttonly)
{
FILE *tfh;
-int x1,y1,cut,rv=-1,btns=buttons,lbtns=(buttons>bpline)?bpline:buttons,blines=1+((btns-1)/lbtns);
+int i,bx,by,x1,y1,rv=-1,run=1,line=0,action=1,cut,itmp,btns=buttons,lbtns=(buttons>bpline)?bpline:buttons,blines=1+((btns-1)/lbtns);
if(hide)
{
- memcpy(lfb, hbb, fix_screeninfo.line_length*var_screeninfo.yres);
+ memcpy(lfb, hbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
return 0;
}
- yo=40+((header)?FSIZE_MED*5/4:0);
+ yo=20+((header)?FSIZE_MED*5/4:0);
if(!buttonly)
{
- memcpy(lbb, ibb, fix_screeninfo.line_length*var_screeninfo.yres);
+ memcpy(lbb, ibb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
}
if((tfh=fopen(TMP_FILE,"r"))!=NULL)
{
if(type==1)
{
myo=blines*(butty+buttdy);
- int itmp = 0,i;
for(i=0; i<btns; i++)
{
itmp=GetStringLen(sx,butmsg[i], 26)+10;
if(btns)
{
buttxstart=psx+pxw/2-(((double)lbtns*(double)buttsize+(((lbtns>2)&&(lbtns&1))?((double)buttdx):0.0))/2.0);
- buttystart=psy+y1*dy;
+ buttystart=psy+y1*dy+15;
}
}
- int bx,by,run=1,line=0,action=1;
+
while(run)
{
//frame layout
{
if(!buttonly)
{
- RenderBox(psx-20, psy-yo, psx+pxw+20, psy+pyw+myo, radius, CMH);
- RenderBox(psx-20+2, psy-yo+2, psx+pxw+20-2, psy+pyw+myo-2, radius, CMC);
+ RenderBox(psx-20, psy-yo, psx+pxw+20, psy+pyw+myo+15, radius, CMH);
+ RenderBox(psx-20+2, psy-yo+2, psx+pxw+20-2, psy+pyw+myo+15-2, radius, CMC);
if(header)
{
RenderBox(psx-20, psy-yo+2-FSIZE_BIG/2, psx+pxw+20, psy-yo+FSIZE_BIG*3/4, radius, CMH);
RenderString(title, psx, psy-yo+FSIZE_BIG/2, pxw, CENTER, FSIZE_BIG, CMHT);
}
}
- if(buttonly || !(rv=fh_txt_load(TMP_FILE, psx, pxw, psy, dy, size, line, &cut)))
+ if(buttonly || !(rv=fh_txt_load(TMP_FILE, psx, pxw, psy+15, dy, size, line, &cut)))
{
if(type==1)
{
- int i;
for(i=0; i<btns; i++)
{
bx=i%lbtns;
RenderString(butmsg[i], buttxstart+bx*(buttsize+buttdx/2), buttystart+by*(butty+buttdy/2)+butty-7, buttsize, CENTER, 26, (i==(selection-1))?CMCST:CMCIT);
}
}
- memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres);
+ memcpy(lfb, lbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
}
}
run=0;
if((xfh=fopen(msg,"r"))!=NULL)
{
fclose(xfh);
- snprintf(TMP_FILE,sizeof(TMP_FILE),"%s",msg);
+ strcpy(TMP_FILE,msg);
}
else
{
}
else
{
+ size_t l = strlen(msg);
+ char *t = (char *)alloca(l * 4 + 1);
+ memcpy(t, msg, l + 1);
+ TranslateString(t, l * 4);
+ msg = t;
+
if((xfh=fopen(TMP_FILE,"w"))!=NULL)
{
while(*msg)
int main (int argc, char **argv)
{
-int index=0,tv=0,found=0, spr=0;
-int dloop=1, rcc=-1, cupd=0;
-char rstr[BUFSIZE]={0}, *rptr=NULL, *aptr=NULL;
-time_t tm1=0,tm2=0;
-//clock_t tk1=0;
+int ix,tv,found=0, spr;
+int dloop=1, rcc=-1;
+char rstr[BUFSIZE]={0}, *rptr, *aptr;
+time_t tm1,tm2;
FILE *fh;
if(argc<2)
{
if(strstr(aptr,"title=")!=NULL)
{
- title=strdup(rptr);
+ size_t l = strlen(rptr);
+ char *t = (char *)alloca(l * 4 + 1);
+ memcpy(t, rptr, l + 1);
+ TranslateString(t, l * 4);
+ title = strdup(t);
CatchTabs(title);
+
if(strcmp(title,"none")==0)
{
header=0;
ey=620;
- for(index=CMCST; index<=CMH; index++)
+ for(ix=CMCST; ix<=CMH; ix++)
{
- sprintf(rstr,"menu_%s_alpha",menucoltxt[index]);
+ sprintf(rstr,"menu_%s_alpha",menucoltxt[ix]);
if((tv=Read_Neutrino_Cfg(rstr))>=0)
- tr[index]=255-(float)tv*2.55;
+ tr[ix]=255-(float)tv*2.55;
- sprintf(rstr,"menu_%s_blue",menucoltxt[index]);
+ sprintf(rstr,"menu_%s_blue",menucoltxt[ix]);
if((tv=Read_Neutrino_Cfg(rstr))>=0)
- bl[index]=(float)tv*2.55;
+ bl[ix]=(float)tv*2.55;
- sprintf(rstr,"menu_%s_green",menucoltxt[index]);
+ sprintf(rstr,"menu_%s_green",menucoltxt[ix]);
if((tv=Read_Neutrino_Cfg(rstr))>=0)
- gn[index]=(float)tv*2.55;
+ gn[ix]=(float)tv*2.55;
- sprintf(rstr,"menu_%s_red",menucoltxt[index]);
+ sprintf(rstr,"menu_%s_red",menucoltxt[ix]);
if((tv=Read_Neutrino_Cfg(rstr))>=0)
- rd[index]=(float)tv*2.55;
+ rd[ix]=(float)tv*2.55;
}
+ for (ix = 0; ix <= RED; ix++)
+ bgra[ix] = (tr[ix] << 24) | (rd[ix] << 16) | (gn[ix] << 8) | bl[ix];
+
if(Read_Neutrino_Cfg("rounded_corners")>0)
- radius=10;
+ radius=11;
else
radius=0;
perror("msgbox <FBIOGET_VSCREENINFO>\n");
return -1;
}
- if(!(lfb = (unsigned char*)mmap(0, fix_screeninfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0)))
+
+ if(!(lfb = (uint32_t*)mmap(0, fix_screeninfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0)))
{
perror("msgbox <mapping of Framebuffer>\n");
return -1;
use_kerning = FT_HAS_KERNING(face);
- desc.flags = FT_LOAD_MONOCHROME;
+ desc.flags = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT;
//init backbuffer
munmap(lfb, fix_screeninfo.smem_len);
return -1;
}
+ stride = fix_screeninfo.line_length/sizeof(uint32_t);
if(!(obb = malloc(fix_screeninfo.line_length*var_screeninfo.yres)))
{
if(refresh & 1)
{
- memcpy(ibb, lfb, fix_screeninfo.line_length*var_screeninfo.yres);
+ memcpy(ibb, lbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
}
else
{
- memset(ibb, TRANSP, fix_screeninfo.line_length*var_screeninfo.yres);
+ memset(ibb, TRANSP, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
}
if(mute==2)
{
- memcpy(hbb, lfb, fix_screeninfo.line_length*var_screeninfo.yres);
+ memcpy(hbb, lbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
}
else
{
- memset(hbb, TRANSP, fix_screeninfo.line_length*var_screeninfo.yres);
+ memset(hbb, TRANSP, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
}
if(refresh & 2)
{
- memcpy(obb, lfb, fix_screeninfo.line_length*var_screeninfo.yres);
+ memcpy(obb, lbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
}
else
{
- memset(obb, TRANSP, fix_screeninfo.line_length*var_screeninfo.yres);
+ memset(obb, TRANSP, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
}
startx = sx;
//main loop
while((rcc!=KEY_EXIT) && (rcc!=KEY_OK) && ((timeout==-1)||((tm2-tm1)<timeout)))
{
- rcc=GetRCCode();
+ rcc=GetRCCode(1000);
if(rcc!=-1)
{
time(&tm1);
}
else
{
+ if(cyclic)
+ show_txt(0);
+#if 0
if(++cupd>100)
{
if(cyclic)
}
}
usleep(10000L);
+#endif
}
if(mute && rcc==KEY_MUTE)
{
hide^=1;
show_txt(0);
- usleep(500000L);
- while(GetRCCode()!=-1);
+
+ while(GetRCCode(300)!=-1);
if(hide)
{
if((fh=fopen(HDF_FILE,"w"))!=NULL)
//cleanup
- memcpy(lfb, obb, fix_screeninfo.line_length*var_screeninfo.yres);
+ memcpy(lfb, obb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t));
munmap(lfb, fix_screeninfo.smem_len);
close(fb);
free(lbb);
#ifndef __MSGBOX_H__
-
#define __MSGBOX_H__
+#include <config.h>
+#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <stdint.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#define MAX_BUTTONS 16
#define BUFSIZE 4095
-extern unsigned char FONT[64];
-
enum {LEFT, CENTER, RIGHT};
-extern FT_Error error;
-extern FT_Library library;
-extern FTC_Manager manager;
-extern FTC_SBitCache cache;
-extern FTC_SBit sbit;
+FT_Error error;
+FT_Library library;
+FTC_Manager manager;
+FTC_SBitCache cache;
+FTC_SBit sbit;
#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0
-extern FTC_Image_Desc desc;
+FTC_Image_Desc desc;
#else
-extern FTC_ImageTypeRec desc;
+FTC_ImageTypeRec desc;
#endif
-extern FT_Face face;
-extern FT_UInt prev_glyphindex;
-extern FT_Bool use_kerning;
+FT_Face face;
+FT_UInt prev_glyphindex;
+FT_Bool use_kerning;
// rc codes
//devs
-extern int fb;
+int fb;
//framebuffer stuff
extern int FSIZE_SMALL;
extern int TABULATOR;
-extern unsigned char *lfb, *lbb, *obb, *hbb;
+extern uint32_t *lfb, *lbb, *obb, *hbb;
-extern struct fb_fix_screeninfo fix_screeninfo;
-extern struct fb_var_screeninfo var_screeninfo;
-extern unsigned char rd[],gn[],bl[],tr[];
+struct fb_fix_screeninfo fix_screeninfo;
+struct fb_var_screeninfo var_screeninfo;
+extern uint32_t bgra[];
+extern int stride;
+
+int startx, starty, sx, ex, sy, ey;
+//int debounce, rblock;
-extern int startx, starty, sx, ex, sy, ey, debounce, rblock;
-extern unsigned char sc[8], tc[8];
extern char *butmsg[MAX_BUTTONS];
extern int buttons,selection;
extern int instance;
int get_instance(void);
void put_instance(int pval);
+#ifndef FB_DEVICE
#define FB_DEVICE "/dev/fb/0"
+#endif
#endif
#include "text.h"
#include "gfx.h"
#include "io.h"
+#include "msgbox.h"
int FSIZE_BIG=28;
int FSIZE_MED=24;
int FSIZE_SMALL=20;
int TABULATOR=72;
+static char *sc = "aouAOUzd",
+ *su= "\xA4\xB6\xBC\x84\x96\x9C\x9F",
+ *tc="\xE4\xF6\xFC\xC4\xD6\xDC\xDF\xB0";
+
+// from neutrino/src/driver/fontrenderer.cpp
+int UTF8ToUnicode(char **textp, const int utf8_encoded) // returns -1 on error
+{
+ int unicode_value, i;
+ char *text = *textp;
+ if (utf8_encoded && ((((unsigned char)(*text)) & 0x80) != 0))
+ {
+ int remaining_unicode_length;
+ if ((((unsigned char)(*text)) & 0xf8) == 0xf0) {
+ unicode_value = ((unsigned char)(*text)) & 0x07;
+ remaining_unicode_length = 3;
+ } else if ((((unsigned char)(*text)) & 0xf0) == 0xe0) {
+ unicode_value = ((unsigned char)(*text)) & 0x0f;
+ remaining_unicode_length = 2;
+ } else if ((((unsigned char)(*text)) & 0xe0) == 0xc0) {
+ unicode_value = ((unsigned char)(*text)) & 0x1f;
+ remaining_unicode_length = 1;
+ } else {
+ (*textp)++;
+ return -1;
+ }
+
+ *textp += remaining_unicode_length;
+
+ for (i = 0; *text && i < remaining_unicode_length; i++) {
+ text++;
+ if (((*text) & 0xc0) != 0x80) {
+ remaining_unicode_length = -1;
+ return -1; // incomplete or corrupted character
+ }
+ unicode_value <<= 6;
+ unicode_value |= ((unsigned char)(*text)) & 0x3f;
+ }
+ } else
+ unicode_value = (unsigned char)(*text);
+
+ (*textp)++;
+ return unicode_value;
+}
+
+void CopyUTF8Char(char **to, char **from)
+{
+ int remaining_unicode_length;
+ if (!((unsigned char)(**from) & 0x80))
+ remaining_unicode_length = 1;
+ else if ((((unsigned char)(**from)) & 0xf8) == 0xf0)
+ remaining_unicode_length = 4;
+ else if ((((unsigned char)(**from)) & 0xf0) == 0xe0)
+ remaining_unicode_length = 3;
+ else if ((((unsigned char)(**from)) & 0xe0) == 0xc0)
+ remaining_unicode_length = 2;
+ else {
+ (*from)++;
+ return;
+ }
+ while (**from && remaining_unicode_length) {
+ **to = **from;
+ (*from)++, (*to)++, remaining_unicode_length--;
+ }
+}
+
+int isValidUTF8(char *text) {
+ while (*text)
+ if (-1 == UTF8ToUnicode(&text, 1))
+ return 0;
+ return 1;
+}
+
+void TranslateString(char *src, size_t size)
+{
+ char *fptr = src;
+ size_t src_len = strlen(src);
+ char *tptr_start = alloca(src_len * 4 + 1);
+ char *tptr = tptr_start;
+
+ if (isValidUTF8(src)) {
+ strncpy(tptr_start, fptr, src_len + 1);
+ }
+ else {
+ while (*fptr) {
+ int i;
+ for (i = 0; tc[i] && (tc[i] != *fptr); i++);
+ if (tc[i]) {
+ *tptr++ = 0xC3;
+ *tptr++ = su[i];
+ fptr++;
+ } else if (*fptr & 0x80)
+ fptr++;
+ else
+ *tptr++ = *fptr++;
+ }
+ *tptr = 0;
+ }
+
+ fptr = tptr_start;
+ tptr = src;
+ char *tptr_end = src + size - 4;
+
+ while (*fptr && tptr <= tptr_end) {
+ if (*fptr == '~') {
+ fptr++;
+ int i;
+ for (i = 0; sc[i] && (sc[i] != *fptr); i++);
+ if (*fptr == 'd') {
+ *tptr++ = 0xC2;
+ *tptr++ = 0xb0;
+ fptr++;
+ } else if (sc[i]) {
+ *tptr++ = 0xC3;
+ *tptr++ = su[i];
+ fptr++;
+ } else {
+ *tptr++ = '~';
+ }
+ } else {
+ CopyUTF8Char(&tptr, &fptr);
+ }
+ }
+ *tptr = 0;
+}
+
/******************************************************************************
* MyFaceRequester
******************************************************************************/
-FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library _library, FT_Pointer request_data, FT_Face *aface)
+FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library lib, FT_Pointer request_data __attribute__((unused)), FT_Face *aface)
{
FT_Error result;
- request_data=request_data;//for unused request_data
- result = FT_New_Face(_library, face_id, 0, aface);
+
+ result = FT_New_Face(lib, face_id, 0, aface);
if(result) printf("msgbox <Font \"%s\" failed>\n", (char*)face_id);
* RenderChar
******************************************************************************/
+struct colors_struct
+{
+ uint32_t fgcolor, bgcolor;
+ uint32_t colors[256];
+};
+
+#define COLORS_LRU_SIZE 16
+static struct colors_struct *colors_lru_array[COLORS_LRU_SIZE] = { NULL };
+
+static uint32_t *lookup_colors(uint32_t fgcolor, uint32_t bgcolor)
+{
+ struct colors_struct *cs;
+ int i = 0, j;
+ for (i = 0; i < COLORS_LRU_SIZE; i++)
+ if (colors_lru_array[i] && colors_lru_array[i]->fgcolor == fgcolor && colors_lru_array[i]->bgcolor == bgcolor) {
+ cs = colors_lru_array[i];
+ for (j = i; j > 0; j--)
+ colors_lru_array[j] = colors_lru_array[j - 1];
+ colors_lru_array[0] = cs;
+ return cs->colors;
+ }
+ i--;
+ cs = colors_lru_array[i];
+ if (!cs)
+ cs = (struct colors_struct *) calloc(1, sizeof(struct colors_struct));
+ for (j = i; j > 0; j--)
+ colors_lru_array[j] = colors_lru_array[j - 1];
+ cs->fgcolor = fgcolor;
+ cs->bgcolor = bgcolor;
+
+ int ro = var_screeninfo.red.offset;
+ int go = var_screeninfo.green.offset;
+ int bo = var_screeninfo.blue.offset;
+ int to = var_screeninfo.transp.offset;
+ int rm = (1 << var_screeninfo.red.length) - 1;
+ int gm = (1 << var_screeninfo.green.length) - 1;
+ int bm = (1 << var_screeninfo.blue.length) - 1;
+ int tm = (1 << var_screeninfo.transp.length) - 1;
+ int fgr = ((int)fgcolor >> ro) & rm;
+ int fgg = ((int)fgcolor >> go) & gm;
+ int fgb = ((int)fgcolor >> bo) & bm;
+ int fgt = ((int)fgcolor >> to) & tm;
+ int deltar = (((int)bgcolor >> ro) & rm) - fgr;
+ int deltag = (((int)bgcolor >> go) & gm) - fgg;
+ int deltab = (((int)bgcolor >> bo) & bm) - fgb;
+ int deltat = (((int)bgcolor >> to) & tm) - fgt;
+ for (i = 0; i < 256; i++)
+ cs->colors[255 - i] =
+ (((fgr + deltar * i / 255) & rm) << ro) |
+ (((fgg + deltag * i / 255) & gm) << go) |
+ (((fgb + deltab * i / 255) & bm) << bo) |
+ (((fgt + deltat * i / 255) & tm) << to);
+
+ colors_lru_array[0] = cs;
+ return cs->colors;
+}
+
int RenderChar(FT_ULong currentchar, int _sx, int _sy, int _ex, int color)
{
-// unsigned char pix[4]={oldcmap.red[col],oldcmap.green[col],oldcmap.blue[col],oldcmap.transp[col]};
-// unsigned char pix[4]={0x80,0x80,0x80,0x80};
+ int row, pitch;
FT_UInt glyphindex;
FT_Vector kerning;
-// FT_Error _error;
+ FT_Error err;
+
+ if (currentchar == '\r') // display \r in windows edited files
+ {
+ if(color != -1)
+ {
+ if (_sx + 10 < _ex)
+ RenderBox(_sx, _sy - 10, _sx + 10, _sy, GRID, color);
+ else
+ return -1;
+ }
+ return 10;
+ }
- currentchar=currentchar & 0xFF;
+ if (currentchar == '\t')
+ {
+ /* simulate horizontal TAB */
+ return 15;
+ }
//load char
- if(!(glyphindex = FT_Get_Char_Index(face, (int)currentchar)))
+ if(!(glyphindex = FT_Get_Char_Index(face, currentchar)))
{
-// printf("msgbox <FT_Get_Char_Index for Char \"%c\" failed\n", (int)currentchar);
+ printf("msgbox <FT_Get_Char_Index for Char \"%c\" failed\n", (int)currentchar);
return 0;
}
-
- if((/*_error =*/ FTC_SBitCache_Lookup(cache, &desc, glyphindex, &sbit, NULL)))
+ if((err = FTC_SBitCache_Lookup(cache, &desc, glyphindex, &sbit, NULL)))
{
-// printf("msgbox <FTC_SBitCache_Lookup for Char \"%c\" failed with Errorcode 0x%.2X>\n", (int)currentchar, _error);
+ printf("msgbox <FTC_SBitCache_Lookup for Char \"%c\" failed with Errorcode 0x%.2X>\n", (int)currentchar, error);
return 0;
}
-// no kerning used
-/*
if(use_kerning)
{
FT_Get_Kerning(face, prev_glyphindex, glyphindex, ft_kerning_default, &kerning);
prev_glyphindex = glyphindex;
kerning.x >>= 6;
- }
- else
-*/
+ } else
kerning.x = 0;
- //render char
+ //render char
if(color != -1) /* don't render char, return charwidth only */
{
- if(_sx + sbit->xadvance >= _ex){
+ if (_sx + sbit->xadvance >= _ex)
return -1; /* limit to maxwidth */
- }
- unsigned char pix[4]={bl[color],gn[color],rd[color],tr[color]};
- int row, pitch, bit, x = 0, y = 0;
+ uint32_t bgcolor = *(lbb + (sy + _sy) * stride + (sx + _sx));
+ uint32_t fgcolor = bgra[color];
+ uint32_t *colors = lookup_colors(fgcolor, bgcolor);
+ uint32_t *p = lbb + (sx + _sx + sbit->left + kerning.x) + stride * (sy + _sy - sbit->top);
+ uint32_t *r = p + (_ex - _sx); /* end of usable box */
for(row = 0; row < sbit->height; row++)
{
- for(pitch = 0; pitch < sbit->pitch; pitch++)
+ uint32_t *q = p;
+ uint8_t *s = sbit->buffer + row * sbit->pitch;
+ for(pitch = 0; pitch < sbit->width; pitch++)
{
- for(bit = 7; bit >= 0; bit--)
- {
- if(pitch*8 + 7-bit >= sbit->width) break; /* render needed bits only */
-
- if((sbit->buffer[row * sbit->pitch + pitch]) & 1<<bit) memcpy(lbb + (startx + _sx + sbit->left + kerning.x + x)*4 + fix_screeninfo.line_length*(starty + _sy - sbit->top + y),pix,4);
-
- x++;
- }
+ if (*s)
+ *q = colors[*s];
+ q++, s++;
+ if (q > r) /* we are past _ex */
+ break;
}
-
- x = 0;
- y++;
+ p += stride;
+ r += stride;
}
-
}
//return charwidth
* GetStringLen
******************************************************************************/
-int GetStringLen(int _sx, char *string, int size)
+int GetStringLen(int _sx, char *string, size_t size)
{
-unsigned int i = 0;
-int stringlen = 0;
+ int i, stringlen = 0;
//reset kerning
- prev_glyphindex = 0;
+ prev_glyphindex = 0;
//calc len
- if(size)
- {
- desc.width = desc.height = size;
- }
-
- while(*string != '\0')
- {
- if(*string != '~')
- {
- stringlen += RenderChar(*string, -1, -1, -1, -1);
- }
- else
- {
- string++;
- if(*string=='t')
- {
- stringlen=desc.width+TABULATOR*((int)(stringlen/TABULATOR)+1);
- }
- else
- {
- if(*string=='T')
- {
- if(sscanf(string+1,"%4d",&i)==1)
- {
- string+=4;
- stringlen=i-_sx;
- }
- }
- else
- {
- int found=0;
- for(i=0; i<sizeof(sc)/sizeof(sc[0]) && !found; i++)
- {
- if(*string==sc[i])
- {
- stringlen += RenderChar(tc[i], -1, -1, -1, -1);
- found=1;
- }
- }
- }
- }
- }
+ if(size)
+ desc.width = desc.height = size;
+
+ while(*string) {
+ switch(*string) {
+ case '~':
string++;
+ if(*string=='t')
+ stringlen=desc.width+TABULATOR*((int)(stringlen/TABULATOR)+1);
+ else if(*string=='T' && sscanf(string+1,"%4d",&i)==1) {
+ string+=5;
+ stringlen=i-_sx;
+ }
+ break;
+ default:
+ stringlen += RenderChar(UTF8ToUnicode(&string, 1), -1, -1, -1, -1);
+ break;
}
+ }
return stringlen;
}
-
void CatchTabs(char *text)
{
int i;
/******************************************************************************
* RenderString
******************************************************************************/
+
int RenderString(char *string, int _sx, int _sy, int maxwidth, int layout, int size, int color)
{
- int stringlen = 0, _ex = 0, charwidth = 0,found = 0;
- unsigned int i = 0;
- char rstr[BUFSIZE]={0}, *rptr=rstr, rc=' ';
+ int stringlen, _ex, charwidth,i;
+ char rstr[BUFSIZE]={0}, *rptr=rstr;
int varcolor=color;
//set size
- snprintf(rstr,sizeof(rstr),"%s",string);
- desc.width = desc.height = size;
- TABULATOR=3*size;
+ strcpy(rstr,string);
+
+ desc.width = desc.height = size;
+ TABULATOR=3*size;
//set alignment
- stringlen = GetStringLen(_sx, rstr, size);
+ stringlen = GetStringLen(_sx, rstr, size);
- if(layout != LEFT)
+ if(layout != LEFT)
+ {
+ switch(layout)
{
- switch(layout)
- {
- case CENTER: if(stringlen < maxwidth) _sx += (maxwidth - stringlen)/2;
- break;
+ case CENTER: if(stringlen < maxwidth) _sx += (maxwidth - stringlen)/2;
+ break;
- case RIGHT: if(stringlen < maxwidth) _sx += maxwidth - stringlen;
- }
+ case RIGHT: if(stringlen < maxwidth) _sx += maxwidth - stringlen;
}
+ }
//reset kerning
- prev_glyphindex = 0;
+ prev_glyphindex = 0;
//render string
- _ex = _sx + maxwidth;
+ _ex = _sx + maxwidth;
- while(*rptr != '\0')
+ while(*rptr != '\0')
+ {
+ if(*rptr=='~')
{
- if(*rptr=='~')
- {
- ++rptr;
- rc=*rptr;
- found=0;
- for(i=0; i< sizeof(sc)/sizeof(sc[0]) && !found; i++)
- {
- if(rc==sc[i])
- {
- rc=tc[i];
- found=1;
- }
- }
- if(found)
- {
- if((charwidth = RenderChar(rc, _sx, _sy, _ex, varcolor)) == -1) return _sx; /* string > maxwidth */
- _sx += charwidth;
- }
- else
- {
- switch(*rptr)
- {
- case 'R': varcolor=RED; break;
- case 'G': varcolor=GREEN; break;
- case 'Y': varcolor=YELLOW; break;
- case 'B': varcolor=BLUE1; break;
- case 'S': varcolor=color; break;
- case 't':
- _sx=TABULATOR*((int)(_sx/TABULATOR)+1);
- break;
- case 'T':
- if(sscanf(rptr+1,"%4d",&i)==1)
- {
- rptr+=4;
- _sx=i;
- }
- break;
- }
- }
- }
- else
+ ++rptr;
+ switch(*rptr)
{
- int uml = 0;
- switch(*rptr) /* skip Umlauts */
- {
- case '\xc4':
- case '\xd6':
- case '\xdc':
- case '\xe4':
- case '\xf6':
- case '\xfc':
- case '\xdf': uml=1; break;
- }
- if (uml == 0)
- {
- // UTF8_to_Latin1 encoding
- if (((*rptr) & 0xf0) == 0xf0) /* skip (can't be encoded in Latin1) */
- {
- rptr++;
- if ((*rptr) == 0)
- *rptr='\x3f'; // ? question mark
- rptr++;
- if ((*rptr) == 0)
- *rptr='\x3f';
- rptr++;
- if ((*rptr) == 0)
- *rptr='\x3f';
- }
- else if (((*rptr) & 0xe0) == 0xe0) /* skip (can't be encoded in Latin1) */
+ case 'R': varcolor=RED; break;
+ case 'G': varcolor=GREEN; break;
+ case 'Y': varcolor=YELLOW; break;
+ case 'B': varcolor=BLUE1; break;
+ case 'S': varcolor=color; break;
+ case 't':
+ _sx=TABULATOR*((int)(_sx/TABULATOR)+1);
+ break;
+ case 'T':
+ if(sscanf(rptr+1,"%4d",&i)==1)
{
- rptr++;
- if ((*rptr) == 0)
- *rptr='\x3f';
- rptr++;
- if ((*rptr) == 0)
- *rptr='\x3f';
+ rptr+=4;
+ _sx=i;
}
- else if (((*rptr) & 0xc0) == 0xc0)
- {
- char c = (((*rptr) & 3) << 6);
- rptr++;
- if ((*rptr) == 0)
- *rptr='\x3f';
- *rptr = (c | ((*rptr) & 0x3f));
- }
- }
- if((charwidth = RenderChar(*rptr, _sx, _sy, _ex, varcolor)) == -1) return _sx; /* string > maxwidth */
- _sx += charwidth;
+ break;
}
rptr++;
}
+ else
+ {
+ if((charwidth = RenderChar(UTF8ToUnicode(&rptr, 1), _sx, _sy, _ex, varcolor)) == -1) return _sx; /* string > maxwidth */
+ _sx += charwidth;
+ }
+ }
return stringlen;
}
#ifndef __TEXT_H__
-
#define __TEXT_H__
#include "msgbox.h"
FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *aface);
int RenderString(char *string, int sx, int sy, int maxwidth, int layout, int size, int color);
-int GetStringLen(int sx, char *string, int size);
+void TranslateString(char *src, size_t size);
+int GetStringLen(int sx, char *string, size_t size);
void CatchTabs(char *text);
#endif
if((loop>0) && (ys<(ey-dy)))
{
rstr[j]=0;
+ char *t = (char *)alloca(j * 4 + 1);
+ memcpy(t, rstr, j + 1);
+ TranslateString(t, j * 4);
+
if(plot)
{
if(loop>=line)
{
- RenderString(rstr, xs, ys, xw, just, size, color);
+ RenderString(t, xs, ys, xw, just, size, color);
ys+=dy;
}
}
else
{
- if(strlen(rstr))
+ if(strlen(t))
{
- slen=GetStringLen(xs, rstr, size);
+ slen=GetStringLen(xs, t, size);
if(slen>*x)
{
*x=slen;
int fh_txt_load(const char *name, int _sx, int wx, int _sy, int dy, int size, int line, int *cut)
{
- int dummy;
+int dummy;
+
return fh_txt_trans(name, _sx, wx, _sy, dy, size, line, cut, &dummy, &dummy, 1);
}